organize: fine-grained agent logging + cluster size cap
Add progress callback to run_one_agent and run_and_apply so callers can see: prompt size, node list, LLM call timing, parsed action count, and per-action applied/skipped status. Daemon writes these to the persistent event log via log_event. Cap organize cluster to 20 nodes - 126 nodes produced a 682KB prompt that timed out every time. Agent has tools to explore further if needed. Restore general query for production runs.
This commit is contained in:
parent
01aba4c12b
commit
4cacfa7599
4 changed files with 56 additions and 6 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
{"agent":"organize","query":"all | key:*identity* | sort:degree | limit:1","model":"sonnet","schedule":"weekly","tools":["Bash(poc-memory:*)"]}
|
{"agent":"organize","query":"all | not-visited:organize,0 | sort:degree | limit:5","model":"sonnet","schedule":"weekly","tools":["Bash(poc-memory:*)"]}
|
||||||
|
|
||||||
# Memory Organization Agent
|
# Memory Organization Agent
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -125,11 +125,17 @@ fn job_consolidation_agent(
|
||||||
) -> Result<(), TaskError> {
|
) -> Result<(), TaskError> {
|
||||||
let agent = agent_type.to_string();
|
let agent = agent_type.to_string();
|
||||||
let batch = batch_size;
|
let batch = batch_size;
|
||||||
run_job(ctx, &format!("c-{}", agent), || {
|
let job_name = format!("c-{}", agent);
|
||||||
|
let job_name2 = job_name.clone();
|
||||||
|
run_job(ctx, &job_name, || {
|
||||||
ctx.log_line("loading store");
|
ctx.log_line("loading store");
|
||||||
let mut store = crate::store::Store::load()?;
|
let mut store = crate::store::Store::load()?;
|
||||||
ctx.log_line(&format!("running agent: {} (batch={})", agent, batch));
|
ctx.log_line(&format!("running agent: {} (batch={})", agent, batch));
|
||||||
let (total, applied) = super::knowledge::run_and_apply(&mut store, &agent, batch, "consolidate")?;
|
let log = |msg: &str| {
|
||||||
|
ctx.log_line(msg);
|
||||||
|
log_event(&job_name2, "progress", msg);
|
||||||
|
};
|
||||||
|
let (total, applied) = super::knowledge::run_and_apply_with_log(&mut store, &agent, batch, "consolidate", &log)?;
|
||||||
ctx.log_line(&format!("done: {} actions ({} applied)", total, applied));
|
ctx.log_line(&format!("done: {} actions ({} applied)", total, applied));
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
|
@ -147,7 +153,8 @@ fn job_rename_agent(
|
||||||
let batch = if batch_size == 0 { 10 } else { batch_size };
|
let batch = if batch_size == 0 { 10 } else { batch_size };
|
||||||
ctx.log_line(&format!("running rename agent (batch={})", batch));
|
ctx.log_line(&format!("running rename agent (batch={})", batch));
|
||||||
|
|
||||||
let result = super::knowledge::run_one_agent(&mut store, "rename", batch, "consolidate")?;
|
let log = |msg: &str| ctx.log_line(msg);
|
||||||
|
let result = super::knowledge::run_one_agent(&mut store, "rename", batch, "consolidate", &log)?;
|
||||||
|
|
||||||
// Parse RENAME actions from response (rename uses its own format, not WRITE_NODE/LINK/REFINE)
|
// Parse RENAME actions from response (rename uses its own format, not WRITE_NODE/LINK/REFINE)
|
||||||
let mut applied = 0;
|
let mut applied = 0;
|
||||||
|
|
|
||||||
|
|
@ -184,6 +184,11 @@ fn resolve(
|
||||||
}
|
}
|
||||||
cluster.sort_by(|a, b| a.0.cmp(&b.0));
|
cluster.sort_by(|a, b| a.0.cmp(&b.0));
|
||||||
|
|
||||||
|
// Cap cluster size — agent has tools to explore more if needed
|
||||||
|
if cluster.len() > 20 {
|
||||||
|
cluster.truncate(20);
|
||||||
|
}
|
||||||
|
|
||||||
// Similarity pairs
|
// Similarity pairs
|
||||||
let pairs = crate::similarity::pairwise_similar(&cluster, 0.4);
|
let pairs = crate::similarity::pairwise_similar(&cluster, 0.4);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -579,13 +579,33 @@ pub fn run_and_apply(
|
||||||
batch_size: usize,
|
batch_size: usize,
|
||||||
llm_tag: &str,
|
llm_tag: &str,
|
||||||
) -> Result<(usize, usize), String> {
|
) -> Result<(usize, usize), String> {
|
||||||
let result = run_one_agent(store, agent_name, batch_size, llm_tag)?;
|
run_and_apply_with_log(store, agent_name, batch_size, llm_tag, &|_| {})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run_and_apply_with_log(
|
||||||
|
store: &mut Store,
|
||||||
|
agent_name: &str,
|
||||||
|
batch_size: usize,
|
||||||
|
llm_tag: &str,
|
||||||
|
log: &dyn Fn(&str),
|
||||||
|
) -> Result<(usize, usize), String> {
|
||||||
|
let result = run_one_agent(store, agent_name, batch_size, llm_tag, log)?;
|
||||||
let actions = resolve_action_names(store, result.actions);
|
let actions = resolve_action_names(store, result.actions);
|
||||||
let ts = store::compact_timestamp();
|
let ts = store::compact_timestamp();
|
||||||
let mut applied = 0;
|
let mut applied = 0;
|
||||||
for action in &actions {
|
for action in &actions {
|
||||||
|
let desc = match &action.kind {
|
||||||
|
ActionKind::WriteNode { key, .. } => format!("WRITE {}", key),
|
||||||
|
ActionKind::Refine { key, .. } => format!("REFINE {}", key),
|
||||||
|
ActionKind::Link { source, target } => format!("LINK {} → {}", source, target),
|
||||||
|
ActionKind::Demote { key } => format!("DEMOTE {}", key),
|
||||||
|
ActionKind::Delete { key } => format!("DELETE {}", key),
|
||||||
|
};
|
||||||
if apply_action(store, action, agent_name, &ts, 0) {
|
if apply_action(store, action, agent_name, &ts, 0) {
|
||||||
|
log(&format!("applied: {}", desc));
|
||||||
applied += 1;
|
applied += 1;
|
||||||
|
} else {
|
||||||
|
log(&format!("skipped: {}", desc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok((actions.len(), applied))
|
Ok((actions.len(), applied))
|
||||||
|
|
@ -600,13 +620,29 @@ pub fn run_one_agent(
|
||||||
agent_name: &str,
|
agent_name: &str,
|
||||||
batch_size: usize,
|
batch_size: usize,
|
||||||
llm_tag: &str,
|
llm_tag: &str,
|
||||||
|
log: &dyn Fn(&str),
|
||||||
) -> Result<AgentResult, String> {
|
) -> Result<AgentResult, String> {
|
||||||
let def = super::defs::get_def(agent_name)
|
let def = super::defs::get_def(agent_name)
|
||||||
.ok_or_else(|| format!("no .agent file for {}", agent_name))?;
|
.ok_or_else(|| format!("no .agent file for {}", agent_name))?;
|
||||||
|
|
||||||
|
log("building prompt");
|
||||||
let agent_batch = super::defs::run_agent(store, &def, batch_size)?;
|
let agent_batch = super::defs::run_agent(store, &def, batch_size)?;
|
||||||
|
|
||||||
|
let prompt_kb = agent_batch.prompt.len() / 1024;
|
||||||
|
let tools_desc = if def.tools.is_empty() { "no tools".into() }
|
||||||
|
else { format!("{} tools", def.tools.len()) };
|
||||||
|
log(&format!("prompt {}KB, model={}, {}, {} nodes",
|
||||||
|
prompt_kb, def.model, tools_desc, agent_batch.node_keys.len()));
|
||||||
|
for key in &agent_batch.node_keys {
|
||||||
|
log(&format!(" node: {}", key));
|
||||||
|
}
|
||||||
|
|
||||||
|
log("calling LLM");
|
||||||
let output = llm::call_for_def(&def, &agent_batch.prompt)?;
|
let output = llm::call_for_def(&def, &agent_batch.prompt)?;
|
||||||
|
|
||||||
|
let output_kb = output.len() / 1024;
|
||||||
|
log(&format!("response {}KB", output_kb));
|
||||||
|
|
||||||
// Store raw output for audit trail
|
// Store raw output for audit trail
|
||||||
let ts = store::compact_timestamp();
|
let ts = store::compact_timestamp();
|
||||||
let report_key = format!("_{}-{}-{}", llm_tag, agent_name, ts);
|
let report_key = format!("_{}-{}-{}", llm_tag, agent_name, ts);
|
||||||
|
|
@ -616,6 +652,8 @@ pub fn run_one_agent(
|
||||||
let actions = parse_all_actions(&output);
|
let actions = parse_all_actions(&output);
|
||||||
let no_ops = count_no_ops(&output);
|
let no_ops = count_no_ops(&output);
|
||||||
|
|
||||||
|
log(&format!("parsed {} actions, {} no-ops", actions.len(), no_ops));
|
||||||
|
|
||||||
// Record visits for processed nodes
|
// Record visits for processed nodes
|
||||||
if !agent_batch.node_keys.is_empty() {
|
if !agent_batch.node_keys.is_empty() {
|
||||||
store.record_agent_visits(&agent_batch.node_keys, agent_name).ok();
|
store.record_agent_visits(&agent_batch.node_keys, agent_name).ok();
|
||||||
|
|
@ -889,7 +927,7 @@ fn run_cycle(
|
||||||
for agent_name in &agent_names {
|
for agent_name in &agent_names {
|
||||||
eprintln!("\n --- {} (n={}) ---", agent_name, config.batch_size);
|
eprintln!("\n --- {} (n={}) ---", agent_name, config.batch_size);
|
||||||
|
|
||||||
let result = match run_one_agent(&mut store, agent_name, config.batch_size, "knowledge") {
|
let result = match run_one_agent(&mut store, agent_name, config.batch_size, "knowledge", &|msg| eprintln!(" {}", msg)) {
|
||||||
Ok(r) => r,
|
Ok(r) => r,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!(" ERROR: {}", e);
|
eprintln!(" ERROR: {}", e);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue