feat(tools): support batched edits with optional replaceAll in edit_file#274
Merged
LeeCheneler merged 1 commit intomainfrom Apr 9, 2026
Merged
feat(tools): support batched edits with optional replaceAll in edit_file#274LeeCheneler merged 1 commit intomainfrom
LeeCheneler merged 1 commit intomainfrom
Conversation
Replace the single oldString/newString pair with an `edits` array so a refactor that touches several spots in a file can complete in one tool call, with one confirmation prompt and one combined diff. Each edit takes oldString, newString, and an optional replaceAll flag (default false). Edits are applied sequentially in memory — each operates on the result of the previous edit, not the original content. The whole call is atomic per file: if any edit fails, the file is left untouched and the error identifies which edit (1-based) failed. Closes #273
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Extend
edit_fileto accept an array of edits and an optionalreplaceAllflag per edit, so the model can complete a multi-spot refactor in a single tool call with one combined diff and one confirmation prompt.GitHub Issue
Closes #273
What Changed
The schema for
edit_filenow takespathand aneditsarray. Each edit is{ oldString, newString, replaceAll? }(replaceAll defaults to false). The single-pair shape is gone.Sequential, atomic application. Edits are applied to the file content in order, in memory. Each edit operates on the result of the previous edit, not the original content — this matches how a person would think about a sequence of changes and avoids forcing the model to mentally diff non-overlapping windows in the original. The whole call is atomic per file: if any edit fails the file is left untouched and the error message identifies which edit (1-based) failed and why.
replaceAll opt-in. With
replaceAll: false(the default) the existing unique-match guardrail still applies —oldStringmust appear exactly once or the edit fails. WithreplaceAll: trueevery occurrence is replaced and the edit fails only if there are zero matches. This removes the friction of having to add surrounding context to disambiguate when the model legitimately wants to rename every occurrence (variable rename, import path change), without weakening the default safety.One diff, one prompt. A single combined unified diff is built from the original file content vs. the final post-all-edits content, and the confirmation prompt fires once with that combined diff. Permission semantics are unchanged.
formatCallshowspathfor a single edit andpath (N edits)for N>1, so the collapsed tool header carries the batch size.Description rewrite. The tool description now explains sequential application, atomicity,
replaceAllsemantics, and explicitly nudges the model to prefer batching over multiple calls — LLMs follow tool descriptions closely and this is where the speedup actually lands.The system prompt's read-before-write example (
src/prompt/build-system-prompt.ts) was updated to use the neweditsarray shape so the model sees a consistent contract.Notes for Reviewers
Regex matching was discussed and intentionally left out — it's a footgun for LLM callers (escaping/flavour confusion, silent corruption on auto-approved edits) and almost everything people reach for regex for is covered by
replaceAllwith a literal string. If a real need surfaces later it can ship as an opt-inmode: "regex"with stricter confirmation rules.