@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
@@ -1 +1 @@
1
- {"version":3,"file":"replace-in-files.js","sourceRoot":"","sources":["../../src/tools/replace-in-files.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 { DEFAULT_EXCLUDE_PATTERNS, 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, 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`. Passing a function to `String.replace` disables RE2's handling\n * entirely, which leaves this the single owner 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 regex.lastIndex = 0;\n let matchCount = 0;\n // Only isRegex=true opts into $1/$& substitution. A literal search reaches\n // this matcher too (case-insensitive and wholeWord both need a regex), and\n // there the replacement must be inserted verbatim.\n if (!expandReplacement) {\n const updated = content.replace(regex, () => {\n matchCount++;\n return replacement;\n });\n return { content: updated, matchCount };\n }\n const updated = content.replace(regex, (match: string, ...rest: unknown[]): string => {\n matchCount++;\n // In ECMAScript/RE2, trailing arguments are [offset, input] or [offset, input, namedGroups].\n const named =\n rest.length >= 3 && typeof rest[rest.length - 3] === 'number'\n ? (rest.pop() as Record<string, string> | undefined)\n : undefined;\n const input = rest.pop() as string;\n const offset = rest.pop() as number;\n return expandDollarTokens(\n replacement,\n match,\n rest as (string | undefined)[],\n offset,\n input,\n named,\n );\n });\n return { content: updated, 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\nfunction buildReplacementPlan(\n content: string,\n replacement: string,\n matcher: ReplacementMatcher,\n): ReplacementPlan | undefined {\n const { content: updatedContent, matchCount } = matcher.replace(content, replacement);\n if (matchCount === 0) {\n return undefined;\n }\n\n return {\n matchCount,\n originalContent: content,\n updatedContent,\n };\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 return buildReplacementPlan(buffer.toString('utf-8'), replacement, matcher);\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 // The async generator matches globEntries' AsyncIterable contract; it needs\n // no await (single yield), hence the disable.\n const entries: AsyncIterable<{ path: string }> = singleFile\n ? // eslint-disable-next-line @typescript-eslint/require-await\n (async function* singleFileEntry() {\n yield { path: singleFile };\n })()\n : globEntries({\n cwd: root,\n pattern: effectivePattern,\n excludePatterns: args.includeIgnored ? [] : DEFAULT_EXCLUDE_PATTERNS,\n includeHidden: args.includeHidden,\n respectGitignore: !args.includeIgnored,\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 SEARCH_AND_REPLACE = 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"]}
1
+ {"version":3,"file":"replace-in-files.js","sourceRoot":"","sources":["../../src/tools/replace-in-files.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 { DEFAULT_EXCLUDE_PATTERNS, 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 excludePatterns: args.includeIgnored ? [] : DEFAULT_EXCLUDE_PATTERNS,\n includeHidden: args.includeHidden,\n respectGitignore: !args.includeIgnored,\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 SEARCH_AND_REPLACE = 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"]}
@@ -1 +1 @@
1
- {"version":3,"file":"search-content.d.ts","sourceRoot":"","sources":["../../src/tools/search-content.ts"],"names":[],"mappings":"AAsVA,eAAO,MAAM,cAAc,mCA8CzB,CAAC"}
1
+ {"version":3,"file":"search-content.d.ts","sourceRoot":"","sources":["../../src/tools/search-content.ts"],"names":[],"mappings":"AAgUA,eAAO,MAAM,cAAc,mCA8CzB,CAAC"}
@@ -8,9 +8,8 @@ import { formatCount, pageTrailer, truncateProgressPattern } from '../core/fmt.j
8
8
  import { DEFAULT_EXCLUDE_PATTERNS } from '../core/glob.js';
9
9
  import { Logger } from '../core/observability.js';
10
10
  import { toPosixRelative } from '../core/path.js';
11
- import { escapeRegexLiteral } from '../core/primitives.js';
12
11
  import { CursorSchema, defaultFalseBoolean, includeHiddenField, includeIgnoredField, isBlank, maxDepthField, NextCursorSchema, NonNegInt, OptionalPath, PositiveInt, SafeGlobPattern, } from '../core/schema.js';
13
- import { compileRegex, freeRegex, searchContent } from '../core/search.js';
12
+ import { searchContent } from '../core/search.js';
14
13
  import { putJsonResource } from '../core/store.js';
15
14
  import { DEFAULT_SEARCH_CONTENT_RESULTS, DEFAULT_SEARCH_TIMEOUT_MS, MAX_SEARCH_RESULTS, } from '../core/util.js';
16
15
  import { defineTool } from './define.js';
@@ -129,15 +128,6 @@ function buildSearchContentOptions(args, signal) {
129
128
  ...(signal ? { signal } : {}),
130
129
  };
