Watch
0
0
Fork
You've already forked hyperhive
0
hyperhive/frontend/packages/agent/src/stats.html
iris a5914274ba feat(stats): surface "favorite tools" (most-run bash commands) on /stats
The surfacing half of the per-agent favorite-tools stat. Reads a
`bash_commands(ts INTEGER NOT NULL, head TEXT NOT NULL)` table from the
per-agent turn-stats.sqlite — one row per bash task, written by
hive-bash-mcp (the capture half, landing separately) — and rolls up the
top-10 command heads for a doughnut, mirroring the existing
tool_breakdown.

- stats.rs: new `Snapshot.bash_breakdown` + `read_bash_breakdown()`.
  The read is guarded: a missing `bash_commands` table (capture hasn't
  shipped / agent hasn't run a bash task) maps to an empty list, never
  an error — the snapshot degrades gracefully. Unit tests cover both
  the absent-table and populated cases (incl. window cutoff + ordering).
- frontend: a "favorite tools (bash)" doughnut card on the agent /stats
  page, kept hidden until bash_breakdown has data so it never shows a
  permanently-empty doughnut while capture is pending.

Part of #1433 (does not close it — pairs with the hive-bash-mcp capture
half). Inert until the capture lands; merge order with it is irrelevant.
2026-06-06 00:53:12 +02:00

50 lines
2.9 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>hyperhive agent — stats</title>
<link rel="icon" type="image/svg+xml" href="icon">
<link rel="stylesheet" href="static/agent.css">
</head>
<body>
<pre class="banner">░▒▓█▓▒░ … ░▒▓█▓▒░ hyperhive ag3nt · stats ░▒▓█▓▒░</pre>
<div class="stats-nav">
<a id="back-link" href="./">← live</a>
<a id="dashboard-link" href="#">dashboard</a>
<h2 id="title">◆ … ◆</h2>
</div>
<div class="window-tabs" id="window-tabs">
<button data-w="1h">last 1h</button>
<button data-w="4h">last 4h</button>
<button data-w="24h" class="active">last 24h</button>
<button data-w="3d">last 3d</button>
<button data-w="7d">last 7d</button>
<button data-w="30d">last 30d</button>
</div>
<div class="summary" id="summary"></div>
<div class="stats-grid">
<div class="stats-card wide"><h3>turns per bucket</h3><div class="chart-wrap"><canvas id="chart-turns"></canvas></div></div>
<div class="stats-card wide"><h3>turn duration (ms) — p50 / p95 / avg</h3><div class="chart-wrap"><canvas id="chart-duration"></canvas></div></div>
<div class="stats-card wide"><h3>context tokens (last inference per turn) — avg / max</h3><div class="chart-wrap"><canvas id="chart-ctx"></canvas></div></div>
<div class="stats-card wide"><h3>token cost per bucket (sum across inferences)</h3><div class="chart-wrap"><canvas id="chart-cost"></canvas></div></div>
<div class="stats-card wide"><h3>turns by model per bucket — model drives token cost</h3><div class="chart-wrap"><canvas id="chart-model"></canvas></div></div>
<div class="stats-card"><h3>top tools</h3><div class="chart-wrap"><canvas id="chart-tools"></canvas></div></div>
<!-- "favorite tools": most-run shell commands. Hidden until the
bash_commands capture (hive-bash-mcp) has recorded data, so the
card never shows a permanently-empty doughnut. -->
<div class="stats-card" id="card-bash" hidden><h3>favorite tools (bash)</h3><div class="chart-wrap"><canvas id="chart-bash"></canvas></div></div>
<div class="stats-card"><h3>wake source mix</h3><div class="chart-wrap"><canvas id="chart-wake"></canvas></div></div>
<div class="stats-card"><h3>result mix</h3><div class="chart-wrap"><canvas id="chart-result"></canvas></div></div>
<div class="stats-card wide"><h3>result trend per bucket — errors / rate-limits / compactions over time</h3><div class="chart-wrap"><canvas id="chart-result-trend"></canvas></div></div>
</div>
<!-- Chart.js is now bundled into stats.js by esbuild (npm dep
chart.js@4.4.4), so the page works offline / on operator
machines without internet egress. No SRI hash to maintain. -->
<script type="module" src="static/stats.js" defer></script>
</body>
</html>