Insights & updates¶
Usage analytics for a stats screen, and the self-update control. Verified against api/routes.py, api/updates.py.
Insights¶
GET /api/insights¶
Query: days (optional, default 30, clamped 1–365).
Response
{
"period_days": 30,
"total_sessions": 42, "total_messages": 310,
"total_input_tokens": 0, "total_output_tokens": 0,
"total_cache_read_tokens": 0, "total_cache_hit_percent": 12.5,
"total_tokens": 0, "total_cost": 0.0,
"models": [
{ "model": "…", "sessions": 3, "input_tokens": 0, "output_tokens": 0,
"cache_hit_percent": null, "total_tokens": 0, "cost": 0.0,
"session_share": 50, "token_share": 40, "cost_share": 30 }
],
"daily_tokens": [
{ "date": "2026-06-01", "input_tokens": 0, "output_tokens": 0,
"cache_read_tokens": 0, "sessions": 0, "cost": 0.0 }
],
"activity_by_day": [ { "day": "Mon", "sessions": 5 } ],
"activity_by_hour": [ { "hour": 0, "sessions": 0 } ]
}
Aggregates WebUI sessions and CLI sessions within the window. models is sorted by cost descending. daily_tokens has one zero-filled entry per day in range. *_share fields are integer percents; costs are rounded to 6 decimal places. Everything a usage dashboard needs (totals, per-model breakdown, daily trend, day-of-week and hour-of-day activity) is in this one response.
Updates¶
Lets a client show "an update is available" and apply it — Hermes updates itself from its git remotes.
GET /api/updates/check¶
Cache-only (no network). ?simulate=1 (localhost only) returns a fake payload for UI testing.
Response
If the update-check setting is off →{ "disabled": true }.
RepoInfo — { "name": "webui"|"agent", "behind": int|null, "current_sha", "latest_sha", "branch", "repo_url", "compare_url", "dirty" }. Variants: { "no_git": true, "behind": null } (no repo), { "error", "stale_check": true } (fetch failed), { "ignored": true } (agent update suppressed).
To force a live check (network fetch),
POST /api/updates/checkwith{ "force": true }.
POST /api/updates/apply¶
Body { "target": "webui"|"agent" } (else 400).
Response (success) — { "ok": true, "message", "target", "restart_scheduled": true, "gateway_restart"?, "stash_conflict"? }. This schedules a self-restart of the server — a client should expect the connection to drop and reconnect shortly.
Response (failure) — { "ok": false, "message", "conflict"?, "diverged"?, "stash_conflict"? }. A dirty tree is auto-stashed then popped; the pull is fast-forward-only, so unresolved conflicts / divergence / a missing upstream each return an actionable message. A concurrent update returns { "ok": false, "message": "Update already in progress" }.
Restart on apply
Applying an update restarts the server process. Design the client to tolerate the drop: poll /api/auth/status (or /api/settings for the new webui_version) until the server is back, then resume.