From c0313010f94b516859637c5fb6daeb2d73d7dbde Mon Sep 17 00:00:00 2001 From: BiuBiu2015 Date: Fri, 17 Jul 2026 23:25:07 +0800 Subject: [PATCH] fix(provider): support Kimi K3 reasoning effort Kimi K3 models using Anthropic-compatible endpoint derive adaptive low/high/max variants from models.dev, preventing budget-token fallback. Includes unit and provider regression coverage. --- packages/opencode/src/provider/transform.ts | 2 ++ .../opencode/test/provider/provider.test.ts | 14 ++++++++++++++ .../opencode/test/provider/transform.test.ts | 17 +++++++++++++++-- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/packages/opencode/src/provider/transform.ts b/packages/opencode/src/provider/transform.ts index 92d84eac8cb0..11c2e5dbd488 100644 --- a/packages/opencode/src/provider/transform.ts +++ b/packages/opencode/src/provider/transform.ts @@ -1704,6 +1704,8 @@ function reasoningEffort(model: Provider.Model, effort: string) { } function anthropicEffort(model: Provider.Model, effort: string) { + // K3's Anthropic-compatible endpoint exposes adaptive thinking through output_config.effort. + if (model.family === "kimi-k3") return { thinking: { type: "adaptive" }, effort } if (["opus-4-5", "opus-4.5"].some((value) => model.api.id.includes(value))) return { effort } if (!anthropicAdaptiveEfforts(model.api.id)) return return { diff --git a/packages/opencode/test/provider/provider.test.ts b/packages/opencode/test/provider/provider.test.ts index e656890b01b0..ffc820e363a8 100644 --- a/packages/opencode/test/provider/provider.test.ts +++ b/packages/opencode/test/provider/provider.test.ts @@ -1514,6 +1514,15 @@ test("models.dev reasoning options replace generated variants and unsupported op limit: { context: 128_000, output: 64_000 }, experimental: { modes: { fast: {} } }, }, + k3: { + id: "k3", + name: "Kimi K3", + family: "kimi-k3", + reasoning: true, + reasoning_options: [{ type: "effort", values: ["low", "high", "max"] }], + provider: { npm: "@ai-sdk/anthropic" }, + limit: { context: 1_048_576, output: 131_072 }, + }, }, } as unknown as ModelsDev.Provider @@ -1531,6 +1540,11 @@ test("models.dev reasoning options replace generated variants and unsupported op high: { thinkingConfig: { includeThoughts: true, thinkingLevel: "high" } }, }) expect(models["gemini-3-pro-fast"].variants).toEqual(models.override.variants) + expect(models.k3.variants).toEqual({ + low: { thinking: { type: "adaptive" }, effort: "low" }, + high: { thinking: { type: "adaptive" }, effort: "high" }, + max: { thinking: { type: "adaptive" }, effort: "max" }, + }) }) test("public provider info omits invalid models", () => { diff --git a/packages/opencode/test/provider/transform.test.ts b/packages/opencode/test/provider/transform.test.ts index 4c462bd3dce2..97a303f88392 100644 --- a/packages/opencode/test/provider/transform.test.ts +++ b/packages/opencode/test/provider/transform.test.ts @@ -3028,8 +3028,8 @@ describe("ProviderTransform.temperature - Cohere North", () => { describe("ProviderTransform.reasoningVariants", () => { const model = (reasoning_options: ModelsDev.Model["reasoning_options"]) => ({ reasoning_options }) as ModelsDev.Model - const target = (npm: string, id = "test-model") => - ({ id, api: { id, npm, url: "" }, capabilities: { reasoning: true }, limit: { output: 64_000 } }) as any + const target = (npm: string, id = "test-model", family?: string) => + ({ id, family, api: { id, npm, url: "" }, capabilities: { reasoning: true }, limit: { output: 64_000 } }) as any test("respects explicitly empty reasoning options", () => { expect(ProviderTransform.reasoningVariants(model([]), target("@ai-sdk/openai"))).toEqual({}) @@ -3103,6 +3103,19 @@ describe("ProviderTransform.reasoningVariants", () => { ).toEqual({ high: { effort: "high" } }) }) + test("uses adaptive effort for Kimi K3", () => { + expect( + ProviderTransform.reasoningVariants( + model([{ type: "effort", values: ["low", "high", "max"] }]), + target("@ai-sdk/anthropic", "k3", "kimi-k3"), + ), + ).toEqual({ + low: { thinking: { type: "adaptive" }, effort: "low" }, + high: { thinking: { type: "adaptive" }, effort: "high" }, + max: { thinking: { type: "adaptive" }, effort: "max" }, + }) + }) + test("leaves legacy Anthropic effort options to budget fallback", () => { expect( ProviderTransform.reasoningVariants(