hivectl/dashboard: add --paused / ?paused=1 to agent start

This commit is contained in:
damocles 2026-08-02 19:52:11 +02:00
commit af3976a76a
4 changed files with 118 additions and 16 deletions

View file

@ -26,9 +26,18 @@ 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.
async function agentMenuPost(actionPath, name, body, graceful) {
const url = actionPath + encodeURIComponent(name) + (graceful ? '?graceful=true' : '');
// 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
// `{ paused: true }`) — every menu action so far needs at most one, but
// this stays a plain object rather than a single named arg so a future
// action needing two doesn't have to touch this signature again.
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');
}
const qs = params.toString();
const url = actionPath + encodeURIComponent(name) + (qs ? '?' + qs : '');
try {
const resp = await fetch(url, {
method: 'POST',
@ -79,20 +88,25 @@ class HiveAgentMenu extends HTMLElement {
}, label);
item.addEventListener('click', async () => {
close();
let graceful = false;
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' });
}
if (opts.paused) {
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',
checkboxes: opts.graceful
? [{ name: 'graceful', label: opts.gracefulLabel || 'stop gracefully — let the agent finish its turn and flush state before the container stops' }]
: [],
checkboxes,
});
if (!r) return;
graceful = !!r.graceful;
flags = { graceful: !!r.graceful, paused: !!r.paused };
}
await agentMenuPost(opts.action, c.name, opts.body || null, graceful);
await agentMenuPost(opts.action, c.name, opts.body || null, flags);
});
li.append(item);
return li;
@ -127,7 +141,12 @@ class HiveAgentMenu extends HTMLElement {
);
} else {
dropdown.append(
menuItem('▶ ST4RT', { action: '/api/start/', confirm: `start ${c.name}?` }),
menuItem('▶ ST4RT', {
action: '/api/start/',
confirm: `start ${c.name}?`,
paused: true,
pausedLabel: 'start paused — come up without driving turns until resumed',
}),
);
}
// Pause/resume is orthogonal to running: a paused stopped agent boots