update config for router feature

This commit is contained in:
Luke Milby 2026-02-19 09:28:21 -05:00
parent eda6e37332
commit b301f2b15a
6 changed files with 224 additions and 215 deletions

View file

@ -599,8 +599,8 @@ func gatewayCmd() {
agentLoop.SetChannelManager(channelManager)
var transcriber *voice.GroqTranscriber
if cfg.Providers.Groq.APIKey != "" {
transcriber = voice.NewGroqTranscriber(cfg.Providers.Groq.APIKey)
if cfg.Providers["groq"].APIKey != "" {
transcriber = voice.NewGroqTranscriber(cfg.Providers["groq"].APIKey)
logger.InfoC("voice", "Groq voice transcription enabled")
}
@ -722,13 +722,13 @@ func statusCmd() {
if _, err := os.Stat(configPath); err == nil {
fmt.Printf("Model: %s\n", cfg.Agents.Defaults.Model)
hasOpenRouter := cfg.Providers.OpenRouter.APIKey != ""
hasAnthropic := cfg.Providers.Anthropic.APIKey != ""
hasOpenAI := cfg.Providers.OpenAI.APIKey != ""
hasGemini := cfg.Providers.Gemini.APIKey != ""
hasZhipu := cfg.Providers.Zhipu.APIKey != ""
hasGroq := cfg.Providers.Groq.APIKey != ""
hasVLLM := cfg.Providers.VLLM.APIBase != ""
hasOpenRouter := cfg.Providers["openrouter"].APIKey != ""
hasAnthropic := cfg.Providers["anthropic"].APIKey != ""
hasOpenAI := cfg.Providers["openai"].APIKey != ""
hasGemini := cfg.Providers["gemini"].APIKey != ""
hasZhipu := cfg.Providers["zhipu"].APIKey != ""
hasGroq := cfg.Providers["groq"].APIKey != ""
hasVLLM := cfg.Providers["vllm"].APIBase != ""
status := func(enabled bool) string {
if enabled {
@ -743,7 +743,7 @@ func statusCmd() {
fmt.Println("Zhipu API:", status(hasZhipu))
fmt.Println("Groq API:", status(hasGroq))
if hasVLLM {
fmt.Printf("vLLM/Local: ✓ %s\n", cfg.Providers.VLLM.APIBase)
fmt.Printf("vLLM/Local: ✓ %s\n", cfg.Providers["vllm"].APIBase)
} else {
fmt.Println("vLLM/Local: not set")
}
@ -859,7 +859,8 @@ func authLoginOpenAI(useDeviceCode bool) {
appCfg, err := loadConfig()
if err == nil {
appCfg.Providers.OpenAI.AuthMethod = "oauth"
temp := appCfg.Providers["openai"]
temp.AuthMethod = "oauth"
if err := config.SaveConfig(getConfigPath(), appCfg); err != nil {
fmt.Printf("Warning: could not update config: %v\n", err)
}
@ -887,9 +888,9 @@ func authLoginPasteToken(provider string) {
if err == nil {
switch provider {
case "anthropic":
appCfg.Providers.Anthropic.AuthMethod = "token"
appCfg.Providers["anthropic"].AuthMethod = "token"
case "openai":
appCfg.Providers.OpenAI.AuthMethod = "token"
appCfg.Providers["openai"].AuthMethod = "token"
}
if err := config.SaveConfig(getConfigPath(), appCfg); err != nil {
fmt.Printf("Warning: could not update config: %v\n", err)
@ -923,9 +924,9 @@ func authLogoutCmd() {
if err == nil {
switch provider {
case "openai":
appCfg.Providers.OpenAI.AuthMethod = ""
appCfg.Providers["openai"].AuthMethod = ""
case "anthropic":
appCfg.Providers.Anthropic.AuthMethod = ""
appCfg.Providers["anthropic"].AuthMethod = ""
}
config.SaveConfig(getConfigPath(), appCfg)
}
@ -939,8 +940,8 @@ func authLogoutCmd() {
appCfg, err := loadConfig()
if err == nil {
appCfg.Providers.OpenAI.AuthMethod = ""
appCfg.Providers.Anthropic.AuthMethod = ""
appCfg.Providers["openai"].AuthMethod = ""
appCfg.Providers["anthropic"].AuthMethod = ""
config.SaveConfig(getConfigPath(), appCfg)
}

View file

@ -9,6 +9,11 @@
"max_tool_iterations": 20
}
},
"router": {
"enabled": false,
"heavy_model": "glm-4.7",
"light_model": "glm-4.7-flash"
},
"channels": {
"telegram": {
"enabled": false,

View file

@ -45,8 +45,9 @@ func (f *FlexibleStringSlice) UnmarshalJSON(data []byte) error {
type Config struct {
Agents AgentsConfig `json:"agents"`
Router RouterConfig `json:"router"`
Channels ChannelsConfig `json:"channels"`
Providers ProvidersConfig `json:"providers"`
Providers map[string]*ProviderConfig `json:"providers"`
Gateway GatewayConfig `json:"gateway"`
Tools ToolsConfig `json:"tools"`
Heartbeat HeartbeatConfig `json:"heartbeat"`
@ -54,6 +55,12 @@ type Config struct {
mu sync.RWMutex
}
type RouterConfig struct {
Enabled bool `json:"enabled"`
HeavyModel string `json:"heavy_model"`
LightModel string `json:"light_model"`
}
type AgentsConfig struct {
Defaults AgentDefaults `json:"defaults"`
}
@ -168,7 +175,7 @@ type DevicesConfig struct {
type ProvidersConfig struct {
Anthropic ProviderConfig `json:"anthropic"`
OpenAI OpenAIProviderConfig `json:"openai"`
OpenAI ProviderConfig `json:"openai"`
OpenRouter ProviderConfig `json:"openrouter"`
Groq ProviderConfig `json:"groq"`
Zhipu ProviderConfig `json:"zhipu"`
@ -188,6 +195,7 @@ type ProviderConfig struct {
Proxy string `json:"proxy,omitempty" env:"PICOCLAW_PROVIDERS_{{.Name}}_PROXY"`
AuthMethod string `json:"auth_method,omitempty" env:"PICOCLAW_PROVIDERS_{{.Name}}_AUTH_METHOD"`
ConnectMode string `json:"connect_mode,omitempty" env:"PICOCLAW_PROVIDERS_{{.Name}}_CONNECT_MODE"` //only for Github Copilot, `stdio` or `grpc`
WebSearch bool `json:"web_search" env:"PICOCLAW_PROVIDERS_{{.Name}}_WEB_SEARCH"`
}
type OpenAIProviderConfig struct {
@ -251,6 +259,11 @@ func DefaultConfig() *Config {
MaxToolIterations: 20,
},
},
Router: RouterConfig{
Enabled: false,
HeavyModel: "glm-4.7",
LightModel: "glm-4.7-flash",
},
Channels: ChannelsConfig{
WhatsApp: WhatsAppConfig{
Enabled: false,
@ -317,17 +330,17 @@ func DefaultConfig() *Config {
AllowFrom: FlexibleStringSlice{},
},
},
Providers: ProvidersConfig{
Anthropic: ProviderConfig{},
OpenAI: OpenAIProviderConfig{WebSearch: true},
OpenRouter: ProviderConfig{},
Groq: ProviderConfig{},
Zhipu: ProviderConfig{},
VLLM: ProviderConfig{},
Gemini: ProviderConfig{},
Nvidia: ProviderConfig{},
Moonshot: ProviderConfig{},
ShengSuanYun: ProviderConfig{},
Providers: map[string]*ProviderConfig{
"anthropic": &ProviderConfig{},
"openai": &ProviderConfig{WebSearch: true},
"openrouter": &ProviderConfig{},
"groq": &ProviderConfig{},
"zhipu": &ProviderConfig{},
"vllm": &ProviderConfig{},
"gemini": &ProviderConfig{},
"nvidia": &ProviderConfig{},
"moonshot": &ProviderConfig{},
"shengsuanyun": &ProviderConfig{},
},
Gateway: GatewayConfig{
Host: "0.0.0.0",
@ -413,32 +426,23 @@ func (c *Config) WorkspacePath() string {
return expandHome(c.Agents.Defaults.Workspace)
}
//func (c *Config) GetEnabledProviders() {
// c.mu.RLock()
// defer c.mu.RUnlock()
//
// for _, provider := range c.Providers {
//
// }
//
//}
func (c *Config) GetAPIKey() string {
c.mu.RLock()
defer c.mu.RUnlock()
if c.Providers.OpenRouter.APIKey != "" {
return c.Providers.OpenRouter.APIKey
for _, config := range c.Providers {
if config.APIKey != "" {
return config.APIKey
}
if c.Providers.Anthropic.APIKey != "" {
return c.Providers.Anthropic.APIKey
}
if c.Providers.OpenAI.APIKey != "" {
return c.Providers.OpenAI.APIKey
}
if c.Providers.Gemini.APIKey != "" {
return c.Providers.Gemini.APIKey
}
if c.Providers.Zhipu.APIKey != "" {
return c.Providers.Zhipu.APIKey
}
if c.Providers.Groq.APIKey != "" {
return c.Providers.Groq.APIKey
}
if c.Providers.VLLM.APIKey != "" {
return c.Providers.VLLM.APIKey
}
if c.Providers.ShengSuanYun.APIKey != "" {
return c.Providers.ShengSuanYun.APIKey
}
return ""
}
@ -446,17 +450,18 @@ func (c *Config) GetAPIKey() string {
func (c *Config) GetAPIBase() string {
c.mu.RLock()
defer c.mu.RUnlock()
if c.Providers.OpenRouter.APIKey != "" {
if c.Providers.OpenRouter.APIBase != "" {
return c.Providers.OpenRouter.APIBase
if c.Providers["openrouter"].APIKey != "" {
if c.Providers["openrouter"].APIBase != "" {
return c.Providers["openrouter"].APIBase
}
return "https://openrouter.ai/api/v1"
}
if c.Providers.Zhipu.APIKey != "" {
return c.Providers.Zhipu.APIBase
if c.Providers["zhipu"].APIKey != "" {
return c.Providers["zhipu"].APIBase
}
if c.Providers.VLLM.APIKey != "" && c.Providers.VLLM.APIBase != "" {
return c.Providers.VLLM.APIBase
if c.Providers["vllm"].APIKey != "" && c.Providers["vllm"].APIBase != "" {
return c.Providers["vllm"].APIBase
}
return ""
}

View file

@ -106,22 +106,20 @@ func ConvertConfig(data map[string]interface{}) (*config.Config, []string, error
pc := config.ProviderConfig{APIKey: apiKey, APIBase: apiBase}
switch name {
case "anthropic":
cfg.Providers.Anthropic = pc
cfg.Providers["anthropic"] = &pc
case "openai":
cfg.Providers.OpenAI = config.OpenAIProviderConfig{
ProviderConfig: pc,
WebSearch: getBoolOrDefault(pMap, "web_search", true),
}
pc.WebSearch = getBoolOrDefault(pMap, "web_search", true)
cfg.Providers["openai"] = &pc
case "openrouter":
cfg.Providers.OpenRouter = pc
cfg.Providers["openrouter"] = &pc
case "groq":
cfg.Providers.Groq = pc
cfg.Providers["groq"] = &pc
case "zhipu":
cfg.Providers.Zhipu = pc
cfg.Providers["zhipu"] = &pc
case "vllm":
cfg.Providers.VLLM = pc
cfg.Providers["vllm"] = &pc
case "gemini":
cfg.Providers.Gemini = pc
cfg.Providers["gemini"] = &pc
}
}
}
@ -235,26 +233,10 @@ func ConvertConfig(data map[string]interface{}) (*config.Config, []string, error
}
func MergeConfig(existing, incoming *config.Config) *config.Config {
if existing.Providers.Anthropic.APIKey == "" {
existing.Providers.Anthropic = incoming.Providers.Anthropic
for provider, cfg := range existing.Providers {
if incoming.Providers[provider].APIKey != "" {
incoming.Providers[provider] = cfg
}
if existing.Providers.OpenAI.APIKey == "" {
existing.Providers.OpenAI = incoming.Providers.OpenAI
}
if existing.Providers.OpenRouter.APIKey == "" {
existing.Providers.OpenRouter = incoming.Providers.OpenRouter
}
if existing.Providers.Groq.APIKey == "" {
existing.Providers.Groq = incoming.Providers.Groq
}
if existing.Providers.Zhipu.APIKey == "" {
existing.Providers.Zhipu = incoming.Providers.Zhipu
}
if existing.Providers.VLLM.APIKey == "" && existing.Providers.VLLM.APIBase == "" {
existing.Providers.VLLM = incoming.Providers.VLLM
}
if existing.Providers.Gemini.APIKey == "" {
existing.Providers.Gemini = incoming.Providers.Gemini
}
if !existing.Channels.Telegram.Enabled && incoming.Channels.Telegram.Enabled {

View file

@ -166,14 +166,14 @@ func TestConvertConfig(t *testing.T) {
if len(warnings) != 0 {
t.Errorf("expected no warnings, got %v", warnings)
}
if cfg.Providers.Anthropic.APIKey != "sk-ant-test" {
t.Errorf("Anthropic.APIKey = %q, want %q", cfg.Providers.Anthropic.APIKey, "sk-ant-test")
if cfg.Providers["anthropic"].APIKey != "sk-ant-test" {
t.Errorf("Anthropic.APIKey = %q, want %q", cfg.Providers["anthropic"].APIKey, "sk-ant-test")
}
if cfg.Providers.OpenRouter.APIKey != "sk-or-test" {
t.Errorf("OpenRouter.APIKey = %q, want %q", cfg.Providers.OpenRouter.APIKey, "sk-or-test")
if cfg.Providers["openrouter"].APIKey != "sk-or-test" {
t.Errorf("OpenRouter.APIKey = %q, want %q", cfg.Providers["openrouter"].APIKey, "sk-or-test")
}
if cfg.Providers.Groq.APIKey != "gsk-test" {
t.Errorf("Groq.APIKey = %q, want %q", cfg.Providers.Groq.APIKey, "gsk-test")
if cfg.Providers["groq"].APIKey != "gsk-test" {
t.Errorf("Groq.APIKey = %q, want %q", cfg.Providers["groq"].APIKey, "gsk-test")
}
})
@ -303,32 +303,48 @@ func TestMergeConfig(t *testing.T) {
t.Run("fills empty fields", func(t *testing.T) {
existing := config.DefaultConfig()
incoming := config.DefaultConfig()
incoming.Providers.Anthropic.APIKey = "sk-ant-incoming"
incoming.Providers.OpenRouter.APIKey = "sk-or-incoming"
incoming.Providers = map[string]config.ProviderConfig{
"anthropic": {
APIKey: "sk-ant-incoming",
},
"openrouter": {
APIKey: "sk-or-incoming",
},
}
result := MergeConfig(existing, incoming)
if result.Providers.Anthropic.APIKey != "sk-ant-incoming" {
t.Errorf("Anthropic.APIKey = %q, want %q", result.Providers.Anthropic.APIKey, "sk-ant-incoming")
if result.Providers["anthropic"].APIKey != "sk-ant-incoming" {
t.Errorf("Anthropic.APIKey = %q, want %q", result.Providers["anthropic"].APIKey, "sk-ant-incoming")
}
if result.Providers.OpenRouter.APIKey != "sk-or-incoming" {
t.Errorf("OpenRouter.APIKey = %q, want %q", result.Providers.OpenRouter.APIKey, "sk-or-incoming")
if result.Providers["openrouter"].APIKey != "sk-or-incoming" {
t.Errorf("OpenRouter.APIKey = %q, want %q", result.Providers["openrouter"].APIKey, "sk-or-incoming")
}
})
t.Run("preserves existing non-empty fields", func(t *testing.T) {
existing := config.DefaultConfig()
existing.Providers.Anthropic.APIKey = "sk-ant-existing"
existing.Providers = map[string]config.ProviderConfig{
"anthropic": {
APIKey: "sk-ant-existing",
},
}
incoming := config.DefaultConfig()
incoming.Providers.Anthropic.APIKey = "sk-ant-incoming"
incoming.Providers.OpenAI.APIKey = "sk-oai-incoming"
incoming.Providers = map[string]config.ProviderConfig{
"anthropic": {
APIKey: "sk-ant-incoming",
},
"openai": {
APIKey: "sk-or-incoming",
},
}
result := MergeConfig(existing, incoming)
if result.Providers.Anthropic.APIKey != "sk-ant-existing" {
t.Errorf("Anthropic.APIKey should be preserved, got %q", result.Providers.Anthropic.APIKey)
if result.Providers["anthropic"].APIKey != "sk-ant-existing" {
t.Errorf("Anthropic.APIKey should be preserved, got %q", result.Providers["anthropic"].APIKey)
}
if result.Providers.OpenAI.APIKey != "sk-oai-incoming" {
t.Errorf("OpenAI.APIKey should be filled, got %q", result.Providers.OpenAI.APIKey)
if result.Providers["openai"].APIKey != "sk-oai-incoming" {
t.Errorf("OpenAI.APIKey should be filled, got %q", result.Providers["openai"].APIKey)
}
})
@ -682,11 +698,11 @@ func TestRunFullMigration(t *testing.T) {
if err != nil {
t.Fatalf("loading PicoClaw config: %v", err)
}
if picoConfig.Providers.Anthropic.APIKey != "sk-ant-migrate-test" {
t.Errorf("Anthropic.APIKey = %q, want %q", picoConfig.Providers.Anthropic.APIKey, "sk-ant-migrate-test")
if picoConfig.Providers["anthropic"].APIKey != "sk-ant-migrate-test" {
t.Errorf("Anthropic.APIKey = %q, want %q", picoConfig.Providers["anthropic"].APIKey, "sk-ant-migrate-test")
}
if picoConfig.Providers.OpenRouter.APIKey != "sk-or-migrate-test" {
t.Errorf("OpenRouter.APIKey = %q, want %q", picoConfig.Providers.OpenRouter.APIKey, "sk-or-migrate-test")
if picoConfig.Providers["openrouter"].APIKey != "sk-or-migrate-test" {
t.Errorf("OpenRouter.APIKey = %q, want %q", picoConfig.Providers["openrouter"].APIKey, "sk-or-migrate-test")
}
if !picoConfig.Channels.Telegram.Enabled {
t.Error("Telegram should be enabled")

View file

@ -233,74 +233,74 @@ func CreateProvider(cfg *config.Config) (LLMProvider, error) {
if providerName != "" {
switch providerName {
case "groq":
if cfg.Providers.Groq.APIKey != "" {
apiKey = cfg.Providers.Groq.APIKey
apiBase = cfg.Providers.Groq.APIBase
if cfg.Providers["groq"].APIKey != "" {
apiKey = cfg.Providers["groq"].APIKey
apiBase = cfg.Providers["groq"].APIBase
if apiBase == "" {
apiBase = "https://api.groq.com/openai/v1"
}
}
case "openai", "gpt":
if cfg.Providers.OpenAI.APIKey != "" || cfg.Providers.OpenAI.AuthMethod != "" {
if cfg.Providers.OpenAI.AuthMethod == "codex-cli" {
if cfg.Providers["openai"].APIKey != "" || cfg.Providers["openai"].AuthMethod != "" {
if cfg.Providers["openai"].AuthMethod == "codex-cli" {
c := NewCodexProviderWithTokenSource("", "", CreateCodexCliTokenSource())
c.enableWebSearch = cfg.Providers.OpenAI.WebSearch
c.enableWebSearch = cfg.Providers["openai"].WebSearch
return c, nil
}
if cfg.Providers.OpenAI.AuthMethod == "oauth" || cfg.Providers.OpenAI.AuthMethod == "token" {
return createCodexAuthProvider(cfg.Providers.OpenAI.WebSearch)
if cfg.Providers["openai"].AuthMethod == "oauth" || cfg.Providers["openai"].AuthMethod == "token" {
return createCodexAuthProvider(cfg.Providers["openai"].WebSearch)
}
apiKey = cfg.Providers.OpenAI.APIKey
apiBase = cfg.Providers.OpenAI.APIBase
apiKey = cfg.Providers["openai"].APIKey
apiBase = cfg.Providers["openai"].APIBase
if apiBase == "" {
apiBase = "https://api.openai.com/v1"
}
}
case "anthropic", "claude":
if cfg.Providers.Anthropic.APIKey != "" || cfg.Providers.Anthropic.AuthMethod != "" {
if cfg.Providers.Anthropic.AuthMethod == "oauth" || cfg.Providers.Anthropic.AuthMethod == "token" {
if cfg.Providers["anthropic"].APIKey != "" || cfg.Providers["anthropic"].AuthMethod != "" {
if cfg.Providers["anthropic"].AuthMethod == "oauth" || cfg.Providers["anthropic"].AuthMethod == "token" {
return createClaudeAuthProvider()
}
apiKey = cfg.Providers.Anthropic.APIKey
apiBase = cfg.Providers.Anthropic.APIBase
apiKey = cfg.Providers["anthropic"].APIKey
apiBase = cfg.Providers["anthropic"].APIBase
if apiBase == "" {
apiBase = "https://api.anthropic.com/v1"
}
}
case "openrouter":
if cfg.Providers.OpenRouter.APIKey != "" {
apiKey = cfg.Providers.OpenRouter.APIKey
if cfg.Providers.OpenRouter.APIBase != "" {
apiBase = cfg.Providers.OpenRouter.APIBase
if cfg.Providers["openrouter"].APIKey != "" {
apiKey = cfg.Providers["openrouter"].APIKey
if cfg.Providers["openrouter"].APIBase != "" {
apiBase = cfg.Providers["openrouter"].APIBase
} else {
apiBase = "https://openrouter.ai/api/v1"
}
}
case "zhipu", "glm":
if cfg.Providers.Zhipu.APIKey != "" {
apiKey = cfg.Providers.Zhipu.APIKey
apiBase = cfg.Providers.Zhipu.APIBase
if cfg.Providers["zhipu"].APIKey != "" {
apiKey = cfg.Providers["zhipu"].APIKey
apiBase = cfg.Providers["zhipu"].APIBase
if apiBase == "" {
apiBase = "https://open.bigmodel.cn/api/paas/v4"
}
}
case "gemini", "google":
if cfg.Providers.Gemini.APIKey != "" {
apiKey = cfg.Providers.Gemini.APIKey
apiBase = cfg.Providers.Gemini.APIBase
if cfg.Providers["gemini"].APIKey != "" {
apiKey = cfg.Providers["gemini"].APIKey
apiBase = cfg.Providers["gemini"].APIBase
if apiBase == "" {
apiBase = "https://generativelanguage.googleapis.com/v1beta"
}
}
case "vllm":
if cfg.Providers.VLLM.APIBase != "" {
apiKey = cfg.Providers.VLLM.APIKey
apiBase = cfg.Providers.VLLM.APIBase
if cfg.Providers["vllm"].APIBase != "" {
apiKey = cfg.Providers["vllm"].APIKey
apiBase = cfg.Providers["vllm"].APIBase
}
case "shengsuanyun":
if cfg.Providers.ShengSuanYun.APIKey != "" {
apiKey = cfg.Providers.ShengSuanYun.APIKey
apiBase = cfg.Providers.ShengSuanYun.APIBase
if cfg.Providers["shengsuanyun"].APIKey != "" {
apiKey = cfg.Providers["shengsuanyun"].APIKey
apiBase = cfg.Providers["shengsuanyun"].APIBase
if apiBase == "" {
apiBase = "https://router.shengsuanyun.com/api/v1"
}
@ -318,9 +318,9 @@ func CreateProvider(cfg *config.Config) (LLMProvider, error) {
}
return NewCodexCliProvider(workspace), nil
case "deepseek":
if cfg.Providers.DeepSeek.APIKey != "" {
apiKey = cfg.Providers.DeepSeek.APIKey
apiBase = cfg.Providers.DeepSeek.APIBase
if cfg.Providers["deepseek"].APIKey != "" {
apiKey = cfg.Providers["deepseek"].APIKey
apiBase = cfg.Providers["deepseek"].APIBase
if apiBase == "" {
apiBase = "https://api.deepseek.com/v1"
}
@ -329,12 +329,12 @@ func CreateProvider(cfg *config.Config) (LLMProvider, error) {
}
}
case "github_copilot", "copilot":
if cfg.Providers.GitHubCopilot.APIBase != "" {
apiBase = cfg.Providers.GitHubCopilot.APIBase
if cfg.Providers["githubcopilot"].APIBase != "" {
apiBase = cfg.Providers["githubcopilot"].APIBase
} else {
apiBase = "localhost:4321"
}
return NewGitHubCopilotProvider(apiBase, cfg.Providers.GitHubCopilot.ConnectMode, model)
return NewGitHubCopilotProvider(apiBase, cfg.Providers["githubcopilot"].ConnectMode, model)
}
@ -343,96 +343,96 @@ func CreateProvider(cfg *config.Config) (LLMProvider, error) {
// Fallback: detect provider from model name
if apiKey == "" && apiBase == "" {
switch {
case (strings.Contains(lowerModel, "kimi") || strings.Contains(lowerModel, "moonshot") || strings.HasPrefix(model, "moonshot/")) && cfg.Providers.Moonshot.APIKey != "":
apiKey = cfg.Providers.Moonshot.APIKey
apiBase = cfg.Providers.Moonshot.APIBase
proxy = cfg.Providers.Moonshot.Proxy
case (strings.Contains(lowerModel, "kimi") || strings.Contains(lowerModel, "moonshot") || strings.HasPrefix(model, "moonshot/")) && cfg.Providers["moonshot"].APIKey != "":
apiKey = cfg.Providers["moonshot"].APIKey
apiBase = cfg.Providers["moonshot"].APIBase
proxy = cfg.Providers["moonshot"].Proxy
if apiBase == "" {
apiBase = "https://api.moonshot.cn/v1"
}
case strings.HasPrefix(model, "openrouter/") || strings.HasPrefix(model, "anthropic/") || strings.HasPrefix(model, "openai/") || strings.HasPrefix(model, "meta-llama/") || strings.HasPrefix(model, "deepseek/") || strings.HasPrefix(model, "google/"):
apiKey = cfg.Providers.OpenRouter.APIKey
proxy = cfg.Providers.OpenRouter.Proxy
if cfg.Providers.OpenRouter.APIBase != "" {
apiBase = cfg.Providers.OpenRouter.APIBase
apiKey = cfg.Providers["openrouter"].APIKey
proxy = cfg.Providers["openrouter"].Proxy
if cfg.Providers["openrouter"].APIBase != "" {
apiBase = cfg.Providers["openrouter"].APIBase
} else {
apiBase = "https://openrouter.ai/api/v1"
}
case (strings.Contains(lowerModel, "claude") || strings.HasPrefix(model, "anthropic/")) && (cfg.Providers.Anthropic.APIKey != "" || cfg.Providers.Anthropic.AuthMethod != ""):
if cfg.Providers.Anthropic.AuthMethod == "oauth" || cfg.Providers.Anthropic.AuthMethod == "token" {
case (strings.Contains(lowerModel, "claude") || strings.HasPrefix(model, "anthropic/")) && (cfg.Providers["anthropic"].APIKey != "" || cfg.Providers["anthropic"].AuthMethod != ""):
if cfg.Providers["anthropic"].AuthMethod == "oauth" || cfg.Providers["anthropic"].AuthMethod == "token" {
return createClaudeAuthProvider()
}
apiKey = cfg.Providers.Anthropic.APIKey
apiBase = cfg.Providers.Anthropic.APIBase
proxy = cfg.Providers.Anthropic.Proxy
apiKey = cfg.Providers["anthropic"].APIKey
apiBase = cfg.Providers["anthropic"].APIBase
proxy = cfg.Providers["anthropic"].Proxy
if apiBase == "" {
apiBase = "https://api.anthropic.com/v1"
}
case (strings.Contains(lowerModel, "gpt") || strings.HasPrefix(model, "openai/")) && (cfg.Providers.OpenAI.APIKey != "" || cfg.Providers.OpenAI.AuthMethod != ""):
if cfg.Providers.OpenAI.AuthMethod == "oauth" || cfg.Providers.OpenAI.AuthMethod == "token" {
return createCodexAuthProvider(cfg.Providers.OpenAI.WebSearch)
case (strings.Contains(lowerModel, "gpt") || strings.HasPrefix(model, "openai/")) && (cfg.Providers["openai"].APIKey != "" || cfg.Providers["openai"].AuthMethod != ""):
if cfg.Providers["openai"].AuthMethod == "oauth" || cfg.Providers["openai"].AuthMethod == "token" {
return createCodexAuthProvider(cfg.Providers["openai"].WebSearch)
}
apiKey = cfg.Providers.OpenAI.APIKey
apiBase = cfg.Providers.OpenAI.APIBase
proxy = cfg.Providers.OpenAI.Proxy
apiKey = cfg.Providers["openai"].APIKey
apiBase = cfg.Providers["openai"].APIBase
proxy = cfg.Providers["openai"].Proxy
if apiBase == "" {
apiBase = "https://api.openai.com/v1"
}
case (strings.Contains(lowerModel, "gemini") || strings.HasPrefix(model, "google/")) && cfg.Providers.Gemini.APIKey != "":
apiKey = cfg.Providers.Gemini.APIKey
apiBase = cfg.Providers.Gemini.APIBase
proxy = cfg.Providers.Gemini.Proxy
case (strings.Contains(lowerModel, "gemini") || strings.HasPrefix(model, "google/")) && cfg.Providers["gemini"].APIKey != "":
apiKey = cfg.Providers["gemini"].APIKey
apiBase = cfg.Providers["gemini"].APIBase
proxy = cfg.Providers["gemini"].Proxy
if apiBase == "" {
apiBase = "https://generativelanguage.googleapis.com/v1beta"
}
case (strings.Contains(lowerModel, "glm") || strings.Contains(lowerModel, "zhipu") || strings.Contains(lowerModel, "zai")) && cfg.Providers.Zhipu.APIKey != "":
apiKey = cfg.Providers.Zhipu.APIKey
apiBase = cfg.Providers.Zhipu.APIBase
proxy = cfg.Providers.Zhipu.Proxy
case (strings.Contains(lowerModel, "glm") || strings.Contains(lowerModel, "zhipu") || strings.Contains(lowerModel, "zai")) && cfg.Providers["zhipu"].APIKey != "":
apiKey = cfg.Providers["zhipu"].APIKey
apiBase = cfg.Providers["zhipu"].APIBase
proxy = cfg.Providers["zhipu"].Proxy
if apiBase == "" {
apiBase = "https://open.bigmodel.cn/api/paas/v4"
}
case (strings.Contains(lowerModel, "groq") || strings.HasPrefix(model, "groq/")) && cfg.Providers.Groq.APIKey != "":
apiKey = cfg.Providers.Groq.APIKey
apiBase = cfg.Providers.Groq.APIBase
proxy = cfg.Providers.Groq.Proxy
case (strings.Contains(lowerModel, "groq") || strings.HasPrefix(model, "groq/")) && cfg.Providers["groq"].APIKey != "":
apiKey = cfg.Providers["groq"].APIKey
apiBase = cfg.Providers["groq"].APIBase
proxy = cfg.Providers["groq"].Proxy
if apiBase == "" {
apiBase = "https://api.groq.com/openai/v1"
}
case (strings.Contains(lowerModel, "nvidia") || strings.HasPrefix(model, "nvidia/")) && cfg.Providers.Nvidia.APIKey != "":
apiKey = cfg.Providers.Nvidia.APIKey
apiBase = cfg.Providers.Nvidia.APIBase
proxy = cfg.Providers.Nvidia.Proxy
case (strings.Contains(lowerModel, "nvidia") || strings.HasPrefix(model, "nvidia/")) && cfg.Providers["nvidia"].APIKey != "":
apiKey = cfg.Providers["nvidia"].APIKey
apiBase = cfg.Providers["nvidia"].APIBase
proxy = cfg.Providers["nvidia"].Proxy
if apiBase == "" {
apiBase = "https://integrate.api.nvidia.com/v1"
}
case (strings.Contains(lowerModel, "ollama") || strings.HasPrefix(model, "ollama/")) && cfg.Providers.Ollama.APIKey != "":
case (strings.Contains(lowerModel, "ollama") || strings.HasPrefix(model, "ollama/")) && cfg.Providers["ollama"].APIKey != "":
fmt.Println("Ollama provider selected based on model name prefix")
apiKey = cfg.Providers.Ollama.APIKey
apiBase = cfg.Providers.Ollama.APIBase
proxy = cfg.Providers.Ollama.Proxy
apiKey = cfg.Providers["ollama"].APIKey
apiBase = cfg.Providers["ollama"].APIBase
proxy = cfg.Providers["ollama"].Proxy
if apiBase == "" {
apiBase = "http://localhost:11434/v1"
}
fmt.Println("Ollama apiBase:", apiBase)
case cfg.Providers.VLLM.APIBase != "":
apiKey = cfg.Providers.VLLM.APIKey
apiBase = cfg.Providers.VLLM.APIBase
proxy = cfg.Providers.VLLM.Proxy
case cfg.Providers["vllm"].APIBase != "":
apiKey = cfg.Providers["vllm"].APIKey
apiBase = cfg.Providers["vllm"].APIBase
proxy = cfg.Providers["vllm"].Proxy
default:
if cfg.Providers.OpenRouter.APIKey != "" {
apiKey = cfg.Providers.OpenRouter.APIKey
proxy = cfg.Providers.OpenRouter.Proxy
if cfg.Providers.OpenRouter.APIBase != "" {
apiBase = cfg.Providers.OpenRouter.APIBase
if cfg.Providers["openrouter"].APIKey != "" {
apiKey = cfg.Providers["openrouter"].APIKey
proxy = cfg.Providers["openrouter"].Proxy
if cfg.Providers["openrouter"].APIBase != "" {
apiBase = cfg.Providers["openrouter"].APIBase
} else {
apiBase = "https://openrouter.ai/api/v1"
}