claudecodeui icon indicating copy to clipboard operation
claudecodeui copied to clipboard

fix(sidebar): refresh on session-created; stabilize streaming and navigation (supersedes #159)

Open xavierliang opened this issue 6 months ago • 5 comments

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 activeCursorStreamSessionIdRef and pendingCursorViewingSessionIdRef.
  • Auto-navigation stabilization: when session-created arrives, 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 incoming projects_updated already 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 avatar Aug 17 '25 01:08 xavierliang

@xavierliang Can you check if the PR is still needed with the v1.8.1 changes in the sessions ?

viper151 avatar Sep 16 '25 19:09 viper151

Yes, it's still needed

xavierliang avatar Sep 17 '25 20:09 xavierliang

@xavierliang thanks. are you able to resolve the conflicts and test it again?

viper151 avatar Sep 18 '25 19:09 viper151

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 control
src/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 options
src/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.

coderabbitai[bot] avatar Sep 30 '25 19:09 coderabbitai[bot]

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-4sonnet-4.5
    • Added support for auto, sonnet-4.5-thinking, and grok models

Ready for review! 🚀

xavierliang avatar Sep 30 '25 19:09 xavierliang