zidane 3.2.0 → 3.3.2
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/dist/{agent-CE2jhpNE.d.ts → agent-DqEkutk4.d.ts} +92 -25
- package/dist/{chunk-HPTCF3EX.js → chunk-3D5Q527Y.js} +3 -3
- package/dist/{chunk-QX7TDFD4.js → chunk-4ILGBQ23.js} +139 -35
- package/dist/{chunk-YPU6KVL6.js → chunk-LIVB5W4B.js} +1 -1
- package/dist/{chunk-AUBXCLUC.js → chunk-W57VY6DJ.js} +22 -20
- package/dist/{chunk-J4ZOSNSH.js → chunk-X3VOTPVM.js} +1 -7
- package/dist/{chunk-6JIVVEQQ.js → chunk-Z2E5QN5X.js} +198 -84
- package/dist/index.d.ts +4 -4
- package/dist/index.js +6 -8
- package/dist/mcp.d.ts +1 -1
- package/dist/presets.d.ts +1 -1
- package/dist/presets.js +3 -3
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +2 -2
- package/dist/session/sqlite.d.ts +1 -1
- package/dist/session.d.ts +1 -1
- package/dist/session.js +1 -1
- package/dist/{skills-use-CqOKEN56.d.ts → skills-use-WbOh6TuS.d.ts} +1 -1
- package/dist/skills.d.ts +113 -105
- package/dist/skills.js +2 -2
- package/dist/tools.d.ts +4 -4
- package/dist/tools.js +2 -4
- package/dist/types.d.ts +2 -2
- package/dist/{validation-DlIURVGV.d.ts → validation-DTbkLXbd.d.ts} +12 -22
- package/package.json +2 -2
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
createSkillActivationState,
|
|
4
4
|
installAllowedToolsGate,
|
|
5
5
|
interpolateShellCommands,
|
|
6
|
-
|
|
6
|
+
resolveSkills,
|
|
7
7
|
validateResourcePath
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-X3VOTPVM.js";
|
|
9
9
|
import {
|
|
10
10
|
createProcessContext
|
|
11
11
|
} from "./chunk-UD25QF3H.js";
|
|
@@ -69,6 +69,26 @@ function desanitize(s) {
|
|
|
69
69
|
out = out.replaceAll(from, to);
|
|
70
70
|
return out;
|
|
71
71
|
}
|
|
72
|
+
var LINE_NUMBER_PREFIX_RE = /^[ \t]*\d{1,9}[\t|\u2192]/gm;
|
|
73
|
+
function stripLineNumberPrefixes(s) {
|
|
74
|
+
return s.replace(LINE_NUMBER_PREFIX_RE, "");
|
|
75
|
+
}
|
|
76
|
+
function locateAndCount(haystack, normFile, target, via) {
|
|
77
|
+
const idx = normFile.indexOf(target);
|
|
78
|
+
if (idx === -1)
|
|
79
|
+
return null;
|
|
80
|
+
const actual = haystack.slice(idx, idx + target.length);
|
|
81
|
+
let occ = 0;
|
|
82
|
+
let cursor = 0;
|
|
83
|
+
while (true) {
|
|
84
|
+
const next = normFile.indexOf(target, cursor);
|
|
85
|
+
if (next === -1)
|
|
86
|
+
break;
|
|
87
|
+
occ++;
|
|
88
|
+
cursor = next + target.length;
|
|
89
|
+
}
|
|
90
|
+
return { actual, occurrences: occ, via };
|
|
91
|
+
}
|
|
72
92
|
function resolveOldString(haystack, needle) {
|
|
73
93
|
const exact = countExactMatches(haystack, needle);
|
|
74
94
|
if (exact > 0)
|
|
@@ -76,20 +96,9 @@ function resolveOldString(haystack, needle) {
|
|
|
76
96
|
const normNeedle = normalizeQuotes(needle);
|
|
77
97
|
const normFile = normalizeQuotes(haystack);
|
|
78
98
|
if (normNeedle !== needle || normFile !== haystack) {
|
|
79
|
-
const
|
|
80
|
-
if (
|
|
81
|
-
|
|
82
|
-
let occ = 0;
|
|
83
|
-
let cursor = 0;
|
|
84
|
-
while (true) {
|
|
85
|
-
const next = normFile.indexOf(normNeedle, cursor);
|
|
86
|
-
if (next === -1)
|
|
87
|
-
break;
|
|
88
|
-
occ++;
|
|
89
|
-
cursor = next + normNeedle.length;
|
|
90
|
-
}
|
|
91
|
-
return { actual, occurrences: occ, via: "quotes" };
|
|
92
|
-
}
|
|
99
|
+
const m = locateAndCount(haystack, normFile, normNeedle, "quotes");
|
|
100
|
+
if (m)
|
|
101
|
+
return m;
|
|
93
102
|
}
|
|
94
103
|
const desan = desanitize(needle);
|
|
95
104
|
if (desan !== needle) {
|
|
@@ -99,23 +108,34 @@ function resolveOldString(haystack, needle) {
|
|
|
99
108
|
}
|
|
100
109
|
const combo = desanitize(normNeedle);
|
|
101
110
|
if (combo !== needle) {
|
|
102
|
-
const
|
|
103
|
-
if (
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
111
|
+
const m = locateAndCount(haystack, normFile, combo, "quotes+desanitize");
|
|
112
|
+
if (m)
|
|
113
|
+
return m;
|
|
114
|
+
}
|
|
115
|
+
const stripped = stripLineNumberPrefixes(needle);
|
|
116
|
+
if (stripped !== needle && stripped.trim().length > 0) {
|
|
117
|
+
const count = countExactMatches(haystack, stripped);
|
|
118
|
+
if (count > 0)
|
|
119
|
+
return { actual: stripped, occurrences: count, via: "line-numbers" };
|
|
120
|
+
const strippedNorm = normalizeQuotes(stripped);
|
|
121
|
+
if (strippedNorm !== stripped || normFile !== haystack) {
|
|
122
|
+
const m = locateAndCount(haystack, normFile, strippedNorm, "quotes+line-numbers");
|
|
123
|
+
if (m)
|
|
124
|
+
return m;
|
|
115
125
|
}
|
|
116
126
|
}
|
|
117
127
|
return null;
|
|
118
128
|
}
|
|
129
|
+
function styleReplacementForVia(replacement, via, actual) {
|
|
130
|
+
let out = replacement;
|
|
131
|
+
if (via === "desanitize" || via === "quotes+desanitize")
|
|
132
|
+
out = desanitize(out);
|
|
133
|
+
if (via === "line-numbers" || via === "quotes+line-numbers")
|
|
134
|
+
out = stripLineNumberPrefixes(out);
|
|
135
|
+
if (via === "quotes" || via === "quotes+desanitize" || via === "quotes+line-numbers")
|
|
136
|
+
out = preserveQuoteStyle(actual, out);
|
|
137
|
+
return out;
|
|
138
|
+
}
|
|
119
139
|
function preserveQuoteStyle(actual, replacement) {
|
|
120
140
|
const hasDouble = actual.includes(LEFT_DOUBLE_CURLY_QUOTE) || actual.includes(RIGHT_DOUBLE_CURLY_QUOTE);
|
|
121
141
|
const hasSingle = actual.includes(LEFT_SINGLE_CURLY_QUOTE) || actual.includes(RIGHT_SINGLE_CURLY_QUOTE);
|
|
@@ -221,7 +241,7 @@ function hashContent(text) {
|
|
|
221
241
|
var edit = {
|
|
222
242
|
spec: {
|
|
223
243
|
name: "edit",
|
|
224
|
-
description: "Replace exact `old_string` with `new_string` in a file. Fails if `old_string` is not unique unless `replace_all: true`. Prefer over `write_file` for surgical changes \u2014 preserves the rest of the file.",
|
|
244
|
+
description: "Replace exact `old_string` with `new_string` in a file. Fails if `old_string` is not unique unless `replace_all: true`. Prefer over `write_file` for surgical changes \u2014 preserves the rest of the file. Tolerates `read_file` line-number prefixes (`<N>\\t\u2026`, `<N>|\u2026`, or `<N>\u2192\u2026`) in `old_string` / `new_string` \u2014 they are stripped before matching/writing, so you can paste a numbered chunk verbatim.",
|
|
225
245
|
inputSchema: {
|
|
226
246
|
type: "object",
|
|
227
247
|
properties: {
|
|
@@ -266,9 +286,7 @@ var edit = {
|
|
|
266
286
|
const { actual, occurrences, via } = match;
|
|
267
287
|
if (occurrences > 1 && !replaceAll)
|
|
268
288
|
return `Edit error: old_string appears ${occurrences} times in ${target}. Pass replace_all=true or expand old_string for uniqueness.`;
|
|
269
|
-
|
|
270
|
-
if (via === "quotes" || via === "quotes+desanitize")
|
|
271
|
-
styledReplacement = preserveQuoteStyle(actual, styledReplacement);
|
|
289
|
+
const styledReplacement = styleReplacementForVia(replacement, via, actual);
|
|
272
290
|
const updated = replaceAll ? original.split(actual).join(styledReplacement) : original.replace(actual, styledReplacement);
|
|
273
291
|
if (updated === original)
|
|
274
292
|
return `Edit error: replacement produced no change in ${target}.`;
|
|
@@ -285,7 +303,8 @@ var edit = {
|
|
|
285
303
|
}
|
|
286
304
|
};
|
|
287
305
|
function nearestMatchPreview(haystack, needle) {
|
|
288
|
-
const
|
|
306
|
+
const normalizedNeedle = stripLineNumberPrefixes(needle);
|
|
307
|
+
const needleFirstLine = normalizedNeedle.split("\n")[0];
|
|
289
308
|
if (needleFirstLine.length < 3)
|
|
290
309
|
return null;
|
|
291
310
|
const lines = haystack.split("\n");
|
|
@@ -312,6 +331,8 @@ function sharedPrefixLength(a, b) {
|
|
|
312
331
|
}
|
|
313
332
|
|
|
314
333
|
// src/tools/glob.ts
|
|
334
|
+
import { stat } from "fs/promises";
|
|
335
|
+
import { resolve } from "path";
|
|
315
336
|
var DEFAULT_LIMIT = 1e3;
|
|
316
337
|
var SAFE_GLOB_PATTERN_RE = /^[\w./*?[\]{}!,^@+-]+$/;
|
|
317
338
|
async function globInProcess(pattern, cwd, limit) {
|
|
@@ -338,7 +359,7 @@ async function globViaShell(pattern, ctx, limit) {
|
|
|
338
359
|
var glob = {
|
|
339
360
|
spec: {
|
|
340
361
|
name: "glob",
|
|
341
|
-
description: "Match files by glob pattern (supports **, *, ?). Relative to the execution context cwd.
|
|
362
|
+
description: "Match files by glob pattern (supports **, *, ?). Relative to the execution context cwd. By default each row is `<path>\\t<size-bytes>\\t<mtime-iso>`; set `metadata: false` for a plain newline-separated list of paths. Always sorted.",
|
|
342
363
|
inputSchema: {
|
|
343
364
|
type: "object",
|
|
344
365
|
properties: {
|
|
@@ -349,17 +370,34 @@ var glob = {
|
|
|
349
370
|
limit: {
|
|
350
371
|
type: "number",
|
|
351
372
|
description: `Maximum number of matches to return. Default: ${DEFAULT_LIMIT}.`
|
|
373
|
+
},
|
|
374
|
+
metadata: {
|
|
375
|
+
type: "boolean",
|
|
376
|
+
description: "Append size (bytes) and mtime (ISO) per row, tab-separated. Default: true. In-process only \u2014 non-process execution contexts always return paths."
|
|
352
377
|
}
|
|
353
378
|
},
|
|
354
379
|
required: ["pattern"]
|
|
355
380
|
}
|
|
356
381
|
},
|
|
357
|
-
async execute({ pattern, limit }, ctx) {
|
|
382
|
+
async execute({ pattern, limit, metadata }, ctx) {
|
|
358
383
|
const pat = pattern;
|
|
359
384
|
const max = typeof limit === "number" && limit > 0 ? limit : DEFAULT_LIMIT;
|
|
385
|
+
const wantMetadata = metadata !== false;
|
|
360
386
|
try {
|
|
361
387
|
const entries = ctx.execution.type === "process" ? await globInProcess(pat, ctx.handle.cwd, max) : await globViaShell(pat, ctx, max);
|
|
362
|
-
|
|
388
|
+
if (entries.length === 0)
|
|
389
|
+
return "(no matches)";
|
|
390
|
+
if (!wantMetadata || ctx.execution.type !== "process")
|
|
391
|
+
return entries.join("\n");
|
|
392
|
+
const rows = await Promise.all(entries.map(async (rel) => {
|
|
393
|
+
try {
|
|
394
|
+
const s = await stat(resolve(ctx.handle.cwd, rel));
|
|
395
|
+
return `${rel} ${s.size} ${new Date(s.mtimeMs).toISOString()}`;
|
|
396
|
+
} catch {
|
|
397
|
+
return `${rel} `;
|
|
398
|
+
}
|
|
399
|
+
}));
|
|
400
|
+
return rows.join("\n");
|
|
363
401
|
} catch (err) {
|
|
364
402
|
const message = err instanceof Error ? err.message : String(err);
|
|
365
403
|
return `Glob error: ${message}`;
|
|
@@ -538,8 +576,8 @@ async function enumerateFiles(input, ctx) {
|
|
|
538
576
|
const root = input.path ?? ".";
|
|
539
577
|
if (input.path && !input.path.includes("*") && !input.path.includes("?")) {
|
|
540
578
|
try {
|
|
541
|
-
const
|
|
542
|
-
if (
|
|
579
|
+
const stat2 = await ctx.execution.exec(ctx.handle, `test -f ${shellQuote(input.path)} && echo file || echo dir`);
|
|
580
|
+
if (stat2.stdout.trim() === "file")
|
|
543
581
|
return [input.path];
|
|
544
582
|
} catch {
|
|
545
583
|
}
|
|
@@ -619,7 +657,7 @@ var listFiles = {
|
|
|
619
657
|
var multiEdit = {
|
|
620
658
|
spec: {
|
|
621
659
|
name: "multi_edit",
|
|
622
|
-
description: "Apply a sequential list of edits to a file atomically. Each edit operates on the result of the previous edit. All edits must succeed for any to be written. Prefer this over multiple `edit` calls when several non-overlapping changes are needed in the same file.",
|
|
660
|
+
description: "Apply a sequential list of edits to a file atomically. Each edit operates on the result of the previous edit. All edits must succeed for any to be written. Prefer this over multiple `edit` calls when several non-overlapping changes are needed in the same file. Each step tolerates `read_file` line-number prefixes (`<N>\\t\u2026`, `<N>|\u2026`, or `<N>\u2192\u2026`) in `old_string` / `new_string`.",
|
|
623
661
|
inputSchema: {
|
|
624
662
|
type: "object",
|
|
625
663
|
properties: {
|
|
@@ -680,9 +718,7 @@ var multiEdit = {
|
|
|
680
718
|
const { actual, occurrences, via } = match;
|
|
681
719
|
if (occurrences > 1 && !replaceAll)
|
|
682
720
|
return `multi_edit error: edit #${i + 1} old_string appears ${occurrences} times. Pass replace_all=true on this edit or expand old_string for uniqueness.`;
|
|
683
|
-
|
|
684
|
-
if (via === "quotes" || via === "quotes+desanitize")
|
|
685
|
-
styledReplacement = preserveQuoteStyle(actual, styledReplacement);
|
|
721
|
+
const styledReplacement = styleReplacementForVia(replacement, via, actual);
|
|
686
722
|
current = replaceAll ? current.split(actual).join(styledReplacement) : current.replace(actual, styledReplacement);
|
|
687
723
|
applied += occurrences;
|
|
688
724
|
}
|
|
@@ -781,19 +817,20 @@ var DEFAULT_IMAGE_BYTE_CAP = 5 * 1024 * 1024;
|
|
|
781
817
|
var readFile = {
|
|
782
818
|
spec: {
|
|
783
819
|
name: "read_file",
|
|
784
|
-
description: "Read a file by path. Returns lines [offset..offset+limit). Default offset=1, limit=2000. A trailing footer explains how to read the rest when truncated. Binary files return a short marker rather than mojibake.",
|
|
820
|
+
description: "Read a file by path. Returns lines [offset..offset+limit). Default offset=1, limit=2000. Each line is prefixed with its 1-indexed line number followed by a tab (e.g. `42\\tconst foo = bar`); the prefix is metadata, not part of the file. Mirrors Claude Code's `cat -n`-style compact output for token efficiency. A trailing footer explains how to read the rest when truncated. Binary files return a short marker rather than mojibake.",
|
|
785
821
|
inputSchema: {
|
|
786
822
|
type: "object",
|
|
787
823
|
properties: {
|
|
788
824
|
path: { type: "string", description: "Relative file path." },
|
|
789
825
|
offset: { type: "integer", description: "1-indexed line number to start from. Default: 1." },
|
|
790
826
|
limit: { type: "integer", description: "Max lines to return. Default: 2000. Set 0 for unlimited." },
|
|
791
|
-
maxBytes: { type: "integer", description: "Hard byte cap regardless of line count. Default: 65536. Set 0 for unlimited." }
|
|
827
|
+
maxBytes: { type: "integer", description: "Hard byte cap on file content read, regardless of line count. Default: 65536. Set 0 for unlimited. The rendered output may be slightly larger than this cap when `lineNumbers` is on (each line carries a `<N>\\t` prefix)." },
|
|
828
|
+
lineNumbers: { type: "boolean", description: "Prefix each line with its 1-indexed line number. Default: true. Override the agent-wide `behavior.readLineNumbers` for this call." }
|
|
792
829
|
},
|
|
793
830
|
required: ["path"]
|
|
794
831
|
}
|
|
795
832
|
},
|
|
796
|
-
async execute({ path, offset, limit, maxBytes }, ctx) {
|
|
833
|
+
async execute({ path, offset, limit, maxBytes, lineNumbers }, ctx) {
|
|
797
834
|
const imgMedia = imageMediaTypeFor(path);
|
|
798
835
|
if (imgMedia) {
|
|
799
836
|
const sizeCap = maxBytes !== void 0 ? normalizeInteger(maxBytes, DEFAULT_IMAGE_BYTE_CAP) : DEFAULT_IMAGE_BYTE_CAP;
|
|
@@ -827,10 +864,11 @@ var readFile = {
|
|
|
827
864
|
const offsetForKey = normalizeInteger(offset, 1);
|
|
828
865
|
const limitForKey = normalizeInteger(limit, DEFAULT_LINE_LIMIT);
|
|
829
866
|
const maxBytesForKey = normalizeInteger(maxBytes, DEFAULT_BYTE_CAP);
|
|
867
|
+
const showLineNumbers = typeof lineNumbers === "boolean" ? lineNumbers : ctx.behavior?.readLineNumbers ?? true;
|
|
830
868
|
const currentHash = readState ? hashContent(raw) : "";
|
|
831
869
|
if (readState) {
|
|
832
870
|
const prior = readState.get(absKey);
|
|
833
|
-
if (prior && prior.contentHash === currentHash && prior.offset === offsetForKey && prior.limit === limitForKey && prior.maxBytes === maxBytesForKey) {
|
|
871
|
+
if (prior && prior.contentHash === currentHash && prior.offset === offsetForKey && prior.limit === limitForKey && prior.maxBytes === maxBytesForKey && prior.lineNumbers === showLineNumbers) {
|
|
834
872
|
return `File ${path} unchanged since the previous read in this session \u2014 the prior result is still current.`;
|
|
835
873
|
}
|
|
836
874
|
}
|
|
@@ -845,10 +883,10 @@ var readFile = {
|
|
|
845
883
|
const startIdx = Math.max(0, offsetN - 1);
|
|
846
884
|
const endIdx = limitN > 0 ? Math.min(totalLines, startIdx + limitN) : totalLines;
|
|
847
885
|
let slice = lines.slice(startIdx, endIdx);
|
|
848
|
-
let bytesUsed = 0;
|
|
849
886
|
let bytesCut = false;
|
|
850
887
|
if (maxBytesN > 0) {
|
|
851
888
|
const truncatedSlice = [];
|
|
889
|
+
let bytesUsed = 0;
|
|
852
890
|
for (const line of slice) {
|
|
853
891
|
const lineBytes = Buffer2.byteLength(line) + 1;
|
|
854
892
|
if (bytesUsed + lineBytes > maxBytesN && truncatedSlice.length > 0) {
|
|
@@ -881,15 +919,16 @@ var readFile = {
|
|
|
881
919
|
bytesCut = true;
|
|
882
920
|
}
|
|
883
921
|
}
|
|
884
|
-
const body = slice.join("\n");
|
|
885
922
|
const linesReturned = slice.length;
|
|
886
923
|
const lastLineRead = startIdx + linesReturned;
|
|
924
|
+
const body = showLineNumbers ? slice.map((line, i) => `${startIdx + i + 1} ${line}`).join("\n") : slice.join("\n");
|
|
887
925
|
if (readState) {
|
|
888
926
|
readState.set(absKey, {
|
|
889
927
|
contentHash: currentHash,
|
|
890
928
|
offset: offsetN,
|
|
891
929
|
limit: limitN,
|
|
892
930
|
maxBytes: maxBytesN,
|
|
931
|
+
lineNumbers: showLineNumbers,
|
|
893
932
|
mtimeMs: Date.now()
|
|
894
933
|
});
|
|
895
934
|
}
|
|
@@ -957,37 +996,54 @@ var DEFAULT_MAX_OUTPUT_BYTES = 8192;
|
|
|
957
996
|
var shell = {
|
|
958
997
|
spec: {
|
|
959
998
|
name: "shell",
|
|
960
|
-
description: "Execute a shell command in the project root and return its combined stdout/stderr. Output is tail-priority truncated at 8 KB by default; errors and exit-code summaries live in the tail. Set maxOutputBytes=0 to disable truncation.",
|
|
999
|
+
description: "Execute a shell command in the project root and return its combined stdout/stderr. Output is tail-priority truncated at 8 KB by default; errors and exit-code summaries live in the tail. By default each call appends a `(exit N, Nms)` footer and surfaces non-empty stderr in a separate section even on success \u2014 set `metadata: false` to return only stdout. Set maxOutputBytes=0 to disable truncation.",
|
|
961
1000
|
inputSchema: {
|
|
962
1001
|
type: "object",
|
|
963
1002
|
properties: {
|
|
964
1003
|
command: { type: "string", description: "Shell command to run." },
|
|
965
1004
|
timeout: { type: "integer", description: "Per-call timeout in milliseconds." },
|
|
966
|
-
maxOutputBytes: { type: "integer", description: "Truncate combined stdout+stderr beyond this many bytes. Default: 8192. Set 0 for unlimited." }
|
|
1005
|
+
maxOutputBytes: { type: "integer", description: "Truncate combined stdout+stderr beyond this many bytes. Default: 8192. Set 0 for unlimited." },
|
|
1006
|
+
metadata: { type: "boolean", description: "Append `(exit N, Nms)` footer and surface non-empty stderr on success. Default: true." }
|
|
967
1007
|
},
|
|
968
1008
|
required: ["command"]
|
|
969
1009
|
}
|
|
970
1010
|
},
|
|
971
|
-
async execute({ command, timeout, maxOutputBytes }, ctx) {
|
|
1011
|
+
async execute({ command, timeout, maxOutputBytes, metadata }, ctx) {
|
|
972
1012
|
const execOpts = {};
|
|
973
1013
|
if (typeof timeout === "number" && Number.isFinite(timeout) && timeout > 0)
|
|
974
1014
|
execOpts.timeout = Math.max(1, Math.ceil(timeout / 1e3));
|
|
975
1015
|
const cmd = command;
|
|
1016
|
+
const wantMetadata = metadata !== false;
|
|
1017
|
+
const startedAt = Date.now();
|
|
976
1018
|
const result = await ctx.execution.exec(ctx.handle, cmd, execOpts);
|
|
1019
|
+
const durationMs = Date.now() - startedAt;
|
|
977
1020
|
const cap = normalizeCap(maxOutputBytes);
|
|
978
1021
|
const semantic = interpretShellResult(cmd, result.exitCode);
|
|
979
|
-
if (result.exitCode === 0)
|
|
980
|
-
|
|
1022
|
+
if (result.exitCode === 0) {
|
|
1023
|
+
const stdoutTail = truncateTail(result.stdout || "(no output)", cap);
|
|
1024
|
+
if (!wantMetadata)
|
|
1025
|
+
return stdoutTail;
|
|
1026
|
+
const stderrTrimmed = result.stderr.trim();
|
|
1027
|
+
const stderrSection = stderrTrimmed ? `
|
|
1028
|
+
[stderr]
|
|
1029
|
+
${truncateTail(stderrTrimmed, Math.min(cap, 2048))}` : "";
|
|
1030
|
+
return `${stdoutTail}${stderrSection}
|
|
1031
|
+
(exit 0, ${durationMs}ms)`;
|
|
1032
|
+
}
|
|
981
1033
|
if (!semantic.isError) {
|
|
982
1034
|
const body = (result.stdout || result.stderr || "").trim();
|
|
983
1035
|
const tail = truncateTail(body, cap);
|
|
984
|
-
const
|
|
1036
|
+
const semanticFooter = semantic.message ? `
|
|
985
1037
|
(${semantic.message})` : "";
|
|
986
|
-
|
|
1038
|
+
const timingFooter = wantMetadata ? `
|
|
1039
|
+
(exit ${result.exitCode}, ${durationMs}ms)` : "";
|
|
1040
|
+
const head = tail.length > 0 ? tail : semantic.message ?? "(no output)";
|
|
1041
|
+
return `${head}${semanticFooter}${timingFooter}`;
|
|
987
1042
|
}
|
|
988
1043
|
const combined = `${result.stdout}
|
|
989
1044
|
${result.stderr}`.trim();
|
|
990
|
-
|
|
1045
|
+
const header = wantMetadata ? `Exit code ${result.exitCode} (${durationMs}ms)` : `Exit code ${result.exitCode}`;
|
|
1046
|
+
return `${header}
|
|
991
1047
|
${truncateTail(combined, cap)}`;
|
|
992
1048
|
}
|
|
993
1049
|
};
|
|
@@ -1568,6 +1624,74 @@ function applyTailCompaction(messages, threshold, keepTurns) {
|
|
|
1568
1624
|
}
|
|
1569
1625
|
return changed ? out : messages;
|
|
1570
1626
|
}
|
|
1627
|
+
var STALE_READ_STUB = "[\u2026elided: file edited later in this run; re-read if still needed.]";
|
|
1628
|
+
function applyStaleReadElision(messages) {
|
|
1629
|
+
if (messages.length === 0)
|
|
1630
|
+
return messages;
|
|
1631
|
+
const resultByCallId = /* @__PURE__ */ new Map();
|
|
1632
|
+
for (const msg of messages) {
|
|
1633
|
+
for (const block of msg.content) {
|
|
1634
|
+
if (block.type === "tool_result" && typeof block.output === "string")
|
|
1635
|
+
resultByCallId.set(block.callId, block.output);
|
|
1636
|
+
}
|
|
1637
|
+
}
|
|
1638
|
+
const maxMutationIdxByPath = /* @__PURE__ */ new Map();
|
|
1639
|
+
const readCallInfo = /* @__PURE__ */ new Map();
|
|
1640
|
+
for (let i = 0; i < messages.length; i++) {
|
|
1641
|
+
for (const block of messages[i].content) {
|
|
1642
|
+
if (block.type !== "tool_call")
|
|
1643
|
+
continue;
|
|
1644
|
+
const path = block.input.path;
|
|
1645
|
+
if (typeof path !== "string")
|
|
1646
|
+
continue;
|
|
1647
|
+
if (block.name === "read_file") {
|
|
1648
|
+
readCallInfo.set(block.id, { path, msgIdx: i });
|
|
1649
|
+
continue;
|
|
1650
|
+
}
|
|
1651
|
+
const isEdit = block.name === "edit" || block.name === "multi_edit";
|
|
1652
|
+
const isWrite = block.name === "write_file";
|
|
1653
|
+
if (!isEdit && !isWrite)
|
|
1654
|
+
continue;
|
|
1655
|
+
const result = resultByCallId.get(block.id);
|
|
1656
|
+
if (typeof result !== "string")
|
|
1657
|
+
continue;
|
|
1658
|
+
const succeeded = isEdit ? result.startsWith("Edited ") : result.startsWith("Created ") || result.startsWith("Updated ");
|
|
1659
|
+
if (!succeeded)
|
|
1660
|
+
continue;
|
|
1661
|
+
const prior = maxMutationIdxByPath.get(path);
|
|
1662
|
+
if (prior === void 0 || i > prior)
|
|
1663
|
+
maxMutationIdxByPath.set(path, i);
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
if (maxMutationIdxByPath.size === 0)
|
|
1667
|
+
return messages;
|
|
1668
|
+
const staleCallIds = /* @__PURE__ */ new Set();
|
|
1669
|
+
for (const [callId, info] of readCallInfo) {
|
|
1670
|
+
const lastMutationIdx = maxMutationIdxByPath.get(info.path);
|
|
1671
|
+
if (typeof lastMutationIdx === "number" && info.msgIdx < lastMutationIdx)
|
|
1672
|
+
staleCallIds.add(callId);
|
|
1673
|
+
}
|
|
1674
|
+
if (staleCallIds.size === 0)
|
|
1675
|
+
return messages;
|
|
1676
|
+
let changed = false;
|
|
1677
|
+
const out = messages.slice();
|
|
1678
|
+
for (let i = 0; i < out.length; i++) {
|
|
1679
|
+
const msg = out[i];
|
|
1680
|
+
let msgChanged = false;
|
|
1681
|
+
const newContent = msg.content.map((block) => {
|
|
1682
|
+
if (block.type !== "tool_result" || !staleCallIds.has(block.callId))
|
|
1683
|
+
return block;
|
|
1684
|
+
if (block.output === STALE_READ_STUB)
|
|
1685
|
+
return block;
|
|
1686
|
+
msgChanged = true;
|
|
1687
|
+
changed = true;
|
|
1688
|
+
return { ...block, output: STALE_READ_STUB };
|
|
1689
|
+
});
|
|
1690
|
+
if (msgChanged)
|
|
1691
|
+
out[i] = { ...msg, content: newContent };
|
|
1692
|
+
}
|
|
1693
|
+
return changed ? out : messages;
|
|
1694
|
+
}
|
|
1571
1695
|
function sanitizeStoredToolResults(provider, messages) {
|
|
1572
1696
|
if (provider.meta.capabilities?.vision !== false)
|
|
1573
1697
|
return messages;
|
|
@@ -1675,7 +1799,9 @@ function wrapProviderError(err, ctx) {
|
|
|
1675
1799
|
}
|
|
1676
1800
|
async function executeTurn(ctx, turn) {
|
|
1677
1801
|
const turnId = await ctx.generateTurnId();
|
|
1678
|
-
|
|
1802
|
+
let canonicalMessages = turnsToMessages(ctx.turns);
|
|
1803
|
+
if (ctx.elideStaleReads === true)
|
|
1804
|
+
canonicalMessages = applyStaleReadElision(canonicalMessages);
|
|
1679
1805
|
const wireMessages = rewriteMessagesToWire(canonicalMessages, ctx.aliasMaps);
|
|
1680
1806
|
let sanitizedMessages = sanitizeStoredToolResults(ctx.provider, wireMessages);
|
|
1681
1807
|
if (ctx.compactStrategy === "tail") {
|
|
@@ -2092,26 +2218,13 @@ async function executeToolsParallel(ctx, toolCalls, turnId) {
|
|
|
2092
2218
|
}
|
|
2093
2219
|
|
|
2094
2220
|
// src/prompt.ts
|
|
2095
|
-
function canonicalizePrompt(prompt
|
|
2221
|
+
function canonicalizePrompt(prompt) {
|
|
2096
2222
|
if (prompt === void 0)
|
|
2097
2223
|
return void 0;
|
|
2098
2224
|
if (typeof prompt === "string") {
|
|
2099
|
-
|
|
2100
|
-
if (prompt.length === 0 && !hasImages)
|
|
2225
|
+
if (prompt.length === 0)
|
|
2101
2226
|
return void 0;
|
|
2102
|
-
|
|
2103
|
-
if (prompt.length > 0)
|
|
2104
|
-
parts.push({ type: "text", text: prompt });
|
|
2105
|
-
if (hasImages) {
|
|
2106
|
-
for (const img of legacyImages) {
|
|
2107
|
-
parts.push({
|
|
2108
|
-
type: "image",
|
|
2109
|
-
mediaType: img.source.media_type,
|
|
2110
|
-
data: img.source.data
|
|
2111
|
-
});
|
|
2112
|
-
}
|
|
2113
|
-
}
|
|
2114
|
-
return parts;
|
|
2227
|
+
return [{ type: "text", text: prompt }];
|
|
2115
2228
|
}
|
|
2116
2229
|
if (prompt.length === 0)
|
|
2117
2230
|
return void 0;
|
|
@@ -2311,7 +2424,9 @@ function resolveBehavior(agentBehavior, runBehavior) {
|
|
|
2311
2424
|
dedupReads: runBehavior?.dedupReads ?? agentBehavior?.dedupReads,
|
|
2312
2425
|
dedupTools: runBehavior?.dedupTools ?? agentBehavior?.dedupTools,
|
|
2313
2426
|
requireReadBeforeEdit: runBehavior?.requireReadBeforeEdit ?? agentBehavior?.requireReadBeforeEdit,
|
|
2314
|
-
toolBudgets: runBehavior?.toolBudgets ?? agentBehavior?.toolBudgets
|
|
2427
|
+
toolBudgets: runBehavior?.toolBudgets ?? agentBehavior?.toolBudgets,
|
|
2428
|
+
readLineNumbers: runBehavior?.readLineNumbers ?? agentBehavior?.readLineNumbers,
|
|
2429
|
+
elideStaleReads: runBehavior?.elideStaleReads ?? agentBehavior?.elideStaleReads
|
|
2315
2430
|
};
|
|
2316
2431
|
}
|
|
2317
2432
|
function createAgent({ provider, name: agentName, system: agentSystem, tools: agentTools, toolAliases, behavior: agentBehavior, execution, mcpServers, session, skills: agentSkills, mcpConnector, eager }) {
|
|
@@ -2374,8 +2489,8 @@ function createAgent({ provider, name: agentName, system: agentSystem, tools: ag
|
|
|
2374
2489
|
options.signal.addEventListener("abort", onExternalAbort, { once: true });
|
|
2375
2490
|
}
|
|
2376
2491
|
}
|
|
2377
|
-
idlePromise = new Promise((
|
|
2378
|
-
idleResolve =
|
|
2492
|
+
idlePromise = new Promise((resolve2) => {
|
|
2493
|
+
idleResolve = resolve2;
|
|
2379
2494
|
});
|
|
2380
2495
|
const childrenStats = [];
|
|
2381
2496
|
const unregisterSpawnHook = hooks.hook("spawn:complete", (ctx) => {
|
|
@@ -2404,7 +2519,7 @@ function createAgent({ provider, name: agentName, system: agentSystem, tools: ag
|
|
|
2404
2519
|
await warmup();
|
|
2405
2520
|
}
|
|
2406
2521
|
if (!skillsDisabled && skillsConfig && !resolvedSkills) {
|
|
2407
|
-
const bundle = await
|
|
2522
|
+
const bundle = await resolveSkills(skillsConfig);
|
|
2408
2523
|
resolvedSkills = bundle.skills;
|
|
2409
2524
|
skillsCleanup = bundle.cleanup;
|
|
2410
2525
|
await hooks.callHook("skills:resolve", { skills: resolvedSkills });
|
|
@@ -2439,7 +2554,7 @@ function createAgent({ provider, name: agentName, system: agentSystem, tools: ag
|
|
|
2439
2554
|
const thinking = options.thinking ?? "off";
|
|
2440
2555
|
const model = options.model ?? provider.meta.defaultModel;
|
|
2441
2556
|
const resolvedBehavior = resolveBehavior(agentBehavior, options.behavior);
|
|
2442
|
-
const { toolExecution, maxTurns, maxTokens, thinkingBudget, schema, cache, toolOutputBudget, compactStrategy, compactThreshold, compactKeepTurns, thinkingDecay, dedupTools, toolBudgets } = resolvedBehavior;
|
|
2557
|
+
const { toolExecution, maxTurns, maxTokens, thinkingBudget, schema, cache, toolOutputBudget, compactStrategy, compactThreshold, compactKeepTurns, thinkingDecay, dedupTools, toolBudgets, elideStaleReads } = resolvedBehavior;
|
|
2443
2558
|
let system = options.system || agentSystem || "You are a helpful assistant.";
|
|
2444
2559
|
if (skillsCatalog) {
|
|
2445
2560
|
system = `${system}
|
|
@@ -2488,7 +2603,7 @@ ${skillsCatalog}`;
|
|
|
2488
2603
|
if (options.system) {
|
|
2489
2604
|
await hooks.callHook("system:before", { system: options.system });
|
|
2490
2605
|
}
|
|
2491
|
-
const promptParts = canonicalizePrompt(options.prompt
|
|
2606
|
+
const promptParts = canonicalizePrompt(options.prompt);
|
|
2492
2607
|
if (promptParts) {
|
|
2493
2608
|
const promptMsg = buildPromptMessage(provider, promptParts);
|
|
2494
2609
|
turns.push({
|
|
@@ -2591,6 +2706,7 @@ ${skillsCatalog}`;
|
|
|
2591
2706
|
compactStrategy,
|
|
2592
2707
|
compactThreshold,
|
|
2593
2708
|
compactKeepTurns,
|
|
2709
|
+
...elideStaleReads !== void 0 ? { elideStaleReads } : {},
|
|
2594
2710
|
...thinkingDecay !== void 0 ? { thinkingDecay } : {},
|
|
2595
2711
|
runStartMs,
|
|
2596
2712
|
runToolCounts: {}
|
|
@@ -2838,9 +2954,9 @@ async function raceWithTimeout(task, timeoutMs) {
|
|
|
2838
2954
|
return task;
|
|
2839
2955
|
let timer;
|
|
2840
2956
|
try {
|
|
2841
|
-
return await new Promise((
|
|
2957
|
+
return await new Promise((resolve2, reject) => {
|
|
2842
2958
|
timer = setTimeout(() => reject(new SpawnTimeoutError(timeoutMs)), timeoutMs);
|
|
2843
|
-
task.then(
|
|
2959
|
+
task.then(resolve2, reject);
|
|
2844
2960
|
});
|
|
2845
2961
|
} finally {
|
|
2846
2962
|
if (timer)
|
|
@@ -3044,7 +3160,6 @@ function createSpawnTool(options = {}) {
|
|
|
3044
3160
|
}
|
|
3045
3161
|
};
|
|
3046
3162
|
}
|
|
3047
|
-
var spawn = createSpawnTool();
|
|
3048
3163
|
|
|
3049
3164
|
// src/tools/write-file.ts
|
|
3050
3165
|
import { Buffer as Buffer4 } from "buffer";
|
|
@@ -3092,6 +3207,5 @@ export {
|
|
|
3092
3207
|
readFile,
|
|
3093
3208
|
shell,
|
|
3094
3209
|
createSpawnTool,
|
|
3095
|
-
spawn,
|
|
3096
3210
|
writeFile
|
|
3097
3211
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { d as AgentHooks } from './agent-
|
|
2
|
-
export {
|
|
1
|
+
import { d as AgentHooks } from './agent-DqEkutk4.js';
|
|
2
|
+
export { ab as ActivationVia, ac as ActiveSkill, A as Agent, a as AgentAbortedError, b as AgentBehavior, c as AgentContextExceededError, e as AgentOptions, f as AgentProviderError, g as AgentRunOptions, h as AgentStats, i as AgentToolNotAllowedError, j as AnthropicParams, C as CONTEXT_EXCEEDED_MESSAGE_PATTERNS, k as CerebrasParams, m as ClassifiedError, n as ClassifiedErrorKind, o as CreateSessionOptions, ad as DeactivationReason, ae as FileMapAdapter, af as FileMapStoreOptions, M as McpConnection, p as McpServerConfig, q as McpToolHookContext, O as OAuthRefreshHookContext, ag as OpenAICompatAuthHeader, ah as OpenAICompatHttpError, ai as OpenAICompatParams, r as OpenAIParams, s as OpenRouterParams, P as PromptDocumentPart, t as PromptImagePart, u as PromptPart, v as PromptTextPart, w as Provider, x as ProviderCapabilities, R as RemoteStoreOptions, y as RunHookMap, S as Session, z as SessionContentBlock, B as SessionData, D as SessionEndStatus, E as SessionHookContext, F as SessionMessage, G as SessionRun, H as SessionStore, I as SessionTurn, aj as SkillActivationState, ak as SkillActivationStateOptions, J as SkillConfig, al as SkillDiagnostic, K as SkillResource, am as SkillSource, L as SkillsConfig, N as SpawnHookContext, Q as StreamCallbacks, T as StreamHookContext, U as StreamOptions, V as ThinkingLevel, W as ToolCall, X as ToolContext, Y as ToolDef, Z as ToolExecutionMode, _ as ToolHookContext, $ as ToolMap, a0 as ToolResult, a1 as ToolResultContent, a2 as ToolResultImageContent, a3 as ToolResultTextContent, a4 as ToolSpec, a5 as TurnFinishReason, a6 as TurnResult, a7 as TurnUsage, an as anthropic, ao as autoDetectAndConvert, ap as cerebras, aq as classifyOpenAICompatError, ar as connectMcpServers, as as createAgent, at as createFileMapStore, au as createMemoryStore, av as createRemoteStore, aw as createSession, ax as createSkillActivationState, ay as fromAnthropic, az as fromOpenAI, aA as loadSession, aB as mapOAIFinishReason, a8 as matchesContextExceeded, aC as normalizeMcpBlocks, aD as normalizeMcpServers, aE as openai, aF as openaiCompat, aG as openrouter, aH as resultToString, aI as toAnthropic, aJ as toOpenAI, aK as toTypedError, a9 as toolOutputByteLength, aa as toolResultToText } from './agent-DqEkutk4.js';
|
|
3
3
|
export { createDockerContext, createProcessContext } from './contexts.js';
|
|
4
4
|
export { S as SandboxProvider, c as createSandboxContext } from './sandbox-CLghrTLi.js';
|
|
5
5
|
export { C as ContextCapabilities, a as ContextType, E as ExecResult, b as ExecutionContext, c as ExecutionHandle, S as SpawnConfig } from './types-vA1a_ZX7.js';
|
|
6
6
|
export { Preset, basic, basicTools, definePreset } from './presets.js';
|
|
7
7
|
export { IMPLICITLY_ALLOWED_SKILL_TOOLS, SkillValidationIssue, SkillValidationResult, SourcedScanPath, buildCatalog, defineSkill, discoverSkills, installAllowedToolsGate, interpolateShellCommands, isToolAllowedByUnion, matchesAllowedTool, parseAllowedToolPattern, parseSkillFile, resolveSkills, validateResourcePath, validateSkillForWrite, validateSkillName, writeSkillToDisk, writeSkillsToDisk } from './skills.js';
|
|
8
|
-
export { S as SkillsReadToolOptions, a as SkillsRunScriptToolOptions, b as SkillsUseToolOptions, c as createSkillsReadTool, d as createSkillsRunScriptTool, e as createSkillsUseTool, f as edit, g as glob, h as grep, m as multiEdit } from './skills-use-
|
|
9
|
-
export { C as ChildAgent, I as InteractionToolOptions, S as SpawnToolOptions, a as SpawnToolState, V as ValidationResult, c as createInteractionTool, b as createSpawnTool,
|
|
8
|
+
export { S as SkillsReadToolOptions, a as SkillsRunScriptToolOptions, b as SkillsUseToolOptions, c as createSkillsReadTool, d as createSkillsRunScriptTool, e as createSkillsUseTool, f as edit, g as glob, h as grep, m as multiEdit } from './skills-use-WbOh6TuS.js';
|
|
9
|
+
export { C as ChildAgent, I as InteractionToolOptions, S as SpawnToolOptions, a as SpawnToolState, V as ValidationResult, c as createInteractionTool, b as createSpawnTool, v as validateToolArgs } from './validation-DTbkLXbd.js';
|
|
10
10
|
import { Hookable } from 'hookable';
|
|
11
11
|
import '@modelcontextprotocol/sdk/client/index.js';
|
|
12
12
|
|
package/dist/index.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
defineSkill
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-LIVB5W4B.js";
|
|
4
4
|
import {
|
|
5
5
|
anthropic,
|
|
6
6
|
cerebras,
|
|
7
7
|
openai,
|
|
8
8
|
openrouter
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-W57VY6DJ.js";
|
|
10
10
|
import {
|
|
11
11
|
basicTools,
|
|
12
12
|
basic_default,
|
|
13
13
|
definePreset
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-3D5Q527Y.js";
|
|
15
15
|
import {
|
|
16
16
|
createAgent,
|
|
17
17
|
createInteractionTool,
|
|
@@ -23,9 +23,8 @@ import {
|
|
|
23
23
|
glob,
|
|
24
24
|
grep,
|
|
25
25
|
multiEdit,
|
|
26
|
-
spawn,
|
|
27
26
|
validateToolArgs
|
|
28
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-Z2E5QN5X.js";
|
|
29
28
|
import {
|
|
30
29
|
IMPLICITLY_ALLOWED_SKILL_TOOLS,
|
|
31
30
|
buildCatalog,
|
|
@@ -43,7 +42,7 @@ import {
|
|
|
43
42
|
validateSkillName,
|
|
44
43
|
writeSkillToDisk,
|
|
45
44
|
writeSkillsToDisk
|
|
46
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-X3VOTPVM.js";
|
|
47
46
|
import {
|
|
48
47
|
createDockerContext,
|
|
49
48
|
createProcessContext,
|
|
@@ -76,7 +75,7 @@ import {
|
|
|
76
75
|
openaiCompat,
|
|
77
76
|
toAnthropic,
|
|
78
77
|
toOpenAI
|
|
79
|
-
} from "./chunk-
|
|
78
|
+
} from "./chunk-4ILGBQ23.js";
|
|
80
79
|
import {
|
|
81
80
|
AgentAbortedError,
|
|
82
81
|
AgentContextExceededError,
|
|
@@ -255,7 +254,6 @@ export {
|
|
|
255
254
|
parseSkillFile,
|
|
256
255
|
resolveSkills,
|
|
257
256
|
resultToString,
|
|
258
|
-
spawn,
|
|
259
257
|
toAnthropic,
|
|
260
258
|
toOpenAI,
|
|
261
259
|
toTypedError,
|
package/dist/mcp.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import 'hookable';
|
|
2
|
-
export { M as McpConnection, p as McpServerConfig,
|
|
2
|
+
export { M as McpConnection, p as McpServerConfig, ar as connectMcpServers, aC as normalizeMcpBlocks, aD as normalizeMcpServers, aH as resultToString } from './agent-DqEkutk4.js';
|
|
3
3
|
import '@modelcontextprotocol/sdk/client/index.js';
|
|
4
4
|
import './types-vA1a_ZX7.js';
|
package/dist/presets.d.ts
CHANGED
package/dist/presets.js
CHANGED
|
@@ -2,9 +2,9 @@ import {
|
|
|
2
2
|
basicTools,
|
|
3
3
|
basic_default,
|
|
4
4
|
definePreset
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-3D5Q527Y.js";
|
|
6
|
+
import "./chunk-Z2E5QN5X.js";
|
|
7
|
+
import "./chunk-X3VOTPVM.js";
|
|
8
8
|
import "./chunk-UD25QF3H.js";
|
|
9
9
|
import "./chunk-7H34OFDA.js";
|
|
10
10
|
import "./chunk-JH6IAAFA.js";
|