Skip to content

fix(chat): stabilize streaming interactions#1732

Merged
zerob13 merged 4 commits into
devfrom
bugfix/renderer-lag
Jun 3, 2026
Merged

fix(chat): stabilize streaming interactions#1732
zerob13 merged 4 commits into
devfrom
bugfix/renderer-lag

Conversation

@zerob13
Copy link
Copy Markdown
Collaborator

@zerob13 zerob13 commented Jun 3, 2026

Summary

  • Restore markdown code block spacing by loading the correct MarkStream Tailwind source.
  • Keep chat views pinned to the bottom after sending messages, stream updates, and session switches.
  • Keep reasoning block headings visually consistent with normal thinking text.
  • Pause pending queue auto-drain after a user stop, while preserving manual resume behavior.

UI Structure

BEFORE:

Chat message
  code block toolbar: compressed / cramped
  code lines: tight vertical rhythm
Session switch / send
  scroll position: sometimes slightly above bottom
Reasoning block
  h1/h2/h3: oversized relative to thinking text

AFTER:

Chat message
  code block toolbar: restored spacing
  code lines: normal MarkStream rhythm
Session switch / send
  scroll position: settles at bottom
Reasoning block
  h1/h2/h3: same readable thinking text scale

Tests

  • pnpm vitest --config vitest.config.ts test/main/presenter/agentRuntimePresenter/agentRuntimePresenter.test.ts -t "pauses automatic queue draining"
  • pnpm vitest --config vitest.config.ts test/main/presenter/agentRuntimePresenter/agentRuntimePresenter.test.ts
  • pnpm vitest --config vitest.config.ts test/renderer/components/ChatPage.test.ts test/renderer/assets/markstreamTailwindSource.test.ts test/renderer/components/think-content/ThinkContentStyle.test.ts
  • pnpm run format
  • pnpm run i18n
  • pnpm run lint
  • pnpm run typecheck:node
  • pnpm run typecheck:web

Summary by CodeRabbit

  • Bug Fixes

    • Restored code block toolbar spacing and styling
    • Improved chat scroll restoration to reliably reach the settled bottom (cancels on user intent or message jumps)
    • Made reasoning/think-heading sizes match surrounding text
    • Prevented queued messages from auto-resuming after stopping generation
  • Improvements

    • Enabled smooth streaming display by default
    • Ensured post-submit reliably scrolls to bottom
  • Documentation

    • Added plans/specs/tasks for these fixes and default PR base guidance (dev)

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 3, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 40c968b4-7b6f-41fd-a7ba-b2650fce0713

📥 Commits

Reviewing files that changed from the base of the PR and between 75d8a88 and 874229f.

📒 Files selected for processing (4)
  • src/main/presenter/agentRuntimePresenter/index.ts
  • src/renderer/src/pages/ChatPage.vue
  • test/main/presenter/agentRuntimePresenter/agentRuntimePresenter.test.ts
  • test/renderer/components/ChatPage.test.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • test/main/presenter/agentRuntimePresenter/agentRuntimePresenter.test.ts
  • src/renderer/src/pages/ChatPage.vue
  • src/main/presenter/agentRuntimePresenter/index.ts

📝 Walkthrough

Walkthrough

Documentation and tests for several renderer regressions; switch Tailwind scan target to markstream-vue/dist/tailwind.js; Make reasoning headings inherit prose sizing; default smoothStreaming true; add ChatPage multi-frame session-restore bottom-settle and post-submit bottom forcing; add AgentRuntimePresenter user-pause for pending queues; bump two dependencies; set default PR base guidance to dev.

Changes

Regression Fixes and Queue Pause Behavior

