mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 08:17:11 +00:00
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:
@@ -1,11 +1,10 @@
|
|||||||
{
|
{
|
||||||
"env": {
|
"env": {
|
||||||
"ANTHROPIC_BASE_URL": "https://api.kimi.com/coding/",
|
"ANTHROPIC_BASE_URL": "http://127.0.0.1:8317/api/provider/kimi",
|
||||||
"ANTHROPIC_AUTH_TOKEN": "YOUR_KIMI_API_KEY_HERE",
|
"ANTHROPIC_AUTH_TOKEN": "ccs-internal-managed",
|
||||||
"ANTHROPIC_MODEL": "kimi-k2-thinking-turbo",
|
"ANTHROPIC_MODEL": "kimi-k2.5",
|
||||||
"ANTHROPIC_DEFAULT_OPUS_MODEL": "kimi-k2-thinking-turbo",
|
"ANTHROPIC_DEFAULT_OPUS_MODEL": "kimi-k2.5",
|
||||||
"ANTHROPIC_DEFAULT_SONNET_MODEL": "kimi-k2-thinking-turbo",
|
"ANTHROPIC_DEFAULT_SONNET_MODEL": "kimi-k2-thinking",
|
||||||
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "kimi-k2-thinking-turbo"
|
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "kimi-k2"
|
||||||
},
|
}
|
||||||
"alwaysThinkingEnabled": true
|
|
||||||
}
|
}
|
||||||
@@ -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]) {
|
if (config.profiles && config.profiles[profileName]) {
|
||||||
return {
|
return {
|
||||||
type: 'settings',
|
type: 'settings',
|
||||||
|
|||||||
+2
-2
@@ -792,7 +792,7 @@ async function main(): Promise<void> {
|
|||||||
const exitCode = await executeCopilotProfile(copilotConfig, remainingArgs);
|
const exitCode = await executeCopilotProfile(copilotConfig, remainingArgs);
|
||||||
process.exit(exitCode);
|
process.exit(exitCode);
|
||||||
} else if (profileInfo.type === 'settings') {
|
} 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
|
// WebSearch is server-side tool - third-party providers have no access
|
||||||
// Inject WebSearch hook into profile settings before launch
|
// Inject WebSearch hook into profile settings before launch
|
||||||
ensureProfileHooks(profileInfo.name);
|
ensureProfileHooks(profileInfo.name);
|
||||||
@@ -869,7 +869,7 @@ async function main(): Promise<void> {
|
|||||||
// GLMT FLOW: Settings-based with embedded proxy for thinking support
|
// GLMT FLOW: Settings-based with embedded proxy for thinking support
|
||||||
await execClaudeWithProxy(claudeCli, profileInfo.name, remainingArgs);
|
await execClaudeWithProxy(claudeCli, profileInfo.name, remainingArgs);
|
||||||
} else {
|
} else {
|
||||||
// EXISTING FLOW: Settings-based profile (glm, kimi)
|
// EXISTING FLOW: Settings-based profile (glm)
|
||||||
// Use --settings flag (backward compatible)
|
// Use --settings flag (backward compatible)
|
||||||
const expandedSettingsPath = getSettingsPath(profileInfo.name);
|
const expandedSettingsPath = getSettingsPath(profileInfo.name);
|
||||||
const webSearchEnv = getWebSearchHookEnv();
|
const webSearchEnv = getWebSearchHookEnv();
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ export function toKiroManagementMethod(method: KiroAuthMethod): 'aws' | 'google'
|
|||||||
* - Kiro: Device Code Flow (polling-based, NO callback port needed)
|
* - Kiro: Device Code Flow (polling-based, NO callback port needed)
|
||||||
* - Qwen: 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)
|
* - 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>> = {
|
export const OAUTH_CALLBACK_PORTS: Partial<Record<CLIProxyProvider, number>> = {
|
||||||
gemini: 8085,
|
gemini: 8085,
|
||||||
@@ -98,6 +99,7 @@ export const OAUTH_CALLBACK_PORTS: Partial<Record<CLIProxyProvider, number>> = {
|
|||||||
// kiro: Device Code Flow - no callback port
|
// kiro: Device Code Flow - no callback port
|
||||||
// qwen: Device Code Flow - no callback port
|
// qwen: Device Code Flow - no callback port
|
||||||
// ghcp: 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'],
|
scopes: ['user:inference', 'user:profile'],
|
||||||
authFlag: '--claude-login',
|
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-'],
|
kiro: ['kiro-', 'aws-', 'codewhisperer-'],
|
||||||
ghcp: ['github-copilot-', 'copilot-', 'gh-'],
|
ghcp: ['github-copilot-', 'copilot-', 'gh-'],
|
||||||
claude: ['claude-', 'anthropic-'],
|
claude: ['claude-', 'anthropic-'],
|
||||||
|
kimi: ['kimi-'],
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -230,6 +240,7 @@ export const PROVIDER_TYPE_VALUES: Record<CLIProxyProvider, string[]> = {
|
|||||||
kiro: ['kiro', 'codewhisperer'],
|
kiro: ['kiro', 'codewhisperer'],
|
||||||
ghcp: ['github-copilot', 'copilot'],
|
ghcp: ['github-copilot', 'copilot'],
|
||||||
claude: ['claude', 'anthropic'],
|
claude: ['claude', 'anthropic'],
|
||||||
|
kimi: ['kimi'],
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -245,6 +256,7 @@ export const CLIPROXY_CALLBACK_PROVIDER_MAP: Record<CLIProxyProvider, string> =
|
|||||||
claude: 'anthropic',
|
claude: 'anthropic',
|
||||||
qwen: 'qwen',
|
qwen: 'qwen',
|
||||||
iflow: 'iflow',
|
iflow: 'iflow',
|
||||||
|
kimi: 'kimi',
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -261,6 +273,7 @@ export const CLIPROXY_AUTH_URL_PROVIDER_MAP: Record<CLIProxyProvider, string> =
|
|||||||
claude: 'anthropic',
|
claude: 'anthropic',
|
||||||
qwen: 'qwen',
|
qwen: 'qwen',
|
||||||
iflow: 'iflow',
|
iflow: 'iflow',
|
||||||
|
kimi: 'kimi',
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*
|
*
|
||||||
* Refresh responsibility:
|
* Refresh responsibility:
|
||||||
* - CCS-managed: gemini (CCS refreshes tokens directly via Google OAuth)
|
* - 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)
|
* (CLIProxyAPIPlus handles refresh automatically in background)
|
||||||
* - Not implemented: claude
|
* - Not implemented: claude
|
||||||
*/
|
*/
|
||||||
@@ -34,6 +34,7 @@ const CLIPROXY_DELEGATED_REFRESH: CLIProxyProvider[] = [
|
|||||||
'ghcp',
|
'ghcp',
|
||||||
'qwen',
|
'qwen',
|
||||||
'iflow',
|
'iflow',
|
||||||
|
'kimi',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -63,6 +64,7 @@ export async function refreshToken(
|
|||||||
case 'iflow':
|
case 'iflow':
|
||||||
case 'kiro':
|
case 'kiro':
|
||||||
case 'ghcp':
|
case 'ghcp':
|
||||||
|
case 'kimi':
|
||||||
// CLIProxyAPIPlus handles refresh for these providers automatically.
|
// CLIProxyAPIPlus handles refresh for these providers automatically.
|
||||||
// No action needed from CCS — report success with delegated flag.
|
// No action needed from CCS — report success with delegated flag.
|
||||||
return { success: true, delegated: true };
|
return { success: true, delegated: true };
|
||||||
|
|||||||
@@ -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: {
|
claude: {
|
||||||
provider: 'claude',
|
provider: 'claude',
|
||||||
displayName: 'Claude (Anthropic)',
|
displayName: 'Claude (Anthropic)',
|
||||||
|
|||||||
@@ -62,6 +62,12 @@ export const PROVIDER_CAPABILITIES: Record<CLIProxyProvider, ProviderCapabilitie
|
|||||||
callbackPort: 54545,
|
callbackPort: 54545,
|
||||||
aliases: ['anthropic'],
|
aliases: ['anthropic'],
|
||||||
},
|
},
|
||||||
|
kimi: {
|
||||||
|
displayName: 'Kimi (Moonshot)',
|
||||||
|
oauthFlow: 'device_code',
|
||||||
|
callbackPort: null,
|
||||||
|
aliases: ['moonshot'],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CLIPROXY_PROVIDER_IDS = Object.freeze(
|
export const CLIPROXY_PROVIDER_IDS = Object.freeze(
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ export interface DownloadResult {
|
|||||||
* - kiro: Kiro (AWS CodeWhisperer) via OAuth
|
* - kiro: Kiro (AWS CodeWhisperer) via OAuth
|
||||||
* - ghcp: GitHub Copilot via Device Code (OAuth through CLIProxyAPIPlus)
|
* - ghcp: GitHub Copilot via Device Code (OAuth through CLIProxyAPIPlus)
|
||||||
* - claude: Claude (Anthropic) via OAuth
|
* - claude: Claude (Anthropic) via OAuth
|
||||||
|
* - kimi: Kimi (Moonshot AI) via Device Code OAuth
|
||||||
*/
|
*/
|
||||||
export type CLIProxyProvider =
|
export type CLIProxyProvider =
|
||||||
| 'gemini'
|
| 'gemini'
|
||||||
@@ -130,7 +131,8 @@ export type CLIProxyProvider =
|
|||||||
| 'iflow'
|
| 'iflow'
|
||||||
| 'kiro'
|
| 'kiro'
|
||||||
| 'ghcp'
|
| 'ghcp'
|
||||||
| 'claude';
|
| 'claude'
|
||||||
|
| 'kimi';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CLIProxy backend selection
|
* CLIProxy backend selection
|
||||||
|
|||||||
Reference in New Issue
Block a user