agents: extract shared run_one_agent, standardize output formats
Three places duplicated the agent execution loop (build prompt → call LLM → store output → parse actions → record visits): consolidate.rs, knowledge.rs, and daemon.rs. Extract into run_one_agent() in knowledge.rs that all three now call. Also standardize consolidation agent prompts to use WRITE_NODE/LINK/REFINE — the same commands the parser handles. Previously agents output CATEGORIZE/NOTE/EXTRACT/DIGEST/DIFFERENTIATE/MERGE/COMPRESS which were silently dropped after the second-LLM-call removal.
This commit is contained in:
parent
f6ea659975
commit
fe7f636ad3
8 changed files with 124 additions and 189 deletions
|
|
@ -319,7 +319,58 @@ fn agent_provenance(agent: &str) -> store::Provenance {
|
|||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Agent runners
|
||||
// Shared agent execution
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Result of running a single agent through the common pipeline.
|
||||
pub struct AgentResult {
|
||||
pub output: String,
|
||||
pub actions: Vec<Action>,
|
||||
pub no_ops: usize,
|
||||
pub node_keys: Vec<String>,
|
||||
}
|
||||
|
||||
/// Run a single agent: build prompt → call LLM → store output → parse actions → record visits.
|
||||
///
|
||||
/// This is the common pipeline shared by the knowledge loop, consolidation pipeline,
|
||||
/// and daemon. Callers handle action application (with or without depth tracking).
|
||||
pub fn run_one_agent(
|
||||
store: &mut Store,
|
||||
agent_name: &str,
|
||||
batch_size: usize,
|
||||
llm_tag: &str,
|
||||
) -> Result<AgentResult, String> {
|
||||
let def = super::defs::get_def(agent_name)
|
||||
.ok_or_else(|| format!("no .agent file for {}", agent_name))?;
|
||||
let agent_batch = super::defs::run_agent(store, &def, batch_size)?;
|
||||
|
||||
let output = llm::call_sonnet(llm_tag, &agent_batch.prompt)?;
|
||||
|
||||
// Store raw output for audit trail
|
||||
let ts = store::format_datetime(store::now_epoch())
|
||||
.replace([':', '-', 'T'], "");
|
||||
let report_key = format!("_{}-{}-{}", llm_tag, agent_name, ts);
|
||||
let provenance = agent_provenance(agent_name);
|
||||
store.upsert_provenance(&report_key, &output, provenance).ok();
|
||||
|
||||
let actions = parse_all_actions(&output);
|
||||
let no_ops = count_no_ops(&output);
|
||||
|
||||
// Record visits for processed nodes
|
||||
if !agent_batch.node_keys.is_empty() {
|
||||
store.record_agent_visits(&agent_batch.node_keys, agent_name).ok();
|
||||
}
|
||||
|
||||
Ok(AgentResult {
|
||||
output,
|
||||
actions,
|
||||
no_ops,
|
||||
node_keys: agent_batch.node_keys,
|
||||
})
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Conversation fragment selection
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Extract human-readable dialogue from a conversation JSONL
|
||||
|
|
@ -573,51 +624,18 @@ fn run_cycle(
|
|||
for agent_name in &agent_names {
|
||||
eprintln!("\n --- {} (n={}) ---", agent_name, config.batch_size);
|
||||
|
||||
let def = match super::defs::get_def(agent_name) {
|
||||
Some(d) => d,
|
||||
None => {
|
||||
eprintln!(" SKIP: no .agent file for {}", agent_name);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let agent_batch = match super::defs::run_agent(&store, &def, config.batch_size) {
|
||||
Ok(b) => b,
|
||||
Err(e) => {
|
||||
eprintln!(" ERROR building prompt: {}", e);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
eprintln!(" prompt: {} chars ({} nodes)", agent_batch.prompt.len(), agent_batch.node_keys.len());
|
||||
let output = llm::call_sonnet("knowledge", &agent_batch.prompt);
|
||||
|
||||
// Record visits for processed nodes
|
||||
if !agent_batch.node_keys.is_empty() {
|
||||
if let Err(e) = store.record_agent_visits(&agent_batch.node_keys, agent_name) {
|
||||
eprintln!(" visit recording: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
let output = match output {
|
||||
Ok(o) => o,
|
||||
let result = match run_one_agent(&mut store, agent_name, config.batch_size, "knowledge") {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
eprintln!(" ERROR: {}", e);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
// Store raw output as a node (for debugging/audit)
|
||||
let raw_key = format!("_knowledge-{}-{}", agent_name, timestamp);
|
||||
let raw_content = format!("# {} Agent Results — {}\n\n{}", agent_name, timestamp, output);
|
||||
store.upsert_provenance(&raw_key, &raw_content,
|
||||
agent_provenance(agent_name)).ok();
|
||||
let mut actions = result.actions;
|
||||
all_no_ops += result.no_ops;
|
||||
|
||||
let mut actions = parse_all_actions(&output);
|
||||
let no_ops = count_no_ops(&output);
|
||||
all_no_ops += no_ops;
|
||||
|
||||
eprintln!(" Actions: {} No-ops: {}", actions.len(), no_ops);
|
||||
eprintln!(" Actions: {} No-ops: {}", actions.len(), result.no_ops);
|
||||
|
||||
let mut applied = 0;
|
||||
for action in &mut actions {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue