fix(ai,coding-agent): replace deprecated kimi k2p5 model closes #3242
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
### Changed
|
### 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 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
|
## [0.67.3] - 2026-04-15
|
||||||
|
|
||||||
|
|||||||
@@ -606,13 +606,22 @@ async function loadModelsDevData(): Promise<Model<any>[]> {
|
|||||||
|
|
||||||
// Process Kimi For Coding models
|
// Process Kimi For Coding models
|
||||||
if (data["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<string, ModelsDevModel>;
|
||||||
|
const hasCanonicalModel = Object.prototype.hasOwnProperty.call(kimiModels, "kimi-for-coding");
|
||||||
|
|
||||||
|
for (const [modelId, model] of Object.entries(kimiModels)) {
|
||||||
const m = model as ModelsDevModel;
|
const m = model as ModelsDevModel;
|
||||||
if (m.tool_call !== true) continue;
|
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({
|
models.push({
|
||||||
id: modelId,
|
id: normalizedId,
|
||||||
name: m.name || modelId,
|
name: normalizedName,
|
||||||
api: "anthropic-messages",
|
api: "anthropic-messages",
|
||||||
provider: "kimi-coding",
|
provider: "kimi-coding",
|
||||||
// Kimi For Coding's Anthropic-compatible API - SDK appends /v1/messages
|
// Kimi For Coding's Anthropic-compatible API - SDK appends /v1/messages
|
||||||
@@ -1458,42 +1467,6 @@ async function generateModels() {
|
|||||||
];
|
];
|
||||||
allModels.push(...vertexModels);
|
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<Api>[] = allModels
|
const azureOpenAiModels: Model<Api>[] = allModels
|
||||||
.filter((model) => model.provider === "openai" && model.api === "openai-responses")
|
.filter((model) => model.provider === "openai" && model.api === "openai-responses")
|
||||||
.map((model) => ({
|
.map((model) => ({
|
||||||
|
|||||||
@@ -4685,9 +4685,9 @@ export const MODELS = {
|
|||||||
} satisfies Model<"openai-completions">,
|
} satisfies Model<"openai-completions">,
|
||||||
},
|
},
|
||||||
"kimi-coding": {
|
"kimi-coding": {
|
||||||
"k2p5": {
|
"kimi-for-coding": {
|
||||||
id: "k2p5",
|
id: "kimi-for-coding",
|
||||||
name: "Kimi K2.5",
|
name: "Kimi For Coding",
|
||||||
api: "anthropic-messages",
|
api: "anthropic-messages",
|
||||||
provider: "kimi-coding",
|
provider: "kimi-coding",
|
||||||
baseUrl: "https://api.kimi.com/coding",
|
baseUrl: "https://api.kimi.com/coding",
|
||||||
@@ -6618,6 +6618,40 @@ export const MODELS = {
|
|||||||
contextWindow: 204800,
|
contextWindow: 204800,
|
||||||
maxTokens: 128000,
|
maxTokens: 128000,
|
||||||
} satisfies Model<"openai-completions">,
|
} 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": {
|
"opencode-go": {
|
||||||
"glm-5": {
|
"glm-5": {
|
||||||
@@ -6739,6 +6773,40 @@ export const MODELS = {
|
|||||||
contextWindow: 204800,
|
contextWindow: 204800,
|
||||||
maxTokens: 131072,
|
maxTokens: 131072,
|
||||||
} satisfies Model<"anthropic-messages">,
|
} 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": {
|
"openrouter": {
|
||||||
"ai21/jamba-large-1.7": {
|
"ai21/jamba-large-1.7": {
|
||||||
|
|||||||
@@ -300,8 +300,8 @@ describe("Tool Results with Images", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe.skipIf(!process.env.KIMI_API_KEY)("Kimi For Coding Provider (k2p5)", () => {
|
describe.skipIf(!process.env.KIMI_API_KEY)("Kimi For Coding Provider (kimi-for-coding)", () => {
|
||||||
const llm = getModel("kimi-coding", "k2p5");
|
const llm = getModel("kimi-coding", "kimi-for-coding");
|
||||||
|
|
||||||
it("should handle tool result with only image", { retry: 3, timeout: 30000 }, async () => {
|
it("should handle tool result with only image", { retry: 3, timeout: 30000 }, async () => {
|
||||||
await handleToolWithImageResult(llm);
|
await handleToolWithImageResult(llm);
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ describe("Token Statistics on Abort", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe.skipIf(!process.env.KIMI_API_KEY)("Kimi For Coding Provider", () => {
|
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 () => {
|
it("should include token stats when aborted mid-stream", { retry: 3, timeout: 30000 }, async () => {
|
||||||
await testTokensOnAbort(llm);
|
await testTokensOnAbort(llm);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
### Fixed
|
### 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 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
|
## [0.67.3] - 2026-04-15
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export const defaultModelPerProvider: Record<KnownProvider, string> = {
|
|||||||
huggingface: "moonshotai/Kimi-K2.5",
|
huggingface: "moonshotai/Kimi-K2.5",
|
||||||
opencode: "claude-opus-4-6",
|
opencode: "claude-opus-4-6",
|
||||||
"opencode-go": "kimi-k2.5",
|
"opencode-go": "kimi-k2.5",
|
||||||
"kimi-coding": "kimi-k2-thinking",
|
"kimi-coding": "kimi-for-coding",
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface ScopedModel {
|
export interface ScopedModel {
|
||||||
|
|||||||
Reference in New Issue
Block a user