get_agent_meta: include hive_name + swarm_name in response (#710)
This commit is contained in:
parent
09c1abe5b4
commit
a91cf4493f
6 changed files with 69 additions and 1 deletions
|
|
@ -39,7 +39,7 @@ Tools (hyperhive surface):
|
||||||
<!-- /role:manager -->
|
<!-- /role:manager -->
|
||||||
- `mcp__hyperhive__remind(message, delay_seconds? | at_unix_timestamp?, file_path?)` — schedule a message to land in your *own* inbox at a future time (sender shows as `reminder`). Set exactly one of `delay_seconds` (relative) or `at_unix_timestamp` (absolute). Use for self-paced follow-ups instead of blocking a whole turn on a long `recv` wait. A large `message` auto-spills to a file under `/agents/{label}/state/reminders/`; pass `file_path` to point at one yourself. Each agent's pending-reminder count is capped (default 50) — the tool will error if the cap is already reached.
|
- `mcp__hyperhive__remind(message, delay_seconds? | at_unix_timestamp?, file_path?)` — schedule a message to land in your *own* inbox at a future time (sender shows as `reminder`). Set exactly one of `delay_seconds` (relative) or `at_unix_timestamp` (absolute). Use for self-paced follow-ups instead of blocking a whole turn on a long `recv` wait. A large `message` auto-spills to a file under `/agents/{label}/state/reminders/`; pass `file_path` to point at one yourself. Each agent's pending-reminder count is capped (default 50) — the tool will error if the cap is already reached.
|
||||||
- `mcp__hyperhive__set_status(text)` — set a free-text status visible on the operator dashboard. **Call this at the start of every task** to say what you're working on (e.g. `"processing matrix messages"`, `"fixing #319 model priority"`, `"idle"`). Single line, ≤200 chars — the dashboard renders this as a short chip, so longer multi-line text is rejected. Pass an empty string to clear. Persists across harness restarts.
|
- `mcp__hyperhive__set_status(text)` — set a free-text status visible on the operator dashboard. **Call this at the start of every task** to say what you're working on (e.g. `"processing matrix messages"`, `"fixing #319 model priority"`, `"idle"`). Single line, ≤200 chars — the dashboard renders this as a short chip, so longer multi-line text is rejected. Pass an empty string to clear. Persists across harness restarts.
|
||||||
- `mcp__hyperhive__get_agent_meta(name?)` — fetch identity + status metadata for an agent: canonical `name`, `role` (`agent` / `manager`), current `hyperhive_rev`, plus self-reported `status` text (set via `set_status`) and how long ago it was set. Pass `name` to query a peer (e.g. check whether iris is idle before pinging them). Omit `name` to get your own trustworthy identity stamp — useful for state files, commit messages, cross-agent attribution that won't drift across renames or session-continue boundaries where the system-prompt label could be stale.
|
- `mcp__hyperhive__get_agent_meta(name?)` — fetch identity + status metadata for an agent: canonical `name`, `role` (`agent` / `manager`), current `hyperhive_rev`, plus self-reported `status` text (set via `set_status`) and how long ago it was set. Also returns the hive + swarm display names (`hive_name`, `swarm_name`) when the operator has configured `services.hyperhive.{hiveName, swarmName}`; both lines omitted when unset. Pass `name` to query a peer (e.g. check whether iris is idle before pinging them). Omit `name` to get your own trustworthy identity stamp — useful for state files, commit messages, cross-agent attribution that won't drift across renames or session-continue boundaries where the system-prompt label could be stale.
|
||||||
<!-- role:agent -->
|
<!-- role:agent -->
|
||||||
- `mcp__hyperhive__request_next_turn()` — ask the harness to start another turn immediately after this one ends, even if the inbox is empty. Use for multi-turn tasks (long builds, sequential steps) where you want to continue without waiting for an external message. The next turn starts with `from: "self"` and `body: "continue"`. No-op if new inbox messages arrive before this turn ends (the harness already loops immediately on pending messages). No args.
|
- `mcp__hyperhive__request_next_turn()` — ask the harness to start another turn immediately after this one ends, even if the inbox is empty. Use for multi-turn tasks (long builds, sequential steps) where you want to continue without waiting for an external message. The next turn starts with `from: "self"` and `body: "continue"`. No-op if new inbox messages arrive before this turn ends (the harness already loops immediately on pending messages). No args.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,8 @@ pub enum SocketReply {
|
||||||
hyperhive_rev: Option<String>,
|
hyperhive_rev: Option<String>,
|
||||||
status_text: Option<String>,
|
status_text: Option<String>,
|
||||||
status_set_at: Option<i64>,
|
status_set_at: Option<i64>,
|
||||||
|
hive_name: Option<String>,
|
||||||
|
swarm_name: Option<String>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -83,6 +85,8 @@ impl From<hive_sh4re::AgentResponse> for SocketReply {
|
||||||
hyperhive_rev,
|
hyperhive_rev,
|
||||||
status_text,
|
status_text,
|
||||||
status_set_at,
|
status_set_at,
|
||||||
|
hive_name,
|
||||||
|
swarm_name,
|
||||||
} => Self::AgentMeta {
|
} => Self::AgentMeta {
|
||||||
name,
|
name,
|
||||||
role,
|
role,
|
||||||
|
|
@ -90,6 +94,8 @@ impl From<hive_sh4re::AgentResponse> for SocketReply {
|
||||||
hyperhive_rev,
|
hyperhive_rev,
|
||||||
status_text,
|
status_text,
|
||||||
status_set_at,
|
status_set_at,
|
||||||
|
hive_name,
|
||||||
|
swarm_name,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -118,6 +124,8 @@ impl From<hive_sh4re::ManagerResponse> for SocketReply {
|
||||||
hyperhive_rev,
|
hyperhive_rev,
|
||||||
status_text,
|
status_text,
|
||||||
status_set_at,
|
status_set_at,
|
||||||
|
hive_name,
|
||||||
|
swarm_name,
|
||||||
} => Self::AgentMeta {
|
} => Self::AgentMeta {
|
||||||
name,
|
name,
|
||||||
role,
|
role,
|
||||||
|
|
@ -125,6 +133,8 @@ impl From<hive_sh4re::ManagerResponse> for SocketReply {
|
||||||
hyperhive_rev,
|
hyperhive_rev,
|
||||||
status_text,
|
status_text,
|
||||||
status_set_at,
|
status_set_at,
|
||||||
|
hive_name,
|
||||||
|
swarm_name,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -298,11 +308,23 @@ pub fn format_agent_meta(resp: Result<SocketReply, anyhow::Error>) -> String {
|
||||||
hyperhive_rev,
|
hyperhive_rev,
|
||||||
status_text,
|
status_text,
|
||||||
status_set_at,
|
status_set_at,
|
||||||
|
hive_name,
|
||||||
|
swarm_name,
|
||||||
}) => {
|
}) => {
|
||||||
let rev = hyperhive_rev.as_deref().unwrap_or("<unknown>");
|
let rev = hyperhive_rev.as_deref().unwrap_or("<unknown>");
|
||||||
let run = if running { "yes" } else { "no" };
|
let run = if running { "yes" } else { "no" };
|
||||||
let mut out =
|
let mut out =
|
||||||
format!("name: {name}\nrole: {role}\nhyperhive_rev: {rev}\nrunning: {run}");
|
format!("name: {name}\nrole: {role}\nhyperhive_rev: {rev}\nrunning: {run}");
|
||||||
|
// #710: surface hive + swarm display names only when set,
|
||||||
|
// so single-hive deployments don't see noisy `<none>` lines.
|
||||||
|
if let Some(hn) = hive_name.as_deref() {
|
||||||
|
use std::fmt::Write as _;
|
||||||
|
let _ = write!(out, "\nhive_name: {hn}");
|
||||||
|
}
|
||||||
|
if let Some(sn) = swarm_name.as_deref() {
|
||||||
|
use std::fmt::Write as _;
|
||||||
|
let _ = write!(out, "\nswarm_name: {sn}");
|
||||||
|
}
|
||||||
match status_text {
|
match status_text {
|
||||||
None => out.push_str("\nstatus: <none>"),
|
None => out.push_str("\nstatus: <none>"),
|
||||||
Some(s) => {
|
Some(s) => {
|
||||||
|
|
|
||||||
|
|
@ -273,6 +273,7 @@ async fn dispatch(req: &AgentRequest, agent: &str, coord: &Arc<Coordinator>) ->
|
||||||
"agent"
|
"agent"
|
||||||
}
|
}
|
||||||
.to_owned();
|
.to_owned();
|
||||||
|
let (hive_name, swarm_name) = crate::container_view::hive_swarm_names();
|
||||||
AgentResponse::AgentMeta {
|
AgentResponse::AgentMeta {
|
||||||
name: target.to_owned(),
|
name: target.to_owned(),
|
||||||
role,
|
role,
|
||||||
|
|
@ -280,6 +281,8 @@ async fn dispatch(req: &AgentRequest, agent: &str, coord: &Arc<Coordinator>) ->
|
||||||
hyperhive_rev: crate::auto_update::current_flake_rev(&coord.hyperhive_flake),
|
hyperhive_rev: crate::auto_update::current_flake_rev(&coord.hyperhive_flake),
|
||||||
status_text,
|
status_text,
|
||||||
status_set_at,
|
status_set_at,
|
||||||
|
hive_name,
|
||||||
|
swarm_name,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AgentRequest::CancelLooseEnd { kind, id } => crate::questions::handle_cancel_loose_end(
|
AgentRequest::CancelLooseEnd { kind, id } => crate::questions::handle_cancel_loose_end(
|
||||||
|
|
|
||||||
|
|
@ -284,6 +284,26 @@ pub async fn read_agent_status_live(name: &str) -> (Option<String>, Option<i64>,
|
||||||
(text, set_at, true)
|
(text, set_at, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Host-side hive + swarm display names, read from the c0re service's
|
||||||
|
/// own process env. The `hive-c0re.nix` module sets these from
|
||||||
|
/// `services.hyperhive.{hiveName, swarmName}` (#701). The agent-side
|
||||||
|
/// `hive-ag3nt::identity::{hive_name, swarm_name}` accessors read the
|
||||||
|
/// same env vars after they're forwarded into each sub-agent's
|
||||||
|
/// harness service environment by `meta::render_flake`; surfacing
|
||||||
|
/// them here from c0re's own env keeps the manager + agent
|
||||||
|
/// `GetAgentMeta` paths consistent without a round-trip to the
|
||||||
|
/// target container (#710).
|
||||||
|
///
|
||||||
|
/// Returns `(hive_name, swarm_name)`. Each is `None` when the
|
||||||
|
/// corresponding env var is unset or empty.
|
||||||
|
#[must_use]
|
||||||
|
pub fn hive_swarm_names() -> (Option<String>, Option<String>) {
|
||||||
|
let read = |var: &str| -> Option<String> {
|
||||||
|
std::env::var(var).ok().filter(|s| !s.is_empty())
|
||||||
|
};
|
||||||
|
(read("HYPERHIVE_HIVE_NAME"), read("HYPERHIVE_SWARM_NAME"))
|
||||||
|
}
|
||||||
|
|
||||||
/// Read the agent's most recent completed turn from its turn-stats
|
/// Read the agent's most recent completed turn from its turn-stats
|
||||||
/// `SQLite`: the context-window size (prompt tokens) and the model name.
|
/// `SQLite`: the context-window size (prompt tokens) and the model name.
|
||||||
/// Returns `None` when the file is absent or has no rows. Best-effort
|
/// Returns `None` when the file is absent or has no rows. Best-effort
|
||||||
|
|
|
||||||
|
|
@ -545,6 +545,7 @@ async fn dispatch(req: &ManagerRequest, coord: &Arc<Coordinator>) -> ManagerResp
|
||||||
"agent"
|
"agent"
|
||||||
}
|
}
|
||||||
.to_owned();
|
.to_owned();
|
||||||
|
let (hive_name, swarm_name) = crate::container_view::hive_swarm_names();
|
||||||
ManagerResponse::AgentMeta {
|
ManagerResponse::AgentMeta {
|
||||||
name: target.to_owned(),
|
name: target.to_owned(),
|
||||||
role,
|
role,
|
||||||
|
|
@ -552,6 +553,8 @@ async fn dispatch(req: &ManagerRequest, coord: &Arc<Coordinator>) -> ManagerResp
|
||||||
hyperhive_rev: crate::auto_update::current_flake_rev(&coord.hyperhive_flake),
|
hyperhive_rev: crate::auto_update::current_flake_rev(&coord.hyperhive_flake),
|
||||||
status_text,
|
status_text,
|
||||||
status_set_at,
|
status_set_at,
|
||||||
|
hive_name,
|
||||||
|
swarm_name,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ManagerRequest::CancelLooseEnd { kind, id } => {
|
ManagerRequest::CancelLooseEnd { kind, id } => {
|
||||||
|
|
|
||||||
|
|
@ -574,6 +574,17 @@ pub enum AgentResponse {
|
||||||
status_text: Option<String>,
|
status_text: Option<String>,
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
status_set_at: Option<i64>,
|
status_set_at: Option<i64>,
|
||||||
|
/// Hive display name (#701 / #710) — e.g. `"pr1ma"`. Host
|
||||||
|
/// reads from its own `HYPERHIVE_HIVE_NAME` env (set by
|
||||||
|
/// `services.hyperhive.hiveName`); `None` when the option
|
||||||
|
/// isn't configured.
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
hive_name: Option<String>,
|
||||||
|
/// Swarm display name (#701 / #710) — e.g. `"constellat1on"`.
|
||||||
|
/// Source mirrors `hive_name` (`HYPERHIVE_SWARM_NAME` env /
|
||||||
|
/// `services.hyperhive.swarmName`).
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
swarm_name: Option<String>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1119,5 +1130,14 @@ pub enum ManagerResponse {
|
||||||
status_text: Option<String>,
|
status_text: Option<String>,
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
status_set_at: Option<i64>,
|
status_set_at: Option<i64>,
|
||||||
|
/// Hive display name (#701 / #710), same source + semantics
|
||||||
|
/// as on `AgentResponse::AgentMeta`. Read from the host's
|
||||||
|
/// `HYPERHIVE_HIVE_NAME` env so manager + agent surfaces
|
||||||
|
/// return the same view.
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
hive_name: Option<String>,
|
||||||
|
/// Swarm display name (#701 / #710), mirror of `hive_name`.
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
swarm_name: Option<String>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue