Native memory tools + MCP server + distill agent improvements
Tools:
- Add native memory_render, memory_write, memory_search,
memory_links, memory_link_set, memory_link_add, memory_used
tools to poc-agent (tools/memory.rs)
- Add MCP server (~/bin/memory-mcp.py) exposing same tools
for Claude Code sessions
- Wire memory tools into poc-agent dispatch and definitions
- poc-memory daemon agents now use memory_* tools instead of
bash poc-memory commands — no shell quoting issues
Distill agent:
- Rewrite distill.agent prompt: "agent of PoC's subconscious"
framing, focus on synthesis and creativity over bookkeeping
- Add {{neighborhood}} placeholder: full seed node content +
all neighbors with content + cross-links between neighbors
- Remove content truncation in prompt builder — agents need
full content for quality work
- Remove bag-of-words similarity suggestions — agents have
tools, let them explore the graph themselves
- Add api_reasoning config option (default: "high")
- link-set now deduplicates — collapses duplicate links
- Full tool call args in debug logs (was truncated to 80 chars)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d9b56a02c3
commit
6d22f70192
8 changed files with 290 additions and 87 deletions
|
|
@ -237,29 +237,50 @@ fn resolve(
|
|||
}
|
||||
|
||||
"siblings" | "neighborhood" => {
|
||||
let mut seen: std::collections::HashSet<String> = keys.iter().cloned().collect();
|
||||
let mut siblings = Vec::new();
|
||||
let mut out = String::new();
|
||||
let mut all_keys: Vec<String> = Vec::new();
|
||||
|
||||
for key in keys {
|
||||
for (neighbor, _) in graph.neighbors(key) {
|
||||
if seen.insert(neighbor.clone()) {
|
||||
if let Some(node) = store.nodes.get(neighbor.as_str()) {
|
||||
siblings.push((neighbor.clone(), node.content.clone()));
|
||||
let Some(node) = store.nodes.get(key.as_str()) else { continue };
|
||||
let neighbors = graph.neighbors(key);
|
||||
|
||||
// Seed node with full content
|
||||
out.push_str(&format!("## {} (seed)\n\n{}\n\n", key, node.content));
|
||||
all_keys.push(key.clone());
|
||||
|
||||
// All neighbors with full content and link strength
|
||||
if !neighbors.is_empty() {
|
||||
out.push_str("### Neighbors\n\n");
|
||||
for (nbr, strength) in &neighbors {
|
||||
if let Some(n) = store.nodes.get(nbr.as_str()) {
|
||||
out.push_str(&format!("#### {} (link: {:.2})\n\n{}\n\n",
|
||||
nbr, strength, n.content));
|
||||
all_keys.push(nbr.to_string());
|
||||
}
|
||||
}
|
||||
if siblings.len() >= count { break; }
|
||||
}
|
||||
if siblings.len() >= count { break; }
|
||||
|
||||
// Cross-links between neighbors (local subgraph structure)
|
||||
let nbr_set: std::collections::HashSet<&str> = neighbors.iter()
|
||||
.map(|(k, _)| k.as_str()).collect();
|
||||
let mut cross_links = Vec::new();
|
||||
for (nbr, _) in &neighbors {
|
||||
for (nbr2, strength) in graph.neighbors(nbr) {
|
||||
if nbr2.as_str() != key && nbr_set.contains(nbr2.as_str()) && nbr.as_str() < nbr2.as_str() {
|
||||
cross_links.push((nbr.clone(), nbr2, strength));
|
||||
}
|
||||
}
|
||||
}
|
||||
if !cross_links.is_empty() {
|
||||
out.push_str("### Cross-links between neighbors\n\n");
|
||||
for (a, b, s) in &cross_links {
|
||||
out.push_str(&format!(" {} ↔ {} ({:.2})\n", a, b, s));
|
||||
}
|
||||
out.push_str("\n");
|
||||
}
|
||||
}
|
||||
let text = if siblings.is_empty() {
|
||||
String::new()
|
||||
} else {
|
||||
let mut out = String::from("## Sibling nodes (one hop in graph)\n\n");
|
||||
for (key, content) in &siblings {
|
||||
out.push_str(&format!("### {}\n{}\n\n", key, content));
|
||||
}
|
||||
out
|
||||
};
|
||||
Some(Resolved { text, keys: vec![] })
|
||||
|
||||
Some(Resolved { text: out, keys: all_keys })
|
||||
}
|
||||
|
||||
// targets/context: aliases for challenger-style presentation
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue