@j0hanz/filesystem-mcp 1.7.2 → 1.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.
Files changed (44) hide show
  1. package/dist/lib/file-operations/common.d.ts +42 -0
  2. package/dist/lib/file-operations/common.js +87 -0
  3. package/dist/lib/file-operations/file-info.js +13 -19
  4. package/dist/lib/file-operations/glob-engine.d.ts +1 -6
  5. package/dist/lib/file-operations/glob-engine.js +0 -9
  6. package/dist/lib/file-operations/glob-helpers.d.ts +18 -0
  7. package/dist/lib/file-operations/glob-helpers.js +23 -0
  8. package/dist/lib/file-operations/list-directory.js +22 -46
  9. package/dist/lib/file-operations/read-multiple-files.js +11 -19
  10. package/dist/lib/file-operations/search-content.d.ts +1 -8
  11. package/dist/lib/file-operations/search-content.js +126 -204
  12. package/dist/lib/file-operations/search-files.js +48 -94
  13. package/dist/lib/file-operations/search-matcher.d.ts +10 -0
  14. package/dist/lib/file-operations/search-matcher.js +72 -0
  15. package/dist/lib/file-operations/search-worker.js +3 -1
  16. package/dist/lib/file-operations/tree.d.ts +2 -2
  17. package/dist/lib/file-operations/tree.js +26 -42
  18. package/dist/lib/fs-helpers.d.ts +1 -0
  19. package/dist/lib/fs-helpers.js +9 -0
  20. package/dist/lib/option-utils.d.ts +3 -0
  21. package/dist/lib/option-utils.js +15 -0
  22. package/dist/lib/path-validation.d.ts +1 -0
  23. package/dist/lib/path-validation.js +7 -0
  24. package/dist/lib/progress-reporting.d.ts +11 -0
  25. package/dist/lib/progress-reporting.js +13 -0
  26. package/dist/prompts.js +3 -3
  27. package/dist/resources/generated-instructions.js +14 -14
  28. package/dist/resources/tool-catalog.js +9 -9
  29. package/dist/resources/tool-info.js +5 -5
  30. package/dist/resources/workflows.js +17 -17
  31. package/dist/schemas.js +21 -90
  32. package/dist/server/bootstrap.js +2 -2
  33. package/dist/tools/apply-patch.js +3 -0
  34. package/dist/tools/calculate-hash.js +12 -12
  35. package/dist/tools/delete-file.js +5 -2
  36. package/dist/tools/list-directory.js +3 -21
  37. package/dist/tools/read-multiple.js +11 -21
  38. package/dist/tools/replace-in-files.js +10 -11
  39. package/dist/tools/search-content.js +2 -2
  40. package/dist/tools/search-files.js +3 -21
  41. package/dist/tools/shared.d.ts +19 -0
  42. package/dist/tools/shared.js +64 -18
  43. package/dist/tools/stat-many.js +11 -22
  44. package/package.json +6 -2
@@ -2,3 +2,45 @@ export declare function needsStatsForSort(sortBy: string): boolean;
2
2
  export declare function withOptionalStoppedReason<T extends object, R extends string>(summary: T, stoppedReason: R | undefined): T | (T & {
3
3
  stoppedReason: R;
4
4
  });
