@j0hanz/filesystem-mcp 2.8.0 → 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.
Files changed (134) hide show
  1. package/README.md +32 -26
  2. package/dist/cli-help.d.ts.map +1 -1
  3. package/dist/cli-help.js +10 -1
  4. package/dist/cli-help.js.map +1 -1
  5. package/dist/cli.d.ts.map +1 -1
  6. package/dist/cli.js +10 -3
  7. package/dist/cli.js.map +1 -1
  8. package/dist/core/concurrency.d.ts +4 -4
  9. package/dist/core/concurrency.d.ts.map +1 -1
  10. package/dist/core/concurrency.js +1 -1
  11. package/dist/core/concurrency.js.map +1 -1
  12. package/dist/core/config.d.ts +2 -0
  13. package/dist/core/config.d.ts.map +1 -1
  14. package/dist/core/config.js.map +1 -1
  15. package/dist/core/cursor.d.ts +8 -0
  16. package/dist/core/cursor.d.ts.map +1 -1
  17. package/dist/core/cursor.js +14 -0
  18. package/dist/core/cursor.js.map +1 -1
  19. package/dist/core/file-uri.d.ts +12 -3
  20. package/dist/core/file-uri.d.ts.map +1 -1
  21. package/dist/core/file-uri.js +35 -7
  22. package/dist/core/file-uri.js.map +1 -1
  23. package/dist/core/fmt.d.ts +2 -0
  24. package/dist/core/fmt.d.ts.map +1 -1
  25. package/dist/core/fmt.js +16 -0
  26. package/dist/core/fmt.js.map +1 -1
  27. package/dist/core/fs.d.ts +16 -1
  28. package/dist/core/fs.d.ts.map +1 -1
  29. package/dist/core/fs.js +191 -72
  30. package/dist/core/fs.js.map +1 -1
  31. package/dist/core/glob.d.ts +8 -0
  32. package/dist/core/glob.d.ts.map +1 -1
  33. package/dist/core/glob.js +84 -11
  34. package/dist/core/glob.js.map +1 -1
  35. package/dist/core/input-required.d.ts +7 -0
  36. package/dist/core/input-required.d.ts.map +1 -1
  37. package/dist/core/input-required.js +13 -0
  38. package/dist/core/input-required.js.map +1 -1
  39. package/dist/core/path-completer.d.ts.map +1 -1
  40. package/dist/core/path-completer.js +5 -3
  41. package/dist/core/path-completer.js.map +1 -1
  42. package/dist/core/path-utils.d.ts +51 -12
  43. package/dist/core/path-utils.d.ts.map +1 -1
  44. package/dist/core/path-utils.js +69 -29
  45. package/dist/core/path-utils.js.map +1 -1
  46. package/dist/core/path.d.ts +108 -21
  47. package/dist/core/path.d.ts.map +1 -1
  48. package/dist/core/path.js +436 -83
  49. package/dist/core/path.js.map +1 -1
  50. package/dist/core/read.d.ts +13 -3
  51. package/dist/core/read.d.ts.map +1 -1
  52. package/dist/core/read.js +46 -40
  53. package/dist/core/read.js.map +1 -1
  54. package/dist/core/schema.d.ts +9 -6
  55. package/dist/core/schema.d.ts.map +1 -1
  56. package/dist/core/schema.js +22 -19
  57. package/dist/core/schema.js.map +1 -1
  58. package/dist/core/search.d.ts +6 -0
  59. package/dist/core/search.d.ts.map +1 -1
  60. package/dist/core/search.js +159 -33
  61. package/dist/core/search.js.map +1 -1
  62. package/dist/core/sensitive.d.ts.map +1 -1
  63. package/dist/core/sensitive.js +71 -29
  64. package/dist/core/sensitive.js.map +1 -1
  65. package/dist/core/store.d.ts +1 -0
  66. package/dist/core/store.d.ts.map +1 -1
  67. package/dist/core/store.js +3 -0
  68. package/dist/core/store.js.map +1 -1
  69. package/dist/core/util.d.ts +12 -1
  70. package/dist/core/util.d.ts.map +1 -1
  71. package/dist/core/util.js +24 -1
  72. package/dist/core/util.js.map +1 -1
  73. package/dist/prompts.d.ts +1 -1
  74. package/dist/prompts.d.ts.map +1 -1
  75. package/dist/prompts.js +1 -1
  76. package/dist/prompts.js.map +1 -1
  77. package/dist/resources.d.ts +1 -2
  78. package/dist/resources.d.ts.map +1 -1
  79. package/dist/resources.js +20 -13
  80. package/dist/resources.js.map +1 -1
  81. package/dist/server.js +2 -2
  82. package/dist/server.js.map +1 -1
  83. package/dist/tools/create.d.ts.map +1 -1
  84. package/dist/tools/create.js +122 -45
  85. package/dist/tools/create.js.map +1 -1
  86. package/dist/tools/define.d.ts +8 -4
  87. package/dist/tools/define.d.ts.map +1 -1
  88. package/dist/tools/define.js +36 -9
  89. package/dist/tools/define.js.map +1 -1
  90. package/dist/tools/delete.d.ts.map +1 -1
  91. package/dist/tools/delete.js +57 -17
  92. package/dist/tools/delete.js.map +1 -1
  93. package/dist/tools/diff.js +1 -1
  94. package/dist/tools/diff.js.map +1 -1
  95. package/dist/tools/edit.d.ts.map +1 -1
  96. package/dist/tools/edit.js +14 -12
  97. package/dist/tools/edit.js.map +1 -1
  98. package/dist/tools/find-files.d.ts.map +1 -1
  99. package/dist/tools/find-files.js +20 -20
  100. package/dist/tools/find-files.js.map +1 -1
  101. package/dist/tools/index.d.ts +1 -1
  102. package/dist/tools/index.d.ts.map +1 -1
  103. package/dist/tools/index.js +1 -1
  104. package/dist/tools/index.js.map +1 -1
  105. package/dist/tools/list.d.ts.map +1 -1
  106. package/dist/tools/list.js +142 -73
  107. package/dist/tools/list.js.map +1 -1
  108. package/dist/tools/move.d.ts.map +1 -1
  109. package/dist/tools/move.js +81 -36
  110. package/dist/tools/move.js.map +1 -1
  111. package/dist/tools/patch.js +13 -6
  112. package/dist/tools/patch.js.map +1 -1
  113. package/dist/tools/read.d.ts.map +1 -1
  114. package/dist/tools/read.js +114 -45
  115. package/dist/tools/read.js.map +1 -1
  116. package/dist/tools/replace-text.d.ts.map +1 -1
  117. package/dist/tools/replace-text.js +49 -35
  118. package/dist/tools/replace-text.js.map +1 -1
  119. package/dist/tools/search-text.d.ts.map +1 -1
  120. package/dist/tools/search-text.js +20 -49
  121. package/dist/tools/search-text.js.map +1 -1
  122. package/dist/tools/stat.d.ts.map +1 -1
  123. package/dist/tools/stat.js +26 -8
  124. package/dist/tools/stat.js.map +1 -1
  125. package/dist/transport/http-policy.d.ts +3 -2
  126. package/dist/transport/http-policy.d.ts.map +1 -1
  127. package/dist/transport/http-policy.js +3 -2
  128. package/dist/transport/http-policy.js.map +1 -1
  129. package/dist/transport/http.d.ts.map +1 -1
  130. package/dist/transport/http.js +2 -2
  131. package/dist/transport/http.js.map +1 -1
  132. package/dist/transport/stdio.js +1 -1
  133. package/dist/transport/stdio.js.map +1 -1
  134. package/package.json +5 -5
