diff options
| author | Paul Buetow <paul@buetow.org> | 2025-09-06 11:57:45 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2025-09-06 11:57:45 +0300 |
| commit | a48079fae6bb19d7c931f275901670cd5839ab5c (patch) | |
| tree | 5788a3e8cac34ffca9d39b0c4b5df720e869b578 /internal/appconfig/config_test.go | |
| parent | fb267966f7840df222338f57023273a993a73c9a (diff) | |
chore(version): bump to 0.6.0; configurable prompts via config + testsv0.6.0
Diffstat (limited to 'internal/appconfig/config_test.go')
| -rw-r--r-- | internal/appconfig/config_test.go | 207 |
1 files changed, 186 insertions, 21 deletions
diff --git a/internal/appconfig/config_test.go b/internal/appconfig/config_test.go index bdf86da..65e6283 100644 --- a/internal/appconfig/config_test.go +++ b/internal/appconfig/config_test.go @@ -52,29 +52,44 @@ func TestLoad_Defaults_WithLogger_NoFile_NoEnv(t *testing.T) { func TestLoad_FileMerge_And_EnvOverride(t *testing.T) { dir := t.TempDir() t.Setenv("XDG_CONFIG_HOME", dir) - cfgPath := filepath.Join(dir, "hexai", "config.toml") - // file configuration in TOML - writeFile(t, cfgPath, ` + cfgPath := filepath.Join(dir, "hexai", "config.toml") + // file configuration in TOML (sectioned) + writeFile(t, cfgPath, ` +[general] max_tokens = 123 context_mode = "file-on-new-func" context_window_lines = 50 max_context_tokens = 999 -log_preview_limit = 0 coding_temperature = 0.0 + +[logging] +log_preview_limit = 0 + +[completion] manual_invoke_min_prefix = 2 completion_debounce_ms = 150 completion_throttle_ms = 300 + +[triggers] trigger_characters = [".", ":"] -provider = "openai" -openai_base_url = "https://api.example" -openai_model = "gpt-x" -openai_temperature = 0.0 -ollama_base_url = "http://ollama" -ollama_model = "llama" -ollama_temperature = 0.0 -copilot_base_url = "http://copilot" -copilot_model = "ghost" -copilot_temperature = 0.0 + +[provider] +name = "openai" + +[openai] +base_url = "https://api.example" +model = "gpt-x" +temperature = 0.0 + +[ollama] +base_url = "http://ollama" +model = "llama" +temperature = 0.0 + +[copilot] +base_url = "http://copilot" +model = "ghost" +temperature = 0.0 `) // Env overrides take precedence @@ -129,13 +144,13 @@ copilot_temperature = 0.0 t.Fatalf("copilot overrides not applied: %+v", cfg) } - // Ensure file values would have applied absent env - // Spot-check: reset env and reload - for _, k := range []string{ - "HEXAI_MAX_TOKENS", "HEXAI_CONTEXT_MODE", "HEXAI_CONTEXT_WINDOW_LINES", "HEXAI_MAX_CONTEXT_TOKENS", "HEXAI_LOG_PREVIEW_LIMIT", "HEXAI_CODING_TEMPERATURE", "HEXAI_MANUAL_INVOKE_MIN_PREFIX", "HEXAI_COMPLETION_DEBOUNCE_MS", "HEXAI_COMPLETION_THROTTLE_MS", "HEXAI_TRIGGER_CHARACTERS", "HEXAI_PROVIDER", "HEXAI_OPENAI_BASE_URL", "HEXAI_OPENAI_MODEL", "HEXAI_OPENAI_TEMPERATURE", "HEXAI_OLLAMA_BASE_URL", "HEXAI_OLLAMA_MODEL", "HEXAI_OLLAMA_TEMPERATURE", "HEXAI_COPILOT_BASE_URL", "HEXAI_COPILOT_MODEL", "HEXAI_COPILOT_TEMPERATURE", - } { - t.Setenv(k, "") - } + // Ensure file values would have applied absent env + // Spot-check: reset env and reload + for _, k := range []string{ + "HEXAI_MAX_TOKENS", "HEXAI_CONTEXT_MODE", "HEXAI_CONTEXT_WINDOW_LINES", "HEXAI_MAX_CONTEXT_TOKENS", "HEXAI_LOG_PREVIEW_LIMIT", "HEXAI_CODING_TEMPERATURE", "HEXAI_MANUAL_INVOKE_MIN_PREFIX", "HEXAI_COMPLETION_DEBOUNCE_MS", "HEXAI_COMPLETION_THROTTLE_MS", "HEXAI_TRIGGER_CHARACTERS", "HEXAI_PROVIDER", "HEXAI_OPENAI_BASE_URL", "HEXAI_OPENAI_MODEL", "HEXAI_OPENAI_TEMPERATURE", "HEXAI_OLLAMA_BASE_URL", "HEXAI_OLLAMA_MODEL", "HEXAI_OLLAMA_TEMPERATURE", "HEXAI_COPILOT_BASE_URL", "HEXAI_COPILOT_MODEL", "HEXAI_COPILOT_TEMPERATURE", + } { + t.Setenv(k, "") + } cfg2 := Load(logger) if cfg2.MaxTokens != 123 || cfg2.ContextMode != "file-on-new-func" || cfg2.ContextWindowLines != 50 || cfg2.MaxContextTokens != 999 || cfg2.LogPreviewLimit != 0 { t.Fatalf("file merge not applied: %+v", cfg2) @@ -175,3 +190,153 @@ func TestLoadFromFile_InvalidTOML(t *testing.T) { t.Fatalf("expected error for invalid TOML") } } + +func TestLoad_FileTables_Sectioned(t *testing.T) { + dir := t.TempDir() + t.Setenv("XDG_CONFIG_HOME", dir) + cfgPath := filepath.Join(dir, "hexai", "config.toml") + content := ` +[general] +max_tokens = 111 +context_mode = "window" +context_window_lines = 42 +max_context_tokens = 777 +coding_temperature = 0.1 + +[logging] +log_preview_limit = 9 + +[completion] +completion_debounce_ms = 123 +completion_throttle_ms = 456 +manual_invoke_min_prefix = 3 + +[triggers] +trigger_characters = [".", ":"] + +[inline] +inline_open = ">" +inline_close = ">" + +[chat] +chat_suffix = ">" +chat_prefixes = ["?", "!"] + +[provider] +name = "openai" + +[openai] +model = "gpt-x" +base_url = "https://api.example" +temperature = 0.0 + +[ollama] +model = "mistral" +base_url = "http://ollama" +temperature = 0.0 + +[copilot] +model = "ghost" +base_url = "http://copilot" +temperature = 0.0 +` + writeFile(t, cfgPath, content) + + // Ensure no env override interferes with manual_invoke_min_prefix in this test + t.Setenv("HEXAI_MANUAL_INVOKE_MIN_PREFIX", "") + logger := newLogger() + cfg := Load(logger) + + if cfg.MaxTokens != 111 || cfg.ContextMode != "window" || cfg.ContextWindowLines != 42 || cfg.MaxContextTokens != 777 { + t.Fatalf("sectioned basics wrong: %+v", cfg) + } + if cfg.LogPreviewLimit != 9 || cfg.CompletionDebounceMs != 123 || cfg.CompletionThrottleMs != 456 || cfg.ManualInvokeMinPrefix != 3 { + t.Fatalf("sectioned ints wrong: %+v", cfg) + } + if cfg.CodingTemperature == nil || *cfg.CodingTemperature != 0.1 { + t.Fatalf("sectioned coding_temperature wrong: %+v", cfg.CodingTemperature) + } + if want := []string{".", ":"}; !reflect.DeepEqual(cfg.TriggerCharacters, want) { + t.Fatalf("sectioned trigger chars wrong: got %v", cfg.TriggerCharacters) + } + if cfg.Provider != "openai" { + t.Fatalf("sectioned provider name wrong: %q", cfg.Provider) + } + if cfg.OpenAIModel != "gpt-x" || cfg.OpenAIBaseURL != "https://api.example" || cfg.OpenAITemperature == nil || *cfg.OpenAITemperature != 0.0 { + t.Fatalf("sectioned openai wrong: %+v", cfg) + } + if cfg.OllamaModel != "mistral" || cfg.OllamaBaseURL != "http://ollama" || cfg.OllamaTemperature == nil || *cfg.OllamaTemperature != 0.0 { + t.Fatalf("sectioned ollama wrong: %+v", cfg) + } + if cfg.CopilotModel != "ghost" || cfg.CopilotBaseURL != "http://copilot" || cfg.CopilotTemperature == nil || *cfg.CopilotTemperature != 0.0 { + t.Fatalf("sectioned copilot wrong: %+v", cfg) + } +} + +func TestLoad_FileTables_Prompts_AllSections(t *testing.T) { + dir := t.TempDir() + t.Setenv("XDG_CONFIG_HOME", dir) + cfgPath := filepath.Join(dir, "hexai", "config.toml") + content := ` +[prompts.completion] +system_general = "SYS-GENERAL" +system_params = "SYS-PARAMS" +system_inline = "SYS-INLINE" +user_general = "USER-GENERAL {{file}} {{char}}" +user_params = "USER-PARAMS {{function}}" +additional_context = "EXTRA {{context}}" + +[prompts.provider_native] +completion = "NATIVE {{path}} {{before}}" + +[prompts.chat] +system = "CHAT-SYS" + +[prompts.code_action] +rewrite_system = "REWRITE-SYS" +diagnostics_system = "DIAG-SYS" +document_system = "DOC-SYS" +rewrite_user = "REWRITE-USER {{instruction}} {{selection}}" +diagnostics_user = "DIAG-USER {{diagnostics}} {{selection}}" +document_user = "DOC-USER {{selection}}" +go_test_system = "GOTEST-SYS" +go_test_user = "GOTEST-USER {{function}}" + +[prompts.cli] +default_system = "CLI-DEFAULT" +explain_system = "CLI-EXPLAIN" +` + writeFile(t, cfgPath, content) + + cfg := Load(newLogger()) + + // completion + if cfg.PromptCompletionSystemGeneral != "SYS-GENERAL" || cfg.PromptCompletionSystemParams != "SYS-PARAMS" || cfg.PromptCompletionSystemInline != "SYS-INLINE" { + t.Fatalf("completion system prompts wrong: %+v", cfg) + } + if cfg.PromptCompletionUserGeneral == "" || cfg.PromptCompletionUserParams == "" || cfg.PromptCompletionExtraHeader == "" { + t.Fatalf("completion user/extra prompts not loaded") + } + // provider-native + if cfg.PromptNativeCompletion != "NATIVE {{path}} {{before}}" { + t.Fatalf("provider-native prompt wrong: %q", cfg.PromptNativeCompletion) + } + // chat + if cfg.PromptChatSystem != "CHAT-SYS" { + t.Fatalf("chat system wrong: %q", cfg.PromptChatSystem) + } + // code action + if cfg.PromptCodeActionRewriteSystem != "REWRITE-SYS" || cfg.PromptCodeActionDiagnosticsSystem != "DIAG-SYS" || cfg.PromptCodeActionDocumentSystem != "DOC-SYS" { + t.Fatalf("code action system prompts wrong") + } + if cfg.PromptCodeActionRewriteUser == "" || cfg.PromptCodeActionDiagnosticsUser == "" || cfg.PromptCodeActionDocumentUser == "" { + t.Fatalf("code action user prompts not loaded") + } + if cfg.PromptCodeActionGoTestSystem != "GOTEST-SYS" || cfg.PromptCodeActionGoTestUser == "" { + t.Fatalf("go test prompts wrong") + } + // CLI + if cfg.PromptCLIDefaultSystem != "CLI-DEFAULT" || cfg.PromptCLIExplainSystem != "CLI-EXPLAIN" { + t.Fatalf("cli prompts wrong: %q %q", cfg.PromptCLIDefaultSystem, cfg.PromptCLIExplainSystem) + } +} |
