@cogitator-ai/sandbox 0.2.29 → 0.4.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/README.md +28 -2
- package/dist/executors/docker.d.ts +10 -0
- package/dist/executors/docker.d.ts.map +1 -1
- package/dist/executors/docker.js +75 -40
- package/dist/executors/docker.js.map +1 -1
- package/dist/executors/native.d.ts +3 -0
- package/dist/executors/native.d.ts.map +1 -1
- package/dist/executors/native.js +102 -36
- package/dist/executors/native.js.map +1 -1
- package/dist/executors/wasm.d.ts +11 -8
- package/dist/executors/wasm.d.ts.map +1 -1
- package/dist/executors/wasm.js +139 -89
- package/dist/executors/wasm.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/pool/container-pool.d.ts +2 -0
- package/dist/pool/container-pool.d.ts.map +1 -1
- package/dist/pool/container-pool.js +29 -4
- package/dist/pool/container-pool.js.map +1 -1
- package/dist/sandbox-manager.d.ts +2 -1
- package/dist/sandbox-manager.d.ts.map +1 -1
- package/dist/sandbox-manager.js +24 -31
- package/dist/sandbox-manager.js.map +1 -1
- package/dist/utils/output-collector.d.ts +12 -0
- package/dist/utils/output-collector.d.ts.map +1 -0
- package/dist/utils/output-collector.js +24 -0
- package/dist/utils/output-collector.js.map +1 -0
- package/dist/utils/parse-resources.d.ts +2 -1
- package/dist/utils/parse-resources.d.ts.map +1 -1
- package/dist/utils/parse-resources.js +8 -7
- package/dist/utils/parse-resources.js.map +1 -1
- package/package.json +15 -13
package/README.md
CHANGED
|
@@ -88,6 +88,12 @@ if (result.success) {
|
|
|
88
88
|
}
|
|
89
89
|
```
|
|
90
90
|
|
|
91
|
+
### Fallback and Initialization
|
|
92
|
+
|
|
93
|
+
`initialize()` is idempotent and safe to call concurrently; `execute()` calls it automatically. When the requested backend is unavailable the manager falls back (`wasm` → `docker` → `native`, `docker` → `native`) with a warning, and the manager `defaults` are applied to the fallback execution as well. The native fallback has **no isolation** — check `isDockerAvailable()` / `isWasmAvailable()` first if untrusted code must never reach the host.
|
|
94
|
+
|
|
95
|
+
When no `docker` connection options are given, Dockerode's defaults are used, so `DOCKER_HOST` is respected.
|
|
96
|
+
|
|
91
97
|
### Availability Checks
|
|
92
98
|
|
|
93
99
|
```typescript
|
|
@@ -169,9 +175,16 @@ Docker containers run with these security settings:
|
|
|
169
175
|
SecurityOpt: ['no-new-privileges'], // No privilege escalation
|
|
170
176
|
PidsLimit: 100, // Limit process count
|
|
171
177
|
ReadonlyRootfs: false, // Writable (can enable true)
|
|
178
|
+
Labels: { 'ai.cogitator.sandbox': 'true' },
|
|
172
179
|
}
|
|
173
180
|
```
|
|
174
181
|
|
|
182
|
+
- `command` is executed as an argv array (no shell); use `['sh', '-c', '...']` for shell syntax.
|
|
183
|
+
- Output is demultiplexed frame by frame (frames split across network chunks are reassembled) and capped at 50 000 bytes per stream.
|
|
184
|
+
- Timed-out containers are destroyed instead of being returned to the pool.
|
|
185
|
+
- `network.dns` is applied to new containers. `network.allowedHosts` is rejected because Docker cannot enforce an egress allow-list — use `mode: 'none'` or a dedicated network.
|
|
186
|
+
- Containers are labeled `ai.cogitator.sandbox=true` (`SANDBOX_CONTAINER_LABEL`), so leftovers from a crashed process can be removed with `docker rm -f $(docker ps -aq --filter label=ai.cogitator.sandbox)`.
|
|
187
|
+
|
|
175
188
|
---
|
|
176
189
|
|
|
177
190
|
## Container Pool
|
|
@@ -198,6 +211,8 @@ await pool.release(container);
|
|
|
198
211
|
await pool.destroyAll();
|
|
199
212
|
```
|
|
200
213
|
|
|
214
|
+
Containers are only reused for requests with identical settings (image, resources, network mode, DNS, mounts and user), so a container created with a host mount or network access is never handed to a request that asked for isolation. The idle-cleanup timer does not keep the Node.js process alive.
|
|
215
|
+
|
|
201
216
|
### Pool Options
|
|
202
217
|
|
|
203
218
|
| Option | Type | Default | Description |
|
|
@@ -209,7 +224,7 @@ await pool.destroyAll();
|
|
|
209
224
|
|
|
210
225
|
## WASM Executor
|
|
211
226
|
|
|
212
|
-
Execute WebAssembly modules via Extism.
|
|
227
|
+
Execute WebAssembly modules via Extism. Each plugin runs in its own worker thread, so a timeout terminates a runaway module instead of blocking the event loop. Idle plugins are pooled per module / WASI / allowed-host combination (up to `cacheSize`); concurrent executions use separate plugin instances.
|
|
213
228
|
|
|
214
229
|
```typescript
|
|
215
230
|
import { WasmSandboxExecutor } from '@cogitator-ai/sandbox';
|
|
@@ -240,6 +255,11 @@ const result = await wasm.execute(
|
|
|
240
255
|
await wasm.disconnect();
|
|
241
256
|
```
|
|
242
257
|
|
|
258
|
+
- Local paths, module specifiers and `http(s)` URLs are supported for `wasmModule`.
|
|
259
|
+
- `wasmModule`, `functionName` and `wasi` from the executor options are used when the per-request config omits them.
|
|
260
|
+
- `network.allowedHosts` is forwarded to Extism's HTTP allow-list (empty when `network.mode` is `'none'`).
|
|
261
|
+
- `memoryPages` (default 256 = 16 MB) is passed to Extism as `memory.maxPages`. It caps the memory Extism allocates for plugin input, output and vars; the module's own linear memory is not limited by it.
|
|
262
|
+
|
|
243
263
|
---
|
|
244
264
|
|
|
245
265
|
## Native Executor
|
|
@@ -267,6 +287,12 @@ console.log(result.data?.stdout);
|
|
|
267
287
|
|
|
268
288
|
**Warning:** Native execution has no isolation. Use only when Docker is unavailable.
|
|
269
289
|
|
|
290
|
+
- A single-element command (`['ls -la | wc -l']`) runs through the system shell; longer commands are executed directly with exact argv (no shell), like Docker.
|
|
291
|
+
- `stdin` is piped to the process.
|
|
292
|
+
- Only `PATH`, `HOME`, temp-dir, locale and Windows system variables are inherited from the host environment; secrets in `process.env` are not passed to executed code. Add variables explicitly via `env`.
|
|
293
|
+
- On timeout the whole process group is killed (`SIGKILL`) and the result is returned immediately with exit code `124`.
|
|
294
|
+
- Output is capped at 50 000 bytes per stream while the process is still drained.
|
|
295
|
+
|
|
270
296
|
---
|
|
271
297
|
|
|
272
298
|
## Execution Request
|
|
@@ -309,7 +335,7 @@ const result = await manager.execute(request, {
|
|
|
309
335
|
});
|
|
310
336
|
```
|
|
311
337
|
|
|
312
|
-
Supported formats: `'256B'`, `'256KB'`, `'256MB'`, `'
|
|
338
|
+
Supported formats: `'256B'`, `'256KB'`, `'256MB'`, `'1GB'`, `'1TB'`, Docker-style `'512m'` / `'2g'` and binary `'1GiB'` (all binary multiples, case-insensitive). Zero or negative memory and CPU limits are rejected instead of silently running unlimited.
|
|
313
339
|
|
|
314
340
|
### CPU
|
|
315
341
|
|
|
@@ -19,4 +19,14 @@ export declare class DockerSandboxExecutor extends BaseSandboxExecutor {
|
|
|
19
19
|
execute(request: SandboxExecutionRequest, config: SandboxConfig): Promise<SandboxResult<SandboxExecutionResult>>;
|
|
20
20
|
private runWithTimeout;
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Decodes Docker's multiplexed attach stream, buffering frames split across chunks.
|
|
24
|
+
*/
|
|
25
|
+
export declare class DockerStreamDemuxer {
|
|
26
|
+
private readonly onStdout;
|
|
27
|
+
private readonly onStderr;
|
|
28
|
+
private buffer;
|
|
29
|
+
constructor(onStdout: (data: Buffer) => void, onStderr: (data: Buffer) => void);
|
|
30
|
+
push(chunk: Buffer): void;
|
|
31
|
+
}
|
|
22
32
|
//# sourceMappingURL=docker.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docker.d.ts","sourceRoot":"","sources":["../../src/executors/docker.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,uBAAuB,EACvB,sBAAsB,EACtB,aAAa,EACb,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"docker.d.ts","sourceRoot":"","sources":["../../src/executors/docker.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,uBAAuB,EACvB,sBAAsB,EACtB,aAAa,EACb,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AAM7C,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,IAAI,CAAC,EAAE,iBAAiB,CAAC;CAC1B;AAMD,qBAAa,qBAAsB,SAAQ,mBAAmB;IAC5D,QAAQ,CAAC,IAAI,YAAY;IACzB,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,IAAI,CAAC,CAAgB;IAC7B,OAAO,CAAC,OAAO,CAAwB;gBAE3B,OAAO,GAAE,qBAA0B;IAKzC,OAAO,IAAI,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IA2BvC,UAAU,IAAI,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAS1C,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAU/B,OAAO,CACX,OAAO,EAAE,uBAAuB,EAChC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,aAAa,CAAC,sBAAsB,CAAC,CAAC;YA6EnC,cAAc;CAgF7B;AAED;;GAEG;AACH,qBAAa,mBAAmB;IAI5B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAJ3B,OAAO,CAAC,MAAM,CAA2B;gBAGtB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAChC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI;IAGnD,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;CAe1B"}
|
package/dist/executors/docker.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { BaseSandboxExecutor } from './base.js';
|
|
5
5
|
import { ContainerPool } from '../pool/container-pool.js';
|
|
6
6
|
import { parseMemory } from '../utils/parse-resources.js';
|
|
7
|
+
import { OutputCollector } from '../utils/output-collector.js';
|
|
7
8
|
const MAX_OUTPUT_SIZE = 50_000;
|
|
8
9
|
const DEFAULT_TIMEOUT = 30_000;
|
|
9
10
|
const DEFAULT_IMAGE = 'alpine:3.19';
|
|
@@ -19,11 +20,13 @@ export class DockerSandboxExecutor extends BaseSandboxExecutor {
|
|
|
19
20
|
async connect() {
|
|
20
21
|
try {
|
|
21
22
|
const Dockerode = (await import('dockerode')).default;
|
|
22
|
-
this.docker
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
const connection = this.options.docker ?? {};
|
|
24
|
+
const dockerOptions = connection.socketPath
|
|
25
|
+
? { socketPath: connection.socketPath }
|
|
26
|
+
: connection.host
|
|
27
|
+
? { host: connection.host, port: connection.port }
|
|
28
|
+
: undefined;
|
|
29
|
+
this.docker = new Dockerode(dockerOptions);
|
|
27
30
|
await this.docker.ping();
|
|
28
31
|
this.pool = new ContainerPool(this.docker, {
|
|
29
32
|
maxSize: this.options.pool?.maxSize ?? 5,
|
|
@@ -61,17 +64,35 @@ export class DockerSandboxExecutor extends BaseSandboxExecutor {
|
|
|
61
64
|
if (!request.command || request.command.length === 0) {
|
|
62
65
|
return this.failure('Command array is empty');
|
|
63
66
|
}
|
|
67
|
+
if (config.network?.allowedHosts?.length) {
|
|
68
|
+
return this.failure('network.allowedHosts is not supported by the Docker executor; use network.mode instead');
|
|
69
|
+
}
|
|
64
70
|
const startTime = Date.now();
|
|
65
71
|
const timeout = request.timeout ?? config.timeout ?? DEFAULT_TIMEOUT;
|
|
66
72
|
const image = config.image ?? DEFAULT_IMAGE;
|
|
73
|
+
let memory;
|
|
74
|
+
try {
|
|
75
|
+
memory = config.resources?.memory ? parseMemory(config.resources.memory) : undefined;
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
return this.failure(error instanceof Error ? error.message : String(error));
|
|
79
|
+
}
|
|
80
|
+
if (memory !== undefined && memory <= 0) {
|
|
81
|
+
return this.failure(`Memory limit must be positive: ${config.resources?.memory}`);
|
|
82
|
+
}
|
|
83
|
+
const cpus = config.resources?.cpus;
|
|
84
|
+
if (cpus !== undefined && (!Number.isFinite(cpus) || cpus <= 0)) {
|
|
85
|
+
return this.failure(`CPU limit must be a positive number: ${cpus}`);
|
|
86
|
+
}
|
|
67
87
|
let containerCorrupted = true;
|
|
68
88
|
try {
|
|
69
89
|
const container = await this.pool.acquire(image, {
|
|
70
|
-
memory
|
|
71
|
-
cpus
|
|
90
|
+
memory,
|
|
91
|
+
cpus,
|
|
72
92
|
cpuShares: config.resources?.cpuShares,
|
|
73
93
|
pidsLimit: config.resources?.pidsLimit,
|
|
74
94
|
networkMode: config.network?.mode ?? 'none',
|
|
95
|
+
dns: config.network?.dns,
|
|
75
96
|
mounts: config.mounts,
|
|
76
97
|
user: config.user,
|
|
77
98
|
});
|
|
@@ -103,41 +124,27 @@ export class DockerSandboxExecutor extends BaseSandboxExecutor {
|
|
|
103
124
|
}
|
|
104
125
|
}
|
|
105
126
|
async runWithTimeout(exec, stdin, timeoutMs) {
|
|
106
|
-
|
|
107
|
-
|
|
127
|
+
const stdout = new OutputCollector(MAX_OUTPUT_SIZE);
|
|
128
|
+
const stderr = new OutputCollector(MAX_OUTPUT_SIZE);
|
|
129
|
+
const demuxer = new DockerStreamDemuxer((data) => stdout.push(data), (data) => stderr.push(data));
|
|
108
130
|
let stream = null;
|
|
109
131
|
const executionPromise = (async () => {
|
|
110
132
|
stream = await exec.start({
|
|
111
133
|
hijack: true,
|
|
112
134
|
stdin: !!stdin,
|
|
113
135
|
});
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
const type = chunk[offset];
|
|
120
|
-
const size = (chunk[offset + 4] << 24) |
|
|
121
|
-
(chunk[offset + 5] << 16) |
|
|
122
|
-
(chunk[offset + 6] << 8) |
|
|
123
|
-
chunk[offset + 7];
|
|
124
|
-
if (offset + 8 + size > chunk.length)
|
|
125
|
-
break;
|
|
126
|
-
const data = chunk.slice(offset + 8, offset + 8 + size).toString('utf-8');
|
|
127
|
-
if (type === 1) {
|
|
128
|
-
stdout += data;
|
|
129
|
-
}
|
|
130
|
-
else if (type === 2) {
|
|
131
|
-
stderr += data;
|
|
132
|
-
}
|
|
133
|
-
offset += 8 + size;
|
|
134
|
-
}
|
|
136
|
+
const active = stream;
|
|
137
|
+
const finished = new Promise((resolve, reject) => {
|
|
138
|
+
active.on('end', () => resolve());
|
|
139
|
+
active.on('close', () => resolve());
|
|
140
|
+
active.on('error', (error) => reject(error instanceof Error ? error : new Error(String(error))));
|
|
135
141
|
});
|
|
142
|
+
active.on('data', (chunk) => demuxer.push(chunk));
|
|
136
143
|
if (stdin) {
|
|
137
|
-
|
|
138
|
-
|
|
144
|
+
active.write(stdin);
|
|
145
|
+
active.end();
|
|
139
146
|
}
|
|
140
|
-
await
|
|
147
|
+
await finished;
|
|
141
148
|
const inspection = await exec.inspect();
|
|
142
149
|
return inspection.ExitCode ?? 1;
|
|
143
150
|
})();
|
|
@@ -151,11 +158,9 @@ export class DockerSandboxExecutor extends BaseSandboxExecutor {
|
|
|
151
158
|
});
|
|
152
159
|
try {
|
|
153
160
|
const exitCode = await Promise.race([executionPromise, timeoutPromise]);
|
|
154
|
-
if (timer)
|
|
155
|
-
clearTimeout(timer);
|
|
156
161
|
return {
|
|
157
|
-
stdout: stdout.
|
|
158
|
-
stderr: stderr.
|
|
162
|
+
stdout: stdout.toString(),
|
|
163
|
+
stderr: stderr.toString(),
|
|
159
164
|
exitCode,
|
|
160
165
|
timedOut: false,
|
|
161
166
|
containerCorrupted: false,
|
|
@@ -163,17 +168,47 @@ export class DockerSandboxExecutor extends BaseSandboxExecutor {
|
|
|
163
168
|
}
|
|
164
169
|
catch (error) {
|
|
165
170
|
if (error instanceof Error && error.message === 'TIMEOUT') {
|
|
171
|
+
executionPromise.catch(() => undefined);
|
|
166
172
|
return {
|
|
167
|
-
stdout: stdout.
|
|
168
|
-
stderr: stderr.
|
|
173
|
+
stdout: stdout.toString(),
|
|
174
|
+
stderr: stderr.toString(),
|
|
169
175
|
exitCode: 124,
|
|
170
176
|
timedOut: true,
|
|
171
177
|
containerCorrupted: true,
|
|
172
178
|
};
|
|
173
179
|
}
|
|
180
|
+
throw error;
|
|
181
|
+
}
|
|
182
|
+
finally {
|
|
174
183
|
if (timer)
|
|
175
184
|
clearTimeout(timer);
|
|
176
|
-
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Decodes Docker's multiplexed attach stream, buffering frames split across chunks.
|
|
190
|
+
*/
|
|
191
|
+
export class DockerStreamDemuxer {
|
|
192
|
+
onStdout;
|
|
193
|
+
onStderr;
|
|
194
|
+
buffer = Buffer.alloc(0);
|
|
195
|
+
constructor(onStdout, onStderr) {
|
|
196
|
+
this.onStdout = onStdout;
|
|
197
|
+
this.onStderr = onStderr;
|
|
198
|
+
}
|
|
199
|
+
push(chunk) {
|
|
200
|
+
this.buffer = this.buffer.length === 0 ? chunk : Buffer.concat([this.buffer, chunk]);
|
|
201
|
+
while (this.buffer.length >= 8) {
|
|
202
|
+
const type = this.buffer[0];
|
|
203
|
+
const size = this.buffer.readUInt32BE(4);
|
|
204
|
+
if (this.buffer.length < 8 + size)
|
|
205
|
+
break;
|
|
206
|
+
const payload = this.buffer.subarray(8, 8 + size);
|
|
207
|
+
if (type === 1)
|
|
208
|
+
this.onStdout(payload);
|
|
209
|
+
else if (type === 2)
|
|
210
|
+
this.onStderr(payload);
|
|
211
|
+
this.buffer = this.buffer.subarray(8 + size);
|
|
177
212
|
}
|
|
178
213
|
}
|
|
179
214
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docker.js","sourceRoot":"","sources":["../../src/executors/docker.ts"],"names":[],"mappings":"AAAA;;GAEG;AAUH,OAAO,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"docker.js","sourceRoot":"","sources":["../../src/executors/docker.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Native sandbox executor - no isolation, runs directly on host.
|
|
3
3
|
* Used as fallback when Docker is unavailable.
|
|
4
|
+
*
|
|
5
|
+
* A single-element command is run through the system shell; longer commands are
|
|
6
|
+
* executed directly with exact argv (no shell), matching the Docker executor.
|
|
4
7
|
*/
|
|
5
8
|
import type { SandboxConfig, SandboxExecutionRequest, SandboxExecutionResult, SandboxResult } from '@cogitator-ai/types';
|
|
6
9
|
import { BaseSandboxExecutor } from './base.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../../src/executors/native.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../../src/executors/native.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EACV,aAAa,EACb,uBAAuB,EACvB,sBAAsB,EACtB,aAAa,EACd,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AA+B7C,qBAAa,qBAAsB,SAAQ,mBAAmB;IAC5D,QAAQ,CAAC,IAAI,YAAY;IAEnB,OAAO,IAAI,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAIvC,UAAU,IAAI,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAI1C,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAI/B,OAAO,CACX,OAAO,EAAE,uBAAuB,EAChC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,aAAa,CAAC,sBAAsB,CAAC,CAAC;CA4ElD"}
|
package/dist/executors/native.js
CHANGED
|
@@ -1,13 +1,39 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Native sandbox executor - no isolation, runs directly on host.
|
|
3
3
|
* Used as fallback when Docker is unavailable.
|
|
4
|
+
*
|
|
5
|
+
* A single-element command is run through the system shell; longer commands are
|
|
6
|
+
* executed directly with exact argv (no shell), matching the Docker executor.
|
|
4
7
|
*/
|
|
5
|
-
import {
|
|
6
|
-
import { promisify } from 'node:util';
|
|
8
|
+
import { spawn } from 'node:child_process';
|
|
7
9
|
import { BaseSandboxExecutor } from './base.js';
|
|
8
|
-
|
|
10
|
+
import { OutputCollector } from '../utils/output-collector.js';
|
|
11
|
+
const DEFAULT_TIMEOUT = 30_000;
|
|
9
12
|
const MAX_OUTPUT_SIZE = 50_000;
|
|
10
|
-
const
|
|
13
|
+
const INHERITED_ENV_KEYS = [
|
|
14
|
+
'PATH',
|
|
15
|
+
'HOME',
|
|
16
|
+
'TMPDIR',
|
|
17
|
+
'TMP',
|
|
18
|
+
'TEMP',
|
|
19
|
+
'LANG',
|
|
20
|
+
'LC_ALL',
|
|
21
|
+
'TZ',
|
|
22
|
+
'SystemRoot',
|
|
23
|
+
'SYSTEMROOT',
|
|
24
|
+
'ComSpec',
|
|
25
|
+
'PATHEXT',
|
|
26
|
+
'WINDIR',
|
|
27
|
+
];
|
|
28
|
+
function baseEnvironment() {
|
|
29
|
+
const env = {};
|
|
30
|
+
for (const key of INHERITED_ENV_KEYS) {
|
|
31
|
+
const value = process.env[key];
|
|
32
|
+
if (value !== undefined)
|
|
33
|
+
env[key] = value;
|
|
34
|
+
}
|
|
35
|
+
return env;
|
|
36
|
+
}
|
|
11
37
|
export class NativeSandboxExecutor extends BaseSandboxExecutor {
|
|
12
38
|
type = 'native';
|
|
13
39
|
async connect() {
|
|
@@ -23,43 +49,83 @@ export class NativeSandboxExecutor extends BaseSandboxExecutor {
|
|
|
23
49
|
if (!request.command || request.command.length === 0) {
|
|
24
50
|
return this.failure('Command array is empty');
|
|
25
51
|
}
|
|
52
|
+
const [file, ...args] = request.command;
|
|
53
|
+
const useShell = request.command.length === 1;
|
|
26
54
|
const startTime = Date.now();
|
|
27
|
-
const timeout = request.timeout ?? config.timeout ??
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
55
|
+
const timeout = request.timeout ?? config.timeout ?? DEFAULT_TIMEOUT;
|
|
56
|
+
const stdout = new OutputCollector(MAX_OUTPUT_SIZE);
|
|
57
|
+
const stderr = new OutputCollector(MAX_OUTPUT_SIZE);
|
|
58
|
+
return new Promise((resolve) => {
|
|
59
|
+
let timedOut = false;
|
|
60
|
+
let settled = false;
|
|
61
|
+
const finish = (exitCode, extraStderr) => {
|
|
62
|
+
if (settled)
|
|
63
|
+
return;
|
|
64
|
+
settled = true;
|
|
65
|
+
clearTimeout(timer);
|
|
66
|
+
if (extraStderr)
|
|
67
|
+
stderr.push(extraStderr);
|
|
68
|
+
resolve(this.success({
|
|
69
|
+
stdout: stdout.toString(),
|
|
70
|
+
stderr: timedOut
|
|
71
|
+
? stderr.toString() || `Command timed out after ${timeout}ms`
|
|
72
|
+
: stderr.toString(),
|
|
73
|
+
exitCode: timedOut ? 124 : exitCode,
|
|
74
|
+
timedOut,
|
|
75
|
+
duration: Date.now() - startTime,
|
|
76
|
+
}));
|
|
77
|
+
};
|
|
78
|
+
const useProcessGroup = process.platform !== 'win32';
|
|
79
|
+
const child = spawn(file, args, {
|
|
31
80
|
cwd: request.cwd ?? config.workdir,
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
81
|
+
env: { ...baseEnvironment(), ...config.env, ...request.env },
|
|
82
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
83
|
+
windowsHide: true,
|
|
84
|
+
detached: useProcessGroup,
|
|
85
|
+
shell: useShell,
|
|
35
86
|
});
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
87
|
+
const timer = setTimeout(() => {
|
|
88
|
+
timedOut = true;
|
|
89
|
+
try {
|
|
90
|
+
if (useProcessGroup && child.pid !== undefined) {
|
|
91
|
+
process.kill(-child.pid, 'SIGKILL');
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
child.kill('SIGKILL');
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
child.kill('SIGKILL');
|
|
99
|
+
}
|
|
100
|
+
child.stdout.destroy();
|
|
101
|
+
child.stderr.destroy();
|
|
102
|
+
finish(124);
|
|
103
|
+
}, timeout);
|
|
104
|
+
child.stdout.on('data', (chunk) => stdout.push(chunk));
|
|
105
|
+
child.stderr.on('data', (chunk) => stderr.push(chunk));
|
|
106
|
+
child.on('error', (error) => {
|
|
107
|
+
const exitCode = error.code === 'ENOENT' ? 127 : error.code === 'EACCES' ? 126 : 1;
|
|
108
|
+
finish(exitCode, error.message);
|
|
42
109
|
});
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const error = err;
|
|
46
|
-
if (error.killed) {
|
|
47
|
-
return this.success({
|
|
48
|
-
stdout: '',
|
|
49
|
-
stderr: `Command timed out after ${timeout.toString()}ms`,
|
|
50
|
-
exitCode: 124,
|
|
51
|
-
timedOut: true,
|
|
52
|
-
duration: Date.now() - startTime,
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
return this.success({
|
|
56
|
-
stdout: (error.stdout ?? '').slice(0, MAX_OUTPUT_SIZE),
|
|
57
|
-
stderr: (error.stderr ?? error.message).slice(0, MAX_OUTPUT_SIZE),
|
|
58
|
-
exitCode: error.code ?? 1,
|
|
59
|
-
timedOut: false,
|
|
60
|
-
duration: Date.now() - startTime,
|
|
110
|
+
child.on('close', (code, signal) => {
|
|
111
|
+
finish(code ?? (signal ? 128 + signalNumber(signal) : 1));
|
|
61
112
|
});
|
|
62
|
-
|
|
113
|
+
child.stdin.on('error', () => undefined);
|
|
114
|
+
child.stdin.end(request.stdin ?? '');
|
|
115
|
+
});
|
|
63
116
|
}
|
|
64
117
|
}
|
|
118
|
+
function signalNumber(signal) {
|
|
119
|
+
const numbers = {
|
|
120
|
+
SIGHUP: 1,
|
|
121
|
+
SIGINT: 2,
|
|
122
|
+
SIGQUIT: 3,
|
|
123
|
+
SIGABRT: 6,
|
|
124
|
+
SIGKILL: 9,
|
|
125
|
+
SIGSEGV: 11,
|
|
126
|
+
SIGPIPE: 13,
|
|
127
|
+
SIGTERM: 15,
|
|
128
|
+
};
|
|
129
|
+
return numbers[signal] ?? 0;
|
|
130
|
+
}
|
|
65
131
|
//# sourceMappingURL=native.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native.js","sourceRoot":"","sources":["../../src/executors/native.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"native.js","sourceRoot":"","sources":["../../src/executors/native.ts"],"names":[],"mappings":"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"}
|
package/dist/executors/wasm.d.ts
CHANGED
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
* WASM sandbox executor - isolated execution via Extism
|
|
3
3
|
*
|
|
4
4
|
* Provides fast, memory-safe execution of WASM modules.
|
|
5
|
-
*
|
|
6
|
-
* Memory: 1-10MB per plugin (vs Docker 50-200MB)
|
|
5
|
+
* Every plugin runs in its own worker thread so timeouts can terminate runaway modules.
|
|
7
6
|
*/
|
|
8
7
|
import type { SandboxConfig, SandboxExecutionRequest, SandboxExecutionResult, SandboxResult, SandboxWasmConfig } from '@cogitator-ai/types';
|
|
9
8
|
import { BaseSandboxExecutor } from './base.js';
|
|
@@ -13,17 +12,21 @@ export interface WasmExecutorOptions {
|
|
|
13
12
|
export declare class WasmSandboxExecutor extends BaseSandboxExecutor {
|
|
14
13
|
readonly type = "wasm";
|
|
15
14
|
private createPlugin?;
|
|
16
|
-
private
|
|
17
|
-
private
|
|
18
|
-
private
|
|
15
|
+
private readonly idlePlugins;
|
|
16
|
+
private readonly activePlugins;
|
|
17
|
+
private idleCount;
|
|
18
|
+
private generation;
|
|
19
|
+
private readonly options;
|
|
19
20
|
constructor(options?: WasmExecutorOptions);
|
|
20
21
|
connect(): Promise<SandboxResult<void>>;
|
|
21
22
|
disconnect(): Promise<SandboxResult<void>>;
|
|
22
23
|
isAvailable(): Promise<boolean>;
|
|
23
24
|
execute(request: SandboxExecutionRequest, config: SandboxConfig): Promise<SandboxResult<SandboxExecutionResult>>;
|
|
24
|
-
private
|
|
25
|
-
private
|
|
25
|
+
private acquire;
|
|
26
|
+
private release;
|
|
27
|
+
private closePlugin;
|
|
28
|
+
private loadManifest;
|
|
26
29
|
private buildInput;
|
|
27
|
-
private
|
|
30
|
+
private callWithTimeout;
|
|
28
31
|
}
|
|
29
32
|
//# sourceMappingURL=wasm.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wasm.d.ts","sourceRoot":"","sources":["../../src/executors/wasm.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"wasm.d.ts","sourceRoot":"","sources":["../../src/executors/wasm.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,uBAAuB,EACvB,sBAAsB,EACtB,aAAa,EACb,iBAAiB,EAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AAK7C,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,iBAAiB,CAAC;CAC1B;AAqCD,qBAAa,mBAAoB,SAAQ,mBAAmB;IAC1D,QAAQ,CAAC,IAAI,UAAU;IACvB,OAAO,CAAC,YAAY,CAAC,CAAiB;IACtC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqC;IACjE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA2B;IACzD,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;gBAElC,OAAO,GAAE,mBAAwB;IAKvC,OAAO,IAAI,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAYvC,UAAU,IAAI,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAU1C,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAQ/B,OAAO,CACX,OAAO,EAAE,uBAAuB,EAChC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,aAAa,CAAC,sBAAsB,CAAC,CAAC;YAuDnC,OAAO;YAuBP,OAAO;YAsBP,WAAW;YAWX,YAAY;IAkB1B,OAAO,CAAC,UAAU;YAWJ,eAAe;CAiC9B"}
|