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.
113 lines
5.5 KiB
HTML
113 lines
5.5 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/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="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="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>
|