diff options
| author | Paul Buetow <paul@buetow.org> | 2025-08-22 23:21:36 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2025-08-22 23:21:36 +0300 |
| commit | c97687cb8a2f7ab578291e707bf6c920c346a8cb (patch) | |
| tree | e447451ce953353892ebb63df5c350da5f97cb1d | |
| parent | 6ec565ce315a83dcd17c138d9347055000034bdd (diff) | |
stuff
| -rw-r--r-- | internal/appconfig/config.go | 27 | ||||
| -rw-r--r-- | internal/hexailsp/run.go | 1 | ||||
| -rw-r--r-- | internal/lsp/context.go | 1 | ||||
| -rw-r--r-- | internal/lsp/context_test.go | 1 | ||||
| -rw-r--r-- | internal/lsp/document.go | 1 | ||||
| -rw-r--r-- | internal/lsp/document_test.go | 1 | ||||
| -rw-r--r-- | internal/lsp/handlers.go | 1 | ||||
| -rw-r--r-- | internal/lsp/handlers_test.go | 1 | ||||
| -rw-r--r-- | internal/lsp/server.go | 87 | ||||
| -rw-r--r-- | internal/lsp/transport.go | 1 |
10 files changed, 63 insertions, 59 deletions
diff --git a/internal/appconfig/config.go b/internal/appconfig/config.go index 6d95da2..7bcafda 100644 --- a/internal/appconfig/config.go +++ b/internal/appconfig/config.go @@ -20,7 +20,10 @@ type App struct { MaxContextTokens int `json:"max_context_tokens"` LogPreviewLimit int `json:"log_preview_limit"` // Single knob for LSP requests; if set, overrides hardcoded temps in LSP. - CodingTemperature *float64 `json:"coding_temperature"` + CodingTemperature *float64 `json:"coding_temperature"` + // Minimum identifier characters required for manual (TriggerKind=1) invoke + // to proceed without structural triggers. 0 means always allow. + ManualInvokeMinPrefix int `json:"manual_invoke_min_prefix"` TriggerCharacters []string `json:"trigger_characters"` Provider string `json:"provider"` @@ -54,8 +57,9 @@ func newDefaultConfig() App { CodingTemperature: &t, OpenAITemperature: &t, OllamaTemperature: &t, - CopilotTemperature: &t, - } + CopilotTemperature: &t, + ManualInvokeMinPrefix: 0, + } } // Load reads configuration from a file and merges with defaults. @@ -129,9 +133,12 @@ func (a *App) mergeBasics(other *App) { if other.LogPreviewLimit >= 0 { a.LogPreviewLimit = other.LogPreviewLimit } - if other.CodingTemperature != nil { // allow explicit 0.0 - a.CodingTemperature = other.CodingTemperature - } + if other.CodingTemperature != nil { // allow explicit 0.0 + a.CodingTemperature = other.CodingTemperature + } + if other.ManualInvokeMinPrefix >= 0 { + a.ManualInvokeMinPrefix = other.ManualInvokeMinPrefix + } if len(other.TriggerCharacters) > 0 { a.TriggerCharacters = slices.Clone(other.TriggerCharacters) } @@ -199,10 +206,7 @@ func loadFromEnv(logger *log.Logger) *App { v := getenv(k) if v == "" { return 0, false } n, err := strconv.Atoi(v) - if err != nil { - if logger != nil { logger.Printf("invalid %s: %v", k, err) } - return 0, false - } + if err != nil { if logger != nil { logger.Printf("invalid %s: %v", k, err) } ; return 0, false } return n, true } parseFloatPtr := func(k string) (*float64, bool) { @@ -231,6 +235,9 @@ func loadFromEnv(logger *log.Logger) *App { if n, ok := parseInt("HEXAI_LOG_PREVIEW_LIMIT"); ok { out.LogPreviewLimit = n; any = true } + if n, ok := parseInt("HEXAI_MANUAL_INVOKE_MIN_PREFIX"); ok { + out.ManualInvokeMinPrefix = n; any = true + } if f, ok := parseFloatPtr("HEXAI_CODING_TEMPERATURE"); ok { out.CodingTemperature = f; any = true } diff --git a/internal/hexailsp/run.go b/internal/hexailsp/run.go index 366d71c..4700f27 100644 --- a/internal/hexailsp/run.go +++ b/internal/hexailsp/run.go @@ -115,5 +115,6 @@ func makeServerOptions(cfg appconfig.App, logContext bool, client llm.Client) ls CodingTemperature: cfg.CodingTemperature, Client: client, TriggerCharacters: cfg.TriggerCharacters, + ManualInvokeMinPrefix: cfg.ManualInvokeMinPrefix, } } diff --git a/internal/lsp/context.go b/internal/lsp/context.go index 02aa40a..89f245d 100644 --- a/internal/lsp/context.go +++ b/internal/lsp/context.go @@ -1,5 +1,4 @@ // Summary: Builds additional context snippets based on configured mode and truncates text by token heuristic. -// Not yet reviewed by a human package lsp import ( diff --git a/internal/lsp/context_test.go b/internal/lsp/context_test.go index 54553d6..dcda042 100644 --- a/internal/lsp/context_test.go +++ b/internal/lsp/context_test.go @@ -1,5 +1,4 @@ // Summary: Tests for context-building logic (window, full-file) and truncation behavior. -// Not yet reviewed by a human package lsp import ( diff --git a/internal/lsp/document.go b/internal/lsp/document.go index dbecd5e..17d2fb9 100644 --- a/internal/lsp/document.go +++ b/internal/lsp/document.go @@ -1,5 +1,4 @@ // Summary: In-memory document model for the LSP; tracks text, lines, and applies edits. -// Not yet reviewed by a human package lsp import ( diff --git a/internal/lsp/document_test.go b/internal/lsp/document_test.go index da17cc5..4bd96e2 100644 --- a/internal/lsp/document_test.go +++ b/internal/lsp/document_test.go @@ -1,5 +1,4 @@ // Summary: Tests for LSP document model (line management, edits, and transformations). -// Not yet reviewed by a human package lsp import ( diff --git a/internal/lsp/handlers.go b/internal/lsp/handlers.go index 3f0f75d..818dbdf 100644 --- a/internal/lsp/handlers.go +++ b/internal/lsp/handlers.go @@ -1,5 +1,4 @@ // Summary: LSP JSON-RPC handlers; implements core methods and integrates with the LLM client when enabled. -// Not yet reviewed by a human package lsp import ( diff --git a/internal/lsp/handlers_test.go b/internal/lsp/handlers_test.go index 35d0651..779a71f 100644 --- a/internal/lsp/handlers_test.go +++ b/internal/lsp/handlers_test.go @@ -1,5 +1,4 @@ // Summary: Tests for instruction extraction helpers in handlers.go -// Not yet reviewed by a human package lsp import "testing" diff --git a/internal/lsp/server.go b/internal/lsp/server.go index db31d42..ea13456 100644 --- a/internal/lsp/server.go +++ b/internal/lsp/server.go @@ -1,5 +1,4 @@ // Summary: Minimal LSP server over stdio; manages documents, dispatches requests, and tracks stats. -// Not yet reviewed by a human package lsp import ( @@ -29,35 +28,38 @@ type Server struct { windowLines int maxContextTokens int noDiskIO bool - triggerChars []string - // If set, used as the LSP coding temperature for all LLM calls - codingTemperature *float64 - // Concurrency guard: prevent overlapping LLM requests (esp. completions) - llmBusy bool + triggerChars []string + // If set, used as the LSP coding temperature for all LLM calls + codingTemperature *float64 + // Concurrency guard: prevent overlapping LLM requests (esp. completions) + llmBusy bool // LLM request stats llmReqTotal int64 llmSentBytesTotal int64 llmRespTotal int64 - llmRespBytesTotal int64 - startTime time.Time - // Small LRU cache for recent code completion outputs (keyed by context) - compCache map[string]string - compCacheOrder []string // most-recent at end; cap ~10 - // Outgoing JSON-RPC id counter for server-initiated requests - nextID int64 + llmRespBytesTotal int64 + startTime time.Time + // Small LRU cache for recent code completion outputs (keyed by context) + compCache map[string]string + compCacheOrder []string // most-recent at end; cap ~10 + // Outgoing JSON-RPC id counter for server-initiated requests + nextID int64 + // Minimum identifier chars required for manual invoke to bypass prefix checks + manualInvokeMinPrefix int } // ServerOptions collects configuration for NewServer to avoid long parameter lists. type ServerOptions struct { - LogContext bool - MaxTokens int - ContextMode string - WindowLines int - MaxContextTokens int + LogContext bool + MaxTokens int + ContextMode string + WindowLines int + MaxContextTokens int - Client llm.Client - TriggerCharacters []string - CodingTemperature *float64 + Client llm.Client + TriggerCharacters []string + CodingTemperature *float64 + ManualInvokeMinPrefix int } func NewServer(r io.Reader, w io.Writer, logger *log.Logger, opts ServerOptions) *Server { @@ -82,37 +84,38 @@ func NewServer(r io.Reader, w io.Writer, logger *log.Logger, opts ServerOptions) s.contextMode = contextMode s.windowLines = windowLines s.maxContextTokens = maxContextTokens - + s.startTime = time.Now() - s.llmClient = opts.Client - if len(opts.TriggerCharacters) == 0 { - // Defaults (no space to avoid auto-trigger after whitespace) - s.triggerChars = []string{".", ":", "/", "_"} - } else { - s.triggerChars = append([]string{}, opts.TriggerCharacters...) - } - s.codingTemperature = opts.CodingTemperature - s.compCache = make(map[string]string) - return s + s.llmClient = opts.Client + if len(opts.TriggerCharacters) == 0 { + // Defaults (no space to avoid auto-trigger after whitespace) + s.triggerChars = []string{".", ":", "/", "_", ")", "{"} + } else { + s.triggerChars = append([]string{}, opts.TriggerCharacters...) + } + s.codingTemperature = opts.CodingTemperature + s.compCache = make(map[string]string) + s.manualInvokeMinPrefix = opts.ManualInvokeMinPrefix + return s } // tryStartLLM attempts to mark the LLM as busy. Returns true when it acquired // the guard; false if another LLM request is already running. func (s *Server) tryStartLLM() bool { - s.mu.Lock() - defer s.mu.Unlock() - if s.llmBusy { - return false - } - s.llmBusy = true - return true + s.mu.Lock() + defer s.mu.Unlock() + if s.llmBusy { + return false + } + s.llmBusy = true + return true } // endLLM releases the busy guard for LLM requests. func (s *Server) endLLM() { - s.mu.Lock() - s.llmBusy = false - s.mu.Unlock() + s.mu.Lock() + s.llmBusy = false + s.mu.Unlock() } func (s *Server) Run() error { diff --git a/internal/lsp/transport.go b/internal/lsp/transport.go index 0c63aa8..4cda4c6 100644 --- a/internal/lsp/transport.go +++ b/internal/lsp/transport.go @@ -1,5 +1,4 @@ // Summary: LSP transport utilities to read and write JSON-RPC messages with Content-Length framing. -// Not yet reviewed by a human package lsp import ( |
