sandbox

package module
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 27, 2026 License: MIT Imports: 23 Imported by: 0

README

Sandbox Go SDK

Go SDK for Sandbox control-plane, build-plane, and nano-executor CMD APIs.

Install

go get github.com/SeaArt-Infra/sandbox-go

Entrypoints

Preferred public API:

  • initialize once: sandbox.NewClient(baseURL, apiKey, opts...)
  • sandbox lifecycle through the root client: client.Create, client.Connect, client.List
  • sandbox runtime modules from the returned object: created.Commands(), created.Files(), created.Git(), created.Pty()
  • template builder through the root client: sandbox.NewTemplate() plus client.BuildTemplate(...)
  • low-level build plane via client.Build
  • raw runtime helper: createdSandbox.Runtime() or client.RuntimeFromSandbox(createdSandbox)

control and build both talk to the same gateway. Runtime access is derived from sandbox create/detail/connect responses; callers should not hardcode runtime endpoints or tokens. On a public gateway, tenant identity is derived from the authenticated API key; caller-supplied identity headers do not select another tenant.

For NFS-backed templates, see Workspace storage and lifecycle before deciding whether a Sandbox should use its default Sandbox-scoped directory or a reusable Workspace.

E2B Alignment

  • Supported alignment target: sandbox lifecycle, files, commands, git, PTY, and the high-level template DSL are designed to follow the same public workflow as e2b-docs/sdk.
  • Known unsupported area: snapshot APIs are not exposed because the underlying platform does not support them yet.
  • Go-specific note: the SDK aims for semantic equivalence rather than identical hand feel. Method names, context.Context, and (..., error) returns stay Go-native on purpose.
  • Runtime compatibility note: the SDK normalizes a few runtime-specific quirks so the high-level behavior stays E2B-like, such as missing-process Kill() results and PTY reconnect output framing.

Environment

Use environment variables for gateway configuration in all examples and quick starts:

  • SEAINFRA_BASE_URL: gateway entrypoint supplied by your platform administrator
  • SEAINFRA_API_KEY: API key used for gateway routing and authentication
  • SEAINFRA_TEMPLATE_ID: sandbox template identifier or official template type for your target environment

Set them once in your shell:

export SEAINFRA_BASE_URL="https://sandbox.example.com/api"
export SEAINFRA_API_KEY="..."
export SEAINFRA_TEMPLATE_ID="tpl-..."

The SDK intentionally has no default gateway. Obtain the endpoint and template reference from the administrator of the environment you are targeting. A template reference can be a concrete template ID such as tpl-... or a stable template type published by that environment.

Deployment Readiness

  • Initialize exactly one root client per process and reuse it.
  • Treat every quick start as creating billable or quota-bound resources unless it explicitly cleans them up.
  • Prefer explicit template references from configuration over hardcoded example values.
  • Prefer stable template types when your environment publishes them.
  • Use longer client timeouts for waitReady flows and image builds.
  • Derive runtime access from sandbox responses instead of storing runtime endpoints or tokens in config.

Compatibility

  • Go: see go.mod for the supported toolchain version used by this SDK.
  • API model: this SDK targets a unified sandbox gateway and keeps public template APIs limited to user-facing fields.
  • Stability: operator/admin routes may exist on the gateway, but they are not part of the public SDK workflow described in this README.
  • Retry model: treat create/delete/build operations as remote control-plane actions; add idempotency and retry policy in your application layer according to your workload.

Quick Start

Control Plane
package main

import (
	"context"
	"log"
	"os"
	"time"

	"github.com/SeaArt-Infra/sandbox-go"
	"github.com/SeaArt-Infra/sandbox-go/core"
)

func main() {
	client, err := sandbox.NewClient(
		os.Getenv("SEAINFRA_BASE_URL"),
		os.Getenv("SEAINFRA_API_KEY"),
		core.WithTimeout(180*time.Second),
	)
	if err != nil {
		log.Fatal(err)
	}

	ready := true
	timeout := int32(1800)
	createdSandbox, err := client.Create(context.Background(), os.Getenv("SEAINFRA_TEMPLATE_ID"), &sandbox.CreateOptions{
		WaitReady: &ready,
		Timeout:   &timeout,
	})
	if err != nil {
		log.Fatal(err)
	}
	defer createdSandbox.Delete(context.Background())

	log.Printf("sandbox=%s envd=%v", createdSandbox.SandboxID, createdSandbox.EnvdURL)
	if createdSandbox.EnvdURL != nil {
		runtime, err := createdSandbox.Runtime()
		if err != nil {
			log.Fatal(err)
		}
		log.Printf("runtime=%s", runtime.BaseURL())
	}
}
Bound Sandbox Workflow
client, err := sandbox.NewClient(os.Getenv("SEAINFRA_BASE_URL"), os.Getenv("SEAINFRA_API_KEY"))
if err != nil {
	log.Fatal(err)
}

listed, err := client.List(context.Background(), nil)
if err != nil {
	log.Fatal(err)
}

for _, sandbox := range listed {
	detail, err := sandbox.Reload(context.Background())
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("sandbox=%s status=%s", detail.SandboxID, detail.Status)
}
Template Build
client, err := sandbox.NewClient(os.Getenv("SEAINFRA_BASE_URL"), os.Getenv("SEAINFRA_API_KEY"))
if err != nil {
	log.Fatal(err)
}

ctx := context.Background()
base, err := client.Build.ResolveTemplateRef(ctx, "node")
if err != nil {
	log.Fatal(err)
}

template := sandbox.NewTemplate().
	FromTemplate(base.TemplateID).
	SetWorkdir("/app").
	Copy("./app", "/app", nil)

built, err := client.BuildTemplate(ctx, template, "demo:v1", &sandbox.TemplateBuildOptions{
	BaseTemplateID: base.TemplateID,
	Workdir:        "/app",
})
if err != nil {
	log.Fatal(err)
}

log.Printf("template=%s build=%s status=%s", built.TemplateID, built.BuildID, built.Status)
Persistent Workspaces

A Workspace is an optional, persistent logical NFS directory owned by one authenticated user in one project and namespace. It is not a host path and the SDK never exposes the underlying NFS layout.

The selected template owns the NFS mount configuration. The SDK may pass the opaque WorkspaceID and optional logical WorkspaceMounts; it cannot submit or inspect an NFS host path, physical sub-path, or runtime volume mount. A newly created Workspace is mounted below the platform-managed workspaces/<workspace-id> directory.

Use it when a replacement Sandbox must continue the same files. Existing calls that omit CreateOptions.WorkspaceID remain fully compatible: they retain the legacy per-Sandbox NFS subdirectory behavior.

The directory selection is entirely server-controlled:

  • Without WorkspaceID, the canonical NFS mount uses the generated Sandbox ID and its mount name, so two Sandboxes never share the same default directory.
  • With WorkspaceID, the canonical mount uses that Workspace's controlled directory. WorkspaceMounts can only create logical container views below it.
  • PromoteSandboxWorkspace adopts the existing legacy Sandbox directory as a Workspace without copying or moving any files.

The control-plane quick start above is also the correct call pattern for an NFS-backed Sandbox that does not need a reusable Workspace: use an approved NFS template and omit both WorkspaceID and WorkspaceMounts. The platform then selects the Sandbox-scoped directory automatically. The SDK caller never constructs an NFS path in either mode.

base, err := client.Build.ResolveTemplateRef(ctx, "nfs")
if err != nil {
	log.Fatal(err)
}

workspace, err := client.CreateWorkspace(ctx, base.TemplateID)
if err != nil {
	log.Fatal(err)
}

waitReady := true
created, err := client.Create(ctx, base.TemplateID, &sandbox.CreateOptions{
	WorkspaceID: workspace.WorkspaceID,
	WorkspaceMounts: []sandbox.WorkspaceMount{
		{Path: "/data"},
		{Path: "/app", SubPath: "apps"},
	},
	WaitReady:   &waitReady,
})
if err != nil {
	log.Fatal(err)
}
defer func() {
	_ = created.Delete(ctx) // Delete the Sandbox before deleting its Workspace.
	_ = client.DeleteWorkspace(ctx, workspace.WorkspaceID)
}()

The public lifecycle methods are CreateWorkspace, ListWorkspaces, GetWorkspace, DeleteWorkspace, and PromoteSandboxWorkspace. Promotion adopts an old NFS Sandbox directory without copying its contents.

Working Directory And File Access

