swarm: publish each agent's turn-state header on its own subject
The swarm can already tell whether an agent is alive — the `agent-status`
KV bucket republishes once a minute — but not what it is doing right now.
A header bar wants the second thing, and a minute-old answer to "is this
agent thinking" is the wrong answer most of the time it is read.
`hive-agent` now publishes a turn-state header to
`$SWARM.agent-state.<hive>.<agent>`, a core subject beside the terminal
rows it already sends. It goes out **on transition, not on a timer**: the
publisher watches the event bus, rebuilds the header, and sends only when
the serialised result differs from the last one it sent — so a second
periodic writer, which is the problem this exists to fix, is not what
replaces the bucket.
The payload is the published contract a swarm-level renderer is written
against, so the test asserts on the serialised JSON keys rather than on
Rust field names. Two fields deliberately depart from the per-agent web
UI's `StateSnapshot`: `turn_state_since` is an ISO 8601 UTC string rather
than unix seconds, matching the sibling `$SWARM.term` subject's stamp, and
`agent_state` carries the swarm's own `AgentState` vocabulary rather than
a `paused` boolean, so a reader can compare actual against wanted without
translating. `turn_state` and `agent_state` stay two separate fields:
neither vocabulary contains the other's values.
Swarm-side, `GET /api/agents/{name}/state/stream` relays the subject as
SSE, resolving the agent's hive at request time exactly as the terminal
stream does and passing the bytes through without parsing them.
The broker grant is a second `--agent-publish-subject` rather than a
widening of the existing one, so the terminal family and the header family
stay independently revocable, and a `module-eval` arm pins the rendered
flag and its argument together — the doubled dollar included, since a
single one expands to nothing in `ExecStart` and yields a grant that
matches nothing.
Refs #3802
This commit is contained in:
parent
065f93f037
commit
1ea3d87d7a
7 changed files with 683 additions and 0 deletions
|
|
@ -28,6 +28,7 @@ mod serve_common;
|
|||
mod state_entry_watch;
|
||||
mod stats;
|
||||
mod stream_enrich;
|
||||
mod swarm_agent_state;
|
||||
mod swarm_queue;
|
||||
mod swarm_term;
|
||||
mod term_msg;
|
||||
|
|
@ -509,6 +510,10 @@ async fn serve_main<S: Surface>(socket: &Path, poll_ms: u64) -> Result<()> {
|
|||
// Subscribes before anything is emitted, so the swarm sees this agent's
|
||||
// terminal from its first row rather than from whenever a reader attached.
|
||||
swarm_term::spawn(bus.subscribe());
|
||||
// Same reason, one subject over: the swarm's header bar wants the turn
|
||||
// state from this agent's first transition, not from whenever a reader
|
||||
// first asked.
|
||||
swarm_agent_state::spawn(&bus);
|
||||
// Set by the web UI's `/api/cancel` on a successful SIGINT, read-and-
|
||||
// cleared by `handle_turn` before building the next wake prompt — see
|
||||
// `hive_sh4re::inbox::INTERRUPTED_HINT`. Shared between the web server task and
|
||||
|
|
|
|||
Loading…
Reference in a new issue