npm package: @sapiom/sandbox
Description: Sandbox environment management for Sapiom SDK
Latest version: 0.7.0

# @sapiom/sandbox

Sandbox environment management for the Sapiom SDK. Create isolated execution environments, manage files, run commands, and stream output in real time.

## Installation

```bash
npm install @sapiom/sandbox
# or
pnpm add @sapiom/sandbox
```

## Quickstart

```typescript
import { SapiomSandbox } from "@sapiom/sandbox";

// Create a sandbox (uses SAPIOM_API_KEY env var by default)
const sandbox = await SapiomSandbox.create({ name: "my-sandbox" });

// Write a file
await sandbox.writeFile("hello.py", 'print("Hello from the sandbox!")');

// Execute a command and wait for completion
const result = await sandbox.exec("python hello.py");
console.log(result.stdout); // "Hello from the sandbox!"

// Stream output from a long-running process
const proc = await sandbox.execStream("node runner.js");
for await (const line of proc.output) {
  console.log(`[${line.stream}] ${line.data}`);
}
console.log("exit code:", proc.exitCode);

// Clean up
await sandbox.destroy();
```

## API

### `SapiomSandbox.create(opts)`

Creates a new sandbox and returns a handle for interacting with it.

```typescript
const sandbox = await SapiomSandbox.create({
  name: "my-sandbox",
  tier: "m",
  ttl: "1h",
  image: "python:3.12",
  envs: { NODE_ENV: "production" },
});
```

**Options:**

| Option    | Type                     | Required | Description                                           |
|-----------|--------------------------|----------|-------------------------------------------------------|
| `name`    | `string`                 | Yes      | Sandbox name (lowercase alphanumeric + hyphens, 2-63 chars) |
| `apiKey`  | `string`                 | No       | Sapiom API key. Falls back to `SAPIOM_API_KEY` env var |
| `baseUrl` | `string`                 | No       | Override the sandbox service URL                       |
| `fetch`   | `typeof fetch`           | No       | Pre-configured fetch function (overrides `apiKey`)     |
| `tier`    | `SandboxTier`            | No       | Memory tier: `'xs'`, `'s'`, `'m'`, `'l'`, `'xl'` (default `'s'`) |
| `ttl`     | `string`                 | No       | Time-to-live (e.g. `'1h'`, `'24h'`, `'7d'`)           |
| `envs`    | `Record<string, string>` | No       | Environment variables                                  |
| `port`    | `number`                 | No       | Single port to expose (mutually exclusive with `ports`) |
| `ports`   | `PortSpec[]`             | No       | Array of port specs to expose (mutually exclusive with `port`) |
| `image`   | `string`                 | No       | Pre-built Docker image for instant creation             |

### `sandbox.writeFile(path, content)`

Writes a file relative to the sandbox's workspace root.

```typescript
await sandbox.writeFile("src/index.ts", 'console.log("hi")');
```

### `sandbox.readFile(path)`

Reads a file relative to the sandbox's workspace root and returns its content as a string.

```typescript
const content = await sandbox.readFile("src/index.ts");
```

### `sandbox.exec(command, opts?)`

Executes a shell command inside the sandbox. By default waits for the process to finish.

```typescript
// Wait for completion (default)
const result = await sandbox.exec("npm install");
console.log(result.exitCode); // 0
console.log(result.stdout);
console.log(result.stderr);

// Fire-and-forget
const bg = await sandbox.exec("npm start", { waitForCompletion: false });
console.log(bg.pid);

// Check on it later
const status = await sandbox.getProcess(bg.pid);
console.log(status.completed, status.exitCode);

// Or wait for it to finish
const final = await sandbox.waitForProcess(bg.pid);
console.log(final.exitCode);
```

**Options:**

| Option               | Type                     | Default | Description                                      |
|----------------------|--------------------------|---------|--------------------------------------------------|
| `cwd`                | `string`                 | —       | Working directory (resolved relative to workspaceRoot) |
| `env`                | `Record<string, string>` | —       | Environment variables for the process             |
| `waitForCompletion`  | `boolean`                | `true`  | Wait for the process to finish                    |
| `pollInterval`       | `number`                 | `1000`  | Polling interval in ms                            |
| `timeout`            | `number`                 | `60000` | Timeout in ms when waiting                        |
| `signal`             | `AbortSignal`            | —       | Signal to cancel the operation                    |

### `sandbox.execStream(command, opts?)`

Executes a command and streams output in real time via an async iterable. Ideal for long-running processes like AI agent runs.

```typescript
const proc = await sandbox.execStream("node agent.js");
for await (const line of proc.output) {
  // line.stream is 'stdout' or 'stderr'
  process.stdout.write(line.data);
}
console.log("exit code:", proc.exitCode);
```

Supports cancellation via `AbortSignal`:

```typescript
const controller = new AbortController();
const proc = await sandbox.execStream("long-task", {
  signal: controller.signal,
});

setTimeout(() => controller.abort(), 30_000);

for await (const line of proc.output) {
  console.log(line.data);
}
```

**Options:**

| Option    | Type                     | Default | Description                                      |
|-----------|--------------------------|---------|--------------------------------------------------|
| `cwd`     | `string`                 | —       | Working directory (resolved relative to workspaceRoot) |
| `env`     | `Record<string, string>` | —       | Environment variables for the process             |
| `signal`  | `AbortSignal`            | —       | Signal to cancel the operation                    |

### `sandbox.getProcess(pid)`

Gets the current status of a process by PID.

```typescript
const status = await sandbox.getProcess(pid);
console.log(status.completed, status.exitCode);
```

### `sandbox.waitForProcess(pid, opts?)`

Waits for a process to complete by polling its status. Returns the same `ExecResult` as `exec()`.

```typescript
const result = await sandbox.waitForProcess(pid, { timeout: 120_000 });
console.log(result.exitCode, result.stdout);
```

### `sandbox.destroy()`

Destroys the sandbox and releases all associated resources.

```typescript
await sandbox.destroy();
```

## Properties

| Property                | Type     | Description                                  |
|-------------------------|----------|----------------------------------------------|
| `sandbox.name`          | `string` | Sandbox identifier                           |
| `sandbox.workspaceRoot` | `string` | Absolute workspace root path in the sandbox  |

## License

MIT