microsandbox-mcp 0.5.7 → 0.5.10
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 +142 -27
- package/dist/config.d.ts +10 -0
- package/dist/config.js +42 -0
- package/dist/config.js.map +1 -0
- package/dist/index.js +13 -1
- package/dist/index.js.map +1 -1
- package/dist/resources.d.ts +2 -0
- package/dist/resources.js +71 -0
- package/dist/resources.js.map +1 -0
- package/dist/schemas/common.d.ts +7 -0
- package/dist/schemas/common.js +8 -0
- package/dist/schemas/common.js.map +1 -0
- package/dist/state/exec-sessions.d.ts +19 -0
- package/dist/state/exec-sessions.js +151 -0
- package/dist/state/exec-sessions.js.map +1 -0
- package/dist/tools/exec.js +283 -56
- package/dist/tools/exec.js.map +1 -1
- package/dist/tools/filesystem.js +195 -59
- package/dist/tools/filesystem.js.map +1 -1
- package/dist/tools/image.d.ts +2 -0
- package/dist/tools/image.js +99 -0
- package/dist/tools/image.js.map +1 -0
- package/dist/tools/logs.d.ts +2 -0
- package/dist/tools/logs.js +128 -0
- package/dist/tools/logs.js.map +1 -0
- package/dist/tools/metrics.js +48 -65
- package/dist/tools/metrics.js.map +1 -1
- package/dist/tools/runtime.d.ts +2 -0
- package/dist/tools/runtime.js +61 -0
- package/dist/tools/runtime.js.map +1 -0
- package/dist/tools/sandbox.d.ts +216 -0
- package/dist/tools/sandbox.js +619 -202
- package/dist/tools/sandbox.js.map +1 -1
- package/dist/tools/snapshot.d.ts +2 -0
- package/dist/tools/snapshot.js +234 -0
- package/dist/tools/snapshot.js.map +1 -0
- package/dist/tools/ssh.d.ts +2 -0
- package/dist/tools/ssh.js +323 -0
- package/dist/tools/ssh.js.map +1 -0
- package/dist/tools/volume.js +287 -23
- package/dist/tools/volume.js.map +1 -1
- package/dist/utils/errors.d.ts +2 -7
- package/dist/utils/errors.js +6 -5
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/exec-output.d.ts +20 -0
- package/dist/utils/exec-output.js +15 -0
- package/dist/utils/exec-output.js.map +1 -0
- package/dist/utils/output.d.ts +11 -0
- package/dist/utils/output.js +21 -0
- package/dist/utils/output.js.map +1 -0
- package/dist/utils/policy.d.ts +8 -0
- package/dist/utils/policy.js +47 -0
- package/dist/utils/policy.js.map +1 -0
- package/dist/utils/redaction.d.ts +1 -0
- package/dist/utils/redaction.js +15 -0
- package/dist/utils/redaction.js.map +1 -0
- package/dist/utils/response.d.ts +34 -0
- package/dist/utils/response.js +38 -0
- package/dist/utils/response.js.map +1 -0
- package/dist/utils/serialization.d.ts +15 -0
- package/dist/utils/serialization.js +164 -0
- package/dist/utils/serialization.js.map +1 -0
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -123,50 +123,161 @@ For any MCP client that supports stdio transport:
|
|
|
123
123
|
|
|
124
124
|
## Available Tools
|
|
125
125
|
|
|
126
|
-
|
|
126
|
+
Every tool returns a JSON envelope: `{ "ok": true, "data": ... }` on success or `{ "ok": false, "error": ... }` on failure. Large command output, logs, and file reads are capped by default and include truncation metadata when shortened.
|
|
127
|
+
|
|
128
|
+
**Runtime**
|
|
129
|
+
|
|
130
|
+
| Tool | Description |
|
|
131
|
+
| ---- | ----------- |
|
|
132
|
+
| `runtime_check` | Check whether the microsandbox runtime, `msb`, and `libkrunfw` are available |
|
|
133
|
+
| `runtime_install` | Install runtime dependencies using the microsandbox SDK installer |
|
|
134
|
+
|
|
135
|
+
**Sandbox Lifecycle**
|
|
136
|
+
|
|
137
|
+
| Tool | Description |
|
|
138
|
+
| ---- | ----------- |
|
|
139
|
+
| `sandbox_run` | Create an ephemeral sandbox, run a shell command, return output, and remove it |
|
|
140
|
+
| `sandbox_create` | Create and boot a persistent sandbox with rootfs, resources, process, mounts, patches, network, secrets, and lifecycle options |
|
|
141
|
+
| `sandbox_start` | Start stopped sandboxes by name, labels, or status selector |
|
|
142
|
+
| `sandbox_list` | List sandboxes with status, image, labels, and timestamps |
|
|
143
|
+
| `sandbox_status` | Show status for one sandbox or a filtered sandbox set |
|
|
144
|
+
| `sandbox_inspect` | Return full configuration and metadata for one sandbox |
|
|
145
|
+
| `sandbox_stop` | Stop selected sandboxes gracefully or forcefully, with optional timeout |
|
|
146
|
+
| `sandbox_drain` | Request graceful drain for selected sandboxes |
|
|
147
|
+
| `sandbox_wait` | Wait until selected sandboxes reach a terminal state |
|
|
148
|
+
| `sandbox_remove` | Remove selected stopped sandboxes, optionally force-stopping running ones first |
|
|
149
|
+
|
|
150
|
+
**Command Execution**
|
|
151
|
+
|
|
152
|
+
| Tool | Description |
|
|
153
|
+
| ---- | ----------- |
|
|
154
|
+
| `sandbox_exec` | Execute an argv command with env, cwd, user, TTY, timeout, rlimits, stdin, and output caps |
|
|
155
|
+
| `sandbox_shell` | Execute a shell command string with the same execution controls |
|
|
156
|
+
| `sandbox_exec_start` | Start a long-running command and return an in-memory exec session id |
|
|
157
|
+
| `sandbox_exec_poll` | Poll output events and exit status for an exec session |
|
|
158
|
+
| `sandbox_exec_write_stdin` | Write UTF-8 or base64 data to an exec session stdin |
|
|
159
|
+
| `sandbox_exec_signal` | Send `hup`, `int`, `term`, `kill`, or a numeric signal to an exec session |
|
|
160
|
+
| `sandbox_exec_close` | Close and forget an exec session |
|
|
161
|
+
|
|
162
|
+
**Logs**
|
|
163
|
+
|
|
127
164
|
| Tool | Description |
|
|
128
165
|
| ---- | ----------- |
|
|
129
|
-
| `
|
|
130
|
-
| `
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
| `sandbox_remove` | Remove a stopped sandbox |
|
|
135
|
-
|
|
136
|
-
**Command Execution:**
|
|
166
|
+
| `sandbox_logs_read` | Read captured logs with tail, time, source, grep, session id, and output cap filters |
|
|
167
|
+
| `sandbox_logs_stream` | Poll captured logs using cursors and a bounded follow timeout |
|
|
168
|
+
|
|
169
|
+
**Filesystem**
|
|
170
|
+
|
|
137
171
|
| Tool | Description |
|
|
138
172
|
| ---- | ----------- |
|
|
139
|
-
| `
|
|
140
|
-
| `
|
|
173
|
+
| `sandbox_fs_read` | Read a sandbox file as UTF-8 text or base64 bytes |
|
|
174
|
+
| `sandbox_fs_write` | Write UTF-8 text or base64 bytes to a sandbox file |
|
|
175
|
+
| `sandbox_fs_list` | List sandbox directory entries |
|
|
176
|
+
| `sandbox_fs_mkdir` | Create a sandbox directory |
|
|
177
|
+
| `sandbox_fs_remove` | Remove a sandbox file or directory |
|
|
178
|
+
| `sandbox_fs_copy` | Copy a file within one sandbox or between two running sandboxes |
|
|
179
|
+
| `sandbox_fs_rename` | Rename a sandbox file or directory |
|
|
180
|
+
| `sandbox_fs_stat` | Get sandbox path metadata |
|
|
181
|
+
| `sandbox_fs_exists` | Check whether a sandbox path exists |
|
|
182
|
+
| `sandbox_fs_copy_from_host` | Copy an allowlisted host path into a sandbox |
|
|
183
|
+
| `sandbox_fs_copy_to_host` | Copy a sandbox path to an allowlisted host destination |
|
|
184
|
+
|
|
185
|
+
**Metrics**
|
|
141
186
|
|
|
142
|
-
**Filesystem:**
|
|
143
187
|
| Tool | Description |
|
|
144
188
|
| ---- | ----------- |
|
|
145
|
-
| `
|
|
146
|
-
| `
|
|
147
|
-
| `
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
**Volume Management:**
|
|
189
|
+
| `sandbox_metrics` | Get point-in-time metrics for one running sandbox |
|
|
190
|
+
| `sandbox_metrics_all` | Get point-in-time metrics for all running sandboxes |
|
|
191
|
+
| `sandbox_metrics_stream` | Collect a bounded number of metrics samples from one sandbox |
|
|
192
|
+
|
|
193
|
+
**Volumes**
|
|
194
|
+
|
|
153
195
|
| Tool | Description |
|
|
154
196
|
| ---- | ----------- |
|
|
155
|
-
| `volume_create` | Create a named
|
|
156
|
-
| `volume_list` | List
|
|
157
|
-
| `
|
|
197
|
+
| `volume_create` | Create a directory or disk-backed named volume with quota, capacity, and labels |
|
|
198
|
+
| `volume_list` | List named volumes with kind, quota, capacity, usage, disk format, labels, and timestamps |
|
|
199
|
+
| `volume_inspect` | Inspect one named volume |
|
|
200
|
+
| `volume_remove` | Remove one or more named volumes |
|
|
201
|
+
| `volume_fs_read` | Read a volume file as UTF-8 text or base64 bytes |
|
|
202
|
+
| `volume_fs_write` | Write UTF-8 text or base64 bytes to a volume file |
|
|
203
|
+
| `volume_fs_list` | List volume directory entries |
|
|
204
|
+
| `volume_fs_mkdir` | Create a directory inside a volume |
|
|
205
|
+
| `volume_fs_remove` | Remove a file or directory from a volume |
|
|
206
|
+
| `volume_fs_copy` | Copy a file inside a volume |
|
|
207
|
+
| `volume_fs_rename` | Rename a file or directory inside a volume |
|
|
208
|
+
| `volume_fs_stat` | Get volume path metadata |
|
|
209
|
+
| `volume_fs_exists` | Check whether a volume path exists |
|
|
210
|
+
|
|
211
|
+
**Images**
|
|
158
212
|
|
|
159
|
-
**Monitoring:**
|
|
160
213
|
| Tool | Description |
|
|
161
214
|
| ---- | ----------- |
|
|
162
|
-
| `
|
|
163
|
-
| `
|
|
215
|
+
| `image_list` | List cached images |
|
|
216
|
+
| `image_inspect` | Inspect cached image config and layers |
|
|
217
|
+
| `image_remove` | Remove one or more cached images, optionally forced with confirmation |
|
|
218
|
+
| `image_prune` | Remove cached image artifacts unused by sandboxes, with confirmation |
|
|
219
|
+
|
|
220
|
+
**Snapshots**
|
|
221
|
+
|
|
222
|
+
| Tool | Description |
|
|
223
|
+
| ---- | ----------- |
|
|
224
|
+
| `snapshot_create` | Create a snapshot from a stopped sandbox by name or explicit host path |
|
|
225
|
+
| `snapshot_list` | List indexed snapshots |
|
|
226
|
+
| `snapshot_inspect` | Inspect snapshot metadata by name, digest, or path, optionally verifying integrity |
|
|
227
|
+
| `snapshot_verify` | Verify recorded snapshot content integrity |
|
|
228
|
+
| `snapshot_remove` | Remove one or more snapshots, optionally forced with confirmation |
|
|
229
|
+
| `snapshot_reindex` | Rebuild the local snapshot index |
|
|
230
|
+
| `snapshot_export` | Export a snapshot to an allowlisted host archive path |
|
|
231
|
+
| `snapshot_import` | Import a snapshot archive from an allowlisted host path |
|
|
232
|
+
|
|
233
|
+
**SSH and SFTP**
|
|
234
|
+
|
|
235
|
+
| Tool | Description |
|
|
236
|
+
| ---- | ----------- |
|
|
237
|
+
| `sandbox_ssh_exec` | Execute a command through the sandbox SSH subsystem |
|
|
238
|
+
| `sandbox_sftp_read` | Read a file through sandbox SFTP as UTF-8 text or base64 bytes |
|
|
239
|
+
| `sandbox_sftp_write` | Write UTF-8 text or base64 bytes through sandbox SFTP |
|
|
240
|
+
| `sandbox_sftp_mkdir` | Create a directory through sandbox SFTP |
|
|
241
|
+
| `sandbox_sftp_remove` | Remove a file or directory through sandbox SFTP |
|
|
242
|
+
| `sandbox_sftp_rename` | Rename a path through sandbox SFTP |
|
|
243
|
+
| `sandbox_sftp_realpath` | Resolve a real path through sandbox SFTP |
|
|
244
|
+
| `sandbox_sftp_readlink` | Read a symlink target through sandbox SFTP |
|
|
245
|
+
| `sandbox_sftp_symlink` | Create a symlink through sandbox SFTP |
|
|
246
|
+
|
|
247
|
+
## Resources
|
|
248
|
+
|
|
249
|
+
| URI | Description |
|
|
250
|
+
| --- | ----------- |
|
|
251
|
+
| `microsandbox://runtime` | Runtime installation status and MCP configuration |
|
|
252
|
+
| `microsandbox://sandboxes` | Current sandbox inventory |
|
|
253
|
+
| `microsandbox://volumes` | Current volume inventory |
|
|
254
|
+
| `microsandbox://images` | Current image cache inventory |
|
|
255
|
+
| `microsandbox://snapshots` | Current snapshot index |
|
|
256
|
+
| `microsandbox://schemas/sandbox-create` | JSON Schema for sandbox creation inputs |
|
|
257
|
+
| `microsandbox://policy` | Effective host path and dangerous-operation policy |
|
|
258
|
+
|
|
259
|
+
## Configuration
|
|
260
|
+
|
|
261
|
+
| Env var | Default | Description |
|
|
262
|
+
| ------- | ------- | ----------- |
|
|
263
|
+
| `MICROSANDBOX_MCP_HOST_PATHS` | current working directory | Colon-separated allowlist for bind mounts, host copy, snapshot import/export, and other host path operations |
|
|
264
|
+
| `MICROSANDBOX_MCP_HOST_PATH_POLICY` | `allowlist` | Set to `unrestricted` to allow any host path |
|
|
265
|
+
| `MICROSANDBOX_MCP_ENABLE_DANGEROUS` | `0` | Enables future dangerous operations; destructive cache operations still require explicit `confirm: true` |
|
|
266
|
+
| `MICROSANDBOX_MCP_MAX_OUTPUT_BYTES` | `1048576` | Default cap for command output, logs, and file reads |
|
|
267
|
+
| `MICROSANDBOX_MCP_DEFAULT_TIMEOUT_MS` | `120000` | Default timeout budget for exec-style operations |
|
|
268
|
+
| `MICROSANDBOX_MCP_SESSION_TTL_MS` | `900000` | Idle TTL for in-memory exec sessions |
|
|
269
|
+
| `MSB_PATH` | unset | Optional path to the `msb` binary for SDK/runtime discovery |
|
|
270
|
+
| `MSB_LIBKRUNFW_PATH` | unset | Optional path to `libkrunfw` |
|
|
271
|
+
|
|
272
|
+
## SDK Gaps
|
|
273
|
+
|
|
274
|
+
The server intentionally stays a thin TypeScript SDK adapter and does not shell out to `msb` for core behavior. Image pull/load/save, persistent registry login/logout/list, SSH authorization management, and managed SSH serving are not exposed until the TypeScript SDK provides first-class APIs for them. Command aliases (`msb install`/`msb uninstall`) and runtime self-update/uninstall are intentionally out of scope.
|
|
164
275
|
|
|
165
276
|
## Requirements
|
|
166
277
|
|
|
167
278
|
macOS (Apple Silicon) or Linux (x86_64/ARM64 with KVM support).
|
|
168
279
|
|
|
169
|
-
|
|
280
|
+
Use `runtime_check` to verify whether `msb` and `libkrunfw` are available. Use `runtime_install` to install them from the MCP server. If that fails, install manually:
|
|
170
281
|
|
|
171
282
|
```bash
|
|
172
283
|
curl -fsSL https://install.microsandbox.dev | sh
|
|
@@ -179,9 +290,13 @@ git clone https://github.com/superradcompany/microsandbox-mcp.git
|
|
|
179
290
|
cd microsandbox-mcp
|
|
180
291
|
npm install
|
|
181
292
|
npm run build
|
|
293
|
+
npm test
|
|
294
|
+
npm run test:e2e
|
|
182
295
|
node dist/index.js
|
|
183
296
|
```
|
|
184
297
|
|
|
298
|
+
`npm run test:e2e` launches the built MCP server over stdio and calls every registered tool and resource with live parameters. It creates temporary sandboxes, volumes, snapshots, and host files, then cleans them up. Global image cache deletion is guarded by default; set `MICROSANDBOX_MCP_E2E_DESTRUCTIVE_CACHE=1` to let the e2e script run destructive image prune behavior instead of the safe confirmation-error path.
|
|
299
|
+
|
|
185
300
|
## Links
|
|
186
301
|
|
|
187
302
|
- [microsandbox](https://github.com/microsandbox/microsandbox) — The microVM sandbox runtime
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface ServerConfig {
|
|
2
|
+
hostPathPolicy: "allowlist" | "unrestricted";
|
|
3
|
+
hostPaths: string[];
|
|
4
|
+
dangerousEnabled: boolean;
|
|
5
|
+
maxOutputBytes: number;
|
|
6
|
+
defaultTimeoutMs: number;
|
|
7
|
+
sessionTtlMs: number;
|
|
8
|
+
}
|
|
9
|
+
export declare function getServerConfig(): ServerConfig;
|
|
10
|
+
export declare function resetServerConfigForTests(): void;
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
const DEFAULT_MAX_OUTPUT_BYTES = 1024 * 1024;
|
|
3
|
+
const DEFAULT_TIMEOUT_MS = 120_000;
|
|
4
|
+
const DEFAULT_SESSION_TTL_MS = 900_000;
|
|
5
|
+
let cachedConfig;
|
|
6
|
+
export function getServerConfig() {
|
|
7
|
+
if (cachedConfig)
|
|
8
|
+
return cachedConfig;
|
|
9
|
+
const hostPathPolicy = parseHostPathPolicy(process.env.MICROSANDBOX_MCP_HOST_PATH_POLICY);
|
|
10
|
+
const hostPaths = parseHostPaths(process.env.MICROSANDBOX_MCP_HOST_PATHS);
|
|
11
|
+
cachedConfig = {
|
|
12
|
+
hostPathPolicy,
|
|
13
|
+
hostPaths,
|
|
14
|
+
dangerousEnabled: process.env.MICROSANDBOX_MCP_ENABLE_DANGEROUS === "1",
|
|
15
|
+
maxOutputBytes: parsePositiveInt(process.env.MICROSANDBOX_MCP_MAX_OUTPUT_BYTES, DEFAULT_MAX_OUTPUT_BYTES),
|
|
16
|
+
defaultTimeoutMs: parsePositiveInt(process.env.MICROSANDBOX_MCP_DEFAULT_TIMEOUT_MS, DEFAULT_TIMEOUT_MS),
|
|
17
|
+
sessionTtlMs: parsePositiveInt(process.env.MICROSANDBOX_MCP_SESSION_TTL_MS, DEFAULT_SESSION_TTL_MS),
|
|
18
|
+
};
|
|
19
|
+
return cachedConfig;
|
|
20
|
+
}
|
|
21
|
+
export function resetServerConfigForTests() {
|
|
22
|
+
cachedConfig = undefined;
|
|
23
|
+
}
|
|
24
|
+
function parseHostPathPolicy(value) {
|
|
25
|
+
if (value === "unrestricted")
|
|
26
|
+
return "unrestricted";
|
|
27
|
+
return "allowlist";
|
|
28
|
+
}
|
|
29
|
+
function parseHostPaths(value) {
|
|
30
|
+
const rawPaths = value && value.trim().length > 0 ? value.split(":") : [process.cwd()];
|
|
31
|
+
return rawPaths
|
|
32
|
+
.map((entry) => entry.trim())
|
|
33
|
+
.filter((entry) => entry.length > 0)
|
|
34
|
+
.map((entry) => path.resolve(entry));
|
|
35
|
+
}
|
|
36
|
+
function parsePositiveInt(value, fallback) {
|
|
37
|
+
if (!value)
|
|
38
|
+
return fallback;
|
|
39
|
+
const parsed = Number.parseInt(value, 10);
|
|
40
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAW7B,MAAM,wBAAwB,GAAG,IAAI,GAAG,IAAI,CAAC;AAC7C,MAAM,kBAAkB,GAAG,OAAO,CAAC;AACnC,MAAM,sBAAsB,GAAG,OAAO,CAAC;AAEvC,IAAI,YAAsC,CAAC;AAE3C,MAAM,UAAU,eAAe;IAC7B,IAAI,YAAY;QAAE,OAAO,YAAY,CAAC;IAEtC,MAAM,cAAc,GAAG,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;IAC1F,MAAM,SAAS,GAAG,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;IAE1E,YAAY,GAAG;QACb,cAAc;QACd,SAAS;QACT,gBAAgB,EAAE,OAAO,CAAC,GAAG,CAAC,iCAAiC,KAAK,GAAG;QACvE,cAAc,EAAE,gBAAgB,CAC9B,OAAO,CAAC,GAAG,CAAC,iCAAiC,EAC7C,wBAAwB,CACzB;QACD,gBAAgB,EAAE,gBAAgB,CAChC,OAAO,CAAC,GAAG,CAAC,mCAAmC,EAC/C,kBAAkB,CACnB;QACD,YAAY,EAAE,gBAAgB,CAC5B,OAAO,CAAC,GAAG,CAAC,+BAA+B,EAC3C,sBAAsB,CACvB;KACF,CAAC;IAEF,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,yBAAyB;IACvC,YAAY,GAAG,SAAS,CAAC;AAC3B,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAyB;IACpD,IAAI,KAAK,KAAK,cAAc;QAAE,OAAO,cAAc,CAAC;IACpD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,SAAS,cAAc,CAAC,KAAyB;IAC/C,MAAM,QAAQ,GAAG,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACvF,OAAO,QAAQ;SACZ,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;SAC5B,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;SACnC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;AACzC,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAyB,EAAE,QAAgB;IACnE,IAAI,CAAC,KAAK;QAAE,OAAO,QAAQ,CAAC;IAC5B,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC1C,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;AACnE,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,19 +1,31 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import { registerResources } from "./resources.js";
|
|
3
4
|
import { registerSandboxTools } from "./tools/sandbox.js";
|
|
4
5
|
import { registerExecTools } from "./tools/exec.js";
|
|
5
6
|
import { registerFilesystemTools } from "./tools/filesystem.js";
|
|
7
|
+
import { registerImageTools } from "./tools/image.js";
|
|
8
|
+
import { registerLogTools } from "./tools/logs.js";
|
|
6
9
|
import { registerVolumeTools } from "./tools/volume.js";
|
|
7
10
|
import { registerMetricsTools } from "./tools/metrics.js";
|
|
11
|
+
import { registerRuntimeTools } from "./tools/runtime.js";
|
|
12
|
+
import { registerSnapshotTools } from "./tools/snapshot.js";
|
|
13
|
+
import { registerSshTools } from "./tools/ssh.js";
|
|
8
14
|
const server = new McpServer({
|
|
9
15
|
name: "microsandbox",
|
|
10
|
-
version: "0.5.
|
|
16
|
+
version: "0.5.10",
|
|
11
17
|
});
|
|
18
|
+
registerResources(server);
|
|
19
|
+
registerRuntimeTools(server);
|
|
12
20
|
registerSandboxTools(server);
|
|
13
21
|
registerExecTools(server);
|
|
22
|
+
registerLogTools(server);
|
|
14
23
|
registerFilesystemTools(server);
|
|
15
24
|
registerVolumeTools(server);
|
|
16
25
|
registerMetricsTools(server);
|
|
26
|
+
registerImageTools(server);
|
|
27
|
+
registerSnapshotTools(server);
|
|
28
|
+
registerSshTools(server);
|
|
17
29
|
const transport = new StdioServerTransport();
|
|
18
30
|
await server.connect(transport);
|
|
19
31
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,cAAc;IACpB,OAAO,EAAE,QAAQ;CAClB,CAAC,CAAC;AAEH,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAC1B,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAC7B,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAC7B,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAC1B,gBAAgB,CAAC,MAAM,CAAC,CAAC;AACzB,uBAAuB,CAAC,MAAM,CAAC,CAAC;AAChC,mBAAmB,CAAC,MAAM,CAAC,CAAC;AAC5B,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAC7B,kBAAkB,CAAC,MAAM,CAAC,CAAC;AAC3B,qBAAqB,CAAC,MAAM,CAAC,CAAC;AAC9B,gBAAgB,CAAC,MAAM,CAAC,CAAC;AAEzB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { Image, isInstalled, Sandbox, Snapshot, Volume } from "microsandbox";
|
|
3
|
+
import { getServerConfig } from "./config.js";
|
|
4
|
+
import { sandboxCreateSchema } from "./tools/sandbox.js";
|
|
5
|
+
import { imageHandleData, sandboxSummaryData, snapshotHandleData, volumeHandleData, } from "./utils/serialization.js";
|
|
6
|
+
export function registerResources(server) {
|
|
7
|
+
server.registerResource("runtime", "microsandbox://runtime", {
|
|
8
|
+
title: "microsandbox runtime",
|
|
9
|
+
description: "Runtime installation and MCP server configuration.",
|
|
10
|
+
mimeType: "application/json",
|
|
11
|
+
}, async (uri) => jsonResource(uri, {
|
|
12
|
+
installed: isInstalled(),
|
|
13
|
+
nodeVersion: process.version,
|
|
14
|
+
platform: process.platform,
|
|
15
|
+
arch: process.arch,
|
|
16
|
+
msbPath: process.env.MSB_PATH ?? null,
|
|
17
|
+
libkrunfwPath: process.env.MSB_LIBKRUNFW_PATH ?? null,
|
|
18
|
+
policy: policyData(),
|
|
19
|
+
}));
|
|
20
|
+
server.registerResource("sandboxes", "microsandbox://sandboxes", {
|
|
21
|
+
title: "microsandbox sandboxes",
|
|
22
|
+
description: "Current sandbox inventory.",
|
|
23
|
+
mimeType: "application/json",
|
|
24
|
+
}, async (uri) => jsonResource(uri, (await Sandbox.list()).map(sandboxSummaryData)));
|
|
25
|
+
server.registerResource("volumes", "microsandbox://volumes", {
|
|
26
|
+
title: "microsandbox volumes",
|
|
27
|
+
description: "Current volume inventory.",
|
|
28
|
+
mimeType: "application/json",
|
|
29
|
+
}, async (uri) => jsonResource(uri, (await Volume.list()).map(volumeHandleData)));
|
|
30
|
+
server.registerResource("images", "microsandbox://images", {
|
|
31
|
+
title: "microsandbox images",
|
|
32
|
+
description: "Current cached image inventory.",
|
|
33
|
+
mimeType: "application/json",
|
|
34
|
+
}, async (uri) => jsonResource(uri, (await Image.list()).map(imageHandleData)));
|
|
35
|
+
server.registerResource("snapshots", "microsandbox://snapshots", {
|
|
36
|
+
title: "microsandbox snapshots",
|
|
37
|
+
description: "Current indexed snapshot inventory.",
|
|
38
|
+
mimeType: "application/json",
|
|
39
|
+
}, async (uri) => jsonResource(uri, (await Snapshot.list()).map(snapshotHandleData)));
|
|
40
|
+
server.registerResource("sandbox-create-schema", "microsandbox://schemas/sandbox-create", {
|
|
41
|
+
title: "sandbox create schema",
|
|
42
|
+
description: "JSON Schema for sandbox_create and sandbox_run creation fields.",
|
|
43
|
+
mimeType: "application/schema+json",
|
|
44
|
+
}, async (uri) => jsonResource(uri, z.toJSONSchema(sandboxCreateSchema)));
|
|
45
|
+
server.registerResource("policy", "microsandbox://policy", {
|
|
46
|
+
title: "microsandbox MCP policy",
|
|
47
|
+
description: "Effective host path and dangerous operation policy.",
|
|
48
|
+
mimeType: "application/json",
|
|
49
|
+
}, async (uri) => jsonResource(uri, policyData()));
|
|
50
|
+
}
|
|
51
|
+
function jsonResource(uri, data) {
|
|
52
|
+
return {
|
|
53
|
+
contents: [{
|
|
54
|
+
uri: uri.href,
|
|
55
|
+
mimeType: "application/json",
|
|
56
|
+
text: JSON.stringify(data, null, 2),
|
|
57
|
+
}],
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function policyData() {
|
|
61
|
+
const config = getServerConfig();
|
|
62
|
+
return {
|
|
63
|
+
hostPathPolicy: config.hostPathPolicy,
|
|
64
|
+
hostPaths: config.hostPaths,
|
|
65
|
+
dangerousEnabled: config.dangerousEnabled,
|
|
66
|
+
maxOutputBytes: config.maxOutputBytes,
|
|
67
|
+
defaultTimeoutMs: config.defaultTimeoutMs,
|
|
68
|
+
sessionTtlMs: config.sessionTtlMs,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=resources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resources.js","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE7E,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,0BAA0B,CAAC;AAElC,MAAM,UAAU,iBAAiB,CAAC,MAAiB;IACjD,MAAM,CAAC,gBAAgB,CACrB,SAAS,EACT,wBAAwB,EACxB;QACE,KAAK,EAAE,sBAAsB;QAC7B,WAAW,EAAE,oDAAoD;QACjE,QAAQ,EAAE,kBAAkB;KAC7B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE;QAC/B,SAAS,EAAE,WAAW,EAAE;QACxB,WAAW,EAAE,OAAO,CAAC,OAAO;QAC5B,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,IAAI;QACrC,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,IAAI;QACrD,MAAM,EAAE,UAAU,EAAE;KACrB,CAAC,CACH,CAAC;IAEF,MAAM,CAAC,gBAAgB,CACrB,WAAW,EACX,0BAA0B,EAC1B;QACE,KAAK,EAAE,wBAAwB;QAC/B,WAAW,EAAE,4BAA4B;QACzC,QAAQ,EAAE,kBAAkB;KAC7B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,CACjF,CAAC;IAEF,MAAM,CAAC,gBAAgB,CACrB,SAAS,EACT,wBAAwB,EACxB;QACE,KAAK,EAAE,sBAAsB;QAC7B,WAAW,EAAE,2BAA2B;QACxC,QAAQ,EAAE,kBAAkB;KAC7B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAC9E,CAAC;IAEF,MAAM,CAAC,gBAAgB,CACrB,QAAQ,EACR,uBAAuB,EACvB;QACE,KAAK,EAAE,qBAAqB;QAC5B,WAAW,EAAE,iCAAiC;QAC9C,QAAQ,EAAE,kBAAkB;KAC7B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAC5E,CAAC;IAEF,MAAM,CAAC,gBAAgB,CACrB,WAAW,EACX,0BAA0B,EAC1B;QACE,KAAK,EAAE,wBAAwB;QAC/B,WAAW,EAAE,qCAAqC;QAClD,QAAQ,EAAE,kBAAkB;KAC7B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAClF,CAAC;IAEF,MAAM,CAAC,gBAAgB,CACrB,uBAAuB,EACvB,uCAAuC,EACvC;QACE,KAAK,EAAE,uBAAuB;QAC9B,WAAW,EAAE,iEAAiE;QAC9E,QAAQ,EAAE,yBAAyB;KACpC,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,CAAC,YAAY,CAAC,mBAAmB,CAAC,CAAC,CACtE,CAAC;IAEF,MAAM,CAAC,gBAAgB,CACrB,QAAQ,EACR,uBAAuB,EACvB;QACE,KAAK,EAAE,yBAAyB;QAChC,WAAW,EAAE,qDAAqD;QAClE,QAAQ,EAAE,kBAAkB;KAC7B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,UAAU,EAAE,CAAC,CAC/C,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,GAAQ,EAAE,IAAa;IAC3C,OAAO;QACL,QAAQ,EAAE,CAAC;gBACT,GAAG,EAAE,GAAG,CAAC,IAAI;gBACb,QAAQ,EAAE,kBAAkB;gBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;aACpC,CAAC;KACH,CAAC;AACJ,CAAC;AAED,SAAS,UAAU;IACjB,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;IACjC,OAAO;QACL,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;QACzC,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;QACzC,YAAY,EAAE,MAAM,CAAC,YAAY;KAClC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const emptySchema: z.ZodObject<{}, z.core.$strip>;
|
|
3
|
+
export declare const sandboxNameSchema: z.ZodString;
|
|
4
|
+
export declare const volumeNameSchema: z.ZodString;
|
|
5
|
+
export declare const outputLimitsSchema: z.ZodOptional<z.ZodObject<{
|
|
6
|
+
maxBytes: z.ZodOptional<z.ZodNumber>;
|
|
7
|
+
}, z.core.$strip>>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const emptySchema = z.object({});
|
|
3
|
+
export const sandboxNameSchema = z.string().min(1).max(128).describe("Sandbox name");
|
|
4
|
+
export const volumeNameSchema = z.string().min(1).max(128).describe("Volume name");
|
|
5
|
+
export const outputLimitsSchema = z.object({
|
|
6
|
+
maxBytes: z.number().int().positive().optional().describe("Maximum bytes to return."),
|
|
7
|
+
}).optional();
|
|
8
|
+
//# sourceMappingURL=common.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../src/schemas/common.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAExC,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;AAErF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;AAEnF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;CACtF,CAAC,CAAC,QAAQ,EAAE,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ExecHandle, ExitStatus } from "microsandbox";
|
|
2
|
+
export interface StoredExecEvent {
|
|
3
|
+
index: number;
|
|
4
|
+
event: Record<string, unknown>;
|
|
5
|
+
}
|
|
6
|
+
export declare function createExecSession(handle: ExecHandle, options?: {
|
|
7
|
+
stopSandboxOnExit?: string | null;
|
|
8
|
+
}): Promise<string>;
|
|
9
|
+
export declare function pollExecSession(id: string, cursor?: number, limit?: number): {
|
|
10
|
+
events: StoredExecEvent[];
|
|
11
|
+
nextCursor: number;
|
|
12
|
+
done: boolean;
|
|
13
|
+
exitStatus: ExitStatus | null;
|
|
14
|
+
error: string | null;
|
|
15
|
+
};
|
|
16
|
+
export declare function writeExecSessionStdin(id: string, data: string | Uint8Array, close?: boolean): Promise<void>;
|
|
17
|
+
export declare function signalExecSession(id: string, signal: number): Promise<void>;
|
|
18
|
+
export declare function killExecSession(id: string): Promise<void>;
|
|
19
|
+
export declare function closeExecSession(id: string): Promise<void>;
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import { Sandbox } from "microsandbox";
|
|
3
|
+
import { getServerConfig } from "../config.js";
|
|
4
|
+
const sessions = new Map();
|
|
5
|
+
export async function createExecSession(handle, options = {}) {
|
|
6
|
+
cleanupExecSessions();
|
|
7
|
+
const id = crypto.randomUUID();
|
|
8
|
+
const stdin = await handle.takeStdin();
|
|
9
|
+
const session = {
|
|
10
|
+
id,
|
|
11
|
+
handle,
|
|
12
|
+
stdin,
|
|
13
|
+
stopSandboxOnExit: options.stopSandboxOnExit ?? null,
|
|
14
|
+
events: [],
|
|
15
|
+
done: false,
|
|
16
|
+
exitStatus: null,
|
|
17
|
+
error: null,
|
|
18
|
+
createdAt: new Date(),
|
|
19
|
+
updatedAt: new Date(),
|
|
20
|
+
};
|
|
21
|
+
sessions.set(id, session);
|
|
22
|
+
void readEvents(session);
|
|
23
|
+
return id;
|
|
24
|
+
}
|
|
25
|
+
export function pollExecSession(id, cursor = 0, limit = 100) {
|
|
26
|
+
const session = requireExecSession(id);
|
|
27
|
+
touch(session);
|
|
28
|
+
const events = session.events
|
|
29
|
+
.filter((entry) => entry.index >= cursor)
|
|
30
|
+
.slice(0, limit);
|
|
31
|
+
const nextCursor = events.length > 0 ? events[events.length - 1].index + 1 : cursor;
|
|
32
|
+
return {
|
|
33
|
+
events,
|
|
34
|
+
nextCursor,
|
|
35
|
+
done: session.done,
|
|
36
|
+
exitStatus: session.exitStatus,
|
|
37
|
+
error: session.error,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export async function writeExecSessionStdin(id, data, close = false) {
|
|
41
|
+
const session = requireExecSession(id);
|
|
42
|
+
touch(session);
|
|
43
|
+
if (!session.stdin) {
|
|
44
|
+
throw new Error("stdin is not available for this exec session");
|
|
45
|
+
}
|
|
46
|
+
await session.stdin.write(data);
|
|
47
|
+
if (close) {
|
|
48
|
+
await session.stdin.close();
|
|
49
|
+
session.stdin = null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export async function signalExecSession(id, signal) {
|
|
53
|
+
const session = requireExecSession(id);
|
|
54
|
+
touch(session);
|
|
55
|
+
await session.handle.signal(signal);
|
|
56
|
+
}
|
|
57
|
+
export async function killExecSession(id) {
|
|
58
|
+
const session = requireExecSession(id);
|
|
59
|
+
touch(session);
|
|
60
|
+
await session.handle.kill();
|
|
61
|
+
}
|
|
62
|
+
export async function closeExecSession(id) {
|
|
63
|
+
const session = requireExecSession(id);
|
|
64
|
+
sessions.delete(id);
|
|
65
|
+
if (session.stdin)
|
|
66
|
+
await session.stdin.close();
|
|
67
|
+
await session.handle[Symbol.asyncDispose]();
|
|
68
|
+
}
|
|
69
|
+
function requireExecSession(id) {
|
|
70
|
+
cleanupExecSessions();
|
|
71
|
+
const session = sessions.get(id);
|
|
72
|
+
if (!session)
|
|
73
|
+
throw new Error(`exec session not found: ${id}`);
|
|
74
|
+
return session;
|
|
75
|
+
}
|
|
76
|
+
async function readEvents(session) {
|
|
77
|
+
try {
|
|
78
|
+
for (;;) {
|
|
79
|
+
const event = await session.handle.recv();
|
|
80
|
+
if (event === null) {
|
|
81
|
+
session.done = true;
|
|
82
|
+
session.updatedAt = new Date();
|
|
83
|
+
await stopSandboxIfNeeded(session);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (event.kind === "exited") {
|
|
87
|
+
session.exitStatus = {
|
|
88
|
+
code: event.code,
|
|
89
|
+
success: event.code === 0,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
session.events.push({
|
|
93
|
+
index: session.events.length,
|
|
94
|
+
event: serializeExecEvent(event),
|
|
95
|
+
});
|
|
96
|
+
session.updatedAt = new Date();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
session.error = error instanceof Error ? error.message : String(error);
|
|
101
|
+
session.done = true;
|
|
102
|
+
session.updatedAt = new Date();
|
|
103
|
+
await stopSandboxIfNeeded(session);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function serializeExecEvent(event) {
|
|
107
|
+
switch (event.kind) {
|
|
108
|
+
case "stdout":
|
|
109
|
+
case "stderr":
|
|
110
|
+
return {
|
|
111
|
+
kind: event.kind,
|
|
112
|
+
data: Buffer.from(event.data).toString("utf8"),
|
|
113
|
+
};
|
|
114
|
+
default:
|
|
115
|
+
return event;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function touch(session) {
|
|
119
|
+
session.updatedAt = new Date();
|
|
120
|
+
}
|
|
121
|
+
function cleanupExecSessions() {
|
|
122
|
+
const ttl = getServerConfig().sessionTtlMs;
|
|
123
|
+
const now = Date.now();
|
|
124
|
+
for (const [id, session] of sessions) {
|
|
125
|
+
if (now - session.updatedAt.getTime() > ttl) {
|
|
126
|
+
sessions.delete(id);
|
|
127
|
+
if (session.stopSandboxOnExit) {
|
|
128
|
+
void stopSandboxByName(session.stopSandboxOnExit);
|
|
129
|
+
}
|
|
130
|
+
void session.handle[Symbol.asyncDispose]();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
async function stopSandboxIfNeeded(session) {
|
|
135
|
+
if (!session.stopSandboxOnExit)
|
|
136
|
+
return;
|
|
137
|
+
const name = session.stopSandboxOnExit;
|
|
138
|
+
session.stopSandboxOnExit = null;
|
|
139
|
+
await stopSandboxByName(name);
|
|
140
|
+
}
|
|
141
|
+
async function stopSandboxByName(name) {
|
|
142
|
+
try {
|
|
143
|
+
const handle = await Sandbox.get(name);
|
|
144
|
+
if (handle.status === "running")
|
|
145
|
+
await handle.stop();
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
// Best-effort cleanup for sandboxes started only to host an exec session.
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=exec-sessions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec-sessions.js","sourceRoot":"","sources":["../../src/state/exec-sessions.ts"],"names":[],"mappings":"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"}
|