spacedriveapp / spacedriveapp/spacebot
[bug] WebChatPanel lags when typing with a long conversation history
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 2.4k
- Forks
- 367
- PR merge metrics
- No merged PRs in 30d
Description
Description
Typing in the WebChatPanel input becomes progressively slower as the conversation history grows. With a long chat, every keypress causes noticeable lag/jank.
Root cause
There are three compounding issues:
1. All markdown re-renders on every keystroke (primary cause)
input state lives in WebChatPanel alongside timeline.map(). Every keypress re-renders WebChatPanel, which walks the entire message list and re-runs react-markdown's full remark-gfm + rehype-raw AST pipeline for every assistant message. No message components are wrapped in React.memo.
Additionally, the components, remarkPlugins, and rehypePlugins props passed to <ReactMarkdown> are defined inline — new object/array references on every render — so ReactMarkdown cannot bail out even if the content string is unchanged.
2. No message list virtualization
@tanstack/react-virtual is already installed and used in AgentMemories.tsx, but never applied to any chat panel. All messages are always in the DOM.
3. DOM reflow per keystroke (textarea auto-resize)
FloatingChatInput has a useEffect([value]) dependency on the input string. On every character typed it removes the "input" event listener, calls adjustHeight() directly (forcing a height="auto" write → scrollHeight read → height write reflow cycle), then re-adds the listener.
Steps to reproduce
- Start a long conversation with an agent (20+ message exchanges with markdown-heavy responses)
- Click in the input field and type — lag increases proportionally to history length
Suggested fixes
- Wrap
MarkdownwithReact.memoand hoistremarkPlugins,rehypePlugins, andcomponentsto module-level constants soReactMarkdownskips re-rendering when content is unchanged - Move
inputstate intoFloatingChatInputso keystrokes only re-render the small input component, notWebChatPaneland its message list - Change the
useEffect([value])to run once on mount ([]) and rely on a native"input"event listener for height adjustment — eliminating the reflow-per-keystroke - (Follow-up) Apply
useVirtualizerfrom@tanstack/react-virtualto the scroll container — the dependency is already installed
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by locating WebChatPanel, Markdown, FloatingChatInput, and the AgentMemories.tsx use of @tanstack/react-virtual. Trace how input state and markdown props flow through the message list, then inspect the textarea height effect. Done means typing stays responsive with long markdown-heavy histories, while message rendering and input resizing avoid unnecessary per-keystroke work.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, typescript
- Domain
- frontend, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100