feat(#2302): thread &Ident through agent path builders
This commit is contained in:
parent
1286029947
commit
bf644cc126
23 changed files with 168 additions and 85 deletions
|
|
@ -64,20 +64,27 @@ pub async fn build_all(coord: &Coordinator) -> Vec<ContainerView> {
|
|||
let topology = crate::topology::read();
|
||||
let mut out = Vec::new();
|
||||
for c in &raw {
|
||||
let Some(logical) = c.strip_prefix(AGENT_PREFIX).map(str::to_owned) else {
|
||||
let Some(logical) = c.strip_prefix(AGENT_PREFIX) else {
|
||||
continue;
|
||||
};
|
||||
// Parse the nspawn machine suffix into an Ident once at this
|
||||
// enumeration origin; a suffix that isn't a valid ident isn't one
|
||||
// of our agents, so skip it.
|
||||
let Ok(logical) = hive_host_sock::Ident::parse(logical) else {
|
||||
continue;
|
||||
};
|
||||
let deployed_full = locked
|
||||
.get(&format!("agent-{logical}"))
|
||||
.map(std::string::String::as_str);
|
||||
let needs_update = crate::auto_update::agent_config_pending(&logical, deployed_full).await;
|
||||
let needs_update =
|
||||
crate::auto_update::agent_config_pending(logical.as_str(), deployed_full).await;
|
||||
let deployed_sha = deployed_full.map(|s| s[..s.len().min(12)].to_owned());
|
||||
let pending_reminders = coord
|
||||
.broker
|
||||
.count_pending_reminders_for(logical.as_str())
|
||||
.unwrap_or(0);
|
||||
let parent = topology.get(&logical).cloned().flatten();
|
||||
let running = lifecycle::is_running(&logical).await;
|
||||
let parent = topology.get(logical.as_str()).cloned().flatten();
|
||||
let running = lifecycle::is_running(logical.as_str()).await;
|
||||
// needs_login fires when EITHER the claude session dir is missing
|
||||
// (boot-time / fresh container) OR the harness wrote the auth-failed
|
||||
// sentinel because a turn hit 401. Cleared for stopped containers —
|
||||
|
|
@ -94,10 +101,10 @@ pub async fn build_all(coord: &Coordinator) -> Vec<ContainerView> {
|
|||
None
|
||||
};
|
||||
out.push(ContainerView {
|
||||
port: lifecycle::agent_web_port(&logical),
|
||||
port: lifecycle::agent_web_port(logical.as_str()),
|
||||
running,
|
||||
container: c.clone(),
|
||||
name: logical,
|
||||
name: logical.into_string(),
|
||||
needs_update,
|
||||
needs_login,
|
||||
deployed_sha,
|
||||
|
|
@ -126,7 +133,7 @@ pub fn claude_has_session(dir: &Path) -> bool {
|
|||
/// the consolidated `hyperhive-harness.json`. Falls back to the legacy
|
||||
/// individual sentinel files written by older harness builds so in-place
|
||||
/// upgrades don't lose state during the transition window.
|
||||
fn read_harness_flags(name: &str) -> (bool, bool) {
|
||||
fn read_harness_flags(name: &hive_host_sock::Ident) -> (bool, bool) {
|
||||
let dir = Coordinator::agent_notes_dir(name);
|
||||
if let Ok(raw) = std::fs::read_to_string(dir.join("hyperhive-harness.json"))
|
||||
&& let Ok(v) = serde_json::from_str::<serde_json::Value>(&raw)
|
||||
|
|
@ -147,7 +154,7 @@ fn read_harness_flags(name: &str) -> (bool, bool) {
|
|||
(rate_limited, needs_login)
|
||||
}
|
||||
|
||||
fn auth_failed_sentinel(name: &str) -> bool {
|
||||
fn auth_failed_sentinel(name: &hive_host_sock::Ident) -> bool {
|
||||
read_harness_flags(name).1
|
||||
}
|
||||
|
||||
|
|
@ -158,7 +165,7 @@ fn auth_failed_sentinel(name: &str) -> bool {
|
|||
/// NB: callers building `AgentMeta` for a *stopped* container should
|
||||
/// clear the result — the on-disk status is a stale snapshot from
|
||||
/// before the stop. Use `read_agent_status_live` for that.
|
||||
pub fn read_agent_status(name: &str) -> (Option<String>, Option<i64>) {
|
||||
pub fn read_agent_status(name: &hive_host_sock::Ident) -> (Option<String>, Option<i64>) {
|
||||
let path = Coordinator::agent_notes_dir(name).join("hyperhive-status");
|
||||
let meta = std::fs::metadata(&path).ok();
|
||||
// Read at most STATUS_MAX_CHARS * 4 + 2 bytes: 4 is the max UTF-8 byte
|
||||
|
|
@ -198,8 +205,10 @@ pub fn read_agent_status(name: &str) -> (Option<String>, Option<i64>) {
|
|||
///
|
||||
/// Returned tuple is `(status_text, status_set_at, running)`.
|
||||
/// `name` is the logical agent name (same as the broker recipient).
|
||||
pub async fn read_agent_status_live(name: &str) -> (Option<String>, Option<i64>, bool) {
|
||||
if !lifecycle::is_running(name).await {
|
||||
pub async fn read_agent_status_live(
|
||||
name: &hive_host_sock::Ident,
|
||||
) -> (Option<String>, Option<i64>, bool) {
|
||||
if !lifecycle::is_running(name.as_str()).await {
|
||||
return (None, None, false);
|
||||
}
|
||||
let (text, set_at) = read_agent_status(name);
|
||||
|
|
@ -212,7 +221,7 @@ pub async fn read_agent_status_live(name: &str) -> (Option<String>, Option<i64>,
|
|||
/// so it always reflects the resolved priority (nix config > runtime
|
||||
/// override > default). Returns `None` when the field is absent or the
|
||||
/// harness has not yet started a turn.
|
||||
fn read_active_model(name: &str) -> Option<String> {
|
||||
fn read_active_model(name: &hive_host_sock::Ident) -> Option<String> {
|
||||
let path = Coordinator::agent_notes_dir(name).join("hyperhive-harness.json");
|
||||
let raw = std::fs::read_to_string(path).ok()?;
|
||||
let v: serde_json::Value = serde_json::from_str(&raw).ok()?;
|
||||
|
|
|
|||
Loading…
Reference in a new issue