@j0hanz/filesystem-mcp 2.9.0 → 2.9.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/README.md +1 -1
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +7 -1
- package/dist/core/errors.js.map +1 -1
- package/dist/core/file-uri.d.ts.map +1 -1
- package/dist/core/file-uri.js +2 -2
- package/dist/core/file-uri.js.map +1 -1
- package/dist/core/glob.d.ts +7 -0
- package/dist/core/glob.d.ts.map +1 -1
- package/dist/core/glob.js +35 -3
- package/dist/core/glob.js.map +1 -1
- package/dist/core/search.d.ts.map +1 -1
- package/dist/core/search.js +2 -0
- package/dist/core/search.js.map +1 -1
- package/dist/core/util.d.ts +6 -0
- package/dist/core/util.d.ts.map +1 -1
- package/dist/core/util.js +8 -0
- package/dist/core/util.js.map +1 -1
- package/dist/resources.d.ts.map +1 -1
- package/dist/resources.js +2 -2
- package/dist/resources.js.map +1 -1
- package/dist/tools/list.d.ts.map +1 -1
- package/dist/tools/list.js +9 -6
- package/dist/tools/list.js.map +1 -1
- package/dist/tools/read.d.ts.map +1 -1
- package/dist/tools/read.js +7 -11
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/replace-text.d.ts.map +1 -1
- package/dist/tools/replace-text.js +1 -0
- package/dist/tools/replace-text.js.map +1 -1
- package/package.json +1 -1
package/dist/tools/list.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { stat } from 'node:fs/promises';
|
|
2
1
|
import { basename, posix } from 'node:path';
|
|
3
2
|
import * as z from 'zod/v4';
|
|
4
3
|
import { processEntriesConcurrently, withAbort } from "../core/concurrency.js";
|
|
@@ -59,6 +58,7 @@ async function collect(rootPath, options) {
|
|
|
59
58
|
skipIgnored: !options.includeIgnored,
|
|
60
59
|
...(ceiling !== undefined ? { ignoreCeiling: ceiling } : {}),
|
|
61
60
|
signal: options.signal,
|
|
61
|
+
pathGuard: options.pathGuard,
|
|
62
62
|
includeHidden: options.includeHidden,
|
|
63
63
|
baseNameMatch: false,
|
|
64
64
|
// ListInputSchema.maxDepth is 1-based (1 = top-level only); the shared
|
|
@@ -80,17 +80,19 @@ async function collect(rootPath, options) {
|
|
|
80
80
|
const entryType = resolveEntryType(entry.dirent);
|
|
81
81
|
const relPath = toPosixRelative(rootPath, entry.path);
|
|
82
82
|
const name = basename(relPath);
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
83
|
+
// A sensitive-named directory never reaches the walk (globEntries
|
|
84
|
+
// prunes it via pathGuard), so no ancestor re-check is needed here.
|
|
87
85
|
const accessible = await options.pathGuard.isEntryAccessible(entry.path);
|
|
88
86
|
if (!accessible)
|
|
89
87
|
return;
|
|
90
88
|
let size;
|
|
91
89
|
if (wantSizes && entryType === 'file') {
|
|
92
90
|
try {
|
|
93
|
-
|
|
91
|
+
// Race the abort from the first await: the guarded stat validates the
|
|
92
|
+
// path before statting, and that validation is not abort-aware, so
|
|
93
|
+
// the race must wrap the whole call.
|
|
94
|
+
const statted = await withAbort(options.fs.stat(entry.path, { signal: options.signal }), options.signal);
|
|
95
|
+
size = statted.stats.size;
|
|
94
96
|
}
|
|
95
97
|
catch (error) {
|
|
96
98
|
rethrowIfAborted(error);
|
|
@@ -243,6 +245,7 @@ export const LIST = defineTool({
|
|
|
243
245
|
includeHidden: args.includeHidden,
|
|
244
246
|
includeIgnored: args.includeIgnored,
|
|
245
247
|
signal: ctx.signal,
|
|
248
|
+
fs: ctx.fs,
|
|
246
249
|
pathGuard: ctx.fs.pathGuard,
|
|
247
250
|
entryCap: MAX_LIST_ENTRIES,
|
|
248
251
|
onProgress: ctx.onProgress,
|
package/dist/tools/list.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/tools/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAE5C,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAAE,0BAA0B,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACvF,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAkB,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EAAkB,gBAAgB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE1F,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,eAAe,EACf,YAAY,EACZ,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,cAAc,EACd,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAiCzC,SAAS,aAAa,CAAC,IAAe;IACpC,IAAI,IAAI,KAAK,WAAW;QAAE,OAAO,CAAC,CAAC;IACnC,OAAO,CAAC,CAAC;AACX,CAAC;AAED,4EAA4E;AAC5E,6EAA6E;AAC7E,SAAS,eAAe,CAAC,MAAuB;IAC9C,OAAO,CAAC,CAAiB,EAAE,CAAiB,EAAU,EAAE;QACtD,MAAM,MAAM,GAAG,CAAC,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,CAAC,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAC/C,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACrE,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACrE,IAAI,OAAO,KAAK,OAAO;YAAE,OAAO,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAC/D,MAAM,QAAQ,GAAG,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC/D,IAAI,QAAQ,KAAK,CAAC;YAAE,OAAO,QAAQ,CAAC;QACpC,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YACtB,MAAM,QAAQ,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;YAC/C,IAAI,QAAQ,KAAK,CAAC;gBAAE,OAAO,QAAQ,CAAC;QACtC,CAAC;QACD,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,OAAO,CAAC,QAAgB,EAAE,OAAuB;IAC9D,MAAM,OAAO,GAAqB,EAAE,CAAC;IACrC,MAAM,SAAS,GAAG,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,CAAC;IACpE,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,gBAAgB,GAAG,CAAC,CAAC;IACzB,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,UAA6B,CAAC;IAClC,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IAClE,MAAM,UAAU,GAAG,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACnD,MAAM,QAAQ,GAAG,GAAS,EAAE;QAC1B,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACzB,IAAI,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,QAAQ;YAAE,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAC3E,CAAC,CAAC;IAEF,MAAM,0BAA0B,CAC9B,WAAW,CAAC;QACV,GAAG,EAAE,QAAQ;QACb,OAAO,EAAE,MAAM;QACf,WAAW,EAAE,CAAC,OAAO,CAAC,cAAc;QACpC,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5D,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,aAAa,EAAE,KAAK;QACpB,uEAAuE;QACvE,+EAA+E;QAC/E,0EAA0E;QAC1E,QAAQ,EAAE,OAAO,CAAC,QAAQ,GAAG,CAAC;QAC9B,SAAS,EAAE,KAAK;KACjB,CAAC,EACF;QACE,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,WAAW,EAAE,oBAAoB;QACjC,OAAO,EAAE,GAAG,EAAE;YACZ,OAAO,EAAE,CAAC;YACV,OAAO,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QAC3C,CAAC;QACD,OAAO,EAAE,CAAC,UAAU,EAAE,GAAG,EAAE,EAAE;YAC3B,UAAU,KAAK,qBAAqB,CAAC,GAAG,CAAC,CAAC;QAC5C,CAAC;QACD,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE;YACpC,MAAM,SAAS,GAAc,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAC5D,MAAM,OAAO,GAAG,eAAe,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YACtD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC/B,KAAK,IAAI,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,GAAG,KAAK,GAAG,EAAE,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC7E,IAAI,OAAO,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,QAAQ,IAAI,GAAG,EAAE,CAAC;oBAAE,OAAO;YAClE,CAAC;YAED,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACzE,IAAI,CAAC,UAAU;gBAAE,OAAO;YAExB,IAAI,IAAwB,CAAC;YAC7B,IAAI,SAAS,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;gBACtC,IAAI,CAAC;oBACH,IAAI,GAAG,CAAC,MAAM,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;gBAClE,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,gBAAgB,CAAC,KAAK,CAAC,CAAC;oBACxB,uFAAuF;gBACzF,CAAC;YACH,CAAC;YAED,YAAY,EAAE,CAAC;YACf,IAAI,SAAS,KAAK,WAAW,EAAE,CAAC;gBAC9B,gBAAgB,EAAE,CAAC;YACrB,CAAC;iBAAM,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;gBAChC,UAAU,EAAE,CAAC;gBACb,IAAI,IAAI,KAAK,SAAS;oBAAE,UAAU,IAAI,IAAI,CAAC;YAC7C,CAAC;YAED,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI;gBACJ,YAAY,EAAE,OAAO;gBACrB,IAAI,EAAE,SAAS;gBACf,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACxC,CAAC,CAAC;YACH,qEAAqE;YACrE,uEAAuE;YACvE,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,QAAQ,GAAG,CAAC;gBAAE,QAAQ,EAAE,CAAC;QACzD,CAAC;KACF,CACF,CAAC;IAEF,IAAI,UAAU,KAAK,SAAS;QAAE,MAAM,UAAU,CAAC;IAC/C,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;IAChC,QAAQ,EAAE,CAAC;IAEX,OAAO;QACL,OAAO;QACP,YAAY;QACZ,UAAU;QACV,gBAAgB;QAChB,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACrC,CAAC;AACJ,CAAC;AAED,MAAM,GAAG,GAAG,MAAM,CAAC;AACnB,MAAM,KAAK,GAAG,MAAM,CAAC;AACrB,MAAM,IAAI,GAAG,MAAM,CAAC;AACpB,MAAM,MAAM,GAAG,MAAM,CAAC;AAEtB;;;;GAIG;AACH,SAAS,UAAU,CAAC,SAAoB,EAAE,GAAW;IACnD,MAAM,KAAK,GAAG,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACzC,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/D,CAAC;AAED,SAAS,cAAc,CACrB,QAAgB,EAChB,IAA+B,EAC/B,IAAmB;IAEnB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,QAAQ,CAAC;IAEvC,2EAA2E;IAC3E,8EAA8E;IAC9E,2EAA2E;IAC3E,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;IACjE,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IAC1B,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;QACzB,KACE,IAAI,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,EAC3C,GAAG,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAChC,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EACxB,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACjB,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,YAAY,EAAE,GAAG,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;QACpF,CAAC;IACH,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAE3C,+BAA+B;IAC/B,MAAM,UAAU,GAAG,IAAI,GAAG,EAA4B,CAAC;IACvD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,KAAK,GAAG,KAAK,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAClD,MAAM,SAAS,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACzE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC;YAAE,UAAU,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC3C,IAAI,QAAQ;YAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC;IAED,MAAM,KAAK,GAAa,CAAC,QAAQ,CAAC,CAAC;IAEnC,SAAS,cAAc,CAAC,SAAiB,EAAE,MAAc;QACvD,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC3C,IAAI,CAAC,QAAQ;YAAE,OAAO;QAEtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACzC,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YAC1B,IAAI,CAAC,KAAK;gBAAE,SAAS;YACrB,MAAM,MAAM,GAAG,CAAC,KAAK,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;YACzC,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;YACvC,MAAM,QAAQ,GACZ,IAAI,CAAC,YAAY,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1F,KAAK,CAAC,IAAI,CACR,MAAM,GAAG,SAAS,GAAG,KAAK,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,QAAQ,CACrF,CAAC;YAEF,MAAM,QAAQ,GAAG,KAAK,CAAC,YAAY,CAAC;YACpC,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACrD,cAAc,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAED,cAAc,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IACvB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,2FAA2F;AAC3F,SAAS,WAAW,CAAC,QAA0B,EAAE,UAAkB;IACjE,OAAO,UAAU,WAAW,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,KAAK,WAAW,CACvE,QAAQ,CAAC,gBAAgB,EACzB,WAAW,CACZ,KAAK,cAAc,CAAC,UAAU,CAAC,QAAQ,CAAC;AAC3C,CAAC;AAED,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAE7B,MAAM,eAAe,GAAG,CAAC,CAAC,YAAY,CAAC;IACrC,IAAI,EAAE,YAAY,CAAC,QAAQ,CAAC,iDAAiD,CAAC;IAC9E,QAAQ,EAAE,WAAW,CAAC,GAAG,CAAC,cAAc,CAAC;SACtC,OAAO,CAAC,kBAAkB,CAAC;SAC3B,QAAQ,CACP,6CAA6C,MAAM,CAAC,kBAAkB,CAAC,gDAAgD,CACxH;IACH,UAAU,EAAE,WAAW,CAAC,GAAG,CAAC,gBAAgB,CAAC;SAC1C,OAAO,CAAC,oBAAoB,CAAC;SAC7B,QAAQ,CACP,uBAAuB,MAAM,CAAC,oBAAoB,CAAC,oGAAoG,CACxJ;IACH,aAAa,EAAE,aAAa;IAC5B,cAAc,EAAE,cAAc;IAC9B,YAAY,EAAE,mBAAmB,CAC/B,mEAAmE,CACpE;IACD,MAAM,EAAE,CAAC;SACN,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;SACtB,QAAQ,EAAE;SACV,OAAO,CAAC,MAAM,CAAC;SACf,QAAQ,CAAC,qEAAqE,CAAC;IAClF,MAAM,EAAE,YAAY;CACrB,CAAC,CAAC;AAiBH,MAAM,CAAC,MAAM,IAAI,GAAG,UAAU,CAAqC;IACjE,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,MAAM;IACb,WAAW,EACT,mFAAmF;QACnF,0DAA0D;IAC5D,KAAK,EAAE,eAAe;IACtB,YAAY,EAAE,IAAI;IAClB,QAAQ,EAAE,IAAI;IACd,gBAAgB,EAAE,SAAS,CAAC,aAAa;IACzC,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACnB,KAAK,EAAE,MAAM;QACb,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG;KAC/C,CAAC;IACF,QAAQ,EAAE,eAAe;IACzB,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;QACvB,MAAM,YAAY,GAAG,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnE,MAAM,UAAU,GAAkB,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;QAC3F,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAuD;YACjF,KAAK,EAAE,GAAG,CAAC,SAAS;YACpB,QAAQ,EAAE,YAAY,CAAC,MAAM,EAAE,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;YACzF,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,QAAQ,EAAE,IAAI,CAAC,UAAU;YACzB,OAAO,EAAE,KAAK,IAAI,EAAE;gBAClB,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,yBAAyB,CAAC,YAAY,CAAC,CAAC;gBAChF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,QAAQ,EAAE;oBACrC,GAAG,UAAU;oBACb,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,aAAa,EAAE,IAAI,CAAC,aAAa;oBACjC,cAAc,EAAE,IAAI,CAAC,cAAc;oBACnC,MAAM,EAAE,GAAG,CAAC,MAAM;oBAClB,SAAS,EAAE,GAAG,CAAC,EAAE,CAAC,SAAS;oBAC3B,QAAQ,EAAE,gBAAgB;oBAC1B,UAAU,EAAE,GAAG,CAAC,UAAU;iBAC3B,CAAC,CAAC;gBACH,OAAO;oBACL,KAAK,EAAE,MAAM,CAAC,OAAO;oBACrB,QAAQ,EAAE;wBACR,IAAI,EAAE,QAAQ;wBACd,YAAY,EAAE,MAAM,CAAC,YAAY;wBACjC,UAAU,EAAE,MAAM,CAAC,UAAU;wBAC7B,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;wBACzC,GAAG,CAAC,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;qBAC9E;oBACD,SAAS,EAAE,MAAM,CAAC,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM;iBACvD,CAAC;YACJ,CAAC;YACD,WAAW,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE;gBACjC,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;gBACrC,uEAAuE;gBACvE,MAAM,UAAU,GAAG;oBACjB,OAAO;oBACP,QAAQ,EAAE,cAAc,CACtB,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,IAAI,CAAC,EAC3C,OAAO,EACP,UAAU,CACX;oBACD,YAAY,EAAE,QAAQ,CAAC,YAAY;oBACnC,UAAU,EAAE,QAAQ,CAAC,UAAU;oBAC/B,gBAAgB,EAAE,QAAQ,CAAC,gBAAgB;oBAC3C,GAAG,CAAC,QAAQ,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACjF,GAAG,CAAC,QAAQ,CAAC,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACvE,CAAC;gBACF,OAAO,eAAe,CAAC,GAAG,CAAC,aAAa,EAAE,GAAG,IAAI,OAAO,EAAE,UAAU,CAAC,CAAC;YACxE,CAAC;SACF,CAAC,CAAC;QAEH,MAAM,UAAU,GAAe;YAC7B,GAAG,KAAK,CAAC,QAAQ;YACjB,OAAO,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC;YACxB,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM;YAC7B,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpE,GAAG,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC5E,CAAC;QACF,2EAA2E;QAC3E,yEAAyE;QACzE,4EAA4E;QAC5E,MAAM,SAAS,GACb,KAAK,CAAC,QAAQ,CAAC,UAAU,KAAK,SAAS,IAAI,IAAI,CAAC,YAAY;YAC1D,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC;YACxD,CAAC,CAAC,EAAE,CAAC;QACT,MAAM,OAAO,GAAG,WAAW,CAAC;YAC1B,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,KAAK,EAAE,UAAU,CAAC,UAAU;YAC5B,KAAK,EAAE,UAAU,CAAC,YAAY;YAC9B,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,MAAM;YACZ,UAAU,EAAE,UAAU,CAAC,UAAU;YACjC,QAAQ,EAAE,IAAI;YACd,GAAG,CAAC,UAAU,CAAC,YAAY,GAAG,gBAAgB,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACvF,CAAC,CAAC;QACH,MAAM,IAAI,GACR,cAAc,CACZ,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EACjD,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,EACf,UAAU,CACX;YACD,SAAS;YACT,CAAC,SAAS,IAAI,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YACnD,CAAC,UAAU,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,kBAAkB,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC3F,OAAO;YACL,UAAU;YACV,IAAI;YACJ,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAChE,CAAC;IACJ,CAAC;CACF,CAAC,CAAC","sourcesContent":["import { stat } from 'node:fs/promises';\nimport { basename, posix } from 'node:path';\n\nimport * as z from 'zod/v4';\n\nimport { processEntriesConcurrently, withAbort } from '../core/concurrency.ts';\nimport { pageQueryKey, paginate } from '../core/cursor.ts';\nimport { ErrorCode, normalizeUnknownError, rethrowIfAborted } from '../core/errors.ts';\nimport { formatByteSize, formatCount, pageTrailer } from '../core/fmt.ts';\nimport { globEntries, type GlobEntry } from '../core/glob.ts';\nimport { type EntryType, resolveEntryType, toPosixRelative } from '../core/path-utils.ts';\nimport type { PathGuard } from '../core/path.ts';\nimport {\n CursorSchema,\n defaultFalseBoolean,\n IncludeHidden,\n IncludeIgnored,\n mapOptionalPath,\n OptionalPath,\n PositiveInt,\n} from '../core/schema.ts';\nimport type { JsonResourceResult } from '../core/store.ts';\nimport { putJsonResource } from '../core/store.ts';\nimport {\n DEFAULT_TREE_ENTRIES,\n MAX_LIST_ENTRIES,\n MAX_TREE_DEPTH,\n PARALLEL_CONCURRENCY,\n} from '../core/util.ts';\nimport { defineTool } from './define.ts';\n\ninterface CollectedEntry {\n name: string;\n relativePath: string; // POSIX\n type: EntryType;\n size?: number;\n}\n\ninterface RenderOptions {\n includeSizes: boolean;\n sortBy: 'name' | 'size';\n}\n\ninterface CollectOptions extends RenderOptions {\n maxDepth: number;\n includeHidden: boolean;\n includeIgnored: boolean;\n signal: AbortSignal;\n pathGuard: PathGuard;\n /** Upper bound on the stored, paginable entry array. */\n entryCap: number;\n onProgress: (progress: { current: number; total?: number }) => void;\n}\n\ninterface CollectResult {\n entries: CollectedEntry[];\n totalEntries: number;\n totalFiles: number;\n totalDirectories: number;\n totalBytes?: number;\n}\n\nfunction entryTypeRank(type: EntryType): number {\n if (type === 'directory') return 0;\n return 1;\n}\n\n// Compare by parent directory first (depth-level grouping), then within the\n// same parent: directories first, then by size (descending) or alphabetical.\nfunction entryComparator(sortBy: 'name' | 'size') {\n return (a: CollectedEntry, b: CollectedEntry): number => {\n const slashA = a.relativePath.lastIndexOf('/');\n const slashB = b.relativePath.lastIndexOf('/');\n const parentA = slashA === -1 ? '' : a.relativePath.slice(0, slashA);\n const parentB = slashB === -1 ? '' : b.relativePath.slice(0, slashB);\n if (parentA !== parentB) return parentA.localeCompare(parentB);\n const rankDiff = entryTypeRank(a.type) - entryTypeRank(b.type);\n if (rankDiff !== 0) return rankDiff;\n if (sortBy === 'size') {\n const sizeDiff = (b.size ?? 0) - (a.size ?? 0);\n if (sizeDiff !== 0) return sizeDiff;\n }\n return a.name.localeCompare(b.name);\n };\n}\n\nasync function collect(rootPath: string, options: CollectOptions): Promise<CollectResult> {\n const entries: CollectedEntry[] = [];\n const wantSizes = options.includeSizes || options.sortBy === 'size';\n let scanned = 0;\n let totalEntries = 0;\n let totalFiles = 0;\n let totalDirectories = 0;\n let totalBytes = 0;\n let fatalError: Error | undefined;\n const ceiling = options.pathGuard.allowedRootContaining(rootPath);\n const comparator = entryComparator(options.sortBy);\n const keepBest = (): void => {\n entries.sort(comparator);\n if (entries.length > options.entryCap) entries.length = options.entryCap;\n };\n\n await processEntriesConcurrently<GlobEntry>(\n globEntries({\n cwd: rootPath,\n pattern: '**/*',\n skipIgnored: !options.includeIgnored,\n ...(ceiling !== undefined ? { ignoreCeiling: ceiling } : {}),\n signal: options.signal,\n includeHidden: options.includeHidden,\n baseNameMatch: false,\n // ListInputSchema.maxDepth is 1-based (1 = top-level only); the shared\n // globEntries primitive is now 0-based, so subtract one here. options.maxDepth\n // is guaranteed >= 1 by its PositiveInt schema, so this never underflows.\n maxDepth: options.maxDepth - 1,\n onlyFiles: false,\n }),\n {\n signal: options.signal,\n concurrency: PARALLEL_CONCURRENCY,\n onEntry: () => {\n scanned++;\n options.onProgress({ current: scanned });\n },\n onError: (_entryPath, err) => {\n fatalError ??= normalizeUnknownError(err);\n },\n runEntry: async (_entryPath, entry) => {\n const entryType: EntryType = resolveEntryType(entry.dirent);\n const relPath = toPosixRelative(rootPath, entry.path);\n const name = basename(relPath);\n for (let dir = posix.dirname(relPath); dir !== '.'; dir = posix.dirname(dir)) {\n if (options.pathGuard.isSensitive(`${rootPath}/${dir}`)) return;\n }\n\n const accessible = await options.pathGuard.isEntryAccessible(entry.path);\n if (!accessible) return;\n\n let size: number | undefined;\n if (wantSizes && entryType === 'file') {\n try {\n size = (await withAbort(stat(entry.path), options.signal)).size;\n } catch (error) {\n rethrowIfAborted(error);\n // A file can vanish between the walk and the stat; it keeps its place, without a size.\n }\n }\n\n totalEntries++;\n if (entryType === 'directory') {\n totalDirectories++;\n } else if (entryType === 'file') {\n totalFiles++;\n if (size !== undefined) totalBytes += size;\n }\n\n entries.push({\n name,\n relativePath: relPath,\n type: entryType,\n ...(size !== undefined ? { size } : {}),\n });\n // Keep at most the best entryCap: prune whenever the buffer doubles,\n // so memory stays O(entryCap) and the sorts O(n log entryCap) overall.\n if (entries.length >= options.entryCap * 2) keepBest();\n },\n },\n );\n\n if (fatalError !== undefined) throw fatalError;\n options.signal.throwIfAborted();\n keepBest();\n\n return {\n entries,\n totalEntries,\n totalFiles,\n totalDirectories,\n ...(wantSizes ? { totalBytes } : {}),\n };\n}\n\nconst TEE = '├── ';\nconst ELBOW = '└── ';\nconst PIPE = '│ ';\nconst INDENT = ' ';\n\n/**\n * The tree's first line names the listed folder the way the caller passes it\n * back: `src/core`, not `core`, which would name `<root>/core`. A root keeps\n * its own name.\n */\nfunction treeHeader(pathGuard: PathGuard, dir: string): string {\n const paths = pathGuard.resultPaths(dir);\n return paths.atRoot ? basename(paths.root) : paths.show(dir);\n}\n\nfunction renderMarkdown(\n rootName: string,\n page: readonly CollectedEntry[],\n opts: RenderOptions,\n): string {\n if (page.length === 0) return rootName;\n\n // The tree is drawn down from the root, but a later page (or a capped set)\n // can hold entries whose ancestors sat elsewhere; those would never be drawn.\n // Re-draw each missing ancestor as context so every entry stays locatable.\n const present = new Set(page.map((entry) => entry.relativePath));\n const entries = [...page];\n for (const entry of page) {\n for (\n let dir = posix.dirname(entry.relativePath);\n dir !== '.' && !present.has(dir);\n dir = posix.dirname(dir)\n ) {\n present.add(dir);\n entries.push({ name: posix.basename(dir), relativePath: dir, type: 'directory' });\n }\n }\n entries.sort(entryComparator(opts.sortBy));\n\n // Group entries by parent path\n const childrenOf = new Map<string, CollectedEntry[]>();\n for (const entry of entries) {\n const slash = entry.relativePath.lastIndexOf('/');\n const parentKey = slash === -1 ? '' : entry.relativePath.slice(0, slash);\n if (!childrenOf.has(parentKey)) childrenOf.set(parentKey, []);\n const children = childrenOf.get(parentKey);\n if (children) children.push(entry);\n }\n\n const lines: string[] = [rootName];\n\n function renderChildren(parentKey: string, prefix: string): void {\n const children = childrenOf.get(parentKey);\n if (!children) return;\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n if (!child) continue;\n const isLast = i === children.length - 1;\n const connector = isLast ? ELBOW : TEE;\n const sizeText =\n opts.includeSizes && child.size !== undefined ? ` (${formatByteSize(child.size)})` : '';\n lines.push(\n prefix + connector + child.name + (child.type === 'directory' ? '/' : '') + sizeText,\n );\n\n const childKey = child.relativePath;\n const nextPrefix = prefix + (isLast ? INDENT : PIPE);\n renderChildren(childKey, nextPrefix);\n }\n }\n\n renderChildren('', '');\n return lines.join('\\n');\n}\n\n/** The `//` line `includeSizes` appends: counts and bytes over the whole collected set. */\nfunction summaryLine(metadata: ListPageMetadata, totalBytes: number): string {\n return `\\n\\n// ${formatCount(metadata.totalFiles, 'file')}, ${formatCount(\n metadata.totalDirectories,\n 'directory',\n )}, ${formatByteSize(totalBytes)} total`;\n}\n\nconst DEFAULT_LIST_DEPTH = 1;\n\nconst ListInputSchema = z.strictObject({\n path: OptionalPath.describe('Directory to list (default: first allowed root)'),\n maxDepth: PositiveInt.max(MAX_TREE_DEPTH)\n .default(DEFAULT_LIST_DEPTH)\n .describe(\n `Max directory depth to traverse (default: ${String(DEFAULT_LIST_DEPTH)} = top-level only; increase to recurse deeper)`,\n ),\n maxEntries: PositiveInt.max(MAX_LIST_ENTRIES)\n .default(DEFAULT_TREE_ENTRIES)\n .describe(\n `Page size (default: ${String(DEFAULT_TREE_ENTRIES)}). Continue with nextCursor; an incomplete first page also carries resourceUri for the whole list.`,\n ),\n includeHidden: IncludeHidden,\n includeIgnored: IncludeIgnored,\n includeSizes: defaultFalseBoolean(\n 'Show file sizes in the tree and a totals line of counts and bytes',\n ),\n sortBy: z\n .enum(['name', 'size'])\n .optional()\n .default('name')\n .describe('Order within each directory: name (default) or size (largest first)'),\n cursor: CursorSchema,\n});\n\ninterface ListPageMetadata {\n readonly path: string;\n readonly totalEntries: number;\n readonly totalFiles: number;\n readonly totalDirectories: number;\n readonly totalBytes?: number;\n}\n\ntype ListOutput = ListPageMetadata & {\n entries: CollectedEntry[];\n entryCount: number;\n resourceUri?: string;\n nextCursor?: string;\n};\n\nexport const LIST = defineTool<typeof ListInputSchema, ListOutput>({\n name: 'list',\n title: 'List',\n description:\n \"List a directory's files and subdirectories as a tree of names, like ls or tree. \" +\n 'includeSizes adds sizes and a total; stat returns dates.',\n input: ListInputSchema,\n readOnlyHint: true,\n deadline: true,\n defaultErrorCode: ErrorCode.NOT_DIRECTORY,\n progress: (args) => ({\n label: 'List',\n subject: args.path ? basename(args.path) : '.',\n }),\n mapPaths: mapOptionalPath,\n run: async (args, ctx) => {\n const resolvedPath = ctx.fs.pathGuard.resolvePathOrRoot(args.path);\n const renderOpts: RenderOptions = { includeSizes: args.includeSizes, sortBy: args.sortBy };\n const paged = await paginate<CollectedEntry, ListPageMetadata, JsonResourceResult>({\n store: ctx.pageStore,\n queryKey: pageQueryKey('list', { ...args, path: resolvedPath }, ['cursor', 'maxEntries']),\n cursor: args.cursor,\n pageSize: args.maxEntries,\n produce: async () => {\n const validDir = await ctx.fs.pathGuard.validateExistingDirectory(resolvedPath);\n const result = await collect(validDir, {\n ...renderOpts,\n maxDepth: args.maxDepth,\n includeHidden: args.includeHidden,\n includeIgnored: args.includeIgnored,\n signal: ctx.signal,\n pathGuard: ctx.fs.pathGuard,\n entryCap: MAX_LIST_ENTRIES,\n onProgress: ctx.onProgress,\n });\n return {\n items: result.entries,\n metadata: {\n path: validDir,\n totalEntries: result.totalEntries,\n totalFiles: result.totalFiles,\n totalDirectories: result.totalDirectories,\n ...(result.totalBytes !== undefined ? { totalBytes: result.totalBytes } : {}),\n },\n truncated: result.totalEntries > result.entries.length,\n };\n },\n externalize: (entries, metadata) => {\n const name = basename(metadata.path);\n // The stored tree is the whole collected set, bounded by the hard cap.\n const fullOutput = {\n entries,\n markdown: renderMarkdown(\n treeHeader(ctx.fs.pathGuard, metadata.path),\n entries,\n renderOpts,\n ),\n totalEntries: metadata.totalEntries,\n totalFiles: metadata.totalFiles,\n totalDirectories: metadata.totalDirectories,\n ...(metadata.totalBytes !== undefined ? { totalBytes: metadata.totalBytes } : {}),\n ...(metadata.totalEntries > entries.length ? { truncated: true } : {}),\n };\n return putJsonResource(ctx.resourceStore, `${name} tree`, fullOutput);\n },\n });\n\n const structured: ListOutput = {\n ...paged.metadata,\n entries: [...paged.page],\n entryCount: paged.page.length,\n ...(paged.resource ? { resourceUri: paged.resource.entry.uri } : {}),\n ...(paged.nextCursor !== undefined ? { nextCursor: paged.nextCursor } : {}),\n };\n // The tree is what the model reads, so position and the full-list URI ride\n // the text too — paging needs no second lookup. `pageTrailer` is the one\n // owner of that line, and it owes it on the last page as much as the first.\n const sizesLine =\n paged.metadata.totalBytes !== undefined && args.includeSizes\n ? summaryLine(paged.metadata, paged.metadata.totalBytes)\n : '';\n const trailer = pageTrailer({\n offset: paged.offset,\n shown: structured.entryCount,\n total: structured.totalEntries,\n noun: 'entries',\n tool: 'list',\n nextCursor: structured.nextCursor,\n nextArgs: args,\n ...(structured.totalEntries > MAX_LIST_ENTRIES ? { stoppedReason: 'maxResults' } : {}),\n });\n const text =\n renderMarkdown(\n treeHeader(ctx.fs.pathGuard, paged.metadata.path),\n [...paged.page],\n renderOpts,\n ) +\n sizesLine +\n (sizesLine && trailer ? trailer.slice(1) : trailer) +\n (structured.resourceUri !== undefined ? `\\nfull tree at ${structured.resourceUri}` : '');\n return {\n structured,\n text,\n ...(paged.resource ? { resources: [paged.resource.link] } : {}),\n };\n },\n});\n"]}
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/tools/list.ts"],"names":[],"mappings":"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","sourcesContent":["import { basename, posix } from 'node:path';\n\nimport * as z from 'zod/v4';\n\nimport { processEntriesConcurrently, withAbort } from '../core/concurrency.ts';\nimport { pageQueryKey, paginate } from '../core/cursor.ts';\nimport { ErrorCode, normalizeUnknownError, rethrowIfAborted } from '../core/errors.ts';\nimport { formatByteSize, formatCount, pageTrailer } from '../core/fmt.ts';\nimport type { GuardedFileSystem } from '../core/fs.ts';\nimport { globEntries, type GlobEntry } from '../core/glob.ts';\nimport { type EntryType, resolveEntryType, toPosixRelative } from '../core/path-utils.ts';\nimport type { PathGuard } from '../core/path.ts';\nimport {\n CursorSchema,\n defaultFalseBoolean,\n IncludeHidden,\n IncludeIgnored,\n mapOptionalPath,\n OptionalPath,\n PositiveInt,\n} from '../core/schema.ts';\nimport type { JsonResourceResult } from '../core/store.ts';\nimport { putJsonResource } from '../core/store.ts';\nimport {\n DEFAULT_TREE_ENTRIES,\n MAX_LIST_ENTRIES,\n MAX_TREE_DEPTH,\n PARALLEL_CONCURRENCY,\n} from '../core/util.ts';\nimport { defineTool } from './define.ts';\n\ninterface CollectedEntry {\n name: string;\n relativePath: string; // POSIX\n type: EntryType;\n size?: number;\n}\n\ninterface RenderOptions {\n includeSizes: boolean;\n sortBy: 'name' | 'size';\n}\n\ninterface CollectOptions extends RenderOptions {\n maxDepth: number;\n includeHidden: boolean;\n includeIgnored: boolean;\n signal: AbortSignal;\n fs: GuardedFileSystem;\n pathGuard: PathGuard;\n /** Upper bound on the stored, paginable entry array. */\n entryCap: number;\n onProgress: (progress: { current: number; total?: number }) => void;\n}\n\ninterface CollectResult {\n entries: CollectedEntry[];\n totalEntries: number;\n totalFiles: number;\n totalDirectories: number;\n totalBytes?: number;\n}\n\nfunction entryTypeRank(type: EntryType): number {\n if (type === 'directory') return 0;\n return 1;\n}\n\n// Compare by parent directory first (depth-level grouping), then within the\n// same parent: directories first, then by size (descending) or alphabetical.\nfunction entryComparator(sortBy: 'name' | 'size') {\n return (a: CollectedEntry, b: CollectedEntry): number => {\n const slashA = a.relativePath.lastIndexOf('/');\n const slashB = b.relativePath.lastIndexOf('/');\n const parentA = slashA === -1 ? '' : a.relativePath.slice(0, slashA);\n const parentB = slashB === -1 ? '' : b.relativePath.slice(0, slashB);\n if (parentA !== parentB) return parentA.localeCompare(parentB);\n const rankDiff = entryTypeRank(a.type) - entryTypeRank(b.type);\n if (rankDiff !== 0) return rankDiff;\n if (sortBy === 'size') {\n const sizeDiff = (b.size ?? 0) - (a.size ?? 0);\n if (sizeDiff !== 0) return sizeDiff;\n }\n return a.name.localeCompare(b.name);\n };\n}\n\nasync function collect(rootPath: string, options: CollectOptions): Promise<CollectResult> {\n const entries: CollectedEntry[] = [];\n const wantSizes = options.includeSizes || options.sortBy === 'size';\n let scanned = 0;\n let totalEntries = 0;\n let totalFiles = 0;\n let totalDirectories = 0;\n let totalBytes = 0;\n let fatalError: Error | undefined;\n const ceiling = options.pathGuard.allowedRootContaining(rootPath);\n const comparator = entryComparator(options.sortBy);\n const keepBest = (): void => {\n entries.sort(comparator);\n if (entries.length > options.entryCap) entries.length = options.entryCap;\n };\n\n await processEntriesConcurrently<GlobEntry>(\n globEntries({\n cwd: rootPath,\n pattern: '**/*',\n skipIgnored: !options.includeIgnored,\n ...(ceiling !== undefined ? { ignoreCeiling: ceiling } : {}),\n signal: options.signal,\n pathGuard: options.pathGuard,\n includeHidden: options.includeHidden,\n baseNameMatch: false,\n // ListInputSchema.maxDepth is 1-based (1 = top-level only); the shared\n // globEntries primitive is now 0-based, so subtract one here. options.maxDepth\n // is guaranteed >= 1 by its PositiveInt schema, so this never underflows.\n maxDepth: options.maxDepth - 1,\n onlyFiles: false,\n }),\n {\n signal: options.signal,\n concurrency: PARALLEL_CONCURRENCY,\n onEntry: () => {\n scanned++;\n options.onProgress({ current: scanned });\n },\n onError: (_entryPath, err) => {\n fatalError ??= normalizeUnknownError(err);\n },\n runEntry: async (_entryPath, entry) => {\n const entryType: EntryType = resolveEntryType(entry.dirent);\n const relPath = toPosixRelative(rootPath, entry.path);\n const name = basename(relPath);\n // A sensitive-named directory never reaches the walk (globEntries\n // prunes it via pathGuard), so no ancestor re-check is needed here.\n\n const accessible = await options.pathGuard.isEntryAccessible(entry.path);\n if (!accessible) return;\n\n let size: number | undefined;\n if (wantSizes && entryType === 'file') {\n try {\n // Race the abort from the first await: the guarded stat validates the\n // path before statting, and that validation is not abort-aware, so\n // the race must wrap the whole call.\n const statted = await withAbort(\n options.fs.stat(entry.path, { signal: options.signal }),\n options.signal,\n );\n size = statted.stats.size;\n } catch (error) {\n rethrowIfAborted(error);\n // A file can vanish between the walk and the stat; it keeps its place, without a size.\n }\n }\n\n totalEntries++;\n if (entryType === 'directory') {\n totalDirectories++;\n } else if (entryType === 'file') {\n totalFiles++;\n if (size !== undefined) totalBytes += size;\n }\n\n entries.push({\n name,\n relativePath: relPath,\n type: entryType,\n ...(size !== undefined ? { size } : {}),\n });\n // Keep at most the best entryCap: prune whenever the buffer doubles,\n // so memory stays O(entryCap) and the sorts O(n log entryCap) overall.\n if (entries.length >= options.entryCap * 2) keepBest();\n },\n },\n );\n\n if (fatalError !== undefined) throw fatalError;\n options.signal.throwIfAborted();\n keepBest();\n\n return {\n entries,\n totalEntries,\n totalFiles,\n totalDirectories,\n ...(wantSizes ? { totalBytes } : {}),\n };\n}\n\nconst TEE = '├── ';\nconst ELBOW = '└── ';\nconst PIPE = '│ ';\nconst INDENT = ' ';\n\n/**\n * The tree's first line names the listed folder the way the caller passes it\n * back: `src/core`, not `core`, which would name `<root>/core`. A root keeps\n * its own name.\n */\nfunction treeHeader(pathGuard: PathGuard, dir: string): string {\n const paths = pathGuard.resultPaths(dir);\n return paths.atRoot ? basename(paths.root) : paths.show(dir);\n}\n\nfunction renderMarkdown(\n rootName: string,\n page: readonly CollectedEntry[],\n opts: RenderOptions,\n): string {\n if (page.length === 0) return rootName;\n\n // The tree is drawn down from the root, but a later page (or a capped set)\n // can hold entries whose ancestors sat elsewhere; those would never be drawn.\n // Re-draw each missing ancestor as context so every entry stays locatable.\n const present = new Set(page.map((entry) => entry.relativePath));\n const entries = [...page];\n for (const entry of page) {\n for (\n let dir = posix.dirname(entry.relativePath);\n dir !== '.' && !present.has(dir);\n dir = posix.dirname(dir)\n ) {\n present.add(dir);\n entries.push({ name: posix.basename(dir), relativePath: dir, type: 'directory' });\n }\n }\n entries.sort(entryComparator(opts.sortBy));\n\n // Group entries by parent path\n const childrenOf = new Map<string, CollectedEntry[]>();\n for (const entry of entries) {\n const slash = entry.relativePath.lastIndexOf('/');\n const parentKey = slash === -1 ? '' : entry.relativePath.slice(0, slash);\n if (!childrenOf.has(parentKey)) childrenOf.set(parentKey, []);\n const children = childrenOf.get(parentKey);\n if (children) children.push(entry);\n }\n\n const lines: string[] = [rootName];\n\n function renderChildren(parentKey: string, prefix: string): void {\n const children = childrenOf.get(parentKey);\n if (!children) return;\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n if (!child) continue;\n const isLast = i === children.length - 1;\n const connector = isLast ? ELBOW : TEE;\n const sizeText =\n opts.includeSizes && child.size !== undefined ? ` (${formatByteSize(child.size)})` : '';\n lines.push(\n prefix + connector + child.name + (child.type === 'directory' ? '/' : '') + sizeText,\n );\n\n const childKey = child.relativePath;\n const nextPrefix = prefix + (isLast ? INDENT : PIPE);\n renderChildren(childKey, nextPrefix);\n }\n }\n\n renderChildren('', '');\n return lines.join('\\n');\n}\n\n/** The `//` line `includeSizes` appends: counts and bytes over the whole collected set. */\nfunction summaryLine(metadata: ListPageMetadata, totalBytes: number): string {\n return `\\n\\n// ${formatCount(metadata.totalFiles, 'file')}, ${formatCount(\n metadata.totalDirectories,\n 'directory',\n )}, ${formatByteSize(totalBytes)} total`;\n}\n\nconst DEFAULT_LIST_DEPTH = 1;\n\nconst ListInputSchema = z.strictObject({\n path: OptionalPath.describe('Directory to list (default: first allowed root)'),\n maxDepth: PositiveInt.max(MAX_TREE_DEPTH)\n .default(DEFAULT_LIST_DEPTH)\n .describe(\n `Max directory depth to traverse (default: ${String(DEFAULT_LIST_DEPTH)} = top-level only; increase to recurse deeper)`,\n ),\n maxEntries: PositiveInt.max(MAX_LIST_ENTRIES)\n .default(DEFAULT_TREE_ENTRIES)\n .describe(\n `Page size (default: ${String(DEFAULT_TREE_ENTRIES)}). Continue with nextCursor; an incomplete first page also carries resourceUri for the whole list.`,\n ),\n includeHidden: IncludeHidden,\n includeIgnored: IncludeIgnored,\n includeSizes: defaultFalseBoolean(\n 'Show file sizes in the tree and a totals line of counts and bytes',\n ),\n sortBy: z\n .enum(['name', 'size'])\n .optional()\n .default('name')\n .describe('Order within each directory: name (default) or size (largest first)'),\n cursor: CursorSchema,\n});\n\ninterface ListPageMetadata {\n readonly path: string;\n readonly totalEntries: number;\n readonly totalFiles: number;\n readonly totalDirectories: number;\n readonly totalBytes?: number;\n}\n\ntype ListOutput = ListPageMetadata & {\n entries: CollectedEntry[];\n entryCount: number;\n resourceUri?: string;\n nextCursor?: string;\n};\n\nexport const LIST = defineTool<typeof ListInputSchema, ListOutput>({\n name: 'list',\n title: 'List',\n description:\n \"List a directory's files and subdirectories as a tree of names, like ls or tree. \" +\n 'includeSizes adds sizes and a total; stat returns dates.',\n input: ListInputSchema,\n readOnlyHint: true,\n deadline: true,\n defaultErrorCode: ErrorCode.NOT_DIRECTORY,\n progress: (args) => ({\n label: 'List',\n subject: args.path ? basename(args.path) : '.',\n }),\n mapPaths: mapOptionalPath,\n run: async (args, ctx) => {\n const resolvedPath = ctx.fs.pathGuard.resolvePathOrRoot(args.path);\n const renderOpts: RenderOptions = { includeSizes: args.includeSizes, sortBy: args.sortBy };\n const paged = await paginate<CollectedEntry, ListPageMetadata, JsonResourceResult>({\n store: ctx.pageStore,\n queryKey: pageQueryKey('list', { ...args, path: resolvedPath }, ['cursor', 'maxEntries']),\n cursor: args.cursor,\n pageSize: args.maxEntries,\n produce: async () => {\n const validDir = await ctx.fs.pathGuard.validateExistingDirectory(resolvedPath);\n const result = await collect(validDir, {\n ...renderOpts,\n maxDepth: args.maxDepth,\n includeHidden: args.includeHidden,\n includeIgnored: args.includeIgnored,\n signal: ctx.signal,\n fs: ctx.fs,\n pathGuard: ctx.fs.pathGuard,\n entryCap: MAX_LIST_ENTRIES,\n onProgress: ctx.onProgress,\n });\n return {\n items: result.entries,\n metadata: {\n path: validDir,\n totalEntries: result.totalEntries,\n totalFiles: result.totalFiles,\n totalDirectories: result.totalDirectories,\n ...(result.totalBytes !== undefined ? { totalBytes: result.totalBytes } : {}),\n },\n truncated: result.totalEntries > result.entries.length,\n };\n },\n externalize: (entries, metadata) => {\n const name = basename(metadata.path);\n // The stored tree is the whole collected set, bounded by the hard cap.\n const fullOutput = {\n entries,\n markdown: renderMarkdown(\n treeHeader(ctx.fs.pathGuard, metadata.path),\n entries,\n renderOpts,\n ),\n totalEntries: metadata.totalEntries,\n totalFiles: metadata.totalFiles,\n totalDirectories: metadata.totalDirectories,\n ...(metadata.totalBytes !== undefined ? { totalBytes: metadata.totalBytes } : {}),\n ...(metadata.totalEntries > entries.length ? { truncated: true } : {}),\n };\n return putJsonResource(ctx.resourceStore, `${name} tree`, fullOutput);\n },\n });\n\n const structured: ListOutput = {\n ...paged.metadata,\n entries: [...paged.page],\n entryCount: paged.page.length,\n ...(paged.resource ? { resourceUri: paged.resource.entry.uri } : {}),\n ...(paged.nextCursor !== undefined ? { nextCursor: paged.nextCursor } : {}),\n };\n // The tree is what the model reads, so position and the full-list URI ride\n // the text too — paging needs no second lookup. `pageTrailer` is the one\n // owner of that line, and it owes it on the last page as much as the first.\n const sizesLine =\n paged.metadata.totalBytes !== undefined && args.includeSizes\n ? summaryLine(paged.metadata, paged.metadata.totalBytes)\n : '';\n const trailer = pageTrailer({\n offset: paged.offset,\n shown: structured.entryCount,\n total: structured.totalEntries,\n noun: 'entries',\n tool: 'list',\n nextCursor: structured.nextCursor,\n nextArgs: args,\n ...(structured.totalEntries > MAX_LIST_ENTRIES ? { stoppedReason: 'maxResults' } : {}),\n });\n const text =\n renderMarkdown(\n treeHeader(ctx.fs.pathGuard, paged.metadata.path),\n [...paged.page],\n renderOpts,\n ) +\n sizesLine +\n (sizesLine && trailer ? trailer.slice(1) : trailer) +\n (structured.resourceUri !== undefined ? `\\nfull tree at ${structured.resourceUri}` : '');\n return {\n structured,\n text,\n ...(paged.resource ? { resources: [paged.resource.link] } : {}),\n };\n },\n});\n"]}
|
package/dist/tools/read.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/tools/read.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/tools/read.ts"],"names":[],"mappings":"AA4ZA,eAAO,MAAM,IAAI,mCAgJf,CAAC"}
|
package/dist/tools/read.js
CHANGED
|
@@ -7,7 +7,7 @@ import { buildFileResourceLinkFor, buildFileResourceUri } from "../core/file-uri
|
|
|
7
7
|
import { detectMimeFromContent, detectMimeType, isKnownBinaryExtension, } from "../core/mime.js";
|
|
8
8
|
import { BINARY_FILE_MESSAGE, isBinaryRefusal, } from "../core/read.js";
|
|
9
9
|
import { defaultFalseBoolean, mapSingleOrBatchPaths, singleOrBatchPathsInput, validateReadRange, } from "../core/schema.js";
|
|
10
|
-
import { DEFAULT_CONTINUATION_CHUNK_SIZE, getMaxTextFileSize, PARALLEL_CONCURRENCY, READ_MANY_MAX_TOTAL_BYTES, } from "../core/util.js";
|
|
10
|
+
import { base64EncodedBytes, DEFAULT_CONTINUATION_CHUNK_SIZE, getMaxTextFileSize, PARALLEL_CONCURRENCY, READ_MANY_MAX_TOTAL_BYTES, } from "../core/util.js";
|
|
11
11
|
import { isTotalFailure, runOverPaths } from "./batch.js";
|
|
12
12
|
import { defineTool } from "./define.js";
|
|
13
13
|
/**
|
|
@@ -15,6 +15,8 @@ import { defineTool } from "./define.js";
|
|
|
15
15
|
* never asks for more. Not restated as `.max()`: that reports it twice.
|
|
16
16
|
*/
|
|
17
17
|
const MAX_LINE_NUMBER = 2_147_483_647;
|
|
18
|
+
/** One spelling of the resource-content digest every read result that carries a hash uses. */
|
|
19
|
+
const sha256Hex = (data) => createHash('sha256').update(data).digest('hex');
|
|
18
20
|
const rangeField = (description, count = false) => {
|
|
19
21
|
const field = z.int32().min(1, { message: 'Min: 1' });
|
|
20
22
|
return (count ? field.max(100000, { message: 'Max: 100,000' }) : field)
|
|
@@ -108,7 +110,7 @@ function budgetBytes(path, size, { fullRead, binary }) {
|
|
|
108
110
|
return size;
|
|
109
111
|
const { kind } = detectMimeType(path);
|
|
110
112
|
const base64 = kind === 'image' || kind === 'audio' || (binary && isKnownBinaryExtension(path));
|
|
111
|
-
return base64 ?
|
|
113
|
+
return base64 ? base64EncodedBytes(size) : size;
|
|
112
114
|
}
|
|
113
115
|
async function collectFileBudget(filePaths, maxTotalSize, maxSize, ctx, mode) {
|
|
114
116
|
const indexed = filePaths.map((path, index) => ({ path, index }));
|
|
@@ -150,9 +152,7 @@ function buildPerPathReadValue(result, options) {
|
|
|
150
152
|
const continuation = result.hasMoreLines && result.readMode !== 'tail'
|
|
151
153
|
? buildReadContinuation(result, options.requestedPath)
|
|
152
154
|
: undefined;
|
|
153
|
-
const contentHash = options.includeHash
|
|
154
|
-
? createHash('sha256').update(result.content, 'utf-8').digest('hex')
|
|
155
|
-
: undefined;
|
|
155
|
+
const contentHash = options.includeHash ? sha256Hex(result.content) : undefined;
|
|
156
156
|
const canLink = result.fileSize === undefined || result.fileSize <= getMaxTextFileSize();
|
|
157
157
|
return {
|
|
158
158
|
content: result.content,
|
|
@@ -213,9 +213,7 @@ async function readBinaryResource(filePath, args, ctx) {
|
|
|
213
213
|
resourceUri: buildFileResourceUri(raw.validPath),
|
|
214
214
|
modified: raw.modified,
|
|
215
215
|
blobData: raw.content.toString('base64'),
|
|
216
|
-
...(args.includeHash
|
|
217
|
-
? { contentHash: createHash('sha256').update(raw.content).digest('hex') }
|
|
218
|
-
: {}),
|
|
216
|
+
...(args.includeHash ? { contentHash: sha256Hex(raw.content) } : {}),
|
|
219
217
|
};
|
|
220
218
|
}
|
|
221
219
|
async function readOnePath(filePath, args, ctx) {
|
|
@@ -239,9 +237,7 @@ async function readOnePath(filePath, args, ctx) {
|
|
|
239
237
|
resourceUri: buildFileResourceUri(raw.validPath),
|
|
240
238
|
modified: raw.modified,
|
|
241
239
|
mediaData: raw.content.toString('base64'),
|
|
242
|
-
...(args.includeHash
|
|
243
|
-
? { contentHash: createHash('sha256').update(raw.content).digest('hex') }
|
|
244
|
-
: {}),
|
|
240
|
+
...(args.includeHash ? { contentHash: sha256Hex(raw.content) } : {}),
|
|
245
241
|
};
|
|
246
242
|
}
|
|
247
243
|
}
|
package/dist/tools/read.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/tools/read.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContentBlock } from '@modelcontextprotocol/server';\n\nimport { createHash } from 'node:crypto';\nimport { basename } from 'node:path';\n\nimport * as z from 'zod/v4';\n\nimport { processInParallel } from '../core/concurrency.ts';\nimport { ErrorCode, FsError } from '../core/errors.ts';\nimport { buildFileResourceLinkFor, buildFileResourceUri } from '../core/file-uri.ts';\nimport {\n detectMimeFromContent,\n detectMimeType,\n type FileKind,\n isKnownBinaryExtension,\n} from '../core/mime.ts';\nimport {\n BINARY_FILE_MESSAGE,\n isBinaryRefusal,\n type ReadFileResult,\n type ReadSpec,\n} from '../core/read.ts';\nimport {\n defaultFalseBoolean,\n mapSingleOrBatchPaths,\n singleOrBatchPathsInput,\n validateReadRange,\n} from '../core/schema.ts';\nimport {\n DEFAULT_CONTINUATION_CHUNK_SIZE,\n getMaxTextFileSize,\n PARALLEL_CONCURRENCY,\n READ_MANY_MAX_TOTAL_BYTES,\n} from '../core/util.ts';\nimport type { BatchResult } from './batch.ts';\nimport { isTotalFailure, runOverPaths } from './batch.ts';\nimport type { ToolCtx } from './define.ts';\nimport { defineTool } from './define.ts';\n\n/**\n * `z.int32()`'s own ceiling on startLine/endLine, named so a continuation\n * never asks for more. Not restated as `.max()`: that reports it twice.\n */\nconst MAX_LINE_NUMBER = 2_147_483_647;\n\nconst rangeField = (description: string, count = false) => {\n const field = z.int32().min(1, { message: 'Min: 1' });\n return (count ? field.max(100000, { message: 'Max: 100,000' }) : field)\n .optional()\n .describe(description);\n};\n\nconst readRangeFields = {\n head: rangeField('Return first N lines', true),\n tail: rangeField('Return last N lines', true),\n startLine: rangeField('Start line (1-indexed)'),\n endLine: rangeField('End line (1-indexed); requires startLine'),\n};\n\n/** A slice read: only a full read returns media or a binary resource. */\nfunction hasLineRange(args: {\n head?: number | undefined;\n tail?: number | undefined;\n startLine?: number | undefined;\n endLine?: number | undefined;\n}): boolean {\n return (\n args.head !== undefined ||\n args.tail !== undefined ||\n args.startLine !== undefined ||\n args.endLine !== undefined\n );\n}\n\nconst ReadFileInputSchema = singleOrBatchPathsInput({\n includeHash: defaultFalseBoolean('Include SHA-256 hash of the returned content in the response'),\n binary: defaultFalseBoolean(\n 'Return a binary file that is not an image or audio whole, as a base64 embedded resource. Full reads only.',\n ),\n ...readRangeFields,\n}).superRefine((value, ctx) => {\n validateReadRange(\n {\n head: value.head,\n tail: value.tail,\n startLine: value.startLine,\n endLine: value.endLine,\n },\n ctx,\n );\n if (value.binary && hasLineRange(value)) {\n ctx.addIssue({\n code: 'custom',\n path: ['binary'],\n message:\n \"Cannot use 'binary' with 'head'/'tail'/'startLine'/'endLine'. A binary file is read whole.\",\n input: value,\n });\n }\n});\n\ninterface ReadContinuation {\n tool: 'read';\n args: { path: string; startLine: number; endLine: number };\n hint: string;\n}\n\n// File bytes ride content blocks, never the structured metadata.\ninterface ReadPerPathValue {\n mimeType?: string;\n kind?: FileKind;\n resourceUri?: string;\n /** Bytes in the file; set when the bytes ride a media or resource block. */\n size?: number;\n /** ISO-8601 mtime at read time; also rides the resource_link. */\n modified?: string;\n continuation?: ReadContinuation;\n totalLines?: number;\n linesRead?: number;\n hasMoreLines?: boolean;\n head?: number;\n tail?: number;\n startLine?: number;\n endLine?: number;\n contentHash?: string;\n}\n\ntype ReadFileInput = z.infer<typeof ReadFileInputSchema>;\n\nconst READ_TOOL_LABEL = 'Read';\n\nfunction buildReadSpec(args: ReadFileInput, signal?: AbortSignal): ReadSpec {\n const signalPart = signal ? { signal } : {};\n const { head, tail, startLine, endLine } = args;\n\n if (head !== undefined) return { kind: 'head', lines: head, ...signalPart };\n if (tail !== undefined) return { kind: 'tail', lines: tail, ...signalPart };\n if (startLine !== undefined || endLine !== undefined) {\n return {\n kind: 'range',\n start: startLine ?? 1,\n ...(endLine !== undefined ? { end: endLine } : {}),\n ...signalPart,\n };\n }\n return { kind: 'full', ...signalPart };\n}\n\n// No `totalLines`: only `readFull` counts them and a full read never leaves\n// more behind, so a continuation cannot know the total without a second pass.\nfunction buildReadContinuation(\n result: ReadFileResult,\n requestedPath: string,\n): ReadContinuation | undefined {\n if (!result.hasMoreLines) return undefined;\n const linesRead = result.linesRead ?? 0;\n const nextStart = (result.startLine ?? 1) + linesRead;\n // Args the schema would reject are no continuation; clamp the end into it.\n if (nextStart > MAX_LINE_NUMBER) return undefined;\n let chunkSize: number;\n if (result.head !== undefined) {\n chunkSize = result.head;\n } else if (result.startLine !== undefined && result.endLine !== undefined) {\n chunkSize = result.endLine - result.startLine + 1;\n } else {\n chunkSize = DEFAULT_CONTINUATION_CHUNK_SIZE;\n }\n const nextEnd = Math.min(nextStart + chunkSize - 1, MAX_LINE_NUMBER);\n return {\n tool: 'read',\n args: { path: requestedPath, startLine: nextStart, endLine: nextEnd },\n hint: `More lines remain from ${String(nextStart)}. Read next chunk with these args.`,\n };\n}\n\n/**\n * The published metadata plus the bytes this call read. `content`, `mediaData`\n * and `blobData` exist only between `readOnePath` and the content blocks `run`\n * builds from them — they are stripped before the structured half is returned,\n * which is why they are not in `ReadPerPathValue`.\n */\ntype PerPathReadValue = ReadPerPathValue & {\n content?: string;\n fileSize?: number;\n mediaData?: string;\n blobData?: string;\n};\n\ninterface BatchFileInfo {\n index: number;\n size: number;\n}\n\ninterface BudgetItem {\n path: string;\n skip?: FsError;\n}\n\ninterface BudgetMode {\n fullRead: boolean;\n binary: boolean;\n}\n\n/**\n * What a file costs the batch: one whose bytes ship as base64 costs that size.\n * Only a full read ships base64; a slice of an svg is text.\n */\nfunction budgetBytes(path: string, size: number, { fullRead, binary }: BudgetMode): number {\n if (!fullRead) return size;\n const { kind } = detectMimeType(path);\n const base64 = kind === 'image' || kind === 'audio' || (binary && isKnownBinaryExtension(path));\n return base64 ? 4 * Math.ceil(size / 3) : size;\n}\n\nasync function collectFileBudget(\n filePaths: readonly string[],\n maxTotalSize: number,\n maxSize: number,\n ctx: Pick<ToolCtx, 'fs' | 'signal' | 'log'>,\n mode: BudgetMode,\n): Promise<BudgetItem[]> {\n const indexed = filePaths.map((path, index) => ({ path, index }));\n const { results } = await processInParallel(\n indexed,\n async ({ path, index }): Promise<BatchFileInfo | undefined> => {\n try {\n const out = await ctx.fs.stat(path);\n return { index, size: budgetBytes(path, Math.min(out.stats.size, maxSize), mode) };\n } catch (err: unknown) {\n ctx.log('debug', `collectFileBudget: stat failed for \"${path}\": ${String(err)}`, 'read');\n return undefined;\n }\n },\n PARALLEL_CONCURRENCY,\n ctx.signal,\n );\n\n const byIndex = new Map<number, BatchFileInfo>();\n for (const { value: item } of results) {\n if (item) byIndex.set(item.index, item);\n }\n\n let total = 0;\n return filePaths.map((path, i): BudgetItem => {\n const info = byIndex.get(i);\n // A failed stat is not skipped, so its read surfaces the\n // real error, not a misleading TOO_LARGE.\n if (info === undefined) return { path };\n // Skip this file only; a later, smaller file that still fits is read.\n if (total + info.size > maxTotalSize) {\n return {\n path,\n skip: new FsError(\n ErrorCode.TOO_LARGE,\n `Skipped: this file alone would push the batch past maxTotalSize (${String(maxTotalSize)} bytes). Read it on its own with path instead of paths.`,\n path,\n ),\n };\n }\n total += info.size;\n return { path };\n });\n}\n\nfunction buildPerPathReadValue(\n result: ReadFileResult,\n options: { includeHash?: boolean; requestedPath: string },\n): PerPathReadValue {\n const mimeInfo = detectMimeFromContent(result.path, result.content);\n const continuation =\n result.hasMoreLines && result.readMode !== 'tail'\n ? buildReadContinuation(result, options.requestedPath)\n : undefined;\n const contentHash = options.includeHash\n ? createHash('sha256').update(result.content, 'utf-8').digest('hex')\n : undefined;\n\n const canLink = result.fileSize === undefined || result.fileSize <= getMaxTextFileSize();\n\n return {\n content: result.content,\n ...(result.fileSize !== undefined ? { fileSize: result.fileSize } : {}),\n mimeType: mimeInfo.mimeType,\n kind: mimeInfo.kind,\n ...(continuation ? { continuation } : {}),\n ...(result.totalLines !== undefined ? { totalLines: result.totalLines } : {}),\n ...(result.linesRead !== undefined ? { linesRead: result.linesRead } : {}),\n ...(result.hasMoreLines ? { hasMoreLines: true } : {}),\n ...(result.head !== undefined ? { head: result.head } : {}),\n ...(result.tail !== undefined ? { tail: result.tail } : {}),\n ...(result.startLine !== undefined ? { startLine: result.startLine } : {}),\n ...(result.endLine !== undefined ? { endLine: result.endLine } : {}),\n ...(contentHash !== undefined ? { contentHash } : {}),\n ...(canLink ? { resourceUri: buildFileResourceUri(result.path) } : {}),\n modified: result.modified,\n };\n}\n\n/**\n * The two facts the model cannot act on without: that lines were dropped, and\n * the exact args to get the next chunk. Both used to live only in the structured\n * half, which no longer reaches the model. Each line is `//` prefixed and set\n * off by a blank line so it cannot be read as file bytes — do not drop either\n * guard.\n */\nfunction readTrailer(v: PerPathReadValue): string[] {\n const lines: string[] = [];\n if (v.continuation) {\n lines.push(\n `// truncated: ${v.continuation.hint} Continue: read ${JSON.stringify(v.continuation.args)}`,\n );\n } else if (v.hasMoreLines && v.linesRead !== undefined) {\n // A tail read gets no continuation — there are no args that read *backwards*\n // — so say what was shown rather than leaving the truncation silent.\n lines.push(`// truncated: showing last ${String(v.linesRead)} lines`);\n }\n if (v.contentHash !== undefined) lines.push(`// sha256: ${v.contentHash}`);\n return lines;\n}\n\n/**\n * `binary: true` after the text path refused the file as binary. readRaw\n * re-validates the path (roots, denylist) and enforces the same size cap.\n * A file refused by its extension can still probe as text: it ships as the\n * extension says, octet-stream.\n */\nasync function readBinaryResource(\n filePath: string,\n args: ReadFileInput,\n ctx: ToolCtx,\n): Promise<PerPathReadValue> {\n const raw = await ctx.fs.readRaw(filePath, { signal: ctx.signal });\n const asText = raw.kind === 'text';\n const kind: FileKind = asText ? 'binary' : raw.kind;\n const mimeType = asText ? 'application/octet-stream' : raw.mimeType;\n const size = raw.content.length;\n return {\n content: `[binary ${kind} content: ${String(size)} bytes (${mimeType}); returned as an embedded resource block]`,\n mimeType,\n kind,\n size,\n resourceUri: buildFileResourceUri(raw.validPath),\n modified: raw.modified,\n blobData: raw.content.toString('base64'),\n ...(args.includeHash\n ? { contentHash: createHash('sha256').update(raw.content).digest('hex') }\n : {}),\n };\n}\n\nasync function readOnePath(\n filePath: string,\n args: ReadFileInput,\n ctx: ToolCtx,\n): Promise<PerPathReadValue> {\n // Image/audio full read: return a media content block instead of throwing\n // INVALID_INPUT (\"Binary file detected.\"). Line-range reads are\n // text-oriented and stay rejected. `readRaw` enforces the same size cap as\n // the text path (getMaxTextFileSize), so a too-large image surfaces TOO_LARGE\n // rather than blowing memory. svg is kind 'image' in EXT_MAP, so readRaw\n // reports it binary and it returns as an image block.\n const isRangeRead = hasLineRange(args);\n if (!isRangeRead) {\n const mime = detectMimeType(filePath);\n if (mime.kind === 'image' || mime.kind === 'audio') {\n const raw = await ctx.fs.readRaw(filePath, { signal: ctx.signal });\n if (raw.isBinary) {\n return {\n content: `[binary ${mime.kind} content: ${String(raw.content.length)} bytes; returned as a ${mime.kind} content block]`,\n mimeType: raw.mimeType,\n kind: mime.kind,\n size: raw.content.length,\n resourceUri: buildFileResourceUri(raw.validPath),\n modified: raw.modified,\n mediaData: raw.content.toString('base64'),\n ...(args.includeHash\n ? { contentHash: createHash('sha256').update(raw.content).digest('hex') }\n : {}),\n };\n }\n }\n }\n\n const spec = buildReadSpec(args, ctx.signal);\n // The read re-validates and re-stats: the budget pass's stat is only a\n // size estimate, never a substitute for the guarded open.\n let result: ReadFileResult;\n try {\n result = await ctx.fs.readFile(filePath, spec);\n } catch (error: unknown) {\n if (!isBinaryRefusal(error)) throw error;\n // The schema refuses binary with a range, so this is always a full read.\n if (args.binary) return await readBinaryResource(filePath, args, ctx);\n throw new FsError(\n ErrorCode.INVALID_INPUT,\n isRangeRead\n ? `${BINARY_FILE_MESSAGE} It has no lines; read it whole with binary: true to get it as a base64 embedded resource.`\n : `${BINARY_FILE_MESSAGE} Pass binary: true to get it as a base64 embedded resource.`,\n filePath,\n error,\n );\n }\n\n return buildPerPathReadValue(result, {\n includeHash: args.includeHash,\n // The continuation is args the caller pastes back, so it echoes the path\n // they wrote, or the root-resolved one a relative path was rewritten to.\n // `result.path` is the real path — on Windows that is a backslash-doubling\n // JSON string that also spells out the server root.\n requestedPath: filePath,\n });\n}\n\nexport const READ = defineTool<typeof ReadFileInputSchema, BatchResult<ReadPerPathValue>>({\n name: 'read',\n title: 'Read File',\n description:\n 'Read text files, like cat: whole, or one slice via head, tail, or startLine/endLine. ' +\n 'Images and audio return as media; pass binary: true to get any other binary file whole as a base64 embedded resource.',\n input: ReadFileInputSchema,\n readOnlyHint: true,\n deadline: true,\n defaultErrorCode: ErrorCode.NOT_FILE,\n progress: (args) => {\n const isBatch = args.paths !== undefined;\n const name = isBatch ? `${String(args.paths?.length ?? 0)} files` : basename(args.path ?? '');\n if (isBatch) {\n return { label: READ_TOOL_LABEL, subject: name };\n }\n let scope: string | undefined;\n if (args.startLine !== undefined) {\n const end = args.endLine ?? '...';\n scope = `${args.startLine}-${String(end)}`;\n } else if (args.head !== undefined) {\n scope = `head ${args.head}`;\n } else if (args.tail !== undefined) {\n scope = `tail ${args.tail}`;\n }\n return { label: READ_TOOL_LABEL, subject: name, ...(scope ? { scope } : {}) };\n },\n mapPaths: mapSingleOrBatchPaths,\n run: async (args, ctx) => {\n const items: BudgetItem[] =\n args.paths !== undefined\n ? await collectFileBudget(\n args.paths,\n READ_MANY_MAX_TOTAL_BYTES,\n getMaxTextFileSize(),\n ctx,\n { fullRead: !hasLineRange(args), binary: args.binary },\n )\n : [{ path: args.path ?? '' }];\n const { results: ordered, summary } = await runOverPaths(\n items,\n ctx,\n ErrorCode.NOT_FILE,\n ({ path, skip }) => {\n if (skip) throw skip;\n return readOnePath(path, args, ctx);\n },\n );\n\n const resources: ContentBlock[] = [];\n for (const result of ordered) {\n if ('error' in result) continue;\n const v = result.value;\n if (v.blobData !== undefined && v.resourceUri !== undefined && v.mimeType !== undefined) {\n resources.push({\n type: 'resource',\n resource: { uri: v.resourceUri, mimeType: v.mimeType, blob: v.blobData },\n });\n continue;\n }\n // Image/audio full read: emit the media content block alongside the\n // structured value. The base64 lives in v.mediaData (set in readOnePath).\n if (v.mediaData && v.mimeType && (v.kind === 'image' || v.kind === 'audio')) {\n resources.push(\n v.kind === 'image'\n ? { type: 'image', data: v.mediaData, mimeType: v.mimeType }\n : { type: 'audio', data: v.mediaData, mimeType: v.mimeType },\n );\n continue;\n }\n if (!v.resourceUri || v.content === undefined) continue;\n // `result.path` is the path as *requested*; `v.resourceUri` was built from\n // the *validated* one. Rebuilding from the request would emit a second URI\n // for the same file whenever the two differ in case — subscribe by one and\n // unsubscribe by the other and the watcher never goes away.\n resources.push(\n buildFileResourceLinkFor(\n v.resourceUri,\n basename(result.path),\n v.mimeType ?? 'application/octet-stream',\n v.fileSize ?? Buffer.byteLength(v.content, 'utf8'),\n v.modified,\n ),\n );\n }\n\n const [firstOrdered] = ordered;\n const body = (v: PerPathReadValue): string => {\n const content = v.content ?? 'read failed';\n const trailer = readTrailer(v);\n if (trailer.length === 0) return content;\n // Exactly one blank line between the bytes and the trailer, whether or not\n // the file ended in a newline.\n return `${content}${content.endsWith('\\n') ? '\\n' : '\\n\\n'}${trailer.join('\\n')}`;\n };\n const text =\n ordered.length === 1 && firstOrdered !== undefined\n ? 'error' in firstOrdered\n ? firstOrdered.error.message\n : body(firstOrdered.value)\n : ordered\n .map((r) => {\n const header = `// ${r.path}`;\n if ('value' in r) return `${header}\\n${body(r.value)}`;\n return `${header}\\n// Error: ${r.error.message}`;\n })\n .join('\\n\\n');\n\n // The bytes ship once. `text` above already carries every file's content\n // verbatim (and image/audio bytes ride the media content block), so\n // repeating them under `results[].value` doubled both the wire payload and\n // the model's token cost for every read. The structured half keeps the\n // metadata a client cannot recover from the text: paths, line counts,\n // hashes, continuations, resourceUri.\n const structuredResults = ordered.map((result) => {\n if ('error' in result) return result;\n const {\n content: _content,\n fileSize: _fileSize,\n mediaData: _mediaData,\n blobData: _blobData,\n ...value\n } = result.value;\n return { ...result, value };\n });\n\n return {\n structured: { results: structuredResults, summary },\n text,\n isError: isTotalFailure(summary),\n ...(resources.length > 0 ? { resources } : {}),\n };\n },\n // Media and binary resources cannot be sliced, so head/tail is no remedy.\n oversizeRemedy: (result) => {\n const types = new Set(result.resources?.map((b) => b.type));\n if (types.has('image') || types.has('audio')) {\n return 'This media file is too large to return over the stdio transport; connect over HTTP, or raise it as a smaller file.';\n }\n if (types.has('resource')) {\n return 'This binary file is too large to return over the stdio transport; connect over HTTP.';\n }\n return 'Read a slice with head, tail, or startLine/endLine.';\n },\n});\n"]}
|
|
1
|
+
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/tools/read.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContentBlock } from '@modelcontextprotocol/server';\n\nimport { createHash } from 'node:crypto';\nimport { basename } from 'node:path';\n\nimport * as z from 'zod/v4';\n\nimport { processInParallel } from '../core/concurrency.ts';\nimport { ErrorCode, FsError } from '../core/errors.ts';\nimport { buildFileResourceLinkFor, buildFileResourceUri } from '../core/file-uri.ts';\nimport {\n detectMimeFromContent,\n detectMimeType,\n type FileKind,\n isKnownBinaryExtension,\n} from '../core/mime.ts';\nimport {\n BINARY_FILE_MESSAGE,\n isBinaryRefusal,\n type ReadFileResult,\n type ReadSpec,\n} from '../core/read.ts';\nimport {\n defaultFalseBoolean,\n mapSingleOrBatchPaths,\n singleOrBatchPathsInput,\n validateReadRange,\n} from '../core/schema.ts';\nimport {\n base64EncodedBytes,\n DEFAULT_CONTINUATION_CHUNK_SIZE,\n getMaxTextFileSize,\n PARALLEL_CONCURRENCY,\n READ_MANY_MAX_TOTAL_BYTES,\n} from '../core/util.ts';\nimport type { BatchResult } from './batch.ts';\nimport { isTotalFailure, runOverPaths } from './batch.ts';\nimport type { ToolCtx } from './define.ts';\nimport { defineTool } from './define.ts';\n\n/**\n * `z.int32()`'s own ceiling on startLine/endLine, named so a continuation\n * never asks for more. Not restated as `.max()`: that reports it twice.\n */\nconst MAX_LINE_NUMBER = 2_147_483_647;\n\n/** One spelling of the resource-content digest every read result that carries a hash uses. */\nconst sha256Hex = (data: string | Buffer): string =>\n createHash('sha256').update(data).digest('hex');\n\nconst rangeField = (description: string, count = false) => {\n const field = z.int32().min(1, { message: 'Min: 1' });\n return (count ? field.max(100000, { message: 'Max: 100,000' }) : field)\n .optional()\n .describe(description);\n};\n\nconst readRangeFields = {\n head: rangeField('Return first N lines', true),\n tail: rangeField('Return last N lines', true),\n startLine: rangeField('Start line (1-indexed)'),\n endLine: rangeField('End line (1-indexed); requires startLine'),\n};\n\n/** A slice read: only a full read returns media or a binary resource. */\nfunction hasLineRange(args: {\n head?: number | undefined;\n tail?: number | undefined;\n startLine?: number | undefined;\n endLine?: number | undefined;\n}): boolean {\n return (\n args.head !== undefined ||\n args.tail !== undefined ||\n args.startLine !== undefined ||\n args.endLine !== undefined\n );\n}\n\nconst ReadFileInputSchema = singleOrBatchPathsInput({\n includeHash: defaultFalseBoolean('Include SHA-256 hash of the returned content in the response'),\n binary: defaultFalseBoolean(\n 'Return a binary file that is not an image or audio whole, as a base64 embedded resource. Full reads only.',\n ),\n ...readRangeFields,\n}).superRefine((value, ctx) => {\n validateReadRange(\n {\n head: value.head,\n tail: value.tail,\n startLine: value.startLine,\n endLine: value.endLine,\n },\n ctx,\n );\n if (value.binary && hasLineRange(value)) {\n ctx.addIssue({\n code: 'custom',\n path: ['binary'],\n message:\n \"Cannot use 'binary' with 'head'/'tail'/'startLine'/'endLine'. A binary file is read whole.\",\n input: value,\n });\n }\n});\n\ninterface ReadContinuation {\n tool: 'read';\n args: { path: string; startLine: number; endLine: number };\n hint: string;\n}\n\n// File bytes ride content blocks, never the structured metadata.\ninterface ReadPerPathValue {\n mimeType?: string;\n kind?: FileKind;\n resourceUri?: string;\n /** Bytes in the file; set when the bytes ride a media or resource block. */\n size?: number;\n /** ISO-8601 mtime at read time; also rides the resource_link. */\n modified?: string;\n continuation?: ReadContinuation;\n totalLines?: number;\n linesRead?: number;\n hasMoreLines?: boolean;\n head?: number;\n tail?: number;\n startLine?: number;\n endLine?: number;\n contentHash?: string;\n}\n\ntype ReadFileInput = z.infer<typeof ReadFileInputSchema>;\n\nconst READ_TOOL_LABEL = 'Read';\n\nfunction buildReadSpec(args: ReadFileInput, signal?: AbortSignal): ReadSpec {\n const signalPart = signal ? { signal } : {};\n const { head, tail, startLine, endLine } = args;\n\n if (head !== undefined) return { kind: 'head', lines: head, ...signalPart };\n if (tail !== undefined) return { kind: 'tail', lines: tail, ...signalPart };\n if (startLine !== undefined || endLine !== undefined) {\n return {\n kind: 'range',\n start: startLine ?? 1,\n ...(endLine !== undefined ? { end: endLine } : {}),\n ...signalPart,\n };\n }\n return { kind: 'full', ...signalPart };\n}\n\n// No `totalLines`: only `readFull` counts them and a full read never leaves\n// more behind, so a continuation cannot know the total without a second pass.\nfunction buildReadContinuation(\n result: ReadFileResult,\n requestedPath: string,\n): ReadContinuation | undefined {\n if (!result.hasMoreLines) return undefined;\n const linesRead = result.linesRead ?? 0;\n const nextStart = (result.startLine ?? 1) + linesRead;\n // Args the schema would reject are no continuation; clamp the end into it.\n if (nextStart > MAX_LINE_NUMBER) return undefined;\n let chunkSize: number;\n if (result.head !== undefined) {\n chunkSize = result.head;\n } else if (result.startLine !== undefined && result.endLine !== undefined) {\n chunkSize = result.endLine - result.startLine + 1;\n } else {\n chunkSize = DEFAULT_CONTINUATION_CHUNK_SIZE;\n }\n const nextEnd = Math.min(nextStart + chunkSize - 1, MAX_LINE_NUMBER);\n return {\n tool: 'read',\n args: { path: requestedPath, startLine: nextStart, endLine: nextEnd },\n hint: `More lines remain from ${String(nextStart)}. Read next chunk with these args.`,\n };\n}\n\n/**\n * The published metadata plus the bytes this call read. `content`, `mediaData`\n * and `blobData` exist only between `readOnePath` and the content blocks `run`\n * builds from them — they are stripped before the structured half is returned,\n * which is why they are not in `ReadPerPathValue`.\n */\ntype PerPathReadValue = ReadPerPathValue & {\n content?: string;\n fileSize?: number;\n mediaData?: string;\n blobData?: string;\n};\n\ninterface BatchFileInfo {\n index: number;\n size: number;\n}\n\ninterface BudgetItem {\n path: string;\n skip?: FsError;\n}\n\ninterface BudgetMode {\n fullRead: boolean;\n binary: boolean;\n}\n\n/**\n * What a file costs the batch: one whose bytes ship as base64 costs that size.\n * Only a full read ships base64; a slice of an svg is text.\n */\nfunction budgetBytes(path: string, size: number, { fullRead, binary }: BudgetMode): number {\n if (!fullRead) return size;\n const { kind } = detectMimeType(path);\n const base64 = kind === 'image' || kind === 'audio' || (binary && isKnownBinaryExtension(path));\n return base64 ? base64EncodedBytes(size) : size;\n}\n\nasync function collectFileBudget(\n filePaths: readonly string[],\n maxTotalSize: number,\n maxSize: number,\n ctx: Pick<ToolCtx, 'fs' | 'signal' | 'log'>,\n mode: BudgetMode,\n): Promise<BudgetItem[]> {\n const indexed = filePaths.map((path, index) => ({ path, index }));\n const { results } = await processInParallel(\n indexed,\n async ({ path, index }): Promise<BatchFileInfo | undefined> => {\n try {\n const out = await ctx.fs.stat(path);\n return { index, size: budgetBytes(path, Math.min(out.stats.size, maxSize), mode) };\n } catch (err: unknown) {\n ctx.log('debug', `collectFileBudget: stat failed for \"${path}\": ${String(err)}`, 'read');\n return undefined;\n }\n },\n PARALLEL_CONCURRENCY,\n ctx.signal,\n );\n\n const byIndex = new Map<number, BatchFileInfo>();\n for (const { value: item } of results) {\n if (item) byIndex.set(item.index, item);\n }\n\n let total = 0;\n return filePaths.map((path, i): BudgetItem => {\n const info = byIndex.get(i);\n // A failed stat is not skipped, so its read surfaces the\n // real error, not a misleading TOO_LARGE.\n if (info === undefined) return { path };\n // Skip this file only; a later, smaller file that still fits is read.\n if (total + info.size > maxTotalSize) {\n return {\n path,\n skip: new FsError(\n ErrorCode.TOO_LARGE,\n `Skipped: this file alone would push the batch past maxTotalSize (${String(maxTotalSize)} bytes). Read it on its own with path instead of paths.`,\n path,\n ),\n };\n }\n total += info.size;\n return { path };\n });\n}\n\nfunction buildPerPathReadValue(\n result: ReadFileResult,\n options: { includeHash?: boolean; requestedPath: string },\n): PerPathReadValue {\n const mimeInfo = detectMimeFromContent(result.path, result.content);\n const continuation =\n result.hasMoreLines && result.readMode !== 'tail'\n ? buildReadContinuation(result, options.requestedPath)\n : undefined;\n const contentHash = options.includeHash ? sha256Hex(result.content) : undefined;\n\n const canLink = result.fileSize === undefined || result.fileSize <= getMaxTextFileSize();\n\n return {\n content: result.content,\n ...(result.fileSize !== undefined ? { fileSize: result.fileSize } : {}),\n mimeType: mimeInfo.mimeType,\n kind: mimeInfo.kind,\n ...(continuation ? { continuation } : {}),\n ...(result.totalLines !== undefined ? { totalLines: result.totalLines } : {}),\n ...(result.linesRead !== undefined ? { linesRead: result.linesRead } : {}),\n ...(result.hasMoreLines ? { hasMoreLines: true } : {}),\n ...(result.head !== undefined ? { head: result.head } : {}),\n ...(result.tail !== undefined ? { tail: result.tail } : {}),\n ...(result.startLine !== undefined ? { startLine: result.startLine } : {}),\n ...(result.endLine !== undefined ? { endLine: result.endLine } : {}),\n ...(contentHash !== undefined ? { contentHash } : {}),\n ...(canLink ? { resourceUri: buildFileResourceUri(result.path) } : {}),\n modified: result.modified,\n };\n}\n\n/**\n * The two facts the model cannot act on without: that lines were dropped, and\n * the exact args to get the next chunk. Both used to live only in the structured\n * half, which no longer reaches the model. Each line is `//` prefixed and set\n * off by a blank line so it cannot be read as file bytes — do not drop either\n * guard.\n */\nfunction readTrailer(v: PerPathReadValue): string[] {\n const lines: string[] = [];\n if (v.continuation) {\n lines.push(\n `// truncated: ${v.continuation.hint} Continue: read ${JSON.stringify(v.continuation.args)}`,\n );\n } else if (v.hasMoreLines && v.linesRead !== undefined) {\n // A tail read gets no continuation — there are no args that read *backwards*\n // — so say what was shown rather than leaving the truncation silent.\n lines.push(`// truncated: showing last ${String(v.linesRead)} lines`);\n }\n if (v.contentHash !== undefined) lines.push(`// sha256: ${v.contentHash}`);\n return lines;\n}\n\n/**\n * `binary: true` after the text path refused the file as binary. readRaw\n * re-validates the path (roots, denylist) and enforces the same size cap.\n * A file refused by its extension can still probe as text: it ships as the\n * extension says, octet-stream.\n */\nasync function readBinaryResource(\n filePath: string,\n args: ReadFileInput,\n ctx: ToolCtx,\n): Promise<PerPathReadValue> {\n const raw = await ctx.fs.readRaw(filePath, { signal: ctx.signal });\n const asText = raw.kind === 'text';\n const kind: FileKind = asText ? 'binary' : raw.kind;\n const mimeType = asText ? 'application/octet-stream' : raw.mimeType;\n const size = raw.content.length;\n return {\n content: `[binary ${kind} content: ${String(size)} bytes (${mimeType}); returned as an embedded resource block]`,\n mimeType,\n kind,\n size,\n resourceUri: buildFileResourceUri(raw.validPath),\n modified: raw.modified,\n blobData: raw.content.toString('base64'),\n ...(args.includeHash ? { contentHash: sha256Hex(raw.content) } : {}),\n };\n}\n\nasync function readOnePath(\n filePath: string,\n args: ReadFileInput,\n ctx: ToolCtx,\n): Promise<PerPathReadValue> {\n // Image/audio full read: return a media content block instead of throwing\n // INVALID_INPUT (\"Binary file detected.\"). Line-range reads are\n // text-oriented and stay rejected. `readRaw` enforces the same size cap as\n // the text path (getMaxTextFileSize), so a too-large image surfaces TOO_LARGE\n // rather than blowing memory. svg is kind 'image' in EXT_MAP, so readRaw\n // reports it binary and it returns as an image block.\n const isRangeRead = hasLineRange(args);\n if (!isRangeRead) {\n const mime = detectMimeType(filePath);\n if (mime.kind === 'image' || mime.kind === 'audio') {\n const raw = await ctx.fs.readRaw(filePath, { signal: ctx.signal });\n if (raw.isBinary) {\n return {\n content: `[binary ${mime.kind} content: ${String(raw.content.length)} bytes; returned as a ${mime.kind} content block]`,\n mimeType: raw.mimeType,\n kind: mime.kind,\n size: raw.content.length,\n resourceUri: buildFileResourceUri(raw.validPath),\n modified: raw.modified,\n mediaData: raw.content.toString('base64'),\n ...(args.includeHash ? { contentHash: sha256Hex(raw.content) } : {}),\n };\n }\n }\n }\n\n const spec = buildReadSpec(args, ctx.signal);\n // The read re-validates and re-stats: the budget pass's stat is only a\n // size estimate, never a substitute for the guarded open.\n let result: ReadFileResult;\n try {\n result = await ctx.fs.readFile(filePath, spec);\n } catch (error: unknown) {\n if (!isBinaryRefusal(error)) throw error;\n // The schema refuses binary with a range, so this is always a full read.\n if (args.binary) return await readBinaryResource(filePath, args, ctx);\n throw new FsError(\n ErrorCode.INVALID_INPUT,\n isRangeRead\n ? `${BINARY_FILE_MESSAGE} It has no lines; read it whole with binary: true to get it as a base64 embedded resource.`\n : `${BINARY_FILE_MESSAGE} Pass binary: true to get it as a base64 embedded resource.`,\n filePath,\n error,\n );\n }\n\n return buildPerPathReadValue(result, {\n includeHash: args.includeHash,\n // The continuation is args the caller pastes back, so it echoes the path\n // they wrote, or the root-resolved one a relative path was rewritten to.\n // `result.path` is the real path — on Windows that is a backslash-doubling\n // JSON string that also spells out the server root.\n requestedPath: filePath,\n });\n}\n\nexport const READ = defineTool<typeof ReadFileInputSchema, BatchResult<ReadPerPathValue>>({\n name: 'read',\n title: 'Read File',\n description:\n 'Read text files, like cat: whole, or one slice via head, tail, or startLine/endLine. ' +\n 'Images and audio return as media; pass binary: true to get any other binary file whole as a base64 embedded resource.',\n input: ReadFileInputSchema,\n readOnlyHint: true,\n deadline: true,\n defaultErrorCode: ErrorCode.NOT_FILE,\n progress: (args) => {\n const isBatch = args.paths !== undefined;\n const name = isBatch ? `${String(args.paths?.length ?? 0)} files` : basename(args.path ?? '');\n if (isBatch) {\n return { label: READ_TOOL_LABEL, subject: name };\n }\n let scope: string | undefined;\n if (args.startLine !== undefined) {\n const end = args.endLine ?? '...';\n scope = `${args.startLine}-${String(end)}`;\n } else if (args.head !== undefined) {\n scope = `head ${args.head}`;\n } else if (args.tail !== undefined) {\n scope = `tail ${args.tail}`;\n }\n return { label: READ_TOOL_LABEL, subject: name, ...(scope ? { scope } : {}) };\n },\n mapPaths: mapSingleOrBatchPaths,\n run: async (args, ctx) => {\n const items: BudgetItem[] =\n args.paths !== undefined\n ? await collectFileBudget(\n args.paths,\n READ_MANY_MAX_TOTAL_BYTES,\n getMaxTextFileSize(),\n ctx,\n { fullRead: !hasLineRange(args), binary: args.binary },\n )\n : [{ path: args.path ?? '' }];\n const { results: ordered, summary } = await runOverPaths(\n items,\n ctx,\n ErrorCode.NOT_FILE,\n ({ path, skip }) => {\n if (skip) throw skip;\n return readOnePath(path, args, ctx);\n },\n );\n\n const resources: ContentBlock[] = [];\n for (const result of ordered) {\n if ('error' in result) continue;\n const v = result.value;\n if (v.blobData !== undefined && v.resourceUri !== undefined && v.mimeType !== undefined) {\n resources.push({\n type: 'resource',\n resource: { uri: v.resourceUri, mimeType: v.mimeType, blob: v.blobData },\n });\n continue;\n }\n // Image/audio full read: emit the media content block alongside the\n // structured value. The base64 lives in v.mediaData (set in readOnePath).\n if (v.mediaData && v.mimeType && (v.kind === 'image' || v.kind === 'audio')) {\n resources.push(\n v.kind === 'image'\n ? { type: 'image', data: v.mediaData, mimeType: v.mimeType }\n : { type: 'audio', data: v.mediaData, mimeType: v.mimeType },\n );\n continue;\n }\n if (!v.resourceUri || v.content === undefined) continue;\n // `result.path` is the path as *requested*; `v.resourceUri` was built from\n // the *validated* one. Rebuilding from the request would emit a second URI\n // for the same file whenever the two differ in case — subscribe by one and\n // unsubscribe by the other and the watcher never goes away.\n resources.push(\n buildFileResourceLinkFor(\n v.resourceUri,\n basename(result.path),\n v.mimeType ?? 'application/octet-stream',\n v.fileSize ?? Buffer.byteLength(v.content, 'utf8'),\n v.modified,\n ),\n );\n }\n\n const [firstOrdered] = ordered;\n const body = (v: PerPathReadValue): string => {\n const content = v.content ?? 'read failed';\n const trailer = readTrailer(v);\n if (trailer.length === 0) return content;\n // Exactly one blank line between the bytes and the trailer, whether or not\n // the file ended in a newline.\n return `${content}${content.endsWith('\\n') ? '\\n' : '\\n\\n'}${trailer.join('\\n')}`;\n };\n const text =\n ordered.length === 1 && firstOrdered !== undefined\n ? 'error' in firstOrdered\n ? firstOrdered.error.message\n : body(firstOrdered.value)\n : ordered\n .map((r) => {\n const header = `// ${r.path}`;\n if ('value' in r) return `${header}\\n${body(r.value)}`;\n return `${header}\\n// Error: ${r.error.message}`;\n })\n .join('\\n\\n');\n\n // The bytes ship once. `text` above already carries every file's content\n // verbatim (and image/audio bytes ride the media content block), so\n // repeating them under `results[].value` doubled both the wire payload and\n // the model's token cost for every read. The structured half keeps the\n // metadata a client cannot recover from the text: paths, line counts,\n // hashes, continuations, resourceUri.\n const structuredResults = ordered.map((result) => {\n if ('error' in result) return result;\n const {\n content: _content,\n fileSize: _fileSize,\n mediaData: _mediaData,\n blobData: _blobData,\n ...value\n } = result.value;\n return { ...result, value };\n });\n\n return {\n structured: { results: structuredResults, summary },\n text,\n isError: isTotalFailure(summary),\n ...(resources.length > 0 ? { resources } : {}),\n };\n },\n // Media and binary resources cannot be sliced, so head/tail is no remedy.\n oversizeRemedy: (result) => {\n const types = new Set(result.resources?.map((b) => b.type));\n if (types.has('image') || types.has('audio')) {\n return 'This media file is too large to return over the stdio transport; connect over HTTP, or raise it as a smaller file.';\n }\n if (types.has('resource')) {\n return 'This binary file is too large to return over the stdio transport; connect over HTTP.';\n }\n return 'Read a slice with head, tail, or startLine/endLine.';\n },\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replace-text.d.ts","sourceRoot":"","sources":["../../src/tools/replace-text.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"replace-text.d.ts","sourceRoot":"","sources":["../../src/tools/replace-text.ts"],"names":[],"mappings":"AAslBA,eAAO,MAAM,YAAY,mCA6FvB,CAAC"}
|
|
@@ -404,6 +404,7 @@ async function handleSearchAndReplace(args, ctx) {
|
|
|
404
404
|
pattern: effectivePattern,
|
|
405
405
|
includeHidden: args.includeHidden,
|
|
406
406
|
skipIgnored: !args.includeIgnored,
|
|
407
|
+
pathGuard: ctx.fs.pathGuard,
|
|
407
408
|
...(ceiling !== undefined ? { ignoreCeiling: ceiling } : {}),
|
|
408
409
|
signal: ctx.signal,
|
|
409
410
|
baseNameMatch: true,
|