Skip to content

fix(response): strip reasoning placeholder from all assistant content paths - #8110

Closed
rafaumeu wants to merge 1 commit into
diegosouzapw:release/v3.8.49from
rafaumeu:fix/reasoning-placeholder-leak-8081
Closed

rafaumeu wants to merge 1 commit into
diegosouzapw:release/v3.8.49from
rafaumeu:fix/reasoning-placeholder-leak-8081

Conversation

@rafaumeu

@rafaumeu rafaumeu commented Jul 22, 2026 •

Copy link
Copy Markdown
Contributor

Fix: Reasoning placeholder leaks into message.content (#8081)

Problem

The internal sentinel "(prior reasoning summary unavailable)" is used as a fallback in reasoning fields for non-Anthropic Claude-shape providers that reject redacted_thinking blobs.

Some upstream providers incorrectly emit this sentinel in message.content or streaming delta.content, causing it to leak into the visible response.

Fix

Added stripReasoningPlaceholderFromContent() in responseSanitizer.ts, applied at non-streaming (sanitizeMessageContent) and streaming (sanitizeStreamingChunk) paths.

Handles: bare, case-variations, <think>-wrapped, and "Thinking:" prefixed variants.

Safety

  • Placeholder preserved in reasoning_content / reasoning fields
  • Only message.content and delta.content are cleaned
  • collapseExcessiveNewlines() runs after strip to prevent artifacts

Tests

9 new tests covering all variants. All 52 existing tests still pass.

Closes #8081

@rafaumeu
rafaumeu requested a review from diegosouzapw as a code owner July 22, 2026 10:57
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

…diegosouzapw#8081)

The internal sentinel '(prior reasoning summary unavailable)' is used as
a fallback in reasoning fields for non-Anthropic Claude-shape providers.

Some upstream providers incorrectly emit it in message.content or
streaming delta.content, causing it to leak into visible response.

Fix: stripReasoningPlaceholderFromContent() in responseSanitizer.ts,
applied at both non-streaming (sanitizeMessageContent) and streaming
(sanitizeStreamingChunk) paths. Handles bare, case-varied,
<think>-wrapped, and 'Thinking:' prefixed variants.

Placeholder is preserved in reasoning_content/reasoning fields.
Tests: 9 new tests covering all variants + regression safety.
@rafaumeu
rafaumeu force-pushed the fix/reasoning-placeholder-leak-8081 branch from d7a3917 to 6cdcc7a Compare July 22, 2026 18:55
@rafaumeu
rafaumeu changed the base branch from main to release/v3.8.49 July 22, 2026 18:55
@rafaumeu

Copy link
Copy Markdown
Contributor Author

Rebased against release/v3.8.49 — single isolated commit, no bundled history. Ready for review.

@diegosouzapw

Copy link
Copy Markdown
Owner

Obrigado pela contribuição, @rafaumeu. Para o #8081 (strip do reasoning placeholder) vamos seguir com o #8162 (@Dingding-leo), que é focado exclusivamente nesse bug e cobre os 4 call sites de tradução — enquanto este PR vem agrupado com mudanças de #8072 e #8059 e cobre um subconjunto. Fechando este em favor do #8162 (que estamos finalizando com a correção dos guards de finish_reason/tool_calls). Se identificar um caminho que o #8162 não cobra, reabra focado só nesse gap que integramos com crédito.

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.

fix(backend): internal reasoning-replay placeholder leaks into assistant message content

2 participants