Watch
0
0
Fork
You've already forked hyperhive
0

drop the host side of the agent broker send

Remove the agent-side Send and AckUntil requests, their hive-c0re handlers
(handle_send with its 4 KiB size cap, handle_ack_until) and Broker::ack_until.
Everything that existed only for them goes with them: the OkWarn response
(its sole producer was Send's reserved-name warning), Recv's max parameter
and RECV_BATCH_MAX (the harness never asked for more than one message),
OPERATOR_SEND_REFUSAL, and the MESSAGE_MAX_BYTES / check_size limit (the
reminder timer keeps its own copy of the cap, so its comment is reworded).

Messages.remaining stays on the wire (default on read) because a harness
built before this change still requires it. Update the conventions docs.
This commit is contained in:
damocles 2026-11-08 02:35:34 +01:00 • committed by mara
commit 1c3b5e52cf

View file

@ -22,24 +22,12 @@ fn default_true() -> bool {
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "cmd", rename_all = "snake_case")]
pub enum Request {
/// Send a message to another agent.
Send {
to: String,
body: String,
/// Optional id of the message being replied to. Stored in the
/// broker DB and returned on `Recv` so the dashboard can render
/// threads. Ignored if the id is unknown or out of retention.
#[serde(default, skip_serializing_if = "Option::is_none")]
in_reply_to: Option<i64>,
},
/// 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<u64>,
#[serde(default)]
max: Option<u32>,
},
/// Non-mutating: how many pending messages are addressed to me?
/// Used by the harness to render a status line after each tool call.
@ -48,7 +36,7 @@ pub enum Request {
/// 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 — the agent can ack it via `AckUntil`.
/// 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
@ -73,15 +61,6 @@ pub enum Request {
/// Harness↔broker pairing fired after `TurnOutcome::Ok`. See
/// `docs/5-project/process/conventions.md::Broker delivery + ack cycle`.
AckTurn,
/// Mark every inbox message with broker row id `<= up_to` as
/// handled (`acked_at` set), whether still pending or already
/// delivered. The agent-facing bulk-triage escape hatch for a
/// redelivered / accumulated backlog: instead of popping and
/// re-reading dozens of already-handled messages one turn at a
/// time, the agent acks everything up to the id it has seen.
/// Recipient-scoped — an agent can only ack its own rows. See
/// `docs/5-project/process/conventions.md::Broker delivery + ack cycle`.
AckUntil { up_to: i64 },
/// Requeue every popped-but-unacked message back into the inbox.
/// Harness fires this once at boot to recover from
/// crashed-mid-turn sessions. See
@ -103,43 +82,25 @@ pub enum Request {
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum Response {
/// `Send` succeeded.
/// The request succeeded.
Ok,
/// The operation succeeded **and** raised advisories the caller
/// should see.
///
/// Distinct from `Err` on purpose: a check that WARNS rather than
/// refuses has no other way to reach the caller. Folding it into
/// `Err` would refuse; folding it into `Ok` would drop it, leaving
/// the daemon's log as the only record — and the person who can act
/// on the advisory is the one holding this response, not the one
/// reading the journal.
///
/// Additive: every existing site returning `Ok` keeps returning it,
/// so a caller that never matches this variant is unaffected.
OkWarn { warnings: Vec<String> },
/// Either `Send` failed or `Recv` errored.
/// A request failed (`Recv` errored, a store write failed, ...).
Err { message: String },
/// `Recv` result: zero or more messages, FIFO-ordered, never
/// longer than the `max` the caller passed. Empty vec = nothing
/// pending (the "(empty)" path for the formatter). Per-row `id` +
/// `redelivered` carry the broker's row id (tracked by the harness
/// for `AckTurn`, and surfaced to claude as a `[msg #<id>]` marker
/// so `AckUntil` has something to reference) and the "previously
/// popped, not acked" flag — see `DeliveredMessage` for details.
/// `remaining` is the inbox depth *after* this batch was popped —
/// how many still-pending messages the caller could drain next. The
/// harness surfaces it to claude ("N more pending") so an in-turn
/// `recv` learns whether the inbox is drained, mirroring the count
/// the wake prompt already carries.
/// `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<DeliveredMessage>,
#[serde(default)]
remaining: u64,
},
/// `Status` result: how many pending messages are in this agent's inbox.
Status { unread: u64 },
/// `AckUntil` result: how many rows were newly marked handled.
Acked { count: u64 },
/// `Recent` result: newest-first inbox rows.
Recent { rows: Vec<InboxRow> },
/// `GetLooseEnds` result: list of loose ends pending against