@ai-sdk/code-mode 1.0.79 → 1.0.81

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.
@@ -1,549 +1,347 @@
1
- import { Buffer } from "node:buffer";
2
- import { createHash } from "node:crypto";
3
- import {
4
- createRunner,
5
- createSignedContinuationCodec,
6
- getHostFunctionContext,
7
- RunError
8
- } from "run";
9
- import {
10
- isCodeModeApprovalInterruptPayload,
11
- normalizeApprovalResolution
12
- } from "./approval.js";
13
- import {
14
- resolveCodeModeContinuationSecurity,
15
- signCodeModeContinuation,
16
- verifyCodeModeContinuation
17
- } from "./continuation-capability.js";
18
- import {
19
- CodeModeAbortedError,
20
- CodeModeBridgeLimitError,
21
- CodeModeConcurrencyError,
22
- CodeModeDetachedBridgeRequestError,
23
- CodeModeError,
24
- CodeModeProtocolError,
25
- CodeModeSourceTooLargeError,
26
- CodeModeTimeoutError,
27
- CodeModeToolApprovalDeniedError
28
- } from "./errors.js";
29
- import { invokeHostTool } from "./tool-invocation.js";
1
+ import { CodeModeAbortedError, CodeModeBridgeLimitError, CodeModeConcurrencyError, CodeModeDetachedBridgeRequestError, CodeModeError, CodeModeProtocolError, CodeModeSourceTooLargeError, CodeModeTimeoutError, CodeModeToolApprovalDeniedError } from "./errors.js";
2
+ import { isCodeModeApprovalInterruptPayload, normalizeApprovalResolution } from "./approval.js";
3
+ import { resolveCodeModeContinuationSecurity, signCodeModeContinuation, verifyCodeModeContinuation } from "./continuation-capability.js";
30
4
  import { fromJsonPayload, toJsonPayload } from "./utils/serialization.js";
5
+ import { invokeHostTool } from "./tool-invocation.js";
6
+ import { createHash } from "node:crypto";
7
+ import { Buffer } from "node:buffer";
8
+ import { RunError, createRunner, createSignedContinuationCodec, getHostFunctionContext } from "run";
9
+ //#region src/run-code-mode.ts
31
10
  const SOURCE_LINE_OFFSET = 1;
32
11
  const MAX_RUN_LIMIT = 2147483647;
33
12
  const DEFAULT_TIMEOUT_MS = 3e4;
34
- const DEFAULT_MEMORY_LIMIT_BYTES = 64 * 1024 * 1024;
35
- const DEFAULT_STACK_LIMIT_BYTES = 2 * 1024 * 1024;
36
- const DEFAULT_MAX_RESULT_BYTES = 1024 * 1024;
37
- const DEFAULT_MAX_CONSOLE_OUTPUT_BYTES = 64 * 1024;
38
- const DEFAULT_MAX_SOURCE_BYTES = 256 * 1024;
39
- const DEFAULT_MAX_TOOL_INPUT_BYTES = 1024 * 1024;
40
- const DEFAULT_MAX_TOOL_OUTPUT_BYTES = 4 * 1024 * 1024;
13
+ const DEFAULT_MEMORY_LIMIT_BYTES = 67108864;
14
+ const DEFAULT_STACK_LIMIT_BYTES = 2097152;
15
+ const DEFAULT_MAX_RESULT_BYTES = 1048576;
16
+ const DEFAULT_MAX_CONSOLE_OUTPUT_BYTES = 65536;
17
+ const DEFAULT_MAX_SOURCE_BYTES = 262144;
18
+ const DEFAULT_MAX_TOOL_INPUT_BYTES = 1048576;
19
+ const DEFAULT_MAX_TOOL_OUTPUT_BYTES = 4194304;
41
20
  const DEFAULT_MAX_BRIDGE_REQUESTS = 256;
42
21
  const DEFAULT_MAX_IN_FLIGHT_BRIDGE_REQUESTS = 32;
43
22
  let invocationCounter = 0;
23
+ /**
24
+ * Runs one code-mode invocation directly without wrapping it as an AI SDK tool.
25
+ *
26
+ * The source is executed in a fresh QuickJS context with the provided host tools
27
+ * and execution limits.
28
+ *
29
+ * @param input - Source code, host tools, forwarded tool execution options, and code-mode options.
30
+ * @returns The JSON-serializable value returned by the sandboxed program.
31
+ */
44
32
  async function runCodeMode(input) {
45
- const policy = resolveExecutionPolicy(input.options?.executionPolicy);
46
- assertSourceSize(input.js, policy.maxSourceBytes);
47
- const toolNames = Object.keys(input.tools).sort();
48
- const continuationState = prepareContinuation(
49
- input,
50
- toolNames,
51
- policy.maxToolOutputBytes
52
- );
53
- if (continuationState.nextInterrupt !== void 0) {
54
- return continuationState.nextInterrupt;
55
- }
56
- const outerToolCallId = input.toolExecutionOptions?.toolCallId ?? input.continuation?.outerToolCallId ?? `code-mode-${++invocationCounter}`;
57
- const source = createCodeModeSource(input.js, toolNames);
58
- const codeModeErrors = [];
59
- const hostFunctions = createHostFunctions({
60
- codeModeErrors,
61
- input,
62
- outerToolCallId,
63
- policy,
64
- toolNames
65
- });
66
- const continuationSecurity = resolveCodeModeContinuationSecurity(
67
- input.options?.continuationSecurity
68
- );
69
- const runner = createRunner({
70
- continuationAudience: "@ai-sdk/code-mode/v2",
71
- continuationCodec: createSignedContinuationCodec({
72
- maxAgeMs: continuationSecurity.maxAgeMs,
73
- secret: createHash("sha256").update(continuationSecurity.signingKey).digest()
74
- })
75
- });
76
- try {
77
- const result = await runner.run({
78
- source,
79
- hostFunctions,
80
- limits: toRunLimits(policy, source, input.js),
81
- continuationContext: { outerToolCallId, toolNames },
82
- ...input.toolExecutionOptions?.abortSignal === void 0 ? {} : { abortSignal: input.toolExecutionOptions.abortSignal },
83
- ...continuationState.token === void 0 ? {} : { continuation: continuationState.token },
84
- ...continuationState.resolutions === void 0 ? {} : { resolutions: continuationState.resolutions }
85
- });
86
- if (result.status === "completed") {
87
- return fromJsonPayload(
88
- toJsonPayload(result.value, policy.maxResultBytes, "Code mode result")
89
- );
90
- }
91
- const pendingInterruptions = toPendingInterruptions({
92
- interruptions: result.interruptions,
93
- outerToolCallId,
94
- toolNames
95
- });
96
- const continuation = signCodeModeContinuation(
97
- {
98
- version: 2,
99
- js: input.js,
100
- outerToolCallId,
101
- toolNames,
102
- token: result.continuation,
103
- pendingInterruptions,
104
- resolutions: []
105
- },
106
- continuationSecurity
107
- );
108
- return toCodeModeInterrupt(continuation, 0);
109
- } catch (error) {
110
- const preserved = findPreservedCodeModeError(error, codeModeErrors);
111
- if (preserved !== void 0) {
112
- throw translateSourceStack(preserved);
113
- }
114
- throw translateSourceStack(toCodeModeRuntimeError(error));
115
- }
33
+ const policy = resolveExecutionPolicy(input.options?.executionPolicy);
34
+ assertSourceSize(input.js, policy.maxSourceBytes);
35
+ const toolNames = Object.keys(input.tools).sort();
36
+ const continuationState = prepareContinuation(input, toolNames, policy.maxToolOutputBytes);
37
+ if (continuationState.nextInterrupt !== void 0) return continuationState.nextInterrupt;
38
+ const outerToolCallId = input.toolExecutionOptions?.toolCallId ?? input.continuation?.outerToolCallId ?? `code-mode-${++invocationCounter}`;
39
+ const source = createCodeModeSource(input.js, toolNames);
40
+ const codeModeErrors = [];
41
+ const hostFunctions = createHostFunctions({
42
+ codeModeErrors,
43
+ input,
44
+ outerToolCallId,
45
+ policy,
46
+ toolNames
47
+ });
48
+ const continuationSecurity = resolveCodeModeContinuationSecurity(input.options?.continuationSecurity);
49
+ const runner = createRunner({
50
+ continuationAudience: "@ai-sdk/code-mode/v2",
51
+ continuationCodec: createSignedContinuationCodec({
52
+ maxAgeMs: continuationSecurity.maxAgeMs,
53
+ secret: createHash("sha256").update(continuationSecurity.signingKey).digest()
54
+ })
55
+ });
56
+ try {
57
+ const result = await runner.run({
58
+ source,
59
+ hostFunctions,
60
+ limits: toRunLimits(policy, source, input.js),
61
+ continuationContext: {
62
+ outerToolCallId,
63
+ toolNames
64
+ },
65
+ ...input.toolExecutionOptions?.abortSignal === void 0 ? {} : { abortSignal: input.toolExecutionOptions.abortSignal },
66
+ ...continuationState.token === void 0 ? {} : { continuation: continuationState.token },
67
+ ...continuationState.resolutions === void 0 ? {} : { resolutions: continuationState.resolutions }
68
+ });
69
+ if (result.status === "completed") return fromJsonPayload(toJsonPayload(result.value, policy.maxResultBytes, "Code mode result"));
70
+ const pendingInterruptions = toPendingInterruptions({
71
+ interruptions: result.interruptions,
72
+ outerToolCallId,
73
+ toolNames
74
+ });
75
+ return toCodeModeInterrupt(signCodeModeContinuation({
76
+ version: 2,
77
+ js: input.js,
78
+ outerToolCallId,
79
+ toolNames,
80
+ token: result.continuation,
81
+ pendingInterruptions,
82
+ resolutions: []
83
+ }, continuationSecurity), 0);
84
+ } catch (error) {
85
+ const preserved = findPreservedCodeModeError(error, codeModeErrors);
86
+ if (preserved !== void 0) throw translateSourceStack(preserved);
87
+ throw translateSourceStack(toCodeModeRuntimeError(error));
88
+ }
116
89
  }
