Add GLM Coding (China) provider with OpenAI-compatible API (#83)

This commit is contained in:
Blade
2026-02-09 10:31:38 +07:00
committed by GitHub
parent 85b7a0b136
commit c68b875a36
7 changed files with 66 additions and 14 deletions
+18
View File
@@ -406,6 +406,24 @@ async function testApiKeyConnection(connection) {
return { valid, error: valid ? null : "Invalid API key" };
}
case "glm-cn": {
// GLM Coding (China) uses OpenAI-compatible API
const res = await fetch("https://open.bigmodel.cn/api/coding/paas/v4/chat/completions", {
method: "POST",
headers: {
"Authorization": `Bearer ${connection.apiKey}`,
"content-type": "application/json",
},
body: JSON.stringify({
model: "glm-4.7",
max_tokens: 1,
messages: [{ role: "user", content: "test" }],
}),
});
const valid = res.status !== 401 && res.status !== 403;
return { valid, error: valid ? null : "Invalid API key" };
}
case "minimax":
case "minimax-cn": {
// MiniMax uses Claude-compatible API
+34 -14
View File
@@ -99,29 +99,49 @@ export async function POST(request) {
break;
case "glm":
case "glm-cn":
case "kimi":
case "minimax":
case "minimax-cn": {
const claudeBaseUrls = {
glm: "https://api.z.ai/api/anthropic/v1/messages",
"glm-cn": "https://open.bigmodel.cn/api/coding/paas/v4/chat/completions",
kimi: "https://api.kimi.com/coding/v1/messages",
minimax: "https://api.minimax.io/anthropic/v1/messages",
"minimax-cn": "https://api.minimaxi.com/anthropic/v1/messages",
};
const claudeRes = await fetch(claudeBaseUrls[provider], {
method: "POST",
headers: {
"x-api-key": apiKey,
"anthropic-version": "2023-06-01",
"content-type": "application/json",
},
body: JSON.stringify({
model: "claude-sonnet-4-20250514",
max_tokens: 1,
messages: [{ role: "user", content: "test" }],
}),
});
isValid = claudeRes.status !== 401;
// glm-cn uses OpenAI format
if (provider === "glm-cn") {
const glmCnRes = await fetch(claudeBaseUrls[provider], {
method: "POST",
headers: {
"Authorization": `Bearer ${apiKey}`,
"content-type": "application/json",
},
body: JSON.stringify({
model: "glm-4.7",
max_tokens: 1,
messages: [{ role: "user", content: "test" }],
}),
});
isValid = glmCnRes.status !== 401 && glmCnRes.status !== 403;
} else {
const claudeRes = await fetch(claudeBaseUrls[provider], {
method: "POST",
headers: {
"x-api-key": apiKey,
"anthropic-version": "2023-06-01",
"content-type": "application/json",
},
body: JSON.stringify({
model: "claude-sonnet-4-20250514",
max_tokens: 1,
messages: [{ role: "user", content: "test" }],
}),
});
isValid = claudeRes.status !== 401;
}
break;
}
+1
View File
@@ -33,6 +33,7 @@ export const API_ENDPOINTS = {
export const PROVIDER_ENDPOINTS = {
openrouter: "https://openrouter.ai/api/v1/chat/completions",
glm: "https://api.z.ai/api/anthropic/v1/messages",
"glm-cn": "https://open.bigmodel.cn/api/coding/paas/v4/chat/completions",
kimi: "https://api.kimi.com/coding/v1/messages",
minimax: "https://api.minimax.io/anthropic/v1/messages",
"minimax-cn": "https://api.minimaxi.com/anthropic/v1/messages",
+1
View File
@@ -20,6 +20,7 @@ export const OAUTH_PROVIDERS = {
export const APIKEY_PROVIDERS = {
openrouter: { id: "openrouter", alias: "openrouter", name: "OpenRouter", icon: "router", color: "#6366F1", textIcon: "OR" , passthroughModels: true },
glm: { id: "glm", alias: "glm", name: "GLM Coding", icon: "code", color: "#2563EB", textIcon: "GL" },
"glm-cn": { id: "glm-cn", alias: "glm-cn", name: "GLM Coding (China)", icon: "code", color: "#DC2626", textIcon: "GC" },
kimi: { id: "kimi", alias: "kimi", name: "Kimi Coding", icon: "psychology", color: "#1E3A8A", textIcon: "KM" },
minimax: { id: "minimax", alias: "minimax", name: "Minimax Coding", icon: "memory", color: "#7C3AED", textIcon: "MM" },
"minimax-cn": { id: "minimax-cn", alias: "minimax-cn", name: "Minimax (China)", icon: "memory", color: "#DC2626", textIcon: "MC" },