Skip to content

improvement(mothership-chat): memoize message rows for long-transcript load speed#4520

Merged
waleedlatif1 merged 2 commits intostagingfrom
waleedlatif1/mothership-chat-memo
May 8, 2026
Merged

improvement(mothership-chat): memoize message rows for long-transcript load speed#4520
waleedlatif1 merged 2 commits intostagingfrom
waleedlatif1/mothership-chat-memo

Conversation

@waleedlatif1
Copy link
Copy Markdown
Collaborator

Summary

  • Wrap MessageContent and ChatContent in React.memo and memoize parseBlocks so historical messages render once instead of on every parent state change
  • Extract AssistantMessageRow / UserMessageRow from the inline .map(...) in mothership-chat.tsx and stabilize parent callbacks via the ref pattern so memo boundaries actually hold
  • Stabilize message identity via WeakMap-cached toDisplayMessage so React Query's structural sharing keeps message references identical across refetches

Net effect: opening a long Mothership task (/task/[taskId]) feels instant, scrolling stays smooth, and during streaming only the active message re-renders.

Type of Change

  • Improvement

Testing

Tested manually on long task transcripts. Streaming, edit, queue, and regenerate flows still work; React DevTools Profiler shows historical messages with 0 commits while a chunk arrives on the last message.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel
Copy link
Copy Markdown

vercel Bot commented May 8, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped May 8, 2026 8:26pm

Request Review

@cursor
Copy link
Copy Markdown

cursor Bot commented May 8, 2026

PR Summary

Low Risk
Low risk performance-focused refactor that mainly adds memoization/caching; primary risk is subtle stale-prop or callback wiring issues affecting streaming/option selection rendering.

Overview
Improves long-transcript chat performance by adding React.memo boundaries and memoizing expensive derived data so historical messages don’t re-render on unrelated state changes.

MothershipChat now renders memoized UserMessageRow/AssistantMessageRow, stabilizes option/resource callbacks via refs, and memoizes preceding-user-message lookup. MessageContent/ChatContent are wrapped in memo, parseBlocks results are memoized, and toDisplayMessage now weakly caches per-PersistedMessage mappings to keep message object identity stable across refetches.

Reviewed by Cursor Bugbot for commit c2cbc7e. Configure here.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 8, 2026

Greptile Summary

This PR memoizes the hot render path for Mothership chat by wrapping MessageContent and ChatContent in React.memo, extracting AssistantMessageRow/UserMessageRow as memoized sub-components, stabilizing callbacks with the ref pattern, memoizing parseBlocks, and adding a WeakMap cache on toDisplayMessage to keep ChatMessage references stable across React Query refetches.

  • MessageContent and ChatContent are wrapped with memo and parseBlocks is gated behind useMemo, so historical blocks are parsed only once per unique blocks reference.
  • AssistantMessageRow and UserMessageRow are extracted into stable memoized components; onSubmit/onWorkspaceResourceSelect are stabilized via the ref-callback pattern so non-streaming rows hold their memo boundary across parent re-renders.
  • toDisplayMessage in display-message.ts caches its result in a WeakMap keyed on the PersistedMessage instance, giving React Query's structural sharing a way to preserve downstream identity.

Confidence Score: 5/5

Safe to merge — changes are purely additive memoization with no altered data flow or side effects.

All four files add memoization boundaries or stabilize existing references without touching data fetching, mutation, auth, or business logic. The ref-callback pattern for stabilizing onSubmit is standard React practice, the WeakMap cache correctly keys on object identity and relies on immutable React Query output (documented in JSDoc), EMPTY_BLOCKS is correctly hoisted, and the conditional early returns in AssistantMessageRow contain no hooks so they are safe.

No files require special attention.

Important Files Changed

Filename Overview
apps/sim/app/workspace/[workspaceId]/home/components/mothership-chat/mothership-chat.tsx Extracts AssistantMessageRow/UserMessageRow as memo'd components, stabilizes callbacks with refs, memoizes precedingUserContentByIndex; logic and prop contracts look correct.
apps/sim/lib/copilot/chat/display-message.ts Adds a WeakMap cache to keep ChatMessage references stable per PersistedMessage instance; correctly gates on object identity and stores result before returning.
apps/sim/app/workspace/[workspaceId]/home/components/message-content/message-content.tsx Wraps component in memo and gates parseBlocks behind useMemo; straightforward and correct.
apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/chat-content/chat-content.tsx Wraps component in memo with no other logic changes; safe.

Sequence Diagram

sequenceDiagram
    participant RQ as React Query
    participant DM as toDisplayMessage
    participant MC as MothershipChat
    participant AMR as AssistantMessageRow (memo)
    participant MsgC as MessageContent (memo)
    participant CC as ChatContent (memo)

    RQ->>DM: new PersistedMessage (structural sharing)
    DM->>DM: WeakMap hit? return cached ChatMessage
    DM-->>MC: stable ChatMessage reference

    MC->>MC: useMemo(precedingUserContentByIndex, [messages])
    MC->>MC: stableOnOptionSelect / stableOnWorkspaceResourceSelect (ref pattern)

    MC->>AMR: message (stable ref), isStreaming, rowClassName
    Note over AMR: memo compares props shallowly —<br/>historical rows skip re-render

    AMR->>MsgC: blocks (EMPTY_BLOCKS or stable array)
    Note over MsgC: memo + useMemo(parseBlocks)<br/>skips parse on stable blocks ref

    MsgC->>CC: content, isStreaming
    Note over CC: memo skips re-render for<br/>non-streaming messages
Loading

Reviews (2): Last reviewed commit: "improvement(mothership-chat): hoist EMPT..." | Re-trigger Greptile

Comment thread apps/sim/lib/copilot/chat/display-message.ts
…sageContent memoized for block-free messages
@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit c2cbc7e. Configure here.

@waleedlatif1 waleedlatif1 merged commit 630db5c into staging May 8, 2026
14 checks passed
@waleedlatif1 waleedlatif1 deleted the waleedlatif1/mothership-chat-memo branch May 8, 2026 22:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant