You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The chat webview turns gray (crashes) during long-running tasks. User-reported diagnostics from logWebviewHiddenDiagnostics confirm 3,525 messages at crash time. This is tracked upstream as a recurring user complaint — PR #153 reduced the react-virtuoso pre-render buffer but did not address the root cause.
Related: Part of the broader webview message architecture addressed by #355 (Stories 3.2c + 3.2d), but scoped as an independent fix that doesn't touch the message protocol or task lifecycle.
Developer Notes
Problem
addToClineMessages (Task.ts:1015) calls postStateToWebviewWithoutTaskHistory() on every single message addition, serializing and posting the entire clineMessages array to the webview. With 3,525 messages averaging ~2KB of tool output each, every state push is ~7MB. During active tool use with checkpoint saves, this fires dozens of times per minute. The webview must deserialize, merge into React state, and re-render each time — eventually exceeding the V8 heap limit and crashing the renderer (gray screen).
Secondary issue: aggregatedCostsMap in ChatView.tsx is never cleared on task change (line 480-491 cleanup effect), causing unbounded growth across task switches with subtasks.
Proposed Fix
Throttle the hot-path state pushes — no new message types, no protocol changes.
Task.ts — swap 2 hot-path call sites (2 line changes)
Line
Context
Change
1015
addToClineMessages — every new message
→ postStateToWebviewThrottled
527
messageQueueService.stateChanged
→ postStateToWebviewThrottled
1828
Task start (clear state)
Keep immediate
2551
Before API request
Keep immediate
3291
After streaming complete
Keep immediate
Partial message streaming is unaffected — updateClineMessage (Task.ts:1048) already uses the lightweight { type: "messageUpdated" } path, bypassing the full state push entirely.
ChatView.tsx:481 — clear aggregatedCostsMap on task change (1 line)
setAggregatedCostsMap(newMap())
Task.abortTask — flush debounce on abort (1 line)
Ensures the final state is delivered when a task is stopped.
Impact
At 3,525 messages:
Before: ~7MB × dozens/sec during rapid tool use → OOM → gray screen
After: ~7MB × max 2/sec (throttled) → webview stays alive
Risk Assessment
Low risk: No new message types, no protocol changes, no task lifecycle changes
UI delay: New message bubbles may appear up to 500ms late; streaming text is unaffected (uses messageUpdated path)
Final state guaranteed:trailing: true + abort flush ensures last state is always delivered
Context
The chat webview turns gray (crashes) during long-running tasks. User-reported diagnostics from
logWebviewHiddenDiagnosticsconfirm 3,525 messages at crash time. This is tracked upstream as a recurring user complaint — PR #153 reduced the react-virtuoso pre-render buffer but did not address the root cause.Related: Part of the broader webview message architecture addressed by #355 (Stories 3.2c + 3.2d), but scoped as an independent fix that doesn't touch the message protocol or task lifecycle.
Developer Notes
Problem
addToClineMessages(Task.ts:1015) callspostStateToWebviewWithoutTaskHistory()on every single message addition, serializing and posting the entireclineMessagesarray to the webview. With 3,525 messages averaging ~2KB of tool output each, every state push is ~7MB. During active tool use with checkpoint saves, this fires dozens of times per minute. The webview must deserialize, merge into React state, and re-render each time — eventually exceeding the V8 heap limit and crashing the renderer (gray screen).Secondary issue:
aggregatedCostsMapinChatView.tsxis never cleared on task change (line 480-491 cleanup effect), causing unbounded growth across task switches with subtasks.Proposed Fix
Throttle the hot-path state pushes — no new message types, no protocol changes.
ClineProvider.ts— add throttled variant (~10 lines)Task.ts— swap 2 hot-path call sites (2 line changes)addToClineMessages— every new messagepostStateToWebviewThrottledmessageQueueService.stateChangedpostStateToWebviewThrottledPartial message streaming is unaffected —
updateClineMessage(Task.ts:1048) already uses the lightweight{ type: "messageUpdated" }path, bypassing the full state push entirely.ChatView.tsx:481— clear aggregatedCostsMap on task change (1 line)Task.abortTask— flush debounce on abort (1 line)Ensures the final state is delivered when a task is stopped.
Impact
At 3,525 messages:
Risk Assessment
messageUpdatedpath)trailing: true+ abort flush ensures last state is always deliveredAcceptance Criteria
aggregatedCostsMapis empty after task switch