Runtime: stabilize tool/run state transitions under compaction and backpressure#33826
Runtime: stabilize tool/run state transitions under compaction and backpressure#33826Takhoffman merged 12 commits intomainfrom
Conversation
Fixes #33621 When compaction trims conversation history, some tool_use blocks may lose their corresponding tool_result blocks. This causes Anthropic to reject the history with 'tool_use ids found without tool_result blocks' error. This change adds stripDanglingAnthropicToolUses() which: - Removes tool_use blocks from assistant messages when the following user message doesn't have a matching tool_result (by tool_use_id) - Preserves non-tool content in assistant messages - Inserts '[tool calls omitted]' fallback when all content would be removed
…o prevent blocking (#33570)
Greptile SummaryThis PR stabilizes the runtime state machine for Discord message handler runs and Anthropic tool-call lifecycle by synthesizing fixes from #33630 and #33583. It adds a new shared Key changes:
Confidence Score: 4/5
Last reviewed commit: 3299bd5 |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3299bd5274
ℹ️ 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".
|
Addressed the current review feedback in Fixed items:
Validation rerun:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: eccd84586e
ℹ️ 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".
| // First, strip dangling tool_use blocks from assistant messages | ||
| const stripped = stripDanglingAnthropicToolUses(messages); | ||
|
|
||
| return validateTurnsWithConsecutiveMerge({ | ||
| messages, | ||
| messages: stripped, |
There was a problem hiding this comment.
Merge user turns before stripping assistant toolUse blocks
validateAnthropicTurns currently runs stripDanglingAnthropicToolUses before mergeConsecutiveUserTurns, so it only inspects the immediately following user message when deciding whether a toolUse is dangling. If the matching toolResult sits in a second consecutive user turn (a case the validator is meant to normalize), the tool call is removed anyway, and the later merged user turn still contains that toolResult without a matching tool call, which can produce Anthropic turn-validation failures and lose valid tool context.
Useful? React with 👍 / 👎.
| result.push({ | ||
| ...assistantMsg, | ||
| content: filteredContent, |
There was a problem hiding this comment.
Preserve legacy assistant content when it is not an array
When assistantMsg.content is a legacy non-array value, originalContent is forced to [] and then written back as content: filteredContent, so the validator silently erases the original assistant content whenever the next message is a user turn. This is a regression from previous behavior (which left these messages intact), and it can both drop prompt context and emit empty assistant turns in replayed histories.
Useful? React with 👍 / 👎.
Summary
What changed
busy/activeRuns/heartbeat/deactivation lifecycle handlingtoolUseblocks after compaction/replayRegression coverage
Verification
Provenance