Metadata-Version: 2.4
Name: seacloud-sandbox
Version: 0.1.4
Summary: SeaCloudAI sandbox SDK for control-plane, build-plane, and runtime CMD APIs.
Author: SeaCloudAI
License-Expression: MIT
Project-URL: Homepage, https://github.com/SeaCloudAI/sandbox-python
Project-URL: Documentation, https://github.com/SeaCloudAI/sandbox-python#readme
Project-URL: Repository, https://github.com/SeaCloudAI/sandbox-python
Project-URL: Issues, https://github.com/SeaCloudAI/sandbox-python/issues
Keywords: seacloudai,sandbox,sdk,python,api
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# Sandbox Python SDK

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

## Install

```bash
pip install seacloud-sandbox
```

If you previously installed `0.1.2`, upgrade to `0.1.3` or later. `0.1.2` shipped without the `sandbox.build` package in the published artifact.

## Entrypoints

Preferred public API:

- initialize once: `Client(base_url=..., api_key=..., project_id="")`
- sandbox lifecycle through the root client: `client.create()`, `client.connect()`, `client.list()`
- sandbox runtime modules from the returned object: `sandbox.commands`, `sandbox.files`, `sandbox.git`, `sandbox.pty`
- template builder through the root client: `Template()` plus `client.build_template()`
- low-level build plane via `client.build`
- raw runtime helper: `client.runtime_from_sandbox(sandbox.raw)` or low-level sandbox instances returned by `create_sandbox(...)` / `get_sandbox(...)`

`control` and `build` talk to the gateway. Runtime access is derived from sandbox create/detail/connect responses; callers should not hardcode runtime endpoints or tokens. `project_id` is an optional gateway routing header for project-scoped deployments.

## 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.
- 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, PTY reconnect output framing, and a one-time retry for transient reconnect-stream open failures.

## Environment

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

- `SEACLOUD_BASE_URL`: SeaCloudAI gateway entrypoint
- `SEACLOUD_API_KEY`: API key used for gateway routing and authentication
- `SEACLOUD_PROJECT_ID`: optional project routing key for project-scoped gateways
- `SEACLOUD_TEMPLATE_ID`: sandbox template identifier or official template type for your target environment

Set them once in your shell:

```bash
export SEACLOUD_BASE_URL="https://sandbox-gateway.cloud.seaart.ai"
export SEACLOUD_API_KEY="..."
export SEACLOUD_PROJECT_ID="project-..."
export SEACLOUD_TEMPLATE_ID="tpl-..."
```

Default production gateway:

```text
https://sandbox-gateway.cloud.seaart.ai
```

Use `SEACLOUD_TEMPLATE_ID` for production integrations. It can be either a concrete template ID such as `tpl-...` or a stable official template type such as `base`, `claude`, or `codex` when your environment publishes those official templates.

## Production Readiness

- Initialize 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.
- In SeaCloudAI environments, prefer official template types such as `base`, `claude`, or `codex` when you want a stable platform-managed entrypoint.
- 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

- Python: use a supported CPython version for the published package and pin the SDK version in production deployments.
- API model: this SDK targets the unified SeaCloudAI 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

```python
import os

from sandbox import Client

client = Client(
    base_url=os.environ["SEACLOUD_BASE_URL"],
    api_key=os.environ["SEACLOUD_API_KEY"],
    project_id=os.getenv("SEACLOUD_PROJECT_ID", ""),
    timeout=180.0,
)

sandbox = client.create(
    os.environ["SEACLOUD_TEMPLATE_ID"],
    timeout=1800,
    waitReady=True,
)
try:
    print(sandbox.sandbox_id, sandbox.sandbox_domain)
finally:
    sandbox.delete()
```

### Bound Sandbox Workflow

```python
from sandbox import Client

client = Client(
    base_url=os.environ["SEACLOUD_BASE_URL"],
    api_key=os.environ["SEACLOUD_API_KEY"],
)
listed = client.list()

for sandbox in listed:
    sandbox.reload()
    print(sandbox.sandbox_id, sandbox.raw.get("status"))
```

### Template Build

