feat(#1014): rename manager agent 'root' to 'ruth' in lifecycle + sh4re
This commit is contained in:
parent
268c2a66ad
commit
0c5760b0da
2 changed files with 16 additions and 38 deletions
|
|
@ -11,13 +11,13 @@ use tokio::process::Command;
|
||||||
pub const AGENT_PREFIX: &str = "h-";
|
pub const AGENT_PREFIX: &str = "h-";
|
||||||
pub const MAX_AGENT_NAME: usize = 9;
|
pub const MAX_AGENT_NAME: usize = 9;
|
||||||
/// Logical name of the manager agent (broker recipient, state-dir key,
|
/// Logical name of the manager agent (broker recipient, state-dir key,
|
||||||
/// meta flake attribute). All persistent state lives under `root/`.
|
/// meta flake attribute). All persistent state lives under `ruth/`.
|
||||||
pub const MANAGER_NAME: &str = "root";
|
pub const MANAGER_NAME: &str = "ruth";
|
||||||
/// Container name of the manager. Uses the same `h-` prefix as sub-agents
|
/// Container name of the manager. Uses the same `h-` prefix as sub-agents
|
||||||
/// so `nixos-container list` output is uniform and the list filter is
|
/// so `nixos-container list` output is uniform and the list filter is
|
||||||
/// a single `starts_with(AGENT_PREFIX)` check. Logical name → container
|
/// a single `starts_with(AGENT_PREFIX)` check. Logical name → container
|
||||||
/// name: `root` → `h-root`.
|
/// name: `ruth` → `h-ruth`.
|
||||||
pub const MANAGER_CONTAINER: &str = "h-root";
|
pub const MANAGER_CONTAINER: &str = "h-ruth";
|
||||||
|
|
||||||
/// Mount point of the per-agent runtime directory inside the container.
|
/// Mount point of the per-agent runtime directory inside the container.
|
||||||
pub const CONTAINER_RUNTIME_MOUNT: &str = "/run/hive";
|
pub const CONTAINER_RUNTIME_MOUNT: &str = "/run/hive";
|
||||||
|
|
@ -26,8 +26,8 @@ pub const CONTAINER_RUNTIME_MOUNT: &str = "/run/hive";
|
||||||
/// container. The harness service runs as a non-root unix user
|
/// container. The harness service runs as a non-root unix user
|
||||||
/// whose home is `/home/<agent>/`, so the mount path varies per
|
/// whose home is `/home/<agent>/`, so the mount path varies per
|
||||||
/// agent — `container_claude_mount(name)` returns
|
/// agent — `container_claude_mount(name)` returns
|
||||||
/// `/home/<name>/.claude` for sub-agents and `/home/root/.claude`
|
/// `/home/<name>/.claude` for every agent including the manager.
|
||||||
/// for the manager. `claude` inside the container reads
|
/// `claude` inside the container reads
|
||||||
/// `$HOME/.claude` and the service environment sets `HOME` to the
|
/// `$HOME/.claude` and the service environment sets `HOME` to the
|
||||||
/// same path, so the OAuth session survives container restarts.
|
/// same path, so the OAuth session survives container restarts.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
|
@ -74,16 +74,7 @@ pub fn agent_web_port(name: &str) -> u16 {
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn container_name(name: &str) -> String {
|
pub fn container_name(name: &str) -> String {
|
||||||
if name == MANAGER_NAME {
|
format!("{AGENT_PREFIX}{name}")
|
||||||
MANAGER_CONTAINER.to_owned()
|
|
||||||
} else {
|
|
||||||
format!("{AGENT_PREFIX}{name}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
pub fn is_manager(name: &str) -> bool {
|
|
||||||
name == MANAGER_NAME
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read the agent user's `(uid, gid)` from the container's nixos-managed
|
/// Read the agent user's `(uid, gid)` from the container's nixos-managed
|
||||||
|
|
@ -143,9 +134,6 @@ fn validate(name: &str) -> Result<()> {
|
||||||
if name.is_empty() {
|
if name.is_empty() {
|
||||||
bail!("agent name must not be empty");
|
bail!("agent name must not be empty");
|
||||||
}
|
}
|
||||||
if is_manager(name) {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
if name.len() > MAX_AGENT_NAME {
|
if name.len() > MAX_AGENT_NAME {
|
||||||
bail!(
|
bail!(
|
||||||
"agent name '{name}' is too long ({} chars); max {MAX_AGENT_NAME}",
|
"agent name '{name}' is too long ({} chars); max {MAX_AGENT_NAME}",
|
||||||
|
|
@ -164,18 +152,14 @@ async fn port_collision(self_name: &str) -> Option<String> {
|
||||||
let port = agent_web_port(self_name);
|
let port = agent_web_port(self_name);
|
||||||
let raw = list().await.unwrap_or_default();
|
let raw = list().await.unwrap_or_default();
|
||||||
for c in raw {
|
for c in raw {
|
||||||
let other = if c == MANAGER_CONTAINER {
|
let Some(other) = c.strip_prefix(AGENT_PREFIX) else {
|
||||||
MANAGER_NAME.to_owned()
|
|
||||||
} else if let Some(n) = c.strip_prefix(AGENT_PREFIX) {
|
|
||||||
n.to_owned()
|
|
||||||
} else {
|
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if other == self_name {
|
if other == self_name {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if agent_web_port(&other) == port && is_running(&other).await {
|
if agent_web_port(other) == port && is_running(other).await {
|
||||||
return Some(other);
|
return Some(other.to_owned());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
|
|
@ -240,17 +224,11 @@ async fn agents_for_meta(name_to_add: Option<&str>) -> Result<Vec<crate::meta::A
|
||||||
let mut out: Vec<crate::meta::AgentSpec> = containers
|
let mut out: Vec<crate::meta::AgentSpec> = containers
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|c| {
|
.filter_map(|c| {
|
||||||
let (name, is_manager) = if c == MANAGER_CONTAINER {
|
let name = c.strip_prefix(AGENT_PREFIX)?.to_owned();
|
||||||
(MANAGER_NAME.to_owned(), true)
|
|
||||||
} else if let Some(n) = c.strip_prefix(AGENT_PREFIX) {
|
|
||||||
(n.to_owned(), false)
|
|
||||||
} else {
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
Some(crate::meta::AgentSpec {
|
Some(crate::meta::AgentSpec {
|
||||||
|
is_manager: name == MANAGER_NAME,
|
||||||
port: agent_web_port(&name),
|
port: agent_web_port(&name),
|
||||||
name,
|
name,
|
||||||
is_manager,
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
@ -258,9 +236,9 @@ async fn agents_for_meta(name_to_add: Option<&str>) -> Result<Vec<crate::meta::A
|
||||||
&& !out.iter().any(|a| a.name == extra)
|
&& !out.iter().any(|a| a.name == extra)
|
||||||
{
|
{
|
||||||
out.push(crate::meta::AgentSpec {
|
out.push(crate::meta::AgentSpec {
|
||||||
name: extra.to_owned(),
|
is_manager: extra == MANAGER_NAME,
|
||||||
is_manager: is_manager(extra),
|
|
||||||
port: agent_web_port(extra),
|
port: agent_web_port(extra),
|
||||||
|
name: extra.to_owned(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
out.sort_by(|a, b| a.name.cmp(&b.name));
|
out.sort_by(|a, b| a.name.cmp(&b.name));
|
||||||
|
|
@ -1104,7 +1082,7 @@ fn set_nspawn_flags(
|
||||||
let original = std::fs::read_to_string(&path).with_context(|| format!("read {path}"))?;
|
let original = std::fs::read_to_string(&path).with_context(|| format!("read {path}"))?;
|
||||||
|
|
||||||
// Logical agent name — strip the `h-` prefix.
|
// Logical agent name — strip the `h-` prefix.
|
||||||
// For the manager: `h-root` → `root`. For sub-agents: `h-iris` → `iris`.
|
// For the manager: `h-ruth` → `ruth`. For sub-agents: `h-iris` → `iris`.
|
||||||
let agent_name = container.strip_prefix(AGENT_PREFIX).unwrap_or(container);
|
let agent_name = container.strip_prefix(AGENT_PREFIX).unwrap_or(container);
|
||||||
|
|
||||||
// Claude credentials land at `/home/<agent>/.claude` so the
|
// Claude credentials land at `/home/<agent>/.claude` so the
|
||||||
|
|
|
||||||
|
|
@ -614,7 +614,7 @@ fn default_true() -> bool {
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
/// Logical name the broker uses for the manager.
|
/// Logical name the broker uses for the manager.
|
||||||
pub const MANAGER_AGENT: &str = "root";
|
pub const MANAGER_AGENT: &str = "ruth";
|
||||||
|
|
||||||
/// Logical name the broker uses for the human operator. Messages with
|
/// Logical name the broker uses for the human operator. Messages with
|
||||||
/// `to = OPERATOR_RECIPIENT` accumulate in sqlite and surface on the
|
/// `to = OPERATOR_RECIPIENT` accumulate in sqlite and surface on the
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue