@j0hanz/filesystem-mcp 2.7.6 → 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.
Files changed (108) hide show
  1. package/dist/cli.d.ts +1 -9
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js.map +1 -1
  4. package/dist/core/errors.d.ts +4 -3
  5. package/dist/core/errors.d.ts.map +1 -1
  6. package/dist/core/errors.js +5 -16
  7. package/dist/core/errors.js.map +1 -1
  8. package/dist/core/fs.d.ts +11 -11
  9. package/dist/core/fs.d.ts.map +1 -1
  10. package/dist/core/fs.js +108 -43
  11. package/dist/core/fs.js.map +1 -1
  12. package/dist/core/glob.d.ts +8 -0
  13. package/dist/core/glob.d.ts.map +1 -1
  14. package/dist/core/glob.js +192 -29
  15. package/dist/core/glob.js.map +1 -1
  16. package/dist/core/input-required.d.ts +12 -0
  17. package/dist/core/input-required.d.ts.map +1 -1
  18. package/dist/core/input-required.js +7 -2
  19. package/dist/core/input-required.js.map +1 -1
  20. package/dist/core/observability.d.ts +2 -0
  21. package/dist/core/observability.d.ts.map +1 -1
  22. package/dist/core/observability.js +7 -0
  23. package/dist/core/observability.js.map +1 -1
  24. package/dist/core/path-completer.d.ts.map +1 -1
  25. package/dist/core/path-completer.js +11 -30
  26. package/dist/core/path-completer.js.map +1 -1
  27. package/dist/core/path.d.ts +0 -2
  28. package/dist/core/path.d.ts.map +1 -1
  29. package/dist/core/path.js +12 -29
  30. package/dist/core/path.js.map +1 -1
  31. package/dist/core/read.d.ts +1 -1
  32. package/dist/core/read.d.ts.map +1 -1
  33. package/dist/core/read.js +13 -14
  34. package/dist/core/read.js.map +1 -1
  35. package/dist/core/schema.d.ts +6 -1
  36. package/dist/core/schema.d.ts.map +1 -1
  37. package/dist/core/schema.js +17 -3
  38. package/dist/core/schema.js.map +1 -1
  39. package/dist/core/search.d.ts.map +1 -1
  40. package/dist/core/search.js +104 -51
  41. package/dist/core/search.js.map +1 -1
  42. package/dist/core/store.d.ts +36 -1
  43. package/dist/core/store.d.ts.map +1 -1
  44. package/dist/core/store.js +71 -6
  45. package/dist/core/store.js.map +1 -1
  46. package/dist/core/util.d.ts +34 -5
  47. package/dist/core/util.d.ts.map +1 -1
  48. package/dist/core/util.js +59 -5
  49. package/dist/core/util.js.map +1 -1
  50. package/dist/index.js +5 -16
  51. package/dist/index.js.map +1 -1
  52. package/dist/resources.d.ts +5 -1
  53. package/dist/resources.d.ts.map +1 -1
  54. package/dist/resources.js +45 -22
  55. package/dist/resources.js.map +1 -1
  56. package/dist/server.d.ts +9 -6
  57. package/dist/server.d.ts.map +1 -1
  58. package/dist/server.js +7 -8
  59. package/dist/server.js.map +1 -1
  60. package/dist/tools/create.d.ts.map +1 -1
  61. package/dist/tools/create.js +8 -19
  62. package/dist/tools/create.js.map +1 -1
  63. package/dist/tools/define.d.ts +8 -7
  64. package/dist/tools/define.d.ts.map +1 -1
  65. package/dist/tools/define.js +48 -16
  66. package/dist/tools/define.js.map +1 -1
  67. package/dist/tools/delete.d.ts.map +1 -1
  68. package/dist/tools/delete.js +39 -21
  69. package/dist/tools/delete.js.map +1 -1
  70. package/dist/tools/edit.d.ts.map +1 -1
  71. package/dist/tools/edit.js +24 -39
  72. package/dist/tools/edit.js.map +1 -1
  73. package/dist/tools/find-files.d.ts.map +1 -1
  74. package/dist/tools/find-files.js +49 -60
  75. package/dist/tools/find-files.js.map +1 -1
  76. package/dist/tools/index.d.ts +2 -11
  77. package/dist/tools/index.d.ts.map +1 -1
  78. package/dist/tools/index.js +1 -9
  79. package/dist/tools/index.js.map +1 -1
  80. package/dist/tools/list.d.ts.map +1 -1
  81. package/dist/tools/list.js +59 -69
  82. package/dist/tools/list.js.map +1 -1
  83. package/dist/tools/move.d.ts.map +1 -1
  84. package/dist/tools/move.js +5 -1
  85. package/dist/tools/move.js.map +1 -1
  86. package/dist/tools/patch.d.ts.map +1 -1
  87. package/dist/tools/patch.js +3 -6
  88. package/dist/tools/patch.js.map +1 -1
  89. package/dist/tools/read.d.ts.map +1 -1
  90. package/dist/tools/read.js +31 -40
  91. package/dist/tools/read.js.map +1 -1
  92. package/dist/tools/replace-text.d.ts.map +1 -1
  93. package/dist/tools/replace-text.js +23 -32
  94. package/dist/tools/replace-text.js.map +1 -1
  95. package/dist/tools/search-text.d.ts.map +1 -1
  96. package/dist/tools/search-text.js +48 -64
  97. package/dist/tools/search-text.js.map +1 -1
  98. package/dist/transport/http.js +1 -1
  99. package/dist/transport/http.js.map +1 -1
  100. package/dist/transport/shared.d.ts +7 -5
  101. package/dist/transport/shared.d.ts.map +1 -1
  102. package/dist/transport/shared.js +8 -2
  103. package/dist/transport/shared.js.map +1 -1
  104. package/dist/transport/stdio.d.ts +4 -1
  105. package/dist/transport/stdio.d.ts.map +1 -1
  106. package/dist/transport/stdio.js +45 -12
  107. package/dist/transport/stdio.js.map +1 -1
  108. package/package.json +3 -2
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,CAAC,OAAO,EAAE;IAC5C,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,mFAAmF;IACnF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmDhB"}
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"]}
@@ -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
- constructor(code: ErrorCode, message: string, path?: string, cause?: unknown);
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;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;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;6BAe7D,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,CAW1D;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;gBAEd,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;IAY5E,IAAI,IAAI,IAAI,SAAS,CAEpB;CACF"}
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"}
@@ -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
- const resolvedPath = path ?? problem.path;
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
- constructor(code, message, path, cause) {
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
- const suggestion = DEFAULT_SUGGESTIONS[code];
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() {
@@ -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,16 +6,6 @@ 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 {
20
10
  #private;
21
11
  readonly pathGuard: PathGuard;
@@ -66,7 +56,17 @@ export declare class GuardedFileSystem {
66
56
  * file — an append's result must describe the resulting file (which may be
67
57
  * a multi-GB log), not the chunk that was appended.
68
58
  */
69
- readLeadingSample(filePath: string, size: number): Promise<Buffer>;
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>;
70
70
  rm(filePath: string, options?: Parameters<typeof fsRm>[1]): Promise<void>;
71
71
  rmdir(filePath: string, options?: Parameters<typeof fsRmdir>[1]): Promise<void>;
72
72
  cp(source: string, destination: string, options?: Parameters<typeof fsCp>[2]): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/core/fs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/core/fs.ts"],"names":[],"mappings":"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"}
package/dist/core/fs.js CHANGED
@@ -1,9 +1,61 @@
1
+ var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
2
+ if (value !== null && value !== void 0) {
3
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
4
+ var dispose, inner;
5
+ if (async) {
6
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
7
+ dispose = value[Symbol.asyncDispose];
8
+ }
9
+ if (dispose === void 0) {
10
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
11
+ dispose = value[Symbol.dispose];
12
+ if (async) inner = dispose;
13
+ }
14
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
15
+ if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
16
+ env.stack.push({ value: value, dispose: dispose, async: async });
17
+ }
18
+ else if (async) {
19
+ env.stack.push({ async: true });
20
+ }
21
+ return value;
22
+ };
23
+ var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
24
+ return function (env) {
25
+ function fail(e) {
26
+ env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
27
+ env.hasError = true;
28
+ }
29
+ var r, s = 0;
30
+ function next() {
31
+ while (r = env.stack.pop()) {
32
+ try {
33
+ if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
34
+ if (r.dispose) {
35
+ var result = r.dispose.call(r.value);
36
+ if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
37
+ }
38
+ else s |= 1;
39
+ }
40
+ catch (e) {
41
+ fail(e);
42
+ }
43
+ }
44
+ if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
45
+ if (env.hasError) throw env.error;
46
+ }
47
+ return next();
48
+ };
49
+ })(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
50
+ var e = new Error(message);
51
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
52
+ });
1
53
  import { randomUUID } from 'node:crypto';
