a hive-side pause holds against the swarm's declared state until an operator resumes
the harness writes the reason into the pause marker when it pauses itself and reports it as paused_by_hive in its turn-state header. swarm-controller declares such an agent paused (only if declared up) and shows the reason on the agents status row and the swarm ui card.
This commit is contained in:
parent
6470e2b109
commit
e5c55257f8
3 changed files with 517 additions and 26 deletions
|
|
@ -43,6 +43,10 @@ export interface AgentRow {
|
|||
// no header since swarm-controller started, or an agent that does not
|
||||
// send the flag — not known, so not "needs login".
|
||||
needs_login: boolean | null;
|
||||
// Why the agent's own harness paused its turn loop. `null`: it did not, or
|
||||
// the harness does not send the field. The controller declares such an agent
|
||||
// paused, and only setting it up again resumes it.
|
||||
paused_by_hive: string | null;
|
||||
// The archetype the agent is built from; `null` for a custom agent.
|
||||
archetype: { source: string; name: string } | null;
|
||||
}
|
||||
|
|
@ -61,6 +65,13 @@ export function showsLoginNeeded(row: Pick<AgentRow, "needs_login">): boolean {
|
|||
return row.needs_login === true;
|
||||
}
|
||||
|
||||
// The reason to show on the "paused by hive" badge; `null` shows no badge.
|
||||
export function hivePauseReason(
|
||||
row: Pick<AgentRow, "paused_by_hive">,
|
||||
): string | null {
|
||||
return row.paused_by_hive ? row.paused_by_hive : null;
|
||||
}
|
||||
|
||||
// Same tone pairing as HivesCard — one freshness enum shared by both
|
||||
// endpoints, so the same tone rule applies to both pages — but
|
||||
// `unknown`'s label diverges deliberately: an agent outside the
|
||||
|
|
|
|||
|
|
@ -23,7 +23,12 @@ import { AgentIcon } from "../AgentIcon.js";
|
|||
import { ClaudeLoginDialog } from "../claude-login/ClaudeLoginDialog.js";
|
||||
import { AgentDetail } from "../detail/AgentDetail.js";
|
||||
import { termPaths } from "../terminal/term-paths.js";
|
||||
import { FRESHNESS, showsLoginNeeded, type AgentRow } from "../AgentTypes.js";
|
||||
import {
|
||||
FRESHNESS,
|
||||
hivePauseReason,
|
||||
showsLoginNeeded,
|
||||
type AgentRow,
|
||||
} from "../AgentTypes.js";
|
||||
import type { AgentActions } from "./AgentActions.js";
|
||||
import { WantedMenu } from "./WantedMenu.js";
|
||||
import { AgentCardLayout } from "./AgentCardLayout.js";
|
||||
|
|
@ -82,6 +87,13 @@ export function AgentCard({
|
|||
</>
|
||||
}
|
||||
/>
|
||||
{hivePauseReason(row) !== null ? (
|
||||
<Badge
|
||||
tone="warning"
|
||||
value="paused by hive"
|
||||
title={`the hive paused this agent: ${hivePauseReason(row)}. Set it up again to resume it.`}
|
||||
/>
|
||||
) : null}
|
||||
{showsLoginNeeded(row) ? (
|
||||
<span
|
||||
class="ui-agent-card-login"
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import assert from "node:assert/strict";
|
|||
import { test } from "node:test";
|
||||
import {
|
||||
canTurnIntoCustom,
|
||||
hivePauseReason,
|
||||
showsLoginNeeded,
|
||||
} from "../src/agent/AgentTypes.ts";
|
||||
|
||||
|
|
@ -42,3 +43,13 @@ test("turn into custom is offered to a placed archetype agent only", () => {
|
|||
false,
|
||||
);
|
||||
});
|
||||
|
||||
test("an agent its hive paused shows the reason, any other shows none", () => {
|
||||
assert.equal(
|
||||
hivePauseReason({ paused_by_hive: "skipped get_loose_ends" }),
|
||||
"skipped get_loose_ends",
|
||||
);
|
||||
assert.equal(hivePauseReason({ paused_by_hive: null }), null);
|
||||
assert.equal(hivePauseReason({ paused_by_hive: "" }), null);
|
||||
assert.equal(hivePauseReason({}), null);
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue