fix(assistant): streaming-render bugs in CLI-backed runs#9
Merged
Conversation
…aragraph-break Claude blocks
Two streaming-rendering bugs surfaced while watching a long Claude Code run
from the workspace view:
1. The workspace polls a snapshot every 5s. `loadSessionData` was
re-creating the session state via `createInitialSessionState`, which
resets `streamingTextByMessageId` to {}. Mid-stream this wiped every
accumulated delta on each tick — text would briefly flash, vanish on
the next 5s boundary, then re-accumulate until the next wipe.
Preserve the in-flight streaming map and `isStreaming` flag across
snapshot loads; both are cleared naturally by completeMessage /
setRunStatus when the run actually terminates.
2. Claude's stream-json splits one assistant message into multiple
content_blocks (text → tool_use → text → ...). Our parser only handled
`content_block_delta` events and concatenated every text fragment
into one string with no separator, so "...PR #6." in one block ran
straight into "Good — PR #6 was merged..." in the next block as a
single paragraph. Now also handle `content_block_start`: when a new
text block opens after existing text content, insert a paragraph
break before its deltas.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #8. Both fixes were originally pushed to `feat/cli-support` after the merge, so neither landed in `main`. Bringing them across.
Summary
Two streaming-rendering bugs surfaced while watching a long Claude Code run from the workspace view:
Disappearing text mid-stream. `Workspace.jsx` polls a snapshot every 5s, which calls `loadSessionData` (`sessionStore.js`). That helper was re-creating the session state via `createInitialSessionState`, which resets `streamingTextByMessageId` to `{}`. Mid-stream this wiped every accumulated delta on each tick — text flashed in, vanished on the next 5s boundary, then re-accumulated until the next wipe. Now `loadSessionData` preserves `streamingTextByMessageId` and `isStreaming` from prior state; both are cleared naturally by `completeMessage` / `setRunStatus` when the run terminates.
No paragraph breaks between Claude content blocks. Claude's stream-json splits one assistant message into multiple `content_block` segments (text → tool_use → text → ...). Our parser in `local_agent.rs::handle_claude_event` only handled `content_block_delta` and `push_str`-ed every text fragment into one string with no separator, so `"...PR test(assistant): add workspace_tasks.rs pure function tests #6."` in one block ran straight into `"Good — PR test(assistant): add workspace_tasks.rs pure function tests #6 was merged..."` from the next block. Now also handle `content_block_start`: when a text block opens after existing text content, insert a paragraph break before its deltas.
Test plan