2
54
  import { chmod as fsChmod, cp as fsCp, lstat as fsLstat, mkdir as fsMkdir, open as fsOpen, opendir as fsOpendir, readFile as fsReadFile, readlink as fsReadlink, rename as fsRename, rm as fsRm, rmdir as fsRmdir, stat as fsStat, unlink as fsUnlink, writeFile as fsWriteFile, } from 'node:fs/promises';
3
55
  import { dirname, isAbsolute, resolve } from 'node:path';
4
56
  import { runExclusive, withAbort } from "./concurrency.js";
5
57
  import { ErrorCode, formatUnknownErrorMessage, FsError, isFsError, isNodeError, isNotFoundErrno, } from "./errors.js";
6
- import { detectMimeFromContent } from "./mime.js";
58
+ import { detectMimeFromContent, MIME_SAMPLE_SIZE } from "./mime.js";
7
59
  import { Logger } from "./observability.js";
8
60
  import { normalizePath, respellCaseOnlyTarget } from "./path-utils.js";
9
61
  import { APPEND_CREATE_NOFOLLOW, APPEND_NOFOLLOW, assertFileStats, createTooLargeError, READ_NOFOLLOW, readFileWithStats, } from "./read.js";
@@ -33,42 +85,6 @@ async function resolveForWrite(pathGuard, filePath) {
33
85
  }
