Files
picoclaw/pkg/providers/provider_metadata.go
T
SiYue-ZO 1bc7abfb50 feat(providers): add CommonModels for MiMo provider
Add mimo-v2.5 (multimodal) and mimo-v2.5-pro to MiMo's CommonModels so
the WebUI recommends vision-capable models by default. mimo-v2.5 supports
image understanding while mimo-v2.5-pro is text-only.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-21 16:36:41 +08:00

583 lines
18 KiB
Go

package providers
import "strings"
// ModelProviderOption describes a canonical provider entry exposed to the Web UI.
// It also serves as the backend-owned source of truth for shared provider metadata.
type ModelProviderOption struct {
ID string `json:"id"`
DisplayName string `json:"display_name,omitempty"`
IconSlug string `json:"icon_slug,omitempty"`
Domain string `json:"domain,omitempty"`
DefaultAPIBase string `json:"default_api_base"`
EmptyAPIKeyAllowed bool `json:"empty_api_key_allowed"`
CreateAllowed bool `json:"create_allowed"`
DefaultModelAllowed bool `json:"default_model_allowed"`
SupportsFetch bool `json:"supports_fetch,omitempty"`
DefaultAuthMethod string `json:"default_auth_method,omitempty"`
AuthMethodLocked bool `json:"auth_method_locked,omitempty"`
Local bool `json:"local,omitempty"`
Priority float64 `json:"priority,omitempty"`
CommonModels []string `json:"common_models,omitempty"`
Aliases []string `json:"aliases,omitempty"`
httpAPI bool `json:"-"`
}
var modelProviderOptionsByName = map[string]ModelProviderOption{
"openai": {
ID: "openai",
DisplayName: "OpenAI",
IconSlug: "openai",
Domain: "openai.com",
DefaultAPIBase: "https://api.openai.com/v1",
CreateAllowed: true,
DefaultModelAllowed: true,
SupportsFetch: true,
Priority: 100,
CommonModels: []string{"gpt-5.4", "gpt-5.4-mini", "gpt-5.5"},
Aliases: []string{"gpt"},
httpAPI: true,
},
"anthropic": {
ID: "anthropic",
DisplayName: "Anthropic",
IconSlug: "anthropic",
Domain: "anthropic.com",
DefaultAPIBase: "https://api.anthropic.com/v1",
CreateAllowed: true,
DefaultModelAllowed: true,
Priority: 95,
CommonModels: []string{"claude-opus-4-7", "claude-sonnet-4-6", "claude-haiku-4-5"},
Aliases: []string{"claude"},
httpAPI: true,
},
"anthropic-messages": {
ID: "anthropic-messages",
DisplayName: "Anthropic Messages",
IconSlug: "anthropic",
Domain: "anthropic.com",
DefaultAPIBase: "https://api.anthropic.com/v1",
CreateAllowed: true,
DefaultModelAllowed: true,
Priority: 94,
CommonModels: []string{"claude-opus-4-7", "claude-sonnet-4-6", "claude-haiku-4-5"},
httpAPI: true,
},
"gemini": {
ID: "gemini",
DisplayName: "Google Gemini",
IconSlug: "googlegemini",
Domain: "gemini.google.com",
DefaultAPIBase: "https://generativelanguage.googleapis.com/v1beta",
CreateAllowed: true,
DefaultModelAllowed: true,
Priority: 90,
CommonModels: []string{"gemini-3.1-pro-preview", "gemini-3-flash-preview", "gemini-3.1-flash-lite"},
Aliases: []string{"google"},
httpAPI: true,
},
"deepseek": {
ID: "deepseek",
DisplayName: "DeepSeek",
IconSlug: "deepseek",
Domain: "deepseek.com",
DefaultAPIBase: "https://api.deepseek.com/v1",
CreateAllowed: true,
DefaultModelAllowed: true,
SupportsFetch: true,
Priority: 85,
CommonModels: []string{"deepseek-v4-flash", "deepseek-v4-pro"},
httpAPI: true,
},
"openrouter": {
ID: "openrouter",
DisplayName: "OpenRouter",
IconSlug: "openrouter",
Domain: "openrouter.ai",
DefaultAPIBase: "https://openrouter.ai/api/v1",
CreateAllowed: true,
DefaultModelAllowed: true,
SupportsFetch: true,
Priority: 80,
CommonModels: []string{
"openai/gpt-5.4",
"anthropic/claude-opus-4.7",
"google/gemini-3.1-pro-preview",
"qwen/qwen3-coder-next",
},
httpAPI: true,
},
"qwen-portal": {
ID: "qwen-portal",
DisplayName: "Qwen",
IconSlug: "alibabacloud",
Domain: "qwenlm.ai",
DefaultAPIBase: "https://dashscope.aliyuncs.com/compatible-mode/v1",
CreateAllowed: true,
DefaultModelAllowed: true,
SupportsFetch: true,
Priority: 75,
CommonModels: []string{"qwen3.6-max-preview", "qwen3.6-plus", "qwen3.6-flash", "qwen3-coder-next"},
Aliases: []string{"qwen"},
httpAPI: true,
},
"qwen-intl": {
ID: "qwen-intl",
DisplayName: "Qwen International",
IconSlug: "alibabacloud",
Domain: "alibabacloud.com",
DefaultAPIBase: "https://dashscope-intl.aliyuncs.com/compatible-mode/v1",
CreateAllowed: true,
DefaultModelAllowed: true,
SupportsFetch: true,
Priority: 74,
CommonModels: []string{"qwen3.6-max-preview", "qwen3.6-plus", "qwen3.6-flash", "qwen3-coder-next"},
Aliases: []string{"qwen-international", "dashscope-intl"},
httpAPI: true,
},
"moonshot": {
ID: "moonshot",
DisplayName: "Moonshot",
Domain: "moonshot.ai",
DefaultAPIBase: "https://api.moonshot.cn/v1",
CreateAllowed: true,
DefaultModelAllowed: true,
SupportsFetch: true,
Priority: 70,
CommonModels: []string{
"kimi-k2.5",
"kimi-k2-thinking",
"kimi-k2-thinking-turbo",
"kimi-k2-turbo-preview",
},
httpAPI: true,
},
"volcengine": {
ID: "volcengine",
DisplayName: "Volcengine",
IconSlug: "bytedance",
Domain: "volcengine.com",
DefaultAPIBase: "https://ark.cn-beijing.volces.com/api/v3",
CreateAllowed: true,
DefaultModelAllowed: true,
SupportsFetch: true,
Priority: 69,
CommonModels: []string{
"doubao-seed-1-6-251015",
"doubao-seed-1-6-flash-250828",
"doubao-seed-1-6-thinking",
},
httpAPI: true,
},
"zhipu": {
ID: "zhipu",
DisplayName: "Zhipu AI",
IconSlug: "zhipu",
Domain: "zhipuai.cn",
DefaultAPIBase: "https://open.bigmodel.cn/api/paas/v4",
CreateAllowed: true,
DefaultModelAllowed: true,
SupportsFetch: true,
Priority: 68,
CommonModels: []string{"glm-5", "glm-4.7", "glm-4.5-air", "glm-4-flash-250414"},
Aliases: []string{"glm"},
httpAPI: true,
},
"groq": {
ID: "groq",
DisplayName: "Groq",
IconSlug: "groq",
Domain: "groq.com",
DefaultAPIBase: "https://api.groq.com/openai/v1",
CreateAllowed: true,
DefaultModelAllowed: true,
SupportsFetch: true,
Priority: 65,
CommonModels: []string{
"openai/gpt-oss-120b",
"openai/gpt-oss-20b",
"llama-3.3-70b-versatile",
"qwen/qwen3-32b",
},
httpAPI: true,
},
"mistral": {
ID: "mistral",
DisplayName: "Mistral AI",
IconSlug: "mistralai",
Domain: "mistral.ai",
DefaultAPIBase: "https://api.mistral.ai/v1",
CreateAllowed: true,
DefaultModelAllowed: true,
SupportsFetch: true,
Priority: 64,
CommonModels: []string{
"mistral-large-latest",
"mistral-medium-3-5",
"mistral-small-latest",
"devstral-latest",
},
httpAPI: true,
},
"nvidia": {
ID: "nvidia",
DisplayName: "NVIDIA",
IconSlug: "nvidia",
Domain: "nvidia.com",
DefaultAPIBase: "https://integrate.api.nvidia.com/v1",
CreateAllowed: true,
DefaultModelAllowed: true,
SupportsFetch: true,
Priority: 63,
CommonModels: []string{
"openai/gpt-oss-120b",
"openai/gpt-oss-20b",
"qwen/qwen3-coder-480b-a35b-instruct",
"qwen/qwen3-next-80b-a3b-thinking",
},
httpAPI: true,
},
"cerebras": {
ID: "cerebras",
DisplayName: "Cerebras",
IconSlug: "cerebras",
Domain: "cerebras.ai",
DefaultAPIBase: "https://api.cerebras.ai/v1",
CreateAllowed: true,
DefaultModelAllowed: true,
SupportsFetch: true,
Priority: 62,
CommonModels: []string{"gpt-oss-120b", "zai-glm-4.7"},
httpAPI: true,
},
"azure": {
ID: "azure",
DisplayName: "Azure OpenAI",
IconSlug: "microsoftazure",
Domain: "azure.com",
CreateAllowed: true,
DefaultModelAllowed: true,
Priority: 61,
Aliases: []string{"azure-openai"},
httpAPI: true,
},
"bedrock": {
ID: "bedrock",
DisplayName: "AWS Bedrock",
IconSlug: "amazonwebservices",
Domain: "aws.amazon.com",
EmptyAPIKeyAllowed: true,
CreateAllowed: true,
DefaultModelAllowed: true,
Priority: 60,
},
"github-copilot": {
ID: "github-copilot",
DisplayName: "GitHub Copilot",
IconSlug: "githubcopilot",
Domain: "github.com",
DefaultAPIBase: "localhost:4321",
EmptyAPIKeyAllowed: true,
CreateAllowed: true,
DefaultModelAllowed: true,
Local: true,
Priority: 55,
Aliases: []string{"copilot"},
},
"antigravity": {
ID: "antigravity",
DisplayName: "Google Code Assist",
Domain: "antigravity.google",
EmptyAPIKeyAllowed: true,
CreateAllowed: true,
DefaultModelAllowed: true,
DefaultAuthMethod: "oauth",
AuthMethodLocked: true,
Priority: 54,
Aliases: []string{"google-antigravity"},
},
"claude-cli": {
ID: "claude-cli",
DisplayName: "Claude CLI",
IconSlug: "anthropic",
Domain: "anthropic.com",
EmptyAPIKeyAllowed: true,
CreateAllowed: true,
DefaultModelAllowed: true,
Local: true,
Priority: 53,
Aliases: []string{"claudecli"},
},
"codex-cli": {
ID: "codex-cli",
DisplayName: "Codex CLI",
IconSlug: "openai",
Domain: "openai.com",
EmptyAPIKeyAllowed: true,
CreateAllowed: true,
DefaultModelAllowed: true,
Local: true,
Priority: 52,
Aliases: []string{"codexcli"},
},
"ollama": {
ID: "ollama",
DisplayName: "Ollama",
IconSlug: "ollama",
Domain: "ollama.com",
DefaultAPIBase: "http://localhost:11434/v1",
EmptyAPIKeyAllowed: true,
CreateAllowed: true,
DefaultModelAllowed: true,
SupportsFetch: true,
Local: true,
Priority: 50,
httpAPI: true,
},
"vllm": {
ID: "vllm",
DisplayName: "VLLM",
Domain: "vllm.ai",
DefaultAPIBase: "http://localhost:8000/v1",
EmptyAPIKeyAllowed: true,
CreateAllowed: true,
DefaultModelAllowed: true,
SupportsFetch: true,
Local: true,
Priority: 49,
httpAPI: true,
},
"lmstudio": {
ID: "lmstudio",
DisplayName: "LM Studio",
Domain: "lmstudio.ai",
DefaultAPIBase: "http://localhost:1234/v1",
EmptyAPIKeyAllowed: true,
CreateAllowed: true,
DefaultModelAllowed: true,
SupportsFetch: true,
Local: true,
Priority: 48,
httpAPI: true,
},
"elevenlabs": {
ID: "elevenlabs",
DisplayName: "ElevenLabs ASR",
IconSlug: "elevenlabs",
Domain: "elevenlabs.io",
DefaultAPIBase: "https://api.elevenlabs.io",
CreateAllowed: true,
DefaultModelAllowed: false,
Priority: 47,
httpAPI: true,
},
"venice": {
ID: "venice",
DisplayName: "Venice AI",
IconSlug: "venice",
Domain: "venice.ai",
DefaultAPIBase: "https://api.venice.ai/api/v1",
CreateAllowed: true,
DefaultModelAllowed: true,
SupportsFetch: true,
Priority: 45,
httpAPI: true,
},
"shengsuanyun": {
ID: "shengsuanyun",
DisplayName: "ShengsuanYun",
Domain: "shengsuanyun.com",
DefaultAPIBase: "https://router.shengsuanyun.com/api/v1",
CreateAllowed: true,
DefaultModelAllowed: true,
SupportsFetch: true,
Priority: 44,
httpAPI: true,
},
"siliconflow": {
ID: "siliconflow",
DisplayName: "SiliconFlow",
Domain: "siliconflow.cn",
DefaultAPIBase: "https://api.siliconflow.cn/v1",
CreateAllowed: true,
DefaultModelAllowed: true,
SupportsFetch: true,
Priority: 43.5,
httpAPI: true,
},
"vivgrid": {
ID: "vivgrid",
DisplayName: "Vivgrid",
Domain: "vivgrid.com",
DefaultAPIBase: "https://api.vivgrid.com/v1",
CreateAllowed: true,
DefaultModelAllowed: true,
SupportsFetch: true,
Priority: 43,
httpAPI: true,
},
"minimax": {
ID: "minimax",
DisplayName: "MiniMax",
Domain: "minimaxi.com",
DefaultAPIBase: "https://api.minimaxi.com/v1",
CreateAllowed: true,
DefaultModelAllowed: true,
SupportsFetch: true,
Priority: 42,
httpAPI: true,
},
"longcat": {
ID: "longcat",
DisplayName: "LongCat",
Domain: "longcat.chat",
DefaultAPIBase: "https://api.longcat.chat/openai",
CreateAllowed: true,
DefaultModelAllowed: true,
SupportsFetch: true,
Priority: 41,
httpAPI: true,
},
"modelscope": {
ID: "modelscope",
DisplayName: "ModelScope",
Domain: "modelscope.cn",
DefaultAPIBase: "https://api-inference.modelscope.cn/v1",
CreateAllowed: true,
DefaultModelAllowed: true,
SupportsFetch: true,
Priority: 40,
httpAPI: true,
},
"mimo": {
ID: "mimo",
DisplayName: "Xiaomi MiMo",
IconSlug: "xiaomi",
Domain: "xiaomi.com",
DefaultAPIBase: "https://api.xiaomimimo.com/v1",
CreateAllowed: true,
DefaultModelAllowed: true,
SupportsFetch: true,
Priority: 39,
CommonModels: []string{"mimo-v2.5", "mimo-v2.5-pro"},
httpAPI: true,
},
"avian": {
ID: "avian",
DisplayName: "Avian",
Domain: "avian.io",
DefaultAPIBase: "https://api.avian.io/v1",
CreateAllowed: true,
DefaultModelAllowed: true,
SupportsFetch: true,
Priority: 38,
httpAPI: true,
},
"zai": {
ID: "zai",
DisplayName: "Z.ai",
Domain: "z.ai",
DefaultAPIBase: "https://api.z.ai/api/coding/paas/v4",
CreateAllowed: true,
DefaultModelAllowed: true,
SupportsFetch: true,
Priority: 37,
CommonModels: []string{"glm-5", "glm-4.7", "glm-4.5-air", "glm-4-flash-250414"},
Aliases: []string{"z.ai", "z-ai"},
httpAPI: true,
},
"alibaba-coding": {
ID: "alibaba-coding",
DisplayName: "Alibaba Coding Plan",
IconSlug: "alibabacloud",
Domain: "alibabacloud.com",
DefaultAPIBase: "https://coding-intl.dashscope.aliyuncs.com/v1",
CreateAllowed: true,
DefaultModelAllowed: true,
Priority: 36.5,
CommonModels: []string{"qwen3.6-plus", "kimi-k2.5", "glm-5", "MiniMax-M2.5"},
Aliases: []string{"coding-plan", "qwen-coding"},
httpAPI: true,
},
"alibaba-coding-anthropic": {
ID: "alibaba-coding-anthropic",
DisplayName: "Alibaba Coding Plan (Anthropic)",
IconSlug: "alibabacloud",
Domain: "alibabacloud.com",
DefaultAPIBase: "https://coding-intl.dashscope.aliyuncs.com/apps/anthropic",
CreateAllowed: true,
DefaultModelAllowed: true,
Priority: 36.25,
CommonModels: []string{"qwen3.6-plus", "kimi-k2.5", "glm-5", "MiniMax-M2.5"},
Aliases: []string{"coding-plan-anthropic"},
httpAPI: true,
},
"novita": {
ID: "novita",
DisplayName: "Novita AI",
Domain: "novita.ai",
DefaultAPIBase: "https://api.novita.ai/openai",
CreateAllowed: true,
DefaultModelAllowed: true,
SupportsFetch: true,
Priority: 36,
httpAPI: true,
},
"litellm": {
ID: "litellm",
DisplayName: "LiteLLM",
Domain: "litellm.ai",
DefaultAPIBase: "http://localhost:4000/v1",
CreateAllowed: true,
DefaultModelAllowed: true,
SupportsFetch: true,
Priority: 35,
httpAPI: true,
},
"qwen-us": {
ID: "qwen-us",
DisplayName: "Qwen US",
IconSlug: "alibabacloud",
Domain: "alibabacloud.com",
DefaultAPIBase: "https://dashscope-us.aliyuncs.com/compatible-mode/v1",
CreateAllowed: true,
DefaultModelAllowed: true,
Priority: 34,
CommonModels: []string{"qwen3.6-max-preview", "qwen3.6-plus", "qwen3.6-flash", "qwen3-coder-next"},
Aliases: []string{"dashscope-us"},
httpAPI: true,
},
}
var normalizedModelProviderAliasesByName = buildModelProviderAliasMap()
func buildModelProviderAliasMap() map[string]string {
totalAliases := 0
for _, option := range modelProviderOptionsByName {
totalAliases += len(option.Aliases)
}
aliases := make(map[string]string, len(modelProviderOptionsByName)+totalAliases)
for provider, option := range modelProviderOptionsByName {
aliases[provider] = provider
for _, alias := range option.Aliases {
normalized := strings.ToLower(strings.TrimSpace(alias))
if normalized == "" {
continue
}
aliases[normalized] = provider
}
}
return aliases
}
func modelProviderOptionForName(provider string) (ModelProviderOption, bool) {
normalized := NormalizeProvider(provider)
if normalized == "" {
return ModelProviderOption{}, false
}
option, ok := modelProviderOptionsByName[normalized]
return option, ok
}