@namzu/sdk 52.5.0 → 52.6.1
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 +13 -0
- package/dist/manager/session/turn-recorder.d.ts.map +1 -1
- package/dist/manager/session/turn-recorder.js +29 -16
- package/dist/manager/session/turn-recorder.js.map +1 -1
- package/dist/store/session-log/core.d.ts +8 -0
- package/dist/store/session-log/core.d.ts.map +1 -1
- package/dist/store/session-log/core.js +8 -1
- package/dist/store/session-log/core.js.map +1 -1
- package/dist/store/session-log/disk.d.ts +2 -2
- package/dist/store/session-log/disk.d.ts.map +1 -1
- package/dist/store/session-log/disk.js +1 -0
- package/dist/store/session-log/disk.js.map +1 -1
- package/dist/store/session-log/memory.d.ts +1 -1
- package/dist/store/session-log/memory.d.ts.map +1 -1
- package/dist/store/session-log/memory.js +1 -0
- package/dist/store/session-log/memory.js.map +1 -1
- package/dist/tools/builtins/edit-apply.d.ts.map +1 -1
- package/dist/tools/builtins/edit-apply.js +30 -12
- package/dist/tools/builtins/edit-apply.js.map +1 -1
- package/dist/tools/builtins/edit-match.d.ts +47 -0
- package/dist/tools/builtins/edit-match.d.ts.map +1 -0
- package/dist/tools/builtins/edit-match.js +262 -0
- package/dist/tools/builtins/edit-match.js.map +1 -0
- package/package.json +1 -1
- package/src/manager/session/turn-recorder.ts +27 -15
- package/src/store/session-log/core.ts +19 -1
- package/src/store/session-log/disk.ts +3 -2
- package/src/store/session-log/memory.ts +5 -1
- package/src/tools/builtins/edit-apply.ts +31 -12
- package/src/tools/builtins/edit-match.ts +274 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../src/store/session-log/memory.ts"],"names":[],"mappings":"AACA,OAAO,EAEN,uBAAuB,EACvB,cAAc,GAEd,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,yBAAyB,EAA0B,MAAM,YAAY,CAAA;AAC9E,OAAO,EAAE,kBAAkB,EAAmB,MAAM,YAAY,CAAA;AAEhE;;;;;GAKG;AAEH,2EAA2E;AAC3E,MAAM,OAAO,iBAAiB;IAC7B,MAAM,GAAW,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAEhC,KAAK,CAAC,IAAI;QACT,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,CAAA;IAC9B,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAc,EAAE,MAAc;QACxC,OAAO,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAA;IAC7E,CAAC;IAED,KAAK,CAAC,CAAC,MAAM,CAAC,MAAc;QAC3B,IAAI,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;YACrC,MAAM,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAC3D,CAAC;IACF,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAiB,EAAE,cAAsB;QACrD,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,KAAK,cAAc,EAAE,CAAC;YAC/C,MAAM,IAAI,uBAAuB,CAChC,cAAc,IAAI,CAAC,MAAM,CAAC,UAAU,sCAAsC,cAAc,GAAG,CAC3F,CAAA;QACF,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAA;IAClD,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,IAAY,EAAE,YAAoB;QAChD,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,KAAK,YAAY,EAAE,CAAC;YAC7C,MAAM,IAAI,uBAAuB,CAChC,cAAc,IAAI,CAAC,MAAM,CAAC,UAAU,mBAAmB,YAAY,sCAAsC,CACzG,CAAA;QACF,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,CAAA;IAC5C,CAAC;IAED,iCAAiC;IACjC,KAAK;QACJ,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAChC,CAAC;IAED,2EAA2E;IAC3E,SAAS,CAAC,KAAiB;QAC1B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACjC,CAAC;CACD;
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../src/store/session-log/memory.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edit-apply.d.ts","sourceRoot":"","sources":["../../../src/tools/builtins/edit-apply.ts"],"names":[],"mappings":"
|
|
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
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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(
|
|
161
|
+
const parts = content.split(oldString);
|
|
142
162
|
const replacements = parts.length - 1;
|
|
143
163
|
return {
|
|
144
164
|
success: true,
|
|
145
|
-
content: parts.join(
|
|
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(
|
|
151
|
-
const secondIndex = content.indexOf(
|
|
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":"
|
|
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.
|
|
3
|
+
"version": "52.6.1",
|
|
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": {
|
|
@@ -1140,23 +1140,30 @@ export class TurnRecorder {
|
|
|
1140
1140
|
this.#view.filter((entry) => entry.id).map((entry, index) => [entry.id as MessageId, index]),
|
|
1141
1141
|
)
|
|
1142
1142
|
const first = durable.findIndex((entry) => entry.id !== undefined)
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1143
|
+
// Keep the longest run of recorded messages from `first` that is still in
|
|
1144
|
+
// log order by id; the first new (id-less) or out-of-order entry and
|
|
1145
|
+
// everything after it is re-recorded below with fresh ids, so the next
|
|
1146
|
+
// re-base sees an ordered view and does nothing wholesale. Only genuinely
|
|
1147
|
+
// new messages BEFORE the first recorded one — the one slot the fold's
|
|
1148
|
+
// [summary, ...kept, ...after] shape leaves them — become the summary.
|
|
1149
|
+
// Collapsing the WHOLE context into the summary and stripping every id (the
|
|
1150
|
+
// old fallback) is what made each pass re-inline an ever-larger context
|
|
1151
|
+
// forever; this bounds a re-base to the messages that actually moved.
|
|
1152
|
+
let runEnd = first < 0 ? 0 : first + 1
|
|
1153
|
+
if (first >= 0) {
|
|
1154
|
+
let prev = recordedOrder.get(durable[first]?.id as MessageId) ?? -1
|
|
1155
|
+
for (let i = first + 1; i < durable.length; i++) {
|
|
1156
|
+
const id = durable[i]?.id
|
|
1157
|
+
if (id === undefined) break
|
|
1158
|
+
const order = recordedOrder.get(id) ?? -1
|
|
1159
|
+
if (order <= prev) break
|
|
1160
|
+
prev = order
|
|
1161
|
+
runEnd = i + 1
|
|
1148
1162
|
}
|
|
1149
1163
|
}
|
|
1150
|
-
const
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
const before = recordedOrder.get(middle[i - 1]?.id as MessageId) ?? -1
|
|
1154
|
-
const after = recordedOrder.get(middle[i]?.id as MessageId) ?? -1
|
|
1155
|
-
if (after <= before) ordered = false
|
|
1156
|
-
}
|
|
1157
|
-
const summaryEntries = !ordered ? durable : first < 0 ? durable : durable.slice(0, first)
|
|
1158
|
-
const keptEntries = ordered ? middle : []
|
|
1159
|
-
const tailEntries = ordered && first >= 0 ? durable.slice(last + 1) : []
|
|
1164
|
+
const summaryEntries = first < 0 ? [] : durable.slice(0, first)
|
|
1165
|
+
const keptEntries = first < 0 ? [] : durable.slice(first, runEnd)
|
|
1166
|
+
const tailEntries = durable.slice(first < 0 ? 0 : runEnd)
|
|
1160
1167
|
for (const entry of summaryEntries) {
|
|
1161
1168
|
entry.id = undefined
|
|
1162
1169
|
this.#ids.delete(entry.message)
|
|
@@ -1187,6 +1194,11 @@ export class TurnRecorder {
|
|
|
1187
1194
|
}).catch(() => undefined)
|
|
1188
1195
|
for (const entry of tailEntries) {
|
|
1189
1196
|
const message = entry.message
|
|
1197
|
+
// A tail entry recorded before the break keeps its object, but its old
|
|
1198
|
+
// record is inside the replaced range; drop the stale id so it is
|
|
1199
|
+
// re-recorded under a fresh one instead of duplicating the old id.
|
|
1200
|
+
this.#ids.delete(message)
|
|
1201
|
+
this.#recorded.delete(message)
|
|
1190
1202
|
const id = this.#idFor(message)
|
|
1191
1203
|
entry.id = id
|
|
1192
1204
|
void this.#enqueue(() =>
|
|
@@ -250,6 +250,14 @@ export interface SessionLogCoreOptions {
|
|
|
250
250
|
* bytes spills its body first. Default {@link SESSION_RECORD_MAX_BYTES}.
|
|
251
251
|
*/
|
|
252
252
|
readonly spillAboveBytes?: number
|
|
253
|
+
/**
|
|
254
|
+
* A `compaction` record whose summary would exceed this many bytes spills
|
|
255
|
+
* it even when under {@link spillAboveBytes}. A re-base summary should be
|
|
256
|
+
* small, so a large one is written beside the log rather than inline, which
|
|
257
|
+
* keeps the log compact and cheap to replay. Capped at `spillAboveBytes`.
|
|
258
|
+
* Default {@link COMPACTION_SPILL_ABOVE_BYTES}.
|
|
259
|
+
*/
|
|
260
|
+
readonly compactionSpillAboveBytes?: number
|
|
253
261
|
/**
|
|
254
262
|
* Spill screened structured tool JSON and accepted structured output when
|
|
255
263
|
* their record exceeds spillAboveBytes. Default false preserves inline
|
|
@@ -280,6 +288,8 @@ const BOUNDARY_TYPES: ReadonlySet<string> = new Set([
|
|
|
280
288
|
|
|
281
289
|
/** Characters of a spilled message kept inline as its preview. */
|
|
282
290
|
const PREVIEW_CHARS = 2000
|
|
291
|
+
/** Default byte bound above which a `compaction` record's summary is spilled. */
|
|
292
|
+
const COMPACTION_SPILL_ABOVE_BYTES = 256 * 1024
|
|
283
293
|
|
|
284
294
|
const ZERO_USAGE = {
|
|
285
295
|
promptTokens: 0,
|
|
@@ -314,6 +324,7 @@ export class SessionLogCore implements SessionLog {
|
|
|
314
324
|
readonly #spills: SpillStore
|
|
315
325
|
readonly #now: () => number
|
|
316
326
|
readonly #spillAbove: number
|
|
327
|
+
readonly #compactionSpillAbove: number
|
|
317
328
|
readonly #structuredResultSpilling: boolean
|
|
318
329
|
readonly #sync: 'boundaries' | 'all' | 'none'
|
|
319
330
|
readonly #mutex = new Mutex()
|
|
@@ -345,6 +356,10 @@ export class SessionLogCore implements SessionLog {
|
|
|
345
356
|
options.spillAboveBytes ?? SESSION_RECORD_MAX_BYTES,
|
|
346
357
|
SESSION_RECORD_MAX_BYTES,
|
|
347
358
|
)
|
|
359
|
+
this.#compactionSpillAbove = Math.min(
|
|
360
|
+
options.compactionSpillAboveBytes ?? COMPACTION_SPILL_ABOVE_BYTES,
|
|
361
|
+
this.#spillAbove,
|
|
362
|
+
)
|
|
348
363
|
this.#sync = options.sync ?? 'boundaries'
|
|
349
364
|
}
|
|
350
365
|
|
|
@@ -659,7 +674,10 @@ export class SessionLogCore implements SessionLog {
|
|
|
659
674
|
)
|
|
660
675
|
return candidate
|
|
661
676
|
const size = Buffer.byteLength(`${JSON.stringify(candidate)}\n`, 'utf8')
|
|
662
|
-
|
|
677
|
+
// A compaction summary should be small; spill it at a lower bound so a
|
|
678
|
+
// single large one never sits inline and bloats the log.
|
|
679
|
+
const spillAbove = type === 'compaction' ? this.#compactionSpillAbove : this.#spillAbove
|
|
680
|
+
if (size <= spillAbove) return candidate
|
|
663
681
|
if (type === 'turn_completed') {
|
|
664
682
|
if (typeof candidate.result !== 'string') return candidate
|
|
665
683
|
const ref = await this.#spills.write(
|
|
@@ -135,7 +135,7 @@ export class DiskLogMedium implements LogMedium {
|
|
|
135
135
|
export interface DiskSessionLogOptions
|
|
136
136
|
extends Pick<
|
|
137
137
|
SessionLogCoreOptions,
|
|
138
|
-
'now' | 'spillAboveBytes' | 'structuredResultSpilling' | 'sync'
|
|
138
|
+
'now' | 'spillAboveBytes' | 'compactionSpillAboveBytes' | 'structuredResultSpilling' | 'sync'
|
|
139
139
|
> {
|
|
140
140
|
readonly sessionId: SessionId
|
|
141
141
|
/** `<session-id>.jsonl`. */
|
|
@@ -171,6 +171,7 @@ export class DiskSessionLog extends SessionLogCore {
|
|
|
171
171
|
spills: new DiskSpillStore(options.sessionDir, options.now),
|
|
172
172
|
now: options.now,
|
|
173
173
|
spillAboveBytes: options.spillAboveBytes,
|
|
174
|
+
compactionSpillAboveBytes: options.compactionSpillAboveBytes,
|
|
174
175
|
structuredResultSpilling: options.structuredResultSpilling,
|
|
175
176
|
sync: options.sync,
|
|
176
177
|
})
|
|
@@ -190,7 +191,7 @@ export class DiskSessionLog extends SessionLogCore {
|
|
|
190
191
|
locator: SessionLocator,
|
|
191
192
|
options: Pick<
|
|
192
193
|
SessionLogCoreOptions,
|
|
193
|
-
'now' | 'spillAboveBytes' | 'structuredResultSpilling' | 'sync'
|
|
194
|
+
'now' | 'spillAboveBytes' | 'compactionSpillAboveBytes' | 'structuredResultSpilling' | 'sync'
|
|
194
195
|
> = {},
|
|
195
196
|
): DiskSessionLog {
|
|
196
197
|
return new DiskSessionLog({
|
|
@@ -63,7 +63,10 @@ export class InMemoryLogMedium implements LogMedium {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
export interface InMemorySessionLogOptions
|
|
66
|
-
extends Pick<
|
|
66
|
+
extends Pick<
|
|
67
|
+
SessionLogCoreOptions,
|
|
68
|
+
'now' | 'spillAboveBytes' | 'compactionSpillAboveBytes' | 'structuredResultSpilling'
|
|
69
|
+
> {
|
|
67
70
|
readonly sessionId: SessionId
|
|
68
71
|
/**
|
|
69
72
|
* Share storage with another instance, as a second process would see one
|
|
@@ -91,6 +94,7 @@ export class InMemorySessionLog extends SessionLogCore {
|
|
|
91
94
|
spills,
|
|
92
95
|
now: options.now,
|
|
93
96
|
spillAboveBytes: options.spillAboveBytes,
|
|
97
|
+
compactionSpillAboveBytes: options.compactionSpillAboveBytes,
|
|
94
98
|
structuredResultSpilling: options.structuredResultSpilling,
|
|
95
99
|
sync: 'none',
|
|
96
100
|
})
|