Skip to content

feat: add Hermes Agent session collector (hardened, closes #167) - #168

Open
kouyichi wants to merge 4 commits into
graykode:mainfrom
kouyichi:feat/hermes-collector
Open

kouyichi wants to merge 4 commits into
graykode:mainfrom
kouyichi:feat/hermes-collector

Conversation

@kouyichi

@kouyichi kouyichi commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Implements the hardened Hermes Agent collector proposed in #167. Closes #167.

What it does

Hermes Agent (Nous Research) sessions are discovered from the tui_gateway.slash_worker --session-key <id> processes Hermes spawns per active session — parsed from the already-scanned SharedProcessData command lines (token parsing only, no string building). Session metadata, token counters and the transcript tail are read directly from ~/.hermes/state.db (or HERMES_HOME/state.db) through an in-process, read-only rusqlite connection with bundled SQLite — no sqlite3 CLI or Python required on any platform.

Feature Hermes Agent
Session Discovery ✅
Token Tracking (in/out/cache) ✅
Context Window % ✅ (model lookup table)
Status Detection (Think/Exec/Wait) ✅ (transcript tail + CPU)
Current Task ✅
Child Processes / Ports ✅
Git Status ✅
Rate Limit ❌ (Hermes doesn't expose it)

Hide via hidden_agents = ["hermes"] like any other agent.

How it addresses the security feedback that closed #139

The previous attempt (PR #139) was closed over four concerns. This implementation addresses each:

  1. No dynamic code generation. No Python, no string-built SQL, no shell surface anywhere. All queries use bound parameters against a SQLITE_OPEN_READ_ONLY connection; process matching parses tokens from command lines already scanned by the shared snapshot.
  2. No predictable temp files. Everything is read in-process; nothing is written.
  3. Privacy/redaction model from the start. Every DB-sourced string — title, cwd, chat tail, tool-call arguments, initial prompt, first assistant text — passes through sanitize_terminal_text → redact_secrets → truncation exactly like the OpenCode/Claude collectors. Tool results (role='tool') and internal session_meta rows never enter the chat tail.
  4. Fail-closed + clippy clean. Symlinked/missing/unopenable DBs yield no Hermes sessions; cargo clippy --all-targets -- -D warnings passes.

DB rows and transcript tails are cached and refreshed only on the slow tick (~10s), matching the OpenCodeCollector pattern.

Verification

Tested live against running Hermes sessions (Linux): abtop --once --json reports each active session with correct PID ↔ session matching, model, token counters, context %, status (Waiting vs Executing with open tool calls), project dir, prompt summary, tool timeline, and redacted chat tail. 10 new unit tests; full suite: 211 passed.

Note: rusqlite (bundled) is a new dependency — the alternative (sqlite3 CLI like OpenCode) would silently fail on machines without the binary, which is why the in-process reader was chosen. Happy to switch if you prefer the CLI pattern.

kouyichi and others added 4 commits August 6, 2026 12:51
Discover Hermes Agent sessions from tui_gateway.slash_worker processes
(--session-key in already-scanned command lines) and read session
metadata, token counters and the redacted transcript tail from
~/.hermes/state.db via an in-process read-only rusqlite connection
(bundled SQLite).

Addresses the security feedback that closed graykode#139:
- No dynamic code generation: no Python, no string-built SQL, no shell
  interpolation anywhere; DB access is a readonly rusqlite connection
  with bound parameters only.
- No temp files: everything is read in-process.
- Follows the existing collector privacy model from the start: every
  DB-sourced string (title, cwd, chat tail, tool args) passes through
  sanitize_terminal_text -> redact_secrets -> truncation.
- Fail-closed on symlinked/missing DBs; DB reads cached on the slow
  tick like OpenCodeCollector.

Supports session discovery, token tracking (input/output/cache),
status detection (Thinking/Executing/Waiting from transcript tail +
CPU), context window % (model lookup table), child processes/ports,
git status. Rate limits are N/A for Hermes.

Closes graykode#167
AgentSession gained a launch_surface field (Cli/App/Ide) while this branch was
open, so the collector no longer compiled. Hermes sessions are matched by their
worker process (python -m tui_gateway.slash_worker --session-key <id>), a plain
CLI invocation: Hermes ships no desktop-app bundle and no editor extension that
vendors that worker, so the collector reports LaunchSurface::Cli.
@kouyichi

Copy link
Copy Markdown
Contributor Author

Kept current with main: 4b96568 merged in (14 commits, plain merge, no rebase, no force-push).

One adaptation was needed. AgentSession gained a launch_surface field (Cli/App/Ide) while this branch was open, so the collector did not compile. Hermes sessions here are matched by their worker process (python -m tui_gateway.slash_worker --session-key <id>), a plain CLI invocation — Hermes ships no desktop-app bundle and no editor extension that vendors that worker — so the collector reports LaunchSurface::Cli (src/collector/hermes.rs, commit 9eca894).

Verified on the merge:

  • cargo test → 231 passed; 3 failed. The three (ui::tests::compact_sizes_render_sessions_instead_of_too_small, ui::tests::desktop_default_detail_shows_chat_instead_of_timeline, ui::tests::fmt_age_buckets) fail identically on a clean checkout of upstream 4b96568 in this environment: they compare rendered frames, and this shell renders the box-drawing/Hidden by multi-width symbols row differently. They are pre-existing and unrelated to the collector.
  • cargo clippy --all-targets -- -D warnings → clean.
  • cargo fmt --check reports the same diff on upstream main as on this branch (the repo is not rustfmt-clean under this toolchain), so no formatting was folded into the PR.

Ready for review when you have a moment.

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.

Feature request: Hermes Agent session monitoring (hardened design, revisit #139)

1 participant