Edit file by replacing text.
| 210 | |
| 211 | |
| 212 | class EditTool(Tool): |
| 213 | """Edit file by replacing text.""" |
| 214 | |
| 215 | def __init__(self, workspace_dir: str = "."): |
| 216 | """Initialize EditTool with workspace directory. |
| 217 | |
| 218 | Args: |
| 219 | workspace_dir: Base directory for resolving relative paths |
| 220 | """ |
| 221 | self.workspace_dir = Path(workspace_dir).absolute() |
| 222 | |
| 223 | @property |
| 224 | def name(self) -> str: |
| 225 | return "edit_file" |
| 226 | |
| 227 | @property |
| 228 | def description(self) -> str: |
| 229 | return ( |
| 230 | "Perform exact string replacement in a file. The old_str must match exactly " |
| 231 | "and appear uniquely in the file, otherwise the operation will fail. " |
| 232 | "You must read the file first before editing. Preserve exact indentation from the source." |
| 233 | ) |
| 234 | |
| 235 | @property |
| 236 | def parameters(self) -> dict[str, Any]: |
| 237 | return { |
| 238 | "type": "object", |
| 239 | "properties": { |
| 240 | "path": { |
| 241 | "type": "string", |
| 242 | "description": "Absolute or relative path to the file", |
| 243 | }, |
| 244 | "old_str": { |
| 245 | "type": "string", |
| 246 | "description": "Exact string to find and replace (must be unique in file)", |
| 247 | }, |
| 248 | "new_str": { |
| 249 | "type": "string", |
| 250 | "description": "Replacement string (use for refactoring, renaming, etc.)", |
| 251 | }, |
| 252 | }, |
| 253 | "required": ["path", "old_str", "new_str"], |
| 254 | } |
| 255 | |
| 256 | async def execute(self, path: str, old_str: str, new_str: str) -> ToolResult: |
| 257 | """Execute edit file.""" |
| 258 | try: |
| 259 | file_path = Path(path) |
| 260 | # Resolve relative paths relative to workspace_dir |
| 261 | if not file_path.is_absolute(): |
| 262 | file_path = self.workspace_dir / file_path |
| 263 | |
| 264 | if not file_path.exists(): |
| 265 | return ToolResult( |
| 266 | success=False, |
| 267 | content="", |
| 268 | error=f"File not found: {path}", |
| 269 | ) |
no outgoing calls