From a6e3fd0a2eaf9e0ee8a9a2a2bf8f120affacda2c Mon Sep 17 00:00:00 2001 From: GRAB Racem Date: Tue, 3 Nov 2026 23:20:21 +0100 Subject: [PATCH] fix(agent): match ARTEX_LLM_PROVIDER case-insensitively FromEnv compared the raw value, so "Ollama" or "OpenAI" matched no case and fell through to the anthropic default. With ARTEX_LLM_PROVIDER=Ollama and an ANTHROPIC_API_KEY set, the Anthropic key was sent to the Ollama base URL. --- agent/provider.go | 4 +++- agent/provider_env_test.go | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 agent/provider_env_test.go diff --git a/agent/provider.go b/agent/provider.go index 6ce4f8a..005f542 100644 --- a/agent/provider.go +++ b/agent/provider.go @@ -203,7 +203,9 @@ func compactionConfig(windowTokens int) *compaction.Config { // ARTEX_LLM_PROXY = proxy URL (optional; http/https/socks5) // ANTHROPIC_API_KEY / OPENAI_API_KEY = credentials (unused for ollama) func FromEnv() (Config, bool) { - prov := os.Getenv("ARTEX_LLM_PROVIDER") + // Case- and space-insensitive: "Ollama" used to miss every case below and + // fall through to anthropic, sending ANTHROPIC_API_KEY to the Ollama base URL. + prov := strings.ToLower(strings.TrimSpace(os.Getenv("ARTEX_LLM_PROVIDER"))) anthKey := os.Getenv("ANTHROPIC_API_KEY") oaiKey := os.Getenv("OPENAI_API_KEY") diff --git a/agent/provider_env_test.go b/agent/provider_env_test.go new file mode 100644 index 0000000..6d58003 --- /dev/null +++ b/agent/provider_env_test.go @@ -0,0 +1,37 @@ +package agent + +import ( + "testing" + + "github.com/Autumn-27/norma/llm" +) + +// ARTEX_LLM_PROVIDER is matched regardless of case and surrounding spaces. A +// miss used to fall through to anthropic: "Ollama" then sent ANTHROPIC_API_KEY +// to the Ollama base URL. +func TestFromEnvProviderIsCaseInsensitive(t *testing.T) { + t.Setenv("ANTHROPIC_API_KEY", "sk-ant-secret") + t.Setenv("OPENAI_API_KEY", "sk-oai") + t.Setenv("ARTEX_LLM_BASE_URL", "") + t.Setenv("ARTEX_LLM_MODEL", "") + for _, tc := range []struct { + env string + want llm.Format + key string + }{ + {"Ollama", FormatOllama, ""}, + {" OLLAMA ", FormatOllama, ""}, + {"OpenAI", llm.FormatOpenAI, "sk-oai"}, + {"OpenAI-Responses", llm.FormatOpenAIResponses, "sk-oai"}, + {"Anthropic", llm.FormatAnthropic, "sk-ant-secret"}, + } { + t.Setenv("ARTEX_LLM_PROVIDER", tc.env) + c, ok := FromEnv() + if !ok { + t.Fatalf("%q: FromEnv returned ok=false", tc.env) + } + if c.Format != tc.want || c.APIKey != tc.key { + t.Fatalf("%q: format=%v key=%q, want format=%v key=%q", tc.env, c.Format, c.APIKey, tc.want, tc.key) + } + } +}