```python
import os

from sandbox import Client, Template, wait_for_file

client = Client(
    base_url=os.environ["SEACLOUD_BASE_URL"],
    api_key=os.environ["SEACLOUD_API_KEY"],
    project_id=os.getenv("SEACLOUD_PROJECT_ID", ""),
)

built = client.build_template(
    Template()
    .from_image("docker.io/library/alpine:3.20")
    .run_cmd("echo hello-from-python >/tmp/hello.txt")
    .set_ready_cmd(wait_for_file("/tmp/hello.txt")),
    "demo:v1",
)

print(built["templateID"], built["buildID"], built["status"])
```

High-level template helpers currently include:

- lifecycle and status: `client.build_template`, `client.build_template_in_background`, `client.template_exists`, `client.template_alias_exists`, `client.get_template_build_status`, `client.list_templates`, `client.get_template`, `client.delete_template`
- serialization: `Template.to_json`, `Template.to_dockerfile`
- base images and registries: `from_dockerfile`, `from_base_image`, `from_node_image`, `from_python_image`, `from_bun_image`, `from_ubuntu_image`, `from_debian_image`, `from_aws_registry`, `from_gcp_registry`
- build-step helpers: `copy`, `copy_items`, `skip_cache`, `apt_install`, `git_clone`, `make_dir`, `make_symlink`, `npm_install`, `pip_install`, `bun_install`, `remove`, `rename`
- execution and config helpers: `run_cmd`, `set_envs`, `set_workdir`, `set_user`, `set_start_cmd`, `set_ready_cmd`, `files_hash`
- supported local copy options: `force_upload`, `mode`, `resolve_symlinks`
- supported command and path options: `run_cmd(..., user=...)`, `git_clone(..., user=...)`, `make_dir(..., user=...)`, `make_symlink(..., user=...)`, `remove(..., user=...)`, `rename(..., user=...)`
- intentionally not exposed yet: `copy(..., user=...)`, MCP server helpers, and devcontainer helpers

### Runtime Modules

```python
import os

from sandbox import Client

client = Client(
    base_url=os.environ["SEACLOUD_BASE_URL"],
    api_key=os.environ["SEACLOUD_API_KEY"],
)

sandbox = client.create(
    os.environ["SEACLOUD_TEMPLATE_ID"],
    waitReady=True,
)

try:
    sandbox.files.write("/root/workspace/hello.txt", b"hello from python")
    print(sandbox.files.read("/root/workspace/hello.txt"))
    print(sandbox.get_host(3000))
finally:
    sandbox.delete()
```

Bound sandbox helpers currently include:

- lifecycle: `reload`, `connect`, `resume`, `get_info`, `logs`, `pause`, `kill`, `delete`, `refresh`, `set_timeout`, `is_running`
- runtime conveniences: `get_metrics`, `get_host`, `proxy`
- commands module: `run`, `exec`, `list`, `connect`, `kill`, `send_stdin`
- filesystem module: `exists`, `get_info`, `list`, `make_dir`, `read`, `write`, `write_files`, `remove`, `rename`, `watch_dir`
- git module: `clone`, `pull`, `checkout`, `status`
- pty module: `create`, `connect`, `kill`, `send_stdin`, `resize`

## Recommended Usage

For most integrations, prefer one root client per process:

- initialize once with `Client(base_url=..., api_key=..., project_id="")`
- create sandboxes with `client.create(...)`
- continue through `sandbox.commands`, `sandbox.files`, `sandbox.git`, and `sandbox.pty`
- build templates with `Template()` plus `client.build_template(...)`

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

- use `create_sandbox`, `list_sandboxes`, `get_sandbox`, `connect_sandbox`
- continue from the returned sandbox object with `reload()`, `connect()`, `resume()`, `get_info()`, `get_metrics()`, `get_host()`, `logs()`, `pause()`, `refresh()`, `set_timeout()`, `kill()`, `delete()`, and `is_running()`
- only switch to runtime with `runtime` when you need file/process/stream operations
- use `build_template`, `build_template_in_background`, `template_exists`, `get_template_build_status`, `list_templates`, `get_template`, and `delete_template` on the root client for bound template workflows
- use `client.build` only for raw template/build workflows
- use `template_build()` when you want a small fluent helper that expands into the public build request payload

Low-level submodules 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 and build-plane methods under `client.build`:

- system: `metrics`, `shutdown`
- sandboxes: `create_sandbox`, `list_sandboxes`, `get_sandbox`, `delete_sandbox`
- sandbox operations: `get_sandbox_logs`, `pause_sandbox`, `connect_sandbox`, `set_sandbox_timeout`, `refresh_sandbox`, `send_heartbeat`

Recommended root-client path:

- high-level lifecycle: `create`, `connect`, `list`
- template helpers: `build_template`, `build_template_in_background`, `template_exists`, `template_alias_exists`, `get_template_build_status`, `list_templates`, `get_template`, `delete_template`
- low-level lifecycle: `create_sandbox`, `list_sandboxes`, `get_sandbox`, `connect_sandbox`
- follow-up control actions from the returned object: `reload()`, `connect()`, `resume()`, `get_info()`, `get_metrics()`, `get_host()`, `logs()`, `pause()`, `refresh()`, `set_timeout()`, `kill()`, `delete()`, `is_running()`
- runtime actions from objects that include `envdUrl`: `runtime`

Low-level direct methods like `delete_sandbox` and `get_sandbox_logs` 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 `get_pool_status`, `start_rolling_update`, `get_rolling_update_status`, and `cancel_rolling_update`.

These routes are intended for platform operators, not normal application workloads. Keep them out of business-facing integrations unless you are explicitly building operational tooling.

### Template Facade

Preferred template path:

- `Template()` for build DSL
- `client.build_template(...)` and `client.build_template_in_background(...)` for create + build + optional polling
- `client.list_templates(...)`, `client.get_template(...)`, `client.delete_template(...)`, `client.template_exists(...)`, `client.template_alias_exists(...)`, `client.get_template_build_status(...)` for bound lifecycle and status
- `Template.to_json(...)`, `Template.to_dockerfile(...)` for export helpers

Template builder conveniences include:

- base images and registries: `from_dockerfile`, `from_base_image`, `from_node_image`, `from_python_image`, `from_bun_image`, `from_ubuntu_image`, `from_debian_image`, `from_aws_registry`, `from_gcp_registry`
- file and command helpers: `copy`, `copy_items`, `skip_cache`, `apt_install`, `git_clone`, `make_dir`, `make_symlink`, `npm_install`, `pip_install`, `bun_install`, `remove`, `rename`, `run_cmd`
- execution and config helpers: `set_envs`, `set_workdir`, `set_user`, `set_start_cmd`, `set_ready_cmd`, `files_hash`
- supported local copy options: `force_upload`, `mode`, `resolve_symlinks`
- supported command and path options: `run_cmd(..., user=...)`, `git_clone(..., user=...)`, `make_dir(..., user=...)`, `make_symlink(..., user=...)`, `remove(..., user=...)`, `rename(..., user=...)`
- intentionally not exposed yet: `copy(..., user=...)`, MCP server helpers, and devcontainer helpers

### Build Plane Namespace

Low-level `client.build` exposes:

- system: `metrics`
- direct build: `direct_build`
- templates: `create_template`, `list_templates`, `get_template_by_alias`, `resolve_template_ref`, `get_template`, `update_template`, `delete_template`
- builds: `create_build`, `get_build_file`, `rollback_template`, `list_builds`, `get_build`, `get_build_status`, `get_build_logs`

The public template contract is split into three layers: top-level create fields (`name`, `tags`, `cpuCount`, `memoryMB`), SeaCloud template extensions under `extensions.seacloud` (`baseTemplateID`, `visibility`, `envs`, `storageType`, `storageSizeGB`), and build-only fields on `create_build` (`fromImage`, `fromTemplate`, `steps`, `startCmd`, `readyCmd`, registry credentials, `filesHash`).
Public create/update calls reject legacy top-level write fields such as `alias`, `teamID`, and `public`.

`create_template` and `update_template` reject `visibility="official"` on public routes, including `extensions.seacloud.visibility == "official"`.

`create_build` now follows the wire contract directly: callers pass top-level `filesHash` when needed, and the SDK returns the raw `202 {}` trigger response without adding helper fields.

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

`resolve_template_ref` is the SeaCloud stable-ref lookup endpoint. It resolves a template by `templateID`, official template `type`, or visible alias.

## Resource Safety

- The quick starts are written for disposable resources and should be adapted before copy-pasting into production jobs.
- Prefer explicit cleanup with `sandbox.delete()` and `client.build.delete_template(...)` 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.

### Runtime Namespace

Low-level runtime objects returned by `client.runtime_from_sandbox(sandbox.raw)` or low-level sandbox instances expose:

