Persist agent stats across restarts, add per-tool metrics grid

Stats now survive daemon restarts via ~/.consciousness/agent-stats.json,
loaded into a global Mutex<HashMap> on first access. Each tool type
tracks last count, EWMA (alpha=0.3), and total calls.

UI shows a grid view: tool | last | avg | total, sorted by total desc.
Failures row appears at bottom if any occurred.

Also fixes temperature/priority not being applied to spawned agents.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
Kent Overstreet 2026-04-11 23:03:10 -04:00
parent 314ae9c4cb
commit f408bb5d86
4 changed files with 148 additions and 56 deletions

View file

@ -142,17 +142,19 @@ impl Unconscious {
self.agents.iter().map(|a| {
let history = store.map(|st| st.recent_by_provenance(&a.name, 30))
.unwrap_or_default();
let stats = crate::agent::oneshot::get_stats(&a.name);
let tool_calls_ewma: f64 = stats.by_tool.values().map(|t| t.ewma).sum();
UnconsciousSnapshot {
name: a.name.clone(),
running: a.is_running(),
enabled: a.enabled,
runs: a.auto.runs,
runs: stats.runs,
last_run_secs_ago: a.last_run.map(|t| t.elapsed().as_secs_f64()),
agent: a.agent.clone(),
last_stats: a.auto.last_stats.clone(),
last_stats: stats.last_stats.clone(),
history,
tool_calls_ewma: a.auto.tool_calls_ewma,
tool_failures_ewma: a.auto.tool_failures_ewma,
tool_calls_ewma,
tool_failures_ewma: stats.failures.ewma,
}
}).collect()
}
@ -186,7 +188,7 @@ impl Unconscious {
agent.auto = auto_back;
match result {
Ok(_) => dbglog!("[unconscious] {} completed (run {})",
agent.name, agent.auto.runs),
agent.name, crate::agent::oneshot::get_stats(&agent.name).runs),
Err(e) => dbglog!("[unconscious] {} failed: {}", agent.name, e),
}
}
@ -242,7 +244,7 @@ impl Unconscious {
// Swap auto out, replace steps with resolved prompts
let mut auto = std::mem::replace(&mut self.agents[idx].auto,
AutoAgent::new(String::new(), vec![], vec![], 0.0, 0));
AutoAgent::new(String::new(), vec![], vec![], 0.6, 0));
let orig_steps = std::mem::replace(&mut auto.steps,
batch.steps.iter().map(|s| AutoStep {
prompt: s.prompt.clone(),
@ -291,7 +293,8 @@ impl Unconscious {
{
let mut st = agent.state.lock().await;
st.provenance = auto.name.clone();
st.priority = Some(10);
st.priority = Some(auto.priority);
st.temperature = auto.temperature;
}
self.agents[idx].agent = Some(agent.clone());