@ai-sdk/code-mode 0.0.1 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +99 -0
  3. package/dist/code-mode-tool.js +40 -0
  4. package/dist/code-mode-tool.js.map +1 -0
  5. package/dist/errors.js +192 -0
  6. package/dist/errors.js.map +1 -0
  7. package/dist/index.d.ts +179 -2
  8. package/dist/index.js +32 -1
  9. package/dist/index.js.map +1 -1
  10. package/dist/run-code-mode.js +8 -0
  11. package/dist/run-code-mode.js.map +1 -0
  12. package/dist/runtime/guest-sources.js +260 -0
  13. package/dist/runtime/guest-sources.js.map +1 -0
  14. package/dist/runtime/manager.js +414 -0
  15. package/dist/runtime/manager.js.map +1 -0
  16. package/dist/runtime/max-workers.js +40 -0
  17. package/dist/runtime/max-workers.js.map +1 -0
  18. package/dist/runtime/protocol.js +1 -0
  19. package/dist/runtime/protocol.js.map +1 -0
  20. package/dist/runtime/worker-source.d.ts +11 -0
  21. package/dist/runtime/worker-source.js +2 -0
  22. package/dist/tool-invocation.js +129 -0
  23. package/dist/tool-invocation.js.map +1 -0
  24. package/dist/tool-prompt.js +440 -0
  25. package/dist/tool-prompt.js.map +1 -0
  26. package/dist/types.js +1 -0
  27. package/dist/types.js.map +1 -0
  28. package/dist/utils/options.js +76 -0
  29. package/dist/utils/options.js.map +1 -0
  30. package/dist/utils/serialization.js +49 -0
  31. package/dist/utils/serialization.js.map +1 -0
  32. package/dist/utils/source-cache.js +77 -0
  33. package/dist/utils/source-cache.js.map +1 -0
  34. package/package.json +57 -16
  35. package/src/code-mode-tool.ts +60 -0
  36. package/src/errors.ts +267 -0
  37. package/src/index.ts +26 -0
  38. package/src/run-code-mode.ts +15 -0
  39. package/src/runtime/guest-sources.ts +260 -0
  40. package/src/runtime/manager.ts +498 -0
  41. package/src/runtime/max-workers.ts +65 -0
  42. package/src/runtime/protocol.ts +52 -0
  43. package/src/runtime/worker-source.ts +10 -0
  44. package/src/runtime/worker.ts +497 -0
  45. package/src/tool-invocation.ts +181 -0
  46. package/src/tool-prompt.ts +585 -0
  47. package/src/tsconfig.json +11 -0
  48. package/src/types.ts +111 -0
  49. package/src/utils/options.ts +83 -0
  50. package/src/utils/serialization.ts +66 -0
  51. package/src/utils/source-cache.ts +91 -0
  52. package/dist/index.d.ts.map +0 -1
