feat(#2017): add hivectl agents list verb showing agent status + technical state

This commit is contained in:
damocles 2026-06-26 22:12:50 +02:00 committed by mara
commit 70d1cdc859
5 changed files with 186 additions and 0 deletions

View file

@ -44,6 +44,11 @@ pub enum HostRequest {
Rebuild { name: String },
/// List managed containers.
List,
/// List managed agents with their full status + technical state
/// (running / needs-login / needs-update / deployed sha / parent /
/// pending reminders) — the `hivectl agents list` roster view.
/// Reuses the dashboard's per-agent `ContainerView` aggregation.
AgentStatus,
/// Report this hive's canonical DNS domain
/// (`services.hyperhive.domain`), or `None` when unset. Lets the
/// operator CLI fill in the hive's own identity (e.g. the federation
@ -140,6 +145,11 @@ pub struct HostResponse {
/// when the domain is unset (no `services.hyperhive.domain`).
#[serde(default, skip_serializing_if = "Option::is_none")]
pub domain: Option<String>,
/// `AgentStatus` result — one row per managed agent with its
/// running/health flags + technical state. `None` for every other
/// request kind.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub agent_statuses: Option<Vec<AgentStatusRow>>,
}
/// One row in the approval queue. `commit_ref` is overloaded per
@ -236,6 +246,7 @@ impl HostResponse {
agents: None,
approvals: None,
domain: None,
agent_statuses: None,
}
}
@ -247,6 +258,7 @@ impl HostResponse {
agents: None,
approvals: None,
domain: None,
agent_statuses: None,
}
}
@ -258,6 +270,7 @@ impl HostResponse {
agents: Some(agents),
approvals: None,
domain: None,
agent_statuses: None,
}
}
@ -269,6 +282,7 @@ impl HostResponse {
agents: None,
approvals: Some(approvals),
domain: None,
agent_statuses: None,
}
}
@ -281,6 +295,20 @@ impl HostResponse {
agents: None,
approvals: None,
domain,
agent_statuses: None,
}
}
/// `AgentStatus` result — one row per managed agent.
#[must_use]
pub fn agent_statuses(rows: Vec<AgentStatusRow>) -> Self {
Self {
ok: true,
error: None,
agents: None,
approvals: None,
domain: None,
agent_statuses: Some(rows),
}
}
}
@ -836,6 +864,34 @@ pub struct ContainerInfo {
pub running: bool,
}
/// One row in a `HostRequest::AgentStatus` result — the operator-CLI
/// projection of the dashboard's per-agent `ContainerView`. Carries the
/// agent's running/health flags plus the technical state an operator
/// wants in a roster overview (`hivectl agents list`).
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentStatusRow {
/// Logical agent name (no `h-` prefix).
pub name: String,
/// Whether the container is currently running.
pub running: bool,
/// Config commit is pending — the locked rev differs from the
/// agent's proposed/applied config (a rebuild would change it).
pub needs_update: bool,
/// The agent has no live claude session and is parked waiting for
/// the operator's re-auth flow.
pub needs_login: bool,
/// First 12 chars of the sha the meta flake currently has locked for
/// this agent's input. `None` when the agent has no locked rev yet.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub deployed_sha: Option<String>,
/// Count of this agent's pending reminders.
#[serde(default)]
pub pending_reminders: u64,
/// Parent in the topology tree. `None` marks a root-level agent.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub parent: Option<String>,
}
/// Serde default for the `running` field; keeps wire backwards-compat
/// with pre-running-field payloads. See
/// `docs/conventions.md::Agent metadata`.