//! Wire types for the *in-agent* socket, served by the hive-agent harness //! to the in-container producers (matrix / bash MCP daemons) and //! `forge_notify`. Currently carries the loose-ends-v2 *todo* op family; //! more in-agent request families may be added over time (the socket is //! deliberately named for the agent, not the todos). //! //! Distinct from `hive-core-agent-sock`, the *host*-served core↔agent //! protocol on `/run/hive/mcp.sock`: this socket never leaves the //! container. The harness owns the todo store locally and signals its own //! turn loop directly, so hive-c0re is not in the todo path — no broker //! round-trip, no long-poll, no marker files. use serde::{Deserialize, Serialize}; use hive_sh4re::LooseEnd; /// In-container path of the harness-served in-agent socket. The harness /// binds it on boot; the in-container producers dial it for todo ops. /// (Placeholder default — the harness + producers resolve the real path /// from config; kept here so a producer with no override has a sane one.) pub const DEFAULT_AGENT_SOCKET: &str = "/run/hive/agent.sock"; /// A request on the in-agent socket. Serialised with a `cmd` tag so the /// in-container producers can emit a plain JSON line without linking a /// typed client (matrix/bash build the JSON by hand). #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(tag = "cmd", rename_all = "snake_case")] pub enum Request { /// Upsert a todo from an in-container subsystem (matrix / bash / /// forge). `subsystem` is the producer marker; `key` the optional /// subsystem-specific dedup key (a matrix room id, a bash task id). /// A new-or-changed row signals the turn loop; an identical keyed /// re-push is a silent no-op. Keyless todos always insert as one-offs. UpsertTodo { subsystem: String, #[serde(default, skip_serializing_if = "Option::is_none")] key: Option, summary: String, #[serde(default, skip_serializing_if = "Option::is_none")] source: Option, }, /// Clear producer-resolved todo(s). `key = Some(k)` clears the one /// keyed row; `key = None` clears the subsystem's keyless rows; `all /// = true` wipes the producer's whole set (cancel-and-recreate on /// daemon restart). ClearTodo { subsystem: String, #[serde(default, skip_serializing_if = "Option::is_none")] key: Option, #[serde(default)] all: bool, }, /// List todos, optionally filtered to one `subsystem` (a producer /// reconciling its own set). `None` = all. ListTodos { #[serde(default, skip_serializing_if = "Option::is_none")] subsystem: Option, }, /// The agent marks one of its own todos done, by id. MarkTodoDone { id: i64 }, } /// A response on the in-agent socket. Serialised with a `kind` tag, /// mirroring the core↔agent protocol's response shape. #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(tag = "kind", rename_all = "snake_case")] pub enum Response { /// Op succeeded, no payload. Ok, /// Op succeeded and touched `count` rows (clear / mark-done). Acked { count: u64 }, /// `ListTodos` result. LooseEnds { loose_ends: Vec }, /// Op failed; `message` is operator-facing. Err { message: String }, }