@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
|
@@ -1,109 +1,85 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'
|
|
1
2
|
import { Worker } from 'node:worker_threads'
|
|
2
3
|
|
|
4
|
+
import { encodeCodeValue } from './json-value.js'
|
|
3
5
|
import {
|
|
4
6
|
type CodeRunResult,
|
|
5
7
|
type CodeRuntime,
|
|
6
8
|
HostCallDeniedError,
|
|
7
9
|
type RunCodeOptions,
|
|
8
10
|
} from './types.js'
|
|
11
|
+
import { QUICKJS_WORKER_SOURCE } from './worker-program.js'
|
|
9
12
|
|
|
10
|
-
|
|
11
|
-
* A `worker_threads` backend.
|
|
12
|
-
*
|
|
13
|
-
* Chosen over `vm` because `vm` is not a sandbox and its own documentation
|
|
14
|
-
* says so: a context shares the process, so a program that reaches a
|
|
15
|
-
* constructor from the host realm is out — `this.constructor.constructor`
|
|
16
|
-
* on any leaked object is the whole escape, and it fits in a tweet. A
|
|
17
|
-
* worker is a separate V8 isolate with its own heap; escaping it means
|
|
18
|
-
* escaping V8.
|
|
19
|
-
*
|
|
20
|
-
* Chosen over a subprocess because a subprocess is a process: it inherits
|
|
21
|
-
* an environment, it can be a fork bomb, and killing it is the process-tree
|
|
22
|
-
* problem `process/kill-tree.ts` exists for. A worker is cheaper to start,
|
|
23
|
-
* cheaper to kill, and cannot outlive the process that made it.
|
|
24
|
-
*
|
|
25
|
-
* What a worker does NOT give, stated because it is the reason this is not
|
|
26
|
-
* the whole answer: a worker shares the process's filesystem and network
|
|
27
|
-
* access. It is not confined by anything the OS enforces. What confines the
|
|
28
|
-
* program here is that it is handed a scope with nothing in it — no
|
|
29
|
-
* `require`, no `process`, no `fetch` — and a single channel back to the
|
|
30
|
-
* host. That is a language-level boundary, and a language-level boundary is
|
|
31
|
-
* exactly as strong as the enumeration of what was withheld. So a host that
|
|
32
|
-
* needs an OS boundary runs this inside a sandbox that has one, and this
|
|
33
|
-
* comment is here so nobody concludes the worker was the boundary.
|
|
34
|
-
*/
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* The worker's own body, as source.
|
|
38
|
-
*
|
|
39
|
-
* Inlined rather than a separate file because a separate file has to be
|
|
40
|
-
* findable at runtime, and this package is consumed as `dist/` by hosts
|
|
41
|
-
* whose bundlers rewrite paths. A string has no path.
|
|
42
|
-
*/
|
|
43
|
-
const WORKER_SOURCE = `
|
|
44
|
-
const { parentPort, workerData } = require('node:worker_threads')
|
|
45
|
-
|
|
46
|
-
// Every host call is a request/response over the port, keyed by an id so
|
|
47
|
-
// several can be in flight — a program that awaits two calls at once is
|
|
48
|
-
// ordinary, and a channel that could only carry one would silently
|
|
49
|
-
// serialise them.
|
|
50
|
-
const pending = new Map()
|
|
51
|
-
let nextId = 0
|
|
13
|
+
const requireFromSdk = createRequire(import.meta.url)
|
|
52
14
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
15
|
+
/** Resource policy for one fresh QuickJS worker execution. */
|
|
16
|
+
export interface WorkerCodeRuntimeOptions {
|
|
17
|
+
/** QuickJS allocator limit, also the WASM linear-memory ceiling. Does not bound total Node/process memory. Default: 64 MiB. */
|
|
18
|
+
readonly memoryLimitBytes?: number
|
|
19
|
+
/** Maximum UTF-8 program source size. Default: 256 KiB. */
|
|
20
|
+
readonly maxSourceBytes?: number
|
|
21
|
+
/** Maximum UTF-8 JSON size of each input, host result, and program return. Default: 1 MiB. */
|
|
22
|
+
readonly maxValueBytes?: number
|
|
23
|
+
/** Maximum host calls admitted by one program, including refusals. Default: 100. */
|
|
24
|
+
readonly maxHostCalls?: number
|
|
25
|
+
/** Maximum host calls awaiting replies simultaneously. Default: 100. */
|
|
26
|
+
readonly maxPendingHostCalls?: number
|
|
59
27
|
}
|
|
60
28
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
function print(...parts) {
|
|
66
|
-
parentPort.postMessage({
|
|
67
|
-
kind: 'print',
|
|
68
|
-
line: parts.map((p) => (typeof p === 'string' ? p : JSON.stringify(p))).join(' '),
|
|
69
|
-
})
|
|
29
|
+
function validateInteger(name: string, value: number, minimum: number, maximum: number): void {
|
|
30
|
+
if (!Number.isSafeInteger(value) || value < minimum || value > maximum) {
|
|
31
|
+
throw new RangeError(`${name} must be an integer between ${minimum} and ${maximum}.`)
|
|
32
|
+
}
|
|
70
33
|
}
|
|
71
34
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
// undefined.
|
|
87
|
-
const names = ['call', 'print', 'require', 'process', 'module', 'exports', 'globalThis', 'fetch']
|
|
88
|
-
const values = [hostCall, print, undefined, undefined, undefined, undefined, undefined, undefined]
|
|
89
|
-
const body = new Function(...names, '"use strict";return (async () => {' + workerData.source + '\\n})()')
|
|
90
|
-
return await body(...values)
|
|
35
|
+
function resolveLimits(options: WorkerCodeRuntimeOptions): Required<WorkerCodeRuntimeOptions> {
|
|
36
|
+
const limits = {
|
|
37
|
+
memoryLimitBytes: options.memoryLimitBytes ?? 64 * 1024 * 1024,
|
|
38
|
+
maxSourceBytes: options.maxSourceBytes ?? 256 * 1024,
|
|
39
|
+
maxValueBytes: options.maxValueBytes ?? 1024 * 1024,
|
|
40
|
+
maxHostCalls: options.maxHostCalls ?? 100,
|
|
41
|
+
maxPendingHostCalls: options.maxPendingHostCalls ?? options.maxHostCalls ?? 100,
|
|
42
|
+
}
|
|
43
|
+
validateInteger('memoryLimitBytes', limits.memoryLimitBytes, 16 * 1024 * 1024, 256 * 1024 * 1024)
|
|
44
|
+
validateInteger('maxSourceBytes', limits.maxSourceBytes, 1, 4 * 1024 * 1024)
|
|
45
|
+
validateInteger('maxValueBytes', limits.maxValueBytes, 1, 16 * 1024 * 1024)
|
|
46
|
+
validateInteger('maxHostCalls', limits.maxHostCalls, 1, 10_000)
|
|
47
|
+
validateInteger('maxPendingHostCalls', limits.maxPendingHostCalls, 1, limits.maxHostCalls)
|
|
48
|
+
return limits
|
|
91
49
|
}
|
|
92
50
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
(
|
|
96
|
-
)
|
|
97
|
-
|
|
51
|
+
function decodeValue(json: unknown, maxBytes: number): unknown {
|
|
52
|
+
if (json === undefined) return undefined
|
|
53
|
+
if (typeof json !== 'string' || Buffer.byteLength(json) > maxBytes) {
|
|
54
|
+
throw new Error('Code runtime value exceeds the serialized value limit.')
|
|
55
|
+
}
|
|
56
|
+
return JSON.parse(json)
|
|
57
|
+
}
|
|
98
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Runs untrusted JavaScript in a QuickJS interpreter inside a worker thread.
|
|
61
|
+
* QuickJS owns the guest globals, functions, and promises. Node capabilities
|
|
62
|
+
* never enter that realm; constructors and dynamic imports cannot recover them.
|
|
63
|
+
* A fresh interpreter and bounded imported WASM memory are created per run.
|
|
64
|
+
* The worker makes wall-clock cancellation independent of interpreter progress.
|
|
65
|
+
*/
|
|
99
66
|
export class WorkerCodeRuntime implements CodeRuntime {
|
|
100
67
|
readonly id = 'worker_threads'
|
|
68
|
+
private readonly limits: Required<WorkerCodeRuntimeOptions>
|
|
69
|
+
|
|
70
|
+
constructor(options: WorkerCodeRuntimeOptions = {}) {
|
|
71
|
+
this.limits = resolveLimits(options)
|
|
72
|
+
}
|
|
101
73
|
|
|
102
74
|
async run(options: RunCodeOptions): Promise<CodeRunResult> {
|
|
75
|
+
validateInteger('timeoutMs', options.timeoutMs, 1, 2_147_483_647)
|
|
76
|
+
validateInteger('maxOutputBytes', options.maxOutputBytes, 0, 16 * 1024 * 1024)
|
|
103
77
|
const allowed = new Set(options.allowedCalls)
|
|
104
78
|
const calls: { name: string; ok: boolean }[] = []
|
|
105
79
|
let output = ''
|
|
106
80
|
let truncated = false
|
|
81
|
+
let printCount = 0
|
|
82
|
+
const seenCalls = new Set<number>()
|
|
107
83
|
|
|
108
84
|
// A withdrawn caller owns admission. Do not start an isolate merely to
|
|
109
85
|
// discover the signal was already aborted after construction.
|
|
@@ -116,10 +92,25 @@ export class WorkerCodeRuntime implements CodeRuntime {
|
|
|
116
92
|
}
|
|
117
93
|
}
|
|
118
94
|
|
|
95
|
+
if (
|
|
96
|
+
options.source.length > this.limits.maxSourceBytes ||
|
|
97
|
+
Buffer.byteLength(options.source) > this.limits.maxSourceBytes
|
|
98
|
+
) {
|
|
99
|
+
return {
|
|
100
|
+
outcome: {
|
|
101
|
+
status: 'failed',
|
|
102
|
+
error: `Program source exceeds ${this.limits.maxSourceBytes} bytes.`,
|
|
103
|
+
},
|
|
104
|
+
output,
|
|
105
|
+
outputTruncated: truncated,
|
|
106
|
+
calls,
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
119
110
|
const appendOutput = (lines: readonly string[]): void => {
|
|
120
111
|
for (const line of lines) {
|
|
121
112
|
if (truncated) return
|
|
122
|
-
const next =
|
|
113
|
+
const next = printCount === 0 ? line : `${output}\n${line}`
|
|
123
114
|
if (Buffer.byteLength(next) > options.maxOutputBytes) {
|
|
124
115
|
// Cut at the LINE that would exceed, and say so. A cut
|
|
125
116
|
// mid-JSON produces output a reader cannot parse and cannot
|
|
@@ -128,26 +119,24 @@ export class WorkerCodeRuntime implements CodeRuntime {
|
|
|
128
119
|
return
|
|
129
120
|
}
|
|
130
121
|
output = next
|
|
122
|
+
printCount++
|
|
131
123
|
}
|
|
132
124
|
}
|
|
133
125
|
|
|
134
|
-
const worker = new Worker(
|
|
126
|
+
const worker = new Worker(QUICKJS_WORKER_SOURCE, {
|
|
135
127
|
eval: true,
|
|
136
|
-
workerData: {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
//
|
|
145
|
-
//
|
|
146
|
-
|
|
128
|
+
workerData: {
|
|
129
|
+
source: options.source,
|
|
130
|
+
corePath: requireFromSdk.resolve('quickjs-emscripten-core'),
|
|
131
|
+
variantPath: requireFromSdk.resolve('@jitl/quickjs-wasmfile-release-sync'),
|
|
132
|
+
limits: this.limits,
|
|
133
|
+
maxOutputBytes: options.maxOutputBytes,
|
|
134
|
+
deadline: Date.now() + options.timeoutMs,
|
|
135
|
+
},
|
|
136
|
+
// Trusted bootstrap requires Node; guest code runs only inside QuickJS.
|
|
137
|
+
// Avoid inheriting --input-type or test loaders into the CJS bootstrap.
|
|
138
|
+
execArgv: [],
|
|
147
139
|
env: {},
|
|
148
|
-
// No stdio inheritance: the program prints through `print`, which
|
|
149
|
-
// is bounded. A worker writing to the host's stdout would bypass
|
|
150
|
-
// the cap and interleave with the operator's own output.
|
|
151
140
|
stdout: true,
|
|
152
141
|
stderr: true,
|
|
153
142
|
})
|
|
@@ -212,13 +201,59 @@ export class WorkerCodeRuntime implements CodeRuntime {
|
|
|
212
201
|
}
|
|
213
202
|
|
|
214
203
|
worker.on('message', (message: Record<string, unknown>) => {
|
|
204
|
+
if (settled) return
|
|
205
|
+
if (message.kind === 'truncated') {
|
|
206
|
+
truncated = true
|
|
207
|
+
return
|
|
208
|
+
}
|
|
209
|
+
if (message.kind === 'timed-out') {
|
|
210
|
+
operation.abort(new Error(`Code runtime exceeded ${options.timeoutMs}ms`))
|
|
211
|
+
finish({
|
|
212
|
+
outcome: { status: 'timed-out' },
|
|
213
|
+
output,
|
|
214
|
+
outputTruncated: truncated,
|
|
215
|
+
calls,
|
|
216
|
+
})
|
|
217
|
+
return
|
|
218
|
+
}
|
|
215
219
|
if (message.kind === 'call') {
|
|
216
220
|
const name = String(message.name)
|
|
217
221
|
const id = message.id
|
|
222
|
+
if (
|
|
223
|
+
typeof id !== 'number' ||
|
|
224
|
+
!Number.isSafeInteger(id) ||
|
|
225
|
+
id < 1 ||
|
|
226
|
+
seenCalls.has(id) ||
|
|
227
|
+
seenCalls.size >= this.limits.maxHostCalls ||
|
|
228
|
+
inFlight.size >= this.limits.maxPendingHostCalls
|
|
229
|
+
) {
|
|
230
|
+
finish({
|
|
231
|
+
outcome: {
|
|
232
|
+
status: 'failed',
|
|
233
|
+
error: 'Invalid or over-budget host call.',
|
|
234
|
+
},
|
|
235
|
+
output,
|
|
236
|
+
outputTruncated: truncated,
|
|
237
|
+
calls,
|
|
238
|
+
})
|
|
239
|
+
return
|
|
240
|
+
}
|
|
241
|
+
seenCalls.add(id)
|
|
242
|
+
let input: unknown
|
|
243
|
+
try {
|
|
244
|
+
input = decodeValue(message.json, this.limits.maxValueBytes)
|
|
245
|
+
} catch (error) {
|
|
246
|
+
finish({
|
|
247
|
+
outcome: { status: 'failed', error: String(error) },
|
|
248
|
+
output,
|
|
249
|
+
outputTruncated: truncated,
|
|
250
|
+
calls,
|
|
251
|
+
})
|
|
252
|
+
return
|
|
253
|
+
}
|
|
218
254
|
if (!allowed.has(name)) {
|
|
219
|
-
//
|
|
220
|
-
//
|
|
221
|
-
// check the program shares a heap with.
|
|
255
|
+
// Authorization remains host-owned even though the interpreter
|
|
256
|
+
// also bounds its own bridge. A worker never expands the grant.
|
|
222
257
|
calls.push({ name, ok: false })
|
|
223
258
|
worker.postMessage({
|
|
224
259
|
kind: 'call-result',
|
|
@@ -234,20 +269,27 @@ export class WorkerCodeRuntime implements CodeRuntime {
|
|
|
234
269
|
const runtimeToolCallId = String(id)
|
|
235
270
|
const hostCall = Promise.resolve()
|
|
236
271
|
.then(() =>
|
|
237
|
-
options.onHostCall(
|
|
238
|
-
{ name, input: message.input },
|
|
239
|
-
{ runtimeToolCallId, signal: operation.signal },
|
|
240
|
-
),
|
|
272
|
+
options.onHostCall({ name, input }, { runtimeToolCallId, signal: operation.signal }),
|
|
241
273
|
)
|
|
242
274
|
.then((result) => {
|
|
243
275
|
if (settled) return
|
|
276
|
+
let json: string | undefined
|
|
277
|
+
try {
|
|
278
|
+
json = result.ok
|
|
279
|
+
? encodeCodeValue(result.value, this.limits.maxValueBytes)
|
|
280
|
+
: undefined
|
|
281
|
+
} catch (error) {
|
|
282
|
+
throw new Error(
|
|
283
|
+
`Host call "${name}" completed, but its result could not be delivered: ${error instanceof Error ? error.message : String(error)} Do not repeat a state-changing call solely to recover its output.`,
|
|
284
|
+
)
|
|
285
|
+
}
|
|
244
286
|
calls.push({ name, ok: result.ok })
|
|
245
287
|
worker.postMessage({
|
|
246
288
|
kind: 'call-result',
|
|
247
289
|
id,
|
|
248
290
|
ok: result.ok,
|
|
249
|
-
|
|
250
|
-
error: result.error,
|
|
291
|
+
json,
|
|
292
|
+
error: result.error?.slice(0, 4096),
|
|
251
293
|
})
|
|
252
294
|
})
|
|
253
295
|
.catch((err: unknown) => {
|
|
@@ -257,7 +299,7 @@ export class WorkerCodeRuntime implements CodeRuntime {
|
|
|
257
299
|
kind: 'call-result',
|
|
258
300
|
id,
|
|
259
301
|
ok: false,
|
|
260
|
-
error: err instanceof Error ? err.message : String(err),
|
|
302
|
+
error: (err instanceof Error ? err.message : String(err)).slice(0, 4096),
|
|
261
303
|
})
|
|
262
304
|
})
|
|
263
305
|
.finally(() => {
|
|
@@ -278,8 +320,20 @@ export class WorkerCodeRuntime implements CodeRuntime {
|
|
|
278
320
|
// declaring its JavaScript body complete is not evidence that the
|
|
279
321
|
// effect it started is complete, so keep the runtime open until the
|
|
280
322
|
// already-admitted host calls settle (or the deadline revokes them).
|
|
323
|
+
let value: unknown
|
|
324
|
+
try {
|
|
325
|
+
value = decodeValue(message.json, this.limits.maxValueBytes)
|
|
326
|
+
} catch (error) {
|
|
327
|
+
finish({
|
|
328
|
+
outcome: { status: 'failed', error: String(error) },
|
|
329
|
+
output,
|
|
330
|
+
outputTruncated: truncated,
|
|
331
|
+
calls,
|
|
332
|
+
})
|
|
333
|
+
return
|
|
334
|
+
}
|
|
281
335
|
terminal = {
|
|
282
|
-
outcome: { status: 'completed', result:
|
|
336
|
+
outcome: { status: 'completed', result: value },
|
|
283
337
|
output,
|
|
284
338
|
outputTruncated: truncated,
|
|
285
339
|
calls,
|
|
@@ -311,9 +365,8 @@ export class WorkerCodeRuntime implements CodeRuntime {
|
|
|
311
365
|
})
|
|
312
366
|
|
|
313
367
|
worker.on('exit', (code) => {
|
|
314
|
-
//
|
|
315
|
-
//
|
|
316
|
-
// `process.exit` through something we failed to withhold.
|
|
368
|
+
// A bootstrap or interpreter failure may exit before a terminal
|
|
369
|
+
// message. Guest code has no access to Node's process object.
|
|
317
370
|
finish({
|
|
318
371
|
outcome: {
|
|
319
372
|
status: 'failed',
|