| 453 | } |
| 454 | |
| 455 | pub async fn execute(&self, name: &str, args: &serde_json::Value) -> Result<ToolResult> { |
| 456 | let ctx = self.registry.context(); |
| 457 | if let Err(e) = Self::check_workspace_boundary(name, args, &ctx) { |
| 458 | return Ok(ToolResult::error(name, e.to_string())); |
| 459 | } |
| 460 | |
| 461 | log_tool_invocation(name, args); |
| 462 | self.capture_snapshot(name, args); |
| 463 | let mut result = self.registry.execute_with_context(name, args, &ctx).await; |
| 464 | if let Ok(ref mut r) = result { |
| 465 | self.attach_diff_metadata(name, args, r); |
| 466 | } |
| 467 | match &result { |
| 468 | Ok(r) => tracing::info!("Tool {} completed with exit_code={}", name, r.exit_code), |
| 469 | Err(e) => tracing::error!("Tool {} failed: {}", name, e), |
| 470 | } |
| 471 | result |
| 472 | } |
| 473 | |
| 474 | pub async fn execute_with_context( |
| 475 | &self, |