mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-03 02:11:48 +00:00
* feat(plugins): bundle hermes-achievements, scan full session history Ships @PCinkusz's hermes-achievements dashboard plugin (https://github.com/PCinkusz/hermes-achievements) as a bundled plugin at plugins/hermes-achievements/ and fixes a bug in the scan path that made the plugin only see the first 200 sessions — making lifetime badges (50k tool calls, 75k errors, etc.) unreachable on long-running installs. Changes: - plugins/hermes-achievements/: vendor v0.3.1 verbatim (manifest, dist/, plugin_api.py, tests, docs, README). - plugins/hermes-achievements/dashboard/plugin_api.py: * scan_sessions(): limit=None now scans ALL sessions via SQLite LIMIT -1. Previously capped at 200, so users with 8000+ sessions saw ~2% of their history. * evaluate_all(): first-ever scans run in a background thread so the dashboard request path never blocks. Stale snapshots serve immediately while a background refresh runs. force=True still blocks synchronously for manual /rescan. * _build_pending_snapshot(), _start_background_scan(), _run_scan_and_update_cache(): supporting plumbing + idempotent thread spawn. - tests/plugins/test_achievements_plugin.py: new tests covering the 200-cap regression, the background-scan first-run flow, stale-serve-plus-background-refresh, forced sync rescan, and scan-thread idempotency. - website/docs/user-guide/features/built-in-plugins.md: lists hermes-achievements in the bundled-plugins table and documents API endpoints, state files, and performance characteristics. E2E validated against a real 8564-session ~6.4GB state.db: * Cold scan: 13m 19s (one-time, backgrounded — UI never blocks) * Warm rescan: 1.47s (8563/8564 sessions reused from checkpoint cache) * 57/60 achievements unlocked, 3 discovered — aggregates like total_tool_calls=259958, total_errors=164213, skill_events=368243 correctly surface lifetime badges that the 200-cap made unreachable. Original credit: @PCinkusz (MIT-licensed). Upstream repo remains the staging ground for new badges; this bundle keeps the dashboard feature parity with Hermes core changes. * feat(achievements): publish partial snapshots during cold scan Previously a cold scan on a large session DB (13min on 8564 sessions) showed zero badges for the entire duration, then every badge at once when the scan completed. A dashboard refresh mid-scan was indistinguishable from a fresh install with no history. Now the scanner publishes a partial snapshot to _SNAPSHOT_CACHE every 250 sessions, so each refresh during a cold scan surfaces more badges incrementally. Mechanism: - scan_sessions() takes an optional progress_callback fired every progress_every sessions with (sessions_so_far, scanned, total). - _compute_from_scan() is extracted from compute_all() and gains an is_partial flag that skips writing to state.json — we don't want to record unlocked_at based on a half-complete aggregate that a later session might rebalance. - _run_scan_and_update_cache() installs a publisher callback that builds a partial snapshot, marks it mode='in_progress', and writes it to the cache with age=0 so the UI keeps polling /scan-status and picks up the final snapshot when the scan completes. - Manual /rescan (force=True) disables partial publishing — the caller is blocking on the final result anyway. E2E against real 8564-session state.db (polled cache every 10s): t=10s: cache empty t=20s: 250/8564 scanned, 35 unlocked, 25 discovered t=40s: 500/8564 scanned, 42 unlocked, 18 discovered t=60s: 1000/8564 scanned, 49 unlocked, 11 discovered ... Tests: 9/9 pass (2 new — partial snapshot publication + no-persist-on-partial). Upstream unittest suite: 10/10 pass. * feat(achievements): in-progress scan banner with live % progress Previously the dashboard showed zero badges silently during long cold scans (13min on 8564 sessions). The backend was publishing partial snapshots every 250 sessions, but the bundled UI didn't surface any indicator that a scan was running — it just rendered the main page with whatever counts were currently published and no way for the user to know more progress was coming. UI changes (dist/index.js, dist/style.css): - Added a scan-in-progress banner rendered between the hero and stats when scan_meta.mode is 'pending' or 'in_progress'. Shows: BUILDING ACHIEVEMENT PROFILE… Scanned 1,750 of 8,564 sessions · 20%. Badges unlock as more history streams in. with a pulsing teal indicator and a filling teal/cyan progress bar. Disappears the moment the backend flips to 'full' or 'incremental'. - Added an auto-poller via useEffect — while scanInFlight is true the page re-fetches /achievements every 4s WITHOUT toggling the loading skeleton, so unlock counts tick up visibly without the user refreshing. The effect cleans itself up when the scan finishes. - Added refresh() (re-fetch, no loading flip) alongside the existing load() (full reload, used by the Rescan button). Attribution preserved: - Added a header comment to index.js crediting @PCinkusz (https://github.com/PCinkusz/hermes-achievements, MIT) as the original author, noting the banner is a layered addition on top of the original dist bundle. - Matching header comment in style.css, flagging the new .ha-scan-banner* rules as the local addition. Live-verified end to end: - Spun up `hermes dashboard --port 9229 --no-open` against a fresh HERMES_HOME symlinked to the real 8564-session state.db. - Opened /achievements in a browser, confirmed the banner renders with live progress: 'Scanned 1,000 of 8,564 sessions · 11%' → updates to '1,250 ... · 14%' → '1,750 ... · 20%' without user interaction, matching the backend's partial publications. - Stats row simultaneously climbed from 35 → 49 → 53 unlocked as more history streamed in. - Vision analysis of the rendered page confirms the banner styling matches the rest of the dashboard (dark card bg, teal accent, same small-caps typography, pulsing indicator reusing ha-pulse keyframes).
148 lines
4.5 KiB
Markdown
148 lines
4.5 KiB
Markdown
# Hermes Achievements
|
|
|
|
> **Bundled with Hermes Agent.** Originally authored by [@PCinkusz](https://github.com/PCinkusz) at https://github.com/PCinkusz/hermes-achievements — vendored into `plugins/hermes-achievements/` so it ships with the dashboard out-of-the-box and stays in lockstep with Hermes feature changes. Upstream repo remains the staging ground for new badges and UI iteration.
|
|
>
|
|
> When Hermes is installed via `pip install hermes-agent` or cloned from source, this plugin auto-registers as a dashboard tab on first `hermes dashboard` launch. No separate install step. See [Built-in Plugins → hermes-achievements](../../website/docs/user-guide/features/built-in-plugins.md) in the main docs.
|
|
|
|
Achievement system for the Hermes Dashboard: collectible, tiered badges generated from real local Hermes session history.
|
|
|
|

|
|
|
|
The screenshots use temporary demo tier data to show the full visual range. The plugin itself reads real local Hermes session history by default.
|
|
|
|
> **Update notice (2026-04-29):** If you installed this plugin before today, update to the latest version. The achievements scan path was refactored for much faster warm loads (snapshot cache + incremental checkpoint scan).
|
|
|
|
## What it does
|
|
|
|
Hermes Achievements scans local Hermes sessions and unlocks badges based on real agent behavior:
|
|
|
|
- autonomous tool chains
|
|
- debugging and recovery patterns
|
|
- vibe-coding file edits
|
|
- Hermes-native skills, memory, cron, and plugin usage
|
|
- web research and browser automation
|
|
- model/provider workflows
|
|
- lifestyle patterns such as weekend or night sessions
|
|
|
|
Achievements have three visible states:
|
|
|
|
- **Unlocked** — earned at least one tier
|
|
- **Discovered** — known achievement, progress visible, not earned yet
|
|
- **Secret** — hidden until Hermes detects the first related signal
|
|
|
|
Most achievements level through:
|
|
|
|
```text
|
|
Copper → Silver → Gold → Diamond → Olympian
|
|
```
|
|
|
|
Each card has a collapsible **What counts** section showing the exact tracked metric or requirement once the user wants details.
|
|
|
|
Version `0.2.x` expands the catalog to 60+ achievements, including model/provider badges such as **Five-Model Flight**, **Provider Polyglot**, **Claude Confidant**, **Gemini Cartographer**, and **Open Weights Pilgrim**.
|
|
|
|
## Examples
|
|
|
|
- Let Him Cook
|
|
- Toolchain Maxxer
|
|
- Red Text Connoisseur
|
|
- Port 3000 Is Taken
|
|
- This Was Supposed To Be Quick
|
|
- One More Small Change
|
|
- Skillsmith
|
|
- Memory Keeper
|
|
- Context Dragon
|
|
- Plugin Goblin
|
|
- Rabbit Hole Certified
|
|
|
|
## Install
|
|
|
|
Clone into your Hermes plugins directory:
|
|
|
|
```bash
|
|
git clone https://github.com/PCinkusz/hermes-achievements ~/.hermes/plugins/hermes-achievements
|
|
```
|
|
|
|
For local development, keep the repo elsewhere and symlink it:
|
|
|
|
```bash
|
|
git clone https://github.com/PCinkusz/hermes-achievements ~/hermes-achievements
|
|
ln -s ~/hermes-achievements ~/.hermes/plugins/hermes-achievements
|
|
```
|
|
|
|
Then rescan dashboard plugins:
|
|
|
|
```bash
|
|
curl http://127.0.0.1:9119/api/dashboard/plugins/rescan
|
|
```
|
|
|
|
If backend API routes 404, restart `hermes dashboard`; plugin APIs are mounted at dashboard startup.
|
|
|
|
## Updating
|
|
|
|
If you installed with git:
|
|
|
|
```bash
|
|
cd ~/.hermes/plugins/hermes-achievements
|
|
git pull --ff-only
|
|
curl http://127.0.0.1:9119/api/dashboard/plugins/rescan
|
|
```
|
|
|
|
If the update changes backend routes or `plugin_api.py`, restart `hermes dashboard` after pulling.
|
|
|
|
As of 2026-04-29, updating is strongly recommended because scan performance changed significantly:
|
|
- removed duplicate `/overview` scan path
|
|
- added cached `/achievements` snapshot
|
|
- added incremental checkpoint reuse for unchanged sessions
|
|
|
|
Achievement unlock state is stored locally in `state.json` and is not overwritten by git updates. New achievements are evaluated from your existing Hermes session history. Achievement IDs are stable and should not be renamed casually because they are the unlock-state keys.
|
|
|
|
Releases are tagged in git, for example:
|
|
|
|
```bash
|
|
git fetch --tags
|
|
git checkout v0.2.0
|
|
```
|
|
|
|
## Files
|
|
|
|
```text
|
|
dashboard/
|
|
├── manifest.json
|
|
├── plugin_api.py
|
|
└── dist/
|
|
├── index.js
|
|
└── style.css
|
|
```
|
|
|
|
## API
|
|
|
|
Routes are mounted under:
|
|
|
|
```text
|
|
/api/plugins/hermes-achievements/
|
|
```
|
|
|
|
Endpoints:
|
|
|
|
```text
|
|
GET /achievements
|
|
GET /scan-status
|
|
GET /recent-unlocks
|
|
GET /sessions/{session_id}/badges
|
|
POST /rescan
|
|
POST /reset-state
|
|
```
|
|
|
|
## Development
|
|
|
|
Run checks:
|
|
|
|
```bash
|
|
node --check dashboard/dist/index.js
|
|
python3 -m py_compile dashboard/plugin_api.py
|
|
python3 -m unittest tests/test_achievement_engine.py -v
|
|
```
|
|
|
|
## License
|
|
|
|
MIT
|