feat(#1021): query_agent_state capability for agent socket GetLooseEnds/CountPendingReminders/ReminderRollup
This commit is contained in:
parent
9a1014f195
commit
4834ca413c
3 changed files with 109 additions and 30 deletions
|
|
@ -307,26 +307,40 @@ async fn dispatch(req: &AgentRequest, agent: &str, coord: &Arc<Coordinator>) ->
|
|||
return resp;
|
||||
}
|
||||
match req {
|
||||
AgentRequest::GetLooseEnds { .. } => match crate::loose_ends::for_agent(coord, agent) {
|
||||
Ok(loose_ends) => AgentResponse::LooseEnds { loose_ends },
|
||||
Err(e) => AgentResponse::Err {
|
||||
message: format!("{e:#}"),
|
||||
},
|
||||
},
|
||||
AgentRequest::CountPendingReminders { .. } => {
|
||||
match coord.broker.count_pending_reminders_for(agent) {
|
||||
Ok(count) => AgentResponse::PendingRemindersCount { count },
|
||||
Err(e) => AgentResponse::Err {
|
||||
message: format!("{e:#}"),
|
||||
AgentRequest::GetLooseEnds { agent: target } => {
|
||||
let name = resolve_agent_state_target(agent, target.as_deref());
|
||||
match name {
|
||||
Ok(name) => match crate::loose_ends::for_agent(coord, name) {
|
||||
Ok(loose_ends) => AgentResponse::LooseEnds { loose_ends },
|
||||
Err(e) => AgentResponse::Err {
|
||||
message: format!("{e:#}"),
|
||||
},
|
||||
},
|
||||
Err(message) => AgentResponse::Err { message },
|
||||
}
|
||||
}
|
||||
AgentRequest::ReminderRollup { since_secs, .. } => {
|
||||
match coord.broker.reminder_rollup_for(agent, *since_secs) {
|
||||
Ok(stats) => AgentResponse::ReminderRollup(stats),
|
||||
Err(e) => AgentResponse::Err {
|
||||
message: format!("{e:#}"),
|
||||
AgentRequest::CountPendingReminders { agent: target } => {
|
||||
let name = resolve_agent_state_target(agent, target.as_deref());
|
||||
match name {
|
||||
Ok(name) => match coord.broker.count_pending_reminders_for(name) {
|
||||
Ok(count) => AgentResponse::PendingRemindersCount { count },
|
||||
Err(e) => AgentResponse::Err {
|
||||
message: format!("{e:#}"),
|
||||
},
|
||||
},
|
||||
Err(message) => AgentResponse::Err { message },
|
||||
}
|
||||
}
|
||||
AgentRequest::ReminderRollup { since_secs, agent: target } => {
|
||||
let name = resolve_agent_state_target(agent, target.as_deref());
|
||||
match name {
|
||||
Ok(name) => match coord.broker.reminder_rollup_for(name, *since_secs) {
|
||||
Ok(stats) => AgentResponse::ReminderRollup(stats),
|
||||
Err(e) => AgentResponse::Err {
|
||||
message: format!("{e:#}"),
|
||||
},
|
||||
},
|
||||
Err(message) => AgentResponse::Err { message },
|
||||
}
|
||||
}
|
||||
// Manager-only variants are not valid on the agent socket.
|
||||
|
|
@ -610,6 +624,34 @@ fn auto_reminder_path(agent: &str) -> String {
|
|||
format!("/agents/{agent}/state/reminders/auto-{ts_ns}.md")
|
||||
}
|
||||
|
||||
/// Resolve the target agent name for `GetLooseEnds`, `CountPendingReminders`,
|
||||
/// and `ReminderRollup` on the agent socket. Returns the caller's own name
|
||||
/// when no target is specified or when the caller lacks `query_agent_state`.
|
||||
/// Returns an error string when the caller requests `"*"` (hive-wide scans
|
||||
/// are manager-only) or requests another agent without the capability.
|
||||
fn resolve_agent_state_target<'a>(caller: &'a str, target: Option<&'a str>) -> Result<&'a str, String> {
|
||||
match target {
|
||||
None => Ok(caller),
|
||||
Some("*") => Err(
|
||||
"hive-wide query (agent=\"*\") is not available on the agent socket; \
|
||||
use the manager socket for swarm-wide scans".to_owned()
|
||||
),
|
||||
Some(name) => {
|
||||
if name == caller {
|
||||
return Ok(caller);
|
||||
}
|
||||
if crate::capabilities::has_cap(caller, hive_sh4re::Capability::QueryAgentState) {
|
||||
Ok(name)
|
||||
} else {
|
||||
Err(format!(
|
||||
"agent `{caller}` does not have the query_agent_state capability; \
|
||||
agent field ignored — grant the capability to query other agents"
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolve the `due_at` unix timestamp for a Remind request. Returns
|
||||
/// distinct error messages for each failure mode (overflow on
|
||||
/// `InSeconds`, pre-epoch clock, `i64` cast wrap) so the caller can tell
|
||||
|
|
|
|||
Loading…
Reference in a new issue