@mcploom/codexec-worker 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,54 @@
1
+ # @mcploom/codexec-worker
2
+
3
+ Worker-thread executor for `@mcploom/codexec`, using the shared QuickJS runner behind a message boundary.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/%40mcploom%2Fcodexec--worker?style=flat-square)](https://www.npmjs.com/package/@mcploom/codexec-worker)
6
+ [![License](https://img.shields.io/github/license/aallam/mcploom?style=flat-square)](https://github.com/aallam/mcploom/blob/main/LICENSE)
7
+
8
+ ## Choose `codexec-worker` When
9
+
10
+ - you want QuickJS semantics without running the runtime on the main thread
11
+ - you want a worker termination backstop for timeouts
12
+ - you are comfortable paying worker startup overhead per execution
13
+
14
+ If you want the simplest default backend, use [`@mcploom/codexec-quickjs`](https://www.npmjs.com/package/@mcploom/codexec-quickjs) instead.
15
+
16
+ ## Install
17
+
18
+ ```bash
19
+ npm install @mcploom/codexec @mcploom/codexec-worker
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ ```ts
25
+ import { resolveProvider } from "@mcploom/codexec";
26
+ import { WorkerExecutor } from "@mcploom/codexec-worker";
27
+
28
+ const provider = resolveProvider({
29
+ name: "tools",
30
+ tools: {
31
+ echo: {
32
+ execute: async (input) => input,
33
+ },
34
+ },
35
+ });
36
+
37
+ const executor = new WorkerExecutor();
38
+ const result = await executor.execute("await tools.echo({ ok: true })", [
39
+ provider,
40
+ ]);
41
+ ```
42
+
43
+ ## Security Notes
44
+
45
+ - This package improves lifecycle isolation by moving the QuickJS runtime to a worker thread.
46
+ - It is still same-process execution and is not documented as a hard hostile-code boundary.
47
+ - Providers remain the real capability boundary.
48
+ - Internally it is a thin transport adapter over the shared `codexec-protocol` host session and the shared QuickJS protocol endpoint.
49
+
50
+ ## Examples
51
+
52
+ - [Worker-backed codexec execution](https://github.com/aallam/mcploom/blob/main/examples/codexec-worker.ts)
53
+ - [Architecture overview](https://github.com/aallam/mcploom/blob/main/docs/codexec/architecture/README.md)
54
+ - [Executors architecture](https://github.com/aallam/mcploom/blob/main/docs/codexec/architecture/codexec-executors.md)
package/dist/index.cjs ADDED
@@ -0,0 +1,94 @@
1
+ let node_crypto = require("node:crypto");
2
+ let node_worker_threads = require("node:worker_threads");
3
+ let __mcploom_codexec_protocol = require("@mcploom/codexec-protocol");
4
+ let __mcploom_codexec = require("@mcploom/codexec");
5
+
6
+ //#region src/workerExecutor.ts
7
+ const DEFAULT_CANCEL_GRACE_MS = 25;
8
+ const DEFAULT_MAX_LOG_CHARS = 64e3;
9
+ const DEFAULT_MAX_LOG_LINES = 100;
10
+ const DEFAULT_MEMORY_LIMIT_BYTES = 64 * 1024 * 1024;
11
+ const DEFAULT_TIMEOUT_MS = 5e3;
12
+ function resolveWorkerEntryUrl() {
13
+ const extension = require("url").pathToFileURL(__filename).href.endsWith(".ts") ? ".ts" : ".js";
14
+ return new URL(`./workerEntry${extension}`, require("url").pathToFileURL(__filename).href);
15
+ }
16
+ function createRuntimeOptions(options, overrides = {}) {
17
+ return {
18
+ maxLogChars: overrides.maxLogChars ?? options.maxLogChars ?? DEFAULT_MAX_LOG_CHARS,
19
+ maxLogLines: overrides.maxLogLines ?? options.maxLogLines ?? DEFAULT_MAX_LOG_LINES,
20
+ memoryLimitBytes: overrides.memoryLimitBytes ?? options.memoryLimitBytes ?? DEFAULT_MEMORY_LIMIT_BYTES,
21
+ timeoutMs: overrides.timeoutMs ?? options.timeoutMs ?? DEFAULT_TIMEOUT_MS
22
+ };
23
+ }
24
+ function createWorkerTransport(worker) {
25
+ return {
26
+ dispose: async () => {
27
+ await worker.terminate().catch(() => {});
28
+ },
29
+ onClose: (handler) => {
30
+ const wrapped = (code) => {
31
+ handler({
32
+ code,
33
+ message: `Worker exited unexpectedly with code ${code}`
34
+ });
35
+ };
36
+ worker.on("exit", wrapped);
37
+ return () => worker.off("exit", wrapped);
38
+ },
39
+ onError: (handler) => {
40
+ worker.on("error", handler);
41
+ return () => worker.off("error", handler);
42
+ },
43
+ onMessage: (handler) => {
44
+ const wrapped = (message) => {
45
+ handler(message);
46
+ };
47
+ worker.on("message", wrapped);
48
+ return () => worker.off("message", wrapped);
49
+ },
50
+ send: (message) => {
51
+ worker.postMessage(message);
52
+ },
53
+ terminate: async () => {
54
+ await worker.terminate().catch(() => {});
55
+ }
56
+ };
57
+ }
58
+ /**
59
+ * Worker-thread executor that runs guest code inside a dedicated QuickJS runtime per call.
60
+ */
61
+ var WorkerExecutor = class {
62
+ cancelGraceMs;
63
+ options;
64
+ /**
65
+ * Creates a worker-backed executor with hard-stop timeout behavior.
66
+ */
67
+ constructor(options = {}) {
68
+ this.cancelGraceMs = options.cancelGraceMs ?? DEFAULT_CANCEL_GRACE_MS;
69
+ this.options = options;
70
+ }
71
+ /**
72
+ * Executes JavaScript inside a fresh worker thread running QuickJS.
73
+ */
74
+ async execute(code, providers, options = {}) {
75
+ if (options.signal?.aborted) return (0, __mcploom_codexec.createTimeoutExecuteResult)();
76
+ const worker = new node_worker_threads.Worker(resolveWorkerEntryUrl(), {
77
+ execArgv: (0, __mcploom_codexec_protocol.getNodeTransportExecArgv)(require("url").pathToFileURL(__filename).href),
78
+ resourceLimits: this.options.workerResourceLimits
79
+ });
80
+ return await (0, __mcploom_codexec_protocol.runHostTransportSession)({
81
+ cancelGraceMs: this.cancelGraceMs,
82
+ code,
83
+ executionId: (0, node_crypto.randomUUID)(),
84
+ providers,
85
+ runtimeOptions: createRuntimeOptions(this.options, options),
86
+ signal: options.signal,
87
+ transport: createWorkerTransport(worker)
88
+ });
89
+ }
90
+ };
91
+
92
+ //#endregion
93
+ exports.WorkerExecutor = WorkerExecutor;
94
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["Worker"],"sources":["../src/workerExecutor.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { Worker } from \"node:worker_threads\";\n\nimport {\n type ExecutorRuntimeOptions,\n runHostTransportSession,\n getNodeTransportExecArgv,\n type HostTransport,\n type RunnerMessage,\n} from \"@mcploom/codexec-protocol\";\nimport {\n createTimeoutExecuteResult,\n type ExecutionOptions,\n type ExecuteResult,\n type Executor,\n type ResolvedToolProvider,\n} from \"@mcploom/codexec\";\n\nimport type { WorkerExecutorOptions } from \"./types\";\n\nconst DEFAULT_CANCEL_GRACE_MS = 25;\nconst DEFAULT_MAX_LOG_CHARS = 64_000;\nconst DEFAULT_MAX_LOG_LINES = 100;\nconst DEFAULT_MEMORY_LIMIT_BYTES = 64 * 1024 * 1024;\nconst DEFAULT_TIMEOUT_MS = 5000;\n\nfunction resolveWorkerEntryUrl(): URL {\n const extension = import.meta.url.endsWith(\".ts\") ? \".ts\" : \".js\";\n return new URL(`./workerEntry${extension}`, import.meta.url);\n}\n\nfunction createRuntimeOptions(\n options: WorkerExecutorOptions,\n overrides: ExecutionOptions = {},\n): Required<ExecutorRuntimeOptions> {\n return {\n maxLogChars:\n overrides.maxLogChars ?? options.maxLogChars ?? DEFAULT_MAX_LOG_CHARS,\n maxLogLines:\n overrides.maxLogLines ?? options.maxLogLines ?? DEFAULT_MAX_LOG_LINES,\n memoryLimitBytes:\n overrides.memoryLimitBytes ??\n options.memoryLimitBytes ??\n DEFAULT_MEMORY_LIMIT_BYTES,\n timeoutMs: overrides.timeoutMs ?? options.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n };\n}\n\nfunction createWorkerTransport(worker: Worker): HostTransport {\n return {\n dispose: async () => {\n await worker.terminate().catch(() => {});\n },\n onClose: (handler) => {\n const wrapped = (code: number) => {\n handler({\n code,\n message: `Worker exited unexpectedly with code ${code}`,\n });\n };\n worker.on(\"exit\", wrapped);\n return () => worker.off(\"exit\", wrapped);\n },\n onError: (handler) => {\n worker.on(\"error\", handler);\n return () => worker.off(\"error\", handler);\n },\n onMessage: (handler) => {\n const wrapped = (message: unknown) => {\n handler(message as RunnerMessage);\n };\n worker.on(\"message\", wrapped);\n return () => worker.off(\"message\", wrapped);\n },\n send: (message) => {\n worker.postMessage(message);\n },\n terminate: async () => {\n await worker.terminate().catch(() => {});\n },\n };\n}\n\n/**\n * Worker-thread executor that runs guest code inside a dedicated QuickJS runtime per call.\n */\nexport class WorkerExecutor implements Executor {\n private readonly cancelGraceMs: number;\n private readonly options: WorkerExecutorOptions;\n\n /**\n * Creates a worker-backed executor with hard-stop timeout behavior.\n */\n constructor(options: WorkerExecutorOptions = {}) {\n this.cancelGraceMs = options.cancelGraceMs ?? DEFAULT_CANCEL_GRACE_MS;\n this.options = options;\n }\n\n /**\n * Executes JavaScript inside a fresh worker thread running QuickJS.\n */\n async execute(\n code: string,\n providers: ResolvedToolProvider[],\n options: ExecutionOptions = {},\n ): Promise<ExecuteResult> {\n if (options.signal?.aborted) {\n return createTimeoutExecuteResult();\n }\n\n const worker = new Worker(resolveWorkerEntryUrl(), {\n execArgv: getNodeTransportExecArgv(import.meta.url),\n resourceLimits: this.options.workerResourceLimits,\n });\n\n return await runHostTransportSession({\n cancelGraceMs: this.cancelGraceMs,\n code,\n executionId: randomUUID(),\n providers,\n runtimeOptions: createRuntimeOptions(this.options, options),\n signal: options.signal,\n transport: createWorkerTransport(worker),\n });\n }\n}\n"],"mappings":";;;;;;AAoBA,MAAM,0BAA0B;AAChC,MAAM,wBAAwB;AAC9B,MAAM,wBAAwB;AAC9B,MAAM,6BAA6B,KAAK,OAAO;AAC/C,MAAM,qBAAqB;AAE3B,SAAS,wBAA6B;CACpC,MAAM,0DAA4B,SAAS,MAAM,GAAG,QAAQ;AAC5D,QAAO,IAAI,IAAI,gBAAgB,2DAA6B;;AAG9D,SAAS,qBACP,SACA,YAA8B,EAAE,EACE;AAClC,QAAO;EACL,aACE,UAAU,eAAe,QAAQ,eAAe;EAClD,aACE,UAAU,eAAe,QAAQ,eAAe;EAClD,kBACE,UAAU,oBACV,QAAQ,oBACR;EACF,WAAW,UAAU,aAAa,QAAQ,aAAa;EACxD;;AAGH,SAAS,sBAAsB,QAA+B;AAC5D,QAAO;EACL,SAAS,YAAY;AACnB,SAAM,OAAO,WAAW,CAAC,YAAY,GAAG;;EAE1C,UAAU,YAAY;GACpB,MAAM,WAAW,SAAiB;AAChC,YAAQ;KACN;KACA,SAAS,wCAAwC;KAClD,CAAC;;AAEJ,UAAO,GAAG,QAAQ,QAAQ;AAC1B,gBAAa,OAAO,IAAI,QAAQ,QAAQ;;EAE1C,UAAU,YAAY;AACpB,UAAO,GAAG,SAAS,QAAQ;AAC3B,gBAAa,OAAO,IAAI,SAAS,QAAQ;;EAE3C,YAAY,YAAY;GACtB,MAAM,WAAW,YAAqB;AACpC,YAAQ,QAAyB;;AAEnC,UAAO,GAAG,WAAW,QAAQ;AAC7B,gBAAa,OAAO,IAAI,WAAW,QAAQ;;EAE7C,OAAO,YAAY;AACjB,UAAO,YAAY,QAAQ;;EAE7B,WAAW,YAAY;AACrB,SAAM,OAAO,WAAW,CAAC,YAAY,GAAG;;EAE3C;;;;;AAMH,IAAa,iBAAb,MAAgD;CAC9C,AAAiB;CACjB,AAAiB;;;;CAKjB,YAAY,UAAiC,EAAE,EAAE;AAC/C,OAAK,gBAAgB,QAAQ,iBAAiB;AAC9C,OAAK,UAAU;;;;;CAMjB,MAAM,QACJ,MACA,WACA,UAA4B,EAAE,EACN;AACxB,MAAI,QAAQ,QAAQ,QAClB,2DAAmC;EAGrC,MAAM,SAAS,IAAIA,2BAAO,uBAAuB,EAAE;GACjD,iHAAmD;GACnD,gBAAgB,KAAK,QAAQ;GAC9B,CAAC;AAEF,SAAO,8DAA8B;GACnC,eAAe,KAAK;GACpB;GACA,0CAAyB;GACzB;GACA,gBAAgB,qBAAqB,KAAK,SAAS,QAAQ;GAC3D,QAAQ,QAAQ;GAChB,WAAW,sBAAsB,OAAO;GACzC,CAAC"}
@@ -0,0 +1,48 @@
1
+ import { ExecuteResult, ExecutionOptions, Executor, ResolvedToolProvider } from "@mcploom/codexec";
2
+
3
+ //#region src/types.d.ts
4
+ /**
5
+ * Optional V8 heap limits used only as a backstop for worker thread safety.
6
+ */
7
+ interface WorkerResourceLimits {
8
+ maxOldGenerationSizeMb?: number;
9
+ maxYoungGenerationSizeMb?: number;
10
+ stackSizeMb?: number;
11
+ }
12
+ /**
13
+ * Options for constructing a {@link WorkerExecutor}.
14
+ */
15
+ interface WorkerExecutorOptions {
16
+ /** Extra grace period after timeout before force-terminating the worker. */
17
+ cancelGraceMs?: number;
18
+ /** Maximum total characters preserved across captured log lines. */
19
+ maxLogChars?: number;
20
+ /** Maximum number of captured log lines returned in the result. */
21
+ maxLogLines?: number;
22
+ /** Guest memory limit in bytes enforced by QuickJS inside the worker. */
23
+ memoryLimitBytes?: number;
24
+ /** Wall-clock execution timeout in milliseconds. */
25
+ timeoutMs?: number;
26
+ /** Optional Node worker heap limits used as a backstop only. */
27
+ workerResourceLimits?: WorkerResourceLimits;
28
+ }
29
+ //#endregion
30
+ //#region src/workerExecutor.d.ts
31
+ /**
32
+ * Worker-thread executor that runs guest code inside a dedicated QuickJS runtime per call.
33
+ */
34
+ declare class WorkerExecutor implements Executor {
35
+ private readonly cancelGraceMs;
36
+ private readonly options;
37
+ /**
38
+ * Creates a worker-backed executor with hard-stop timeout behavior.
39
+ */
40
+ constructor(options?: WorkerExecutorOptions);
41
+ /**
42
+ * Executes JavaScript inside a fresh worker thread running QuickJS.
43
+ */
44
+ execute(code: string, providers: ResolvedToolProvider[], options?: ExecutionOptions): Promise<ExecuteResult>;
45
+ }
46
+ //#endregion
47
+ export { WorkerExecutor, type WorkerExecutorOptions, type WorkerResourceLimits };
48
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/workerExecutor.ts"],"sourcesContent":[],"mappings":";;;;;;AAGiB,UAAA,oBAAA,CAAoB;EASpB,sBAAA,CAAA,EAAqB,MAAA;;;;AC0EtC;;;AAkBa,UD5FI,qBAAA,CC4FJ;EACA;EAAR,aAAA,CAAA,EAAA,MAAA;EAnBkC;EAAQ,WAAA,CAAA,EAAA,MAAA;;;;;;;;yBD9DtB;;;;;AArBzB;AASA;cC0Ea,cAAA,YAA0B;;;EAA1B;;;EAkBA,WAAA,CAAA,OAAA,CAAA,EAXU,qBAWV;EACA;;;EAnBkC,OAAA,CAAA,IAAA,EAAA,MAAA,EAAA,SAAA,EAiBhC,oBAjBgC,EAAA,EAAA,OAAA,CAAA,EAkBlC,gBAlBkC,CAAA,EAmB1C,OAnB0C,CAmBlC,aAnBkC,CAAA"}
@@ -0,0 +1,48 @@
1
+ import { ExecuteResult, ExecutionOptions, Executor, ResolvedToolProvider } from "@mcploom/codexec";
2
+
3
+ //#region src/types.d.ts
4
+ /**
5
+ * Optional V8 heap limits used only as a backstop for worker thread safety.
6
+ */
7
+ interface WorkerResourceLimits {
8
+ maxOldGenerationSizeMb?: number;
9
+ maxYoungGenerationSizeMb?: number;
10
+ stackSizeMb?: number;
11
+ }
12
+ /**
13
+ * Options for constructing a {@link WorkerExecutor}.
14
+ */
15
+ interface WorkerExecutorOptions {
16
+ /** Extra grace period after timeout before force-terminating the worker. */
17
+ cancelGraceMs?: number;
18
+ /** Maximum total characters preserved across captured log lines. */
19
+ maxLogChars?: number;
20
+ /** Maximum number of captured log lines returned in the result. */
21
+ maxLogLines?: number;
22
+ /** Guest memory limit in bytes enforced by QuickJS inside the worker. */
23
+ memoryLimitBytes?: number;
24
+ /** Wall-clock execution timeout in milliseconds. */
25
+ timeoutMs?: number;
26
+ /** Optional Node worker heap limits used as a backstop only. */
27
+ workerResourceLimits?: WorkerResourceLimits;
28
+ }
29
+ //#endregion
30
+ //#region src/workerExecutor.d.ts
31
+ /**
32
+ * Worker-thread executor that runs guest code inside a dedicated QuickJS runtime per call.
33
+ */
34
+ declare class WorkerExecutor implements Executor {
35
+ private readonly cancelGraceMs;
36
+ private readonly options;
37
+ /**
38
+ * Creates a worker-backed executor with hard-stop timeout behavior.
39
+ */
40
+ constructor(options?: WorkerExecutorOptions);
41
+ /**
42
+ * Executes JavaScript inside a fresh worker thread running QuickJS.
43
+ */
44
+ execute(code: string, providers: ResolvedToolProvider[], options?: ExecutionOptions): Promise<ExecuteResult>;
45
+ }
46
+ //#endregion
47
+ export { WorkerExecutor, type WorkerExecutorOptions, type WorkerResourceLimits };
48
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/workerExecutor.ts"],"sourcesContent":[],"mappings":";;;;;;AAGiB,UAAA,oBAAA,CAAoB;EASpB,sBAAA,CAAA,EAAqB,MAAA;;;;AC0EtC;;;AAkBa,UD5FI,qBAAA,CC4FJ;EACA;EAAR,aAAA,CAAA,EAAA,MAAA;EAnBkC;EAAQ,WAAA,CAAA,EAAA,MAAA;;;;;;;;yBD9DtB;;;;;AArBzB;AASA;cC0Ea,cAAA,YAA0B;;;EAA1B;;;EAkBA,WAAA,CAAA,OAAA,CAAA,EAXU,qBAWV;EACA;;;EAnBkC,OAAA,CAAA,IAAA,EAAA,MAAA,EAAA,SAAA,EAiBhC,oBAjBgC,EAAA,EAAA,OAAA,CAAA,EAkBlC,gBAlBkC,CAAA,EAmB1C,OAnB0C,CAmBlC,aAnBkC,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,94 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { Worker } from "node:worker_threads";
3
+ import { getNodeTransportExecArgv, runHostTransportSession } from "@mcploom/codexec-protocol";
4
+ import { createTimeoutExecuteResult } from "@mcploom/codexec";
5
+
6
+ //#region src/workerExecutor.ts
7
+ const DEFAULT_CANCEL_GRACE_MS = 25;
8
+ const DEFAULT_MAX_LOG_CHARS = 64e3;
9
+ const DEFAULT_MAX_LOG_LINES = 100;
10
+ const DEFAULT_MEMORY_LIMIT_BYTES = 64 * 1024 * 1024;
11
+ const DEFAULT_TIMEOUT_MS = 5e3;
12
+ function resolveWorkerEntryUrl() {
13
+ const extension = import.meta.url.endsWith(".ts") ? ".ts" : ".js";
14
+ return new URL(`./workerEntry${extension}`, import.meta.url);
15
+ }
16
+ function createRuntimeOptions(options, overrides = {}) {
17
+ return {
18
+ maxLogChars: overrides.maxLogChars ?? options.maxLogChars ?? DEFAULT_MAX_LOG_CHARS,
19
+ maxLogLines: overrides.maxLogLines ?? options.maxLogLines ?? DEFAULT_MAX_LOG_LINES,
20
+ memoryLimitBytes: overrides.memoryLimitBytes ?? options.memoryLimitBytes ?? DEFAULT_MEMORY_LIMIT_BYTES,
21
+ timeoutMs: overrides.timeoutMs ?? options.timeoutMs ?? DEFAULT_TIMEOUT_MS
22
+ };
23
+ }
24
+ function createWorkerTransport(worker) {
25
+ return {
26
+ dispose: async () => {
27
+ await worker.terminate().catch(() => {});
28
+ },
29
+ onClose: (handler) => {
30
+ const wrapped = (code) => {
31
+ handler({
32
+ code,
33
+ message: `Worker exited unexpectedly with code ${code}`
34
+ });
35
+ };
36
+ worker.on("exit", wrapped);
37
+ return () => worker.off("exit", wrapped);
38
+ },
39
+ onError: (handler) => {
40
+ worker.on("error", handler);
41
+ return () => worker.off("error", handler);
42
+ },
43
+ onMessage: (handler) => {
44
+ const wrapped = (message) => {
45
+ handler(message);
46
+ };
47
+ worker.on("message", wrapped);
48
+ return () => worker.off("message", wrapped);
49
+ },
50
+ send: (message) => {
51
+ worker.postMessage(message);
52
+ },
53
+ terminate: async () => {
54
+ await worker.terminate().catch(() => {});
55
+ }
56
+ };
57
+ }
58
+ /**
59
+ * Worker-thread executor that runs guest code inside a dedicated QuickJS runtime per call.
60
+ */
61
+ var WorkerExecutor = class {
62
+ cancelGraceMs;
63
+ options;
64
+ /**
65
+ * Creates a worker-backed executor with hard-stop timeout behavior.
66
+ */
67
+ constructor(options = {}) {
68
+ this.cancelGraceMs = options.cancelGraceMs ?? DEFAULT_CANCEL_GRACE_MS;
69
+ this.options = options;
70
+ }
71
+ /**
72
+ * Executes JavaScript inside a fresh worker thread running QuickJS.
73
+ */
74
+ async execute(code, providers, options = {}) {
75
+ if (options.signal?.aborted) return createTimeoutExecuteResult();
76
+ const worker = new Worker(resolveWorkerEntryUrl(), {
77
+ execArgv: getNodeTransportExecArgv(import.meta.url),
78
+ resourceLimits: this.options.workerResourceLimits
79
+ });
80
+ return await runHostTransportSession({
81
+ cancelGraceMs: this.cancelGraceMs,
82
+ code,
83
+ executionId: randomUUID(),
84
+ providers,
85
+ runtimeOptions: createRuntimeOptions(this.options, options),
86
+ signal: options.signal,
87
+ transport: createWorkerTransport(worker)
88
+ });
89
+ }
90
+ };
91
+
92
+ //#endregion
93
+ export { WorkerExecutor };
94
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/workerExecutor.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { Worker } from \"node:worker_threads\";\n\nimport {\n type ExecutorRuntimeOptions,\n runHostTransportSession,\n getNodeTransportExecArgv,\n type HostTransport,\n type RunnerMessage,\n} from \"@mcploom/codexec-protocol\";\nimport {\n createTimeoutExecuteResult,\n type ExecutionOptions,\n type ExecuteResult,\n type Executor,\n type ResolvedToolProvider,\n} from \"@mcploom/codexec\";\n\nimport type { WorkerExecutorOptions } from \"./types\";\n\nconst DEFAULT_CANCEL_GRACE_MS = 25;\nconst DEFAULT_MAX_LOG_CHARS = 64_000;\nconst DEFAULT_MAX_LOG_LINES = 100;\nconst DEFAULT_MEMORY_LIMIT_BYTES = 64 * 1024 * 1024;\nconst DEFAULT_TIMEOUT_MS = 5000;\n\nfunction resolveWorkerEntryUrl(): URL {\n const extension = import.meta.url.endsWith(\".ts\") ? \".ts\" : \".js\";\n return new URL(`./workerEntry${extension}`, import.meta.url);\n}\n\nfunction createRuntimeOptions(\n options: WorkerExecutorOptions,\n overrides: ExecutionOptions = {},\n): Required<ExecutorRuntimeOptions> {\n return {\n maxLogChars:\n overrides.maxLogChars ?? options.maxLogChars ?? DEFAULT_MAX_LOG_CHARS,\n maxLogLines:\n overrides.maxLogLines ?? options.maxLogLines ?? DEFAULT_MAX_LOG_LINES,\n memoryLimitBytes:\n overrides.memoryLimitBytes ??\n options.memoryLimitBytes ??\n DEFAULT_MEMORY_LIMIT_BYTES,\n timeoutMs: overrides.timeoutMs ?? options.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n };\n}\n\nfunction createWorkerTransport(worker: Worker): HostTransport {\n return {\n dispose: async () => {\n await worker.terminate().catch(() => {});\n },\n onClose: (handler) => {\n const wrapped = (code: number) => {\n handler({\n code,\n message: `Worker exited unexpectedly with code ${code}`,\n });\n };\n worker.on(\"exit\", wrapped);\n return () => worker.off(\"exit\", wrapped);\n },\n onError: (handler) => {\n worker.on(\"error\", handler);\n return () => worker.off(\"error\", handler);\n },\n onMessage: (handler) => {\n const wrapped = (message: unknown) => {\n handler(message as RunnerMessage);\n };\n worker.on(\"message\", wrapped);\n return () => worker.off(\"message\", wrapped);\n },\n send: (message) => {\n worker.postMessage(message);\n },\n terminate: async () => {\n await worker.terminate().catch(() => {});\n },\n };\n}\n\n/**\n * Worker-thread executor that runs guest code inside a dedicated QuickJS runtime per call.\n */\nexport class WorkerExecutor implements Executor {\n private readonly cancelGraceMs: number;\n private readonly options: WorkerExecutorOptions;\n\n /**\n * Creates a worker-backed executor with hard-stop timeout behavior.\n */\n constructor(options: WorkerExecutorOptions = {}) {\n this.cancelGraceMs = options.cancelGraceMs ?? DEFAULT_CANCEL_GRACE_MS;\n this.options = options;\n }\n\n /**\n * Executes JavaScript inside a fresh worker thread running QuickJS.\n */\n async execute(\n code: string,\n providers: ResolvedToolProvider[],\n options: ExecutionOptions = {},\n ): Promise<ExecuteResult> {\n if (options.signal?.aborted) {\n return createTimeoutExecuteResult();\n }\n\n const worker = new Worker(resolveWorkerEntryUrl(), {\n execArgv: getNodeTransportExecArgv(import.meta.url),\n resourceLimits: this.options.workerResourceLimits,\n });\n\n return await runHostTransportSession({\n cancelGraceMs: this.cancelGraceMs,\n code,\n executionId: randomUUID(),\n providers,\n runtimeOptions: createRuntimeOptions(this.options, options),\n signal: options.signal,\n transport: createWorkerTransport(worker),\n });\n }\n}\n"],"mappings":";;;;;;AAoBA,MAAM,0BAA0B;AAChC,MAAM,wBAAwB;AAC9B,MAAM,wBAAwB;AAC9B,MAAM,6BAA6B,KAAK,OAAO;AAC/C,MAAM,qBAAqB;AAE3B,SAAS,wBAA6B;CACpC,MAAM,YAAY,OAAO,KAAK,IAAI,SAAS,MAAM,GAAG,QAAQ;AAC5D,QAAO,IAAI,IAAI,gBAAgB,aAAa,OAAO,KAAK,IAAI;;AAG9D,SAAS,qBACP,SACA,YAA8B,EAAE,EACE;AAClC,QAAO;EACL,aACE,UAAU,eAAe,QAAQ,eAAe;EAClD,aACE,UAAU,eAAe,QAAQ,eAAe;EAClD,kBACE,UAAU,oBACV,QAAQ,oBACR;EACF,WAAW,UAAU,aAAa,QAAQ,aAAa;EACxD;;AAGH,SAAS,sBAAsB,QAA+B;AAC5D,QAAO;EACL,SAAS,YAAY;AACnB,SAAM,OAAO,WAAW,CAAC,YAAY,GAAG;;EAE1C,UAAU,YAAY;GACpB,MAAM,WAAW,SAAiB;AAChC,YAAQ;KACN;KACA,SAAS,wCAAwC;KAClD,CAAC;;AAEJ,UAAO,GAAG,QAAQ,QAAQ;AAC1B,gBAAa,OAAO,IAAI,QAAQ,QAAQ;;EAE1C,UAAU,YAAY;AACpB,UAAO,GAAG,SAAS,QAAQ;AAC3B,gBAAa,OAAO,IAAI,SAAS,QAAQ;;EAE3C,YAAY,YAAY;GACtB,MAAM,WAAW,YAAqB;AACpC,YAAQ,QAAyB;;AAEnC,UAAO,GAAG,WAAW,QAAQ;AAC7B,gBAAa,OAAO,IAAI,WAAW,QAAQ;;EAE7C,OAAO,YAAY;AACjB,UAAO,YAAY,QAAQ;;EAE7B,WAAW,YAAY;AACrB,SAAM,OAAO,WAAW,CAAC,YAAY,GAAG;;EAE3C;;;;;AAMH,IAAa,iBAAb,MAAgD;CAC9C,AAAiB;CACjB,AAAiB;;;;CAKjB,YAAY,UAAiC,EAAE,EAAE;AAC/C,OAAK,gBAAgB,QAAQ,iBAAiB;AAC9C,OAAK,UAAU;;;;;CAMjB,MAAM,QACJ,MACA,WACA,UAA4B,EAAE,EACN;AACxB,MAAI,QAAQ,QAAQ,QAClB,QAAO,4BAA4B;EAGrC,MAAM,SAAS,IAAI,OAAO,uBAAuB,EAAE;GACjD,UAAU,yBAAyB,OAAO,KAAK,IAAI;GACnD,gBAAgB,KAAK,QAAQ;GAC9B,CAAC;AAEF,SAAO,MAAM,wBAAwB;GACnC,eAAe,KAAK;GACpB;GACA,aAAa,YAAY;GACzB;GACA,gBAAgB,qBAAqB,KAAK,SAAS,QAAQ;GAC3D,QAAQ,QAAQ;GAChB,WAAW,sBAAsB,OAAO;GACzC,CAAC"}
@@ -0,0 +1,18 @@
1
+ let node_worker_threads = require("node:worker_threads");
2
+ let __mcploom_codexec_quickjs_runner_protocol_endpoint = require("@mcploom/codexec-quickjs/runner/protocol-endpoint");
3
+
4
+ //#region src/workerEntry.ts
5
+ if (!node_worker_threads.parentPort) throw new Error("WorkerExecutor requires a worker parent port");
6
+ const workerPort = node_worker_threads.parentPort;
7
+ (0, __mcploom_codexec_quickjs_runner_protocol_endpoint.attachQuickJsProtocolEndpoint)({
8
+ onMessage(handler) {
9
+ workerPort.on("message", handler);
10
+ return () => workerPort.off("message", handler);
11
+ },
12
+ send(message) {
13
+ workerPort.postMessage(message);
14
+ }
15
+ });
16
+
17
+ //#endregion
18
+ //# sourceMappingURL=workerEntry.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workerEntry.cjs","names":["parentPort"],"sources":["../src/workerEntry.ts"],"sourcesContent":["import { parentPort } from \"node:worker_threads\";\n\nimport { attachQuickJsProtocolEndpoint } from \"@mcploom/codexec-quickjs/runner/protocol-endpoint\";\nimport type { DispatcherMessage, RunnerMessage } from \"@mcploom/codexec-protocol\";\n\nif (!parentPort) {\n throw new Error(\"WorkerExecutor requires a worker parent port\");\n}\n\nconst workerPort = parentPort;\n\nattachQuickJsProtocolEndpoint({\n onMessage(handler: (message: DispatcherMessage) => void): () => void {\n workerPort.on(\"message\", handler);\n return () => workerPort.off(\"message\", handler);\n },\n send(message: RunnerMessage): void {\n workerPort.postMessage(message);\n },\n});\n"],"mappings":";;;;AAKA,IAAI,CAACA,+BACH,OAAM,IAAI,MAAM,+CAA+C;AAGjE,MAAM,aAAaA;sFAEW;CAC5B,UAAU,SAA2D;AACnE,aAAW,GAAG,WAAW,QAAQ;AACjC,eAAa,WAAW,IAAI,WAAW,QAAQ;;CAEjD,KAAK,SAA8B;AACjC,aAAW,YAAY,QAAQ;;CAElC,CAAC"}
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,19 @@
1
+ import { parentPort } from "node:worker_threads";
2
+ import { attachQuickJsProtocolEndpoint } from "@mcploom/codexec-quickjs/runner/protocol-endpoint";
3
+
4
+ //#region src/workerEntry.ts
5
+ if (!parentPort) throw new Error("WorkerExecutor requires a worker parent port");
6
+ const workerPort = parentPort;
7
+ attachQuickJsProtocolEndpoint({
8
+ onMessage(handler) {
9
+ workerPort.on("message", handler);
10
+ return () => workerPort.off("message", handler);
11
+ },
12
+ send(message) {
13
+ workerPort.postMessage(message);
14
+ }
15
+ });
16
+
17
+ //#endregion
18
+ export { };
19
+ //# sourceMappingURL=workerEntry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workerEntry.js","names":[],"sources":["../src/workerEntry.ts"],"sourcesContent":["import { parentPort } from \"node:worker_threads\";\n\nimport { attachQuickJsProtocolEndpoint } from \"@mcploom/codexec-quickjs/runner/protocol-endpoint\";\nimport type { DispatcherMessage, RunnerMessage } from \"@mcploom/codexec-protocol\";\n\nif (!parentPort) {\n throw new Error(\"WorkerExecutor requires a worker parent port\");\n}\n\nconst workerPort = parentPort;\n\nattachQuickJsProtocolEndpoint({\n onMessage(handler: (message: DispatcherMessage) => void): () => void {\n workerPort.on(\"message\", handler);\n return () => workerPort.off(\"message\", handler);\n },\n send(message: RunnerMessage): void {\n workerPort.postMessage(message);\n },\n});\n"],"mappings":";;;;AAKA,IAAI,CAAC,WACH,OAAM,IAAI,MAAM,+CAA+C;AAGjE,MAAM,aAAa;AAEnB,8BAA8B;CAC5B,UAAU,SAA2D;AACnE,aAAW,GAAG,WAAW,QAAQ;AACjC,eAAa,WAAW,IAAI,WAAW,QAAQ;;CAEjD,KAAK,SAA8B;AACjC,aAAW,YAAY,QAAQ;;CAElC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@mcploom/codexec-worker",
3
+ "version": "0.1.1",
4
+ "description": "Worker thread executor for the mcploom codexec core package.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "engines": {
8
+ "node": ">=22"
9
+ },
10
+ "main": "./dist/index.cjs",
11
+ "module": "./dist/index.js",
12
+ "types": "./dist/index.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js",
17
+ "require": "./dist/index.cjs"
18
+ }
19
+ },
20
+ "sideEffects": false,
21
+ "files": [
22
+ "dist",
23
+ "README.md",
24
+ "LICENSE"
25
+ ],
26
+ "scripts": {
27
+ "build": "tsdown"
28
+ },
29
+ "keywords": [
30
+ "mcp",
31
+ "model-context-protocol",
32
+ "worker-threads",
33
+ "quickjs",
34
+ "code-execution"
35
+ ],
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "git+https://github.com/aallam/mcploom.git",
39
+ "directory": "packages/codexec-worker"
40
+ },
41
+ "homepage": "https://github.com/aallam/mcploom/tree/main/packages/codexec-worker#readme",
42
+ "bugs": "https://github.com/aallam/mcploom/issues",
43
+ "dependencies": {
44
+ "@mcploom/codexec": "^0.3.0",
45
+ "@mcploom/codexec-protocol": "^0.1.1",
46
+ "@mcploom/codexec-quickjs": "^0.2.0"
47
+ }
48
+ }