Skip to content

feat(dashboard): cross-profile sessions, profile-aware status, offline platforms, time filter - #31427

Closed
02356abc wants to merge 2 commits into
NousResearch:mainfrom
02356abc:feat/dashboard-cross-profile-v2
Closed

feat(dashboard): cross-profile sessions, profile-aware status, offline platforms, time filter#31427
02356abc wants to merge 2 commits into
NousResearch:mainfrom
02356abc:feat/dashboard-cross-profile-v2

Conversation

@02356abc

Copy link
Copy Markdown
Contributor

Summary

This PR adds multi-profile support to the Hermes web dashboard:

  1. Cross-profile session aggregation — Sessions page now aggregates across all profiles when "All Profiles" is selected, with correct pagination and counts.
  2. Profile-specific filtering — Dropdown filter to view sessions from a single profile.
  3. Time-based filtering — 7D / 30D / 90D / ALL buttons filter sessions by started_at.
  4. Profile-aware Connected Platforms — Status page shows platforms for the selected profile (or aggregate), with offline platforms displayed instead of hidden.
  5. Offline platform display — Platforms that are configured but not currently connected show as "offline" with a gray indicator.

Backend changes

  • gateway/status.py: read_runtime_status() accepts optional status_path for reading other profiles' state.
  • hermes_cli/profiles.py: ProfileInfo gains gateway_state, gateway_platforms, gateway_updated_at.
  • hermes_cli/web_server.py:
    • get_sessions(), search_sessions() accept profile and since parameters.
    • get_status() accepts profile parameter for profile-specific status.
    • Fixes SessionDB path caching bug by passing db_path directly.

Frontend changes

  • web/src/lib/api.ts: getSessions() and searchSessions() accept profile and since.
  • web/src/pages/SessionsPage.tsx: Profile dropdown + time filter buttons moved to page content area.

Test plan

  • Aggregate session count matches sum of per-profile counts
  • Pagination works correctly across profiles
  • Time filter counts match SQL COUNT(*) WHERE started_at >= ?
  • Profile-specific status shows correct platforms
  • Offline platforms display with gray indicator
  • Search works with profile + time filter combined

🤖 Generated with Claude Code

@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/cli CLI entry point, hermes_cli/, setup wizard labels May 24, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Resubmission of closed #31413 (same author). Also competes with #9496 for the same feature scope. Tracking issue: #10674.

@02356abc

Copy link
Copy Markdown
Contributor Author

Why this approach

Re: #10674 — this PR follows a single-process with request-scoped profile context model rather than a supervisor + worker architecture. Three reasons:

  1. Simplicity over indirection — the dashboard already runs as a single process. Adding a supervisor layer with per-profile worker processes would introduce significant complexity (worker lifecycle, proxying, port management) for marginal isolation benefit. Instead, we scope all file/DB access per-request via explicit paths, achieving the same isolation guarantees without extra processes.

  2. Sessions-first incremental delivery — this PR limits changes to the Sessions page, the highest-traffic dashboard surface. Analytics and Status profile filters are intentionally deferred to keep the review surface small. This mirrors the cron cross-profile approach (#27568), which was merged as a focused increment.

  3. Time filter for performance at scale — the since parameter pushes time filtering to SQL (WHERE started_at >= ?), making single-profile queries ~12x faster and aggregate queries ~3x faster thanks to idx_sessions_started. With 1000+ sessions across profiles, this avoids fetching thousands of rows into memory only to discard them.

Isolation mechanism

Unlike the cron implementation, which mutates global module variables under a lock, this PR passes db_path directly to SessionDB. Each profile's state.db is opened independently and closed immediately — no shared mutable state, no locks needed.

02356abc added 2 commits May 24, 2026 22:36
…based filtering

- gateway/status.py: read_runtime_status() accepts optional status_path for
  reading other profiles' gateway_state.json
- hermes_cli/profiles.py: ProfileInfo gains gateway_state, gateway_platforms,
  gateway_updated_at; add _read_profile_runtime_status()
- hermes_cli/web_server.py:
  - get_status(profile): profile-aware status with aggregate mode (all),
    specific profile mode, and backward-compatible default mode
  - _get_status_for_profile_dir(): read status from arbitrary profile dir
  - get_sessions(profile, since): cross-profile session listing with
    time-based filtering (7D/30D/90D/ALL)
  - search_sessions(profile, since): cross-profile session search with
    time-based filtering
  - _list_sessions_for_profile(): per-profile session read using
    SessionDB(db_path=...) instead of os.environ mutation (fixes caching bug)
  - _search_sessions_for_profile(): per-profile search with since filter
  - _session_profile_home() / _annotate_session(): profile resolution helpers
  - _profile_to_dict(): expose gateway fields to frontend

Co-Authored-By: 02356abc <198679067+02356abc@users.noreply.github.com>
…platform display

- web/src/lib/api.ts:
  - getStatus(profile): pass profile to /api/status endpoint
  - getSessions(profile, since): cross-profile + time filter params
  - searchSessions(profile): cross-profile search param
  - SessionInfo / SessionSearchResult: add profile, profile_name,
    hermes_home, is_default_profile fields
- web/src/components/PlatformsCard.tsx: add offline state mapping
  (outline badge, WifiOff icon, muted-foreground color)
- web/src/pages/SessionsPage.tsx:
  - Profile dropdown selector (All profiles / specific profile)
  - Time filter buttons (ALL / 7D / 30D / 90D), default 30D
  - Profile badges on session rows
  - Pass selectedProfile to getStatus, getSessions, searchSessions
  - Filter placement in page content area (below title)

Co-Authored-By: 02356abc <198679067+02356abc@users.noreply.github.com>
@02356abc
02356abc force-pushed the feat/dashboard-cross-profile-v2 branch from cdae7c6 to 8f2fa63 Compare May 24, 2026 14:41
@02356abc

Copy link
Copy Markdown
Contributor Author

Closing to re-evaluate approach. Will reopen or create a new PR after further refinement.

@02356abc 02356abc closed this May 24, 2026
@02356abc
02356abc deleted the feat/dashboard-cross-profile-v2 branch May 24, 2026 14:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants