@namzu/sdk 36.0.0 → 37.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +180 -0
- package/README.md +68 -41
- package/dist/bridge/a2a/mapper.d.ts.map +1 -1
- package/dist/bridge/a2a/mapper.js +2 -0
- package/dist/bridge/a2a/mapper.js.map +1 -1
- package/dist/bridge/sse/mapper.d.ts.map +1 -1
- package/dist/bridge/sse/mapper.js +2 -0
- package/dist/bridge/sse/mapper.js.map +1 -1
- package/dist/compaction/extractor.d.ts +1 -1
- package/dist/compaction/extractor.d.ts.map +1 -1
- package/dist/compaction/extractor.js +15 -7
- package/dist/compaction/extractor.js.map +1 -1
- package/dist/compaction/manager.d.ts +2 -0
- package/dist/compaction/manager.d.ts.map +1 -1
- package/dist/compaction/manager.js +12 -1
- package/dist/compaction/manager.js.map +1 -1
- package/dist/compaction/verifier.d.ts.map +1 -1
- package/dist/compaction/verifier.js +82 -15
- package/dist/compaction/verifier.js.map +1 -1
- package/dist/contracts/schemas.d.ts +10 -10
- package/dist/eval/harness-verification.d.ts +63 -0
- package/dist/eval/harness-verification.d.ts.map +1 -0
- package/dist/eval/harness-verification.js +165 -0
- package/dist/eval/harness-verification.js.map +1 -0
- package/dist/eval/index.d.ts +2 -0
- package/dist/eval/index.d.ts.map +1 -1
- package/dist/eval/index.js +1 -0
- package/dist/eval/index.js.map +1 -1
- package/dist/execution/code-runtime/json-value.d.ts +10 -0
- package/dist/execution/code-runtime/json-value.d.ts.map +1 -0
- package/dist/execution/code-runtime/json-value.js +89 -0
- package/dist/execution/code-runtime/json-value.js.map +1 -0
- package/dist/execution/code-runtime/worker-program.d.ts +8 -0
- package/dist/execution/code-runtime/worker-program.d.ts.map +1 -0
- package/dist/execution/code-runtime/worker-program.js +240 -0
- package/dist/execution/code-runtime/worker-program.js.map +1 -0
- package/dist/execution/code-runtime/worker.d.ts +22 -0
- package/dist/execution/code-runtime/worker.d.ts.map +1 -1
- package/dist/execution/code-runtime/worker.js +148 -111
- package/dist/execution/code-runtime/worker.js.map +1 -1
- package/dist/manager/agent/lifecycle.d.ts +12 -0
- package/dist/manager/agent/lifecycle.d.ts.map +1 -1
- package/dist/manager/agent/lifecycle.js +306 -37
- package/dist/manager/agent/lifecycle.js.map +1 -1
- package/dist/manager/run/persistence.d.ts +2 -0
- package/dist/manager/run/persistence.d.ts.map +1 -1
- package/dist/manager/run/persistence.js +6 -0
- package/dist/manager/run/persistence.js.map +1 -1
- package/dist/provider/capabilities.d.ts +3 -1
- package/dist/provider/capabilities.d.ts.map +1 -1
- package/dist/provider/capabilities.js +13 -0
- package/dist/provider/capabilities.js.map +1 -1
- package/dist/provider/fallback.d.ts.map +1 -1
- package/dist/provider/fallback.js +2 -0
- package/dist/provider/fallback.js.map +1 -1
- package/dist/public-runtime.d.ts +3 -1
- package/dist/public-runtime.d.ts.map +1 -1
- package/dist/public-runtime.js +2 -1
- package/dist/public-runtime.js.map +1 -1
- package/dist/public-tools.d.ts +1 -1
- package/dist/public-tools.d.ts.map +1 -1
- package/dist/public-tools.js +1 -1
- package/dist/public-tools.js.map +1 -1
- package/dist/public-types.d.ts +1 -0
- package/dist/public-types.d.ts.map +1 -1
- package/dist/registry/tool/execute.d.ts +3 -0
- package/dist/registry/tool/execute.d.ts.map +1 -1
- package/dist/registry/tool/execute.js +11 -80
- package/dist/registry/tool/execute.js.map +1 -1
- package/dist/run/command-gate.d.ts.map +1 -1
- package/dist/run/command-gate.js +65 -12
- package/dist/run/command-gate.js.map +1 -1
- package/dist/run/index.d.ts +2 -0
- package/dist/run/index.d.ts.map +1 -1
- package/dist/run/index.js +1 -0
- package/dist/run/index.js.map +1 -1
- package/dist/run/memory-promoter.d.ts +3 -35
- package/dist/run/memory-promoter.d.ts.map +1 -1
- package/dist/run/memory-promoter.js +32 -40
- package/dist/run/memory-promoter.js.map +1 -1
- package/dist/run/memory-recall.d.ts +25 -0
- package/dist/run/memory-recall.d.ts.map +1 -0
- package/dist/run/memory-recall.js +228 -0
- package/dist/run/memory-recall.js.map +1 -0
- package/dist/run/reporter.d.ts.map +1 -1
- package/dist/run/reporter.js +1 -0
- package/dist/run/reporter.js.map +1 -1
- package/dist/run/token-budget.d.ts +2 -0
- package/dist/run/token-budget.d.ts.map +1 -1
- package/dist/run/token-budget.js +4 -0
- package/dist/run/token-budget.js.map +1 -1
- package/dist/run/workspace-fingerprint.d.ts +10 -3
- package/dist/run/workspace-fingerprint.d.ts.map +1 -1
- package/dist/run/workspace-fingerprint.js +17 -8
- package/dist/run/workspace-fingerprint.js.map +1 -1
- package/dist/runtime/query/checkpoint.d.ts +14 -0
- package/dist/runtime/query/checkpoint.d.ts.map +1 -1
- package/dist/runtime/query/checkpoint.js +82 -1
- package/dist/runtime/query/checkpoint.js.map +1 -1
- package/dist/runtime/query/executor.d.ts +5 -0
- package/dist/runtime/query/executor.d.ts.map +1 -1
- package/dist/runtime/query/executor.js +70 -14
- package/dist/runtime/query/executor.js.map +1 -1
- package/dist/runtime/query/index.d.ts +5 -8
- package/dist/runtime/query/index.d.ts.map +1 -1
- package/dist/runtime/query/index.js +54 -7
- package/dist/runtime/query/index.js.map +1 -1
- package/dist/runtime/query/iteration/index.d.ts +10 -0
- package/dist/runtime/query/iteration/index.d.ts.map +1 -1
- package/dist/runtime/query/iteration/index.js +325 -36
- package/dist/runtime/query/iteration/index.js.map +1 -1
- package/dist/runtime/query/iteration/native-output.d.ts +10 -0
- package/dist/runtime/query/iteration/native-output.d.ts.map +1 -0
- package/dist/runtime/query/iteration/native-output.js +32 -0
- package/dist/runtime/query/iteration/native-output.js.map +1 -0
- package/dist/runtime/query/iteration/phases/advisory.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/advisory.js +18 -13
- package/dist/runtime/query/iteration/phases/advisory.js.map +1 -1
- package/dist/runtime/query/iteration/phases/compaction.d.ts +2 -0
- package/dist/runtime/query/iteration/phases/compaction.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/compaction.js +32 -11
- package/dist/runtime/query/iteration/phases/compaction.js.map +1 -1
- package/dist/runtime/query/iteration/phases/context.d.ts +9 -0
- package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/context.js.map +1 -1
- package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/tool-review.js +1 -1
- package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
- package/dist/runtime/query/iteration/phases/working-memory.d.ts +1 -1
- package/dist/runtime/query/iteration/phases/working-memory.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/working-memory.js +23 -6
- package/dist/runtime/query/iteration/phases/working-memory.js.map +1 -1
- package/dist/runtime/query/iteration/stream-turn.d.ts.map +1 -1
- package/dist/runtime/query/iteration/stream-turn.js +2 -0
- package/dist/runtime/query/iteration/stream-turn.js.map +1 -1
- package/dist/runtime/query/steering.d.ts +6 -2
- package/dist/runtime/query/steering.d.ts.map +1 -1
- package/dist/runtime/query/steering.js +17 -2
- package/dist/runtime/query/steering.js.map +1 -1
- package/dist/runtime/query/tool-call-budget.d.ts +19 -0
- package/dist/runtime/query/tool-call-budget.d.ts.map +1 -0
- package/dist/runtime/query/tool-call-budget.js +110 -0
- package/dist/runtime/query/tool-call-budget.js.map +1 -0
- package/dist/runtime/query/tooling.d.ts +2 -0
- package/dist/runtime/query/tooling.d.ts.map +1 -1
- package/dist/runtime/query/tooling.js +4 -0
- package/dist/runtime/query/tooling.js.map +1 -1
- package/dist/scheduler/local.d.ts.map +1 -1
- package/dist/scheduler/local.js +1 -0
- package/dist/scheduler/local.js.map +1 -1
- package/dist/session/handoff/capacity.d.ts +2 -2
- package/dist/session/handoff/capacity.d.ts.map +1 -1
- package/dist/session/handoff/capacity.js +3 -2
- package/dist/session/handoff/capacity.js.map +1 -1
- package/dist/store/memory/disk.d.ts +6 -2
- package/dist/store/memory/disk.d.ts.map +1 -1
- package/dist/store/memory/disk.js +42 -25
- package/dist/store/memory/disk.js.map +1 -1
- package/dist/store/memory/index.d.ts +4 -0
- package/dist/store/memory/index.d.ts.map +1 -1
- package/dist/store/memory/index.js +55 -19
- package/dist/store/memory/index.js.map +1 -1
- package/dist/store/memory/memory.d.ts +3 -2
- package/dist/store/memory/memory.d.ts.map +1 -1
- package/dist/store/memory/memory.js +11 -2
- package/dist/store/memory/memory.js.map +1 -1
- package/dist/store/memory/operation-lock.d.ts +11 -0
- package/dist/store/memory/operation-lock.d.ts.map +1 -0
- package/dist/store/memory/operation-lock.js +94 -0
- package/dist/store/memory/operation-lock.js.map +1 -0
- package/dist/tools/builtins/computer-use.d.ts.map +1 -1
- package/dist/tools/builtins/computer-use.js +60 -10
- package/dist/tools/builtins/computer-use.js.map +1 -1
- package/dist/tools/builtins/run-code.d.ts +6 -0
- package/dist/tools/builtins/run-code.d.ts.map +1 -1
- package/dist/tools/builtins/run-code.js +15 -4
- package/dist/tools/builtins/run-code.js.map +1 -1
- package/dist/tools/builtins/search-tools.d.ts.map +1 -1
- package/dist/tools/builtins/search-tools.js +14 -2
- package/dist/tools/builtins/search-tools.js.map +1 -1
- package/dist/tools/defineTool.d.ts +2 -0
- package/dist/tools/defineTool.d.ts.map +1 -1
- package/dist/tools/defineTool.js +3 -0
- package/dist/tools/defineTool.js.map +1 -1
- package/dist/tools/memory/delete.d.ts +4 -0
- package/dist/tools/memory/delete.d.ts.map +1 -0
- package/dist/tools/memory/delete.js +26 -0
- package/dist/tools/memory/delete.js.map +1 -0
- package/dist/tools/memory/index.d.ts +2 -0
- package/dist/tools/memory/index.d.ts.map +1 -1
- package/dist/tools/memory/index.js +6 -0
- package/dist/tools/memory/index.js.map +1 -1
- package/dist/tools/memory/save.d.ts.map +1 -1
- package/dist/tools/memory/save.js +3 -2
- package/dist/tools/memory/save.js.map +1 -1
- package/dist/tools/memory/search.d.ts.map +1 -1
- package/dist/tools/memory/search.js +12 -5
- package/dist/tools/memory/search.js.map +1 -1
- package/dist/tools/memory/update.d.ts +4 -0
- package/dist/tools/memory/update.d.ts.map +1 -0
- package/dist/tools/memory/update.js +47 -0
- package/dist/tools/memory/update.js.map +1 -0
- package/dist/types/agent/scheduler.d.ts +5 -0
- package/dist/types/agent/scheduler.d.ts.map +1 -1
- package/dist/types/agent/task.d.ts +10 -0
- package/dist/types/agent/task.d.ts.map +1 -1
- package/dist/types/computer-use/index.d.ts +6 -0
- package/dist/types/computer-use/index.d.ts.map +1 -1
- package/dist/types/computer-use/index.js.map +1 -1
- package/dist/types/errors/catalog.js +1 -1
- package/dist/types/errors/catalog.js.map +1 -1
- package/dist/types/hitl/index.d.ts +11 -1
- package/dist/types/hitl/index.d.ts.map +1 -1
- package/dist/types/hitl/index.js.map +1 -1
- package/dist/types/memory/index.d.ts +14 -1
- package/dist/types/memory/index.d.ts.map +1 -1
- package/dist/types/project/entity.d.ts +1 -0
- package/dist/types/project/entity.d.ts.map +1 -1
- package/dist/types/provider/config.d.ts +2 -0
- package/dist/types/provider/config.d.ts.map +1 -1
- package/dist/types/provider/model.d.ts +4 -0
- package/dist/types/provider/model.d.ts.map +1 -1
- package/dist/types/run/answer-review.d.ts +2 -0
- package/dist/types/run/answer-review.d.ts.map +1 -1
- package/dist/types/run/events.d.ts +9 -0
- package/dist/types/run/events.d.ts.map +1 -1
- package/dist/types/run/events.js.map +1 -1
- package/dist/types/run/prepare-step.d.ts +19 -1
- package/dist/types/run/prepare-step.d.ts.map +1 -1
- package/dist/types/structured-output/index.d.ts +8 -2
- package/dist/types/structured-output/index.d.ts.map +1 -1
- package/dist/types/tool/index.d.ts +15 -0
- package/dist/types/tool/index.d.ts.map +1 -1
- package/dist/types/tool/index.js.map +1 -1
- package/dist/utils/json-snapshot.d.ts +3 -0
- package/dist/utils/json-snapshot.d.ts.map +1 -0
- package/dist/utils/json-snapshot.js +79 -0
- package/dist/utils/json-snapshot.js.map +1 -0
- package/package.json +4 -2
- package/src/bridge/a2a/mapper.ts +2 -0
- package/src/bridge/sse/mapper.ts +2 -0
- package/src/compaction/extractor.ts +21 -8
- package/src/compaction/manager.ts +11 -1
- package/src/compaction/verifier.ts +80 -18
- package/src/eval/harness-verification.ts +270 -0
- package/src/eval/index.ts +10 -0
- package/src/execution/code-runtime/json-value.ts +82 -0
- package/src/execution/code-runtime/worker-program.ts +239 -0
- package/src/execution/code-runtime/worker.ts +164 -111
- package/src/manager/agent/lifecycle.ts +340 -45
- package/src/manager/run/persistence.ts +7 -0
- package/src/provider/capabilities.ts +25 -1
- package/src/provider/fallback.ts +2 -0
- package/src/public-runtime.ts +4 -0
- package/src/public-tools.ts +5 -1
- package/src/public-types.ts +1 -0
- package/src/registry/tool/execute.ts +17 -79
- package/src/run/command-gate.ts +61 -13
- package/src/run/index.ts +2 -0
- package/src/run/memory-promoter.ts +32 -40
- package/src/run/memory-recall.ts +254 -0
- package/src/run/reporter.ts +1 -0
- package/src/run/token-budget.ts +4 -0
- package/src/run/workspace-fingerprint.ts +17 -8
- package/src/runtime/query/checkpoint.ts +96 -2
- package/src/runtime/query/executor.ts +77 -14
- package/src/runtime/query/index.ts +73 -16
- package/src/runtime/query/iteration/index.ts +377 -44
- package/src/runtime/query/iteration/native-output.ts +35 -0
- package/src/runtime/query/iteration/phases/advisory.ts +21 -11
- package/src/runtime/query/iteration/phases/compaction.ts +36 -14
- package/src/runtime/query/iteration/phases/context.ts +9 -0
- package/src/runtime/query/iteration/phases/tool-review.ts +5 -1
- package/src/runtime/query/iteration/phases/working-memory.ts +23 -5
- package/src/runtime/query/iteration/stream-turn.ts +2 -0
- package/src/runtime/query/steering.ts +19 -2
- package/src/runtime/query/tool-call-budget.ts +115 -0
- package/src/runtime/query/tooling.ts +6 -0
- package/src/scheduler/local.ts +1 -0
- package/src/session/handoff/capacity.ts +7 -3
- package/src/store/memory/disk.ts +52 -30
- package/src/store/memory/index.ts +75 -27
- package/src/store/memory/memory.ts +18 -6
- package/src/store/memory/operation-lock.ts +99 -0
- package/src/tools/builtins/computer-use.ts +61 -7
- package/src/tools/builtins/run-code.ts +24 -5
- package/src/tools/builtins/search-tools.ts +18 -3
- package/src/tools/defineTool.ts +5 -0
- package/src/tools/memory/delete.ts +29 -0
- package/src/tools/memory/index.ts +6 -0
- package/src/tools/memory/save.ts +4 -2
- package/src/tools/memory/search.ts +12 -5
- package/src/tools/memory/update.ts +50 -0
- package/src/types/agent/scheduler.ts +6 -0
- package/src/types/agent/task.ts +13 -0
- package/src/types/computer-use/index.ts +6 -0
- package/src/types/errors/catalog.ts +1 -1
- package/src/types/hitl/index.ts +11 -1
- package/src/types/memory/index.ts +16 -1
- package/src/types/project/entity.ts +1 -0
- package/src/types/provider/config.ts +2 -0
- package/src/types/provider/model.ts +4 -0
- package/src/types/run/answer-review.ts +2 -0
- package/src/types/run/events.ts +10 -0
- package/src/types/run/prepare-step.ts +19 -1
- package/src/types/structured-output/index.ts +15 -2
- package/src/types/tool/index.ts +16 -0
- package/src/utils/json-snapshot.ts +76 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serialize application data before sending it to the interpreter.
|
|
3
|
+
*
|
|
4
|
+
* JSON.stringify alone can allocate an arbitrarily large intermediate string.
|
|
5
|
+
* This writer accounts for each piece, refuses cycles and non-JSON values, and
|
|
6
|
+
* limits nesting. It never installs application objects in the guest realm.
|
|
7
|
+
* Undefined is supported only as a top-level result, represented out of band.
|
|
8
|
+
*/
|
|
9
|
+
export function encodeCodeValue(value, maxBytes) {
|
|
10
|
+
if (value === undefined)
|
|
11
|
+
return undefined;
|
|
12
|
+
const pieces = [];
|
|
13
|
+
const ancestors = new Set();
|
|
14
|
+
let bytes = 0;
|
|
15
|
+
const append = (text) => {
|
|
16
|
+
bytes += Buffer.byteLength(text);
|
|
17
|
+
if (bytes > maxBytes)
|
|
18
|
+
throw new Error(`Code runtime value exceeds ${maxBytes} bytes.`);
|
|
19
|
+
pieces.push(text);
|
|
20
|
+
};
|
|
21
|
+
const quote = (text) => {
|
|
22
|
+
if (text.length > maxBytes - bytes) {
|
|
23
|
+
throw new Error(`Code runtime value exceeds ${maxBytes} bytes.`);
|
|
24
|
+
}
|
|
25
|
+
append(JSON.stringify(text));
|
|
26
|
+
};
|
|
27
|
+
const visit = (item, depth) => {
|
|
28
|
+
if (depth > 64)
|
|
29
|
+
throw new Error('Code runtime value exceeds 64 levels of nesting.');
|
|
30
|
+
if (item === null) {
|
|
31
|
+
append('null');
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (typeof item === 'string') {
|
|
35
|
+
quote(item);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (typeof item === 'boolean') {
|
|
39
|
+
append(String(item));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (typeof item === 'number' && Number.isFinite(item)) {
|
|
43
|
+
append(String(item));
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (typeof item !== 'object')
|
|
47
|
+
throw new Error('Code runtime values must be JSON-safe.');
|
|
48
|
+
if (ancestors.has(item))
|
|
49
|
+
throw new Error('Code runtime values must not contain cycles.');
|
|
50
|
+
const array = Array.isArray(item);
|
|
51
|
+
if (!array &&
|
|
52
|
+
Object.getPrototypeOf(item) !== Object.prototype &&
|
|
53
|
+
Object.getPrototypeOf(item) !== null) {
|
|
54
|
+
throw new Error('Code runtime values must contain only plain objects and arrays.');
|
|
55
|
+
}
|
|
56
|
+
ancestors.add(item);
|
|
57
|
+
if (array) {
|
|
58
|
+
if (item.length > maxBytes)
|
|
59
|
+
throw new Error(`Code runtime value exceeds ${maxBytes} bytes.`);
|
|
60
|
+
append('[');
|
|
61
|
+
for (let index = 0; index < item.length; index++) {
|
|
62
|
+
if (index > 0)
|
|
63
|
+
append(',');
|
|
64
|
+
visit(item[index], depth + 1);
|
|
65
|
+
}
|
|
66
|
+
append(']');
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
append('{');
|
|
70
|
+
const keys = Object.keys(item);
|
|
71
|
+
for (const [index, key] of keys.entries()) {
|
|
72
|
+
if (index > 0)
|
|
73
|
+
append(',');
|
|
74
|
+
quote(key);
|
|
75
|
+
append(':');
|
|
76
|
+
const descriptor = Object.getOwnPropertyDescriptor(item, key);
|
|
77
|
+
if (!descriptor || !('value' in descriptor)) {
|
|
78
|
+
throw new Error('Code runtime values must not contain accessors.');
|
|
79
|
+
}
|
|
80
|
+
visit(descriptor.value, depth + 1);
|
|
81
|
+
}
|
|
82
|
+
append('}');
|
|
83
|
+
}
|
|
84
|
+
ancestors.delete(item);
|
|
85
|
+
};
|
|
86
|
+
visit(value, 0);
|
|
87
|
+
return pieces.join('');
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=json-value.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-value.js","sourceRoot":"","sources":["../../../src/execution/code-runtime/json-value.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trusted worker bootstrap. Only vm.evalCode executes the untrusted program.
|
|
3
|
+
* Kept as source so installed/bundled SDKs need no separate worker entry file.
|
|
4
|
+
* No Node object or callback is injected into QuickJS: its native functions
|
|
5
|
+
* exchange bounded strings and interpreter-owned promise handles.
|
|
6
|
+
*/
|
|
7
|
+
export declare const QUICKJS_WORKER_SOURCE = "\nconst { parentPort, workerData } = require('node:worker_threads')\nconst { newQuickJSWASMModuleFromVariant, newVariant } = require(workerData.corePath)\nconst variantModule = require(workerData.variantPath)\nconst variant = variantModule.default || variantModule\n\nasync function main() {\n\tconst limits = workerData.limits\n\tconst pages = Math.floor(limits.memoryLimitBytes / 65536)\n\tconst wasmMemory = new WebAssembly.Memory({ initial: Math.min(256, pages), maximum: pages })\n\tconst module = await newQuickJSWASMModuleFromVariant(newVariant(variant, { wasmMemory }))\n\tconst runtime = module.newRuntime()\n\truntime.setMemoryLimit(limits.memoryLimitBytes)\n\truntime.setMaxStackSize(512 * 1024)\n\truntime.setInterruptHandler(() => Date.now() >= workerData.deadline)\n\tconst vm = runtime.newContext()\n\tconst pending = new Map()\n\tlet nextId = 0\n\tlet printBytes = 0\n\tlet printCount = 0\n\tlet truncated = false\n\tlet ended = false\n\tlet pumping = false\n\tlet scheduled = false\n\tlet program\n\tconst owned = []\n\n\tfunction keep(result) {\n\t\tconst handle = vm.unwrapResult(result)\n\t\towned.push(handle)\n\t\treturn handle\n\t}\n\t// Capture intrinsics before the program may replace its own globals.\n\tconst encode = keep(vm.evalCode('(' + function () {\n\t\tconst stringify = JSON.stringify\n\t\tconst finite = Number.isFinite\n\t\tconst prototype = Object.getPrototypeOf\n\t\tconst plain = Object.prototype\n\t\tconst isArray = Array.isArray\n\t\tconst keys = Object.keys\n\t\tconst descriptor = Object.getOwnPropertyDescriptor\n\t\treturn function (value) {\n\t\t\tif (value === undefined) return undefined\n\t\t\tconst parents = new Set()\n\t\t\tfunction check(item, depth) {\n\t\t\t\tconst kind = typeof item\n\t\t\t\tif (item === null || kind === 'string' || kind === 'boolean' || (kind === 'number' && finite(item))) return\n\t\t\t\tif (kind !== 'object' || depth > 64 || parents.has(item)) throw new Error('Code runtime values must be JSON-safe.')\n\t\t\t\tif (!isArray(item) && prototype(item) !== plain && prototype(item) !== null) throw new Error('Code runtime values must use plain objects and arrays.')\n\t\t\t\tparents.add(item)\n\t\t\t\tfor (const key of keys(item)) {\n\t\t\t\t\tconst property = descriptor(item, key)\n\t\t\t\t\tif (!property || !('value' in property)) throw new Error('Code runtime values must not contain accessors.')\n\t\t\t\t\tcheck(property.value, depth + 1)\n\t\t\t\t}\n\t\t\t\tparents.delete(item)\n\t\t\t}\n\t\t\tcheck(value, 0)\n\t\t\treturn stringify(value)\n\t\t}\n\t}.toString() + ')()'))\n\tconst decode = keep(vm.evalCode('(function () { const parse = JSON.parse; return function(value) { return parse(value); }; })()'))\n\tconst errorText = keep(vm.evalCode('(function () { const string = String; return function(error) { try { return typeof error.message === \"string\" ? error.message : string(error); } catch { return \"The program failed.\"; } }; })()'))\n\n\tfunction textValue(handle, maximum) {\n\t\tconst length = vm.getProp(handle, 'length')\n\t\ttry {\n\t\t\tif (vm.getNumber(length) > maximum) throw new Error('Code runtime value exceeds ' + maximum + ' bytes.')\n\t\t} finally { length.dispose() }\n\t\tconst text = vm.getString(handle)\n\t\tif (Buffer.byteLength(text) > maximum) throw new Error('Code runtime value exceeds ' + maximum + ' bytes.')\n\t\treturn text\n\t}\n\tfunction serialize(handle, maximum) {\n\t\tif (vm.typeof(handle) === 'undefined') return undefined\n\t\tconst encoded = vm.callFunction(encode, vm.undefined, handle)\n\t\tif (encoded.error) {\n\t\t\tencoded.error.dispose()\n\t\t\tthrow new Error('Code runtime values must be JSON-safe and serializable.')\n\t\t}\n\t\ttry { return textValue(encoded.value, maximum) }\n\t\tfinally { encoded.value.dispose() }\n\t}\n\tfunction failureText(handle) {\n\t\tconst result = vm.callFunction(errorText, vm.undefined, handle)\n\t\tif (result.error) { result.error.dispose(); return 'The program failed.' }\n\t\t// Diagnostics have their own fixed bound. A deliberately tiny data\n\t\t// allowance must not erase the reason or the no-replay guidance for an\n\t\t// effect that completed but whose return value could not be delivered.\n\t\ttry { return textValue(result.value, 4096) }\n\t\tcatch { return 'The program failed with an oversized error.' }\n\t\tfinally { result.value.dispose() }\n\t}\n\tfunction dispose() {\n\t\tfor (const deferred of pending.values()) deferred.dispose()\n\t\tpending.clear()\n\t\tif (program && program.alive) program.dispose()\n\t\tfor (const handle of owned) if (handle.alive) handle.dispose()\n\t\tvm.dispose()\n\t\truntime.dispose()\n\t}\n\tfunction finish(message) {\n\t\tif (ended) return\n\t\tended = true\n\t\t// A guest OOM can make QuickJS teardown throw. The worker still owns\n\t\t// the whole WASM module and is terminated by its parent on settlement.\n\t\ttry { dispose() } catch {}\n\t\tparentPort.postMessage(message)\n\t}\n\tfunction fail(error) {\n\t\tfinish(Date.now() >= workerData.deadline\n\t\t\t? { kind: 'timed-out' }\n\t\t\t: { kind: 'error', error: String(error && error.message || error).slice(0, 4096) })\n\t}\n\tfunction schedule() {\n\t\tif (ended || scheduled) return\n\t\tscheduled = true\n\t\tsetImmediate(() => { scheduled = false; pump() })\n\t}\n\tfunction pump() {\n\t\tif (ended || pumping) return\n\t\tpumping = true\n\t\ttry {\n\t\t\tconst jobs = runtime.executePendingJobs(32)\n\t\t\tif (jobs.error) {\n\t\t\t\tconst error = failureText(jobs.error)\n\t\t\t\tjobs.error.dispose()\n\t\t\t\tthrow new Error(error)\n\t\t\t}\n\t\t\tconst state = vm.getPromiseState(program)\n\t\t\tif (state.type === 'fulfilled') {\n\t\t\t\tlet json\n\t\t\t\ttry { json = serialize(state.value, limits.maxValueBytes) }\n\t\t\t\tfinally { state.value.dispose() }\n\t\t\t\tfinish({ kind: 'done', json })\n\t\t\t} else if (state.type === 'rejected') {\n\t\t\t\tlet error\n\t\t\t\ttry { error = failureText(state.error) }\n\t\t\t\tfinally { state.error.dispose() }\n\t\t\t\tfail(new Error(error))\n\t\t\t} else if (runtime.hasPendingJob()) schedule()\n\t\t} catch (error) { fail(error) }\n\t\tfinally { pumping = false }\n\t}\n\tfunction rejected(message) {\n\t\tconst deferred = vm.newPromise()\n\t\tconst error = vm.newError(message)\n\t\tdeferred.reject(error)\n\t\terror.dispose()\n\t\treturn deferred.handle\n\t}\n\tconst call = vm.newFunction('call', (name, input = vm.undefined) => {\n\t\ttry {\n\t\t\tif (nextId >= limits.maxHostCalls) return rejected('Code runtime host-call limit reached.')\n\t\t\tif (pending.size >= limits.maxPendingHostCalls) return rejected('Code runtime pending host-call limit reached.')\n\t\t\tif (vm.typeof(name) !== 'string') return rejected('A host call requires a tool name string.')\n\t\t\tconst tool = textValue(name, Math.min(limits.maxValueBytes, 1024))\n\t\t\tconst json = serialize(input, limits.maxValueBytes)\n\t\t\tconst id = ++nextId\n\t\t\tconst deferred = vm.newPromise()\n\t\t\tpending.set(id, deferred)\n\t\t\tparentPort.postMessage({ kind: 'call', id, name: tool, json })\n\t\t\treturn deferred.handle\n\t\t} catch (error) { return rejected(String(error.message || error)) }\n\t})\n\tvm.setProp(vm.global, 'call', call)\n\tcall.dispose()\n\tconst print = vm.newFunction('print', (...values) => {\n\t\tif (truncated) return vm.undefined\n\t\ttry {\n\t\t\tconst parts = []\n\t\t\tlet remaining = workerData.maxOutputBytes - printBytes - (printCount > 0 ? 1 : 0)\n\t\t\tfor (const value of values) {\n\t\t\t\tif (parts.length) remaining--\n\t\t\t\tif (remaining < 0) throw new Error('output limit')\n\t\t\t\tconst text = vm.typeof(value) === 'string' ? textValue(value, remaining) : serialize(value, remaining)\n\t\t\t\tconst part = text === undefined ? '' : text\n\t\t\t\tremaining -= Buffer.byteLength(part)\n\t\t\t\tparts.push(part)\n\t\t\t}\n\t\t\tconst line = parts.join(' ')\n\t\t\tconst size = Buffer.byteLength(line) + (printCount > 0 ? 1 : 0)\n\t\t\tif (printBytes + size > workerData.maxOutputBytes) throw new Error('output limit')\n\t\t\t// Empty prints consume a newline after the first, so the byte\n\t\t\t// budget also bounds the number of worker messages.\n\t\t\tprintBytes += size\n\t\t\tprintCount++\n\t\t\tparentPort.postMessage({ kind: 'print', line })\n\t\t} catch {\n\t\t\ttruncated = true\n\t\t\tparentPort.postMessage({ kind: 'truncated' })\n\t\t}\n\t\treturn vm.undefined\n\t})\n\tvm.setProp(vm.global, 'print', print)\n\tprint.dispose()\n\n\tparentPort.on('message', (message) => {\n\t\tif (ended || message.kind !== 'call-result') return\n\t\tconst deferred = pending.get(message.id)\n\t\tif (!deferred) return\n\t\tpending.delete(message.id)\n\t\ttry {\n\t\t\tif (message.ok) {\n\t\t\t\tlet value = vm.undefined\n\t\t\t\tif (message.json !== undefined) {\n\t\t\t\t\tif (typeof message.json !== 'string' || Buffer.byteLength(message.json) > limits.maxValueBytes) throw new Error('Host result exceeds the value limit.')\n\t\t\t\t\tconst input = vm.newString(message.json)\n\t\t\t\t\ttry { value = vm.unwrapResult(vm.callFunction(decode, vm.undefined, input)) }\n\t\t\t\t\tfinally { input.dispose() }\n\t\t\t\t}\n\t\t\t\tdeferred.resolve(value)\n\t\t\t\tif (value !== vm.undefined) value.dispose()\n\t\t\t} else {\n\t\t\t\tconst error = vm.newError(String(message.error).slice(0, 4096))\n\t\t\t\tdeferred.reject(error)\n\t\t\t\terror.dispose()\n\t\t\t}\n\t\t\tdeferred.dispose()\n\t\t\tschedule()\n\t\t} catch (error) { deferred.dispose(); fail(error) }\n\t})\n\ttry {\n\t\tconst result = vm.evalCode('(async () => {\\n' + workerData.source + '\\n})()', 'model-program.js')\n\t\tif (result.error) {\n\t\t\tconst error = failureText(result.error)\n\t\t\tresult.error.dispose()\n\t\t\tfail(new Error(error))\n\t\t} else { program = result.value; pump() }\n\t} catch (error) { fail(error) }\n}\nmain().catch((error) => parentPort.postMessage({ kind: 'error', error: String(error && error.message || error).slice(0, 4096) }))\n";
|
|
8
|
+
//# sourceMappingURL=worker-program.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-program.d.ts","sourceRoot":"","sources":["../../../src/execution/code-runtime/worker-program.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,8qTAwOjC,CAAA"}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trusted worker bootstrap. Only vm.evalCode executes the untrusted program.
|
|
3
|
+
* Kept as source so installed/bundled SDKs need no separate worker entry file.
|
|
4
|
+
* No Node object or callback is injected into QuickJS: its native functions
|
|
5
|
+
* exchange bounded strings and interpreter-owned promise handles.
|
|
6
|
+
*/
|
|
7
|
+
export const QUICKJS_WORKER_SOURCE = `
|
|
8
|
+
const { parentPort, workerData } = require('node:worker_threads')
|
|
9
|
+
const { newQuickJSWASMModuleFromVariant, newVariant } = require(workerData.corePath)
|
|
10
|
+
const variantModule = require(workerData.variantPath)
|
|
11
|
+
const variant = variantModule.default || variantModule
|
|
12
|
+
|
|
13
|
+
async function main() {
|
|
14
|
+
const limits = workerData.limits
|
|
15
|
+
const pages = Math.floor(limits.memoryLimitBytes / 65536)
|
|
16
|
+
const wasmMemory = new WebAssembly.Memory({ initial: Math.min(256, pages), maximum: pages })
|
|
17
|
+
const module = await newQuickJSWASMModuleFromVariant(newVariant(variant, { wasmMemory }))
|
|
18
|
+
const runtime = module.newRuntime()
|
|
19
|
+
runtime.setMemoryLimit(limits.memoryLimitBytes)
|
|
20
|
+
runtime.setMaxStackSize(512 * 1024)
|
|
21
|
+
runtime.setInterruptHandler(() => Date.now() >= workerData.deadline)
|
|
22
|
+
const vm = runtime.newContext()
|
|
23
|
+
const pending = new Map()
|
|
24
|
+
let nextId = 0
|
|
25
|
+
let printBytes = 0
|
|
26
|
+
let printCount = 0
|
|
27
|
+
let truncated = false
|
|
28
|
+
let ended = false
|
|
29
|
+
let pumping = false
|
|
30
|
+
let scheduled = false
|
|
31
|
+
let program
|
|
32
|
+
const owned = []
|
|
33
|
+
|
|
34
|
+
function keep(result) {
|
|
35
|
+
const handle = vm.unwrapResult(result)
|
|
36
|
+
owned.push(handle)
|
|
37
|
+
return handle
|
|
38
|
+
}
|
|
39
|
+
// Capture intrinsics before the program may replace its own globals.
|
|
40
|
+
const encode = keep(vm.evalCode('(' + function () {
|
|
41
|
+
const stringify = JSON.stringify
|
|
42
|
+
const finite = Number.isFinite
|
|
43
|
+
const prototype = Object.getPrototypeOf
|
|
44
|
+
const plain = Object.prototype
|
|
45
|
+
const isArray = Array.isArray
|
|
46
|
+
const keys = Object.keys
|
|
47
|
+
const descriptor = Object.getOwnPropertyDescriptor
|
|
48
|
+
return function (value) {
|
|
49
|
+
if (value === undefined) return undefined
|
|
50
|
+
const parents = new Set()
|
|
51
|
+
function check(item, depth) {
|
|
52
|
+
const kind = typeof item
|
|
53
|
+
if (item === null || kind === 'string' || kind === 'boolean' || (kind === 'number' && finite(item))) return
|
|
54
|
+
if (kind !== 'object' || depth > 64 || parents.has(item)) throw new Error('Code runtime values must be JSON-safe.')
|
|
55
|
+
if (!isArray(item) && prototype(item) !== plain && prototype(item) !== null) throw new Error('Code runtime values must use plain objects and arrays.')
|
|
56
|
+
parents.add(item)
|
|
57
|
+
for (const key of keys(item)) {
|
|
58
|
+
const property = descriptor(item, key)
|
|
59
|
+
if (!property || !('value' in property)) throw new Error('Code runtime values must not contain accessors.')
|
|
60
|
+
check(property.value, depth + 1)
|
|
61
|
+
}
|
|
62
|
+
parents.delete(item)
|
|
63
|
+
}
|
|
64
|
+
check(value, 0)
|
|
65
|
+
return stringify(value)
|
|
66
|
+
}
|
|
67
|
+
}.toString() + ')()'))
|
|
68
|
+
const decode = keep(vm.evalCode('(function () { const parse = JSON.parse; return function(value) { return parse(value); }; })()'))
|
|
69
|
+
const errorText = keep(vm.evalCode('(function () { const string = String; return function(error) { try { return typeof error.message === "string" ? error.message : string(error); } catch { return "The program failed."; } }; })()'))
|
|
70
|
+
|
|
71
|
+
function textValue(handle, maximum) {
|
|
72
|
+
const length = vm.getProp(handle, 'length')
|
|
73
|
+
try {
|
|
74
|
+
if (vm.getNumber(length) > maximum) throw new Error('Code runtime value exceeds ' + maximum + ' bytes.')
|
|
75
|
+
} finally { length.dispose() }
|
|
76
|
+
const text = vm.getString(handle)
|
|
77
|
+
if (Buffer.byteLength(text) > maximum) throw new Error('Code runtime value exceeds ' + maximum + ' bytes.')
|
|
78
|
+
return text
|
|
79
|
+
}
|
|
80
|
+
function serialize(handle, maximum) {
|
|
81
|
+
if (vm.typeof(handle) === 'undefined') return undefined
|
|
82
|
+
const encoded = vm.callFunction(encode, vm.undefined, handle)
|
|
83
|
+
if (encoded.error) {
|
|
84
|
+
encoded.error.dispose()
|
|
85
|
+
throw new Error('Code runtime values must be JSON-safe and serializable.')
|
|
86
|
+
}
|
|
87
|
+
try { return textValue(encoded.value, maximum) }
|
|
88
|
+
finally { encoded.value.dispose() }
|
|
89
|
+
}
|
|
90
|
+
function failureText(handle) {
|
|
91
|
+
const result = vm.callFunction(errorText, vm.undefined, handle)
|
|
92
|
+
if (result.error) { result.error.dispose(); return 'The program failed.' }
|
|
93
|
+
// Diagnostics have their own fixed bound. A deliberately tiny data
|
|
94
|
+
// allowance must not erase the reason or the no-replay guidance for an
|
|
95
|
+
// effect that completed but whose return value could not be delivered.
|
|
96
|
+
try { return textValue(result.value, 4096) }
|
|
97
|
+
catch { return 'The program failed with an oversized error.' }
|
|
98
|
+
finally { result.value.dispose() }
|
|
99
|
+
}
|
|
100
|
+
function dispose() {
|
|
101
|
+
for (const deferred of pending.values()) deferred.dispose()
|
|
102
|
+
pending.clear()
|
|
103
|
+
if (program && program.alive) program.dispose()
|
|
104
|
+
for (const handle of owned) if (handle.alive) handle.dispose()
|
|
105
|
+
vm.dispose()
|
|
106
|
+
runtime.dispose()
|
|
107
|
+
}
|
|
108
|
+
function finish(message) {
|
|
109
|
+
if (ended) return
|
|
110
|
+
ended = true
|
|
111
|
+
// A guest OOM can make QuickJS teardown throw. The worker still owns
|
|
112
|
+
// the whole WASM module and is terminated by its parent on settlement.
|
|
113
|
+
try { dispose() } catch {}
|
|
114
|
+
parentPort.postMessage(message)
|
|
115
|
+
}
|
|
116
|
+
function fail(error) {
|
|
117
|
+
finish(Date.now() >= workerData.deadline
|
|
118
|
+
? { kind: 'timed-out' }
|
|
119
|
+
: { kind: 'error', error: String(error && error.message || error).slice(0, 4096) })
|
|
120
|
+
}
|
|
121
|
+
function schedule() {
|
|
122
|
+
if (ended || scheduled) return
|
|
123
|
+
scheduled = true
|
|
124
|
+
setImmediate(() => { scheduled = false; pump() })
|
|
125
|
+
}
|
|
126
|
+
function pump() {
|
|
127
|
+
if (ended || pumping) return
|
|
128
|
+
pumping = true
|
|
129
|
+
try {
|
|
130
|
+
const jobs = runtime.executePendingJobs(32)
|
|
131
|
+
if (jobs.error) {
|
|
132
|
+
const error = failureText(jobs.error)
|
|
133
|
+
jobs.error.dispose()
|
|
134
|
+
throw new Error(error)
|
|
135
|
+
}
|
|
136
|
+
const state = vm.getPromiseState(program)
|
|
137
|
+
if (state.type === 'fulfilled') {
|
|
138
|
+
let json
|
|
139
|
+
try { json = serialize(state.value, limits.maxValueBytes) }
|
|
140
|
+
finally { state.value.dispose() }
|
|
141
|
+
finish({ kind: 'done', json })
|
|
142
|
+
} else if (state.type === 'rejected') {
|
|
143
|
+
let error
|
|
144
|
+
try { error = failureText(state.error) }
|
|
145
|
+
finally { state.error.dispose() }
|
|
146
|
+
fail(new Error(error))
|
|
147
|
+
} else if (runtime.hasPendingJob()) schedule()
|
|
148
|
+
} catch (error) { fail(error) }
|
|
149
|
+
finally { pumping = false }
|
|
150
|
+
}
|
|
151
|
+
function rejected(message) {
|
|
152
|
+
const deferred = vm.newPromise()
|
|
153
|
+
const error = vm.newError(message)
|
|
154
|
+
deferred.reject(error)
|
|
155
|
+
error.dispose()
|
|
156
|
+
return deferred.handle
|
|
157
|
+
}
|
|
158
|
+
const call = vm.newFunction('call', (name, input = vm.undefined) => {
|
|
159
|
+
try {
|
|
160
|
+
if (nextId >= limits.maxHostCalls) return rejected('Code runtime host-call limit reached.')
|
|
161
|
+
if (pending.size >= limits.maxPendingHostCalls) return rejected('Code runtime pending host-call limit reached.')
|
|
162
|
+
if (vm.typeof(name) !== 'string') return rejected('A host call requires a tool name string.')
|
|
163
|
+
const tool = textValue(name, Math.min(limits.maxValueBytes, 1024))
|
|
164
|
+
const json = serialize(input, limits.maxValueBytes)
|
|
165
|
+
const id = ++nextId
|
|
166
|
+
const deferred = vm.newPromise()
|
|
167
|
+
pending.set(id, deferred)
|
|
168
|
+
parentPort.postMessage({ kind: 'call', id, name: tool, json })
|
|
169
|
+
return deferred.handle
|
|
170
|
+
} catch (error) { return rejected(String(error.message || error)) }
|
|
171
|
+
})
|
|
172
|
+
vm.setProp(vm.global, 'call', call)
|
|
173
|
+
call.dispose()
|
|
174
|
+
const print = vm.newFunction('print', (...values) => {
|
|
175
|
+
if (truncated) return vm.undefined
|
|
176
|
+
try {
|
|
177
|
+
const parts = []
|
|
178
|
+
let remaining = workerData.maxOutputBytes - printBytes - (printCount > 0 ? 1 : 0)
|
|
179
|
+
for (const value of values) {
|
|
180
|
+
if (parts.length) remaining--
|
|
181
|
+
if (remaining < 0) throw new Error('output limit')
|
|
182
|
+
const text = vm.typeof(value) === 'string' ? textValue(value, remaining) : serialize(value, remaining)
|
|
183
|
+
const part = text === undefined ? '' : text
|
|
184
|
+
remaining -= Buffer.byteLength(part)
|
|
185
|
+
parts.push(part)
|
|
186
|
+
}
|
|
187
|
+
const line = parts.join(' ')
|
|
188
|
+
const size = Buffer.byteLength(line) + (printCount > 0 ? 1 : 0)
|
|
189
|
+
if (printBytes + size > workerData.maxOutputBytes) throw new Error('output limit')
|
|
190
|
+
// Empty prints consume a newline after the first, so the byte
|
|
191
|
+
// budget also bounds the number of worker messages.
|
|
192
|
+
printBytes += size
|
|
193
|
+
printCount++
|
|
194
|
+
parentPort.postMessage({ kind: 'print', line })
|
|
195
|
+
} catch {
|
|
196
|
+
truncated = true
|
|
197
|
+
parentPort.postMessage({ kind: 'truncated' })
|
|
198
|
+
}
|
|
199
|
+
return vm.undefined
|
|
200
|
+
})
|
|
201
|
+
vm.setProp(vm.global, 'print', print)
|
|
202
|
+
print.dispose()
|
|
203
|
+
|
|
204
|
+
parentPort.on('message', (message) => {
|
|
205
|
+
if (ended || message.kind !== 'call-result') return
|
|
206
|
+
const deferred = pending.get(message.id)
|
|
207
|
+
if (!deferred) return
|
|
208
|
+
pending.delete(message.id)
|
|
209
|
+
try {
|
|
210
|
+
if (message.ok) {
|
|
211
|
+
let value = vm.undefined
|
|
212
|
+
if (message.json !== undefined) {
|
|
213
|
+
if (typeof message.json !== 'string' || Buffer.byteLength(message.json) > limits.maxValueBytes) throw new Error('Host result exceeds the value limit.')
|
|
214
|
+
const input = vm.newString(message.json)
|
|
215
|
+
try { value = vm.unwrapResult(vm.callFunction(decode, vm.undefined, input)) }
|
|
216
|
+
finally { input.dispose() }
|
|
217
|
+
}
|
|
218
|
+
deferred.resolve(value)
|
|
219
|
+
if (value !== vm.undefined) value.dispose()
|
|
220
|
+
} else {
|
|
221
|
+
const error = vm.newError(String(message.error).slice(0, 4096))
|
|
222
|
+
deferred.reject(error)
|
|
223
|
+
error.dispose()
|
|
224
|
+
}
|
|
225
|
+
deferred.dispose()
|
|
226
|
+
schedule()
|
|
227
|
+
} catch (error) { deferred.dispose(); fail(error) }
|
|
228
|
+
})
|
|
229
|
+
try {
|
|
230
|
+
const result = vm.evalCode('(async () => {\\n' + workerData.source + '\\n})()', 'model-program.js')
|
|
231
|
+
if (result.error) {
|
|
232
|
+
const error = failureText(result.error)
|
|
233
|
+
result.error.dispose()
|
|
234
|
+
fail(new Error(error))
|
|
235
|
+
} else { program = result.value; pump() }
|
|
236
|
+
} catch (error) { fail(error) }
|
|
237
|
+
}
|
|
238
|
+
main().catch((error) => parentPort.postMessage({ kind: 'error', error: String(error && error.message || error).slice(0, 4096) }))
|
|
239
|
+
`;
|
|
240
|
+
//# sourceMappingURL=worker-program.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-program.js","sourceRoot":"","sources":["../../../src/execution/code-runtime/worker-program.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwOpC,CAAA"}
|
|
@@ -1,6 +1,28 @@
|
|
|
1
1
|
import { type CodeRunResult, type CodeRuntime, type RunCodeOptions } from './types.js';
|
|
2
|
+
/** Resource policy for one fresh QuickJS worker execution. */
|
|
3
|
+
export interface WorkerCodeRuntimeOptions {
|
|
4
|
+
/** QuickJS allocator limit, also the WASM linear-memory ceiling. Does not bound total Node/process memory. Default: 64 MiB. */
|
|
5
|
+
readonly memoryLimitBytes?: number;
|
|
6
|
+
/** Maximum UTF-8 program source size. Default: 256 KiB. */
|
|
7
|
+
readonly maxSourceBytes?: number;
|
|
8
|
+
/** Maximum UTF-8 JSON size of each input, host result, and program return. Default: 1 MiB. */
|
|
9
|
+
readonly maxValueBytes?: number;
|
|
10
|
+
/** Maximum host calls admitted by one program, including refusals. Default: 100. */
|
|
11
|
+
readonly maxHostCalls?: number;
|
|
12
|
+
/** Maximum host calls awaiting replies simultaneously. Default: 100. */
|
|
13
|
+
readonly maxPendingHostCalls?: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Runs untrusted JavaScript in a QuickJS interpreter inside a worker thread.
|
|
17
|
+
* QuickJS owns the guest globals, functions, and promises. Node capabilities
|
|
18
|
+
* never enter that realm; constructors and dynamic imports cannot recover them.
|
|
19
|
+
* A fresh interpreter and bounded imported WASM memory are created per run.
|
|
20
|
+
* The worker makes wall-clock cancellation independent of interpreter progress.
|
|
21
|
+
*/
|
|
2
22
|
export declare class WorkerCodeRuntime implements CodeRuntime {
|
|
3
23
|
readonly id = "worker_threads";
|
|
24
|
+
private readonly limits;
|
|
25
|
+
constructor(options?: WorkerCodeRuntimeOptions);
|
|
4
26
|
run(options: RunCodeOptions): Promise<CodeRunResult>;
|
|
5
27
|
}
|
|
6
28
|
//# sourceMappingURL=worker.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../../src/execution/code-runtime/worker.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../../src/execution/code-runtime/worker.ts"],"names":[],"mappings":"AAIA,OAAO,EACN,KAAK,aAAa,EAClB,KAAK,WAAW,EAEhB,KAAK,cAAc,EACnB,MAAM,YAAY,CAAA;AAKnB,8DAA8D;AAC9D,MAAM,WAAW,wBAAwB;IACxC,+HAA+H;IAC/H,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;IAClC,2DAA2D;IAC3D,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;IAChC,8FAA8F;IAC9F,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAC/B,oFAAoF;IACpF,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;IAC9B,wEAAwE;IACxE,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAA;CACrC;AAgCD;;;;;;GAMG;AACH,qBAAa,iBAAkB,YAAW,WAAW;IACpD,QAAQ,CAAC,EAAE,oBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoC;gBAE/C,OAAO,GAAE,wBAA6B;IAI5C,GAAG,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;CAoT1D"}
|