@mcploom/codexec-remote 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/LICENSE +21 -0
- package/README.md +62 -0
- package/dist/index.cjs +101 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +52 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.ts +52 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +100 -0
- package/dist/index.js.map +1 -0
- package/package.json +48 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mouaad Aallam
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# @mcploom/codexec-remote
|
|
2
|
+
|
|
3
|
+
Transport-backed remote executor for `@mcploom/codexec`.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@mcploom/codexec-remote)
|
|
6
|
+
[](https://github.com/aallam/mcploom/blob/main/LICENSE)
|
|
7
|
+
|
|
8
|
+
## Choose `codexec-remote` When
|
|
9
|
+
|
|
10
|
+
- you want codexec execution to live outside the application process
|
|
11
|
+
- you already own the transport and runtime deployment shape
|
|
12
|
+
- you want to keep the same `Executor` API while swapping in a stronger boundary
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @mcploom/codexec @mcploom/codexec-remote
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { resolveProvider } from "@mcploom/codexec";
|
|
24
|
+
import { RemoteExecutor, attachQuickJsRemoteEndpoint } from "@mcploom/codexec-remote";
|
|
25
|
+
|
|
26
|
+
const provider = resolveProvider({
|
|
27
|
+
name: "tools",
|
|
28
|
+
tools: {
|
|
29
|
+
echo: {
|
|
30
|
+
execute: async (input) => input,
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const executor = new RemoteExecutor({
|
|
36
|
+
connectTransport: async () => myHostTransport,
|
|
37
|
+
timeoutMs: 1000,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const result = await executor.execute(
|
|
41
|
+
"await tools.echo({ ok: true })",
|
|
42
|
+
[provider],
|
|
43
|
+
{ timeoutMs: 250 },
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
attachQuickJsRemoteEndpoint(myRunnerPort);
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
`RemoteExecutor` stays transport-agnostic. Your application owns the network stack and provides a fresh `HostTransport` per execution. `attachQuickJsRemoteEndpoint()` binds the shared QuickJS runner protocol to an app-provided remote port on the runner side.
|
|
50
|
+
|
|
51
|
+
## Security Notes
|
|
52
|
+
|
|
53
|
+
- This package improves the process boundary by moving execution behind a caller-supplied transport.
|
|
54
|
+
- It is still not a hard security boundary by itself. Your actual trust boundary depends on the remote runtime you deploy.
|
|
55
|
+
- Providers remain the capability boundary.
|
|
56
|
+
- The package is intentionally small: it does not create servers, own authentication, or prescribe an HTTP/WebSocket framework.
|
|
57
|
+
|
|
58
|
+
## Examples
|
|
59
|
+
|
|
60
|
+
- [Remote codexec execution](https://github.com/aallam/mcploom/blob/main/examples/codexec-remote.ts)
|
|
61
|
+
- [Codexec architecture overview](https://github.com/aallam/mcploom/blob/main/docs/codexec/architecture/README.md)
|
|
62
|
+
- [Codexec MCP adapters and protocol](https://github.com/aallam/mcploom/blob/main/docs/codexec/architecture/codexec-mcp-and-protocol.md)
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
let node_crypto = require("node:crypto");
|
|
2
|
+
let __mcploom_codexec_protocol = require("@mcploom/codexec-protocol");
|
|
3
|
+
let __mcploom_codexec = require("@mcploom/codexec");
|
|
4
|
+
let __mcploom_codexec_quickjs_runner_protocol_endpoint = require("@mcploom/codexec-quickjs/runner/protocol-endpoint");
|
|
5
|
+
|
|
6
|
+
//#region src/remoteExecutor.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 createRuntimeOptions(options, overrides = {}) {
|
|
13
|
+
return {
|
|
14
|
+
maxLogChars: overrides.maxLogChars ?? options.maxLogChars ?? DEFAULT_MAX_LOG_CHARS,
|
|
15
|
+
maxLogLines: overrides.maxLogLines ?? options.maxLogLines ?? DEFAULT_MAX_LOG_LINES,
|
|
16
|
+
memoryLimitBytes: overrides.memoryLimitBytes ?? options.memoryLimitBytes ?? DEFAULT_MEMORY_LIMIT_BYTES,
|
|
17
|
+
timeoutMs: overrides.timeoutMs ?? options.timeoutMs ?? DEFAULT_TIMEOUT_MS
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Transport-backed executor that runs guest code outside the host process.
|
|
22
|
+
*/
|
|
23
|
+
var RemoteExecutor = class {
|
|
24
|
+
cancelGraceMs;
|
|
25
|
+
options;
|
|
26
|
+
/**
|
|
27
|
+
* Creates a transport-backed executor with caller-supplied remote connectivity.
|
|
28
|
+
*/
|
|
29
|
+
constructor(options) {
|
|
30
|
+
this.cancelGraceMs = options.cancelGraceMs ?? DEFAULT_CANCEL_GRACE_MS;
|
|
31
|
+
this.options = options;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Executes JavaScript against the provided tool namespaces over a remote transport.
|
|
35
|
+
*/
|
|
36
|
+
async execute(code, providers, options = {}) {
|
|
37
|
+
if (options.signal?.aborted) return (0, __mcploom_codexec.createTimeoutExecuteResult)();
|
|
38
|
+
let transport;
|
|
39
|
+
try {
|
|
40
|
+
transport = await this.options.connectTransport();
|
|
41
|
+
} catch (error) {
|
|
42
|
+
return {
|
|
43
|
+
durationMs: 0,
|
|
44
|
+
error: {
|
|
45
|
+
code: "internal_error",
|
|
46
|
+
message: error instanceof Error ? error.message : String(error)
|
|
47
|
+
},
|
|
48
|
+
logs: [],
|
|
49
|
+
ok: false
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
return await (0, __mcploom_codexec_protocol.runHostTransportSession)({
|
|
53
|
+
cancelGraceMs: this.cancelGraceMs,
|
|
54
|
+
code,
|
|
55
|
+
executionId: (0, node_crypto.randomUUID)(),
|
|
56
|
+
providers,
|
|
57
|
+
runtimeOptions: createRuntimeOptions(this.options, options),
|
|
58
|
+
signal: options.signal,
|
|
59
|
+
transport
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
//#endregion
|
|
65
|
+
//#region src/runnerEndpoint.ts
|
|
66
|
+
/**
|
|
67
|
+
* Attaches the shared QuickJS protocol endpoint to a remote runner transport
|
|
68
|
+
* and tears it down automatically when the transport closes or errors.
|
|
69
|
+
*/
|
|
70
|
+
function attachQuickJsRemoteEndpoint(port) {
|
|
71
|
+
const detachProtocol = (0, __mcploom_codexec_quickjs_runner_protocol_endpoint.attachQuickJsProtocolEndpoint)({
|
|
72
|
+
onMessage(handler) {
|
|
73
|
+
const maybeDetach = port.onMessage((message) => {
|
|
74
|
+
handler(message);
|
|
75
|
+
});
|
|
76
|
+
return () => {
|
|
77
|
+
if (typeof maybeDetach === "function") maybeDetach();
|
|
78
|
+
};
|
|
79
|
+
},
|
|
80
|
+
send(message) {
|
|
81
|
+
Promise.resolve(port.send(message)).catch(() => {});
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
const offClose = port.onClose?.(() => {
|
|
85
|
+
cleanup();
|
|
86
|
+
});
|
|
87
|
+
const offError = port.onError?.(() => {
|
|
88
|
+
cleanup();
|
|
89
|
+
});
|
|
90
|
+
function cleanup() {
|
|
91
|
+
if (typeof offClose === "function") offClose();
|
|
92
|
+
if (typeof offError === "function") offError();
|
|
93
|
+
detachProtocol();
|
|
94
|
+
}
|
|
95
|
+
return cleanup;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
//#endregion
|
|
99
|
+
exports.RemoteExecutor = RemoteExecutor;
|
|
100
|
+
exports.attachQuickJsRemoteEndpoint = attachQuickJsRemoteEndpoint;
|
|
101
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["transport: HostTransport"],"sources":["../src/remoteExecutor.ts","../src/runnerEndpoint.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\n\nimport {\n runHostTransportSession,\n type HostTransport,\n type ExecutorRuntimeOptions,\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 { RemoteExecutorOptions } 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 createRuntimeOptions(\n options: RemoteExecutorOptions,\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\n/**\n * Transport-backed executor that runs guest code outside the host process.\n */\nexport class RemoteExecutor implements Executor {\n private readonly cancelGraceMs: number;\n private readonly options: RemoteExecutorOptions;\n\n /**\n * Creates a transport-backed executor with caller-supplied remote connectivity.\n */\n constructor(options: RemoteExecutorOptions) {\n this.cancelGraceMs = options.cancelGraceMs ?? DEFAULT_CANCEL_GRACE_MS;\n this.options = options;\n }\n\n /**\n * Executes JavaScript against the provided tool namespaces over a remote transport.\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 let transport: HostTransport;\n\n try {\n transport = await this.options.connectTransport();\n } catch (error) {\n return {\n durationMs: 0,\n error: {\n code: \"internal_error\",\n message: error instanceof Error ? error.message : String(error),\n },\n logs: [],\n ok: false,\n };\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,\n });\n }\n}\n","import { attachQuickJsProtocolEndpoint } from \"@mcploom/codexec-quickjs/runner/protocol-endpoint\";\nimport type {\n DispatcherMessage,\n RunnerMessage,\n} from \"@mcploom/codexec-protocol\";\n\nimport type { RemoteRunnerPort } from \"./types\";\n\n/**\n * Attaches the shared QuickJS protocol endpoint to a remote runner transport\n * and tears it down automatically when the transport closes or errors.\n */\nexport function attachQuickJsRemoteEndpoint(port: RemoteRunnerPort): () => void {\n const detachProtocol = attachQuickJsProtocolEndpoint({\n onMessage(handler: (message: DispatcherMessage) => void): () => void {\n const maybeDetach = port.onMessage((message: unknown) => {\n handler(message as DispatcherMessage);\n });\n\n return () => {\n if (typeof maybeDetach === \"function\") {\n maybeDetach();\n }\n };\n },\n send(message: RunnerMessage): void {\n void Promise.resolve(port.send(message)).catch(() => {});\n },\n });\n\n const offClose = port.onClose?.(() => {\n cleanup();\n });\n const offError = port.onError?.(() => {\n cleanup();\n });\n\n function cleanup(): void {\n if (typeof offClose === \"function\") {\n offClose();\n }\n if (typeof offError === \"function\") {\n offError();\n }\n detachProtocol();\n }\n\n return cleanup;\n}\n"],"mappings":";;;;;;AAiBA,MAAM,0BAA0B;AAChC,MAAM,wBAAwB;AAC9B,MAAM,wBAAwB;AAC9B,MAAM,6BAA6B,KAAK,OAAO;AAC/C,MAAM,qBAAqB;AAE3B,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;;;;;AAMH,IAAa,iBAAb,MAAgD;CAC9C,AAAiB;CACjB,AAAiB;;;;CAKjB,YAAY,SAAgC;AAC1C,OAAK,gBAAgB,QAAQ,iBAAiB;AAC9C,OAAK,UAAU;;;;;CAMjB,MAAM,QACJ,MACA,WACA,UAA4B,EAAE,EACN;AACxB,MAAI,QAAQ,QAAQ,QAClB,2DAAmC;EAGrC,IAAIA;AAEJ,MAAI;AACF,eAAY,MAAM,KAAK,QAAQ,kBAAkB;WAC1C,OAAO;AACd,UAAO;IACL,YAAY;IACZ,OAAO;KACL,MAAM;KACN,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;KAChE;IACD,MAAM,EAAE;IACR,IAAI;IACL;;AAGH,SAAO,8DAA8B;GACnC,eAAe,KAAK;GACpB;GACA,0CAAyB;GACzB;GACA,gBAAgB,qBAAqB,KAAK,SAAS,QAAQ;GAC3D,QAAQ,QAAQ;GAChB;GACD,CAAC;;;;;;;;;;AC/EN,SAAgB,4BAA4B,MAAoC;CAC9E,MAAM,uGAA+C;EACnD,UAAU,SAA2D;GACnE,MAAM,cAAc,KAAK,WAAW,YAAqB;AACvD,YAAQ,QAA6B;KACrC;AAEF,gBAAa;AACX,QAAI,OAAO,gBAAgB,WACzB,cAAa;;;EAInB,KAAK,SAA8B;AACjC,GAAK,QAAQ,QAAQ,KAAK,KAAK,QAAQ,CAAC,CAAC,YAAY,GAAG;;EAE3D,CAAC;CAEF,MAAM,WAAW,KAAK,gBAAgB;AACpC,WAAS;GACT;CACF,MAAM,WAAW,KAAK,gBAAgB;AACpC,WAAS;GACT;CAEF,SAAS,UAAgB;AACvB,MAAI,OAAO,aAAa,WACtB,WAAU;AAEZ,MAAI,OAAO,aAAa,WACtB,WAAU;AAEZ,kBAAgB;;AAGlB,QAAO"}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { ExecuteResult, ExecutionOptions, Executor, ExecutorRuntimeOptions, ResolvedToolProvider } from "@mcploom/codexec";
|
|
2
|
+
import { HostTransport, TransportCloseReason } from "@mcploom/codexec-protocol";
|
|
3
|
+
|
|
4
|
+
//#region src/types.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Factory that creates a fresh transport connection for one remote execution.
|
|
8
|
+
*/
|
|
9
|
+
type RemoteTransportFactory = () => HostTransport | Promise<HostTransport>;
|
|
10
|
+
/**
|
|
11
|
+
* Minimal runner-side port for transport-backed QuickJS execution.
|
|
12
|
+
*/
|
|
13
|
+
interface RemoteRunnerPort {
|
|
14
|
+
onClose?(handler: (reason?: TransportCloseReason) => void): void | (() => void);
|
|
15
|
+
onError?(handler: (error: Error) => void): void | (() => void);
|
|
16
|
+
onMessage(handler: (message: unknown) => void): void | (() => void);
|
|
17
|
+
send(message: unknown): void | Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Options for constructing a {@link RemoteExecutor}.
|
|
21
|
+
*/
|
|
22
|
+
interface RemoteExecutorOptions extends ExecutorRuntimeOptions {
|
|
23
|
+
cancelGraceMs?: number;
|
|
24
|
+
connectTransport: RemoteTransportFactory;
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/remoteExecutor.d.ts
|
|
28
|
+
/**
|
|
29
|
+
* Transport-backed executor that runs guest code outside the host process.
|
|
30
|
+
*/
|
|
31
|
+
declare class RemoteExecutor implements Executor {
|
|
32
|
+
private readonly cancelGraceMs;
|
|
33
|
+
private readonly options;
|
|
34
|
+
/**
|
|
35
|
+
* Creates a transport-backed executor with caller-supplied remote connectivity.
|
|
36
|
+
*/
|
|
37
|
+
constructor(options: RemoteExecutorOptions);
|
|
38
|
+
/**
|
|
39
|
+
* Executes JavaScript against the provided tool namespaces over a remote transport.
|
|
40
|
+
*/
|
|
41
|
+
execute(code: string, providers: ResolvedToolProvider[], options?: ExecutionOptions): Promise<ExecuteResult>;
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
44
|
+
//#region src/runnerEndpoint.d.ts
|
|
45
|
+
/**
|
|
46
|
+
* Attaches the shared QuickJS protocol endpoint to a remote runner transport
|
|
47
|
+
* and tears it down automatically when the transport closes or errors.
|
|
48
|
+
*/
|
|
49
|
+
declare function attachQuickJsRemoteEndpoint(port: RemoteRunnerPort): () => void;
|
|
50
|
+
//#endregion
|
|
51
|
+
export { RemoteExecutor, type RemoteExecutorOptions, type RemoteRunnerPort, type RemoteTransportFactory, attachQuickJsRemoteEndpoint };
|
|
52
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/remoteExecutor.ts","../src/runnerEndpoint.ts"],"sourcesContent":[],"mappings":";;;;;;;AAMA;AACI,KADQ,sBAAA,GACR,GAAA,GAAA,aAAA,GACA,OADA,CACQ,aADR,CAAA;;;;AAMa,UAAA,gBAAA,CAAgB;EACH,OAAA,EAAA,OAAA,EAAA,CAAA,MAAA,CAAA,EAAA,oBAAA,EAAA,GAAA,IAAA,CAAA,EAAA,IAAA,GAAA,CAAA,GAAA,GAAA,IAAA,CAAA;EACF,OAAA,EAAA,OAAA,EAAA,CAAA,KAAA,EAAA,KAAA,EAAA,GAAA,IAAA,CAAA,EAAA,IAAA,GAAA,CAAA,GAAA,GAAA,IAAA,CAAA;EAEK,SAAA,CAAA,OAAA,EAAA,CAAA,OAAA,EAAA,OAAA,EAAA,GAAA,IAAA,CAAA,EAAA,IAAA,GAAA,CAAA,GAAA,GAAA,IAAA,CAAA;EAAO,IAAA,CAAA,OAAA,EAAA,OAAA,CAAA,EAAA,IAAA,GAAP,OAAO,CAAA,IAAA,CAAA;AAMxC;;;;ACoBa,UDpBI,qBAAA,SAA8B,sBCoBnB,CAAA;EAOL,aAAA,CAAA,EAAA,MAAA;EAUR,gBAAA,EDnCK,sBCmCL;;;;;;ADtDf;AACI,cCoCS,cAAA,YAA0B,QDpCnC,CAAA;EACQ,iBAAA,aAAA;EAAR,iBAAA,OAAA;EAAO;AAKX;;EAE4B,WAAA,CAAA,OAAA,ECmCL,qBDnCK;EAEK;;AAMjC;mCCqCe,kCACF,mBACR,QAAQ;;;;;;;ADxDb;AACI,iBEKY,2BAAA,CFLZ,IAAA,EEK8C,gBFL9C,CAAA,EAAA,GAAA,GAAA,IAAA"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { HostTransport, TransportCloseReason } from "@mcploom/codexec-protocol";
|
|
2
|
+
import { ExecuteResult, ExecutionOptions, Executor, ExecutorRuntimeOptions, ResolvedToolProvider } from "@mcploom/codexec";
|
|
3
|
+
|
|
4
|
+
//#region src/types.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Factory that creates a fresh transport connection for one remote execution.
|
|
8
|
+
*/
|
|
9
|
+
type RemoteTransportFactory = () => HostTransport | Promise<HostTransport>;
|
|
10
|
+
/**
|
|
11
|
+
* Minimal runner-side port for transport-backed QuickJS execution.
|
|
12
|
+
*/
|
|
13
|
+
interface RemoteRunnerPort {
|
|
14
|
+
onClose?(handler: (reason?: TransportCloseReason) => void): void | (() => void);
|
|
15
|
+
onError?(handler: (error: Error) => void): void | (() => void);
|
|
16
|
+
onMessage(handler: (message: unknown) => void): void | (() => void);
|
|
17
|
+
send(message: unknown): void | Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Options for constructing a {@link RemoteExecutor}.
|
|
21
|
+
*/
|
|
22
|
+
interface RemoteExecutorOptions extends ExecutorRuntimeOptions {
|
|
23
|
+
cancelGraceMs?: number;
|
|
24
|
+
connectTransport: RemoteTransportFactory;
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/remoteExecutor.d.ts
|
|
28
|
+
/**
|
|
29
|
+
* Transport-backed executor that runs guest code outside the host process.
|
|
30
|
+
*/
|
|
31
|
+
declare class RemoteExecutor implements Executor {
|
|
32
|
+
private readonly cancelGraceMs;
|
|
33
|
+
private readonly options;
|
|
34
|
+
/**
|
|
35
|
+
* Creates a transport-backed executor with caller-supplied remote connectivity.
|
|
36
|
+
*/
|
|
37
|
+
constructor(options: RemoteExecutorOptions);
|
|
38
|
+
/**
|
|
39
|
+
* Executes JavaScript against the provided tool namespaces over a remote transport.
|
|
40
|
+
*/
|
|
41
|
+
execute(code: string, providers: ResolvedToolProvider[], options?: ExecutionOptions): Promise<ExecuteResult>;
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
44
|
+
//#region src/runnerEndpoint.d.ts
|
|
45
|
+
/**
|
|
46
|
+
* Attaches the shared QuickJS protocol endpoint to a remote runner transport
|
|
47
|
+
* and tears it down automatically when the transport closes or errors.
|
|
48
|
+
*/
|
|
49
|
+
declare function attachQuickJsRemoteEndpoint(port: RemoteRunnerPort): () => void;
|
|
50
|
+
//#endregion
|
|
51
|
+
export { RemoteExecutor, type RemoteExecutorOptions, type RemoteRunnerPort, type RemoteTransportFactory, attachQuickJsRemoteEndpoint };
|
|
52
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/remoteExecutor.ts","../src/runnerEndpoint.ts"],"sourcesContent":[],"mappings":";;;;;;;AAMA;AACI,KADQ,sBAAA,GACR,GAAA,GAAA,aAAA,GACA,OADA,CACQ,aADR,CAAA;;;;AAMa,UAAA,gBAAA,CAAgB;EACH,OAAA,EAAA,OAAA,EAAA,CAAA,MAAA,CAAA,EAAA,oBAAA,EAAA,GAAA,IAAA,CAAA,EAAA,IAAA,GAAA,CAAA,GAAA,GAAA,IAAA,CAAA;EACF,OAAA,EAAA,OAAA,EAAA,CAAA,KAAA,EAAA,KAAA,EAAA,GAAA,IAAA,CAAA,EAAA,IAAA,GAAA,CAAA,GAAA,GAAA,IAAA,CAAA;EAEK,SAAA,CAAA,OAAA,EAAA,CAAA,OAAA,EAAA,OAAA,EAAA,GAAA,IAAA,CAAA,EAAA,IAAA,GAAA,CAAA,GAAA,GAAA,IAAA,CAAA;EAAO,IAAA,CAAA,OAAA,EAAA,OAAA,CAAA,EAAA,IAAA,GAAP,OAAO,CAAA,IAAA,CAAA;AAMxC;;;;ACoBa,UDpBI,qBAAA,SAA8B,sBCoBnB,CAAA;EAOL,aAAA,CAAA,EAAA,MAAA;EAUR,gBAAA,EDnCK,sBCmCL;;;;;;ADtDf;AACI,cCoCS,cAAA,YAA0B,QDpCnC,CAAA;EACQ,iBAAA,aAAA;EAAR,iBAAA,OAAA;EAAO;AAKX;;EAE4B,WAAA,CAAA,OAAA,ECmCL,qBDnCK;EAEK;;AAMjC;mCCqCe,kCACF,mBACR,QAAQ;;;;;;;ADxDb;AACI,iBEKY,2BAAA,CFLZ,IAAA,EEK8C,gBFL9C,CAAA,EAAA,GAAA,GAAA,IAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { runHostTransportSession } from "@mcploom/codexec-protocol";
|
|
3
|
+
import { createTimeoutExecuteResult } from "@mcploom/codexec";
|
|
4
|
+
import { attachQuickJsProtocolEndpoint } from "@mcploom/codexec-quickjs/runner/protocol-endpoint";
|
|
5
|
+
|
|
6
|
+
//#region src/remoteExecutor.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 createRuntimeOptions(options, overrides = {}) {
|
|
13
|
+
return {
|
|
14
|
+
maxLogChars: overrides.maxLogChars ?? options.maxLogChars ?? DEFAULT_MAX_LOG_CHARS,
|
|
15
|
+
maxLogLines: overrides.maxLogLines ?? options.maxLogLines ?? DEFAULT_MAX_LOG_LINES,
|
|
16
|
+
memoryLimitBytes: overrides.memoryLimitBytes ?? options.memoryLimitBytes ?? DEFAULT_MEMORY_LIMIT_BYTES,
|
|
17
|
+
timeoutMs: overrides.timeoutMs ?? options.timeoutMs ?? DEFAULT_TIMEOUT_MS
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Transport-backed executor that runs guest code outside the host process.
|
|
22
|
+
*/
|
|
23
|
+
var RemoteExecutor = class {
|
|
24
|
+
cancelGraceMs;
|
|
25
|
+
options;
|
|
26
|
+
/**
|
|
27
|
+
* Creates a transport-backed executor with caller-supplied remote connectivity.
|
|
28
|
+
*/
|
|
29
|
+
constructor(options) {
|
|
30
|
+
this.cancelGraceMs = options.cancelGraceMs ?? DEFAULT_CANCEL_GRACE_MS;
|
|
31
|
+
this.options = options;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Executes JavaScript against the provided tool namespaces over a remote transport.
|
|
35
|
+
*/
|
|
36
|
+
async execute(code, providers, options = {}) {
|
|
37
|
+
if (options.signal?.aborted) return createTimeoutExecuteResult();
|
|
38
|
+
let transport;
|
|
39
|
+
try {
|
|
40
|
+
transport = await this.options.connectTransport();
|
|
41
|
+
} catch (error) {
|
|
42
|
+
return {
|
|
43
|
+
durationMs: 0,
|
|
44
|
+
error: {
|
|
45
|
+
code: "internal_error",
|
|
46
|
+
message: error instanceof Error ? error.message : String(error)
|
|
47
|
+
},
|
|
48
|
+
logs: [],
|
|
49
|
+
ok: false
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
return await runHostTransportSession({
|
|
53
|
+
cancelGraceMs: this.cancelGraceMs,
|
|
54
|
+
code,
|
|
55
|
+
executionId: randomUUID(),
|
|
56
|
+
providers,
|
|
57
|
+
runtimeOptions: createRuntimeOptions(this.options, options),
|
|
58
|
+
signal: options.signal,
|
|
59
|
+
transport
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
//#endregion
|
|
65
|
+
//#region src/runnerEndpoint.ts
|
|
66
|
+
/**
|
|
67
|
+
* Attaches the shared QuickJS protocol endpoint to a remote runner transport
|
|
68
|
+
* and tears it down automatically when the transport closes or errors.
|
|
69
|
+
*/
|
|
70
|
+
function attachQuickJsRemoteEndpoint(port) {
|
|
71
|
+
const detachProtocol = attachQuickJsProtocolEndpoint({
|
|
72
|
+
onMessage(handler) {
|
|
73
|
+
const maybeDetach = port.onMessage((message) => {
|
|
74
|
+
handler(message);
|
|
75
|
+
});
|
|
76
|
+
return () => {
|
|
77
|
+
if (typeof maybeDetach === "function") maybeDetach();
|
|
78
|
+
};
|
|
79
|
+
},
|
|
80
|
+
send(message) {
|
|
81
|
+
Promise.resolve(port.send(message)).catch(() => {});
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
const offClose = port.onClose?.(() => {
|
|
85
|
+
cleanup();
|
|
86
|
+
});
|
|
87
|
+
const offError = port.onError?.(() => {
|
|
88
|
+
cleanup();
|
|
89
|
+
});
|
|
90
|
+
function cleanup() {
|
|
91
|
+
if (typeof offClose === "function") offClose();
|
|
92
|
+
if (typeof offError === "function") offError();
|
|
93
|
+
detachProtocol();
|
|
94
|
+
}
|
|
95
|
+
return cleanup;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
//#endregion
|
|
99
|
+
export { RemoteExecutor, attachQuickJsRemoteEndpoint };
|
|
100
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["transport: HostTransport"],"sources":["../src/remoteExecutor.ts","../src/runnerEndpoint.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\n\nimport {\n runHostTransportSession,\n type HostTransport,\n type ExecutorRuntimeOptions,\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 { RemoteExecutorOptions } 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 createRuntimeOptions(\n options: RemoteExecutorOptions,\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\n/**\n * Transport-backed executor that runs guest code outside the host process.\n */\nexport class RemoteExecutor implements Executor {\n private readonly cancelGraceMs: number;\n private readonly options: RemoteExecutorOptions;\n\n /**\n * Creates a transport-backed executor with caller-supplied remote connectivity.\n */\n constructor(options: RemoteExecutorOptions) {\n this.cancelGraceMs = options.cancelGraceMs ?? DEFAULT_CANCEL_GRACE_MS;\n this.options = options;\n }\n\n /**\n * Executes JavaScript against the provided tool namespaces over a remote transport.\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 let transport: HostTransport;\n\n try {\n transport = await this.options.connectTransport();\n } catch (error) {\n return {\n durationMs: 0,\n error: {\n code: \"internal_error\",\n message: error instanceof Error ? error.message : String(error),\n },\n logs: [],\n ok: false,\n };\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,\n });\n }\n}\n","import { attachQuickJsProtocolEndpoint } from \"@mcploom/codexec-quickjs/runner/protocol-endpoint\";\nimport type {\n DispatcherMessage,\n RunnerMessage,\n} from \"@mcploom/codexec-protocol\";\n\nimport type { RemoteRunnerPort } from \"./types\";\n\n/**\n * Attaches the shared QuickJS protocol endpoint to a remote runner transport\n * and tears it down automatically when the transport closes or errors.\n */\nexport function attachQuickJsRemoteEndpoint(port: RemoteRunnerPort): () => void {\n const detachProtocol = attachQuickJsProtocolEndpoint({\n onMessage(handler: (message: DispatcherMessage) => void): () => void {\n const maybeDetach = port.onMessage((message: unknown) => {\n handler(message as DispatcherMessage);\n });\n\n return () => {\n if (typeof maybeDetach === \"function\") {\n maybeDetach();\n }\n };\n },\n send(message: RunnerMessage): void {\n void Promise.resolve(port.send(message)).catch(() => {});\n },\n });\n\n const offClose = port.onClose?.(() => {\n cleanup();\n });\n const offError = port.onError?.(() => {\n cleanup();\n });\n\n function cleanup(): void {\n if (typeof offClose === \"function\") {\n offClose();\n }\n if (typeof offError === \"function\") {\n offError();\n }\n detachProtocol();\n }\n\n return cleanup;\n}\n"],"mappings":";;;;;;AAiBA,MAAM,0BAA0B;AAChC,MAAM,wBAAwB;AAC9B,MAAM,wBAAwB;AAC9B,MAAM,6BAA6B,KAAK,OAAO;AAC/C,MAAM,qBAAqB;AAE3B,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;;;;;AAMH,IAAa,iBAAb,MAAgD;CAC9C,AAAiB;CACjB,AAAiB;;;;CAKjB,YAAY,SAAgC;AAC1C,OAAK,gBAAgB,QAAQ,iBAAiB;AAC9C,OAAK,UAAU;;;;;CAMjB,MAAM,QACJ,MACA,WACA,UAA4B,EAAE,EACN;AACxB,MAAI,QAAQ,QAAQ,QAClB,QAAO,4BAA4B;EAGrC,IAAIA;AAEJ,MAAI;AACF,eAAY,MAAM,KAAK,QAAQ,kBAAkB;WAC1C,OAAO;AACd,UAAO;IACL,YAAY;IACZ,OAAO;KACL,MAAM;KACN,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;KAChE;IACD,MAAM,EAAE;IACR,IAAI;IACL;;AAGH,SAAO,MAAM,wBAAwB;GACnC,eAAe,KAAK;GACpB;GACA,aAAa,YAAY;GACzB;GACA,gBAAgB,qBAAqB,KAAK,SAAS,QAAQ;GAC3D,QAAQ,QAAQ;GAChB;GACD,CAAC;;;;;;;;;;AC/EN,SAAgB,4BAA4B,MAAoC;CAC9E,MAAM,iBAAiB,8BAA8B;EACnD,UAAU,SAA2D;GACnE,MAAM,cAAc,KAAK,WAAW,YAAqB;AACvD,YAAQ,QAA6B;KACrC;AAEF,gBAAa;AACX,QAAI,OAAO,gBAAgB,WACzB,cAAa;;;EAInB,KAAK,SAA8B;AACjC,GAAK,QAAQ,QAAQ,KAAK,KAAK,QAAQ,CAAC,CAAC,YAAY,GAAG;;EAE3D,CAAC;CAEF,MAAM,WAAW,KAAK,gBAAgB;AACpC,WAAS;GACT;CACF,MAAM,WAAW,KAAK,gBAAgB;AACpC,WAAS;GACT;CAEF,SAAS,UAAgB;AACvB,MAAI,OAAO,aAAa,WACtB,WAAU;AAEZ,MAAI,OAAO,aAAa,WACtB,WAAU;AAEZ,kBAAgB;;AAGlB,QAAO"}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mcploom/codexec-remote",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Transport-backed remote 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
|
+
"remote",
|
|
33
|
+
"sandbox",
|
|
34
|
+
"code-execution"
|
|
35
|
+
],
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "git+https://github.com/aallam/mcploom.git",
|
|
39
|
+
"directory": "packages/codexec-remote"
|
|
40
|
+
},
|
|
41
|
+
"homepage": "https://github.com/aallam/mcploom/tree/main/packages/codexec-remote#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
|
+
}
|