Skip to content

nodus.sandbox

View Markdown

Sandbox: an isolated long-running container driven by exec, files and tunnels (resources.md §3.5, ADR-044).

Sandbox.create(name=...) is create-by-name: an identical create reconnects to (and wakes) the existing Sandbox, a different spec is AlreadyExists with a diff. The image defaults to nodus/agent-tools client-side.

Spec fields the API does not serve yet (volumes, ports, init, service, egress allow-lists) raise errors.Unsupported before anything is sent, because the API rejects an unknown field outright. secrets is sent when set, and a server that does not take it yet answers Unsupported as well.

class Init(git: str | None = None, ref: str | None = None, path: str | None = None, project: str | Path | None = None, setup: str | None = None) -> None

One-time setup: clone git (or upload the local project directory), then run setup as Process setup.

Type: str | None

Type: str | None

Type: str | Path | None

Type: str | None

Type: str | None

class Sandbox(obj: Obj) -> None
create(*command: str, name: str | None = None, image: Any = None, cpu: Any = None, memory: Any = None, gpu: Any = None, disk: Any = None, timeout: Any = None, idle_timeout: Any = None, on_idle: str = 'stop', secrets: list[Any] | None = None, volumes: Mapping[str, Any] | None = None, env: dict[str, str] | None = None, workdir: str | None = None, network: _spec.Egress | None = None, ports: list[int] | None = None, init: Init | None = None, service: Service | None = None, max_cost: Any = None, labels: dict[str, str] | None = None, idempotency_key: str | None = None, project: str | None = None) -> _Sandbox

Create (or reconnect to, by name) a Sandbox; returns without waiting for it to start.

exec(*command: str, pty: bool = False, stdin: bool = False, env: dict[str, str] | None = None, workdir: str | None = None, timeout: Any = None) -> _Process

Start a recorded Process; a single string with spaces runs under /bin/sh -c. Wakes a stopped Sandbox.

Type: _Files

from_id(object_id: str, project: str | None = None) -> _Sandbox
from_name(name: str, project: str | None = None) -> _Sandbox

Reconnect by name; a Sandbox the user stopped is started again.

list(labels: Mapping[str, str] | None = None, project: str | None = None) -> list[_Sandbox]
logs(follow: bool = False) -> AsyncIterator[str]

Type: str

Type: str | None

open(path: str, mode: str = 'r') -> _File
refresh_secrets() -> None
snapshot_filesystem(name: str | None = None) -> Any

Build an Image from this Sandbox’s filesystem (Beta); use it as image= for new Sandboxes.

start() -> None
status() -> View

The Sandbox’s status (phase, activity, endpoints, stop reason, cost).

stop() -> None
terminate() -> None

Type: _Tunnels

wait() -> int | None

Wait for the main command to exit and return its exit code (None when the Sandbox stopped without one).

class Service(command: str | list[str], port: int, health_path: str | None = None) -> None

A supervised main service: restarted on exit, health-checked on health_path.

Type: str | list[str]

Type: str | None

Type: int

class Tunnel(port: int, url: str, public: bool = False) -> None

Type: int

Type: bool

Type: str

class Tunnels(sb: _Sandbox) -> None

sb.tunnels.open(port) adds an ingress port and returns its URL; sb.tunnels() lists them.

open(port: int, public: bool = False) -> Tunnel