fix: use more elegant way to solve the issue.

This commit is contained in:
zenix.huang 2026-02-18 17:01:28 +09:00
parent 8b3bc15ba2
commit 42d2937372
6 changed files with 50 additions and 37 deletions

View file

@ -80,7 +80,7 @@
"openai": { "openai": {
"api_key": "", "api_key": "",
"api_base": "", "api_base": "",
"codex_web_search": true "web_search": true
}, },
"openrouter": { "openrouter": {
"api_key": "sk-or-v1-xxx", "api_key": "sk-or-v1-xxx",
@ -145,4 +145,4 @@
"host": "0.0.0.0", "host": "0.0.0.0",
"port": 18790 "port": 18790
} }
} }

View file

@ -167,28 +167,32 @@ type DevicesConfig struct {
} }
type ProvidersConfig struct { type ProvidersConfig struct {
Anthropic ProviderConfig `json:"anthropic"` Anthropic ProviderConfig `json:"anthropic"`
OpenAI ProviderConfig `json:"openai"` OpenAI OpenAIProviderConfig `json:"openai"`
OpenRouter ProviderConfig `json:"openrouter"` OpenRouter ProviderConfig `json:"openrouter"`
Groq ProviderConfig `json:"groq"` Groq ProviderConfig `json:"groq"`
Zhipu ProviderConfig `json:"zhipu"` Zhipu ProviderConfig `json:"zhipu"`
VLLM ProviderConfig `json:"vllm"` VLLM ProviderConfig `json:"vllm"`
Gemini ProviderConfig `json:"gemini"` Gemini ProviderConfig `json:"gemini"`
Nvidia ProviderConfig `json:"nvidia"` Nvidia ProviderConfig `json:"nvidia"`
Ollama ProviderConfig `json:"ollama"` Ollama ProviderConfig `json:"ollama"`
Moonshot ProviderConfig `json:"moonshot"` Moonshot ProviderConfig `json:"moonshot"`
ShengSuanYun ProviderConfig `json:"shengsuanyun"` ShengSuanYun ProviderConfig `json:"shengsuanyun"`
DeepSeek ProviderConfig `json:"deepseek"` DeepSeek ProviderConfig `json:"deepseek"`
GitHubCopilot ProviderConfig `json:"github_copilot"` GitHubCopilot ProviderConfig `json:"github_copilot"`
} }
type ProviderConfig struct { type ProviderConfig struct {
APIKey string `json:"api_key" env:"PICOCLAW_PROVIDERS_{{.Name}}_API_KEY"` APIKey string `json:"api_key" env:"PICOCLAW_PROVIDERS_{{.Name}}_API_KEY"`
APIBase string `json:"api_base" env:"PICOCLAW_PROVIDERS_{{.Name}}_API_BASE"` APIBase string `json:"api_base" env:"PICOCLAW_PROVIDERS_{{.Name}}_API_BASE"`
Proxy string `json:"proxy,omitempty" env:"PICOCLAW_PROVIDERS_{{.Name}}_PROXY"` Proxy string `json:"proxy,omitempty" env:"PICOCLAW_PROVIDERS_{{.Name}}_PROXY"`
AuthMethod string `json:"auth_method,omitempty" env:"PICOCLAW_PROVIDERS_{{.Name}}_AUTH_METHOD"` 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` ConnectMode string `json:"connect_mode,omitempty" env:"PICOCLAW_PROVIDERS_{{.Name}}_CONNECT_MODE"` //only for Github Copilot, `stdio` or `grpc`
CodexWebSearch bool `json:"codex_web_search,omitempty" env:"PICOCLAW_PROVIDERS_{{.Name}}_CODEX_WEB_SEARCH"` }
type OpenAIProviderConfig struct {
ProviderConfig
WebSearch bool `json:"web_search" env:"PICOCLAW_PROVIDERS_OPENAI_WEB_SEARCH"`
} }
type GatewayConfig struct { type GatewayConfig struct {
@ -309,7 +313,7 @@ func DefaultConfig() *Config {
}, },
Providers: ProvidersConfig{ Providers: ProvidersConfig{
Anthropic: ProviderConfig{}, Anthropic: ProviderConfig{},
OpenAI: ProviderConfig{CodexWebSearch: true}, OpenAI: OpenAIProviderConfig{WebSearch: true},
OpenRouter: ProviderConfig{}, OpenRouter: ProviderConfig{},
Groq: ProviderConfig{}, Groq: ProviderConfig{},
Zhipu: ProviderConfig{}, Zhipu: ProviderConfig{},

View file

@ -205,14 +205,14 @@ func TestConfig_Complete(t *testing.T) {
} }
} }
func TestDefaultConfig_OpenAICodexWebSearchEnabled(t *testing.T) { func TestDefaultConfig_OpenAIWebSearchEnabled(t *testing.T) {
cfg := DefaultConfig() cfg := DefaultConfig()
if !cfg.Providers.OpenAI.CodexWebSearch { if !cfg.Providers.OpenAI.WebSearch {
t.Fatal("DefaultConfig().Providers.OpenAI.CodexWebSearch should be true") t.Fatal("DefaultConfig().Providers.OpenAI.WebSearch should be true")
} }
} }
func TestLoadConfig_OpenAICodexWebSearchDefaultsTrueWhenUnset(t *testing.T) { func TestLoadConfig_OpenAIWebSearchDefaultsTrueWhenUnset(t *testing.T) {
dir := t.TempDir() dir := t.TempDir()
configPath := filepath.Join(dir, "config.json") configPath := filepath.Join(dir, "config.json")
if err := os.WriteFile(configPath, []byte(`{"providers":{"openai":{"api_base":""}}}`), 0o600); err != nil { if err := os.WriteFile(configPath, []byte(`{"providers":{"openai":{"api_base":""}}}`), 0o600); err != nil {
@ -223,15 +223,15 @@ func TestLoadConfig_OpenAICodexWebSearchDefaultsTrueWhenUnset(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("LoadConfig() error: %v", err) t.Fatalf("LoadConfig() error: %v", err)
} }
if !cfg.Providers.OpenAI.CodexWebSearch { if !cfg.Providers.OpenAI.WebSearch {
t.Fatal("OpenAI codex web search should remain true when unset in config file") t.Fatal("OpenAI codex web search should remain true when unset in config file")
} }
} }
func TestLoadConfig_OpenAICodexWebSearchCanBeDisabled(t *testing.T) { func TestLoadConfig_OpenAIWebSearchCanBeDisabled(t *testing.T) {
dir := t.TempDir() dir := t.TempDir()
configPath := filepath.Join(dir, "config.json") configPath := filepath.Join(dir, "config.json")
if err := os.WriteFile(configPath, []byte(`{"providers":{"openai":{"codex_web_search":false}}}`), 0o600); err != nil { if err := os.WriteFile(configPath, []byte(`{"providers":{"openai":{"web_search":false}}}`), 0o600); err != nil {
t.Fatalf("WriteFile() error: %v", err) t.Fatalf("WriteFile() error: %v", err)
} }
@ -239,7 +239,7 @@ func TestLoadConfig_OpenAICodexWebSearchCanBeDisabled(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("LoadConfig() error: %v", err) t.Fatalf("LoadConfig() error: %v", err)
} }
if cfg.Providers.OpenAI.CodexWebSearch { if cfg.Providers.OpenAI.WebSearch {
t.Fatal("OpenAI codex web search should be false when disabled in config file") t.Fatal("OpenAI codex web search should be false when disabled in config file")
} }
} }

View file

@ -108,7 +108,10 @@ func ConvertConfig(data map[string]interface{}) (*config.Config, []string, error
case "anthropic": case "anthropic":
cfg.Providers.Anthropic = pc cfg.Providers.Anthropic = pc
case "openai": case "openai":
cfg.Providers.OpenAI = pc cfg.Providers.OpenAI = config.OpenAIProviderConfig{
ProviderConfig: pc,
WebSearch: getBoolOrDefault(pMap, "web_search", true),
}
case "openrouter": case "openrouter":
cfg.Providers.OpenRouter = pc cfg.Providers.OpenRouter = pc
case "groq": case "groq":
@ -363,6 +366,13 @@ func getBool(data map[string]interface{}, key string) (bool, bool) {
return b, ok return b, ok
} }
func getBoolOrDefault(data map[string]interface{}, key string, defaultVal bool) bool {
if v, ok := getBool(data, key); ok {
return v
}
return defaultVal
}
func getStringSlice(data map[string]interface{}, key string) []string { func getStringSlice(data map[string]interface{}, key string) []string {
v, ok := data[key] v, ok := data[key]
if !ok { if !ok {

View file

@ -32,9 +32,6 @@ func TestBuildCodexParams_BasicMessage(t *testing.T) {
if params.MaxOutputTokens.Valid() { if params.MaxOutputTokens.Valid() {
t.Fatalf("MaxOutputTokens should not be set for Codex backend") t.Fatalf("MaxOutputTokens should not be set for Codex backend")
} }
if params.MaxOutputTokens.Valid() {
t.Error("MaxOutputTokens should not be set for codex backend")
}
} }
func TestBuildCodexParams_SystemAsInstructions(t *testing.T) { func TestBuildCodexParams_SystemAsInstructions(t *testing.T) {

View file

@ -243,10 +243,12 @@ func CreateProvider(cfg *config.Config) (LLMProvider, error) {
case "openai", "gpt": case "openai", "gpt":
if cfg.Providers.OpenAI.APIKey != "" || cfg.Providers.OpenAI.AuthMethod != "" { if cfg.Providers.OpenAI.APIKey != "" || cfg.Providers.OpenAI.AuthMethod != "" {
if cfg.Providers.OpenAI.AuthMethod == "codex-cli" { if cfg.Providers.OpenAI.AuthMethod == "codex-cli" {
return NewCodexProviderWithTokenSource("", "", CreateCodexCliTokenSource()), nil c := NewCodexProviderWithTokenSource("", "", CreateCodexCliTokenSource())
c.enableWebSearch = cfg.Providers.OpenAI.WebSearch
return c, nil
} }
if cfg.Providers.OpenAI.AuthMethod == "oauth" || cfg.Providers.OpenAI.AuthMethod == "token" { if cfg.Providers.OpenAI.AuthMethod == "oauth" || cfg.Providers.OpenAI.AuthMethod == "token" {
return createCodexAuthProvider(cfg.Providers.OpenAI.CodexWebSearch) return createCodexAuthProvider(cfg.Providers.OpenAI.WebSearch)
} }
apiKey = cfg.Providers.OpenAI.APIKey apiKey = cfg.Providers.OpenAI.APIKey
apiBase = cfg.Providers.OpenAI.APIBase apiBase = cfg.Providers.OpenAI.APIBase
@ -371,7 +373,7 @@ func CreateProvider(cfg *config.Config) (LLMProvider, error) {
case (strings.Contains(lowerModel, "gpt") || strings.HasPrefix(model, "openai/")) && (cfg.Providers.OpenAI.APIKey != "" || cfg.Providers.OpenAI.AuthMethod != ""): 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" { if cfg.Providers.OpenAI.AuthMethod == "oauth" || cfg.Providers.OpenAI.AuthMethod == "token" {
return createCodexAuthProvider(cfg.Providers.OpenAI.CodexWebSearch) return createCodexAuthProvider(cfg.Providers.OpenAI.WebSearch)
} }
apiKey = cfg.Providers.OpenAI.APIKey apiKey = cfg.Providers.OpenAI.APIKey
apiBase = cfg.Providers.OpenAI.APIBase apiBase = cfg.Providers.OpenAI.APIBase