agent: wire Header/StatusChips to real /api/state polling

- useAgentState hook: polls GET /api/state (4s interval for now — see
  its file comment for why this isn't yet the SSE-triggered + login-
  only-timer cadence the old page used; that lands with the live
  stream + term-input commit, which is when clobbering the operator's
  in-progress input actually becomes a risk).
- format.ts: fmtTokens/fmtAge, same output shapes as app.js's.
- modelEffort.ts: POST /api/model + /api/effort (same-origin, plain
  fetch).
- dashboardBase.ts + pauseAction.ts: pause/resume POST to the
  *dashboard's* origin via a real <form> submit, kept unchanged from
  app.js — a cross-origin fetch needs CORS headers hive-c0re doesn't
  send, a form submit sidesteps that same as it already did.
- Root.tsx: wires it all together, including app.js's "any non-online
  status forces the turn-state badge to offline" behavior.

Screenshot-verified against a mock GET /api/state (real fetch, not
hardcoded props) + the real agent.css/theme.css/colors.css.

Builds + tsc --noEmit clean.
This commit is contained in:
iris 2026-08-28 02:07:17 +02:00
commit 908f479372
6 changed files with 239 additions and 26 deletions

View file

@ -0,0 +1,16 @@
// Pause/resume POST to the *dashboard's* origin (hive-c0re, not this
// agent's own `/api/*`) — see dashboardBase.ts. A real `<form>` submit
// rather than `fetch`, kept unchanged from app.js: accessed directly
// (not through the gateway proxy), the dashboard is a different origin/
// port, and a cross-origin `fetch` POST needs the response readable
// under CORS to report success/failure — a full navigation form submit
// sidesteps that (the browser reloads to whatever the endpoint
// returns) without needing hive-c0re to grow CORS headers for what's
// otherwise a same-origin action behind the gateway.
export function submitPauseResume(dashboardBase: string, label: string, verb: 'pause' | 'resume'): void {
const form = document.createElement('form');
form.method = 'POST';
form.action = `${dashboardBase}api/${verb}/${label}`;
document.body.appendChild(form);
form.submit();
}