@j0hanz/filesystem-mcp 2.4.1 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -23
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +3 -10
- package/dist/cli.js.map +1 -1
- package/dist/core/concurrency.d.ts +1 -1
- package/dist/core/concurrency.d.ts.map +1 -1
- package/dist/core/concurrency.js +1 -1
- package/dist/core/concurrency.js.map +1 -1
- package/dist/core/cursor.d.ts.map +1 -1
- package/dist/core/cursor.js +2 -5
- package/dist/core/cursor.js.map +1 -1
- package/dist/core/errors.d.ts +1 -4
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +14 -20
- package/dist/core/errors.js.map +1 -1
- package/dist/core/file-uri.d.ts.map +1 -1
- package/dist/core/file-uri.js +3 -8
- package/dist/core/file-uri.js.map +1 -1
- package/dist/core/fmt.d.ts +13 -7
- package/dist/core/fmt.d.ts.map +1 -1
- package/dist/core/fmt.js +22 -10
- package/dist/core/fmt.js.map +1 -1
- package/dist/core/fs.d.ts +5 -18
- package/dist/core/fs.d.ts.map +1 -1
- package/dist/core/fs.js +1 -6
- package/dist/core/fs.js.map +1 -1
- package/dist/core/glob.d.ts +1 -2
- package/dist/core/glob.d.ts.map +1 -1
- package/dist/core/glob.js +1 -7
- package/dist/core/glob.js.map +1 -1
- package/dist/core/input-required.d.ts +0 -8
- package/dist/core/input-required.d.ts.map +1 -1
- package/dist/core/input-required.js +5 -15
- package/dist/core/input-required.js.map +1 -1
- package/dist/core/path-completer.d.ts.map +1 -1
- package/dist/core/path-completer.js +0 -2
- package/dist/core/path-completer.js.map +1 -1
- package/dist/core/path.d.ts.map +1 -1
- package/dist/core/path.js +1 -8
- package/dist/core/path.js.map +1 -1
- package/dist/core/read.d.ts.map +1 -1
- package/dist/core/read.js +13 -35
- package/dist/core/read.js.map +1 -1
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/schema.js +1 -1
- package/dist/core/schema.js.map +1 -1
- package/dist/core/search.d.ts +3 -4
- package/dist/core/search.d.ts.map +1 -1
- package/dist/core/search.js +4 -0
- package/dist/core/search.js.map +1 -1
- package/dist/core/store.d.ts.map +1 -1
- package/dist/core/store.js +0 -3
- package/dist/core/store.js.map +1 -1
- package/dist/index.js +3 -5
- package/dist/index.js.map +1 -1
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +1 -4
- package/dist/prompts.js.map +1 -1
- package/dist/resources.d.ts.map +1 -1
- package/dist/resources.js +23 -18
- package/dist/resources.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +4 -3
- package/dist/server.js.map +1 -1
- package/dist/tools/batch.d.ts.map +1 -1
- package/dist/tools/batch.js +1 -2
- package/dist/tools/batch.js.map +1 -1
- package/dist/tools/create.d.ts.map +1 -1
- package/dist/tools/create.js +2 -6
- package/dist/tools/create.js.map +1 -1
- package/dist/tools/define.d.ts +6 -4
- package/dist/tools/define.d.ts.map +1 -1
- package/dist/tools/define.js +1 -1
- package/dist/tools/define.js.map +1 -1
- package/dist/tools/delete.d.ts.map +1 -1
- package/dist/tools/delete.js +1 -7
- package/dist/tools/delete.js.map +1 -1
- package/dist/tools/diff.d.ts.map +1 -1
- package/dist/tools/diff.js +17 -21
- package/dist/tools/diff.js.map +1 -1
- package/dist/tools/edit.d.ts.map +1 -1
- package/dist/tools/edit.js +22 -16
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/find-files.d.ts.map +1 -1
- package/dist/tools/find-files.js +3 -5
- package/dist/tools/find-files.js.map +1 -1
- package/dist/tools/list-roots.d.ts.map +1 -1
- package/dist/tools/list-roots.js +4 -6
- package/dist/tools/list-roots.js.map +1 -1
- package/dist/tools/list.d.ts.map +1 -1
- package/dist/tools/list.js +18 -8
- package/dist/tools/list.js.map +1 -1
- package/dist/tools/move.d.ts.map +1 -1
- package/dist/tools/move.js +2 -14
- package/dist/tools/move.js.map +1 -1
- package/dist/tools/patch.d.ts.map +1 -1
- package/dist/tools/patch.js +83 -76
- package/dist/tools/patch.js.map +1 -1
- package/dist/tools/read.d.ts.map +1 -1
- package/dist/tools/read.js +2 -6
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/replace-text.d.ts.map +1 -1
- package/dist/tools/replace-text.js +51 -17
- package/dist/tools/replace-text.js.map +1 -1
- package/dist/tools/search-text.d.ts.map +1 -1
- package/dist/tools/search-text.js +23 -22
- package/dist/tools/search-text.js.map +1 -1
- package/dist/tools/stat.d.ts.map +1 -1
- package/dist/tools/stat.js +3 -5
- package/dist/tools/stat.js.map +1 -1
- package/dist/transport/http-policy.d.ts +15 -10
- package/dist/transport/http-policy.d.ts.map +1 -1
- package/dist/transport/http-policy.js +21 -28
- package/dist/transport/http-policy.js.map +1 -1
- package/dist/transport/http.d.ts.map +1 -1
- package/dist/transport/http.js +4 -4
- package/dist/transport/http.js.map +1 -1
- package/dist/transport/shared.d.ts +13 -12
- package/dist/transport/shared.d.ts.map +1 -1
- package/dist/transport/shared.js +21 -25
- package/dist/transport/shared.js.map +1 -1
- package/dist/transport/stdio.d.ts.map +1 -1
- package/dist/transport/stdio.js +5 -8
- package/dist/transport/stdio.js.map +1 -1
- package/package.json +1 -2
package/dist/tools/define.d.ts
CHANGED
|
@@ -72,11 +72,13 @@ interface RunResult<T> {
|
|
|
72
72
|
readonly isError?: boolean;
|
|
73
73
|
}
|
|
74
74
|
/**
|
|
75
|
-
* `ToolAnnotations` with `readOnlyHint` required
|
|
76
|
-
*
|
|
77
|
-
* forgets it must be a compile error
|
|
75
|
+
* `ToolAnnotations` with `readOnlyHint` required and `idempotentHint` removed.
|
|
76
|
+
* `readOnlyHint` is optional in the SDK, but MUTATING_TOOL_NAMES derives the
|
|
77
|
+
* `--read-only` gate from it, so a tool that forgets it must be a compile error
|
|
78
|
+
* rather than a silent reclassification. `idempotentHint` is omitted because
|
|
79
|
+
* nothing reads it: `publishedAnnotations` derives the wire set below.
|
|
78
80
|
*/
|
|
79
|
-
type DeclaredAnnotations = ToolAnnotations & {
|
|
81
|
+
type DeclaredAnnotations = Omit<ToolAnnotations, 'idempotentHint'> & {
|
|
80
82
|
readonly readOnlyHint: boolean;
|
|
81
83
|
};
|
|
82
84
|
export interface ToolDef<I extends z.ZodType, O extends z.ZodType> {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define.d.ts","sourceRoot":"","sources":["../../src/tools/define.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,kBAAkB,EAClB,YAAY,EACZ,mBAAmB,EACnB,SAAS,EACT,YAAY,EACZ,cAAc,EACd,SAAS,EACT,WAAW,EACX,oBAAoB,EACpB,aAAa,EAEb,eAAe,EAChB,MAAM,8BAA8B,CAAC;AAOtC,OAAO,KAAK,KAAK,CAAC,MAAM,QAAQ,CAAC;AAEjC,OAAO,EAAE,SAAS,EAAsC,MAAM,mBAAmB,CAAC;AAClF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAQlD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGzE,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IACzC,wFAAwF;IACxF,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,sFAAsF;IACtF,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,EAAE,EAAE,iBAAiB,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAC;IACtC,QAAQ,CAAC,aAAa,EAAE,aAAa,GAAG,SAAS,CAAC;IAClD,0EAA0E;IAC1E,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7E,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,YAAY,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1E,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC5E;;;;;OAKG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IAC9D;;;;;OAKG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;IACzD;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;IAC7D,iGAAiG;IACjG,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;CACnC;AAED,UAAU,QAAQ;IAChB,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAC;IACtC,QAAQ,CAAC,aAAa,EAAE,aAAa,GAAG,SAAS,CAAC;IAClD,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;CACpC;AAED,UAAU,SAAS,CAAC,CAAC;IACnB,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,CAAC,EAAE,YAAY,EAAE,CAAC;IACpC;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED
|
|
1
|
+
{"version":3,"file":"define.d.ts","sourceRoot":"","sources":["../../src/tools/define.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/define.js
CHANGED
|
@@ -134,7 +134,7 @@ class ToolExecutor {
|
|
|
134
134
|
const errMsg = formatUnknownErrorMessage(error);
|
|
135
135
|
this.#progressSession.fail(plainMessage('fail', { ...this.#progressCtx, error: errMsg }));
|
|
136
136
|
await this.#progressSession.flush();
|
|
137
|
-
const
|
|
137
|
+
const errorText = Problem.toText(error, this.def.defaultErrorCode ?? ErrorCode.UNKNOWN);
|
|
138
138
|
return {
|
|
139
139
|
content: [{ type: 'text', text: errorText }],
|
|
140
140
|
isError: true,
|
package/dist/tools/define.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define.js","sourceRoot":"","sources":["../../src/tools/define.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n CallToolResult,\n ClientCapabilities,\n ContentBlock,\n InputRequiredResult,\n McpServer,\n Notification,\n RegisteredTool,\n RequestId,\n RequestMeta,\n RequestStateAccessor,\n ServerContext,\n StandardSchemaWithJSON,\n ToolAnnotations,\n} from '@modelcontextprotocol/server';\nimport {\n CLIENT_CAPABILITIES_META_KEY,\n isInputRequiredResult,\n TRACEPARENT_META_KEY,\n} from '@modelcontextprotocol/server';\n\nimport type * as z from 'zod/v4';\n\nimport { ErrorCode, formatUnknownErrorMessage, Problem } from '../core/errors.ts';\nimport type { ProgressCtx } from '../core/fmt.ts';\nimport { plainMessage } from '../core/fmt.ts';\nimport { GuardedFileSystem } from '../core/fs.ts';\nimport {\n confirmKey,\n pendingRoundTrip,\n readAcceptedConfirm,\n readAcceptedMultiChoice,\n} from '../core/input-required.ts';\nimport { Logger, sanitizeLogField } from '../core/observability.ts';\nimport type { LoggingLevel } from '../core/observability.ts';\nimport { isSamePath } from '../core/path-utils.ts';\nimport type { PathGuard } from '../core/path.ts';\nimport type { PageSnapshotStore, ResourceStore } from '../core/store.ts';\nimport { ProgressSession } from './progress.ts';\n\nexport interface ToolCtx {\n readonly signal: AbortSignal;\n readonly _meta?: RequestMeta | undefined;\n /** The JSON-RPC id of the `tools/call` this context serves; prefixes every log line. */\n readonly requestId: RequestId;\n /** W3C trace context the client put in `_meta`, when it did; rides the log prefix. */\n readonly traceparent?: string | undefined;\n readonly fs: GuardedFileSystem;\n readonly pageStore: PageSnapshotStore;\n readonly resourceStore: ResourceStore | undefined;\n /** Emits a log line to stderr via `Logger.emit`, gated by `LOG_LEVEL`. */\n readonly log?: (level: LoggingLevel, data: unknown, logger?: string) => void;\n readonly sendNotification?: (notification: Notification) => Promise<void>;\n readonly onProgress?: (params: { current: number; total?: number }) => void;\n /**\n * Multi-round-trip `inputResponses` carried by a retried `tools/call`\n * (protocol revision 2026-07-28); `undefined` on the first round. Bare,\n * unvalidated client values — handlers read them through\n * `readAcceptedConfirm`.\n */\n readonly inputResponses?: Record<string, unknown> | undefined;\n /**\n * Reads the verified multi-round-trip `requestState` for the current round:\n * the decoded `PendingState` the `requestStateCodec` verified, or `undefined`\n * when the round carried no state (the first round). `undefined` when no\n * live request context is available.\n */\n readonly requestState?: RequestStateAccessor | undefined;\n /**\n * What the connected client declared it can do, or `undefined` when this\n * connection cannot say. Read by the `input_required` flows: an embedded\n * elicitation sent to a client that never declared `elicitation` is rejected\n * by the SDK with `-32021` before it reaches the wire, so the handlers check\n * first and answer with an actionable tool error instead.\n *\n * Two sources, because the eras differ: a legacy connection negotiated them\n * at `initialize` (`Server.getClientCapabilities()`), a modern one carries\n * them per request in the `_meta` envelope and never runs `initialize` at\n * all. `undefined` means \"cannot tell\" — never \"no capabilities\".\n */\n readonly clientCapabilities?: ClientCapabilities | undefined;\n /** The SDK request context this call runs under; `pendingRoundTrip` binds minted state to it. */\n readonly serverCtx: ServerContext;\n}\n\ninterface ToolDeps {\n readonly server: McpServer;\n readonly pathGuard: PathGuard;\n readonly pageStore: PageSnapshotStore;\n readonly resourceStore: ResourceStore | undefined;\n readonly era?: 'legacy' | 'modern';\n}\n\ninterface RunResult<T> {\n readonly structured: T;\n readonly text?: string;\n readonly resources?: ContentBlock[];\n /**\n * The call as a whole failed. Batch tools set it from `isTotalFailure` in\n * `batch.ts` — every requested item failed — so the executor never has to\n * know a tool's output shape. Absent or `false` means the call did work.\n */\n readonly isError?: boolean;\n}\n\n/**\n * `ToolAnnotations` with `readOnlyHint` required. It is optional in the SDK, but\n * MUTATING_TOOL_NAMES derives the `--read-only` gate from it, so a tool that\n * forgets it must be a compile error rather than a silent reclassification.\n */\ntype DeclaredAnnotations = ToolAnnotations & { readonly readOnlyHint: boolean };\n\nexport interface ToolDef<I extends z.ZodType, O extends z.ZodType> {\n readonly name: string;\n readonly title: string;\n readonly description: string;\n readonly input: I;\n readonly output: O;\n readonly annotations: DeclaredAnnotations;\n readonly timeoutMs?: number;\n readonly progress?: (args: z.infer<I>) => ProgressCtx;\n readonly progressDone?: (args: z.infer<I>, result: z.infer<O>) => Partial<ProgressCtx>;\n readonly defaultErrorCode?: ErrorCode;\n /**\n * The filesystem paths this tool will operate on, extracted from its parsed\n * args. The executor runs an access-grant pre-check over these BEFORE `run`\n * (R7): any path outside the granted roots yields an `input_required`\n * round-trip requesting a grant, and nothing is touched until the client\n * retries with an accepted grant (R8). Omit for tools that do not operate on\n * caller-supplied filesystem paths.\n */\n readonly accessPaths?: (args: z.infer<I>) => readonly string[];\n readonly run: (\n args: z.infer<I>,\n ctx: ToolCtx,\n ) => Promise<RunResult<z.infer<O>> | InputRequiredResult>;\n}\n\nexport interface DefinedTool {\n readonly name: string;\n readonly annotations: DeclaredAnnotations;\n\n register(deps: ToolDeps): RegisteredTool;\n}\n\nfunction toToolCtx(\n ctx: ServerContext,\n deps: Pick<ToolDeps, 'pathGuard' | 'pageStore' | 'resourceStore' | 'server' | 'era'>,\n): ToolCtx {\n // Envelope first, accessor second — the two eras carry this differently.\n // A modern request states the capabilities in its own `_meta` envelope; a\n // legacy connection fixed them at `initialize` and has no envelope at all.\n // The deprecated accessor still answers for both today (the SDK backfills it\n // per request from the validated envelope on modern instances), but reading\n // the envelope directly is the supported path, so it leads: when the accessor\n // goes, legacy degrades to \"cannot tell\", which fails open to the behavior\n // that predates this check.\n //\n // The cast is the SDK's shipped `RequestMetaEnvelope` declaration collapsing\n // to `{}` — the reserved keys survive at runtime but not in the .d.ts, so the\n // key constant cannot index the declared type.\n const envelope = ctx.mcpReq.envelope as Record<string, unknown> | undefined;\n const clientCapabilities =\n (envelope?.[CLIENT_CAPABILITIES_META_KEY] as ClientCapabilities | undefined) ??\n // eslint-disable-next-line @typescript-eslint/no-deprecated -- the only source of client capabilities on a legacy connection, where no envelope exists.\n deps.server.server.getClientCapabilities() ??\n // A legacy instance that never saw `initialize` is the HTTP leg's\n // per-request serving (`createMcpHandler` with `legacy: 'stateless'`):\n // there is no return path for a server-to-client request, so read the\n // client as having declared nothing. The `input_required` flows then\n // answer with their named workaround instead of the SDK's generic refusal.\n // sunset(SEP-2577): removal trigger in docs/adr/002-legacy-protocol-paths-sunset.md.\n (deps.era === 'legacy' ? {} : undefined);\n\n return {\n signal: ctx.mcpReq.signal,\n ...(ctx.mcpReq._meta ? { _meta: ctx.mcpReq._meta } : {}),\n requestId: ctx.mcpReq.id,\n ...(typeof ctx.mcpReq._meta?.[TRACEPARENT_META_KEY] === 'string'\n ? { traceparent: ctx.mcpReq._meta[TRACEPARENT_META_KEY] }\n : {}),\n fs: new GuardedFileSystem(deps.pathGuard),\n pageStore: deps.pageStore,\n resourceStore: deps.resourceStore,\n sendNotification: async (notification) => ctx.mcpReq.notify(notification),\n inputResponses: ctx.mcpReq.inputResponses,\n requestState: ctx.mcpReq.requestState,\n serverCtx: ctx,\n ...(clientCapabilities ? { clientCapabilities } : {}),\n };\n}\n\n/**\n * Claude Code — and any client that treats `structuredContent` as the canonical\n * model view — discards the `text` blocks when `structuredContent` is present,\n * showing the model `JSON.stringify(structuredContent)` instead. A tool that\n * authored a text result (list's ASCII tree, read's file) meant that text for\n * the model, so it ships its metadata under `_meta`, which no client renders in\n * place of the content. Tools with no `text` keep `structuredContent`: the JSON\n * *is* their model-facing view.\n */\nfunction buildSuccessResponse<O>(result: RunResult<O>): CallToolResult {\n const hasText = result.text !== undefined;\n const text = result.text ?? JSON.stringify(result.structured);\n const content: ContentBlock[] = [{ type: 'text' as const, text }, ...(result.resources ?? [])];\n return {\n content,\n ...(hasText\n ? // Safe because every `ToolDef.output` is a Zod object schema, so\n // `structured` is always a plain object. Constraining `O` to prove it\n // is not worth the cost: the bound has to thread through five generic\n // sites and still loses to `exactOptionalPropertyTypes` variance on\n // `RunResult`'s optional fields.\n { _meta: result.structured as Record<string, unknown> }\n : { structuredContent: result.structured }),\n ...(result.isError ? { isError: true } : {}),\n };\n}\n\nclass ToolExecutor<I extends z.ZodType, O extends z.ZodType> {\n readonly signal: AbortSignal;\n private readonly def: ToolDef<I, O>;\n private readonly parsedArgs: z.infer<I>;\n private readonly toolCtx: ToolCtx;\n\n readonly #progressCtx: ProgressCtx;\n readonly #progressSession: ProgressSession;\n\n constructor(toolName: string, ctx: ToolCtx, def: ToolDef<I, O>, parsedArgs: z.infer<I>) {\n this.def = def;\n this.parsedArgs = parsedArgs;\n this.signal = def.timeoutMs\n ? AbortSignal.any([ctx.signal, AbortSignal.timeout(def.timeoutMs)])\n : ctx.signal;\n this.#progressCtx = def.progress ? def.progress(parsedArgs) : { label: def.title };\n const token = ctx._meta?.progressToken;\n const notify = ctx.sendNotification;\n this.#progressSession = new ProgressSession({\n label: this.#progressCtx.label,\n ...(token !== undefined && notify !== undefined ? { sink: { toolName, token, notify } } : {}),\n });\n this.toolCtx = {\n ...ctx,\n signal: this.signal,\n log: (level: LoggingLevel, data: unknown, logger?: string) => {\n const msg = typeof data === 'string' ? data : String(data);\n // `[req <id>]` first so one grep finds every line of one call; the\n // traceparent rides along only when the client sent one. Both are\n // client-supplied, so they pass through `sanitizeLogField`: a control\n // character in a JSON-RPC id or a traceparent would forge log lines.\n // The message is flattened too (uncapped): it can carry a resolved\n // path or OS error text, and input schemas reject CR/LF but not the\n // Unicode line separators.\n const trace = ctx.traceparent ? ` ${sanitizeLogField(ctx.traceparent)}` : '';\n const prefix = logger ? `[${logger}] ` : '';\n const text = sanitizeLogField(msg, Infinity);\n Logger.emit(\n level,\n `[req ${sanitizeLogField(String(ctx.requestId))}${trace}] ${prefix}${text}`,\n );\n },\n onProgress: (p) => {\n this.#tick(p);\n },\n };\n }\n\n #tick(p: { current: number; total?: number }): void {\n const tickCtx: ProgressCtx = {\n ...this.#progressCtx,\n current: p.current,\n ...(p.total !== undefined ? { total: p.total } : {}),\n };\n this.#progressSession.set({ ...p, message: plainMessage('tick', tickCtx) });\n }\n\n private async completeProgress(result: z.infer<O>): Promise<void> {\n const doneCtx: ProgressCtx = this.def.progressDone\n ? { ...this.#progressCtx, ...this.def.progressDone(this.parsedArgs, result) }\n : this.#progressCtx;\n this.#progressSession.complete(plainMessage('done', doneCtx));\n await this.#progressSession.flush();\n }\n\n private async failProgress(error: unknown): Promise<{ isError: true; content: ContentBlock[] }> {\n const errMsg = formatUnknownErrorMessage(error);\n this.#progressSession.fail(plainMessage('fail', { ...this.#progressCtx, error: errMsg }));\n await this.#progressSession.flush();\n const { text: errorText } = Problem.toText(\n error,\n this.def.defaultErrorCode ?? ErrorCode.UNKNOWN,\n );\n return {\n content: [{ type: 'text' as const, text: errorText }],\n isError: true,\n };\n }\n\n /**\n * Access-grant pre-check (R7/R8/R9). Before `run` touches the filesystem,\n * ask PathGuard which of the tool's declared paths are out-of-root and\n * grantable. If any are and this round carries no verified `requestState`,\n * return `input_required` (nothing is read or written — R7). On retry, the\n * verified state must bind this grant set (R9); apply each accepted grant for\n * the session (R8) and proceed. A declined or ungrantable path is left for\n * `validateAccess` to fail closed during the operation. Returns `undefined`\n * when no round-trip is needed and any applicable grants have been applied.\n */\n private async precheckGrant(): Promise<InputRequiredResult | undefined> {\n const extract = this.def.accessPaths;\n if (!extract) return undefined;\n const paths = extract(this.parsedArgs);\n if (paths.length === 0) return undefined;\n const grantDirs = await this.toolCtx.fs.pathGuard.precheckAccess(paths);\n if (grantDirs.length === 0) return undefined;\n\n // One grant dir: a single boolean confirm. Multiple: one multi-select\n // elicitation so the client picks the subset to allow in one round-trip\n // (N dirs → 1 round-trip, not N). `pendingRoundTrip` still binds\n // `paths: grantDirs` sorted, so R9 path-binding is unaffected.\n const multi = grantDirs.length > 1;\n const round = await pendingRoundTrip({\n op: 'grant',\n pending: grantDirs,\n requestState: this.toolCtx.requestState,\n clientCapabilities: this.toolCtx.clientCapabilities,\n serverCtx: this.toolCtx.serverCtx,\n buildInputs: (dirs) =>\n multi\n ? [\n {\n key: 'grant',\n message: 'Grant filesystem access to these directories? Select the ones to allow.',\n choices: dirs,\n multi: true,\n },\n ]\n : dirs.map((dir, i) => ({\n key: confirmKey(i),\n message: `Grant filesystem access to \"${dir}\"?`,\n })),\n });\n if (round !== undefined) return round;\n // Apply accepted grants for the session (R8). Declined/missing dirs are\n // skipped here; their paths fail with ACCESS_DENIED during the operation.\n //\n // No list-changed notification follows: a grant widens the allowed roots,\n // and no resource list reads them. The instructions resource has a fixed\n // URI, the result template lists the ResourceStore, and the file template\n // lists nothing at all (see resources.ts). Notifying here only bought the\n // client a round trip to re-fetch a list that could not have changed.\n //\n // `readAcceptedMultiChoice` does NOT validate against the offered choices\n // (attacker-controlled inputResponses on re-entry). Only grant dirs that\n // were actually offered by precheckAccess — a value outside grantDirs is\n // ignored and fails closed in validateAccess. The single-select path reads\n // `confirmKey(i)` for `grantDirs[i]`, so the isSamePath filter is a no-op\n // there; it only bites for the multi-select array.\n const accepted = multi\n ? (readAcceptedMultiChoice(this.toolCtx.inputResponses, 'grant') ?? [])\n : grantDirs.filter((_dir, i) =>\n readAcceptedConfirm(this.toolCtx.inputResponses, confirmKey(i)),\n );\n for (const dir of accepted) {\n if (!grantDirs.some((g) => isSamePath(g, dir))) continue;\n await this.toolCtx.fs.pathGuard.applyGrant(dir);\n }\n return undefined;\n }\n\n async execute(): Promise<CallToolResult | InputRequiredResult> {\n try {\n // Access-grant pre-check before any filesystem touch (R7/R8/R9). A\n // grant input_required short-circuits here (progress paused, not\n // finished); an R9 mismatch throws, which this catch surfaces as an\n // isError tool result like every other handler failure — not a raw\n // JSON-RPC error (GRANT-1 impact #2).\n const grantRequired = await this.precheckGrant();\n if (grantRequired !== undefined) return grantRequired;\n const result = await this.def.run(this.parsedArgs, this.toolCtx);\n // input_required is a return value, not a completed call: the client\n // retries the same tools/call carrying inputResponses, and this\n // handler re-enters from the top. Skip the progress \"done\" close and\n // return it verbatim — progress is paused, not finished.\n if (isInputRequiredResult(result)) {\n return result;\n }\n await this.completeProgress(result.structured);\n return buildSuccessResponse(result);\n } catch (error) {\n return await this.failProgress(error);\n } finally {\n await this.#progressSession.flush();\n }\n }\n}\n\nexport function defineTool<I extends z.ZodType, O extends z.ZodType>(\n def: ToolDef<I, O>,\n): DefinedTool {\n // Nothing here depends on `deps`, so it is built once per tool definition\n // rather than once per `register` — the HTTP leg registers every tool afresh\n // on each request.\n // Published annotations are derived, not passed through. `readOnlyHint` is\n // load-bearing (MUTATING_TOOL_NAMES derives the --read-only gate from it) and\n // `openWorldHint: false` is a real claim for a filesystem server. The other\n // two describe behavior a read-only tool cannot have, and restate the default\n // for a mutating one — 29 tokens per tool for nothing a client acts on.\n const publishedAnnotations: ToolAnnotations = {\n readOnlyHint: def.annotations.readOnlyHint,\n openWorldHint: def.annotations.openWorldHint ?? false,\n ...(def.annotations.readOnlyHint\n ? {}\n : { destructiveHint: def.annotations.destructiveHint ?? true }),\n };\n\n const toolDefShape = {\n title: def.title,\n description: def.description,\n // The Zod schema goes in as-is: the SDK validates with it and publishes its\n // own draft-2020-12 conversion in `tools/list`. The cast only names the\n // in/out types a generic `ZodType` cannot surface through `~standard`.\n inputSchema: def.input as unknown as StandardSchemaWithJSON<z.input<I>, z.output<I>>,\n // No `outputSchema`, ever. Publishing one obliges the result to carry\n // `structuredContent` (clients enforce it), and every tool that authors its\n // own text ships its metadata under `_meta` instead — see\n // `buildSuccessResponse`. The two cannot both hold, and the text is what\n // the model reads. `TOOL-SURFACE-001` pins this for the whole surface.\n //\n // `def.output` stays: it types `RunResult<z.infer<O>>`, which is what makes\n // a tool returning the wrong shape a compile error.\n annotations: publishedAnnotations,\n };\n\n return {\n name: def.name,\n annotations: def.annotations,\n\n register(deps: ToolDeps): RegisteredTool {\n return deps.server.registerTool(def.name, toolDefShape, async (args, ctx) =>\n new ToolExecutor<I, O>(def.name, toToolCtx(ctx, deps), def, args).execute(),\n );\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"define.js","sourceRoot":"","sources":["../../src/tools/define.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n CallToolResult,\n ClientCapabilities,\n ContentBlock,\n InputRequiredResult,\n McpServer,\n Notification,\n RegisteredTool,\n RequestId,\n RequestMeta,\n RequestStateAccessor,\n ServerContext,\n StandardSchemaWithJSON,\n ToolAnnotations,\n} from '@modelcontextprotocol/server';\nimport {\n CLIENT_CAPABILITIES_META_KEY,\n isInputRequiredResult,\n TRACEPARENT_META_KEY,\n} from '@modelcontextprotocol/server';\n\nimport type * as z from 'zod/v4';\n\nimport { ErrorCode, formatUnknownErrorMessage, Problem } from '../core/errors.ts';\nimport type { ProgressCtx } from '../core/fmt.ts';\nimport { plainMessage } from '../core/fmt.ts';\nimport { GuardedFileSystem } from '../core/fs.ts';\nimport {\n confirmKey,\n pendingRoundTrip,\n readAcceptedConfirm,\n readAcceptedMultiChoice,\n} from '../core/input-required.ts';\nimport { Logger, sanitizeLogField } from '../core/observability.ts';\nimport type { LoggingLevel } from '../core/observability.ts';\nimport { isSamePath } from '../core/path-utils.ts';\nimport type { PathGuard } from '../core/path.ts';\nimport type { PageSnapshotStore, ResourceStore } from '../core/store.ts';\nimport { ProgressSession } from './progress.ts';\n\nexport interface ToolCtx {\n readonly signal: AbortSignal;\n readonly _meta?: RequestMeta | undefined;\n /** The JSON-RPC id of the `tools/call` this context serves; prefixes every log line. */\n readonly requestId: RequestId;\n /** W3C trace context the client put in `_meta`, when it did; rides the log prefix. */\n readonly traceparent?: string | undefined;\n readonly fs: GuardedFileSystem;\n readonly pageStore: PageSnapshotStore;\n readonly resourceStore: ResourceStore | undefined;\n /** Emits a log line to stderr via `Logger.emit`, gated by `LOG_LEVEL`. */\n readonly log?: (level: LoggingLevel, data: unknown, logger?: string) => void;\n readonly sendNotification?: (notification: Notification) => Promise<void>;\n readonly onProgress?: (params: { current: number; total?: number }) => void;\n /**\n * Multi-round-trip `inputResponses` carried by a retried `tools/call`\n * (protocol revision 2026-07-28); `undefined` on the first round. Bare,\n * unvalidated client values — handlers read them through\n * `readAcceptedConfirm`.\n */\n readonly inputResponses?: Record<string, unknown> | undefined;\n /**\n * Reads the verified multi-round-trip `requestState` for the current round:\n * the decoded `PendingState` the `requestStateCodec` verified, or `undefined`\n * when the round carried no state (the first round). `undefined` when no\n * live request context is available.\n */\n readonly requestState?: RequestStateAccessor | undefined;\n /**\n * What the connected client declared it can do, or `undefined` when this\n * connection cannot say. Read by the `input_required` flows: an embedded\n * elicitation sent to a client that never declared `elicitation` is rejected\n * by the SDK with `-32021` before it reaches the wire, so the handlers check\n * first and answer with an actionable tool error instead.\n *\n * Two sources, because the eras differ: a legacy connection negotiated them\n * at `initialize` (`Server.getClientCapabilities()`), a modern one carries\n * them per request in the `_meta` envelope and never runs `initialize` at\n * all. `undefined` means \"cannot tell\" — never \"no capabilities\".\n */\n readonly clientCapabilities?: ClientCapabilities | undefined;\n /** The SDK request context this call runs under; `pendingRoundTrip` binds minted state to it. */\n readonly serverCtx: ServerContext;\n}\n\ninterface ToolDeps {\n readonly server: McpServer;\n readonly pathGuard: PathGuard;\n readonly pageStore: PageSnapshotStore;\n readonly resourceStore: ResourceStore | undefined;\n readonly era?: 'legacy' | 'modern';\n}\n\ninterface RunResult<T> {\n readonly structured: T;\n readonly text?: string;\n readonly resources?: ContentBlock[];\n /**\n * The call as a whole failed. Batch tools set it from `isTotalFailure` in\n * `batch.ts` — every requested item failed — so the executor never has to\n * know a tool's output shape. Absent or `false` means the call did work.\n */\n readonly isError?: boolean;\n}\n\n/**\n * `ToolAnnotations` with `readOnlyHint` required and `idempotentHint` removed.\n * `readOnlyHint` is optional in the SDK, but MUTATING_TOOL_NAMES derives the\n * `--read-only` gate from it, so a tool that forgets it must be a compile error\n * rather than a silent reclassification. `idempotentHint` is omitted because\n * nothing reads it: `publishedAnnotations` derives the wire set below.\n */\ntype DeclaredAnnotations = Omit<ToolAnnotations, 'idempotentHint'> & {\n readonly readOnlyHint: boolean;\n};\n\nexport interface ToolDef<I extends z.ZodType, O extends z.ZodType> {\n readonly name: string;\n readonly title: string;\n readonly description: string;\n readonly input: I;\n readonly output: O;\n readonly annotations: DeclaredAnnotations;\n readonly timeoutMs?: number;\n readonly progress?: (args: z.infer<I>) => ProgressCtx;\n readonly progressDone?: (args: z.infer<I>, result: z.infer<O>) => Partial<ProgressCtx>;\n readonly defaultErrorCode?: ErrorCode;\n /**\n * The filesystem paths this tool will operate on, extracted from its parsed\n * args. The executor runs an access-grant pre-check over these BEFORE `run`\n * (R7): any path outside the granted roots yields an `input_required`\n * round-trip requesting a grant, and nothing is touched until the client\n * retries with an accepted grant (R8). Omit for tools that do not operate on\n * caller-supplied filesystem paths.\n */\n readonly accessPaths?: (args: z.infer<I>) => readonly string[];\n readonly run: (\n args: z.infer<I>,\n ctx: ToolCtx,\n ) => Promise<RunResult<z.infer<O>> | InputRequiredResult>;\n}\n\nexport interface DefinedTool {\n readonly name: string;\n readonly annotations: DeclaredAnnotations;\n\n register(deps: ToolDeps): RegisteredTool;\n}\n\nfunction toToolCtx(\n ctx: ServerContext,\n deps: Pick<ToolDeps, 'pathGuard' | 'pageStore' | 'resourceStore' | 'server' | 'era'>,\n): ToolCtx {\n // Envelope first, accessor second — the two eras carry this differently.\n // A modern request states the capabilities in its own `_meta` envelope; a\n // legacy connection fixed them at `initialize` and has no envelope at all.\n // The deprecated accessor still answers for both today (the SDK backfills it\n // per request from the validated envelope on modern instances), but reading\n // the envelope directly is the supported path, so it leads: when the accessor\n // goes, legacy degrades to \"cannot tell\", which fails open to the behavior\n // that predates this check.\n //\n // The cast is the SDK's shipped `RequestMetaEnvelope` declaration collapsing\n // to `{}` — the reserved keys survive at runtime but not in the .d.ts, so the\n // key constant cannot index the declared type.\n const envelope = ctx.mcpReq.envelope as Record<string, unknown> | undefined;\n const clientCapabilities =\n (envelope?.[CLIENT_CAPABILITIES_META_KEY] as ClientCapabilities | undefined) ??\n // eslint-disable-next-line @typescript-eslint/no-deprecated -- the only source of client capabilities on a legacy connection, where no envelope exists.\n deps.server.server.getClientCapabilities() ??\n // A legacy instance that never saw `initialize` is the HTTP leg's\n // per-request serving (`createMcpHandler` with `legacy: 'stateless'`):\n // there is no return path for a server-to-client request, so read the\n // client as having declared nothing. The `input_required` flows then\n // answer with their named workaround instead of the SDK's generic refusal.\n // sunset(SEP-2577): removal trigger in docs/adr/002-legacy-protocol-paths-sunset.md.\n (deps.era === 'legacy' ? {} : undefined);\n\n return {\n signal: ctx.mcpReq.signal,\n ...(ctx.mcpReq._meta ? { _meta: ctx.mcpReq._meta } : {}),\n requestId: ctx.mcpReq.id,\n ...(typeof ctx.mcpReq._meta?.[TRACEPARENT_META_KEY] === 'string'\n ? { traceparent: ctx.mcpReq._meta[TRACEPARENT_META_KEY] }\n : {}),\n fs: new GuardedFileSystem(deps.pathGuard),\n pageStore: deps.pageStore,\n resourceStore: deps.resourceStore,\n sendNotification: async (notification) => ctx.mcpReq.notify(notification),\n inputResponses: ctx.mcpReq.inputResponses,\n requestState: ctx.mcpReq.requestState,\n serverCtx: ctx,\n ...(clientCapabilities ? { clientCapabilities } : {}),\n };\n}\n\n/**\n * Claude Code — and any client that treats `structuredContent` as the canonical\n * model view — discards the `text` blocks when `structuredContent` is present,\n * showing the model `JSON.stringify(structuredContent)` instead. A tool that\n * authored a text result (list's ASCII tree, read's file) meant that text for\n * the model, so it ships its metadata under `_meta`, which no client renders in\n * place of the content. Tools with no `text` keep `structuredContent`: the JSON\n * *is* their model-facing view.\n */\nfunction buildSuccessResponse<O>(result: RunResult<O>): CallToolResult {\n const hasText = result.text !== undefined;\n const text = result.text ?? JSON.stringify(result.structured);\n const content: ContentBlock[] = [{ type: 'text' as const, text }, ...(result.resources ?? [])];\n return {\n content,\n ...(hasText\n ? // Safe because every `ToolDef.output` is a Zod object schema, so\n // `structured` is always a plain object. Constraining `O` to prove it\n // is not worth the cost: the bound has to thread through five generic\n // sites and still loses to `exactOptionalPropertyTypes` variance on\n // `RunResult`'s optional fields.\n { _meta: result.structured as Record<string, unknown> }\n : { structuredContent: result.structured }),\n ...(result.isError ? { isError: true } : {}),\n };\n}\n\nclass ToolExecutor<I extends z.ZodType, O extends z.ZodType> {\n readonly signal: AbortSignal;\n private readonly def: ToolDef<I, O>;\n private readonly parsedArgs: z.infer<I>;\n private readonly toolCtx: ToolCtx;\n\n readonly #progressCtx: ProgressCtx;\n readonly #progressSession: ProgressSession;\n\n constructor(toolName: string, ctx: ToolCtx, def: ToolDef<I, O>, parsedArgs: z.infer<I>) {\n this.def = def;\n this.parsedArgs = parsedArgs;\n this.signal = def.timeoutMs\n ? AbortSignal.any([ctx.signal, AbortSignal.timeout(def.timeoutMs)])\n : ctx.signal;\n this.#progressCtx = def.progress ? def.progress(parsedArgs) : { label: def.title };\n const token = ctx._meta?.progressToken;\n const notify = ctx.sendNotification;\n this.#progressSession = new ProgressSession({\n label: this.#progressCtx.label,\n ...(token !== undefined && notify !== undefined ? { sink: { toolName, token, notify } } : {}),\n });\n this.toolCtx = {\n ...ctx,\n signal: this.signal,\n log: (level: LoggingLevel, data: unknown, logger?: string) => {\n const msg = typeof data === 'string' ? data : String(data);\n // `[req <id>]` first so one grep finds every line of one call; the\n // traceparent rides along only when the client sent one. Both are\n // client-supplied, so they pass through `sanitizeLogField`: a control\n // character in a JSON-RPC id or a traceparent would forge log lines.\n // The message is flattened too (uncapped): it can carry a resolved\n // path or OS error text, and input schemas reject CR/LF but not the\n // Unicode line separators.\n const trace = ctx.traceparent ? ` ${sanitizeLogField(ctx.traceparent)}` : '';\n const prefix = logger ? `[${logger}] ` : '';\n const text = sanitizeLogField(msg, Infinity);\n Logger.emit(\n level,\n `[req ${sanitizeLogField(String(ctx.requestId))}${trace}] ${prefix}${text}`,\n );\n },\n onProgress: (p) => {\n this.#tick(p);\n },\n };\n }\n\n #tick(p: { current: number; total?: number }): void {\n const tickCtx: ProgressCtx = {\n ...this.#progressCtx,\n current: p.current,\n ...(p.total !== undefined ? { total: p.total } : {}),\n };\n this.#progressSession.set({ ...p, message: plainMessage('tick', tickCtx) });\n }\n\n private async completeProgress(result: z.infer<O>): Promise<void> {\n const doneCtx: ProgressCtx = this.def.progressDone\n ? { ...this.#progressCtx, ...this.def.progressDone(this.parsedArgs, result) }\n : this.#progressCtx;\n this.#progressSession.complete(plainMessage('done', doneCtx));\n await this.#progressSession.flush();\n }\n\n private async failProgress(error: unknown): Promise<{ isError: true; content: ContentBlock[] }> {\n const errMsg = formatUnknownErrorMessage(error);\n this.#progressSession.fail(plainMessage('fail', { ...this.#progressCtx, error: errMsg }));\n await this.#progressSession.flush();\n const errorText = Problem.toText(error, this.def.defaultErrorCode ?? ErrorCode.UNKNOWN);\n return {\n content: [{ type: 'text' as const, text: errorText }],\n isError: true,\n };\n }\n\n /**\n * Access-grant pre-check (R7/R8/R9). Before `run` touches the filesystem,\n * ask PathGuard which of the tool's declared paths are out-of-root and\n * grantable. If any are and this round carries no verified `requestState`,\n * return `input_required` (nothing is read or written — R7). On retry, the\n * verified state must bind this grant set (R9); apply each accepted grant for\n * the session (R8) and proceed. A declined or ungrantable path is left for\n * `validateAccess` to fail closed during the operation. Returns `undefined`\n * when no round-trip is needed and any applicable grants have been applied.\n */\n private async precheckGrant(): Promise<InputRequiredResult | undefined> {\n const extract = this.def.accessPaths;\n if (!extract) return undefined;\n const paths = extract(this.parsedArgs);\n if (paths.length === 0) return undefined;\n const grantDirs = await this.toolCtx.fs.pathGuard.precheckAccess(paths);\n if (grantDirs.length === 0) return undefined;\n\n // One grant dir: a single boolean confirm. Multiple: one multi-select\n // elicitation so the client picks the subset to allow in one round-trip\n // (N dirs → 1 round-trip, not N). `pendingRoundTrip` still binds\n // `paths: grantDirs` sorted, so R9 path-binding is unaffected.\n const multi = grantDirs.length > 1;\n const round = await pendingRoundTrip({\n op: 'grant',\n pending: grantDirs,\n requestState: this.toolCtx.requestState,\n clientCapabilities: this.toolCtx.clientCapabilities,\n serverCtx: this.toolCtx.serverCtx,\n buildInputs: (dirs) =>\n multi\n ? [\n {\n key: 'grant',\n message: 'Grant filesystem access to these directories? Select the ones to allow.',\n choices: dirs,\n multi: true,\n },\n ]\n : dirs.map((dir, i) => ({\n key: confirmKey(i),\n message: `Grant filesystem access to \"${dir}\"?`,\n })),\n });\n if (round !== undefined) return round;\n // Apply accepted grants for the session (R8). Declined/missing dirs are\n // skipped here; their paths fail with ACCESS_DENIED during the operation.\n //\n // No list-changed notification follows: a grant widens the allowed roots,\n // and no resource list reads them. The instructions resource has a fixed\n // URI, the result template lists the ResourceStore, and the file template\n // lists nothing at all (see resources.ts). Notifying here only bought the\n // client a round trip to re-fetch a list that could not have changed.\n //\n // `readAcceptedMultiChoice` does NOT validate against the offered choices\n // (attacker-controlled inputResponses on re-entry). Only grant dirs that\n // were actually offered by precheckAccess — a value outside grantDirs is\n // ignored and fails closed in validateAccess. The single-select path reads\n // `confirmKey(i)` for `grantDirs[i]`, so the isSamePath filter is a no-op\n // there; it only bites for the multi-select array.\n const accepted = multi\n ? (readAcceptedMultiChoice(this.toolCtx.inputResponses, 'grant') ?? [])\n : grantDirs.filter((_dir, i) =>\n readAcceptedConfirm(this.toolCtx.inputResponses, confirmKey(i)),\n );\n for (const dir of accepted) {\n if (!grantDirs.some((g) => isSamePath(g, dir))) continue;\n await this.toolCtx.fs.pathGuard.applyGrant(dir);\n }\n return undefined;\n }\n\n async execute(): Promise<CallToolResult | InputRequiredResult> {\n try {\n // Access-grant pre-check before any filesystem touch (R7/R8/R9). A\n // grant input_required short-circuits here (progress paused, not\n // finished); an R9 mismatch throws, which this catch surfaces as an\n // isError tool result like every other handler failure — not a raw\n // JSON-RPC error (GRANT-1 impact #2).\n const grantRequired = await this.precheckGrant();\n if (grantRequired !== undefined) return grantRequired;\n const result = await this.def.run(this.parsedArgs, this.toolCtx);\n // input_required is a return value, not a completed call: the client\n // retries the same tools/call carrying inputResponses, and this\n // handler re-enters from the top. Skip the progress \"done\" close and\n // return it verbatim — progress is paused, not finished.\n if (isInputRequiredResult(result)) {\n return result;\n }\n await this.completeProgress(result.structured);\n return buildSuccessResponse(result);\n } catch (error) {\n return await this.failProgress(error);\n } finally {\n await this.#progressSession.flush();\n }\n }\n}\n\nexport function defineTool<I extends z.ZodType, O extends z.ZodType>(\n def: ToolDef<I, O>,\n): DefinedTool {\n // Nothing here depends on `deps`, so it is built once per tool definition\n // rather than once per `register` — the HTTP leg registers every tool afresh\n // on each request.\n // Published annotations are derived, not passed through. `readOnlyHint` is\n // load-bearing (MUTATING_TOOL_NAMES derives the --read-only gate from it) and\n // `openWorldHint: false` is a real claim for a filesystem server. The other\n // two describe behavior a read-only tool cannot have, and restate the default\n // for a mutating one — 29 tokens per tool for nothing a client acts on.\n const publishedAnnotations: ToolAnnotations = {\n readOnlyHint: def.annotations.readOnlyHint,\n openWorldHint: def.annotations.openWorldHint ?? false,\n ...(def.annotations.readOnlyHint\n ? {}\n : { destructiveHint: def.annotations.destructiveHint ?? true }),\n };\n\n const toolDefShape = {\n title: def.title,\n description: def.description,\n // The Zod schema goes in as-is: the SDK validates with it and publishes its\n // own draft-2020-12 conversion in `tools/list`. The cast only names the\n // in/out types a generic `ZodType` cannot surface through `~standard`.\n inputSchema: def.input as unknown as StandardSchemaWithJSON<z.input<I>, z.output<I>>,\n // No `outputSchema`, ever. Publishing one obliges the result to carry\n // `structuredContent` (clients enforce it), and every tool that authors its\n // own text ships its metadata under `_meta` instead — see\n // `buildSuccessResponse`. The two cannot both hold, and the text is what\n // the model reads. `TOOL-SURFACE-001` pins this for the whole surface.\n //\n // `def.output` stays: it types `RunResult<z.infer<O>>`, which is what makes\n // a tool returning the wrong shape a compile error.\n annotations: publishedAnnotations,\n };\n\n return {\n name: def.name,\n annotations: def.annotations,\n\n register(deps: ToolDeps): RegisteredTool {\n return deps.server.registerTool(def.name, toolDefShape, async (args, ctx) =>\n new ToolExecutor<I, O>(def.name, toToolCtx(ctx, deps), def, args).execute(),\n );\n },\n };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["../../src/tools/delete.ts"],"names":[],"mappings":"AA4YA,eAAO,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["../../src/tools/delete.ts"],"names":[],"mappings":"AA4YA,eAAO,MAAM,MAAM,mCAkDjB,CAAC"}
|
package/dist/tools/delete.js
CHANGED
|
@@ -282,17 +282,11 @@ async function handleDelete(args, ctx) {
|
|
|
282
282
|
export const DELETE = defineTool({
|
|
283
283
|
name: 'delete',
|
|
284
284
|
title: 'Delete File',
|
|
285
|
-
description: 'Permanently delete
|
|
286
|
-
'Pass paths: [...] — there is no single-path form. ' +
|
|
287
|
-
'Non-empty directories require recursive=true and additionally prompt the user to confirm each one, ' +
|
|
288
|
-
'so the call returns without deleting anything until that confirmation comes back; ' +
|
|
289
|
-
'a client that cannot prompt gets an error naming the alternative. ' +
|
|
290
|
-
'Workspace root directories cannot be deleted.',
|
|
285
|
+
description: 'Permanently delete files, directories, or symlinks, like rm or rm -r. Paths are exact; globs are not expanded.',
|
|
291
286
|
input: DeleteInputSchema,
|
|
292
287
|
output: DeleteOutputSchema,
|
|
293
288
|
annotations: {
|
|
294
289
|
readOnlyHint: false,
|
|
295
|
-
idempotentHint: false,
|
|
296
290
|
destructiveHint: true,
|
|
297
291
|
openWorldHint: false,
|
|
298
292
|
},
|
package/dist/tools/delete.js.map
CHANGED
|
@@ -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 pendingRoundTrip,\n readAcceptedChoice,\n} from '../core/input-required.ts';\nimport { resolveEntryType } from '../core/path-utils.ts';\nimport {\n defaultFalseBoolean,\n OperationSummarySchema,\n PerFileErrorSchema,\n RequiredPath,\n} from '../core/schema.ts';\nimport { PARALLEL_CONCURRENCY } from '../core/util.ts';\nimport { isTotalFailure } 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\nconst DeletePerPathValueSchema = z.strictObject({\n deleted: z.boolean().describe('True when the path was removed; false when the user chose Skip'),\n});\n\nconst DeletePerPathSchema = z.strictObject({\n path: z.string().describe('Requested path'),\n value: DeletePerPathValueSchema.optional().describe('Delete outcome; present on success'),\n error: PerFileErrorSchema.optional().describe('Error details; present on failure'),\n});\n\n// One envelope for every batch tool: `read` and `stat` already answer with\n// `{ results, summary }`, so `delete` does too. The old shape switched between\n// `{ ok, path }` and `{ ok: false, failures }` depending on the outcome, which\n// left a caller parsing two schemas for one tool and never named the paths in a\n// multi-delete's text.\nconst DeleteOutputSchema = z.strictObject({\n results: z\n .array(DeletePerPathSchema)\n .describe('Per-path results ordered to match the input paths'),\n summary: OperationSummarySchema,\n});\n\ntype DeleteInput = z.infer<typeof DeleteInputSchema>;\ntype DeleteOutput = z.infer<typeof DeleteOutputSchema>;\ntype DeletePerPathResult = z.infer<typeof DeletePerPathSchema>;\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 const pending = hasChildren;\n return { status: 'plan', plan: { inputPath, validPath, itemType, firstStats, pending } };\n}\n\nasync function performDeletion(\n validPath: string,\n args: Pick<DeleteInput, 'recursive' | 'ignoreIfNotExists'>,\n isDirectory: boolean,\n fsOps: Pick<GuardedFileSystem, 'rm' | 'rmdir'>,\n): Promise<void> {\n if (isDirectory && !args.recursive) {\n await fsOps.rmdir(validPath);\n } else {\n await fsOps.rm(validPath, {\n recursive: args.recursive,\n force: args.ignoreIfNotExists,\n });\n }\n}\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 =\n plan.firstStats.stats.dev !== currentStats.stats.dev ||\n plan.firstStats.stats.ino !== currentStats.stats.ino ||\n plan.firstStats.stats.birthtimeMs !== currentStats.stats.birthtimeMs;\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 await performDeletion(plan.validPath, args, currentStats.stats.isDirectory(), ctx.fs);\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' | 'log'>,\n pendingSorted: readonly string[],\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.inputResponses, key)}`,\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 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 plans.push({ plan: r.plan, index });\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 if (pendingSorted.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({\n op: 'delete',\n pending: pendingSorted,\n requestState: ctx.requestState,\n clientCapabilities: ctx.clientCapabilities,\n serverCtx: ctx.serverCtx,\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),\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 const failed = results.filter((r) => r.error !== undefined).length;\n return {\n results,\n summary: { total: results.length, succeeded: results.length - failed, failed },\n };\n}\n\nexport const DELETE = defineTool({\n name: 'delete',\n title: 'Delete File',\n description:\n 'Permanently delete one or more files, directories, or symlinks (max 1000 per call). This action is irreversible. ' +\n 'Pass paths: [...] — there is no single-path form. ' +\n 'Non-empty directories require recursive=true and additionally prompt the user to confirm each one, ' +\n 'so the call returns without deleting anything until that confirmation comes back; ' +\n 'a client that cannot prompt gets an error naming the alternative. ' +\n 'Workspace root directories cannot be deleted.',\n input: DeleteInputSchema,\n output: DeleteOutputSchema,\n annotations: {\n readOnlyHint: false,\n idempotentHint: false,\n destructiveHint: true,\n openWorldHint: false,\n },\n defaultErrorCode: ErrorCode.UNKNOWN,\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?.message ?? 'unknown error'}`,\n isError,\n };\n }\n const tokens = structured.results.map((r) => {\n const label = pathLabel(r.path);\n if (r.error) 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":"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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 pendingRoundTrip,\n readAcceptedChoice,\n} from '../core/input-required.ts';\nimport { resolveEntryType } from '../core/path-utils.ts';\nimport {\n defaultFalseBoolean,\n OperationSummarySchema,\n PerFileErrorSchema,\n RequiredPath,\n} from '../core/schema.ts';\nimport { PARALLEL_CONCURRENCY } from '../core/util.ts';\nimport { isTotalFailure } 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\nconst DeletePerPathValueSchema = z.strictObject({\n deleted: z.boolean().describe('True when the path was removed; false when the user chose Skip'),\n});\n\nconst DeletePerPathSchema = z.strictObject({\n path: z.string().describe('Requested path'),\n value: DeletePerPathValueSchema.optional().describe('Delete outcome; present on success'),\n error: PerFileErrorSchema.optional().describe('Error details; present on failure'),\n});\n\n// One envelope for every batch tool: `read` and `stat` already answer with\n// `{ results, summary }`, so `delete` does too. The old shape switched between\n// `{ ok, path }` and `{ ok: false, failures }` depending on the outcome, which\n// left a caller parsing two schemas for one tool and never named the paths in a\n// multi-delete's text.\nconst DeleteOutputSchema = z.strictObject({\n results: z\n .array(DeletePerPathSchema)\n .describe('Per-path results ordered to match the input paths'),\n summary: OperationSummarySchema,\n});\n\ntype DeleteInput = z.infer<typeof DeleteInputSchema>;\ntype DeleteOutput = z.infer<typeof DeleteOutputSchema>;\ntype DeletePerPathResult = z.infer<typeof DeletePerPathSchema>;\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 const pending = hasChildren;\n return { status: 'plan', plan: { inputPath, validPath, itemType, firstStats, pending } };\n}\n\nasync function performDeletion(\n validPath: string,\n args: Pick<DeleteInput, 'recursive' | 'ignoreIfNotExists'>,\n isDirectory: boolean,\n fsOps: Pick<GuardedFileSystem, 'rm' | 'rmdir'>,\n): Promise<void> {\n if (isDirectory && !args.recursive) {\n await fsOps.rmdir(validPath);\n } else {\n await fsOps.rm(validPath, {\n recursive: args.recursive,\n force: args.ignoreIfNotExists,\n });\n }\n}\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 =\n plan.firstStats.stats.dev !== currentStats.stats.dev ||\n plan.firstStats.stats.ino !== currentStats.stats.ino ||\n plan.firstStats.stats.birthtimeMs !== currentStats.stats.birthtimeMs;\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 await performDeletion(plan.validPath, args, currentStats.stats.isDirectory(), ctx.fs);\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' | 'log'>,\n pendingSorted: readonly string[],\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.inputResponses, key)}`,\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 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 plans.push({ plan: r.plan, index });\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 if (pendingSorted.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({\n op: 'delete',\n pending: pendingSorted,\n requestState: ctx.requestState,\n clientCapabilities: ctx.clientCapabilities,\n serverCtx: ctx.serverCtx,\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),\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 const failed = results.filter((r) => r.error !== undefined).length;\n return {\n results,\n summary: { total: results.length, succeeded: results.length - failed, failed },\n };\n}\n\nexport const DELETE = defineTool({\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 output: DeleteOutputSchema,\n annotations: {\n readOnlyHint: false,\n destructiveHint: true,\n openWorldHint: false,\n },\n defaultErrorCode: ErrorCode.UNKNOWN,\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?.message ?? 'unknown error'}`,\n isError,\n };\n }\n const tokens = structured.results.map((r) => {\n const label = pathLabel(r.path);\n if (r.error) 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"]}
|
package/dist/tools/diff.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/tools/diff.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/tools/diff.ts"],"names":[],"mappings":"AAyBA,eAAO,MAAM,IAAI,mCA2Cf,CAAC"}
|
package/dist/tools/diff.js
CHANGED
|
@@ -18,33 +18,14 @@ const DiffOutputSchema = z.strictObject({
|
|
|
18
18
|
linesAdded: NonNegInt.describe('Number of lines added'),
|
|
19
19
|
linesRemoved: NonNegInt.describe('Number of lines removed'),
|
|
20
20
|
});
|
|
21
|
-
async function handleDiff(args, ctx) {
|
|
22
|
-
const [{ validPath: validA, content: contentA }, { validPath: validB, content: contentB }] = await Promise.all([
|
|
23
|
-
ctx.fs.readEditableText(args.a, { signal: ctx.signal, tool: 'diff' }),
|
|
24
|
-
ctx.fs.readEditableText(args.b, { signal: ctx.signal, tool: 'diff' }),
|
|
25
|
-
]);
|
|
26
|
-
// createTwoFilesPatch returns the unified diff string synchronously on diff v9
|
|
27
|
-
// (the { callback } option does not fire on this version — verified).
|
|
28
|
-
const diffText = createTwoFilesPatch(basename(validA), basename(validB), contentA, contentB, 'a', 'b', { context: args.context });
|
|
29
|
-
const { linesAdded, linesRemoved } = computeDiffStats(contentA, contentB);
|
|
30
|
-
// The text block is the one copy of the diff; a model reads that, and a
|
|
31
|
-
// structured duplicate or a store entry would only ship the same bytes again.
|
|
32
|
-
return {
|
|
33
|
-
structured: { a: validA, b: validB, linesAdded, linesRemoved },
|
|
34
|
-
text: diffText,
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
21
|
export const DIFF = defineTool({
|
|
38
22
|
name: 'diff',
|
|
39
23
|
title: 'Diff',
|
|
40
|
-
description: 'Compare two files and return a unified diff
|
|
41
|
-
'Use after an edit dry-run to compare against another file, or to inspect changes between two paths.',
|
|
24
|
+
description: 'Compare two text files and return a unified diff from a to b, like diff -u.',
|
|
42
25
|
input: DiffInputSchema,
|
|
43
26
|
output: DiffOutputSchema,
|
|
44
27
|
annotations: {
|
|
45
28
|
readOnlyHint: true,
|
|
46
|
-
idempotentHint: true,
|
|
47
|
-
destructiveHint: false,
|
|
48
29
|
openWorldHint: false,
|
|
49
30
|
},
|
|
50
31
|
progress: (args) => ({
|
|
@@ -52,6 +33,21 @@ export const DIFF = defineTool({
|
|
|
52
33
|
subject: basename(args.a),
|
|
53
34
|
}),
|
|
54
35
|
accessPaths: (args) => [args.a, args.b],
|
|
55
|
-
run: (args, ctx) =>
|
|
36
|
+
run: async (args, ctx) => {
|
|
37
|
+
const [{ validPath: validA, content: contentA }, { validPath: validB, content: contentB }] = await Promise.all([
|
|
38
|
+
ctx.fs.readEditableText(args.a, { signal: ctx.signal, tool: 'diff' }),
|
|
39
|
+
ctx.fs.readEditableText(args.b, { signal: ctx.signal, tool: 'diff' }),
|
|
40
|
+
]);
|
|
41
|
+
// createTwoFilesPatch returns the unified diff string synchronously on diff v9
|
|
42
|
+
// (the { callback } option does not fire on this version — verified).
|
|
43
|
+
const diffText = createTwoFilesPatch(basename(validA), basename(validB), contentA, contentB, 'a', 'b', { context: args.context });
|
|
44
|
+
const { linesAdded, linesRemoved } = computeDiffStats(contentA, contentB);
|
|
45
|
+
// The text block is the one copy of the diff; a model reads that, and a
|
|
46
|
+
// structured duplicate or a store entry would only ship the same bytes again.
|
|
47
|
+
return {
|
|
48
|
+
structured: { a: validA, b: validB, linesAdded, linesRemoved },
|
|
49
|
+
text: diffText,
|
|
50
|
+
};
|
|
51
|
+
},
|
|
56
52
|
});
|
|
57
53
|
//# sourceMappingURL=diff.js.map
|
package/dist/tools/diff.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/tools/diff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,MAAM,MAAM,CAAC;AAE3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/tools/diff.ts"],"names":[],"mappings":"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","sourcesContent":["import { basename } from 'node:path';\n\nimport * as z from 'zod/v4';\nimport { createTwoFilesPatch } from 'diff';\n\nimport { computeDiffStats } from '../core/diff.ts';\nimport { NonNegInt, PositiveInt, RequiredPath } from '../core/schema.ts';\nimport { defineTool } from './define.ts';\n\nconst DiffInputSchema = z.strictObject({\n a: RequiredPath.describe('First file to compare'),\n b: RequiredPath.describe('Second file to compare'),\n context: PositiveInt.max(50)\n .default(3)\n .describe('Number of context lines surrounding each change (default: 3)'),\n});\n\nconst DiffOutputSchema = z.strictObject({\n a: z.string().describe('Resolved absolute path of the first file'),\n b: z.string().describe('Resolved absolute path of the second file'),\n // The unified diff itself rides the text content block.\n linesAdded: NonNegInt.describe('Number of lines added'),\n linesRemoved: NonNegInt.describe('Number of lines removed'),\n});\n\nexport const DIFF = defineTool({\n name: 'diff',\n title: 'Diff',\n description: 'Compare two text files and return a unified diff from a to b, like diff -u.',\n input: DiffInputSchema,\n output: DiffOutputSchema,\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n progress: (args) => ({\n label: 'Diff',\n subject: basename(args.a),\n }),\n accessPaths: (args) => [args.a, args.b],\n run: async (args, ctx) => {\n const [{ validPath: validA, content: contentA }, { validPath: validB, content: contentB }] =\n await Promise.all([\n ctx.fs.readEditableText(args.a, { signal: ctx.signal, tool: 'diff' }),\n ctx.fs.readEditableText(args.b, { signal: ctx.signal, tool: 'diff' }),\n ]);\n\n // createTwoFilesPatch returns the unified diff string synchronously on diff v9\n // (the { callback } option does not fire on this version — verified).\n const diffText = createTwoFilesPatch(\n basename(validA),\n basename(validB),\n contentA,\n contentB,\n 'a',\n 'b',\n { context: args.context },\n );\n\n const { linesAdded, linesRemoved } = computeDiffStats(contentA, contentB);\n\n // The text block is the one copy of the diff; a model reads that, and a\n // structured duplicate or a store entry would only ship the same bytes again.\n return {\n structured: { a: validA, b: validB, linesAdded, linesRemoved },\n text: diffText,\n };\n },\n});\n"]}
|
package/dist/tools/edit.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../src/tools/edit.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../src/tools/edit.ts"],"names":[],"mappings":"AAqdA,eAAO,MAAM,IAAI,mCAqEf,CAAC"}
|
package/dist/tools/edit.js
CHANGED
|
@@ -3,6 +3,7 @@ import * as z from 'zod/v4';
|
|
|
3
3
|
import { computeDiffStats, unifiedPatch } from "../core/diff.js";
|
|
4
4
|
import { ErrorCode, FsError } from "../core/errors.js";
|
|
5
5
|
import { buildWrittenFileMeta } from "../core/file-uri.js";
|
|
6
|
+
import { joinRoster, truncateProgressPattern } from "../core/fmt.js";
|
|
6
7
|
import { defaultFalseBoolean, FileKind, isBlank, IsoDateTime, NonNegInt, OperationSummarySchema, PerFileErrorSchema, RequiredPath, singleOrBatchAccessPaths, } from "../core/schema.js";
|
|
7
8
|
import { compileRegex, execMatches, freeRegex } from "../core/search.js";
|
|
8
9
|
import { isTotalFailure, runOverPaths } from "./batch.js";
|
|
@@ -218,9 +219,6 @@ function ambiguousEditError(content, found, editIndex, shifted) {
|
|
|
218
219
|
return new FsError(ErrorCode.INVALID_INPUT, `edits[${String(editIndex)}]: oldText matches ${String(found.count)} places${where} ` +
|
|
219
220
|
`(${label} ${lines.join(', ')}${more}). Add surrounding lines so it matches once.`);
|
|
220
221
|
}
|
|
221
|
-
function replaceEditMatch(content, match, newText) {
|
|
222
|
-
return (content.slice(0, match.startIndex) + newText + content.slice(match.startIndex + match.length));
|
|
223
|
-
}
|
|
224
222
|
function buildEditFileValue(validPath, meta, modified, result) {
|
|
225
223
|
return {
|
|
226
224
|
path: validPath,
|
|
@@ -263,7 +261,11 @@ function applyEdits(content, edits, ignoreWhitespace) {
|
|
|
263
261
|
unmatchedEdits.push(edit.oldText);
|
|
264
262
|
continue;
|
|
265
263
|
}
|
|
266
|
-
|
|
264
|
+
const first = found.first;
|
|
265
|
+
newContent =
|
|
266
|
+
newContent.slice(0, first.startIndex) +
|
|
267
|
+
edit.newText +
|
|
268
|
+
newContent.slice(first.startIndex + first.length);
|
|
267
269
|
appliedEdits += 1;
|
|
268
270
|
}
|
|
269
271
|
const { linesAdded, linesRemoved } = appliedEdits > 0 ? computeDiffStats(content, newContent) : { linesAdded: 0, linesRemoved: 0 };
|
|
@@ -285,11 +287,10 @@ async function handleEditFile(filePath, edits, options, ctx) {
|
|
|
285
287
|
const meta = buildEditFileMetadata(editResult.content, validPath, 0, ctx.resourceStore);
|
|
286
288
|
return {
|
|
287
289
|
file: buildEditFileValue(validPath, meta, new Date().toISOString(), editResult),
|
|
288
|
-
...(meta.resourceLink ? { resourceLink: meta.resourceLink } : {}),
|
|
289
290
|
};
|
|
290
291
|
}
|
|
291
292
|
if (editResult.unmatchedEdits.length > 0) {
|
|
292
|
-
throw new FsError(ErrorCode.INVALID_INPUT,
|
|
293
|
+
throw new FsError(ErrorCode.INVALID_INPUT, `no match for oldText ${joinRoster(editResult.unmatchedEdits.map((t) => JSON.stringify(truncateProgressPattern(t))), ', ')}; it must match the file exactly`, filePath);
|
|
293
294
|
}
|
|
294
295
|
if (editResult.appliedEdits > 0) {
|
|
295
296
|
await ctx.fs.writeFile(filePath, editResult.content, {
|
|
@@ -322,8 +323,10 @@ function formatEditSummary(results, dryRun) {
|
|
|
322
323
|
const v = r.value;
|
|
323
324
|
if (!v)
|
|
324
325
|
return `${basename(r.path)} (no result)`;
|
|
325
|
-
if (v.unmatchedEdits && v.unmatchedEdits.length > 0)
|
|
326
|
-
|
|
326
|
+
if (v.unmatchedEdits && v.unmatchedEdits.length > 0) {
|
|
327
|
+
const quoted = v.unmatchedEdits.map((t) => JSON.stringify(truncateProgressPattern(t)));
|
|
328
|
+
return `${basename(v.path)} NO MATCH ${joinRoster(quoted, ', ')}`;
|
|
329
|
+
}
|
|
327
330
|
const added = v.linesAdded ?? 0;
|
|
328
331
|
const removed = v.linesRemoved ?? 0;
|
|
329
332
|
if (added === 0 && removed === 0)
|
|
@@ -333,22 +336,25 @@ function formatEditSummary(results, dryRun) {
|
|
|
333
336
|
const failed = results.filter((r) => r.error !== undefined).length;
|
|
334
337
|
const ok = results.length - failed;
|
|
335
338
|
const ratio = failed > 0 ? ` (${String(ok)}/${String(results.length)} ok)` : '';
|
|
336
|
-
|
|
339
|
+
// Only a dry run carries a diff, and it is the preview the caller asked for:
|
|
340
|
+
// the structured value ships under `_meta`, which clients do not show the model.
|
|
341
|
+
// A no-op edit still yields a header-only diff; it previews nothing.
|
|
342
|
+
const diffs = results
|
|
343
|
+
.map((r) => r.value?.diff ?? '')
|
|
344
|
+
.filter((d) => d.includes('\n@@'))
|
|
345
|
+
.join('');
|
|
346
|
+
return `edit: ${tokens.join(' · ')}${ratio}${tag}${diffs ? `\n\n${diffs}` : ''}`;
|
|
337
347
|
}
|
|
338
348
|
export const EDIT = defineTool({
|
|
339
349
|
name: 'edit',
|
|
340
350
|
title: 'Edit Files',
|
|
341
|
-
description: '
|
|
342
|
-
'
|
|
343
|
-
'
|
|
344
|
-
'or the edit fails listing the lines it matched. ' +
|
|
345
|
-
'Set dryRun=true to preview diffs without writing. ' +
|
|
346
|
-
'For glob-based bulk regex replacement across many files, use replace_text instead.',
|
|
351
|
+
description: 'Edit text files in place by replacing exact oldText with newText, like str_replace. ' +
|
|
352
|
+
'Each oldText must match exactly once, and a file is written only if all its edits match. ' +
|
|
353
|
+
'replace_text replaces every occurrence across files.',
|
|
347
354
|
input: EditFileInputSchema,
|
|
348
355
|
output: EditFileOutputSchema,
|
|
349
356
|
annotations: {
|
|
350
357
|
readOnlyHint: false,
|
|
351
|
-
idempotentHint: false,
|
|
352
358
|
destructiveHint: true,
|
|
353
359
|
openWorldHint: false,
|
|
354
360
|
},
|