use std::sync::Arc;
use schemars::JsonSchema;
use serde::Deserialize;
use serde_json::Value;
use sgr_agent_core::agent_tool::{Tool, ToolError, ToolOutput, parse_args};
use sgr_agent_core::context::AgentContext;
use sgr_agent_core::schema::json_schema_for;
use crate::backend::FileBackend;
pub struct DeleteTool<B: FileBackend>(pub Arc<B>);
#[derive(Deserialize, JsonSchema)]
struct DeleteArgs {
#[serde(default)]
path: Option<String>,
#[serde(default)]
paths: Option<Vec<String>>,
}
#[async_trait::async_trait]
impl<B: FileBackend> Tool for DeleteTool<B> {
fn name(&self) -> &str {
"delete"
}
fn description(&self) -> &str {
"Delete one or more files. Pass `path` for a single file, or `paths` (array) to delete many files at once."
}
fn parameters_schema(&self) -> Value {
json_schema_for::<DeleteArgs>()
}
async fn execute(&self, args: Value, _ctx: &mut AgentContext) -> Result<ToolOutput, ToolError> {
let a: DeleteArgs = parse_args(&args)?;
let targets: Vec<String> = match (a.path, a.paths) {
(_, Some(ps)) if !ps.is_empty() => ps,
(Some(p), _) => vec![p],
_ => {
return Err(ToolError::InvalidArgs(
"provide `path` (string) or `paths` (array)".into(),
));
}
};
let mut results: Vec<String> = Vec::with_capacity(targets.len());
let mut errors: Vec<String> = Vec::new();
for path in &targets {
match self.0.delete(path).await {
Ok(()) => results.push(format!("Deleted {}", path)),
Err(e) => errors.push(format!("FAILED {}: {}", path, e)),
}
}
let mut out = results.join("\n");
if !errors.is_empty() {
if !out.is_empty() {
out.push('\n');
}
out.push_str(&errors.join("\n"));
}
if out.is_empty() {
out = "No files deleted".to_string();
}
Ok(ToolOutput::text(out))
}
}