use crate::tools::{all_tools, Tool, ToolCtx}; use anyhow::Result; use std::future::Future; use zesdex_application::agent::ToolExecutor; pub struct InfrastructureToolExecutor { ctx: ToolCtx, tools: Vec>, } impl InfrastructureToolExecutor { pub fn new(ctx: ToolCtx) -> Self { Self { ctx, tools: all_tools(), } } /// Whether a tool is read-only and safe to execute concurrently with /// other parallel-safe tools. Delegates to the registry so the main /// turn loop and subagent engine share one source of truth. pub fn is_parallel_safe(tool_name: &str) -> bool { crate::tools::tool_is_parallel_safe(tool_name) } } impl ToolExecutor for InfrastructureToolExecutor { fn execute( &self, tool_name: &str, args: &serde_json::Value, ) -> impl Future> + Send { // Find the tool by name let tool_opt = self.tools.iter().find(|t| t.name() == tool_name); let ctx = self.ctx.clone(); let args = args.clone(); async move { match tool_opt { Some(tool) => tokio::task::block_in_place(move || tool.run(&ctx, &args)), None => { anyhow::bail!("Unknown tool: {}", tool_name) } } } } fn is_parallel_safe(&self, tool_name: &str) -> bool { Self::is_parallel_safe(tool_name) } }