Layer / File(s) Summary
Issue plans, specs, tasks
docs/issues/markdown-codeblock-session-scroll-regressions/*, docs/issues/reasoning-heading-font-size/*, docs/issues/stop-pauses-pending-queue/*
Adds plans, specs, and task lists covering Tailwind/code-block styling, session-restore scroll settling, reasoning heading sizing, and pending-queue pause behavior.
Dependency version updates
package.json
Bumps markstream-vue to 1.0.1-beta.4 and stream-monaco to ^0.0.41.
Queue pause on user stop
src/main/presenter/agentRuntimePresenter/index.ts, test/main/presenter/agentRuntimePresenter/agentRuntimePresenter.test.ts
Adds user-paused pending-queue tracking and guards to block automatic drains/start while paused; clears pause on resume, empty pending lane, or session destroy; adds regression test.
Tailwind wiring & ThinkContent heading overrides
src/renderer/src/assets/style.css, src/renderer/src/components/markdown/MarkdownRenderer.vue, src/renderer/src/components/think-content/ThinkContent.vue, test/renderer/assets/markstreamTailwindSource.test.ts, test/renderer/components/think-content/ThinkContentStyle.test.ts
Switches Tailwind source to markstream-vue/dist/tailwind.js, adds style guards/test for generated utilities, sets smooth streaming default true, and makes reasoning headings inherit body font-size/line-height via CSS variables and :deep fallback.
Chat scroll restoration and post-submit settling
src/renderer/src/pages/ChatPage.vue, test/renderer/components/ChatPage.test.ts
Adds bounded multi-frame scroll-settle to reliably restore bottom after late layout growth, cancels on user intent/session change/spotlight, and schedules post-submit forced bottom scroll; includes tests for settling, forcing, and cancellation.

Repository Guidelines Update

Layer / File(s) Summary
Default PR base branch rule
AGENTS.md, docs/issues/pr-base-dev-default/*
Adds guidance and docs to default routine PRs to dev with an example command, aligning with release flow docs.

Sequence Diagram

sequenceDiagram
  participant User
  participant ChatPage
  participant ScrollSettle
  participant Queue as AgentRuntimePresenter
  User->>ChatPage: submit message / switch session / stop
  ChatPage->>ScrollSettle: schedule post-submit bottom scroll or session-restore settle
  ScrollSettle->>ChatPage: read scrollHeight, set scrollTop to bottom
  ScrollSettle->>ChatPage: observe ResizeObserver events and retry if height grows
  User->>ChatPage: wheel/scroll/keydown intent
  ChatPage->>ScrollSettle: cancel settle
  User->>Queue: stop active queued turn (via cancelGeneration)
  Queue->>Queue: mark session paused, block drain
  User->>Queue: resumePendingQueue
  Queue->>Queue: clear pause and resume drain
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I nudge the scroll to find the floor,

Code blocks bloom with styles restored,
Queues that stop now hold their place,
Headings shrink to match the prose’ grace,
A tiny hop — devs ship with cheer!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'fix(chat): stabilize streaming interactions' is directly relevant to the main change objectives: fixing chat UI regressions related to streaming, scrolling, and queue behavior. The title succinctly captures the core intent of the changeset.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 bugfix/renderer-lag

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 and usage tips.

@zerob13 zerob13 changed the base branch from main to dev June 3, 2026 14:21
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/presenter/agentRuntimePresenter/index.ts (1)

621-631: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Clear the pause flag even when draining must wait.

Line 626 returns before the explicit resume action clears userPausedPendingQueues. That means the UI resume path in src/renderer/src/stores/ui/pendingInput.ts:114-124 is ignored whenever the session is waiting for a follow-up answer, and once that follow-up is sent the later 'completed' drain path is still blocked by the stale pause flag.

Suggested fix
   async resumePendingQueue(sessionId: string): Promise<void> {
     const state = await this.getSessionState(sessionId)
     if (!state) {
       throw new Error(`Session ${sessionId} not found`)
     }
+    this.userPausedPendingQueues.delete(sessionId)
     if (this.isAwaitingToolQuestionFollowUp(sessionId)) {
       return
     }
-
-    this.userPausedPendingQueues.delete(sessionId)
     void this.drainPendingQueueIfPossible(sessionId, 'resume')
   }
🤖 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/main/presenter/agentRuntimePresenter/index.ts` around lines 621 - 631, In
resumePendingQueue, the code returns early when
isAwaitingToolQuestionFollowUp(sessionId) is true but that prevents clearing the
userPausedPendingQueues flag; move or add the deletion of the pause flag so
userPausedPendingQueues.delete(sessionId) is executed regardless of the
follow-up-waiting check (i.e., delete before or immediately after calling
isAwaitingToolQuestionFollowUp), and keep the existing early return behavior so
that drainPendingQueueIfPossible(sessionId, 'resume') is only invoked when
appropriate.
🤖 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/pages/ChatPage.vue`:
- Around line 451-517: The settleSessionRestoreScrollToBottom function only
cancels restore-settling on wheel/touchstart, allowing scrollbar drags and
keyboard scrolling to be overridden; update it to listen for additional
user-scroll intents (add 'scroll' on scrollContainer, pointer events like
'pointerdown'/'mousedown' to catch scrollbar drags, and keyboard events such as
'keydown' for PageUp/PageDown/Arrow/Home/End) and wire those to
cancelSessionRestoreScrollSettle via the existing
cancelSessionRestoreScrollIntentListeners mechanism; ensure you register these
same handlers on the same element(s) (scrollContainer.value) and remove them in
cancelSessionRestoreScrollIntentListeners so cancelSessionRestoreScrollSettle
still tears down RAF (sessionRestoreScrollFrame), ResizeObserver
(sessionRestoreResizeObserver) and timeout (sessionRestoreScrollTimer)
correctly.

In `@test/main/presenter/agentRuntimePresenter/agentRuntimePresenter.test.ts`:
- Line 3476: Replace the non-deterministic sleep calls "await new
Promise((resolve) => setTimeout(resolve, 10))" in the test file with
deterministic coordination: use Vitest's vi.waitFor to poll for the expected
condition (e.g., assert that the presenter state or mock call count has changed)
or refactor to await an event/promise returned by the code under test; update
both occurrences (the one at the shown line and the other at the noted nearby
line) to wait for a concrete observable condition instead of a fixed timeout so
the tests are reliable on slow CI/machines.

---

Outside diff comments:
In `@src/main/presenter/agentRuntimePresenter/index.ts`:
- Around line 621-631: In resumePendingQueue, the code returns early when
isAwaitingToolQuestionFollowUp(sessionId) is true but that prevents clearing the
userPausedPendingQueues flag; move or add the deletion of the pause flag so
userPausedPendingQueues.delete(sessionId) is executed regardless of the
follow-up-waiting check (i.e., delete before or immediately after calling
isAwaitingToolQuestionFollowUp), and keep the existing early return behavior so
that drainPendingQueueIfPossible(sessionId, 'resume') is only invoked when
appropriate.
🪄 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: 86b56889-6647-4819-866c-53a20c117353

📥 Commits

Reviewing files that changed from the base of the PR and between 9d5f0db and 9d82aa6.

📒 Files selected for processing (19)
  • docs/issues/markdown-codeblock-session-scroll-regressions/plan.md
  • docs/issues/markdown-codeblock-session-scroll-regressions/spec.md
  • docs/issues/markdown-codeblock-session-scroll-regressions/tasks.md
  • docs/issues/reasoning-heading-font-size/plan.md
  • docs/issues/reasoning-heading-font-size/spec.md
  • docs/issues/reasoning-heading-font-size/tasks.md
  • docs/issues/stop-pauses-pending-queue/plan.md
  • docs/issues/stop-pauses-pending-queue/spec.md
  • docs/issues/stop-pauses-pending-queue/tasks.md
  • package.json
  • src/main/presenter/agentRuntimePresenter/index.ts
  • src/renderer/src/assets/style.css
  • src/renderer/src/components/markdown/MarkdownRenderer.vue
  • src/renderer/src/components/think-content/ThinkContent.vue
  • src/renderer/src/pages/ChatPage.vue
  • test/main/presenter/agentRuntimePresenter/agentRuntimePresenter.test.ts
  • test/renderer/assets/markstreamTailwindSource.test.ts
  • test/renderer/components/ChatPage.test.ts
  • test/renderer/components/think-content/ThinkContentStyle.test.ts

Comment thread src/renderer/src/pages/ChatPage.vue
Comment thread test/main/presenter/agentRuntimePresenter/agentRuntimePresenter.test.ts Outdated
@zerob13
Copy link
Copy Markdown
Collaborator Author

zerob13 commented Jun 3, 2026

Addressed the remaining review feedback in 874229f1: resumePendingQueue now clears the user pause before the follow-up early return, session restore settling cancels on wheel/touch/pointer/mouse/manual scroll/keyboard scroll intent, and the queue pause regression test now uses deterministic coordination instead of fixed sleeps. Re-ran the related main/renderer tests plus format, i18n, lint, and typecheck.

@zerob13 zerob13 merged commit 599a203 into dev Jun 3, 2026
3 checks passed
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