refactor: reduce code duplication across providers, status, tools, and auth

- Extract applyProviderConfig() helper to eliminate repeated apiKey/apiBase/proxy
  assignment pattern in factory.go (reduced from 323 to 223 lines)
- Replace repetitive provider status checks with data-driven loops in status display
- Deduplicate filesystem tool constructors via shared newFileSystem() helper
- Unify model type-check functions (isAntigravityModel, isOpenAIModel,
  isAnthropicModel) with generic isProviderModel() helper
- Fix bug in cronSetJobEnabled() that always printed "enabled" regardless
  of the actual enabled/disabled state

https://claude.ai/code/session_01M1YgMhxq3coXK2hGmUvfFX
This commit is contained in:
Claude 2026-02-26 15:09:15 +00:00
parent cca12ab08a
commit 6f72f0f528
No known key found for this signature in database
5 changed files with 97 additions and 204 deletions

View file

@ -416,22 +416,25 @@ func authModelsCmd() error {
return nil return nil
} }
// isAntigravityModel checks if a model string belongs to antigravity provider // isProviderModel checks if a model string matches any of the given provider prefixes.
// It returns true if the model equals a prefix or starts with "prefix/".
func isProviderModel(model string, providers ...string) bool {
for _, p := range providers {
if model == p || strings.HasPrefix(model, p+"/") {
return true
}
}
return false
}
func isAntigravityModel(model string) bool { func isAntigravityModel(model string) bool {
return model == "antigravity" || return isProviderModel(model, "antigravity", "google-antigravity")
model == "google-antigravity" ||
strings.HasPrefix(model, "antigravity/") ||
strings.HasPrefix(model, "google-antigravity/")
} }
// isOpenAIModel checks if a model string belongs to openai provider
func isOpenAIModel(model string) bool { func isOpenAIModel(model string) bool {
return model == "openai" || return isProviderModel(model, "openai")
strings.HasPrefix(model, "openai/")
} }
// isAnthropicModel checks if a model string belongs to anthropic provider
func isAnthropicModel(model string) bool { func isAnthropicModel(model string) bool {
return model == "anthropic" || return isProviderModel(model, "anthropic")
strings.HasPrefix(model, "anthropic/")
} }

View file

