@j0hanz/filesystem-mcp 2.7.5 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +290 -394
- package/dist/cli-help.d.ts.map +1 -1
- package/dist/cli-help.js +15 -7
- package/dist/cli-help.js.map +1 -1
- package/dist/cli.d.ts +1 -9
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/core/concurrency.d.ts +7 -0
- package/dist/core/concurrency.d.ts.map +1 -1
- package/dist/core/concurrency.js +19 -0
- package/dist/core/concurrency.js.map +1 -1
- package/dist/core/errors.d.ts +4 -3
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +5 -16
- package/dist/core/errors.js.map +1 -1
- package/dist/core/fs.d.ts +19 -11
- package/dist/core/fs.d.ts.map +1 -1
- package/dist/core/fs.js +168 -53
- package/dist/core/fs.js.map +1 -1
- package/dist/core/glob.d.ts +8 -0
- package/dist/core/glob.d.ts.map +1 -1
- package/dist/core/glob.js +192 -29
- package/dist/core/glob.js.map +1 -1
- package/dist/core/input-required.d.ts +12 -0
- package/dist/core/input-required.d.ts.map +1 -1
- package/dist/core/input-required.js +7 -2
- package/dist/core/input-required.js.map +1 -1
- package/dist/core/observability.d.ts +2 -0
- package/dist/core/observability.d.ts.map +1 -1
- package/dist/core/observability.js +7 -0
- package/dist/core/observability.js.map +1 -1
- package/dist/core/path-completer.d.ts.map +1 -1
- package/dist/core/path-completer.js +11 -30
- package/dist/core/path-completer.js.map +1 -1
- package/dist/core/path.d.ts +7 -18
- package/dist/core/path.d.ts.map +1 -1
- package/dist/core/path.js +22 -55
- package/dist/core/path.js.map +1 -1
- package/dist/core/read.d.ts +4 -1
- package/dist/core/read.d.ts.map +1 -1
- package/dist/core/read.js +25 -16
- package/dist/core/read.js.map +1 -1
- package/dist/core/schema.d.ts +6 -1
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/schema.js +17 -3
- package/dist/core/schema.js.map +1 -1
- package/dist/core/search.d.ts +7 -0
- package/dist/core/search.d.ts.map +1 -1
- package/dist/core/search.js +154 -66
- package/dist/core/search.js.map +1 -1
- package/dist/core/store.d.ts +36 -1
- package/dist/core/store.d.ts.map +1 -1
- package/dist/core/store.js +71 -6
- package/dist/core/store.js.map +1 -1
- package/dist/core/util.d.ts +37 -0
- package/dist/core/util.d.ts.map +1 -1
- package/dist/core/util.js +62 -0
- package/dist/core/util.js.map +1 -1
- package/dist/index.js +5 -16
- package/dist/index.js.map +1 -1
- package/dist/resources.d.ts +5 -1
- package/dist/resources.d.ts.map +1 -1
- package/dist/resources.js +45 -22
- package/dist/resources.js.map +1 -1
- package/dist/server.d.ts +10 -5
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +8 -8
- package/dist/server.js.map +1 -1
- package/dist/tools/create.d.ts.map +1 -1
- package/dist/tools/create.js +93 -90
- package/dist/tools/create.js.map +1 -1
- package/dist/tools/define.d.ts +10 -6
- package/dist/tools/define.d.ts.map +1 -1
- package/dist/tools/define.js +49 -16
- package/dist/tools/define.js.map +1 -1
- package/dist/tools/delete.d.ts.map +1 -1
- package/dist/tools/delete.js +39 -21
- package/dist/tools/delete.js.map +1 -1
- package/dist/tools/edit.d.ts.map +1 -1
- package/dist/tools/edit.js +37 -39
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/find-files.d.ts.map +1 -1
- package/dist/tools/find-files.js +49 -60
- package/dist/tools/find-files.js.map +1 -1
- package/dist/tools/index.d.ts +2 -10
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +1 -8
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/list.d.ts.map +1 -1
- package/dist/tools/list.js +59 -69
- package/dist/tools/list.js.map +1 -1
- package/dist/tools/move.d.ts.map +1 -1
- package/dist/tools/move.js +39 -5
- package/dist/tools/move.js.map +1 -1
- package/dist/tools/patch.d.ts.map +1 -1
- package/dist/tools/patch.js +88 -86
- package/dist/tools/patch.js.map +1 -1
- package/dist/tools/read.d.ts.map +1 -1
- package/dist/tools/read.js +30 -24
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/replace-text.d.ts.map +1 -1
- package/dist/tools/replace-text.js +60 -46
- package/dist/tools/replace-text.js.map +1 -1
- package/dist/tools/search-text.d.ts.map +1 -1
- package/dist/tools/search-text.js +48 -64
- package/dist/tools/search-text.js.map +1 -1
- package/dist/transport/http.d.ts.map +1 -1
- package/dist/transport/http.js +2 -1
- package/dist/transport/http.js.map +1 -1
- package/dist/transport/shared.d.ts +7 -5
- package/dist/transport/shared.d.ts.map +1 -1
- package/dist/transport/shared.js +8 -2
- package/dist/transport/shared.js.map +1 -1
- package/dist/transport/stdio.d.ts +4 -1
- package/dist/transport/stdio.d.ts.map +1 -1
- package/dist/transport/stdio.js +46 -12
- package/dist/transport/stdio.js.map +1 -1
- package/package.json +3 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replace-text.js","sourceRoot":"","sources":["../../src/tools/replace-text.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContentBlock } from '@modelcontextprotocol/server';\n\nimport { Buffer, isUtf8 } from 'node:buffer';\nimport { basename, dirname } from 'node:path';\n\nimport * as z from 'zod/v4';\n\nimport type { StoppedReason } from '../core/concurrency.ts';\nimport { processEntriesConcurrently } from '../core/concurrency.ts';\nimport { unifiedPatch } from '../core/diff.ts';\nimport { ErrorCode, FsError, Problem } from '../core/errors.ts';\nimport { buildWrittenFileMeta } from '../core/file-uri.ts';\nimport { stoppedEarlyLine, truncateProgressPattern, zeroMatchHint } from '../core/fmt.ts';\nimport type { GuardedFileSystem } from '../core/fs.ts';\nimport { globEntries } from '../core/glob.ts';\nimport { toPosixRelative } from '../core/path.ts';\nimport { readFileBufferWithLimit } from '../core/read.ts';\nimport {\n defaultFalseBoolean,\n IncludeHidden,\n IncludeIgnored,\n isBlank,\n MaxDepth,\n OptionalPath,\n SafeGlobPattern,\n} from '../core/schema.ts';\nimport type { Regex } from '../core/search.ts';\nimport { compileRegex, execMatches, freeRegex, RE2_MAX_INPUT_BYTES } from '../core/search.ts';\nimport {\n DEFAULT_SEARCH_RESULTS,\n DEFAULT_SEARCH_TIMEOUT_MS,\n escapeRegExp,\n getMaxTextFileSize,\n MAX_SEARCH_RESULTS,\n PARALLEL_CONCURRENCY,\n} from '../core/util.ts';\nimport { type BatchResult, isTotalFailure } from './batch.ts';\nimport { defineTool, type ToolCtx } from './define.ts';\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 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: IncludeHidden,\n includeIgnored: IncludeIgnored,\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: MaxDepth,\n});\n\ntype SearchAndReplaceOutput = BatchResult<{ matches: number }> & {\n totalMatches: number;\n filesScanned: number;\n skippedBinary?: number;\n resultsTruncated?: boolean;\n diff?: string;\n diffTruncated?: boolean;\n stoppedReason?: StoppedReason;\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: Problem;\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, plan: ReplacementPlan, filePath: string): void {\n const relativePath = toPosixRelative(summary.root, filePath);\n // The first changed file is the one the resource_link points at; keep what\n // was written so the link needs no read-back.\n summary.primary ??= { path: filePath, content: plan.updatedContent };\n if (summary.changedFiles.length < MAX_CHANGED_FILES) {\n summary.changedFiles.push({ path: relativePath, matches: plan.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 if (buffer.length > RE2_MAX_INPUT_BYTES) {\n throw new FsError(\n ErrorCode.TOO_LARGE,\n `File too large for a regex replace (${String(buffer.length)} > ${String(RE2_MAX_INPUT_BYTES)} bytes). Regex mode is used for isRegex, wholeWord, or the default caseSensitive: false; pass caseSensitive: true with a literal searchPattern, or split the file.`,\n );\n }\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>;\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 singleFile: boolean;\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\n try {\n const plan = await readReplacementPlan(entryPath, ctx);\n if (!plan) {\n return;\n }\n\n if (!options.dryRun) {\n await ctx.fs.writeFile(entryPath, plan.updatedContent, {\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, plan, entryPath);\n\n maybeAppendPatchDiff(summary, {\n filePath: entryPath,\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, entryPath),\n error: Problem.fromUnknown(error, ErrorCode.UNKNOWN, entryPath),\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 // Only bytes that decode to UTF-8 losslessly survive the string round trip;\n // anything else would be written back with U+FFFD in place of every bad byte.\n // NUL is valid UTF-8 but marks a binary file, as it does for `read`.\n if (!isUtf8(buffer) || buffer.includes(0)) {\n if (ctx.singleFile) {\n throw new FsError(ErrorCode.INVALID_INPUT, 'Binary or non-UTF-8 file detected.', validPath);\n }\n ctx.summary.skippedBinary++;\n return undefined;\n }\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\n // Budget first: a full budget must not pay for a diff it will discard, and a\n // diff past its deadline counts as truncated output, not a failed file.\n if (summary.diff.length >= MAX_DIFF_SIZE) {\n summary.diffTruncated = true;\n return;\n }\n const header = toPosixRelative(summary.root, params.filePath);\n const patch = unifiedPatch(header, params.originalContent, params.updatedContent);\n if (patch === undefined) {\n summary.diffTruncated = true;\n return;\n }\n if (summary.diff.length + patch.length <= MAX_DIFF_SIZE + DIFF_APPEND_BUFFER) {\n summary.diff += patch;\n return;\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 skippedBinary: number;\n failures: Failure[];\n changedFiles: { path: string; matches: number }[];\n changedFilesTruncated: boolean;\n /** First file changed, as written. */\n primary?: { path: string; content: string };\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 skippedBinary: 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 = escapeRegExp(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 ...(summary.skippedBinary ? { skippedBinary: summary.skippedBinary } : {}),\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 const ceiling = ctx.fs.pathGuard.allowedRootContaining(root);\n\n // An explicit single-file target bypasses baseNameMatch/exclude/hidden/\n // gitignore filtering — it should always be processed as the one file named.\n const entries: AsyncIterable<{ path: string }> | Iterable<{ path: string }> = singleFile\n ? [{ path: singleFile }]\n : globEntries({\n cwd: root,\n pattern: effectivePattern,\n includeHidden: args.includeHidden,\n skipIgnored: !args.includeIgnored,\n ...(ceiling !== undefined ? { ignoreCeiling: ceiling } : {}),\n signal: ctx.signal,\n baseNameMatch: true,\n onlyFiles: true,\n suppressErrors: true,\n ...(args.maxDepth !== undefined ? { maxDepth: args.maxDepth } : {}),\n });\n\n const summary = createReplaceSummary(root);\n\n // The matcher may own a compiled RE2 pattern, whose wasm memory re2-wasm\n // never reclaims on its own. Nothing past the scan touches it, so free it the\n // moment the scan is done — success, failure, or abort alike.\n const matcher = createReplacementMatcher(args);\n let stoppedReason: StoppedReason | undefined;\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 singleFile: singleFile !== undefined,\n };\n\n stoppedReason = 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 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 let primaryModified: string | undefined;\n if (summary.primary && !args.dryRun) {\n try {\n primaryModified = (\n await ctx.fs.stat(summary.primary.path, { signal: ctx.signal })\n ).stats.mtime.toISOString();\n } catch {\n /* result metadata only; the write already succeeded */\n }\n }\n const link = summary.primary\n ? buildWrittenFileMeta({\n validPath: summary.primary.path,\n content: summary.primary.content,\n dryRun: args.dryRun,\n lastModified: primaryModified,\n }).resourceLink\n : undefined;\n return link ? { structured, link } : { structured };\n}\n\nexport const REPLACE_TEXT = defineTool<typeof SearchAndReplaceInputSchema, SearchAndReplaceOutput>({\n name: 'replace_text',\n title: 'Search and Replace',\n description:\n 'Find and replace every occurrence of literal text or an RE2 regex, like sed -i, in one file or all files ' +\n 'under a directory, optionally filtered by glob. The pattern runs over the whole file: it can span lines, ' +\n 'and ^ and $ anchor to file start and end. edit replaces one unique exact match.',\n input: SearchAndReplaceInputSchema,\n readOnlyHint: false,\n timeoutMs: DEFAULT_SEARCH_TIMEOUT_MS,\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 (structured.skippedBinary\n ? ` \\u00b7 ${String(structured.skippedBinary)} binary skipped`\n : '');\n // The structured half ships under `_meta`, which clients do not show the\n // model, so the stop state and the diff preview must ride the text.\n const lines = [summaryText];\n const stop = structured.stoppedReason;\n if (stop === 'timeout') lines.push(stoppedEarlyLine(stop));\n else if (stop !== undefined) {\n // maxResults/maxFiles here are the caller's own caps, so raising one is\n // what reaches the rest; the search engine's advice to narrow is not.\n lines.push(\n `// scan stopped early: hit the ${stop} limit; later files were not scanned. A higher ${stop} reaches them.`,\n );\n }\n const hint =\n structured.totalMatches === 0\n ? zeroMatchHint({\n ...args,\n filesScanned: structured.filesScanned,\n // A failed file, or a binary one the needle did hit, explains the\n // zero better than a guess about the pattern.\n incomplete:\n stop !== undefined ||\n structured.summary.failed > 0 ||\n Boolean(structured.skippedBinary),\n })\n : undefined;\n if (hint) lines.push(hint);\n // A failure's reason lives in `results`, which ships under `_meta`.\n for (const r of structured.results.filter((x) => 'error' in x).slice(0, 3)) {\n lines.push(`// ${basename(r.path)}: ${r.error.code} ${r.error.message}`);\n }\n if (structured.diffTruncated) {\n lines.push(\n `// diff cut at ${String(MAX_DIFF_SIZE / 1024)} KB: some files' changes are not shown.`,\n );\n }\n const text = lines.join('\\n') + (structured.diff ? `\\n\\n${structured.diff}` : '');\n const isError = isTotalFailure(structured.summary);\n if (link) {\n return { structured, text, resources: [link], isError };\n }\n return { structured, text, isError };\n },\n});\n"]}
|
|
1
|
+
{"version":3,"file":"replace-text.js","sourceRoot":"","sources":["../../src/tools/replace-text.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContentBlock } from '@modelcontextprotocol/server';\n\nimport { Buffer, isUtf8 } from 'node:buffer';\nimport { dirname } from 'node:path';\n\nimport * as z from 'zod/v4';\n\nimport type { StoppedReason } from '../core/concurrency.ts';\nimport { processEntriesConcurrently } from '../core/concurrency.ts';\nimport { unifiedPatch } from '../core/diff.ts';\nimport { ErrorCode, FsError, Problem } from '../core/errors.ts';\nimport { buildWrittenFileMeta } from '../core/file-uri.ts';\nimport { stoppedEarlyLine, truncateProgressPattern, zeroMatchHint } from '../core/fmt.ts';\nimport type { GuardedFileSystem } from '../core/fs.ts';\nimport { globEntries } from '../core/glob.ts';\nimport { toPosixRelative } from '../core/path.ts';\nimport { createTooLargeError, readFileBufferWithLimit } from '../core/read.ts';\nimport {\n defaultFalseBoolean,\n IncludeHidden,\n IncludeIgnored,\n MaxDepth,\n nonBlankString,\n OptionalPath,\n SafeGlobPattern,\n} from '../core/schema.ts';\nimport type { Regex } from '../core/search.ts';\nimport {\n compileRegex,\n createYielder,\n execMatches,\n freeRegex,\n RE2_MAX_INPUT_BYTES,\n} from '../core/search.ts';\nimport {\n DEFAULT_SEARCH_RESULTS,\n DEFAULT_SEARCH_TIMEOUT_MS,\n escapeRegExp,\n getMaxTextFileSize,\n MAX_SEARCH_RESULTS,\n PARALLEL_CONCURRENCY,\n} from '../core/util.ts';\nimport { type BatchResult, isTotalFailure } from './batch.ts';\nimport { defineTool, type ToolCtx } from './define.ts';\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: nonBlankString('searchPattern')\n .max(10000)\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 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: IncludeHidden,\n includeIgnored: IncludeIgnored,\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: MaxDepth,\n});\n\ntype SearchAndReplaceOutput = BatchResult<{ matches: number }> & {\n totalMatches: number;\n filesScanned: number;\n skippedBinary?: number;\n resultsTruncated?: boolean;\n diff?: string;\n diffTruncated?: boolean;\n stoppedReason?: StoppedReason;\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: Problem;\n}\n\n/** Counts every failure; keeps the first MAX_FAILURES of them for the result. */\nfunction recordFailure(summary: ReplaceSummary, entryPath: string, error: unknown): void {\n summary.failedFiles++;\n if (summary.failures.length >= MAX_FAILURES) return;\n summary.failures.push({\n path: toPosixRelative(summary.root, entryPath),\n error: Problem.fromUnknown(error, ErrorCode.UNKNOWN, entryPath),\n });\n}\n\nfunction recordChangedFile(summary: ReplaceSummary, plan: ReplacementPlan, filePath: string): void {\n const relativePath = toPosixRelative(summary.root, filePath);\n // The first changed file is the one the resource_link points at; keep what\n // was written so the link needs no read-back.\n summary.primary ??= { path: filePath, content: plan.updatedContent };\n if (summary.changedFiles.length < MAX_CHANGED_FILES) {\n summary.changedFiles.push({ path: relativePath, matches: plan.matchCount });\n return;\n }\n summary.changedFilesTruncated = true;\n}\n\ninterface ReplacementMatcher {\n /** Yields periodically and throws on abort: a partial splice must never be written. */\n replace(\n content: string,\n replacement: string,\n signal: AbortSignal | undefined,\n ): Promise<{ 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 if (buffer.length > RE2_MAX_INPUT_BYTES) {\n throw new FsError(\n ErrorCode.TOO_LARGE,\n `File too large for a regex replace (${String(buffer.length)} > ${String(RE2_MAX_INPUT_BYTES)} bytes). Regex mode is used for isRegex, wholeWord, or the default caseSensitive: false; pass caseSensitive: true with a literal searchPattern, or split the file.`,\n );\n }\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 async replace(content, replacement, signal) {\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 const tick = createYielder(signal);\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 if (await tick()) signal?.throwIfAborted();\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 // One native O(n) pass; nothing to yield for.\n replace(content, replacement) {\n let matchCount = 0;\n const updated = content.replaceAll(searchPattern, () => {\n matchCount++;\n return replacement;\n });\n return Promise.resolve({ content: updated, matchCount });\n },\n dispose(): void {\n // no compiled pattern to release\n },\n };\n}\n\ntype SearchAndReplaceArgs = z.infer<typeof SearchAndReplaceInputSchema>;\n\ninterface ReplaceContext {\n dryRun: boolean;\n returnDiff: boolean;\n replacement: string;\n matcher: ReplacementMatcher;\n maxFileSize: number;\n signal: AbortSignal | undefined;\n summary: ReplaceSummary;\n fs: GuardedFileSystem;\n singleFile: boolean;\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 { dryRun, returnDiff, signal, summary } = ctx;\n\n try {\n // Lock the read→write per file so a concurrent writer is not lost; a dry\n // run never writes and skips the lock.\n const plan = dryRun\n ? await readReplacementPlan(entryPath, ctx)\n : await ctx.fs.lockForWrite(entryPath, async () => {\n const planned = await readReplacementPlan(entryPath, ctx);\n if (planned) await ctx.fs.writeFile(entryPath, planned.updatedContent, { signal });\n return planned;\n });\n if (!plan) {\n return;\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, plan, entryPath);\n\n maybeAppendPatchDiff(summary, {\n filePath: entryPath,\n originalContent: plan.originalContent,\n updatedContent: plan.updatedContent,\n includeDiff: dryRun || returnDiff,\n });\n } catch (error) {\n // A timeout/cancel aborts the whole scan, not just this file: don't record\n // it as a per-file failure. processEntriesConcurrently reports the run as\n // stoppedReason 'timeout' instead.\n if (signal?.aborted) return;\n recordFailure(summary, entryPath, error);\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 createTooLargeError(stats.size, maxFileSize, validPath);\n }\n\n const buffer = await readFileBufferWithLimit(fileHandle, maxFileSize, validPath, signal);\n if (!matcher.testBuffer(buffer)) return undefined;\n // Only bytes that decode to UTF-8 losslessly survive the string round trip;\n // anything else would be written back with U+FFFD in place of every bad byte.\n // NUL is valid UTF-8 but marks a binary file, as it does for `read`.\n if (!isUtf8(buffer) || buffer.includes(0)) {\n if (ctx.singleFile) {\n throw new FsError(ErrorCode.INVALID_INPUT, 'Binary or non-UTF-8 file detected.', validPath);\n }\n ctx.summary.skippedBinary++;\n return undefined;\n }\n\n const originalContent = buffer.toString('utf-8');\n const { content: updatedContent, matchCount } = await matcher.replace(\n originalContent,\n replacement,\n signal,\n );\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\n // Budget first: a full budget must not pay for a diff it will discard, and a\n // diff past its deadline counts as truncated output, not a failed file.\n if (summary.diff.length >= MAX_DIFF_SIZE) {\n summary.diffTruncated = true;\n return;\n }\n const header = toPosixRelative(summary.root, params.filePath);\n const patch = unifiedPatch(header, params.originalContent, params.updatedContent);\n if (patch === undefined) {\n summary.diffTruncated = true;\n return;\n }\n if (summary.diff.length + patch.length <= MAX_DIFF_SIZE + DIFF_APPEND_BUFFER) {\n summary.diff += patch;\n return;\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 skippedBinary: number;\n failures: Failure[];\n changedFiles: { path: string; matches: number }[];\n changedFilesTruncated: boolean;\n /** First file changed, as written. */\n primary?: { path: string; content: string };\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 skippedBinary: 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 = escapeRegExp(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 ...(summary.skippedBinary ? { skippedBinary: summary.skippedBinary } : {}),\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 const ceiling = ctx.fs.pathGuard.allowedRootContaining(root);\n\n // An explicit single-file target bypasses baseNameMatch/exclude/hidden/\n // gitignore filtering — it should always be processed as the one file named.\n const entries: AsyncIterable<{ path: string }> | Iterable<{ path: string }> = singleFile\n ? [{ path: singleFile }]\n : globEntries({\n cwd: root,\n pattern: effectivePattern,\n includeHidden: args.includeHidden,\n skipIgnored: !args.includeIgnored,\n ...(ceiling !== undefined ? { ignoreCeiling: ceiling } : {}),\n signal: ctx.signal,\n baseNameMatch: true,\n onlyFiles: true,\n suppressErrors: true,\n ...(args.maxDepth !== undefined ? { maxDepth: args.maxDepth } : {}),\n });\n\n const summary = createReplaceSummary(root);\n\n // The matcher may own a compiled RE2 pattern, whose wasm memory re2-wasm\n // never reclaims on its own. Nothing past the scan touches it, so free it the\n // moment the scan is done — success, failure, or abort alike.\n const matcher = createReplacementMatcher(args);\n let stoppedReason: StoppedReason | undefined;\n try {\n const context: ReplaceContext = {\n dryRun: args.dryRun,\n returnDiff: args.returnDiff,\n replacement: args.replacement,\n matcher,\n maxFileSize,\n signal: ctx.signal,\n summary,\n fs: ctx.fs,\n singleFile: singleFile !== undefined,\n };\n\n stoppedReason = 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 recordFailure(summary, entryPath, err);\n },\n runEntry: (entryPath) => processEntry(entryPath, context),\n });\n } finally {\n matcher.dispose();\n }\n if (stoppedReason !== undefined) summary.stoppedReason = stoppedReason;\n // A single file that aborts mid-scan throws inside processEntry (caught and\n // swallowed as a timeout) and leaves the dispatch loop with no more entries,\n // so processEntriesConcurrently returns undefined; surface the timeout here so\n // the result is not reported as a clean \"0 matches\". search_text's engine\n // checks the signal directly, so only replace needs this fallback.\n else if (ctx.signal.aborted) summary.stoppedReason = 'timeout';\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 let primaryModified: string | undefined;\n if (summary.primary && !args.dryRun) {\n try {\n primaryModified = (\n await ctx.fs.stat(summary.primary.path, { signal: ctx.signal })\n ).stats.mtime.toISOString();\n } catch {\n /* result metadata only; the write already succeeded */\n }\n }\n const link = summary.primary\n ? buildWrittenFileMeta({\n validPath: summary.primary.path,\n content: summary.primary.content,\n dryRun: args.dryRun,\n lastModified: primaryModified,\n }).resourceLink\n : undefined;\n return link ? { structured, link } : { structured };\n}\n\nexport const REPLACE_TEXT = defineTool<typeof SearchAndReplaceInputSchema, SearchAndReplaceOutput>({\n name: 'replace_text',\n title: 'Search and Replace',\n description:\n 'Find and replace every occurrence of literal text or an RE2 regex, like sed -i, in one file or all files ' +\n 'under a directory, optionally filtered by glob. The pattern runs over the whole file: it can span lines, ' +\n 'and ^ and $ anchor to file start and end. edit replaces one unique exact match.',\n input: SearchAndReplaceInputSchema,\n readOnlyHint: false,\n timeoutMs: DEFAULT_SEARCH_TIMEOUT_MS,\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 (structured.skippedBinary\n ? ` \\u00b7 ${String(structured.skippedBinary)} binary skipped`\n : '');\n // The structured half ships under `_meta`, which clients do not show the\n // model, so the stop state and the diff preview must ride the text.\n const lines = [summaryText];\n const stop = structured.stoppedReason;\n if (stop === 'timeout') lines.push(stoppedEarlyLine(stop));\n else if (stop !== undefined) {\n // maxResults/maxFiles here are the caller's own caps, so raising one is\n // what reaches the rest; the search engine's advice to narrow is not.\n lines.push(\n `// scan stopped early: hit the ${stop} limit; later files were not scanned. A higher ${stop} reaches them.`,\n );\n }\n const hint =\n structured.totalMatches === 0\n ? zeroMatchHint({\n ...args,\n filesScanned: structured.filesScanned,\n // A failed file, or a binary one the needle did hit, explains the\n // zero better than a guess about the pattern.\n incomplete:\n stop !== undefined ||\n structured.summary.failed > 0 ||\n Boolean(structured.skippedBinary),\n })\n : undefined;\n if (hint) lines.push(hint);\n // A failure's reason lives in `results`, which ships under `_meta`. The\n // full relative path, not the basename: the error message may not carry\n // the path, and two same-named files in different directories must not\n // render as the same row.\n for (const r of structured.results.filter((x) => 'error' in x).slice(0, 3)) {\n lines.push(`// ${r.path}: ${r.error.code} ${r.error.message}`);\n }\n if (structured.diffTruncated) {\n lines.push(\n `// diff cut at ${String(MAX_DIFF_SIZE / 1024)} KB: some files' changes are not shown.`,\n );\n }\n const text = lines.join('\\n') + (structured.diff ? `\\n\\n${structured.diff}` : '');\n return {\n structured,\n text,\n resources: link ? [link] : [],\n isError: isTotalFailure(structured.summary),\n };\n },\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-text.d.ts","sourceRoot":"","sources":["../../src/tools/search-text.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"search-text.d.ts","sourceRoot":"","sources":["../../src/tools/search-text.ts"],"names":[],"mappings":"AA4MA,eAAO,MAAM,WAAW,mCA+GtB,CAAC"}
|
|
@@ -5,7 +5,7 @@ import { paginate } from "../core/cursor.js";
|
|
|
5
5
|
import { ErrorCode, FsError } from "../core/errors.js";
|
|
6
6
|
import { formatCount, pageTrailer, truncateProgressPattern, zeroMatchHint } from "../core/fmt.js";
|
|
7
7
|
import { toPosixRelative } from "../core/path.js";
|
|
8
|
-
import { CursorSchema, defaultFalseBoolean, IncludeHidden, IncludeIgnored,
|
|
8
|
+
import { CursorSchema, defaultFalseBoolean, IncludeHidden, IncludeIgnored, MaxDepth, nonBlankString, OptionalPath, SafeGlobPattern, } from "../core/schema.js";
|
|
9
9
|
import { searchContent } from "../core/search.js";
|
|
10
10
|
import { putJsonResource } from "../core/store.js";
|
|
11
11
|
import { DEFAULT_SEARCH_CONTENT_RESULTS, DEFAULT_SEARCH_TIMEOUT_MS, MAX_SEARCH_RESULTS, } from "../core/util.js";
|
|
@@ -13,13 +13,8 @@ import { defineTool } from "./define.js";
|
|
|
13
13
|
const GrepInputSchema = z.strictObject({
|
|
14
14
|
path: OptionalPath.describe('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.'),
|
|
15
15
|
pattern: SafeGlobPattern.optional().describe('Glob to restrict search to specific file types (e.g. **/*.ts); default: all text files'),
|
|
16
|
-
searchPattern:
|
|
17
|
-
.string()
|
|
18
|
-
.min(1)
|
|
16
|
+
searchPattern: nonBlankString('searchPattern')
|
|
19
17
|
.max(10000)
|
|
20
|
-
.refine((val) => !isBlank(val), {
|
|
21
|
-
message: 'searchPattern cannot be empty or whitespace-only',
|
|
22
|
-
})
|
|
23
18
|
.describe('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.'),
|
|
24
19
|
isRegex: defaultFalseBoolean('Treat searchPattern as a regex (default: literal text match)'),
|
|
25
20
|
includeHidden: IncludeHidden,
|
|
@@ -148,56 +143,6 @@ async function resolveSearchScope(path, ctx) {
|
|
|
148
143
|
explicitFile: resolved,
|
|
149
144
|
};
|
|
150
145
|
}
|
|
151
|
-
async function handleSearchContent(args, ctx) {
|
|
152
|
-
const requestedPath = ctx.fs.pathGuard.resolvePathOrRoot(args.path);
|
|
153
|
-
const queryKey = JSON.stringify({
|
|
154
|
-
method: 'search_text',
|
|
155
|
-
path: requestedPath,
|
|
156
|
-
pattern: args.pattern,
|
|
157
|
-
searchPattern: args.searchPattern,
|
|
158
|
-
isRegex: args.isRegex,
|
|
159
|
-
includeHidden: args.includeHidden,
|
|
160
|
-
includeIgnored: args.includeIgnored,
|
|
161
|
-
caseSensitive: args.caseSensitive,
|
|
162
|
-
maxDepth: args.maxDepth,
|
|
163
|
-
context: args.context,
|
|
164
|
-
});
|
|
165
|
-
const paged = await paginate({
|
|
166
|
-
store: ctx.pageStore,
|
|
167
|
-
queryKey,
|
|
168
|
-
cursor: args.cursor,
|
|
169
|
-
pageSize: args.maxResults,
|
|
170
|
-
produce: async () => {
|
|
171
|
-
const { basePath, explicitFile } = await resolveSearchScope(args.path, ctx);
|
|
172
|
-
const result = await searchContent(basePath, args.searchPattern, {
|
|
173
|
-
includeHidden: args.includeHidden,
|
|
174
|
-
filePattern: args.pattern ?? '**/*',
|
|
175
|
-
caseSensitive: args.caseSensitive,
|
|
176
|
-
isRegex: args.isRegex,
|
|
177
|
-
maxResults: MAX_SEARCH_RESULTS,
|
|
178
|
-
skipIgnored: !args.includeIgnored,
|
|
179
|
-
context: args.context,
|
|
180
|
-
...(explicitFile !== undefined ? { explicitFile } : {}),
|
|
181
|
-
...(args.maxDepth !== undefined ? { maxDepth: args.maxDepth } : {}),
|
|
182
|
-
signal: ctx.signal,
|
|
183
|
-
}, ctx.fs.pathGuard);
|
|
184
|
-
return {
|
|
185
|
-
items: buildSortedPayloads(result),
|
|
186
|
-
metadata: result.summary,
|
|
187
|
-
truncated: result.summary.truncated,
|
|
188
|
-
};
|
|
189
|
-
},
|
|
190
|
-
externalize: (matches, metadata) => putJsonResource(ctx.resourceStore, `'${args.searchPattern}' matches`, {
|
|
191
|
-
...searchContentOutput(matches, metadata, undefined, undefined),
|
|
192
|
-
}),
|
|
193
|
-
});
|
|
194
|
-
return {
|
|
195
|
-
structured: searchContentOutput(paged.page, paged.metadata, paged.nextCursor, paged.resource?.entry.uri),
|
|
196
|
-
offset: paged.offset,
|
|
197
|
-
total: paged.metadata.matchingLines,
|
|
198
|
-
...(paged.resource ? { link: paged.resource.link } : {}),
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
146
|
export const SEARCH_TEXT = defineTool({
|
|
202
147
|
name: 'search_text',
|
|
203
148
|
title: 'Search Content',
|
|
@@ -215,7 +160,49 @@ export const SEARCH_TEXT = defineTool({
|
|
|
215
160
|
}),
|
|
216
161
|
accessPaths: (args) => (args.path ? [args.path] : []),
|
|
217
162
|
run: async (args, ctx) => {
|
|
218
|
-
const
|
|
163
|
+
const requestedPath = ctx.fs.pathGuard.resolvePathOrRoot(args.path);
|
|
164
|
+
const queryKey = JSON.stringify({
|
|
165
|
+
method: 'search_text',
|
|
166
|
+
path: requestedPath,
|
|
167
|
+
pattern: args.pattern,
|
|
168
|
+
searchPattern: args.searchPattern,
|
|
169
|
+
isRegex: args.isRegex,
|
|
170
|
+
includeHidden: args.includeHidden,
|
|
171
|
+
includeIgnored: args.includeIgnored,
|
|
172
|
+
caseSensitive: args.caseSensitive,
|
|
173
|
+
maxDepth: args.maxDepth,
|
|
174
|
+
context: args.context,
|
|
175
|
+
});
|
|
176
|
+
const paged = await paginate({
|
|
177
|
+
store: ctx.pageStore,
|
|
178
|
+
queryKey,
|
|
179
|
+
cursor: args.cursor,
|
|
180
|
+
pageSize: args.maxResults,
|
|
181
|
+
produce: async () => {
|
|
182
|
+
const { basePath, explicitFile } = await resolveSearchScope(args.path, ctx);
|
|
183
|
+
const result = await searchContent(basePath, args.searchPattern, {
|
|
184
|
+
includeHidden: args.includeHidden,
|
|
185
|
+
filePattern: args.pattern ?? '**/*',
|
|
186
|
+
caseSensitive: args.caseSensitive,
|
|
187
|
+
isRegex: args.isRegex,
|
|
188
|
+
maxResults: MAX_SEARCH_RESULTS,
|
|
189
|
+
skipIgnored: !args.includeIgnored,
|
|
190
|
+
context: args.context,
|
|
191
|
+
...(explicitFile !== undefined ? { explicitFile } : {}),
|
|
192
|
+
...(args.maxDepth !== undefined ? { maxDepth: args.maxDepth } : {}),
|
|
193
|
+
signal: ctx.signal,
|
|
194
|
+
}, ctx.fs.pathGuard);
|
|
195
|
+
return {
|
|
196
|
+
items: buildSortedPayloads(result),
|
|
197
|
+
metadata: result.summary,
|
|
198
|
+
truncated: result.summary.truncated,
|
|
199
|
+
};
|
|
200
|
+
},
|
|
201
|
+
externalize: (matches, metadata) => putJsonResource(ctx.resourceStore, `'${args.searchPattern}' matches`, {
|
|
202
|
+
...searchContentOutput(matches, metadata, undefined, undefined),
|
|
203
|
+
}),
|
|
204
|
+
});
|
|
205
|
+
const structured = searchContentOutput(paged.page, paged.metadata, paged.nextCursor, paged.resource?.entry.uri);
|
|
219
206
|
const rows = renderRows(structured.matches, args.context > 0);
|
|
220
207
|
const body = rows.length > 0
|
|
221
208
|
? rows.join('\n')
|
|
@@ -233,9 +220,9 @@ export const SEARCH_TEXT = defineTool({
|
|
|
233
220
|
.join('\n');
|
|
234
221
|
const text = body +
|
|
235
222
|
pageTrailer({
|
|
236
|
-
offset,
|
|
223
|
+
offset: paged.offset,
|
|
237
224
|
shown: structured.matches.length,
|
|
238
|
-
total,
|
|
225
|
+
total: paged.metadata.matchingLines,
|
|
239
226
|
noun: 'matches',
|
|
240
227
|
tool: 'search_text',
|
|
241
228
|
nextCursor: structured.nextCursor,
|
|
@@ -244,10 +231,7 @@ export const SEARCH_TEXT = defineTool({
|
|
|
244
231
|
skippedTooLarge: structured.skippedTooLarge,
|
|
245
232
|
skippedInaccessible: structured.skippedInaccessible,
|
|
246
233
|
});
|
|
247
|
-
|
|
248
|
-
return { structured, text, resources: [link] };
|
|
249
|
-
}
|
|
250
|
-
return { structured, text };
|
|
234
|
+
return { structured, text, resources: paged.resource ? [paged.resource.link] : [] };
|
|
251
235
|
},
|
|
252
236
|
});
|
|
253
237
|
//# sourceMappingURL=search-text.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-text.js","sourceRoot":"","sources":["../../src/tools/search-text.ts"],"names":[],"mappings":"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","sourcesContent":["import { stat } from 'node:fs/promises';\nimport { dirname } from 'node:path';\n\nimport * as z from 'zod/v4';\n\nimport { paginate } from '../core/cursor.ts';\nimport { ErrorCode, FsError } from '../core/errors.ts';\nimport { formatCount, pageTrailer, truncateProgressPattern, zeroMatchHint } from '../core/fmt.ts';\nimport { toPosixRelative } from '../core/path.ts';\nimport {\n CursorSchema,\n defaultFalseBoolean,\n IncludeHidden,\n IncludeIgnored,\n isBlank,\n MaxDepth,\n OptionalPath,\n SafeGlobPattern,\n} from '../core/schema.ts';\nimport { searchContent } from '../core/search.ts';\nimport type { JsonResourceResult } from '../core/store.ts';\nimport { putJsonResource } from '../core/store.ts';\nimport {\n DEFAULT_SEARCH_CONTENT_RESULTS,\n DEFAULT_SEARCH_TIMEOUT_MS,\n MAX_SEARCH_RESULTS,\n} from '../core/util.ts';\nimport { defineTool, type ToolCtx } from './define.ts';\n\n// Type Definitions\ntype SearchInput = z.infer<typeof GrepInputSchema>;\ntype SearchResultValue = Awaited<ReturnType<typeof searchContent>>;\ntype SearchMatchPayload = SearchResultValue['matches'][number];\n/** The engine's own summary is the page metadata; nothing is copied out of it. */\ntype SearchContentPageMetadata = SearchResultValue['summary'];\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 isRegex: defaultFalseBoolean('Treat searchPattern as a regex (default: literal text match)'),\n includeHidden: IncludeHidden,\n includeIgnored: IncludeIgnored,\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 context: z\n .uint32()\n .max(10)\n .optional()\n .default(0)\n .describe(\n 'Lines of context to return either side of each match, like grep -C (default: 0, max: 10)',\n ),\n maxDepth: MaxDepth,\n cursor: CursorSchema,\n});\n\ninterface SearchOutput {\n matches: SearchMatchPayload[];\n totalMatches?: number;\n filesMatched?: number;\n filesScanned?: number;\n skippedInaccessible?: number;\n skippedTooLarge?: number;\n skippedBinary?: number;\n truncated?: boolean;\n stoppedReason?: 'maxResults' | 'timeout';\n resourceUri?: string;\n nextCursor?: string;\n}\n\nfunction matchRow(m: SearchMatchPayload): string {\n return `${m.file}:${String(m.line)}: ${m.content}`;\n}\n\n/**\n * grep -C layout: `file-line- text` for a context line, `--` between groups\n * that are not adjacent. Every match's window lands in a per-file line map\n * where a match wins over context, so a line two windows share prints once,\n * and as a match when it is one. The maps iterate in line order without a\n * sort: matches arrive sorted, each window is contiguous, and setting an\n * existing key keeps its slot. Without context the rows are the bare match\n * lines, byte-identical to before the option existed.\n */\nfunction renderRows(matches: readonly SearchMatchPayload[], withContext: boolean): string[] {\n if (!withContext) return matches.map(matchRow);\n const byFile = new Map<string, Map<number, string>>();\n for (const m of matches) {\n const lines = byFile.get(m.file) ?? new Map<number, string>();\n byFile.set(m.file, lines);\n const setContext = (n: number, text: string): void => {\n if (!lines.has(n)) lines.set(n, `${m.file}-${String(n)}- ${text}`);\n };\n const before = m.before ?? [];\n before.forEach((text, k) => {\n setContext(m.line - before.length + k, text);\n });\n lines.set(m.line, matchRow(m));\n (m.after ?? []).forEach((text, k) => {\n setContext(m.line + 1 + k, text);\n });\n }\n const rows: string[] = [];\n for (const lines of byFile.values()) {\n let prev: number | undefined;\n for (const [n, row] of lines) {\n if (prev === undefined ? rows.length > 0 : n > prev + 1) rows.push('--');\n rows.push(row);\n prev = n;\n }\n }\n return rows;\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.matchingLines,\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 ...(metadata.skippedBinary ? { skippedBinary: metadata.skippedBinary } : {}),\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 ...(match.before !== undefined ? { before: match.before } : {}),\n ...(match.after !== undefined ? { after: match.after } : {}),\n }));\n\n payloads.sort((l, r) => l.file.localeCompare(r.file) || l.line - r.line);\n return payloads;\n}\n\n/** Explicit files bypass glob filtering; their parent anchors the relative result paths. */\nasync function resolveSearchScope(\n path: string | undefined,\n ctx: ToolCtx,\n): Promise<{ basePath: string; explicitFile?: string }> {\n const requested = ctx.fs.pathGuard.resolvePathOrRoot(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 };\n }\n return {\n basePath: dirname(resolved),\n // The name is NOT turned into a glob: `[slug].tsx` would read as a\n // character class. searchContent scans exactly this file instead, and\n // hidden/ignored filtering is moot for a file the caller named.\n explicitFile: resolved,\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 = 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 context: args.context,\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, explicitFile } = await resolveSearchScope(args.path, ctx);\n\n const result = await searchContent(\n basePath,\n args.searchPattern,\n {\n includeHidden: args.includeHidden,\n filePattern: args.pattern ?? '**/*',\n caseSensitive: args.caseSensitive,\n isRegex: args.isRegex,\n maxResults: MAX_SEARCH_RESULTS,\n skipIgnored: !args.includeIgnored,\n context: args.context,\n ...(explicitFile !== undefined ? { explicitFile } : {}),\n ...(args.maxDepth !== undefined ? { maxDepth: args.maxDepth } : {}),\n signal: ctx.signal,\n },\n ctx.fs.pathGuard,\n );\n\n return {\n items: buildSortedPayloads(result),\n metadata: result.summary,\n truncated: result.summary.truncated,\n };\n },\n externalize: (matches, metadata) =>\n putJsonResource(ctx.resourceStore, `'${args.searchPattern}' matches`, {\n ...searchContentOutput(matches, metadata, undefined, undefined),\n }),\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.matchingLines,\n ...(paged.resource ? { link: paged.resource.link } : {}),\n };\n}\n\nexport const SEARCH_TEXT = defineTool<typeof GrepInputSchema, SearchOutput>({\n name: 'search_text',\n title: 'Search Content',\n description:\n 'Search file contents for literal text or an RE2 regex, like grep; returns matching lines with line numbers ' +\n 'and paths relative to the searched directory. Patterns match within one line. find_files matches file names.',\n input: GrepInputSchema,\n readOnlyHint: true,\n timeoutMs: DEFAULT_SEARCH_TIMEOUT_MS,\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 = renderRows(structured.matches, args.context > 0);\n const body =\n rows.length > 0\n ? rows.join('\\n')\n : [\n `No matches for '${args.searchPattern}'`,\n zeroMatchHint({\n ...args,\n filesScanned: structured.filesScanned ?? 0,\n incomplete: Boolean(\n structured.stoppedReason ??\n structured.skippedTooLarge ??\n structured.skippedInaccessible,\n ),\n }),\n ]\n .filter(Boolean)\n .join('\\n');\n const text =\n body +\n pageTrailer({\n offset,\n shown: structured.matches.length,\n total,\n noun: 'matches',\n tool: 'search_text',\n nextCursor: structured.nextCursor,\n nextArgs: args,\n stoppedReason: structured.stoppedReason,\n skippedTooLarge: structured.skippedTooLarge,\n skippedInaccessible: structured.skippedInaccessible,\n });\n if (link) {\n return { structured, text, resources: [link] };\n }\n return { structured, text };\n },\n});\n"]}
|
|
1
|
+
{"version":3,"file":"search-text.js","sourceRoot":"","sources":["../../src/tools/search-text.ts"],"names":[],"mappings":"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","sourcesContent":["import { stat } from 'node:fs/promises';\nimport { dirname } from 'node:path';\n\nimport * as z from 'zod/v4';\n\nimport { paginate } from '../core/cursor.ts';\nimport { ErrorCode, FsError } from '../core/errors.ts';\nimport { formatCount, pageTrailer, truncateProgressPattern, zeroMatchHint } from '../core/fmt.ts';\nimport { toPosixRelative } from '../core/path.ts';\nimport {\n CursorSchema,\n defaultFalseBoolean,\n IncludeHidden,\n IncludeIgnored,\n MaxDepth,\n nonBlankString,\n OptionalPath,\n SafeGlobPattern,\n} from '../core/schema.ts';\nimport { searchContent } from '../core/search.ts';\nimport type { JsonResourceResult } from '../core/store.ts';\nimport { putJsonResource } from '../core/store.ts';\nimport {\n DEFAULT_SEARCH_CONTENT_RESULTS,\n DEFAULT_SEARCH_TIMEOUT_MS,\n MAX_SEARCH_RESULTS,\n} from '../core/util.ts';\nimport { defineTool, type ToolCtx } from './define.ts';\n\n// Type Definitions\ntype SearchResultValue = Awaited<ReturnType<typeof searchContent>>;\ntype SearchMatchPayload = SearchResultValue['matches'][number];\n/** The engine's own summary is the page metadata; nothing is copied out of it. */\ntype SearchContentPageMetadata = SearchResultValue['summary'];\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: nonBlankString('searchPattern')\n .max(10000)\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 isRegex: defaultFalseBoolean('Treat searchPattern as a regex (default: literal text match)'),\n includeHidden: IncludeHidden,\n includeIgnored: IncludeIgnored,\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 context: z\n .uint32()\n .max(10)\n .optional()\n .default(0)\n .describe(\n 'Lines of context to return either side of each match, like grep -C (default: 0, max: 10)',\n ),\n maxDepth: MaxDepth,\n cursor: CursorSchema,\n});\n\ninterface SearchOutput {\n matches: SearchMatchPayload[];\n totalMatches?: number;\n filesMatched?: number;\n filesScanned?: number;\n skippedInaccessible?: number;\n skippedTooLarge?: number;\n skippedBinary?: number;\n truncated?: boolean;\n stoppedReason?: 'maxResults' | 'timeout';\n resourceUri?: string;\n nextCursor?: string;\n}\n\nfunction matchRow(m: SearchMatchPayload): string {\n return `${m.file}:${String(m.line)}: ${m.content}`;\n}\n\n/**\n * grep -C layout: `file-line- text` for a context line, `--` between groups\n * that are not adjacent. Every match's window lands in a per-file line map\n * where a match wins over context, so a line two windows share prints once,\n * and as a match when it is one. The maps iterate in line order without a\n * sort: matches arrive sorted, each window is contiguous, and setting an\n * existing key keeps its slot. Without context the rows are the bare match\n * lines, byte-identical to before the option existed.\n */\nfunction renderRows(matches: readonly SearchMatchPayload[], withContext: boolean): string[] {\n if (!withContext) return matches.map(matchRow);\n const byFile = new Map<string, Map<number, string>>();\n for (const m of matches) {\n const lines = byFile.get(m.file) ?? new Map<number, string>();\n byFile.set(m.file, lines);\n const setContext = (n: number, text: string): void => {\n if (!lines.has(n)) lines.set(n, `${m.file}-${String(n)}- ${text}`);\n };\n const before = m.before ?? [];\n before.forEach((text, k) => {\n setContext(m.line - before.length + k, text);\n });\n lines.set(m.line, matchRow(m));\n (m.after ?? []).forEach((text, k) => {\n setContext(m.line + 1 + k, text);\n });\n }\n const rows: string[] = [];\n for (const lines of byFile.values()) {\n let prev: number | undefined;\n for (const [n, row] of lines) {\n if (prev === undefined ? rows.length > 0 : n > prev + 1) rows.push('--');\n rows.push(row);\n prev = n;\n }\n }\n return rows;\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.matchingLines,\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 ...(metadata.skippedBinary ? { skippedBinary: metadata.skippedBinary } : {}),\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 ...(match.before !== undefined ? { before: match.before } : {}),\n ...(match.after !== undefined ? { after: match.after } : {}),\n }));\n\n payloads.sort((l, r) => l.file.localeCompare(r.file) || l.line - r.line);\n return payloads;\n}\n\n/** Explicit files bypass glob filtering; their parent anchors the relative result paths. */\nasync function resolveSearchScope(\n path: string | undefined,\n ctx: ToolCtx,\n): Promise<{ basePath: string; explicitFile?: string }> {\n const requested = ctx.fs.pathGuard.resolvePathOrRoot(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 };\n }\n return {\n basePath: dirname(resolved),\n // The name is NOT turned into a glob: `[slug].tsx` would read as a\n // character class. searchContent scans exactly this file instead, and\n // hidden/ignored filtering is moot for a file the caller named.\n explicitFile: resolved,\n };\n}\n\nexport const SEARCH_TEXT = defineTool<typeof GrepInputSchema, SearchOutput>({\n name: 'search_text',\n title: 'Search Content',\n description:\n 'Search file contents for literal text or an RE2 regex, like grep; returns matching lines with line numbers ' +\n 'and paths relative to the searched directory. Patterns match within one line. find_files matches file names.',\n input: GrepInputSchema,\n readOnlyHint: true,\n timeoutMs: DEFAULT_SEARCH_TIMEOUT_MS,\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 requestedPath = ctx.fs.pathGuard.resolvePathOrRoot(args.path);\n const queryKey = 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 context: args.context,\n });\n const paged = await paginate<SearchMatchPayload, SearchContentPageMetadata, JsonResourceResult>(\n {\n store: ctx.pageStore,\n queryKey,\n cursor: args.cursor,\n pageSize: args.maxResults,\n produce: async () => {\n const { basePath, explicitFile } = await resolveSearchScope(args.path, ctx);\n\n const result = await searchContent(\n basePath,\n args.searchPattern,\n {\n includeHidden: args.includeHidden,\n filePattern: args.pattern ?? '**/*',\n caseSensitive: args.caseSensitive,\n isRegex: args.isRegex,\n maxResults: MAX_SEARCH_RESULTS,\n skipIgnored: !args.includeIgnored,\n context: args.context,\n ...(explicitFile !== undefined ? { explicitFile } : {}),\n ...(args.maxDepth !== undefined ? { maxDepth: args.maxDepth } : {}),\n signal: ctx.signal,\n },\n ctx.fs.pathGuard,\n );\n\n return {\n items: buildSortedPayloads(result),\n metadata: result.summary,\n truncated: result.summary.truncated,\n };\n },\n externalize: (matches, metadata) =>\n putJsonResource(ctx.resourceStore, `'${args.searchPattern}' matches`, {\n ...searchContentOutput(matches, metadata, undefined, undefined),\n }),\n },\n );\n\n const structured = searchContentOutput(\n paged.page,\n paged.metadata,\n paged.nextCursor,\n paged.resource?.entry.uri,\n );\n const rows = renderRows(structured.matches, args.context > 0);\n const body =\n rows.length > 0\n ? rows.join('\\n')\n : [\n `No matches for '${args.searchPattern}'`,\n zeroMatchHint({\n ...args,\n filesScanned: structured.filesScanned ?? 0,\n incomplete: Boolean(\n structured.stoppedReason ??\n structured.skippedTooLarge ??\n structured.skippedInaccessible,\n ),\n }),\n ]\n .filter(Boolean)\n .join('\\n');\n const text =\n body +\n pageTrailer({\n offset: paged.offset,\n shown: structured.matches.length,\n total: paged.metadata.matchingLines,\n noun: 'matches',\n tool: 'search_text',\n nextCursor: structured.nextCursor,\n nextArgs: args,\n stoppedReason: structured.stoppedReason,\n skippedTooLarge: structured.skippedTooLarge,\n skippedInaccessible: structured.skippedInaccessible,\n });\n return { structured, text, resources: paged.resource ? [paged.resource.link] : [] };\n },\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/transport/http.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAUxC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAmBrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAmNjD,wBAAsB,eAAe,CACnC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,aAAa,EACtB,MAAM,GAAE,aAAkB,GACzB,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/transport/http.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAUxC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAmBrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAmNjD,wBAAsB,eAAe,CACnC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,aAAa,EACtB,MAAM,GAAE,aAAkB,GACzB,OAAO,CAAC,MAAM,CAAC,CA6HjB"}
|
package/dist/transport/http.js
CHANGED
|
@@ -208,7 +208,8 @@ export async function startHttpServer(port, options, config = {}) {
|
|
|
208
208
|
resourceStore: sharedStore,
|
|
209
209
|
pageStore: sharedPageStore,
|
|
210
210
|
era,
|
|
211
|
-
|
|
211
|
+
transport: 'http',
|
|
212
|
+
cacheScope: apiKey ? 'private' : 'public',
|
|
212
213
|
});
|
|
213
214
|
return c.mcp;
|
|
214
215
|
}, {
|