- Added tracing instrumentation and improved logging messages in the Pong, Todofinish, and Todowrite tools for better debugging and monitoring. - Enhanced documentation comments for clarity on tool functionalities and workflows. - Implemented tracing in WorkflowRun, NoteFinding, ReadFindings, and HiveMind tools to track execution phases and findings. - Updated TUI overlays (e.g., Bash, Clear Confirm, Editor, Effort Level, Help, Key Input, Learning, Loading, MCP, Model Selector, Plan, Quit Confirm, Rewind, Settings, Todo, Usage) with debug logging to capture rendering details. - Improved the status bar and workflow panel rendering with additional debug information. - Added tracing to various utility functions to facilitate better performance monitoring and error tracking.
79 lines
2.4 KiB
Rust
79 lines
2.4 KiB
Rust
//! Edit a file by replacing a text block.
|
|
|
|
use crate::tools::{resolve_path, Tool, ToolCtx};
|
|
use anyhow::Result;
|
|
use serde_json::{json, Value};
|
|
use std::fs;
|
|
use tracing::{info, instrument, warn};
|
|
|
|
/// Edit a file by replacing `old` text with `new` text.
|
|
///
|
|
/// Flow: resolve path → read file → ensure `old` exists → perform single
|
|
/// replacement → write file.
|
|
pub struct Edit;
|
|
|
|
impl Tool for Edit {
|
|
fn name(&self) -> &'static str {
|
|
"edit"
|
|
}
|
|
|
|
fn description(&self) -> &'static str {
|
|
"Edit a file by replacing 'old' text with 'new' text"
|
|
}
|
|
|
|
fn parameters(&self) -> Value {
|
|
json!({
|
|
"type": "object",
|
|
"properties": {
|
|
"path": {
|
|
"type": "string",
|
|
"description": "Path to the file to edit (relative to workspace root)"
|
|
},
|
|
"old": {
|
|
"type": "string",
|
|
"description": "Text to replace (must exist in the file)"
|
|
},
|
|
"new": {
|
|
"type": "string",
|
|
"description": "Replacement text"
|
|
},
|
|
"reason": {
|
|
"type": "string",
|
|
"description": "Reason for this change"
|
|
}
|
|
},
|
|
"required": ["path", "old", "new"]
|
|
})
|
|
}
|
|
|
|
#[instrument(skip(self, ctx, args))]
|
|
fn run(&self, ctx: &ToolCtx, args: &Value) -> Result<String> {
|
|
let rel = crate::tools::arg_str(args, "path")?;
|
|
let old = crate::tools::arg_str(args, "old")?;
|
|
let new = crate::tools::arg_str(args, "new")?;
|
|
let path = resolve_path(&ctx.workspaces, &rel)?;
|
|
|
|
if !path.exists() {
|
|
warn!(rel = %rel, "edit target does not exist");
|
|
anyhow::bail!("file '{rel}' does not exist");
|
|
}
|
|
|
|
let content = fs::read_to_string(&path)?;
|
|
if !content.contains(&old) {
|
|
warn!(rel = %rel, old_len = old.len(), "old text not found in file");
|
|
anyhow::bail!("old text not found in '{}'", rel);
|
|
}
|
|
|
|
let new_content = content.replacen(&old, &new, 1);
|
|
fs::write(&path, &new_content)?;
|
|
|
|
info!(rel = %rel, old_len = old.len(), new_len = new.len(), "file edited");
|
|
Ok(format!(
|
|
"Edited '{}': replaced {} bytes with {} bytes",
|
|
rel,
|
|
old.len(),
|
|
new.len()
|
|
))
|
|
}
|
|
}
|