fix: group parallel tool results in stream retry replay (#3072)
## Summary
- Fixes #3070 (and likely related to #2879)
- When retrying after a transient stream termination, parallel tool-call
results were split into separate `tool` messages instead of being
grouped. This violated the Anthropic API constraint that every
`tool_use` in an assistant message must have its `tool_result` in the
immediately following message, causing `400 invalid_request_error`.
- Extracted replay logic from `local_agent_handler.ts` into
`retry_replay_utils.ts` for testability, and fixed
`buildRetryReplayMessages` to merge consecutive tool-result entries into
a single tool message.
## Test plan
- [x] Added 18 new tests in `retry_replay_utils.test.ts` covering:
- Parallel tool results grouped into single message (the core fix)
- Sequential + parallel mixed scenarios
- Incomplete tool exchanges excluded
- Event capture deduplication
- Edge cases (empty events, whitespace text, null inputs)
- [x] All 18 existing `local_agent_handler.test.ts` tests still pass
(including stream retry tests)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- devin-review-badge-begin -->
---
<a href="https://app.devin.ai/review/dyad-sh/dyad/pull/3072"
target="_blank">
<picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1">
<img
src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1"
alt="Open with Devin">
</picture>
</a>
<!-- devin-review-badge-end -->
---------
Co-authored-by:
Will Chen <7344640+wwwillchen@users.noreply.github.com>
Co-authored-by:
Claude Opus 4.6 (1M context) <noreply@anthropic.com>
正在显示
差异被折叠。
请
注册
或者
登录
后发表评论