agent stats: track tool calls by type with EWMA, add Stats pane
- RunStats now includes tool_calls_by_type HashMap - AutoAgent tracks runs, last_stats, and EWMA for tool calls/failures - Removed duplicate stats fields from individual agent structs - Fixed provenance to use bare agent name (no "agent:" prefix) - Subconscious screen now displays both agent types consistently - Added Stats pane showing tool call breakdown sorted by count Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
parent
e9e7458013
commit
314ae9c4cb
4 changed files with 169 additions and 55 deletions
|
|
@ -294,6 +294,7 @@ pub struct SubconsciousSnapshot {
|
|||
pub enabled: bool,
|
||||
pub current_phase: String,
|
||||
pub turn: usize,
|
||||
pub runs: usize,
|
||||
pub last_run_secs_ago: Option<f64>,
|
||||
/// Shared handle to the forked agent — UI locks to read entries.
|
||||
pub forked_agent: Option<Arc<crate::agent::Agent>>,
|
||||
|
|
@ -303,6 +304,9 @@ pub struct SubconsciousSnapshot {
|
|||
pub state: std::collections::BTreeMap<String, String>,
|
||||
/// Recent store activity for this agent: (key, timestamp), newest first.
|
||||
pub history: Vec<(String, i64)>,
|
||||
pub last_stats: Option<crate::agent::oneshot::RunStats>,
|
||||
pub tool_calls_ewma: f64,
|
||||
pub tool_failures_ewma: f64,
|
||||
}
|
||||
|
||||
struct SubconsciousAgent {
|
||||
|
|
@ -367,11 +371,15 @@ impl SubconsciousAgent {
|
|||
enabled: self.auto.enabled,
|
||||
current_phase: self.auto.current_phase.clone(),
|
||||
turn: self.auto.turn,
|
||||
runs: self.auto.runs,
|
||||
last_run_secs_ago: self.last_run.map(|t| t.elapsed().as_secs_f64()),
|
||||
forked_agent: self.forked_agent.clone(),
|
||||
fork_point: self.fork_point,
|
||||
state: state.clone(),
|
||||
history,
|
||||
last_stats: self.auto.last_stats.clone(),
|
||||
tool_calls_ewma: self.auto.tool_calls_ewma,
|
||||
tool_failures_ewma: self.auto.tool_failures_ewma,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -614,7 +622,8 @@ impl Subconscious {
|
|||
|
||||
self.agents[idx].handle = Some(tokio::spawn(async move {
|
||||
let result = auto.run_forked_shared(&forked, &keys, &st, &recent).await;
|
||||
crate::agent::oneshot::save_agent_log(&auto.name, &forked).await;
|
||||
let stats = crate::agent::oneshot::save_agent_log(&auto.name, &forked).await;
|
||||
auto.update_stats(stats);
|
||||
(auto, result)
|
||||
}));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,12 +34,10 @@ struct UnconsciousAgent {
|
|||
name: String,
|
||||
enabled: bool,
|
||||
auto: AutoAgent,
|
||||
handle: Option<tokio::task::JoinHandle<(AutoAgent, Result<String, String>, RunStats)>>,
|
||||
handle: Option<tokio::task::JoinHandle<(AutoAgent, Result<String, String>)>>,
|
||||
/// Shared agent handle — UI locks to read context live.
|
||||
pub agent: Option<std::sync::Arc<crate::agent::Agent>>,
|
||||
last_run: Option<Instant>,
|
||||
runs: usize,
|
||||
last_stats: Option<RunStats>,
|
||||
}
|
||||
|
||||
impl UnconsciousAgent {
|
||||
|
|
@ -64,6 +62,8 @@ pub struct UnconsciousSnapshot {
|
|||
pub last_stats: Option<RunStats>,
|
||||
/// Recent store activity for this agent: (key, timestamp), newest first.
|
||||
pub history: Vec<(String, i64)>,
|
||||
pub tool_calls_ewma: f64,
|
||||
pub tool_failures_ewma: f64,
|
||||
}
|
||||
|
||||
pub struct Unconscious {
|
||||
|
|
@ -107,8 +107,6 @@ impl Unconscious {
|
|||
handle: None,
|
||||
agent: None,
|
||||
last_run: None,
|
||||
runs: 0,
|
||||
last_stats: None,
|
||||
});
|
||||
}
|
||||
agents.sort_by(|a, b| a.name.cmp(&b.name));
|
||||
|
|
@ -148,11 +146,13 @@ impl Unconscious {
|
|||
name: a.name.clone(),
|
||||
running: a.is_running(),
|
||||
enabled: a.enabled,
|
||||
runs: a.runs,
|
||||
runs: a.auto.runs,
|
||||
last_run_secs_ago: a.last_run.map(|t| t.elapsed().as_secs_f64()),
|
||||
agent: a.agent.clone(),
|
||||
last_stats: a.last_stats.clone(),
|
||||
last_stats: a.auto.last_stats.clone(),
|
||||
history,
|
||||
tool_calls_ewma: a.auto.tool_calls_ewma,
|
||||
tool_failures_ewma: a.auto.tool_failures_ewma,
|
||||
}
|
||||
}).collect()
|
||||
}
|
||||
|
|
@ -180,15 +180,13 @@ impl Unconscious {
|
|||
if agent.handle.as_ref().is_some_and(|h| h.is_finished()) {
|
||||
let handle = agent.handle.take().unwrap();
|
||||
agent.last_run = Some(Instant::now());
|
||||
agent.runs += 1;
|
||||
// Get the AutoAgent back from the finished task
|
||||
// Get the AutoAgent back from the finished task (stats already updated)
|
||||
match handle.now_or_never() {
|
||||
Some(Ok((auto_back, result, stats))) => {
|
||||
Some(Ok((auto_back, result))) => {
|
||||
agent.auto = auto_back;
|
||||
agent.last_stats = Some(stats);
|
||||
match result {
|
||||
Ok(_) => dbglog!("[unconscious] {} completed (run {})",
|
||||
agent.name, agent.runs),
|
||||
agent.name, agent.auto.runs),
|
||||
Err(e) => dbglog!("[unconscious] {} failed: {}", agent.name, e),
|
||||
}
|
||||
}
|
||||
|
|
@ -301,8 +299,9 @@ impl Unconscious {
|
|||
self.agents[idx].handle = Some(tokio::spawn(async move {
|
||||
let result = auto.run_shared(&agent).await;
|
||||
let stats = crate::agent::oneshot::save_agent_log(&auto.name, &agent).await;
|
||||
auto.update_stats(stats);
|
||||
auto.steps = orig_steps;
|
||||
(auto, result, stats)
|
||||
(auto, result)
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue