Skip to content

fix(desktop): scope messaging and cron session fetches to active profile - #60688

Closed
Ahmett101 wants to merge 2 commits into
NousResearch:mainfrom
Ahmett101:fix/60678-profile-scope-messaging-cron
Closed

fix(desktop): scope messaging and cron session fetches to active profile#60688
Ahmett101 wants to merge 2 commits into
NousResearch:mainfrom
Ahmett101:fix/60678-profile-scope-messaging-cron

Conversation

@Ahmett101

Copy link
Copy Markdown
Contributor

Summary

When using the Hermes Desktop with multiple profiles, the Messaging and Cron sidebar sections leaked sessions from all profiles regardless of which profile was active. The main Recents list correctly scoped to the active profile, but refreshCronSessions, refreshMessagingSessions, and loadMoreMessagingForPlatform all hardcoded profile='all'.

Changes

apps/desktop/src/app/session/hooks/use-session-list-actions.ts: Applied the same profileScope === ALL_PROFILES ? 'all' : profileScope resolution pattern already used by refreshSessions to the other three functions. Added profileScope to their useCallback dependency arrays.

How to Test

Manual: Switch profiles in Desktop App (Ctrl+D) and verify Messaging/Cron sidebar sections only show sessions from the active profile, not all profiles.

Checklist

  • Follows Conventional Commits
  • Changes scoped to this fix only (single file, 9 insertions / 6 deletions)
  • Cross-platform impact: Desktop (TypeScript frontend only)
  • profile-safe paths: N/A
  • .env not used for non-credential settings

Closes #60678

refreshCronSessions, refreshMessagingSessions, and
loadMoreMessagingForPlatform all hardcoded profile='all' in their
listAllProfileSessions() calls, causing sessions from all profiles
to leak into the sidebar regardless of which profile is active.

Apply the same profileScope resolution pattern already used by
refreshSessions to the other three functions, and add profileScope
to their useCallback dependency arrays.

Closes NousResearch#60678
@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 8, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related: #52910 (broader competing PR — same fix relocated into desktop-controller.tsx+hermes.ts, also scopes messaging sessions), #44157 (messaging-only), #42654 (cron-only), and issue #60678 which this closes. Same goal (scope Messaging/Cron sidebar fetches to the active profile) via a different code site (use-session-list-actions.ts) — not a duplicate; a maintainer picks the canonical approach.

@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 narrowing this to the extracted session-list hook. The premise is confirmed on current main: apps/desktop/src/app/session/hooks/use-session-list-actions.ts:86, :102, and :126 still pass 'all', while Recents resolves profileScope at :174.

Problems

  • The new profile-specific callbacks need stale-response protection. refreshSessions invokes them after its own awaited request (use-session-list-actions.ts:191-193); a prior-profile closure may therefore start a late fetch after a switch. Recents guards its writes with refreshSessionsRequestRef (:180-188), but the cron and messaging setters do not (:90, :110-113).
  • Please add regression coverage for concrete-profile and ALL_PROFILES arguments across all three changed fetch paths. Current helper coverage only asserts the default all-profile request (apps/desktop/src/hermes.test.ts:51-60).

Suggested changes

  • Discard stale cron/messaging responses with a request generation or current-scope check.
  • Add a hook-level test covering profile changes and a delayed old response.

Automated hermes-sweeper review.

