@j0hanz/filesystem-mcp 1.8.0 → 1.9.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 +635 -377
- package/dist/cli.js +2 -2
- package/dist/completions.js +2 -3
- package/dist/index.js +2 -2
- package/dist/lib/file-operations/{common.d.ts → core.d.ts} +6 -0
- package/dist/lib/file-operations/{common.js → core.js} +45 -0
- package/dist/lib/file-operations/metadata.d.ts +73 -0
- package/dist/lib/file-operations/metadata.js +889 -0
- package/dist/lib/file-operations/{search-content.d.ts → search.d.ts} +35 -2
- package/dist/lib/file-operations/{search-content.js → search.js} +413 -15
- package/dist/lib/file-operations/{glob-engine.d.ts → traversal.d.ts} +18 -1
- package/dist/lib/file-operations/{glob-engine.js → traversal.js} +25 -2
- package/dist/lib/fs-helpers.js +1 -2
- package/dist/lib/observability.js +1 -1
- package/dist/lib/{path-validation.d.ts → paths.d.ts} +3 -0
- package/dist/lib/{path-validation.js → paths.js} +105 -1
- package/dist/lib/utils.d.ts +15 -0
- package/dist/lib/utils.js +33 -0
- package/dist/resources/generated-instructions.js +6 -6
- package/dist/resources/tool-catalog.js +9 -9
- package/dist/resources/tool-info.js +3 -3
- package/dist/resources/workflows.js +10 -23
- package/dist/schemas.js +15 -15
- package/dist/server/bootstrap.d.ts +19 -1
- package/dist/server/bootstrap.js +103 -9
- package/dist/server/roots-manager.d.ts +2 -2
- package/dist/server/roots-manager.js +3 -3
- package/dist/tools/apply-patch.js +4 -3
- package/dist/tools/calculate-hash.js +4 -4
- package/dist/tools/create-directory.js +1 -1
- package/dist/tools/delete-file.js +3 -3
- package/dist/tools/diff-files.js +2 -2
- package/dist/tools/edit-file.js +14 -13
- package/dist/tools/list-directory.js +5 -7
- package/dist/tools/move-file.js +2 -1
- package/dist/tools/read-multiple.js +3 -4
- package/dist/tools/read.js +3 -3
- package/dist/tools/replace-in-files.js +8 -10
- package/dist/tools/roots.js +4 -6
- package/dist/tools/search-content.js +7 -9
- package/dist/tools/search-files.js +4 -6
- package/dist/tools/shared.d.ts +2 -1
- package/dist/tools/shared.js +2 -1
- package/dist/tools/stat-many.js +4 -3
- package/dist/tools/stat.js +4 -3
- package/dist/tools/task-support.js +1 -1
- package/dist/tools/tree.js +3 -4
- package/dist/tools/write-file.js +1 -1
- package/package.json +4 -4
- package/dist/lib/file-operations/file-info.d.ts +0 -10
- package/dist/lib/file-operations/file-info.js +0 -143
- package/dist/lib/file-operations/gitignore.d.ts +0 -6
- package/dist/lib/file-operations/gitignore.js +0 -45
- package/dist/lib/file-operations/glob-helpers.d.ts +0 -18
- package/dist/lib/file-operations/glob-helpers.js +0 -23
- package/dist/lib/file-operations/list-directory.d.ts +0 -14
- package/dist/lib/file-operations/list-directory.js +0 -252
- package/dist/lib/file-operations/read-multiple-files.d.ts +0 -25
- package/dist/lib/file-operations/read-multiple-files.js +0 -252
- package/dist/lib/file-operations/search-files.d.ts +0 -27
- package/dist/lib/file-operations/search-files.js +0 -216
- package/dist/lib/file-operations/search-matcher.d.ts +0 -10
- package/dist/lib/file-operations/search-matcher.js +0 -72
- package/dist/lib/file-operations/search-worker.d.ts +0 -2
- package/dist/lib/file-operations/search-worker.js +0 -131
- package/dist/lib/file-operations/tree.d.ts +0 -28
- package/dist/lib/file-operations/tree.js +0 -265
- package/dist/lib/option-utils.d.ts +0 -3
- package/dist/lib/option-utils.js +0 -15
- package/dist/lib/path-format.d.ts +0 -1
- package/dist/lib/path-format.js +0 -7
- package/dist/lib/path-policy.d.ts +0 -2
- package/dist/lib/path-policy.js +0 -100
- package/dist/lib/progress-reporting.d.ts +0 -11
- package/dist/lib/progress-reporting.js +0 -13
- package/dist/lib/type-guards.d.ts +0 -1
- package/dist/lib/type-guards.js +0 -3
- package/dist/server/capabilities.d.ts +0 -10
- package/dist/server/capabilities.js +0 -48
- package/dist/server/logging.d.ts +0 -7
- package/dist/server/logging.js +0 -41
- package/dist/server/types.d.ts +0 -4
- package/dist/server/types.js +0 -1
|
@@ -2,7 +2,7 @@ import * as fs from 'node:fs/promises';
|
|
|
2
2
|
import * as path from 'node:path';
|
|
3
3
|
import { ErrorCode, isNodeError, McpError } from '../lib/errors.js';
|
|
4
4
|
import { withAbort } from '../lib/fs-helpers.js';
|
|
5
|
-
import { isAllowedDirectoryRoot, validatePathForWrite
|
|
5
|
+
import { isAllowedDirectoryRoot, validatePathForWrite } from '../lib/paths.js';
|
|
6
6
|
import { DeleteFileInputSchema, DeleteFileOutputSchema } from '../schemas.js';
|
|
7
7
|
import { buildToolErrorResponse, buildToolResponse, DESTRUCTIVE_WRITE_TOOL_ANNOTATIONS, executeToolWithDiagnostics, withDefaultIcons, withValidatedArgs, wrapToolHandler, } from './shared.js';
|
|
8
8
|
import { registerToolTaskIfAvailable } from './task-support.js';
|
|
@@ -14,8 +14,8 @@ export const DELETE_FILE_TOOL = {
|
|
|
14
14
|
outputSchema: DeleteFileOutputSchema,
|
|
15
15
|
annotations: DESTRUCTIVE_WRITE_TOOL_ANNOTATIONS,
|
|
16
16
|
gotchas: [
|
|
17
|
-
'
|
|
18
|
-
'Non-empty
|
|
17
|
+
'No undo — deletion is permanent.',
|
|
18
|
+
'Non-empty directories require `recursive=true`.',
|
|
19
19
|
],
|
|
20
20
|
};
|
|
21
21
|
async function handleDeleteFile(args, signal) {
|
package/dist/tools/diff-files.js
CHANGED
|
@@ -4,7 +4,7 @@ import { createTwoFilesPatch } from 'diff';
|
|
|
4
4
|
import { MAX_TEXT_FILE_SIZE } from '../lib/constants.js';
|
|
5
5
|
import { ErrorCode, McpError } from '../lib/errors.js';
|
|
6
6
|
import { withAbort } from '../lib/fs-helpers.js';
|
|
7
|
-
import { validateExistingPath } from '../lib/
|
|
7
|
+
import { validateExistingPath } from '../lib/paths.js';
|
|
8
8
|
import { DiffFilesInputSchema, DiffFilesOutputSchema } from '../schemas.js';
|
|
9
9
|
import { buildResourceLink, buildToolErrorResponse, buildToolResponse, executeToolWithDiagnostics, maybeExternalizeTextContent, READ_ONLY_TOOL_ANNOTATIONS, withDefaultIcons, withValidatedArgs, wrapToolHandler, } from './shared.js';
|
|
10
10
|
import { registerToolTaskIfAvailable } from './task-support.js';
|
|
@@ -13,7 +13,7 @@ export const DIFF_FILES_TOOL = {
|
|
|
13
13
|
title: 'Diff Files',
|
|
14
14
|
description: 'Generate a unified diff between two files. ' +
|
|
15
15
|
'Output feeds directly into `apply_patch`. ' +
|
|
16
|
-
'
|
|
16
|
+
'`isIdentical=true` means files match \u2014 no patch needed.',
|
|
17
17
|
inputSchema: DiffFilesInputSchema,
|
|
18
18
|
outputSchema: DiffFilesOutputSchema,
|
|
19
19
|
annotations: READ_ONLY_TOOL_ANNOTATIONS,
|
package/dist/tools/edit-file.js
CHANGED
|
@@ -1,28 +1,24 @@
|
|
|
1
1
|
import * as fs from 'node:fs/promises';
|
|
2
2
|
import * as path from 'node:path';
|
|
3
3
|
import RE2 from 're2';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import { MAX_TEXT_FILE_SIZE } from '../lib/constants.js';
|
|
5
|
+
import { ErrorCode, McpError } from '../lib/errors.js';
|
|
6
|
+
import { atomicWriteFile, withAbort } from '../lib/fs-helpers.js';
|
|
7
|
+
import { assertAllowedFileAccess, validateExistingPath } from '../lib/paths.js';
|
|
7
8
|
import { EditFileInputSchema, EditFileOutputSchema } from '../schemas.js';
|
|
8
9
|
import { buildToolErrorResponse, buildToolResponse, DESTRUCTIVE_WRITE_TOOL_ANNOTATIONS, executeToolWithDiagnostics, withDefaultIcons, withValidatedArgs, wrapToolHandler, } from './shared.js';
|
|
9
10
|
import { registerToolTaskIfAvailable } from './task-support.js';
|
|
10
11
|
export const EDIT_FILE_TOOL = {
|
|
11
12
|
name: 'edit',
|
|
12
13
|
title: 'Edit File',
|
|
13
|
-
description: '
|
|
14
|
-
'
|
|
15
|
-
'`
|
|
16
|
-
'Use `dryRun: true` to validate edits before writing.',
|
|
14
|
+
description: 'Apply sequential literal string replacements to a file (first occurrence per edit). ' +
|
|
15
|
+
'`oldText` must match exactly \u2014 include 3\u20135 lines of context for unique targeting. ' +
|
|
16
|
+
'Use `dryRun:true` to preview.',
|
|
17
17
|
inputSchema: EditFileInputSchema,
|
|
18
18
|
outputSchema: EditFileOutputSchema,
|
|
19
19
|
annotations: DESTRUCTIVE_WRITE_TOOL_ANNOTATIONS,
|
|
20
|
-
nuances: [
|
|
21
|
-
|
|
22
|
-
],
|
|
23
|
-
gotchas: [
|
|
24
|
-
'`oldText` must match exactly; unmatched items are reported in `unmatchedEdits`.',
|
|
25
|
-
],
|
|
20
|
+
nuances: ['Each edit applies to the output of the previous edit.'],
|
|
21
|
+
gotchas: ['Unmatched `oldText` entries listed in `unmatchedEdits`.'],
|
|
26
22
|
};
|
|
27
23
|
function escapeRegExp(string) {
|
|
28
24
|
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
@@ -88,6 +84,11 @@ function applyEdits(content, edits, ignoreWhitespace) {
|
|
|
88
84
|
}
|
|
89
85
|
export async function handleEditFile(args, signal) {
|
|
90
86
|
const validPath = await validateExistingPath(args.path, signal);
|
|
87
|
+
assertAllowedFileAccess(args.path, validPath);
|
|
88
|
+
const stats = await withAbort(fs.stat(validPath), signal);
|
|
89
|
+
if (stats.size > MAX_TEXT_FILE_SIZE) {
|
|
90
|
+
throw new McpError(ErrorCode.E_TOO_LARGE, `File too large for edit: ${args.path} (${stats.size} bytes > ${MAX_TEXT_FILE_SIZE} bytes)`, args.path, { size: stats.size, maxFileSize: MAX_TEXT_FILE_SIZE });
|
|
91
|
+
}
|
|
91
92
|
const content = await fs.readFile(validPath, { encoding: 'utf-8', signal });
|
|
92
93
|
const { content: newContent, appliedEdits, unmatchedEdits, lineRange, } = applyEdits(content, args.edits, args.ignoreWhitespace);
|
|
93
94
|
const structured = {
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
import * as path from 'node:path';
|
|
2
|
-
import { formatOperationSummary, joinLines } from '../config.js';
|
|
3
2
|
import { DEFAULT_EXCLUDE_PATTERNS } from '../lib/constants.js';
|
|
4
3
|
import { ErrorCode } from '../lib/errors.js';
|
|
5
|
-
import { listDirectory } from '../lib/file-operations/
|
|
4
|
+
import { listDirectory } from '../lib/file-operations/metadata.js';
|
|
5
|
+
import { formatOperationSummary, joinLines } from '../config.js';
|
|
6
6
|
import { ListDirectoryInputSchema, ListDirectoryOutputSchema, } from '../schemas.js';
|
|
7
7
|
import { buildToolErrorResponse, buildToolResponse, decodeOffsetCursor, encodeOffsetCursor, executeToolWithDiagnostics, READ_ONLY_TOOL_ANNOTATIONS, resolvePathOrRoot, withDefaultIcons, withValidatedArgs, wrapToolHandler, } from './shared.js';
|
|
8
8
|
import { registerToolTaskIfAvailable } from './task-support.js';
|
|
9
9
|
export const LIST_DIRECTORY_TOOL = {
|
|
10
10
|
name: 'ls',
|
|
11
11
|
title: 'List Directory',
|
|
12
|
-
description: 'List
|
|
13
|
-
'
|
|
14
|
-
'
|
|
15
|
-
'Use includeIgnored=true to include ignored directories like node_modules. ' +
|
|
16
|
-
'For recursive searches, use find instead.',
|
|
12
|
+
description: 'List immediate directory contents (non-recursive): name, path, type, size, modified date. ' +
|
|
13
|
+
'Omit path for workspace root. `includeIgnored=true` for node_modules etc. ' +
|
|
14
|
+
'For recursive search, use `find`.',
|
|
17
15
|
inputSchema: ListDirectoryInputSchema,
|
|
18
16
|
outputSchema: ListDirectoryOutputSchema,
|
|
19
17
|
annotations: READ_ONLY_TOOL_ANNOTATIONS,
|
package/dist/tools/move-file.js
CHANGED
|
@@ -2,7 +2,7 @@ import * as fs from 'node:fs/promises';
|
|
|
2
2
|
import * as path from 'node:path';
|
|
3
3
|
import { ErrorCode, formatUnknownErrorMessage, isNodeError, McpError, } from '../lib/errors.js';
|
|
4
4
|
import { withAbort } from '../lib/fs-helpers.js';
|
|
5
|
-
import { validateExistingPath, validatePathForWrite, } from '../lib/
|
|
5
|
+
import { assertAllowedFileAccess, validateExistingPath, validatePathForWrite, } from '../lib/paths.js';
|
|
6
6
|
import { MoveFileInputSchema, MoveFileOutputSchema } from '../schemas.js';
|
|
7
7
|
import { buildToolErrorResponse, buildToolResponse, DESTRUCTIVE_WRITE_TOOL_ANNOTATIONS, executeToolWithDiagnostics, withDefaultIcons, withValidatedArgs, wrapToolHandler, } from './shared.js';
|
|
8
8
|
import { registerToolTaskIfAvailable } from './task-support.js';
|
|
@@ -48,6 +48,7 @@ export async function handleMoveFile(args, signal) {
|
|
|
48
48
|
let validSource;
|
|
49
49
|
try {
|
|
50
50
|
validSource = await validateExistingPath(src, signal);
|
|
51
|
+
assertAllowedFileAccess(src, validSource);
|
|
51
52
|
}
|
|
52
53
|
catch (error) {
|
|
53
54
|
failed.push({
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import * as path from 'node:path';
|
|
2
2
|
import { DEFAULT_READ_MANY_MAX_TOTAL_SIZE, DEFAULT_SEARCH_TIMEOUT_MS, } from '../lib/constants.js';
|
|
3
3
|
import { ErrorCode } from '../lib/errors.js';
|
|
4
|
-
import { readMultipleFiles } from '../lib/file-operations/
|
|
4
|
+
import { readMultipleFiles } from '../lib/file-operations/metadata.js';
|
|
5
5
|
import { ReadMultipleFilesInputSchema, ReadMultipleFilesOutputSchema, } from '../schemas.js';
|
|
6
6
|
import { buildBatchCompletionSuffix, buildBatchPathContext, buildResourceLink, buildToolErrorResponse, buildToolResponse, createBatchProgressCallbacks, executeToolWithDiagnostics, maybeExternalizeTextContent, READ_ONLY_TOOL_ANNOTATIONS, resolveFinalProgressCurrent, withDefaultIcons, withValidatedArgs, wrapToolHandler, } from './shared.js';
|
|
7
7
|
import { registerToolTaskIfAvailable } from './task-support.js';
|
|
8
8
|
export const READ_MULTIPLE_FILES_TOOL = {
|
|
9
9
|
name: 'read_many',
|
|
10
10
|
title: 'Read Multiple Files',
|
|
11
|
-
description: 'Read multiple text files in
|
|
12
|
-
'
|
|
13
|
-
'For single file, use read for simpler output.',
|
|
11
|
+
description: 'Read multiple text files in one request with contents and metadata. ' +
|
|
12
|
+
'For a single file, use `read`.',
|
|
14
13
|
inputSchema: ReadMultipleFilesInputSchema,
|
|
15
14
|
outputSchema: ReadMultipleFilesOutputSchema,
|
|
16
15
|
annotations: READ_ONLY_TOOL_ANNOTATIONS,
|
package/dist/tools/read.js
CHANGED
|
@@ -8,9 +8,9 @@ import { registerToolTaskIfAvailable } from './task-support.js';
|
|
|
8
8
|
export const READ_FILE_TOOL = {
|
|
9
9
|
name: 'read',
|
|
10
10
|
title: 'Read File',
|
|
11
|
-
description: 'Read
|
|
12
|
-
'Use head
|
|
13
|
-
'For multiple files, use read_many
|
|
11
|
+
description: 'Read text file contents. ' +
|
|
12
|
+
'Use `head` to preview first N lines of large files. ' +
|
|
13
|
+
'For multiple files, use `read_many`.',
|
|
14
14
|
inputSchema: ReadFileInputSchema,
|
|
15
15
|
outputSchema: ReadFileOutputSchema,
|
|
16
16
|
annotations: READ_ONLY_TOOL_ANNOTATIONS,
|
|
@@ -5,28 +5,26 @@ import RE2 from 're2';
|
|
|
5
5
|
import safeRegex from 'safe-regex2';
|
|
6
6
|
import { DEFAULT_EXCLUDE_PATTERNS, MAX_TEXT_FILE_SIZE, PARALLEL_CONCURRENCY, } from '../lib/constants.js';
|
|
7
7
|
import { ErrorCode, formatUnknownErrorMessage, McpError, } from '../lib/errors.js';
|
|
8
|
-
import { globEntries } from '../lib/file-operations/
|
|
8
|
+
import { globEntries } from '../lib/file-operations/traversal.js';
|
|
9
9
|
import { atomicWriteFile, withAbort } from '../lib/fs-helpers.js';
|
|
10
|
-
import { validateExistingPath, validatePathForWrite
|
|
11
|
-
import { reportPeriodicProgress } from '../lib/
|
|
10
|
+
import { validateExistingPath, validatePathForWrite } from '../lib/paths.js';
|
|
11
|
+
import { reportPeriodicProgress } from '../lib/utils.js';
|
|
12
12
|
import { SearchAndReplaceInputSchema, SearchAndReplaceOutputSchema, } from '../schemas.js';
|
|
13
13
|
import { buildToolErrorResponse, buildToolResponse, createToolProgressSession, DESTRUCTIVE_WRITE_TOOL_ANNOTATIONS, executeToolWithDiagnostics, resolveFinalProgressCurrent, resolvePathOrRoot, withDefaultIcons, withValidatedArgs, wrapToolHandler, } from './shared.js';
|
|
14
14
|
import { registerToolTaskIfAvailable } from './task-support.js';
|
|
15
15
|
export const SEARCH_AND_REPLACE_TOOL = {
|
|
16
16
|
name: 'search_and_replace',
|
|
17
17
|
title: 'Search and Replace',
|
|
18
|
-
description: '
|
|
19
|
-
'Replaces ALL occurrences
|
|
20
|
-
'
|
|
21
|
-
'
|
|
22
|
-
'Returns a unified diff of changes in `dryRun` mode. ' +
|
|
23
|
-
'Literal mode (default) matches exact text; `isRegex: true` enables RE2 regex with capture groups ($1, $2).',
|
|
18
|
+
description: 'Bulk search-and-replace across files matching a glob. ' +
|
|
19
|
+
'Replaces ALL occurrences per file (unlike `edit`: first only). ' +
|
|
20
|
+
'Always `dryRun:true` first \u2014 returns a unified diff. ' +
|
|
21
|
+
'Literal matching by default; `isRegex:true` enables RE2 with capture groups ($1, $2).',
|
|
24
22
|
inputSchema: SearchAndReplaceInputSchema,
|
|
25
23
|
outputSchema: SearchAndReplaceOutputSchema,
|
|
26
24
|
annotations: DESTRUCTIVE_WRITE_TOOL_ANNOTATIONS,
|
|
27
25
|
taskSupport: 'optional',
|
|
28
26
|
gotchas: [
|
|
29
|
-
'
|
|
27
|
+
'Replaces ALL occurrences — not just the first. Use `edit` for single replacements.',
|
|
30
28
|
],
|
|
31
29
|
nuances: [
|
|
32
30
|
'Changed-file sample and failure sample are capped/truncated in output.',
|
package/dist/tools/roots.js
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
import { joinLines } from '../config.js';
|
|
2
1
|
import { ErrorCode } from '../lib/errors.js';
|
|
3
|
-
import { getAllowedDirectories } from '../lib/
|
|
2
|
+
import { getAllowedDirectories } from '../lib/paths.js';
|
|
3
|
+
import { joinLines } from '../config.js';
|
|
4
4
|
import { ListAllowedDirectoriesInputSchema, ListAllowedDirectoriesOutputSchema, } from '../schemas.js';
|
|
5
5
|
import { buildToolErrorResponse, buildToolResponse, executeToolWithDiagnostics, READ_ONLY_TOOL_ANNOTATIONS, withDefaultIcons, withValidatedArgs, wrapToolHandler, } from './shared.js';
|
|
6
6
|
import { registerToolTaskIfAvailable } from './task-support.js';
|
|
7
7
|
export const LIST_ALLOWED_DIRECTORIES_TOOL = {
|
|
8
8
|
name: 'roots',
|
|
9
9
|
title: 'Workspace Roots',
|
|
10
|
-
description: 'List
|
|
11
|
-
'Call this first to see available directories. ' +
|
|
12
|
-
'All other tools only work within these directories.',
|
|
10
|
+
description: 'List allowed workspace roots. Call first \u2014 all other tools are scoped to these directories.',
|
|
13
11
|
inputSchema: ListAllowedDirectoriesInputSchema,
|
|
14
12
|
outputSchema: ListAllowedDirectoriesOutputSchema,
|
|
15
13
|
annotations: READ_ONLY_TOOL_ANNOTATIONS,
|
|
16
|
-
nuances: ['
|
|
14
|
+
nuances: ['Returns absolute paths of all allowed directories.'],
|
|
17
15
|
};
|
|
18
16
|
function buildTextRoots(dirs) {
|
|
19
17
|
if (dirs.length === 0) {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as path from 'node:path';
|
|
2
2
|
import RE2 from 're2';
|
|
3
|
-
import { formatOperationSummary, joinLines } from '../config.js';
|
|
4
3
|
import { DEFAULT_EXCLUDE_PATTERNS } from '../lib/constants.js';
|
|
5
4
|
import { ErrorCode, formatUnknownErrorMessage, McpError, } from '../lib/errors.js';
|
|
6
|
-
import { searchContent } from '../lib/file-operations/search
|
|
5
|
+
import { searchContent } from '../lib/file-operations/search.js';
|
|
6
|
+
import { formatOperationSummary, joinLines } from '../config.js';
|
|
7
7
|
import { SearchContentInputSchema, SearchContentOutputSchema, } from '../schemas.js';
|
|
8
8
|
import { buildResourceLink, buildToolErrorResponse, buildToolResponse, createToolProgressSession, executeToolWithDiagnostics, READ_ONLY_TOOL_ANNOTATIONS, resolveFinalProgressCurrent, resolvePathOrRoot, withDefaultIcons, withValidatedArgs, wrapToolHandler, } from './shared.js';
|
|
9
9
|
import { registerToolTaskIfAvailable } from './task-support.js';
|
|
@@ -11,20 +11,18 @@ const MAX_INLINE_MATCHES = parseInt(process.env['FS_CONTEXT_MAX_INLINE_MATCHES']
|
|
|
11
11
|
export const SEARCH_CONTENT_TOOL = {
|
|
12
12
|
name: 'grep',
|
|
13
13
|
title: 'Search Content',
|
|
14
|
-
description: 'Search for text
|
|
15
|
-
'
|
|
16
|
-
'
|
|
17
|
-
'Use `filePattern` to scope by file type (e.g. `**/*.ts`) and avoid noisy results. ' +
|
|
18
|
-
'Use includeHidden=true to include hidden files and directories.',
|
|
14
|
+
description: 'Search file contents for text (grep-like). Returns matching lines. ' +
|
|
15
|
+
'Scope with `filePattern` (e.g. `**/*.ts`) to reduce noise. ' +
|
|
16
|
+
'`includeHidden=true` for dotfiles.',
|
|
19
17
|
inputSchema: SearchContentInputSchema,
|
|
20
18
|
outputSchema: SearchContentOutputSchema,
|
|
21
19
|
annotations: READ_ONLY_TOOL_ANNOTATIONS,
|
|
22
20
|
nuances: [
|
|
23
|
-
'Inline
|
|
21
|
+
'Inline results capped at 50 matches; full results via `resourceUri`.',
|
|
24
22
|
'Skips binary and oversized files.',
|
|
25
23
|
],
|
|
26
24
|
gotchas: [
|
|
27
|
-
'Skips binary
|
|
25
|
+
'Skips binary/oversized files silently — verify with `stat` if no matches.',
|
|
28
26
|
],
|
|
29
27
|
taskSupport: 'optional',
|
|
30
28
|
};
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import * as path from 'node:path';
|
|
2
|
-
import { formatOperationSummary, joinLines } from '../config.js';
|
|
3
2
|
import { DEFAULT_EXCLUDE_PATTERNS, DEFAULT_SEARCH_TIMEOUT_MS, } from '../lib/constants.js';
|
|
4
3
|
import { ErrorCode } from '../lib/errors.js';
|
|
5
|
-
import { searchFiles } from '../lib/file-operations/search
|
|
4
|
+
import { searchFiles } from '../lib/file-operations/search.js';
|
|
5
|
+
import { formatOperationSummary, joinLines } from '../config.js';
|
|
6
6
|
import { SearchFilesInputSchema, SearchFilesOutputSchema } from '../schemas.js';
|
|
7
7
|
import { buildToolErrorResponse, buildToolResponse, createProgressReporter, decodeOffsetCursor, encodeOffsetCursor, executeToolWithDiagnostics, notifyProgress, READ_ONLY_TOOL_ANNOTATIONS, resolvePathOrRoot, withDefaultIcons, withValidatedArgs, wrapToolHandler, } from './shared.js';
|
|
8
8
|
import { registerToolTaskIfAvailable } from './task-support.js';
|
|
9
9
|
export const SEARCH_FILES_TOOL = {
|
|
10
10
|
name: 'find',
|
|
11
11
|
title: 'Find Files',
|
|
12
|
-
description: 'Find files by glob pattern (e.g
|
|
13
|
-
'
|
|
14
|
-
'For text search inside files, use grep. ' +
|
|
15
|
-
'To bulk-edit the matched files, pass the same glob pattern to search_and_replace.',
|
|
12
|
+
description: 'Find files by glob pattern (e.g. `**/*.ts`). Returns matching files with metadata. ' +
|
|
13
|
+
'For content search, use `grep`. For bulk edits, pass the same glob to `search_and_replace`.',
|
|
16
14
|
inputSchema: SearchFilesInputSchema,
|
|
17
15
|
outputSchema: SearchFilesOutputSchema,
|
|
18
16
|
annotations: READ_ONLY_TOOL_ANNOTATIONS,
|
package/dist/tools/shared.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { ContentBlock, Icon, ProgressNotificationParams } from '@modelcontextprotocol/sdk/types.js';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import type { FileInfo } from '../config.js';
|
|
4
3
|
import { ErrorCode } from '../lib/errors.js';
|
|
5
4
|
import type { ResourceStore } from '../lib/resource-store.js';
|
|
5
|
+
import type { FileInfo } from '../config.js';
|
|
6
6
|
export { type ToolContract } from './contract.js';
|
|
7
7
|
export declare const READ_ONLY_TOOL_ANNOTATIONS: {
|
|
8
8
|
readonly readOnlyHint: true;
|
|
@@ -12,6 +12,7 @@ export declare const READ_ONLY_TOOL_ANNOTATIONS: {
|
|
|
12
12
|
};
|
|
13
13
|
export declare const DESTRUCTIVE_WRITE_TOOL_ANNOTATIONS: {
|
|
14
14
|
readonly readOnlyHint: false;
|
|
15
|
+
readonly idempotentHint: false;
|
|
15
16
|
readonly destructiveHint: true;
|
|
16
17
|
readonly openWorldHint: false;
|
|
17
18
|
};
|
package/dist/tools/shared.js
CHANGED
|
@@ -5,7 +5,7 @@ import { parseTrueEnvFlag } from '../lib/constants.js';
|
|
|
5
5
|
import { createDetailedError, ErrorCode, formatDetailedError, getSuggestion, McpError, } from '../lib/errors.js';
|
|
6
6
|
import { createTimedAbortSignal } from '../lib/fs-helpers.js';
|
|
7
7
|
import { withToolDiagnostics } from '../lib/observability.js';
|
|
8
|
-
import { getAllowedDirectories } from '../lib/
|
|
8
|
+
import { getAllowedDirectories } from '../lib/paths.js';
|
|
9
9
|
export {} from './contract.js';
|
|
10
10
|
const MAX_INLINE_CONTENT_CHARS = parseInt(process.env['FS_CONTEXT_MAX_INLINE_CHARS'] ?? '', 10) || 20_000;
|
|
11
11
|
const MAX_INLINE_PREVIEW_CHARS = 4_000;
|
|
@@ -24,6 +24,7 @@ export const READ_ONLY_TOOL_ANNOTATIONS = {
|
|
|
24
24
|
};
|
|
25
25
|
export const DESTRUCTIVE_WRITE_TOOL_ANNOTATIONS = {
|
|
26
26
|
readOnlyHint: false,
|
|
27
|
+
idempotentHint: false,
|
|
27
28
|
destructiveHint: true,
|
|
28
29
|
openWorldHint: false,
|
|
29
30
|
};
|
package/dist/tools/stat-many.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { formatBytes, joinLines } from '../config.js';
|
|
2
1
|
import { DEFAULT_SEARCH_TIMEOUT_MS } from '../lib/constants.js';
|
|
3
2
|
import { ErrorCode } from '../lib/errors.js';
|
|
4
|
-
import { getMultipleFileInfo } from '../lib/file-operations/
|
|
3
|
+
import { getMultipleFileInfo } from '../lib/file-operations/metadata.js';
|
|
4
|
+
import { formatBytes, joinLines } from '../config.js';
|
|
5
5
|
import { GetMultipleFileInfoInputSchema, GetMultipleFileInfoOutputSchema, } from '../schemas.js';
|
|
6
6
|
import { buildBatchCompletionSuffix, buildBatchPathContext, buildFileInfoPayload, buildToolErrorResponse, buildToolResponse, createBatchProgressCallbacks, executeToolWithDiagnostics, READ_ONLY_TOOL_ANNOTATIONS, resolveFinalProgressCurrent, withDefaultIcons, withValidatedArgs, wrapToolHandler, } from './shared.js';
|
|
7
7
|
import { registerToolTaskIfAvailable } from './task-support.js';
|
|
8
8
|
export const GET_MULTIPLE_FILE_INFO_TOOL = {
|
|
9
9
|
name: 'stat_many',
|
|
10
10
|
title: 'Get Multiple File Info',
|
|
11
|
-
description: 'Get metadata
|
|
11
|
+
description: 'Get metadata for multiple files/directories in one request. ' +
|
|
12
|
+
'Use `tokenEstimate` (size\u00f74) to pre-screen token cost before reading.',
|
|
12
13
|
inputSchema: GetMultipleFileInfoInputSchema,
|
|
13
14
|
outputSchema: GetMultipleFileInfoOutputSchema,
|
|
14
15
|
annotations: READ_ONLY_TOOL_ANNOTATIONS,
|
package/dist/tools/stat.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import * as path from 'node:path';
|
|
2
|
-
import { formatBytes, joinLines } from '../config.js';
|
|
3
2
|
import { DEFAULT_SEARCH_TIMEOUT_MS } from '../lib/constants.js';
|
|
4
3
|
import { ErrorCode } from '../lib/errors.js';
|
|
5
|
-
import { getFileInfo } from '../lib/file-operations/
|
|
4
|
+
import { getFileInfo } from '../lib/file-operations/metadata.js';
|
|
5
|
+
import { formatBytes, joinLines } from '../config.js';
|
|
6
6
|
import { GetFileInfoInputSchema, GetFileInfoOutputSchema } from '../schemas.js';
|
|
7
7
|
import { buildFileInfoPayload, buildToolErrorResponse, buildToolResponse, executeToolWithDiagnostics, READ_ONLY_TOOL_ANNOTATIONS, withDefaultIcons, withValidatedArgs, wrapToolHandler, } from './shared.js';
|
|
8
8
|
export const GET_FILE_INFO_TOOL = {
|
|
9
9
|
name: 'stat',
|
|
10
10
|
title: 'Get File Info',
|
|
11
|
-
description: 'Get metadata
|
|
11
|
+
description: 'Get file/directory metadata: size, modified, permissions, mime, tokenEstimate. ' +
|
|
12
|
+
'Use `tokenEstimate` (size\u00f74) to pre-screen token cost before reading.',
|
|
12
13
|
inputSchema: GetFileInfoInputSchema,
|
|
13
14
|
outputSchema: GetFileInfoOutputSchema,
|
|
14
15
|
annotations: READ_ONLY_TOOL_ANNOTATIONS,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { channel } from 'node:diagnostics_channel';
|
|
2
2
|
import { CallToolResultSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
3
3
|
import { ErrorCode, McpError } from '../lib/errors.js';
|
|
4
|
-
import { isRecord } from '../lib/
|
|
4
|
+
import { isRecord } from '../lib/utils.js';
|
|
5
5
|
import { buildToolErrorResponse, maybeStripStructuredContentFromResult, withDefaultIcons, } from './shared.js';
|
|
6
6
|
function isExperimentalTaskRegistration(value) {
|
|
7
7
|
if (!value || typeof value !== 'object')
|
package/dist/tools/tree.js
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import * as path from 'node:path';
|
|
2
2
|
import { DEFAULT_SEARCH_TIMEOUT_MS } from '../lib/constants.js';
|
|
3
3
|
import { ErrorCode } from '../lib/errors.js';
|
|
4
|
-
import { formatTreeAscii, treeDirectory } from '../lib/file-operations/
|
|
4
|
+
import { formatTreeAscii, treeDirectory, } from '../lib/file-operations/metadata.js';
|
|
5
5
|
import { TreeInputSchema, TreeOutputSchema } from '../schemas.js';
|
|
6
6
|
import { buildToolErrorResponse, buildToolResponse, createProgressReporter, executeToolWithDiagnostics, notifyProgress, READ_ONLY_TOOL_ANNOTATIONS, resolvePathOrRoot, withDefaultIcons, withValidatedArgs, wrapToolHandler, } from './shared.js';
|
|
7
7
|
import { registerToolTaskIfAvailable } from './task-support.js';
|
|
8
8
|
export const TREE_TOOL = {
|
|
9
9
|
name: 'tree',
|
|
10
10
|
title: 'Tree',
|
|
11
|
-
description: 'Render a directory tree (bounded recursion). ' +
|
|
12
|
-
'
|
|
13
|
-
'Note: maxDepth=0 returns only the root node with empty children array.',
|
|
11
|
+
description: 'Render a directory tree (bounded recursion). Returns ASCII tree + structured JSON. ' +
|
|
12
|
+
'`maxDepth=0` returns only the root node.',
|
|
14
13
|
inputSchema: TreeInputSchema,
|
|
15
14
|
outputSchema: TreeOutputSchema,
|
|
16
15
|
annotations: READ_ONLY_TOOL_ANNOTATIONS,
|
package/dist/tools/write-file.js
CHANGED
|
@@ -2,7 +2,7 @@ import * as fs from 'node:fs/promises';
|
|
|
2
2
|
import * as path from 'node:path';
|
|
3
3
|
import { ErrorCode } from '../lib/errors.js';
|
|
4
4
|
import { atomicWriteFile, withAbort } from '../lib/fs-helpers.js';
|
|
5
|
-
import { validatePathForWrite } from '../lib/
|
|
5
|
+
import { validatePathForWrite } from '../lib/paths.js';
|
|
6
6
|
import { WriteFileInputSchema, WriteFileOutputSchema } from '../schemas.js';
|
|
7
7
|
import { buildToolErrorResponse, buildToolResponse, DESTRUCTIVE_WRITE_TOOL_ANNOTATIONS, executeToolWithDiagnostics, withDefaultIcons, withValidatedArgs, wrapToolHandler, } from './shared.js';
|
|
8
8
|
import { registerToolTaskIfAvailable } from './task-support.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@j0hanz/filesystem-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.0",
|
|
4
4
|
"mcpName": "io.github.j0hanz/filesystem-mcp",
|
|
5
5
|
"description": "MCP Server that enables LLMs to interact with the local filesystem.",
|
|
6
6
|
"type": "module",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"commander": "^14.0.3",
|
|
69
69
|
"diff": "^8.0.3",
|
|
70
70
|
"ignore": "^7.0.5",
|
|
71
|
-
"re2": "^1.23.
|
|
71
|
+
"re2": "^1.23.3",
|
|
72
72
|
"safe-regex2": "^5.0.0",
|
|
73
73
|
"zod": "^4.3.6"
|
|
74
74
|
},
|
|
@@ -78,8 +78,8 @@
|
|
|
78
78
|
"@types/node": "^24",
|
|
79
79
|
"eslint": "^10.0.2",
|
|
80
80
|
"eslint-config-prettier": "^10.1.8",
|
|
81
|
-
"eslint-plugin-de-morgan": "^2.
|
|
82
|
-
"eslint-plugin-depend": "^1.
|
|
81
|
+
"eslint-plugin-de-morgan": "^2.1.1",
|
|
82
|
+
"eslint-plugin-depend": "^1.5.0",
|
|
83
83
|
"eslint-plugin-sonarjs": "^4.0.0",
|
|
84
84
|
"eslint-plugin-unused-imports": "^4.4.1",
|
|
85
85
|
"jscpd": "^4.0.8",
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { FileInfo, GetMultipleFileInfoResult } from '../../config.js';
|
|
2
|
-
interface FileInfoOptions {
|
|
3
|
-
includeMimeType?: boolean | undefined;
|
|
4
|
-
signal?: AbortSignal | undefined;
|
|
5
|
-
onProgress?: () => void;
|
|
6
|
-
}
|
|
7
|
-
export declare function getFileInfo(filePath: string, options?: FileInfoOptions): Promise<FileInfo>;
|
|
8
|
-
type GetMultipleFileInfoOptions = FileInfoOptions;
|
|
9
|
-
export declare function getMultipleFileInfo(paths: readonly string[], options?: GetMultipleFileInfoOptions): Promise<GetMultipleFileInfoResult>;
|
|
10
|
-
export {};
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import * as fsp from 'node:fs/promises';
|
|
2
|
-
import * as path from 'node:path';
|
|
3
|
-
import { getMimeType, PARALLEL_CONCURRENCY } from '../constants.js';
|
|
4
|
-
import { isAbortError } from '../errors.js';
|
|
5
|
-
import { assertNotAborted, getFileType, isHidden, processInParallel, withAbort, } from '../fs-helpers.js';
|
|
6
|
-
import { assertAllowedFileAccess } from '../path-policy.js';
|
|
7
|
-
import { validateExistingPathDetailed } from '../path-validation.js';
|
|
8
|
-
import { applyIndexedErrors, applyIndexedValues } from './common.js';
|
|
9
|
-
const PERM_STRINGS = [
|
|
10
|
-
'---',
|
|
11
|
-
'--x',
|
|
12
|
-
'-w-',
|
|
13
|
-
'-wx',
|
|
14
|
-
'r--',
|
|
15
|
-
'r-x',
|
|
16
|
-
'rw-',
|
|
17
|
-
'rwx',
|
|
18
|
-
];
|
|
19
|
-
const UNKNOWN_PATH = '(unknown)';
|
|
20
|
-
function getPermissions(mode) {
|
|
21
|
-
const ownerIndex = (mode >> 6) & 0b111;
|
|
22
|
-
const groupIndex = (mode >> 3) & 0b111;
|
|
23
|
-
const otherIndex = mode & 0b111;
|
|
24
|
-
const owner = PERM_STRINGS[ownerIndex] ?? '---';
|
|
25
|
-
const group = PERM_STRINGS[groupIndex] ?? '---';
|
|
26
|
-
const other = PERM_STRINGS[otherIndex] ?? '---';
|
|
27
|
-
return `${owner}${group}${other}`;
|
|
28
|
-
}
|
|
29
|
-
function buildFileInfoResult(name, requestedPath, isSymlink, stats, mimeType, symlinkTarget) {
|
|
30
|
-
const tokenEstimate = stats.isFile() ? Math.ceil(stats.size / 4) : undefined;
|
|
31
|
-
return {
|
|
32
|
-
name,
|
|
33
|
-
path: requestedPath,
|
|
34
|
-
type: isSymlink ? 'symlink' : getFileType(stats),
|
|
35
|
-
size: stats.size,
|
|
36
|
-
...(tokenEstimate !== undefined ? { tokenEstimate } : {}),
|
|
37
|
-
created: stats.birthtime,
|
|
38
|
-
modified: stats.mtime,
|
|
39
|
-
accessed: stats.atime,
|
|
40
|
-
permissions: getPermissions(stats.mode),
|
|
41
|
-
isHidden: isHidden(name),
|
|
42
|
-
...(mimeType !== undefined ? { mimeType } : {}),
|
|
43
|
-
...(symlinkTarget !== undefined ? { symlinkTarget } : {}),
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
async function getSymlinkTarget(pathToRead, signal) {
|
|
47
|
-
assertNotAborted(signal);
|
|
48
|
-
try {
|
|
49
|
-
return await withAbort(fsp.readlink(pathToRead), signal);
|
|
50
|
-
}
|
|
51
|
-
catch (error) {
|
|
52
|
-
if (isAbortError(error))
|
|
53
|
-
throw error;
|
|
54
|
-
return undefined;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
export async function getFileInfo(filePath, options = {}) {
|
|
58
|
-
const { signal } = options;
|
|
59
|
-
assertNotAborted(signal);
|
|
60
|
-
const { requestedPath, resolvedPath, isSymlink } = await validateExistingPathDetailed(filePath, signal);
|
|
61
|
-
assertAllowedFileAccess(requestedPath, resolvedPath);
|
|
62
|
-
const name = path.basename(requestedPath);
|
|
63
|
-
const ext = path.extname(name).toLowerCase();
|
|
64
|
-
const includeMimeType = options.includeMimeType !== false;
|
|
65
|
-
const mimeType = includeMimeType && ext.length > 0 ? getMimeType(ext) : undefined;
|
|
66
|
-
const symlinkTarget = isSymlink
|
|
67
|
-
? await getSymlinkTarget(requestedPath, signal)
|
|
68
|
-
: undefined;
|
|
69
|
-
const stats = await withAbort(fsp.stat(resolvedPath), signal);
|
|
70
|
-
return buildFileInfoResult(name, requestedPath, isSymlink, stats, mimeType, symlinkTarget);
|
|
71
|
-
}
|
|
72
|
-
function buildEmptyResult() {
|
|
73
|
-
return {
|
|
74
|
-
results: [],
|
|
75
|
-
summary: { total: 0, succeeded: 0, failed: 0, totalSize: 0 },
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
async function processFileInfo(filePath, options) {
|
|
79
|
-
const info = await getFileInfo(filePath, options);
|
|
80
|
-
return { path: filePath, info };
|
|
81
|
-
}
|
|
82
|
-
function buildIndexedPathTasks(paths) {
|
|
83
|
-
const tasks = [];
|
|
84
|
-
for (let index = 0; index < paths.length; index += 1) {
|
|
85
|
-
const filePath = paths[index];
|
|
86
|
-
if (filePath === undefined)
|
|
87
|
-
continue;
|
|
88
|
-
tasks.push({ filePath, index });
|
|
89
|
-
}
|
|
90
|
-
return tasks;
|
|
91
|
-
}
|
|
92
|
-
async function readFileInfoInParallel(paths, options) {
|
|
93
|
-
return processInParallel(buildIndexedPathTasks(paths), async ({ filePath, index }) => {
|
|
94
|
-
const value = await processFileInfo(filePath, options);
|
|
95
|
-
options.onProgress?.();
|
|
96
|
-
return { index, value };
|
|
97
|
-
}, PARALLEL_CONCURRENCY, options.signal);
|
|
98
|
-
}
|
|
99
|
-
function calculateSummary(results) {
|
|
100
|
-
let succeeded = 0;
|
|
101
|
-
let failed = 0;
|
|
102
|
-
let totalSize = 0;
|
|
103
|
-
for (const result of results) {
|
|
104
|
-
if (result.info !== undefined) {
|
|
105
|
-
succeeded++;
|
|
106
|
-
totalSize += result.info.size;
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
failed++;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
return {
|
|
113
|
-
total: results.length,
|
|
114
|
-
succeeded,
|
|
115
|
-
failed,
|
|
116
|
-
totalSize,
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
export async function getMultipleFileInfo(paths, options = {}) {
|
|
120
|
-
if (paths.length === 0)
|
|
121
|
-
return buildEmptyResult();
|
|
122
|
-
const output = new Array(paths.length);
|
|
123
|
-
for (let index = 0; index < paths.length; index += 1) {
|
|
124
|
-
output[index] = { path: paths[index] ?? UNKNOWN_PATH };
|
|
125
|
-
}
|
|
126
|
-
const { results, errors } = await readFileInfoInParallel(paths, options);
|
|
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
|
-
});
|
|
139
|
-
return {
|
|
140
|
-
results: output,
|
|
141
|
-
summary: calculateSummary(output),
|
|
142
|
-
};
|
|
143
|
-
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { type Ignore } from 'ignore';
|
|
2
|
-
export declare function loadRootGitignore(root: string, signal?: AbortSignal): Promise<Ignore | null>;
|
|
3
|
-
export declare function isIgnoredByGitignore(matcher: Ignore, root: string, absolutePath: string, options?: {
|
|
4
|
-
isDirectory?: boolean;
|
|
5
|
-
relativePath?: string;
|
|
6
|
-
}): boolean;
|