@@ -1,42 +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';
3
- import { paginate } from "../core/cursor.js";
4
- import { ErrorCode } from "../core/errors.js";
5
- import { pageTrailer } from "../core/fmt.js";
4
+ import { processEntriesConcurrently, withAbort } from "../core/concurrency.js";
5
+ import { pageQueryKey, paginate } from "../core/cursor.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
- import { resolveEntryType } from "../core/path-utils.js";
8
- import { toPosixRelative } from "../core/path.js";
9
- import { CursorSchema, IncludeHidden, IncludeIgnored, OptionalPath, PositiveInt, } from "../core/schema.js";
9
+ import { resolveEntryType, toPosixRelative } from "../core/path-utils.js";
10
+ import { CursorSchema, defaultFalseBoolean, IncludeHidden, IncludeIgnored, mapOptionalPath, OptionalPath, PositiveInt, } from "../core/schema.js";
10
11
  import { putJsonResource } from "../core/store.js";
11
- import { DEFAULT_SEARCH_TIMEOUT_MS, DEFAULT_TREE_ENTRIES, MAX_LIST_ENTRIES, MAX_TREE_DEPTH, } from "../core/util.js";
12
+ import { DEFAULT_TREE_ENTRIES, MAX_LIST_ENTRIES, MAX_TREE_DEPTH, PARALLEL_CONCURRENCY, } from "../core/util.js";
12
13
  import { defineTool } from "./define.js";
