← Back to PRs

#14946: fix(webchat): accumulate text across blocks in streaming buffer

by mcaxtr open 2026-02-12 20:12 View on GitHub →
app: web-ui gateway size: M trusted-contributor experienced-contributor
Fixes #14361 ## Summary - Track per-run block state (`blockBases`, `lastBlockTexts`) in `ChatRunState` so that when the agent emits a new text block after a tool call, previous blocks are preserved in the streaming buffer - Detect block boundaries via prefix check (`!text.startsWith(lastBlock)`) — safe because the agent runner suppresses non-prefix updates within a block - Centralize buffer cleanup in `deleteRunBufferState()` and thread it through all abort/TTL paths to prevent stale state leaks ## Root Cause `emitChatDelta` replaced the streaming buffer with each incoming `text` value. Between text blocks (after tool calls), the agent runner resets its accumulated text, so the new block's `text` starts fresh — overwriting the buffer and losing all previous blocks' content. ## Test plan - [x] New test: "accumulates text across multiple assistant blocks" — verifies delta broadcast contains text from both blocks - [x] New test: "includes all blocks in the final chat message" — verifies lifecycle end emits a final payload with both blocks joined - [x] All 11 tests in `server-chat.agent-events.test.ts` pass (7 existing + 2 new + 2 registry) - [x] `pnpm build && pnpm check` pass <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR fixes webchat streaming buffer behavior when assistant output arrives in multiple text blocks (e.g., around tool calls). It extends `ChatRunState` with per-run block tracking (`blockBases`, `lastBlockTexts`) and updates `emitChatDelta` (`src/gateway/server-chat.ts:250+`) to detect block boundaries and build `fullText` as “previous blocks + current block”, so deltas no longer overwrite prior content. Cleanup of buffer-related state is centralized via `deleteRunBufferState` and threaded through abort and maintenance TTL paths (`src/gateway/chat-abort.ts`, `src/gateway/server-maintenance.ts`, and context plumbing in `src/gateway/server.impl.ts`), preventing stale state leaks. New vitest cases in `src/gateway/server-chat.agent-events.test.ts` cover multi-block accumulation and final payload behavior, including the edge case where lifecycle end fires without a trailing delta after the last boundary. <h3>Confidence Score: 5/5</h3> - This PR appears safe to merge with minimal risk. - Changes are localized to webchat streaming state handling, include centralized cleanup to prevent leaks, and are covered by targeted unit tests for multi-block streaming and final message composition. No regressions or missing plumbing were found in the reviewed changeset. - No files require special attention <sub>Last reviewed commit: d967c83</sub> <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs