summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-08-22 23:21:36 +0300
committerPaul Buetow <paul@buetow.org>2025-08-22 23:21:36 +0300
commitc97687cb8a2f7ab578291e707bf6c920c346a8cb (patch)
treee447451ce953353892ebb63df5c350da5f97cb1d
parent6ec565ce315a83dcd17c138d9347055000034bdd (diff)
stuff
-rw-r--r--internal/appconfig/config.go27
-rw-r--r--internal/hexailsp/run.go1
-rw-r--r--internal/lsp/context.go1
-rw-r--r--internal/lsp/context_test.go1
-rw-r--r--internal/lsp/document.go1
-rw-r--r--internal/lsp/document_test.go1
-rw-r--r--internal/lsp/handlers.go1
-rw-r--r--internal/lsp/handlers_test.go1
-rw-r--r--internal/lsp/server.go87
-rw-r--r--internal/lsp/transport.go1
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 (