@j0hanz/filesystem-mcp 2.1.7 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -9
- package/dist/cli.d.ts +1 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +29 -34
- package/dist/cli.js.map +1 -1
- package/dist/core/concurrency.d.ts +4 -7
- package/dist/core/concurrency.d.ts.map +1 -1
- package/dist/core/concurrency.js +4 -12
- package/dist/core/concurrency.js.map +1 -1
- package/dist/core/cursor.d.ts +11 -0
- package/dist/core/cursor.d.ts.map +1 -1
- package/dist/core/cursor.js +18 -20
- package/dist/core/cursor.js.map +1 -1
- package/dist/core/fmt.d.ts +2 -1
- package/dist/core/fmt.d.ts.map +1 -1
- package/dist/core/fmt.js +8 -15
- package/dist/core/fmt.js.map +1 -1
- package/dist/core/fs.d.ts +0 -14
- package/dist/core/fs.d.ts.map +1 -1
- package/dist/core/fs.js +1 -0
- package/dist/core/fs.js.map +1 -1
- package/dist/core/glob.d.ts +4 -16
- package/dist/core/glob.d.ts.map +1 -1
- package/dist/core/glob.js +16 -33
- package/dist/core/glob.js.map +1 -1
- package/dist/core/input-required.d.ts +10 -2
- package/dist/core/input-required.d.ts.map +1 -1
- package/dist/core/input-required.js +10 -0
- package/dist/core/input-required.js.map +1 -1
- package/dist/core/observability.d.ts.map +1 -1
- package/dist/core/observability.js +2 -1
- package/dist/core/observability.js.map +1 -1
- package/dist/core/path-completer.d.ts.map +1 -1
- package/dist/core/path-completer.js +4 -27
- package/dist/core/path-completer.js.map +1 -1
- package/dist/core/path-utils.d.ts +1 -1
- package/dist/core/path-utils.d.ts.map +1 -1
- package/dist/core/path-utils.js +2 -2
- package/dist/core/path-utils.js.map +1 -1
- package/dist/core/path.d.ts +7 -9
- package/dist/core/path.d.ts.map +1 -1
- package/dist/core/path.js +24 -42
- package/dist/core/path.js.map +1 -1
- package/dist/core/primitives.d.ts +7 -0
- package/dist/core/primitives.d.ts.map +1 -1
- package/dist/core/primitives.js +15 -8
- package/dist/core/primitives.js.map +1 -1
- package/dist/core/read.d.ts.map +1 -1
- package/dist/core/read.js +6 -23
- package/dist/core/read.js.map +1 -1
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/schema.js +19 -74
- package/dist/core/schema.js.map +1 -1
- package/dist/core/search.d.ts +4 -11
- package/dist/core/search.d.ts.map +1 -1
- package/dist/core/search.js +11 -18
- package/dist/core/search.js.map +1 -1
- package/dist/core/store.d.ts.map +1 -1
- package/dist/core/store.js +6 -17
- package/dist/core/store.js.map +1 -1
- package/dist/core/util.d.ts.map +1 -1
- package/dist/core/util.js +2 -11
- package/dist/core/util.js.map +1 -1
- package/dist/index.js +15 -42
- package/dist/index.js.map +1 -1
- package/dist/instructions.js +11 -11
- package/dist/instructions.js.map +1 -1
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +17 -25
- package/dist/prompts.js.map +1 -1
- package/dist/resources.d.ts +4 -4
- package/dist/resources.d.ts.map +1 -1
- package/dist/resources.js +7 -17
- package/dist/resources.js.map +1 -1
- package/dist/server.d.ts +1 -12
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +15 -30
- package/dist/server.js.map +1 -1
- package/dist/tools/define.d.ts.map +1 -1
- package/dist/tools/define.js +39 -65
- package/dist/tools/define.js.map +1 -1
- package/dist/tools/delete.d.ts +2 -0
- package/dist/tools/delete.d.ts.map +1 -0
- package/dist/tools/{delete-file.js → delete.js} +35 -40
- package/dist/tools/delete.js.map +1 -0
- package/dist/tools/find-files.d.ts +2 -0
- package/dist/tools/find-files.d.ts.map +1 -0
- package/dist/tools/{search-files.js → find-files.js} +14 -19
- package/dist/tools/find-files.js.map +1 -0
- package/dist/tools/index.d.ts +6 -6
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +15 -15
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/list-roots.d.ts +2 -0
- package/dist/tools/list-roots.d.ts.map +1 -0
- package/dist/tools/{roots.js → list-roots.js} +2 -2
- package/dist/tools/list-roots.js.map +1 -0
- package/dist/tools/list.d.ts.map +1 -1
- package/dist/tools/list.js +29 -37
- package/dist/tools/list.js.map +1 -1
- package/dist/tools/move.d.ts.map +1 -1
- package/dist/tools/move.js +5 -7
- package/dist/tools/move.js.map +1 -1
- package/dist/tools/progress.d.ts +1 -1
- package/dist/tools/progress.d.ts.map +1 -1
- package/dist/tools/progress.js.map +1 -1
- package/dist/tools/read.d.ts +1 -1
- package/dist/tools/read.d.ts.map +1 -1
- package/dist/tools/read.js +37 -43
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/replace-text.d.ts +2 -0
- package/dist/tools/replace-text.d.ts.map +1 -0
- package/dist/tools/{replace-in-files.js → replace-text.js} +9 -23
- package/dist/tools/replace-text.js.map +1 -0
- package/dist/tools/search-text.d.ts +2 -0
- package/dist/tools/search-text.d.ts.map +1 -0
- package/dist/tools/{search-content.js → search-text.js} +10 -37
- package/dist/tools/search-text.js.map +1 -0
- package/dist/tools/stat.d.ts +1 -1
- package/dist/tools/stat.d.ts.map +1 -1
- package/dist/tools/stat.js +10 -38
- package/dist/tools/stat.js.map +1 -1
- package/dist/transport/http-policy.d.ts +18 -15
- package/dist/transport/http-policy.d.ts.map +1 -1
- package/dist/transport/http-policy.js +29 -39
- package/dist/transport/http-policy.js.map +1 -1
- package/dist/transport/http.d.ts.map +1 -1
- package/dist/transport/http.js +29 -39
- package/dist/transport/http.js.map +1 -1
- package/package.json +4 -7
- package/dist/tools/delete-file.d.ts +0 -2
- package/dist/tools/delete-file.d.ts.map +0 -1
- package/dist/tools/delete-file.js.map +0 -1
- package/dist/tools/replace-in-files.d.ts +0 -2
- package/dist/tools/replace-in-files.d.ts.map +0 -1
- package/dist/tools/replace-in-files.js.map +0 -1
- package/dist/tools/roots.d.ts +0 -2
- package/dist/tools/roots.d.ts.map +0 -1
- package/dist/tools/roots.js.map +0 -1
- package/dist/tools/search-content.d.ts +0 -2
- package/dist/tools/search-content.d.ts.map +0 -1
- package/dist/tools/search-content.js.map +0 -1
- package/dist/tools/search-files.d.ts +0 -2
- package/dist/tools/search-files.d.ts.map +0 -1
- package/dist/tools/search-files.js.map +0 -1
package/dist/tools/read.js
CHANGED
|
@@ -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:
|
|
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
|
|
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
|
|
163
|
-
if (
|
|
164
|
+
const path = filePaths[i];
|
|
165
|
+
if (path === undefined)
|
|
164
166
|
continue;
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
//
|
|
168
|
-
// through to survivors so its read surfaces the real error
|
|
169
|
-
//
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
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
|
-
|
|
185
|
+
continue;
|
|
176
186
|
}
|
|
177
|
-
|
|
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
|
-
|
|
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(
|
|
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')
|
|
@@ -291,7 +289,7 @@ async function readOnePath(filePath, args, ctx, known) {
|
|
|
291
289
|
requestedPath: filePath,
|
|
292
290
|
});
|
|
293
291
|
}
|
|
294
|
-
export const
|
|
292
|
+
export const READ = defineTool({
|
|
295
293
|
name: 'read',
|
|
296
294
|
title: 'Read File',
|
|
297
295
|
description: 'Read one or more text files and return content. ' +
|
|
@@ -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
|
-
|
|
343
|
-
|
|
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 ?? ''];
|
package/dist/tools/read.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/tools/read.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContentBlock } from '@modelcontextprotocol/server';\n\nimport { createHash } from 'node:crypto';\nimport 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 = 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"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replace-text.d.ts","sourceRoot":"","sources":["../../src/tools/replace-text.ts"],"names":[],"mappings":"AAylBA,eAAO,MAAM,YAAY,mCAyCvB,CAAC"}
|
|
@@ -58,7 +58,7 @@ import { unifiedPatch } from '../core/diff.js';
|
|
|
58
58
|
import { ErrorCode, formatUnknownErrorMessage, FsError, Problem, rethrowIfAborted, } from '../core/errors.js';
|
|
59
59
|
import { buildFileResourceLink } from '../core/file-uri.js';
|
|
60
60
|
import { truncateProgressPattern } from '../core/fmt.js';
|
|
61
|
-
import {
|
|
61
|
+
import { globEntries } from '../core/glob.js';
|
|
62
62
|
import { toPosixRelative } from '../core/path.js';
|
|
63
63
|
import { escapeRegexLiteral } from '../core/primitives.js';
|
|
64
64
|
import { readFileBufferWithLimit } from '../core/read.js';
|
|
@@ -251,17 +251,6 @@ function createCaseSensitiveLiteralMatcher(searchPattern) {
|
|
|
251
251
|
},
|
|
252
252
|
};
|
|
253
253
|
}
|
|
254
|
-
function buildReplacementPlan(content, replacement, matcher) {
|
|
255
|
-
const { content: updatedContent, matchCount } = matcher.replace(content, replacement);
|
|
256
|
-
if (matchCount === 0) {
|
|
257
|
-
return undefined;
|
|
258
|
-
}
|
|
259
|
-
return {
|
|
260
|
-
matchCount,
|
|
261
|
-
originalContent: content,
|
|
262
|
-
updatedContent,
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
254
|
async function processEntry(entryPath, ctx) {
|
|
266
255
|
const { options, signal, summary } = ctx;
|
|
267
256
|
const validPath = entryPath;
|
|
@@ -308,7 +297,9 @@ async function readReplacementPlan(validPath, ctx) {
|
|
|
308
297
|
const buffer = await readFileBufferWithLimit(fileHandle, maxFileSize, validPath, signal);
|
|
309
298
|
if (!matcher.testBuffer(buffer))
|
|
310
299
|
return undefined;
|
|
311
|
-
|
|
300
|
+
const originalContent = buffer.toString('utf-8');
|
|
301
|
+
const { content: updatedContent, matchCount } = matcher.replace(originalContent, replacement);
|
|
302
|
+
return matchCount === 0 ? undefined : { matchCount, originalContent, updatedContent };
|
|
312
303
|
}
|
|
313
304
|
catch (e_1) {
|
|
314
305
|
env_1.error = e_1;
|
|
@@ -414,19 +405,14 @@ async function handleSearchAndReplace(args, ctx) {
|
|
|
414
405
|
const effectivePattern = args.pattern ?? '**/*';
|
|
415
406
|
// An explicit single-file target bypasses baseNameMatch/exclude/hidden/
|
|
416
407
|
// gitignore filtering — it should always be processed as the one file named.
|
|
417
|
-
// The async generator matches globEntries' AsyncIterable contract; it needs
|
|
418
|
-
// no await (single yield), hence the disable.
|
|
419
408
|
const entries = singleFile
|
|
420
|
-
?
|
|
421
|
-
(async function* singleFileEntry() {
|
|
422
|
-
yield { path: singleFile };
|
|
423
|
-
})()
|
|
409
|
+
? [{ path: singleFile }]
|
|
424
410
|
: globEntries({
|
|
425
411
|
cwd: root,
|
|
426
412
|
pattern: effectivePattern,
|
|
427
|
-
excludePatterns: args.includeIgnored ? [] : DEFAULT_EXCLUDE_PATTERNS,
|
|
428
413
|
includeHidden: args.includeHidden,
|
|
429
|
-
|
|
414
|
+
skipIgnored: !args.includeIgnored,
|
|
415
|
+
signal: ctx.signal,
|
|
430
416
|
baseNameMatch: true,
|
|
431
417
|
onlyFiles: true,
|
|
432
418
|
suppressErrors: true,
|
|
@@ -506,7 +492,7 @@ async function handleSearchAndReplace(args, ctx) {
|
|
|
506
492
|
}
|
|
507
493
|
return { structured };
|
|
508
494
|
}
|
|
509
|
-
export const
|
|
495
|
+
export const REPLACE_TEXT = defineTool({
|
|
510
496
|
name: 'replace_text',
|
|
511
497
|
title: 'Search and Replace',
|
|
512
498
|
description: 'Bulk search-and-replace across files matching a glob pattern. ' +
|
|
@@ -546,4 +532,4 @@ export const SEARCH_AND_REPLACE = defineTool({
|
|
|
546
532
|
return { structured, text: summaryText, isError };
|
|
547
533
|
},
|
|
548
534
|
});
|
|
549
|
-
//# sourceMappingURL=replace-
|
|
535
|
+
//# sourceMappingURL=replace-text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replace-text.js","sourceRoot":"","sources":["../../src/tools/replace-text.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContentBlock } from '@modelcontextprotocol/server';\n\nimport { Buffer } from 'node:buffer';\nimport { dirname, join } from 'node:path';\n\nimport * as z from 'zod/v4';\n\nimport type { StoppedReason, StopReasonTracker } from '../core/concurrency.js';\nimport { processEntriesConcurrently, StoppedReasonSchema } from '../core/concurrency.js';\nimport { unifiedPatch } from '../core/diff.js';\nimport {\n ErrorCode,\n formatUnknownErrorMessage,\n FsError,\n Problem,\n rethrowIfAborted,\n} from '../core/errors.js';\nimport { buildFileResourceLink } from '../core/file-uri.js';\nimport { truncateProgressPattern } from '../core/fmt.js';\nimport type { GuardedFileSystem } from '../core/fs.js';\nimport { globEntries } from '../core/glob.js';\nimport { toPosixRelative } from '../core/path.js';\nimport { escapeRegexLiteral } from '../core/primitives.js';\nimport { readFileBufferWithLimit } from '../core/read.js';\nimport {\n defaultFalseBoolean,\n includeHiddenField,\n includeIgnoredField,\n isBlank,\n maxDepthField,\n NonNegInt,\n OperationSummarySchema,\n OptionalPath,\n PerFileErrorSchema,\n SafeGlobPattern,\n} from '../core/schema.js';\nimport type { Regex } from '../core/search.js';\nimport { compileRegex, execMatches, freeRegex } from '../core/search.js';\nimport {\n DEFAULT_SEARCH_RESULTS,\n DEFAULT_SEARCH_TIMEOUT_MS,\n getMaxTextFileSize,\n MAX_SEARCH_RESULTS,\n PARALLEL_CONCURRENCY,\n} from '../core/util.js';\nimport { isTotalFailure } from './batch.js';\nimport { defineTool, type ToolCtx } from './define.js';\n\nconst SearchAndReplaceInputSchema = z.strictObject({\n path: OptionalPath.describe(\n 'File to rewrite, or directory to rewrite under. Omitting it targets the ENTIRE first allowed root — ' +\n 'scope it deliberately, and pair a wide scope with dryRun=true first',\n ),\n pattern: SafeGlobPattern.optional().describe(\n 'Glob to restrict replacements to specific file types (e.g. **/*.ts); default: all text files',\n ),\n searchPattern: z\n .string()\n .min(1)\n .max(10000)\n .refine((val) => !isBlank(val), {\n message: 'searchPattern cannot be empty or whitespace-only',\n })\n .describe(\n 'Exact literal text or RE2 regex pattern to search for. When isRegex=true, uses RE2 syntax (no lookahead, lookbehind, or backreferences are supported). Cannot be empty or whitespace-only.',\n )\n .meta({ examples: ['TODO', 'function\\\\s+(\\\\w+)', 'import.*from'] }),\n replacement: z\n .string()\n .max(10000)\n .describe(\n 'Replacement text. Use capture group references ($1, $2, etc.) when isRegex=true. Use an empty string to delete all matches.',\n )\n .meta({ examples: ['$1_renamed', '', 'TODO: fix'] }),\n isRegex: defaultFalseBoolean('Treat searchPattern as a RE2 regex (default: literal text match)'),\n includeHidden: includeHiddenField(),\n includeIgnored: includeIgnoredField(),\n caseSensitive: defaultFalseBoolean('Enable case-sensitive matching (default: case-insensitive)'),\n wholeWord: defaultFalseBoolean('Match whole words only (word boundary anchoring)'),\n dryRun: defaultFalseBoolean(\n 'Preview replacements without writing to disk (default: false = apply changes)',\n ),\n returnDiff: defaultFalseBoolean('Include a unified diff of all changes in the response'),\n maxResults: z\n .uint32()\n .min(1)\n .max(MAX_SEARCH_RESULTS)\n .optional()\n .default(DEFAULT_SEARCH_RESULTS)\n .describe('Maximum total match count across all files before stopping'),\n maxFiles: z\n .uint32()\n .min(1)\n .max(MAX_SEARCH_RESULTS)\n .optional()\n .describe('Maximum number of files to process'),\n maxDepth: maxDepthField(),\n});\n\nconst ReplacePerPathSchema = z.strictObject({\n path: z.string().describe('File path relative to the search root'),\n value: z\n .strictObject({ matches: NonNegInt.describe('Replacements applied in this file') })\n .optional()\n .describe('Replacement outcome; present on success'),\n error: PerFileErrorSchema.optional().describe('Error details; present on failure'),\n});\n\n// The same `{ results, summary }` envelope `read`, `stat`, and `delete` use, so\n// a caller learns one shape for every tool that spans many paths. The former\n// `filesModified` / `failedFiles` counters are `summary.succeeded` / `.failed`,\n// and the old `primaryFile` block is gone — the resource_link content block\n// already points at the first modified file.\nconst SearchAndReplaceOutputSchema = z.strictObject({\n results: z\n .array(ReplacePerPathSchema)\n .describe('Per-file results: modified files, then any that could not be processed'),\n summary: OperationSummarySchema,\n totalMatches: NonNegInt.describe('Total number of replacements made across all files'),\n filesScanned: NonNegInt.describe('Total number of files examined'),\n resultsTruncated: z\n .boolean()\n .optional()\n .describe(\n 'True when the results list holds fewer entries than summary.total: the changed-file or failed-file cap was hit. Trust summary over results.length.',\n ),\n diff: z\n .string()\n .optional()\n .describe('Unified diff of all changes (present when returnDiff=true or dryRun=true)'),\n diffTruncated: z\n .boolean()\n .optional()\n .describe('True when the diff was cut due to the size limit'),\n stoppedReason: StoppedReasonSchema.describe(\n 'Why enumeration stopped early: maxResults = match cap reached, maxFiles = file cap reached, timeout = time limit hit or cancelled. Absent when every matching file was enumerated. Marks the sweep incomplete, not the writes; files already dispatched still complete.',\n ),\n});\n\nconst MAX_FAILURES = 20;\nconst REPLACE_CONCURRENCY = Math.min(PARALLEL_CONCURRENCY, 8);\nconst MAX_CHANGED_FILES = 100;\nconst MAX_DIFF_SIZE = 20 * 1024; // 20KB limit for diff output\nconst DIFF_APPEND_BUFFER = 1024;\n\ninterface Failure {\n path: string;\n error: NonNullable<z.infer<typeof ReplacePerPathSchema>['error']>;\n}\n\nfunction recordFailure(failures: Failure[], failure: Failure): void {\n if (failures.length >= MAX_FAILURES) return;\n failures.push(failure);\n}\n\nfunction recordChangedFile(summary: ReplaceSummary, filePath: string, matchCount: number): void {\n const relativePath = toPosixRelative(summary.root, filePath);\n if (summary.changedFiles.length < MAX_CHANGED_FILES) {\n summary.changedFiles.push({ path: relativePath, matches: matchCount });\n return;\n }\n summary.changedFilesTruncated = true;\n}\n\ninterface ReplacementMatcher {\n replace(content: string, replacement: string): { content: string; matchCount: number };\n testBuffer(buffer: Buffer): boolean;\n /** Releases any compiled pattern this matcher owns. Idempotent. */\n dispose(): void;\n}\n\nconst DOLLAR_TOKEN = /\\$(\\$|&|`|'|<([^>]*)>|\\d{1,2})/g;\n\n/**\n * Expand `$`-substitutions in a replacement template the way `RegExp` does.\n *\n * We cannot hand the template to RE2's own string replacer: it throws\n * `Invalid replacement string` on any `$` not followed by a substitution it\n * recognises (so a replacement of `$100` or a trailing `$` fails outright,\n * where `RegExp` inserts the `$` literally), and it renders an out-of-range\n * `$5` as `$4`. The matcher splices matches itself, so this is the single owner\n * of the syntax.\n */\nfunction expandDollarTokens(\n template: string,\n match: string,\n groups: (string | undefined)[],\n offset: number,\n input: string,\n named: Record<string, string> | undefined,\n): string {\n return template.replace(DOLLAR_TOKEN, (token: string, kind: string, name?: string) => {\n if (kind === '$') return '$';\n if (kind === '&') return match;\n if (kind === '`') return input.slice(0, offset);\n if (kind === \"'\") return input.slice(offset + match.length);\n if (name !== undefined) {\n if (named && Object.hasOwn(named, name)) return named[name] ?? '';\n return token;\n }\n // `$12` prefers group 12, then falls back to group 1 followed by a literal\n // `2`, and stays literal when neither exists — RegExp's own precedence.\n const two = Number.parseInt(kind, 10);\n if (kind.length === 2 && two >= 1 && two <= groups.length) return groups[two - 1] ?? '';\n const one = Number.parseInt(kind.slice(0, 1), 10);\n if (one >= 1 && one <= groups.length) {\n return (groups[one - 1] ?? '') + (kind.length === 2 ? kind.slice(1) : '');\n }\n return token;\n });\n}\n\nfunction createRegexReplacementMatcher(\n regex: Regex,\n expandReplacement: boolean,\n): ReplacementMatcher {\n return {\n testBuffer(buffer: Buffer): boolean {\n // The regex is global and shared across every file in the batch, so a\n // previous file's match would otherwise start this scan mid-string.\n regex.lastIndex = 0;\n return regex.test(buffer.toString('utf-8'));\n },\n replace(content: string, replacement: string): { content: string; matchCount: number } {\n // Splicing by hand rather than through `String.replace(regex, …)`: RE2's\n // own replacer indexes the JS string with the code-point offsets it\n // reports, which lands the replacement short by one per astral character\n // (most emoji) earlier in the file. execMatches reports UTF-16 offsets.\n let matchCount = 0;\n let updated = '';\n let cursor = 0;\n for (const match of execMatches(regex, content)) {\n matchCount++;\n // Only isRegex=true opts into $1/$& substitution. A literal search\n // reaches this matcher too (case-insensitive and wholeWord both need a\n // regex), and there the replacement must be inserted verbatim.\n updated +=\n content.slice(cursor, match.start) +\n (expandReplacement\n ? expandDollarTokens(\n replacement,\n match.text,\n match.groups,\n match.start,\n content,\n match.named,\n )\n : replacement);\n cursor = match.end;\n }\n return { content: updated + content.slice(cursor), matchCount };\n },\n dispose(): void {\n freeRegex(regex);\n },\n };\n}\n\nfunction createCaseSensitiveLiteralMatcher(searchPattern: string): ReplacementMatcher {\n const searchBuffer = Buffer.from(searchPattern, 'utf8');\n\n return {\n testBuffer(buffer: Buffer): boolean {\n return buffer.indexOf(searchBuffer) !== -1;\n },\n replace(content: string, replacement: string): { content: string; matchCount: number } {\n let matchCount = 0;\n const updated = content.replaceAll(searchPattern, () => {\n matchCount++;\n return replacement;\n });\n return { content: updated, matchCount };\n },\n dispose(): void {\n // no compiled pattern to release\n },\n };\n}\n\ntype SearchAndReplaceArgs = z.infer<typeof SearchAndReplaceInputSchema>;\ntype SearchAndReplaceOutput = z.infer<typeof SearchAndReplaceOutputSchema>;\n\ninterface ReplaceContext {\n options: { dryRun: boolean; returnDiff: boolean };\n replacement: string;\n matcher: ReplacementMatcher;\n maxFileSize: number;\n signal: AbortSignal | undefined;\n summary: ReplaceSummary;\n fs: GuardedFileSystem;\n}\n\ninterface ReplacementPlan {\n matchCount: number;\n originalContent: string;\n updatedContent: string;\n}\n\nasync function processEntry(entryPath: string, ctx: ReplaceContext): Promise<void> {\n const { options, signal, summary } = ctx;\n const validPath = entryPath;\n\n try {\n const plan = await readReplacementPlan(validPath, ctx);\n if (!plan) {\n return;\n }\n\n if (!options.dryRun) {\n await ctx.fs.writeFile(entryPath, plan.updatedContent, {\n encoding: 'utf-8',\n signal,\n });\n }\n\n // Bookkeep only after the write succeeds (or in dryRun, where there is no\n // write): a failed write must not count the file as changed.\n summary.totalMatches += plan.matchCount;\n summary.filesChanged++;\n\n recordChangedFile(summary, validPath, plan.matchCount);\n\n maybeAppendPatchDiff(summary, {\n filePath: validPath,\n originalContent: plan.originalContent,\n updatedContent: plan.updatedContent,\n includeDiff: options.dryRun || options.returnDiff,\n });\n } catch (error) {\n summary.failedFiles++;\n recordFailure(summary.failures, {\n path: toPosixRelative(summary.root, validPath),\n error: Problem.fromUnknown(error, ErrorCode.UNKNOWN, validPath),\n });\n }\n}\n\nasync function readReplacementPlan(\n validPath: string,\n ctx: ReplaceContext,\n): Promise<ReplacementPlan | undefined> {\n const { matcher, replacement, maxFileSize, signal } = ctx;\n await using fileHandle = await ctx.fs.open(validPath);\n const stats = await fileHandle.stat();\n if (stats.size > maxFileSize) {\n throw new FsError(\n ErrorCode.TOO_LARGE,\n `File too large: ${validPath} (${String(stats.size)} bytes > ${String(maxFileSize)} bytes)`,\n );\n }\n\n const buffer = await readFileBufferWithLimit(fileHandle, maxFileSize, validPath, signal);\n if (!matcher.testBuffer(buffer)) return undefined;\n\n const originalContent = buffer.toString('utf-8');\n const { content: updatedContent, matchCount } = matcher.replace(originalContent, replacement);\n return matchCount === 0 ? undefined : { matchCount, originalContent, updatedContent };\n}\n\nfunction maybeAppendPatchDiff(\n summary: ReplaceSummary,\n params: {\n filePath: string;\n originalContent: string;\n updatedContent: string;\n includeDiff: boolean;\n },\n): void {\n if (!params.includeDiff) return;\n const header = toPosixRelative(summary.root, params.filePath);\n\n const patch = unifiedPatch(header, params.originalContent, params.updatedContent);\n\n if (summary.diff.length >= MAX_DIFF_SIZE) {\n summary.diffTruncated = true;\n return;\n }\n\n if (summary.diff.length + patch.length <= MAX_DIFF_SIZE + DIFF_APPEND_BUFFER) {\n summary.diff += patch;\n return;\n }\n\n summary.diffTruncated = true;\n}\n\ninterface ReplaceSummary {\n root: string;\n totalMatches: number;\n filesChanged: number;\n failedFiles: number;\n processedFiles: number;\n failures: Failure[];\n changedFiles: { path: string; matches: number }[];\n changedFilesTruncated: boolean;\n diff: string;\n diffTruncated: boolean;\n stoppedReason?: StoppedReason;\n}\n\nfunction createReplaceSummary(root: string): ReplaceSummary {\n return {\n root,\n totalMatches: 0,\n filesChanged: 0,\n failedFiles: 0,\n processedFiles: 0,\n failures: [],\n changedFiles: [],\n changedFilesTruncated: false,\n diff: '',\n diffTruncated: false,\n };\n}\n\nasync function resolveSearchRoot(\n pathValue: string | undefined,\n fs: GuardedFileSystem,\n): Promise<{ root: string; singleFile?: string }> {\n if (!pathValue) {\n return { root: fs.pathGuard.resolvePathOrRoot(undefined) };\n }\n const resolvedPath = await fs.pathGuard.validateExistingPath(pathValue);\n const { stats: fileStats } = await fs.stat(resolvedPath);\n if (fileStats.isFile()) {\n // A single explicit file target bypasses the glob machinery entirely:\n // routing it through globEntries with baseNameMatch would rewrite the\n // escaped basename to `**/${basename}` and match every same-named file\n // under the parent tree, not just this one.\n return {\n root: dirname(resolvedPath),\n singleFile: resolvedPath,\n };\n }\n return { root: resolvedPath };\n}\n\nfunction buildSearchPattern(args: SearchAndReplaceArgs): string {\n if (args.isRegex) {\n return args.wholeWord ? `\\\\b(?:${args.searchPattern})\\\\b` : args.searchPattern;\n }\n const escaped = escapeRegexLiteral(args.searchPattern);\n return args.wholeWord ? `\\\\b(?:${escaped})\\\\b` : escaped;\n}\n\nfunction createReplacementMatcher(args: SearchAndReplaceArgs): ReplacementMatcher {\n // Use regex when isRegex, wholeWord, or case-insensitive (all require RE2)\n if (args.isRegex || args.wholeWord || !args.caseSensitive) {\n const regex = compileRegex(buildSearchPattern(args), { caseSensitive: args.caseSensitive });\n return createRegexReplacementMatcher(regex, args.isRegex);\n }\n return createCaseSensitiveLiteralMatcher(args.searchPattern);\n}\n\nfunction buildSearchAndReplaceStructuredResult(\n summary: ReplaceSummary,\n args: SearchAndReplaceArgs,\n): SearchAndReplaceOutput {\n const results = [\n ...summary.changedFiles.map((f) => ({ path: f.path, value: { matches: f.matches } })),\n ...summary.failures.map((f) => ({ path: f.path, error: f.error })),\n ];\n return {\n results,\n // `failedFiles` counts every failure; `failures` itself is capped at\n // MAX_FAILURES, so the summary must not be derived from the array length.\n summary: {\n total: summary.filesChanged + summary.failedFiles,\n succeeded: summary.filesChanged,\n failed: summary.failedFiles,\n },\n totalMatches: summary.totalMatches,\n filesScanned: summary.processedFiles,\n // Failures are capped at MAX_FAILURES independently of the changed-file\n // cap, so either cap can leave `results` shorter than `summary.total`.\n ...(summary.changedFilesTruncated || summary.failures.length < summary.failedFiles\n ? { resultsTruncated: true }\n : {}),\n ...((args.dryRun || args.returnDiff) && summary.diff ? { diff: summary.diff } : {}),\n ...(summary.diffTruncated ? { diffTruncated: true } : {}),\n ...(summary.stoppedReason ? { stoppedReason: summary.stoppedReason } : {}),\n };\n}\n\nasync function handleSearchAndReplace(\n args: SearchAndReplaceArgs,\n ctx: ToolCtx,\n): Promise<{\n structured: SearchAndReplaceOutput;\n link?: ContentBlock;\n}> {\n const maxFileSize = getMaxTextFileSize();\n const { root, singleFile } = await resolveSearchRoot(args.path, ctx.fs);\n const effectivePattern = args.pattern ?? '**/*';\n\n // An explicit single-file target bypasses baseNameMatch/exclude/hidden/\n // gitignore filtering — it should always be processed as the one file named.\n const entries: AsyncIterable<{ path: string }> | Iterable<{ path: string }> = singleFile\n ? [{ path: singleFile }]\n : globEntries({\n cwd: root,\n pattern: effectivePattern,\n includeHidden: args.includeHidden,\n skipIgnored: !args.includeIgnored,\n signal: ctx.signal,\n baseNameMatch: true,\n onlyFiles: true,\n suppressErrors: true,\n ...(args.maxDepth !== undefined ? { maxDepth: args.maxDepth } : {}),\n });\n\n const summary = createReplaceSummary(root);\n\n // The matcher may own a compiled RE2 pattern, whose wasm memory re2-wasm\n // never reclaims on its own. Nothing past the scan touches it, so free it the\n // moment the scan is done — success, failure, or abort alike.\n const matcher = createReplacementMatcher(args);\n let scan: StopReasonTracker;\n try {\n const context: ReplaceContext = {\n options: {\n dryRun: args.dryRun,\n returnDiff: args.returnDiff,\n },\n replacement: args.replacement,\n matcher,\n maxFileSize,\n signal: ctx.signal,\n summary,\n fs: ctx.fs,\n };\n\n scan = await processEntriesConcurrently(entries, {\n signal: ctx.signal,\n concurrency: REPLACE_CONCURRENCY,\n ...(args.maxFiles !== undefined ? { maxEntries: args.maxFiles } : {}),\n shouldStop: () => summary.totalMatches >= args.maxResults,\n onEntry: () => {\n summary.processedFiles++;\n ctx.onProgress?.({ current: summary.processedFiles });\n },\n onError: (entryPath, err) => {\n summary.failedFiles++;\n recordFailure(summary.failures, {\n path: toPosixRelative(summary.root, entryPath),\n error: Problem.fromUnknown(err, ErrorCode.UNKNOWN, entryPath),\n });\n },\n runEntry: (entryPath) => processEntry(entryPath, context),\n });\n } finally {\n matcher.dispose();\n }\n const stoppedReason = scan.resolve();\n if (stoppedReason !== undefined) summary.stoppedReason = stoppedReason;\n\n ctx.onProgress?.({ current: summary.processedFiles });\n\n if (!args.dryRun && summary.totalMatches > 0) {\n ctx.log?.(\n 'info',\n `${summary.filesChanged} file(s) changed, ${summary.totalMatches} match(es)`,\n 'replace_text',\n );\n }\n\n const structured = buildSearchAndReplaceStructuredResult(summary, args);\n\n // Store primary file in resource store if available (skip in dryRun to avoid reading stale disk content)\n if (\n !args.dryRun &&\n ctx.resourceStore &&\n summary.changedFiles.length > 0 &&\n summary.filesChanged > 0\n ) {\n const primaryFile = summary.changedFiles[0];\n if (!primaryFile) return { structured };\n\n const primaryFilePath = primaryFile.path;\n const fullPath = join(summary.root, primaryFilePath);\n\n try {\n const { content: rawBuffer, mimeType } = await ctx.fs.readRaw(fullPath, {\n signal: ctx.signal,\n });\n const link = buildFileResourceLink(fullPath, mimeType, rawBuffer.length);\n return { structured, link };\n } catch (error) {\n rethrowIfAborted(error);\n // Gracefully fall back if resource storage fails\n ctx.log?.(\n 'error',\n `Failed to store primary file in resource store: ${formatUnknownErrorMessage(error)}`,\n 'replace_text',\n );\n }\n }\n\n return { structured };\n}\n\nexport const REPLACE_TEXT = defineTool({\n name: 'replace_text',\n title: 'Search and Replace',\n description:\n 'Bulk search-and-replace across files matching a glob pattern. ' +\n 'Replaces ALL occurrences per file (unlike edit, which replaces only the first match). ' +\n 'Set returnDiff=true to preview changes as a unified diff before or after writing. ' +\n 'Literal matching by default; set isRegex=true to enable RE2 regex with capture groups ($1, $2).',\n input: SearchAndReplaceInputSchema,\n output: SearchAndReplaceOutputSchema,\n annotations: {\n readOnlyHint: false,\n idempotentHint: false,\n destructiveHint: true,\n openWorldHint: false,\n },\n timeoutMs: DEFAULT_SEARCH_TIMEOUT_MS,\n defaultErrorCode: ErrorCode.UNKNOWN,\n progress: (args) => {\n const dryLabel = args.dryRun ? ' [dry run]' : '';\n return {\n label: `Replace${dryLabel}`,\n subject: `${truncateProgressPattern(args.searchPattern)} → ${truncateProgressPattern(args.replacement)}`,\n };\n },\n accessPaths: (args) => (args.path ? [args.path] : []),\n run: async (args, ctx) => {\n const truncatedPattern = truncateProgressPattern(args.searchPattern);\n const { structured, link } = await handleSearchAndReplace(args, ctx);\n const dryLabel = args.dryRun ? ' [dry run]' : '';\n const summaryText =\n `replace_text: '${truncatedPattern}'${dryLabel}` +\n ` \\u00b7 ${String(structured.totalMatches)} match(es)` +\n ` in ${String(structured.summary.succeeded)} file(s)` +\n (structured.summary.failed > 0 ? ` \\u00b7 ${String(structured.summary.failed)} failed` : '');\n const isError = isTotalFailure(structured.summary);\n if (link) {\n return { structured, text: summaryText, resources: [link], isError };\n }\n return { structured, text: summaryText, isError };\n },\n});\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-text.d.ts","sourceRoot":"","sources":["../../src/tools/search-text.ts"],"names":[],"mappings":"AA0TA,eAAO,MAAM,WAAW,mCA8CtB,CAAC"}
|
|
@@ -2,15 +2,13 @@ import { stat } from 'node:fs/promises';
|
|
|
2
2
|
import { basename, dirname } from 'node:path';
|
|
3
3
|
import * as z from 'zod/v4';
|
|
4
4
|
import { SearchStoppedReasonSchema } from '../core/concurrency.js';
|
|
5
|
-
import { paginate } from '../core/cursor.js';
|
|
5
|
+
import { pageQueryKey, paginate } from '../core/cursor.js';
|
|
6
6
|
import { ErrorCode, FsError } from '../core/errors.js';
|
|
7
7
|
import { formatCount, pageTrailer, truncateProgressPattern } from '../core/fmt.js';
|
|
8
|
-
import { DEFAULT_EXCLUDE_PATTERNS } from '../core/glob.js';
|
|
9
8
|
import { Logger } from '../core/observability.js';
|
|
10
9
|
import { toPosixRelative } from '../core/path.js';
|
|
11
|
-
import { escapeRegexLiteral } from '../core/primitives.js';
|
|
12
10
|
import { CursorSchema, defaultFalseBoolean, includeHiddenField, includeIgnoredField, isBlank, maxDepthField, NextCursorSchema, NonNegInt, OptionalPath, PositiveInt, SafeGlobPattern, } from '../core/schema.js';
|
|
13
|
-
import {
|
|
11
|
+
import { searchContent } from '../core/search.js';
|
|
14
12
|
import { putJsonResource } from '../core/store.js';
|
|
15
13
|
import { DEFAULT_SEARCH_CONTENT_RESULTS, DEFAULT_SEARCH_TIMEOUT_MS, MAX_SEARCH_RESULTS, } from '../core/util.js';
|
|
16
14
|
import { defineTool } from './define.js';
|
|
@@ -119,25 +117,15 @@ function buildSortedPayloads(result) {
|
|
|
119
117
|
function buildSearchContentOptions(args, signal) {
|
|
120
118
|
return {
|
|
121
119
|
includeHidden: args.includeHidden,
|
|
122
|
-
excludePatterns: args.includeIgnored ? [] : DEFAULT_EXCLUDE_PATTERNS,
|
|
123
120
|
filePattern: args.pattern ?? '**/*',
|
|
124
121
|
caseSensitive: args.caseSensitive,
|
|
125
122
|
isRegex: args.isRegex,
|
|
126
123
|
maxResults: args.maxResults,
|
|
127
|
-
|
|
124
|
+
skipIgnored: !args.includeIgnored,
|
|
128
125
|
...(args.maxDepth !== undefined ? { maxDepth: args.maxDepth } : {}),
|
|
129
126
|
...(signal ? { signal } : {}),
|
|
130
127
|
};
|
|
131
128
|
}
|
|
132
|
-
function createSearchMatcher(args) {
|
|
133
|
-
if (args.isRegex) {
|
|
134
|
-
return compileRegex(args.searchPattern, { caseSensitive: args.caseSensitive });
|
|
135
|
-
}
|
|
136
|
-
if (!args.caseSensitive) {
|
|
137
|
-
return compileRegex(escapeRegexLiteral(args.searchPattern), { caseSensitive: false });
|
|
138
|
-
}
|
|
139
|
-
return undefined;
|
|
140
|
-
}
|
|
141
129
|
/**
|
|
142
130
|
* `path` is documented as "file to search, or directory to search under", but
|
|
143
131
|
* the scan itself only walks directories. A file path is therefore rewritten
|
|
@@ -165,8 +153,9 @@ async function resolveSearchScope(args, ctx) {
|
|
|
165
153
|
args: { ...args, pattern: basename(resolved), includeHidden: true, includeIgnored: true },
|
|
166
154
|
};
|
|
167
155
|
}
|
|
168
|
-
function
|
|
169
|
-
|
|
156
|
+
async function handleSearchContent(args, ctx) {
|
|
157
|
+
const requestedPath = ctx.fs.pathGuard.resolvePathOrRoot(args.path);
|
|
158
|
+
const queryKey = pageQueryKey({
|
|
170
159
|
method: 'search_text',
|
|
171
160
|
path: requestedPath,
|
|
172
161
|
pattern: args.pattern,
|
|
@@ -177,10 +166,6 @@ function searchContentQueryKey(args, requestedPath) {
|
|
|
177
166
|
caseSensitive: args.caseSensitive,
|
|
178
167
|
maxDepth: args.maxDepth,
|
|
179
168
|
});
|
|
180
|
-
}
|
|
181
|
-
async function handleSearchContent(args, ctx) {
|
|
182
|
-
const requestedPath = ctx.fs.pathGuard.resolvePathOrRoot(args.path);
|
|
183
|
-
const queryKey = searchContentQueryKey(args, requestedPath);
|
|
184
169
|
const { resourceStore } = ctx;
|
|
185
170
|
const paged = await paginate({
|
|
186
171
|
store: ctx.pageStore,
|
|
@@ -189,20 +174,8 @@ async function handleSearchContent(args, ctx) {
|
|
|
189
174
|
pageSize: args.maxResults,
|
|
190
175
|
produce: async () => {
|
|
191
176
|
const { basePath, args: scoped } = await resolveSearchScope(args, ctx);
|
|
192
|
-
const
|
|
193
|
-
const
|
|
194
|
-
// Same pattern, same flags as createSearchMatcher compiled above; pass it
|
|
195
|
-
// through so searchContent does not compile a second copy in re2-wasm's
|
|
196
|
-
// fixed 16 MB heap.
|
|
197
|
-
regexMatcher);
|
|
198
|
-
// regexMatcher holds wasm memory re2-wasm never reclaims on its own.
|
|
199
|
-
let items;
|
|
200
|
-
try {
|
|
201
|
-
items = buildSortedPayloads(result);
|
|
202
|
-
}
|
|
203
|
-
finally {
|
|
204
|
-
freeRegex(regexMatcher);
|
|
205
|
-
}
|
|
177
|
+
const result = await searchContent(basePath, scoped.searchPattern, buildSearchContentOptions({ ...scoped, maxResults: MAX_SEARCH_RESULTS }, ctx.signal), ctx.fs.pathGuard);
|
|
178
|
+
const items = buildSortedPayloads(result);
|
|
206
179
|
return {
|
|
207
180
|
items,
|
|
208
181
|
metadata: {
|
|
@@ -234,7 +207,7 @@ async function handleSearchContent(args, ctx) {
|
|
|
234
207
|
...(paged.resource ? { link: paged.resource.link } : {}),
|
|
235
208
|
};
|
|
236
209
|
}
|
|
237
|
-
export const
|
|
210
|
+
export const SEARCH_TEXT = defineTool({
|
|
238
211
|
name: 'search_text',
|
|
239
212
|
title: 'Search Content',
|
|
240
213
|
description: 'Search file contents by text or regex (grep-style). Returns matching lines with file path, ' +
|
|
@@ -279,4 +252,4 @@ export const SEARCH_CONTENT = defineTool({
|
|
|
279
252
|
return { structured, text };
|
|
280
253
|
},
|
|
281
254
|
});
|
|
282
|
-
//# sourceMappingURL=search-
|
|
255
|
+
//# sourceMappingURL=search-text.js.map
|