Closes the #3110 split — lib.rs is now just the crate doc comment and the pub mod list. journal.rs's new doc comment fixes a pre-existing bug: the old JournalPriority doc text in lib.rs was actually half Capability's doc (a leftover from an earlier reorder that moved the code but not the comment above it).
155 lines
7.3 KiB
Rust
155 lines
7.3 KiB
Rust
//! 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` are the built-in ones today, but `subsystem` on the todo
|
|
//! ops below is a plain string, not a closed set: any user-configured MCP
|
|
//! server declared in an agent's `agent.nix` can dial this socket and push
|
|
//! its own todos the same way. Carries the loose-ends-v2 *todo* op family
|
|
//! plus the harness-local *reminder* and *question* op families; 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 + reminder stores locally and
|
|
//! signals its own turn loop directly, so hive-c0re is not in either path —
|
|
//! no broker round-trip, no long-poll, no marker files.
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use hive_sh4re::inbox::LooseEnd;
|
|
|
|
pub mod paths;
|
|
|
|
/// 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; a user-configured
|
|
/// MCP server can do the same with its own `subsystem` marker).
|
|
#[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 are the built-in producers, but any subsystem name is
|
|
/// accepted; nothing restricts `subsystem` to a fixed set, so a
|
|
/// user-configured MCP server can push its own todos here too.
|
|
/// `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<String>,
|
|
summary: String,
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
source: Option<String>,
|
|
},
|
|
/// 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<String>,
|
|
#[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<String>,
|
|
},
|
|
/// The agent marks one of its own todos done, by id.
|
|
MarkTodoDone { id: i64 },
|
|
/// The agent bulk-acks a specific, explicit list of its own todos in
|
|
/// one shot — for clearing a backlog that's piled up past the point of
|
|
/// per-id triage, without the range-based `ack_until`-style semantics
|
|
/// that risk silently acking something never actually looked at (see
|
|
/// `Todos::mark_done_many`'s doc for why it's ids, not a threshold).
|
|
MarkTodosDone { ids: Vec<i64> },
|
|
/// Schedule a reminder that fires into this agent's own turn loop at
|
|
/// `timing` (harness-local — no broker round-trip). Same semantics as
|
|
/// the old broker `Remind` request. `file_path`, when set, is where the
|
|
/// harness persists an over-cap body instead of inlining it.
|
|
StoreReminder {
|
|
message: String,
|
|
timing: hive_sh4re::inbox::ReminderTiming,
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
file_path: Option<String>,
|
|
},
|
|
/// List this agent's pending reminders (single-agent scope — unlike
|
|
/// the old broker query, there's no cross-agent `agent` filter here).
|
|
ListReminders,
|
|
/// Cancel one of this agent's own pending reminders by id, before it
|
|
/// fires.
|
|
CancelReminder { id: i64 },
|
|
/// This agent's pending-reminder count — used by the pre-`remind` cap
|
|
/// check and the harness's own turn-stats sink.
|
|
CountPendingReminders,
|
|
/// Scheduled/delivered/pending reminder counts over a trailing
|
|
/// `since_secs` window (`0` = all time) — the harness's own `/api/stats`
|
|
/// reminder-activity chart data (was `hive-core-agent-sock`'s
|
|
/// `ReminderRollup` against the broker; now served from the local store).
|
|
ReminderRollup { since_secs: u64 },
|
|
/// Agent self-service request to compact the current session, mirroring
|
|
/// the operator's `/compact` dashboard button. Gated server-side: only
|
|
/// honoured when the last completed turn's context usage is above 66%
|
|
/// of the effective context window — below that, `Response::Err`
|
|
/// explains why and takes no action. On a pass, queues the same
|
|
/// deferred `compact_pending` flag the operator's button sets (consumed
|
|
/// at the next turn boundary), so it never races a live claude process.
|
|
Compact,
|
|
/// Mirror an outstanding question this agent asked (`ask()` succeeded).
|
|
/// `target` is who it's waiting on (`"operator"` when asked with
|
|
/// `to: None`). Part of the questions-mirror increment — see
|
|
/// `hive-agent::questions`.
|
|
RecordAskedQuestion {
|
|
id: i64,
|
|
target: String,
|
|
question: String,
|
|
},
|
|
/// Mirror an outstanding question this agent was asked (a
|
|
/// `question_asked` system event arrived in the inbox). `asker` is who's
|
|
/// waiting on this agent for a reply.
|
|
RecordAnsweringQuestion {
|
|
id: i64,
|
|
asker: String,
|
|
question: String,
|
|
},
|
|
/// Drop the mirror row for `id` (either role) — the question resolved
|
|
/// from this agent's side (answered, or the `question_answered` event
|
|
/// for a question this agent asked arrived).
|
|
ClearQuestion { id: i64 },
|
|
/// List this agent's mirrored questions (both roles) — single-agent
|
|
/// scope, same shape as `ListReminders`.
|
|
ListQuestions,
|
|
}
|
|
|
|
/// 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` / `ListReminders` / `ListQuestions` result (each wraps
|
|
/// its rows as the matching [`LooseEnd`] variant).
|
|
LooseEnds { loose_ends: Vec<LooseEnd> },
|
|
/// `CountPendingReminders` result.
|
|
PendingRemindersCount { count: u64 },
|
|
/// `ReminderRollup` result.
|
|
ReminderRollup {
|
|
stats: hive_sh4re::approvals::ReminderStats,
|
|
},
|
|
/// Op failed; `message` is operator-facing.
|
|
Err { message: String },
|
|
}
|