Files
Naiyuan Qing 2e8578acbd fix(chat): stop remounting the live timeline on every streamed task message (MUL-3960) (#4845)
* fix(chat): stop remounting the live timeline on every streamed task message (MUL-3960)

The Virtuoso components prop was built inline, so every render produced new
Header/Footer component types and React unmounted + remounted the entire live
timeline subtree. During task streaming that meant every task:message event
tore down and rebuilt thousands of rows and re-parsed all Markdown, freezing
the renderer for seconds at a time on long agent runs.

- Hoist Header/Footer to module scope and pass per-render data through
  Virtuoso's context prop (re-render instead of remount).
- Memoize buildTimeline on the task-messages cache array identity (live
  timeline and persisted AssistantMessage).
- Render message text through MemoizedMarkdown so unchanged content skips
  the markdown re-parse; only the streaming tail re-renders.

Regression tests assert the footer DOM node survives a streamed message and
that a user-collapsed process fold stays closed (both failed before the fix).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>

* perf(chat): memoize MessageBubble so streamed messages skip untouched rows

Follow-up to the MUL-3960 remount fix: each task:message still re-rendered
every visible history row through itemContent. Message objects are
referentially stable and isPending is a boolean, so a shallow memo makes
the persisted history inert during streaming — only the live footer
reconciles per message.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
2026-07-02 16:12:50 +08:00
..