Skip to navigation

nemo_gym.sandbox.providers.openshell

View as MarkdownOpen in Claude

OpenShell sandbox provider package.

Submodules

Package Contents

Classes

NameDescription
OpenShellConnectionConfigGateway connection settings. Defaults target a local plaintext gateway (deploy/docker compose).
OpenShellCreateConfig-
OpenShellCreateErrorRaised when the OpenShell gateway cannot create a sandbox.
OpenShellCreateVerificationErrorRaised when a new sandbox fails its readiness probe.
OpenShellExecConfig-
OpenShellOperationsConfig-
OpenShellProbeConfig-
OpenShellProviderSandbox provider backed by an OpenShell gateway’s gRPC control plane.
OpenShellProviderOptionsValidated per-sandbox options carried in SandboxSpec.provider_options.

API

class nemo_gym.sandbox.providers.openshell.OpenShellConnectionConfig(
endpoint: str = 'localhost:8080',
workspace: str = 'default',
bearer_token: str | None = None,
tls_ca_path: str | None = None,
tls_cert_path: str | None = None,
tls_key_path: str | None = None,
request_timeout_s: float = 30.0
)
Dataclass

Gateway connection settings. Defaults target a local plaintext gateway (deploy/docker compose).

bearer_token
str | None = None
endpoint
str = 'localhost:8080'
request_timeout_s
float = 30.0
tls_ca_path
str | None = None
tls_cert_path
str | None = None
tls_key_path
str | None = None
workspace
str = 'default'
nemo_gym.sandbox.providers.openshell.OpenShellConnectionConfig.__post_init__() -> None
class nemo_gym.sandbox.providers.openshell.OpenShellCreateConfig(
ready_timeout_s: float = 300,
poll_interval_s: float = 1.0,
retries: int = 2,
retry_delay_s: float = 1.0,
retry_max_delay_s: float = 30.0
)
Dataclass
poll_interval_s
float = 1.0
ready_timeout_s
float = 300
retries
int = 2
retry_delay_s
float = 1.0
retry_max_delay_s
float = 30.0
nemo_gym.sandbox.providers.openshell.OpenShellCreateConfig.__post_init__() -> None
class nemo_gym.sandbox.providers.openshell.OpenShellCreateError()

Bases: SandboxCreateError

Raised when the OpenShell gateway cannot create a sandbox.

class nemo_gym.sandbox.providers.openshell.OpenShellCreateVerificationError()

Bases: SandboxCreateVerificationError

Raised when a new sandbox fails its readiness probe.