The working directory is part of the template contract, not a per-Sandbox Create setting. For an NFS-backed runtime, derive a personal template from the approved NFS base and set its runtime workdir to the base template's logical NFS mount path. This example uses /agent-workspace; use the logical mount path published by the base template in the target environment.

base, err := client.Build.ResolveTemplateRef(ctx, "nfs")
if err != nil {
	return err
}

template := sandbox.NewTemplate().
	FromTemplate(base.TemplateID).
	SetWorkdir("/agent-workspace")

_, err = client.BuildTemplate(ctx, template, "nfs-workdir:v1", &sandbox.TemplateBuildOptions{
	BaseTemplateID: base.TemplateID,
	Visibility:     "personal",
	Workdir:        "/agent-workspace",
})
if err != nil {
	return err
}

There are three deliberately separate concepts:

  • Template.SetWorkdir(path) emits the image build WORKDIR for subsequent template build steps such as COPY and RUN.
  • TemplateBuildOptions.Workdir records the runtime working directory for Sandboxes created from the resulting template. It is also the root allowed by the executor Files() API.
  • CommandRunOptions.CWD applies only to that command. It does not change the runtime workdir or expand the paths allowed by Files().

Set the first two values to the same path when image build steps and runtime file access should use the same directory. They may differ, for example when the image is built under /app but runtime data lives under /agent-workspace. CreateOptions intentionally has no Workdir override. Use Commands() or Pty() for an additional logical Workspace view outside the runtime workdir, such as /data or /app. See Workspace storage and lifecycle for the complete contract.

Template Default Workspace Mappings

An NFS-backed template can define reusable logical mappings once. They are used only when a later Create call supplies WorkspaceID and omits explicit WorkspaceMounts; normal creates without WorkspaceID retain legacy NFS behavior. When both are omitted, the template's canonical workspace NFS container path is retained, for example /agent-workspace.

built, err := client.BuildTemplate(ctx, template, "workspace-ready:v1", &sandbox.TemplateBuildOptions{
	BaseTemplateID: base.TemplateID,
	Visibility:     "personal",
	WorkspaceMounts: []build.TemplateWorkspaceMount{
		{Path: "/data"},
		{Path: "/app", SubPath: "apps"},
	},
})
if err != nil {
	log.Fatal(err)
}

workspace, err := client.CreateWorkspace(ctx, built.TemplateID)
if err != nil {
	log.Fatal(err)
}
created, err := client.Create(ctx, built.TemplateID, &sandbox.CreateOptions{
	WorkspaceID: workspace.WorkspaceID,
	// No WorkspaceMounts: use the template defaults above.
})

TemplateWorkspaceMount intentionally contains only a container Path and an optional Workspace-relative SubPath. The SDK never accepts an NFS host root or physical storage subpath.

Workspace rules are enforced by the control plane:

  • A Workspace is optional and only valid for templates with the canonical NFS mount named workspace.
  • The NFS template defines the default container path. Omitting WorkspaceMounts preserves that path exactly. WorkspaceMounts may add or override logical views of the same Workspace, for example its root at /data and its apps child at /app.
  • Every WorkspaceMount.SubPath is relative to the Workspace root. It cannot be absolute, contain .., reference another Workspace, or configure NFS.
  • It can be mounted by exactly one active Sandbox. A second create returns a conflict rather than sharing the directory.
  • Pause and deletion detach the Workspace only after the provider resource has stopped or been destroyed. Resume atomically claims it again.
  • Cross-user, cross-project, and cross-namespace lookups are returned as not found. A caller cannot choose an NFS path or another tenant's storage.
  • DeleteWorkspace returns a conflict while it is attached or a create lease is still pending.

Run the cleanup-safe lifecycle example with only the normal SDK variables:

export SEAINFRA_BASE_URL="..."
export SEAINFRA_API_KEY="..."
# Optional: SANDBOX_EXAMPLE_NFS_TEMPLATE=nfs
# Optional: SANDBOX_EXAMPLE_WORKSPACE_DIR=/agent-workspace
go run ./examples/workspace_lifecycle

For the complete decision guide, replacement-Sandbox flow, legacy promotion, and a path mapping reference, see docs/workspaces.md.

Build An NFS-backed Web Template

Use the managed nfs template when a Sandbox needs a persistent workspace. The recommended layout deliberately separates the image build from runtime storage:

  • /app is populated while the derived template image is built. Application dependencies and static build output belong here.
  • /agent-workspace is the runtime working directory and NFS mount inside each Sandbox.
  • The physical NFS root is control-plane data owned by the official base template. SDK callers do not provide, inspect, or override it.
  • Without a logical Workspace, the platform scopes an NFS mount below the configured root by Sandbox ID and mount name. When CreateOptions.WorkspaceID is set, it instead mounts the server-owned Workspace subdirectory after verifying the same user, project, namespace, and NFS template configuration.

The startup command copies the prepared application from /app into /agent-workspace only when the NFS workspace is empty. Subsequent starts, pause/resume cycles, and replacement containers keep the files already stored on NFS instead of overwriting them from the image.

Prerequisites
  1. The target gateway must publish an NFS-capable template, such as one exposed through a stable nfs type. Resolve the stable type through the SDK instead of hardcoding its current tpl-nfs-* ID.
  2. Use an API key that belongs to the calling workload. The key determines template and Sandbox ownership. Never put the key in source code.
  3. For the included Web example, the source directory must contain package.json, package-lock.json, index.html, and src. Its package scripts must provide build and dev.
Run The Included End-to-end Example

The repository includes a complete, cleanup-safe implementation at examples/build_nfs_web_template. It uploads an npm/Vite application, builds a personal derived template, creates a Sandbox, validates nano-executor and port 3000, writes an NFS marker, pauses and resumes the Sandbox, verifies persistence, and then deletes the Sandbox and derived template.

export SEAINFRA_BASE_URL="https://sandbox.example.com/api"
export SEAINFRA_API_KEY="..."

export SANDBOX_EXAMPLE_WEB_SOURCE_DIR="/absolute/path/to/your-vite-project"

# Optional overrides:
export SANDBOX_EXAMPLE_NFS_BASE_TEMPLATE="nfs"
export SANDBOX_EXAMPLE_NFS_WORKSPACE_DIR="/agent-workspace"
export SANDBOX_EXAMPLE_TEMPLATE_NAME="my-nfs-web-template"

go run ./examples/build_nfs_web_template

Do not set SANDBOX_EXAMPLE_KEEP_RESOURCES=1 for normal smoke tests. By default, the example deletes the Sandbox first and then the derived template, including when a later verification step fails after the resource IDs have been returned. Set it only when an operator needs to inspect the generated resources manually.

The example copies an explicit allowlist of source files. It does not upload .env, .git, node_modules, or local build output. Keep the same boundary when adapting it for another application.

Core SDK Flow

The essential build and create calls are shown below. The repository example adds stronger validation, build-log streaming, pause/resume verification, and partial-failure cleanup around this flow.

package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"time"

	sandbox "github.com/SeaArt-Infra/sandbox-go"
	"github.com/SeaArt-Infra/sandbox-go/core"
)

func main() {
	if err := run(); err != nil {
		log.Fatal(err)
	}
}

func run() error {
	ctx, cancel := context.WithTimeout(context.Background(), 45*time.Minute)
	defer cancel()

	client, err := sandbox.NewClient(
		os.Getenv("SEAINFRA_BASE_URL"),
		os.Getenv("SEAINFRA_API_KEY"),
		core.WithTimeout(4*time.Minute),
	)
	if err != nil {
		return fmt.Errorf("create Sandbox client: %w", err)
	}

	base, err := client.Build.ResolveTemplateRef(ctx, "nfs")
	if err != nil {
		return fmt.Errorf("resolve managed NFS template: %w", err)
	}
	if base == nil || base.TemplateID == "" {
		return fmt.Errorf("resolve managed NFS template: empty template ID")
	}

	sourceDir := os.Getenv("SANDBOX_EXAMPLE_WEB_SOURCE_DIR")
	workspaceDir := "/agent-workspace"
	if sourceDir == "" {
		return fmt.Errorf("SANDBOX_EXAMPLE_WEB_SOURCE_DIR is required")
	}

	template := sandbox.NewTemplate().
		FromTemplate(base.TemplateID).
		SetWorkdir("/app")
	for _, source := range []struct {
		name     string
		required bool
	}{
		{name: "package.json", required: true},
		{name: "package-lock.json", required: true},
		{name: "index.html", required: true},
		{name: "src", required: true},
		{name: "public"},
		{name: "tsconfig.json"},
		{name: "tsconfig.app.json"},
		{name: "tsconfig.node.json"},
		{name: "vite.config.js"},
		{name: "vite.config.mjs"},
		{name: "vite.config.ts"},
		{name: "postcss.config.js"},
		{name: "postcss.config.cjs"},
		{name: "postcss.config.mjs"},
		{name: "tailwind.config.js"},
		{name: "tailwind.config.cjs"},
		{name: "tailwind.config.mjs"},
		{name: "tailwind.config.ts"},
		{name: "eslint.config.js"},
		{name: "eslint.config.mjs"},
		{name: "eslint.config.ts"},
	} {
		localPath := filepath.Join(sourceDir, source.name)
		if _, statErr := os.Stat(localPath); statErr != nil {
			if os.IsNotExist(statErr) && !source.required {
				continue
			}
			return fmt.Errorf("inspect Web source %s: %w", source.name, statErr)
		}
		template.Copy(localPath, path.Join("/app", source.name), nil)
	}

	startCommand := `set -eu
mkdir -p /agent-workspace
if [ -z "$(ls -A /agent-workspace 2>/dev/null)" ]; then
  cp -a /app/. /agent-workspace/
fi
cd /agent-workspace
exec npm run dev -- --host 0.0.0.0 --port 3000`

	template.
		RunCmd("apk add --no-cache nodejs npm curl", nil).
		RunCmd("npm ci --no-audit --no-fund", nil).
		RunCmd("npm run build", nil).
		SetStartCmd(
			startCommand,
			sandbox.WaitForURL("http://127.0.0.1:3000/", http.StatusOK),
		)

	templateName := fmt.Sprintf("nfs-web-%d", time.Now().UTC().UnixNano())
	built, err := client.BuildTemplate(ctx, template, templateName, &sandbox.TemplateBuildOptions{
		BaseTemplateID: base.TemplateID,
		Visibility:     "personal",
		Workdir:        workspaceDir,
		WaitTimeout:  30 * time.Minute,
		PollInterval: 2 * time.Second,
		OnBuildLog: func(entry sandbox.LogEntry) {
			log.Println(entry.String())
		},
	})
	if built != nil && built.TemplateID != "" {
		defer func() {
			cleanupCtx, cleanupCancel := context.WithTimeout(context.Background(), 2*time.Minute)
			defer cleanupCancel()
			if err := client.DeleteTemplate(cleanupCtx, built.TemplateID); err != nil {
				log.Printf("delete template: %v", err)
			}
		}()
	}
	if err != nil {
		return fmt.Errorf("build NFS template: %w", err)
	}
	if built == nil || built.TemplateID == "" {
		return fmt.Errorf("build NFS template: empty result")
	}

	waitReady := true
	autoPause := false
	timeoutSeconds := int32(900)
	created, err := client.Create(ctx, built.TemplateID, &sandbox.CreateOptions{
		WaitReady:    &waitReady,
		AutoPause:    &autoPause,
		Timeout:      &timeoutSeconds,
		WaitTimeout:  8 * time.Minute,
		PollInterval: 2 * time.Second,
	})
	if created != nil && created.SandboxID != "" {
		defer func() {
			cleanupCtx, cleanupCancel := context.WithTimeout(context.Background(), 2*time.Minute)
			defer cleanupCancel()
			if err := created.Delete(cleanupCtx); err != nil {
				log.Printf("delete Sandbox: %v", err)
			}
		}()
	}
	if err != nil {
		return fmt.Errorf("create Sandbox: %w", err)
	}
	if created == nil || created.SandboxID == "" {
		return fmt.Errorf("create Sandbox: empty result")
	}

	commands, err := created.Commands()
	if err != nil {
		return fmt.Errorf("bind Sandbox commands: %w", err)
	}
	result, err := commands.Run(ctx, "pwd && test -f package.json", &sandbox.CommandRunOptions{
		CWD: workspaceDir,
	})
	if err != nil {
		return fmt.Errorf("verify NFS workspace: %w", err)
	}
	if result.ExitCode != 0 {
		return fmt.Errorf("verify NFS workspace: result=%#v", result)
	}

	webURL, err := created.GetHost(3000)
	if err != nil {
		return fmt.Errorf("get Web URL: %w", err)
	}
	log.Printf("template=%s sandbox=%s web=%s", built.TemplateID, created.SandboxID, webURL)
	return nil
}

The order of the two workdir settings is intentional:

  • template.SetWorkdir("/app") emits the image build WORKDIR; build commands such as npm ci run against files copied into the image.
  • TemplateBuildOptions.Workdir = "/agent-workspace" configures the resulting Sandbox runtime workdir after the NFS volume is mounted.

Likewise, FromTemplate(base.TemplateID) preserves the managed nano-executor runtime and NFS storage from the official base. TemplateBuildOptions.Workdir only sets the runtime working directory; it never changes the inherited storage configuration.

Lifecycle And Persistence
  • Timeout controls the Sandbox runtime deadline, not template retention. The SDK accepts 0..86400 seconds; the example uses 900 seconds.
  • Connect and Resume are lifecycle-neutral: they send no timeout value and never alter the Sandbox deadline. Use SetTimeout or Refresh only when a caller intentionally changes the lifecycle.
  • AutoPause=false keeps the disposable onTimeout=kill behavior. Set it to true only when a paused Sandbox should retain held capacity and its NFS workspace for a later resume.
  • NFS data persists across pause/resume for the same Sandbox. Deleting the Sandbox releases runtime capacity; template deletion is a separate operation.
  • Always delete the Sandbox before deleting its template during tests and CI. Production services should persist both IDs and reconcile cleanup after process crashes instead of relying only on in-process defer calls.
  • Get the Web endpoint with created.GetHost(3000) or proxy through created.Proxy(...). Do not construct an sbxrouter hostname manually.
Common Failures
  • resolve NFS base template ... 404: the selected Gateway environment does not publish the official nfs type. Verify SEAINFRA_BASE_URL; do not substitute a template ID from another environment.
  • A derived template has no persistent workspace mount: build it from the managed nfs base and omit VolumeMounts so its approved NFS mount is inherited.
  • Application files appear under /app but not /agent-workspace: the startup seed command is missing, failed, or the runtime workdir/mount path differs from the configured value.
  • Runtime CMD APIs return 404: the selected base template does not contain a running nano-executor, or the inherited start command was replaced without preserving it. Start from the managed nfs type.
  • A resumed Sandbox starts with stale application files: this is expected when the NFS directory is non-empty. Update files through the runtime Files/CMD APIs, or create a new Sandbox when a clean seed is required.
  • Build or create exceeds the normal HTTP timeout: keep the transport timeout, WaitTimeout, and polling interval explicit as shown above.

High-level template helpers currently include:

  • lifecycle and status: client.BuildTemplate, client.BuildTemplateInBackground, client.TemplateExists, client.TemplateAliasExists, client.GetTemplateBuildStatus, client.ListTemplates, client.GetTemplate, client.DeleteTemplate
  • serialization: sandbox.TemplateToJSON, sandbox.TemplateToDockerfile
  • base images and registries: FromDockerfile, FromBaseImage, FromNodeImage, FromPythonImage, FromBunImage, FromUbuntuImage, FromDebianImage, FromAWSRegistry, FromGCPRegistry
  • build-step helpers: Copy, CopyItems, SkipCache, AptInstall, GitClone, MakeDir, MakeSymlink, NpmInstall, PipInstall, BunInstall, Remove, Rename, RunCmd, RunCmds
  • execution and config helpers: SetEnvs, SetWorkdir, SetUser, SetStartCmd, SetReadyCmd
  • supported local copy options: ForceUpload, Mode, ResolveSymlinks
  • supported command and path options: RunCmd(..., &sandbox.TemplateCommandOptions{User: ...}), GitClone(..., &sandbox.TemplateGitCloneOptions{User: ...}), MakeDir(..., &sandbox.TemplateMakeDirOptions{User: ...}), MakeSymlink(..., &sandbox.TemplateMakeSymlinkOptions{User: ...}), Remove(..., &sandbox.TemplateRemoveOptions{...User: ...}), Rename(..., &sandbox.TemplateRenameOptions{...User: ...})
  • intentionally not exposed yet: Copy(..., user=...), MCP server helpers, and devcontainer helpers
Raw Build Plane Through Root Client
package main

import (
	"context"
	"log"
	"os"

	"github.com/SeaArt-Infra/sandbox-go"
	"github.com/SeaArt-Infra/sandbox-go/build"
)

func main() {
	client, err := sandbox.NewClient(
		os.Getenv("SEAINFRA_BASE_URL"),
		os.Getenv("SEAINFRA_API_KEY"),
	)
	if err != nil {
		log.Fatal(err)
	}

	resp, err := client.Build.CreateTemplate(context.Background(), &build.TemplateCreateRequest{
		Name: "demo",
	})
	if err != nil {
		log.Fatal(err)
	}
	defer client.Build.DeleteTemplate(context.Background(), resp.TemplateID)

	buildID := "build-demo"
	_, err = client.Build.CreateBuild(
		context.Background(),
		resp.TemplateID,
		buildID,
		build.NewTemplateBuildBuilder().
			FromImage("docker.io/library/alpine:3.20").
			Run("echo hello-from-go >/tmp/hello.txt", nil).
			Request(),
	)
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("template=%s build=%s", resp.TemplateID, buildID)
}
Runtime Modules
package main

import (
	"context"
	"log"
	"os"

	"github.com/SeaArt-Infra/sandbox-go"
)

func main() {
	client, err := sandbox.NewClient(os.Getenv("SEAINFRA_BASE_URL"), os.Getenv("SEAINFRA_API_KEY"))
	if err != nil {
		log.Fatal(err)
	}

	ready := true
	createdSandbox, err := client.Create(context.Background(), os.Getenv("SEAINFRA_TEMPLATE_ID"), &sandbox.CreateOptions{
		WaitReady: &ready,
	})
	if err != nil {
		log.Fatal(err)
	}
	defer createdSandbox.Delete(context.Background())

	files, err := createdSandbox.Files()
	if err != nil {
		log.Fatal(err)
	}
	if _, err := files.Write(context.Background(), "/root/workspace/hello.txt", []byte("hello from go")); err != nil {
		log.Fatal(err)
	}

	body, err := files.Read(context.Background(), "/root/workspace/hello.txt")
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("%s", body)
}

Bound sandbox helpers currently include:

  • lifecycle: Reload, Connect, Resume, GetInfo, Logs, Pause, Kill, Delete, Refresh, SetTimeout, IsRunning
  • runtime conveniences: GetMetrics, GetHost, Proxy
  • commands module: Run, Exec, Start, Wait, List, Connect, Kill, SendStdin
  • filesystem module: Exists, GetInfo, List, MakeDir, Read, Write, WriteFiles, Remove, Rename, WatchDir
  • git module: Clone, Pull, Checkout, Status
  • pty module: Create, Connect, Kill, SendStdin, Resize

For most integrations, prefer one root client per process:

  • initialize once with sandbox.NewClient(baseURL, apiKey, opts...)
  • create sandboxes with client.Create(...)
  • continue through Commands()/Files()/Git()/Pty()
  • build templates with sandbox.NewTemplate() plus client.BuildTemplate(...)

Low-level methods remain available when you need tighter request control:

  • use CreateSandbox, ListSandboxes, GetSandbox, ConnectSandbox
  • continue from the returned sandbox object with Reload(), Connect(), Resume(), GetInfo(), GetMetrics(), GetHost(), Logs(), Pause(), Refresh(), SetTimeout(), Kill(), Delete(), and IsRunning()
  • only switch to runtime with Runtime() when you need file/process/stream operations
  • use BuildTemplate, BuildTemplateInBackground, TemplateExists, GetTemplateBuildStatus, ListTemplates, GetTemplate, and DeleteTemplate on the root client for bound template workflows
  • use client.Build only for raw template/build workflows
  • use build.NewTemplateBuildBuilder() when you want a small fluent helper that expands into BuildRequest

Low-level domain packages remain available when you need direct request/response models or tighter transport control.

API Surface

Control Plane APIs

sandbox.Client exposes control-plane methods directly:

  • system: Metrics, Shutdown
  • sandboxes: CreateSandbox, ListSandboxes, GetSandbox, DeleteSandbox
  • sandbox operations: GetSandboxLogs, PauseSandbox, ConnectSandbox, SetSandboxTimeout, RefreshSandbox, SendHeartbeat

Recommended root-client path:

  • high-level lifecycle: Create, Connect, List, Get
  • template helpers: BuildTemplate, BuildTemplateInBackground, TemplateExists, TemplateAliasExists, GetTemplateBuildStatus, ListTemplates, GetTemplate, DeleteTemplate
  • low-level lifecycle: CreateSandbox, ListSandboxes, GetSandbox, ConnectSandbox
  • follow-up control actions from the returned object: Reload(), Connect(), Resume(), GetInfo(), GetMetrics(), GetHost(), Logs(), Pause(), Refresh(), SetTimeout(), Kill(), Delete(), IsRunning()
  • runtime actions from objects that include EnvdURL: Runtime()

Low-level direct methods like DeleteSandbox and GetSandboxLogs remain available on the root client when you want explicit control-plane requests.

Operator APIs

The root client also includes operator-oriented methods such as GetPoolStatus, StartRollingUpdate, GetRollingUpdateStatus, and CancelRollingUpdate.

These routes are intended for trusted operator deployments connected directly to an operator endpoint. Public API-key gateways commonly do not expose them.

Template Facade

Preferred template path:

  • sandbox.NewTemplate() for build DSL
  • client.BuildTemplate(...) for create + build + optional polling
  • client.BuildTemplateInBackground(...) for fire-and-poll-later workflows
  • client.ListTemplates(...), client.GetTemplate(...), client.DeleteTemplate(...), client.TemplateExists(...), client.TemplateAliasExists(...), client.GetTemplateBuildStatus(...) for bound lifecycle and status
  • sandbox.TemplateToJSON(...), sandbox.TemplateToDockerfile(...) for export helpers

Template builder conveniences include:

  • base images and registries: FromDockerfile (returns (*Template, error)), FromBaseImage, FromNodeImage, FromPythonImage, FromBunImage, FromUbuntuImage, FromDebianImage, FromAWSRegistry, FromGCPRegistry
  • file and command helpers: Copy, CopyItems, SkipCache, AptInstall, GitClone, MakeDir, MakeSymlink, NpmInstall, PipInstall, BunInstall, Remove, Rename, RunCmd, RunCmds
  • execution and config helpers: SetEnvs, SetWorkdir, SetUser, SetStartCmd, SetReadyCmd
  • supported local copy options: ForceUpload, Mode, ResolveSymlinks
  • supported command and path options: RunCmd(..., &sandbox.TemplateCommandOptions{User: ...}), GitClone(..., &sandbox.TemplateGitCloneOptions{User: ...}), MakeDir(..., &sandbox.TemplateMakeDirOptions{User: ...}), MakeSymlink(..., &sandbox.TemplateMakeSymlinkOptions{User: ...}), Remove(..., &sandbox.TemplateRemoveOptions{...User: ...}), Rename(..., &sandbox.TemplateRenameOptions{...User: ...})
  • intentionally not exposed yet: Copy(..., user=...), MCP server helpers, and devcontainer helpers
Build Plane Through client.Build

Low-level client.Build contains:

  • operator-only helpers: Metrics, DirectBuild (commonly not exposed by public API-key gateways)
  • templates: CreateTemplate, ListTemplates, GetTemplateByAlias, ResolveTemplateRef, GetTemplate, UpdateTemplate, DeleteTemplate
  • builds: CreateBuild, GetBuildFile, RollbackTemplate, ListBuilds, GetBuild, GetBuildStatus, GetBuildLogs

The public template contract is split into three layers: top-level create fields (Name, Tags, CPUCount, MemoryMB), flat template extensions (BaseTemplateID, Visibility, Envs, WorkspaceMounts, Workdir), and build-only fields on CreateBuild (FromImage, FromTemplate, Steps, StartCmd, ReadyCmd, and registry credentials). WorkspaceMounts contains only logical container paths and Workspace-relative subpaths. Persistent NFS storage is inherited from an approved base template, not configured by the caller. COPY content hashes belong to each COPY step as BuildStep.FilesHash; the public Builder does not accept a top-level filesHash. Public create calls reject legacy top-level write fields such as Alias and TeamID. Public update only changes the Public visibility flag.

For Go callers, TemplateCreateRequest uses PublicTemplateExtensions and TemplateUpdateRequest only changes Public. Public read responses follow the Builder's E2B-facing list/detail shapes; Admin template metadata is not available through this route.

CreateTemplate rejects Extensions.Visibility == "official" on public routes.

CreateBuild follows the wire contract directly and returns the raw 202 {} trigger response without adding helper fields. Local files are packed and uploaded by Template.Copy/BuildTemplate, which places the resulting hash on the COPY step.

GetTemplateByAlias is a pure alias lookup endpoint. It should only be used with an actual published alias value.

ResolveTemplateRef resolves a template by templateID, stable template type, or visible alias.

Runtime Helper

Low-level runtime objects returned by createdSandbox.Runtime() or client.RuntimeFromSandbox(...) expose:

  • system: Metrics, Envs, Configure, Ports
  • proxy and file transfer: Proxy, Download, FilesContent, UploadBytes, UploadJSON, UploadMultipart, WriteBatch, ComposeFiles, ReadFile, WriteFile
  • filesystem RPC: ListDir, Stat, MakeDir, Remove, Move, Edit
  • watchers: WatchDir, CreateWatcher, GetWatcherEvents, RemoveWatcher
  • process RPC: Start, Connect, ListProcesses, SendInput, SendSignal, CloseStdin, Update, StreamInput, GetResult, Run

cmd.RequestOptions supports:

  • Username: basic-auth username for envd operations that need it
  • Signature and SignatureExpiration: signed file access parameters
  • Range: partial download support
  • Headers: custom header injection

Streaming APIs return ProcessStream, FilesystemWatchStream, and ConnectFrame.

Resource Safety

  • The quick starts are written for disposable resources and should be adapted before copy-pasting into production jobs.
  • Prefer explicit cleanup with defer createdSandbox.Delete(...) and defer client.Build.DeleteTemplate(...) when running probes, smoke tests, or CI.
  • For long-lived workloads, move cleanup and timeout policy into your own lifecycle manager instead of relying on sample code defaults.

Package Layout

  • github.com/SeaArt-Infra/sandbox-go: root client and recommended entrypoint
  • github.com/SeaArt-Infra/sandbox-go/control: control-plane models and low-level APIs
  • github.com/SeaArt-Infra/sandbox-go/build: build-plane models and low-level APIs
  • github.com/SeaArt-Infra/sandbox-go/cmd: runtime models and low-level APIs
  • github.com/SeaArt-Infra/sandbox-go/core: shared transport and error primitives

