fix(agents): preserve thinking/redacted_thinking blocks in session history#44827
fix(agents): preserve thinking/redacted_thinking blocks in session history#44827a-alphayed wants to merge 5 commits intoopenclaw:mainfrom
Conversation
Greptile SummaryThis PR fixes a bug where multi-turn conversations with Anthropic's extended thinking feature would fail on replay because four sanitization functions in the session history pipeline were mutating The fix introduces a shared Key points:
Confidence Score: 5/5
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b9acea5c19
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
1363e24 to
897a2b8
Compare
…story sanitization The Anthropic API requires thinking and redacted_thinking blocks to be returned byte-for-byte identical in conversation history. Multiple sanitization functions were mutating these blocks via object spread and field deletion, causing API rejections with: "thinking or redacted_thinking blocks in the latest assistant message cannot be modified." Add isImmutableThinkingBlock() guard and apply it in all four mutation sites: - stripThoughtSignatures (bootstrap.ts) — was deleting signature fields - sanitizeToolResult (pi-embedded-subscribe.tools.ts) — was deleting .data - pruneProcessedHistoryImages (history-image-prune.ts) — was replacing blocks - dropThinkingBlocks (thinking.ts) — was missing redacted_thinking type Fixes openclaw#29618 Supersedes openclaw#29620 Co-Authored-By: Claude Opus 4.6 <[email protected]>
Co-Authored-By: Claude Opus 4.6 <[email protected]>
The isImmutableThinkingBlock guard in stripThoughtSignatures was preventing signature stripping on non-Anthropic paths (Gemini), where thought_signature fields must be removed before replaying history. The existing early-return (!stripSnake && !stripCamel) already handles the no-op case correctly. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
897a2b8 to
7c1d603
Compare
Summary
thinkingandredacted_thinkingblocks in assistant messages to be returned byte-for-byte identical when replayed in conversation historyisImmutableThinkingBlock()guard and applies it across all four mutation sites, not juststripThoughtSignaturesRoot Cause
Four functions in the sanitization pipeline modify content blocks before sending them back to the Anthropic API:
stripThoughtSignaturespi-embedded-helpers/bootstrap.tsthought_signaturefieldssanitizeToolResultpi-embedded-subscribe.tools.ts.datafield (breaksredacted_thinkingencrypted payload)pruneProcessedHistoryImagespi-embedded-runner/run/history-image-prune.tsdropThinkingBlockspi-embedded-runner/thinking.tstype === "thinking", missedredacted_thinkingFix
isImmutableThinkingBlock(block)returnstrueforthinkingandredacted_thinkingtypesdropThinkingBlocksnow also handlesredacted_thinkingblocksReproduction
sanitizeSessionHistorypipeline"thinking or redacted_thinking blocks in the latest assistant message cannot be modified. These blocks must remain as they were in the original response."Test plan
isImmutableThinkingBlockguard (5 cases)dropThinkingBlockswithredacted_thinkingblocksFixes #29618
Supersedes #29620
🤖 Generated with Claude Code