diff --git a/src/agent/context.rs b/src/agent/context.rs index 094d42e..8063918 100644 --- a/src/agent/context.rs +++ b/src/agent/context.rs @@ -801,7 +801,7 @@ impl ContextState { pub fn push_log(&mut self, section: Section, node: AstNode) { if let Some(ref log) = self.conversation_log { if let Err(e) = log.append_node(&node) { - dbglog!("warning: log: {:#}", e); + eprintln!("warning: log: {:#}", e); } } self.section_mut(section).push(node); diff --git a/src/agent/mod.rs b/src/agent/mod.rs index e371a53..54bc418 100644 --- a/src/agent/mod.rs +++ b/src/agent/mod.rs @@ -42,17 +42,6 @@ pub struct ActivityGuard { id: u64, } -impl ActivityGuard { - pub async fn update(&self, label: impl Into) { - let label = label.into(); - let mut st = self.agent.state.lock().await; - if let Some(entry) = st.activities.iter_mut().find(|a| a.id == self.id) { - entry.label = label; - } - st.changed.notify_one(); - } -} - const ACTIVITY_LINGER: std::time::Duration = std::time::Duration::from_secs(5); impl Drop for ActivityGuard { @@ -318,7 +307,6 @@ impl Agent { } let mut overflow_retries: u32 = 0; - let mut overflow_activity: Option = None; let mut empty_retries: u32 = 0; let mut ds = DispatchState::new(); @@ -383,12 +371,8 @@ impl Agent { } if overflow_retries < 2 { overflow_retries += 1; - let msg = format!("context overflow — compacting ({}/2)", overflow_retries); - match &overflow_activity { - Some(a) => a.update(&msg).await, - None => overflow_activity = Some( - start_activity(&agent, &msg).await), - } + agent.state.lock().await.notify( + format!("context overflow — retrying ({}/2)", overflow_retries)); agent.compact().await; continue; } @@ -403,7 +387,7 @@ impl Agent { if let Some(ref log) = ctx.conversation_log { let node = &ctx.conversation()[branch_idx]; if let Err(e) = log.append_node(node) { - dbglog!("warning: log: {:#}", e); + eprintln!("warning: log: {:#}", e); } } } @@ -578,7 +562,7 @@ impl Agent { } } Err(e) => { - dbglog!("warning: failed to reload identity: {:#}", e); + eprintln!("warning: failed to reload identity: {:#}", e); } } diff --git a/src/agent/tools/mcp_client.rs b/src/agent/tools/mcp_client.rs index acdb095..a7348ec 100644 --- a/src/agent/tools/mcp_client.rs +++ b/src/agent/tools/mcp_client.rs @@ -140,7 +140,7 @@ fn registry() -> &'static TokioMutex { }) } -async fn ensure_init(agent: Option<&std::sync::Arc>) -> Result<()> { +async fn ensure_init() -> Result<()> { let mut reg = registry().lock().await; if !reg.servers.is_empty() { return Ok(()); } let configs = crate::config::get().mcp_servers.clone(); @@ -148,24 +148,14 @@ async fn ensure_init(agent: Option<&std::sync::Arc>) -> Res let args: Vec<&str> = cfg.args.iter().map(|s| s.as_str()).collect(); match McpServer::spawn(&cfg.name, &cfg.command, &args).await { Ok(server) => reg.servers.push(server), - Err(e) => { - let msg = format!("MCP server {} failed: {:#}", cfg.name, e); - dbglog!("{}", msg); - if let Some(a) = agent { - if let Ok(mut st) = a.state.try_lock() { - st.notify(msg); - } - } - } + Err(e) => eprintln!("warning: MCP server {} failed: {:#}", cfg.name, e), } } Ok(()) } -pub(super) async fn call_tool(name: &str, args: &serde_json::Value, - agent: Option<&std::sync::Arc>, -) -> Result { - ensure_init(agent).await?; +pub(super) async fn call_tool(name: &str, args: &serde_json::Value) -> Result { + ensure_init().await?; let mut reg = registry().lock().await; let server = reg.servers.iter_mut() .find(|s| s.tools.iter().any(|t| t.name == name)) @@ -188,7 +178,7 @@ pub(super) async fn call_tool(name: &str, args: &serde_json::Value, } pub(super) async fn tool_definitions_json() -> Vec { - let _ = ensure_init(None).await; + let _ = ensure_init().await; let reg = registry().lock().await; reg.servers.iter() .flat_map(|s| s.tools.iter()) diff --git a/src/agent/tools/mod.rs b/src/agent/tools/mod.rs index ce42c9e..55fe311 100644 --- a/src/agent/tools/mod.rs +++ b/src/agent/tools/mod.rs @@ -164,7 +164,7 @@ pub async fn dispatch_with_agent( None => true, }; if allowed { - if let Ok(result) = mcp_client::call_tool(name, args, agent.as_ref()).await { + if let Ok(result) = mcp_client::call_tool(name, args).await { return result; } } diff --git a/src/hippocampus/store/persist.rs b/src/hippocampus/store/persist.rs index 2af3983..5668dd2 100644 --- a/src/hippocampus/store/persist.rs +++ b/src/hippocampus/store/persist.rs @@ -200,7 +200,7 @@ impl Store { // Report duplicate keys for (key, uuids) in &key_uuids { if uuids.len() > 1 { - dbglog!("WARNING: key '{}' has {} UUIDs (duplicate nodes)", key, uuids.len()); + eprintln!("WARNING: key '{}' has {} UUIDs (duplicate nodes)", key, uuids.len()); } } diff --git a/src/user/chat.rs b/src/user/chat.rs index 3d2a2b6..800bf2a 100644 --- a/src/user/chat.rs +++ b/src/user/chat.rs @@ -902,8 +902,9 @@ impl InteractScreen { // Draw status bar with live activity indicator let timer = if !app.activity.is_empty() { - let elapsed = app.activity_started.map(|t| t.elapsed().as_secs()).unwrap_or(0); - format!(" {}s", elapsed) + let total = self.turn_started.map(|t| t.elapsed().as_secs()).unwrap_or(0); + let call = self.call_started.map(|t| t.elapsed().as_secs()).unwrap_or(0); + format!(" {}s, {}/{}s", total, call, self.call_timeout_secs) } else { String::new() }; @@ -1056,8 +1057,6 @@ impl ScreenView for InteractScreen { app.activity = st.activities.last() .map(|a| a.label.clone()) .unwrap_or_default(); - app.activity_started = st.activities.last() - .map(|a| a.started); } if let Ok(ctx) = self.agent.context.try_lock() { let window = crate::agent::context::context_window(); diff --git a/src/user/mod.rs b/src/user/mod.rs index 6904234..8904dcd 100644 --- a/src/user/mod.rs +++ b/src/user/mod.rs @@ -358,11 +358,7 @@ async fn run( let mut startup_done = false; let mut dirty = true; // render on first loop - let mut activity_tick = tokio::time::interval(std::time::Duration::from_secs(1)); - activity_tick.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); - loop { - let has_activity = !app.activity.is_empty(); tokio::select! { biased; @@ -384,10 +380,6 @@ async fn run( Some(channels) = channel_rx.recv() => { app.set_channel_status(channels); } - - _ = activity_tick.tick(), if has_activity => { - dirty = true; - } } // State sync on every wake