forked from kent/consciousness
defs.rs: remove store/graph params, use typed memory API
resolve_placeholders() and run_agent() no longer take &Store. All placeholders now use async memory_render/memory_links/memory_query directly. The "siblings" placeholder uses Vec<LinkInfo> for ranking neighbors by link_strength * node_weight. Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
parent
598f0112a4
commit
419bb222b5
4 changed files with 19 additions and 26 deletions
|
|
@ -405,7 +405,7 @@ pub async fn run_one_agent(
|
|||
let mut all_keys: Vec<String> = keys.to_vec();
|
||||
for step in &def.steps {
|
||||
let (prompt, extra_keys) = defs::resolve_placeholders(
|
||||
&step.prompt, store, keys, count,
|
||||
&step.prompt, keys, count,
|
||||
).await;
|
||||
all_keys.extend(extra_keys);
|
||||
resolved_steps.push(prompts::ResolvedStep {
|
||||
|
|
@ -420,7 +420,7 @@ pub async fn run_one_agent(
|
|||
batch
|
||||
} else {
|
||||
let effective_count = def.count.unwrap_or(count);
|
||||
defs::run_agent(store, &def, effective_count, &Default::default()).await?
|
||||
defs::run_agent(&def, effective_count, &Default::default()).await?
|
||||
};
|
||||
|
||||
// Base memory tools + extras from agent def (matching unconscious.rs pattern)
|
||||
|
|
|
|||
|
|
@ -264,7 +264,7 @@ pub async fn prepare_spawn(name: &str, mut auto: AutoAgent) -> Result<SpawnResul
|
|||
|
||||
let exclude: std::collections::HashSet<String> = std::collections::HashSet::new();
|
||||
let batch = match defs::run_agent(
|
||||
&store, &def, def.count.unwrap_or(5), &exclude,
|
||||
&def, def.count.unwrap_or(5), &exclude,
|
||||
).await {
|
||||
Ok(b) => b,
|
||||
Err(e) => {
|
||||
|
|
|
|||
|
|
@ -15,8 +15,6 @@
|
|||
// The query selects what to operate on; placeholders pull in context.
|
||||
|
||||
use crate::agent::tools::memory::memory_render;
|
||||
use crate::graph::Graph;
|
||||
use crate::store::Store;
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
|
|
@ -201,8 +199,6 @@ struct Resolved {
|
|||
/// Returns the replacement text and any node keys it produced (for visit tracking).
|
||||
async fn resolve(
|
||||
name: &str,
|
||||
store: &Store,
|
||||
graph: &Graph,
|
||||
keys: &[String],
|
||||
_count: usize,
|
||||
) -> Option<Resolved> {
|
||||
|
|
@ -245,6 +241,7 @@ async fn resolve(
|
|||
}
|
||||
|
||||
"siblings" | "neighborhood" => {
|
||||
use crate::agent::tools::memory::{memory_render, memory_links};
|
||||
const MAX_NEIGHBORS: usize = 20;
|
||||
const BUDGET: usize = 400_000; // ~100K tokens
|
||||
|
||||
|
|
@ -255,19 +252,18 @@ async fn resolve(
|
|||
for key in keys {
|
||||
if included.contains(key) { continue; }
|
||||
included.insert(key.clone());
|
||||
let Some(node) = store.nodes.get(key.as_str()) else { continue };
|
||||
|
||||
// Seed node with full content
|
||||
out.push_str(&format!("## {} (seed)\n\n{}\n\n", key, node.content));
|
||||
let Ok(content) = memory_render(None, key, Some(true)).await else { continue };
|
||||
out.push_str(&format!("## {} (seed)\n\n{}\n\n", key, content));
|
||||
all_keys.push(key.clone());
|
||||
|
||||
// Rank neighbors by link_strength * node_weight, take top 20
|
||||
let mut ranked: Vec<_> = graph.neighbors(key).iter()
|
||||
.filter_map(|(nbr, strength)| {
|
||||
store.nodes.get(nbr.as_str()).map(|n| {
|
||||
let score = strength * n.weight.max(0.01);
|
||||
(nbr.to_string(), *strength, score)
|
||||
})
|
||||
// Get neighbors with link_strength and node_weight, rank and take top 20
|
||||
let Ok(links) = memory_links(None, key).await else { continue };
|
||||
let mut ranked: Vec<_> = links.into_iter()
|
||||
.map(|l| {
|
||||
let score = l.link_strength * l.node_weight.max(0.01);
|
||||
(l.key, l.link_strength, score)
|
||||
})
|
||||
.collect();
|
||||
ranked.sort_by(|a, b| b.2.total_cmp(&a.2));
|
||||
|
|
@ -279,15 +275,15 @@ async fn resolve(
|
|||
for (nbr, strength, _) in &ranked {
|
||||
if included.contains(nbr) { continue; }
|
||||
included.insert(nbr.clone());
|
||||
if let Some(n) = store.nodes.get(nbr.as_str()) {
|
||||
if let Ok(content) = memory_render(None, nbr, Some(true)).await {
|
||||
if out.len() > BUDGET {
|
||||
// Header-only past budget
|
||||
let first = n.content.lines()
|
||||
let first = content.lines()
|
||||
.find(|l| !l.trim().is_empty())
|
||||
.unwrap_or("(empty)");
|
||||
out.push_str(&format!("#### {} ({:.2}) — {}\n", nbr, strength, first));
|
||||
} else {
|
||||
out.push_str(&format!("#### {} ({:.2})\n\n{}\n\n", nbr, strength, n.content));
|
||||
out.push_str(&format!("#### {} ({:.2})\n\n{}\n\n", nbr, strength, content));
|
||||
}
|
||||
all_keys.push(nbr.to_string());
|
||||
}
|
||||
|
|
@ -558,11 +554,9 @@ async fn resolve_tool(spec: &str) -> Option<Resolved> {
|
|||
/// Returns the resolved text and all node keys collected from placeholders.
|
||||
pub async fn resolve_placeholders(
|
||||
template: &str,
|
||||
store: &Store,
|
||||
keys: &[String],
|
||||
count: usize,
|
||||
) -> (String, Vec<String>) {
|
||||
let graph = store.build_graph();
|
||||
let mut result = template.to_string();
|
||||
let mut extra_keys = Vec::new();
|
||||
let mut pos = 0;
|
||||
|
|
@ -572,7 +566,7 @@ pub async fn resolve_placeholders(
|
|||
let Some(rel_end) = result[start + 2..].find("}}") else { break };
|
||||
let end = start + 2 + rel_end;
|
||||
let name = result[start + 2..end].trim().to_lowercase();
|
||||
match resolve(&name, store, &graph, keys, count).await {
|
||||
match resolve(&name, keys, count).await {
|
||||
Some(resolved) => {
|
||||
let len = resolved.text.len();
|
||||
extra_keys.extend(resolved.keys);
|
||||
|
|
@ -594,7 +588,6 @@ pub async fn resolve_placeholders(
|
|||
/// `exclude` filters out nodes (and their neighborhoods) already being
|
||||
/// worked on by other agents, preventing concurrent collisions.
|
||||
pub async fn run_agent(
|
||||
store: &Store,
|
||||
def: &AgentDef,
|
||||
count: usize,
|
||||
exclude: &std::collections::HashSet<String>,
|
||||
|
|
@ -635,7 +628,7 @@ pub async fn run_agent(
|
|||
.replace("{agent_name}", &def.agent)
|
||||
.replace("{user_name}", &cfg.user_name)
|
||||
.replace("{assistant_name}", &cfg.assistant_name);
|
||||
let (prompt, extra_keys) = resolve_placeholders(&template, store, &all_keys, count).await;
|
||||
let (prompt, extra_keys) = resolve_placeholders(&template, &all_keys, count).await;
|
||||
all_keys.extend(extra_keys);
|
||||
resolved_steps.push(super::prompts::ResolvedStep {
|
||||
prompt,
|
||||
|
|
|
|||
|
|
@ -212,8 +212,8 @@ pub fn format_health_section(store: &Store, graph: &Graph) -> String {
|
|||
}
|
||||
|
||||
/// Generate a specific agent prompt with filled-in data.
|
||||
pub async fn agent_prompt(store: &Store, agent: &str, count: usize) -> Result<AgentBatch, String> {
|
||||
pub async fn agent_prompt(agent: &str, count: usize) -> Result<AgentBatch, String> {
|
||||
let def = super::defs::get_def(agent)
|
||||
.ok_or_else(|| format!("Unknown agent: {}", agent))?;
|
||||
super::defs::run_agent(store, &def, count, &Default::default()).await
|
||||
super::defs::run_agent(&def, count, &Default::default()).await
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue