fix(#947): include manager in agent-sockets.json

This commit is contained in:
damocles 2026-06-01 16:29:46 +02:00 committed by mara
commit 4435666c00

View file

@ -38,7 +38,7 @@ pub const SOCKET_FILENAME: &str = "web.sock";
/// sub-agent that hasn't flipped the option yet. /// sub-agent that hasn't flipped the option yet.
/// ///
/// Renamed from `.bound` (legacy) to match the `hyperhive-` prefix /// Renamed from `.bound` (legacy) to match the `hyperhive-` prefix
/// convention for all harness-written state files. `build_map` /// convention for all harness-written state files (#838). `build_map`
/// checks both names during the transition window so existing containers /// checks both names during the transition window so existing containers
/// don't lose gateway routing before their next rebuild. /// don't lose gateway routing before their next rebuild.
pub const READY_MARKER: &str = "hyperhive-socket-bound"; pub const READY_MARKER: &str = "hyperhive-socket-bound";
@ -67,12 +67,9 @@ pub fn socket_path_for(name: &str) -> PathBuf {
} }
/// Compute the agent-socket map for the given logical agent names. /// Compute the agent-socket map for the given logical agent names.
/// Sub-agents only — manager is filtered out at the call boundary /// Includes manager and sub-agents — all managed containers that have
/// for the same reason it's filtered from `agent_ports::build_map` /// bound a unix socket get an entry. Filters by `READY_MARKER` presence:
/// (manager UI is routed via the c0re dashboard upstream, not via /// only agents whose
/// `/agent/<name>/`).
///
/// Also filters by `READY_MARKER` presence: only agents whose
/// harness has actually bound the unix socket (and dropped the /// harness has actually bound the unix socket (and dropped the
/// marker) appear in the map. Without this, the gateway would /// marker) appear in the map. Without this, the gateway would
/// `proxy_pass` to a non-existent socket for every sub-agent that /// `proxy_pass` to a non-existent socket for every sub-agent that
@ -105,7 +102,6 @@ where
{ {
names names
.iter() .iter()
.filter(|n| n.as_str() != MANAGER_NAME)
.filter(|n| is_ready(n)) .filter(|n| is_ready(n))
.map(|n| (n.clone(), socket_path_for(n))) .map(|n| (n.clone(), socket_path_for(n)))
.collect() .collect()
@ -241,18 +237,18 @@ mod tests {
} }
#[test] #[test]
fn build_map_filters_manager() { fn build_map_includes_manager() {
// Use `MANAGER_NAME` in the input so the assert actually // Manager is now included in the gateway socket map so the
// exercises the filter path — a literal `"hm1nd"` would pass // gateway can route `/agent/<manager-name>/` to its unix socket,
// trivially if the constant ever changed and the filter // giving the operator access to the manager's per-agent web UI
// silently became a no-op. All-ready predicate bypasses the // (terminal, inbox, stats). All-ready predicate bypasses the
// marker check so we exercise the manager filter in isolation. // marker check so we exercise the manager inclusion in isolation.
let names: Vec<String> = ["iris", MANAGER_NAME, "argus"] let names: Vec<String> = ["iris", MANAGER_NAME, "argus"]
.iter() .iter()
.map(|s| (*s).to_owned()) .map(|s| (*s).to_owned())
.collect(); .collect();
let map = build_map_with(&names, |_| true); let map = build_map_with(&names, |_| true);
assert!(!map.contains_key(MANAGER_NAME)); assert!(map.contains_key(MANAGER_NAME));
assert!(map.contains_key("iris")); assert!(map.contains_key("iris"));
assert!(map.contains_key("argus")); assert!(map.contains_key("argus"));
} }