Skip to main content

sgr_agent_tools/
delete.rs

1//! DeleteTool — delete one or more files (batch delete support).
2
3use std::sync::Arc;
4
5use schemars::JsonSchema;
6use serde::Deserialize;
7use serde_json::Value;
8use sgr_agent_core::agent_tool::{Tool, ToolError, ToolOutput, parse_args};
9use sgr_agent_core::context::AgentContext;
10use sgr_agent_core::schema::json_schema_for;
11
12use crate::backend::FileBackend;
13
14pub struct DeleteTool<B: FileBackend>(pub Arc<B>);
15
16#[derive(Deserialize, JsonSchema)]
17struct DeleteArgs {
18    /// File path to delete (use this for single file)
19    #[serde(default)]
20    path: Option<String>,
21    /// Multiple file paths to delete in one call (preferred for bulk cleanup)
22    #[serde(default)]
23    paths: Option<Vec<String>>,
24}
25
26#[async_trait::async_trait]
27impl<B: FileBackend> Tool for DeleteTool<B> {
28    fn name(&self) -> &str {
29        "delete"
30    }
31    fn description(&self) -> &str {
32        "Delete one or more files. Pass `path` for a single file, or `paths` (array) to delete many files at once."
33    }
34    fn parameters_schema(&self) -> Value {
35        json_schema_for::<DeleteArgs>()
36    }
37    async fn execute(&self, args: Value, _ctx: &mut AgentContext) -> Result<ToolOutput, ToolError> {
38        let a: DeleteArgs = parse_args(&args)?;
39
40        let targets: Vec<String> = match (a.path, a.paths) {
41            (_, Some(ps)) if !ps.is_empty() => ps,
42            (Some(p), _) => vec![p],
43            _ => {
44                return Err(ToolError::InvalidArgs(
45                    "provide `path` (string) or `paths` (array)".into(),
46                ));
47            }
48        };
49
50        let mut results: Vec<String> = Vec::with_capacity(targets.len());
51        let mut errors: Vec<String> = Vec::new();
52
53        for path in &targets {
54            match self.0.delete(path).await {
55                Ok(()) => results.push(format!("Deleted {}", path)),
56                Err(e) => errors.push(format!("FAILED {}: {}", path, e)),
57            }
58        }
59
60        let mut out = results.join("\n");
61        if !errors.is_empty() {
62            if !out.is_empty() {
63                out.push('\n');
64            }
65            out.push_str(&errors.join("\n"));
66        }
67        if out.is_empty() {
68            out = "No files deleted".to_string();
69        }
70        Ok(ToolOutput::text(out))
71    }
72}