refactor(desktop): derive working/attention session sets from $sessionStates - #66454
Merged
Merged
Conversation
…nStates $workingSessionIds and $attentionSessionIds were independently maintained atoms that updateSessionState had to manually keep in sync with the session cache (paired setSessionWorking/setSessionAttention calls, plus a rotation special-case in ensureSessionState). Make them computed() projections of $sessionStates instead, so the data flow is one-directional: gateway event → cache → $sessionStates → computed views. Transition side-effects (watchdog arm/disarm, settle grace, unread marker, compression id rotation signal) move into handleTransition, fired from publishSessionState by diffing previous vs next — one choke point instead of per-callsite bookkeeping. The watchdog's force-clear reaches the cache through setWatchdogClearFn rather than a listener set. Also: - clearAllSessionStates disarms all watchdog timers and drops settle-grace entries so a gateway switch can't leak stale timers or keep-set rows - dropSessionState disarms the dropped runtime's watchdog timer - watchdog tests now exercise the real timer→callback wiring instead of manually simulating the clear
This was referenced Jul 18, 2026
Merged
17 tasks
Closed
4 tasks
Gravezzz
pushed a commit
to Gravezzz/hermes-agent
that referenced
this pull request
Jul 21, 2026
…-status-sync refactor(desktop): derive working/attention session sets from $sessionStates
randlee
pushed a commit
to randlee/hermes-agent
that referenced
this pull request
Aug 11, 2026
…-status-sync refactor(desktop): derive working/attention session sets from $sessionStates
prmartinow
pushed a commit
to prmartinow/hermes-agent
that referenced
this pull request
Aug 26, 2026
…-status-sync refactor(desktop): derive working/attention session sets from $sessionStates
melon-xf
added a commit
to melon-xf/hermes-agent
that referenced
this pull request
Sep 3, 2026
…-status-sync refactor(desktop): derive working/attention session sets from $sessionStates
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
$workingSessionIdsand$attentionSessionIdswere independently-maintainedatoms that
updateSessionStatehad to manually keep in sync with the sessioncache — paired
setSessionWorking/setSessionAttentioncalls on every statetick, plus a rotation special-case in
ensureSessionState. This is the classic"projection atom drifted from the cache" bug class: two sources of truth that
must agree but nothing enforces agreement.
This PR makes them pure
computed()projections of$sessionStates,so the data flow is one-directional:
All transition side-effects (watchdog arm/disarm, settle grace, unread
marker, compression id rotation signal) move into a single
handleTransitionfunction fired from
publishSessionStateby diffing previous vs next — onechoke point instead of per-callsite bookkeeping.
The watchdog's force-clear (8 min of stream silence) now reaches the cache
through a
setWatchdogClearFncallback the cache wires on mount, instead ofa listener set.
Related Issue
No issue — self-driven refactor found during review of the session-status
data flow.
Type of Change
Changes Made
store/session-states.ts$workingSessionIds/$attentionSessionIdsare nowcomputed($sessionStates)projections — deleted the independently-maintained atoms + their setters (setWorkingSessionIds,setAttentionSessionIds,setSessionWorking,setSessionAttention)handleTransition(prev, next, runtimeId), called frompublishSessionStateclearAllSessionStates()now disarms all watchdog timers and drops settle-grace entries — a gateway switch can no longer leak stale 8-min timers or let the old gateway's sessions squat in the sidebar merge keep-set for 30sdropSessionState()disarms the dropped runtime's watchdog timersetWatchdogClearFnreplacesonSessionWatchdogClearlistener patternstore/session.ts— removed ~180 lines of now-dead watchdog/settle/attention/unread code that moved tosession-states.tsapp/session/hooks/use-session-state-cache.tsupdateSessionStateno longer manually callssetSessionWorking/setSessionAttention/noteSessionActivity—publishSessionStatehandles all transitionsensureSessionStatecreates a new state object on stored-id rotation (instead of mutating in place) soupdateSessionStatecan detect the transitionsetWatchdogClearFneffectImport sites — 8 files updated to import
$workingSessionIds/$attentionSessionIds/getRecentlySettledSessionIdsfromsession-statesinstead ofsessionHow to Test
npm run typecheck— both tsconfigs cleannpm run lint— eslint cleannpm test— 214 files, 1792 passed / 1 skippedsetWatchdogClearFn) instead of manually simulating the clear — and a new test assertsclearAllSessionStatesdisarms all timersChecklist
Code
npm testand all tests passpublishSessionState(the real public surface), plus a newclearAllSessionStatesdisarm testDocumentation & Housekeeping