From eb1cf80b10cc2ca96484141140a6b9c364822b29 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Thu, 16 Apr 2026 12:06:24 +0200 Subject: [PATCH] fix(ai,coding-agent): replace deprecated kimi k2p5 model closes #3242 --- packages/ai/CHANGELOG.md | 1 + packages/ai/scripts/generate-models.ts | 51 +++---------- packages/ai/src/models.generated.ts | 74 ++++++++++++++++++- packages/ai/test/image-tool-result.test.ts | 4 +- packages/ai/test/tokens.test.ts | 2 +- packages/coding-agent/CHANGELOG.md | 1 + .../coding-agent/src/core/model-resolver.ts | 2 +- 7 files changed, 89 insertions(+), 46 deletions(-) diff --git a/packages/ai/CHANGELOG.md b/packages/ai/CHANGELOG.md index be19509e..186c607d 100644 --- a/packages/ai/CHANGELOG.md +++ b/packages/ai/CHANGELOG.md @@ -5,6 +5,7 @@ ### Changed - Changed Anthropic prompt caching to add a `cache_control` breakpoint on the last tool definition, so tool schemas can be cached independently from transcript updates while preserving existing cache retention behavior ([#3260](https://github.com/badlogic/pi-mono/issues/3260)) +- Changed Kimi Coding model generation to normalize deprecated `k2p5` to `kimi-for-coding` from models.dev data and removed the old static fallback model list ([#3242](https://github.com/badlogic/pi-mono/issues/3242)) ## [0.67.3] - 2026-04-15 diff --git a/packages/ai/scripts/generate-models.ts b/packages/ai/scripts/generate-models.ts index 1fd80907..902d798c 100644 --- a/packages/ai/scripts/generate-models.ts +++ b/packages/ai/scripts/generate-models.ts @@ -606,13 +606,22 @@ async function loadModelsDevData(): Promise[]> { // Process Kimi For Coding models if (data["kimi-for-coding"]?.models) { - for (const [modelId, model] of Object.entries(data["kimi-for-coding"].models)) { + const kimiModels = data["kimi-for-coding"].models as Record; + const hasCanonicalModel = Object.prototype.hasOwnProperty.call(kimiModels, "kimi-for-coding"); + + for (const [modelId, model] of Object.entries(kimiModels)) { const m = model as ModelsDevModel; if (m.tool_call !== true) continue; + // models.dev still exposes deprecated "k2p5" in some snapshots. + // Normalize to the canonical model id and drop duplicates when canonical exists. + if (modelId === "k2p5" && hasCanonicalModel) continue; + + const normalizedId = modelId === "k2p5" ? "kimi-for-coding" : modelId; + const normalizedName = modelId === "k2p5" ? "Kimi For Coding" : m.name || normalizedId; models.push({ - id: modelId, - name: m.name || modelId, + id: normalizedId, + name: normalizedName, api: "anthropic-messages", provider: "kimi-coding", // Kimi For Coding's Anthropic-compatible API - SDK appends /v1/messages @@ -1458,42 +1467,6 @@ async function generateModels() { ]; allModels.push(...vertexModels); - // Kimi For Coding models (Moonshot AI's Anthropic-compatible coding API) - // Static fallback in case models.dev doesn't have them yet - const KIMI_CODING_BASE_URL = "https://api.kimi.com/coding"; - const kimiCodingModels: Model<"anthropic-messages">[] = [ - { - id: "kimi-k2-thinking", - name: "Kimi K2 Thinking", - api: "anthropic-messages", - provider: "kimi-coding", - baseUrl: KIMI_CODING_BASE_URL, - reasoning: true, - input: ["text"], - cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, - contextWindow: 262144, - maxTokens: 32768, - }, - { - id: "k2p5", - name: "Kimi K2.5", - api: "anthropic-messages", - provider: "kimi-coding", - baseUrl: KIMI_CODING_BASE_URL, - reasoning: true, - input: ["text"], - cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, - contextWindow: 262144, - maxTokens: 32768, - }, - ]; - // Only add if not already present from models.dev - for (const model of kimiCodingModels) { - if (!allModels.some(m => m.provider === "kimi-coding" && m.id === model.id)) { - allModels.push(model); - } - } - const azureOpenAiModels: Model[] = allModels .filter((model) => model.provider === "openai" && model.api === "openai-responses") .map((model) => ({ diff --git a/packages/ai/src/models.generated.ts b/packages/ai/src/models.generated.ts index 9ed30755..757d4c68 100644 --- a/packages/ai/src/models.generated.ts +++ b/packages/ai/src/models.generated.ts @@ -4685,9 +4685,9 @@ export const MODELS = { } satisfies Model<"openai-completions">, }, "kimi-coding": { - "k2p5": { - id: "k2p5", - name: "Kimi K2.5", + "kimi-for-coding": { + id: "kimi-for-coding", + name: "Kimi For Coding", api: "anthropic-messages", provider: "kimi-coding", baseUrl: "https://api.kimi.com/coding", @@ -6618,6 +6618,40 @@ export const MODELS = { contextWindow: 204800, maxTokens: 128000, } satisfies Model<"openai-completions">, + "qwen3.5-plus": { + id: "qwen3.5-plus", + name: "Qwen3.5 Plus", + api: "openai-completions", + provider: "opencode", + baseUrl: "https://opencode.ai/zen/v1", + reasoning: true, + input: ["text", "image"], + cost: { + input: 0.2, + output: 1.2, + cacheRead: 0.02, + cacheWrite: 0.25, + }, + contextWindow: 262144, + maxTokens: 65536, + } satisfies Model<"openai-completions">, + "qwen3.6-plus": { + id: "qwen3.6-plus", + name: "Qwen3.6 Plus", + api: "openai-completions", + provider: "opencode", + baseUrl: "https://opencode.ai/zen/v1", + reasoning: true, + input: ["text", "image"], + cost: { + input: 0.5, + output: 3, + cacheRead: 0.05, + cacheWrite: 0.625, + }, + contextWindow: 262144, + maxTokens: 65536, + } satisfies Model<"openai-completions">, }, "opencode-go": { "glm-5": { @@ -6739,6 +6773,40 @@ export const MODELS = { contextWindow: 204800, maxTokens: 131072, } satisfies Model<"anthropic-messages">, + "qwen3.5-plus": { + id: "qwen3.5-plus", + name: "Qwen3.5 Plus", + api: "openai-completions", + provider: "opencode-go", + baseUrl: "https://opencode.ai/zen/go/v1", + reasoning: true, + input: ["text", "image"], + cost: { + input: 0.2, + output: 1.2, + cacheRead: 0.02, + cacheWrite: 0.25, + }, + contextWindow: 262144, + maxTokens: 65536, + } satisfies Model<"openai-completions">, + "qwen3.6-plus": { + id: "qwen3.6-plus", + name: "Qwen3.6 Plus", + api: "openai-completions", + provider: "opencode-go", + baseUrl: "https://opencode.ai/zen/go/v1", + reasoning: true, + input: ["text", "image"], + cost: { + input: 0.5, + output: 3, + cacheRead: 0.05, + cacheWrite: 0.625, + }, + contextWindow: 262144, + maxTokens: 65536, + } satisfies Model<"openai-completions">, }, "openrouter": { "ai21/jamba-large-1.7": { diff --git a/packages/ai/test/image-tool-result.test.ts b/packages/ai/test/image-tool-result.test.ts index dfb1215c..da5f12e3 100644 --- a/packages/ai/test/image-tool-result.test.ts +++ b/packages/ai/test/image-tool-result.test.ts @@ -300,8 +300,8 @@ describe("Tool Results with Images", () => { }); }); - describe.skipIf(!process.env.KIMI_API_KEY)("Kimi For Coding Provider (k2p5)", () => { - const llm = getModel("kimi-coding", "k2p5"); + describe.skipIf(!process.env.KIMI_API_KEY)("Kimi For Coding Provider (kimi-for-coding)", () => { + const llm = getModel("kimi-coding", "kimi-for-coding"); it("should handle tool result with only image", { retry: 3, timeout: 30000 }, async () => { await handleToolWithImageResult(llm); diff --git a/packages/ai/test/tokens.test.ts b/packages/ai/test/tokens.test.ts index b0b37a45..2af593a2 100644 --- a/packages/ai/test/tokens.test.ts +++ b/packages/ai/test/tokens.test.ts @@ -192,7 +192,7 @@ describe("Token Statistics on Abort", () => { }); describe.skipIf(!process.env.KIMI_API_KEY)("Kimi For Coding Provider", () => { - const llm = getModel("kimi-coding", "k2p5"); + const llm = getModel("kimi-coding", "kimi-for-coding"); it("should include token stats when aborted mid-stream", { retry: 3, timeout: 30000 }, async () => { await testTokensOnAbort(llm); diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index f55e8a5b..cf780463 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -9,6 +9,7 @@ ### Fixed - Fixed flaky `edit-tool-no-full-redraw` TUI tests by waiting for asynchronous preview and preflight error rendering instead of relying on fixed render ticks. +- Fixed `kimi-coding` default model selection to use `kimi-for-coding` instead of `kimi-k2-thinking` ([#3242](https://github.com/badlogic/pi-mono/issues/3242)) ## [0.67.3] - 2026-04-15 diff --git a/packages/coding-agent/src/core/model-resolver.ts b/packages/coding-agent/src/core/model-resolver.ts index 1825274a..0dad6e47 100644 --- a/packages/coding-agent/src/core/model-resolver.ts +++ b/packages/coding-agent/src/core/model-resolver.ts @@ -34,7 +34,7 @@ export const defaultModelPerProvider: Record = { huggingface: "moonshotai/Kimi-K2.5", opencode: "claude-opus-4-6", "opencode-go": "kimi-k2.5", - "kimi-coding": "kimi-k2-thinking", + "kimi-coding": "kimi-for-coding", }; export interface ScopedModel {