`goal_reached`/`need_help` took the session name as a tool argument, so identity was an assertion by the caller and the only guard on it was `occupancy()` — "does that name have a turn in flight", which two concurrently running siblings both satisfy for each other. A subagent could stop its sibling's run by naming it. Identity moves into the URL. Each spawned run is minted an unguessable token (`Uuid::new_v4`, the OS CSPRNG), the URL carrying it goes into that one subagent's own `--mcp-config`, and the route resolves it back to a session before dispatching to a handler bound to that session. Neither tool takes a `name` any more: a subagent has no field in which to name a sibling, and a sibling's name — which a brief may well mention — is not a token. One route with a path parameter, not a route per session: the `Router` is built once at startup and subagents come and go for the daemon's whole life. An unminted or revoked token gets a bare 404, the same answer either way, so nothing enumerates. A run's token is revoked when the run ends (`finish_turn`) or when a call never reached a spawn. Two things fall out of that: - the config file becomes one per session. A single shared path was already a race between two `start`s; with a per-session URL in it, the loser would read the winner's identity. - `occupancy()` stops being the identity guard and is gone from the signal path entirely rather than kept "just in case" — a revoked token can't reach it, and it never answered the question it was standing in for. It still backs `status`, which is what it was always actually for. Refs #4403 Refs #4413
22 lines
1.1 KiB
Rust
22 lines
1.1 KiB
Rust
//! Library for `hive-subagent-daemon`: spawns nested claude sessions on
|
|
//! request and serves the `start`/`continue`/`status`/`interrupt` MCP tool
|
|
//! surface directly over streamable-http — no stdio bridge, no round-trip
|
|
//! socket. Independent of `hive-bash-mcp` — a subagent is a much heavier
|
|
//! capability than a bash command (a full nested `claude` process), worth
|
|
//! its own deployable/restartable unit rather than sharing one.
|
|
//!
|
|
//! A second route on the same listener serves `goal_reached`/`need_help` to
|
|
//! the *subagents*, which is how a run says it's done or stuck; see
|
|
//! [`mcp`]'s module doc for why that is a separate surface rather than two
|
|
//! more tools on the parent's, and why it is served per session under a
|
|
//! minted token rather than at one shared path — neither tool takes a
|
|
//! session name, so a subagent has no way to say it is somebody else.
|
|
//!
|
|
//! See [`session`]'s module doc for the actual design: no task files, no
|
|
//! restart recovery, no mid-turn compaction — the daemon's only state is a
|
|
//! handful of in-memory maps, live only as long as the process is.
|
|
|
|
pub mod mcp;
|
|
pub mod mcp_config;
|
|
pub mod paths;
|
|
pub mod session;
|