mirror of
https://github.com/Nezumi-2711/9router.git
synced 2026-09-22 13:38:31 +00:00
Add GLM Coding (China) provider with OpenAI-compatible API (#83)
This commit is contained in:
@@ -104,6 +104,11 @@ export const PROVIDERS = {
|
|||||||
"Anthropic-Beta": "claude-code-20250219,interleaved-thinking-2025-05-14"
|
"Anthropic-Beta": "claude-code-20250219,interleaved-thinking-2025-05-14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"glm-cn": {
|
||||||
|
baseUrl: "https://open.bigmodel.cn/api/coding/paas/v4/chat/completions",
|
||||||
|
format: "openai",
|
||||||
|
headers: {}
|
||||||
|
},
|
||||||
kimi: {
|
kimi: {
|
||||||
baseUrl: "https://api.kimi.com/coding/v1/messages",
|
baseUrl: "https://api.kimi.com/coding/v1/messages",
|
||||||
format: "claude",
|
format: "claude",
|
||||||
|
|||||||
@@ -131,6 +131,12 @@ export const PROVIDER_MODELS = {
|
|||||||
{ id: "glm-4.7", name: "GLM 4.7" },
|
{ id: "glm-4.7", name: "GLM 4.7" },
|
||||||
{ id: "glm-4.6v", name: "GLM 4.6V (Vision)" },
|
{ id: "glm-4.6v", name: "GLM 4.6V (Vision)" },
|
||||||
],
|
],
|
||||||
|
"glm-cn": [
|
||||||
|
{ id: "glm-4.7", name: "GLM-4.7" },
|
||||||
|
{ id: "glm-4.6", name: "GLM-4.6" },
|
||||||
|
{ id: "glm-4.5", name: "GLM-4.5" },
|
||||||
|
{ id: "glm-4.5-air", name: "GLM-4.5-Air" },
|
||||||
|
],
|
||||||
kimi: [
|
kimi: [
|
||||||
{ id: "kimi-k2.5", name: "Kimi K2.5" },
|
{ id: "kimi-k2.5", name: "Kimi K2.5" },
|
||||||
{ id: "kimi-k2.5-thinking", name: "Kimi K2.5 Thinking" },
|
{ id: "kimi-k2.5-thinking", name: "Kimi K2.5 Thinking" },
|
||||||
@@ -188,6 +194,7 @@ export const PROVIDER_ID_TO_ALIAS = {
|
|||||||
gemini: "gemini",
|
gemini: "gemini",
|
||||||
openrouter: "openrouter",
|
openrouter: "openrouter",
|
||||||
glm: "glm",
|
glm: "glm",
|
||||||
|
"glm-cn": "glm-cn",
|
||||||
kimi: "kimi",
|
kimi: "kimi",
|
||||||
minimax: "minimax",
|
minimax: "minimax",
|
||||||
"minimax-cn": "minimax",
|
"minimax-cn": "minimax",
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
@@ -406,6 +406,24 @@ async function testApiKeyConnection(connection) {
|
|||||||
return { valid, error: valid ? null : "Invalid API key" };
|
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":
|
||||||
case "minimax-cn": {
|
case "minimax-cn": {
|
||||||
// MiniMax uses Claude-compatible API
|
// MiniMax uses Claude-compatible API
|
||||||
|
|||||||
@@ -99,29 +99,49 @@ export async function POST(request) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case "glm":
|
case "glm":
|
||||||
|
case "glm-cn":
|
||||||
case "kimi":
|
case "kimi":
|
||||||
case "minimax":
|
case "minimax":
|
||||||
case "minimax-cn": {
|
case "minimax-cn": {
|
||||||
const claudeBaseUrls = {
|
const claudeBaseUrls = {
|
||||||
glm: "https://api.z.ai/api/anthropic/v1/messages",
|
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",
|
kimi: "https://api.kimi.com/coding/v1/messages",
|
||||||
minimax: "https://api.minimax.io/anthropic/v1/messages",
|
minimax: "https://api.minimax.io/anthropic/v1/messages",
|
||||||
"minimax-cn": "https://api.minimaxi.com/anthropic/v1/messages",
|
"minimax-cn": "https://api.minimaxi.com/anthropic/v1/messages",
|
||||||
};
|
};
|
||||||
const claudeRes = await fetch(claudeBaseUrls[provider], {
|
|
||||||
method: "POST",
|
// glm-cn uses OpenAI format
|
||||||
headers: {
|
if (provider === "glm-cn") {
|
||||||
"x-api-key": apiKey,
|
const glmCnRes = await fetch(claudeBaseUrls[provider], {
|
||||||
"anthropic-version": "2023-06-01",
|
method: "POST",
|
||||||
"content-type": "application/json",
|
headers: {
|
||||||
},
|
"Authorization": `Bearer ${apiKey}`,
|
||||||
body: JSON.stringify({
|
"content-type": "application/json",
|
||||||
model: "claude-sonnet-4-20250514",
|
},
|
||||||
max_tokens: 1,
|
body: JSON.stringify({
|
||||||
messages: [{ role: "user", content: "test" }],
|
model: "glm-4.7",
|
||||||
}),
|
max_tokens: 1,
|
||||||
});
|
messages: [{ role: "user", content: "test" }],
|
||||||
isValid = claudeRes.status !== 401;
|
}),
|
||||||
|
});
|
||||||
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ export const API_ENDPOINTS = {
|
|||||||
export const PROVIDER_ENDPOINTS = {
|
export const PROVIDER_ENDPOINTS = {
|
||||||
openrouter: "https://openrouter.ai/api/v1/chat/completions",
|
openrouter: "https://openrouter.ai/api/v1/chat/completions",
|
||||||
glm: "https://api.z.ai/api/anthropic/v1/messages",
|
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",
|
kimi: "https://api.kimi.com/coding/v1/messages",
|
||||||
minimax: "https://api.minimax.io/anthropic/v1/messages",
|
minimax: "https://api.minimax.io/anthropic/v1/messages",
|
||||||
"minimax-cn": "https://api.minimaxi.com/anthropic/v1/messages",
|
"minimax-cn": "https://api.minimaxi.com/anthropic/v1/messages",
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ export const OAUTH_PROVIDERS = {
|
|||||||
export const APIKEY_PROVIDERS = {
|
export const APIKEY_PROVIDERS = {
|
||||||
openrouter: { id: "openrouter", alias: "openrouter", name: "OpenRouter", icon: "router", color: "#6366F1", textIcon: "OR" , passthroughModels: true },
|
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: { 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" },
|
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: { 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" },
|
"minimax-cn": { id: "minimax-cn", alias: "minimax-cn", name: "Minimax (China)", icon: "memory", color: "#DC2626", textIcon: "MC" },
|
||||||
|
|||||||
Reference in New Issue
Block a user