fix(providers): strip thinking param for minimax-m2.7 on NVIDIA NIM (#6102)

Strip unsupported thinking param for minimax-m2.7 on NVIDIA NIM. Integrated into release/v3.8.44.
This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-07-04 00:37:10 -03:00
committed by GitHub
parent 402d9dea81
commit c900bbb67a
3 changed files with 58 additions and 0 deletions

View File

@@ -23,6 +23,8 @@
### 🔧 Bug Fixes
- **fix(providers):** disable the unsupported `thinking` param for `minimax-m2.7` on NVIDIA NIM (the upstream rejects it). Regression guard: `tests/unit/nvidia-minimax-thinking-strip.test.ts`. (thanks @anki1kr)
- **fix(mitm):** add an in-process guard so concurrent MITM server starts no longer race — a second start while one is already in flight is short-circuited instead of double-binding the listener. Regression guard: `tests/unit/mitm-start-guard.test.ts`. (thanks @anki1kr)
- **translator (Responses → Chat Completions):** strip the Responses-API-only `truncation` field before forwarding a `/v1/responses` request to a non-OpenAI Chat Completions upstream. Strict upstreams (e.g. NVIDIA NIM) rejected it with HTTP 400 `Unsupported parameter(s): truncation`, breaking Codex-style clients routed to those providers. `client_metadata`, `background`, and `safety_identifier` were already stripped — `truncation` was the remaining gap. Regression guard: `tests/unit/responses-strip-truncation-2311.test.ts`. (thanks @TuanNguyen0708)

View File

@@ -29,6 +29,10 @@ const STRIP_RULES: StripRule[] = [
/claude/i.test(m) && !/claude.*(opus|sonnet).*4\.6/i.test(m),
drop: ["thinking", "reasoning_effort"],
},
// NVIDIA NIM minimaxai/minimax-m2.7: NVIDIA's OpenAI-compatible wrapper
// (format:"openai") does not accept the Claude-style `thinking` body field
// and returns 400 "Unsupported parameter(s): thinking". Upstream #2268.
{ provider: "nvidia", match: /minimax-m2\.7/i, drop: ["thinking"] },
];
function matches(rule: StripRule, model: string): boolean {

View File

@@ -0,0 +1,52 @@
// Regression guard: NVIDIA NIM's OpenAI-compatible wrapper (format:"openai")
// does not accept the Claude-style `thinking` body field for
// minimaxai/minimax-m2.7 and returns 400 "Unsupported parameter(s): thinking".
// Upstream #2268 / 9router#2323.
//
// Fix: paramSupport.ts STRIP_RULES drops `thinking` for provider "nvidia" +
// model matching /minimax-m2\.7/i before the request reaches the executor.
import { test } from "node:test";
import assert from "node:assert/strict";
import { stripUnsupportedParams } from "../../open-sse/translator/paramSupport.ts";
test("stripUnsupportedParams: nvidia + minimaxai/minimax-m2.7 drops thinking", () => {
const body: Record<string, unknown> = {
model: "minimaxai/minimax-m2.7",
thinking: { type: "adaptive" },
max_tokens: 512,
temperature: 0.7,
};
stripUnsupportedParams("nvidia", "minimaxai/minimax-m2.7", body);
assert.equal(body.thinking, undefined, "thinking must be stripped for NVIDIA minimax-m2.7");
assert.equal(body.max_tokens, 512, "other params must survive");
assert.equal(body.temperature, 0.7, "other params must survive");
assert.equal(body.model, "minimaxai/minimax-m2.7", "model must not be touched");
});
test("stripUnsupportedParams: nvidia + other model KEEPS thinking (regression guard)", () => {
const body: Record<string, unknown> = { thinking: { type: "adaptive" } };
stripUnsupportedParams("nvidia", "some-other-model", body);
assert.deepEqual(
body.thinking,
{ type: "adaptive" },
"unrelated NVIDIA-hosted models must not be affected"
);
});
test("stripUnsupportedParams: non-nvidia provider KEEPS thinking for minimax-m2.7", () => {
const body: Record<string, unknown> = { thinking: { type: "adaptive" } };
stripUnsupportedParams("minimax", "minimax-m2.7", body);
assert.deepEqual(
body.thinking,
{ type: "adaptive" },
"direct MiniMax API still supports the native thinking field"
);
});
test("stripUnsupportedParams: nvidia + minimax-m2.7 without thinking present is a no-op", () => {
const body: Record<string, unknown> = { max_tokens: 100 };
stripUnsupportedParams("nvidia", "minimaxai/minimax-m2.7", body);
assert.equal(body.max_tokens, 100);
assert.equal("thinking" in body, false);
});