use anyhow::Result;
use async_trait::async_trait;
use serde_json::Value;
use std::path::Path;
use super::{Tool, ToolOutput};
use crate::tools::file_ops::edit_file_in_workspace;
pub struct EditFileTool;
impl EditFileTool {
pub fn new() -> Self {
Self
}
}
impl Default for EditFileTool {
fn default() -> Self {
Self::new()
}
}
#[async_trait]
impl Tool for EditFileTool {
fn name(&self) -> &str {
"edit_file"
}
fn description(&self) -> &str {
"Replace text in a workspace file."
}
fn parameters_schema(&self) -> Value {
serde_json::json!({
"type": "object",
"properties": {
"path": { "type": "string" },
"old_string": { "type": "string" },
"new_string": { "type": "string" },
"replace_all": { "type": "boolean" }
},
"required": ["path", "old_string", "new_string"],
"additionalProperties": false
})
}
async fn execute(&self, input: Value) -> Result<ToolOutput> {
let path = input["path"]
.as_str()
.ok_or_else(|| anyhow::anyhow!("Missing required parameter: path"))?;
let old_string = input["old_string"]
.as_str()
.ok_or_else(|| anyhow::anyhow!("Missing required parameter: old_string"))?;
let new_string = input["new_string"]
.as_str()
.ok_or_else(|| anyhow::anyhow!("Missing required parameter: new_string"))?;
let replace_all = input["replace_all"].as_bool().unwrap_or(false);
let workspace_root = std::env::current_dir()?;
match edit_file_in_workspace(path, old_string, new_string, replace_all, &workspace_root) {
Ok(output) => {
let serialized = serde_json::to_string_pretty(&output)?;
Ok(ToolOutput::success(serialized))
}
Err(e) => Ok(ToolOutput::error(format!("Error editing file: {}", e))),
}
}
}