fix(ui): deduplicate streaming chat segments to prevent growing duplicate bubbles#47399
Closed
LittleBreak wants to merge 1 commit into
Closed
fix(ui): deduplicate streaming chat segments to prevent growing duplicate bubbles#47399LittleBreak wants to merge 1 commit into
LittleBreak wants to merge 1 commit into
Conversation
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
Fixes #47188 — webchat streaming responses create multiple duplicate message bubbles with growing text instead of updating a single bubble in-place.
Root Cause
The gateway sends the full accumulated assistant text in each streaming delta event. When a tool call interrupts the stream,
app-tool-stream.tssaves the currentchatStream(full accumulated text) as a segment. After the tool completes, new delta events arrive containing the full text again (including text already in segments), causing each segment to show incrementally more duplicated text.This was previously masked by a
loadChatHistory()call after every tool result (removed in 0e8672a to fix a reload storm). Removing that call exposed this pre-existing segment duplication bug.Fix
Introduce
chatStreamSegmentOffsetto track the length of text already committed to segments:app-tool-stream.ts: When saving a segment on tool start, usechatStream.slice(offset)to store only the delta text (not the full accumulated text). Updateoffset = chatStream.lengthafter each save.views/chat.ts: When rendering the live stream bubble, usestream.slice(offset)to display only new text after the last segment.resetToolStream().Files Changed (8)
ui/src/ui/app-tool-stream.tsui/src/ui/views/chat.tsstreamSegmentOffsetpropui/src/ui/app.ts@state() chatStreamSegmentOffsetui/src/ui/app-view-state.tsui/src/ui/app-render.tsui/src/ui/views/chat.test.tsui/src/ui/app-tool-stream.node.test.tsui/src/ui/app-gateway.node.test.tsTesting