Repository navigation
Conversation
bloodf
pushed a commit
to bloodf/durindoor
that referenced
this pull request
Jul 10, 2026
Translator regression asserting a Claude->OpenAI stream surfaces reasoning via the reasoning channel and never emits literal <think>/</think> text in delta.content. Logic (reasoningDelta channel, no think-tag content deltas) already present in dev; this locks the behavior. Ported from decolua/9router#2190 @ dc417f9b3f
bloodf
pushed a commit
to bloodf/durindoor
that referenced
this pull request
Jul 10, 2026
Translator regression asserting a Claude->OpenAI stream surfaces reasoning via the reasoning channel and never emits literal <think>/</think> text in delta.content. Logic (reasoningDelta channel, no think-tag content deltas) already present in dev; this locks the behavior. Ported from decolua/9router#2190 @ dc417f9b3f
bloodf
pushed a commit
to bloodf/durindoor
that referenced
this pull request
Jul 10, 2026
Translator regression asserting a Claude->OpenAI stream surfaces reasoning via the reasoning channel and never emits literal <think>/</think> text in delta.content. Logic (reasoningDelta channel, no think-tag content deltas) already present in dev; this locks the behavior. Ported from decolua/9router#2190 @ dc417f9b3f
bloodf
added a commit
to bloodf/durindoor
that referenced
this pull request
Jul 10, 2026
* port(upstream): #2237 - salvage orphaned tool results across formats Non-lossy salvageOrphanedToolResults folds orphan tool output into user text (`[Tool result: ...]`) instead of dropping it, across messages[] (OpenAI role:tool, Claude tool_result blocks) and contents[] (Gemini/Antigravity functionResponse). Runs unconditionally in the request pipeline and after each compression stage (RTK/Headroom/PXPIPE) with fixMissingToolResponses to restore the tool-pairing invariant. Responses API function_call_output stays structurally stripped in openai-responses.js. Removes the obsolete shouldStripOrphanedToolResults gate; Gemini-family standalone functionResponse (no functionCall) is preserved. Ported from decolua/9router#2237 @ a32bda9e44 * port(upstream): #2279 - test doubled tool args collapse openai->claude Translator regression asserting the OpenAI->Claude response translator deduplicates doubled JSON tool arguments (same object emitted twice) into a single parseable input_json_delta, and emits message_stop exactly once. Logic (claudeFinishHandled finish guard + deduplicateDoubledJson) already present in dev; this locks the behavior. Ported from decolua/9router#2279 @ 1c9ad466ed * port(upstream): #2190 - test thinking stays out of visible content Translator regression asserting a Claude->OpenAI stream surfaces reasoning via the reasoning channel and never emits literal <think>/</think> text in delta.content. Logic (reasoningDelta channel, no think-tag content deltas) already present in dev; this locks the behavior. Ported from decolua/9router#2190 @ dc417f9b3f * port(upstream): #2318 - test strip Responses-only fields before forward Translator regression asserting Responses->Chat translation drops client_metadata/background/truncation (Responses-API-only fields rejected by third-party chat providers with HTTP 400) while the plain OPENAI->OPENAI path preserves them (negative control). Logic already present in dev; locks behavior. Ported from decolua/9router#2318 @ edb20e143d * fix(translator): skip salvage on native Gemini contents[] restore the Gemini-family (gemini/gemini-cli/antigravity/vertex) guard around salvageOrphanedToolResults in the translateRequest pipeline. the body still carries native contents[] at that point; salvage keys known functionCalls globally and rewrites any functionResponse whose id is not in that set into '[Tool result: ...]' text, dropping legitimate tool results before gemini->openai conversion can read them. fixes CI run 29122517702 (tests/unit/gemini-to-openai-function-response). --------- Co-authored-by: CortexOS <cortexos@localhost>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Fixes a Claude-to-OpenAI streaming translation leak where Claude
thinkingblocks were emitted both as OpenAI-compatiblereasoning_contentand as visiblecontentchunks containing<think>/</think>markers.Root cause
In
open-sse/translator/response/claude-to-openai.js, the Claudethinkingblock lifecycle emitted synthetic OpenAI content chunks:content_block_startforthinkingemitteddelta.content: "<think>"content_block_deltacorrectly emitteddelta.reasoning_contentcontent_block_stopemitteddelta.content: "</think>"This meant OpenAI-compatible clients could receive reasoning markers through normal visible
content, even though the actual thinking text was already carried separately inreasoning_content.Changes
<think>/</think>chunks intodelta.contentfor Claude thinking blocks.thinking_deltamapped todelta.reasoning_content, preserving reasoning for clients/providers that support it.Verification
npx vitest run tests/unit/claude-reasoning-response.test.jsgit diff --checkThe regression test verifies:
contentonly contains the final answer textdelta.contentchunk is<think>or</think>reasoning_contentNotes
There is a separate non-streaming cleanup opportunity around how mixed
content+reasoning_contentresponses are handled, but this PR intentionally keeps the scope limited to the streaming leak reported in #2158.Closes #2158