mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
feat: add Avian as a named LLM provider
Add Avian (https://avian.io) as an OpenAI-compatible provider with API base https://api.avian.io/v1 and AVIAN_API_KEY env var support. Models: deepseek/deepseek-v3.2, moonshotai/kimi-k2.5, z-ai/glm-5, minimax/minimax-m2.5. Supports chat completions, streaming, and function calling. Changes: - Add Avian to ProvidersConfig struct, IsEmpty(), HasProvidersConfig() - Add avian protocol to factory provider and default API base - Add avian case to legacy provider selection (factory.go) - Add avian migration rule for old config format - Add default model entries to ModelList (deepseek-v3.2, kimi-k2.5) - Add avian to example config - Update AllProviders test count from 18 to 19
This commit is contained in:
@@ -222,6 +222,10 @@
|
||||
"mistral": {
|
||||
"api_key": "",
|
||||
"api_base": "https://api.mistral.ai/v1"
|
||||
},
|
||||
"avian": {
|
||||
"api_key": "",
|
||||
"api_base": "https://api.avian.io/v1"
|
||||
}
|
||||
},
|
||||
"tools": {
|
||||
|
||||
@@ -429,6 +429,7 @@ type ProvidersConfig struct {
|
||||
Antigravity ProviderConfig `json:"antigravity"`
|
||||
Qwen ProviderConfig `json:"qwen"`
|
||||
Mistral ProviderConfig `json:"mistral"`
|
||||
Avian ProviderConfig `json:"avian"`
|
||||
}
|
||||
|
||||
// IsEmpty checks if all provider configs are empty (no API keys or API bases set)
|
||||
@@ -452,7 +453,8 @@ func (p ProvidersConfig) IsEmpty() bool {
|
||||
p.GitHubCopilot.APIKey == "" && p.GitHubCopilot.APIBase == "" &&
|
||||
p.Antigravity.APIKey == "" && p.Antigravity.APIBase == "" &&
|
||||
p.Qwen.APIKey == "" && p.Qwen.APIBase == "" &&
|
||||
p.Mistral.APIKey == "" && p.Mistral.APIBase == ""
|
||||
p.Mistral.APIKey == "" && p.Mistral.APIBase == "" &&
|
||||
p.Avian.APIKey == "" && p.Avian.APIBase == ""
|
||||
}
|
||||
|
||||
// MarshalJSON implements custom JSON marshaling for ProvidersConfig
|
||||
|
||||
@@ -306,6 +306,20 @@ func DefaultConfig() *Config {
|
||||
APIKey: "",
|
||||
},
|
||||
|
||||
// Avian - https://avian.io
|
||||
{
|
||||
ModelName: "deepseek-v3.2",
|
||||
Model: "avian/deepseek/deepseek-v3.2",
|
||||
APIBase: "https://api.avian.io/v1",
|
||||
APIKey: "",
|
||||
},
|
||||
{
|
||||
ModelName: "kimi-k2.5",
|
||||
Model: "avian/moonshotai/kimi-k2.5",
|
||||
APIBase: "https://api.avian.io/v1",
|
||||
APIKey: "",
|
||||
},
|
||||
|
||||
// VLLM (local) - http://localhost:8000
|
||||
{
|
||||
ModelName: "local-model",
|
||||
|
||||
@@ -373,6 +373,23 @@ func ConvertProvidersToModelList(cfg *Config) []ModelConfig {
|
||||
}, true
|
||||
},
|
||||
},
|
||||
{
|
||||
providerNames: []string{"avian"},
|
||||
protocol: "avian",
|
||||
buildConfig: func(p ProvidersConfig) (ModelConfig, bool) {
|
||||
if p.Avian.APIKey == "" && p.Avian.APIBase == "" {
|
||||
return ModelConfig{}, false
|
||||
}
|
||||
return ModelConfig{
|
||||
ModelName: "avian",
|
||||
Model: "avian/deepseek/deepseek-v3.2",
|
||||
APIKey: p.Avian.APIKey,
|
||||
APIBase: p.Avian.APIBase,
|
||||
Proxy: p.Avian.Proxy,
|
||||
RequestTimeout: p.Avian.RequestTimeout,
|
||||
}, true
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Process each provider migration
|
||||
|
||||
@@ -160,6 +160,7 @@ func TestConvertProvidersToModelList_AllProviders(t *testing.T) {
|
||||
Antigravity: ProviderConfig{AuthMethod: "oauth"},
|
||||
Qwen: ProviderConfig{APIKey: "key17"},
|
||||
Mistral: ProviderConfig{APIKey: "key18"},
|
||||
Avian: ProviderConfig{APIKey: "key19"},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -181,6 +181,15 @@ func resolveProviderSelection(cfg *config.Config) (providerSelection, error) {
|
||||
sel.model = "deepseek-chat"
|
||||
}
|
||||
}
|
||||
case "avian":
|
||||
if cfg.Providers.Avian.APIKey != "" {
|
||||
sel.apiKey = cfg.Providers.Avian.APIKey
|
||||
sel.apiBase = cfg.Providers.Avian.APIBase
|
||||
sel.proxy = cfg.Providers.Avian.Proxy
|
||||
if sel.apiBase == "" {
|
||||
sel.apiBase = "https://api.avian.io/v1"
|
||||
}
|
||||
}
|
||||
case "mistral":
|
||||
if cfg.Providers.Mistral.APIKey != "" {
|
||||
sel.apiKey = cfg.Providers.Mistral.APIKey
|
||||
@@ -300,6 +309,13 @@ func resolveProviderSelection(cfg *config.Config) (providerSelection, error) {
|
||||
if sel.apiBase == "" {
|
||||
sel.apiBase = "https://api.mistral.ai/v1"
|
||||
}
|
||||
case strings.HasPrefix(model, "avian/") && cfg.Providers.Avian.APIKey != "":
|
||||
sel.apiKey = cfg.Providers.Avian.APIKey
|
||||
sel.apiBase = cfg.Providers.Avian.APIBase
|
||||
sel.proxy = cfg.Providers.Avian.Proxy
|
||||
if sel.apiBase == "" {
|
||||
sel.apiBase = "https://api.avian.io/v1"
|
||||
}
|
||||
case cfg.Providers.VLLM.APIBase != "":
|
||||
sel.apiKey = cfg.Providers.VLLM.APIKey
|
||||
sel.apiBase = cfg.Providers.VLLM.APIBase
|
||||
|
||||
@@ -94,7 +94,7 @@ func CreateProviderFromConfig(cfg *config.ModelConfig) (LLMProvider, string, err
|
||||
|
||||
case "litellm", "openrouter", "groq", "zhipu", "gemini", "nvidia",
|
||||
"ollama", "moonshot", "shengsuanyun", "deepseek", "cerebras",
|
||||
"volcengine", "vllm", "qwen", "mistral":
|
||||
"volcengine", "vllm", "qwen", "mistral", "avian":
|
||||
// All other OpenAI-compatible HTTP providers
|
||||
if cfg.APIKey == "" && cfg.APIBase == "" {
|
||||
return nil, "", fmt.Errorf("api_key or api_base is required for HTTP-based protocol %q", protocol)
|
||||
@@ -208,6 +208,8 @@ func getDefaultAPIBase(protocol string) string {
|
||||
return "http://localhost:8000/v1"
|
||||
case "mistral":
|
||||
return "https://api.mistral.ai/v1"
|
||||
case "avian":
|
||||
return "https://api.avian.io/v1"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user