mirror of
https://github.com/alibaba/open-code-review.git
synced 2026-07-09 17:28:58 +00:00
* feat(llm): add z-ai-coding provider for GLM Coding Plan endpoint Z.AI (智谱) subscribers to the GLM Coding Plan must route requests through the dedicated coding endpoint (https://open.bigmodel.cn/api/coding/paas/v4) for them to be billed against the subscription quota. The existing z-ai provider points at the generic pay-as-you-go endpoint (https://open.bigmodel.cn/api/paas/v4), so Coding Plan keys silently drain the wallet balance instead of consuming the plan quota, surfacing as a spurious "1113 余额不足" error even when the plan is barely used. Add a dedicated z-ai-coding provider following the existing *-tokenplan pattern (dashscope/dashscope-tokenplan, tencent-tokenhub/hy-tokenplan). It reuses Z_AI_API_KEY — the same key authenticates against both endpoints, so selecting this provider is all that's needed to activate the plan. The model list is restricted to the models officially supported by the Coding Plan to avoid selecting a non-plan model that falls back to wallet billing. - internal/llm/providers.go: register z-ai-coding preset - extensions/vscode/src/shared/providers.ts: mirror the preset (kept in sync with the Go registry per the file header) - internal/llm/providers_test.go: update the sorted provider list assertion Co-Authored-By: Oz <oz-agent@warp.dev> * docs(pages): add Z.AI GLM Coding Plan config tip to docs page Subscribers to the Z.AI (Zhipu) GLM Coding Plan must route requests through the dedicated coding endpoint (https://open.bigmodel.cn/api/coding/paas/v4) to bill against the plan quota. The default z-ai preset points at the generic pay-as-you-go endpoint, so coding-plan keys silently drain the wallet and surface a spurious "1113 余额不足" error — a recurring trap for new users. Add a provider-specific callout at the end of the Docs config section showing the one-line fix that works today on any released version: ocr config set providers.z-ai.url https://open.bigmodel.cn/api/coding/paas/v4 This complements the z-ai-coding provider added in the previous commit: the provider gives a native first-class option going forward, while this doc tip rescues users already running released builds. Copy/localized for zh/en/ja. Co-Authored-By: Oz <oz-agent@warp.dev> * fix(llm): address review feedback for z-ai-coding provider - Switch z-ai-coding to a dedicated Z_AI_CODING_API_KEY env var instead of reusing Z_AI_API_KEY, matching the tokenplan-provider convention so pay-as-you-go and Coding Plan keys can be configured independently - Remove comment blocks from the z-ai-coding presets (Go and TS) to keep the registry as plain data consistent with the other entries - Revert pages/ changes (i18n + DocsPage.tsx); provider docs are out of scope for a provider-registration PR Co-Authored-By: Oz <oz-agent@warp.dev> --------- Co-authored-by: mountainwu <mountainwu@kuainiugroup.com> Co-authored-by: Oz <oz-agent@warp.dev>
269 lines
5.9 KiB
Go
269 lines
5.9 KiB
Go
package llm
|
|
|
|
import (
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
// Provider holds the preset configuration for a known LLM provider.
|
|
type Provider struct {
|
|
Name string
|
|
DisplayName string
|
|
Protocol string // "anthropic" or "openai"
|
|
BaseURL string
|
|
AuthHeader string // Anthropic-only; empty for OpenAI-compatible
|
|
EnvVar string // environment variable name for API key fallback
|
|
Models []string
|
|
}
|
|
|
|
var registry = []Provider{
|
|
{
|
|
Name: "anthropic",
|
|
DisplayName: "Anthropic Claude API",
|
|
Protocol: "anthropic",
|
|
BaseURL: "https://api.anthropic.com",
|
|
AuthHeader: "x-api-key",
|
|
EnvVar: "ANTHROPIC_API_KEY",
|
|
Models: []string{
|
|
"claude-opus-4-8",
|
|
"claude-opus-4-7",
|
|
"claude-opus-4-6",
|
|
"claude-sonnet-4-6",
|
|
},
|
|
},
|
|
{
|
|
Name: "openai",
|
|
DisplayName: "OpenAI API",
|
|
Protocol: "openai",
|
|
BaseURL: "https://api.openai.com/v1",
|
|
EnvVar: "OPENAI_API_KEY",
|
|
Models: []string{
|
|
"gpt-5.5",
|
|
"gpt-5.4",
|
|
"gpt-5.4-mini",
|
|
},
|
|
},
|
|
{
|
|
Name: "dashscope",
|
|
DisplayName: "Alibaba DashScope API",
|
|
Protocol: "openai",
|
|
BaseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1",
|
|
EnvVar: "DASHSCOPE_API_KEY",
|
|
Models: []string{
|
|
"qwen3.7-max",
|
|
"qwen3.7-plus",
|
|
"qwen3.6-plus",
|
|
"qwen3.6-flash",
|
|
"deepseek-v4-pro",
|
|
"deepseek-v4-flash",
|
|
"kimi-k2.7-code",
|
|
"glm-5.2",
|
|
"MiniMax-M2.5",
|
|
},
|
|
},
|
|
{
|
|
Name: "dashscope-tokenplan",
|
|
DisplayName: "Alibaba DashScope Token Plan API",
|
|
Protocol: "openai",
|
|
BaseURL: "https://token-plan.cn-beijing.maas.aliyuncs.com/compatible-mode/v1",
|
|
EnvVar: "DASHSCOPE_TOKENPLAN_KEY",
|
|
Models: []string{
|
|
"qwen3.7-max",
|
|
"qwen3.7-plus",
|
|
"qwen3.6-plus",
|
|
"qwen3.6-flash",
|
|
"deepseek-v4-pro",
|
|
"deepseek-v4-flash",
|
|
"kimi-k2.7-code",
|
|
"kimi-k2.6",
|
|
"kimi-k2.5",
|
|
"glm-5.2",
|
|
"glm-5.1",
|
|
"glm-5",
|
|
"MiniMax-M2.5",
|
|
},
|
|
},
|
|
{
|
|
Name: "volcengine",
|
|
DisplayName: "Volcano Engine Ark API",
|
|
Protocol: "openai",
|
|
BaseURL: "https://ark.cn-beijing.volces.com/api/v3",
|
|
EnvVar: "ARK_API_KEY",
|
|
Models: []string{
|
|
"doubao-seed-evolving",
|
|
"doubao-seed-2-1-pro-260628",
|
|
"doubao-seed-2-1-turbo-260628",
|
|
"doubao-seed-2-0-lite-260428",
|
|
"doubao-seed-2-0-mini-260428",
|
|
"doubao-seed-2-0-pro-260215",
|
|
},
|
|
},
|
|
{
|
|
Name: "deepseek",
|
|
DisplayName: "DeepSeek API",
|
|
Protocol: "openai",
|
|
BaseURL: "https://api.deepseek.com",
|
|
EnvVar: "DEEPSEEK_API_KEY",
|
|
Models: []string{
|
|
"deepseek-v4-pro",
|
|
"deepseek-v4-flash",
|
|
},
|
|
},
|
|
{
|
|
Name: "tencent-tokenhub",
|
|
DisplayName: "Tencent TokenHub API",
|
|
Protocol: "openai",
|
|
BaseURL: "https://tokenhub.tencentmaas.com/v1",
|
|
EnvVar: "TENCENT_TOKENHUB_API_KEY",
|
|
Models: []string{
|
|
"hy3-preview",
|
|
"deepseek-v4-pro",
|
|
"deepseek-v4-flash",
|
|
"glm-5.2",
|
|
"glm-5.1",
|
|
"glm-5",
|
|
"glm-5-turbo",
|
|
"kimi-k2.7-code",
|
|
"kimi-k2.6",
|
|
"kimi-k2.5",
|
|
"minimax-m3",
|
|
"minimax-m2.7",
|
|
"minimax-m2.5",
|
|
},
|
|
},
|
|
{
|
|
Name: "hy-tokenplan",
|
|
DisplayName: "Tencent Hunyuan Token Plan API",
|
|
Protocol: "openai",
|
|
BaseURL: "https://api.lkeap.cloud.tencent.com/plan/v3",
|
|
EnvVar: "TENCENT_HUNYUAN_TOKENPLAN_KEY",
|
|
Models: []string{
|
|
"hy3-preview",
|
|
},
|
|
},
|
|
{
|
|
Name: "kimi",
|
|
DisplayName: "Kimi Moonshot API",
|
|
Protocol: "openai",
|
|
BaseURL: "https://api.moonshot.cn/v1",
|
|
EnvVar: "MOONSHOT_API_KEY",
|
|
Models: []string{
|
|
"kimi-k2.7-code",
|
|
"kimi-k2.7-code-highspeed",
|
|
"kimi-k2.6",
|
|
"kimi-k2.5",
|
|
},
|
|
},
|
|
{
|
|
Name: "z-ai",
|
|
DisplayName: "Z.AI API",
|
|
Protocol: "openai",
|
|
BaseURL: "https://open.bigmodel.cn/api/paas/v4",
|
|
EnvVar: "Z_AI_API_KEY",
|
|
Models: []string{
|
|
"glm-5.2",
|
|
"glm-5.1",
|
|
"glm-5",
|
|
"glm-5-turbo",
|
|
"glm-4.7",
|
|
},
|
|
},
|
|
{
|
|
Name: "z-ai-coding",
|
|
DisplayName: "Z.AI Coding Plan API",
|
|
Protocol: "openai",
|
|
BaseURL: "https://open.bigmodel.cn/api/coding/paas/v4",
|
|
EnvVar: "Z_AI_CODING_API_KEY",
|
|
Models: []string{
|
|
"glm-5.2",
|
|
"glm-5.1",
|
|
"glm-5-turbo",
|
|
"glm-4.7",
|
|
},
|
|
},
|
|
{
|
|
Name: "mimo",
|
|
DisplayName: "Xiaomi MiMo API",
|
|
Protocol: "openai",
|
|
BaseURL: "https://api.xiaomimimo.com/v1",
|
|
EnvVar: "MIMO_API_KEY",
|
|
Models: []string{
|
|
"mimo-v2.5-pro",
|
|
"mimo-v2.5",
|
|
},
|
|
},
|
|
{
|
|
Name: "minimax",
|
|
DisplayName: "MiniMax API",
|
|
Protocol: "openai",
|
|
BaseURL: "https://api.minimaxi.com/v1",
|
|
EnvVar: "MINIMAX_API_KEY",
|
|
Models: []string{
|
|
"MiniMax-M3",
|
|
"MiniMax-M2.7",
|
|
"MiniMax-M2.7-highspeed",
|
|
"MiniMax-M2.5",
|
|
"MiniMax-M2.5-highspeed",
|
|
},
|
|
},
|
|
{
|
|
Name: "baidu-qianfan",
|
|
DisplayName: "Baidu Qianfan API",
|
|
Protocol: "openai",
|
|
BaseURL: "https://qianfan.baidubce.com/v2",
|
|
EnvVar: "QIANFAN_API_KEY",
|
|
Models: []string{
|
|
"ernie-5.1",
|
|
"ernie-5.0",
|
|
"ernie-x1.1",
|
|
"ernie-x1-turbo-32k-preview",
|
|
"deepseek-v4-pro",
|
|
"deepseek-v4-flash",
|
|
"glm-5.2",
|
|
"glm-5.1",
|
|
"glm-5",
|
|
"kimi-k2.6",
|
|
},
|
|
},
|
|
}
|
|
|
|
var registryMap map[string]Provider
|
|
|
|
func init() {
|
|
registryMap = make(map[string]Provider, len(registry))
|
|
for _, p := range registry {
|
|
registryMap[strings.ToLower(p.Name)] = p
|
|
}
|
|
}
|
|
|
|
// LookupProvider returns the preset provider by name.
|
|
// The returned Provider has its own copy of the Models slice.
|
|
func LookupProvider(name string) (Provider, bool) {
|
|
p, ok := registryMap[strings.ToLower(strings.TrimSpace(name))]
|
|
if ok {
|
|
p = copyProvider(p)
|
|
}
|
|
return p, ok
|
|
}
|
|
|
|
// ListProviders returns all built-in providers sorted by provider name.
|
|
// Each returned Provider has its own copy of the Models slice in registry order.
|
|
func ListProviders() []Provider {
|
|
out := make([]Provider, len(registry))
|
|
for i, p := range registry {
|
|
out[i] = copyProvider(p)
|
|
}
|
|
sort.Slice(out, func(i, j int) bool {
|
|
return out[i].Name < out[j].Name
|
|
})
|
|
return out
|
|
}
|
|
|
|
func copyProvider(p Provider) Provider {
|
|
if p.Models != nil {
|
|
models := make([]string, len(p.Models))
|
|
copy(models, p.Models)
|
|
p.Models = models
|
|
}
|
|
return p
|
|
}
|