@@ -0,0 +1,260 @@
1
+ const HARDENING_SOURCE = `
2
+ (function() {
3
+ try { delete globalThis.crypto; } catch {}
4
+ if ('crypto' in globalThis) {
5
+ Object.defineProperty(globalThis, 'crypto', {
6
+ value: undefined,
7
+ writable: false,
8
+ configurable: false,
9
+ });
10
+ }
11
+ try { delete globalThis.performance; } catch {}
12
+ if ('performance' in globalThis) {
13
+ Object.defineProperty(globalThis, 'performance', {
14
+ value: undefined,
15
+ writable: false,
16
+ configurable: false,
17
+ });
18
+ }
19
+
20
+ Object.defineProperty(globalThis, 'eval', {
21
+ value: undefined,
22
+ writable: false,
23
+ configurable: false,
24
+ });
25
+
26
+ const OriginalFunction = Function;
27
+ const BlockedFunction = function() {
28
+ throw new TypeError('Function constructor is not allowed');
29
+ };
30
+ BlockedFunction.prototype = OriginalFunction.prototype;
31
+
32
+ const AsyncFunction = (async function(){}).constructor;
33
+ const GeneratorFunction = (function*(){}).constructor;
34
+ const AsyncGeneratorFunction = (async function*(){}).constructor;
35
+ for (const proto of [
36
+ OriginalFunction.prototype,
37
+ AsyncFunction.prototype,
38
+ GeneratorFunction.prototype,
39
+ AsyncGeneratorFunction.prototype,
40
+ ]) {
41
+ Object.defineProperty(proto, 'constructor', {
42
+ value: BlockedFunction,
43
+ writable: false,
44
+ configurable: false,
45
+ });
46
+ }
47
+ Object.defineProperty(globalThis, 'Function', {
48
+ value: BlockedFunction,
49
+ writable: false,
50
+ configurable: false,
51
+ });
52
+
53
+ const g = globalThis;
54
+ const toFreeze = [
55
+ Object, Object.prototype,
56
+ OriginalFunction, OriginalFunction.prototype,
57
+ AsyncFunction, AsyncFunction.prototype,
58
+ GeneratorFunction, GeneratorFunction.prototype,
59
+ AsyncGeneratorFunction, AsyncGeneratorFunction.prototype,
60
+ Array, Array.prototype,
61
+ String, String.prototype,
62
+ Number, Number.prototype,
63
+ g.BigInt, g.BigInt && g.BigInt.prototype,
64
+ Boolean, Boolean.prototype,
65
+ g.Symbol, g.Symbol && g.Symbol.prototype,
66
+ RegExp, RegExp.prototype,
67
+ Date, Date.prototype,
68
+ Map, Map.prototype,
69
+ Set, Set.prototype,
70
+ WeakMap, WeakMap.prototype,
71
+ WeakSet, WeakSet.prototype,
72
+ Promise, Promise.prototype,
73
+ ArrayBuffer, ArrayBuffer.prototype,
74
+ g.DataView, g.DataView && g.DataView.prototype,
75
+ JSON, Math, g.Reflect, g.Proxy,
76
+ ];
77
+ for (const name of [
78
+ 'Int8Array','Uint8Array','Uint8ClampedArray',
79
+ 'Int16Array','Uint16Array','Int32Array','Uint32Array',
80
+ 'Float32Array','Float64Array',
81
+ 'BigInt64Array','BigUint64Array',
82
+ ]) {
83
+ if (g[name]) toFreeze.push(g[name], g[name].prototype);
84
+ }
85
+ for (const obj of toFreeze) {
86
+ if (obj != null) {
87
+ try { Object.freeze(obj); } catch {}
88
+ }
89
+ }
90
+ })();
91
+ `;
92
+ const BRIDGE_TRACKING_SOURCE = `
93
+ (function() {
94
+ var nextRecordId = 0;
95
+ var records = [];
96
+
97
+ function detachedError(message, record) {
98
+ var error = new Error(message);
99
+ error.name = 'CodeModeDetachedBridgeRequestError';
100
+ error.code = 'CODE_MODE_DETACHED_BRIDGE_REQUEST';
101
+ error.details = {
102
+ id: record.id,
103
+ kind: record.kind,
104
+ name: record.name,
105
+ status: record.status
106
+ };
107
+ return error;
108
+ }
109
+
110
+ Object.defineProperty(globalThis, '__codeModeCreateBridgePromise', {
111
+ value: function(kind, name, start) {
112
+ var record = {
113
+ id: ++nextRecordId,
114
+ kind: String(kind),
115
+ name: String(name || ''),
116
+ observed: false,
117
+ status: 'idle'
118
+ };
119
+ var promise;
120
+ records.push(record);
121
+
122
+ function getPromise() {
123
+ record.observed = true;
124
+ if (!promise) {
125
+ record.status = 'pending';
126
+ promise = Promise.resolve().then(start).then(
127
+ function(value) {
128
+ record.status = 'fulfilled';
129
+ return value;
130
+ },
131
+ function(error) {
132
+ record.status = 'rejected';
133
+ throw error;
134
+ }
135
+ );
136
+ }
137
+ return promise;
138
+ }
139
+
140
+ return Object.freeze({
141
+ then: function(onFulfilled, onRejected) {
142
+ return getPromise().then(onFulfilled, onRejected);
143
+ },
144
+ catch: function(onRejected) {
145
+ return getPromise().catch(onRejected);
146
+ },
147
+ finally: function(onFinally) {
148
+ return getPromise().finally(onFinally);
149
+ },
150
+ get [Symbol.toStringTag]() {
151
+ return 'Promise';
152
+ }
153
+ });
154
+ },
155
+ writable: false,
156
+ configurable: false
157
+ });
158
+
159
+ Object.defineProperty(globalThis, '__codeModeAssertNoDetachedBridgeCalls', {
160
+ value: function() {
161
+ for (var i = 0; i < records.length; i++) {
162
+ var record = records[i];
163
+ if (!record.observed) {
164
+ throw detachedError(
165
+ 'Code mode created an unawaited ' + record.kind + ' bridge request: ' + record.name + '.',
166
+ record
167
+ );
168
+ }
169
+ if (record.status === 'pending') {
170
+ throw detachedError(
171
+ 'Code mode returned while a ' + record.kind + ' bridge request was still pending: ' + record.name + '.',
172
+ record
173
+ );
174
+ }
175
+ }
176
+ },
177
+ writable: false,
178
+ configurable: false
179
+ });
180
+ })();
181
+ `;
182
+ const TOOLS_PROXY_SOURCE = `
183
+ (function(invokeTool) {
184
+ globalThis.tools = (function makeProxy(path) {
185
+ return new Proxy(function(){}, {
186
+ get: function(_target, prop) {
187
+ if (prop === 'then' || typeof prop === 'symbol') return undefined;
188
+ return makeProxy(path.concat([String(prop)]));
189
+ },
190
+ apply: function(_target, _thisArg, args) {
191
+ var toolPath = path.join('.');
192
+ if (!toolPath) throw new Error('Tool path missing in invocation');
193
+ var inputJson = args.length > 0 ? JSON.stringify(args[0]) : '';
194
+ if (inputJson === undefined) {
195
+ throw new Error('Tool input must be JSON-serializable');
196
+ }
197
+ return globalThis.__codeModeCreateBridgePromise('tool', toolPath, async function() {
198
+ var resultJson = await invokeTool(toolPath, inputJson);
199
+ return resultJson === '' ? undefined : JSON.parse(resultJson);
200
+ });
201
+ }
202
+ });
203
+ })([]);
204
+ })(__codeModeInvokeTool);
205
+ `;
206
+ const SERIALIZATION_GUARD_SOURCE = `
207
+ (function() {
208
+ function serializeJsonPayload(value) {
209
+ if (typeof globalThis.__codeModeAssertNoDetachedBridgeCalls === 'function') {
210
+ globalThis.__codeModeAssertNoDetachedBridgeCalls();
211
+ }
212
+
213
+ if (value === undefined) {
214
+ return '';
215
+ }
216
+
217
+ var encoded;
218
+ try {
219
+ encoded = JSON.stringify(value);
220
+ } catch (error) {
221
+ var message = error && error.message ? String(error.message) : String(error);
222
+ throw new TypeError('Code mode result is not JSON-serializable: ' + message);
223
+ }
224
+
225
+ if (encoded === undefined) {
226
+ throw new TypeError('Code mode result is not JSON-serializable.');
227
+ }
228
+
229
+ return encoded;
230
+ }
231
+
232
+ Object.defineProperty(globalThis, '__codeModeSerializeJsonPayload', {
233
+ value: serializeJsonPayload,
234
+ writable: false,
235
+ configurable: false,
236
+ });
237
+ })();
238
+ `;
239
+ function buildGuestRuntimeSetupSource() {
240
+ return `
241
+ (function(__codeModeInvokeTool) {
242
+ ${HARDENING_SOURCE}
243
+ ${BRIDGE_TRACKING_SOURCE}
244
+ ${TOOLS_PROXY_SOURCE}
245
+ ${SERIALIZATION_GUARD_SOURCE}
246
+ })
247
+ `;
248
+ }
249
+ function wrapUserCode(js) {
250
+ return `
251
+ globalThis.__codeModeResult = (async () => {
252
+ ${js}
253
+ })();
254
+ `;
255
+ }
256
+ export {
257
+ buildGuestRuntimeSetupSource,
258
+ wrapUserCode
259
+ };
260
+ //# sourceMappingURL=guest-sources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/runtime/guest-sources.ts"],"sourcesContent":["const HARDENING_SOURCE = `\n(function() {\n try { delete globalThis.crypto; } catch {}\n if ('crypto' in globalThis) {\n Object.defineProperty(globalThis, 'crypto', {\n value: undefined,\n writable: false,\n configurable: false,\n });\n }\n try { delete globalThis.performance; } catch {}\n if ('performance' in globalThis) {\n Object.defineProperty(globalThis, 'performance', {\n value: undefined,\n writable: false,\n configurable: false,\n });\n }\n\n Object.defineProperty(globalThis, 'eval', {\n value: undefined,\n writable: false,\n configurable: false,\n });\n\n const OriginalFunction = Function;\n const BlockedFunction = function() {\n throw new TypeError('Function constructor is not allowed');\n };\n BlockedFunction.prototype = OriginalFunction.prototype;\n\n const AsyncFunction = (async function(){}).constructor;\n const GeneratorFunction = (function*(){}).constructor;\n const AsyncGeneratorFunction = (async function*(){}).constructor;\n for (const proto of [\n OriginalFunction.prototype,\n AsyncFunction.prototype,\n GeneratorFunction.prototype,\n AsyncGeneratorFunction.prototype,\n ]) {\n Object.defineProperty(proto, 'constructor', {\n value: BlockedFunction,\n writable: false,\n configurable: false,\n });\n }\n Object.defineProperty(globalThis, 'Function', {\n value: BlockedFunction,\n writable: false,\n configurable: false,\n });\n\n const g = globalThis;\n const toFreeze = [\n Object, Object.prototype,\n OriginalFunction, OriginalFunction.prototype,\n AsyncFunction, AsyncFunction.prototype,\n GeneratorFunction, GeneratorFunction.prototype,\n AsyncGeneratorFunction, AsyncGeneratorFunction.prototype,\n Array, Array.prototype,\n String, String.prototype,\n Number, Number.prototype,\n g.BigInt, g.BigInt && g.BigInt.prototype,\n Boolean, Boolean.prototype,\n g.Symbol, g.Symbol && g.Symbol.prototype,\n RegExp, RegExp.prototype,\n Date, Date.prototype,\n Map, Map.prototype,\n Set, Set.prototype,\n WeakMap, WeakMap.prototype,\n WeakSet, WeakSet.prototype,\n Promise, Promise.prototype,\n ArrayBuffer, ArrayBuffer.prototype,\n g.DataView, g.DataView && g.DataView.prototype,\n JSON, Math, g.Reflect, g.Proxy,\n ];\n for (const name of [\n 'Int8Array','Uint8Array','Uint8ClampedArray',\n 'Int16Array','Uint16Array','Int32Array','Uint32Array',\n 'Float32Array','Float64Array',\n 'BigInt64Array','BigUint64Array',\n ]) {\n if (g[name]) toFreeze.push(g[name], g[name].prototype);\n }\n for (const obj of toFreeze) {\n if (obj != null) {\n try { Object.freeze(obj); } catch {}\n }\n }\n})();\n`;\n\nconst BRIDGE_TRACKING_SOURCE = `\n(function() {\n var nextRecordId = 0;\n var records = [];\n\n function detachedError(message, record) {\n var error = new Error(message);\n error.name = 'CodeModeDetachedBridgeRequestError';\n error.code = 'CODE_MODE_DETACHED_BRIDGE_REQUEST';\n error.details = {\n id: record.id,\n kind: record.kind,\n name: record.name,\n status: record.status\n };\n return error;\n }\n\n Object.defineProperty(globalThis, '__codeModeCreateBridgePromise', {\n value: function(kind, name, start) {\n var record = {\n id: ++nextRecordId,\n kind: String(kind),\n name: String(name || ''),\n observed: false,\n status: 'idle'\n };\n var promise;\n records.push(record);\n\n function getPromise() {\n record.observed = true;\n if (!promise) {\n record.status = 'pending';\n promise = Promise.resolve().then(start).then(\n function(value) {\n record.status = 'fulfilled';\n return value;\n },\n function(error) {\n record.status = 'rejected';\n throw error;\n }\n );\n }\n return promise;\n }\n\n return Object.freeze({\n then: function(onFulfilled, onRejected) {\n return getPromise().then(onFulfilled, onRejected);\n },\n catch: function(onRejected) {\n return getPromise().catch(onRejected);\n },\n finally: function(onFinally) {\n return getPromise().finally(onFinally);\n },\n get [Symbol.toStringTag]() {\n return 'Promise';\n }\n });\n },\n writable: false,\n configurable: false\n });\n\n Object.defineProperty(globalThis, '__codeModeAssertNoDetachedBridgeCalls', {\n value: function() {\n for (var i = 0; i < records.length; i++) {\n var record = records[i];\n if (!record.observed) {\n throw detachedError(\n 'Code mode created an unawaited ' + record.kind + ' bridge request: ' + record.name + '.',\n record\n );\n }\n if (record.status === 'pending') {\n throw detachedError(\n 'Code mode returned while a ' + record.kind + ' bridge request was still pending: ' + record.name + '.',\n record\n );\n }\n }\n },\n writable: false,\n configurable: false\n });\n})();\n`;\n\nconst TOOLS_PROXY_SOURCE = `\n(function(invokeTool) {\n globalThis.tools = (function makeProxy(path) {\n return new Proxy(function(){}, {\n get: function(_target, prop) {\n if (prop === 'then' || typeof prop === 'symbol') return undefined;\n return makeProxy(path.concat([String(prop)]));\n },\n apply: function(_target, _thisArg, args) {\n var toolPath = path.join('.');\n if (!toolPath) throw new Error('Tool path missing in invocation');\n var inputJson = args.length > 0 ? JSON.stringify(args[0]) : '';\n if (inputJson === undefined) {\n throw new Error('Tool input must be JSON-serializable');\n }\n return globalThis.__codeModeCreateBridgePromise('tool', toolPath, async function() {\n var resultJson = await invokeTool(toolPath, inputJson);\n return resultJson === '' ? undefined : JSON.parse(resultJson);\n });\n }\n });\n })([]);\n})(__codeModeInvokeTool);\n`;\n\nconst SERIALIZATION_GUARD_SOURCE = `\n(function() {\n function serializeJsonPayload(value) {\n if (typeof globalThis.__codeModeAssertNoDetachedBridgeCalls === 'function') {\n globalThis.__codeModeAssertNoDetachedBridgeCalls();\n }\n\n if (value === undefined) {\n return '';\n }\n\n var encoded;\n try {\n encoded = JSON.stringify(value);\n } catch (error) {\n var message = error && error.message ? String(error.message) : String(error);\n throw new TypeError('Code mode result is not JSON-serializable: ' + message);\n }\n\n if (encoded === undefined) {\n throw new TypeError('Code mode result is not JSON-serializable.');\n }\n\n return encoded;\n }\n\n Object.defineProperty(globalThis, '__codeModeSerializeJsonPayload', {\n value: serializeJsonPayload,\n writable: false,\n configurable: false,\n });\n})();\n`;\n\nexport function buildGuestRuntimeSetupSource(): string {\n return `\n(function(__codeModeInvokeTool) {\n${HARDENING_SOURCE}\n${BRIDGE_TRACKING_SOURCE}\n${TOOLS_PROXY_SOURCE}\n${SERIALIZATION_GUARD_SOURCE}\n})\n`;\n}\n\nexport function wrapUserCode(js: string): string {\n return `\nglobalThis.__codeModeResult = (async () => {\n${js}\n})();\n`;\n}\n"],"mappings":"AAAA,MAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA4FzB,MAAM,yBAAyB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA2F/B,MAAM,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAyB3B,MAAM,6BAA6B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkC5B,SAAS,+BAAuC;AACrD,SAAO;AAAA;AAAA,EAEP,gBAAgB;AAAA,EAChB,sBAAsB;AAAA,EACtB,kBAAkB;AAAA,EAClB,0BAA0B;AAAA;AAAA;AAG5B;AAEO,SAAS,aAAa,IAAoB;AAC/C,SAAO;AAAA;AAAA,EAEP,EAAE;AAAA;AAAA;AAGJ;","names":[]}
@@ -0,0 +1,414 @@
1
+ import { AsyncResource } from "node:async_hooks";
2
+ import { Buffer } from "node:buffer";
3
+ import { Worker } from "node:worker_threads";
4
+ import {
5
+ CodeModeAbortedError,
6
+ CodeModeBridgeLimitError,
7
+ CodeModeConcurrencyError,
8
+ CodeModeDetachedBridgeRequestError,
9
+ CodeModeProtocolError,
10
+ CodeModeTimeoutError,
11
+ deserializeError,
12
+ serializeBridgeErrorForGuest
13
+ } from "../errors.js";
14
+ import { invokeHostTool } from "../tool-invocation.js";
15
+ import { normalizeOptions } from "../utils/options.js";
16
+ import { assertSourceSize, transformSource } from "../utils/source-cache.js";
17
+ import { getMaxWorkers } from "./max-workers.js";
18
+ import { INLINE_CODE_MODE_WORKER_SOURCE } from "./worker-source.js";
19
+ let invocationCounter = 0;
20
+ let activeInvocations = 0;
21
+ let inlineWorkerUrl;
22
+ const idleWorkers = [];
23
+ async function runManagedCodeMode(input) {
24
+ const normalizedOptions = normalizeOptions(input.options);
25
+ const maxWorkers = getMaxWorkers({
26
+ memoryLimitBytes: normalizedOptions.memoryLimitBytes,
27
+ activeWorkers: activeInvocations
28
+ });
29
+ if (activeInvocations >= maxWorkers) {
30
+ throw new CodeModeConcurrencyError(maxWorkers);
31
+ }
32
+ activeInvocations++;
33
+ try {
34
+ if (input.toolExecutionOptions?.abortSignal?.aborted) {
35
+ throw new CodeModeAbortedError();
36
+ }
37
+ assertSourceSize(input.js, normalizedOptions.maxSourceBytes);
38
+ const run = startWorkerRun({
39
+ ...input,
40
+ js: transformSource(input.js),
41
+ normalizedOptions,
42
+ maxWorkers
43
+ });
44
+ return await run.result;
45
+ } finally {
46
+ releaseInvocationSlot(normalizedOptions.memoryLimitBytes);
47
+ }
48
+ }
49
+ function startWorkerRun({
50
+ js,
51
+ tools,
52
+ toolExecutionOptions,
53
+ normalizedOptions,
54
+ maxWorkers
55
+ }) {
56
+ const invocationId = `code-mode-${++invocationCounter}`;
57
+ const pooledWorker = acquireWorker(maxWorkers);
58
+ const worker = pooledWorker.worker;
59
+ const invocationContext = new AsyncResource("ai-sdk-code-mode:invocation");
60
+ const bindInvocationContext = (handler) => {
61
+ return (...args) => {
62
+ invocationContext.runInAsyncScope(handler, void 0, ...args);
63
+ };
64
+ };
65
+ const outerAbortSignal = toolExecutionOptions?.abortSignal;
66
+ const invocationAbortController = new AbortController();
67
+ const forwardedContext = toolExecutionOptions?.context ?? toolExecutionOptions?.experimental_context;
68
+ const forwardedExperimentalContext = toolExecutionOptions?.experimental_context ?? toolExecutionOptions?.context;
69
+ const baseExecutionOptions = {
70
+ toolCallId: toolExecutionOptions?.toolCallId ?? invocationId,
71
+ messages: toolExecutionOptions?.messages ?? [],
72
+ abortSignal: invocationAbortController.signal,
73
+ ...forwardedExperimentalContext !== void 0 ? { experimental_context: forwardedExperimentalContext } : {},
74
+ ...forwardedContext !== void 0 ? { context: forwardedContext } : {}
75
+ };
76
+ let resultMessage;
77
+ let callerSettled = false;
78
+ let terminalReached = false;
79
+ let workerCleanedUp = false;
80
+ let totalBridgeRequests = 0;
81
+ let inFlightBridgeRequests = 0;
82
+ const seenWorkerRequestIds = /* @__PURE__ */ new Set();
83
+ let resolveResult;
84
+ let rejectResult;
85
+ const result = new Promise((resolve, reject) => {
86
+ resolveResult = resolve;
87
+ rejectResult = reject;
88
+ });
89
+ const abortInvocation = (reason) => {
90
+ if (!invocationAbortController.signal.aborted) {
91
+ invocationAbortController.abort(reason);
92
+ }
93
+ };
94
+ const cleanupWorker = (reuseWorker) => {
95
+ if (workerCleanedUp) {
96
+ return;
97
+ }
98
+ workerCleanedUp = true;
99
+ clearTimeout(timeoutHandle);
100
+ outerAbortSignal?.removeEventListener("abort", onAbort);
101
+ worker.off("message", onMessage);
102
+ worker.off("error", onError);
103
+ worker.off("exit", onExit);
104
+ invocationContext.emitDestroy();
105
+ if (reuseWorker) {
106
+ releaseWorker(pooledWorker);
107
+ } else {
108
+ destroyWorker(pooledWorker);
109
+ }
110
+ };
111
+ const settleCaller = (settle) => {
112
+ if (callerSettled) {
113
+ return;
114
+ }
115
+ callerSettled = true;
116
+ try {
117
+ settle();
118
+ } catch (error) {
119
+ rejectResult(error);
120
+ }
121
+ };
122
+ const failTerminal = (error) => {
123
+ if (terminalReached) {
124
+ return;
125
+ }
126
+ terminalReached = true;
127
+ abortInvocation(error);
128
+ cleanupWorker(false);
129
+ settleCaller(() => rejectResult(error));
130
+ };
131
+ const onAbort = bindInvocationContext(() => {
132
+ failTerminal(new CodeModeAbortedError());
133
+ });
134
+ const timeoutHandle = setTimeout(
135
+ bindInvocationContext(() => {
136
+ failTerminal(new CodeModeTimeoutError(normalizedOptions.timeoutMs));
137
+ }),
138
+ normalizedOptions.timeoutMs
139
+ );
140
+ const onMessage = bindInvocationContext((message) => {
141
+ if (message.invocationId !== invocationId) {
142
+ failTerminal(
143
+ new CodeModeProtocolError(
144
+ `Worker message invocationId mismatch: expected ${invocationId}, received ${message.invocationId}.`,
145
+ {
146
+ expectedInvocationId: invocationId,
147
+ receivedInvocationId: message.invocationId,
148
+ messageType: message.type
149
+ }
150
+ )
151
+ );
152
+ return;
153
+ }
154
+ if (message.type === "result") {
155
+ if (resultMessage !== void 0) {
156
+ failTerminal(
157
+ new CodeModeProtocolError(
158
+ `Worker sent duplicate result for invocation ${invocationId}.`,
159
+ { invocationId }
160
+ )
161
+ );
162
+ return;
163
+ }
164
+ resultMessage = message;
165
+ return;
166
+ }
167
+ if (message.type === "ready") {
168
+ handleReadyMessage(message);
169
+ return;
170
+ }
171
+ const bridgeIndex = markWorkerRequest(message);
172
+ if (bridgeIndex !== void 0) {
173
+ void handleToolRequest(message, bridgeIndex);
174
+ }
175
+ });
176
+ const onError = bindInvocationContext((error) => {
177
+ failTerminal(error);
178
+ });
179
+ const onExit = bindInvocationContext((code) => {
180
+ if (!terminalReached) {
181
+ failTerminal(
182
+ new Error(
183
+ `Code mode worker exited before completion with code ${code}.`
184
+ )
185
+ );
186
+ }
187
+ });
188
+ worker.on("message", onMessage);
189
+ worker.on("error", onError);
190
+ worker.on("exit", onExit);
191
+ outerAbortSignal?.addEventListener("abort", onAbort, { once: true });
192
+ if (outerAbortSignal?.aborted) {
193
+ onAbort();
194
+ }
195
+ const runMessage = {
196
+ type: "run",
197
+ invocationId,
198
+ js,
199
+ options: {
200
+ timeoutMs: normalizedOptions.timeoutMs,
201
+ memoryLimitBytes: normalizedOptions.memoryLimitBytes,
202
+ maxStackSizeBytes: normalizedOptions.maxStackSizeBytes,
203
+ maxResultBytes: normalizedOptions.maxResultBytes,
204
+ maxConsoleOutputBytes: normalizedOptions.maxConsoleOutputBytes
205
+ }
206
+ };
207
+ if (!terminalReached) {
208
+ try {
209
+ worker.postMessage(runMessage);
210
+ } catch (error) {
211
+ failTerminal(error);
212
+ }
213
+ }
214
+ return { result };
215
+ function markWorkerRequest(message) {
216
+ if (terminalReached) {
217
+ return void 0;
218
+ }
219
+ if (seenWorkerRequestIds.has(message.requestId)) {
220
+ failTerminal(
221
+ new CodeModeProtocolError(
222
+ `Worker sent duplicate requestId ${message.requestId}.`,
223
+ { invocationId, requestId: message.requestId }
224
+ )
225
+ );
226
+ return void 0;
227
+ }
228
+ seenWorkerRequestIds.add(message.requestId);
229
+ if (totalBridgeRequests >= normalizedOptions.maxBridgeRequests) {
230
+ failTerminal(
231
+ new CodeModeBridgeLimitError(
232
+ `Code mode exceeded the ${normalizedOptions.maxBridgeRequests} bridge request limit.`,
233
+ {
234
+ invocationId,
235
+ maxBridgeRequests: normalizedOptions.maxBridgeRequests
236
+ }
237
+ )
238
+ );
239
+ return void 0;
240
+ }
241
+ if (inFlightBridgeRequests >= normalizedOptions.maxInFlightBridgeRequests) {
242
+ failTerminal(
243
+ new CodeModeBridgeLimitError(
244
+ `Code mode exceeded the ${normalizedOptions.maxInFlightBridgeRequests} in-flight bridge request limit.`,
245
+ {
246
+ invocationId,
247
+ maxInFlightBridgeRequests: normalizedOptions.maxInFlightBridgeRequests
248
+ }
249
+ )
250
+ );
251
+ return void 0;
252
+ }
253
+ totalBridgeRequests++;
254
+ inFlightBridgeRequests++;
255
+ return totalBridgeRequests;
256
+ }
257
+ async function handleToolRequest(message, bridgeIndex) {
258
+ try {
259
+ const valueJson = await invokeHostTool({
260
+ toolName: message.toolName,
261
+ inputJson: message.inputJson,
262
+ tools,
263
+ baseExecutionOptions,
264
+ maxToolInputBytes: normalizedOptions.maxToolInputBytes,
265
+ maxToolOutputBytes: normalizedOptions.maxToolOutputBytes,
266
+ toolCallId: `${baseExecutionOptions.toolCallId}:tool-${bridgeIndex}`
267
+ });
268
+ postBridgeResponse({
269
+ type: "bridge-response",
270
+ invocationId,
271
+ requestId: message.requestId,
272
+ success: true,
273
+ valueJson
274
+ });
275
+ } catch (error) {
276
+ postBridgeResponse({
277
+ type: "bridge-response",
278
+ invocationId,
279
+ requestId: message.requestId,
280
+ success: false,
281
+ error: serializeBridgeErrorForGuest(error, "tool")
282
+ });
283
+ } finally {
284
+ inFlightBridgeRequests--;
285
+ }
286
+ }
287
+ function postBridgeResponse(message) {
288
+ if (terminalReached) {
289
+ return;
290
+ }
291
+ try {
292
+ worker.postMessage(message);
293
+ } catch (error) {
294
+ failTerminal(error);
295
+ }
296
+ }
297
+ function handleReadyMessage(message) {
298
+ if (terminalReached) {
299
+ return;
300
+ }
301
+ if (resultMessage === void 0) {
302
+ failTerminal(
303
+ new CodeModeProtocolError(
304
+ `Code mode worker became ready without a result for ${message.invocationId}.`,
305
+ { invocationId: message.invocationId }
306
+ )
307
+ );
308
+ return;
309
+ }
310
+ terminalReached = true;
311
+ const finalResultMessage = resultMessage;
312
+ if (inFlightBridgeRequests > 0) {
313
+ const error = finalResultMessage.success ? new CodeModeDetachedBridgeRequestError(
314
+ `Code mode returned while ${inFlightBridgeRequests} bridge request(s) were still in flight.`,
315
+ {
316
+ invocationId,
317
+ inFlightBridgeRequests,
318
+ totalBridgeRequests
319
+ }
320
+ ) : deserializeResultError(finalResultMessage);
321
+ abortInvocation(error);
322
+ cleanupWorker(false);
323
+ settleCaller(() => rejectResult(error));
324
+ return;
325
+ }
326
+ cleanupWorker(true);
327
+ settleCaller(
328
+ () => settleWithResultMessage(finalResultMessage, resolveResult, rejectResult)
329
+ );
330
+ }
331
+ }
332
+ function acquireWorker(maxPoolSize) {
333
+ let pooledWorker = idleWorkers.pop();
334
+ while (pooledWorker?.destroyed) {
335
+ pooledWorker = idleWorkers.pop();
336
+ }
337
+ pooledWorker ??= createWorker();
338
+ pooledWorker.worker.removeAllListeners("exit");
339
+ pooledWorker.worker.ref();
340
+ trimIdleWorkers(Math.max(0, maxPoolSize - activeInvocations));
341
+ return pooledWorker;
342
+ }
343
+ function createWorker() {
344
+ return {
345
+ worker: new Worker(getInlineWorkerUrl(), { execArgv: [] }),
346
+ destroyed: false
347
+ };
348
+ }
349
+ function getInlineWorkerUrl() {
350
+ inlineWorkerUrl ??= new URL(
351
+ `data:text/javascript;base64,${Buffer.from(INLINE_CODE_MODE_WORKER_SOURCE).toString("base64")}`
352
+ );
353
+ return inlineWorkerUrl;
354
+ }
355
+ function releaseWorker(pooledWorker) {
356
+ if (pooledWorker.destroyed) {
357
+ return;
358
+ }
359
+ pooledWorker.worker.once("exit", () => {
360
+ pooledWorker.destroyed = true;
361
+ const index = idleWorkers.indexOf(pooledWorker);
362
+ if (index !== -1) {
363
+ idleWorkers.splice(index, 1);
364
+ }
365
+ });
366
+ pooledWorker.worker.unref();
367
+ idleWorkers.push(pooledWorker);
368
+ }
369
+ function destroyWorker(pooledWorker) {
370
+ if (pooledWorker.destroyed) {
371
+ return;
372
+ }
373
+ pooledWorker.destroyed = true;
374
+ pooledWorker.worker.removeAllListeners();
375
+ void pooledWorker.worker.terminate();
376
+ }
377
+ function trimIdleWorkers(maxIdleWorkers) {
378
+ while (idleWorkers.length > maxIdleWorkers) {
379
+ const pooledWorker = idleWorkers.pop();
380
+ if (pooledWorker !== void 0) {
381
+ destroyWorker(pooledWorker);
382
+ }
383
+ }
384
+ }
385
+ function releaseInvocationSlot(memoryLimitBytes) {
386
+ activeInvocations = Math.max(0, activeInvocations - 1);
387
+ const maxWorkers = getMaxWorkers({
388
+ memoryLimitBytes,
389
+ activeWorkers: activeInvocations
390
+ });
391
+ trimIdleWorkers(Math.max(0, maxWorkers - activeInvocations));
392
+ }
393
+ function settleWithResultMessage(message, resolve, reject) {
394
+ if (!message.success) {
395
+ reject(deserializeResultError(message));
396
+ return;
397
+ }
398
+ resolve(
399
+ message.valueJson === "" || message.valueJson === void 0 ? void 0 : JSON.parse(message.valueJson)
400
+ );
401
+ }
402
+ function deserializeResultError(message) {
403
+ if (message.error === void 0) {
404
+ return new CodeModeProtocolError(
405
+ `Code mode worker failed without an error for ${message.invocationId}.`,
406
+ { invocationId: message.invocationId }
407
+ );
408
+ }
409
+ return deserializeError(message.error);
410
+ }
411
+ export {
412
+ runManagedCodeMode
413
+ };
414
+ //# sourceMappingURL=manager.js.map