fix(translator): strip reasoning param for nvidia z-ai/glm-5.2 (#6181)

* fix(translator): strip reasoning param for nvidia z-ai/glm-5.2

NVIDIA NIM OpenAI-compatible wrapper rejects the reasoning body field
and returns HTTP 400 "Unsupported parameter(s): `reasoning`".
Add a StripRule scoped to provider=nvidia + model /z-ai\/glm-5\.2/i.
Mirrors PR #6102 drop pattern (minimax-m2.7 thinking).

* docs(translator): tighten nvidia glm-5.2 strip-rule comment

* fix(translator): anchor glm-5.2 strip rule with word boundary
This commit is contained in:
Danny S
2026-07-05 13:29:59 +08:00
committed by GitHub
parent 6816bcdaf3
commit 6a12ba07b1
2 changed files with 45 additions and 0 deletions

View File

@@ -29,6 +29,9 @@ const STRIP_RULES: StripRule[] = [
/claude/i.test(m) && !/claude.*(opus|sonnet).*4\.6/i.test(m),
drop: ["thinking", "reasoning_effort"],
},
// NVIDIA NIM z-ai/glm-5.2: OpenAI-compatible wrapper rejects the `reasoning`
// body field → HTTP 400 "Unsupported parameter(s): `reasoning`". #6102 drop pattern.
{ provider: "nvidia", match: /z-ai\/glm-5\.2\b/i, drop: ["reasoning"] },
// 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.

View File

@@ -5,6 +5,7 @@
// 1. claude-opus-4 series: temperature deprecated → Anthropic 400.
// 2. github + gpt-5.4: temperature unsupported.
// 3. github + Claude (except opus/sonnet 4.6): thinking + reasoning_effort rejected.
// 4. nvidia + z-ai/glm-5.2: reasoning rejected → NVIDIA 400.
import { test } from "node:test";
import assert from "node:assert/strict";
@@ -112,6 +113,47 @@ test("stripUnsupportedParams: missing model is a no-op", () => {
assert.equal(body.temperature, 0.7);
});
test("stripUnsupportedParams: drops reasoning for nvidia z-ai/glm-5.2", () => {
const body: Record<string, unknown> = {
model: "z-ai/glm-5.2",
reasoning: { effort: "high" },
temperature: 0.7,
};
stripUnsupportedParams("nvidia", "z-ai/glm-5.2", body);
assert.equal(body.reasoning, undefined, "reasoning must be stripped");
assert.equal(body.temperature, 0.7, "other params must survive");
assert.equal(body.model, "z-ai/glm-5.2", "model must not be touched");
});
test("stripUnsupportedParams: nvidia z-ai/glm-5.1 keeps reasoning (rule is 5.2-only)", () => {
const body: Record<string, unknown> = {
model: "z-ai/glm-5.1",
reasoning: { effort: "medium" },
max_tokens: 100,
};
stripUnsupportedParams("nvidia", "z-ai/glm-5.1", body);
assert.ok(body.reasoning !== undefined, "reasoning must survive for glm-5.1");
assert.equal(body.max_tokens, 100, "other params must survive");
});
test("stripUnsupportedParams: nvidia glm-5 rule is provider-scoped (no-op for other providers)", () => {
const body: Record<string, unknown> = {
model: "z-ai/glm-5.2",
reasoning: { effort: "high" },
};
stripUnsupportedParams("openai", "z-ai/glm-5.2", body);
assert.ok(body.reasoning !== undefined, "reasoning must survive for non-nvidia provider");
});
test("stripUnsupportedParams: nvidia non-glm-5 model keeps reasoning", () => {
const body: Record<string, unknown> = {
model: "deepseek-ai/deepseek-v4-pro",
reasoning: { effort: "high" },
};
stripUnsupportedParams("nvidia", "deepseek-ai/deepseek-v4-pro", body);
assert.ok(body.reasoning !== undefined, "reasoning must survive for non-glm-5 nvidia model");
});
test("STRIP_RULES is non-empty and every rule has a drop list", () => {
assert.ok(__STRIP_RULES_FOR_TEST.length > 0);
for (const rule of __STRIP_RULES_FOR_TEST) {