@meistrari/sandbox-sdk
v0.1.5
Published
SDK for Sandbox - a secure code execution service.
Keywords
Readme
@meistrari/sandbox-sdk
SDK for Sandbox - a secure code execution service.
Installation
npm install @meistrari/sandbox-sdk
# or
bun add @meistrari/sandbox-sdkQuick Start
import { sandbox, DataTokenAuthStrategy } from '@meistrari/sandbox-sdk'
// Create client
const client = sandbox({
apiUrl: 'https://sandbox.meistrari.com',
auth: new DataTokenAuthStrategy(dataToken),
})
// Execute code
const run = await client.createRunAndWait({
code: 'console.log("Hello, World!")',
language: 'typescript',
})
console.log(run.stdout) // "Hello, World!"Usage
Simple Code Execution
// One-shot execution (no persistent sandbox)
const run = await client.createRunAndWait({
code: `
const result = 1 + 1
console.log(result)
`,
language: 'typescript',
})
console.log(run.stdout) // "2"
console.log(run.exitCode) // 0
console.log(run.isSuccess) // truePersistent Sandbox
import { Sandbox } from '@meistrari/sandbox-sdk'
// Create a persistent sandbox
const sandbox = await Sandbox.create(client, {
memSize: 512,
cpuSize: 1.0,
})
// Execute multiple commands in the same sandbox
const result1 = await sandbox.runCode('const x = 42', { language: 'typescript' })
const result2 = await sandbox.runCode('console.log(x)', { language: 'typescript' })
console.log(result2.stdout) // "42"
// Cleanup when done
await sandbox.kill()File Operations
const sandbox = await client.createSandbox()
// Write files
await sandbox.files.write('/home/user/config.json', '{"key": "value"}')
await sandbox.files.write('/home/user/data.bin', binaryData) // Uint8Array
// Read files
const text = await sandbox.files.read('/home/user/config.json')
const binary = await sandbox.files.read('/home/user/data.bin', { format: 'blob' })
// Check if file exists
const exists = await sandbox.files.exists('/home/user/config.json')
// List files
const files = await sandbox.files.list('/home/user')
// Remove files
await sandbox.files.remove('/home/user/config.json')Shell Commands
const sandbox = await client.createSandbox()
// Run shell commands
const { stdout, stderr, exitCode } = await sandbox.commands.run('ls -la')
console.log(stdout)
// Install packages
await sandbox.commands.run('bun add lodash')Using Libraries
const sandbox = await client.createSandbox()
// Execute code with npm libraries (installed automatically)
const result = await sandbox.runCode(`
import _ from 'lodash'
import { z } from 'zod'
const schema = z.object({ name: z.string(), age: z.number() })
const data = { name: 'John', age: 30, extra: 'ignored' }
console.log(_.pick(data, ['name', 'age']))
console.log(schema.parse(data))
`, {
language: 'typescript',
libraries: ['lodash', 'zod'],
})
console.log(result.stdout)
// { name: 'John', age: 30 }
// { name: 'John', age: 30 }Using Environment Variables
const sandbox = await client.createSandbox()
const result = await sandbox.runCode(`
console.log('API Key:', process.env.API_KEY)
console.log('Environment:', process.env.NODE_ENV)
`, {
language: 'typescript',
envs: {
API_KEY: 'secret-key-123',
NODE_ENV: 'production',
},
})Using Input Files
const sandbox = await client.createSandbox()
// Execute code with input files provided inline
const result = await sandbox.runCode(`
import fs from 'fs'
const config = JSON.parse(fs.readFileSync('/workspace/user-code/config.json', 'utf8'))
const data = fs.readFileSync('/workspace/user-code/data.csv', 'utf8')
console.log('Config:', config)
console.log('Data lines:', data.split('\\n').length)
`, {
language: 'typescript',
files: [
{
name: 'config.json',
content: JSON.stringify({ apiUrl: 'https://api.example.com', timeout: 5000 }),
encoding: 'utf8',
},
{
name: 'data.csv',
content: 'name,age\\nJohn,30\\nJane,25',
encoding: 'utf8',
},
],
})Complete Example (Libraries + Envs + Files)
const sandbox = await client.createSandbox({ memSize: 512 })
const result = await sandbox.runCode(`
import Papa from 'papaparse'
import fs from 'fs'
const csvData = fs.readFileSync('/workspace/user-code/users.csv', 'utf8')
const parsed = Papa.parse(csvData, { header: true })
const apiKey = process.env.PARSER_API_KEY
console.log('Using API Key:', apiKey.substring(0, 4) + '...')
console.log('Parsed records:', parsed.data.length)
console.log('First record:', JSON.stringify(parsed.data[0]))
`, {
language: 'typescript',
libraries: ['papaparse'],
envs: {
PARSER_API_KEY: 'pk_live_abc123xyz',
},
files: [
{
name: 'users.csv',
content: 'id,name,email\\n1,John,[email protected]\\n2,Jane,[email protected]',
encoding: 'utf8',
},
],
})
await sandbox.kill()Streaming Output
const result = await sandbox.runCode(longRunningScript, {
language: 'typescript',
onStdout: ({ line }) => console.log('[stdout]', line),
onStderr: ({ line }) => console.log('[stderr]', line),
onError: (error) => console.error('[error]', error),
})Connect to Existing Sandbox
// Reconnect to a previously created sandbox
const sandbox = await Sandbox.connect(client, existingSandboxId)
// Continue working
await sandbox.runCode('console.log("I am back!")')API Reference
sandbox(config)
Creates a new Sandbox client instance.
const client = sandbox({
apiUrl: string, // Sandbox API URL
auth: AuthStrategy, // Authentication strategy
timeout?: number, // Request timeout in ms (default: 300000)
})SandboxClient
Methods
| Method | Description |
|--------|-------------|
| createRun(request) | Create a code execution run |
| createRunAndWait(request) | Create and wait for completion |
| streamRun(request) | Create run with SSE streaming |
| getRun(runId) | Get run by ID |
| createSandbox(options) | Create a persistent sandbox |
| connectToSandbox(sandboxId) | Connect to existing sandbox |
| deleteSandbox(sandboxId) | Delete a sandbox |
Sandbox
Properties
| Property | Type | Description |
|----------|------|-------------|
| sandboxId | string | Unique sandbox identifier |
| files | SandboxFiles | File operations interface |
| commands | SandboxCommands | Command execution interface |
Methods
| Method | Description |
|--------|-------------|
| runCode(code, options) | Execute code in the sandbox |
| kill() | Terminate the sandbox |
| setTimeout(ms) | Set execution timeout |
SandboxRun
Properties
| Property | Type | Description |
|----------|------|-------------|
| id | string | Run ID |
| sandboxId | string? | Associated sandbox ID |
| status | Status | Current status |
| stdout | string? | Standard output |
| stderr | string? | Standard error |
| exitCode | number? | Exit code |
| isComplete | boolean | Whether run has finished |
| isSuccess | boolean | Whether run succeeded |
Types
type Status = 'pending' | 'running' | 'completed' | 'failed' | 'timeout' | 'cancelled'
interface CreateRunRequest {
code: string
language?: 'javascript' | 'typescript' | 'python' | 'bash'
libraries?: string[]
env?: Record<string, string>
files?: FileInput[]
memSize?: number // MB (default: 512)
cpuSize?: number // cores (default: 1.0)
timeoutMs?: number // ms (default: 300000)
sandboxId?: string // Use existing sandbox
persistent?: boolean // Keep sandbox after execution
}
interface RunCodeOptions {
language?: 'typescript' | 'javascript' | 'python' | 'bash'
envs?: Record<string, string>
timeoutMs?: number
libraries?: string[] // npm packages to install
files?: FileInput[] // input files to provide
onStdout?: (data: { line: string }) => void
onStderr?: (data: { line: string }) => void
onError?: (error: Error) => void
}
interface FileInput {
name: string // filename
content: string // file content
encoding: 'utf8' | 'base64'
path?: string // optional custom path
}E2B Compatibility
This SDK is designed to be compatible with E2B's SandboxLike interface, making migration straightforward:
// E2B
import { Sandbox } from '@e2b/code-interpreter'
const sandbox = await Sandbox.create(templateId, { apiKey })
// Sandbox (drop-in replacement)
import { Sandbox, sandbox, DataTokenAuthStrategy } from '@meistrari/sandbox-sdk'
const client = sandbox({ apiUrl, auth: new DataTokenAuthStrategy(token) })
const sandbox = await Sandbox.create(client)
// Same interface works for both
await sandbox.files.write('/path', content)
await sandbox.runCode(code, { onStdout: ({ line }) => console.log(line) })
await sandbox.kill()Error Handling
import { FetchError } from '@meistrari/sandbox-sdk'
try {
const run = await client.createRunAndWait({ code: 'invalid(' })
} catch (error) {
if (error instanceof FetchError) {
console.error(`API Error: ${error.message}`)
console.error(`Status: ${error.status}`)
console.error(`URL: ${error.url}`)
}
}License
MIT
