1use async_trait::async_trait;
4use serde::Deserialize;
5
6use crate::diagnostics::{collect_doctor_report, render_doctor_report};
7
8use super::traits::*;
9
10pub struct DoctorTool;
11
12impl DoctorTool {
13 pub fn new() -> Self {
14 Self
15 }
16}
17
18impl Default for DoctorTool {
19 fn default() -> Self {
20 Self::new()
21 }
22}
23
24#[derive(Deserialize)]
25struct DoctorArgs {
26 #[serde(default)]
27 verbose: bool,
28}
29
30#[async_trait]
31impl Tool for DoctorTool {
32 fn name(&self) -> &str {
33 "doctor"
34 }
35
36 fn spec(&self) -> ToolSpec {
37 ToolSpec {
38 name: "doctor".to_string(),
39 description: "Run system diagnostics — check deps, env vars, disk space, memory, network, and bot health. Like 'zeroclaw doctor'.".to_string(),
40 parameters: serde_json::json!({
41 "type": "object",
42 "properties": {
43 "verbose": {
44 "type": "boolean",
45 "description": "Show detailed output (default false)"
46 }
47 }
48 }),
49 }
50 }
51
52 async fn execute(&self, arguments: &str) -> anyhow::Result<ToolResult> {
53 let args: DoctorArgs =
54 serde_json::from_str(arguments).unwrap_or(DoctorArgs { verbose: false });
55 let report = collect_doctor_report(None, Some("apollo.json"), args.verbose).await;
56 Ok(ToolResult::success(render_doctor_report(&report)))
57 }
58}