diff --git a/src/thought/memory.rs b/src/thought/memory.rs index fdac7de..c931c03 100644 --- a/src/thought/memory.rs +++ b/src/thought/memory.rs @@ -6,6 +6,7 @@ use anyhow::{Context, Result}; use serde_json::json; use crate::hippocampus::memory::MemoryNode; +use crate::store::StoreView; use super::ToolDef; use crate::store::Store; @@ -100,7 +101,7 @@ pub fn dispatch(name: &str, args: &serde_json::Value, provenance: Option<&str>) store.save().map_err(|e| anyhow::anyhow!("{}", e))?; Ok(format!("{} '{}'", result, key)) } - "memory_search" => { + "memory_search" | "memory_search_content" => { let query = get_str(args, "query")?; let store = Store::load().map_err(|e| anyhow::anyhow!("{}", e))?; let results = crate::search::search(query, &store); @@ -113,6 +114,38 @@ pub fn dispatch(name: &str, args: &serde_json::Value, provenance: Option<&str>) .collect::>().join("\n")) } } + "memory_spread" => { + let keys: Vec = args.get("keys") + .and_then(|v| v.as_array()) + .map(|arr| arr.iter().filter_map(|v| v.as_str().map(String::from)).collect()) + .unwrap_or_default(); + if keys.is_empty() { + anyhow::bail!("spread requires at least one seed key"); + } + let store = Store::load().map_err(|e| anyhow::anyhow!("{}", e))?; + let graph = crate::graph::build_graph_fast(&store); + let params = store.params(); + let seeds: Vec<(String, f64)> = keys.iter() + .filter_map(|k| { + let resolved = store.resolve_key(k).ok()?; + Some((resolved, 1.0)) + }) + .collect(); + if seeds.is_empty() { + anyhow::bail!("no valid seed keys found"); + } + let seed_set: std::collections::HashSet<&str> = seeds.iter() + .map(|(k, _)| k.as_str()).collect(); + let results = crate::search::spreading_activation( + &seeds, &graph, &store, + params.max_hops, params.edge_decay, params.min_activation, + ); + Ok(results.iter() + .filter(|(k, _)| !seed_set.contains(k.as_str())) + .take(20) + .map(|(key, score)| format!(" {:.2} {}", score, key)) + .collect::>().join("\n")) + } "memory_links" => { let key = get_str(args, "key")?; let node = MemoryNode::load(key)