Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .env.test.example
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,16 @@ POSTGRES_PORT=5433
POSTGRES_DB=kode_test
POSTGRES_USER=postgres
POSTGRES_PASSWORD=testpass123

# =============================================================================
# E2B Cloud Sandbox (for E2B integration/e2e tests)
# =============================================================================
# E2B API Key - 从 https://e2b.dev/dashboard 获取
# 如果不配置,E2B 相关的 E2E 测试将自动跳过
E2B_API_KEY=replace-with-your-e2b-api-key

# E2B 沙箱模板(可选,默认使用 'base')
E2B_TEMPLATE=base

# E2B 沙箱超时时间(毫秒,可选,默认 300000)
E2B_TIMEOUT_MS=300000
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ test-workspace/
.DS_Store
test-cli.ts
.env.test
.data

# Ignore all markdown files except README.md and files in doc/docs folders
*.md
!README.md
!README.zh-CN.md
!README.en.md
!ROADMAP.md
!doc/**/*.md
!docs/**/*.md
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- **Long-Running & Resumable** - Seven-stage checkpoints with Safe-Fork-Point for crash recovery
- **Multi-Agent Collaboration** - AgentPool, Room messaging, and task delegation
- **Enterprise Persistence** - SQLite/PostgreSQL support with unified WAL
- **Cloud Sandbox** - [E2B](https://e2b.dev) integration for isolated remote code execution
- **Extensible Ecosystem** - MCP tools, custom Providers, Skills system

## Quick Start
Expand Down
1 change: 1 addition & 0 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- **长时运行与恢复** - 七段断点机制,支持 Safe-Fork-Point 崩溃恢复
- **多 Agent 协作** - AgentPool、Room 消息、任务委派
- **企业级持久化** - 支持 SQLite/PostgreSQL,统一 WAL 日志
- **云端沙箱** - 集成 [E2B](https://e2b.dev),提供隔离的远程代码执行环境
- **可扩展生态** - MCP 工具、自定义 Provider、Skills 系统

## 快速开始
Expand Down
198 changes: 198 additions & 0 deletions docs/en/guides/e2b-sandbox.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
# E2B Cloud Sandbox Guide

KODE SDK supports [E2B](https://e2b.dev) as a cloud sandbox backend, providing fully isolated remote Linux environments for AI Agent code execution.

---

## Overview

| Feature | Description |
|---------|-------------|
| **Isolation** | Each sandbox runs in an isolated micro-VM |
| **Startup** | ~150ms to create a full Linux environment |
| **Pre-installed** | Python, Node.js, common system tools |
| **Scalable** | Each Agent gets its own sandbox instance |

### When to Use E2B vs Local Sandbox

| Scenario | Recommended |
|----------|-------------|
| Development/Testing | Local Sandbox |
| Production with untrusted code | E2B |
| Multi-user concurrent agents | E2B |
| Need specific environment (GPU, packages) | E2B (Custom Template) |
| Offline / No internet | Local Sandbox |

---

## Prerequisites

1. Sign up at [e2b.dev](https://e2b.dev)
2. Get your API Key from the Dashboard
3. Set environment variable:

```bash
export E2B_API_KEY=your-api-key
```

---

## Quick Start

### Create and Use a Sandbox

```typescript
import { E2BSandbox } from '@shareai-lab/kode-sdk';

const sandbox = new E2BSandbox({
apiKey: process.env.E2B_API_KEY,
template: 'base',
timeoutMs: 300_000, // 5 minutes
});
await sandbox.init();

// Execute commands
const result = await sandbox.exec('python3 -c "print(1+1)"');
console.log(result.stdout); // "2\n"

// File operations
await sandbox.fs.write('script.py', 'print("hello")');
const content = await sandbox.fs.read('script.py');

// Cleanup
await sandbox.dispose();
```

---

## Configuration

### E2BSandboxOptions

```typescript
interface E2BSandboxOptions {
apiKey?: string; // E2B API Key (or use E2B_API_KEY env)
template?: string; // Template ID/alias, default 'base'
timeoutMs?: number; // Sandbox lifetime, default 300_000 (5min)
workDir?: string; // Working directory, default '/home/user'
envs?: Record<string, string>; // Environment variables
metadata?: Record<string, string>; // Custom metadata
allowInternetAccess?: boolean; // Allow internet, default true
execTimeoutMs?: number; // Command timeout, default 120_000
sandboxId?: string; // Connect to existing sandbox (resume)
domain?: string; // E2B API domain
}
```

### Environment Variables

| Variable | Description |
|----------|-------------|
| `E2B_API_KEY` | Your E2B API key (used if `apiKey` not provided) |

---

## Agent Integration

### Using E2B Sandbox with Agent

```typescript
import { Agent, E2BSandbox } from '@shareai-lab/kode-sdk';
import { createRuntime } from './shared/runtime';

const sandbox = new E2BSandbox({
template: 'base',
timeoutMs: 600_000,
});
await sandbox.init();

const deps = createRuntime(({ templates, registerBuiltin }) => {
registerBuiltin('fs', 'bash', 'todo');
templates.register({
id: 'coder',
systemPrompt: 'You are a coding assistant.',
tools: ['bash_run', 'fs_read', 'fs_write', 'todo_read', 'todo_write'],
});
});

const agent = await Agent.create({ templateId: 'coder', sandbox }, deps);
await agent.send('Write and run a Python fibonacci script');
```

### Sandbox Lifecycle Binding

- **Agent Start**: Call `sandbox.init()` before `Agent.create()`
- **Agent Pause**: Sandbox persists (use `sandboxId` to reconnect)
- **Agent Resume**: Pass `sandboxId` to reconnect to existing sandbox
- **Agent Destroy**: Call `sandbox.dispose()` to terminate

### Resume / Fork with Persistent sandboxId

```typescript
// First run - create
const sandbox = new E2BSandbox({ template: 'base' });
await sandbox.init();
const id = sandbox.getSandboxId(); // persist this

// Later - resume
const restored = new E2BSandbox({ sandboxId: id });
await restored.init();
// Same sandbox environment is available
```

---

## Custom Templates

### Using E2BTemplateBuilder

```typescript
import { E2BTemplateBuilder } from '@shareai-lab/kode-sdk';

await E2BTemplateBuilder.build({
alias: 'data-analysis',
base: 'python',
baseVersion: '3.11',
aptPackages: ['graphviz'],
pipPackages: ['pandas', 'numpy', 'matplotlib'],
workDir: '/workspace',
cpuCount: 4,
memoryMB: 2048,
});
```

### Available Base Images

| Base | Description |
|------|-------------|
| `python` | Python with pip |
| `node` | Node.js with npm |
| `debian` | Debian base |
| `ubuntu` | Ubuntu base |
| `custom` | Custom Dockerfile |

---

## Network & Ports

### Exposing Ports

```typescript
const sandbox = new E2BSandbox({ template: 'node' });
await sandbox.init();

await sandbox.exec('npx serve -l 3000 &');
const url = sandbox.getHostUrl(3000);
console.log(`Preview: ${url}`);
// https://3000-<sandboxId>.e2b.app
```

---

## Best Practices

1. **Timeout Management**: Set appropriate `timeoutMs` to control costs. Call `dispose()` when done.
2. **Error Handling**: E2B operations are remote calls; handle network errors gracefully.
3. **Data Export**: Sandbox data is lost after `dispose()`. Export important results first.
4. **Concurrency**: E2B has account-level sandbox limits. Plan accordingly with AgentPool.
5. **Template Reuse**: Build templates once, reuse across sandboxes for faster startup.
58 changes: 58 additions & 0 deletions docs/en/reference/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,64 @@ const agentId = generateAgentId(); // e.g., 'agt-abc123xyz'

---

## E2BSandbox

Cloud sandbox powered by [E2B](https://e2b.dev) for isolated code execution.

### Constructor

```typescript
new E2BSandbox(options?: E2BSandboxOptions)
```

### Methods

| Method | Signature | Description |
|--------|-----------|-------------|
| `init()` | `async init(): Promise<void>` | Initialize (create or connect) sandbox |
| `exec(cmd, opts?)` | `async exec(cmd: string, opts?: { timeoutMs?: number }): Promise<SandboxExecResult>` | Execute a command |
| `dispose()` | `async dispose(): Promise<void>` | Kill sandbox and cleanup |
| `getSandboxId()` | `getSandboxId(): string` | Get sandbox ID for persistence |
| `getHostUrl(port)` | `getHostUrl(port: number): string` | Get accessible URL for a port |
| `setTimeout(ms)` | `async setTimeout(timeoutMs: number): Promise<void>` | Extend sandbox lifetime |
| `isRunning()` | `async isRunning(): Promise<boolean>` | Check if sandbox is alive |
| `watchFiles(paths, listener)` | `async watchFiles(...): Promise<string>` | Watch file changes |
| `unwatchFiles(id)` | `unwatchFiles(id: string): void` | Stop watching |
| `getE2BInstance()` | `getE2BInstance(): E2BSdk` | Access underlying E2B SDK |

### Properties

| Property | Type | Description |
|----------|------|-------------|
| `kind` | `'e2b'` | Sandbox type identifier |
| `workDir` | `string` | Working directory path |
| `fs` | `SandboxFS` | File system operations |

---

## E2BTemplateBuilder

Static utility for building custom E2B sandbox templates.

### Static Methods

#### `E2BTemplateBuilder.build(config, opts?)`

```typescript
static async build(
config: E2BTemplateConfig,
opts?: { apiKey?: string; onLog?: (log: string) => void }
): Promise<{ templateId: string; alias: string }>
```

#### `E2BTemplateBuilder.exists(alias, opts?)`

```typescript
static async exists(alias: string, opts?: { apiKey?: string }): Promise<boolean>
```

---

## References

- [Types Reference](./types.md)
Expand Down
39 changes: 39 additions & 0 deletions docs/en/reference/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,45 @@ interface ReminderOptions {

---

## E2B Types

### E2BSandboxOptions

```typescript
interface E2BSandboxOptions {
apiKey?: string;
template?: string;
timeoutMs?: number;
workDir?: string;
envs?: Record<string, string>;
metadata?: Record<string, string>;
allowInternetAccess?: boolean;
execTimeoutMs?: number;
sandboxId?: string;
domain?: string;
}
```

### E2BTemplateConfig

```typescript
interface E2BTemplateConfig {
alias: string;
base: 'python' | 'node' | 'debian' | 'ubuntu' | 'custom';
baseVersion?: string;
dockerfile?: string;
aptPackages?: string[];
pipPackages?: string[];
npmPackages?: string[];
buildCommands?: string[];
workDir?: string;
cpuCount?: number;
memoryMB?: number;
}
```

---

## References

- [API Reference](./api.md)
Expand Down
Loading