34
86
  const CHAR_LF = 10;
35
87
  const LINE_COUNT_CHUNK_BYTES = 64 * 1024;
36
- /**
37
- * Line count for a file on disk, counting newline bytes in fixed 64 KiB
38
- * chunks so an arbitrarily large file (one append's result metadata) costs
39
- * bounded memory. NOT FileHandle.readLines: it decodes each physical line
40
- * whole, so a multi-GB single-line log OOMs the server after the append has
41
- * already landed — a reported failure invites a retry that appends twice.
42
- * Matches read.ts's countLines semantics: a trailing newline does not open
43
- * a new line, an unterminated final line counts, an empty file is 0.
44
- */
45
- export async function countFileLines(filePath) {
46
- const handle = await fsOpen(filePath, READ_NOFOLLOW);
47
- try {
48
- let newlines = 0;
49
- let lastByte = 0;
50
- let totalBytes = 0;
51
- const chunk = Buffer.alloc(LINE_COUNT_CHUNK_BYTES);
52
- for (;;) {
53
- const { bytesRead } = await handle.read(chunk, 0, chunk.length, null);
54
- if (bytesRead === 0)
55
- break;
56
- totalBytes += bytesRead;
57
- for (let i = 0; i < bytesRead; i++) {
58
- const byte = chunk[i] ?? 0;
59
- if (byte === CHAR_LF)
60
- newlines++;
61
- lastByte = byte;
62
- }
63
- }
64
- // totalBytes is the empty-file sentinel: a NUL (0x00) final byte is real
65
- // content and must count as an unterminated final line, not "empty".
66
- return totalBytes === 0 ? 0 : lastByte === CHAR_LF ? newlines : newlines + 1;
67
- }
68
- finally {
69
- await handle.close();
70
- }
71
- }
72
88
  export class GuardedFileSystem {
73
89
  pathGuard;
74
90
  constructor(pathGuard) {
@@ -276,16 +292,65 @@ export class GuardedFileSystem {
276
292
  * file — an append's result must describe the resulting file (which may be
277
293
  * a multi-GB log), not the chunk that was appended.
278
294
  */
279
- async readLeadingSample(filePath, size) {
280
- const { validPath } = await this.stat(filePath);
281
- const handle = await fsOpen(validPath, READ_NOFOLLOW);
295
+ async readLeadingSample(filePath) {
296
+ const env_1 = { stack: [], error: void 0, hasError: false };
282
297
  try {
283
- const buffer = Buffer.alloc(size);
284
- const { bytesRead } = await handle.read(buffer, 0, size, 0);
298
+ const handle = __addDisposableResource(env_1, await this.open(filePath), true);
299
+ const buffer = Buffer.alloc(MIME_SAMPLE_SIZE);
300
+ const { bytesRead } = await handle.read(buffer, 0, MIME_SAMPLE_SIZE, 0);
285
301
  return buffer.subarray(0, bytesRead);
286
302
  }
303
+ catch (e_1) {
304
+ env_1.error = e_1;
305
+ env_1.hasError = true;
306
+ }
287
307
  finally {
288
- await handle.close();
308
+ const result_1 = __disposeResources(env_1);
309
+ if (result_1)
310
+ await result_1;
311
+ }
312
+ }
313
+ /**
314
+ * Line count for a file on disk, counting newline bytes in fixed 64 KiB
315
+ * chunks so an arbitrarily large file (one append's result metadata) costs
316
+ * bounded memory. NOT FileHandle.readLines: it decodes each physical line
317
+ * whole, so a multi-GB single-line log OOMs the server after the append has
318
+ * already landed — a reported failure invites a retry that appends twice.
319
+ * Matches read.ts's countLines semantics: a trailing newline does not open
320
+ * a new line, an unterminated final line counts, an empty file is 0.
321
+ */
322
+ async countFileLines(filePath) {
323
+ const env_2 = { stack: [], error: void 0, hasError: false };
324
+ try {
325
+ const handle = __addDisposableResource(env_2, await this.open(filePath), true);
326
+ let newlines = 0;
327
+ let lastByte = 0;
328
+ let totalBytes = 0;
329
+ const chunk = Buffer.alloc(LINE_COUNT_CHUNK_BYTES);
330
+ for (;;) {
331
+ const { bytesRead } = await handle.read(chunk, 0, chunk.length, null);
332
+ if (bytesRead === 0)
333
+ break;
334
+ totalBytes += bytesRead;
335
+ for (let i = 0; i < bytesRead; i++) {
336
+ const byte = chunk[i] ?? 0;
337
+ if (byte === CHAR_LF)
338
+ newlines++;
339
+ lastByte = byte;
340
+ }
341
+ }
342
+ // totalBytes is the empty-file sentinel: a NUL (0x00) final byte is real
343
+ // content and must count as an unterminated final line, not "empty".
344
+ return totalBytes === 0 ? 0 : lastByte === CHAR_LF ? newlines : newlines + 1;
345
+ }
346
+ catch (e_2) {
347
+ env_2.error = e_2;
348
+ env_2.hasError = true;
349
+ }
350
+ finally {
351
+ const result_2 = __disposeResources(env_2);
352
+ if (result_2)
353
+ await result_2;
289
354
  }
290
355
  }
291
356
  async rm(filePath, options) {