hyperhive/frontend/packages/agent/src/index.html
iris 4ce919a19f agent-ui: running bash-tasks pill + flyout on the agent page
Adds a 'tasks' header pill (hidden at zero, like inbox/loose-ends) that
opens a side-panel flyout listing the agent's in-flight bash tasks from
GET /api/bash-tasks. Each row shows status (running/queued), task id,
elapsed time, and a truncated single-line command preview. Polled on the
same /api/state cycle as loose-ends (tasks complete async between turns, so
the count stays live); clicking the pill opens the flyout. Snapshot-only
v1 — SSE live-push is a possible follow-up.
2026-06-21 13:28:37 +02:00

122 lines
6 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</title>
<link rel="icon" type="image/svg+xml" href="icon">
<link rel="stylesheet" href="static/colors.css">
<link rel="stylesheet" href="static/theme.css">
<link rel="stylesheet" href="static/agent.css">
</head>
<body class="agent-shell">
<!-- Fixed-overlay header — see docs/web-ui.md::Per-agent page
for the three-column layout (icon · main · pills). All asset
/ API hrefs are relative — see docs/web-ui.md::Per-agent
relative paths for the document-baseURI resolution model. -->
<header class="agent-header" id="agent-header">
<img class="agent-icon" src="icon" alt="">
<div class="agent-header-main">
<div class="agent-header-row agent-header-title-row">
<h2 id="title">◆ … ◆</h2>
<!-- Meta-nav: backend-supplied links (stats / screen / forge /
…) plus a client-injected `↑ dashboard` link prepended in
setHeader so the host dashboard stays one click away
without a separate button styled differently. -->
<nav class="meta agent-nav" id="meta-links"></nav>
</div>
<!-- Hive identity line: "swarm / hive" label. Hidden until JS
populates it from /api/state (hive_name + swarm_name). -->
<div class="agent-header-row agent-hive-row">
<span class="agent-hive-label" hidden></span>
</div>
<div id="state-row" class="agent-state-row agent-header-row">
<span id="alive-badge" class="status-badge status-loading" title="harness reachability"></span>
<span id="state-badge" class="state-badge state-loading">… booting</span>
<span id="model-chip" class="model-chip" hidden></span>
<span id="effort-chip" class="effort-chip" hidden></span>
<span id="ctx-badge" class="ctx-badge" hidden title="tokens used in the current context window"></span>
<span id="cost-badge" class="ctx-badge" hidden title="cumulative tokens billed across the last turn (sum across every inference; tool-heavy turns rebill the cached prompt per call)"></span>
<span id="last-turn" class="last-turn" hidden></span>
<button type="button" id="cancel-btn" class="btn-cancel-turn" hidden>■ cancel turn</button>
</div>
</div>
<!-- Right cluster: flyout triggers + overflow menu. Pills stay
hidden until their list is non-empty; the overflow `⋯` is
always visible. Rebuild + new-session + logout live inside
it — see docs/web-ui.md::Per-agent page (Overflow button)
for the rare-destructive-extra-click rationale. -->
<div class="agent-header-pills">
<button type="button" id="inbox-pill" class="header-pill header-pill-inbox" hidden
title="open inbox flyout">
<span class="header-pill-icon" aria-hidden="true">📬</span>
<span class="header-pill-label">inbox</span>
<span class="header-pill-count" id="inbox-count">0</span>
</button>
<button type="button" id="loose-ends-pill" class="header-pill header-pill-loose" hidden
title="open loose-ends flyout">
<span class="header-pill-icon" aria-hidden="true">🪢</span>
<span class="header-pill-label">loose ends</span>
<span class="header-pill-count" id="loose-ends-count">0</span>
</button>
<button type="button" id="bash-tasks-pill" class="header-pill header-pill-tasks" hidden
title="open running bash-tasks flyout">
<span class="header-pill-icon" aria-hidden="true"></span>
<span class="header-pill-label">tasks</span>
<span class="header-pill-count" id="bash-tasks-count">0</span>
</button>
<button type="button" id="overflow-btn" class="overflow-btn"
aria-haspopup="menu" aria-expanded="false"
title="more actions"></button>
</div>
</header>
<!-- Overflow popover. Sits outside the header so the header's
`overflow: hidden`-adjacent ancestors don't clip it; positioned
in JS relative to the overflow button (top-right anchor). -->
<div id="overflow-menu" class="overflow-menu" role="menu" hidden></div>
<!-- Main content area. The terminal fills it edge-to-edge and
scrolls behind the floating header + composer. The `#status`
overlay renders only when login is required (transient first-
time-setup state); otherwise the terminal owns the screen. -->
<main class="agent-main" id="agent-main">
<div id="status" class="agent-status-overlay"></div>
<div class="terminal-wrap">
<div id="live" class="live terminal"><div class="meta">connecting…</div></div>
</div>
</main>
<!-- Fixed-overlay composer. Same frosted-glass treatment as the
header for symmetric framing. Empty until the harness sets up
the textarea via `renderTermInput`. -->
<footer class="agent-composer" id="agent-composer">
<div id="term-input" class="term-input"></div>
</footer>
<!-- Slide-in side panel. Singleton — JS swaps the title + body
and toggles `.open`. Shared shape with the dashboard's panel
(candidate for extraction into @hive/shared in a follow-up). -->
<div id="side-panel" class="side-panel" aria-hidden="true">
<div class="side-panel-backdrop" id="side-panel-backdrop"></div>
<aside class="side-panel-drawer" role="dialog" aria-modal="true"
aria-labelledby="side-panel-title">
<header class="side-panel-head">
<span class="side-panel-title" id="side-panel-title"></span>
<button type="button" class="side-panel-close" id="side-panel-close"
title="close (esc)"></button>
</header>
<div class="side-panel-body" id="side-panel-body"></div>
</aside>
</div>
<!-- Single bundled entry. esbuild folds @hive/shared/terminal.js and
the marked npm package into app.js. -->
<script type="module" src="static/app.js" defer></script>
</body>
</html>