diff options
| author | Paul Buetow <paul@buetow.org> | 2026-03-02 13:47:07 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-03-02 13:47:07 +0200 |
| commit | a065de381f0343b580db47509a8c0f46384c7ae8 (patch) | |
| tree | b36ded44ce20058833f4a73a8e9cf9a6c74a565b /internal | |
| parent | 393af17e8f274537a8fa6c302e0bcab21d191e7b (diff) | |
lsp: simplify ServerOptions to config-first model (task 410)
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/hexailsp/run.go | 63 | ||||
| -rw-r--r-- | internal/hexailsp/run_more_test.go | 14 | ||||
| -rw-r--r-- | internal/hexailsp/run_test.go | 26 | ||||
| -rw-r--r-- | internal/lsp/server.go | 87 | ||||
| -rw-r--r-- | internal/lsp/triggers_config_test.go | 10 |
5 files changed, 39 insertions, 161 deletions
diff --git a/internal/hexailsp/run.go b/internal/hexailsp/run.go index e357cbb..3c86414 100644 --- a/internal/hexailsp/run.go +++ b/internal/hexailsp/run.go @@ -137,63 +137,12 @@ func ensureFactory(factory ServerFactory) ServerFactory { } func makeServerOptions(cfg appconfig.App, logContext bool, client llm.Client, loadOpts appconfig.LoadOptions, ignoreChecker *ignore.Checker) lsp.ServerOptions { - // Map custom actions from appconfig to lsp type - var customs []lsp.CustomAction - if len(cfg.CustomActions) > 0 { - customs = make([]lsp.CustomAction, 0, len(cfg.CustomActions)) - for _, ca := range cfg.CustomActions { - customs = append(customs, lsp.CustomAction{ - ID: ca.ID, - Title: ca.Title, - Kind: ca.Kind, - Scope: ca.Scope, - Instruction: ca.Instruction, - System: ca.System, - User: ca.User, - }) - } - } return lsp.ServerOptions{ - ConfigLoadOptions: loadOpts, - LogContext: logContext, - ConfigStore: nil, - Config: &cfg, - MaxTokens: cfg.MaxTokens, - ContextMode: cfg.ContextMode, - WindowLines: cfg.ContextWindowLines, - MaxContextTokens: cfg.MaxContextTokens, - CodingTemperature: cfg.CodingTemperature, - Client: client, - TriggerCharacters: cfg.TriggerCharacters, - ManualInvokeMinPrefix: cfg.ManualInvokeMinPrefix, - CompletionDebounceMs: cfg.CompletionDebounceMs, - CompletionThrottleMs: cfg.CompletionThrottleMs, - CompletionWaitAll: cfg.CompletionWaitAll, - InlineOpen: cfg.InlineOpen, - InlineClose: cfg.InlineClose, - ChatSuffix: cfg.ChatSuffix, - ChatPrefixes: cfg.ChatPrefixes, - - // Prompts - PromptCompSysGeneral: cfg.PromptCompletionSystemGeneral, - PromptCompSysParams: cfg.PromptCompletionSystemParams, - PromptCompSysInline: cfg.PromptCompletionSystemInline, - PromptCompUserGeneral: cfg.PromptCompletionUserGeneral, - PromptCompUserParams: cfg.PromptCompletionUserParams, - PromptCompExtraHeader: cfg.PromptCompletionExtraHeader, - PromptNativeCompletion: cfg.PromptNativeCompletion, - PromptChatSystem: cfg.PromptChatSystem, - PromptRewriteSystem: cfg.PromptCodeActionRewriteSystem, - PromptDiagnosticsSystem: cfg.PromptCodeActionDiagnosticsSystem, - PromptDocumentSystem: cfg.PromptCodeActionDocumentSystem, - PromptRewriteUser: cfg.PromptCodeActionRewriteUser, - PromptDiagnosticsUser: cfg.PromptCodeActionDiagnosticsUser, - PromptDocumentUser: cfg.PromptCodeActionDocumentUser, - PromptGoTestSystem: cfg.PromptCodeActionGoTestSystem, - PromptGoTestUser: cfg.PromptCodeActionGoTestUser, - PromptSimplifySystem: cfg.PromptCodeActionSimplifySystem, - PromptSimplifyUser: cfg.PromptCodeActionSimplifyUser, - CustomActions: customs, - IgnoreChecker: ignoreChecker, + ConfigLoadOptions: loadOpts, + LogContext: logContext, + ConfigStore: nil, + Config: &cfg, + Client: client, + IgnoreChecker: ignoreChecker, } } diff --git a/internal/hexailsp/run_more_test.go b/internal/hexailsp/run_more_test.go index 338dd48..7017811 100644 --- a/internal/hexailsp/run_more_test.go +++ b/internal/hexailsp/run_more_test.go @@ -47,10 +47,13 @@ func TestRunWithFactory_BuildsOptionsAndClient(t *testing.T) { if err := RunWithFactory("", "", &in, &out, logger, cfg, nil, factory); err != nil { t.Fatalf("RunWithFactory error: %v", err) } - if captured.MaxTokens != 123 { + if captured.Config == nil { + t.Fatalf("expected Config to be set in ServerOptions") + } + if captured.Config.MaxTokens != 123 { t.Fatalf("opts not applied: %+v", captured) } - if captured.PromptRewriteSystem != "RSYS" || captured.PromptRewriteUser != "RUSER" { + if captured.Config.PromptCodeActionRewriteSystem != "RSYS" || captured.Config.PromptCodeActionRewriteUser != "RUSER" { t.Fatalf("prompts not mapped: %+v", captured) } if captured.Client == nil { @@ -88,10 +91,13 @@ func TestRunWithFactory_SubscriptionAppliesUpdates(t *testing.T) { t.Fatalf("expected ApplyOptions to be invoked on config update, got %d calls", len(runner.opts)) } latest := runner.opts[len(runner.opts)-1] - if latest.MaxTokens != updated.MaxTokens { + if latest.Config == nil { + t.Fatalf("expected Config on latest options") + } + if latest.Config.MaxTokens != updated.MaxTokens { t.Fatalf("expected updated max tokens, got %+v", latest) } - if latest.ContextMode != "always-full" { + if latest.Config.ContextMode != "always-full" { t.Fatalf("expected normalized context mode, got %+v", latest) } } diff --git a/internal/hexailsp/run_test.go b/internal/hexailsp/run_test.go index 12b56c0..743f064 100644 --- a/internal/hexailsp/run_test.go +++ b/internal/hexailsp/run_test.go @@ -39,17 +39,20 @@ func TestRunWithFactory_UsesDefaultsAndCallsServer(t *testing.T) { if err := RunWithFactory("", "", bytes.NewBuffer(nil), bytes.NewBuffer(nil), logger, cfg, nil, factory); err != nil { t.Fatalf("RunWithFactory error: %v", err) } - if gotOpts.MaxTokens != cfg.MaxTokens { - t.Fatalf("MaxTokens want %d got %d", cfg.MaxTokens, gotOpts.MaxTokens) + if gotOpts.Config == nil { + t.Fatalf("expected Config to be set in ServerOptions") } - if gotOpts.ContextMode != cfg.ContextMode { - t.Fatalf("ContextMode want %q got %q", cfg.ContextMode, gotOpts.ContextMode) + if gotOpts.Config.MaxTokens != cfg.MaxTokens { + t.Fatalf("MaxTokens want %d got %d", cfg.MaxTokens, gotOpts.Config.MaxTokens) } - if gotOpts.WindowLines != cfg.ContextWindowLines { - t.Fatalf("WindowLines want %d got %d", cfg.ContextWindowLines, gotOpts.WindowLines) + if gotOpts.Config.ContextMode != cfg.ContextMode { + t.Fatalf("ContextMode want %q got %q", cfg.ContextMode, gotOpts.Config.ContextMode) } - if gotOpts.MaxContextTokens != cfg.MaxContextTokens { - t.Fatalf("MaxContextTokens want %d got %d", cfg.MaxContextTokens, gotOpts.MaxContextTokens) + if gotOpts.Config.ContextWindowLines != cfg.ContextWindowLines { + t.Fatalf("ContextWindowLines want %d got %d", cfg.ContextWindowLines, gotOpts.Config.ContextWindowLines) + } + if gotOpts.Config.MaxContextTokens != cfg.MaxContextTokens { + t.Fatalf("MaxContextTokens want %d got %d", cfg.MaxContextTokens, gotOpts.Config.MaxContextTokens) } if gotOpts.Client != nil { // with no env, openai client fails to build @@ -107,8 +110,11 @@ func TestRunWithFactory_NormalizesContextMode_AndSetsPreviewLimit(t *testing.T) if err := RunWithFactory("", "", bytes.NewBuffer(nil), bytes.NewBuffer(nil), logger, cfg, nil, factory); err != nil { t.Fatalf("RunWithFactory error: %v", err) } - if gotOpts.ContextMode != "file-on-new-func" { - t.Fatalf("ContextMode not normalized: %q", gotOpts.ContextMode) + if gotOpts.Config == nil { + t.Fatalf("expected Config to be set in ServerOptions") + } + if gotOpts.Config.ContextMode != "file-on-new-func" { + t.Fatalf("ContextMode not normalized: %q", gotOpts.Config.ContextMode) } if logging.PreviewForLog("abcdef") != "abc…" { t.Fatalf("PreviewForLog not respecting limit: %q", logging.PreviewForLog("abcdef")) diff --git a/internal/lsp/server.go b/internal/lsp/server.go index 385f5ce..dc76975 100644 --- a/internal/lsp/server.go +++ b/internal/lsp/server.go @@ -63,49 +63,9 @@ type ServerOptions struct { LogContext bool ConfigStore *runtimeconfig.Store Config *appconfig.App - MaxTokens int - ContextMode string - WindowLines int - MaxContextTokens int ConfigLoadOptions appconfig.LoadOptions - Client llm.Client - TriggerCharacters []string - CodingTemperature *float64 - ManualInvokeMinPrefix int - CompletionDebounceMs int - CompletionThrottleMs int - CompletionWaitAll *bool - - // Inline/chat triggers - InlineOpen string - InlineClose string - ChatSuffix string - ChatPrefixes []string - - // Prompt templates - PromptCompSysGeneral string - PromptCompSysParams string - PromptCompSysInline string - PromptCompUserGeneral string - PromptCompUserParams string - PromptCompExtraHeader string - PromptNativeCompletion string - PromptChatSystem string - PromptRewriteSystem string - PromptDiagnosticsSystem string - PromptDocumentSystem string - PromptRewriteUser string - PromptDiagnosticsUser string - PromptDocumentUser string - PromptGoTestSystem string - PromptGoTestUser string - PromptSimplifySystem string - PromptSimplifyUser string - - // Custom actions - CustomActions []CustomAction - + Client llm.Client // Gitignore-aware file checker (optional) IgnoreChecker *ignore.Checker } @@ -158,51 +118,6 @@ func (s *Server) applyOptions(opts ServerOptions) { s.cfg = opts.ConfigStore.Snapshot() } else { s.cfg = appconfig.App{} - // populate from legacy ServerOptions fields - s.cfg.MaxTokens = opts.MaxTokens - s.cfg.ContextMode = opts.ContextMode - s.cfg.ContextWindowLines = opts.WindowLines - s.cfg.MaxContextTokens = opts.MaxContextTokens - s.cfg.TriggerCharacters = append([]string{}, opts.TriggerCharacters...) - s.cfg.CodingTemperature = opts.CodingTemperature - s.cfg.ManualInvokeMinPrefix = opts.ManualInvokeMinPrefix - s.cfg.CompletionDebounceMs = opts.CompletionDebounceMs - s.cfg.CompletionThrottleMs = opts.CompletionThrottleMs - s.cfg.CompletionWaitAll = opts.CompletionWaitAll - s.cfg.InlineOpen = opts.InlineOpen - s.cfg.InlineClose = opts.InlineClose - s.cfg.ChatSuffix = opts.ChatSuffix - s.cfg.ChatPrefixes = append([]string{}, opts.ChatPrefixes...) - s.cfg.PromptCompletionSystemGeneral = opts.PromptCompSysGeneral - s.cfg.PromptCompletionSystemParams = opts.PromptCompSysParams - s.cfg.PromptCompletionSystemInline = opts.PromptCompSysInline - s.cfg.PromptCompletionUserGeneral = opts.PromptCompUserGeneral - s.cfg.PromptCompletionUserParams = opts.PromptCompUserParams - s.cfg.PromptCompletionExtraHeader = opts.PromptCompExtraHeader - s.cfg.PromptNativeCompletion = opts.PromptNativeCompletion - s.cfg.PromptChatSystem = opts.PromptChatSystem - s.cfg.PromptCodeActionRewriteSystem = opts.PromptRewriteSystem - s.cfg.PromptCodeActionDiagnosticsSystem = opts.PromptDiagnosticsSystem - s.cfg.PromptCodeActionDocumentSystem = opts.PromptDocumentSystem - s.cfg.PromptCodeActionRewriteUser = opts.PromptRewriteUser - s.cfg.PromptCodeActionDiagnosticsUser = opts.PromptDiagnosticsUser - s.cfg.PromptCodeActionDocumentUser = opts.PromptDocumentUser - s.cfg.PromptCodeActionGoTestSystem = opts.PromptGoTestSystem - s.cfg.PromptCodeActionGoTestUser = opts.PromptGoTestUser - s.cfg.PromptCodeActionSimplifySystem = opts.PromptSimplifySystem - s.cfg.PromptCodeActionSimplifyUser = opts.PromptSimplifyUser - s.cfg.CustomActions = make([]appconfig.CustomAction, len(opts.CustomActions)) - for i, ca := range opts.CustomActions { - s.cfg.CustomActions[i] = appconfig.CustomAction{ - ID: ca.ID, - Title: ca.Title, - Kind: ca.Kind, - Scope: ca.Scope, - Instruction: ca.Instruction, - System: ca.System, - User: ca.User, - } - } } s.llmClient = opts.Client if opts.Client != nil { diff --git a/internal/lsp/triggers_config_test.go b/internal/lsp/triggers_config_test.go index 9ab2752..193e117 100644 --- a/internal/lsp/triggers_config_test.go +++ b/internal/lsp/triggers_config_test.go @@ -7,6 +7,8 @@ import ( "log" "testing" "time" + + "codeberg.org/snonux/hexai/internal/appconfig" ) func TestShouldSuppressForChatTriggerEOL_CustomConfig(t *testing.T) { @@ -28,9 +30,8 @@ func TestShouldSuppressForChatTriggerEOL_CustomConfig(t *testing.T) { func TestNewServer_AssignsTriggerGlobals_AndParsingUsesThem(t *testing.T) { var out bytes.Buffer - s := NewServer(bytes.NewReader(nil), &out, log.New(io.Discard, "", 0), ServerOptions{ - InlineOpen: "<", InlineClose: ">", ChatSuffix: ")", ChatPrefixes: []string{":"}, - }) + cfg := appconfig.App{InlineOpen: "<", InlineClose: ">", ChatSuffix: ")", ChatPrefixes: []string{":"}} + s := NewServer(bytes.NewReader(nil), &out, log.New(io.Discard, "", 0), ServerOptions{Config: &cfg}) openStr, _, openChar, closeChar := s.inlineMarkers() if openChar != '<' || closeChar != '>' { t.Fatalf("inline markers not applied: %q %q", string(openChar), string(closeChar)) @@ -67,7 +68,8 @@ func TestIsTriggerEvent_BareDoubleOpenBlocksEvenWithContextTriggerChar(t *testin func TestDetectAndHandleChat_CustomConfig_InsertsReply(t *testing.T) { var out bytes.Buffer - s := NewServer(bytes.NewReader(nil), &out, log.New(io.Discard, "", 0), ServerOptions{ChatSuffix: "#", ChatPrefixes: []string{")"}}) + cfg := appconfig.App{ChatSuffix: "#", ChatPrefixes: []string{")"}} + s := NewServer(bytes.NewReader(nil), &out, log.New(io.Discard, "", 0), ServerOptions{Config: &cfg}) s.llmClient = fakeLLM{resp: "Hello\nmulti-line reply"} uri := "file:///chat2.go" s.setDocument(uri, "ok)#\n\n") |