- system: `metrics`, `envs`, `configure`, `ports`
- proxy and file transfer: `proxy`, `download`, `files_content`, `upload_bytes`, `upload_json`, `upload_multipart`, `write_batch`, `compose_files`, `read_file`, `write_file`
- filesystem RPC: `list_dir`, `stat`, `make_dir`, `remove`, `move`, `edit`
- watchers: `watch_dir`, `create_watcher`, `get_watcher_events`, `remove_watcher`
- process RPC: `start`, `connect`, `list_processes`, `send_input`, `send_signal`, `close_stdin`, `update`, `stream_input`, `get_result`, `run`

Useful CMD helpers:

- `sandbox.cmd.CmdRequestOptions`: username, signature, signature expiration, range, timeout, extra headers
- `ProcessStream` and `FilesystemWatchStream`: Connect-RPC stream readers
- `ConnectFrame`: low-level frame parser

## Module Layout

- `sandbox`: root `Client` and recommended entrypoint
- `sandbox.control`: control-plane models and low-level APIs
- `sandbox.build`: build-plane models and low-level APIs
- `sandbox.cmd`: runtime models and low-level APIs
- `sandbox.core`: shared transport and error primitives

## Notes

- The gateway entrypoint always needs `base_url + api_key`; project-scoped deployments can additionally set `project_id`.
- Runtime access should be derived from sandbox response objects with `client.runtime_from_sandbox(sandbox.raw)` or low-level sandbox instances.
- `create_sandbox` and `get_sandbox` return `envdUrl` and `envdAccessToken` when nano-executor access is enabled.
- 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.
- Runtime requests can override timeout per call through `CmdRequestOptions(timeout=...)`.
- `waitReady=True` can take longer than the default timeout in production; pass `timeout=...` to `Client(...)` for long-wait workflows.
- HTTP errors are classified into typed exceptions such as `NotFoundError`, `RateLimitError`, and `ServerError`. Transport timeouts raise `RequestTimeoutError`.
- 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`.
- Runtime reconnect streams such as `connect()` and `watch_dir()` retry once on transient TLS EOF / remote-close failures before surfacing the transport error.
- Sandbox timeout is validated to `0..86400`; refresh duration to `0..3600`.
- Build 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 `SEACLOUD_API_KEY`, `envdAccessToken`, or sandbox access tokens.
- Treat runtime tokens as sandbox-scoped secrets. Prefer `client.runtime_from_sandbox(sandbox.raw)` or low-level sandbox instances so response-scoped runtime access is not copied into configuration.
- Do not log raw API keys or runtime tokens. SDK exceptions may include response bodies, so avoid logging full error payloads in shared systems.
- Set `project_id` in `Client(...)` when your gateway requires explicit project routing. The SDK sends it as `X-Project-ID`.

## Production Smoke

Use production smoke tests only with explicitly provided credentials and disposable sandboxes:

```bash
SANDBOX_RUN_INTEGRATION=1 \
SANDBOX_TEST_BASE_URL="${SEACLOUD_BASE_URL}" \
SANDBOX_TEST_API_KEY="${SEACLOUD_API_KEY}" \
SANDBOX_TEST_TEMPLATE_ID=tpl-base-dc11799b9f9f4f9e \
PYTHONPATH=src python -m unittest discover -s tests -p 'test_*.py' -v
```

`tpl-base-dc11799b9f9f4f9e` is a known-good SeaCloudAI runtime template for validating CMD routes such as `list_dir`, `read_file`, `write_file`, and `run`.
You can also run the same disposable smoke flow from GitHub Actions with `.github/workflows/integration-smoke.yml` after setting the `SANDBOX_TEST_API_KEY` repository secret.

## Integration Tests

```bash
SANDBOX_RUN_INTEGRATION=1 \
SANDBOX_TEST_BASE_URL="${SEACLOUD_BASE_URL}" \
SANDBOX_TEST_API_KEY="${SEACLOUD_API_KEY}" \
SANDBOX_TEST_TEMPLATE_ID=... \
PYTHONPATH=src python -m unittest discover -s tests -p 'test_*.py' -v
```

Use a runtime-enabled template for CMD integration coverage. For SeaCloudAI production smoke tests, `tpl-base-dc11799b9f9f4f9e` is a known-good runtime template.
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.
- GitHub Actions can publish to PyPI through Trusted Publishing with `.github/workflows/publish.yml`.
