@ai-agent-forge/plugin-process-exec 0.85.5 → 0.85.7

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/agent-forge.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "packageFormatVersion": 1,
3
3
  "id": "agent-forge.plugin.process-exec",
4
- "pluginVersion": "0.85.5",
4
+ "pluginVersion": "0.85.7",
5
5
  "apiVersion": "1",
6
6
  "minHostVersion": "0.84.4",
7
7
  "capabilityRefs": [
@@ -1 +1 @@
1
- {"version":3,"file":"capability.d.ts","sourceRoot":"","sources":["../src/capability.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AAU3E,OAAO,KAAK,EAAE,oBAAoB,EAA6C,MAAM,YAAY,CAAC;AA6KlG,gEAAgE;AAChE,wBAAgB,oCAAoC,CAAC,OAAO,EAAE,oBAAoB,GAAG,2BAA2B,CAmD/G","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport type { CapabilityPluginSyncFactory } from \"@agent-forge/plugin-sdk\";\nimport { validatePluginErrorV1 } from \"@agent-forge/plugin-sdk\";\nimport { Type } from \"typebox\";\nimport { Value } from \"typebox/value\";\nimport {\n\tPROCESS_EXEC_MAX_OPERATION_ID_CHARS_V1,\n\tPROCESS_EXEC_MAX_OUTPUT_BYTES_V1,\n\tPROCESS_EXEC_MAX_PREVIEW_BYTES_V1,\n\tsanitizeProcessTextV1,\n} from \"./node-adapter.ts\";\nimport type { ProcessExecAdapterV1, ProcessExecRequestV1, ProcessExecResultV1 } from \"./types.ts\";\n\nconst requestSchema = Type.Object(\n\t{\n\t\tcommand: Type.String({ minLength: 1, maxLength: 512, pattern: \"^[^\\\\u0000\\\\r\\\\n]+$\" }),\n\t\targs: Type.Array(Type.String({ maxLength: 4096, pattern: \"^[^\\\\u0000\\\\r\\\\n]*$\" }), { maxItems: 256 }),\n\t\ttimeoutMs: Type.Optional(Type.Integer({ minimum: 1, maximum: 120_000 })),\n\t},\n\t{ additionalProperties: false },\n);\nconst inputSchema = Type.Object({ request: requestSchema }, { additionalProperties: false });\n\nconst INVALID_ERROR = Symbol(\"process-exec-invalid-error\");\n\nfunction generatedOperationId(): string {\n\treturn `profile-runtime-tool-call-${randomUUID()}`;\n}\n\nfunction objectInput(first: unknown, second: unknown): Record<string, unknown> {\n\tconst value = second === undefined ? first : second;\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value))\n\t\tthrow new Error(\"Process input must be an object\");\n\treturn value as Record<string, unknown>;\n}\n\nfunction operationIdFor(first: unknown, second: unknown): string {\n\tconst explicitOperationId = second === undefined ? undefined : first;\n\treturn typeof explicitOperationId === \"string\" &&\n\t\texplicitOperationId.trim() !== \"\" &&\n\t\texplicitOperationId.length <= PROCESS_EXEC_MAX_OPERATION_ID_CHARS_V1 &&\n\t\t![...explicitOperationId].some((character) => /[\\u0000-\\u001f\\u007f]/u.test(character))\n\t\t? explicitOperationId\n\t\t: generatedOperationId();\n}\n\nfunction invocation(\n\tfirst: unknown,\n\tsecond: unknown,\n): { readonly input: Record<string, unknown>; readonly operationId: string } {\n\treturn {\n\t\tinput: objectInput(first, second),\n\t\toperationId: operationIdFor(first, second),\n\t};\n}\n\nfunction signalFrom(value: unknown): AbortSignal | undefined {\n\treturn value instanceof AbortSignal ? value : undefined;\n}\n\nfunction cancelled(operationId: string): ProcessExecResultV1 {\n\treturn {\n\t\tversion: 1,\n\t\toperationId,\n\t\tstatus: \"cancelled\",\n\t\tsummary: \"Process execution was cancelled\",\n\t\tstdoutBytes: 0,\n\t\tstderrBytes: 0,\n\t\tstdoutPreview: \"\",\n\t\tstderrPreview: \"\",\n\t\tstdoutTruncated: false,\n\t\tstderrTruncated: false,\n\t\terror: { version: 1, code: \"cancelled\", message: \"Process execution was cancelled\" },\n\t};\n}\n\nfunction malformed(operationId: string): ProcessExecResultV1 {\n\treturn {\n\t\t...cancelled(operationId),\n\t\tstatus: \"failed\",\n\t\tsummary: \"Process adapter returned an invalid result\",\n\t\terror: { version: 1, code: \"adapter_failed\", message: \"Process adapter returned an invalid result\" },\n\t};\n}\n\nfunction invalidInput(operationId: string): ProcessExecResultV1 {\n\treturn {\n\t\t...cancelled(operationId),\n\t\tstatus: \"failed\",\n\t\tsummary: \"Process request was invalid\",\n\t\terror: { version: 1, code: \"invalid_input\", message: \"Process request was invalid\" },\n\t};\n}\n\nfunction boundedError(value: unknown): ProcessExecResultV1[\"error\"] | typeof INVALID_ERROR | undefined {\n\tif (value === undefined) return undefined;\n\ttry {\n\t\tconst error = validatePluginErrorV1(value, \"Process adapter error\");\n\t\tif (\n\t\t\terror.code.length > 128 ||\n\t\t\terror.message.length > 512 ||\n\t\t\t(error.causeCode !== undefined && error.causeCode.length > 128)\n\t\t)\n\t\t\treturn INVALID_ERROR;\n\t\treturn {\n\t\t\tversion: 1,\n\t\t\tcode: error.code,\n\t\t\tmessage: sanitizeProcessTextV1(error.message, 512),\n\t\t\t...(error.causeCode === undefined ? {} : { causeCode: error.causeCode }),\n\t\t};\n\t} catch {\n\t\treturn INVALID_ERROR;\n\t}\n}\n\nfunction boundedResult(value: unknown, operationId: string): ProcessExecResultV1 {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) return malformed(operationId);\n\tconst result = value as Record<string, unknown>;\n\tconst exitCode = result.exitCode;\n\tconst stdoutBytes = typeof result.stdoutBytes === \"number\" ? result.stdoutBytes : undefined;\n\tconst stderrBytes = typeof result.stderrBytes === \"number\" ? result.stderrBytes : undefined;\n\tif (\n\t\tresult.version !== 1 ||\n\t\tresult.operationId !== operationId ||\n\t\ttypeof result.status !== \"string\" ||\n\t\t![\"succeeded\", \"failed\", \"cancelled\", \"needs_user\", \"unsupported\"].includes(result.status) ||\n\t\ttypeof result.summary !== \"string\" ||\n\t\tresult.summary.length > 2048 ||\n\t\tstdoutBytes === undefined ||\n\t\tstderrBytes === undefined ||\n\t\t!Number.isSafeInteger(stdoutBytes) ||\n\t\t!Number.isSafeInteger(stderrBytes) ||\n\t\tstdoutBytes < 0 ||\n\t\tstderrBytes < 0 ||\n\t\tstdoutBytes > PROCESS_EXEC_MAX_OUTPUT_BYTES_V1 ||\n\t\tstderrBytes > PROCESS_EXEC_MAX_OUTPUT_BYTES_V1 ||\n\t\ttypeof result.stdoutPreview !== \"string\" ||\n\t\ttypeof result.stderrPreview !== \"string\" ||\n\t\tresult.stdoutPreview.length > PROCESS_EXEC_MAX_PREVIEW_BYTES_V1 ||\n\t\tresult.stderrPreview.length > PROCESS_EXEC_MAX_PREVIEW_BYTES_V1 ||\n\t\t(stdoutBytes === 0 && result.stdoutPreview.length !== 0) ||\n\t\t(stderrBytes === 0 && result.stderrPreview.length !== 0) ||\n\t\ttypeof result.stdoutTruncated !== \"boolean\" ||\n\t\ttypeof result.stderrTruncated !== \"boolean\"\n\t)\n\t\treturn malformed(operationId);\n\tconst status = result.status as ProcessExecResultV1[\"status\"];\n\tif (\n\t\t(exitCode !== undefined && (typeof exitCode !== \"number\" || !Number.isSafeInteger(exitCode) || exitCode < 0)) ||\n\t\t(status === \"succeeded\" && result.error !== undefined)\n\t)\n\t\treturn malformed(operationId);\n\tconst error = boundedError(result.error);\n\tif (error === INVALID_ERROR || (status !== \"succeeded\" && error === undefined)) return malformed(operationId);\n\tconst projected: ProcessExecResultV1 = {\n\t\tversion: 1,\n\t\toperationId,\n\t\tstatus,\n\t\tsummary: sanitizeProcessTextV1(result.summary as string, 2048),\n\t\t...(exitCode === undefined ? {} : { exitCode: exitCode as number }),\n\t\tstdoutBytes,\n\t\tstderrBytes,\n\t\tstdoutPreview: sanitizeProcessTextV1(result.stdoutPreview as string),\n\t\tstderrPreview: sanitizeProcessTextV1(result.stderrPreview as string),\n\t\tstdoutTruncated: result.stdoutTruncated as boolean,\n\t\tstderrTruncated: result.stderrTruncated as boolean,\n\t\t...(error === undefined ? {} : { error }),\n\t};\n\tif (new TextEncoder().encode(JSON.stringify(projected)).byteLength > 64 * 1024) return malformed(operationId);\n\treturn projected;\n}\n\nasync function runWithCancellation(\n\trun: () => Promise<ProcessExecResultV1>,\n\tsignal: AbortSignal | undefined,\n\toperationId: string,\n): Promise<ProcessExecResultV1> {\n\t// The adapter owns cancellation and must settle after it has drained its\n\t// child/process resources. Do not race the adapter with a local cancellation\n\t// promise: that would return before the host has finished cleanup.\n\tconst output = await run();\n\treturn signal?.aborted && output.status !== \"cancelled\" ? cancelled(operationId) : output;\n}\n\n/** Registers process execution only for a full-control host. */\nexport function createProcessExecCapabilityFactoryV1(runtime: ProcessExecAdapterV1): CapabilityPluginSyncFactory {\n\treturn (api) => {\n\t\tif (api.host.mode === \"readonly\") return;\n\t\tapi.registerTool({\n\t\t\tname: \"process_exec\",\n\t\t\tlabel: \"Process exec\",\n\t\t\tdescription: \"Run an argv command through the selected host process adapter with bounded output\",\n\t\t\tparameters: inputSchema,\n\t\t\texecute: async (first: unknown, second?: unknown, third?: unknown) => {\n\t\t\t\tlet invocationResult: { readonly input: Record<string, unknown>; readonly operationId: string };\n\t\t\t\ttry {\n\t\t\t\t\tinvocationResult = invocation(first, second);\n\t\t\t\t} catch {\n\t\t\t\t\treturn invalidInput(operationIdFor(first, second));\n\t\t\t\t}\n\t\t\t\tconst { input, operationId } = invocationResult;\n\t\t\t\tconst signal = signalFrom(third);\n\t\t\t\tif (signal?.aborted) return cancelled(operationId);\n\t\t\t\tlet request: ProcessExecRequestV1;\n\t\t\t\ttry {\n\t\t\t\t\tif (!Value.Check(inputSchema, input)) return invalidInput(operationId);\n\t\t\t\t\tconst requestInput = objectInput(input.request, undefined);\n\t\t\t\t\tif (\n\t\t\t\t\t\ttypeof requestInput.command !== \"string\" ||\n\t\t\t\t\t\trequestInput.command.trim() === \"\" ||\n\t\t\t\t\t\t!Array.isArray(requestInput.args) ||\n\t\t\t\t\t\trequestInput.args.some((arg) => typeof arg !== \"string\")\n\t\t\t\t\t)\n\t\t\t\t\t\treturn invalidInput(operationId);\n\t\t\t\t\tconst command = requestInput.command as string;\n\t\t\t\t\tconst args = requestInput.args as string[];\n\t\t\t\t\tconst timeoutMs = requestInput.timeoutMs as number | undefined;\n\t\t\t\t\trequest = {\n\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\toperationId,\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\targs,\n\t\t\t\t\t\t...(timeoutMs === undefined ? {} : { timeoutMs }),\n\t\t\t\t\t};\n\t\t\t\t} catch {\n\t\t\t\t\treturn invalidInput(operationId);\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tconst output = await runWithCancellation(() => runtime.run(request, signal), signal, operationId);\n\t\t\t\t\treturn boundedResult(output, operationId);\n\t\t\t\t} catch {\n\t\t\t\t\treturn signal?.aborted ? cancelled(operationId) : malformed(operationId);\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t};\n}\n"]}
1
+ {"version":3,"file":"capability.d.ts","sourceRoot":"","sources":["../src/capability.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AAU3E,OAAO,KAAK,EAAE,oBAAoB,EAA6C,MAAM,YAAY,CAAC;AAiLlG,gEAAgE;AAChE,wBAAgB,oCAAoC,CAAC,OAAO,EAAE,oBAAoB,GAAG,2BAA2B,CAmD/G","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport type { CapabilityPluginSyncFactory } from \"@agent-forge/plugin-sdk\";\nimport { validatePluginErrorV1 } from \"@agent-forge/plugin-sdk\";\nimport { Type } from \"typebox\";\nimport { Value } from \"typebox/value\";\nimport {\n\tPROCESS_EXEC_MAX_OPERATION_ID_CHARS_V1,\n\tPROCESS_EXEC_MAX_OUTPUT_BYTES_V1,\n\tPROCESS_EXEC_MAX_PREVIEW_BYTES_V1,\n\tsanitizeProcessTextV1,\n} from \"./node-adapter.ts\";\nimport type { ProcessExecAdapterV1, ProcessExecRequestV1, ProcessExecResultV1 } from \"./types.ts\";\n\nconst requestSchema = Type.Object(\n\t{\n\t\tcommand: Type.String({ minLength: 1, maxLength: 512, pattern: \"^[^\\\\u0000\\\\r\\\\n]+$\" }),\n\t\targs: Type.Array(Type.String({ maxLength: 4096, pattern: \"^[^\\\\u0000\\\\r\\\\n]*$\" }), { maxItems: 256 }),\n\t\ttimeoutMs: Type.Optional(Type.Integer({ minimum: 1, maximum: 120_000 })),\n\t},\n\t{ additionalProperties: false },\n);\nconst inputSchema = Type.Object({ request: requestSchema }, { additionalProperties: false });\n\nconst INVALID_ERROR = Symbol(\"process-exec-invalid-error\");\n\nfunction generatedOperationId(): string {\n\treturn `profile-runtime-tool-call-${randomUUID()}`;\n}\n\nfunction objectInput(first: unknown, second: unknown): Record<string, unknown> {\n\t// Shape-based dual-convention read (aligned with subagent-delegate): the\n\t// runtime invoke face passes the input object first and the host\n\t// CapabilityToolContext second; the agent tool face passes the tool call\n\t// id (a string) first and the params object second.\n\tconst value = first !== null && typeof first === \"object\" && !Array.isArray(first) ? first : second;\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value))\n\t\tthrow new Error(\"Process input must be an object\");\n\treturn value as Record<string, unknown>;\n}\n\nfunction operationIdFor(first: unknown, second: unknown): string {\n\tconst explicitOperationId = typeof first === \"string\" && second !== undefined ? first : undefined;\n\treturn typeof explicitOperationId === \"string\" &&\n\t\texplicitOperationId.trim() !== \"\" &&\n\t\texplicitOperationId.length <= PROCESS_EXEC_MAX_OPERATION_ID_CHARS_V1 &&\n\t\t![...explicitOperationId].some((character) => /[\\u0000-\\u001f\\u007f]/u.test(character))\n\t\t? explicitOperationId\n\t\t: generatedOperationId();\n}\n\nfunction invocation(\n\tfirst: unknown,\n\tsecond: unknown,\n): { readonly input: Record<string, unknown>; readonly operationId: string } {\n\treturn {\n\t\tinput: objectInput(first, second),\n\t\toperationId: operationIdFor(first, second),\n\t};\n}\n\nfunction signalFrom(value: unknown): AbortSignal | undefined {\n\treturn value instanceof AbortSignal ? value : undefined;\n}\n\nfunction cancelled(operationId: string): ProcessExecResultV1 {\n\treturn {\n\t\tversion: 1,\n\t\toperationId,\n\t\tstatus: \"cancelled\",\n\t\tsummary: \"Process execution was cancelled\",\n\t\tstdoutBytes: 0,\n\t\tstderrBytes: 0,\n\t\tstdoutPreview: \"\",\n\t\tstderrPreview: \"\",\n\t\tstdoutTruncated: false,\n\t\tstderrTruncated: false,\n\t\terror: { version: 1, code: \"cancelled\", message: \"Process execution was cancelled\" },\n\t};\n}\n\nfunction malformed(operationId: string): ProcessExecResultV1 {\n\treturn {\n\t\t...cancelled(operationId),\n\t\tstatus: \"failed\",\n\t\tsummary: \"Process adapter returned an invalid result\",\n\t\terror: { version: 1, code: \"adapter_failed\", message: \"Process adapter returned an invalid result\" },\n\t};\n}\n\nfunction invalidInput(operationId: string): ProcessExecResultV1 {\n\treturn {\n\t\t...cancelled(operationId),\n\t\tstatus: \"failed\",\n\t\tsummary: \"Process request was invalid\",\n\t\terror: { version: 1, code: \"invalid_input\", message: \"Process request was invalid\" },\n\t};\n}\n\nfunction boundedError(value: unknown): ProcessExecResultV1[\"error\"] | typeof INVALID_ERROR | undefined {\n\tif (value === undefined) return undefined;\n\ttry {\n\t\tconst error = validatePluginErrorV1(value, \"Process adapter error\");\n\t\tif (\n\t\t\terror.code.length > 128 ||\n\t\t\terror.message.length > 512 ||\n\t\t\t(error.causeCode !== undefined && error.causeCode.length > 128)\n\t\t)\n\t\t\treturn INVALID_ERROR;\n\t\treturn {\n\t\t\tversion: 1,\n\t\t\tcode: error.code,\n\t\t\tmessage: sanitizeProcessTextV1(error.message, 512),\n\t\t\t...(error.causeCode === undefined ? {} : { causeCode: error.causeCode }),\n\t\t};\n\t} catch {\n\t\treturn INVALID_ERROR;\n\t}\n}\n\nfunction boundedResult(value: unknown, operationId: string): ProcessExecResultV1 {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) return malformed(operationId);\n\tconst result = value as Record<string, unknown>;\n\tconst exitCode = result.exitCode;\n\tconst stdoutBytes = typeof result.stdoutBytes === \"number\" ? result.stdoutBytes : undefined;\n\tconst stderrBytes = typeof result.stderrBytes === \"number\" ? result.stderrBytes : undefined;\n\tif (\n\t\tresult.version !== 1 ||\n\t\tresult.operationId !== operationId ||\n\t\ttypeof result.status !== \"string\" ||\n\t\t![\"succeeded\", \"failed\", \"cancelled\", \"needs_user\", \"unsupported\"].includes(result.status) ||\n\t\ttypeof result.summary !== \"string\" ||\n\t\tresult.summary.length > 2048 ||\n\t\tstdoutBytes === undefined ||\n\t\tstderrBytes === undefined ||\n\t\t!Number.isSafeInteger(stdoutBytes) ||\n\t\t!Number.isSafeInteger(stderrBytes) ||\n\t\tstdoutBytes < 0 ||\n\t\tstderrBytes < 0 ||\n\t\tstdoutBytes > PROCESS_EXEC_MAX_OUTPUT_BYTES_V1 ||\n\t\tstderrBytes > PROCESS_EXEC_MAX_OUTPUT_BYTES_V1 ||\n\t\ttypeof result.stdoutPreview !== \"string\" ||\n\t\ttypeof result.stderrPreview !== \"string\" ||\n\t\tresult.stdoutPreview.length > PROCESS_EXEC_MAX_PREVIEW_BYTES_V1 ||\n\t\tresult.stderrPreview.length > PROCESS_EXEC_MAX_PREVIEW_BYTES_V1 ||\n\t\t(stdoutBytes === 0 && result.stdoutPreview.length !== 0) ||\n\t\t(stderrBytes === 0 && result.stderrPreview.length !== 0) ||\n\t\ttypeof result.stdoutTruncated !== \"boolean\" ||\n\t\ttypeof result.stderrTruncated !== \"boolean\"\n\t)\n\t\treturn malformed(operationId);\n\tconst status = result.status as ProcessExecResultV1[\"status\"];\n\tif (\n\t\t(exitCode !== undefined && (typeof exitCode !== \"number\" || !Number.isSafeInteger(exitCode) || exitCode < 0)) ||\n\t\t(status === \"succeeded\" && result.error !== undefined)\n\t)\n\t\treturn malformed(operationId);\n\tconst error = boundedError(result.error);\n\tif (error === INVALID_ERROR || (status !== \"succeeded\" && error === undefined)) return malformed(operationId);\n\tconst projected: ProcessExecResultV1 = {\n\t\tversion: 1,\n\t\toperationId,\n\t\tstatus,\n\t\tsummary: sanitizeProcessTextV1(result.summary as string, 2048),\n\t\t...(exitCode === undefined ? {} : { exitCode: exitCode as number }),\n\t\tstdoutBytes,\n\t\tstderrBytes,\n\t\tstdoutPreview: sanitizeProcessTextV1(result.stdoutPreview as string),\n\t\tstderrPreview: sanitizeProcessTextV1(result.stderrPreview as string),\n\t\tstdoutTruncated: result.stdoutTruncated as boolean,\n\t\tstderrTruncated: result.stderrTruncated as boolean,\n\t\t...(error === undefined ? {} : { error }),\n\t};\n\tif (new TextEncoder().encode(JSON.stringify(projected)).byteLength > 64 * 1024) return malformed(operationId);\n\treturn projected;\n}\n\nasync function runWithCancellation(\n\trun: () => Promise<ProcessExecResultV1>,\n\tsignal: AbortSignal | undefined,\n\toperationId: string,\n): Promise<ProcessExecResultV1> {\n\t// The adapter owns cancellation and must settle after it has drained its\n\t// child/process resources. Do not race the adapter with a local cancellation\n\t// promise: that would return before the host has finished cleanup.\n\tconst output = await run();\n\treturn signal?.aborted && output.status !== \"cancelled\" ? cancelled(operationId) : output;\n}\n\n/** Registers process execution only for a full-control host. */\nexport function createProcessExecCapabilityFactoryV1(runtime: ProcessExecAdapterV1): CapabilityPluginSyncFactory {\n\treturn (api) => {\n\t\tif (api.host.mode === \"readonly\") return;\n\t\tapi.registerTool({\n\t\t\tname: \"process_exec\",\n\t\t\tlabel: \"Process exec\",\n\t\t\tdescription: \"Run an argv command through the selected host process adapter with bounded output\",\n\t\t\tparameters: inputSchema,\n\t\t\texecute: async (first: unknown, second?: unknown, third?: unknown) => {\n\t\t\t\tlet invocationResult: { readonly input: Record<string, unknown>; readonly operationId: string };\n\t\t\t\ttry {\n\t\t\t\t\tinvocationResult = invocation(first, second);\n\t\t\t\t} catch {\n\t\t\t\t\treturn invalidInput(operationIdFor(first, second));\n\t\t\t\t}\n\t\t\t\tconst { input, operationId } = invocationResult;\n\t\t\t\tconst signal = signalFrom(third);\n\t\t\t\tif (signal?.aborted) return cancelled(operationId);\n\t\t\t\tlet request: ProcessExecRequestV1;\n\t\t\t\ttry {\n\t\t\t\t\tif (!Value.Check(inputSchema, input)) return invalidInput(operationId);\n\t\t\t\t\tconst requestInput = objectInput(input.request, undefined);\n\t\t\t\t\tif (\n\t\t\t\t\t\ttypeof requestInput.command !== \"string\" ||\n\t\t\t\t\t\trequestInput.command.trim() === \"\" ||\n\t\t\t\t\t\t!Array.isArray(requestInput.args) ||\n\t\t\t\t\t\trequestInput.args.some((arg) => typeof arg !== \"string\")\n\t\t\t\t\t)\n\t\t\t\t\t\treturn invalidInput(operationId);\n\t\t\t\t\tconst command = requestInput.command as string;\n\t\t\t\t\tconst args = requestInput.args as string[];\n\t\t\t\t\tconst timeoutMs = requestInput.timeoutMs as number | undefined;\n\t\t\t\t\trequest = {\n\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\toperationId,\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\targs,\n\t\t\t\t\t\t...(timeoutMs === undefined ? {} : { timeoutMs }),\n\t\t\t\t\t};\n\t\t\t\t} catch {\n\t\t\t\t\treturn invalidInput(operationId);\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tconst output = await runWithCancellation(() => runtime.run(request, signal), signal, operationId);\n\t\t\t\t\treturn boundedResult(output, operationId);\n\t\t\t\t} catch {\n\t\t\t\t\treturn signal?.aborted ? cancelled(operationId) : malformed(operationId);\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t};\n}\n"]}
@@ -14,13 +14,17 @@ function generatedOperationId() {
14
14
  return `profile-runtime-tool-call-${randomUUID()}`;
15
15
  }
16
16
  function objectInput(first, second) {
17
- const value = second === undefined ? first : second;
17
+ // Shape-based dual-convention read (aligned with subagent-delegate): the
18
+ // runtime invoke face passes the input object first and the host
19
+ // CapabilityToolContext second; the agent tool face passes the tool call
20
+ // id (a string) first and the params object second.
21
+ const value = first !== null && typeof first === "object" && !Array.isArray(first) ? first : second;
18
22
  if (value === null || typeof value !== "object" || Array.isArray(value))
19
23
  throw new Error("Process input must be an object");
20
24
  return value;
21
25
  }
22
26
  function operationIdFor(first, second) {
23
- const explicitOperationId = second === undefined ? undefined : first;
27
+ const explicitOperationId = typeof first === "string" && second !== undefined ? first : undefined;
24
28
  return typeof explicitOperationId === "string" &&
25
29
  explicitOperationId.trim() !== "" &&
26
30
  explicitOperationId.length <= PROCESS_EXEC_MAX_OPERATION_ID_CHARS_V1 &&
@@ -1 +1 @@
1
- {"version":3,"file":"capability.js","sourceRoot":"","sources":["../src/capability.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport type { CapabilityPluginSyncFactory } from \"@agent-forge/plugin-sdk\";\nimport { validatePluginErrorV1 } from \"@agent-forge/plugin-sdk\";\nimport { Type } from \"typebox\";\nimport { Value } from \"typebox/value\";\nimport {\n\tPROCESS_EXEC_MAX_OPERATION_ID_CHARS_V1,\n\tPROCESS_EXEC_MAX_OUTPUT_BYTES_V1,\n\tPROCESS_EXEC_MAX_PREVIEW_BYTES_V1,\n\tsanitizeProcessTextV1,\n} from \"./node-adapter.ts\";\nimport type { ProcessExecAdapterV1, ProcessExecRequestV1, ProcessExecResultV1 } from \"./types.ts\";\n\nconst requestSchema = Type.Object(\n\t{\n\t\tcommand: Type.String({ minLength: 1, maxLength: 512, pattern: \"^[^\\\\u0000\\\\r\\\\n]+$\" }),\n\t\targs: Type.Array(Type.String({ maxLength: 4096, pattern: \"^[^\\\\u0000\\\\r\\\\n]*$\" }), { maxItems: 256 }),\n\t\ttimeoutMs: Type.Optional(Type.Integer({ minimum: 1, maximum: 120_000 })),\n\t},\n\t{ additionalProperties: false },\n);\nconst inputSchema = Type.Object({ request: requestSchema }, { additionalProperties: false });\n\nconst INVALID_ERROR = Symbol(\"process-exec-invalid-error\");\n\nfunction generatedOperationId(): string {\n\treturn `profile-runtime-tool-call-${randomUUID()}`;\n}\n\nfunction objectInput(first: unknown, second: unknown): Record<string, unknown> {\n\tconst value = second === undefined ? first : second;\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value))\n\t\tthrow new Error(\"Process input must be an object\");\n\treturn value as Record<string, unknown>;\n}\n\nfunction operationIdFor(first: unknown, second: unknown): string {\n\tconst explicitOperationId = second === undefined ? undefined : first;\n\treturn typeof explicitOperationId === \"string\" &&\n\t\texplicitOperationId.trim() !== \"\" &&\n\t\texplicitOperationId.length <= PROCESS_EXEC_MAX_OPERATION_ID_CHARS_V1 &&\n\t\t![...explicitOperationId].some((character) => /[\\u0000-\\u001f\\u007f]/u.test(character))\n\t\t? explicitOperationId\n\t\t: generatedOperationId();\n}\n\nfunction invocation(\n\tfirst: unknown,\n\tsecond: unknown,\n): { readonly input: Record<string, unknown>; readonly operationId: string } {\n\treturn {\n\t\tinput: objectInput(first, second),\n\t\toperationId: operationIdFor(first, second),\n\t};\n}\n\nfunction signalFrom(value: unknown): AbortSignal | undefined {\n\treturn value instanceof AbortSignal ? value : undefined;\n}\n\nfunction cancelled(operationId: string): ProcessExecResultV1 {\n\treturn {\n\t\tversion: 1,\n\t\toperationId,\n\t\tstatus: \"cancelled\",\n\t\tsummary: \"Process execution was cancelled\",\n\t\tstdoutBytes: 0,\n\t\tstderrBytes: 0,\n\t\tstdoutPreview: \"\",\n\t\tstderrPreview: \"\",\n\t\tstdoutTruncated: false,\n\t\tstderrTruncated: false,\n\t\terror: { version: 1, code: \"cancelled\", message: \"Process execution was cancelled\" },\n\t};\n}\n\nfunction malformed(operationId: string): ProcessExecResultV1 {\n\treturn {\n\t\t...cancelled(operationId),\n\t\tstatus: \"failed\",\n\t\tsummary: \"Process adapter returned an invalid result\",\n\t\terror: { version: 1, code: \"adapter_failed\", message: \"Process adapter returned an invalid result\" },\n\t};\n}\n\nfunction invalidInput(operationId: string): ProcessExecResultV1 {\n\treturn {\n\t\t...cancelled(operationId),\n\t\tstatus: \"failed\",\n\t\tsummary: \"Process request was invalid\",\n\t\terror: { version: 1, code: \"invalid_input\", message: \"Process request was invalid\" },\n\t};\n}\n\nfunction boundedError(value: unknown): ProcessExecResultV1[\"error\"] | typeof INVALID_ERROR | undefined {\n\tif (value === undefined) return undefined;\n\ttry {\n\t\tconst error = validatePluginErrorV1(value, \"Process adapter error\");\n\t\tif (\n\t\t\terror.code.length > 128 ||\n\t\t\terror.message.length > 512 ||\n\t\t\t(error.causeCode !== undefined && error.causeCode.length > 128)\n\t\t)\n\t\t\treturn INVALID_ERROR;\n\t\treturn {\n\t\t\tversion: 1,\n\t\t\tcode: error.code,\n\t\t\tmessage: sanitizeProcessTextV1(error.message, 512),\n\t\t\t...(error.causeCode === undefined ? {} : { causeCode: error.causeCode }),\n\t\t};\n\t} catch {\n\t\treturn INVALID_ERROR;\n\t}\n}\n\nfunction boundedResult(value: unknown, operationId: string): ProcessExecResultV1 {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) return malformed(operationId);\n\tconst result = value as Record<string, unknown>;\n\tconst exitCode = result.exitCode;\n\tconst stdoutBytes = typeof result.stdoutBytes === \"number\" ? result.stdoutBytes : undefined;\n\tconst stderrBytes = typeof result.stderrBytes === \"number\" ? result.stderrBytes : undefined;\n\tif (\n\t\tresult.version !== 1 ||\n\t\tresult.operationId !== operationId ||\n\t\ttypeof result.status !== \"string\" ||\n\t\t![\"succeeded\", \"failed\", \"cancelled\", \"needs_user\", \"unsupported\"].includes(result.status) ||\n\t\ttypeof result.summary !== \"string\" ||\n\t\tresult.summary.length > 2048 ||\n\t\tstdoutBytes === undefined ||\n\t\tstderrBytes === undefined ||\n\t\t!Number.isSafeInteger(stdoutBytes) ||\n\t\t!Number.isSafeInteger(stderrBytes) ||\n\t\tstdoutBytes < 0 ||\n\t\tstderrBytes < 0 ||\n\t\tstdoutBytes > PROCESS_EXEC_MAX_OUTPUT_BYTES_V1 ||\n\t\tstderrBytes > PROCESS_EXEC_MAX_OUTPUT_BYTES_V1 ||\n\t\ttypeof result.stdoutPreview !== \"string\" ||\n\t\ttypeof result.stderrPreview !== \"string\" ||\n\t\tresult.stdoutPreview.length > PROCESS_EXEC_MAX_PREVIEW_BYTES_V1 ||\n\t\tresult.stderrPreview.length > PROCESS_EXEC_MAX_PREVIEW_BYTES_V1 ||\n\t\t(stdoutBytes === 0 && result.stdoutPreview.length !== 0) ||\n\t\t(stderrBytes === 0 && result.stderrPreview.length !== 0) ||\n\t\ttypeof result.stdoutTruncated !== \"boolean\" ||\n\t\ttypeof result.stderrTruncated !== \"boolean\"\n\t)\n\t\treturn malformed(operationId);\n\tconst status = result.status as ProcessExecResultV1[\"status\"];\n\tif (\n\t\t(exitCode !== undefined && (typeof exitCode !== \"number\" || !Number.isSafeInteger(exitCode) || exitCode < 0)) ||\n\t\t(status === \"succeeded\" && result.error !== undefined)\n\t)\n\t\treturn malformed(operationId);\n\tconst error = boundedError(result.error);\n\tif (error === INVALID_ERROR || (status !== \"succeeded\" && error === undefined)) return malformed(operationId);\n\tconst projected: ProcessExecResultV1 = {\n\t\tversion: 1,\n\t\toperationId,\n\t\tstatus,\n\t\tsummary: sanitizeProcessTextV1(result.summary as string, 2048),\n\t\t...(exitCode === undefined ? {} : { exitCode: exitCode as number }),\n\t\tstdoutBytes,\n\t\tstderrBytes,\n\t\tstdoutPreview: sanitizeProcessTextV1(result.stdoutPreview as string),\n\t\tstderrPreview: sanitizeProcessTextV1(result.stderrPreview as string),\n\t\tstdoutTruncated: result.stdoutTruncated as boolean,\n\t\tstderrTruncated: result.stderrTruncated as boolean,\n\t\t...(error === undefined ? {} : { error }),\n\t};\n\tif (new TextEncoder().encode(JSON.stringify(projected)).byteLength > 64 * 1024) return malformed(operationId);\n\treturn projected;\n}\n\nasync function runWithCancellation(\n\trun: () => Promise<ProcessExecResultV1>,\n\tsignal: AbortSignal | undefined,\n\toperationId: string,\n): Promise<ProcessExecResultV1> {\n\t// The adapter owns cancellation and must settle after it has drained its\n\t// child/process resources. Do not race the adapter with a local cancellation\n\t// promise: that would return before the host has finished cleanup.\n\tconst output = await run();\n\treturn signal?.aborted && output.status !== \"cancelled\" ? cancelled(operationId) : output;\n}\n\n/** Registers process execution only for a full-control host. */\nexport function createProcessExecCapabilityFactoryV1(runtime: ProcessExecAdapterV1): CapabilityPluginSyncFactory {\n\treturn (api) => {\n\t\tif (api.host.mode === \"readonly\") return;\n\t\tapi.registerTool({\n\t\t\tname: \"process_exec\",\n\t\t\tlabel: \"Process exec\",\n\t\t\tdescription: \"Run an argv command through the selected host process adapter with bounded output\",\n\t\t\tparameters: inputSchema,\n\t\t\texecute: async (first: unknown, second?: unknown, third?: unknown) => {\n\t\t\t\tlet invocationResult: { readonly input: Record<string, unknown>; readonly operationId: string };\n\t\t\t\ttry {\n\t\t\t\t\tinvocationResult = invocation(first, second);\n\t\t\t\t} catch {\n\t\t\t\t\treturn invalidInput(operationIdFor(first, second));\n\t\t\t\t}\n\t\t\t\tconst { input, operationId } = invocationResult;\n\t\t\t\tconst signal = signalFrom(third);\n\t\t\t\tif (signal?.aborted) return cancelled(operationId);\n\t\t\t\tlet request: ProcessExecRequestV1;\n\t\t\t\ttry {\n\t\t\t\t\tif (!Value.Check(inputSchema, input)) return invalidInput(operationId);\n\t\t\t\t\tconst requestInput = objectInput(input.request, undefined);\n\t\t\t\t\tif (\n\t\t\t\t\t\ttypeof requestInput.command !== \"string\" ||\n\t\t\t\t\t\trequestInput.command.trim() === \"\" ||\n\t\t\t\t\t\t!Array.isArray(requestInput.args) ||\n\t\t\t\t\t\trequestInput.args.some((arg) => typeof arg !== \"string\")\n\t\t\t\t\t)\n\t\t\t\t\t\treturn invalidInput(operationId);\n\t\t\t\t\tconst command = requestInput.command as string;\n\t\t\t\t\tconst args = requestInput.args as string[];\n\t\t\t\t\tconst timeoutMs = requestInput.timeoutMs as number | undefined;\n\t\t\t\t\trequest = {\n\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\toperationId,\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\targs,\n\t\t\t\t\t\t...(timeoutMs === undefined ? {} : { timeoutMs }),\n\t\t\t\t\t};\n\t\t\t\t} catch {\n\t\t\t\t\treturn invalidInput(operationId);\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tconst output = await runWithCancellation(() => runtime.run(request, signal), signal, operationId);\n\t\t\t\t\treturn boundedResult(output, operationId);\n\t\t\t\t} catch {\n\t\t\t\t\treturn signal?.aborted ? cancelled(operationId) : malformed(operationId);\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t};\n}\n"]}
1
+ {"version":3,"file":"capability.js","sourceRoot":"","sources":["../src/capability.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport type { CapabilityPluginSyncFactory } from \"@agent-forge/plugin-sdk\";\nimport { validatePluginErrorV1 } from \"@agent-forge/plugin-sdk\";\nimport { Type } from \"typebox\";\nimport { Value } from \"typebox/value\";\nimport {\n\tPROCESS_EXEC_MAX_OPERATION_ID_CHARS_V1,\n\tPROCESS_EXEC_MAX_OUTPUT_BYTES_V1,\n\tPROCESS_EXEC_MAX_PREVIEW_BYTES_V1,\n\tsanitizeProcessTextV1,\n} from \"./node-adapter.ts\";\nimport type { ProcessExecAdapterV1, ProcessExecRequestV1, ProcessExecResultV1 } from \"./types.ts\";\n\nconst requestSchema = Type.Object(\n\t{\n\t\tcommand: Type.String({ minLength: 1, maxLength: 512, pattern: \"^[^\\\\u0000\\\\r\\\\n]+$\" }),\n\t\targs: Type.Array(Type.String({ maxLength: 4096, pattern: \"^[^\\\\u0000\\\\r\\\\n]*$\" }), { maxItems: 256 }),\n\t\ttimeoutMs: Type.Optional(Type.Integer({ minimum: 1, maximum: 120_000 })),\n\t},\n\t{ additionalProperties: false },\n);\nconst inputSchema = Type.Object({ request: requestSchema }, { additionalProperties: false });\n\nconst INVALID_ERROR = Symbol(\"process-exec-invalid-error\");\n\nfunction generatedOperationId(): string {\n\treturn `profile-runtime-tool-call-${randomUUID()}`;\n}\n\nfunction objectInput(first: unknown, second: unknown): Record<string, unknown> {\n\t// Shape-based dual-convention read (aligned with subagent-delegate): the\n\t// runtime invoke face passes the input object first and the host\n\t// CapabilityToolContext second; the agent tool face passes the tool call\n\t// id (a string) first and the params object second.\n\tconst value = first !== null && typeof first === \"object\" && !Array.isArray(first) ? first : second;\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value))\n\t\tthrow new Error(\"Process input must be an object\");\n\treturn value as Record<string, unknown>;\n}\n\nfunction operationIdFor(first: unknown, second: unknown): string {\n\tconst explicitOperationId = typeof first === \"string\" && second !== undefined ? first : undefined;\n\treturn typeof explicitOperationId === \"string\" &&\n\t\texplicitOperationId.trim() !== \"\" &&\n\t\texplicitOperationId.length <= PROCESS_EXEC_MAX_OPERATION_ID_CHARS_V1 &&\n\t\t![...explicitOperationId].some((character) => /[\\u0000-\\u001f\\u007f]/u.test(character))\n\t\t? explicitOperationId\n\t\t: generatedOperationId();\n}\n\nfunction invocation(\n\tfirst: unknown,\n\tsecond: unknown,\n): { readonly input: Record<string, unknown>; readonly operationId: string } {\n\treturn {\n\t\tinput: objectInput(first, second),\n\t\toperationId: operationIdFor(first, second),\n\t};\n}\n\nfunction signalFrom(value: unknown): AbortSignal | undefined {\n\treturn value instanceof AbortSignal ? value : undefined;\n}\n\nfunction cancelled(operationId: string): ProcessExecResultV1 {\n\treturn {\n\t\tversion: 1,\n\t\toperationId,\n\t\tstatus: \"cancelled\",\n\t\tsummary: \"Process execution was cancelled\",\n\t\tstdoutBytes: 0,\n\t\tstderrBytes: 0,\n\t\tstdoutPreview: \"\",\n\t\tstderrPreview: \"\",\n\t\tstdoutTruncated: false,\n\t\tstderrTruncated: false,\n\t\terror: { version: 1, code: \"cancelled\", message: \"Process execution was cancelled\" },\n\t};\n}\n\nfunction malformed(operationId: string): ProcessExecResultV1 {\n\treturn {\n\t\t...cancelled(operationId),\n\t\tstatus: \"failed\",\n\t\tsummary: \"Process adapter returned an invalid result\",\n\t\terror: { version: 1, code: \"adapter_failed\", message: \"Process adapter returned an invalid result\" },\n\t};\n}\n\nfunction invalidInput(operationId: string): ProcessExecResultV1 {\n\treturn {\n\t\t...cancelled(operationId),\n\t\tstatus: \"failed\",\n\t\tsummary: \"Process request was invalid\",\n\t\terror: { version: 1, code: \"invalid_input\", message: \"Process request was invalid\" },\n\t};\n}\n\nfunction boundedError(value: unknown): ProcessExecResultV1[\"error\"] | typeof INVALID_ERROR | undefined {\n\tif (value === undefined) return undefined;\n\ttry {\n\t\tconst error = validatePluginErrorV1(value, \"Process adapter error\");\n\t\tif (\n\t\t\terror.code.length > 128 ||\n\t\t\terror.message.length > 512 ||\n\t\t\t(error.causeCode !== undefined && error.causeCode.length > 128)\n\t\t)\n\t\t\treturn INVALID_ERROR;\n\t\treturn {\n\t\t\tversion: 1,\n\t\t\tcode: error.code,\n\t\t\tmessage: sanitizeProcessTextV1(error.message, 512),\n\t\t\t...(error.causeCode === undefined ? {} : { causeCode: error.causeCode }),\n\t\t};\n\t} catch {\n\t\treturn INVALID_ERROR;\n\t}\n}\n\nfunction boundedResult(value: unknown, operationId: string): ProcessExecResultV1 {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) return malformed(operationId);\n\tconst result = value as Record<string, unknown>;\n\tconst exitCode = result.exitCode;\n\tconst stdoutBytes = typeof result.stdoutBytes === \"number\" ? result.stdoutBytes : undefined;\n\tconst stderrBytes = typeof result.stderrBytes === \"number\" ? result.stderrBytes : undefined;\n\tif (\n\t\tresult.version !== 1 ||\n\t\tresult.operationId !== operationId ||\n\t\ttypeof result.status !== \"string\" ||\n\t\t![\"succeeded\", \"failed\", \"cancelled\", \"needs_user\", \"unsupported\"].includes(result.status) ||\n\t\ttypeof result.summary !== \"string\" ||\n\t\tresult.summary.length > 2048 ||\n\t\tstdoutBytes === undefined ||\n\t\tstderrBytes === undefined ||\n\t\t!Number.isSafeInteger(stdoutBytes) ||\n\t\t!Number.isSafeInteger(stderrBytes) ||\n\t\tstdoutBytes < 0 ||\n\t\tstderrBytes < 0 ||\n\t\tstdoutBytes > PROCESS_EXEC_MAX_OUTPUT_BYTES_V1 ||\n\t\tstderrBytes > PROCESS_EXEC_MAX_OUTPUT_BYTES_V1 ||\n\t\ttypeof result.stdoutPreview !== \"string\" ||\n\t\ttypeof result.stderrPreview !== \"string\" ||\n\t\tresult.stdoutPreview.length > PROCESS_EXEC_MAX_PREVIEW_BYTES_V1 ||\n\t\tresult.stderrPreview.length > PROCESS_EXEC_MAX_PREVIEW_BYTES_V1 ||\n\t\t(stdoutBytes === 0 && result.stdoutPreview.length !== 0) ||\n\t\t(stderrBytes === 0 && result.stderrPreview.length !== 0) ||\n\t\ttypeof result.stdoutTruncated !== \"boolean\" ||\n\t\ttypeof result.stderrTruncated !== \"boolean\"\n\t)\n\t\treturn malformed(operationId);\n\tconst status = result.status as ProcessExecResultV1[\"status\"];\n\tif (\n\t\t(exitCode !== undefined && (typeof exitCode !== \"number\" || !Number.isSafeInteger(exitCode) || exitCode < 0)) ||\n\t\t(status === \"succeeded\" && result.error !== undefined)\n\t)\n\t\treturn malformed(operationId);\n\tconst error = boundedError(result.error);\n\tif (error === INVALID_ERROR || (status !== \"succeeded\" && error === undefined)) return malformed(operationId);\n\tconst projected: ProcessExecResultV1 = {\n\t\tversion: 1,\n\t\toperationId,\n\t\tstatus,\n\t\tsummary: sanitizeProcessTextV1(result.summary as string, 2048),\n\t\t...(exitCode === undefined ? {} : { exitCode: exitCode as number }),\n\t\tstdoutBytes,\n\t\tstderrBytes,\n\t\tstdoutPreview: sanitizeProcessTextV1(result.stdoutPreview as string),\n\t\tstderrPreview: sanitizeProcessTextV1(result.stderrPreview as string),\n\t\tstdoutTruncated: result.stdoutTruncated as boolean,\n\t\tstderrTruncated: result.stderrTruncated as boolean,\n\t\t...(error === undefined ? {} : { error }),\n\t};\n\tif (new TextEncoder().encode(JSON.stringify(projected)).byteLength > 64 * 1024) return malformed(operationId);\n\treturn projected;\n}\n\nasync function runWithCancellation(\n\trun: () => Promise<ProcessExecResultV1>,\n\tsignal: AbortSignal | undefined,\n\toperationId: string,\n): Promise<ProcessExecResultV1> {\n\t// The adapter owns cancellation and must settle after it has drained its\n\t// child/process resources. Do not race the adapter with a local cancellation\n\t// promise: that would return before the host has finished cleanup.\n\tconst output = await run();\n\treturn signal?.aborted && output.status !== \"cancelled\" ? cancelled(operationId) : output;\n}\n\n/** Registers process execution only for a full-control host. */\nexport function createProcessExecCapabilityFactoryV1(runtime: ProcessExecAdapterV1): CapabilityPluginSyncFactory {\n\treturn (api) => {\n\t\tif (api.host.mode === \"readonly\") return;\n\t\tapi.registerTool({\n\t\t\tname: \"process_exec\",\n\t\t\tlabel: \"Process exec\",\n\t\t\tdescription: \"Run an argv command through the selected host process adapter with bounded output\",\n\t\t\tparameters: inputSchema,\n\t\t\texecute: async (first: unknown, second?: unknown, third?: unknown) => {\n\t\t\t\tlet invocationResult: { readonly input: Record<string, unknown>; readonly operationId: string };\n\t\t\t\ttry {\n\t\t\t\t\tinvocationResult = invocation(first, second);\n\t\t\t\t} catch {\n\t\t\t\t\treturn invalidInput(operationIdFor(first, second));\n\t\t\t\t}\n\t\t\t\tconst { input, operationId } = invocationResult;\n\t\t\t\tconst signal = signalFrom(third);\n\t\t\t\tif (signal?.aborted) return cancelled(operationId);\n\t\t\t\tlet request: ProcessExecRequestV1;\n\t\t\t\ttry {\n\t\t\t\t\tif (!Value.Check(inputSchema, input)) return invalidInput(operationId);\n\t\t\t\t\tconst requestInput = objectInput(input.request, undefined);\n\t\t\t\t\tif (\n\t\t\t\t\t\ttypeof requestInput.command !== \"string\" ||\n\t\t\t\t\t\trequestInput.command.trim() === \"\" ||\n\t\t\t\t\t\t!Array.isArray(requestInput.args) ||\n\t\t\t\t\t\trequestInput.args.some((arg) => typeof arg !== \"string\")\n\t\t\t\t\t)\n\t\t\t\t\t\treturn invalidInput(operationId);\n\t\t\t\t\tconst command = requestInput.command as string;\n\t\t\t\t\tconst args = requestInput.args as string[];\n\t\t\t\t\tconst timeoutMs = requestInput.timeoutMs as number | undefined;\n\t\t\t\t\trequest = {\n\t\t\t\t\t\tversion: 1,\n\t\t\t\t\t\toperationId,\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\targs,\n\t\t\t\t\t\t...(timeoutMs === undefined ? {} : { timeoutMs }),\n\t\t\t\t\t};\n\t\t\t\t} catch {\n\t\t\t\t\treturn invalidInput(operationId);\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tconst output = await runWithCancellation(() => runtime.run(request, signal), signal, operationId);\n\t\t\t\t\treturn boundedResult(output, operationId);\n\t\t\t\t} catch {\n\t\t\t\t\treturn signal?.aborted ? cancelled(operationId) : malformed(operationId);\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t};\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-agent-forge/plugin-process-exec",
3
- "version": "0.85.5",
3
+ "version": "0.85.7",
4
4
  "description": "Process execution capability plugin for Agent Forge (full-control process_exec tool)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -44,11 +44,11 @@
44
44
  "node": ">=22.19.0"
45
45
  },
46
46
  "dependencies": {
47
- "@agent-forge/plugin-sdk": "^0.85.5",
47
+ "@agent-forge/plugin-sdk": "^0.85.7",
48
48
  "typebox": "1.3.27"
49
49
  },
50
50
  "devDependencies": {
51
- "@agent-forge/agent-forge": "^0.85.5",
51
+ "@agent-forge/agent-forge": "^0.85.7",
52
52
  "shx": "0.4.0",
53
53
  "vitest": "4.1.9"
54
54
  }
package/plugin.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "agent-forge.plugin.process-exec",
3
- "version": "0.85.5",
3
+ "version": "0.85.7",
4
4
  "apiVersion": "1-draft",
5
5
  "entry": "./dist/entry.js",
6
6
  "hostVersion": ">=0.84.4",