fix(sidebar): refresh on session-created; stabilize streaming and navigation (supersedes #159)
Summary
This PR supersedes and replaces #159. It includes all improvements from #159 (stabilizing streaming message rendering and post-completion sync), and adds a robust Sidebar refresh mechanism for newly created sessions.
Brought over from #159
- Streaming ownership guard: render incremental updates only for the active session using
activeCursorStreamSessionIdRefandpendingCursorViewingSessionIdRef. - Auto-navigation stabilization: when
session-createdarrives, auto-navigate only from/and avoid double-handling by advancing the processed index before returning. - Post-completion authoritative sync (Cursor): after
cursor-result, silently reload and replace history if the fetched log is richer or differs. - Prevent cross-session contamination and flicker during streaming; preserve current chat state when background updates arrive.
New in this PR
- Sidebar refresh on
session-created: schedule a single delayed refresh (same behavior as clicking the Sidebar refresh button), and cancel it if an incomingprojects_updatedalready includes the new session. - Relax additive-update guard so Sidebar updates remain visible during active sessions (Cursor always treated as additive; Claude checks by id only).
Related issues
- Closes #153
- Supersedes #159
Test plan
- Create new session → Sidebar shows the new session once; no infinite refresh.
- Switch to another session while creating a new one → background refresh still occurs; no UI flicker; selected session unaffected.
- Stream long outputs → increments only render for the correct session; no contamination across sessions.
- After completion (Cursor), history silently reloaded and replaced only when richer/different.
Summary by CodeRabbit
-
New Features
- Added full support for Cursor sessions, including persistent session data and selection from the Sidebar.
- Expanded Cursor model options (auto, gpt-5, sonnet-4.5, sonnet-4.5-thinking, opus-4.1, grok) with an always-visible model selector when using Cursor.
-
Bug Fixes
- Reduced duplicate and out-of-order messages during streaming; final messages are consolidated reliably.
- Improved session navigation to avoid unexpected jumps and duplicate redirects.
-
Chores
- Optimized background refreshes and debounced Sidebar updates to prevent unnecessary reloads and preserve selections.
@xavierliang Can you check if the PR is still needed with the v1.8.1 changes in the sessions ?
Yes, it's still needed
@xavierliang thanks. are you able to resolve the conflicts and test it again?
Walkthrough
Introduces incremental WebSocket processing, additive-update gating, and timer-managed Sidebar refreshes. Adds comprehensive streaming/state management for Cursor sessions: chunk accumulation, finalization, session-guarded updates, silent post-stream refresh, expanded model mapping, and navigation deduping. Selection preservation and URL/session routing are adjusted to include Cursor sessions and provider metadata.
Changes
| Cohort / File(s) | Summary |
|---|---|
Session, projects, and WebSocket controlsrc/App.jsx |
Adds refs for projects and last processed index; incremental WebSocket handling; global debounced/cancelable Sidebar refresh timers; additive-only updates when a session is active (Cursor treated additive); selection preservation for project/session including Cursor sessions; merges Cursor sessions in fetch/compare; URL/session routing updated for Cursor. |
Streaming, Cursor integration, and UI optionssrc/components/ChatInterface.jsx |
Implements guarded navigation to new sessions; rich streaming state via refs; helpers to append/finalize streaming chunks; session-gated incremental updates; silent refresh after Cursor streaming; dedupe final content; buffered Claude streaming handling; guards on system-driven session changes; extended Cursor model mapping and selector; stable message keys. |
Sequence Diagram(s)
sequenceDiagram
autonumber
participant WS as WebSocket
participant App as App.jsx
participant Timers as window.__ensureTimers
participant Sidebar as Sidebar (refresh)
participant Store as Projects State
WS->>App: projects_updated / session_created / message events
App->>App: Check appLastProcessedIndexRef (incremental)
App->>App: isUpdateAdditive? (Cursor sessions additive)
alt Active session AND non-additive
App--xWS: Skip update (protect active session)
else Additive or no active session
App->>Store: Merge projects with cursorSessions
App->>App: Update projectsRef
end
opt session_created received
App->>Timers: schedule one-time Sidebar refresh
end
WS-->>App: projects_updated includes session
App->>Timers: cancel pending refresh (if includes session)
Timers->>Sidebar: refresh
Sidebar->>Store: fetch baseProjects
Sidebar->>Store: attach Cursor session data
Sidebar->>App: return updated list
App->>App: Preserve selected project/session if possible
sequenceDiagram
autonumber
participant WS as WebSocket
participant Chat as ChatInterface.jsx
participant Cursor as Cursor Provider
participant Router as Router
participant Store as Chat State
Note over Chat: Initialize streaming refs and guards
WS-->>Chat: claude-response / claude-output deltas
Chat->>Chat: buffer deltas (accumulate-and-flush)
Chat->>Store: appendStreamingChunk(session-scoped)
WS-->>Chat: final result / done
Chat->>Store: finalizeStreaming -> stable assistant message
Chat->>Chat: Update lastAssistantTextRef
alt Provider == Cursor
Chat->>Chat: Start silent refresh timer
Chat-->>Cursor: fetch authoritative history (deferred)
Cursor-->>Chat: history
Chat->>Store: reconcile without duplicates
end
opt session_created or session switch
Chat->>Chat: Dedup navigate (navigatedToSessionRef)
alt At root path only
Chat->>Router: navigate to new session
else
Chat--xRouter: no auto-navigation
end
end
Note over Chat: Guards prevent cross-session updates and duplicate finals
Estimated code review effort
🎯 4 (Complex) | ⏱️ ~60 minutes
Poem
A twitch of whiskers, streams align,
I nibble bugs where bytes entwine.
Chunks now cuddle, finals chime,
Sessions hop in tidy time.
Cursor’s burrow, models bloom—
Refreshes tiptoe, skip the boom.
Thump! The chat now sings in tune. 🐇✨
Pre-merge checks and finishing touches
❌ Failed checks (1 warning)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Out of Scope Changes Check | ⚠️ Warning | In addition to the streaming fixes required by issue #153, this PR introduces sidebar refresh scheduling and cancellation logic, global timer management, navigation stabilization tied to session creation, expanded Cursor model UI selectors, and extended project/session fetch behavior, all of which lie outside the scope of the linked streaming bug objectives. | Please isolate the streaming-rendering fixes into a dedicated PR and split the sidebar refresh, navigation stabilization, and Cursor integration features into separate changes or update the linked issues to explicitly cover these additional scopes. |
✅ Passed checks (4 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
| Title Check | ✅ Passed | The title clearly and concisely summarizes the primary fixes in this changeset by indicating the sidebar refresh on session creation and the stabilization of streaming and navigation behavior, directly reflecting the main objectives without extraneous or misleading information. |
| Linked Issues Check | ✅ Passed | The pull request implements a comprehensive streaming ownership guard with explicit accumulate-and-flush logic (appendStreamingChunk/finalizeStreaming) to eliminate missing characters during live AI responses, ensures the final rendered message matches the post-refresh state without flicker, and validates long continuous streams in real time, fully addressing the objectives of issue #153. |
| Docstring Coverage | ✅ Passed | Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. |
✨ Finishing touches
- [ ] 📝 Generate Docstrings
🧪 Generate unit tests
- [ ] Create PR with unit tests
- [ ] Post copyable unit tests in a comment
Comment @coderabbitai help to get the list of available commands and usage tips.
Updated PR with latest changes
I've updated this PR to resolve the merge conflicts with the latest main branch (v1.8.10).
Changes included:
- ✅ Resolved merge conflicts in
MainContent.jsx - ✅ Added Cursor CLI model name fixes (Previous models unavailable after sonnet 4.5):
- Updated
sonnet-4→sonnet-4.5 - Added support for
auto,sonnet-4.5-thinking, andgrokmodels
- Updated
Ready for review! 🚀