recv: fold batch drain into recv(max) — one tool, uniform list response
This commit is contained in:
parent
77b89bf2c6
commit
5d27ae3048
8 changed files with 271 additions and 417 deletions
|
|
@ -174,10 +174,12 @@ pub struct InboxRow {
|
|||
pub at: i64,
|
||||
}
|
||||
|
||||
/// One delivered message in a `RecvBatch` response. Same fields as
|
||||
/// `AgentResponse::Message` / `ManagerResponse::Message` without the
|
||||
/// variant wrapper — a batch returns a `Vec<DeliveredMessage>` so the
|
||||
/// harness can iterate without unpicking N separate top-level frames.
|
||||
/// One delivered message in a `Recv` response. The unified
|
||||
/// `Recv { max }` always returns a `Vec<DeliveredMessage>` — single
|
||||
/// pop = a one-element vec, batch = up to `max` elements, idle =
|
||||
/// empty. Each row carries the broker's id + redelivered flag so the
|
||||
/// harness can drive `AckTurn` and surface the "may already be
|
||||
/// handled" hint per-row.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct DeliveredMessage {
|
||||
pub from: String,
|
||||
|
|
@ -286,22 +288,25 @@ pub enum CancelLooseEndKind {
|
|||
pub enum AgentRequest {
|
||||
/// Send a message to another agent.
|
||||
Send { to: String, body: String },
|
||||
/// Pop one pending message from this agent's inbox. Long-polls
|
||||
/// up to `wait_seconds` (capped at 60s server-side, default 30s
|
||||
/// when None) before returning `Empty`.
|
||||
/// Pop pending messages from this agent's inbox. Always returns
|
||||
/// a list (`Messages { messages }`) — empty when nothing's
|
||||
/// pending. `max` caps the batch size (default 1 = single-message
|
||||
/// behaviour, server-side cap 32). `wait_seconds` long-polls for
|
||||
/// the first message; once one arrives (or one is already
|
||||
/// pending), the call drains up to `max` in total before
|
||||
/// returning. Same delivery + ack bookkeeping per row as before:
|
||||
/// `delivered_at = NOW`, tracked on the per-recipient
|
||||
/// `unacked_ids` list (the next `AckTurn` closes them out), and
|
||||
/// each row carries `redelivered = true` if `RequeueInflight`
|
||||
/// resurfaced it.
|
||||
Recv {
|
||||
#[serde(default)]
|
||||
wait_seconds: Option<u64>,
|
||||
/// Maximum number of messages to pop. None = 1 (single).
|
||||
/// Server-side cap is 32; values above clamp silently.
|
||||
#[serde(default)]
|
||||
max: Option<u32>,
|
||||
},
|
||||
/// Pop up to `max` pending messages in one round-trip. No
|
||||
/// long-poll — returns whatever's currently queued (possibly
|
||||
/// zero) immediately. Same delivery + ack bookkeeping as `Recv`:
|
||||
/// every popped row is marked `delivered_at = NOW`, tracked in
|
||||
/// the broker's per-recipient `unacked_ids` list (so the next
|
||||
/// `AckTurn` closes them out), and tagged `redelivered = true` if
|
||||
/// it was resurfaced by `RequeueInflight`. Used by the harness to
|
||||
/// drain a bursty inbox without N socket round-trips.
|
||||
RecvBatch { max: u32 },
|
||||
/// Non-mutating: how many pending messages are addressed to me?
|
||||
/// Used by the harness to render a status line after each tool call.
|
||||
Status,
|
||||
|
|
@ -421,28 +426,13 @@ pub enum AgentResponse {
|
|||
Ok,
|
||||
/// Either `Send` failed or `Recv` errored.
|
||||
Err { message: String },
|
||||
/// `Recv` produced a message. `id` is the broker's row id — opaque
|
||||
/// to claude (the MCP surface strips it before handing the body
|
||||
/// to the model) but tracked by the harness so the broker's
|
||||
/// in-memory unacked list can be drained on `AckTurn`. When
|
||||
/// `redelivered = true` this row was popped earlier, never
|
||||
/// acked (turn crash / OOM / restart), and resurfaced by
|
||||
/// `RequeueInflight` — the harness prepends a "may already be
|
||||
/// handled" hint to the wake prompt so claude can DTRT.
|
||||
Message {
|
||||
from: String,
|
||||
body: String,
|
||||
#[serde(default)]
|
||||
id: i64,
|
||||
#[serde(default)]
|
||||
redelivered: bool,
|
||||
},
|
||||
/// `Recv` found nothing pending.
|
||||
Empty,
|
||||
/// `RecvBatch` result. `messages` is in FIFO order and may be
|
||||
/// empty (treated like `Empty` for `Recv`); never longer than the
|
||||
/// `max` the caller passed.
|
||||
Batch { messages: Vec<DeliveredMessage> },
|
||||
/// `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 (opaque to claude;
|
||||
/// tracked by the harness for `AckTurn`) and the "previously
|
||||
/// popped, not acked" flag — see `DeliveredMessage` for details.
|
||||
Messages { messages: Vec<DeliveredMessage> },
|
||||
/// `Status` result: how many pending messages are in this agent's inbox.
|
||||
Status { unread: u64 },
|
||||
/// `Recent` result: newest-first inbox rows.
|
||||
|
|
@ -612,16 +602,16 @@ pub enum ManagerRequest {
|
|||
to: String,
|
||||
body: String,
|
||||
},
|
||||
/// Same shape as `AgentRequest::Recv` — caller-tunable long-poll
|
||||
/// duration, capped at 60s server-side, default 30s when None.
|
||||
/// Same shape as `AgentRequest::Recv` — caller-tunable
|
||||
/// `wait_seconds` (capped at 60s server-side, default 30s when
|
||||
/// None) for first-message long-poll, plus `max` (default 1, cap
|
||||
/// 32) to drain up to N popped rows in one round-trip.
|
||||
Recv {
|
||||
#[serde(default)]
|
||||
wait_seconds: Option<u64>,
|
||||
#[serde(default)]
|
||||
max: Option<u32>,
|
||||
},
|
||||
/// Mirror of `AgentRequest::RecvBatch` on the manager surface —
|
||||
/// pop up to `max` pending messages in one round-trip, no
|
||||
/// long-poll. Same ack + redelivery bookkeeping.
|
||||
RecvBatch { max: u32 },
|
||||
/// Non-mutating: pending message count, used to render a status line
|
||||
/// after each MCP tool call (mirrors `AgentRequest::Status`).
|
||||
Status,
|
||||
|
|
@ -759,23 +749,11 @@ pub enum ManagerResponse {
|
|||
Err {
|
||||
message: String,
|
||||
},
|
||||
/// Same delivery shape as `AgentResponse::Message` — `id` +
|
||||
/// `redelivered` carry the broker's row id and the
|
||||
/// "previously popped, not acked" flag through the manager
|
||||
/// surface so the manager harness drives the same
|
||||
/// requeue-with-hint flow as a sub-agent.
|
||||
Message {
|
||||
from: String,
|
||||
body: String,
|
||||
#[serde(default)]
|
||||
id: i64,
|
||||
#[serde(default)]
|
||||
redelivered: bool,
|
||||
},
|
||||
Empty,
|
||||
/// Mirror of `AgentResponse::Batch` on the manager surface.
|
||||
/// `messages` is in FIFO order and may be empty.
|
||||
Batch {
|
||||
/// Mirror of `AgentResponse::Messages` on the manager surface.
|
||||
/// Always-list shape: 0..=max popped rows, FIFO-ordered. Carries
|
||||
/// per-row `id` + `redelivered` so the manager harness drives the
|
||||
/// same ack + requeue-with-hint flow as a sub-agent.
|
||||
Messages {
|
||||
messages: Vec<DeliveredMessage>,
|
||||
},
|
||||
Status {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue