swarm-controller: replay a subagent's newest rows before its live tail
A subagent's terminal opened directly showed nothing until the subagent published again: the relay was a core subscription, though its rows sit in term-sub-<agent> for 24 hours. It now goes through the agent route's replay-then-tail, so it opens with the subagent's newest 100 rows and resumes after Last-Event-ID. - term_stream.rs: the replay takes a stream name and a filter subject instead of an agent, and `replay_or_live` (replay, else the live core subscription) is the one fn both routes call. When the filter is one of several subjects in the stream, a fresh reader's consumer starts at the oldest row and drops all but the newest REPLAY_ROWS it counts as pending, since the stream's newest sequences may belong to sibling subagents. A single-subject stream (term-main-<agent>) picks its start with replay_start exactly as before. Tests for both subagent cases. - subagent_term.rs: the relay calls replay_or_live on the subagent's subject in term-sub-<agent> and reads Last-Event-ID; module doc and OpenAPI text no longer say "live only". - main.rs: the handler test passes the new headers argument. - swarm-queue-client agent_term.rs: replay_consumer_config takes the filter subject instead of the agent. - swarm-queue-client subagent_term.rs: consumer_create_grant, the extended CONSUMER.CREATE form with a subagent subject as filter. - swarm-nats-auth policy.rs: the controller holds that grant; the agent grant's `$SWARM.term.*` filter is two tokens short of a subagent subject, and the test that refused it now admits it. - docs/swarm/ui.md, README.md: a subagent terminal opens with its newest rows. Fixes #5527
This commit is contained in:
parent
f65364759f
commit
d9c586ef94
8 changed files with 272 additions and 71 deletions
|
|
@ -702,6 +702,10 @@ impl Policy {
|
|||
// `MSG.GET` above. No bare `CONSUMER.CREATE.<stream>`, whose
|
||||
// filter is unchecked.
|
||||
swarm_queue_client::agent_term::consumer_create_grant(),
|
||||
// The same for one subagent's rows in `term-sub-<agent>`: the
|
||||
// filter is `$SWARM.term.<agent>.sub.<subagent>`, two tokens
|
||||
// deeper than the grant above reaches.
|
||||
swarm_queue_client::subagent_term::consumer_create_grant(),
|
||||
"$KV.*.>".to_owned(),
|
||||
]);
|
||||
// The per-agent status bucket, read-side only. Same five subjects as
|
||||
|
|
@ -1788,12 +1792,24 @@ mod tests {
|
|||
&stream_name("atlas"),
|
||||
&term_subject("atlas")
|
||||
)));
|
||||
assert!(may_publish(&create(
|
||||
&subagent_term::stream_name("atlas"),
|
||||
&subagent_term::subject("atlas", "scout"),
|
||||
)));
|
||||
for refused in [
|
||||
// The bare form, whose filter rides in the payload alone.
|
||||
format!("$JS.API.CONSUMER.CREATE.{}", stream_name("atlas")),
|
||||
format!(
|
||||
"$JS.API.CONSUMER.CREATE.{}",
|
||||
subagent_term::stream_name("atlas")
|
||||
),
|
||||
create(
|
||||
&subagent_term::stream_name("atlas"),
|
||||
&subagent_term::subject("atlas", "scout"),
|
||||
&format!("{}.x", subagent_term::subject("atlas", "scout")),
|
||||
),
|
||||
create(
|
||||
&subagent_term::stream_name("atlas"),
|
||||
"$SWARM.agent-state.atlas.sub.scout",
|
||||
),
|
||||
create("hive-notices", "hive-notices.alpha"),
|
||||
create(&stream_name("atlas"), "$SWARM.agent-state.atlas"),
|
||||
|
|
|
|||
Loading…
Reference in a new issue