- Bump version in package.json to 0.3.10-beta.4.
- Add a new GitHub Actions job to validate that the version in package.json matches the release tag.
- Introduce scripts for versioning and release validation to streamline the release process.
Eliminate the phase completion timer and its associated logic from the Gateway. The handling of run completion is now solely based on Gateway phase events and streaming final events. This change simplifies the code and ensures that the state transitions are more reliable, as run completion is no longer inferred from the timer.
Additionally, update the runtime send actions to finalize the sending state immediately after the chat.send RPC completes, ensuring accurate state management during agent conversations.
The Gateway sends phase "end" after each tool-execution round (sub-run),
not just when the entire conversation finishes. This caused sending=false
between tool rounds, breaking the thinking indicator and input state.
Add a 5-second grace timer: on phase "end", delay sending=false. If a
new streaming event, "started" phase, or chat data arrives within the
window, the timer is cancelled and sending stays true. Only if the
grace period expires with no new activity does the run finalize.
Also: remove loadHistory finalize logic entirely — run completion is
now handled exclusively by Gateway phase events (with grace) and
streaming final events.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
loadHistory repeatedly set sending=false during server-side tool execution
by incorrectly inferring run completion from message content.
Run completion is now ONLY signalled by:
1. Gateway's phase 'completed' event (gateway.ts)
2. Streaming 'final' event (runtime-event-handlers.ts)
3. Safety timeout after 90s of no events
Also: fully controlled graph expanded prop, stable key, card.active
decoupled from streamingReplyText, suppressThinking prop.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 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>