Skip to content

fix(desktop): keep cron, messaging and search inside the active profi… - #83640

Closed
cspiritsong wants to merge 1 commit into
NousResearch:mainfrom
cspiritsong:feat/sidebar-profile-scope
Closed

cspiritsong wants to merge 1 commit into
NousResearch:mainfrom
cspiritsong:feat/sidebar-profile-scope

Conversation

@cspiritsong

Copy link
Copy Markdown

Summary

The sidebar keeps cron and messaging session caches warm by fetching them cross-profile, but in a concrete profile view those caches were rendered unfiltered: a profile like sabby showed another profile's Telegram threads in the messaging platform sections, and Pinned resolution could surface cron/messaging rows from other profiles. Session search also hit every profile's DB regardless of scope, and the per-slice messaging fetches (seed + per-platform pager) always asked for profile=all, bypassing the batched endpoint's single-scope behavior.

This PR makes every sidebar surface answer to the same profile scope as Recents:

Notes

  • No new endpoint parameters: the change follows the backend's existing single-scope semantics.
  • Preserves the reference-identity invariant: filterByProfile returns the input array unchanged when nothing is filtered, so sidebar memos don't recompute on no-ops.

Verification

  • npm run check:lint — clean (typecheck ×3, eslint 0 errors)
  • npm run test:ui — 3683 passed (413 files)
  • npm run test:desktop:platforms — skipped: needs packaged release/ artifacts from a full build (exercises installer boot, not store logic)

@alt-glitch alt-glitch added type/bug Something isn't working comp/desktop Electron desktop app (apps/desktop/*) area/profiles Multi-profile isolation, HERMES_HOME scoping area/sessions Session lifecycle, resume, persistence, history P3 Low — cosmetic, nice to have sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state labels Aug 11, 2026
@alt-glitch

Copy link
Copy Markdown
Contributor

This was generated by AI during triage.

Related: #82515 and #82575 also repair active-profile sidebar scoping. This PR adds display filtering, scoped search, and remote fan-out; maintainers should consolidate the overlapping approaches.

@cspiritsong

Copy link
Copy Markdown
Author

Thanks for the triage pass — the overlap is real, and consolidation is the right call. For orientation: #82515 scopes the messaging and cron caches, #82575 scopes sidebar data broadly, and this PR covers the full chain — messaging list, cron list, Pinned rows, search, and the remote-backend fan-out paths — with a test at each layer, including the non-GUI gateway paths where the same cross-profile leak appears.

Happy to cooperate whichever way the maintainers prefer: rebase this into a delta on top of whichever PR is chosen as the base, trim it to only the parts the others don't cover, or close it if another PR supersedes it.

@Enough1122

Copy link
Copy Markdown
Contributor

AI code review — automated review for reference, author can ignore or act on any point.

fix(desktop): keep cron, messaging and search inside the active profile

  1. apps/desktop/electron/main.tscronSp/messagingSp now use recentsProfile for the remote fan-out. Please verify recentsProfile is always defined at that point; if it can be undefined, sliceParams(..., { profile: undefined }) would emit a different query than the intended profile scope.
  2. apps/desktop/src/hermes.ts searchSessions() — the client now sends ?profile=..., but this diff contains no backend change. Please confirm the local /api/sessions/search endpoint honors the profile param and that the batched sidebar endpoint scopes cron + messaging slices too (the triage note about fix(desktop): scope sidebar messaging and cron caches by profile #82515/fix(desktop): scope sidebar data to active profile #82575 consolidation is relevant here). If the backend ignores profile, the serverMatchesScope guard still renders results, but they are not actually scoped.
  3. session-index.ts filterByProfile() — untagged rows map to 'default', relying on the profile store normalizing profileScope identically (case/whitespace). If the store can emit a different normalized form (e.g. empty string for default), filtered rows silently vanish. A test asserting filterByProfile against the real normalized scope value would pin this.
  4. Pinned rows: sessionByAnyId now indexes only profile-visible sessions, so a pin pointing at another profile’s session disappears in single-profile view (intended per the PR title), but nothing hints why the pinned row vanished. A small count/note when pins are hidden by scope would prevent “my pin disappeared” reports.

@teknium1

Copy link
Copy Markdown
Collaborator

The unfiltered-cache rendering and pinned-resolution halves landed on main via #87566 (itself a salvage of your #83708 — thanks again). What survives here: session-search profile scoping (session-index.ts + the electron search path). Leaving open for that half.

@badiyee85

Copy link
Copy Markdown
Contributor

Thanks for clarifying. Understood that #83640 is being kept open for the remaining session-search profile-scoping change. I’ll leave it open.

@cspiritsong

Copy link
Copy Markdown
Author

Addressed the review points in rebased commit 8016cfac6b40a71ef38e5c699a5f2249b42966c5.

This PR is now intentionally the session-search profile-scoping delta only:

  • The cache-rendering, pinned-resolution, and stale-profile-write work is already on main via fix(desktop): scope messaging to active remote profile (salvage of #83708) #87566, so those overlapping changes were removed from this branch.
  • The duplicate filterByProfile() helper was removed; the current canonical filterSessionsByProfileScope() path owns profile normalization, including legacy untagged rows as default.
  • The existing backend GET /api/sessions/search accepts profile and opens the corresponding profile database via _open_session_db_for_profile(profile). The Desktop client now passes the concrete active profile and leaves explicit All Profiles unscoped.
  • serverMatchesScope clears/ignores a late response from a previous profile after a scope switch, so stale search results cannot repaint the new workspace.
  • The former recentsProfile/remote fan-out and pinned-row concerns are no longer part of this PR’s diff; current main owns those paths.

Verification on the rebased tree:

  • npm run typecheck — passed
  • Focused profile-scope + REST tests — 32 passed
  • npm run lint0 errors (110 existing warnings)
  • Diff against current upstream — 3 files, +40/-7

Please re-review the updated search-only head.

Route concrete-profile search through the selected profile state.db, preserve All Profiles behavior, and discard stale full-text results after a profile switch.
@cspiritsong
cspiritsong force-pushed the feat/sidebar-profile-scope branch 3 times, most recently from 95c0407 to 922d3fd Compare August 19, 2026 08:15
@cspiritsong

Copy link
Copy Markdown
Author

I’ve rebased this PR onto the live upstream main (63565fa) and narrowed it to the remaining session-search profile-scoping fix. The cache-rendering and pinned-resolution work is intentionally not reintroduced here; that work is already on main via #87566.

The remaining gap is that Desktop search still calls /api/sessions/search without a profile when the user is browsing a concrete profile. The backend already accepts profile and opens that profile’s state.db, so this update wires the existing contract through the Desktop search path.

This update:

  • sends the concrete active profile to session search;
  • leaves All Profiles unscoped;
  • clears old FTS hits and ignores late responses after a profile switch.

Verification on the repaired current-main file set:

  • focused Hermes REST test: 31 passed
  • Desktop typecheck: passed
  • Desktop lint: 0 errors (126 warnings)
  • current diff: 3 files, +40/-7

Please review this remaining search-only delta.

@cspiritsong

Copy link
Copy Markdown
Author

Rebased onto current main and reopened as #114102.

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/*) P3 Low — cosmetic, nice to have 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.

5 participants