5
+ export interface DirentLike {
6
+ isDirectory(): boolean;
7
+ isFile(): boolean;
8
+ isSymbolicLink(): boolean;
9
+ }
10
+ export type EntryType = 'file' | 'directory' | 'symlink' | 'other';
11
+ export interface IndexedValue<T> {
12
+ index: number;
13
+ value: T;
14
+ }
15
+ export interface IndexedError {
16
+ index: number;
17
+ error: Error;
18
+ }
19
+ export declare function resolveEntryType(dirent: DirentLike): EntryType;
20
+ export declare function resolveStopReason<R extends string>(options: {
21
+ signal: AbortSignal;
22
+ current: number;
23
+ max: number;
24
+ abortedReason: R;
25
+ maxReason: R;
26
+ }): R | undefined;
27
+ export declare function compareStringValues(left?: string, right?: string): number;
28
+ export declare function compareOptionalNumberDesc(left: number | undefined, right: number | undefined, tieBreak: () => number): number;
29
+ export declare function stableSortByDerivedString<T>(items: T[], derive: (item: T) => string, tieBreak: (left: T, right: T) => number): void;
30
+ export declare function applyIndexedValues<T>(output: T[], results: readonly IndexedValue<T>[]): void;
31
+ export declare function applyIndexedErrors<T>(options: {
32
+ output: T[];
33
+ errors: readonly IndexedError[];
34
+ resolveIndex: (failureIndex: number) => number | undefined;
35
+ buildValue: (resolvedIndex: number, error: Error) => T;
36
+ }): void;
37
+ export interface EntryAccessDependencies {
38
+ normalizePath: (inputPath: string) => string;
39
+ isPathWithinDirectories: (normalizedPath: string, rootDirectories: readonly string[]) => boolean;
40
+ isSensitivePath: (requestedPath: string, resolvedPath: string) => boolean;
41
+ validateSymlinkPath: (inputPath: string, signal: AbortSignal) => Promise<{
42
+ requestedPath: string;
43
+ resolvedPath: string;
44
+ }>;
45
+ }
46
+ export declare function isEntryAccessibleByType(entryPath: string, entryType: EntryType, rootDirectories: readonly string[], signal: AbortSignal, deps: EntryAccessDependencies): Promise<boolean>;
@@ -1,9 +1,96 @@
1
1
  export function needsStatsForSort(sortBy) {
2
2
  return sortBy === 'size' || sortBy === 'modified';
3
3
  }
4
+ const collator = new Intl.Collator(undefined, { numeric: true });
4
5
  export function withOptionalStoppedReason(summary, stoppedReason) {
5
6
  if (stoppedReason === undefined) {
6
7
  return summary;
7
8
  }
8
9
  return { ...summary, stoppedReason };
9
10
  }
11
+ export function resolveEntryType(dirent) {
12
+ if (dirent.isSymbolicLink())
13
+ return 'symlink';
14
+ if (dirent.isDirectory())
15
+ return 'directory';
16
+ if (dirent.isFile())
17
+ return 'file';
18
+ return 'other';
19
+ }
20
+ export function resolveStopReason(options) {
21
+ if (options.signal.aborted)
22
+ return options.abortedReason;
23
+ if (options.current >= options.max)
24
+ return options.maxReason;
25
+ return undefined;
26
+ }
27
+ export function compareStringValues(left, right) {
28
+ return collator.compare(left ?? '', right ?? '');
29
+ }
30
+ export function compareOptionalNumberDesc(left, right, tieBreak) {
31
+ const diff = (right ?? 0) - (left ?? 0);
32
+ if (diff !== 0)
33
+ return diff;
34
+ return tieBreak();
35
+ }
36
+ export function stableSortByDerivedString(items, derive, tieBreak) {
37
+ const decorated = [];
38
+ for (let index = 0; index < items.length; index += 1) {
39
+ const item = items[index];
40
+ if (item === undefined)
41
+ continue;
42
+ decorated.push({
43
+ item,
44
+ derived: derive(item),
45
+ index,
46
+ });
47
+ }
48
+ decorated.sort((left, right) => {
49
+ const derivedCompare = compareStringValues(left.derived, right.derived);
50
+ if (derivedCompare !== 0)
51
+ return derivedCompare;
52
+ const tiedCompare = tieBreak(left.item, right.item);
53
+ if (tiedCompare !== 0)
54
+ return tiedCompare;
55
+ return left.index - right.index;
56
+ });
57
+ for (let index = 0; index < decorated.length; index += 1) {
58
+ const entry = decorated[index];
59
+ if (!entry)
60
+ continue;
61
+ items[index] = entry.item;
62
+ }
63
+ }
64
+ export function applyIndexedValues(output, results) {
65
+ for (const result of results) {
66
+ if (result.index < 0 || result.index >= output.length)
67
+ continue;
68
+ output[result.index] = result.value;
69
+ }
70
+ }
71
+ export function applyIndexedErrors(options) {
72
+ for (const failure of options.errors) {
73
+ const resolvedIndex = options.resolveIndex(failure.index);
74
+ if (resolvedIndex === undefined)
75
+ continue;
76
+ if (resolvedIndex < 0 || resolvedIndex >= options.output.length)
77
+ continue;
78
+ options.output[resolvedIndex] = options.buildValue(resolvedIndex, failure.error);
79
+ }
80
+ }
81
+ export async function isEntryAccessibleByType(entryPath, entryType, rootDirectories, signal, deps) {
82
+ if (entryType !== 'symlink') {
83
+ const normalizedPath = deps.normalizePath(entryPath);
84
+ if (!deps.isPathWithinDirectories(normalizedPath, rootDirectories)) {
85
+ return false;
86
+ }
87
+ return !deps.isSensitivePath(entryPath, normalizedPath);
88
+ }
89
+ try {
90
+ const validated = await deps.validateSymlinkPath(entryPath, signal);
91
+ return !deps.isSensitivePath(validated.requestedPath, validated.resolvedPath);
92
+ }
93
+ catch {
94
+ return false;
95
+ }
96
+ }
@@ -5,6 +5,7 @@ import { isAbortError } from '../errors.js';
5
5
  import { assertNotAborted, getFileType, isHidden, processInParallel, withAbort, } from '../fs-helpers.js';
