tools: each module owns its Tool list, no duplication
Each tool module exports its own tools() returning Vec<Tool>. mod.rs::tools() chains them. Individual _def() and handler functions are pub(super), not exported. Aggregate definitions derived from the Tool lists. - memory: memory_tools(), journal_tools() - channels: tools() - control: tools() - mod.rs: just chains + adds file/bash/web/vision Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
parent
aa7511d110
commit
6d6da07f91
4 changed files with 91 additions and 81 deletions
|
|
@ -51,7 +51,16 @@ pub fn definitions() -> Vec<ToolDef> {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Dispatch ───────────────────────────────────────────────────
|
pub fn tools() -> Vec<super::Tool> {
|
||||||
|
use super::Tool;
|
||||||
|
let defs = definitions();
|
||||||
|
vec![
|
||||||
|
Tool { def: defs[0].clone(), handler: |_a, _v| Box::pin(async move { channel_list().await }) },
|
||||||
|
Tool { def: defs[1].clone(), handler: |_a, v| Box::pin(async move { channel_recv(&v).await }) },
|
||||||
|
Tool { def: defs[2].clone(), handler: |_a, v| Box::pin(async move { channel_send(&v).await }) },
|
||||||
|
Tool { def: defs[3].clone(), handler: |_a, _v| Box::pin(async move { channel_notifications().await }) },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
// ── Tool implementations ───────────────────────────────────────
|
// ── Tool implementations ───────────────────────────────────────
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,26 @@ pub(super) fn yield_to_user(args: &serde_json::Value) -> Result<ToolOutput> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn definitions() -> Vec<ToolDef> {
|
pub(super) fn tools() -> Vec<super::Tool> {
|
||||||
|
use super::Tool;
|
||||||
|
let defs = definitions();
|
||||||
|
vec![
|
||||||
|
Tool { def: defs[0].clone(), // switch_model
|
||||||
|
handler: |_a, v| Box::pin(async move {
|
||||||
|
let model = v.get("model").and_then(|v| v.as_str()).unwrap_or("");
|
||||||
|
Ok(format!("Switching to model: {}", model))
|
||||||
|
}) },
|
||||||
|
Tool { def: defs[1].clone(), // pause
|
||||||
|
handler: |_a, _v| Box::pin(async { Ok("Pausing autonomous behavior. Only user input will wake you.".into()) }) },
|
||||||
|
Tool { def: defs[2].clone(), // yield_to_user
|
||||||
|
handler: |_a, v| Box::pin(async move {
|
||||||
|
let msg = v.get("message").and_then(|v| v.as_str()).unwrap_or("(yielding to user)");
|
||||||
|
Ok(msg.to_string())
|
||||||
|
}) },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn definitions() -> Vec<ToolDef> {
|
||||||
vec![
|
vec![
|
||||||
ToolDef::new(
|
ToolDef::new(
|
||||||
"switch_model",
|
"switch_model",
|
||||||
|
|
|
||||||
|
|
@ -29,40 +29,55 @@ fn provenance() -> &'static str { "manual" }
|
||||||
|
|
||||||
// ── Definitions ────────────────────────────────────────────────
|
// ── Definitions ────────────────────────────────────────────────
|
||||||
|
|
||||||
pub fn definitions() -> Vec<ToolDef> {
|
pub fn memory_tools() -> Vec<super::Tool> {
|
||||||
|
use super::Tool;
|
||||||
vec![
|
vec![
|
||||||
render_def(), write_def(), search_def(), links_def(),
|
Tool { def: render_def(), handler: |_a, v| Box::pin(async move { render(&v) }) },
|
||||||
link_set_def(), link_add_def(), used_def(), weight_set_def(),
|
Tool { def: write_def(), handler: |_a, v| Box::pin(async move { write(&v) }) },
|
||||||
rename_def(), supersede_def(), query_def(), output_def(),
|
Tool { def: search_def(), handler: |_a, v| Box::pin(async move { search(&v) }) },
|
||||||
|
Tool { def: links_def(), handler: |_a, v| Box::pin(async move { links(&v) }) },
|
||||||
|
Tool { def: link_set_def(), handler: |_a, v| Box::pin(async move { link_set(&v) }) },
|
||||||
|
Tool { def: link_add_def(), handler: |_a, v| Box::pin(async move { link_add(&v) }) },
|
||||||
|
Tool { def: used_def(), handler: |_a, v| Box::pin(async move { used(&v) }) },
|
||||||
|
Tool { def: weight_set_def(), handler: |_a, v| Box::pin(async move { weight_set(&v) }) },
|
||||||
|
Tool { def: rename_def(), handler: |_a, v| Box::pin(async move { rename(&v) }) },
|
||||||
|
Tool { def: supersede_def(), handler: |_a, v| Box::pin(async move { supersede(&v) }) },
|
||||||
|
Tool { def: query_def(), handler: |_a, v| Box::pin(async move { query(&v) }) },
|
||||||
|
Tool { def: output_def(), handler: |_a, v| Box::pin(async move { output(&v) }) },
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn journal_definitions() -> Vec<ToolDef> {
|
pub fn journal_tools() -> Vec<super::Tool> {
|
||||||
vec![journal_tail_def(), journal_new_def(), journal_update_def()]
|
use super::Tool;
|
||||||
|
vec![
|
||||||
|
Tool { def: journal_tail_def(), handler: |_a, v| Box::pin(async move { journal_tail(&v) }) },
|
||||||
|
Tool { def: journal_new_def(), handler: |_a, v| Box::pin(async move { journal_new(&v) }) },
|
||||||
|
Tool { def: journal_update_def(), handler: |_a, v| Box::pin(async move { journal_update(&v) }) },
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Memory tools ───────────────────────────────────────────────
|
// ── Memory tools ───────────────────────────────────────────────
|
||||||
|
|
||||||
pub fn render_def() -> ToolDef {
|
fn render_def() -> ToolDef {
|
||||||
ToolDef::new("memory_render",
|
ToolDef::new("memory_render",
|
||||||
"Read a memory node's content and links.",
|
"Read a memory node's content and links.",
|
||||||
json!({"type":"object","properties":{"key":{"type":"string","description":"Node key"}},"required":["key"]}))
|
json!({"type":"object","properties":{"key":{"type":"string","description":"Node key"}},"required":["key"]}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(args: &serde_json::Value) -> Result<String> {
|
fn render(args: &serde_json::Value) -> Result<String> {
|
||||||
let key = get_str(args, "key")?;
|
let key = get_str(args, "key")?;
|
||||||
Ok(MemoryNode::load(key)
|
Ok(MemoryNode::load(key)
|
||||||
.ok_or_else(|| anyhow::anyhow!("node not found: {}", key))?
|
.ok_or_else(|| anyhow::anyhow!("node not found: {}", key))?
|
||||||
.render())
|
.render())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_def() -> ToolDef {
|
fn write_def() -> ToolDef {
|
||||||
ToolDef::new("memory_write",
|
ToolDef::new("memory_write",
|
||||||
"Create or update a memory node.",
|
"Create or update a memory node.",
|
||||||
json!({"type":"object","properties":{"key":{"type":"string","description":"Node key"},"content":{"type":"string","description":"Full content (markdown)"}},"required":["key","content"]}))
|
json!({"type":"object","properties":{"key":{"type":"string","description":"Node key"},"content":{"type":"string","description":"Full content (markdown)"}},"required":["key","content"]}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(args: &serde_json::Value) -> Result<String> {
|
fn write(args: &serde_json::Value) -> Result<String> {
|
||||||
let key = get_str(args, "key")?;
|
let key = get_str(args, "key")?;
|
||||||
let content = get_str(args, "content")?;
|
let content = get_str(args, "content")?;
|
||||||
let mut store = load_store()?;
|
let mut store = load_store()?;
|
||||||
|
|
@ -72,7 +87,7 @@ pub fn write(args: &serde_json::Value) -> Result<String> {
|
||||||
Ok(format!("{} '{}'", result, key))
|
Ok(format!("{} '{}'", result, key))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn search_def() -> ToolDef {
|
fn search_def() -> ToolDef {
|
||||||
ToolDef::new("memory_search",
|
ToolDef::new("memory_search",
|
||||||
"Search the memory graph via spreading activation. Give 2-4 seed \
|
"Search the memory graph via spreading activation. Give 2-4 seed \
|
||||||
node keys related to what you're looking for. Returns nodes ranked \
|
node keys related to what you're looking for. Returns nodes ranked \
|
||||||
|
|
@ -81,7 +96,7 @@ pub fn search_def() -> ToolDef {
|
||||||
json!({"type":"object","properties":{"keys":{"type":"array","items":{"type":"string"},"description":"Seed node keys to activate from"}},"required":["keys"]}))
|
json!({"type":"object","properties":{"keys":{"type":"array","items":{"type":"string"},"description":"Seed node keys to activate from"}},"required":["keys"]}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn search(args: &serde_json::Value) -> Result<String> {
|
fn search(args: &serde_json::Value) -> Result<String> {
|
||||||
let keys: Vec<String> = args.get("keys")
|
let keys: Vec<String> = args.get("keys")
|
||||||
.and_then(|v| v.as_array())
|
.and_then(|v| v.as_array())
|
||||||
.map(|arr| arr.iter().filter_map(|v| v.as_str().map(String::from)).collect())
|
.map(|arr| arr.iter().filter_map(|v| v.as_str().map(String::from)).collect())
|
||||||
|
|
@ -114,13 +129,13 @@ pub fn search(args: &serde_json::Value) -> Result<String> {
|
||||||
.collect::<Vec<_>>().join("\n"))
|
.collect::<Vec<_>>().join("\n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn links_def() -> ToolDef {
|
fn links_def() -> ToolDef {
|
||||||
ToolDef::new("memory_links",
|
ToolDef::new("memory_links",
|
||||||
"Show a node's neighbors with link strengths.",
|
"Show a node's neighbors with link strengths.",
|
||||||
json!({"type":"object","properties":{"key":{"type":"string","description":"Node key"}},"required":["key"]}))
|
json!({"type":"object","properties":{"key":{"type":"string","description":"Node key"}},"required":["key"]}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn links(args: &serde_json::Value) -> Result<String> {
|
fn links(args: &serde_json::Value) -> Result<String> {
|
||||||
let key = get_str(args, "key")?;
|
let key = get_str(args, "key")?;
|
||||||
let node = MemoryNode::load(key)
|
let node = MemoryNode::load(key)
|
||||||
.ok_or_else(|| anyhow::anyhow!("node not found: {}", key))?;
|
.ok_or_else(|| anyhow::anyhow!("node not found: {}", key))?;
|
||||||
|
|
@ -132,13 +147,13 @@ pub fn links(args: &serde_json::Value) -> Result<String> {
|
||||||
Ok(out)
|
Ok(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn link_set_def() -> ToolDef {
|
fn link_set_def() -> ToolDef {
|
||||||
ToolDef::new("memory_link_set",
|
ToolDef::new("memory_link_set",
|
||||||
"Set link strength between two nodes.",
|
"Set link strength between two nodes.",
|
||||||
json!({"type":"object","properties":{"source":{"type":"string"},"target":{"type":"string"},"strength":{"type":"number","description":"0.01 to 1.0"}},"required":["source","target","strength"]}))
|
json!({"type":"object","properties":{"source":{"type":"string"},"target":{"type":"string"},"strength":{"type":"number","description":"0.01 to 1.0"}},"required":["source","target","strength"]}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn link_set(args: &serde_json::Value) -> Result<String> {
|
fn link_set(args: &serde_json::Value) -> Result<String> {
|
||||||
let mut store = load_store()?;
|
let mut store = load_store()?;
|
||||||
let s = store.resolve_key(get_str(args, "source")?).map_err(|e| anyhow::anyhow!("{}", e))?;
|
let s = store.resolve_key(get_str(args, "source")?).map_err(|e| anyhow::anyhow!("{}", e))?;
|
||||||
let t = store.resolve_key(get_str(args, "target")?).map_err(|e| anyhow::anyhow!("{}", e))?;
|
let t = store.resolve_key(get_str(args, "target")?).map_err(|e| anyhow::anyhow!("{}", e))?;
|
||||||
|
|
@ -148,13 +163,13 @@ pub fn link_set(args: &serde_json::Value) -> Result<String> {
|
||||||
Ok(format!("{} ↔ {} strength {:.2} → {:.2}", s, t, old, strength))
|
Ok(format!("{} ↔ {} strength {:.2} → {:.2}", s, t, old, strength))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn link_add_def() -> ToolDef {
|
fn link_add_def() -> ToolDef {
|
||||||
ToolDef::new("memory_link_add",
|
ToolDef::new("memory_link_add",
|
||||||
"Add a new link between two nodes.",
|
"Add a new link between two nodes.",
|
||||||
json!({"type":"object","properties":{"source":{"type":"string"},"target":{"type":"string"}},"required":["source","target"]}))
|
json!({"type":"object","properties":{"source":{"type":"string"},"target":{"type":"string"}},"required":["source","target"]}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn link_add(args: &serde_json::Value) -> Result<String> {
|
fn link_add(args: &serde_json::Value) -> Result<String> {
|
||||||
let mut store = load_store()?;
|
let mut store = load_store()?;
|
||||||
let s = store.resolve_key(get_str(args, "source")?).map_err(|e| anyhow::anyhow!("{}", e))?;
|
let s = store.resolve_key(get_str(args, "source")?).map_err(|e| anyhow::anyhow!("{}", e))?;
|
||||||
let t = store.resolve_key(get_str(args, "target")?).map_err(|e| anyhow::anyhow!("{}", e))?;
|
let t = store.resolve_key(get_str(args, "target")?).map_err(|e| anyhow::anyhow!("{}", e))?;
|
||||||
|
|
@ -163,13 +178,13 @@ pub fn link_add(args: &serde_json::Value) -> Result<String> {
|
||||||
Ok(format!("linked {} → {} (strength={:.2})", s, t, strength))
|
Ok(format!("linked {} → {} (strength={:.2})", s, t, strength))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn used_def() -> ToolDef {
|
fn used_def() -> ToolDef {
|
||||||
ToolDef::new("memory_used",
|
ToolDef::new("memory_used",
|
||||||
"Mark a node as useful (boosts weight).",
|
"Mark a node as useful (boosts weight).",
|
||||||
json!({"type":"object","properties":{"key":{"type":"string","description":"Node key"}},"required":["key"]}))
|
json!({"type":"object","properties":{"key":{"type":"string","description":"Node key"}},"required":["key"]}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn used(args: &serde_json::Value) -> Result<String> {
|
fn used(args: &serde_json::Value) -> Result<String> {
|
||||||
let key = get_str(args, "key")?;
|
let key = get_str(args, "key")?;
|
||||||
let mut store = load_store()?;
|
let mut store = load_store()?;
|
||||||
if !store.nodes.contains_key(key) {
|
if !store.nodes.contains_key(key) {
|
||||||
|
|
@ -180,13 +195,13 @@ pub fn used(args: &serde_json::Value) -> Result<String> {
|
||||||
Ok(format!("marked {} as used", key))
|
Ok(format!("marked {} as used", key))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn weight_set_def() -> ToolDef {
|
fn weight_set_def() -> ToolDef {
|
||||||
ToolDef::new("memory_weight_set",
|
ToolDef::new("memory_weight_set",
|
||||||
"Set a node's weight directly (0.01 to 1.0).",
|
"Set a node's weight directly (0.01 to 1.0).",
|
||||||
json!({"type":"object","properties":{"key":{"type":"string"},"weight":{"type":"number","description":"0.01 to 1.0"}},"required":["key","weight"]}))
|
json!({"type":"object","properties":{"key":{"type":"string"},"weight":{"type":"number","description":"0.01 to 1.0"}},"required":["key","weight"]}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn weight_set(args: &serde_json::Value) -> Result<String> {
|
fn weight_set(args: &serde_json::Value) -> Result<String> {
|
||||||
let mut store = load_store()?;
|
let mut store = load_store()?;
|
||||||
let key = store.resolve_key(get_str(args, "key")?).map_err(|e| anyhow::anyhow!("{}", e))?;
|
let key = store.resolve_key(get_str(args, "key")?).map_err(|e| anyhow::anyhow!("{}", e))?;
|
||||||
let weight = get_f64(args, "weight")? as f32;
|
let weight = get_f64(args, "weight")? as f32;
|
||||||
|
|
@ -195,13 +210,13 @@ pub fn weight_set(args: &serde_json::Value) -> Result<String> {
|
||||||
Ok(format!("weight {} {:.2} → {:.2}", key, old, new))
|
Ok(format!("weight {} {:.2} → {:.2}", key, old, new))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rename_def() -> ToolDef {
|
fn rename_def() -> ToolDef {
|
||||||
ToolDef::new("memory_rename",
|
ToolDef::new("memory_rename",
|
||||||
"Rename a node key in place. Same content, same links, new key.",
|
"Rename a node key in place. Same content, same links, new key.",
|
||||||
json!({"type":"object","properties":{"old_key":{"type":"string"},"new_key":{"type":"string"}},"required":["old_key","new_key"]}))
|
json!({"type":"object","properties":{"old_key":{"type":"string"},"new_key":{"type":"string"}},"required":["old_key","new_key"]}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rename(args: &serde_json::Value) -> Result<String> {
|
fn rename(args: &serde_json::Value) -> Result<String> {
|
||||||
let old_key = get_str(args, "old_key")?;
|
let old_key = get_str(args, "old_key")?;
|
||||||
let new_key = get_str(args, "new_key")?;
|
let new_key = get_str(args, "new_key")?;
|
||||||
let mut store = load_store()?;
|
let mut store = load_store()?;
|
||||||
|
|
@ -211,13 +226,13 @@ pub fn rename(args: &serde_json::Value) -> Result<String> {
|
||||||
Ok(format!("Renamed '{}' → '{}'", resolved, new_key))
|
Ok(format!("Renamed '{}' → '{}'", resolved, new_key))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn supersede_def() -> ToolDef {
|
fn supersede_def() -> ToolDef {
|
||||||
ToolDef::new("memory_supersede",
|
ToolDef::new("memory_supersede",
|
||||||
"Mark a node as superseded by another (sets weight to 0.01).",
|
"Mark a node as superseded by another (sets weight to 0.01).",
|
||||||
json!({"type":"object","properties":{"old_key":{"type":"string"},"new_key":{"type":"string"},"reason":{"type":"string"}},"required":["old_key","new_key"]}))
|
json!({"type":"object","properties":{"old_key":{"type":"string"},"new_key":{"type":"string"},"reason":{"type":"string"}},"required":["old_key","new_key"]}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn supersede(args: &serde_json::Value) -> Result<String> {
|
fn supersede(args: &serde_json::Value) -> Result<String> {
|
||||||
let old_key = get_str(args, "old_key")?;
|
let old_key = get_str(args, "old_key")?;
|
||||||
let new_key = get_str(args, "new_key")?;
|
let new_key = get_str(args, "new_key")?;
|
||||||
let reason = args.get("reason").and_then(|v| v.as_str()).unwrap_or("superseded");
|
let reason = args.get("reason").and_then(|v| v.as_str()).unwrap_or("superseded");
|
||||||
|
|
@ -234,7 +249,7 @@ pub fn supersede(args: &serde_json::Value) -> Result<String> {
|
||||||
Ok(format!("superseded {} → {} ({})", old_key, new_key, reason))
|
Ok(format!("superseded {} → {} ({})", old_key, new_key, reason))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn query_def() -> ToolDef {
|
fn query_def() -> ToolDef {
|
||||||
ToolDef::new("memory_query",
|
ToolDef::new("memory_query",
|
||||||
"Run a structured query against the memory graph. Supports filtering, \
|
"Run a structured query against the memory graph. Supports filtering, \
|
||||||
sorting, field selection. Examples: \"degree > 10 | sort weight | limit 5\", \
|
sorting, field selection. Examples: \"degree > 10 | sort weight | limit 5\", \
|
||||||
|
|
@ -242,7 +257,7 @@ pub fn query_def() -> ToolDef {
|
||||||
json!({"type":"object","properties":{"query":{"type":"string","description":"Query expression"}},"required":["query"]}))
|
json!({"type":"object","properties":{"query":{"type":"string","description":"Query expression"}},"required":["query"]}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn query(args: &serde_json::Value) -> Result<String> {
|
fn query(args: &serde_json::Value) -> Result<String> {
|
||||||
let query_str = get_str(args, "query")?;
|
let query_str = get_str(args, "query")?;
|
||||||
let store = load_store()?;
|
let store = load_store()?;
|
||||||
let graph = store.build_graph();
|
let graph = store.build_graph();
|
||||||
|
|
@ -250,7 +265,7 @@ pub fn query(args: &serde_json::Value) -> Result<String> {
|
||||||
.map_err(|e| anyhow::anyhow!("{}", e))
|
.map_err(|e| anyhow::anyhow!("{}", e))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn output_def() -> ToolDef {
|
pub(super) fn output_def() -> ToolDef {
|
||||||
ToolDef::new("output",
|
ToolDef::new("output",
|
||||||
"Produce a named output value. Use this to pass structured results \
|
"Produce a named output value. Use this to pass structured results \
|
||||||
between steps — subsequent prompts can see these in the conversation history.",
|
between steps — subsequent prompts can see these in the conversation history.",
|
||||||
|
|
@ -260,7 +275,7 @@ pub fn output_def() -> ToolDef {
|
||||||
},"required":["key","value"]}))
|
},"required":["key","value"]}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn output(args: &serde_json::Value) -> Result<String> {
|
pub(super) fn output(args: &serde_json::Value) -> Result<String> {
|
||||||
let key = get_str(args, "key")?;
|
let key = get_str(args, "key")?;
|
||||||
if key.starts_with("pid-") || key.contains('/') || key.contains("..") {
|
if key.starts_with("pid-") || key.contains('/') || key.contains("..") {
|
||||||
anyhow::bail!("invalid output key: {}", key);
|
anyhow::bail!("invalid output key: {}", key);
|
||||||
|
|
@ -276,7 +291,7 @@ pub fn output(args: &serde_json::Value) -> Result<String> {
|
||||||
|
|
||||||
// ── Journal tools ──────────────────────────────────────────────
|
// ── Journal tools ──────────────────────────────────────────────
|
||||||
|
|
||||||
pub fn journal_tail_def() -> ToolDef {
|
pub(super) fn journal_tail_def() -> ToolDef {
|
||||||
ToolDef::new("journal_tail",
|
ToolDef::new("journal_tail",
|
||||||
"Read the last N journal entries (default 1).",
|
"Read the last N journal entries (default 1).",
|
||||||
json!({"type":"object","properties":{
|
json!({"type":"object","properties":{
|
||||||
|
|
@ -284,7 +299,7 @@ pub fn journal_tail_def() -> ToolDef {
|
||||||
}}))
|
}}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn journal_tail(args: &serde_json::Value) -> Result<String> {
|
pub(super) fn journal_tail(args: &serde_json::Value) -> Result<String> {
|
||||||
let count = args.get("count").and_then(|v| v.as_u64()).unwrap_or(1) as usize;
|
let count = args.get("count").and_then(|v| v.as_u64()).unwrap_or(1) as usize;
|
||||||
let store = load_store()?;
|
let store = load_store()?;
|
||||||
let mut entries: Vec<&crate::store::Node> = store.nodes.values()
|
let mut entries: Vec<&crate::store::Node> = store.nodes.values()
|
||||||
|
|
@ -302,7 +317,7 @@ pub fn journal_tail(args: &serde_json::Value) -> Result<String> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn journal_new_def() -> ToolDef {
|
pub(super) fn journal_new_def() -> ToolDef {
|
||||||
ToolDef::new("journal_new",
|
ToolDef::new("journal_new",
|
||||||
"Start a new journal entry.",
|
"Start a new journal entry.",
|
||||||
json!({"type":"object","properties":{
|
json!({"type":"object","properties":{
|
||||||
|
|
@ -312,7 +327,7 @@ pub fn journal_new_def() -> ToolDef {
|
||||||
},"required":["name","title","body"]}))
|
},"required":["name","title","body"]}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn journal_new(args: &serde_json::Value) -> Result<String> {
|
pub(super) fn journal_new(args: &serde_json::Value) -> Result<String> {
|
||||||
let name = get_str(args, "name")?;
|
let name = get_str(args, "name")?;
|
||||||
let title = get_str(args, "title")?;
|
let title = get_str(args, "title")?;
|
||||||
let body = get_str(args, "body")?;
|
let body = get_str(args, "body")?;
|
||||||
|
|
@ -348,7 +363,7 @@ pub fn journal_new(args: &serde_json::Value) -> Result<String> {
|
||||||
Ok(format!("New entry '{}' ({} words)", title, word_count))
|
Ok(format!("New entry '{}' ({} words)", title, word_count))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn journal_update_def() -> ToolDef {
|
pub(super) fn journal_update_def() -> ToolDef {
|
||||||
ToolDef::new("journal_update",
|
ToolDef::new("journal_update",
|
||||||
"Append text to the most recent journal entry (same thread continuing).",
|
"Append text to the most recent journal entry (same thread continuing).",
|
||||||
json!({"type":"object","properties":{
|
json!({"type":"object","properties":{
|
||||||
|
|
@ -356,7 +371,7 @@ pub fn journal_update_def() -> ToolDef {
|
||||||
},"required":["body"]}))
|
},"required":["body"]}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn journal_update(args: &serde_json::Value) -> Result<String> {
|
pub(super) fn journal_update(args: &serde_json::Value) -> Result<String> {
|
||||||
let body = get_str(args, "body")?;
|
let body = get_str(args, "body")?;
|
||||||
let mut store = load_store()?;
|
let mut store = load_store()?;
|
||||||
let latest_key = store.nodes.values()
|
let latest_key = store.nodes.values()
|
||||||
|
|
|
||||||
|
|
@ -202,56 +202,22 @@ pub async fn dispatch_shared(
|
||||||
|
|
||||||
/// Return all registered tools with definitions + handlers.
|
/// Return all registered tools with definitions + handlers.
|
||||||
pub fn tools() -> Vec<Tool> {
|
pub fn tools() -> Vec<Tool> {
|
||||||
vec![
|
let mut all = vec![
|
||||||
// File tools
|
// File tools
|
||||||
Tool { def: read::definition(), handler: |_a, v| Box::pin(async move { read::read_file(&v) }) },
|
Tool { def: read::definition(), handler: |_a, v| Box::pin(async move { read::read_file(&v) }) },
|
||||||
Tool { def: write::definition(), handler: |_a, v| Box::pin(async move { write::write_file(&v) }) },
|
Tool { def: write::definition(), handler: |_a, v| Box::pin(async move { write::write_file(&v) }) },
|
||||||
Tool { def: edit::definition(), handler: |_a, v| Box::pin(async move { edit::edit_file(&v) }) },
|
Tool { def: edit::definition(), handler: |_a, v| Box::pin(async move { edit::edit_file(&v) }) },
|
||||||
Tool { def: grep::definition(), handler: |_a, v| Box::pin(async move { grep::grep(&v) }) },
|
Tool { def: grep::definition(), handler: |_a, v| Box::pin(async move { grep::grep(&v) }) },
|
||||||
Tool { def: glob::definition(), handler: |_a, v| Box::pin(async move { glob::glob_search(&v) }) },
|
Tool { def: glob::definition(), handler: |_a, v| Box::pin(async move { glob::glob_search(&v) }) },
|
||||||
|
|
||||||
// Execution tools
|
|
||||||
Tool { def: bash::definition(), handler: |_a, v| Box::pin(async move { bash::run_bash(&v).await }) },
|
Tool { def: bash::definition(), handler: |_a, v| Box::pin(async move { bash::run_bash(&v).await }) },
|
||||||
Tool { def: web::fetch_definition(), handler: |_a, v| Box::pin(async move { web::web_fetch(&v).await }) },
|
Tool { def: web::fetch_definition(), handler: |_a, v| Box::pin(async move { web::web_fetch(&v).await }) },
|
||||||
Tool { def: web::search_definition(), handler: |_a, v| Box::pin(async move { web::web_search(&v).await }) },
|
Tool { def: web::search_definition(), handler: |_a, v| Box::pin(async move { web::web_search(&v).await }) },
|
||||||
|
|
||||||
// Vision
|
|
||||||
Tool { def: vision::definition(), handler: |_a, v| Box::pin(async move { vision::view_image_text(&v) }) },
|
Tool { def: vision::definition(), handler: |_a, v| Box::pin(async move { vision::view_image_text(&v) }) },
|
||||||
|
];
|
||||||
// Memory tools
|
all.extend(memory::memory_tools());
|
||||||
Tool { def: memory::render_def(), handler: |_a, v| Box::pin(async move { memory::render(&v) }) },
|
all.extend(channels::tools());
|
||||||
Tool { def: memory::write_def(), handler: |_a, v| Box::pin(async move { memory::write(&v) }) },
|
all.extend(control::tools());
|
||||||
Tool { def: memory::search_def(), handler: |_a, v| Box::pin(async move { memory::search(&v) }) },
|
all
|
||||||
Tool { def: memory::links_def(), handler: |_a, v| Box::pin(async move { memory::links(&v) }) },
|
|
||||||
Tool { def: memory::link_set_def(), handler: |_a, v| Box::pin(async move { memory::link_set(&v) }) },
|
|
||||||
Tool { def: memory::link_add_def(), handler: |_a, v| Box::pin(async move { memory::link_add(&v) }) },
|
|
||||||
Tool { def: memory::used_def(), handler: |_a, v| Box::pin(async move { memory::used(&v) }) },
|
|
||||||
Tool { def: memory::weight_set_def(), handler: |_a, v| Box::pin(async move { memory::weight_set(&v) }) },
|
|
||||||
Tool { def: memory::rename_def(), handler: |_a, v| Box::pin(async move { memory::rename(&v) }) },
|
|
||||||
Tool { def: memory::supersede_def(), handler: |_a, v| Box::pin(async move { memory::supersede(&v) }) },
|
|
||||||
Tool { def: memory::query_def(), handler: |_a, v| Box::pin(async move { memory::query(&v) }) },
|
|
||||||
Tool { def: memory::output_def(), handler: |_a, v| Box::pin(async move { memory::output(&v) }) },
|
|
||||||
|
|
||||||
// Channel tools
|
|
||||||
Tool { def: channels::definitions()[0].clone(), handler: |_a, v| Box::pin(async move { channels::channel_list().await }) },
|
|
||||||
Tool { def: channels::definitions()[1].clone(), handler: |_a, v| Box::pin(async move { channels::channel_recv(&v).await }) },
|
|
||||||
Tool { def: channels::definitions()[2].clone(), handler: |_a, v| Box::pin(async move { channels::channel_send(&v).await }) },
|
|
||||||
Tool { def: channels::definitions()[3].clone(), handler: |_a, v| Box::pin(async move { channels::channel_notifications().await }) },
|
|
||||||
|
|
||||||
// Control tools
|
|
||||||
Tool { def: control::definitions()[0].clone(),
|
|
||||||
handler: |_a, _v| Box::pin(async { Ok("Pausing autonomous behavior. Only user input will wake you.".into()) }) },
|
|
||||||
Tool { def: control::definitions()[1].clone(),
|
|
||||||
handler: |_a, v| Box::pin(async move {
|
|
||||||
let model = v.get("model").and_then(|v| v.as_str()).unwrap_or("");
|
|
||||||
Ok(format!("Switching to model: {}", model))
|
|
||||||
}) },
|
|
||||||
Tool { def: control::definitions()[2].clone(),
|
|
||||||
handler: |_a, v| Box::pin(async move {
|
|
||||||
let msg = v.get("message").and_then(|v| v.as_str()).unwrap_or("(yielding to user)");
|
|
||||||
Ok(msg.to_string())
|
|
||||||
}) },
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return all tool definitions (extracted from tools()).
|
/// Return all tool definitions (extracted from tools()).
|
||||||
|
|
@ -261,9 +227,10 @@ pub fn definitions() -> Vec<ToolDef> {
|
||||||
|
|
||||||
/// Return memory + journal tool definitions only.
|
/// Return memory + journal tool definitions only.
|
||||||
pub fn memory_and_journal_definitions() -> Vec<ToolDef> {
|
pub fn memory_and_journal_definitions() -> Vec<ToolDef> {
|
||||||
let mut defs = memory::definitions();
|
memory::memory_tools().into_iter()
|
||||||
defs.extend(memory::journal_definitions());
|
.chain(memory::journal_tools())
|
||||||
defs
|
.map(|t| t.def)
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a short summary of tool args for the tools pane header.
|
/// Create a short summary of tool args for the tools pane header.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue