From b11b39dbceb2f5afc52fd644ce0017cf4ad8dd92 Mon Sep 17 00:00:00 2001 From: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> Date: Thu, 10 Sep 2026 14:41:01 -0300 Subject: [PATCH] fix(providers): minimax-m3 collapses manual thinking.type:enabled to adaptive (#12132) The minimax-m3 modelSpecs entry never received adaptiveThinkingOnly: true (issue #9155 proposed the one-line change but no PR landed it). Both normalizeClaudeAdaptiveThinking() and the explicit thinking.type:"enabled" branch in openai-to-claude.ts gate purely on isAdaptiveThinkingOnly(model), so a manual thinking.type:"enabled" request routed to MiniMax M3 (via either the minimax or minimax-cn provider, since both alias to the same spec entry) was forwarded unchanged and rejected upstream with 400 (2013). Adding adaptiveThinkingOnly: true to the minimax-m3 spec entry closes the gap for every call path (direct, combo, cache-rebuild). --- .../12132-minimax-m3-adaptive-thinking.md | 1 + src/shared/constants/modelSpecs.ts | 4 ++ ...minimax-m3-adaptive-thinking-12132.test.ts | 48 +++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 changelog.d/fixes/12132-minimax-m3-adaptive-thinking.md create mode 100644 tests/unit/minimax-m3-adaptive-thinking-12132.test.ts diff --git a/changelog.d/fixes/12132-minimax-m3-adaptive-thinking.md b/changelog.d/fixes/12132-minimax-m3-adaptive-thinking.md new file mode 100644 index 0000000000..496332561c --- /dev/null +++ b/changelog.d/fixes/12132-minimax-m3-adaptive-thinking.md @@ -0,0 +1 @@ +- fix(providers): minimax-m3 now collapses manual thinking.type:"enabled" to adaptive, preventing upstream 400 (2013) (#12132) diff --git a/src/shared/constants/modelSpecs.ts b/src/shared/constants/modelSpecs.ts index c8b6faaf4b..94da085228 100644 --- a/src/shared/constants/modelSpecs.ts +++ b/src/shared/constants/modelSpecs.ts @@ -680,12 +680,16 @@ export const MODEL_SPECS: Record = { // ── MiniMax M3 (1M context, 512K max output) ───────────────────── // max output verified against MiniMax docs / OpenRouter / Artificial // Analysis (Nov 2025 launch): 1,048,576-token context, up to 512K output. + // Adaptive-thinking-only: MiniMax rejects manual budget_tokens / + // thinking.type:"enabled" with 400 (2013) — "invalid thinking.type: + // \"enabled\" (allowed: adaptive, disabled)" (#12132). "minimax-m3": { maxOutputTokens: 512000, contextWindow: 1048576, thinkingBudgetCap: 32768, supportsThinking: true, supportsTools: true, + adaptiveThinkingOnly: true, aliases: ["MiniMax-M3", "MiniMaxAI/MiniMax-M3"], }, diff --git a/tests/unit/minimax-m3-adaptive-thinking-12132.test.ts b/tests/unit/minimax-m3-adaptive-thinking-12132.test.ts new file mode 100644 index 0000000000..960bf7eb96 --- /dev/null +++ b/tests/unit/minimax-m3-adaptive-thinking-12132.test.ts @@ -0,0 +1,48 @@ +import { test } from "node:test"; +import assert from "node:assert/strict"; +import { isAdaptiveThinkingOnly } from "@/shared/constants/modelSpecs.ts"; +import { normalizeClaudeAdaptiveThinking } from "@omniroute/open-sse/services/claudeAdaptiveThinking.ts"; + +// Issue #12132: MiniMax M3 rejects thinking.type:"enabled" with 400 (2013) +// ("invalid thinking.type: \"enabled\" (allowed: adaptive, disabled)"), but the +// modelSpecs entry for minimax-m3 was never given `adaptiveThinkingOnly: true` +// (the change #9155 proposed and claimed to have landed). Because every +// normalization site that would collapse `enabled` -> `adaptive` gates on +// `isAdaptiveThinkingOnly()`, a manual thinking.type:"enabled" request that +// resolves to MiniMax M3 (via either the `minimax` or `minimax-cn` provider, +// since both alias to the same spec entry) was forwarded unchanged and +// upstream 400s. + +test("minimax-m3 is flagged adaptiveThinkingOnly so manual thinking.type is collapsed", () => { + assert.equal( + isAdaptiveThinkingOnly("minimax-m3"), + true, + "minimax-m3 modelSpec is missing adaptiveThinkingOnly: true" + ); + assert.equal( + isAdaptiveThinkingOnly("MiniMax-M3"), + true, + "MiniMax-M3 alias must resolve to the same adaptive-thinking-only spec" + ); +}); + +test("normalizeClaudeAdaptiveThinking collapses enabled->adaptive for MiniMax M3", () => { + const body = { + thinking: { type: "enabled", budget_tokens: 20000 }, + output_config: { effort: "max" }, + }; + + const result = normalizeClaudeAdaptiveThinking(body, "MiniMax-M3"); + + assert.equal( + (result.thinking as Record).type, + "adaptive", + "thinking.type:\"enabled\" must be collapsed to \"adaptive\" for MiniMax M3, " + + "otherwise upstream rejects it with 400 (2013)" + ); + assert.equal( + (result.thinking as Record).budget_tokens, + undefined, + "budget_tokens must be dropped once thinking is collapsed to adaptive" + ); +});