Skip to content

perf(desktop): keep cached transcript visible while session resumes - #96721

Closed
helix4u wants to merge 2 commits into
NousResearch:mainfrom
helix4u:feat/desktop-session-resume-fast-path
Closed

helix4u wants to merge 2 commits into
NousResearch:mainfrom
helix4u:feat/desktop-session-resume-fast-path

Conversation

@helix4u

@helix4u helix4u commented Aug 27, 2026 •

Copy link
Copy Markdown
Collaborator

What does this PR do?

Desktop can already have the exact remembered session's bounded transcript snapshot before backend/profile hydration and session.resume finish binding a live runtime. Without an early navigation claim, the cold / route can expose a usable fresh composer during that window and later replace what the user was doing when remembered navigation resolves.

This claims remembered navigation before first paint, restores only the exact connection/profile-scoped transcript snapshot, and keeps that presentation provisional until the live session list validates ownership. Cached text may remain visible while the runtime binds, but the composer and fresh-session intro remain unavailable until the remembered route owns a live runtime.

Current main also keeps the loader visible when the session list says a routed session has history but no display-authoritative transcript has arrived. The rebased implementation preserves that behavior: a brand-new routed draft with a bound runtime may be empty, while known history, route mismatch, missing runtime binding, or unresolved remembered navigation remains pending. The transcript loader is suppressed only when cached text is already visible; the composer gate remains active.

The explicit last-opened session is authoritative when a torn shutdown left the remembered route and session ID disagreeing. The route is healed only after live validation. Cached text never creates or impersonates a runtime, and stale, missing, cross-profile, or unnameable remote targets fail closed and clear only the provisional paint.

Desktop performance series

This change is one independently reviewable layer of the same Desktop startup and first-interaction performance pass.

This PR owns remembered-session presentation and pending-runtime gating. It does not change backend startup, session-list caching, transcript snapshot bounds, or Bot Mode roster behavior.

Related Issue

None.

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • Claim remembered startup navigation during layout so / cannot expose a competing fresh composer before session hydration.
  • Restore a bounded transcript tail only for the exact remembered connection/profile/session scope.
  • Keep cached transcript presentation visible while live ownership validation and session.resume bind the runtime.
  • Keep the composer and fresh-session intro unavailable throughout that pending state.
  • Preserve current main's distinction between a legitimately empty new draft and a known-history session whose transcript has not arrived.
  • Treat the explicit last-opened session as the chat authority when route/session persistence was torn, then heal the route after live validation.
  • Fail closed for stale, cross-profile, or unnameable legacy remote ownership and clear only provisional state owned by startup restore.
  • Add behavioral coverage for pre-profile paint, torn persistence, ownership rejection, runtime binding, fresh-route gating, cached-transcript loading, known-history loading, and exhausted recovery.

How to Test

  1. From apps/desktop, run npx vitest run --project ui --maxWorkers=4 src/app/contrib/hooks/use-desktop-integrations.test.tsx src/app/session/hooks/use-route-resume.test.tsx src/app/chat/index.test.tsx src/app/chat/thread-loading.test.ts.
  2. Run npm run typecheck.
  3. Run ESLint over the ten changed renderer and store files.

Expected result: the exact scoped cached transcript can paint before live hydration; cached text stays visible while runtime binding is pending; the composer remains gated; known-history sessions do not flash blank; new empty drafts remain usable after runtime binding; and invalid ownership fails closed.

Focused result: 4 Vitest files passed with 56 tests. Desktop renderer, Electron, and E2E typechecks passed. Affected-file ESLint and git diff --check passed.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: Windows 11

The Python suite was not run because this is a renderer-only change.

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

Screenshots / Logs

Not applicable. This changes loading behavior without changing the visual design.

@helix4u
helix4u marked this pull request as ready for review August 27, 2026 23:35
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/desktop Electron desktop app (apps/desktop/*) area/sessions Session lifecycle, resume, persistence, history sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state labels Aug 27, 2026
@helix4u
helix4u marked this pull request as draft August 27, 2026 23:44
@helix4u
helix4u marked this pull request as ready for review August 27, 2026 23:49
@helix4u
helix4u force-pushed the feat/desktop-session-resume-fast-path branch from 7032df9 to 6a7d804 Compare August 28, 2026 10:18
@helix4u

helix4u commented Aug 29, 2026

Copy link
Copy Markdown
Collaborator Author
image

@helix4u
helix4u force-pushed the feat/desktop-session-resume-fast-path branch from 6a7d804 to f217472 Compare August 29, 2026 03:31
@teknium1

teknium1 commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Thanks — reviewed against current origin/main. Main already paints the durable transcript-tail cache on cold resume (f8767d1 / #89206, profile-scoped by #94828): transcript visible at ~1.43-1.48 s, under the boot overlay until ≥2.1 s, so a pre-boot prepaint cannot be seen. The early setMessages()/$selectedStoredSessionId claim from a useLayoutEffect also bypasses the persisted-display provenance gate (b6eb17d), and the prefetched-REST early paint landed via #101227. Closing as redundant.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/sessions Session lifecycle, resume, persistence, history comp/desktop Electron desktop app (apps/desktop/*) P3 Low — cosmetic, nice to have sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants