mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-21 08:13:34 +00:00
feat(ai): add Zhipu provider preset
This commit is contained in:
@@ -0,0 +1 @@
|
||||
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Zhipu</title><path d="M11.991 23.503a.24.24 0 00-.244.248.24.24 0 00.244.249.24.24 0 00.245-.249.24.24 0 00-.22-.247l-.025-.001zM9.671 5.365a1.697 1.697 0 011.099 2.132l-.071.172-.016.04-.018.054c-.07.16-.104.32-.104.498-.035.71.47 1.279 1.186 1.314h.366c1.309.053 2.338 1.173 2.286 2.523-.052 1.332-1.152 2.38-2.478 2.327h-.174c-.715.018-1.274.64-1.239 1.368 0 .124.018.23.053.337.209.373.54.658.96.8.75.23 1.517-.125 1.9-.782l.018-.035c.402-.64 1.17-.96 1.92-.711.854.284 1.378 1.226 1.099 2.167a1.661 1.661 0 01-2.077 1.102 1.711 1.711 0 01-.907-.711l-.017-.035c-.2-.323-.463-.58-.851-.711l-.056-.018a1.646 1.646 0 00-1.954.746 1.66 1.66 0 01-1.065.764 1.677 1.677 0 01-1.989-1.279c-.209-.906.332-1.83 1.257-2.043a1.51 1.51 0 01.296-.035h.018c.68-.071 1.151-.622 1.116-1.333a1.307 1.307 0 00-.227-.693 2.515 2.515 0 01-.366-1.403 2.39 2.39 0 01.366-1.208c.14-.195.21-.444.227-.693.018-.71-.506-1.261-1.186-1.332l-.07-.018a1.43 1.43 0 01-.299-.07l-.05-.019a1.7 1.7 0 01-1.047-2.114 1.68 1.68 0 012.094-1.101zm-5.575 10.11c.26-.264.639-.367.994-.27.355.096.633.379.728.74.095.362-.007.748-.267 1.013-.402.41-1.053.41-1.455 0a1.062 1.062 0 010-1.482zm14.845-.294c.359-.09.738.024.992.297.254.274.344.665.237 1.025-.107.36-.396.634-.756.718-.551.128-1.1-.22-1.23-.781a1.05 1.05 0 01.757-1.26zm-.064-4.39c.314.32.49.753.49 1.206 0 .452-.176.886-.49 1.206-.315.32-.74.5-1.185.5-.444 0-.87-.18-1.184-.5a1.727 1.727 0 010-2.412 1.654 1.654 0 012.369 0zm-11.243.163c.364.484.447 1.128.218 1.691a1.665 1.665 0 01-2.188.923c-.855-.36-1.26-1.358-.907-2.228a1.68 1.68 0 011.33-1.038c.593-.08 1.183.169 1.547.652zm11.545-4.221c.368 0 .708.2.892.524.184.324.184.724 0 1.048a1.026 1.026 0 01-.892.524c-.568 0-1.03-.47-1.03-1.048 0-.579.462-1.048 1.03-1.048zm-14.358 0c.368 0 .707.2.891.524.184.324.184.724 0 1.048a1.026 1.026 0 01-.891.524c-.569 0-1.03-.47-1.03-1.048 0-.579.461-1.048 1.03-1.048zm10.031-1.475c.925 0 1.675.764 1.675 1.706s-.75 1.705-1.675 1.705-1.674-.763-1.674-1.705c0-.942.75-1.706 1.674-1.706zm-2.626-.684c.362-.082.653-.356.761-.718a1.062 1.062 0 00-.238-1.028 1.017 1.017 0 00-.996-.294c-.547.14-.881.7-.752 1.257.13.558.675.907 1.225.783zm0 16.876c.359-.087.644-.36.75-.72a1.062 1.062 0 00-.237-1.019 1.018 1.018 0 00-.985-.301 1.037 1.037 0 00-.762.717c-.108.361-.017.754.239 1.028.245.263.606.377.953.305l.043-.01zM17.19 3.5a.631.631 0 00.628-.64c0-.355-.279-.64-.628-.64a.631.631 0 00-.628.64c0 .355.28.64.628.64zm-10.38 0a.631.631 0 00.628-.64c0-.355-.28-.64-.628-.64a.631.631 0 00-.628.64c0 .355.279.64.628.64zm-5.182 7.852a.631.631 0 00-.628.64c0 .354.28.639.628.639a.63.63 0 00.627-.606l.001-.034a.62.62 0 00-.628-.64zm5.182 9.13a.631.631 0 00-.628.64c0 .355.279.64.628.64a.631.631 0 00.628-.64c0-.355-.28-.64-.628-.64zm10.38.018a.631.631 0 00-.628.64c0 .355.28.64.628.64a.631.631 0 00.628-.64c0-.355-.279-.64-.628-.64zm5.182-9.148a.631.631 0 00-.628.64c0 .354.279.639.628.639a.631.631 0 00.628-.64c0-.355-.28-.64-.628-.64zm-.384-4.992a.24.24 0 00.244-.249.24.24 0 00-.244-.249.24.24 0 00-.244.249c0 .142.122.249.244.249zM11.991.497a.24.24 0 00.245-.248A.24.24 0 0011.99 0a.24.24 0 00-.244.249c0 .133.108.236.223.247l.021.001zM2.011 6.36a.24.24 0 00.245-.249.24.24 0 00-.244-.249.24.24 0 00-.244.249.24.24 0 00.244.249zm0 11.263a.24.24 0 00-.243.248.24.24 0 00.244.249.24.24 0 00.244-.249.252.252 0 00-.244-.248zm19.995-.018a.24.24 0 00-.245.248.24.24 0 00.245.25.24.24 0 00.244-.25.252.252 0 00-.244-.248z" fill="#3859FF" fill-rule="nonzero"></path></svg>
|
||||
|
After Width: | Height: | Size: 3.5 KiB |
@@ -772,6 +772,19 @@ describe("settingsStore AI API key normalization", () => {
|
||||
expect(normalizeAiConfig({ endpoint: "https://api.moonshot.cn/v1", model: "kimi-k2.5" }).provider).toBe("kimi");
|
||||
});
|
||||
|
||||
it("provides Zhipu defaults and recognizes legacy Zhipu configurations", () => {
|
||||
expect(AI_PROVIDER_PRESETS.zhipu).toMatchObject({
|
||||
provider: "zhipu",
|
||||
endpoint: "https://open.bigmodel.cn/api/paas/v4",
|
||||
model: "glm-5.3",
|
||||
apiStyle: "completions",
|
||||
authMethod: "bearer",
|
||||
requiresApiKey: true,
|
||||
});
|
||||
expect(normalizeAiConfig({ endpoint: "https://open.bigmodel.cn/api/paas/v4", model: "glm-4.6" }).provider).toBe("zhipu");
|
||||
expect(normalizeAiConfig({ endpoint: "https://api.z.ai/api/paas/v4", model: "glm-5.2" }).provider).toBe("zhipu");
|
||||
});
|
||||
|
||||
it("uses the mainland MiniMax endpoint only for new zh-CN presets", () => {
|
||||
expect(getAiProviderPresetDefaultEndpoint(AI_PROVIDER_PRESETS.minimax, "zh-CN")).toBe("https://api.minimaxi.com/v1");
|
||||
expect(getAiProviderPresetDefaultEndpoint(AI_PROVIDER_PRESETS.minimax, "zh-TW")).toBe("https://api.minimax.io/v1");
|
||||
@@ -779,6 +792,12 @@ describe("settingsStore AI API key normalization", () => {
|
||||
expect(getAiProviderPresetDefaultEndpoint(AI_PROVIDER_PRESETS.openai, "zh-CN")).toBe(AI_PROVIDER_PRESETS.openai.endpoint);
|
||||
});
|
||||
|
||||
it("uses the international Zhipu endpoint for non-zh-CN presets", () => {
|
||||
expect(getAiProviderPresetDefaultEndpoint(AI_PROVIDER_PRESETS.zhipu, "zh-CN")).toBe("https://open.bigmodel.cn/api/paas/v4");
|
||||
expect(getAiProviderPresetDefaultEndpoint(AI_PROVIDER_PRESETS.zhipu, "zh-TW")).toBe("https://api.z.ai/api/paas/v4");
|
||||
expect(getAiProviderPresetDefaultEndpoint(AI_PROVIDER_PRESETS.zhipu, "en")).toBe("https://api.z.ai/api/paas/v4");
|
||||
});
|
||||
|
||||
it("preserves saved MiniMax endpoints during normalization", () => {
|
||||
expect(normalizeAiConfig({ provider: "minimax", endpoint: "https://api.minimaxi.com/v1" }).endpoint).toBe("https://api.minimaxi.com/v1");
|
||||
expect(normalizeAiConfig({ provider: "minimax", endpoint: "https://minimax.example.com/v1" }).endpoint).toBe("https://minimax.example.com/v1");
|
||||
|
||||
@@ -301,6 +301,16 @@ export const AI_PROVIDER_PRESETS: Record<AiProvider, AiProviderPreset> = {
|
||||
authMethod: "bearer",
|
||||
requiresApiKey: true,
|
||||
},
|
||||
zhipu: {
|
||||
label: "Zhipu",
|
||||
iconSlug: "zhipu",
|
||||
provider: "zhipu",
|
||||
endpoint: "https://open.bigmodel.cn/api/paas/v4",
|
||||
model: "glm-5.3",
|
||||
apiStyle: "completions",
|
||||
authMethod: "bearer",
|
||||
requiresApiKey: true,
|
||||
},
|
||||
minimax: {
|
||||
label: "MiniMax",
|
||||
iconSlug: "minimax",
|
||||
@@ -490,6 +500,9 @@ export function getAiProviderPresetDefaultEndpoint(preset: AiProviderPreset | Ai
|
||||
if (preset.provider === "minimax" && locale === "zh-CN") {
|
||||
return "https://api.minimaxi.com/v1";
|
||||
}
|
||||
if (preset.provider === "zhipu" && locale !== "zh-CN") {
|
||||
return "https://api.z.ai/api/paas/v4";
|
||||
}
|
||||
return preset.endpoint;
|
||||
}
|
||||
|
||||
@@ -588,6 +601,7 @@ function inferAiProviderFromConfig(config: Partial<AiConfig> | null | undefined)
|
||||
if (endpoint.includes("deepseek") || model.includes("deepseek")) return "deepseek";
|
||||
if (endpoint.includes("moonshot") || endpoint.includes("kimi.com") || model.includes("kimi")) return "kimi";
|
||||
if (endpoint.includes("dashscope") || endpoint.includes("aliyuncs") || model.includes("qwen")) return "qwen";
|
||||
if (endpoint.includes("bigmodel.cn") || endpoint.includes("api.z.ai") || model.startsWith("glm-")) return "zhipu";
|
||||
if (endpoint.includes("generativelanguage.googleapis.com") || model.includes("gemini")) return "gemini";
|
||||
if (endpoint.includes("minimax.io") || endpoint.includes("minimaxi.com") || model.includes("minimax")) return "minimax";
|
||||
if (endpoint.includes("localhost:11434") || endpoint.includes("127.0.0.1:11434")) return "ollama";
|
||||
|
||||
@@ -1,4 +1,24 @@
|
||||
export type AiProvider = "claude" | "openai" | "gemini" | "deepseek" | "kimi" | "qwen" | "minimax" | "ollama" | "anthropic-compatible" | "openai-compatible" | "claude-code-cli" | "pi-agent-cli" | "codex-cli" | "opencode-cli" | "cursor-cli" | "grok-cli" | "codebuddy-cli" | "qoder-cli" | "custom";
|
||||
export type AiProvider =
|
||||
| "claude"
|
||||
| "openai"
|
||||
| "gemini"
|
||||
| "deepseek"
|
||||
| "kimi"
|
||||
| "qwen"
|
||||
| "zhipu"
|
||||
| "minimax"
|
||||
| "ollama"
|
||||
| "anthropic-compatible"
|
||||
| "openai-compatible"
|
||||
| "claude-code-cli"
|
||||
| "pi-agent-cli"
|
||||
| "codex-cli"
|
||||
| "opencode-cli"
|
||||
| "cursor-cli"
|
||||
| "grok-cli"
|
||||
| "codebuddy-cli"
|
||||
| "qoder-cli"
|
||||
| "custom";
|
||||
export type AiApiStyle = "completions" | "responses" | "anthropic-messages";
|
||||
export type AiAuthMethod = "api-key" | "bearer";
|
||||
export type AiEffortLevel = "low" | "medium" | "high" | "xhigh" | "max";
|
||||
|
||||
@@ -88,6 +88,7 @@ pub enum AiProvider {
|
||||
Deepseek,
|
||||
Kimi,
|
||||
Qwen,
|
||||
Zhipu,
|
||||
MiniMax,
|
||||
Ollama,
|
||||
#[serde(rename = "openai-compatible")]
|
||||
@@ -121,6 +122,7 @@ impl AiProvider {
|
||||
AiProvider::Deepseek => "deepseek",
|
||||
AiProvider::Kimi => "kimi",
|
||||
AiProvider::Qwen => "qwen",
|
||||
AiProvider::Zhipu => "zhipu",
|
||||
AiProvider::MiniMax => "minimax",
|
||||
AiProvider::Ollama => "ollama",
|
||||
AiProvider::OpenaiCompatible => "openai-compatible",
|
||||
@@ -887,6 +889,7 @@ pub fn resolve_endpoint(config: &AiConfig) -> String {
|
||||
| AiProvider::Deepseek
|
||||
| AiProvider::Kimi
|
||||
| AiProvider::Qwen
|
||||
| AiProvider::Zhipu
|
||||
| AiProvider::MiniMax
|
||||
| AiProvider::Ollama
|
||||
| AiProvider::OpenaiCompatible
|
||||
@@ -1689,6 +1692,7 @@ fn provider_requires_api_key(provider: &AiProvider) -> bool {
|
||||
| AiProvider::Deepseek
|
||||
| AiProvider::Kimi
|
||||
| AiProvider::Qwen
|
||||
| AiProvider::Zhipu
|
||||
| AiProvider::MiniMax
|
||||
)
|
||||
}
|
||||
@@ -2179,6 +2183,7 @@ pub async fn list_models_core(config: &AiConfig) -> Result<Vec<AiModelInfo>, Str
|
||||
| AiProvider::Deepseek
|
||||
| AiProvider::Kimi
|
||||
| AiProvider::Qwen
|
||||
| AiProvider::Zhipu
|
||||
| AiProvider::MiniMax
|
||||
| AiProvider::OpenaiCompatible => list_openai_compatible_models(&client, config).await?,
|
||||
AiProvider::Custom => {
|
||||
@@ -3614,6 +3619,7 @@ pub async fn complete(request: &AiCompletionRequest) -> Result<String, String> {
|
||||
| AiProvider::Deepseek
|
||||
| AiProvider::Kimi
|
||||
| AiProvider::Qwen
|
||||
| AiProvider::Zhipu
|
||||
| AiProvider::MiniMax
|
||||
| AiProvider::Ollama
|
||||
| AiProvider::OpenaiCompatible => {
|
||||
@@ -3676,6 +3682,7 @@ pub async fn stream(
|
||||
| AiProvider::Deepseek
|
||||
| AiProvider::Kimi
|
||||
| AiProvider::Qwen
|
||||
| AiProvider::Zhipu
|
||||
| AiProvider::MiniMax
|
||||
| AiProvider::Ollama
|
||||
| AiProvider::OpenaiCompatible => {
|
||||
|
||||
@@ -78,7 +78,7 @@ pub fn static_effort_capability(config: &AiConfig, model_id: &str) -> Option<AiE
|
||||
AiProvider::Deepseek => deepseek_capability(&model, source),
|
||||
AiProvider::Kimi => kimi_capability(&model, source),
|
||||
AiProvider::Qwen => qwen_capability(&model, source),
|
||||
AiProvider::Ollama => ollama_capability(&model, source),
|
||||
AiProvider::Zhipu | AiProvider::Ollama => ollama_capability(&model, source),
|
||||
AiProvider::MiniMax if matches_family(&model, "minimax-m3") => Some(boolean_capability(source)),
|
||||
AiProvider::MiniMax => None,
|
||||
AiProvider::AnthropicCompatible | AiProvider::OpenaiCompatible | AiProvider::Custom => {
|
||||
@@ -208,7 +208,7 @@ pub fn registry_source_url(provider: &AiProvider) -> Option<&'static str> {
|
||||
AiProvider::Deepseek => Some(DEEPSEEK_THINKING_DOCS),
|
||||
AiProvider::Kimi => Some(KIMI_REASONING_DOCS),
|
||||
AiProvider::Qwen => Some(QWEN_THINKING_DOCS),
|
||||
AiProvider::Ollama => Some(OLLAMA_THINKING_DOCS),
|
||||
AiProvider::Zhipu | AiProvider::Ollama => Some(OLLAMA_THINKING_DOCS),
|
||||
AiProvider::MiniMax => Some(MINIMAX_THINKING_DOCS),
|
||||
AiProvider::Claude
|
||||
| AiProvider::AnthropicCompatible
|
||||
@@ -287,7 +287,7 @@ pub fn apply_runtime_effort(body: &mut Value, config: &AiConfig) {
|
||||
AiProvider::Deepseek => apply_deepseek_effort(object, selection),
|
||||
AiProvider::Kimi => apply_kimi_effort(object, &config.model, selection),
|
||||
AiProvider::Qwen => apply_qwen_effort(object, selection),
|
||||
AiProvider::Ollama => apply_openai_effort(object, &config.api_style, selection),
|
||||
AiProvider::Zhipu | AiProvider::Ollama => apply_openai_effort(object, &config.api_style, selection),
|
||||
AiProvider::MiniMax => apply_minimax_effort(object, selection),
|
||||
AiProvider::Openai | AiProvider::OpenaiCompatible => apply_openai_effort(object, &config.api_style, selection),
|
||||
AiProvider::Custom => {
|
||||
|
||||
@@ -92,6 +92,7 @@ pub(crate) fn model_is_assistant_compatible(provider: &AiProvider, model_id: &st
|
||||
| AiProvider::AnthropicCompatible
|
||||
| AiProvider::Deepseek
|
||||
| AiProvider::Kimi
|
||||
| AiProvider::Zhipu
|
||||
| AiProvider::Ollama
|
||||
| AiProvider::OpenaiCompatible
|
||||
| AiProvider::CodexCli
|
||||
|
||||
+6
@@ -892,6 +892,12 @@ test("AI provider presets include common hosted and local providers", () => {
|
||||
assert.equal(AI_PROVIDER_PRESETS.minimax.requiresApiKey, true);
|
||||
assert.equal(AI_PROVIDER_PRESETS.minimax.iconSlug, "minimax");
|
||||
assert.equal(AI_PROVIDER_PRESETS.qwen.endpoint, "https://dashscope.aliyuncs.com/compatible-mode/v1");
|
||||
assert.equal(AI_PROVIDER_PRESETS.zhipu.endpoint, "https://open.bigmodel.cn/api/paas/v4");
|
||||
assert.equal(AI_PROVIDER_PRESETS.zhipu.model, "glm-5.3");
|
||||
assert.equal(AI_PROVIDER_PRESETS.zhipu.apiStyle, "completions");
|
||||
assert.equal(AI_PROVIDER_PRESETS.zhipu.authMethod, "bearer");
|
||||
assert.equal(AI_PROVIDER_PRESETS.zhipu.requiresApiKey, true);
|
||||
assert.equal(AI_PROVIDER_PRESETS.zhipu.iconSlug, "zhipu");
|
||||
assert.equal(AI_PROVIDER_PRESETS.ollama.endpoint, "http://localhost:11434/v1");
|
||||
assert.equal(AI_PROVIDER_PRESETS.ollama.requiresApiKey, false);
|
||||
assert.equal(AI_PROVIDER_PRESETS.claude.authMethod, "api-key");
|
||||
|
||||
Reference in New Issue
Block a user