Skip to content

perf(chat): smooth stream rendering - #1954

Merged
zerob13 merged 1 commit into
devfrom
chat-stream-rendering-perf
Jul 13, 2026
Merged

perf(chat): smooth stream rendering#1954
zerob13 merged 1 commit into
devfrom
chat-stream-rendering-perf

Conversation

@zhangmo8

@zhangmo8 zhangmo8 commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • Performance Improvements

    • Improved streaming artifact parsing for smoother long-text rendering.
    • Reduced chat rendering and scrolling work during streaming to minimize jitter.
    • Optimized message updates in long conversations.
  • Bug Fixes

    • Reduced flicker when reapplying the same chat search highlights.
    • Improved handling of streaming artifacts and tool-call content.
  • Documentation

    • Added specifications for artifact parsing, chat search highlighting, streaming scroll feedback, and message rendering performance issues.

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The PR optimizes artifact streaming parsing, stabilizes repeated chat-search highlighting, and refactors ChatPage streaming display and scroll coordination. It also adds issue specifications and focused tests for parser caching, highlight reuse, message caching, and streaming behavior.

Changes

Artifact parsing optimization

Layer / File(s) Summary
Parser primitives and specification
docs/issues/artifact-streaming-parse-hotspot/spec.md, src/renderer/src/composables/useArtifacts.ts
Documents the parsing hotspot and adds reusable parser regular expressions and memoization state.
Tag scanning and matching
src/renderer/src/composables/useArtifacts.ts
Uses shared tag probing, earliest-tag detection, targeted matching, and loading-state filtering.
Part generation and parser validation
src/renderer/src/composables/useArtifacts.ts, test/renderer/composables/useArtifacts.test.ts
Builds parsed part variants, preserves tool-call state handling, and tests artifact, thinking, tool-call, extraction, and cache behavior.

Chat search highlight stability

Layer / File(s) Summary
Applied-query highlight state
docs/issues/chat-search-highlight-flicker/spec.md, src/renderer/src/lib/chatSearch.ts
Stores the normalized applied query and avoids clearing existing marks when the query is unchanged.
Highlight reuse and rebuild tests
test/renderer/lib/chatSearch.test.ts
Tests cleared query state, mark preservation for repeated queries, and rebuilding when the query changes.

Streaming rendering and scroll coordination

Layer / File(s) Summary
Scroll feedback-loop control
docs/issues/chat-stream-scroll-feedback-loop/spec.md, src/renderer/src/pages/ChatPage.vue
Coordinates bottom-following and anchor restoration, marks programmatic writes, and coalesces deferred scroll updates.
Stable and streaming display merge
docs/issues/display-messages-streaming-hot-path/spec.md, src/renderer/src/pages/ChatPage.vue
Separates stable history from the streaming tail and reinserts the active streaming row in message order.
Rendering cache regression coverage
test/renderer/components/ChatPage.test.ts
Models production message, cache, and revision updates in the display-message rebuild test.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ChatPage
  participant MessageListRow
  participant ResizeObserver
  participant useMessageWindow
  ChatPage->>MessageListRow: render streaming message
  MessageListRow->>ResizeObserver: report measured height
  ResizeObserver->>useMessageWindow: update virtual-window measurements
  useMessageWindow->>ChatPage: return viewport updates
  ChatPage->>ChatPage: coalesce programmatic bottom scroll
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the PR’s main goal: improving chat stream rendering performance and smoothness.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chat-stream-rendering-perf

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/renderer/src/composables/useArtifacts.ts (1)

97-98: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Unclosed-artifact regex requires title/identifier/type and scans full content via .* + /s.

Two concerns on this hot path:

  • The three lookaheads use greedy .* with the s flag, so each match attempt scans the entire remaining content (including artifact body) — partially reintroducing the linear-per-scan cost this PR targets, and allowing attributes located in the body to satisfy the lookaheads.
  • ARTIFACT_CLOSED_RE accepts any attribute set (parseAttributes defaults missing ones), but ARTIFACT_UNCLOSED_RE matches only when all three attributes are present. A streaming artifact whose opening tag lacks title is treated as plain text instead of a loading artifact, which can surface the raw tag during streaming.

Consider deriving the unclosed part from the opening-tag substring (as buildUnclosedArtifactPart already does) rather than encoding required attributes in lookaheads.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/renderer/src/composables/useArtifacts.ts` around lines 97 - 98, The
ARTIFACT_UNCLOSED_RE pattern incorrectly scans the artifact body and requires
title, identifier, and type. Update the unclosed-artifact handling to derive
attributes from only the opening-tag substring, reusing the approach in
buildUnclosedArtifactPart, and allow missing attributes consistently with
ARTIFACT_CLOSED_RE so incomplete streaming artifacts still produce loading
output.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/renderer/src/lib/chatSearch.ts`:
- Around line 118-120: Update the chat-search root state handling around
setAppliedSearchQuery and related query-change logic to preserve applied-query
state for plain DocumentFragment roots that lack the data-chat-search-root
attribute. Store fragment state in a WeakMap<ParentNode, string>, continue using
the attribute for element roots, and ensure later query changes invoke
clearChatSearchHighlights so stale marks are rebuilt. Add a regression test
covering successive queries on a plain DocumentFragment.

---

Nitpick comments:
In `@src/renderer/src/composables/useArtifacts.ts`:
- Around line 97-98: The ARTIFACT_UNCLOSED_RE pattern incorrectly scans the
artifact body and requires title, identifier, and type. Update the
unclosed-artifact handling to derive attributes from only the opening-tag
substring, reusing the approach in buildUnclosedArtifactPart, and allow missing
attributes consistently with ARTIFACT_CLOSED_RE so incomplete streaming
artifacts still produce loading output.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a10d5818-ed4a-46a4-b0c9-3de225cb0466

📥 Commits

Reviewing files that changed from the base of the PR and between f5d0377 and 4a16cae.

📒 Files selected for processing (10)
  • docs/issues/artifact-streaming-parse-hotspot/spec.md
  • docs/issues/chat-search-highlight-flicker/spec.md
  • docs/issues/chat-stream-scroll-feedback-loop/spec.md
  • docs/issues/display-messages-streaming-hot-path/spec.md
  • src/renderer/src/composables/useArtifacts.ts
  • src/renderer/src/lib/chatSearch.ts
  • src/renderer/src/pages/ChatPage.vue
  • test/renderer/components/ChatPage.test.ts
  • test/renderer/composables/useArtifacts.test.ts
  • test/renderer/lib/chatSearch.test.ts

Comment thread src/renderer/src/lib/chatSearch.ts
@zerob13
zerob13 merged commit 38f7cb5 into dev Jul 13, 2026
4 checks passed
@zhangmo8
zhangmo8 deleted the chat-stream-rendering-perf branch July 13, 2026 07:57
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.

2 participants