llmz 0.9.0 → 1.0.2
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/DOCS.md +232 -1794
- package/ERRORS.md +101 -0
- package/README.md +96 -582
- package/dist/chat/chat.d.ts +63 -0
- package/dist/chat/component.d.ts +31 -0
- package/dist/chat/component.default.d.ts +58 -0
- package/dist/chat/response.d.ts +15 -0
- package/dist/compiler/compiler.d.ts +2 -7
- package/dist/compiler/plugins/dynamic-code.d.ts +7 -0
- package/dist/compiler/plugins/replace-comment.d.ts +2 -3
- package/dist/compiler/plugins/return-async.d.ts +5 -4
- package/dist/compiler/plugins/termination.d.ts +8 -0
- package/dist/compiler/plugins/tool-resolution.d.ts +4 -0
- package/dist/compiler/plugins/variable-extraction.d.ts +2 -8
- package/dist/component-CMFoCHyu.cjs +649 -0
- package/dist/component-DncqP4fB.js +614 -0
- package/dist/context.d.ts +71 -378
- package/dist/custom-client-C-WXvLD9.js +1655 -0
- package/dist/custom-client-Cgt9_0r1.cjs +1732 -0
- package/dist/custom-client.d.ts +12 -2
- package/dist/errors/catalog.d.ts +294 -0
- package/dist/errors/hooks.d.ts +2 -0
- package/dist/errors-C6ppQUZX.cjs +893 -0
- package/dist/errors-Crk5P8jo.js +636 -0
- package/dist/errors.d.ts +24 -36
- package/dist/execute-CiYvPs5Q.js +2061 -0
- package/dist/execute-DTTfacsi.cjs +2062 -0
- package/dist/{exit-DUM96DN1.cjs → exit-BOtKWPuT.cjs} +38 -28
- package/dist/{exit-CDdxDBRT.js → exit-DMPwCSba.js} +37 -27
- package/dist/exit.d.ts +19 -16
- package/dist/index.cjs +177 -1237
- package/dist/index.d.ts +25 -28
- package/dist/index.js +137 -1213
- package/dist/index.workerd.js +8974 -11145
- package/dist/inspect.d.ts +18 -4
- package/dist/inspection.d.ts +40 -0
- package/dist/native-0bq5ATZM.cjs +212 -0
- package/dist/native-n_718Z-T.js +177 -0
- package/dist/objects.d.ts +2 -57
- package/dist/prompts/native.d.ts +2 -0
- package/dist/prompts/prompt.d.ts +10 -101
- package/dist/quickjs-variant-21IO97PF.cjs +1080 -0
- package/dist/quickjs-variant-CtuGagsb.js +985 -0
- package/dist/result.d.ts +30 -861
- package/dist/runtime/execute.d.ts +3 -2
- package/dist/runtime/execution-activity.d.ts +11 -0
- package/dist/runtime/execution-diagnostics.d.ts +11 -0
- package/dist/runtime/execution-report.d.ts +51 -0
- package/dist/runtime/fixtures/chat.d.ts +8 -0
- package/dist/runtime/fixtures/long-search.d.ts +1 -1
- package/dist/runtime/fixtures/native-client.d.ts +33 -0
- package/dist/runtime/fixtures/protocol-languages.d.ts +1 -1
- package/dist/runtime/forced-inspection.d.ts +13 -0
- package/dist/runtime/forced-inspection.test.d.ts +1 -0
- package/dist/runtime/generate.d.ts +23 -20
- package/dist/runtime/generate.test.d.ts +1 -0
- package/dist/runtime/hook-provenance.test.d.ts +1 -0
- package/dist/runtime/inspection-hook.test.d.ts +1 -0
- package/dist/runtime/inspection-values.d.ts +14 -0
- package/dist/runtime/inspection-values.test.d.ts +1 -0
- package/dist/runtime/interruption-control-flow.test.d.ts +1 -0
- package/dist/runtime/interruption-settings.test.d.ts +1 -0
- package/dist/runtime/javascript-api.d.ts +62 -0
- package/dist/runtime/javascript-api.test.d.ts +1 -0
- package/dist/runtime/native-review.test.d.ts +1 -0
- package/dist/runtime/native-tools.d.ts +18 -0
- package/dist/runtime/native-tools.test.d.ts +1 -0
- package/dist/runtime/object-memory.test.d.ts +1 -0
- package/dist/runtime/single-tool.test.d.ts +1 -0
- package/dist/runtime/think-signal.test.d.ts +1 -0
- package/dist/runtime/token-budget.d.ts +22 -0
- package/dist/runtime/token-budget.test.d.ts +1 -0
- package/dist/runtime/tool-wrapper.d.ts +6 -5
- package/dist/runtime/traces.test.d.ts +1 -0
- package/dist/runtime/truncation.test.d.ts +1 -0
- package/dist/runtime/types.d.ts +47 -31
- package/dist/runtime/variable-recovery.test.d.ts +1 -0
- package/dist/runtime/vm-context.d.ts +6 -1
- package/dist/runtime/worker-completion.test.d.ts +1 -0
- package/dist/runtime-names.d.ts +4 -0
- package/dist/schema-CXlnbb3n.cjs +68 -0
- package/dist/schema-GE4ISPCR.js +45 -0
- package/dist/schema.d.ts +10 -0
- package/dist/schema.test.d.ts +1 -0
- package/dist/session/compactor.d.ts +51 -0
- package/dist/session/compactor.test.d.ts +1 -0
- package/dist/session/history.d.ts +36 -0
- package/dist/session/history.test.d.ts +1 -0
- package/dist/session/json.d.ts +3 -0
- package/dist/session/json.test.d.ts +1 -0
- package/dist/session/memory-codec.d.ts +9 -0
- package/dist/session/memory-codec.test.d.ts +1 -0
- package/dist/session/memory-render.d.ts +15 -0
- package/dist/session/memory-render.test.d.ts +1 -0
- package/dist/session/memory.d.ts +112 -0
- package/dist/session/memory.test.d.ts +1 -0
- package/dist/session/messages.d.ts +19 -0
- package/dist/session/messages.test.d.ts +1 -0
- package/dist/session/serialization.d.ts +36 -0
- package/dist/session/serialization.test.d.ts +1 -0
- package/dist/session/session-memory.test.d.ts +1 -0
- package/dist/session/session.d.ts +121 -0
- package/dist/session/session.test.d.ts +1 -0
- package/dist/session/speaker.test.d.ts +1 -0
- package/dist/{transcript.d.ts → session/transcript.d.ts} +4 -8
- package/dist/session/transcript.test.d.ts +1 -0
- package/dist/{tool-Bv8N4IPj.js → tool-DstssiAs.js} +144 -92
- package/dist/{tool-Dy6AJpJH.cjs → tool-_wK9hQOb.cjs} +146 -94
- package/dist/tool.d.ts +25 -17
- package/dist/truncate-BEKbdo3t.js +79 -0
- package/dist/truncate-uomAMGPs.cjs +102 -0
- package/dist/truncate.d.ts +24 -0
- package/dist/truncate.test.d.ts +1 -0
- package/dist/types.d.ts +33 -9
- package/dist/{typings-3lsqCbkn.cjs → typings-BA_XxAcY.cjs} +38 -193
- package/dist/{typings-CrBa7Tyy.js → typings-BEVDvtuk.js} +38 -175
- package/dist/typings-formatter.d.ts +1 -1
- package/dist/typings.d.ts +3 -0
- package/dist/{uniq-BYQ7GWwb.js → uniq-DfUeSNaX.js} +2 -2
- package/dist/{uniq-G872RWmE.cjs → uniq-DiXgysNV.cjs} +6 -18
- package/dist/{_baseIteratee-P_firB7b.js → utils-BOFzb8Ok.js} +1134 -16
- package/dist/{_baseIteratee-CF4qP2a8.cjs → utils-CTlsXvdj.cjs} +1281 -84
- package/dist/vm/drivers/node.d.ts +1 -1
- package/dist/vm/drivers/quickjs.d.ts +1 -1
- package/dist/vm/errors.d.ts +4 -4
- package/dist/vm/index.d.ts +3 -4
- package/dist/vm/instrument.d.ts +14 -6
- package/dist/vm/member-proxy.d.ts +4 -0
- package/dist/vm/member-proxy.test.d.ts +1 -0
- package/dist/vm/memory.test.d.ts +1 -0
- package/dist/vm/return-semantics.test.d.ts +1 -0
- package/dist/vm/types.d.ts +20 -3
- package/dist/{vm-BLsHw1da.js → vm-C7SfutHn.js} +1187 -180
- package/dist/{vm-D6s1zF6M.cjs → vm-gmekHc0i.cjs} +1221 -207
- package/package.json +13 -6
- package/dist/_baseForOwn-BfWDTL8L.cjs +0 -53
- package/dist/_baseForOwn-CFhWe_W6.js +0 -48
- package/dist/_getPrototype-CG7Dxrrz.js +0 -6
- package/dist/_getPrototype-DQDlNVVM.cjs +0 -10
- package/dist/_overArg-C5Hy7oCi.cjs +0 -196
- package/dist/_overArg-CRYbj1NH.js +0 -155
- package/dist/chat.d.ts +0 -401
- package/dist/common-BlRFtdf2.js +0 -807
- package/dist/common-BnvrDnIT.cjs +0 -860
- package/dist/compiler/plugins/track-tool-calls.d.ts +0 -33
- package/dist/compiler-C-OI9sim.cjs +0 -547
- package/dist/compiler-CW1VjQsn.js +0 -473
- package/dist/component-C6Agl2ns.cjs +0 -73
- package/dist/component-DGG7d_Mz.js +0 -44
- package/dist/component.d.ts +0 -88
- package/dist/component.default.d.ts +0 -278
- package/dist/custom-client-ChuZ63zp.js +0 -2658
- package/dist/custom-client-DAsGRnYc.cjs +0 -2729
- package/dist/dual-modes-DDkoCp3R.js +0 -3006
- package/dist/dual-modes-DPXiuvNe.cjs +0 -3090
- package/dist/errors-C962uJdS.cjs +0 -220
- package/dist/errors-Cg1G0Awu.js +0 -161
- package/dist/example-format.d.ts +0 -8
- package/dist/example.d.ts +0 -45
- package/dist/execute-BWcdv9so.js +0 -1059
- package/dist/execute-DM2-7y86.cjs +0 -1060
- package/dist/exit-parser.d.ts +0 -39
- package/dist/handlers.d.ts +0 -10
- package/dist/hoist.d.ts +0 -2
- package/dist/isEmpty-BhJRCqIF.js +0 -52
- package/dist/isEmpty-LY533Wmh.cjs +0 -57
- package/dist/isPlainObject-CSxXVKCk.cjs +0 -56
- package/dist/isPlainObject-D39AzPO2.js +0 -51
- package/dist/jsx-CIgdGGVs.js +0 -52
- package/dist/jsx-owqxrquU.cjs +0 -75
- package/dist/jsx.d.ts +0 -11
- package/dist/message-stream/index.d.ts +0 -9
- package/dist/message-stream/instructions.d.ts +0 -30
- package/dist/message-stream/normalizer.d.ts +0 -21
- package/dist/message-stream/parser.d.ts +0 -89
- package/dist/message-stream/registry.d.ts +0 -14
- package/dist/message-stream/replayable.d.ts +0 -27
- package/dist/message-stream/response-parser.d.ts +0 -24
- package/dist/message-stream/sanitize.d.ts +0 -10
- package/dist/message-stream/stream.d.ts +0 -54
- package/dist/message-stream/types.d.ts +0 -97
- package/dist/message-stream/validator.d.ts +0 -23
- package/dist/prompts/chat-mode/protocol.d.ts +0 -2
- package/dist/prompts/chat-mode/system.d.ts +0 -2
- package/dist/prompts/chat-mode/system.md.d.ts +0 -2
- package/dist/prompts/chat-mode/user.d.ts +0 -2
- package/dist/prompts/chat-mode/user.md.d.ts +0 -2
- package/dist/prompts/code-examples.d.ts +0 -2
- package/dist/prompts/common.d.ts +0 -7
- package/dist/prompts/dual-modes.d.ts +0 -2
- package/dist/prompts/execution-history.d.ts +0 -6
- package/dist/prompts/execution-state.d.ts +0 -3
- package/dist/prompts/protocol-basics.d.ts +0 -5
- package/dist/prompts/protocol.d.ts +0 -31
- package/dist/prompts/worker-mode/protocol.d.ts +0 -2
- package/dist/prompts/worker-mode/system.d.ts +0 -2
- package/dist/prompts/worker-mode/system.md.d.ts +0 -2
- package/dist/prompts/worker-mode/user.d.ts +0 -2
- package/dist/prompts/worker-mode/user.md.d.ts +0 -2
- package/dist/quickjs-variant-BYhMBpwU.js +0 -45
- package/dist/quickjs-variant-CsIwTVFC.cjs +0 -56
- package/dist/rolldown-runtime-EAsCxrDo.js +0 -14
- package/dist/runtime/fixtures/qwen-protocol-failures.d.ts +0 -29
- package/dist/runtime/interpret-result.d.ts +0 -22
- package/dist/snapshots.d.ts +0 -249
- package/dist/stack-traces-BIE_5Xwf.js +0 -21
- package/dist/stack-traces-ntw_qhoy.cjs +0 -26
- package/dist/truncator-CLkouTCO.cjs +0 -276
- package/dist/truncator-DZqEqnpD.js +0 -253
- package/dist/truncator.d.ts +0 -118
- package/dist/utils-3ESwP3yg.cjs +0 -1075
- package/dist/utils-UBeAFeEI.js +0 -950
- /package/dist/{citations.d.ts → chat/citations.d.ts} +0 -0
- /package/dist/{citations.test.d.ts → chat/citations.test.d.ts} +0 -0
- /package/dist/{component.default.test.d.ts → chat/component.default.test.d.ts} +0 -0
- /package/dist/{compiler/plugins/track-tool-calls.test.d.ts → chat/component.test.d.ts} +0 -0
- /package/dist/{example.test.d.ts → chat/response.test.d.ts} +0 -0
- /package/dist/{exit-parser.test.d.ts → compiler/plugins/dynamic-code.test.d.ts} +0 -0
- /package/dist/{handlers.test.d.ts → compiler/plugins/tool-resolution.test.d.ts} +0 -0
- /package/dist/{hoist.test.d.ts → errors/catalog.test.d.ts} +0 -0
- /package/dist/{message-stream/instructions.test.d.ts → exit.test.d.ts} +0 -0
- /package/dist/{message-stream/normalizer.test.d.ts → inspection.test.d.ts} +0 -0
- /package/dist/{message-stream/parser.test.d.ts → prompts/native.test.d.ts} +0 -0
- /package/dist/{message-stream/response-parser.test.d.ts → result.test.d.ts} +0 -0
- /package/dist/{message-stream/stream.test.d.ts → runtime/chat-completion.test.d.ts} +0 -0
- /package/dist/{message-stream/validator.test.d.ts → runtime/chat-delivery.test.d.ts} +0 -0
- /package/dist/{prompts/adherence.test.d.ts → runtime/chat-last-speaker.test.d.ts} +0 -0
- /package/dist/{prompts/catalogue-examples.test.d.ts → runtime/compatibility-regressions.test.d.ts} +0 -0
- /package/dist/{prompts/code-examples.test.d.ts → runtime/context-registration.test.d.ts} +0 -0
- /package/dist/{prompts/common.test.d.ts → runtime/empty-completion.test.d.ts} +0 -0
- /package/dist/{prompts/concrete-patterns.test.d.ts → runtime/error-recovery.test.d.ts} +0 -0
- /package/dist/{prompts/long-search.test.d.ts → runtime/errors.test.d.ts} +0 -0
- /package/dist/{prompts/protocol-simple.test.d.ts → runtime/execution-activity.test.d.ts} +0 -0
- /package/dist/{prompts/protocol.test.d.ts → runtime/execution-diagnostics.test.d.ts} +0 -0
- /package/dist/{prompts/sections.test.d.ts → runtime/execution-report.test.d.ts} +0 -0
- /package/dist/runtime/{interpret-result.test.d.ts → execution-safety.test.d.ts} +0 -0
- /package/dist/{transcript.test.d.ts → runtime/exit-control-flow.test.d.ts} +0 -0
- /package/dist/{truncator.test.d.ts → runtime/fixtures/long-search.test.d.ts} +0 -0
|
@@ -1,11 +1,55 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
import { n as compile, t as Identifiers } from "./compiler-CW1VjQsn.js";
|
|
7
|
-
import { n as getQuickJSVariant } from "./quickjs-variant-BYhMBpwU.js";
|
|
1
|
+
import { A as keys, B as baseAssignValue, J as __commonJSMin, V as isFunction, W as isSymbol, h as baseIteratee } from "./utils-BOFzb8Ok.js";
|
|
2
|
+
import { P as ReservedIdentifierError, U as isLLMzError, V as UnknownToolError, o as AssignmentError, r as VMSignal, s as CodeExecutionError, t as Signals, v as InvalidCodeError } from "./errors-Crk5P8jo.js";
|
|
3
|
+
import { a as cloneMemoryValue, d as TERMINATION_BINDING_NAMES, l as RESERVED_RUNTIME_NAMES, n as getQuickJSVariant, o as decodeMemoryValue, u as RUNTIME_BINDING_NAMES } from "./quickjs-variant-CtuGagsb.js";
|
|
4
|
+
import MagicString from "magic-string";
|
|
5
|
+
import { parse } from "acorn";
|
|
8
6
|
import { newQuickJSWASMModuleFromVariant, shouldInterruptAfterDeadline } from "quickjs-emscripten-core";
|
|
7
|
+
//#region ../../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_createBaseFor.js
|
|
8
|
+
/**
|
|
9
|
+
* Creates a base function for methods like `_.forIn` and `_.forOwn`.
|
|
10
|
+
*
|
|
11
|
+
* @private
|
|
12
|
+
* @param {boolean} [fromRight] Specify iterating from right to left.
|
|
13
|
+
* @returns {Function} Returns the new base function.
|
|
14
|
+
*/
|
|
15
|
+
function createBaseFor(fromRight) {
|
|
16
|
+
return function(object, iteratee, keysFunc) {
|
|
17
|
+
var index = -1, iterable = Object(object), props = keysFunc(object), length = props.length;
|
|
18
|
+
while (length--) {
|
|
19
|
+
var key = props[fromRight ? length : ++index];
|
|
20
|
+
if (iteratee(iterable[key], key, iterable) === false) break;
|
|
21
|
+
}
|
|
22
|
+
return object;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region ../../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseFor.js
|
|
27
|
+
/**
|
|
28
|
+
* The base implementation of `baseForOwn` which iterates over `object`
|
|
29
|
+
* properties returned by `keysFunc` and invokes `iteratee` for each property.
|
|
30
|
+
* Iteratee functions may exit iteration early by explicitly returning `false`.
|
|
31
|
+
*
|
|
32
|
+
* @private
|
|
33
|
+
* @param {Object} object The object to iterate over.
|
|
34
|
+
* @param {Function} iteratee The function invoked per iteration.
|
|
35
|
+
* @param {Function} keysFunc The function to get the keys of `object`.
|
|
36
|
+
* @returns {Object} Returns `object`.
|
|
37
|
+
*/
|
|
38
|
+
var baseFor = createBaseFor();
|
|
39
|
+
//#endregion
|
|
40
|
+
//#region ../../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseForOwn.js
|
|
41
|
+
/**
|
|
42
|
+
* The base implementation of `_.forOwn` without support for iteratee shorthands.
|
|
43
|
+
*
|
|
44
|
+
* @private
|
|
45
|
+
* @param {Object} object The object to iterate over.
|
|
46
|
+
* @param {Function} iteratee The function invoked per iteration.
|
|
47
|
+
* @returns {Object} Returns `object`.
|
|
48
|
+
*/
|
|
49
|
+
function baseForOwn(object, iteratee) {
|
|
50
|
+
return object && baseFor(object, iteratee, keys);
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
9
53
|
//#region ../../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseGt.js
|
|
10
54
|
/**
|
|
11
55
|
* The base implementation of `_.gt` which doesn't coerce arguments.
|
|
@@ -2204,13 +2248,599 @@ var require_source_node = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
2204
2248
|
exports.SourceNode = SourceNode;
|
|
2205
2249
|
}));
|
|
2206
2250
|
//#endregion
|
|
2207
|
-
//#region src/
|
|
2251
|
+
//#region src/compiler/ast.ts
|
|
2208
2252
|
var import_source_map = (/* @__PURE__ */ __commonJSMin(((exports) => {
|
|
2209
2253
|
exports.SourceMapGenerator = require_source_map_generator().SourceMapGenerator;
|
|
2210
2254
|
exports.SourceMapConsumer = require_source_map_consumer().SourceMapConsumer;
|
|
2211
2255
|
exports.SourceNode = require_source_node().SourceNode;
|
|
2212
2256
|
})))();
|
|
2213
|
-
const
|
|
2257
|
+
const TS_SMELL = /(^|[^:]):\s*(string|number|boolean|any|unknown|void)\b|\bas\s+(const\b|[A-Z])|\binterface\s+[A-Z]|^\s*type\s+[A-Z]|[a-zA-Z)\]]!\.|<(string|number|boolean)[,>]/m;
|
|
2258
|
+
function parseScript(code, opts) {
|
|
2259
|
+
try {
|
|
2260
|
+
return parse(code, {
|
|
2261
|
+
ecmaVersion: "latest",
|
|
2262
|
+
sourceType: "script",
|
|
2263
|
+
locations: true,
|
|
2264
|
+
allowReturnOutsideFunction: true,
|
|
2265
|
+
allowAwaitOutsideFunction: true,
|
|
2266
|
+
...opts,
|
|
2267
|
+
onComment: opts === null || opts === void 0 ? void 0 : opts.comments
|
|
2268
|
+
});
|
|
2269
|
+
} catch (err) {
|
|
2270
|
+
if (err instanceof SyntaxError && TS_SMELL.test(code)) err.message += ". The code must be plain JavaScript: do not use TypeScript syntax (type annotations, \"as\" casts, generics, interfaces or type aliases).";
|
|
2271
|
+
throw err;
|
|
2272
|
+
}
|
|
2273
|
+
}
|
|
2274
|
+
/**
|
|
2275
|
+
* Depth-first pre-order walk. `ancestors` is ordered outermost → innermost and
|
|
2276
|
+
* excludes `node` itself; `parent` is `ancestors[ancestors.length - 1]`.
|
|
2277
|
+
*/
|
|
2278
|
+
function walk(root, enter) {
|
|
2279
|
+
const ancestors = [];
|
|
2280
|
+
const visit = (node) => {
|
|
2281
|
+
enter(node, ancestors[ancestors.length - 1] ?? null, ancestors);
|
|
2282
|
+
ancestors.push(node);
|
|
2283
|
+
for (const key of Object.keys(node)) {
|
|
2284
|
+
if (key === "loc") continue;
|
|
2285
|
+
const value = node[key];
|
|
2286
|
+
if (Array.isArray(value)) {
|
|
2287
|
+
for (const child of value) if (isNode(child)) visit(child);
|
|
2288
|
+
} else if (isNode(value)) visit(value);
|
|
2289
|
+
}
|
|
2290
|
+
ancestors.pop();
|
|
2291
|
+
};
|
|
2292
|
+
visit(root);
|
|
2293
|
+
}
|
|
2294
|
+
const isNode = (value) => !!value && typeof value === "object" && typeof value.type === "string";
|
|
2295
|
+
const isStatementContainer = (node) => !!node && (node.type === "Program" || node.type === "BlockStatement" || node.type === "StaticBlock");
|
|
2296
|
+
/**
|
|
2297
|
+
* The statement that contains `node`: the outermost ancestor (or the node
|
|
2298
|
+
* itself) whose parent is a statement container.
|
|
2299
|
+
*/
|
|
2300
|
+
function enclosingStatement(node, ancestors) {
|
|
2301
|
+
const chain = [...ancestors, node];
|
|
2302
|
+
for (let i = chain.length - 1; i > 0; i--) if (isStatementContainer(chain[i - 1])) return chain[i];
|
|
2303
|
+
return null;
|
|
2304
|
+
}
|
|
2305
|
+
/** The innermost node whose range contains [start, end] */
|
|
2306
|
+
function innermostContaining(ast, start, end) {
|
|
2307
|
+
let best = null;
|
|
2308
|
+
walk(ast, (node) => {
|
|
2309
|
+
if (node.start <= start && node.end >= end) {
|
|
2310
|
+
if (!best || node.start >= best.start && node.end <= best.end) best = node;
|
|
2311
|
+
}
|
|
2312
|
+
});
|
|
2313
|
+
return best;
|
|
2314
|
+
}
|
|
2315
|
+
//#endregion
|
|
2316
|
+
//#region src/compiler/plugins/async-wrapper.ts
|
|
2317
|
+
const Open = "async function __fn__() {";
|
|
2318
|
+
const Close = "}";
|
|
2319
|
+
const USER_CODE_START_MARKER = "/* __LLMZ_USER_CODE_START__ */";
|
|
2320
|
+
const USER_CODE_END_MARKER = "/* __LLMZ_USER_CODE_END__ */";
|
|
2321
|
+
/**
|
|
2322
|
+
* Wraps user code in an async function so top-level `await` and `return` parse,
|
|
2323
|
+
* and so plugins can target the `__fn__` declaration. The wrapper is removed
|
|
2324
|
+
* after transformation — drivers re-wrap the bare statements themselves.
|
|
2325
|
+
*/
|
|
2326
|
+
const AsyncWrapper = {
|
|
2327
|
+
preProcessing: (code) => {
|
|
2328
|
+
return `"use strict";
|
|
2329
|
+
${Open}
|
|
2330
|
+
${USER_CODE_START_MARKER}
|
|
2331
|
+
${code}
|
|
2332
|
+
${USER_CODE_END_MARKER}
|
|
2333
|
+
${Close}
|
|
2334
|
+
`.trim();
|
|
2335
|
+
},
|
|
2336
|
+
postProcessing: (code) => {
|
|
2337
|
+
code = code.slice(code.indexOf(Open) + 25);
|
|
2338
|
+
code = code.slice(0, code.lastIndexOf(Close));
|
|
2339
|
+
code = code.replace(USER_CODE_START_MARKER, "").replace(USER_CODE_END_MARKER, "");
|
|
2340
|
+
return code.trimEnd();
|
|
2341
|
+
}
|
|
2342
|
+
};
|
|
2343
|
+
//#endregion
|
|
2344
|
+
//#region src/compiler/plugins/dynamic-code.ts
|
|
2345
|
+
const DYNAMIC_GLOBALS = /* @__PURE__ */ new Set([
|
|
2346
|
+
"eval",
|
|
2347
|
+
"Function",
|
|
2348
|
+
"AsyncFunction",
|
|
2349
|
+
"GeneratorFunction",
|
|
2350
|
+
"AsyncGeneratorFunction"
|
|
2351
|
+
]);
|
|
2352
|
+
const GLOBAL_OBJECTS = /* @__PURE__ */ new Set([
|
|
2353
|
+
"globalThis",
|
|
2354
|
+
"global",
|
|
2355
|
+
"window",
|
|
2356
|
+
"self"
|
|
2357
|
+
]);
|
|
2358
|
+
const INVOCATION_METHODS = /* @__PURE__ */ new Set([
|
|
2359
|
+
"call",
|
|
2360
|
+
"apply",
|
|
2361
|
+
"bind"
|
|
2362
|
+
]);
|
|
2363
|
+
function propertyName(node) {
|
|
2364
|
+
if (!node.computed && node.property.type === "Identifier") return node.property.name;
|
|
2365
|
+
if (node.property.type === "Literal" && typeof node.property.value === "string") return node.property.value;
|
|
2366
|
+
}
|
|
2367
|
+
function isConstructorAccess(node) {
|
|
2368
|
+
return node.type === "MemberExpression" && propertyName(node) === "constructor";
|
|
2369
|
+
}
|
|
2370
|
+
function isReference(node, parent) {
|
|
2371
|
+
if (!parent) return true;
|
|
2372
|
+
if (parent.type === "MemberExpression" && parent.property === node && !parent.computed) return false;
|
|
2373
|
+
if (parent.type === "Property" && parent.key === node && !parent.computed && !parent.shorthand) return false;
|
|
2374
|
+
return parent.type !== "VariableDeclarator" || parent.id !== node;
|
|
2375
|
+
}
|
|
2376
|
+
/**
|
|
2377
|
+
* Dynamically generated source bypasses the VM's control-flow instrumentation.
|
|
2378
|
+
* Reject identifiable entry points and constructor aliases. This is a language
|
|
2379
|
+
* restriction, not a security boundary against reflective JavaScript escapes.
|
|
2380
|
+
*/
|
|
2381
|
+
function rejectDynamicCode(ast) {
|
|
2382
|
+
const constructorAliases = /* @__PURE__ */ new Set();
|
|
2383
|
+
const globalAliases = new Set(GLOBAL_OBJECTS);
|
|
2384
|
+
const aliasAssignments = [];
|
|
2385
|
+
const reject = () => {
|
|
2386
|
+
throw new Error("Dynamic code generation is not supported in run_javascript. Write JavaScript directly; do not use eval, Function, or async/generator function constructors.");
|
|
2387
|
+
};
|
|
2388
|
+
walk(ast, (node, parent) => {
|
|
2389
|
+
if (node.type === "Identifier" && DYNAMIC_GLOBALS.has(node.name) && isReference(node, parent)) reject();
|
|
2390
|
+
if (node.type === "MemberExpression" && node.object.type === "Identifier" && GLOBAL_OBJECTS.has(node.object.name) && DYNAMIC_GLOBALS.has(propertyName(node) ?? "")) reject();
|
|
2391
|
+
if (node.type === "VariableDeclarator" && node.init) {
|
|
2392
|
+
if (node.id.type === "Identifier") aliasAssignments.push({
|
|
2393
|
+
name: node.id.name,
|
|
2394
|
+
value: node.init
|
|
2395
|
+
});
|
|
2396
|
+
if (node.id.type === "ObjectPattern") for (const property of node.id.properties) {
|
|
2397
|
+
var _property$key, _property$key2, _property$key3, _property$value;
|
|
2398
|
+
if ((property.computed ? (_property$key = property.key) === null || _property$key === void 0 ? void 0 : _property$key.value : ((_property$key2 = property.key) === null || _property$key2 === void 0 ? void 0 : _property$key2.name) ?? ((_property$key3 = property.key) === null || _property$key3 === void 0 ? void 0 : _property$key3.value)) === "constructor" && ((_property$value = property.value) === null || _property$value === void 0 ? void 0 : _property$value.type) === "Identifier") constructorAliases.add(property.value.name);
|
|
2399
|
+
}
|
|
2400
|
+
}
|
|
2401
|
+
if (node.type === "AssignmentExpression" && node.left.type === "Identifier") aliasAssignments.push({
|
|
2402
|
+
name: node.left.name,
|
|
2403
|
+
value: node.right
|
|
2404
|
+
});
|
|
2405
|
+
});
|
|
2406
|
+
let changed = true;
|
|
2407
|
+
while (changed) {
|
|
2408
|
+
changed = false;
|
|
2409
|
+
for (const { name, value } of aliasAssignments) {
|
|
2410
|
+
const fromAlias = value.type === "Identifier" && constructorAliases.has(value.name);
|
|
2411
|
+
if (!constructorAliases.has(name) && (isConstructorAccess(value) || fromAlias)) {
|
|
2412
|
+
constructorAliases.add(name);
|
|
2413
|
+
changed = true;
|
|
2414
|
+
}
|
|
2415
|
+
if (value.type === "Identifier" && globalAliases.has(value.name) && !globalAliases.has(name)) {
|
|
2416
|
+
globalAliases.add(name);
|
|
2417
|
+
changed = true;
|
|
2418
|
+
}
|
|
2419
|
+
}
|
|
2420
|
+
}
|
|
2421
|
+
walk(ast, (node) => {
|
|
2422
|
+
var _node$init;
|
|
2423
|
+
if (node.type === "MemberExpression" && node.object.type === "Identifier" && globalAliases.has(node.object.name) && DYNAMIC_GLOBALS.has(propertyName(node) ?? "")) reject();
|
|
2424
|
+
if (node.type === "VariableDeclarator" && node.id.type === "ObjectPattern" && ((_node$init = node.init) === null || _node$init === void 0 ? void 0 : _node$init.type) === "Identifier" && globalAliases.has(node.init.name)) {
|
|
2425
|
+
if (node.id.properties.some((property) => {
|
|
2426
|
+
var _property$key4, _property$key5, _property$key6;
|
|
2427
|
+
const key = property.computed ? (_property$key4 = property.key) === null || _property$key4 === void 0 ? void 0 : _property$key4.value : ((_property$key5 = property.key) === null || _property$key5 === void 0 ? void 0 : _property$key5.name) ?? ((_property$key6 = property.key) === null || _property$key6 === void 0 ? void 0 : _property$key6.value);
|
|
2428
|
+
return DYNAMIC_GLOBALS.has(key);
|
|
2429
|
+
})) reject();
|
|
2430
|
+
}
|
|
2431
|
+
if (node.type !== "CallExpression" && node.type !== "NewExpression") return;
|
|
2432
|
+
let callee = node.callee;
|
|
2433
|
+
while (callee.type === "MemberExpression" && INVOCATION_METHODS.has(propertyName(callee) ?? "")) callee = callee.object;
|
|
2434
|
+
if (isConstructorAccess(callee) || callee.type === "Identifier" && constructorAliases.has(callee.name)) reject();
|
|
2435
|
+
});
|
|
2436
|
+
}
|
|
2437
|
+
//#endregion
|
|
2438
|
+
//#region src/compiler/plugins/line-tracking.ts
|
|
2439
|
+
const LineTrackingFnIdentifier = "__track__";
|
|
2440
|
+
const TRACKED_TYPES = /* @__PURE__ */ new Set([
|
|
2441
|
+
"FunctionDeclaration",
|
|
2442
|
+
"MethodDefinition",
|
|
2443
|
+
"ReturnStatement",
|
|
2444
|
+
"AwaitExpression",
|
|
2445
|
+
"ForOfStatement",
|
|
2446
|
+
"CallExpression",
|
|
2447
|
+
"UnaryExpression",
|
|
2448
|
+
"VariableDeclaration",
|
|
2449
|
+
"AssignmentExpression"
|
|
2450
|
+
]);
|
|
2451
|
+
const SKIPPED_PARENT_TYPES = /* @__PURE__ */ new Set([
|
|
2452
|
+
"ArrowFunctionExpression",
|
|
2453
|
+
"Property",
|
|
2454
|
+
"AwaitExpression",
|
|
2455
|
+
"UnaryExpression",
|
|
2456
|
+
"ReturnStatement",
|
|
2457
|
+
"ForOfStatement",
|
|
2458
|
+
"ForStatement",
|
|
2459
|
+
"ForInStatement",
|
|
2460
|
+
"VariableDeclaration",
|
|
2461
|
+
"BinaryExpression",
|
|
2462
|
+
"LogicalExpression"
|
|
2463
|
+
]);
|
|
2464
|
+
/**
|
|
2465
|
+
* Inserts a `__track__(<line>)` call before the statement containing each
|
|
2466
|
+
* tracked node — at most one per source line.
|
|
2467
|
+
*/
|
|
2468
|
+
function applyLineTracking(ctx) {
|
|
2469
|
+
const trackedLines = /* @__PURE__ */ new Set();
|
|
2470
|
+
walk(ctx.ast, (node, parent, ancestors) => {
|
|
2471
|
+
if (!parent || !node.loc) return;
|
|
2472
|
+
if (!TRACKED_TYPES.has(node.type) && parent.type !== "BlockStatement") return;
|
|
2473
|
+
const line = node.loc.start.line;
|
|
2474
|
+
if (trackedLines.has(line) || SKIPPED_PARENT_TYPES.has(parent.type)) return;
|
|
2475
|
+
const statement = enclosingStatement(node, ancestors);
|
|
2476
|
+
if (!statement) return;
|
|
2477
|
+
trackedLines.add(line);
|
|
2478
|
+
ctx.ms.appendLeft(statement.start, `${LineTrackingFnIdentifier}(${line});`);
|
|
2479
|
+
});
|
|
2480
|
+
}
|
|
2481
|
+
//#endregion
|
|
2482
|
+
//#region src/compiler/plugins/replace-comment.ts
|
|
2483
|
+
const CommentFnIdentifier = "__comment__";
|
|
2484
|
+
const MARKER_TAGS = [USER_CODE_START_MARKER, USER_CODE_END_MARKER].map((m) => m.replace(/\/\*|\*\/|\s/g, ""));
|
|
2485
|
+
/** Blanks a range, keeping newlines so line numbers are preserved */
|
|
2486
|
+
const blank = (ctx, start, end) => {
|
|
2487
|
+
ctx.ms.update(start, end, ctx.code.slice(start, end).replace(/[^\n]/g, " "));
|
|
2488
|
+
};
|
|
2489
|
+
/**
|
|
2490
|
+
* Replaces comments at statement position with `__comment__("<text>", <line>)`
|
|
2491
|
+
* calls so the agent's inline "thinking" comments show up as traces at runtime.
|
|
2492
|
+
* Comments inside expressions and the user-code markers are blanked.
|
|
2493
|
+
*/
|
|
2494
|
+
function applyCommentReplacement(ctx) {
|
|
2495
|
+
for (const comment of ctx.comments) {
|
|
2496
|
+
const text = comment.value.trim();
|
|
2497
|
+
if (MARKER_TAGS.some((tag) => text.includes(tag))) {
|
|
2498
|
+
blank(ctx, comment.start, comment.end);
|
|
2499
|
+
continue;
|
|
2500
|
+
}
|
|
2501
|
+
const container = innermostContaining(ctx.ast, comment.start, comment.end);
|
|
2502
|
+
if (isStatementContainer(container)) {
|
|
2503
|
+
const newlines = ctx.code.slice(comment.start, comment.end).replace(/[^\n]/g, "");
|
|
2504
|
+
ctx.ms.update(comment.start, comment.end, `;${CommentFnIdentifier}(${JSON.stringify(text)}, ${comment.loc.start.line});${newlines}`);
|
|
2505
|
+
} else blank(ctx, comment.start, comment.end);
|
|
2506
|
+
}
|
|
2507
|
+
}
|
|
2508
|
+
//#endregion
|
|
2509
|
+
//#region src/compiler/plugins/return-async.ts
|
|
2510
|
+
/**
|
|
2511
|
+
* Awaits the last expression without changing whether the program returns it.
|
|
2512
|
+
* The isolated VM cannot return a pending Promise:
|
|
2513
|
+
* - `return expr` → `return await (expr)`
|
|
2514
|
+
* - a trailing `call()` / `await call()` statement → `await (…)`
|
|
2515
|
+
*
|
|
2516
|
+
* Discarded values must stay discarded, especially terminal decision receipts.
|
|
2517
|
+
*
|
|
2518
|
+
* The prefix must be applied before, and the suffix after, all other edits so
|
|
2519
|
+
* they wrap around the tool-call instrumentation.
|
|
2520
|
+
*/
|
|
2521
|
+
function planLastLineInstrumentation(ast) {
|
|
2522
|
+
const fn = ast.body.find((node) => {
|
|
2523
|
+
var _id;
|
|
2524
|
+
return node.type === "FunctionDeclaration" && ((_id = node.id) === null || _id === void 0 ? void 0 : _id.name) === "__fn__";
|
|
2525
|
+
});
|
|
2526
|
+
if (!fn) return null;
|
|
2527
|
+
const statements = fn.body.body;
|
|
2528
|
+
const last = statements[statements.length - 1];
|
|
2529
|
+
if (!last) return null;
|
|
2530
|
+
if (last.type === "ReturnStatement") {
|
|
2531
|
+
if (!last.argument) return null;
|
|
2532
|
+
return {
|
|
2533
|
+
prefixPos: last.argument.start,
|
|
2534
|
+
prefix: "await (",
|
|
2535
|
+
suffixPos: last.argument.end,
|
|
2536
|
+
suffix: ")"
|
|
2537
|
+
};
|
|
2538
|
+
}
|
|
2539
|
+
if (last.type === "ExpressionStatement" && (last.expression.type === "CallExpression" || last.expression.type === "AwaitExpression")) return {
|
|
2540
|
+
prefixPos: last.expression.start,
|
|
2541
|
+
prefix: "await (",
|
|
2542
|
+
suffixPos: last.expression.end,
|
|
2543
|
+
suffix: ")"
|
|
2544
|
+
};
|
|
2545
|
+
return null;
|
|
2546
|
+
}
|
|
2547
|
+
//#endregion
|
|
2548
|
+
//#region src/compiler/plugins/termination.ts
|
|
2549
|
+
const TerminationGuardIdentifier = "__llmz_guard";
|
|
2550
|
+
const TerminationCheckpointIdentifier = "__llmz_checkpoint";
|
|
2551
|
+
const FUNCTIONS = /* @__PURE__ */ new Set([
|
|
2552
|
+
"FunctionDeclaration",
|
|
2553
|
+
"FunctionExpression",
|
|
2554
|
+
"ArrowFunctionExpression"
|
|
2555
|
+
]);
|
|
2556
|
+
const INTERNAL_CALLS = /* @__PURE__ */ new Set([
|
|
2557
|
+
"__var__",
|
|
2558
|
+
"__track__",
|
|
2559
|
+
"__comment__"
|
|
2560
|
+
]);
|
|
2561
|
+
/**
|
|
2562
|
+
* A terminal host call unwinds ordinary JavaScript. User error handlers must not
|
|
2563
|
+
* consume that control flow, and async continuations must check before resuming.
|
|
2564
|
+
*/
|
|
2565
|
+
function applyTerminationGuards(ctx) {
|
|
2566
|
+
const suffixes = [];
|
|
2567
|
+
const wrapper = ctx.ast.body.find((node) => {
|
|
2568
|
+
var _id;
|
|
2569
|
+
return node.type === "FunctionDeclaration" && ((_id = node.id) === null || _id === void 0 ? void 0 : _id.name) === "__fn__";
|
|
2570
|
+
});
|
|
2571
|
+
const guard = `${TerminationGuardIdentifier}();`;
|
|
2572
|
+
const wrap = (node, prefix) => {
|
|
2573
|
+
ctx.ms.appendLeft(node.start, prefix);
|
|
2574
|
+
suffixes.unshift(() => ctx.ms.appendRight(node.end, ")"));
|
|
2575
|
+
};
|
|
2576
|
+
const isCaptureGetter = (node, parent) => (parent === null || parent === void 0 ? void 0 : parent.type) === "CallExpression" && parent.callee.name === "__var__" && parent.arguments[1] === node;
|
|
2577
|
+
walk(ctx.ast, (node, parent, ancestors) => {
|
|
2578
|
+
if (isCaptureGetter(node, parent) || ancestors.some((ancestor, index) => isCaptureGetter(ancestor, ancestors[index - 1] ?? null))) return;
|
|
2579
|
+
if (node.type === "CallExpression" && node.callee.type === "Identifier" && INTERNAL_CALLS.has(node.callee.name)) return;
|
|
2580
|
+
if (node.type === "CatchClause") {
|
|
2581
|
+
ctx.ms.appendLeft(node.body.start + 1, guard);
|
|
2582
|
+
return;
|
|
2583
|
+
}
|
|
2584
|
+
if (node.type === "TryStatement" && node.finalizer) ctx.ms.appendLeft(node.finalizer.start + 1, guard);
|
|
2585
|
+
if (FUNCTIONS.has(node.type)) {
|
|
2586
|
+
if (node === wrapper) return;
|
|
2587
|
+
if (node.body.type === "BlockStatement") ctx.ms.appendLeft(node.body.start + 1, guard);
|
|
2588
|
+
else wrap(node.body, `(${TerminationGuardIdentifier}(), `);
|
|
2589
|
+
}
|
|
2590
|
+
if (node.type === "AssignmentPattern") wrap(node.right, `(${TerminationGuardIdentifier}(), `);
|
|
2591
|
+
if ([
|
|
2592
|
+
"AwaitExpression",
|
|
2593
|
+
"CallExpression",
|
|
2594
|
+
"NewExpression",
|
|
2595
|
+
"TaggedTemplateExpression"
|
|
2596
|
+
].includes(node.type)) {
|
|
2597
|
+
wrap(node, `(${TerminationGuardIdentifier}(), ${TerminationCheckpointIdentifier}(`);
|
|
2598
|
+
suffixes.unshift(() => ctx.ms.appendRight(node.end, ")"));
|
|
2599
|
+
}
|
|
2600
|
+
if (node.type === "AssignmentExpression" || node.type === "UpdateExpression" || node.type === "UnaryExpression" && node.operator === "delete") wrap(node, `(${TerminationGuardIdentifier}(), `);
|
|
2601
|
+
});
|
|
2602
|
+
return () => suffixes.forEach((apply) => apply());
|
|
2603
|
+
}
|
|
2604
|
+
//#endregion
|
|
2605
|
+
//#region src/compiler/plugins/tool-resolution.ts
|
|
2606
|
+
const MissingToolIdentifier = "__llmz_missing_tool";
|
|
2607
|
+
/** Diagnose missing free callables at the lookup, before evaluating their arguments. */
|
|
2608
|
+
function applyToolResolution({ ast, ms }) {
|
|
2609
|
+
const declared = /* @__PURE__ */ new Set();
|
|
2610
|
+
const collect = (pattern) => {
|
|
2611
|
+
walk(pattern, (node) => {
|
|
2612
|
+
if (node.type === "Identifier") declared.add(node.name);
|
|
2613
|
+
});
|
|
2614
|
+
};
|
|
2615
|
+
walk(ast, (node) => {
|
|
2616
|
+
if (node.type === "VariableDeclarator") collect(node.id);
|
|
2617
|
+
else if ([
|
|
2618
|
+
"FunctionDeclaration",
|
|
2619
|
+
"FunctionExpression",
|
|
2620
|
+
"ArrowFunctionExpression"
|
|
2621
|
+
].includes(node.type)) {
|
|
2622
|
+
if (node.id) collect(node.id);
|
|
2623
|
+
for (const param of node.params) collect(param);
|
|
2624
|
+
} else if (node.type === "CatchClause" && node.param) collect(node.param);
|
|
2625
|
+
else if (node.type === "ClassDeclaration" && node.id) collect(node.id);
|
|
2626
|
+
});
|
|
2627
|
+
walk(ast, (node) => {
|
|
2628
|
+
if (node.type !== "CallExpression" || node.optional || node.callee.type !== "Identifier") return;
|
|
2629
|
+
const name = node.callee.name;
|
|
2630
|
+
if (declared.has(name) || name.startsWith("__")) return;
|
|
2631
|
+
ms.overwrite(node.callee.start, node.callee.end, `(typeof ${name} === "undefined" ? ${MissingToolIdentifier}(${JSON.stringify(name)}) : ${name})`);
|
|
2632
|
+
});
|
|
2633
|
+
}
|
|
2634
|
+
//#endregion
|
|
2635
|
+
//#region src/compiler/plugins/variable-extraction.ts
|
|
2636
|
+
const VariableTrackingFnIdentifier = "__var__";
|
|
2637
|
+
const FUNCTION_TYPES = /* @__PURE__ */ new Set([
|
|
2638
|
+
"FunctionDeclaration",
|
|
2639
|
+
"FunctionExpression",
|
|
2640
|
+
"ArrowFunctionExpression"
|
|
2641
|
+
]);
|
|
2642
|
+
const RESERVED = RESERVED_RUNTIME_NAMES;
|
|
2643
|
+
function names(id) {
|
|
2644
|
+
if (!id) return [];
|
|
2645
|
+
if (id.type === "Identifier") return [id.name];
|
|
2646
|
+
if (id.type === "RestElement") return names(id.argument);
|
|
2647
|
+
if (id.type === "AssignmentPattern") return names(id.left);
|
|
2648
|
+
if (id.type === "ObjectPattern") return id.properties.flatMap((prop) => names(prop.type === "RestElement" ? prop.argument : prop.value));
|
|
2649
|
+
if (id.type === "ArrayPattern") return id.elements.flatMap(names);
|
|
2650
|
+
return [];
|
|
2651
|
+
}
|
|
2652
|
+
function rootName(node) {
|
|
2653
|
+
if (node.type === "Identifier") return node.name;
|
|
2654
|
+
if (node.type === "MemberExpression") return rootName(node.object);
|
|
2655
|
+
}
|
|
2656
|
+
/** Capture only session-level bindings, and record completed writes without changing expression values. */
|
|
2657
|
+
function applyVariableTracking(ctx, variables, deferSuffixes = false) {
|
|
2658
|
+
const suffixes = [];
|
|
2659
|
+
const wrapper = ctx.ast.body.find((node) => {
|
|
2660
|
+
var _node$id;
|
|
2661
|
+
return node.type === "FunctionDeclaration" && ((_node$id = node.id) === null || _node$id === void 0 ? void 0 : _node$id.name) === "__fn__";
|
|
2662
|
+
});
|
|
2663
|
+
const root = (wrapper === null || wrapper === void 0 ? void 0 : wrapper.body) ?? ctx.ast;
|
|
2664
|
+
const scopes = /* @__PURE__ */ new Map();
|
|
2665
|
+
const sessionDeclarations = /* @__PURE__ */ new Set();
|
|
2666
|
+
const varBindings = /* @__PURE__ */ new Set();
|
|
2667
|
+
const scope = (node) => {
|
|
2668
|
+
if (!scopes.has(node)) scopes.set(node, /* @__PURE__ */ new Set());
|
|
2669
|
+
return scopes.get(node);
|
|
2670
|
+
};
|
|
2671
|
+
const owner = (ancestors, isVar = false) => [...ancestors].reverse().find((node) => node === root || node.type === "Program" || node.type === "StaticBlock" || FUNCTION_TYPES.has(node.type) || !isVar && (node.type === "BlockStatement" || node.type === "SwitchStatement" || node.type === "CatchClause" || node.type === "ForStatement" || node.type === "ForOfStatement" || node.type === "ForInStatement")) ?? root;
|
|
2672
|
+
walk(ctx.ast, (node, parent, ancestors) => {
|
|
2673
|
+
let declared = [];
|
|
2674
|
+
if (node.type === "VariableDeclarator") {
|
|
2675
|
+
declared = names(node.id);
|
|
2676
|
+
const bindingScope = owner(ancestors, (parent === null || parent === void 0 ? void 0 : parent.kind) === "var");
|
|
2677
|
+
for (const name of declared) scope(bindingScope).add(name);
|
|
2678
|
+
if (bindingScope === root) {
|
|
2679
|
+
sessionDeclarations.add(node);
|
|
2680
|
+
for (const name of declared.filter((name) => !name.startsWith("__"))) {
|
|
2681
|
+
variables.add(name);
|
|
2682
|
+
if ((parent === null || parent === void 0 ? void 0 : parent.kind) === "var") varBindings.add(name);
|
|
2683
|
+
}
|
|
2684
|
+
}
|
|
2685
|
+
} else if (FUNCTION_TYPES.has(node.type)) {
|
|
2686
|
+
declared = node.params.flatMap(names);
|
|
2687
|
+
if (node.id) declared.push(node.id.name);
|
|
2688
|
+
for (const name of declared) scope(node).add(name);
|
|
2689
|
+
} else if (node.type === "CatchClause" && node.param) {
|
|
2690
|
+
declared = names(node.param);
|
|
2691
|
+
for (const name of declared) scope(node).add(name);
|
|
2692
|
+
}
|
|
2693
|
+
for (const name of declared) if (RESERVED.has(name)) throw new ReservedIdentifierError(name, "variable", false, `${name} is reserved for runtime memory`);
|
|
2694
|
+
});
|
|
2695
|
+
const eligible = (name, ancestors) => {
|
|
2696
|
+
if (name.startsWith("__")) return false;
|
|
2697
|
+
for (const ancestor of [...ancestors].reverse()) {
|
|
2698
|
+
var _scopes$get;
|
|
2699
|
+
if (ancestor === root) return true;
|
|
2700
|
+
if ((_scopes$get = scopes.get(ancestor)) === null || _scopes$get === void 0 ? void 0 : _scopes$get.has(name)) return false;
|
|
2701
|
+
}
|
|
2702
|
+
return true;
|
|
2703
|
+
};
|
|
2704
|
+
const wrap = (node, bindingNames, kind = "assignment") => {
|
|
2705
|
+
if (!bindingNames.length) return;
|
|
2706
|
+
ctx.ms.appendLeft(node.start, bindingNames.map((name) => `${VariableTrackingFnIdentifier}(${JSON.stringify(name)}, () => eval(${JSON.stringify(name)}), (`).join(""));
|
|
2707
|
+
suffixes.unshift(() => ctx.ms.appendRight(node.end, bindingNames.map(() => `), ${JSON.stringify(kind)})`).join("")));
|
|
2708
|
+
};
|
|
2709
|
+
const varGetters = [...varBindings].map((name) => `${VariableTrackingFnIdentifier}(${JSON.stringify(name)}, () => eval(${JSON.stringify(name)}), undefined, "initialize");`).join("");
|
|
2710
|
+
const entry = root.body.find((node) => !node.directive);
|
|
2711
|
+
if (entry && varGetters) ctx.ms.appendLeft(entry.start, varGetters);
|
|
2712
|
+
walk(ctx.ast, (node, parent, ancestors) => {
|
|
2713
|
+
if (node.type === "VariableDeclaration" && parent === root && node.kind !== "var") {
|
|
2714
|
+
const declared = node.declarations.flatMap((declaration) => names(declaration.id)).filter((name) => variables.has(name));
|
|
2715
|
+
ctx.ms.appendLeft(node.start, declared.map((name) => `${VariableTrackingFnIdentifier}(${JSON.stringify(name)}, () => eval(${JSON.stringify(name)}), undefined, "initialize");`).join(""));
|
|
2716
|
+
}
|
|
2717
|
+
if (node.type === "VariableDeclarator" && sessionDeclarations.has(node)) {
|
|
2718
|
+
const declared = names(node.id).filter((name) => variables.has(name) && eligible(name, ancestors));
|
|
2719
|
+
if (node.init) wrap(node.init, declared);
|
|
2720
|
+
else if (parent && parent.kind !== "var") {
|
|
2721
|
+
const trackers = declared.map((name) => `${VariableTrackingFnIdentifier}(${JSON.stringify(name)}, () => eval(${JSON.stringify(name)}));`).join("");
|
|
2722
|
+
ctx.ms.appendRight(parent.end, `${ctx.code[parent.end - 1] === ";" ? "" : ";"}${trackers}`);
|
|
2723
|
+
}
|
|
2724
|
+
}
|
|
2725
|
+
if ((node.type === "ForOfStatement" || node.type === "ForInStatement") && node.left.type === "VariableDeclaration") {
|
|
2726
|
+
const declared = node.left.declarations.filter((declaration) => sessionDeclarations.has(declaration)).flatMap((declaration) => names(declaration.id)).filter((name) => eligible(name, ancestors));
|
|
2727
|
+
if (declared.length) {
|
|
2728
|
+
const trackers = declared.map((name) => `${VariableTrackingFnIdentifier}(${JSON.stringify(name)}, () => eval(${JSON.stringify(name)}));`).join("");
|
|
2729
|
+
ctx.ms.appendLeft(node.body.start, `{${trackers}`);
|
|
2730
|
+
suffixes.unshift(() => ctx.ms.appendRight(node.body.end, "}"));
|
|
2731
|
+
}
|
|
2732
|
+
}
|
|
2733
|
+
if (node.type === "AssignmentExpression" || node.type === "UpdateExpression" || node.type === "UnaryExpression" && node.operator === "delete") {
|
|
2734
|
+
const target = node.left ?? node.argument;
|
|
2735
|
+
const roots = target.type === "MemberExpression" ? [rootName(target)].filter(Boolean) : names(target);
|
|
2736
|
+
for (const name of roots) if (RESERVED.has(name)) throw new AssignmentError(`${name} is read-only runtime memory`);
|
|
2737
|
+
const tracked = [...new Set(roots)].filter((name) => eligible(name, ancestors));
|
|
2738
|
+
const kind = target.type === "MemberExpression" ? "mutation" : "assignment";
|
|
2739
|
+
if ([
|
|
2740
|
+
"||=",
|
|
2741
|
+
"&&=",
|
|
2742
|
+
"??="
|
|
2743
|
+
].includes(node.operator)) {
|
|
2744
|
+
if (target.type === "Identifier" && tracked.length) {
|
|
2745
|
+
const name = tracked[0];
|
|
2746
|
+
const operator = node.operator.slice(0, -1);
|
|
2747
|
+
const lineBreaks = ctx.code.slice(target.end, node.right.start).replace(/[^\n]/g, "");
|
|
2748
|
+
ctx.ms.appendLeft(node.start, "(");
|
|
2749
|
+
ctx.ms.overwrite(target.end, node.right.start, ` ${operator} ${lineBreaks}`);
|
|
2750
|
+
ctx.ms.appendLeft(node.right.start, `${VariableTrackingFnIdentifier}(${JSON.stringify(name)}, () => eval(${JSON.stringify(name)}), (${name} = (`);
|
|
2751
|
+
suffixes.unshift(() => ctx.ms.appendRight(node.end, `)), "assignment"))`));
|
|
2752
|
+
}
|
|
2753
|
+
return;
|
|
2754
|
+
}
|
|
2755
|
+
wrap(node, tracked, kind);
|
|
2756
|
+
}
|
|
2757
|
+
});
|
|
2758
|
+
const finish = () => suffixes.forEach((apply) => apply());
|
|
2759
|
+
if (!deferSuffixes) finish();
|
|
2760
|
+
return finish;
|
|
2761
|
+
}
|
|
2762
|
+
//#endregion
|
|
2763
|
+
//#region src/compiler/compiler.ts
|
|
2764
|
+
const Identifiers = {
|
|
2765
|
+
ConsoleObjIdentifier: "console",
|
|
2766
|
+
LineTrackingFnIdentifier,
|
|
2767
|
+
VariableTrackingFnIdentifier,
|
|
2768
|
+
CommentFnIdentifier
|
|
2769
|
+
};
|
|
2770
|
+
/**
|
|
2771
|
+
* Compiles the agent's generated JavaScript for VM execution:
|
|
2772
|
+
*
|
|
2773
|
+
* 1. wraps it in an async `__fn__` so top-level `await`/`return` parse
|
|
2774
|
+
* 2. instruments it in a single parse + text-edit pass:
|
|
2775
|
+
* line tracking, last-line awaiting, comment tracing and variable tracking
|
|
2776
|
+
* 3. unwraps it — the VM drivers re-wrap the bare statements themselves
|
|
2777
|
+
*
|
|
2778
|
+
* All edits preserve line numbers 1:1 with the wrapped source, so positions
|
|
2779
|
+
* reported at runtime map straight back to the user code.
|
|
2780
|
+
*/
|
|
2781
|
+
function compile(code) {
|
|
2782
|
+
try {
|
|
2783
|
+
return compileProgram(code);
|
|
2784
|
+
} catch (cause) {
|
|
2785
|
+
if (isLLMzError(cause)) throw cause;
|
|
2786
|
+
throw new InvalidCodeError(cause instanceof Error ? cause.message : String(cause), code, { cause });
|
|
2787
|
+
}
|
|
2788
|
+
}
|
|
2789
|
+
function compileProgram(code) {
|
|
2790
|
+
const wrapped = AsyncWrapper.preProcessing(code);
|
|
2791
|
+
const comments = [];
|
|
2792
|
+
const ast = parseScript(wrapped, { comments });
|
|
2793
|
+
rejectDynamicCode(ast);
|
|
2794
|
+
const variables = /* @__PURE__ */ new Set();
|
|
2795
|
+
const lastLine = planLastLineInstrumentation(ast);
|
|
2796
|
+
const msMarkers = new MagicString(wrapped);
|
|
2797
|
+
if (lastLine) {
|
|
2798
|
+
msMarkers.appendLeft(lastLine.prefixPos, lastLine.prefix);
|
|
2799
|
+
msMarkers.appendRight(lastLine.suffixPos, lastLine.suffix);
|
|
2800
|
+
}
|
|
2801
|
+
const codeWithMarkers = msMarkers.toString();
|
|
2802
|
+
const ms = new MagicString(wrapped);
|
|
2803
|
+
const ctx = {
|
|
2804
|
+
code: wrapped,
|
|
2805
|
+
ms,
|
|
2806
|
+
ast,
|
|
2807
|
+
comments
|
|
2808
|
+
};
|
|
2809
|
+
applyToolResolution(ctx);
|
|
2810
|
+
applyLineTracking(ctx);
|
|
2811
|
+
if (lastLine) ms.appendLeft(lastLine.prefixPos, lastLine.prefix);
|
|
2812
|
+
const finishVariableTracking = applyVariableTracking(ctx, variables, true);
|
|
2813
|
+
applyCommentReplacement(ctx);
|
|
2814
|
+
finishVariableTracking();
|
|
2815
|
+
if (lastLine) ms.appendRight(lastLine.suffixPos, lastLine.suffix);
|
|
2816
|
+
const instrumented = ms.toString();
|
|
2817
|
+
const terminationSource = new MagicString(instrumented);
|
|
2818
|
+
applyTerminationGuards({
|
|
2819
|
+
code: instrumented,
|
|
2820
|
+
ms: terminationSource,
|
|
2821
|
+
ast: parseScript(instrumented),
|
|
2822
|
+
comments: []
|
|
2823
|
+
})();
|
|
2824
|
+
const firstMap = ms.generateMap({
|
|
2825
|
+
hires: true,
|
|
2826
|
+
source: "<anonymous>"
|
|
2827
|
+
});
|
|
2828
|
+
const secondMap = terminationSource.generateMap({
|
|
2829
|
+
hires: true,
|
|
2830
|
+
source: "<instrumented>"
|
|
2831
|
+
});
|
|
2832
|
+
const map = import_source_map.SourceMapGenerator.fromSourceMap(new import_source_map.SourceMapConsumer(JSON.parse(secondMap.toString())));
|
|
2833
|
+
map.applySourceMap(new import_source_map.SourceMapConsumer(JSON.parse(firstMap.toString())), "<instrumented>");
|
|
2834
|
+
return {
|
|
2835
|
+
code: AsyncWrapper.postProcessing(terminationSource.toString()),
|
|
2836
|
+
codeWithMarkers,
|
|
2837
|
+
map: map.toJSON(),
|
|
2838
|
+
variables
|
|
2839
|
+
};
|
|
2840
|
+
}
|
|
2841
|
+
//#endregion
|
|
2842
|
+
//#region src/vm/errors.ts
|
|
2843
|
+
const handleErrorQuickJS = (err, code, _consumer, traces, variables, lines_executed, userCodeStartLine, recordTrace) => {
|
|
2214
2844
|
err = Signals.maybeDeserializeError(err);
|
|
2215
2845
|
const lines = code.split("\n");
|
|
2216
2846
|
const stackTrace = err.stack || "";
|
|
@@ -2235,9 +2865,9 @@ const handleErrorQuickJS = (err, code, _consumer, traces, variables, lines_execu
|
|
|
2235
2865
|
column: whiteSpacesCount
|
|
2236
2866
|
});
|
|
2237
2867
|
}
|
|
2238
|
-
return formatError(err, lines, matches, traces, variables, lines_executed,
|
|
2868
|
+
return formatError(err, lines, matches, traces, variables, lines_executed, code, recordTrace);
|
|
2239
2869
|
};
|
|
2240
|
-
const handleErrorNode = (err, code, consumer,
|
|
2870
|
+
const handleErrorNode = (err, code, consumer, recordTrace, variables, _lines_executed, lastExecutedLine) => {
|
|
2241
2871
|
err = Signals.maybeDeserializeError(err);
|
|
2242
2872
|
const lines = code.split("\n");
|
|
2243
2873
|
const stackTrace = err.stack || "";
|
|
@@ -2260,32 +2890,39 @@ const handleErrorNode = (err, code, consumer, traces, variables, _lines_executed
|
|
|
2260
2890
|
column: Math.min(minColumn, Number(x[2]))
|
|
2261
2891
|
};
|
|
2262
2892
|
});
|
|
2893
|
+
if (!matches.length && lastExecutedLine !== void 0) {
|
|
2894
|
+
const sourceLine = lines[lastExecutedLine - LINE_OFFSET] ?? "";
|
|
2895
|
+
matches.push({
|
|
2896
|
+
line: lastExecutedLine,
|
|
2897
|
+
column: sourceLine.length - sourceLine.trimStart().length
|
|
2898
|
+
});
|
|
2899
|
+
}
|
|
2263
2900
|
const { debugUserCode, truncatedCode } = buildDebugCode(lines, matches);
|
|
2264
|
-
if (err
|
|
2901
|
+
if (VMSignal.is(err)) {
|
|
2265
2902
|
err.stack = debugUserCode;
|
|
2266
2903
|
err.truncatedCode = truncatedCode;
|
|
2267
2904
|
err.variables = mapValues(variables, (getter) => isFunction(getter) ? getter() : getter);
|
|
2268
|
-
err.toolCall = currentToolCall;
|
|
2269
2905
|
throw err;
|
|
2270
2906
|
} else {
|
|
2271
2907
|
var _matches$, _matches$2;
|
|
2272
|
-
|
|
2908
|
+
recordTrace({
|
|
2273
2909
|
type: "code_execution_exception",
|
|
2274
2910
|
position: [((_matches$ = matches[0]) === null || _matches$ === void 0 ? void 0 : _matches$.line) ?? 0, ((_matches$2 = matches[0]) === null || _matches$2 === void 0 ? void 0 : _matches$2.column) ?? 0],
|
|
2275
2911
|
message: err.message,
|
|
2276
2912
|
stackTrace: debugUserCode,
|
|
2277
2913
|
started_at: Date.now()
|
|
2278
2914
|
});
|
|
2279
|
-
|
|
2915
|
+
const originalErrorName = CodeExecutionError.is(err) ? err.originalErrorName : err.name;
|
|
2916
|
+
throw new CodeExecutionError(err.message, code, debugUserCode, originalErrorName, err);
|
|
2280
2917
|
}
|
|
2281
2918
|
};
|
|
2282
2919
|
const handleCatch = (err, traces, variables, lines_executed) => {
|
|
2283
2920
|
err = Signals.maybeDeserializeError(err);
|
|
2284
2921
|
return {
|
|
2285
|
-
success: err
|
|
2922
|
+
success: VMSignal.is(err) ? true : false,
|
|
2286
2923
|
variables: mapValues(variables, (getter) => isFunction(getter) ? getter() : getter),
|
|
2287
2924
|
error: err,
|
|
2288
|
-
signal: err
|
|
2925
|
+
signal: VMSignal.is(err) ? err : void 0,
|
|
2289
2926
|
traces,
|
|
2290
2927
|
lines_executed: Array.from(lines_executed)
|
|
2291
2928
|
};
|
|
@@ -2315,18 +2952,16 @@ function buildDebugCode(lines, matches) {
|
|
|
2315
2952
|
} else appendCode(` ${paddedLineNumber} | ${line}\n`);
|
|
2316
2953
|
}
|
|
2317
2954
|
return {
|
|
2318
|
-
debugUserCode:
|
|
2319
|
-
truncatedCode:
|
|
2955
|
+
debugUserCode: debugUserCode.trim(),
|
|
2956
|
+
truncatedCode: truncatedCode.trim()
|
|
2320
2957
|
};
|
|
2321
2958
|
}
|
|
2322
|
-
function formatError(err, lines, matches, traces, variables, lines_executed,
|
|
2959
|
+
function formatError(err, lines, matches, traces, variables, lines_executed, code, recordTrace) {
|
|
2323
2960
|
const { debugUserCode, truncatedCode } = buildDebugCode(lines, matches);
|
|
2324
|
-
if (err
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
signalError.variables = mapValues(variables, (getter) => isFunction(getter) ? getter() : getter);
|
|
2329
|
-
signalError.toolCall = currentToolCall;
|
|
2961
|
+
if (VMSignal.is(err)) {
|
|
2962
|
+
err.stack = debugUserCode;
|
|
2963
|
+
err.truncatedCode = truncatedCode;
|
|
2964
|
+
err.variables = mapValues(variables, (getter) => isFunction(getter) ? getter() : getter);
|
|
2330
2965
|
return {
|
|
2331
2966
|
success: true,
|
|
2332
2967
|
variables: mapValues(variables, (getter) => isFunction(getter) ? getter() : getter),
|
|
@@ -2335,14 +2970,15 @@ function formatError(err, lines, matches, traces, variables, lines_executed, cur
|
|
|
2335
2970
|
};
|
|
2336
2971
|
} else {
|
|
2337
2972
|
var _matches$3, _matches$4;
|
|
2338
|
-
|
|
2973
|
+
recordTrace({
|
|
2339
2974
|
type: "code_execution_exception",
|
|
2340
2975
|
position: [((_matches$3 = matches[0]) === null || _matches$3 === void 0 ? void 0 : _matches$3.line) ?? 0, ((_matches$4 = matches[0]) === null || _matches$4 === void 0 ? void 0 : _matches$4.column) ?? 0],
|
|
2341
2976
|
message: err.message,
|
|
2342
2977
|
stackTrace: debugUserCode,
|
|
2343
2978
|
started_at: Date.now()
|
|
2344
2979
|
});
|
|
2345
|
-
const
|
|
2980
|
+
const originalErrorName = CodeExecutionError.is(err) ? err.originalErrorName : err.name;
|
|
2981
|
+
const codeError = new CodeExecutionError(err.message, code, debugUserCode, originalErrorName, err);
|
|
2346
2982
|
const deserializedError = Signals.maybeDeserializeError(codeError);
|
|
2347
2983
|
return {
|
|
2348
2984
|
success: false,
|
|
@@ -2354,21 +2990,49 @@ function formatError(err, lines, matches, traces, variables, lines_executed, cur
|
|
|
2354
2990
|
}
|
|
2355
2991
|
}
|
|
2356
2992
|
//#endregion
|
|
2993
|
+
//#region src/vm/types.ts
|
|
2994
|
+
/** Host-only lifecycle hook; symbols are not copied into the generated program's globals. */
|
|
2995
|
+
const VM_PROGRAM_COMPLETE = Symbol("llmz.programComplete");
|
|
2996
|
+
const VM_TERMINATION = Symbol("llmz.termination");
|
|
2997
|
+
const VM_CALL_SITE = Symbol("llmz.callSite");
|
|
2998
|
+
const VM_ON_ERROR = Symbol("llmz.onError");
|
|
2999
|
+
//#endregion
|
|
2357
3000
|
//#region src/vm/instrument.ts
|
|
2358
3001
|
const USER_CODE_MARKER_TAG_START = "__LLMZ_USER_CODE_START__";
|
|
2359
3002
|
const USER_CODE_MARKER_TAG_END = "__LLMZ_USER_CODE_END__";
|
|
2360
3003
|
const NO_TRACKING = [
|
|
2361
3004
|
Identifiers.CommentFnIdentifier,
|
|
2362
|
-
Identifiers.ToolCallTrackerFnIdentifier,
|
|
2363
|
-
Identifiers.ToolTrackerRetIdentifier,
|
|
2364
3005
|
Identifiers.VariableTrackingFnIdentifier,
|
|
2365
|
-
Identifiers.ConsoleObjIdentifier
|
|
3006
|
+
Identifiers.ConsoleObjIdentifier,
|
|
3007
|
+
TerminationCheckpointIdentifier,
|
|
3008
|
+
TerminationGuardIdentifier
|
|
2366
3009
|
];
|
|
2367
|
-
function instrumentContext(context, transformed,
|
|
2368
|
-
const state = {
|
|
3010
|
+
function instrumentContext(context, transformed, recordTrace, variables, lines_executed, consumer, userCodeStartLine, memoryNames = []) {
|
|
3011
|
+
const state = {
|
|
3012
|
+
lastExecutedLine: void 0,
|
|
3013
|
+
memoryNames: /* @__PURE__ */ new Set([...memoryNames, ...transformed.variables]),
|
|
3014
|
+
variableWrites: [],
|
|
3015
|
+
captureErrors: []
|
|
3016
|
+
};
|
|
3017
|
+
context[MissingToolIdentifier] = (name) => {
|
|
3018
|
+
var _context$VM_ON_ERROR;
|
|
3019
|
+
const error = new UnknownToolError(name, Object.keys(context).filter((key) => !key.startsWith("__") && typeof context[key] === "function"));
|
|
3020
|
+
(_context$VM_ON_ERROR = context[VM_ON_ERROR]) === null || _context$VM_ON_ERROR === void 0 || _context$VM_ON_ERROR.call(context, error);
|
|
3021
|
+
throw error;
|
|
3022
|
+
};
|
|
3023
|
+
context[TerminationGuardIdentifier] = () => {
|
|
3024
|
+
var _context$VM_TERMINATI;
|
|
3025
|
+
return (_context$VM_TERMINATI = context[VM_TERMINATION]) === null || _context$VM_TERMINATI === void 0 ? void 0 : _context$VM_TERMINATI.check();
|
|
3026
|
+
};
|
|
3027
|
+
context[TerminationCheckpointIdentifier] = (value) => {
|
|
3028
|
+
var _context$VM_TERMINATI2;
|
|
3029
|
+
if (value instanceof Promise) Promise.prototype.then.call(value, void 0, () => {});
|
|
3030
|
+
(_context$VM_TERMINATI2 = context[VM_TERMINATION]) === null || _context$VM_TERMINATI2 === void 0 || _context$VM_TERMINATI2.check();
|
|
3031
|
+
return value;
|
|
3032
|
+
};
|
|
2369
3033
|
context[Identifiers.CommentFnIdentifier] = (comment, line) => {
|
|
2370
3034
|
if (comment.includes(USER_CODE_MARKER_TAG_START) || comment.includes(USER_CODE_MARKER_TAG_END)) return;
|
|
2371
|
-
|
|
3035
|
+
recordTrace({
|
|
2372
3036
|
type: "comment",
|
|
2373
3037
|
comment,
|
|
2374
3038
|
line,
|
|
@@ -2381,35 +3045,33 @@ function instrumentContext(context, transformed, traces, variables, lines_execut
|
|
|
2381
3045
|
column: 0
|
|
2382
3046
|
}).line ?? line;
|
|
2383
3047
|
const userCodeLine = Math.max(1, mappedLine - userCodeStartLine);
|
|
3048
|
+
state.lastExecutedLine = userCodeLine;
|
|
2384
3049
|
lines_executed.set(userCodeLine, (lines_executed.get(userCodeLine) ?? 0) + 1);
|
|
2385
3050
|
};
|
|
2386
|
-
context[Identifiers.VariableTrackingFnIdentifier] = (name, getter) => {
|
|
2387
|
-
if (NO_TRACKING.includes(name)) return;
|
|
3051
|
+
context[Identifiers.VariableTrackingFnIdentifier] = (name, getter, result, kind = "assignment") => {
|
|
3052
|
+
if (NO_TRACKING.includes(name) || !state.memoryNames.has(name)) return result;
|
|
3053
|
+
if (kind !== "initialize" && kind !== "read") state.variableWrites.push({
|
|
3054
|
+
name,
|
|
3055
|
+
timestamp: Date.now(),
|
|
3056
|
+
kind
|
|
3057
|
+
});
|
|
2388
3058
|
variables[name] = () => {
|
|
2389
3059
|
try {
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
3060
|
+
return getter();
|
|
3061
|
+
} catch (err) {
|
|
3062
|
+
if (!state.captureErrors.some((entry) => entry.name === name)) state.captureErrors.push({
|
|
3063
|
+
name,
|
|
3064
|
+
reason: err instanceof Error ? err.message : String(err)
|
|
3065
|
+
});
|
|
3066
|
+
return;
|
|
2395
3067
|
}
|
|
2396
3068
|
};
|
|
2397
|
-
|
|
2398
|
-
context[Identifiers.ToolCallTrackerFnIdentifier] = (callId, type, outputOrError) => {
|
|
2399
|
-
const temp = Signals.maybeDeserializeError(outputOrError === null || outputOrError === void 0 ? void 0 : outputOrError.message);
|
|
2400
|
-
if (type === "end" && temp instanceof SnapshotSignal && (temp === null || temp === void 0 ? void 0 : temp.toolCall)) {
|
|
2401
|
-
var _transformed$toolCall;
|
|
2402
|
-
state.currentToolCall = {
|
|
2403
|
-
...temp.toolCall,
|
|
2404
|
-
assignment: (_transformed$toolCall = transformed.toolCalls.get(callId)) === null || _transformed$toolCall === void 0 ? void 0 : _transformed$toolCall.assignment
|
|
2405
|
-
};
|
|
2406
|
-
}
|
|
3069
|
+
return result;
|
|
2407
3070
|
};
|
|
2408
3071
|
context[Identifiers.ConsoleObjIdentifier] = { log: (...args) => {
|
|
2409
|
-
|
|
2410
|
-
traces.push({
|
|
3072
|
+
recordTrace({
|
|
2411
3073
|
type: "log",
|
|
2412
|
-
message,
|
|
3074
|
+
message: args.shift(),
|
|
2413
3075
|
args,
|
|
2414
3076
|
started_at: Date.now()
|
|
2415
3077
|
});
|
|
@@ -2424,14 +3086,54 @@ function findUserCodeStartLine(transformed) {
|
|
|
2424
3086
|
}
|
|
2425
3087
|
return -1;
|
|
2426
3088
|
}
|
|
3089
|
+
/** Drop unsupported captures explicitly instead of presenting lossy placeholders as data. */
|
|
3090
|
+
function finalizeMemoryCapture(result, state) {
|
|
3091
|
+
for (const [name, value] of Object.entries(result.variables)) try {
|
|
3092
|
+
result.variables[name] = cloneMemoryValue(value);
|
|
3093
|
+
} catch (err) {
|
|
3094
|
+
if (!state.captureErrors.some((entry) => entry.name === name)) state.captureErrors.push({
|
|
3095
|
+
name,
|
|
3096
|
+
reason: err instanceof Error ? err.message : String(err)
|
|
3097
|
+
});
|
|
3098
|
+
}
|
|
3099
|
+
for (const failure of state.captureErrors) {
|
|
3100
|
+
var _result$signal;
|
|
3101
|
+
delete result.variables[failure.name];
|
|
3102
|
+
if ((_result$signal = result.signal) === null || _result$signal === void 0 ? void 0 : _result$signal.variables) delete result.signal.variables[failure.name];
|
|
3103
|
+
}
|
|
3104
|
+
if (result.success && !result.signal) try {
|
|
3105
|
+
result.return_value = cloneMemoryValue(result.return_value);
|
|
3106
|
+
} catch (err) {
|
|
3107
|
+
if (!state.captureErrors.some((entry) => entry.name === "$return")) state.captureErrors.push({
|
|
3108
|
+
name: "$return",
|
|
3109
|
+
reason: err instanceof Error ? err.message : String(err)
|
|
3110
|
+
});
|
|
3111
|
+
result.return_value = void 0;
|
|
3112
|
+
}
|
|
3113
|
+
return {
|
|
3114
|
+
...result,
|
|
3115
|
+
variableWrites: state.variableWrites,
|
|
3116
|
+
captureErrors: state.captureErrors
|
|
3117
|
+
};
|
|
3118
|
+
}
|
|
2427
3119
|
//#endregion
|
|
2428
3120
|
//#region src/vm/drivers/node.ts
|
|
2429
3121
|
var NodeDriver = class {
|
|
2430
3122
|
async execute(ctx) {
|
|
2431
|
-
const { transformed, consumer, context, traces, code, lines_executed, variables } = ctx;
|
|
2432
|
-
const state = instrumentContext(context, transformed,
|
|
3123
|
+
const { transformed, consumer, context, traces, recordTrace, code, lines_executed, variables } = ctx;
|
|
3124
|
+
const state = instrumentContext(context, transformed, recordTrace, variables, lines_executed, consumer, findUserCodeStartLine(transformed), ctx.memoryNames);
|
|
3125
|
+
context[VM_CALL_SITE] = () => {
|
|
3126
|
+
var _Error$stack;
|
|
3127
|
+
const frame = (_Error$stack = (/* @__PURE__ */ new Error()).stack) === null || _Error$stack === void 0 ? void 0 : _Error$stack.match(/<anonymous>:(\d+):(\d+)/);
|
|
3128
|
+
if (!frame) return;
|
|
3129
|
+
const position = consumer.originalPositionFor({
|
|
3130
|
+
line: Number(frame[1]) - 1,
|
|
3131
|
+
column: Number(frame[2])
|
|
3132
|
+
});
|
|
3133
|
+
return position.line ? Math.max(1, position.line - 3) : void 0;
|
|
3134
|
+
};
|
|
2433
3135
|
const AsyncFunction = async function() {}.constructor;
|
|
2434
|
-
return await (async () => {
|
|
3136
|
+
return finalizeMemoryCapture(await (async () => {
|
|
2435
3137
|
const descriptors = Object.getOwnPropertyDescriptors(context);
|
|
2436
3138
|
const topLevelProperties = Object.keys(descriptors).filter((x) => !NO_TRACKING.includes(x) && descriptors[x] && typeof descriptors[x].value !== "function" && typeof descriptors[x].value !== "object");
|
|
2437
3139
|
const __report = (name, value) => {
|
|
@@ -2439,21 +3141,59 @@ var NodeDriver = class {
|
|
|
2439
3141
|
};
|
|
2440
3142
|
context.__report = __report;
|
|
2441
3143
|
const reportAll = topLevelProperties.map((x) => `__report("${x}", ${x})`).join(";");
|
|
2442
|
-
const
|
|
2443
|
-
|
|
3144
|
+
const assigner = `let __${Identifiers.LineTrackingFnIdentifier} = ${Identifiers.LineTrackingFnIdentifier}; ${Identifiers.LineTrackingFnIdentifier} = function(line) { ${reportAll}; __${Identifiers.LineTrackingFnIdentifier}(line);}`;
|
|
3145
|
+
const trackInputs = ctx.memoryNames.map((name) => `${Identifiers.VariableTrackingFnIdentifier}(${JSON.stringify(name)}, () => eval(${JSON.stringify(name)}), undefined, "read");`).join("");
|
|
3146
|
+
const bindings = Object.keys(context);
|
|
3147
|
+
const protectedBindings = bindings.filter((name) => RESERVED_RUNTIME_NAMES.has(name)).map((name) => `const ${name} = __llmz_binding_${bindings.indexOf(name)};`).join("");
|
|
3148
|
+
const parameters = bindings.map((name, index) => RESERVED_RUNTIME_NAMES.has(name) ? `__llmz_binding_${index}` : name);
|
|
3149
|
+
const wrapper = `"use strict"; ${protectedBindings} try { ${assigner};${trackInputs}${transformed.code} } finally { ${reportAll} };`;
|
|
3150
|
+
const fn = AsyncFunction(...parameters, wrapper);
|
|
3151
|
+
try {
|
|
3152
|
+
return await fn(...Object.values(context));
|
|
3153
|
+
} finally {
|
|
3154
|
+
var _context$VM_PROGRAM_C;
|
|
3155
|
+
(_context$VM_PROGRAM_C = context[VM_PROGRAM_COMPLETE]) === null || _context$VM_PROGRAM_C === void 0 || _context$VM_PROGRAM_C.call(context);
|
|
3156
|
+
}
|
|
2444
3157
|
})().then((res) => {
|
|
3158
|
+
var _context$VM_TERMINATI, _context$VM_TERMINATI2, _context$VM_TERMINATI3;
|
|
3159
|
+
const signal = (_context$VM_TERMINATI = context[VM_TERMINATION]) === null || _context$VM_TERMINATI === void 0 || (_context$VM_TERMINATI2 = _context$VM_TERMINATI.getSignal) === null || _context$VM_TERMINATI2 === void 0 ? void 0 : _context$VM_TERMINATI2.call(_context$VM_TERMINATI);
|
|
3160
|
+
if (signal) throw signal;
|
|
3161
|
+
if ((_context$VM_TERMINATI3 = context[VM_TERMINATION]) === null || _context$VM_TERMINATI3 === void 0 ? void 0 : _context$VM_TERMINATI3.isTerminated()) res = void 0;
|
|
2445
3162
|
res = Signals.maybeDeserializeError(res);
|
|
2446
3163
|
return {
|
|
2447
3164
|
success: true,
|
|
2448
3165
|
variables: mapValues(variables, (getter) => isFunction(getter) ? getter() : getter),
|
|
2449
|
-
signal: res
|
|
3166
|
+
signal: VMSignal.is(res) ? res : void 0,
|
|
2450
3167
|
lines_executed: Array.from(lines_executed),
|
|
2451
3168
|
return_value: res
|
|
2452
3169
|
};
|
|
2453
|
-
}).catch((err) =>
|
|
3170
|
+
}).catch((err) => {
|
|
3171
|
+
var _context$VM_TERMINATI4, _context$VM_TERMINATI5, _context$VM_TERMINATI6;
|
|
3172
|
+
const signal = (_context$VM_TERMINATI4 = context[VM_TERMINATION]) === null || _context$VM_TERMINATI4 === void 0 || (_context$VM_TERMINATI5 = _context$VM_TERMINATI4.getSignal) === null || _context$VM_TERMINATI5 === void 0 ? void 0 : _context$VM_TERMINATI5.call(_context$VM_TERMINATI4);
|
|
3173
|
+
if (signal) return handleErrorNode(signal, code, consumer, recordTrace, variables, lines_executed, state.lastExecutedLine);
|
|
3174
|
+
if ((_context$VM_TERMINATI6 = context[VM_TERMINATION]) === null || _context$VM_TERMINATI6 === void 0 ? void 0 : _context$VM_TERMINATI6.isTerminated()) return {
|
|
3175
|
+
success: true,
|
|
3176
|
+
variables: mapValues(variables, (getter) => isFunction(getter) ? getter() : getter),
|
|
3177
|
+
lines_executed: Array.from(lines_executed)
|
|
3178
|
+
};
|
|
3179
|
+
return handleErrorNode(err, code, consumer, recordTrace, variables, lines_executed, state.lastExecutedLine);
|
|
3180
|
+
}).catch((err) => handleCatch(err, traces, variables, lines_executed)), state);
|
|
2454
3181
|
}
|
|
2455
3182
|
};
|
|
2456
3183
|
//#endregion
|
|
3184
|
+
//#region src/vm/member-proxy.ts
|
|
3185
|
+
/** Host-only metadata lets QuickJS install the same missing-member behavior in its own realm. */
|
|
3186
|
+
const MISSING_MEMBER = Symbol("llmz.missingMember");
|
|
3187
|
+
/** Only registered own members are callable; inherited Object methods are not API members. */
|
|
3188
|
+
function withMissingMember(target, missing) {
|
|
3189
|
+
Object.defineProperty(target, MISSING_MEMBER, { value: missing });
|
|
3190
|
+
Object.freeze(target);
|
|
3191
|
+
return new Proxy(target, { get(object, key, receiver) {
|
|
3192
|
+
if (typeof key === "string" && !Object.hasOwn(object, key)) return missing(key);
|
|
3193
|
+
return Reflect.get(object, key, receiver);
|
|
3194
|
+
} });
|
|
3195
|
+
}
|
|
3196
|
+
//#endregion
|
|
2457
3197
|
//#region src/vm/drivers/quickjs.ts
|
|
2458
3198
|
let _quickJSModule;
|
|
2459
3199
|
let _loadedVariant;
|
|
@@ -2467,9 +3207,27 @@ const loadQuickJSModule = () => {
|
|
|
2467
3207
|
};
|
|
2468
3208
|
var QuickJSDriver = class {
|
|
2469
3209
|
async execute(ctx) {
|
|
2470
|
-
const { transformed, consumer, context, traces, signal, timeout, code, lines_executed, variables } = ctx;
|
|
3210
|
+
const { transformed, consumer, context, traces, recordTrace, signal, timeout, code, lines_executed, variables } = ctx;
|
|
2471
3211
|
const userCodeStartLine = findUserCodeStartLine(transformed);
|
|
2472
|
-
const state = instrumentContext(context, transformed,
|
|
3212
|
+
const state = instrumentContext(context, transformed, recordTrace, variables, lines_executed, consumer, userCodeStartLine, ctx.memoryNames);
|
|
3213
|
+
const isTerminated = () => {
|
|
3214
|
+
var _context$VM_TERMINATI;
|
|
3215
|
+
return ((_context$VM_TERMINATI = context[VM_TERMINATION]) === null || _context$VM_TERMINATI === void 0 ? void 0 : _context$VM_TERMINATI.isTerminated()) ?? false;
|
|
3216
|
+
};
|
|
3217
|
+
const shouldStopJobs = () => {
|
|
3218
|
+
var _context$VM_TERMINATI2, _context$VM_TERMINATI3;
|
|
3219
|
+
return isTerminated() && !((_context$VM_TERMINATI2 = context[VM_TERMINATION]) === null || _context$VM_TERMINATI2 === void 0 || (_context$VM_TERMINATI3 = _context$VM_TERMINATI2.getSignal) === null || _context$VM_TERMINATI3 === void 0 ? void 0 : _context$VM_TERMINATI3.call(_context$VM_TERMINATI2));
|
|
3220
|
+
};
|
|
3221
|
+
const terminalResult = () => {
|
|
3222
|
+
var _context$VM_TERMINATI4, _context$VM_TERMINATI5;
|
|
3223
|
+
const interruption = (_context$VM_TERMINATI4 = context[VM_TERMINATION]) === null || _context$VM_TERMINATI4 === void 0 || (_context$VM_TERMINATI5 = _context$VM_TERMINATI4.getSignal) === null || _context$VM_TERMINATI5 === void 0 ? void 0 : _context$VM_TERMINATI5.call(_context$VM_TERMINATI4);
|
|
3224
|
+
if (interruption) return finalizeMemoryCapture(handleErrorQuickJS(interruption, code, consumer, traces, variables, lines_executed, userCodeStartLine, recordTrace), state);
|
|
3225
|
+
return finalizeMemoryCapture({
|
|
3226
|
+
success: true,
|
|
3227
|
+
variables: mapValues(variables, (getter) => isFunction(getter) ? getter() : getter),
|
|
3228
|
+
lines_executed: Array.from(lines_executed)
|
|
3229
|
+
}, state);
|
|
3230
|
+
};
|
|
2473
3231
|
const runtime = (await loadQuickJSModule()).newRuntime();
|
|
2474
3232
|
runtime.setMemoryLimit(134217728);
|
|
2475
3233
|
const timeoutHandler = shouldInterruptAfterDeadline(Date.now() + timeout);
|
|
@@ -2481,42 +3239,65 @@ var QuickJSDriver = class {
|
|
|
2481
3239
|
const trackedProperties = /* @__PURE__ */ new Set();
|
|
2482
3240
|
const referenceProperties = /* @__PURE__ */ new Set();
|
|
2483
3241
|
const pendingPromises = [];
|
|
2484
|
-
const
|
|
3242
|
+
const variableGetters = /* @__PURE__ */ new Map();
|
|
3243
|
+
let captureValue;
|
|
3244
|
+
const objectConstructor = vm.getProp(vm.global, "Object");
|
|
3245
|
+
const freezeFunction = vm.getProp(objectConstructor, "freeze");
|
|
3246
|
+
objectConstructor.dispose();
|
|
3247
|
+
const preserveHostFreeze = (hostValue, handle, preserveFrozen) => {
|
|
3248
|
+
if (!preserveFrozen || !Object.isFrozen(hostValue)) return handle;
|
|
3249
|
+
const frozen = vm.callFunction(freezeFunction, vm.undefined, handle);
|
|
3250
|
+
if ("error" in frozen) {
|
|
3251
|
+
const error = vm.dump(frozen.error);
|
|
3252
|
+
frozen.error.dispose();
|
|
3253
|
+
handle.dispose();
|
|
3254
|
+
throw new Error(error.message);
|
|
3255
|
+
}
|
|
3256
|
+
frozen.value.dispose();
|
|
3257
|
+
return handle;
|
|
3258
|
+
};
|
|
3259
|
+
const toVmValue = (value, preserveFrozen = false) => {
|
|
2485
3260
|
if (typeof value === "string") return vm.newString(value);
|
|
2486
3261
|
else if (typeof value === "number") return vm.newNumber(value);
|
|
2487
3262
|
else if (typeof value === "boolean") return value ? vm.true : vm.false;
|
|
2488
3263
|
else if (value === null) return vm.null;
|
|
2489
3264
|
else if (value === void 0) return vm.undefined;
|
|
2490
3265
|
else if (Array.isArray(value)) {
|
|
2491
|
-
const
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
else if (typeof item === "object") return JSON.stringify(item);
|
|
2497
|
-
return "undefined";
|
|
3266
|
+
const array = vm.newArray();
|
|
3267
|
+
value.forEach((item, index) => {
|
|
3268
|
+
const handle = toVmValue(item, preserveFrozen);
|
|
3269
|
+
vm.setProp(array, index, handle);
|
|
3270
|
+
disposeIfNeeded(handle);
|
|
2498
3271
|
});
|
|
2499
|
-
|
|
2500
|
-
if ("error" in result) {
|
|
2501
|
-
var _result$error;
|
|
2502
|
-
(_result$error = result.error) === null || _result$error === void 0 || _result$error.dispose();
|
|
2503
|
-
return vm.undefined;
|
|
2504
|
-
}
|
|
2505
|
-
return result.value;
|
|
3272
|
+
return preserveHostFreeze(value, array, preserveFrozen);
|
|
2506
3273
|
} else if (typeof value === "object") {
|
|
2507
3274
|
const obj = vm.newObject();
|
|
2508
3275
|
for (const [k, v] of Object.entries(value)) if (typeof v !== "function") {
|
|
2509
|
-
const propHandle = toVmValue(v);
|
|
3276
|
+
const propHandle = toVmValue(v, preserveFrozen);
|
|
2510
3277
|
vm.setProp(obj, k, propHandle);
|
|
2511
3278
|
disposeIfNeeded(propHandle);
|
|
2512
3279
|
}
|
|
2513
|
-
return obj;
|
|
3280
|
+
return preserveHostFreeze(value, obj, preserveFrozen);
|
|
2514
3281
|
}
|
|
2515
3282
|
return vm.undefined;
|
|
2516
3283
|
};
|
|
2517
3284
|
const disposeIfNeeded = (handle) => {
|
|
2518
3285
|
if (handle !== vm.true && handle !== vm.false && handle !== vm.null && handle !== vm.undefined) handle.dispose();
|
|
2519
3286
|
};
|
|
3287
|
+
context[VM_CALL_SITE] = () => {
|
|
3288
|
+
const stack = vm.evalCode("new Error().stack");
|
|
3289
|
+
if ("error" in stack) {
|
|
3290
|
+
var _stack$error;
|
|
3291
|
+
(_stack$error = stack.error) === null || _stack$error === void 0 || _stack$error.dispose();
|
|
3292
|
+
return;
|
|
3293
|
+
}
|
|
3294
|
+
try {
|
|
3295
|
+
const frame = vm.getString(stack.value).match(/<quickjs>:(\d+)/);
|
|
3296
|
+
return frame ? Math.max(1, Number(frame[1]) - 9 - userCodeStartLine + 1) : void 0;
|
|
3297
|
+
} finally {
|
|
3298
|
+
stack.value.dispose();
|
|
3299
|
+
}
|
|
3300
|
+
};
|
|
2520
3301
|
const bridgeFunction = (fn, _fnName = "anonymous") => {
|
|
2521
3302
|
return (...argHandles) => {
|
|
2522
3303
|
const args = argHandles.map((h) => vm.dump(h));
|
|
@@ -2524,36 +3305,94 @@ var QuickJSDriver = class {
|
|
|
2524
3305
|
const result = fn(...args);
|
|
2525
3306
|
if (result && typeof result.then === "function") {
|
|
2526
3307
|
const promise = vm.newPromise();
|
|
3308
|
+
const hostPromise = Promise.resolve(result).then((value) => cloneMemoryValue(value));
|
|
3309
|
+
hostPromise.catch(() => {});
|
|
2527
3310
|
pendingPromises.push({
|
|
2528
|
-
hostPromise
|
|
3311
|
+
hostPromise,
|
|
2529
3312
|
deferredPromise: promise
|
|
2530
3313
|
});
|
|
2531
3314
|
promise.settled.then(() => {
|
|
2532
|
-
if (runtime.alive) runtime.executePendingJobs();
|
|
3315
|
+
if (runtime.alive && !shouldStopJobs()) runtime.executePendingJobs();
|
|
2533
3316
|
});
|
|
2534
3317
|
return promise.handle;
|
|
2535
3318
|
}
|
|
2536
|
-
return toVmValue(result);
|
|
3319
|
+
return toVmValue(cloneMemoryValue(result));
|
|
2537
3320
|
} catch (err) {
|
|
2538
|
-
|
|
2539
|
-
throw new Error(serialized);
|
|
3321
|
+
return { error: guestError(vm, err) };
|
|
2540
3322
|
}
|
|
2541
3323
|
};
|
|
2542
3324
|
};
|
|
2543
3325
|
try {
|
|
2544
|
-
|
|
2545
|
-
|
|
3326
|
+
captureValue = setupMemoryCapture(vm);
|
|
3327
|
+
bridgeContextToVM(context, vm, trackedProperties, referenceProperties, toVmValue, disposeIfNeeded, bridgeFunction, captureValue);
|
|
3328
|
+
setupVariableTrackingBridge(vm, variables, variableGetters, state, captureValue);
|
|
3329
|
+
vm.evalCode(`(() => {
|
|
3330
|
+
const then = Promise.prototype.then;
|
|
3331
|
+
const check = globalThis.${TerminationGuardIdentifier};
|
|
3332
|
+
globalThis.${TerminationCheckpointIdentifier} = (value) => {
|
|
3333
|
+
if (value instanceof Promise) {
|
|
3334
|
+
then.call(value, undefined, () => {});
|
|
3335
|
+
}
|
|
3336
|
+
check();
|
|
3337
|
+
return value;
|
|
3338
|
+
};
|
|
3339
|
+
})()`).unwrap().dispose();
|
|
3340
|
+
const complete = vm.newFunction("__llmz_program_complete", () => {
|
|
3341
|
+
var _context$VM_PROGRAM_C;
|
|
3342
|
+
(_context$VM_PROGRAM_C = context[VM_PROGRAM_COMPLETE]) === null || _context$VM_PROGRAM_C === void 0 || _context$VM_PROGRAM_C.call(context);
|
|
3343
|
+
return vm.undefined;
|
|
3344
|
+
});
|
|
3345
|
+
vm.setProp(vm.global, "__llmz_program_complete", complete);
|
|
3346
|
+
complete.dispose();
|
|
3347
|
+
for (const name of ctx.memoryNames) {
|
|
3348
|
+
const tracked = vm.evalCode(`${Identifiers.VariableTrackingFnIdentifier}(${JSON.stringify(name)}, () => globalThis[${JSON.stringify(name)}], undefined, "read");`);
|
|
3349
|
+
if ("error" in tracked) {
|
|
3350
|
+
var _tracked$error;
|
|
3351
|
+
(_tracked$error = tracked.error) === null || _tracked$error === void 0 || _tracked$error.dispose();
|
|
3352
|
+
} else tracked.value.dispose();
|
|
3353
|
+
}
|
|
3354
|
+
const protect = vm.evalCode(`(() => {
|
|
3355
|
+
function freeze(value) {
|
|
3356
|
+
if (value && (typeof value === 'object' || typeof value === 'function') && !Object.isFrozen(value)) {
|
|
3357
|
+
Object.values(value).forEach(freeze);
|
|
3358
|
+
Object.freeze(value);
|
|
3359
|
+
}
|
|
3360
|
+
return value;
|
|
3361
|
+
}
|
|
3362
|
+
for (const name of ${JSON.stringify([
|
|
3363
|
+
...RUNTIME_BINDING_NAMES,
|
|
3364
|
+
...TERMINATION_BINDING_NAMES,
|
|
3365
|
+
"__llmz_program_complete"
|
|
3366
|
+
])}) {
|
|
3367
|
+
if (Object.prototype.hasOwnProperty.call(globalThis, name)) {
|
|
3368
|
+
Object.defineProperty(globalThis, name, {
|
|
3369
|
+
value: freeze(globalThis[name]),
|
|
3370
|
+
writable: false,
|
|
3371
|
+
configurable: false,
|
|
3372
|
+
});
|
|
3373
|
+
}
|
|
3374
|
+
}
|
|
3375
|
+
})()`);
|
|
3376
|
+
if ("error" in protect) {
|
|
3377
|
+
const error = vm.dump(protect.error);
|
|
3378
|
+
protect.error.dispose();
|
|
3379
|
+
throw new Error(error.message);
|
|
3380
|
+
}
|
|
3381
|
+
protect.value.dispose();
|
|
2546
3382
|
const scriptCode = buildScriptCode(transformed.code);
|
|
2547
3383
|
const copyBackContextFromVM = () => {
|
|
2548
3384
|
for (const key of trackedProperties) {
|
|
2549
3385
|
if (referenceProperties.has(key)) continue;
|
|
2550
3386
|
try {
|
|
2551
|
-
const
|
|
2552
|
-
const vmValue = vm.dump(valueResult.unwrap());
|
|
2553
|
-
valueResult.unwrap().dispose();
|
|
3387
|
+
const handle = vm.evalCode(`globalThis['${key}']`).unwrap();
|
|
2554
3388
|
try {
|
|
2555
|
-
|
|
2556
|
-
|
|
3389
|
+
const vmValue = ctx.memoryNames.includes(key) ? captureValue(handle) : vm.dump(handle);
|
|
3390
|
+
try {
|
|
3391
|
+
context[key] = vmValue;
|
|
3392
|
+
} catch {}
|
|
3393
|
+
} finally {
|
|
3394
|
+
handle.dispose();
|
|
3395
|
+
}
|
|
2557
3396
|
} catch {}
|
|
2558
3397
|
}
|
|
2559
3398
|
};
|
|
@@ -2567,7 +3406,11 @@ var QuickJSDriver = class {
|
|
|
2567
3406
|
throw new Error("Execution failed");
|
|
2568
3407
|
}
|
|
2569
3408
|
execResult.value.dispose();
|
|
2570
|
-
await this._pumpEventLoop(runtime, vm, pendingPromises, signal, toVmValue, disposeIfNeeded);
|
|
3409
|
+
await this._pumpEventLoop(runtime, vm, pendingPromises, signal, toVmValue, disposeIfNeeded, shouldStopJobs);
|
|
3410
|
+
if (isTerminated()) {
|
|
3411
|
+
copyBackContextFromVM();
|
|
3412
|
+
return terminalResult();
|
|
3413
|
+
}
|
|
2571
3414
|
const errorResult = vm.evalCode("globalThis.__llmz_error");
|
|
2572
3415
|
const errorValue = vm.dump(errorResult.unwrap());
|
|
2573
3416
|
errorResult.unwrap().dispose();
|
|
@@ -2584,11 +3427,14 @@ var QuickJSDriver = class {
|
|
|
2584
3427
|
const errorStack = vm.dump(errorStackResult.unwrap()) || "";
|
|
2585
3428
|
errorStackResult.unwrap().dispose();
|
|
2586
3429
|
const deserializedError = Signals.maybeDeserializeError(errorValue);
|
|
2587
|
-
if (deserializedError
|
|
3430
|
+
if (VMSignal.is(deserializedError)) {
|
|
2588
3431
|
deserializedError.stack = errorStack;
|
|
2589
3432
|
throw deserializedError;
|
|
2590
3433
|
}
|
|
2591
3434
|
const error = new Error(errorValue);
|
|
3435
|
+
const errorNameResult = vm.evalCode("globalThis.__llmz_error_name");
|
|
3436
|
+
error.name = vm.dump(errorNameResult.unwrap()) || "Error";
|
|
3437
|
+
errorNameResult.unwrap().dispose();
|
|
2592
3438
|
error.stack = errorStack;
|
|
2593
3439
|
throw error;
|
|
2594
3440
|
}
|
|
@@ -2598,23 +3444,35 @@ var QuickJSDriver = class {
|
|
|
2598
3444
|
resultSetResult.unwrap().dispose();
|
|
2599
3445
|
let returnValue = void 0;
|
|
2600
3446
|
if (resultSet) {
|
|
2601
|
-
const
|
|
2602
|
-
|
|
2603
|
-
|
|
3447
|
+
const resultHandle = vm.evalCode("globalThis.__llmz_result").unwrap();
|
|
3448
|
+
try {
|
|
3449
|
+
returnValue = captureValue(resultHandle);
|
|
3450
|
+
} catch (err) {
|
|
3451
|
+
state.captureErrors.push({
|
|
3452
|
+
name: "$return",
|
|
3453
|
+
reason: err instanceof Error ? err.message : String(err)
|
|
3454
|
+
});
|
|
3455
|
+
} finally {
|
|
3456
|
+
resultHandle.dispose();
|
|
3457
|
+
}
|
|
2604
3458
|
}
|
|
2605
3459
|
returnValue = Signals.maybeDeserializeError(returnValue);
|
|
2606
|
-
return {
|
|
3460
|
+
return finalizeMemoryCapture({
|
|
2607
3461
|
success: true,
|
|
2608
3462
|
variables: mapValues(variables, (getter) => isFunction(getter) ? getter() : getter),
|
|
2609
|
-
signal: returnValue
|
|
3463
|
+
signal: VMSignal.is(returnValue) ? returnValue : void 0,
|
|
2610
3464
|
lines_executed: Array.from(lines_executed),
|
|
2611
|
-
return_value: returnValue
|
|
2612
|
-
|
|
3465
|
+
return_value: returnValue,
|
|
3466
|
+
variableWrites: state.variableWrites,
|
|
3467
|
+
captureErrors: state.captureErrors
|
|
3468
|
+
}, state);
|
|
2613
3469
|
} catch (err) {
|
|
3470
|
+
runtime.setInterruptHandler(shouldInterruptAfterDeadline(Date.now() + 1e3));
|
|
3471
|
+
if (isTerminated()) return terminalResult();
|
|
2614
3472
|
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
2615
3473
|
const reason = signal.reason;
|
|
2616
3474
|
const abortError = reason instanceof Error ? reason : new Error(reason ? String(reason) : "Execution was aborted");
|
|
2617
|
-
return handleErrorQuickJS(abortError, code, consumer, traces, variables, lines_executed, userCodeStartLine,
|
|
3475
|
+
return finalizeMemoryCapture(handleErrorQuickJS(abortError, code, consumer, traces, variables, lines_executed, userCodeStartLine, recordTrace), state);
|
|
2618
3476
|
}
|
|
2619
3477
|
await Promise.all(pendingPromises.map(async ({ hostPromise, deferredPromise }) => {
|
|
2620
3478
|
try {
|
|
@@ -2629,8 +3487,13 @@ var QuickJSDriver = class {
|
|
|
2629
3487
|
errValue.dispose();
|
|
2630
3488
|
}
|
|
2631
3489
|
})).catch(() => {});
|
|
2632
|
-
return handleErrorQuickJS(err, code, consumer, traces, variables, lines_executed, userCodeStartLine,
|
|
3490
|
+
return finalizeMemoryCapture(handleErrorQuickJS(err, code, consumer, traces, variables, lines_executed, userCodeStartLine, recordTrace), state);
|
|
2633
3491
|
} finally {
|
|
3492
|
+
var _context$VM_PROGRAM_C2;
|
|
3493
|
+
(_context$VM_PROGRAM_C2 = context[VM_PROGRAM_COMPLETE]) === null || _context$VM_PROGRAM_C2 === void 0 || _context$VM_PROGRAM_C2.call(context);
|
|
3494
|
+
for (const { deferredPromise } of pendingPromises) deferredPromise.dispose();
|
|
3495
|
+
for (const getter of variableGetters.values()) getter.dispose();
|
|
3496
|
+
freezeFunction.dispose();
|
|
2634
3497
|
try {
|
|
2635
3498
|
vm.dispose();
|
|
2636
3499
|
} catch {}
|
|
@@ -2639,16 +3502,17 @@ var QuickJSDriver = class {
|
|
|
2639
3502
|
} catch {}
|
|
2640
3503
|
}
|
|
2641
3504
|
}
|
|
2642
|
-
async _pumpEventLoop(runtime, vm, pendingPromises, signal, toVmValue, disposeIfNeeded) {
|
|
3505
|
+
async _pumpEventLoop(runtime, vm, pendingPromises, signal, toVmValue, disposeIfNeeded, shouldStopJobs) {
|
|
2643
3506
|
const maxIterations = 1e3;
|
|
2644
3507
|
let iteration = 0;
|
|
2645
3508
|
while (iteration < maxIterations) {
|
|
3509
|
+
if (shouldStopJobs()) break;
|
|
2646
3510
|
let hasJobs = false;
|
|
2647
3511
|
const maxJobs = 1e4;
|
|
2648
3512
|
for (let i = 0; i < maxJobs; i++) {
|
|
2649
3513
|
var _runtime$executePendi;
|
|
2650
3514
|
const pending = (_runtime$executePendi = runtime.executePendingJobs) === null || _runtime$executePendi === void 0 ? void 0 : _runtime$executePendi.call(runtime, -1);
|
|
2651
|
-
if ((pending === void 0 ? 0 : pending.unwrap()) <= 0) break;
|
|
3515
|
+
if ((pending === void 0 ? 0 : pending.unwrap()) <= 0 || shouldStopJobs()) break;
|
|
2652
3516
|
hasJobs = true;
|
|
2653
3517
|
}
|
|
2654
3518
|
const currentPromises = [...pendingPromises];
|
|
@@ -2656,7 +3520,7 @@ var QuickJSDriver = class {
|
|
|
2656
3520
|
if (currentPromises.length > 0) {
|
|
2657
3521
|
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
2658
3522
|
const reason = signal.reason;
|
|
2659
|
-
const abortMessage =
|
|
3523
|
+
const abortMessage = describeAbortReason(reason);
|
|
2660
3524
|
for (const { deferredPromise } of currentPromises) {
|
|
2661
3525
|
const errValue = vm.newString(abortMessage);
|
|
2662
3526
|
deferredPromise.reject(errValue);
|
|
@@ -2669,7 +3533,7 @@ var QuickJSDriver = class {
|
|
|
2669
3533
|
if (signal) {
|
|
2670
3534
|
abortListener = () => {
|
|
2671
3535
|
const reason = signal.reason;
|
|
2672
|
-
const abortMessage =
|
|
3536
|
+
const abortMessage = describeAbortReason(reason);
|
|
2673
3537
|
for (const { deferredPromise } of currentPromises) {
|
|
2674
3538
|
const errValue = vm.newString(abortMessage);
|
|
2675
3539
|
deferredPromise.reject(errValue);
|
|
@@ -2681,17 +3545,18 @@ var QuickJSDriver = class {
|
|
|
2681
3545
|
}
|
|
2682
3546
|
try {
|
|
2683
3547
|
await Promise.all(currentPromises.map(async ({ hostPromise, deferredPromise }) => {
|
|
2684
|
-
if (signal === null || signal === void 0 ? void 0 : signal.aborted) return;
|
|
3548
|
+
if ((signal === null || signal === void 0 ? void 0 : signal.aborted) || shouldStopJobs()) return;
|
|
2685
3549
|
try {
|
|
2686
3550
|
const value = await hostPromise;
|
|
2687
|
-
if (signal === null || signal === void 0 ? void 0 : signal.aborted) return;
|
|
3551
|
+
if ((signal === null || signal === void 0 ? void 0 : signal.aborted) || shouldStopJobs()) return;
|
|
2688
3552
|
const vmValue = toVmValue(value);
|
|
2689
3553
|
deferredPromise.resolve(vmValue);
|
|
2690
3554
|
disposeIfNeeded(vmValue);
|
|
2691
3555
|
} catch (err) {
|
|
2692
|
-
if (signal === null || signal === void 0 ? void 0 : signal.aborted) return;
|
|
2693
|
-
const
|
|
2694
|
-
const
|
|
3556
|
+
if ((signal === null || signal === void 0 ? void 0 : signal.aborted) || shouldStopJobs()) return;
|
|
3557
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
3558
|
+
const serialized = err instanceof Error ? Signals.serializeError(err) : message;
|
|
3559
|
+
const createErrorResult = vm.evalCode(`Object.assign(new Error(${JSON.stringify(message)}), { __llmz_error: ${JSON.stringify(serialized)} })`);
|
|
2695
3560
|
if ("error" in createErrorResult) {
|
|
2696
3561
|
const errValue = vm.newString(serialized);
|
|
2697
3562
|
deferredPromise.reject(errValue);
|
|
@@ -2705,9 +3570,10 @@ var QuickJSDriver = class {
|
|
|
2705
3570
|
}));
|
|
2706
3571
|
} finally {
|
|
2707
3572
|
if (signal && abortListener) signal.removeEventListener("abort", abortListener);
|
|
3573
|
+
if (shouldStopJobs()) currentPromises.forEach(({ deferredPromise }) => deferredPromise.dispose());
|
|
2708
3574
|
}
|
|
2709
|
-
runtime.executePendingJobs();
|
|
2710
|
-
if (signal === null || signal === void 0 ? void 0 : signal.aborted) break;
|
|
3575
|
+
if (!shouldStopJobs()) runtime.executePendingJobs();
|
|
3576
|
+
if ((signal === null || signal === void 0 ? void 0 : signal.aborted) || shouldStopJobs()) break;
|
|
2711
3577
|
}
|
|
2712
3578
|
if (!hasJobs && pendingPromises.length === 0) break;
|
|
2713
3579
|
iteration++;
|
|
@@ -2715,13 +3581,13 @@ var QuickJSDriver = class {
|
|
|
2715
3581
|
if (iteration >= maxIterations) throw new Error("Maximum event loop iterations exceeded");
|
|
2716
3582
|
}
|
|
2717
3583
|
};
|
|
2718
|
-
function bridgeContextToVM(context, vm, trackedProperties, referenceProperties, toVmValue, disposeIfNeeded, bridgeFunction) {
|
|
3584
|
+
function bridgeContextToVM(context, vm, trackedProperties, referenceProperties, toVmValue, disposeIfNeeded, bridgeFunction, captureValue) {
|
|
2719
3585
|
for (const [key, value] of Object.entries(context)) {
|
|
2720
3586
|
const descriptor = Object.getOwnPropertyDescriptor(context, key);
|
|
2721
3587
|
if (descriptor && (descriptor.get || descriptor.set)) {
|
|
2722
3588
|
referenceProperties.add(key);
|
|
2723
3589
|
trackedProperties.add(key);
|
|
2724
|
-
bridgeGetterSetter(vm, key, void 0, descriptor, context, toVmValue);
|
|
3590
|
+
bridgeGetterSetter(vm, key, void 0, descriptor, context, toVmValue, captureValue);
|
|
2725
3591
|
continue;
|
|
2726
3592
|
}
|
|
2727
3593
|
if (typeof value === "function") {
|
|
@@ -2758,18 +3624,25 @@ function bridgeContextToVM(context, vm, trackedProperties, referenceProperties,
|
|
|
2758
3624
|
}
|
|
2759
3625
|
vm.setProp(vm.global, key, objHandle);
|
|
2760
3626
|
objHandle.dispose();
|
|
2761
|
-
for (const { prop, descriptor } of getterSetterProps) bridgeGetterSetter(vm, key, prop, descriptor, context, toVmValue);
|
|
3627
|
+
for (const { prop, descriptor } of getterSetterProps) bridgeGetterSetter(vm, key, prop, descriptor, context, toVmValue, captureValue);
|
|
3628
|
+
const missing = value[MISSING_MEMBER];
|
|
3629
|
+
if (missing) {
|
|
3630
|
+
trackedProperties.delete(key);
|
|
3631
|
+
installMemberProxy(vm, key, bridgeFunction(missing));
|
|
3632
|
+
}
|
|
2762
3633
|
if (Object.isSealed(value)) {
|
|
2763
|
-
var _sealResult$error;
|
|
2764
3634
|
const sealResult = vm.evalCode(`Object.seal(globalThis['${key}']);`);
|
|
2765
|
-
if ("error" in sealResult)
|
|
2766
|
-
|
|
3635
|
+
if ("error" in sealResult) {
|
|
3636
|
+
var _sealResult$error;
|
|
3637
|
+
(_sealResult$error = sealResult.error) === null || _sealResult$error === void 0 || _sealResult$error.dispose();
|
|
3638
|
+
} else sealResult.value.dispose();
|
|
2767
3639
|
}
|
|
2768
3640
|
if (!Object.isExtensible(value)) {
|
|
2769
|
-
var _preventResult$error;
|
|
2770
3641
|
const preventResult = vm.evalCode(`Object.preventExtensions(globalThis['${key}']);`);
|
|
2771
|
-
if ("error" in preventResult)
|
|
2772
|
-
|
|
3642
|
+
if ("error" in preventResult) {
|
|
3643
|
+
var _preventResult$error;
|
|
3644
|
+
(_preventResult$error = preventResult.error) === null || _preventResult$error === void 0 || _preventResult$error.dispose();
|
|
3645
|
+
} else preventResult.value.dispose();
|
|
2773
3646
|
}
|
|
2774
3647
|
} else {
|
|
2775
3648
|
trackedProperties.add(key);
|
|
@@ -2779,8 +3652,43 @@ function bridgeContextToVM(context, vm, trackedProperties, referenceProperties,
|
|
|
2779
3652
|
}
|
|
2780
3653
|
}
|
|
2781
3654
|
}
|
|
2782
|
-
function
|
|
2783
|
-
|
|
3655
|
+
function installMemberProxy(vm, key, missing) {
|
|
3656
|
+
const factory = vm.evalCode("(function(target, missing) { return new Proxy(target, { get(object, key, receiver) { if (typeof key === \"string\" && !Object.prototype.hasOwnProperty.call(object, key)) { return missing(key); } return Reflect.get(object, key, receiver); } }); })");
|
|
3657
|
+
if ("error" in factory) {
|
|
3658
|
+
var _factory$error;
|
|
3659
|
+
(_factory$error = factory.error) === null || _factory$error === void 0 || _factory$error.dispose();
|
|
3660
|
+
throw new Error("Could not create the API member proxy.");
|
|
3661
|
+
}
|
|
3662
|
+
const missingHandle = vm.newFunction("missingMember", missing);
|
|
3663
|
+
const target = vm.getProp(vm.global, key);
|
|
3664
|
+
try {
|
|
3665
|
+
const result = vm.callFunction(factory.value, vm.undefined, target, missingHandle);
|
|
3666
|
+
if ("error" in result) {
|
|
3667
|
+
var _result$error;
|
|
3668
|
+
(_result$error = result.error) === null || _result$error === void 0 || _result$error.dispose();
|
|
3669
|
+
throw new Error("Could not install the API member proxy.");
|
|
3670
|
+
}
|
|
3671
|
+
vm.setProp(vm.global, key, result.value);
|
|
3672
|
+
result.value.dispose();
|
|
3673
|
+
} finally {
|
|
3674
|
+
target.dispose();
|
|
3675
|
+
factory.value.dispose();
|
|
3676
|
+
missingHandle.dispose();
|
|
3677
|
+
}
|
|
3678
|
+
}
|
|
3679
|
+
/** Preserve readable guest messages and host error types without serializing Error as a string. */
|
|
3680
|
+
function guestError(vm, cause) {
|
|
3681
|
+
const error = cause instanceof Error ? cause : new Error(String(cause));
|
|
3682
|
+
const handle = vm.newError({
|
|
3683
|
+
name: error.name,
|
|
3684
|
+
message: error.message
|
|
3685
|
+
});
|
|
3686
|
+
const details = vm.newString(Signals.serializeError(error));
|
|
3687
|
+
vm.setProp(handle, "__llmz_error", details);
|
|
3688
|
+
details.dispose();
|
|
3689
|
+
return handle;
|
|
3690
|
+
}
|
|
3691
|
+
function bridgeGetterSetter(vm, key, prop, descriptor, context, toVmValue, captureValue) {
|
|
2784
3692
|
const target = prop ? `${key}` : "globalThis";
|
|
2785
3693
|
const propName = prop ?? key;
|
|
2786
3694
|
const prefix = prop ? `${key}_${prop}` : key;
|
|
@@ -2788,9 +3696,9 @@ function bridgeGetterSetter(vm, key, prop, descriptor, context, toVmValue) {
|
|
|
2788
3696
|
if (descriptor.get) {
|
|
2789
3697
|
const getterBridge = vm.newFunction(`get_${propName}`, () => {
|
|
2790
3698
|
try {
|
|
2791
|
-
return toVmValue(prop ? context[key][prop] : context[key]);
|
|
3699
|
+
return toVmValue(prop ? context[key][prop] : context[key], true);
|
|
2792
3700
|
} catch (err) {
|
|
2793
|
-
|
|
3701
|
+
return { error: guestError(vm, err) };
|
|
2794
3702
|
}
|
|
2795
3703
|
});
|
|
2796
3704
|
const getterName = `__getter_${prefix}__`;
|
|
@@ -2802,12 +3710,12 @@ function bridgeGetterSetter(vm, key, prop, descriptor, context, toVmValue) {
|
|
|
2802
3710
|
if (descriptor.set) {
|
|
2803
3711
|
const setterBridge = vm.newFunction(`set_${propName}`, (valueHandle) => {
|
|
2804
3712
|
try {
|
|
2805
|
-
const jsValue =
|
|
3713
|
+
const jsValue = captureValue(valueHandle);
|
|
2806
3714
|
if (prop) context[key][prop] = jsValue;
|
|
2807
3715
|
else context[key] = jsValue;
|
|
2808
3716
|
return vm.undefined;
|
|
2809
3717
|
} catch (err) {
|
|
2810
|
-
|
|
3718
|
+
return { error: guestError(vm, err) };
|
|
2811
3719
|
}
|
|
2812
3720
|
});
|
|
2813
3721
|
const setterName = `__setter_${prefix}__`;
|
|
@@ -2824,31 +3732,131 @@ function bridgeGetterSetter(vm, key, prop, descriptor, context, toVmValue) {
|
|
|
2824
3732
|
});
|
|
2825
3733
|
`;
|
|
2826
3734
|
const result = vm.evalCode(definePropertyCode);
|
|
2827
|
-
if ("error" in result)
|
|
2828
|
-
|
|
3735
|
+
if ("error" in result) {
|
|
3736
|
+
var _result$error2;
|
|
3737
|
+
(_result$error2 = result.error) === null || _result$error2 === void 0 || _result$error2.dispose();
|
|
3738
|
+
} else result.value.dispose();
|
|
2829
3739
|
}
|
|
2830
|
-
function
|
|
2831
|
-
const
|
|
2832
|
-
|
|
2833
|
-
|
|
3740
|
+
function setupMemoryCapture(vm) {
|
|
3741
|
+
const installed = vm.evalCode(`
|
|
3742
|
+
globalThis.__llmz_encode_memory = function encode(value, seen = new Set()) {
|
|
3743
|
+
if (value === undefined) {
|
|
3744
|
+
return ['undefined'];
|
|
3745
|
+
}
|
|
3746
|
+
if (Object.is(value, -0)) {
|
|
3747
|
+
return ['negative-zero'];
|
|
3748
|
+
}
|
|
3749
|
+
if (value === null || typeof value === 'boolean' || typeof value === 'string') {
|
|
3750
|
+
return ['value', value];
|
|
3751
|
+
}
|
|
3752
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
3753
|
+
return ['value', value];
|
|
3754
|
+
}
|
|
3755
|
+
if (!value || typeof value !== 'object') {
|
|
3756
|
+
throw new Error('Unsupported memory value: ' + typeof value);
|
|
3757
|
+
}
|
|
3758
|
+
if (seen.has(value)) {
|
|
3759
|
+
throw new Error('Cyclic values cannot be retained in memory');
|
|
3760
|
+
}
|
|
3761
|
+
const plainObject = Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null;
|
|
3762
|
+
if (!Array.isArray(value) && !plainObject) {
|
|
3763
|
+
throw new Error('Only plain objects and arrays can be retained in memory');
|
|
3764
|
+
}
|
|
3765
|
+
if (Object.getOwnPropertySymbols(value).length) {
|
|
3766
|
+
throw new Error('Symbol properties cannot be retained in memory');
|
|
3767
|
+
}
|
|
3768
|
+
seen.add(value);
|
|
3769
|
+
try {
|
|
3770
|
+
if (Array.isArray(value)) {
|
|
3771
|
+
if (Object.keys(value).length !== value.length) {
|
|
3772
|
+
throw new Error('Sparse arrays and custom array properties are unsupported');
|
|
3773
|
+
}
|
|
3774
|
+
const items = [];
|
|
3775
|
+
for (let index = 0; index < value.length; index++) {
|
|
3776
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, index);
|
|
3777
|
+
if (!descriptor || descriptor.get || descriptor.set) {
|
|
3778
|
+
throw new Error('Array accessor properties cannot be retained in memory');
|
|
3779
|
+
}
|
|
3780
|
+
items.push(encode(descriptor.value, seen));
|
|
3781
|
+
}
|
|
3782
|
+
return ['array', items];
|
|
3783
|
+
}
|
|
3784
|
+
const entries = [];
|
|
3785
|
+
for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(value))) {
|
|
3786
|
+
if (descriptor.get || descriptor.set || !descriptor.enumerable) {
|
|
3787
|
+
throw new Error('Accessor and non-enumerable properties cannot be retained in memory');
|
|
3788
|
+
}
|
|
3789
|
+
entries.push([key, encode(descriptor.value, seen)]);
|
|
3790
|
+
}
|
|
3791
|
+
return ['object', entries];
|
|
3792
|
+
} finally {
|
|
3793
|
+
seen.delete(value);
|
|
3794
|
+
}
|
|
3795
|
+
};
|
|
3796
|
+
`);
|
|
3797
|
+
if ("error" in installed) {
|
|
3798
|
+
const error = vm.dump(installed.error);
|
|
3799
|
+
installed.error.dispose();
|
|
3800
|
+
throw new Error(error.message);
|
|
3801
|
+
}
|
|
3802
|
+
installed.value.dispose();
|
|
3803
|
+
return (handle) => {
|
|
3804
|
+
const encoder = vm.getProp(vm.global, "__llmz_encode_memory");
|
|
2834
3805
|
try {
|
|
2835
|
-
const
|
|
2836
|
-
if ("error" in
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
return;
|
|
3806
|
+
const encoded = vm.callFunction(encoder, vm.undefined, handle);
|
|
3807
|
+
if ("error" in encoded) {
|
|
3808
|
+
const error = vm.dump(encoded.error);
|
|
3809
|
+
encoded.error.dispose();
|
|
3810
|
+
throw new Error(error.message);
|
|
2841
3811
|
}
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
3812
|
+
try {
|
|
3813
|
+
return decodeMemoryValue(vm.dump(encoded.value));
|
|
3814
|
+
} finally {
|
|
3815
|
+
encoded.value.dispose();
|
|
3816
|
+
}
|
|
3817
|
+
} finally {
|
|
3818
|
+
encoder.dispose();
|
|
2848
3819
|
}
|
|
3820
|
+
};
|
|
3821
|
+
}
|
|
3822
|
+
function setupVariableTrackingBridge(vm, variables, getters, state, capture) {
|
|
3823
|
+
const tracker = vm.newFunction(Identifiers.VariableTrackingFnIdentifier, (nameHandle, getterHandle, resultHandle, kindHandle) => {
|
|
3824
|
+
var _getters$get;
|
|
3825
|
+
const name = vm.getString(nameHandle);
|
|
3826
|
+
if (NO_TRACKING.includes(name) || !state.memoryNames.has(name)) return (resultHandle === null || resultHandle === void 0 ? void 0 : resultHandle.dup()) ?? vm.undefined;
|
|
3827
|
+
const kind = kindHandle ? vm.dump(kindHandle) : "assignment";
|
|
3828
|
+
if (kind !== "initialize" && kind !== "read") state.variableWrites.push({
|
|
3829
|
+
name,
|
|
3830
|
+
timestamp: Date.now(),
|
|
3831
|
+
kind: kind === "mutation" ? "mutation" : "assignment"
|
|
3832
|
+
});
|
|
3833
|
+
(_getters$get = getters.get(name)) === null || _getters$get === void 0 || _getters$get.dispose();
|
|
3834
|
+
getters.set(name, getterHandle.dup());
|
|
3835
|
+
variables[name] = () => {
|
|
3836
|
+
try {
|
|
3837
|
+
const result = vm.callFunction(getters.get(name), vm.undefined);
|
|
3838
|
+
if ("error" in result) {
|
|
3839
|
+
const error = vm.dump(result.error);
|
|
3840
|
+
result.error.dispose();
|
|
3841
|
+
throw new Error(error.message);
|
|
3842
|
+
}
|
|
3843
|
+
try {
|
|
3844
|
+
return capture(result.value);
|
|
3845
|
+
} finally {
|
|
3846
|
+
result.value.dispose();
|
|
3847
|
+
}
|
|
3848
|
+
} catch (err) {
|
|
3849
|
+
if (!state.captureErrors.some((entry) => entry.name === name)) state.captureErrors.push({
|
|
3850
|
+
name,
|
|
3851
|
+
reason: err instanceof Error ? err.message : String(err)
|
|
3852
|
+
});
|
|
3853
|
+
return;
|
|
3854
|
+
}
|
|
3855
|
+
};
|
|
3856
|
+
return (resultHandle === null || resultHandle === void 0 ? void 0 : resultHandle.dup()) ?? vm.undefined;
|
|
2849
3857
|
});
|
|
2850
|
-
vm.setProp(vm.global, Identifiers.VariableTrackingFnIdentifier,
|
|
2851
|
-
|
|
3858
|
+
vm.setProp(vm.global, Identifiers.VariableTrackingFnIdentifier, tracker);
|
|
3859
|
+
tracker.dispose();
|
|
2852
3860
|
}
|
|
2853
3861
|
function buildScriptCode(transformedCode) {
|
|
2854
3862
|
return `
|
|
@@ -2867,12 +3875,19 @@ ${transformedCode}
|
|
|
2867
3875
|
globalThis.__llmz_result = await __fn__();
|
|
2868
3876
|
globalThis.__llmz_result_set = true;
|
|
2869
3877
|
} catch (err) {
|
|
2870
|
-
globalThis.__llmz_error = typeof err === 'string' ? err : String(err.message || err || '');
|
|
3878
|
+
globalThis.__llmz_error = typeof err === 'string' ? err : String(err.__llmz_error || err.message || err || '');
|
|
3879
|
+
globalThis.__llmz_error_name = typeof err?.name === 'string' ? err.name : 'Error';
|
|
2871
3880
|
globalThis.__llmz_error_stack = '' + (err.stack || '');
|
|
3881
|
+
} finally {
|
|
3882
|
+
__llmz_program_complete();
|
|
2872
3883
|
}
|
|
2873
3884
|
})();
|
|
2874
3885
|
`.trim();
|
|
2875
3886
|
}
|
|
3887
|
+
function describeAbortReason(reason) {
|
|
3888
|
+
if (reason instanceof Error) return `${reason.name}: ${reason.message}`;
|
|
3889
|
+
return reason ? String(reason) : "Execution was aborted";
|
|
3890
|
+
}
|
|
2876
3891
|
//#endregion
|
|
2877
3892
|
//#region src/vm/index.ts
|
|
2878
3893
|
const MAX_VM_EXECUTION_TIME = 6e4;
|
|
@@ -2884,27 +3899,20 @@ const isWorkerd = () => {
|
|
|
2884
3899
|
var _navigator;
|
|
2885
3900
|
return typeof navigator !== "undefined" && ((_navigator = navigator) === null || _navigator === void 0 ? void 0 : _navigator.userAgent) === "Cloudflare-Workers";
|
|
2886
3901
|
};
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
* writing a `■run` block, so the module loads while the code is still being
|
|
2891
|
-
* generated. No-op when the QuickJS driver is disabled or already loaded.
|
|
2892
|
-
*/
|
|
2893
|
-
const warmupVM = () => {
|
|
2894
|
-
if (useQuickJS()) loadQuickJSModule().catch(() => {});
|
|
2895
|
-
};
|
|
2896
|
-
async function runAsyncFunction(context, code, traces = [], signal = null, timeout = MAX_VM_EXECUTION_TIME) {
|
|
3902
|
+
async function runAsyncFunction(context, code, traces = [], signal = null, timeout = MAX_VM_EXECUTION_TIME, memoryNames, recordTrace = (trace) => {
|
|
3903
|
+
traces.push(trace);
|
|
3904
|
+
}) {
|
|
2897
3905
|
const transformed = (() => {
|
|
2898
3906
|
try {
|
|
2899
3907
|
return compile(code);
|
|
2900
3908
|
} catch (err) {
|
|
2901
|
-
|
|
3909
|
+
recordTrace({
|
|
2902
3910
|
type: "invalid_code_exception",
|
|
2903
3911
|
message: (err === null || err === void 0 ? void 0 : err.message) ?? "Unknown error",
|
|
2904
3912
|
code,
|
|
2905
3913
|
started_at: Date.now()
|
|
2906
3914
|
});
|
|
2907
|
-
throw new InvalidCodeError(err.message, code);
|
|
3915
|
+
throw isLLMzError(err) ? err : new InvalidCodeError(err.message, code, { cause: err });
|
|
2908
3916
|
}
|
|
2909
3917
|
})();
|
|
2910
3918
|
const lines_executed = /* @__PURE__ */ new Map();
|
|
@@ -2918,22 +3926,21 @@ async function runAsyncFunction(context, code, traces = [], signal = null, timeo
|
|
|
2918
3926
|
file: transformed.map.file
|
|
2919
3927
|
});
|
|
2920
3928
|
context ??= {};
|
|
3929
|
+
memoryNames ??= Object.keys(context).filter((name) => {
|
|
3930
|
+
if (name.startsWith("__") || RESERVED_RUNTIME_NAMES.has(name)) return false;
|
|
3931
|
+
try {
|
|
3932
|
+
cloneMemoryValue(context[name]);
|
|
3933
|
+
return true;
|
|
3934
|
+
} catch {
|
|
3935
|
+
return false;
|
|
3936
|
+
}
|
|
3937
|
+
});
|
|
3938
|
+
memoryNames = memoryNames.filter((name) => !transformed.variables.has(name) && !RESERVED_RUNTIME_NAMES.has(name) && !name.startsWith("__"));
|
|
2921
3939
|
for (const name of Array.from(transformed.variables)) delete context[name];
|
|
2922
|
-
let driver;
|
|
3940
|
+
let driver = new NodeDriver();
|
|
2923
3941
|
if (useQuickJS()) try {
|
|
3942
|
+
await loadQuickJSModule();
|
|
2924
3943
|
driver = new QuickJSDriver();
|
|
2925
|
-
return await driver.execute({
|
|
2926
|
-
transformed,
|
|
2927
|
-
consumer,
|
|
2928
|
-
context,
|
|
2929
|
-
traces,
|
|
2930
|
-
signal,
|
|
2931
|
-
timeout,
|
|
2932
|
-
code,
|
|
2933
|
-
lines_executed,
|
|
2934
|
-
variables,
|
|
2935
|
-
currentToolCall: void 0
|
|
2936
|
-
});
|
|
2937
3944
|
} catch (quickjsError) {
|
|
2938
3945
|
const variant = getQuickJSVariant();
|
|
2939
3946
|
const debugInfo = {
|
|
@@ -2950,7 +3957,7 @@ async function runAsyncFunction(context, code, traces = [], signal = null, timeo
|
|
|
2950
3957
|
console.error("QuickJS failed to load and the node driver is unavailable on Cloudflare Workers.");
|
|
2951
3958
|
console.error("Debug info:", JSON.stringify(debugInfo, null, 2));
|
|
2952
3959
|
if (quickjsError instanceof Error) {
|
|
2953
|
-
quickjsError
|
|
3960
|
+
Object.assign(quickjsError, { debugInfo });
|
|
2954
3961
|
throw quickjsError;
|
|
2955
3962
|
}
|
|
2956
3963
|
throw new Error(`QuickJS failed to load on Cloudflare Workers: ${debugInfo.error}`);
|
|
@@ -2959,19 +3966,19 @@ async function runAsyncFunction(context, code, traces = [], signal = null, timeo
|
|
|
2959
3966
|
console.warn("Error:", (quickjsError === null || quickjsError === void 0 ? void 0 : quickjsError.message) || quickjsError);
|
|
2960
3967
|
console.warn("Debug info:", JSON.stringify(debugInfo, null, 2));
|
|
2961
3968
|
}
|
|
2962
|
-
driver = new NodeDriver();
|
|
2963
3969
|
return await driver.execute({
|
|
2964
3970
|
transformed,
|
|
3971
|
+
memoryNames,
|
|
2965
3972
|
consumer,
|
|
2966
3973
|
context,
|
|
2967
3974
|
traces,
|
|
3975
|
+
recordTrace,
|
|
2968
3976
|
signal,
|
|
2969
3977
|
timeout,
|
|
2970
3978
|
code,
|
|
2971
3979
|
lines_executed,
|
|
2972
|
-
variables
|
|
2973
|
-
currentToolCall: void 0
|
|
3980
|
+
variables
|
|
2974
3981
|
});
|
|
2975
3982
|
}
|
|
2976
3983
|
//#endregion
|
|
2977
|
-
export { runAsyncFunction,
|
|
3984
|
+
export { VM_TERMINATION as a, VM_PROGRAM_COMPLETE as i, VM_CALL_SITE as n, compile as o, VM_ON_ERROR as r, runAsyncFunction, withMissingMember as t };
|