Problem
When the model produces text followed by a tool call, the Control UI receives the tool event before the final text delta has been delivered. This causes text preceding a tool card to appear truncated during streaming.
Root Cause
In server-chat.ts, emitChatDelta throttles text broadcasts at 150ms intervals (line 374). When a tool event fires, it is broadcast immediately via emitAgentEvent / broadcastToConnIds. There is no flush of the pending chat delta buffer before the tool event is sent.
The server already flushes buffered text before emitChatFinal (around line 425) to ensure the client has the complete text before the final event. The same pattern should apply before tool events.
Expected Behavior
All accumulated text deltas should be flushed to WebSocket clients before the corresponding tool start event is broadcast. This ensures the UI can display the complete text above the tool card without relying on client-side timing heuristics.
Current Workaround
PR #39036 adds chatStreamSegments to commit whatever text has been received at the time a tool card renders. This works but results in truncated text fragments when the tool event arrives before the throttled delta. History reload shows the correct final state.
Proposed Fix
In the tool event emission path (likely where emitAgentEvent is called with stream: "tool" and phase: "start"), flush any pending chat delta for the same runId/sessionKey before broadcasting the tool event. This mirrors the existing flush-before-final pattern.
Related
Problem
When the model produces text followed by a tool call, the Control UI receives the tool event before the final text delta has been delivered. This causes text preceding a tool card to appear truncated during streaming.
Root Cause
In
server-chat.ts,emitChatDeltathrottles text broadcasts at 150ms intervals (line 374). When a tool event fires, it is broadcast immediately viaemitAgentEvent/broadcastToConnIds. There is no flush of the pending chat delta buffer before the tool event is sent.The server already flushes buffered text before
emitChatFinal(around line 425) to ensure the client has the complete text before the final event. The same pattern should apply before tool events.Expected Behavior
All accumulated text deltas should be flushed to WebSocket clients before the corresponding tool
startevent is broadcast. This ensures the UI can display the complete text above the tool card without relying on client-side timing heuristics.Current Workaround
PR #39036 adds
chatStreamSegmentsto commit whatever text has been received at the time a tool card renders. This works but results in truncated text fragments when the tool event arrives before the throttled delta. History reload shows the correct final state.Proposed Fix
In the tool event emission path (likely where
emitAgentEventis called withstream: "tool"andphase: "start"), flush any pending chat delta for the samerunId/sessionKeybefore broadcasting the tool event. This mirrors the existing flush-before-final pattern.Related