diff --git a/packages/opencode/src/provider/transform.ts b/packages/opencode/src/provider/transform.ts index f0a47d8b0e..26c7d80ff0 100644 --- a/packages/opencode/src/provider/transform.ts +++ b/packages/opencode/src/provider/transform.ts @@ -682,6 +682,30 @@ function googleThinkingVariants(model: Provider.Model): Record> { if (!model.capabilities.reasoning) return {} @@ -689,15 +713,8 @@ export function variants(model: Provider.Model): Record id.includes(name) || model.api.id.toLowerCase().includes(name), ) - if ( - model.api.id.toLowerCase().includes("minimax-m3") && - ["@ai-sdk/anthropic", "@ai-sdk/openai-compatible"].includes(model.api.npm) - ) { - return { - none: { thinking: { type: "disabled" } }, - thinking: { thinking: { type: "adaptive" } }, - } - } + const minimaxM3 = minimaxM3ThinkingVariants(model) + if (minimaxM3) return minimaxM3 const adaptiveThinkingOmitted = anthropicOmitsThinking(model.api.id) const adaptiveEfforts = anthropicAdaptiveEfforts(model.api.id) if (glm52 && model.api.npm === "@openrouter/ai-sdk-provider") { @@ -1652,6 +1669,8 @@ function nonEmptyVariants(variants: NonNullable): Pr } function reasoningToggle(model: Provider.Model): NonNullable { + const minimaxM3 = minimaxM3ThinkingVariants(model) + if (minimaxM3) return minimaxM3 if (model.api.npm === "@ai-sdk/alibaba") return { none: { enableThinking: false }, diff --git a/packages/opencode/test/provider/transform.test.ts b/packages/opencode/test/provider/transform.test.ts index 0c478ad812..22d030ba5a 100644 --- a/packages/opencode/test/provider/transform.test.ts +++ b/packages/opencode/test/provider/transform.test.ts @@ -3077,10 +3077,10 @@ 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") => + const target = (npm: string, id = "test-model", providerID = "test") => ({ id, - providerID: "test", + providerID, api: { id, npm, url: "" }, capabilities: { reasoning: true }, limit: { output: 64_000 }, @@ -3253,6 +3253,61 @@ describe("ProviderTransform.reasoningVariants", () => { expect(ProviderTransform.reasoningVariants(model([{ type: "toggle" }]), target(npm))).toEqual(expected) }) + test.each([ + [ + "minimax", + "@ai-sdk/anthropic", + { + none: { thinking: { type: "disabled" } }, + thinking: { thinking: { type: "adaptive" } }, + }, + ], + [ + "crossmodel", + "@ai-sdk/openai-compatible", + { + none: { thinking: { type: "disabled" } }, + thinking: { thinking: { type: "adaptive" } }, + }, + ], + [ + "nvidia", + "@ai-sdk/openai-compatible", + { + none: { chat_template_kwargs: { thinking_mode: "disabled" } }, + thinking: { chat_template_kwargs: { thinking_mode: "enabled" } }, + }, + ], + [ + "lilac", + "@ai-sdk/openai-compatible", + { + none: { chat_template_kwargs: { thinking_mode: "disabled" } }, + thinking: { chat_template_kwargs: { thinking_mode: "enabled" } }, + }, + ], + [ + "kilo", + "@ai-sdk/openai-compatible", + { + none: { reasoning: { enabled: false } }, + thinking: { reasoning: { enabled: true } }, + }, + ], + [ + "vercel", + "@ai-sdk/gateway", + { + none: { reasoning: { enabled: false } }, + thinking: { reasoning: { enabled: true } }, + }, + ], + ])("maps MiniMax M3 toggle options for %s", (providerID, npm, expected) => { + expect( + ProviderTransform.reasoningVariants(model([{ type: "toggle" }]), target(npm, "minimaxai/minimax-m3", providerID)), + ).toEqual(expected) + }) + test("combines Cohere toggle and budget options", () => { expect( ProviderTransform.reasoningVariants( @@ -3468,6 +3523,22 @@ describe("ProviderTransform.variants", () => { }) }) + test("nvidia minimax m3 uses chat template thinking toggles", () => { + const model = createMockModel({ + id: "nvidia/minimaxai/minimax-m3", + providerID: "nvidia", + api: { + id: "minimaxai/minimax-m3", + url: "https://integrate.api.nvidia.com/v1", + npm: "@ai-sdk/openai-compatible", + }, + }) + expect(ProviderTransform.variants(model)).toEqual({ + none: { chat_template_kwargs: { thinking_mode: "disabled" } }, + thinking: { chat_template_kwargs: { thinking_mode: "enabled" } }, + }) + }) + test("glm returns empty object", () => { const model = createMockModel({ id: "glm/glm-4",