@ai-sdk/code-mode 0.0.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +13 -0
- package/README.md +99 -0
- package/dist/code-mode-tool.js +40 -0
- package/dist/code-mode-tool.js.map +1 -0
- package/dist/errors.js +192 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +179 -2
- package/dist/index.js +32 -1
- package/dist/index.js.map +1 -1
- package/dist/run-code-mode.js +8 -0
- package/dist/run-code-mode.js.map +1 -0
- package/dist/runtime/guest-sources.js +260 -0
- package/dist/runtime/guest-sources.js.map +1 -0
- package/dist/runtime/manager.js +414 -0
- package/dist/runtime/manager.js.map +1 -0
- package/dist/runtime/max-workers.js +40 -0
- package/dist/runtime/max-workers.js.map +1 -0
- package/dist/runtime/protocol.js +1 -0
- package/dist/runtime/protocol.js.map +1 -0
- package/dist/runtime/worker-source.d.ts +11 -0
- package/dist/runtime/worker-source.js +2 -0
- package/dist/tool-invocation.js +129 -0
- package/dist/tool-invocation.js.map +1 -0
- package/dist/tool-prompt.js +440 -0
- package/dist/tool-prompt.js.map +1 -0
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/options.js +76 -0
- package/dist/utils/options.js.map +1 -0
- package/dist/utils/serialization.js +49 -0
- package/dist/utils/serialization.js.map +1 -0
- package/dist/utils/source-cache.js +77 -0
- package/dist/utils/source-cache.js.map +1 -0
- package/package.json +57 -16
- package/src/code-mode-tool.ts +60 -0
- package/src/errors.ts +267 -0
- package/src/index.ts +26 -0
- package/src/run-code-mode.ts +15 -0
- package/src/runtime/guest-sources.ts +260 -0
- package/src/runtime/manager.ts +498 -0
- package/src/runtime/max-workers.ts +65 -0
- package/src/runtime/protocol.ts +52 -0
- package/src/runtime/worker-source.ts +10 -0
- package/src/runtime/worker.ts +497 -0
- package/src/tool-invocation.ts +181 -0
- package/src/tool-prompt.ts +585 -0
- package/src/tsconfig.json +11 -0
- package/src/types.ts +111 -0
- package/src/utils/options.ts +83 -0
- package/src/utils/serialization.ts +66 -0
- package/src/utils/source-cache.ts +91 -0
- 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
|