Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
- **oauth:** repair native Google loopback callback flow and support remote callbacks via state matching on 127.0.0.1 (#2796 — thanks @akarray)
- **combos:** fix combo handling so transient 429 rate limit errors do not poison or persist the rate limited state for the same-provider connection (#2800 — thanks @apoapostolov)
- **gemini:** translate signature-less Gemini thinking model tool calls to text parts to prevent `400 "missing thought_signature"` errors (#2801 — thanks @herjarsa)
- **translator:** strip `safety_identifier` from `/v1/responses` body before forwarding to Chat Completions upstream; fixes LobeHub-originated `400` errors (#2770)
- **warning-cleanup:** relax node engine constraint to `>=22.0.0` and clean dependencies (keeping `marked-terminal` to prevent TUI REPL crash) (#2792 — thanks @oyi77)

### 🧹 Chores
Expand Down
3 changes: 3 additions & 0 deletions open-sse/translator/request/openai-responses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,9 @@ export function openaiResponsesToOpenAIRequest(
}
}
delete result.reasoning;
// Strip Responses-API-only fields that Chat Completions rejects with 400.
// safety_identifier is sent by LobeHub and has no Chat Completions equivalent (#2770).
delete result.safety_identifier;

return result;
}
Expand Down
17 changes: 17 additions & 0 deletions tests/unit/translator-openai-responses-req.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,23 @@ test("Responses -> Chat passes through when background flag is unset or false (n
}
});

test("Responses -> Chat strips safety_identifier (LobeHub #2770)", () => {
// LobeHub sends safety_identifier in Responses API bodies. Chat Completions rejects it
// with HTTP 400. The translator must strip it in the Responses-API cleanup block.
const result = openaiResponsesToOpenAIRequest(
"gpt-4o",
{
input: [{ role: "user", content: [{ type: "input_text", text: "hi" }] }],
safety_identifier: "sid-xyz",
},
false,
null
) as Record<string, unknown>;

assert.equal(result.safety_identifier, undefined, "safety_identifier must be stripped before forwarding to Chat Completions");
assert.ok(Array.isArray(result.messages), "translation must still produce messages");
});

test("Chat -> Responses converts messages, tool calls, tool outputs, tools and pass-through params", () => {
const result = openaiToOpenAIResponsesRequest(
"gpt-4o",
Expand Down