Notes

  • The gateway entrypoint always needs baseURL + apiKey to initialize.
  • core.WithProjectID(...) is retained for direct/private deployments. Public gateways ignore caller-supplied identity and derive the canonical tenant from the authenticated API key.
  • Runtime access should be derived from sandbox response objects with Runtime() or RuntimeFromSandbox(...).
  • CreateSandbox and GetSandbox responses include EnvdURL and EnvdAccessToken when the target sandbox supports CMD access.
  • Runtime file/process APIs require a template image that starts nano-executor and returns runtime access fields; if runtime APIs return 404, verify the selected template supports CMD runtime routes.
  • High-level Create converts waitReady=true into a short create followed by cancellable client polling, so the sandbox ID is available even when readiness times out. Configure WaitTimeout and PollInterval when needed.
  • CreateOptions.AutoPause maps to the public autoPause lifecycle flag. The default is disposable (lifecycle.onTimeout=kill); set it to true only when a stopped sandbox should retain held capacity.
  • API errors expose Kind and Retryable() for retry logic and alert routing.
  • High-level Kill() helpers send SIGNAL_SIGKILL and return false when the runtime reports a missing process through either 404 or ESRCH.
  • PTY handles normalize reconnect output into PTY even when the runtime emits the bytes through Stdout / Stderr.
  • Sandbox timeout values are validated to 0..86400; refresh duration to 0..3600.
  • Build request validation accepts E2B-style COPY / ENV / RUN / WORKDIR / USER steps, force, and structured fromImageRegistry credentials (registry / aws / gcp).
  • Some gateways do not expose /admin/* or /build; integration tests skip those cases on 404.
  • Some filesystem layouts reject watcher APIs entirely; the integration suite skips watcher coverage when the runtime reports that limitation.

Security

  • Do not commit SEAINFRA_API_KEY, envdAccessToken, or sandbox access tokens.
  • Treat runtime tokens as sandbox-scoped secrets. Prefer createdSandbox.Runtime() or client.RuntimeFromSandbox(...) so response-scoped runtime access is not copied into configuration.
  • Do not log raw API keys or runtime tokens. SDK errors may include response bodies, so avoid logging full error payloads in shared systems.
  • Do not rely on core.WithProjectID(...) for public tenant selection. Public gateways derive the tenant from the authenticated API key.

Integration Tests

SANDBOX_RUN_INTEGRATION=1 \
SANDBOX_TEST_BASE_URL="${SEAINFRA_BASE_URL}" \
SANDBOX_TEST_API_KEY="${SEAINFRA_API_KEY}" \
SANDBOX_TEST_TEMPLATE_ID=... \
go test ./tests/... -count=1 -v

Use a runtime-enabled template selected by the environment administrator for CMD integration coverage. The same smoke suite is available as a manual GitHub Actions dispatch in .github/workflows/integration-smoke.yml.

Release

  • See CHANGELOG.md for release notes.
  • See RELEASE_CHECKLIST.md before tagging or publishing a new version.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func TemplateToDockerfile

func TemplateToDockerfile(template *Template) (string, error)

TemplateToDockerfile converts the currently supported template subset into a Dockerfile string.

func TemplateToJSON

func TemplateToJSON(template *Template, computeHashes bool) (string, error)

TemplateToJSON serializes the currently supported template subset into build-request JSON.

Types

type Client

type Client struct {
	*control.Service
	Build *build.Service
}

func NewClient

func NewClient(baseURL, apiKey string, opts ...core.TransportOption) (*Client, error)

func (*Client) BuildTemplate

func (c *Client) BuildTemplate(ctx context.Context, template *Template, name string, opts *TemplateBuildOptions) (*TemplateBuildInfo, error)

func (*Client) BuildTemplateInBackground

func (c *Client) BuildTemplateInBackground(ctx context.Context, template *Template, name string, opts *TemplateBuildOptions) (*TemplateBuildInfo, error)

func (*Client) Connect

func (c *Client) Connect(ctx context.Context, sandboxID string) (*Sandbox, error)

Connect resumes a paused Sandbox or retrieves a running Sandbox's current connection details. It never modifies the Sandbox lifetime.

func (*Client) ConnectSandbox

func (c *Client) ConnectSandbox(
	ctx context.Context,
	sandboxID string,
) (*ConnectSandboxResponse, error)

func (*Client) Create

func (c *Client) Create(ctx context.Context, templateID string, opts *CreateOptions) (*Sandbox, error)

func (*Client) CreateSandbox

func (c *Client) CreateSandbox(ctx context.Context, req *control.NewSandboxRequest) (*Sandbox, error)

func (*Client) CreateWorkspace added in v0.1.4

func (c *Client) CreateWorkspace(ctx context.Context, templateID string) (*Workspace, error)

CreateWorkspace creates an empty persistent Workspace for an NFS-backed template owned by the caller.

func (*Client) DeleteTemplate

func (c *Client) DeleteTemplate(ctx context.Context, ref string) error

func (*Client) DeleteWorkspace added in v0.1.4

func (c *Client) DeleteWorkspace(ctx context.Context, workspaceID string) error

DeleteWorkspace deletes a detached Workspace record. The server returns a conflict while a Sandbox holds it or a pending create lease is active.

func (*Client) Get

func (c *Client) Get(ctx context.Context, sandboxID string) (*SandboxDetail, error)

func (*Client) GetSandbox

func (c *Client) GetSandbox(ctx context.Context, sandboxID string) (*SandboxDetail, error)

func (*Client) GetTemplate

func (c *Client) GetTemplate(ctx context.Context, ref string, opts *TemplateGetOptions) (*build.TemplateResponse, error)

func (*Client) GetTemplateBuildStatus

func (c *Client) GetTemplateBuildStatus(ctx context.Context, templateID, buildID string, opts *TemplateBuildStatusOptions) (*build.BuildStatusResponse, error)

func (*Client) GetWorkspace added in v0.1.4

func (c *Client) GetWorkspace(ctx context.Context, workspaceID string) (*Workspace, error)

GetWorkspace returns one caller-owned Workspace. Foreign Workspaces are deliberately non-enumerable and return not found.

func (*Client) List

func (c *Client) List(ctx context.Context, opts *ListOptions) ([]*SandboxHandle, error)

func (*Client) ListSandboxes

func (c *Client) ListSandboxes(
	ctx context.Context,
	params *control.ListSandboxesParams,
) ([]*SandboxHandle, error)

func (*Client) ListTemplates

func (c *Client) ListTemplates(ctx context.Context, opts *TemplateListOptions) ([]build.ListedTemplate, error)

func (*Client) ListWorkspaces added in v0.1.4

func (c *Client) ListWorkspaces(ctx context.Context) ([]Workspace, error)

ListWorkspaces lists Workspaces owned by the authenticated caller.

func (*Client) NewCMD

func (c *Client) NewCMD(baseURL, accessToken string) (*cmd.Service, error)

func (*Client) PromoteSandboxWorkspace added in v0.1.4

func (c *Client) PromoteSandboxWorkspace(ctx context.Context, sandboxID string) (*Workspace, error)

PromoteSandboxWorkspace adopts an existing legacy NFS Sandbox directory as a Workspace without copying its contents. The Sandbox must be owned by the caller and use an NFS workspace mount.

func (*Client) Runtime

func (c *Client) Runtime(baseURL, accessToken string) (*Runtime, error)

func (*Client) RuntimeFromDetail

func (c *Client) RuntimeFromDetail(sandbox *control.SandboxDetail) (*Runtime, error)

func (*Client) RuntimeFromSandbox

func (c *Client) RuntimeFromSandbox(sandbox *control.Sandbox) (*Runtime, error)

func (*Client) TemplateAliasExists

func (c *Client) TemplateAliasExists(ctx context.Context, alias string) (bool, error)

func (*Client) TemplateExists

func (c *Client) TemplateExists(ctx context.Context, ref string) (bool, error)

type CommandHandle

type CommandHandle struct {
	PID   int
	CmdID string
	PTY   bool
	// contains filtered or unexported fields
}

func (*CommandHandle) Close

func (h *CommandHandle) Close() error

func (*CommandHandle) CloseStdin

func (h *CommandHandle) CloseStdin(ctx context.Context) error

func (*CommandHandle) Kill

func (h *CommandHandle) Kill(ctx context.Context) (bool, error)

func (*CommandHandle) SendStdin

func (h *CommandHandle) SendStdin(ctx context.Context, data string) error

func (*CommandHandle) Wait

type CommandResult

type CommandResult struct {
	Stdout     string
	Stderr     string
	ExitCode   int
	DurationMS int64
	Error      string
}

type CommandRunOptions

type CommandRunOptions struct {
	Args []string
	Envs map[string]string
	// CWD applies only to this command. It does not change the Sandbox runtime
	// workdir or the path boundary enforced by Files().
	CWD     string
	Timeout *int
	Stdin   *string
}

type CommandWaitResult

type CommandWaitResult struct {
	Stdout   string
	Stderr   string
	PTY      string
	ExitCode int
}

type CommandsModule

type CommandsModule struct {
	// contains filtered or unexported fields
}

func (*CommandsModule) Connect

func (m *CommandsModule) Connect(ctx context.Context, pid int) (*CommandHandle, error)

func (*CommandsModule) Exec

func (m *CommandsModule) Exec(ctx context.Context, command string, opts *CommandRunOptions) (*CommandResult, error)

func (*CommandsModule) Kill

func (m *CommandsModule) Kill(ctx context.Context, pid int) (bool, error)

func (*CommandsModule) List

func (m *CommandsModule) List(ctx context.Context) ([]cmd.ProcessInfo, error)

func (*CommandsModule) Run

func (m *CommandsModule) Run(ctx context.Context, command string, opts *CommandRunOptions) (*CommandResult, error)

func (*CommandsModule) SendStdin

func (m *CommandsModule) SendStdin(ctx context.Context, pid int, data string) error

func (*CommandsModule) Start

func (m *CommandsModule) Start(ctx context.Context, command string, opts *CommandRunOptions) (*CommandHandle, error)

type ConnectSandboxResponse

type ConnectSandboxResponse struct {
	StatusCode int
	Sandbox    *Sandbox
}

type CreateOptions

type CreateOptions struct {
	GatewayConfig
	TemplateID      string
	WorkspaceID     string
	WorkspaceMounts []WorkspaceMount
	Timeout         *int32
	Metadata        map[string]string
	EnvVars         map[string]string
	// Deprecated: Runtime volume mounts are unsupported. Configure volumes on
	// the Sandbox Template instead. This field is retained for source
	// compatibility and Create rejects a non-empty value locally.
	VolumeMounts []control.VolumeMount
	WaitReady    *bool
	AutoPause    *bool
	WaitTimeout  time.Duration
	PollInterval time.Duration
}

type FilesystemModule

type FilesystemModule struct {
	// contains filtered or unexported fields
}

func (*FilesystemModule) Exists

func (m *FilesystemModule) Exists(ctx context.Context, path string) (bool, error)

func (*FilesystemModule) GetInfo

func (m *FilesystemModule) GetInfo(ctx context.Context, path string) (*cmd.EntryInfo, error)

func (*FilesystemModule) List

func (m *FilesystemModule) List(ctx context.Context, path string, depth *int) ([]cmd.EntryInfo, error)

func (*FilesystemModule) MakeDir

func (m *FilesystemModule) MakeDir(ctx context.Context, path string) (bool, error)

func (*FilesystemModule) Read

func (m *FilesystemModule) Read(ctx context.Context, path string) (string, error)

func (*FilesystemModule) Remove

func (m *FilesystemModule) Remove(ctx context.Context, path string) error

func (*FilesystemModule) Rename

func (m *FilesystemModule) Rename(ctx context.Context, oldPath, newPath string) (*cmd.EntryInfo, error)

func (*FilesystemModule) WatchDir

func (m *FilesystemModule) WatchDir(ctx context.Context, path string, recursive *bool) (*cmd.FilesystemWatchStream, error)

func (*FilesystemModule) Write

func (m *FilesystemModule) Write(ctx context.Context, path string, data []byte) (*WriteInfo, error)

func (*FilesystemModule) WriteFiles

func (m *FilesystemModule) WriteFiles(ctx context.Context, files []cmd.WriteFileEntry) ([]WriteInfo, error)

type GatewayConfig

type GatewayConfig struct {
	BaseURL   string
	APIKey    string
	ProjectID string
	Timeout   time.Duration
}

type GitCloneOptions

type GitCloneOptions struct {
	GitCommandOptions
	Branch string
	Depth  int
}

type GitCommandOptions

type GitCommandOptions struct {
	Envs    map[string]string
	CWD     string
	Timeout *int
	User    string
}

type GitModule

type GitModule struct {
	// contains filtered or unexported fields
}

func (*GitModule) Checkout

func (m *GitModule) Checkout(ctx context.Context, ref, path string, opts *GitCommandOptions) (*CommandResult, error)

func (*GitModule) Clone

func (m *GitModule) Clone(ctx context.Context, repoURL, path string, opts *GitCloneOptions) (*CommandResult, error)

func (*GitModule) Pull

func (m *GitModule) Pull(ctx context.Context, path string, opts *GitCommandOptions) (*CommandResult, error)

func (*GitModule) Status

func (m *GitModule) Status(ctx context.Context, path string, opts *GitCommandOptions) (*CommandResult, error)

type ListOptions

type ListOptions struct {
	GatewayConfig
	Metadata  map[string]string
	State     []string
	Limit     int
	NextToken string
}

type LogEntry

type LogEntry struct {
	Timestamp time.Time
	Level     string
	Message   string
}

func (LogEntry) String

func (l LogEntry) String() string

type PtyCreateOptions

type PtyCreateOptions struct {
	Args    []string
	Envs    map[string]string
	CWD     string
	Timeout *int
	Size    *cmd.PtySize
}

type PtyModule

type PtyModule struct {
	// contains filtered or unexported fields
}

func (*PtyModule) Connect

func (m *PtyModule) Connect(ctx context.Context, pid int) (*CommandHandle, error)

func (*PtyModule) Create

func (m *PtyModule) Create(ctx context.Context, command string, opts *PtyCreateOptions) (*CommandHandle, error)

func (*PtyModule) Kill

func (m *PtyModule) Kill(ctx context.Context, pid int) (bool, error)

func (*PtyModule) Resize

func (m *PtyModule) Resize(ctx context.Context, pid int, size cmd.PtySize) error

func (*PtyModule) SendStdin

func (m *PtyModule) SendStdin(ctx context.Context, pid int, data string) error

type ReadyCmd

type ReadyCmd struct {
	// contains filtered or unexported fields
}

func WaitForCommand

func WaitForCommand(command string) ReadyCmd

WaitForCommand uses a caller-provided command as the template readiness probe.

func WaitForFile

func WaitForFile(filename string) ReadyCmd

func WaitForPort

func WaitForPort(port int) ReadyCmd

func WaitForProcess

func WaitForProcess(processName string) ReadyCmd

func WaitForTimeout

func WaitForTimeout(timeout time.Duration) ReadyCmd

func WaitForURL

func WaitForURL(rawURL string, statusCode int) ReadyCmd

func (ReadyCmd) Command

func (r ReadyCmd) Command() string

type ResourceOperationError

type ResourceOperationError struct {
	Operation        string
	ResourceType     string
	ResourceID       string
	RelatedID        string
	CleanupAttempted bool
	CleanupErr       error
	Err              error
}

ResourceOperationError preserves resource identity after a partially successful operation.

func (*ResourceOperationError) Error

func (e *ResourceOperationError) Error() string

func (*ResourceOperationError) Unwrap

func (e *ResourceOperationError) Unwrap() error

type Runtime

type Runtime struct {
	*cmd.Service
}

type Sandbox

type Sandbox struct {
	*control.Sandbox
	// contains filtered or unexported fields
}

func (*Sandbox) Commands

func (s *Sandbox) Commands() (*CommandsModule, error)

func (*Sandbox) Connect

func (s *Sandbox) Connect(ctx context.Context) (*ConnectSandboxResponse, error)

func (*Sandbox) Delete

func (s *Sandbox) Delete(ctx context.Context) error

func (*Sandbox) Files

func (s *Sandbox) Files() (*FilesystemModule, error)

func (*Sandbox) GetHost

func (s *Sandbox) GetHost(port int) (string, error)

func (*Sandbox) GetInfo

func (s *Sandbox) GetInfo(ctx context.Context) (*SandboxDetail, error)

GetInfo fetches the latest sandbox detail for this sandbox ID.

func (*Sandbox) GetMetrics

func (s *Sandbox) GetMetrics(ctx context.Context) (*cmd.MetricsResponse, error)

GetMetrics reads runtime metrics for sandboxes that expose nano-executor access.

func (*Sandbox) Git

func (s *Sandbox) Git() (*GitModule, error)

func (*Sandbox) IsRunning

func (s *Sandbox) IsRunning() bool

IsRunning reports whether the sandbox is in an active state.

func (*Sandbox) Kill

func (s *Sandbox) Kill(ctx context.Context) error

Kill deletes the sandbox.

func (*Sandbox) Logs

func (*Sandbox) Pause

func (s *Sandbox) Pause(ctx context.Context) error

func (*Sandbox) Proxy

func (s *Sandbox) Proxy(ctx context.Context, req *cmd.ProxyRequest) (*http.Response, error)

func (*Sandbox) Pty

func (s *Sandbox) Pty() (*PtyModule, error)

func (*Sandbox) Refresh

func (s *Sandbox) Refresh(ctx context.Context, req *control.RefreshSandboxRequest) error

func (*Sandbox) Reload

func (s *Sandbox) Reload(ctx context.Context) (*SandboxDetail, error)

func (*Sandbox) Resume

func (s *Sandbox) Resume(ctx context.Context) (*Sandbox, error)

Resume reconnects to a paused sandbox and returns the running sandbox handle without changing its configured lifetime.

func (*Sandbox) Runtime

func (s *Sandbox) Runtime() (*Runtime, error)

func (*Sandbox) SetTimeout

func (s *Sandbox) SetTimeout(ctx context.Context, req *control.TimeoutRequest) error

type SandboxDetail

type SandboxDetail struct {
	*control.SandboxDetail
	// contains filtered or unexported fields
}

func (*SandboxDetail) Commands

func (s *SandboxDetail) Commands() (*CommandsModule, error)

func (*SandboxDetail) Connect

func (*SandboxDetail) Delete

func (s *SandboxDetail) Delete(ctx context.Context) error

func (*SandboxDetail) Files

func (s *SandboxDetail) Files() (*FilesystemModule, error)

func (*SandboxDetail) GetHost

func (s *SandboxDetail) GetHost(port int) (string, error)

func (*SandboxDetail) GetInfo

func (s *SandboxDetail) GetInfo(ctx context.Context) (*SandboxDetail, error)

GetInfo refreshes the sandbox detail for this sandbox ID.

func (*SandboxDetail) GetMetrics

func (s *SandboxDetail) GetMetrics(ctx context.Context) (*cmd.MetricsResponse, error)

GetMetrics reads runtime metrics for sandboxes that expose nano-executor access.

func (*SandboxDetail) Git

func (s *SandboxDetail) Git() (*GitModule, error)

func (*SandboxDetail) IsRunning

func (s *SandboxDetail) IsRunning() bool

IsRunning reports whether the sandbox is in an active state.

func (*SandboxDetail) Kill

func (s *SandboxDetail) Kill(ctx context.Context) error

Kill deletes the sandbox.

func (*SandboxDetail) Logs

func (*SandboxDetail) Pause

func (s *SandboxDetail) Pause(ctx context.Context) error

func (*SandboxDetail) Proxy

func (s *SandboxDetail) Proxy(ctx context.Context, req *cmd.ProxyRequest) (*http.Response, error)

func (*SandboxDetail) Pty

func (s *SandboxDetail) Pty() (*PtyModule, error)

func (*SandboxDetail) Refresh

func (*SandboxDetail) Reload

func (s *SandboxDetail) Reload(ctx context.Context) (*SandboxDetail, error)

func (*SandboxDetail) Resume

func (s *SandboxDetail) Resume(ctx context.Context) (*Sandbox, error)

Resume reconnects to a paused sandbox detail and returns a running sandbox handle without changing its configured lifetime.

func (*SandboxDetail) Runtime

func (s *SandboxDetail) Runtime() (*Runtime, error)

func (*SandboxDetail) SetTimeout

func (s *SandboxDetail) SetTimeout(ctx context.Context, req *control.TimeoutRequest) error

type SandboxHandle

type SandboxHandle struct {
	*control.ListedSandbox
	// contains filtered or unexported fields
}

func (*SandboxHandle) Connect

func (*SandboxHandle) Delete

func (s *SandboxHandle) Delete(ctx context.Context) error

func (*SandboxHandle) GetInfo

func (s *SandboxHandle) GetInfo(ctx context.Context) (*SandboxDetail, error)

GetInfo fetches the latest sandbox detail for this sandbox ID.

func (*SandboxHandle) IsRunning

func (s *SandboxHandle) IsRunning() bool

IsRunning reports whether the sandbox is in an active state.

func (*SandboxHandle) Kill

func (s *SandboxHandle) Kill(ctx context.Context) error

Kill deletes the sandbox.

func (*SandboxHandle) Logs

func (*SandboxHandle) Pause

func (s *SandboxHandle) Pause(ctx context.Context) error

func (*SandboxHandle) Refresh

func (*SandboxHandle) Reload

func (s *SandboxHandle) Reload(ctx context.Context) (*SandboxDetail, error)

func (*SandboxHandle) Resume

func (s *SandboxHandle) Resume(ctx context.Context) (*Sandbox, error)

Resume reconnects to a paused sandbox handle and returns a running sandbox handle without changing its configured lifetime.

func (*SandboxHandle) SetTimeout

func (s *SandboxHandle) SetTimeout(ctx context.Context, req *control.TimeoutRequest) error

type Template

type Template struct {
	// contains filtered or unexported fields
}

func NewTemplate

func NewTemplate() *Template

NewTemplate creates a high-level template builder with E2B-style helpers.

func (*Template) AptInstall

func (t *Template) AptInstall(packages []string, opts *TemplateAptInstallOptions) *Template

func (*Template) BunInstall

func (t *Template) BunInstall(packages []string, opts *TemplateBunInstallOptions) *Template

func (*Template) Copy

func (t *Template) Copy(src, dest string, opts *TemplateCopyOptions) *Template

Copy adds one local source to the template build context.

func (*Template) CopyItems

func (t *Template) CopyItems(items []TemplateCopyItem) *Template

CopyItems adds multiple local sources with per-item copy options.

func (*Template) FromAWSRegistry

func (t *Template) FromAWSRegistry(image, accessKeyID, secretAccessKey, region string) *Template

func (*Template) FromBaseImage

func (t *Template) FromBaseImage() *Template

func (*Template) FromBunImage

func (t *Template) FromBunImage(variant string) *Template

func (*Template) FromDebianImage

func (t *Template) FromDebianImage(variant string) *Template

func (*Template) FromDockerfile

func (t *Template) FromDockerfile(dockerfileContentOrPath string) (*Template, error)

FromDockerfile parses a supported Dockerfile subset into template build steps.

func (*Template) FromGCPRegistry

func (t *Template) FromGCPRegistry(image string, serviceAccountJSON any) *Template

func (*Template) FromImage

func (t *Template) FromImage(image string, registryConfig ...map[string]any) *Template

func (*Template) FromNodeImage

func (t *Template) FromNodeImage(variant string) *Template

func (*Template) FromPythonImage

func (t *Template) FromPythonImage(version string) *Template

func (*Template) FromTemplate

func (t *Template) FromTemplate(templateID string) *Template

func (*Template) FromUbuntuImage

func (t *Template) FromUbuntuImage(variant string) *Template

func (*Template) GitClone

func (t *Template) GitClone(repoURL, path string, opts *TemplateGitCloneOptions) *Template

func (*Template) MakeDir

func (t *Template) MakeDir(paths []string, opts *TemplateMakeDirOptions) *Template
func (t *Template) MakeSymlink(src, dest string, opts *TemplateMakeSymlinkOptions) *Template

func (*Template) NpmInstall

func (t *Template) NpmInstall(packages []string, opts *TemplateNpmInstallOptions) *Template

func (*Template) PipInstall

func (t *Template) PipInstall(packages []string, opts *TemplatePipInstallOptions) *Template

func (*Template) Remove

func (t *Template) Remove(paths []string, opts *TemplateRemoveOptions) *Template

func (*Template) Rename

func (t *Template) Rename(src, dest string, opts *TemplateRenameOptions) *Template

func (*Template) Request

func (t *Template) Request() *build.BuildRequest

func (*Template) RunCmd

func (t *Template) RunCmd(command string, opts *TemplateCommandOptions) *Template

RunCmd adds one RUN step and optionally wraps it to execute as a specific user.

func (*Template) RunCmds

func (t *Template) RunCmds(commands []string, opts *TemplateCommandOptions) *Template

RunCmds adds multiple RUN steps using the same options.

func (*Template) SetEnvs

func (t *Template) SetEnvs(envs map[string]string) *Template

func (*Template) SetReadyCmd

func (t *Template) SetReadyCmd(readyCommand ReadyCmd) *Template

func (*Template) SetStartCmd

func (t *Template) SetStartCmd(startCommand string, readyCommand ReadyCmd) *Template

SetStartCmd records the start command and ready command for the built template.

func (*Template) SetUser

func (t *Template) SetUser(user string) *Template

func (*Template) SetWorkdir

func (t *Template) SetWorkdir(path string) *Template

func (*Template) SkipCache

func (t *Template) SkipCache() *Template

SkipCache forces subsequent helper-generated steps to bypass build cache.

type TemplateAptInstallOptions

type TemplateAptInstallOptions struct {
	NoInstallRecommends bool
	Force               *bool
}

type TemplateBuildInfo

type TemplateBuildInfo struct {
	TemplateID string
	BuildID    string
	Name       string
	Tags       []string
	Status     string
	Template   *build.TemplateResponse
	Build      *build.BuildResponse
}

type TemplateBuildOptions

type TemplateBuildOptions struct {
	GatewayConfig
	Tags           []string
	BaseTemplateID string
	Visibility     string
	Envs           map[string]string
	// Deprecated: public template creation rejects physical volume mounts.
	// Derive from an approved base template and use WorkspaceMounts for logical
	// Workspace views instead. Retained for source compatibility.
	VolumeMounts []build.TemplateVolumeMount
	// WorkspaceMounts are template defaults used only when CreateOptions has a
	// WorkspaceID and omits explicit WorkspaceMounts. They expose logical
	// container paths only; physical NFS details stay control-plane owned.
	WorkspaceMounts []build.TemplateWorkspaceMount
	// Workdir is the runtime working directory for Sandboxes created from this
	// template. It is the root allowed by Files(). To set the image build
	// WORKDIR for template steps, use Template.SetWorkdir instead.
	Workdir      string
	CPUCount     *int32
	MemoryMB     *int32
	Wait         *bool
	WaitTimeout  time.Duration
	PollInterval time.Duration
	OnBuildLog   func(LogEntry)
}

type TemplateBuildStatusOptions

type TemplateBuildStatusOptions struct {
	GatewayConfig
	LogsOffset *int
	Limit      *int
	Level      string
}

type TemplateBunInstallOptions

type TemplateBunInstallOptions struct {
	Dev   bool
	G     bool
	Force *bool
}

type TemplateCommandOptions

type TemplateCommandOptions struct {
	User  string
	Force *bool
}

TemplateCommandOptions configures template RUN helper commands.

type TemplateCopyItem

type TemplateCopyItem struct {
	Src             string
	Srcs            []string
	Dest            string
	FilesHash       string
	ForceUpload     bool
	Mode            *int
	ResolveSymlinks bool
}

TemplateCopyItem describes one COPY helper entry with per-item options.

type TemplateCopyOptions

type TemplateCopyOptions struct {
	FilesHash       string
	ForceUpload     bool
	Mode            *int
	ResolveSymlinks bool
}

TemplateCopyOptions configures local sources copied into a template build.

type TemplateGetOptions

type TemplateGetOptions struct {
	GatewayConfig
	Limit     int
	NextToken string
}

type TemplateGitCloneOptions

type TemplateGitCloneOptions struct {
	Branch string
	Depth  int
	User   string
	Force  *bool
}

type TemplateListOptions

type TemplateListOptions struct {
	GatewayConfig
	Visibility string
	TeamID     string
	Limit      int
	Offset     int
}

type TemplateMakeDirOptions

type TemplateMakeDirOptions struct {
	TemplatePathOptions
	Mode *int
}

type TemplateMakeSymlinkOptions

type TemplateMakeSymlinkOptions struct {
	TemplatePathOptions
}

type TemplateNpmInstallOptions

type TemplateNpmInstallOptions struct {
	Dev   bool
	G     bool
	Force *bool
}

type TemplatePathOptions

type TemplatePathOptions struct {
	User  string
	Force *bool
}

type TemplatePipInstallOptions

type TemplatePipInstallOptions struct {
	G     *bool
	Force *bool
}

type TemplateRemoveOptions

type TemplateRemoveOptions struct {
	TemplatePathOptions
	Recursive bool
}

type TemplateRenameOptions

type TemplateRenameOptions struct {
	TemplatePathOptions
}

type Workspace added in v0.1.4

type Workspace = control.Workspace

Workspace is a server-owned persistent NFS directory. Attach it to a Sandbox with CreateOptions.WorkspaceID; physical storage paths never cross the public SDK boundary.

type WorkspaceMount added in v0.2.0

type WorkspaceMount = control.WorkspaceMount

WorkspaceMount is a logical view of the one Workspace selected by CreateOptions.WorkspaceID. It cannot configure physical NFS storage.

type WriteInfo

type WriteInfo struct {
	Path         string
	BytesWritten int64
}

Directories

Path Synopsis
examples
build_nfs_codex_template command
Build an NFS-backed sandbox that runs Codex through nano-executor.
Build an NFS-backed sandbox that runs Codex through nano-executor.
build_template command
cmd_smoke command
control_sandbox command
full_workflow command
nfs_sandbox_lifecycle command
NFS Sandbox lifecycle example: use the legacy Sandbox-scoped NFS directory without creating a reusable Workspace.
NFS Sandbox lifecycle example: use the legacy Sandbox-scoped NFS directory without creating a reusable Workspace.
workspace_lifecycle command
Workspace lifecycle example: create, attach, pause, resume, replace, and clean up a persistent NFS directory without exposing its physical storage path.
Workspace lifecycle example: create, attach, pause, resume, replace, and clean up a persistent NFS directory without exposing its physical storage path.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL