fix(tui): restore auto-scroll during streaming#506
Closed
avoidwork wants to merge 4 commits into
Closed
Conversation
The refactoring in 6a89549 extracted createStreamingHandler and finalizeStreaming but accidentally removed the setMessages() calls that trigger React re-renders. Without setMessages, the messages state never updates, so the scroll effect in conversationPanel.js never fires. Added setMessages(cloned) to both createStreamingHandler and finalizeStreaming to restore the re-render pipeline.
The refactoring in 6a89549 extracted createStreamingHandler and finalizeStreaming but removed the setMessages() calls that triggered re-renders. Restoring setMessages defeats the useRef optimization that was the whole point of the refactor. Instead, trigger scroll-to-bottom from the setInterval that already drives the render tick — it reads messagesRef.current each frame and can check streaming state without any state churn.
The refactoring in 6a89549 extracted createStreamingHandler and finalizeStreaming but removed the setMessages() calls. The handlers now mutate messagesRef.current directly, but without a state update React never re-renders and the scroll effect never fires. Adding setMessages() in the streaming handlers defeats the useRef optimization. Instead, call setMessages(messagesRef.current) from the existing setInterval that already drives the render tick — this keeps the 30fps cadence, creates a new array reference each frame so the scroll effect detects changes, and avoids per-event state churn.
Replace the messages-state-dependent scroll effect with ScrollView's onContentHeightChange callback. The previous approach tracked message count and streaming content hash, but never fired during streaming because messagesRef.current mutations don't change the messages array reference. onContentHeightChange fires when ink-scroll-view's internal content height actually changes — driven by MeasurableItem useLayoutEffect measurements — so it catches both streaming text growth and new messages without any state churn.
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.
Problem
Commit 6a89549 extracted
createStreamingHandlerandfinalizeStreaminghelpers, eliminating duplicated callback logic. In the process, thesetMessages()calls that triggered React re-renders were removed. The streaming handlers now mutatemessagesRef.currentdirectly, but withoutsetMessages, React never re-renders and the scroll effect inConversationPanelnever fires.Restoring
setMessagesdefeats theuseRefoptimization that was the whole point of the refactor.Fix
Trigger scroll-to-bottom from the
setIntervalthat already drives the render tick. It readsmessagesRef.currenteach frame and checks streaming state — no state churn, no re-render overhead.Changes
src/tui/app.js: Added scroll-to-bottom check in the render tick interval when the last message is streaming