swarm-controller: create every agent's subagent stream
swarm-controller now creates `term-sub-<agent>` for every agent a hive is declared to run, at start and every minute after, with the config `swarm_queue_client::subagent_term::open_or_create` spells (subjects `$SWARM.term.<agent>.sub.>`, max_age 24h). An existing stream is opened as it is, as the controller does for its other streams and buckets, under the `$JS.API.STREAM.CREATE.*` grant it already holds. The agent no longer creates the stream: its token is granted publish on `$SWARM.term.<agent>.sub.>` and no `$JS.API.STREAM.CREATE|INFO` subject, and the subagent daemon only publishes. A `CREATE` carries the stream's config in its payload, which no subject grant narrows, so the agent could otherwise pick the stream's subjects and limits.
This commit is contained in:
parent
d6f94e5247
commit
318f67cda9
13 changed files with 135 additions and 102 deletions
|
|
@ -30,8 +30,8 @@ kv = ["async-nats/kv"]
|
|||
# `cargo check -p swarm-nats-auth` — no `kv` anywhere in that build —
|
||||
# surfaced it as `cannot find jetstream in async_nats`).
|
||||
notices = ["async-nats/jetstream"]
|
||||
# `subagent_term::open_or_create`, for the one publisher that creates its own
|
||||
# stream. Explicit for the same reason as `notices`.
|
||||
# `subagent_term::open_or_create`, for swarm-controller, which creates every
|
||||
# agent's subagent stream. Explicit for the same reason as `notices`.
|
||||
subagent-term = ["async-nats/jetstream"]
|
||||
|
||||
[dependencies]
|
||||
|
|
|
|||
|
|
@ -3,21 +3,20 @@
|
|||
//!
|
||||
//! An agent's subagent daemon publishes each subagent's classified terminal
|
||||
//! rows on `$SWARM.term.<agent>.sub.<subagent>`, under the agent's own queue
|
||||
//! credential. The queue grants that credential this subject family and
|
||||
//! `CREATE`/`INFO` on the one stream [`crate::subagent_term::stream_name`]
|
||||
//! names, nothing else of `JetStream`, so the agent creates its own stream on
|
||||
//! first use.
|
||||
//! credential. The queue grants that credential publish on this subject
|
||||
//! family and no `JetStream` subject.
|
||||
//!
|
||||
//! The stream exists so the swarm can list an agent's subagents: subagents
|
||||
//! are spawned on demand under caller-chosen names, and the set of subjects
|
||||
//! the stream holds is the list. A reader takes it from the stream's subject
|
||||
//! counts ([`crate::subagent_term::subagent_names`]) and never creates the
|
||||
//! stream.
|
||||
//! the stream holds is the list. `swarm-controller` creates one stream per
|
||||
//! agent with the fixed config [`crate::subagent_term::open_or_create`]
|
||||
//! spells, and takes the list from its subject counts
|
||||
//! ([`crate::subagent_term::subagent_names`]).
|
||||
//!
|
||||
//! The name and the subject live here because three crates must agree on
|
||||
//! them: the publisher in `hive-subagent-mcp`, the reader in
|
||||
//! `swarm-controller`, and the queue grant in `swarm-nats.nix`, whose
|
||||
//! `{agent}` templates spell the same strings.
|
||||
//! them: the publisher in `hive-subagent-mcp`, `swarm-controller`, and the
|
||||
//! queue grant in `swarm-nats.nix`, whose `{agent}` template spells the same
|
||||
//! subjects.
|
||||
|
||||
/// The subject family every agent terminal shares.
|
||||
const TERM_PREFIX: &str = "$SWARM.term";
|
||||
|
|
@ -79,10 +78,8 @@ pub fn subagent_names<'a>(agent: &str, subjects: impl IntoIterator<Item = &'a st
|
|||
names
|
||||
}
|
||||
|
||||
/// Open `agent`'s subagent stream, creating it if it does not exist yet.
|
||||
///
|
||||
/// Called by the publisher only. The reader opens the stream with `get_stream`
|
||||
/// and reads a missing one as "no subagents".
|
||||
/// Open `agent`'s subagent stream, creating it if it does not exist yet. An
|
||||
/// existing stream is opened as it is.
|
||||
#[cfg(feature = "subagent-term")]
|
||||
pub async fn open_or_create(
|
||||
client: &async_nats::Client,
|
||||
|
|
|
|||
Loading…
Reference in a new issue