mindweave 2.2.1 → 2.3.0
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/README.md +6 -2
- package/dist/cli/App.js +104 -39
- package/dist/cli/App.js.map +1 -1
- package/dist/cli/altScreen.js +17 -1
- package/dist/cli/altScreen.js.map +1 -1
- package/dist/cli/blockSpacing.js +29 -0
- package/dist/cli/blockSpacing.js.map +1 -0
- package/dist/cli/commandLabel.js +85 -0
- package/dist/cli/commandLabel.js.map +1 -0
- package/dist/cli/commands.js +40 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/components/PromptInput.js +8 -1
- package/dist/cli/components/PromptInput.js.map +1 -1
- package/dist/cli/components/ToolGroup.js +5 -1
- package/dist/cli/components/ToolGroup.js.map +1 -1
- package/dist/cli/components/ToolLine.js +61 -6
- package/dist/cli/components/ToolLine.js.map +1 -1
- package/dist/cli/framebuffer/parse.js +10 -4
- package/dist/cli/framebuffer/parse.js.map +1 -1
- package/dist/cli/framebuffer/screen.js +26 -0
- package/dist/cli/framebuffer/screen.js.map +1 -1
- package/dist/cli/framebuffer/writer.js +131 -23
- package/dist/cli/framebuffer/writer.js.map +1 -1
- package/dist/cli/restart.js +99 -0
- package/dist/cli/restart.js.map +1 -0
- package/dist/cli/selfUpdate.js +124 -0
- package/dist/cli/selfUpdate.js.map +1 -0
- package/dist/cli/startupArgs.js +29 -2
- package/dist/cli/startupArgs.js.map +1 -1
- package/dist/cli/terminalRestore.js +9 -1
- package/dist/cli/terminalRestore.js.map +1 -1
- package/dist/cli/toolDisplay.js +15 -6
- package/dist/cli/toolDisplay.js.map +1 -1
- package/dist/cli/transcript.js +1 -1
- package/dist/cli/transcript.js.map +1 -1
- package/dist/cli/updateRunner.js +105 -0
- package/dist/cli/updateRunner.js.map +1 -0
- package/dist/drivers/gemini/manifest.js +16 -11
- package/dist/drivers/gemini/manifest.js.map +1 -1
- package/dist/dynamo/engine.js +30 -4
- package/dist/dynamo/engine.js.map +1 -1
- package/dist/dynamo/prompt.js +7 -4
- package/dist/dynamo/prompt.js.map +1 -1
- package/dist/dynamo/verify.js +8 -5
- package/dist/dynamo/verify.js.map +1 -1
- package/dist/index.js +32 -2
- package/dist/index.js.map +1 -1
- package/dist/memory/types.js.map +1 -1
- package/dist/tools/askUser.js +17 -5
- package/dist/tools/askUser.js.map +1 -1
- package/dist/tools/detail.js +69 -11
- package/dist/tools/detail.js.map +1 -1
- package/dist/tools/exitPlan.js +17 -1
- package/dist/tools/exitPlan.js.map +1 -1
- package/dist/tools/outputShape.js +137 -0
- package/dist/tools/outputShape.js.map +1 -0
- package/dist/tools/registry.js +0 -2
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/runCommand.js +31 -7
- package/dist/tools/runCommand.js.map +1 -1
- package/dist/tools/screenshot.js +33 -5
- package/dist/tools/screenshot.js.map +1 -1
- package/dist/tools/testSummary.js +211 -0
- package/dist/tools/testSummary.js.map +1 -0
- package/package.json +2 -2
- package/dist/alternator/chassis/rank.js +0 -72
- package/dist/alternator/chassis/rank.js.map +0 -1
- package/dist/cli/components/MenuFrame.js +0 -24
- package/dist/cli/components/MenuFrame.js.map +0 -1
- package/dist/cli/reveal.js +0 -32
- package/dist/cli/reveal.js.map +0 -1
- package/dist/cli/smoothScroll.js +0 -74
- package/dist/cli/smoothScroll.js.map +0 -1
- package/dist/cli/viewport.js +0 -179
- package/dist/cli/viewport.js.map +0 -1
- package/dist/dynamo/_probe.tmp.js +0 -20
- package/dist/dynamo/_probe.tmp.js.map +0 -1
- package/dist/tools/captureSweep.js +0 -77
- package/dist/tools/captureSweep.js.map +0 -1
- package/dist/tools/diagnostics.js +0 -174
- package/dist/tools/diagnostics.js.map +0 -1
- package/dist/tools/editFile.js +0 -183
- package/dist/tools/editFile.js.map +0 -1
- package/dist/tools/multiEdit.js +0 -168
- package/dist/tools/multiEdit.js.map +0 -1
package/dist/tools/editFile.js
DELETED
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* editFile.ts — a surgical find-and-replace on one file.
|
|
3
|
-
*
|
|
4
|
-
* The workhorse mutating tool. It replaces an exact `old_string` with
|
|
5
|
-
* `new_string`. Reliability comes from the tool REFUSING bad edits, not from the
|
|
6
|
-
* model being careful — the three refusals below make the classic failure modes
|
|
7
|
-
* (editing a file you never read, a stale/typo'd match, an ambiguous match)
|
|
8
|
-
* structurally impossible:
|
|
9
|
-
*
|
|
10
|
-
* - read-before-edit: the file must have been read this session, so the model's
|
|
11
|
-
* `old_string` is copied from real content, not imagined.
|
|
12
|
-
* - must-exist: zero matches errors instead of silently doing nothing, so the
|
|
13
|
-
* model learns its match was wrong.
|
|
14
|
-
* - unique-match: more than one match (without replace_all) errors and hands back
|
|
15
|
-
* WHERE the candidates are, so an edit never lands in the wrong place and the
|
|
16
|
-
* retry is informed rather than another guess.
|
|
17
|
-
*
|
|
18
|
-
* Matching is exact first, then line-trimmed — and stops there. It is deliberately not
|
|
19
|
-
* a stack of ever-looser matchers: past a point, "looser" only means "more ways to edit
|
|
20
|
-
* the wrong block", which is a corruption bug rather than a convenience. The reasoning,
|
|
21
|
-
* and what is deliberately NOT implemented, lives in editCore.ts.
|
|
22
|
-
* (Deciding *what* to change is the model's job; this tool only applies it.)
|
|
23
|
-
*/
|
|
24
|
-
import { promises as fs } from "node:fs";
|
|
25
|
-
import { recordWrite, relativize } from "./paths.js";
|
|
26
|
-
import { editDetail, lineCount, magnitude, rangeLabel, withScope } from "./detail.js";
|
|
27
|
-
import { applyEol } from "./eol.js";
|
|
28
|
-
import { applyOneEdit } from "./editCore.js";
|
|
29
|
-
import { prepareEditTarget, fail, failQuietly, errText } from "./editTarget.js";
|
|
30
|
-
export const editFile = {
|
|
31
|
-
name: "edit_file",
|
|
32
|
-
readOnly: false,
|
|
33
|
-
// The old wording said `old_string` "must match the file's text", which undersold the
|
|
34
|
-
// matcher in a way that costs real work: matching is tiered, so indentation and line
|
|
35
|
-
// endings are already forgiven. A model told it needs the exact bytes re-reads whole
|
|
36
|
-
// files to get them and retries edits that would have applied. What the tiers do NOT
|
|
37
|
-
// forgive is stated just as plainly, because a matcher that sounds infinitely lenient
|
|
38
|
-
// invites the sloppy input that makes a wrong-place edit possible. See editCore.ts.
|
|
39
|
-
description: "Replace a string in a file with another. This is the DEFAULT editing tool: reach for " +
|
|
40
|
-
"it whenever you are changing one place in a file. Read the file first. " +
|
|
41
|
-
"`old_string` has to identify exactly ONE place, and it is matched on content rather " +
|
|
42
|
-
"than on formatting: if an exact match is not found, each line is compared with its " +
|
|
43
|
-
"leading and trailing whitespace ignored, and line endings are normalized on both " +
|
|
44
|
-
"sides. So you do not need to reproduce a file's exact indentation, and a CRLF file " +
|
|
45
|
-
"is not a problem. What is never forgiven is a skipped, reordered, or extra line. " +
|
|
46
|
-
"If `old_string` matches SEVERAL places the file is left untouched and you get the " +
|
|
47
|
-
"candidate locations back with surrounding context: pick one and include enough " +
|
|
48
|
-
"nearby lines to make it unique, or set `replace_all` to change every occurrence. " +
|
|
49
|
-
"If the SAME file needs changing in several separate places, use multi_edit instead " +
|
|
50
|
-
"of calling this repeatedly. Use write_file only to create a new file or replace one " +
|
|
51
|
-
"wholesale.",
|
|
52
|
-
parameters: {
|
|
53
|
-
type: "object",
|
|
54
|
-
additionalProperties: false,
|
|
55
|
-
required: ["path", "old_string", "new_string"],
|
|
56
|
-
properties: {
|
|
57
|
-
path: {
|
|
58
|
-
type: "string",
|
|
59
|
-
description: "Path to the file, absolute or relative to the working directory.",
|
|
60
|
-
},
|
|
61
|
-
old_string: {
|
|
62
|
-
type: "string",
|
|
63
|
-
description: "The exact text to replace. Include enough surrounding lines to make it unique.",
|
|
64
|
-
},
|
|
65
|
-
new_string: {
|
|
66
|
-
type: "string",
|
|
67
|
-
description: "The replacement text. Use an empty string to delete old_string.",
|
|
68
|
-
},
|
|
69
|
-
replace_all: {
|
|
70
|
-
type: "boolean",
|
|
71
|
-
description: "Replace every occurrence instead of requiring a unique match. Default false.",
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
},
|
|
75
|
-
async execute(args, ctx) {
|
|
76
|
-
const rawPath = typeof args.path === "string" ? args.path.trim() : "";
|
|
77
|
-
if (!rawPath)
|
|
78
|
-
return fail("`path` is required.");
|
|
79
|
-
if (typeof args.old_string !== "string" || args.old_string === "") {
|
|
80
|
-
return fail("`old_string` is required and must not be empty — it identifies the text to replace.");
|
|
81
|
-
}
|
|
82
|
-
if (typeof args.new_string !== "string") {
|
|
83
|
-
return fail("`new_string` is required (use an empty string to delete old_string).");
|
|
84
|
-
}
|
|
85
|
-
const oldString = args.old_string;
|
|
86
|
-
const newString = args.new_string;
|
|
87
|
-
const replaceAll = args.replace_all === true;
|
|
88
|
-
if (oldString === newString) {
|
|
89
|
-
return fail("`old_string` and `new_string` are identical — nothing to change.");
|
|
90
|
-
}
|
|
91
|
-
const target = await prepareEditTarget(ctx, rawPath, "editing");
|
|
92
|
-
if (!target.ok)
|
|
93
|
-
return target.error;
|
|
94
|
-
const { filePath, content, eol } = target;
|
|
95
|
-
// Match line-ending-agnostically. The file on disk may use CRLF (Windows)
|
|
96
|
-
// while the model's old_string — copied from text it was shown — uses LF; an
|
|
97
|
-
// exact byte match would then fail on every multi-line edit. Normalizing the
|
|
98
|
-
// CR the model can't see is a representation fix, not fuzzy matching: we still
|
|
99
|
-
// match whitespace and indentation exactly (handled in editCore). The file's
|
|
100
|
-
// own line endings are preserved on write.
|
|
101
|
-
const applied = applyOneEdit(content, { oldString, newString, replaceAll });
|
|
102
|
-
// A match that didn't land is the model's to correct — it gets the reason and the
|
|
103
|
-
// candidate locations, and retries. Not the user's business, so it stays off screen.
|
|
104
|
-
if (!applied.ok)
|
|
105
|
-
return failQuietly(`${applied.reason} (in ${rawPath}).`);
|
|
106
|
-
const { updated: updatedNorm, count, changeStart, changeEnd } = applied;
|
|
107
|
-
const updated = applyEol(updatedNorm, eol);
|
|
108
|
-
// Snapshot the pre-edit bytes for /undo before touching disk.
|
|
109
|
-
ctx.checkpoints?.backup(filePath, content, updated);
|
|
110
|
-
try {
|
|
111
|
-
await fs.writeFile(filePath, updated, "utf8");
|
|
112
|
-
}
|
|
113
|
-
catch (error) {
|
|
114
|
-
return fail(`could not write ${rawPath}: ${errText(error)}`);
|
|
115
|
-
}
|
|
116
|
-
// Still seen+touched this session — record the new state (with the edited region
|
|
117
|
-
// as this file's focus, so a large file localizes to it in the working set).
|
|
118
|
-
await recordWrite(ctx, filePath, {
|
|
119
|
-
start: charToLine(updatedNorm, Math.max(0, changeStart)) + 1,
|
|
120
|
-
end: charToLine(updatedNorm, changeEnd) + 1,
|
|
121
|
-
});
|
|
122
|
-
const shown = relativize(ctx, filePath);
|
|
123
|
-
const n = replaceAll ? count : 1;
|
|
124
|
-
const plural = n === 1 ? "" : "s";
|
|
125
|
-
// Hand back the changed region WITH fresh line numbers. This is what stops the
|
|
126
|
-
// model from re-reading the whole file after every edit (the loop that bloats a
|
|
127
|
-
// multi-edit task): it can target its next edit straight from this snippet.
|
|
128
|
-
const window = numberedWindow(updatedNorm, Math.max(0, changeStart), changeEnd);
|
|
129
|
-
const span = replaceAll && n > 1 ? ` (showing the first of ${n} sites)` : "";
|
|
130
|
-
// The scope of the change — WHERE and HOW MUCH — so the row shows more than a bare
|
|
131
|
-
// diff: the line range touched (or "N sites" for a spread replace_all) and ± lines.
|
|
132
|
-
const startLine = charToLine(updatedNorm, Math.max(0, changeStart)) + 1;
|
|
133
|
-
const endLine = charToLine(updatedNorm, changeEnd) + 1;
|
|
134
|
-
const removed = lineCount(oldString) * n;
|
|
135
|
-
const added = lineCount(newString) * n;
|
|
136
|
-
const scope = replaceAll && n > 1
|
|
137
|
-
? `${n} sites · ${magnitude(removed, added)}`
|
|
138
|
-
: `${rangeLabel(startLine, endLine)} · ${magnitude(removed, added)}`;
|
|
139
|
-
return {
|
|
140
|
-
output: `Edited ${shown}: ${n} replacement${plural}.\n` +
|
|
141
|
-
`Updated region${span} — line-numbered so you can make further edits without re-reading:\n${window}`,
|
|
142
|
-
summary: `edited ${shown} · ${scope}`,
|
|
143
|
-
detail: withScope(scope, editDetail(oldString, newString)),
|
|
144
|
-
};
|
|
145
|
-
},
|
|
146
|
-
};
|
|
147
|
-
/**
|
|
148
|
-
* Render the lines spanning [startChar, endChar] in `text`, plus `pad` lines of
|
|
149
|
-
* context on each side, with 1-based right-aligned line numbers. Pure and indexed
|
|
150
|
-
* on the normalized (LF) text, so it's independent of the file's real EOL. Bounded
|
|
151
|
-
* by `maxLines` so a sweeping replace can't flood the result.
|
|
152
|
-
*/
|
|
153
|
-
export function numberedWindow(text, startChar, endChar, pad = 4, maxLines = 30) {
|
|
154
|
-
const lines = text.split("\n");
|
|
155
|
-
const startLine = charToLine(text, startChar);
|
|
156
|
-
const endLine = charToLine(text, endChar);
|
|
157
|
-
const from = Math.max(0, startLine - pad);
|
|
158
|
-
let to = Math.min(lines.length - 1, endLine + pad);
|
|
159
|
-
let truncated = false;
|
|
160
|
-
if (to - from + 1 > maxLines) {
|
|
161
|
-
to = from + maxLines - 1;
|
|
162
|
-
truncated = true;
|
|
163
|
-
}
|
|
164
|
-
const width = String(to + 1).length;
|
|
165
|
-
const out = [];
|
|
166
|
-
for (let i = from; i <= to; i++) {
|
|
167
|
-
out.push(`${String(i + 1).padStart(width)} ${lines[i] ?? ""}`);
|
|
168
|
-
}
|
|
169
|
-
if (truncated)
|
|
170
|
-
out.push(" … (region continues; re-read the file if you need the rest)");
|
|
171
|
-
return out.join("\n");
|
|
172
|
-
}
|
|
173
|
-
/** The 0-based line a character offset falls on (count of newlines before it). */
|
|
174
|
-
export function charToLine(text, charIndex) {
|
|
175
|
-
let line = 0;
|
|
176
|
-
const limit = Math.min(charIndex, text.length);
|
|
177
|
-
for (let i = 0; i < limit; i++) {
|
|
178
|
-
if (text[i] === "\n")
|
|
179
|
-
line++;
|
|
180
|
-
}
|
|
181
|
-
return line;
|
|
182
|
-
}
|
|
183
|
-
//# sourceMappingURL=editFile.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"editFile.js","sourceRoot":"","sources":["../../src/tools/editFile.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/multiEdit.js
DELETED
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* multiEdit.ts — several edits to ONE file, in a single call, applied atomically.
|
|
3
|
-
*
|
|
4
|
-
* Why it exists: a real change to a file is often several small replacements in
|
|
5
|
-
* different places. One call per replacement burns model turns and step budget and
|
|
6
|
-
* re-invites the re-read-after-every-edit loop. multi_edit lands them together, and each
|
|
7
|
-
* edit sees the result of the one before, so you can add a symbol and then edit around it.
|
|
8
|
-
*
|
|
9
|
-
* ── DELIBERATELY ONE FILE PER CALL ──────────────────────────────────────────────
|
|
10
|
-
*
|
|
11
|
-
* This tool briefly accepted edits across several files in one call, and that was
|
|
12
|
-
* reverted on purpose. It worked, but the shape was wrong:
|
|
13
|
-
*
|
|
14
|
-
* - BLAST RADIUS. Twelve edits across five files is one UI row, one merged diff, and
|
|
15
|
-
* one `/undo` unit. Per file, you get a row, a scoped diff and an undo point each,
|
|
16
|
-
* which is the difference between a change you can review and one you have to trust.
|
|
17
|
-
* - IT HID THE UNIT OF WORK. "Edit this file in three places" is a thing a person can
|
|
18
|
-
* check. "Edit the codebase" is not, and the tool should not encourage collapsing a
|
|
19
|
-
* whole task into one indivisible action.
|
|
20
|
-
*
|
|
21
|
-
* The cost is honest and worth stating: three files still mean three calls, so if the
|
|
22
|
-
* second refuses, the first has already landed. What makes that acceptable is that the
|
|
23
|
-
* refusals themselves became rare — matching now tolerates indentation drift, and an
|
|
24
|
-
* ambiguous match reports WHERE the candidates are instead of leaving the model to guess
|
|
25
|
-
* (see editCore.ts). The fix for half-applied refactors is fewer failures, not bigger
|
|
26
|
-
* transactions.
|
|
27
|
-
*
|
|
28
|
-
* ATOMIC WITHIN THE FILE: edits are applied to an in-memory copy, and if any of them
|
|
29
|
-
* fails to match, nothing is written and the offending edit is named. A file is never
|
|
30
|
-
* left half-changed. It reuses the shared pre-edit gauntlet (read-before-edit, path
|
|
31
|
-
* guards, forbidden-path approval) and the pure edit core, so its safety guarantees are
|
|
32
|
-
* identical to edit_file's.
|
|
33
|
-
*/
|
|
34
|
-
import { promises as fs } from "node:fs";
|
|
35
|
-
import { recordWrite, relativize } from "./paths.js";
|
|
36
|
-
import { applyEol } from "./eol.js";
|
|
37
|
-
import { multiEditDetail, lineCount, magnitude, rangeLabel, withScope } from "./detail.js";
|
|
38
|
-
import { applyEditSequence } from "./editCore.js";
|
|
39
|
-
import { numberedWindow, charToLine } from "./editFile.js";
|
|
40
|
-
import { prepareEditTarget, fail, failQuietly, errText } from "./editTarget.js";
|
|
41
|
-
export const multiEdit = {
|
|
42
|
-
name: "multi_edit",
|
|
43
|
-
readOnly: false,
|
|
44
|
-
description: "Apply several string replacements to ONE file in a single call, in order. Use it when " +
|
|
45
|
-
"a single file needs changing in more than one place — say an import at the top, a call " +
|
|
46
|
-
"site in the middle, and a helper further down. For a single change to a file, use " +
|
|
47
|
-
"edit_file instead. For several files, make one multi_edit call PER FILE; do not try to " +
|
|
48
|
-
"cover more than one file in a call. Each `old_string` must match the file's text and be " +
|
|
49
|
-
"unique unless `replace_all` is set, and each edit sees the result of the previous ones. " +
|
|
50
|
-
"All-or-nothing: if any edit doesn't match, the file is left completely untouched. Read " +
|
|
51
|
-
"the file first.",
|
|
52
|
-
parameters: {
|
|
53
|
-
type: "object",
|
|
54
|
-
additionalProperties: false,
|
|
55
|
-
required: ["path", "edits"],
|
|
56
|
-
properties: {
|
|
57
|
-
path: {
|
|
58
|
-
type: "string",
|
|
59
|
-
description: "The one file every edit in this call applies to, absolute or relative to the working directory.",
|
|
60
|
-
},
|
|
61
|
-
edits: {
|
|
62
|
-
type: "array",
|
|
63
|
-
description: "The replacements to apply to that file, in order.",
|
|
64
|
-
items: {
|
|
65
|
-
type: "object",
|
|
66
|
-
additionalProperties: false,
|
|
67
|
-
required: ["old_string", "new_string"],
|
|
68
|
-
properties: {
|
|
69
|
-
old_string: {
|
|
70
|
-
type: "string",
|
|
71
|
-
description: "The text to replace. Include enough surrounding lines to make it unique.",
|
|
72
|
-
},
|
|
73
|
-
new_string: {
|
|
74
|
-
type: "string",
|
|
75
|
-
description: "The replacement text. Use an empty string to delete old_string.",
|
|
76
|
-
},
|
|
77
|
-
replace_all: {
|
|
78
|
-
type: "boolean",
|
|
79
|
-
description: "Replace every occurrence instead of requiring a unique match. Use it when the same change applies " +
|
|
80
|
-
"to all of them — e.g. deleting a duplicated helper that appears twice in this file. Default false.",
|
|
81
|
-
},
|
|
82
|
-
},
|
|
83
|
-
},
|
|
84
|
-
},
|
|
85
|
-
},
|
|
86
|
-
},
|
|
87
|
-
async execute(args, ctx) {
|
|
88
|
-
const rawPath = typeof args.path === "string" ? args.path.trim() : "";
|
|
89
|
-
if (!rawPath)
|
|
90
|
-
return fail("`path` is required — it names the one file this call edits.");
|
|
91
|
-
if (!Array.isArray(args.edits) || args.edits.length === 0) {
|
|
92
|
-
return fail("`edits` is required and must be a non-empty array of {old_string, new_string} edits.");
|
|
93
|
-
}
|
|
94
|
-
// Validate and normalize each edit up front, so a bad shape is reported before we
|
|
95
|
-
// touch the file.
|
|
96
|
-
const ops = [];
|
|
97
|
-
for (let i = 0; i < args.edits.length; i++) {
|
|
98
|
-
const e = args.edits[i];
|
|
99
|
-
if (!e || typeof e !== "object")
|
|
100
|
-
return fail(`edit #${i + 1} is not an object.`);
|
|
101
|
-
// A per-edit path is refused rather than ignored. Silently dropping it would apply
|
|
102
|
-
// the edit to the WRONG file — the top-level one — which is the worst outcome
|
|
103
|
-
// available here, so say what to do instead.
|
|
104
|
-
if (typeof e.path === "string" && e.path.trim() && e.path.trim() !== rawPath) {
|
|
105
|
-
return fail(`edit #${i + 1} names a different file (${e.path.trim()}). One multi_edit call edits one file: ` +
|
|
106
|
-
`make a separate call for each file you need to change.`);
|
|
107
|
-
}
|
|
108
|
-
if (typeof e.old_string !== "string" || e.old_string === "") {
|
|
109
|
-
return fail(`edit #${i + 1}: \`old_string\` is required and must not be empty.`);
|
|
110
|
-
}
|
|
111
|
-
if (typeof e.new_string !== "string") {
|
|
112
|
-
return fail(`edit #${i + 1}: \`new_string\` is required (use an empty string to delete).`);
|
|
113
|
-
}
|
|
114
|
-
ops.push({ oldString: e.old_string, newString: e.new_string, replaceAll: e.replace_all === true });
|
|
115
|
-
}
|
|
116
|
-
const target = await prepareEditTarget(ctx, rawPath, "editing");
|
|
117
|
-
if (!target.ok)
|
|
118
|
-
return target.error;
|
|
119
|
-
const { filePath, content, eol } = target;
|
|
120
|
-
// Apply the whole sequence to an in-memory copy. Atomic: a failure names the
|
|
121
|
-
// offending edit and writes nothing.
|
|
122
|
-
const seq = applyEditSequence(content, ops);
|
|
123
|
-
if (!seq.ok) {
|
|
124
|
-
// The reason may already end in a sentence (the ambiguity report does), so don't
|
|
125
|
-
// staple a second full stop onto it.
|
|
126
|
-
const reason = /[.!?]$/.test(seq.reason) ? seq.reason : `${seq.reason}.`;
|
|
127
|
-
// Quiet: the model has the reason and the candidate locations and fixes its own
|
|
128
|
-
// aim. Nothing reached disk, so there is nothing for the user to act on.
|
|
129
|
-
return failQuietly(`edit #${seq.index + 1} could not be applied to ${rawPath}: ${reason} No changes were written.`);
|
|
130
|
-
}
|
|
131
|
-
const updated = applyEol(seq.updated, eol);
|
|
132
|
-
// Snapshot the pre-edit bytes for /undo before touching disk.
|
|
133
|
-
ctx.checkpoints?.backup(filePath, content, updated);
|
|
134
|
-
try {
|
|
135
|
-
await fs.writeFile(filePath, updated, "utf8");
|
|
136
|
-
}
|
|
137
|
-
catch (error) {
|
|
138
|
-
return fail(`could not write ${rawPath}: ${errText(error)}`);
|
|
139
|
-
}
|
|
140
|
-
await recordWrite(ctx, filePath, {
|
|
141
|
-
start: charToLine(seq.updated, seq.spanStart) + 1,
|
|
142
|
-
end: charToLine(seq.updated, seq.spanEnd) + 1,
|
|
143
|
-
});
|
|
144
|
-
const shown = relativize(ctx, filePath);
|
|
145
|
-
const nEdits = ops.length;
|
|
146
|
-
// One numbered window spanning from the first change to the last, so the model can
|
|
147
|
-
// keep working from the result without re-reading the file.
|
|
148
|
-
const window = numberedWindow(seq.updated, seq.spanStart, seq.spanEnd);
|
|
149
|
-
// Scope: how many edits, the line span they cover, and the ± lines across them — so a
|
|
150
|
-
// multi-part change reads as "3 edits · L120-420 · −18 +40", not just a diff.
|
|
151
|
-
const startLine = charToLine(seq.updated, seq.spanStart) + 1;
|
|
152
|
-
const endLine = charToLine(seq.updated, seq.spanEnd) + 1;
|
|
153
|
-
let removed = 0;
|
|
154
|
-
let added = 0;
|
|
155
|
-
for (const op of ops) {
|
|
156
|
-
removed += lineCount(op.oldString);
|
|
157
|
-
added += lineCount(op.newString);
|
|
158
|
-
}
|
|
159
|
-
const scope = `${nEdits} edits · ${rangeLabel(startLine, endLine)} · ${magnitude(removed, added)}`;
|
|
160
|
-
return {
|
|
161
|
-
output: `Edited ${shown}: ${nEdits} edits, ${seq.total} replacement${seq.total === 1 ? "" : "s"} total.\n` +
|
|
162
|
-
`Changed region — line-numbered so you can make further edits without re-reading:\n${window}`,
|
|
163
|
-
summary: `edited ${shown} · ${scope}`,
|
|
164
|
-
detail: withScope(scope, multiEditDetail(ops)),
|
|
165
|
-
};
|
|
166
|
-
},
|
|
167
|
-
};
|
|
168
|
-
//# sourceMappingURL=multiEdit.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"multiEdit.js","sourceRoot":"","sources":["../../src/tools/multiEdit.ts"],"names":[],"mappings":"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"}
|