Skip to content

fix: purge missing inflight sessions - #2129

Merged
1 commit merged into
nesquena:masterfrom
Michaelyklam:freebuff/issue-2092-inflight-purge
May 12, 2026
Merged

fix: purge missing inflight sessions#2129
1 commit merged into
nesquena:masterfrom
Michaelyklam:freebuff/issue-2092-inflight-purge

Conversation

@Michaelyklam

@Michaelyklam Michaelyklam commented May 12, 2026

Copy link
Copy Markdown
Contributor

Thinking Path

  • Hermes WebUI relies on INFLIGHT to track active streaming sessions in the browser.
  • The stale-entry cleanup only removed entries for sessions still present in _allSessions and marked non-streaming.
  • Deleted, archived, or filtered-out sessions are absent from _allSessions, so their INFLIGHT entries were never visited as non-streaming and could accumulate indefinitely.
  • This PR changes the cleanup to iterate INFLIGHT keys and explicitly drop ids absent from the current session list while preserving still-streaming sessions.

What Changed

Why It Matters

Long-running browser tabs no longer keep ghost INFLIGHT entries after sessions are deleted, archived, or filtered out of the current list. This keeps future INFLIGHT iteration from seeing stale session ids.

Verification

  • git diff --check
  • node --check static/sessions.js
  • env -u HERMES_CONFIG_PATH /home/michael/.hermes/hermes-agent/venv/bin/python -m pytest tests/test_inflight_purge_missing_sessions.py tests/test_issue2066_stale_sidebar_spinner.py -q — 6 passed

Risks / Follow-ups

  • Risk is low: the change is scoped to stale in-memory cleanup and introduces no new state.
  • The regression test is source-level, matching existing lightweight frontend test patterns; if the helper is refactored heavily later, the test may need updating.

Model Used

  • Freebuff/Codebuff free mode via local Hermes maintainer automation.
  • Backend model: minimax/minimax-m2.7.
  • GPT-5.5 via Hermes Agent performed queue stewardship, review gate, and publication.

Closes #2092

@Michaelyklam
Michaelyklam force-pushed the freebuff/issue-2092-inflight-purge branch from 818865b to dd543e4 Compare May 12, 2026 09:57
@nesquena-hermes

Copy link
Copy Markdown
Collaborator

Summary

Read the diff at PR head dd543e41 (static/sessions.js:246-275, worktree at /tmp/wt-cron-2129), plus the new tests/test_inflight_purge_missing_sessions.py and the updated tests/test_issue2066_stale_sidebar_spinner.py. The change implements exactly the first proposed shape in issue #2092: iterate INFLIGHT keys (not _allSessions), drop entries whose sid is absent from the current session list, preserve actively-streaming sessions, and continue to purge non-streaming present sessions.

Code reference

static/sessions.js:257-273 at PR head:

for (const sid of Object.keys(INFLIGHT)) {
  if (!sessionsById.has(sid)) {
    // Session is absent from _allSessions — it was deleted / archived /
    // filtered and can never stream again, so drop the entry.
    delete INFLIGHT[sid];
    if (typeof clearInflightState === 'function') clearInflightState(sid);
    continue;
  }
  const s = sessionsById.get(sid);
  if (!s.is_streaming) {
    // Session exists but is not streaming — purge it.
    delete INFLIGHT[sid];
    if (typeof clearInflightState === 'function') clearInflightState(sid);
  }
  // Sessions that exist and are still streaming are preserved.
}

Diagnosis

This matches the bug shape described in #2092 exactly. The original guard was if (s && !s.is_streaming) — the s && short-circuit meant absent-from-_allSessions sids were silently retained. The fix inverts the iteration to walk INFLIGHT keys instead of _allSessions, with the missing-from-map check happening before the streaming check.

One subtlety worth confirming: _allSessions is populated from GET /api/sessions in renderSessionList() (static/sessions.js:1762-1772). When the user toggles the "show archived" filter or the all-profiles toggle off, _allSessions does contain only the visible scope, so an active stream that's been archived mid-flight would be purged from INFLIGHT here. In practice that's the right behavior (the user can't see the spinner anyway, and on un-archive a new SSE subscription is established via loadSession / checkInflightOnBoot). The PR description and issue #2092 both treat "filtered out" as a valid purge case, so this is intentional.

Test plan

The new tests/test_inflight_purge_missing_sessions.py is a parse-and-substring check on the function body — three assertions covering:

  1. sessionsById.has(sid) check is present
  2. The absent-session delete runs without an is_streaming guard (verified by inspecting the body between the has() check and the first delete)
  3. Exactly two delete INFLIGHT[sid] statements exist (one per guarded path)

The updated tests/test_issue2066_stale_sidebar_spinner.py now spins Node and runs the actual function against a synthetic _allSessions + INFLIGHT, verifying running-session survives, done-session and unknown-session are both cleared. That's the right shape — the existing #2066 contract is preserved and the new #2092 case is exercised.

Recommendation

LGTM. The change is surgical, the tests cover both regression cases, and the comment update on lines 246-253 explains the broadened scope clearly. CI should be green; no further work needed.

@nesquena-hermes nesquena-hermes closed this pull request by merging all changes into nesquena:master in 6297443 May 12, 2026
pull Bot pushed a commit to TKaxv-7S/hermes-webui that referenced this pull request May 12, 2026
fix: purge missing inflight sessions (closes nesquena#2092)
SysAdminDoc pushed a commit to SysAdminDoc/hermes-webui that referenced this pull request Jun 26, 2026
fix: purge missing inflight sessions (closes nesquena#2092)
bernyforce pushed a commit to bernyforce/hermes-webui that referenced this pull request Jul 29, 2026
fix: purge missing inflight sessions (closes nesquena#2092)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Follow-up: _purgeStaleInflightEntries doesn't handle missing-from-list sessions (deleted/archived/filtered)

2 participants