13
14
  function entryTypeRank(type) {
14
15
  if (type === 'directory')
15
16
  return 0;
16
17
  return 1;
17
18
  }
18
- function compareEntries(a, b) {
19
- // Compare by parent directory first (depth-level grouping)
20
- const slashA = a.relativePath.lastIndexOf('/');
21
- const slashB = b.relativePath.lastIndexOf('/');
22
- const parentA = slashA === -1 ? '' : a.relativePath.slice(0, slashA);
23
- const parentB = slashB === -1 ? '' : b.relativePath.slice(0, slashB);
24
- if (parentA !== parentB)
25
- return parentA.localeCompare(parentB);
26
- // Within same parent: dirs first, then alphabetical
27
- const rankDiff = entryTypeRank(a.type) - entryTypeRank(b.type);
28
- if (rankDiff !== 0)
29
- return rankDiff;
30
- return a.name.localeCompare(b.name);
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;
36
+ }
37
+ return a.name.localeCompare(b.name);
38
+ };
31
39
  }
32
40
  async function collect(rootPath, options) {
33
41
  const entries = [];
42
+ const wantSizes = options.includeSizes || options.sortBy === 'size';
34
43
  let scanned = 0;
35
44
  let totalEntries = 0;
36
45
  let totalFiles = 0;
37
46
  let totalDirectories = 0;
47
+ let totalBytes = 0;
48
+ let fatalError;
38
49
  const ceiling = options.pathGuard.allowedRootContaining(rootPath);
39
- for await (const entry of globEntries({
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({
40
57
  cwd: rootPath,
41
58
  pattern: '**/*',
42
59
  skipIgnored: !options.includeIgnored,
@@ -49,46 +66,84 @@ async function collect(rootPath, options) {
49
66
  // is guaranteed >= 1 by its PositiveInt schema, so this never underflows.
50
67
  maxDepth: options.maxDepth - 1,
51
68
  onlyFiles: false,
52
- })) {
53
- options.signal.throwIfAborted();
54
- scanned++;
55
- options.onProgress({ current: scanned });
56
- const entryType = resolveEntryType(entry.dirent);
57
- const relPath = toPosixRelative(rootPath, entry.path);
58
- const name = basename(relPath);
59
- const accessible = await options.pathGuard.isEntryAccessible(entry.path);
60
- if (!accessible)
61
- continue;
62
- totalEntries++;
63
- if (entryType === 'directory') {
64
- totalDirectories++;
65
- }
66
- else {
67
- totalFiles++;
68
- }
69
- const collectedEntry = {
70
- name,
71
- relativePath: relPath,
72
- type: entryType,
73
- };
74
- if (entries.length < options.entryCap) {
75
- entries.push(collectedEntry);
76
- }
77
- }
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;
78
123
  options.signal.throwIfAborted();
79
- entries.sort(compareEntries);
124
+ keepBest();
80
125
  return {
81
126
  entries,
82
127
  totalEntries,
83
128
  totalFiles,
84
129
  totalDirectories,
130
+ ...(wantSizes ? { totalBytes } : {}),
85
131
  };
86
132
  }
87
133
  const TEE = '├── ';
88
134
  const ELBOW = '└── ';
89
135
  const PIPE = '│ ';
90
136
  const INDENT = ' ';
91
- function renderMarkdown(rootName, page) {
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) {
92
147
  if (page.length === 0)
93
148
  return rootName;
94
149
  // The tree is drawn down from the root, but a later page (or a capped set)
@@ -102,7 +157,7 @@ function renderMarkdown(rootName, page) {
102
157
  entries.push({ name: posix.basename(dir), relativePath: dir, type: 'directory' });
103
158
  }
104
159
  }
105
- entries.sort(compareEntries);
160
+ entries.sort(entryComparator(opts.sortBy));
106
161
  // Group entries by parent path
107
162
  const childrenOf = new Map();
108
163
  for (const entry of entries) {
@@ -125,7 +180,8 @@ function renderMarkdown(rootName, page) {
125
180
  continue;
126
181
  const isLast = i === children.length - 1;
127
182
  const connector = isLast ? ELBOW : TEE;
128
- lines.push(prefix + connector + child.name + (child.type === 'directory' ? '/' : ''));
183
+ const sizeText = opts.includeSizes && child.size !== undefined ? ` (${formatByteSize(child.size)})` : '';
184
+ lines.push(prefix + connector + child.name + (child.type === 'directory' ? '/' : '') + sizeText);
129
185
  const childKey = child.relativePath;
130
186
  const nextPrefix = prefix + (isLast ? INDENT : PIPE);
131
187
  renderChildren(childKey, nextPrefix);
@@ -134,6 +190,10 @@ function renderMarkdown(rootName, page) {
134
190
  renderChildren('', '');
135
191
  return lines.join('\n');
136
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
+ }
137
197
  const DEFAULT_LIST_DEPTH = 1;
138
198
  const ListInputSchema = z.strictObject({
139
199
  path: OptionalPath.describe('Directory to list (default: first allowed root)'),
@@ -145,39 +205,40 @@ const ListInputSchema = z.strictObject({
145
205
  .describe(`Page size (default: ${String(DEFAULT_TREE_ENTRIES)}). Continue with nextCursor; an incomplete first page also carries resourceUri for the whole list.`),
146
206
  includeHidden: IncludeHidden,
147
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)'),
148
214
  cursor: CursorSchema,
149
215
  });
150
216
  export const LIST = defineTool({
151
217
  name: 'list',
152
218
  title: 'List',
153
219
  description: "List a directory's files and subdirectories as a tree of names, like ls or tree. " +
154
- 'stat returns sizes and dates.',
220
+ 'includeSizes adds sizes and a total; stat returns dates.',
155
221
  input: ListInputSchema,
156
222
  readOnlyHint: true,
157
- timeoutMs: DEFAULT_SEARCH_TIMEOUT_MS,
223
+ deadline: true,
158
224
  defaultErrorCode: ErrorCode.NOT_DIRECTORY,
159
225
  progress: (args) => ({
160
226
  label: 'List',
161
227
  subject: args.path ? basename(args.path) : '.',
162
228
  }),
163
- accessPaths: (args) => (args.path ? [args.path] : []),
229
+ mapPaths: mapOptionalPath,
164
230
  run: async (args, ctx) => {
165
231
  const resolvedPath = ctx.fs.pathGuard.resolvePathOrRoot(args.path);
166
- const queryKey = JSON.stringify({
167
- method: 'list',
168
- path: resolvedPath,
169
- maxDepth: args.maxDepth,
170
- includeHidden: args.includeHidden,
171
- includeIgnored: args.includeIgnored,
172
- });
232
+ const renderOpts = { includeSizes: args.includeSizes, sortBy: args.sortBy };
173
233
  const paged = await paginate({
174
234
  store: ctx.pageStore,
175
- queryKey,
235
+ queryKey: pageQueryKey('list', { ...args, path: resolvedPath }, ['cursor', 'maxEntries']),
176
236
  cursor: args.cursor,
177
237
  pageSize: args.maxEntries,
178
238
  produce: async () => {
179
239
  const validDir = await ctx.fs.pathGuard.validateExistingDirectory(resolvedPath);
180
240
  const result = await collect(validDir, {
241
+ ...renderOpts,
181
242
  maxDepth: args.maxDepth,
182
243
  includeHidden: args.includeHidden,
183
244
  includeIgnored: args.includeIgnored,
@@ -193,6 +254,7 @@ export const LIST = defineTool({
193
254
  totalEntries: result.totalEntries,
194
255
  totalFiles: result.totalFiles,
195
256
  totalDirectories: result.totalDirectories,
257
+ ...(result.totalBytes !== undefined ? { totalBytes: result.totalBytes } : {}),
196
258
  },
197
259
  truncated: result.totalEntries > result.entries.length,
198
260
  };
@@ -202,10 +264,11 @@ export const LIST = defineTool({
202
264
  // The stored tree is the whole collected set, bounded by the hard cap.
203
265
  const fullOutput = {
204
266
  entries,
205
- markdown: renderMarkdown(name, entries),
267
+ markdown: renderMarkdown(treeHeader(ctx.fs.pathGuard, metadata.path), entries, renderOpts),
206
268
  totalEntries: metadata.totalEntries,
207
269
  totalFiles: metadata.totalFiles,
208
270
  totalDirectories: metadata.totalDirectories,
271
+ ...(metadata.totalBytes !== undefined ? { totalBytes: metadata.totalBytes } : {}),
209
272
  ...(metadata.totalEntries > entries.length ? { truncated: true } : {}),
210
273
  };
211
274
  return putJsonResource(ctx.resourceStore, `${name} tree`, fullOutput);
@@ -221,16 +284,22 @@ export const LIST = defineTool({
221
284
  // The tree is what the model reads, so position and the full-list URI ride
222
285
  // the text too — paging needs no second lookup. `pageTrailer` is the one
223
286
  // owner of that line, and it owes it on the last page as much as the first.
224
- const text = renderMarkdown(basename(paged.metadata.path), [...paged.page]) +
225
- pageTrailer({
226
- offset: paged.offset,
227
- shown: structured.entryCount,
228
- total: structured.totalEntries,
229
- noun: 'entries',
230
- tool: 'list',
231
- nextCursor: structured.nextCursor,
232
- nextArgs: args,
233
- }) +
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) +
234
303
  (structured.resourceUri !== undefined ? `\nfull tree at ${structured.resourceUri}` : '');
235
304
  return {
236
305
  structured,
@@ -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 { paginate } from '../core/cursor.ts';\nimport { ErrorCode } from '../core/errors.ts';\nimport { pageTrailer } from '../core/fmt.ts';\nimport { globEntries } from '../core/glob.ts';\nimport { type EntryType, resolveEntryType } from '../core/path-utils.ts';\nimport type { PathGuard } from '../core/path.ts';\nimport { toPosixRelative } 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\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 options.pathGuard.isEntryAccessible(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 queryKey = JSON.stringify({\n method: 'list',\n path: resolvedPath,\n maxDepth: args.maxDepth,\n includeHidden: args.includeHidden,\n includeIgnored: args.includeIgnored,\n });\n const paged = await paginate<CollectedEntry, ListPageMetadata, JsonResourceResult>({\n store: ctx.pageStore,\n queryKey,\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"]}
@@ -1 +1 @@
1
- {"version":3,"file":"move.d.ts","sourceRoot":"","sources":["../../src/tools/move.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAwfvD,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,mCAwCf,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"}