hivectl: rename hivectl agents to hivectl agent <name> <verb>
This commit is contained in:
parent
f48ba3ca0d
commit
03afbd1316
19 changed files with 367 additions and 525 deletions
|
|
@ -17,8 +17,9 @@ recovery / debugging verbs.\
|
|||
)]
|
||||
pub struct Cli {
|
||||
/// Path to the hive-c0re host admin socket, used by the daemon-assisted
|
||||
/// verbs (`agents`, `stop`, `start`). Global: accepted before or after
|
||||
/// the subcommand. Verbs that don't talk to the daemon ignore it.
|
||||
/// verbs (`agent`, `list-agents`, `stop`, `start`). Global: accepted
|
||||
/// before or after the subcommand. Verbs that don't talk to the daemon
|
||||
/// ignore it.
|
||||
#[arg(long, global = true, default_value = DEFAULT_HOST_SOCKET)]
|
||||
pub(crate) socket: PathBuf,
|
||||
#[command(subcommand)]
|
||||
|
|
@ -61,14 +62,36 @@ pub enum Cmd {
|
|||
#[command(subcommand)]
|
||||
cmd: GatewayCmd,
|
||||
},
|
||||
/// Agent container management.
|
||||
/// Lifecycle actions on ONE managed agent container. Needs the
|
||||
/// hive-c0re daemon running.
|
||||
///
|
||||
/// Lifecycle actions on managed agent containers. Needs the hive-c0re
|
||||
/// daemon running.
|
||||
Agents {
|
||||
/// Everything here targets a single named agent (`hivectl agent foo
|
||||
/// restart`, `hivectl agent foo choom`, …) — anything that acts
|
||||
/// hive-wide lives at the top level instead (`list-agents`,
|
||||
/// `restart`/`stop`/`start` with a scope, `quota-enable`).
|
||||
Agent {
|
||||
/// Agent name (e.g. `damocles`, `iris`).
|
||||
name: String,
|
||||
#[command(subcommand)]
|
||||
cmd: AgentsCmd,
|
||||
cmd: AgentCmd,
|
||||
},
|
||||
/// Show all managed agents with their status and technical state.
|
||||
///
|
||||
/// Global — not scoped to one agent, so it lives at the top level
|
||||
/// rather than under `hivectl agent <name>`. Needs the hive-c0re
|
||||
/// daemon running.
|
||||
ListAgents {
|
||||
/// Emit the raw JSON rows instead of the padded table (for
|
||||
/// scripting). The table is the default human-readable shape.
|
||||
#[arg(long)]
|
||||
json: bool,
|
||||
},
|
||||
/// Enable btrfs qgroup accounting on the agent-state filesystem.
|
||||
///
|
||||
/// Global one-shot toggle (not per-agent), hence top-level rather than
|
||||
/// under `hivectl agent <name>`. Idempotent — safe to re-run. Once
|
||||
/// enabled, `hivectl agent <name> quota show`/`quota set` work.
|
||||
QuotaEnable,
|
||||
/// Operator approval queue: list, approve, or deny pending requests.
|
||||
///
|
||||
/// Needs the hive-c0re daemon running.
|
||||
|
|
@ -98,22 +121,6 @@ pub enum Cmd {
|
|||
#[arg(long)]
|
||||
wg_endpoint: Option<String>,
|
||||
},
|
||||
/// Open an interactive Claude session inside an agent container.
|
||||
///
|
||||
/// A fresh session by default, or resume a prior one. Requires root
|
||||
/// and a running container.
|
||||
Choom {
|
||||
/// Agent name (e.g. `damocles`, `iris`).
|
||||
name: String,
|
||||
/// Resume a prior claude session by its session id, passed
|
||||
/// through as `claude --resume <value>` (claude's `--continue`
|
||||
/// takes no value — it resumes the cwd's latest session, which
|
||||
/// is the harness's, so choom never uses it; this flag matches
|
||||
/// the claude flag it maps to). Omit for a fresh blank session.
|
||||
/// A value is required when the flag is given.
|
||||
#[arg(long = "resume", value_name = "SESSION")]
|
||||
resume_session: Option<String>,
|
||||
},
|
||||
/// Stop containers hive-wide in one operator action.
|
||||
///
|
||||
/// Bare `hivectl stop` stops everything; scope flags narrow it to
|
||||
|
|
@ -435,128 +442,68 @@ pub enum WgCmd {
|
|||
Status,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
pub enum QuotaCmd {
|
||||
/// Enable btrfs qgroup accounting on the agent-state filesystem.
|
||||
///
|
||||
/// Run once before `show` / `limit`. No-op on non-btrfs hosts.
|
||||
Enable,
|
||||
/// Report per-agent disk usage from btrfs qgroups (all agents, or one
|
||||
/// by name).
|
||||
Show {
|
||||
/// Agent to show (omit for all agents with a state subvolume).
|
||||
name: Option<String>,
|
||||
},
|
||||
/// Set or clear an agent's disk-usage quota.
|
||||
///
|
||||
/// Named `set` rather than `set-quota` because the enclosing `quota`
|
||||
/// group already carries the noun — `agents quota set iris 5G`. The
|
||||
/// `set-<noun>` spelling stays for the flat verbs (`set-parent`,
|
||||
/// `set-limits`), which have no group to inherit it from.
|
||||
Set {
|
||||
/// Agent whose state subvolume to limit.
|
||||
name: String,
|
||||
/// Size cap (`5G`, `500M`, `1073741824`) or `none` to clear.
|
||||
size: String,
|
||||
},
|
||||
}
|
||||
|
||||
// Default host admin socket path. Shared with `hive-c0re`'s `main.rs`
|
||||
// default via `hive_host_sock::HOST_SOCKET` — the daemon binds there
|
||||
// and `hivectl agents` connects to it.
|
||||
// and `hivectl` connects to it.
|
||||
pub(crate) use hive_host_sock::HOST_SOCKET as DEFAULT_HOST_SOCKET;
|
||||
|
||||
/// Verbs under `hivectl agent <name> <verb>` — every one of these targets
|
||||
/// the single agent named on the parent command, so none of them carry
|
||||
/// their own `name` field.
|
||||
#[derive(Subcommand)]
|
||||
pub enum AgentsCmd {
|
||||
/// Show all managed agents with their status and technical state.
|
||||
List {
|
||||
/// Emit the raw JSON rows instead of the padded table (for
|
||||
/// scripting). The table is the default human-readable shape.
|
||||
#[arg(long)]
|
||||
json: bool,
|
||||
},
|
||||
/// Stop and start a single agent container without rebuilding config.
|
||||
pub enum AgentCmd {
|
||||
/// Stop and start this agent container without rebuilding config.
|
||||
Restart {
|
||||
/// Agent name (e.g. `damocles`, `ruth`).
|
||||
name: String,
|
||||
/// Return immediately after the restart DAG is queued.
|
||||
#[arg(long)]
|
||||
no_wait: bool,
|
||||
},
|
||||
/// Restart all managed agent containers.
|
||||
RestartAll {
|
||||
/// Return immediately after the restart DAGs are queued.
|
||||
#[arg(long)]
|
||||
no_wait: bool,
|
||||
},
|
||||
/// Park an agent's turn loop, leaving the container running.
|
||||
/// Park this agent's turn loop, leaving the container running.
|
||||
///
|
||||
/// The harness stops driving turns but keeps serving its web UI and
|
||||
/// MCP daemons, so the container, its mounts and its warm caches stay
|
||||
/// up while it burns no tokens. Inbox messages queue unacked and the
|
||||
/// backlog drains on `resume`. Sticky: it survives a restart, and
|
||||
/// pausing a stopped agent makes it come up paused.
|
||||
Pause {
|
||||
/// Agent name.
|
||||
name: String,
|
||||
},
|
||||
/// Resume a paused agent — it drains whatever queued up while parked.
|
||||
Resume {
|
||||
/// Agent name.
|
||||
name: String,
|
||||
},
|
||||
/// Spawn a new agent container directly, bypassing the approval queue.
|
||||
Pause,
|
||||
/// Resume this paused agent — it drains whatever queued up while parked.
|
||||
Resume,
|
||||
/// Spawn this agent container directly, bypassing the approval queue.
|
||||
///
|
||||
/// Operator-on-the-host only; use `request-spawn` for an approval-gated
|
||||
/// spawn.
|
||||
Spawn {
|
||||
/// Agent name (e.g. `iris`).
|
||||
name: String,
|
||||
},
|
||||
Spawn,
|
||||
/// Queue a spawn request for operator approval.
|
||||
RequestSpawn {
|
||||
/// Agent name.
|
||||
name: String,
|
||||
},
|
||||
/// Stop a managed container (graceful).
|
||||
Kill {
|
||||
/// Agent name.
|
||||
name: String,
|
||||
},
|
||||
/// Tear down a sub-agent container, keeping its state by default. No
|
||||
/// undo.
|
||||
RequestSpawn,
|
||||
/// Stop this managed container (graceful).
|
||||
Kill,
|
||||
/// Tear down this sub-agent container, keeping its state by default.
|
||||
/// No undo.
|
||||
Destroy {
|
||||
/// Agent name.
|
||||
name: String,
|
||||
/// Also wipe the agent's state dirs (config + creds + notes).
|
||||
#[arg(long)]
|
||||
purge: bool,
|
||||
},
|
||||
/// Apply pending config to a managed container.
|
||||
Rebuild {
|
||||
/// Agent name.
|
||||
name: String,
|
||||
},
|
||||
/// Move an agent in the topology tree — under a new parent, or to root.
|
||||
/// Apply pending config to this managed container.
|
||||
Rebuild,
|
||||
/// Move this agent in the topology tree — under a new parent, or to
|
||||
/// root.
|
||||
SetParent {
|
||||
/// Agent to move.
|
||||
child: String,
|
||||
/// New parent agent name. Mutually exclusive with `--root`.
|
||||
#[arg(long, conflicts_with = "root", required_unless_present = "root")]
|
||||
parent: Option<String>,
|
||||
/// Promote `child` to root (no parent).
|
||||
/// Promote this agent to root (no parent).
|
||||
#[arg(long)]
|
||||
root: bool,
|
||||
},
|
||||
/// Declare an agent's CPU/memory limits, overriding the hive-wide defaults.
|
||||
/// Declare this agent's CPU/memory limits, overriding the hive-wide
|
||||
/// defaults.
|
||||
///
|
||||
/// Replaces the agent's whole override entry rather than merging into
|
||||
/// it: any limit you don't pass returns to the hive-wide default. To
|
||||
/// change one and keep the other, pass both. Disk is a separate
|
||||
/// resource with its own group — see `agents quota`.
|
||||
/// resource with its own group — see `quota`.
|
||||
SetLimits {
|
||||
/// Agent name.
|
||||
name: String,
|
||||
/// systemd `CPUQuota=` value, e.g. `400%` (100% = one full core).
|
||||
#[arg(long, conflicts_with = "reset")]
|
||||
cpu_quota: Option<String>,
|
||||
|
|
@ -573,15 +520,29 @@ pub enum AgentsCmd {
|
|||
)]
|
||||
reset: bool,
|
||||
},
|
||||
/// Per-agent disk accounting + optional quotas via btrfs qgroups.
|
||||
/// Open an interactive Claude session inside this agent's container.
|
||||
///
|
||||
/// Opt-in: enable qgroup accounting, then report per-agent usage or
|
||||
/// cap an agent. No-op on non-btrfs hosts.
|
||||
/// A fresh session by default, or resume a prior one. Requires root
|
||||
/// and a running container.
|
||||
Choom {
|
||||
/// Resume a prior claude session by its session id, passed
|
||||
/// through as `claude --resume <value>` (claude's `--continue`
|
||||
/// takes no value — it resumes the cwd's latest session, which
|
||||
/// is the harness's, so choom never uses it; this flag matches
|
||||
/// the claude flag it maps to). Omit for a fresh blank session.
|
||||
/// A value is required when the flag is given.
|
||||
#[arg(long = "resume", value_name = "SESSION")]
|
||||
resume_session: Option<String>,
|
||||
},
|
||||
/// This agent's disk accounting + optional quota via btrfs qgroups.
|
||||
///
|
||||
/// Needs `hivectl quota-enable` run once hive-wide first. No-op on
|
||||
/// non-btrfs hosts.
|
||||
Quota {
|
||||
#[command(subcommand)]
|
||||
cmd: QuotaCmd,
|
||||
cmd: AgentQuotaCmd,
|
||||
},
|
||||
/// btrfs subvolume management for agent state dirs.
|
||||
/// btrfs subvolume management for this agent's state dir.
|
||||
///
|
||||
/// Upgrade an existing plain-dir agent's state into a btrfs subvolume
|
||||
/// so it gains snapshots and per-subvol usage/quota.
|
||||
|
|
@ -591,6 +552,17 @@ pub enum AgentsCmd {
|
|||
},
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
pub enum AgentQuotaCmd {
|
||||
/// Report this agent's disk usage from btrfs qgroups.
|
||||
Show,
|
||||
/// Set or clear this agent's disk-usage quota.
|
||||
Set {
|
||||
/// Size cap (`5G`, `500M`, `1073741824`) or `none` to clear.
|
||||
size: String,
|
||||
},
|
||||
}
|
||||
|
||||
/// Operator approval queue: list, approve, or deny pending requests.
|
||||
#[derive(Subcommand)]
|
||||
pub enum ApprovalsCmd {
|
||||
|
|
@ -615,14 +587,12 @@ pub enum SubvolCmd {
|
|||
///
|
||||
/// Bounces the agent to migrate its state, so it requires `--yes`.
|
||||
Upgrade {
|
||||
/// Agent name (e.g. `damocles`, `iris`).
|
||||
name: String,
|
||||
/// Confirm: this stops the agent, migrates its state dir, and
|
||||
/// restarts it. Required — the command refuses without it.
|
||||
#[arg(long)]
|
||||
yes: bool,
|
||||
},
|
||||
/// Read-only snapshots of an agent's state subvolume.
|
||||
/// Read-only snapshots of this agent's state subvolume.
|
||||
Snapshot {
|
||||
#[command(subcommand)]
|
||||
cmd: SnapshotCmd,
|
||||
|
|
@ -633,8 +603,6 @@ pub enum SubvolCmd {
|
|||
pub enum SnapshotCmd {
|
||||
/// Create a read-only snapshot (agent must already be a subvolume).
|
||||
Create {
|
||||
/// Agent name (e.g. `damocles`, `iris`).
|
||||
name: String,
|
||||
/// Snapshot label. Mandatory, and must start with `hive-` — the
|
||||
/// prefix doubles as an allow-list hive-priv checks so only
|
||||
/// hivectl-issued snapshot names can reach the `btrfs subvolume
|
||||
|
|
@ -644,8 +612,6 @@ pub enum SnapshotCmd {
|
|||
},
|
||||
/// Delete a snapshot created by `subvol snapshot create`.
|
||||
Delete {
|
||||
/// Agent name the snapshot belongs to.
|
||||
name: String,
|
||||
/// Snapshot label passed to `subvol snapshot create --label`.
|
||||
label: String,
|
||||
},
|
||||
|
|
@ -655,8 +621,6 @@ pub enum SnapshotCmd {
|
|||
/// point-in-time backup: a full send with no `--parent` produces a
|
||||
/// self-contained archive of the snapshot.
|
||||
Send {
|
||||
/// Agent name the snapshot belongs to.
|
||||
name: String,
|
||||
/// Snapshot label passed to `subvol snapshot create --label`.
|
||||
label: String,
|
||||
/// Optional parent snapshot label for an incremental send
|
||||
|
|
|
|||
Loading…
Reference in a new issue