Skip to content

fix(desktop): force-include pinned sessions in session list via include_ids - #43167

Closed
hrnbld wants to merge 1 commit into
NousResearch:mainfrom
hrnbld:main
Closed

fix(desktop): force-include pinned sessions in session list via include_ids#43167
hrnbld wants to merge 1 commit into
NousResearch:mainfrom
hrnbld:main

Conversation

@hrnbld

@hrnbld hrnbld commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Problem

Pinned sessions that aged off the 50-session recency page silently vanished from the Desktop sidebar. The root cause is twofold:

  1. Initial fetch: refreshSessions only loads the 50 most recent sessions from /api/profiles/sessions. Pinned sessions outside that window are never fetched.

  2. Merge limitation: mergeSessionPage() can only preserve sessions already in the in-memory previous list — it cannot resurrect sessions that were never loaded. The pinned-IDs-as-keepIds mechanism inherited this limitation.

Fix

Backend (hermes_state.py):

  • Added include_ids parameter to list_sessions_rich that resolves each ID to its live compression tip (via get_compression_tip + _get_session_rich_row) and prepends it to the result, deduped by both live ID and _lineage_root_id.

API (web_server.py):

  • Threaded include_ids query param through both /api/sessions and /api/profiles/sessions endpoints.

Frontend (hermes.ts, desktop-controller.tsx):

  • listAllProfileSessions now accepts optional includeIds: string[] and appends &include_ids=... to the request URL.
  • refreshSessions and loadMoreSessionsForProfile pass $pinnedSessionIds so pinned conversations are always included regardless of how long ago they were last active.

Testing

  • Verified all 8 locally pinned sessions (some as old as May 11) are now force-included in the session list response.
  • Desktop app rebuilt successfully; pinned sessions appear immediately on restart.

…de_ids

Pinned sessions that aged off the 50-session recency page silently
vanished from the Desktop sidebar because the initial page load never
included them and mergeSessionPage can only preserve rows already in
the in-memory list — it cannot conjure sessions that were never fetched.

Add an include_ids parameter to list_sessions_rich (hermes_state.py) that
resolves each id to its live compression tip and prepends it to the
result, then thread it through /api/sessions, /api/profiles/sessions,
and the Desktop frontend (listAllProfileSessions, refreshSessions).

The frontend now passes $pinnedSessionIds on every refresh so pinned
conversations are always present regardless of how long ago they were
last active.

Closes the 'pinned sessions disappear until refresh — and even refresh
does not bring them back when they are past the recency window' bug.
@alt-glitch alt-glitch added type/bug Something isn't working comp/gateway Gateway runner, session dispatch, delivery P3 Low — cosmetic, nice to have labels Jun 10, 2026
@alt-glitch alt-glitch added comp/desktop Electron desktop app (apps/desktop/*) comp/dashboard Web dashboard / control panel UI (dashboard/, landing) sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state and removed comp/gateway Gateway runner, session dispatch, delivery labels Jun 26, 2026

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for tracing the bounded-page versus renderer-cache failure mode. The premise still holds on current main: refreshSessions fetches a bounded profile list at apps/desktop/src/app/session/hooks/use-session-list-actions.ts:176, while mergeSessionPage can only retain rows already in previous (apps/desktop/src/store/session.ts:188-195).

Problems

  • In this PR, get_profiles_sessions passes include_ids to each profile list at hermes_cli/web_server.py:1935, but then globally sorts merged by last_active and slices it to the requested limit at lines 1961-1963. A pinned conversation old enough to be off the recency page is therefore sorted out again, so the Desktop aggregate endpoint still does not hydrate it.
  • The diff does not add a cold-start/reconnect regression test. Existing coverage at apps/desktop/src/store/session.test.ts:124 only proves preservation of an already-loaded pinned row.

Suggested changes

  • Keep explicitly hydrated rows outside the normal recency window, dedupe by lineage, and append/merge them after pagination.
  • Port the caller change to apps/desktop/src/app/session/hooks/use-session-list-actions.ts; commit 25c7900fb moved the relevant controller code there.

Automated hermes-sweeper review.

Comment thread hermes_cli/web_server.py
include_archived=include_archived,
archived_only=archived_only,
order_by_last_active=order == "recent",
include_ids=include_list,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

list_sessions_rich() prepends these rows per profile, but this endpoint then globally sorts merged by last_active and truncates it at lines 1961-1963. An old pinned session is therefore ejected from the aggregate response again; carry hydrated rows outside the recency window and dedupe them before returning.

@OutThisLife

Copy link
Copy Markdown
Collaborator

Superseded by #74234, which makes pins server-owned so they survive paging and sync between apps. Your work is carried in it and you're credited as a co-author — thank you.

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) comp/desktop Electron desktop app (apps/desktop/*) P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform 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.

4 participants