@ai-sdk/code-mode 1.0.21 → 1.0.22
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 +1 -1
- package/dist/continuation-capability.js +5 -0
- package/dist/continuation-capability.js.map +1 -1
- package/dist/errors.js +1 -136
- package/dist/errors.js.map +1 -1
- package/dist/host-interrupt.js +2 -14
- package/dist/host-interrupt.js.map +1 -1
- package/dist/index.d.ts +14 -44
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/interrupt-continuation.js +3 -8
- package/dist/interrupt-continuation.js.map +1 -1
- package/dist/run-code-mode.js +543 -2
- package/dist/run-code-mode.js.map +1 -1
- package/dist/tool-invocation.js +9 -23
- package/dist/tool-invocation.js.map +1 -1
- package/dist/utils/serialization.js +4 -0
- package/dist/utils/serialization.js.map +1 -1
- package/package.json +8 -7
- package/src/continuation-capability.ts +18 -0
- package/src/errors.ts +0 -190
- package/src/host-interrupt.ts +2 -31
- package/src/index.ts +1 -1
- package/src/interrupt-continuation.ts +13 -15
- package/src/run-code-mode.ts +706 -3
- package/src/tool-invocation.ts +9 -23
- package/src/types.ts +38 -68
- package/src/utils/serialization.ts +4 -0
- package/dist/runtime/guest-sources.js +0 -350
- package/dist/runtime/guest-sources.js.map +0 -1
- package/dist/runtime/manager.js +0 -794
- package/dist/runtime/manager.js.map +0 -1
- package/dist/runtime/max-workers.js +0 -40
- package/dist/runtime/max-workers.js.map +0 -1
- package/dist/runtime/protocol.js +0 -1
- package/dist/runtime/protocol.js.map +0 -1
- package/dist/runtime/worker-source.d.ts +0 -11
- package/dist/runtime/worker-source.js +0 -2
- package/dist/utils/options.js +0 -76
- package/dist/utils/options.js.map +0 -1
- package/dist/utils/source-cache.js +0 -77
- package/dist/utils/source-cache.js.map +0 -1
- package/src/runtime/guest-sources.ts +0 -351
- package/src/runtime/manager.ts +0 -963
- package/src/runtime/max-workers.ts +0 -65
- package/src/runtime/protocol.ts +0 -74
- package/src/runtime/worker-source.ts +0 -10
- package/src/runtime/worker.ts +0 -607
- package/src/utils/options.ts +0 -83
- package/src/utils/source-cache.ts +0 -91
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/tool-invocation.ts"],"sourcesContent":["import { asSchema } from 'ai';\nimport { CODE_MODE_TOOL_APPROVAL_KIND } from './approval.js';\nimport {\n CodeModeProtocolError,\n CodeModeToolApprovalDeniedError,\n CodeModeToolApprovalRequiredError,\n CodeModeToolError,\n} from './errors.js';\nimport { isCodeModeHostInterruptSignal } from './host-interrupt.js';\nimport type {\n CodeModeInterruptExecutionContext,\n CodeModeInterruptPayload,\n CodeModeOptions,\n CodeModeToolExecutionOptions,\n CodeModeToolSet,\n} from './types.js';\nimport {\n assertJsonSerializable,\n toJsonPayload,\n} from './utils/serialization.js';\n\nexport type HostToolInvocationResult =\n | { type: 'success'; valueJson: string }\n | {\n type: 'interrupted';\n toolName: string;\n input: unknown;\n toolCallId: string;\n payload: CodeModeInterruptPayload;\n };\n\nexport async function invokeHostTool({\n toolName,\n inputJson,\n tools,\n baseExecutionOptions,\n codeModeOptions,\n maxToolInputBytes,\n maxToolOutputBytes,\n toolCallId,\n codeModeInterrupt,\n skipApproval = false,\n}: {\n toolName: string;\n inputJson: string;\n tools: CodeModeToolSet;\n baseExecutionOptions: CodeModeToolExecutionOptions;\n codeModeOptions: CodeModeOptions;\n maxToolInputBytes: number;\n maxToolOutputBytes: number;\n toolCallId: string;\n codeModeInterrupt?: CodeModeInterruptExecutionContext;\n skipApproval?: boolean;\n}): Promise<HostToolInvocationResult> {\n throwIfAborted(baseExecutionOptions.abortSignal);\n\n const hostTool = tools[toolName];\n if (!hostTool) {\n throw new CodeModeToolError(`Unknown tool: ${toolName}`, {\n toolName,\n availableTools: Object.keys(tools),\n });\n }\n if (hostTool.execute == null) {\n throw new CodeModeToolError(`Tool \"${toolName}\" does not have execute().`, {\n toolName,\n });\n }\n\n const input = inputJson === '' ? undefined : JSON.parse(inputJson);\n assertJsonSerializable(input, maxToolInputBytes, `Tool \"${toolName}\" input`);\n\n const validation = await raceAgainstAbort(\n validateToolInput(hostTool.inputSchema, input),\n baseExecutionOptions.abortSignal,\n );\n if (!validation.success) {\n throw new CodeModeToolError(\n `Invalid input for tool \"${toolName}\": ${validation.error.message}`,\n { toolName, input, cause: validation.error.message },\n );\n }\n\n const executionOptions: CodeModeToolExecutionOptions = {\n ...baseExecutionOptions,\n toolCallId,\n ...(codeModeInterrupt !== undefined ? { codeModeInterrupt } : {}),\n };\n\n const needsApproval =\n !skipApproval &&\n (await raceAgainstAbort(\n requiresApproval(hostTool, validation.value, executionOptions),\n executionOptions.abortSignal,\n ));\n\n if (needsApproval) {\n if (codeModeOptions.approval?.mode === 'interrupt') {\n return {\n type: 'interrupted',\n toolName,\n input: validation.value,\n toolCallId,\n payload: { kind: CODE_MODE_TOOL_APPROVAL_KIND },\n };\n }\n\n const approval = await raceAgainstAbort(\n Promise.resolve(\n codeModeOptions.approval?.onApprovalRequired?.({\n toolName,\n input: validation.value,\n toolCallId,\n }),\n ),\n baseExecutionOptions.abortSignal,\n );\n if (approval === undefined) {\n throw new CodeModeToolApprovalRequiredError(\n toolName,\n validation.value,\n toolCallId,\n );\n }\n const approved =\n typeof approval === 'string'\n ? approval === 'approved'\n : approval?.approved;\n const reason = typeof approval === 'string' ? undefined : approval?.reason;\n if (typeof approved !== 'boolean') {\n throw new CodeModeProtocolError(\n `Tool \"${toolName}\" approval callback returned a malformed approval decision.`,\n { toolName, toolCallId },\n );\n }\n if (reason !== undefined && typeof reason !== 'string') {\n throw new CodeModeProtocolError(\n `Tool \"${toolName}\" approval callback returned a malformed approval reason.`,\n { toolName, toolCallId },\n );\n }\n if (!approved) {\n throw new CodeModeToolApprovalDeniedError(\n toolName,\n validation.value,\n toolCallId,\n reason,\n );\n }\n }\n\n let output: unknown;\n try {\n output = await raceAgainstAbort(\n executeHostTool(hostTool.execute.bind(hostTool), {\n input: validation.value,\n options: executionOptions,\n }),\n executionOptions.abortSignal,\n );\n } catch (error) {\n if (isCodeModeHostInterruptSignal(error)) {\n return {\n type: 'interrupted',\n toolName,\n input: validation.value,\n toolCallId,\n payload: error.payload,\n };\n }\n throw error;\n }\n return {\n type: 'success',\n valueJson: toJsonPayload(\n output,\n maxToolOutputBytes,\n `Tool \"${toolName}\" output`,\n ),\n };\n}\n\nasync function requiresApproval(\n hostTool: CodeModeToolSet[string],\n input: unknown,\n options: CodeModeToolExecutionOptions,\n): Promise<boolean> {\n if (hostTool.needsApproval == null) {\n return false;\n }\n if (typeof hostTool.needsApproval === 'boolean') {\n return hostTool.needsApproval;\n }\n return await hostTool.needsApproval(input as never, options as never);\n}\n\nasync function validateToolInput(\n schema: CodeModeToolSet[string]['inputSchema'],\n input: unknown,\n): Promise<\n { success: true; value: unknown } | { success: false; error: Error }\n> {\n const normalizedSchema = asSchema(schema);\n if (normalizedSchema.validate === undefined) {\n return { success: true, value: input };\n }\n return await normalizedSchema.validate(input);\n}\n\nasync function executeHostTool(\n execute: NonNullable<CodeModeToolSet[string]['execute']>,\n {\n input,\n options,\n }: {\n input: unknown;\n options: CodeModeToolExecutionOptions;\n },\n): Promise<unknown> {\n const output = execute(input as never, options as never);\n if (isAsyncIterable(output)) {\n let finalOutput: unknown;\n for await (const part of output) {\n finalOutput = part;\n }\n return finalOutput;\n }\n return await output;\n}\n\nfunction isAsyncIterable(value: unknown): value is AsyncIterable<unknown> {\n return (\n typeof value === 'object' &&\n value !== null &&\n Symbol.asyncIterator in value &&\n typeof (value as { [Symbol.asyncIterator]?: unknown })[\n Symbol.asyncIterator\n ] === 'function'\n );\n}\n\nasync function raceAgainstAbort<T>(\n operation: Promise<T>,\n abortSignal: AbortSignal | undefined,\n): Promise<T> {\n if (abortSignal === undefined) {\n return await operation;\n }\n throwIfAborted(abortSignal);\n\n let rejectOnAbort!: (reason?: unknown) => void;\n const aborted = new Promise<never>((_resolve, reject) => {\n rejectOnAbort = reject;\n });\n const onAbort = () => {\n rejectOnAbort(abortReason(abortSignal));\n };\n\n abortSignal.addEventListener('abort', onAbort, { once: true });\n if (abortSignal.aborted) {\n onAbort();\n }\n\n try {\n return await Promise.race([operation, aborted]);\n } finally {\n abortSignal.removeEventListener('abort', onAbort);\n }\n}\n\nfunction throwIfAborted(abortSignal: AbortSignal | undefined): void {\n if (abortSignal?.aborted) {\n throw abortReason(abortSignal);\n }\n}\n\nfunction abortReason(abortSignal: AbortSignal): unknown {\n return (\n abortSignal.reason ??\n new DOMException('The operation was aborted.', 'AbortError')\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/tool-invocation.ts"],"sourcesContent":["import { asSchema } from 'ai';\nimport { CODE_MODE_TOOL_APPROVAL_KIND } from './approval.js';\nimport {\n CodeModeProtocolError,\n CodeModeToolApprovalDeniedError,\n CodeModeToolApprovalRequiredError,\n CodeModeToolError,\n} from './errors.js';\nimport type {\n CodeModeInterruptExecutionContext,\n CodeModeInterruptPayload,\n CodeModeOptions,\n CodeModeToolExecutionOptions,\n CodeModeToolSet,\n} from './types.js';\nimport {\n assertJsonSerializable,\n fromJsonPayload,\n toJsonPayload,\n} from './utils/serialization.js';\n\nexport type HostToolInvocationResult =\n | { type: 'success'; valueJson: string }\n | {\n type: 'interrupted';\n toolName: string;\n input: unknown;\n toolCallId: string;\n payload: CodeModeInterruptPayload;\n };\n\nexport async function invokeHostTool({\n toolName,\n inputJson,\n tools,\n baseExecutionOptions,\n codeModeOptions,\n maxToolInputBytes,\n maxToolOutputBytes,\n toolCallId,\n codeModeInterrupt,\n skipApproval = false,\n}: {\n toolName: string;\n inputJson: string;\n tools: CodeModeToolSet;\n baseExecutionOptions: CodeModeToolExecutionOptions;\n codeModeOptions: CodeModeOptions;\n maxToolInputBytes: number;\n maxToolOutputBytes: number;\n toolCallId: string;\n codeModeInterrupt?: CodeModeInterruptExecutionContext;\n skipApproval?: boolean;\n}): Promise<HostToolInvocationResult> {\n throwIfAborted(baseExecutionOptions.abortSignal);\n\n const hostTool = tools[toolName];\n if (!hostTool) {\n throw new CodeModeToolError(`Unknown tool: ${toolName}`, {\n toolName,\n availableTools: Object.keys(tools),\n });\n }\n if (hostTool.execute == null) {\n throw new CodeModeToolError(`Tool \"${toolName}\" does not have execute().`, {\n toolName,\n });\n }\n\n const input = fromJsonPayload(inputJson);\n assertJsonSerializable(input, maxToolInputBytes, `Tool \"${toolName}\" input`);\n\n const validation = await raceAgainstAbort(\n validateToolInput(hostTool.inputSchema, input),\n baseExecutionOptions.abortSignal,\n );\n if (!validation.success) {\n throw new CodeModeToolError(\n `Invalid input for tool \"${toolName}\": ${validation.error.message}`,\n { toolName, input, cause: validation.error.message },\n );\n }\n\n const executionOptions: CodeModeToolExecutionOptions = {\n ...baseExecutionOptions,\n toolCallId,\n ...(codeModeInterrupt !== undefined ? { codeModeInterrupt } : {}),\n };\n\n const needsApproval =\n !skipApproval &&\n (await raceAgainstAbort(\n requiresApproval(hostTool, validation.value, executionOptions),\n executionOptions.abortSignal,\n ));\n\n if (needsApproval) {\n if (codeModeOptions.approval?.mode === 'interrupt') {\n return {\n type: 'interrupted',\n toolName,\n input: validation.value,\n toolCallId,\n payload: { kind: CODE_MODE_TOOL_APPROVAL_KIND },\n };\n }\n\n const approval = await raceAgainstAbort(\n Promise.resolve(\n codeModeOptions.approval?.onApprovalRequired?.({\n toolName,\n input: validation.value,\n toolCallId,\n }),\n ),\n baseExecutionOptions.abortSignal,\n );\n if (approval === undefined) {\n throw new CodeModeToolApprovalRequiredError(\n toolName,\n validation.value,\n toolCallId,\n );\n }\n const approved =\n typeof approval === 'string'\n ? approval === 'approved'\n : approval?.approved;\n const reason = typeof approval === 'string' ? undefined : approval?.reason;\n if (typeof approved !== 'boolean') {\n throw new CodeModeProtocolError(\n `Tool \"${toolName}\" approval callback returned a malformed approval decision.`,\n { toolName, toolCallId },\n );\n }\n if (reason !== undefined && typeof reason !== 'string') {\n throw new CodeModeProtocolError(\n `Tool \"${toolName}\" approval callback returned a malformed approval reason.`,\n { toolName, toolCallId },\n );\n }\n if (!approved) {\n throw new CodeModeToolApprovalDeniedError(\n toolName,\n validation.value,\n toolCallId,\n reason,\n );\n }\n }\n\n const output = await raceAgainstAbort(\n executeHostTool(hostTool.execute.bind(hostTool), {\n input: validation.value,\n options: executionOptions,\n }),\n executionOptions.abortSignal,\n );\n return {\n type: 'success',\n valueJson: toJsonPayload(\n output,\n maxToolOutputBytes,\n `Tool \"${toolName}\" output`,\n ),\n };\n}\n\nasync function requiresApproval(\n hostTool: CodeModeToolSet[string],\n input: unknown,\n options: CodeModeToolExecutionOptions,\n): Promise<boolean> {\n if (hostTool.needsApproval == null) {\n return false;\n }\n if (typeof hostTool.needsApproval === 'boolean') {\n return hostTool.needsApproval;\n }\n return await hostTool.needsApproval(input as never, options as never);\n}\n\nasync function validateToolInput(\n schema: CodeModeToolSet[string]['inputSchema'],\n input: unknown,\n): Promise<\n { success: true; value: unknown } | { success: false; error: Error }\n> {\n const normalizedSchema = asSchema(schema);\n if (normalizedSchema.validate === undefined) {\n return { success: true, value: input };\n }\n return await normalizedSchema.validate(input);\n}\n\nasync function executeHostTool(\n execute: NonNullable<CodeModeToolSet[string]['execute']>,\n {\n input,\n options,\n }: {\n input: unknown;\n options: CodeModeToolExecutionOptions;\n },\n): Promise<unknown> {\n const output = execute(input as never, options as never);\n if (isAsyncIterable(output)) {\n let finalOutput: unknown;\n for await (const part of output) {\n finalOutput = part;\n }\n return finalOutput;\n }\n return await output;\n}\n\nfunction isAsyncIterable(value: unknown): value is AsyncIterable<unknown> {\n return (\n typeof value === 'object' &&\n value !== null &&\n Symbol.asyncIterator in value &&\n typeof (value as { [Symbol.asyncIterator]?: unknown })[\n Symbol.asyncIterator\n ] === 'function'\n );\n}\n\nasync function raceAgainstAbort<T>(\n operation: Promise<T>,\n abortSignal: AbortSignal | undefined,\n): Promise<T> {\n if (abortSignal === undefined) {\n return await operation;\n }\n throwIfAborted(abortSignal);\n\n let rejectOnAbort!: (reason?: unknown) => void;\n const aborted = new Promise<never>((_resolve, reject) => {\n rejectOnAbort = reject;\n });\n const onAbort = () => {\n rejectOnAbort(abortReason(abortSignal));\n };\n\n abortSignal.addEventListener('abort', onAbort, { once: true });\n if (abortSignal.aborted) {\n onAbort();\n }\n\n try {\n return await Promise.race([operation, aborted]);\n } finally {\n abortSignal.removeEventListener('abort', onAbort);\n }\n}\n\nfunction throwIfAborted(abortSignal: AbortSignal | undefined): void {\n if (abortSignal?.aborted) {\n throw abortReason(abortSignal);\n }\n}\n\nfunction abortReason(abortSignal: AbortSignal): unknown {\n return (\n abortSignal.reason ??\n new DOMException('The operation was aborted.', 'AbortError')\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -8,6 +8,9 @@ function toJsonPayload(value, maxBytes, label) {
|
|
|
8
8
|
}
|
|
9
9
|
return toStrictJsonPayload(value, maxBytes, label);
|
|
10
10
|
}
|
|
11
|
+
function fromJsonPayload(valueJson) {
|
|
12
|
+
return valueJson === "" ? void 0 : JSON.parse(valueJson);
|
|
13
|
+
}
|
|
11
14
|
function toStrictJsonPayload(value, maxBytes, label) {
|
|
12
15
|
let encoded;
|
|
13
16
|
try {
|
|
@@ -43,6 +46,7 @@ function getErrorMessage(error) {
|
|
|
43
46
|
export {
|
|
44
47
|
assertJsonPayloadSize,
|
|
45
48
|
assertJsonSerializable,
|
|
49
|
+
fromJsonPayload,
|
|
46
50
|
toJsonPayload,
|
|
47
51
|
toStrictJsonPayload
|
|
48
52
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/serialization.ts"],"sourcesContent":["import { CodeModeError } from '../errors.js';\n\nexport function assertJsonSerializable(\n value: unknown,\n maxBytes: number,\n label: string,\n): void {\n void toJsonPayload(value, maxBytes, label);\n}\n\nexport function toJsonPayload(\n value: unknown,\n maxBytes: number,\n label: string,\n): string {\n if (value === undefined) {\n return '';\n }\n\n return toStrictJsonPayload(value, maxBytes, label);\n}\n\nexport function toStrictJsonPayload(\n value: unknown,\n maxBytes: number,\n label: string,\n): string {\n let encoded: string | undefined;\n try {\n encoded = JSON.stringify(value);\n } catch (error) {\n throw new CodeModeError(\n `${label} is not JSON-serializable: ${getErrorMessage(error)}`,\n 'CODE_MODE_SERIALIZATION_ERROR',\n );\n }\n\n if (encoded === undefined) {\n throw new CodeModeError(\n `${label} is not JSON-serializable.`,\n 'CODE_MODE_SERIALIZATION_ERROR',\n );\n }\n\n assertJsonPayloadSize(encoded, maxBytes, label);\n return encoded;\n}\n\nexport function assertJsonPayloadSize(\n valueJson: string,\n maxBytes: number,\n label: string,\n): void {\n const bytes = new TextEncoder().encode(valueJson).byteLength;\n if (bytes > maxBytes) {\n throw new CodeModeError(\n `${label} exceeds the ${maxBytes} byte size limit.`,\n 'CODE_MODE_SERIALIZATION_ERROR',\n { bytes, maxBytes },\n );\n }\n}\n\nfunction getErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n"],"mappings":"AAAA,SAAS,qBAAqB;AAEvB,SAAS,uBACd,OACA,UACA,OACM;AACN,OAAK,cAAc,OAAO,UAAU,KAAK;AAC3C;AAEO,SAAS,cACd,OACA,UACA,OACQ;AACR,MAAI,UAAU,QAAW;AACvB,WAAO;AAAA,EACT;AAEA,SAAO,oBAAoB,OAAO,UAAU,KAAK;AACnD;AAEO,SAAS,oBACd,OACA,UACA,OACQ;AACR,MAAI;AACJ,MAAI;AACF,cAAU,KAAK,UAAU,KAAK;AAAA,EAChC,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,GAAG,KAAK,8BAA8B,gBAAgB,KAAK,CAAC;AAAA,MAC5D;AAAA,IACF;AAAA,EACF;AAEA,MAAI,YAAY,QAAW;AACzB,UAAM,IAAI;AAAA,MACR,GAAG,KAAK;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,wBAAsB,SAAS,UAAU,KAAK;AAC9C,SAAO;AACT;AAEO,SAAS,sBACd,WACA,UACA,OACM;AACN,QAAM,QAAQ,IAAI,YAAY,EAAE,OAAO,SAAS,EAAE;AAClD,MAAI,QAAQ,UAAU;AACpB,UAAM,IAAI;AAAA,MACR,GAAG,KAAK,gBAAgB,QAAQ;AAAA,MAChC;AAAA,MACA,EAAE,OAAO,SAAS;AAAA,IACpB;AAAA,EACF;AACF;AAEA,SAAS,gBAAgB,OAAwB;AAC/C,SAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC9D;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/utils/serialization.ts"],"sourcesContent":["import { CodeModeError } from '../errors.js';\n\nexport function assertJsonSerializable(\n value: unknown,\n maxBytes: number,\n label: string,\n): void {\n void toJsonPayload(value, maxBytes, label);\n}\n\nexport function toJsonPayload(\n value: unknown,\n maxBytes: number,\n label: string,\n): string {\n if (value === undefined) {\n return '';\n }\n\n return toStrictJsonPayload(value, maxBytes, label);\n}\n\nexport function fromJsonPayload(valueJson: string): unknown {\n return valueJson === '' ? undefined : JSON.parse(valueJson);\n}\n\nexport function toStrictJsonPayload(\n value: unknown,\n maxBytes: number,\n label: string,\n): string {\n let encoded: string | undefined;\n try {\n encoded = JSON.stringify(value);\n } catch (error) {\n throw new CodeModeError(\n `${label} is not JSON-serializable: ${getErrorMessage(error)}`,\n 'CODE_MODE_SERIALIZATION_ERROR',\n );\n }\n\n if (encoded === undefined) {\n throw new CodeModeError(\n `${label} is not JSON-serializable.`,\n 'CODE_MODE_SERIALIZATION_ERROR',\n );\n }\n\n assertJsonPayloadSize(encoded, maxBytes, label);\n return encoded;\n}\n\nexport function assertJsonPayloadSize(\n valueJson: string,\n maxBytes: number,\n label: string,\n): void {\n const bytes = new TextEncoder().encode(valueJson).byteLength;\n if (bytes > maxBytes) {\n throw new CodeModeError(\n `${label} exceeds the ${maxBytes} byte size limit.`,\n 'CODE_MODE_SERIALIZATION_ERROR',\n { bytes, maxBytes },\n );\n }\n}\n\nfunction getErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n"],"mappings":"AAAA,SAAS,qBAAqB;AAEvB,SAAS,uBACd,OACA,UACA,OACM;AACN,OAAK,cAAc,OAAO,UAAU,KAAK;AAC3C;AAEO,SAAS,cACd,OACA,UACA,OACQ;AACR,MAAI,UAAU,QAAW;AACvB,WAAO;AAAA,EACT;AAEA,SAAO,oBAAoB,OAAO,UAAU,KAAK;AACnD;AAEO,SAAS,gBAAgB,WAA4B;AAC1D,SAAO,cAAc,KAAK,SAAY,KAAK,MAAM,SAAS;AAC5D;AAEO,SAAS,oBACd,OACA,UACA,OACQ;AACR,MAAI;AACJ,MAAI;AACF,cAAU,KAAK,UAAU,KAAK;AAAA,EAChC,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,GAAG,KAAK,8BAA8B,gBAAgB,KAAK,CAAC;AAAA,MAC5D;AAAA,IACF;AAAA,EACF;AAEA,MAAI,YAAY,QAAW;AACzB,UAAM,IAAI;AAAA,MACR,GAAG,KAAK;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,wBAAsB,SAAS,UAAU,KAAK;AAC9C,SAAO;AACT;AAEO,SAAS,sBACd,WACA,UACA,OACM;AACN,QAAM,QAAQ,IAAI,YAAY,EAAE,OAAO,SAAS,EAAE;AAClD,MAAI,QAAQ,UAAU;AACpB,UAAM,IAAI;AAAA,MACR,GAAG,KAAK,gBAAgB,QAAQ;AAAA,MAChC;AAAA,MACA,EAAE,OAAO,SAAS;AAAA,IACpB;AAAA,EACF;AACF;AAEA,SAAS,gBAAgB,OAAwB;AAC/C,SAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC9D;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/code-mode",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.22",
|
|
4
4
|
"description": "QuickJS-backed code mode tool for AI SDK",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -37,20 +37,18 @@
|
|
|
37
37
|
"README.md"
|
|
38
38
|
],
|
|
39
39
|
"peerDependencies": {
|
|
40
|
-
"ai": "7.0.
|
|
40
|
+
"ai": "7.0.65"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/node": "22.19.19",
|
|
44
|
-
"esbuild": "^0.28.1",
|
|
45
|
-
"quickjs-emscripten": "^0.32.0",
|
|
46
44
|
"tsup": "^8.5.1",
|
|
47
45
|
"typescript": "5.8.3",
|
|
48
46
|
"zod": "3.25.76",
|
|
49
47
|
"@vercel/ai-tsconfig": "0.0.0",
|
|
50
|
-
"ai": "7.0.
|
|
48
|
+
"ai": "7.0.65"
|
|
51
49
|
},
|
|
52
50
|
"engines": {
|
|
53
|
-
"node": ">=22"
|
|
51
|
+
"node": ">=22.13.0"
|
|
54
52
|
},
|
|
55
53
|
"publishConfig": {
|
|
56
54
|
"access": "public",
|
|
@@ -65,8 +63,11 @@
|
|
|
65
63
|
"bugs": {
|
|
66
64
|
"url": "https://github.com/vercel/ai/issues"
|
|
67
65
|
},
|
|
66
|
+
"dependencies": {
|
|
67
|
+
"run": "^2.0.0"
|
|
68
|
+
},
|
|
68
69
|
"scripts": {
|
|
69
|
-
"build": "pnpm clean && tsup --tsconfig tsconfig.build.json
|
|
70
|
+
"build": "pnpm clean && tsup --tsconfig tsconfig.build.json",
|
|
70
71
|
"clean": "del-cli build dist *.tsbuildinfo",
|
|
71
72
|
"type-check": "tsc --build && tsc -p src/tsconfig.json",
|
|
72
73
|
"test": "pnpm test:node",
|
|
@@ -82,6 +82,24 @@ export function verifyCodeModeContinuation(
|
|
|
82
82
|
continuation: CodeModeContinuation,
|
|
83
83
|
security: CodeModeContinuationSecurityOptions = {},
|
|
84
84
|
): void {
|
|
85
|
+
if (
|
|
86
|
+
typeof continuation !== 'object' ||
|
|
87
|
+
continuation === null ||
|
|
88
|
+
continuation.version !== 2 ||
|
|
89
|
+
typeof continuation.js !== 'string' ||
|
|
90
|
+
typeof continuation.outerToolCallId !== 'string' ||
|
|
91
|
+
!Array.isArray(continuation.toolNames) ||
|
|
92
|
+
!continuation.toolNames.every(name => typeof name === 'string') ||
|
|
93
|
+
typeof continuation.token !== 'string' ||
|
|
94
|
+
continuation.token.length === 0 ||
|
|
95
|
+
!Array.isArray(continuation.pendingInterruptions) ||
|
|
96
|
+
continuation.pendingInterruptions.length === 0 ||
|
|
97
|
+
!Array.isArray(continuation.resolutions)
|
|
98
|
+
) {
|
|
99
|
+
throw new CodeModeProtocolError(
|
|
100
|
+
'Code mode continuation envelope is malformed.',
|
|
101
|
+
);
|
|
102
|
+
}
|
|
85
103
|
assertAuthShape(continuation.auth);
|
|
86
104
|
const now = Date.now();
|
|
87
105
|
if (continuation.auth.expiresAtMs < now) {
|
package/src/errors.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import type { SerializableError } from './types.js';
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* Base class for errors raised by code mode.
|
|
5
3
|
*
|
|
@@ -142,191 +140,3 @@ export class CodeModeToolApprovalDeniedError extends CodeModeToolError {
|
|
|
142
140
|
this.code = 'CODE_MODE_TOOL_APPROVAL_DENIED';
|
|
143
141
|
}
|
|
144
142
|
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Converts an unknown thrown value into a worker-safe serializable shape.
|
|
148
|
-
*
|
|
149
|
-
* @internal
|
|
150
|
-
*/
|
|
151
|
-
export function serializeError(error: unknown): SerializableError {
|
|
152
|
-
if (error instanceof CodeModeError) {
|
|
153
|
-
const result = compactError({
|
|
154
|
-
name: error.name,
|
|
155
|
-
message: error.message,
|
|
156
|
-
code: error.code,
|
|
157
|
-
});
|
|
158
|
-
if (error.stack !== undefined) {
|
|
159
|
-
result.stack = error.stack;
|
|
160
|
-
}
|
|
161
|
-
if (error.details !== undefined) {
|
|
162
|
-
result.details = error.details;
|
|
163
|
-
}
|
|
164
|
-
return result;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
if (error instanceof Error) {
|
|
168
|
-
const result = compactError({
|
|
169
|
-
name: error.name,
|
|
170
|
-
message: error.message,
|
|
171
|
-
});
|
|
172
|
-
if (error.stack !== undefined) {
|
|
173
|
-
result.stack = error.stack;
|
|
174
|
-
}
|
|
175
|
-
const maybeCoded = error as Error & { code?: unknown; details?: unknown };
|
|
176
|
-
if (typeof maybeCoded.code === 'string') {
|
|
177
|
-
result.code = maybeCoded.code;
|
|
178
|
-
}
|
|
179
|
-
if (maybeCoded.details !== undefined) {
|
|
180
|
-
result.details = maybeCoded.details;
|
|
181
|
-
}
|
|
182
|
-
return result;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
return {
|
|
186
|
-
name: 'Error',
|
|
187
|
-
message: String(error),
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* Converts host bridge failures into a sandbox-visible sanitized shape.
|
|
193
|
-
*
|
|
194
|
-
* This intentionally omits stack traces and diagnostic details. Full host
|
|
195
|
-
* diagnostics remain on the host side.
|
|
196
|
-
*
|
|
197
|
-
* @internal
|
|
198
|
-
*/
|
|
199
|
-
export function serializeBridgeErrorForGuest(
|
|
200
|
-
error: unknown,
|
|
201
|
-
context: 'tool' | 'bridge',
|
|
202
|
-
): SerializableError {
|
|
203
|
-
if (error instanceof CodeModeError) {
|
|
204
|
-
return compactError({
|
|
205
|
-
name: error.name,
|
|
206
|
-
message: error.message,
|
|
207
|
-
code: error.code,
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
const fallback =
|
|
212
|
-
context === 'tool'
|
|
213
|
-
? {
|
|
214
|
-
message: 'Host tool failed.',
|
|
215
|
-
code: 'CODE_MODE_HOST_TOOL_ERROR',
|
|
216
|
-
}
|
|
217
|
-
: {
|
|
218
|
-
message: 'Host bridge request failed.',
|
|
219
|
-
code: 'CODE_MODE_HOST_BRIDGE_ERROR',
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
return {
|
|
223
|
-
name: 'Error',
|
|
224
|
-
message: fallback.message,
|
|
225
|
-
code: fallback.code,
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
function compactError(error: {
|
|
230
|
-
name: string;
|
|
231
|
-
message: string;
|
|
232
|
-
stack?: string;
|
|
233
|
-
code?: string;
|
|
234
|
-
details?: unknown;
|
|
235
|
-
}): SerializableError {
|
|
236
|
-
return {
|
|
237
|
-
name: error.name,
|
|
238
|
-
message: error.message,
|
|
239
|
-
...(error.stack !== undefined ? { stack: error.stack } : {}),
|
|
240
|
-
...(error.code !== undefined ? { code: error.code } : {}),
|
|
241
|
-
...(error.details !== undefined ? { details: error.details } : {}),
|
|
242
|
-
};
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* Rehydrates a serialized worker error into an Error instance.
|
|
247
|
-
*
|
|
248
|
-
* @internal
|
|
249
|
-
*/
|
|
250
|
-
export function deserializeError(error: SerializableError): Error {
|
|
251
|
-
if (error.code === 'CODE_MODE_SOURCE_TOO_LARGE') {
|
|
252
|
-
const details = error.details as
|
|
253
|
-
| { bytes?: number; maxBytes?: number }
|
|
254
|
-
| undefined;
|
|
255
|
-
const result = new CodeModeSourceTooLargeError(
|
|
256
|
-
details?.bytes ?? 0,
|
|
257
|
-
details?.maxBytes ?? 0,
|
|
258
|
-
);
|
|
259
|
-
restoreStack(result, error);
|
|
260
|
-
return result;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
if (error.code === 'CODE_MODE_BRIDGE_LIMIT') {
|
|
264
|
-
const result = new CodeModeBridgeLimitError(error.message, error.details);
|
|
265
|
-
restoreStack(result, error);
|
|
266
|
-
return result;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
if (error.code === 'CODE_MODE_DETACHED_BRIDGE_REQUEST') {
|
|
270
|
-
const result = new CodeModeDetachedBridgeRequestError(
|
|
271
|
-
error.message,
|
|
272
|
-
error.details,
|
|
273
|
-
);
|
|
274
|
-
restoreStack(result, error);
|
|
275
|
-
return result;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
if (error.code === 'CODE_MODE_PROTOCOL_ERROR') {
|
|
279
|
-
const result = new CodeModeProtocolError(error.message, error.details);
|
|
280
|
-
restoreStack(result, error);
|
|
281
|
-
return result;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
if (error.code === 'CODE_MODE_TOOL_APPROVAL_REQUIRED') {
|
|
285
|
-
const details = error.details as
|
|
286
|
-
| { toolName?: string; input?: unknown; toolCallId?: string }
|
|
287
|
-
| undefined;
|
|
288
|
-
const result = new CodeModeToolApprovalRequiredError(
|
|
289
|
-
details?.toolName ?? 'unknown',
|
|
290
|
-
details?.input,
|
|
291
|
-
details?.toolCallId ?? 'unknown',
|
|
292
|
-
);
|
|
293
|
-
result.message = error.message;
|
|
294
|
-
restoreStack(result, error);
|
|
295
|
-
return result;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
if (error.code === 'CODE_MODE_TOOL_APPROVAL_DENIED') {
|
|
299
|
-
const details = error.details as
|
|
300
|
-
| {
|
|
301
|
-
toolName?: string;
|
|
302
|
-
input?: unknown;
|
|
303
|
-
toolCallId?: string;
|
|
304
|
-
reason?: string;
|
|
305
|
-
}
|
|
306
|
-
| undefined;
|
|
307
|
-
const result = new CodeModeToolApprovalDeniedError(
|
|
308
|
-
details?.toolName ?? 'unknown',
|
|
309
|
-
details?.input,
|
|
310
|
-
details?.toolCallId ?? 'unknown',
|
|
311
|
-
details?.reason,
|
|
312
|
-
);
|
|
313
|
-
result.message = error.message;
|
|
314
|
-
restoreStack(result, error);
|
|
315
|
-
return result;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
const result = new CodeModeError(
|
|
319
|
-
error.message,
|
|
320
|
-
error.code ?? 'CODE_MODE_ERROR',
|
|
321
|
-
error.details,
|
|
322
|
-
);
|
|
323
|
-
result.name = error.name;
|
|
324
|
-
restoreStack(result, error);
|
|
325
|
-
return result;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
function restoreStack(error: Error, serialized: SerializableError): void {
|
|
329
|
-
if (serialized.stack) {
|
|
330
|
-
error.stack = serialized.stack;
|
|
331
|
-
}
|
|
332
|
-
}
|
package/src/host-interrupt.ts
CHANGED
|
@@ -1,14 +1,6 @@
|
|
|
1
|
+
import { getHostFunctionContext } from 'run';
|
|
1
2
|
import type { CodeModeInterruptPayload } from './types.js';
|
|
2
3
|
|
|
3
|
-
const CODE_MODE_HOST_INTERRUPT_SIGNAL = Symbol.for(
|
|
4
|
-
'@ai-sdk/code-mode.host-interrupt',
|
|
5
|
-
);
|
|
6
|
-
|
|
7
|
-
interface CodeModeHostInterruptSignal extends Error {
|
|
8
|
-
readonly [CODE_MODE_HOST_INTERRUPT_SIGNAL]: true;
|
|
9
|
-
readonly payload: CodeModeInterruptPayload;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
4
|
export function requestCodeModeInterrupt<
|
|
13
5
|
TPayload extends CodeModeInterruptPayload,
|
|
14
6
|
>(payload: TPayload): never {
|
|
@@ -24,26 +16,5 @@ export function requestCodeModeInterrupt<
|
|
|
24
16
|
'Code mode interrupt payload must include a string kind.',
|
|
25
17
|
);
|
|
26
18
|
}
|
|
27
|
-
|
|
28
|
-
const error = new Error('Code mode host interruption requested.');
|
|
29
|
-
error.name = 'CodeModeHostInterruptSignal';
|
|
30
|
-
Object.defineProperties(error, {
|
|
31
|
-
[CODE_MODE_HOST_INTERRUPT_SIGNAL]: { value: true },
|
|
32
|
-
payload: { value: payload },
|
|
33
|
-
});
|
|
34
|
-
throw error;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export function isCodeModeHostInterruptSignal(
|
|
38
|
-
value: unknown,
|
|
39
|
-
): value is CodeModeHostInterruptSignal {
|
|
40
|
-
return (
|
|
41
|
-
typeof value === 'object' &&
|
|
42
|
-
value !== null &&
|
|
43
|
-
(value as { [CODE_MODE_HOST_INTERRUPT_SIGNAL]?: unknown })[
|
|
44
|
-
CODE_MODE_HOST_INTERRUPT_SIGNAL
|
|
45
|
-
] === true &&
|
|
46
|
-
typeof (value as { payload?: unknown }).payload === 'object' &&
|
|
47
|
-
(value as { payload?: unknown }).payload !== null
|
|
48
|
-
);
|
|
19
|
+
return getHostFunctionContext().interrupt(payload);
|
|
49
20
|
}
|
package/src/index.ts
CHANGED
|
@@ -31,7 +31,7 @@ export {
|
|
|
31
31
|
} from './interrupt-continuation.js';
|
|
32
32
|
export { runCodeMode as experimental_runCodeMode } from './run-code-mode.js';
|
|
33
33
|
export { setCodeModeContinuationSigningKey as experimental_setCodeModeContinuationSigningKey } from './continuation-capability.js';
|
|
34
|
-
export { setMaxWorkers as experimental_setMaxWorkers } from '
|
|
34
|
+
export { setMaxWorkers as experimental_setMaxWorkers } from 'run';
|
|
35
35
|
export type {
|
|
36
36
|
ApprovalDecision,
|
|
37
37
|
CodeModeApprovalInterrupt,
|
|
@@ -143,19 +143,21 @@ function assertInterruptMatchesLedger(interrupt: CodeModeInterrupt): void {
|
|
|
143
143
|
'Code-mode interrupt outer tool call id does not match its continuation.',
|
|
144
144
|
);
|
|
145
145
|
}
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
146
|
+
const pending =
|
|
147
|
+
interrupt.continuation.pendingInterruptions[
|
|
148
|
+
interrupt.continuation.resolutions.length
|
|
149
|
+
];
|
|
150
|
+
if (
|
|
151
|
+
pending === undefined ||
|
|
152
|
+
pending.interruptId !== interrupt.interruptId ||
|
|
153
|
+
pending.toolCallId !== interrupt.toolCallId ||
|
|
154
|
+
pending.toolName !== interrupt.toolName ||
|
|
155
|
+
!jsonEqual(pending.input, interrupt.input) ||
|
|
156
|
+
!jsonEqual(pending.payload, interrupt.payload)
|
|
157
|
+
) {
|
|
156
158
|
throw new CodeModeProtocolError(
|
|
157
159
|
'Code-mode interrupt metadata does not match the signed continuation ledger.',
|
|
158
|
-
{ interruptId: interrupt.interruptId
|
|
160
|
+
{ interruptId: interrupt.interruptId },
|
|
159
161
|
);
|
|
160
162
|
}
|
|
161
163
|
}
|
|
@@ -164,10 +166,6 @@ function jsonEqual(left: unknown, right: unknown): boolean {
|
|
|
164
166
|
return JSON.stringify(left) === JSON.stringify(right);
|
|
165
167
|
}
|
|
166
168
|
|
|
167
|
-
function fromJsonPayload(valueJson: string): unknown {
|
|
168
|
-
return valueJson === '' ? undefined : JSON.parse(valueJson);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
169
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
172
170
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
173
171
|
}
|