feat: add set_status MCP tool and status field to whoami/dashboard (closes #325)
This commit is contained in:
parent
6f3b56ad84
commit
fe2933b213
8 changed files with 170 additions and 16 deletions
|
|
@ -77,6 +77,11 @@ pub struct ContainerView {
|
|||
/// the file is absent or the agent declares no links.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub extra_links: Vec<DashboardLink>,
|
||||
/// Free-text status set by the agent via `mcp__hyperhive__set_status`.
|
||||
/// Persisted to `{state_dir}/hyperhive-status`. `None` when the file
|
||||
/// is absent or empty — the agent hasn't set one yet.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub status_text: Option<String>,
|
||||
}
|
||||
|
||||
/// Build the full container list. Wraps `lifecycle::list()` and
|
||||
|
|
@ -119,6 +124,7 @@ pub async fn build_all(coord: &Coordinator) -> Vec<ContainerView> {
|
|||
.and_then(|(_, model)| resolve_ctx_window(model, &coord.context_window_tokens));
|
||||
let rate_limited = is_rate_limited(&logical);
|
||||
let extra_links = read_dashboard_links(&logical);
|
||||
let status_text = read_status_text(&logical);
|
||||
out.push(ContainerView {
|
||||
port: lifecycle::agent_web_port(&logical),
|
||||
running: lifecycle::is_running(&logical).await,
|
||||
|
|
@ -133,6 +139,7 @@ pub async fn build_all(coord: &Coordinator) -> Vec<ContainerView> {
|
|||
context_window_tokens,
|
||||
rate_limited,
|
||||
extra_links,
|
||||
status_text,
|
||||
});
|
||||
}
|
||||
out
|
||||
|
|
@ -172,6 +179,20 @@ fn is_rate_limited(name: &str) -> bool {
|
|||
.exists()
|
||||
}
|
||||
|
||||
/// Read the agent's free-text status set via `mcp__hyperhive__set_status`.
|
||||
/// Returns `None` when the file is absent or empty — best-effort, never panics.
|
||||
/// `pub` so `agent_server` and `manager_server` can include it in `Whoami` responses.
|
||||
pub fn read_agent_status_text(name: &str) -> Option<String> {
|
||||
let path = Coordinator::agent_notes_dir(name).join("hyperhive-status");
|
||||
let s = std::fs::read_to_string(path).ok()?;
|
||||
let trimmed = s.trim();
|
||||
if trimmed.is_empty() { None } else { Some(trimmed.to_owned()) }
|
||||
}
|
||||
|
||||
fn read_status_text(name: &str) -> Option<String> {
|
||||
read_agent_status_text(name)
|
||||
}
|
||||
|
||||
/// Read the agent's most recent completed turn from its turn-stats
|
||||
/// `SQLite`: the context-window size (prompt tokens) and the model name.
|
||||
/// Returns `None` when the file is absent or has no rows. Best-effort
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue