//! Per-agent socket wire types (`/run/hive/mcp.sock`). //! //! The unified `Request` / `Response` protocol spoken between an agent's //! in-container harness and the `hive-c0re` daemon over the //! per-agent mcp socket. Re-homed out of `hive-sh4re` so this one socket owns //! its own protocol crate, mirroring `hive-host-sock` / `hive-priv-sock`. The //! shared payload types it references (`Message`, `LooseEnd`, …) //! stay in `hive-sh4re`, which this crate depends on. use hive_sh4re::container::MatrixIdentity; use hive_sh4re::inbox::{DeliveredMessage, InboxRow, LooseEnd}; use hive_types::Ident; use serde::{Deserialize, Serialize}; /// serde `default` helper for `Response::AgentMeta::running` (absent = true). fn default_true() -> bool { true } /// Unified request enum for the per-agent socket. The agent's /// identity is the socket it arrived on. #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(tag = "cmd", rename_all = "snake_case")] pub enum Request { /// Pop pending messages from this agent's inbox. /// Delivery + ack cycle: see /// `docs/5-project/process/conventions.md::Broker delivery + ack cycle`. Recv { #[serde(default)] wait_seconds: Option, }, /// Non-mutating: how many pending messages are addressed to me? /// Used by the harness to render a status line after each tool call. Status, /// Wake-up event injected from inside the container. Recipient is /// implicit (this agent); `from` is caller-chosen. See /// `docs/5-project/process/conventions.md::Wake injection` for the trust model and /// typical callers. The wake is persisted in the sqlite broker /// like any other message. Wake { from: String, body: String }, /// Last `limit` messages addressed to this agent, newest-first. /// Non-mutating — pulls from the broker without delivering. The /// per-agent web UI uses this to render its own inbox section. Recent { limit: u64 }, /// Loose-ends view — always the caller's own. See /// `docs/5-project/process/conventions.md::Loose-ends wire shape`. GetLooseEnds, /// Set a free-text status string visible on the dashboard. The harness /// writes `{state_dir}/hyperhive-status` locally before sending this /// request; hive-c0re just triggers a dashboard rescan on receipt. /// Pass an empty string to clear the status. SetStatus { text: String }, /// Fetch identity + status for an agent. `name = None` = /// self-introspection; `Some()` = target query. See /// `docs/5-project/process/conventions.md::Agent metadata`. GetAgentMeta { #[serde(default, skip_serializing_if = "Option::is_none")] name: Option, }, /// Mark every message popped since the last `AckTurn` as handled. /// Harness↔broker pairing fired after `TurnOutcome::Ok`. See /// `docs/5-project/process/conventions.md::Broker delivery + ack cycle`. AckTurn, /// Requeue every popped-but-unacked message back into the inbox. /// Harness fires this once at boot to recover from /// crashed-mid-turn sessions. See /// `docs/5-project/process/conventions.md::Broker delivery + ack cycle`. RequeueInflight, /// Harness → c0re: "I saw the `GracefulStop` signal, ran my /// stop-checkpoint turn (durable `/state` flushed) and am exiting my /// serve loop now." Lets the `GracefulStop` orchestration stop the /// container immediately instead of waiting out its timeout fallback. GracefulStopComplete, /// Harness → c0re: "the `Pause` marker check I run between turns /// (never mid-turn) just flipped `false → true`." Lets the pause /// DAG's drain node resolve immediately instead of waiting out its /// timeout fallback — same shape as `GracefulStopComplete`. PauseAcknowledged, } /// Unified response enum for the per-agent socket. #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(tag = "kind", rename_all = "snake_case")] pub enum Response { /// The request succeeded. Ok, /// A request failed (`Recv` errored, a store write failed, ...). Err { message: String }, /// `Recv` result: zero or one message. Empty vec = nothing pending. /// Per-row `id` + `redelivered` carry the broker's row id (tracked by /// the harness for `AckTurn`) and the "previously popped, not acked" /// flag — see `DeliveredMessage` for details. `remaining` is the inbox /// depth after the pop. No reader uses it any more, but a harness built /// before it stopped being used still requires the field, so hive-c0re /// keeps sending it until every agent has rebuilt; `default` lets a new /// harness read an answer from a c0re that has dropped it. Messages { messages: Vec, #[serde(default)] remaining: u64, }, /// `Status` result: how many pending messages are in this agent's inbox. Status { unread: u64 }, /// `Recent` result: newest-first inbox rows. Recent { rows: Vec }, /// `GetLooseEnds` result: list of loose ends pending against /// this agent. Ordered newest-first within each kind. LooseEnds { loose_ends: Vec }, /// `GetAgentMeta` result. Per-field semantics + serde defaults /// live in `docs/5-project/process/conventions.md::Agent metadata`. AgentMeta { name: String, #[serde(default = "default_true")] running: bool, #[serde(default, skip_serializing_if = "Option::is_none")] hyperhive_rev: Option, #[serde(default, skip_serializing_if = "Option::is_none")] status_text: Option, #[serde(default, skip_serializing_if = "Option::is_none")] status_set_at: Option, #[serde(default, skip_serializing_if = "Option::is_none")] hive_name: Option, #[serde(default, skip_serializing_if = "Option::is_none")] swarm_name: Option, /// Matrix identities this agent can act as (one per configured + /// live account). Empty for agents with no matrix provisioning. #[serde(default, skip_serializing_if = "Vec::is_empty")] matrix_accounts: Vec, }, /// `Recv` result when a graceful stop is pending for this agent /// (set by hive-c0re's `GracefulStop` orchestration). Returned in /// place of `Messages` — it doubles as the inbound fence: the harness /// stops consuming normal inbox messages and instead runs one /// stop-checkpoint turn (flush durable `/state`), then reports /// `GracefulStopComplete` and exits its serve loop so the container /// can be stopped cleanly. New sends keep queueing in the broker for /// the agent's next start. GracefulStop, }