open_threads: new get_open_threads MCP tool on agent + manager surfaces
This commit is contained in:
parent
9ec0d60308
commit
dc1ce1f236
11 changed files with 305 additions and 9 deletions
|
|
@ -185,6 +185,46 @@ pub enum ReminderTiming {
|
|||
At { unix_timestamp: i64 },
|
||||
}
|
||||
|
||||
/// One row in the response to `GetOpenThreads`. Tagged enum so new
|
||||
/// thread kinds (forge PRs, long-running approvals from a privileged
|
||||
/// bot, etc) can land later without breaking existing handlers. The
|
||||
/// caller (claude in the agent harness) is expected to render these
|
||||
/// as a short bulleted list — the per-row fields are all the context
|
||||
/// needed without a follow-up fetch.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(tag = "kind", rename_all = "snake_case")]
|
||||
pub enum OpenThread {
|
||||
/// A pending approval. For agent-flavour `GetOpenThreads` calls
|
||||
/// this only surfaces when the agent itself is the manager
|
||||
/// (sub-agents don't submit approvals). For manager-flavour calls
|
||||
/// it lists every pending approval in the swarm. `agent` is the
|
||||
/// affected agent (target of the spawn / config commit).
|
||||
Approval {
|
||||
id: i64,
|
||||
agent: String,
|
||||
commit_ref: String,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
description: Option<String>,
|
||||
/// Wall-clock seconds since `requested_at`. Saturates at zero on
|
||||
/// any clock anomaly (back-step etc).
|
||||
age_seconds: u64,
|
||||
},
|
||||
/// An unanswered question. For agent-flavour calls: only threads
|
||||
/// where the agent is `asker` OR `target`. For manager-flavour
|
||||
/// calls: every unanswered question in the swarm. `target = None`
|
||||
/// means the question is addressed to the operator (dashboard
|
||||
/// path); `Some(agent)` is a peer-to-peer thread.
|
||||
Question {
|
||||
id: i64,
|
||||
asker: String,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
target: Option<String>,
|
||||
question: String,
|
||||
/// Wall-clock seconds since `asked_at`. Saturates at zero.
|
||||
age_seconds: u64,
|
||||
},
|
||||
}
|
||||
|
||||
/// Requests on a per-agent socket. The agent's identity is the socket
|
||||
/// it came in on; `Send.from` is filled in by the server, not the client.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
|
|
@ -263,6 +303,12 @@ pub enum AgentRequest {
|
|||
#[serde(default)]
|
||||
file_path: Option<String>,
|
||||
},
|
||||
/// Loose-ends view: pending approvals + unanswered questions
|
||||
/// pending against THIS agent. Approvals only surface if this
|
||||
/// agent submitted them (which only ever happens for the
|
||||
/// manager); questions surface where the agent is `asker` or
|
||||
/// `target`. Cheap O(n) sweep server-side — no caching.
|
||||
GetOpenThreads,
|
||||
}
|
||||
|
||||
/// Responses on a per-agent socket.
|
||||
|
|
@ -284,6 +330,9 @@ pub enum AgentResponse {
|
|||
/// `Ask` result: the queued question id. The answer lands later
|
||||
/// as `HelperEvent::QuestionAnswered` in this agent's inbox.
|
||||
QuestionQueued { id: i64 },
|
||||
/// `GetOpenThreads` result: list of loose ends pending against
|
||||
/// this agent. Ordered newest-first within each kind.
|
||||
OpenThreads { threads: Vec<OpenThread> },
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
@ -541,6 +590,12 @@ pub enum ManagerRequest {
|
|||
#[serde(default)]
|
||||
file_path: Option<String>,
|
||||
},
|
||||
/// Hive-wide loose-ends view: EVERY pending approval + EVERY
|
||||
/// unanswered question in the swarm. Used by the manager to scan
|
||||
/// for stalled coordination — the per-agent equivalent on the
|
||||
/// sub-agent surface is `AgentRequest::GetOpenThreads` which
|
||||
/// only returns rows where the agent itself is asker / target.
|
||||
GetOpenThreads,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
|
|
@ -573,4 +628,10 @@ pub enum ManagerResponse {
|
|||
Logs {
|
||||
content: String,
|
||||
},
|
||||
/// `GetOpenThreads` result: hive-wide loose ends (approvals +
|
||||
/// unanswered questions). Same `OpenThread` variants as the
|
||||
/// agent surface; the manager's view is unfiltered.
|
||||
OpenThreads {
|
||||
threads: Vec<OpenThread>,
|
||||
},
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue