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
This commit is contained in:
Tam Nhu Tran
2026-02-17 17:02:55 +07:00
parent 94b03c7f75
commit 08b2a67913
8 changed files with 72 additions and 14 deletions
+8 -9
View File
@@ -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
}
"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"
}
}
+1 -1
View File
@@ -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',
+2 -2
View File
@@ -792,7 +792,7 @@ async function main(): Promise<void> {
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<void> {
// 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();
+13
View File
@@ -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<Record<CLIProxyProvider, number>> = {
gemini: 8085,
@@ -98,6 +99,7 @@ export const OAUTH_CALLBACK_PORTS: Partial<Record<CLIProxyProvider, number>> = {
// 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<CLIProxyProvider, ProviderOAuthConfig> = {
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<CLIProxyProvider, string[]> = {
kiro: ['kiro-', 'aws-', 'codewhisperer-'],
ghcp: ['github-copilot-', 'copilot-', 'gh-'],
claude: ['claude-', 'anthropic-'],
kimi: ['kimi-'],
};
/**
@@ -230,6 +240,7 @@ export const PROVIDER_TYPE_VALUES: Record<CLIProxyProvider, string[]> = {
kiro: ['kiro', 'codewhisperer'],
ghcp: ['github-copilot', 'copilot'],
claude: ['claude', 'anthropic'],
kimi: ['kimi'],
};
/**
@@ -245,6 +256,7 @@ export const CLIPROXY_CALLBACK_PROVIDER_MAP: Record<CLIProxyProvider, string> =
claude: 'anthropic',
qwen: 'qwen',
iflow: 'iflow',
kimi: 'kimi',
};
/**
@@ -261,6 +273,7 @@ export const CLIPROXY_AUTH_URL_PROVIDER_MAP: Record<CLIProxyProvider, string> =
claude: 'anthropic',
qwen: 'qwen',
iflow: 'iflow',
kimi: 'kimi',
};
/**
@@ -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 };
+36
View File
@@ -197,6 +197,42 @@ export const MODEL_CATALOG: Partial<Record<CLIProxyProvider, ProviderCatalog>> =
},
],
},
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)',
+6
View File
@@ -62,6 +62,12 @@ export const PROVIDER_CAPABILITIES: Record<CLIProxyProvider, ProviderCapabilitie
callbackPort: 54545,
aliases: ['anthropic'],
},
kimi: {
displayName: 'Kimi (Moonshot)',
oauthFlow: 'device_code',
callbackPort: null,
aliases: ['moonshot'],
},
};
export const CLIPROXY_PROVIDER_IDS = Object.freeze(
+3 -1
View File
@@ -121,6 +121,7 @@ export interface DownloadResult {
* - kiro: Kiro (AWS CodeWhisperer) via OAuth
* - ghcp: GitHub Copilot via Device Code (OAuth through CLIProxyAPIPlus)
* - claude: Claude (Anthropic) via OAuth
* - kimi: Kimi (Moonshot AI) via Device Code OAuth
*/
export type CLIProxyProvider =
| 'gemini'
@@ -130,7 +131,8 @@ export type CLIProxyProvider =
| 'iflow'
| 'kiro'
| 'ghcp'
| 'claude';
| 'claude'
| 'kimi';
/**
* CLIProxy backend selection