Skip to content

fix(web): rotate PTY attach token on session switch - #62058

Closed
mario841859784 wants to merge 1 commit into
NousResearch:mainfrom
mario841859784:fix/session-switch-pty-token
Closed

fix(web): rotate PTY attach token on session switch#62058
mario841859784 wants to merge 1 commit into
NousResearch:mainfrom
mario841859784:fix/session-switch-pty-token

Conversation

@mario841859784

Copy link
Copy Markdown

Problem

In the Dashboard Chat page, switching between sessions via the sidebar updates the resume query parameter but the terminal shows an empty view instead of the selected session's conversation history.

Root Cause

ptyAttachToken() in ChatPage.tsx persists the attach token in localStorage so page refreshes can reattach to the same live PTY. However, when the user switches to a different session, resume changes but the token stays the same. The server sees the identical attach token and reattaches to the old PTY instead of spawning a new one for the new session — so no history is loaded.

Fix

Add a useEffect that watches resumeParam changes. When it changes (and it's not the initial mount), call ptyAttachToken(true) to force-rotate the token, then bump reconnectNonce to trigger a fresh WebSocket connect. The server sees the new token, starts a new PTY bound to the new session, and replays its history.

Changes

  • web/src/pages/ChatPage.tsx: add prevResumeRef and a useEffect that rotates the attach token on resumeParam change.

Verification

  • tsc --noEmit passes
  • npm run build succeeds
  • Manual test: switch between sessions in the sidebar, confirm the terminal shows the correct conversation history each time.

@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/dashboard Web dashboard / control panel UI (dashboard/, landing) sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state labels Jul 10, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related to the dashboard wrong-session-on-switch cluster (#61284 issue; #61045 earliest-open frontend anchor, #60745 backend anchor, #61107 frontend sibling), all stemming from the merged keep-alive PTY regression #60515. This is not a duplicate — it uses a different mechanism: it rotates/mints a new attach token on every resume change (orphaning the old PTY), whereas #61045/#61107 namespace the token per resume target so a per-session keep-alive PTY survives switch-back. Same goal, different trade-off — flagging for a maintainer to pick between rotate-on-switch and per-session namespacing.

When switching sessions via the resume parameter, the localStorage-persisted
attach token remained unchanged, causing the server to reattach to the old
PTY instead of spawning a new one for the new session. This prevented the
previous conversation history from loading.

Now listens for resumeParam changes and forces a token rotation via
ptyAttachToken(true), triggering a fresh PTY connection that loads the
correct session history.

Fixes the issue where switching between sessions in the Dashboard Chat
page showed an empty terminal instead of the selected session's history.
@mario841859784
mario841859784 force-pushed the fix/session-switch-pty-token branch from b5ca55b to 1a7ad69 Compare July 10, 2026 12:25
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for the focused session-switch fix. The current-main premise is confirmed: ChatPage sends a persistent bare attach token (web/src/pages/ChatPage.tsx:61-81, :799-809) and the server reattaches live PTYs solely by that token (hermes_cli/web_server.py:15430-15454; hermes_cli/pty_session.py:148-166).

Problems

  • The new resume-only rotation does not cover a profile switch. scopedProfile already rebuilds the websocket and is sent to /api/pty (web/src/pages/ChatPage.tsx:294, :805-809), but the new effect does not rotate on that change and the backend registry does not scope its key by profile. A live PTY from the previous profile can still be reattached.
  • The PR has no regression coverage. Existing keep-alive coverage only asserts same-token reuse (tests/test_pty_keepalive_ws.py:7-52), not target isolation.

Suggested changes

  • Scope the attach identity by both resume and profile, preferably enforcing that invariant before PTY_REGISTRY.attach_or_spawn in hermes_cli/web_server.py:15452-15454.
  • Add tests for different resume targets and different profiles, alongside same-target reattachment.

Automated hermes-sweeper review.

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/dashboard Web dashboard / control panel UI (dashboard/, landing) P2 Medium — degraded but workaround exists sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages 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