@j0hanz/filesystem-mcp 2.8.0 → 2.8.1

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 (75) hide show
  1. package/dist/cli.d.ts.map +1 -1
  2. package/dist/cli.js +2 -2
  3. package/dist/cli.js.map +1 -1
  4. package/dist/core/cursor.d.ts +8 -0
  5. package/dist/core/cursor.d.ts.map +1 -1
  6. package/dist/core/cursor.js +14 -0
  7. package/dist/core/cursor.js.map +1 -1
  8. package/dist/core/fs.d.ts.map +1 -1
  9. package/dist/core/fs.js +64 -40
  10. package/dist/core/fs.js.map +1 -1
  11. package/dist/core/input-required.d.ts +7 -0
  12. package/dist/core/input-required.d.ts.map +1 -1
  13. package/dist/core/input-required.js +13 -0
  14. package/dist/core/input-required.js.map +1 -1
  15. package/dist/core/path-utils.d.ts +9 -6
  16. package/dist/core/path-utils.d.ts.map +1 -1
  17. package/dist/core/path-utils.js +13 -19
  18. package/dist/core/path-utils.js.map +1 -1
  19. package/dist/core/path.d.ts +1 -18
  20. package/dist/core/path.d.ts.map +1 -1
  21. package/dist/core/path.js +5 -40
  22. package/dist/core/path.js.map +1 -1
  23. package/dist/core/read.d.ts +7 -3
  24. package/dist/core/read.d.ts.map +1 -1
  25. package/dist/core/read.js +20 -37
  26. package/dist/core/read.js.map +1 -1
  27. package/dist/core/sensitive.d.ts.map +1 -1
  28. package/dist/core/sensitive.js +7 -14
  29. package/dist/core/sensitive.js.map +1 -1
  30. package/dist/core/util.d.ts +6 -0
  31. package/dist/core/util.d.ts.map +1 -1
  32. package/dist/core/util.js +16 -0
  33. package/dist/core/util.js.map +1 -1
  34. package/dist/prompts.d.ts +1 -1
  35. package/dist/prompts.d.ts.map +1 -1
  36. package/dist/prompts.js +1 -1
  37. package/dist/prompts.js.map +1 -1
  38. package/dist/resources.d.ts +1 -2
  39. package/dist/resources.d.ts.map +1 -1
  40. package/dist/resources.js +2 -4
  41. package/dist/resources.js.map +1 -1
  42. package/dist/server.js +1 -1
  43. package/dist/server.js.map +1 -1
  44. package/dist/tools/create.d.ts.map +1 -1
  45. package/dist/tools/create.js +5 -6
  46. package/dist/tools/create.js.map +1 -1
  47. package/dist/tools/delete.d.ts.map +1 -1
  48. package/dist/tools/delete.js +7 -6
  49. package/dist/tools/delete.js.map +1 -1
  50. package/dist/tools/find-files.d.ts.map +1 -1
  51. package/dist/tools/find-files.js +6 -12
  52. package/dist/tools/find-files.js.map +1 -1
  53. package/dist/tools/index.d.ts +1 -1
  54. package/dist/tools/index.d.ts.map +1 -1
  55. package/dist/tools/index.js +1 -1
  56. package/dist/tools/index.js.map +1 -1
  57. package/dist/tools/list.d.ts.map +1 -1
  58. package/dist/tools/list.js +30 -13
  59. package/dist/tools/list.js.map +1 -1
  60. package/dist/tools/move.d.ts.map +1 -1
  61. package/dist/tools/move.js +12 -13
  62. package/dist/tools/move.js.map +1 -1
  63. package/dist/tools/replace-text.js +1 -1
  64. package/dist/tools/replace-text.js.map +1 -1
  65. package/dist/tools/search-text.d.ts.map +1 -1
  66. package/dist/tools/search-text.js +7 -18
  67. package/dist/tools/search-text.js.map +1 -1
  68. package/dist/transport/http-policy.d.ts +3 -2
  69. package/dist/transport/http-policy.d.ts.map +1 -1
  70. package/dist/transport/http-policy.js +3 -2
  71. package/dist/transport/http-policy.js.map +1 -1
  72. package/dist/transport/http.d.ts.map +1 -1
  73. package/dist/transport/http.js +1 -2
  74. package/dist/transport/http.js.map +1 -1
  75. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n Implementation,\n ServerCapabilities,\n ServerNotifier,\n} from '@modelcontextprotocol/server';\nimport { McpServer } from '@modelcontextprotocol/server';\n\nimport packageJson from '../package.json' with { type: 'json' };\nimport { requestStateCodec } from './core/input-required.ts';\nimport { Logger, voidSend } from './core/observability.ts';\nimport type { ServerOptions } from './core/path.ts';\nimport { PathGuard } from './core/path.ts';\nimport { PageSnapshotStore, ResourceStore } from './core/store.ts';\nimport { MAX_OUTBOUND_RESULT_BYTES, MAX_TOOL_INPUT_ELEMENTS } from './core/util.ts';\nimport type { WatcherRegistry } from './core/watcher-registry.ts';\nimport { INSTRUCTIONS_SUMMARY, INSTRUCTIONS_URI } from './instructions.ts';\nimport { registerPrompts } from './prompts.ts';\nimport { registerResources } from './resources.ts';\nimport { registerTools } from './tools/index.ts';\n\n// ═══════════════════════════════════════════════════════════════\n// bootstrap\n// ═══════════════════════════════════════════════════════════════\n\nconst {\n version: SERVER_VERSION,\n description: SERVER_DESCRIPTION,\n homepage: SERVER_HOMEPAGE,\n} = packageJson;\n\nexport interface FilesystemServerContext {\n readonly mcp: McpServer;\n readonly pathGuard: PathGuard;\n disposeRuntimeState(): void;\n}\n\nexport async function createServer(\n options: ServerOptions = {},\n extraDeps?: {\n /** Shared file-watcher registry for the modern (per-request) HTTP leg. */\n watcherRegistry?: WatcherRegistry;\n /** Modern-leg typed notification publisher. */\n notifier?: ServerNotifier;\n /**\n * Guard to use instead of constructing one. The HTTP leg builds a single\n * guard for the whole endpoint and passes it to every per-request instance,\n * so an accepted access grant survives the request that accepted it (R8) and\n * the listen-watcher path validates against the same allowed set. Omitted on\n * stdio, where the instance is pinned for the connection and owns its guard.\n */\n pathGuard?: PathGuard;\n /**\n * Store to use instead of constructing one. The HTTP modern leg shares one\n * store across every per-request instance, so a result a tool externalized\n * in one POST survives to the follow-up resources/read. Omitted on stdio,\n * where the pinned instance owns its store for the connection.\n */\n resourceStore?: ResourceStore;\n /**\n * Pagination snapshots shared by every modern HTTP request. Omitted on\n * stdio, where the connection-owned context clears its store on close.\n */\n pageStore?: PageSnapshotStore;\n /** The protocol era this instance serves; omitted where the caller does not know. */\n era?: 'legacy' | 'modern';\n /**\n * Only `stdio` has the SDK's fixed 10 MiB ReadBuffer, so only there are\n * results capped: any tool call that changed nothing, any resource read,\n * and a result-store entry by the size of its read (define.ts,\n * resources.ts, store.ts).\n */\n transport?: 'stdio' | 'http';\n /**\n * `private` when the HTTP host requires a bearer key, so a shared cache\n * never serves one tenant's listing to another. Default `public`.\n */\n cacheScope?: 'private' | 'public';\n },\n): Promise<FilesystemServerContext> {\n // Only `resources` is declared: `McpServer` advertises `tools` and `prompts`\n // (with `listChanged: true`) and `completions` from the registrations below,\n // but never infers `subscribe`.\n //\n // `resources.subscribe` stays advertised on both eras: the verb itself is\n // 2025-only, but the SDK's listen router honors a `subscriptions/listen`\n // resource filter only while this bit is advertised (dist: `allow(\n // capabilities?.resources?.subscribe)` on `resourceSubscriptions`). The\n // strict-capability gate on outbound `notifications/resources/updated`\n // checks only that `resources` exists. The one exception is a\n // legacy instance on the HTTP leg (era 'legacy' with a notifier): it serves\n // one request, registers no subscribe handler (resources.ts, same\n // predicate) and sends no notification of any kind — there is no stream to\n // send it on — so neither `subscribe` nor `listChanged` is advertised.\n // sunset(SEP-2577): removal trigger in docs/adr/002-legacy-protocol-paths-sunset.md.\n const legacyHttp = extraDeps?.era === 'legacy' && extraDeps.notifier !== undefined;\n const capabilities = {\n resources: { subscribe: !legacyHttp, listChanged: !legacyHttp },\n } satisfies ServerCapabilities;\n\n const cacheScope = extraDeps?.cacheScope ?? 'public';\n const serverConfig: NonNullable<ConstructorParameters<typeof McpServer>[1]> = {\n capabilities,\n enforceStrictCapabilities: true,\n // Structural bound on tools/call arguments, checked before Zod walks the\n // value: the body limit is bytes (31 MiB by default), and every per-tool\n // `.max()` runs only after a full traversal. No schema-legal call comes\n // near this (see MAX_TOOL_INPUT_ELEMENTS); a payload over it is answered\n // with a tool error after counting at most 4097 nodes.\n maxToolInputElements: MAX_TOOL_INPUT_ELEMENTS,\n cacheHints: {\n 'tools/list': { ttlMs: 3_600_000, cacheScope },\n 'prompts/list': { ttlMs: 3_600_000, cacheScope },\n // Always private, never `cacheScope`: this list enumerates the\n // ResourceStore, so its entries are one caller's externalized tool output\n // — the same entries whose own read hint is `private` (resources.ts). The\n // other four lists are the same for every caller and follow the key, and\n // they are built from frozen module-level arrays that cannot change at\n // runtime, so an hour is honest: a shorter hint only buys the client a\n // re-fetch of bytes that cannot have differed, at the cost of the prompt\n // cache stability the spec asks deterministic ordering to preserve.\n 'resources/list': { ttlMs: 30_000, cacheScope: 'private' },\n 'resources/templates/list': { ttlMs: 3_600_000, cacheScope },\n 'server/discover': { ttlMs: 3_600_000, cacheScope },\n },\n // Multi-round-trip `requestState` integrity (protocol revision 2026-07-28):\n // the codec verifies the HMAC on every retried round before the handler\n // runs, so a tampered or expired state is rejected as `-32602` rather than\n // trusted. The decoded `PendingState` reaches handlers via\n // `ctx.mcpReq.requestState<T>()`.\n // eslint-disable-next-line @typescript-eslint/unbound-method\n requestState: { verify: requestStateCodec.verify },\n // The ResourceStore fires list-changed on every externalization and on\n // every expiry prune (store.ts), so parallel tools/call on one\n // connection can send the same notification several times in one tick;\n // each copy makes the client refetch an unchanged list. The SDK\n // coalesces same-tick duplicates for methods listed here.\n // ponytail: same-tick coalescing only — cross-tick bursts (batch\n // externalizations separated by fs awaits) still fan out; a store-level\n // debounce is the fix if clients ever report that. The modern HTTP leg\n // publishes through the ServerEventBus, which this option does not\n // touch, so it protects the stdio/in-memory leg.\n debouncedNotificationMethods: ['notifications/resources/list_changed'],\n };\n\n serverConfig.instructions =\n `${INSTRUCTIONS_SUMMARY} ` +\n `For full guidance, read ${INSTRUCTIONS_URI} or run the get-help prompt.`;\n\n const implementation: Implementation = {\n name: 'filesystem-mcp',\n title: 'Filesystem MCP',\n version: SERVER_VERSION,\n ...(SERVER_DESCRIPTION ? { description: SERVER_DESCRIPTION } : {}),\n ...(SERVER_HOMEPAGE ? { websiteUrl: SERVER_HOMEPAGE } : {}),\n };\n const server = new McpServer(implementation, serverConfig);\n server.server.fallbackNotificationHandler = (notification) => {\n Logger.debug('Unhandled client notification', { method: notification.method });\n return Promise.resolve();\n };\n\n const resourceStore =\n extraDeps?.resourceStore ??\n new ResourceStore(\n () => {\n if (extraDeps?.notifier) {\n extraDeps.notifier.resourcesChanged();\n return;\n }\n voidSend(server.server.sendResourceListChanged(), 'resource list_changed');\n },\n // A tool hands out no link that this connection's resources/read refuses.\n extraDeps?.transport === 'stdio' ? { maxReadResultBytes: MAX_OUTBOUND_RESULT_BYTES } : {},\n );\n const pageStore = extraDeps?.pageStore ?? new PageSnapshotStore();\n\n const pathGuard = extraDeps?.pathGuard ?? new PathGuard(options);\n // Recompute once per guard, keyed on the guard's own state rather than on\n // whether it was injected — an injected-but-uninitialized guard would\n // otherwise deny every path. Not unconditional: the HTTP leg shares one guard\n // across a fresh instance per request, and a repeat recompute would both redo\n // the root resolution per request and race a concurrent `applyGrant`, which\n // commits under a mutation lock this call does not take.\n if (!pathGuard.isInitialized()) await pathGuard.recomputeAllowedDirectories();\n\n const deps = {\n server,\n pathGuard,\n pageStore,\n resourceStore,\n cacheScope,\n ...(options.readOnly ? { readOnly: true } : {}),\n ...(extraDeps?.watcherRegistry ? { watcherRegistry: extraDeps.watcherRegistry } : {}),\n ...(extraDeps?.notifier ? { notifier: extraDeps.notifier } : {}),\n ...(extraDeps?.era ? { era: extraDeps.era } : {}),\n ...(extraDeps?.transport ? { transport: extraDeps.transport } : {}),\n };\n\n const resourceDisposable = registerResources(deps);\n registerPrompts(deps);\n registerTools(deps);\n\n // False when the store is shared across instances and outlives this one.\n const ownsPages = extraDeps?.pageStore === undefined;\n let cleanedUp = false;\n const context: FilesystemServerContext = {\n mcp: server,\n pathGuard,\n disposeRuntimeState() {\n if (cleanedUp) return;\n cleanedUp = true;\n if (ownsPages) pageStore.clear();\n resourceDisposable.dispose();\n },\n };\n const previousOnClose = server.server.onclose;\n server.server.onclose = () => {\n previousOnClose?.();\n context.disposeRuntimeState();\n };\n return context;\n}\n"]}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n Implementation,\n ServerCapabilities,\n ServerNotifier,\n} from '@modelcontextprotocol/server';\nimport { McpServer } from '@modelcontextprotocol/server';\n\nimport packageJson from '../package.json' with { type: 'json' };\nimport { requestStateCodec } from './core/input-required.ts';\nimport { Logger, voidSend } from './core/observability.ts';\nimport type { ServerOptions } from './core/path.ts';\nimport { PathGuard } from './core/path.ts';\nimport { PageSnapshotStore, ResourceStore } from './core/store.ts';\nimport { MAX_OUTBOUND_RESULT_BYTES, MAX_TOOL_INPUT_ELEMENTS } from './core/util.ts';\nimport type { WatcherRegistry } from './core/watcher-registry.ts';\nimport { INSTRUCTIONS_SUMMARY, INSTRUCTIONS_URI } from './instructions.ts';\nimport { registerPrompts } from './prompts.ts';\nimport { registerResources } from './resources.ts';\nimport { registerTools } from './tools/index.ts';\n\n// ═══════════════════════════════════════════════════════════════\n// bootstrap\n// ═══════════════════════════════════════════════════════════════\n\nconst {\n version: SERVER_VERSION,\n description: SERVER_DESCRIPTION,\n homepage: SERVER_HOMEPAGE,\n} = packageJson;\n\nexport interface FilesystemServerContext {\n readonly mcp: McpServer;\n readonly pathGuard: PathGuard;\n disposeRuntimeState(): void;\n}\n\nexport async function createServer(\n options: ServerOptions = {},\n extraDeps?: {\n /** Shared file-watcher registry for the modern (per-request) HTTP leg. */\n watcherRegistry?: WatcherRegistry;\n /** Modern-leg typed notification publisher. */\n notifier?: ServerNotifier;\n /**\n * Guard to use instead of constructing one. The HTTP leg builds a single\n * guard for the whole endpoint and passes it to every per-request instance,\n * so an accepted access grant survives the request that accepted it (R8) and\n * the listen-watcher path validates against the same allowed set. Omitted on\n * stdio, where the instance is pinned for the connection and owns its guard.\n */\n pathGuard?: PathGuard;\n /**\n * Store to use instead of constructing one. The HTTP modern leg shares one\n * store across every per-request instance, so a result a tool externalized\n * in one POST survives to the follow-up resources/read. Omitted on stdio,\n * where the pinned instance owns its store for the connection.\n */\n resourceStore?: ResourceStore;\n /**\n * Pagination snapshots shared by every modern HTTP request. Omitted on\n * stdio, where the connection-owned context clears its store on close.\n */\n pageStore?: PageSnapshotStore;\n /** The protocol era this instance serves; omitted where the caller does not know. */\n era?: 'legacy' | 'modern';\n /**\n * Only `stdio` has the SDK's fixed 10 MiB ReadBuffer, so only there are\n * results capped: any tool call that changed nothing, any resource read,\n * and a result-store entry by the size of its read (define.ts,\n * resources.ts, store.ts).\n */\n transport?: 'stdio' | 'http';\n /**\n * `private` when the HTTP host requires a bearer key, so a shared cache\n * never serves one tenant's listing to another. Default `public`.\n */\n cacheScope?: 'private' | 'public';\n },\n): Promise<FilesystemServerContext> {\n // Only `resources` is declared: `McpServer` advertises `tools` and `prompts`\n // (with `listChanged: true`) and `completions` from the registrations below,\n // but never infers `subscribe`.\n //\n // `resources.subscribe` stays advertised on both eras: the verb itself is\n // 2025-only, but the SDK's listen router honors a `subscriptions/listen`\n // resource filter only while this bit is advertised (dist: `allow(\n // capabilities?.resources?.subscribe)` on `resourceSubscriptions`). The\n // strict-capability gate on outbound `notifications/resources/updated`\n // checks only that `resources` exists. The one exception is a\n // legacy instance on the HTTP leg (era 'legacy' with a notifier): it serves\n // one request, registers no subscribe handler (resources.ts, same\n // predicate) and sends no notification of any kind — there is no stream to\n // send it on — so neither `subscribe` nor `listChanged` is advertised.\n // sunset(SEP-2577): removal trigger in docs/adr/002-legacy-protocol-paths-sunset.md.\n const legacyHttp = extraDeps?.era === 'legacy' && extraDeps.notifier !== undefined;\n const capabilities = {\n resources: { subscribe: !legacyHttp, listChanged: !legacyHttp },\n } satisfies ServerCapabilities;\n\n const cacheScope = extraDeps?.cacheScope ?? 'public';\n const serverConfig: NonNullable<ConstructorParameters<typeof McpServer>[1]> = {\n capabilities,\n enforceStrictCapabilities: true,\n // Structural bound on tools/call arguments, checked before Zod walks the\n // value: the body limit is bytes (31 MiB by default), and every per-tool\n // `.max()` runs only after a full traversal. No schema-legal call comes\n // near this (see MAX_TOOL_INPUT_ELEMENTS); a payload over it is answered\n // with a tool error after counting at most 4097 nodes.\n maxToolInputElements: MAX_TOOL_INPUT_ELEMENTS,\n cacheHints: {\n 'tools/list': { ttlMs: 3_600_000, cacheScope },\n 'prompts/list': { ttlMs: 3_600_000, cacheScope },\n // Always private, never `cacheScope`: this list enumerates the\n // ResourceStore, so its entries are one caller's externalized tool output\n // — the same entries whose own read hint is `private` (resources.ts). The\n // other four lists are the same for every caller and follow the key, and\n // they are built from frozen module-level arrays that cannot change at\n // runtime, so an hour is honest: a shorter hint only buys the client a\n // re-fetch of bytes that cannot have differed, at the cost of the prompt\n // cache stability the spec asks deterministic ordering to preserve.\n 'resources/list': { ttlMs: 30_000, cacheScope: 'private' },\n 'resources/templates/list': { ttlMs: 3_600_000, cacheScope },\n 'server/discover': { ttlMs: 3_600_000, cacheScope },\n },\n // Multi-round-trip `requestState` integrity (protocol revision 2026-07-28):\n // the codec verifies the HMAC on every retried round before the handler\n // runs, so a tampered or expired state is rejected as `-32602` rather than\n // trusted. The decoded `PendingState` reaches handlers via\n // `ctx.mcpReq.requestState<T>()`.\n // eslint-disable-next-line @typescript-eslint/unbound-method\n requestState: { verify: requestStateCodec.verify },\n // The ResourceStore fires list-changed on every externalization and on\n // every expiry prune (store.ts), so parallel tools/call on one\n // connection can send the same notification several times in one tick;\n // each copy makes the client refetch an unchanged list. The SDK\n // coalesces same-tick duplicates for methods listed here.\n // ponytail: same-tick coalescing only — cross-tick bursts (batch\n // externalizations separated by fs awaits) still fan out; a store-level\n // debounce is the fix if clients ever report that. The modern HTTP leg\n // publishes through the ServerEventBus, which this option does not\n // touch, so it protects the stdio/in-memory leg.\n debouncedNotificationMethods: ['notifications/resources/list_changed'],\n };\n\n serverConfig.instructions =\n `${INSTRUCTIONS_SUMMARY} ` +\n `For full guidance, read ${INSTRUCTIONS_URI} or run the get-help prompt.`;\n\n const implementation: Implementation = {\n name: 'filesystem-mcp',\n title: 'Filesystem MCP',\n version: SERVER_VERSION,\n ...(SERVER_DESCRIPTION ? { description: SERVER_DESCRIPTION } : {}),\n ...(SERVER_HOMEPAGE ? { websiteUrl: SERVER_HOMEPAGE } : {}),\n };\n const server = new McpServer(implementation, serverConfig);\n server.server.fallbackNotificationHandler = (notification) => {\n Logger.debug('Unhandled client notification', { method: notification.method });\n return Promise.resolve();\n };\n\n const resourceStore =\n extraDeps?.resourceStore ??\n new ResourceStore(\n () => {\n if (extraDeps?.notifier) {\n extraDeps.notifier.resourcesChanged();\n return;\n }\n voidSend(server.server.sendResourceListChanged(), 'resource list_changed');\n },\n // A tool hands out no link that this connection's resources/read refuses.\n extraDeps?.transport === 'stdio' ? { maxReadResultBytes: MAX_OUTBOUND_RESULT_BYTES } : {},\n );\n const pageStore = extraDeps?.pageStore ?? new PageSnapshotStore();\n\n const pathGuard = extraDeps?.pathGuard ?? new PathGuard(options);\n // Recompute once per guard, keyed on the guard's own state rather than on\n // whether it was injected — an injected-but-uninitialized guard would\n // otherwise deny every path. Not unconditional: the HTTP leg shares one guard\n // across a fresh instance per request, and a repeat recompute would both redo\n // the root resolution per request and race a concurrent `applyGrant`, which\n // commits under a mutation lock this call does not take.\n if (!pathGuard.isInitialized()) await pathGuard.recomputeAllowedDirectories();\n\n const deps = {\n server,\n pathGuard,\n pageStore,\n resourceStore,\n cacheScope,\n readOnly: options.readOnly ?? false,\n ...(extraDeps?.watcherRegistry ? { watcherRegistry: extraDeps.watcherRegistry } : {}),\n ...(extraDeps?.notifier ? { notifier: extraDeps.notifier } : {}),\n ...(extraDeps?.era ? { era: extraDeps.era } : {}),\n ...(extraDeps?.transport ? { transport: extraDeps.transport } : {}),\n };\n\n const resourceDisposable = registerResources(deps);\n registerPrompts(deps);\n registerTools(deps);\n\n // False when the store is shared across instances and outlives this one.\n const ownsPages = extraDeps?.pageStore === undefined;\n let cleanedUp = false;\n const context: FilesystemServerContext = {\n mcp: server,\n pathGuard,\n disposeRuntimeState() {\n if (cleanedUp) return;\n cleanedUp = true;\n if (ownsPages) pageStore.clear();\n resourceDisposable.dispose();\n },\n };\n const previousOnClose = server.server.onclose;\n server.server.onclose = () => {\n previousOnClose?.();\n context.disposeRuntimeState();\n };\n return context;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/tools/create.ts"],"names":[],"mappings":"AA+GA,eAAO,MAAM,MAAM,mCA8HjB,CAAC"}
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/tools/create.ts"],"names":[],"mappings":"AA0GA,eAAO,MAAM,MAAM,mCA6HjB,CAAC"}
@@ -4,7 +4,7 @@ import { processInParallel } from "../core/concurrency.js";
4
4
  import { ErrorCode, formatUnknownErrorMessage, FsError, rethrowIfAborted, } from "../core/errors.js";
