//! Container/agent-roster wire shapes: what `ListDescendants` and //! `HostRequest::AgentStatus` return, plus the per-account matrix //! identity shape surfaced by `GetAgentMeta`. use serde::{Deserialize, Serialize}; /// One entry in a `ListDescendants` result. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ContainerInfo { /// Logical agent name (no `h-` prefix). pub name: String, /// Whether the container is currently running. 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 list-agents`). // // Four orthogonal, independently-observed facts about one agent, each // rendered as its own column/token by `hivectl list-agents` and read // individually by `--json` consumers. Any combination is meaningful // (a stopped agent can be paused and need an update), so folding them // into a state machine or nested flag structs would only add // `serde(flatten)` indirection to preserve the same flat JSON. Same // rationale as `LifecycleScope` in hive-host-sock. #[allow( clippy::struct_excessive_bools, reason = "flat wire projection of independent per-agent flags" )] #[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, /// The container's unit is in systemd's `failed` state — it exhausted /// its bounded restarts and gave up, as opposed to being stopped /// deliberately. Orthogonal to `running`, like every other flag here: /// a failed unit is not running, but a not-running unit is usually /// just off. #[serde(default)] pub failed: 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, /// Count of this agent's pending reminders. #[serde(default)] pub pending_reminders: u64, /// The agent's turn loop is parked (pause marker present in its /// harness dir): the container may well be up and serving, it just /// drives no turns. Orthogonal to `running` — an agent can be /// paused while stopped, and pause survives a restart. #[serde(default)] pub paused: bool, /// Parent in the topology tree. `None` marks a root-level agent. #[serde(default, skip_serializing_if = "Option::is_none")] pub parent: Option, } /// One matrix identity an agent can act as, surfaced in `GetAgentMeta`'s /// `matrix_accounts`. Field names match the daemon's `matrix-accounts.json` /// snapshot (written by `hive-matrix-mcp`'s account registry) so hive-c0re /// deserializes the snapshot straight into `Vec`; the /// snapshot's `live` / `is_primary` fields are ignored here (only live /// accounts are listed). #[derive(Debug, Clone, Serialize, Deserialize)] pub struct MatrixIdentity { /// Logical account name (the `account` arg on the matrix MCP tools). pub name: String, /// Matrix user id (`@user:server`). `None` if the session restored /// without a known user id yet. #[serde(default, skip_serializing_if = "Option::is_none")] pub user_id: Option, /// Homeserver base URL this account is on. pub homeserver: String, }