/** * Universal Sandbox Interface * * The canonical interface for all ComputeSDK sandboxes. * * Core methods (required): * - runCode, runCommand, getInfo, getUrl, destroy, filesystem * * Advanced features (optional): * - terminal, server, watcher, auth, env, etc. * * Providers can implement as much or as little as makes sense for their platform. * The gateway Sandbox class implements the full specification. * * **Note on naming:** This interface is named "Sandbox" in this file for clarity, * but is exported as "SandboxInterface" from the main computesdk package to avoid * collision with the gateway Sandbox class. The rename happens at export time in * src/index.ts. Providers using @computesdk/provider will only see "SandboxInterface". * * @example Minimal implementation * ```typescript * class MinimalSandbox implements Pick { * // Just implement core methods * } * ``` * * @example Full implementation * ```typescript * class FullSandbox implements Sandbox { * // Implement everything - core + advanced features * } * ``` */ /** * Supported runtime environments */ type Runtime = 'node' | 'python' | 'deno' | 'bun'; /** * Code execution result */ interface CodeResult$1 { output: string; exitCode: number; language: string; } /** * Command execution result */ interface CommandResult$1 { stdout: string; stderr: string; exitCode: number; durationMs: number; } /** * Sandbox information */ interface SandboxInfo$1 { /** Unique identifier for the sandbox */ id: string; /** Provider hosting the sandbox */ provider: string; /** Runtime environment in the sandbox */ runtime: Runtime; /** Current status of the sandbox */ status: 'running' | 'stopped' | 'error'; /** When the sandbox was created */ createdAt: Date; /** Execution timeout in milliseconds */ timeout: number; /** Additional provider-specific metadata */ metadata?: Record; } /** * File entry from directory listing */ interface FileEntry { name: string; type: 'file' | 'directory'; size?: number; modified?: Date; } /** * Options for running a command */ interface RunCommandOptions { cwd?: string; env?: Record; timeout?: number; background?: boolean; } /** * Filesystem operations interface */ interface SandboxFileSystem { readFile(path: string): Promise; writeFile(path: string, content: string): Promise; readdir(path: string): Promise; mkdir(path: string): Promise; exists(path: string): Promise; remove(path: string): Promise; } /** * Options for creating a sandbox * * Providers can extend this with additional properties specific to their implementation */ interface CreateSandboxOptions$1 { runtime?: Runtime; timeout?: number; templateId?: string; metadata?: Record; envs?: Record; name?: string; namespace?: string; directory?: string; overlays?: SandboxOverlayConfig[]; servers?: SandboxServerConfig[]; [key: string]: any; } interface SandboxOverlayConfig { source: string; target: string; ignore?: string[]; strategy?: 'copy' | 'smart'; } type SandboxRestartPolicy = 'never' | 'on-failure' | 'always'; /** * Health check configuration for servers */ interface SandboxHealthCheckConfig { /** Path to poll for health checks (default: "/") */ path?: string; /** Interval between health checks in milliseconds (default: 2000) */ interval_ms?: number; /** Timeout for each health check request in milliseconds (default: 1500) */ timeout_ms?: number; /** Delay before starting health checks after port detection in milliseconds (default: 5000) */ delay_ms?: number; } interface SandboxServerConfig { slug: string; start: string; install?: string; path?: string; port?: number; strict_port?: boolean; autostart?: boolean; env_file?: string; environment?: Record; restart_policy?: SandboxRestartPolicy; max_restarts?: number; restart_delay_ms?: number; stop_timeout_ms?: number; depends_on?: string[]; overlay?: SandboxOverlayConfig; overlays?: SandboxOverlayConfig[]; health_check?: SandboxHealthCheckConfig; } /** * Universal Sandbox Interface * * All ComputeSDK sandboxes implement this interface. * Core methods are required, advanced features are optional. * * Note: Implementations may use slightly different types for return values * as long as they are structurally compatible. For example, getInfo() might * return additional fields beyond the base SandboxInfo. */ interface Sandbox$1 { /** Unique identifier for the sandbox */ readonly sandboxId: string; /** Provider name (e2b, railway, modal, gateway, etc.) */ readonly provider: string; /** Execute code in the sandbox */ runCode(code: string, runtime?: Runtime): Promise; /** * Execute shell command * * Send raw command string to the sandbox - no preprocessing. * The provider/server handles shell invocation and execution details. */ runCommand(command: string, options?: RunCommandOptions): Promise; /** Get information about the sandbox */ getInfo(): Promise; /** Get URL for accessing the sandbox on a specific port */ getUrl(options: { port: number; protocol?: string; }): Promise; /** Destroy the sandbox and clean up resources */ destroy(): Promise; /** File system operations */ readonly filesystem: SandboxFileSystem; /** * Terminal management (interactive PTY and exec modes) * Available in: gateway, e2b (potentially) */ readonly terminal?: any; /** * Code and command execution namespace * Available in: gateway */ readonly run?: any; /** * Managed server operations * Available in: gateway */ readonly server?: any; /** * File watcher with real-time change events * Available in: gateway */ readonly watcher?: any; /** * Session token management * Available in: gateway */ readonly sessionToken?: any; /** * Magic link authentication * Available in: gateway */ readonly magicLink?: any; /** * Signal service for port/error events * Available in: gateway */ readonly signal?: any; /** * File operations namespace * Available in: gateway */ readonly file?: any; /** * Environment variable management * Available in: gateway */ readonly env?: any; /** * Authentication operations * Available in: gateway */ readonly auth?: any; /** * Child sandbox management * Available in: gateway */ readonly child?: any; } /** * Terminal created notification */ interface TerminalCreatedMessage { type: 'terminal:created'; channel: string; data: { id: string; status: 'running' | 'stopped'; }; } /** * Terminal output data * Note: output field may be base64 encoded depending on encoding field */ interface TerminalOutputMessage { type: 'terminal:output'; channel: string; data: { output: string; encoding?: 'raw' | 'base64'; }; } /** * Terminal destroyed notification */ interface TerminalDestroyedMessage { type: 'terminal:destroyed'; channel: string; data: { id: string; }; } /** * Terminal error notification */ interface TerminalErrorMessage { type: 'terminal:error'; channel: string; data: { error: string; }; } /** * Command stdout streaming message (exec mode with stream: true) */ interface CommandStdoutMessage { type: 'command:stdout'; channel: string; data: { terminal_id: string; cmd_id: string; output: string; }; } /** * Command stderr streaming message (exec mode with stream: true) */ interface CommandStderrMessage { type: 'command:stderr'; channel: string; data: { terminal_id: string; cmd_id: string; output: string; }; } /** * Command exit message (exec mode with stream: true) */ interface CommandExitMessage { type: 'command:exit'; channel: string; data: { terminal_id: string; cmd_id: string; exit_code: number; }; } /** * File watcher created notification */ interface WatcherCreatedMessage { type: 'watcher:created'; channel: string; data: { id: string; path: string; }; } /** * File change event * Note: content field may be base64 encoded depending on encoding field */ interface FileChangedMessage { type: 'file:changed'; channel: string; data: { event: 'add' | 'change' | 'unlink' | 'addDir' | 'unlinkDir'; path: string; content?: string; encoding?: 'raw' | 'base64'; }; } /** * File watcher destroyed notification */ interface WatcherDestroyedMessage { type: 'watcher:destroyed'; channel: string; data: { id: string; }; } /** * System signal event */ interface SignalMessage { type: 'signal'; channel: 'signals'; data: { signal: 'port' | 'error' | 'server-ready'; port?: number; url?: string; message?: string; }; } /** * Sandbox created notification */ interface SandboxCreatedMessage { type: 'sandbox.created'; data: { subdomain: string; url: string; }; } /** * Sandbox deleted notification */ interface SandboxDeletedMessage { type: 'sandbox.deleted'; data: { subdomain: string; }; } type WebSocketConstructor$1 = new (url: string) => WebSocket; interface WebSocketManagerConfig { /** WebSocket URL (will be generated from client config if not provided) */ url: string; /** WebSocket implementation */ WebSocket: WebSocketConstructor$1; /** Enable automatic reconnection on disconnect (default: true) */ autoReconnect?: boolean; /** Reconnection delay in milliseconds (default: 1000) */ reconnectDelay?: number; /** Maximum reconnection attempts (default: 5, 0 = infinite) */ maxReconnectAttempts?: number; /** Enable debug logging (default: false) */ debug?: boolean; /** WebSocket protocol: 'binary' (default, recommended) or 'json' (for debugging) */ protocol?: 'json' | 'binary'; } type MessageHandler = (message: T) => void; type ErrorHandler = (error: Event) => void; type ConnectionHandler = () => void; /** * WebSocket Manager for handling real-time communication * * @example * ```typescript * import { ComputeClient } from '@computesdk/client' * * const client = new ComputeClient({ sandboxUrl: 'https://sandbox-123.sandbox.computesdk.com' }); * await client.generateToken(); * * // Create WebSocket manager * const ws = client.createWebSocketManager(); * * // Listen for connection * ws.on('open', () => { * console.log('Connected!'); * }); * * // Subscribe to terminal output * ws.subscribe('terminal:term_abc123'); * ws.on('terminal:output', (msg) => { * console.log('Terminal output:', msg.data.output); * }); * * // Send terminal input * ws.sendTerminalInput('term_abc123', 'ls -la\n'); * * // Subscribe to file changes * ws.subscribe('watcher:watcher_xyz789'); * ws.on('file:changed', (msg) => { * console.log('File changed:', msg.data.path, msg.data.event); * }); * * // Subscribe to signals * ws.subscribe('signals'); * ws.on('signal', (msg) => { * console.log('Signal:', msg.data); * }); * ``` */ declare class WebSocketManager { private config; private ws; private eventHandlers; private reconnectAttempts; private reconnectTimer; private subscribedChannels; private isManualClose; constructor(config: WebSocketManagerConfig); /** * Connect to WebSocket server */ connect(): Promise; /** * Disconnect from WebSocket server */ disconnect(): void; /** * Check if WebSocket is connected */ isConnected(): boolean; /** * Attempt to reconnect to WebSocket server */ private attemptReconnect; /** * Subscribe to a channel * @param channel - Channel name (e.g., 'terminal:term_abc123', 'watcher:watcher_xyz789', 'signals') */ subscribe(channel: string): void; /** * Unsubscribe from a channel */ unsubscribe(channel: string): void; /** * Get list of subscribed channels */ getSubscribedChannels(): string[]; /** * Send raw message to server */ private sendRaw; /** * Send input to a terminal (sent as-is, not encoded) */ sendTerminalInput(terminalId: string, input: string): void; /** * Resize terminal window */ resizeTerminal(terminalId: string, cols: number, rows: number): void; /** * Start a pending streaming command * Used in two-phase streaming flow: HTTP request creates pending command, * then this signal triggers execution after client has subscribed. */ startCommand(cmdId: string): void; /** * Register event handler */ on(event: 'open', handler: ConnectionHandler): void; on(event: 'close', handler: ConnectionHandler): void; on(event: 'error', handler: ErrorHandler): void; on(event: 'reconnect-failed', handler: ConnectionHandler): void; on(event: 'terminal:created', handler: MessageHandler): void; on(event: 'terminal:output', handler: MessageHandler): void; on(event: 'terminal:destroyed', handler: MessageHandler): void; on(event: 'terminal:error', handler: MessageHandler): void; on(event: 'command:stdout', handler: MessageHandler): void; on(event: 'command:stderr', handler: MessageHandler): void; on(event: 'command:exit', handler: MessageHandler): void; on(event: 'watcher:created', handler: MessageHandler): void; on(event: 'file:changed', handler: MessageHandler): void; on(event: 'watcher:destroyed', handler: MessageHandler): void; on(event: 'signal', handler: MessageHandler): void; on(event: 'sandbox.created', handler: MessageHandler): void; on(event: 'sandbox.deleted', handler: MessageHandler): void; /** * Unregister event handler */ off(event: string, handler: MessageHandler): void; /** * Unregister all event handlers for an event */ offAll(event: string): void; /** * Emit event to registered handlers */ private emit; /** * Handle incoming message */ private handleMessage; /** * Log debug message if debug mode is enabled */ private log; /** * Get current connection state */ getState(): 'connecting' | 'open' | 'closing' | 'closed'; /** * Get reconnection attempt count */ getReconnectAttempts(): number; } /** * Command - Represents a command execution in a terminal */ /** * Command execution result with wait capability */ declare class Command { readonly id: string; readonly terminalId: string; readonly command: string; private _status; private _stdout; private _stderr; private _exitCode?; private _durationMs?; private _startedAt; private _finishedAt?; private waitHandler?; private retrieveHandler?; constructor(data: { cmdId: string; terminalId: string; command: string; status: 'running' | 'completed' | 'failed'; stdout: string; stderr: string; exitCode?: number; durationMs?: number; startedAt: string; finishedAt?: string; }); get status(): 'running' | 'completed' | 'failed'; get stdout(): string; get stderr(): string; get exitCode(): number | undefined; get durationMs(): number | undefined; get startedAt(): string; get finishedAt(): string | undefined; /** * Set the wait handler (called by TerminalCommands) * @internal */ setWaitHandler(handler: (timeout?: number) => Promise): void; /** * Set the retrieve handler (called by TerminalCommands) * @internal */ setRetrieveHandler(handler: () => Promise): void; /** * Wait for the command to complete * @param timeout - Optional timeout in seconds (0 = no timeout) * @returns This command with updated status */ wait(timeout?: number): Promise; /** * Refresh the command status from the server * @returns This command with updated status */ refresh(): Promise; /** * Update internal state from API response */ private updateFromResponse; } /** * TerminalCommand - Resource namespace for terminal commands */ /** * Command resource namespace for a terminal * * @example * ```typescript * const terminal = await sandbox.terminal.create({ pty: false }); * * // Run a command * const cmd = await terminal.command.run('npm test'); * console.log(cmd.stdout); * * // Run in background and wait * const cmd = await terminal.command.run('npm install', { background: true }); * await cmd.wait(); * console.log(cmd.exitCode); * * // List commands * const commands = await terminal.command.list(); * * // Retrieve a specific command * const cmd = await terminal.command.retrieve(cmdId); * ``` */ declare class TerminalCommand { private terminalId; private runHandler; private listHandler; private retrieveHandler; private waitHandler; constructor(terminalId: string, handlers: { run: (command: string, background?: boolean) => Promise; list: () => Promise; retrieve: (cmdId: string) => Promise; wait: (cmdId: string, timeout?: number) => Promise; }); /** * Run a command in the terminal * @param command - The command to execute * @param options - Execution options * @param options.background - If true, returns immediately without waiting for completion * @returns Command object with results or status */ run(command: string, options?: { background?: boolean; }): Promise; /** * List all commands executed in this terminal * @returns Array of Command objects */ list(): Promise; /** * Retrieve a specific command by ID * @param cmdId - The command ID * @returns Command object with full details */ retrieve(cmdId: string): Promise; } /** * Terminal class for managing terminal sessions with WebSocket integration */ /** * Terminal event handlers */ type TerminalEventHandler = { output: (data: string) => void; error: (error: string) => void; destroyed: () => void; }; /** * TerminalInstance - A connected terminal session with WebSocket support * * This is the object returned by sandbox.terminal.create() * * @example * ```typescript * // PTY mode - Interactive shell * const pty = await sandbox.terminal.create({ pty: true }); * pty.on('output', (data) => console.log(data)); * pty.write('ls -la\n'); * await pty.destroy(); * * // Exec mode - Command tracking * const exec = await sandbox.terminal.create({ pty: false }); * const cmd = await exec.command.run('npm test'); * console.log(cmd.exitCode); * * // Background execution with wait * const cmd = await exec.command.run('npm install', { background: true }); * await cmd.wait(); * console.log(cmd.stdout); * ``` */ declare class TerminalInstance { private _id; private _pty; private _status; private _channel; private _ws; private _encoding; private _eventHandlers; /** * Command namespace for exec mode terminals */ readonly command: TerminalCommand; private _executeHandler?; private _listCommandsHandler?; private _retrieveCommandHandler?; private _waitCommandHandler?; private _destroyHandler?; constructor(id: string, pty: boolean, status: 'running' | 'stopped' | 'active' | 'ready', channel: string | null, ws: WebSocketManager | null, encoding?: 'raw' | 'base64'); /** * Set up WebSocket event handlers (PTY mode only) */ private setupWebSocketHandlers; /** * Terminal ID */ get id(): string; /** * Get terminal ID (deprecated, use .id property) * @deprecated Use .id property instead */ getId(): string; /** * Terminal status */ get status(): 'running' | 'stopped' | 'active' | 'ready'; /** * Get terminal status (deprecated, use .status property) * @deprecated Use .status property instead */ getStatus(): 'running' | 'stopped' | 'active' | 'ready'; /** * Terminal channel (null for exec mode) */ get channel(): string | null; /** * Get terminal channel (deprecated, use .channel property) * @deprecated Use .channel property instead */ getChannel(): string | null; /** * Whether this is a PTY terminal */ get pty(): boolean; /** * Get terminal PTY mode (deprecated, use .pty property) * @deprecated Use .pty property instead */ isPTY(): boolean; /** * Check if terminal is running */ isRunning(): boolean; /** * Write input to the terminal (PTY mode only) */ write(input: string): void; /** * Resize terminal window (PTY mode only) */ resize(cols: number, rows: number): void; /** * Set execute command handler (called by Sandbox) * @internal */ setExecuteHandler(handler: (command: string, background?: boolean) => Promise): void; /** * Set list commands handler (called by Sandbox) * @internal */ setListCommandsHandler(handler: () => Promise): void; /** * Set retrieve command handler (called by Sandbox) * @internal */ setRetrieveCommandHandler(handler: (cmdId: string) => Promise): void; /** * Set wait command handler (called by Sandbox) * @internal */ setWaitCommandHandler(handler: (cmdId: string, timeout?: number) => Promise): void; /** * Set destroy handler (called by Sandbox) * @internal */ setDestroyHandler(handler: () => Promise): void; /** * Execute a command in the terminal (deprecated, use command.run()) * @deprecated Use terminal.command.run() instead */ execute(command: string, options?: { background?: boolean; }): Promise; /** * Destroy the terminal */ destroy(): Promise; /** * Clean up resources */ private cleanup; /** * Register event handler */ on(event: K, handler: TerminalEventHandler[K]): void; /** * Unregister event handler */ off(event: K, handler: TerminalEventHandler[K]): void; /** * Emit event to registered handlers */ private emit; } /** * FileWatcher class for monitoring file system changes with WebSocket integration */ /** * File change event data */ interface FileChangeEvent { event: 'add' | 'change' | 'unlink' | 'addDir' | 'unlinkDir'; path: string; content?: string; } /** * FileWatcher event handlers */ type FileWatcherEventHandler = { change: (event: FileChangeEvent) => void; destroyed: () => void; }; /** * FileWatcher class for monitoring file system changes * * @example * ```typescript * const client = new ComputeClient({ sandboxUrl: '...' }); * await client.generateToken(); * * const watcher = await client.createWatcher('/home/project', { * ignored: ['node_modules', '.git'] * }); * * watcher.on('change', (event) => { * console.log(`File ${event.event}: ${event.path}`); * }); * * await watcher.destroy(); * ``` */ declare class FileWatcher { private id; private path; private status; private channel; private includeContent; private ignored; private encoding; private ws; private eventHandlers; constructor(id: string, path: string, status: 'active' | 'stopped', channel: string, includeContent: boolean, ignored: string[], ws: WebSocketManager, encoding?: 'raw' | 'base64'); /** * Set up WebSocket event handlers */ private setupWebSocketHandlers; /** * Get watcher ID */ getId(): string; /** * Get watched path */ getPath(): string; /** * Get watcher status */ getStatus(): 'active' | 'stopped'; /** * Get watcher channel */ getChannel(): string; /** * Check if content is included in events */ isIncludingContent(): boolean; /** * Get ignored patterns */ getIgnoredPatterns(): string[]; /** * Check if watcher is active */ isActive(): boolean; /** * Destroy the watcher (uses REST API, not WebSocket) */ private destroyWatcher?; /** * Set destroy handler (called by client) */ setDestroyHandler(handler: () => Promise): void; /** * Destroy the watcher */ destroy(): Promise; /** * Clean up resources */ private cleanup; /** * Register event handler */ on(event: K, handler: FileWatcherEventHandler[K]): void; /** * Unregister event handler */ off(event: K, handler: FileWatcherEventHandler[K]): void; /** * Emit event to registered handlers */ private emit; } /** * SignalService class for monitoring system signals with WebSocket integration */ /** * Port signal data */ interface PortSignalEvent { signal: 'port' | 'server-ready'; port: number; url: string; type?: 'open' | 'close'; } /** * Error signal data */ interface ErrorSignalEvent { signal: 'error'; message: string; } /** * Generic signal event (union type) */ type SignalEvent = PortSignalEvent | ErrorSignalEvent; /** * SignalService event handlers */ type SignalServiceEventHandler = { port: (event: PortSignalEvent) => void; error: (event: ErrorSignalEvent) => void; signal: (event: SignalEvent) => void; }; /** * SignalService class for monitoring system signals and events * * @example * ```typescript * const client = new ComputeClient({ sandboxUrl: '...' }); * await client.generateToken(); * * const signals = await client.startSignals(); * * signals.on('port', (event) => { * console.log(`Port ${event.port} ${event.type}: ${event.url}`); * }); * * signals.on('error', (event) => { * console.error(`Error: ${event.message}`); * }); * * await signals.stop(); * ``` */ declare class SignalService { private status; private channel; private ws; private eventHandlers; constructor(status: 'active' | 'stopped', channel: string, ws: WebSocketManager); /** * Set up WebSocket event handlers */ private setupWebSocketHandlers; /** * Get service status */ getStatus(): 'active' | 'stopped'; /** * Get service channel */ getChannel(): string; /** * Check if service is active */ isActive(): boolean; /** * Stop the signal service (uses REST API, not WebSocket) */ private stopService?; /** * Set stop handler (called by client) */ setStopHandler(handler: () => Promise): void; /** * Stop the signal service */ stop(): Promise; /** * Clean up resources */ private cleanup; /** * Register event handler */ on(event: K, handler: SignalServiceEventHandler[K]): void; /** * Unregister event handler */ off(event: K, handler: SignalServiceEventHandler[K]): void; /** * Emit event to registered handlers */ private emit; } /** * Terminal - Resource namespace for terminal management */ /** * Terminal resource namespace * * @example * ```typescript * // Create a PTY terminal (interactive shell) * const pty = await sandbox.terminal.create({ pty: true, shell: '/bin/bash' }); * pty.on('output', (data) => console.log(data)); * pty.write('ls -la\n'); * * // Create an exec terminal (command tracking) * const exec = await sandbox.terminal.create({ pty: false }); * const cmd = await exec.command.run('npm test'); * console.log(cmd.exitCode); * * // List all terminals * const terminals = await sandbox.terminal.list(); * * // Retrieve a specific terminal * const terminal = await sandbox.terminal.retrieve(id); * * // Destroy a terminal * await sandbox.terminal.destroy(id); * ``` */ declare class Terminal { private createHandler; private listHandler; private retrieveHandler; private destroyHandler; constructor(handlers: { create: (options?: { shell?: string; encoding?: 'raw' | 'base64'; pty?: boolean; }) => Promise; list: () => Promise; retrieve: (id: string) => Promise; destroy: (id: string) => Promise; }); /** * Create a new terminal session * * @param options - Terminal creation options * @param options.shell - Shell to use (e.g., '/bin/bash') - PTY mode only * @param options.encoding - Encoding: 'raw' (default) or 'base64' (binary-safe) * @param options.pty - Terminal mode: true = PTY (interactive), false = exec (command tracking) * @returns TerminalInstance */ create(options?: { shell?: string; encoding?: 'raw' | 'base64'; pty?: boolean; }): Promise; /** * List all active terminals * @returns Array of terminal responses */ list(): Promise; /** * Retrieve a specific terminal by ID * @param id - The terminal ID * @returns Terminal instance */ retrieve(id: string): Promise; /** * Destroy a terminal by ID * @param id - The terminal ID */ destroy(id: string): Promise; } /** * Overlay - Resource namespace for filesystem overlay operations * * Overlays enable instant sandbox setup from template directories by copying * files directly for isolation, with heavy directories copied in the background. */ /** * Options for waiting for overlay copy completion */ interface WaitForCompletionOptions { /** Maximum number of retry attempts (default: 60) */ maxRetries?: number; /** Initial delay between retries in milliseconds (default: 500) */ initialDelayMs?: number; /** Maximum delay between retries in milliseconds (default: 5000) */ maxDelayMs?: number; /** Backoff multiplier for exponential backoff (default: 1.5) */ backoffFactor?: number; } /** * Strategy for creating an overlay * - 'copy': Full copy of all files (standard behavior) * - 'smart': Use symlinks for immutable packages (e.g. node_modules) for instant creation */ type OverlayStrategy = 'copy' | 'smart'; /** * Options for creating an overlay */ interface CreateOverlayOptions { /** Absolute path to source directory (template) */ source: string; /** Relative path in sandbox where overlay will be mounted */ target: string; /** Glob patterns to ignore (e.g., ["node_modules", "*.log"]) */ ignore?: string[]; /** Strategy to use (default: 'smart') */ strategy?: OverlayStrategy; /** If true, wait for background copy to complete before returning (default: false) */ waitForCompletion?: boolean | WaitForCompletionOptions; } /** * Copy status for overlay background operations */ type OverlayCopyStatus = 'pending' | 'in_progress' | 'complete' | 'failed'; /** * Statistics about an overlay */ interface OverlayStats { /** Number of copied files */ copiedFiles: number; /** Number of copied directories (heavy dirs copied in background) */ copiedDirs: number; /** Paths that were skipped (e.g., .git, ignored patterns) */ skipped: string[]; } /** * Overlay information (client-side normalized type) */ interface OverlayInfo { /** Unique overlay identifier */ id: string; /** Absolute path to source directory */ source: string; /** Relative path in sandbox */ target: string; /** Strategy used for the overlay */ strategy: OverlayStrategy; /** When the overlay was created */ createdAt: string; /** Statistics about the overlay */ stats: OverlayStats; /** Copy status for background operations */ copyStatus: OverlayCopyStatus; /** Error message if copy failed */ copyError?: string; } /** * API response for overlay operations (snake_case from server) */ interface OverlayResponse { id: string; source: string; target: string; strategy?: string; created_at: string; stats: { copied_files: number; copied_dirs: number; skipped: string[]; }; copy_status: string; copy_error?: string; } /** * API response for listing overlays */ interface OverlayListResponse { overlays: OverlayResponse[]; } /** * Overlay resource namespace * * @example * ```typescript * // Create an overlay from a template directory * const overlay = await sandbox.filesystem.overlay.create({ * source: '/templates/nextjs', * target: 'project', * }); * console.log(overlay.copyStatus); // 'pending' | 'in_progress' | 'complete' | 'failed' * * // Create an overlay and wait for background copy to complete * const overlay = await sandbox.filesystem.overlay.create({ * source: '/templates/nextjs', * target: 'project', * waitForCompletion: true, // blocks until copy is complete * }); * * // Wait for an existing overlay's copy to complete * const overlay = await sandbox.filesystem.overlay.waitForCompletion('overlay-id'); * * // List all overlays * const overlays = await sandbox.filesystem.overlay.list(); * * // Get a specific overlay (useful for polling copy status) * const overlay = await sandbox.filesystem.overlay.retrieve('overlay-id'); * if (overlay.copyStatus === 'complete') { * console.log('Background copy finished!'); * } * * // Delete an overlay * await sandbox.filesystem.overlay.destroy('overlay-id'); * ``` */ declare class Overlay { private createHandler; private listHandler; private retrieveHandler; private destroyHandler; constructor(handlers: { create: (options: CreateOverlayOptions) => Promise; list: () => Promise; retrieve: (id: string) => Promise; destroy: (id: string) => Promise; }); /** * Create a new overlay from a template directory * * The overlay copies files from the source directory into the target path * for better isolation. Heavy directories (node_modules, .venv, etc.) are * copied in the background. Use the `ignore` option to exclude files/directories. * * @param options - Overlay creation options * @param options.source - Absolute path to source directory * @param options.target - Relative path in sandbox * @param options.ignore - Glob patterns to ignore (e.g., ["node_modules", "*.log"]) * @param options.strategy - Strategy to use ('copy' or 'smart') * @param options.waitForCompletion - If true or options object, wait for background copy to complete * @returns Overlay info with copy status */ create(options: CreateOverlayOptions): Promise; /** * List all overlays for the current sandbox * @returns Array of overlay info */ list(): Promise; /** * Retrieve a specific overlay by ID * * Useful for polling the copy status of an overlay. * * @param id - Overlay ID * @returns Overlay info */ retrieve(id: string): Promise; /** * Destroy (delete) an overlay * @param id - Overlay ID */ destroy(id: string): Promise; /** * Wait for an overlay's background copy to complete * * Polls the overlay status with exponential backoff until the copy * is complete or fails. Throws an error if the copy fails or times out. * * @param id - Overlay ID * @param options - Polling options * @returns Overlay info with final copy status * @throws Error if copy fails or times out */ waitForCompletion(id: string, options?: WaitForCompletionOptions): Promise; /** * Convert API response to OverlayInfo */ private toOverlayInfo; /** * Validate and return strategy, defaulting to 'copy' for unknown/missing values (legacy support) */ private validateStrategy; /** * Validate and return copy status, defaulting to 'pending' for unknown values */ private validateCopyStatus; } /** * Server - Resource namespace for managed server operations */ /** * Options for starting a managed server */ interface ServerStartOptions { /** Unique server identifier (URL-safe) */ slug: string; /** Install command to run before starting (optional, runs blocking, e.g., "npm install") */ install?: string; /** Command to start the server (e.g., "npm run dev") */ start: string; /** Working directory (optional) */ path?: string; /** Path to .env file relative to path (optional) */ env_file?: string; /** Inline environment variables (merged with env_file if both provided) */ environment?: Record; /** Requested port number (preallocated before start) */ port?: number; /** If true, fail instead of auto-incrementing when port is taken */ strict_port?: boolean; /** Whether to auto-start the server on daemon boot (default: true) */ autostart?: boolean; /** Inline overlay to create before starting the server */ overlay?: Omit; /** Additional overlays to create before starting the server */ overlays?: Array>; /** Overlay IDs this server depends on (waits for copy completion) */ depends_on?: string[]; /** * When to automatically restart the server: * - `never`: No automatic restart (default) * - `on-failure`: Restart only on non-zero exit code * - `always`: Always restart on exit (including exit code 0) */ restart_policy?: RestartPolicy; /** Maximum restart attempts (0 = unlimited, default: 0) */ max_restarts?: number; /** Delay between restart attempts in milliseconds (default: 1000) */ restart_delay_ms?: number; /** Graceful shutdown timeout in milliseconds - SIGTERM → wait → SIGKILL (default: 10000) */ stop_timeout_ms?: number; /** * Health check configuration for monitoring server availability * When configured, the server will be polled to verify it's responding to requests */ health_check?: HealthCheckConfig; } /** * Server resource namespace * * @example * ```typescript * // Start a basic server * const server = await sandbox.server.start({ * slug: 'api', * start: 'npm start', * path: '/app', * }); * * // Start with install command (runs before start) * const server = await sandbox.server.start({ * slug: 'web', * install: 'npm install', * start: 'npm run dev', * path: '/app', * }); * * // Start with supervisor settings (auto-restart on failure) * const server = await sandbox.server.start({ * slug: 'web', * start: 'node server.js', * path: '/app', * environment: { NODE_ENV: 'production', PORT: '3000' }, * restart_policy: 'on-failure', * max_restarts: 5, * restart_delay_ms: 2000, * }); * * // Start with inline overlay dependencies * const server = await sandbox.server.start({ * slug: 'web', * start: 'npm run dev', * path: '/app', * overlay: { * source: '/templates/nextjs', * target: 'app', * strategy: 'smart', * }, * }); * * // List all servers * const servers = await sandbox.server.list(); * * // Retrieve a specific server * const server = await sandbox.server.retrieve('api'); * * // Stop a server (graceful shutdown with SIGTERM → SIGKILL) * await sandbox.server.stop('api'); * * // Delete a server config * await sandbox.server.delete('api'); * * // Restart a server * await sandbox.server.restart('api'); * ``` */ /** * Options for retrieving server logs */ interface ServerLogsOptions { /** Which output stream to return: 'stdout', 'stderr', or 'combined' (default) */ stream?: ServerLogStream; } /** * Server logs info returned from the logs method */ interface ServerLogsInfo { /** Server slug identifier */ slug: string; /** Which stream was returned */ stream: ServerLogStream; /** The captured logs */ logs: string; } declare class Server { private startHandler; private listHandler; private retrieveHandler; private stopHandler; private deleteHandler; private restartHandler; private updateStatusHandler; private logsHandler; constructor(handlers: { start: (options: ServerStartOptions) => Promise; list: () => Promise; retrieve: (slug: string) => Promise; stop: (slug: string) => Promise; delete: (slug: string) => Promise; restart: (slug: string) => Promise; updateStatus: (slug: string, status: ServerStatus) => Promise; logs: (slug: string, options?: ServerLogsOptions) => Promise; }); /** * Start a new managed server with optional supervisor settings * * **Install Phase:** * If `install` is provided, it runs blocking before `start` (e.g., "npm install"). * The server status will be `installing` during this phase. * * **Restart Policies:** * - `never` (default): No automatic restart on exit * - `on-failure`: Restart only on non-zero exit code * - `always`: Always restart on exit (including exit code 0) * * **Graceful Shutdown:** * When stopping a server, it first sends SIGTERM and waits for `stop_timeout_ms` * before sending SIGKILL if the process hasn't exited. * * @param options - Server configuration * @returns Server info * * @example * ```typescript * // Basic server * const server = await sandbox.server.start({ * slug: 'web', * start: 'npm run dev', * path: '/app', * }); * * // With install command * const server = await sandbox.server.start({ * slug: 'api', * install: 'npm install', * start: 'node server.js', * environment: { NODE_ENV: 'production' }, * restart_policy: 'always', * max_restarts: 0, // unlimited * }); * ``` */ start(options: ServerStartOptions): Promise; /** * List all managed servers * @returns Array of server info */ list(): Promise; /** * Retrieve a specific server by slug * @param slug - The server slug * @returns Server info */ retrieve(slug: string): Promise; /** * Stop a server by slug (non-destructive) * @param slug - The server slug */ stop(slug: string): Promise; /** * Delete a server config by slug (stops + removes persistence) * @param slug - The server slug */ delete(slug: string): Promise; /** * Restart a server by slug * @param slug - The server slug * @returns Server info */ restart(slug: string): Promise; /** * Update server status (internal use) * @param slug - The server slug * @param status - New status */ updateStatus(slug: string, status: ServerStatus): Promise; /** * Retrieve captured output (logs) for a managed server * @param slug - The server slug * @param options - Options for log retrieval * @returns Server logs info * * @example * ```typescript * // Get combined logs (default) * const logs = await sandbox.server.logs('api'); * console.log(logs.logs); * * // Get only stdout * const stdout = await sandbox.server.logs('api', { stream: 'stdout' }); * * // Get only stderr * const stderr = await sandbox.server.logs('api', { stream: 'stderr' }); * ``` */ logs(slug: string, options?: ServerLogsOptions): Promise; } /** * Watcher - Resource namespace for file watcher operations */ /** * Watcher resource namespace * * @example * ```typescript * // Create a file watcher * const watcher = await sandbox.watcher.create('/project', { * ignored: ['node_modules', '.git'], * includeContent: true, * }); * watcher.on('change', (event) => { * console.log(`${event.event}: ${event.path}`); * }); * * // List all watchers * const watchers = await sandbox.watcher.list(); * * // Retrieve a specific watcher * const watcher = await sandbox.watcher.retrieve(id); * * // Destroy a watcher * await sandbox.watcher.destroy(id); * ``` */ declare class Watcher { private createHandler; private listHandler; private retrieveHandler; private destroyHandler; constructor(handlers: { create: (path: string, options?: { includeContent?: boolean; ignored?: string[]; encoding?: 'raw' | 'base64'; }) => Promise; list: () => Promise; retrieve: (id: string) => Promise; destroy: (id: string) => Promise; }); /** * Create a new file watcher * @param path - Path to watch * @param options - Watcher options * @param options.includeContent - Include file content in change events * @param options.ignored - Patterns to ignore * @param options.encoding - Encoding: 'raw' (default) or 'base64' (binary-safe) * @returns FileWatcher instance */ create(path: string, options?: { includeContent?: boolean; ignored?: string[]; encoding?: 'raw' | 'base64'; }): Promise; /** * List all active file watchers * @returns Array of watcher info */ list(): Promise; /** * Retrieve a specific watcher by ID * @param id - The watcher ID * @returns Watcher info */ retrieve(id: string): Promise; /** * Destroy a watcher by ID * @param id - The watcher ID */ destroy(id: string): Promise; } /** * SessionToken - Resource namespace for session token management */ /** * Session token info */ interface SessionTokenInfo { id: string; token?: string; description?: string; createdAt: string; expiresAt: string; lastUsedAt?: string; } /** * SessionToken resource namespace * * @example * ```typescript * // Create a session token (requires access token) * const token = await sandbox.sessionToken.create({ * description: 'My Application', * expiresIn: 604800, // 7 days * }); * console.log(token.token); * * // List all session tokens * const tokens = await sandbox.sessionToken.list(); * * // Retrieve a specific token * const token = await sandbox.sessionToken.retrieve(id); * * // Revoke a token * await sandbox.sessionToken.revoke(id); * ``` */ declare class SessionToken { private createHandler; private listHandler; private retrieveHandler; private revokeHandler; constructor(handlers: { create: (options?: { description?: string; expiresIn?: number; }) => Promise; list: () => Promise; retrieve: (id: string) => Promise; revoke: (id: string) => Promise; }); /** * Create a new session token (requires access token) * @param options - Token configuration * @param options.description - Description for the token * @param options.expiresIn - Expiration time in seconds (default: 7 days) * @returns Session token info including the token value */ create(options?: { description?: string; expiresIn?: number; }): Promise; /** * List all session tokens * @returns Array of session token info */ list(): Promise; /** * Retrieve a specific session token by ID * @param id - The token ID * @returns Session token info */ retrieve(id: string): Promise; /** * Revoke a session token * @param id - The token ID to revoke */ revoke(id: string): Promise; } /** * MagicLink - Resource namespace for magic link operations */ /** * Magic link info */ interface MagicLinkInfo { url: string; expiresAt: string; redirectUrl: string; } /** * MagicLink resource namespace * * @example * ```typescript * // Create a magic link (requires access token) * const link = await sandbox.magicLink.create({ * redirectUrl: '/dashboard', * }); * console.log(link.url); * ``` */ declare class MagicLink { private createHandler; constructor(handlers: { create: (options?: { redirectUrl?: string; }) => Promise; }); /** * Create a magic link for browser authentication (requires access token) * * Magic links are one-time URLs that automatically create a session token * and set it as a cookie in the user's browser. * * @param options - Magic link configuration * @param options.redirectUrl - URL to redirect to after authentication * @returns Magic link info including the URL */ create(options?: { redirectUrl?: string; }): Promise; } /** * Signal - Resource namespace for signal service operations */ /** * Signal service status info */ interface SignalStatusInfo { status: 'active' | 'stopped'; channel: string; wsUrl: string; } /** * Signal resource namespace * * @example * ```typescript * // Start the signal service * const signals = await sandbox.signal.start(); * signals.on('port', (event) => { * console.log(`Port ${event.port} opened: ${event.url}`); * }); * * // Get signal service status * const status = await sandbox.signal.status(); * * // Emit signals * await sandbox.signal.emitPort(3000, 'open', 'http://localhost:3000'); * await sandbox.signal.emitError('Something went wrong'); * * // Stop the signal service * await sandbox.signal.stop(); * ``` */ declare class Signal { private startHandler; private statusHandler; private stopHandler; private emitPortHandler; private emitErrorHandler; private emitServerReadyHandler; constructor(handlers: { start: () => Promise; status: () => Promise; stop: () => Promise; emitPort: (port: number, type: 'open' | 'close', url: string) => Promise; emitError: (message: string) => Promise; emitServerReady: (port: number, url: string) => Promise; }); /** * Start the signal service * @returns SignalService instance with event handling */ start(): Promise; /** * Get the signal service status * @returns Signal service status info */ status(): Promise; /** * Stop the signal service */ stop(): Promise; /** * Emit a port signal * @param port - Port number * @param type - Signal type ('open' or 'close') * @param url - URL associated with the port */ emitPort(port: number, type: 'open' | 'close', url: string): Promise; /** * Emit an error signal * @param message - Error message */ emitError(message: string): Promise; /** * Emit a server ready signal * @param port - Port number * @param url - Server URL */ emitServerReady(port: number, url: string): Promise; } /** * File - Resource namespace for file operations */ /** * File resource namespace * * @example * ```typescript * // Create a file * const file = await sandbox.file.create('/project/hello.txt', 'Hello, World!'); * * // List files in a directory * const files = await sandbox.file.list('/project'); * * // Retrieve file content * const content = await sandbox.file.retrieve('/project/hello.txt'); * * // Destroy (delete) a file * await sandbox.file.destroy('/project/hello.txt'); * * // Batch write multiple files * const results = await sandbox.file.batchWrite([ * { path: '/project/a.txt', operation: 'write', content: 'A' }, * { path: '/project/b.txt', operation: 'write', content: 'B' }, * ]); * * // Batch delete files * const results = await sandbox.file.batchWrite([ * { path: '/project/old.txt', operation: 'delete' }, * ]); * ``` */ declare class File { private createHandler; private listHandler; private retrieveHandler; private destroyHandler; private batchWriteHandler; private existsHandler; constructor(handlers: { create: (path: string, content?: string) => Promise; list: (path: string) => Promise; retrieve: (path: string) => Promise; destroy: (path: string) => Promise; batchWrite: (files: Array<{ path: string; operation: BatchFileOperation; content?: string; }>) => Promise; exists: (path: string) => Promise; }); /** * Create a new file with optional content * @param path - File path * @param content - File content (optional) * @returns File info */ create(path: string, content?: string): Promise; /** * List files at the specified path * @param path - Directory path (default: '/') * @returns Array of file info */ list(path?: string): Promise; /** * Retrieve file content * @param path - File path * @returns File content as string */ retrieve(path: string): Promise; /** * Destroy (delete) a file or directory * @param path - File or directory path */ destroy(path: string): Promise; /** * Batch file operations (write or delete multiple files) * * Features: * - Deduplication: Last operation wins per path * - File locking: Prevents race conditions * - Deterministic ordering: Alphabetical path sorting * - Partial failure handling: Returns per-file results * * @param files - Array of file operations * @returns Results for each file operation */ batchWrite(files: Array<{ path: string; operation: BatchFileOperation; content?: string; }>): Promise; /** * Check if a file exists * @param path - File path * @returns True if file exists */ exists(path: string): Promise; } /** * Env - Resource namespace for environment variable operations */ /** * Env resource namespace * * @example * ```typescript * // Retrieve environment variables * const vars = await sandbox.env.retrieve('.env'); * console.log(vars); * * // Update environment variables (merges with existing) * await sandbox.env.update('.env', { * API_KEY: 'secret', * DEBUG: 'true', * }); * * // Remove environment variables * await sandbox.env.remove('.env', ['OLD_KEY', 'DEPRECATED']); * ``` */ declare class Env { private retrieveHandler; private updateHandler; private removeHandler; private existsHandler; constructor(handlers: { retrieve: (file: string) => Promise; update: (file: string, variables: Record) => Promise; remove: (file: string, keys: string[]) => Promise; exists: (file: string) => Promise; }); /** * Retrieve environment variables from a file * @param file - Path to the .env file (relative to sandbox root) * @returns Key-value map of environment variables */ retrieve(file: string): Promise>; /** * Update (merge) environment variables in a file * @param file - Path to the .env file (relative to sandbox root) * @param variables - Key-value pairs to set * @returns Keys that were updated */ update(file: string, variables: Record): Promise; /** * Remove environment variables from a file * @param file - Path to the .env file (relative to sandbox root) * @param keys - Keys to remove * @returns Keys that were removed */ remove(file: string, keys: string[]): Promise; /** * Check if an environment file exists * @param file - Path to the .env file (relative to sandbox root) * @returns True if file exists */ exists(file: string): Promise; } /** * Auth - Resource namespace for authentication info */ /** * Authentication status info */ interface AuthStatusInfo { authenticated: boolean; tokenType?: 'access_token' | 'session_token'; expiresAt?: string; } /** * Authentication endpoints info */ interface AuthEndpointsInfo { createSessionToken: string; listSessionTokens: string; getSessionToken: string; revokeSessionToken: string; createMagicLink: string; authStatus: string; authInfo: string; } /** * Authentication info */ interface AuthInfo { message: string; instructions: string; endpoints: AuthEndpointsInfo; } /** * Auth resource namespace * * @example * ```typescript * // Check authentication status * const status = await sandbox.auth.status(); * console.log(status.authenticated); * console.log(status.tokenType); * * // Get authentication info and instructions * const info = await sandbox.auth.info(); * console.log(info.instructions); * ``` */ declare class Auth { private statusHandler; private infoHandler; constructor(handlers: { status: () => Promise; info: () => Promise; }); /** * Check authentication status * @returns Authentication status info */ status(): Promise; /** * Get authentication information and usage instructions * @returns Authentication info */ info(): Promise; } /** * Run - Resource namespace for code and command execution */ /** * Code execution result */ interface CodeResult { output: string; exitCode: number; language: string; } /** * Command execution result */ interface CommandResult { stdout: string; stderr: string; exitCode: number; durationMs: number; /** Command ID (present for background commands) */ cmdId?: string; /** Terminal ID (present for background commands) */ terminalId?: string; /** Command status (present for background commands) */ status?: 'running' | 'completed' | 'failed'; } /** * Supported languages for code execution */ type CodeLanguage = 'python' | 'python3' | 'node' | 'javascript' | 'js' | 'bash' | 'sh' | 'ruby'; /** * Code execution options */ interface CodeRunOptions { /** Programming language (optional - will auto-detect if not specified) */ language?: CodeLanguage; } /** * Options for waiting for command completion */ interface CommandWaitOptions { /** Timeout in seconds to wait for command completion (default: 300, max: 300) */ timeoutSeconds?: number; } /** * Command execution options */ interface CommandRunOptions { /** Shell to use (optional) */ shell?: string; /** Run in background (optional) */ background?: boolean; /** Working directory for the command (optional) */ cwd?: string; /** Environment variables (optional) */ env?: Record; /** If true, wait for background command to complete before returning (default: false) */ waitForCompletion?: boolean | CommandWaitOptions; } /** * Run - Resource namespace for executing code and commands * * @example * ```typescript * // Run code with auto-detection * const result = await sandbox.run.code('print("Hello from Python")'); * console.log(result.output); // "Hello from Python\n" * console.log(result.language); // "python" * * // Run code with explicit language * const result = await sandbox.run.code('console.log("Hello")', { language: 'node' }); * * // Run a command * const result = await sandbox.run.command('ls -la'); * console.log(result.stdout); * console.log(result.exitCode); * * // Run a command in background and wait for completion * const result = await sandbox.run.command('npm install', { * background: true, * waitForCompletion: true, // blocks until command completes * }); * console.log(result.exitCode); * * // Run in background without waiting (fire-and-forget) * const result = await sandbox.run.command('npm install', { background: true }); * console.log(result.cmdId); // command ID for manual tracking * console.log(result.terminalId); // terminal ID for manual tracking * ``` */ declare class Run { private codeHandler; private commandHandler; private waitHandler?; constructor(handlers: { code: (code: string, options?: CodeRunOptions) => Promise; command: (command: string, options?: CommandRunOptions) => Promise; wait?: (terminalId: string, cmdId: string, options?: CommandWaitOptions) => Promise; }); /** * Execute code with automatic language detection * * Supports: python, python3, node, javascript, js, bash, sh, ruby * * @param code - The code to execute * @param options - Execution options * @param options.language - Programming language (auto-detected if not specified) * @returns Code execution result with output, exit code, and detected language */ code(code: string, options?: CodeRunOptions): Promise; /** * Execute a shell command * * @param command - The command to execute * @param options - Execution options * @param options.shell - Shell to use (optional) * @param options.background - Run in background (optional) * @param options.cwd - Working directory for the command (optional) * @param options.env - Environment variables (optional) * @param options.waitForCompletion - If true (with background), wait for command to complete * @returns Command execution result with stdout, stderr, exit code, and duration */ command(command: string, options?: CommandRunOptions): Promise; /** * Wait for a background command to complete * * Uses the configured wait handler to block until the command * is complete or fails (typically via server-side long-polling). * Throws an error if the command fails or times out. * * @param terminalId - Terminal ID from background command result * @param cmdId - Command ID from background command result * @param options - Wait options passed to the handler * @returns Command result with final status * @throws Error if command fails or times out */ waitForCompletion(terminalId: string, cmdId: string, options?: CommandWaitOptions): Promise; } /** * Client Types * * Types specific to the gateway Sandbox client implementation. * Core universal types are imported from ../types/universal-sandbox */ /** * Sandbox status types (client-specific, more limited than universal) */ type SandboxStatus = 'running' | 'stopped' | 'error'; /** * Provider-agnostic sandbox info (alias for SandboxInfo for backward compatibility) */ interface ProviderSandboxInfo { /** Unique identifier for the sandbox */ id: string; /** Provider hosting the sandbox */ provider: string; /** Runtime environment in the sandbox */ runtime: Runtime; /** Current status of the sandbox */ status: SandboxStatus; /** When the sandbox was created */ createdAt: Date; /** Execution timeout in milliseconds */ timeout: number; /** Additional provider-specific metadata */ metadata?: Record; } /** * Error thrown when a command exits with a non-zero status */ declare class CommandExitError extends Error { result: { exitCode: number; stdout: string; stderr: string; error: boolean; }; name: string; constructor(result: { exitCode: number; stdout: string; stderr: string; error: boolean; }); } /** * Type guard to check if an error is a CommandExitError */ declare function isCommandExitError(error: unknown): error is CommandExitError; /** * Child - Resource namespace for child sandbox operations */ /** * Child resource namespace for managing child sandboxes * * Child sandboxes are isolated environments within the parent sandbox, * each with their own filesystem. Available only in multi-tenant mode. * * @example * ```typescript * // Create a new child sandbox * const child = await sandbox.child.create({ * directory: '/custom/path', * overlays: [ * { * source: '/templates/nextjs', * target: 'app', * strategy: 'smart', * }, * ], * servers: [ * { * slug: 'web', * start: 'npm run dev', * path: '/app', * }, * ], * }); * console.log(child.url); // https://sandbox-12345.sandbox.computesdk.com * * // List all children * const all = await sandbox.child.list(); * * // Get a specific child * const info = await sandbox.child.retrieve('sandbox-12345'); * * // Delete a child sandbox * await sandbox.child.destroy('sandbox-12345'); * * // Delete child and its files * await sandbox.child.destroy('sandbox-12345', { deleteFiles: true }); * ``` */ declare class Child { private createHandler; private listHandler; private retrieveHandler; private destroyHandler; constructor(handlers: { create: (options?: CreateSandboxOptions$1) => Promise; list: () => Promise; retrieve: (subdomain: string) => Promise; destroy: (subdomain: string, deleteFiles: boolean) => Promise; }); /** * Create a new child sandbox * @returns Child sandbox info including URL and subdomain */ create(options?: CreateSandboxOptions$1): Promise; /** * List all child sandboxes * @returns Array of child sandbox info */ list(): Promise; /** * Retrieve a specific child sandbox by subdomain * @param subdomain - The child subdomain (e.g., 'sandbox-12345') * @returns Child sandbox info */ retrieve(subdomain: string): Promise; /** * Destroy (delete) a child sandbox * @param subdomain - The child subdomain * @param options - Destroy options * @param options.deleteFiles - Whether to delete the child's files (default: false) */ destroy(subdomain: string, options?: { deleteFiles?: boolean; }): Promise; } /** * Binary WebSocket Protocol Implementation * * Implements the ComputeSDK binary protocol for WebSocket communication. * Provides 50-90% size reduction compared to JSON protocol. * * Binary Message Format: * [1 byte: message type] * [2 bytes: channel length (uint16, big-endian)] * [N bytes: channel string (UTF-8)] * [2 bytes: msg type length (uint16, big-endian)] * [N bytes: msg type string (UTF-8)] * [4 bytes: data length (uint32, big-endian)] * [N bytes: data (key-value encoded for complex objects, raw bytes for binary data)] * * Key-Value Encoding Format: * [2 bytes: num_fields (uint16, big-endian)] * For each field: * [2 bytes: key_length (uint16, big-endian)] * [N bytes: key string (UTF-8)] * [1 byte: value_type (0x01=string, 0x02=number, 0x03=boolean, 0x04=bytes)] * [4 bytes: value_length (uint32, big-endian)] * [N bytes: value data] */ declare enum MessageType { Subscribe = 1, Unsubscribe = 2, Data = 3, Error = 4, Connected = 5 } /** * Encode a WebSocket message to binary format * @param message - The message object to encode * @returns ArrayBuffer containing the encoded binary message */ declare function encodeBinaryMessage(message: any): ArrayBuffer; /** * Decode a binary WebSocket message * @param buffer - The binary data to decode (ArrayBuffer or Uint8Array) * @returns Decoded message object */ declare function decodeBinaryMessage(buffer: ArrayBuffer | Uint8Array): any; /** * ComputeSDK Client - Universal Sandbox Implementation * * This package provides a Sandbox for interacting with ComputeSDK sandboxes * through API endpoints at ${sandboxId}.sandbox.computesdk.com * * Works in browser, Node.js, and edge runtimes. * Browser: Uses native WebSocket and fetch * Node.js: Pass WebSocket implementation (e.g., 'ws' library) */ /** * Extended filesystem interface with overlay support */ interface ExtendedFileSystem extends SandboxFileSystem { /** Overlay operations for template directories */ readonly overlay: Overlay; } /** * WebSocket constructor type */ type WebSocketConstructor = new (url: string) => WebSocket; /** * Configuration options for creating a Sandbox */ interface SandboxConfig { /** API endpoint URL (e.g., https://sandbox-123.sandbox.computesdk.com). Optional in browser - can be auto-detected from URL query param or localStorage */ sandboxUrl?: string; /** Sandbox ID */ sandboxId: string; /** Provider name (e.g., 'e2b', 'gateway') */ provider: string; /** Access token or session token for authentication. Optional in browser - can be auto-detected from URL query param or localStorage */ token?: string; /** Optional headers to include with all requests */ headers?: Record; /** Request timeout in milliseconds (default: 30000) */ timeout?: number; /** WebSocket implementation (optional, uses global WebSocket if not provided) */ WebSocket?: WebSocketConstructor; /** WebSocket protocol: 'binary' (default, recommended) or 'json' (for debugging) */ protocol?: 'json' | 'binary'; /** Optional metadata associated with the sandbox */ metadata?: Record; /** * Handler called when destroy() is invoked. * If provided, this is called to destroy the sandbox (e.g., via gateway API). * If not provided, destroy() only disconnects the WebSocket. * @internal */ destroyHandler?: () => Promise; } /** * Health check response */ interface HealthResponse { status: string; timestamp: string; } /** * Server info response */ interface InfoResponse { message: string; data: { auth_enabled: boolean; main_subdomain: string; sandbox_count: number; sandbox_url: string; version: string; }; } /** * Session token response */ interface SessionTokenResponse { id: string; token: string; description?: string; createdAt: string; expiresAt: string; expiresIn: number; } /** * Session token list response */ interface SessionTokenListResponse { message: string; data: { tokens: Array<{ id: string; description?: string; created_at: string; expires_at: string; last_used_at?: string; }>; }; } /** * Magic link response */ interface MagicLinkResponse { message: string; data: { magic_url: string; expires_at: string; redirect_url: string; }; } /** * Authentication status response */ interface AuthStatusResponse { message: string; data: { authenticated: boolean; token_type?: 'access_token' | 'session_token'; expires_at?: string; }; } /** * Authentication information response */ interface AuthInfoResponse { message: string; data: { message: string; instructions: string; endpoints: { create_session_token: string; list_session_tokens: string; get_session_token: string; revoke_session_token: string; create_magic_link: string; auth_status: string; auth_info: string; }; }; } /** * File information */ interface FileInfo { name: string; path: string; size: number; is_dir: boolean; modified_at: string; } /** * Files list response */ interface FilesListResponse { message: string; data: { files: FileInfo[]; path: string; }; } /** * File response */ interface FileResponse { message: string; data: { file: FileInfo; content?: string; }; } /** * Command execution response (used by both /run/command and /terminals/{id}/execute) */ interface CommandExecutionResponse { message: string; data: { terminal_id?: string; cmd_id?: string; command: string; stdout: string; stderr: string; exit_code?: number; duration_ms?: number; status?: 'running' | 'completed' | 'failed'; channel?: string; pty?: boolean; }; } /** * Command details response */ interface CommandDetailsResponse { message: string; data: { cmd_id: string; command: string; status: 'running' | 'completed' | 'failed'; stdout: string; stderr: string; started_at: string; finished_at?: string; duration_ms?: number; exit_code?: number; }; } /** * Command list item */ interface CommandListItem { cmd_id: string; command: string; status: 'running' | 'completed' | 'failed'; started_at: string; finished_at?: string; duration_ms?: number; exit_code?: number; } /** * Commands list response */ interface CommandsListResponse { message: string; data: { commands: CommandListItem[]; count: number; }; } /** * Code execution response (POST /run/code) */ interface CodeExecutionResponse { data: { output: string; exit_code: number; language: string; }; } /** * File watcher information */ interface WatcherInfo { id: string; path: string; includeContent: boolean; ignored: string[]; status: 'active' | 'stopped'; channel: string; encoding?: 'raw' | 'base64'; } /** * File watcher response */ interface WatcherResponse { message: string; data: WatcherInfo & { ws_url: string; }; } /** * File watchers list response */ interface WatchersListResponse { message: string; data: { watchers: WatcherInfo[]; }; } /** * Signal service response */ interface SignalServiceResponse { message: string; data: { status: 'active' | 'stopped'; channel: string; ws_url: string; }; } /** * Port signal response */ interface PortSignalResponse { message: string; data: { port: number; type: 'open' | 'close'; url: string; }; } /** * Generic signal response */ interface GenericSignalResponse { message: string; data: { message: string; }; } /** * Sandbox information */ interface SandboxInfo { subdomain: string; directory: string; is_main: boolean; created_at: string; url: string; overlays?: SandboxOverlayInfo[]; servers?: SandboxServerInfo[]; } /** * Sandboxes list response */ interface SandboxesListResponse { sandboxes: SandboxInfo[]; } /** * Terminal response */ interface TerminalResponse { message: string; data: { id: string; pty: boolean; status: 'running' | 'stopped' | 'ready' | 'active'; channel?: string; ws_url?: string; encoding?: 'raw' | 'base64'; }; } /** * Terminal response */ interface TerminalResponse { message: string; data: { id: string; pty: boolean; status: 'running' | 'stopped' | 'ready' | 'active'; channel?: string; ws_url?: string; encoding?: 'raw' | 'base64'; }; } /** * Server status types * * - `installing`: Running install command (e.g., npm install) before starting * - `starting`: Initial startup of the server process * - `running`: Server process is running * - `ready`: Server is running and ready to accept traffic * - `failed`: Server failed to start or encountered a fatal error * - `stopped`: Server was intentionally stopped * - `restarting`: Server is being automatically restarted by the supervisor */ type ServerStatus = 'installing' | 'starting' | 'running' | 'ready' | 'failed' | 'stopped' | 'restarting'; /** * Server restart policy * - `never`: No automatic restart (default) * - `on-failure`: Restart only on non-zero exit code * - `always`: Always restart on exit (including exit code 0) */ type RestartPolicy = 'never' | 'on-failure' | 'always'; /** * Health check configuration for servers * Polls the server to verify it's responding to requests */ interface HealthCheckConfig { /** Path to poll for health checks (default: "/") */ path?: string; /** Interval between health checks in milliseconds (default: 2000) */ interval_ms?: number; /** Timeout for each health check request in milliseconds (default: 1500) */ timeout_ms?: number; /** Delay before starting health checks after port detection in milliseconds (default: 5000) */ delay_ms?: number; } /** * Health check status information returned from server */ interface HealthCheckStatus { /** When the last health check was performed (ISO 8601) */ last_check?: string; /** HTTP status code from the last health check */ last_status?: number; /** Number of consecutive failed health checks */ consecutive_failures: number; } /** * Server information */ interface ServerInfo { /** Unique server identifier */ slug: string; /** Install command (optional, runs blocking before start) */ install?: string; /** Command used to start the server */ start: string; /** Working directory path */ path: string; /** Original path before resolution */ original_path?: string; /** Path to .env file */ env_file?: string; /** Inline environment variables */ environment?: Record; /** Whether to auto-start the server on daemon boot */ autostart?: boolean; /** If true, port allocation is strict (no auto-increment) */ strict_port?: boolean; /** Overlay IDs this server depends on */ depends_on?: string[]; /** Auto-detected port number (populated when port monitor detects listening port) */ port?: number; /** Generated URL from subdomain + port (populated when port is detected) */ url?: string; /** Server lifecycle status */ status: ServerStatus; /** Process ID (direct process, not shell wrapper) */ pid?: number; /** Configured restart policy */ restart_policy?: RestartPolicy; /** Maximum restart attempts (0 = unlimited) */ max_restarts?: number; /** Delay between restarts in nanoseconds (input uses milliseconds via restart_delay_ms) */ restart_delay?: number; /** Graceful shutdown timeout in nanoseconds (input uses milliseconds via stop_timeout_ms) */ stop_timeout?: number; /** Number of times the server has been automatically restarted */ restart_count?: number; /** Last exit code (null if process is still running) */ exit_code?: number | null; /** Health check configuration (if configured) */ health_check?: HealthCheckConfig; /** Whether the server is healthy (only present if health_check is configured) */ healthy?: boolean; /** Health check status details (only present if health_check is configured) */ health_status?: HealthCheckStatus; /** When the server was created */ created_at: string; /** When the server was last updated */ updated_at: string; } /** * Sandbox server info returned by setup flows */ interface SandboxServerInfo { slug: string; port?: number; url?: string; status: ServerStatus; /** Whether the server is healthy (only present if health_check is configured) */ healthy?: boolean; /** Health check status details (only present if health_check is configured) */ health_check?: HealthCheckStatus; } /** * Sandbox overlay info returned by setup flows */ interface SandboxOverlayInfo { id: string; source: string; target: string; copy_status: string; } /** * Ready response (public endpoint) */ interface ReadyResponse { /** Whether all servers have ports allocated (URLs available) */ ready: boolean; /** Whether all servers with health checks are passing */ healthy?: boolean; servers: SandboxServerInfo[]; overlays: SandboxOverlayInfo[]; } /** * Servers list response */ interface ServersListResponse { status: string; message: string; data: { servers: ServerInfo[]; }; } /** * Server response */ interface ServerResponse { status: string; message: string; data: { server: ServerInfo; }; } /** * Server stop response */ interface ServerStopResponse { status: string; message: string; data: { slug: string; }; } /** * Server logs stream type */ type ServerLogStream = 'stdout' | 'stderr' | 'combined'; /** * Server logs response */ interface ServerLogsResponse { status: string; message: string; data: { slug: string; stream: ServerLogStream; logs: string; }; } /** * Server status update response */ interface ServerStatusUpdateResponse { status: string; message: string; data: { slug: string; status: ServerStatus; }; } /** * Environment variables response */ interface EnvGetResponse { status: string; message: string; data: { file: string; variables: Record; }; } /** * Environment set response */ interface EnvSetResponse { status: string; message: string; data: { file: string; keys: string[]; }; } /** * Environment delete response */ interface EnvDeleteResponse { status: string; message: string; data: { file: string; keys: string[]; }; } /** * Batch file operation type */ type BatchFileOperation = 'write' | 'delete'; /** * Batch file operation result */ interface BatchWriteResult { path: string; success: boolean; error?: string; file?: FileInfo; } /** * Batch file operation response */ interface BatchWriteResponse { message: string; data: { results: BatchWriteResult[]; }; } /** * Sandbox - Full-featured gateway sandbox implementation * * Provides complete feature set including: * - Interactive terminals (PTY and exec modes) * - Managed servers * - File watchers with real-time events * - Authentication (session tokens, magic links) * - Environment management * - Signal service for port/error events * - Child sandbox creation * * This is the most feature-rich implementation available. * * @example * ```typescript * import { Sandbox } from 'computesdk' * * // Pattern 1: Admin operations (requires access token) * const sandbox = new Sandbox({ * sandboxUrl: 'https://sandbox-123.sandbox.computesdk.com', * token: accessToken, // From edge service * }); * * // Create session token for delegated operations * const sessionToken = await sandbox.createSessionToken({ * description: 'My Application', * expiresIn: 604800, // 7 days * }); * * // Pattern 2: Delegated operations (binary protocol by default) * const sandbox2 = new Sandbox({ * sandboxUrl: 'https://sandbox-123.sandbox.computesdk.com', * token: sessionToken.data.token, * // protocol: 'binary' is the default (50-90% size reduction) * }); * * // Execute a one-off command * const result = await sandbox.execute({ command: 'ls -la' }); * console.log(result.data.stdout); * * // Run code * const codeResult = await sandbox.runCode('console.log("Hello!")', 'node'); * * // Work with files * const files = await sandbox.listFiles('/home/project'); * await sandbox.writeFile('/home/project/test.txt', 'Hello, World!'); * const content = await sandbox.readFile('/home/project/test.txt'); * * // Create a PTY terminal with real-time output (interactive shell) * const terminal = await sandbox.createTerminal({ pty: true }); * terminal.on('output', (data) => console.log(data)); * terminal.write('ls -la\n'); * await terminal.destroy(); * * // Create an exec terminal for command tracking * const execTerminal = await sandbox.createTerminal({ pty: false }); * const result = await execTerminal.execute('npm install', { background: true }); * const cmd = await sandbox.getCommand(execTerminal.getId(), result.data.cmd_id); * console.log(cmd.data.status); // "running" | "completed" | "failed" * await execTerminal.destroy(); * * // Watch for file changes * const watcher = await sandbox.createWatcher('/home/project', { * ignored: ['node_modules', '.git'] * }); * watcher.on('change', (event) => { * console.log(`${event.event}: ${event.path}`); * }); * await watcher.destroy(); * * // Monitor system signals * const signals = await sandbox.startSignals(); * signals.on('port', (event) => { * console.log(`Port ${event.port} opened: ${event.url}`); * }); * await signals.stop(); * * // Clean up * await sandbox.disconnect(); * ``` */ declare class Sandbox { readonly sandboxId: string; readonly provider: string; readonly filesystem: ExtendedFileSystem; readonly terminal: Terminal; readonly run: Run; readonly server: Server; readonly watcher: Watcher; readonly sessionToken: SessionToken; readonly magicLink: MagicLink; readonly signal: Signal; readonly file: File; readonly env: Env; readonly auth: Auth; readonly child: Child; private config; private _token; private _ws; private WebSocketImpl; private _terminals; constructor(config: SandboxConfig); /** * Get or create internal WebSocket manager */ private ensureWebSocket; /** * Create and configure a TerminalInstance from response data */ private hydrateTerminal; private request; /** * Check service health */ health(): Promise; /** * Create a session token (requires access token) * * Session tokens are delegated credentials that can authenticate API requests * without exposing your access token. Only access tokens can create session tokens. * * @param options - Token configuration * @throws {Error} 403 Forbidden if called with a session token */ createSessionToken(options?: { description?: string; expiresIn?: number; }): Promise; /** * List all session tokens (requires access token) * * @throws {Error} 403 Forbidden if called with a session token */ listSessionTokens(): Promise; /** * Get details of a specific session token (requires access token) * * @param tokenId - The token ID * @throws {Error} 403 Forbidden if called with a session token */ getSessionToken(tokenId: string): Promise; /** * Revoke a session token (requires access token) * * @param tokenId - The token ID to revoke * @throws {Error} 403 Forbidden if called with a session token */ revokeSessionToken(tokenId: string): Promise; /** * Generate a magic link for browser authentication (requires access token) * * Magic links are one-time URLs that automatically create a session token * and set it as a cookie in the user's browser. This provides an easy way * to authenticate users in browser-based applications. * * The generated link: * - Expires after 5 minutes or first use (whichever comes first) * - Automatically creates a new session token (7 day expiry) * - Sets the session token as an HttpOnly cookie * - Redirects to the specified URL * * @param options - Magic link configuration * @throws {Error} 403 Forbidden if called with a session token */ createMagicLink(options?: { redirectUrl?: string; }): Promise; /** * Check authentication status * Does not require authentication */ getAuthStatus(): Promise; /** * Get authentication information and usage instructions * Does not require authentication */ getAuthInfo(): Promise; /** * Set authentication token manually * @param token - Access token or session token */ setToken(token: string): void; /** * Get current authentication token */ getToken(): string | null; /** * Get current sandbox URL */ getSandboxUrl(): string; /** * Execute a one-off command without creating a persistent terminal * * @example * ```typescript * // Synchronous execution (waits for completion) * const result = await sandbox.execute({ command: 'npm test' }); * console.log(result.data.exit_code); * * // Background execution (returns immediately) * const result = await sandbox.execute({ * command: 'npm install', * background: true * }); * // Use result.data.terminal_id and result.data.cmd_id to track * const cmd = await sandbox.getCommand(result.data.terminal_id!, result.data.cmd_id!); * ``` */ execute(options: { command: string; shell?: string; background?: boolean; }): Promise; /** * Execute code with automatic language detection (POST /run/code) * * @param code - The code to execute * @param language - Programming language (optional - auto-detects if not specified) * @returns Code execution result with output, exit code, and detected language * * @example * ```typescript * // Auto-detect language * const result = await sandbox.runCodeRequest('print("Hello")'); * console.log(result.data.output); // "Hello\n" * console.log(result.data.language); // "python" * * // Explicit language * const result = await sandbox.runCodeRequest('console.log("Hi")', 'node'); * ``` */ runCodeRequest(code: string, language?: string): Promise; /** * Execute a command and get the result * Lower-level method that returns the raw API response * * @param options.command - Command to execute * @param options.shell - Shell to use (optional) * @param options.background - Run in background (optional) * @param options.cwd - Working directory for the command (optional) * @param options.env - Environment variables (optional) * @returns Command execution result * * @example * ```typescript * const result = await sandbox.runCommandRequest({ command: 'ls -la' }); * console.log(result.data.stdout); * ``` */ runCommandRequest(options: { command: string; shell?: string; background?: boolean; stream?: boolean; cwd?: string; env?: Record; }): Promise; /** * List files at the specified path */ listFiles(path?: string): Promise; /** * Create a new file with optional content */ createFile(path: string, content?: string): Promise; /** * Get file metadata (without content) */ getFile(path: string): Promise; /** * Encode a file path for use in URLs * Strips leading slash and encodes each segment separately to preserve path structure */ private encodeFilePath; /** * Read file content */ readFile(path: string): Promise; /** * Write file content (creates or updates) */ writeFile(path: string, content: string): Promise; /** * Delete a file or directory */ deleteFile(path: string): Promise; /** * Check if a file exists (HEAD request) * @returns true if file exists, false otherwise */ checkFileExists(path: string): Promise; /** * Batch file operations (write or delete multiple files) * * Features: * - Deduplication: Last operation wins per path * - File locking: Prevents race conditions * - Deterministic ordering: Alphabetical path sorting * - Partial failure handling: Returns 207 Multi-Status with per-file results * * @param files - Array of file operations * @returns Results for each file operation * * @example * ```typescript * // Write multiple files * const results = await sandbox.batchWriteFiles([ * { path: '/app/file1.txt', operation: 'write', content: 'Hello' }, * { path: '/app/file2.txt', operation: 'write', content: 'World' }, * ]); * * // Mixed operations (write and delete) * const results = await sandbox.batchWriteFiles([ * { path: '/app/new.txt', operation: 'write', content: 'New file' }, * { path: '/app/old.txt', operation: 'delete' }, * ]); * ``` */ batchWriteFiles(files: Array<{ path: string; operation: 'write' | 'delete'; content?: string; }>): Promise; /** * Create a new filesystem overlay from a template directory * * Overlays enable instant sandbox setup by symlinking template files first, * then copying heavy directories (node_modules, .venv, etc.) in the background. * * @param options - Overlay creation options * @param options.source - Absolute path to source directory (template) * @param options.target - Relative path in sandbox where overlay will be mounted * @returns Overlay response with copy status * * @example * ```typescript * // Prefer using sandbox.filesystem.overlay.create() for camelCase response * const overlay = await sandbox.filesystem.overlay.create({ * source: '/templates/nextjs', * target: 'project', * }); * console.log(overlay.copyStatus); // 'pending' | 'in_progress' | 'complete' | 'failed' * ``` */ createOverlay(options: CreateOverlayOptions): Promise; /** * List all filesystem overlays for the current sandbox * @returns List of overlays with their copy status */ listOverlays(): Promise; /** * Get a specific filesystem overlay by ID * * Useful for polling the copy status of an overlay. * * @param id - Overlay ID * @returns Overlay details with current copy status */ getOverlay(id: string): Promise; /** * Delete a filesystem overlay * @param id - Overlay ID */ deleteOverlay(id: string): Promise; /** * Create a new persistent terminal session * * Terminal Modes: * - **PTY mode** (pty: true): Interactive shell with real-time WebSocket streaming * - Use for: Interactive shells, vim/nano, real-time output * - Methods: write(), resize(), on('output') * * - **Exec mode** (pty: false, default): Command tracking with HTTP polling * - Use for: CI/CD, automation, command tracking, exit codes * - Methods: execute(), getCommand(), listCommands(), waitForCommand() * * @example * ```typescript * // PTY mode - Interactive shell * const pty = await sandbox.createTerminal({ pty: true, shell: '/bin/bash' }); * pty.on('output', (data) => console.log(data)); * pty.write('npm install\n'); * * // Exec mode - Command tracking * const exec = await sandbox.createTerminal({ pty: false }); * const result = await exec.execute('npm test', { background: true }); * const cmd = await sandbox.waitForCommand(exec.getId(), result.data.cmd_id); * console.log(cmd.data.exit_code); * * // Backward compatible - creates PTY terminal * const terminal = await sandbox.createTerminal('/bin/bash'); * ``` * * @param options - Terminal creation options * @param options.shell - Shell to use (e.g., '/bin/bash', '/bin/sh') - PTY mode only * @param options.encoding - Encoding for terminal I/O: 'raw' (default) or 'base64' (binary-safe) * @param options.pty - Terminal mode: true = PTY (interactive shell), false = exec (command tracking, default) * @returns Terminal instance with event handling */ createTerminal(shellOrOptions?: string | { shell?: string; encoding?: 'raw' | 'base64'; pty?: boolean; }, encoding?: 'raw' | 'base64'): Promise; /** * List all active terminals (fetches from API) */ listTerminals(): Promise; /** * Get terminal by ID */ getTerminal(id: string): Promise; /** * List all commands executed in a terminal (exec mode only) * @param terminalId - The terminal ID * @returns List of all commands with their status * @throws {Error} If terminal is in PTY mode (command tracking not available) */ listCommands(terminalId: string): Promise; /** * Get details of a specific command execution (exec mode only) * @param terminalId - The terminal ID * @param cmdId - The command ID * @returns Command execution details including stdout, stderr, and exit code * @throws {Error} If terminal is in PTY mode or command not found */ getCommand(terminalId: string, cmdId: string): Promise; /** * Wait for a command to complete (HTTP long-polling, exec mode only) * @param terminalId - The terminal ID * @param cmdId - The command ID * @param timeout - Optional timeout in seconds (0 = no timeout) * @returns Command execution details when completed * @throws {Error} If terminal is in PTY mode, command not found, or timeout occurs */ waitForCommand(terminalId: string, cmdId: string, timeout?: number): Promise; /** * Wait for a background command to complete using long-polling * * Uses the server's long-polling endpoint with configurable timeout. * The tunnel supports up to 5 minutes (300 seconds) via X-Request-Timeout header. * * @param terminalId - The terminal ID * @param cmdId - The command ID * @param options - Wait options (timeoutSeconds, default 300) * @returns Command result with final status * @throws Error if command fails or times out * @internal */ private waitForCommandCompletion; /** * Wait for a command with extended timeout support * Uses X-Request-Timeout header for tunnel timeout configuration * @internal */ private waitForCommandWithTimeout; /** * Create a new file watcher with WebSocket integration * @param path - Path to watch * @param options - Watcher options * @param options.includeContent - Include file content in change events * @param options.ignored - Patterns to ignore * @param options.encoding - Encoding for file content: 'raw' (default) or 'base64' (binary-safe) * @returns FileWatcher instance with event handling */ createWatcher(path: string, options?: { includeContent?: boolean; ignored?: string[]; encoding?: 'raw' | 'base64'; }): Promise; /** * List all active file watchers (fetches from API) */ listWatchers(): Promise; /** * Get file watcher by ID */ getWatcher(id: string): Promise; /** * Start the signal service with WebSocket integration * @returns SignalService instance with event handling */ startSignals(): Promise; /** * Get the signal service status (fetches from API) */ getSignalStatus(): Promise; /** * Emit a port signal */ emitPortSignal(port: number, type: 'open' | 'close', url: string): Promise; /** * Emit a port signal (alternative endpoint using path parameters) */ emitPortSignalAlt(port: number, type: 'open' | 'close'): Promise; /** * Emit an error signal */ emitErrorSignal(message: string): Promise; /** * Emit a server ready signal */ emitServerReadySignal(port: number, url: string): Promise; /** * Get environment variables from a .env file * @param file - Path to the .env file (relative to sandbox root) */ getEnv(file: string): Promise; /** * Set (merge) environment variables in a .env file * @param file - Path to the .env file (relative to sandbox root) * @param variables - Key-value pairs to set */ setEnv(file: string, variables: Record): Promise; /** * Delete environment variables from a .env file * @param file - Path to the .env file (relative to sandbox root) * @param keys - Keys to delete */ deleteEnv(file: string, keys: string[]): Promise; /** * Check if an environment file exists (HEAD request) * @param file - Path to the .env file (relative to sandbox root) * @returns true if file exists, false otherwise */ checkEnvFile(file: string): Promise; /** * List all managed servers */ listServers(): Promise; /** * Start a new managed server with optional supervisor settings * * @param options - Server configuration * @param options.slug - Unique server identifier * @param options.install - Install command (optional, runs blocking before start, e.g., "npm install") * @param options.start - Command to start the server (e.g., "npm run dev") * @param options.path - Working directory (optional) * @param options.env_file - Path to .env file relative to path (optional) * @param options.environment - Inline environment variables (merged with env_file if both provided) * @param options.port - Requested port (preallocated before start) * @param options.strict_port - If true, fail instead of auto-incrementing when port is taken * @param options.autostart - Auto-start on daemon boot (default: true) * @param options.overlay - Inline overlay to create before starting * @param options.overlays - Additional overlays to create before starting * @param options.depends_on - Overlay IDs this server depends on * @param options.restart_policy - When to automatically restart: 'never' (default), 'on-failure', 'always' * @param options.max_restarts - Maximum restart attempts, 0 = unlimited (default: 0) * @param options.restart_delay_ms - Delay between restart attempts in milliseconds (default: 1000) * @param options.stop_timeout_ms - Graceful shutdown timeout in milliseconds (default: 10000) * * @example * ```typescript * // Basic server * await sandbox.startServer({ * slug: 'web', * start: 'npm run dev', * path: '/app', * }); * * // With install command and supervisor settings * await sandbox.startServer({ * slug: 'api', * install: 'npm install', * start: 'node server.js', * path: '/app', * environment: { NODE_ENV: 'production', PORT: '3000' }, * restart_policy: 'on-failure', * max_restarts: 5, * restart_delay_ms: 2000, * stop_timeout_ms: 5000, * }); * * // With inline overlay dependencies * await sandbox.startServer({ * slug: 'web', * start: 'npm run dev', * path: '/app', * overlay: { * source: '/templates/nextjs', * target: 'app', * strategy: 'smart', * }, * }); * ``` */ startServer(options: { slug: string; install?: string; start: string; path?: string; env_file?: string; environment?: Record; port?: number; strict_port?: boolean; autostart?: boolean; overlay?: Omit; overlays?: Array>; depends_on?: string[]; restart_policy?: RestartPolicy; max_restarts?: number; restart_delay_ms?: number; stop_timeout_ms?: number; }): Promise; /** * Get information about a specific server * @param slug - Server slug */ getServer(slug: string): Promise; /** * Stop a managed server (non-destructive) * @param slug - Server slug */ stopServer(slug: string): Promise; /** * Delete a managed server configuration * @param slug - Server slug */ deleteServer(slug: string): Promise; /** * Restart a managed server * @param slug - Server slug */ restartServer(slug: string): Promise; /** * Get logs for a managed server * @param slug - Server slug * @param options - Options for log retrieval */ getServerLogs(slug: string, options?: { stream?: ServerLogStream; }): Promise; /** * Update server status (internal use) * @param slug - Server slug * @param status - New server status */ updateServerStatus(slug: string, status: ServerStatus): Promise; /** * Get readiness status for autostarted servers and overlays */ ready(): Promise; /** * Create a new sandbox environment */ createSandbox(options?: CreateSandboxOptions$1): Promise; /** * List all sandboxes */ listSandboxes(): Promise; /** * Get sandbox details */ getSandbox(subdomain: string): Promise; /** * Delete a sandbox */ deleteSandbox(subdomain: string, deleteFiles?: boolean): Promise; /** * Get WebSocket URL for real-time communication * @private */ private getWebSocketUrl; /** * Execute code in the sandbox (convenience method) * * Delegates to sandbox.run.code() - prefer using that directly for new code. * * @param code - The code to execute * @param language - Programming language (auto-detected if not specified) * @returns Code execution result */ runCode(code: string, language?: 'node' | 'python'): Promise<{ output: string; exitCode: number; language: string; }>; /** * Execute shell command in the sandbox * * Sends clean command string to server - no preprocessing or shell wrapping. * The server handles shell invocation, working directory, and backgrounding. * * @param command - The command to execute (raw string, e.g., "npm install") * @param options - Execution options * @param options.background - Run in background (server uses goroutines) * @param options.cwd - Working directory (server uses cmd.Dir) * @param options.env - Environment variables (server uses cmd.Env) * @param options.onStdout - Callback for streaming stdout data * @param options.onStderr - Callback for streaming stderr data * @returns Command execution result * * @example * ```typescript * // Simple command * await sandbox.runCommand('ls -la') * * // With working directory * await sandbox.runCommand('npm install', { cwd: '/app' }) * * // Background with env vars * await sandbox.runCommand('node server.js', { * background: true, * env: { PORT: '3000' } * }) * * // With streaming output * await sandbox.runCommand('npm install', { * onStdout: (data) => console.log(data), * onStderr: (data) => console.error(data), * }) * ``` */ runCommand(command: string, options?: { background?: boolean; cwd?: string; env?: Record; onStdout?: (data: string) => void; onStderr?: (data: string) => void; }): Promise<{ stdout: string; stderr: string; exitCode: number; durationMs: number; }>; /** * Get server information * Returns details about the server including auth status, main subdomain, sandbox count, and version */ getServerInfo(): Promise; /** * Get sandbox information */ getInfo(): Promise<{ id: string; provider: string; runtime: 'node' | 'python'; status: 'running' | 'stopped' | 'error'; createdAt: Date; timeout: number; metadata?: Record; }>; /** * Get URL for accessing sandbox on a specific port (Sandbox interface method) */ getUrl(options: { port: number; protocol?: string; }): Promise; /** * Get provider instance * Note: Not available when using Sandbox directly - only available through gateway provider */ getProvider(): never; /** * Get native provider instance * Returns the Sandbox itself since this IS the sandbox implementation */ getInstance(): this; /** * Destroy the sandbox (Sandbox interface method) * * If a destroyHandler was provided (e.g., from gateway), calls it to destroy * the sandbox on the backend. Otherwise, only disconnects the WebSocket. */ destroy(): Promise; /** * Disconnect WebSocket * * Note: This only disconnects the WebSocket. Terminals, watchers, and signals * will continue running on the server until explicitly destroyed via their * respective destroy() methods or the DELETE endpoints. */ disconnect(): Promise; } /** * Helpers for building setup payloads used by COMPUTESDK_SETUP_B64 or POST /sandboxes */ type SetupOverlayConfig = Omit; interface SetupPayload { overlays?: SetupOverlayConfig[]; servers?: ServerStartOptions[]; } interface BuildSetupPayloadOptions { overlays?: CreateOverlayOptions[]; servers?: ServerStartOptions[]; } /** * Build a setup payload for COMPUTESDK_SETUP_B64 or POST /sandboxes */ declare const buildSetupPayload: (options: BuildSetupPayloadOptions) => SetupPayload; /** * Build and base64-encode a setup payload for COMPUTESDK_SETUP_B64 */ declare const encodeSetupPayload: (options: BuildSetupPayloadOptions) => string; /** * Unified Provider Configuration * * Single source of truth for all provider auth requirements. * Used by both explicit mode (computesdk) and magic mode (workbench). */ /** * Provider auth requirements * * Structure: { provider: [[option1_vars], [option2_vars], ...] } * - Outer array: OR conditions (any option can satisfy auth) * - Inner arrays: AND conditions (all vars in option must be present) * * Example: vercel: [['OIDC_TOKEN'], ['TOKEN', 'TEAM_ID', 'PROJECT_ID']] * -> Ready if OIDC_TOKEN is set, OR if all three traditional vars are set */ declare const PROVIDER_AUTH: { readonly e2b: readonly [readonly ["E2B_API_KEY"]]; readonly modal: readonly [readonly ["MODAL_TOKEN_ID", "MODAL_TOKEN_SECRET"]]; readonly railway: readonly [readonly ["RAILWAY_API_KEY", "RAILWAY_PROJECT_ID", "RAILWAY_ENVIRONMENT_ID"]]; readonly render: readonly [readonly ["RENDER_API_KEY", "RENDER_OWNER_ID"]]; readonly daytona: readonly [readonly ["DAYTONA_API_KEY"]]; readonly vercel: readonly [readonly ["VERCEL_OIDC_TOKEN"], readonly ["VERCEL_TOKEN", "VERCEL_TEAM_ID", "VERCEL_PROJECT_ID"]]; readonly runloop: readonly [readonly ["RUNLOOP_API_KEY"]]; readonly cloudflare: readonly [readonly ["CLOUDFLARE_API_TOKEN", "CLOUDFLARE_ACCOUNT_ID"]]; readonly codesandbox: readonly [readonly ["CSB_API_KEY"]]; readonly blaxel: readonly [readonly ["BL_API_KEY", "BL_WORKSPACE"]]; readonly namespace: readonly [readonly ["NSC_TOKEN"]]; readonly hopx: readonly [readonly ["HOPX_API_KEY"]]; }; /** * All supported provider names (excluding gateway which is special) */ declare const PROVIDER_NAMES: ProviderName[]; /** * Provider name type derived from PROVIDER_AUTH */ type ProviderName = keyof typeof PROVIDER_AUTH; /** * Header mapping for each provider * Maps config field names to HTTP header names */ declare const PROVIDER_HEADERS: Record>; /** * Environment variable to config field mapping for each provider */ declare const PROVIDER_ENV_MAP: Record>; /** * Dashboard URLs for each provider (for error messages) */ declare const PROVIDER_DASHBOARD_URLS: Record; /** * Check if a provider name is valid */ declare function isValidProvider(name: string): name is ProviderName; /** * Build headers from provider config */ declare function buildProviderHeaders(provider: ProviderName, config: Record): Record; /** * Get provider config from environment variables */ declare function getProviderConfigFromEnv(provider: ProviderName): Record; /** * Check if provider has complete auth from environment */ declare function isProviderAuthComplete(provider: ProviderName): boolean; /** * Get missing env vars for a provider (returns the option closest to completion) */ declare function getMissingEnvVars(provider: ProviderName): string[]; /** * Compute API - Gateway HTTP Implementation * * Provides the unified compute.* API using direct HTTP calls to the gateway. * The `compute` export works as both a singleton and a callable function: * * - Singleton: `compute.sandbox.create()` (auto-detects from env vars) * - Callable: `compute({ provider: 'e2b', ... }).sandbox.create()` (explicit config) */ /** * Explicit compute configuration for callable mode */ interface ExplicitComputeConfig { /** Provider name to use */ provider: ProviderName; /** * ComputeSDK API key (required for gateway mode) * @deprecated Use `computesdkApiKey` for clarity */ apiKey?: string; /** ComputeSDK API key (required for gateway mode) */ computesdkApiKey?: string; /** Optional gateway URL override */ gatewayUrl?: string; /** HTTP request timeout for gateway calls in milliseconds */ requestTimeoutMs?: number; /** * WebSocket implementation for environments without native WebSocket support. * In Node.js < 22, pass the 'ws' package: `import WebSocket from 'ws'` */ WebSocket?: WebSocketConstructor; /** Provider-specific configurations */ e2b?: { apiKey?: string; projectId?: string; templateId?: string; }; modal?: { tokenId?: string; tokenSecret?: string; }; railway?: { apiToken?: string; projectId?: string; environmentId?: string; }; render?: { apiKey?: string; serviceId?: string; }; daytona?: { apiKey?: string; }; vercel?: { oidcToken?: string; token?: string; teamId?: string; projectId?: string; }; runloop?: { apiKey?: string; }; cloudflare?: { apiToken?: string; accountId?: string; }; codesandbox?: { apiKey?: string; templateId?: string; timeout?: number; }; blaxel?: { apiKey?: string; workspace?: string; image?: string; region?: string; memory?: number; }; namespace?: { token?: string; }; hopx?: { apiKey?: string; }; } /** * Options for creating a sandbox via the gateway * * Note: Runtime is determined by the provider, not specified at creation time. * Use sandbox.runCode(code, runtime) to specify which runtime to use for execution. */ interface CreateSandboxOptions { timeout?: number; templateId?: string; metadata?: Record; envs?: Record; name?: string; namespace?: string; directory?: string; overlays?: SetupOverlayConfig[]; servers?: ServerStartOptions[]; /** Docker image to use for the sandbox (for infrastructure providers like Railway) */ image?: string; /** Provider-specific snapshot to create from (e.g., Vercel snapshots) */ snapshotId?: string; } /** * Options for finding or creating a named sandbox */ interface FindOrCreateSandboxOptions extends CreateSandboxOptions { name: string; namespace?: string; } /** * Options for finding a named sandbox */ interface FindSandboxOptions { name: string; namespace?: string; } /** * Options for extending sandbox timeout */ interface ExtendTimeoutOptions { duration?: number; } /** * Compute singleton implementation */ declare class ComputeManager { private config; private autoConfigured; /** * Lazy auto-configure from environment if not explicitly configured */ private ensureConfigured; /** * Get gateway config, throwing if not configured */ private getGatewayConfig; /** * Explicitly configure the compute singleton * * @example * ```typescript * import { compute } from 'computesdk'; * * compute.setConfig({ * provider: 'e2b', * apiKey: 'computesdk_xxx', * e2b: { apiKey: 'e2b_xxx' } * }); * * const sandbox = await compute.sandbox.create(); * ``` */ setConfig(config: ExplicitComputeConfig): void; sandbox: { /** * Create a new sandbox * * @example * ```typescript * const sandbox = await compute.sandbox.create({ * directory: '/custom/path', * overlays: [ * { * source: '/templates/nextjs', * target: 'app', * strategy: 'smart', * }, * ], * servers: [ * { * slug: 'web', * start: 'npm run dev', * path: '/app', * }, * ], * }); * ``` */ create: (options?: CreateSandboxOptions) => Promise; /** * Get an existing sandbox by ID */ getById: (sandboxId: string) => Promise; /** * List all active sandboxes */ list: () => Promise; /** * Destroy a sandbox */ destroy: (sandboxId: string) => Promise; /** * Find existing or create new sandbox by (namespace, name) */ findOrCreate: (options: FindOrCreateSandboxOptions) => Promise; /** * Find existing sandbox by (namespace, name) without creating */ find: (options: FindSandboxOptions) => Promise; /** * Extend sandbox timeout/expiration */ extendTimeout: (sandboxId: string, options?: ExtendTimeoutOptions) => Promise; }; } /** * Callable compute interface - dual nature as both singleton and factory * * This interface represents the compute export's two modes: * 1. As a ComputeManager singleton (accessed via properties like compute.sandbox) * 2. As a factory function (called with config to create new instances) */ interface CallableCompute extends ComputeManager { /** Create a new compute instance with explicit configuration */ (config: ExplicitComputeConfig): ComputeManager; /** Explicitly configure the singleton */ setConfig(config: ExplicitComputeConfig): void; } /** * Callable compute - works as both singleton and factory function * * @example * ```typescript * import { compute } from 'computesdk'; * * // Singleton mode (auto-detects from env vars) * const sandbox1 = await compute.sandbox.create(); * * // Callable mode (explicit config) * const sandbox2 = await compute({ * provider: 'e2b', * apiKey: 'computesdk_xxx', * e2b: { apiKey: 'e2b_xxx' } * }).sandbox.create(); * ``` */ declare const compute: CallableCompute; /** * Auto-Detection Module * * Automatically detects gateway mode and provider from environment variables. * Enables zero-config usage of ComputeSDK. */ /** * Check if gateway mode is enabled * Gateway mode requires COMPUTESDK_API_KEY to be set */ declare function isGatewayModeEnabled(): boolean; /** * Detect which provider to use from environment variables * * Detection order: * 1. Check for explicit COMPUTESDK_PROVIDER override * 2. Auto-detect based on PROVIDER_PRIORITY order * * @returns Provider name or null if none detected */ declare function detectProvider(): string | null; /** * Build provider-specific headers from environment variables * These headers are passed through to the gateway */ declare function getProviderHeaders(provider: string): Record; /** * Gateway configuration object */ interface GatewayConfig { apiKey: string; gatewayUrl: string; provider: string; providerHeaders: Record; requestTimeoutMs?: number; WebSocket?: WebSocketConstructor; } /** * Main auto-configuration function * Returns gateway configuration or null if auto-detection not possible * * @throws Error if COMPUTESDK_API_KEY is set but no provider detected */ declare function autoConfigureCompute(): GatewayConfig | null; /** * ComputeSDK Constants * * Default configuration values and provider definitions */ /** * Default gateway URL for sandbox lifecycle operations */ declare const GATEWAY_URL = "https://gateway.computesdk.com"; /** * Provider detection priority order * When multiple provider credentials are detected, use the first one in this list */ declare const PROVIDER_PRIORITY: readonly ["e2b", "railway", "render", "daytona", "modal", "runloop", "vercel", "cloudflare", "codesandbox", "blaxel", "namespace", "hopx"]; /** * Required environment variables for each provider * @deprecated Use PROVIDER_AUTH from provider-config instead */ declare const PROVIDER_ENV_VARS: { readonly e2b: readonly ["E2B_API_KEY"]; readonly railway: readonly ["RAILWAY_API_KEY", "RAILWAY_PROJECT_ID", "RAILWAY_ENVIRONMENT_ID"]; readonly render: readonly ["RENDER_API_KEY", "RENDER_OWNER_ID"]; readonly daytona: readonly ["DAYTONA_API_KEY"]; readonly modal: readonly ["MODAL_TOKEN_ID", "MODAL_TOKEN_SECRET"]; readonly runloop: readonly ["RUNLOOP_API_KEY"]; readonly vercel: readonly ["VERCEL_TOKEN", "VERCEL_TEAM_ID", "VERCEL_PROJECT_ID"]; readonly cloudflare: readonly ["CLOUDFLARE_API_TOKEN", "CLOUDFLARE_ACCOUNT_ID"]; readonly codesandbox: readonly ["CSB_API_KEY"]; readonly blaxel: readonly ["BL_API_KEY", "BL_WORKSPACE"]; readonly namespace: readonly ["NSC_TOKEN"]; readonly hopx: readonly ["HOPX_API_KEY"]; }; export { type CallableCompute, type CodeResult$1 as CodeResult, CommandExitError, type CommandResult$1 as CommandResult, type CreateSandboxOptions$1 as CreateSandboxOptions, type ExplicitComputeConfig, type FileEntry, FileWatcher, GATEWAY_URL, Sandbox as GatewaySandbox, MessageType, PROVIDER_AUTH, PROVIDER_DASHBOARD_URLS, PROVIDER_ENV_MAP, PROVIDER_ENV_VARS, PROVIDER_HEADERS, PROVIDER_NAMES, PROVIDER_PRIORITY, type ProviderName, type ProviderSandboxInfo, type RunCommandOptions, type Runtime, Sandbox, type SandboxFileSystem, type SandboxInfo$1 as SandboxInfo, type Sandbox$1 as SandboxInterface, type SandboxStatus, type SetupOverlayConfig, type SetupPayload, SignalService, TerminalInstance, type WebSocketConstructor, autoConfigureCompute, buildProviderHeaders, buildSetupPayload, compute, decodeBinaryMessage, detectProvider, encodeBinaryMessage, encodeSetupPayload, getMissingEnvVars, getProviderConfigFromEnv, getProviderHeaders, isCommandExitError, isGatewayModeEnabled, isProviderAuthComplete, isValidProvider };