@ -59,7 +59,11 @@ func cronSetJobEnabled(storePath, jobID string, enabled bool) {
cs := cron.NewCronService(storePath, nil) cs := cron.NewCronService(storePath, nil)
job := cs.EnableJob(jobID, enabled) job := cs.EnableJob(jobID, enabled)
if job != nil { if job != nil {
fmt.Printf("✓ Job '%s' enabled\n", job.Name) status := "enabled"
if !enabled {
status = "disabled"
}
fmt.Printf("✓ Job '%s' %s\n", job.Name, status)
} else { } else {
fmt.Printf("✗ Job %s not found\n", jobID) fmt.Printf("✗ Job %s not found\n", jobID)
} }

View file

@ -41,46 +41,43 @@ func statusCmd() {
if _, err := os.Stat(configPath); err == nil { if _, err := os.Stat(configPath); err == nil {
fmt.Printf("Model: %s\n", cfg.Agents.Defaults.GetModelName()) fmt.Printf("Model: %s\n", cfg.Agents.Defaults.GetModelName())
hasOpenRouter := cfg.Providers.OpenRouter.APIKey != "" apiKeyProviders := []struct {
hasAnthropic := cfg.Providers.Anthropic.APIKey != "" name string
hasOpenAI := cfg.Providers.OpenAI.APIKey != "" hasKey bool
hasGemini := cfg.Providers.Gemini.APIKey != "" }{
hasZhipu := cfg.Providers.Zhipu.APIKey != "" {"OpenRouter API", cfg.Providers.OpenRouter.APIKey != ""},
hasQwen := cfg.Providers.Qwen.APIKey != "" {"Anthropic API", cfg.Providers.Anthropic.APIKey != ""},
hasGroq := cfg.Providers.Groq.APIKey != "" {"OpenAI API", cfg.Providers.OpenAI.APIKey != ""},
hasVLLM := cfg.Providers.VLLM.APIBase != "" {"Gemini API", cfg.Providers.Gemini.APIKey != ""},
hasMoonshot := cfg.Providers.Moonshot.APIKey != "" {"Zhipu API", cfg.Providers.Zhipu.APIKey != ""},
hasDeepSeek := cfg.Providers.DeepSeek.APIKey != "" {"Qwen API", cfg.Providers.Qwen.APIKey != ""},
hasVolcEngine := cfg.Providers.VolcEngine.APIKey != "" {"Groq API", cfg.Providers.Groq.APIKey != ""},
hasNvidia := cfg.Providers.Nvidia.APIKey != "" {"Moonshot API", cfg.Providers.Moonshot.APIKey != ""},
hasOllama := cfg.Providers.Ollama.APIBase != "" {"DeepSeek API", cfg.Providers.DeepSeek.APIKey != ""},
{"VolcEngine API", cfg.Providers.VolcEngine.APIKey != ""},
{"Nvidia API", cfg.Providers.Nvidia.APIKey != ""},
}
for _, p := range apiKeyProviders {
if p.hasKey {
fmt.Printf("%s: ✓\n", p.name)
} else {
fmt.Printf("%s: not set\n", p.name)
}
}
status := func(enabled bool) string { urlProviders := []struct {
if enabled { name string
return "✓" apiBase string
}{
{"vLLM/Local", cfg.Providers.VLLM.APIBase},
{"Ollama", cfg.Providers.Ollama.APIBase},
} }
return "not set" for _, p := range urlProviders {
} if p.apiBase != "" {
fmt.Println("OpenRouter API:", status(hasOpenRouter)) fmt.Printf("%s: ✓ %s\n", p.name, p.apiBase)
fmt.Println("Anthropic API:", status(hasAnthropic))
fmt.Println("OpenAI API:", status(hasOpenAI))
fmt.Println("Gemini API:", status(hasGemini))
fmt.Println("Zhipu API:", status(hasZhipu))
fmt.Println("Qwen API:", status(hasQwen))
fmt.Println("Groq API:", status(hasGroq))
fmt.Println("Moonshot API:", status(hasMoonshot))
fmt.Println("DeepSeek API:", status(hasDeepSeek))
fmt.Println("VolcEngine API:", status(hasVolcEngine))
fmt.Println("Nvidia API:", status(hasNvidia))
if hasVLLM {
fmt.Printf("vLLM/Local: ✓ %s\n", cfg.Providers.VLLM.APIBase)
} else { } else {
fmt.Println("vLLM/Local: not set") fmt.Printf("%s: not set\n", p.name)
} }
if hasOllama {
fmt.Printf("Ollama: ✓ %s\n", cfg.Providers.Ollama.APIBase)
} else {
fmt.Println("Ollama: not set")
} }
store, _ := auth.LoadStore() store, _ := auth.LoadStore()

View file

@ -35,6 +35,17 @@ type providerSelection struct {
enableWebSearch bool enableWebSearch bool
} }
// applyProviderConfig copies the standard provider config fields into the selection.
// If the resolved apiBase is empty, defaultBase is used as fallback.
func applyProviderConfig(sel *providerSelection, pc config.ProviderConfig, defaultBase string) {
sel.apiKey = pc.APIKey
sel.apiBase = pc.APIBase
sel.proxy = pc.Proxy
if sel.apiBase == "" && defaultBase != "" {
sel.apiBase = defaultBase
}
}
func resolveProviderSelection(cfg *config.Config) (providerSelection, error) { func resolveProviderSelection(cfg *config.Config) (providerSelection, error) {
model := cfg.Agents.Defaults.GetModelName() model := cfg.Agents.Defaults.GetModelName()
providerName := strings.ToLower(cfg.Agents.Defaults.Provider) providerName := strings.ToLower(cfg.Agents.Defaults.Provider)
@ -50,12 +61,7 @@ func resolveProviderSelection(cfg *config.Config) (providerSelection, error) {
switch providerName { switch providerName {
case "groq": case "groq":
if cfg.Providers.Groq.APIKey != "" { if cfg.Providers.Groq.APIKey != "" {
sel.apiKey = cfg.Providers.Groq.APIKey applyProviderConfig(&sel, cfg.Providers.Groq, "https://api.groq.com/openai/v1")
sel.apiBase = cfg.Providers.Groq.APIBase
sel.proxy = cfg.Providers.Groq.Proxy
if sel.apiBase == "" {
sel.apiBase = "https://api.groq.com/openai/v1"
}
} }
case "openai", "gpt": case "openai", "gpt":
if cfg.Providers.OpenAI.APIKey != "" || cfg.Providers.OpenAI.AuthMethod != "" { if cfg.Providers.OpenAI.APIKey != "" || cfg.Providers.OpenAI.AuthMethod != "" {
@ -68,12 +74,7 @@ func resolveProviderSelection(cfg *config.Config) (providerSelection, error) {
sel.providerType = providerTypeCodexAuth sel.providerType = providerTypeCodexAuth
return sel, nil return sel, nil
} }
sel.apiKey = cfg.Providers.OpenAI.APIKey applyProviderConfig(&sel, cfg.Providers.OpenAI.ProviderConfig, "https://api.openai.com/v1")
sel.apiBase = cfg.Providers.OpenAI.APIBase
sel.proxy = cfg.Providers.OpenAI.Proxy
if sel.apiBase == "" {
sel.apiBase = "https://api.openai.com/v1"
}
} }
case "anthropic", "claude": case "anthropic", "claude":
if cfg.Providers.Anthropic.APIKey != "" || cfg.Providers.Anthropic.AuthMethod != "" { if cfg.Providers.Anthropic.APIKey != "" || cfg.Providers.Anthropic.AuthMethod != "" {
@ -85,64 +86,31 @@ func resolveProviderSelection(cfg *config.Config) (providerSelection, error) {
sel.providerType = providerTypeClaudeAuth sel.providerType = providerTypeClaudeAuth
return sel, nil return sel, nil
} }
sel.apiKey = cfg.Providers.Anthropic.APIKey applyProviderConfig(&sel, cfg.Providers.Anthropic, defaultAnthropicAPIBase)
sel.apiBase = cfg.Providers.Anthropic.APIBase
sel.proxy = cfg.Providers.Anthropic.Proxy
if sel.apiBase == "" {
sel.apiBase = defaultAnthropicAPIBase
}
} }
case "openrouter": case "openrouter":
if cfg.Providers.OpenRouter.APIKey != "" { if cfg.Providers.OpenRouter.APIKey != "" {
sel.apiKey = cfg.Providers.OpenRouter.APIKey applyProviderConfig(&sel, cfg.Providers.OpenRouter, "https://openrouter.ai/api/v1")
sel.proxy = cfg.Providers.OpenRouter.Proxy
if cfg.Providers.OpenRouter.APIBase != "" {
sel.apiBase = cfg.Providers.OpenRouter.APIBase
} else {
sel.apiBase = "https://openrouter.ai/api/v1"
}
} }
case "zhipu", "glm": case "zhipu", "glm":
if cfg.Providers.Zhipu.APIKey != "" { if cfg.Providers.Zhipu.APIKey != "" {
sel.apiKey = cfg.Providers.Zhipu.APIKey applyProviderConfig(&sel, cfg.Providers.Zhipu, "https://open.bigmodel.cn/api/paas/v4")
sel.apiBase = cfg.Providers.Zhipu.APIBase
sel.proxy = cfg.Providers.Zhipu.Proxy
if sel.apiBase == "" {
sel.apiBase = "https://open.bigmodel.cn/api/paas/v4"
}
} }
case "gemini", "google": case "gemini", "google":
if cfg.Providers.Gemini.APIKey != "" { if cfg.Providers.Gemini.APIKey != "" {
sel.apiKey = cfg.Providers.Gemini.APIKey applyProviderConfig(&sel, cfg.Providers.Gemini, "https://generativelanguage.googleapis.com/v1beta")
sel.apiBase = cfg.Providers.Gemini.APIBase
sel.proxy = cfg.Providers.Gemini.Proxy
if sel.apiBase == "" {
sel.apiBase = "https://generativelanguage.googleapis.com/v1beta"
}
} }
case "vllm": case "vllm":
if cfg.Providers.VLLM.APIBase != "" { if cfg.Providers.VLLM.APIBase != "" {
sel.apiKey = cfg.Providers.VLLM.APIKey applyProviderConfig(&sel, cfg.Providers.VLLM, "")
sel.apiBase = cfg.Providers.VLLM.APIBase
sel.proxy = cfg.Providers.VLLM.Proxy
} }
case "shengsuanyun": case "shengsuanyun":
if cfg.Providers.ShengSuanYun.APIKey != "" { if cfg.Providers.ShengSuanYun.APIKey != "" {
sel.apiKey = cfg.Providers.ShengSuanYun.APIKey applyProviderConfig(&sel, cfg.Providers.ShengSuanYun, "https://router.shengsuanyun.com/api/v1")
sel.apiBase = cfg.Providers.ShengSuanYun.APIBase
sel.proxy = cfg.Providers.ShengSuanYun.Proxy
if sel.apiBase == "" {
sel.apiBase = "https://router.shengsuanyun.com/api/v1"
}
} }
case "nvidia": case "nvidia":
if cfg.Providers.Nvidia.APIKey != "" { if cfg.Providers.Nvidia.APIKey != "" {
sel.apiKey = cfg.Providers.Nvidia.APIKey applyProviderConfig(&sel, cfg.Providers.Nvidia, "https://integrate.api.nvidia.com/v1")
sel.apiBase = cfg.Providers.Nvidia.APIBase
sel.proxy = cfg.Providers.Nvidia.Proxy
if sel.apiBase == "" {
sel.apiBase = "https://integrate.api.nvidia.com/v1"
}
} }
case "claude-cli", "claude-code", "claudecode": case "claude-cli", "claude-code", "claudecode":
workspace := cfg.WorkspacePath() workspace := cfg.WorkspacePath()
@ -162,24 +130,14 @@ func resolveProviderSelection(cfg *config.Config) (providerSelection, error) {
return sel, nil return sel, nil
case "deepseek": case "deepseek":
if cfg.Providers.DeepSeek.APIKey != "" { if cfg.Providers.DeepSeek.APIKey != "" {
sel.apiKey = cfg.Providers.DeepSeek.APIKey applyProviderConfig(&sel, cfg.Providers.DeepSeek, "https://api.deepseek.com/v1")
sel.apiBase = cfg.Providers.DeepSeek.APIBase
sel.proxy = cfg.Providers.DeepSeek.Proxy
if sel.apiBase == "" {
sel.apiBase = "https://api.deepseek.com/v1"
}
if model != "deepseek-chat" && model != "deepseek-reasoner" { if model != "deepseek-chat" && model != "deepseek-reasoner" {
sel.model = "deepseek-chat" sel.model = "deepseek-chat"
} }
} }
case "mistral": case "mistral":
if cfg.Providers.Mistral.APIKey != "" { if cfg.Providers.Mistral.APIKey != "" {
sel.apiKey = cfg.Providers.Mistral.APIKey applyProviderConfig(&sel, cfg.Providers.Mistral, "https://api.mistral.ai/v1")
sel.apiBase = cfg.Providers.Mistral.APIBase
sel.proxy = cfg.Providers.Mistral.Proxy
if sel.apiBase == "" {
sel.apiBase = "https://api.mistral.ai/v1"
}
} }
case "github_copilot", "copilot": case "github_copilot", "copilot":
sel.providerType = providerTypeGitHubCopilot sel.providerType = providerTypeGitHubCopilot
@ -197,25 +155,14 @@ func resolveProviderSelection(cfg *config.Config) (providerSelection, error) {
if sel.apiKey == "" && sel.apiBase == "" { if sel.apiKey == "" && sel.apiBase == "" {
switch { switch {
case (strings.Contains(lowerModel, "kimi") || strings.Contains(lowerModel, "moonshot") || strings.HasPrefix(model, "moonshot/")) && cfg.Providers.Moonshot.APIKey != "": case (strings.Contains(lowerModel, "kimi") || strings.Contains(lowerModel, "moonshot") || strings.HasPrefix(model, "moonshot/")) && cfg.Providers.Moonshot.APIKey != "":
sel.apiKey = cfg.Providers.Moonshot.APIKey applyProviderConfig(&sel, cfg.Providers.Moonshot, "https://api.moonshot.cn/v1")
sel.apiBase = cfg.Providers.Moonshot.APIBase
sel.proxy = cfg.Providers.Moonshot.Proxy
if sel.apiBase == "" {
sel.apiBase = "https://api.moonshot.cn/v1"
}
case strings.HasPrefix(model, "openrouter/") || case strings.HasPrefix(model, "openrouter/") ||
strings.HasPrefix(model, "anthropic/") || strings.HasPrefix(model, "anthropic/") ||
strings.HasPrefix(model, "openai/") || strings.HasPrefix(model, "openai/") ||
strings.HasPrefix(model, "meta-llama/") || strings.HasPrefix(model, "meta-llama/") ||
strings.HasPrefix(model, "deepseek/") || strings.HasPrefix(model, "deepseek/") ||
strings.HasPrefix(model, "google/"): strings.HasPrefix(model, "google/"):
sel.apiKey = cfg.Providers.OpenRouter.APIKey applyProviderConfig(&sel, cfg.Providers.OpenRouter, "https://openrouter.ai/api/v1")
sel.proxy = cfg.Providers.OpenRouter.Proxy
if cfg.Providers.OpenRouter.APIBase != "" {
sel.apiBase = cfg.Providers.OpenRouter.APIBase
} else {
sel.apiBase = "https://openrouter.ai/api/v1"
}
case (strings.Contains(lowerModel, "claude") || strings.HasPrefix(model, "anthropic/")) && case (strings.Contains(lowerModel, "claude") || strings.HasPrefix(model, "anthropic/")) &&
(cfg.Providers.Anthropic.APIKey != "" || cfg.Providers.Anthropic.AuthMethod != ""): (cfg.Providers.Anthropic.APIKey != "" || cfg.Providers.Anthropic.AuthMethod != ""):
if cfg.Providers.Anthropic.AuthMethod == "oauth" || cfg.Providers.Anthropic.AuthMethod == "token" { if cfg.Providers.Anthropic.AuthMethod == "oauth" || cfg.Providers.Anthropic.AuthMethod == "token" {
@ -226,12 +173,7 @@ func resolveProviderSelection(cfg *config.Config) (providerSelection, error) {
sel.providerType = providerTypeClaudeAuth sel.providerType = providerTypeClaudeAuth
return sel, nil return sel, nil
} }
sel.apiKey = cfg.Providers.Anthropic.APIKey applyProviderConfig(&sel, cfg.Providers.Anthropic, defaultAnthropicAPIBase)
sel.apiBase = cfg.Providers.Anthropic.APIBase
sel.proxy = cfg.Providers.Anthropic.Proxy
if sel.apiBase == "" {
sel.apiBase = defaultAnthropicAPIBase
}
case (strings.Contains(lowerModel, "gpt") || strings.HasPrefix(model, "openai/")) && case (strings.Contains(lowerModel, "gpt") || strings.HasPrefix(model, "openai/")) &&
(cfg.Providers.OpenAI.APIKey != "" || cfg.Providers.OpenAI.AuthMethod != ""): (cfg.Providers.OpenAI.APIKey != "" || cfg.Providers.OpenAI.AuthMethod != ""):
sel.enableWebSearch = cfg.Providers.OpenAI.WebSearch sel.enableWebSearch = cfg.Providers.OpenAI.WebSearch
@ -243,67 +185,24 @@ func resolveProviderSelection(cfg *config.Config) (providerSelection, error) {
sel.providerType = providerTypeCodexAuth sel.providerType = providerTypeCodexAuth
return sel, nil return sel, nil
} }
sel.apiKey = cfg.Providers.OpenAI.APIKey applyProviderConfig(&sel, cfg.Providers.OpenAI.ProviderConfig, "https://api.openai.com/v1")
sel.apiBase = cfg.Providers.OpenAI.APIBase
sel.proxy = cfg.Providers.OpenAI.Proxy
if sel.apiBase == "" {
sel.apiBase = "https://api.openai.com/v1"
}
case (strings.Contains(lowerModel, "gemini") || strings.HasPrefix(model, "google/")) && cfg.Providers.Gemini.APIKey != "": case (strings.Contains(lowerModel, "gemini") || strings.HasPrefix(model, "google/")) && cfg.Providers.Gemini.APIKey != "":
sel.apiKey = cfg.Providers.Gemini.APIKey applyProviderConfig(&sel, cfg.Providers.Gemini, "https://generativelanguage.googleapis.com/v1beta")
sel.apiBase = cfg.Providers.Gemini.APIBase
sel.proxy = cfg.Providers.Gemini.Proxy
if sel.apiBase == "" {
sel.apiBase = "https://generativelanguage.googleapis.com/v1beta"
}
case (strings.Contains(lowerModel, "glm") || strings.Contains(lowerModel, "zhipu") || strings.Contains(lowerModel, "zai")) && cfg.Providers.Zhipu.APIKey != "": case (strings.Contains(lowerModel, "glm") || strings.Contains(lowerModel, "zhipu") || strings.Contains(lowerModel, "zai")) && cfg.Providers.Zhipu.APIKey != "":
sel.apiKey = cfg.Providers.Zhipu.APIKey applyProviderConfig(&sel, cfg.Providers.Zhipu, "https://open.bigmodel.cn/api/paas/v4")
sel.apiBase = cfg.Providers.Zhipu.APIBase
sel.proxy = cfg.Providers.Zhipu.Proxy
if sel.apiBase == "" {
sel.apiBase = "https://open.bigmodel.cn/api/paas/v4"
}
case (strings.Contains(lowerModel, "groq") || strings.HasPrefix(model, "groq/")) && cfg.Providers.Groq.APIKey != "": case (strings.Contains(lowerModel, "groq") || strings.HasPrefix(model, "groq/")) && cfg.Providers.Groq.APIKey != "":
sel.apiKey = cfg.Providers.Groq.APIKey applyProviderConfig(&sel, cfg.Providers.Groq, "https://api.groq.com/openai/v1")
sel.apiBase = cfg.Providers.Groq.APIBase
sel.proxy = cfg.Providers.Groq.Proxy
if sel.apiBase == "" {
sel.apiBase = "https://api.groq.com/openai/v1"
}
case (strings.Contains(lowerModel, "nvidia") || strings.HasPrefix(model, "nvidia/")) && cfg.Providers.Nvidia.APIKey != "": case (strings.Contains(lowerModel, "nvidia") || strings.HasPrefix(model, "nvidia/")) && cfg.Providers.Nvidia.APIKey != "":
sel.apiKey = cfg.Providers.Nvidia.APIKey applyProviderConfig(&sel, cfg.Providers.Nvidia, "https://integrate.api.nvidia.com/v1")
sel.apiBase = cfg.Providers.Nvidia.APIBase
sel.proxy = cfg.Providers.Nvidia.Proxy
if sel.apiBase == "" {
sel.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 != "":
sel.apiKey = cfg.Providers.Ollama.APIKey applyProviderConfig(&sel, cfg.Providers.Ollama, "http://localhost:11434/v1")
sel.apiBase = cfg.Providers.Ollama.APIBase
sel.proxy = cfg.Providers.Ollama.Proxy
if sel.apiBase == "" {
sel.apiBase = "http://localhost:11434/v1"
}
case (strings.Contains(lowerModel, "mistral") || strings.HasPrefix(model, "mistral/")) && cfg.Providers.Mistral.APIKey != "": case (strings.Contains(lowerModel, "mistral") || strings.HasPrefix(model, "mistral/")) && cfg.Providers.Mistral.APIKey != "":
sel.apiKey = cfg.Providers.Mistral.APIKey applyProviderConfig(&sel, cfg.Providers.Mistral, "https://api.mistral.ai/v1")
sel.apiBase = cfg.Providers.Mistral.APIBase
sel.proxy = cfg.Providers.Mistral.Proxy
if sel.apiBase == "" {
sel.apiBase = "https://api.mistral.ai/v1"
}
case cfg.Providers.VLLM.APIBase != "": case cfg.Providers.VLLM.APIBase != "":
sel.apiKey = cfg.Providers.VLLM.APIKey applyProviderConfig(&sel, cfg.Providers.VLLM, "")
sel.apiBase = cfg.Providers.VLLM.APIBase
sel.proxy = cfg.Providers.VLLM.Proxy
default: default:
if cfg.Providers.OpenRouter.APIKey != "" { if cfg.Providers.OpenRouter.APIKey != "" {
sel.apiKey = cfg.Providers.OpenRouter.APIKey applyProviderConfig(&sel, cfg.Providers.OpenRouter, "https://openrouter.ai/api/v1")
sel.proxy = cfg.Providers.OpenRouter.Proxy
if cfg.Providers.OpenRouter.APIBase != "" {
sel.apiBase = cfg.Providers.OpenRouter.APIBase
} else {
sel.apiBase = "https://openrouter.ai/api/v1"
}
} else { } else {
return providerSelection{}, fmt.Errorf("no API key configured for model: %s", model) return providerSelection{}, fmt.Errorf("no API key configured for model: %s", model)
} }

View file

@ -85,14 +85,16 @@ type ReadFileTool struct {
fs fileSystem fs fileSystem
} }
func NewReadFileTool(workspace string, restrict bool) *ReadFileTool { // newFileSystem creates the appropriate fileSystem based on sandbox settings.
var fs fileSystem func newFileSystem(workspace string, restrict bool) fileSystem {
if restrict { if restrict {
fs = &sandboxFs{workspace: workspace} return &sandboxFs{workspace: workspace}
} else {
fs = &hostFs{}
} }
return &ReadFileTool{fs: fs} return &hostFs{}
}
func NewReadFileTool(workspace string, restrict bool) *ReadFileTool {
return &ReadFileTool{fs: newFileSystem(workspace, restrict)}
} }
func (t *ReadFileTool) Name() string { func (t *ReadFileTool) Name() string {
@ -138,13 +140,7 @@ type WriteFileTool struct {
} }
func NewWriteFileTool(workspace string, restrict bool) *WriteFileTool { func NewWriteFileTool(workspace string, restrict bool) *WriteFileTool {
var fs fileSystem return &WriteFileTool{fs: newFileSystem(workspace, restrict)}
if restrict {
fs = &sandboxFs{workspace: workspace}
} else {
fs = &hostFs{}
}
return &WriteFileTool{fs: fs}
} }
func (t *WriteFileTool) Name() string { func (t *WriteFileTool) Name() string {
@ -195,13 +191,7 @@ type ListDirTool struct {
} }
func NewListDirTool(workspace string, restrict bool) *ListDirTool { func NewListDirTool(workspace string, restrict bool) *ListDirTool {
var fs fileSystem return &ListDirTool{fs: newFileSystem(workspace, restrict)}
if restrict {
fs = &sandboxFs{workspace: workspace}
} else {
fs = &hostFs{}
}
return &ListDirTool{fs: fs}
} }
func (t *ListDirTool) Name() string { func (t *ListDirTool) Name() string {