feat(config): add complete model_list template with all 17 providers
- Include all 17 supported providers in default config as templates - Each entry has model_name, model, api_base, and empty api_key - Add comments with API key links for each provider - Keep onboard message simple (only OpenRouter and Ollama) - Fix duplicate model_name (cerebras-llama-3.3-70b) Providers included: Zhipu, OpenAI, Anthropic, DeepSeek, Gemini, Qwen, Moonshot, Groq, OpenRouter, NVIDIA, Cerebras, Volcengine, ShengsuanYun, Antigravity, GitHub Copilot, Ollama, VLLM Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
08d9396767
commit
8df3b0b8ef
3 changed files with 211 additions and 22 deletions
|
|
@ -43,7 +43,13 @@ func onboard() {
|
||||||
fmt.Printf("%s picoclaw is ready!\n", logo)
|
fmt.Printf("%s picoclaw is ready!\n", logo)
|
||||||
fmt.Println("\nNext steps:")
|
fmt.Println("\nNext steps:")
|
||||||
fmt.Println(" 1. Add your API key to", configPath)
|
fmt.Println(" 1. Add your API key to", configPath)
|
||||||
fmt.Println(" Get one at: https://openrouter.ai/keys")
|
fmt.Println("")
|
||||||
|
fmt.Println(" Recommended:")
|
||||||
|
fmt.Println(" - OpenRouter: https://openrouter.ai/keys (access 100+ models)")
|
||||||
|
fmt.Println(" - Ollama: https://ollama.com (local, free)")
|
||||||
|
fmt.Println("")
|
||||||
|
fmt.Println(" See README.md for 17+ supported providers.")
|
||||||
|
fmt.Println("")
|
||||||
fmt.Println(" 2. Chat: picoclaw agent -m \"Hello!\"")
|
fmt.Println(" 2. Chat: picoclaw agent -m \"Hello!\"")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ type Config struct {
|
||||||
Bindings []AgentBinding `json:"bindings,omitempty"`
|
Bindings []AgentBinding `json:"bindings,omitempty"`
|
||||||
Session SessionConfig `json:"session,omitempty"`
|
Session SessionConfig `json:"session,omitempty"`
|
||||||
Channels ChannelsConfig `json:"channels"`
|
Channels ChannelsConfig `json:"channels"`
|
||||||
Providers ProvidersConfig `json:"providers"`
|
Providers ProvidersConfig `json:"providers,omitempty"`
|
||||||
ModelList []ModelConfig `json:"model_list"` // New model-centric provider configuration
|
ModelList []ModelConfig `json:"model_list"` // New model-centric provider configuration
|
||||||
Gateway GatewayConfig `json:"gateway"`
|
Gateway GatewayConfig `json:"gateway"`
|
||||||
Tools ToolsConfig `json:"tools"`
|
Tools ToolsConfig `json:"tools"`
|
||||||
|
|
@ -59,6 +59,31 @@ type Config struct {
|
||||||
rrCounters map[string]*atomic.Uint64 // Round-robin counters for load balancing
|
rrCounters map[string]*atomic.Uint64 // Round-robin counters for load balancing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements custom JSON marshaling for Config
|
||||||
|
// to omit providers section when empty and session when empty
|
||||||
|
func (c Config) MarshalJSON() ([]byte, error) {
|
||||||
|
type Alias Config
|
||||||
|
aux := &struct {
|
||||||
|
Providers *ProvidersConfig `json:"providers,omitempty"`
|
||||||
|
Session *SessionConfig `json:"session,omitempty"`
|
||||||
|
*Alias
|
||||||
|
}{
|
||||||
|
Alias: (*Alias)(&c),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only include providers if not empty
|
||||||
|
if !c.Providers.IsEmpty() {
|
||||||
|
aux.Providers = &c.Providers
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only include session if not empty
|
||||||
|
if c.Session.DMScope != "" || len(c.Session.IdentityLinks) > 0 {
|
||||||
|
aux.Session = &c.Session
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.Marshal(aux)
|
||||||
|
}
|
||||||
|
|
||||||
type AgentsConfig struct {
|
type AgentsConfig struct {
|
||||||
Defaults AgentDefaults `json:"defaults"`
|
Defaults AgentDefaults `json:"defaults"`
|
||||||
List []AgentConfig `json:"list,omitempty"`
|
List []AgentConfig `json:"list,omitempty"`
|
||||||
|
|
@ -272,6 +297,38 @@ type ProvidersConfig struct {
|
||||||
Qwen ProviderConfig `json:"qwen"`
|
Qwen ProviderConfig `json:"qwen"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsEmpty checks if all provider configs are empty (no API keys or API bases set)
|
||||||
|
// Note: WebSearch is an optimization option and doesn't count as "non-empty"
|
||||||
|
func (p ProvidersConfig) IsEmpty() bool {
|
||||||
|
return p.Anthropic.APIKey == "" && p.Anthropic.APIBase == "" &&
|
||||||
|
p.OpenAI.APIKey == "" && p.OpenAI.APIBase == "" &&
|
||||||
|
p.OpenRouter.APIKey == "" && p.OpenRouter.APIBase == "" &&
|
||||||
|
p.Groq.APIKey == "" && p.Groq.APIBase == "" &&
|
||||||
|
p.Zhipu.APIKey == "" && p.Zhipu.APIBase == "" &&
|
||||||
|
p.VLLM.APIKey == "" && p.VLLM.APIBase == "" &&
|
||||||
|
p.Gemini.APIKey == "" && p.Gemini.APIBase == "" &&
|
||||||
|
p.Nvidia.APIKey == "" && p.Nvidia.APIBase == "" &&
|
||||||
|
p.Ollama.APIKey == "" && p.Ollama.APIBase == "" &&
|
||||||
|
p.Moonshot.APIKey == "" && p.Moonshot.APIBase == "" &&
|
||||||
|
p.ShengSuanYun.APIKey == "" && p.ShengSuanYun.APIBase == "" &&
|
||||||
|
p.DeepSeek.APIKey == "" && p.DeepSeek.APIBase == "" &&
|
||||||
|
p.Cerebras.APIKey == "" && p.Cerebras.APIBase == "" &&
|
||||||
|
p.VolcEngine.APIKey == "" && p.VolcEngine.APIBase == "" &&
|
||||||
|
p.GitHubCopilot.APIKey == "" && p.GitHubCopilot.APIBase == "" &&
|
||||||
|
p.Antigravity.APIKey == "" && p.Antigravity.APIBase == "" &&
|
||||||
|
p.Qwen.APIKey == "" && p.Qwen.APIBase == ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements custom JSON marshaling for ProvidersConfig
|
||||||
|
// to omit the entire section when empty
|
||||||
|
func (p ProvidersConfig) MarshalJSON() ([]byte, error) {
|
||||||
|
if p.IsEmpty() {
|
||||||
|
return []byte("null"), nil
|
||||||
|
}
|
||||||
|
type Alias ProvidersConfig
|
||||||
|
return json.Marshal((*Alias)(&p))
|
||||||
|
}
|
||||||
|
|
||||||
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"`
|
||||||
|
|
@ -297,7 +354,7 @@ type ModelConfig struct {
|
||||||
|
|
||||||
// HTTP-based providers
|
// HTTP-based providers
|
||||||
APIBase string `json:"api_base,omitempty"` // API endpoint URL
|
APIBase string `json:"api_base,omitempty"` // API endpoint URL
|
||||||
APIKey string `json:"api_key,omitempty"` // API authentication key
|
APIKey string `json:"api_key"` // API authentication key
|
||||||
Proxy string `json:"proxy,omitempty"` // HTTP proxy URL
|
Proxy string `json:"proxy,omitempty"` // HTTP proxy URL
|
||||||
|
|
||||||
// Special providers (CLI-based, OAuth, etc.)
|
// Special providers (CLI-based, OAuth, etc.)
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@ func DefaultConfig() *Config {
|
||||||
MaxToolIterations: 20,
|
MaxToolIterations: 20,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Bindings: []AgentBinding{},
|
||||||
|
Session: SessionConfig{},
|
||||||
Channels: ChannelsConfig{
|
Channels: ChannelsConfig{
|
||||||
WhatsApp: WhatsAppConfig{
|
WhatsApp: WhatsAppConfig{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
|
|
@ -86,23 +88,147 @@ func DefaultConfig() *Config {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Providers: ProvidersConfig{
|
Providers: ProvidersConfig{
|
||||||
Anthropic: ProviderConfig{},
|
OpenAI: OpenAIProviderConfig{WebSearch: true},
|
||||||
OpenAI: OpenAIProviderConfig{WebSearch: true},
|
},
|
||||||
OpenRouter: ProviderConfig{},
|
ModelList: []ModelConfig{
|
||||||
Groq: ProviderConfig{},
|
// ============================================
|
||||||
Zhipu: ProviderConfig{},
|
// Add your API key to the model you want to use
|
||||||
VLLM: ProviderConfig{},
|
// ============================================
|
||||||
Gemini: ProviderConfig{},
|
|
||||||
Nvidia: ProviderConfig{},
|
// Zhipu AI (智谱) - https://open.bigmodel.cn/usercenter/apikeys
|
||||||
Ollama: ProviderConfig{},
|
{
|
||||||
Moonshot: ProviderConfig{},
|
ModelName: "glm-4.7",
|
||||||
ShengSuanYun: ProviderConfig{},
|
Model: "zhipu/glm-4.7",
|
||||||
DeepSeek: ProviderConfig{},
|
APIBase: "https://open.bigmodel.cn/api/paas/v4",
|
||||||
Cerebras: ProviderConfig{},
|
APIKey: "",
|
||||||
VolcEngine: ProviderConfig{},
|
},
|
||||||
GitHubCopilot: ProviderConfig{},
|
|
||||||
Antigravity: ProviderConfig{},
|
// OpenAI - https://platform.openai.com/api-keys
|
||||||
Qwen: ProviderConfig{},
|
{
|
||||||
|
ModelName: "gpt-4o",
|
||||||
|
Model: "openai/gpt-4o",
|
||||||
|
APIBase: "https://api.openai.com/v1",
|
||||||
|
APIKey: "",
|
||||||
|
},
|
||||||
|
|
||||||
|
// Anthropic Claude - https://console.anthropic.com/settings/keys
|
||||||
|
{
|
||||||
|
ModelName: "claude-sonnet-4",
|
||||||
|
Model: "anthropic/claude-sonnet-4-20250514",
|
||||||
|
APIBase: "https://api.anthropic.com/v1",
|
||||||
|
APIKey: "",
|
||||||
|
},
|
||||||
|
|
||||||
|
// DeepSeek - https://platform.deepseek.com/
|
||||||
|
{
|
||||||
|
ModelName: "deepseek-chat",
|
||||||
|
Model: "deepseek/deepseek-chat",
|
||||||
|
APIBase: "https://api.deepseek.com/v1",
|
||||||
|
APIKey: "",
|
||||||
|
},
|
||||||
|
|
||||||
|
// Google Gemini - https://ai.google.dev/
|
||||||
|
{
|
||||||
|
ModelName: "gemini-2.0-flash",
|
||||||
|
Model: "gemini/gemini-2.0-flash-exp",
|
||||||
|
APIBase: "https://generativelanguage.googleapis.com/v1beta",
|
||||||
|
APIKey: "",
|
||||||
|
},
|
||||||
|
|
||||||
|
// Qwen (通义千问) - https://dashscope.console.aliyun.com/apiKey
|
||||||
|
{
|
||||||
|
ModelName: "qwen-plus",
|
||||||
|
Model: "qwen/qwen-plus",
|
||||||
|
APIBase: "https://dashscope.aliyuncs.com/compatible-mode/v1",
|
||||||
|
APIKey: "",
|
||||||
|
},
|
||||||
|
|
||||||
|
// Moonshot (月之暗面) - https://platform.moonshot.cn/console/api-keys
|
||||||
|
{
|
||||||
|
ModelName: "moonshot-v1-8k",
|
||||||
|
Model: "moonshot/moonshot-v1-8k",
|
||||||
|
APIBase: "https://api.moonshot.cn/v1",
|
||||||
|
APIKey: "",
|
||||||
|
},
|
||||||
|
|
||||||
|
// Groq - https://console.groq.com/keys
|
||||||
|
{
|
||||||
|
ModelName: "llama-3.3-70b",
|
||||||
|
Model: "groq/llama-3.3-70b-versatile",
|
||||||
|
APIBase: "https://api.groq.com/openai/v1",
|
||||||
|
APIKey: "",
|
||||||
|
},
|
||||||
|
|
||||||
|
// OpenRouter (100+ models) - https://openrouter.ai/keys
|
||||||
|
{
|
||||||
|
ModelName: "openrouter-gpt-4o",
|
||||||
|
Model: "openrouter/openai/gpt-4o",
|
||||||
|
APIBase: "https://openrouter.ai/api/v1",
|
||||||
|
APIKey: "",
|
||||||
|
},
|
||||||
|
|
||||||
|
// NVIDIA - https://build.nvidia.com/
|
||||||
|
{
|
||||||
|
ModelName: "nemotron-4-340b",
|
||||||
|
Model: "nvidia/nemotron-4-340b-instruct",
|
||||||
|
APIBase: "https://integrate.api.nvidia.com/v1",
|
||||||
|
APIKey: "",
|
||||||
|
},
|
||||||
|
|
||||||
|
// Cerebras - https://inference.cerebras.ai/
|
||||||
|
{
|
||||||
|
ModelName: "cerebras-llama-3.3-70b",
|
||||||
|
Model: "cerebras/llama-3.3-70b",
|
||||||
|
APIBase: "https://api.cerebras.ai/v1",
|
||||||
|
APIKey: "",
|
||||||
|
},
|
||||||
|
|
||||||
|
// Volcengine (火山引擎) - https://console.volcengine.com/ark
|
||||||
|
{
|
||||||
|
ModelName: "doubao-pro",
|
||||||
|
Model: "volcengine/doubao-pro-32k",
|
||||||
|
APIBase: "https://ark.cn-beijing.volces.com/api/v3",
|
||||||
|
APIKey: "",
|
||||||
|
},
|
||||||
|
|
||||||
|
// ShengsuanYun (神算云)
|
||||||
|
{
|
||||||
|
ModelName: "deepseek-v3",
|
||||||
|
Model: "shengsuanyun/deepseek-v3",
|
||||||
|
APIBase: "https://api.shengsuanyun.com/v1",
|
||||||
|
APIKey: "",
|
||||||
|
},
|
||||||
|
|
||||||
|
// Antigravity (Google Cloud Code Assist) - OAuth only
|
||||||
|
{
|
||||||
|
ModelName: "gemini-flash",
|
||||||
|
Model: "antigravity/gemini-3-flash",
|
||||||
|
AuthMethod: "oauth",
|
||||||
|
},
|
||||||
|
|
||||||
|
// GitHub Copilot - https://github.com/settings/tokens
|
||||||
|
{
|
||||||
|
ModelName: "copilot-gpt-4o",
|
||||||
|
Model: "github-copilot/gpt-4o",
|
||||||
|
APIBase: "http://localhost:4321",
|
||||||
|
AuthMethod: "oauth",
|
||||||
|
},
|
||||||
|
|
||||||
|
// Ollama (local) - https://ollama.com
|
||||||
|
{
|
||||||
|
ModelName: "llama3",
|
||||||
|
Model: "ollama/llama3",
|
||||||
|
APIBase: "http://localhost:11434/v1",
|
||||||
|
APIKey: "ollama",
|
||||||
|
},
|
||||||
|
|
||||||
|
// VLLM (local) - http://localhost:8000
|
||||||
|
{
|
||||||
|
ModelName: "local-model",
|
||||||
|
Model: "vllm/custom-model",
|
||||||
|
APIBase: "http://localhost:8000/v1",
|
||||||
|
APIKey: "",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Gateway: GatewayConfig{
|
Gateway: GatewayConfig{
|
||||||
Host: "0.0.0.0",
|
Host: "0.0.0.0",
|
||||||
|
|
@ -126,12 +252,12 @@ func DefaultConfig() *Config {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Cron: CronToolsConfig{
|
Cron: CronToolsConfig{
|
||||||
ExecTimeoutMinutes: 5, // default 5 minutes for LLM operations
|
ExecTimeoutMinutes: 5,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Heartbeat: HeartbeatConfig{
|
Heartbeat: HeartbeatConfig{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
Interval: 30, // default 30 minutes
|
Interval: 30,
|
||||||
},
|
},
|
||||||
Devices: DevicesConfig{
|
Devices: DevicesConfig{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue