Files
FastGPT/sdk/sandbox/README.md
Jon cfded3af41 feat(sandbox): introduce unified sandbox adapter architecture (#6362)
Introduces a new, extensible sandbox adapter architecture to abstract
various sandbox providers behind a unified ISandbox interface. This
design utilizes an adapter pattern with a BaseSandboxAdapter, enabling
easy integration of providers like OpenSandboxAdapter and
MinimalProviderAdapter. It ensures consistent functionality across
environments through capability-driven polyfills for missing
features. This provides a scalable and maintainable foundation for
different execution environments.
2026-02-02 21:41:05 +08:00

5.5 KiB

@fastgpt/sandbox

A unified, high-level abstraction layer for cloud sandbox providers. It offers a consistent, vendor-agnostic interface for creating, managing, and interacting with sandboxed environments like OpenSandbox.

This package is ESM-only ("type": "module") and requires Node.js >= 20.

Installation

pnpm add @fastgpt/sandbox

Quick Start

The following example demonstrates the complete lifecycle of a sandbox: creating, executing commands, managing files, and finally, deleting it.

import { createSandbox } from '@fastgpt/sandbox';

async function main() {
  // 1. Create a sandbox with the OpenSandbox provider
  const sandbox = createSandbox({
    provider: 'opensandbox',
    connection: {
      apiKey: process.env.OPEN_SANDBOX_API_KEY,
      baseUrl: 'http://127.0.0.1:8080', // Your OpenSandbox server
      runtime: 'kubernetes',
    },
  });

  console.log(`Provider: ${sandbox.provider}`);
  console.log(`Native filesystem support: ${sandbox.capabilities.nativeFileSystem}`);

  try {
    // 2. Create the sandbox instance with a specific image
    await sandbox.create({
      image: { repository: 'nginx', tag: 'latest' },
      timeout: 3600, // Expiration in seconds
    });
    console.log(`Sandbox created: ${sandbox.id}`);

    // 3. Wait until the sandbox is fully ready
    await sandbox.waitUntilReady(60000); // 60-second timeout
    console.log('Sandbox is ready.');

    // 4. Execute a simple command
    const version = await sandbox.execute('nginx -v');
    console.log(`Nginx version: ${version.stdout || version.stderr}`);

    // 5. Execute a command with streaming output
    console.log('--- Streaming Execution ---');
    await sandbox.executeStream('for i in 1 2 3; do echo "Line $i"; sleep 0.5; done', {
      onStdout: (msg) => console.log(`  [stdout] ${msg.text}`),
      onStderr: (msg) => console.log(`  [stderr] ${msg.text}`),
      onComplete: (result) => console.log(`  [done] Exit code: ${result.exitCode}`),
    });

    // 6. Work with the filesystem
    console.log('\n--- Filesystem Operations ---');
    // Write a file
    await sandbox.writeFiles([
      {
        path: '/app/hello.js',
        data: `console.log('Hello from sandbox!');`,
      },
    ]);
    console.log('Written /app/hello.js');

    // Read the file back
    const [file] = await sandbox.readFiles(['/app/hello.js']);
    if (file && !file.error) {
        const content = new TextDecoder().decode(file.content);
        console.log(`Read content: "${content}"`);
    }

    // List directory
    const entries = await sandbox.listDirectory('/app');
    console.log('Directory listing for /app:', entries.map(e => e.name));


    // 7. Stop and delete the sandbox
    console.log('\n--- Cleanup ---');
    await sandbox.stop();
    console.log('Sandbox stopped.');
    
    if (sandbox.runtime !== 'kubernetes') {
      await sandbox.delete();
      console.log('Sandbox deleted.');
    }

  } catch (error) {
    console.error('An error occurred:', error);
  } finally {
    // 8. Close the connection
    await sandbox.close();
    console.log('Connection closed.');
  }
}

main();

API (ISandbox)

The createSandbox(options) function returns an instance that implements the ISandbox interface.

Lifecycle Management

  • create(options): Creates a new sandbox instance.
  • getInfo(): Retrieves detailed information about the sandbox.
  • waitUntilReady(timeout): Waits for the sandbox to become fully operational.
  • renewExpiration(seconds): Extends the sandbox's lifetime.
  • pause() / resume(): Pauses and resumes a running sandbox (if supported).
  • stop(): Stops the sandbox gracefully.
  • delete(): Deletes the sandbox instance.
  • close(): Closes the connection to the provider.

Command Execution

  • execute(command): Executes a command and returns the result after completion.
  • executeStream(command, handlers): Executes a command and streams stdout and stderr in real-time.
  • executeBackground(command): Starts a command in the background and returns a session handle.

Filesystem Operations

  • writeFiles(files): Writes one or more files to the sandbox.
  • readFiles(paths): Reads one or more files from the sandbox.
  • listDirectory(path): Lists the contents of a directory.
  • createDirectories(paths): Creates directories.
  • deleteFiles(paths): Deletes files.
  • moveFiles(files): Moves or renames files.

Health and Metrics

  • ping(): Performs a quick health check.
  • getMetrics(): Retrieves CPU and memory usage statistics.

Provider Capabilities

Different sandbox providers have different native capabilities. The SDK uses polyfills to provide a consistent API, but performance may vary.

Feature OpenSandbox MinimalProvider
Native Filesystem (polyfilled)
Streaming Output (fallback)
Background Exec ⚠️ (simulated)
Pause/Resume
Health Check ⚠️ (polyfilled)
Metrics ⚠️ (polyfilled)
File Search ⚠️ (polyfilled)

Error Handling

The SDK exports specific error types to facilitate robust error handling:

  • SandboxException
  • FeatureNotSupportedError
  • FileOperationError
  • CommandExecutionError
  • TimeoutError

Example:

import { FileOperationError } from '@fastgpt/sandbox';

try {
  await sandbox.readFiles(['/nonexistent-file']);
} catch (error) {
  if (error instanceof FileOperationError) {
    console.error(`File operation failed: ${error.message}`);
  }
}