117
90
  function resolveExecutionPolicy(policy = {}) {
118
- return {
119
- timeoutMs: policy.timeoutMs ?? DEFAULT_TIMEOUT_MS,
120
- memoryLimitBytes: policy.memoryLimitBytes ?? DEFAULT_MEMORY_LIMIT_BYTES,
121
- maxStackSizeBytes: policy.maxStackSizeBytes ?? DEFAULT_STACK_LIMIT_BYTES,
122
- maxResultBytes: policy.maxResultBytes ?? DEFAULT_MAX_RESULT_BYTES,
123
- maxConsoleOutputBytes: policy.maxConsoleOutputBytes ?? DEFAULT_MAX_CONSOLE_OUTPUT_BYTES,
124
- maxSourceBytes: policy.maxSourceBytes ?? DEFAULT_MAX_SOURCE_BYTES,
125
- maxToolInputBytes: policy.maxToolInputBytes ?? DEFAULT_MAX_TOOL_INPUT_BYTES,
126
- maxToolOutputBytes: policy.maxToolOutputBytes ?? DEFAULT_MAX_TOOL_OUTPUT_BYTES,
127
- maxBridgeRequests: policy.maxBridgeRequests ?? DEFAULT_MAX_BRIDGE_REQUESTS,
128
- maxInFlightBridgeRequests: policy.maxInFlightBridgeRequests ?? DEFAULT_MAX_IN_FLIGHT_BRIDGE_REQUESTS
129
- };
91
+ return {
92
+ timeoutMs: policy.timeoutMs ?? DEFAULT_TIMEOUT_MS,
93
+ memoryLimitBytes: policy.memoryLimitBytes ?? DEFAULT_MEMORY_LIMIT_BYTES,
94
+ maxStackSizeBytes: policy.maxStackSizeBytes ?? DEFAULT_STACK_LIMIT_BYTES,
95
+ maxResultBytes: policy.maxResultBytes ?? DEFAULT_MAX_RESULT_BYTES,
96
+ maxConsoleOutputBytes: policy.maxConsoleOutputBytes ?? DEFAULT_MAX_CONSOLE_OUTPUT_BYTES,
97
+ maxSourceBytes: policy.maxSourceBytes ?? DEFAULT_MAX_SOURCE_BYTES,
98
+ maxToolInputBytes: policy.maxToolInputBytes ?? DEFAULT_MAX_TOOL_INPUT_BYTES,
99
+ maxToolOutputBytes: policy.maxToolOutputBytes ?? DEFAULT_MAX_TOOL_OUTPUT_BYTES,
100
+ maxBridgeRequests: policy.maxBridgeRequests ?? DEFAULT_MAX_BRIDGE_REQUESTS,
101
+ maxInFlightBridgeRequests: policy.maxInFlightBridgeRequests ?? DEFAULT_MAX_IN_FLIGHT_BRIDGE_REQUESTS
102
+ };
130
103
  }
131
104
  function assertSourceSize(source, maxBytes) {
132
- if (!isValidRunLimit(maxBytes)) {
133
- return;
134
- }
135
- const bytes = Buffer.byteLength(source);
136
- if (bytes > maxBytes) {
137
- throw new CodeModeSourceTooLargeError(bytes, maxBytes);
138
- }
105
+ if (!isValidRunLimit(maxBytes)) return;
106
+ const bytes = Buffer.byteLength(source);
107
+ if (bytes > maxBytes) throw new CodeModeSourceTooLargeError(bytes, maxBytes);
139
108
  }
140
109
  function createCodeModeSource(js, toolNames) {
141
- const bindings = Object.fromEntries(
142
- toolNames.map((toolName, index) => [toolName, `__codeMode.tool${index}`])
143
- );
144
- const bindingSource = Object.entries(bindings).map(([name, reference]) => `${JSON.stringify(name)}:${reference}`).join(",");
145
- return `const __codeModeBindings={${bindingSource}};const tools=new Proxy(Object.create(null),{get(_target,name){const binding=__codeModeBindings[name];return typeof binding==="function"?(input)=>binding(input):(input)=>__codeMode.missing(String(name),input);}});const __codeModeResult=await(async()=>{
146
- ${js}
147
- })();if(__codeModeResult===undefined)return undefined;return JSON.parse(JSON.stringify(__codeModeResult));`;
110
+ const bindings = Object.fromEntries(toolNames.map((toolName, index) => [toolName, `__codeMode.tool${index}`]));
111
+ return `const __codeModeBindings={${Object.entries(bindings).map(([name, reference]) => `${JSON.stringify(name)}:${reference}`).join(",")}};const tools=new Proxy(Object.create(null),{get(_target,name){const binding=__codeModeBindings[name];return typeof binding==="function"?(input)=>binding(input):(input)=>__codeMode.missing(String(name),input);}});const __codeModeResult=await(async()=>{\n${js}\n})();if(__codeModeResult===undefined)return undefined;return JSON.parse(JSON.stringify(__codeModeResult));`;
148
112
  }
