@j0hanz/filesystem-mcp 2.1.6 → 2.1.8

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 (102) hide show
  1. package/README.md +7 -7
  2. package/dist/cli.d.ts +1 -2
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +29 -34
  5. package/dist/cli.js.map +1 -1
  6. package/dist/core/concurrency.d.ts +4 -7
  7. package/dist/core/concurrency.d.ts.map +1 -1
  8. package/dist/core/concurrency.js +4 -12
  9. package/dist/core/concurrency.js.map +1 -1
  10. package/dist/core/cursor.d.ts.map +1 -1
  11. package/dist/core/cursor.js +8 -20
  12. package/dist/core/cursor.js.map +1 -1
  13. package/dist/core/fmt.d.ts +2 -1
  14. package/dist/core/fmt.d.ts.map +1 -1
  15. package/dist/core/fmt.js +8 -15
  16. package/dist/core/fmt.js.map +1 -1
  17. package/dist/core/fs.d.ts +0 -14
  18. package/dist/core/fs.d.ts.map +1 -1
  19. package/dist/core/fs.js +1 -0
  20. package/dist/core/fs.js.map +1 -1
  21. package/dist/core/glob.d.ts +0 -3
  22. package/dist/core/glob.d.ts.map +1 -1
  23. package/dist/core/glob.js +5 -27
  24. package/dist/core/glob.js.map +1 -1
  25. package/dist/core/input-required.d.ts +2 -2
  26. package/dist/core/input-required.d.ts.map +1 -1
  27. package/dist/core/input-required.js.map +1 -1
  28. package/dist/core/path-completer.d.ts.map +1 -1
  29. package/dist/core/path-completer.js +4 -27
  30. package/dist/core/path-completer.js.map +1 -1
  31. package/dist/core/path-utils.d.ts +1 -1
  32. package/dist/core/path-utils.d.ts.map +1 -1
  33. package/dist/core/path-utils.js +2 -2
  34. package/dist/core/path-utils.js.map +1 -1
  35. package/dist/core/path.d.ts +7 -9
  36. package/dist/core/path.d.ts.map +1 -1
  37. package/dist/core/path.js +24 -42
  38. package/dist/core/path.js.map +1 -1
  39. package/dist/core/read.d.ts.map +1 -1
  40. package/dist/core/read.js +6 -23
  41. package/dist/core/read.js.map +1 -1
  42. package/dist/core/schema.d.ts.map +1 -1
  43. package/dist/core/schema.js +19 -74
  44. package/dist/core/schema.js.map +1 -1
  45. package/dist/core/search.d.ts +30 -7
  46. package/dist/core/search.d.ts.map +1 -1
  47. package/dist/core/search.js +63 -21
  48. package/dist/core/search.js.map +1 -1
  49. package/dist/core/store.d.ts.map +1 -1
  50. package/dist/core/store.js +6 -17
  51. package/dist/core/store.js.map +1 -1
  52. package/dist/index.js +15 -42
  53. package/dist/index.js.map +1 -1
  54. package/dist/prompts.d.ts.map +1 -1
  55. package/dist/prompts.js +17 -25
  56. package/dist/prompts.js.map +1 -1
  57. package/dist/resources.d.ts +4 -4
  58. package/dist/resources.d.ts.map +1 -1
  59. package/dist/resources.js +7 -17
  60. package/dist/resources.js.map +1 -1
  61. package/dist/server.d.ts +1 -4
  62. package/dist/server.d.ts.map +1 -1
  63. package/dist/server.js +2 -7
  64. package/dist/server.js.map +1 -1
  65. package/dist/tools/define.d.ts.map +1 -1
  66. package/dist/tools/define.js +35 -61
  67. package/dist/tools/define.js.map +1 -1
  68. package/dist/tools/delete-file.d.ts.map +1 -1
  69. package/dist/tools/delete-file.js +30 -35
  70. package/dist/tools/delete-file.js.map +1 -1
  71. package/dist/tools/edit.d.ts.map +1 -1
  72. package/dist/tools/edit.js +8 -13
  73. package/dist/tools/edit.js.map +1 -1
  74. package/dist/tools/list.d.ts.map +1 -1
  75. package/dist/tools/list.js +3 -7
  76. package/dist/tools/list.js.map +1 -1
  77. package/dist/tools/move.d.ts.map +1 -1
  78. package/dist/tools/move.js +2 -4
  79. package/dist/tools/move.js.map +1 -1
  80. package/dist/tools/progress.d.ts +1 -1
  81. package/dist/tools/progress.d.ts.map +1 -1
  82. package/dist/tools/progress.js.map +1 -1
  83. package/dist/tools/read.d.ts.map +1 -1
  84. package/dist/tools/read.js +36 -42
  85. package/dist/tools/read.js.map +1 -1
  86. package/dist/tools/replace-in-files.d.ts.map +1 -1
  87. package/dist/tools/replace-in-files.js +25 -42
  88. package/dist/tools/replace-in-files.js.map +1 -1
  89. package/dist/tools/search-content.d.ts.map +1 -1
  90. package/dist/tools/search-content.js +3 -25
  91. package/dist/tools/search-content.js.map +1 -1
  92. package/dist/tools/stat.d.ts.map +1 -1
  93. package/dist/tools/stat.js +9 -37
  94. package/dist/tools/stat.js.map +1 -1
  95. package/dist/transport/http-policy.d.ts +18 -15
  96. package/dist/transport/http-policy.d.ts.map +1 -1
  97. package/dist/transport/http-policy.js +29 -39
  98. package/dist/transport/http-policy.js.map +1 -1
  99. package/dist/transport/http.d.ts.map +1 -1
  100. package/dist/transport/http.js +29 -39
  101. package/dist/transport/http.js.map +1 -1
  102. package/package.json +4 -7
