fix(dashboard): force fresh PTY spawn when resume target changes - #64444
fix(dashboard): force fresh PTY spawn when resume target changes#64444daniloneto wants to merge 2 commits into
Conversation
Three-part fix for dashboard session resume after keep-alive PTY:
1. **Backend (pty_session.py)**: Add method to
PtySessionRegistry — discards an existing PTY session so
is forced to create a new one with updated
argv/env.
2. **Backend (web_server.py)**: Two changes in :
- Guard behind inside the
block — prevents from dropping an
explicit resume target ( from
sidebar click).
- Call when
is set — ensures the registry spawns a fresh PTY
with the new instead of reattaching the
stale session.
3. **Frontend (ChatPage.tsx)**: Track previous via
ref and set when the sidebar switches to a
different session, so the WebSocket connection carries
.
Without (1)+(2), every resume-after-the-first silently lands on
the original session's PTY regardless of which session was clicked
in the sidebar — the PTY registry returns the existing session
(whose env var points at the first session)
and the new argv is never used.
Closes NousResearch#63701.
Related: this PR now uses target-aware PTY identity (resume session + profile) so same-target reconnects preserve the live PTY while changed targets respawn it. It remains complementary to #61313 and #62058, and related to the closed earlier teardown variant #63731; its separate dashboard-backup argument fix is bundled and needs maintainer review. |
|
All three are needed — the PR combines two orthogonal bugs under one label: Frontend-only approaches (#61313 force-fresh, #62058 token rotation, #61107 namespacing) fix session switch in PTY registry but do not fix the server-side Backend-only ( This PR: frontend sends Would be happy to drop any part that the maintainer considers redundant once they pick a direction — just explaining why they're together here. |
|
Thanks for tracing the attach-token/root-environment mismatch; the current-main premise is real: Problems
Suggested changes
Automated hermes-sweeper review. |
The old code called PTY_REGISTRY.close_if_exists(attach_token) whenever resume was not None. This broke transient-drop reconnects: the browser reconnects with the same ?attach= AND same ?resume= (they stay in the URL), but the unconditional close killed the PTY on every WS reconnect, forcing a pointless respawn. Fix moves the teardown decision into attach_or_spawn via a target_id param. - attach_or_spawn stores the target on PtySession and compares it on reuse - Same attach_key + same target_id → reattach (transient drop, refresh) - Same attach_key + different target_id → close old, spawn fresh (sidebar session switch, profile change) - No target_id → backward-compat reattach Also removes the dead 'if not resume: resume = None' branch.
Target-aware PTY identity (replaces close_if_exists approach)The previous approach called FixMoves the teardown decision inside
Target identity includes both resume session and profile — switching sessions or profiles via the dashboard triggers a fresh PTY; transient drops and page refreshes reattach to the living one. Tests
|
Bug
When resuming a session in the web dashboard (sidebar click or Sessions → History → "Resume in Chat"), every resume-after-the-first silently lands on the original session's PTY regardless of which session was clicked. Only the first session after a dashboard restart works correctly.
Root cause: the PTY keep-alive registry (
PtySessionRegistry.attach_or_spawn) returns the existing session when the sameattach_tokenis presented. The old session was spawned withHERMES_TUI_RESUMEpointing at the first session, so every subsequent reattach ignores the new?resume=parameter in the WebSocket URL.Fix (3 files, 3 parts)
1.
hermes_cli/pty_session.py—close_if_existsNew method on
PtySessionRegistrythat closes and removes a session by key. Allows the keep-alive path to discard a stale PTY beforeattach_or_spawnreuses it.2.
hermes_cli/web_server.py— Two guards inpty_wsforce_freshguard (line 15718): Restrictresume = Noneto only fire when there is no explicit?resume=param. Without this, a sidebar click sending?resume=TARGET_ID&fresh=1has its resume target silently dropped byforce_fresh.close_if_existscall (line 15773): Whenresumeis non-None, close any existing PTY session in the registry before callingattach_or_spawn. This forces a fresh PTY spawn with the updatedargv/env (containing the correctHERMES_TUI_RESUME).3.
web/src/pages/ChatPage.tsx— Resume param trackingTrack the previous
resumeParamvia a ref. When it changes (user clicks a different session in the sidebar), setforceFreshPtyRef.current = trueso the next WebSocket connection carriesfresh=1.Testing
?resume=SESSION_B→ session B loads ✅Closes #63701.