From a224f68e5cac5c2f847a29ba9de3a3c1ea25bdd0 Mon Sep 17 00:00:00 2001 From: decolua Date: Thu, 12 Mar 2026 10:48:11 +0700 Subject: [PATCH] feat(kimi-coding): Added Kimi Coding to the list of supported OAuth providers with specific configuration. --- open-sse/config/constants.js | 15 +++++++++++++++ open-sse/executors/default.js | 17 +++++++++++++---- src/app/api/providers/[id]/test/testUtils.js | 1 + src/shared/constants/providers.js | 10 +++++++++- 4 files changed, 38 insertions(+), 5 deletions(-) diff --git a/open-sse/config/constants.js b/open-sse/config/constants.js index 63f2991..d319b36 100644 --- a/open-sse/config/constants.js +++ b/open-sse/config/constants.js @@ -564,3 +564,18 @@ export const SKIP_PATTERNS = [ "Please write a 5-10 word title for the following conversation:" ]; +// Generate Kimi OAuth custom headers +export function buildKimiHeaders() { + const deviceId = `kimi-${Date.now()}`; + const platform = "9router"; + const version = "2.1.2"; + const deviceModel = typeof process !== "undefined" ? `${process.platform} ${process.arch}` : "unknown"; + + return { + "X-Msh-Platform": platform, + "X-Msh-Version": version, + "X-Msh-Device-Model": deviceModel, + "X-Msh-Device-Id": deviceId + }; +} + diff --git a/open-sse/executors/default.js b/open-sse/executors/default.js index eba3c61..2b5ccde 100644 --- a/open-sse/executors/default.js +++ b/open-sse/executors/default.js @@ -1,5 +1,5 @@ import { BaseExecutor } from "./base.js"; -import { PROVIDERS, OAUTH_ENDPOINTS } from "../config/constants.js"; +import { PROVIDERS, OAUTH_ENDPOINTS, buildKimiHeaders } from "../config/constants.js"; import { buildClineHeaders } from "../../src/shared/utils/clineAuth.js"; export class DefaultExecutor extends BaseExecutor { @@ -23,10 +23,11 @@ export class DefaultExecutor extends BaseExecutor { case "claude": case "glm": case "kimi": - case "kimi-coding": case "minimax": case "minimax-cn": return `${this.config.baseUrl}?beta=true`; + case "kimi-coding": + return `${this.config.baseUrl}?beta=true`; case "gemini": return `${this.config.baseUrl}/${model}:${stream ? "streamGenerateContent?alt=sse" : "generateContent"}`; default: @@ -46,11 +47,14 @@ export class DefaultExecutor extends BaseExecutor { break; case "glm": case "kimi": - case "kimi-coding": case "minimax": case "minimax-cn": headers["x-api-key"] = credentials.apiKey || credentials.accessToken; break; + case "kimi-coding": + headers["Authorization"] = `Bearer ${credentials.accessToken}`; + Object.assign(headers, buildKimiHeaders()); + break; default: if (this.provider?.startsWith?.("anthropic-compatible-")) { if (credentials.apiKey) { @@ -184,9 +188,14 @@ export class DefaultExecutor extends BaseExecutor { } async refreshKimiCoding(refreshToken) { + const kimiHeaders = buildKimiHeaders(); const response = await fetch("https://auth.kimi.com/api/oauth/token", { method: "POST", - headers: { "Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json" }, + headers: { + "Content-Type": "application/x-www-form-urlencoded", + "Accept": "application/json", + ...kimiHeaders + }, body: new URLSearchParams({ grant_type: "refresh_token", refresh_token: refreshToken, client_id: "17e5f671-d194-4dfb-9706-5516cb48c098" }) }); if (!response.ok) return null; diff --git a/src/app/api/providers/[id]/test/testUtils.js b/src/app/api/providers/[id]/test/testUtils.js index 7a11f97..2c4e350 100644 --- a/src/app/api/providers/[id]/test/testUtils.js +++ b/src/app/api/providers/[id]/test/testUtils.js @@ -48,6 +48,7 @@ const OAUTH_TEST_CONFIG = { }, qwen: { checkExpiry: true, refreshable: true }, kiro: { checkExpiry: true, refreshable: true }, + "kimi-coding": { checkExpiry: true, refreshable: false }, cursor: { tokenExists: true }, kilocode: { url: `${KILOCODE_CONFIG.apiBaseUrl}/api/profile`, diff --git a/src/shared/constants/providers.js b/src/shared/constants/providers.js index 6024fc6..975c9a1 100644 --- a/src/shared/constants/providers.js +++ b/src/shared/constants/providers.js @@ -15,6 +15,7 @@ export const OAUTH_PROVIDERS = { codex: { id: "codex", alias: "cx", name: "OpenAI Codex", icon: "code", color: "#3B82F6" }, github: { id: "github", alias: "gh", name: "GitHub Copilot", icon: "code", color: "#333333" }, cursor: { id: "cursor", alias: "cu", name: "Cursor IDE", icon: "edit_note", color: "#00D4AA" }, + // "kimi-coding": { id: "kimi-coding", alias: "kmc", name: "Kimi Coding", icon: "psychology", color: "#1E40AF", textIcon: "KC" }, kilocode: { id: "kilocode", alias: "kc", name: "Kilo Code", icon: "code", color: "#FF6B35", textIcon: "KC" }, cline: { id: "cline", alias: "cl", name: "Cline", icon: "smart_toy", color: "#5B9BD5", textIcon: "CL" }, }; @@ -105,4 +106,11 @@ export const ID_TO_ALIAS = Object.values(AI_PROVIDERS).reduce((acc, p) => { }, {}); // Providers that support usage/quota API -export const USAGE_SUPPORTED_PROVIDERS = [ "claude", "antigravity", "kiro", "github", "codex"]; +export const USAGE_SUPPORTED_PROVIDERS = [ + "claude", + "antigravity", + "kiro", + "github", + "codex", + "kimi-coding", +];