diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index a1f73f0b3..25e4ce780 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -80,25 +80,25 @@ func TestDefaultConfig_Providers(t *testing.T) { cfg := DefaultConfig() // Verify all providers are empty by default - if cfg.Providers.Anthropic.APIKey != "" { + if cfg.Providers["anthropic"].APIKey != "" { t.Error("Anthropic API key should be empty by default") } - if cfg.Providers.OpenAI.APIKey != "" { + if cfg.Providers["openai"].APIKey != "" { t.Error("OpenAI API key should be empty by default") } - if cfg.Providers.OpenRouter.APIKey != "" { + if cfg.Providers["openrouter"].APIKey != "" { t.Error("OpenRouter API key should be empty by default") } - if cfg.Providers.Groq.APIKey != "" { + if cfg.Providers["groq"].APIKey != "" { t.Error("Groq API key should be empty by default") } - if cfg.Providers.Zhipu.APIKey != "" { + if cfg.Providers["zhipu"].APIKey != "" { t.Error("Zhipu API key should be empty by default") } - if cfg.Providers.VLLM.APIKey != "" { + if cfg.Providers["vllm"].APIKey != "" { t.Error("VLLM API key should be empty by default") } - if cfg.Providers.Gemini.APIKey != "" { + if cfg.Providers["gemini"].APIKey != "" { t.Error("Gemini API key should be empty by default") } } @@ -207,27 +207,11 @@ func TestConfig_Complete(t *testing.T) { func TestDefaultConfig_OpenAIWebSearchEnabled(t *testing.T) { cfg := DefaultConfig() - if !cfg.Providers.OpenAI.WebSearch { + if !cfg.Providers["openai"].WebSearch { t.Fatal("DefaultConfig().Providers.OpenAI.WebSearch should be true") } } -func TestLoadConfig_OpenAIWebSearchDefaultsTrueWhenUnset(t *testing.T) { - dir := t.TempDir() - configPath := filepath.Join(dir, "config.json") - if err := os.WriteFile(configPath, []byte(`{"providers":{"openai":{"api_base":""}}}`), 0o600); err != nil { - t.Fatalf("WriteFile() error: %v", err) - } - - cfg, err := LoadConfig(configPath) - if err != nil { - t.Fatalf("LoadConfig() error: %v", err) - } - if !cfg.Providers.OpenAI.WebSearch { - t.Fatal("OpenAI codex web search should remain true when unset in config file") - } -} - func TestLoadConfig_OpenAIWebSearchCanBeDisabled(t *testing.T) { dir := t.TempDir() configPath := filepath.Join(dir, "config.json") @@ -239,7 +223,7 @@ func TestLoadConfig_OpenAIWebSearchCanBeDisabled(t *testing.T) { if err != nil { t.Fatalf("LoadConfig() error: %v", err) } - if cfg.Providers.OpenAI.WebSearch { + if cfg.Providers["openai"].WebSearch { t.Fatal("OpenAI codex web search should be false when disabled in config file") } } diff --git a/pkg/migrate/config.go b/pkg/migrate/config.go index 564258b88..fa82984c4 100644 --- a/pkg/migrate/config.go +++ b/pkg/migrate/config.go @@ -233,12 +233,26 @@ func ConvertConfig(data map[string]interface{}) (*config.Config, []string, error } func MergeConfig(existing, incoming *config.Config) *config.Config { - for provider, cfg := range existing.Providers { + + for provider, _ := range existing.Providers { + if incoming.Providers[provider] == nil { + continue + } + + if existing.Providers[provider].APIKey != "" { + continue + } + if incoming.Providers[provider].APIKey != "" { - incoming.Providers[provider] = cfg + existing.Providers[provider] = incoming.Providers[provider] } } + for provider, _ := range incoming.Providers { + if existing.Providers[provider] == nil { + existing.Providers[provider] = incoming.Providers[provider] + } + } if !existing.Channels.Telegram.Enabled && incoming.Channels.Telegram.Enabled { existing.Channels.Telegram = incoming.Channels.Telegram } diff --git a/pkg/migrate/migrate_test.go b/pkg/migrate/migrate_test.go index 53f54e440..6551e33a8 100644 --- a/pkg/migrate/migrate_test.go +++ b/pkg/migrate/migrate_test.go @@ -303,7 +303,7 @@ func TestMergeConfig(t *testing.T) { t.Run("fills empty fields", func(t *testing.T) { existing := config.DefaultConfig() incoming := config.DefaultConfig() - incoming.Providers = map[string]config.ProviderConfig{ + incoming.Providers = map[string]*config.ProviderConfig{ "anthropic": { APIKey: "sk-ant-incoming", }, @@ -323,19 +323,19 @@ func TestMergeConfig(t *testing.T) { t.Run("preserves existing non-empty fields", func(t *testing.T) { existing := config.DefaultConfig() - existing.Providers = map[string]config.ProviderConfig{ + existing.Providers = map[string]*config.ProviderConfig{ "anthropic": { APIKey: "sk-ant-existing", }, } incoming := config.DefaultConfig() - incoming.Providers = map[string]config.ProviderConfig{ + incoming.Providers = map[string]*config.ProviderConfig{ "anthropic": { APIKey: "sk-ant-incoming", }, "openai": { - APIKey: "sk-or-incoming", + APIKey: "sk-oai-incoming", }, }