Skip to content

fix(desktop): keep queued drains out of the foreground session on session switch - #73875

Merged
OutThisLife merged 2 commits into
mainfrom
bb/review-69049
Jul 29, 2026
Merged

OutThisLife merged 2 commits into
mainfrom
bb/review-69049

Conversation

@OutThisLife

Copy link
Copy Markdown
Contributor

A queue drain pairs two identifiers that move on different clocks: the queue key flips with the route, while the explicit runtime id lags a resume behind. Mid-switch the composer can fire a drain carrying session B's queue key alongside session A's runtime id, and prompt.submit then lands B's queued prompt — and its entire answer turn — inside A. The existing guard only covered the case where the runtime id came through null; this closes the remaining case where it is non-null and stale.

Supersedes #69049 by @theone139344, whose diagnosis and fix this builds on directly.

The fix

use-prompt-actions/submit.ts treated an explicit options.sessionId as authoritative and never checked it against getRuntimeIdForStoredSession. Queued sends now verify the pair against the central runtime↔stored-session binding:

  • pair matches the binding → proceed unchanged
  • binding exists but differs → adopt the bound runtime id
  • no binding recorded → drop the stale id and re-home through the stored-session resume path, the same fallback the background drain already uses
  • identity pairs (storedSessionId === sessionId, a brand-new unsaved chat) pass through untouched

The check is scoped to fromQueue. Only a drain pairs ids from two clocks; every other explicit-target caller resolves both in the same tick and is authoritative by construction. A slash skill dispatch into a fresh ⌘T tab passes the same shape — sessionId=tab-runtime, storedSessionId=tab-stored, no binding recorded yet — so an unscoped check nulls the target and silently drops the kickoff.

Changes from #69049

  • gate the binding check on fromQueue, with the scoping invariant covered by a test
  • refresh the two drain tests for queued: true, which prompt.submit started sending for queued drains in ab68c5e after that branch was cut
  • fix the mock signatures so tsc --noEmit is clean

Verification

use-prompt-actions, use-background-queue-drain, composer-queue, and use-session-state-cache — 182 passing. tsc -p apps/desktop --noEmit clean.

theone139344 and others added 2 commits July 29, 2026 00:03
…sion switch

A queue drain pairs two identifiers from different clocks: the queue key
(flips with the route) and the explicit runtime id (lags a resume behind).
Mid-switch the composer can fire a drain with storedSessionId=B but
sessionId=A-runtime, and prompt.submit then lands B's queued prompt — and
its whole answer turn — inside session A.

Make the central runtime binding authoritative for queued sends: when the
explicit runtime id no longer matches the binding recorded for the target
stored session, adopt the binding (or drop to the stored-id resume path
when none exists yet). The identity pair (storedSessionId === sessionId)
is the fresh-chat fallback and stays untouched.

Tests: re-home-via-resume and rebind-to-central-runtime; existing
background-drain and sleep/wake cases declare central bindings explicitly.
Null-fallback guard already on main; this PR is the remaining half.
The binding check landed unscoped, so it fired for every caller passing a
sessionId/storedSessionId pair — not just queue drains. A slash skill
dispatch into a fresh ⌘T tab passes exactly that shape (sessionId=tab
runtime, storedSessionId=tab stored) with no central binding recorded yet,
so the check nulled the target and the kickoff dropped instead of landing
in the tab.

Only a drain pairs identifiers from two different clocks; every other
explicit-target caller resolves both ids in the same tick and is
authoritative by construction. Gate on fromQueue and add the scoping
invariant as a test.

Also refresh the two drain tests for `queued: true`, which prompt.submit
started sending for queued drains in ab68c5e after this work branched.

Co-authored-by: theone139344 <theone139344@users.noreply.github.com>
@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

૮ >ﻌ< ა ci review

ran on 8830f22

ℹ️ Info

Desktop E2E visual evidence · View test artifacts · View job

1 visual diff.

inline evidence upload failed.

Failed to upload diff-665a0833239e-onboarding-overlay-diff.png with gh image (exit code 1): Error uploading /home/runner/work/_temp/e2e-evidence/diff-665a0833239e-onboarding-overlay-diff.png: step 0 (get upload token): uploadToken not found on repo page — do you have write access to NousResearch/hermes-agent? (or, if NousResearch enforces SAML SSO, authorize at https://github.com/orgs/NousResearch/sso)

@OutThisLife
OutThisLife merged commit 9bf1f73 into main Jul 29, 2026
34 checks passed
@OutThisLife
OutThisLife deleted the bb/review-69049 branch July 29, 2026 06:42
@alt-glitch alt-glitch added type/bug Something isn't working comp/desktop Electron desktop app (apps/desktop/*) P3 Low — cosmetic, nice to have labels Jul 29, 2026
randlee pushed a commit to randlee/hermes-agent that referenced this pull request Aug 11, 2026
fix(desktop): keep queued drains out of the foreground session on session switch
33hodl pushed a commit to 33hodl/hermes-agent that referenced this pull request Aug 12, 2026
fix(desktop): keep queued drains out of the foreground session on session switch
prmartinow pushed a commit to prmartinow/hermes-agent that referenced this pull request Aug 26, 2026
fix(desktop): keep queued drains out of the foreground session on session switch
melon-xf added a commit to melon-xf/hermes-agent that referenced this pull request Sep 3, 2026
fix(desktop): keep queued drains out of the foreground session on session switch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/desktop Electron desktop app (apps/desktop/*) P3 Low — cosmetic, nice to have type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants