Dispatch a tool call to the appropriate handler. `base_dir` is the project root directory used for file operations, command execution, and benchmark/profiling tools. `state` is the mutable agent session state used by `get_status` and `finish`.
(
call: &ToolCall,
base_dir: &std::path::Path,
config: &crate::bench_tools::BenchConfig,
state: &mut crate::state::AgentState,
)
| 303 | /// |
| 304 | /// `state` is the mutable agent session state used by `get_status` and `finish`. |
| 305 | pub async fn dispatch_tool_call( |
| 306 | call: &ToolCall, |
| 307 | base_dir: &std::path::Path, |
| 308 | config: &crate::bench_tools::BenchConfig, |
| 309 | state: &mut crate::state::AgentState, |
| 310 | ) -> ToolResult { |
| 311 | let result = match call { |
| 312 | ToolCall::ReadFile { path } => crate::sandbox::read_file(base_dir, path), |
| 313 | ToolCall::WriteFile { path, content } => { |
| 314 | crate::sandbox::write_file(base_dir, path, content) |
| 315 | } |
| 316 | ToolCall::ListFiles { path } => crate::sandbox::list_files(base_dir, path), |
| 317 | ToolCall::RunBenchmark { |
| 318 | concurrency, |
| 319 | warmup, |
| 320 | max_queries, |
| 321 | } => crate::bench_tools::run_benchmark(base_dir, config, *concurrency, *warmup, *max_queries).await, |
| 322 | ToolCall::RunProfiling { duration } => { |
| 323 | crate::bench_tools::run_profiling(base_dir, config, *duration).await |
| 324 | } |
| 325 | ToolCall::RunCorrectnessTest => crate::bench_tools::run_correctness_test(base_dir, config).await, |
| 326 | ToolCall::BuildProject => crate::bench_tools::build_project_tool(base_dir).await, |
| 327 | ToolCall::GetStatus => ToolResult::GetStatus(state.get_status()), |
| 328 | ToolCall::Finish { summary } => state.finish(base_dir, config, summary).await, |
| 329 | }; |
| 330 | |
| 331 | // Track best benchmark result and backup src when a new best QPS is achieved |
| 332 | if let ToolResult::RunBenchmark(ref br) = result { |
| 333 | if br.recall_passed { |
| 334 | let is_new_best = match &state.best_benchmark { |
| 335 | Some(prev) => br.qps > prev.qps, |
| 336 | None => true, |
| 337 | }; |
| 338 | if is_new_best { |
| 339 | eprintln!( |
| 340 | "[agent] New best QPS: {:.2} (recall: {:.4}). Backing up src to src_best_qps/", |
| 341 | br.qps, br.recall |
| 342 | ); |
| 343 | state.best_benchmark = Some(br.clone()); |
| 344 | // Backup src/ to src_best_qps/ |
| 345 | let src_dir = base_dir.join("src"); |
| 346 | let backup_dir = base_dir.join("src_best_qps"); |
| 347 | if backup_dir.exists() { |
| 348 | let _ = std::fs::remove_dir_all(&backup_dir); |
| 349 | } |
| 350 | if let Err(e) = copy_dir_recursive(&src_dir, &backup_dir) { |
| 351 | eprintln!("[agent] Warning: failed to backup src to src_best_qps: {}", e); |
| 352 | } |
| 353 | } |
| 354 | } |
| 355 | } |
| 356 | |
| 357 | result |
| 358 | } |
| 359 | |
| 360 | /// Recursively copy a directory. |
| 361 | fn copy_dir_recursive(src: &std::path::Path, dst: &std::path::Path) -> std::io::Result<()> { |