149
- function createHostFunctions({
150
- codeModeErrors,
151
- input,
152
- outerToolCallId,
153
- policy,
154
- toolNames
155
- }) {
156
- const group = {};
157
- for (const [index, toolName] of toolNames.entries()) {
158
- group[`tool${index}`] = async (toolInput) => await invokeCodeModeTool({
159
- codeModeErrors,
160
- input,
161
- outerToolCallId,
162
- policy,
163
- toolInput,
164
- toolName
165
- });
166
- }
167
- group.missing = async (toolName, toolInput) => await invokeCodeModeTool({
168
- codeModeErrors,
169
- input,
170
- outerToolCallId,
171
- policy,
172
- toolInput,
173
- toolName: String(toolName)
174
- });
175
- return { __codeMode: group };
113
+ function createHostFunctions({ codeModeErrors, input, outerToolCallId, policy, toolNames }) {
114
+ const group = {};
115
+ for (const [index, toolName] of toolNames.entries()) group[`tool${index}`] = async (toolInput) => await invokeCodeModeTool({
116
+ codeModeErrors,
117
+ input,
118
+ outerToolCallId,
119
+ policy,
120
+ toolInput,
121
+ toolName
122
+ });
123
+ group.missing = async (toolName, toolInput) => await invokeCodeModeTool({
124
+ codeModeErrors,
125
+ input,
126
+ outerToolCallId,
127
+ policy,
128
+ toolInput,
129
+ toolName: String(toolName)
130
+ });
131
+ return { __codeMode: group };
176
132
  }
177
- async function invokeCodeModeTool({
178
- codeModeErrors,
179
- input,
180
- outerToolCallId,
181
- policy,
182
- toolInput,
183
- toolName
184
- }) {
185
- const context = getHostFunctionContext();
186
- const toolCallId = `${outerToolCallId}:tool-${context.requestIndex}`;
187
- const forwardedContext = input.toolExecutionOptions?.context ?? input.toolExecutionOptions?.experimental_context;
188
- const forwardedExperimentalContext = input.toolExecutionOptions?.experimental_context ?? input.toolExecutionOptions?.context;
189
- const baseExecutionOptions = {
190
- toolCallId: outerToolCallId,
191
- messages: input.toolExecutionOptions?.messages ?? [],
192
- abortSignal: context.abortSignal,
193
- ...forwardedContext === void 0 ? {} : { context: forwardedContext },
194
- ...forwardedExperimentalContext === void 0 ? {} : { experimental_context: forwardedExperimentalContext }
195
- };
196
- let codeModeInterrupt;
197
- let skipApproval = false;
198
- if (context.resume !== void 0) {
199
- const payload = assertInterruptPayload(context.resume.payload);
200
- if (isCodeModeApprovalInterruptPayload(payload)) {
201
- const decision = normalizeApprovalResolution(context.resume.resolution);
202
- if (!decision.approved) {
203
- throw new CodeModeToolApprovalDeniedError(
204
- toolName,
205
- toolInput,
206
- toolCallId,
207
- decision.reason
208
- );
209
- }
210
- skipApproval = true;
211
- } else {
212
- codeModeInterrupt = {
213
- interruptId: `${toolCallId}:interrupt`,
214
- payload,
215
- resolution: context.resume.resolution
216
- };
217
- }
218
- }
219
- try {
220
- const inputJson = toJsonPayload(
221
- toolInput,
222
- policy.maxToolInputBytes,
223
- `Tool "${toolName}" input`
224
- );
225
- const outcome = await invokeHostTool({
226
- toolName,
227
- inputJson,
228
- tools: input.tools,
229
- baseExecutionOptions,
230
- codeModeOptions: input.options ?? {},
231
- maxToolInputBytes: policy.maxToolInputBytes,
232
- maxToolOutputBytes: policy.maxToolOutputBytes,
233
- toolCallId,
234
- ...codeModeInterrupt === void 0 ? {} : { codeModeInterrupt },
235
- skipApproval
236
- });
237
- if (outcome.type === "interrupted") {
238
- return context.interrupt(outcome.payload);
239
- }
240
- return fromJsonPayload(outcome.valueJson);
241
- } catch (error) {
242
- if (error instanceof CodeModeError) {
243
- codeModeErrors.push(error);
244
- throw new RunError(error.message, error.code, error.details);
245
- }
246
- if (RunError.isInstance(error) || error instanceof Error && error.name === "HostFunctionInterruptSignal") {
247
- throw error;
248
- }
249
- throw new RunError("Host tool failed.", "CODE_MODE_HOST_TOOL_ERROR");
250
- }
133
+ async function invokeCodeModeTool({ codeModeErrors, input, outerToolCallId, policy, toolInput, toolName }) {
134
+ const context = getHostFunctionContext();
135
+ const toolCallId = `${outerToolCallId}:tool-${context.requestIndex}`;
136
+ const forwardedContext = input.toolExecutionOptions?.context ?? input.toolExecutionOptions?.experimental_context;
137
+ const forwardedExperimentalContext = input.toolExecutionOptions?.experimental_context ?? input.toolExecutionOptions?.context;
138
+ const baseExecutionOptions = {
139
+ toolCallId: outerToolCallId,
140
+ messages: input.toolExecutionOptions?.messages ?? [],
141
+ abortSignal: context.abortSignal,
142
+ ...forwardedContext === void 0 ? {} : { context: forwardedContext },
143
+ ...forwardedExperimentalContext === void 0 ? {} : { experimental_context: forwardedExperimentalContext }
144
+ };
145
+ let codeModeInterrupt;
146
+ let skipApproval = false;
147
+ if (context.resume !== void 0) {
148
+ const payload = assertInterruptPayload(context.resume.payload);
149
+ if (isCodeModeApprovalInterruptPayload(payload)) {
150
+ const decision = normalizeApprovalResolution(context.resume.resolution);
151
+ if (!decision.approved) throw new CodeModeToolApprovalDeniedError(toolName, toolInput, toolCallId, decision.reason);
152
+ skipApproval = true;
153
+ } else codeModeInterrupt = {
154
+ interruptId: `${toolCallId}:interrupt`,
155
+ payload,
156
+ resolution: context.resume.resolution
157
+ };
158
+ }
159
+ try {
160
+ const inputJson = toJsonPayload(toolInput, policy.maxToolInputBytes, `Tool "${toolName}" input`);
161
+ const outcome = await invokeHostTool({
162
+ toolName,
163
+ inputJson,
164
+ tools: input.tools,
165
+ baseExecutionOptions,
166
+ codeModeOptions: input.options ?? {},
167
+ maxToolInputBytes: policy.maxToolInputBytes,
168
+ maxToolOutputBytes: policy.maxToolOutputBytes,
169
+ toolCallId,
170
+ ...codeModeInterrupt === void 0 ? {} : { codeModeInterrupt },
171
+ skipApproval
172
+ });
173
+ if (outcome.type === "interrupted") return context.interrupt(outcome.payload);
174
+ return fromJsonPayload(outcome.valueJson);
175
+ } catch (error) {
176
+ if (error instanceof CodeModeError) {
177
+ codeModeErrors.push(error);
178
+ throw new RunError(error.message, error.code, error.details);
179
+ }
180
+ if (RunError.isInstance(error) || error instanceof Error && error.name === "HostFunctionInterruptSignal") throw error;
181
+ throw new RunError("Host tool failed.", "CODE_MODE_HOST_TOOL_ERROR");
182
+ }
251
183
  }
252
184
  function assertInterruptPayload(value) {
253
- if (typeof value !== "object" || value === null || Array.isArray(value) || typeof value.kind !== "string") {
254
- throw new CodeModeProtocolError(
255
- "Code mode interruption payload is malformed."
256
- );
257
- }
258
- return value;
185
+ if (typeof value !== "object" || value === null || Array.isArray(value) || typeof value.kind !== "string") throw new CodeModeProtocolError("Code mode interruption payload is malformed.");
186
+ return value;
259
187
  }
260
188
  function toRunLimits(policy, source, userSource) {
261
- return {
262
- timeoutMs: policy.timeoutMs,
263
- memoryLimitBytes: policy.memoryLimitBytes,
264
- maxStackSizeBytes: policy.maxStackSizeBytes,
265
- maxResultBytes: expandedSerializationLimit(policy.maxResultBytes),
266
- maxConsoleOutputBytes: policy.maxConsoleOutputBytes,
267
- maxSourceBytes: withSerializationOverhead(
268
- policy.maxSourceBytes,
269
- Buffer.byteLength(source) - Buffer.byteLength(userSource)
270
- ),
271
- maxHostFunctionArgumentsBytes: expandedSerializationLimit(
272
- policy.maxToolInputBytes
273
- ),
274
- maxHostFunctionOutputBytes: expandedSerializationLimit(
275
- policy.maxToolOutputBytes
276
- ),
277
- maxBridgeRequests: policy.maxBridgeRequests,
278
- maxInFlightBridgeRequests: policy.maxInFlightBridgeRequests
279
- };
189
+ return {
190
+ timeoutMs: policy.timeoutMs,
191
+ memoryLimitBytes: policy.memoryLimitBytes,
192
+ maxStackSizeBytes: policy.maxStackSizeBytes,
193
+ maxResultBytes: expandedSerializationLimit(policy.maxResultBytes),
194
+ maxConsoleOutputBytes: policy.maxConsoleOutputBytes,
195
+ maxSourceBytes: withSerializationOverhead(policy.maxSourceBytes, Buffer.byteLength(source) - Buffer.byteLength(userSource)),
196
+ maxHostFunctionArgumentsBytes: expandedSerializationLimit(policy.maxToolInputBytes),
197
+ maxHostFunctionOutputBytes: expandedSerializationLimit(policy.maxToolOutputBytes),
198
+ maxBridgeRequests: policy.maxBridgeRequests,
199
+ maxInFlightBridgeRequests: policy.maxInFlightBridgeRequests
200
+ };
280
201
  }
281
202
  function expandedSerializationLimit(value) {
282
- if (!isValidRunLimit(value)) {
283
- return value;
284
- }
285
- return Math.min(MAX_RUN_LIMIT, Math.max(4096, value * 2 + 1024));
203
+ if (!isValidRunLimit(value)) return value;
204
+ return Math.min(MAX_RUN_LIMIT, Math.max(4096, value * 2 + 1024));
286
205
  }
287
206
  function withSerializationOverhead(value, overhead) {
288
- return isValidRunLimit(value) ? Math.min(MAX_RUN_LIMIT, value + overhead) : value;
207
+ return isValidRunLimit(value) ? Math.min(MAX_RUN_LIMIT, value + overhead) : value;
289
208
  }
290
209
  function isValidRunLimit(value) {
291
- return Number.isInteger(value) && value > 0 && value <= MAX_RUN_LIMIT;
210
+ return Number.isInteger(value) && value > 0 && value <= MAX_RUN_LIMIT;
292
211
  }
293
212
  function prepareContinuation(input, toolNames, maxToolOutputBytes) {
294
- if (input.continuation === void 0) {
295
- if (input.interruptResolution !== void 0) {
296
- throw new CodeModeProtocolError(
297
- "A code-mode interrupt resolution was provided without continuation state."
298
- );
299
- }
300
- return {};
301
- }
302
- verifyCodeModeContinuation(
303
- input.continuation,
304
- input.options?.continuationSecurity
305
- );
306
- if (input.continuation.js !== input.js) {
307
- throw new CodeModeProtocolError(
308
- "Code mode continuation source does not match the resumed source."
309
- );
310
- }
311
- if (!stringArraysEqual(input.continuation.toolNames, toolNames)) {
312
- throw new CodeModeProtocolError(
313
- "Code mode continuation tool names do not match the resumed tools."
314
- );
315
- }
316
- if (input.interruptResolution === void 0) {
317
- throw new CodeModeProtocolError(
318
- "A code-mode continuation requires an interrupt resolution."
319
- );
320
- }
321
- const resolutionIndex = input.continuation.resolutions.length;
322
- const pending = input.continuation.pendingInterruptions[resolutionIndex];
323
- if (pending === void 0 || pending.interruptId !== input.interruptResolution.interruptId) {
324
- throw new CodeModeProtocolError(
325
- "Interrupt resolution does not match the next pending code-mode interruption.",
326
- { interruptId: input.interruptResolution.interruptId }
327
- );
328
- }
329
- const resolutionValue = normalizeResolutionForPending(
330
- pending,
331
- input.interruptResolution.resolution,
332
- maxToolOutputBytes
333
- );
334
- const resolutions = [
335
- ...input.continuation.resolutions,
336
- {
337
- runInterruptionId: pending.runInterruptionId,
338
- value: resolutionValue
339
- }
340
- ];
341
- if (resolutions.length < input.continuation.pendingInterruptions.length) {
342
- const continuation = signCodeModeContinuation(
343
- {
344
- ...withoutAuth(input.continuation),
345
- resolutions
346
- },
347
- resolveCodeModeContinuationSecurity(input.options?.continuationSecurity)
348
- );
349
- return {
350
- nextInterrupt: toCodeModeInterrupt(continuation, resolutions.length)
351
- };
352
- }
353
- assertNoDeniedApproval(input.continuation.pendingInterruptions, resolutions);
354
- return {
355
- token: input.continuation.token,
356
- resolutions: resolutions.map((resolution) => ({
357
- interruptionId: resolution.runInterruptionId,
358
- value: resolution.value
359
- }))
360
- };
213
+ if (input.continuation === void 0) {
214
+ if (input.interruptResolution !== void 0) throw new CodeModeProtocolError("A code-mode interrupt resolution was provided without continuation state.");
215
+ return {};
216
+ }
217
+ verifyCodeModeContinuation(input.continuation, input.options?.continuationSecurity);
218
+ if (input.continuation.js !== input.js) throw new CodeModeProtocolError("Code mode continuation source does not match the resumed source.");
219
+ if (!stringArraysEqual(input.continuation.toolNames, toolNames)) throw new CodeModeProtocolError("Code mode continuation tool names do not match the resumed tools.");
220
+ if (input.interruptResolution === void 0) throw new CodeModeProtocolError("A code-mode continuation requires an interrupt resolution.");
221
+ const resolutionIndex = input.continuation.resolutions.length;
222
+ const pending = input.continuation.pendingInterruptions[resolutionIndex];
223
+ if (pending === void 0 || pending.interruptId !== input.interruptResolution.interruptId) throw new CodeModeProtocolError("Interrupt resolution does not match the next pending code-mode interruption.", { interruptId: input.interruptResolution.interruptId });
224
+ const resolutionValue = normalizeResolutionForPending(pending, input.interruptResolution.resolution, maxToolOutputBytes);
225
+ const resolutions = [...input.continuation.resolutions, {
226
+ runInterruptionId: pending.runInterruptionId,
227
+ value: resolutionValue
228
+ }];
229
+ if (resolutions.length < input.continuation.pendingInterruptions.length) return { nextInterrupt: toCodeModeInterrupt(signCodeModeContinuation({
230
+ ...withoutAuth(input.continuation),
231
+ resolutions
232
+ }, resolveCodeModeContinuationSecurity(input.options?.continuationSecurity)), resolutions.length) };
233
+ assertNoDeniedApproval(input.continuation.pendingInterruptions, resolutions);
234
+ return {
235
+ token: input.continuation.token,
236
+ resolutions: resolutions.map((resolution) => ({
237
+ interruptionId: resolution.runInterruptionId,
238
+ value: resolution.value
239
+ }))
240
+ };
361
241
  }
362
242
  function normalizeResolutionForPending(pending, resolution, maxToolOutputBytes) {
363
- return isCodeModeApprovalInterruptPayload(pending.payload) ? normalizeApprovalResolution(resolution) : fromJsonPayload(
364
- toJsonPayload(
365
- resolution,
366
- maxToolOutputBytes,
367
- `Resolution "${pending.interruptId}"`
368
- )
369
- );
243
+ return isCodeModeApprovalInterruptPayload(pending.payload) ? normalizeApprovalResolution(resolution) : fromJsonPayload(toJsonPayload(resolution, maxToolOutputBytes, `Resolution "${pending.interruptId}"`));
370
244
  }
371
245
  function assertNoDeniedApproval(pendingInterruptions, resolutions) {
372
- for (const [index, pending] of pendingInterruptions.entries()) {
373
- if (!isCodeModeApprovalInterruptPayload(pending.payload)) {
374
- continue;
375
- }
376
- const decision = normalizeApprovalResolution(resolutions[index]?.value);
377
- if (!decision.approved) {
378
- throw new CodeModeToolApprovalDeniedError(
379
- pending.toolName,
380
- pending.input,
381
- pending.toolCallId,
382
- decision.reason
383
- );
384
- }
385
- }
246
+ for (const [index, pending] of pendingInterruptions.entries()) {
247
+ if (!isCodeModeApprovalInterruptPayload(pending.payload)) continue;
248
+ const decision = normalizeApprovalResolution(resolutions[index]?.value);
249
+ if (!decision.approved) throw new CodeModeToolApprovalDeniedError(pending.toolName, pending.input, pending.toolCallId, decision.reason);
250
+ }
386
251
  }
387
252
  function withoutAuth(continuation) {
388
- const { auth: _auth, ...unsigned } = continuation;
389
- return unsigned;
253
+ const { auth: _auth, ...unsigned } = continuation;
254
+ return unsigned;
390
255
  }
391
- function toPendingInterruptions({
392
- interruptions,
393
- outerToolCallId,
394
- toolNames
395
- }) {
396
- return interruptions.map((interruption) => {
397
- const requestIndex = interruptionIndex(interruption.id);
398
- const toolName = toolNameForInterruption(interruption, toolNames);
399
- const toolCallId = `${outerToolCallId}:tool-${requestIndex}`;
400
- return {
401
- runInterruptionId: interruption.id,
402
- interruptId: `${toolCallId}:interrupt`,
403
- toolName,
404
- toolCallId,
405
- input: interruption.hostFunctionName === "__codeMode.missing" ? interruption.arguments[1] : interruption.arguments[0],
406
- payload: assertInterruptPayload(interruption.payload)
407
- };
408
- });
256
+ function toPendingInterruptions({ interruptions, outerToolCallId, toolNames }) {
257
+ return interruptions.map((interruption) => {
258
+ const requestIndex = interruptionIndex(interruption.id);
259
+ const toolName = toolNameForInterruption(interruption, toolNames);
260
+ const toolCallId = `${outerToolCallId}:tool-${requestIndex}`;
261
+ return {
262
+ runInterruptionId: interruption.id,
263
+ interruptId: `${toolCallId}:interrupt`,
264
+ toolName,
265
+ toolCallId,
266
+ input: interruption.hostFunctionName === "__codeMode.missing" ? interruption.arguments[1] : interruption.arguments[0],
267
+ payload: assertInterruptPayload(interruption.payload)
268
+ };
269
+ });
409
270
  }
410
271
  function interruptionIndex(interruptionId) {
411
- const match = /^interrupt-(\d+)$/u.exec(interruptionId);
412
- if (match === null) {
413
- throw new CodeModeProtocolError(
414
- `Run returned malformed interruption id "${interruptionId}".`
415
- );
416
- }
417
- return Number(match[1]);
272
+ const match = /^interrupt-(\d+)$/u.exec(interruptionId);
273
+ if (match === null) throw new CodeModeProtocolError(`Run returned malformed interruption id "${interruptionId}".`);
274
+ return Number(match[1]);
418
275
  }
419
276
  function toolNameForInterruption(interruption, toolNames) {
420
- if (interruption.hostFunctionName === "__codeMode.missing") {
421
- return String(interruption.arguments[0]);
422
- }
423
- const match = /^__codeMode\.tool(\d+)$/u.exec(interruption.hostFunctionName);
424
- const toolName = match === null ? void 0 : toolNames[Number(match[1])];
425
- if (toolName === void 0) {
426
- throw new CodeModeProtocolError(
427
- `Run returned an unknown code-mode host function "${interruption.hostFunctionName}".`
428
- );
429
- }
430
- return toolName;
277
+ if (interruption.hostFunctionName === "__codeMode.missing") return String(interruption.arguments[0]);
278
+ const match = /^__codeMode\.tool(\d+)$/u.exec(interruption.hostFunctionName);
279
+ const toolName = match === null ? void 0 : toolNames[Number(match[1])];
280
+ if (toolName === void 0) throw new CodeModeProtocolError(`Run returned an unknown code-mode host function "${interruption.hostFunctionName}".`);
281
+ return toolName;
431
282
  }
432
283
  function toCodeModeInterrupt(continuation, index) {
433
- const pending = continuation.pendingInterruptions[index];
434
- if (pending === void 0) {
435
- throw new CodeModeProtocolError(
436
- "Code mode continuation has no pending interruption at the requested index."
437
- );
438
- }
439
- return {
440
- type: "code-mode-interrupt",
441
- interruptId: pending.interruptId,
442
- toolName: pending.toolName,
443
- toolCallId: pending.toolCallId,
444
- outerToolCallId: continuation.outerToolCallId,
445
- input: structuredClone(pending.input),
446
- payload: structuredClone(pending.payload),
447
- continuation
448
- };
284
+ const pending = continuation.pendingInterruptions[index];
285
+ if (pending === void 0) throw new CodeModeProtocolError("Code mode continuation has no pending interruption at the requested index.");
286
+ return {
287
+ type: "code-mode-interrupt",
288
+ interruptId: pending.interruptId,
289
+ toolName: pending.toolName,
290
+ toolCallId: pending.toolCallId,
291
+ outerToolCallId: continuation.outerToolCallId,
292
+ input: structuredClone(pending.input),
293
+ payload: structuredClone(pending.payload),
294
+ continuation
295
+ };
449
296
  }
450
297
  function stringArraysEqual(left, right) {
451
- return left.length === right.length && left.every((value, index) => value === right[index]);
298
+ return left.length === right.length && left.every((value, index) => value === right[index]);
452
299
  }
453
300
  function findPreservedCodeModeError(error, errors) {
454
- if (!RunError.isInstance(error)) {
455
- return void 0;
456
- }
457
- return errors.find((candidate) => candidate.code === error.code);
301
+ if (!RunError.isInstance(error)) return;
302
+ return errors.find((candidate) => candidate.code === error.code);
458
303
  }
459
304
  function toCodeModeRuntimeError(error) {
460
- if (error instanceof TypeError) {
461
- error.message = translateLimitPath(error.message);
462
- }
463
- if (error instanceof Error && error.name === "SyntaxError" && !/syntax|unexpected|expression expected/iu.test(error.message)) {
464
- error.message = `Syntax error: ${error.message}`;
465
- }
466
- if (!RunError.isInstance(error)) {
467
- return error;
468
- }
469
- const details = error.details;
470
- switch (error.code) {
471
- case "RUN_ABORTED":
472
- return copyStack(new CodeModeAbortedError(), error);
473
- case "RUN_TIMEOUT":
474
- return copyStack(
475
- new CodeModeTimeoutError(Number(details?.timeoutMs ?? 0)),
476
- error
477
- );
478
- case "RUN_CONCURRENCY_LIMIT":
479
- return copyStack(
480
- new CodeModeConcurrencyError(Number(details?.maxWorkers ?? 0)),
481
- error
482
- );
483
- case "RUN_SOURCE_TOO_LARGE":
484
- return copyStack(
485
- new CodeModeSourceTooLargeError(
486
- Number(details?.bytes ?? 0),
487
- Number(details?.maxBytes ?? 0)
488
- ),
489
- error
490
- );
491
- case "RUN_BRIDGE_LIMIT":
492
- return copyStack(
493
- new CodeModeBridgeLimitError(error.message, error.details),
494
- error
495
- );
496
- case "RUN_DETACHED_BRIDGE_REQUEST":
497
- return copyStack(
498
- new CodeModeDetachedBridgeRequestError(error.message, error.details),
499
- error
500
- );
501
- case "RUN_PROTOCOL_ERROR":
502
- return copyStack(
503
- new CodeModeProtocolError(error.message, error.details),
504
- error
505
- );
506
- default:
507
- return error;
508
- }
305
+ if (error instanceof TypeError) error.message = translateLimitPath(error.message);
306
+ if (error instanceof Error && error.name === "SyntaxError" && !/syntax|unexpected|expression expected/iu.test(error.message)) error.message = `Syntax error: ${error.message}`;
307
+ if (!RunError.isInstance(error)) return error;
308
+ const details = error.details;
309
+ switch (error.code) {
310
+ case "RUN_ABORTED": return copyStack(new CodeModeAbortedError(), error);
311
+ case "RUN_TIMEOUT": return copyStack(new CodeModeTimeoutError(Number(details?.timeoutMs ?? 0)), error);
312
+ case "RUN_CONCURRENCY_LIMIT": return copyStack(new CodeModeConcurrencyError(Number(details?.maxWorkers ?? 0)), error);
313
+ case "RUN_SOURCE_TOO_LARGE": return copyStack(new CodeModeSourceTooLargeError(Number(details?.bytes ?? 0), Number(details?.maxBytes ?? 0)), error);
314
+ case "RUN_BRIDGE_LIMIT": return copyStack(new CodeModeBridgeLimitError(error.message, error.details), error);
315
+ case "RUN_DETACHED_BRIDGE_REQUEST": return copyStack(new CodeModeDetachedBridgeRequestError(error.message, error.details), error);
316
+ case "RUN_PROTOCOL_ERROR": return copyStack(new CodeModeProtocolError(error.message, error.details), error);
317
+ default: return error;
318
+ }
509
319
  }
510
320
  function translateLimitPath(message) {
511
- const paths = {
512
- "limits.timeoutMs": "executionPolicy.timeoutMs",
513
- "limits.memoryLimitBytes": "executionPolicy.memoryLimitBytes",
514
- "limits.maxStackSizeBytes": "executionPolicy.maxStackSizeBytes",
515
- "limits.maxResultBytes": "executionPolicy.maxResultBytes",
516
- "limits.maxConsoleOutputBytes": "executionPolicy.maxConsoleOutputBytes",
517
- "limits.maxSourceBytes": "executionPolicy.maxSourceBytes",
518
- "limits.maxHostFunctionArgumentsBytes": "executionPolicy.maxToolInputBytes",
519
- "limits.maxHostFunctionOutputBytes": "executionPolicy.maxToolOutputBytes",
520
- "limits.maxBridgeRequests": "executionPolicy.maxBridgeRequests",
521
- "limits.maxInFlightBridgeRequests": "executionPolicy.maxInFlightBridgeRequests"
522
- };
523
- for (const [runPath, codeModePath] of Object.entries(paths)) {
524
- if (message.includes(runPath)) {
525
- return message.replace(runPath, codeModePath);
526
- }
527
- }
528
- return message;
321
+ for (const [runPath, codeModePath] of Object.entries({
322
+ "limits.timeoutMs": "executionPolicy.timeoutMs",
323
+ "limits.memoryLimitBytes": "executionPolicy.memoryLimitBytes",
324
+ "limits.maxStackSizeBytes": "executionPolicy.maxStackSizeBytes",
325
+ "limits.maxResultBytes": "executionPolicy.maxResultBytes",
326
+ "limits.maxConsoleOutputBytes": "executionPolicy.maxConsoleOutputBytes",
327
+ "limits.maxSourceBytes": "executionPolicy.maxSourceBytes",
328
+ "limits.maxHostFunctionArgumentsBytes": "executionPolicy.maxToolInputBytes",
329
+ "limits.maxHostFunctionOutputBytes": "executionPolicy.maxToolOutputBytes",
330
+ "limits.maxBridgeRequests": "executionPolicy.maxBridgeRequests",
331
+ "limits.maxInFlightBridgeRequests": "executionPolicy.maxInFlightBridgeRequests"
332
+ })) if (message.includes(runPath)) return message.replace(runPath, codeModePath);
333
+ return message;
529
334
  }
530
335
  function copyStack(target, source) {
531
- if (source.stack !== void 0) {
532
- target.stack = source.stack;
533
- }
534
- return target;
336
+ if (source.stack !== void 0) target.stack = source.stack;
337
+ return target;
535
338
  }
536
339
  function translateSourceStack(error) {
537
- if (!(error instanceof Error) || error.stack === void 0) {
538
- return error;
539
- }
540
- error.stack = error.stack.replaceAll(
541
- /run\.js:(\d+):(\d+)/gu,
542
- (_match, line, column) => `code-mode.js:${Math.max(1, Number(line) - SOURCE_LINE_OFFSET)}:${column}`
543
- );
544
- return error;
340
+ if (!(error instanceof Error) || error.stack === void 0) return error;
341
+ error.stack = error.stack.replaceAll(/run\.js:(\d+):(\d+)/gu, (_match, line, column) => `code-mode.js:${Math.max(1, Number(line) - SOURCE_LINE_OFFSET)}:${column}`);
342
+ return error;
545
343
  }
546
- export {
547
- runCodeMode
548
- };
344
+ //#endregion
345
+ export { runCodeMode };
346
+
549
347
  //# sourceMappingURL=run-code-mode.js.map