editcodewithai 2.6.0 → 2.7.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 -3
- package/dist/applyEngine.js +28 -7
- package/dist/fileUtils.d.ts +9 -0
- package/dist/fileUtils.js +32 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -204,9 +204,11 @@ for (const warning of result.warnings ?? []) {
|
|
|
204
204
|
| `NO_EDITS_PARSED` | The model response contained no recognizable edits. |
|
|
205
205
|
|
|
206
206
|
Matching is deterministic: only harmless formatting drift is absorbed (CRLF vs
|
|
207
|
-
LF, a missing/extra trailing newline, trailing whitespace)
|
|
208
|
-
|
|
209
|
-
|
|
207
|
+
LF, a missing/extra trailing newline, trailing whitespace) plus filename drift —
|
|
208
|
+
model-emitted decoration (backticks, bold, headings, a `File:` label, a trailing
|
|
209
|
+
colon, a leading `./`) is stripped, and a target resolves by normalized name,
|
|
210
|
+
case-insensitively, or by a unique basename. Anything ambiguous or unmatched is
|
|
211
|
+
skipped rather than guessed. Successful normalized matches produce no warnings.
|
|
210
212
|
|
|
211
213
|
`warnings` is optional, so existing consumers continue to work unchanged.
|
|
212
214
|
|
|
@@ -265,6 +267,7 @@ import {
|
|
|
265
267
|
|
|
266
268
|
// --- Diff parsing (manual use) ---
|
|
267
269
|
parseDiffs, // Parse search/replace blocks (diff format)
|
|
270
|
+
normalizeDiffFileName, // Normalize a model-emitted filename (strip decoration/path noise)
|
|
268
271
|
applyDiffs, // Apply parsed diffs to a file set (throws on unmatched edits)
|
|
269
272
|
applyDiffsSafe, // Best-effort apply: returns { files, warnings } instead of throwing
|
|
270
273
|
parseDiffFenced, // Parse search/replace blocks (diff-fenced format)
|
package/dist/applyEngine.js
CHANGED
|
@@ -6,23 +6,44 @@ const matching_1 = require("./matching");
|
|
|
6
6
|
* Normalizes a filename for comparison: trims, converts Windows separators to
|
|
7
7
|
* "/", collapses duplicate separators, and strips leading "./" and "/".
|
|
8
8
|
*
|
|
9
|
-
* Case is intentionally preserved
|
|
10
|
-
*
|
|
9
|
+
* Case is intentionally preserved here; callers that need to tolerate case
|
|
10
|
+
* drift fall back to case-insensitive and basename matching after this exact
|
|
11
|
+
* normalized comparison fails.
|
|
11
12
|
*/
|
|
12
13
|
function normalizeFileName(name) {
|
|
13
14
|
return name
|
|
14
15
|
.trim()
|
|
15
16
|
.replace(/\\/g, "/")
|
|
16
17
|
.replace(/\/+/g, "/")
|
|
17
|
-
.replace(
|
|
18
|
+
.replace(/^(?:\.\/)+/, "")
|
|
18
19
|
.replace(/^\/+/, "");
|
|
19
20
|
}
|
|
21
|
+
function normalizeForBasename(name) {
|
|
22
|
+
const normalized = normalizeFileName(name).toLowerCase();
|
|
23
|
+
return normalized.substring(normalized.lastIndexOf("/") + 1);
|
|
24
|
+
}
|
|
20
25
|
function resolveFileId(files, rawName) {
|
|
21
26
|
const target = normalizeFileName(rawName);
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if (
|
|
27
|
+
const ids = Object.keys(files);
|
|
28
|
+
// 1. Exact match on the normalized name.
|
|
29
|
+
const exact = ids.filter((id) => normalizeFileName(files[id].name) === target);
|
|
30
|
+
if (exact.length === 1)
|
|
31
|
+
return { kind: "found", id: exact[0] };
|
|
32
|
+
if (exact.length > 1)
|
|
33
|
+
return { kind: "ambiguous" };
|
|
34
|
+
// 2. Case-insensitive match on the normalized name.
|
|
35
|
+
const lowerTarget = target.toLowerCase();
|
|
36
|
+
const caseInsensitive = ids.filter((id) => normalizeFileName(files[id].name).toLowerCase() === lowerTarget);
|
|
37
|
+
if (caseInsensitive.length === 1)
|
|
38
|
+
return { kind: "found", id: caseInsensitive[0] };
|
|
39
|
+
if (caseInsensitive.length > 1)
|
|
40
|
+
return { kind: "ambiguous" };
|
|
41
|
+
// 3. Basename match (substring after the last "/"), case-insensitive.
|
|
42
|
+
const basename = lowerTarget.substring(lowerTarget.lastIndexOf("/") + 1);
|
|
43
|
+
const byBasename = ids.filter((id) => normalizeForBasename(files[id].name) === basename);
|
|
44
|
+
if (byBasename.length === 1)
|
|
45
|
+
return { kind: "found", id: byBasename[0] };
|
|
46
|
+
if (byBasename.length > 1)
|
|
26
47
|
return { kind: "ambiguous" };
|
|
27
48
|
return { kind: "none" };
|
|
28
49
|
}
|
package/dist/fileUtils.d.ts
CHANGED
|
@@ -25,6 +25,15 @@ export interface Diff {
|
|
|
25
25
|
search: string;
|
|
26
26
|
replace: string;
|
|
27
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Normalizes a model-emitted diff filename line, tolerating common
|
|
30
|
+
* decoration drift (markdown headings, list markers, labels, backticks,
|
|
31
|
+
* bold/italic asterisks, trailing colons) as well as path noise.
|
|
32
|
+
*
|
|
33
|
+
* Decoration-stripping rules are applied repeatedly until the string stops
|
|
34
|
+
* changing, so combinations (e.g. `- **`index.js`**:`) fully normalize.
|
|
35
|
+
*/
|
|
36
|
+
export declare function normalizeDiffFileName(raw: string): string;
|
|
28
37
|
export declare function parseDiffs(responseText: string): Diff[];
|
|
29
38
|
export declare function applyDiffs(originalFiles: VizFiles, diffs: Diff[]): VizFiles;
|
|
30
39
|
export declare function parseDiffFenced(responseText: string): Diff[];
|
package/dist/fileUtils.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.shouldDeleteFile = shouldDeleteFile;
|
|
|
4
4
|
exports.isImageFile = isImageFile;
|
|
5
5
|
exports.prepareFilesForPrompt = prepareFilesForPrompt;
|
|
6
6
|
exports.mergeFileChanges = mergeFileChanges;
|
|
7
|
+
exports.normalizeDiffFileName = normalizeDiffFileName;
|
|
7
8
|
exports.parseDiffs = parseDiffs;
|
|
8
9
|
exports.applyDiffs = applyDiffs;
|
|
9
10
|
exports.parseDiffFenced = parseDiffFenced;
|
|
@@ -88,6 +89,35 @@ function mergeFileChanges(originalFiles, parsedFiles) {
|
|
|
88
89
|
});
|
|
89
90
|
return changedFiles;
|
|
90
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* Normalizes a model-emitted diff filename line, tolerating common
|
|
94
|
+
* decoration drift (markdown headings, list markers, labels, backticks,
|
|
95
|
+
* bold/italic asterisks, trailing colons) as well as path noise.
|
|
96
|
+
*
|
|
97
|
+
* Decoration-stripping rules are applied repeatedly until the string stops
|
|
98
|
+
* changing, so combinations (e.g. `- **`index.js`**:`) fully normalize.
|
|
99
|
+
*/
|
|
100
|
+
function normalizeDiffFileName(raw) {
|
|
101
|
+
let name = raw;
|
|
102
|
+
let previous;
|
|
103
|
+
do {
|
|
104
|
+
previous = name;
|
|
105
|
+
name = name.trim();
|
|
106
|
+
name = name.replace(/^#{1,6}\s+/, "");
|
|
107
|
+
name = name.replace(/^[-*+]\s+/, "");
|
|
108
|
+
name = name.replace(/^(?:file|path)\s*:\s*/i, "");
|
|
109
|
+
name = name.replace(/^`+|`+$/g, "");
|
|
110
|
+
name = name.replace(/^\*+|\*+$/g, "");
|
|
111
|
+
name = name.replace(/:\s*$/, "");
|
|
112
|
+
name = name.trim();
|
|
113
|
+
} while (name !== previous);
|
|
114
|
+
return name
|
|
115
|
+
.replace(/\\/g, "/")
|
|
116
|
+
.replace(/\/+/g, "/")
|
|
117
|
+
.replace(/^(?:\.\/)+/, "")
|
|
118
|
+
.replace(/^\/+/, "")
|
|
119
|
+
.trim();
|
|
120
|
+
}
|
|
91
121
|
function parseDiffs(responseText) {
|
|
92
122
|
const diffs = [];
|
|
93
123
|
// This regex captures the file path, and the content of the SEARCH and REPLACE blocks.
|
|
@@ -96,7 +126,7 @@ function parseDiffs(responseText) {
|
|
|
96
126
|
for (const match of matches) {
|
|
97
127
|
const [_, fileName, search, replace] = match;
|
|
98
128
|
diffs.push({
|
|
99
|
-
fileName: fileName
|
|
129
|
+
fileName: normalizeDiffFileName(fileName),
|
|
100
130
|
search,
|
|
101
131
|
replace,
|
|
102
132
|
});
|
|
@@ -127,7 +157,7 @@ function parseDiffFenced(responseText) {
|
|
|
127
157
|
for (const match of matches) {
|
|
128
158
|
const [_, fileName, search, replace] = match;
|
|
129
159
|
diffs.push({
|
|
130
|
-
fileName: fileName
|
|
160
|
+
fileName: normalizeDiffFileName(fileName),
|
|
131
161
|
search,
|
|
132
162
|
replace,
|
|
133
163
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { PerformAiEditParams, PerformAiEditResult } from "./types";
|
|
2
2
|
import { PROMPT_TEMPLATE_VERSION, assembleFullPrompt, FORMAT_INSTRUCTIONS } from "./prompt";
|
|
3
3
|
import { getGenerationMetadata } from "./metadata";
|
|
4
|
-
import { prepareFilesForPrompt, mergeFileChanges, parseDiffs, applyDiffs, applyDiffsSafe, parseDiffFenced, parseUdiffs, applyUdiffs, applyUdiffsSafe, applyHybridEdits, applyHybridEditsSafe, isImageFile } from "./fileUtils";
|
|
4
|
+
import { prepareFilesForPrompt, mergeFileChanges, parseDiffs, applyDiffs, applyDiffsSafe, parseDiffFenced, normalizeDiffFileName, parseUdiffs, applyUdiffs, applyUdiffsSafe, applyHybridEdits, applyHybridEditsSafe, isImageFile } from "./fileUtils";
|
|
5
5
|
export type { LlmFunction, PerformAiEditParams, PerformAiEditResult, EditFormat, ApplyWarning, ApplyWarningCode, ApplyResult, ParsedEdit, } from "./types";
|
|
6
|
-
export { FORMAT_INSTRUCTIONS, mergeFileChanges, prepareFilesForPrompt, isImageFile, parseDiffs, applyDiffs, applyDiffsSafe, parseDiffFenced, parseUdiffs, applyUdiffs, applyUdiffsSafe, applyHybridEdits, applyHybridEditsSafe, assembleFullPrompt, getGenerationMetadata, PROMPT_TEMPLATE_VERSION, };
|
|
6
|
+
export { FORMAT_INSTRUCTIONS, mergeFileChanges, prepareFilesForPrompt, isImageFile, parseDiffs, applyDiffs, applyDiffsSafe, parseDiffFenced, normalizeDiffFileName, parseUdiffs, applyUdiffs, applyUdiffsSafe, applyHybridEdits, applyHybridEditsSafe, assembleFullPrompt, getGenerationMetadata, PROMPT_TEMPLATE_VERSION, };
|
|
7
7
|
/**
|
|
8
8
|
* Core AI logic for:
|
|
9
9
|
* - Building the prompt (including context)
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PROMPT_TEMPLATE_VERSION = exports.getGenerationMetadata = exports.assembleFullPrompt = exports.applyHybridEditsSafe = exports.applyHybridEdits = exports.applyUdiffsSafe = exports.applyUdiffs = exports.parseUdiffs = exports.parseDiffFenced = exports.applyDiffsSafe = exports.applyDiffs = exports.parseDiffs = exports.isImageFile = exports.prepareFilesForPrompt = exports.mergeFileChanges = exports.FORMAT_INSTRUCTIONS = void 0;
|
|
3
|
+
exports.PROMPT_TEMPLATE_VERSION = exports.getGenerationMetadata = exports.assembleFullPrompt = exports.applyHybridEditsSafe = exports.applyHybridEdits = exports.applyUdiffsSafe = exports.applyUdiffs = exports.parseUdiffs = exports.normalizeDiffFileName = exports.parseDiffFenced = exports.applyDiffsSafe = exports.applyDiffs = exports.parseDiffs = exports.isImageFile = exports.prepareFilesForPrompt = exports.mergeFileChanges = exports.FORMAT_INSTRUCTIONS = void 0;
|
|
4
4
|
exports.performAiEdit = performAiEdit;
|
|
5
5
|
const llm_code_format_1 = require("llm-code-format");
|
|
6
6
|
const prompt_1 = require("./prompt");
|
|
@@ -16,6 +16,7 @@ Object.defineProperty(exports, "parseDiffs", { enumerable: true, get: function (
|
|
|
16
16
|
Object.defineProperty(exports, "applyDiffs", { enumerable: true, get: function () { return fileUtils_1.applyDiffs; } });
|
|
17
17
|
Object.defineProperty(exports, "applyDiffsSafe", { enumerable: true, get: function () { return fileUtils_1.applyDiffsSafe; } });
|
|
18
18
|
Object.defineProperty(exports, "parseDiffFenced", { enumerable: true, get: function () { return fileUtils_1.parseDiffFenced; } });
|
|
19
|
+
Object.defineProperty(exports, "normalizeDiffFileName", { enumerable: true, get: function () { return fileUtils_1.normalizeDiffFileName; } });
|
|
19
20
|
Object.defineProperty(exports, "parseUdiffs", { enumerable: true, get: function () { return fileUtils_1.parseUdiffs; } });
|
|
20
21
|
Object.defineProperty(exports, "applyUdiffs", { enumerable: true, get: function () { return fileUtils_1.applyUdiffs; } });
|
|
21
22
|
Object.defineProperty(exports, "applyUdiffsSafe", { enumerable: true, get: function () { return fileUtils_1.applyUdiffsSafe; } });
|