tools: route all dispatch through Tool registry
dispatch() and dispatch_shared() now look up tools by name in the registry and call the handler directly. No more match-on-name-strings. MCP server also uses the registry for both definitions and dispatch, eliminating the last duplicated tool logic. dispatch_with_agent() passes the optional Arc<Mutex<Agent>> through for tools that need agent context (control tools, working stack). Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
parent
3e6c77e31e
commit
03cf13e9eb
2 changed files with 46 additions and 83 deletions
|
|
@ -158,81 +158,46 @@ pub fn truncate_output(mut s: String, max: usize) -> String {
|
|||
s
|
||||
}
|
||||
|
||||
/// Dispatch a tool call by name.
|
||||
///
|
||||
/// Tries agent-specific tools first (control, vision), then
|
||||
/// delegates to thought::dispatch for shared tools.
|
||||
///
|
||||
/// Note: working_stack is handled in runner.rs before reaching this
|
||||
/// function (it needs mutable context access).
|
||||
/// Dispatch a tool call by name. Handles all tools:
|
||||
/// agent-specific (control, vision), memory/journal, file/bash.
|
||||
/// Dispatch a tool call by name through the registry.
|
||||
pub async fn dispatch(
|
||||
name: &str,
|
||||
args: &serde_json::Value,
|
||||
) -> ToolOutput {
|
||||
// Agent-specific tools
|
||||
let rich_result = match name {
|
||||
"pause" => Some(control::pause(args)),
|
||||
"switch_model" => Some(control::switch_model(args)),
|
||||
"yield_to_user" => Some(control::yield_to_user(args)),
|
||||
"view_image" => Some(vision::view_image(args)),
|
||||
_ => None,
|
||||
};
|
||||
if let Some(result) = rich_result {
|
||||
return result.unwrap_or_else(ToolOutput::error);
|
||||
}
|
||||
dispatch_with_agent(name, args, None).await
|
||||
}
|
||||
|
||||
if let Some(output) = dispatch_shared(name, args, None).await {
|
||||
return output;
|
||||
/// Dispatch a tool call with optional agent context.
|
||||
pub async fn dispatch_with_agent(
|
||||
name: &str,
|
||||
args: &serde_json::Value,
|
||||
agent: Option<std::sync::Arc<tokio::sync::Mutex<super::Agent>>>,
|
||||
) -> ToolOutput {
|
||||
for tool in tools() {
|
||||
if tool.def.function.name == name {
|
||||
return match (tool.handler)(agent, args.clone()).await {
|
||||
Ok(s) => ToolOutput::text(s),
|
||||
Err(e) => ToolOutput::error(e),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
ToolOutput::error(format!("Unknown tool: {}", name))
|
||||
}
|
||||
|
||||
/// Dispatch shared tools (memory, file, bash). Used by both the
|
||||
/// interactive agent and subconscious agents. Provenance tracks
|
||||
/// which agent made the call for memory attribution.
|
||||
/// Dispatch shared tools — used by subconscious agents.
|
||||
pub async fn dispatch_shared(
|
||||
name: &str,
|
||||
args: &serde_json::Value,
|
||||
provenance: Option<&str>,
|
||||
_provenance: Option<&str>,
|
||||
) -> Option<ToolOutput> {
|
||||
// Memory and journal tools
|
||||
if name.starts_with("memory_") || name.starts_with("journal_") || name == "output" {
|
||||
let result = memory::dispatch(name, args, provenance);
|
||||
return Some(match result {
|
||||
Ok(s) => ToolOutput::text(s),
|
||||
Err(e) => ToolOutput::error(e),
|
||||
});
|
||||
for tool in tools() {
|
||||
if tool.def.function.name == name {
|
||||
return Some(match (tool.handler)(None, args.clone()).await {
|
||||
Ok(s) => ToolOutput::text(s),
|
||||
Err(e) => ToolOutput::error(e),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Channel tools
|
||||
if name.starts_with("channel_") {
|
||||
let result = channels::dispatch(name, args).await;
|
||||
return Some(match result {
|
||||
Ok(s) => ToolOutput::text(s),
|
||||
Err(e) => ToolOutput::error(e),
|
||||
});
|
||||
}
|
||||
|
||||
// File and execution tools
|
||||
let result = match name {
|
||||
"read_file" => read::read_file(args),
|
||||
"write_file" => write::write_file(args),
|
||||
"edit_file" => edit::edit_file(args),
|
||||
"bash" => bash::run_bash(args).await,
|
||||
"web_fetch" => web::web_fetch(args).await,
|
||||
"web_search" => web::web_search(args).await,
|
||||
"grep" => grep::grep(args),
|
||||
"glob" => glob::glob_search(args),
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
Some(match result {
|
||||
Ok(s) => ToolOutput::text(s),
|
||||
Err(e) => ToolOutput::error(e),
|
||||
})
|
||||
None
|
||||
}
|
||||
|
||||
/// Return all registered tools with definitions + handlers.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue