Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/1panel-dev_1panel.json
T

1 line
308 KiB
JSON

{"repo": "1panel-dev/1panel", "files": {"agent/app/provider/catalog.go": {"60d16609f7fac966ef45fc15ab11cd387cb6016b": {"t": 1785745649.5753703, "n": 17490, "h": "369ac577a54a00ea", "c": "package provider\n\nimport (\n\t\"fmt\"\n\t\"net/url\"\n\t\"strings\"\n)\n\ntype APIConfig struct {\n\tAPIType string\n\tBaseURL string\n\tEditableBaseURL bool\n\tDiscoverModels bool\n\tDefaultAuthMode string\n\tAuthModes []string\n\tModels []Model\n}\n\nconst (\n\tAuthModeBearer = \"bearer\"\n\tAuthModeXAPIKey = \"x-api-key\"\n)\n\ntype Model struct {\n\tID string\n\tName string\n}\n\ntype Meta struct {\n\tKey string\n\tDisplayName string\n\tDisplayNameKey string\n\tSort uint\n\tDefaultAPIType string\n\tAPIConfigs []APIConfig\n\tEnvKey string\n\tModels []Model\n}\n\nvar catalog = map[string]Meta{\n\t\"custom\": {\n\t\tKey: \"custom\", DisplayName: \"Custom\", Sort: 10, DefaultAPIType: \"openai-completions\", EnvKey: \"CUSTOM_API_KEY\",\n\t\tAPIConfigs: editableAPIConfigs(true, \"openai-completions\", \"openai-responses\", \"anthropic-messages\", \"openai-images\", \"dashscope-images\", \"minimax-images\", \"openrouter-images\"),\n\t},\n\t\"ollama\": {\n\t\tKey: \"ollama\", DisplayName: \"Ollama\", Sort: 15, DefaultAPIType: \"openai-responses\",\n\t\tAPIConfigs: editableAPIConfigs(false, \"openai-responses\", \"openai-completions\"),\n\t},\n\t\"vllm\": {\n\t\tKey: \"vllm\", DisplayName: \"vLLM\", Sort: 20, DefaultAPIType: \"openai-completions\", EnvKey: \"VLLM_API_KEY\",\n\t\tAPIConfigs: editableAPIConfigs(false, \"openai-completions\", \"openai-responses\", \"anthropic-messages\", \"openai-images\"),\n\t},\n\t\"deepseek\": {\n\t\tKey: \"deepseek\", DisplayName: \"DeepSeek\", Sort: 25, DefaultAPIType: \"openai-completions\", EnvKey: \"DEEPSEEK_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://api.deepseek.com/v1\"},\n\t\t\tanthropicAPIConfig(\"https://api.deepseek.com/anthropic\", AuthModeXAPIKey),\n\t\t},\n\t\tModels: []Model{{ID: \"deepseek-v4-flash\", Name: \"deepseek-v4-flash\"}, {ID: \"deepseek-v4-pro\", Name: \"deepseek-v4-pro\"}},\n\t},\n\t\"bailian-coding-plan\": {\n\t\tKey: \"bailian-coding-plan\", DisplayNameKey: \"AIProviderBailianCodingPlan\", Sort: 30, DefaultAPIType: \"openai-completions\", EnvKey: \"QWEN_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://coding.dashscope.aliyuncs.com/v1\"},\n\t\t\tanthropicAPIConfig(\"https://coding.dashscope.aliyuncs.com/apps/anthropic\", AuthModeBearer),\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"qwen3-coder-plus\", Name: \"Qwen3-Coder-Plus\"},\n\t\t\t{ID: \"qwen3-max-2026-01-23\", Name: \"Qwen3-Max-2026-01-23\"},\n\t\t\t{ID: \"qwen3-coder-next\", Name: \"Qwen3-Coder-Next\"},\n\t\t\t{ID: \"glm-4.7\", Name: \"GLM-4.7\"},\n\t\t\t{ID: \"kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"qwen3.5-plus\", Name: \"Qwen3.5-Plus\"},\n\t\t\t{ID: \"glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"MiniMax-M2.5\", Name: \"MiniMax M2.5\"},\n\t\t\t{ID: \"qwen3.6-plus\", Name: \"Qwen3.6-Plus\"},\n\t\t\t{ID: \"qwen3.7-plus\", Name: \"Qwen3.7-Plus\"},\n\t\t},\n\t},\n\t\"ark-coding-plan\": {\n\t\tKey: \"ark-coding-plan\", DisplayNameKey: \"AIProviderArkCodingPlan\", Sort: 35, DefaultAPIType: \"openai-completions\", EnvKey: \"ARK_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://ark.cn-beijing.volces.com/api/coding/v3\"},\n\t\t\tanthropicAPIConfig(\"https://ark.cn-beijing.volces.com/api/coding\", AuthModeBearer),\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"ark-code-latest\", Name: \"Ark Coding Plan\"}, {ID: \"doubao-seed-code\", Name: \"Doubao Seed Code\"},\n\t\t\t{ID: \"glm-4.7\", Name: \"GLM 4.7 Coding\"}, {ID: \"kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t\t{ID: \"kimi-k2.5\", Name: \"Kimi K2.5 Coding\"}, {ID: \"doubao-seed-code-preview-251028\", Name: \"Doubao Seed Code Preview\"},\n\t\t},\n\t},\n\t\"zai\": {\n\t\tKey: \"zai\", DisplayName: \"Z.ai\", Sort: 40, DefaultAPIType: \"openai-completions\", EnvKey: \"ZAI_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://open.bigmodel.cn/api/paas/v4\", EditableBaseURL: true},\n\t\t\t{APIType: \"openai-images\", BaseURL: \"https://open.bigmodel.cn/api/paas/v4\", EditableBaseURL: true},\n\t\t},\n\t\tModels: []Model{{ID: \"glm-5\", Name: \"GLM-5\"}, {ID: \"glm-4.7\", Name: \"GLM-4.7\"}, {ID: \"glm-4.7-flash\", Name: \"GLM-4.7-Flash\"}, {ID: \"glm-4.7-flashx\", Name: \"GLM-4.7-FlashX\"}},\n\t},\n\t\"minimax\": {\n\t\tKey: \"minimax\", DisplayName: \"MiniMax (CN)\", Sort: 45, DefaultAPIType: \"anthropic-messages\", EnvKey: \"MINIMAX_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\tanthropicAPIConfig(\"https://api.minimaxi.com/anthropic\", AuthModeXAPIKey, AuthModeBearer),\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://api.minimaxi.com/v1\"},\n\t\t\t{APIType: \"minimax-images\", BaseURL: \"https://api.minimaxi.com\"},\n\t\t},\n\t\tModels: []Model{{ID: \"MiniMax-M3\", Name: \"MiniMax M3\"}, {ID: \"MiniMax-M2.7\", Name: \"MiniMax M2.7\"}, {ID: \"MiniMax-M2.7-highspeed\", Name: \"MiniMax M2.7 highspeed\"}},\n\t},\n\t\"xiaomi\": {\n\t\tKey: \"xiaomi\", DisplayName: \"Xiaomi\", Sort: 46, DefaultAPIType: \"openai-completions\", EnvKey: \"XIAOMI_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://api.xiaomimimo.com/v1\"},\n\t\t\t{APIType: \"openai-responses\", BaseURL: \"https://api.xiaomimimo.com/v1\"},\n\t\t\tanthropicAPIConfig(\"https://api.xiaomimimo.com/anthropic\", AuthModeBearer),\n\t\t},\n\t\tModels: []Model{{ID: \"mimo-v2.5\", Name: \"Xiaomi MiMo V2.5\"}, {ID: \"mimo-v2.5-pro\", Name: \"Xiaomi MiMo V2.5 Pro\"}},\n\t},\n\t\"kimi\": {\n\t\tKey: \"kimi\", DisplayName: \"Kimi (CN)\", Sort: 50, DefaultAPIType: \"openai-completions\", EnvKey: \"KIMI_API_KEY\",\n\t\tAPIConfigs: []APIConfig{{APIType: \"openai-completions\", BaseURL: \"https://api.moonshot.cn/v1\"}},\n\t\tModels: []Model{{ID: \"kimi-k2.5\", Name: \"Kimi K2.5\"}, {ID: \"kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"}, {ID: \"kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"}},\n\t},\n\t\"kimi-coding\": {\n\t\tKey: \"kimi-coding\", DisplayName: \"Kimi Coding\", Sort: 51, DefaultAPIType: \"anthropic-messages\", EnvKey: \"KIMI_API_KEY\",\n\t\tAPIConfigs: []APIConfig{anthropicAPIConfig(\"https://api.kimi.com/coding/\", AuthModeXAPIKey)},\n\t\tModels: []Model{{ID: \"kimi-code\", Name: \"Kimi Code\"}, {ID: \"k2p5\", Name: \"Kimi K2.5\"}},\n\t},\n\t\"openai\": {\n\t\tKey: \"openai\", DisplayName: \"OpenAI\", Sort: 55, DefaultAPIType: \"openai-responses\", EnvKey: \"OPENAI_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{APIType: \"openai-responses\", BaseURL: \"https://api.openai.com/v1\"},\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://api.openai.com/v1\"},\n\t\t\t{APIType: \"openai-images\", BaseURL: \"https://api.openai.com/v1\"},\n\t\t},\n\t\tModels: []Model{{ID: \"gpt-5.4\", Name: \"gpt-5.4\"}, {ID: \"gpt-5.4-pro\", Name: \"gpt-5.4-pro\"}, {ID: \"gpt-5.4-mini\", Name: \"gpt-5.4-mini\"}, {ID: \"gpt-5.4-nano\", Name: \"gpt-5.4-nano\"}},\n\t},\n\t\"openrouter\": {\n\t\tKey: \"openrouter\", DisplayName: \"OpenRouter\", Sort: 56, DefaultAPIType: \"openai-completions\", EnvKey: \"OPENROUTER_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://openrouter.ai/api/v1\"},\n\t\t\t{APIType: \"openrouter-images\", BaseURL: \"https://openrouter.ai\"},\n\t\t},\n\t\tModels: []Model{{ID: \"openrouter/free\", Name: \"openrouter/free\"}, {ID: \"openrouter/auto\", Name: \"openrouter/auto\"}},\n\t},\n\t\"anthropic\": {\n\t\tKey: \"anthropic\", DisplayName: \"Anthropic\", Sort: 60, DefaultAPIType: \"anthropic-messages\", EnvKey: \"ANTHROPIC_API_KEY\",\n\t\tAPIConfigs: []APIConfig{anthropicAPIConfig(\"https://api.anthropic.com\", AuthModeXAPIKey)},\n\t\tModels: []Model{{ID: \"claude-sonnet-4-6\", Name: \"Claude Sonnet 4.6\"}, {ID: \"claude-opus-4-6\", Name: \"Claude Opus 4.6\"}, {ID: \"claude-opus-4-5\", Name: \"Claude Opus 4.5\"}, {ID: \"claude-sonnet-4-5\", Name: \"Claude Sonnet 4.5\"}, {ID: \"claude-haiku-4-5\", Name: \"Claude Haiku 4.5\"}},\n\t},\n\t\"gemini\": {\n\t\tKey: \"gemini\", DisplayName: \"Gemini\", Sort: 65, DefaultAPIType: \"gemini-generate-content\", EnvKey: \"GEMINI_API_KEY\",\n\t\tAPIConfigs: []APIConfig{{APIType: \"gemini-generate-content\", BaseURL: \"https://generativelanguage.googleapis.com\"}},\n\t\tModels: []Model{{ID: \"gemini-3-flash-preview\", Name: \"Gemini 3 Flash Preview\"}, {ID: \"gemini-flash-latest\", Name: \"Gemini Flash Latest\"}, {ID: \"gemini-3-pro-preview\", Name: \"Gemini 3 Pro Preview\"}},\n\t},\n\t\"moonshot\": {\n\t\tKey: \"moonshot\", DisplayName: \"Moonshot (Global)\", Sort: 70, DefaultAPIType: \"openai-completions\", EnvKey: \"MOONSHOT_API_KEY\",\n\t\tAPIConfigs: []APIConfig{{APIType: \"openai-completions\", BaseURL: \"https://api.moonshot.ai/v1\"}},\n\t\tModels: []Model{{ID: \"kimi-k2.5\", Name: \"Kimi K2.5\"}, {ID: \"kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"}, {ID: \"kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"}},\n\t},\n\t\"bailian\": {\n\t\tKey: \"bailian\", DisplayNameKey: \"AIProviderBailian\", Sort: 31, DefaultAPIType: \"openai-completions\", EnvKey: \"DASHSCOPE_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{\n\t\t\t\tAPIType: \"openai-completions\", BaseURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n\t\t\t\tDiscoverModels: true,\n\t\t\t\tModels: []Model{{ID: \"qwen3.7-plus\", Name: \"qwen3.7-plus\"}, {ID: \"qwen3.6-plus\", Name: \"qwen3.6-plus\"}, {ID: \"qwen3.6-flash\", Name: \"qwen3.6-flash\"}},\n\t\t\t},\n\t\t\t{\n\t\t\t\tAPIType: \"openai-responses\", BaseURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n\t\t\t\tDiscoverModels: true,\n\t\t\t\tModels: []Model{{ID: \"qwen3.7-plus\", Name: \"qwen3.7-plus\"}, {ID: \"qwen3.6-plus\", Name: \"qwen3.6-plus\"}, {ID: \"qwen3.6-flash\", Name: \"qwen3.6-flash\"}},\n\t\t\t},\n\t\t\t{\n\t\t\t\tAPIType: \"anthropic-messages\", BaseURL: \"https://dashscope.aliyuncs.com/apps/anthropic\",\n\t\t\t\tDefaultAuthMode: AuthModeBearer,\n\t\t\t\tAuthModes: []string{AuthModeBearer},\n\t\t\t\tModels: []Model{{ID: \"qwen3.7-plus\", Name: \"qwen3.7-plus\"}, {ID: \"qwen3.6-plus\", Name: \"qwen3.6-plus\"}, {ID: \"qwen3.6-flash\", Name: \"qwen3.6-flash\"}},\n\t\t\t},\n\t\t\t{\n\t\t\t\tAPIType: \"dashscope-images\", BaseURL: \"https://dashscope.aliyuncs.com\",\n\t\t\t\tModels: []Model{\n\t\t\t\t\t{ID: \"qwen-image-2.0-pro\", Name: \"qwen-image-2.0-pro\"},\n\t\t\t\t\t{ID: \"qwen-image-2.0\", Name: \"qwen-image-2.0\"},\n\t\t\t\t\t{ID: \"wan2.7-image-pro\", Name: \"wan2.7-image-pro\"},\n\t\t\t\t\t{ID: \"wan2.7-image\", Name: \"wan2.7-image\"},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n\t\"ark\": {\n\t\tKey: \"ark\", DisplayNameKey: \"AIProviderArk\", Sort: 36, DefaultAPIType: \"openai-completions\", EnvKey: \"ARK_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{\n\t\t\t\tAPIType: \"openai-completions\", BaseURL: \"https://ark.cn-beijing.volces.com/api/v3\",\n\t\t\t\tDiscoverModels: true,\n\t\t\t\tModels: []Model{{ID: \"doubao-seed-2-0-pro-260215\", Name: \"doubao-seed-2-0-pro-260215\"}, {ID: \"doubao-seed-2-0-lite-260215\", Name: \"doubao-seed-2-0-lite-260215\"}},\n\t\t\t},\n\t\t\t{\n\t\t\t\tAPIType: \"openai-responses\", BaseURL: \"https://ark.cn-beijing.volces.com/api/v3\",\n\t\t\t\tDiscoverModels: true,\n\t\t\t\tModels: []Model{{ID: \"doubao-seed-2-0-pro-260215\", Name: \"doubao-seed-2-0-pro-260215\"}, {ID: \"doubao-seed-2-0-lite-260215\", Name: \"doubao-seed-2-0-lite-260215\"}},\n\t\t\t},\n\t\t\t{\n\t\t\t\tAPIType: \"openai-images\", BaseURL: \"https://ark.cn-beijing.volces.com/api/v3\",\n\t\t\t\tModels: []Model{\n\t\t\t\t\t{ID: \"doubao-seedream-5-0-260128\", Name: \"doubao-seedream-5-0-260128\"},\n\t\t\t\t\t{ID: \"doubao-seedream-5-0-lite-260128\", Name: \"doubao-seedream-5-0-lite-260128\"},\n\t\t\t\t\t{ID: \"doubao-seedream-4-5-251128\", Name: \"doubao-seedream-4-5-251128\"},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n}\n\nfunc editableAPIConfigs(discoverModels bool, apiTypes ...string) []APIConfig {\n\tconfigs := make([]APIConfig, 0, len(apiTypes))\n\tfor _, apiType := range apiTypes {\n\t\tif apiType == \"anthropic-messages\" {\n\t\t\tconfig := anthropicAPIConfig(\"\", AuthModeXAPIKey, AuthModeBearer)\n\t\t\tconfig.EditableBaseURL = true\n\t\t\tconfigs = append(configs, config)\n\t\t\tcontinue\n\t\t}\n\t\tconfigs = append(configs, APIConfig{\n\t\t\tAPIType: apiType,\n\t\t\tEditableBaseURL: true,\n\t\t\tDiscoverModels: discoverModels && (apiType == \"openai-completions\" || apiType == \"openai-responses\"),\n\t\t})\n\t}\n\treturn configs\n}\n\nfunc anthropicAPIConfig(baseURL, defaultAuthMode string, additionalAuthModes ...string) APIConfig {\n\tauthModes := []string{defaultAuthMode}\n\tfor _, authMode := range additionalAuthModes {\n\t\tif authMode != defaultAuthMode {\n\t\t\tauthModes = append(authModes, authMode)\n\t\t}\n\t}\n\treturn APIConfig{\n\t\tAPIType: \"anthropic-messages\",\n\t\tBaseURL: baseURL,\n\t\tDefaultAuthMode: defaultAuthMode,\n\t\tAuthModes: authModes,\n\t}\n}\n\nfunc Get(key string) (Meta, bool) {\n\tmeta, ok := catalog[key]\n\tif !ok {\n\t\treturn Meta{}, false\n\t}\n\treturn cloneMeta(meta), true\n}\n\nfunc All() map[string]Meta {\n\tresult := make(map[string]Meta, len(catalog))\n\tfor key, meta := range catalog {\n\t\tresult[key] = cloneMeta(meta)\n\t}\n\treturn result\n}\n\nfunc FindAPIConfig(key, apiType string) (APIConfig, bool) {\n\tmeta, ok := catalog[key]\n\tif !ok {\n\t\treturn APIConfig{}, false\n\t}\n\ttarget := strings.TrimSpace(apiType)\n\tif target == \"\" {\n\t\ttarget = meta.DefaultAPIType\n\t}\n\tfor _, config := range meta.APIConfigs {\n\t\tif config.APIType == target {\n\t\t\tconfig.AuthModes = append([]string(nil), config.AuthModes...)\n\t\t\tconfig.Models = append([]Model(nil), config.Models...)\n\t\t\treturn config, true\n\t\t}\n\t}\n\treturn APIConfig{}, false\n}\n\nfunc DefaultModels(key, apiType string) []Model {\n\tmeta, ok := catalog[key]\n\tif !ok {\n\t\treturn nil\n\t}\n\ttarget := strings.TrimSpace(apiType)\n\tif target == \"\" {\n\t\ttarget = meta.DefaultAPIType\n\t}\n\tfor _, config := range meta.APIConfigs {\n\t\tif config.APIType != target {\n\t\t\tcontinue\n\t\t}\n\t\tif len(config.Models) > 0 {\n\t\t\treturn append([]Model(nil), config.Models...)\n\t\t}\n\t\tif IsImageAPIType(config.APIType) {\n\t\t\treturn nil\n\t\t}\n\t\tbreak\n\t}\n\treturn append([]Model(nil), meta.Models...)\n}\n\nfunc ResolveAuthMode(provider, apiType, requested string) (string, error) {\n\tconfig, ok := FindAPIConfig(provider, apiType)\n\tif !ok {\n\t\treturn \"\", fmt.Errorf(\"provider %s does not support api type %s\", provider, apiType)\n\t}\n\tif config.APIType != \"anthropic-messages\" {\n\t\treturn \"\", nil\n\t}\n\tauthMode := strings.TrimSpace(requested)\n\tif authMode == \"\" {\n\t\tauthMode = config.DefaultAuthMode\n\t}\n\tfor _, allowed := range config.AuthModes {\n\t\tif authMode == allowed {\n\t\t\treturn authMode, nil\n\t\t}\n\t}\n\treturn \"\", fmt.Errorf(\"provider %s does not support auth mode %s\", provider, authMode)\n}\n\nfunc DefaultBaseURL(key string) (string, bool) {\n\tconfig, ok := FindAPIConfig(key, \"\")\n\tif !ok || strings.TrimSpace(config.BaseURL) == \"\" {\n\t\treturn \"\", false\n\t}\n\treturn config.BaseURL, true\n}\n\nfunc DefaultAPIType(key string) string {\n\tmeta, ok := catalog[key]\n\tif !ok || strings.TrimSpace(meta.DefaultAPIType) == \"\" {\n\t\treturn \"openai-completions\"\n\t}\n\treturn meta.DefaultAPIType\n}\n\nfunc ResolveBaseURL(key, apiType, requested string) (string, error) {\n\tconfig, ok := FindAPIConfig(key, apiType)\n\tif !ok {\n\t\treturn \"\", fmt.Errorf(\"provider %s does not support api type %s\", key, apiType)\n\t}\n\tif !config.EditableBaseURL {\n\t\treturn strings.TrimRight(config.BaseURL, \"/\"), nil\n\t}\n\tbaseURL := strings.TrimSpace(requested)\n\tif baseURL == \"\" {\n\t\tbaseURL = config.BaseURL\n\t}\n\tif baseURL == \"\" {\n\t\treturn \"\", fmt.Errorf(\"base url is required\")\n\t}\n\tparsed, err := url.Parse(baseURL)\n\tif err != nil || parsed.Scheme == \"\" || parsed.Host == \"\" {\n\t\treturn \"\", fmt.Errorf(\"invalid base url\")\n\t}\n\tif key == \"custom\" && IsImageAPIType(config.APIType) {\n\t\treturn baseURL, nil\n\t}\n\tparsed.Path = normalizeEndpointPath(config.APIType, parsed.Path)\n\tparsed.RawQuery = \"\"\n\tparsed.Fragment = \"\"\n\treturn strings.TrimRight(parsed.String(), \"/\"), nil\n}\n\nfunc normalizeEndpointPath(apiType, value string) string {\n\tif IsImageAPIType(apiType) {\n\t\treturn strings.TrimRight(value, \"/\")\n\t}\n\tpath := strings.TrimRight(value, \"/\")\n\tsuffixes := []string{}\n\tswitch apiType {\n\tcase \"openai-completions\":\n\t\tsuffixes = []string{\"/chat/completions\"}\n\tcase \"openai-responses\":\n\t\tsuffixes = []string{\"/responses\"}\n\tcase \"anthropic-messages\":\n\t\tsuffixes = []string{\"/v1/messages\", \"/messages\"}\n\t}\n\tfor _, suffix := range suffixes {\n\t\tif strings.HasSuffix(strings.ToLower(path), suffix) {\n\t\t\treturn path[:len(path)-len(suffix)]\n\t\t}\n\t}\n\treturn path\n}\n\nfunc IsImageAPIType(apiType string) bool {\n\tswitch apiType {\n\tcase \"openai-images\", \"dashscope-images\", \"minimax-images\", \"openrouter-images\":\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n\nfunc EnvKey(key string) string {\n\tmeta, ok := catalog[key]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.EnvKey\n}\n\nfunc DisplayName(key string) string {\n\tmeta, ok := catalog[key]\n\tif !ok || strings.TrimSpace(meta.DisplayName) == \"\" {\n\t\treturn key\n\t}\n\treturn meta.DisplayName\n}\n\nfunc DisplayNameKey(key string) string {\n\tmeta, ok := catalog[key]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.DisplayNameKey\n}\n\nfunc NormalizeModelID(provider, modelID string) string {\n\ttarget := strings.TrimLeft(strings.TrimSpace(modelID), \"/\")\n\tfor _, prefix := range legacyModelPrefixes[provider] {\n\t\tlegacyPrefix := prefix + \"/\"\n\t\tif !strings.HasPrefix(target, legacyPrefix) {\n\t\t\tcontinue\n\t\t}\n\t\tcandidate := strings.TrimSpace(strings.TrimPrefix(target, legacyPrefix))\n\t\tif candidate != \"\" {\n\t\t\treturn candidate\n\t\t}\n\t}\n\treturn target\n}\n\nvar legacyModelPrefixes = map[string][]string{\n\t\"custom\": {\"custom\"},\n\t\"vllm\": {\"custom\"},\n\t\"ollama\": {\"ollama\"},\n\t\"deepseek\": {\"deepseek\"},\n\t\"bailian-coding-plan\": {\"bailian-coding-plan\"},\n\t\"ark-coding-plan\": {\"ark-coding-plan\"},\n\t\"zai\": {\"zai\"},\n\t\"minimax\": {\"minimax\"},\n\t\"xiaomi\": {\"xiaomi\"},\n\t\"kimi\": {\"kimi\", \"moonshot\"},\n\t\"kimi-coding\": {\"kimi-coding\"},\n\t\"openai\": {\"openai\"},\n\t\"anthropic\": {\"anthropic\"},\n\t\"gemini\": {\"google\", \"gemini\"},\n\t\"moonshot\": {\"moonshot\"},\n}\n\nfunc cloneMeta(meta Meta) Meta {\n\tclone := meta\n\tclone.APIConfigs = make([]APIConfig, len(meta.APIConfigs))\n\tfor index, config := range meta.APIConfigs {\n\t\tclone.APIConfigs[index] = config\n\t\tclone.APIConfigs[index].AuthModes = append([]string(nil), config.AuthModes...)\n\t\tclone.APIConfigs[index].Models = append([]Model(nil), config.Models...)\n\t}\n\tclone.Models = append([]Model(nil), meta.Models...)\n\treturn clone\n}\n"}, "02ca9347dcdd86addf50b425d68a13c162bb9edf": {"t": 1785755370.3393428, "n": 17490, "h": "369ac577a54a00ea", "c": "package provider\n\nimport (\n\t\"fmt\"\n\t\"net/url\"\n\t\"strings\"\n)\n\ntype APIConfig struct {\n\tAPIType string\n\tBaseURL string\n\tEditableBaseURL bool\n\tDiscoverModels bool\n\tDefaultAuthMode string\n\tAuthModes []string\n\tModels []Model\n}\n\nconst (\n\tAuthModeBearer = \"bearer\"\n\tAuthModeXAPIKey = \"x-api-key\"\n)\n\ntype Model struct {\n\tID string\n\tName string\n}\n\ntype Meta struct {\n\tKey string\n\tDisplayName string\n\tDisplayNameKey string\n\tSort uint\n\tDefaultAPIType string\n\tAPIConfigs []APIConfig\n\tEnvKey string\n\tModels []Model\n}\n\nvar catalog = map[string]Meta{\n\t\"custom\": {\n\t\tKey: \"custom\", DisplayName: \"Custom\", Sort: 10, DefaultAPIType: \"openai-completions\", EnvKey: \"CUSTOM_API_KEY\",\n\t\tAPIConfigs: editableAPIConfigs(true, \"openai-completions\", \"openai-responses\", \"anthropic-messages\", \"openai-images\", \"dashscope-images\", \"minimax-images\", \"openrouter-images\"),\n\t},\n\t\"ollama\": {\n\t\tKey: \"ollama\", DisplayName: \"Ollama\", Sort: 15, DefaultAPIType: \"openai-responses\",\n\t\tAPIConfigs: editableAPIConfigs(false, \"openai-responses\", \"openai-completions\"),\n\t},\n\t\"vllm\": {\n\t\tKey: \"vllm\", DisplayName: \"vLLM\", Sort: 20, DefaultAPIType: \"openai-completions\", EnvKey: \"VLLM_API_KEY\",\n\t\tAPIConfigs: editableAPIConfigs(false, \"openai-completions\", \"openai-responses\", \"anthropic-messages\", \"openai-images\"),\n\t},\n\t\"deepseek\": {\n\t\tKey: \"deepseek\", DisplayName: \"DeepSeek\", Sort: 25, DefaultAPIType: \"openai-completions\", EnvKey: \"DEEPSEEK_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://api.deepseek.com/v1\"},\n\t\t\tanthropicAPIConfig(\"https://api.deepseek.com/anthropic\", AuthModeXAPIKey),\n\t\t},\n\t\tModels: []Model{{ID: \"deepseek-v4-flash\", Name: \"deepseek-v4-flash\"}, {ID: \"deepseek-v4-pro\", Name: \"deepseek-v4-pro\"}},\n\t},\n\t\"bailian-coding-plan\": {\n\t\tKey: \"bailian-coding-plan\", DisplayNameKey: \"AIProviderBailianCodingPlan\", Sort: 30, DefaultAPIType: \"openai-completions\", EnvKey: \"QWEN_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://coding.dashscope.aliyuncs.com/v1\"},\n\t\t\tanthropicAPIConfig(\"https://coding.dashscope.aliyuncs.com/apps/anthropic\", AuthModeBearer),\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"qwen3-coder-plus\", Name: \"Qwen3-Coder-Plus\"},\n\t\t\t{ID: \"qwen3-max-2026-01-23\", Name: \"Qwen3-Max-2026-01-23\"},\n\t\t\t{ID: \"qwen3-coder-next\", Name: \"Qwen3-Coder-Next\"},\n\t\t\t{ID: \"glm-4.7\", Name: \"GLM-4.7\"},\n\t\t\t{ID: \"kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"qwen3.5-plus\", Name: \"Qwen3.5-Plus\"},\n\t\t\t{ID: \"glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"MiniMax-M2.5\", Name: \"MiniMax M2.5\"},\n\t\t\t{ID: \"qwen3.6-plus\", Name: \"Qwen3.6-Plus\"},\n\t\t\t{ID: \"qwen3.7-plus\", Name: \"Qwen3.7-Plus\"},\n\t\t},\n\t},\n\t\"ark-coding-plan\": {\n\t\tKey: \"ark-coding-plan\", DisplayNameKey: \"AIProviderArkCodingPlan\", Sort: 35, DefaultAPIType: \"openai-completions\", EnvKey: \"ARK_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://ark.cn-beijing.volces.com/api/coding/v3\"},\n\t\t\tanthropicAPIConfig(\"https://ark.cn-beijing.volces.com/api/coding\", AuthModeBearer),\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"ark-code-latest\", Name: \"Ark Coding Plan\"}, {ID: \"doubao-seed-code\", Name: \"Doubao Seed Code\"},\n\t\t\t{ID: \"glm-4.7\", Name: \"GLM 4.7 Coding\"}, {ID: \"kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t\t{ID: \"kimi-k2.5\", Name: \"Kimi K2.5 Coding\"}, {ID: \"doubao-seed-code-preview-251028\", Name: \"Doubao Seed Code Preview\"},\n\t\t},\n\t},\n\t\"zai\": {\n\t\tKey: \"zai\", DisplayName: \"Z.ai\", Sort: 40, DefaultAPIType: \"openai-completions\", EnvKey: \"ZAI_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://open.bigmodel.cn/api/paas/v4\", EditableBaseURL: true},\n\t\t\t{APIType: \"openai-images\", BaseURL: \"https://open.bigmodel.cn/api/paas/v4\", EditableBaseURL: true},\n\t\t},\n\t\tModels: []Model{{ID: \"glm-5\", Name: \"GLM-5\"}, {ID: \"glm-4.7\", Name: \"GLM-4.7\"}, {ID: \"glm-4.7-flash\", Name: \"GLM-4.7-Flash\"}, {ID: \"glm-4.7-flashx\", Name: \"GLM-4.7-FlashX\"}},\n\t},\n\t\"minimax\": {\n\t\tKey: \"minimax\", DisplayName: \"MiniMax (CN)\", Sort: 45, DefaultAPIType: \"anthropic-messages\", EnvKey: \"MINIMAX_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\tanthropicAPIConfig(\"https://api.minimaxi.com/anthropic\", AuthModeXAPIKey, AuthModeBearer),\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://api.minimaxi.com/v1\"},\n\t\t\t{APIType: \"minimax-images\", BaseURL: \"https://api.minimaxi.com\"},\n\t\t},\n\t\tModels: []Model{{ID: \"MiniMax-M3\", Name: \"MiniMax M3\"}, {ID: \"MiniMax-M2.7\", Name: \"MiniMax M2.7\"}, {ID: \"MiniMax-M2.7-highspeed\", Name: \"MiniMax M2.7 highspeed\"}},\n\t},\n\t\"xiaomi\": {\n\t\tKey: \"xiaomi\", DisplayName: \"Xiaomi\", Sort: 46, DefaultAPIType: \"openai-completions\", EnvKey: \"XIAOMI_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://api.xiaomimimo.com/v1\"},\n\t\t\t{APIType: \"openai-responses\", BaseURL: \"https://api.xiaomimimo.com/v1\"},\n\t\t\tanthropicAPIConfig(\"https://api.xiaomimimo.com/anthropic\", AuthModeBearer),\n\t\t},\n\t\tModels: []Model{{ID: \"mimo-v2.5\", Name: \"Xiaomi MiMo V2.5\"}, {ID: \"mimo-v2.5-pro\", Name: \"Xiaomi MiMo V2.5 Pro\"}},\n\t},\n\t\"kimi\": {\n\t\tKey: \"kimi\", DisplayName: \"Kimi (CN)\", Sort: 50, DefaultAPIType: \"openai-completions\", EnvKey: \"KIMI_API_KEY\",\n\t\tAPIConfigs: []APIConfig{{APIType: \"openai-completions\", BaseURL: \"https://api.moonshot.cn/v1\"}},\n\t\tModels: []Model{{ID: \"kimi-k2.5\", Name: \"Kimi K2.5\"}, {ID: \"kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"}, {ID: \"kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"}},\n\t},\n\t\"kimi-coding\": {\n\t\tKey: \"kimi-coding\", DisplayName: \"Kimi Coding\", Sort: 51, DefaultAPIType: \"anthropic-messages\", EnvKey: \"KIMI_API_KEY\",\n\t\tAPIConfigs: []APIConfig{anthropicAPIConfig(\"https://api.kimi.com/coding/\", AuthModeXAPIKey)},\n\t\tModels: []Model{{ID: \"kimi-code\", Name: \"Kimi Code\"}, {ID: \"k2p5\", Name: \"Kimi K2.5\"}},\n\t},\n\t\"openai\": {\n\t\tKey: \"openai\", DisplayName: \"OpenAI\", Sort: 55, DefaultAPIType: \"openai-responses\", EnvKey: \"OPENAI_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{APIType: \"openai-responses\", BaseURL: \"https://api.openai.com/v1\"},\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://api.openai.com/v1\"},\n\t\t\t{APIType: \"openai-images\", BaseURL: \"https://api.openai.com/v1\"},\n\t\t},\n\t\tModels: []Model{{ID: \"gpt-5.4\", Name: \"gpt-5.4\"}, {ID: \"gpt-5.4-pro\", Name: \"gpt-5.4-pro\"}, {ID: \"gpt-5.4-mini\", Name: \"gpt-5.4-mini\"}, {ID: \"gpt-5.4-nano\", Name: \"gpt-5.4-nano\"}},\n\t},\n\t\"openrouter\": {\n\t\tKey: \"openrouter\", DisplayName: \"OpenRouter\", Sort: 56, DefaultAPIType: \"openai-completions\", EnvKey: \"OPENROUTER_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://openrouter.ai/api/v1\"},\n\t\t\t{APIType: \"openrouter-images\", BaseURL: \"https://openrouter.ai\"},\n\t\t},\n\t\tModels: []Model{{ID: \"openrouter/free\", Name: \"openrouter/free\"}, {ID: \"openrouter/auto\", Name: \"openrouter/auto\"}},\n\t},\n\t\"anthropic\": {\n\t\tKey: \"anthropic\", DisplayName: \"Anthropic\", Sort: 60, DefaultAPIType: \"anthropic-messages\", EnvKey: \"ANTHROPIC_API_KEY\",\n\t\tAPIConfigs: []APIConfig{anthropicAPIConfig(\"https://api.anthropic.com\", AuthModeXAPIKey)},\n\t\tModels: []Model{{ID: \"claude-sonnet-4-6\", Name: \"Claude Sonnet 4.6\"}, {ID: \"claude-opus-4-6\", Name: \"Claude Opus 4.6\"}, {ID: \"claude-opus-4-5\", Name: \"Claude Opus 4.5\"}, {ID: \"claude-sonnet-4-5\", Name: \"Claude Sonnet 4.5\"}, {ID: \"claude-haiku-4-5\", Name: \"Claude Haiku 4.5\"}},\n\t},\n\t\"gemini\": {\n\t\tKey: \"gemini\", DisplayName: \"Gemini\", Sort: 65, DefaultAPIType: \"gemini-generate-content\", EnvKey: \"GEMINI_API_KEY\",\n\t\tAPIConfigs: []APIConfig{{APIType: \"gemini-generate-content\", BaseURL: \"https://generativelanguage.googleapis.com\"}},\n\t\tModels: []Model{{ID: \"gemini-3-flash-preview\", Name: \"Gemini 3 Flash Preview\"}, {ID: \"gemini-flash-latest\", Name: \"Gemini Flash Latest\"}, {ID: \"gemini-3-pro-preview\", Name: \"Gemini 3 Pro Preview\"}},\n\t},\n\t\"moonshot\": {\n\t\tKey: \"moonshot\", DisplayName: \"Moonshot (Global)\", Sort: 70, DefaultAPIType: \"openai-completions\", EnvKey: \"MOONSHOT_API_KEY\",\n\t\tAPIConfigs: []APIConfig{{APIType: \"openai-completions\", BaseURL: \"https://api.moonshot.ai/v1\"}},\n\t\tModels: []Model{{ID: \"kimi-k2.5\", Name: \"Kimi K2.5\"}, {ID: \"kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"}, {ID: \"kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"}},\n\t},\n\t\"bailian\": {\n\t\tKey: \"bailian\", DisplayNameKey: \"AIProviderBailian\", Sort: 31, DefaultAPIType: \"openai-completions\", EnvKey: \"DASHSCOPE_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{\n\t\t\t\tAPIType: \"openai-completions\", BaseURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n\t\t\t\tDiscoverModels: true,\n\t\t\t\tModels: []Model{{ID: \"qwen3.7-plus\", Name: \"qwen3.7-plus\"}, {ID: \"qwen3.6-plus\", Name: \"qwen3.6-plus\"}, {ID: \"qwen3.6-flash\", Name: \"qwen3.6-flash\"}},\n\t\t\t},\n\t\t\t{\n\t\t\t\tAPIType: \"openai-responses\", BaseURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n\t\t\t\tDiscoverModels: true,\n\t\t\t\tModels: []Model{{ID: \"qwen3.7-plus\", Name: \"qwen3.7-plus\"}, {ID: \"qwen3.6-plus\", Name: \"qwen3.6-plus\"}, {ID: \"qwen3.6-flash\", Name: \"qwen3.6-flash\"}},\n\t\t\t},\n\t\t\t{\n\t\t\t\tAPIType: \"anthropic-messages\", BaseURL: \"https://dashscope.aliyuncs.com/apps/anthropic\",\n\t\t\t\tDefaultAuthMode: AuthModeBearer,\n\t\t\t\tAuthModes: []string{AuthModeBearer},\n\t\t\t\tModels: []Model{{ID: \"qwen3.7-plus\", Name: \"qwen3.7-plus\"}, {ID: \"qwen3.6-plus\", Name: \"qwen3.6-plus\"}, {ID: \"qwen3.6-flash\", Name: \"qwen3.6-flash\"}},\n\t\t\t},\n\t\t\t{\n\t\t\t\tAPIType: \"dashscope-images\", BaseURL: \"https://dashscope.aliyuncs.com\",\n\t\t\t\tModels: []Model{\n\t\t\t\t\t{ID: \"qwen-image-2.0-pro\", Name: \"qwen-image-2.0-pro\"},\n\t\t\t\t\t{ID: \"qwen-image-2.0\", Name: \"qwen-image-2.0\"},\n\t\t\t\t\t{ID: \"wan2.7-image-pro\", Name: \"wan2.7-image-pro\"},\n\t\t\t\t\t{ID: \"wan2.7-image\", Name: \"wan2.7-image\"},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n\t\"ark\": {\n\t\tKey: \"ark\", DisplayNameKey: \"AIProviderArk\", Sort: 36, DefaultAPIType: \"openai-completions\", EnvKey: \"ARK_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{\n\t\t\t\tAPIType: \"openai-completions\", BaseURL: \"https://ark.cn-beijing.volces.com/api/v3\",\n\t\t\t\tDiscoverModels: true,\n\t\t\t\tModels: []Model{{ID: \"doubao-seed-2-0-pro-260215\", Name: \"doubao-seed-2-0-pro-260215\"}, {ID: \"doubao-seed-2-0-lite-260215\", Name: \"doubao-seed-2-0-lite-260215\"}},\n\t\t\t},\n\t\t\t{\n\t\t\t\tAPIType: \"openai-responses\", BaseURL: \"https://ark.cn-beijing.volces.com/api/v3\",\n\t\t\t\tDiscoverModels: true,\n\t\t\t\tModels: []Model{{ID: \"doubao-seed-2-0-pro-260215\", Name: \"doubao-seed-2-0-pro-260215\"}, {ID: \"doubao-seed-2-0-lite-260215\", Name: \"doubao-seed-2-0-lite-260215\"}},\n\t\t\t},\n\t\t\t{\n\t\t\t\tAPIType: \"openai-images\", BaseURL: \"https://ark.cn-beijing.volces.com/api/v3\",\n\t\t\t\tModels: []Model{\n\t\t\t\t\t{ID: \"doubao-seedream-5-0-260128\", Name: \"doubao-seedream-5-0-260128\"},\n\t\t\t\t\t{ID: \"doubao-seedream-5-0-lite-260128\", Name: \"doubao-seedream-5-0-lite-260128\"},\n\t\t\t\t\t{ID: \"doubao-seedream-4-5-251128\", Name: \"doubao-seedream-4-5-251128\"},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n}\n\nfunc editableAPIConfigs(discoverModels bool, apiTypes ...string) []APIConfig {\n\tconfigs := make([]APIConfig, 0, len(apiTypes))\n\tfor _, apiType := range apiTypes {\n\t\tif apiType == \"anthropic-messages\" {\n\t\t\tconfig := anthropicAPIConfig(\"\", AuthModeXAPIKey, AuthModeBearer)\n\t\t\tconfig.EditableBaseURL = true\n\t\t\tconfigs = append(configs, config)\n\t\t\tcontinue\n\t\t}\n\t\tconfigs = append(configs, APIConfig{\n\t\t\tAPIType: apiType,\n\t\t\tEditableBaseURL: true,\n\t\t\tDiscoverModels: discoverModels && (apiType == \"openai-completions\" || apiType == \"openai-responses\"),\n\t\t})\n\t}\n\treturn configs\n}\n\nfunc anthropicAPIConfig(baseURL, defaultAuthMode string, additionalAuthModes ...string) APIConfig {\n\tauthModes := []string{defaultAuthMode}\n\tfor _, authMode := range additionalAuthModes {\n\t\tif authMode != defaultAuthMode {\n\t\t\tauthModes = append(authModes, authMode)\n\t\t}\n\t}\n\treturn APIConfig{\n\t\tAPIType: \"anthropic-messages\",\n\t\tBaseURL: baseURL,\n\t\tDefaultAuthMode: defaultAuthMode,\n\t\tAuthModes: authModes,\n\t}\n}\n\nfunc Get(key string) (Meta, bool) {\n\tmeta, ok := catalog[key]\n\tif !ok {\n\t\treturn Meta{}, false\n\t}\n\treturn cloneMeta(meta), true\n}\n\nfunc All() map[string]Meta {\n\tresult := make(map[string]Meta, len(catalog))\n\tfor key, meta := range catalog {\n\t\tresult[key] = cloneMeta(meta)\n\t}\n\treturn result\n}\n\nfunc FindAPIConfig(key, apiType string) (APIConfig, bool) {\n\tmeta, ok := catalog[key]\n\tif !ok {\n\t\treturn APIConfig{}, false\n\t}\n\ttarget := strings.TrimSpace(apiType)\n\tif target == \"\" {\n\t\ttarget = meta.DefaultAPIType\n\t}\n\tfor _, config := range meta.APIConfigs {\n\t\tif config.APIType == target {\n\t\t\tconfig.AuthModes = append([]string(nil), config.AuthModes...)\n\t\t\tconfig.Models = append([]Model(nil), config.Models...)\n\t\t\treturn config, true\n\t\t}\n\t}\n\treturn APIConfig{}, false\n}\n\nfunc DefaultModels(key, apiType string) []Model {\n\tmeta, ok := catalog[key]\n\tif !ok {\n\t\treturn nil\n\t}\n\ttarget := strings.TrimSpace(apiType)\n\tif target == \"\" {\n\t\ttarget = meta.DefaultAPIType\n\t}\n\tfor _, config := range meta.APIConfigs {\n\t\tif config.APIType != target {\n\t\t\tcontinue\n\t\t}\n\t\tif len(config.Models) > 0 {\n\t\t\treturn append([]Model(nil), config.Models...)\n\t\t}\n\t\tif IsImageAPIType(config.APIType) {\n\t\t\treturn nil\n\t\t}\n\t\tbreak\n\t}\n\treturn append([]Model(nil), meta.Models...)\n}\n\nfunc ResolveAuthMode(provider, apiType, requested string) (string, error) {\n\tconfig, ok := FindAPIConfig(provider, apiType)\n\tif !ok {\n\t\treturn \"\", fmt.Errorf(\"provider %s does not support api type %s\", provider, apiType)\n\t}\n\tif config.APIType != \"anthropic-messages\" {\n\t\treturn \"\", nil\n\t}\n\tauthMode := strings.TrimSpace(requested)\n\tif authMode == \"\" {\n\t\tauthMode = config.DefaultAuthMode\n\t}\n\tfor _, allowed := range config.AuthModes {\n\t\tif authMode == allowed {\n\t\t\treturn authMode, nil\n\t\t}\n\t}\n\treturn \"\", fmt.Errorf(\"provider %s does not support auth mode %s\", provider, authMode)\n}\n\nfunc DefaultBaseURL(key string) (string, bool) {\n\tconfig, ok := FindAPIConfig(key, \"\")\n\tif !ok || strings.TrimSpace(config.BaseURL) == \"\" {\n\t\treturn \"\", false\n\t}\n\treturn config.BaseURL, true\n}\n\nfunc DefaultAPIType(key string) string {\n\tmeta, ok := catalog[key]\n\tif !ok || strings.TrimSpace(meta.DefaultAPIType) == \"\" {\n\t\treturn \"openai-completions\"\n\t}\n\treturn meta.DefaultAPIType\n}\n\nfunc ResolveBaseURL(key, apiType, requested string) (string, error) {\n\tconfig, ok := FindAPIConfig(key, apiType)\n\tif !ok {\n\t\treturn \"\", fmt.Errorf(\"provider %s does not support api type %s\", key, apiType)\n\t}\n\tif !config.EditableBaseURL {\n\t\treturn strings.TrimRight(config.BaseURL, \"/\"), nil\n\t}\n\tbaseURL := strings.TrimSpace(requested)\n\tif baseURL == \"\" {\n\t\tbaseURL = config.BaseURL\n\t}\n\tif baseURL == \"\" {\n\t\treturn \"\", fmt.Errorf(\"base url is required\")\n\t}\n\tparsed, err := url.Parse(baseURL)\n\tif err != nil || parsed.Scheme == \"\" || parsed.Host == \"\" {\n\t\treturn \"\", fmt.Errorf(\"invalid base url\")\n\t}\n\tif key == \"custom\" && IsImageAPIType(config.APIType) {\n\t\treturn baseURL, nil\n\t}\n\tparsed.Path = normalizeEndpointPath(config.APIType, parsed.Path)\n\tparsed.RawQuery = \"\"\n\tparsed.Fragment = \"\"\n\treturn strings.TrimRight(parsed.String(), \"/\"), nil\n}\n\nfunc normalizeEndpointPath(apiType, value string) string {\n\tif IsImageAPIType(apiType) {\n\t\treturn strings.TrimRight(value, \"/\")\n\t}\n\tpath := strings.TrimRight(value, \"/\")\n\tsuffixes := []string{}\n\tswitch apiType {\n\tcase \"openai-completions\":\n\t\tsuffixes = []string{\"/chat/completions\"}\n\tcase \"openai-responses\":\n\t\tsuffixes = []string{\"/responses\"}\n\tcase \"anthropic-messages\":\n\t\tsuffixes = []string{\"/v1/messages\", \"/messages\"}\n\t}\n\tfor _, suffix := range suffixes {\n\t\tif strings.HasSuffix(strings.ToLower(path), suffix) {\n\t\t\treturn path[:len(path)-len(suffix)]\n\t\t}\n\t}\n\treturn path\n}\n\nfunc IsImageAPIType(apiType string) bool {\n\tswitch apiType {\n\tcase \"openai-images\", \"dashscope-images\", \"minimax-images\", \"openrouter-images\":\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n\nfunc EnvKey(key string) string {\n\tmeta, ok := catalog[key]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.EnvKey\n}\n\nfunc DisplayName(key string) string {\n\tmeta, ok := catalog[key]\n\tif !ok || strings.TrimSpace(meta.DisplayName) == \"\" {\n\t\treturn key\n\t}\n\treturn meta.DisplayName\n}\n\nfunc DisplayNameKey(key string) string {\n\tmeta, ok := catalog[key]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.DisplayNameKey\n}\n\nfunc NormalizeModelID(provider, modelID string) string {\n\ttarget := strings.TrimLeft(strings.TrimSpace(modelID), \"/\")\n\tfor _, prefix := range legacyModelPrefixes[provider] {\n\t\tlegacyPrefix := prefix + \"/\"\n\t\tif !strings.HasPrefix(target, legacyPrefix) {\n\t\t\tcontinue\n\t\t}\n\t\tcandidate := strings.TrimSpace(strings.TrimPrefix(target, legacyPrefix))\n\t\tif candidate != \"\" {\n\t\t\treturn candidate\n\t\t}\n\t}\n\treturn target\n}\n\nvar legacyModelPrefixes = map[string][]string{\n\t\"custom\": {\"custom\"},\n\t\"vllm\": {\"custom\"},\n\t\"ollama\": {\"ollama\"},\n\t\"deepseek\": {\"deepseek\"},\n\t\"bailian-coding-plan\": {\"bailian-coding-plan\"},\n\t\"ark-coding-plan\": {\"ark-coding-plan\"},\n\t\"zai\": {\"zai\"},\n\t\"minimax\": {\"minimax\"},\n\t\"xiaomi\": {\"xiaomi\"},\n\t\"kimi\": {\"kimi\", \"moonshot\"},\n\t\"kimi-coding\": {\"kimi-coding\"},\n\t\"openai\": {\"openai\"},\n\t\"anthropic\": {\"anthropic\"},\n\t\"gemini\": {\"google\", \"gemini\"},\n\t\"moonshot\": {\"moonshot\"},\n}\n\nfunc cloneMeta(meta Meta) Meta {\n\tclone := meta\n\tclone.APIConfigs = make([]APIConfig, len(meta.APIConfigs))\n\tfor index, config := range meta.APIConfigs {\n\t\tclone.APIConfigs[index] = config\n\t\tclone.APIConfigs[index].AuthModes = append([]string(nil), config.AuthModes...)\n\t\tclone.APIConfigs[index].Models = append([]Model(nil), config.Models...)\n\t}\n\tclone.Models = append([]Model(nil), meta.Models...)\n\treturn clone\n}\n"}, "e2754b447d6682cfee4968c19a00a026b8900c67": {"t": 1785755373.8552284, "n": 17469, "h": "2883ec8ec3c306c4", "c": "package provider\n\nimport (\n\t\"fmt\"\n\t\"net/url\"\n\t\"strings\"\n)\n\ntype APIConfig struct {\n\tAPIType string\n\tBaseURL string\n\tEditableBaseURL bool\n\tDiscoverModels bool\n\tDefaultAuthMode string\n\tAuthModes []string\n\tModels []Model\n}\n\nconst (\n\tAuthModeBearer = \"bearer\"\n\tAuthModeXAPIKey = \"x-api-key\"\n)\n\ntype Model struct {\n\tID string\n\tName string\n}\n\ntype Meta struct {\n\tKey string\n\tDisplayName string\n\tDisplayNameKey string\n\tSort uint\n\tDefaultAPIType string\n\tAPIConfigs []APIConfig\n\tEnvKey string\n\tModels []Model\n}\n\nvar catalog = map[string]Meta{\n\t\"custom\": {\n\t\tKey: \"custom\", DisplayName: \"Custom\", Sort: 10, DefaultAPIType: \"openai-completions\", EnvKey: \"CUSTOM_API_KEY\",\n\t\tAPIConfigs: editableAPIConfigs(true, \"openai-completions\", \"openai-responses\", \"anthropic-messages\", \"openai-images\", \"dashscope-images\", \"minimax-images\", \"openrouter-images\"),\n\t},\n\t\"ollama\": {\n\t\tKey: \"ollama\", DisplayName: \"Ollama\", Sort: 15, DefaultAPIType: \"openai-responses\",\n\t\tAPIConfigs: editableAPIConfigs(false, \"openai-responses\", \"openai-completions\"),\n\t},\n\t\"vllm\": {\n\t\tKey: \"vllm\", DisplayName: \"vLLM\", Sort: 20, DefaultAPIType: \"openai-completions\", EnvKey: \"VLLM_API_KEY\",\n\t\tAPIConfigs: editableAPIConfigs(false, \"openai-completions\", \"openai-responses\", \"anthropic-messages\", \"openai-images\"),\n\t},\n\t\"deepseek\": {\n\t\tKey: \"deepseek\", DisplayName: \"DeepSeek\", Sort: 25, DefaultAPIType: \"openai-completions\", EnvKey: \"DEEPSEEK_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://api.deepseek.com/v1\"},\n\t\t\tanthropicAPIConfig(\"https://api.deepseek.com/anthropic\", AuthModeXAPIKey),\n\t\t},\n\t\tModels: []Model{{ID: \"deepseek-v4-flash\", Name: \"deepseek-v4-flash\"}, {ID: \"deepseek-v4-pro\", Name: \"deepseek-v4-pro\"}},\n\t},\n\t\"bailian-coding-plan\": {\n\t\tKey: \"bailian-coding-plan\", DisplayNameKey: \"AIProviderBailianCodingPlan\", Sort: 30, DefaultAPIType: \"openai-completions\", EnvKey: \"QWEN_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://coding.dashscope.aliyuncs.com/v1\"},\n\t\t\tanthropicAPIConfig(\"https://coding.dashscope.aliyuncs.com/apps/anthropic\", AuthModeBearer),\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"qwen3-coder-plus\", Name: \"Qwen3-Coder-Plus\"},\n\t\t\t{ID: \"qwen3-max-2026-01-23\", Name: \"Qwen3-Max-2026-01-23\"},\n\t\t\t{ID: \"qwen3-coder-next\", Name: \"Qwen3-Coder-Next\"},\n\t\t\t{ID: \"glm-4.7\", Name: \"GLM-4.7\"},\n\t\t\t{ID: \"kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"qwen3.5-plus\", Name: \"Qwen3.5-Plus\"},\n\t\t\t{ID: \"glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"MiniMax-M2.5\", Name: \"MiniMax M2.5\"},\n\t\t\t{ID: \"qwen3.6-plus\", Name: \"Qwen3.6-Plus\"},\n\t\t\t{ID: \"qwen3.7-plus\", Name: \"Qwen3.7-Plus\"},\n\t\t},\n\t},\n\t\"ark-coding-plan\": {\n\t\tKey: \"ark-coding-plan\", DisplayNameKey: \"AIProviderArkCodingPlan\", Sort: 35, DefaultAPIType: \"openai-completions\", EnvKey: \"ARK_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://ark.cn-beijing.volces.com/api/coding/v3\"},\n\t\t\tanthropicAPIConfig(\"https://ark.cn-beijing.volces.com/api/coding\", AuthModeBearer),\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"ark-code-latest\", Name: \"Ark Coding Plan\"}, {ID: \"doubao-seed-code\", Name: \"Doubao Seed Code\"},\n\t\t\t{ID: \"glm-4.7\", Name: \"GLM 4.7 Coding\"}, {ID: \"kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t\t{ID: \"kimi-k2.5\", Name: \"Kimi K2.5 Coding\"}, {ID: \"doubao-seed-code-preview-251028\", Name: \"Doubao Seed Code Preview\"},\n\t\t},\n\t},\n\t\"zai\": {\n\t\tKey: \"zai\", DisplayName: \"Z.ai\", Sort: 40, DefaultAPIType: \"openai-completions\", EnvKey: \"ZAI_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://open.bigmodel.cn/api/paas/v4\", EditableBaseURL: true},\n\t\t\t{APIType: \"openai-images\", BaseURL: \"https://open.bigmodel.cn/api/paas/v4\", EditableBaseURL: true},\n\t\t},\n\t\tModels: []Model{{ID: \"glm-5\", Name: \"GLM-5\"}, {ID: \"glm-4.7\", Name: \"GLM-4.7\"}, {ID: \"glm-4.7-flash\", Name: \"GLM-4.7-Flash\"}, {ID: \"glm-4.7-flashx\", Name: \"GLM-4.7-FlashX\"}},\n\t},\n\t\"minimax\": {\n\t\tKey: \"minimax\", DisplayName: \"MiniMax (CN)\", Sort: 45, DefaultAPIType: \"anthropic-messages\", EnvKey: \"MINIMAX_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\tanthropicAPIConfig(\"https://api.minimaxi.com/anthropic\", AuthModeXAPIKey, AuthModeBearer),\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://api.minimaxi.com/v1\"},\n\t\t\t{APIType: \"minimax-images\", BaseURL: \"https://api.minimaxi.com\"},\n\t\t},\n\t\tModels: []Model{{ID: \"MiniMax-M3\", Name: \"MiniMax M3\"}, {ID: \"MiniMax-M2.7\", Name: \"MiniMax M2.7\"}, {ID: \"MiniMax-M2.7-highspeed\", Name: \"MiniMax M2.7 highspeed\"}},\n\t},\n\t\"xiaomi\": {\n\t\tKey: \"xiaomi\", DisplayName: \"Xiaomi\", Sort: 46, DefaultAPIType: \"openai-completions\", EnvKey: \"XIAOMI_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://api.xiaomimimo.com/v1\"},\n\t\t\tanthropicAPIConfig(\"https://api.xiaomimimo.com/anthropic\", AuthModeBearer),\n\t\t},\n\t\tModels: []Model{{ID: \"mimo-v2-flash\", Name: \"Xiaomi MiMo V2 Flash\"}, {ID: \"mimo-v2-pro\", Name: \"Xiaomi MiMo V2 Pro\"}, {ID: \"mimo-v2-omni\", Name: \"Xiaomi MiMo V2 Omni\"}},\n\t},\n\t\"kimi\": {\n\t\tKey: \"kimi\", DisplayName: \"Kimi (CN)\", Sort: 50, DefaultAPIType: \"openai-completions\", EnvKey: \"KIMI_API_KEY\",\n\t\tAPIConfigs: []APIConfig{{APIType: \"openai-completions\", BaseURL: \"https://api.moonshot.cn/v1\"}},\n\t\tModels: []Model{{ID: \"kimi-k2.5\", Name: \"Kimi K2.5\"}, {ID: \"kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"}, {ID: \"kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"}},\n\t},\n\t\"kimi-coding\": {\n\t\tKey: \"kimi-coding\", DisplayName: \"Kimi Coding\", Sort: 51, DefaultAPIType: \"anthropic-messages\", EnvKey: \"KIMI_API_KEY\",\n\t\tAPIConfigs: []APIConfig{anthropicAPIConfig(\"https://api.kimi.com/coding/\", AuthModeXAPIKey)},\n\t\tModels: []Model{{ID: \"kimi-code\", Name: \"Kimi Code\"}, {ID: \"k2p5\", Name: \"Kimi K2.5\"}},\n\t},\n\t\"openai\": {\n\t\tKey: \"openai\", DisplayName: \"OpenAI\", Sort: 55, DefaultAPIType: \"openai-responses\", EnvKey: \"OPENAI_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{APIType: \"openai-responses\", BaseURL: \"https://api.openai.com/v1\"},\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://api.openai.com/v1\"},\n\t\t\t{APIType: \"openai-images\", BaseURL: \"https://api.openai.com/v1\"},\n\t\t},\n\t\tModels: []Model{{ID: \"gpt-5.4\", Name: \"gpt-5.4\"}, {ID: \"gpt-5.4-pro\", Name: \"gpt-5.4-pro\"}, {ID: \"gpt-5.4-mini\", Name: \"gpt-5.4-mini\"}, {ID: \"gpt-5.4-nano\", Name: \"gpt-5.4-nano\"}},\n\t},\n\t\"openrouter\": {\n\t\tKey: \"openrouter\", DisplayName: \"OpenRouter\", Sort: 56, DefaultAPIType: \"openai-completions\", EnvKey: \"OPENROUTER_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://openrouter.ai/api/v1\"},\n\t\t\t{APIType: \"openrouter-images\", BaseURL: \"https://openrouter.ai\"},\n\t\t},\n\t\tModels: []Model{{ID: \"openrouter/free\", Name: \"openrouter/free\"}, {ID: \"openrouter/auto\", Name: \"openrouter/auto\"}},\n\t},\n\t\"anthropic\": {\n\t\tKey: \"anthropic\", DisplayName: \"Anthropic\", Sort: 60, DefaultAPIType: \"anthropic-messages\", EnvKey: \"ANTHROPIC_API_KEY\",\n\t\tAPIConfigs: []APIConfig{anthropicAPIConfig(\"https://api.anthropic.com\", AuthModeXAPIKey)},\n\t\tModels: []Model{{ID: \"claude-sonnet-4-6\", Name: \"Claude Sonnet 4.6\"}, {ID: \"claude-opus-4-6\", Name: \"Claude Opus 4.6\"}, {ID: \"claude-opus-4-5\", Name: \"Claude Opus 4.5\"}, {ID: \"claude-sonnet-4-5\", Name: \"Claude Sonnet 4.5\"}, {ID: \"claude-haiku-4-5\", Name: \"Claude Haiku 4.5\"}},\n\t},\n\t\"gemini\": {\n\t\tKey: \"gemini\", DisplayName: \"Gemini\", Sort: 65, DefaultAPIType: \"gemini-generate-content\", EnvKey: \"GEMINI_API_KEY\",\n\t\tAPIConfigs: []APIConfig{{APIType: \"gemini-generate-content\", BaseURL: \"https://generativelanguage.googleapis.com\"}},\n\t\tModels: []Model{{ID: \"gemini-3-flash-preview\", Name: \"Gemini 3 Flash Preview\"}, {ID: \"gemini-flash-latest\", Name: \"Gemini Flash Latest\"}, {ID: \"gemini-3-pro-preview\", Name: \"Gemini 3 Pro Preview\"}},\n\t},\n\t\"moonshot\": {\n\t\tKey: \"moonshot\", DisplayName: \"Moonshot (Global)\", Sort: 70, DefaultAPIType: \"openai-completions\", EnvKey: \"MOONSHOT_API_KEY\",\n\t\tAPIConfigs: []APIConfig{{APIType: \"openai-completions\", BaseURL: \"https://api.moonshot.ai/v1\"}},\n\t\tModels: []Model{{ID: \"kimi-k2.5\", Name: \"Kimi K2.5\"}, {ID: \"kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"}, {ID: \"kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"}},\n\t},\n\t\"bailian\": {\n\t\tKey: \"bailian\", DisplayNameKey: \"AIProviderBailian\", Sort: 31, DefaultAPIType: \"openai-completions\", EnvKey: \"DASHSCOPE_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{\n\t\t\t\tAPIType: \"openai-completions\", BaseURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n\t\t\t\tDiscoverModels: true,\n\t\t\t\tModels: []Model{{ID: \"qwen3.7-plus\", Name: \"qwen3.7-plus\"}, {ID: \"qwen3.6-plus\", Name: \"qwen3.6-plus\"}, {ID: \"qwen3.6-flash\", Name: \"qwen3.6-flash\"}},\n\t\t\t},\n\t\t\t{\n\t\t\t\tAPIType: \"openai-responses\", BaseURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n\t\t\t\tDiscoverModels: true,\n\t\t\t\tModels: []Model{{ID: \"qwen3.7-plus\", Name: \"qwen3.7-plus\"}, {ID: \"qwen3.6-plus\", Name: \"qwen3.6-plus\"}, {ID: \"qwen3.6-flash\", Name: \"qwen3.6-flash\"}},\n\t\t\t},\n\t\t\t{\n\t\t\t\tAPIType: \"anthropic-messages\", BaseURL: \"https://dashscope.aliyuncs.com/apps/anthropic\",\n\t\t\t\tDefaultAuthMode: AuthModeBearer,\n\t\t\t\tAuthModes: []string{AuthModeBearer},\n\t\t\t\tModels: []Model{{ID: \"qwen3.7-plus\", Name: \"qwen3.7-plus\"}, {ID: \"qwen3.6-plus\", Name: \"qwen3.6-plus\"}, {ID: \"qwen3.6-flash\", Name: \"qwen3.6-flash\"}},\n\t\t\t},\n\t\t\t{\n\t\t\t\tAPIType: \"dashscope-images\", BaseURL: \"https://dashscope.aliyuncs.com\",\n\t\t\t\tModels: []Model{\n\t\t\t\t\t{ID: \"qwen-image-2.0-pro\", Name: \"qwen-image-2.0-pro\"},\n\t\t\t\t\t{ID: \"qwen-image-2.0\", Name: \"qwen-image-2.0\"},\n\t\t\t\t\t{ID: \"wan2.7-image-pro\", Name: \"wan2.7-image-pro\"},\n\t\t\t\t\t{ID: \"wan2.7-image\", Name: \"wan2.7-image\"},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n\t\"ark\": {\n\t\tKey: \"ark\", DisplayNameKey: \"AIProviderArk\", Sort: 36, DefaultAPIType: \"openai-completions\", EnvKey: \"ARK_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{\n\t\t\t\tAPIType: \"openai-completions\", BaseURL: \"https://ark.cn-beijing.volces.com/api/v3\",\n\t\t\t\tDiscoverModels: true,\n\t\t\t\tModels: []Model{{ID: \"doubao-seed-2-0-pro-260215\", Name: \"doubao-seed-2-0-pro-260215\"}, {ID: \"doubao-seed-2-0-lite-260215\", Name: \"doubao-seed-2-0-lite-260215\"}},\n\t\t\t},\n\t\t\t{\n\t\t\t\tAPIType: \"openai-responses\", BaseURL: \"https://ark.cn-beijing.volces.com/api/v3\",\n\t\t\t\tDiscoverModels: true,\n\t\t\t\tModels: []Model{{ID: \"doubao-seed-2-0-pro-260215\", Name: \"doubao-seed-2-0-pro-260215\"}, {ID: \"doubao-seed-2-0-lite-260215\", Name: \"doubao-seed-2-0-lite-260215\"}},\n\t\t\t},\n\t\t\t{\n\t\t\t\tAPIType: \"openai-images\", BaseURL: \"https://ark.cn-beijing.volces.com/api/v3\",\n\t\t\t\tModels: []Model{\n\t\t\t\t\t{ID: \"doubao-seedream-5-0-260128\", Name: \"doubao-seedream-5-0-260128\"},\n\t\t\t\t\t{ID: \"doubao-seedream-5-0-lite-260128\", Name: \"doubao-seedream-5-0-lite-260128\"},\n\t\t\t\t\t{ID: \"doubao-seedream-4-5-251128\", Name: \"doubao-seedream-4-5-251128\"},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n}\n\nfunc editableAPIConfigs(discoverModels bool, apiTypes ...string) []APIConfig {\n\tconfigs := make([]APIConfig, 0, len(apiTypes))\n\tfor _, apiType := range apiTypes {\n\t\tif apiType == \"anthropic-messages\" {\n\t\t\tconfig := anthropicAPIConfig(\"\", AuthModeXAPIKey, AuthModeBearer)\n\t\t\tconfig.EditableBaseURL = true\n\t\t\tconfigs = append(configs, config)\n\t\t\tcontinue\n\t\t}\n\t\tconfigs = append(configs, APIConfig{\n\t\t\tAPIType: apiType,\n\t\t\tEditableBaseURL: true,\n\t\t\tDiscoverModels: discoverModels && (apiType == \"openai-completions\" || apiType == \"openai-responses\"),\n\t\t})\n\t}\n\treturn configs\n}\n\nfunc anthropicAPIConfig(baseURL, defaultAuthMode string, additionalAuthModes ...string) APIConfig {\n\tauthModes := []string{defaultAuthMode}\n\tfor _, authMode := range additionalAuthModes {\n\t\tif authMode != defaultAuthMode {\n\t\t\tauthModes = append(authModes, authMode)\n\t\t}\n\t}\n\treturn APIConfig{\n\t\tAPIType: \"anthropic-messages\",\n\t\tBaseURL: baseURL,\n\t\tDefaultAuthMode: defaultAuthMode,\n\t\tAuthModes: authModes,\n\t}\n}\n\nfunc Get(key string) (Meta, bool) {\n\tmeta, ok := catalog[key]\n\tif !ok {\n\t\treturn Meta{}, false\n\t}\n\treturn cloneMeta(meta), true\n}\n\nfunc All() map[string]Meta {\n\tresult := make(map[string]Meta, len(catalog))\n\tfor key, meta := range catalog {\n\t\tresult[key] = cloneMeta(meta)\n\t}\n\treturn result\n}\n\nfunc FindAPIConfig(key, apiType string) (APIConfig, bool) {\n\tmeta, ok := catalog[key]\n\tif !ok {\n\t\treturn APIConfig{}, false\n\t}\n\ttarget := strings.TrimSpace(apiType)\n\tif target == \"\" {\n\t\ttarget = meta.DefaultAPIType\n\t}\n\tfor _, config := range meta.APIConfigs {\n\t\tif config.APIType == target {\n\t\t\tconfig.AuthModes = append([]string(nil), config.AuthModes...)\n\t\t\tconfig.Models = append([]Model(nil), config.Models...)\n\t\t\treturn config, true\n\t\t}\n\t}\n\treturn APIConfig{}, false\n}\n\nfunc DefaultModels(key, apiType string) []Model {\n\tmeta, ok := catalog[key]\n\tif !ok {\n\t\treturn nil\n\t}\n\ttarget := strings.TrimSpace(apiType)\n\tif target == \"\" {\n\t\ttarget = meta.DefaultAPIType\n\t}\n\tfor _, config := range meta.APIConfigs {\n\t\tif config.APIType != target {\n\t\t\tcontinue\n\t\t}\n\t\tif len(config.Models) > 0 {\n\t\t\treturn append([]Model(nil), config.Models...)\n\t\t}\n\t\tif IsImageAPIType(config.APIType) {\n\t\t\treturn nil\n\t\t}\n\t\tbreak\n\t}\n\treturn append([]Model(nil), meta.Models...)\n}\n\nfunc ResolveAuthMode(provider, apiType, requested string) (string, error) {\n\tconfig, ok := FindAPIConfig(provider, apiType)\n\tif !ok {\n\t\treturn \"\", fmt.Errorf(\"provider %s does not support api type %s\", provider, apiType)\n\t}\n\tif config.APIType != \"anthropic-messages\" {\n\t\treturn \"\", nil\n\t}\n\tauthMode := strings.TrimSpace(requested)\n\tif authMode == \"\" {\n\t\tauthMode = config.DefaultAuthMode\n\t}\n\tfor _, allowed := range config.AuthModes {\n\t\tif authMode == allowed {\n\t\t\treturn authMode, nil\n\t\t}\n\t}\n\treturn \"\", fmt.Errorf(\"provider %s does not support auth mode %s\", provider, authMode)\n}\n\nfunc DefaultBaseURL(key string) (string, bool) {\n\tconfig, ok := FindAPIConfig(key, \"\")\n\tif !ok || strings.TrimSpace(config.BaseURL) == \"\" {\n\t\treturn \"\", false\n\t}\n\treturn config.BaseURL, true\n}\n\nfunc DefaultAPIType(key string) string {\n\tmeta, ok := catalog[key]\n\tif !ok || strings.TrimSpace(meta.DefaultAPIType) == \"\" {\n\t\treturn \"openai-completions\"\n\t}\n\treturn meta.DefaultAPIType\n}\n\nfunc ResolveBaseURL(key, apiType, requested string) (string, error) {\n\tconfig, ok := FindAPIConfig(key, apiType)\n\tif !ok {\n\t\treturn \"\", fmt.Errorf(\"provider %s does not support api type %s\", key, apiType)\n\t}\n\tif !config.EditableBaseURL {\n\t\treturn strings.TrimRight(config.BaseURL, \"/\"), nil\n\t}\n\tbaseURL := strings.TrimSpace(requested)\n\tif baseURL == \"\" {\n\t\tbaseURL = config.BaseURL\n\t}\n\tif baseURL == \"\" {\n\t\treturn \"\", fmt.Errorf(\"base url is required\")\n\t}\n\tparsed, err := url.Parse(baseURL)\n\tif err != nil || parsed.Scheme == \"\" || parsed.Host == \"\" {\n\t\treturn \"\", fmt.Errorf(\"invalid base url\")\n\t}\n\tif key == \"custom\" && IsImageAPIType(config.APIType) {\n\t\treturn baseURL, nil\n\t}\n\tparsed.Path = normalizeEndpointPath(config.APIType, parsed.Path)\n\tparsed.RawQuery = \"\"\n\tparsed.Fragment = \"\"\n\treturn strings.TrimRight(parsed.String(), \"/\"), nil\n}\n\nfunc normalizeEndpointPath(apiType, value string) string {\n\tif IsImageAPIType(apiType) {\n\t\treturn strings.TrimRight(value, \"/\")\n\t}\n\tpath := strings.TrimRight(value, \"/\")\n\tsuffixes := []string{}\n\tswitch apiType {\n\tcase \"openai-completions\":\n\t\tsuffixes = []string{\"/chat/completions\"}\n\tcase \"openai-responses\":\n\t\tsuffixes = []string{\"/responses\"}\n\tcase \"anthropic-messages\":\n\t\tsuffixes = []string{\"/v1/messages\", \"/messages\"}\n\t}\n\tfor _, suffix := range suffixes {\n\t\tif strings.HasSuffix(strings.ToLower(path), suffix) {\n\t\t\treturn path[:len(path)-len(suffix)]\n\t\t}\n\t}\n\treturn path\n}\n\nfunc IsImageAPIType(apiType string) bool {\n\tswitch apiType {\n\tcase \"openai-images\", \"dashscope-images\", \"minimax-images\", \"openrouter-images\":\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n\nfunc EnvKey(key string) string {\n\tmeta, ok := catalog[key]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.EnvKey\n}\n\nfunc DisplayName(key string) string {\n\tmeta, ok := catalog[key]\n\tif !ok || strings.TrimSpace(meta.DisplayName) == \"\" {\n\t\treturn key\n\t}\n\treturn meta.DisplayName\n}\n\nfunc DisplayNameKey(key string) string {\n\tmeta, ok := catalog[key]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.DisplayNameKey\n}\n\nfunc NormalizeModelID(provider, modelID string) string {\n\ttarget := strings.TrimLeft(strings.TrimSpace(modelID), \"/\")\n\tfor _, prefix := range legacyModelPrefixes[provider] {\n\t\tlegacyPrefix := prefix + \"/\"\n\t\tif !strings.HasPrefix(target, legacyPrefix) {\n\t\t\tcontinue\n\t\t}\n\t\tcandidate := strings.TrimSpace(strings.TrimPrefix(target, legacyPrefix))\n\t\tif candidate != \"\" {\n\t\t\treturn candidate\n\t\t}\n\t}\n\treturn target\n}\n\nvar legacyModelPrefixes = map[string][]string{\n\t\"custom\": {\"custom\"},\n\t\"vllm\": {\"custom\"},\n\t\"ollama\": {\"ollama\"},\n\t\"deepseek\": {\"deepseek\"},\n\t\"bailian-coding-plan\": {\"bailian-coding-plan\"},\n\t\"ark-coding-plan\": {\"ark-coding-plan\"},\n\t\"zai\": {\"zai\"},\n\t\"minimax\": {\"minimax\"},\n\t\"xiaomi\": {\"xiaomi\"},\n\t\"kimi\": {\"kimi\", \"moonshot\"},\n\t\"kimi-coding\": {\"kimi-coding\"},\n\t\"openai\": {\"openai\"},\n\t\"anthropic\": {\"anthropic\"},\n\t\"gemini\": {\"google\", \"gemini\"},\n\t\"moonshot\": {\"moonshot\"},\n}\n\nfunc cloneMeta(meta Meta) Meta {\n\tclone := meta\n\tclone.APIConfigs = make([]APIConfig, len(meta.APIConfigs))\n\tfor index, config := range meta.APIConfigs {\n\t\tclone.APIConfigs[index] = config\n\t\tclone.APIConfigs[index].AuthModes = append([]string(nil), config.AuthModes...)\n\t\tclone.APIConfigs[index].Models = append([]Model(nil), config.Models...)\n\t}\n\tclone.Models = append([]Model(nil), meta.Models...)\n\treturn clone\n}\n"}, "8b265bb81ecf6276df0188595230317f2770c1ac": {"t": 1785755376.2400873, "n": 13069, "h": "1ba14a0399f8f75a", "c": "package provider\n\nimport (\n\t\"fmt\"\n\t\"net/url\"\n\t\"strings\"\n)\n\ntype APIConfig struct {\n\tAPIType string\n\tBaseURL string\n\tEditableBaseURL bool\n\tDefaultAuthMode string\n\tAuthModes []string\n}\n\nconst (\n\tAuthModeBearer = \"bearer\"\n\tAuthModeXAPIKey = \"x-api-key\"\n)\n\ntype Model struct {\n\tID string\n\tName string\n}\n\ntype Meta struct {\n\tKey string\n\tDisplayName string\n\tSort uint\n\tDefaultAPIType string\n\tAPIConfigs []APIConfig\n\tEnvKey string\n\tModels []Model\n}\n\nvar catalog = map[string]Meta{\n\t\"custom\": {\n\t\tKey: \"custom\", DisplayName: \"Custom\", Sort: 10, DefaultAPIType: \"openai-completions\", EnvKey: \"CUSTOM_API_KEY\",\n\t\tAPIConfigs: editableAPIConfigs(\"openai-completions\", \"openai-responses\", \"anthropic-messages\"),\n\t},\n\t\"ollama\": {\n\t\tKey: \"ollama\", DisplayName: \"Ollama\", Sort: 15, DefaultAPIType: \"openai-responses\",\n\t\tAPIConfigs: editableAPIConfigs(\"openai-responses\", \"openai-completions\"),\n\t},\n\t\"vllm\": {\n\t\tKey: \"vllm\", DisplayName: \"vLLM\", Sort: 20, DefaultAPIType: \"openai-completions\", EnvKey: \"VLLM_API_KEY\",\n\t\tAPIConfigs: editableAPIConfigs(\"openai-completions\", \"openai-responses\", \"anthropic-messages\"),\n\t},\n\t\"deepseek\": {\n\t\tKey: \"deepseek\", DisplayName: \"DeepSeek\", Sort: 25, DefaultAPIType: \"openai-completions\", EnvKey: \"DEEPSEEK_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://api.deepseek.com/v1\"},\n\t\t\tanthropicAPIConfig(\"https://api.deepseek.com/anthropic\", AuthModeXAPIKey),\n\t\t},\n\t\tModels: []Model{{ID: \"deepseek-v4-flash\", Name: \"deepseek-v4-flash\"}, {ID: \"deepseek-v4-pro\", Name: \"deepseek-v4-pro\"}},\n\t},\n\t\"bailian-coding-plan\": {\n\t\tKey: \"bailian-coding-plan\", DisplayName: \"阿里云百炼 Coding Plan\", Sort: 30, DefaultAPIType: \"openai-completions\", EnvKey: \"QWEN_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://coding.dashscope.aliyuncs.com/v1\"},\n\t\t\tanthropicAPIConfig(\"https://coding.dashscope.aliyuncs.com/apps/anthropic\", AuthModeBearer),\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"qwen3-coder-plus\", Name: \"Qwen3-Coder-Plus\"},\n\t\t\t{ID: \"qwen3-max-2026-01-23\", Name: \"Qwen3-Max-2026-01-23\"},\n\t\t\t{ID: \"qwen3-coder-next\", Name: \"Qwen3-Coder-Next\"},\n\t\t\t{ID: \"glm-4.7\", Name: \"GLM-4.7\"},\n\t\t\t{ID: \"kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"qwen3.5-plus\", Name: \"Qwen3.5-Plus\"},\n\t\t\t{ID: \"glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"MiniMax-M2.5\", Name: \"MiniMax M2.5\"},\n\t\t\t{ID: \"qwen3.6-plus\", Name: \"Qwen3.6-Plus\"},\n\t\t\t{ID: \"qwen3.7-plus\", Name: \"Qwen3.7-Plus\"},\n\t\t},\n\t},\n\t\"ark-coding-plan\": {\n\t\tKey: \"ark-coding-plan\", DisplayName: \"方舟 Coding Plan\", Sort: 35, DefaultAPIType: \"openai-completions\", EnvKey: \"ARK_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://ark.cn-beijing.volces.com/api/coding/v3\"},\n\t\t\tanthropicAPIConfig(\"https://ark.cn-beijing.volces.com/api/coding\", AuthModeBearer),\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"ark-code-latest\", Name: \"Ark Coding Plan\"}, {ID: \"doubao-seed-code\", Name: \"Doubao Seed Code\"},\n\t\t\t{ID: \"glm-4.7\", Name: \"GLM 4.7 Coding\"}, {ID: \"kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t\t{ID: \"kimi-k2.5\", Name: \"Kimi K2.5 Coding\"}, {ID: \"doubao-seed-code-preview-251028\", Name: \"Doubao Seed Code Preview\"},\n\t\t},\n\t},\n\t\"zai\": {\n\t\tKey: \"zai\", DisplayName: \"Z.ai\", Sort: 40, DefaultAPIType: \"openai-completions\", EnvKey: \"ZAI_API_KEY\",\n\t\tAPIConfigs: []APIConfig{{APIType: \"openai-completions\", BaseURL: \"https://open.bigmodel.cn/api/paas/v4\", EditableBaseURL: true}},\n\t\tModels: []Model{{ID: \"glm-5\", Name: \"GLM-5\"}, {ID: \"glm-4.7\", Name: \"GLM-4.7\"}, {ID: \"glm-4.7-flash\", Name: \"GLM-4.7-Flash\"}, {ID: \"glm-4.7-flashx\", Name: \"GLM-4.7-FlashX\"}},\n\t},\n\t\"minimax\": {\n\t\tKey: \"minimax\", DisplayName: \"MiniMax (CN)\", Sort: 45, DefaultAPIType: \"anthropic-messages\", EnvKey: \"MINIMAX_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\tanthropicAPIConfig(\"https://api.minimaxi.com/anthropic\", AuthModeXAPIKey, AuthModeBearer),\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://api.minimaxi.com/v1\"},\n\t\t},\n\t\tModels: []Model{{ID: \"MiniMax-M3\", Name: \"MiniMax M3\"}, {ID: \"MiniMax-M2.7\", Name: \"MiniMax M2.7\"}, {ID: \"MiniMax-M2.7-highspeed\", Name: \"MiniMax M2.7 highspeed\"}},\n\t},\n\t\"xiaomi\": {\n\t\tKey: \"xiaomi\", DisplayName: \"Xiaomi\", Sort: 46, DefaultAPIType: \"openai-completions\", EnvKey: \"XIAOMI_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://api.xiaomimimo.com/v1\"},\n\t\t\tanthropicAPIConfig(\"https://api.xiaomimimo.com/anthropic\", AuthModeBearer),\n\t\t},\n\t\tModels: []Model{{ID: \"mimo-v2-flash\", Name: \"Xiaomi MiMo V2 Flash\"}, {ID: \"mimo-v2-pro\", Name: \"Xiaomi MiMo V2 Pro\"}, {ID: \"mimo-v2-omni\", Name: \"Xiaomi MiMo V2 Omni\"}},\n\t},\n\t\"kimi\": {\n\t\tKey: \"kimi\", DisplayName: \"Kimi (CN)\", Sort: 50, DefaultAPIType: \"openai-completions\", EnvKey: \"KIMI_API_KEY\",\n\t\tAPIConfigs: []APIConfig{{APIType: \"openai-completions\", BaseURL: \"https://api.moonshot.cn/v1\"}},\n\t\tModels: []Model{{ID: \"kimi-k2.5\", Name: \"Kimi K2.5\"}, {ID: \"kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"}, {ID: \"kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"}},\n\t},\n\t\"kimi-coding\": {\n\t\tKey: \"kimi-coding\", DisplayName: \"Kimi Coding\", Sort: 51, DefaultAPIType: \"anthropic-messages\", EnvKey: \"KIMI_API_KEY\",\n\t\tAPIConfigs: []APIConfig{anthropicAPIConfig(\"https://api.kimi.com/coding/\", AuthModeXAPIKey)},\n\t\tModels: []Model{{ID: \"kimi-code\", Name: \"Kimi Code\"}, {ID: \"k2p5\", Name: \"Kimi K2.5\"}},\n\t},\n\t\"openai\": {\n\t\tKey: \"openai\", DisplayName: \"OpenAI\", Sort: 55, DefaultAPIType: \"openai-responses\", EnvKey: \"OPENAI_API_KEY\",\n\t\tAPIConfigs: []APIConfig{\n\t\t\t{APIType: \"openai-responses\", BaseURL: \"https://api.openai.com/v1\"},\n\t\t\t{APIType: \"openai-completions\", BaseURL: \"https://api.openai.com/v1\"},\n\t\t},\n\t\tModels: []Model{{ID: \"gpt-5.4\", Name: \"gpt-5.4\"}, {ID: \"gpt-5.4-pro\", Name: \"gpt-5.4-pro\"}, {ID: \"gpt-5.4-mini\", Name: \"gpt-5.4-mini\"}, {ID: \"gpt-5.4-nano\", Name: \"gpt-5.4-nano\"}},\n\t},\n\t\"openrouter\": {\n\t\tKey: \"openrouter\", DisplayName: \"OpenRouter\", Sort: 56, DefaultAPIType: \"openai-completions\", EnvKey: \"OPENROUTER_API_KEY\",\n\t\tAPIConfigs: []APIConfig{{APIType: \"openai-completions\", BaseURL: \"https://openrouter.ai/api/v1\"}},\n\t\tModels: []Model{{ID: \"openrouter/free\", Name: \"openrouter/free\"}, {ID: \"openrouter/auto\", Name: \"openrouter/auto\"}},\n\t},\n\t\"anthropic\": {\n\t\tKey: \"anthropic\", DisplayName: \"Anthropic\", Sort: 60, DefaultAPIType: \"anthropic-messages\", EnvKey: \"ANTHROPIC_API_KEY\",\n\t\tAPIConfigs: []APIConfig{anthropicAPIConfig(\"https://api.anthropic.com\", AuthModeXAPIKey)},\n\t\tModels: []Model{{ID: \"claude-sonnet-4-6\", Name: \"Claude Sonnet 4.6\"}, {ID: \"claude-opus-4-6\", Name: \"Claude Opus 4.6\"}, {ID: \"claude-opus-4-5\", Name: \"Claude Opus 4.5\"}, {ID: \"claude-sonnet-4-5\", Name: \"Claude Sonnet 4.5\"}, {ID: \"claude-haiku-4-5\", Name: \"Claude Haiku 4.5\"}},\n\t},\n\t\"gemini\": {\n\t\tKey: \"gemini\", DisplayName: \"Gemini\", Sort: 65, DefaultAPIType: \"gemini-generate-content\", EnvKey: \"GEMINI_API_KEY\",\n\t\tAPIConfigs: []APIConfig{{APIType: \"gemini-generate-content\", BaseURL: \"https://generativelanguage.googleapis.com\"}},\n\t\tModels: []Model{{ID: \"gemini-3-flash-preview\", Name: \"Gemini 3 Flash Preview\"}, {ID: \"gemini-flash-latest\", Name: \"Gemini Flash Latest\"}, {ID: \"gemini-3-pro-preview\", Name: \"Gemini 3 Pro Preview\"}},\n\t},\n\t\"moonshot\": {\n\t\tKey: \"moonshot\", DisplayName: \"Moonshot (Global)\", Sort: 70, DefaultAPIType: \"openai-completions\", EnvKey: \"MOONSHOT_API_KEY\",\n\t\tAPIConfigs: []APIConfig{{APIType: \"openai-completions\", BaseURL: \"https://api.moonshot.ai/v1\"}},\n\t\tModels: []Model{{ID: \"kimi-k2.5\", Name: \"Kimi K2.5\"}, {ID: \"kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"}, {ID: \"kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"}},\n\t},\n}\n\nfunc editableAPIConfigs(apiTypes ...string) []APIConfig {\n\tconfigs := make([]APIConfig, 0, len(apiTypes))\n\tfor _, apiType := range apiTypes {\n\t\tif apiType == \"anthropic-messages\" {\n\t\t\tconfig := anthropicAPIConfig(\"\", AuthModeXAPIKey, AuthModeBearer)\n\t\t\tconfig.EditableBaseURL = true\n\t\t\tconfigs = append(configs, config)\n\t\t\tcontinue\n\t\t}\n\t\tconfigs = append(configs, APIConfig{APIType: apiType, EditableBaseURL: true})\n\t}\n\treturn configs\n}\n\nfunc anthropicAPIConfig(baseURL, defaultAuthMode string, additionalAuthModes ...string) APIConfig {\n\tauthModes := []string{defaultAuthMode}\n\tfor _, authMode := range additionalAuthModes {\n\t\tif authMode != defaultAuthMode {\n\t\t\tauthModes = append(authModes, authMode)\n\t\t}\n\t}\n\treturn APIConfig{\n\t\tAPIType: \"anthropic-messages\",\n\t\tBaseURL: baseURL,\n\t\tDefaultAuthMode: defaultAuthMode,\n\t\tAuthModes: authModes,\n\t}\n}\n\nfunc Get(key string) (Meta, bool) {\n\tmeta, ok := catalog[key]\n\tif !ok {\n\t\treturn Meta{}, false\n\t}\n\treturn cloneMeta(meta), true\n}\n\nfunc All() map[string]Meta {\n\tresult := make(map[string]Meta, len(catalog))\n\tfor key, meta := range catalog {\n\t\tresult[key] = cloneMeta(meta)\n\t}\n\treturn result\n}\n\nfunc FindAPIConfig(key, apiType string) (APIConfig, bool) {\n\tmeta, ok := catalog[key]\n\tif !ok {\n\t\treturn APIConfig{}, false\n\t}\n\ttarget := strings.TrimSpace(apiType)\n\tif target == \"\" {\n\t\ttarget = meta.DefaultAPIType\n\t}\n\tfor _, config := range meta.APIConfigs {\n\t\tif config.APIType == target {\n\t\t\treturn config, true\n\t\t}\n\t}\n\treturn APIConfig{}, false\n}\n\nfunc ResolveAuthMode(provider, apiType, requested string) (string, error) {\n\tconfig, ok := FindAPIConfig(provider, apiType)\n\tif !ok {\n\t\treturn \"\", fmt.Errorf(\"provider %s does not support api type %s\", provider, apiType)\n\t}\n\tif config.APIType != \"anthropic-messages\" {\n\t\treturn \"\", nil\n\t}\n\tauthMode := strings.TrimSpace(requested)\n\tif authMode == \"\" {\n\t\tauthMode = config.DefaultAuthMode\n\t}\n\tfor _, allowed := range config.AuthModes {\n\t\tif authMode == allowed {\n\t\t\treturn authMode, nil\n\t\t}\n\t}\n\treturn \"\", fmt.Errorf(\"provider %s does not support auth mode %s\", provider, authMode)\n}\n\nfunc DefaultBaseURL(key string) (string, bool) {\n\tconfig, ok := FindAPIConfig(key, \"\")\n\tif !ok || strings.TrimSpace(config.BaseURL) == \"\" {\n\t\treturn \"\", false\n\t}\n\treturn config.BaseURL, true\n}\n\nfunc DefaultAPIType(key string) string {\n\tmeta, ok := catalog[key]\n\tif !ok || strings.TrimSpace(meta.DefaultAPIType) == \"\" {\n\t\treturn \"openai-completions\"\n\t}\n\treturn meta.DefaultAPIType\n}\n\nfunc ResolveBaseURL(key, apiType, requested string) (string, error) {\n\tconfig, ok := FindAPIConfig(key, apiType)\n\tif !ok {\n\t\treturn \"\", fmt.Errorf(\"provider %s does not support api type %s\", key, apiType)\n\t}\n\tif !config.EditableBaseURL {\n\t\treturn strings.TrimRight(config.BaseURL, \"/\"), nil\n\t}\n\tbaseURL := strings.TrimSpace(requested)\n\tif baseURL == \"\" {\n\t\tbaseURL = config.BaseURL\n\t}\n\tif baseURL == \"\" {\n\t\treturn \"\", fmt.Errorf(\"base url is required\")\n\t}\n\tparsed, err := url.Parse(baseURL)\n\tif err != nil || parsed.Scheme == \"\" || parsed.Host == \"\" {\n\t\treturn \"\", fmt.Errorf(\"invalid base url\")\n\t}\n\tparsed.Path = normalizeEndpointPath(config.APIType, parsed.Path)\n\tparsed.RawQuery = \"\"\n\tparsed.Fragment = \"\"\n\treturn strings.TrimRight(parsed.String(), \"/\"), nil\n}\n\nfunc normalizeEndpointPath(apiType, value string) string {\n\tpath := strings.TrimRight(value, \"/\")\n\tsuffixes := []string{}\n\tswitch apiType {\n\tcase \"openai-completions\":\n\t\tsuffixes = []string{\"/chat/completions\"}\n\tcase \"openai-responses\":\n\t\tsuffixes = []string{\"/responses\"}\n\tcase \"anthropic-messages\":\n\t\tsuffixes = []string{\"/v1/messages\", \"/messages\"}\n\t}\n\tfor _, suffix := range suffixes {\n\t\tif strings.HasSuffix(strings.ToLower(path), suffix) {\n\t\t\treturn path[:len(path)-len(suffix)]\n\t\t}\n\t}\n\treturn path\n}\n\nfunc EnvKey(key string) string {\n\tmeta, ok := catalog[key]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.EnvKey\n}\n\nfunc DisplayName(key string) string {\n\tmeta, ok := catalog[key]\n\tif !ok || strings.TrimSpace(meta.DisplayName) == \"\" {\n\t\treturn key\n\t}\n\treturn meta.DisplayName\n}\n\nfunc NormalizeModelID(provider, modelID string) string {\n\ttarget := strings.TrimLeft(strings.TrimSpace(modelID), \"/\")\n\tfor _, prefix := range legacyModelPrefixes[provider] {\n\t\tlegacyPrefix := prefix + \"/\"\n\t\tif !strings.HasPrefix(target, legacyPrefix) {\n\t\t\tcontinue\n\t\t}\n\t\tcandidate := strings.TrimSpace(strings.TrimPrefix(target, legacyPrefix))\n\t\tif candidate != \"\" {\n\t\t\treturn candidate\n\t\t}\n\t}\n\treturn target\n}\n\nvar legacyModelPrefixes = map[string][]string{\n\t\"custom\": {\"custom\"},\n\t\"vllm\": {\"custom\"},\n\t\"ollama\": {\"ollama\"},\n\t\"deepseek\": {\"deepseek\"},\n\t\"bailian-coding-plan\": {\"bailian-coding-plan\"},\n\t\"ark-coding-plan\": {\"ark-coding-plan\"},\n\t\"zai\": {\"zai\"},\n\t\"minimax\": {\"minimax\"},\n\t\"xiaomi\": {\"xiaomi\"},\n\t\"kimi\": {\"kimi\", \"moonshot\"},\n\t\"kimi-coding\": {\"kimi-coding\"},\n\t\"openai\": {\"openai\"},\n\t\"anthropic\": {\"anthropic\"},\n\t\"gemini\": {\"google\", \"gemini\"},\n\t\"moonshot\": {\"moonshot\"},\n}\n\nfunc cloneMeta(meta Meta) Meta {\n\tclone := meta\n\tclone.APIConfigs = make([]APIConfig, len(meta.APIConfigs))\n\tfor index, config := range meta.APIConfigs {\n\t\tclone.APIConfigs[index] = config\n\t\tclone.APIConfigs[index].AuthModes = append([]string(nil), config.AuthModes...)\n\t}\n\tclone.Models = append([]Model(nil), meta.Models...)\n\treturn clone\n}\n"}, "27ba50d8be3ca248c03751ba6eac2fa7ac12e8c7": {"t": 1785755377.7446628, "n": 13550, "h": "e78c8e58b9d1af73", "c": "package provider\n\nimport (\n\t\"strings\"\n)\n\ntype Model struct {\n\tID string\n\tName string\n\tContextWindow int\n\tMaxTokens int\n\tReasoning bool\n\tInput []string\n}\n\ntype RuntimeDefault struct {\n\tAPIType string\n\tContextWindow int\n\tMaxTokens int\n\tInput []string\n}\n\ntype Meta struct {\n\tKey string\n\tDisplayName string\n\tSort uint\n\tDefaultBaseURL string\n\tEnvKey string\n\tDefault RuntimeDefault\n\tModels []Model\n}\n\nvar catalog = map[string]Meta{\n\t\"custom\": {\n\t\tKey: \"custom\",\n\t\tDisplayName: \"Custom\",\n\t\tSort: 10,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"CUSTOM_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 128000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{},\n\t},\n\t\"ollama\": {\n\t\tKey: \"ollama\",\n\t\tDisplayName: \"Ollama\",\n\t\tSort: 15,\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-responses\",\n\t\t\tContextWindow: 160000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t},\n\t\"vllm\": {\n\t\tKey: \"vllm\",\n\t\tDisplayName: \"vLLM\",\n\t\tSort: 20,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"VLLM_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 128000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{},\n\t},\n\t\"deepseek\": {\n\t\tKey: \"deepseek\",\n\t\tDisplayName: \"DeepSeek\",\n\t\tSort: 25,\n\t\tDefaultBaseURL: \"https://api.deepseek.com/v1\",\n\t\tEnvKey: \"DEEPSEEK_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 131072,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"deepseek/deepseek-v4-flash\", Name: \"deepseek-v4-flash\"},\n\t\t\t{ID: \"deepseek/deepseek-v4-pro\", Name: \"deepseek-v4-pro\"},\n\t\t},\n\t},\n\t\"bailian-coding-plan\": {\n\t\tKey: \"bailian-coding-plan\",\n\t\tDisplayName: \"阿里云百炼 Coding Plan\",\n\t\tSort: 30,\n\t\tDefaultBaseURL: \"https://coding.dashscope.aliyuncs.com/v1\",\n\t\tEnvKey: \"QWEN_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"bailian-coding-plan/qwen3.5-plus\", Name: \"Qwen3.5-Plus\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-max\", Name: \"Qwen3-Max\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-next\", Name: \"Qwen3-Coder-Next\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-plus\", Name: \"Qwen3-Coder-Plus\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/minimax-m2.5\", Name: \"MiniMax M2.5\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/glm-5\", Name: \"GLM-5\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/kimi-k2.5\", Name: \"Kimi-k2.5\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/glm-4.7\", Name: \"GLM-4.7\", Reasoning: true},\n\t\t},\n\t},\n\t\"ark-coding-plan\": {\n\t\tKey: \"ark-coding-plan\",\n\t\tDisplayName: \"方舟 Coding Plan\",\n\t\tSort: 35,\n\t\tDefaultBaseURL: \"https://ark.cn-beijing.volces.com/api/coding/v3\",\n\t\tEnvKey: \"ARK_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 4096,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"ark-coding-plan/ark-code-latest\", Name: \"Ark Coding Plan\", ContextWindow: 256000, MaxTokens: 4096},\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-code\", Name: \"Doubao Seed Code\", ContextWindow: 256000, MaxTokens: 4096},\n\t\t\t{ID: \"ark-coding-plan/glm-4.7\", Name: \"GLM 4.7 Coding\", ContextWindow: 200000, MaxTokens: 4096},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\", ContextWindow: 256000, MaxTokens: 4096},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2.5\", Name: \"Kimi K2.5 Coding\", ContextWindow: 256000, MaxTokens: 4096},\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-code-preview-251028\", Name: \"Doubao Seed Code Preview\", ContextWindow: 256000, MaxTokens: 4096},\n\t\t},\n\t},\n\t\"zai\": {\n\t\tKey: \"zai\",\n\t\tDisplayName: \"Z.ai\",\n\t\tSort: 40,\n\t\tDefaultBaseURL: \"https://open.bigmodel.cn/api/paas/v4\",\n\t\tEnvKey: \"ZAI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 204800,\n\t\t\tMaxTokens: 131072,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"zai/glm-5\", Name: \"GLM-5\", Reasoning: true},\n\t\t\t{ID: \"zai/glm-4.7\", Name: \"GLM-4.7\", Reasoning: true},\n\t\t\t{ID: \"zai/glm-4.7-flash\", Name: \"GLM-4.7-Flash\", Reasoning: true},\n\t\t\t{ID: \"zai/glm-4.7-flashx\", Name: \"GLM-4.7-FlashX\", Reasoning: true},\n\t\t},\n\t},\n\t\"minimax\": {\n\t\tKey: \"minimax\",\n\t\tDisplayName: \"MiniMax (CN)\",\n\t\tSort: 45,\n\t\tDefaultBaseURL: \"https://api.minimaxi.com/anthropic\",\n\t\tEnvKey: \"MINIMAX_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"anthropic-messages\",\n\t\t\tContextWindow: 200000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"minimax/MiniMax-M3\", Name: \"MiniMax M3\", ContextWindow: 1000000, MaxTokens: 128000, Reasoning: true, Input: []string{\"text\", \"image\"}},\n\t\t\t{ID: \"minimax/MiniMax-M2.7\", Name: \"MiniMax M2.7\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.7-highspeed\", Name: \"MiniMax M2.7 highspeed\"},\n\t\t},\n\t},\n\t\"xiaomi\": {\n\t\tKey: \"xiaomi\",\n\t\tDisplayName: \"Xiaomi\",\n\t\tSort: 46,\n\t\tDefaultBaseURL: \"https://api.xiaomimimo.com/v1\",\n\t\tEnvKey: \"XIAOMI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 262144,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"xiaomi/mimo-v2-flash\", Name: \"Xiaomi MiMo V2 Flash\", ContextWindow: 262144, MaxTokens: 8192, Input: []string{\"text\"}},\n\t\t\t{ID: \"xiaomi/mimo-v2-pro\", Name: \"Xiaomi MiMo V2 Pro\", ContextWindow: 1048576, MaxTokens: 32000, Reasoning: true, Input: []string{\"text\"}},\n\t\t\t{ID: \"xiaomi/mimo-v2-omni\", Name: \"Xiaomi MiMo V2 Omni\", ContextWindow: 262144, MaxTokens: 32000, Reasoning: true, Input: []string{\"text\", \"image\"}},\n\t\t},\n\t},\n\t\"kimi\": {\n\t\tKey: \"kimi\",\n\t\tDisplayName: \"Kimi (CN)\",\n\t\tSort: 50,\n\t\tDefaultBaseURL: \"https://api.moonshot.cn/v1\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\", \"image\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi/kimi-k2.5\", Name: \"Kimi K2.5\", Reasoning: true},\n\t\t\t{ID: \"kimi/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"kimi/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\", Reasoning: true},\n\t\t},\n\t},\n\t\"kimi-coding\": {\n\t\tKey: \"kimi-coding\",\n\t\tDisplayName: \"Kimi Coding\",\n\t\tSort: 51,\n\t\tDefaultBaseURL: \"https://api.kimi.com/coding/\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"anthropic-messages\",\n\t\t\tContextWindow: 262144,\n\t\t\tMaxTokens: 32768,\n\t\t\tInput: []string{\"text\", \"image\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi-coding/kimi-code\", Name: \"Kimi Code\", ContextWindow: 262144, MaxTokens: 32768, Reasoning: true, Input: []string{\"text\", \"image\"}},\n\t\t\t{ID: \"kimi-coding/k2p5\", Name: \"Kimi K2.5\", ContextWindow: 262144, MaxTokens: 32768, Reasoning: true, Input: []string{\"text\", \"image\"}},\n\t\t},\n\t},\n\t\"openai\": {\n\t\tKey: \"openai\",\n\t\tDisplayName: \"OpenAI\",\n\t\tSort: 55,\n\t\tDefaultBaseURL: \"https://api.openai.com/v1\",\n\t\tEnvKey: \"OPENAI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-responses\",\n\t\t\tContextWindow: 272000,\n\t\t\tMaxTokens: 128000,\n\t\t\tInput: []string{\"text\", \"image\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"openai/gpt-5.4\", Name: \"gpt-5.4\", ContextWindow: 272000, MaxTokens: 128000, Reasoning: true, Input: []string{\"text\", \"image\"}},\n\t\t\t{ID: \"openai/gpt-5.4-pro\", Name: \"gpt-5.4-pro\", ContextWindow: 1050000, MaxTokens: 128000, Reasoning: true, Input: []string{\"text\", \"image\"}},\n\t\t\t{ID: \"openai/gpt-5.4-mini\", Name: \"gpt-5.4-mini\", ContextWindow: 400000, MaxTokens: 128000, Reasoning: true, Input: []string{\"text\", \"image\"}},\n\t\t\t{ID: \"openai/gpt-5.4-nano\", Name: \"gpt-5.4-nano\", ContextWindow: 400000, MaxTokens: 128000, Reasoning: true, Input: []string{\"text\", \"image\"}},\n\t\t},\n\t},\n\t\"openrouter\": {\n\t\tKey: \"openrouter\",\n\t\tDisplayName: \"OpenRouter\",\n\t\tSort: 56,\n\t\tDefaultBaseURL: \"https://openrouter.ai/api/v1\",\n\t\tEnvKey: \"OPENROUTER_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 128000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"openrouter/free\", Name: \"openrouter/free\"},\n\t\t\t{ID: \"openrouter/auto\", Name: \"openrouter/auto\"},\n\t\t},\n\t},\n\t\"anthropic\": {\n\t\tKey: \"anthropic\",\n\t\tDisplayName: \"Anthropic\",\n\t\tSort: 60,\n\t\tDefaultBaseURL: \"https://api.anthropic.com\",\n\t\tEnvKey: \"ANTHROPIC_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"anthropic-messages\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\", \"image\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"anthropic/claude-sonnet-4-6\", Name: \"Claude Sonnet 4.6\", Reasoning: true},\n\t\t\t{ID: \"anthropic/claude-opus-4-6\", Name: \"Claude Opus 4.6\", Reasoning: true},\n\t\t\t{ID: \"anthropic/claude-opus-4-5\", Name: \"Claude Opus 4.5\"},\n\t\t\t{ID: \"anthropic/claude-sonnet-4-5\", Name: \"Claude Sonnet 4.5\"},\n\t\t\t{ID: \"anthropic/claude-haiku-4-5\", Name: \"Claude Haiku 4.5\"},\n\t\t},\n\t},\n\t\"gemini\": {\n\t\tKey: \"gemini\",\n\t\tDisplayName: \"Gemini\",\n\t\tSort: 65,\n\t\tDefaultBaseURL: \"https://generativelanguage.googleapis.com\",\n\t\tEnvKey: \"GEMINI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\", \"image\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"google/gemini-3-flash-preview\", Name: \"Gemini 3 Flash Preview\", Reasoning: true},\n\t\t\t{ID: \"google/gemini-flash-latest\", Name: \"Gemini Flash Latest\"},\n\t\t\t{ID: \"google/gemini-3-pro-preview\", Name: \"Gemini 3 Pro Preview\", Reasoning: true},\n\t\t},\n\t},\n\t\"moonshot\": {\n\t\tKey: \"moonshot\",\n\t\tDisplayName: \"Moonshot (Global)\",\n\t\tSort: 70,\n\t\tDefaultBaseURL: \"https://api.moonshot.ai/v1\",\n\t\tEnvKey: \"MOONSHOT_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"moonshot/kimi-k2.5\", Name: \"Kimi K2.5\", Reasoning: true},\n\t\t\t{ID: \"moonshot/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"moonshot/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\", Reasoning: true},\n\t\t},\n\t},\n}\n\nfunc Get(key string) (Meta, bool) {\n\tmeta, ok := catalog[key]\n\tif !ok {\n\t\treturn Meta{}, false\n\t}\n\treturn cloneMeta(meta), true\n}\n\nfunc All() map[string]Meta {\n\tresult := make(map[string]Meta, len(catalog))\n\tfor key, meta := range catalog {\n\t\tresult[key] = cloneMeta(meta)\n\t}\n\treturn result\n}\n\nfunc DefaultBaseURL(key string) (string, bool) {\n\tmeta, ok := catalog[key]\n\tif !ok || strings.TrimSpace(meta.DefaultBaseURL) == \"\" {\n\t\treturn \"\", false\n\t}\n\treturn meta.DefaultBaseURL, true\n}\n\nfunc EnvKey(key string) string {\n\tmeta, ok := catalog[key]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.EnvKey\n}\n\nfunc DisplayName(key string) string {\n\tmeta, ok := catalog[key]\n\tif !ok {\n\t\treturn key\n\t}\n\tif strings.TrimSpace(meta.DisplayName) == \"\" {\n\t\treturn key\n\t}\n\treturn meta.DisplayName\n}\n\nfunc FindModel(key, modelID string) (Model, bool) {\n\tmeta, ok := Get(key)\n\tif !ok {\n\t\treturn Model{}, false\n\t}\n\tfor _, item := range meta.Models {\n\t\tif item.ID == modelID {\n\t\t\treturn item, true\n\t\t}\n\t}\n\treturn Model{}, false\n}\n\nfunc cloneMeta(meta Meta) Meta {\n\tclone := meta\n\tif len(meta.Default.Input) > 0 {\n\t\tclone.Default.Input = make([]string, len(meta.Default.Input))\n\t\tcopy(clone.Default.Input, meta.Default.Input)\n\t}\n\tif len(meta.Models) > 0 {\n\t\tclone.Models = make([]Model, len(meta.Models))\n\t\tfor i, item := range meta.Models {\n\t\t\tclone.Models[i] = normalizeModel(meta, item)\n\t\t}\n\t}\n\treturn clone\n}\n\nfunc normalizeModel(meta Meta, model Model) Model {\n\tclone := model\n\tclone.ID = strings.TrimSpace(clone.ID)\n\tclone.Name = strings.TrimSpace(clone.Name)\n\tif clone.Name == \"\" {\n\t\tclone.Name = clone.ID\n\t}\n\tif clone.MaxTokens <= 0 {\n\t\tclone.MaxTokens = meta.Default.MaxTokens\n\t}\n\tif clone.ContextWindow <= 0 {\n\t\tclone.ContextWindow = meta.Default.ContextWindow\n\t}\n\tif len(clone.Input) == 0 && len(meta.Default.Input) > 0 {\n\t\tclone.Input = make([]string, len(meta.Default.Input))\n\t\tcopy(clone.Input, meta.Default.Input)\n\t}\n\treturn clone\n}\n\nfunc ResolveRuntimeParams(provider, apiType string, maxTokens, contextWindow int) (string, int, int) {\n\tdefaultAPIType := \"openai-completions\"\n\tdefaultMaxTokens := 8192\n\tdefaultContextWindow := 256000\n\tif meta, ok := Get(provider); ok {\n\t\tif meta.Default.APIType != \"\" {\n\t\t\tdefaultAPIType = meta.Default.APIType\n\t\t}\n\t\tif meta.Default.MaxTokens > 0 {\n\t\t\tdefaultMaxTokens = meta.Default.MaxTokens\n\t\t}\n\t\tif meta.Default.ContextWindow > 0 {\n\t\t\tdefaultContextWindow = meta.Default.ContextWindow\n\t\t}\n\t}\n\tresolvedAPI := apiType\n\tif strings.TrimSpace(apiType) == \"\" {\n\t\tresolvedAPI = defaultAPIType\n\t}\n\tresolvedMaxTokens := defaultMaxTokens\n\tresolvedContextWindow := defaultContextWindow\n\tif maxTokens > 0 {\n\t\tresolvedMaxTokens = maxTokens\n\t}\n\tif contextWindow > 0 {\n\t\tresolvedContextWindow = contextWindow\n\t}\n\treturn resolvedAPI, resolvedMaxTokens, resolvedContextWindow\n}\n"}, "4deb2ea484b4e0b650423833adb06372a2e85a97": {"t": 1785755379.363684, "n": 13552, "h": "062de613a230dbfe", "c": "package provider\n\nimport (\n\t\"strings\"\n)\n\ntype Model struct {\n\tID string\n\tName string\n\tContextWindow int\n\tMaxTokens int\n\tReasoning bool\n\tInput []string\n}\n\ntype RuntimeDefault struct {\n\tAPIType string\n\tContextWindow int\n\tMaxTokens int\n\tInput []string\n}\n\ntype Meta struct {\n\tKey string\n\tDisplayName string\n\tSort uint\n\tDefaultBaseURL string\n\tEnvKey string\n\tDefault RuntimeDefault\n\tModels []Model\n}\n\nvar catalog = map[string]Meta{\n\t\"custom\": {\n\t\tKey: \"custom\",\n\t\tDisplayName: \"Custom\",\n\t\tSort: 10,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"CUSTOM_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 128000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{},\n\t},\n\t\"ollama\": {\n\t\tKey: \"ollama\",\n\t\tDisplayName: \"Ollama\",\n\t\tSort: 15,\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-responses\",\n\t\t\tContextWindow: 160000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t},\n\t\"vllm\": {\n\t\tKey: \"vllm\",\n\t\tDisplayName: \"vLLM\",\n\t\tSort: 20,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"VLLM_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 128000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{},\n\t},\n\t\"deepseek\": {\n\t\tKey: \"deepseek\",\n\t\tDisplayName: \"DeepSeek\",\n\t\tSort: 25,\n\t\tDefaultBaseURL: \"https://api.deepseek.com/v1\",\n\t\tEnvKey: \"DEEPSEEK_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 131072,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"deepseek/deepseek-v4-flash\", Name: \"deepseek-v4-flash\"},\n\t\t\t{ID: \"deepseek/deepseek-v4-pro\", Name: \"deepseek-v4-pro\"},\n\t\t},\n\t},\n\t\"bailian-coding-plan\": {\n\t\tKey: \"bailian-coding-plan\",\n\t\tDisplayName: \"阿里云百炼 Coding Plan\",\n\t\tSort: 30,\n\t\tDefaultBaseURL: \"https://coding.dashscope.aliyuncs.com/v1\",\n\t\tEnvKey: \"QWEN_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"bailian-coding-plan/qwen3.5-plus\", Name: \"Qwen3.5-Plus\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-max\", Name: \"Qwen3-Max\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-next\", Name: \"Qwen3-Coder-Next\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-plus\", Name: \"Qwen3-Coder-Plus\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/minimax-m2.5\", Name: \"MiniMax M2.5\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/glm-5\", Name: \"GLM-5\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/kimi-k2.5\", Name: \"Kimi-k2.5\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/glm-4.7\", Name: \"GLM-4.7\", Reasoning: true},\n\t\t},\n\t},\n\t\"ark-coding-plan\": {\n\t\tKey: \"ark-coding-plan\",\n\t\tDisplayName: \"方舟 Coding Plan\",\n\t\tSort: 35,\n\t\tDefaultBaseURL: \"https://ark.cn-beijing.volces.com/api/coding/v3\",\n\t\tEnvKey: \"ARK_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 4096,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"ark-coding-plan/ark-code-latest\", Name: \"Ark Coding Plan\", ContextWindow: 256000, MaxTokens: 4096},\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-code\", Name: \"Doubao Seed Code\", ContextWindow: 256000, MaxTokens: 4096},\n\t\t\t{ID: \"ark-coding-plan/glm-4.7\", Name: \"GLM 4.7 Coding\", ContextWindow: 200000, MaxTokens: 4096},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\", ContextWindow: 256000, MaxTokens: 4096},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2.5\", Name: \"Kimi K2.5 Coding\", ContextWindow: 256000, MaxTokens: 4096},\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-code-preview-251028\", Name: \"Doubao Seed Code Preview\", ContextWindow: 256000, MaxTokens: 4096},\n\t\t},\n\t},\n\t\"zai\": {\n\t\tKey: \"zai\",\n\t\tDisplayName: \"Z.ai\",\n\t\tSort: 40,\n\t\tDefaultBaseURL: \"https://open.bigmodel.cn/api/paas/v4\",\n\t\tEnvKey: \"ZAI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 204800,\n\t\t\tMaxTokens: 131072,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"zai/glm-5\", Name: \"GLM-5\", Reasoning: true},\n\t\t\t{ID: \"zai/glm-4.7\", Name: \"GLM-4.7\", Reasoning: true},\n\t\t\t{ID: \"zai/glm-4.7-flash\", Name: \"GLM-4.7-Flash\", Reasoning: true},\n\t\t\t{ID: \"zai/glm-4.7-flashx\", Name: \"GLM-4.7-FlashX\", Reasoning: true},\n\t\t},\n\t},\n\t\"minimax\": {\n\t\tKey: \"minimax\",\n\t\tDisplayName: \"MiniMax (CN)\",\n\t\tSort: 45,\n\t\tDefaultBaseURL: \"https://api.minimaxi.com/anthropic\",\n\t\tEnvKey: \"MINIMAX_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"anthropic-messages\",\n\t\t\tContextWindow: 200000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"minimax/MiniMax-M2.7\", Name: \"MiniMax M2.7\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.7-highspeed\", Name: \"MiniMax M2.7 highspeed\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.5\", Name: \"MiniMax M2.5\", Reasoning: true},\n\t\t\t{ID: \"minimax/MiniMax-M2.5-highspeed\", Name: \"MiniMax M2.5 highspeed\"},\n\t\t},\n\t},\n\t\"xiaomi\": {\n\t\tKey: \"xiaomi\",\n\t\tDisplayName: \"Xiaomi\",\n\t\tSort: 46,\n\t\tDefaultBaseURL: \"https://api.xiaomimimo.com/v1\",\n\t\tEnvKey: \"XIAOMI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 262144,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"xiaomi/mimo-v2-flash\", Name: \"Xiaomi MiMo V2 Flash\", ContextWindow: 262144, MaxTokens: 8192, Input: []string{\"text\"}},\n\t\t\t{ID: \"xiaomi/mimo-v2-pro\", Name: \"Xiaomi MiMo V2 Pro\", ContextWindow: 1048576, MaxTokens: 32000, Reasoning: true, Input: []string{\"text\"}},\n\t\t\t{ID: \"xiaomi/mimo-v2-omni\", Name: \"Xiaomi MiMo V2 Omni\", ContextWindow: 262144, MaxTokens: 32000, Reasoning: true, Input: []string{\"text\", \"image\"}},\n\t\t},\n\t},\n\t\"kimi\": {\n\t\tKey: \"kimi\",\n\t\tDisplayName: \"Kimi (CN)\",\n\t\tSort: 50,\n\t\tDefaultBaseURL: \"https://api.moonshot.cn/v1\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\", \"image\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi/kimi-k2.5\", Name: \"Kimi K2.5\", Reasoning: true},\n\t\t\t{ID: \"kimi/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"kimi/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\", Reasoning: true},\n\t\t},\n\t},\n\t\"kimi-coding\": {\n\t\tKey: \"kimi-coding\",\n\t\tDisplayName: \"Kimi Coding\",\n\t\tSort: 51,\n\t\tDefaultBaseURL: \"https://api.kimi.com/coding/\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"anthropic-messages\",\n\t\t\tContextWindow: 262144,\n\t\t\tMaxTokens: 32768,\n\t\t\tInput: []string{\"text\", \"image\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi-coding/kimi-code\", Name: \"Kimi Code\", ContextWindow: 262144, MaxTokens: 32768, Reasoning: true, Input: []string{\"text\", \"image\"}},\n\t\t\t{ID: \"kimi-coding/k2p5\", Name: \"Kimi K2.5\", ContextWindow: 262144, MaxTokens: 32768, Reasoning: true, Input: []string{\"text\", \"image\"}},\n\t\t},\n\t},\n\t\"openai\": {\n\t\tKey: \"openai\",\n\t\tDisplayName: \"OpenAI\",\n\t\tSort: 55,\n\t\tDefaultBaseURL: \"https://api.openai.com/v1\",\n\t\tEnvKey: \"OPENAI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-responses\",\n\t\t\tContextWindow: 272000,\n\t\t\tMaxTokens: 128000,\n\t\t\tInput: []string{\"text\", \"image\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"openai/gpt-5.4\", Name: \"gpt-5.4\", ContextWindow: 272000, MaxTokens: 128000, Reasoning: true, Input: []string{\"text\", \"image\"}},\n\t\t\t{ID: \"openai/gpt-5.4-pro\", Name: \"gpt-5.4-pro\", ContextWindow: 1050000, MaxTokens: 128000, Reasoning: true, Input: []string{\"text\", \"image\"}},\n\t\t\t{ID: \"openai/gpt-5.4-mini\", Name: \"gpt-5.4-mini\", ContextWindow: 400000, MaxTokens: 128000, Reasoning: true, Input: []string{\"text\", \"image\"}},\n\t\t\t{ID: \"openai/gpt-5.4-nano\", Name: \"gpt-5.4-nano\", ContextWindow: 400000, MaxTokens: 128000, Reasoning: true, Input: []string{\"text\", \"image\"}},\n\t\t},\n\t},\n\t\"openrouter\": {\n\t\tKey: \"openrouter\",\n\t\tDisplayName: \"OpenRouter\",\n\t\tSort: 56,\n\t\tDefaultBaseURL: \"https://openrouter.ai/api/v1\",\n\t\tEnvKey: \"OPENROUTER_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 128000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"openrouter/free\", Name: \"openrouter/free\"},\n\t\t\t{ID: \"openrouter/auto\", Name: \"openrouter/auto\"},\n\t\t},\n\t},\n\t\"anthropic\": {\n\t\tKey: \"anthropic\",\n\t\tDisplayName: \"Anthropic\",\n\t\tSort: 60,\n\t\tDefaultBaseURL: \"https://api.anthropic.com\",\n\t\tEnvKey: \"ANTHROPIC_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"anthropic-messages\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\", \"image\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"anthropic/claude-sonnet-4-6\", Name: \"Claude Sonnet 4.6\", Reasoning: true},\n\t\t\t{ID: \"anthropic/claude-opus-4-6\", Name: \"Claude Opus 4.6\", Reasoning: true},\n\t\t\t{ID: \"anthropic/claude-opus-4-5\", Name: \"Claude Opus 4.5\"},\n\t\t\t{ID: \"anthropic/claude-sonnet-4-5\", Name: \"Claude Sonnet 4.5\"},\n\t\t\t{ID: \"anthropic/claude-haiku-4-5\", Name: \"Claude Haiku 4.5\"},\n\t\t},\n\t},\n\t\"gemini\": {\n\t\tKey: \"gemini\",\n\t\tDisplayName: \"Gemini\",\n\t\tSort: 65,\n\t\tDefaultBaseURL: \"https://generativelanguage.googleapis.com\",\n\t\tEnvKey: \"GEMINI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\", \"image\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"google/gemini-3-flash-preview\", Name: \"Gemini 3 Flash Preview\", Reasoning: true},\n\t\t\t{ID: \"google/gemini-flash-latest\", Name: \"Gemini Flash Latest\"},\n\t\t\t{ID: \"google/gemini-3-pro-preview\", Name: \"Gemini 3 Pro Preview\", Reasoning: true},\n\t\t},\n\t},\n\t\"moonshot\": {\n\t\tKey: \"moonshot\",\n\t\tDisplayName: \"Moonshot (Global)\",\n\t\tSort: 70,\n\t\tDefaultBaseURL: \"https://api.moonshot.ai/v1\",\n\t\tEnvKey: \"MOONSHOT_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"moonshot/kimi-k2.5\", Name: \"Kimi K2.5\", Reasoning: true},\n\t\t\t{ID: \"moonshot/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"moonshot/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\", Reasoning: true},\n\t\t},\n\t},\n}\n\nfunc Get(key string) (Meta, bool) {\n\tmeta, ok := catalog[key]\n\tif !ok {\n\t\treturn Meta{}, false\n\t}\n\treturn cloneMeta(meta), true\n}\n\nfunc All() map[string]Meta {\n\tresult := make(map[string]Meta, len(catalog))\n\tfor key, meta := range catalog {\n\t\tresult[key] = cloneMeta(meta)\n\t}\n\treturn result\n}\n\nfunc DefaultBaseURL(key string) (string, bool) {\n\tmeta, ok := catalog[key]\n\tif !ok || strings.TrimSpace(meta.DefaultBaseURL) == \"\" {\n\t\treturn \"\", false\n\t}\n\treturn meta.DefaultBaseURL, true\n}\n\nfunc EnvKey(key string) string {\n\tmeta, ok := catalog[key]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.EnvKey\n}\n\nfunc DisplayName(key string) string {\n\tmeta, ok := catalog[key]\n\tif !ok {\n\t\treturn key\n\t}\n\tif strings.TrimSpace(meta.DisplayName) == \"\" {\n\t\treturn key\n\t}\n\treturn meta.DisplayName\n}\n\nfunc FindModel(key, modelID string) (Model, bool) {\n\tmeta, ok := Get(key)\n\tif !ok {\n\t\treturn Model{}, false\n\t}\n\tfor _, item := range meta.Models {\n\t\tif item.ID == modelID {\n\t\t\treturn item, true\n\t\t}\n\t}\n\treturn Model{}, false\n}\n\nfunc cloneMeta(meta Meta) Meta {\n\tclone := meta\n\tif len(meta.Default.Input) > 0 {\n\t\tclone.Default.Input = make([]string, len(meta.Default.Input))\n\t\tcopy(clone.Default.Input, meta.Default.Input)\n\t}\n\tif len(meta.Models) > 0 {\n\t\tclone.Models = make([]Model, len(meta.Models))\n\t\tfor i, item := range meta.Models {\n\t\t\tclone.Models[i] = normalizeModel(meta, item)\n\t\t}\n\t}\n\treturn clone\n}\n\nfunc normalizeModel(meta Meta, model Model) Model {\n\tclone := model\n\tclone.ID = strings.TrimSpace(clone.ID)\n\tclone.Name = strings.TrimSpace(clone.Name)\n\tif clone.Name == \"\" {\n\t\tclone.Name = clone.ID\n\t}\n\tif clone.MaxTokens <= 0 {\n\t\tclone.MaxTokens = meta.Default.MaxTokens\n\t}\n\tif clone.ContextWindow <= 0 {\n\t\tclone.ContextWindow = meta.Default.ContextWindow\n\t}\n\tif len(clone.Input) == 0 && len(meta.Default.Input) > 0 {\n\t\tclone.Input = make([]string, len(meta.Default.Input))\n\t\tcopy(clone.Input, meta.Default.Input)\n\t}\n\treturn clone\n}\n\nfunc ResolveRuntimeParams(provider, apiType string, maxTokens, contextWindow int) (string, int, int) {\n\tdefaultAPIType := \"openai-completions\"\n\tdefaultMaxTokens := 8192\n\tdefaultContextWindow := 256000\n\tif meta, ok := Get(provider); ok {\n\t\tif meta.Default.APIType != \"\" {\n\t\t\tdefaultAPIType = meta.Default.APIType\n\t\t}\n\t\tif meta.Default.MaxTokens > 0 {\n\t\t\tdefaultMaxTokens = meta.Default.MaxTokens\n\t\t}\n\t\tif meta.Default.ContextWindow > 0 {\n\t\t\tdefaultContextWindow = meta.Default.ContextWindow\n\t\t}\n\t}\n\tresolvedAPI := apiType\n\tif strings.TrimSpace(apiType) == \"\" {\n\t\tresolvedAPI = defaultAPIType\n\t}\n\tresolvedMaxTokens := defaultMaxTokens\n\tresolvedContextWindow := defaultContextWindow\n\tif maxTokens > 0 {\n\t\tresolvedMaxTokens = maxTokens\n\t}\n\tif contextWindow > 0 {\n\t\tresolvedContextWindow = contextWindow\n\t}\n\treturn resolvedAPI, resolvedMaxTokens, resolvedContextWindow\n}\n"}, "4c2694591050d22c13f48f5c4f3bcb380c8e00ed": {"t": 1785755380.8133569, "n": 13606, "h": "589e617e6dc85389", "c": "package provider\n\nimport (\n\t\"strings\"\n)\n\ntype Model struct {\n\tID string\n\tName string\n\tContextWindow int\n\tMaxTokens int\n\tReasoning bool\n\tInput []string\n}\n\ntype RuntimeDefault struct {\n\tAPIType string\n\tContextWindow int\n\tMaxTokens int\n\tInput []string\n}\n\ntype Meta struct {\n\tKey string\n\tDisplayName string\n\tSort uint\n\tDefaultBaseURL string\n\tEnvKey string\n\tDefault RuntimeDefault\n\tModels []Model\n}\n\nvar catalog = map[string]Meta{\n\t\"custom\": {\n\t\tKey: \"custom\",\n\t\tDisplayName: \"Custom\",\n\t\tSort: 10,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"CUSTOM_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 128000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{},\n\t},\n\t\"ollama\": {\n\t\tKey: \"ollama\",\n\t\tDisplayName: \"Ollama\",\n\t\tSort: 15,\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-responses\",\n\t\t\tContextWindow: 160000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t},\n\t\"vllm\": {\n\t\tKey: \"vllm\",\n\t\tDisplayName: \"vLLM\",\n\t\tSort: 20,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"VLLM_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 128000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{},\n\t},\n\t\"deepseek\": {\n\t\tKey: \"deepseek\",\n\t\tDisplayName: \"DeepSeek\",\n\t\tSort: 25,\n\t\tDefaultBaseURL: \"https://api.deepseek.com/v1\",\n\t\tEnvKey: \"DEEPSEEK_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 131072,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"deepseek/deepseek-chat\", Name: \"DeepSeek Chat\"},\n\t\t\t{ID: \"deepseek/deepseek-reasoner\", Name: \"DeepSeek Reasoner\", MaxTokens: 65536, ContextWindow: 131072, Reasoning: true},\n\t\t},\n\t},\n\t\"bailian-coding-plan\": {\n\t\tKey: \"bailian-coding-plan\",\n\t\tDisplayName: \"阿里云百炼 Coding Plan\",\n\t\tSort: 30,\n\t\tDefaultBaseURL: \"https://coding.dashscope.aliyuncs.com/v1\",\n\t\tEnvKey: \"QWEN_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"bailian-coding-plan/qwen3.5-plus\", Name: \"Qwen3.5-Plus\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-max\", Name: \"Qwen3-Max\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-next\", Name: \"Qwen3-Coder-Next\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-plus\", Name: \"Qwen3-Coder-Plus\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/minimax-m2.5\", Name: \"MiniMax M2.5\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/glm-5\", Name: \"GLM-5\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/kimi-k2.5\", Name: \"Kimi-k2.5\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/glm-4.7\", Name: \"GLM-4.7\", Reasoning: true},\n\t\t},\n\t},\n\t\"ark-coding-plan\": {\n\t\tKey: \"ark-coding-plan\",\n\t\tDisplayName: \"方舟 Coding Plan\",\n\t\tSort: 35,\n\t\tDefaultBaseURL: \"https://ark.cn-beijing.volces.com/api/coding/v3\",\n\t\tEnvKey: \"ARK_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 4096,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"ark-coding-plan/ark-code-latest\", Name: \"Ark Coding Plan\", ContextWindow: 256000, MaxTokens: 4096},\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-code\", Name: \"Doubao Seed Code\", ContextWindow: 256000, MaxTokens: 4096},\n\t\t\t{ID: \"ark-coding-plan/glm-4.7\", Name: \"GLM 4.7 Coding\", ContextWindow: 200000, MaxTokens: 4096},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\", ContextWindow: 256000, MaxTokens: 4096},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2.5\", Name: \"Kimi K2.5 Coding\", ContextWindow: 256000, MaxTokens: 4096},\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-code-preview-251028\", Name: \"Doubao Seed Code Preview\", ContextWindow: 256000, MaxTokens: 4096},\n\t\t},\n\t},\n\t\"zai\": {\n\t\tKey: \"zai\",\n\t\tDisplayName: \"Z.ai\",\n\t\tSort: 40,\n\t\tDefaultBaseURL: \"https://open.bigmodel.cn/api/paas/v4\",\n\t\tEnvKey: \"ZAI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 204800,\n\t\t\tMaxTokens: 131072,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"zai/glm-5\", Name: \"GLM-5\", Reasoning: true},\n\t\t\t{ID: \"zai/glm-4.7\", Name: \"GLM-4.7\", Reasoning: true},\n\t\t\t{ID: \"zai/glm-4.7-flash\", Name: \"GLM-4.7-Flash\", Reasoning: true},\n\t\t\t{ID: \"zai/glm-4.7-flashx\", Name: \"GLM-4.7-FlashX\", Reasoning: true},\n\t\t},\n\t},\n\t\"minimax\": {\n\t\tKey: \"minimax\",\n\t\tDisplayName: \"MiniMax (CN)\",\n\t\tSort: 45,\n\t\tDefaultBaseURL: \"https://api.minimaxi.com/anthropic\",\n\t\tEnvKey: \"MINIMAX_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"anthropic-messages\",\n\t\t\tContextWindow: 200000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"minimax/MiniMax-M2.7\", Name: \"MiniMax M2.7\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.7-highspeed\", Name: \"MiniMax M2.7 highspeed\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.5\", Name: \"MiniMax M2.5\", Reasoning: true},\n\t\t\t{ID: \"minimax/MiniMax-M2.5-highspeed\", Name: \"MiniMax M2.5 highspeed\"},\n\t\t},\n\t},\n\t\"xiaomi\": {\n\t\tKey: \"xiaomi\",\n\t\tDisplayName: \"Xiaomi\",\n\t\tSort: 46,\n\t\tDefaultBaseURL: \"https://api.xiaomimimo.com/v1\",\n\t\tEnvKey: \"XIAOMI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 262144,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"xiaomi/mimo-v2-flash\", Name: \"Xiaomi MiMo V2 Flash\", ContextWindow: 262144, MaxTokens: 8192, Input: []string{\"text\"}},\n\t\t\t{ID: \"xiaomi/mimo-v2-pro\", Name: \"Xiaomi MiMo V2 Pro\", ContextWindow: 1048576, MaxTokens: 32000, Reasoning: true, Input: []string{\"text\"}},\n\t\t\t{ID: \"xiaomi/mimo-v2-omni\", Name: \"Xiaomi MiMo V2 Omni\", ContextWindow: 262144, MaxTokens: 32000, Reasoning: true, Input: []string{\"text\", \"image\"}},\n\t\t},\n\t},\n\t\"kimi\": {\n\t\tKey: \"kimi\",\n\t\tDisplayName: \"Kimi (CN)\",\n\t\tSort: 50,\n\t\tDefaultBaseURL: \"https://api.moonshot.cn/v1\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\", \"image\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi/kimi-k2.5\", Name: \"Kimi K2.5\", Reasoning: true},\n\t\t\t{ID: \"kimi/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"kimi/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\", Reasoning: true},\n\t\t},\n\t},\n\t\"kimi-coding\": {\n\t\tKey: \"kimi-coding\",\n\t\tDisplayName: \"Kimi Coding\",\n\t\tSort: 51,\n\t\tDefaultBaseURL: \"https://api.kimi.com/coding/\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"anthropic-messages\",\n\t\t\tContextWindow: 262144,\n\t\t\tMaxTokens: 32768,\n\t\t\tInput: []string{\"text\", \"image\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi-coding/kimi-code\", Name: \"Kimi Code\", ContextWindow: 262144, MaxTokens: 32768, Reasoning: true, Input: []string{\"text\", \"image\"}},\n\t\t\t{ID: \"kimi-coding/k2p5\", Name: \"Kimi K2.5\", ContextWindow: 262144, MaxTokens: 32768, Reasoning: true, Input: []string{\"text\", \"image\"}},\n\t\t},\n\t},\n\t\"openai\": {\n\t\tKey: \"openai\",\n\t\tDisplayName: \"OpenAI\",\n\t\tSort: 55,\n\t\tDefaultBaseURL: \"https://api.openai.com/v1\",\n\t\tEnvKey: \"OPENAI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-responses\",\n\t\t\tContextWindow: 272000,\n\t\t\tMaxTokens: 128000,\n\t\t\tInput: []string{\"text\", \"image\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"openai/gpt-5.4\", Name: \"gpt-5.4\", ContextWindow: 272000, MaxTokens: 128000, Reasoning: true, Input: []string{\"text\", \"image\"}},\n\t\t\t{ID: \"openai/gpt-5.4-pro\", Name: \"gpt-5.4-pro\", ContextWindow: 1050000, MaxTokens: 128000, Reasoning: true, Input: []string{\"text\", \"image\"}},\n\t\t\t{ID: \"openai/gpt-5.4-mini\", Name: \"gpt-5.4-mini\", ContextWindow: 400000, MaxTokens: 128000, Reasoning: true, Input: []string{\"text\", \"image\"}},\n\t\t\t{ID: \"openai/gpt-5.4-nano\", Name: \"gpt-5.4-nano\", ContextWindow: 400000, MaxTokens: 128000, Reasoning: true, Input: []string{\"text\", \"image\"}},\n\t\t},\n\t},\n\t\"openrouter\": {\n\t\tKey: \"openrouter\",\n\t\tDisplayName: \"OpenRouter\",\n\t\tSort: 56,\n\t\tDefaultBaseURL: \"https://openrouter.ai/api/v1\",\n\t\tEnvKey: \"OPENROUTER_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 128000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"openrouter/free\", Name: \"openrouter/free\"},\n\t\t\t{ID: \"openrouter/auto\", Name: \"openrouter/auto\"},\n\t\t},\n\t},\n\t\"anthropic\": {\n\t\tKey: \"anthropic\",\n\t\tDisplayName: \"Anthropic\",\n\t\tSort: 60,\n\t\tDefaultBaseURL: \"https://api.anthropic.com\",\n\t\tEnvKey: \"ANTHROPIC_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"anthropic-messages\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\", \"image\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"anthropic/claude-sonnet-4-6\", Name: \"Claude Sonnet 4.6\", Reasoning: true},\n\t\t\t{ID: \"anthropic/claude-opus-4-6\", Name: \"Claude Opus 4.6\", Reasoning: true},\n\t\t\t{ID: \"anthropic/claude-opus-4-5\", Name: \"Claude Opus 4.5\"},\n\t\t\t{ID: \"anthropic/claude-sonnet-4-5\", Name: \"Claude Sonnet 4.5\"},\n\t\t\t{ID: \"anthropic/claude-haiku-4-5\", Name: \"Claude Haiku 4.5\"},\n\t\t},\n\t},\n\t\"gemini\": {\n\t\tKey: \"gemini\",\n\t\tDisplayName: \"Gemini\",\n\t\tSort: 65,\n\t\tDefaultBaseURL: \"https://generativelanguage.googleapis.com\",\n\t\tEnvKey: \"GEMINI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\", \"image\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"google/gemini-3-flash-preview\", Name: \"Gemini 3 Flash Preview\", Reasoning: true},\n\t\t\t{ID: \"google/gemini-flash-latest\", Name: \"Gemini Flash Latest\"},\n\t\t\t{ID: \"google/gemini-3-pro-preview\", Name: \"Gemini 3 Pro Preview\", Reasoning: true},\n\t\t},\n\t},\n\t\"moonshot\": {\n\t\tKey: \"moonshot\",\n\t\tDisplayName: \"Moonshot (Global)\",\n\t\tSort: 70,\n\t\tDefaultBaseURL: \"https://api.moonshot.ai/v1\",\n\t\tEnvKey: \"MOONSHOT_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"moonshot/kimi-k2.5\", Name: \"Kimi K2.5\", Reasoning: true},\n\t\t\t{ID: \"moonshot/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"moonshot/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\", Reasoning: true},\n\t\t},\n\t},\n}\n\nfunc Get(key string) (Meta, bool) {\n\tmeta, ok := catalog[key]\n\tif !ok {\n\t\treturn Meta{}, false\n\t}\n\treturn cloneMeta(meta), true\n}\n\nfunc All() map[string]Meta {\n\tresult := make(map[string]Meta, len(catalog))\n\tfor key, meta := range catalog {\n\t\tresult[key] = cloneMeta(meta)\n\t}\n\treturn result\n}\n\nfunc DefaultBaseURL(key string) (string, bool) {\n\tmeta, ok := catalog[key]\n\tif !ok || strings.TrimSpace(meta.DefaultBaseURL) == \"\" {\n\t\treturn \"\", false\n\t}\n\treturn meta.DefaultBaseURL, true\n}\n\nfunc EnvKey(key string) string {\n\tmeta, ok := catalog[key]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.EnvKey\n}\n\nfunc DisplayName(key string) string {\n\tmeta, ok := catalog[key]\n\tif !ok {\n\t\treturn key\n\t}\n\tif strings.TrimSpace(meta.DisplayName) == \"\" {\n\t\treturn key\n\t}\n\treturn meta.DisplayName\n}\n\nfunc FindModel(key, modelID string) (Model, bool) {\n\tmeta, ok := Get(key)\n\tif !ok {\n\t\treturn Model{}, false\n\t}\n\tfor _, item := range meta.Models {\n\t\tif item.ID == modelID {\n\t\t\treturn item, true\n\t\t}\n\t}\n\treturn Model{}, false\n}\n\nfunc cloneMeta(meta Meta) Meta {\n\tclone := meta\n\tif len(meta.Default.Input) > 0 {\n\t\tclone.Default.Input = make([]string, len(meta.Default.Input))\n\t\tcopy(clone.Default.Input, meta.Default.Input)\n\t}\n\tif len(meta.Models) > 0 {\n\t\tclone.Models = make([]Model, len(meta.Models))\n\t\tfor i, item := range meta.Models {\n\t\t\tclone.Models[i] = normalizeModel(meta, item)\n\t\t}\n\t}\n\treturn clone\n}\n\nfunc normalizeModel(meta Meta, model Model) Model {\n\tclone := model\n\tclone.ID = strings.TrimSpace(clone.ID)\n\tclone.Name = strings.TrimSpace(clone.Name)\n\tif clone.Name == \"\" {\n\t\tclone.Name = clone.ID\n\t}\n\tif clone.MaxTokens <= 0 {\n\t\tclone.MaxTokens = meta.Default.MaxTokens\n\t}\n\tif clone.ContextWindow <= 0 {\n\t\tclone.ContextWindow = meta.Default.ContextWindow\n\t}\n\tif len(clone.Input) == 0 && len(meta.Default.Input) > 0 {\n\t\tclone.Input = make([]string, len(meta.Default.Input))\n\t\tcopy(clone.Input, meta.Default.Input)\n\t}\n\treturn clone\n}\n\nfunc ResolveRuntimeParams(provider, apiType string, maxTokens, contextWindow int) (string, int, int) {\n\tdefaultAPIType := \"openai-completions\"\n\tdefaultMaxTokens := 8192\n\tdefaultContextWindow := 256000\n\tif meta, ok := Get(provider); ok {\n\t\tif meta.Default.APIType != \"\" {\n\t\t\tdefaultAPIType = meta.Default.APIType\n\t\t}\n\t\tif meta.Default.MaxTokens > 0 {\n\t\t\tdefaultMaxTokens = meta.Default.MaxTokens\n\t\t}\n\t\tif meta.Default.ContextWindow > 0 {\n\t\t\tdefaultContextWindow = meta.Default.ContextWindow\n\t\t}\n\t}\n\tresolvedAPI := apiType\n\tif strings.TrimSpace(apiType) == \"\" {\n\t\tresolvedAPI = defaultAPIType\n\t}\n\tresolvedMaxTokens := defaultMaxTokens\n\tresolvedContextWindow := defaultContextWindow\n\tif maxTokens > 0 {\n\t\tresolvedMaxTokens = maxTokens\n\t}\n\tif contextWindow > 0 {\n\t\tresolvedContextWindow = contextWindow\n\t}\n\treturn resolvedAPI, resolvedMaxTokens, resolvedContextWindow\n}\n"}, "42f6e9a9a65a50d40f17427910ca114ac96042d6": {"t": 1785755382.8729029, "n": 12977, "h": "10b6ab1a932ff323", "c": "package provider\n\nimport (\n\t\"strings\"\n)\n\ntype Model struct {\n\tID string\n\tName string\n\tContextWindow int\n\tMaxTokens int\n\tReasoning bool\n\tInput []string\n}\n\ntype RuntimeDefault struct {\n\tAPIType string\n\tContextWindow int\n\tMaxTokens int\n\tInput []string\n}\n\ntype Meta struct {\n\tKey string\n\tDisplayName string\n\tSort uint\n\tDefaultBaseURL string\n\tEnvKey string\n\tDefault RuntimeDefault\n\tModels []Model\n}\n\nvar catalog = map[string]Meta{\n\t\"custom\": {\n\t\tKey: \"custom\",\n\t\tDisplayName: \"Custom\",\n\t\tSort: 10,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"CUSTOM_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 128000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{},\n\t},\n\t\"ollama\": {\n\t\tKey: \"ollama\",\n\t\tDisplayName: \"Ollama\",\n\t\tSort: 15,\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-responses\",\n\t\t\tContextWindow: 160000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t},\n\t\"vllm\": {\n\t\tKey: \"vllm\",\n\t\tDisplayName: \"vLLM\",\n\t\tSort: 20,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"VLLM_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 128000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{},\n\t},\n\t\"deepseek\": {\n\t\tKey: \"deepseek\",\n\t\tDisplayName: \"DeepSeek\",\n\t\tSort: 25,\n\t\tDefaultBaseURL: \"https://api.deepseek.com/v1\",\n\t\tEnvKey: \"DEEPSEEK_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 128000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"deepseek/deepseek-chat\", Name: \"DeepSeek Chat\"},\n\t\t\t{ID: \"deepseek/deepseek-reasoner\", Name: \"DeepSeek Reasoner\", Reasoning: true},\n\t\t\t{ID: \"deepseek/deepseek-r1:1.5b\", Name: \"DeepSeek R1 1.5B\", Reasoning: true},\n\t\t},\n\t},\n\t\"bailian-coding-plan\": {\n\t\tKey: \"bailian-coding-plan\",\n\t\tDisplayName: \"阿里云百炼 Coding Plan\",\n\t\tSort: 30,\n\t\tDefaultBaseURL: \"https://coding.dashscope.aliyuncs.com/v1\",\n\t\tEnvKey: \"QWEN_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"bailian-coding-plan/qwen3.5-plus\", Name: \"Qwen3.5-Plus\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-max\", Name: \"Qwen3-Max\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-next\", Name: \"Qwen3-Coder-Next\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-plus\", Name: \"Qwen3-Coder-Plus\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/minimax-m2.5\", Name: \"MiniMax M2.5\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/glm-5\", Name: \"GLM-5\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/kimi-k2.5\", Name: \"Kimi-k2.5\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/glm-4.7\", Name: \"GLM-4.7\", Reasoning: true},\n\t\t},\n\t},\n\t\"ark-coding-plan\": {\n\t\tKey: \"ark-coding-plan\",\n\t\tDisplayName: \"方舟 Coding Plan\",\n\t\tSort: 35,\n\t\tDefaultBaseURL: \"https://ark.cn-beijing.volces.com/api/coding/v3\",\n\t\tEnvKey: \"ARK_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-2.0-code\", Name: \"Doubao-Seed-2.0-Code\"},\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-code\", Name: \"Doubao-Seed-Code\"},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2.5\", Name: \"Kimi-K2.5\", Reasoning: true},\n\t\t\t{ID: \"ark-coding-plan/glm-4.7\", Name: \"GLM-4.7\", Reasoning: true},\n\t\t\t{ID: \"ark-coding-plan/deepseek-v3.2\", Name: \"DeepSeek-V3.2\", Reasoning: true},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2-thinking\", Name: \"Kimi-K2-thinking\", Reasoning: true},\n\t\t},\n\t},\n\t\"zai\": {\n\t\tKey: \"zai\",\n\t\tDisplayName: \"Z.ai\",\n\t\tSort: 40,\n\t\tDefaultBaseURL: \"https://open.bigmodel.cn/api/paas/v4\",\n\t\tEnvKey: \"ZAI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 204800,\n\t\t\tMaxTokens: 131072,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"zai/glm-5\", Name: \"GLM-5\", Reasoning: true},\n\t\t\t{ID: \"zai/glm-4.7\", Name: \"GLM-4.7\", Reasoning: true},\n\t\t\t{ID: \"zai/glm-4.7-flash\", Name: \"GLM-4.7-Flash\", Reasoning: true},\n\t\t\t{ID: \"zai/glm-4.7-flashx\", Name: \"GLM-4.7-FlashX\", Reasoning: true},\n\t\t},\n\t},\n\t\"minimax\": {\n\t\tKey: \"minimax\",\n\t\tDisplayName: \"MiniMax (CN)\",\n\t\tSort: 45,\n\t\tDefaultBaseURL: \"https://api.minimaxi.com/anthropic\",\n\t\tEnvKey: \"MINIMAX_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"anthropic-messages\",\n\t\t\tContextWindow: 200000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"minimax/MiniMax-M2.7\", Name: \"MiniMax M2.7\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.7-highspeed\", Name: \"MiniMax M2.7 highspeed\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.5\", Name: \"MiniMax M2.5\", Reasoning: true},\n\t\t\t{ID: \"minimax/MiniMax-M2.5-highspeed\", Name: \"MiniMax M2.5 highspeed\"},\n\t\t},\n\t},\n\t\"xiaomi\": {\n\t\tKey: \"xiaomi\",\n\t\tDisplayName: \"Xiaomi\",\n\t\tSort: 46,\n\t\tDefaultBaseURL: \"https://api.xiaomimimo.com/anthropic\",\n\t\tEnvKey: \"XIAOMI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"anthropic-messages\",\n\t\t\tContextWindow: 262144,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"xiaomi/mimo-v2-pro\", Name: \"Xiaomi MiMo V2 Pro\"},\n\t\t\t{ID: \"xiaomi/mimo-v2-omni\", Name: \"Xiaomi MiMo V2 Omni\"},\n\t\t\t{ID: \"xiaomi/mimo-v2-tts\", Name: \"Xiaomi MiMo V2 TTS\"},\n\t\t\t{ID: \"xiaomi/mimo-v2-flash\", Name: \"Xiaomi MiMo V2 Flash\"},\n\t\t},\n\t},\n\t\"kimi\": {\n\t\tKey: \"kimi\",\n\t\tDisplayName: \"Kimi (CN)\",\n\t\tSort: 50,\n\t\tDefaultBaseURL: \"https://api.moonshot.cn/v1\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\", \"image\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi/kimi-k2.5\", Name: \"Kimi K2.5\", Reasoning: true},\n\t\t\t{ID: \"kimi/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"kimi/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\", Reasoning: true},\n\t\t},\n\t},\n\t\"kimi-coding\": {\n\t\tKey: \"kimi-coding\",\n\t\tDisplayName: \"Kimi Coding\",\n\t\tSort: 51,\n\t\tDefaultBaseURL: \"https://api.kimi.com/coding/\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 262144,\n\t\t\tMaxTokens: 32768,\n\t\t\tInput: []string{\"text\", \"image\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi-coding/k2p5\", Name: \"Kimi K2.5\", Reasoning: true},\n\t\t},\n\t},\n\t\"openai\": {\n\t\tKey: \"openai\",\n\t\tDisplayName: \"OpenAI\",\n\t\tSort: 55,\n\t\tDefaultBaseURL: \"https://api.openai.com/v1\",\n\t\tEnvKey: \"OPENAI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\", \"image\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"openai/codex-mini-latest\", Name: \"Codex Mini\", Reasoning: true},\n\t\t\t{ID: \"openai/gpt-5\", Name: \"GPT-5\", Reasoning: true},\n\t\t\t{ID: \"openai/gpt-5-mini\", Name: \"GPT-5 Mini\", Reasoning: true},\n\t\t\t{ID: \"openai/gpt-5.4\", Name: \"GPT-5.4\", Reasoning: true},\n\t\t\t{ID: \"openai/gpt-5.3-codex\", Name: \"GPT-5.3-Codex\", Reasoning: true},\n\t\t},\n\t},\n\t\"openrouter\": {\n\t\tKey: \"openrouter\",\n\t\tDisplayName: \"OpenRouter\",\n\t\tSort: 56,\n\t\tDefaultBaseURL: \"https://openrouter.ai/api/v1\",\n\t\tEnvKey: \"OPENROUTER_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 128000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"openrouter/free\", Name: \"openrouter/free\"},\n\t\t\t{ID: \"openrouter/auto\", Name: \"openrouter/auto\"},\n\t\t},\n\t},\n\t\"anthropic\": {\n\t\tKey: \"anthropic\",\n\t\tDisplayName: \"Anthropic\",\n\t\tSort: 60,\n\t\tDefaultBaseURL: \"https://api.anthropic.com\",\n\t\tEnvKey: \"ANTHROPIC_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\", \"image\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"anthropic/claude-3-haiku-20240307\", Name: \"Claude 3 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-haiku-latest\", Name: \"Claude 3.5 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-sonnet-20241022\", Name: \"Claude 3.5 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-3-7-sonnet-20250219\", Name: \"Claude 3.7 Sonnet\", Reasoning: true},\n\t\t\t{ID: \"anthropic/claude-opus-4-1\", Name: \"Claude Opus 4.1\", Reasoning: true},\n\t\t},\n\t},\n\t\"gemini\": {\n\t\tKey: \"gemini\",\n\t\tDisplayName: \"Gemini\",\n\t\tSort: 65,\n\t\tDefaultBaseURL: \"https://generativelanguage.googleapis.com\",\n\t\tEnvKey: \"GEMINI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\", \"image\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"google/gemini-3-flash-preview\", Name: \"Gemini 3 Flash Preview\", Reasoning: true},\n\t\t\t{ID: \"google/gemini-flash-latest\", Name: \"Gemini Flash Latest\"},\n\t\t\t{ID: \"google/gemini-3-pro-preview\", Name: \"Gemini 3 Pro Preview\", Reasoning: true},\n\t\t},\n\t},\n\t\"moonshot\": {\n\t\tKey: \"moonshot\",\n\t\tDisplayName: \"Moonshot (Global)\",\n\t\tSort: 70,\n\t\tDefaultBaseURL: \"https://api.moonshot.ai/v1\",\n\t\tEnvKey: \"MOONSHOT_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"moonshot/kimi-k2.5\", Name: \"Kimi K2.5\", Reasoning: true},\n\t\t\t{ID: \"moonshot/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"moonshot/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\", Reasoning: true},\n\t\t},\n\t},\n}\n\nfunc Get(key string) (Meta, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn Meta{}, false\n\t}\n\treturn cloneMeta(meta), true\n}\n\nfunc All() map[string]Meta {\n\tresult := make(map[string]Meta, len(catalog))\n\tfor key, meta := range catalog {\n\t\tresult[key] = cloneMeta(meta)\n\t}\n\treturn result\n}\n\nfunc DefaultBaseURL(key string) (string, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok || strings.TrimSpace(meta.DefaultBaseURL) == \"\" {\n\t\treturn \"\", false\n\t}\n\treturn meta.DefaultBaseURL, true\n}\n\nfunc EnvKey(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.EnvKey\n}\n\nfunc DisplayName(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn key\n\t}\n\tif strings.TrimSpace(meta.DisplayName) == \"\" {\n\t\treturn key\n\t}\n\treturn meta.DisplayName\n}\n\nfunc FindModel(key, modelID string) (Model, bool) {\n\tmeta, ok := Get(key)\n\tif !ok {\n\t\treturn Model{}, false\n\t}\n\tfor _, item := range meta.Models {\n\t\tif item.ID == modelID {\n\t\t\treturn item, true\n\t\t}\n\t}\n\treturn Model{}, false\n}\n\nfunc cloneMeta(meta Meta) Meta {\n\tclone := meta\n\tif len(meta.Default.Input) > 0 {\n\t\tclone.Default.Input = make([]string, len(meta.Default.Input))\n\t\tcopy(clone.Default.Input, meta.Default.Input)\n\t}\n\tif len(meta.Models) > 0 {\n\t\tclone.Models = make([]Model, len(meta.Models))\n\t\tfor i, item := range meta.Models {\n\t\t\tclone.Models[i] = normalizeModel(meta, item)\n\t\t}\n\t}\n\treturn clone\n}\n\nfunc normalizeModel(meta Meta, model Model) Model {\n\tclone := model\n\tclone.ID = strings.TrimSpace(clone.ID)\n\tclone.Name = strings.TrimSpace(clone.Name)\n\tif clone.Name == \"\" {\n\t\tclone.Name = clone.ID\n\t}\n\tif clone.MaxTokens <= 0 {\n\t\tclone.MaxTokens = meta.Default.MaxTokens\n\t}\n\tif clone.ContextWindow <= 0 {\n\t\tclone.ContextWindow = meta.Default.ContextWindow\n\t}\n\tif len(clone.Input) == 0 && len(meta.Default.Input) > 0 {\n\t\tclone.Input = make([]string, len(meta.Default.Input))\n\t\tcopy(clone.Input, meta.Default.Input)\n\t}\n\treturn clone\n}\n\nfunc ResolveRuntimeParams(provider, apiType string, maxTokens, contextWindow int) (string, int, int) {\n\tdefaultAPIType := \"openai-completions\"\n\tdefaultMaxTokens := 8192\n\tdefaultContextWindow := 256000\n\tif meta, ok := Get(provider); ok {\n\t\tif meta.Default.APIType != \"\" {\n\t\t\tdefaultAPIType = meta.Default.APIType\n\t\t}\n\t\tif meta.Default.MaxTokens > 0 {\n\t\t\tdefaultMaxTokens = meta.Default.MaxTokens\n\t\t}\n\t\tif meta.Default.ContextWindow > 0 {\n\t\t\tdefaultContextWindow = meta.Default.ContextWindow\n\t\t}\n\t}\n\tresolvedAPI := apiType\n\tif strings.TrimSpace(apiType) == \"\" {\n\t\tresolvedAPI = defaultAPIType\n\t}\n\tresolvedMaxTokens := defaultMaxTokens\n\tresolvedContextWindow := defaultContextWindow\n\tif maxTokens > 0 {\n\t\tresolvedMaxTokens = maxTokens\n\t}\n\tif contextWindow > 0 {\n\t\tresolvedContextWindow = contextWindow\n\t}\n\treturn resolvedAPI, resolvedMaxTokens, resolvedContextWindow\n}\n"}, "df90286253b8536c6f02cd9e1a60ebdbb0a8cfac": {"t": 1785755384.3449337, "n": 12941, "h": "eab060c360e7c5d1", "c": "package provider\n\nimport (\n\t\"strings\"\n)\n\ntype Model struct {\n\tID string\n\tName string\n\tContextWindow int\n\tMaxTokens int\n\tReasoning bool\n\tInput []string\n}\n\ntype RuntimeDefault struct {\n\tAPIType string\n\tContextWindow int\n\tMaxTokens int\n\tInput []string\n}\n\ntype Meta struct {\n\tKey string\n\tDisplayName string\n\tSort uint\n\tDefaultBaseURL string\n\tEnvKey string\n\tDefault RuntimeDefault\n\tModels []Model\n}\n\nvar catalog = map[string]Meta{\n\t\"custom\": {\n\t\tKey: \"custom\",\n\t\tDisplayName: \"Custom\",\n\t\tSort: 10,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"CUSTOM_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 128000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{},\n\t},\n\t\"ollama\": {\n\t\tKey: \"ollama\",\n\t\tDisplayName: \"Ollama\",\n\t\tSort: 15,\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-responses\",\n\t\t\tContextWindow: 160000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t},\n\t\"vllm\": {\n\t\tKey: \"vllm\",\n\t\tDisplayName: \"vLLM\",\n\t\tSort: 20,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"VLLM_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 128000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{},\n\t},\n\t\"deepseek\": {\n\t\tKey: \"deepseek\",\n\t\tDisplayName: \"DeepSeek\",\n\t\tSort: 25,\n\t\tDefaultBaseURL: \"https://api.deepseek.com/v1\",\n\t\tEnvKey: \"DEEPSEEK_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 128000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"deepseek/deepseek-chat\", Name: \"DeepSeek Chat\"},\n\t\t\t{ID: \"deepseek/deepseek-reasoner\", Name: \"DeepSeek Reasoner\", Reasoning: true},\n\t\t\t{ID: \"deepseek/deepseek-r1:1.5b\", Name: \"DeepSeek R1 1.5B\", Reasoning: true},\n\t\t},\n\t},\n\t\"bailian-coding-plan\": {\n\t\tKey: \"bailian-coding-plan\",\n\t\tDisplayName: \"阿里云百炼 Coding Plan\",\n\t\tSort: 30,\n\t\tDefaultBaseURL: \"https://coding.dashscope.aliyuncs.com/v1\",\n\t\tEnvKey: \"QWEN_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"bailian-coding-plan/qwen3.5-plus\", Name: \"Qwen3.5-Plus\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-max\", Name: \"Qwen3-Max\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-next\", Name: \"Qwen3-Coder-Next\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-plus\", Name: \"Qwen3-Coder-Plus\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/minimax-m2.5\", Name: \"MiniMax M2.5\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/glm-5\", Name: \"GLM-5\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/kimi-k2.5\", Name: \"Kimi-k2.5\", Reasoning: true},\n\t\t\t{ID: \"bailian-coding-plan/glm-4.7\", Name: \"GLM-4.7\", Reasoning: true},\n\t\t},\n\t},\n\t\"ark-coding-plan\": {\n\t\tKey: \"ark-coding-plan\",\n\t\tDisplayName: \"方舟 Coding Plan\",\n\t\tSort: 35,\n\t\tDefaultBaseURL: \"https://ark.cn-beijing.volces.com/api/coding/v3\",\n\t\tEnvKey: \"ARK_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-2.0-code\", Name: \"Doubao-Seed-2.0-Code\"},\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-code\", Name: \"Doubao-Seed-Code\"},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2.5\", Name: \"Kimi-K2.5\", Reasoning: true},\n\t\t\t{ID: \"ark-coding-plan/glm-4.7\", Name: \"GLM-4.7\", Reasoning: true},\n\t\t\t{ID: \"ark-coding-plan/deepseek-v3.2\", Name: \"DeepSeek-V3.2\", Reasoning: true},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2-thinking\", Name: \"Kimi-K2-thinking\", Reasoning: true},\n\t\t},\n\t},\n\t\"zai\": {\n\t\tKey: \"zai\",\n\t\tDisplayName: \"Z.ai\",\n\t\tSort: 40,\n\t\tDefaultBaseURL: \"https://open.bigmodel.cn/api/paas/v4\",\n\t\tEnvKey: \"ZAI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 204800,\n\t\t\tMaxTokens: 131072,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"zai/glm-5\", Name: \"GLM-5\", Reasoning: true},\n\t\t\t{ID: \"zai/glm-4.7\", Name: \"GLM-4.7\", Reasoning: true},\n\t\t\t{ID: \"zai/glm-4.7-flash\", Name: \"GLM-4.7-Flash\", Reasoning: true},\n\t\t\t{ID: \"zai/glm-4.7-flashx\", Name: \"GLM-4.7-FlashX\", Reasoning: true},\n\t\t},\n\t},\n\t\"minimax\": {\n\t\tKey: \"minimax\",\n\t\tDisplayName: \"MiniMax (CN)\",\n\t\tSort: 45,\n\t\tDefaultBaseURL: \"https://api.minimaxi.com/anthropic\",\n\t\tEnvKey: \"MINIMAX_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"anthropic-messages\",\n\t\t\tContextWindow: 200000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"minimax/MiniMax-M2.7\", Name: \"MiniMax M2.7\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.7-highspeed\", Name: \"MiniMax M2.7 highspeed\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.5\", Name: \"MiniMax M2.5\", Reasoning: true},\n\t\t\t{ID: \"minimax/MiniMax-M2.5-highspeed\", Name: \"MiniMax M2.5 highspeed\"},\n\t\t},\n\t},\n\t\"xiaomi\": {\n\t\tKey: \"xiaomi\",\n\t\tDisplayName: \"Xiaomi\",\n\t\tSort: 46,\n\t\tDefaultBaseURL: \"https://api.xiaomimimo.com/anthropic\",\n\t\tEnvKey: \"XIAOMI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"anthropic-messages\",\n\t\t\tContextWindow: 262144,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"xiaomi/mimo-v2-pro\", Name: \"Xiaomi MiMo V2 Pro\"},\n\t\t\t{ID: \"xiaomi/mimo-v2-omni\", Name: \"Xiaomi MiMo V2 Omni\"},\n\t\t\t{ID: \"xiaomi/mimo-v2-tts\", Name: \"Xiaomi MiMo V2 TTS\"},\n\t\t\t{ID: \"xiaomi/mimo-v2-flash\", Name: \"Xiaomi MiMo V2 Flash\"},\n\t\t},\n\t},\n\t\"kimi\": {\n\t\tKey: \"kimi\",\n\t\tDisplayName: \"Kimi (CN)\",\n\t\tSort: 50,\n\t\tDefaultBaseURL: \"https://api.moonshot.cn/v1\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi/kimi-k2.5\", Name: \"Kimi K2.5\", Reasoning: true},\n\t\t\t{ID: \"kimi/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"kimi/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\", Reasoning: true},\n\t\t},\n\t},\n\t\"kimi-coding\": {\n\t\tKey: \"kimi-coding\",\n\t\tDisplayName: \"Kimi Coding\",\n\t\tSort: 51,\n\t\tDefaultBaseURL: \"https://api.kimi.com/coding/\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 262144,\n\t\t\tMaxTokens: 32768,\n\t\t\tInput: []string{\"text\", \"image\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi-coding/k2p5\", Name: \"Kimi K2.5\", Reasoning: true},\n\t\t},\n\t},\n\t\"openai\": {\n\t\tKey: \"openai\",\n\t\tDisplayName: \"OpenAI\",\n\t\tSort: 55,\n\t\tDefaultBaseURL: \"https://api.openai.com/v1\",\n\t\tEnvKey: \"OPENAI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"openai/codex-mini-latest\", Name: \"Codex Mini\", Reasoning: true},\n\t\t\t{ID: \"openai/gpt-5\", Name: \"GPT-5\", Reasoning: true},\n\t\t\t{ID: \"openai/gpt-5-mini\", Name: \"GPT-5 Mini\", Reasoning: true},\n\t\t\t{ID: \"openai/gpt-5.4\", Name: \"GPT-5.4\", Reasoning: true},\n\t\t\t{ID: \"openai/gpt-5.3-codex\", Name: \"GPT-5.3-Codex\", Reasoning: true},\n\t\t},\n\t},\n\t\"openrouter\": {\n\t\tKey: \"openrouter\",\n\t\tDisplayName: \"OpenRouter\",\n\t\tSort: 56,\n\t\tDefaultBaseURL: \"https://openrouter.ai/api/v1\",\n\t\tEnvKey: \"OPENROUTER_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 128000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"openrouter/free\", Name: \"openrouter/free\"},\n\t\t\t{ID: \"openrouter/auto\", Name: \"openrouter/auto\"},\n\t\t},\n\t},\n\t\"anthropic\": {\n\t\tKey: \"anthropic\",\n\t\tDisplayName: \"Anthropic\",\n\t\tSort: 60,\n\t\tDefaultBaseURL: \"https://api.anthropic.com\",\n\t\tEnvKey: \"ANTHROPIC_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"anthropic/claude-3-haiku-20240307\", Name: \"Claude 3 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-haiku-latest\", Name: \"Claude 3.5 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-sonnet-20241022\", Name: \"Claude 3.5 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-3-7-sonnet-20250219\", Name: \"Claude 3.7 Sonnet\", Reasoning: true},\n\t\t\t{ID: \"anthropic/claude-opus-4-1\", Name: \"Claude Opus 4.1\", Reasoning: true},\n\t\t},\n\t},\n\t\"gemini\": {\n\t\tKey: \"gemini\",\n\t\tDisplayName: \"Gemini\",\n\t\tSort: 65,\n\t\tDefaultBaseURL: \"https://generativelanguage.googleapis.com\",\n\t\tEnvKey: \"GEMINI_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"google/gemini-3-flash-preview\", Name: \"Gemini 3 Flash Preview\", Reasoning: true},\n\t\t\t{ID: \"google/gemini-flash-latest\", Name: \"Gemini Flash Latest\"},\n\t\t\t{ID: \"google/gemini-3-pro-preview\", Name: \"Gemini 3 Pro Preview\", Reasoning: true},\n\t\t},\n\t},\n\t\"moonshot\": {\n\t\tKey: \"moonshot\",\n\t\tDisplayName: \"Moonshot (Global)\",\n\t\tSort: 70,\n\t\tDefaultBaseURL: \"https://api.moonshot.ai/v1\",\n\t\tEnvKey: \"MOONSHOT_API_KEY\",\n\t\tDefault: RuntimeDefault{\n\t\t\tAPIType: \"openai-completions\",\n\t\t\tContextWindow: 256000,\n\t\t\tMaxTokens: 8192,\n\t\t\tInput: []string{\"text\"},\n\t\t},\n\t\tModels: []Model{\n\t\t\t{ID: \"moonshot/kimi-k2.5\", Name: \"Kimi K2.5\", Reasoning: true},\n\t\t\t{ID: \"moonshot/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"moonshot/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\", Reasoning: true},\n\t\t},\n\t},\n}\n\nfunc Get(key string) (Meta, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn Meta{}, false\n\t}\n\treturn cloneMeta(meta), true\n}\n\nfunc All() map[string]Meta {\n\tresult := make(map[string]Meta, len(catalog))\n\tfor key, meta := range catalog {\n\t\tresult[key] = cloneMeta(meta)\n\t}\n\treturn result\n}\n\nfunc DefaultBaseURL(key string) (string, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok || strings.TrimSpace(meta.DefaultBaseURL) == \"\" {\n\t\treturn \"\", false\n\t}\n\treturn meta.DefaultBaseURL, true\n}\n\nfunc EnvKey(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.EnvKey\n}\n\nfunc DisplayName(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn key\n\t}\n\tif strings.TrimSpace(meta.DisplayName) == \"\" {\n\t\treturn key\n\t}\n\treturn meta.DisplayName\n}\n\nfunc FindModel(key, modelID string) (Model, bool) {\n\tmeta, ok := Get(key)\n\tif !ok {\n\t\treturn Model{}, false\n\t}\n\tfor _, item := range meta.Models {\n\t\tif item.ID == modelID {\n\t\t\treturn item, true\n\t\t}\n\t}\n\treturn Model{}, false\n}\n\nfunc cloneMeta(meta Meta) Meta {\n\tclone := meta\n\tif len(meta.Default.Input) > 0 {\n\t\tclone.Default.Input = make([]string, len(meta.Default.Input))\n\t\tcopy(clone.Default.Input, meta.Default.Input)\n\t}\n\tif len(meta.Models) > 0 {\n\t\tclone.Models = make([]Model, len(meta.Models))\n\t\tfor i, item := range meta.Models {\n\t\t\tclone.Models[i] = normalizeModel(meta, item)\n\t\t}\n\t}\n\treturn clone\n}\n\nfunc normalizeModel(meta Meta, model Model) Model {\n\tclone := model\n\tclone.ID = strings.TrimSpace(clone.ID)\n\tclone.Name = strings.TrimSpace(clone.Name)\n\tif clone.Name == \"\" {\n\t\tclone.Name = clone.ID\n\t}\n\tif clone.MaxTokens <= 0 {\n\t\tclone.MaxTokens = meta.Default.MaxTokens\n\t}\n\tif clone.ContextWindow <= 0 {\n\t\tclone.ContextWindow = meta.Default.ContextWindow\n\t}\n\tif len(clone.Input) == 0 && len(meta.Default.Input) > 0 {\n\t\tclone.Input = make([]string, len(meta.Default.Input))\n\t\tcopy(clone.Input, meta.Default.Input)\n\t}\n\treturn clone\n}\n\nfunc ResolveRuntimeParams(provider, apiType string, maxTokens, contextWindow int) (string, int, int) {\n\tdefaultAPIType := \"openai-completions\"\n\tdefaultMaxTokens := 8192\n\tdefaultContextWindow := 256000\n\tif meta, ok := Get(provider); ok {\n\t\tif meta.Default.APIType != \"\" {\n\t\t\tdefaultAPIType = meta.Default.APIType\n\t\t}\n\t\tif meta.Default.MaxTokens > 0 {\n\t\t\tdefaultMaxTokens = meta.Default.MaxTokens\n\t\t}\n\t\tif meta.Default.ContextWindow > 0 {\n\t\t\tdefaultContextWindow = meta.Default.ContextWindow\n\t\t}\n\t}\n\tresolvedAPI := apiType\n\tif strings.TrimSpace(apiType) == \"\" {\n\t\tresolvedAPI = defaultAPIType\n\t}\n\tresolvedMaxTokens := defaultMaxTokens\n\tresolvedContextWindow := defaultContextWindow\n\tif maxTokens > 0 {\n\t\tresolvedMaxTokens = maxTokens\n\t}\n\tif contextWindow > 0 {\n\t\tresolvedContextWindow = contextWindow\n\t}\n\treturn resolvedAPI, resolvedMaxTokens, resolvedContextWindow\n}\n"}, "59c657e403177cd98e15a9816e52523fa8558c76": {"t": 1785755385.7703044, "n": 9547, "h": "b49521146df2e9d8", "c": "package provider\n\nimport (\n\t\"strings\"\n)\n\ntype Model struct {\n\tID string\n\tName string\n\tContextWindow int\n\tMaxTokens int\n\tReasoning bool\n\tInput []string\n}\n\ntype Meta struct {\n\tKey string\n\tDisplayName string\n\tSort uint\n\tDefaultBaseURL string\n\tEnvKey string\n\tModels []Model\n}\n\nvar catalog = map[string]Meta{\n\t\"custom\": {\n\t\tKey: \"custom\",\n\t\tDisplayName: \"Custom\",\n\t\tSort: 10,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"CUSTOM_API_KEY\",\n\t\tModels: []Model{},\n\t},\n\t\"ollama\": {\n\t\tKey: \"ollama\",\n\t\tDisplayName: \"Ollama\",\n\t\tSort: 15,\n\t},\n\t\"vllm\": {\n\t\tKey: \"vllm\",\n\t\tDisplayName: \"vLLM\",\n\t\tSort: 20,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"VLLM_API_KEY\",\n\t\tModels: []Model{},\n\t},\n\t\"deepseek\": {\n\t\tKey: \"deepseek\",\n\t\tDisplayName: \"DeepSeek\",\n\t\tSort: 25,\n\t\tDefaultBaseURL: \"https://api.deepseek.com/v1\",\n\t\tEnvKey: \"DEEPSEEK_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"deepseek/deepseek-chat\", Name: \"DeepSeek Chat\"},\n\t\t\t{ID: \"deepseek/deepseek-reasoner\", Name: \"DeepSeek Reasoner\"},\n\t\t\t{ID: \"deepseek/deepseek-r1:1.5b\", Name: \"DeepSeek R1 1.5B\"},\n\t\t},\n\t},\n\t\"bailian-coding-plan\": {\n\t\tKey: \"bailian-coding-plan\",\n\t\tDisplayName: \"阿里云百炼 Coding Plan\",\n\t\tSort: 30,\n\t\tDefaultBaseURL: \"https://coding.dashscope.aliyuncs.com/v1\",\n\t\tEnvKey: \"QWEN_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"bailian-coding-plan/qwen3.5-plus\", Name: \"Qwen3.5-Plus\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-max\", Name: \"Qwen3-Max\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-next\", Name: \"Qwen3-Coder-Next\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-plus\", Name: \"Qwen3-Coder-Plus\"},\n\t\t\t{ID: \"bailian-coding-plan/minimax-m2.5\", Name: \"MiniMax M2.5\"},\n\t\t\t{ID: \"bailian-coding-plan/glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"bailian-coding-plan/kimi-k2.5\", Name: \"Kimi-k2.5\"},\n\t\t\t{ID: \"bailian-coding-plan/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t},\n\t},\n\t\"ark-coding-plan\": {\n\t\tKey: \"ark-coding-plan\",\n\t\tDisplayName: \"方舟 Coding Plan\",\n\t\tSort: 35,\n\t\tDefaultBaseURL: \"https://ark.cn-beijing.volces.com/api/coding/v3\",\n\t\tEnvKey: \"ARK_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-2.0-code\", Name: \"Doubao-Seed-2.0-Code\"},\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-code\", Name: \"Doubao-Seed-Code\"},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2.5\", Name: \"Kimi-K2.5\"},\n\t\t\t{ID: \"ark-coding-plan/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t\t{ID: \"ark-coding-plan/deepseek-v3.2\", Name: \"DeepSeek-V3.2\"},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2-thinking\", Name: \"Kimi-K2-thinking\"},\n\t\t},\n\t},\n\t\"zai\": {\n\t\tKey: \"zai\",\n\t\tDisplayName: \"Z.ai\",\n\t\tSort: 40,\n\t\tDefaultBaseURL: \"https://open.bigmodel.cn/api/paas/v4\",\n\t\tEnvKey: \"ZAI_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"zai/glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"zai/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t\t{ID: \"zai/glm-4.7-flash\", Name: \"GLM-4.7-Flash\"},\n\t\t\t{ID: \"zai/glm-4.7-flashx\", Name: \"GLM-4.7-FlashX\"},\n\t\t},\n\t},\n\t\"minimax\": {\n\t\tKey: \"minimax\",\n\t\tDisplayName: \"MiniMax (CN)\",\n\t\tSort: 45,\n\t\tDefaultBaseURL: \"https://api.minimaxi.com/anthropic\",\n\t\tEnvKey: \"MINIMAX_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"minimax/MiniMax-M2.7\", Name: \"MiniMax M2.7\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.7-highspeed\", Name: \"MiniMax M2.7 highspeed\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.5\", Name: \"MiniMax M2.5\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.5-highspeed\", Name: \"MiniMax M2.5 highspeed\"},\n\t\t},\n\t},\n\t\"xiaomi\": {\n\t\tKey: \"xiaomi\",\n\t\tDisplayName: \"Xiaomi\",\n\t\tSort: 46,\n\t\tDefaultBaseURL: \"https://api.xiaomimimo.com/anthropic\",\n\t\tEnvKey: \"XIAOMI_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"xiaomi/mimo-v2-pro\", Name: \"Xiaomi MiMo V2 Pro\", ContextWindow: 262144, MaxTokens: 8192, Reasoning: false, Input: []string{\"text\"}},\n\t\t\t{ID: \"xiaomi/mimo-v2-omni\", Name: \"Xiaomi MiMo V2 Omni\", ContextWindow: 262144, MaxTokens: 8192, Reasoning: false, Input: []string{\"text\"}},\n\t\t\t{ID: \"xiaomi/mimo-v2-tts\", Name: \"Xiaomi MiMo V2 TTS\", ContextWindow: 262144, MaxTokens: 8192, Reasoning: false, Input: []string{\"text\"}},\n\t\t\t{ID: \"xiaomi/mimo-v2-flash\", Name: \"Xiaomi MiMo V2 Flash\", ContextWindow: 262144, MaxTokens: 8192, Reasoning: false, Input: []string{\"text\"}},\n\t\t},\n\t},\n\t\"kimi\": {\n\t\tKey: \"kimi\",\n\t\tDisplayName: \"Kimi (CN)\",\n\t\tSort: 50,\n\t\tDefaultBaseURL: \"https://api.moonshot.cn/v1\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"kimi/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"kimi/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n\t\"kimi-coding\": {\n\t\tKey: \"kimi-coding\",\n\t\tDisplayName: \"Kimi Coding\",\n\t\tSort: 51,\n\t\tDefaultBaseURL: \"https://api.kimi.com/coding/\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi-coding/k2p5\", Name: \"Kimi K2.5\"},\n\t\t},\n\t},\n\t\"openai\": {\n\t\tKey: \"openai\",\n\t\tDisplayName: \"OpenAI\",\n\t\tSort: 55,\n\t\tDefaultBaseURL: \"https://api.openai.com/v1\",\n\t\tEnvKey: \"OPENAI_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"openai/codex-mini-latest\", Name: \"Codex Mini\"},\n\t\t\t{ID: \"openai/gpt-4.1\", Name: \"GPT-4.1\"},\n\t\t\t{ID: \"openai/gpt-4o\", Name: \"GPT-4o\"},\n\t\t\t{ID: \"openai/gpt-4o-mini\", Name: \"GPT-4o Mini\"},\n\t\t\t{ID: \"openai/gpt-5\", Name: \"GPT-5\"},\n\t\t\t{ID: \"openai/gpt-5-mini\", Name: \"GPT-5 Mini\"},\n\t\t},\n\t},\n\t\"openrouter\": {\n\t\tKey: \"openrouter\",\n\t\tDisplayName: \"OpenRouter\",\n\t\tSort: 56,\n\t\tDefaultBaseURL: \"https://openrouter.ai/api/v1\",\n\t\tEnvKey: \"OPENROUTER_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"openrouter/free\", Name: \"openrouter/free\"},\n\t\t\t{ID: \"openrouter/auto\", Name: \"openrouter/auto\"},\n\t\t},\n\t},\n\t\"anthropic\": {\n\t\tKey: \"anthropic\",\n\t\tDisplayName: \"Anthropic\",\n\t\tSort: 60,\n\t\tDefaultBaseURL: \"https://api.anthropic.com\",\n\t\tEnvKey: \"ANTHROPIC_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"anthropic/claude-3-haiku-20240307\", Name: \"Claude 3 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-haiku-latest\", Name: \"Claude 3.5 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-sonnet-20241022\", Name: \"Claude 3.5 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-3-7-sonnet-20250219\", Name: \"Claude 3.7 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-opus-4-1\", Name: \"Claude Opus 4.1\"},\n\t\t},\n\t},\n\t\"gemini\": {\n\t\tKey: \"gemini\",\n\t\tDisplayName: \"Gemini\",\n\t\tSort: 65,\n\t\tDefaultBaseURL: \"https://generativelanguage.googleapis.com\",\n\t\tEnvKey: \"GEMINI_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"google/gemini-3-flash-preview\", Name: \"Gemini 3 Flash Preview\"},\n\t\t\t{ID: \"google/gemini-flash-latest\", Name: \"Gemini Flash Latest\"},\n\t\t\t{ID: \"google/gemini-3-pro-preview\", Name: \"Gemini 3 Pro Preview\"},\n\t\t},\n\t},\n\t\"moonshot\": {\n\t\tKey: \"moonshot\",\n\t\tDisplayName: \"Moonshot (Global)\",\n\t\tSort: 70,\n\t\tDefaultBaseURL: \"https://api.moonshot.ai/v1\",\n\t\tEnvKey: \"MOONSHOT_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"moonshot/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"moonshot/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"moonshot/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n}\n\nfunc Get(key string) (Meta, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn Meta{}, false\n\t}\n\treturn cloneMeta(meta), true\n}\n\nfunc All() map[string]Meta {\n\tresult := make(map[string]Meta, len(catalog))\n\tfor key, meta := range catalog {\n\t\tresult[key] = cloneMeta(meta)\n\t}\n\treturn result\n}\n\nfunc DefaultBaseURL(key string) (string, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok || strings.TrimSpace(meta.DefaultBaseURL) == \"\" {\n\t\treturn \"\", false\n\t}\n\treturn meta.DefaultBaseURL, true\n}\n\nfunc EnvKey(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.EnvKey\n}\n\nfunc DisplayName(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn key\n\t}\n\tif strings.TrimSpace(meta.DisplayName) == \"\" {\n\t\treturn key\n\t}\n\treturn meta.DisplayName\n}\n\nfunc cloneMeta(meta Meta) Meta {\n\tclone := meta\n\tif len(meta.Models) > 0 {\n\t\tclone.Models = make([]Model, len(meta.Models))\n\t\tfor i, item := range meta.Models {\n\t\t\tclone.Models[i] = normalizeModel(meta.Key, item)\n\t\t}\n\t}\n\treturn clone\n}\n\nfunc normalizeModel(provider string, model Model) Model {\n\tclone := model\n\tclone.ID = strings.TrimSpace(clone.ID)\n\tclone.Name = strings.TrimSpace(clone.Name)\n\tif clone.Name == \"\" {\n\t\tclone.Name = clone.ID\n\t}\n\tif clone.MaxTokens <= 0 || clone.ContextWindow <= 0 {\n\t\tresolvedMaxTokens, resolvedContextWindow := catalogRuntimeDefaults(strings.ToLower(strings.TrimSpace(provider)))\n\t\tif clone.MaxTokens <= 0 {\n\t\t\tclone.MaxTokens = resolvedMaxTokens\n\t\t}\n\t\tif clone.ContextWindow <= 0 {\n\t\t\tclone.ContextWindow = resolvedContextWindow\n\t\t}\n\t}\n\tif len(clone.Input) == 0 {\n\t\tclone.Input = defaultModelInputs(provider)\n\t}\n\tif !clone.Reasoning {\n\t\tclone.Reasoning = isReasoningModel(clone.ID)\n\t}\n\treturn clone\n}\n\nfunc defaultModelInputs(provider string) []string {\n\tswitch strings.ToLower(strings.TrimSpace(provider)) {\n\tcase \"kimi-coding\":\n\t\treturn []string{\"text\", \"image\"}\n\tdefault:\n\t\treturn []string{\"text\"}\n\t}\n}\n\nfunc catalogRuntimeDefaults(provider string) (int, int) {\n\tswitch provider {\n\tcase \"deepseek\":\n\t\treturn 8192, 128000\n\tcase \"zai\":\n\t\treturn 131072, 204800\n\tcase \"openrouter\":\n\t\treturn 8192, 128000\n\tcase \"minimax\", \"kimi-coding\":\n\t\treturn 8192, 200000\n\tcase \"custom\", \"vllm\":\n\t\treturn 8192, 128000\n\tdefault:\n\t\treturn 8192, 256000\n\t}\n}\n"}, "57a7edf48185aa2307e2598a8ab33c8ad57a4507": {"t": 1785755387.333, "n": 8760, "h": "8aa2dc438dc4e806", "c": "package provider\n\nimport (\n\t\"strings\"\n)\n\ntype Model struct {\n\tID string\n\tName string\n\tContextWindow int\n\tMaxTokens int\n\tReasoning bool\n\tInput []string\n}\n\ntype Meta struct {\n\tKey string\n\tDisplayName string\n\tSort uint\n\tDefaultBaseURL string\n\tEnvKey string\n\tModels []Model\n}\n\nvar catalog = map[string]Meta{\n\t\"custom\": {\n\t\tKey: \"custom\",\n\t\tDisplayName: \"Custom\",\n\t\tSort: 10,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"CUSTOM_API_KEY\",\n\t\tModels: []Model{},\n\t},\n\t\"ollama\": {\n\t\tKey: \"ollama\",\n\t\tDisplayName: \"Ollama\",\n\t\tSort: 15,\n\t},\n\t\"vllm\": {\n\t\tKey: \"vllm\",\n\t\tDisplayName: \"vLLM\",\n\t\tSort: 20,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"VLLM_API_KEY\",\n\t\tModels: []Model{},\n\t},\n\t\"deepseek\": {\n\t\tKey: \"deepseek\",\n\t\tDisplayName: \"DeepSeek\",\n\t\tSort: 25,\n\t\tDefaultBaseURL: \"https://api.deepseek.com/v1\",\n\t\tEnvKey: \"DEEPSEEK_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"deepseek/deepseek-chat\", Name: \"DeepSeek Chat\"},\n\t\t\t{ID: \"deepseek/deepseek-reasoner\", Name: \"DeepSeek Reasoner\"},\n\t\t\t{ID: \"deepseek/deepseek-r1:1.5b\", Name: \"DeepSeek R1 1.5B\"},\n\t\t},\n\t},\n\t\"bailian-coding-plan\": {\n\t\tKey: \"bailian-coding-plan\",\n\t\tDisplayName: \"阿里云百炼 Coding Plan\",\n\t\tSort: 30,\n\t\tDefaultBaseURL: \"https://coding.dashscope.aliyuncs.com/v1\",\n\t\tEnvKey: \"QWEN_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"bailian-coding-plan/qwen3.5-plus\", Name: \"Qwen3.5-Plus\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-max\", Name: \"Qwen3-Max\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-next\", Name: \"Qwen3-Coder-Next\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-plus\", Name: \"Qwen3-Coder-Plus\"},\n\t\t\t{ID: \"bailian-coding-plan/minimax-m2.5\", Name: \"MiniMax M2.5\"},\n\t\t\t{ID: \"bailian-coding-plan/glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"bailian-coding-plan/kimi-k2.5\", Name: \"Kimi-k2.5\"},\n\t\t\t{ID: \"bailian-coding-plan/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t},\n\t},\n\t\"ark-coding-plan\": {\n\t\tKey: \"ark-coding-plan\",\n\t\tDisplayName: \"方舟 Coding Plan\",\n\t\tSort: 35,\n\t\tDefaultBaseURL: \"https://ark.cn-beijing.volces.com/api/coding/v3\",\n\t\tEnvKey: \"ARK_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-2.0-code\", Name: \"Doubao-Seed-2.0-Code\"},\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-code\", Name: \"Doubao-Seed-Code\"},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2.5\", Name: \"Kimi-K2.5\"},\n\t\t\t{ID: \"ark-coding-plan/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t\t{ID: \"ark-coding-plan/deepseek-v3.2\", Name: \"DeepSeek-V3.2\"},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2-thinking\", Name: \"Kimi-K2-thinking\"},\n\t\t},\n\t},\n\t\"zai\": {\n\t\tKey: \"zai\",\n\t\tDisplayName: \"Z.ai\",\n\t\tSort: 40,\n\t\tDefaultBaseURL: \"https://open.bigmodel.cn/api/paas/v4\",\n\t\tEnvKey: \"ZAI_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"zai/glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"zai/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t\t{ID: \"zai/glm-4.7-flash\", Name: \"GLM-4.7-Flash\"},\n\t\t\t{ID: \"zai/glm-4.7-flashx\", Name: \"GLM-4.7-FlashX\"},\n\t\t},\n\t},\n\t\"minimax\": {\n\t\tKey: \"minimax\",\n\t\tDisplayName: \"MiniMax (CN)\",\n\t\tSort: 45,\n\t\tDefaultBaseURL: \"https://api.minimaxi.com/anthropic\",\n\t\tEnvKey: \"MINIMAX_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"minimax/MiniMax-M2.7\", Name: \"MiniMax M2.7\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.7-highspeed\", Name: \"MiniMax M2.7 highspeed\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.5\", Name: \"MiniMax M2.5\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.5-highspeed\", Name: \"MiniMax M2.5 highspeed\"},\n\t\t},\n\t},\n\t\"kimi\": {\n\t\tKey: \"kimi\",\n\t\tDisplayName: \"Kimi (CN)\",\n\t\tSort: 50,\n\t\tDefaultBaseURL: \"https://api.moonshot.cn/v1\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"kimi/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"kimi/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n\t\"kimi-coding\": {\n\t\tKey: \"kimi-coding\",\n\t\tDisplayName: \"Kimi Coding\",\n\t\tSort: 51,\n\t\tDefaultBaseURL: \"https://api.kimi.com/coding/\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi-coding/k2p5\", Name: \"Kimi K2.5\"},\n\t\t},\n\t},\n\t\"openai\": {\n\t\tKey: \"openai\",\n\t\tDisplayName: \"OpenAI\",\n\t\tSort: 55,\n\t\tDefaultBaseURL: \"https://api.openai.com/v1\",\n\t\tEnvKey: \"OPENAI_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"openai/codex-mini-latest\", Name: \"Codex Mini\"},\n\t\t\t{ID: \"openai/gpt-4.1\", Name: \"GPT-4.1\"},\n\t\t\t{ID: \"openai/gpt-4o\", Name: \"GPT-4o\"},\n\t\t\t{ID: \"openai/gpt-4o-mini\", Name: \"GPT-4o Mini\"},\n\t\t\t{ID: \"openai/gpt-5\", Name: \"GPT-5\"},\n\t\t\t{ID: \"openai/gpt-5-mini\", Name: \"GPT-5 Mini\"},\n\t\t},\n\t},\n\t\"openrouter\": {\n\t\tKey: \"openrouter\",\n\t\tDisplayName: \"OpenRouter\",\n\t\tSort: 56,\n\t\tDefaultBaseURL: \"https://openrouter.ai/api/v1\",\n\t\tEnvKey: \"OPENROUTER_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"openrouter/free\", Name: \"openrouter/free\"},\n\t\t\t{ID: \"openrouter/auto\", Name: \"openrouter/auto\"},\n\t\t},\n\t},\n\t\"anthropic\": {\n\t\tKey: \"anthropic\",\n\t\tDisplayName: \"Anthropic\",\n\t\tSort: 60,\n\t\tDefaultBaseURL: \"https://api.anthropic.com\",\n\t\tEnvKey: \"ANTHROPIC_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"anthropic/claude-3-haiku-20240307\", Name: \"Claude 3 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-haiku-latest\", Name: \"Claude 3.5 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-sonnet-20241022\", Name: \"Claude 3.5 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-3-7-sonnet-20250219\", Name: \"Claude 3.7 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-opus-4-1\", Name: \"Claude Opus 4.1\"},\n\t\t},\n\t},\n\t\"gemini\": {\n\t\tKey: \"gemini\",\n\t\tDisplayName: \"Gemini\",\n\t\tSort: 65,\n\t\tDefaultBaseURL: \"https://generativelanguage.googleapis.com\",\n\t\tEnvKey: \"GEMINI_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"google/gemini-3-flash-preview\", Name: \"Gemini 3 Flash Preview\"},\n\t\t\t{ID: \"google/gemini-flash-latest\", Name: \"Gemini Flash Latest\"},\n\t\t\t{ID: \"google/gemini-3-pro-preview\", Name: \"Gemini 3 Pro Preview\"},\n\t\t},\n\t},\n\t\"moonshot\": {\n\t\tKey: \"moonshot\",\n\t\tDisplayName: \"Moonshot (Global)\",\n\t\tSort: 70,\n\t\tDefaultBaseURL: \"https://api.moonshot.ai/v1\",\n\t\tEnvKey: \"MOONSHOT_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"moonshot/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"moonshot/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"moonshot/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n}\n\nfunc Get(key string) (Meta, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn Meta{}, false\n\t}\n\treturn cloneMeta(meta), true\n}\n\nfunc All() map[string]Meta {\n\tresult := make(map[string]Meta, len(catalog))\n\tfor key, meta := range catalog {\n\t\tresult[key] = cloneMeta(meta)\n\t}\n\treturn result\n}\n\nfunc DefaultBaseURL(key string) (string, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok || strings.TrimSpace(meta.DefaultBaseURL) == \"\" {\n\t\treturn \"\", false\n\t}\n\treturn meta.DefaultBaseURL, true\n}\n\nfunc EnvKey(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.EnvKey\n}\n\nfunc DisplayName(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn key\n\t}\n\tif strings.TrimSpace(meta.DisplayName) == \"\" {\n\t\treturn key\n\t}\n\treturn meta.DisplayName\n}\n\nfunc cloneMeta(meta Meta) Meta {\n\tclone := meta\n\tif len(meta.Models) > 0 {\n\t\tclone.Models = make([]Model, len(meta.Models))\n\t\tfor i, item := range meta.Models {\n\t\t\tclone.Models[i] = normalizeModel(meta.Key, item)\n\t\t}\n\t}\n\treturn clone\n}\n\nfunc normalizeModel(provider string, model Model) Model {\n\tclone := model\n\tclone.ID = strings.TrimSpace(clone.ID)\n\tclone.Name = strings.TrimSpace(clone.Name)\n\tif clone.Name == \"\" {\n\t\tclone.Name = clone.ID\n\t}\n\tif clone.MaxTokens <= 0 || clone.ContextWindow <= 0 {\n\t\tresolvedMaxTokens, resolvedContextWindow := catalogRuntimeDefaults(strings.ToLower(strings.TrimSpace(provider)))\n\t\tif clone.MaxTokens <= 0 {\n\t\t\tclone.MaxTokens = resolvedMaxTokens\n\t\t}\n\t\tif clone.ContextWindow <= 0 {\n\t\t\tclone.ContextWindow = resolvedContextWindow\n\t\t}\n\t}\n\tif len(clone.Input) == 0 {\n\t\tclone.Input = defaultModelInputs(provider)\n\t}\n\tif !clone.Reasoning {\n\t\tclone.Reasoning = isReasoningModel(clone.ID)\n\t}\n\treturn clone\n}\n\nfunc defaultModelInputs(provider string) []string {\n\tswitch strings.ToLower(strings.TrimSpace(provider)) {\n\tcase \"kimi-coding\":\n\t\treturn []string{\"text\", \"image\"}\n\tdefault:\n\t\treturn []string{\"text\"}\n\t}\n}\n\nfunc catalogRuntimeDefaults(provider string) (int, int) {\n\tswitch provider {\n\tcase \"deepseek\":\n\t\treturn 8192, 128000\n\tcase \"zai\":\n\t\treturn 131072, 204800\n\tcase \"openrouter\":\n\t\treturn 8192, 128000\n\tcase \"minimax\", \"kimi-coding\":\n\t\treturn 8192, 200000\n\tcase \"custom\", \"vllm\":\n\t\treturn 8192, 128000\n\tdefault:\n\t\treturn 8192, 256000\n\t}\n}\n"}, "fa843f0940dc6e26a42176ed93f173b9d90649fe": {"t": 1785755388.6342072, "n": 8630, "h": "5bb6cbaf82ea45b6", "c": "package provider\n\nimport (\n\t\"strings\"\n)\n\ntype Model struct {\n\tID string\n\tName string\n\tContextWindow int\n\tMaxTokens int\n\tReasoning bool\n\tInput []string\n}\n\ntype Meta struct {\n\tKey string\n\tDisplayName string\n\tSort uint\n\tDefaultBaseURL string\n\tEnvKey string\n\tModels []Model\n}\n\nvar catalog = map[string]Meta{\n\t\"custom\": {\n\t\tKey: \"custom\",\n\t\tDisplayName: \"Custom\",\n\t\tSort: 10,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"CUSTOM_API_KEY\",\n\t\tModels: []Model{},\n\t},\n\t\"ollama\": {\n\t\tKey: \"ollama\",\n\t\tDisplayName: \"Ollama\",\n\t\tSort: 15,\n\t},\n\t\"vllm\": {\n\t\tKey: \"vllm\",\n\t\tDisplayName: \"vLLM\",\n\t\tSort: 20,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"VLLM_API_KEY\",\n\t\tModels: []Model{},\n\t},\n\t\"deepseek\": {\n\t\tKey: \"deepseek\",\n\t\tDisplayName: \"DeepSeek\",\n\t\tSort: 25,\n\t\tDefaultBaseURL: \"https://api.deepseek.com/v1\",\n\t\tEnvKey: \"DEEPSEEK_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"deepseek/deepseek-chat\", Name: \"DeepSeek Chat\"},\n\t\t\t{ID: \"deepseek/deepseek-reasoner\", Name: \"DeepSeek Reasoner\"},\n\t\t\t{ID: \"deepseek/deepseek-r1:1.5b\", Name: \"DeepSeek R1 1.5B\"},\n\t\t},\n\t},\n\t\"bailian-coding-plan\": {\n\t\tKey: \"bailian-coding-plan\",\n\t\tDisplayName: \"阿里云百炼 Coding Plan\",\n\t\tSort: 30,\n\t\tDefaultBaseURL: \"https://coding.dashscope.aliyuncs.com/v1\",\n\t\tEnvKey: \"QWEN_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"bailian-coding-plan/qwen3.5-plus\", Name: \"Qwen3.5-Plus\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-max\", Name: \"Qwen3-Max\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-next\", Name: \"Qwen3-Coder-Next\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-plus\", Name: \"Qwen3-Coder-Plus\"},\n\t\t\t{ID: \"bailian-coding-plan/minimax-m2.5\", Name: \"MiniMax M2.5\"},\n\t\t\t{ID: \"bailian-coding-plan/glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"bailian-coding-plan/kimi-k2.5\", Name: \"Kimi-k2.5\"},\n\t\t\t{ID: \"bailian-coding-plan/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t},\n\t},\n\t\"ark-coding-plan\": {\n\t\tKey: \"ark-coding-plan\",\n\t\tDisplayName: \"方舟 Coding Plan\",\n\t\tSort: 35,\n\t\tDefaultBaseURL: \"https://ark.cn-beijing.volces.com/api/coding/v3\",\n\t\tEnvKey: \"ARK_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-2.0-code\", Name: \"Doubao-Seed-2.0-Code\"},\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-code\", Name: \"Doubao-Seed-Code\"},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2.5\", Name: \"Kimi-K2.5\"},\n\t\t\t{ID: \"ark-coding-plan/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t\t{ID: \"ark-coding-plan/deepseek-v3.2\", Name: \"DeepSeek-V3.2\"},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2-thinking\", Name: \"Kimi-K2-thinking\"},\n\t\t},\n\t},\n\t\"zai\": {\n\t\tKey: \"zai\",\n\t\tDisplayName: \"Z.ai\",\n\t\tSort: 40,\n\t\tDefaultBaseURL: \"https://open.bigmodel.cn/api/paas/v4\",\n\t\tEnvKey: \"ZAI_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"zai/glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"zai/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t\t{ID: \"zai/glm-4.7-flash\", Name: \"GLM-4.7-Flash\"},\n\t\t\t{ID: \"zai/glm-4.7-flashx\", Name: \"GLM-4.7-FlashX\"},\n\t\t},\n\t},\n\t\"minimax\": {\n\t\tKey: \"minimax\",\n\t\tDisplayName: \"MiniMax (CN)\",\n\t\tSort: 45,\n\t\tDefaultBaseURL: \"https://api.minimaxi.com/anthropic\",\n\t\tEnvKey: \"MINIMAX_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"minimax/MiniMax-M2.5\", Name: \"MiniMax M2.5\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.5-highspeed\", Name: \"MiniMax M2.5 highspeed\"},\n\t\t},\n\t},\n\t\"kimi\": {\n\t\tKey: \"kimi\",\n\t\tDisplayName: \"Kimi (CN)\",\n\t\tSort: 50,\n\t\tDefaultBaseURL: \"https://api.moonshot.cn/v1\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"kimi/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"kimi/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n\t\"kimi-coding\": {\n\t\tKey: \"kimi-coding\",\n\t\tDisplayName: \"Kimi Coding\",\n\t\tSort: 51,\n\t\tDefaultBaseURL: \"https://api.kimi.com/coding/\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi-coding/k2p5\", Name: \"Kimi K2.5\"},\n\t\t},\n\t},\n\t\"openai\": {\n\t\tKey: \"openai\",\n\t\tDisplayName: \"OpenAI\",\n\t\tSort: 55,\n\t\tDefaultBaseURL: \"https://api.openai.com/v1\",\n\t\tEnvKey: \"OPENAI_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"openai/codex-mini-latest\", Name: \"Codex Mini\"},\n\t\t\t{ID: \"openai/gpt-4.1\", Name: \"GPT-4.1\"},\n\t\t\t{ID: \"openai/gpt-4o\", Name: \"GPT-4o\"},\n\t\t\t{ID: \"openai/gpt-4o-mini\", Name: \"GPT-4o Mini\"},\n\t\t\t{ID: \"openai/gpt-5\", Name: \"GPT-5\"},\n\t\t\t{ID: \"openai/gpt-5-mini\", Name: \"GPT-5 Mini\"},\n\t\t},\n\t},\n\t\"openrouter\": {\n\t\tKey: \"openrouter\",\n\t\tDisplayName: \"OpenRouter\",\n\t\tSort: 56,\n\t\tDefaultBaseURL: \"https://openrouter.ai/api/v1\",\n\t\tEnvKey: \"OPENROUTER_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"openrouter/free\", Name: \"openrouter/free\"},\n\t\t\t{ID: \"openrouter/auto\", Name: \"openrouter/auto\"},\n\t\t},\n\t},\n\t\"anthropic\": {\n\t\tKey: \"anthropic\",\n\t\tDisplayName: \"Anthropic\",\n\t\tSort: 60,\n\t\tDefaultBaseURL: \"https://api.anthropic.com\",\n\t\tEnvKey: \"ANTHROPIC_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"anthropic/claude-3-haiku-20240307\", Name: \"Claude 3 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-haiku-latest\", Name: \"Claude 3.5 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-sonnet-20241022\", Name: \"Claude 3.5 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-3-7-sonnet-20250219\", Name: \"Claude 3.7 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-opus-4-1\", Name: \"Claude Opus 4.1\"},\n\t\t},\n\t},\n\t\"gemini\": {\n\t\tKey: \"gemini\",\n\t\tDisplayName: \"Gemini\",\n\t\tSort: 65,\n\t\tDefaultBaseURL: \"https://generativelanguage.googleapis.com\",\n\t\tEnvKey: \"GEMINI_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"google/gemini-3-flash-preview\", Name: \"Gemini 3 Flash Preview\"},\n\t\t\t{ID: \"google/gemini-flash-latest\", Name: \"Gemini Flash Latest\"},\n\t\t\t{ID: \"google/gemini-3-pro-preview\", Name: \"Gemini 3 Pro Preview\"},\n\t\t},\n\t},\n\t\"moonshot\": {\n\t\tKey: \"moonshot\",\n\t\tDisplayName: \"Moonshot (Global)\",\n\t\tSort: 70,\n\t\tDefaultBaseURL: \"https://api.moonshot.ai/v1\",\n\t\tEnvKey: \"MOONSHOT_API_KEY\",\n\t\tModels: []Model{\n\t\t\t{ID: \"moonshot/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"moonshot/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"moonshot/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n}\n\nfunc Get(key string) (Meta, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn Meta{}, false\n\t}\n\treturn cloneMeta(meta), true\n}\n\nfunc All() map[string]Meta {\n\tresult := make(map[string]Meta, len(catalog))\n\tfor key, meta := range catalog {\n\t\tresult[key] = cloneMeta(meta)\n\t}\n\treturn result\n}\n\nfunc DefaultBaseURL(key string) (string, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok || strings.TrimSpace(meta.DefaultBaseURL) == \"\" {\n\t\treturn \"\", false\n\t}\n\treturn meta.DefaultBaseURL, true\n}\n\nfunc EnvKey(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.EnvKey\n}\n\nfunc DisplayName(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn key\n\t}\n\tif strings.TrimSpace(meta.DisplayName) == \"\" {\n\t\treturn key\n\t}\n\treturn meta.DisplayName\n}\n\nfunc cloneMeta(meta Meta) Meta {\n\tclone := meta\n\tif len(meta.Models) > 0 {\n\t\tclone.Models = make([]Model, len(meta.Models))\n\t\tfor i, item := range meta.Models {\n\t\t\tclone.Models[i] = normalizeModel(meta.Key, item)\n\t\t}\n\t}\n\treturn clone\n}\n\nfunc normalizeModel(provider string, model Model) Model {\n\tclone := model\n\tclone.ID = strings.TrimSpace(clone.ID)\n\tclone.Name = strings.TrimSpace(clone.Name)\n\tif clone.Name == \"\" {\n\t\tclone.Name = clone.ID\n\t}\n\tif clone.MaxTokens <= 0 || clone.ContextWindow <= 0 {\n\t\tresolvedMaxTokens, resolvedContextWindow := catalogRuntimeDefaults(strings.ToLower(strings.TrimSpace(provider)))\n\t\tif clone.MaxTokens <= 0 {\n\t\t\tclone.MaxTokens = resolvedMaxTokens\n\t\t}\n\t\tif clone.ContextWindow <= 0 {\n\t\t\tclone.ContextWindow = resolvedContextWindow\n\t\t}\n\t}\n\tif len(clone.Input) == 0 {\n\t\tclone.Input = defaultModelInputs(provider)\n\t}\n\tif !clone.Reasoning {\n\t\tclone.Reasoning = isReasoningModel(clone.ID)\n\t}\n\treturn clone\n}\n\nfunc defaultModelInputs(provider string) []string {\n\tswitch strings.ToLower(strings.TrimSpace(provider)) {\n\tcase \"kimi-coding\":\n\t\treturn []string{\"text\", \"image\"}\n\tdefault:\n\t\treturn []string{\"text\"}\n\t}\n}\n\nfunc catalogRuntimeDefaults(provider string) (int, int) {\n\tswitch provider {\n\tcase \"deepseek\":\n\t\treturn 8192, 128000\n\tcase \"zai\":\n\t\treturn 131072, 204800\n\tcase \"openrouter\":\n\t\treturn 8192, 128000\n\tcase \"minimax\", \"kimi-coding\":\n\t\treturn 8192, 200000\n\tcase \"custom\", \"vllm\":\n\t\treturn 8192, 128000\n\tdefault:\n\t\treturn 8192, 256000\n\t}\n}\n"}, "c68251cada085b951dbbb487475d81d02ad89be2": {"t": 1785755391.1090734, "n": 9134, "h": "ca4097836434df78", "c": "package provider\n\nimport (\n\t\"strings\"\n)\n\ntype Model struct {\n\tID string\n\tName string\n\tContextWindow int\n\tMaxTokens int\n\tReasoning bool\n\tInput []string\n}\n\ntype Meta struct {\n\tKey string\n\tDisplayName string\n\tSort uint\n\tDefaultBaseURL string\n\tEnvKey string\n\tModels []Model\n\tEnabled bool\n}\n\nvar catalog = map[string]Meta{\n\t\"custom\": {\n\t\tKey: \"custom\",\n\t\tDisplayName: \"Custom\",\n\t\tSort: 10,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"CUSTOM_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{},\n\t},\n\t\"ollama\": {\n\t\tKey: \"ollama\",\n\t\tDisplayName: \"Ollama\",\n\t\tSort: 15,\n\t\tEnabled: true,\n\t},\n\t\"vllm\": {\n\t\tKey: \"vllm\",\n\t\tDisplayName: \"vLLM\",\n\t\tSort: 20,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"VLLM_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{},\n\t},\n\t\"deepseek\": {\n\t\tKey: \"deepseek\",\n\t\tDisplayName: \"DeepSeek\",\n\t\tSort: 25,\n\t\tDefaultBaseURL: \"https://api.deepseek.com/v1\",\n\t\tEnvKey: \"DEEPSEEK_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"deepseek/deepseek-chat\", Name: \"DeepSeek Chat\"},\n\t\t\t{ID: \"deepseek/deepseek-reasoner\", Name: \"DeepSeek Reasoner\"},\n\t\t\t{ID: \"deepseek/deepseek-r1:1.5b\", Name: \"DeepSeek R1 1.5B\"},\n\t\t},\n\t},\n\t\"bailian-coding-plan\": {\n\t\tKey: \"bailian-coding-plan\",\n\t\tDisplayName: \"阿里云百炼 Coding Plan\",\n\t\tSort: 30,\n\t\tDefaultBaseURL: \"https://coding.dashscope.aliyuncs.com/v1\",\n\t\tEnvKey: \"QWEN_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"bailian-coding-plan/qwen3.5-plus\", Name: \"Qwen3.5-Plus\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-max\", Name: \"Qwen3-Max\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-next\", Name: \"Qwen3-Coder-Next\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-plus\", Name: \"Qwen3-Coder-Plus\"},\n\t\t\t{ID: \"bailian-coding-plan/minimax-m2.5\", Name: \"MiniMax M2.5\"},\n\t\t\t{ID: \"bailian-coding-plan/glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"bailian-coding-plan/kimi-k2.5\", Name: \"Kimi-k2.5\"},\n\t\t\t{ID: \"bailian-coding-plan/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t},\n\t},\n\t\"ark-coding-plan\": {\n\t\tKey: \"ark-coding-plan\",\n\t\tDisplayName: \"方舟 Coding Plan\",\n\t\tSort: 35,\n\t\tDefaultBaseURL: \"https://ark.cn-beijing.volces.com/api/coding/v3\",\n\t\tEnvKey: \"ARK_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-2.0-code\", Name: \"Doubao-Seed-2.0-Code\"},\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-code\", Name: \"Doubao-Seed-Code\"},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2.5\", Name: \"Kimi-K2.5\"},\n\t\t\t{ID: \"ark-coding-plan/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t\t{ID: \"ark-coding-plan/deepseek-v3.2\", Name: \"DeepSeek-V3.2\"},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2-thinking\", Name: \"Kimi-K2-thinking\"},\n\t\t},\n\t},\n\t\"zai\": {\n\t\tKey: \"zai\",\n\t\tDisplayName: \"Z.ai\",\n\t\tSort: 40,\n\t\tDefaultBaseURL: \"https://open.bigmodel.cn/api/paas/v4\",\n\t\tEnvKey: \"ZAI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"zai/glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"zai/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t\t{ID: \"zai/glm-4.7-flash\", Name: \"GLM-4.7-Flash\"},\n\t\t\t{ID: \"zai/glm-4.7-flashx\", Name: \"GLM-4.7-FlashX\"},\n\t\t},\n\t},\n\t\"minimax\": {\n\t\tKey: \"minimax\",\n\t\tDisplayName: \"MiniMax (CN)\",\n\t\tSort: 45,\n\t\tDefaultBaseURL: \"https://api.minimaxi.com/anthropic\",\n\t\tEnvKey: \"MINIMAX_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"minimax/MiniMax-M2.5\", Name: \"MiniMax M2.5\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.5-highspeed\", Name: \"MiniMax M2.5 highspeed\"},\n\t\t},\n\t},\n\t\"kimi\": {\n\t\tKey: \"kimi\",\n\t\tDisplayName: \"Kimi (CN)\",\n\t\tSort: 50,\n\t\tDefaultBaseURL: \"https://api.moonshot.cn/v1\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"kimi/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"kimi/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n\t\"kimi-coding\": {\n\t\tKey: \"kimi-coding\",\n\t\tDisplayName: \"Kimi Coding\",\n\t\tSort: 51,\n\t\tDefaultBaseURL: \"https://api.kimi.com/coding/\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi-coding/k2p5\", Name: \"Kimi K2.5\"},\n\t\t},\n\t},\n\t\"openai\": {\n\t\tKey: \"openai\",\n\t\tDisplayName: \"OpenAI\",\n\t\tSort: 55,\n\t\tDefaultBaseURL: \"https://api.openai.com/v1\",\n\t\tEnvKey: \"OPENAI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"openai/codex-mini-latest\", Name: \"Codex Mini\"},\n\t\t\t{ID: \"openai/gpt-4.1\", Name: \"GPT-4.1\"},\n\t\t\t{ID: \"openai/gpt-4o\", Name: \"GPT-4o\"},\n\t\t\t{ID: \"openai/gpt-4o-mini\", Name: \"GPT-4o Mini\"},\n\t\t\t{ID: \"openai/gpt-5\", Name: \"GPT-5\"},\n\t\t\t{ID: \"openai/gpt-5-mini\", Name: \"GPT-5 Mini\"},\n\t\t},\n\t},\n\t\"openrouter\": {\n\t\tKey: \"openrouter\",\n\t\tDisplayName: \"OpenRouter\",\n\t\tSort: 56,\n\t\tDefaultBaseURL: \"https://openrouter.ai/api/v1\",\n\t\tEnvKey: \"OPENROUTER_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"openrouter/free\", Name: \"openrouter/free\"},\n\t\t\t{ID: \"openrouter/auto\", Name: \"openrouter/auto\"},\n\t\t},\n\t},\n\t\"anthropic\": {\n\t\tKey: \"anthropic\",\n\t\tDisplayName: \"Anthropic\",\n\t\tSort: 60,\n\t\tDefaultBaseURL: \"https://api.anthropic.com\",\n\t\tEnvKey: \"ANTHROPIC_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"anthropic/claude-3-haiku-20240307\", Name: \"Claude 3 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-haiku-latest\", Name: \"Claude 3.5 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-sonnet-20241022\", Name: \"Claude 3.5 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-3-7-sonnet-20250219\", Name: \"Claude 3.7 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-opus-4-1\", Name: \"Claude Opus 4.1\"},\n\t\t},\n\t},\n\t\"gemini\": {\n\t\tKey: \"gemini\",\n\t\tDisplayName: \"Gemini\",\n\t\tSort: 65,\n\t\tDefaultBaseURL: \"https://generativelanguage.googleapis.com\",\n\t\tEnvKey: \"GEMINI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"google/gemini-3-flash-preview\", Name: \"Gemini 3 Flash Preview\"},\n\t\t\t{ID: \"google/gemini-flash-latest\", Name: \"Gemini Flash Latest\"},\n\t\t\t{ID: \"google/gemini-3-pro-preview\", Name: \"Gemini 3 Pro Preview\"},\n\t\t},\n\t},\n\t\"moonshot\": {\n\t\tKey: \"moonshot\",\n\t\tDisplayName: \"Moonshot (Global)\",\n\t\tSort: 70,\n\t\tDefaultBaseURL: \"https://api.moonshot.ai/v1\",\n\t\tEnvKey: \"MOONSHOT_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"moonshot/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"moonshot/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"moonshot/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n}\n\nfunc Get(key string) (Meta, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn Meta{}, false\n\t}\n\treturn cloneMeta(meta), true\n}\n\nfunc All() map[string]Meta {\n\tresult := make(map[string]Meta, len(catalog))\n\tfor key, meta := range catalog {\n\t\tresult[key] = cloneMeta(meta)\n\t}\n\treturn result\n}\n\nfunc IsEnabled(key string) bool {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\treturn ok && meta.Enabled\n}\n\nfunc DefaultBaseURL(key string) (string, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok || strings.TrimSpace(meta.DefaultBaseURL) == \"\" {\n\t\treturn \"\", false\n\t}\n\treturn meta.DefaultBaseURL, true\n}\n\nfunc EnvKey(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.EnvKey\n}\n\nfunc DisplayName(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn key\n\t}\n\tif strings.TrimSpace(meta.DisplayName) == \"\" {\n\t\treturn key\n\t}\n\treturn meta.DisplayName\n}\n\nfunc cloneMeta(meta Meta) Meta {\n\tclone := meta\n\tif len(meta.Models) > 0 {\n\t\tclone.Models = make([]Model, len(meta.Models))\n\t\tfor i, item := range meta.Models {\n\t\t\tclone.Models[i] = normalizeModel(meta.Key, item)\n\t\t}\n\t}\n\treturn clone\n}\n\nfunc normalizeModel(provider string, model Model) Model {\n\tclone := model\n\tclone.ID = strings.TrimSpace(clone.ID)\n\tclone.Name = strings.TrimSpace(clone.Name)\n\tif clone.Name == \"\" {\n\t\tclone.Name = clone.ID\n\t}\n\tif clone.MaxTokens <= 0 || clone.ContextWindow <= 0 {\n\t\tresolvedMaxTokens, resolvedContextWindow := catalogRuntimeDefaults(strings.ToLower(strings.TrimSpace(provider)))\n\t\tif clone.MaxTokens <= 0 {\n\t\t\tclone.MaxTokens = resolvedMaxTokens\n\t\t}\n\t\tif clone.ContextWindow <= 0 {\n\t\t\tclone.ContextWindow = resolvedContextWindow\n\t\t}\n\t}\n\tif len(clone.Input) == 0 {\n\t\tclone.Input = defaultModelInputs(provider)\n\t}\n\tif !clone.Reasoning {\n\t\tclone.Reasoning = isReasoningModel(clone.ID)\n\t}\n\treturn clone\n}\n\nfunc defaultModelInputs(provider string) []string {\n\tswitch strings.ToLower(strings.TrimSpace(provider)) {\n\tcase \"kimi-coding\":\n\t\treturn []string{\"text\", \"image\"}\n\tdefault:\n\t\treturn []string{\"text\"}\n\t}\n}\n\nfunc catalogRuntimeDefaults(provider string) (int, int) {\n\tswitch provider {\n\tcase \"deepseek\":\n\t\treturn 8192, 128000\n\tcase \"zai\":\n\t\treturn 131072, 204800\n\tcase \"openrouter\":\n\t\treturn 8192, 128000\n\tcase \"minimax\", \"kimi-coding\":\n\t\treturn 8192, 200000\n\tcase \"custom\", \"vllm\":\n\t\treturn 8192, 128000\n\tdefault:\n\t\treturn 8192, 256000\n\t}\n}\n"}, "2dfe5096f01d204d1cfedf0b85eb9cbeedd35596": {"t": 1785755392.3309538, "n": 7735, "h": "48da1e0152196cf3", "c": "package provider\n\nimport (\n\t\"strings\"\n)\n\ntype Model struct {\n\tID string\n\tName string\n}\n\ntype Meta struct {\n\tKey string\n\tDisplayName string\n\tSort uint\n\tDefaultBaseURL string\n\tEnvKey string\n\tModels []Model\n\tEnabled bool\n}\n\nvar catalog = map[string]Meta{\n\t\"custom\": {\n\t\tKey: \"custom\",\n\t\tDisplayName: \"Custom\",\n\t\tSort: 10,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"CUSTOM_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{},\n\t},\n\t\"ollama\": {\n\t\tKey: \"ollama\",\n\t\tDisplayName: \"Ollama\",\n\t\tSort: 15,\n\t\tEnabled: true,\n\t},\n\t\"vllm\": {\n\t\tKey: \"vllm\",\n\t\tDisplayName: \"vLLM\",\n\t\tSort: 20,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"VLLM_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{},\n\t},\n\t\"deepseek\": {\n\t\tKey: \"deepseek\",\n\t\tDisplayName: \"DeepSeek\",\n\t\tSort: 25,\n\t\tDefaultBaseURL: \"https://api.deepseek.com/v1\",\n\t\tEnvKey: \"DEEPSEEK_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"deepseek/deepseek-chat\", Name: \"DeepSeek Chat\"},\n\t\t\t{ID: \"deepseek/deepseek-reasoner\", Name: \"DeepSeek Reasoner\"},\n\t\t\t{ID: \"deepseek/deepseek-r1:1.5b\", Name: \"DeepSeek R1 1.5B\"},\n\t\t},\n\t},\n\t\"bailian-coding-plan\": {\n\t\tKey: \"bailian-coding-plan\",\n\t\tDisplayName: \"阿里云百炼 Coding Plan\",\n\t\tSort: 30,\n\t\tDefaultBaseURL: \"https://coding.dashscope.aliyuncs.com/v1\",\n\t\tEnvKey: \"QWEN_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"bailian-coding-plan/qwen3.5-plus\", Name: \"Qwen3.5-Plus\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-max\", Name: \"Qwen3-Max\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-next\", Name: \"Qwen3-Coder-Next\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-plus\", Name: \"Qwen3-Coder-Plus\"},\n\t\t\t{ID: \"bailian-coding-plan/minimax-m2.5\", Name: \"MiniMax M2.5\"},\n\t\t\t{ID: \"bailian-coding-plan/glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"bailian-coding-plan/kimi-k2.5\", Name: \"Kimi-k2.5\"},\n\t\t\t{ID: \"bailian-coding-plan/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t},\n\t},\n\t\"ark-coding-plan\": {\n\t\tKey: \"ark-coding-plan\",\n\t\tDisplayName: \"方舟 Coding Plan\",\n\t\tSort: 35,\n\t\tDefaultBaseURL: \"https://ark.cn-beijing.volces.com/api/coding/v3\",\n\t\tEnvKey: \"ARK_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-2.0-code\", Name: \"Doubao-Seed-2.0-Code\"},\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-code\", Name: \"Doubao-Seed-Code\"},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2.5\", Name: \"Kimi-K2.5\"},\n\t\t\t{ID: \"ark-coding-plan/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t\t{ID: \"ark-coding-plan/deepseek-v3.2\", Name: \"DeepSeek-V3.2\"},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2-thinking\", Name: \"Kimi-K2-thinking\"},\n\t\t},\n\t},\n\t\"zai\": {\n\t\tKey: \"zai\",\n\t\tDisplayName: \"Z.ai\",\n\t\tSort: 40,\n\t\tDefaultBaseURL: \"https://open.bigmodel.cn/api/paas/v4\",\n\t\tEnvKey: \"ZAI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"zai/glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"zai/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t\t{ID: \"zai/glm-4.7-flash\", Name: \"GLM-4.7-Flash\"},\n\t\t\t{ID: \"zai/glm-4.7-flashx\", Name: \"GLM-4.7-FlashX\"},\n\t\t},\n\t},\n\t\"minimax\": {\n\t\tKey: \"minimax\",\n\t\tDisplayName: \"MiniMax (CN)\",\n\t\tSort: 45,\n\t\tDefaultBaseURL: \"https://api.minimaxi.com/anthropic\",\n\t\tEnvKey: \"MINIMAX_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"minimax/MiniMax-M2.5\", Name: \"MiniMax M2.5\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.5-highspeed\", Name: \"MiniMax M2.5 highspeed\"},\n\t\t},\n\t},\n\t\"kimi\": {\n\t\tKey: \"kimi\",\n\t\tDisplayName: \"Kimi (CN)\",\n\t\tSort: 50,\n\t\tDefaultBaseURL: \"https://api.moonshot.cn/v1\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"kimi/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"kimi/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n\t\"kimi-coding\": {\n\t\tKey: \"kimi-coding\",\n\t\tDisplayName: \"Kimi Coding\",\n\t\tSort: 51,\n\t\tDefaultBaseURL: \"https://api.kimi.com/coding/\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi-coding/k2p5\", Name: \"Kimi K2.5\"},\n\t\t},\n\t},\n\t\"openai\": {\n\t\tKey: \"openai\",\n\t\tDisplayName: \"OpenAI\",\n\t\tSort: 55,\n\t\tDefaultBaseURL: \"https://api.openai.com/v1\",\n\t\tEnvKey: \"OPENAI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"openai/codex-mini-latest\", Name: \"Codex Mini\"},\n\t\t\t{ID: \"openai/gpt-4.1\", Name: \"GPT-4.1\"},\n\t\t\t{ID: \"openai/gpt-4o\", Name: \"GPT-4o\"},\n\t\t\t{ID: \"openai/gpt-4o-mini\", Name: \"GPT-4o Mini\"},\n\t\t\t{ID: \"openai/gpt-5\", Name: \"GPT-5\"},\n\t\t\t{ID: \"openai/gpt-5-mini\", Name: \"GPT-5 Mini\"},\n\t\t},\n\t},\n\t\"openrouter\": {\n\t\tKey: \"openrouter\",\n\t\tDisplayName: \"OpenRouter\",\n\t\tSort: 56,\n\t\tDefaultBaseURL: \"https://openrouter.ai/api/v1\",\n\t\tEnvKey: \"OPENROUTER_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"openrouter/free\", Name: \"openrouter/free\"},\n\t\t\t{ID: \"openrouter/auto\", Name: \"openrouter/auto\"},\n\t\t},\n\t},\n\t\"anthropic\": {\n\t\tKey: \"anthropic\",\n\t\tDisplayName: \"Anthropic\",\n\t\tSort: 60,\n\t\tDefaultBaseURL: \"https://api.anthropic.com\",\n\t\tEnvKey: \"ANTHROPIC_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"anthropic/claude-3-haiku-20240307\", Name: \"Claude 3 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-haiku-latest\", Name: \"Claude 3.5 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-sonnet-20241022\", Name: \"Claude 3.5 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-3-7-sonnet-20250219\", Name: \"Claude 3.7 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-opus-4-1\", Name: \"Claude Opus 4.1\"},\n\t\t},\n\t},\n\t\"gemini\": {\n\t\tKey: \"gemini\",\n\t\tDisplayName: \"Gemini\",\n\t\tSort: 65,\n\t\tDefaultBaseURL: \"https://generativelanguage.googleapis.com\",\n\t\tEnvKey: \"GEMINI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"google/gemini-3-flash-preview\", Name: \"Gemini 3 Flash Preview\"},\n\t\t\t{ID: \"google/gemini-flash-latest\", Name: \"Gemini Flash Latest\"},\n\t\t\t{ID: \"google/gemini-3-pro-preview\", Name: \"Gemini 3 Pro Preview\"},\n\t\t},\n\t},\n\t\"moonshot\": {\n\t\tKey: \"moonshot\",\n\t\tDisplayName: \"Moonshot (Global)\",\n\t\tSort: 70,\n\t\tDefaultBaseURL: \"https://api.moonshot.ai/v1\",\n\t\tEnvKey: \"MOONSHOT_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"moonshot/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"moonshot/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"moonshot/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n}\n\nfunc Get(key string) (Meta, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn Meta{}, false\n\t}\n\treturn cloneMeta(meta), true\n}\n\nfunc All() map[string]Meta {\n\tresult := make(map[string]Meta, len(catalog))\n\tfor key, meta := range catalog {\n\t\tresult[key] = cloneMeta(meta)\n\t}\n\treturn result\n}\n\nfunc IsEnabled(key string) bool {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\treturn ok && meta.Enabled\n}\n\nfunc DefaultBaseURL(key string) (string, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok || strings.TrimSpace(meta.DefaultBaseURL) == \"\" {\n\t\treturn \"\", false\n\t}\n\treturn meta.DefaultBaseURL, true\n}\n\nfunc EnvKey(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.EnvKey\n}\n\nfunc DisplayName(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn key\n\t}\n\tif strings.TrimSpace(meta.DisplayName) == \"\" {\n\t\treturn key\n\t}\n\treturn meta.DisplayName\n}\n\nfunc cloneMeta(meta Meta) Meta {\n\tclone := meta\n\tif len(meta.Models) > 0 {\n\t\tclone.Models = make([]Model, len(meta.Models))\n\t\tcopy(clone.Models, meta.Models)\n\t}\n\treturn clone\n}\n"}, "fb87cf545f14e97f628de6a605f5bddc059e821d": {"t": 1785755393.7325492, "n": 7735, "h": "5bdce5c4e9a780f1", "c": "package provider\n\nimport (\n\t\"strings\"\n)\n\ntype Model struct {\n\tID string\n\tName string\n}\n\ntype Meta struct {\n\tKey string\n\tDisplayName string\n\tSort uint\n\tDefaultBaseURL string\n\tEnvKey string\n\tModels []Model\n\tEnabled bool\n}\n\nvar catalog = map[string]Meta{\n\t\"custom\": {\n\t\tKey: \"custom\",\n\t\tDisplayName: \"Custom\",\n\t\tSort: 10,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"CUSTOM_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{},\n\t},\n\t\"ollama\": {\n\t\tKey: \"ollama\",\n\t\tDisplayName: \"Ollama\",\n\t\tSort: 15,\n\t\tEnabled: true,\n\t},\n\t\"vllm\": {\n\t\tKey: \"vllm\",\n\t\tDisplayName: \"vLLM\",\n\t\tSort: 20,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"VLLM_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{},\n\t},\n\t\"deepseek\": {\n\t\tKey: \"deepseek\",\n\t\tDisplayName: \"DeepSeek\",\n\t\tSort: 25,\n\t\tDefaultBaseURL: \"https://api.deepseek.com/v1\",\n\t\tEnvKey: \"DEEPSEEK_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"deepseek/deepseek-chat\", Name: \"DeepSeek Chat\"},\n\t\t\t{ID: \"deepseek/deepseek-reasoner\", Name: \"DeepSeek Reasoner\"},\n\t\t\t{ID: \"deepseek/deepseek-r1:1.5b\", Name: \"DeepSeek R1 1.5B\"},\n\t\t},\n\t},\n\t\"bailian-coding-plan\": {\n\t\tKey: \"bailian-coding-plan\",\n\t\tDisplayName: \"阿里云百炼 Coding Plan\",\n\t\tSort: 30,\n\t\tDefaultBaseURL: \"https://coding.dashscope.aliyuncs.com/v1\",\n\t\tEnvKey: \"QWEN_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"bailian-coding-plan/qwen3.5-plus\", Name: \"Qwen3.5-Plus\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-max\", Name: \"Qwen3-Max\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-next\", Name: \"Qwen3-Coder-Next\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-plus\", Name: \"Qwen3-Coder-Plus\"},\n\t\t\t{ID: \"bailian-coding-plan/minimax-m2.5\", Name: \"MiniMax M2.5\"},\n\t\t\t{ID: \"bailian-coding-plan/glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"bailian-coding-plan/kimi-k2.5\", Name: \"Kimi-k2.5\"},\n\t\t\t{ID: \"bailian-coding-plan/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t},\n\t},\n\t\"ark-coding-plan\": {\n\t\tKey: \"ark-coding-plan\",\n\t\tDisplayName: \"方舟 Coding Plan\",\n\t\tSort: 35,\n\t\tDefaultBaseURL: \"https://ark.cn-beijing.volces.com/api/coding/v3\",\n\t\tEnvKey: \"ARK_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-2.0-code\", Name: \"Doubao-Seed-2.0-Code\"},\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-code\", Name: \"Doubao-Seed-Code\"},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2.5\", Name: \"Kimi-K2.5\"},\n\t\t\t{ID: \"ark-coding-plan/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t\t{ID: \"ark-coding-plan/deepseek-v3.2\", Name: \"DeepSeek-V3.2\"},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2-thinking\", Name: \"Kimi-K2-thinking\"},\n\t\t},\n\t},\n\t\"zai\": {\n\t\tKey: \"zai\",\n\t\tDisplayName: \"Z.ai\",\n\t\tSort: 40,\n\t\tDefaultBaseURL: \"https://open.bigmodel.cn/api/paas/v4\",\n\t\tEnvKey: \"ZAI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"zai/glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"zai/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t\t{ID: \"zai/glm-4.7-flash\", Name: \"GLM-4.7-Flash\"},\n\t\t\t{ID: \"zai/glm-4.7-flashx\", Name: \"GLM-4.7-FlashX\"},\n\t\t},\n\t},\n\t\"minimax\": {\n\t\tKey: \"minimax\",\n\t\tDisplayName: \"MiniMax (CN)\",\n\t\tSort: 45,\n\t\tDefaultBaseURL: \"https://api.minimaxi.com/anthropic\",\n\t\tEnvKey: \"MINIMAX_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"minimax/MiniMax-M2.1\", Name: \"MiniMax M2.1\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.1-lightning\", Name: \"MiniMax M2.1 Lightning\"},\n\t\t},\n\t},\n\t\"kimi\": {\n\t\tKey: \"kimi\",\n\t\tDisplayName: \"Kimi (CN)\",\n\t\tSort: 50,\n\t\tDefaultBaseURL: \"https://api.moonshot.cn/v1\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"kimi/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"kimi/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n\t\"kimi-coding\": {\n\t\tKey: \"kimi-coding\",\n\t\tDisplayName: \"Kimi Coding\",\n\t\tSort: 51,\n\t\tDefaultBaseURL: \"https://api.kimi.com/coding/\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi-coding/k2p5\", Name: \"Kimi K2.5\"},\n\t\t},\n\t},\n\t\"openai\": {\n\t\tKey: \"openai\",\n\t\tDisplayName: \"OpenAI\",\n\t\tSort: 55,\n\t\tDefaultBaseURL: \"https://api.openai.com/v1\",\n\t\tEnvKey: \"OPENAI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"openai/codex-mini-latest\", Name: \"Codex Mini\"},\n\t\t\t{ID: \"openai/gpt-4.1\", Name: \"GPT-4.1\"},\n\t\t\t{ID: \"openai/gpt-4o\", Name: \"GPT-4o\"},\n\t\t\t{ID: \"openai/gpt-4o-mini\", Name: \"GPT-4o Mini\"},\n\t\t\t{ID: \"openai/gpt-5\", Name: \"GPT-5\"},\n\t\t\t{ID: \"openai/gpt-5-mini\", Name: \"GPT-5 Mini\"},\n\t\t},\n\t},\n\t\"openrouter\": {\n\t\tKey: \"openrouter\",\n\t\tDisplayName: \"OpenRouter\",\n\t\tSort: 56,\n\t\tDefaultBaseURL: \"https://openrouter.ai/api/v1\",\n\t\tEnvKey: \"OPENROUTER_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"openrouter/free\", Name: \"openrouter/free\"},\n\t\t\t{ID: \"openrouter/auto\", Name: \"openrouter/auto\"},\n\t\t},\n\t},\n\t\"anthropic\": {\n\t\tKey: \"anthropic\",\n\t\tDisplayName: \"Anthropic\",\n\t\tSort: 60,\n\t\tDefaultBaseURL: \"https://api.anthropic.com\",\n\t\tEnvKey: \"ANTHROPIC_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"anthropic/claude-3-haiku-20240307\", Name: \"Claude 3 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-haiku-latest\", Name: \"Claude 3.5 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-sonnet-20241022\", Name: \"Claude 3.5 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-3-7-sonnet-20250219\", Name: \"Claude 3.7 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-opus-4-1\", Name: \"Claude Opus 4.1\"},\n\t\t},\n\t},\n\t\"gemini\": {\n\t\tKey: \"gemini\",\n\t\tDisplayName: \"Gemini\",\n\t\tSort: 65,\n\t\tDefaultBaseURL: \"https://generativelanguage.googleapis.com\",\n\t\tEnvKey: \"GEMINI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"google/gemini-3-flash-preview\", Name: \"Gemini 3 Flash Preview\"},\n\t\t\t{ID: \"google/gemini-flash-latest\", Name: \"Gemini Flash Latest\"},\n\t\t\t{ID: \"google/gemini-3-pro-preview\", Name: \"Gemini 3 Pro Preview\"},\n\t\t},\n\t},\n\t\"moonshot\": {\n\t\tKey: \"moonshot\",\n\t\tDisplayName: \"Moonshot (Global)\",\n\t\tSort: 70,\n\t\tDefaultBaseURL: \"https://api.moonshot.ai/v1\",\n\t\tEnvKey: \"MOONSHOT_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"moonshot/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"moonshot/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"moonshot/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n}\n\nfunc Get(key string) (Meta, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn Meta{}, false\n\t}\n\treturn cloneMeta(meta), true\n}\n\nfunc All() map[string]Meta {\n\tresult := make(map[string]Meta, len(catalog))\n\tfor key, meta := range catalog {\n\t\tresult[key] = cloneMeta(meta)\n\t}\n\treturn result\n}\n\nfunc IsEnabled(key string) bool {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\treturn ok && meta.Enabled\n}\n\nfunc DefaultBaseURL(key string) (string, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok || strings.TrimSpace(meta.DefaultBaseURL) == \"\" {\n\t\treturn \"\", false\n\t}\n\treturn meta.DefaultBaseURL, true\n}\n\nfunc EnvKey(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.EnvKey\n}\n\nfunc DisplayName(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn key\n\t}\n\tif strings.TrimSpace(meta.DisplayName) == \"\" {\n\t\treturn key\n\t}\n\treturn meta.DisplayName\n}\n\nfunc cloneMeta(meta Meta) Meta {\n\tclone := meta\n\tif len(meta.Models) > 0 {\n\t\tclone.Models = make([]Model, len(meta.Models))\n\t\tcopy(clone.Models, meta.Models)\n\t}\n\treturn clone\n}\n"}, "d114933fe9a44f6fbe65178cbbd56c9c5940baec": {"t": 1785755395.487384, "n": 7899, "h": "da246bb933ce0774", "c": "package provider\n\nimport (\n\t\"strings\"\n)\n\ntype Model struct {\n\tID string\n\tName string\n}\n\ntype Meta struct {\n\tKey string\n\tDisplayName string\n\tSort uint\n\tDefaultBaseURL string\n\tEnvKey string\n\tModels []Model\n\tEnabled bool\n}\n\nvar catalog = map[string]Meta{\n\t\"custom\": {\n\t\tKey: \"custom\",\n\t\tDisplayName: \"Custom\",\n\t\tSort: 10,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"CUSTOM_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{},\n\t},\n\t\"ollama\": {\n\t\tKey: \"ollama\",\n\t\tDisplayName: \"Ollama\",\n\t\tSort: 15,\n\t\tEnabled: true,\n\t},\n\t\"vllm\": {\n\t\tKey: \"vllm\",\n\t\tDisplayName: \"vLLM\",\n\t\tSort: 20,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"VLLM_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{},\n\t},\n\t\"deepseek\": {\n\t\tKey: \"deepseek\",\n\t\tDisplayName: \"DeepSeek\",\n\t\tSort: 25,\n\t\tDefaultBaseURL: \"https://api.deepseek.com/v1\",\n\t\tEnvKey: \"DEEPSEEK_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"deepseek/deepseek-chat\", Name: \"DeepSeek Chat\"},\n\t\t\t{ID: \"deepseek/deepseek-reasoner\", Name: \"DeepSeek Reasoner\"},\n\t\t\t{ID: \"deepseek/deepseek-r1:1.5b\", Name: \"DeepSeek R1 1.5B\"},\n\t\t},\n\t},\n\t\"bailian-coding-plan\": {\n\t\tKey: \"bailian-coding-plan\",\n\t\tDisplayName: \"阿里云百炼 Coding Plan\",\n\t\tSort: 30,\n\t\tDefaultBaseURL: \"https://coding.dashscope.aliyuncs.com/v1\",\n\t\tEnvKey: \"QWEN_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"bailian-coding-plan/qwen3.5-plus\", Name: \"Qwen3.5-Plus\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-max\", Name: \"Qwen3-Max\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-next\", Name: \"Qwen3-Coder-Next\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-plus\", Name: \"Qwen3-Coder-Plus\"},\n\t\t\t{ID: \"bailian-coding-plan/minimax-m2.5\", Name: \"MiniMax M2.5\"},\n\t\t\t{ID: \"bailian-coding-plan/glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"bailian-coding-plan/kimi-k2.5\", Name: \"Kimi-k2.5\"},\n\t\t\t{ID: \"bailian-coding-plan/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t},\n\t},\n\t\"ark-coding-plan\": {\n\t\tKey: \"ark-coding-plan\",\n\t\tDisplayName: \"方舟 Coding Plan\",\n\t\tSort: 35,\n\t\tDefaultBaseURL: \"https://ark.cn-beijing.volces.com/api/coding/v3\",\n\t\tEnvKey: \"ARK_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-2.0-code\", Name: \"Doubao-Seed-2.0-Code\"},\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-code\", Name: \"Doubao-Seed-Code\"},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2.5\", Name: \"Kimi-K2.5\"},\n\t\t\t{ID: \"ark-coding-plan/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t\t{ID: \"ark-coding-plan/deepseek-v3.2\", Name: \"DeepSeek-V3.2\"},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2-thinking\", Name: \"Kimi-K2-thinking\"},\n\t\t},\n\t},\n\t\"zai\": {\n\t\tKey: \"zai\",\n\t\tDisplayName: \"Z.ai\",\n\t\tSort: 40,\n\t\tDefaultBaseURL: \"https://open.bigmodel.cn/api/paas/v4\",\n\t\tEnvKey: \"ZAI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"zai/glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"zai/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t\t{ID: \"zai/glm-4.7-flash\", Name: \"GLM-4.7-Flash\"},\n\t\t\t{ID: \"zai/glm-4.7-flashx\", Name: \"GLM-4.7-FlashX\"},\n\t\t},\n\t},\n\t\"minimax\": {\n\t\tKey: \"minimax\",\n\t\tDisplayName: \"MiniMax (CN)\",\n\t\tSort: 45,\n\t\tDefaultBaseURL: \"https://api.minimaxi.com/anthropic\",\n\t\tEnvKey: \"MINIMAX_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"minimax/MiniMax-M2.1\", Name: \"MiniMax M2.1\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.1-lightning\", Name: \"MiniMax M2.1 Lightning\"},\n\t\t},\n\t},\n\t\"kimi\": {\n\t\tKey: \"kimi\",\n\t\tDisplayName: \"Kimi (CN)\",\n\t\tSort: 50,\n\t\tDefaultBaseURL: \"https://api.moonshot.cn/v1\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"kimi/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"kimi/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n\t\"kimi-coding\": {\n\t\tKey: \"kimi-coding\",\n\t\tDisplayName: \"Kimi Coding\",\n\t\tSort: 51,\n\t\tDefaultBaseURL: \"https://api.kimi.com/coding/\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi-coding/k2p5\", Name: \"Kimi K2.5\"},\n\t\t},\n\t},\n\t\"openai\": {\n\t\tKey: \"openai\",\n\t\tDisplayName: \"OpenAI\",\n\t\tSort: 55,\n\t\tDefaultBaseURL: \"https://api.openai.com/v1\",\n\t\tEnvKey: \"OPENAI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"openai/codex-mini-latest\", Name: \"Codex Mini\"},\n\t\t\t{ID: \"openai/gpt-4.1\", Name: \"GPT-4.1\"},\n\t\t\t{ID: \"openai/gpt-4o\", Name: \"GPT-4o\"},\n\t\t\t{ID: \"openai/gpt-4o-mini\", Name: \"GPT-4o Mini\"},\n\t\t\t{ID: \"openai/gpt-5\", Name: \"GPT-5\"},\n\t\t\t{ID: \"openai/gpt-5-mini\", Name: \"GPT-5 Mini\"},\n\t\t},\n\t},\n\t\"openrouter\": {\n\t\tKey: \"openrouter\",\n\t\tDisplayName: \"OpenRouter\",\n\t\tSort: 56,\n\t\tDefaultBaseURL: \"https://openrouter.ai/api/v1\",\n\t\tEnvKey: \"OPENROUTER_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"openrouter/free\", Name: \"openrouter/free\"},\n\t\t\t{ID: \"openrouter/auto\", Name: \"openrouter/auto\"},\n\t\t},\n\t},\n\t\"anthropic\": {\n\t\tKey: \"anthropic\",\n\t\tDisplayName: \"Anthropic\",\n\t\tSort: 60,\n\t\tDefaultBaseURL: \"https://api.anthropic.com\",\n\t\tEnvKey: \"ANTHROPIC_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"anthropic/claude-3-haiku-20240307\", Name: \"Claude 3 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-haiku-latest\", Name: \"Claude 3.5 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-sonnet-20241022\", Name: \"Claude 3.5 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-3-7-sonnet-20250219\", Name: \"Claude 3.7 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-opus-4-1\", Name: \"Claude Opus 4.1\"},\n\t\t},\n\t},\n\t\"gemini\": {\n\t\tKey: \"gemini\",\n\t\tDisplayName: \"Gemini\",\n\t\tSort: 65,\n\t\tDefaultBaseURL: \"https://generativelanguage.googleapis.com\",\n\t\tEnvKey: \"GEMINI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"google/gemini-1.5-flash\", Name: \"Gemini 1.5 Flash\"},\n\t\t\t{ID: \"google/gemini-1.5-pro\", Name: \"Gemini 1.5 Pro\"},\n\t\t\t{ID: \"google/gemini-2.0-flash\", Name: \"Gemini 2.0 Flash\"},\n\t\t\t{ID: \"google/gemini-2.5-flash\", Name: \"Gemini 2.5 Flash\"},\n\t\t\t{ID: \"google/gemini-2.5-pro\", Name: \"Gemini 2.5 Pro\"},\n\t\t\t{ID: \"google/gemini-3-flash-preview\", Name: \"Gemini 3 Flash Preview\"},\n\t\t},\n\t},\n\t\"moonshot\": {\n\t\tKey: \"moonshot\",\n\t\tDisplayName: \"Moonshot (Global)\",\n\t\tSort: 70,\n\t\tDefaultBaseURL: \"https://api.moonshot.ai/v1\",\n\t\tEnvKey: \"MOONSHOT_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"moonshot/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"moonshot/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"moonshot/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n}\n\nfunc Get(key string) (Meta, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn Meta{}, false\n\t}\n\treturn cloneMeta(meta), true\n}\n\nfunc All() map[string]Meta {\n\tresult := make(map[string]Meta, len(catalog))\n\tfor key, meta := range catalog {\n\t\tresult[key] = cloneMeta(meta)\n\t}\n\treturn result\n}\n\nfunc IsEnabled(key string) bool {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\treturn ok && meta.Enabled\n}\n\nfunc DefaultBaseURL(key string) (string, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok || strings.TrimSpace(meta.DefaultBaseURL) == \"\" {\n\t\treturn \"\", false\n\t}\n\treturn meta.DefaultBaseURL, true\n}\n\nfunc EnvKey(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.EnvKey\n}\n\nfunc DisplayName(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn key\n\t}\n\tif strings.TrimSpace(meta.DisplayName) == \"\" {\n\t\treturn key\n\t}\n\treturn meta.DisplayName\n}\n\nfunc cloneMeta(meta Meta) Meta {\n\tclone := meta\n\tif len(meta.Models) > 0 {\n\t\tclone.Models = make([]Model, len(meta.Models))\n\t\tcopy(clone.Models, meta.Models)\n\t}\n\treturn clone\n}\n"}, "eda9641d35a1c3defa2c7153fb806919bb4c5aa8": {"t": 1785755397.0406477, "n": 7548, "h": "1bfdc47f0cff6eaa", "c": "package provider\n\nimport (\n\t\"strings\"\n)\n\ntype Model struct {\n\tID string\n\tName string\n}\n\ntype Meta struct {\n\tKey string\n\tDisplayName string\n\tSort uint\n\tDefaultBaseURL string\n\tEnvKey string\n\tModels []Model\n\tEnabled bool\n}\n\nvar catalog = map[string]Meta{\n\t\"custom\": {\n\t\tKey: \"custom\",\n\t\tDisplayName: \"Custom\",\n\t\tSort: 10,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"CUSTOM_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{},\n\t},\n\t\"ollama\": {\n\t\tKey: \"ollama\",\n\t\tDisplayName: \"Ollama\",\n\t\tSort: 15,\n\t\tEnabled: true,\n\t},\n\t\"vllm\": {\n\t\tKey: \"vllm\",\n\t\tDisplayName: \"vLLM\",\n\t\tSort: 20,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"VLLM_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{},\n\t},\n\t\"deepseek\": {\n\t\tKey: \"deepseek\",\n\t\tDisplayName: \"DeepSeek\",\n\t\tSort: 25,\n\t\tDefaultBaseURL: \"https://api.deepseek.com/v1\",\n\t\tEnvKey: \"DEEPSEEK_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"deepseek/deepseek-chat\", Name: \"DeepSeek Chat\"},\n\t\t\t{ID: \"deepseek/deepseek-reasoner\", Name: \"DeepSeek Reasoner\"},\n\t\t\t{ID: \"deepseek/deepseek-r1:1.5b\", Name: \"DeepSeek R1 1.5B\"},\n\t\t},\n\t},\n\t\"bailian-coding-plan\": {\n\t\tKey: \"bailian-coding-plan\",\n\t\tDisplayName: \"阿里云百炼 Coding Plan\",\n\t\tSort: 30,\n\t\tDefaultBaseURL: \"https://coding.dashscope.aliyuncs.com/v1\",\n\t\tEnvKey: \"QWEN_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"bailian-coding-plan/qwen3.5-plus\", Name: \"Qwen3.5-Plus\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-max\", Name: \"Qwen3-Max\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-next\", Name: \"Qwen3-Coder-Next\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-plus\", Name: \"Qwen3-Coder-Plus\"},\n\t\t\t{ID: \"bailian-coding-plan/minimax-m2.5\", Name: \"MiniMax M2.5\"},\n\t\t\t{ID: \"bailian-coding-plan/glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"bailian-coding-plan/kimi-k2.5\", Name: \"Kimi-k2.5\"},\n\t\t\t{ID: \"bailian-coding-plan/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t},\n\t},\n\t\"ark-coding-plan\": {\n\t\tKey: \"ark-coding-plan\",\n\t\tDisplayName: \"方舟 Coding Plan\",\n\t\tSort: 35,\n\t\tDefaultBaseURL: \"https://ark.cn-beijing.volces.com/api/coding/v3\",\n\t\tEnvKey: \"ARK_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-2.0-code\", Name: \"Doubao-Seed-2.0-Code\"},\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-code\", Name: \"Doubao-Seed-Code\"},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2.5\", Name: \"Kimi-K2.5\"},\n\t\t\t{ID: \"ark-coding-plan/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t\t{ID: \"ark-coding-plan/deepseek-v3.2\", Name: \"DeepSeek-V3.2\"},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2-thinking\", Name: \"Kimi-K2-thinking\"},\n\t\t},\n\t},\n\t\"zai\": {\n\t\tKey: \"zai\",\n\t\tDisplayName: \"Z.ai\",\n\t\tSort: 40,\n\t\tDefaultBaseURL: \"https://open.bigmodel.cn/api/paas/v4\",\n\t\tEnvKey: \"ZAI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"zai/glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"zai/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t\t{ID: \"zai/glm-4.7-flash\", Name: \"GLM-4.7-Flash\"},\n\t\t\t{ID: \"zai/glm-4.7-flashx\", Name: \"GLM-4.7-FlashX\"},\n\t\t},\n\t},\n\t\"minimax\": {\n\t\tKey: \"minimax\",\n\t\tDisplayName: \"MiniMax (CN)\",\n\t\tSort: 45,\n\t\tDefaultBaseURL: \"https://api.minimaxi.com/anthropic\",\n\t\tEnvKey: \"MINIMAX_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"minimax/MiniMax-M2.1\", Name: \"MiniMax M2.1\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.1-lightning\", Name: \"MiniMax M2.1 Lightning\"},\n\t\t},\n\t},\n\t\"kimi\": {\n\t\tKey: \"kimi\",\n\t\tDisplayName: \"Kimi (CN)\",\n\t\tSort: 50,\n\t\tDefaultBaseURL: \"https://api.moonshot.cn/v1\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"kimi/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"kimi/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n\t\"kimi-coding\": {\n\t\tKey: \"kimi-coding\",\n\t\tDisplayName: \"Kimi Coding\",\n\t\tSort: 51,\n\t\tDefaultBaseURL: \"https://api.kimi.com/coding/\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi-coding/k2p5\", Name: \"Kimi K2.5\"},\n\t\t},\n\t},\n\t\"openai\": {\n\t\tKey: \"openai\",\n\t\tDisplayName: \"OpenAI\",\n\t\tSort: 55,\n\t\tDefaultBaseURL: \"https://api.openai.com/v1\",\n\t\tEnvKey: \"OPENAI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"openai/codex-mini-latest\", Name: \"Codex Mini\"},\n\t\t\t{ID: \"openai/gpt-4.1\", Name: \"GPT-4.1\"},\n\t\t\t{ID: \"openai/gpt-4o\", Name: \"GPT-4o\"},\n\t\t\t{ID: \"openai/gpt-4o-mini\", Name: \"GPT-4o Mini\"},\n\t\t\t{ID: \"openai/gpt-5\", Name: \"GPT-5\"},\n\t\t\t{ID: \"openai/gpt-5-mini\", Name: \"GPT-5 Mini\"},\n\t\t},\n\t},\n\t\"anthropic\": {\n\t\tKey: \"anthropic\",\n\t\tDisplayName: \"Anthropic\",\n\t\tSort: 60,\n\t\tDefaultBaseURL: \"https://api.anthropic.com\",\n\t\tEnvKey: \"ANTHROPIC_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"anthropic/claude-3-haiku-20240307\", Name: \"Claude 3 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-haiku-latest\", Name: \"Claude 3.5 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-sonnet-20241022\", Name: \"Claude 3.5 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-3-7-sonnet-20250219\", Name: \"Claude 3.7 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-opus-4-1\", Name: \"Claude Opus 4.1\"},\n\t\t},\n\t},\n\t\"gemini\": {\n\t\tKey: \"gemini\",\n\t\tDisplayName: \"Gemini\",\n\t\tSort: 65,\n\t\tDefaultBaseURL: \"https://generativelanguage.googleapis.com\",\n\t\tEnvKey: \"GEMINI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"google/gemini-1.5-flash\", Name: \"Gemini 1.5 Flash\"},\n\t\t\t{ID: \"google/gemini-1.5-pro\", Name: \"Gemini 1.5 Pro\"},\n\t\t\t{ID: \"google/gemini-2.0-flash\", Name: \"Gemini 2.0 Flash\"},\n\t\t\t{ID: \"google/gemini-2.5-flash\", Name: \"Gemini 2.5 Flash\"},\n\t\t\t{ID: \"google/gemini-2.5-pro\", Name: \"Gemini 2.5 Pro\"},\n\t\t\t{ID: \"google/gemini-3-flash-preview\", Name: \"Gemini 3 Flash Preview\"},\n\t\t},\n\t},\n\t\"moonshot\": {\n\t\tKey: \"moonshot\",\n\t\tDisplayName: \"Moonshot (Global)\",\n\t\tSort: 70,\n\t\tDefaultBaseURL: \"https://api.moonshot.ai/v1\",\n\t\tEnvKey: \"MOONSHOT_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"moonshot/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"moonshot/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"moonshot/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n}\n\nfunc Get(key string) (Meta, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn Meta{}, false\n\t}\n\treturn cloneMeta(meta), true\n}\n\nfunc All() map[string]Meta {\n\tresult := make(map[string]Meta, len(catalog))\n\tfor key, meta := range catalog {\n\t\tresult[key] = cloneMeta(meta)\n\t}\n\treturn result\n}\n\nfunc IsEnabled(key string) bool {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\treturn ok && meta.Enabled\n}\n\nfunc DefaultBaseURL(key string) (string, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok || strings.TrimSpace(meta.DefaultBaseURL) == \"\" {\n\t\treturn \"\", false\n\t}\n\treturn meta.DefaultBaseURL, true\n}\n\nfunc EnvKey(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.EnvKey\n}\n\nfunc DisplayName(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn key\n\t}\n\tif strings.TrimSpace(meta.DisplayName) == \"\" {\n\t\treturn key\n\t}\n\treturn meta.DisplayName\n}\n\nfunc cloneMeta(meta Meta) Meta {\n\tclone := meta\n\tif len(meta.Models) > 0 {\n\t\tclone.Models = make([]Model, len(meta.Models))\n\t\tcopy(clone.Models, meta.Models)\n\t}\n\treturn clone\n}\n"}, "e82d6869405f522335f326b0e82da4223d510a9a": {"t": 1785755398.518412, "n": 7769, "h": "cf13906fe24b101c", "c": "package provider\n\nimport (\n\t\"strings\"\n)\n\ntype Model struct {\n\tID string\n\tName string\n}\n\ntype Meta struct {\n\tKey string\n\tDisplayName string\n\tSort uint\n\tDefaultBaseURL string\n\tEnvKey string\n\tModels []Model\n\tEnabled bool\n}\n\nvar catalog = map[string]Meta{\n\t\"ollama\": {\n\t\tKey: \"ollama\",\n\t\tDisplayName: \"Ollama\",\n\t\tSort: 10,\n\t\tEnabled: true,\n\t},\n\t\"deepseek\": {\n\t\tKey: \"deepseek\",\n\t\tDisplayName: \"DeepSeek\",\n\t\tSort: 20,\n\t\tDefaultBaseURL: \"https://api.deepseek.com/v1\",\n\t\tEnvKey: \"DEEPSEEK_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"deepseek/deepseek-chat\", Name: \"DeepSeek Chat\"},\n\t\t\t{ID: \"deepseek/deepseek-reasoner\", Name: \"DeepSeek Reasoner\"},\n\t\t\t{ID: \"deepseek/deepseek-r1:1.5b\", Name: \"DeepSeek R1 1.5B\"},\n\t\t},\n\t},\n\t\"custom\": {\n\t\tKey: \"custom\",\n\t\tDisplayName: \"Custom\",\n\t\tSort: 30,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"CUSTOM_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{},\n\t},\n\t\"vllm\": {\n\t\tKey: \"vllm\",\n\t\tDisplayName: \"vLLM\",\n\t\tSort: 31,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"VLLM_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{},\n\t},\n\t\"openai\": {\n\t\tKey: \"openai\",\n\t\tDisplayName: \"OpenAI\",\n\t\tSort: 40,\n\t\tDefaultBaseURL: \"https://api.openai.com/v1\",\n\t\tEnvKey: \"OPENAI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"openai/codex-mini-latest\", Name: \"Codex Mini\"},\n\t\t\t{ID: \"openai/gpt-4.1\", Name: \"GPT-4.1\"},\n\t\t\t{ID: \"openai/gpt-4o\", Name: \"GPT-4o\"},\n\t\t\t{ID: \"openai/gpt-4o-mini\", Name: \"GPT-4o Mini\"},\n\t\t\t{ID: \"openai/gpt-5\", Name: \"GPT-5\"},\n\t\t\t{ID: \"openai/gpt-5-mini\", Name: \"GPT-5 Mini\"},\n\t\t},\n\t},\n\t\"anthropic\": {\n\t\tKey: \"anthropic\",\n\t\tDisplayName: \"Anthropic\",\n\t\tSort: 50,\n\t\tDefaultBaseURL: \"https://api.anthropic.com\",\n\t\tEnvKey: \"ANTHROPIC_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"anthropic/claude-3-haiku-20240307\", Name: \"Claude 3 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-haiku-latest\", Name: \"Claude 3.5 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-sonnet-20241022\", Name: \"Claude 3.5 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-3-7-sonnet-20250219\", Name: \"Claude 3.7 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-opus-4-1\", Name: \"Claude Opus 4.1\"},\n\t\t},\n\t},\n\t\"gemini\": {\n\t\tKey: \"gemini\",\n\t\tDisplayName: \"Gemini\",\n\t\tSort: 60,\n\t\tDefaultBaseURL: \"https://generativelanguage.googleapis.com\",\n\t\tEnvKey: \"GEMINI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"google/gemini-1.5-flash\", Name: \"Gemini 1.5 Flash\"},\n\t\t\t{ID: \"google/gemini-1.5-pro\", Name: \"Gemini 1.5 Pro\"},\n\t\t\t{ID: \"google/gemini-2.0-flash\", Name: \"Gemini 2.0 Flash\"},\n\t\t\t{ID: \"google/gemini-2.5-flash\", Name: \"Gemini 2.5 Flash\"},\n\t\t\t{ID: \"google/gemini-2.5-pro\", Name: \"Gemini 2.5 Pro\"},\n\t\t\t{ID: \"google/gemini-3-flash-preview\", Name: \"Gemini 3 Flash Preview\"},\n\t\t},\n\t},\n\t\"minimax\": {\n\t\tKey: \"minimax\",\n\t\tDisplayName: \"MiniMax (CN)\",\n\t\tSort: 70,\n\t\tDefaultBaseURL: \"https://api.minimaxi.com/anthropic\",\n\t\tEnvKey: \"MINIMAX_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"minimax/MiniMax-M2.1\", Name: \"MiniMax M2.1\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.1-lightning\", Name: \"MiniMax M2.1 Lightning\"},\n\t\t},\n\t},\n\t\"moonshot\": {\n\t\tKey: \"moonshot\",\n\t\tDisplayName: \"Moonshot (Global)\",\n\t\tSort: 80,\n\t\tDefaultBaseURL: \"https://api.moonshot.ai/v1\",\n\t\tEnvKey: \"MOONSHOT_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"moonshot/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"moonshot/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"moonshot/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n\t\"kimi\": {\n\t\tKey: \"kimi\",\n\t\tDisplayName: \"Kimi (CN)\",\n\t\tSort: 90,\n\t\tDefaultBaseURL: \"https://api.moonshot.cn/v1\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"kimi/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"kimi/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n\t\"zai\": {\n\t\tKey: \"zai\",\n\t\tDisplayName: \"Z.ai\",\n\t\tSort: 95,\n\t\tDefaultBaseURL: \"https://open.bigmodel.cn/api/paas/v4\",\n\t\tEnvKey: \"ZAI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"zai/glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"zai/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t\t{ID: \"zai/glm-4.7-flash\", Name: \"GLM-4.7-Flash\"},\n\t\t\t{ID: \"zai/glm-4.7-flashx\", Name: \"GLM-4.7-FlashX\"},\n\t\t},\n\t},\n\t\"kimi-coding\": {\n\t\tKey: \"kimi-coding\",\n\t\tDisplayName: \"Kimi Coding\",\n\t\tSort: 100,\n\t\tDefaultBaseURL: \"https://api.kimi.com/coding/\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi-coding/k2p5\", Name: \"Kimi K2.5\"},\n\t\t},\n\t},\n\t\"bailian-coding-plan\": {\n\t\tKey: \"bailian-coding-plan\",\n\t\tDisplayName: \"阿里云百炼 Coding Plan\",\n\t\tSort: 11,\n\t\tDefaultBaseURL: \"https://coding.dashscope.aliyuncs.com/v1\",\n\t\tEnvKey: \"QWEN_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"bailian-coding-plan/qwen3.5-plus\", Name: \"Qwen3.5-Plus\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-max\", Name: \"Qwen3-Max\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-next\", Name: \"Qwen3-Coder-Next\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-plus\", Name: \"Qwen3-Coder-Plus\"},\n\t\t\t{ID: \"bailian-coding-plan/minimax-m2.5\", Name: \"MiniMax M2.5\"},\n\t\t\t{ID: \"bailian-coding-plan/glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"bailian-coding-plan/kimi-k2.5\", Name: \"Kimi-k2.5\"},\n\t\t\t{ID: \"bailian-coding-plan/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t},\n\t},\n\t\"ark-coding-plan\": {\n\t\tKey: \"ark-coding-plan\",\n\t\tDisplayName: \"方舟 Coding Plan\",\n\t\tSort: 12,\n\t\tDefaultBaseURL: \"https://ark.cn-beijing.volces.com/api/coding/v3\",\n\t\tEnvKey: \"ARK_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-2.0-code\", Name: \"Doubao-Seed-2.0-Code\"},\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-code\", Name: \"Doubao-Seed-Code\"},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2.5\", Name: \"Kimi-K2.5\"},\n\t\t\t{ID: \"ark-coding-plan/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t\t{ID: \"ark-coding-plan/deepseek-v3.2\", Name: \"DeepSeek-V3.2\"},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2-thinking\", Name: \"Kimi-K2-thinking\"},\n\t\t},\n\t},\n\t\"qwen\": {\n\t\tKey: \"qwen\",\n\t\tDisplayName: \"Qwen\",\n\t\tSort: 110,\n\t\tDefaultBaseURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n\t\tEnvKey: \"QWEN_API_KEY\",\n\t\tEnabled: false,\n\t},\n}\n\nfunc Get(key string) (Meta, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn Meta{}, false\n\t}\n\treturn cloneMeta(meta), true\n}\n\nfunc All() map[string]Meta {\n\tresult := make(map[string]Meta, len(catalog))\n\tfor key, meta := range catalog {\n\t\tresult[key] = cloneMeta(meta)\n\t}\n\treturn result\n}\n\nfunc IsEnabled(key string) bool {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\treturn ok && meta.Enabled\n}\n\nfunc DefaultBaseURL(key string) (string, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok || strings.TrimSpace(meta.DefaultBaseURL) == \"\" {\n\t\treturn \"\", false\n\t}\n\treturn meta.DefaultBaseURL, true\n}\n\nfunc EnvKey(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.EnvKey\n}\n\nfunc DisplayName(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn key\n\t}\n\tif strings.TrimSpace(meta.DisplayName) == \"\" {\n\t\treturn key\n\t}\n\treturn meta.DisplayName\n}\n\nfunc cloneMeta(meta Meta) Meta {\n\tclone := meta\n\tif len(meta.Models) > 0 {\n\t\tclone.Models = make([]Model, len(meta.Models))\n\t\tcopy(clone.Models, meta.Models)\n\t}\n\treturn clone\n}\n"}, "1728511badefa814de58c45642b844715cd0ba8c": {"t": 1785755400.0933578, "n": 7571, "h": "9158164070435bf9", "c": "package provider\n\nimport (\n\t\"strings\"\n)\n\ntype Model struct {\n\tID string\n\tName string\n}\n\ntype Meta struct {\n\tKey string\n\tDisplayName string\n\tSort uint\n\tDefaultBaseURL string\n\tEnvKey string\n\tModels []Model\n\tEnabled bool\n}\n\nvar catalog = map[string]Meta{\n\t\"ollama\": {\n\t\tKey: \"ollama\",\n\t\tDisplayName: \"Ollama\",\n\t\tSort: 10,\n\t\tEnabled: true,\n\t},\n\t\"deepseek\": {\n\t\tKey: \"deepseek\",\n\t\tDisplayName: \"DeepSeek\",\n\t\tSort: 20,\n\t\tDefaultBaseURL: \"https://api.deepseek.com/v1\",\n\t\tEnvKey: \"DEEPSEEK_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"deepseek/deepseek-chat\", Name: \"DeepSeek Chat\"},\n\t\t\t{ID: \"deepseek/deepseek-reasoner\", Name: \"DeepSeek Reasoner\"},\n\t\t\t{ID: \"deepseek/deepseek-r1:1.5b\", Name: \"DeepSeek R1 1.5B\"},\n\t\t},\n\t},\n\t\"custom\": {\n\t\tKey: \"custom\",\n\t\tDisplayName: \"Custom\",\n\t\tSort: 30,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"CUSTOM_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{},\n\t},\n\t\"openai\": {\n\t\tKey: \"openai\",\n\t\tDisplayName: \"OpenAI\",\n\t\tSort: 40,\n\t\tDefaultBaseURL: \"https://api.openai.com/v1\",\n\t\tEnvKey: \"OPENAI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"openai/codex-mini-latest\", Name: \"Codex Mini\"},\n\t\t\t{ID: \"openai/gpt-4.1\", Name: \"GPT-4.1\"},\n\t\t\t{ID: \"openai/gpt-4o\", Name: \"GPT-4o\"},\n\t\t\t{ID: \"openai/gpt-4o-mini\", Name: \"GPT-4o Mini\"},\n\t\t\t{ID: \"openai/gpt-5\", Name: \"GPT-5\"},\n\t\t\t{ID: \"openai/gpt-5-mini\", Name: \"GPT-5 Mini\"},\n\t\t},\n\t},\n\t\"anthropic\": {\n\t\tKey: \"anthropic\",\n\t\tDisplayName: \"Anthropic\",\n\t\tSort: 50,\n\t\tDefaultBaseURL: \"https://api.anthropic.com\",\n\t\tEnvKey: \"ANTHROPIC_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"anthropic/claude-3-haiku-20240307\", Name: \"Claude 3 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-haiku-latest\", Name: \"Claude 3.5 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-sonnet-20241022\", Name: \"Claude 3.5 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-3-7-sonnet-20250219\", Name: \"Claude 3.7 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-opus-4-1\", Name: \"Claude Opus 4.1\"},\n\t\t},\n\t},\n\t\"gemini\": {\n\t\tKey: \"gemini\",\n\t\tDisplayName: \"Gemini\",\n\t\tSort: 60,\n\t\tDefaultBaseURL: \"https://generativelanguage.googleapis.com\",\n\t\tEnvKey: \"GEMINI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"google/gemini-1.5-flash\", Name: \"Gemini 1.5 Flash\"},\n\t\t\t{ID: \"google/gemini-1.5-pro\", Name: \"Gemini 1.5 Pro\"},\n\t\t\t{ID: \"google/gemini-2.0-flash\", Name: \"Gemini 2.0 Flash\"},\n\t\t\t{ID: \"google/gemini-2.5-flash\", Name: \"Gemini 2.5 Flash\"},\n\t\t\t{ID: \"google/gemini-2.5-pro\", Name: \"Gemini 2.5 Pro\"},\n\t\t\t{ID: \"google/gemini-3-flash-preview\", Name: \"Gemini 3 Flash Preview\"},\n\t\t},\n\t},\n\t\"minimax\": {\n\t\tKey: \"minimax\",\n\t\tDisplayName: \"MiniMax (CN)\",\n\t\tSort: 70,\n\t\tDefaultBaseURL: \"https://api.minimaxi.com/anthropic\",\n\t\tEnvKey: \"MINIMAX_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"minimax/MiniMax-M2.1\", Name: \"MiniMax M2.1\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.1-lightning\", Name: \"MiniMax M2.1 Lightning\"},\n\t\t},\n\t},\n\t\"moonshot\": {\n\t\tKey: \"moonshot\",\n\t\tDisplayName: \"Moonshot (Global)\",\n\t\tSort: 80,\n\t\tDefaultBaseURL: \"https://api.moonshot.ai/v1\",\n\t\tEnvKey: \"MOONSHOT_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"moonshot/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"moonshot/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"moonshot/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n\t\"kimi\": {\n\t\tKey: \"kimi\",\n\t\tDisplayName: \"Kimi (CN)\",\n\t\tSort: 90,\n\t\tDefaultBaseURL: \"https://api.moonshot.cn/v1\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"kimi/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"kimi/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n\t\"zai\": {\n\t\tKey: \"zai\",\n\t\tDisplayName: \"Z.ai\",\n\t\tSort: 95,\n\t\tDefaultBaseURL: \"https://open.bigmodel.cn/api/paas/v4\",\n\t\tEnvKey: \"ZAI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"zai/glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"zai/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t\t{ID: \"zai/glm-4.7-flash\", Name: \"GLM-4.7-Flash\"},\n\t\t\t{ID: \"zai/glm-4.7-flashx\", Name: \"GLM-4.7-FlashX\"},\n\t\t},\n\t},\n\t\"kimi-coding\": {\n\t\tKey: \"kimi-coding\",\n\t\tDisplayName: \"Kimi Coding\",\n\t\tSort: 100,\n\t\tDefaultBaseURL: \"https://api.kimi.com/coding/\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi-coding/k2p5\", Name: \"Kimi K2.5\"},\n\t\t},\n\t},\n\t\"bailian-coding-plan\": {\n\t\tKey: \"bailian-coding-plan\",\n\t\tDisplayName: \"阿里云百炼 Coding Plan\",\n\t\tSort: 11,\n\t\tDefaultBaseURL: \"https://coding.dashscope.aliyuncs.com/v1\",\n\t\tEnvKey: \"QWEN_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"bailian-coding-plan/qwen3.5-plus\", Name: \"Qwen3.5-Plus\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-max\", Name: \"Qwen3-Max\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-next\", Name: \"Qwen3-Coder-Next\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-plus\", Name: \"Qwen3-Coder-Plus\"},\n\t\t\t{ID: \"bailian-coding-plan/minimax-m2.5\", Name: \"MiniMax M2.5\"},\n\t\t\t{ID: \"bailian-coding-plan/glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"bailian-coding-plan/kimi-k2.5\", Name: \"Kimi-k2.5\"},\n\t\t\t{ID: \"bailian-coding-plan/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t},\n\t},\n\t\"ark-coding-plan\": {\n\t\tKey: \"ark-coding-plan\",\n\t\tDisplayName: \"方舟 Coding Plan\",\n\t\tSort: 12,\n\t\tDefaultBaseURL: \"https://ark.cn-beijing.volces.com/api/coding/v3\",\n\t\tEnvKey: \"ARK_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-2.0-code\", Name: \"Doubao-Seed-2.0-Code\"},\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-code\", Name: \"Doubao-Seed-Code\"},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2.5\", Name: \"Kimi-K2.5\"},\n\t\t\t{ID: \"ark-coding-plan/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t\t{ID: \"ark-coding-plan/deepseek-v3.2\", Name: \"DeepSeek-V3.2\"},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2-thinking\", Name: \"Kimi-K2-thinking\"},\n\t\t},\n\t},\n\t\"qwen\": {\n\t\tKey: \"qwen\",\n\t\tDisplayName: \"Qwen\",\n\t\tSort: 110,\n\t\tDefaultBaseURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n\t\tEnvKey: \"QWEN_API_KEY\",\n\t\tEnabled: false,\n\t},\n}\n\nfunc Get(key string) (Meta, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn Meta{}, false\n\t}\n\treturn cloneMeta(meta), true\n}\n\nfunc All() map[string]Meta {\n\tresult := make(map[string]Meta, len(catalog))\n\tfor key, meta := range catalog {\n\t\tresult[key] = cloneMeta(meta)\n\t}\n\treturn result\n}\n\nfunc IsEnabled(key string) bool {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\treturn ok && meta.Enabled\n}\n\nfunc DefaultBaseURL(key string) (string, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok || strings.TrimSpace(meta.DefaultBaseURL) == \"\" {\n\t\treturn \"\", false\n\t}\n\treturn meta.DefaultBaseURL, true\n}\n\nfunc EnvKey(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.EnvKey\n}\n\nfunc DisplayName(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn key\n\t}\n\tif strings.TrimSpace(meta.DisplayName) == \"\" {\n\t\treturn key\n\t}\n\treturn meta.DisplayName\n}\n\nfunc cloneMeta(meta Meta) Meta {\n\tclone := meta\n\tif len(meta.Models) > 0 {\n\t\tclone.Models = make([]Model, len(meta.Models))\n\t\tcopy(clone.Models, meta.Models)\n\t}\n\treturn clone\n}\n"}, "67155599255360c78b36f5a43b721bf4db5c0992": {"t": 1785755403.5935278, "n": 7576, "h": "f083f097ba1486dc", "c": "package provider\n\nimport (\n\t\"strings\"\n)\n\ntype Model struct {\n\tID string\n\tName string\n}\n\ntype Meta struct {\n\tKey string\n\tDisplayName string\n\tSort uint\n\tDefaultBaseURL string\n\tEnvKey string\n\tModels []Model\n\tEnabled bool\n}\n\nvar catalog = map[string]Meta{\n\t\"ollama\": {\n\t\tKey: \"ollama\",\n\t\tDisplayName: \"Ollama\",\n\t\tSort: 10,\n\t\tEnabled: true,\n\t},\n\t\"deepseek\": {\n\t\tKey: \"deepseek\",\n\t\tDisplayName: \"DeepSeek\",\n\t\tSort: 20,\n\t\tDefaultBaseURL: \"https://api.deepseek.com/v1\",\n\t\tEnvKey: \"DEEPSEEK_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"deepseek/deepseek-chat\", Name: \"DeepSeek Chat\"},\n\t\t\t{ID: \"deepseek/deepseek-reasoner\", Name: \"DeepSeek Reasoner\"},\n\t\t\t{ID: \"deepseek/deepseek-r1:1.5b\", Name: \"DeepSeek R1 1.5B\"},\n\t\t},\n\t},\n\t\"custom\": {\n\t\tKey: \"custom\",\n\t\tDisplayName: \"Custom\",\n\t\tSort: 30,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"CUSTOM_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{},\n\t},\n\t\"openai\": {\n\t\tKey: \"openai\",\n\t\tDisplayName: \"OpenAI\",\n\t\tSort: 40,\n\t\tDefaultBaseURL: \"https://api.openai.com/v1\",\n\t\tEnvKey: \"OPENAI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"openai/codex-mini-latest\", Name: \"Codex Mini\"},\n\t\t\t{ID: \"openai/gpt-4.1\", Name: \"GPT-4.1\"},\n\t\t\t{ID: \"openai/gpt-4o\", Name: \"GPT-4o\"},\n\t\t\t{ID: \"openai/gpt-4o-mini\", Name: \"GPT-4o Mini\"},\n\t\t\t{ID: \"openai/gpt-5\", Name: \"GPT-5\"},\n\t\t\t{ID: \"openai/gpt-5-mini\", Name: \"GPT-5 Mini\"},\n\t\t},\n\t},\n\t\"anthropic\": {\n\t\tKey: \"anthropic\",\n\t\tDisplayName: \"Anthropic\",\n\t\tSort: 50,\n\t\tDefaultBaseURL: \"https://api.anthropic.com\",\n\t\tEnvKey: \"ANTHROPIC_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"anthropic/claude-3-haiku-20240307\", Name: \"Claude 3 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-haiku-latest\", Name: \"Claude 3.5 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-sonnet-20241022\", Name: \"Claude 3.5 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-3-7-sonnet-20250219\", Name: \"Claude 3.7 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-opus-4-1\", Name: \"Claude Opus 4.1\"},\n\t\t},\n\t},\n\t\"gemini\": {\n\t\tKey: \"gemini\",\n\t\tDisplayName: \"Gemini\",\n\t\tSort: 60,\n\t\tDefaultBaseURL: \"https://generativelanguage.googleapis.com\",\n\t\tEnvKey: \"GEMINI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"google/gemini-1.5-flash\", Name: \"Gemini 1.5 Flash\"},\n\t\t\t{ID: \"google/gemini-1.5-pro\", Name: \"Gemini 1.5 Pro\"},\n\t\t\t{ID: \"google/gemini-2.0-flash\", Name: \"Gemini 2.0 Flash\"},\n\t\t\t{ID: \"google/gemini-2.5-flash\", Name: \"Gemini 2.5 Flash\"},\n\t\t\t{ID: \"google/gemini-2.5-pro\", Name: \"Gemini 2.5 Pro\"},\n\t\t\t{ID: \"google/gemini-3-flash-preview\", Name: \"Gemini 3 Flash Preview\"},\n\t\t},\n\t},\n\t\"minimax\": {\n\t\tKey: \"minimax\",\n\t\tDisplayName: \"MiniMax (CN)\",\n\t\tSort: 70,\n\t\tDefaultBaseURL: \"https://api.minimaxi.com/anthropic\",\n\t\tEnvKey: \"MINIMAX_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"minimax/MiniMax-M2.1\", Name: \"MiniMax M2.1\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.1-lightning\", Name: \"MiniMax M2.1 Lightning\"},\n\t\t},\n\t},\n\t\"moonshot\": {\n\t\tKey: \"moonshot\",\n\t\tDisplayName: \"Moonshot (Global)\",\n\t\tSort: 80,\n\t\tDefaultBaseURL: \"https://api.moonshot.ai/v1\",\n\t\tEnvKey: \"MOONSHOT_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"moonshot/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"moonshot/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"moonshot/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n\t\"kimi\": {\n\t\tKey: \"kimi\",\n\t\tDisplayName: \"Kimi (CN)\",\n\t\tSort: 90,\n\t\tDefaultBaseURL: \"https://api.moonshot.cn/v1\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"kimi/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"kimi/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n\t\"zai\": {\n\t\tKey: \"zai\",\n\t\tDisplayName: \"Z.ai\",\n\t\tSort: 95,\n\t\tDefaultBaseURL: \"https://open.bigmodel.cn/api/paas/v4\",\n\t\tEnvKey: \"ZAI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"zai/glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"zai/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t\t{ID: \"zai/glm-4.7-flash\", Name: \"GLM-4.7-Flash\"},\n\t\t\t{ID: \"zai/glm-4.7-flashx\", Name: \"GLM-4.7-FlashX\"},\n\t\t},\n\t},\n\t\"kimi-coding\": {\n\t\tKey: \"kimi-coding\",\n\t\tDisplayName: \"Kimi Coding\",\n\t\tSort: 100,\n\t\tDefaultBaseURL: \"https://kimi-code.moonshot.cn/api\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi-coding/k2p5\", Name: \"Kimi K2.5\"},\n\t\t},\n\t},\n\t\"bailian-coding-plan\": {\n\t\tKey: \"bailian-coding-plan\",\n\t\tDisplayName: \"阿里云百炼 Coding Plan\",\n\t\tSort: 11,\n\t\tDefaultBaseURL: \"https://coding.dashscope.aliyuncs.com/v1\",\n\t\tEnvKey: \"QWEN_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"bailian-coding-plan/qwen3.5-plus\", Name: \"Qwen3.5-Plus\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-max\", Name: \"Qwen3-Max\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-next\", Name: \"Qwen3-Coder-Next\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-plus\", Name: \"Qwen3-Coder-Plus\"},\n\t\t\t{ID: \"bailian-coding-plan/minimax-m2.5\", Name: \"MiniMax M2.5\"},\n\t\t\t{ID: \"bailian-coding-plan/glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"bailian-coding-plan/kimi-k2.5\", Name: \"Kimi-k2.5\"},\n\t\t\t{ID: \"bailian-coding-plan/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t},\n\t},\n\t\"ark-coding-plan\": {\n\t\tKey: \"ark-coding-plan\",\n\t\tDisplayName: \"方舟 Coding Plan\",\n\t\tSort: 12,\n\t\tDefaultBaseURL: \"https://ark.cn-beijing.volces.com/api/coding/v3\",\n\t\tEnvKey: \"ARK_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-2.0-code\", Name: \"Doubao-Seed-2.0-Code\"},\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-code\", Name: \"Doubao-Seed-Code\"},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2.5\", Name: \"Kimi-K2.5\"},\n\t\t\t{ID: \"ark-coding-plan/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t\t{ID: \"ark-coding-plan/deepseek-v3.2\", Name: \"DeepSeek-V3.2\"},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2-thinking\", Name: \"Kimi-K2-thinking\"},\n\t\t},\n\t},\n\t\"qwen\": {\n\t\tKey: \"qwen\",\n\t\tDisplayName: \"Qwen\",\n\t\tSort: 110,\n\t\tDefaultBaseURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n\t\tEnvKey: \"QWEN_API_KEY\",\n\t\tEnabled: false,\n\t},\n}\n\nfunc Get(key string) (Meta, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn Meta{}, false\n\t}\n\treturn cloneMeta(meta), true\n}\n\nfunc All() map[string]Meta {\n\tresult := make(map[string]Meta, len(catalog))\n\tfor key, meta := range catalog {\n\t\tresult[key] = cloneMeta(meta)\n\t}\n\treturn result\n}\n\nfunc IsEnabled(key string) bool {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\treturn ok && meta.Enabled\n}\n\nfunc DefaultBaseURL(key string) (string, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok || strings.TrimSpace(meta.DefaultBaseURL) == \"\" {\n\t\treturn \"\", false\n\t}\n\treturn meta.DefaultBaseURL, true\n}\n\nfunc EnvKey(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.EnvKey\n}\n\nfunc DisplayName(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn key\n\t}\n\tif strings.TrimSpace(meta.DisplayName) == \"\" {\n\t\treturn key\n\t}\n\treturn meta.DisplayName\n}\n\nfunc cloneMeta(meta Meta) Meta {\n\tclone := meta\n\tif len(meta.Models) > 0 {\n\t\tclone.Models = make([]Model, len(meta.Models))\n\t\tcopy(clone.Models, meta.Models)\n\t}\n\treturn clone\n}\n"}, "222702f66b7c638871c25d7538af2c36e8102af0": {"t": 1785755405.403935, "n": 7164, "h": "04126d2f4b012c24", "c": "package provider\n\nimport (\n\t\"strings\"\n)\n\ntype Model struct {\n\tID string\n\tName string\n}\n\ntype Meta struct {\n\tKey string\n\tDisplayName string\n\tSort uint\n\tDefaultBaseURL string\n\tEnvKey string\n\tModels []Model\n\tEnabled bool\n}\n\nvar catalog = map[string]Meta{\n\t\"ollama\": {\n\t\tKey: \"ollama\",\n\t\tDisplayName: \"Ollama\",\n\t\tSort: 10,\n\t\tEnabled: true,\n\t},\n\t\"deepseek\": {\n\t\tKey: \"deepseek\",\n\t\tDisplayName: \"DeepSeek\",\n\t\tSort: 20,\n\t\tDefaultBaseURL: \"https://api.deepseek.com/v1\",\n\t\tEnvKey: \"DEEPSEEK_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"deepseek/deepseek-chat\", Name: \"DeepSeek Chat\"},\n\t\t\t{ID: \"deepseek/deepseek-reasoner\", Name: \"DeepSeek Reasoner\"},\n\t\t\t{ID: \"deepseek/deepseek-r1:1.5b\", Name: \"DeepSeek R1 1.5B\"},\n\t\t},\n\t},\n\t\"custom\": {\n\t\tKey: \"custom\",\n\t\tDisplayName: \"Custom\",\n\t\tSort: 30,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"CUSTOM_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{},\n\t},\n\t\"openai\": {\n\t\tKey: \"openai\",\n\t\tDisplayName: \"OpenAI\",\n\t\tSort: 40,\n\t\tDefaultBaseURL: \"https://api.openai.com/v1\",\n\t\tEnvKey: \"OPENAI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"openai/codex-mini-latest\", Name: \"Codex Mini\"},\n\t\t\t{ID: \"openai/gpt-4.1\", Name: \"GPT-4.1\"},\n\t\t\t{ID: \"openai/gpt-4o\", Name: \"GPT-4o\"},\n\t\t\t{ID: \"openai/gpt-4o-mini\", Name: \"GPT-4o Mini\"},\n\t\t\t{ID: \"openai/gpt-5\", Name: \"GPT-5\"},\n\t\t\t{ID: \"openai/gpt-5-mini\", Name: \"GPT-5 Mini\"},\n\t\t},\n\t},\n\t\"anthropic\": {\n\t\tKey: \"anthropic\",\n\t\tDisplayName: \"Anthropic\",\n\t\tSort: 50,\n\t\tDefaultBaseURL: \"https://api.anthropic.com\",\n\t\tEnvKey: \"ANTHROPIC_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"anthropic/claude-3-haiku-20240307\", Name: \"Claude 3 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-haiku-latest\", Name: \"Claude 3.5 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-sonnet-20241022\", Name: \"Claude 3.5 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-3-7-sonnet-20250219\", Name: \"Claude 3.7 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-opus-4-1\", Name: \"Claude Opus 4.1\"},\n\t\t},\n\t},\n\t\"gemini\": {\n\t\tKey: \"gemini\",\n\t\tDisplayName: \"Gemini\",\n\t\tSort: 60,\n\t\tDefaultBaseURL: \"https://generativelanguage.googleapis.com\",\n\t\tEnvKey: \"GEMINI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"google/gemini-1.5-flash\", Name: \"Gemini 1.5 Flash\"},\n\t\t\t{ID: \"google/gemini-1.5-pro\", Name: \"Gemini 1.5 Pro\"},\n\t\t\t{ID: \"google/gemini-2.0-flash\", Name: \"Gemini 2.0 Flash\"},\n\t\t\t{ID: \"google/gemini-2.5-flash\", Name: \"Gemini 2.5 Flash\"},\n\t\t\t{ID: \"google/gemini-2.5-pro\", Name: \"Gemini 2.5 Pro\"},\n\t\t\t{ID: \"google/gemini-3-flash-preview\", Name: \"Gemini 3 Flash Preview\"},\n\t\t},\n\t},\n\t\"minimax\": {\n\t\tKey: \"minimax\",\n\t\tDisplayName: \"MiniMax (CN)\",\n\t\tSort: 70,\n\t\tDefaultBaseURL: \"https://api.minimaxi.com/anthropic\",\n\t\tEnvKey: \"MINIMAX_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"minimax/MiniMax-M2.1\", Name: \"MiniMax M2.1\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.1-lightning\", Name: \"MiniMax M2.1 Lightning\"},\n\t\t},\n\t},\n\t\"moonshot\": {\n\t\tKey: \"moonshot\",\n\t\tDisplayName: \"Moonshot (Global)\",\n\t\tSort: 80,\n\t\tDefaultBaseURL: \"https://api.moonshot.ai/v1\",\n\t\tEnvKey: \"MOONSHOT_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"moonshot/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"moonshot/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"moonshot/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n\t\"kimi\": {\n\t\tKey: \"kimi\",\n\t\tDisplayName: \"Kimi (CN)\",\n\t\tSort: 90,\n\t\tDefaultBaseURL: \"https://api.moonshot.cn/v1\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"kimi/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"kimi/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n\t\"kimi-coding\": {\n\t\tKey: \"kimi-coding\",\n\t\tDisplayName: \"Kimi Coding\",\n\t\tSort: 100,\n\t\tDefaultBaseURL: \"https://kimi-code.moonshot.cn/api\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi-coding/k2p5\", Name: \"Kimi K2.5\"},\n\t\t},\n\t},\n\t\"bailian-coding-plan\": {\n\t\tKey: \"bailian-coding-plan\",\n\t\tDisplayName: \"阿里云百炼 Coding Plan\",\n\t\tSort: 11,\n\t\tDefaultBaseURL: \"https://coding.dashscope.aliyuncs.com/v1\",\n\t\tEnvKey: \"QWEN_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"bailian-coding-plan/qwen3.5-plus\", Name: \"Qwen3.5-Plus\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-max\", Name: \"Qwen3-Max\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-next\", Name: \"Qwen3-Coder-Next\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-plus\", Name: \"Qwen3-Coder-Plus\"},\n\t\t\t{ID: \"bailian-coding-plan/minimax-m2.5\", Name: \"MiniMax M2.5\"},\n\t\t\t{ID: \"bailian-coding-plan/glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"bailian-coding-plan/kimi-k2.5\", Name: \"Kimi-k2.5\"},\n\t\t\t{ID: \"bailian-coding-plan/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t},\n\t},\n\t\"ark-coding-plan\": {\n\t\tKey: \"ark-coding-plan\",\n\t\tDisplayName: \"方舟 Coding Plan\",\n\t\tSort: 12,\n\t\tDefaultBaseURL: \"https://ark.cn-beijing.volces.com/api/coding/v3\",\n\t\tEnvKey: \"ARK_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-2.0-code\", Name: \"Doubao-Seed-2.0-Code\"},\n\t\t\t{ID: \"ark-coding-plan/doubao-seed-code\", Name: \"Doubao-Seed-Code\"},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2.5\", Name: \"Kimi-K2.5\"},\n\t\t\t{ID: \"ark-coding-plan/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t\t{ID: \"ark-coding-plan/deepseek-v3.2\", Name: \"DeepSeek-V3.2\"},\n\t\t\t{ID: \"ark-coding-plan/kimi-k2-thinking\", Name: \"Kimi-K2-thinking\"},\n\t\t},\n\t},\n\t\"qwen\": {\n\t\tKey: \"qwen\",\n\t\tDisplayName: \"Qwen\",\n\t\tSort: 110,\n\t\tDefaultBaseURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n\t\tEnvKey: \"QWEN_API_KEY\",\n\t\tEnabled: false,\n\t},\n}\n\nfunc Get(key string) (Meta, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn Meta{}, false\n\t}\n\treturn cloneMeta(meta), true\n}\n\nfunc All() map[string]Meta {\n\tresult := make(map[string]Meta, len(catalog))\n\tfor key, meta := range catalog {\n\t\tresult[key] = cloneMeta(meta)\n\t}\n\treturn result\n}\n\nfunc IsEnabled(key string) bool {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\treturn ok && meta.Enabled\n}\n\nfunc DefaultBaseURL(key string) (string, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok || strings.TrimSpace(meta.DefaultBaseURL) == \"\" {\n\t\treturn \"\", false\n\t}\n\treturn meta.DefaultBaseURL, true\n}\n\nfunc EnvKey(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.EnvKey\n}\n\nfunc DisplayName(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn key\n\t}\n\tif strings.TrimSpace(meta.DisplayName) == \"\" {\n\t\treturn key\n\t}\n\treturn meta.DisplayName\n}\n\nfunc cloneMeta(meta Meta) Meta {\n\tclone := meta\n\tif len(meta.Models) > 0 {\n\t\tclone.Models = make([]Model, len(meta.Models))\n\t\tcopy(clone.Models, meta.Models)\n\t}\n\treturn clone\n}\n"}, "d155217ce3b31d01cddffa69ada9a89fb4269d4f": {"t": 1785755406.7336738, "n": 6497, "h": "0956b23c2382c718", "c": "package provider\n\nimport (\n\t\"strings\"\n)\n\ntype Model struct {\n\tID string\n\tName string\n}\n\ntype Meta struct {\n\tKey string\n\tDisplayName string\n\tSort uint\n\tDefaultBaseURL string\n\tEnvKey string\n\tModels []Model\n\tEnabled bool\n}\n\nvar catalog = map[string]Meta{\n\t\"ollama\": {\n\t\tKey: \"ollama\",\n\t\tDisplayName: \"Ollama\",\n\t\tSort: 10,\n\t\tEnabled: true,\n\t},\n\t\"deepseek\": {\n\t\tKey: \"deepseek\",\n\t\tDisplayName: \"DeepSeek\",\n\t\tSort: 20,\n\t\tDefaultBaseURL: \"https://api.deepseek.com/v1\",\n\t\tEnvKey: \"DEEPSEEK_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"deepseek/deepseek-chat\", Name: \"DeepSeek Chat\"},\n\t\t\t{ID: \"deepseek/deepseek-reasoner\", Name: \"DeepSeek Reasoner\"},\n\t\t\t{ID: \"deepseek/deepseek-r1:1.5b\", Name: \"DeepSeek R1 1.5B\"},\n\t\t},\n\t},\n\t\"custom\": {\n\t\tKey: \"custom\",\n\t\tDisplayName: \"Custom\",\n\t\tSort: 30,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"CUSTOM_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{},\n\t},\n\t\"openai\": {\n\t\tKey: \"openai\",\n\t\tDisplayName: \"OpenAI\",\n\t\tSort: 40,\n\t\tDefaultBaseURL: \"https://api.openai.com/v1\",\n\t\tEnvKey: \"OPENAI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"openai/codex-mini-latest\", Name: \"Codex Mini\"},\n\t\t\t{ID: \"openai/gpt-4.1\", Name: \"GPT-4.1\"},\n\t\t\t{ID: \"openai/gpt-4o\", Name: \"GPT-4o\"},\n\t\t\t{ID: \"openai/gpt-4o-mini\", Name: \"GPT-4o Mini\"},\n\t\t\t{ID: \"openai/gpt-5\", Name: \"GPT-5\"},\n\t\t\t{ID: \"openai/gpt-5-mini\", Name: \"GPT-5 Mini\"},\n\t\t},\n\t},\n\t\"anthropic\": {\n\t\tKey: \"anthropic\",\n\t\tDisplayName: \"Anthropic\",\n\t\tSort: 50,\n\t\tDefaultBaseURL: \"https://api.anthropic.com\",\n\t\tEnvKey: \"ANTHROPIC_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"anthropic/claude-3-haiku-20240307\", Name: \"Claude 3 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-haiku-latest\", Name: \"Claude 3.5 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-sonnet-20241022\", Name: \"Claude 3.5 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-3-7-sonnet-20250219\", Name: \"Claude 3.7 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-opus-4-1\", Name: \"Claude Opus 4.1\"},\n\t\t},\n\t},\n\t\"gemini\": {\n\t\tKey: \"gemini\",\n\t\tDisplayName: \"Gemini\",\n\t\tSort: 60,\n\t\tDefaultBaseURL: \"https://generativelanguage.googleapis.com\",\n\t\tEnvKey: \"GEMINI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"google/gemini-1.5-flash\", Name: \"Gemini 1.5 Flash\"},\n\t\t\t{ID: \"google/gemini-1.5-pro\", Name: \"Gemini 1.5 Pro\"},\n\t\t\t{ID: \"google/gemini-2.0-flash\", Name: \"Gemini 2.0 Flash\"},\n\t\t\t{ID: \"google/gemini-2.5-flash\", Name: \"Gemini 2.5 Flash\"},\n\t\t\t{ID: \"google/gemini-2.5-pro\", Name: \"Gemini 2.5 Pro\"},\n\t\t\t{ID: \"google/gemini-3-flash-preview\", Name: \"Gemini 3 Flash Preview\"},\n\t\t},\n\t},\n\t\"minimax\": {\n\t\tKey: \"minimax\",\n\t\tDisplayName: \"MiniMax (CN)\",\n\t\tSort: 70,\n\t\tDefaultBaseURL: \"https://api.minimaxi.com/anthropic\",\n\t\tEnvKey: \"MINIMAX_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"minimax/MiniMax-M2.1\", Name: \"MiniMax M2.1\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.1-lightning\", Name: \"MiniMax M2.1 Lightning\"},\n\t\t},\n\t},\n\t\"moonshot\": {\n\t\tKey: \"moonshot\",\n\t\tDisplayName: \"Moonshot (Global)\",\n\t\tSort: 80,\n\t\tDefaultBaseURL: \"https://api.moonshot.ai/v1\",\n\t\tEnvKey: \"MOONSHOT_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"moonshot/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"moonshot/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"moonshot/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n\t\"kimi\": {\n\t\tKey: \"kimi\",\n\t\tDisplayName: \"Kimi (CN)\",\n\t\tSort: 90,\n\t\tDefaultBaseURL: \"https://api.moonshot.cn/v1\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"kimi/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"kimi/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n\t\"kimi-coding\": {\n\t\tKey: \"kimi-coding\",\n\t\tDisplayName: \"Kimi Coding\",\n\t\tSort: 100,\n\t\tDefaultBaseURL: \"https://kimi-code.moonshot.cn/api\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi-coding/k2p5\", Name: \"Kimi K2.5\"},\n\t\t},\n\t},\n\t\"bailian-coding-plan\": {\n\t\tKey: \"bailian-coding-plan\",\n\t\tDisplayName: \"阿里云百炼 Coding Plan\",\n\t\tSort: 11,\n\t\tDefaultBaseURL: \"https://coding.dashscope.aliyuncs.com/v1\",\n\t\tEnvKey: \"QWEN_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"bailian-coding-plan/qwen3.5-plus\", Name: \"Qwen3.5-Plus\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-max\", Name: \"Qwen3-Max\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-next\", Name: \"Qwen3-Coder-Next\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-plus\", Name: \"Qwen3-Coder-Plus\"},\n\t\t\t{ID: \"bailian-coding-plan/minimax-m2.5\", Name: \"MiniMax M2.5\"},\n\t\t\t{ID: \"bailian-coding-plan/glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"bailian-coding-plan/kimi-k2.5\", Name: \"Kimi-k2.5\"},\n\t\t\t{ID: \"bailian-coding-plan/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t},\n\t},\n\t\"qwen\": {\n\t\tKey: \"qwen\",\n\t\tDisplayName: \"Qwen\",\n\t\tSort: 110,\n\t\tDefaultBaseURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n\t\tEnvKey: \"QWEN_API_KEY\",\n\t\tEnabled: false,\n\t},\n}\n\nfunc Get(key string) (Meta, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn Meta{}, false\n\t}\n\treturn cloneMeta(meta), true\n}\n\nfunc All() map[string]Meta {\n\tresult := make(map[string]Meta, len(catalog))\n\tfor key, meta := range catalog {\n\t\tresult[key] = cloneMeta(meta)\n\t}\n\treturn result\n}\n\nfunc IsEnabled(key string) bool {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\treturn ok && meta.Enabled\n}\n\nfunc DefaultBaseURL(key string) (string, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok || strings.TrimSpace(meta.DefaultBaseURL) == \"\" {\n\t\treturn \"\", false\n\t}\n\treturn meta.DefaultBaseURL, true\n}\n\nfunc EnvKey(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.EnvKey\n}\n\nfunc DisplayName(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn key\n\t}\n\tif strings.TrimSpace(meta.DisplayName) == \"\" {\n\t\treturn key\n\t}\n\treturn meta.DisplayName\n}\n\nfunc cloneMeta(meta Meta) Meta {\n\tclone := meta\n\tif len(meta.Models) > 0 {\n\t\tclone.Models = make([]Model, len(meta.Models))\n\t\tcopy(clone.Models, meta.Models)\n\t}\n\treturn clone\n}\n"}, "4b2d6f0ef2a74d4dfa33995dfdb031a8663c34cf": {"t": 1785755408.2275722, "n": 6498, "h": "5298ab0166c2e415", "c": "package provider\n\nimport (\n\t\"strings\"\n)\n\ntype Model struct {\n\tID string\n\tName string\n}\n\ntype Meta struct {\n\tKey string\n\tDisplayName string\n\tSort uint\n\tDefaultBaseURL string\n\tEnvKey string\n\tModels []Model\n\tEnabled bool\n}\n\nvar catalog = map[string]Meta{\n\t\"ollama\": {\n\t\tKey: \"ollama\",\n\t\tDisplayName: \"Ollama\",\n\t\tSort: 10,\n\t\tEnabled: true,\n\t},\n\t\"deepseek\": {\n\t\tKey: \"deepseek\",\n\t\tDisplayName: \"DeepSeek\",\n\t\tSort: 20,\n\t\tDefaultBaseURL: \"https://api.deepseek.com/v1\",\n\t\tEnvKey: \"DEEPSEEK_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"deepseek/deepseek-chat\", Name: \"DeepSeek Chat\"},\n\t\t\t{ID: \"deepseek/deepseek-reasoner\", Name: \"DeepSeek Reasoner\"},\n\t\t\t{ID: \"deepseek/deepseek-r1:1.5b\", Name: \"DeepSeek R1 1.5B\"},\n\t\t},\n\t},\n\t\"custom\": {\n\t\tKey: \"custom\",\n\t\tDisplayName: \"Custom\",\n\t\tSort: 30,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"CUSTOM_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{},\n\t},\n\t\"openai\": {\n\t\tKey: \"openai\",\n\t\tDisplayName: \"OpenAI\",\n\t\tSort: 40,\n\t\tDefaultBaseURL: \"https://api.openai.com/v1\",\n\t\tEnvKey: \"OPENAI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"openai/codex-mini-latest\", Name: \"Codex Mini\"},\n\t\t\t{ID: \"openai/gpt-4.1\", Name: \"GPT-4.1\"},\n\t\t\t{ID: \"openai/gpt-4o\", Name: \"GPT-4o\"},\n\t\t\t{ID: \"openai/gpt-4o-mini\", Name: \"GPT-4o Mini\"},\n\t\t\t{ID: \"openai/gpt-5\", Name: \"GPT-5\"},\n\t\t\t{ID: \"openai/gpt-5-mini\", Name: \"GPT-5 Mini\"},\n\t\t},\n\t},\n\t\"anthropic\": {\n\t\tKey: \"anthropic\",\n\t\tDisplayName: \"Anthropic\",\n\t\tSort: 50,\n\t\tDefaultBaseURL: \"https://api.anthropic.com\",\n\t\tEnvKey: \"ANTHROPIC_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"anthropic/claude-3-haiku-20240307\", Name: \"Claude 3 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-haiku-latest\", Name: \"Claude 3.5 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-sonnet-20241022\", Name: \"Claude 3.5 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-3-7-sonnet-20250219\", Name: \"Claude 3.7 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-opus-4-1\", Name: \"Claude Opus 4.1\"},\n\t\t},\n\t},\n\t\"gemini\": {\n\t\tKey: \"gemini\",\n\t\tDisplayName: \"Gemini\",\n\t\tSort: 60,\n\t\tDefaultBaseURL: \"https://generativelanguage.googleapis.com\",\n\t\tEnvKey: \"GEMINI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"google/gemini-1.5-flash\", Name: \"Gemini 1.5 Flash\"},\n\t\t\t{ID: \"google/gemini-1.5-pro\", Name: \"Gemini 1.5 Pro\"},\n\t\t\t{ID: \"google/gemini-2.0-flash\", Name: \"Gemini 2.0 Flash\"},\n\t\t\t{ID: \"google/gemini-2.5-flash\", Name: \"Gemini 2.5 Flash\"},\n\t\t\t{ID: \"google/gemini-2.5-pro\", Name: \"Gemini 2.5 Pro\"},\n\t\t\t{ID: \"google/gemini-3-flash-preview\", Name: \"Gemini 3 Flash Preview\"},\n\t\t},\n\t},\n\t\"minimax\": {\n\t\tKey: \"minimax\",\n\t\tDisplayName: \"MiniMax (CN)\",\n\t\tSort: 70,\n\t\tDefaultBaseURL: \"https://api.minimaxi.com/anthropic\",\n\t\tEnvKey: \"MINIMAX_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"minimax/MiniMax-M2.1\", Name: \"MiniMax M2.1\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.1-lightning\", Name: \"MiniMax M2.1 Lightning\"},\n\t\t},\n\t},\n\t\"moonshot\": {\n\t\tKey: \"moonshot\",\n\t\tDisplayName: \"Moonshot (Global)\",\n\t\tSort: 80,\n\t\tDefaultBaseURL: \"https://api.moonshot.ai/v1\",\n\t\tEnvKey: \"MOONSHOT_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"moonshot/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"moonshot/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"moonshot/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n\t\"kimi\": {\n\t\tKey: \"kimi\",\n\t\tDisplayName: \"Kimi (CN)\",\n\t\tSort: 90,\n\t\tDefaultBaseURL: \"https://api.moonshot.cn/v1\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"kimi/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"kimi/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n\t\"kimi-coding\": {\n\t\tKey: \"kimi-coding\",\n\t\tDisplayName: \"Kimi Coding\",\n\t\tSort: 100,\n\t\tDefaultBaseURL: \"https://kimi-code.moonshot.cn/api\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi-coding/k2p5\", Name: \"Kimi K2.5\"},\n\t\t},\n\t},\n\t\"bailian-coding-plan\": {\n\t\tKey: \"bailian-coding-plan\",\n\t\tDisplayName: \"阿里云百炼 Coding Plan\",\n\t\tSort: 105,\n\t\tDefaultBaseURL: \"https://coding.dashscope.aliyuncs.com/v1\",\n\t\tEnvKey: \"QWEN_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"bailian-coding-plan/qwen3.5-plus\", Name: \"Qwen3.5-Plus\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-max\", Name: \"Qwen3-Max\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-next\", Name: \"Qwen3-Coder-Next\"},\n\t\t\t{ID: \"bailian-coding-plan/qwen3-coder-plus\", Name: \"Qwen3-Coder-Plus\"},\n\t\t\t{ID: \"bailian-coding-plan/minimax-m2.5\", Name: \"MiniMax M2.5\"},\n\t\t\t{ID: \"bailian-coding-plan/glm-5\", Name: \"GLM-5\"},\n\t\t\t{ID: \"bailian-coding-plan/kimi-k2.5\", Name: \"Kimi-k2.5\"},\n\t\t\t{ID: \"bailian-coding-plan/glm-4.7\", Name: \"GLM-4.7\"},\n\t\t},\n\t},\n\t\"qwen\": {\n\t\tKey: \"qwen\",\n\t\tDisplayName: \"Qwen\",\n\t\tSort: 110,\n\t\tDefaultBaseURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n\t\tEnvKey: \"QWEN_API_KEY\",\n\t\tEnabled: false,\n\t},\n}\n\nfunc Get(key string) (Meta, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn Meta{}, false\n\t}\n\treturn cloneMeta(meta), true\n}\n\nfunc All() map[string]Meta {\n\tresult := make(map[string]Meta, len(catalog))\n\tfor key, meta := range catalog {\n\t\tresult[key] = cloneMeta(meta)\n\t}\n\treturn result\n}\n\nfunc IsEnabled(key string) bool {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\treturn ok && meta.Enabled\n}\n\nfunc DefaultBaseURL(key string) (string, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok || strings.TrimSpace(meta.DefaultBaseURL) == \"\" {\n\t\treturn \"\", false\n\t}\n\treturn meta.DefaultBaseURL, true\n}\n\nfunc EnvKey(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.EnvKey\n}\n\nfunc DisplayName(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn key\n\t}\n\tif strings.TrimSpace(meta.DisplayName) == \"\" {\n\t\treturn key\n\t}\n\treturn meta.DisplayName\n}\n\nfunc cloneMeta(meta Meta) Meta {\n\tclone := meta\n\tif len(meta.Models) > 0 {\n\t\tclone.Models = make([]Model, len(meta.Models))\n\t\tcopy(clone.Models, meta.Models)\n\t}\n\treturn clone\n}\n"}, "8cead06d7ba8d61832a4cd7fa4e266309d76d46e": {"t": 1785755409.6226633, "n": 5705, "h": "5282aa0468718392", "c": "package provider\n\nimport (\n\t\"strings\"\n)\n\ntype Model struct {\n\tID string\n\tName string\n}\n\ntype Meta struct {\n\tKey string\n\tDisplayName string\n\tSort uint\n\tDefaultBaseURL string\n\tEnvKey string\n\tModels []Model\n\tEnabled bool\n}\n\nvar catalog = map[string]Meta{\n\t\"ollama\": {\n\t\tKey: \"ollama\",\n\t\tDisplayName: \"Ollama\",\n\t\tSort: 10,\n\t\tEnabled: true,\n\t},\n\t\"deepseek\": {\n\t\tKey: \"deepseek\",\n\t\tDisplayName: \"DeepSeek\",\n\t\tSort: 20,\n\t\tDefaultBaseURL: \"https://api.deepseek.com/v1\",\n\t\tEnvKey: \"DEEPSEEK_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"deepseek/deepseek-chat\", Name: \"DeepSeek Chat\"},\n\t\t\t{ID: \"deepseek/deepseek-reasoner\", Name: \"DeepSeek Reasoner\"},\n\t\t\t{ID: \"deepseek/deepseek-r1:1.5b\", Name: \"DeepSeek R1 1.5B\"},\n\t\t},\n\t},\n\t\"custom\": {\n\t\tKey: \"custom\",\n\t\tDisplayName: \"Custom\",\n\t\tSort: 30,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"CUSTOM_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{},\n\t},\n\t\"openai\": {\n\t\tKey: \"openai\",\n\t\tDisplayName: \"OpenAI\",\n\t\tSort: 40,\n\t\tDefaultBaseURL: \"https://api.openai.com/v1\",\n\t\tEnvKey: \"OPENAI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"openai/codex-mini-latest\", Name: \"Codex Mini\"},\n\t\t\t{ID: \"openai/gpt-4.1\", Name: \"GPT-4.1\"},\n\t\t\t{ID: \"openai/gpt-4o\", Name: \"GPT-4o\"},\n\t\t\t{ID: \"openai/gpt-4o-mini\", Name: \"GPT-4o Mini\"},\n\t\t\t{ID: \"openai/gpt-5\", Name: \"GPT-5\"},\n\t\t\t{ID: \"openai/gpt-5-mini\", Name: \"GPT-5 Mini\"},\n\t\t},\n\t},\n\t\"anthropic\": {\n\t\tKey: \"anthropic\",\n\t\tDisplayName: \"Anthropic\",\n\t\tSort: 50,\n\t\tDefaultBaseURL: \"https://api.anthropic.com\",\n\t\tEnvKey: \"ANTHROPIC_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"anthropic/claude-3-haiku-20240307\", Name: \"Claude 3 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-haiku-latest\", Name: \"Claude 3.5 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-sonnet-20241022\", Name: \"Claude 3.5 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-3-7-sonnet-20250219\", Name: \"Claude 3.7 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-opus-4-1\", Name: \"Claude Opus 4.1\"},\n\t\t},\n\t},\n\t\"gemini\": {\n\t\tKey: \"gemini\",\n\t\tDisplayName: \"Gemini\",\n\t\tSort: 60,\n\t\tDefaultBaseURL: \"https://generativelanguage.googleapis.com\",\n\t\tEnvKey: \"GEMINI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"google/gemini-1.5-flash\", Name: \"Gemini 1.5 Flash\"},\n\t\t\t{ID: \"google/gemini-1.5-pro\", Name: \"Gemini 1.5 Pro\"},\n\t\t\t{ID: \"google/gemini-2.0-flash\", Name: \"Gemini 2.0 Flash\"},\n\t\t\t{ID: \"google/gemini-2.5-flash\", Name: \"Gemini 2.5 Flash\"},\n\t\t\t{ID: \"google/gemini-2.5-pro\", Name: \"Gemini 2.5 Pro\"},\n\t\t\t{ID: \"google/gemini-3-flash-preview\", Name: \"Gemini 3 Flash Preview\"},\n\t\t},\n\t},\n\t\"minimax\": {\n\t\tKey: \"minimax\",\n\t\tDisplayName: \"MiniMax (CN)\",\n\t\tSort: 70,\n\t\tDefaultBaseURL: \"https://api.minimaxi.com/anthropic\",\n\t\tEnvKey: \"MINIMAX_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"minimax/MiniMax-M2.1\", Name: \"MiniMax M2.1\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.1-lightning\", Name: \"MiniMax M2.1 Lightning\"},\n\t\t},\n\t},\n\t\"moonshot\": {\n\t\tKey: \"moonshot\",\n\t\tDisplayName: \"Moonshot (Global)\",\n\t\tSort: 80,\n\t\tDefaultBaseURL: \"https://api.moonshot.ai/v1\",\n\t\tEnvKey: \"MOONSHOT_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"moonshot/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"moonshot/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"moonshot/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n\t\"kimi\": {\n\t\tKey: \"kimi\",\n\t\tDisplayName: \"Kimi (CN)\",\n\t\tSort: 90,\n\t\tDefaultBaseURL: \"https://api.moonshot.cn/v1\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"kimi/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"kimi/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n\t\"kimi-coding\": {\n\t\tKey: \"kimi-coding\",\n\t\tDisplayName: \"Kimi Coding\",\n\t\tSort: 100,\n\t\tDefaultBaseURL: \"https://kimi-code.moonshot.cn/api\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi-coding/k2p5\", Name: \"Kimi K2.5\"},\n\t\t},\n\t},\n\t\"qwen\": {\n\t\tKey: \"qwen\",\n\t\tDisplayName: \"Qwen\",\n\t\tSort: 110,\n\t\tDefaultBaseURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n\t\tEnvKey: \"QWEN_API_KEY\",\n\t\tEnabled: false,\n\t},\n}\n\nfunc Get(key string) (Meta, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn Meta{}, false\n\t}\n\treturn cloneMeta(meta), true\n}\n\nfunc All() map[string]Meta {\n\tresult := make(map[string]Meta, len(catalog))\n\tfor key, meta := range catalog {\n\t\tresult[key] = cloneMeta(meta)\n\t}\n\treturn result\n}\n\nfunc IsEnabled(key string) bool {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\treturn ok && meta.Enabled\n}\n\nfunc DefaultBaseURL(key string) (string, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok || strings.TrimSpace(meta.DefaultBaseURL) == \"\" {\n\t\treturn \"\", false\n\t}\n\treturn meta.DefaultBaseURL, true\n}\n\nfunc EnvKey(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.EnvKey\n}\n\nfunc DisplayName(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn key\n\t}\n\tif strings.TrimSpace(meta.DisplayName) == \"\" {\n\t\treturn key\n\t}\n\treturn meta.DisplayName\n}\n\nfunc cloneMeta(meta Meta) Meta {\n\tclone := meta\n\tif len(meta.Models) > 0 {\n\t\tclone.Models = make([]Model, len(meta.Models))\n\t\tcopy(clone.Models, meta.Models)\n\t}\n\treturn clone\n}\n"}, "a77e61a861a0f3bdb7cbab03133d756ba4f3c65d": {"t": 1785755411.3170712, "n": 5708, "h": "df596683b449168d", "c": "package provider\n\nimport (\n\t\"strings\"\n)\n\ntype Model struct {\n\tID string\n\tName string\n}\n\ntype Meta struct {\n\tKey string\n\tDisplayName string\n\tSort uint\n\tDefaultBaseURL string\n\tEnvKey string\n\tModels []Model\n\tEnabled bool\n}\n\nvar catalog = map[string]Meta{\n\t\"ollama\": {\n\t\tKey: \"ollama\",\n\t\tDisplayName: \"Ollama\",\n\t\tSort: 10,\n\t\tEnabled: true,\n\t},\n\t\"deepseek\": {\n\t\tKey: \"deepseek\",\n\t\tDisplayName: \"DeepSeek\",\n\t\tSort: 20,\n\t\tDefaultBaseURL: \"https://api.deepseek.com/v1\",\n\t\tEnvKey: \"DEEPSEEK_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"deepseek/deepseek-chat\", Name: \"DeepSeek Chat\"},\n\t\t\t{ID: \"deepseek/deepseek-reasoner\", Name: \"DeepSeek Reasoner\"},\n\t\t\t{ID: \"deepseek/deepseek-r1:1.5b\", Name: \"DeepSeek R1 1.5B\"},\n\t\t},\n\t},\n\t\"custom\": {\n\t\tKey: \"custom\",\n\t\tDisplayName: \"Custom\",\n\t\tSort: 30,\n\t\tDefaultBaseURL: \"\",\n\t\tEnvKey: \"CUSTOM_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{},\n\t},\n\t\"openai\": {\n\t\tKey: \"openai\",\n\t\tDisplayName: \"OpenAI\",\n\t\tSort: 40,\n\t\tDefaultBaseURL: \"https://api.openai.com/v1\",\n\t\tEnvKey: \"OPENAI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"openai/codex-mini-latest\", Name: \"Codex Mini\"},\n\t\t\t{ID: \"openai/gpt-4.1\", Name: \"GPT-4.1\"},\n\t\t\t{ID: \"openai/gpt-4o\", Name: \"GPT-4o\"},\n\t\t\t{ID: \"openai/gpt-4o-mini\", Name: \"GPT-4o Mini\"},\n\t\t\t{ID: \"openai/gpt-5\", Name: \"GPT-5\"},\n\t\t\t{ID: \"openai/gpt-5-mini\", Name: \"GPT-5 Mini\"},\n\t\t},\n\t},\n\t\"anthropic\": {\n\t\tKey: \"anthropic\",\n\t\tDisplayName: \"Anthropic\",\n\t\tSort: 50,\n\t\tDefaultBaseURL: \"https://api.anthropic.com\",\n\t\tEnvKey: \"ANTHROPIC_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"anthropic/claude-3-haiku-20240307\", Name: \"Claude 3 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-haiku-latest\", Name: \"Claude 3.5 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-sonnet-20241022\", Name: \"Claude 3.5 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-3-7-sonnet-20250219\", Name: \"Claude 3.7 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-opus-4-1\", Name: \"Claude Opus 4.1\"},\n\t\t},\n\t},\n\t\"gemini\": {\n\t\tKey: \"gemini\",\n\t\tDisplayName: \"Gemini\",\n\t\tSort: 60,\n\t\tDefaultBaseURL: \"https://generativelanguage.googleapis.com\",\n\t\tEnvKey: \"GEMINI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"google/gemini-1.5-flash\", Name: \"Gemini 1.5 Flash\"},\n\t\t\t{ID: \"google/gemini-1.5-pro\", Name: \"Gemini 1.5 Pro\"},\n\t\t\t{ID: \"google/gemini-2.0-flash\", Name: \"Gemini 2.0 Flash\"},\n\t\t\t{ID: \"google/gemini-2.5-flash\", Name: \"Gemini 2.5 Flash\"},\n\t\t\t{ID: \"google/gemini-2.5-pro\", Name: \"Gemini 2.5 Pro\"},\n\t\t\t{ID: \"google/gemini-3-flash-preview\", Name: \"Gemini 3 Flash Preview\"},\n\t\t},\n\t},\n\t\"minimax\": {\n\t\tKey: \"minimax\",\n\t\tDisplayName: \"MiniMax (CN)\",\n\t\tSort: 70,\n\t\tDefaultBaseURL: \"https://api.minimaxi.com/anthropic\",\n\t\tEnvKey: \"MINIMAX_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"minimax/MiniMax-M2.1\", Name: \"MiniMax M2.1\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.1-lightning\", Name: \"MiniMax M2.1 Lightning\"},\n\t\t},\n\t},\n\t\"moonshot\": {\n\t\tKey: \"moonshot\",\n\t\tDisplayName: \"Moonshot (Global)\",\n\t\tSort: 80,\n\t\tDefaultBaseURL: \"https://api.moonshot.ai/v1\",\n\t\tEnvKey: \"MOONSHOT_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"moonshot/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"moonshot/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"moonshot/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n\t\"kimi\": {\n\t\tKey: \"kimi\",\n\t\tDisplayName: \"Kimi (CN)\",\n\t\tSort: 90,\n\t\tDefaultBaseURL: \"https://api.moonshot.cn/v1\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"kimi/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"kimi/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n\t\"kimi-coding\": {\n\t\tKey: \"kimi-coding\",\n\t\tDisplayName: \"Kimi Coding\",\n\t\tSort: 100,\n\t\tDefaultBaseURL: \"https://api.moonshot.cn/anthropic/v1\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi-coding/k2p5\", Name: \"Kimi K2.5\"},\n\t\t},\n\t},\n\t\"qwen\": {\n\t\tKey: \"qwen\",\n\t\tDisplayName: \"Qwen\",\n\t\tSort: 110,\n\t\tDefaultBaseURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n\t\tEnvKey: \"QWEN_API_KEY\",\n\t\tEnabled: false,\n\t},\n}\n\nfunc Get(key string) (Meta, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn Meta{}, false\n\t}\n\treturn cloneMeta(meta), true\n}\n\nfunc All() map[string]Meta {\n\tresult := make(map[string]Meta, len(catalog))\n\tfor key, meta := range catalog {\n\t\tresult[key] = cloneMeta(meta)\n\t}\n\treturn result\n}\n\nfunc IsEnabled(key string) bool {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\treturn ok && meta.Enabled\n}\n\nfunc DefaultBaseURL(key string) (string, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok || strings.TrimSpace(meta.DefaultBaseURL) == \"\" {\n\t\treturn \"\", false\n\t}\n\treturn meta.DefaultBaseURL, true\n}\n\nfunc EnvKey(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.EnvKey\n}\n\nfunc DisplayName(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn key\n\t}\n\tif strings.TrimSpace(meta.DisplayName) == \"\" {\n\t\treturn key\n\t}\n\treturn meta.DisplayName\n}\n\nfunc cloneMeta(meta Meta) Meta {\n\tclone := meta\n\tif len(meta.Models) > 0 {\n\t\tclone.Models = make([]Model, len(meta.Models))\n\t\tcopy(clone.Models, meta.Models)\n\t}\n\treturn clone\n}\n"}, "65a7193bc670551422ba1248c6f4995be3d2be6b": {"t": 1785755412.6700132, "n": 5486, "h": "05bd939d5cda372b", "c": "package provider\n\nimport \"strings\"\n\ntype Model struct {\n\tID string\n\tName string\n}\n\ntype Meta struct {\n\tKey string\n\tDisplayName string\n\tSort uint\n\tDefaultBaseURL string\n\tEnvKey string\n\tModels []Model\n\tEnabled bool\n}\n\nvar catalog = map[string]Meta{\n\t\"ollama\": {\n\t\tKey: \"ollama\",\n\t\tDisplayName: \"Ollama\",\n\t\tSort: 1,\n\t\tEnabled: true,\n\t},\n\t\"deepseek\": {\n\t\tKey: \"deepseek\",\n\t\tDisplayName: \"DeepSeek\",\n\t\tSort: 2,\n\t\tDefaultBaseURL: \"https://api.deepseek.com/v1\",\n\t\tEnvKey: \"DEEPSEEK_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"deepseek/deepseek-chat\", Name: \"DeepSeek Chat\"},\n\t\t\t{ID: \"deepseek/deepseek-reasoner\", Name: \"DeepSeek Reasoner\"},\n\t\t\t{ID: \"deepseek/deepseek-r1:1.5b\", Name: \"DeepSeek R1 1.5B\"},\n\t\t},\n\t},\n\t\"openai\": {\n\t\tKey: \"openai\",\n\t\tDisplayName: \"OpenAI\",\n\t\tSort: 3,\n\t\tDefaultBaseURL: \"https://api.openai.com/v1\",\n\t\tEnvKey: \"OPENAI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"openai/codex-mini-latest\", Name: \"Codex Mini\"},\n\t\t\t{ID: \"openai/gpt-4.1\", Name: \"GPT-4.1\"},\n\t\t\t{ID: \"openai/gpt-4o\", Name: \"GPT-4o\"},\n\t\t\t{ID: \"openai/gpt-4o-mini\", Name: \"GPT-4o Mini\"},\n\t\t\t{ID: \"openai/gpt-5\", Name: \"GPT-5\"},\n\t\t\t{ID: \"openai/gpt-5-mini\", Name: \"GPT-5 Mini\"},\n\t\t},\n\t},\n\t\"anthropic\": {\n\t\tKey: \"anthropic\",\n\t\tDisplayName: \"Anthropic\",\n\t\tSort: 4,\n\t\tDefaultBaseURL: \"https://api.anthropic.com\",\n\t\tEnvKey: \"ANTHROPIC_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"anthropic/claude-3-haiku-20240307\", Name: \"Claude 3 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-haiku-latest\", Name: \"Claude 3.5 Haiku\"},\n\t\t\t{ID: \"anthropic/claude-3-5-sonnet-20241022\", Name: \"Claude 3.5 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-3-7-sonnet-20250219\", Name: \"Claude 3.7 Sonnet\"},\n\t\t\t{ID: \"anthropic/claude-opus-4-1\", Name: \"Claude Opus 4.1\"},\n\t\t},\n\t},\n\t\"gemini\": {\n\t\tKey: \"gemini\",\n\t\tDisplayName: \"Gemini\",\n\t\tSort: 5,\n\t\tDefaultBaseURL: \"https://generativelanguage.googleapis.com\",\n\t\tEnvKey: \"GEMINI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"google/gemini-1.5-flash\", Name: \"Gemini 1.5 Flash\"},\n\t\t\t{ID: \"google/gemini-1.5-pro\", Name: \"Gemini 1.5 Pro\"},\n\t\t\t{ID: \"google/gemini-2.0-flash\", Name: \"Gemini 2.0 Flash\"},\n\t\t\t{ID: \"google/gemini-2.5-flash\", Name: \"Gemini 2.5 Flash\"},\n\t\t\t{ID: \"google/gemini-2.5-pro\", Name: \"Gemini 2.5 Pro\"},\n\t\t\t{ID: \"google/gemini-3-flash-preview\", Name: \"Gemini 3 Flash Preview\"},\n\t\t},\n\t},\n\t\"minimax\": {\n\t\tKey: \"minimax\",\n\t\tDisplayName: \"MiniMax (CN)\",\n\t\tSort: 6,\n\t\tDefaultBaseURL: \"https://api.minimaxi.com/anthropic\",\n\t\tEnvKey: \"MINIMAX_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"minimax/MiniMax-M2.1\", Name: \"MiniMax M2.1\"},\n\t\t\t{ID: \"minimax/MiniMax-M2.1-lightning\", Name: \"MiniMax M2.1 Lightning\"},\n\t\t},\n\t},\n\t\"moonshot\": {\n\t\tKey: \"moonshot\",\n\t\tDisplayName: \"Moonshot (Global)\",\n\t\tSort: 7,\n\t\tDefaultBaseURL: \"https://api.moonshot.ai/v1\",\n\t\tEnvKey: \"MOONSHOT_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"moonshot/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"moonshot/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"moonshot/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n\t\"kimi\": {\n\t\tKey: \"kimi\",\n\t\tDisplayName: \"Kimi (CN)\",\n\t\tSort: 8,\n\t\tDefaultBaseURL: \"https://api.moonshot.cn/v1\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi/kimi-k2.5\", Name: \"Kimi K2.5\"},\n\t\t\t{ID: \"kimi/kimi-k2-0905-preview\", Name: \"Kimi K2 0905 Preview\"},\n\t\t\t{ID: \"kimi/kimi-k2-thinking\", Name: \"Kimi K2 Thinking\"},\n\t\t},\n\t},\n\t\"kimi-coding\": {\n\t\tKey: \"kimi-coding\",\n\t\tDisplayName: \"Kimi Coding\",\n\t\tSort: 9,\n\t\tDefaultBaseURL: \"https://api.moonshot.cn/anthropic/v1\",\n\t\tEnvKey: \"KIMI_API_KEY\",\n\t\tEnabled: true,\n\t\tModels: []Model{\n\t\t\t{ID: \"kimi-coding/k2p5\", Name: \"Kimi K2.5\"},\n\t\t},\n\t},\n\t\"qwen\": {\n\t\tKey: \"qwen\",\n\t\tDisplayName: \"Qwen\",\n\t\tSort: 10,\n\t\tDefaultBaseURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n\t\tEnvKey: \"QWEN_API_KEY\",\n\t\tEnabled: false,\n\t},\n}\n\nfunc Get(key string) (Meta, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn Meta{}, false\n\t}\n\treturn cloneMeta(meta), true\n}\n\nfunc All() map[string]Meta {\n\tresult := make(map[string]Meta, len(catalog))\n\tfor key, meta := range catalog {\n\t\tresult[key] = cloneMeta(meta)\n\t}\n\treturn result\n}\n\nfunc IsEnabled(key string) bool {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\treturn ok && meta.Enabled\n}\n\nfunc DefaultBaseURL(key string) (string, bool) {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok || strings.TrimSpace(meta.DefaultBaseURL) == \"\" {\n\t\treturn \"\", false\n\t}\n\treturn meta.DefaultBaseURL, true\n}\n\nfunc EnvKey(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn \"\"\n\t}\n\treturn meta.EnvKey\n}\n\nfunc DisplayName(key string) string {\n\tmeta, ok := catalog[strings.ToLower(strings.TrimSpace(key))]\n\tif !ok {\n\t\treturn key\n\t}\n\tif strings.TrimSpace(meta.DisplayName) == \"\" {\n\t\treturn key\n\t}\n\treturn meta.DisplayName\n}\n\nfunc cloneMeta(meta Meta) Meta {\n\tclone := meta\n\tif len(meta.Models) > 0 {\n\t\tclone.Models = make([]Model, len(meta.Models))\n\t\tcopy(clone.Models, meta.Models)\n\t}\n\treturn clone\n}\n"}}, "agent/init/migration/migrations/utils/agent_account_model_pool.go": {"60d16609f7fac966ef45fc15ab11cd387cb6016b": {"t": 1785746094.090185, "n": 4193, "h": "fbbdf27dd34df103", "c": "package utils\n\nimport (\n\t\"encoding/json\"\n\t\"strings\"\n\n\t\"github.com/1Panel-dev/1Panel/agent/app/dto\"\n\t\"github.com/1Panel-dev/1Panel/agent/app/model\"\n\tprovidercatalog \"github.com/1Panel-dev/1Panel/agent/app/provider\"\n\t\"github.com/1Panel-dev/1Panel/agent/app/service\"\n\n\t\"gorm.io/gorm\"\n)\n\ntype legacyAgentAccountModelPoolSource struct {\n\tmodel.AgentAccount\n\tLegacyModel string `gorm:\"column:model\"`\n\tLegacyModels string `gorm:\"column:models\"`\n}\n\nfunc MigrateAgentAccountModelPool(tx *gorm.DB) error {\n\tvar accounts []legacyAgentAccountModelPoolSource\n\tif err := tx.Table(model.AgentAccount{}.TableName()).Find(&accounts).Error; err != nil {\n\t\treturn err\n\t}\n\tfor _, account := range accounts {\n\t\tcount := int64(0)\n\t\tif err := tx.Model(&model.AgentAccountModel{}).Where(\"account_id = ?\", account.ID).Count(&count).Error; err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif count > 0 {\n\t\t\tcontinue\n\t\t}\n\t\tmodels, err := buildMigratedAgentAccountModels(tx, &account)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif len(models) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tfor index, item := range models {\n\t\t\trecord := &model.AgentAccountModel{\n\t\t\t\tAccountID: account.ID,\n\t\t\t\tModel: item.ID,\n\t\t\t\tName: item.Name,\n\t\t\t\tSortOrder: index + 1,\n\t\t\t}\n\t\t\tif err := tx.Create(record).Error; err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc buildMigratedAgentAccountModels(tx *gorm.DB, account *legacyAgentAccountModelPoolSource) ([]dto.AgentAccountModel, error) {\n\tif account == nil {\n\t\treturn nil, nil\n\t}\n\tbaseAccount := account.AgentAccount\n\trequested := make([]dto.AgentAccountModel, 0)\n\tif strings.TrimSpace(account.LegacyModels) != \"\" {\n\t\tif err := json.Unmarshal([]byte(account.LegacyModels), &requested); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\tseen := make(map[string]struct{}, len(requested))\n\tfor _, item := range requested {\n\t\ttarget := strings.TrimSpace(item.ID)\n\t\tif target == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tseen[target] = struct{}{}\n\t}\n\tappendModel := func(modelID string) {\n\t\ttarget := strings.TrimSpace(modelID)\n\t\tif target == \"\" {\n\t\t\treturn\n\t\t}\n\t\tif _, ok := seen[target]; ok {\n\t\t\treturn\n\t\t}\n\t\tseen[target] = struct{}{}\n\t\trequested = append(requested, dto.AgentAccountModel{ID: target})\n\t}\n\tappendModel(account.LegacyModel)\n\tif account.ID > 0 {\n\t\tvar agents []model.Agent\n\t\tif err := tx.Where(\"account_id = ?\", account.ID).Find(&agents).Error; err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tfor _, agent := range agents {\n\t\t\tappendModel(agent.Model)\n\t\t}\n\t}\n\tmodels, err := service.MergeCatalogAgentAccountModelsForMigration(&baseAccount, requested)\n\tif err != nil {\n\t\tif strings.TrimSpace(err.Error()) == \"model is required\" {\n\t\t\treturn nil, nil\n\t\t}\n\t\treturn nil, err\n\t}\n\treturn models, nil\n}\n\nfunc NormalizeAgentAccountModelIDs(tx *gorm.DB) error {\n\tvar accounts []model.AgentAccount\n\tif err := tx.Find(&accounts).Error; err != nil {\n\t\treturn err\n\t}\n\tfor _, account := range accounts {\n\t\tvar accountModels []model.AgentAccountModel\n\t\tif err := tx.Where(\"account_id = ?\", account.ID).Find(&accountModels).Error; err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfor _, item := range accountModels {\n\t\t\tnormalized := providercatalog.NormalizeModelID(account.Provider, item.Model)\n\t\t\tif normalized != item.Model {\n\t\t\t\tif err := tx.Model(&model.AgentAccountModel{}).Where(\"id = ?\", item.ID).Update(\"model\", normalized).Error; err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tvar agents []model.Agent\n\t\tif err := tx.Where(\"account_id = ?\", account.ID).Find(&agents).Error; err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfor _, agent := range agents {\n\t\t\tnormalized := providercatalog.NormalizeModelID(account.Provider, agent.Model)\n\t\t\tif normalized != agent.Model {\n\t\t\t\tif err := tx.Model(&model.Agent{}).Where(\"id = ?\", agent.ID).Update(\"model\", normalized).Error; err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif err := tx.Model(&model.AgentAccount{}).\n\t\tWhere(\"provider = ? AND api_type = ? AND (base_url = '' OR base_url = ? OR base_url = ?)\", \"deepseek\", \"anthropic-messages\", \"https://api.deepseek.com\", \"https://api.deepseek.com/v1\").\n\t\tUpdate(\"base_url\", \"https://api.deepseek.com/anthropic\").Error; err != nil {\n\t\treturn err\n\t}\n\treturn tx.Model(&model.AgentAccount{}).\n\t\tWhere(\"provider = ?\", \"gemini\").\n\t\tUpdate(\"api_type\", \"gemini-generate-content\").Error\n}\n"}, "8b265bb81ecf6276df0188595230317f2770c1ac": {"t": 1785755371.9878416, "n": 4193, "h": "fbbdf27dd34df103", "c": "package utils\n\nimport (\n\t\"encoding/json\"\n\t\"strings\"\n\n\t\"github.com/1Panel-dev/1Panel/agent/app/dto\"\n\t\"github.com/1Panel-dev/1Panel/agent/app/model\"\n\tprovidercatalog \"github.com/1Panel-dev/1Panel/agent/app/provider\"\n\t\"github.com/1Panel-dev/1Panel/agent/app/service\"\n\n\t\"gorm.io/gorm\"\n)\n\ntype legacyAgentAccountModelPoolSource struct {\n\tmodel.AgentAccount\n\tLegacyModel string `gorm:\"column:model\"`\n\tLegacyModels string `gorm:\"column:models\"`\n}\n\nfunc MigrateAgentAccountModelPool(tx *gorm.DB) error {\n\tvar accounts []legacyAgentAccountModelPoolSource\n\tif err := tx.Table(model.AgentAccount{}.TableName()).Find(&accounts).Error; err != nil {\n\t\treturn err\n\t}\n\tfor _, account := range accounts {\n\t\tcount := int64(0)\n\t\tif err := tx.Model(&model.AgentAccountModel{}).Where(\"account_id = ?\", account.ID).Count(&count).Error; err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif count > 0 {\n\t\t\tcontinue\n\t\t}\n\t\tmodels, err := buildMigratedAgentAccountModels(tx, &account)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif len(models) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tfor index, item := range models {\n\t\t\trecord := &model.AgentAccountModel{\n\t\t\t\tAccountID: account.ID,\n\t\t\t\tModel: item.ID,\n\t\t\t\tName: item.Name,\n\t\t\t\tSortOrder: index + 1,\n\t\t\t}\n\t\t\tif err := tx.Create(record).Error; err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc buildMigratedAgentAccountModels(tx *gorm.DB, account *legacyAgentAccountModelPoolSource) ([]dto.AgentAccountModel, error) {\n\tif account == nil {\n\t\treturn nil, nil\n\t}\n\tbaseAccount := account.AgentAccount\n\trequested := make([]dto.AgentAccountModel, 0)\n\tif strings.TrimSpace(account.LegacyModels) != \"\" {\n\t\tif err := json.Unmarshal([]byte(account.LegacyModels), &requested); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\tseen := make(map[string]struct{}, len(requested))\n\tfor _, item := range requested {\n\t\ttarget := strings.TrimSpace(item.ID)\n\t\tif target == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tseen[target] = struct{}{}\n\t}\n\tappendModel := func(modelID string) {\n\t\ttarget := strings.TrimSpace(modelID)\n\t\tif target == \"\" {\n\t\t\treturn\n\t\t}\n\t\tif _, ok := seen[target]; ok {\n\t\t\treturn\n\t\t}\n\t\tseen[target] = struct{}{}\n\t\trequested = append(requested, dto.AgentAccountModel{ID: target})\n\t}\n\tappendModel(account.LegacyModel)\n\tif account.ID > 0 {\n\t\tvar agents []model.Agent\n\t\tif err := tx.Where(\"account_id = ?\", account.ID).Find(&agents).Error; err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tfor _, agent := range agents {\n\t\t\tappendModel(agent.Model)\n\t\t}\n\t}\n\tmodels, err := service.MergeCatalogAgentAccountModelsForMigration(&baseAccount, requested)\n\tif err != nil {\n\t\tif strings.TrimSpace(err.Error()) == \"model is required\" {\n\t\t\treturn nil, nil\n\t\t}\n\t\treturn nil, err\n\t}\n\treturn models, nil\n}\n\nfunc NormalizeAgentAccountModelIDs(tx *gorm.DB) error {\n\tvar accounts []model.AgentAccount\n\tif err := tx.Find(&accounts).Error; err != nil {\n\t\treturn err\n\t}\n\tfor _, account := range accounts {\n\t\tvar accountModels []model.AgentAccountModel\n\t\tif err := tx.Where(\"account_id = ?\", account.ID).Find(&accountModels).Error; err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfor _, item := range accountModels {\n\t\t\tnormalized := providercatalog.NormalizeModelID(account.Provider, item.Model)\n\t\t\tif normalized != item.Model {\n\t\t\t\tif err := tx.Model(&model.AgentAccountModel{}).Where(\"id = ?\", item.ID).Update(\"model\", normalized).Error; err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tvar agents []model.Agent\n\t\tif err := tx.Where(\"account_id = ?\", account.ID).Find(&agents).Error; err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfor _, agent := range agents {\n\t\t\tnormalized := providercatalog.NormalizeModelID(account.Provider, agent.Model)\n\t\t\tif normalized != agent.Model {\n\t\t\t\tif err := tx.Model(&model.Agent{}).Where(\"id = ?\", agent.ID).Update(\"model\", normalized).Error; err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif err := tx.Model(&model.AgentAccount{}).\n\t\tWhere(\"provider = ? AND api_type = ? AND (base_url = '' OR base_url = ? OR base_url = ?)\", \"deepseek\", \"anthropic-messages\", \"https://api.deepseek.com\", \"https://api.deepseek.com/v1\").\n\t\tUpdate(\"base_url\", \"https://api.deepseek.com/anthropic\").Error; err != nil {\n\t\treturn err\n\t}\n\treturn tx.Model(&model.AgentAccount{}).\n\t\tWhere(\"provider = ?\", \"gemini\").\n\t\tUpdate(\"api_type\", \"gemini-generate-content\").Error\n}\n"}, "2d78ca5a869c832a31e4e5eae1b9419cd5245cd7": {"t": 1785755373.5609682, "n": 3527, "h": "a05aef61c9070d86", "c": "package utils\n\nimport (\n\t\"encoding/json\"\n\t\"strings\"\n\n\t\"github.com/1Panel-dev/1Panel/agent/app/dto\"\n\t\"github.com/1Panel-dev/1Panel/agent/app/model\"\n\tprovidercatalog \"github.com/1Panel-dev/1Panel/agent/app/provider\"\n\t\"github.com/1Panel-dev/1Panel/agent/app/service\"\n\n\t\"gorm.io/gorm\"\n)\n\ntype legacyAgentAccountModelPoolSource struct {\n\tmodel.AgentAccount\n\tLegacyModel string `gorm:\"column:model\"`\n\tLegacyModels string `gorm:\"column:models\"`\n}\n\nfunc MigrateAgentAccountModelPool(tx *gorm.DB) error {\n\tvar accounts []legacyAgentAccountModelPoolSource\n\tif err := tx.Table(model.AgentAccount{}.TableName()).Find(&accounts).Error; err != nil {\n\t\treturn err\n\t}\n\tfor _, account := range accounts {\n\t\tcount := int64(0)\n\t\tif err := tx.Model(&model.AgentAccountModel{}).Where(\"account_id = ?\", account.ID).Count(&count).Error; err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif count > 0 {\n\t\t\tcontinue\n\t\t}\n\t\tmodels, err := buildMigratedAgentAccountModels(tx, &account)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif len(models) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tfor index, item := range models {\n\t\t\tinputPayload, err := json.Marshal(item.Input)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\trecord := &model.AgentAccountModel{\n\t\t\t\tAccountID: account.ID,\n\t\t\t\tModel: item.ID,\n\t\t\t\tName: item.Name,\n\t\t\t\tContextWindow: item.ContextWindow,\n\t\t\t\tMaxTokens: item.MaxTokens,\n\t\t\t\tReasoning: item.Reasoning,\n\t\t\t\tInput: string(inputPayload),\n\t\t\t\tSortOrder: index + 1,\n\t\t\t}\n\t\t\tif err := tx.Create(record).Error; err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc buildMigratedAgentAccountModels(tx *gorm.DB, account *legacyAgentAccountModelPoolSource) ([]dto.AgentAccountModel, error) {\n\tif account == nil {\n\t\treturn nil, nil\n\t}\n\tbaseAccount := account.AgentAccount\n\trequested := make([]dto.AgentAccountModel, 0)\n\tif strings.TrimSpace(account.LegacyModels) != \"\" {\n\t\tif err := json.Unmarshal([]byte(account.LegacyModels), &requested); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\tseen := make(map[string]struct{}, len(requested))\n\tfor _, item := range requested {\n\t\ttarget := strings.TrimSpace(item.ID)\n\t\tif target == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tseen[target] = struct{}{}\n\t}\n\tappendModel := func(modelID string) {\n\t\ttarget := strings.TrimSpace(modelID)\n\t\tif target == \"\" {\n\t\t\treturn\n\t\t}\n\t\tif _, ok := seen[target]; ok {\n\t\t\treturn\n\t\t}\n\t\tseen[target] = struct{}{}\n\t\trequested = append(requested, dto.AgentAccountModel{ID: target})\n\t}\n\tappendModel(account.LegacyModel)\n\tif account.ID > 0 {\n\t\tvar agents []model.Agent\n\t\tif err := tx.Where(\"account_id = ?\", account.ID).Find(&agents).Error; err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tfor _, agent := range agents {\n\t\t\tappendModel(agent.Model)\n\t\t}\n\t}\n\tmodels, err := service.MergeCatalogAgentAccountModelsForMigration(&baseAccount, requested)\n\tif err != nil {\n\t\tif strings.TrimSpace(err.Error()) == \"model is required\" {\n\t\t\treturn nil, nil\n\t\t}\n\t\treturn nil, err\n\t}\n\tapplyLegacyAgentAccountModelDefaults(account.Provider, models)\n\treturn models, nil\n}\n\nfunc applyLegacyAgentAccountModelDefaults(provider string, models []dto.AgentAccountModel) {\n\tif provider != \"custom\" && provider != \"ollama\" && provider != \"vllm\" {\n\t\treturn\n\t}\n\tmeta, ok := providercatalog.Get(provider)\n\tif !ok {\n\t\treturn\n\t}\n\tfor i := range models {\n\t\tif strings.TrimSpace(models[i].Name) == \"\" {\n\t\t\tmodels[i].Name = strings.TrimSpace(models[i].ID)\n\t\t}\n\t\tif models[i].ContextWindow <= 0 {\n\t\t\tmodels[i].ContextWindow = meta.Default.ContextWindow\n\t\t}\n\t\tif models[i].MaxTokens <= 0 {\n\t\t\tmodels[i].MaxTokens = meta.Default.MaxTokens\n\t\t}\n\t}\n}\n"}, "fa843f0940dc6e26a42176ed93f173b9d90649fe": {"t": 1785755375.3321848, "n": 2839, "h": "64784fb30ddc5760", "c": "package utils\n\nimport (\n\t\"encoding/json\"\n\t\"strings\"\n\n\t\"github.com/1Panel-dev/1Panel/agent/app/dto\"\n\t\"github.com/1Panel-dev/1Panel/agent/app/model\"\n\t\"github.com/1Panel-dev/1Panel/agent/app/service\"\n\n\t\"gorm.io/gorm\"\n)\n\ntype legacyAgentAccountModelPoolSource struct {\n\tmodel.AgentAccount\n\tLegacyModel string `gorm:\"column:model\"`\n\tLegacyModels string `gorm:\"column:models\"`\n}\n\nfunc MigrateAgentAccountModelPool(tx *gorm.DB) error {\n\tvar accounts []legacyAgentAccountModelPoolSource\n\tif err := tx.Table(model.AgentAccount{}.TableName()).Find(&accounts).Error; err != nil {\n\t\treturn err\n\t}\n\tfor _, account := range accounts {\n\t\tcount := int64(0)\n\t\tif err := tx.Model(&model.AgentAccountModel{}).Where(\"account_id = ?\", account.ID).Count(&count).Error; err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif count > 0 {\n\t\t\tcontinue\n\t\t}\n\t\tmodels, err := buildMigratedAgentAccountModels(tx, &account)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif len(models) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tfor index, item := range models {\n\t\t\tinputPayload, err := json.Marshal(item.Input)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\trecord := &model.AgentAccountModel{\n\t\t\t\tAccountID: account.ID,\n\t\t\t\tModel: item.ID,\n\t\t\t\tName: item.Name,\n\t\t\t\tContextWindow: item.ContextWindow,\n\t\t\t\tMaxTokens: item.MaxTokens,\n\t\t\t\tReasoning: item.Reasoning,\n\t\t\t\tInput: string(inputPayload),\n\t\t\t\tSortOrder: index + 1,\n\t\t\t}\n\t\t\tif err := tx.Create(record).Error; err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc buildMigratedAgentAccountModels(tx *gorm.DB, account *legacyAgentAccountModelPoolSource) ([]dto.AgentAccountModel, error) {\n\tif account == nil {\n\t\treturn nil, nil\n\t}\n\tbaseAccount := account.AgentAccount\n\trequested := make([]dto.AgentAccountModel, 0)\n\tif strings.TrimSpace(account.LegacyModels) != \"\" {\n\t\tif err := json.Unmarshal([]byte(account.LegacyModels), &requested); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\tseen := make(map[string]struct{}, len(requested))\n\tfor _, item := range requested {\n\t\ttarget := strings.TrimSpace(item.ID)\n\t\tif target == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tseen[target] = struct{}{}\n\t}\n\tappendModel := func(modelID string) {\n\t\ttarget := strings.TrimSpace(modelID)\n\t\tif target == \"\" {\n\t\t\treturn\n\t\t}\n\t\tif _, ok := seen[target]; ok {\n\t\t\treturn\n\t\t}\n\t\tseen[target] = struct{}{}\n\t\trequested = append(requested, dto.AgentAccountModel{ID: target})\n\t}\n\tappendModel(account.LegacyModel)\n\tif account.ID > 0 {\n\t\tvar agents []model.Agent\n\t\tif err := tx.Where(\"account_id = ?\", account.ID).Find(&agents).Error; err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tfor _, agent := range agents {\n\t\t\tappendModel(agent.Model)\n\t\t}\n\t}\n\tmodels, err := service.MergeCatalogAgentAccountModelsForMigration(&baseAccount, requested)\n\tif err != nil {\n\t\tif strings.TrimSpace(err.Error()) == \"model is required\" {\n\t\t\treturn nil, nil\n\t\t}\n\t\treturn nil, err\n\t}\n\treturn models, nil\n}\n"}, "c68251cada085b951dbbb487475d81d02ad89be2": {"t": 1785755376.7459598, "n": 2551, "h": "beaca7300798a4bd", "c": "package utils\n\nimport (\n\t\"encoding/json\"\n\t\"strings\"\n\n\t\"github.com/1Panel-dev/1Panel/agent/app/dto\"\n\t\"github.com/1Panel-dev/1Panel/agent/app/model\"\n\t\"github.com/1Panel-dev/1Panel/agent/app/service\"\n\n\t\"gorm.io/gorm\"\n)\n\nfunc MigrateAgentAccountModelPool(tx *gorm.DB) error {\n\tvar accounts []model.AgentAccount\n\tif err := tx.Find(&accounts).Error; err != nil {\n\t\treturn err\n\t}\n\tfor _, account := range accounts {\n\t\tcount := int64(0)\n\t\tif err := tx.Model(&model.AgentAccountModel{}).Where(\"account_id = ?\", account.ID).Count(&count).Error; err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif count > 0 {\n\t\t\tcontinue\n\t\t}\n\t\tmodels, err := buildMigratedAgentAccountModels(tx, &account)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif len(models) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tfor index, item := range models {\n\t\t\tinputPayload, err := json.Marshal(item.Input)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\trecord := &model.AgentAccountModel{\n\t\t\t\tAccountID: account.ID,\n\t\t\t\tModel: item.ID,\n\t\t\t\tName: item.Name,\n\t\t\t\tContextWindow: item.ContextWindow,\n\t\t\t\tMaxTokens: item.MaxTokens,\n\t\t\t\tReasoning: item.Reasoning,\n\t\t\t\tInput: string(inputPayload),\n\t\t\t\tSortOrder: index + 1,\n\t\t\t}\n\t\t\tif err := tx.Create(record).Error; err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc buildMigratedAgentAccountModels(tx *gorm.DB, account *model.AgentAccount) ([]dto.AgentAccountModel, error) {\n\tif account == nil {\n\t\treturn nil, nil\n\t}\n\trequested := make([]dto.AgentAccountModel, 0)\n\tif strings.TrimSpace(account.Models) != \"\" {\n\t\tif err := json.Unmarshal([]byte(account.Models), &requested); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\tseen := make(map[string]struct{}, len(requested))\n\tfor _, item := range requested {\n\t\ttarget := strings.TrimSpace(item.ID)\n\t\tif target == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tseen[target] = struct{}{}\n\t}\n\tappendModel := func(modelID string) {\n\t\ttarget := strings.TrimSpace(modelID)\n\t\tif target == \"\" {\n\t\t\treturn\n\t\t}\n\t\tif _, ok := seen[target]; ok {\n\t\t\treturn\n\t\t}\n\t\tseen[target] = struct{}{}\n\t\trequested = append(requested, dto.AgentAccountModel{ID: target})\n\t}\n\tappendModel(account.Model)\n\tif account.ID > 0 {\n\t\tvar agents []model.Agent\n\t\tif err := tx.Where(\"account_id = ?\", account.ID).Find(&agents).Error; err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tfor _, agent := range agents {\n\t\t\tappendModel(agent.Model)\n\t\t}\n\t}\n\tmodels, err := service.MergeCatalogAgentAccountModelsForMigration(account, requested)\n\tif err != nil {\n\t\tif strings.TrimSpace(err.Error()) == \"model is required\" {\n\t\t\treturn nil, nil\n\t\t}\n\t\treturn nil, err\n\t}\n\treturn models, nil\n}\n"}}}}