- Revert hasCompletedToolPhase to simple check (segmentHasTools only).
The lastAssistantHasNoTools guard was too restrictive: during reply
streaming the last assistant in history still has tool_use (reply only
exists in streamingMessage). The intermediate-narration edge case is
already handled by stripProcessMessagePrefix producing empty
trimmedReplyText, causing graceful fallback to buildSteps(false).
- Fix stale graph cache: filter out stream-generated message steps
(id prefix 'stream-message') instead of brittle exact-match. These
steps contain accumulated narration+reply text from streaming phase
that should not persist after completion.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- hasCompletedToolPhase now checks that the last assistant message in the
segment has no tool_use blocks, preventing false positives during
intermediate tool rounds that would suppress the trailing thinking indicator
- Filter reply text from cached graph steps when a completed run falls
back to the step cache, preventing the final response from appearing
inside the graph when expanding after completion
- Remove debug logging
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Gateway history contains `role: 'user'` messages that are actually
tool-result wrappers (Anthropic API format). These were incorrectly
treated as run boundaries in nextUserMessageIndexes, causing:
- isLatestOpenRun=false during tool execution → graph collapses
- Run split into multiple segments → incorrect step attribution
Add isRealUserMessage() that detects tool-result wrappers by checking
if all content blocks are type 'tool_result', and use it in both
nextUserMessageIndexes computation and userRunCards filtering.
Also remove debug logging from previous iterations.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Prevent execution graph from auto-collapsing while reply is still
streaming by excluding from autoCollapsedRunKeys and keeping
expanded=true via controlled prop
- Strip thinking blocks from the streaming ChatMessage when the reply
renders as a separate bubble, so thinking content doesn't duplicate
alongside the response text
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>