agent: move oneshot execution from subconscious to agent module
Move agent execution machinery (run_one_agent, spawn_agent, PID tracking) from subconscious/knowledge.rs to agent/oneshot.rs — the agent module owns execution, subconscious owns scheduling and defs. Delete subconscious/llm.rs — callers now use api::call_api_with_tools_sync directly. Audit and compare inline the call; oneshot inlines tool filtering. Update all callers: consolidate, daemon, subconscious, cli/agent. Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
parent
1457a1b50d
commit
0f4ca9e2f2
10 changed files with 43 additions and 106 deletions
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
pub mod api;
|
pub mod api;
|
||||||
pub mod context;
|
pub mod context;
|
||||||
|
pub mod oneshot;
|
||||||
pub mod parsing;
|
pub mod parsing;
|
||||||
pub mod tools;
|
pub mod tools;
|
||||||
pub mod training;
|
pub mod training;
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
// knowledge.rs — agent execution and conversation fragment selection
|
// oneshot.rs — One-shot agent execution
|
||||||
//
|
//
|
||||||
// Agent prompts live in agents/*.agent files, dispatched via defs.rs.
|
// Runs an agent definition (from agents/*.agent files) through the API:
|
||||||
// This module handles:
|
// build prompt → call LLM with tools → return result. Agents apply
|
||||||
// - Agent execution (build prompt → call LLM with tools → log)
|
// changes via tool calls during the LLM call — no action parsing needed.
|
||||||
// - Conversation fragment selection (for observation agent)
|
|
||||||
//
|
//
|
||||||
// Agents apply changes via tool calls (poc-memory write/link-add/etc)
|
// This is distinct from the interactive agent loop in agent/mod.rs:
|
||||||
// during the LLM call — no action parsing needed.
|
// oneshot agents run a fixed prompt sequence and exit, while the
|
||||||
|
// interactive agent has a turn loop with streaming and TUI.
|
||||||
|
|
||||||
use super::llm;
|
|
||||||
use crate::store::{self, Store};
|
use crate::store::{self, Store};
|
||||||
|
use crate::subconscious::{defs, prompts};
|
||||||
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
@ -93,7 +93,6 @@ pub fn run_and_apply_with_log(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Like run_and_apply_with_log but with an in-flight exclusion set.
|
/// Like run_and_apply_with_log but with an in-flight exclusion set.
|
||||||
/// Returns the keys that were processed (for the daemon to track).
|
|
||||||
pub fn run_and_apply_excluded(
|
pub fn run_and_apply_excluded(
|
||||||
store: &mut Store,
|
store: &mut Store,
|
||||||
agent_name: &str,
|
agent_name: &str,
|
||||||
|
|
@ -103,7 +102,6 @@ pub fn run_and_apply_excluded(
|
||||||
exclude: &std::collections::HashSet<String>,
|
exclude: &std::collections::HashSet<String>,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
let _result = run_one_agent_excluded(store, agent_name, batch_size, llm_tag, log, exclude)?;
|
let _result = run_one_agent_excluded(store, agent_name, batch_size, llm_tag, log, exclude)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -116,7 +114,7 @@ pub fn run_one_agent_with_keys(
|
||||||
llm_tag: &str,
|
llm_tag: &str,
|
||||||
log: &(dyn Fn(&str) + Sync),
|
log: &(dyn Fn(&str) + Sync),
|
||||||
) -> Result<AgentResult, String> {
|
) -> Result<AgentResult, String> {
|
||||||
let def = super::defs::get_def(agent_name)
|
let def = 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))?;
|
||||||
|
|
||||||
let (state_dir, pid_path, _guard) = setup_agent_state(agent_name, &def)?;
|
let (state_dir, pid_path, _guard) = setup_agent_state(agent_name, &def)?;
|
||||||
|
|
@ -126,16 +124,16 @@ pub fn run_one_agent_with_keys(
|
||||||
let mut resolved_steps = Vec::new();
|
let mut resolved_steps = Vec::new();
|
||||||
let mut all_keys: Vec<String> = keys.to_vec();
|
let mut all_keys: Vec<String> = keys.to_vec();
|
||||||
for step in &def.steps {
|
for step in &def.steps {
|
||||||
let (prompt, extra_keys) = super::defs::resolve_placeholders(
|
let (prompt, extra_keys) = defs::resolve_placeholders(
|
||||||
&step.prompt, store, &graph, keys, count,
|
&step.prompt, store, &graph, keys, count,
|
||||||
);
|
);
|
||||||
all_keys.extend(extra_keys);
|
all_keys.extend(extra_keys);
|
||||||
resolved_steps.push(super::prompts::ResolvedStep {
|
resolved_steps.push(prompts::ResolvedStep {
|
||||||
prompt,
|
prompt,
|
||||||
phase: step.phase.clone(),
|
phase: step.phase.clone(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let agent_batch = super::prompts::AgentBatch { steps: resolved_steps, node_keys: all_keys };
|
let agent_batch = prompts::AgentBatch { steps: resolved_steps, node_keys: all_keys };
|
||||||
|
|
||||||
// Record visits eagerly so concurrent agents pick different seeds
|
// Record visits eagerly so concurrent agents pick different seeds
|
||||||
if !agent_batch.node_keys.is_empty() {
|
if !agent_batch.node_keys.is_empty() {
|
||||||
|
|
@ -164,7 +162,7 @@ pub fn run_one_agent_excluded(
|
||||||
log: &(dyn Fn(&str) + Sync),
|
log: &(dyn Fn(&str) + Sync),
|
||||||
exclude: &std::collections::HashSet<String>,
|
exclude: &std::collections::HashSet<String>,
|
||||||
) -> Result<AgentResult, String> {
|
) -> Result<AgentResult, String> {
|
||||||
let def = super::defs::get_def(agent_name)
|
let def = 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))?;
|
||||||
|
|
||||||
// Set up output dir and write pid file BEFORE prompt building
|
// Set up output dir and write pid file BEFORE prompt building
|
||||||
|
|
@ -172,7 +170,7 @@ pub fn run_one_agent_excluded(
|
||||||
|
|
||||||
log("building prompt");
|
log("building prompt");
|
||||||
let effective_count = def.count.unwrap_or(batch_size);
|
let effective_count = def.count.unwrap_or(batch_size);
|
||||||
let agent_batch = super::defs::run_agent(store, &def, effective_count, exclude)?;
|
let agent_batch = defs::run_agent(store, &def, effective_count, exclude)?;
|
||||||
|
|
||||||
run_one_agent_inner(store, agent_name, &def, agent_batch, state_dir, pid_path, llm_tag, log)
|
run_one_agent_inner(store, agent_name, &def, agent_batch, state_dir, pid_path, llm_tag, log)
|
||||||
}
|
}
|
||||||
|
|
@ -181,7 +179,7 @@ pub fn run_one_agent_excluded(
|
||||||
/// Returns (state_dir, pid_path, guard). The guard removes the pid file on drop.
|
/// Returns (state_dir, pid_path, guard). The guard removes the pid file on drop.
|
||||||
fn setup_agent_state(
|
fn setup_agent_state(
|
||||||
agent_name: &str,
|
agent_name: &str,
|
||||||
def: &super::defs::AgentDef,
|
def: &defs::AgentDef,
|
||||||
) -> Result<(PathBuf, PathBuf, PidGuard), String> {
|
) -> Result<(PathBuf, PathBuf, PidGuard), String> {
|
||||||
let state_dir = std::env::var("POC_AGENT_OUTPUT_DIR")
|
let state_dir = std::env::var("POC_AGENT_OUTPUT_DIR")
|
||||||
.map(PathBuf::from)
|
.map(PathBuf::from)
|
||||||
|
|
@ -247,7 +245,6 @@ pub fn scan_pid_files(state_dir: &std::path::Path, timeout_secs: u64) -> Vec<(St
|
||||||
|
|
||||||
/// Spawn an agent asynchronously. Writes the pid file before returning
|
/// Spawn an agent asynchronously. Writes the pid file before returning
|
||||||
/// so the caller immediately sees the agent as running.
|
/// so the caller immediately sees the agent as running.
|
||||||
/// Spawn result: child process handle and log path.
|
|
||||||
pub struct SpawnResult {
|
pub struct SpawnResult {
|
||||||
pub child: std::process::Child,
|
pub child: std::process::Child,
|
||||||
pub log_path: PathBuf,
|
pub log_path: PathBuf,
|
||||||
|
|
@ -258,7 +255,7 @@ pub fn spawn_agent(
|
||||||
state_dir: &std::path::Path,
|
state_dir: &std::path::Path,
|
||||||
session_id: &str,
|
session_id: &str,
|
||||||
) -> Option<SpawnResult> {
|
) -> Option<SpawnResult> {
|
||||||
let def = super::defs::get_def(agent_name)?;
|
let def = defs::get_def(agent_name)?;
|
||||||
let first_phase = def.steps.first()
|
let first_phase = def.steps.first()
|
||||||
.map(|s| s.phase.as_str())
|
.map(|s| s.phase.as_str())
|
||||||
.unwrap_or("step-0");
|
.unwrap_or("step-0");
|
||||||
|
|
@ -288,16 +285,17 @@ pub fn spawn_agent(
|
||||||
fn run_one_agent_inner(
|
fn run_one_agent_inner(
|
||||||
_store: &mut Store,
|
_store: &mut Store,
|
||||||
agent_name: &str,
|
agent_name: &str,
|
||||||
def: &super::defs::AgentDef,
|
def: &defs::AgentDef,
|
||||||
agent_batch: super::prompts::AgentBatch,
|
agent_batch: prompts::AgentBatch,
|
||||||
state_dir: std::path::PathBuf,
|
state_dir: std::path::PathBuf,
|
||||||
pid_path: std::path::PathBuf,
|
pid_path: std::path::PathBuf,
|
||||||
_llm_tag: &str,
|
_llm_tag: &str,
|
||||||
log: &(dyn Fn(&str) + Sync),
|
log: &(dyn Fn(&str) + Sync),
|
||||||
) -> Result<AgentResult, String> {
|
) -> Result<AgentResult, String> {
|
||||||
let all_tools = crate::agent::tools::memory_and_journal_tools();
|
// Filter tools based on agent def specification
|
||||||
let effective_tools: Vec<crate::agent::tools::Tool> = if def.tools.is_empty() {
|
let all_tools = super::tools::memory_and_journal_tools();
|
||||||
all_tools
|
let effective_tools: Vec<super::tools::Tool> = if def.tools.is_empty() {
|
||||||
|
all_tools.to_vec()
|
||||||
} else {
|
} else {
|
||||||
all_tools.into_iter()
|
all_tools.into_iter()
|
||||||
.filter(|t| def.tools.iter().any(|w| w == &t.name))
|
.filter(|t| def.tools.iter().any(|w| w == &t.name))
|
||||||
|
|
@ -354,8 +352,7 @@ fn run_one_agent_inner(
|
||||||
// Bail check: if the agent defines a bail script, run it between steps.
|
// Bail check: if the agent defines a bail script, run it between steps.
|
||||||
// The script receives the pid file path as $1, cwd = state dir.
|
// The script receives the pid file path as $1, cwd = state dir.
|
||||||
let bail_script = def.bail.as_ref().map(|name| {
|
let bail_script = def.bail.as_ref().map(|name| {
|
||||||
// Look for the script next to the .agent file
|
let agents_dir = defs::agents_dir();
|
||||||
let agents_dir = super::defs::agents_dir();
|
|
||||||
agents_dir.join(name)
|
agents_dir.join(name)
|
||||||
});
|
});
|
||||||
let state_dir_for_bail = state_dir.clone();
|
let state_dir_for_bail = state_dir.clone();
|
||||||
|
|
@ -381,7 +378,9 @@ fn run_one_agent_inner(
|
||||||
Ok(())
|
Ok(())
|
||||||
};
|
};
|
||||||
|
|
||||||
let output = llm::call_for_def_multi(def, &prompts, &step_phases, Some(&bail_fn), log)?;
|
let output = crate::subconscious::api::call_api_with_tools_sync(
|
||||||
|
agent_name, &prompts, &step_phases, def.temperature, def.priority,
|
||||||
|
&effective_tools, Some(&bail_fn), log)?;
|
||||||
|
|
||||||
Ok(AgentResult {
|
Ok(AgentResult {
|
||||||
output,
|
output,
|
||||||
|
|
@ -389,6 +388,3 @@ fn run_one_agent_inner(
|
||||||
state_dir,
|
state_dir,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// Conversation fragment selection removed — observe/journal agents handle transcripts.
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
// cli/agent.rs — agent subcommand handlers
|
// cli/agent.rs — agent subcommand handlers
|
||||||
|
|
||||||
use crate::store;
|
use crate::store;
|
||||||
use crate::agents::llm;
|
|
||||||
|
|
||||||
pub fn cmd_run_agent(agent: &str, count: usize, target: &[String], query: Option<&str>, dry_run: bool, local: bool, state_dir: Option<&str>) -> Result<(), String> {
|
pub fn cmd_run_agent(agent: &str, count: usize, target: &[String], query: Option<&str>, dry_run: bool, local: bool, state_dir: Option<&str>) -> Result<(), String> {
|
||||||
// Mark as agent so tool calls (e.g. poc-memory render) don't
|
// Mark as agent so tool calls (e.g. poc-memory render) don't
|
||||||
|
|
@ -60,7 +59,7 @@ pub fn cmd_run_agent(agent: &str, count: usize, target: &[String], query: Option
|
||||||
for (i, key) in resolved_targets.iter().enumerate() {
|
for (i, key) in resolved_targets.iter().enumerate() {
|
||||||
println!("[{}] [{}/{}] {}", agent, i + 1, resolved_targets.len(), key);
|
println!("[{}] [{}/{}] {}", agent, i + 1, resolved_targets.len(), key);
|
||||||
if i > 0 { store = store::Store::load()?; }
|
if i > 0 { store = store::Store::load()?; }
|
||||||
if let Err(e) = crate::agents::knowledge::run_one_agent_with_keys(
|
if let Err(e) = crate::agent::oneshot::run_one_agent_with_keys(
|
||||||
&mut store, agent, &[key.clone()], count, "test", &log,
|
&mut store, agent, &[key.clone()], count, "test", &log,
|
||||||
) {
|
) {
|
||||||
println!("[{}] ERROR on {}: {}", agent, key, e);
|
println!("[{}] ERROR on {}: {}", agent, key, e);
|
||||||
|
|
@ -80,7 +79,7 @@ pub fn cmd_run_agent(agent: &str, count: usize, target: &[String], query: Option
|
||||||
println!("[{}] queued {} tasks to daemon", agent, queued);
|
println!("[{}] queued {} tasks to daemon", agent, queued);
|
||||||
} else {
|
} else {
|
||||||
// Local execution (--local, --debug, dry-run, or daemon unavailable)
|
// Local execution (--local, --debug, dry-run, or daemon unavailable)
|
||||||
crate::agents::knowledge::run_one_agent(
|
crate::agent::oneshot::run_one_agent(
|
||||||
&mut store, agent, count, "test", &log,
|
&mut store, agent, count, "test", &log,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
@ -400,7 +399,8 @@ fn llm_compare(
|
||||||
let prompt = build_compare_prompt(a, b);
|
let prompt = build_compare_prompt(a, b);
|
||||||
|
|
||||||
let _ = model; // model selection handled by API backend config
|
let _ = model; // model selection handled by API backend config
|
||||||
let response = llm::call_simple("compare", &prompt)?;
|
let response = crate::subconscious::api::call_api_with_tools_sync(
|
||||||
|
"compare", &[prompt], &[], None, 10, &[], None, &|_| {})?;
|
||||||
let response = response.trim().to_uppercase();
|
let response = response.trim().to_uppercase();
|
||||||
|
|
||||||
if response.contains("BETTER: B") {
|
if response.contains("BETTER: B") {
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ pub use hippocampus::query::parser as query_parser;
|
||||||
|
|
||||||
pub use subconscious as agents;
|
pub use subconscious as agents;
|
||||||
pub use subconscious::{
|
pub use subconscious::{
|
||||||
llm, audit, consolidate, knowledge,
|
audit, consolidate,
|
||||||
digest, daemon,
|
digest, daemon,
|
||||||
};
|
};
|
||||||
// Backward compat: memory_search moved from subconscious::hook to claude::hook
|
// Backward compat: memory_search moved from subconscious::hook to claude::hook
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
// Each batch of links gets reviewed by Sonnet, which returns per-link actions:
|
// Each batch of links gets reviewed by Sonnet, which returns per-link actions:
|
||||||
// KEEP, DELETE, RETARGET, WEAKEN, STRENGTHEN. Batches run in parallel via rayon.
|
// KEEP, DELETE, RETARGET, WEAKEN, STRENGTHEN. Batches run in parallel via rayon.
|
||||||
|
|
||||||
use super::llm;
|
|
||||||
use crate::store::{self, Store, new_relation};
|
use crate::store::{self, Store, new_relation};
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
@ -211,7 +210,8 @@ pub fn link_audit(store: &mut Store, apply: bool) -> Result<AuditStats, String>
|
||||||
// Run batches in parallel via rayon
|
// Run batches in parallel via rayon
|
||||||
let batch_results: Vec<_> = batch_data.par_iter()
|
let batch_results: Vec<_> = batch_data.par_iter()
|
||||||
.map(|(batch_idx, batch_infos, prompt)| {
|
.map(|(batch_idx, batch_infos, prompt)| {
|
||||||
let response = llm::call_simple("audit", prompt);
|
let response = super::api::call_api_with_tools_sync(
|
||||||
|
"audit", &[prompt.clone()], &[], None, 10, &[], None, &|_| {});
|
||||||
let completed = done.fetch_add(1, Ordering::Relaxed) + 1;
|
let completed = done.fetch_add(1, Ordering::Relaxed) + 1;
|
||||||
eprint!("\r Batches: {}/{} done", completed, total_batches);
|
eprint!("\r Batches: {}/{} done", completed, total_batches);
|
||||||
(*batch_idx, batch_infos, response)
|
(*batch_idx, batch_infos, response)
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
// 6. Summary: final metrics comparison
|
// 6. Summary: final metrics comparison
|
||||||
|
|
||||||
use super::digest;
|
use super::digest;
|
||||||
use super::knowledge;
|
use crate::agent::oneshot;
|
||||||
use crate::neuro;
|
use crate::neuro;
|
||||||
use crate::store::{self, Store};
|
use crate::store::{self, Store};
|
||||||
|
|
||||||
|
|
@ -74,7 +74,7 @@ pub fn consolidate_full_with_progress(
|
||||||
*store = Store::load()?;
|
*store = Store::load()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
match knowledge::run_and_apply(store, agent_type, *count, "consolidate") {
|
match oneshot::run_and_apply(store, agent_type, *count, "consolidate") {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
let msg = " Done".to_string();
|
let msg = " Done".to_string();
|
||||||
log_line(&mut log_buf, &msg);
|
log_line(&mut log_buf, &msg);
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ fn job_targeted_agent(
|
||||||
ctx.log_line(msg);
|
ctx.log_line(msg);
|
||||||
log_event(&job_name, "progress", msg);
|
log_event(&job_name, "progress", msg);
|
||||||
};
|
};
|
||||||
super::knowledge::run_one_agent_with_keys(
|
crate::agent::oneshot::run_one_agent_with_keys(
|
||||||
&mut store, &agent, std::slice::from_ref(&key), 5, "daemon", &log,
|
&mut store, &agent, std::slice::from_ref(&key), 5, "daemon", &log,
|
||||||
)?;
|
)?;
|
||||||
ctx.log_line("done");
|
ctx.log_line("done");
|
||||||
|
|
@ -208,7 +208,7 @@ fn job_consolidation_agent(
|
||||||
};
|
};
|
||||||
// Use run_one_agent_with_keys — we already selected seeds above,
|
// Use run_one_agent_with_keys — we already selected seeds above,
|
||||||
// no need to re-run the query.
|
// no need to re-run the query.
|
||||||
let result = super::knowledge::run_one_agent_with_keys(
|
let result = crate::agent::oneshot::run_one_agent_with_keys(
|
||||||
&mut store, &agent, &claimed_keys, batch, "consolidate", &log,
|
&mut store, &agent, &claimed_keys, batch, "consolidate", &log,
|
||||||
).map(|_| ());
|
).map(|_| ());
|
||||||
|
|
||||||
|
|
@ -239,7 +239,7 @@ fn job_rename_agent(
|
||||||
ctx.log_line(format!("running rename agent (batch={})", batch));
|
ctx.log_line(format!("running rename agent (batch={})", batch));
|
||||||
|
|
||||||
let log = |msg: &str| ctx.log_line(msg);
|
let log = |msg: &str| ctx.log_line(msg);
|
||||||
let result = super::knowledge::run_one_agent(&mut store, "rename", batch, "consolidate", &log)?;
|
let result = crate::agent::oneshot::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;
|
||||||
|
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
// LLM utilities: model invocation via direct API
|
|
||||||
|
|
||||||
use crate::store::Store;
|
|
||||||
use std::fs;
|
|
||||||
|
|
||||||
/// Simple LLM call for non-agent uses (audit, digest, compare).
|
|
||||||
/// Logs to llm-logs/{caller}/ file.
|
|
||||||
pub(crate) fn call_simple(caller: &str, prompt: &str) -> Result<String, String> {
|
|
||||||
let log_dir = dirs::home_dir().unwrap_or_default()
|
|
||||||
.join(".consciousness/logs/llm").join(caller);
|
|
||||||
fs::create_dir_all(&log_dir).ok();
|
|
||||||
let log_path = log_dir.join(format!("{}.txt", crate::store::compact_timestamp()));
|
|
||||||
|
|
||||||
use std::io::Write;
|
|
||||||
let log = move |msg: &str| {
|
|
||||||
if let Ok(mut f) = fs::OpenOptions::new()
|
|
||||||
.create(true).append(true).open(&log_path)
|
|
||||||
{
|
|
||||||
let _ = writeln!(f, "{}", msg);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let prompts = vec![prompt.to_string()];
|
|
||||||
let phases = vec![];
|
|
||||||
super::api::call_api_with_tools_sync(caller, &prompts, &phases, None, 10, &[], None, &log)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Call a model using an agent definition's configuration (multi-step).
|
|
||||||
/// Optional bail_fn is called between steps — return Err to stop the pipeline.
|
|
||||||
pub(crate) fn call_for_def_multi(
|
|
||||||
def: &super::defs::AgentDef,
|
|
||||||
prompts: &[String],
|
|
||||||
phases: &[String],
|
|
||||||
bail_fn: Option<&(dyn Fn(usize) -> Result<(), String> + Sync)>,
|
|
||||||
log: &(dyn Fn(&str) + Sync),
|
|
||||||
) -> Result<String, String> {
|
|
||||||
// Filter tools based on AgentDef specification
|
|
||||||
let all_tools = crate::agent::tools::memory_and_journal_tools();
|
|
||||||
let effective_tools: Vec<crate::agent::tools::Tool> = if def.tools.is_empty() {
|
|
||||||
all_tools
|
|
||||||
} else {
|
|
||||||
all_tools.into_iter()
|
|
||||||
.filter(|t| def.tools.iter().any(|w| w == &t.name))
|
|
||||||
.collect()
|
|
||||||
};
|
|
||||||
super::api::call_api_with_tools_sync(&def.agent, prompts, phases, def.temperature, def.priority, &effective_tools, bail_fn, log)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Get all keys for prompt context.
|
|
||||||
pub(crate) fn semantic_keys(store: &Store) -> Vec<String> {
|
|
||||||
let mut keys: Vec<String> = store.nodes.keys()
|
|
||||||
.cloned()
|
|
||||||
.collect();
|
|
||||||
keys.sort();
|
|
||||||
keys.truncate(200);
|
|
||||||
keys
|
|
||||||
}
|
|
||||||
|
|
@ -19,11 +19,9 @@
|
||||||
|
|
||||||
pub mod subconscious;
|
pub mod subconscious;
|
||||||
pub mod api;
|
pub mod api;
|
||||||
pub mod llm;
|
|
||||||
pub mod prompts;
|
pub mod prompts;
|
||||||
pub mod defs;
|
pub mod defs;
|
||||||
pub mod audit;
|
pub mod audit;
|
||||||
pub mod consolidate;
|
pub mod consolidate;
|
||||||
pub mod knowledge;
|
|
||||||
pub mod digest;
|
pub mod digest;
|
||||||
pub mod daemon;
|
pub mod daemon;
|
||||||
|
|
|
||||||
|
|
@ -156,7 +156,7 @@ impl AgentCycleState {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn agent_spawned(&mut self, name: &str, phase: &str,
|
fn agent_spawned(&mut self, name: &str, phase: &str,
|
||||||
result: crate::agents::knowledge::SpawnResult) {
|
result: crate::agent::oneshot::SpawnResult) {
|
||||||
if let Some(agent) = self.agents.iter_mut().find(|a| a.name == name) {
|
if let Some(agent) = self.agents.iter_mut().find(|a| a.name == name) {
|
||||||
agent.pid = Some(result.child.id());
|
agent.pid = Some(result.child.id());
|
||||||
agent.phase = Some(phase.to_string());
|
agent.phase = Some(phase.to_string());
|
||||||
|
|
@ -279,7 +279,7 @@ impl AgentCycleState {
|
||||||
if transcript.size > 0 {
|
if transcript.size > 0 {
|
||||||
fs::write(&offset_path, transcript.size.to_string()).ok();
|
fs::write(&offset_path, transcript.size.to_string()).ok();
|
||||||
}
|
}
|
||||||
if let Some(result) = crate::agents::knowledge::spawn_agent(
|
if let Some(result) = crate::agent::oneshot::spawn_agent(
|
||||||
"surface-observe", &state_dir, &session.session_id) {
|
"surface-observe", &state_dir, &session.session_id) {
|
||||||
self.log(format_args!("spawned surface-observe pid {}\n", result.child.id()));
|
self.log(format_args!("spawned surface-observe pid {}\n", result.child.id()));
|
||||||
self.agent_spawned("surface-observe", "surface", result);
|
self.agent_spawned("surface-observe", "surface", result);
|
||||||
|
|
@ -346,7 +346,7 @@ impl AgentCycleState {
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::write(&offset_path, transcript.size.to_string()).ok();
|
fs::write(&offset_path, transcript.size.to_string()).ok();
|
||||||
if let Some(result) = crate::agents::knowledge::spawn_agent(
|
if let Some(result) = crate::agent::oneshot::spawn_agent(
|
||||||
"reflect", &state_dir, &session.session_id) {
|
"reflect", &state_dir, &session.session_id) {
|
||||||
self.log(format_args!("reflect: spawned pid {}\n", result.child.id()));
|
self.log(format_args!("reflect: spawned pid {}\n", result.child.id()));
|
||||||
self.agent_spawned("reflect", "step-0", result);
|
self.agent_spawned("reflect", "step-0", result);
|
||||||
|
|
@ -375,7 +375,7 @@ impl AgentCycleState {
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::write(&offset_path, transcript.size.to_string()).ok();
|
fs::write(&offset_path, transcript.size.to_string()).ok();
|
||||||
if let Some(result) = crate::agents::knowledge::spawn_agent(
|
if let Some(result) = crate::agent::oneshot::spawn_agent(
|
||||||
"journal", &state_dir, &session.session_id) {
|
"journal", &state_dir, &session.session_id) {
|
||||||
self.log(format_args!("journal: spawned pid {}\n", result.child.id()));
|
self.log(format_args!("journal: spawned pid {}\n", result.child.id()));
|
||||||
self.agent_spawned("journal", "step-0", result);
|
self.agent_spawned("journal", "step-0", result);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue