@j0hanz/filesystem-mcp 2.8.1 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -26
- package/dist/cli-help.d.ts.map +1 -1
- package/dist/cli-help.js +10 -1
- package/dist/cli-help.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +10 -3
- package/dist/cli.js.map +1 -1
- package/dist/core/concurrency.d.ts +4 -4
- package/dist/core/concurrency.d.ts.map +1 -1
- package/dist/core/concurrency.js +1 -1
- package/dist/core/concurrency.js.map +1 -1
- package/dist/core/config.d.ts +2 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js.map +1 -1
- package/dist/core/file-uri.d.ts +12 -3
- package/dist/core/file-uri.d.ts.map +1 -1
- package/dist/core/file-uri.js +35 -7
- package/dist/core/file-uri.js.map +1 -1
- package/dist/core/fmt.d.ts +2 -0
- package/dist/core/fmt.d.ts.map +1 -1
- package/dist/core/fmt.js +16 -0
- package/dist/core/fmt.js.map +1 -1
- package/dist/core/fs.d.ts +16 -1
- package/dist/core/fs.d.ts.map +1 -1
- package/dist/core/fs.js +127 -32
- package/dist/core/fs.js.map +1 -1
- package/dist/core/glob.d.ts +8 -0
- package/dist/core/glob.d.ts.map +1 -1
- package/dist/core/glob.js +84 -11
- package/dist/core/glob.js.map +1 -1
- package/dist/core/path-completer.d.ts.map +1 -1
- package/dist/core/path-completer.js +5 -3
- package/dist/core/path-completer.js.map +1 -1
- package/dist/core/path-utils.d.ts +42 -6
- package/dist/core/path-utils.d.ts.map +1 -1
- package/dist/core/path-utils.js +56 -10
- package/dist/core/path-utils.js.map +1 -1
- package/dist/core/path.d.ts +111 -7
- package/dist/core/path.d.ts.map +1 -1
- package/dist/core/path.js +453 -65
- package/dist/core/path.js.map +1 -1
- package/dist/core/read.d.ts +6 -0
- package/dist/core/read.d.ts.map +1 -1
- package/dist/core/read.js +26 -3
- package/dist/core/read.js.map +1 -1
- package/dist/core/schema.d.ts +9 -6
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/schema.js +22 -19
- package/dist/core/schema.js.map +1 -1
- package/dist/core/search.d.ts +6 -0
- package/dist/core/search.d.ts.map +1 -1
- package/dist/core/search.js +159 -33
- package/dist/core/search.js.map +1 -1
- package/dist/core/sensitive.d.ts.map +1 -1
- package/dist/core/sensitive.js +64 -15
- package/dist/core/sensitive.js.map +1 -1
- package/dist/core/store.d.ts +1 -0
- package/dist/core/store.d.ts.map +1 -1
- package/dist/core/store.js +3 -0
- package/dist/core/store.js.map +1 -1
- package/dist/core/util.d.ts +6 -1
- package/dist/core/util.d.ts.map +1 -1
- package/dist/core/util.js +8 -1
- package/dist/core/util.js.map +1 -1
- package/dist/resources.d.ts.map +1 -1
- package/dist/resources.js +18 -9
- package/dist/resources.js.map +1 -1
- package/dist/server.js +1 -1
- package/dist/server.js.map +1 -1
- package/dist/tools/create.d.ts.map +1 -1
- package/dist/tools/create.js +121 -43
- package/dist/tools/create.js.map +1 -1
- package/dist/tools/define.d.ts +8 -4
- package/dist/tools/define.d.ts.map +1 -1
- package/dist/tools/define.js +36 -9
- package/dist/tools/define.js.map +1 -1
- package/dist/tools/delete.d.ts.map +1 -1
- package/dist/tools/delete.js +50 -11
- package/dist/tools/delete.js.map +1 -1
- package/dist/tools/diff.js +1 -1
- package/dist/tools/diff.js.map +1 -1
- package/dist/tools/edit.d.ts.map +1 -1
- package/dist/tools/edit.js +14 -12
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/find-files.d.ts.map +1 -1
- package/dist/tools/find-files.js +15 -9
- package/dist/tools/find-files.js.map +1 -1
- package/dist/tools/list.d.ts.map +1 -1
- package/dist/tools/list.js +138 -86
- package/dist/tools/list.js.map +1 -1
- package/dist/tools/move.d.ts.map +1 -1
- package/dist/tools/move.js +72 -26
- package/dist/tools/move.js.map +1 -1
- package/dist/tools/patch.js +13 -6
- package/dist/tools/patch.js.map +1 -1
- package/dist/tools/read.d.ts.map +1 -1
- package/dist/tools/read.js +114 -45
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/replace-text.d.ts.map +1 -1
- package/dist/tools/replace-text.js +49 -35
- package/dist/tools/replace-text.js.map +1 -1
- package/dist/tools/search-text.d.ts.map +1 -1
- package/dist/tools/search-text.js +15 -33
- package/dist/tools/search-text.js.map +1 -1
- package/dist/tools/stat.d.ts.map +1 -1
- package/dist/tools/stat.js +26 -8
- package/dist/tools/stat.js.map +1 -1
- package/dist/transport/http.d.ts.map +1 -1
- package/dist/transport/http.js +1 -0
- package/dist/transport/http.js.map +1 -1
- package/dist/transport/stdio.js +1 -1
- package/dist/transport/stdio.js.map +1 -1
- package/package.json +5 -5
package/dist/tools/list.js
CHANGED
|
@@ -1,66 +1,59 @@
|
|
|
1
|
+
import { stat } from 'node:fs/promises';
|
|
1
2
|
import { basename, posix } from 'node:path';
|
|
2
3
|
import * as z from 'zod/v4';
|
|
4
|
+
import { processEntriesConcurrently, withAbort } from "../core/concurrency.js";
|
|
3
5
|
import { pageQueryKey, paginate } from "../core/cursor.js";
|
|
4
|
-
import { ErrorCode,
|
|
5
|
-
import { pageTrailer } from "../core/fmt.js";
|
|
6
|
+
import { ErrorCode, normalizeUnknownError, rethrowIfAborted } from "../core/errors.js";
|
|
7
|
+
import { formatByteSize, formatCount, pageTrailer } from "../core/fmt.js";
|
|
6
8
|
import { globEntries } from "../core/glob.js";
|
|
7
9
|
import { resolveEntryType, toPosixRelative } from "../core/path-utils.js";
|
|
8
|
-
import { CursorSchema, IncludeHidden, IncludeIgnored, OptionalPath, PositiveInt, } from "../core/schema.js";
|
|
10
|
+
import { CursorSchema, defaultFalseBoolean, IncludeHidden, IncludeIgnored, mapOptionalPath, OptionalPath, PositiveInt, } from "../core/schema.js";
|
|
9
11
|
import { putJsonResource } from "../core/store.js";
|
|
10
|
-
import {
|
|
12
|
+
import { DEFAULT_TREE_ENTRIES, MAX_LIST_ENTRIES, MAX_TREE_DEPTH, PARALLEL_CONCURRENCY, } from "../core/util.js";
|
|
11
13
|
import { defineTool } from "./define.js";
|
|
12
14
|
function entryTypeRank(type) {
|
|
13
15
|
if (type === 'directory')
|
|
14
16
|
return 0;
|
|
15
17
|
return 1;
|
|
16
18
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
* symlinked ancestor pointing outside the sandbox would otherwise pass the
|
|
35
|
-
* lexical check (fs.glob follows symlinks and yields external entries as
|
|
36
|
-
* non-symlink dirents). Escapes and sensitive targets throw ACCESS_DENIED and
|
|
37
|
-
* skippable errors filter the entry; anything else is fatal. The accepted
|
|
38
|
-
* TOCTOU window is documented on PathGuard.
|
|
39
|
-
*/
|
|
40
|
-
async function isEntryAccessible(guard, entryPath) {
|
|
41
|
-
try {
|
|
42
|
-
const { requestedPath, resolvedPath } = await guard.validateExistingPathDetailed(entryPath);
|
|
43
|
-
return !guard.isSensitive(requestedPath) && !guard.isSensitive(resolvedPath);
|
|
44
|
-
}
|
|
45
|
-
catch (error) {
|
|
46
|
-
if (isFsError(error)) {
|
|
47
|
-
if (SKIPPABLE_FS_CODES.has(error.code))
|
|
48
|
-
return false;
|
|
49
|
-
throw error;
|
|
19
|
+
// Compare by parent directory first (depth-level grouping), then within the
|
|
20
|
+
// same parent: directories first, then by size (descending) or alphabetical.
|
|
21
|
+
function entryComparator(sortBy) {
|
|
22
|
+
return (a, b) => {
|
|
23
|
+
const slashA = a.relativePath.lastIndexOf('/');
|
|
24
|
+
const slashB = b.relativePath.lastIndexOf('/');
|
|
25
|
+
const parentA = slashA === -1 ? '' : a.relativePath.slice(0, slashA);
|
|
26
|
+
const parentB = slashB === -1 ? '' : b.relativePath.slice(0, slashB);
|
|
27
|
+
if (parentA !== parentB)
|
|
28
|
+
return parentA.localeCompare(parentB);
|
|
29
|
+
const rankDiff = entryTypeRank(a.type) - entryTypeRank(b.type);
|
|
30
|
+
if (rankDiff !== 0)
|
|
31
|
+
return rankDiff;
|
|
32
|
+
if (sortBy === 'size') {
|
|
33
|
+
const sizeDiff = (b.size ?? 0) - (a.size ?? 0);
|
|
34
|
+
if (sizeDiff !== 0)
|
|
35
|
+
return sizeDiff;
|
|
50
36
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
throw error;
|
|
54
|
-
}
|
|
37
|
+
return a.name.localeCompare(b.name);
|
|
38
|
+
};
|
|
55
39
|
}
|
|
56
40
|
async function collect(rootPath, options) {
|
|
57
41
|
const entries = [];
|
|
42
|
+
const wantSizes = options.includeSizes || options.sortBy === 'size';
|
|
58
43
|
let scanned = 0;
|
|
59
44
|
let totalEntries = 0;
|
|
60
45
|
let totalFiles = 0;
|
|
61
46
|
let totalDirectories = 0;
|
|
47
|
+
let totalBytes = 0;
|
|
48
|
+
let fatalError;
|
|
62
49
|
const ceiling = options.pathGuard.allowedRootContaining(rootPath);
|
|
63
|
-
|
|
50
|
+
const comparator = entryComparator(options.sortBy);
|
|
51
|
+
const keepBest = () => {
|
|
52
|
+
entries.sort(comparator);
|
|
53
|
+
if (entries.length > options.entryCap)
|
|
54
|
+
entries.length = options.entryCap;
|
|
55
|
+
};
|
|
56
|
+
await processEntriesConcurrently(globEntries({
|
|
64
57
|
cwd: rootPath,
|
|
65
58
|
pattern: '**/*',
|
|
66
59
|
skipIgnored: !options.includeIgnored,
|
|
@@ -73,46 +66,84 @@ async function collect(rootPath, options) {
|
|
|
73
66
|
// is guaranteed >= 1 by its PositiveInt schema, so this never underflows.
|
|
74
67
|
maxDepth: options.maxDepth - 1,
|
|
75
68
|
onlyFiles: false,
|
|
76
|
-
})
|
|
77
|
-
options.signal
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
69
|
+
}), {
|
|
70
|
+
signal: options.signal,
|
|
71
|
+
concurrency: PARALLEL_CONCURRENCY,
|
|
72
|
+
onEntry: () => {
|
|
73
|
+
scanned++;
|
|
74
|
+
options.onProgress({ current: scanned });
|
|
75
|
+
},
|
|
76
|
+
onError: (_entryPath, err) => {
|
|
77
|
+
fatalError ??= normalizeUnknownError(err);
|
|
78
|
+
},
|
|
79
|
+
runEntry: async (_entryPath, entry) => {
|
|
80
|
+
const entryType = resolveEntryType(entry.dirent);
|
|
81
|
+
const relPath = toPosixRelative(rootPath, entry.path);
|
|
82
|
+
const name = basename(relPath);
|
|
83
|
+
for (let dir = posix.dirname(relPath); dir !== '.'; dir = posix.dirname(dir)) {
|
|
84
|
+
if (options.pathGuard.isSensitive(`${rootPath}/${dir}`))
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const accessible = await options.pathGuard.isEntryAccessible(entry.path);
|
|
88
|
+
if (!accessible)
|
|
89
|
+
return;
|
|
90
|
+
let size;
|
|
91
|
+
if (wantSizes && entryType === 'file') {
|
|
92
|
+
try {
|
|
93
|
+
size = (await withAbort(stat(entry.path), options.signal)).size;
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
rethrowIfAborted(error);
|
|
97
|
+
// A file can vanish between the walk and the stat; it keeps its place, without a size.
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
totalEntries++;
|
|
101
|
+
if (entryType === 'directory') {
|
|
102
|
+
totalDirectories++;
|
|
103
|
+
}
|
|
104
|
+
else if (entryType === 'file') {
|
|
105
|
+
totalFiles++;
|
|
106
|
+
if (size !== undefined)
|
|
107
|
+
totalBytes += size;
|
|
108
|
+
}
|
|
109
|
+
entries.push({
|
|
110
|
+
name,
|
|
111
|
+
relativePath: relPath,
|
|
112
|
+
type: entryType,
|
|
113
|
+
...(size !== undefined ? { size } : {}),
|
|
114
|
+
});
|
|
115
|
+
// Keep at most the best entryCap: prune whenever the buffer doubles,
|
|
116
|
+
// so memory stays O(entryCap) and the sorts O(n log entryCap) overall.
|
|
117
|
+
if (entries.length >= options.entryCap * 2)
|
|
118
|
+
keepBest();
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
if (fatalError !== undefined)
|
|
122
|
+
throw fatalError;
|
|
102
123
|
options.signal.throwIfAborted();
|
|
103
|
-
|
|
124
|
+
keepBest();
|
|
104
125
|
return {
|
|
105
126
|
entries,
|
|
106
127
|
totalEntries,
|
|
107
128
|
totalFiles,
|
|
108
129
|
totalDirectories,
|
|
130
|
+
...(wantSizes ? { totalBytes } : {}),
|
|
109
131
|
};
|
|
110
132
|
}
|
|
111
133
|
const TEE = '├── ';
|
|
112
134
|
const ELBOW = '└── ';
|
|
113
135
|
const PIPE = '│ ';
|
|
114
136
|
const INDENT = ' ';
|
|
115
|
-
|
|
137
|
+
/**
|
|
138
|
+
* The tree's first line names the listed folder the way the caller passes it
|
|
139
|
+
* back: `src/core`, not `core`, which would name `<root>/core`. A root keeps
|
|
140
|
+
* its own name.
|
|
141
|
+
*/
|
|
142
|
+
function treeHeader(pathGuard, dir) {
|
|
143
|
+
const paths = pathGuard.resultPaths(dir);
|
|
144
|
+
return paths.atRoot ? basename(paths.root) : paths.show(dir);
|
|
145
|
+
}
|
|
146
|
+
function renderMarkdown(rootName, page, opts) {
|
|
116
147
|
if (page.length === 0)
|
|
117
148
|
return rootName;
|
|
118
149
|
// The tree is drawn down from the root, but a later page (or a capped set)
|
|
@@ -126,7 +157,7 @@ function renderMarkdown(rootName, page) {
|
|
|
126
157
|
entries.push({ name: posix.basename(dir), relativePath: dir, type: 'directory' });
|
|
127
158
|
}
|
|
128
159
|
}
|
|
129
|
-
entries.sort(
|
|
160
|
+
entries.sort(entryComparator(opts.sortBy));
|
|
130
161
|
// Group entries by parent path
|
|
131
162
|
const childrenOf = new Map();
|
|
132
163
|
for (const entry of entries) {
|
|
@@ -149,7 +180,8 @@ function renderMarkdown(rootName, page) {
|
|
|
149
180
|
continue;
|
|
150
181
|
const isLast = i === children.length - 1;
|
|
151
182
|
const connector = isLast ? ELBOW : TEE;
|
|
152
|
-
|
|
183
|
+
const sizeText = opts.includeSizes && child.size !== undefined ? ` (${formatByteSize(child.size)})` : '';
|
|
184
|
+
lines.push(prefix + connector + child.name + (child.type === 'directory' ? '/' : '') + sizeText);
|
|
153
185
|
const childKey = child.relativePath;
|
|
154
186
|
const nextPrefix = prefix + (isLast ? INDENT : PIPE);
|
|
155
187
|
renderChildren(childKey, nextPrefix);
|
|
@@ -158,6 +190,10 @@ function renderMarkdown(rootName, page) {
|
|
|
158
190
|
renderChildren('', '');
|
|
159
191
|
return lines.join('\n');
|
|
160
192
|
}
|
|
193
|
+
/** The `//` line `includeSizes` appends: counts and bytes over the whole collected set. */
|
|
194
|
+
function summaryLine(metadata, totalBytes) {
|
|
195
|
+
return `\n\n// ${formatCount(metadata.totalFiles, 'file')}, ${formatCount(metadata.totalDirectories, 'directory')}, ${formatByteSize(totalBytes)} total`;
|
|
196
|
+
}
|
|
161
197
|
const DEFAULT_LIST_DEPTH = 1;
|
|
162
198
|
const ListInputSchema = z.strictObject({
|
|
163
199
|
path: OptionalPath.describe('Directory to list (default: first allowed root)'),
|
|
@@ -169,24 +205,31 @@ const ListInputSchema = z.strictObject({
|
|
|
169
205
|
.describe(`Page size (default: ${String(DEFAULT_TREE_ENTRIES)}). Continue with nextCursor; an incomplete first page also carries resourceUri for the whole list.`),
|
|
170
206
|
includeHidden: IncludeHidden,
|
|
171
207
|
includeIgnored: IncludeIgnored,
|
|
208
|
+
includeSizes: defaultFalseBoolean('Show file sizes in the tree and a totals line of counts and bytes'),
|
|
209
|
+
sortBy: z
|
|
210
|
+
.enum(['name', 'size'])
|
|
211
|
+
.optional()
|
|
212
|
+
.default('name')
|
|
213
|
+
.describe('Order within each directory: name (default) or size (largest first)'),
|
|
172
214
|
cursor: CursorSchema,
|
|
173
215
|
});
|
|
174
216
|
export const LIST = defineTool({
|
|
175
217
|
name: 'list',
|
|
176
218
|
title: 'List',
|
|
177
219
|
description: "List a directory's files and subdirectories as a tree of names, like ls or tree. " +
|
|
178
|
-
'
|
|
220
|
+
'includeSizes adds sizes and a total; stat returns dates.',
|
|
179
221
|
input: ListInputSchema,
|
|
180
222
|
readOnlyHint: true,
|
|
181
|
-
|
|
223
|
+
deadline: true,
|
|
182
224
|
defaultErrorCode: ErrorCode.NOT_DIRECTORY,
|
|
183
225
|
progress: (args) => ({
|
|
184
226
|
label: 'List',
|
|
185
227
|
subject: args.path ? basename(args.path) : '.',
|
|
186
228
|
}),
|
|
187
|
-
|
|
229
|
+
mapPaths: mapOptionalPath,
|
|
188
230
|
run: async (args, ctx) => {
|
|
189
231
|
const resolvedPath = ctx.fs.pathGuard.resolvePathOrRoot(args.path);
|
|
232
|
+
const renderOpts = { includeSizes: args.includeSizes, sortBy: args.sortBy };
|
|
190
233
|
const paged = await paginate({
|
|
191
234
|
store: ctx.pageStore,
|
|
192
235
|
queryKey: pageQueryKey('list', { ...args, path: resolvedPath }, ['cursor', 'maxEntries']),
|
|
@@ -195,6 +238,7 @@ export const LIST = defineTool({
|
|
|
195
238
|
produce: async () => {
|
|
196
239
|
const validDir = await ctx.fs.pathGuard.validateExistingDirectory(resolvedPath);
|
|
197
240
|
const result = await collect(validDir, {
|
|
241
|
+
...renderOpts,
|
|
198
242
|
maxDepth: args.maxDepth,
|
|
199
243
|
includeHidden: args.includeHidden,
|
|
200
244
|
includeIgnored: args.includeIgnored,
|
|
@@ -210,6 +254,7 @@ export const LIST = defineTool({
|
|
|
210
254
|
totalEntries: result.totalEntries,
|
|
211
255
|
totalFiles: result.totalFiles,
|
|
212
256
|
totalDirectories: result.totalDirectories,
|
|
257
|
+
...(result.totalBytes !== undefined ? { totalBytes: result.totalBytes } : {}),
|
|
213
258
|
},
|
|
214
259
|
truncated: result.totalEntries > result.entries.length,
|
|
215
260
|
};
|
|
@@ -219,10 +264,11 @@ export const LIST = defineTool({
|
|
|
219
264
|
// The stored tree is the whole collected set, bounded by the hard cap.
|
|
220
265
|
const fullOutput = {
|
|
221
266
|
entries,
|
|
222
|
-
markdown: renderMarkdown(
|
|
267
|
+
markdown: renderMarkdown(treeHeader(ctx.fs.pathGuard, metadata.path), entries, renderOpts),
|
|
223
268
|
totalEntries: metadata.totalEntries,
|
|
224
269
|
totalFiles: metadata.totalFiles,
|
|
225
270
|
totalDirectories: metadata.totalDirectories,
|
|
271
|
+
...(metadata.totalBytes !== undefined ? { totalBytes: metadata.totalBytes } : {}),
|
|
226
272
|
...(metadata.totalEntries > entries.length ? { truncated: true } : {}),
|
|
227
273
|
};
|
|
228
274
|
return putJsonResource(ctx.resourceStore, `${name} tree`, fullOutput);
|
|
@@ -238,16 +284,22 @@ export const LIST = defineTool({
|
|
|
238
284
|
// The tree is what the model reads, so position and the full-list URI ride
|
|
239
285
|
// the text too — paging needs no second lookup. `pageTrailer` is the one
|
|
240
286
|
// owner of that line, and it owes it on the last page as much as the first.
|
|
241
|
-
const
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
287
|
+
const sizesLine = paged.metadata.totalBytes !== undefined && args.includeSizes
|
|
288
|
+
? summaryLine(paged.metadata, paged.metadata.totalBytes)
|
|
289
|
+
: '';
|
|
290
|
+
const trailer = pageTrailer({
|
|
291
|
+
offset: paged.offset,
|
|
292
|
+
shown: structured.entryCount,
|
|
293
|
+
total: structured.totalEntries,
|
|
294
|
+
noun: 'entries',
|
|
295
|
+
tool: 'list',
|
|
296
|
+
nextCursor: structured.nextCursor,
|
|
297
|
+
nextArgs: args,
|
|
298
|
+
...(structured.totalEntries > MAX_LIST_ENTRIES ? { stoppedReason: 'maxResults' } : {}),
|
|
299
|
+
});
|
|
300
|
+
const text = renderMarkdown(treeHeader(ctx.fs.pathGuard, paged.metadata.path), [...paged.page], renderOpts) +
|
|
301
|
+
sizesLine +
|
|
302
|
+
(sizesLine && trailer ? trailer.slice(1) : trailer) +
|
|
251
303
|
(structured.resourceUri !== undefined ? `\nfull tree at ${structured.resourceUri}` : '');
|
|
252
304
|
return {
|
|
253
305
|
structured,
|
package/dist/tools/list.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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 { pageQueryKey, paginate } from '../core/cursor.ts';\nimport { ErrorCode, isFsError, isSkippableErrno, SKIPPABLE_FS_CODES } from '../core/errors.ts';\nimport { pageTrailer } from '../core/fmt.ts';\nimport { globEntries } 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 IncludeHidden,\n IncludeIgnored,\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_SEARCH_TIMEOUT_MS,\n DEFAULT_TREE_ENTRIES,\n MAX_LIST_ENTRIES,\n MAX_TREE_DEPTH,\n} from '../core/util.ts';\nimport { defineTool } from './define.ts';\n\ninterface CollectedEntry {\n name: string;\n relativePath: string; // POSIX\n type: EntryType;\n}\n\ninterface CollectOptions {\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}\n\nfunction entryTypeRank(type: EntryType): number {\n if (type === 'directory') return 0;\n return 1;\n}\n\nfunction compareEntries(a: CollectedEntry, b: CollectedEntry): number {\n // Compare by parent directory first (depth-level grouping)\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\n if (parentA !== parentB) return parentA.localeCompare(parentB);\n\n // Within same parent: dirs first, then alphabetical\n const rankDiff = entryTypeRank(a.type) - entryTypeRank(b.type);\n if (rankDiff !== 0) return rankDiff;\n return a.name.localeCompare(b.name);\n}\n\n/**\n * True when a walked entry is inside the allowed directories and not sensitive,\n * on both its requested and resolved paths. Every entry is realpath-resolved: a\n * symlinked ancestor pointing outside the sandbox would otherwise pass the\n * lexical check (fs.glob follows symlinks and yields external entries as\n * non-symlink dirents). Escapes and sensitive targets throw ACCESS_DENIED and\n * skippable errors filter the entry; anything else is fatal. The accepted\n * TOCTOU window is documented on PathGuard.\n */\nasync function isEntryAccessible(guard: PathGuard, entryPath: string): Promise<boolean> {\n try {\n const { requestedPath, resolvedPath } = await guard.validateExistingPathDetailed(entryPath);\n return !guard.isSensitive(requestedPath) && !guard.isSensitive(resolvedPath);\n } catch (error) {\n if (isFsError(error)) {\n if (SKIPPABLE_FS_CODES.has(error.code)) return false;\n throw error;\n }\n if (isSkippableErrno(error)) return false;\n throw error;\n }\n}\n\nasync function collect(rootPath: string, options: CollectOptions): Promise<CollectResult> {\n const entries: CollectedEntry[] = [];\n let scanned = 0;\n let totalEntries = 0;\n let totalFiles = 0;\n let totalDirectories = 0;\n const ceiling = options.pathGuard.allowedRootContaining(rootPath);\n\n for await (const entry of 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 options.signal.throwIfAborted();\n scanned++;\n options.onProgress({ current: scanned });\n\n const entryType: EntryType = resolveEntryType(entry.dirent);\n const relPath = toPosixRelative(rootPath, entry.path);\n const name = basename(relPath);\n\n const accessible = await isEntryAccessible(options.pathGuard, entry.path);\n if (!accessible) continue;\n\n totalEntries++;\n if (entryType === 'directory') {\n totalDirectories++;\n } else {\n totalFiles++;\n }\n\n const collectedEntry: CollectedEntry = {\n name,\n relativePath: relPath,\n type: entryType,\n };\n\n if (entries.length < options.entryCap) {\n entries.push(collectedEntry);\n }\n }\n\n options.signal.throwIfAborted();\n entries.sort(compareEntries);\n\n return {\n entries,\n totalEntries,\n totalFiles,\n totalDirectories,\n };\n}\n\nconst TEE = '├── ';\nconst ELBOW = '└── ';\nconst PIPE = '│ ';\nconst INDENT = ' ';\n\nfunction renderMarkdown(rootName: string, page: readonly CollectedEntry[]): 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(compareEntries);\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 lines.push(prefix + connector + child.name + (child.type === 'directory' ? '/' : ''));\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\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 cursor: CursorSchema,\n});\n\ninterface ListPageMetadata {\n readonly path: string;\n readonly totalEntries: number;\n readonly totalFiles: number;\n readonly totalDirectories: 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 'stat returns sizes and dates.',\n input: ListInputSchema,\n readOnlyHint: true,\n timeoutMs: DEFAULT_SEARCH_TIMEOUT_MS,\n defaultErrorCode: ErrorCode.NOT_DIRECTORY,\n progress: (args) => ({\n label: 'List',\n subject: args.path ? basename(args.path) : '.',\n }),\n accessPaths: (args) => (args.path ? [args.path] : []),\n run: async (args, ctx) => {\n const resolvedPath = ctx.fs.pathGuard.resolvePathOrRoot(args.path);\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 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 },\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(name, entries),\n totalEntries: metadata.totalEntries,\n totalFiles: metadata.totalFiles,\n totalDirectories: metadata.totalDirectories,\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 text =\n renderMarkdown(basename(paged.metadata.path), [...paged.page]) +\n 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 }) +\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 { 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"]}
|
package/dist/tools/move.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"move.d.ts","sourceRoot":"","sources":["../../src/tools/move.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"move.d.ts","sourceRoot":"","sources":["../../src/tools/move.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AA8hBvD,wBAAsB,yBAAyB,CAC7C,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,IAAI,CAAC,iBAAiB,EAAE,QAAQ,GAAG,IAAI,GAAG,IAAI,CAAC,EACtD,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,IAAI,CAAC,CA2Cf;AAED,eAAO,MAAM,IAAI,mCA2Cf,CAAC"}
|