6
6
  import { assertAllowedFileAccess } from '../path-policy.js';
7
7
  import { validateExistingPathDetailed } from '../path-validation.js';
8
+ import { applyIndexedErrors, applyIndexedValues } from './common.js';
8
9
  const PERM_STRINGS = [
9
10
  '---',
10
11
  '--x',
@@ -95,23 +96,6 @@ async function readFileInfoInParallel(paths, options) {
95
96
  return { index, value };
96
97
  }, PARALLEL_CONCURRENCY, options.signal);
97
98
  }
98
- function applyResults(output, results) {
99
- for (const result of results) {
100
- output[result.index] = result.value;
101
- }
102
- }
103
- function applyErrors(output, errors, paths) {
104
- for (const failure of errors) {
105
- const { index } = failure;
106
- if (!isValidOutputIndex(index, output.length))
107
- continue;
108
- const filePath = paths[index] ?? UNKNOWN_PATH;
109
- output[index] = { path: filePath, error: failure.error.message };
110
- }
111
- }
112
- function isValidOutputIndex(index, length) {
113
- return index >= 0 && index < length;
114
- }
115
99
  function calculateSummary(results) {
116
100
  let succeeded = 0;
117
101
  let failed = 0;
@@ -140,8 +124,18 @@ export async function getMultipleFileInfo(paths, options = {}) {
140
124
  output[index] = { path: paths[index] ?? UNKNOWN_PATH };
141
125
  }
142
126
  const { results, errors } = await readFileInfoInParallel(paths, options);
143
- applyResults(output, results);
144
- applyErrors(output, errors, paths);
127
+ applyIndexedValues(output, results);
128
+ applyIndexedErrors({
129
+ output,
130
+ errors,
131
+ resolveIndex: (failureIndex) => failureIndex >= 0 && failureIndex < output.length
132
+ ? failureIndex
133
+ : undefined,
134
+ buildValue: (resolvedIndex, error) => ({
135
+ path: paths[resolvedIndex] ?? UNKNOWN_PATH,
136
+ error: error.message,
137
+ }),
138
+ });
145
139
  return {
146
140
  results: output,
147
141
  summary: calculateSummary(output),
@@ -1,10 +1,5 @@
1
1
  import type { Stats } from 'node:fs';
2
- interface DirentLike {
3
- isDirectory(): boolean;
4
- isFile(): boolean;
5
- isSymbolicLink(): boolean;
6
- }
7
- export declare function resolveEntryType(dirent: DirentLike): 'file' | 'directory' | 'symlink' | 'other';
2
+ import type { DirentLike } from './common.js';
8
3
  interface GlobEntry {
9
4
  path: string;
10
5
  relativePath?: string;
@@ -4,15 +4,6 @@ import { glob as fsGlob } from 'node:fs/promises';
4
4
  import { getToolContextSnapshot, publishOpsTraceEnd, publishOpsTraceError, publishOpsTraceStart, shouldPublishOpsTrace, startPerfMeasure, } from '../observability.js';
5
5
  import { toPosixPath } from '../path-format.js';
6
6
  import { isRecord } from '../type-guards.js';
7
- export function resolveEntryType(dirent) {
8
- if (dirent.isDirectory())
9
- return 'directory';
10
- if (dirent.isSymbolicLink())
11
- return 'symlink';
12
- if (dirent.isFile())
13
- return 'file';
14
- return 'other';
15
- }
16
7
  const GLOB_MAGIC_RE = /[*?[\]{}!]/u;
17
8
  const DEFAULT_MAX_HIDDEN_DEPTH = 10;
18
9
  const GLOB_BATCH_CONCURRENCY = 64;
@@ -0,0 +1,18 @@
1
+ import type { globEntries } from './glob-engine.js';
2
+ export interface GlobConfig {
3
+ cwd: string;
4
+ pattern: string;
5
+ excludePatterns?: readonly string[];
6
+ includeHidden?: boolean;
7
+ baseNameMatch?: boolean;
8
+ caseSensitiveMatch?: boolean;
9
+ followSymbolicLinks?: boolean;
10
+ onlyFiles?: boolean;
11
+ stats?: boolean;
12
+ maxDepth?: number;
13
+ suppressErrors?: boolean;
14
+ }
15
+ /**
16
+ * Builds standard options for globEntries to ensure consistency across search tools.
17
+ */
18
+ export declare function buildGlobOptions(config: GlobConfig): Parameters<typeof globEntries>[0];
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Builds standard options for globEntries to ensure consistency across search tools.
3
+ */
4
+ export function buildGlobOptions(config) {
5
+ const options = {
6
+ cwd: config.cwd,
7
+ pattern: config.pattern,
8
+ excludePatterns: config.excludePatterns ?? [],
9
+ includeHidden: config.includeHidden ?? false,
10
+ baseNameMatch: config.baseNameMatch ?? false,
11
+ caseSensitiveMatch: config.caseSensitiveMatch ?? true,
12
+ followSymbolicLinks: config.followSymbolicLinks ?? false,
13
+ onlyFiles: config.onlyFiles ?? true,
14
+ stats: config.stats ?? false,
15
+ };
16
+ if (config.suppressErrors) {
17
+ options.suppressErrors = config.suppressErrors;
18
+ }
19
+ if (config.maxDepth !== undefined) {
20
+ options.maxDepth = config.maxDepth;
21
+ }
22
+ return options;
23
+ }
@@ -1,11 +1,11 @@
1
1
  import * as fsp from 'node:fs/promises';
2
2
  import * as path from 'node:path';
3
3
  import { DEFAULT_LIST_MAX_ENTRIES, DEFAULT_MAX_DEPTH, DEFAULT_SEARCH_TIMEOUT_MS, PARALLEL_CONCURRENCY, } from '../constants.js';
4
- import { createTimedAbortSignal, processInParallel, withAbort, } from '../fs-helpers.js';
4
+ import { isHidden, processInParallel, withAbort, withTimedAbortSignal, } from '../fs-helpers.js';
5
5
  import { isSensitivePath } from '../path-policy.js';
6
6
  import { isPathWithinDirectories, normalizePath, validateExistingDirectory, validateExistingPathDetailed, } from '../path-validation.js';
7
- import { needsStatsForSort, withOptionalStoppedReason } from './common.js';
8
- import { globEntries, resolveEntryType } from './glob-engine.js';
7
+ import { isEntryAccessibleByType, needsStatsForSort, resolveEntryType, resolveStopReason, withOptionalStoppedReason, } from './common.js';
8
+ import { globEntries } from './glob-engine.js';
9
9
  function normalizePattern(pattern) {
10
10
  if (!pattern || pattern.length === 0)
11
11
  return undefined;
@@ -40,18 +40,11 @@ function resolveMaxDepth(normalized) {
40
40
  }
41
41
  return normalized.maxDepth;
42
42
  }
43
- function getStopReason(signal, acceptedCount, maxEntries) {
44
- if (signal.aborted)
45
- return 'aborted';
46
- if (acceptedCount >= maxEntries)
47
- return 'maxEntries';
48
- return undefined;
49
- }
50
43
  async function* readDirectoryEntries(basePath, normalized, needsStats, signal) {
51
44
  const dirents = await withAbort(fsp.readdir(basePath, { withFileTypes: true }), signal);
52
45
  const entries = [];
53
46
  for (const dirent of dirents) {
54
- if (!normalized.includeHidden && dirent.name.startsWith('.')) {
47
+ if (!normalized.includeHidden && isHidden(dirent.name)) {
55
48
  continue;
56
49
  }
57
50
  entries.push({ dirent, entryPath: path.join(basePath, dirent.name) });
@@ -149,32 +142,6 @@ function trackSymlink(entryType, includeSymlinkTargets, counters) {
149
142
  counters.symlinksNotFollowed += 1;
150
143
  }
151
144
  }
152
- async function isEntryAccessible(entryPath, entryType, basePathDirectories, signal, counters) {
153
- if (entryType !== 'symlink') {
154
- const normalized = normalizePath(entryPath);
155
- if (!isPathWithinDirectories(normalized, basePathDirectories)) {
156
- counters.skippedInaccessible += 1;
157
- return false;
158
- }
159
- if (isSensitivePath(entryPath, normalized)) {
160
- counters.skippedInaccessible += 1;
161
- return false;
162
- }
163
- return true;
164
- }
165
- try {
166
- const validated = await validateExistingPathDetailed(entryPath, signal);
167
- if (isSensitivePath(validated.requestedPath, validated.resolvedPath)) {
168
- counters.skippedInaccessible += 1;
169
- return false;
170
- }
171
- return true;
172
- }
173
- catch {
174
- counters.skippedInaccessible += 1;
175
- return false;
176
- }
177
- }
178
145
  function appendEntry(entry, entryType, symlinkTarget, ctx) {
179
146
  updateTotals(entryType, ctx.totals);
180
147
  ctx.entries.push(buildDirectoryEntry(ctx.basePath, entry, entryType, ctx.needsStats, symlinkTarget));
@@ -214,6 +181,12 @@ async function collectEntries(basePath, normalized, signal, needsStats, maxDepth
214
181
  const totals = { files: 0, directories: 0 };
215
182
  const counters = { skippedInaccessible: 0, symlinksNotFollowed: 0 };
216
183
  const basePathDirectories = [basePath];
184
+ const accessDeps = {
185
+ normalizePath,
186
+ isPathWithinDirectories,
187
+ isSensitivePath,
188
+ validateSymlinkPath: validateExistingPathDetailed,
189
+ };
217
190
  let truncated = false;
218
191
  let stoppedReason;
219
192
  const pending = [];
@@ -232,7 +205,13 @@ async function collectEntries(basePath, normalized, signal, needsStats, maxDepth
232
205
  entries,
233
206
  };
234
207
  for await (const entry of stream) {
235
- const stopReason = getStopReason(signal, acceptedCount, normalized.maxEntries);
208
+ const stopReason = resolveStopReason({
209
+ signal,
210
+ current: acceptedCount,
211
+ max: normalized.maxEntries,
212
+ abortedReason: 'aborted',
213
+ maxReason: 'maxEntries',
214
+ });
236
215
  if (stopReason) {
237
216
  truncated = true;
238
217
  stoppedReason = stopReason;
@@ -240,8 +219,9 @@ async function collectEntries(basePath, normalized, signal, needsStats, maxDepth
240
219
  }
241
220
  const entryType = resolveEntryType(entry.dirent);
242
221
  trackSymlink(entryType, normalized.includeSymlinkTargets, counters);
243
- const accessible = await isEntryAccessible(entry.path, entryType, basePathDirectories, signal, counters);
222
+ const accessible = await isEntryAccessibleByType(entry.path, entryType, basePathDirectories, signal, accessDeps);
244
223
  if (!accessible) {
224
+ counters.skippedInaccessible += 1;
245
225
  continue;
246
226
  }
247
227
  acceptedCount += 1;
@@ -264,13 +244,9 @@ async function executeListDirectory(basePath, normalized, signal) {
264
244
  }
265
245
  export async function listDirectory(dirPath, options = {}) {
266
246
  const normalized = normalizeOptions(options);
267
- const { signal, cleanup } = createTimedAbortSignal(options.signal, normalized.timeoutMs);
268
- const basePath = await validateExistingDirectory(dirPath, signal);
269
- try {
247
+ return withTimedAbortSignal(options.signal, normalized.timeoutMs, async (signal) => {
248
+ const basePath = await validateExistingDirectory(dirPath, signal);
270
249
  const { entries, summary } = await executeListDirectory(basePath, normalized, signal);
271
250
  return { path: basePath, entries, summary };
272
- }
273
- finally {
274
- cleanup();
275
- }
251
+ });
276
252
  }
@@ -2,6 +2,7 @@ import * as fsp from 'node:fs/promises';
2
2
  import { DEFAULT_READ_MANY_MAX_TOTAL_SIZE, MAX_TEXT_FILE_SIZE, PARALLEL_CONCURRENCY, } from '../constants.js';
3
3
  import { processInParallel, readFile, readFileWithStats, withAbort, } from '../fs-helpers.js';
4
4
  import { validateExistingPath } from '../path-validation.js';
5
+ import { applyIndexedErrors, applyIndexedValues } from './common.js';
5
6
  const UNKNOWN_PATH = '(unknown)';
6
7
  function estimateReadSize(stats, maxSize) {
7
8
  // `readFile`/`readFileWithStats` are always invoked with a `maxSize` cap, so the
@@ -173,11 +174,6 @@ function buildOutput(filePaths) {
173
174
  }
174
175
  return output;
175
176
  }
176
- function applyResults(output, results) {
177
- for (const result of results) {
178
- output[result.index] = result.value;
179
- }
180
- }
181
177
  function resolveErrorOriginalIndex(failureIndex, filesToProcess, totalInputFiles) {
182
178
  // processInParallel implementations vary: some return error indices relative to
183
179
  // the submitted batch (filesToProcess), others may forward the task/index.
@@ -192,18 +188,6 @@ function resolveErrorOriginalIndex(failureIndex, filesToProcess, totalInputFiles
192
188
  }
193
189
  return undefined;
194
190
  }
195
- function applyErrors(output, errors, filesToProcess, filePaths) {
196
- for (const failure of errors) {
197
- const originalIndex = resolveErrorOriginalIndex(failure.index, filesToProcess, filePaths.length);
198
- if (originalIndex === undefined)
199
- continue;
200
- const filePath = filePaths[originalIndex] ?? UNKNOWN_PATH;
201
- output[originalIndex] = {
202
- path: filePath,
203
- error: failure.error.message,
204
- };
205
- }
206
- }
207
191
  function buildFilesToProcess(filePaths, validated, skippedBudget) {
208
192
  const filesToProcess = [];
209
193
  for (let index = 0; index < filePaths.length; index += 1) {
@@ -253,8 +237,16 @@ export async function readMultipleFiles(filePaths, options = {}) {
253
237
  const { skippedBudget, validated } = await collectFileBudget(filePaths, normalized.maxTotalSize, normalized.maxSize, signal);
254
238
  const filesToProcess = buildFilesToProcess(filePaths, validated, skippedBudget);
255
239
  const { results, errors } = await readFilesInParallel(filesToProcess, normalized, signal, options.onReadComplete);
256
- applyResults(output, results);
257
- applyErrors(output, errors, filesToProcess, filePaths);
240
+ applyIndexedValues(output, results);
241
+ applyIndexedErrors({
242
+ output,
243
+ errors,
244
+ resolveIndex: (failureIndex) => resolveErrorOriginalIndex(failureIndex, filesToProcess, filePaths.length),
245
+ buildValue: (resolvedIndex, error) => ({
246
+ path: filePaths[resolvedIndex] ?? UNKNOWN_PATH,
247
+ error: error.message,
248
+ }),
249
+ });
258
250
  applySkippedBudget(output, skippedBudget, filePaths, normalized.maxTotalSize);
259
251
  return output;
260
252
  }
@@ -1,12 +1,7 @@
1
1
  import * as fsp from 'node:fs/promises';
2
2
  import { z } from 'zod';
3
3
  import type { ContentMatch, SearchContentResult } from '../../config.js';
4
- export declare const MatcherOptionsSchema: z.ZodObject<{
5
- caseSensitive: z.ZodBoolean;
6
- wholeWord: z.ZodBoolean;
7
- isLiteral: z.ZodBoolean;
8
- }, z.core.$strict>;
9
- export type MatcherOptions = z.infer<typeof MatcherOptionsSchema>;
4
+ import type { Matcher, MatcherOptions } from './search-matcher.js';
10
5
  export interface ScanFileOptions {
11
6
  maxFileSize: number;
12
7
  skipBinary: boolean;
@@ -36,8 +31,6 @@ export interface SearchContentOptions extends Partial<ResolvedOptions> {
36
31
  current: number;
37
32
  }) => void;
38
33
  }
39
- export type Matcher = (line: string) => number;
40
- export declare function buildMatcher(pattern: string, options: MatcherOptions): Matcher;
41
34
  type BinaryDetector = (resolvedPath: string, handle: fsp.FileHandle, signal?: AbortSignal) => Promise<boolean>;
42
35
  export interface ScanRequest {
43
36
  type: 'scan';