- Required top-level `path` in edit requests, removed per-entry `path` fields, and updated docs/tests to match. - Updated patch/hashline/atom streaming preview generation to return a single request-level path diff preview. - Changed edit execution to route patch/replace/atom/hashline through single-path handlers sharing `path`. - Added `scripts/analyze-edit-formats` Go CLI with reports to audit edit-tool usage from session JSONL logs.
3.5 KiB
Applies precise file edits using full anchors from read output (for example 160sr).
Read the file first. Copy the full anchors exactly as shown by read.
Edit entry: { loc, content }
loc— where to apply the edit (see below)content— replacement/inserted lines (string[], one element per line;nullto delete)
loc values
"append"/"prepend"— insert at end/start of file{ append: "123th" }/{ prepend: "123th" }— insert after/before anchored line{ range: { pos: "123th", end: "123th" } }— replace inclusive rangepos..endwith new content (setpos == endfor single-line replace)
{{hline 1 "// @ts-ignore"}}
{{hline 2 "const timeout = 5000;"}}
{{hline 3 "const tag = \"DO NOT SHIP\";"}}
{{hline 4 ""}}
{{hline 5 "function alpha() {"}}
{{hline 6 "\tlog();"}}
{{hline 7 "}"}}
{{hline 8 ""}}
{{hline 9 "function beta() {"}}
{{hline 10 "\t// TODO: remove after migration"}}
{{hline 11 "\tlegacy();"}}
{{hline 12 "\ttry {"}}
{{hline 13 "\t\treturn parse(data);"}}
{{hline 14 "\t} catch (err) {"}}
{{hline 15 "\t\tconsole.error(err);"}}
{{hline 16 "\t\treturn null;"}}
{{hline 17 "\t}"}}
{{hline 18 "}"}}
Replace a block body
Replace only the catch body. Do not target the shared boundary line } catch (err) {.
{path:"a.ts",edits:[{loc:{range:{pos:{{href 15 "\t\tconsole.error(err);"}},end:{{href 16 "\t\treturn null;"}}}},content:["\t\tif (isEnoent(err)) return null;","\t\tthrow err;"]}]}
Replace whole block including closing brace
Replace alpha's entire body including the closing }. end MUST be {{href 7 "}"}} because content includes }.
{path:"a.ts",edits:[{loc:{range:{pos:{{href 6 "\tlog();"}},end:{{href 7 "}"}}}},content:["\tvalidate();","\tlog();","}"]}]}
Wrong: end: {{href 6 "\tlog();"}} — line 7 (}) survives AND content emits }, producing two closing braces.
Replace one line
Single-line replace uses pos == end.
{path:"a.ts",edits:[{loc:{range:{pos:{{href 2 "const timeout = 5000;"}},end:{{href 2 "const timeout = 5000;"}}}},content:["const timeout = 30_000;"]}]}
Delete a range
{path:"a.ts",edits:[{loc:{range:{pos:{{href 10 "\t// TODO: remove after migration"}},end:{{href 11 "\tlegacy();"}}}},content:null}]}
Insert before a sibling
When adding a sibling declaration, prefer prepend on the next declaration.
{path:"a.ts",edits:[{loc:{prepend:{{href 9 "function beta() {"}}},content:["function gamma() {","\tvalidate();","}",""]}]}