@probelabs/probe 0.6.0-rc309 → 0.6.0-rc311
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/binaries/{probe-v0.6.0-rc309-aarch64-apple-darwin.tar.gz → probe-v0.6.0-rc311-aarch64-apple-darwin.tar.gz} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc309-aarch64-unknown-linux-musl.tar.gz → probe-v0.6.0-rc311-aarch64-unknown-linux-musl.tar.gz} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc309-x86_64-apple-darwin.tar.gz → probe-v0.6.0-rc311-x86_64-apple-darwin.tar.gz} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc309-x86_64-pc-windows-msvc.zip → probe-v0.6.0-rc311-x86_64-pc-windows-msvc.zip} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc309-x86_64-unknown-linux-musl.tar.gz → probe-v0.6.0-rc311-x86_64-unknown-linux-musl.tar.gz} +0 -0
- package/build/agent/ProbeAgent.js +2 -0
- package/build/agent/shared/prompts.js +2 -0
- package/build/tools/edit.js +58 -21
- package/cjs/agent/ProbeAgent.cjs +60 -22
- package/cjs/index.cjs +60 -22
- package/package.json +1 -1
- package/src/agent/ProbeAgent.js +2 -0
- package/src/agent/shared/prompts.js +2 -0
- package/src/tools/edit.js +58 -21
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -3179,6 +3179,8 @@ Follow these instructions carefully:
|
|
|
3179
3179
|
7. When modifying files, choose the appropriate tool:
|
|
3180
3180
|
- Use 'edit' for all code modifications:
|
|
3181
3181
|
* PREFERRED: Use start_line (and optionally end_line) for line-targeted editing — this is the safest and most precise approach.${this.hashLines ? ' Use the line:hash references from extract/search output (e.g. "42:ab") for integrity verification.' : ''} Always use extract first to see line numbers${this.hashLines ? ' and hashes' : ''}, then edit by line reference.
|
|
3182
|
+
* In line-targeted mode, omitting position means replace/update the addressed lines. To insert new code near a line, you MUST set position="before" or position="after". Never express insertion as end_line < start_line.
|
|
3183
|
+
* To delete lines in line-targeted mode, target the exact start_line/end_line range and set new_string to the empty string "".
|
|
3182
3184
|
* For editing inside large functions: first use extract with the symbol target (e.g. "file.js#myFunction") to see the function with line numbers${this.hashLines ? ' and hashes' : ''}, then use start_line/end_line to surgically edit specific lines within it.
|
|
3183
3185
|
* For rewriting entire functions/classes/methods, use the symbol parameter instead (no exact text matching needed).
|
|
3184
3186
|
* FALLBACK ONLY: Use old_string + new_string for simple single-line changes where the text is unique. Copy old_string verbatim from the file. Keep old_string as small as possible.
|
|
@@ -141,6 +141,8 @@ Bash is fine for: formatters (gofmt, prettier, black), build/test/lint commands,
|
|
|
141
141
|
- Never expose secrets, API keys, or credentials in generated code. Never log sensitive information.
|
|
142
142
|
- Do not surprise the user with unrequested changes. Do what was asked, including reasonable follow-up actions, but do not refactor surrounding code or add features that were not requested.
|
|
143
143
|
- When editing files, keep edits focused and minimal. For changes spanning more than a few lines, prefer line-targeted editing (start_line/end_line) over text replacement (old_string) — it constrains scope and prevents accidental removal of adjacent content. Never include unrelated sections in an edit operation.
|
|
144
|
+
- In line-targeted mode, omitting position means replace/update the addressed lines. To insert code near an existing line, you MUST use position="before" or position="after". Never express insertion as end_line < start_line.
|
|
145
|
+
- To remove lines with line-targeted mode, target the exact start_line/end_line range and set new_string to the empty string "".
|
|
144
146
|
- After every significant change, verify the project still builds and passes linting. Do not wait until the end to discover breakage.
|
|
145
147
|
|
|
146
148
|
# Writing Tests
|
package/build/tools/edit.js
CHANGED
|
@@ -186,6 +186,13 @@ function buildLineEditResponse(file_path, startLine, endLine, newLineCount, upda
|
|
|
186
186
|
return msg;
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
+
const lineTargetedModeGuidance = `Line-targeted mode has three explicit behaviors:
|
|
190
|
+
- Replace/update lines: provide start_line and optionally end_line, and omit position
|
|
191
|
+
- Insert near a line: provide start_line and set position to "before" or "after"
|
|
192
|
+
- Delete lines: provide start_line/end_line for the exact range and set new_string to empty string ""
|
|
193
|
+
|
|
194
|
+
Inverted ranges (end_line < start_line) are always invalid and are never treated as insertion.`;
|
|
195
|
+
|
|
189
196
|
/**
|
|
190
197
|
* Handle line-targeted editing (replace, insert, delete by line numbers)
|
|
191
198
|
* @param {Object} params - Parameters
|
|
@@ -211,12 +218,15 @@ async function handleLineEdit({ resolvedPath, file_path, start_line, end_line, n
|
|
|
211
218
|
const endLine = endRef ? endRef.line : startLine;
|
|
212
219
|
|
|
213
220
|
if (endLine < startLine) {
|
|
214
|
-
|
|
221
|
+
const insertionHint = endLine === startLine - 1
|
|
222
|
+
? ` This looks like an insertion between lines ${endLine} and ${startLine}. To insert there without replacing existing code, use start_line="${startLine}" with position="before" or start_line="${endLine}" with position="after".`
|
|
223
|
+
: ' To insert new code, choose a single anchor line in start_line and set position to "before" or "after" instead of using an inverted range.';
|
|
224
|
+
return `Error editing file: end_line (${endLine}) must be >= start_line (${startLine}). Omitting position means replace/update the addressed lines, not insert.${insertionHint} To delete lines, use new_string as the empty string "" with a valid non-inverted range.`;
|
|
215
225
|
}
|
|
216
226
|
|
|
217
227
|
// Validate position if provided
|
|
218
228
|
if (position !== undefined && position !== null && position !== 'before' && position !== 'after') {
|
|
219
|
-
return 'Error editing file: Invalid position - must be "before" or "after". Use position="before" to insert before
|
|
229
|
+
return 'Error editing file: Invalid position - must be "before" or "after". Use position="before" to insert before start_line, position="after" to insert after start_line, or omit position to replace/update the addressed lines.';
|
|
220
230
|
}
|
|
221
231
|
|
|
222
232
|
// Read the file
|
|
@@ -304,23 +314,25 @@ export const editTool = (options = {}) => {
|
|
|
304
314
|
|
|
305
315
|
return tool({
|
|
306
316
|
name: 'edit',
|
|
307
|
-
description: `Edit files using text replacement, AST-aware symbol operations, or line-targeted
|
|
317
|
+
description: `Edit files using text replacement, AST-aware symbol operations, or line-targeted line replacement/insertion/deletion.
|
|
308
318
|
|
|
309
319
|
Modes:
|
|
310
320
|
1. Text edit: Provide old_string + new_string to find and replace text (with fuzzy matching fallback)
|
|
311
321
|
2. Symbol replace: Provide symbol + new_string to replace an entire function/class/method by name
|
|
312
322
|
3. Symbol insert: Provide symbol + new_string + position to insert code before/after a symbol
|
|
313
|
-
4. Line-targeted edit: Provide start_line + new_string to
|
|
323
|
+
4. Line-targeted edit: Provide start_line + new_string to replace/update, insert, or delete lines by line number (from extract/search output)
|
|
324
|
+
|
|
325
|
+
${lineTargetedModeGuidance}
|
|
314
326
|
|
|
315
327
|
Parameters:
|
|
316
328
|
- file_path: Path to the file to edit (absolute or relative)
|
|
317
|
-
- new_string: Replacement text or new code content
|
|
329
|
+
- new_string: Replacement text or new code content. Use empty string "" to delete the targeted line range.
|
|
318
330
|
- old_string: (optional) Text to find and replace. If omitted, symbol or start_line must be provided.
|
|
319
331
|
- replace_all: (optional) Replace all occurrences (text mode only)
|
|
320
332
|
- symbol: (optional) Symbol name for AST-aware editing (e.g. "myFunction", "MyClass.myMethod")
|
|
321
|
-
- position: (optional) "before" or "after" — insert code near a symbol or line instead of replacing it
|
|
322
|
-
- start_line: (optional) Line reference (e.g. "42" or "42:ab") for line-targeted editing
|
|
323
|
-
- end_line: (optional) End of line range, inclusive (e.g. "55" or "55:cd")
|
|
333
|
+
- position: (optional) "before" or "after" — insert code near a symbol or line instead of replacing it. Omit position to replace/update.
|
|
334
|
+
- start_line: (optional) Line reference (e.g. "42" or "42:ab") for line-targeted editing. With position, this is the insertion anchor. Without position, this is the first line to replace/update/delete.
|
|
335
|
+
- end_line: (optional) End of line range, inclusive (e.g. "55" or "55:cd"). Must be >= start_line. Omit for single-line updates. Do not use inverted ranges for insertion.`,
|
|
324
336
|
|
|
325
337
|
inputSchema: {
|
|
326
338
|
type: 'object',
|
|
@@ -335,7 +347,7 @@ Parameters:
|
|
|
335
347
|
},
|
|
336
348
|
new_string: {
|
|
337
349
|
type: 'string',
|
|
338
|
-
description: 'Replacement text or new code content'
|
|
350
|
+
description: 'Replacement text or new code content. Use empty string "" to delete the targeted line range.'
|
|
339
351
|
},
|
|
340
352
|
replace_all: {
|
|
341
353
|
type: 'boolean',
|
|
@@ -349,15 +361,15 @@ Parameters:
|
|
|
349
361
|
position: {
|
|
350
362
|
type: 'string',
|
|
351
363
|
enum: ['before', 'after'],
|
|
352
|
-
description: 'Insert before/after
|
|
364
|
+
description: 'Insert before/after the target symbol or start_line anchor. Omit position to replace/update the addressed symbol or line range.'
|
|
353
365
|
},
|
|
354
366
|
start_line: {
|
|
355
367
|
type: 'string',
|
|
356
|
-
description: 'Line reference for line-targeted editing (e.g. "42" or "42:ab" with hash)'
|
|
368
|
+
description: 'Line reference for line-targeted editing (e.g. "42" or "42:ab" with hash). With position, this is the insertion anchor. Without position, this is the first line to replace/update/delete.'
|
|
357
369
|
},
|
|
358
370
|
end_line: {
|
|
359
371
|
type: 'string',
|
|
360
|
-
description: '
|
|
372
|
+
description: 'Inclusive end of the line range to replace/delete (e.g. "55" or "55:cd"). Must be >= start_line. Defaults to start_line.'
|
|
361
373
|
}
|
|
362
374
|
},
|
|
363
375
|
required: ['file_path', 'new_string']
|
|
@@ -702,7 +714,7 @@ export const editSchema = {
|
|
|
702
714
|
},
|
|
703
715
|
new_string: {
|
|
704
716
|
type: 'string',
|
|
705
|
-
description: 'Replacement text or new code content'
|
|
717
|
+
description: 'Replacement text or new code content. Use empty string "" to delete the targeted line range.'
|
|
706
718
|
},
|
|
707
719
|
replace_all: {
|
|
708
720
|
type: 'boolean',
|
|
@@ -715,15 +727,15 @@ export const editSchema = {
|
|
|
715
727
|
position: {
|
|
716
728
|
type: 'string',
|
|
717
729
|
enum: ['before', 'after'],
|
|
718
|
-
description: 'Insert before/after
|
|
730
|
+
description: 'Insert before/after the target symbol or start_line anchor. Omit position to replace/update the addressed symbol or line range.'
|
|
719
731
|
},
|
|
720
732
|
start_line: {
|
|
721
733
|
type: 'string',
|
|
722
|
-
description: 'Line reference for line-targeted editing (e.g. "42" or "42:ab" with hash)'
|
|
734
|
+
description: 'Line reference for line-targeted editing (e.g. "42" or "42:ab" with hash). With position, this is the insertion anchor. Without position, this is the first line to replace/update/delete.'
|
|
723
735
|
},
|
|
724
736
|
end_line: {
|
|
725
737
|
type: 'string',
|
|
726
|
-
description: '
|
|
738
|
+
description: 'Inclusive end of the line range to replace/delete (e.g. "55" or "55:cd"). Must be >= start_line. Defaults to start_line.'
|
|
727
739
|
}
|
|
728
740
|
},
|
|
729
741
|
required: ['file_path', 'new_string']
|
|
@@ -760,7 +772,7 @@ export const multiEditSchema = {
|
|
|
760
772
|
};
|
|
761
773
|
|
|
762
774
|
// Tool descriptions for XML definitions
|
|
763
|
-
export const editDescription = 'Edit files using text replacement, AST-aware symbol operations, or line-targeted
|
|
775
|
+
export const editDescription = 'Edit files using text replacement, AST-aware symbol operations, or line-targeted replacement/insertion/deletion. Supports fuzzy matching for text edits and optional hash-based integrity verification for line edits.';
|
|
764
776
|
export const createDescription = 'Create new files with specified content. Will create parent directories if needed.';
|
|
765
777
|
export const multiEditDescription = 'Apply multiple file edits in a single tool call. Accepts a JSON array of edit operations, each supporting the same modes as the edit tool.';
|
|
766
778
|
|
|
@@ -779,15 +791,21 @@ Four editing modes — choose based on the scope of your change:
|
|
|
779
791
|
|
|
780
792
|
4. **Line-targeted edit** (start_line + new_string): For precise edits using line numbers from extract/search output. Use start_line with a line number (e.g. "42") or line:hash (e.g. "42:ab") for integrity verification. Add end_line for multi-line ranges. Use position="before" or "after" to insert instead of replace.
|
|
781
793
|
|
|
794
|
+
How line-targeted mode behaves:
|
|
795
|
+
- Replace/update lines: provide start_line and optionally end_line, and omit position
|
|
796
|
+
- Insert near a line: provide start_line and set position to "before" or "after"
|
|
797
|
+
- Delete lines: provide start_line/end_line for the exact range and set new_string to empty string ""
|
|
798
|
+
- Inverted ranges are invalid: end_line must be >= start_line and is never treated as insertion
|
|
799
|
+
|
|
782
800
|
Parameters:
|
|
783
801
|
- file_path: (required) Path to the file to edit
|
|
784
|
-
- new_string: (required) Replacement text or new code content
|
|
802
|
+
- new_string: (required) Replacement text or new code content. Use empty string "" to delete the targeted line range.
|
|
785
803
|
- old_string: (optional) Text to find and replace — copy verbatim from the file, do not paraphrase or reformat
|
|
786
804
|
- replace_all: (optional, default: false) Replace all occurrences of old_string (text mode only)
|
|
787
805
|
- symbol: (optional) Name of a code symbol (e.g. "myFunction", "MyClass.myMethod") — must match a function, class, or method definition
|
|
788
|
-
- position: (optional) "before" or "after" — insert new_string near the symbol or line instead of replacing it
|
|
789
|
-
- start_line: (optional) Line reference for line-targeted editing (e.g. "42" or "42:ab")
|
|
790
|
-
- end_line: (optional) End of line range, inclusive (e.g. "55" or "55:cd"). Defaults to start_line.
|
|
806
|
+
- position: (optional) "before" or "after" — insert new_string near the symbol or line instead of replacing it. Omit position to replace/update.
|
|
807
|
+
- start_line: (optional) Line reference for line-targeted editing (e.g. "42" or "42:ab"). With position, this is the insertion anchor. Without position, this is the first line to replace/update/delete.
|
|
808
|
+
- end_line: (optional) End of line range, inclusive (e.g. "55" or "55:cd"). Defaults to start_line. Must be >= start_line. Use it for replace/update/delete ranges, not insertion.
|
|
791
809
|
|
|
792
810
|
Mode selection rules (priority order):
|
|
793
811
|
- If symbol is provided, symbol mode is used (old_string and start_line are ignored)
|
|
@@ -799,12 +817,15 @@ When to use each mode:
|
|
|
799
817
|
- Small edits (a line or a few lines): use text mode with old_string
|
|
800
818
|
- Replacing entire functions/classes/methods: use symbol mode — no exact text matching needed
|
|
801
819
|
- Editing specific lines from extract/search output: use line-targeted mode with start_line
|
|
820
|
+
- Adding a new block near an existing line: use line-targeted mode with start_line plus position="before" or position="after"
|
|
821
|
+
- Removing lines entirely: use line-targeted mode with start_line/end_line and new_string=""
|
|
802
822
|
- Editing inside large functions without rewriting them entirely: first use extract with the symbol target (e.g. "file.js#myFunction") to see the function with line numbers, then use start_line/end_line to edit specific lines within it
|
|
803
823
|
|
|
804
824
|
Error handling:
|
|
805
825
|
- If an edit fails, read the error message carefully — it contains specific instructions for how to fix the call and retry
|
|
806
826
|
- Common fixes: use 'search'/'extract' to get exact file content, add more context to old_string, switch between text and symbol modes
|
|
807
827
|
- Line-targeted hash mismatch: the file changed since last read; the error provides updated line:hash references
|
|
828
|
+
- Inverted line ranges are invalid; the error explains how to express insertion with position="before"/"after"
|
|
808
829
|
|
|
809
830
|
Examples:
|
|
810
831
|
|
|
@@ -858,6 +879,22 @@ Line-targeted edit (replace a range of lines):
|
|
|
858
879
|
return processItems(order.items);</new_string>
|
|
859
880
|
</edit>
|
|
860
881
|
|
|
882
|
+
Line-targeted edit (insert before a line without replacing it):
|
|
883
|
+
<edit>
|
|
884
|
+
<file_path>src/main.js</file_path>
|
|
885
|
+
<start_line>42</start_line>
|
|
886
|
+
<position>before</position>
|
|
887
|
+
<new_string> logger.debug("starting process");</new_string>
|
|
888
|
+
</edit>
|
|
889
|
+
|
|
890
|
+
Line-targeted edit (delete a range of lines):
|
|
891
|
+
<edit>
|
|
892
|
+
<file_path>src/main.js</file_path>
|
|
893
|
+
<start_line>42</start_line>
|
|
894
|
+
<end_line>45</end_line>
|
|
895
|
+
<new_string></new_string>
|
|
896
|
+
</edit>
|
|
897
|
+
|
|
861
898
|
Line-targeted edit with hash verification:
|
|
862
899
|
<edit>
|
|
863
900
|
<file_path>src/main.js</file_path>
|
package/cjs/agent/ProbeAgent.cjs
CHANGED
|
@@ -31560,10 +31560,11 @@ async function handleLineEdit({ resolvedPath, file_path, start_line, end_line, n
|
|
|
31560
31560
|
const startLine = startRef.line;
|
|
31561
31561
|
const endLine = endRef ? endRef.line : startLine;
|
|
31562
31562
|
if (endLine < startLine) {
|
|
31563
|
-
|
|
31563
|
+
const insertionHint = endLine === startLine - 1 ? ` This looks like an insertion between lines ${endLine} and ${startLine}. To insert there without replacing existing code, use start_line="${startLine}" with position="before" or start_line="${endLine}" with position="after".` : ' To insert new code, choose a single anchor line in start_line and set position to "before" or "after" instead of using an inverted range.';
|
|
31564
|
+
return `Error editing file: end_line (${endLine}) must be >= start_line (${startLine}). Omitting position means replace/update the addressed lines, not insert.${insertionHint} To delete lines, use new_string as the empty string "" with a valid non-inverted range.`;
|
|
31564
31565
|
}
|
|
31565
31566
|
if (position !== void 0 && position !== null && position !== "before" && position !== "after") {
|
|
31566
|
-
return 'Error editing file: Invalid position - must be "before" or "after". Use position="before" to insert before
|
|
31567
|
+
return 'Error editing file: Invalid position - must be "before" or "after". Use position="before" to insert before start_line, position="after" to insert after start_line, or omit position to replace/update the addressed lines.';
|
|
31567
31568
|
}
|
|
31568
31569
|
const content = await import_fs7.promises.readFile(resolvedPath, "utf-8");
|
|
31569
31570
|
const fileLines = content.split("\n");
|
|
@@ -31620,7 +31621,7 @@ async function handleLineEdit({ resolvedPath, file_path, start_line, end_line, n
|
|
|
31620
31621
|
return buildLineEditResponse(file_path, startLine, endLine, newLines.length, fileLines, startLine - 1, action, modifications);
|
|
31621
31622
|
}
|
|
31622
31623
|
}
|
|
31623
|
-
var import_ai3, import_fs7, import_path9, import_fs8, editTool, createTool, multiEditTool, editSchema, createSchema, multiEditSchema, editDescription, createDescription, multiEditDescription, editToolDefinition, createToolDefinition, multiEditToolDefinition;
|
|
31624
|
+
var import_ai3, import_fs7, import_path9, import_fs8, lineTargetedModeGuidance, editTool, createTool, multiEditTool, editSchema, createSchema, multiEditSchema, editDescription, createDescription, multiEditDescription, editToolDefinition, createToolDefinition, multiEditToolDefinition;
|
|
31624
31625
|
var init_edit = __esm({
|
|
31625
31626
|
"src/tools/edit.js"() {
|
|
31626
31627
|
"use strict";
|
|
@@ -31633,27 +31634,35 @@ var init_edit = __esm({
|
|
|
31633
31634
|
init_symbolEdit();
|
|
31634
31635
|
init_hashline();
|
|
31635
31636
|
init_lineEditHeuristics();
|
|
31637
|
+
lineTargetedModeGuidance = `Line-targeted mode has three explicit behaviors:
|
|
31638
|
+
- Replace/update lines: provide start_line and optionally end_line, and omit position
|
|
31639
|
+
- Insert near a line: provide start_line and set position to "before" or "after"
|
|
31640
|
+
- Delete lines: provide start_line/end_line for the exact range and set new_string to empty string ""
|
|
31641
|
+
|
|
31642
|
+
Inverted ranges (end_line < start_line) are always invalid and are never treated as insertion.`;
|
|
31636
31643
|
editTool = (options = {}) => {
|
|
31637
31644
|
const { debug, allowedFolders, cwd, workspaceRoot } = parseFileToolOptions(options);
|
|
31638
31645
|
return (0, import_ai3.tool)({
|
|
31639
31646
|
name: "edit",
|
|
31640
|
-
description: `Edit files using text replacement, AST-aware symbol operations, or line-targeted
|
|
31647
|
+
description: `Edit files using text replacement, AST-aware symbol operations, or line-targeted line replacement/insertion/deletion.
|
|
31641
31648
|
|
|
31642
31649
|
Modes:
|
|
31643
31650
|
1. Text edit: Provide old_string + new_string to find and replace text (with fuzzy matching fallback)
|
|
31644
31651
|
2. Symbol replace: Provide symbol + new_string to replace an entire function/class/method by name
|
|
31645
31652
|
3. Symbol insert: Provide symbol + new_string + position to insert code before/after a symbol
|
|
31646
|
-
4. Line-targeted edit: Provide start_line + new_string to
|
|
31653
|
+
4. Line-targeted edit: Provide start_line + new_string to replace/update, insert, or delete lines by line number (from extract/search output)
|
|
31654
|
+
|
|
31655
|
+
${lineTargetedModeGuidance}
|
|
31647
31656
|
|
|
31648
31657
|
Parameters:
|
|
31649
31658
|
- file_path: Path to the file to edit (absolute or relative)
|
|
31650
|
-
- new_string: Replacement text or new code content
|
|
31659
|
+
- new_string: Replacement text or new code content. Use empty string "" to delete the targeted line range.
|
|
31651
31660
|
- old_string: (optional) Text to find and replace. If omitted, symbol or start_line must be provided.
|
|
31652
31661
|
- replace_all: (optional) Replace all occurrences (text mode only)
|
|
31653
31662
|
- symbol: (optional) Symbol name for AST-aware editing (e.g. "myFunction", "MyClass.myMethod")
|
|
31654
|
-
- position: (optional) "before" or "after" \u2014 insert code near a symbol or line instead of replacing it
|
|
31655
|
-
- start_line: (optional) Line reference (e.g. "42" or "42:ab") for line-targeted editing
|
|
31656
|
-
- end_line: (optional) End of line range, inclusive (e.g. "55" or "55:cd")
|
|
31663
|
+
- position: (optional) "before" or "after" \u2014 insert code near a symbol or line instead of replacing it. Omit position to replace/update.
|
|
31664
|
+
- start_line: (optional) Line reference (e.g. "42" or "42:ab") for line-targeted editing. With position, this is the insertion anchor. Without position, this is the first line to replace/update/delete.
|
|
31665
|
+
- end_line: (optional) End of line range, inclusive (e.g. "55" or "55:cd"). Must be >= start_line. Omit for single-line updates. Do not use inverted ranges for insertion.`,
|
|
31657
31666
|
inputSchema: {
|
|
31658
31667
|
type: "object",
|
|
31659
31668
|
properties: {
|
|
@@ -31667,7 +31676,7 @@ Parameters:
|
|
|
31667
31676
|
},
|
|
31668
31677
|
new_string: {
|
|
31669
31678
|
type: "string",
|
|
31670
|
-
description:
|
|
31679
|
+
description: 'Replacement text or new code content. Use empty string "" to delete the targeted line range.'
|
|
31671
31680
|
},
|
|
31672
31681
|
replace_all: {
|
|
31673
31682
|
type: "boolean",
|
|
@@ -31681,15 +31690,15 @@ Parameters:
|
|
|
31681
31690
|
position: {
|
|
31682
31691
|
type: "string",
|
|
31683
31692
|
enum: ["before", "after"],
|
|
31684
|
-
description: "Insert before/after
|
|
31693
|
+
description: "Insert before/after the target symbol or start_line anchor. Omit position to replace/update the addressed symbol or line range."
|
|
31685
31694
|
},
|
|
31686
31695
|
start_line: {
|
|
31687
31696
|
type: "string",
|
|
31688
|
-
description: 'Line reference for line-targeted editing (e.g. "42" or "42:ab" with hash)'
|
|
31697
|
+
description: 'Line reference for line-targeted editing (e.g. "42" or "42:ab" with hash). With position, this is the insertion anchor. Without position, this is the first line to replace/update/delete.'
|
|
31689
31698
|
},
|
|
31690
31699
|
end_line: {
|
|
31691
31700
|
type: "string",
|
|
31692
|
-
description: '
|
|
31701
|
+
description: 'Inclusive end of the line range to replace/delete (e.g. "55" or "55:cd"). Must be >= start_line. Defaults to start_line.'
|
|
31693
31702
|
}
|
|
31694
31703
|
},
|
|
31695
31704
|
required: ["file_path", "new_string"]
|
|
@@ -31940,7 +31949,7 @@ Important:
|
|
|
31940
31949
|
},
|
|
31941
31950
|
new_string: {
|
|
31942
31951
|
type: "string",
|
|
31943
|
-
description:
|
|
31952
|
+
description: 'Replacement text or new code content. Use empty string "" to delete the targeted line range.'
|
|
31944
31953
|
},
|
|
31945
31954
|
replace_all: {
|
|
31946
31955
|
type: "boolean",
|
|
@@ -31953,15 +31962,15 @@ Important:
|
|
|
31953
31962
|
position: {
|
|
31954
31963
|
type: "string",
|
|
31955
31964
|
enum: ["before", "after"],
|
|
31956
|
-
description: "Insert before/after
|
|
31965
|
+
description: "Insert before/after the target symbol or start_line anchor. Omit position to replace/update the addressed symbol or line range."
|
|
31957
31966
|
},
|
|
31958
31967
|
start_line: {
|
|
31959
31968
|
type: "string",
|
|
31960
|
-
description: 'Line reference for line-targeted editing (e.g. "42" or "42:ab" with hash)'
|
|
31969
|
+
description: 'Line reference for line-targeted editing (e.g. "42" or "42:ab" with hash). With position, this is the insertion anchor. Without position, this is the first line to replace/update/delete.'
|
|
31961
31970
|
},
|
|
31962
31971
|
end_line: {
|
|
31963
31972
|
type: "string",
|
|
31964
|
-
description: '
|
|
31973
|
+
description: 'Inclusive end of the line range to replace/delete (e.g. "55" or "55:cd"). Must be >= start_line. Defaults to start_line.'
|
|
31965
31974
|
}
|
|
31966
31975
|
},
|
|
31967
31976
|
required: ["file_path", "new_string"]
|
|
@@ -31994,7 +32003,7 @@ Important:
|
|
|
31994
32003
|
},
|
|
31995
32004
|
required: ["edits"]
|
|
31996
32005
|
};
|
|
31997
|
-
editDescription = "Edit files using text replacement, AST-aware symbol operations, or line-targeted
|
|
32006
|
+
editDescription = "Edit files using text replacement, AST-aware symbol operations, or line-targeted replacement/insertion/deletion. Supports fuzzy matching for text edits and optional hash-based integrity verification for line edits.";
|
|
31998
32007
|
createDescription = "Create new files with specified content. Will create parent directories if needed.";
|
|
31999
32008
|
multiEditDescription = "Apply multiple file edits in a single tool call. Accepts a JSON array of edit operations, each supporting the same modes as the edit tool.";
|
|
32000
32009
|
editToolDefinition = `
|
|
@@ -32011,15 +32020,21 @@ Four editing modes \u2014 choose based on the scope of your change:
|
|
|
32011
32020
|
|
|
32012
32021
|
4. **Line-targeted edit** (start_line + new_string): For precise edits using line numbers from extract/search output. Use start_line with a line number (e.g. "42") or line:hash (e.g. "42:ab") for integrity verification. Add end_line for multi-line ranges. Use position="before" or "after" to insert instead of replace.
|
|
32013
32022
|
|
|
32023
|
+
How line-targeted mode behaves:
|
|
32024
|
+
- Replace/update lines: provide start_line and optionally end_line, and omit position
|
|
32025
|
+
- Insert near a line: provide start_line and set position to "before" or "after"
|
|
32026
|
+
- Delete lines: provide start_line/end_line for the exact range and set new_string to empty string ""
|
|
32027
|
+
- Inverted ranges are invalid: end_line must be >= start_line and is never treated as insertion
|
|
32028
|
+
|
|
32014
32029
|
Parameters:
|
|
32015
32030
|
- file_path: (required) Path to the file to edit
|
|
32016
|
-
- new_string: (required) Replacement text or new code content
|
|
32031
|
+
- new_string: (required) Replacement text or new code content. Use empty string "" to delete the targeted line range.
|
|
32017
32032
|
- old_string: (optional) Text to find and replace \u2014 copy verbatim from the file, do not paraphrase or reformat
|
|
32018
32033
|
- replace_all: (optional, default: false) Replace all occurrences of old_string (text mode only)
|
|
32019
32034
|
- symbol: (optional) Name of a code symbol (e.g. "myFunction", "MyClass.myMethod") \u2014 must match a function, class, or method definition
|
|
32020
|
-
- position: (optional) "before" or "after" \u2014 insert new_string near the symbol or line instead of replacing it
|
|
32021
|
-
- start_line: (optional) Line reference for line-targeted editing (e.g. "42" or "42:ab")
|
|
32022
|
-
- end_line: (optional) End of line range, inclusive (e.g. "55" or "55:cd"). Defaults to start_line.
|
|
32035
|
+
- position: (optional) "before" or "after" \u2014 insert new_string near the symbol or line instead of replacing it. Omit position to replace/update.
|
|
32036
|
+
- start_line: (optional) Line reference for line-targeted editing (e.g. "42" or "42:ab"). With position, this is the insertion anchor. Without position, this is the first line to replace/update/delete.
|
|
32037
|
+
- end_line: (optional) End of line range, inclusive (e.g. "55" or "55:cd"). Defaults to start_line. Must be >= start_line. Use it for replace/update/delete ranges, not insertion.
|
|
32023
32038
|
|
|
32024
32039
|
Mode selection rules (priority order):
|
|
32025
32040
|
- If symbol is provided, symbol mode is used (old_string and start_line are ignored)
|
|
@@ -32031,12 +32046,15 @@ When to use each mode:
|
|
|
32031
32046
|
- Small edits (a line or a few lines): use text mode with old_string
|
|
32032
32047
|
- Replacing entire functions/classes/methods: use symbol mode \u2014 no exact text matching needed
|
|
32033
32048
|
- Editing specific lines from extract/search output: use line-targeted mode with start_line
|
|
32049
|
+
- Adding a new block near an existing line: use line-targeted mode with start_line plus position="before" or position="after"
|
|
32050
|
+
- Removing lines entirely: use line-targeted mode with start_line/end_line and new_string=""
|
|
32034
32051
|
- Editing inside large functions without rewriting them entirely: first use extract with the symbol target (e.g. "file.js#myFunction") to see the function with line numbers, then use start_line/end_line to edit specific lines within it
|
|
32035
32052
|
|
|
32036
32053
|
Error handling:
|
|
32037
32054
|
- If an edit fails, read the error message carefully \u2014 it contains specific instructions for how to fix the call and retry
|
|
32038
32055
|
- Common fixes: use 'search'/'extract' to get exact file content, add more context to old_string, switch between text and symbol modes
|
|
32039
32056
|
- Line-targeted hash mismatch: the file changed since last read; the error provides updated line:hash references
|
|
32057
|
+
- Inverted line ranges are invalid; the error explains how to express insertion with position="before"/"after"
|
|
32040
32058
|
|
|
32041
32059
|
Examples:
|
|
32042
32060
|
|
|
@@ -32090,6 +32108,22 @@ Line-targeted edit (replace a range of lines):
|
|
|
32090
32108
|
return processItems(order.items);</new_string>
|
|
32091
32109
|
</edit>
|
|
32092
32110
|
|
|
32111
|
+
Line-targeted edit (insert before a line without replacing it):
|
|
32112
|
+
<edit>
|
|
32113
|
+
<file_path>src/main.js</file_path>
|
|
32114
|
+
<start_line>42</start_line>
|
|
32115
|
+
<position>before</position>
|
|
32116
|
+
<new_string> logger.debug("starting process");</new_string>
|
|
32117
|
+
</edit>
|
|
32118
|
+
|
|
32119
|
+
Line-targeted edit (delete a range of lines):
|
|
32120
|
+
<edit>
|
|
32121
|
+
<file_path>src/main.js</file_path>
|
|
32122
|
+
<start_line>42</start_line>
|
|
32123
|
+
<end_line>45</end_line>
|
|
32124
|
+
<new_string></new_string>
|
|
32125
|
+
</edit>
|
|
32126
|
+
|
|
32093
32127
|
Line-targeted edit with hash verification:
|
|
32094
32128
|
<edit>
|
|
32095
32129
|
<file_path>src/main.js</file_path>
|
|
@@ -89942,6 +89976,8 @@ Bash is fine for: formatters (gofmt, prettier, black), build/test/lint commands,
|
|
|
89942
89976
|
- Never expose secrets, API keys, or credentials in generated code. Never log sensitive information.
|
|
89943
89977
|
- Do not surprise the user with unrequested changes. Do what was asked, including reasonable follow-up actions, but do not refactor surrounding code or add features that were not requested.
|
|
89944
89978
|
- When editing files, keep edits focused and minimal. For changes spanning more than a few lines, prefer line-targeted editing (start_line/end_line) over text replacement (old_string) \u2014 it constrains scope and prevents accidental removal of adjacent content. Never include unrelated sections in an edit operation.
|
|
89979
|
+
- In line-targeted mode, omitting position means replace/update the addressed lines. To insert code near an existing line, you MUST use position="before" or position="after". Never express insertion as end_line < start_line.
|
|
89980
|
+
- To remove lines with line-targeted mode, target the exact start_line/end_line range and set new_string to the empty string "".
|
|
89945
89981
|
- After every significant change, verify the project still builds and passes linting. Do not wait until the end to discover breakage.
|
|
89946
89982
|
|
|
89947
89983
|
# Writing Tests
|
|
@@ -103538,6 +103574,8 @@ Follow these instructions carefully:
|
|
|
103538
103574
|
7. When modifying files, choose the appropriate tool:
|
|
103539
103575
|
- Use 'edit' for all code modifications:
|
|
103540
103576
|
* PREFERRED: Use start_line (and optionally end_line) for line-targeted editing \u2014 this is the safest and most precise approach.${this.hashLines ? ' Use the line:hash references from extract/search output (e.g. "42:ab") for integrity verification.' : ""} Always use extract first to see line numbers${this.hashLines ? " and hashes" : ""}, then edit by line reference.
|
|
103577
|
+
* In line-targeted mode, omitting position means replace/update the addressed lines. To insert new code near a line, you MUST set position="before" or position="after". Never express insertion as end_line < start_line.
|
|
103578
|
+
* To delete lines in line-targeted mode, target the exact start_line/end_line range and set new_string to the empty string "".
|
|
103541
103579
|
* For editing inside large functions: first use extract with the symbol target (e.g. "file.js#myFunction") to see the function with line numbers${this.hashLines ? " and hashes" : ""}, then use start_line/end_line to surgically edit specific lines within it.
|
|
103542
103580
|
* For rewriting entire functions/classes/methods, use the symbol parameter instead (no exact text matching needed).
|
|
103543
103581
|
* FALLBACK ONLY: Use old_string + new_string for simple single-line changes where the text is unique. Copy old_string verbatim from the file. Keep old_string as small as possible.
|
package/cjs/index.cjs
CHANGED
|
@@ -74139,6 +74139,8 @@ Bash is fine for: formatters (gofmt, prettier, black), build/test/lint commands,
|
|
|
74139
74139
|
- Never expose secrets, API keys, or credentials in generated code. Never log sensitive information.
|
|
74140
74140
|
- Do not surprise the user with unrequested changes. Do what was asked, including reasonable follow-up actions, but do not refactor surrounding code or add features that were not requested.
|
|
74141
74141
|
- When editing files, keep edits focused and minimal. For changes spanning more than a few lines, prefer line-targeted editing (start_line/end_line) over text replacement (old_string) \u2014 it constrains scope and prevents accidental removal of adjacent content. Never include unrelated sections in an edit operation.
|
|
74142
|
+
- In line-targeted mode, omitting position means replace/update the addressed lines. To insert code near an existing line, you MUST use position="before" or position="after". Never express insertion as end_line < start_line.
|
|
74143
|
+
- To remove lines with line-targeted mode, target the exact start_line/end_line range and set new_string to the empty string "".
|
|
74142
74144
|
- After every significant change, verify the project still builds and passes linting. Do not wait until the end to discover breakage.
|
|
74143
74145
|
|
|
74144
74146
|
# Writing Tests
|
|
@@ -100082,6 +100084,8 @@ Follow these instructions carefully:
|
|
|
100082
100084
|
7. When modifying files, choose the appropriate tool:
|
|
100083
100085
|
- Use 'edit' for all code modifications:
|
|
100084
100086
|
* PREFERRED: Use start_line (and optionally end_line) for line-targeted editing \u2014 this is the safest and most precise approach.${this.hashLines ? ' Use the line:hash references from extract/search output (e.g. "42:ab") for integrity verification.' : ""} Always use extract first to see line numbers${this.hashLines ? " and hashes" : ""}, then edit by line reference.
|
|
100087
|
+
* In line-targeted mode, omitting position means replace/update the addressed lines. To insert new code near a line, you MUST set position="before" or position="after". Never express insertion as end_line < start_line.
|
|
100088
|
+
* To delete lines in line-targeted mode, target the exact start_line/end_line range and set new_string to the empty string "".
|
|
100085
100089
|
* For editing inside large functions: first use extract with the symbol target (e.g. "file.js#myFunction") to see the function with line numbers${this.hashLines ? " and hashes" : ""}, then use start_line/end_line to surgically edit specific lines within it.
|
|
100086
100090
|
* For rewriting entire functions/classes/methods, use the symbol parameter instead (no exact text matching needed).
|
|
100087
100091
|
* FALLBACK ONLY: Use old_string + new_string for simple single-line changes where the text is unique. Copy old_string verbatim from the file. Keep old_string as small as possible.
|
|
@@ -104614,10 +104618,11 @@ async function handleLineEdit({ resolvedPath, file_path, start_line, end_line, n
|
|
|
104614
104618
|
const startLine = startRef.line;
|
|
104615
104619
|
const endLine = endRef ? endRef.line : startLine;
|
|
104616
104620
|
if (endLine < startLine) {
|
|
104617
|
-
|
|
104621
|
+
const insertionHint = endLine === startLine - 1 ? ` This looks like an insertion between lines ${endLine} and ${startLine}. To insert there without replacing existing code, use start_line="${startLine}" with position="before" or start_line="${endLine}" with position="after".` : ' To insert new code, choose a single anchor line in start_line and set position to "before" or "after" instead of using an inverted range.';
|
|
104622
|
+
return `Error editing file: end_line (${endLine}) must be >= start_line (${startLine}). Omitting position means replace/update the addressed lines, not insert.${insertionHint} To delete lines, use new_string as the empty string "" with a valid non-inverted range.`;
|
|
104618
104623
|
}
|
|
104619
104624
|
if (position !== void 0 && position !== null && position !== "before" && position !== "after") {
|
|
104620
|
-
return 'Error editing file: Invalid position - must be "before" or "after". Use position="before" to insert before
|
|
104625
|
+
return 'Error editing file: Invalid position - must be "before" or "after". Use position="before" to insert before start_line, position="after" to insert after start_line, or omit position to replace/update the addressed lines.';
|
|
104621
104626
|
}
|
|
104622
104627
|
const content = await import_fs13.promises.readFile(resolvedPath, "utf-8");
|
|
104623
104628
|
const fileLines = content.split("\n");
|
|
@@ -104674,7 +104679,7 @@ async function handleLineEdit({ resolvedPath, file_path, start_line, end_line, n
|
|
|
104674
104679
|
return buildLineEditResponse(file_path, startLine, endLine, newLines.length, fileLines, startLine - 1, action, modifications);
|
|
104675
104680
|
}
|
|
104676
104681
|
}
|
|
104677
|
-
var import_ai6, import_fs13, import_path17, import_fs14, editTool, createTool, multiEditTool, editSchema, createSchema, multiEditSchema, editDescription, createDescription, multiEditDescription, editToolDefinition, createToolDefinition, multiEditToolDefinition;
|
|
104682
|
+
var import_ai6, import_fs13, import_path17, import_fs14, lineTargetedModeGuidance, editTool, createTool, multiEditTool, editSchema, createSchema, multiEditSchema, editDescription, createDescription, multiEditDescription, editToolDefinition, createToolDefinition, multiEditToolDefinition;
|
|
104678
104683
|
var init_edit = __esm({
|
|
104679
104684
|
"src/tools/edit.js"() {
|
|
104680
104685
|
"use strict";
|
|
@@ -104687,27 +104692,35 @@ var init_edit = __esm({
|
|
|
104687
104692
|
init_symbolEdit();
|
|
104688
104693
|
init_hashline();
|
|
104689
104694
|
init_lineEditHeuristics();
|
|
104695
|
+
lineTargetedModeGuidance = `Line-targeted mode has three explicit behaviors:
|
|
104696
|
+
- Replace/update lines: provide start_line and optionally end_line, and omit position
|
|
104697
|
+
- Insert near a line: provide start_line and set position to "before" or "after"
|
|
104698
|
+
- Delete lines: provide start_line/end_line for the exact range and set new_string to empty string ""
|
|
104699
|
+
|
|
104700
|
+
Inverted ranges (end_line < start_line) are always invalid and are never treated as insertion.`;
|
|
104690
104701
|
editTool = (options = {}) => {
|
|
104691
104702
|
const { debug, allowedFolders, cwd, workspaceRoot } = parseFileToolOptions(options);
|
|
104692
104703
|
return (0, import_ai6.tool)({
|
|
104693
104704
|
name: "edit",
|
|
104694
|
-
description: `Edit files using text replacement, AST-aware symbol operations, or line-targeted
|
|
104705
|
+
description: `Edit files using text replacement, AST-aware symbol operations, or line-targeted line replacement/insertion/deletion.
|
|
104695
104706
|
|
|
104696
104707
|
Modes:
|
|
104697
104708
|
1. Text edit: Provide old_string + new_string to find and replace text (with fuzzy matching fallback)
|
|
104698
104709
|
2. Symbol replace: Provide symbol + new_string to replace an entire function/class/method by name
|
|
104699
104710
|
3. Symbol insert: Provide symbol + new_string + position to insert code before/after a symbol
|
|
104700
|
-
4. Line-targeted edit: Provide start_line + new_string to
|
|
104711
|
+
4. Line-targeted edit: Provide start_line + new_string to replace/update, insert, or delete lines by line number (from extract/search output)
|
|
104712
|
+
|
|
104713
|
+
${lineTargetedModeGuidance}
|
|
104701
104714
|
|
|
104702
104715
|
Parameters:
|
|
104703
104716
|
- file_path: Path to the file to edit (absolute or relative)
|
|
104704
|
-
- new_string: Replacement text or new code content
|
|
104717
|
+
- new_string: Replacement text or new code content. Use empty string "" to delete the targeted line range.
|
|
104705
104718
|
- old_string: (optional) Text to find and replace. If omitted, symbol or start_line must be provided.
|
|
104706
104719
|
- replace_all: (optional) Replace all occurrences (text mode only)
|
|
104707
104720
|
- symbol: (optional) Symbol name for AST-aware editing (e.g. "myFunction", "MyClass.myMethod")
|
|
104708
|
-
- position: (optional) "before" or "after" \u2014 insert code near a symbol or line instead of replacing it
|
|
104709
|
-
- start_line: (optional) Line reference (e.g. "42" or "42:ab") for line-targeted editing
|
|
104710
|
-
- end_line: (optional) End of line range, inclusive (e.g. "55" or "55:cd")
|
|
104721
|
+
- position: (optional) "before" or "after" \u2014 insert code near a symbol or line instead of replacing it. Omit position to replace/update.
|
|
104722
|
+
- start_line: (optional) Line reference (e.g. "42" or "42:ab") for line-targeted editing. With position, this is the insertion anchor. Without position, this is the first line to replace/update/delete.
|
|
104723
|
+
- end_line: (optional) End of line range, inclusive (e.g. "55" or "55:cd"). Must be >= start_line. Omit for single-line updates. Do not use inverted ranges for insertion.`,
|
|
104711
104724
|
inputSchema: {
|
|
104712
104725
|
type: "object",
|
|
104713
104726
|
properties: {
|
|
@@ -104721,7 +104734,7 @@ Parameters:
|
|
|
104721
104734
|
},
|
|
104722
104735
|
new_string: {
|
|
104723
104736
|
type: "string",
|
|
104724
|
-
description:
|
|
104737
|
+
description: 'Replacement text or new code content. Use empty string "" to delete the targeted line range.'
|
|
104725
104738
|
},
|
|
104726
104739
|
replace_all: {
|
|
104727
104740
|
type: "boolean",
|
|
@@ -104735,15 +104748,15 @@ Parameters:
|
|
|
104735
104748
|
position: {
|
|
104736
104749
|
type: "string",
|
|
104737
104750
|
enum: ["before", "after"],
|
|
104738
|
-
description: "Insert before/after
|
|
104751
|
+
description: "Insert before/after the target symbol or start_line anchor. Omit position to replace/update the addressed symbol or line range."
|
|
104739
104752
|
},
|
|
104740
104753
|
start_line: {
|
|
104741
104754
|
type: "string",
|
|
104742
|
-
description: 'Line reference for line-targeted editing (e.g. "42" or "42:ab" with hash)'
|
|
104755
|
+
description: 'Line reference for line-targeted editing (e.g. "42" or "42:ab" with hash). With position, this is the insertion anchor. Without position, this is the first line to replace/update/delete.'
|
|
104743
104756
|
},
|
|
104744
104757
|
end_line: {
|
|
104745
104758
|
type: "string",
|
|
104746
|
-
description: '
|
|
104759
|
+
description: 'Inclusive end of the line range to replace/delete (e.g. "55" or "55:cd"). Must be >= start_line. Defaults to start_line.'
|
|
104747
104760
|
}
|
|
104748
104761
|
},
|
|
104749
104762
|
required: ["file_path", "new_string"]
|
|
@@ -104994,7 +105007,7 @@ Important:
|
|
|
104994
105007
|
},
|
|
104995
105008
|
new_string: {
|
|
104996
105009
|
type: "string",
|
|
104997
|
-
description:
|
|
105010
|
+
description: 'Replacement text or new code content. Use empty string "" to delete the targeted line range.'
|
|
104998
105011
|
},
|
|
104999
105012
|
replace_all: {
|
|
105000
105013
|
type: "boolean",
|
|
@@ -105007,15 +105020,15 @@ Important:
|
|
|
105007
105020
|
position: {
|
|
105008
105021
|
type: "string",
|
|
105009
105022
|
enum: ["before", "after"],
|
|
105010
|
-
description: "Insert before/after
|
|
105023
|
+
description: "Insert before/after the target symbol or start_line anchor. Omit position to replace/update the addressed symbol or line range."
|
|
105011
105024
|
},
|
|
105012
105025
|
start_line: {
|
|
105013
105026
|
type: "string",
|
|
105014
|
-
description: 'Line reference for line-targeted editing (e.g. "42" or "42:ab" with hash)'
|
|
105027
|
+
description: 'Line reference for line-targeted editing (e.g. "42" or "42:ab" with hash). With position, this is the insertion anchor. Without position, this is the first line to replace/update/delete.'
|
|
105015
105028
|
},
|
|
105016
105029
|
end_line: {
|
|
105017
105030
|
type: "string",
|
|
105018
|
-
description: '
|
|
105031
|
+
description: 'Inclusive end of the line range to replace/delete (e.g. "55" or "55:cd"). Must be >= start_line. Defaults to start_line.'
|
|
105019
105032
|
}
|
|
105020
105033
|
},
|
|
105021
105034
|
required: ["file_path", "new_string"]
|
|
@@ -105048,7 +105061,7 @@ Important:
|
|
|
105048
105061
|
},
|
|
105049
105062
|
required: ["edits"]
|
|
105050
105063
|
};
|
|
105051
|
-
editDescription = "Edit files using text replacement, AST-aware symbol operations, or line-targeted
|
|
105064
|
+
editDescription = "Edit files using text replacement, AST-aware symbol operations, or line-targeted replacement/insertion/deletion. Supports fuzzy matching for text edits and optional hash-based integrity verification for line edits.";
|
|
105052
105065
|
createDescription = "Create new files with specified content. Will create parent directories if needed.";
|
|
105053
105066
|
multiEditDescription = "Apply multiple file edits in a single tool call. Accepts a JSON array of edit operations, each supporting the same modes as the edit tool.";
|
|
105054
105067
|
editToolDefinition = `
|
|
@@ -105065,15 +105078,21 @@ Four editing modes \u2014 choose based on the scope of your change:
|
|
|
105065
105078
|
|
|
105066
105079
|
4. **Line-targeted edit** (start_line + new_string): For precise edits using line numbers from extract/search output. Use start_line with a line number (e.g. "42") or line:hash (e.g. "42:ab") for integrity verification. Add end_line for multi-line ranges. Use position="before" or "after" to insert instead of replace.
|
|
105067
105080
|
|
|
105081
|
+
How line-targeted mode behaves:
|
|
105082
|
+
- Replace/update lines: provide start_line and optionally end_line, and omit position
|
|
105083
|
+
- Insert near a line: provide start_line and set position to "before" or "after"
|
|
105084
|
+
- Delete lines: provide start_line/end_line for the exact range and set new_string to empty string ""
|
|
105085
|
+
- Inverted ranges are invalid: end_line must be >= start_line and is never treated as insertion
|
|
105086
|
+
|
|
105068
105087
|
Parameters:
|
|
105069
105088
|
- file_path: (required) Path to the file to edit
|
|
105070
|
-
- new_string: (required) Replacement text or new code content
|
|
105089
|
+
- new_string: (required) Replacement text or new code content. Use empty string "" to delete the targeted line range.
|
|
105071
105090
|
- old_string: (optional) Text to find and replace \u2014 copy verbatim from the file, do not paraphrase or reformat
|
|
105072
105091
|
- replace_all: (optional, default: false) Replace all occurrences of old_string (text mode only)
|
|
105073
105092
|
- symbol: (optional) Name of a code symbol (e.g. "myFunction", "MyClass.myMethod") \u2014 must match a function, class, or method definition
|
|
105074
|
-
- position: (optional) "before" or "after" \u2014 insert new_string near the symbol or line instead of replacing it
|
|
105075
|
-
- start_line: (optional) Line reference for line-targeted editing (e.g. "42" or "42:ab")
|
|
105076
|
-
- end_line: (optional) End of line range, inclusive (e.g. "55" or "55:cd"). Defaults to start_line.
|
|
105093
|
+
- position: (optional) "before" or "after" \u2014 insert new_string near the symbol or line instead of replacing it. Omit position to replace/update.
|
|
105094
|
+
- start_line: (optional) Line reference for line-targeted editing (e.g. "42" or "42:ab"). With position, this is the insertion anchor. Without position, this is the first line to replace/update/delete.
|
|
105095
|
+
- end_line: (optional) End of line range, inclusive (e.g. "55" or "55:cd"). Defaults to start_line. Must be >= start_line. Use it for replace/update/delete ranges, not insertion.
|
|
105077
105096
|
|
|
105078
105097
|
Mode selection rules (priority order):
|
|
105079
105098
|
- If symbol is provided, symbol mode is used (old_string and start_line are ignored)
|
|
@@ -105085,12 +105104,15 @@ When to use each mode:
|
|
|
105085
105104
|
- Small edits (a line or a few lines): use text mode with old_string
|
|
105086
105105
|
- Replacing entire functions/classes/methods: use symbol mode \u2014 no exact text matching needed
|
|
105087
105106
|
- Editing specific lines from extract/search output: use line-targeted mode with start_line
|
|
105107
|
+
- Adding a new block near an existing line: use line-targeted mode with start_line plus position="before" or position="after"
|
|
105108
|
+
- Removing lines entirely: use line-targeted mode with start_line/end_line and new_string=""
|
|
105088
105109
|
- Editing inside large functions without rewriting them entirely: first use extract with the symbol target (e.g. "file.js#myFunction") to see the function with line numbers, then use start_line/end_line to edit specific lines within it
|
|
105089
105110
|
|
|
105090
105111
|
Error handling:
|
|
105091
105112
|
- If an edit fails, read the error message carefully \u2014 it contains specific instructions for how to fix the call and retry
|
|
105092
105113
|
- Common fixes: use 'search'/'extract' to get exact file content, add more context to old_string, switch between text and symbol modes
|
|
105093
105114
|
- Line-targeted hash mismatch: the file changed since last read; the error provides updated line:hash references
|
|
105115
|
+
- Inverted line ranges are invalid; the error explains how to express insertion with position="before"/"after"
|
|
105094
105116
|
|
|
105095
105117
|
Examples:
|
|
105096
105118
|
|
|
@@ -105144,6 +105166,22 @@ Line-targeted edit (replace a range of lines):
|
|
|
105144
105166
|
return processItems(order.items);</new_string>
|
|
105145
105167
|
</edit>
|
|
105146
105168
|
|
|
105169
|
+
Line-targeted edit (insert before a line without replacing it):
|
|
105170
|
+
<edit>
|
|
105171
|
+
<file_path>src/main.js</file_path>
|
|
105172
|
+
<start_line>42</start_line>
|
|
105173
|
+
<position>before</position>
|
|
105174
|
+
<new_string> logger.debug("starting process");</new_string>
|
|
105175
|
+
</edit>
|
|
105176
|
+
|
|
105177
|
+
Line-targeted edit (delete a range of lines):
|
|
105178
|
+
<edit>
|
|
105179
|
+
<file_path>src/main.js</file_path>
|
|
105180
|
+
<start_line>42</start_line>
|
|
105181
|
+
<end_line>45</end_line>
|
|
105182
|
+
<new_string></new_string>
|
|
105183
|
+
</edit>
|
|
105184
|
+
|
|
105147
105185
|
Line-targeted edit with hash verification:
|
|
105148
105186
|
<edit>
|
|
105149
105187
|
<file_path>src/main.js</file_path>
|
package/package.json
CHANGED
package/src/agent/ProbeAgent.js
CHANGED
|
@@ -3179,6 +3179,8 @@ Follow these instructions carefully:
|
|
|
3179
3179
|
7. When modifying files, choose the appropriate tool:
|
|
3180
3180
|
- Use 'edit' for all code modifications:
|
|
3181
3181
|
* PREFERRED: Use start_line (and optionally end_line) for line-targeted editing — this is the safest and most precise approach.${this.hashLines ? ' Use the line:hash references from extract/search output (e.g. "42:ab") for integrity verification.' : ''} Always use extract first to see line numbers${this.hashLines ? ' and hashes' : ''}, then edit by line reference.
|
|
3182
|
+
* In line-targeted mode, omitting position means replace/update the addressed lines. To insert new code near a line, you MUST set position="before" or position="after". Never express insertion as end_line < start_line.
|
|
3183
|
+
* To delete lines in line-targeted mode, target the exact start_line/end_line range and set new_string to the empty string "".
|
|
3182
3184
|
* For editing inside large functions: first use extract with the symbol target (e.g. "file.js#myFunction") to see the function with line numbers${this.hashLines ? ' and hashes' : ''}, then use start_line/end_line to surgically edit specific lines within it.
|
|
3183
3185
|
* For rewriting entire functions/classes/methods, use the symbol parameter instead (no exact text matching needed).
|
|
3184
3186
|
* FALLBACK ONLY: Use old_string + new_string for simple single-line changes where the text is unique. Copy old_string verbatim from the file. Keep old_string as small as possible.
|
|
@@ -141,6 +141,8 @@ Bash is fine for: formatters (gofmt, prettier, black), build/test/lint commands,
|
|
|
141
141
|
- Never expose secrets, API keys, or credentials in generated code. Never log sensitive information.
|
|
142
142
|
- Do not surprise the user with unrequested changes. Do what was asked, including reasonable follow-up actions, but do not refactor surrounding code or add features that were not requested.
|
|
143
143
|
- When editing files, keep edits focused and minimal. For changes spanning more than a few lines, prefer line-targeted editing (start_line/end_line) over text replacement (old_string) — it constrains scope and prevents accidental removal of adjacent content. Never include unrelated sections in an edit operation.
|
|
144
|
+
- In line-targeted mode, omitting position means replace/update the addressed lines. To insert code near an existing line, you MUST use position="before" or position="after". Never express insertion as end_line < start_line.
|
|
145
|
+
- To remove lines with line-targeted mode, target the exact start_line/end_line range and set new_string to the empty string "".
|
|
144
146
|
- After every significant change, verify the project still builds and passes linting. Do not wait until the end to discover breakage.
|
|
145
147
|
|
|
146
148
|
# Writing Tests
|
package/src/tools/edit.js
CHANGED
|
@@ -186,6 +186,13 @@ function buildLineEditResponse(file_path, startLine, endLine, newLineCount, upda
|
|
|
186
186
|
return msg;
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
+
const lineTargetedModeGuidance = `Line-targeted mode has three explicit behaviors:
|
|
190
|
+
- Replace/update lines: provide start_line and optionally end_line, and omit position
|
|
191
|
+
- Insert near a line: provide start_line and set position to "before" or "after"
|
|
192
|
+
- Delete lines: provide start_line/end_line for the exact range and set new_string to empty string ""
|
|
193
|
+
|
|
194
|
+
Inverted ranges (end_line < start_line) are always invalid and are never treated as insertion.`;
|
|
195
|
+
|
|
189
196
|
/**
|
|
190
197
|
* Handle line-targeted editing (replace, insert, delete by line numbers)
|
|
191
198
|
* @param {Object} params - Parameters
|
|
@@ -211,12 +218,15 @@ async function handleLineEdit({ resolvedPath, file_path, start_line, end_line, n
|
|
|
211
218
|
const endLine = endRef ? endRef.line : startLine;
|
|
212
219
|
|
|
213
220
|
if (endLine < startLine) {
|
|
214
|
-
|
|
221
|
+
const insertionHint = endLine === startLine - 1
|
|
222
|
+
? ` This looks like an insertion between lines ${endLine} and ${startLine}. To insert there without replacing existing code, use start_line="${startLine}" with position="before" or start_line="${endLine}" with position="after".`
|
|
223
|
+
: ' To insert new code, choose a single anchor line in start_line and set position to "before" or "after" instead of using an inverted range.';
|
|
224
|
+
return `Error editing file: end_line (${endLine}) must be >= start_line (${startLine}). Omitting position means replace/update the addressed lines, not insert.${insertionHint} To delete lines, use new_string as the empty string "" with a valid non-inverted range.`;
|
|
215
225
|
}
|
|
216
226
|
|
|
217
227
|
// Validate position if provided
|
|
218
228
|
if (position !== undefined && position !== null && position !== 'before' && position !== 'after') {
|
|
219
|
-
return 'Error editing file: Invalid position - must be "before" or "after". Use position="before" to insert before
|
|
229
|
+
return 'Error editing file: Invalid position - must be "before" or "after". Use position="before" to insert before start_line, position="after" to insert after start_line, or omit position to replace/update the addressed lines.';
|
|
220
230
|
}
|
|
221
231
|
|
|
222
232
|
// Read the file
|
|
@@ -304,23 +314,25 @@ export const editTool = (options = {}) => {
|
|
|
304
314
|
|
|
305
315
|
return tool({
|
|
306
316
|
name: 'edit',
|
|
307
|
-
description: `Edit files using text replacement, AST-aware symbol operations, or line-targeted
|
|
317
|
+
description: `Edit files using text replacement, AST-aware symbol operations, or line-targeted line replacement/insertion/deletion.
|
|
308
318
|
|
|
309
319
|
Modes:
|
|
310
320
|
1. Text edit: Provide old_string + new_string to find and replace text (with fuzzy matching fallback)
|
|
311
321
|
2. Symbol replace: Provide symbol + new_string to replace an entire function/class/method by name
|
|
312
322
|
3. Symbol insert: Provide symbol + new_string + position to insert code before/after a symbol
|
|
313
|
-
4. Line-targeted edit: Provide start_line + new_string to
|
|
323
|
+
4. Line-targeted edit: Provide start_line + new_string to replace/update, insert, or delete lines by line number (from extract/search output)
|
|
324
|
+
|
|
325
|
+
${lineTargetedModeGuidance}
|
|
314
326
|
|
|
315
327
|
Parameters:
|
|
316
328
|
- file_path: Path to the file to edit (absolute or relative)
|
|
317
|
-
- new_string: Replacement text or new code content
|
|
329
|
+
- new_string: Replacement text or new code content. Use empty string "" to delete the targeted line range.
|
|
318
330
|
- old_string: (optional) Text to find and replace. If omitted, symbol or start_line must be provided.
|
|
319
331
|
- replace_all: (optional) Replace all occurrences (text mode only)
|
|
320
332
|
- symbol: (optional) Symbol name for AST-aware editing (e.g. "myFunction", "MyClass.myMethod")
|
|
321
|
-
- position: (optional) "before" or "after" — insert code near a symbol or line instead of replacing it
|
|
322
|
-
- start_line: (optional) Line reference (e.g. "42" or "42:ab") for line-targeted editing
|
|
323
|
-
- end_line: (optional) End of line range, inclusive (e.g. "55" or "55:cd")
|
|
333
|
+
- position: (optional) "before" or "after" — insert code near a symbol or line instead of replacing it. Omit position to replace/update.
|
|
334
|
+
- start_line: (optional) Line reference (e.g. "42" or "42:ab") for line-targeted editing. With position, this is the insertion anchor. Without position, this is the first line to replace/update/delete.
|
|
335
|
+
- end_line: (optional) End of line range, inclusive (e.g. "55" or "55:cd"). Must be >= start_line. Omit for single-line updates. Do not use inverted ranges for insertion.`,
|
|
324
336
|
|
|
325
337
|
inputSchema: {
|
|
326
338
|
type: 'object',
|
|
@@ -335,7 +347,7 @@ Parameters:
|
|
|
335
347
|
},
|
|
336
348
|
new_string: {
|
|
337
349
|
type: 'string',
|
|
338
|
-
description: 'Replacement text or new code content'
|
|
350
|
+
description: 'Replacement text or new code content. Use empty string "" to delete the targeted line range.'
|
|
339
351
|
},
|
|
340
352
|
replace_all: {
|
|
341
353
|
type: 'boolean',
|
|
@@ -349,15 +361,15 @@ Parameters:
|
|
|
349
361
|
position: {
|
|
350
362
|
type: 'string',
|
|
351
363
|
enum: ['before', 'after'],
|
|
352
|
-
description: 'Insert before/after
|
|
364
|
+
description: 'Insert before/after the target symbol or start_line anchor. Omit position to replace/update the addressed symbol or line range.'
|
|
353
365
|
},
|
|
354
366
|
start_line: {
|
|
355
367
|
type: 'string',
|
|
356
|
-
description: 'Line reference for line-targeted editing (e.g. "42" or "42:ab" with hash)'
|
|
368
|
+
description: 'Line reference for line-targeted editing (e.g. "42" or "42:ab" with hash). With position, this is the insertion anchor. Without position, this is the first line to replace/update/delete.'
|
|
357
369
|
},
|
|
358
370
|
end_line: {
|
|
359
371
|
type: 'string',
|
|
360
|
-
description: '
|
|
372
|
+
description: 'Inclusive end of the line range to replace/delete (e.g. "55" or "55:cd"). Must be >= start_line. Defaults to start_line.'
|
|
361
373
|
}
|
|
362
374
|
},
|
|
363
375
|
required: ['file_path', 'new_string']
|
|
@@ -702,7 +714,7 @@ export const editSchema = {
|
|
|
702
714
|
},
|
|
703
715
|
new_string: {
|
|
704
716
|
type: 'string',
|
|
705
|
-
description: 'Replacement text or new code content'
|
|
717
|
+
description: 'Replacement text or new code content. Use empty string "" to delete the targeted line range.'
|
|
706
718
|
},
|
|
707
719
|
replace_all: {
|
|
708
720
|
type: 'boolean',
|
|
@@ -715,15 +727,15 @@ export const editSchema = {
|
|
|
715
727
|
position: {
|
|
716
728
|
type: 'string',
|
|
717
729
|
enum: ['before', 'after'],
|
|
718
|
-
description: 'Insert before/after
|
|
730
|
+
description: 'Insert before/after the target symbol or start_line anchor. Omit position to replace/update the addressed symbol or line range.'
|
|
719
731
|
},
|
|
720
732
|
start_line: {
|
|
721
733
|
type: 'string',
|
|
722
|
-
description: 'Line reference for line-targeted editing (e.g. "42" or "42:ab" with hash)'
|
|
734
|
+
description: 'Line reference for line-targeted editing (e.g. "42" or "42:ab" with hash). With position, this is the insertion anchor. Without position, this is the first line to replace/update/delete.'
|
|
723
735
|
},
|
|
724
736
|
end_line: {
|
|
725
737
|
type: 'string',
|
|
726
|
-
description: '
|
|
738
|
+
description: 'Inclusive end of the line range to replace/delete (e.g. "55" or "55:cd"). Must be >= start_line. Defaults to start_line.'
|
|
727
739
|
}
|
|
728
740
|
},
|
|
729
741
|
required: ['file_path', 'new_string']
|
|
@@ -760,7 +772,7 @@ export const multiEditSchema = {
|
|
|
760
772
|
};
|
|
761
773
|
|
|
762
774
|
// Tool descriptions for XML definitions
|
|
763
|
-
export const editDescription = 'Edit files using text replacement, AST-aware symbol operations, or line-targeted
|
|
775
|
+
export const editDescription = 'Edit files using text replacement, AST-aware symbol operations, or line-targeted replacement/insertion/deletion. Supports fuzzy matching for text edits and optional hash-based integrity verification for line edits.';
|
|
764
776
|
export const createDescription = 'Create new files with specified content. Will create parent directories if needed.';
|
|
765
777
|
export const multiEditDescription = 'Apply multiple file edits in a single tool call. Accepts a JSON array of edit operations, each supporting the same modes as the edit tool.';
|
|
766
778
|
|
|
@@ -779,15 +791,21 @@ Four editing modes — choose based on the scope of your change:
|
|
|
779
791
|
|
|
780
792
|
4. **Line-targeted edit** (start_line + new_string): For precise edits using line numbers from extract/search output. Use start_line with a line number (e.g. "42") or line:hash (e.g. "42:ab") for integrity verification. Add end_line for multi-line ranges. Use position="before" or "after" to insert instead of replace.
|
|
781
793
|
|
|
794
|
+
How line-targeted mode behaves:
|
|
795
|
+
- Replace/update lines: provide start_line and optionally end_line, and omit position
|
|
796
|
+
- Insert near a line: provide start_line and set position to "before" or "after"
|
|
797
|
+
- Delete lines: provide start_line/end_line for the exact range and set new_string to empty string ""
|
|
798
|
+
- Inverted ranges are invalid: end_line must be >= start_line and is never treated as insertion
|
|
799
|
+
|
|
782
800
|
Parameters:
|
|
783
801
|
- file_path: (required) Path to the file to edit
|
|
784
|
-
- new_string: (required) Replacement text or new code content
|
|
802
|
+
- new_string: (required) Replacement text or new code content. Use empty string "" to delete the targeted line range.
|
|
785
803
|
- old_string: (optional) Text to find and replace — copy verbatim from the file, do not paraphrase or reformat
|
|
786
804
|
- replace_all: (optional, default: false) Replace all occurrences of old_string (text mode only)
|
|
787
805
|
- symbol: (optional) Name of a code symbol (e.g. "myFunction", "MyClass.myMethod") — must match a function, class, or method definition
|
|
788
|
-
- position: (optional) "before" or "after" — insert new_string near the symbol or line instead of replacing it
|
|
789
|
-
- start_line: (optional) Line reference for line-targeted editing (e.g. "42" or "42:ab")
|
|
790
|
-
- end_line: (optional) End of line range, inclusive (e.g. "55" or "55:cd"). Defaults to start_line.
|
|
806
|
+
- position: (optional) "before" or "after" — insert new_string near the symbol or line instead of replacing it. Omit position to replace/update.
|
|
807
|
+
- start_line: (optional) Line reference for line-targeted editing (e.g. "42" or "42:ab"). With position, this is the insertion anchor. Without position, this is the first line to replace/update/delete.
|
|
808
|
+
- end_line: (optional) End of line range, inclusive (e.g. "55" or "55:cd"). Defaults to start_line. Must be >= start_line. Use it for replace/update/delete ranges, not insertion.
|
|
791
809
|
|
|
792
810
|
Mode selection rules (priority order):
|
|
793
811
|
- If symbol is provided, symbol mode is used (old_string and start_line are ignored)
|
|
@@ -799,12 +817,15 @@ When to use each mode:
|
|
|
799
817
|
- Small edits (a line or a few lines): use text mode with old_string
|
|
800
818
|
- Replacing entire functions/classes/methods: use symbol mode — no exact text matching needed
|
|
801
819
|
- Editing specific lines from extract/search output: use line-targeted mode with start_line
|
|
820
|
+
- Adding a new block near an existing line: use line-targeted mode with start_line plus position="before" or position="after"
|
|
821
|
+
- Removing lines entirely: use line-targeted mode with start_line/end_line and new_string=""
|
|
802
822
|
- Editing inside large functions without rewriting them entirely: first use extract with the symbol target (e.g. "file.js#myFunction") to see the function with line numbers, then use start_line/end_line to edit specific lines within it
|
|
803
823
|
|
|
804
824
|
Error handling:
|
|
805
825
|
- If an edit fails, read the error message carefully — it contains specific instructions for how to fix the call and retry
|
|
806
826
|
- Common fixes: use 'search'/'extract' to get exact file content, add more context to old_string, switch between text and symbol modes
|
|
807
827
|
- Line-targeted hash mismatch: the file changed since last read; the error provides updated line:hash references
|
|
828
|
+
- Inverted line ranges are invalid; the error explains how to express insertion with position="before"/"after"
|
|
808
829
|
|
|
809
830
|
Examples:
|
|
810
831
|
|
|
@@ -858,6 +879,22 @@ Line-targeted edit (replace a range of lines):
|
|
|
858
879
|
return processItems(order.items);</new_string>
|
|
859
880
|
</edit>
|
|
860
881
|
|
|
882
|
+
Line-targeted edit (insert before a line without replacing it):
|
|
883
|
+
<edit>
|
|
884
|
+
<file_path>src/main.js</file_path>
|
|
885
|
+
<start_line>42</start_line>
|
|
886
|
+
<position>before</position>
|
|
887
|
+
<new_string> logger.debug("starting process");</new_string>
|
|
888
|
+
</edit>
|
|
889
|
+
|
|
890
|
+
Line-targeted edit (delete a range of lines):
|
|
891
|
+
<edit>
|
|
892
|
+
<file_path>src/main.js</file_path>
|
|
893
|
+
<start_line>42</start_line>
|
|
894
|
+
<end_line>45</end_line>
|
|
895
|
+
<new_string></new_string>
|
|
896
|
+
</edit>
|
|
897
|
+
|
|
861
898
|
Line-targeted edit with hash verification:
|
|
862
899
|
<edit>
|
|
863
900
|
<file_path>src/main.js</file_path>
|