try {
const result = await listAllProfileSessions(MESSAGING_SECTION_LIMIT, 1, 'exclude', 'recent', 'all', {
const sessionProfile = profileScope === ALL_PROFILES ? 'all' : profileScope
const result = await listAllProfileSessions(MESSAGING_SECTION_LIMIT, 1, 'exclude', 'recent', sessionProfile, {

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.

This fetch is now profile-specific, but it has no generation/current-scope guard. refreshSessions can invoke an old closure after awaiting its own request (use-session-list-actions.ts:191-193), so a late previous-profile response can overwrite the new profile's messaging rows. Please discard stale responses here and in the analogous cron/pagination paths.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 10, 2026
@CaptainHowlingMadMurdockBot

Copy link
Copy Markdown

Addressing @teknium1's review comment:

Added per-function useRef request counters (mirroring the existing refreshSessionsRequestRef pattern) to refreshCronSessions, refreshMessagingSessions, and loadMoreMessagingForPlatform. Each call increments the counter before the await; after the await, stale responses where ref.current !== requestId are discarded, preventing a late previous-profile response from overwriting the active profile's sidebar rows.

diff --git a/apps/desktop/src/app/session/hooks/use-session-list-actions.ts b/apps/desktop/src/app/session/hooks/use-session-list-actions.ts
index 373618ad..63295faf 100644
--- a/apps/desktop/src/app/session/hooks/use-session-list-actions.ts
+++ b/apps/desktop/src/app/session/hooks/use-session-list-actions.ts
@@ -77,6 +77,9 @@ export function useSessionListActions({ profileScope }: UseSessionListActionsArg
 export function useSessionListActions({ profileScope }: UseSessionListActionsArgs) {
   const refreshSessionsRequestRef = useRef(0)
+  const cronSessionsRequestRef = useRef(0)
+  const messagingSessionsRequestRef = useRef(0)
+  const loadMoreMessagingRequestRef = useRef(0)
 
   const refreshCronSessions = useCallback(async () => {
+    const requestId = cronSessionsRequestRef.current + 1
+    cronSessionsRequestRef.current = requestId
     try {
       const sessionProfile = profileScope === ALL_PROFILES ? 'all' : profileScope
       const { sessions } = await listAllProfileSessions(...)
-      setCronSessions(prev => (sameCronSignature(prev, sessions) ? prev : sessions))
+      if (cronSessionsRequestRef.current === requestId) {
+        setCronSessions(prev => (sameCronSignature(prev, sessions) ? prev : sessions))
+      }
     } catch { }

   const refreshMessagingSessions = useCallback(async () => {
+    const requestId = messagingSessionsRequestRef.current + 1
+    messagingSessionsRequestRef.current = requestId
     try {
       ...
-      setMessagingSessions(...)
-      setMessagingTruncated(...)
+      if (messagingSessionsRequestRef.current === requestId) {
+        setMessagingSessions(...)
+        setMessagingTruncated(...)
+      }
     } catch { }

   const loadMoreMessagingForPlatform = useCallback(async (platform) => {
+    const requestId = loadMoreMessagingRequestRef.current + 1
+    loadMoreMessagingRequestRef.current = requestId
     ...
     const result = await listAllProfileSessions(...)
+    if (loadMoreMessagingRequestRef.current !== requestId) return
     ...
   })

Full patch available at: CaptainHowlingMadMurdockBot@63295fa

The branch fix/60678-profile-scope-messaging-cron on my fork contains the full commit. Happy to rebase onto the PR branch if the maintainer can grant temporary push access, or this can be cherry-picked.

TypeScript typecheck (tsc -p . --noEmit) passes with zero errors.

@teknium1 teknium1 added area/sessions Session lifecycle, resume, persistence, history area/profiles Multi-profile isolation, HERMES_HOME scoping labels Jul 19, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Status update: the desktop cron helper scoping landed via #67493/#67602 and list filtering via #67615, but this PR's target — scoping the messaging/cron session fetches in use-session-list-actions — is a different call-site set that those merges don't cover (except the cron-jobs refresh, which #67615 now scopes). Leaving open; a rebase onto current main narrowing to the session-fetch call sites would make this reviewable.

@teknium1

Copy link
Copy Markdown
Contributor

Resolved on main by #87566, which consolidated this PR's fix with your Co-authored-by credit preserved in the merged commits. Thank you!

@teknium1 teknium1 closed this Aug 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/profiles Multi-profile isolation, HERMES_HOME scoping area/sessions Session lifecycle, resume, persistence, history comp/desktop Electron desktop app (apps/desktop/*) needs-decision Awaiting maintainer decision before any implementation P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades 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.

fix: scope messaging and cron session fetches to active profile

4 participants