@namzu/sdk 52.5.0 → 52.6.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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 52.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - c230860: Make `edit` recover a few `old_string` near-misses instead of failing, matching the reference terminal's resolver and order: a straight quote against the file's curly one (or the reverse), and a `\uXXXX` escape where the file holds the character (or a character where the file holds the escape). The matched span is a real substring of the file, so the uniqueness rule still applies and the same transformation is carried onto `new_string`. A whitespace or indentation difference is still not recovered — the error continues to tell the model to match those exactly. A deletion (empty `new_string`) now takes the matched line's trailing newline with it, so removing a whole line no longer leaves a blank one behind. The CRLF/LF reconciliation this kernel already did is unchanged.
8
+
3
9
  ## 52.5.0
4
10
 
5
11
  ### Minor Changes
@@ -1 +1 @@
1
- {"version":3,"file":"edit-apply.d.ts","sourceRoot":"","sources":["../../../src/tools/builtins/edit-apply.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAE1C;;;;;;;;;;GAUG;AAEH,MAAM,MAAM,mBAAmB,GAC5B;IACA,SAAS,EAAE,SAAS,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,OAAO,CAAA;CACnB,GACD;IACA,SAAS,EAAE,QAAQ,CAAA;IACnB,UAAU,EAAE,MAAM,GAAG,KAAK,CAAA;IAC1B,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,OAAO,CAAA;CACnB,CAAA;AAEJ;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CACjC,KAAK,EAAE,SAAS,GACd;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,mBAAmB,EAAE,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAuD1F;AAoCD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,SAAS,CACxB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,SAAS,mBAAmB,EAAE,GACxC;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAiB9F;AA2HD;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,GACtB;IACA,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAA;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;CAC5B,GACD;IAAE,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACzD;IACA,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAA;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACrB,CAAA;AAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,oBAAoB,CACnC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,OAAO,EACrB,SAAS,EAAE,MAAM,GACf,aAAa,CAOf;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACrC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,SAAS,mBAAmB,EAAE,EAC1C,SAAS,EAAE,MAAM,GACf,aAAa,CAyBf"}
1
+ {"version":3,"file":"edit-apply.d.ts","sourceRoot":"","sources":["../../../src/tools/builtins/edit-apply.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAE1C;;;;;;;;;;GAUG;AAEH,MAAM,MAAM,mBAAmB,GAC5B;IACA,SAAS,EAAE,SAAS,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,OAAO,CAAA;CACnB,GACD;IACA,SAAS,EAAE,QAAQ,CAAA;IACnB,UAAU,EAAE,MAAM,GAAG,KAAK,CAAA;IAC1B,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,OAAO,CAAA;CACnB,CAAA;AAEJ;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CACjC,KAAK,EAAE,SAAS,GACd;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,mBAAmB,EAAE,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAuD1F;AAoCD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,SAAS,CACxB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,SAAS,mBAAmB,EAAE,GACxC;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAiB9F;AA6ID;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,GACtB;IACA,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAA;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;CAC5B,GACD;IAAE,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACzD;IACA,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAA;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACrB,CAAA;AAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,oBAAoB,CACnC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,OAAO,EACrB,SAAS,EAAE,MAAM,GACf,aAAa,CAOf;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACrC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,SAAS,mBAAmB,EAAE,EAC1C,SAAS,EAAE,MAAM,GACf,aAAa,CAyBf"}
@@ -1,3 +1,4 @@
1
+ import { reconcileNewString, resolveOldString } from './edit-match.js';
1
2
  /**
2
3
  * Turn one call into the ordered list of operations it stands for.
3
4
  *
@@ -131,24 +132,43 @@ function applyOne(content, input) {
131
132
  return applyLineInsert(content, input);
132
133
  }
133
134
  const replacement = normalizeLineEndings(content, input);
134
- if (!content.includes(replacement.oldString)) {
135
- return {
136
- success: false,
137
- error: 'old_string/oldStr not found in file. Make sure the string matches exactly, including whitespace and indentation.',
138
- };
135
+ // Exact first — which, after the CRLF reconciliation above, is what nearly
136
+ // every call is. On a miss, recover the span across a difference the model
137
+ // did not mean: a curly quote for a straight one, a `\uXXXX` escape for the
138
+ // character or the reverse. `resolveOldString` returns the real span in the
139
+ // file, and `reconcileNewString` carries the same change onto the
140
+ // replacement so it fits where it lands. See `edit-match.ts`.
141
+ let oldString = replacement.oldString;
142
+ let newString = replacement.newString;
143
+ if (!content.includes(oldString)) {
144
+ const resolved = resolveOldString(content, oldString);
145
+ if (resolved === null) {
146
+ return {
147
+ success: false,
148
+ error: 'old_string/oldStr not found in file. Make sure the string matches exactly, including whitespace and indentation.',
149
+ };
150
+ }
151
+ newString = reconcileNewString(oldString, resolved, newString);
152
+ oldString = resolved;
153
+ }
154
+ // A deletion takes the line's trailing newline with it, so removing a whole
155
+ // line does not leave a blank one behind. Only when the anchor is not
156
+ // already newline-terminated and the file has it followed by one.
157
+ if (newString === '' && !oldString.endsWith('\n') && content.includes(`${oldString}\n`)) {
158
+ oldString = `${oldString}\n`;
139
159
  }
140
160
  if (replacement.replace_all) {
141
- const parts = content.split(replacement.oldString);
161
+ const parts = content.split(oldString);
142
162
  const replacements = parts.length - 1;
143
163
  return {
144
164
  success: true,
145
- content: parts.join(replacement.newString),
165
+ content: parts.join(newString),
146
166
  replacements,
147
167
  };
148
168
  }
149
169
  // Uniqueness check: old_string/oldStr must appear exactly once
150
- const firstIndex = content.indexOf(replacement.oldString);
151
- const secondIndex = content.indexOf(replacement.oldString, firstIndex + 1);
170
+ const firstIndex = content.indexOf(oldString);
171
+ const secondIndex = content.indexOf(oldString, firstIndex + 1);
152
172
  if (secondIndex !== -1) {
153
173
  const lineNumber = content.slice(0, firstIndex).split('\n').length;
154
174
  const secondLine = content.slice(0, secondIndex).split('\n').length;
@@ -159,9 +179,7 @@ function applyOne(content, input) {
159
179
  }
160
180
  return {
161
181
  success: true,
162
- content: content.slice(0, firstIndex) +
163
- replacement.newString +
164
- content.slice(firstIndex + replacement.oldString.length),
182
+ content: content.slice(0, firstIndex) + newString + content.slice(firstIndex + oldString.length),
165
183
  replacements: 1,
166
184
  };
167
185
  }
@@ -1 +1 @@
1
- {"version":3,"file":"edit-apply.js","sourceRoot":"","sources":["../../../src/tools/builtins/edit-apply.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"edit-apply.js","sourceRoot":"","sources":["../../../src/tools/builtins/edit-apply.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Flexible `old_string` matching for the edit tool.
3
+ *
4
+ * When an exact match of `old_string` against the file fails, a handful of
5
+ * near-misses are not the model being wrong about the text, only about one
6
+ * invisible or interchangeable detail: a curly quote where the file has a
7
+ * straight one, or a `\uXXXX` escape where the file has the character itself
8
+ * (or the reverse). This module recovers the real span the model meant, and
9
+ * carries the same transformation across to `new_string` so the replacement
10
+ * stays consistent with what it replaced.
11
+ *
12
+ * The strategies and their order are a faithful port of the reference client's
13
+ * file-edit resolver (the `lje`/`b`/`_`/`L`/`k`/`R`/`C`/`cDs`/`ipt`/`H`/`Q`/`N`
14
+ * functions in its shipped bundle), so an edit that lands there lands here:
15
+ *
16
+ * 1. exact
17
+ * 2. curly vs straight quotes, both directions
18
+ * 3. `\uXXXX` escape in `old_string`, character in the file
19
+ * 4. character in `old_string`, `\uXXXX` escape in the file
20
+ *
21
+ * The reference also expands a map of its own prompt delimiters (`<fnr>` →
22
+ * `<function_results>`, `\n\nH:` → `\n\nHuman:`, …). That is deliberately NOT
23
+ * ported: those tokens are artifacts of that client's own transcript format,
24
+ * not a mismatch a Namzu model produces against a real source file.
25
+ *
26
+ * Pure by construction, like `edit-apply`: every function here is from strings
27
+ * to strings, with no filesystem access.
28
+ */
29
+ /**
30
+ * The span of `content` that `oldString` refers to, recovering it across a
31
+ * quote- or escape-only difference, or null when nothing matches even then.
32
+ *
33
+ * The returned string is a real substring of `content` (or its escaped form),
34
+ * so the caller can run the ordinary uniqueness check and splice against it.
35
+ */
36
+ export declare function resolveOldString(content: string, oldString: string): string | null;
37
+ /**
38
+ * Carry the transformation that matched `oldString` across to `newString`, so
39
+ * the replacement matches the span it lands in rather than the literal the
40
+ * model typed.
41
+ *
42
+ * `resolved` is what {@link resolveOldString} returned — equal to `oldString`
43
+ * for an exact match (then `newString` is returned unchanged), and otherwise
44
+ * the real span, which tells us which strategy fired.
45
+ */
46
+ export declare function reconcileNewString(oldString: string, resolved: string, newString: string): string;
47
+ //# sourceMappingURL=edit-match.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edit-match.d.ts","sourceRoot":"","sources":["../../../src/tools/builtins/edit-match.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAkHH;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkBlF;AAiDD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAiDjG"}
@@ -0,0 +1,262 @@
1
+ /**
2
+ * Flexible `old_string` matching for the edit tool.
3
+ *
4
+ * When an exact match of `old_string` against the file fails, a handful of
5
+ * near-misses are not the model being wrong about the text, only about one
6
+ * invisible or interchangeable detail: a curly quote where the file has a
7
+ * straight one, or a `\uXXXX` escape where the file has the character itself
8
+ * (or the reverse). This module recovers the real span the model meant, and
9
+ * carries the same transformation across to `new_string` so the replacement
10
+ * stays consistent with what it replaced.
11
+ *
12
+ * The strategies and their order are a faithful port of the reference client's
13
+ * file-edit resolver (the `lje`/`b`/`_`/`L`/`k`/`R`/`C`/`cDs`/`ipt`/`H`/`Q`/`N`
14
+ * functions in its shipped bundle), so an edit that lands there lands here:
15
+ *
16
+ * 1. exact
17
+ * 2. curly vs straight quotes, both directions
18
+ * 3. `\uXXXX` escape in `old_string`, character in the file
19
+ * 4. character in `old_string`, `\uXXXX` escape in the file
20
+ *
21
+ * The reference also expands a map of its own prompt delimiters (`<fnr>` →
22
+ * `<function_results>`, `\n\nH:` → `\n\nHuman:`, …). That is deliberately NOT
23
+ * ported: those tokens are artifacts of that client's own transcript format,
24
+ * not a mismatch a Namzu model produces against a real source file.
25
+ *
26
+ * Pure by construction, like `edit-apply`: every function here is from strings
27
+ * to strings, with no filesystem access.
28
+ */
29
+ const LEFT_SINGLE_QUOTE = '‘';
30
+ const RIGHT_SINGLE_QUOTE = '’';
31
+ const LEFT_DOUBLE_QUOTE = '“';
32
+ const RIGHT_DOUBLE_QUOTE = '”';
33
+ /** `old_string` carries a `\uXXXX` escape the file may hold as a character. */
34
+ const HAS_UNICODE_ESCAPE = /\\u[0-9a-fA-F]{4}/;
35
+ /** `old_string` carries a non-ASCII character the file may hold as an escape. */
36
+ const HAS_NON_ASCII = /[\u0080-￿]/;
37
+ /** Curly quotes to straight. Length-preserving: one character for one. */
38
+ function straightenQuotes(text) {
39
+ return text
40
+ .replaceAll(LEFT_SINGLE_QUOTE, "'")
41
+ .replaceAll(RIGHT_SINGLE_QUOTE, "'")
42
+ .replaceAll(LEFT_DOUBLE_QUOTE, '"')
43
+ .replaceAll(RIGHT_DOUBLE_QUOTE, '"');
44
+ }
45
+ /**
46
+ * Replace each `\uXXXX` escape with its character, leaving an escaped
47
+ * backslash (`\\`) untouched so `\\u0041` stays the five characters it is
48
+ * rather than becoming a stray `A`.
49
+ */
50
+ function decodeUnicodeEscapes(text) {
51
+ return text.replace(/(\\\\)|\\u([0-9a-fA-F]{4})/g, (whole, backslashes, hex) => backslashes !== undefined ? whole : String.fromCharCode(Number.parseInt(hex, 16)));
52
+ }
53
+ /** The length `text` would have if every non-ASCII character were a `\uXXXX`. */
54
+ function escapedLength(text) {
55
+ let nonAscii = 0;
56
+ for (let i = 0; i < text.length; i++)
57
+ if (text.charCodeAt(i) >= 128)
58
+ nonAscii++;
59
+ return text.length + 5 * nonAscii;
60
+ }
61
+ /** Consecutive backslashes immediately before index `at`. */
62
+ function trailingBackslashes(text, at) {
63
+ let count = 0;
64
+ while (text[at - 1 - count] === '\\')
65
+ count++;
66
+ return count;
67
+ }
68
+ /** Escape a literal string so it matches itself inside a `RegExp`. */
69
+ function escapeRegExp(text) {
70
+ return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
71
+ }
72
+ /**
73
+ * A pattern that matches `model` where every non-ASCII character appears as its
74
+ * `\uXXXX` escape (case-insensitive in the hex letters) and every ASCII
75
+ * character appears literally. Used to find, in a file written with escapes,
76
+ * the span a model wrote with the characters themselves.
77
+ */
78
+ function buildEscapeTolerantPattern(model) {
79
+ let pattern = '';
80
+ for (let i = 0; i < model.length; i++) {
81
+ const code = model.charCodeAt(i);
82
+ if (code >= 128) {
83
+ pattern += '\\\\u';
84
+ for (const digit of code.toString(16).padStart(4, '0'))
85
+ pattern += digit >= 'a' ? `[${digit}${digit.toUpperCase()}]` : digit;
86
+ }
87
+ else {
88
+ // biome-ignore lint/style/noNonNullAssertion: index < length
89
+ pattern += escapeRegExp(model[i]);
90
+ }
91
+ }
92
+ return pattern;
93
+ }
94
+ /**
95
+ * Find, in `file`, the escaped form of `model` — where `model` is written with
96
+ * real non-ASCII characters and `file` holds them as `\uXXXX`. Returns the
97
+ * matched (escaped) substring, or null when there is no such span, when the
98
+ * pattern would be ambiguous, or when a matched `\u` is itself escaped by an
99
+ * odd run of backslashes (a literal `\u`, not an escape).
100
+ */
101
+ function findEscapedForm(model, file) {
102
+ // A model ending in an odd number of backslashes cannot be the clean prefix
103
+ // of an escape sequence; bail rather than build a pattern that misreads it.
104
+ if (trailingBackslashes(model, model.length) % 2 === 1)
105
+ return null;
106
+ // Offsets, within the escaped match, whose backslash parity must be checked
107
+ // so a literal `\u` in the file is not mistaken for an escape.
108
+ const sensitiveOffsets = model[0] === '\\' ? [0] : [];
109
+ let offset = 0;
110
+ for (let i = 0; i < model.length; i++) {
111
+ if (model.charCodeAt(i) >= 128) {
112
+ sensitiveOffsets.push(offset);
113
+ offset += 6;
114
+ }
115
+ else {
116
+ offset += 1;
117
+ }
118
+ }
119
+ let regex;
120
+ try {
121
+ regex = new RegExp(buildEscapeTolerantPattern(model), 'g');
122
+ }
123
+ catch {
124
+ return null;
125
+ }
126
+ for (let match = regex.exec(file); match !== null; match = regex.exec(file)) {
127
+ const at = match.index;
128
+ if (sensitiveOffsets.every((o) => trailingBackslashes(file, at + o) % 2 === 0)) {
129
+ return file.indexOf(match[0]) === at ? match[0] : null;
130
+ }
131
+ regex.lastIndex = at + 1;
132
+ }
133
+ return null;
134
+ }
135
+ /**
136
+ * The span of `content` that `oldString` refers to, recovering it across a
137
+ * quote- or escape-only difference, or null when nothing matches even then.
138
+ *
139
+ * The returned string is a real substring of `content` (or its escaped form),
140
+ * so the caller can run the ordinary uniqueness check and splice against it.
141
+ */
142
+ export function resolveOldString(content, oldString) {
143
+ if (content.includes(oldString))
144
+ return oldString;
145
+ const straight = straightenQuotes(oldString);
146
+ const quoteIndex = straightenQuotes(content).indexOf(straight);
147
+ if (quoteIndex !== -1)
148
+ return content.substring(quoteIndex, quoteIndex + oldString.length);
149
+ if (HAS_UNICODE_ESCAPE.test(oldString)) {
150
+ const decoded = decodeUnicodeEscapes(oldString);
151
+ if (decoded !== oldString && content.includes(decoded))
152
+ return decoded;
153
+ }
154
+ if (HAS_NON_ASCII.test(oldString)) {
155
+ if (escapedLength(oldString) > content.length || !content.includes('\\u'))
156
+ return null;
157
+ return findEscapedForm(oldString, content);
158
+ }
159
+ return null;
160
+ }
161
+ /** Is `char` at `index` opening a quote (preceded by a boundary) rather than closing one? */
162
+ function isOpeningPosition(chars, index) {
163
+ if (index === 0)
164
+ return true;
165
+ const before = chars[index - 1];
166
+ return (before === ' ' ||
167
+ before === '\t' ||
168
+ before === '\n' ||
169
+ before === '\r' ||
170
+ before === '(' ||
171
+ before === '[' ||
172
+ before === '{' ||
173
+ before === '—' ||
174
+ before === '–');
175
+ }
176
+ /** Apply curly double quotes to `text`, choosing opening vs closing by context. */
177
+ function curlifyDoubleQuotes(text) {
178
+ const chars = [...text];
179
+ return chars
180
+ .map((char, index) => char === '"'
181
+ ? isOpeningPosition(chars, index)
182
+ ? LEFT_DOUBLE_QUOTE
183
+ : RIGHT_DOUBLE_QUOTE
184
+ : char)
185
+ .join('');
186
+ }
187
+ /** Apply curly single quotes to `text`; an apostrophe between letters is always closing. */
188
+ function curlifySingleQuotes(text) {
189
+ const chars = [...text];
190
+ return chars
191
+ .map((char, index) => {
192
+ if (char !== "'")
193
+ return char;
194
+ const before = index > 0 ? chars[index - 1] : undefined;
195
+ const after = index < chars.length - 1 ? chars[index + 1] : undefined;
196
+ const betweenLetters = before !== undefined && /\p{L}/u.test(before) && after !== undefined && /\p{L}/u.test(after);
197
+ if (betweenLetters)
198
+ return RIGHT_SINGLE_QUOTE;
199
+ return isOpeningPosition(chars, index) ? LEFT_SINGLE_QUOTE : RIGHT_SINGLE_QUOTE;
200
+ })
201
+ .join('');
202
+ }
203
+ /**
204
+ * Carry the transformation that matched `oldString` across to `newString`, so
205
+ * the replacement matches the span it lands in rather than the literal the
206
+ * model typed.
207
+ *
208
+ * `resolved` is what {@link resolveOldString} returned — equal to `oldString`
209
+ * for an exact match (then `newString` is returned unchanged), and otherwise
210
+ * the real span, which tells us which strategy fired.
211
+ */
212
+ export function reconcileNewString(oldString, resolved, newString) {
213
+ if (resolved === oldString)
214
+ return newString;
215
+ // character in old, escape in file: re-escape new's non-ASCII to the file's
216
+ // hex spelling, matching the letter-case the file used.
217
+ if (HAS_NON_ASCII.test(oldString) &&
218
+ escapedLength(oldString) === resolved.length &&
219
+ findEscapedForm(oldString, resolved) !== null) {
220
+ const perChar = new Map();
221
+ let upper = 0;
222
+ let lower = 0;
223
+ for (let oldIndex = 0, resolvedIndex = 0; oldIndex < oldString.length; oldIndex++) {
224
+ const code = oldString.charCodeAt(oldIndex);
225
+ if (code >= 128) {
226
+ const hex = resolved.slice(resolvedIndex + 2, resolvedIndex + 6);
227
+ perChar.set(code, hex);
228
+ for (const digit of hex)
229
+ if (digit >= 'a' && digit <= 'f')
230
+ lower++;
231
+ else if (digit >= 'A' && digit <= 'F')
232
+ upper++;
233
+ resolvedIndex += 6;
234
+ }
235
+ else {
236
+ resolvedIndex += 1;
237
+ }
238
+ }
239
+ return newString.replace(/[\u0080-￿]/g, (char) => {
240
+ const code = char.charCodeAt(0);
241
+ const known = perChar.get(code);
242
+ if (known !== undefined)
243
+ return `\\u${known}`;
244
+ const hex = code.toString(16).padStart(4, '0');
245
+ return `\\u${upper > lower ? hex.toUpperCase() : hex}`;
246
+ });
247
+ }
248
+ // escape in old, character in file: decode new's escapes to match.
249
+ if (HAS_UNICODE_ESCAPE.test(oldString) && decodeUnicodeEscapes(oldString) === resolved) {
250
+ return decodeUnicodeEscapes(newString);
251
+ }
252
+ // quote difference: re-apply the file's curly quotes to new, by kind.
253
+ const hasCurlyDouble = resolved.includes(LEFT_DOUBLE_QUOTE) || resolved.includes(RIGHT_DOUBLE_QUOTE);
254
+ const hasCurlySingle = resolved.includes(LEFT_SINGLE_QUOTE) || resolved.includes(RIGHT_SINGLE_QUOTE);
255
+ let reconciled = newString;
256
+ if (hasCurlyDouble)
257
+ reconciled = curlifyDoubleQuotes(reconciled);
258
+ if (hasCurlySingle)
259
+ reconciled = curlifySingleQuotes(reconciled);
260
+ return reconciled;
261
+ }
262
+ //# sourceMappingURL=edit-match.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edit-match.js","sourceRoot":"","sources":["../../../src/tools/builtins/edit-match.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@namzu/sdk",
3
- "version": "52.5.0",
3
+ "version": "52.6.0",
4
4
  "description": "Open-source AI kernel for TypeScript: runs an agent the way an operating system runs a process, with an identity and a budget, scheduled tool calls and checkpointed turns.",
5
5
  "license": "FSL-1.1-MIT",
6
6
  "engines": {
@@ -1,3 +1,4 @@
1
+ import { reconcileNewString, resolveOldString } from './edit-match.js'
1
2
  import type { EditInput } from './edit.js'
2
3
 
3
4
  /**
@@ -177,27 +178,47 @@ function applyOne(
177
178
 
178
179
  const replacement = normalizeLineEndings(content, input)
179
180
 
180
- if (!content.includes(replacement.oldString)) {
181
- return {
182
- success: false,
183
- error:
184
- 'old_string/oldStr not found in file. Make sure the string matches exactly, including whitespace and indentation.',
181
+ // Exact first — which, after the CRLF reconciliation above, is what nearly
182
+ // every call is. On a miss, recover the span across a difference the model
183
+ // did not mean: a curly quote for a straight one, a `\uXXXX` escape for the
184
+ // character or the reverse. `resolveOldString` returns the real span in the
185
+ // file, and `reconcileNewString` carries the same change onto the
186
+ // replacement so it fits where it lands. See `edit-match.ts`.
187
+ let oldString = replacement.oldString
188
+ let newString = replacement.newString
189
+ if (!content.includes(oldString)) {
190
+ const resolved = resolveOldString(content, oldString)
191
+ if (resolved === null) {
192
+ return {
193
+ success: false,
194
+ error:
195
+ 'old_string/oldStr not found in file. Make sure the string matches exactly, including whitespace and indentation.',
196
+ }
185
197
  }
198
+ newString = reconcileNewString(oldString, resolved, newString)
199
+ oldString = resolved
200
+ }
201
+
202
+ // A deletion takes the line's trailing newline with it, so removing a whole
203
+ // line does not leave a blank one behind. Only when the anchor is not
204
+ // already newline-terminated and the file has it followed by one.
205
+ if (newString === '' && !oldString.endsWith('\n') && content.includes(`${oldString}\n`)) {
206
+ oldString = `${oldString}\n`
186
207
  }
187
208
 
188
209
  if (replacement.replace_all) {
189
- const parts = content.split(replacement.oldString)
210
+ const parts = content.split(oldString)
190
211
  const replacements = parts.length - 1
191
212
  return {
192
213
  success: true,
193
- content: parts.join(replacement.newString),
214
+ content: parts.join(newString),
194
215
  replacements,
195
216
  }
196
217
  }
197
218
 
198
219
  // Uniqueness check: old_string/oldStr must appear exactly once
199
- const firstIndex = content.indexOf(replacement.oldString)
200
- const secondIndex = content.indexOf(replacement.oldString, firstIndex + 1)
220
+ const firstIndex = content.indexOf(oldString)
221
+ const secondIndex = content.indexOf(oldString, firstIndex + 1)
201
222
 
202
223
  if (secondIndex !== -1) {
203
224
  const lineNumber = content.slice(0, firstIndex).split('\n').length
@@ -211,9 +232,7 @@ function applyOne(
211
232
  return {
212
233
  success: true,
213
234
  content:
214
- content.slice(0, firstIndex) +
215
- replacement.newString +
216
- content.slice(firstIndex + replacement.oldString.length),
235
+ content.slice(0, firstIndex) + newString + content.slice(firstIndex + oldString.length),
217
236
  replacements: 1,
218
237
  }
219
238
  }
@@ -0,0 +1,274 @@
1
+ /**
2
+ * Flexible `old_string` matching for the edit tool.
3
+ *
4
+ * When an exact match of `old_string` against the file fails, a handful of
5
+ * near-misses are not the model being wrong about the text, only about one
6
+ * invisible or interchangeable detail: a curly quote where the file has a
7
+ * straight one, or a `\uXXXX` escape where the file has the character itself
8
+ * (or the reverse). This module recovers the real span the model meant, and
9
+ * carries the same transformation across to `new_string` so the replacement
10
+ * stays consistent with what it replaced.
11
+ *
12
+ * The strategies and their order are a faithful port of the reference client's
13
+ * file-edit resolver (the `lje`/`b`/`_`/`L`/`k`/`R`/`C`/`cDs`/`ipt`/`H`/`Q`/`N`
14
+ * functions in its shipped bundle), so an edit that lands there lands here:
15
+ *
16
+ * 1. exact
17
+ * 2. curly vs straight quotes, both directions
18
+ * 3. `\uXXXX` escape in `old_string`, character in the file
19
+ * 4. character in `old_string`, `\uXXXX` escape in the file
20
+ *
21
+ * The reference also expands a map of its own prompt delimiters (`<fnr>` →
22
+ * `<function_results>`, `\n\nH:` → `\n\nHuman:`, …). That is deliberately NOT
23
+ * ported: those tokens are artifacts of that client's own transcript format,
24
+ * not a mismatch a Namzu model produces against a real source file.
25
+ *
26
+ * Pure by construction, like `edit-apply`: every function here is from strings
27
+ * to strings, with no filesystem access.
28
+ */
29
+
30
+ const LEFT_SINGLE_QUOTE = '‘'
31
+ const RIGHT_SINGLE_QUOTE = '’'
32
+ const LEFT_DOUBLE_QUOTE = '“'
33
+ const RIGHT_DOUBLE_QUOTE = '”'
34
+
35
+ /** `old_string` carries a `\uXXXX` escape the file may hold as a character. */
36
+ const HAS_UNICODE_ESCAPE = /\\u[0-9a-fA-F]{4}/
37
+ /** `old_string` carries a non-ASCII character the file may hold as an escape. */
38
+ const HAS_NON_ASCII = /[\u0080-￿]/
39
+
40
+ /** Curly quotes to straight. Length-preserving: one character for one. */
41
+ function straightenQuotes(text: string): string {
42
+ return text
43
+ .replaceAll(LEFT_SINGLE_QUOTE, "'")
44
+ .replaceAll(RIGHT_SINGLE_QUOTE, "'")
45
+ .replaceAll(LEFT_DOUBLE_QUOTE, '"')
46
+ .replaceAll(RIGHT_DOUBLE_QUOTE, '"')
47
+ }
48
+
49
+ /**
50
+ * Replace each `\uXXXX` escape with its character, leaving an escaped
51
+ * backslash (`\\`) untouched so `\\u0041` stays the five characters it is
52
+ * rather than becoming a stray `A`.
53
+ */
54
+ function decodeUnicodeEscapes(text: string): string {
55
+ return text.replace(/(\\\\)|\\u([0-9a-fA-F]{4})/g, (whole, backslashes, hex) =>
56
+ backslashes !== undefined ? whole : String.fromCharCode(Number.parseInt(hex, 16)),
57
+ )
58
+ }
59
+
60
+ /** The length `text` would have if every non-ASCII character were a `\uXXXX`. */
61
+ function escapedLength(text: string): number {
62
+ let nonAscii = 0
63
+ for (let i = 0; i < text.length; i++) if (text.charCodeAt(i) >= 128) nonAscii++
64
+ return text.length + 5 * nonAscii
65
+ }
66
+
67
+ /** Consecutive backslashes immediately before index `at`. */
68
+ function trailingBackslashes(text: string, at: number): number {
69
+ let count = 0
70
+ while (text[at - 1 - count] === '\\') count++
71
+ return count
72
+ }
73
+
74
+ /** Escape a literal string so it matches itself inside a `RegExp`. */
75
+ function escapeRegExp(text: string): string {
76
+ return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
77
+ }
78
+
79
+ /**
80
+ * A pattern that matches `model` where every non-ASCII character appears as its
81
+ * `\uXXXX` escape (case-insensitive in the hex letters) and every ASCII
82
+ * character appears literally. Used to find, in a file written with escapes,
83
+ * the span a model wrote with the characters themselves.
84
+ */
85
+ function buildEscapeTolerantPattern(model: string): string {
86
+ let pattern = ''
87
+ for (let i = 0; i < model.length; i++) {
88
+ const code = model.charCodeAt(i)
89
+ if (code >= 128) {
90
+ pattern += '\\\\u'
91
+ for (const digit of code.toString(16).padStart(4, '0'))
92
+ pattern += digit >= 'a' ? `[${digit}${digit.toUpperCase()}]` : digit
93
+ } else {
94
+ // biome-ignore lint/style/noNonNullAssertion: index < length
95
+ pattern += escapeRegExp(model[i]!)
96
+ }
97
+ }
98
+ return pattern
99
+ }
100
+
101
+ /**
102
+ * Find, in `file`, the escaped form of `model` — where `model` is written with
103
+ * real non-ASCII characters and `file` holds them as `\uXXXX`. Returns the
104
+ * matched (escaped) substring, or null when there is no such span, when the
105
+ * pattern would be ambiguous, or when a matched `\u` is itself escaped by an
106
+ * odd run of backslashes (a literal `\u`, not an escape).
107
+ */
108
+ function findEscapedForm(model: string, file: string): string | null {
109
+ // A model ending in an odd number of backslashes cannot be the clean prefix
110
+ // of an escape sequence; bail rather than build a pattern that misreads it.
111
+ if (trailingBackslashes(model, model.length) % 2 === 1) return null
112
+
113
+ // Offsets, within the escaped match, whose backslash parity must be checked
114
+ // so a literal `\u` in the file is not mistaken for an escape.
115
+ const sensitiveOffsets: number[] = model[0] === '\\' ? [0] : []
116
+ let offset = 0
117
+ for (let i = 0; i < model.length; i++) {
118
+ if (model.charCodeAt(i) >= 128) {
119
+ sensitiveOffsets.push(offset)
120
+ offset += 6
121
+ } else {
122
+ offset += 1
123
+ }
124
+ }
125
+
126
+ let regex: RegExp
127
+ try {
128
+ regex = new RegExp(buildEscapeTolerantPattern(model), 'g')
129
+ } catch {
130
+ return null
131
+ }
132
+ for (let match = regex.exec(file); match !== null; match = regex.exec(file)) {
133
+ const at = match.index
134
+ if (sensitiveOffsets.every((o) => trailingBackslashes(file, at + o) % 2 === 0)) {
135
+ return file.indexOf(match[0]) === at ? match[0] : null
136
+ }
137
+ regex.lastIndex = at + 1
138
+ }
139
+ return null
140
+ }
141
+
142
+ /**
143
+ * The span of `content` that `oldString` refers to, recovering it across a
144
+ * quote- or escape-only difference, or null when nothing matches even then.
145
+ *
146
+ * The returned string is a real substring of `content` (or its escaped form),
147
+ * so the caller can run the ordinary uniqueness check and splice against it.
148
+ */
149
+ export function resolveOldString(content: string, oldString: string): string | null {
150
+ if (content.includes(oldString)) return oldString
151
+
152
+ const straight = straightenQuotes(oldString)
153
+ const quoteIndex = straightenQuotes(content).indexOf(straight)
154
+ if (quoteIndex !== -1) return content.substring(quoteIndex, quoteIndex + oldString.length)
155
+
156
+ if (HAS_UNICODE_ESCAPE.test(oldString)) {
157
+ const decoded = decodeUnicodeEscapes(oldString)
158
+ if (decoded !== oldString && content.includes(decoded)) return decoded
159
+ }
160
+
161
+ if (HAS_NON_ASCII.test(oldString)) {
162
+ if (escapedLength(oldString) > content.length || !content.includes('\\u')) return null
163
+ return findEscapedForm(oldString, content)
164
+ }
165
+
166
+ return null
167
+ }
168
+
169
+ /** Is `char` at `index` opening a quote (preceded by a boundary) rather than closing one? */
170
+ function isOpeningPosition(chars: readonly string[], index: number): boolean {
171
+ if (index === 0) return true
172
+ const before = chars[index - 1]
173
+ return (
174
+ before === ' ' ||
175
+ before === '\t' ||
176
+ before === '\n' ||
177
+ before === '\r' ||
178
+ before === '(' ||
179
+ before === '[' ||
180
+ before === '{' ||
181
+ before === '—' ||
182
+ before === '–'
183
+ )
184
+ }
185
+
186
+ /** Apply curly double quotes to `text`, choosing opening vs closing by context. */
187
+ function curlifyDoubleQuotes(text: string): string {
188
+ const chars = [...text]
189
+ return chars
190
+ .map((char, index) =>
191
+ char === '"'
192
+ ? isOpeningPosition(chars, index)
193
+ ? LEFT_DOUBLE_QUOTE
194
+ : RIGHT_DOUBLE_QUOTE
195
+ : char,
196
+ )
197
+ .join('')
198
+ }
199
+
200
+ /** Apply curly single quotes to `text`; an apostrophe between letters is always closing. */
201
+ function curlifySingleQuotes(text: string): string {
202
+ const chars = [...text]
203
+ return chars
204
+ .map((char, index) => {
205
+ if (char !== "'") return char
206
+ const before = index > 0 ? chars[index - 1] : undefined
207
+ const after = index < chars.length - 1 ? chars[index + 1] : undefined
208
+ const betweenLetters =
209
+ before !== undefined && /\p{L}/u.test(before) && after !== undefined && /\p{L}/u.test(after)
210
+ if (betweenLetters) return RIGHT_SINGLE_QUOTE
211
+ return isOpeningPosition(chars, index) ? LEFT_SINGLE_QUOTE : RIGHT_SINGLE_QUOTE
212
+ })
213
+ .join('')
214
+ }
215
+
216
+ /**
217
+ * Carry the transformation that matched `oldString` across to `newString`, so
218
+ * the replacement matches the span it lands in rather than the literal the
219
+ * model typed.
220
+ *
221
+ * `resolved` is what {@link resolveOldString} returned — equal to `oldString`
222
+ * for an exact match (then `newString` is returned unchanged), and otherwise
223
+ * the real span, which tells us which strategy fired.
224
+ */
225
+ export function reconcileNewString(oldString: string, resolved: string, newString: string): string {
226
+ if (resolved === oldString) return newString
227
+
228
+ // character in old, escape in file: re-escape new's non-ASCII to the file's
229
+ // hex spelling, matching the letter-case the file used.
230
+ if (
231
+ HAS_NON_ASCII.test(oldString) &&
232
+ escapedLength(oldString) === resolved.length &&
233
+ findEscapedForm(oldString, resolved) !== null
234
+ ) {
235
+ const perChar = new Map<number, string>()
236
+ let upper = 0
237
+ let lower = 0
238
+ for (let oldIndex = 0, resolvedIndex = 0; oldIndex < oldString.length; oldIndex++) {
239
+ const code = oldString.charCodeAt(oldIndex)
240
+ if (code >= 128) {
241
+ const hex = resolved.slice(resolvedIndex + 2, resolvedIndex + 6)
242
+ perChar.set(code, hex)
243
+ for (const digit of hex)
244
+ if (digit >= 'a' && digit <= 'f') lower++
245
+ else if (digit >= 'A' && digit <= 'F') upper++
246
+ resolvedIndex += 6
247
+ } else {
248
+ resolvedIndex += 1
249
+ }
250
+ }
251
+ return newString.replace(/[\u0080-￿]/g, (char) => {
252
+ const code = char.charCodeAt(0)
253
+ const known = perChar.get(code)
254
+ if (known !== undefined) return `\\u${known}`
255
+ const hex = code.toString(16).padStart(4, '0')
256
+ return `\\u${upper > lower ? hex.toUpperCase() : hex}`
257
+ })
258
+ }
259
+
260
+ // escape in old, character in file: decode new's escapes to match.
261
+ if (HAS_UNICODE_ESCAPE.test(oldString) && decodeUnicodeEscapes(oldString) === resolved) {
262
+ return decodeUnicodeEscapes(newString)
263
+ }
264
+
265
+ // quote difference: re-apply the file's curly quotes to new, by kind.
266
+ const hasCurlyDouble =
267
+ resolved.includes(LEFT_DOUBLE_QUOTE) || resolved.includes(RIGHT_DOUBLE_QUOTE)
268
+ const hasCurlySingle =
269
+ resolved.includes(LEFT_SINGLE_QUOTE) || resolved.includes(RIGHT_SINGLE_QUOTE)
270
+ let reconciled = newString
271
+ if (hasCurlyDouble) reconciled = curlifyDoubleQuotes(reconciled)
272
+ if (hasCurlySingle) reconciled = curlifySingleQuotes(reconciled)
273
+ return reconciled
274
+ }