@@ -103,7 +103,7 @@ function buildReadSpec(args, signal) {
103
103
  }
104
104
  // No `totalLines`: only `readFull` counts them and a full read never leaves
105
105
  // more behind, so a continuation cannot know the total without a second pass.
106
- function buildReadContinuation(result) {
106
+ function buildReadContinuation(result, requestedPath) {
107
107
  if (!result.hasMoreLines)
108
108
  return undefined;
109
109
  const linesRead = result.linesRead ?? 0;
@@ -121,7 +121,7 @@ function buildReadContinuation(result) {
121
121
  const nextEnd = nextStart + chunkSize - 1;
122
122
  return {
123
123
  tool: 'read',
124
- args: { path: result.path, startLine: nextStart, endLine: nextEnd },
124
+ args: { path: requestedPath, startLine: nextStart, endLine: nextEnd },
125
125
  hint: `More lines remain from ${String(nextStart)}. Read next chunk with these args.`,
126
126
  };
127
127
  }
@@ -157,60 +157,58 @@ async function collectFileBudget(filePaths, maxTotalSize, maxSize, ctx) {
157
157
  }
158
158
  }
159
159
  let total = 0;
160
- const skippedBudget = new Set();
160
+ const skippedResults = new Map();
161
+ const survivors = [];
162
+ let overflowed = false;
161
163
  for (let i = 0; i < filePaths.length; i += 1) {
162
- const size = byIndex.get(i);
163
- if (size === undefined)
164
+ const path = filePaths[i];
165
+ if (path === undefined)
164
166
  continue;
165
- if (total + size > maxTotalSize) {
166
- // Only mark files that were actually stat'd as too large for the batch
167
- // budget. A file whose stat already failed (byIndex undefined) must fall
168
- // through to survivors so its read surfaces the real error (NOT_FILE /
169
- // permission) — not a misleading TOO_LARGE.
170
- for (let j = i; j < filePaths.length; j += 1) {
171
- if (byIndex.get(j) === undefined)
172
- continue;
173
- skippedBudget.add(j);
167
+ const size = byIndex.get(i);
168
+ if (overflowed) {
169
+ // Only files that were actually stat'd get the TOO_LARGE result; a failed
170
+ // stat falls through to survivors so its read surfaces the real error —
171
+ // not a misleading TOO_LARGE.
172
+ if (size !== undefined) {
173
+ skippedResults.set(i, {
174
+ path,
175
+ error: {
176
+ code: ErrorCode.TOO_LARGE,
177
+ message: `Skipped: combined estimated read would exceed maxTotalSize (${String(maxTotalSize)} bytes)`,
178
+ path,
179
+ },
180
+ });
181
+ }
182
+ else {
183
+ survivors.push(path);
174
184
  }
175
- break;
185
+ continue;
176
186
  }
177
- total += size;
178
- }
179
- return { skippedBudget, known };
180
- }
181
- function preFilterByBudget(pathList, budgetState) {
182
- const skippedResults = new Map();
183
- const survivors = [];
184
- for (let i = 0; i < pathList.length; i += 1) {
185
- const path = pathList[i];
186
- if (path === undefined)
187
+ if (size === undefined) {
188
+ survivors.push(path);
187
189
  continue;
188
- if (budgetState.skippedBudget.has(i)) {
190
+ }
191
+ if (total + size > maxTotalSize) {
192
+ overflowed = true;
189
193
  skippedResults.set(i, {
190
194
  path,
191
195
  error: {
192
196
  code: ErrorCode.TOO_LARGE,
193
- message: `Skipped: combined estimated read would exceed maxTotalSize (${String(budgetState.maxTotalSize)} bytes)`,
197
+ message: `Skipped: combined estimated read would exceed maxTotalSize (${String(maxTotalSize)} bytes)`,
194
198
  path,
195
199
  },
196
200
  });
197
201
  continue;
198
202
  }
203
+ total += size;
199
204
  survivors.push(path);
200
205
  }
201
- return { skippedResults, survivors };
206
+ return { skippedResults, survivors, known };
202
207
  }
203
208
  function buildPerPathReadValue(result, options) {
204
209
  const mimeInfo = detectMimeFromContent(result.path, result.content);
205
210
  const continuation = result.hasMoreLines && result.readMode !== 'tail'
206
- ? buildReadContinuation({
207
- path: options.requestedPath,
208
- hasMoreLines: true,
209
- ...(result.linesRead !== undefined ? { linesRead: result.linesRead } : {}),
210
- ...(result.startLine !== undefined ? { startLine: result.startLine } : {}),
211
- ...(result.endLine !== undefined ? { endLine: result.endLine } : {}),
212
- ...(result.head !== undefined ? { head: result.head } : {}),
213
- })
211
+ ? buildReadContinuation(result, options.requestedPath)
214
212
  : undefined;
215
213
  const contentHash = options.includeHash
216
214
  ? createHash('sha256').update(result.content, 'utf-8').digest('hex')
@@ -339,12 +337,8 @@ export const READ_FILE = defineTool({
339
337
  const maxTextFileSize = getMaxTextFileSize();
340
338
  const budget = await collectFileBudget(pathList, defaultMaxTotalSize, maxTextFileSize, ctx);
341
339
  known = budget.known;
342
- const filtered = preFilterByBudget(pathList, {
343
- skippedBudget: budget.skippedBudget,
344
- maxTotalSize: defaultMaxTotalSize,
345
- });
346
- skippedResults = filtered.skippedResults;
347
- survivors = filtered.survivors;
340
+ skippedResults = budget.skippedResults;
341
+ survivors = budget.survivors;
348
342
  }
349
343
  else {
350
344
  pathList = [args.path ?? ''];
@@ -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 type { Stats } from 'node:fs';\nimport { basename } from 'node:path';\n\nimport * as z from 'zod/v4';\n\nimport { processInParallel } from '../core/concurrency.js';\nimport { ErrorCode } from '../core/errors.js';\nimport { buildFileResourceLinkFor, buildFileResourceUri } from '../core/file-uri.js';\nimport { detectMimeFromContent, detectMimeType } from '../core/mime.js';\nimport type { ReadFileResult, ReadSpec } from '../core/read.js';\nimport { readFileWithStats } from '../core/read.js';\nimport {\n ContinuationSchema,\n defaultFalseBoolean,\n FileKind,\n NonNegInt,\n OperationSummarySchema,\n PerFileErrorSchema,\n PositiveInt,\n Sha256Hex,\n singleOrBatchAccessPaths,\n singleOrBatchPathsInput,\n validateReadRange,\n} from '../core/schema.js';\nimport {\n DEFAULT_CONTINUATION_CHUNK_SIZE,\n DEFAULT_SEARCH_TIMEOUT_MS,\n getDefaultReadManyMaxTotalSize,\n getMaxTextFileSize,\n PARALLEL_CONCURRENCY,\n} from '../core/util.js';\nimport type { PerPathResult } from './batch.js';\nimport { isTotalFailure, runOverPaths } from './batch.js';\nimport type { ToolCtx } from './define.js';\nimport { defineTool } from './define.js';\n\nconst rangeField = (description: string) =>\n z\n .int32()\n .min(1, { message: 'Min: 1' })\n .max(100000, { message: 'Max: 100,000' })\n .optional()\n .describe(description);\n\nconst readRangeFields = {\n head: rangeField('Return first N lines'),\n tail: rangeField('Return last N lines'),\n startLine: rangeField('Start line (1-indexed)'),\n endLine: rangeField('End line (1-indexed)'),\n};\n\nconst ReadFileInputSchema = singleOrBatchPathsInput({\n includeHash: defaultFalseBoolean('Include SHA-256 hash of the returned content in the response'),\n ...readRangeFields,\n})\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 })\n // Mirror `validateReadRange` on the wire. Without this the four line params\n // published as four independent optional integers, so `{ path, head, tail }`\n // passed the advertised schema and was rejected only at call time.\n //\n // `oneOf` is restated because `.meta()` replaces the entry\n // `singleOrBatchPathsInput` set rather than merging into it — dropping it here\n // would silently un-publish the path/paths rule.\n .meta({\n // The line-param exclusivity that used to sit here as a five-branch\n // `not/anyOf` is one sentence in the description instead: validateReadRange\n // rejects every conflicting combination by name at runtime, so the wire copy\n // was paying for a second statement of a rule the model reads better in\n // prose.\n oneOf: [{ required: ['path'] }, { required: ['paths'] }],\n dependentRequired: { endLine: ['startLine'] },\n });\n\n// File bytes are NOT here: text rides the text content block, image/audio ride\n// a media block. This schema is the metadata a caller cannot recover from\n// those blocks. `readOnePath` carries the bytes internally via\n// `PerPathReadValue` and `run` drops them before the structured half goes out.\nconst ReadPerPathValueSchema = z.strictObject({\n mimeType: z.string().optional().describe('Detected MIME type (e.g. text/typescript)'),\n kind: FileKind.optional().describe('Broad file kind: text, binary, image, audio, or pdf'),\n resourceUri: z\n .string()\n .optional()\n .describe(\n 'Resource URI for externalized content (present when file is stored in resource store)',\n ),\n continuation: ContinuationSchema.optional().describe(\n 'Next-read arguments; present when content was truncated due to size limits',\n ),\n totalLines: NonNegInt.optional().describe('Total line count in the full file'),\n linesRead: NonNegInt.optional().describe('Number of lines returned in this response'),\n hasMoreLines: z\n .boolean()\n .optional()\n .describe('True when additional lines remain beyond what was returned'),\n head: PositiveInt.optional().describe('Head lines requested'),\n tail: PositiveInt.optional().describe('Tail lines requested'),\n startLine: PositiveInt.optional().describe('Start line'),\n endLine: PositiveInt.optional().describe('End line'),\n contentHash: Sha256Hex.optional().describe(\n 'SHA-256 hex digest of the returned content (present when includeHash=true)',\n ),\n});\n\nconst ReadPerPathSchema = z.strictObject({\n path: z.string().describe('Requested file path'),\n value: ReadPerPathValueSchema.optional().describe('Read result; present on success'),\n error: PerFileErrorSchema.optional().describe('Error details; present on failure'),\n});\n\nconst ReadFileOutputSchema = z.strictObject({\n results: z.array(ReadPerPathSchema).describe('Per-path results ordered to match the input paths'),\n summary: OperationSummarySchema,\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(result: {\n path: string;\n hasMoreLines?: boolean;\n linesRead?: number;\n startLine?: number;\n endLine?: number;\n head?: number;\n}): z.infer<typeof ContinuationSchema> | undefined {\n if (!result.hasMoreLines) return undefined;\n const linesRead = result.linesRead ?? 0;\n const nextStart = (result.startLine ?? 1) + linesRead;\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 = nextStart + chunkSize - 1;\n return {\n tool: 'read',\n args: { path: result.path, 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` and\n * `mediaData` 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 `ReadPerPathValueSchema`.\n */\ntype PerPathReadValue = z.infer<typeof ReadPerPathValueSchema> & {\n content?: string;\n mediaData?: string;\n};\n\ninterface BatchFileInfo {\n index: number;\n size: number;\n validPath: string;\n stats: Stats;\n}\n\nasync function collectFileBudget(\n filePaths: readonly string[],\n maxTotalSize: number,\n maxSize: number,\n ctx: Pick<ToolCtx, 'fs' | 'signal' | 'log'>,\n): Promise<{\n skippedBudget: Set<number>;\n known: Map<string, { validPath: string; stats: Stats }>;\n}> {\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 {\n index,\n size: Math.min(out.stats.size, maxSize),\n validPath: out.validPath,\n stats: out.stats,\n };\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, number>();\n const known = new Map<string, { validPath: string; stats: Stats }>();\n for (const { value: item } of results) {\n if (!item) continue;\n byIndex.set(item.index, item.size);\n // Keyed by the ORIGINAL requested path string (not validPath) — that's\n // what readOnePath is called with downstream, and what filePaths[i]\n // holds.\n const requestedPath = filePaths[item.index];\n if (requestedPath !== undefined) {\n known.set(requestedPath, { validPath: item.validPath, stats: item.stats });\n }\n }\n\n let total = 0;\n const skippedBudget = new Set<number>();\n for (let i = 0; i < filePaths.length; i += 1) {\n const size = byIndex.get(i);\n if (size === undefined) continue;\n if (total + size > maxTotalSize) {\n // Only mark files that were actually stat'd as too large for the batch\n // budget. A file whose stat already failed (byIndex undefined) must fall\n // through to survivors so its read surfaces the real error (NOT_FILE /\n // permission) — not a misleading TOO_LARGE.\n for (let j = i; j < filePaths.length; j += 1) {\n if (byIndex.get(j) === undefined) continue;\n skippedBudget.add(j);\n }\n break;\n }\n total += size;\n }\n\n return { skippedBudget, known };\n}\n\nfunction preFilterByBudget(\n pathList: readonly string[],\n budgetState: { skippedBudget: Set<number>; maxTotalSize: number },\n): { skippedResults: Map<number, PerPathResult<PerPathReadValue>>; survivors: string[] } {\n const skippedResults = new Map<number, PerPathResult<PerPathReadValue>>();\n const survivors: string[] = [];\n\n for (let i = 0; i < pathList.length; i += 1) {\n const path = pathList[i];\n if (path === undefined) continue;\n if (budgetState.skippedBudget.has(i)) {\n skippedResults.set(i, {\n path,\n error: {\n code: ErrorCode.TOO_LARGE,\n message: `Skipped: combined estimated read would exceed maxTotalSize (${String(\n budgetState.maxTotalSize,\n )} bytes)`,\n path,\n },\n });\n continue;\n }\n survivors.push(path);\n }\n\n return { skippedResults, survivors };\n}\n\nfunction buildPerPathReadValue(\n result: ReadFileResult,\n options: { includeHash?: boolean; hasResourceStore?: boolean; requestedPath: string },\n): PerPathReadValue {\n const mimeInfo = detectMimeFromContent(result.path, result.content);\n const continuation =\n result.hasMoreLines && result.readMode !== 'tail'\n ? buildReadContinuation({\n path: options.requestedPath,\n hasMoreLines: true,\n ...(result.linesRead !== undefined ? { linesRead: result.linesRead } : {}),\n ...(result.startLine !== undefined ? { startLine: result.startLine } : {}),\n ...(result.endLine !== undefined ? { endLine: result.endLine } : {}),\n ...(result.head !== undefined ? { head: result.head } : {}),\n })\n : undefined;\n const contentHash = options.includeHash\n ? createHash('sha256').update(result.content, 'utf-8').digest('hex')\n : undefined;\n const resourceUri = options.hasResourceStore ? buildFileResourceUri(result.path) : undefined;\n\n return {\n content: result.content,\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 ...(resourceUri !== undefined ? { resourceUri } : {}),\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\nasync function readOnePath(\n filePath: string,\n args: ReadFileInput,\n ctx: ToolCtx,\n known?: { validPath: string; stats: Stats },\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 carries kind:'image' but is XML text —\n // readRaw.isBinary is false for it, so it falls through to the text path.\n const isRangeRead =\n args.head !== undefined ||\n args.tail !== undefined ||\n args.startLine !== undefined ||\n args.endLine !== undefined;\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 mediaData: raw.content.toString('base64'),\n };\n }\n }\n }\n\n const spec = buildReadSpec(args, ctx.signal);\n const result = known\n ? await readFileWithStats(filePath, known.validPath, known.stats, spec)\n : await ctx.fs.readFile(filePath, spec);\n\n return buildPerPathReadValue(result, {\n includeHash: args.includeHash,\n hasResourceStore: ctx.resourceStore !== undefined,\n // The continuation is args the caller pastes back, so it echoes the path\n // they wrote. `result.path` is the resolved absolute one — on Windows that\n // is a backslash-doubling JSON string that also spells out the server root.\n requestedPath: filePath,\n });\n}\n\nexport const READ_FILE = defineTool({\n name: 'read',\n title: 'Read File',\n description:\n 'Read one or more text files and return content. ' +\n 'Partial reads: head (first N lines), tail (last N lines), startLine/endLine (line range). ' +\n 'Batch mode: pass paths[] instead of path; line params are shared across all files. ' +\n 'head, tail, and startLine/endLine are mutually exclusive — use exactly one.',\n input: ReadFileInputSchema,\n output: ReadFileOutputSchema,\n annotations: {\n readOnlyHint: true,\n idempotentHint: true,\n destructiveHint: false,\n openWorldHint: false,\n },\n timeoutMs: DEFAULT_SEARCH_TIMEOUT_MS,\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 accessPaths: singleOrBatchAccessPaths,\n run: async (args, ctx) => {\n let pathList: string[];\n let skippedResults = new Map<number, PerPathResult<PerPathReadValue>>();\n let survivors: string[];\n let known = new Map<string, { validPath: string; stats: Stats }>();\n\n if (args.paths !== undefined) {\n pathList = args.paths;\n const defaultMaxTotalSize = getDefaultReadManyMaxTotalSize();\n const maxTextFileSize = getMaxTextFileSize();\n const budget = await collectFileBudget(pathList, defaultMaxTotalSize, maxTextFileSize, ctx);\n known = budget.known;\n const filtered = preFilterByBudget(pathList, {\n skippedBudget: budget.skippedBudget,\n maxTotalSize: defaultMaxTotalSize,\n });\n skippedResults = filtered.skippedResults;\n survivors = filtered.survivors;\n } else {\n pathList = [args.path ?? ''];\n survivors = [...pathList];\n }\n\n const batchInput = { paths: survivors };\n\n // Every path can be budget-skipped (a single file over maxTotalSize does\n // it), and runOverPaths rejects an empty list. The per-path TOO_LARGE\n // results are already built — return those rather than failing the call.\n const batch =\n survivors.length === 0\n ? { results: [] as PerPathResult<PerPathReadValue>[] }\n : await runOverPaths<undefined, PerPathReadValue>(\n batchInput,\n ctx,\n ({ path }) => readOnePath(path, args, ctx, known.get(path)),\n { defaultErrorCode: ErrorCode.NOT_FILE },\n );\n\n const resultMap = new Map(batch.results.map((r) => [r.path, r]));\n const ordered: PerPathResult<PerPathReadValue>[] = pathList.map((path, idx) => {\n const skipped = skippedResults.get(idx);\n if (skipped) return skipped;\n const result = resultMap.get(path);\n return (\n result ?? {\n path,\n error: { code: ErrorCode.UNKNOWN, message: 'Unknown read failure' },\n }\n );\n });\n\n const failed = ordered.filter((r) => 'error' in r).length;\n const summary = {\n total: ordered.length,\n succeeded: ordered.length - failed,\n failed,\n };\n\n const resources: ContentBlock[] = [];\n for (const result of ordered) {\n if ('error' in result) continue;\n const v = result.value;\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) 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 Buffer.byteLength(v.content, 'utf8'),\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 { content: _content, mediaData: _mediaData, ...value } = 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});\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 type { Stats } from 'node:fs';\nimport { basename } from 'node:path';\n\nimport * as z from 'zod/v4';\n\nimport { processInParallel } from '../core/concurrency.js';\nimport { ErrorCode } from '../core/errors.js';\nimport { buildFileResourceLinkFor, buildFileResourceUri } from '../core/file-uri.js';\nimport { detectMimeFromContent, detectMimeType } from '../core/mime.js';\nimport type { ReadFileResult, ReadSpec } from '../core/read.js';\nimport { readFileWithStats } from '../core/read.js';\nimport {\n ContinuationSchema,\n defaultFalseBoolean,\n FileKind,\n NonNegInt,\n OperationSummarySchema,\n PerFileErrorSchema,\n PositiveInt,\n Sha256Hex,\n singleOrBatchAccessPaths,\n singleOrBatchPathsInput,\n validateReadRange,\n} from '../core/schema.js';\nimport {\n DEFAULT_CONTINUATION_CHUNK_SIZE,\n DEFAULT_SEARCH_TIMEOUT_MS,\n getDefaultReadManyMaxTotalSize,\n getMaxTextFileSize,\n PARALLEL_CONCURRENCY,\n} from '../core/util.js';\nimport type { PerPathResult } from './batch.js';\nimport { isTotalFailure, runOverPaths } from './batch.js';\nimport type { ToolCtx } from './define.js';\nimport { defineTool } from './define.js';\n\nconst rangeField = (description: string) =>\n z\n .int32()\n .min(1, { message: 'Min: 1' })\n .max(100000, { message: 'Max: 100,000' })\n .optional()\n .describe(description);\n\nconst readRangeFields = {\n head: rangeField('Return first N lines'),\n tail: rangeField('Return last N lines'),\n startLine: rangeField('Start line (1-indexed)'),\n endLine: rangeField('End line (1-indexed)'),\n};\n\nconst ReadFileInputSchema = singleOrBatchPathsInput({\n includeHash: defaultFalseBoolean('Include SHA-256 hash of the returned content in the response'),\n ...readRangeFields,\n})\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 })\n // Mirror `validateReadRange` on the wire. Without this the four line params\n // published as four independent optional integers, so `{ path, head, tail }`\n // passed the advertised schema and was rejected only at call time.\n //\n // `oneOf` is restated because `.meta()` replaces the entry\n // `singleOrBatchPathsInput` set rather than merging into it — dropping it here\n // would silently un-publish the path/paths rule.\n .meta({\n // The line-param exclusivity that used to sit here as a five-branch\n // `not/anyOf` is one sentence in the description instead: validateReadRange\n // rejects every conflicting combination by name at runtime, so the wire copy\n // was paying for a second statement of a rule the model reads better in\n // prose.\n oneOf: [{ required: ['path'] }, { required: ['paths'] }],\n dependentRequired: { endLine: ['startLine'] },\n });\n\n// File bytes are NOT here: text rides the text content block, image/audio ride\n// a media block. This schema is the metadata a caller cannot recover from\n// those blocks. `readOnePath` carries the bytes internally via\n// `PerPathReadValue` and `run` drops them before the structured half goes out.\nconst ReadPerPathValueSchema = z.strictObject({\n mimeType: z.string().optional().describe('Detected MIME type (e.g. text/typescript)'),\n kind: FileKind.optional().describe('Broad file kind: text, binary, image, audio, or pdf'),\n resourceUri: z\n .string()\n .optional()\n .describe(\n 'Resource URI for externalized content (present when file is stored in resource store)',\n ),\n continuation: ContinuationSchema.optional().describe(\n 'Next-read arguments; present when content was truncated due to size limits',\n ),\n totalLines: NonNegInt.optional().describe('Total line count in the full file'),\n linesRead: NonNegInt.optional().describe('Number of lines returned in this response'),\n hasMoreLines: z\n .boolean()\n .optional()\n .describe('True when additional lines remain beyond what was returned'),\n head: PositiveInt.optional().describe('Head lines requested'),\n tail: PositiveInt.optional().describe('Tail lines requested'),\n startLine: PositiveInt.optional().describe('Start line'),\n endLine: PositiveInt.optional().describe('End line'),\n contentHash: Sha256Hex.optional().describe(\n 'SHA-256 hex digest of the returned content (present when includeHash=true)',\n ),\n});\n\nconst ReadPerPathSchema = z.strictObject({\n path: z.string().describe('Requested file path'),\n value: ReadPerPathValueSchema.optional().describe('Read result; present on success'),\n error: PerFileErrorSchema.optional().describe('Error details; present on failure'),\n});\n\nconst ReadFileOutputSchema = z.strictObject({\n results: z.array(ReadPerPathSchema).describe('Per-path results ordered to match the input paths'),\n summary: OperationSummarySchema,\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): z.infer<typeof ContinuationSchema> | undefined {\n if (!result.hasMoreLines) return undefined;\n const linesRead = result.linesRead ?? 0;\n const nextStart = (result.startLine ?? 1) + linesRead;\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 = nextStart + chunkSize - 1;\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` and\n * `mediaData` 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 `ReadPerPathValueSchema`.\n */\ntype PerPathReadValue = z.infer<typeof ReadPerPathValueSchema> & {\n content?: string;\n mediaData?: string;\n};\n\ninterface BatchFileInfo {\n index: number;\n size: number;\n validPath: string;\n stats: Stats;\n}\n\nasync function collectFileBudget(\n filePaths: readonly string[],\n maxTotalSize: number,\n maxSize: number,\n ctx: Pick<ToolCtx, 'fs' | 'signal' | 'log'>,\n): Promise<{\n skippedResults: Map<number, PerPathResult<PerPathReadValue>>;\n survivors: string[];\n known: Map<string, { validPath: string; stats: Stats }>;\n}> {\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 {\n index,\n size: Math.min(out.stats.size, maxSize),\n validPath: out.validPath,\n stats: out.stats,\n };\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, number>();\n const known = new Map<string, { validPath: string; stats: Stats }>();\n for (const { value: item } of results) {\n if (!item) continue;\n byIndex.set(item.index, item.size);\n // Keyed by the ORIGINAL requested path string (not validPath) — that's\n // what readOnePath is called with downstream, and what filePaths[i]\n // holds.\n const requestedPath = filePaths[item.index];\n if (requestedPath !== undefined) {\n known.set(requestedPath, { validPath: item.validPath, stats: item.stats });\n }\n }\n\n let total = 0;\n const skippedResults = new Map<number, PerPathResult<PerPathReadValue>>();\n const survivors: string[] = [];\n let overflowed = false;\n for (let i = 0; i < filePaths.length; i += 1) {\n const path = filePaths[i];\n if (path === undefined) continue;\n const size = byIndex.get(i);\n if (overflowed) {\n // Only files that were actually stat'd get the TOO_LARGE result; a failed\n // stat falls through to survivors so its read surfaces the real error —\n // not a misleading TOO_LARGE.\n if (size !== undefined) {\n skippedResults.set(i, {\n path,\n error: {\n code: ErrorCode.TOO_LARGE,\n message: `Skipped: combined estimated read would exceed maxTotalSize (${String(maxTotalSize)} bytes)`,\n path,\n },\n });\n } else {\n survivors.push(path);\n }\n continue;\n }\n if (size === undefined) {\n survivors.push(path);\n continue;\n }\n if (total + size > maxTotalSize) {\n overflowed = true;\n skippedResults.set(i, {\n path,\n error: {\n code: ErrorCode.TOO_LARGE,\n message: `Skipped: combined estimated read would exceed maxTotalSize (${String(maxTotalSize)} bytes)`,\n path,\n },\n });\n continue;\n }\n total += size;\n survivors.push(path);\n }\n\n return { skippedResults, survivors, known };\n}\n\nfunction buildPerPathReadValue(\n result: ReadFileResult,\n options: { includeHash?: boolean; hasResourceStore?: 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 const resourceUri = options.hasResourceStore ? buildFileResourceUri(result.path) : undefined;\n\n return {\n content: result.content,\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 ...(resourceUri !== undefined ? { resourceUri } : {}),\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\nasync function readOnePath(\n filePath: string,\n args: ReadFileInput,\n ctx: ToolCtx,\n known?: { validPath: string; stats: Stats },\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 carries kind:'image' but is XML text —\n // readRaw.isBinary is false for it, so it falls through to the text path.\n const isRangeRead =\n args.head !== undefined ||\n args.tail !== undefined ||\n args.startLine !== undefined ||\n args.endLine !== undefined;\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 mediaData: raw.content.toString('base64'),\n };\n }\n }\n }\n\n const spec = buildReadSpec(args, ctx.signal);\n const result = known\n ? await readFileWithStats(filePath, known.validPath, known.stats, spec)\n : await ctx.fs.readFile(filePath, spec);\n\n return buildPerPathReadValue(result, {\n includeHash: args.includeHash,\n hasResourceStore: ctx.resourceStore !== undefined,\n // The continuation is args the caller pastes back, so it echoes the path\n // they wrote. `result.path` is the resolved absolute one — on Windows that\n // is a backslash-doubling JSON string that also spells out the server root.\n requestedPath: filePath,\n });\n}\n\nexport const READ_FILE = defineTool({\n name: 'read',\n title: 'Read File',\n description:\n 'Read one or more text files and return content. ' +\n 'Partial reads: head (first N lines), tail (last N lines), startLine/endLine (line range). ' +\n 'Batch mode: pass paths[] instead of path; line params are shared across all files. ' +\n 'head, tail, and startLine/endLine are mutually exclusive — use exactly one.',\n input: ReadFileInputSchema,\n output: ReadFileOutputSchema,\n annotations: {\n readOnlyHint: true,\n idempotentHint: true,\n destructiveHint: false,\n openWorldHint: false,\n },\n timeoutMs: DEFAULT_SEARCH_TIMEOUT_MS,\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 accessPaths: singleOrBatchAccessPaths,\n run: async (args, ctx) => {\n let pathList: string[];\n let skippedResults = new Map<number, PerPathResult<PerPathReadValue>>();\n let survivors: string[];\n let known = new Map<string, { validPath: string; stats: Stats }>();\n\n if (args.paths !== undefined) {\n pathList = args.paths;\n const defaultMaxTotalSize = getDefaultReadManyMaxTotalSize();\n const maxTextFileSize = getMaxTextFileSize();\n const budget = await collectFileBudget(pathList, defaultMaxTotalSize, maxTextFileSize, ctx);\n known = budget.known;\n skippedResults = budget.skippedResults;\n survivors = budget.survivors;\n } else {\n pathList = [args.path ?? ''];\n survivors = [...pathList];\n }\n\n const batchInput = { paths: survivors };\n\n // Every path can be budget-skipped (a single file over maxTotalSize does\n // it), and runOverPaths rejects an empty list. The per-path TOO_LARGE\n // results are already built — return those rather than failing the call.\n const batch =\n survivors.length === 0\n ? { results: [] as PerPathResult<PerPathReadValue>[] }\n : await runOverPaths<undefined, PerPathReadValue>(\n batchInput,\n ctx,\n ({ path }) => readOnePath(path, args, ctx, known.get(path)),\n { defaultErrorCode: ErrorCode.NOT_FILE },\n );\n\n const resultMap = new Map(batch.results.map((r) => [r.path, r]));\n const ordered: PerPathResult<PerPathReadValue>[] = pathList.map((path, idx) => {\n const skipped = skippedResults.get(idx);\n if (skipped) return skipped;\n const result = resultMap.get(path);\n return (\n result ?? {\n path,\n error: { code: ErrorCode.UNKNOWN, message: 'Unknown read failure' },\n }\n );\n });\n\n const failed = ordered.filter((r) => 'error' in r).length;\n const summary = {\n total: ordered.length,\n succeeded: ordered.length - failed,\n failed,\n };\n\n const resources: ContentBlock[] = [];\n for (const result of ordered) {\n if ('error' in result) continue;\n const v = result.value;\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) 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 Buffer.byteLength(v.content, 'utf8'),\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 { content: _content, mediaData: _mediaData, ...value } = 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});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"replace-in-files.d.ts","sourceRoot":"","sources":["../../src/tools/replace-in-files.ts"],"names":[],"mappings":"AAinBA,eAAO,MAAM,kBAAkB,mCAyC7B,CAAC"}
1
+ {"version":3,"file":"replace-in-files.d.ts","sourceRoot":"","sources":["../../src/tools/replace-in-files.ts"],"names":[],"mappings":"AAylBA,eAAO,MAAM,kBAAkB,mCAyC7B,CAAC"}
@@ -63,7 +63,7 @@ import { toPosixRelative } from '../core/path.js';
63
63
  import { escapeRegexLiteral } from '../core/primitives.js';
64
64
  import { readFileBufferWithLimit } from '../core/read.js';
65
65
  import { defaultFalseBoolean, includeHiddenField, includeIgnoredField, isBlank, maxDepthField, NonNegInt, OperationSummarySchema, OptionalPath, PerFileErrorSchema, SafeGlobPattern, } from '../core/schema.js';
66
- import { compileRegex, freeRegex } from '../core/search.js';
66
+ import { compileRegex, execMatches, freeRegex } from '../core/search.js';
67
67
  import { DEFAULT_SEARCH_RESULTS, DEFAULT_SEARCH_TIMEOUT_MS, getMaxTextFileSize, MAX_SEARCH_RESULTS, PARALLEL_CONCURRENCY, } from '../core/util.js';
68
68
  import { isTotalFailure } from './batch.js';
69
69
  import { defineTool } from './define.js';
@@ -167,8 +167,8 @@ const DOLLAR_TOKEN = /\$(\$|&|`|'|<([^>]*)>|\d{1,2})/g;
167
167
  * `Invalid replacement string` on any `$` not followed by a substitution it
168
168
  * recognises (so a replacement of `$100` or a trailing `$` fails outright,
169
169
  * where `RegExp` inserts the `$` literally), and it renders an out-of-range
170
- * `$5` as `$4`. Passing a function to `String.replace` disables RE2's handling
171
- * entirely, which leaves this the single owner of the syntax.
170
+ * `$5` as `$4`. The matcher splices matches itself, so this is the single owner
171
+ * of the syntax.
172
172
  */
173
173
  function expandDollarTokens(template, match, groups, offset, input, named) {
174
174
  return template.replace(DOLLAR_TOKEN, (token, kind, name) => {
@@ -206,29 +206,26 @@ function createRegexReplacementMatcher(regex, expandReplacement) {
206
206
  return regex.test(buffer.toString('utf-8'));
207
207
  },
208
208
  replace(content, replacement) {
209
- regex.lastIndex = 0;
209
+ // Splicing by hand rather than through `String.replace(regex, …)`: RE2's
210
+ // own replacer indexes the JS string with the code-point offsets it
211
+ // reports, which lands the replacement short by one per astral character
212
+ // (most emoji) earlier in the file. execMatches reports UTF-16 offsets.
210
213
  let matchCount = 0;
211
- // Only isRegex=true opts into $1/$& substitution. A literal search reaches
212
- // this matcher too (case-insensitive and wholeWord both need a regex), and
213
- // there the replacement must be inserted verbatim.
214
- if (!expandReplacement) {
215
- const updated = content.replace(regex, () => {
216
- matchCount++;
217
- return replacement;
218
- });
219
- return { content: updated, matchCount };
220
- }
221
- const updated = content.replace(regex, (match, ...rest) => {
214
+ let updated = '';
215
+ let cursor = 0;
216
+ for (const match of execMatches(regex, content)) {
222
217
  matchCount++;
223
- // In ECMAScript/RE2, trailing arguments are [offset, input] or [offset, input, namedGroups].
224
- const named = rest.length >= 3 && typeof rest[rest.length - 3] === 'number'
225
- ? rest.pop()
226
- : undefined;
227
- const input = rest.pop();
228
- const offset = rest.pop();
229
- return expandDollarTokens(replacement, match, rest, offset, input, named);
230
- });
231
- return { content: updated, matchCount };
218
+ // Only isRegex=true opts into $1/$& substitution. A literal search
219
+ // reaches this matcher too (case-insensitive and wholeWord both need a
220
+ // regex), and there the replacement must be inserted verbatim.
221
+ updated +=
222
+ content.slice(cursor, match.start) +
223
+ (expandReplacement
224
+ ? expandDollarTokens(replacement, match.text, match.groups, match.start, content, match.named)
225
+ : replacement);
226
+ cursor = match.end;
227
+ }
228
+ return { content: updated + content.slice(cursor), matchCount };
232
229
  },
233
230
  dispose() {
234
231
  freeRegex(regex);
@@ -254,17 +251,6 @@ function createCaseSensitiveLiteralMatcher(searchPattern) {
254
251
  },
255
252
  };
256
253
  }
257
- function buildReplacementPlan(content, replacement, matcher) {
258
- const { content: updatedContent, matchCount } = matcher.replace(content, replacement);
259
- if (matchCount === 0) {
260
- return undefined;
261
- }
262
- return {
263
- matchCount,
264
- originalContent: content,
265
- updatedContent,
266
- };
267
- }
268
254
  async function processEntry(entryPath, ctx) {
269
255
  const { options, signal, summary } = ctx;
270
256
  const validPath = entryPath;
@@ -311,7 +297,9 @@ async function readReplacementPlan(validPath, ctx) {
311
297
  const buffer = await readFileBufferWithLimit(fileHandle, maxFileSize, validPath, signal);
312
298
  if (!matcher.testBuffer(buffer))
313
299
  return undefined;
314
- return buildReplacementPlan(buffer.toString('utf-8'), replacement, matcher);
300
+ const originalContent = buffer.toString('utf-8');
301
+ const { content: updatedContent, matchCount } = matcher.replace(originalContent, replacement);
302
+ return matchCount === 0 ? undefined : { matchCount, originalContent, updatedContent };
315
303
  }
316
304
  catch (e_1) {
317
305
  env_1.error = e_1;
@@ -417,13 +405,8 @@ async function handleSearchAndReplace(args, ctx) {
417
405
  const effectivePattern = args.pattern ?? '**/*';
418
406
  // An explicit single-file target bypasses baseNameMatch/exclude/hidden/
419
407
  // gitignore filtering — it should always be processed as the one file named.
420
- // The async generator matches globEntries' AsyncIterable contract; it needs
421
- // no await (single yield), hence the disable.
422
408
  const entries = singleFile
423
- ? // eslint-disable-next-line @typescript-eslint/require-await
424
- (async function* singleFileEntry() {
425
- yield { path: singleFile };
426
- })()
409
+ ? [{ path: singleFile }]
427
410
  : globEntries({
428
411
  cwd: root,
429
412
  pattern: effectivePattern,