hive-sh4re + docs: extract Ask/Answer routing prose (#717 batch 2)
This commit is contained in:
parent
3958079a8e
commit
a12c097044
2 changed files with 45 additions and 34 deletions
|
|
@ -108,6 +108,42 @@ each id in a per-recipient in-memory set so the next `Recv` can tag
|
||||||
the row with `redelivered: true`. Idempotent + cheap when there's
|
the row with `redelivered: true`. Idempotent + cheap when there's
|
||||||
nothing in flight, so the at-boot fire is unconditional.
|
nothing in flight, so the at-boot fire is unconditional.
|
||||||
|
|
||||||
|
### Question routing (Ask / Answer)
|
||||||
|
|
||||||
|
`AgentRequest::Ask` (and the manager-flavour mirror) surfaces a
|
||||||
|
structured question that either lands in the operator's dashboard
|
||||||
|
queue or in a peer agent's inbox. The recipient is the `to` field:
|
||||||
|
|
||||||
|
- `to = None` or `to = Some("operator")` — routes to the
|
||||||
|
operator-question queue. The dashboard renders the question with
|
||||||
|
any `options` as a chip strip plus a free-text fallback (`Other…`)
|
||||||
|
so the operator is never trapped by an incomplete list. The
|
||||||
|
legacy `AskOperator` variant collapses into this case.
|
||||||
|
- `to = Some(<agent>)` — peer Q&A. The target agent receives a
|
||||||
|
`HelperEvent::QuestionAsked { id, asker, question, options, multi }`
|
||||||
|
in their inbox. They reply via `AgentRequest::Answer` (or
|
||||||
|
`ManagerRequest::Answer` if they're the manager); the answer
|
||||||
|
threads back to the asker as a `HelperEvent::QuestionAnswered`
|
||||||
|
event.
|
||||||
|
|
||||||
|
Shape fields are uniform across both targets:
|
||||||
|
|
||||||
|
- `options` is advisory — the dashboard chips are decoration over a
|
||||||
|
free-text fallback; peer-agent recipients see the list in their
|
||||||
|
`QuestionAsked` event and can return any string.
|
||||||
|
- `multi = true` lets the answerer pick multiple options (checkboxes
|
||||||
|
in the dashboard, a hint in the peer-agent event). The answer
|
||||||
|
comes back as a single string with selections joined by `", "`.
|
||||||
|
- `ttl_seconds` auto-cancels with answer `[expired]` (and `answerer:
|
||||||
|
"ttl-watchdog"`) when the wait becomes moot. `None` = wait
|
||||||
|
indefinitely or until manual cancel.
|
||||||
|
|
||||||
|
Response shape is always `QuestionQueued { id }` — the asker stores
|
||||||
|
the id and correlates the asynchronous answer event when it lands.
|
||||||
|
Authorisation on `Answer`: only the question's `target` agent (or
|
||||||
|
the operator via the dashboard) is permitted to reply; an answer
|
||||||
|
attempt from anyone else fails the wire-side check.
|
||||||
|
|
||||||
### Loose-ends wire shape
|
### Loose-ends wire shape
|
||||||
|
|
||||||
`LooseEnd` is the per-row response shape for `GetLooseEnds` (both
|
`LooseEnd` is the per-row response shape for `GetLooseEnds` (both
|
||||||
|
|
|
||||||
|
|
@ -337,15 +337,8 @@ pub enum AgentRequest {
|
||||||
/// per-agent web UI uses this to render its own inbox section.
|
/// per-agent web UI uses this to render its own inbox section.
|
||||||
Recent { limit: u64 },
|
Recent { limit: u64 },
|
||||||
/// Surface a question to either the operator or another agent.
|
/// Surface a question to either the operator or another agent.
|
||||||
/// `to = None` (or `Some("operator")`) routes the question to the
|
/// Routing + shape: see
|
||||||
/// dashboard's operator-question queue (legacy `AskOperator`
|
/// `docs/conventions.md::Question routing (Ask / Answer)`.
|
||||||
/// behaviour). `to = Some(<agent>)` routes it to that agent's
|
|
||||||
/// inbox as a `HelperEvent::QuestionAsked` so the recipient can
|
|
||||||
/// answer back via `AgentRequest::Answer` (or
|
|
||||||
/// `ManagerRequest::Answer`); the answer threads back to the asker
|
|
||||||
/// as a `HelperEvent::QuestionAnswered` event. Either way the
|
|
||||||
/// response shape is `QuestionQueued { id }` — the asker uses the
|
|
||||||
/// id to correlate the asynchronous answer event.
|
|
||||||
Ask {
|
Ask {
|
||||||
question: String,
|
question: String,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
|
@ -354,17 +347,13 @@ pub enum AgentRequest {
|
||||||
multi: bool,
|
multi: bool,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
ttl_seconds: Option<u64>,
|
ttl_seconds: Option<u64>,
|
||||||
/// Recipient of the question. `None` or `Some("operator")` =
|
|
||||||
/// the human operator (dashboard); `Some(<agent_name>)` = a
|
|
||||||
/// peer agent (their inbox).
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
to: Option<String>,
|
to: Option<String>,
|
||||||
},
|
},
|
||||||
/// Answer a question previously routed to this agent via
|
/// Answer a question previously routed to this agent via
|
||||||
/// `HelperEvent::QuestionAsked`. The caller is implicitly the
|
/// `HelperEvent::QuestionAsked`. Authorised callers + threading
|
||||||
/// answerer; only the question's `target` agent (or the operator,
|
/// back via `HelperEvent::QuestionAnswered`: see
|
||||||
/// via the dashboard) is authorised. Wires through to
|
/// `docs/conventions.md::Question routing (Ask / Answer)`.
|
||||||
/// `HelperEvent::QuestionAnswered` in the asker's inbox.
|
|
||||||
Answer { id: i64, answer: String },
|
Answer { id: i64, answer: String },
|
||||||
/// Schedule a reminder message to be delivered to this agent at a
|
/// Schedule a reminder message to be delivered to this agent at a
|
||||||
/// future time. The reminder lands in the agent's inbox as an auto-sent
|
/// future time. The reminder lands in the agent's inbox as an auto-sent
|
||||||
|
|
@ -723,22 +712,8 @@ pub enum ManagerRequest {
|
||||||
description: Option<String>,
|
description: Option<String>,
|
||||||
},
|
},
|
||||||
/// Surface a question to either the operator or another agent.
|
/// Surface a question to either the operator or another agent.
|
||||||
/// Mirrors `AgentRequest::Ask` exactly — see that doc for the
|
/// Manager-flavour mirror of `AgentRequest::Ask` — routing + shape
|
||||||
/// routing semantics (operator = dashboard queue; agent = the
|
/// docs in `docs/conventions.md::Question routing (Ask / Answer)`.
|
||||||
/// peer's inbox via `HelperEvent::QuestionAsked`).
|
|
||||||
///
|
|
||||||
/// - `options` is advisory: empty = free-text only; non-empty = the
|
|
||||||
/// dashboard renders the choices alongside a free-text fallback
|
|
||||||
/// ("Other…") so the operator is never trapped.
|
|
||||||
/// - `multi=true` lets the operator pick multiple options (rendered
|
|
||||||
/// as checkboxes). The answer is returned as a single string with
|
|
||||||
/// selections joined by ", ".
|
|
||||||
/// - `ttl_seconds`: optional auto-cancel after that many seconds. On
|
|
||||||
/// expiry the question is resolved with answer `[expired]` and the
|
|
||||||
/// asker gets the usual `QuestionAnswered` event. None = wait
|
|
||||||
/// forever for an answer (or manual cancel).
|
|
||||||
/// - `to`: recipient (None / `Some("operator")` = operator;
|
|
||||||
/// `Some(<agent>)` = peer agent).
|
|
||||||
Ask {
|
Ask {
|
||||||
question: String,
|
question: String,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
|
@ -751,8 +726,8 @@ pub enum ManagerRequest {
|
||||||
to: Option<String>,
|
to: Option<String>,
|
||||||
},
|
},
|
||||||
/// Answer a question previously routed to the manager via
|
/// Answer a question previously routed to the manager via
|
||||||
/// `HelperEvent::QuestionAsked` (i.e. an agent asked the manager
|
/// `HelperEvent::QuestionAsked`. Mirror of `AgentRequest::Answer`;
|
||||||
/// for input). Mirror of `AgentRequest::Answer`.
|
/// see `docs/conventions.md::Question routing (Ask / Answer)`.
|
||||||
Answer { id: i64, answer: String },
|
Answer { id: i64, answer: String },
|
||||||
/// Fetch recent journal lines for a sub-agent container. `agent`
|
/// Fetch recent journal lines for a sub-agent container. `agent`
|
||||||
/// is the logical agent name; hive-c0re resolves it to the
|
/// is the logical agent name; hive-c0re resolves it to the
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue