mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
1bc7abfb50
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>
583 lines
18 KiB
Go
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
|
|
}
|