class nemo_gym.sandbox.providers.openshell.OpenShellExecConfig(
default_timeout_s: float | None = 180,
concurrency: int = 32,
exec_shell: str = '/bin/sh',
upload_chunk_bytes: int = DEFAULT_UPLOAD_CHUNK_BYTES
)
Dataclass
concurrency
int = 32
default_timeout_s
float | None = 180
exec_shell
str = '/bin/sh'
upload_chunk_bytes
int = DEFAULT_UPLOAD_CHUNK_BYTES
nemo_gym.sandbox.providers.openshell.OpenShellExecConfig.__post_init__() -> None
class nemo_gym.sandbox.providers.openshell.OpenShellOperationsConfig(
delete_rpc_timeout_s: float = 120,
delete_concurrency: int = 32,
close_wait_deleted: bool = True,
close_timeout_s: float = 60,
poll_interval_s: float = 1.0
)
Dataclass
close_timeout_s
float = 60
close_wait_deleted
bool = True
delete_concurrency
int = 32
delete_rpc_timeout_s
float = 120
poll_interval_s
float = 1.0
nemo_gym.sandbox.providers.openshell.OpenShellOperationsConfig.__post_init__() -> None
class nemo_gym.sandbox.providers.openshell.OpenShellProbeConfig(
command: str | None = READY_PROBE_COMMAND,
expected_stdout: str | None = READY_PROBE_EXPECTED,
timeout_s: int = 30,
deadline_s: float | None = 60,
stable_count: int = 1,
stable_delay_s: float = 1.0
)
Dataclass
command
str | None = READY_PROBE_COMMAND
deadline_s
float | None = 60
expected_stdout
str | None = READY_PROBE_EXPECTED
stable_count
int = 1
stable_delay_s
float = 1.0
timeout_s
int = 30
nemo_gym.sandbox.providers.openshell.OpenShellProbeConfig.__post_init__() -> None
class nemo_gym.sandbox.providers.openshell.OpenShellProvider(
connection: nemo_gym.sandbox.providers.openshell.provider.OpenShellConnectionConfig | collections.abc.Mapping[str, typing.Any] | None = None,
create: nemo_gym.sandbox.providers.openshell.provider.OpenShellCreateConfig | collections.abc.Mapping[str, typing.Any] | None = None,
exec: nemo_gym.sandbox.providers.openshell.provider.OpenShellExecConfig | collections.abc.Mapping[str, typing.Any] | None = None,
probe: nemo_gym.sandbox.providers.openshell.provider.OpenShellProbeConfig | collections.abc.Mapping[str, typing.Any] | None = None,
operations: nemo_gym.sandbox.providers.openshell.provider.OpenShellOperationsConfig | collections.abc.Mapping[str, typing.Any] | None = None,
attribution: nemo_gym.sandbox.attribution.AttributionConfig | collections.abc.Mapping[str, typing.Any] | None = None
)

Sandbox provider backed by an OpenShell gateway’s gRPC control plane.

_attribution
= _coerce_config(attribution, AttributionConfig)
_connection
_create_config
= _coerce_config(create, OpenShellCreateConfig)
_delete_shared
_exec_config
= _coerce_config(exec, OpenShellExecConfig)
_operations
_probe
= _coerce_config(probe, OpenShellProbeConfig)
_shared
name
= 'openshell'
nemo_gym.sandbox.providers.openshell.OpenShellProvider._build_policy(
policy: str | collections.abc.Mapping[str, typing.Any]
) -> typing.Any
nemo_gym.sandbox.providers.openshell.OpenShellProvider._build_sandbox_spec(
image: str | None,
) -> typing.Any
nemo_gym.sandbox.providers.openshell.OpenShellProvider._call(
func: typing.Any,
args: typing.Any = (),
kwargs: typing.Any = {}
) -> typing.Any
async
nemo_gym.sandbox.providers.openshell.OpenShellProvider._call_create(
name: str,
workspace: str,
kwargs: typing.Any = {}
) -> typing.Any
async

Run CreateSandbox on a worker. Cancelling the await does not stop a call already running, so a create that commits after the cancel is deleted when it returns.

nemo_gym.sandbox.providers.openshell.OpenShellProvider._cleanup_failed_create_handle(
) -> None
async
nemo_gym.sandbox.providers.openshell.OpenShellProvider._create_sandbox_with_retries(
pb_spec: typing.Any,
name: str,
labels: dict[str, str]
) -> typing.Any
async

Issue CreateSandbox, retrying transient gRPC failures with the same name.

Retrying with the same name is safe: if an earlier attempt actually committed, the retry fails ALREADY_EXISTS and the sandbox is recovered via GetSandbox.

nemo_gym.sandbox.providers.openshell.OpenShellProvider._reap_orphans() -> None
async

Delete this process’s orphaned sandboxes: ones it no longer tracks, for example a create cancelled after the gateway committed it. Selected by the process label, which needs attribution to be enabled.

nemo_gym.sandbox.providers.openshell.OpenShellProvider._submit_delete(
) -> None
nemo_gym.sandbox.providers.openshell.OpenShellProvider._timed_exec(
args: typing.Any = (),
kwargs: typing.Any = {}
) -> tuple[typing.Any, float]

Run the SDK exec and time it inside the worker thread, so executor queueing is not counted.

