treefmt: apply prettier
Pure `nix fmt` output from the commit before this one — no hand edits. 203 files: 52 md, 42 tsx, 32 js, 32 css, 21 ts, 13 html, 8 json, 3 mjs. Reproduce with `nix develop -c nix fmt` on the parent commit; the result should be byte-identical to this tree. None of the 13 `.prettierignore` entries appears here — verified by intersecting the changed-file list against the ignore file, with a control proving the intersection finds a match when one exists.
This commit is contained in:
parent
5d24bedd60
commit
39b95c2ede
203 changed files with 10090 additions and 6085 deletions
|
|
@ -22,9 +22,9 @@
|
|||
// pure positioning rule which is now generic and lives in `<hive-menu>`'s
|
||||
// own shadow-scoped `.menu-dropdown`).
|
||||
|
||||
import { el } from '@hive/shared/dom.js';
|
||||
import { themedConfirm, themedToast } from '@hive/shared/modal.js';
|
||||
import '@hive/shared/hive-menu.js'; // registers <hive-menu> — side-effect import
|
||||
import { el } from "@hive/shared/dom.js";
|
||||
import { themedConfirm, themedToast } from "@hive/shared/modal.js";
|
||||
import "@hive/shared/hive-menu.js"; // registers <hive-menu> — side-effect import
|
||||
|
||||
// Single-agent POST helper shared by all menu items. `flags` is an object
|
||||
// of boolean query params to set truthy (e.g. `{ graceful: true }` or
|
||||
|
|
@ -34,25 +34,32 @@ import '@hive/shared/hive-menu.js'; // registers <hive-menu> — side-effect imp
|
|||
async function agentMenuPost(actionPath, name, body, flags) {
|
||||
const params = new URLSearchParams();
|
||||
for (const [k, v] of Object.entries(flags || {})) {
|
||||
if (v) params.set(k, 'true');
|
||||
if (v) params.set(k, "true");
|
||||
}
|
||||
const qs = params.toString();
|
||||
const url = actionPath + encodeURIComponent(name) + (qs ? '?' + qs : '');
|
||||
const url = actionPath + encodeURIComponent(name) + (qs ? "?" + qs : "");
|
||||
try {
|
||||
const resp = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: body ? { 'Content-Type': 'application/x-www-form-urlencoded' } : {},
|
||||
method: "POST",
|
||||
headers: body
|
||||
? { "Content-Type": "application/x-www-form-urlencoded" }
|
||||
: {},
|
||||
body: body ? new URLSearchParams(body) : undefined,
|
||||
redirect: 'manual',
|
||||
redirect: "manual",
|
||||
});
|
||||
const ok = resp.ok || resp.type === 'opaqueredirect'
|
||||
|| (resp.status >= 200 && resp.status < 400);
|
||||
const ok =
|
||||
resp.ok ||
|
||||
resp.type === "opaqueredirect" ||
|
||||
(resp.status >= 200 && resp.status < 400);
|
||||
if (!ok) {
|
||||
const text = await resp.text().catch(() => '');
|
||||
themedToast('action failed: ' + resp.status + (text ? '\n\n' + text : ''), { type: 'error' });
|
||||
const text = await resp.text().catch(() => "");
|
||||
themedToast(
|
||||
"action failed: " + resp.status + (text ? "\n\n" + text : ""),
|
||||
{ type: "error" },
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
themedToast('action failed: ' + err, { type: 'error' });
|
||||
themedToast("action failed: " + err, { type: "error" });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -67,40 +74,58 @@ class HiveAgentMenu extends HTMLElement {
|
|||
|
||||
const { c, forgeBase } = this._opts || {};
|
||||
|
||||
const btn = el('button', {
|
||||
type: 'button',
|
||||
class: 'agent-menu-btn',
|
||||
title: `actions for ${c.name}`,
|
||||
'aria-label': `actions for ${c.name}`,
|
||||
'aria-haspopup': 'menu',
|
||||
'aria-expanded': 'false',
|
||||
}, '⋮');
|
||||
const dropdown = el('ul', { class: 'agent-menu-dropdown', role: 'menu' });
|
||||
const btn = el(
|
||||
"button",
|
||||
{
|
||||
type: "button",
|
||||
class: "agent-menu-btn",
|
||||
title: `actions for ${c.name}`,
|
||||
"aria-label": `actions for ${c.name}`,
|
||||
"aria-haspopup": "menu",
|
||||
"aria-expanded": "false",
|
||||
},
|
||||
"⋮",
|
||||
);
|
||||
const dropdown = el("ul", { class: "agent-menu-dropdown", role: "menu" });
|
||||
|
||||
const close = () => this._menu.close();
|
||||
|
||||
const menuItem = (label, opts) => {
|
||||
const li = el('li', { role: 'presentation' });
|
||||
const item = el('button', {
|
||||
type: 'button',
|
||||
class: 'agent-menu-item',
|
||||
role: 'menuitem',
|
||||
}, label);
|
||||
item.addEventListener('click', async () => {
|
||||
const li = el("li", { role: "presentation" });
|
||||
const item = el(
|
||||
"button",
|
||||
{
|
||||
type: "button",
|
||||
class: "agent-menu-item",
|
||||
role: "menuitem",
|
||||
},
|
||||
label,
|
||||
);
|
||||
item.addEventListener("click", async () => {
|
||||
close();
|
||||
let flags = {};
|
||||
if (opts.confirm) {
|
||||
const checkboxes = [];
|
||||
if (opts.graceful) {
|
||||
checkboxes.push({ name: 'graceful', label: opts.gracefulLabel || 'stop gracefully — let the agent finish its turn and flush state before the container stops' });
|
||||
checkboxes.push({
|
||||
name: "graceful",
|
||||
label:
|
||||
opts.gracefulLabel ||
|
||||
"stop gracefully — let the agent finish its turn and flush state before the container stops",
|
||||
});
|
||||
}
|
||||
if (opts.paused) {
|
||||
checkboxes.push({ name: 'paused', label: opts.pausedLabel || 'start paused — come up without driving turns until resumed' });
|
||||
checkboxes.push({
|
||||
name: "paused",
|
||||
label:
|
||||
opts.pausedLabel ||
|
||||
"start paused — come up without driving turns until resumed",
|
||||
});
|
||||
}
|
||||
const r = await themedConfirm({
|
||||
message: opts.confirm,
|
||||
danger: true,
|
||||
confirmLabel: opts.confirmLabel || 'confirm',
|
||||
confirmLabel: opts.confirmLabel || "confirm",
|
||||
checkboxes,
|
||||
});
|
||||
if (!r) return;
|
||||
|
|
@ -112,18 +137,23 @@ class HiveAgentMenu extends HTMLElement {
|
|||
return li;
|
||||
};
|
||||
|
||||
const menuSep = () => el('li', { class: 'agent-menu-sep', role: 'separator' });
|
||||
const menuSep = () =>
|
||||
el("li", { class: "agent-menu-sep", role: "separator" });
|
||||
|
||||
// Navigation link item (opens in same tab by default).
|
||||
const menuLink = (label, href, title) => {
|
||||
const li = el('li', { role: 'presentation' });
|
||||
const a = el('a', {
|
||||
class: 'agent-menu-item',
|
||||
href,
|
||||
role: 'menuitem',
|
||||
title: title || '',
|
||||
}, label);
|
||||
a.addEventListener('click', close);
|
||||
const li = el("li", { role: "presentation" });
|
||||
const a = el(
|
||||
"a",
|
||||
{
|
||||
class: "agent-menu-item",
|
||||
href,
|
||||
role: "menuitem",
|
||||
title: title || "",
|
||||
},
|
||||
label,
|
||||
);
|
||||
a.addEventListener("click", close);
|
||||
li.append(a);
|
||||
return li;
|
||||
};
|
||||
|
|
@ -131,21 +161,28 @@ class HiveAgentMenu extends HTMLElement {
|
|||
// Show only actions that are applicable in the current state.
|
||||
if (c.running) {
|
||||
dropdown.append(
|
||||
menuItem('↺ R3ST4RT', {
|
||||
action: '/api/restart/',
|
||||
menuItem("↺ R3ST4RT", {
|
||||
action: "/api/restart/",
|
||||
confirm: `restart ${c.name}?`,
|
||||
graceful: true,
|
||||
gracefulLabel: 'restart gracefully — let the agent finish its turn and flush state before the container restarts',
|
||||
gracefulLabel:
|
||||
"restart gracefully — let the agent finish its turn and flush state before the container restarts",
|
||||
}),
|
||||
menuItem("■ ST0P", {
|
||||
action: "/api/kill/",
|
||||
confirm: `stop ${c.name}?`,
|
||||
confirmLabel: "■ stop",
|
||||
graceful: true,
|
||||
}),
|
||||
menuItem('■ ST0P', { action: '/api/kill/', confirm: `stop ${c.name}?`, confirmLabel: '■ stop', graceful: true }),
|
||||
);
|
||||
} else {
|
||||
dropdown.append(
|
||||
menuItem('▶ ST4RT', {
|
||||
action: '/api/start/',
|
||||
menuItem("▶ ST4RT", {
|
||||
action: "/api/start/",
|
||||
confirm: `start ${c.name}?`,
|
||||
paused: true,
|
||||
pausedLabel: 'start paused — come up without driving turns until resumed',
|
||||
pausedLabel:
|
||||
"start paused — come up without driving turns until resumed",
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
|
@ -153,55 +190,70 @@ class HiveAgentMenu extends HTMLElement {
|
|||
// paused; a paused running agent keeps its container but drives no turns.
|
||||
if (c.paused) {
|
||||
dropdown.append(
|
||||
menuItem('▶ R3SUM3', { action: '/api/resume/', confirm: `resume ${c.name}? the turn loop restarts and drains queued messages.` }),
|
||||
menuItem("▶ R3SUM3", {
|
||||
action: "/api/resume/",
|
||||
confirm: `resume ${c.name}? the turn loop restarts and drains queued messages.`,
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
dropdown.append(
|
||||
menuItem('⏸ P4US3', { action: '/api/pause/', confirm: `pause ${c.name}? parks the turn loop — inbox messages queue unacked.` }),
|
||||
menuItem("⏸ P4US3", {
|
||||
action: "/api/pause/",
|
||||
confirm: `pause ${c.name}? parks the turn loop — inbox messages queue unacked.`,
|
||||
}),
|
||||
);
|
||||
}
|
||||
dropdown.append(
|
||||
menuSep(),
|
||||
menuItem('↻ R3BU1LD', { action: '/api/rebuild/', confirm: `rebuild ${c.name}? hot-reloads the container.` }),
|
||||
menuItem("↻ R3BU1LD", {
|
||||
action: "/api/rebuild/",
|
||||
confirm: `rebuild ${c.name}? hot-reloads the container.`,
|
||||
}),
|
||||
menuSep(),
|
||||
// Deep-link to the AGENT log tab pre-filtered to this container.
|
||||
// The ?agent= param is read by logs.js on load and pre-selects this
|
||||
// agent's journal without extra clicks.
|
||||
menuLink('journal logs →',
|
||||
menuLink(
|
||||
"journal logs →",
|
||||
`/logs.html?agent=${encodeURIComponent(c.name)}#agent`,
|
||||
`view ${c.name} journal logs`),
|
||||
`view ${c.name} journal logs`,
|
||||
),
|
||||
);
|
||||
|
||||
dropdown.append(
|
||||
menuSep(),
|
||||
menuItem('DESTR0Y', {
|
||||
action: '/api/destroy/',
|
||||
menuItem("DESTR0Y", {
|
||||
action: "/api/destroy/",
|
||||
confirm: `destroy ${c.name}? container removed; state + creds kept.`,
|
||||
}),
|
||||
menuItem('PURG3', {
|
||||
action: '/api/destroy/',
|
||||
body: { purge: 'on' },
|
||||
menuItem("PURG3", {
|
||||
action: "/api/destroy/",
|
||||
body: { purge: "on" },
|
||||
confirm: `PURGE ${c.name}? WIPES container, config history, claude creds, and notes. no undo.`,
|
||||
}),
|
||||
);
|
||||
|
||||
if (c.deployed_sha && forgeBase) {
|
||||
const li = el('li', { role: 'presentation' });
|
||||
const a = el('a', {
|
||||
class: 'agent-menu-item',
|
||||
href: `${forgeBase}/agent-configs/${encodeURIComponent(c.name)}/commit/${c.deployed_sha}`,
|
||||
target: '_blank',
|
||||
rel: 'noopener',
|
||||
role: 'menuitem',
|
||||
title: 'deployed config commit on forge',
|
||||
}, `deployed:${c.deployed_sha} ↗`);
|
||||
const li = el("li", { role: "presentation" });
|
||||
const a = el(
|
||||
"a",
|
||||
{
|
||||
class: "agent-menu-item",
|
||||
href: `${forgeBase}/agent-configs/${encodeURIComponent(c.name)}/commit/${c.deployed_sha}`,
|
||||
target: "_blank",
|
||||
rel: "noopener",
|
||||
role: "menuitem",
|
||||
title: "deployed config commit on forge",
|
||||
},
|
||||
`deployed:${c.deployed_sha} ↗`,
|
||||
);
|
||||
li.append(a);
|
||||
dropdown.append(menuSep(), li);
|
||||
}
|
||||
|
||||
this._menu = document.createElement('hive-menu');
|
||||
this._menu = document.createElement("hive-menu");
|
||||
this._menu._opts = { trigger: btn, content: dropdown };
|
||||
this.append(this._menu);
|
||||
}
|
||||
}
|
||||
customElements.define('hive-agent-menu', HiveAgentMenu);
|
||||
customElements.define("hive-agent-menu", HiveAgentMenu);
|
||||
|
|
|
|||
Loading…
Reference in a new issue