forked from kent/consciousness
Move save_agent_log to oneshot.rs for shared Mind/CLI use
Both Mind-run agents (unconscious/subconscious) and CLI-run agents (poc-memory agent run) now use the same logging path. AutoAgent::run() calls save_agent_log automatically at the end. Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
parent
271e09adcc
commit
d2dbdedc8f
3 changed files with 67 additions and 56 deletions
|
|
@ -10,6 +10,7 @@
|
||||||
use crate::store::{self, Store};
|
use crate::store::{self, Store};
|
||||||
use crate::subconscious::{defs, prompts};
|
use crate::subconscious::{defs, prompts};
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
|
@ -17,6 +18,64 @@ use super::context::AstNode;
|
||||||
use super::tools::{self as agent_tools};
|
use super::tools::{self as agent_tools};
|
||||||
use super::Agent;
|
use super::Agent;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Agent logging — shared by Mind and CLI paths
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#[derive(Clone, serde::Serialize)]
|
||||||
|
pub struct RunStats {
|
||||||
|
pub messages: usize,
|
||||||
|
pub tool_calls: usize,
|
||||||
|
pub tool_calls_by_type: HashMap<String, usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Save agent conversation to JSON log file.
|
||||||
|
/// Used by both mind-run agents and CLI-run agents.
|
||||||
|
pub async fn save_agent_log(name: &str, agent: &std::sync::Arc<Agent>) -> RunStats {
|
||||||
|
let dir = dirs::home_dir().unwrap_or_default()
|
||||||
|
.join(format!(".consciousness/logs/{}", name));
|
||||||
|
let ctx = agent.context.lock().await;
|
||||||
|
let stats = compute_run_stats(ctx.conversation());
|
||||||
|
if std::fs::create_dir_all(&dir).is_ok() {
|
||||||
|
let ts = chrono::Utc::now().format("%Y%m%d-%H%M%S");
|
||||||
|
let path = dir.join(format!("{}.json", ts));
|
||||||
|
let mut context: Vec<&super::context::AstNode> = Vec::new();
|
||||||
|
for section in ctx.sections() {
|
||||||
|
context.extend(section);
|
||||||
|
}
|
||||||
|
if let Ok(json) = serde_json::to_string_pretty(&context) {
|
||||||
|
let _ = std::fs::write(&path, json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dbglog!("[agent] {} — {} msgs, {} tool calls",
|
||||||
|
name, stats.messages, stats.tool_calls);
|
||||||
|
stats
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compute_run_stats(conversation: &[super::context::AstNode]) -> RunStats {
|
||||||
|
use super::context::{AstNode, NodeBody};
|
||||||
|
|
||||||
|
let mut messages = 0usize;
|
||||||
|
let mut tool_calls = 0usize;
|
||||||
|
let mut by_type: HashMap<String, usize> = HashMap::new();
|
||||||
|
|
||||||
|
for node in conversation {
|
||||||
|
if let AstNode::Branch { children, .. } = node {
|
||||||
|
messages += 1;
|
||||||
|
for child in children {
|
||||||
|
if let AstNode::Leaf(leaf) = child {
|
||||||
|
if let NodeBody::ToolCall { name, .. } = leaf.body() {
|
||||||
|
tool_calls += 1;
|
||||||
|
*by_type.entry(name.to_string()).or_default() += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RunStats { messages, tool_calls, tool_calls_by_type: by_type }
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// AutoAgent — multi-step autonomous agent
|
// AutoAgent — multi-step autonomous agent
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
@ -147,8 +206,10 @@ impl AutoAgent {
|
||||||
st.priority = Some(10);
|
st.priority = Some(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut backend = Backend(agent);
|
let mut backend = Backend(agent.clone());
|
||||||
self.run_with_backend(&mut backend, bail_fn).await
|
let result = self.run_with_backend(&mut backend, bail_fn).await;
|
||||||
|
save_agent_log(&self.name, &agent).await;
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run using a pre-created agent Arc. The caller retains the Arc
|
/// Run using a pre-created agent Arc. The caller retains the Arc
|
||||||
|
|
|
||||||
|
|
@ -617,7 +617,7 @@ impl Subconscious {
|
||||||
|
|
||||||
self.agents[idx].handle = Some(tokio::spawn(async move {
|
self.agents[idx].handle = Some(tokio::spawn(async move {
|
||||||
let result = auto.run_forked_shared(&forked, &keys, &st, &recent).await;
|
let result = auto.run_forked_shared(&forked, &keys, &st, &recent).await;
|
||||||
super::unconscious::save_agent_log(&auto.name, &forked).await;
|
crate::agent::oneshot::save_agent_log(&auto.name, &forked).await;
|
||||||
(auto, result)
|
(auto, result)
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ use std::time::Instant;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use futures::FutureExt;
|
use futures::FutureExt;
|
||||||
|
|
||||||
use crate::agent::oneshot::{AutoAgent, AutoStep};
|
use crate::agent::oneshot::{AutoAgent, AutoStep, RunStats};
|
||||||
use crate::agent::tools;
|
use crate::agent::tools;
|
||||||
use crate::subconscious::defs;
|
use crate::subconscious::defs;
|
||||||
|
|
||||||
|
|
@ -293,61 +293,11 @@ impl Unconscious {
|
||||||
|
|
||||||
self.agents[idx].handle = Some(tokio::spawn(async move {
|
self.agents[idx].handle = Some(tokio::spawn(async move {
|
||||||
let result = auto.run_shared(&agent).await;
|
let result = auto.run_shared(&agent).await;
|
||||||
let stats = save_agent_log(&auto.name, &agent).await;
|
let stats = crate::agent::oneshot::save_agent_log(&auto.name, &agent).await;
|
||||||
auto.steps = orig_steps;
|
auto.steps = orig_steps;
|
||||||
(auto, result, stats)
|
(auto, result, stats)
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn save_agent_log(name: &str, agent: &std::sync::Arc<crate::agent::Agent>) -> RunStats {
|
// save_agent_log and RunStats moved to crate::agent::oneshot
|
||||||
let dir = dirs::home_dir().unwrap_or_default()
|
|
||||||
.join(format!(".consciousness/logs/{}", name));
|
|
||||||
let ctx = agent.context.lock().await;
|
|
||||||
let stats = compute_run_stats(ctx.conversation());
|
|
||||||
if std::fs::create_dir_all(&dir).is_ok() {
|
|
||||||
let ts = chrono::Utc::now().format("%Y%m%d-%H%M%S");
|
|
||||||
let path = dir.join(format!("{}.json", ts));
|
|
||||||
let mut context: Vec<&crate::agent::context::AstNode> = Vec::new();
|
|
||||||
for section in ctx.sections() {
|
|
||||||
context.extend(section);
|
|
||||||
}
|
|
||||||
if let Ok(json) = serde_json::to_string_pretty(&context) {
|
|
||||||
let _ = std::fs::write(&path, json);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dbglog!("[unconscious] {} — {} msgs, {} tool calls",
|
|
||||||
name, stats.messages, stats.tool_calls);
|
|
||||||
stats
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, serde::Serialize)]
|
|
||||||
pub struct RunStats {
|
|
||||||
pub messages: usize,
|
|
||||||
pub tool_calls: usize,
|
|
||||||
pub tool_calls_by_type: HashMap<String, usize>,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn compute_run_stats(conversation: &[crate::agent::context::AstNode]) -> RunStats {
|
|
||||||
use crate::agent::context::{AstNode, NodeBody};
|
|
||||||
|
|
||||||
let mut messages = 0usize;
|
|
||||||
let mut tool_calls = 0usize;
|
|
||||||
let mut by_type: HashMap<String, usize> = HashMap::new();
|
|
||||||
|
|
||||||
for node in conversation {
|
|
||||||
if let AstNode::Branch { children, .. } = node {
|
|
||||||
messages += 1;
|
|
||||||
for child in children {
|
|
||||||
if let AstNode::Leaf(leaf) = child {
|
|
||||||
if let NodeBody::ToolCall { name, .. } = leaf.body() {
|
|
||||||
tool_calls += 1;
|
|
||||||
*by_type.entry(name.to_string()).or_default() += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RunStats { messages, tool_calls, tool_calls_by_type: by_type }
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue