fix: resolve provider env vars not being applied (#66)

Replace unsupported {{.Name}} template syntax in ProviderConfig env tags
with envPrefix on each provider field in ProvidersConfig, so that
environment variables like PICOCLAW_PROVIDERS_ANTHROPIC_API_KEY are
correctly parsed by caarlos0/env.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
boengai 2026-02-16 11:53:04 +07:00
parent 341dbd3007
commit d891405c9d
2 changed files with 46 additions and 18 deletions

View file

@ -167,27 +167,27 @@ type DevicesConfig struct {
}
type ProvidersConfig struct {
Anthropic ProviderConfig `json:"anthropic"`
OpenAI ProviderConfig `json:"openai"`
OpenRouter ProviderConfig `json:"openrouter"`
Groq ProviderConfig `json:"groq"`
Zhipu ProviderConfig `json:"zhipu"`
VLLM ProviderConfig `json:"vllm"`
Gemini ProviderConfig `json:"gemini"`
Nvidia ProviderConfig `json:"nvidia"`
Ollama ProviderConfig `json:"ollama"`
Moonshot ProviderConfig `json:"moonshot"`
ShengSuanYun ProviderConfig `json:"shengsuanyun"`
DeepSeek ProviderConfig `json:"deepseek"`
GitHubCopilot ProviderConfig `json:"github_copilot"`
Anthropic ProviderConfig `json:"anthropic" envPrefix:"PICOCLAW_PROVIDERS_ANTHROPIC_"`
OpenAI ProviderConfig `json:"openai" envPrefix:"PICOCLAW_PROVIDERS_OPENAI_"`
OpenRouter ProviderConfig `json:"openrouter" envPrefix:"PICOCLAW_PROVIDERS_OPENROUTER_"`
Groq ProviderConfig `json:"groq" envPrefix:"PICOCLAW_PROVIDERS_GROQ_"`
Zhipu ProviderConfig `json:"zhipu" envPrefix:"PICOCLAW_PROVIDERS_ZHIPU_"`
VLLM ProviderConfig `json:"vllm" envPrefix:"PICOCLAW_PROVIDERS_VLLM_"`
Gemini ProviderConfig `json:"gemini" envPrefix:"PICOCLAW_PROVIDERS_GEMINI_"`
Nvidia ProviderConfig `json:"nvidia" envPrefix:"PICOCLAW_PROVIDERS_NVIDIA_"`
Ollama ProviderConfig `json:"ollama" envPrefix:"PICOCLAW_PROVIDERS_OLLAMA_"`
Moonshot ProviderConfig `json:"moonshot" envPrefix:"PICOCLAW_PROVIDERS_MOONSHOT_"`
ShengSuanYun ProviderConfig `json:"shengsuanyun" envPrefix:"PICOCLAW_PROVIDERS_SHENGSUANYUN_"`
DeepSeek ProviderConfig `json:"deepseek" envPrefix:"PICOCLAW_PROVIDERS_DEEPSEEK_"`
GitHubCopilot ProviderConfig `json:"github_copilot" envPrefix:"PICOCLAW_PROVIDERS_GITHUB_COPILOT_"`
}
type ProviderConfig struct {
APIKey string `json:"api_key" env:"PICOCLAW_PROVIDERS_{{.Name}}_API_KEY"`
APIBase string `json:"api_base" env:"PICOCLAW_PROVIDERS_{{.Name}}_API_BASE"`
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`
APIKey string `json:"api_key" env:"API_KEY"`
APIBase string `json:"api_base" env:"API_BASE"`
Proxy string `json:"proxy,omitempty" env:"PROXY"`
AuthMethod string `json:"auth_method,omitempty" env:"AUTH_METHOD"`
ConnectMode string `json:"connect_mode,omitempty" env:"CONNECT_MODE"` //only for Github Copilot, `stdio` or `grpc`
}
type GatewayConfig struct {

View file

@ -2,6 +2,8 @@ package config
import (
"testing"
"github.com/caarlos0/env/v11"
)
// TestDefaultConfig_HeartbeatEnabled verifies heartbeat is enabled by default
@ -147,6 +149,32 @@ func TestDefaultConfig_WebTools(t *testing.T) {
}
}
// TestProviderConfig_EnvVars verifies provider env vars are correctly parsed
func TestProviderConfig_EnvVars(t *testing.T) {
t.Setenv("PICOCLAW_PROVIDERS_ANTHROPIC_API_KEY", "test-anthropic-key")
t.Setenv("PICOCLAW_PROVIDERS_OPENAI_API_KEY", "test-openai-key")
t.Setenv("PICOCLAW_PROVIDERS_OPENAI_API_BASE", "https://custom.openai.example.com")
t.Setenv("PICOCLAW_PROVIDERS_GITHUB_COPILOT_CONNECT_MODE", "stdio")
cfg := DefaultConfig()
if err := env.Parse(cfg); err != nil {
t.Fatalf("env.Parse failed: %v", err)
}
if cfg.Providers.Anthropic.APIKey != "test-anthropic-key" {
t.Errorf("Anthropic API key: got %q, want %q", cfg.Providers.Anthropic.APIKey, "test-anthropic-key")
}
if cfg.Providers.OpenAI.APIKey != "test-openai-key" {
t.Errorf("OpenAI API key: got %q, want %q", cfg.Providers.OpenAI.APIKey, "test-openai-key")
}
if cfg.Providers.OpenAI.APIBase != "https://custom.openai.example.com" {
t.Errorf("OpenAI API base: got %q, want %q", cfg.Providers.OpenAI.APIBase, "https://custom.openai.example.com")
}
if cfg.Providers.GitHubCopilot.ConnectMode != "stdio" {
t.Errorf("GitHub Copilot connect mode: got %q, want %q", cfg.Providers.GitHubCopilot.ConnectMode, "stdio")
}
}
// TestConfig_Complete verifies all config fields are set
func TestConfig_Complete(t *testing.T) {
cfg := DefaultConfig()