fix(translator): strip Responses-only truncation field before Chat Completions forwarding (#6109)

Strip Responses-only truncation field before Chat Completions forwarding (#2311). Integrated into release/v3.8.44.
This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-07-04 00:30:04 -03:00
committed by GitHub
parent d8e4eeef5d
commit d927f2d31f
3 changed files with 50 additions and 0 deletions

View File

@@ -22,6 +22,8 @@
### 🔧 Bug Fixes
- **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)
- **combo (prefer known context capacity over unknown):** when a combo filters out at least one target for exceeding a *known* context limit, the router now prefers the remaining known-compatible targets over targets whose context metadata is simply unknown, instead of letting unknown-metadata targets be the only survivors. If no known-compatible context target remains, context-only candidates fall back to the normal strategy order. Regression guard: `tests/unit/combo-context-window-filter.test.ts`. ([#6088](https://github.com/diegosouzapw/OmniRoute/pull/6088) — thanks @Thinkscape)
- **models (GLM-5.2 context normalization):** stop treating every hosted GLM-5.2 provider alias as the native 1M-context model. Native/bare GLM-5.2 and verified OpenCode / ZenMux routes keep their 1,000,000-token context, while hosted-provider aliases now respect the caps declared in their provider metadata instead of inheriting the native max. Regression guards: `tests/unit/model-capabilities-registry.test.ts`, `tests/unit/models-catalog-route.test.ts`. ([#6091](https://github.com/diegosouzapw/OmniRoute/pull/6091) — thanks @Thinkscape)

View File

@@ -520,6 +520,10 @@ export function openaiResponsesToOpenAIRequest(
// client_metadata is sent by Codex CLI and has no Chat Completions equivalent.
// Strict upstreams (e.g. Mistral) reject it with HTTP 422 extra_forbidden.
delete result.client_metadata;
// truncation ("auto"/"disabled") is a Responses-API-only field with no Chat
// Completions equivalent. Strict non-OpenAI upstreams (e.g. NVIDIA NIM) reject
// it with HTTP 400 "Unsupported parameter(s): truncation" (#2311).
delete result.truncation;
return result;
}

View File

@@ -0,0 +1,44 @@
import test from "node:test";
import assert from "node:assert/strict";
// Regression for port of decolua/9router#2311 (PR #2318): OpenAI Responses-API-only
// fields must be stripped before forwarding to a Chat Completions upstream, otherwise
// strict non-OpenAI upstreams (e.g. NVIDIA NIM) reject with HTTP 400
// "Unsupported parameter(s): ...". OmniRoute already strips `client_metadata`,
// `background`, and `safety_identifier`; `truncation` was the remaining gap.
const { openaiResponsesToOpenAIRequest } = await import(
"../../open-sse/translator/request/openai-responses.ts"
);
test("Responses -> OpenAI: truncation is stripped (never forwarded to Chat Completions)", () => {
const result = openaiResponsesToOpenAIRequest(
"z-ai/glm-5.2",
{
input: [{ type: "message", role: "user", content: [{ type: "input_text", text: "hi" }] }],
truncation: "auto",
},
false,
{}
) as Record<string, unknown>;
assert.equal("truncation" in result, false);
});
test("Responses -> OpenAI: full Responses-only field set is stripped together", () => {
const result = openaiResponsesToOpenAIRequest(
"z-ai/glm-5.2",
{
input: [{ type: "message", role: "user", content: [{ type: "input_text", text: "hi" }] }],
truncation: "disabled",
client_metadata: { user_id: "abc" },
background: true,
safety_identifier: "lobehub-user",
},
false,
{}
) as Record<string, unknown>;
for (const field of ["truncation", "client_metadata", "background", "safety_identifier"]) {
assert.equal(field in result, false, `${field} should be stripped`);
}
});