From 08b2a6791398912ff5ea6b3cce18b37552c1ef10 Mon Sep 17 00:00:00 2001 From: Tam Nhu Tran Date: Tue, 17 Feb 2026 17:02:55 +0700 Subject: [PATCH] feat(cliproxy): add Kimi as OAuth CLIProxy provider - add 'kimi' to CLIProxyProvider union type - register Kimi capabilities (device_code flow, moonshot alias) - add OAuth config, auth prefixes, type values, channel maps - add CLIProxy-delegated token refresh for Kimi - add Kimi model catalog (k2.5, k2-thinking, k2) - switch base-kimi.settings.json to CLIProxy mode (127.0.0.1:8317) - update comments removing kimi from settings-based profile mentions Closes #574 --- config/base-kimi.settings.json | 17 +++++---- src/auth/profile-detector.ts | 2 +- src/ccs.ts | 4 +-- src/cliproxy/auth/auth-types.ts | 13 +++++++ .../auth/provider-refreshers/index.ts | 4 ++- src/cliproxy/model-catalog.ts | 36 +++++++++++++++++++ src/cliproxy/provider-capabilities.ts | 6 ++++ src/cliproxy/types.ts | 4 ++- 8 files changed, 72 insertions(+), 14 deletions(-) diff --git a/config/base-kimi.settings.json b/config/base-kimi.settings.json index ad4b2dee..5b72a69f 100644 --- a/config/base-kimi.settings.json +++ b/config/base-kimi.settings.json @@ -1,11 +1,10 @@ { "env": { - "ANTHROPIC_BASE_URL": "https://api.kimi.com/coding/", - "ANTHROPIC_AUTH_TOKEN": "YOUR_KIMI_API_KEY_HERE", - "ANTHROPIC_MODEL": "kimi-k2-thinking-turbo", - "ANTHROPIC_DEFAULT_OPUS_MODEL": "kimi-k2-thinking-turbo", - "ANTHROPIC_DEFAULT_SONNET_MODEL": "kimi-k2-thinking-turbo", - "ANTHROPIC_DEFAULT_HAIKU_MODEL": "kimi-k2-thinking-turbo" - }, - "alwaysThinkingEnabled": true -} \ No newline at end of file + "ANTHROPIC_BASE_URL": "http://127.0.0.1:8317/api/provider/kimi", + "ANTHROPIC_AUTH_TOKEN": "ccs-internal-managed", + "ANTHROPIC_MODEL": "kimi-k2.5", + "ANTHROPIC_DEFAULT_OPUS_MODEL": "kimi-k2.5", + "ANTHROPIC_DEFAULT_SONNET_MODEL": "kimi-k2-thinking", + "ANTHROPIC_DEFAULT_HAIKU_MODEL": "kimi-k2" + } +} diff --git a/src/auth/profile-detector.ts b/src/auth/profile-detector.ts index 23570249..f700b030 100644 --- a/src/auth/profile-detector.ts +++ b/src/auth/profile-detector.ts @@ -308,7 +308,7 @@ class ProfileDetector { }; } - // Priority 3: Check settings-based profiles (glm, kimi) - LEGACY FALLBACK + // Priority 3: Check settings-based profiles (glm) - LEGACY FALLBACK if (config.profiles && config.profiles[profileName]) { return { type: 'settings', diff --git a/src/ccs.ts b/src/ccs.ts index b1df1571..1bf77d6d 100644 --- a/src/ccs.ts +++ b/src/ccs.ts @@ -792,7 +792,7 @@ async function main(): Promise { const exitCode = await executeCopilotProfile(copilotConfig, remainingArgs); process.exit(exitCode); } else if (profileInfo.type === 'settings') { - // Settings-based profiles (glm, glmt, kimi) are third-party providers + // Settings-based profiles (glm, glmt) are third-party providers // WebSearch is server-side tool - third-party providers have no access // Inject WebSearch hook into profile settings before launch ensureProfileHooks(profileInfo.name); @@ -869,7 +869,7 @@ async function main(): Promise { // GLMT FLOW: Settings-based with embedded proxy for thinking support await execClaudeWithProxy(claudeCli, profileInfo.name, remainingArgs); } else { - // EXISTING FLOW: Settings-based profile (glm, kimi) + // EXISTING FLOW: Settings-based profile (glm) // Use --settings flag (backward compatible) const expandedSettingsPath = getSettingsPath(profileInfo.name); const webSearchEnv = getWebSearchHookEnv(); diff --git a/src/cliproxy/auth/auth-types.ts b/src/cliproxy/auth/auth-types.ts index 91feaa70..acb10a43 100644 --- a/src/cliproxy/auth/auth-types.ts +++ b/src/cliproxy/auth/auth-types.ts @@ -88,6 +88,7 @@ export function toKiroManagementMethod(method: KiroAuthMethod): 'aws' | 'google' * - Kiro: Device Code Flow (polling-based, NO callback port needed) * - Qwen: Device Code Flow (polling-based, NO callback port needed) * - GHCP: Device Code Flow (polling-based, NO callback port needed) + * - Kimi: Device Code Flow (polling-based, NO callback port needed) */ export const OAUTH_CALLBACK_PORTS: Partial> = { gemini: 8085, @@ -98,6 +99,7 @@ export const OAUTH_CALLBACK_PORTS: Partial> = { // kiro: Device Code Flow - no callback port // qwen: Device Code Flow - no callback port // ghcp: Device Code Flow - no callback port + // kimi: Device Code Flow - no callback port }; /** @@ -199,6 +201,13 @@ export const OAUTH_CONFIGS: Record = { scopes: ['user:inference', 'user:profile'], authFlag: '--claude-login', }, + kimi: { + provider: 'kimi', + displayName: 'Kimi (Moonshot)', + authUrl: 'https://auth.kimi.com/api/oauth/device_authorization', + scopes: ['api'], + authFlag: '--kimi-login', + }, }; /** @@ -215,6 +224,7 @@ export const PROVIDER_AUTH_PREFIXES: Record = { kiro: ['kiro-', 'aws-', 'codewhisperer-'], ghcp: ['github-copilot-', 'copilot-', 'gh-'], claude: ['claude-', 'anthropic-'], + kimi: ['kimi-'], }; /** @@ -230,6 +240,7 @@ export const PROVIDER_TYPE_VALUES: Record = { kiro: ['kiro', 'codewhisperer'], ghcp: ['github-copilot', 'copilot'], claude: ['claude', 'anthropic'], + kimi: ['kimi'], }; /** @@ -245,6 +256,7 @@ export const CLIPROXY_CALLBACK_PROVIDER_MAP: Record = claude: 'anthropic', qwen: 'qwen', iflow: 'iflow', + kimi: 'kimi', }; /** @@ -261,6 +273,7 @@ export const CLIPROXY_AUTH_URL_PROVIDER_MAP: Record = claude: 'anthropic', qwen: 'qwen', iflow: 'iflow', + kimi: 'kimi', }; /** diff --git a/src/cliproxy/auth/provider-refreshers/index.ts b/src/cliproxy/auth/provider-refreshers/index.ts index 3c642340..abcf3ff8 100644 --- a/src/cliproxy/auth/provider-refreshers/index.ts +++ b/src/cliproxy/auth/provider-refreshers/index.ts @@ -5,7 +5,7 @@ * * Refresh responsibility: * - CCS-managed: gemini (CCS refreshes tokens directly via Google OAuth) - * - CLIProxy-delegated: codex, agy, kiro, ghcp, qwen, iflow + * - CLIProxy-delegated: codex, agy, kiro, ghcp, qwen, iflow, kimi * (CLIProxyAPIPlus handles refresh automatically in background) * - Not implemented: claude */ @@ -34,6 +34,7 @@ const CLIPROXY_DELEGATED_REFRESH: CLIProxyProvider[] = [ 'ghcp', 'qwen', 'iflow', + 'kimi', ]; /** @@ -63,6 +64,7 @@ export async function refreshToken( case 'iflow': case 'kiro': case 'ghcp': + case 'kimi': // CLIProxyAPIPlus handles refresh for these providers automatically. // No action needed from CCS — report success with delegated flag. return { success: true, delegated: true }; diff --git a/src/cliproxy/model-catalog.ts b/src/cliproxy/model-catalog.ts index e50d0ffc..c73e61bd 100644 --- a/src/cliproxy/model-catalog.ts +++ b/src/cliproxy/model-catalog.ts @@ -197,6 +197,42 @@ export const MODEL_CATALOG: Partial> = }, ], }, + kimi: { + provider: 'kimi', + displayName: 'Kimi (Moonshot)', + defaultModel: 'kimi-k2.5', + models: [ + { + id: 'kimi-k2.5', + name: 'Kimi K2.5', + description: 'Latest Moonshot coding model', + thinking: { + type: 'budget', + min: 1024, + max: 32000, + zeroAllowed: true, + dynamicAllowed: true, + }, + }, + { + id: 'kimi-k2-thinking', + name: 'Kimi K2 Thinking', + description: 'Extended reasoning model', + thinking: { + type: 'budget', + min: 1024, + max: 32000, + zeroAllowed: true, + dynamicAllowed: true, + }, + }, + { + id: 'kimi-k2', + name: 'Kimi K2', + description: 'Flagship coding model', + }, + ], + }, claude: { provider: 'claude', displayName: 'Claude (Anthropic)', diff --git a/src/cliproxy/provider-capabilities.ts b/src/cliproxy/provider-capabilities.ts index 6dec96a8..4ddd4f27 100644 --- a/src/cliproxy/provider-capabilities.ts +++ b/src/cliproxy/provider-capabilities.ts @@ -62,6 +62,12 @@ export const PROVIDER_CAPABILITIES: Record