@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
package/dist/cli-help.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-help.d.ts","sourceRoot":"","sources":["../src/cli-help.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli-help.d.ts","sourceRoot":"","sources":["../src/cli-help.ts"],"names":[],"mappings":"AA+IA,wBAAgB,gBAAgB,IAAI,KAAK,CA8BxC;AAED,wBAAgB,mBAAmB,IAAI,KAAK,CAG3C"}
|
package/dist/cli-help.js
CHANGED
|
@@ -29,7 +29,7 @@ const OPTIONS_HELP = [
|
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
flags: '--allow-sensitive',
|
|
32
|
-
desc: '
|
|
32
|
+
desc: 'Turn off the built-in secret-file denylist (.env, keys, credentials) (env: FS_ALLOW_SENSITIVE)',
|
|
33
33
|
},
|
|
34
34
|
{
|
|
35
35
|
flags: '--root-boundary <path>',
|
|
@@ -39,15 +39,21 @@ const OPTIONS_HELP = [
|
|
|
39
39
|
flags: '--max-file-size <bytes>',
|
|
40
40
|
desc: 'Maximum file size for reads and for one create call, in bytes; the per-message wire limit is 3 × this + 1 MiB (env: FS_MAX_FILE_SIZE)',
|
|
41
41
|
},
|
|
42
|
-
{
|
|
43
|
-
|
|
42
|
+
{
|
|
43
|
+
flags: '--walk-cwd',
|
|
44
|
+
desc: 'Walk up from CWD to find a project root; implies --allow-cwd (env: FS_ALLOW_CWD_WALK)',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
flags: '--deny <pattern>',
|
|
48
|
+
desc: 'Block paths matching this pattern; repeatable (env: FS_DENYLIST)',
|
|
49
|
+
},
|
|
44
50
|
{
|
|
45
51
|
flags: '--allow <pattern>',
|
|
46
52
|
desc: 'Exempt a pattern from the built-in sensitive denylist; repeatable (env: FS_ALLOWLIST)',
|
|
47
53
|
},
|
|
48
54
|
{
|
|
49
55
|
flags: '--allow-missing-roots',
|
|
50
|
-
desc: 'Start even if configured allowed directories do not exist',
|
|
56
|
+
desc: 'Start even if configured allowed directories do not exist (env: FS_ALLOW_MISSING_ROOTS)',
|
|
51
57
|
},
|
|
52
58
|
];
|
|
53
59
|
const ENV_HELP = [
|
|
@@ -64,7 +70,7 @@ const ENV_HELP = [
|
|
|
64
70
|
},
|
|
65
71
|
{
|
|
66
72
|
flags: 'FS_ALLOW_SENSITIVE',
|
|
67
|
-
desc: '
|
|
73
|
+
desc: 'Turn off the built-in secret-file denylist ("true" or "1" enables this)',
|
|
68
74
|
},
|
|
69
75
|
{ flags: 'FS_ROOT_BOUNDARY', desc: 'Path prefix all allowed roots must fall under' },
|
|
70
76
|
{
|
|
@@ -124,7 +130,9 @@ const EXAMPLES_HELP = [
|
|
|
124
130
|
'$ filesystem-mcp --print-config /project',
|
|
125
131
|
];
|
|
126
132
|
export function printHelpAndExit() {
|
|
127
|
-
|
|
133
|
+
// Sized from the longest name so a long one (FS_ALLOW_UNRESTRICTED_HOSTS)
|
|
134
|
+
// never runs into its description.
|
|
135
|
+
const COL = Math.max(...[...OPTIONS_HELP, ...ENV_HELP].map(({ flags }) => flags.length)) + 2;
|
|
128
136
|
// Pad first, colour after: `styleText` honours NO_COLOR, and padding the
|
|
129
137
|
// plain text keeps the columns aligned whether or not colour is on.
|
|
130
138
|
const row = (color, name, desc) => ` ${styleText(color, name.padEnd(COL))}${desc}`;
|
|
@@ -139,7 +147,7 @@ export function printHelpAndExit() {
|
|
|
139
147
|
section('Options:'),
|
|
140
148
|
...OPTIONS_HELP.map(({ flags, desc }) => row('green', flags, desc)),
|
|
141
149
|
'',
|
|
142
|
-
`${section('Environment variables:')} ${dim('(flags
|
|
150
|
+
`${section('Environment variables:')} ${dim('(flags win when both are set; --deny/--allow add to FS_DENYLIST/FS_ALLOWLIST)')}`,
|
|
143
151
|
...ENV_HELP.map(({ flags, desc }) => row('cyan', flags, desc)),
|
|
144
152
|
'',
|
|
145
153
|
section('Examples:'),
|
package/dist/cli-help.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-help.js","sourceRoot":"","sources":["../src/cli-help.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,WAAW,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvD,6EAA6E;AAC7E,6EAA6E;AAC7E,kDAAkD;AAElD,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,WAAW,CAAC;AAOhD,MAAM,YAAY,GAAc;IAC9B,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,wBAAwB,EAAE;IACvD,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,yBAAyB,EAAE;IAC3D,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,sDAAsD,EAAE;IACtF;QACE,KAAK,EAAE,iBAAiB;QACxB,IAAI,EAAE,kDAAkD;KACzD;IACD;QACE,KAAK,EAAE,aAAa;QACpB,IAAI,EAAE,wBAAwB,CAAC,GAAG,mBAAmB,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;KAC3E;IACD,EAAE,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,iDAAiD,EAAE;IACpF;QACE,KAAK,EAAE,qBAAqB;QAC5B,IAAI,EAAE,gGAAgG;KACvG;IACD,EAAE,KAAK,EAAE,oBAAoB,EAAE,IAAI,EAAE,8CAA8C,EAAE;IACrF;QACE,KAAK,EAAE,iBAAiB;QACxB,IAAI,EAAE,mFAAmF;KAC1F;IACD;QACE,KAAK,EAAE,mBAAmB;QAC1B,IAAI,EAAE,kEAAkE;KACzE;IACD;QACE,KAAK,EAAE,wBAAwB;QAC/B,IAAI,EAAE,2EAA2E;KAClF;IACD;QACE,KAAK,EAAE,yBAAyB;QAChC,IAAI,EAAE,uIAAuI;KAC9I;IACD,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,8DAA8D,EAAE;IAC7F,EAAE,KAAK,EAAE,kBAAkB,EAAE,IAAI,EAAE,+CAA+C,EAAE;IACpF;QACE,KAAK,EAAE,mBAAmB;QAC1B,IAAI,EAAE,uFAAuF;KAC9F;IACD;QACE,KAAK,EAAE,uBAAuB;QAC9B,IAAI,EAAE,2DAA2D;KAClE;CACF,CAAC;AAEF,MAAM,QAAQ,GAAc;IAC1B;QACE,KAAK,EAAE,cAAc;QACrB,IAAI,EAAE,4EAA4E;KACnF;IACD,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,mDAAmD,EAAE;IAC/E,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,mBAAmB,EAAE;IACpD,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE;IAC7C;QACE,KAAK,EAAE,gBAAgB;QACvB,IAAI,EAAE,2FAA2F;KAClG;IACD;QACE,KAAK,EAAE,oBAAoB;QAC3B,IAAI,EAAE,2DAA2D;KAClE;IACD,EAAE,KAAK,EAAE,kBAAkB,EAAE,IAAI,EAAE,+CAA+C,EAAE;IACpF;QACE,KAAK,EAAE,kBAAkB;QACzB,IAAI,EAAE,wGAAwG;KAC/G;IACD;QACE,KAAK,EAAE,iBAAiB;QACxB,IAAI,EAAE,qEAAqE;KAC5E;IACD;QACE,KAAK,EAAE,mBAAmB;QAC1B,IAAI,EAAE,sEAAsE;KAC7E;IACD,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,0CAA0C,EAAE;IAC1E;QACE,KAAK,EAAE,cAAc;QACrB,IAAI,EAAE,uGAAuG;KAC9G;IACD;QACE,KAAK,EAAE,wBAAwB;QAC/B,IAAI,EAAE,wFAAwF;KAC/F;IACD;QACE,KAAK,EAAE,kBAAkB;QACzB,IAAI,EAAE,+DAA+D;KACtE;IACD;QACE,KAAK,EAAE,oBAAoB;QAC3B,IAAI,EAAE,iJAAiJ;KACxJ;IACD;QACE,KAAK,EAAE,6BAA6B;QACpC,IAAI,EAAE,6FAA6F;KACpG;IACD,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,gDAAgD,EAAE;IAClF;QACE,KAAK,EAAE,mBAAmB;QAC1B,IAAI,EAAE,yFAAyF;KAChG;IACD;QACE,KAAK,EAAE,iBAAiB;QACxB,IAAI,EAAE,oDAAoD;KAC3D;IACD,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,sCAAsC,EAAE;IACnE;QACE,KAAK,EAAE,sBAAsB;QAC7B,IAAI,EAAE,kEAAkE;KACzE;CACF,CAAC;AAEF,MAAM,aAAa,GAAG;IACpB,uCAAuC;IACvC,8BAA8B;IAC9B,0DAA0D;IAC1D,mDAAmD;IACnD,6CAA6C;IAC7C,0CAA0C;CAC3C,CAAC;AAEF,MAAM,UAAU,gBAAgB;IAC9B,MAAM,GAAG,GAAG,EAAE,CAAC;IACf,yEAAyE;IACzE,oEAAoE;IACpE,MAAM,GAAG,GAAG,CAAC,KAAuB,EAAE,IAAY,EAAE,IAAY,EAAU,EAAE,CAC1E,KAAK,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC;IACnD,MAAM,GAAG,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACvD,MAAM,OAAO,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAEtE,MAAM,KAAK,GAAG;QACZ,EAAE;QACF,GAAG,SAAS,CAAC,MAAM,EAAE,gBAAgB,CAAC,IAAI,GAAG,CAAC,IAAI,cAAc,EAAE,CAAC,EAAE;QACrE,EAAE;QACF,GAAG,CAAC,+DAA+D,CAAC;QACpE,EAAE;QACF,OAAO,CAAC,UAAU,CAAC;QACnB,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QACnE,EAAE;QACF,GAAG,OAAO,CAAC,wBAAwB,CAAC,IAAI,GAAG,CAAC,2CAA2C,CAAC,EAAE;QAC1F,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QAC9D,EAAE;QACF,OAAO,CAAC,WAAW,CAAC;QACpB,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;QAC5C,EAAE;KACH,CAAC;IAEF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,mBAAmB;IACjC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,cAAc,CAAC,IAAI,CAAC,CAAC;IAC/D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC","sourcesContent":["import { styleText } from 'node:util';\n\nimport packageJson from '../package.json' with { type: 'json' };\nimport { MUTATING_TOOL_NAMES } from './tools/index.ts';\n\n// Help text and its rendering. Split out of cli.ts so that module holds only\n// argument parsing and directory validation: this file is static copy plus a\n// formatter, and shares no state with the parser.\n\nconst { version: SERVER_VERSION } = packageJson;\n\ninterface HelpRow {\n flags: string;\n desc: string;\n}\n\nconst OPTIONS_HELP: HelpRow[] = [\n { flags: '-h, --help', desc: 'Show this help message' },\n { flags: '-v, --version', desc: 'Show the server version' },\n { flags: '--allow-cwd', desc: 'Add the current working directory as an allowed root' },\n {\n flags: '--port <number>',\n desc: 'Start HTTP transport on this port (env: FS_PORT)',\n },\n {\n flags: '--read-only',\n desc: `Disable write tools: ${[...MUTATING_TOOL_NAMES].sort().join(', ')}`,\n },\n { flags: '--print-config', desc: 'Print the active configuration as JSON and exit' },\n {\n flags: '--log-level <level>',\n desc: 'Log level, RFC 5424: debug|info|notice|warn|error|critical|alert|emergency (env: FS_LOG_LEVEL)',\n },\n { flags: '--http-host <host>', desc: 'HTTP server bind address (env: FS_HTTP_HOST)' },\n {\n flags: '--api-key <key>',\n desc: 'Require this API key on HTTP requests; prefer FS_API_KEY (argv is world-readable)',\n },\n {\n flags: '--allow-sensitive',\n desc: 'Allow access to sensitive system paths (env: FS_ALLOW_SENSITIVE)',\n },\n {\n flags: '--root-boundary <path>',\n desc: 'Require all allowed roots to fall under this path (env: FS_ROOT_BOUNDARY)',\n },\n {\n flags: '--max-file-size <bytes>',\n desc: 'Maximum file size for reads and for one create call, in bytes; the per-message wire limit is 3 × this + 1 MiB (env: FS_MAX_FILE_SIZE)',\n },\n { flags: '--walk-cwd', desc: 'Walk up from CWD to find a project root; implies --allow-cwd' },\n { flags: '--deny <pattern>', desc: 'Block paths matching this pattern; repeatable' },\n {\n flags: '--allow <pattern>',\n desc: 'Exempt a pattern from the built-in sensitive denylist; repeatable (env: FS_ALLOWLIST)',\n },\n {\n flags: '--allow-missing-roots',\n desc: 'Start even if configured allowed directories do not exist',\n },\n];\n\nconst ENV_HELP: HelpRow[] = [\n {\n flags: 'FS_LOG_LEVEL',\n desc: 'Log level, RFC 5424: debug|info|notice|warn|error|critical|alert|emergency',\n },\n { flags: 'FS_PORT', desc: 'Start HTTP transport on this port (unset = stdio)' },\n { flags: 'FS_HTTP_HOST', desc: 'HTTP bind address' },\n { flags: 'FS_API_KEY', desc: 'HTTP API key' },\n {\n flags: 'FS_TRUST_PROXY',\n desc: 'Express trust-proxy setting: hop count or expression (unset = do not trust X-Forwarded-*)',\n },\n {\n flags: 'FS_ALLOW_SENSITIVE',\n desc: 'Allow sensitive system paths (\"true\" or \"1\" enables this)',\n },\n { flags: 'FS_ROOT_BOUNDARY', desc: 'Path prefix all allowed roots must fall under' },\n {\n flags: 'FS_MAX_FILE_SIZE',\n desc: 'Maximum file size for reads and for one create call, in bytes; sizes the wire limit (3 × this + 1 MiB)',\n },\n {\n flags: 'FS_ALLOWED_DIRS',\n desc: 'Allowed dirs: colon-separated (Unix), semicolon-separated (Windows)',\n },\n {\n flags: 'FS_ALLOW_CWD_WALK',\n desc: 'Walk up from CWD to find a project root (\"true\" or \"1\" enables this)',\n },\n { flags: 'FS_DENYLIST', desc: 'Paths/patterns to block, comma-separated' },\n {\n flags: 'FS_ALLOWLIST',\n desc: 'Patterns exempted from the built-in sensitive denylist, comma-separated; --deny/FS_DENYLIST still win',\n },\n {\n flags: 'FS_ALLOW_MISSING_ROOTS',\n desc: 'Start even if configured allowed directories do not exist (\"true\" or \"1\" enables this)',\n },\n {\n flags: 'FS_ALLOWED_HOSTS',\n desc: 'Comma-separated Host header values to accept (HTTP transport)',\n },\n {\n flags: 'FS_ALLOWED_ORIGINS',\n desc: 'Comma-separated origin hostnames for CORS; an extension ID or a lowercase <scheme>://* entry (e.g. moz-extension://*) admits browser extensions',\n },\n {\n flags: 'FS_ALLOW_UNRESTRICTED_HOSTS',\n desc: 'Bind a wildcard host with no Host validation, accepts the risk (\"true\" or \"1\" enables this)',\n },\n { flags: 'FS_PUBLIC_URL', desc: 'Resource identifier URL for RFC 9728 discovery' },\n {\n flags: 'FS_RATE_LIMIT_RPM',\n desc: 'Per-client-IP requests/min (default 120 authenticated, 6000 keyless loopback; 1–100000)',\n },\n {\n flags: 'FS_MAX_WATCHERS',\n desc: 'Max concurrent file watchers (default 256, 1–4096)',\n },\n { flags: 'NO_COLOR', desc: 'Any value disables ANSI color output' },\n {\n flags: 'FS_REQUEST_STATE_KEY',\n desc: 'HMAC key for input_required state; optional, >=32 bytes when set',\n },\n];\n\nconst EXAMPLES_HELP = [\n '$ filesystem-mcp /path/to/allowed/dir',\n '$ filesystem-mcp --allow-cwd',\n '$ filesystem-mcp /project/src /project/tests --allow-cwd',\n '$ filesystem-mcp --port 3000 /path/to/allowed/dir',\n '$ filesystem-mcp --read-only /data/readonly',\n '$ filesystem-mcp --print-config /project',\n];\n\nexport function printHelpAndExit(): never {\n const COL = 27;\n // Pad first, colour after: `styleText` honours NO_COLOR, and padding the\n // plain text keeps the columns aligned whether or not colour is on.\n const row = (color: 'green' | 'cyan', name: string, desc: string): string =>\n ` ${styleText(color, name.padEnd(COL))}${desc}`;\n const dim = (t: string): string => styleText('dim', t);\n const section = (t: string): string => styleText(['cyan', 'bold'], t);\n\n const lines = [\n '',\n `${styleText('bold', 'Filesystem MCP')} ${dim(`v${SERVER_VERSION}`)}`,\n '',\n dim('Pass one or more directories to set the allowed access roots.'),\n '',\n section('Options:'),\n ...OPTIONS_HELP.map(({ flags, desc }) => row('green', flags, desc)),\n '',\n `${section('Environment variables:')} ${dim('(flags take precedence when both are set)')}`,\n ...ENV_HELP.map(({ flags, desc }) => row('cyan', flags, desc)),\n '',\n section('Examples:'),\n ...EXAMPLES_HELP.map((ex) => ` ${dim(ex)}`),\n '',\n ];\n\n process.stdout.write(lines.join('\\n'));\n process.exit(0);\n}\n\nexport function printVersionAndExit(): never {\n process.stdout.write(`${styleText('cyan', SERVER_VERSION)}\\n`);\n process.exit(0);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"cli-help.js","sourceRoot":"","sources":["../src/cli-help.ts"],"names":[],"mappings":"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","sourcesContent":["import { styleText } from 'node:util';\n\nimport packageJson from '../package.json' with { type: 'json' };\nimport { MUTATING_TOOL_NAMES } from './tools/index.ts';\n\n// Help text and its rendering. Split out of cli.ts so that module holds only\n// argument parsing and directory validation: this file is static copy plus a\n// formatter, and shares no state with the parser.\n\nconst { version: SERVER_VERSION } = packageJson;\n\ninterface HelpRow {\n flags: string;\n desc: string;\n}\n\nconst OPTIONS_HELP: HelpRow[] = [\n { flags: '-h, --help', desc: 'Show this help message' },\n { flags: '-v, --version', desc: 'Show the server version' },\n { flags: '--allow-cwd', desc: 'Add the current working directory as an allowed root' },\n {\n flags: '--port <number>',\n desc: 'Start HTTP transport on this port (env: FS_PORT)',\n },\n {\n flags: '--read-only',\n desc: `Disable write tools: ${[...MUTATING_TOOL_NAMES].sort().join(', ')}`,\n },\n { flags: '--print-config', desc: 'Print the active configuration as JSON and exit' },\n {\n flags: '--log-level <level>',\n desc: 'Log level, RFC 5424: debug|info|notice|warn|error|critical|alert|emergency (env: FS_LOG_LEVEL)',\n },\n { flags: '--http-host <host>', desc: 'HTTP server bind address (env: FS_HTTP_HOST)' },\n {\n flags: '--api-key <key>',\n desc: 'Require this API key on HTTP requests; prefer FS_API_KEY (argv is world-readable)',\n },\n {\n flags: '--allow-sensitive',\n desc: 'Turn off the built-in secret-file denylist (.env, keys, credentials) (env: FS_ALLOW_SENSITIVE)',\n },\n {\n flags: '--root-boundary <path>',\n desc: 'Require all allowed roots to fall under this path (env: FS_ROOT_BOUNDARY)',\n },\n {\n flags: '--max-file-size <bytes>',\n desc: 'Maximum file size for reads and for one create call, in bytes; the per-message wire limit is 3 × this + 1 MiB (env: FS_MAX_FILE_SIZE)',\n },\n {\n flags: '--walk-cwd',\n desc: 'Walk up from CWD to find a project root; implies --allow-cwd (env: FS_ALLOW_CWD_WALK)',\n },\n {\n flags: '--deny <pattern>',\n desc: 'Block paths matching this pattern; repeatable (env: FS_DENYLIST)',\n },\n {\n flags: '--allow <pattern>',\n desc: 'Exempt a pattern from the built-in sensitive denylist; repeatable (env: FS_ALLOWLIST)',\n },\n {\n flags: '--allow-missing-roots',\n desc: 'Start even if configured allowed directories do not exist (env: FS_ALLOW_MISSING_ROOTS)',\n },\n];\n\nconst ENV_HELP: HelpRow[] = [\n {\n flags: 'FS_LOG_LEVEL',\n desc: 'Log level, RFC 5424: debug|info|notice|warn|error|critical|alert|emergency',\n },\n { flags: 'FS_PORT', desc: 'Start HTTP transport on this port (unset = stdio)' },\n { flags: 'FS_HTTP_HOST', desc: 'HTTP bind address' },\n { flags: 'FS_API_KEY', desc: 'HTTP API key' },\n {\n flags: 'FS_TRUST_PROXY',\n desc: 'Express trust-proxy setting: hop count or expression (unset = do not trust X-Forwarded-*)',\n },\n {\n flags: 'FS_ALLOW_SENSITIVE',\n desc: 'Turn off the built-in secret-file denylist (\"true\" or \"1\" enables this)',\n },\n { flags: 'FS_ROOT_BOUNDARY', desc: 'Path prefix all allowed roots must fall under' },\n {\n flags: 'FS_MAX_FILE_SIZE',\n desc: 'Maximum file size for reads and for one create call, in bytes; sizes the wire limit (3 × this + 1 MiB)',\n },\n {\n flags: 'FS_ALLOWED_DIRS',\n desc: 'Allowed dirs: colon-separated (Unix), semicolon-separated (Windows)',\n },\n {\n flags: 'FS_ALLOW_CWD_WALK',\n desc: 'Walk up from CWD to find a project root (\"true\" or \"1\" enables this)',\n },\n { flags: 'FS_DENYLIST', desc: 'Paths/patterns to block, comma-separated' },\n {\n flags: 'FS_ALLOWLIST',\n desc: 'Patterns exempted from the built-in sensitive denylist, comma-separated; --deny/FS_DENYLIST still win',\n },\n {\n flags: 'FS_ALLOW_MISSING_ROOTS',\n desc: 'Start even if configured allowed directories do not exist (\"true\" or \"1\" enables this)',\n },\n {\n flags: 'FS_ALLOWED_HOSTS',\n desc: 'Comma-separated Host header values to accept (HTTP transport)',\n },\n {\n flags: 'FS_ALLOWED_ORIGINS',\n desc: 'Comma-separated origin hostnames for CORS; an extension ID or a lowercase <scheme>://* entry (e.g. moz-extension://*) admits browser extensions',\n },\n {\n flags: 'FS_ALLOW_UNRESTRICTED_HOSTS',\n desc: 'Bind a wildcard host with no Host validation, accepts the risk (\"true\" or \"1\" enables this)',\n },\n { flags: 'FS_PUBLIC_URL', desc: 'Resource identifier URL for RFC 9728 discovery' },\n {\n flags: 'FS_RATE_LIMIT_RPM',\n desc: 'Per-client-IP requests/min (default 120 authenticated, 6000 keyless loopback; 1–100000)',\n },\n {\n flags: 'FS_MAX_WATCHERS',\n desc: 'Max concurrent file watchers (default 256, 1–4096)',\n },\n { flags: 'NO_COLOR', desc: 'Any value disables ANSI color output' },\n {\n flags: 'FS_REQUEST_STATE_KEY',\n desc: 'HMAC key for input_required state; optional, >=32 bytes when set',\n },\n];\n\nconst EXAMPLES_HELP = [\n '$ filesystem-mcp /path/to/allowed/dir',\n '$ filesystem-mcp --allow-cwd',\n '$ filesystem-mcp /project/src /project/tests --allow-cwd',\n '$ filesystem-mcp --port 3000 /path/to/allowed/dir',\n '$ filesystem-mcp --read-only /data/readonly',\n '$ filesystem-mcp --print-config /project',\n];\n\nexport function printHelpAndExit(): never {\n // Sized from the longest name so a long one (FS_ALLOW_UNRESTRICTED_HOSTS)\n // never runs into its description.\n const COL = Math.max(...[...OPTIONS_HELP, ...ENV_HELP].map(({ flags }) => flags.length)) + 2;\n // Pad first, colour after: `styleText` honours NO_COLOR, and padding the\n // plain text keeps the columns aligned whether or not colour is on.\n const row = (color: 'green' | 'cyan', name: string, desc: string): string =>\n ` ${styleText(color, name.padEnd(COL))}${desc}`;\n const dim = (t: string): string => styleText('dim', t);\n const section = (t: string): string => styleText(['cyan', 'bold'], t);\n\n const lines = [\n '',\n `${styleText('bold', 'Filesystem MCP')} ${dim(`v${SERVER_VERSION}`)}`,\n '',\n dim('Pass one or more directories to set the allowed access roots.'),\n '',\n section('Options:'),\n ...OPTIONS_HELP.map(({ flags, desc }) => row('green', flags, desc)),\n '',\n `${section('Environment variables:')} ${dim('(flags win when both are set; --deny/--allow add to FS_DENYLIST/FS_ALLOWLIST)')}`,\n ...ENV_HELP.map(({ flags, desc }) => row('cyan', flags, desc)),\n '',\n section('Examples:'),\n ...EXAMPLES_HELP.map((ex) => ` ${dim(ex)}`),\n '',\n ];\n\n process.stdout.write(lines.join('\\n'));\n process.exit(0);\n}\n\nexport function printVersionAndExit(): never {\n process.stdout.write(`${styleText('cyan', SERVER_VERSION)}\\n`);\n process.exit(0);\n}\n"]}
|
package/dist/cli.d.ts
CHANGED
|
@@ -10,13 +10,5 @@ export declare function parseArgs(): Promise<{
|
|
|
10
10
|
httpHost: string | undefined;
|
|
11
11
|
apiKey: string | undefined;
|
|
12
12
|
}>;
|
|
13
|
-
export declare function runPrintConfig(options:
|
|
14
|
-
allowedDirs: string[];
|
|
15
|
-
allowCwd: boolean;
|
|
16
|
-
readOnly: boolean;
|
|
17
|
-
/** Resolved `--port`. Present means the launch this reports on is an HTTP bind. */
|
|
18
|
-
port?: number;
|
|
19
|
-
httpHost?: string;
|
|
20
|
-
apiKey?: string;
|
|
21
|
-
}): Promise<void>;
|
|
13
|
+
export declare function runPrintConfig(options: Awaited<ReturnType<typeof parseArgs>>): Promise<void>;
|
|
22
14
|
//# sourceMappingURL=cli.d.ts.map
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AA0BA,qBAAa,YAAa,SAAQ,KAAK;gBACzB,OAAO,EAAE,MAAM;CAI5B;AAyGD,wBAAsB,SAAS,IAAI,OAAO,CAAC;IACzC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B,CAAC,CAqED;AAMD,wBAAsB,cAAc,
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AA0BA,qBAAa,YAAa,SAAQ,KAAK;gBACzB,OAAO,EAAE,MAAM;CAI5B;AAyGD,wBAAsB,SAAS,IAAI,OAAO,CAAC;IACzC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B,CAAC,CAqED;AAMD,wBAAsB,cAAc,CAClC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC,GAC7C,OAAO,CAAC,IAAI,CAAC,CAmDf"}
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["import { LATEST_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS } from '@modelcontextprotocol/server';\n\nimport type { Stats } from 'node:fs';\nimport { stat } from 'node:fs/promises';\nimport { parseArgs as utilParseArgs } from 'node:util';\n\nimport packageJson from '../package.json' with { type: 'json' };\nimport { printHelpAndExit, printVersionAndExit } from './cli-help.ts';\nimport { cli, MODERN_PROTOCOL_REVISION } from './core/config.ts';\nimport { formatUnknownErrorMessage } from './core/errors.ts';\nimport {\n getReservedDeviceNameForPath,\n IS_WINDOWS,\n isWindowsDriveRelativePath,\n normalizePath,\n parseTrueEnvFlag,\n} from './core/path-utils.ts';\nimport { PathGuard } from './core/path.ts';\nimport { describeSensitivePolicy } from './core/sensitive.ts';\nimport { getMaxInboundMessageBytes, getMaxTextFileSize } from './core/util.ts';\nimport { registeredTools } from './tools/index.ts';\n\n// ════════════════════════════════════════════════════════════\n// Path & Config Utilities — pure functions and error types\n// ════════════════════════════════════════════════════════════\n\nexport class CliExitError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'CliExitError';\n }\n}\n\nfunction validateCliPath(inputPath: string): void {\n if (inputPath.includes('\\0')) {\n throw new CliExitError('Path contains null bytes.');\n }\n\n if (isWindowsDriveRelativePath(inputPath)) {\n throw new CliExitError(\n 'Windows drive-relative paths are not allowed. Use C:\\\\path or C:/path instead of C:path.',\n );\n }\n\n const reserved = IS_WINDOWS ? getReservedDeviceNameForPath(inputPath) : undefined;\n if (reserved) {\n throw new CliExitError(`Windows reserved device name not allowed: ${reserved}.`);\n }\n}\n\nasync function validateDirectoryPath(inputPath: string, allowMissing = false): Promise<string> {\n const normalized = normalizePath(inputPath);\n\n let stats: Stats;\n try {\n stats = await stat(normalized);\n } catch (error) {\n if (allowMissing) return normalized;\n // Node's own message already names the syscall and the errno.\n throw new Error(`Cannot access directory ${inputPath}: ${formatUnknownErrorMessage(error)}`, {\n cause: error,\n });\n }\n\n if (!stats.isDirectory()) throw new Error(`${inputPath} is not a directory`);\n return normalized;\n}\n\n// No dedupe here: PathGuard's `normalizeAllowedDirectories` already Set-dedupes\n// the normalized set, and containment checks are case-insensitive where the\n// filesystem is.\nasync function normalizeAndValidateDirs(\n paths: readonly string[],\n allowMissing = false,\n): Promise<string[]> {\n const normalized: string[] = [];\n for (const p of paths) {\n normalized.push(await validateDirectoryPath(p, allowMissing));\n }\n return normalized;\n}\n\nfunction normalizeCliExitMessage(error: unknown): string {\n const rawMessage = formatUnknownErrorMessage(error);\n return rawMessage.startsWith('Error:') ? rawMessage : `Error: ${rawMessage}`;\n}\n\nfunction parsePortOption(raw: unknown): number | undefined {\n // '' reads as unset: FS_PORT set-but-empty (compose templating) means stdio.\n if (raw === undefined || raw === '') return undefined;\n const n = Number(raw);\n if (!Number.isInteger(n) || n < 1 || n > 65535) {\n throw new CliExitError(`Error: --port / FS_PORT must be an integer between 1 and 65535`);\n }\n return n;\n}\n\nconst ENV_PLACEHOLDER = /^\\$\\{([A-Za-z_]\\w*)\\}$/;\n\n/**\n * Plugin hosts start servers outside the project and substitute only the\n * variables they know: Antigravity CLI passes `${PWD}` through verbatim, and\n * Copilot CLI does when the launching shell exported no PWD (PowerShell, cmd).\n * A whole-argument `${NAME}` resolves from this process's environment; unset\n * or empty drops it, so it never becomes a bogus relative root.\n */\nfunction expandEnvPlaceholder(arg: string): string[] {\n const name = ENV_PLACEHOLDER.exec(arg)?.[1];\n if (name === undefined) return [arg];\n const value = process.env[name];\n return value ? [value] : [];\n}\n\nconst CLI_PARSER_CONFIG = {\n options: {\n 'allow-cwd': { type: 'boolean', default: false },\n 'read-only': { type: 'boolean', default: false },\n 'print-config': { type: 'boolean', default: false },\n port: { type: 'string' },\n help: { type: 'boolean', short: 'h' },\n version: { type: 'boolean', short: 'v' },\n 'log-level': { type: 'string' },\n 'http-host': { type: 'string' },\n 'api-key': { type: 'string' },\n 'allow-sensitive': { type: 'boolean', default: false },\n 'root-boundary': { type: 'string' },\n 'max-file-size': { type: 'string' },\n 'walk-cwd': { type: 'boolean', default: false },\n deny: { type: 'string', multiple: true },\n allow: { type: 'string', multiple: true },\n 'allow-missing-roots': { type: 'boolean', default: false },\n },\n strict: true,\n allowPositionals: true,\n} as const;\n\nexport async function parseArgs(): Promise<{\n allowedDirs: string[];\n allowCwd: boolean;\n port: number | undefined;\n readOnly: boolean;\n printConfig: boolean;\n httpHost: string | undefined;\n apiKey: string | undefined;\n}> {\n try {\n const parsed = utilParseArgs(CLI_PARSER_CONFIG);\n\n if (parsed.values.help) {\n printHelpAndExit();\n }\n\n if (parsed.values.version) {\n printVersionAndExit();\n }\n\n const positionals = parsed.positionals.flatMap(expandEnvPlaceholder);\n for (const positional of positionals) {\n validateCliPath(positional);\n }\n\n const v = parsed.values;\n // `--http-host` and `--api-key` are returned to the caller and handed to\n // the server as config. Every other flag lands in the CLI-override store\n // (core/config.ts) — the one owner of the flag-beats-env rule — which deep\n // core readers (path, sensitive, observability, util) consult before\n // falling back to the operator's environment. Nothing writes process.env.\n const httpHost = v['http-host'] ?? process.env['FS_HTTP_HOST'];\n const apiKey = v['api-key'] ?? process.env['FS_API_KEY'];\n if (v['log-level'] !== undefined) cli.logLevel = v['log-level'];\n if (v['max-file-size'] !== undefined) cli.maxFileSize = v['max-file-size'];\n if (v['root-boundary'] !== undefined) cli.rootBoundary = v['root-boundary'];\n if (v['allow-sensitive']) cli.allowSensitive = true;\n if (v['walk-cwd']) cli.allowCwdWalk = true;\n if (v['allow-missing-roots']) cli.allowMissingRoots = true;\n const patternList = (entries: readonly string[] | undefined): readonly string[] => [\n ...new Set((entries ?? []).map((entry) => entry.trim()).filter(Boolean)),\n ];\n const denyPatterns = patternList(v.deny);\n if (denyPatterns.length > 0) cli.denyPatterns = denyPatterns;\n const allowPatterns = patternList(v.allow);\n if (allowPatterns.length > 0) cli.allowPatterns = allowPatterns;\n\n const allowCwd =\n v['allow-cwd'] ||\n v['walk-cwd'] ||\n parseTrueEnvFlag(process.env['FS_ALLOW_CWD_WALK'], 'FS_ALLOW_CWD_WALK');\n const readOnly = v['read-only'];\n const printConfig = v['print-config'];\n const port = parsePortOption(v.port ?? process.env['FS_PORT']);\n const allowMissingRoots =\n v['allow-missing-roots'] ||\n parseTrueEnvFlag(process.env['FS_ALLOW_MISSING_ROOTS'], 'FS_ALLOW_MISSING_ROOTS');\n\n const allowedDirs =\n positionals.length > 0 ? await normalizeAndValidateDirs(positionals, allowMissingRoots) : [];\n\n return {\n allowedDirs,\n allowCwd,\n port,\n readOnly,\n printConfig,\n httpHost,\n apiKey,\n };\n } catch (error: unknown) {\n if (error instanceof CliExitError) {\n throw error;\n }\n\n throw new CliExitError(normalizeCliExitMessage(error));\n }\n}\n\n// ════════════════════════════════════════════════════════════\n// Effective config reporting — prints the resolved server config as JSON\n// ════════════════════════════════════════════════════════════\n\nexport async function runPrintConfig(options: {\n allowedDirs: string[];\n allowCwd: boolean;\n readOnly: boolean;\n /** Resolved `--port`. Present means the launch this reports on is an HTTP bind. */\n port?: number;\n httpHost?: string;\n apiKey?: string;\n}): Promise<void> {\n const pathGuard = new PathGuard({\n allowCwd: options.allowCwd,\n cliAllowedDirs: options.allowedDirs,\n });\n await pathGuard.recomputeAllowedDirectories();\n const allowedRoots = pathGuard.getRoots();\n\n const tools = registeredTools(options.readOnly).map((t) => t.name);\n\n // Derived, never assumed: `--print-config --port 3000` reports the HTTP bind\n // that `--port` would actually have started, not the stdio default.\n const config = {\n transport:\n options.port !== undefined\n ? `http://${options.httpHost ?? '127.0.0.1'}:${String(options.port)}`\n : 'stdio',\n readOnly: options.readOnly,\n allowedRoots,\n tools,\n apiKey: options.apiKey ? '***' : null,\n limits: {\n maxFileSizeBytes: getMaxTextFileSize(),\n maxInboundMessageBytes: getMaxInboundMessageBytes(),\n },\n // What the binary negotiates with, so an era mismatch (\"unsupported\n // protocol version\") can be diagnosed without attaching a client. The\n // legacy list is the SDK's own; the modern revision has no SDK export.\n // The pins are exact (package.json), so the manifest value is the\n // installed one.\n protocol: {\n modern: MODERN_PROTOCOL_REVISION,\n legacy: { latest: LATEST_PROTOCOL_VERSION, supported: SUPPORTED_PROTOCOL_VERSIONS },\n sdk: {\n server: packageJson.dependencies['@modelcontextprotocol/server'],\n node: packageJson.dependencies['@modelcontextprotocol/node'],\n express: packageJson.dependencies['@modelcontextprotocol/express'],\n },\n },\n // Everything that can produce ACCESS_DENIED, read through the same\n // sources the guard and the matcher use (flag beats env).\n policy: {\n ...describeSensitivePolicy(),\n rootBoundary: cli.rootBoundary ?? process.env['FS_ROOT_BOUNDARY'] ?? null,\n allowMissingRoots:\n cli.allowMissingRoots ??\n parseTrueEnvFlag(process.env['FS_ALLOW_MISSING_ROOTS'], 'FS_ALLOW_MISSING_ROOTS'),\n },\n };\n\n process.stdout.write(`${JSON.stringify(config, null, 2)}\\n`);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["import { LATEST_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS } from '@modelcontextprotocol/server';\n\nimport type { Stats } from 'node:fs';\nimport { stat } from 'node:fs/promises';\nimport { parseArgs as utilParseArgs } from 'node:util';\n\nimport packageJson from '../package.json' with { type: 'json' };\nimport { printHelpAndExit, printVersionAndExit } from './cli-help.ts';\nimport { cli, MODERN_PROTOCOL_REVISION } from './core/config.ts';\nimport { formatUnknownErrorMessage } from './core/errors.ts';\nimport {\n getReservedDeviceNameForPath,\n IS_WINDOWS,\n isWindowsDriveRelativePath,\n normalizePath,\n parseTrueEnvFlag,\n} from './core/path-utils.ts';\nimport { PathGuard } from './core/path.ts';\nimport { describeSensitivePolicy } from './core/sensitive.ts';\nimport { getMaxInboundMessageBytes, getMaxTextFileSize } from './core/util.ts';\nimport { registeredTools } from './tools/index.ts';\n\n// ════════════════════════════════════════════════════════════\n// Path & Config Utilities — pure functions and error types\n// ════════════════════════════════════════════════════════════\n\nexport class CliExitError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'CliExitError';\n }\n}\n\nfunction validateCliPath(inputPath: string): void {\n if (inputPath.includes('\\0')) {\n throw new CliExitError('Path contains null bytes.');\n }\n\n if (isWindowsDriveRelativePath(inputPath)) {\n throw new CliExitError(\n 'Windows drive-relative paths are not allowed. Use C:\\\\path or C:/path instead of C:path.',\n );\n }\n\n const reserved = IS_WINDOWS ? getReservedDeviceNameForPath(inputPath) : undefined;\n if (reserved) {\n throw new CliExitError(`Windows reserved device name not allowed: ${reserved}.`);\n }\n}\n\nasync function validateDirectoryPath(inputPath: string, allowMissing = false): Promise<string> {\n const normalized = normalizePath(inputPath);\n\n let stats: Stats;\n try {\n stats = await stat(normalized);\n } catch (error) {\n if (allowMissing) return normalized;\n // Node's own message already names the syscall and the errno.\n throw new Error(`Cannot access directory ${inputPath}: ${formatUnknownErrorMessage(error)}`, {\n cause: error,\n });\n }\n\n if (!stats.isDirectory()) throw new Error(`${inputPath} is not a directory`);\n return normalized;\n}\n\n// No dedupe here: PathGuard's `normalizeAllowedDirectories` already Set-dedupes\n// the normalized set, and containment checks are case-insensitive where the\n// filesystem is.\nasync function normalizeAndValidateDirs(\n paths: readonly string[],\n allowMissing = false,\n): Promise<string[]> {\n const normalized: string[] = [];\n for (const p of paths) {\n normalized.push(await validateDirectoryPath(p, allowMissing));\n }\n return normalized;\n}\n\nfunction normalizeCliExitMessage(error: unknown): string {\n const rawMessage = formatUnknownErrorMessage(error);\n return rawMessage.startsWith('Error:') ? rawMessage : `Error: ${rawMessage}`;\n}\n\nfunction parsePortOption(raw: unknown): number | undefined {\n // '' reads as unset: FS_PORT set-but-empty (compose templating) means stdio.\n if (raw === undefined || raw === '') return undefined;\n const n = Number(raw);\n if (!Number.isInteger(n) || n < 1 || n > 65535) {\n throw new CliExitError(`Error: --port / FS_PORT must be an integer between 1 and 65535`);\n }\n return n;\n}\n\nconst ENV_PLACEHOLDER = /^\\$\\{([A-Za-z_]\\w*)\\}$/;\n\n/**\n * Plugin hosts start servers outside the project and substitute only the\n * variables they know: Antigravity CLI passes `${PWD}` through verbatim, and\n * Copilot CLI does when the launching shell exported no PWD (PowerShell, cmd).\n * A whole-argument `${NAME}` resolves from this process's environment; unset\n * or empty drops it, so it never becomes a bogus relative root.\n */\nfunction expandEnvPlaceholder(arg: string): string[] {\n const name = ENV_PLACEHOLDER.exec(arg)?.[1];\n if (name === undefined) return [arg];\n const value = process.env[name];\n return value ? [value] : [];\n}\n\nconst CLI_PARSER_CONFIG = {\n options: {\n 'allow-cwd': { type: 'boolean', default: false },\n 'read-only': { type: 'boolean', default: false },\n 'print-config': { type: 'boolean', default: false },\n port: { type: 'string' },\n help: { type: 'boolean', short: 'h' },\n version: { type: 'boolean', short: 'v' },\n 'log-level': { type: 'string' },\n 'http-host': { type: 'string' },\n 'api-key': { type: 'string' },\n 'allow-sensitive': { type: 'boolean', default: false },\n 'root-boundary': { type: 'string' },\n 'max-file-size': { type: 'string' },\n 'walk-cwd': { type: 'boolean', default: false },\n deny: { type: 'string', multiple: true },\n allow: { type: 'string', multiple: true },\n 'allow-missing-roots': { type: 'boolean', default: false },\n },\n strict: true,\n allowPositionals: true,\n} as const;\n\nexport async function parseArgs(): Promise<{\n allowedDirs: string[];\n allowCwd: boolean;\n port: number | undefined;\n readOnly: boolean;\n printConfig: boolean;\n httpHost: string | undefined;\n apiKey: string | undefined;\n}> {\n try {\n const parsed = utilParseArgs(CLI_PARSER_CONFIG);\n\n if (parsed.values.help) {\n printHelpAndExit();\n }\n\n if (parsed.values.version) {\n printVersionAndExit();\n }\n\n const positionals = parsed.positionals.flatMap(expandEnvPlaceholder);\n for (const positional of positionals) {\n validateCliPath(positional);\n }\n\n const v = parsed.values;\n // `--http-host` and `--api-key` are returned to the caller and handed to\n // the server as config. Every other flag lands in the CLI-override store\n // (core/config.ts) — the one owner of the flag-beats-env rule — which deep\n // core readers (path, sensitive, observability, util) consult before\n // falling back to the operator's environment. Nothing writes process.env.\n const httpHost = v['http-host'] ?? process.env['FS_HTTP_HOST'];\n const apiKey = v['api-key'] ?? process.env['FS_API_KEY'];\n if (v['log-level'] !== undefined) cli.logLevel = v['log-level'];\n if (v['max-file-size'] !== undefined) cli.maxFileSize = v['max-file-size'];\n if (v['root-boundary'] !== undefined) cli.rootBoundary = v['root-boundary'];\n if (v['allow-sensitive']) cli.allowSensitive = true;\n if (v['walk-cwd']) cli.allowCwdWalk = true;\n if (v['allow-missing-roots']) cli.allowMissingRoots = true;\n const patternList = (entries: readonly string[] | undefined): readonly string[] => [\n ...new Set((entries ?? []).map((entry) => entry.trim()).filter(Boolean)),\n ];\n const denyPatterns = patternList(v.deny);\n if (denyPatterns.length > 0) cli.denyPatterns = denyPatterns;\n const allowPatterns = patternList(v.allow);\n if (allowPatterns.length > 0) cli.allowPatterns = allowPatterns;\n\n const allowCwd =\n v['allow-cwd'] ||\n v['walk-cwd'] ||\n parseTrueEnvFlag(process.env['FS_ALLOW_CWD_WALK'], 'FS_ALLOW_CWD_WALK');\n const readOnly = v['read-only'];\n const printConfig = v['print-config'];\n const port = parsePortOption(v.port ?? process.env['FS_PORT']);\n const allowMissingRoots =\n v['allow-missing-roots'] ||\n parseTrueEnvFlag(process.env['FS_ALLOW_MISSING_ROOTS'], 'FS_ALLOW_MISSING_ROOTS');\n\n const allowedDirs =\n positionals.length > 0 ? await normalizeAndValidateDirs(positionals, allowMissingRoots) : [];\n\n return {\n allowedDirs,\n allowCwd,\n port,\n readOnly,\n printConfig,\n httpHost,\n apiKey,\n };\n } catch (error: unknown) {\n if (error instanceof CliExitError) {\n throw error;\n }\n\n throw new CliExitError(normalizeCliExitMessage(error));\n }\n}\n\n// ════════════════════════════════════════════════════════════\n// Effective config reporting — prints the resolved server config as JSON\n// ════════════════════════════════════════════════════════════\n\nexport async function runPrintConfig(\n options: Awaited<ReturnType<typeof parseArgs>>,\n): Promise<void> {\n const pathGuard = new PathGuard({\n allowCwd: options.allowCwd,\n cliAllowedDirs: options.allowedDirs,\n });\n await pathGuard.recomputeAllowedDirectories();\n const allowedRoots = pathGuard.getRoots();\n\n const tools = registeredTools(options.readOnly).map((t) => t.name);\n\n // Derived, never assumed: `--print-config --port 3000` reports the HTTP bind\n // that `--port` would actually have started, not the stdio default.\n const config = {\n transport:\n options.port !== undefined\n ? `http://${options.httpHost ?? '127.0.0.1'}:${String(options.port)}`\n : 'stdio',\n readOnly: options.readOnly,\n allowedRoots,\n tools,\n apiKey: options.apiKey ? '***' : null,\n limits: {\n maxFileSizeBytes: getMaxTextFileSize(),\n maxInboundMessageBytes: getMaxInboundMessageBytes(),\n },\n // What the binary negotiates with, so an era mismatch (\"unsupported\n // protocol version\") can be diagnosed without attaching a client. The\n // legacy list is the SDK's own; the modern revision has no SDK export.\n // The pins are exact (package.json), so the manifest value is the\n // installed one.\n protocol: {\n modern: MODERN_PROTOCOL_REVISION,\n legacy: { latest: LATEST_PROTOCOL_VERSION, supported: SUPPORTED_PROTOCOL_VERSIONS },\n sdk: {\n server: packageJson.dependencies['@modelcontextprotocol/server'],\n node: packageJson.dependencies['@modelcontextprotocol/node'],\n express: packageJson.dependencies['@modelcontextprotocol/express'],\n },\n },\n // Everything that can produce ACCESS_DENIED, read through the same\n // sources the guard and the matcher use (flag beats env).\n policy: {\n ...describeSensitivePolicy(),\n rootBoundary: cli.rootBoundary ?? process.env['FS_ROOT_BOUNDARY'] ?? null,\n allowMissingRoots:\n cli.allowMissingRoots ??\n parseTrueEnvFlag(process.env['FS_ALLOW_MISSING_ROOTS'], 'FS_ALLOW_MISSING_ROOTS'),\n },\n };\n\n process.stdout.write(`${JSON.stringify(config, null, 2)}\\n`);\n}\n"]}
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
export type StoppedReason = 'maxResults' | 'maxFiles' | 'timeout';
|
|
2
|
+
/**
|
|
3
|
+
* Run `fn` as the next holder of `key`'s lock: a read-`await`-write under one
|
|
4
|
+
* key never interleaves with another. A rejected `fn` does not poison the next
|
|
5
|
+
* waiter, and the entry is dropped once the chain drains. Keys: a PathGuard
|
|
6
|
+
* instance (allowed-set grants) or a resolved write target (per-file writes).
|
|
7
|
+
*/
|
|
8
|
+
export declare function runExclusive<T>(key: unknown, fn: () => Promise<T>): Promise<T>;
|
|
2
9
|
/** The one precedence both scans share: the result cap wins over an abort that fired the same iteration. */
|
|
3
10
|
export declare function resolveStopReason(hitCap: boolean, aborted: boolean): 'maxResults' | 'timeout' | undefined;
|
|
4
11
|
interface ParallelResult<R> {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"concurrency.d.ts","sourceRoot":"","sources":["../../src/core/concurrency.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,UAAU,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"concurrency.d.ts","sourceRoot":"","sources":["../../src/core/concurrency.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,UAAU,GAAG,SAAS,CAAC;AAIlE;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAYpF;AAED,4GAA4G;AAC5G,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,OAAO,GACf,YAAY,GAAG,SAAS,GAAG,SAAS,CAEtC;AAED,UAAU,cAAc,CAAC,CAAC;IACxB,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,CAAC,CAAA;KAAE,EAAE,CAAC;IACvC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,EAAE,CAAC;CAC3C;AAED,wBAAsB,iBAAiB,CAAC,CAAC,EAAE,CAAC,EAC1C,KAAK,EAAE,SAAS,CAAC,EAAE,EACnB,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,EACjD,WAAW,GAAE,MAA6B,EAC1C,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAgE5B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,aAAa,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,QAAQ,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EACrE,OAAO,EAAE;IACP,MAAM,EAAE,WAAW,GAAG,SAAS,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC;IAC3B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IACpD,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAChD,GACA,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAuEpC;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,CAmBlF"}
|
package/dist/core/concurrency.js
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
import { normalizeUnknownError } from "./errors.js";
|
|
2
2
|
import { PARALLEL_CONCURRENCY } from "./util.js";
|
|
3
|
+
const exclusiveChains = new Map();
|
|
4
|
+
/**
|
|
5
|
+
* Run `fn` as the next holder of `key`'s lock: a read-`await`-write under one
|
|
6
|
+
* key never interleaves with another. A rejected `fn` does not poison the next
|
|
7
|
+
* waiter, and the entry is dropped once the chain drains. Keys: a PathGuard
|
|
8
|
+
* instance (allowed-set grants) or a resolved write target (per-file writes).
|
|
9
|
+
*/
|
|
10
|
+
export async function runExclusive(key, fn) {
|
|
11
|
+
const run = (exclusiveChains.get(key) ?? Promise.resolve()).then(fn, fn);
|
|
12
|
+
const tail = run.then(() => undefined, () => undefined);
|
|
13
|
+
exclusiveChains.set(key, tail);
|
|
14
|
+
try {
|
|
15
|
+
return await run;
|
|
16
|
+
}
|
|
17
|
+
finally {
|
|
18
|
+
if (exclusiveChains.get(key) === tail)
|
|
19
|
+
exclusiveChains.delete(key);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
3
22
|
/** The one precedence both scans share: the result cap wins over an abort that fired the same iteration. */
|
|
4
23
|
export function resolveStopReason(hitCap, aborted) {
|
|
5
24
|
return hitCap ? 'maxResults' : aborted ? 'timeout' : undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"concurrency.js","sourceRoot":"","sources":["../../src/core/concurrency.ts"],"names":[],"mappings":"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","sourcesContent":["import { normalizeUnknownError } from './errors.ts';\nimport { PARALLEL_CONCURRENCY } from './util.ts';\n\nexport type StoppedReason = 'maxResults' | 'maxFiles' | 'timeout';\n\n/** The one precedence both scans share: the result cap wins over an abort that fired the same iteration. */\nexport function resolveStopReason(\n hitCap: boolean,\n aborted: boolean,\n): 'maxResults' | 'timeout' | undefined {\n return hitCap ? 'maxResults' : aborted ? 'timeout' : undefined;\n}\n\ninterface ParallelResult<R> {\n results: { index: number; value: R }[];\n errors: { index: number; error: Error }[];\n}\n\nexport async function processInParallel<T, R>(\n items: readonly T[],\n processor: (item: T, index: number) => Promise<R>,\n concurrency: number = PARALLEL_CONCURRENCY,\n signal?: AbortSignal,\n): Promise<ParallelResult<R>> {\n const itemCount = items.length;\n if (itemCount === 0) return { results: [], errors: [] };\n\n const results: { index: number; value: R }[] = [];\n const errors: { index: number; error: Error }[] = [];\n\n signal?.throwIfAborted();\n\n let nextIndex = 0;\n // Set when a worker saw the signal fire before an item ran — the only\n // shape in which the batch is genuinely incomplete. The annotation\n // matters: without it control-flow analysis keeps the `false` narrowing\n // from the initializer and cannot see the closure assignment.\n let truncated = false as boolean;\n\n const next = async (): Promise<void> => {\n while (nextIndex < itemCount) {\n if (signal?.aborted) {\n truncated = true;\n signal.throwIfAborted();\n }\n\n const index = nextIndex;\n nextIndex += 1;\n const item = items[index];\n if (item === undefined) {\n continue;\n }\n\n try {\n // No abort check after the processor: once an item has run, its\n // result is real work that a write caller may have committed to\n // disk. Discarding it here would report a finished append as\n // failed, and a client retry would append twice.\n const value = await processor(item, index);\n results.push({ index, value });\n } catch (error) {\n errors.push({\n index,\n error: normalizeUnknownError(error),\n });\n }\n }\n };\n\n const workerCount = Math.min(itemCount, concurrency);\n const workers: Promise<void>[] = new Array<Promise<void>>(workerCount);\n for (let index = 0; index < workerCount; index += 1) {\n workers[index] = next();\n }\n\n await Promise.allSettled(workers);\n // A deadline (AbortSignal.timeout) hit during the run surfaces here as\n // signal.reason — a TimeoutError — rather than a fresh AbortError, so\n // callers see TIMEOUT, not CANCELLED. Only a run that actually skipped\n // items reports the abort: a deadline firing after the last item\n // finished leaves a complete batch, and returning it beats telling the\n // caller that committed writes failed. The per-item throws above are\n // swallowed by allSettled.\n if (truncated) signal?.throwIfAborted();\n\n results.sort((left, right) => left.index - right.index);\n return { results, errors };\n}\n\n/**\n * The streaming sibling of {@link processInParallel}: bounded-concurrency\n * dispatch over an AsyncIterable that may be far larger than the caller wants\n * to walk, so it stops early and reports why.\n *\n * `maxEntries` caps how many entries are dispatched (maxFiles); `shouldStop`\n * lets the caller stop on its own accumulating result count (maxResults). Both\n * are checked before dispatch, so the returned reason is exactly one — the\n * loop breaks on the first that fires. `undefined` means every entry was\n * dispatched.\n */\nexport async function processEntriesConcurrently(\n entries: AsyncIterable<{ path: string }> | Iterable<{ path: string }>,\n options: {\n signal: AbortSignal | undefined;\n concurrency: number;\n maxEntries?: number;\n shouldStop?: () => boolean;\n onEntry: () => void;\n onError?: (entryPath: string, err: unknown) => void;\n runEntry: (entryPath: string) => Promise<void>;\n },\n): Promise<StoppedReason | undefined> {\n const pending = new Set<Promise<void>>();\n const { signal, concurrency, maxEntries, shouldStop, onEntry, onError, runEntry } = options;\n let stoppedReason: StoppedReason | undefined;\n let dispatched = 0;\n\n const waitForSlot = async (): Promise<void> => {\n if (pending.size < concurrency) return;\n await Promise.race(pending);\n };\n\n let walkFailed = false;\n let walkError: unknown;\n try {\n for await (const entry of entries) {\n // The signal is cancellation OR the caller's timeout: stop dispatching and\n // let the caller report the run as incomplete rather than as a full sweep.\n if (signal?.aborted) {\n stoppedReason = 'timeout';\n break;\n }\n if (maxEntries !== undefined && dispatched >= maxEntries) {\n stoppedReason = 'maxFiles';\n break;\n }\n // Check the result cap before waiting for a slot so an in-flight task that\n // already crossed the cap stops dispatch without an extra wait...\n if (shouldStop?.()) {\n stoppedReason = 'maxResults';\n break;\n }\n await waitForSlot();\n // ...and again after the slot frees, since tasks settle concurrently. The\n // cap can still be exceeded by at most `concurrency - 1` already-dispatched\n // tasks that are mid-flight; that overrun is inherent to concurrent dispatch.\n if (shouldStop?.()) {\n stoppedReason = 'maxResults';\n break;\n }\n onEntry();\n dispatched++;\n\n // Track a non-rejecting wrapper so a rejected task can never propagate out of\n // Promise.race(pending) in waitForSlot() and abort the loop before the final\n // drain below (which would silently abandon other in-flight tasks).\n // runEntry is expected to catch its own errors; if it unexpectedly throws,\n // record it as a failure rather than silently dropping it.\n const tracked = runEntry(entry.path).catch((err: unknown) => {\n onError?.(entry.path, err);\n });\n pending.add(tracked);\n void tracked.finally(() => {\n pending.delete(tracked);\n });\n }\n } catch (error) {\n // A walk the signal cut short throws its reason (see globEntries): that is\n // the same timeout as the check above, not a failed walk.\n if (signal?.aborted) stoppedReason = 'timeout';\n else {\n walkFailed = true;\n walkError = error;\n }\n }\n\n if (pending.size > 0) {\n await Promise.allSettled([...pending]);\n }\n\n if (walkFailed) throw walkError;\n return stoppedReason;\n}\n\nexport function withAbort<T>(promise: Promise<T>, signal?: AbortSignal): Promise<T> {\n if (!signal) {\n return promise;\n }\n signal.throwIfAborted();\n let onAbort: (() => void) | undefined;\n return Promise.race([\n promise,\n new Promise<never>((_, reject) => {\n onAbort = () => {\n reject(signal.reason instanceof Error ? signal.reason : new Error('Operation aborted'));\n };\n signal.addEventListener('abort', onAbort, { once: true });\n }),\n ]).finally(() => {\n if (onAbort) {\n signal.removeEventListener('abort', onAbort);\n }\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"concurrency.js","sourceRoot":"","sources":["../../src/core/concurrency.ts"],"names":[],"mappings":"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","sourcesContent":["import { normalizeUnknownError } from './errors.ts';\nimport { PARALLEL_CONCURRENCY } from './util.ts';\n\nexport type StoppedReason = 'maxResults' | 'maxFiles' | 'timeout';\n\nconst exclusiveChains = new Map<unknown, Promise<unknown>>();\n\n/**\n * Run `fn` as the next holder of `key`'s lock: a read-`await`-write under one\n * key never interleaves with another. A rejected `fn` does not poison the next\n * waiter, and the entry is dropped once the chain drains. Keys: a PathGuard\n * instance (allowed-set grants) or a resolved write target (per-file writes).\n */\nexport async function runExclusive<T>(key: unknown, fn: () => Promise<T>): Promise<T> {\n const run = (exclusiveChains.get(key) ?? Promise.resolve()).then(fn, fn);\n const tail = run.then(\n () => undefined,\n () => undefined,\n );\n exclusiveChains.set(key, tail);\n try {\n return await run;\n } finally {\n if (exclusiveChains.get(key) === tail) exclusiveChains.delete(key);\n }\n}\n\n/** The one precedence both scans share: the result cap wins over an abort that fired the same iteration. */\nexport function resolveStopReason(\n hitCap: boolean,\n aborted: boolean,\n): 'maxResults' | 'timeout' | undefined {\n return hitCap ? 'maxResults' : aborted ? 'timeout' : undefined;\n}\n\ninterface ParallelResult<R> {\n results: { index: number; value: R }[];\n errors: { index: number; error: Error }[];\n}\n\nexport async function processInParallel<T, R>(\n items: readonly T[],\n processor: (item: T, index: number) => Promise<R>,\n concurrency: number = PARALLEL_CONCURRENCY,\n signal?: AbortSignal,\n): Promise<ParallelResult<R>> {\n const itemCount = items.length;\n if (itemCount === 0) return { results: [], errors: [] };\n\n const results: { index: number; value: R }[] = [];\n const errors: { index: number; error: Error }[] = [];\n\n signal?.throwIfAborted();\n\n let nextIndex = 0;\n // Set when a worker saw the signal fire before an item ran — the only\n // shape in which the batch is genuinely incomplete. The annotation\n // matters: without it control-flow analysis keeps the `false` narrowing\n // from the initializer and cannot see the closure assignment.\n let truncated = false as boolean;\n\n const next = async (): Promise<void> => {\n while (nextIndex < itemCount) {\n if (signal?.aborted) {\n truncated = true;\n signal.throwIfAborted();\n }\n\n const index = nextIndex;\n nextIndex += 1;\n const item = items[index];\n if (item === undefined) {\n continue;\n }\n\n try {\n // No abort check after the processor: once an item has run, its\n // result is real work that a write caller may have committed to\n // disk. Discarding it here would report a finished append as\n // failed, and a client retry would append twice.\n const value = await processor(item, index);\n results.push({ index, value });\n } catch (error) {\n errors.push({\n index,\n error: normalizeUnknownError(error),\n });\n }\n }\n };\n\n const workerCount = Math.min(itemCount, concurrency);\n const workers: Promise<void>[] = new Array<Promise<void>>(workerCount);\n for (let index = 0; index < workerCount; index += 1) {\n workers[index] = next();\n }\n\n await Promise.allSettled(workers);\n // A deadline (AbortSignal.timeout) hit during the run surfaces here as\n // signal.reason — a TimeoutError — rather than a fresh AbortError, so\n // callers see TIMEOUT, not CANCELLED. Only a run that actually skipped\n // items reports the abort: a deadline firing after the last item\n // finished leaves a complete batch, and returning it beats telling the\n // caller that committed writes failed. The per-item throws above are\n // swallowed by allSettled.\n if (truncated) signal?.throwIfAborted();\n\n results.sort((left, right) => left.index - right.index);\n return { results, errors };\n}\n\n/**\n * The streaming sibling of {@link processInParallel}: bounded-concurrency\n * dispatch over an AsyncIterable that may be far larger than the caller wants\n * to walk, so it stops early and reports why.\n *\n * `maxEntries` caps how many entries are dispatched (maxFiles); `shouldStop`\n * lets the caller stop on its own accumulating result count (maxResults). Both\n * are checked before dispatch, so the returned reason is exactly one — the\n * loop breaks on the first that fires. `undefined` means every entry was\n * dispatched.\n */\nexport async function processEntriesConcurrently(\n entries: AsyncIterable<{ path: string }> | Iterable<{ path: string }>,\n options: {\n signal: AbortSignal | undefined;\n concurrency: number;\n maxEntries?: number;\n shouldStop?: () => boolean;\n onEntry: () => void;\n onError?: (entryPath: string, err: unknown) => void;\n runEntry: (entryPath: string) => Promise<void>;\n },\n): Promise<StoppedReason | undefined> {\n const pending = new Set<Promise<void>>();\n const { signal, concurrency, maxEntries, shouldStop, onEntry, onError, runEntry } = options;\n let stoppedReason: StoppedReason | undefined;\n let dispatched = 0;\n\n const waitForSlot = async (): Promise<void> => {\n if (pending.size < concurrency) return;\n await Promise.race(pending);\n };\n\n let walkFailed = false;\n let walkError: unknown;\n try {\n for await (const entry of entries) {\n // The signal is cancellation OR the caller's timeout: stop dispatching and\n // let the caller report the run as incomplete rather than as a full sweep.\n if (signal?.aborted) {\n stoppedReason = 'timeout';\n break;\n }\n if (maxEntries !== undefined && dispatched >= maxEntries) {\n stoppedReason = 'maxFiles';\n break;\n }\n // Check the result cap before waiting for a slot so an in-flight task that\n // already crossed the cap stops dispatch without an extra wait...\n if (shouldStop?.()) {\n stoppedReason = 'maxResults';\n break;\n }\n await waitForSlot();\n // ...and again after the slot frees, since tasks settle concurrently. The\n // cap can still be exceeded by at most `concurrency - 1` already-dispatched\n // tasks that are mid-flight; that overrun is inherent to concurrent dispatch.\n if (shouldStop?.()) {\n stoppedReason = 'maxResults';\n break;\n }\n onEntry();\n dispatched++;\n\n // Track a non-rejecting wrapper so a rejected task can never propagate out of\n // Promise.race(pending) in waitForSlot() and abort the loop before the final\n // drain below (which would silently abandon other in-flight tasks).\n // runEntry is expected to catch its own errors; if it unexpectedly throws,\n // record it as a failure rather than silently dropping it.\n const tracked = runEntry(entry.path).catch((err: unknown) => {\n onError?.(entry.path, err);\n });\n pending.add(tracked);\n void tracked.finally(() => {\n pending.delete(tracked);\n });\n }\n } catch (error) {\n // A walk the signal cut short throws its reason (see globEntries): that is\n // the same timeout as the check above, not a failed walk.\n if (signal?.aborted) stoppedReason = 'timeout';\n else {\n walkFailed = true;\n walkError = error;\n }\n }\n\n if (pending.size > 0) {\n await Promise.allSettled([...pending]);\n }\n\n if (walkFailed) throw walkError;\n return stoppedReason;\n}\n\nexport function withAbort<T>(promise: Promise<T>, signal?: AbortSignal): Promise<T> {\n if (!signal) {\n return promise;\n }\n signal.throwIfAborted();\n let onAbort: (() => void) | undefined;\n return Promise.race([\n promise,\n new Promise<never>((_, reject) => {\n onAbort = () => {\n reject(signal.reason instanceof Error ? signal.reason : new Error('Operation aborted'));\n };\n signal.addEventListener('abort', onAbort, { once: true });\n }),\n ]).finally(() => {\n if (onAbort) {\n signal.removeEventListener('abort', onAbort);\n }\n });\n}\n"]}
|
package/dist/core/errors.d.ts
CHANGED
|
@@ -21,8 +21,8 @@ export interface Problem {
|
|
|
21
21
|
readonly suggestion?: string;
|
|
22
22
|
}
|
|
23
23
|
interface ProblemFactoryOptions {
|
|
24
|
-
path?: string;
|
|
25
|
-
suggestion?: string;
|
|
24
|
+
path?: string | undefined;
|
|
25
|
+
suggestion?: string | undefined;
|
|
26
26
|
}
|
|
27
27
|
export declare const Problem: {
|
|
28
28
|
readonly invalidInput: (msg: string, o?: ProblemFactoryOptions) => Problem;
|
|
@@ -51,7 +51,8 @@ export declare function formatUnknownErrorMessage(error: unknown): string;
|
|
|
51
51
|
export declare function normalizeUnknownError(error: unknown): Error;
|
|
52
52
|
export declare class FsError extends Error {
|
|
53
53
|
readonly problem: Problem;
|
|
54
|
-
|
|
54
|
+
/** `suggestion` replaces the code's default for a thrower that knows the better next step. */
|
|
55
|
+
constructor(code: ErrorCode, message: string, path?: string, cause?: unknown, suggestion?: string | undefined);
|
|
55
56
|
get code(): ErrorCode;
|
|
56
57
|
}
|
|
57
58
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS;;;;;;;;;;;;;;CAcZ,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,OAAO,SAAS,CAAC,CAAC;AAEnE,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,UAAU,qBAAqB;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS;;;;;;;;;;;;;;CAcZ,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,OAAO,SAAS,CAAC,CAAC;AAEnE,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,UAAU,qBAAqB;IAC7B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC;AAWD,eAAO,MAAM,OAAO;iCACE,MAAM,MAAM,qBAAqB,KAAG,OAAO;iCAE3C,MAAM,MAAM,qBAAqB,KAAG,OAAO;8BAE9C,MAAM,MAAM,qBAAqB,KAAG,OAAO;kCAEzC,OAAO,eAAe,SAAS,SAAS,MAAM,KAAG,OAAO;6BAW7D,OAAO,eAAe,SAAS,KAAG,MAAM;CAG9C,CAAC;AAoCX,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,SAAS,CAOpD,CAAC;AA0CH,gFAAgF;AAChF,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAS1D;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,OAAO,CAE1D;AAoBD,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,cAAc,CAK1E;AAED,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,cAAc,CAE9E;AAED,mFAAmF;AACnF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,cAAc,CAE/E;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAMrD;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAQhE;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAE3D;AAeD,qBAAa,OAAQ,SAAQ,KAAK;IAChC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAE1B,8FAA8F;gBAE5F,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,MAAM,EACb,KAAK,CAAC,EAAE,OAAO,EACf,UAAU,GAAE,MAAM,GAAG,SAAqC;IAO5D,IAAI,IAAI,IAAI,SAAS,CAEpB;CACF"}
|
package/dist/core/errors.js
CHANGED
|
@@ -32,11 +32,7 @@ export const Problem = {
|
|
|
32
32
|
const suggestion = (shouldOverride ? DEFAULT_SUGGESTIONS[code] : undefined) ??
|
|
33
33
|
problem.suggestion ??
|
|
34
34
|
DEFAULT_SUGGESTIONS[problem.code];
|
|
35
|
-
|
|
36
|
-
return build(code, problem.message, {
|
|
37
|
-
...(resolvedPath !== undefined ? { path: resolvedPath } : {}),
|
|
38
|
-
...(suggestion !== undefined ? { suggestion } : {}),
|
|
39
|
-
});
|
|
35
|
+
return build(code, problem.message, { path: path ?? problem.path, suggestion });
|
|
40
36
|
},
|
|
41
37
|
toText(error, defaultCode) {
|
|
42
38
|
return formatDetailedError(Problem.fromUnknown(error, defaultCode));
|
|
@@ -121,9 +117,7 @@ export function classifyCauseChain(error) {
|
|
|
121
117
|
if (timedOut)
|
|
122
118
|
return build(ErrorCode.TIMEOUT, message);
|
|
123
119
|
if (errno !== undefined) {
|
|
124
|
-
return build(ERRNO_MAP[errno.code] ?? ErrorCode.IO_ERROR, message, {
|
|
125
|
-
...(errno.path !== undefined ? { path: errno.path } : {}),
|
|
126
|
-
});
|
|
120
|
+
return build(ERRNO_MAP[errno.code] ?? ErrorCode.IO_ERROR, message, { path: errno.path });
|
|
127
121
|
}
|
|
128
122
|
return build(ErrorCode.UNKNOWN, message);
|
|
129
123
|
}
|
|
@@ -206,15 +200,10 @@ function formatDetailedError(error) {
|
|
|
206
200
|
}
|
|
207
201
|
export class FsError extends Error {
|
|
208
202
|
problem;
|
|
209
|
-
|
|
203
|
+
/** `suggestion` replaces the code's default for a thrower that knows the better next step. */
|
|
204
|
+
constructor(code, message, path, cause, suggestion = DEFAULT_SUGGESTIONS[code]) {
|
|
210
205
|
super(message, cause === undefined ? {} : { cause });
|
|
211
|
-
|
|
212
|
-
this.problem = {
|
|
213
|
-
code,
|
|
214
|
-
message,
|
|
215
|
-
...(path !== undefined ? { path } : {}),
|
|
216
|
-
...(suggestion !== undefined ? { suggestion } : {}),
|
|
217
|
-
};
|
|
206
|
+
this.problem = build(code, message, { path, suggestion });
|
|
218
207
|
this.name = 'FsError';
|
|
219
208
|
}
|
|
220
209
|
get code() {
|
package/dist/core/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"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","sourcesContent":["export const ErrorCode = {\n ACCESS_DENIED: 'ACCESS_DENIED',\n NOT_FOUND: 'NOT_FOUND',\n NOT_FILE: 'NOT_FILE',\n NOT_DIRECTORY: 'NOT_DIRECTORY',\n TOO_LARGE: 'TOO_LARGE',\n TIMEOUT: 'TIMEOUT',\n CANCELLED: 'CANCELLED',\n INVALID_PATTERN: 'INVALID_PATTERN',\n INVALID_INPUT: 'INVALID_INPUT',\n PERMISSION_DENIED: 'PERMISSION_DENIED',\n SYMLINK_NOT_ALLOWED: 'SYMLINK_NOT_ALLOWED',\n IO_ERROR: 'IO_ERROR',\n UNKNOWN: 'UNKNOWN',\n} as const;\n\nexport type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];\n\nexport interface Problem {\n readonly code: ErrorCode;\n readonly message: string;\n readonly path?: string;\n readonly suggestion?: string;\n}\n\ninterface ProblemFactoryOptions {\n path?: string;\n suggestion?: string;\n}\n\nfunction build(code: ErrorCode, message: string, opts: ProblemFactoryOptions = {}): Problem {\n return {\n code,\n message,\n ...(opts.path !== undefined ? { path: opts.path } : {}),\n ...(opts.suggestion !== undefined ? { suggestion: opts.suggestion } : {}),\n };\n}\n\nexport const Problem = {\n invalidInput: (msg: string, o?: ProblemFactoryOptions): Problem =>\n build(ErrorCode.INVALID_INPUT, msg, o),\n accessDenied: (msg: string, o?: ProblemFactoryOptions): Problem =>\n build(ErrorCode.ACCESS_DENIED, msg, o),\n cancelled: (msg: string, o?: ProblemFactoryOptions): Problem =>\n build(ErrorCode.CANCELLED, msg, o),\n fromUnknown(error: unknown, defaultCode: ErrorCode, path?: string): Problem {\n const problem = classify(error);\n const shouldOverride =\n problem.code === ErrorCode.UNKNOWN || problem.code === ErrorCode.IO_ERROR;\n const code = shouldOverride ? defaultCode : problem.code;\n const suggestion =\n (shouldOverride ? DEFAULT_SUGGESTIONS[code] : undefined) ??\n problem.suggestion ??\n DEFAULT_SUGGESTIONS[problem.code];\n const resolvedPath = path ?? problem.path;\n return build(code, problem.message, {\n ...(resolvedPath !== undefined ? { path: resolvedPath } : {}),\n ...(suggestion !== undefined ? { suggestion } : {}),\n });\n },\n toText(error: unknown, defaultCode: ErrorCode): string {\n return formatDetailedError(Problem.fromUnknown(error, defaultCode));\n },\n} as const;\n\nconst DEFAULT_SUGGESTIONS: Readonly<Partial<Record<ErrorCode, string>>> = {\n [ErrorCode.ACCESS_DENIED]: 'Run list_roots to list allowed directories.',\n [ErrorCode.NOT_FOUND]: 'Run list or find_files to verify the path.',\n [ErrorCode.NOT_FILE]: 'Target is a directory, not a file.',\n [ErrorCode.NOT_DIRECTORY]: 'Target is a file, not a directory.',\n [ErrorCode.TOO_LARGE]: 'Use head/tail or line ranges to read partially.',\n [ErrorCode.TIMEOUT]: 'Reduce scope, depth, or maxResults.',\n [ErrorCode.INVALID_PATTERN]: 'Check syntax and escape special characters.',\n [ErrorCode.PERMISSION_DENIED]: 'Check OS file permissions.',\n [ErrorCode.SYMLINK_NOT_ALLOWED]: 'Symlink escapes allowed directories.',\n};\n\nconst ERRNO_MAP: Readonly<Record<string, ErrorCode>> = {\n ENOENT: ErrorCode.NOT_FOUND,\n EACCES: ErrorCode.PERMISSION_DENIED,\n EPERM: ErrorCode.PERMISSION_DENIED,\n ENOTDIR: ErrorCode.NOT_DIRECTORY,\n EISDIR: ErrorCode.NOT_FILE,\n ELOOP: ErrorCode.SYMLINK_NOT_ALLOWED,\n ENAMETOOLONG: ErrorCode.INVALID_INPUT,\n ETIMEDOUT: ErrorCode.TIMEOUT,\n EMFILE: ErrorCode.IO_ERROR,\n ENFILE: ErrorCode.IO_ERROR,\n EBUSY: ErrorCode.IO_ERROR,\n ENOTEMPTY: ErrorCode.NOT_DIRECTORY,\n EEXIST: ErrorCode.INVALID_INPUT,\n EINVAL: ErrorCode.INVALID_INPUT,\n};\n\nconst ERRNO_RE = /^E[A-Z]+$/;\n\n// NOT_FOUND is in here (not just ENOENT) because a dangling symlink whose\n// target sits inside an allowed root surfaces as an FsError NOT_FOUND. Skipping\n// the entry is the point of a listing; rethrowing would fail the whole listing.\nexport const SKIPPABLE_FS_CODES: ReadonlySet<ErrorCode> = new Set([\n ErrorCode.ACCESS_DENIED,\n ErrorCode.NOT_FOUND,\n // OS-level EACCES/EPERM on a symlink target during a listing is exactly as\n // skippable as the other three codes.\n ErrorCode.PERMISSION_DENIED,\n ErrorCode.SYMLINK_NOT_ALLOWED,\n]);\n\nconst SKIPPABLE_ERRNOS: ReadonlySet<string> = new Set(['ENOENT', 'EACCES', 'ELOOP']);\n\n/**\n * Walk `error` and its `cause` chain once for the three facts error handling\n * needs: an abort anywhere, a timeout anywhere, and the FIRST errno seen.\n * `visited` guards a cyclic chain. A node that reads as an abort or a timeout\n * never also contributes its errno.\n */\nfunction scanCauseChain(error: unknown): {\n aborted: boolean;\n timedOut: boolean;\n errno: { code: string; path?: string } | undefined;\n} {\n const visited = new Set<unknown>();\n let aborted = false;\n let timedOut = false;\n let errno: { code: string; path?: string } | undefined;\n\n for (\n let current: unknown = error;\n current !== undefined && current !== null && !visited.has(current);\n current = (current as { cause?: unknown }).cause\n ) {\n visited.add(current);\n if (!(current instanceof Error)) continue;\n const raw = (current as { code?: unknown }).code;\n const code = typeof raw === 'string' ? raw : undefined;\n if (current.name === 'AbortError' || code === 'ABORT_ERR') {\n aborted = true;\n } else if (current.name === 'TimeoutError' || code === 'ETIMEDOUT') {\n timedOut = true;\n } else if (errno === undefined && code !== undefined && ERRNO_RE.test(code)) {\n const { path } = current as NodeJS.ErrnoException;\n errno = { code, ...(typeof path === 'string' ? { path } : {}) };\n }\n }\n\n return { aborted, timedOut, errno };\n}\n\n/** The scan's facts as a Problem: an abort wins, then a timeout, then errno. */\nexport function classifyCauseChain(error: unknown): Problem {\n const message = formatUnknownErrorMessage(error);\n const { aborted, timedOut, errno } = scanCauseChain(error);\n if (aborted) return Problem.cancelled(message);\n if (timedOut) return build(ErrorCode.TIMEOUT, message);\n if (errno !== undefined) {\n return build(ERRNO_MAP[errno.code] ?? ErrorCode.IO_ERROR, message, {\n ...(errno.path !== undefined ? { path: errno.path } : {}),\n });\n }\n return build(ErrorCode.UNKNOWN, message);\n}\n\nexport function isFsError(error: unknown): error is FsError {\n return error instanceof FsError;\n}\n\nfunction classify(error: unknown): Problem {\n if (error === null || error === undefined) {\n return build(ErrorCode.UNKNOWN, 'Unknown error');\n }\n if (isFsError(error)) return error.problem;\n // No `ZodError` branch, deliberately. Tool arguments are validated by the\n // SDK from the zod schema `defineTool` hands it (tools/define.ts); the SDK\n // formats issues itself and never throws a ZodError into a handler, and\n // nothing in `src/` calls `.parse()`. A ZodError reaching here would fall\n // through to UNKNOWN with Zod's raw JSON-dump `.message`, so if a\n // `.parse()` is ever added, add the branch back with it rather than\n // discovering this.\n if (!(error instanceof Error)) {\n return build(ErrorCode.UNKNOWN, typeof error === 'string' ? error : '[non-Error thrown]');\n }\n return classifyCauseChain(error);\n}\n\nexport function isNodeError(error: unknown): error is NodeJS.ErrnoException {\n if (!(error instanceof Error)) return false;\n if (!('code' in error)) return false;\n const { code } = error as { code?: unknown };\n return typeof code === 'string';\n}\n\n/** True when `error` is a Node errno error with code `ENOENT` (path not found). */\nexport function isNotFoundErrno(error: unknown): error is NodeJS.ErrnoException {\n return isNodeError(error) && error.code === 'ENOENT';\n}\n\n/** True when `error` is a Node errno error whose code is in `SKIPPABLE_ERRNOS`. */\nexport function isSkippableErrno(error: unknown): error is NodeJS.ErrnoException {\n return isNodeError(error) && error.code !== undefined && SKIPPABLE_ERRNOS.has(error.code);\n}\n\n/**\n * Rethrow when `error` reads as cancelled. Answers the question directly rather\n * than through `classify`, which allocated a Problem — and ran\n * `formatUnknownErrorMessage`, i.e. a `JSON.stringify` on a non-Error — for a\n * boolean. This sits in eight catch blocks, several inside per-entry scan loops.\n */\nexport function rethrowIfAborted(error: unknown): void {\n if (isFsError(error)) {\n if (error.code === ErrorCode.CANCELLED) throw error;\n return;\n }\n if (scanCauseChain(error).aborted) throw error;\n}\n\nexport function formatUnknownErrorMessage(error: unknown): string {\n if (typeof error === 'string') return error;\n if (error instanceof Error) return error.message;\n try {\n return JSON.stringify(error);\n } catch {\n return `[non-serializable: ${Object.prototype.toString.call(error)}]`;\n }\n}\n\nexport function normalizeUnknownError(error: unknown): Error {\n return error instanceof Error ? error : new Error(formatUnknownErrorMessage(error));\n}\n\nfunction formatDetailedError(\n error: Pick<Problem, 'code' | 'message' | 'path' | 'suggestion'>,\n): string {\n const lines: string[] = [`${error.code}: ${error.message}`];\n if (error.path && !error.message.includes(error.path)) {\n lines.push(error.path);\n }\n if (error.suggestion) {\n lines.push(error.suggestion);\n }\n return lines.join('\\n');\n}\n\nexport class FsError extends Error {\n readonly problem: Problem;\n\n constructor(code: ErrorCode, message: string, path?: string, cause?: unknown) {\n super(message, cause === undefined ? {} : { cause });\n const suggestion = DEFAULT_SUGGESTIONS[code];\n this.problem = {\n code,\n message,\n ...(path !== undefined ? { path } : {}),\n ...(suggestion !== undefined ? { suggestion } : {}),\n };\n this.name = 'FsError';\n }\n\n get code(): ErrorCode {\n return this.problem.code;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"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","sourcesContent":["export const ErrorCode = {\n ACCESS_DENIED: 'ACCESS_DENIED',\n NOT_FOUND: 'NOT_FOUND',\n NOT_FILE: 'NOT_FILE',\n NOT_DIRECTORY: 'NOT_DIRECTORY',\n TOO_LARGE: 'TOO_LARGE',\n TIMEOUT: 'TIMEOUT',\n CANCELLED: 'CANCELLED',\n INVALID_PATTERN: 'INVALID_PATTERN',\n INVALID_INPUT: 'INVALID_INPUT',\n PERMISSION_DENIED: 'PERMISSION_DENIED',\n SYMLINK_NOT_ALLOWED: 'SYMLINK_NOT_ALLOWED',\n IO_ERROR: 'IO_ERROR',\n UNKNOWN: 'UNKNOWN',\n} as const;\n\nexport type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];\n\nexport interface Problem {\n readonly code: ErrorCode;\n readonly message: string;\n readonly path?: string;\n readonly suggestion?: string;\n}\n\ninterface ProblemFactoryOptions {\n path?: string | undefined;\n suggestion?: string | undefined;\n}\n\nfunction build(code: ErrorCode, message: string, opts: ProblemFactoryOptions = {}): Problem {\n return {\n code,\n message,\n ...(opts.path !== undefined ? { path: opts.path } : {}),\n ...(opts.suggestion !== undefined ? { suggestion: opts.suggestion } : {}),\n };\n}\n\nexport const Problem = {\n invalidInput: (msg: string, o?: ProblemFactoryOptions): Problem =>\n build(ErrorCode.INVALID_INPUT, msg, o),\n accessDenied: (msg: string, o?: ProblemFactoryOptions): Problem =>\n build(ErrorCode.ACCESS_DENIED, msg, o),\n cancelled: (msg: string, o?: ProblemFactoryOptions): Problem =>\n build(ErrorCode.CANCELLED, msg, o),\n fromUnknown(error: unknown, defaultCode: ErrorCode, path?: string): Problem {\n const problem = classify(error);\n const shouldOverride =\n problem.code === ErrorCode.UNKNOWN || problem.code === ErrorCode.IO_ERROR;\n const code = shouldOverride ? defaultCode : problem.code;\n const suggestion =\n (shouldOverride ? DEFAULT_SUGGESTIONS[code] : undefined) ??\n problem.suggestion ??\n DEFAULT_SUGGESTIONS[problem.code];\n return build(code, problem.message, { path: path ?? problem.path, suggestion });\n },\n toText(error: unknown, defaultCode: ErrorCode): string {\n return formatDetailedError(Problem.fromUnknown(error, defaultCode));\n },\n} as const;\n\nconst DEFAULT_SUGGESTIONS: Readonly<Partial<Record<ErrorCode, string>>> = {\n [ErrorCode.ACCESS_DENIED]: 'Run list_roots to list allowed directories.',\n [ErrorCode.NOT_FOUND]: 'Run list or find_files to verify the path.',\n [ErrorCode.NOT_FILE]: 'Target is a directory, not a file.',\n [ErrorCode.NOT_DIRECTORY]: 'Target is a file, not a directory.',\n [ErrorCode.TOO_LARGE]: 'Use head/tail or line ranges to read partially.',\n [ErrorCode.TIMEOUT]: 'Reduce scope, depth, or maxResults.',\n [ErrorCode.INVALID_PATTERN]: 'Check syntax and escape special characters.',\n [ErrorCode.PERMISSION_DENIED]: 'Check OS file permissions.',\n [ErrorCode.SYMLINK_NOT_ALLOWED]: 'Symlink escapes allowed directories.',\n};\n\nconst ERRNO_MAP: Readonly<Record<string, ErrorCode>> = {\n ENOENT: ErrorCode.NOT_FOUND,\n EACCES: ErrorCode.PERMISSION_DENIED,\n EPERM: ErrorCode.PERMISSION_DENIED,\n ENOTDIR: ErrorCode.NOT_DIRECTORY,\n EISDIR: ErrorCode.NOT_FILE,\n ELOOP: ErrorCode.SYMLINK_NOT_ALLOWED,\n ENAMETOOLONG: ErrorCode.INVALID_INPUT,\n ETIMEDOUT: ErrorCode.TIMEOUT,\n EMFILE: ErrorCode.IO_ERROR,\n ENFILE: ErrorCode.IO_ERROR,\n EBUSY: ErrorCode.IO_ERROR,\n ENOTEMPTY: ErrorCode.NOT_DIRECTORY,\n EEXIST: ErrorCode.INVALID_INPUT,\n EINVAL: ErrorCode.INVALID_INPUT,\n};\n\nconst ERRNO_RE = /^E[A-Z]+$/;\n\n// NOT_FOUND is in here (not just ENOENT) because a dangling symlink whose\n// target sits inside an allowed root surfaces as an FsError NOT_FOUND. Skipping\n// the entry is the point of a listing; rethrowing would fail the whole listing.\nexport const SKIPPABLE_FS_CODES: ReadonlySet<ErrorCode> = new Set([\n ErrorCode.ACCESS_DENIED,\n ErrorCode.NOT_FOUND,\n // OS-level EACCES/EPERM on a symlink target during a listing is exactly as\n // skippable as the other three codes.\n ErrorCode.PERMISSION_DENIED,\n ErrorCode.SYMLINK_NOT_ALLOWED,\n]);\n\nconst SKIPPABLE_ERRNOS: ReadonlySet<string> = new Set(['ENOENT', 'EACCES', 'ELOOP']);\n\n/**\n * Walk `error` and its `cause` chain once for the three facts error handling\n * needs: an abort anywhere, a timeout anywhere, and the FIRST errno seen.\n * `visited` guards a cyclic chain. A node that reads as an abort or a timeout\n * never also contributes its errno.\n */\nfunction scanCauseChain(error: unknown): {\n aborted: boolean;\n timedOut: boolean;\n errno: { code: string; path?: string } | undefined;\n} {\n const visited = new Set<unknown>();\n let aborted = false;\n let timedOut = false;\n let errno: { code: string; path?: string } | undefined;\n\n for (\n let current: unknown = error;\n current !== undefined && current !== null && !visited.has(current);\n current = (current as { cause?: unknown }).cause\n ) {\n visited.add(current);\n if (!(current instanceof Error)) continue;\n const raw = (current as { code?: unknown }).code;\n const code = typeof raw === 'string' ? raw : undefined;\n if (current.name === 'AbortError' || code === 'ABORT_ERR') {\n aborted = true;\n } else if (current.name === 'TimeoutError' || code === 'ETIMEDOUT') {\n timedOut = true;\n } else if (errno === undefined && code !== undefined && ERRNO_RE.test(code)) {\n const { path } = current as NodeJS.ErrnoException;\n errno = { code, ...(typeof path === 'string' ? { path } : {}) };\n }\n }\n\n return { aborted, timedOut, errno };\n}\n\n/** The scan's facts as a Problem: an abort wins, then a timeout, then errno. */\nexport function classifyCauseChain(error: unknown): Problem {\n const message = formatUnknownErrorMessage(error);\n const { aborted, timedOut, errno } = scanCauseChain(error);\n if (aborted) return Problem.cancelled(message);\n if (timedOut) return build(ErrorCode.TIMEOUT, message);\n if (errno !== undefined) {\n return build(ERRNO_MAP[errno.code] ?? ErrorCode.IO_ERROR, message, { path: errno.path });\n }\n return build(ErrorCode.UNKNOWN, message);\n}\n\nexport function isFsError(error: unknown): error is FsError {\n return error instanceof FsError;\n}\n\nfunction classify(error: unknown): Problem {\n if (error === null || error === undefined) {\n return build(ErrorCode.UNKNOWN, 'Unknown error');\n }\n if (isFsError(error)) return error.problem;\n // No `ZodError` branch, deliberately. Tool arguments are validated by the\n // SDK from the zod schema `defineTool` hands it (tools/define.ts); the SDK\n // formats issues itself and never throws a ZodError into a handler, and\n // nothing in `src/` calls `.parse()`. A ZodError reaching here would fall\n // through to UNKNOWN with Zod's raw JSON-dump `.message`, so if a\n // `.parse()` is ever added, add the branch back with it rather than\n // discovering this.\n if (!(error instanceof Error)) {\n return build(ErrorCode.UNKNOWN, typeof error === 'string' ? error : '[non-Error thrown]');\n }\n return classifyCauseChain(error);\n}\n\nexport function isNodeError(error: unknown): error is NodeJS.ErrnoException {\n if (!(error instanceof Error)) return false;\n if (!('code' in error)) return false;\n const { code } = error as { code?: unknown };\n return typeof code === 'string';\n}\n\n/** True when `error` is a Node errno error with code `ENOENT` (path not found). */\nexport function isNotFoundErrno(error: unknown): error is NodeJS.ErrnoException {\n return isNodeError(error) && error.code === 'ENOENT';\n}\n\n/** True when `error` is a Node errno error whose code is in `SKIPPABLE_ERRNOS`. */\nexport function isSkippableErrno(error: unknown): error is NodeJS.ErrnoException {\n return isNodeError(error) && error.code !== undefined && SKIPPABLE_ERRNOS.has(error.code);\n}\n\n/**\n * Rethrow when `error` reads as cancelled. Answers the question directly rather\n * than through `classify`, which allocated a Problem — and ran\n * `formatUnknownErrorMessage`, i.e. a `JSON.stringify` on a non-Error — for a\n * boolean. This sits in eight catch blocks, several inside per-entry scan loops.\n */\nexport function rethrowIfAborted(error: unknown): void {\n if (isFsError(error)) {\n if (error.code === ErrorCode.CANCELLED) throw error;\n return;\n }\n if (scanCauseChain(error).aborted) throw error;\n}\n\nexport function formatUnknownErrorMessage(error: unknown): string {\n if (typeof error === 'string') return error;\n if (error instanceof Error) return error.message;\n try {\n return JSON.stringify(error);\n } catch {\n return `[non-serializable: ${Object.prototype.toString.call(error)}]`;\n }\n}\n\nexport function normalizeUnknownError(error: unknown): Error {\n return error instanceof Error ? error : new Error(formatUnknownErrorMessage(error));\n}\n\nfunction formatDetailedError(\n error: Pick<Problem, 'code' | 'message' | 'path' | 'suggestion'>,\n): string {\n const lines: string[] = [`${error.code}: ${error.message}`];\n if (error.path && !error.message.includes(error.path)) {\n lines.push(error.path);\n }\n if (error.suggestion) {\n lines.push(error.suggestion);\n }\n return lines.join('\\n');\n}\n\nexport class FsError extends Error {\n readonly problem: Problem;\n\n /** `suggestion` replaces the code's default for a thrower that knows the better next step. */\n constructor(\n code: ErrorCode,\n message: string,\n path?: string,\n cause?: unknown,\n suggestion: string | undefined = DEFAULT_SUGGESTIONS[code],\n ) {\n super(message, cause === undefined ? {} : { cause });\n this.problem = build(code, message, { path, suggestion });\n this.name = 'FsError';\n }\n\n get code(): ErrorCode {\n return this.problem.code;\n }\n}\n"]}
|
package/dist/core/fs.d.ts
CHANGED
|
@@ -6,19 +6,17 @@ import type { PathGuard } from './path.ts';
|
|
|
6
6
|
import type { ReadFileResult, ReadSpec } from './read.ts';
|
|
7
7
|
export type { FileType };
|
|
8
8
|
export type { Stats };
|
|
9
|
-
/**
|
|
10
|
-
* Line count for a file on disk, counting newline bytes in fixed 64 KiB
|
|
11
|
-
* chunks so an arbitrarily large file (one append's result metadata) costs
|
|
12
|
-
* bounded memory. NOT FileHandle.readLines: it decodes each physical line
|
|
13
|
-
* whole, so a multi-GB single-line log OOMs the server after the append has
|
|
14
|
-
* already landed — a reported failure invites a retry that appends twice.
|
|
15
|
-
* Matches read.ts's countLines semantics: a trailing newline does not open
|
|
16
|
-
* a new line, an unterminated final line counts, an empty file is 0.
|
|
17
|
-
*/
|
|
18
|
-
export declare function countFileLines(filePath: string): Promise<number>;
|
|
19
9
|
export declare class GuardedFileSystem {
|
|
10
|
+
#private;
|
|
20
11
|
readonly pathGuard: PathGuard;
|
|
21
12
|
constructor(pathGuard: PathGuard);
|
|
13
|
+
/**
|
|
14
|
+
* Serialize a read-modify-write on the resolved write target, so two writers
|
|
15
|
+
* of one file (any spelling, including via a symlinked parent) cannot both
|
|
16
|
+
* read the same base and have the last rename win. `writeFile`/`appendFile`
|
|
17
|
+
* do not take the lock, so `fn` may call them.
|
|
18
|
+
*/
|
|
19
|
+
lockForWrite<T>(filePath: string, fn: (resolvedTarget: string) => Promise<T>): Promise<T>;
|
|
22
20
|
stat(filePath: string, options?: {
|
|
23
21
|
signal?: AbortSignal | undefined;
|
|
24
22
|
}): Promise<{
|
|
@@ -58,7 +56,17 @@ export declare class GuardedFileSystem {
|
|
|
58
56
|
* file — an append's result must describe the resulting file (which may be
|
|
59
57
|
* a multi-GB log), not the chunk that was appended.
|
|
60
58
|
*/
|
|
61
|
-
readLeadingSample(filePath: string
|
|
59
|
+
readLeadingSample(filePath: string): Promise<Buffer>;
|
|
60
|
+
/**
|
|
61
|
+
* Line count for a file on disk, counting newline bytes in fixed 64 KiB
|
|
62
|
+
* chunks so an arbitrarily large file (one append's result metadata) costs
|
|
63
|
+
* bounded memory. NOT FileHandle.readLines: it decodes each physical line
|
|
64
|
+
* whole, so a multi-GB single-line log OOMs the server after the append has
|
|
65
|
+
* already landed — a reported failure invites a retry that appends twice.
|
|
66
|
+
* Matches read.ts's countLines semantics: a trailing newline does not open
|
|
67
|
+
* a new line, an unterminated final line counts, an empty file is 0.
|
|
68
|
+
*/
|
|
69
|
+
countFileLines(filePath: string): Promise<number>;
|
|
62
70
|
rm(filePath: string, options?: Parameters<typeof fsRm>[1]): Promise<void>;
|
|
63
71
|
rmdir(filePath: string, options?: Parameters<typeof fsRmdir>[1]): Promise<void>;
|
|
64
72
|
cp(source: string, destination: string, options?: Parameters<typeof fsCp>[2]): Promise<void>;
|
package/dist/core/fs.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/core/fs.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAEL,EAAE,IAAI,IAAI,EAEV,KAAK,IAAI,OAAO,EAIhB,QAAQ,IAAI,UAAU,EAEtB,EAAE,IAAI,IAAI,EACV,KAAK,IAAI,OAAO,EAIjB,MAAM,kBAAkB,CAAC;AAc1B,OAAO,KAAK,EAAE,SAAS,IAAI,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/core/fs.ts"],"names":[],"mappings":"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"}
|