131
130
  }
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
131
  /**
142
132
  * `path` is documented as "file to search, or directory to search under", but
143
133
  * the scan itself only walks directories. A file path is therefore rewritten
@@ -189,20 +179,8 @@ async function handleSearchContent(args, ctx) {
189
179
  pageSize: args.maxResults,
190
180
  produce: async () => {
191
181
  const { basePath, args: scoped } = await resolveSearchScope(args, ctx);
192
- const regexMatcher = createSearchMatcher(scoped);
193
- const result = await searchContent(basePath, scoped.searchPattern, buildSearchContentOptions({ ...scoped, maxResults: MAX_SEARCH_RESULTS }, ctx.signal), ctx.fs.pathGuard,
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
- }
182
+ const result = await searchContent(basePath, scoped.searchPattern, buildSearchContentOptions({ ...scoped, maxResults: MAX_SEARCH_RESULTS }, ctx.signal), ctx.fs.pathGuard);
183
+ const items = buildSortedPayloads(result);
206
184
  return {
207
185
  items,
208
186
  metadata: {
@@ -1 +1 @@
1
- {"version":3,"file":"search-content.js","sourceRoot":"","sources":["../../src/tools/search-content.ts"],"names":[],"mappings":"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","sourcesContent":["import { stat } from 'node:fs/promises';\nimport { basename, dirname } from 'node:path';\n\nimport * as z from 'zod/v4';\n\nimport { SearchStoppedReasonSchema } from '../core/concurrency.js';\nimport { paginate } from '../core/cursor.js';\nimport { ErrorCode, FsError } from '../core/errors.js';\nimport { formatCount, pageTrailer, truncateProgressPattern } from '../core/fmt.js';\nimport { DEFAULT_EXCLUDE_PATTERNS } from '../core/glob.js';\nimport { Logger } from '../core/observability.js';\nimport { toPosixRelative } from '../core/path.js';\nimport { escapeRegexLiteral } from '../core/primitives.js';\nimport {\n CursorSchema,\n defaultFalseBoolean,\n includeHiddenField,\n includeIgnoredField,\n isBlank,\n maxDepthField,\n NextCursorSchema,\n NonNegInt,\n OptionalPath,\n PositiveInt,\n SafeGlobPattern,\n} from '../core/schema.js';\nimport type { Regex, SearchContentOptions } from '../core/search.js';\nimport { compileRegex, freeRegex, searchContent } from '../core/search.js';\nimport type { JsonResourceResult } from '../core/store.js';\nimport { putJsonResource } from '../core/store.js';\nimport {\n DEFAULT_SEARCH_CONTENT_RESULTS,\n DEFAULT_SEARCH_TIMEOUT_MS,\n MAX_SEARCH_RESULTS,\n} from '../core/util.js';\nimport { defineTool, type ToolCtx } from './define.js';\n\n/**\n * `FS_MAX_INLINE_MATCHES` used to cap how many matches a page showed inline\n * and, past it, push the rest into the resource store. `maxResults` is the one\n * page size now, and the full list is externalized whenever a response is\n * incomplete, so the variable does nothing. It is still read so an operator who\n * set it hears why it stopped mattering; the read goes at the next major.\n */\nif (process.env['FS_MAX_INLINE_MATCHES'] !== undefined) {\n Logger.warn(\n 'FS_MAX_INLINE_MATCHES is deprecated and ignored: maxResults sets the search_text page size. It will be removed in the next major release.',\n );\n}\n\n// Type Definitions\ntype SearchInput = z.infer<typeof GrepInputSchema>;\ntype SearchOutput = z.infer<typeof GrepOutputSchema>;\ntype SearchMatchPayload = NonNullable<SearchOutput['matches']>[number];\ntype SearchResultValue = Awaited<ReturnType<typeof searchContent>>;\n\ninterface SearchContentPageMetadata {\n readonly totalMatches: number;\n readonly filesScanned: number;\n readonly filesMatched?: number;\n readonly truncated: boolean;\n readonly stoppedReason?: SearchOutput['stoppedReason'];\n readonly skippedInaccessible?: number;\n readonly skippedTooLarge?: number;\n}\n\nconst GrepInputSchema = z.strictObject({\n path: OptionalPath.describe(\n 'File to search, or directory to search under (default: the whole first allowed root). Naming a file searches that file alone: pattern is ignored and hidden/ignored filtering does not apply.',\n ),\n pattern: SafeGlobPattern.optional().describe(\n 'Glob to restrict search 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 in file contents. When isRegex=true, uses RE2 syntax (no lookahead, lookbehind, or backreferences). Cannot be empty or whitespace-only.',\n )\n .meta({ examples: ['TODO', 'function\\\\s+(\\\\w+)', 'import.*from'] }),\n isRegex: defaultFalseBoolean('Treat searchPattern as a regex (default: literal text match)'),\n includeHidden: includeHiddenField(),\n includeIgnored: includeIgnoredField(),\n caseSensitive: defaultFalseBoolean('Enable case-sensitive matching (default: case-insensitive)'),\n maxResults: z\n .uint32()\n .min(1)\n .max(MAX_SEARCH_RESULTS)\n .optional()\n .default(DEFAULT_SEARCH_CONTENT_RESULTS)\n .describe('Maximum number of matching lines to return per page'),\n maxDepth: maxDepthField(),\n cursor: CursorSchema,\n});\n\nconst GrepOutputSchema = z.strictObject({\n matches: z\n .array(\n z.strictObject({\n file: z.string().describe('File path relative to the search root'),\n line: PositiveInt.describe('1-indexed line number of the match'),\n column: NonNegInt.optional().describe('0-indexed column offset of the match start'),\n content: z.string().describe('Full text of the matching line'),\n matchCount: NonNegInt.optional().describe('Number of pattern occurrences on this line'),\n }),\n )\n .describe('Flat list of matches sorted by file path then line number'),\n totalMatches: NonNegInt.optional().describe(\n \"Total matching lines, one per entry in matches (not per occurrence); see that entry's matchCount for occurrences on a line.\",\n ),\n filesMatched: NonNegInt.optional().describe('Number of files containing at least one match'),\n filesScanned: NonNegInt.optional().describe('Total number of files examined'),\n skippedInaccessible: NonNegInt.optional().describe(\n 'Files skipped unread due to permission or access errors',\n ),\n skippedTooLarge: NonNegInt.optional().describe(\n 'Files skipped unread because they exceed the text-file size limit; raise the limit or narrow pattern if a match was expected in one',\n ),\n truncated: z\n .boolean()\n .optional()\n .describe(\n 'True when the search engine cut the match list — the hard result cap or the time limit. Paging is not truncation: a set that spans pages has nextCursor instead.',\n ),\n stoppedReason: SearchStoppedReasonSchema.describe(\n 'Why the search ended early: maxResults = result cap reached, timeout = time limit hit or the request was cancelled. Absent when the scan ran to completion.',\n ),\n resourceUri: z\n .string()\n .optional()\n .describe(\n 'URI to the full match list in the resource store; first page only, whenever the response is incomplete — more pages follow, or the engine cut the search',\n ),\n nextCursor: NextCursorSchema,\n});\n\nfunction buildSearchMatchDetail(totalMatches: number, filesMatched: number): string {\n const matchDetail = formatCount(totalMatches, 'match', 'matches');\n if (filesMatched <= 0) return matchDetail;\n return `${matchDetail} · ${formatCount(filesMatched, 'file', 'files')}`;\n}\n\nfunction searchContentOutput(\n matches: readonly SearchMatchPayload[],\n metadata: SearchContentPageMetadata,\n nextCursor: string | undefined,\n resourceUri: string | undefined,\n): SearchOutput {\n return {\n matches: [...matches],\n totalMatches: metadata.totalMatches,\n filesScanned: metadata.filesScanned,\n ...(metadata.filesMatched ? { filesMatched: metadata.filesMatched } : {}),\n ...(metadata.truncated ? { truncated: true } : {}),\n ...(metadata.stoppedReason !== undefined ? { stoppedReason: metadata.stoppedReason } : {}),\n ...(metadata.skippedInaccessible ? { skippedInaccessible: metadata.skippedInaccessible } : {}),\n ...(metadata.skippedTooLarge ? { skippedTooLarge: metadata.skippedTooLarge } : {}),\n ...(resourceUri !== undefined ? { resourceUri } : {}),\n ...(nextCursor !== undefined ? { nextCursor } : {}),\n };\n}\n\nfunction buildSortedPayloads(result: SearchResultValue): SearchMatchPayload[] {\n const relativeByFile = new Map<string, string>();\n\n const getRelativeFile = (file: string): string => {\n const cached = relativeByFile.get(file);\n if (cached !== undefined) return cached;\n\n const rel = toPosixRelative(result.basePath, file);\n relativeByFile.set(file, rel);\n return rel;\n };\n\n const payloads = result.matches.map((match): SearchMatchPayload => ({\n file: getRelativeFile(match.file),\n line: match.line,\n column: match.column,\n content: match.content,\n matchCount: match.matchCount,\n }));\n\n payloads.sort((l, r) => l.file.localeCompare(r.file) || l.line - r.line);\n return payloads;\n}\n\nfunction buildSearchContentOptions(args: SearchInput, signal?: AbortSignal): SearchContentOptions {\n return {\n includeHidden: args.includeHidden,\n excludePatterns: args.includeIgnored ? [] : DEFAULT_EXCLUDE_PATTERNS,\n filePattern: args.pattern ?? '**/*',\n caseSensitive: args.caseSensitive,\n isRegex: args.isRegex,\n maxResults: args.maxResults,\n respectGitignore: !args.includeIgnored,\n ...(args.maxDepth !== undefined ? { maxDepth: args.maxDepth } : {}),\n ...(signal ? { signal } : {}),\n };\n}\n\nfunction createSearchMatcher(args: SearchInput): Regex | undefined {\n if (args.isRegex) {\n return compileRegex(args.searchPattern, { caseSensitive: args.caseSensitive });\n }\n if (!args.caseSensitive) {\n return compileRegex(escapeRegexLiteral(args.searchPattern), { caseSensitive: false });\n }\n return undefined;\n}\n\n/**\n * `path` is documented as \"file to search, or directory to search under\", but\n * the scan itself only walks directories. A file path is therefore rewritten\n * into the scan it means: its parent as the base, its own name as the glob.\n * Naming a file is an explicit request for that file, so hidden/ignored\n * filtering is lifted for it — otherwise `search_text` on a path the caller can\n * see returned nothing.\n */\nasync function resolveSearchScope(\n args: SearchInput,\n ctx: ToolCtx,\n): Promise<{ basePath: string; args: SearchInput }> {\n const requested = ctx.fs.pathGuard.resolvePathOrRoot(args.path);\n // One resolution, one stat: validateExistingDirectory would redo both.\n const resolved = await ctx.fs.pathGuard.validateExistingPath(requested);\n const stats = await stat(resolved);\n if (!stats.isFile()) {\n if (!stats.isDirectory()) {\n throw new FsError(ErrorCode.NOT_DIRECTORY, 'Not a directory', requested);\n }\n return { basePath: resolved, args };\n }\n return {\n basePath: dirname(resolved),\n // ponytail: the name goes through as a glob, so a file whose name contains\n // glob metacharacters (`[id].ts`) matches as a pattern rather than\n // literally. Escape it here if that ever bites.\n args: { ...args, pattern: basename(resolved), includeHidden: true, includeIgnored: true },\n };\n}\n\nfunction searchContentQueryKey(args: SearchInput, requestedPath: string): string {\n return JSON.stringify({\n method: 'search_text',\n path: requestedPath,\n pattern: args.pattern,\n searchPattern: args.searchPattern,\n isRegex: args.isRegex,\n includeHidden: args.includeHidden,\n includeIgnored: args.includeIgnored,\n caseSensitive: args.caseSensitive,\n maxDepth: args.maxDepth,\n });\n}\n\nasync function handleSearchContent(\n args: SearchInput,\n ctx: ToolCtx,\n): Promise<{\n structured: SearchOutput;\n offset: number;\n total: number;\n link?: ReturnType<typeof putJsonResource>['link'];\n}> {\n const requestedPath = ctx.fs.pathGuard.resolvePathOrRoot(args.path);\n const queryKey = searchContentQueryKey(args, requestedPath);\n const { resourceStore } = ctx;\n\n const paged = await paginate<SearchMatchPayload, SearchContentPageMetadata, JsonResourceResult>({\n store: ctx.pageStore,\n queryKey,\n cursor: args.cursor,\n pageSize: args.maxResults,\n produce: async () => {\n const { basePath, args: scoped } = await resolveSearchScope(args, ctx);\n const regexMatcher = createSearchMatcher(scoped);\n\n const result = await searchContent(\n basePath,\n scoped.searchPattern,\n buildSearchContentOptions({ ...scoped, maxResults: MAX_SEARCH_RESULTS }, ctx.signal),\n ctx.fs.pathGuard,\n // Same pattern, same flags as createSearchMatcher compiled above; pass it\n // through so searchContent does not compile a second copy in re2-wasm's\n // fixed 16 MB heap.\n regexMatcher,\n );\n\n // regexMatcher holds wasm memory re2-wasm never reclaims on its own.\n let items: SearchMatchPayload[];\n try {\n items = buildSortedPayloads(result);\n } finally {\n freeRegex(regexMatcher);\n }\n return {\n items,\n metadata: {\n totalMatches: result.summary.matchingLines,\n filesScanned: result.summary.filesScanned,\n ...(result.summary.filesMatched ? { filesMatched: result.summary.filesMatched } : {}),\n truncated: result.summary.truncated,\n ...(result.summary.stoppedReason !== undefined\n ? { stoppedReason: result.summary.stoppedReason }\n : {}),\n ...(result.summary.skippedInaccessible\n ? { skippedInaccessible: result.summary.skippedInaccessible }\n : {}),\n ...(result.summary.skippedTooLarge\n ? { skippedTooLarge: result.summary.skippedTooLarge }\n : {}),\n },\n truncated: result.summary.truncated,\n };\n },\n externalize: resourceStore\n ? (matches, metadata) =>\n putJsonResource(\n resourceStore,\n `'${args.searchPattern}' matches`,\n searchContentOutput(matches, metadata, undefined, undefined),\n )\n : undefined,\n });\n\n return {\n structured: searchContentOutput(\n paged.page,\n paged.metadata,\n paged.nextCursor,\n paged.resource?.entry.uri,\n ),\n offset: paged.offset,\n total: paged.metadata.totalMatches,\n ...(paged.resource ? { link: paged.resource.link } : {}),\n };\n}\n\nexport const SEARCH_CONTENT = defineTool({\n name: 'search_text',\n title: 'Search Content',\n description:\n 'Search file contents by text or regex (grep-style). Returns matching lines with file path, ' +\n '1-indexed line number and 0-indexed column offset. ' +\n 'Scope to specific file types with pattern (e.g. **/*.ts). ' +\n 'Set includeHidden=true to include dotfiles. Use find_files to search by filename instead.',\n input: GrepInputSchema,\n output: GrepOutputSchema,\n annotations: {\n readOnlyHint: true,\n idempotentHint: true,\n destructiveHint: false,\n openWorldHint: false,\n },\n timeoutMs: DEFAULT_SEARCH_TIMEOUT_MS,\n defaultErrorCode: ErrorCode.UNKNOWN,\n progress: (args) => ({\n label: 'Search',\n subject: truncateProgressPattern(args.searchPattern),\n }),\n progressDone: (_args, result) => ({\n detail: buildSearchMatchDetail(result.totalMatches ?? 0, result.filesMatched ?? 0),\n }),\n accessPaths: (args) => (args.path ? [args.path] : []),\n run: async (args, ctx) => {\n const { structured, offset, total, link } = await handleSearchContent(args, ctx);\n const rows = structured.matches.map((m) => `${m.file}:${String(m.line)}: ${m.content}`);\n const body = rows.length > 0 ? rows.join('\\n') : `No matches for '${args.searchPattern}'`;\n const text =\n body +\n pageTrailer({\n offset,\n shown: rows.length,\n total,\n noun: 'matches',\n tool: 'search_text',\n nextCursor: structured.nextCursor,\n stoppedReason: structured.stoppedReason,\n });\n if (link) {\n return { structured, text, resources: [link] };\n }\n return { structured, text };\n },\n});\n"]}
1
+ {"version":3,"file":"search-content.js","sourceRoot":"","sources":["../../src/tools/search-content.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE9C,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AACnF,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,OAAO,EACP,aAAa,EACb,gBAAgB,EAChB,SAAS,EACT,YAAY,EACZ,WAAW,EACX,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EACL,8BAA8B,EAC9B,yBAAyB,EACzB,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,UAAU,EAAgB,MAAM,aAAa,CAAC;AAEvD;;;;;;GAMG;AACH,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,KAAK,SAAS,EAAE,CAAC;IACvD,MAAM,CAAC,IAAI,CACT,2IAA2I,CAC5I,CAAC;AACJ,CAAC;AAkBD,MAAM,eAAe,GAAG,CAAC,CAAC,YAAY,CAAC;IACrC,IAAI,EAAE,YAAY,CAAC,QAAQ,CACzB,+LAA+L,CAChM;IACD,OAAO,EAAE,eAAe,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAC1C,wFAAwF,CACzF;IACD,aAAa,EAAE,CAAC;SACb,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,KAAK,CAAC;SACV,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;QAC9B,OAAO,EAAE,kDAAkD;KAC5D,CAAC;SACD,QAAQ,CACP,+LAA+L,CAChM;SACA,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,oBAAoB,EAAE,cAAc,CAAC,EAAE,CAAC;IACrE,OAAO,EAAE,mBAAmB,CAAC,8DAA8D,CAAC;IAC5F,aAAa,EAAE,kBAAkB,EAAE;IACnC,cAAc,EAAE,mBAAmB,EAAE;IACrC,aAAa,EAAE,mBAAmB,CAAC,4DAA4D,CAAC;IAChG,UAAU,EAAE,CAAC;SACV,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,kBAAkB,CAAC;SACvB,QAAQ,EAAE;SACV,OAAO,CAAC,8BAA8B,CAAC;SACvC,QAAQ,CAAC,qDAAqD,CAAC;IAClE,QAAQ,EAAE,aAAa,EAAE;IACzB,MAAM,EAAE,YAAY;CACrB,CAAC,CAAC;AAEH,MAAM,gBAAgB,GAAG,CAAC,CAAC,YAAY,CAAC;IACtC,OAAO,EAAE,CAAC;SACP,KAAK,CACJ,CAAC,CAAC,YAAY,CAAC;QACb,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uCAAuC,CAAC;QAClE,IAAI,EAAE,WAAW,CAAC,QAAQ,CAAC,oCAAoC,CAAC;QAChE,MAAM,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4CAA4C,CAAC;QACnF,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gCAAgC,CAAC;QAC9D,UAAU,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4CAA4C,CAAC;KACxF,CAAC,CACH;SACA,QAAQ,CAAC,2DAA2D,CAAC;IACxE,YAAY,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC,QAAQ,CACzC,6HAA6H,CAC9H;IACD,YAAY,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+CAA+C,CAAC;IAC5F,YAAY,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,gCAAgC,CAAC;IAC7E,mBAAmB,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAChD,yDAAyD,CAC1D;IACD,eAAe,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAC5C,qIAAqI,CACtI;IACD,SAAS,EAAE,CAAC;SACT,OAAO,EAAE;SACT,QAAQ,EAAE;SACV,QAAQ,CACP,kKAAkK,CACnK;IACH,aAAa,EAAE,yBAAyB,CAAC,QAAQ,CAC/C,6JAA6J,CAC9J;IACD,WAAW,EAAE,CAAC;SACX,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,0JAA0J,CAC3J;IACH,UAAU,EAAE,gBAAgB;CAC7B,CAAC,CAAC;AAEH,SAAS,sBAAsB,CAAC,YAAoB,EAAE,YAAoB;IACxE,MAAM,WAAW,GAAG,WAAW,CAAC,YAAY,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IAClE,IAAI,YAAY,IAAI,CAAC;QAAE,OAAO,WAAW,CAAC;IAC1C,OAAO,GAAG,WAAW,MAAM,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;AAC1E,CAAC;AAED,SAAS,mBAAmB,CAC1B,OAAsC,EACtC,QAAmC,EACnC,UAA8B,EAC9B,WAA+B;IAE/B,OAAO;QACL,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC;QACrB,YAAY,EAAE,QAAQ,CAAC,YAAY;QACnC,YAAY,EAAE,QAAQ,CAAC,YAAY;QACnC,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzE,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClD,GAAG,CAAC,QAAQ,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1F,GAAG,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE,mBAAmB,EAAE,QAAQ,CAAC,mBAAmB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9F,GAAG,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,QAAQ,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClF,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrD,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACpD,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAAC,MAAyB;IACpD,MAAM,cAAc,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEjD,MAAM,eAAe,GAAG,CAAC,IAAY,EAAU,EAAE;QAC/C,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,MAAM,CAAC;QAExC,MAAM,GAAG,GAAG,eAAe,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACnD,cAAc,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC9B,OAAO,GAAG,CAAC;IACb,CAAC,CAAC;IAEF,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAsB,EAAE,CAAC,CAAC;QAClE,IAAI,EAAE,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC;QACjC,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,UAAU,EAAE,KAAK,CAAC,UAAU;KAC7B,CAAC,CAAC,CAAC;IAEJ,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;IACzE,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,yBAAyB,CAAC,IAAiB,EAAE,MAAoB;IACxE,OAAO;QACL,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,eAAe,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,wBAAwB;QACpE,WAAW,EAAE,IAAI,CAAC,OAAO,IAAI,MAAM;QACnC,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,gBAAgB,EAAE,CAAC,IAAI,CAAC,cAAc;QACtC,GAAG,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9B,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,KAAK,UAAU,kBAAkB,CAC/B,IAAiB,EACjB,GAAY;IAEZ,MAAM,SAAS,GAAG,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChE,uEAAuE;IACvE,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC;IACxE,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;IACnC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;QACpB,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACzB,MAAM,IAAI,OAAO,CAAC,SAAS,CAAC,aAAa,EAAE,iBAAiB,EAAE,SAAS,CAAC,CAAC;QAC3E,CAAC;QACD,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACtC,CAAC;IACD,OAAO;QACL,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC;QAC3B,2EAA2E;QAC3E,mEAAmE;QACnE,gDAAgD;QAChD,IAAI,EAAE,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE;KAC1F,CAAC;AACJ,CAAC;AAED,SAAS,qBAAqB,CAAC,IAAiB,EAAE,aAAqB;IACrE,OAAO,IAAI,CAAC,SAAS,CAAC;QACpB,MAAM,EAAE,aAAa;QACrB,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,cAAc,EAAE,IAAI,CAAC,cAAc;QACnC,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,QAAQ,EAAE,IAAI,CAAC,QAAQ;KACxB,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,mBAAmB,CAChC,IAAiB,EACjB,GAAY;IAOZ,MAAM,aAAa,GAAG,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpE,MAAM,QAAQ,GAAG,qBAAqB,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;IAC5D,MAAM,EAAE,aAAa,EAAE,GAAG,GAAG,CAAC;IAE9B,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAoE;QAC9F,KAAK,EAAE,GAAG,CAAC,SAAS;QACpB,QAAQ;QACR,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,QAAQ,EAAE,IAAI,CAAC,UAAU;QACzB,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,kBAAkB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAEvE,MAAM,MAAM,GAAG,MAAM,aAAa,CAChC,QAAQ,EACR,MAAM,CAAC,aAAa,EACpB,yBAAyB,CAAC,EAAE,GAAG,MAAM,EAAE,UAAU,EAAE,kBAAkB,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,EACpF,GAAG,CAAC,EAAE,CAAC,SAAS,CACjB,CAAC;YAEF,MAAM,KAAK,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;YAC1C,OAAO;gBACL,KAAK;gBACL,QAAQ,EAAE;oBACR,YAAY,EAAE,MAAM,CAAC,OAAO,CAAC,aAAa;oBAC1C,YAAY,EAAE,MAAM,CAAC,OAAO,CAAC,YAAY;oBACzC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACrF,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,SAAS;oBACnC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,aAAa,KAAK,SAAS;wBAC5C,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,CAAC,OAAO,CAAC,aAAa,EAAE;wBACjD,CAAC,CAAC,EAAE,CAAC;oBACP,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,mBAAmB;wBACpC,CAAC,CAAC,EAAE,mBAAmB,EAAE,MAAM,CAAC,OAAO,CAAC,mBAAmB,EAAE;wBAC7D,CAAC,CAAC,EAAE,CAAC;oBACP,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,eAAe;wBAChC,CAAC,CAAC,EAAE,eAAe,EAAE,MAAM,CAAC,OAAO,CAAC,eAAe,EAAE;wBACrD,CAAC,CAAC,EAAE,CAAC;iBACR;gBACD,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,SAAS;aACpC,CAAC;QACJ,CAAC;QACD,WAAW,EAAE,aAAa;YACxB,CAAC,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE,CACpB,eAAe,CACb,aAAa,EACb,IAAI,IAAI,CAAC,aAAa,WAAW,EACjC,mBAAmB,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAC,CAC7D;YACL,CAAC,CAAC,SAAS;KACd,CAAC,CAAC;IAEH,OAAO;QACL,UAAU,EAAE,mBAAmB,CAC7B,KAAK,CAAC,IAAI,EACV,KAAK,CAAC,QAAQ,EACd,KAAK,CAAC,UAAU,EAChB,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,GAAG,CAC1B;QACD,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,YAAY;QAClC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACzD,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,UAAU,CAAC;IACvC,IAAI,EAAE,aAAa;IACnB,KAAK,EAAE,gBAAgB;IACvB,WAAW,EACT,6FAA6F;QAC7F,qDAAqD;QACrD,4DAA4D;QAC5D,2FAA2F;IAC7F,KAAK,EAAE,eAAe;IACtB,MAAM,EAAE,gBAAgB;IACxB,WAAW,EAAE;QACX,YAAY,EAAE,IAAI;QAClB,cAAc,EAAE,IAAI;QACpB,eAAe,EAAE,KAAK;QACtB,aAAa,EAAE,KAAK;KACrB;IACD,SAAS,EAAE,yBAAyB;IACpC,gBAAgB,EAAE,SAAS,CAAC,OAAO;IACnC,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACnB,KAAK,EAAE,QAAQ;QACf,OAAO,EAAE,uBAAuB,CAAC,IAAI,CAAC,aAAa,CAAC;KACrD,CAAC;IACF,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;QAChC,MAAM,EAAE,sBAAsB,CAAC,MAAM,CAAC,YAAY,IAAI,CAAC,EAAE,MAAM,CAAC,YAAY,IAAI,CAAC,CAAC;KACnF,CAAC;IACF,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACrD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;QACvB,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,mBAAmB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACjF,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QACxF,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,mBAAmB,IAAI,CAAC,aAAa,GAAG,CAAC;QAC1F,MAAM,IAAI,GACR,IAAI;YACJ,WAAW,CAAC;gBACV,MAAM;gBACN,KAAK,EAAE,IAAI,CAAC,MAAM;gBAClB,KAAK;gBACL,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,aAAa;gBACnB,UAAU,EAAE,UAAU,CAAC,UAAU;gBACjC,aAAa,EAAE,UAAU,CAAC,aAAa;aACxC,CAAC,CAAC;QACL,IAAI,IAAI,EAAE,CAAC;YACT,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACjD,CAAC;QACD,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;IAC9B,CAAC;CACF,CAAC,CAAC","sourcesContent":["import { stat } from 'node:fs/promises';\nimport { basename, dirname } from 'node:path';\n\nimport * as z from 'zod/v4';\n\nimport { SearchStoppedReasonSchema } from '../core/concurrency.js';\nimport { paginate } from '../core/cursor.js';\nimport { ErrorCode, FsError } from '../core/errors.js';\nimport { formatCount, pageTrailer, truncateProgressPattern } from '../core/fmt.js';\nimport { DEFAULT_EXCLUDE_PATTERNS } from '../core/glob.js';\nimport { Logger } from '../core/observability.js';\nimport { toPosixRelative } from '../core/path.js';\nimport {\n CursorSchema,\n defaultFalseBoolean,\n includeHiddenField,\n includeIgnoredField,\n isBlank,\n maxDepthField,\n NextCursorSchema,\n NonNegInt,\n OptionalPath,\n PositiveInt,\n SafeGlobPattern,\n} from '../core/schema.js';\nimport type { SearchContentOptions } from '../core/search.js';\nimport { searchContent } from '../core/search.js';\nimport type { JsonResourceResult } from '../core/store.js';\nimport { putJsonResource } from '../core/store.js';\nimport {\n DEFAULT_SEARCH_CONTENT_RESULTS,\n DEFAULT_SEARCH_TIMEOUT_MS,\n MAX_SEARCH_RESULTS,\n} from '../core/util.js';\nimport { defineTool, type ToolCtx } from './define.js';\n\n/**\n * `FS_MAX_INLINE_MATCHES` used to cap how many matches a page showed inline\n * and, past it, push the rest into the resource store. `maxResults` is the one\n * page size now, and the full list is externalized whenever a response is\n * incomplete, so the variable does nothing. It is still read so an operator who\n * set it hears why it stopped mattering; the read goes at the next major.\n */\nif (process.env['FS_MAX_INLINE_MATCHES'] !== undefined) {\n Logger.warn(\n 'FS_MAX_INLINE_MATCHES is deprecated and ignored: maxResults sets the search_text page size. It will be removed in the next major release.',\n );\n}\n\n// Type Definitions\ntype SearchInput = z.infer<typeof GrepInputSchema>;\ntype SearchOutput = z.infer<typeof GrepOutputSchema>;\ntype SearchMatchPayload = NonNullable<SearchOutput['matches']>[number];\ntype SearchResultValue = Awaited<ReturnType<typeof searchContent>>;\n\ninterface SearchContentPageMetadata {\n readonly totalMatches: number;\n readonly filesScanned: number;\n readonly filesMatched?: number;\n readonly truncated: boolean;\n readonly stoppedReason?: SearchOutput['stoppedReason'];\n readonly skippedInaccessible?: number;\n readonly skippedTooLarge?: number;\n}\n\nconst GrepInputSchema = z.strictObject({\n path: OptionalPath.describe(\n 'File to search, or directory to search under (default: the whole first allowed root). Naming a file searches that file alone: pattern is ignored and hidden/ignored filtering does not apply.',\n ),\n pattern: SafeGlobPattern.optional().describe(\n 'Glob to restrict search 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 in file contents. When isRegex=true, uses RE2 syntax (no lookahead, lookbehind, or backreferences). Cannot be empty or whitespace-only.',\n )\n .meta({ examples: ['TODO', 'function\\\\s+(\\\\w+)', 'import.*from'] }),\n isRegex: defaultFalseBoolean('Treat searchPattern as a regex (default: literal text match)'),\n includeHidden: includeHiddenField(),\n includeIgnored: includeIgnoredField(),\n caseSensitive: defaultFalseBoolean('Enable case-sensitive matching (default: case-insensitive)'),\n maxResults: z\n .uint32()\n .min(1)\n .max(MAX_SEARCH_RESULTS)\n .optional()\n .default(DEFAULT_SEARCH_CONTENT_RESULTS)\n .describe('Maximum number of matching lines to return per page'),\n maxDepth: maxDepthField(),\n cursor: CursorSchema,\n});\n\nconst GrepOutputSchema = z.strictObject({\n matches: z\n .array(\n z.strictObject({\n file: z.string().describe('File path relative to the search root'),\n line: PositiveInt.describe('1-indexed line number of the match'),\n column: NonNegInt.optional().describe('0-indexed column offset of the match start'),\n content: z.string().describe('Full text of the matching line'),\n matchCount: NonNegInt.optional().describe('Number of pattern occurrences on this line'),\n }),\n )\n .describe('Flat list of matches sorted by file path then line number'),\n totalMatches: NonNegInt.optional().describe(\n \"Total matching lines, one per entry in matches (not per occurrence); see that entry's matchCount for occurrences on a line.\",\n ),\n filesMatched: NonNegInt.optional().describe('Number of files containing at least one match'),\n filesScanned: NonNegInt.optional().describe('Total number of files examined'),\n skippedInaccessible: NonNegInt.optional().describe(\n 'Files skipped unread due to permission or access errors',\n ),\n skippedTooLarge: NonNegInt.optional().describe(\n 'Files skipped unread because they exceed the text-file size limit; raise the limit or narrow pattern if a match was expected in one',\n ),\n truncated: z\n .boolean()\n .optional()\n .describe(\n 'True when the search engine cut the match list — the hard result cap or the time limit. Paging is not truncation: a set that spans pages has nextCursor instead.',\n ),\n stoppedReason: SearchStoppedReasonSchema.describe(\n 'Why the search ended early: maxResults = result cap reached, timeout = time limit hit or the request was cancelled. Absent when the scan ran to completion.',\n ),\n resourceUri: z\n .string()\n .optional()\n .describe(\n 'URI to the full match list in the resource store; first page only, whenever the response is incomplete — more pages follow, or the engine cut the search',\n ),\n nextCursor: NextCursorSchema,\n});\n\nfunction buildSearchMatchDetail(totalMatches: number, filesMatched: number): string {\n const matchDetail = formatCount(totalMatches, 'match', 'matches');\n if (filesMatched <= 0) return matchDetail;\n return `${matchDetail} · ${formatCount(filesMatched, 'file', 'files')}`;\n}\n\nfunction searchContentOutput(\n matches: readonly SearchMatchPayload[],\n metadata: SearchContentPageMetadata,\n nextCursor: string | undefined,\n resourceUri: string | undefined,\n): SearchOutput {\n return {\n matches: [...matches],\n totalMatches: metadata.totalMatches,\n filesScanned: metadata.filesScanned,\n ...(metadata.filesMatched ? { filesMatched: metadata.filesMatched } : {}),\n ...(metadata.truncated ? { truncated: true } : {}),\n ...(metadata.stoppedReason !== undefined ? { stoppedReason: metadata.stoppedReason } : {}),\n ...(metadata.skippedInaccessible ? { skippedInaccessible: metadata.skippedInaccessible } : {}),\n ...(metadata.skippedTooLarge ? { skippedTooLarge: metadata.skippedTooLarge } : {}),\n ...(resourceUri !== undefined ? { resourceUri } : {}),\n ...(nextCursor !== undefined ? { nextCursor } : {}),\n };\n}\n\nfunction buildSortedPayloads(result: SearchResultValue): SearchMatchPayload[] {\n const relativeByFile = new Map<string, string>();\n\n const getRelativeFile = (file: string): string => {\n const cached = relativeByFile.get(file);\n if (cached !== undefined) return cached;\n\n const rel = toPosixRelative(result.basePath, file);\n relativeByFile.set(file, rel);\n return rel;\n };\n\n const payloads = result.matches.map((match): SearchMatchPayload => ({\n file: getRelativeFile(match.file),\n line: match.line,\n column: match.column,\n content: match.content,\n matchCount: match.matchCount,\n }));\n\n payloads.sort((l, r) => l.file.localeCompare(r.file) || l.line - r.line);\n return payloads;\n}\n\nfunction buildSearchContentOptions(args: SearchInput, signal?: AbortSignal): SearchContentOptions {\n return {\n includeHidden: args.includeHidden,\n excludePatterns: args.includeIgnored ? [] : DEFAULT_EXCLUDE_PATTERNS,\n filePattern: args.pattern ?? '**/*',\n caseSensitive: args.caseSensitive,\n isRegex: args.isRegex,\n maxResults: args.maxResults,\n respectGitignore: !args.includeIgnored,\n ...(args.maxDepth !== undefined ? { maxDepth: args.maxDepth } : {}),\n ...(signal ? { signal } : {}),\n };\n}\n\n/**\n * `path` is documented as \"file to search, or directory to search under\", but\n * the scan itself only walks directories. A file path is therefore rewritten\n * into the scan it means: its parent as the base, its own name as the glob.\n * Naming a file is an explicit request for that file, so hidden/ignored\n * filtering is lifted for it — otherwise `search_text` on a path the caller can\n * see returned nothing.\n */\nasync function resolveSearchScope(\n args: SearchInput,\n ctx: ToolCtx,\n): Promise<{ basePath: string; args: SearchInput }> {\n const requested = ctx.fs.pathGuard.resolvePathOrRoot(args.path);\n // One resolution, one stat: validateExistingDirectory would redo both.\n const resolved = await ctx.fs.pathGuard.validateExistingPath(requested);\n const stats = await stat(resolved);\n if (!stats.isFile()) {\n if (!stats.isDirectory()) {\n throw new FsError(ErrorCode.NOT_DIRECTORY, 'Not a directory', requested);\n }\n return { basePath: resolved, args };\n }\n return {\n basePath: dirname(resolved),\n // ponytail: the name goes through as a glob, so a file whose name contains\n // glob metacharacters (`[id].ts`) matches as a pattern rather than\n // literally. Escape it here if that ever bites.\n args: { ...args, pattern: basename(resolved), includeHidden: true, includeIgnored: true },\n };\n}\n\nfunction searchContentQueryKey(args: SearchInput, requestedPath: string): string {\n return JSON.stringify({\n method: 'search_text',\n path: requestedPath,\n pattern: args.pattern,\n searchPattern: args.searchPattern,\n isRegex: args.isRegex,\n includeHidden: args.includeHidden,\n includeIgnored: args.includeIgnored,\n caseSensitive: args.caseSensitive,\n maxDepth: args.maxDepth,\n });\n}\n\nasync function handleSearchContent(\n args: SearchInput,\n ctx: ToolCtx,\n): Promise<{\n structured: SearchOutput;\n offset: number;\n total: number;\n link?: ReturnType<typeof putJsonResource>['link'];\n}> {\n const requestedPath = ctx.fs.pathGuard.resolvePathOrRoot(args.path);\n const queryKey = searchContentQueryKey(args, requestedPath);\n const { resourceStore } = ctx;\n\n const paged = await paginate<SearchMatchPayload, SearchContentPageMetadata, JsonResourceResult>({\n store: ctx.pageStore,\n queryKey,\n cursor: args.cursor,\n pageSize: args.maxResults,\n produce: async () => {\n const { basePath, args: scoped } = await resolveSearchScope(args, ctx);\n\n const result = await searchContent(\n basePath,\n scoped.searchPattern,\n buildSearchContentOptions({ ...scoped, maxResults: MAX_SEARCH_RESULTS }, ctx.signal),\n ctx.fs.pathGuard,\n );\n\n const items = buildSortedPayloads(result);\n return {\n items,\n metadata: {\n totalMatches: result.summary.matchingLines,\n filesScanned: result.summary.filesScanned,\n ...(result.summary.filesMatched ? { filesMatched: result.summary.filesMatched } : {}),\n truncated: result.summary.truncated,\n ...(result.summary.stoppedReason !== undefined\n ? { stoppedReason: result.summary.stoppedReason }\n : {}),\n ...(result.summary.skippedInaccessible\n ? { skippedInaccessible: result.summary.skippedInaccessible }\n : {}),\n ...(result.summary.skippedTooLarge\n ? { skippedTooLarge: result.summary.skippedTooLarge }\n : {}),\n },\n truncated: result.summary.truncated,\n };\n },\n externalize: resourceStore\n ? (matches, metadata) =>\n putJsonResource(\n resourceStore,\n `'${args.searchPattern}' matches`,\n searchContentOutput(matches, metadata, undefined, undefined),\n )\n : undefined,\n });\n\n return {\n structured: searchContentOutput(\n paged.page,\n paged.metadata,\n paged.nextCursor,\n paged.resource?.entry.uri,\n ),\n offset: paged.offset,\n total: paged.metadata.totalMatches,\n ...(paged.resource ? { link: paged.resource.link } : {}),\n };\n}\n\nexport const SEARCH_CONTENT = defineTool({\n name: 'search_text',\n title: 'Search Content',\n description:\n 'Search file contents by text or regex (grep-style). Returns matching lines with file path, ' +\n '1-indexed line number and 0-indexed column offset. ' +\n 'Scope to specific file types with pattern (e.g. **/*.ts). ' +\n 'Set includeHidden=true to include dotfiles. Use find_files to search by filename instead.',\n input: GrepInputSchema,\n output: GrepOutputSchema,\n annotations: {\n readOnlyHint: true,\n idempotentHint: true,\n destructiveHint: false,\n openWorldHint: false,\n },\n timeoutMs: DEFAULT_SEARCH_TIMEOUT_MS,\n defaultErrorCode: ErrorCode.UNKNOWN,\n progress: (args) => ({\n label: 'Search',\n subject: truncateProgressPattern(args.searchPattern),\n }),\n progressDone: (_args, result) => ({\n detail: buildSearchMatchDetail(result.totalMatches ?? 0, result.filesMatched ?? 0),\n }),\n accessPaths: (args) => (args.path ? [args.path] : []),\n run: async (args, ctx) => {\n const { structured, offset, total, link } = await handleSearchContent(args, ctx);\n const rows = structured.matches.map((m) => `${m.file}:${String(m.line)}: ${m.content}`);\n const body = rows.length > 0 ? rows.join('\\n') : `No matches for '${args.searchPattern}'`;\n const text =\n body +\n pageTrailer({\n offset,\n shown: rows.length,\n total,\n noun: 'matches',\n tool: 'search_text',\n nextCursor: structured.nextCursor,\n stoppedReason: structured.stoppedReason,\n });\n if (link) {\n return { structured, text, resources: [link] };\n }\n return { structured, text };\n },\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"stat.d.ts","sourceRoot":"","sources":["../../src/tools/stat.ts"],"names":[],"mappings":"AA4LA,eAAO,MAAM,aAAa,mCAsExB,CAAC"}
1
+ {"version":3,"file":"stat.d.ts","sourceRoot":"","sources":["../../src/tools/stat.ts"],"names":[],"mappings":"AAkKA,eAAO,MAAM,aAAa,mCAiExB,CAAC"}
@@ -43,9 +43,9 @@ function buildFileInfoResult(name, requestedPath, isSymlink, stats, mimeType, sy
43
43
  type: isSymlink ? 'symlink' : resolveEntryType(stats),
44
44
  size: stats.size,
45
45
  ...(tokenEstimate !== undefined ? { tokenEstimate } : {}),
46
- created: stats.birthtime,
47
- modified: stats.mtime,
48
- accessed: stats.atime,
46
+ created: stats.birthtime.toISOString(),
47
+ modified: stats.mtime.toISOString(),
48
+ accessed: stats.atime.toISOString(),
49
49
  permissions: getPermissions(stats.mode),
50
50
  isHidden: isHidden(name),
51
51
  ...(mimeType !== undefined ? { mimeType } : {}),
@@ -64,10 +64,9 @@ async function getSymlinkTarget(pathToRead, fs, signal, log) {
64
64
  return undefined;
65
65
  }
66
66
  }
67
- async function getFileInfo(filePath, options) {
68
- const { signal, fs, log } = options;
69
- signal?.throwIfAborted();
70
- const { requestedPath, isSymlink, stats: followedStats, } = await fs.statDetailed(filePath, signal ? { signal } : undefined);
67
+ async function getFileInfo(filePath, { signal, fs, log }) {
68
+ signal.throwIfAborted();
69
+ const { requestedPath, isSymlink, stats: followedStats, } = await fs.statDetailed(filePath, { signal });
71
70
  const { base: name, ext: rawExt } = parse(requestedPath);
72
71
  const mimeType = rawExt.length > 0 ? detectMimeType(requestedPath).mimeType : undefined;
73
72
  // For a symlink, fsStat follows the link and reports the target's metadata.
@@ -76,7 +75,7 @@ async function getFileInfo(filePath, options) {
76
75
  let stats = followedStats;
77
76
  if (isSymlink) {
78
77
  try {
79
- ({ stats } = await fs.lstat(requestedPath, signal ? { signal } : undefined));
78
+ ({ stats } = await fs.lstat(requestedPath, { signal }));
80
79
  }
81
80
  catch (error) {
82
81
  // A cancelled request is not a "link metadata unavailable" fallback.
@@ -112,29 +111,6 @@ function classifyTypeCounts(results) {
112
111
  }
113
112
  return { fileCount, dirCount };
114
113
  }
115
- function toStatPerPathPayload(r) {
116
- if ('error' in r) {
117
- return { path: r.path, error: r.error };
118
- }
119
- const info = r.value;
120
- return {
121
- path: r.path,
122
- value: {
123
- name: info.name,
124
- path: info.path,
125
- type: info.type,
126
- size: info.size,
127
- ...(info.tokenEstimate !== undefined ? { tokenEstimate: info.tokenEstimate } : {}),
128
- created: info.created.toISOString(),
129
- modified: info.modified.toISOString(),
130
- accessed: info.accessed.toISOString(),
131
- permissions: info.permissions,
132
- isHidden: info.isHidden,
133
- ...(info.mimeType !== undefined ? { mimeType: info.mimeType } : {}),
134
- ...(info.symlinkTarget !== undefined ? { symlinkTarget: info.symlinkTarget } : {}),
135
- },
136
- };
137
- }
138
114
  export const GET_FILE_INFO = defineTool({
139
115
  name: 'stat',
140
116
  title: 'Get File Info',
@@ -160,13 +136,9 @@ export const GET_FILE_INFO = defineTool({
160
136
  accessPaths: singleOrBatchAccessPaths,
161
137
  run: async (args, ctx) => {
162
138
  const batchInput = args.path !== undefined ? { path: args.path } : { paths: args.paths ?? [] };
163
- const batch = await runOverPaths(batchInput, ctx, async ({ path }) => getFileInfo(path, {
164
- fs: ctx.fs,
165
- signal: ctx.signal,
166
- log: ctx.log,
167
- }), { defaultErrorCode: ErrorCode.NOT_FOUND });
139
+ const batch = await runOverPaths(batchInput, ctx, async ({ path }) => getFileInfo(path, ctx), { defaultErrorCode: ErrorCode.NOT_FOUND });
168
140
  const { fileCount, dirCount } = classifyTypeCounts(batch.results);
169
- const perPathPayload = batch.results.map(toStatPerPathPayload);
141
+ const perPathPayload = batch.results;
170
142
  let resourceUri;
171
143
  const resources = [];
172
144
  if (ctx.resourceStore && batch.summary.total > 1) {
@@ -1 +1 @@
1
- {"version":3,"file":"stat.js","sourceRoot":"","sources":["../../src/tools/stat.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContentBlock } from '@modelcontextprotocol/server';\n\nimport { parse } from 'node:path';\n\nimport * as z from 'zod/v4';\n\nimport { ErrorCode, rethrowIfAborted } from '../core/errors.js';\nimport type { FileInfo, GuardedFileSystem, Stats } from '../core/fs.js';\nimport { isHidden } from '../core/fs.js';\nimport { detectMimeType } from '../core/mime.js';\nimport { resolveEntryType } from '../core/primitives.js';\nimport {\n FileInfoSchema,\n NonNegInt,\n OperationSummarySchema,\n PerFileErrorSchema,\n singleOrBatchAccessPaths,\n singleOrBatchPathsInput,\n} from '../core/schema.js';\nimport { putJsonResource } from '../core/store.js';\nimport { DEFAULT_SEARCH_TIMEOUT_MS } 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 StatInputSchema = singleOrBatchPathsInput({});\n\nconst StatPerPathSchema = z.strictObject({\n path: z.string().describe('Requested path'),\n value: FileInfoSchema.optional().describe('File metadata; present on success'),\n error: PerFileErrorSchema.optional().describe('Error details; present on failure'),\n});\n\nconst StatOutputSchema = z.strictObject({\n results: z\n .array(StatPerPathSchema)\n .describe('Per-path metadata results ordered to match the input paths'),\n summary: OperationSummarySchema,\n fileCount: NonNegInt.optional().describe('Number of regular files in the results'),\n dirCount: NonNegInt.optional().describe('Number of directories in the results'),\n resourceUri: z\n .string()\n .optional()\n .describe(\n 'URI to aggregated stats.json in the resource store (present when resource store is available)',\n ),\n});\n\nfunction getPermissions(mode: number): string {\n let out = '';\n for (const shift of [6, 3, 0]) {\n const bits = (mode >> shift) & 0b111;\n out += (bits & 0b100 ? 'r' : '-') + (bits & 0b010 ? 'w' : '-') + (bits & 0b001 ? 'x' : '-');\n }\n return out;\n}\n\nfunction buildFileInfoResult(\n name: string,\n requestedPath: string,\n isSymlink: boolean,\n stats: Stats,\n mimeType: string | undefined,\n symlinkTarget: string | undefined,\n): FileInfo {\n const tokenEstimate = stats.isFile() ? Math.ceil(stats.size / 4) : undefined;\n return {\n name,\n path: requestedPath,\n type: isSymlink ? 'symlink' : resolveEntryType(stats),\n size: stats.size,\n ...(tokenEstimate !== undefined ? { tokenEstimate } : {}),\n created: stats.birthtime,\n modified: stats.mtime,\n accessed: stats.atime,\n permissions: getPermissions(stats.mode),\n isHidden: isHidden(name),\n ...(mimeType !== undefined ? { mimeType } : {}),\n ...(symlinkTarget !== undefined ? { symlinkTarget } : {}),\n };\n}\n\nasync function getSymlinkTarget(\n pathToRead: string,\n fs: GuardedFileSystem,\n signal?: AbortSignal,\n log?: ToolCtx['log'],\n): Promise<string | undefined> {\n signal?.throwIfAborted();\n try {\n const { linkString } = await fs.readlink(pathToRead);\n return linkString;\n } catch (error) {\n rethrowIfAborted(error);\n log?.('warning', `stat: readlink failed for \"${pathToRead}\": ${String(error)}`, 'stat');\n return undefined;\n }\n}\n\ninterface FileInfoOptions {\n signal?: AbortSignal | undefined;\n fs: GuardedFileSystem;\n log?: ToolCtx['log'] | undefined;\n}\n\nasync function getFileInfo(filePath: string, options: FileInfoOptions): Promise<FileInfo> {\n const { signal, fs, log } = options;\n signal?.throwIfAborted();\n\n const {\n requestedPath,\n isSymlink,\n stats: followedStats,\n } = await fs.statDetailed(filePath, signal ? { signal } : undefined);\n\n const { base: name, ext: rawExt } = parse(requestedPath);\n const mimeType = rawExt.length > 0 ? detectMimeType(requestedPath).mimeType : undefined;\n\n // For a symlink, fsStat follows the link and reports the target's metadata.\n // Report the link's own metadata instead so size/permissions/timestamps\n // describe the link the user asked about, not its target.\n let stats = followedStats;\n if (isSymlink) {\n try {\n ({ stats } = await fs.lstat(requestedPath, signal ? { signal } : undefined));\n } catch (error) {\n // A cancelled request is not a \"link metadata unavailable\" fallback.\n rethrowIfAborted(error);\n // Guarded lstat can be refused where raw lstat succeeded (e.g. an allowed\n // root that is itself a symlink, whose parent sits outside the roots).\n // Falling back to the followed stats degrades the report to the target's\n // metadata, so leave a trace instead of degrading silently.\n log?.('warning', `stat: lstat failed for \"${requestedPath}\": ${String(error)}`, 'stat');\n stats = followedStats;\n }\n }\n\n // isSymlink above is true whenever ANY ancestor is a symlink, because it\n // compares the requested path with its fully-resolved real path. Only the\n // entry's own lstat says whether THIS path is a link, so a regular file under\n // a symlinked parent is reported as a file and no readlink is attempted.\n const isOwnSymlink = stats.isSymbolicLink();\n const symlinkTarget = isOwnSymlink\n ? await getSymlinkTarget(requestedPath, fs, signal, log)\n : undefined;\n\n return buildFileInfoResult(name, requestedPath, isOwnSymlink, stats, mimeType, symlinkTarget);\n}\n\nfunction classifyTypeCounts(results: readonly PerPathResult<FileInfo>[]): {\n fileCount: number;\n dirCount: number;\n} {\n let fileCount = 0;\n let dirCount = 0;\n for (const result of results) {\n if ('error' in result) continue;\n if (result.value.type === 'directory') dirCount += 1;\n else fileCount += 1;\n }\n return { fileCount, dirCount };\n}\n\nfunction toStatPerPathPayload(r: PerPathResult<FileInfo>): z.infer<typeof StatPerPathSchema> {\n if ('error' in r) {\n return { path: r.path, error: r.error };\n }\n const info = r.value;\n return {\n path: r.path,\n value: {\n name: info.name,\n path: info.path,\n type: info.type,\n size: info.size,\n ...(info.tokenEstimate !== undefined ? { tokenEstimate: info.tokenEstimate } : {}),\n created: info.created.toISOString(),\n modified: info.modified.toISOString(),\n accessed: info.accessed.toISOString(),\n permissions: info.permissions,\n isHidden: info.isHidden,\n ...(info.mimeType !== undefined ? { mimeType: info.mimeType } : {}),\n ...(info.symlinkTarget !== undefined ? { symlinkTarget: info.symlinkTarget } : {}),\n },\n };\n}\n\nexport const GET_FILE_INFO = defineTool({\n name: 'stat',\n title: 'Get File Info',\n description:\n 'Get metadata for one or more files or directories: size, type, permissions, MIME type, timestamps, and tokenEstimate. ' +\n 'Use tokenEstimate to pre-screen read cost before calling read. ' +\n 'Single path: pass path. Batch mode: pass paths[].',\n input: StatInputSchema,\n output: StatOutputSchema,\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_FOUND,\n progress: (args) => {\n if (args.paths !== undefined) {\n return { label: 'Stat', subject: `${String(args.paths.length)} paths` };\n }\n return { label: 'Stat', subject: args.path ?? '' };\n },\n accessPaths: singleOrBatchAccessPaths,\n run: async (args, ctx) => {\n const batchInput = args.path !== undefined ? { path: args.path } : { paths: args.paths ?? [] };\n\n const batch = await runOverPaths<undefined, FileInfo>(\n batchInput,\n ctx,\n async ({ path }) =>\n getFileInfo(path, {\n fs: ctx.fs,\n signal: ctx.signal,\n log: ctx.log,\n }),\n { defaultErrorCode: ErrorCode.NOT_FOUND },\n );\n\n const { fileCount, dirCount } = classifyTypeCounts(batch.results);\n const perPathPayload = batch.results.map(toStatPerPathPayload);\n\n let resourceUri: string | undefined;\n const resources: ContentBlock[] = [];\n if (ctx.resourceStore && batch.summary.total > 1) {\n const { entry, link } = putJsonResource(\n ctx.resourceStore,\n `${String(batch.summary.total)} paths`,\n perPathPayload,\n );\n resourceUri = entry.uri;\n resources.push(link);\n }\n\n // No `text` on purpose. The one-liner this used to build (`AGENTS.md: file,\n // 751 B`) dropped tokenEstimate, modified, mimeType and isHidden — the very\n // fields a caller asks `stat` for. Supplying no text makes this a data tool,\n // so `define.ts` renders the JSON and keeps it in `structuredContent`.\n return {\n structured: {\n results: perPathPayload,\n summary: batch.summary,\n fileCount,\n dirCount,\n ...(resourceUri ? { resourceUri } : {}),\n },\n isError: isTotalFailure(batch.summary),\n ...(resources.length > 0 ? { resources } : {}),\n };\n },\n});\n"]}
1
+ {"version":3,"file":"stat.js","sourceRoot":"","sources":["../../src/tools/stat.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContentBlock } from '@modelcontextprotocol/server';\n\nimport { parse } from 'node:path';\n\nimport * as z from 'zod/v4';\n\nimport { ErrorCode, rethrowIfAborted } from '../core/errors.js';\nimport type { GuardedFileSystem, Stats } from '../core/fs.js';\nimport { isHidden } from '../core/fs.js';\nimport { detectMimeType } from '../core/mime.js';\nimport { resolveEntryType } from '../core/primitives.js';\nimport {\n FileInfoSchema,\n NonNegInt,\n OperationSummarySchema,\n PerFileErrorSchema,\n singleOrBatchAccessPaths,\n singleOrBatchPathsInput,\n} from '../core/schema.js';\nimport { putJsonResource } from '../core/store.js';\nimport { DEFAULT_SEARCH_TIMEOUT_MS } 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\ntype FileInfo = z.infer<typeof FileInfoSchema>;\n\nconst StatInputSchema = singleOrBatchPathsInput({});\n\nconst StatPerPathSchema = z.strictObject({\n path: z.string().describe('Requested path'),\n value: FileInfoSchema.optional().describe('File metadata; present on success'),\n error: PerFileErrorSchema.optional().describe('Error details; present on failure'),\n});\n\nconst StatOutputSchema = z.strictObject({\n results: z\n .array(StatPerPathSchema)\n .describe('Per-path metadata results ordered to match the input paths'),\n summary: OperationSummarySchema,\n fileCount: NonNegInt.optional().describe('Number of regular files in the results'),\n dirCount: NonNegInt.optional().describe('Number of directories in the results'),\n resourceUri: z\n .string()\n .optional()\n .describe(\n 'URI to aggregated stats.json in the resource store (present when resource store is available)',\n ),\n});\n\nfunction getPermissions(mode: number): string {\n let out = '';\n for (const shift of [6, 3, 0]) {\n const bits = (mode >> shift) & 0b111;\n out += (bits & 0b100 ? 'r' : '-') + (bits & 0b010 ? 'w' : '-') + (bits & 0b001 ? 'x' : '-');\n }\n return out;\n}\n\nfunction buildFileInfoResult(\n name: string,\n requestedPath: string,\n isSymlink: boolean,\n stats: Stats,\n mimeType: string | undefined,\n symlinkTarget: string | undefined,\n): FileInfo {\n const tokenEstimate = stats.isFile() ? Math.ceil(stats.size / 4) : undefined;\n return {\n name,\n path: requestedPath,\n type: isSymlink ? 'symlink' : resolveEntryType(stats),\n size: stats.size,\n ...(tokenEstimate !== undefined ? { tokenEstimate } : {}),\n created: stats.birthtime.toISOString(),\n modified: stats.mtime.toISOString(),\n accessed: stats.atime.toISOString(),\n permissions: getPermissions(stats.mode),\n isHidden: isHidden(name),\n ...(mimeType !== undefined ? { mimeType } : {}),\n ...(symlinkTarget !== undefined ? { symlinkTarget } : {}),\n };\n}\n\nasync function getSymlinkTarget(\n pathToRead: string,\n fs: GuardedFileSystem,\n signal?: AbortSignal,\n log?: ToolCtx['log'],\n): Promise<string | undefined> {\n signal?.throwIfAborted();\n try {\n const { linkString } = await fs.readlink(pathToRead);\n return linkString;\n } catch (error) {\n rethrowIfAborted(error);\n log?.('warning', `stat: readlink failed for \"${pathToRead}\": ${String(error)}`, 'stat');\n return undefined;\n }\n}\n\nasync function getFileInfo(\n filePath: string,\n { signal, fs, log }: Pick<ToolCtx, 'fs' | 'signal' | 'log'>,\n): Promise<FileInfo> {\n signal.throwIfAborted();\n\n const {\n requestedPath,\n isSymlink,\n stats: followedStats,\n } = await fs.statDetailed(filePath, { signal });\n\n const { base: name, ext: rawExt } = parse(requestedPath);\n const mimeType = rawExt.length > 0 ? detectMimeType(requestedPath).mimeType : undefined;\n\n // For a symlink, fsStat follows the link and reports the target's metadata.\n // Report the link's own metadata instead so size/permissions/timestamps\n // describe the link the user asked about, not its target.\n let stats = followedStats;\n if (isSymlink) {\n try {\n ({ stats } = await fs.lstat(requestedPath, { signal }));\n } catch (error) {\n // A cancelled request is not a \"link metadata unavailable\" fallback.\n rethrowIfAborted(error);\n // Guarded lstat can be refused where raw lstat succeeded (e.g. an allowed\n // root that is itself a symlink, whose parent sits outside the roots).\n // Falling back to the followed stats degrades the report to the target's\n // metadata, so leave a trace instead of degrading silently.\n log?.('warning', `stat: lstat failed for \"${requestedPath}\": ${String(error)}`, 'stat');\n stats = followedStats;\n }\n }\n\n // isSymlink above is true whenever ANY ancestor is a symlink, because it\n // compares the requested path with its fully-resolved real path. Only the\n // entry's own lstat says whether THIS path is a link, so a regular file under\n // a symlinked parent is reported as a file and no readlink is attempted.\n const isOwnSymlink = stats.isSymbolicLink();\n const symlinkTarget = isOwnSymlink\n ? await getSymlinkTarget(requestedPath, fs, signal, log)\n : undefined;\n\n return buildFileInfoResult(name, requestedPath, isOwnSymlink, stats, mimeType, symlinkTarget);\n}\n\nfunction classifyTypeCounts(results: readonly PerPathResult<FileInfo>[]): {\n fileCount: number;\n dirCount: number;\n} {\n let fileCount = 0;\n let dirCount = 0;\n for (const result of results) {\n if ('error' in result) continue;\n if (result.value.type === 'directory') dirCount += 1;\n else fileCount += 1;\n }\n return { fileCount, dirCount };\n}\n\nexport const GET_FILE_INFO = defineTool({\n name: 'stat',\n title: 'Get File Info',\n description:\n 'Get metadata for one or more files or directories: size, type, permissions, MIME type, timestamps, and tokenEstimate. ' +\n 'Use tokenEstimate to pre-screen read cost before calling read. ' +\n 'Single path: pass path. Batch mode: pass paths[].',\n input: StatInputSchema,\n output: StatOutputSchema,\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_FOUND,\n progress: (args) => {\n if (args.paths !== undefined) {\n return { label: 'Stat', subject: `${String(args.paths.length)} paths` };\n }\n return { label: 'Stat', subject: args.path ?? '' };\n },\n accessPaths: singleOrBatchAccessPaths,\n run: async (args, ctx) => {\n const batchInput = args.path !== undefined ? { path: args.path } : { paths: args.paths ?? [] };\n\n const batch = await runOverPaths<undefined, FileInfo>(\n batchInput,\n ctx,\n async ({ path }) => getFileInfo(path, ctx),\n { defaultErrorCode: ErrorCode.NOT_FOUND },\n );\n\n const { fileCount, dirCount } = classifyTypeCounts(batch.results);\n const perPathPayload = batch.results;\n\n let resourceUri: string | undefined;\n const resources: ContentBlock[] = [];\n if (ctx.resourceStore && batch.summary.total > 1) {\n const { entry, link } = putJsonResource(\n ctx.resourceStore,\n `${String(batch.summary.total)} paths`,\n perPathPayload,\n );\n resourceUri = entry.uri;\n resources.push(link);\n }\n\n // No `text` on purpose. The one-liner this used to build (`AGENTS.md: file,\n // 751 B`) dropped tokenEstimate, modified, mimeType and isHidden — the very\n // fields a caller asks `stat` for. Supplying no text makes this a data tool,\n // so `define.ts` renders the JSON and keeps it in `structuredContent`.\n return {\n structured: {\n results: perPathPayload,\n summary: batch.summary,\n fileCount,\n dirCount,\n ...(resourceUri ? { resourceUri } : {}),\n },\n isError: isTotalFailure(batch.summary),\n ...(resources.length > 0 ? { resources } : {}),\n };\n },\n});\n"]}
@@ -102,24 +102,27 @@ export declare function bearerAuthMiddleware(apiKey: string | undefined, hostVal
102
102
  * so loopback browser clients keep working; operators set
103
103
  * `FS_ALLOWED_ORIGINS` to allow remote clients on non-loopback
104
104
  * binds. An empty value reads as unset, matching how parseAllowedHostsEnv
105
- * treats an all-empty list. The same set is consulted by corsPreflightHandler
105
+ * treats an all-empty list. The same set is consulted by corsMiddleware
106
106
  * so a remote origin is reflected end-to-end in Access-Control-Allow-Origin.
107
107
  */
108
108
  export declare function computeAllowedOriginHostnames(originsEnv: string | undefined): string[];
109
- /** Mounted ahead of the `/mcp` handlers so every response — not just the
110
- * OPTIONS preflight — carries `Access-Control-Allow-Origin` for an allowed
111
- * Origin. */
112
- export declare function corsOriginMiddleware(allowedOriginHostnames: readonly string[]): RequestHandler;
113
- /**
114
- * OPTIONS preflight for `/mcp`. The allow-list carries the SEP-2243 standard
115
- * headers (`mcp-protocol-version`, `mcp-method`, `mcp-name`): SDK clients send
116
- * all three on every modern request POST and `createMcpHandler` requires them
117
- * (400 / -32020), so omitting them here would fail every browser preflight —
118
- * and the HTTP leg is modern-only, so there is no legacy path to fall back to.
119
- * `mcp-session-id` is deliberately absent: it is 2025-era only and this
120
- * endpoint rejects legacy traffic.
121
- */
122
- export declare function corsPreflightHandler(allowedOriginHostnames: readonly string[]): RequestHandler;
109
+ /** Mounted at the `/mcp` prefix: every response — not just the OPTIONS preflight —
110
+ * carries `Access-Control-Allow-Origin` for an allowed Origin (localhost, or in
111
+ * the env-derived `FS_ALLOWED_ORIGINS` set — no wildcard fallback), and the
112
+ * preflight answers only the exact endpoint. Reflection must happen here
113
+ * because `createMcpExpressApp`'s `allowedOrigins` only gates which Origins
114
+ * are accepted, it never sets `Access-Control-Allow-Origin` on the actual
115
+ * response, so without this a browser client would pass preflight and then
116
+ * have the POST response body blocked by CORS. Mounted at a prefix, Express
117
+ * rewrites `req.url` to the remainder, so `req.path` is mount-relative:
118
+ * `/` means `/mcp` and `/mcp/`
119
+ * — exactly what the old exact-path `app.options('/mcp')` route matched — while
120
+ * `/sub` stays a subpath and falls through to the same 404 it gets today, not a
121
+ * phantom preflight. The allow-list carries the SEP-2243 standard headers
122
+ * (`mcp-protocol-version`, `mcp-method`, `mcp-name`): SDK clients send all three
123
+ * on every modern request POST and `createMcpHandler` requires them (400 /
124
+ * -32020), so omitting them here would fail every browser preflight. */
125
+ export declare function corsMiddleware(allowedOriginHostnames: readonly string[]): RequestHandler;
123
126
  /**
124
127
  * Fixed-window per-client-IP rate limiter.
125
128
  */
@@ -1 +1 @@
1
- {"version":3,"file":"http-policy.d.ts","sourceRoot":"","sources":["../../src/transport/http-policy.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAgB,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAS/E;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,SAAS,CAAC;AAE3C;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,QAAQ,EACb,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,EAAE,GAAE,MAAM,GAAG,MAAM,GAAG,IAAW,EACjC,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GACnC,IAAI,CAKN;AAID;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAQxD;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEhE;AAgBD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAI5F;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,OAAO,GAClB,UAAU,IAAI,MAAM,CAiBtB;AAMD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAetF;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,MAAM,GAAG,SAAS,GAClC,MAAM,EAAE,CAMV;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAI/F;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,SAAS,MAAM,EAAE,EAC/B,iBAAiB,EAAE,OAAO,GACzB,IAAI,CAUN;AAID;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,OAAO,EACZ,aAAa,EAAE,OAAO,EACtB,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,GAAG,GAAG,IAAI,CAcZ;AAyBD;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,aAAa,EAAE,OAAO,EACtB,SAAS,CAAC,EAAE,MAAM,GACjB,cAAc,CAgChB;AAED;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAKtF;AAyBD;;aAEa;AACb,wBAAgB,oBAAoB,CAAC,sBAAsB,EAAE,SAAS,MAAM,EAAE,GAAG,cAAc,CAK9F;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,sBAAsB,EAAE,SAAS,MAAM,EAAE,GAAG,cAAc,CAU9F;AAYD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CA+B7D"}
1
+ {"version":3,"file":"http-policy.d.ts","sourceRoot":"","sources":["../../src/transport/http-policy.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAgB,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAS/E;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,SAAS,CAAC;AAE3C;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,QAAQ,EACb,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,EAAE,GAAE,MAAM,GAAG,MAAM,GAAG,IAAW,EACjC,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GACnC,IAAI,CAKN;AAID;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAQxD;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEhE;AAgBD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAI5F;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,OAAO,GAClB,UAAU,IAAI,MAAM,CAiBtB;AAMD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAetF;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,MAAM,GAAG,SAAS,GAClC,MAAM,EAAE,CAMV;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAI/F;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,SAAS,MAAM,EAAE,EAC/B,iBAAiB,EAAE,OAAO,GACzB,IAAI,CAUN;AAID;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,OAAO,EACZ,aAAa,EAAE,OAAO,EACtB,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,GAAG,GAAG,IAAI,CAcZ;AAyBD;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,aAAa,EAAE,OAAO,EACtB,SAAS,CAAC,EAAE,MAAM,GACjB,cAAc,CAgChB;AAED;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAKtF;AAED;;;;;;;;;;;;;;;wEAewE;AACxE,wBAAgB,cAAc,CAAC,sBAAsB,EAAE,SAAS,MAAM,EAAE,GAAG,cAAc,CAoBxF;AAYD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CA+B7D"}