nemo_gym.sandbox.providers.openshell.OpenShellProvider._verify_created_handle(
) -> None
async

Poll the readiness probe until it passes stable_count times or the deadline elapses.

nemo_gym.sandbox.providers.openshell.OpenShellProvider._wait_ready(
timeout_s: int | float
) -> None
async

Poll GetSandbox until READY, raising on the ERROR/DELETING phases or the deadline.

nemo_gym.sandbox.providers.openshell.OpenShellProvider.aclose() -> None
async

Release the shared client/pool (closed for real when the last provider releases it).

Does not wait for deletes: they run on their own workers. When no sandbox of this process is still live or being created, it first deletes this process’s orphaned sandboxes (see _reap_orphans).

nemo_gym.sandbox.providers.openshell.OpenShellProvider.close(
) -> None
async

Hand the sandbox’s delete to a worker thread and return without waiting for the gateway.

The worker deletes, waits until the sandbox is gone when operations.close_wait_deleted is set, and retries transient failures. It is already queued when this returns and runs to completion at interpreter exit even if the event loop is gone. Every outcome is logged with the sandbox name; a delete that fails for good is logged as possibly leaked and then forgotten.

nemo_gym.sandbox.providers.openshell.OpenShellProvider.create(
async

Create a sandbox through the gateway, wait for the READY phase, then probe exec readiness.

spec.image is optional (the gateway’s configured default image is used when unset). spec.ttl_s is not enforced (OpenShell sandboxes live until deleted) and only logs a warning. spec.entrypoint is unsupported: the OpenShell supervisor owns the sandbox entrypoint. spec.provider_options accepts providers (OpenShell credential-provider names), policy (a SandboxPolicy mapping or YAML path), and template_resources / driver_config (free-form driver passthrough Structs). A half-created sandbox is deleted on any failure.

nemo_gym.sandbox.providers.openshell.OpenShellProvider.download_file(
source_path: str,
target_path: pathlib.Path
) -> None
async

Download one sandbox file via a base64 round-trip (binary-safe over the text exec stream).

The whole file is buffered in memory (inflated 4/3 by base64), so this is intended for small-to-medium artifacts rather than large archives.

nemo_gym.sandbox.providers.openshell.OpenShellProvider.exec(
command: str,
cwd: str | None = None,
env: dict[str, str] | None = None,
timeout_s: int | float | None = None,
user: str | int | None = None,
stdin: bytes | None = None
async

Run <shell> -c <command> through the gateway’s streaming exec; never raises for command failure.

The timeout is enforced by the gateway (timeout_seconds); the SDK extends its gRPC deadline past it. user is ignored with a warning: the OpenShell exec API has no user field, so commands run as the sandbox’s default user.

nemo_gym.sandbox.providers.openshell.OpenShellProvider.status(
async

Sandbox phase via GetSandbox (missing -> STOPPED; RPC failure -> UNKNOWN).

nemo_gym.sandbox.providers.openshell.OpenShellProvider.upload_file(
source_path: pathlib.Path,
target_path: str
) -> None
async

Upload one local file by streaming its bytes through exec stdin (creates the parent dir).

Bytes are sent in exec.upload_chunk_bytes chunks because each chunk travels as a single gRPC message that must stay under the gateway’s max decode size.

class nemo_gym.sandbox.providers.openshell.OpenShellProviderOptions(
providers: list[str] = list(),
policy: typing.Any | None = None,
template_resources: dict[str, typing.Any] = dict(),
driver_config: dict[str, typing.Any] = dict()
)
Dataclass

Validated per-sandbox options carried in SandboxSpec.provider_options.

driver_config
dict[str, Any] = field(default_factory=dict)
policy
Any | None = None
providers
list[str] = field(default_factory=list)
template_resources
dict[str, Any] = field(default_factory=dict)
nemo_gym.sandbox.providers.openshell.OpenShellProviderOptions.from_mapping(
options: collections.abc.Mapping[str, typing.Any]
classmethod