Adds a Window::All option to the per-agent stats page and the hive-wide
rollup, selectable as a new 'all' tab on both.
- hive-ag3nt (per-agent, time-bucketed): All ranges from MIN(started_at)
to now (fallback to now on an empty table) with an adaptive bucket
width laddered by span — hourly <=2d, daily <=90d, weekly <=2y, 30-day
beyond — so the trend series stays bounded (~<=104 buckets) at any age.
- hive-c0re (swarm rollup, not time-bucketed): All sets from=0 so the
aggregate covers every recorded turn across all agents.
- frontend: an 'all' button on both the agent stats and dashboard hive
stats window selectors (createTabStrip + fetch already pass the window
string through, so no JS change needed).
cargo check passes on both crates; FE builds clean. Fixes#1919.
Per mara: the agent sub-pages should use the same back-link nav as the
dashboard's standalone pages, while the live terminal page stays as-is (no
tabs of each other, not an SPA).
Pull the shared `@hive/shared/chrome.css` into the agent bundle (via agent.css's
existing @import line; esbuild inlines it into the one dist/static/agent.css all
agent pages link), then:
- stats.html: replace the ASCII banner + bespoke `.stats-nav` with the shared
`page-header` (← live back-link + dashboard link + title). Keeps the #back-link
/ #dashboard-link / #title ids stats.js drives, and the time-window picker +
charts below are unchanged.
- screen.html: replace the bespoke `#toolbar` nav with the same `page-header`
(← agent back-link + title), keeping the fit / match / debug controls + the
status text in the bar.
The live terminal (index.html) is untouched. The now-unused `.banner` /
`.stats-nav` / `#toolbar` rules in agent.css are left for a follow-up prune to
keep this diff focused on the markup. Agent build clean.
Closes#1874.
Replaces the agent stats page's bespoke window-tab click handler with the
shared createTabStrip (@hive/shared/tabs.js). The selector is now
hash-routed — #1h / #24h / … become deep-linkable and survive
back/forward navigation.
- window buttons use data-tab (was data-w); the strip resolves them by
that convention and toggles .hive-tab--active + aria-selected.
- onShow(w) sets currentWindow + reloads stats; the strip's initial show
fires it once, so the explicit loadStats() in DOMContentLoaded is
dropped (avoids a double fetch).
- the selector keeps its distinct pill look — agent.css now targets
.window-tabs button.hive-tab--active (was .active), not the shared
.hive-tab text-tab base. It's a pure data-selector with no panes;
createTabStrip skips the absent [data-tab-pane] gracefully.
Behaviour-preserving; aria-selected is now standardised on the buttons.
Split the palette into two standalone stylesheets:
- colors.css — the 16 base16 slots (--base00..--base0F). This is the
entire theme swap contract; a generator (e.g. a stylix base16 scheme,
which is natively base00-base0F) replaces only this file.
- theme.css — the semantic layer (--bg, --purple, …) derived from the
base16 slots via var()/color-mix. Never changes on a swap.
Every page links colors.css then theme.css; theme.css does NOT @import
colors.css (that would re-bake the slots into it) — they're separate
dist outputs so a swap touches just colors.css. Pixel-identical refactor:
base16 defaults are Catppuccin Mocha and the three off-slot vars
(--crust, --muted, --subtext0) derive via color-mix reproducing their
exact prior hexes.
Wires colors.css through both build.mjs CSS entry lists, the
@hive/shared exports map, and all 7 page templates. css-vars.md + the
frontend.nix output-list comment updated.
Phase 1 of stylix integration (#1457): extract the Catppuccin palette
into a dedicated, separately-linked stylesheet so a theme swap can
replace just that file without rebuilding the rest of the frontend.
- shared/src/theme.css (new): the `:root` palette, moved out of
base.css (which now holds only the body typography it references).
- shared/package.json: export `./theme.css`.
- dashboard/src/theme.css + agent/src/theme.css (new): one-line
re-exports of @hive/shared/theme.css so each package's esbuild emits
its own standalone `dist/static/theme.css` (palette is NOT inlined
into the page bundles).
- both build.mjs: add theme.css to the CSS build list.
- every page (dashboard index/flow/logs, agent index/stats/screen):
link `theme.css` first, ahead of the page CSS, so the `:root` vars
resolve for everything.
- docs/web-ui/css-vars.md: document the split + the no-rebuild rationale.
Behaviour-neutral — same colours, just relocated. Verified both
`npm run build` outputs: theme.css emits standalone (383b) with the
palette; no `--*` palette defs duplicated into common.css/agent.css.
Phase 2 (nix derivation that swaps theme.css from stylix colours) is a
follow-up; touches nix/frontend.nix, coordinating with damocles.
Part of #1457.
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.
First slice of #1424 (per-agent /stats enrichments):
- Backend: add per-bucket result_counts to the stats Snapshot (mirrors
model_counts), so result outcomes can be charted over time, not just
as a window total.
- Frontend: two new summary chips — cache hit-rate % (cached input vs
all input-side tokens) and avg tokens/turn — both derived from the
existing per-bucket token sums. Plus a stacked result-trend chart so
error / rate-limit / compaction spikes are visible across the window.
Hive-wide aggregate, cost estimate, and container resource load land in
follow-up PRs.
Without a viewport meta tag, some browsers (notably Firefox with
Fingerprinting Protection active) internally read screen.availWidth /
screen.availHeight to compute the default viewport size, producing the
console warning 'Fingerprinting Protection is altering screen.availWidth
and screen.availHeight'.
Fix:
- Add <meta name="viewport" content="width=device-width, initial-scale=1">
to all five pages that were missing it (dashboard index/flow/logs, agent
index/stats). screen.html already had it.
- Replace window.innerWidth with document.documentElement.clientWidth in
the side-panel drag-resize code in common.js. clientWidth returns the
actual CSS layout viewport width and is not rounded by Firefox's
Fingerprinting Protection, making the drag calculation correct even
with privacy.resistFingerprinting enabled.
stats.html had a <style> block with all its page-specific CSS inline.
Move to agent.css under a '--- /stats page ---' section, renaming
the generic .grid/.card/.empty-note classes to .stats-grid/.stats-card/
.stats-empty-note to avoid future collisions with other agent pages.
Per mara on #14: 'make agent page not assume root path, links / api
calls need to be relative'. atlas's nginx side (#15) will mount the
per-agent UI at a prefix like /agent/<name>/ instead of its own
port; for the page to keep working under that prefix, every
in-page reference needs to resolve document-relative rather than
root-anchored.
Converted in this pass:
- HTML <link>/<script>/<img>/<a> hrefs in index.html, stats.html,
screen.html: '/icon' → 'icon', '/static/agent.css' →
'static/agent.css', back links '/' → './'.
- app.js fetch() targets ('/api/state' → 'api/state', /api/cancel,
/api/loose-ends, etc.), form actions ('/login/start', '/send'),
EventSource urls ('/events/stream', '/events/history').
- stats.js fetch() targets.
- screen.html WebSocket URL: was hardcoded as
ws(s)://host/screen/ws; now derived from document.baseURI via
new URL('screen/ws', document.baseURI) so the gateway prefix
flows through.
Slash-command labels (/cancel, /compact, …) and the dashboard-port
link (different port, intentionally absolute) intentionally
untouched.
Added a new 'Per-agent relative paths' section to docs/web-ui.md
covering the rationale + the trailing-slash gotcha (sub-pages like
/stats must NOT have a trailing slash, or 'static/app.js' resolves
under /stats/ instead of replacing the segment).
Functional code unchanged; build clean. Damocles + atlas can
proceed with the backend / nginx side without depending on this
landing first, but once both ship the agent page works under the
gateway-prefixed URL without further changes.
refs #14
Phase 1 of the backend/frontend code split (#273). Additive — no
existing code is touched; the legacy hive-c0re/assets, hive-ag3nt/
assets and hive-fr0nt/assets trees stay in place until the Rust
cutover later in this branch.
Layout:
frontend/package.json npm workspaces root
frontend/packages/shared/ @hive/shared
src/{base,terminal}.css + terminal.js (ES module)
src/index.js re-exports terminal.js
frontend/packages/dashboard/ @hive/dashboard
src/{index.html, app.js, dashboard.css} ported from hive-c0re/assets
build.mjs esbuild config → dist/
frontend/packages/agent/ @hive/agent
src/{index,stats,screen}.html + agent.css
+ {app,stats}.js ported from hive-ag3nt/assets
build.mjs esbuild config → dist/
Changes vs the existing assets:
- terminal.js is an ES module exporting { create, linkify } instead
of assigning to window.HiveTerminal. The dashboard / agent app.js
files re-expose them on window so the IIFE bodies keep working
unchanged through Phase 1; the global aliases can be dropped in a
follow-up once the IIFEs are unwrapped.
- marked is imported from the marked@4.3.0 npm package (replacing
the vendored hive-fr0nt/assets/marked.umd.js bundle).
- chart.js is imported from chart.js@4.4.4 (replacing the jsDelivr
CDN script tag on the per-agent stats page — page now works
offline / on operator machines without internet egress).
- dashboard.css and agent.css both gain @import lines at the top
that pull base.css + terminal.css from @hive/shared, replacing
the runtime string concatenation in serve_css.
- index.html / stats.html collapse from three / two script tags to
one type="module" tag pointing at the bundled output.
package-lock.json is intentionally omitted from this commit — npm
isn't available in the iris container yet (approval pending) and the
lockfile will land in the next commit on this branch once the
toolchain is in place. The PR will not be opened until it's there.
Phase 2 (nix derivations), Phase 3 (container plumbing + the
hyperhive.frontend.extraFiles option for per-agent layering), and
Phase 4 (Rust cutover to tower_http::ServeDir, delete hive-fr0nt
+ legacy assets dirs) land as follow-up commits on this same
branch.
Refs #273.