use super::ToolArgs;
use super::ToolContext;
use super::error::ToolError;
use serde_json::Value;
use std::fs;
pub(super) fn tool_edit(args: &Value, ctx: &ToolContext) -> Result<String, ToolError> {
let args = ToolArgs::new(args);
let path = args.get_str("path")?;
let old = args.get_str("old")?;
let new = args.get_str("new")?;
let all = args.get_bool("all", false);
let full_path = ctx.resolve_path(path)?;
let text =
fs::read_to_string(&full_path).map_err(|_| ToolError::FileNotFound(path.to_string()))?;
if !text.contains(old) {
return Err(ToolError::PatternNotFound(old.to_string()));
}
let count = text.matches(old).count();
if !all && count > 1 {
return Err(ToolError::AmbiguousPattern(count));
}
let replacement = if all {
text.replace(old, new)
} else {
text.replacen(old, new, 1)
};
fs::write(&full_path, replacement)?;
Ok("ok".to_string())
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
use std::fs;
#[test]
fn edit_replaces_text() {
let dir = tempfile::tempdir().unwrap();
let file = dir.path().join("a.txt");
fs::write(&file, "hello world").unwrap();
let ctx =
ToolContext::from_working_dir(dir.path().to_path_buf(), crate::fs_mode::FsMode::Write);
let args = json!({"path": "a.txt", "old": "world", "new": "there"});
let out = tool_edit(&args, &ctx).unwrap();
assert_eq!(out, "ok");
let content = fs::read_to_string(file).unwrap();
assert_eq!(content, "hello there");
}
}