From 3767b95735950b506e2470a0454d4d0db7f00764 Mon Sep 17 00:00:00 2001 From: Tam Nhu Tran Date: Thu, 19 Feb 2026 10:28:40 +0700 Subject: [PATCH 1/3] fix(cliproxy): add Kimi model catalog, sync, and pricing to dashboard - Add kimi entry to UI model-catalogs.ts with K2.5, K2 Thinking, K2 models and preset mappings so dashboard shows available models - Add kimi to CHANNEL_TO_PROVIDER and SYNCABLE_PROVIDERS in catalog-cache.ts so models sync from upstream CLIProxyAPI - Add kimi/moonshot to provider-editor ownerMap for model filtering - Update Kimi model pricing to match official Kimi Platform rates: kimi-k2.5 ($0.60/$3.00), kimi-k2-thinking ($0.60/$2.50), kimi-k2-turbo-preview ($1.15/$8.00) - Add missing kimi-k2.5 pricing entry Closes #581 --- src/cliproxy/catalog-cache.ts | 3 +- src/web-server/model-pricing.ts | 41 +++++++++++-------- .../cliproxy/provider-editor/index.tsx | 1 + ui/src/lib/model-catalogs.ts | 34 +++++++++++++++ 4 files changed, 61 insertions(+), 18 deletions(-) diff --git a/src/cliproxy/catalog-cache.ts b/src/cliproxy/catalog-cache.ts index 3045bc6a..948f0b75 100644 --- a/src/cliproxy/catalog-cache.ts +++ b/src/cliproxy/catalog-cache.ts @@ -23,6 +23,7 @@ const CHANNEL_TO_PROVIDER: Record = { codex: 'codex', qwen: 'qwen', iflow: 'iflow', + kimi: 'kimi', }; /** CCS provider → channel name mapping (reverse) */ @@ -31,7 +32,7 @@ export const PROVIDER_TO_CHANNEL: Record = Object.fromEntries( ); /** Providers to sync from CLIProxyAPI */ -export const SYNCABLE_PROVIDERS: CLIProxyProvider[] = ['agy', 'gemini', 'codex', 'claude']; +export const SYNCABLE_PROVIDERS: CLIProxyProvider[] = ['agy', 'gemini', 'codex', 'claude', 'kimi']; function getCacheFilePath(): string { return path.join(getCcsDir(), CACHE_FILE_NAME); diff --git a/src/web-server/model-pricing.ts b/src/web-server/model-pricing.ts index 3af43b91..88d008f4 100644 --- a/src/web-server/model-pricing.ts +++ b/src/web-server/model-pricing.ts @@ -450,37 +450,44 @@ const PRICING_REGISTRY: Record = { }, // --------------------------------------------------------------------------- - // Kimi Models (Moonshot AI) - Source: better-ccusage + // Kimi Models (Moonshot AI) - Source: Official Kimi Platform pricing + // inputPerMillion = cache miss price, cacheReadPerMillion = cache hit price // --------------------------------------------------------------------------- - 'kimi-for-coding': { - inputPerMillion: 0.15, - outputPerMillion: 0.6, + 'kimi-k2.5': { + inputPerMillion: 0.6, + outputPerMillion: 3.0, cacheCreationPerMillion: 0.0, - cacheReadPerMillion: 0.0, + cacheReadPerMillion: 0.1, + }, + 'kimi-for-coding': { + inputPerMillion: 0.6, + outputPerMillion: 2.5, + cacheCreationPerMillion: 0.0, + cacheReadPerMillion: 0.15, }, 'kimi-k2-0905-preview': { - inputPerMillion: 0.15, - outputPerMillion: 0.6, + inputPerMillion: 0.6, + outputPerMillion: 2.5, cacheCreationPerMillion: 0.0, - cacheReadPerMillion: 0.0, + cacheReadPerMillion: 0.15, }, 'kimi-k2-turbo-preview': { - inputPerMillion: 0.15, - outputPerMillion: 1.15, + inputPerMillion: 1.15, + outputPerMillion: 8.0, cacheCreationPerMillion: 0.0, - cacheReadPerMillion: 0.0, + cacheReadPerMillion: 0.15, }, 'kimi-k2-thinking': { - inputPerMillion: 0.15, - outputPerMillion: 0.6, + inputPerMillion: 0.6, + outputPerMillion: 2.5, cacheCreationPerMillion: 0.0, - cacheReadPerMillion: 0.0, + cacheReadPerMillion: 0.15, }, 'kimi-k2-thinking-turbo': { - inputPerMillion: 0.15, - outputPerMillion: 1.15, + inputPerMillion: 1.15, + outputPerMillion: 8.0, cacheCreationPerMillion: 0.0, - cacheReadPerMillion: 0.0, + cacheReadPerMillion: 0.15, }, 'kimi-k2-instruct': { inputPerMillion: 1.0, diff --git a/ui/src/components/cliproxy/provider-editor/index.tsx b/ui/src/components/cliproxy/provider-editor/index.tsx index f7a6c172..72a64f5d 100644 --- a/ui/src/components/cliproxy/provider-editor/index.tsx +++ b/ui/src/components/cliproxy/provider-editor/index.tsx @@ -70,6 +70,7 @@ export function ProviderEditor({ iflow: ['iflow'], kiro: ['kiro', 'aws'], ghcp: ['github', 'copilot'], + kimi: ['kimi', 'moonshot'], }; const owners = ownerMap[modelFilterProvider.toLowerCase()] || [ modelFilterProvider.toLowerCase(), diff --git a/ui/src/lib/model-catalogs.ts b/ui/src/lib/model-catalogs.ts index 12aa1df1..1736b19a 100644 --- a/ui/src/lib/model-catalogs.ts +++ b/ui/src/lib/model-catalogs.ts @@ -275,6 +275,40 @@ export const MODEL_CATALOGS: Record = { }, ], }, + kimi: { + provider: 'kimi', + displayName: 'Kimi (Moonshot)', + defaultModel: 'kimi-k2.5', + models: [ + { + id: 'kimi-k2.5', + name: 'Kimi K2.5', + description: 'Latest multimodal model (262K context)', + presetMapping: { + default: 'kimi-k2.5', + opus: 'kimi-k2.5', + sonnet: 'kimi-k2-thinking', + haiku: 'kimi-k2', + }, + }, + { + id: 'kimi-k2-thinking', + name: 'Kimi K2 Thinking', + description: 'Extended reasoning model', + presetMapping: { + default: 'kimi-k2-thinking', + opus: 'kimi-k2.5', + sonnet: 'kimi-k2-thinking', + haiku: 'kimi-k2', + }, + }, + { + id: 'kimi-k2', + name: 'Kimi K2', + description: 'Flagship coding model', + }, + ], + }, kiro: { provider: 'kiro', displayName: 'Kiro (AWS)', From dd38df6b8d7a5367c06b14b0258a271af8545fd4 Mon Sep 17 00:00:00 2001 From: Tam Nhu Tran Date: Thu, 19 Feb 2026 10:36:42 +0700 Subject: [PATCH 2/3] fix(cliproxy): add kimi-k2 pricing and kimi catalog tests Address review feedback from PR #585: - Add missing kimi-k2 pricing entry ($0.60/$2.50, cache $0.15) to avoid fallback to unknown model pricing - Add kimi provider tests to model-catalog.test.js verifying catalog structure, default model, and model IDs --- src/web-server/model-pricing.ts | 6 +++++ tests/unit/cliproxy/model-catalog.test.js | 27 +++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/web-server/model-pricing.ts b/src/web-server/model-pricing.ts index 88d008f4..dfc654a6 100644 --- a/src/web-server/model-pricing.ts +++ b/src/web-server/model-pricing.ts @@ -489,6 +489,12 @@ const PRICING_REGISTRY: Record = { cacheCreationPerMillion: 0.0, cacheReadPerMillion: 0.15, }, + 'kimi-k2': { + inputPerMillion: 0.6, + outputPerMillion: 2.5, + cacheCreationPerMillion: 0.0, + cacheReadPerMillion: 0.15, + }, 'kimi-k2-instruct': { inputPerMillion: 1.0, outputPerMillion: 3.0, diff --git a/tests/unit/cliproxy/model-catalog.test.js b/tests/unit/cliproxy/model-catalog.test.js index cbf631cc..1f0fdbf0 100644 --- a/tests/unit/cliproxy/model-catalog.test.js +++ b/tests/unit/cliproxy/model-catalog.test.js @@ -36,6 +36,33 @@ describe('Model Catalog', () => { }); }); + describe('Kimi models', () => { + it('contains Kimi provider catalog', () => { + const { MODEL_CATALOG } = modelCatalog; + assert(MODEL_CATALOG.kimi, 'Should have kimi provider'); + assert.strictEqual(MODEL_CATALOG.kimi.provider, 'kimi'); + assert.strictEqual(MODEL_CATALOG.kimi.displayName, 'Kimi (Moonshot)'); + }); + + it('has correct default model', () => { + const { MODEL_CATALOG } = modelCatalog; + assert.strictEqual(MODEL_CATALOG.kimi.defaultModel, 'kimi-k2.5'); + }); + + it('includes K2.5, K2 Thinking, K2', () => { + const { MODEL_CATALOG } = modelCatalog; + const ids = MODEL_CATALOG.kimi.models.map((m) => m.id); + assert(ids.includes('kimi-k2.5'), 'Should include kimi-k2.5'); + assert(ids.includes('kimi-k2-thinking'), 'Should include kimi-k2-thinking'); + assert(ids.includes('kimi-k2'), 'Should include kimi-k2'); + }); + + it('has 3 models total', () => { + const { MODEL_CATALOG } = modelCatalog; + assert.strictEqual(MODEL_CATALOG.kimi.models.length, 3); + }); + }); + describe('AGY models', () => { it('has correct default model', () => { const { MODEL_CATALOG } = modelCatalog; From c73a26c51c5340598aacf25f48fb2851bf61d5a8 Mon Sep 17 00:00:00 2001 From: Tam Nhu Tran Date: Thu, 19 Feb 2026 10:41:32 +0700 Subject: [PATCH 3/3] fix(cliproxy): address review feedback on kimi catalog - Sync kimi-k2.5 description between backend and UI catalogs to 'Latest multimodal model (262K context)' per official naming - Add kimi-k2 pricing entry to avoid fallback to unknown model rate - Add supportsModelConfig and getProviderCatalog tests for kimi --- src/cliproxy/model-catalog.ts | 2 +- tests/unit/cliproxy/model-catalog.test.js | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/cliproxy/model-catalog.ts b/src/cliproxy/model-catalog.ts index c73e61bd..e03d6b6a 100644 --- a/src/cliproxy/model-catalog.ts +++ b/src/cliproxy/model-catalog.ts @@ -205,7 +205,7 @@ export const MODEL_CATALOG: Partial> = { id: 'kimi-k2.5', name: 'Kimi K2.5', - description: 'Latest Moonshot coding model', + description: 'Latest multimodal model (262K context)', thinking: { type: 'budget', min: 1024, diff --git a/tests/unit/cliproxy/model-catalog.test.js b/tests/unit/cliproxy/model-catalog.test.js index 1f0fdbf0..b3fcfa68 100644 --- a/tests/unit/cliproxy/model-catalog.test.js +++ b/tests/unit/cliproxy/model-catalog.test.js @@ -153,6 +153,11 @@ describe('Model Catalog', () => { assert.strictEqual(supportsModelConfig('codex'), true); }); + it('returns true for kimi', () => { + const { supportsModelConfig } = modelCatalog; + assert.strictEqual(supportsModelConfig('kimi'), true); + }); + it('returns false for qwen', () => { const { supportsModelConfig } = modelCatalog; assert.strictEqual(supportsModelConfig('qwen'), false); @@ -182,6 +187,14 @@ describe('Model Catalog', () => { assert.strictEqual(catalog.provider, 'codex'); assert(Array.isArray(catalog.models)); }); + + it('returns catalog for kimi', () => { + const { getProviderCatalog } = modelCatalog; + const catalog = getProviderCatalog('kimi'); + assert(catalog, 'Should return catalog'); + assert.strictEqual(catalog.provider, 'kimi'); + assert(Array.isArray(catalog.models)); + }); }); describe('findModel', () => {