refactor: eliminate streamingContent state, inline assistant messages - #75
Merged
Conversation
Move streaming content directly into messages array instead of maintaining separate streamingContent state. Assistant placeholder added immediately on ask(), tokens update the last message in-place, eliminating the component swap (unmount/remount) that caused re-renders when streaming finished. Copy button now hidden during streaming, appears only after done. Fixes: text component re-rendering after streaming completes Approach 1: single source of truth (one message array) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
…JSDoc - Add !isGenerating guard to canSave logic to prevent Save button appearing mid-stream - Fix stale JSDoc on ask() that claimed code avoids array copies (it now does the opposite) - Prevents user from saving incomplete conversations during active generation Fixes code review issues from PR #75 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
Add isGenerating to auto-scroll effect dependency array so viewport scrolls to bottom when copy button appears after streaming finishes. Prevents button from being cut off below the fold. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
quiet-node
added a commit
that referenced
this pull request
Apr 10, 2026
…#75) * refactor: eliminate streamingContent state, inline assistant messages Move streaming content directly into messages array instead of maintaining separate streamingContent state. Assistant placeholder added immediately on ask(), tokens update the last message in-place, eliminating the component swap (unmount/remount) that caused re-renders when streaming finished. Copy button now hidden during streaming, appears only after done. Fixes: text component re-rendering after streaming completes Approach 1: single source of truth (one message array) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com> * fix: guard canSave against empty assistant placeholder, update stale JSDoc - Add !isGenerating guard to canSave logic to prevent Save button appearing mid-stream - Fix stale JSDoc on ask() that claimed code avoids array copies (it now does the opposite) - Prevents user from saving incomplete conversations during active generation Fixes code review issues from PR #75 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com> * fix: auto-scroll when streaming ends to reveal copy button Add isGenerating to auto-scroll effect dependency array so viewport scrolls to bottom when copy button appears after streaming finishes. Prevents button from being cut off below the fold. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com> --------- Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
quiet-node
added a commit
that referenced
this pull request
Apr 10, 2026
…#75) * refactor: eliminate streamingContent state, inline assistant messages Move streaming content directly into messages array instead of maintaining separate streamingContent state. Assistant placeholder added immediately on ask(), tokens update the last message in-place, eliminating the component swap (unmount/remount) that caused re-renders when streaming finished. Copy button now hidden during streaming, appears only after done. Fixes: text component re-rendering after streaming completes Approach 1: single source of truth (one message array) Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com> * fix: guard canSave against empty assistant placeholder, update stale JSDoc - Add !isGenerating guard to canSave logic to prevent Save button appearing mid-stream - Fix stale JSDoc on ask() that claimed code avoids array copies (it now does the opposite) - Prevents user from saving incomplete conversations during active generation Fixes code review issues from PR #75 Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com> * fix: auto-scroll when streaming ends to reveal copy button Add isGenerating to auto-scroll effect dependency array so viewport scrolls to bottom when copy button appears after streaming finishes. Prevents button from being cut off below the fold. Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com> --------- Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
quiet-node
added a commit
that referenced
this pull request
Apr 11, 2026
…#75) * refactor: eliminate streamingContent state, inline assistant messages Move streaming content directly into messages array instead of maintaining separate streamingContent state. Assistant placeholder added immediately on ask(), tokens update the last message in-place, eliminating the component swap (unmount/remount) that caused re-renders when streaming finished. Copy button now hidden during streaming, appears only after done. Fixes: text component re-rendering after streaming completes Approach 1: single source of truth (one message array) Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com> * fix: guard canSave against empty assistant placeholder, update stale JSDoc - Add !isGenerating guard to canSave logic to prevent Save button appearing mid-stream - Fix stale JSDoc on ask() that claimed code avoids array copies (it now does the opposite) - Prevents user from saving incomplete conversations during active generation Fixes code review issues from PR #75 Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com> * fix: auto-scroll when streaming ends to reveal copy button Add isGenerating to auto-scroll effect dependency array so viewport scrolls to bottom when copy button appears after streaming finishes. Prevents button from being cut off below the fold. Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com> --------- Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
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.
Summary
streamingContentstate; tokens now update the assistant message in-placeTechnical Details
Old flow: During streaming, content lived in
streamingContentstate in a separate bubble (key="streaming"). On Done, that bubble unmounted and a new one mounted frommessages. The Streamdown renderer mode switched from "streaming" to "static", causing a re-parse and visible re-render.New flow: When
ask()is called, both user + empty assistant message are added tomessages. Tokens update the last message in-place viamap(). On Done,isGeneratingflips to false. Same component instance, no mode change, no re-render.Test Updates
Validation
✓ All 463 tests pass
✓ Lint + format + typecheck all pass
✓ Production build succeeds