memory_links: return typed Vec<LinkInfo> with node weights

- hippocampus::memory_links now returns Vec<LinkInfo> with key,
  link_strength, and node_weight for each neighbor
- Unified memory_tool! macro: mut/ref as token, single main rule
- All tools use serde serialize/deserialize for RPC consistency
- jsonargs handlers now work in client mode (RPC to daemon)
- cli/graph.rs formats LinkInfo for display

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
Kent Overstreet 2026-04-13 15:12:06 -04:00
parent 359955f838
commit 598f0112a4
3 changed files with 67 additions and 57 deletions

View file

@ -84,15 +84,29 @@ pub fn memory_search(
.collect::<Vec<_>>().join("\n"))
}
pub fn memory_links(store: &Store, _provenance: &str, key: &str) -> Result<String> {
/// Info about a linked neighbor node.
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
pub struct LinkInfo {
pub key: String,
pub link_strength: f32,
pub node_weight: f32,
}
pub fn memory_links(store: &Store, _provenance: &str, key: &str) -> Result<Vec<LinkInfo>> {
let node = MemoryNode::from_store(store, key)
.ok_or_else(|| anyhow::anyhow!("node not found: {}", key))?;
let mut out = format!("Neighbors of '{}':\n", key);
for (target, strength, is_new) in &node.links {
let tag = if *is_new { " (new)" } else { "" };
out.push_str(&format!(" ({:.2}) {}{}\n", strength, target, tag));
let mut links = Vec::new();
for (target, strength, _is_new) in &node.links {
let node_weight = store.nodes.get(target.as_str())
.map(|n| n.weight)
.unwrap_or(0.5);
links.push(LinkInfo {
key: target.clone(),
link_strength: *strength,
node_weight,
});
}
Ok(out)
Ok(links)
}
pub fn memory_link_set(store: &mut Store, _provenance: &str, source: &str, target: &str, strength: f32) -> Result<String> {