feat(#2067): choom --continue passes through to claude --continue (drop --resume translation)
This commit is contained in:
parent
c5847e25ea
commit
0125fcfae8
3 changed files with 51 additions and 43 deletions
|
|
@ -379,14 +379,17 @@ Generate the federation peer-config block for THIS hive — the nix a peer opera
|
|||
|
||||
Open an interactive Claude session inside an agent container.
|
||||
|
||||
Execs `machinectl shell <name>@h-<name>` running claude as the agent user from its state dir, with the same settings / MCP config / system prompt the harness uses. Without a session id you get a fresh blank session each launch; pass one to resume an earlier choom session (`--resume <id>`). Either way it never collides with the harness's live session — the harness pins its own session id via `--resume`, so a blank choom session is invisible to it. Requires root + a running container.
|
||||
Execs `machinectl shell <name>@h-<name>` running claude as the agent user from its state dir, with the same settings / MCP config / system prompt the harness uses. Bare `choom <name>` launches a fresh blank session; `choom <name> --continue <id|name>` passes `--continue <value>` straight through to claude to rejoin a prior session (claude resolves whether the value is a session id or a display name). It never collides with the harness's live session — the harness pins its own session via `--resume`, so a blank choom session is invisible to it. Requires root + a running container.
|
||||
|
||||
**Usage:** `hivectl choom <NAME> [SESSION]`
|
||||
**Usage:** `hivectl choom [OPTIONS] <NAME>`
|
||||
|
||||
###### **Arguments:**
|
||||
|
||||
* `<NAME>` — Agent name (e.g. `damocles`, `iris`)
|
||||
* `<SESSION>` — Optional session id to resume (`claude --resume <id>`). Omit for a fresh blank session
|
||||
|
||||
###### **Options:**
|
||||
|
||||
* `--continue <SESSION>` — Resume a prior claude session by id or display name, passed through as `claude --continue <value>`. Omit for a fresh blank session. A value is required when the flag is given
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -127,16 +127,18 @@ running claude from the agent's state dir. Requires root (same as all
|
|||
`machinectl shell` operations).
|
||||
|
||||
```bash
|
||||
hivectl choom iris # fresh blank Claude session in iris's container
|
||||
hivectl choom iris <session-id> # resume an earlier choom session
|
||||
hivectl choom iris # fresh blank Claude session in iris's container
|
||||
hivectl choom iris --continue <id|name> # rejoin a prior session by id or display name
|
||||
```
|
||||
|
||||
With no session id, claude starts a fresh blank session (mints its own
|
||||
id). Pass a session id to resume it (`claude --resume <id>`); you can
|
||||
rename it in-session. Either way choom never collides with the harness's
|
||||
live session in the same project dir: the harness pins its own id via
|
||||
`--resume`, so a blank choom session is invisible to it. The container
|
||||
must be running.
|
||||
Bare `choom` starts a fresh blank session. `--continue <value>` is
|
||||
passed straight through as `claude --continue <value>` to rejoin a
|
||||
prior session — claude resolves whether the value is a session id or a
|
||||
display name (you can `/rename` a session in-session for an easy
|
||||
handle). A value is required when the flag is given. Either way choom
|
||||
never collides with the harness's live session in the same project dir:
|
||||
the harness pins its own id via `--resume`, so a blank choom session is
|
||||
invisible to it. The container must be running.
|
||||
|
||||
choom reproduces the harness's own claude invocation so the operator
|
||||
lands in a faithful copy of the agent's environment:
|
||||
|
|
|
|||
|
|
@ -112,18 +112,21 @@ enum Cmd {
|
|||
///
|
||||
/// Execs `machinectl shell <name>@h-<name>` running claude as the
|
||||
/// agent user from its state dir, with the same settings / MCP config
|
||||
/// / system prompt the harness uses. Without a session id you get a
|
||||
/// fresh blank session each launch; pass one to resume an earlier
|
||||
/// choom session (`--resume <id>`). Either way it never collides with
|
||||
/// the harness's live session — the harness pins its own session id
|
||||
/// via `--resume`, so a blank choom session is invisible to it.
|
||||
/// Requires root + a running container.
|
||||
/// / system prompt the harness uses. Bare `choom <name>` launches a
|
||||
/// fresh blank session; `choom <name> --continue <id|name>` passes
|
||||
/// `--continue <value>` straight through to claude to rejoin a prior
|
||||
/// session (claude resolves whether the value is a session id or a
|
||||
/// display name). It never collides with the harness's live session —
|
||||
/// the harness pins its own session via `--resume`, so a blank choom
|
||||
/// session is invisible to it. Requires root + a running container.
|
||||
Choom {
|
||||
/// Agent name (e.g. `damocles`, `iris`).
|
||||
name: String,
|
||||
/// Optional session id to resume (`claude --resume <id>`). Omit
|
||||
/// for a fresh blank session.
|
||||
session: Option<String>,
|
||||
/// Resume a prior claude session by id or display name, passed
|
||||
/// through as `claude --continue <value>`. Omit for a fresh
|
||||
/// blank session. A value is required when the flag is given.
|
||||
#[arg(long = "continue", value_name = "SESSION")]
|
||||
continue_session: Option<String>,
|
||||
},
|
||||
/// Stop containers hive-wide in one operator action. Bare `hivectl
|
||||
/// stop` stops **everything** — all sub-agents plus the ci, forge,
|
||||
|
|
@ -630,7 +633,10 @@ async fn main() -> Result<()> {
|
|||
Cmd::Subvol { cmd } => match cmd {
|
||||
SubvolCmd::Upgrade { name, yes } => subvol_upgrade(&socket, &name, yes).await,
|
||||
},
|
||||
Cmd::Choom { name, session } => choom(&name, session.as_deref()),
|
||||
Cmd::Choom {
|
||||
name,
|
||||
continue_session,
|
||||
} => choom(&name, continue_session.as_deref()),
|
||||
Cmd::Quota { cmd } => match cmd {
|
||||
QuotaCmd::Enable => quota_enable().await,
|
||||
QuotaCmd::Show { name } => quota_show(name.as_deref()).await,
|
||||
|
|
@ -1034,15 +1040,17 @@ fn agent_exists(name: &str) -> Result<bool> {
|
|||
/// 3. **Pass the harness's flags** (`--settings` / `--mcp-config` /
|
||||
/// `--system-prompt-file` from `/run/hive-config/`), each only if its
|
||||
/// file exists so a half-up container degrades to a bare session.
|
||||
/// 4. **Pick the session explicitly.** With no `session` arg, claude
|
||||
/// starts a fresh blank session (mints a random id). Pass a session
|
||||
/// id to resume it (`--resume <id>`); the operator can rename it
|
||||
/// in-session. Either way choom never clobbers the harness's live
|
||||
/// session: the harness pins its own id via `--resume`, so a blank
|
||||
/// choom session in this shared project dir is invisible to it.
|
||||
/// 4. **Pick the session explicitly.** Bare choom starts a fresh blank
|
||||
/// session. `--continue <value>` is passed straight through as
|
||||
/// `claude --continue <value>` to rejoin a prior session — claude
|
||||
/// resolves whether the value is a session id or a display name (the
|
||||
/// operator can `/rename` a session in-session for an easy handle).
|
||||
/// Either way choom never clobbers the harness's live session: the
|
||||
/// harness pins its own id via `--resume`, so a blank choom session
|
||||
/// in this shared project dir is invisible to it.
|
||||
///
|
||||
/// Inherits the caller's PTY. Requires root + a running container.
|
||||
fn choom(name: &str, session: Option<&str>) -> Result<()> {
|
||||
fn choom(name: &str, continue_session: Option<&str>) -> Result<()> {
|
||||
if !agent_exists(name)? {
|
||||
bail!("no such agent: '{name}' (no state dir under /var/lib/hyperhive/agents/)");
|
||||
}
|
||||
|
|
@ -1059,22 +1067,17 @@ fn choom(name: &str, session: Option<&str>) -> Result<()> {
|
|||
// `hive-config`); matches `hive-ag3nt::paths::config_dir()`. These
|
||||
// are the exact files the harness passes to claude each turn.
|
||||
let cfg = "/run/hive-config";
|
||||
// A session id (if given) is resumed via `--resume <id>`; with none,
|
||||
// claude starts a fresh blank session. The id is interpolated into
|
||||
// the shell script, so constrain it to a safe charset first to rule
|
||||
// out injection (real session ids are UUIDs).
|
||||
let session_arg = match session {
|
||||
Some(sid) => {
|
||||
if sid.is_empty()
|
||||
|| !sid
|
||||
.bytes()
|
||||
.all(|b| b.is_ascii_alphanumeric() || b"-_.".contains(&b))
|
||||
{
|
||||
bail!(
|
||||
"invalid session id '{sid}': expected a claude session id (alphanumerics, '-', '_', '.')"
|
||||
);
|
||||
// `--continue <value>` (if given) is passed straight through to
|
||||
// claude; with none, claude starts a fresh blank session. The value
|
||||
// is single-quoted into the shell script, so reject an embedded
|
||||
// single quote (the only char that breaks single-quoting) to rule
|
||||
// out injection — ids and display names never contain one.
|
||||
let session_arg = match continue_session {
|
||||
Some(val) => {
|
||||
if val.contains('\'') {
|
||||
bail!("invalid --continue value '{val}': must not contain a single quote");
|
||||
}
|
||||
format!("set -- --resume {sid};")
|
||||
format!("set -- --continue '{val}';")
|
||||
}
|
||||
None => "set --;".to_string(),
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue