microsandbox 0.1.0 → 0.3.6
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 +368 -14
- package/index.cjs +609 -0
- package/index.d.cts +751 -0
- package/index.mjs +21 -0
- package/package.json +31 -30
- package/postinstall.js +144 -0
- package/dist/index.d.ts +0 -12
- package/dist/index.js +0 -19
package/index.d.cts
ADDED
|
@@ -0,0 +1,751 @@
|
|
|
1
|
+
/* auto-generated by NAPI-RS */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
/**
|
|
4
|
+
* Handle for a streaming command execution.
|
|
5
|
+
*
|
|
6
|
+
* Use `recv()` to get events one at a time, or iterate with a loop:
|
|
7
|
+
* ```js
|
|
8
|
+
* const handle = await sandbox.execStream("tail", ["-f", "/var/log/app.log"]);
|
|
9
|
+
* let event;
|
|
10
|
+
* while ((event = await handle.recv()) !== null) {
|
|
11
|
+
* if (event.eventType === "stdout") process.stdout.write(event.data);
|
|
12
|
+
* }
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export declare class ExecHandle {
|
|
16
|
+
/** Get the correlation ID for this execution. */
|
|
17
|
+
get id(): Promise<string>
|
|
18
|
+
/** Receive the next event. Returns `null` when the stream ends. */
|
|
19
|
+
recv(): Promise<ExecEvent | null>
|
|
20
|
+
/** Take the stdin writer. Can only be called once; returns `null` on subsequent calls. */
|
|
21
|
+
takeStdin(): Promise<ExecSink | null>
|
|
22
|
+
/** Wait for the process to exit and return the exit status. */
|
|
23
|
+
wait(): Promise<ExitStatus>
|
|
24
|
+
/** Wait for completion and collect all output. */
|
|
25
|
+
collect(): Promise<ExecOutput>
|
|
26
|
+
/** Send a signal to the running process. */
|
|
27
|
+
signal(signal: number): Promise<void>
|
|
28
|
+
/** Kill the running process (SIGKILL). */
|
|
29
|
+
kill(): Promise<void>
|
|
30
|
+
}
|
|
31
|
+
export type JsExecHandle = ExecHandle
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Output of a completed command execution.
|
|
35
|
+
*
|
|
36
|
+
* Provides both string and raw byte access to stdout/stderr:
|
|
37
|
+
* ```js
|
|
38
|
+
* const output = await sandbox.shell("echo hello");
|
|
39
|
+
* console.log(output.stdout()); // "hello
|
|
40
|
+
"
|
|
41
|
+
* console.log(output.stdoutBytes()); // <Buffer 68 65 6c 6c 6f 0a>
|
|
42
|
+
* console.log(output.code); // 0
|
|
43
|
+
* console.log(output.success); // true
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare class ExecOutput {
|
|
47
|
+
/** Exit code of the process. */
|
|
48
|
+
get code(): number
|
|
49
|
+
/** Whether the process exited successfully (code == 0). */
|
|
50
|
+
get success(): boolean
|
|
51
|
+
/** Get stdout as a UTF-8 string. */
|
|
52
|
+
stdout(): string
|
|
53
|
+
/** Get stderr as a UTF-8 string. */
|
|
54
|
+
stderr(): string
|
|
55
|
+
/** Get stdout as raw bytes. */
|
|
56
|
+
stdoutBytes(): Buffer
|
|
57
|
+
/** Get stderr as raw bytes. */
|
|
58
|
+
stderrBytes(): Buffer
|
|
59
|
+
/** Get the exit status. */
|
|
60
|
+
status(): ExitStatus
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Stdin writer for a running process. */
|
|
64
|
+
export declare class ExecSink {
|
|
65
|
+
/** Write data to the process stdin. */
|
|
66
|
+
write(data: Buffer): Promise<void>
|
|
67
|
+
/** Close stdin (sends EOF to the process). */
|
|
68
|
+
close(): Promise<void>
|
|
69
|
+
}
|
|
70
|
+
export type JsExecSink = ExecSink
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Factory for creating volume mount configurations.
|
|
74
|
+
*
|
|
75
|
+
* ```js
|
|
76
|
+
* import { Mount, Sandbox } from 'microsandbox'
|
|
77
|
+
*
|
|
78
|
+
* const sb = await Sandbox.create({
|
|
79
|
+
* name: "worker",
|
|
80
|
+
* image: "python:3.12",
|
|
81
|
+
* volumes: {
|
|
82
|
+
* "/app/src": Mount.bind("./src", { readonly: true }),
|
|
83
|
+
* "/data": Mount.named("my-data"),
|
|
84
|
+
* "/tmp": Mount.tmpfs({ sizeMib: 100 }),
|
|
85
|
+
* },
|
|
86
|
+
* })
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
export declare class Mount {
|
|
90
|
+
/** Create a bind mount (host directory → guest path). */
|
|
91
|
+
static bind(path: string, opts?: MountOptions | undefined | null): MountConfig
|
|
92
|
+
/** Create a named volume mount. */
|
|
93
|
+
static named(name: string, opts?: MountOptions | undefined | null): MountConfig
|
|
94
|
+
/** Create a tmpfs (in-memory) mount. */
|
|
95
|
+
static tmpfs(opts?: TmpfsOptions | undefined | null): MountConfig
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Factory for creating network policy configurations.
|
|
100
|
+
*
|
|
101
|
+
* ```js
|
|
102
|
+
* import { NetworkPolicy, Sandbox } from 'microsandbox'
|
|
103
|
+
*
|
|
104
|
+
* const sb = await Sandbox.create({
|
|
105
|
+
* name: "worker",
|
|
106
|
+
* image: "python:3.12",
|
|
107
|
+
* network: NetworkPolicy.publicOnly(),
|
|
108
|
+
* })
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
export declare class NetworkPolicy {
|
|
112
|
+
/** No network access at all. */
|
|
113
|
+
static none(): NetworkConfig
|
|
114
|
+
/** Public internet only — blocks private ranges (default). */
|
|
115
|
+
static publicOnly(): NetworkConfig
|
|
116
|
+
/** Unrestricted network access. */
|
|
117
|
+
static allowAll(): NetworkConfig
|
|
118
|
+
}
|
|
119
|
+
export type JsNetworkPolicy = NetworkPolicy
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Factory for creating rootfs patch configurations.
|
|
123
|
+
*
|
|
124
|
+
* ```js
|
|
125
|
+
* import { Patch, Sandbox } from 'microsandbox'
|
|
126
|
+
*
|
|
127
|
+
* const sb = await Sandbox.create({
|
|
128
|
+
* name: "worker",
|
|
129
|
+
* image: "alpine",
|
|
130
|
+
* patches: [
|
|
131
|
+
* Patch.text("/etc/greeting.txt", "Hello!
|
|
132
|
+
"),
|
|
133
|
+
* Patch.mkdir("/app", { mode: 0o755 }),
|
|
134
|
+
* Patch.append("/etc/hosts", "127.0.0.1 myapp.local
|
|
135
|
+
"),
|
|
136
|
+
* Patch.copyFile("./config.json", "/app/config.json"),
|
|
137
|
+
* Patch.copyDir("./scripts", "/app/scripts"),
|
|
138
|
+
* Patch.symlink("/usr/bin/python3", "/usr/bin/python"),
|
|
139
|
+
* Patch.remove("/etc/motd"),
|
|
140
|
+
* ],
|
|
141
|
+
* })
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
export declare class Patch {
|
|
145
|
+
/** Write text content to a file in the guest filesystem. */
|
|
146
|
+
static text(path: string, content: string, opts?: PatchOptions | undefined | null): PatchConfig
|
|
147
|
+
/** Create a directory in the guest filesystem (idempotent). */
|
|
148
|
+
static mkdir(path: string, opts?: PatchOptions | undefined | null): PatchConfig
|
|
149
|
+
/** Append content to an existing file in the guest filesystem. */
|
|
150
|
+
static append(path: string, content: string): PatchConfig
|
|
151
|
+
/** Copy a file from the host into the guest filesystem. */
|
|
152
|
+
static copyFile(src: string, dst: string, opts?: PatchOptions | undefined | null): PatchConfig
|
|
153
|
+
/** Copy a directory from the host into the guest filesystem. */
|
|
154
|
+
static copyDir(src: string, dst: string, opts?: PatchReplaceOptions | undefined | null): PatchConfig
|
|
155
|
+
/** Create a symlink in the guest filesystem. */
|
|
156
|
+
static symlink(target: string, link: string, opts?: PatchReplaceOptions | undefined | null): PatchConfig
|
|
157
|
+
/** Remove a file or directory from the guest filesystem (idempotent). */
|
|
158
|
+
static remove(path: string): PatchConfig
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* A running sandbox instance.
|
|
163
|
+
*
|
|
164
|
+
* Created via `Sandbox.create()` or `Sandbox.start()`. Holds a live connection
|
|
165
|
+
* to the guest VM and can execute commands, access the filesystem, and query metrics.
|
|
166
|
+
*/
|
|
167
|
+
export declare class Sandbox {
|
|
168
|
+
/** Create a sandbox from configuration (attached mode — stops on GC/process exit). */
|
|
169
|
+
static create(config: SandboxConfig): Promise<Sandbox>
|
|
170
|
+
/** Create a sandbox that survives the parent process (detached mode). */
|
|
171
|
+
static createDetached(config: SandboxConfig): Promise<Sandbox>
|
|
172
|
+
/** Start an existing stopped sandbox (attached mode). */
|
|
173
|
+
static start(name: string): Promise<Sandbox>
|
|
174
|
+
/** Start an existing stopped sandbox (detached mode). */
|
|
175
|
+
static startDetached(name: string): Promise<Sandbox>
|
|
176
|
+
/** Get a lightweight handle to an existing sandbox. */
|
|
177
|
+
static get(name: string): Promise<JsSandboxHandle>
|
|
178
|
+
/** List all sandboxes. */
|
|
179
|
+
static list(): Promise<Array<SandboxInfo>>
|
|
180
|
+
/** Remove a stopped sandbox from the database. */
|
|
181
|
+
static remove(name: string): Promise<void>
|
|
182
|
+
/** Sandbox name. */
|
|
183
|
+
get name(): Promise<string>
|
|
184
|
+
/** Whether this handle owns the sandbox lifecycle (attached mode). */
|
|
185
|
+
get ownsLifecycle(): Promise<boolean>
|
|
186
|
+
/** Execute a command and wait for completion. */
|
|
187
|
+
exec(cmd: string, args?: Array<string> | undefined | null): Promise<ExecOutput>
|
|
188
|
+
/** Execute a command with full configuration and wait for completion. */
|
|
189
|
+
execWithConfig(config: ExecConfig): Promise<ExecOutput>
|
|
190
|
+
/** Execute a command with streaming I/O. */
|
|
191
|
+
execStream(cmd: string, args?: Array<string> | undefined | null): Promise<ExecHandle>
|
|
192
|
+
/** Execute a shell command using the sandbox's configured shell. */
|
|
193
|
+
shell(script: string): Promise<ExecOutput>
|
|
194
|
+
/** Execute a shell command with streaming I/O. */
|
|
195
|
+
shellStream(script: string): Promise<ExecHandle>
|
|
196
|
+
/** Get a filesystem handle for operations on the running sandbox. */
|
|
197
|
+
fs(): SandboxFs
|
|
198
|
+
/** Get point-in-time resource metrics. */
|
|
199
|
+
metrics(): Promise<SandboxMetrics>
|
|
200
|
+
/** Stop the sandbox gracefully (SIGTERM). */
|
|
201
|
+
stop(): Promise<void>
|
|
202
|
+
/** Stop and wait for exit, returning the exit status. */
|
|
203
|
+
stopAndWait(): Promise<ExitStatus>
|
|
204
|
+
/** Kill the sandbox immediately (SIGKILL). */
|
|
205
|
+
kill(): Promise<void>
|
|
206
|
+
/** Graceful drain (SIGUSR1 — for load balancing). */
|
|
207
|
+
drain(): Promise<void>
|
|
208
|
+
/** Wait for the sandbox process to exit. */
|
|
209
|
+
wait(): Promise<ExitStatus>
|
|
210
|
+
/** Detach from the sandbox — it will continue running after this handle is dropped. */
|
|
211
|
+
detach(): Promise<void>
|
|
212
|
+
/** Remove the persisted database record after stopping. */
|
|
213
|
+
removePersisted(): Promise<void>
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/** Filesystem operations on a running sandbox (via agent protocol). */
|
|
217
|
+
export declare class SandboxFs {
|
|
218
|
+
/** Read a file as a Buffer. */
|
|
219
|
+
read(path: string): Promise<Buffer>
|
|
220
|
+
/** Read a file as a UTF-8 string. */
|
|
221
|
+
readString(path: string): Promise<string>
|
|
222
|
+
/** Write data to a file (accepts Buffer or string). */
|
|
223
|
+
write(path: string, data: Buffer): Promise<void>
|
|
224
|
+
/** List directory contents. */
|
|
225
|
+
list(path: string): Promise<Array<FsEntry>>
|
|
226
|
+
/** Create a directory. */
|
|
227
|
+
mkdir(path: string): Promise<void>
|
|
228
|
+
/** Remove a directory. */
|
|
229
|
+
removeDir(path: string): Promise<void>
|
|
230
|
+
/** Remove a file. */
|
|
231
|
+
remove(path: string): Promise<void>
|
|
232
|
+
/** Copy a file within the sandbox. */
|
|
233
|
+
copy(from: string, to: string): Promise<void>
|
|
234
|
+
/** Rename a file within the sandbox. */
|
|
235
|
+
rename(from: string, to: string): Promise<void>
|
|
236
|
+
/** Get file or directory metadata. */
|
|
237
|
+
stat(path: string): Promise<FsMetadata>
|
|
238
|
+
/** Check if a path exists. */
|
|
239
|
+
exists(path: string): Promise<boolean>
|
|
240
|
+
/** Copy a file from the host into the sandbox. */
|
|
241
|
+
copyFromHost(hostPath: string, guestPath: string): Promise<void>
|
|
242
|
+
/** Copy a file from the sandbox to the host. */
|
|
243
|
+
copyToHost(guestPath: string, hostPath: string): Promise<void>
|
|
244
|
+
}
|
|
245
|
+
export type JsSandboxFs = SandboxFs
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* A lightweight handle to a sandbox from the database.
|
|
249
|
+
*
|
|
250
|
+
* Does NOT hold a live connection — use `connect()` or `start()` to get a live `Sandbox`.
|
|
251
|
+
*/
|
|
252
|
+
export declare class SandboxHandle {
|
|
253
|
+
/** Sandbox name. */
|
|
254
|
+
get name(): string
|
|
255
|
+
/** Status at time of query: "running", "stopped", "crashed", or "draining". */
|
|
256
|
+
get status(): string
|
|
257
|
+
/** Raw config JSON string from the database. */
|
|
258
|
+
get configJson(): string
|
|
259
|
+
/** Creation timestamp as ms since Unix epoch. */
|
|
260
|
+
get createdAt(): number | null
|
|
261
|
+
/** Last update timestamp as ms since Unix epoch. */
|
|
262
|
+
get updatedAt(): number | null
|
|
263
|
+
/** Get point-in-time metrics from the database. */
|
|
264
|
+
metrics(): Promise<SandboxMetrics>
|
|
265
|
+
/** Start the sandbox (attached mode) — returns a live Sandbox handle. */
|
|
266
|
+
start(): Promise<Sandbox>
|
|
267
|
+
/** Start the sandbox (detached mode). */
|
|
268
|
+
startDetached(): Promise<Sandbox>
|
|
269
|
+
/** Connect to an already-running sandbox (no lifecycle ownership). */
|
|
270
|
+
connect(): Promise<Sandbox>
|
|
271
|
+
/** Stop the sandbox (SIGTERM). */
|
|
272
|
+
stop(): Promise<void>
|
|
273
|
+
/** Kill the sandbox (SIGKILL). */
|
|
274
|
+
kill(): Promise<void>
|
|
275
|
+
/** Remove the sandbox from the database. */
|
|
276
|
+
remove(): Promise<void>
|
|
277
|
+
}
|
|
278
|
+
export type JsSandboxHandle = SandboxHandle
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Factory for creating secret entries.
|
|
282
|
+
*
|
|
283
|
+
* ```js
|
|
284
|
+
* import { Secret, Sandbox } from 'microsandbox'
|
|
285
|
+
*
|
|
286
|
+
* const sb = await Sandbox.create({
|
|
287
|
+
* name: "agent",
|
|
288
|
+
* image: "python:3.12",
|
|
289
|
+
* secrets: [
|
|
290
|
+
* Secret.env("OPENAI_API_KEY", {
|
|
291
|
+
* value: process.env.OPENAI_API_KEY,
|
|
292
|
+
* allowHosts: ["api.openai.com"],
|
|
293
|
+
* }),
|
|
294
|
+
* ],
|
|
295
|
+
* })
|
|
296
|
+
* ```
|
|
297
|
+
*/
|
|
298
|
+
export declare class Secret {
|
|
299
|
+
/** Create a secret bound to an environment variable. */
|
|
300
|
+
static env(envVar: string, opts: SecretEnvOptions): SecretEntry
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/** A named persistent volume. */
|
|
304
|
+
export declare class Volume {
|
|
305
|
+
/** Create a new named volume. */
|
|
306
|
+
static create(config: VolumeConfig): Promise<Volume>
|
|
307
|
+
/** Get a lightweight handle to an existing volume. */
|
|
308
|
+
static get(name: string): Promise<VolumeHandle>
|
|
309
|
+
/** List all volumes. */
|
|
310
|
+
static list(): Promise<Array<VolumeInfo>>
|
|
311
|
+
/** Remove a volume. */
|
|
312
|
+
static remove(name: string): Promise<void>
|
|
313
|
+
/** Volume name. */
|
|
314
|
+
get name(): string
|
|
315
|
+
/** Host path of the volume. */
|
|
316
|
+
get path(): string
|
|
317
|
+
}
|
|
318
|
+
export type JsVolume = Volume
|
|
319
|
+
|
|
320
|
+
/** A lightweight handle to a volume from the database. */
|
|
321
|
+
export declare class VolumeHandle {
|
|
322
|
+
/** Volume name. */
|
|
323
|
+
get name(): string
|
|
324
|
+
/** Size quota in MiB, if set. */
|
|
325
|
+
get quotaMib(): number | null
|
|
326
|
+
/** Used bytes on disk. */
|
|
327
|
+
get usedBytes(): number
|
|
328
|
+
/** Key-value labels. */
|
|
329
|
+
get labels(): Record<string, string>
|
|
330
|
+
/** Creation timestamp as ms since epoch. */
|
|
331
|
+
get createdAt(): number | null
|
|
332
|
+
/** Remove this volume. */
|
|
333
|
+
remove(): Promise<void>
|
|
334
|
+
}
|
|
335
|
+
export type JsVolumeHandle = VolumeHandle
|
|
336
|
+
|
|
337
|
+
/** Get metrics for all running sandboxes. */
|
|
338
|
+
export declare function allSandboxMetrics(): Promise<Record<string, SandboxMetrics>>
|
|
339
|
+
|
|
340
|
+
/** Configuration for command execution. */
|
|
341
|
+
export interface ExecConfig {
|
|
342
|
+
/** Command to execute. */
|
|
343
|
+
cmd: string
|
|
344
|
+
/** Command arguments. */
|
|
345
|
+
args?: Array<string>
|
|
346
|
+
/** Working directory inside the sandbox. */
|
|
347
|
+
cwd?: string
|
|
348
|
+
/** User to run as. */
|
|
349
|
+
user?: string
|
|
350
|
+
/** Environment variables. */
|
|
351
|
+
env?: Record<string, string>
|
|
352
|
+
/** Timeout in milliseconds. */
|
|
353
|
+
timeoutMs?: number
|
|
354
|
+
/** Stdin mode: "null" (default), "pipe", or a string to send as stdin bytes. */
|
|
355
|
+
stdin?: string
|
|
356
|
+
/** Enable pseudo-TTY. */
|
|
357
|
+
tty?: boolean
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/** Execution event emitted by `ExecHandle.recv()`. */
|
|
361
|
+
export interface ExecEvent {
|
|
362
|
+
/** "started", "stdout", "stderr", or "exited". */
|
|
363
|
+
eventType: string
|
|
364
|
+
/** Process ID (only for "started" events). */
|
|
365
|
+
pid?: number
|
|
366
|
+
/** Output data (only for "stdout" and "stderr" events). */
|
|
367
|
+
data?: Buffer
|
|
368
|
+
/** Exit code (only for "exited" events). */
|
|
369
|
+
code?: number
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/** Execution event type. */
|
|
373
|
+
export declare const enum ExecEventType {
|
|
374
|
+
Started = 'started',
|
|
375
|
+
Stdout = 'stdout',
|
|
376
|
+
Stderr = 'stderr',
|
|
377
|
+
Exited = 'exited'
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/** Process exit status. */
|
|
381
|
+
export interface ExitStatus {
|
|
382
|
+
code: number
|
|
383
|
+
success: boolean
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/** Filesystem entry metadata returned by `fs.list()`. */
|
|
387
|
+
export interface FsEntry {
|
|
388
|
+
path: string
|
|
389
|
+
/** "file", "directory", "symlink", or "other". */
|
|
390
|
+
kind: string
|
|
391
|
+
size: number
|
|
392
|
+
mode: number
|
|
393
|
+
modified?: number
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/** Filesystem entry kind. */
|
|
397
|
+
export declare const enum FsEntryKind {
|
|
398
|
+
File = 'file',
|
|
399
|
+
Directory = 'directory',
|
|
400
|
+
Symlink = 'symlink',
|
|
401
|
+
Other = 'other'
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/** Filesystem metadata returned by `fs.stat()`. */
|
|
405
|
+
export interface FsMetadata {
|
|
406
|
+
/** "file", "directory", "symlink", or "other". */
|
|
407
|
+
kind: string
|
|
408
|
+
size: number
|
|
409
|
+
mode: number
|
|
410
|
+
readonly: boolean
|
|
411
|
+
modified?: number
|
|
412
|
+
created?: number
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/** Download and install msb + libkrunfw to ~/.microsandbox/. */
|
|
416
|
+
export declare function install(): Promise<void>
|
|
417
|
+
|
|
418
|
+
/** Check if msb and libkrunfw are installed and available. */
|
|
419
|
+
export declare function isInstalled(): boolean
|
|
420
|
+
|
|
421
|
+
/** Log level for sandbox process output. */
|
|
422
|
+
export declare const enum LogLevel {
|
|
423
|
+
Trace = 'trace',
|
|
424
|
+
Debug = 'debug',
|
|
425
|
+
Info = 'info',
|
|
426
|
+
Warn = 'warn',
|
|
427
|
+
Error = 'error'
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/** Volume mount configuration. */
|
|
431
|
+
export interface MountConfig {
|
|
432
|
+
/** Mount a host directory. Mutually exclusive with `named` and `tmpfs`. */
|
|
433
|
+
bind?: string
|
|
434
|
+
/** Mount a named volume. Mutually exclusive with `bind` and `tmpfs`. */
|
|
435
|
+
named?: string
|
|
436
|
+
/** Use tmpfs (memory-backed). Mutually exclusive with `bind` and `named`. */
|
|
437
|
+
tmpfs?: boolean
|
|
438
|
+
/** Read-only mount. */
|
|
439
|
+
readonly?: boolean
|
|
440
|
+
/** Size limit in MiB (for tmpfs). */
|
|
441
|
+
sizeMib?: number
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/** Options for bind and named volume mounts. */
|
|
445
|
+
export interface MountOptions {
|
|
446
|
+
/** Read-only mount. */
|
|
447
|
+
readonly?: boolean
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/** Network configuration. */
|
|
451
|
+
export interface NetworkConfig {
|
|
452
|
+
/**
|
|
453
|
+
* Preset policy: "public-only" (default), "allow-all", or "none".
|
|
454
|
+
* Ignored if `rules` is provided.
|
|
455
|
+
*/
|
|
456
|
+
policy?: string
|
|
457
|
+
/** Custom policy rules (first match wins). Overrides `policy` preset. */
|
|
458
|
+
rules?: Array<PolicyRule>
|
|
459
|
+
/** Default action when no rule matches: "allow" or "deny". */
|
|
460
|
+
defaultAction?: string
|
|
461
|
+
/** Block specific domains via DNS interception. */
|
|
462
|
+
blockDomains?: Array<string>
|
|
463
|
+
/** Block domain suffixes via DNS interception. */
|
|
464
|
+
blockDomainSuffixes?: Array<string>
|
|
465
|
+
/** Enable DNS rebinding protection (default: true). */
|
|
466
|
+
dnsRebindProtection?: boolean
|
|
467
|
+
/** TLS interception configuration. */
|
|
468
|
+
tls?: TlsConfig
|
|
469
|
+
/** Max concurrent connections (default: 256). */
|
|
470
|
+
maxConnections?: number
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/** Rootfs patch applied before VM startup. */
|
|
474
|
+
export interface PatchConfig {
|
|
475
|
+
/** Patch kind: "text", "file", "copyFile", "copyDir", "symlink", "mkdir", "remove", "append". */
|
|
476
|
+
kind: string
|
|
477
|
+
/** Guest path (all kinds except symlink where it's `link`). */
|
|
478
|
+
path?: string
|
|
479
|
+
/** Text content (for "text" and "append" kinds). */
|
|
480
|
+
content?: string
|
|
481
|
+
/** Source host path (for "copyFile" and "copyDir" kinds). */
|
|
482
|
+
src?: string
|
|
483
|
+
/** Destination guest path (for "copyFile" and "copyDir" kinds). */
|
|
484
|
+
dst?: string
|
|
485
|
+
/** Symlink target path (for "symlink" kind). */
|
|
486
|
+
target?: string
|
|
487
|
+
/** Symlink link path (for "symlink" kind). */
|
|
488
|
+
link?: string
|
|
489
|
+
/** File permissions (e.g. 0o644). */
|
|
490
|
+
mode?: number
|
|
491
|
+
/** Allow replacing existing files. */
|
|
492
|
+
replace?: boolean
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
/** Options for `Patch.text()` and `Patch.copyFile()`. */
|
|
496
|
+
export interface PatchOptions {
|
|
497
|
+
/** File permissions (e.g. 0o644). */
|
|
498
|
+
mode?: number
|
|
499
|
+
/** Allow replacing existing files. */
|
|
500
|
+
replace?: boolean
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/** Options for `Patch.copyDir()` and `Patch.symlink()`. */
|
|
504
|
+
export interface PatchReplaceOptions {
|
|
505
|
+
/** Allow replacing existing files/directories. */
|
|
506
|
+
replace?: boolean
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/** Network policy rule action. */
|
|
510
|
+
export declare const enum PolicyAction {
|
|
511
|
+
Allow = 'allow',
|
|
512
|
+
Deny = 'deny'
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/** Network policy rule direction. */
|
|
516
|
+
export declare const enum PolicyDirection {
|
|
517
|
+
Outbound = 'outbound',
|
|
518
|
+
Inbound = 'inbound'
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
/** Network policy rule protocol. */
|
|
522
|
+
export declare const enum PolicyProtocol {
|
|
523
|
+
Tcp = 'tcp',
|
|
524
|
+
Udp = 'udp',
|
|
525
|
+
Icmpv4 = 'icmpv4',
|
|
526
|
+
Icmpv6 = 'icmpv6'
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/** A network policy rule. */
|
|
530
|
+
export interface PolicyRule {
|
|
531
|
+
/** "allow" or "deny". */
|
|
532
|
+
action: string
|
|
533
|
+
/** "outbound" or "inbound". */
|
|
534
|
+
direction?: string
|
|
535
|
+
/**
|
|
536
|
+
* Destination filter. One of:
|
|
537
|
+
* - "*" — any destination
|
|
538
|
+
* - "1.2.3.4/24" — CIDR notation
|
|
539
|
+
* - "example.com" — exact domain
|
|
540
|
+
* - ".example.com" — domain suffix
|
|
541
|
+
* - "loopback", "private", "link-local", "metadata", "multicast" — destination group
|
|
542
|
+
*/
|
|
543
|
+
destination?: string
|
|
544
|
+
/** Protocol filter: "tcp", "udp", "icmpv4", "icmpv6". */
|
|
545
|
+
protocol?: string
|
|
546
|
+
/** Port or port range (e.g. 443 or "8000-9000"). */
|
|
547
|
+
port?: string
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/** Image pull policy. */
|
|
551
|
+
export declare const enum PullPolicy {
|
|
552
|
+
Always = 'always',
|
|
553
|
+
IfMissing = 'if-missing',
|
|
554
|
+
Never = 'never'
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/** Registry credentials for pulling private images. */
|
|
558
|
+
export interface RegistryCredentials {
|
|
559
|
+
username: string
|
|
560
|
+
password: string
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/** Configuration for creating a sandbox. */
|
|
564
|
+
export interface SandboxConfig {
|
|
565
|
+
/** Unique sandbox name. */
|
|
566
|
+
name: string
|
|
567
|
+
/** OCI image ref (e.g. "python:3.12"), host path, or disk image path. */
|
|
568
|
+
image: string
|
|
569
|
+
/** Guest memory in MiB (default: 512). */
|
|
570
|
+
memoryMib?: number
|
|
571
|
+
/** Virtual CPU count (default: 1). */
|
|
572
|
+
cpus?: number
|
|
573
|
+
/** Working directory inside the guest. */
|
|
574
|
+
workdir?: string
|
|
575
|
+
/** Default shell binary path. */
|
|
576
|
+
shell?: string
|
|
577
|
+
/** Override image entrypoint. */
|
|
578
|
+
entrypoint?: Array<string>
|
|
579
|
+
/** Override image cmd. */
|
|
580
|
+
cmd?: Array<string>
|
|
581
|
+
/** Guest hostname. */
|
|
582
|
+
hostname?: string
|
|
583
|
+
/** User to run as (UID or name). */
|
|
584
|
+
user?: string
|
|
585
|
+
/** Environment variables. */
|
|
586
|
+
env?: Record<string, string>
|
|
587
|
+
/** Named scripts that can be run via `sandbox.run(name)`. */
|
|
588
|
+
scripts?: Record<string, string>
|
|
589
|
+
/** Volume mounts keyed by guest path. */
|
|
590
|
+
volumes?: Record<string, MountConfig>
|
|
591
|
+
/** Rootfs patches applied before boot. */
|
|
592
|
+
patches?: Array<PatchConfig>
|
|
593
|
+
/** Image pull policy: "always", "if-missing", or "never". */
|
|
594
|
+
pullPolicy?: string
|
|
595
|
+
/** Log level: "trace", "debug", "info", "warn", "error". */
|
|
596
|
+
logLevel?: string
|
|
597
|
+
/** Kill any existing sandbox with the same name before creating. */
|
|
598
|
+
replace?: boolean
|
|
599
|
+
/** Suppress log output. */
|
|
600
|
+
quietLogs?: boolean
|
|
601
|
+
/** Arbitrary key-value labels. */
|
|
602
|
+
labels?: Record<string, string>
|
|
603
|
+
/** Signal to send on stop (default: SIGTERM). */
|
|
604
|
+
stopSignal?: string
|
|
605
|
+
/** Maximum run duration in seconds. */
|
|
606
|
+
maxDurationSecs?: number
|
|
607
|
+
/** Registry credentials for pulling private images. */
|
|
608
|
+
registryAuth?: RegistryCredentials
|
|
609
|
+
/** Port mappings: host_port → guest_port (TCP). */
|
|
610
|
+
ports?: Record<string, number>
|
|
611
|
+
/** Network configuration. */
|
|
612
|
+
network?: NetworkConfig
|
|
613
|
+
/**
|
|
614
|
+
* Secret entries. Created with `Secret.env()`.
|
|
615
|
+
*
|
|
616
|
+
* ```js
|
|
617
|
+
* import { Secret } from 'microsandbox'
|
|
618
|
+
* secrets: [
|
|
619
|
+
* Secret.env("OPENAI_API_KEY", { value: "sk-...", allowHosts: ["api.openai.com"] }),
|
|
620
|
+
* ]
|
|
621
|
+
* ```
|
|
622
|
+
*/
|
|
623
|
+
secrets?: Array<SecretEntry>
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
/** Lightweight handle info for a sandbox from the database. */
|
|
627
|
+
export interface SandboxInfo {
|
|
628
|
+
name: string
|
|
629
|
+
/** "running", "stopped", "crashed", or "draining". */
|
|
630
|
+
status: string
|
|
631
|
+
configJson: string
|
|
632
|
+
createdAt?: number
|
|
633
|
+
updatedAt?: number
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
/** Point-in-time resource metrics for a sandbox. */
|
|
637
|
+
export interface SandboxMetrics {
|
|
638
|
+
cpuPercent: number
|
|
639
|
+
memoryBytes: number
|
|
640
|
+
memoryLimitBytes: number
|
|
641
|
+
diskReadBytes: number
|
|
642
|
+
diskWriteBytes: number
|
|
643
|
+
netRxBytes: number
|
|
644
|
+
netTxBytes: number
|
|
645
|
+
/** Uptime in milliseconds. */
|
|
646
|
+
uptimeMs: number
|
|
647
|
+
/** Timestamp as milliseconds since Unix epoch. */
|
|
648
|
+
timestampMs: number
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
/** Sandbox status. */
|
|
652
|
+
export declare const enum SandboxStatus {
|
|
653
|
+
Running = 'running',
|
|
654
|
+
Stopped = 'stopped',
|
|
655
|
+
Crashed = 'crashed',
|
|
656
|
+
Draining = 'draining'
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
/**
|
|
660
|
+
* A secret entry for the `secrets` array on `SandboxConfig`.
|
|
661
|
+
*
|
|
662
|
+
* Created via `Secret.env()`:
|
|
663
|
+
* ```js
|
|
664
|
+
* import { Secret } from 'microsandbox'
|
|
665
|
+
* Secret.env("OPENAI_API_KEY", { value: "sk-...", allowHosts: ["api.openai.com"] })
|
|
666
|
+
* ```
|
|
667
|
+
*/
|
|
668
|
+
export interface SecretEntry {
|
|
669
|
+
/** Environment variable name. */
|
|
670
|
+
envVar: string
|
|
671
|
+
/** The secret value (never enters the sandbox). */
|
|
672
|
+
value: string
|
|
673
|
+
/** Allowed hosts (exact match, e.g. `["api.openai.com"]`). */
|
|
674
|
+
allowHosts?: Array<string>
|
|
675
|
+
/** Allowed host patterns (wildcard, e.g. `["*.openai.com"]`). */
|
|
676
|
+
allowHostPatterns?: Array<string>
|
|
677
|
+
/** Custom placeholder (auto-generated as `$MSB_<ENV_VAR>` if omitted). */
|
|
678
|
+
placeholder?: string
|
|
679
|
+
/** Require verified TLS identity before substitution (default: true). */
|
|
680
|
+
requireTls?: boolean
|
|
681
|
+
/** Violation action: "block", "block-and-log" (default), "block-and-terminate". */
|
|
682
|
+
onViolation?: string
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
/** Options for `Secret.env()`. */
|
|
686
|
+
export interface SecretEnvOptions {
|
|
687
|
+
/** The secret value (never enters the sandbox). */
|
|
688
|
+
value: string
|
|
689
|
+
/** Allowed hosts (exact match, e.g. `["api.openai.com"]`). */
|
|
690
|
+
allowHosts?: Array<string>
|
|
691
|
+
/** Allowed host patterns (wildcard, e.g. `["*.openai.com"]`). */
|
|
692
|
+
allowHostPatterns?: Array<string>
|
|
693
|
+
/** Custom placeholder (auto-generated as `$MSB_<ENV_VAR>` if omitted). */
|
|
694
|
+
placeholder?: string
|
|
695
|
+
/** Require verified TLS identity before substitution (default: true). */
|
|
696
|
+
requireTls?: boolean
|
|
697
|
+
/** Violation action: "block", "block-and-log" (default), "block-and-terminate". */
|
|
698
|
+
onViolation?: string
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
/** TLS interception configuration. */
|
|
702
|
+
export interface TlsConfig {
|
|
703
|
+
/** Domains to bypass (no interception). Supports "*.suffix" wildcards. */
|
|
704
|
+
bypass?: Array<string>
|
|
705
|
+
/** Verify upstream server certificates (default: true). */
|
|
706
|
+
verifyUpstream?: boolean
|
|
707
|
+
/** Ports to intercept (default: [443]). */
|
|
708
|
+
interceptedPorts?: Array<number>
|
|
709
|
+
/** Block QUIC on intercepted ports (default: false). */
|
|
710
|
+
blockQuic?: boolean
|
|
711
|
+
/** Path to custom CA certificate PEM file. */
|
|
712
|
+
caCert?: string
|
|
713
|
+
/** Path to custom CA private key PEM file. */
|
|
714
|
+
caKey?: string
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
/** Options for tmpfs mounts. */
|
|
718
|
+
export interface TmpfsOptions {
|
|
719
|
+
/** Size limit in MiB. */
|
|
720
|
+
sizeMib?: number
|
|
721
|
+
/** Read-only mount. */
|
|
722
|
+
readonly?: boolean
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
/** Action to take when a secret is sent to a disallowed host. */
|
|
726
|
+
export declare const enum ViolationAction {
|
|
727
|
+
/** Silently block the request. */
|
|
728
|
+
Block = 'block',
|
|
729
|
+
/** Block the request and log the violation. */
|
|
730
|
+
BlockAndLog = 'block-and-log',
|
|
731
|
+
/** Block the request and terminate the sandbox. */
|
|
732
|
+
BlockAndTerminate = 'block-and-terminate'
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
/** Volume configuration for creation. */
|
|
736
|
+
export interface VolumeConfig {
|
|
737
|
+
name: string
|
|
738
|
+
/** Size quota in MiB. */
|
|
739
|
+
quotaMib?: number
|
|
740
|
+
/** Arbitrary key-value labels. */
|
|
741
|
+
labels?: Record<string, string>
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
/** Volume handle info from the database. */
|
|
745
|
+
export interface VolumeInfo {
|
|
746
|
+
name: string
|
|
747
|
+
quotaMib?: number
|
|
748
|
+
usedBytes: number
|
|
749
|
+
labels: Record<string, string>
|
|
750
|
+
createdAt?: number
|
|
751
|
+
}
|