5
5
  import { buildWrittenFileMeta, writtenFileLinks } from "../core/file-uri.js";
6
6
  import { destExists } from "../core/fs.js";
7
- import { confirmKey, describeRefusal, pendingRoundTrip, readAcceptedChoice, } from "../core/input-required.js";
7
+ import { confirmKey, pendingRoundTrip, readPendingVerdict } from "../core/input-required.js";
8
8
  import { detectMimeFromContent } from "../core/mime.js";
9
9
  import { isSamePath } from "../core/path-utils.js";
10
10
  import { RequiredPath } from "../core/schema.js";
@@ -119,12 +119,11 @@ export const CREATE = defineTool({
119
119
  const batch = await runOverPaths(args.files, ctx, ErrorCode.UNKNOWN, async ({ path, content, append, overwrite }) => {
120
120
  const pendingPath = pendingByPath.get(path);
121
121
  if (pendingPath !== undefined) {
122
- const key = confirmKey(pendingSorted.indexOf(pendingPath));
123
- const choice = readAcceptedChoice(ctx.inputResponses, key);
124
- if (choice === 'skip')
122
+ const verdict = readPendingVerdict(ctx, pendingSorted, pendingPath, 'overwrite');
123
+ if (verdict === 'skipped')
125
124
  return { skipped: path };
126
- if (choice !== 'overwrite') {
127
- throw new FsError(ErrorCode.CANCELLED, `create cancelled: overwrite of "${path}" was ${describeRefusal(ctx, key)}`, path);
125
+ if (verdict !== 'accepted') {
126
+ throw new FsError(ErrorCode.CANCELLED, `create cancelled: overwrite of "${path}" was ${verdict.refused}`, path);
128
127
  }
129
128
  }
130
129
  // Lock per resolved file so two entries naming one file (e.g. through a
@@ -1 +1 @@
1
- {"version":3,"file":"create.js","sourceRoot":"","sources":["../../src/tools/create.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE9C,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EACL,SAAS,EACT,yBAAyB,EACzB,OAAO,EAEP,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAwB,MAAM,qBAAqB,CAAC;AACnG,OAAO,EAAE,UAAU,EAAc,MAAM,eAAe,CAAC;AACvD,OAAO,EACL,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,qBAAqB,EAAiB,MAAM,iBAAiB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAgB,MAAM,aAAa,CAAC;AAEvD,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;AAE1B,MAAM,oBAAoB,GAAG,CAAC,CAAC,YAAY,CAAC;IAC1C,IAAI,EAAE,YAAY,CAAC,QAAQ,CAAC,8CAA8C,CAAC;IAC3E,OAAO,EAAE,CAAC;SACP,MAAM,EAAE;SACR,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,IAAI,kBAAkB,EAAE,EAAE;QACnD,OAAO,EAAE,gDAAgD;KAC1D,CAAC;SACD,QAAQ,CAAC,kCAAkC,CAAC;IAC/C,MAAM,EAAE,CAAC;SACN,OAAO,EAAE;SACT,QAAQ,EAAE;SACV,QAAQ,CACP,yGAAyG,CAC1G;IACH,SAAS,EAAE,CAAC;SACT,OAAO,EAAE;SACT,QAAQ,EAAE;SACV,QAAQ,CACP,wGAAwG,CACzG;CACJ,CAAC,CAAC;AAQH,MAAM,iBAAiB,GAAG,CAAC;KACxB,YAAY,CAAC;IACZ,KAAK,EAAE,CAAC;SACL,KAAK,CAAC,oBAAoB,CAAC;SAC3B,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,GAAG,CAAC;SACR,QAAQ,CACP,4HAA4H,CAC7H;CACJ,CAAC;KACD,WAAW,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;IAC1B,qEAAqE;IACrE,kEAAkE;IAClE,iEAAiE;IACjE,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;QAClD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAClF,IAAI,KAAK,GAAG,KAAK,EAAE,CAAC;YAClB,GAAG,CAAC,QAAQ,CAAC;gBACX,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC;gBAC9B,OAAO,EAAE,sBAAsB,MAAM,CAAC,KAAK,CAAC,4BAA4B;gBACxE,KAAK,EAAE,KAAK;aACb,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,yEAAyE;IACzE,6EAA6E;IAC7E,2EAA2E;IAC3E,6CAA6C;IAC7C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC9E,MAAM,KAAK,GAAG,kBAAkB,EAAE,CAAC;IACnC,IAAI,KAAK,GAAG,KAAK,EAAE,CAAC;QAClB,GAAG,CAAC,QAAQ,CAAC;YACX,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,OAAO,CAAC;YACf,OAAO,EAAE,uBAAuB,MAAM,CAAC,KAAK,CAAC,gDAAgD,MAAM,CAAC,KAAK,CAAC,uCAAuC;YACjJ,KAAK,EAAE,KAAK;SACb,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC,CAAC;AAaL,MAAM,CAAC,MAAM,MAAM,GAAG,UAAU,CAAyC;IACvE,IAAI,EAAE,QAAQ;IACd,KAAK,EAAE,cAAc;IACrB,WAAW,EACT,yGAAyG;QACzG,iDAAiD;IACnD,KAAK,EAAE,iBAAiB;IACxB,YAAY,EAAE,KAAK;IACnB,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACpD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;QACvB,wEAAwE;QACxE,0EAA0E;QAC1E,0EAA0E;QAC1E,wEAAwE;QACxE,wEAAwE;QACxE,oEAAoE;QACpE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,MAAM,iBAAiB,CAClD,IAAI,CAAC,KAAK,EACV,KAAK,EAAE,KAAK,EAAE,EAAE;YACd,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,SAAS;gBAAE,OAAO,SAAS,CAAC;YACtD,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,oBAAoB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC1E,OAAO,CAAC,MAAM,UAAU,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;YACjF,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,gBAAgB,CAAC,KAAK,CAAC,CAAC;gBACxB,OAAO,SAAS,CAAC;YACnB,CAAC;QACH,CAAC,EACD,oBAAoB,EACpB,GAAG,CAAC,MAAM,CACX,CAAC;QACF,MAAM,aAAa,GAAG,IAAI,GAAG,EAAkB,CAAC;QAChD,KAAK,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,OAAO,EAAE,CAAC;YACvC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC;YAC1C,IAAI,KAAK,IAAI,SAAS;gBAAE,aAAa,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAC9D,CAAC;QACD,MAAM,aAAa,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAClE,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,wEAAwE;YACxE,8DAA8D;YAC9D,MAAM,KAAK,GAAG,MAAM,gBAAgB,CAAC,GAAG,EAAE;gBACxC,EAAE,EAAE,QAAQ;gBACZ,OAAO,EAAE,aAAa;gBACtB,WAAW,EAAE,CAAC,KAAK,EAAE,EAAE,CACrB,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;oBACxB,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC;oBAClB,OAAO,EAAE,IAAI,MAAM,iCAAiC;oBACpD,OAAO,EAAE,CAAC,WAAW,EAAE,MAAM,CAAC;iBAC/B,CAAC,CAAC;aACN,CAAC,CAAC;YACH,IAAI,KAAK,KAAK,SAAS;gBAAE,OAAO,KAAK,CAAC;QACxC,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,YAAY,CAG9B,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,SAAS,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE;YACnF,MAAM,WAAW,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC5C,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;gBAC9B,MAAM,GAAG,GAAG,UAAU,CAAC,aAAa,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;gBAC3D,MAAM,MAAM,GAAG,kBAAkB,CAAC,GAAG,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;gBAC3D,IAAI,MAAM,KAAK,MAAM;oBAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;gBAChD,IAAI,MAAM,KAAK,WAAW,EAAE,CAAC;oBAC3B,MAAM,IAAI,OAAO,CACf,SAAS,CAAC,SAAS,EACnB,mCAAmC,IAAI,SAAS,eAAe,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EAC3E,IAAI,CACL,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,wEAAwE;YACxE,+CAA+C;YAC/C,OAAO,GAAG,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;gBACxD,kEAAkE;gBAClE,IACE,CAAC,MAAM;oBACP,CAAC,SAAS;oBACV,WAAW,KAAK,SAAS;oBACzB,CAAC,MAAM,UAAU,CAAC,GAAG,CAAC,EAAE,EAAE,cAAc,EAAE,QAAQ,CAAC,CAAC,EACpD,CAAC;oBACD,MAAM,IAAI,OAAO,CACf,SAAS,CAAC,aAAa,EACvB,oBAAoB,IAAI,qDAAqD,EAC7E,IAAI,CACL,CAAC;gBACJ,CAAC;gBACD,OAAO,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;YAC/C,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,MAAM,OAAO,GAAuB,EAAE,CAAC;QACvC,MAAM,QAAQ,GAAwB,EAAE,CAAC;QACzC,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAmB,EAAE,CAAC;QACjC,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAC9B,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;gBACjB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;gBAChD,SAAS;YACX,CAAC;YACD,IAAI,SAAS,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;gBACzB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBAC9B,SAAS;YACX,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC3B,IAAI,CAAC,CAAC,KAAK,CAAC,YAAY;gBAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAC7D,CAAC;QAED,MAAM,UAAU,GAAG;YACjB,KAAK,EAAE,OAAO;YACd,GAAG,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5C,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC3C,CAAC;QACF,yEAAyE;QACzE,yEAAyE;QACzE,mEAAmE;QACnE,oEAAoE;QACpE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;IAClF,CAAC;IACD,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACnB,KAAK,EAAE,QAAQ;QACf,OAAO,EACL,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;YACrB,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,EAAE,CAAC;YACrC,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ;KAC3C,CAAC;CACH,CAAC,CAAC;AAEH,KAAK,UAAU,SAAS,CACtB,IAAY,EACZ,OAAe,EACf,MAA2B,EAC3B,GAAY;IAEZ,MAAM,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEvD,mEAAmE;IACnE,qEAAqE;IACrE,+DAA+D;IAC/D,mEAAmE;IACnE,mEAAmE;IACnE,oEAAoE;IACpE,qCAAqC;IACrC,IAAI,SAAiB,CAAC;IACtB,IAAI,IAAqB,CAAC;IAC1B,IAAI,OAAe,CAAC;IACpB,IAAI,QAAgB,CAAC;IACrB,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE;YACtD,MAAM,EAAE,GAAG,CAAC,MAAM;SACnB,CAAC,CAAC;QACH,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC;QAC/B,4DAA4D;QAC5D,mEAAmE;QACnE,+DAA+D;QAC/D,kEAAkE;QAClE,kEAAkE;QAClE,+DAA+D;QAC/D,gEAAgE;QAChE,6DAA6D;QAC7D,IAAI,KAAwB,CAAC;QAC7B,IAAI,QAAgB,CAAC;QACrB,IAAI,IAAc,CAAC;QACnB,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,IAAI,CAAC;YACH,KAAK,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC;YACtD,6DAA6D;YAC7D,gEAAgE;YAChE,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,iBAAiB,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;YAClE,MAAM,QAAQ,GAAG,qBAAqB,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YACnE,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC;YAC7B,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;YACrB,SAAS,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,cAAc,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QAC9D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,GAAG,CAAC,GAAG,CACL,SAAS,EACT,+CAA+C,QAAQ,CAAC,SAAS,KAAK,yBAAyB,CAAC,KAAK,CAAC,EAAE,EACxG,QAAQ,CACT,CAAC;YACF,gEAAgE;YAChE,gEAAgE;YAChE,iEAAiE;YACjE,MAAM,QAAQ,GAAG,qBAAqB,CAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YACpE,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC;YAC7B,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;QACvB,CAAC;QACD,mEAAmE;QACnE,IAAI,GAAG;YACL,IAAI,EAAE,KAAK,EAAE,IAAI,IAAI,CAAC;YACtB,SAAS;YACT,QAAQ;YACR,IAAI;YACJ,GAAG,gBAAgB,CACjB,QAAQ,CAAC,SAAS,EAClB,QAAQ,EACR,KAAK,EAAE,IAAI,EACX,KAAK,EACL,KAAK,EAAE,KAAK,CAAC,WAAW,EAAE,CAC3B;SACF,CAAC;QACF,OAAO,GAAG,CAAC,KAAK,EAAE,SAAS,IAAI,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;QACpD,QAAQ,GAAG,CAAC,KAAK,EAAE,KAAK,IAAI,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;IACnD,CAAC;SAAM,CAAC;QACN,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE;YACpD,MAAM,EAAE,GAAG,CAAC,MAAM;SACnB,CAAC,CAAC;QACH,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;QAC9B,MAAM,SAAS,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;QAC1E,OAAO,GAAG,SAAS,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC;QAC5C,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;QACzC,IAAI,GAAG,oBAAoB,CAAC;YAC1B,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,OAAO;YACP,YAAY,EAAE,QAAQ;SACvB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,EAAE,YAAY,EAAE,GAAG,QAAQ,EAAE,GAAG,IAAI,CAAC;IAC3C,MAAM,IAAI,GAAqB,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;IAEnF,OAAO,YAAY,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;AAC1D,CAAC","sourcesContent":["import type { ContentBlock } from '@modelcontextprotocol/server';\n\nimport { basename, dirname } from 'node:path';\n\nimport * as z from 'zod/v4';\n\nimport { processInParallel } from '../core/concurrency.ts';\nimport {\n ErrorCode,\n formatUnknownErrorMessage,\n FsError,\n type Problem,\n rethrowIfAborted,\n} from '../core/errors.ts';\nimport { buildWrittenFileMeta, writtenFileLinks, type WrittenFileMeta } from '../core/file-uri.ts';\nimport { destExists, type Stats } from '../core/fs.ts';\nimport {\n confirmKey,\n describeRefusal,\n pendingRoundTrip,\n readAcceptedChoice,\n} from '../core/input-required.ts';\nimport { detectMimeFromContent, type FileKind } from '../core/mime.ts';\nimport { isSamePath } from '../core/path-utils.ts';\nimport { RequiredPath } from '../core/schema.ts';\nimport { getMaxTextFileSize, PARALLEL_CONCURRENCY } from '../core/util.ts';\nimport { isTotalFailure, runOverPaths } from './batch.ts';\nimport { defineTool, type ToolCtx } from './define.ts';\n\nconst EPOCH = new Date(0);\n\nconst CreateFileItemSchema = z.strictObject({\n path: RequiredPath.describe('Absolute path where the file will be created'),\n content: z\n .string()\n .refine((val) => val.length <= getMaxTextFileSize(), {\n message: 'Content exceeds maximum allowed text file size',\n })\n .describe('Text content to write, verbatim.'),\n append: z\n .boolean()\n .optional()\n .describe(\n 'Append the content to the end of the file instead of overwriting; creates the file if it does not exist',\n ),\n overwrite: z\n .boolean()\n .optional()\n .describe(\n 'Replace an existing file without asking the user; without it an existing file prompts for confirmation',\n ),\n});\n\ntype CreateFileResult = Omit<WrittenFileMeta, 'resourceLink'> & {\n path: string;\n created: string;\n modified: string;\n};\n\nconst CreateInputSchema = z\n .strictObject({\n files: z\n .array(CreateFileItemSchema)\n .min(1)\n .max(100)\n .describe(\n 'List of files to create (max 100); each entry requires path and content; combined content is capped at the file-size limit',\n ),\n })\n .superRefine((value, ctx) => {\n // Entries write in parallel and each replaces its file whole, so two\n // entries for one path race: the last rename wins and the other's\n // content is lost while both report success. One entry per file.\n for (const [index, file] of value.files.entries()) {\n const first = value.files.findIndex((other) => isSamePath(other.path, file.path));\n if (first < index) {\n ctx.addIssue({\n code: 'custom',\n path: ['files', index, 'path'],\n message: `duplicate of files[${String(first)}].path; one entry per file`,\n input: value,\n });\n }\n }\n // One call's content is what one inbound message carries; the transports\n // size their message bound from this same limit (getMaxInboundMessageBytes),\n // so a batch that passes here always fits on the wire. Counted in the same\n // UTF-16 units as the per-file refine above.\n const total = value.files.reduce((sum, file) => sum + file.content.length, 0);\n const limit = getMaxTextFileSize();\n if (total > limit) {\n ctx.addIssue({\n code: 'custom',\n path: ['files'],\n message: `combined content is ${String(total)} characters; one create call carries at most ${String(limit)} (FS_MAX_FILE_SIZE). Split the batch.`,\n input: value,\n });\n }\n });\n\ninterface CreateFailureItem {\n path: string;\n error: Problem;\n}\n\ninterface CreateOutput {\n files: CreateFileResult[];\n failures?: CreateFailureItem[];\n skipped?: string[];\n}\n\nexport const CREATE = defineTool<typeof CreateInputSchema, CreateOutput>({\n name: 'create',\n title: 'Create Files',\n description:\n 'Write whole text files: create new ones, overwrite, or append. Missing parent directories are created. ' +\n 'edit or patch changes part of an existing file.',\n input: CreateInputSchema,\n readOnlyHint: false,\n accessPaths: (args) => args.files.map((f) => f.path),\n run: async (args, ctx) => {\n // Phase 1 (no mutation): which entries would replace a file that exists\n // right now? Those need the user's word before anything is written (R14).\n // append never destroys, and overwrite: true is that word given up front.\n // A path that fails validation here is left for runOverPaths to report.\n // A file that appears between rounds needs no re-stat before the write:\n // the retry re-plans, and the grown pending set fails the R9 check.\n const { results: planned } = await processInParallel(\n args.files,\n async (entry) => {\n if (entry.append || entry.overwrite) return undefined;\n try {\n const validPath = await ctx.fs.pathGuard.validatePathForWrite(entry.path);\n return (await destExists(ctx.fs, validPath, 'create')) ? validPath : undefined;\n } catch (error) {\n rethrowIfAborted(error);\n return undefined;\n }\n },\n PARALLEL_CONCURRENCY,\n ctx.signal,\n );\n const pendingByPath = new Map<string, string>();\n for (const { index, value } of planned) {\n const requested = args.files[index]?.path;\n if (value && requested) pendingByPath.set(requested, value);\n }\n const pendingSorted = [...new Set(pendingByPath.values())].sort();\n if (pendingSorted.length > 0) {\n // Round 1 returns input_required; a retry whose verified state does not\n // bind this overwrite set throws (R9) via `pendingRoundTrip`.\n const round = await pendingRoundTrip(ctx, {\n op: 'create',\n pending: pendingSorted,\n buildInputs: (paths) =>\n paths.map((target, i) => ({\n key: confirmKey(i),\n message: `\"${target}\" already exists. Overwrite it?`,\n choices: ['overwrite', 'skip'],\n })),\n });\n if (round !== undefined) return round;\n }\n\n const batch = await runOverPaths<\n z.infer<typeof CreateFileItemSchema>,\n { file: CreateFileResult; resourceLink?: ContentBlock } | { skipped: string }\n >(args.files, ctx, ErrorCode.UNKNOWN, async ({ path, content, append, overwrite }) => {\n const pendingPath = pendingByPath.get(path);\n if (pendingPath !== undefined) {\n const key = confirmKey(pendingSorted.indexOf(pendingPath));\n const choice = readAcceptedChoice(ctx.inputResponses, key);\n if (choice === 'skip') return { skipped: path };\n if (choice !== 'overwrite') {\n throw new FsError(\n ErrorCode.CANCELLED,\n `create cancelled: overwrite of \"${path}\" was ${describeRefusal(ctx, key)}`,\n path,\n );\n }\n }\n\n // Lock per resolved file so two entries naming one file (e.g. through a\n // symlinked parent) cannot clobber each other.\n return ctx.fs.lockForWrite(path, async (resolvedTarget) => {\n // The file may have appeared since the overwrite set was planned.\n if (\n !append &&\n !overwrite &&\n pendingPath === undefined &&\n (await destExists(ctx.fs, resolvedTarget, 'create'))\n ) {\n throw new FsError(\n ErrorCode.INVALID_INPUT,\n `create refused: \"${path}\" appeared after overwrite confirmation was checked`,\n path,\n );\n }\n return createOne(path, content, append, ctx);\n });\n });\n\n const results: CreateFileResult[] = [];\n const failures: CreateFailureItem[] = [];\n const skipped: string[] = [];\n const links: ContentBlock[] = [];\n for (const r of batch.results) {\n if ('error' in r) {\n failures.push({ path: r.path, error: r.error });\n continue;\n }\n if ('skipped' in r.value) {\n skipped.push(r.value.skipped);\n continue;\n }\n results.push(r.value.file);\n if (r.value.resourceLink) links.push(r.value.resourceLink);\n }\n\n const structured = {\n files: results,\n ...(failures.length > 0 ? { failures } : {}),\n ...(skipped.length > 0 ? { skipped } : {}),\n };\n // No `text` on purpose. The one-line roster this used to build named the\n // paths and dropped every per-file size, line count and error the caller\n // asked `create` for. Supplying no text makes this a data tool, so\n // `define.ts` renders the JSON and keeps it in `structuredContent`.\n return { structured, resources: links, isError: isTotalFailure(batch.summary) };\n },\n progress: (args) => ({\n label: 'Create',\n subject:\n args.files.length === 1\n ? basename(args.files[0]?.path ?? '')\n : `${String(args.files.length)} files`,\n }),\n});\n\nasync function createOne(\n path: string,\n content: string,\n append: boolean | undefined,\n ctx: ToolCtx,\n): Promise<{ file: CreateFileResult; resourceLink?: ContentBlock }> {\n await ctx.fs.mkdir(dirname(path), { recursive: true });\n\n // Overwrite: file content == `content`, so content-derived meta is\n // exact and the atomic temp+rename write protects the existing mode.\n // Append: the resulting file is everything that was there plus\n // `content`, so size/created/modified come from a real post-append\n // stat, MIME from the resulting file's leading bytes, and the line\n // count streams the file — reading a multi-GB log back whole is the\n // round-trip append exists to avoid.\n let validPath: string;\n let meta: WrittenFileMeta;\n let created: string;\n let modified: string;\n if (append) {\n const appended = await ctx.fs.appendFile(path, content, {\n signal: ctx.signal,\n });\n validPath = appended.validPath;\n // The append is the commit point: the bytes are on disk, so\n // everything below is best-effort RESULT METADATA, not part of the\n // write. It runs unwired to ctx.signal, and a metadata failure\n // degrades the result instead of failing it — either would report\n // the append as failed and a client retry would append twice. The\n // stat covers the committed validPath, never the input path: a\n // symlink there could have been swapped between write and stat,\n // and the result must describe the file the bytes landed in.\n let stats: Stats | undefined;\n let mimeType: string;\n let kind: FileKind;\n let lineCount = 0;\n try {\n stats = (await ctx.fs.stat(appended.validPath)).stats;\n // Sniff the resulting file's leading bytes, not the appended\n // chunk: text appended to a binary file is still a binary file.\n const sample = await ctx.fs.readLeadingSample(appended.validPath);\n const mimeInfo = detectMimeFromContent(appended.validPath, sample);\n mimeType = mimeInfo.mimeType;\n kind = mimeInfo.kind;\n lineCount = await ctx.fs.countFileLines(appended.validPath);\n } catch (error) {\n ctx.log(\n 'warning',\n `create append: result metadata degraded for ${appended.validPath}: ${formatUnknownErrorMessage(error)}`,\n 'create',\n );\n // A POSIX mode-0222 file appends fine but cannot be opened 'r';\n // fall back to the chunk for MIME (an approximation) and report\n // the line count as unknown-as-zero rather than fail the append.\n const mimeInfo = detectMimeFromContent(appended.validPath, content);\n mimeType = mimeInfo.mimeType;\n kind = mimeInfo.kind;\n }\n // A failed stat leaves the size unknown, so nothing is advertised.\n meta = {\n size: stats?.size ?? 0,\n lineCount,\n mimeType,\n kind,\n ...writtenFileLinks(\n appended.validPath,\n mimeType,\n stats?.size,\n false,\n stats?.mtime.toISOString(),\n ),\n };\n created = (stats?.birthtime ?? EPOCH).toISOString();\n modified = (stats?.mtime ?? EPOCH).toISOString();\n } else {\n const written = await ctx.fs.writeFile(path, content, {\n signal: ctx.signal,\n });\n validPath = written.validPath;\n const fileStats = (await ctx.fs.stat(path, { signal: ctx.signal })).stats;\n created = fileStats.birthtime.toISOString();\n modified = fileStats.mtime.toISOString();\n meta = buildWrittenFileMeta({\n validPath: written.validPath,\n content,\n lastModified: modified,\n });\n }\n\n const { resourceLink, ...fileMeta } = meta;\n const file: CreateFileResult = { path: validPath, ...fileMeta, created, modified };\n\n return resourceLink ? { file, resourceLink } : { file };\n}\n"]}
1
+ {"version":3,"file":"create.js","sourceRoot":"","sources":["../../src/tools/create.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContentBlock } from '@modelcontextprotocol/server';\n\nimport { basename, dirname } from 'node:path';\n\nimport * as z from 'zod/v4';\n\nimport { processInParallel } from '../core/concurrency.ts';\nimport {\n ErrorCode,\n formatUnknownErrorMessage,\n FsError,\n type Problem,\n rethrowIfAborted,\n} from '../core/errors.ts';\nimport { buildWrittenFileMeta, writtenFileLinks, type WrittenFileMeta } from '../core/file-uri.ts';\nimport { destExists, type Stats } from '../core/fs.ts';\nimport { confirmKey, pendingRoundTrip, readPendingVerdict } from '../core/input-required.ts';\nimport { detectMimeFromContent, type FileKind } from '../core/mime.ts';\nimport { isSamePath } from '../core/path-utils.ts';\nimport { RequiredPath } from '../core/schema.ts';\nimport { getMaxTextFileSize, PARALLEL_CONCURRENCY } from '../core/util.ts';\nimport { isTotalFailure, runOverPaths } from './batch.ts';\nimport { defineTool, type ToolCtx } from './define.ts';\n\nconst EPOCH = new Date(0);\n\nconst CreateFileItemSchema = z.strictObject({\n path: RequiredPath.describe('Absolute path where the file will be created'),\n content: z\n .string()\n .refine((val) => val.length <= getMaxTextFileSize(), {\n message: 'Content exceeds maximum allowed text file size',\n })\n .describe('Text content to write, verbatim.'),\n append: z\n .boolean()\n .optional()\n .describe(\n 'Append the content to the end of the file instead of overwriting; creates the file if it does not exist',\n ),\n overwrite: z\n .boolean()\n .optional()\n .describe(\n 'Replace an existing file without asking the user; without it an existing file prompts for confirmation',\n ),\n});\n\ntype CreateFileResult = Omit<WrittenFileMeta, 'resourceLink'> & {\n path: string;\n created: string;\n modified: string;\n};\n\nconst CreateInputSchema = z\n .strictObject({\n files: z\n .array(CreateFileItemSchema)\n .min(1)\n .max(100)\n .describe(\n 'List of files to create (max 100); each entry requires path and content; combined content is capped at the file-size limit',\n ),\n })\n .superRefine((value, ctx) => {\n // Entries write in parallel and each replaces its file whole, so two\n // entries for one path race: the last rename wins and the other's\n // content is lost while both report success. One entry per file.\n for (const [index, file] of value.files.entries()) {\n const first = value.files.findIndex((other) => isSamePath(other.path, file.path));\n if (first < index) {\n ctx.addIssue({\n code: 'custom',\n path: ['files', index, 'path'],\n message: `duplicate of files[${String(first)}].path; one entry per file`,\n input: value,\n });\n }\n }\n // One call's content is what one inbound message carries; the transports\n // size their message bound from this same limit (getMaxInboundMessageBytes),\n // so a batch that passes here always fits on the wire. Counted in the same\n // UTF-16 units as the per-file refine above.\n const total = value.files.reduce((sum, file) => sum + file.content.length, 0);\n const limit = getMaxTextFileSize();\n if (total > limit) {\n ctx.addIssue({\n code: 'custom',\n path: ['files'],\n message: `combined content is ${String(total)} characters; one create call carries at most ${String(limit)} (FS_MAX_FILE_SIZE). Split the batch.`,\n input: value,\n });\n }\n });\n\ninterface CreateFailureItem {\n path: string;\n error: Problem;\n}\n\ninterface CreateOutput {\n files: CreateFileResult[];\n failures?: CreateFailureItem[];\n skipped?: string[];\n}\n\nexport const CREATE = defineTool<typeof CreateInputSchema, CreateOutput>({\n name: 'create',\n title: 'Create Files',\n description:\n 'Write whole text files: create new ones, overwrite, or append. Missing parent directories are created. ' +\n 'edit or patch changes part of an existing file.',\n input: CreateInputSchema,\n readOnlyHint: false,\n accessPaths: (args) => args.files.map((f) => f.path),\n run: async (args, ctx) => {\n // Phase 1 (no mutation): which entries would replace a file that exists\n // right now? Those need the user's word before anything is written (R14).\n // append never destroys, and overwrite: true is that word given up front.\n // A path that fails validation here is left for runOverPaths to report.\n // A file that appears between rounds needs no re-stat before the write:\n // the retry re-plans, and the grown pending set fails the R9 check.\n const { results: planned } = await processInParallel(\n args.files,\n async (entry) => {\n if (entry.append || entry.overwrite) return undefined;\n try {\n const validPath = await ctx.fs.pathGuard.validatePathForWrite(entry.path);\n return (await destExists(ctx.fs, validPath, 'create')) ? validPath : undefined;\n } catch (error) {\n rethrowIfAborted(error);\n return undefined;\n }\n },\n PARALLEL_CONCURRENCY,\n ctx.signal,\n );\n const pendingByPath = new Map<string, string>();\n for (const { index, value } of planned) {\n const requested = args.files[index]?.path;\n if (value && requested) pendingByPath.set(requested, value);\n }\n const pendingSorted = [...new Set(pendingByPath.values())].sort();\n if (pendingSorted.length > 0) {\n // Round 1 returns input_required; a retry whose verified state does not\n // bind this overwrite set throws (R9) via `pendingRoundTrip`.\n const round = await pendingRoundTrip(ctx, {\n op: 'create',\n pending: pendingSorted,\n buildInputs: (paths) =>\n paths.map((target, i) => ({\n key: confirmKey(i),\n message: `\"${target}\" already exists. Overwrite it?`,\n choices: ['overwrite', 'skip'],\n })),\n });\n if (round !== undefined) return round;\n }\n\n const batch = await runOverPaths<\n z.infer<typeof CreateFileItemSchema>,\n { file: CreateFileResult; resourceLink?: ContentBlock } | { skipped: string }\n >(args.files, ctx, ErrorCode.UNKNOWN, async ({ path, content, append, overwrite }) => {\n const pendingPath = pendingByPath.get(path);\n if (pendingPath !== undefined) {\n const verdict = readPendingVerdict(ctx, pendingSorted, pendingPath, 'overwrite');\n if (verdict === 'skipped') return { skipped: path };\n if (verdict !== 'accepted') {\n throw new FsError(\n ErrorCode.CANCELLED,\n `create cancelled: overwrite of \"${path}\" was ${verdict.refused}`,\n path,\n );\n }\n }\n\n // Lock per resolved file so two entries naming one file (e.g. through a\n // symlinked parent) cannot clobber each other.\n return ctx.fs.lockForWrite(path, async (resolvedTarget) => {\n // The file may have appeared since the overwrite set was planned.\n if (\n !append &&\n !overwrite &&\n pendingPath === undefined &&\n (await destExists(ctx.fs, resolvedTarget, 'create'))\n ) {\n throw new FsError(\n ErrorCode.INVALID_INPUT,\n `create refused: \"${path}\" appeared after overwrite confirmation was checked`,\n path,\n );\n }\n return createOne(path, content, append, ctx);\n });\n });\n\n const results: CreateFileResult[] = [];\n const failures: CreateFailureItem[] = [];\n const skipped: string[] = [];\n const links: ContentBlock[] = [];\n for (const r of batch.results) {\n if ('error' in r) {\n failures.push({ path: r.path, error: r.error });\n continue;\n }\n if ('skipped' in r.value) {\n skipped.push(r.value.skipped);\n continue;\n }\n results.push(r.value.file);\n if (r.value.resourceLink) links.push(r.value.resourceLink);\n }\n\n const structured = {\n files: results,\n ...(failures.length > 0 ? { failures } : {}),\n ...(skipped.length > 0 ? { skipped } : {}),\n };\n // No `text` on purpose. The one-line roster this used to build named the\n // paths and dropped every per-file size, line count and error the caller\n // asked `create` for. Supplying no text makes this a data tool, so\n // `define.ts` renders the JSON and keeps it in `structuredContent`.\n return { structured, resources: links, isError: isTotalFailure(batch.summary) };\n },\n progress: (args) => ({\n label: 'Create',\n subject:\n args.files.length === 1\n ? basename(args.files[0]?.path ?? '')\n : `${String(args.files.length)} files`,\n }),\n});\n\nasync function createOne(\n path: string,\n content: string,\n append: boolean | undefined,\n ctx: ToolCtx,\n): Promise<{ file: CreateFileResult; resourceLink?: ContentBlock }> {\n await ctx.fs.mkdir(dirname(path), { recursive: true });\n\n // Overwrite: file content == `content`, so content-derived meta is\n // exact and the atomic temp+rename write protects the existing mode.\n // Append: the resulting file is everything that was there plus\n // `content`, so size/created/modified come from a real post-append\n // stat, MIME from the resulting file's leading bytes, and the line\n // count streams the file — reading a multi-GB log back whole is the\n // round-trip append exists to avoid.\n let validPath: string;\n let meta: WrittenFileMeta;\n let created: string;\n let modified: string;\n if (append) {\n const appended = await ctx.fs.appendFile(path, content, {\n signal: ctx.signal,\n });\n validPath = appended.validPath;\n // The append is the commit point: the bytes are on disk, so\n // everything below is best-effort RESULT METADATA, not part of the\n // write. It runs unwired to ctx.signal, and a metadata failure\n // degrades the result instead of failing it — either would report\n // the append as failed and a client retry would append twice. The\n // stat covers the committed validPath, never the input path: a\n // symlink there could have been swapped between write and stat,\n // and the result must describe the file the bytes landed in.\n let stats: Stats | undefined;\n let mimeType: string;\n let kind: FileKind;\n let lineCount = 0;\n try {\n stats = (await ctx.fs.stat(appended.validPath)).stats;\n // Sniff the resulting file's leading bytes, not the appended\n // chunk: text appended to a binary file is still a binary file.\n const sample = await ctx.fs.readLeadingSample(appended.validPath);\n const mimeInfo = detectMimeFromContent(appended.validPath, sample);\n mimeType = mimeInfo.mimeType;\n kind = mimeInfo.kind;\n lineCount = await ctx.fs.countFileLines(appended.validPath);\n } catch (error) {\n ctx.log(\n 'warning',\n `create append: result metadata degraded for ${appended.validPath}: ${formatUnknownErrorMessage(error)}`,\n 'create',\n );\n // A POSIX mode-0222 file appends fine but cannot be opened 'r';\n // fall back to the chunk for MIME (an approximation) and report\n // the line count as unknown-as-zero rather than fail the append.\n const mimeInfo = detectMimeFromContent(appended.validPath, content);\n mimeType = mimeInfo.mimeType;\n kind = mimeInfo.kind;\n }\n // A failed stat leaves the size unknown, so nothing is advertised.\n meta = {\n size: stats?.size ?? 0,\n lineCount,\n mimeType,\n kind,\n ...writtenFileLinks(\n appended.validPath,\n mimeType,\n stats?.size,\n false,\n stats?.mtime.toISOString(),\n ),\n };\n created = (stats?.birthtime ?? EPOCH).toISOString();\n modified = (stats?.mtime ?? EPOCH).toISOString();\n } else {\n const written = await ctx.fs.writeFile(path, content, {\n signal: ctx.signal,\n });\n validPath = written.validPath;\n const fileStats = (await ctx.fs.stat(path, { signal: ctx.signal })).stats;\n created = fileStats.birthtime.toISOString();\n modified = fileStats.mtime.toISOString();\n meta = buildWrittenFileMeta({\n validPath: written.validPath,\n content,\n lastModified: modified,\n });\n }\n\n const { resourceLink, ...fileMeta } = meta;\n const file: CreateFileResult = { path: validPath, ...fileMeta, created, modified };\n\n return resourceLink ? { file, resourceLink } : { file };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["../../src/tools/delete.ts"],"names":[],"mappings":"AAoYA,eAAO,MAAM,MAAM,mCA4CjB,CAAC"}
1
+ {"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["../../src/tools/delete.ts"],"names":[],"mappings":"AAiYA,eAAO,MAAM,MAAM,mCA4CjB,CAAC"}
@@ -4,7 +4,7 @@ import * as z from 'zod/v4';
4
4
  import { processInParallel } from "../core/concurrency.js";
5
5
  import { ErrorCode, FsError, isFsError, isNodeError, isNotFoundErrno, Problem, } from "../core/errors.js";
6
6
  import { joinRoster, pathLabel } from "../core/fmt.js";
7
- import { confirmKey, describeRefusal, pendingRoundTrip, readAcceptedChoice, } from "../core/input-required.js";
7
+ import { confirmKey, pendingRoundTrip, readPendingVerdict, } from "../core/input-required.js";
8
8
  import { resolveEntryType } from "../core/path-utils.js";
9
9
  import { defaultFalseBoolean, RequiredPath } from "../core/schema.js";
10
10
  import { PARALLEL_CONCURRENCY } from "../core/util.js";
@@ -149,16 +149,17 @@ async function finalizeDeletion(plan, args, ctx) {
149
149
  */
150
150
  async function executePlan(plan, args, ctx, pendingSorted, confirmationState) {
151
151
  if (plan.pending) {
152
- const key = confirmKey(pendingSorted.indexOf(plan.validPath));
153
- const choice = readAcceptedChoice(ctx.inputResponses, key);
154
- if (choice === 'skip') {
152
+ const verdict = readPendingVerdict(ctx, pendingSorted, plan.validPath, 'delete');
153
+ if (verdict === 'skipped') {
155
154
  return { skipped: true, path: plan.validPath };
156
155
  }
157
- if (choice !== 'delete') {
156
+ if (verdict !== 'accepted') {
158
157
  return {
159
158
  failure: {
160
159
  path: plan.validPath,
161
- error: Problem.cancelled(`Delete cancelled: confirmation was ${describeRefusal(ctx, key)}`, { path: plan.validPath }),
160
+ error: Problem.cancelled(`Delete cancelled: confirmation was ${verdict.refused}`, {
161
+ path: plan.validPath,
162
+ }),
162
163
  },
163
164
  };
164
165
  }
@@ -1 +1 @@
1
- {"version":3,"file":"delete.js","sourceRoot":"","sources":["../../src/tools/delete.ts"],"names":[],"mappings":"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","sourcesContent":["import type { InputRequiredResult } from '@modelcontextprotocol/server';\nimport { isInputRequiredResult } from '@modelcontextprotocol/server';\n\nimport { basename } from 'node:path';\n\nimport * as z from 'zod/v4';\n\nimport { processInParallel } from '../core/concurrency.ts';\nimport {\n ErrorCode,\n FsError,\n isFsError,\n isNodeError,\n isNotFoundErrno,\n Problem,\n} from '../core/errors.ts';\nimport { joinRoster, pathLabel } from '../core/fmt.ts';\nimport type { FileType, GuardedFileSystem } from '../core/fs.ts';\nimport {\n confirmKey,\n describeRefusal,\n type PendingDeleteIdentity,\n pendingRoundTrip,\n type PendingState,\n readAcceptedChoice,\n} from '../core/input-required.ts';\nimport { resolveEntryType } from '../core/path-utils.ts';\nimport { defaultFalseBoolean, RequiredPath } from '../core/schema.ts';\nimport { PARALLEL_CONCURRENCY } from '../core/util.ts';\nimport { type BatchResult, isTotalFailure, type PerPathResult, summarize } from './batch.ts';\nimport type { ToolCtx } from './define.ts';\nimport { defineTool } from './define.ts';\n\nconst DeleteInputSchema = z.strictObject({\n paths: z\n .array(RequiredPath)\n .min(1)\n .max(1000)\n .describe('Paths to delete (max 1000); accepts files, directories, or symlinks'),\n recursive: defaultFalseBoolean(\n 'Delete directory contents recursively (required for non-empty directories)',\n ),\n ignoreIfNotExists: defaultFalseBoolean(\n 'Silently succeed if a path does not exist instead of returning an error',\n ),\n});\n\ntype DeleteInput = z.infer<typeof DeleteInputSchema>;\ntype DeleteOutput = BatchResult<{ deleted: boolean }>;\ntype DeletePerPathResult = PerPathResult<{ deleted: boolean }>;\n\n// Internal types for error handling\ninterface DeleteFailure {\n path: string;\n error: Problem;\n}\n\nconst ERR_NOT_EMPTY = new Error('Directory not empty. Set recursive: true.');\n\nfunction toDeleteFailure(path: string, error: unknown): DeleteFailure {\n // A missing path reached here as the raw errno text (\"ENOENT: no such file or\n // directory, lstat 'c:\\...'\"), while `stat` reported the same condition as\n // \"Path not found\". One condition, one message — and the syscall name stays\n // off the wire.\n if (isNotFoundErrno(error)) {\n return {\n path,\n error: Problem.fromUnknown(\n new FsError(ErrorCode.NOT_FOUND, 'Path not found', path),\n ErrorCode.NOT_FOUND,\n path,\n ),\n };\n }\n if (\n isNodeError(error) &&\n (error.code === 'ENOTEMPTY' || error.code === 'EISDIR' || error.code === 'EEXIST')\n ) {\n return {\n path,\n error: Problem.fromUnknown(ERR_NOT_EMPTY, ErrorCode.INVALID_INPUT, path),\n };\n }\n return { path, error: Problem.fromUnknown(error, ErrorCode.UNKNOWN, path) };\n}\n\ntype LstatResult = Awaited<ReturnType<GuardedFileSystem['lstat']>>;\n\n/** A path's pre-checked plan: validated, statted, and flagged if it needs confirmation. */\ninterface DeletePlan {\n inputPath: string;\n validPath: string;\n itemType: FileType;\n firstStats: LstatResult;\n /** Recursive + non-empty directory: needs a round-trip confirmation. */\n pending: boolean;\n}\n\ntype PlanResult =\n | { status: 'fail'; failure: DeleteFailure }\n | { status: 'noop'; deleted: string }\n | { status: 'plan'; plan: DeletePlan };\n\n/**\n * Phase 1 (no mutation): validate, stat, and decide whether a path needs a\n * confirmation before anything is deleted. A pending path is a recursive\n * non-empty directory; everything else is ready to delete directly.\n */\nasync function planPath(\n inputPath: string,\n args: Pick<DeleteInput, 'recursive' | 'ignoreIfNotExists'>,\n fs: Pick<GuardedFileSystem, 'pathGuard' | 'lstat' | 'hasChildrenUnchecked'>,\n): Promise<PlanResult> {\n let validPath: string;\n try {\n validPath = await fs.pathGuard.validatePathForDelete(inputPath);\n } catch (error) {\n if (\n args.ignoreIfNotExists &&\n ((isFsError(error) && error.code === ErrorCode.NOT_FOUND) || isNotFoundErrno(error))\n ) {\n return { status: 'noop', deleted: inputPath };\n }\n return { status: 'fail', failure: toDeleteFailure(inputPath, error) };\n }\n\n if (fs.pathGuard.isAllowedRoot(validPath)) {\n return {\n status: 'fail',\n // Keyed by the REQUESTED path, like every other failure here: handleDelete\n // orders results by input path, and a resolved key would not be found for\n // a relative request.\n failure: {\n path: inputPath,\n error: Problem.accessDenied('Deleting a workspace root directory is not allowed', {\n path: validPath,\n }),\n },\n };\n }\n\n let firstStats: LstatResult;\n try {\n firstStats = await fs.lstat(validPath);\n } catch (error) {\n if (isNotFoundErrno(error) && args.ignoreIfNotExists) {\n return { status: 'noop', deleted: inputPath };\n }\n return { status: 'fail', failure: toDeleteFailure(inputPath, error) };\n }\n\n const itemType = resolveEntryType(firstStats.stats);\n let hasChildren = false;\n if (args.recursive && itemType === 'directory') {\n try {\n hasChildren = await fs.hasChildrenUnchecked(validPath);\n } catch (error) {\n return { status: 'fail', failure: toDeleteFailure(inputPath, error) };\n }\n }\n return {\n status: 'plan',\n plan: { inputPath, validPath, itemType, firstStats, pending: hasChildren },\n };\n}\n\ntype Identity = Pick<LstatResult['stats'], 'dev' | 'ino' | 'birthtimeMs'>;\n\n/** Same filesystem object. birthtimeMs joins dev/ino, which read 0 on some non-POSIX drivers. */\nconst sameIdentity = (a: Identity, b: Identity): boolean =>\n a.dev === b.dev && a.ino === b.ino && a.birthtimeMs === b.birthtimeMs;\n\n/**\n * Phase 2 (mutation): TOCTOU re-stat against the plan's first stat, then\n * delete. A type or identity change across the confirmation gap fails closed\n * rather than deleting a replacement object the user never confirmed.\n */\nasync function finalizeDeletion(\n plan: DeletePlan,\n args: Pick<DeleteInput, 'recursive' | 'ignoreIfNotExists'>,\n ctx: Pick<ToolCtx, 'fs' | 'log'>,\n): Promise<{ deleted: string } | { failure: DeleteFailure }> {\n let currentStats: LstatResult;\n try {\n currentStats = await ctx.fs.lstat(plan.validPath);\n } catch (error) {\n if (isNotFoundErrno(error) && args.ignoreIfNotExists) {\n return { deleted: plan.validPath };\n }\n return { failure: toDeleteFailure(plan.inputPath, error) };\n }\n\n const currentItemType = resolveEntryType(currentStats.stats);\n // Identity comparison, not just the coarse category: a swap during the\n // confirmation gap (delete original, create a same-named replacement) keeps\n // the type but changes dev/ino/birthtimeMs. birthtimeMs is the primary\n // cross-platform signal — dev/ino can read 0 on some non-POSIX drivers — so\n // combine all three rather than trusting dev/ino alone.\n const identityChanged = !sameIdentity(plan.firstStats.stats, currentStats.stats);\n if (plan.itemType !== 'other' && (currentItemType !== plan.itemType || identityChanged)) {\n return {\n failure: {\n path: plan.validPath,\n error: Problem.invalidInput(\n `Delete failed: item type changed from ${plan.itemType} to ${currentItemType} during confirmation.`,\n { path: plan.validPath },\n ),\n },\n };\n }\n\n try {\n if (currentStats.stats.isDirectory() && !args.recursive) await ctx.fs.rmdir(plan.validPath);\n else\n await ctx.fs.rm(plan.validPath, { recursive: args.recursive, force: args.ignoreIfNotExists });\n } catch (error) {\n return { failure: toDeleteFailure(plan.inputPath, error) };\n }\n\n ctx.log('info', `rm: ${plan.inputPath}`, 'delete');\n return { deleted: plan.validPath };\n}\n\n/**\n * Execute one planned path on the retry round. A pending path deletes only on\n * an accepted `confirm: true`; decline, cancel, or a missing key report\n * `CANCELLED` for that path (R3 proceed, R4/R5 cancelled). A non-pending path\n * deletes directly (R14: non-pending items proceed alongside accepted ones).\n */\nasync function executePlan(\n plan: DeletePlan,\n args: Pick<DeleteInput, 'recursive' | 'ignoreIfNotExists'>,\n ctx: Pick<ToolCtx, 'fs' | 'inputResponses' | 'droppedInputResponseKeys' | 'log'>,\n pendingSorted: readonly string[],\n confirmationState: PendingState | undefined,\n): Promise<{ deleted: string } | { failure: DeleteFailure } | { skipped: true; path: string }> {\n if (plan.pending) {\n const key = confirmKey(pendingSorted.indexOf(plan.validPath));\n const choice = readAcceptedChoice(ctx.inputResponses, key);\n if (choice === 'skip') {\n return { skipped: true as const, path: plan.validPath };\n }\n if (choice !== 'delete') {\n return {\n failure: {\n path: plan.validPath,\n error: Problem.cancelled(\n `Delete cancelled: confirmation was ${describeRefusal(ctx, key)}`,\n { path: plan.validPath },\n ),\n },\n };\n }\n const identity = confirmationState?.deleteIdentities?.find(\n (entry) => entry.path === plan.validPath,\n );\n if (identity?.itemType !== plan.itemType || !sameIdentity(identity, plan.firstStats.stats)) {\n return {\n failure: {\n path: plan.validPath,\n error: Problem.invalidInput(\n 'Delete failed: item identity changed or is missing from the confirmation.',\n { path: plan.validPath },\n ),\n },\n };\n }\n }\n return finalizeDeletion(plan, args, ctx);\n}\n\nasync function handleDelete(\n args: DeleteInput,\n ctx: ToolCtx,\n): Promise<DeleteOutput | InputRequiredResult> {\n // Duplicate paths collapse: results are keyed by path, so a repeated entry\n // would emit two rows for one deletion and inflate `summary.total`.\n const paths = [...new Set(args.paths)];\n\n // Phase 1 (no mutation): plan every path.\n const planned = await processInParallel(\n paths,\n (inputPath) => planPath(inputPath, args, ctx.fs),\n PARALLEL_CONCURRENCY,\n ctx.signal,\n );\n\n const out = new Array<DeletePerPathResult | undefined>(paths.length).fill(undefined);\n const plans: { plan: DeletePlan; index: number }[] = [];\n const confirmationState = ctx.requestState?.<PendingState>();\n const previouslyPendingPaths = new Set(\n confirmationState?.op === 'delete' ? confirmationState.paths : [],\n );\n for (const { index, value: r } of planned.results) {\n if (r.status === 'fail') out[index] = { path: r.failure.path, error: r.failure.error };\n else if (r.status === 'noop') out[index] = { path: r.deleted, value: { deleted: true } };\n else {\n // Emptying a directory while its prompt is open must not discard the\n // answer. Keep that path pending so the verified retry still honors skip.\n r.plan.pending ||= previouslyPendingPaths.has(r.plan.validPath);\n plans.push({ plan: r.plan, index });\n }\n }\n for (const { index, error } of planned.errors) {\n out[index] = {\n path: paths[index] ?? '(unknown)',\n error: { code: ErrorCode.UNKNOWN, message: error.message },\n };\n }\n\n // Pending set: recursive + non-empty directories, sorted and de-duplicated.\n // `buildInputRequired` seals exactly this set into the requestState, and the\n // retried round recomputes it from the same args so a swapped retry (accept\n // for X, retry with Y) is rejected — the codec only proves the state was not\n // tampered, not that it matches the current request (R9).\n const pendingSorted = [\n ...new Set(plans.filter((p) => p.plan.pending).map((p) => p.plan.validPath)),\n ].sort();\n\n // With no actionable plans, preserve per-path NOT_FOUND / ignoreIfNotExists\n // results. Otherwise even an empty pending set must be checked before an\n // unrelated non-pending batch entry can mutate.\n if (pendingSorted.length > 0 || (confirmationState?.op === 'delete' && plans.length > 0)) {\n // Round 1 returns input_required (atomic — R14: nothing deleted yet, not\n // even the non-pending items in the same call); a retry whose verified\n // state does not bind this pending set throws (R9) via `pendingRoundTrip`.\n const round = await pendingRoundTrip(ctx, {\n op: 'delete',\n pending: pendingSorted,\n deleteIdentities: plans\n .filter(({ plan }) => plan.pending)\n .map(({ plan }): PendingDeleteIdentity => {\n const { dev, ino, birthtimeMs } = plan.firstStats.stats;\n return { path: plan.validPath, itemType: plan.itemType, dev, ino, birthtimeMs };\n }),\n buildInputs: (ps) =>\n ps.map((p, i) => ({\n key: confirmKey(i),\n message: `Permanently delete \"${p}\" and all its contents? This cannot be undone.`,\n choices: ['delete', 'skip'],\n })),\n });\n if (round !== undefined) return round;\n }\n\n // Phase 2 (mutation): execute deletions for every planned path.\n const executed = await processInParallel(\n plans,\n ({ plan }) => executePlan(plan, args, ctx, pendingSorted, confirmationState),\n PARALLEL_CONCURRENCY,\n ctx.signal,\n );\n\n for (const { index, value: r } of executed.results) {\n const slot = plans[index]?.index;\n if (slot === undefined) continue;\n if ('skipped' in r) {\n out[slot] = { path: r.path, value: { deleted: false } };\n } else if ('failure' in r) {\n out[slot] = { path: r.failure.path, error: r.failure.error };\n } else {\n out[slot] = { path: r.deleted, value: { deleted: true } };\n }\n }\n for (const { index, error } of executed.errors) {\n const slot = plans[index]?.index;\n if (slot === undefined) continue;\n out[slot] = {\n path: paths[slot] ?? '(unknown)',\n error: { code: ErrorCode.UNKNOWN, message: error.message },\n };\n }\n\n // Emit in the caller's input order so `results[i]` lines up with `paths[i]`\n // the way read/stat guarantee.\n const results: DeletePerPathResult[] = paths.map((requested, i) => {\n const entry = out[i];\n return (\n entry ?? {\n path: requested,\n error: { code: ErrorCode.UNKNOWN, message: 'Unknown delete failure' },\n }\n );\n });\n\n return { results, summary: summarize(results) };\n}\n\nexport const DELETE = defineTool<typeof DeleteInputSchema, DeleteOutput>({\n name: 'delete',\n title: 'Delete File',\n description:\n 'Permanently delete files, directories, or symlinks, like rm or rm -r. Paths are exact; globs are not expanded.',\n input: DeleteInputSchema,\n readOnlyHint: false,\n progress: (args) => ({\n label: 'Delete',\n subject:\n args.paths.length === 1\n ? basename(args.paths[0] ?? '')\n : `${String(args.paths.length)} paths`,\n }),\n accessPaths: (args) => [...args.paths],\n run: async (args, ctx) => {\n const structured = await handleDelete(args, ctx);\n // input_required is a return value, not a completed call: surface it\n // verbatim so the executor short-circuits before building a CallToolResult.\n if (isInputRequiredResult(structured)) return structured;\n // Name every path and its outcome. The old text said \"deleted 2 paths\"\n // without saying which two, so a partial failure was unreadable without\n // parsing the structured half.\n const { failed, total } = structured.summary;\n const isError = isTotalFailure(structured.summary);\n // A lone failure carries its reason in the text. \"delete: . FAILED (0/1 ok)\"\n // made the model re-read structuredContent to learn it was ACCESS_DENIED;\n // with one path there is no ambiguity about which message applies.\n if (total === 1 && failed === 1) {\n const only = structured.results[0];\n return {\n structured,\n text: `delete: ${only?.path ?? ''} FAILED — ${only && 'error' in only ? only.error.message : 'unknown error'}`,\n isError,\n };\n }\n const tokens = structured.results.map((r) => {\n const label = pathLabel(r.path);\n if ('error' in r) return `${label} FAILED`;\n return r.value.deleted ? label : `${label} SKIPPED`;\n });\n const ratio = failed > 0 ? ` (${String(total - failed)}/${String(total)} ok)` : '';\n return { structured, text: `delete: ${joinRoster(tokens)}${ratio}`, isError };\n },\n});\n"]}
1
+ {"version":3,"file":"delete.js","sourceRoot":"","sources":["../../src/tools/delete.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAErE,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EACL,SAAS,EACT,OAAO,EACP,SAAS,EACT,WAAW,EACX,eAAe,EACf,OAAO,GACR,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEvD,OAAO,EACL,UAAU,EAEV,gBAAgB,EAEhB,kBAAkB,GACnB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAoB,cAAc,EAAsB,SAAS,EAAE,MAAM,YAAY,CAAC;AAE7F,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,iBAAiB,GAAG,CAAC,CAAC,YAAY,CAAC;IACvC,KAAK,EAAE,CAAC;SACL,KAAK,CAAC,YAAY,CAAC;SACnB,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,IAAI,CAAC;SACT,QAAQ,CAAC,qEAAqE,CAAC;IAClF,SAAS,EAAE,mBAAmB,CAC5B,4EAA4E,CAC7E;IACD,iBAAiB,EAAE,mBAAmB,CACpC,yEAAyE,CAC1E;CACF,CAAC,CAAC;AAYH,MAAM,aAAa,GAAG,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;AAE7E,SAAS,eAAe,CAAC,IAAY,EAAE,KAAc;IACnD,8EAA8E;IAC9E,2EAA2E;IAC3E,4EAA4E;IAC5E,gBAAgB;IAChB,IAAI,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO;YACL,IAAI;YACJ,KAAK,EAAE,OAAO,CAAC,WAAW,CACxB,IAAI,OAAO,CAAC,SAAS,CAAC,SAAS,EAAE,gBAAgB,EAAE,IAAI,CAAC,EACxD,SAAS,CAAC,SAAS,EACnB,IAAI,CACL;SACF,CAAC;IACJ,CAAC;IACD,IACE,WAAW,CAAC,KAAK,CAAC;QAClB,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,EAClF,CAAC;QACD,OAAO;YACL,IAAI;YACJ,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,aAAa,EAAE,SAAS,CAAC,aAAa,EAAE,IAAI,CAAC;SACzE,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;AAC9E,CAAC;AAmBD;;;;GAIG;AACH,KAAK,UAAU,QAAQ,CACrB,SAAiB,EACjB,IAA0D,EAC1D,EAA2E;IAE3E,IAAI,SAAiB,CAAC;IACtB,IAAI,CAAC;QACH,SAAS,GAAG,MAAM,EAAE,CAAC,SAAS,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;IAClE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IACE,IAAI,CAAC,iBAAiB;YACtB,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,SAAS,CAAC,IAAI,eAAe,CAAC,KAAK,CAAC,CAAC,EACpF,CAAC;YACD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;QAChD,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC;IACxE,CAAC;IAED,IAAI,EAAE,CAAC,SAAS,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1C,OAAO;YACL,MAAM,EAAE,MAAM;YACd,2EAA2E;YAC3E,0EAA0E;YAC1E,sBAAsB;YACtB,OAAO,EAAE;gBACP,IAAI,EAAE,SAAS;gBACf,KAAK,EAAE,OAAO,CAAC,YAAY,CAAC,oDAAoD,EAAE;oBAChF,IAAI,EAAE,SAAS;iBAChB,CAAC;aACH;SACF,CAAC;IACJ,CAAC;IAED,IAAI,UAAuB,CAAC;IAC5B,IAAI,CAAC;QACH,UAAU,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACzC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,eAAe,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACrD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;QAChD,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC;IACxE,CAAC;IAED,MAAM,QAAQ,GAAG,gBAAgB,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IACpD,IAAI,WAAW,GAAG,KAAK,CAAC;IACxB,IAAI,IAAI,CAAC,SAAS,IAAI,QAAQ,KAAK,WAAW,EAAE,CAAC;QAC/C,IAAI,CAAC;YACH,WAAW,GAAG,MAAM,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC;QACzD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC;QACxE,CAAC;IACH,CAAC;IACD,OAAO;QACL,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE;KAC3E,CAAC;AACJ,CAAC;AAID,iGAAiG;AACjG,MAAM,YAAY,GAAG,CAAC,CAAW,EAAE,CAAW,EAAW,EAAE,CACzD,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,WAAW,KAAK,CAAC,CAAC,WAAW,CAAC;AAExE;;;;GAIG;AACH,KAAK,UAAU,gBAAgB,CAC7B,IAAgB,EAChB,IAA0D,EAC1D,GAAgC;IAEhC,IAAI,YAAyB,CAAC;IAC9B,IAAI,CAAC;QACH,YAAY,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,eAAe,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACrD,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;QACrC,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,eAAe,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC;IAC7D,CAAC;IAED,MAAM,eAAe,GAAG,gBAAgB,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAC7D,uEAAuE;IACvE,4EAA4E;IAC5E,uEAAuE;IACvE,4EAA4E;IAC5E,wDAAwD;IACxD,MAAM,eAAe,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC;IACjF,IAAI,IAAI,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC,eAAe,KAAK,IAAI,CAAC,QAAQ,IAAI,eAAe,CAAC,EAAE,CAAC;QACxF,OAAO;YACL,OAAO,EAAE;gBACP,IAAI,EAAE,IAAI,CAAC,SAAS;gBACpB,KAAK,EAAE,OAAO,CAAC,YAAY,CACzB,yCAAyC,IAAI,CAAC,QAAQ,OAAO,eAAe,uBAAuB,EACnG,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,CACzB;aACF;SACF,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,IAAI,YAAY,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,MAAM,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;;YAE1F,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAClG,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,OAAO,EAAE,eAAe,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC;IAC7D,CAAC;IAED,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,IAAI,CAAC,SAAS,EAAE,EAAE,QAAQ,CAAC,CAAC;IACnD,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;AACrC,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,WAAW,CACxB,IAAgB,EAChB,IAA0D,EAC1D,GAAgF,EAChF,aAAgC,EAChC,iBAA2C;IAE3C,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,MAAM,OAAO,GAAG,kBAAkB,CAAC,GAAG,EAAE,aAAa,EAAE,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QACjF,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,EAAE,OAAO,EAAE,IAAa,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;QAC1D,CAAC;QACD,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;YAC3B,OAAO;gBACL,OAAO,EAAE;oBACP,IAAI,EAAE,IAAI,CAAC,SAAS;oBACpB,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,sCAAsC,OAAO,CAAC,OAAO,EAAE,EAAE;wBAChF,IAAI,EAAE,IAAI,CAAC,SAAS;qBACrB,CAAC;iBACH;aACF,CAAC;QACJ,CAAC;QACD,MAAM,QAAQ,GAAG,iBAAiB,EAAE,gBAAgB,EAAE,IAAI,CACxD,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,SAAS,CACzC,CAAC;QACF,IAAI,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC,QAAQ,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3F,OAAO;gBACL,OAAO,EAAE;oBACP,IAAI,EAAE,IAAI,CAAC,SAAS;oBACpB,KAAK,EAAE,OAAO,CAAC,YAAY,CACzB,2EAA2E,EAC3E,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,CACzB;iBACF;aACF,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;AAC3C,CAAC;AAED,KAAK,UAAU,YAAY,CACzB,IAAiB,EACjB,GAAY;IAEZ,2EAA2E;IAC3E,oEAAoE;IACpE,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAEvC,0CAA0C;IAC1C,MAAM,OAAO,GAAG,MAAM,iBAAiB,CACrC,KAAK,EACL,CAAC,SAAS,EAAE,EAAE,CAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC,EAChD,oBAAoB,EACpB,GAAG,CAAC,MAAM,CACX,CAAC;IAEF,MAAM,GAAG,GAAG,IAAI,KAAK,CAAkC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACrF,MAAM,KAAK,GAA0C,EAAE,CAAC;IACxD,MAAM,iBAAiB,GAAG,GAAG,CAAC,YAAY,EAAE,EAAgB,CAAC;IAC7D,MAAM,sBAAsB,GAAG,IAAI,GAAG,CACpC,iBAAiB,EAAE,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAClE,CAAC;IACF,KAAK,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QAClD,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM;YAAE,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;aAClF,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM;YAAE,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC;aACpF,CAAC;YACJ,qEAAqE;YACrE,0EAA0E;YAC1E,CAAC,CAAC,IAAI,CAAC,OAAO,KAAK,sBAAsB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAChE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IACD,KAAK,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QAC9C,GAAG,CAAC,KAAK,CAAC,GAAG;YACX,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,WAAW;YACjC,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE;SAC3D,CAAC;IACJ,CAAC;IAED,4EAA4E;IAC5E,6EAA6E;IAC7E,4EAA4E;IAC5E,6EAA6E;IAC7E,0DAA0D;IAC1D,MAAM,aAAa,GAAG;QACpB,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;KAC7E,CAAC,IAAI,EAAE,CAAC;IAET,4EAA4E;IAC5E,yEAAyE;IACzE,gDAAgD;IAChD,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;QACzF,yEAAyE;QACzE,uEAAuE;QACvE,2EAA2E;QAC3E,MAAM,KAAK,GAAG,MAAM,gBAAgB,CAAC,GAAG,EAAE;YACxC,EAAE,EAAE,QAAQ;YACZ,OAAO,EAAE,aAAa;YACtB,gBAAgB,EAAE,KAAK;iBACpB,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC;iBAClC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAyB,EAAE;gBACvC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;gBACxD,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,WAAW,EAAE,CAAC;YAClF,CAAC,CAAC;YACJ,WAAW,EAAE,CAAC,EAAE,EAAE,EAAE,CAClB,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;gBAChB,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC;gBAClB,OAAO,EAAE,uBAAuB,CAAC,gDAAgD;gBACjF,OAAO,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC;aAC5B,CAAC,CAAC;SACN,CAAC,CAAC;QACH,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;IACxC,CAAC;IAED,gEAAgE;IAChE,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CACtC,KAAK,EACL,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,aAAa,EAAE,iBAAiB,CAAC,EAC5E,oBAAoB,EACpB,GAAG,CAAC,MAAM,CACX,CAAC;IAEF,KAAK,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;QACnD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;QACjC,IAAI,IAAI,KAAK,SAAS;YAAE,SAAS;QACjC,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;YACnB,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC;QAC1D,CAAC;aAAM,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;YAC1B,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAC/D,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC;QAC5D,CAAC;IACH,CAAC;IACD,KAAK,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC/C,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;QACjC,IAAI,IAAI,KAAK,SAAS;YAAE,SAAS;QACjC,GAAG,CAAC,IAAI,CAAC,GAAG;YACV,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,WAAW;YAChC,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE;SAC3D,CAAC;IACJ,CAAC;IAED,4EAA4E;IAC5E,+BAA+B;IAC/B,MAAM,OAAO,GAA0B,KAAK,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,CAAC,EAAE,EAAE;QAChE,MAAM,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QACrB,OAAO,CACL,KAAK,IAAI;YACP,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,wBAAwB,EAAE;SACtE,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;AAClD,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAG,UAAU,CAAyC;IACvE,IAAI,EAAE,QAAQ;IACd,KAAK,EAAE,aAAa;IACpB,WAAW,EACT,gHAAgH;IAClH,KAAK,EAAE,iBAAiB;IACxB,YAAY,EAAE,KAAK;IACnB,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACnB,KAAK,EAAE,QAAQ;QACf,OAAO,EACL,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;YACrB,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC/B,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ;KAC3C,CAAC;IACF,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;IACtC,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;QACvB,MAAM,UAAU,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACjD,qEAAqE;QACrE,4EAA4E;QAC5E,IAAI,qBAAqB,CAAC,UAAU,CAAC;YAAE,OAAO,UAAU,CAAC;QACzD,uEAAuE;QACvE,wEAAwE;QACxE,+BAA+B;QAC/B,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,UAAU,CAAC,OAAO,CAAC;QAC7C,MAAM,OAAO,GAAG,cAAc,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QACnD,6EAA6E;QAC7E,0EAA0E;QAC1E,mEAAmE;QACnE,IAAI,KAAK,KAAK,CAAC,IAAI,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACnC,OAAO;gBACL,UAAU;gBACV,IAAI,EAAE,WAAW,IAAI,EAAE,IAAI,IAAI,EAAE,aAAa,IAAI,IAAI,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE;gBAC9G,OAAO;aACR,CAAC;QACJ,CAAC;QACD,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YAC1C,MAAM,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAChC,IAAI,OAAO,IAAI,CAAC;gBAAE,OAAO,GAAG,KAAK,SAAS,CAAC;YAC3C,OAAO,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,UAAU,CAAC;QACtD,CAAC,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QACnF,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,UAAU,CAAC,MAAM,CAAC,GAAG,KAAK,EAAE,EAAE,OAAO,EAAE,CAAC;IAChF,CAAC;CACF,CAAC,CAAC","sourcesContent":["import type { InputRequiredResult } from '@modelcontextprotocol/server';\nimport { isInputRequiredResult } from '@modelcontextprotocol/server';\n\nimport { basename } from 'node:path';\n\nimport * as z from 'zod/v4';\n\nimport { processInParallel } from '../core/concurrency.ts';\nimport {\n ErrorCode,\n FsError,\n isFsError,\n isNodeError,\n isNotFoundErrno,\n Problem,\n} from '../core/errors.ts';\nimport { joinRoster, pathLabel } from '../core/fmt.ts';\nimport type { FileType, GuardedFileSystem } from '../core/fs.ts';\nimport {\n confirmKey,\n type PendingDeleteIdentity,\n pendingRoundTrip,\n type PendingState,\n readPendingVerdict,\n} from '../core/input-required.ts';\nimport { resolveEntryType } from '../core/path-utils.ts';\nimport { defaultFalseBoolean, RequiredPath } from '../core/schema.ts';\nimport { PARALLEL_CONCURRENCY } from '../core/util.ts';\nimport { type BatchResult, isTotalFailure, type PerPathResult, summarize } from './batch.ts';\nimport type { ToolCtx } from './define.ts';\nimport { defineTool } from './define.ts';\n\nconst DeleteInputSchema = z.strictObject({\n paths: z\n .array(RequiredPath)\n .min(1)\n .max(1000)\n .describe('Paths to delete (max 1000); accepts files, directories, or symlinks'),\n recursive: defaultFalseBoolean(\n 'Delete directory contents recursively (required for non-empty directories)',\n ),\n ignoreIfNotExists: defaultFalseBoolean(\n 'Silently succeed if a path does not exist instead of returning an error',\n ),\n});\n\ntype DeleteInput = z.infer<typeof DeleteInputSchema>;\ntype DeleteOutput = BatchResult<{ deleted: boolean }>;\ntype DeletePerPathResult = PerPathResult<{ deleted: boolean }>;\n\n// Internal types for error handling\ninterface DeleteFailure {\n path: string;\n error: Problem;\n}\n\nconst ERR_NOT_EMPTY = new Error('Directory not empty. Set recursive: true.');\n\nfunction toDeleteFailure(path: string, error: unknown): DeleteFailure {\n // A missing path reached here as the raw errno text (\"ENOENT: no such file or\n // directory, lstat 'c:\\...'\"), while `stat` reported the same condition as\n // \"Path not found\". One condition, one message — and the syscall name stays\n // off the wire.\n if (isNotFoundErrno(error)) {\n return {\n path,\n error: Problem.fromUnknown(\n new FsError(ErrorCode.NOT_FOUND, 'Path not found', path),\n ErrorCode.NOT_FOUND,\n path,\n ),\n };\n }\n if (\n isNodeError(error) &&\n (error.code === 'ENOTEMPTY' || error.code === 'EISDIR' || error.code === 'EEXIST')\n ) {\n return {\n path,\n error: Problem.fromUnknown(ERR_NOT_EMPTY, ErrorCode.INVALID_INPUT, path),\n };\n }\n return { path, error: Problem.fromUnknown(error, ErrorCode.UNKNOWN, path) };\n}\n\ntype LstatResult = Awaited<ReturnType<GuardedFileSystem['lstat']>>;\n\n/** A path's pre-checked plan: validated, statted, and flagged if it needs confirmation. */\ninterface DeletePlan {\n inputPath: string;\n validPath: string;\n itemType: FileType;\n firstStats: LstatResult;\n /** Recursive + non-empty directory: needs a round-trip confirmation. */\n pending: boolean;\n}\n\ntype PlanResult =\n | { status: 'fail'; failure: DeleteFailure }\n | { status: 'noop'; deleted: string }\n | { status: 'plan'; plan: DeletePlan };\n\n/**\n * Phase 1 (no mutation): validate, stat, and decide whether a path needs a\n * confirmation before anything is deleted. A pending path is a recursive\n * non-empty directory; everything else is ready to delete directly.\n */\nasync function planPath(\n inputPath: string,\n args: Pick<DeleteInput, 'recursive' | 'ignoreIfNotExists'>,\n fs: Pick<GuardedFileSystem, 'pathGuard' | 'lstat' | 'hasChildrenUnchecked'>,\n): Promise<PlanResult> {\n let validPath: string;\n try {\n validPath = await fs.pathGuard.validatePathForDelete(inputPath);\n } catch (error) {\n if (\n args.ignoreIfNotExists &&\n ((isFsError(error) && error.code === ErrorCode.NOT_FOUND) || isNotFoundErrno(error))\n ) {\n return { status: 'noop', deleted: inputPath };\n }\n return { status: 'fail', failure: toDeleteFailure(inputPath, error) };\n }\n\n if (fs.pathGuard.isAllowedRoot(validPath)) {\n return {\n status: 'fail',\n // Keyed by the REQUESTED path, like every other failure here: handleDelete\n // orders results by input path, and a resolved key would not be found for\n // a relative request.\n failure: {\n path: inputPath,\n error: Problem.accessDenied('Deleting a workspace root directory is not allowed', {\n path: validPath,\n }),\n },\n };\n }\n\n let firstStats: LstatResult;\n try {\n firstStats = await fs.lstat(validPath);\n } catch (error) {\n if (isNotFoundErrno(error) && args.ignoreIfNotExists) {\n return { status: 'noop', deleted: inputPath };\n }\n return { status: 'fail', failure: toDeleteFailure(inputPath, error) };\n }\n\n const itemType = resolveEntryType(firstStats.stats);\n let hasChildren = false;\n if (args.recursive && itemType === 'directory') {\n try {\n hasChildren = await fs.hasChildrenUnchecked(validPath);\n } catch (error) {\n return { status: 'fail', failure: toDeleteFailure(inputPath, error) };\n }\n }\n return {\n status: 'plan',\n plan: { inputPath, validPath, itemType, firstStats, pending: hasChildren },\n };\n}\n\ntype Identity = Pick<LstatResult['stats'], 'dev' | 'ino' | 'birthtimeMs'>;\n\n/** Same filesystem object. birthtimeMs joins dev/ino, which read 0 on some non-POSIX drivers. */\nconst sameIdentity = (a: Identity, b: Identity): boolean =>\n a.dev === b.dev && a.ino === b.ino && a.birthtimeMs === b.birthtimeMs;\n\n/**\n * Phase 2 (mutation): TOCTOU re-stat against the plan's first stat, then\n * delete. A type or identity change across the confirmation gap fails closed\n * rather than deleting a replacement object the user never confirmed.\n */\nasync function finalizeDeletion(\n plan: DeletePlan,\n args: Pick<DeleteInput, 'recursive' | 'ignoreIfNotExists'>,\n ctx: Pick<ToolCtx, 'fs' | 'log'>,\n): Promise<{ deleted: string } | { failure: DeleteFailure }> {\n let currentStats: LstatResult;\n try {\n currentStats = await ctx.fs.lstat(plan.validPath);\n } catch (error) {\n if (isNotFoundErrno(error) && args.ignoreIfNotExists) {\n return { deleted: plan.validPath };\n }\n return { failure: toDeleteFailure(plan.inputPath, error) };\n }\n\n const currentItemType = resolveEntryType(currentStats.stats);\n // Identity comparison, not just the coarse category: a swap during the\n // confirmation gap (delete original, create a same-named replacement) keeps\n // the type but changes dev/ino/birthtimeMs. birthtimeMs is the primary\n // cross-platform signal — dev/ino can read 0 on some non-POSIX drivers — so\n // combine all three rather than trusting dev/ino alone.\n const identityChanged = !sameIdentity(plan.firstStats.stats, currentStats.stats);\n if (plan.itemType !== 'other' && (currentItemType !== plan.itemType || identityChanged)) {\n return {\n failure: {\n path: plan.validPath,\n error: Problem.invalidInput(\n `Delete failed: item type changed from ${plan.itemType} to ${currentItemType} during confirmation.`,\n { path: plan.validPath },\n ),\n },\n };\n }\n\n try {\n if (currentStats.stats.isDirectory() && !args.recursive) await ctx.fs.rmdir(plan.validPath);\n else\n await ctx.fs.rm(plan.validPath, { recursive: args.recursive, force: args.ignoreIfNotExists });\n } catch (error) {\n return { failure: toDeleteFailure(plan.inputPath, error) };\n }\n\n ctx.log('info', `rm: ${plan.inputPath}`, 'delete');\n return { deleted: plan.validPath };\n}\n\n/**\n * Execute one planned path on the retry round. A pending path deletes only on\n * an accepted `confirm: true`; decline, cancel, or a missing key report\n * `CANCELLED` for that path (R3 proceed, R4/R5 cancelled). A non-pending path\n * deletes directly (R14: non-pending items proceed alongside accepted ones).\n */\nasync function executePlan(\n plan: DeletePlan,\n args: Pick<DeleteInput, 'recursive' | 'ignoreIfNotExists'>,\n ctx: Pick<ToolCtx, 'fs' | 'inputResponses' | 'droppedInputResponseKeys' | 'log'>,\n pendingSorted: readonly string[],\n confirmationState: PendingState | undefined,\n): Promise<{ deleted: string } | { failure: DeleteFailure } | { skipped: true; path: string }> {\n if (plan.pending) {\n const verdict = readPendingVerdict(ctx, pendingSorted, plan.validPath, 'delete');\n if (verdict === 'skipped') {\n return { skipped: true as const, path: plan.validPath };\n }\n if (verdict !== 'accepted') {\n return {\n failure: {\n path: plan.validPath,\n error: Problem.cancelled(`Delete cancelled: confirmation was ${verdict.refused}`, {\n path: plan.validPath,\n }),\n },\n };\n }\n const identity = confirmationState?.deleteIdentities?.find(\n (entry) => entry.path === plan.validPath,\n );\n if (identity?.itemType !== plan.itemType || !sameIdentity(identity, plan.firstStats.stats)) {\n return {\n failure: {\n path: plan.validPath,\n error: Problem.invalidInput(\n 'Delete failed: item identity changed or is missing from the confirmation.',\n { path: plan.validPath },\n ),\n },\n };\n }\n }\n return finalizeDeletion(plan, args, ctx);\n}\n\nasync function handleDelete(\n args: DeleteInput,\n ctx: ToolCtx,\n): Promise<DeleteOutput | InputRequiredResult> {\n // Duplicate paths collapse: results are keyed by path, so a repeated entry\n // would emit two rows for one deletion and inflate `summary.total`.\n const paths = [...new Set(args.paths)];\n\n // Phase 1 (no mutation): plan every path.\n const planned = await processInParallel(\n paths,\n (inputPath) => planPath(inputPath, args, ctx.fs),\n PARALLEL_CONCURRENCY,\n ctx.signal,\n );\n\n const out = new Array<DeletePerPathResult | undefined>(paths.length).fill(undefined);\n const plans: { plan: DeletePlan; index: number }[] = [];\n const confirmationState = ctx.requestState?.<PendingState>();\n const previouslyPendingPaths = new Set(\n confirmationState?.op === 'delete' ? confirmationState.paths : [],\n );\n for (const { index, value: r } of planned.results) {\n if (r.status === 'fail') out[index] = { path: r.failure.path, error: r.failure.error };\n else if (r.status === 'noop') out[index] = { path: r.deleted, value: { deleted: true } };\n else {\n // Emptying a directory while its prompt is open must not discard the\n // answer. Keep that path pending so the verified retry still honors skip.\n r.plan.pending ||= previouslyPendingPaths.has(r.plan.validPath);\n plans.push({ plan: r.plan, index });\n }\n }\n for (const { index, error } of planned.errors) {\n out[index] = {\n path: paths[index] ?? '(unknown)',\n error: { code: ErrorCode.UNKNOWN, message: error.message },\n };\n }\n\n // Pending set: recursive + non-empty directories, sorted and de-duplicated.\n // `buildInputRequired` seals exactly this set into the requestState, and the\n // retried round recomputes it from the same args so a swapped retry (accept\n // for X, retry with Y) is rejected — the codec only proves the state was not\n // tampered, not that it matches the current request (R9).\n const pendingSorted = [\n ...new Set(plans.filter((p) => p.plan.pending).map((p) => p.plan.validPath)),\n ].sort();\n\n // With no actionable plans, preserve per-path NOT_FOUND / ignoreIfNotExists\n // results. Otherwise even an empty pending set must be checked before an\n // unrelated non-pending batch entry can mutate.\n if (pendingSorted.length > 0 || (confirmationState?.op === 'delete' && plans.length > 0)) {\n // Round 1 returns input_required (atomic — R14: nothing deleted yet, not\n // even the non-pending items in the same call); a retry whose verified\n // state does not bind this pending set throws (R9) via `pendingRoundTrip`.\n const round = await pendingRoundTrip(ctx, {\n op: 'delete',\n pending: pendingSorted,\n deleteIdentities: plans\n .filter(({ plan }) => plan.pending)\n .map(({ plan }): PendingDeleteIdentity => {\n const { dev, ino, birthtimeMs } = plan.firstStats.stats;\n return { path: plan.validPath, itemType: plan.itemType, dev, ino, birthtimeMs };\n }),\n buildInputs: (ps) =>\n ps.map((p, i) => ({\n key: confirmKey(i),\n message: `Permanently delete \"${p}\" and all its contents? This cannot be undone.`,\n choices: ['delete', 'skip'],\n })),\n });\n if (round !== undefined) return round;\n }\n\n // Phase 2 (mutation): execute deletions for every planned path.\n const executed = await processInParallel(\n plans,\n ({ plan }) => executePlan(plan, args, ctx, pendingSorted, confirmationState),\n PARALLEL_CONCURRENCY,\n ctx.signal,\n );\n\n for (const { index, value: r } of executed.results) {\n const slot = plans[index]?.index;\n if (slot === undefined) continue;\n if ('skipped' in r) {\n out[slot] = { path: r.path, value: { deleted: false } };\n } else if ('failure' in r) {\n out[slot] = { path: r.failure.path, error: r.failure.error };\n } else {\n out[slot] = { path: r.deleted, value: { deleted: true } };\n }\n }\n for (const { index, error } of executed.errors) {\n const slot = plans[index]?.index;\n if (slot === undefined) continue;\n out[slot] = {\n path: paths[slot] ?? '(unknown)',\n error: { code: ErrorCode.UNKNOWN, message: error.message },\n };\n }\n\n // Emit in the caller's input order so `results[i]` lines up with `paths[i]`\n // the way read/stat guarantee.\n const results: DeletePerPathResult[] = paths.map((requested, i) => {\n const entry = out[i];\n return (\n entry ?? {\n path: requested,\n error: { code: ErrorCode.UNKNOWN, message: 'Unknown delete failure' },\n }\n );\n });\n\n return { results, summary: summarize(results) };\n}\n\nexport const DELETE = defineTool<typeof DeleteInputSchema, DeleteOutput>({\n name: 'delete',\n title: 'Delete File',\n description:\n 'Permanently delete files, directories, or symlinks, like rm or rm -r. Paths are exact; globs are not expanded.',\n input: DeleteInputSchema,\n readOnlyHint: false,\n progress: (args) => ({\n label: 'Delete',\n subject:\n args.paths.length === 1\n ? basename(args.paths[0] ?? '')\n : `${String(args.paths.length)} paths`,\n }),\n accessPaths: (args) => [...args.paths],\n run: async (args, ctx) => {\n const structured = await handleDelete(args, ctx);\n // input_required is a return value, not a completed call: surface it\n // verbatim so the executor short-circuits before building a CallToolResult.\n if (isInputRequiredResult(structured)) return structured;\n // Name every path and its outcome. The old text said \"deleted 2 paths\"\n // without saying which two, so a partial failure was unreadable without\n // parsing the structured half.\n const { failed, total } = structured.summary;\n const isError = isTotalFailure(structured.summary);\n // A lone failure carries its reason in the text. \"delete: . FAILED (0/1 ok)\"\n // made the model re-read structuredContent to learn it was ACCESS_DENIED;\n // with one path there is no ambiguity about which message applies.\n if (total === 1 && failed === 1) {\n const only = structured.results[0];\n return {\n structured,\n text: `delete: ${only?.path ?? ''} FAILED — ${only && 'error' in only ? only.error.message : 'unknown error'}`,\n isError,\n };\n }\n const tokens = structured.results.map((r) => {\n const label = pathLabel(r.path);\n if ('error' in r) return `${label} FAILED`;\n return r.value.deleted ? label : `${label} SKIPPED`;\n });\n const ratio = failed > 0 ? ` (${String(total - failed)}/${String(total)} ok)` : '';\n return { structured, text: `delete: ${joinRoster(tokens)}${ratio}`, isError };\n },\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"find-files.d.ts","sourceRoot":"","sources":["../../src/tools/find-files.ts"],"names":[],"mappings":"AAiEA,eAAO,MAAM,UAAU,mCAsFrB,CAAC"}
1
+ {"version":3,"file":"find-files.d.ts","sourceRoot":"","sources":["../../src/tools/find-files.ts"],"names":[],"mappings":"AAiEA,eAAO,MAAM,UAAU,mCAgFrB,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import * as z from 'zod/v4';
2
- import { paginate } from "../core/cursor.js";
2
+ import { pageQueryKey, paginate } from "../core/cursor.js";
3
3
  import { formatCount, pageTrailer, truncateProgressPattern } from "../core/fmt.js";
4
- import { toPosixRelative } from "../core/path.js";
4
+ import { toPosixRelative } from "../core/path-utils.js";
5
5
  import { CursorSchema, IncludeHidden, IncludeIgnored, MaxDepth, OptionalPath, SafeGlobPattern, } from "../core/schema.js";
6
6
  import { searchFiles } from "../core/search.js";
7
7
  import { putJsonResource } from "../core/store.js";
@@ -46,18 +46,12 @@ export const FIND_FILES = defineTool({
46
46
  accessPaths: (args) => (args.path ? [args.path] : []),
47
47
  run: async (args, ctx) => {
48
48
  const requestedBasePath = ctx.fs.pathGuard.resolvePathOrRoot(args.path);
49
- const queryKey = JSON.stringify({
50
- method: 'find_files',
51
- path: requestedBasePath,
52
- pattern: args.pattern,
53
- includeIgnored: args.includeIgnored,
54
- includeHidden: args.includeHidden,
55
- sortBy: args.sortBy,
56
- maxDepth: args.maxDepth,
57
- });
58
49
  const paged = await paginate({
59
50
  store: ctx.pageStore,
60
- queryKey,
51
+ queryKey: pageQueryKey('find_files', { ...args, path: requestedBasePath }, [
52
+ 'cursor',
53
+ 'maxResults',
54
+ ]),
61
55
  cursor: args.cursor,
62
56
  pageSize: args.maxResults,
63
57
  produce: async () => {
@@ -1 +1 @@
1
- {"version":3,"file":"find-files.js","sourceRoot":"","sources":["../../src/tools/find-files.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AACnF,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EACL,YAAY,EACZ,aAAa,EACb,cAAc,EACd,QAAQ,EACR,YAAY,EACZ,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EACL,sBAAsB,EACtB,yBAAyB,EACzB,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,8EAA8E;AAE9E,MAAM,sBAAsB,GAAG,CAAC,CAAC,YAAY,CAAC;IAC5C,IAAI,EAAE,YAAY,CAAC,QAAQ,CAAC,8DAA8D,CAAC;IAC3F,OAAO,EAAE,eAAe,CAAC,QAAQ,CAAC,8DAA8D,CAAC;IACjG,UAAU,EAAE,CAAC;SACV,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,kBAAkB,CAAC;SACvB,QAAQ,EAAE;SACV,OAAO,CAAC,sBAAsB,CAAC;SAC/B,QAAQ,CAAC,qDAAqD,CAAC;IAClE,cAAc,EAAE,cAAc;IAC9B,aAAa,EAAE,aAAa;IAC5B,MAAM,EAAE,CAAC;SACN,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;SACtB,QAAQ,EAAE;SACV,OAAO,CAAC,MAAM,CAAC;SACf,QAAQ,CAAC,8DAA8D,CAAC;IAC3E,QAAQ,EAAE,QAAQ;IAClB,MAAM,EAAE,YAAY;CACrB,CAAC,CAAC;AAqBH,MAAM,CAAC,MAAM,UAAU,GAAG,UAAU,CAAmD;IACrF,IAAI,EAAE,YAAY;IAClB,KAAK,EAAE,YAAY;IACnB,WAAW,EACT,6FAA6F;QAC7F,qFAAqF;IACvF,KAAK,EAAE,sBAAsB;IAC7B,YAAY,EAAE,IAAI;IAClB,SAAS,EAAE,yBAAyB;IACpC,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACnB,KAAK,EAAE,MAAM;QACb,OAAO,EAAE,uBAAuB,CAAC,IAAI,CAAC,OAAO,CAAC;KAC/C,CAAC;IACF,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;QAChC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,YAAY,IAAI,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC;KAClE,CAAC;IACF,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACrD,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;QACvB,MAAM,iBAAiB,GAAG,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxE,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC;YAC9B,MAAM,EAAE,YAAY;YACpB,IAAI,EAAE,iBAAiB;YACvB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAgE;YAC1F,KAAK,EAAE,GAAG,CAAC,SAAS;YACpB,QAAQ;YACR,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,QAAQ,EAAE,IAAI,CAAC,UAAU;YACzB,OAAO,EAAE,KAAK,IAAI,EAAE;gBAClB,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,yBAAyB,CAAC,iBAAiB,CAAC,CAAC;gBACrF,MAAM,aAAa,GAAsC;oBACvD,UAAU,EAAE,kBAAkB;oBAC9B,aAAa,EAAE,IAAI,CAAC,aAAa;oBACjC,MAAM,EAAE,IAAI,CAAC,MAAM;oBACnB,WAAW,EAAE,CAAC,IAAI,CAAC,cAAc;oBACjC,GAAG,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACnE,MAAM,EAAE,GAAG,CAAC,MAAM;iBACnB,CAAC;gBACF,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC;gBAC1F,OAAO;oBACL,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;oBACtF,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,GAAG,MAAM,CAAC,OAAO,EAAE;oBACtD,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,SAAS;iBACpC,CAAC;YACJ,CAAC;YACD,WAAW,EAAE,CAAC,OAAO,EAAE,EAAE,CACvB,eAAe,CAAC,GAAG,CAAC,aAAa,EAAE,GAAG,IAAI,CAAC,OAAO,QAAQ,EAAE,OAAO,CAAC;SACvE,CAAC,CAAC;QAEH,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;QACnC,MAAM,UAAU,GAAsB;YACpC,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,OAAO,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC;YACxB,YAAY,EAAE,QAAQ,CAAC,OAAO;YAC9B,YAAY,EAAE,QAAQ,CAAC,YAAY;YACnC,GAAG,CAAC,QAAQ,CAAC,mBAAmB;gBAC9B,CAAC,CAAC,EAAE,mBAAmB,EAAE,QAAQ,CAAC,mBAAmB,EAAE;gBACvD,CAAC,CAAC,EAAE,CAAC;YACP,GAAG,CAAC,QAAQ,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1F,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpE,GAAG,CAAC,KAAK,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC5E,CAAC;QACF,MAAM,IAAI,GACR,UAAU,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;YAC3B,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;YAClD,CAAC,CAAC,sBAAsB,IAAI,CAAC,OAAO,GAAG,CAAC;QAC5C,MAAM,IAAI,GACR,IAAI;YACJ,WAAW,CAAC;gBACV,MAAM;gBACN,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC,MAAM;gBAChC,KAAK,EAAE,QAAQ,CAAC,OAAO;gBACvB,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,YAAY;gBAClB,UAAU,EAAE,UAAU,CAAC,UAAU;gBACjC,QAAQ,EAAE,IAAI;gBACd,aAAa,EAAE,UAAU,CAAC,aAAa;gBACvC,mBAAmB,EAAE,UAAU,CAAC,mBAAmB;aACpD,CAAC,CAAC;QACL,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IACtF,CAAC;CACF,CAAC,CAAC","sourcesContent":["import * as z from 'zod/v4';\n\nimport { paginate } from '../core/cursor.ts';\nimport { formatCount, pageTrailer, truncateProgressPattern } from '../core/fmt.ts';\nimport { toPosixRelative } from '../core/path.ts';\nimport {\n CursorSchema,\n IncludeHidden,\n IncludeIgnored,\n MaxDepth,\n OptionalPath,\n SafeGlobPattern,\n} from '../core/schema.ts';\nimport { searchFiles } from '../core/search.ts';\nimport type { JsonResourceResult } from '../core/store.ts';\nimport { putJsonResource } from '../core/store.ts';\nimport {\n DEFAULT_SEARCH_RESULTS,\n DEFAULT_SEARCH_TIMEOUT_MS,\n MAX_SEARCH_RESULTS,\n} from '../core/util.ts';\nimport { defineTool } from './define.ts';\n\n// ---------------------------------------------------------------------------\n\nconst SearchFilesInputSchema = z.strictObject({\n path: OptionalPath.describe('Base directory to search under (default: first allowed root)'),\n pattern: SafeGlobPattern.describe('Glob pattern to match file paths (e.g. **/*.ts, src/**/*.js)'),\n maxResults: z\n .uint32()\n .min(1)\n .max(MAX_SEARCH_RESULTS)\n .optional()\n .default(DEFAULT_SEARCH_RESULTS)\n .describe('Maximum number of matching files to return per page'),\n includeIgnored: IncludeIgnored,\n includeHidden: IncludeHidden,\n sortBy: z\n .enum(['name', 'path'])\n .optional()\n .default('path')\n .describe('Sort order: path = full path (default), name = basename only'),\n maxDepth: MaxDepth,\n cursor: CursorSchema,\n});\n\ninterface SearchFileResult {\n path: string;\n}\ninterface SearchFilesOutput {\n root: string;\n results: SearchFileResult[];\n totalMatches?: number;\n filesScanned?: number;\n skippedInaccessible?: number;\n stoppedReason?: 'maxResults' | 'timeout';\n resourceUri?: string;\n nextCursor?: string;\n}\n\n/** The engine's own summary plus its root is the page metadata; nothing is copied out of it. */\ntype SearchFilesPageMetadata = Awaited<ReturnType<typeof searchFiles>>['summary'] & {\n readonly root: string;\n};\n\nexport const FIND_FILES = defineTool<typeof SearchFilesInputSchema, SearchFilesOutput>({\n name: 'find_files',\n title: 'Find Files',\n description:\n 'Find files by name or glob pattern; returns file paths relative to the searched directory. ' +\n 'A pattern without / matches file names at any depth. search_text searches contents.',\n input: SearchFilesInputSchema,\n readOnlyHint: true,\n timeoutMs: DEFAULT_SEARCH_TIMEOUT_MS,\n progress: (args) => ({\n label: 'Find',\n subject: truncateProgressPattern(args.pattern),\n }),\n progressDone: (_args, result) => ({\n detail: formatCount(result.totalMatches ?? 0, 'match', 'matches'),\n }),\n accessPaths: (args) => (args.path ? [args.path] : []),\n run: async (args, ctx) => {\n const requestedBasePath = ctx.fs.pathGuard.resolvePathOrRoot(args.path);\n const queryKey = JSON.stringify({\n method: 'find_files',\n path: requestedBasePath,\n pattern: args.pattern,\n includeIgnored: args.includeIgnored,\n includeHidden: args.includeHidden,\n sortBy: args.sortBy,\n maxDepth: args.maxDepth,\n });\n const paged = await paginate<SearchFileResult, SearchFilesPageMetadata, JsonResourceResult>({\n store: ctx.pageStore,\n queryKey,\n cursor: args.cursor,\n pageSize: args.maxResults,\n produce: async () => {\n const basePath = await ctx.fs.pathGuard.validateExistingDirectory(requestedBasePath);\n const searchOptions: Parameters<typeof searchFiles>[2] = {\n maxResults: MAX_SEARCH_RESULTS,\n includeHidden: args.includeHidden,\n sortBy: args.sortBy,\n skipIgnored: !args.includeIgnored,\n ...(args.maxDepth !== undefined ? { maxDepth: args.maxDepth } : {}),\n signal: ctx.signal,\n };\n const result = await searchFiles(basePath, args.pattern, searchOptions, ctx.fs.pathGuard);\n return {\n items: result.results.map((r) => ({ path: toPosixRelative(result.basePath, r.path) })),\n metadata: { root: result.basePath, ...result.summary },\n truncated: result.summary.truncated,\n };\n },\n externalize: (results) =>\n putJsonResource(ctx.resourceStore, `${args.pattern} files`, results),\n });\n\n const { metadata, offset } = paged;\n const structured: SearchFilesOutput = {\n root: metadata.root,\n results: [...paged.page],\n totalMatches: metadata.matched,\n filesScanned: metadata.filesScanned,\n ...(metadata.skippedInaccessible\n ? { skippedInaccessible: metadata.skippedInaccessible }\n : {}),\n ...(metadata.stoppedReason !== undefined ? { stoppedReason: metadata.stoppedReason } : {}),\n ...(paged.resource ? { resourceUri: paged.resource.entry.uri } : {}),\n ...(paged.nextCursor !== undefined ? { nextCursor: paged.nextCursor } : {}),\n };\n const body =\n structured.results.length > 0\n ? structured.results.map((r) => r.path).join('\\n')\n : `No files matching '${args.pattern}'`;\n const text =\n body +\n pageTrailer({\n offset,\n shown: structured.results.length,\n total: metadata.matched,\n noun: 'files',\n tool: 'find_files',\n nextCursor: structured.nextCursor,\n nextArgs: args,\n stoppedReason: structured.stoppedReason,\n skippedInaccessible: structured.skippedInaccessible,\n });\n return { structured, text, resources: paged.resource ? [paged.resource.link] : [] };\n },\n});\n"]}
1
+ {"version":3,"file":"find-files.js","sourceRoot":"","sources":["../../src/tools/find-files.ts"],"names":[],"mappings":"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","sourcesContent":["import * as z from 'zod/v4';\n\nimport { pageQueryKey, paginate } from '../core/cursor.ts';\nimport { formatCount, pageTrailer, truncateProgressPattern } from '../core/fmt.ts';\nimport { toPosixRelative } from '../core/path-utils.ts';\nimport {\n CursorSchema,\n IncludeHidden,\n IncludeIgnored,\n MaxDepth,\n OptionalPath,\n SafeGlobPattern,\n} from '../core/schema.ts';\nimport { searchFiles } from '../core/search.ts';\nimport type { JsonResourceResult } from '../core/store.ts';\nimport { putJsonResource } from '../core/store.ts';\nimport {\n DEFAULT_SEARCH_RESULTS,\n DEFAULT_SEARCH_TIMEOUT_MS,\n MAX_SEARCH_RESULTS,\n} from '../core/util.ts';\nimport { defineTool } from './define.ts';\n\n// ---------------------------------------------------------------------------\n\nconst SearchFilesInputSchema = z.strictObject({\n path: OptionalPath.describe('Base directory to search under (default: first allowed root)'),\n pattern: SafeGlobPattern.describe('Glob pattern to match file paths (e.g. **/*.ts, src/**/*.js)'),\n maxResults: z\n .uint32()\n .min(1)\n .max(MAX_SEARCH_RESULTS)\n .optional()\n .default(DEFAULT_SEARCH_RESULTS)\n .describe('Maximum number of matching files to return per page'),\n includeIgnored: IncludeIgnored,\n includeHidden: IncludeHidden,\n sortBy: z\n .enum(['name', 'path'])\n .optional()\n .default('path')\n .describe('Sort order: path = full path (default), name = basename only'),\n maxDepth: MaxDepth,\n cursor: CursorSchema,\n});\n\ninterface SearchFileResult {\n path: string;\n}\ninterface SearchFilesOutput {\n root: string;\n results: SearchFileResult[];\n totalMatches?: number;\n filesScanned?: number;\n skippedInaccessible?: number;\n stoppedReason?: 'maxResults' | 'timeout';\n resourceUri?: string;\n nextCursor?: string;\n}\n\n/** The engine's own summary plus its root is the page metadata; nothing is copied out of it. */\ntype SearchFilesPageMetadata = Awaited<ReturnType<typeof searchFiles>>['summary'] & {\n readonly root: string;\n};\n\nexport const FIND_FILES = defineTool<typeof SearchFilesInputSchema, SearchFilesOutput>({\n name: 'find_files',\n title: 'Find Files',\n description:\n 'Find files by name or glob pattern; returns file paths relative to the searched directory. ' +\n 'A pattern without / matches file names at any depth. search_text searches contents.',\n input: SearchFilesInputSchema,\n readOnlyHint: true,\n timeoutMs: DEFAULT_SEARCH_TIMEOUT_MS,\n progress: (args) => ({\n label: 'Find',\n subject: truncateProgressPattern(args.pattern),\n }),\n progressDone: (_args, result) => ({\n detail: formatCount(result.totalMatches ?? 0, 'match', 'matches'),\n }),\n accessPaths: (args) => (args.path ? [args.path] : []),\n run: async (args, ctx) => {\n const requestedBasePath = ctx.fs.pathGuard.resolvePathOrRoot(args.path);\n const paged = await paginate<SearchFileResult, SearchFilesPageMetadata, JsonResourceResult>({\n store: ctx.pageStore,\n queryKey: pageQueryKey('find_files', { ...args, path: requestedBasePath }, [\n 'cursor',\n 'maxResults',\n ]),\n cursor: args.cursor,\n pageSize: args.maxResults,\n produce: async () => {\n const basePath = await ctx.fs.pathGuard.validateExistingDirectory(requestedBasePath);\n const searchOptions: Parameters<typeof searchFiles>[2] = {\n maxResults: MAX_SEARCH_RESULTS,\n includeHidden: args.includeHidden,\n sortBy: args.sortBy,\n skipIgnored: !args.includeIgnored,\n ...(args.maxDepth !== undefined ? { maxDepth: args.maxDepth } : {}),\n signal: ctx.signal,\n };\n const result = await searchFiles(basePath, args.pattern, searchOptions, ctx.fs.pathGuard);\n return {\n items: result.results.map((r) => ({ path: toPosixRelative(result.basePath, r.path) })),\n metadata: { root: result.basePath, ...result.summary },\n truncated: result.summary.truncated,\n };\n },\n externalize: (results) =>\n putJsonResource(ctx.resourceStore, `${args.pattern} files`, results),\n });\n\n const { metadata, offset } = paged;\n const structured: SearchFilesOutput = {\n root: metadata.root,\n results: [...paged.page],\n totalMatches: metadata.matched,\n filesScanned: metadata.filesScanned,\n ...(metadata.skippedInaccessible\n ? { skippedInaccessible: metadata.skippedInaccessible }\n : {}),\n ...(metadata.stoppedReason !== undefined ? { stoppedReason: metadata.stoppedReason } : {}),\n ...(paged.resource ? { resourceUri: paged.resource.entry.uri } : {}),\n ...(paged.nextCursor !== undefined ? { nextCursor: paged.nextCursor } : {}),\n };\n const body =\n structured.results.length > 0\n ? structured.results.map((r) => r.path).join('\\n')\n : `No files matching '${args.pattern}'`;\n const text =\n body +\n pageTrailer({\n offset,\n shown: structured.results.length,\n total: metadata.matched,\n noun: 'files',\n tool: 'find_files',\n nextCursor: structured.nextCursor,\n nextArgs: args,\n stoppedReason: structured.stoppedReason,\n skippedInaccessible: structured.skippedInaccessible,\n });\n return { structured, text, resources: paged.resource ? [paged.resource.link] : [] };\n },\n});\n"]}
@@ -11,7 +11,7 @@ export declare const MUTATING_TOOL_NAMES: Set<string>;
11
11
  export declare function registeredTools(readOnly: boolean): readonly DefinedTool[];
12
12
  export { LIST, LIST_ROOTS, READ, SEARCH_TEXT, FIND_FILES, STAT };
13
13
  interface ToolRegistrarDeps extends ToolDeps {
14
- readonly readOnly?: boolean;
14
+ readonly readOnly: boolean;
15
15
  }
16
16
  export declare function registerTools(deps: ToolRegistrarDeps): void;
17
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAIzD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,eAAO,MAAM,SAAS,oLAcZ,CAAC;AAEX,eAAO,MAAM,mBAAmB,aAE/B,CAAC;AAEF,8FAA8F;AAC9F,wBAAgB,eAAe,CAAC,QAAQ,EAAE,OAAO,GAAG,SAAS,WAAW,EAAE,CAEzE;AAOD,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;AAEjE,UAAU,iBAAkB,SAAQ,QAAQ;IAC1C,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAI3D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAIzD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,eAAO,MAAM,SAAS,oLAcZ,CAAC;AAEX,eAAO,MAAM,mBAAmB,aAE/B,CAAC;AAEF,8FAA8F;AAC9F,wBAAgB,eAAe,CAAC,QAAQ,EAAE,OAAO,GAAG,SAAS,WAAW,EAAE,CAEzE;AAOD,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;AAEjE,UAAU,iBAAkB,SAAQ,QAAQ;IAC1C,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAI3D"}
@@ -38,7 +38,7 @@ export function registeredTools(readOnly) {
38
38
  // MUTATING_TOOL_NAMES and ALL_TOOLS instead.
39
39
  export { LIST, LIST_ROOTS, READ, SEARCH_TEXT, FIND_FILES, STAT };
40
40
  export function registerTools(deps) {
41
- for (const tool of registeredTools(deps.readOnly ?? false)) {
41
+ for (const tool of registeredTools(deps.readOnly)) {
42
42
  tool.register(deps);
43
43
  }
44
44
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,MAAM;IACN,MAAM;IACN,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,KAAK;IACL,IAAI;IACJ,YAAY;IACZ,UAAU;IACV,WAAW;IACX,UAAU;IACV,IAAI;CACI,CAAC;AAEX,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,GAAG,CACxC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAC5D,CAAC;AAEF,8FAA8F;AAC9F,MAAM,UAAU,eAAe,CAAC,QAAiB;IAC/C,OAAO,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC1F,CAAC;AAED,gFAAgF;AAChF,6EAA6E;AAC7E,2EAA2E;AAC3E,uEAAuE;AACvE,6CAA6C;AAC7C,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;AAMjE,MAAM,UAAU,aAAa,CAAC,IAAuB;IACnD,KAAK,MAAM,IAAI,IAAI,eAAe,CAAC,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,EAAE,CAAC;QAC3D,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;AACH,CAAC","sourcesContent":["import { CREATE } from './create.ts';\nimport type { DefinedTool, ToolDeps } from './define.ts';\nimport { DELETE } from './delete.ts';\nimport { DIFF } from './diff.ts';\nimport { EDIT } from './edit.ts';\nimport { FIND_FILES } from './find-files.ts';\nimport { LIST_ROOTS } from './list-roots.ts';\nimport { LIST } from './list.ts';\nimport { MOVE } from './move.ts';\nimport { PATCH } from './patch.ts';\nimport { READ } from './read.ts';\nimport { REPLACE_TEXT } from './replace-text.ts';\nimport { SEARCH_TEXT } from './search-text.ts';\nimport { STAT } from './stat.ts';\n\nexport const ALL_TOOLS = [\n CREATE,\n DELETE,\n DIFF,\n EDIT,\n LIST,\n MOVE,\n PATCH,\n READ,\n REPLACE_TEXT,\n LIST_ROOTS,\n SEARCH_TEXT,\n FIND_FILES,\n STAT,\n] as const;\n\nexport const MUTATING_TOOL_NAMES = new Set(\n ALL_TOOLS.filter((t) => !t.readOnlyHint).map((t) => t.name),\n);\n\n/** The tools a server registers at this setting — the one owner of the `--read-only` gate. */\nexport function registeredTools(readOnly: boolean): readonly DefinedTool[] {\n return readOnly ? ALL_TOOLS.filter((t) => !MUTATING_TOOL_NAMES.has(t.name)) : ALL_TOOLS;\n}\n\n// Re-exported so documentation surfaces quote `.name` off the definition rather\n// than repeating the string. This module is the only owner of the inventory.\n// Only the read-only tools are named individually: the mutating six are no\n// longer listed by hand anywhere, so their names reach callers through\n// MUTATING_TOOL_NAMES and ALL_TOOLS instead.\nexport { LIST, LIST_ROOTS, READ, SEARCH_TEXT, FIND_FILES, STAT };\n\ninterface ToolRegistrarDeps extends ToolDeps {\n readonly readOnly?: boolean;\n}\n\nexport function registerTools(deps: ToolRegistrarDeps): void {\n for (const tool of registeredTools(deps.readOnly ?? false)) {\n tool.register(deps);\n }\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,MAAM;IACN,MAAM;IACN,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,KAAK;IACL,IAAI;IACJ,YAAY;IACZ,UAAU;IACV,WAAW;IACX,UAAU;IACV,IAAI;CACI,CAAC;AAEX,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,GAAG,CACxC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAC5D,CAAC;AAEF,8FAA8F;AAC9F,MAAM,UAAU,eAAe,CAAC,QAAiB;IAC/C,OAAO,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC1F,CAAC;AAED,gFAAgF;AAChF,6EAA6E;AAC7E,2EAA2E;AAC3E,uEAAuE;AACvE,6CAA6C;AAC7C,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;AAMjE,MAAM,UAAU,aAAa,CAAC,IAAuB;IACnD,KAAK,MAAM,IAAI,IAAI,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;AACH,CAAC","sourcesContent":["import { CREATE } from './create.ts';\nimport type { DefinedTool, ToolDeps } from './define.ts';\nimport { DELETE } from './delete.ts';\nimport { DIFF } from './diff.ts';\nimport { EDIT } from './edit.ts';\nimport { FIND_FILES } from './find-files.ts';\nimport { LIST_ROOTS } from './list-roots.ts';\nimport { LIST } from './list.ts';\nimport { MOVE } from './move.ts';\nimport { PATCH } from './patch.ts';\nimport { READ } from './read.ts';\nimport { REPLACE_TEXT } from './replace-text.ts';\nimport { SEARCH_TEXT } from './search-text.ts';\nimport { STAT } from './stat.ts';\n\nexport const ALL_TOOLS = [\n CREATE,\n DELETE,\n DIFF,\n EDIT,\n LIST,\n MOVE,\n PATCH,\n READ,\n REPLACE_TEXT,\n LIST_ROOTS,\n SEARCH_TEXT,\n FIND_FILES,\n STAT,\n] as const;\n\nexport const MUTATING_TOOL_NAMES = new Set(\n ALL_TOOLS.filter((t) => !t.readOnlyHint).map((t) => t.name),\n);\n\n/** The tools a server registers at this setting — the one owner of the `--read-only` gate. */\nexport function registeredTools(readOnly: boolean): readonly DefinedTool[] {\n return readOnly ? ALL_TOOLS.filter((t) => !MUTATING_TOOL_NAMES.has(t.name)) : ALL_TOOLS;\n}\n\n// Re-exported so documentation surfaces quote `.name` off the definition rather\n// than repeating the string. This module is the only owner of the inventory.\n// Only the read-only tools are named individually: the mutating six are no\n// longer listed by hand anywhere, so their names reach callers through\n// MUTATING_TOOL_NAMES and ALL_TOOLS instead.\nexport { LIST, LIST_ROOTS, READ, SEARCH_TEXT, FIND_FILES, STAT };\n\ninterface ToolRegistrarDeps extends ToolDeps {\n readonly readOnly: boolean;\n}\n\nexport function registerTools(deps: ToolRegistrarDeps): void {\n for (const tool of registeredTools(deps.readOnly)) {\n tool.register(deps);\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/tools/list.ts"],"names":[],"mappings":"AAiOA,eAAO,MAAM,IAAI,mCA8Ff,CAAC"}
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/tools/list.ts"],"names":[],"mappings":"AAuPA,eAAO,MAAM,IAAI,mCAuFf,CAAC"}