Skip to content

fix(translator): drop unsigned reasoning on Claude output - #12917

Merged
diegosouzapw merged 6 commits into
diegosouzapw:release/v3.8.52from
atescivitci-cmd:fix/tracker-44-thinking-signature
Oct 2, 2026
Merged

diegosouzapw merged 6 commits into
diegosouzapw:release/v3.8.52from
atescivitci-cmd:fix/tracker-44-thinking-signature

Conversation

@atescivitci-cmd

Copy link
Copy Markdown
Contributor

Summary

  • stop converting non-Anthropic OpenAI-compatible reasoning_content into Claude thinking blocks
  • apply the same suppression to the non-streaming OpenAI chat-completion to Claude conversion path
  • update response translator regression tests to assert unsigned reasoning is not emitted as Claude thinking
  • prune now-stale ESLint suppression count for the changed test file

Why

thinking blocks sent back to Anthropic must carry Anthropic-valid signatures. Reasoning fields from OpenAI-compatible providers do not have those signatures, so translating them into Claude thinking creates replay history that Anthropic rejects with Invalid signature in thinking block.

Validation

  • node --import tsx/esm --test tests/unit/translator-resp-openai-to-claude.test.ts
  • node --import tsx/esm --test tests/unit/translator-openai-to-claude.test.ts
  • npx eslint open-sse/handlers/responseTranslator.ts open-sse/translator/response/openai-to-claude.ts tests/unit/translator-resp-openai-to-claude.test.ts --cache --cache-location .eslintcache --suppressions-location config/quality/eslint-suppressions.json
  • npm run typecheck:core -- --pretty false

⚠️ base-red inherited: #12732

@diegosouzapw

Copy link
Copy Markdown
Owner

Clean, well-reasoned fix — dropping unsigned reasoning instead of laundering it into visible
text is the right call (avoids both the Anthropic signature-replay error and a chain-of-thought
privacy leak), and it's applied consistently to both the streaming and non-streaming paths. Ran
translator-resp-openai-to-claude.test.ts at your head — 13/13 pass.
One heads-up for coordination: #12905 touches the exact same code region
(openai-to-claude.ts:300-333, per its own PR description) with a different, gated approach —
git merge-tree confirms a real conflict across 3 files including the shared test. Flagging
this for the maintainer's merge-order decision, not a blocker on your side. Only ask: add a
changelog.d/fixes/ fragment.

@diegosouzapw diegosouzapw changed the title fix(translator): drop unsigned reasoning on Claude output [defer] fix(translator): drop unsigned reasoning on Claude output Sep 29, 2026
@diegosouzapw diegosouzapw added the deferred-v3.8.52 Grande demais / suspeito para o lote atual; precisa de sessão dedicada no ciclo v3.8.52 label Sep 29, 2026
@diegosouzapw
diegosouzapw changed the base branch from release/v3.8.51 to release/v3.8.52 September 29, 2026 11:27
@diegosouzapw

Copy link
Copy Markdown
Owner

Re-homed to release/v3.8.52: v3.8.51 entered its release freeze, so the branch now belongs to the release captain and development continues on the next cycle. Nothing is wrong with this PR — it just needed a live base. No action needed from you; CI will re-run against the new base.

atescivitci-cmd and others added 3 commits September 29, 2026 19:06
Rescope per owner decision: the response-side translators keep the tip's
deliberate policy (relay reasoning as thinking unless the client opted out),
so the response-side edits of this branch are dropped in favor of the tip's
versions. The signature-replay fix moves to the request path toward Anthropic.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
Assistant thinking/redacted_thinking blocks with no signature/data (reasoning
relayed from a non-Anthropic leg) can only be rejected by api.anthropic.com
with "Invalid signature in thinking block". Drop them on the Claude passthrough
request path (provider claude); signed blocks are forwarded verbatim.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
…ough helper

Keeps chatCore.ts within its frozen file-size ceiling.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings September 29, 2026 22:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Open tool-use cycles can still reach Anthropic without the required thinking precursor, and the PR description does not match the current diff.

Review effort: Balanced
Findings: 1 Medium severity · 1 Low severity

Open (2)
What changed in this PR

Adds Claude passthrough sanitization to prevent unsigned thinking blocks from being replayed to Anthropic.

Changes:

  • Removes unsigned thinking history while preserving signed blocks.
  • Adds unit and passthrough regression coverage.
  • Adds a changelog fragment.

Validation: Commands run: none. Changed test: tests/unit/claude-passthrough-unsigned-thinking-12917.test.ts. Coverage: not provided.

File Description
open-sse/​handlers/​chatCore/​passthroughHelpers.ts Filters unsigned thinking blocks.
tests/​unit/​claude-passthrough-unsigned-thinking-12917.test.ts Tests helper and passthrough behavior.
changelog.d/​fixes/​12917-drop-unsigned-reasoning-claude-output.md Documents the fix.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +220 to +222
changed = true;
const content = message.content.filter((block) => !isUnsignedThinkingBlock(block));
if (content.length > 0) kept.push({ ...message, content });
@@ -0,0 +1 @@
- **fix(claude):** drop assistant `thinking` / `redacted_thinking` blocks that carry no signature from the history before it is replayed to the genuine Anthropic upstream (Claude passthrough), so reasoning relayed from an OpenAI-compatible leg no longer triggers `Invalid signature in thinking block` on the next turn — signed blocks are forwarded untouched ([#12917](https://github.com/diegosouzapw/OmniRoute/pull/12917)) — thanks @atescivitci-cmd
@diegosouzapw diegosouzapw removed the deferred-v3.8.52 Grande demais / suspeito para o lote atual; precisa de sessão dedicada no ciclo v3.8.52 label Oct 1, 2026
@diegosouzapw diegosouzapw changed the title [defer] fix(translator): drop unsigned reasoning on Claude output fix(translator): drop unsigned reasoning on Claude output Oct 1, 2026
@diegosouzapw
diegosouzapw merged commit 87a7534 into diegosouzapw:release/v3.8.52 Oct 2, 2026
3 checks passed
@diegosouzapw

Copy link
Copy Markdown
Owner

Thanks @atescivitci-cmd — merged into release/v3.8.52; it ships in the next release.

@atescivitci-cmd
atescivitci-cmd deleted the fix/tracker-44-thinking-signature branch October 5, 2026 02:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants