chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:12:00 +08:00
commit 3de48288cb
2986 changed files with 1131193 additions and 0 deletions
@@ -0,0 +1,417 @@
#!/usr/bin/env python3
"""
End-to-end test: create a managed session against an Omnigent server, and have
the agent run a REAL workload — an LLM turn against the CoreWeave / W&B inference
endpoint — from inside the managed CHILD sandbox the server provisions.
Two modes:
1. --server <url>: use an EXISTING omnigent server (already configured with
sandbox.provider=cwsandbox). No public-IP sandbox required — good for W&B
serverless users who can't expose a public service.
python tests/e2e/integrations/deploy/cwsandbox/e2e_managed.py \
--server http://my-omnigent:6767
2. (default) spin the server up inside a CW Sandbox with a public service. The
sandbox runs a prebaked image with this fork's omnigent + the cwsandbox SDK
(build/push first; pass --image), and the driver injects the LLM creds.
export CWSANDBOX_API_KEY=... # provisions the sandboxes
export WANDB_INFERENCE_KEY=... # the agent's LLM credential
python tests/e2e/integrations/deploy/cwsandbox/e2e_managed.py \
--image docker.io/<you>/omnigent-cwsandbox:test
"""
from __future__ import annotations
import argparse
import base64
import json
import os
import sys
import time
import httpx
from cwsandbox import NetworkOptions, Sandbox
SERVER_PORT = 6767
CONFIG_HOME = "/root/.omnigent"
WANDB_BASE_URL = "https://api.inference.wandb.ai/v1"
WANDB_MODEL = "Qwen/Qwen3-Coder-480B-A35B-Instruct"
PROMPT = "What is 2+2? Reply with ONLY the number, nothing else."
def _child_env(wandb_key: str) -> dict[str, str]:
"""Env injected into every managed CHILD sandbox — the single source of truth.
The launcher forwards these by NAME from the server process env. OPENAI_*
reach the harness automatically; the HARNESS_* knobs ride
OMNIGENT_RUNNER_ENV_PASSTHROUGH. The config's `sandbox.cwsandbox.env` name
list and the server sandbox's env values both derive from this dict.
"""
return {
"OPENAI_API_KEY": wandb_key,
"OPENAI_BASE_URL": WANDB_BASE_URL,
"HARNESS_OPENAI_AGENTS_MODEL": WANDB_MODEL,
# W&B is chat/completions-compatible, not the Responses API.
"HARNESS_OPENAI_AGENTS_USE_RESPONSES": "0",
# Tell the in-child host to forward the HARNESS_* knobs to the runner.
"OMNIGENT_RUNNER_ENV_PASSTHROUGH": (
"HARNESS_OPENAI_AGENTS_MODEL,HARNESS_OPENAI_AGENTS_USE_RESPONSES"
),
}
def log(msg: str) -> None:
print(msg, flush=True)
def start_server_sandbox(image: str, cw_key: str, wandb_key: str) -> tuple[Sandbox, str]:
"""Provision the server sandbox (public service) carrying the child-env values."""
log(f"[1/6] provisioning server sandbox from {image}")
sb = Sandbox.run(
"sleep",
"infinity",
container_image=image,
profile_names=["default"],
max_lifetime_seconds=3600,
resources={"cpu": "2", "memory": "4Gi"},
network=NetworkOptions(
ingress_mode="public", exposed_ports=[SERVER_PORT], egress_mode="internet"
),
environment_variables={
"CWSANDBOX_API_KEY": cw_key,
"OMNIGENT_CWSANDBOX_HOST_IMAGE": image,
# Values the launcher passes through (by name) into each child:
**_child_env(wandb_key),
},
tags=["omnigent-e2e", "server"],
)
sb.wait()
ip = (sb.service_address or "").split(":")[0]
if not ip:
raise SystemExit(f"server sandbox {sb.sandbox_id} has no public service address")
log(f" sandbox={sb.sandbox_id} public_ip={ip}")
return sb, ip
def _write(sb: Sandbox, path: str, content: str) -> None:
b64 = base64.b64encode(content.encode()).decode()
sb.exec(
["bash", "-lc", f"mkdir -p $(dirname {path}) && echo {b64} | base64 -d > {path}"]
).result()
def configure_and_start_server(sb: Sandbox, server_url: str, wandb_key: str) -> None:
"""Write config + an openai-agents agent, then launch `omnigent server`."""
log(f"[2/6] starting omnigent server (server_url={server_url})")
child_env_names = ", ".join(_child_env(wandb_key))
_write(
sb,
f"{CONFIG_HOME}/config.yaml",
"sandbox:\n"
" provider: cwsandbox\n"
f" server_url: {server_url}\n"
" cwsandbox:\n"
f" env: [{child_env_names}]\n",
)
# Agent bound to the openai-agents harness + the W&B model. executor.auth
# (ApiKeyAuth) is what the runner's gateway routing reads for base_url +
# api_key — the bare OPENAI_BASE_URL env is ignored, so this is required
# to target W&B instead of defaulting to api.openai.com.
_write(
sb,
"/root/e2e-agent/agent.yaml",
"name: e2e-probe\n"
"prompt: You are a terse calculator. Answer with only the number.\n"
"executor:\n"
" harness: openai-agents\n"
f" model: {WANDB_MODEL}\n"
" auth:\n"
" type: api_key\n"
f" api_key: {wandb_key}\n"
f" base_url: {WANDB_BASE_URL}\n",
)
start = (
f"OMNIGENT_CONFIG_HOME={CONFIG_HOME} OMNIGENT_LOCAL_SINGLE_USER=1 "
f"setsid nohup omnigent server --host 0.0.0.0 --port {SERVER_PORT} "
f"--config {CONFIG_HOME}/config.yaml --no-open --agent /root/e2e-agent "
"> /tmp/omnigent-server.log 2>&1 < /dev/null & echo started"
)
sb.exec(["bash", "-lc", start]).result()
def wait_server_ready(base: str, sb: Sandbox | None, timeout_s: float = 120.0) -> dict:
log(f"[3/6] waiting for {base}/v1/info")
deadline = time.monotonic() + timeout_s
last = ""
while time.monotonic() < deadline:
try:
r = httpx.get(f"{base}/v1/info", timeout=5.0)
if r.status_code == 200:
log(f" ready: {json.dumps(r.json())}")
return r.json()
last = f"HTTP {r.status_code}"
except httpx.HTTPError as exc:
last = str(exc)
time.sleep(3.0)
log(f" not ready ({last}); server log:")
_dump_server_logs(sb)
raise SystemExit("server never became ready")
def pick_agent(base: str, agent_id: str | None = None) -> str:
resp = httpx.get(f"{base}/v1/agents", timeout=10.0)
resp.raise_for_status()
agents = resp.json()["data"]
if not agents:
raise SystemExit("no agents registered on the server to bind a session to")
if agent_id:
chosen = next((a for a in agents if a.get("id") == agent_id), None)
if chosen is None:
raise SystemExit(f"agent_id {agent_id!r} not found on the server")
else:
chosen = next((a for a in agents if a.get("name") == "e2e-probe"), agents[0])
log(f" agent_id={chosen['id']} ({chosen.get('name')})")
return chosen["id"]
def create_managed_session(base: str, agent_id: str) -> str:
log("[4/6] creating managed session with a prompt")
body = {
"agent_id": agent_id,
"host_type": "managed",
"initial_items": [
{
"type": "message",
"data": {"role": "user", "content": [{"type": "input_text", "text": PROMPT}]},
}
],
}
r = httpx.post(f"{base}/v1/sessions", json=body, timeout=180.0)
if r.status_code >= 300:
raise SystemExit(f"create session failed: HTTP {r.status_code}: {r.text[:600]}")
conv_id = r.json()["id"]
log(f" session={conv_id}")
return conv_id
def _dump_server_logs(sb: Sandbox | None) -> None:
if sb is None:
log(" (external server — check its own logs)")
return
out = sb.exec(
[
"bash",
"-lc",
"tail -50 ~/.omnigent/logs/cli-*.log 2>/dev/null; "
"echo '--- stdout ---'; tail -15 /tmp/omnigent-server.log",
]
).result()
log(out.stdout)
def _omnigent_children() -> list:
"""List sandboxes the launcher tags 'omnigent' (managed hosts); [] on error."""
try:
return Sandbox.list(tags=["omnigent"]).result()
except Exception as exc:
log(f" (could not list child sandboxes: {exc})")
return []
def dump_child_logs(exclude: set[str]) -> None:
"""Dump runner/harness logs from a CHILD this run created (not in *exclude*)."""
# Scope to children NOT present before this run — never touch sandboxes
# belonging to other runs / deployments that share the 'omnigent' tag.
children = [c for c in _omnigent_children() if c.sandbox_id not in exclude]
running = [c for c in children if "RUNNING" in str(getattr(c, "status", "")).upper()]
target = (running or children or [None])[0]
if target is None:
log(" (no child sandbox found for this run)")
return
log(f" --- child sandbox {target.sandbox_id} runner/harness logs ---")
try:
out = target.exec(
[
"bash",
"-lc",
"tail -60 ~/.omnigent/logs/*.log 2>/dev/null; echo '--- host log ---'; "
"tail -40 /tmp/omnigent-host.log 2>/dev/null",
]
).result()
log(out.stdout)
except Exception as exc:
log(f" (could not read child logs: {exc})")
def wait_host_online(
base: str, conv_id: str, sb: Sandbox | None, timeout_s: float = 360.0
) -> bool:
log("[5/6] waiting for the managed host to register (child sandbox)")
deadline = time.monotonic() + timeout_s
while time.monotonic() < deadline:
try:
d = httpx.get(f"{base}/v1/sessions/{conv_id}", timeout=5.0).json()
if d.get("host_online"):
log(f" ✓ host online: host_id={d.get('host_id')}")
log(f" runner_id={d.get('runner_id')}")
return True
if d.get("last_task_error"):
log(f" launch error: {d['last_task_error']}")
break
except httpx.HTTPError:
pass
time.sleep(5.0)
log(" host did not come online; server logs:")
_dump_server_logs(sb)
return False
def _assistant_text(items: list[dict]) -> str:
"""Extract concatenated assistant text from session items."""
out = []
for it in items:
if it.get("type") != "message":
continue
data = it.get("data") or {}
if data.get("role") != "assistant":
continue
for block in data.get("content") or []:
if isinstance(block, dict) and block.get("text"):
out.append(block["text"])
elif isinstance(block, str):
out.append(block)
return " ".join(out).strip()
def wait_for_reply(
base: str,
conv_id: str,
sb: Sandbox | None,
pre_children: set[str],
timeout_s: float = 180.0,
) -> str | None:
"""Poll session items until the agent posts an assistant reply."""
log("[6/6] waiting for the agent to run the LLM turn and reply")
deadline = time.monotonic() + timeout_s
while time.monotonic() < deadline:
try:
d = httpx.get(f"{base}/v1/sessions/{conv_id}", timeout=5.0).json()
# Check for a failure FIRST — an error that arrives after partial
# assistant text must not be masked by returning that text.
if d.get("last_task_error"):
log(f" task error: {d['last_task_error']}")
break
# Only accept the reply once the turn has FINISHED (status back to
# idle), so an intermediate/streaming block isn't a false PASS.
text = _assistant_text(d.get("items") or [])
if text and d.get("status") == "idle":
return text
except httpx.HTTPError:
pass
time.sleep(4.0)
log(" no reply.")
try:
items = httpx.get(f"{base}/v1/sessions/{conv_id}", timeout=5.0).json().get("items", [])
log(f" raw items: {json.dumps(items)[:1500]}")
except httpx.HTTPError:
pass
log(" server logs:")
_dump_server_logs(sb)
if sb is not None:
log(" child sandbox logs:")
dump_child_logs(pre_children)
return None
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"--server",
default=None,
help="Use an EXISTING omnigent server at this URL (e.g. http://host:6767) "
"instead of spinning one up in a CW sandbox. The server must already be "
"configured with sandbox.provider=cwsandbox. No public-IP sandbox needed.",
)
parser.add_argument(
"--image",
default=None,
help="Prebaked omnigent+cwsandbox image (required only when spinning up the server).",
)
parser.add_argument(
"--agent-id",
default=None,
help="Bind the session to this agent id (default: the seeded e2e-probe, "
"else the first registered agent). Useful with --server.",
)
parser.add_argument("--keep", action="store_true")
args = parser.parse_args()
external = args.server is not None
cw_key = os.environ.get("CWSANDBOX_API_KEY")
wandb_key = os.environ.get("WANDB_INFERENCE_KEY")
if not external:
# Self-hosted mode spins up the server sandbox + injects the LLM creds.
if not args.image:
print("ERROR: --image is required unless --server is given", file=sys.stderr)
return 2
if not cw_key or not wandb_key:
print("ERROR: set CWSANDBOX_API_KEY and WANDB_INFERENCE_KEY", file=sys.stderr)
return 2
sb: Sandbox | None = None
if external:
base = args.server.rstrip("/")
log(f"[*] using existing omnigent server at {base}")
else:
sb, ip = start_server_sandbox(args.image, cw_key, wandb_key)
base = f"http://{ip}:{SERVER_PORT}"
# Children carry the shared "omnigent" tag, so snapshot which ones already
# existed before this run — we only ever touch the ones WE cause to appear,
# never another run's / deployment's managed hosts.
pre_children = {c.sandbox_id for c in _omnigent_children()} if sb is not None else set()
reply = None
try:
if not external:
configure_and_start_server(sb, base, wandb_key)
wait_server_ready(base, sb)
agent_id = pick_agent(base, args.agent_id)
conv_id = create_managed_session(base, agent_id)
if wait_host_online(base, conv_id, sb):
reply = wait_for_reply(base, conv_id, sb, pre_children)
finally:
# Only tear down sandboxes WE created. An external server owns its own
# children, so leave them alone.
if sb is not None and not args.keep:
log(f"cleaning up server sandbox {sb.sandbox_id} + managed child(ren)")
try:
sb.stop().result()
except Exception as exc:
log(f" warning: server cleanup failed: {exc}")
# Stop only children that appeared during this run (id not in the
# pre-run snapshot) — never another run's sandboxes.
for child in _omnigent_children():
if child.sandbox_id in pre_children:
continue
try:
child.stop().result()
log(f" stopped child {child.sandbox_id}")
except Exception as exc:
log(f" warning: child cleanup failed for {child.sandbox_id}: {exc}")
print("\n" + "=" * 60)
if reply:
print("E2E PASSED — agent ran a real LLM workload in the sandbox.")
print(f"Prompt: {PROMPT}")
print(f"Reply: {reply!r}")
return 0
print("E2E FAILED — see logs above.")
return 1
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,245 @@
#!/usr/bin/env python3
"""
Smoke test for the CoreWeave Sandbox (cwsandbox) provider.
Talks directly to the CW Sandbox HTTP API to validate the
primitives the managed-host launcher relies on: provision → RUNNING,
unary exec, AddFile, public egress, detach survival (setsid nohup), and
terminate.
export CWSANDBOX_API_KEY=...
python tests/e2e/integrations/deploy/cwsandbox/smoke_test.py [--image IMG] [--keep]
Transport is curl (subprocess): the system Python's TLS may be too old
to reach the API, while curl uses the OS's. Zero pip dependencies.
"""
from __future__ import annotations
import argparse
import base64
import json
import os
import subprocess
import sys
import time
from urllib.parse import quote
DEFAULT_IMAGE = "python:3.11-slim"
MAX_LIFETIME_S = 3600
PROVISION_TIMEOUT_S = 300
POLL_INTERVAL_S = 3.0
class SmokeError(Exception):
"""A smoke-test check failed."""
class Client:
"""CW Sandbox API client over curl (Bearer auth, JSON)."""
def __init__(self, base_url: str, api_key: str) -> None:
self._base = base_url.rstrip("/")
self._auth = f"Authorization: Bearer {api_key}"
def _request(self, method: str, path: str, op: str, body: dict | None = None) -> dict:
cmd = [
"curl",
"-sS",
"-X",
method,
f"{self._base}{path}",
"-H",
self._auth,
"-H",
"Accept: application/json",
"-w",
"\n%{http_code}",
]
if body is not None:
cmd += ["-H", "Content-Type: application/json", "--data-binary", json.dumps(body)]
try:
proc = subprocess.run(cmd, capture_output=True, text=True, timeout=70.0)
except FileNotFoundError as exc:
raise SmokeError("curl not found on PATH") from exc
except subprocess.TimeoutExpired as exc:
raise SmokeError(f"{op} -> timed out") from exc
if proc.returncode != 0:
raise SmokeError(f"{op} -> curl failed: {proc.stderr.strip()[:300]}")
raw, _, status = proc.stdout.rpartition("\n")
if not status.isdigit() or int(status) >= 400:
raise SmokeError(f"{op} -> HTTP {status}: {raw[:500]}")
return json.loads(raw) if raw.strip() else {}
def provision(self, *, image: str, name: str) -> str:
body = {
"containerImage": image,
"command": "sleep",
"args": ["infinity"],
"resources": {"cpu": "1", "memory": "1Gi"},
"maxLifetimeSeconds": MAX_LIFETIME_S,
"network": {"egressMode": "internet"}, # egress defaults to none
"tags": ["omnigent-smoke", name],
}
return self._request("POST", "/v1beta2/sandboxes", "provision", body)["sandboxId"]
def wait_running(self, sandbox_id: str) -> None:
deadline = time.monotonic() + PROVISION_TIMEOUT_S
last = ""
while time.monotonic() < deadline:
payload = self._request("GET", f"/v1beta2/sandboxes/{sandbox_id}", "get")
status = payload.get("sandboxStatus", "")
if status != last:
print(f" status: {status}")
last = status
if status == "SANDBOX_STATUS_RUNNING":
return
if status.startswith("SANDBOX_STATUS_") and status not in (
"SANDBOX_STATUS_CREATING",
"SANDBOX_STATUS_PENDING",
"SANDBOX_STATUS_UNSPECIFIED",
):
raise SmokeError(f"terminal status {status}: {payload.get('statusReason', '?')}")
time.sleep(POLL_INTERVAL_S)
raise SmokeError(f"not RUNNING within {PROVISION_TIMEOUT_S}s (last={last})")
def exec(self, sandbox_id: str, command: str) -> tuple[int, str, str]:
result = self._request(
"POST",
f"/v1beta2/sandboxes/{sandbox_id}/exec",
"exec",
{"command": ["bash", "-lc", command], "maxTimeoutSeconds": 60},
).get("result", {})
# exitCode is omitted from the response when it is 0 (zero default).
return (
int(result.get("exitCode", 0)),
_b64(result.get("stdout", "")),
_b64(result.get("stderr", "")),
)
def put_file(self, sandbox_id: str, path: str, contents: bytes) -> None:
payload = self._request(
"POST",
f"/v1beta2/sandboxes/{sandbox_id}/files",
"addFile",
{"filepath": path, "fileContents": base64.b64encode(contents).decode("ascii")},
)
if not payload.get("success", False):
raise SmokeError(f"addFile failed: {payload.get('errorMessage')}")
def get_file(self, sandbox_id: str, path: str) -> bytes:
payload = self._request(
"GET",
f"/v1beta2/sandboxes/{sandbox_id}/files/{quote(path, safe='')}",
"retrieveFile",
)
return base64.b64decode(payload.get("fileContents", ""))
def stop(self, sandbox_id: str) -> None:
self._request("POST", f"/v1beta2/sandboxes/{sandbox_id}/stop", "stop", {})
def _b64(value: str) -> str:
try:
return base64.b64decode(value).decode("utf-8", errors="replace") if value else ""
except Exception:
return value
def _check(failures: list[str], ok: bool, label: str) -> None:
print(f" {'' if ok else ''} {label}")
if not ok:
failures.append(label)
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--image", default=DEFAULT_IMAGE)
parser.add_argument("--keep", action="store_true", help="don't terminate at the end")
args = parser.parse_args()
api_key = os.environ.get("CWSANDBOX_API_KEY")
if not api_key:
print("ERROR: set CWSANDBOX_API_KEY", file=sys.stderr)
return 2
base_url = os.environ.get("CWSANDBOX_BASE_URL", "https://api.cwsandbox.com")
client = Client(base_url, api_key)
name = f"smoke-{int(time.time())}"
print(f"▸ smoke test against {base_url} image={args.image} tag={name}")
sandbox_id: str | None = None
failures: list[str] = []
try:
print("\n[1/6] provision")
sandbox_id = client.provision(image=args.image, name=name)
print(f" sandbox_id={sandbox_id}")
client.wait_running(sandbox_id)
_check(failures, True, "RUNNING")
print("\n[2/6] unary exec")
code, out, _ = client.exec(sandbox_id, 'printf %s "$HOME"; echo; uname -sm')
_check(failures, code == 0, "exec exit code 0")
_check(failures, out.strip() != "", "exec returned $HOME")
print("\n[3/6] AddFile (+ read-back via exec)")
marker = b"cwsandbox-omnigent-smoke\n"
client.put_file(sandbox_id, "/tmp/oa-smoke.txt", marker)
_, out, _ = client.exec(sandbox_id, "cat /tmp/oa-smoke.txt")
_check(failures, out.encode() == marker, "file readable via exec after AddFile")
# RetrieveFile-over-REST can't route an absolute {filepath}; reads
# (never needed by the launcher) go through exec+base64 instead.
try:
ok = client.get_file(sandbox_id, "/tmp/oa-smoke.txt") == marker
print(f" {'' if ok else ''} RetrieveFile REST (bonus): {'works' if ok else 'no'}")
except SmokeError:
print(" RetrieveFile REST unsupported for absolute paths (expected)")
print("\n[4/6] public egress (outbound https from inside)")
code, out, _ = client.exec(
sandbox_id,
'python3 -c "import urllib.request as u; '
"print(u.urlopen('https://api.github.com', timeout=15).status)\"",
)
_check(failures, code == 0 and "200" in out, "outbound HTTPS reached api.github.com")
print("\n[5/6] detach survives exec session (setsid nohup ... &)")
client.exec(sandbox_id, "rm -f /tmp/oa-detach-alive")
client.exec(
sandbox_id,
"setsid nohup sh -c 'sleep 4; echo alive > /tmp/oa-detach-alive' "
"> /tmp/oa-detach.log 2>&1 < /dev/null & echo launched",
)
time.sleep(7)
_, out, _ = client.exec(sandbox_id, "cat /tmp/oa-detach-alive 2>/dev/null")
_check(failures, out.strip() == "alive", "detached process kept running after exec")
print("\n[6/6] terminate")
if args.keep:
print(f" --keep set; leaving {sandbox_id} running")
else:
client.stop(sandbox_id)
_check(failures, True, "stop accepted")
sandbox_id = None
except SmokeError as exc:
failures.append(f"FATAL: {exc}")
finally:
if sandbox_id is not None and not args.keep:
try:
client.stop(sandbox_id)
print(f"\n (cleaned up {sandbox_id})")
except Exception as exc:
print(f"\n WARNING: failed to clean up {sandbox_id}: {exc}")
print("\n" + "=" * 60)
if failures:
print("SMOKE TEST FAILED:")
for f in failures:
print(f"{f}")
return 1
print("SMOKE TEST PASSED — every managed-host primitive works.")
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,176 @@
#!/usr/bin/env python3
"""
Smoke test for the E2B sandbox provider.
Drives the REAL :class:`~omnigent.onboarding.sandboxes.e2b.E2BSandboxLauncher`
against a live E2B sandbox to validate every primitive the managed-host /
CLI-bootstrap flows rely on: provision -> run (incl. the non-zero-exit
``CommandExitException`` path) -> put + read-back -> keep_alive ->
stream_exec (combined output) -> attach -> public egress -> terminate
(idempotent). This is the test that actually exercises the E2B SDK calls
the launcher makes, end to end.
By default it boots from E2B's stock ``base`` template, so it needs NO
pre-built omnigent host template — it validates the launcher's SDK wiring
in isolation. Pass ``--template omnigent-host`` (after ``e2b template
build``; see deploy/e2b/README.md) to smoke the real host template too.
pip install 'omnigent[e2b]'
export E2B_API_KEY=e2b_...
python tests/e2e/integrations/deploy/e2b/e2b_smoke_test.py [--template NAME] [--keep]
Exit code 0 = every primitive worked; 1 = a check failed; 2 = setup error.
"""
from __future__ import annotations
import argparse
import os
import sys
import time
# The launcher lazy-imports the e2b SDK; surface a clean hint if it (or the
# omnigent package) isn't importable rather than a raw traceback.
try:
from omnigent.onboarding.sandboxes.e2b import (
E2BSandboxLauncher,
resolve_max_lifetime_s,
)
except ImportError as exc: # pragma: no cover - environment guard
print(f"ERROR: cannot import the launcher ({exc}).", file=sys.stderr)
print("Run from the repo root with omnigent installed.", file=sys.stderr)
raise SystemExit(2) from exc
def _check(failures: list[str], ok: bool, label: str) -> None:
"""Record and print one check result."""
print(f" {'' if ok else ''} {label}", flush=True)
if not ok:
failures.append(label)
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"--template",
default="base",
help="E2B template to boot from (default: E2B's stock 'base'; pass "
"'omnigent-host' to smoke the real host template once built).",
)
parser.add_argument("--keep", action="store_true", help="don't terminate at the end")
args = parser.parse_args()
if not os.environ.get("E2B_API_KEY"):
print("ERROR: set E2B_API_KEY (https://e2b.dev/dashboard)", file=sys.stderr)
return 2
# A sentinel env var we inject at provision and read back from inside the
# sandbox — exercises the env-passthrough path (resolved from THIS process
# env by name, exactly like the server forwards its own environment).
marker_name = "OMNIGENT_E2B_SMOKE_MARKER"
marker_value = f"smoke-{int(time.time())}"
os.environ[marker_name] = marker_value
launcher = E2BSandboxLauncher(template=args.template, env=[marker_name])
name = f"smoke-{int(time.time())}"
print(f"▸ E2B launcher smoke template={args.template} tag={name}")
sandbox_id: str | None = None
failures: list[str] = []
try:
print("\n[1/8] prepare (SDK + credentials)")
launcher.prepare()
_check(failures, True, "prepare passed")
print("\n[2/8] provision")
sandbox_id = launcher.provision(name)
_check(failures, bool(sandbox_id), f"provisioned sandbox_id={sandbox_id}")
print("\n[3/8] run: exit code, output, and env passthrough")
result = launcher.run(sandbox_id, f'echo "$HOME"; printf %s "${marker_name}"', check=True)
_check(failures, result.returncode == 0, "run exit code 0")
_check(failures, result.stdout.strip() != "", "run captured stdout")
_check(failures, marker_value in result.stdout, "injected env var visible inside sandbox")
print("\n[4/8] run: non-zero exit (CommandExitException path)")
# E2B raises CommandExitException on non-zero exit — the launcher must
# catch it and surface the code/streams rather than letting it escape.
failed = launcher.run(sandbox_id, "echo to-stderr >&2; exit 7", check=False)
_check(failures, failed.returncode == 7, "non-zero exit surfaced as returncode 7")
_check(failures, "to-stderr" in failed.stderr, "stderr captured on failing command")
print("\n[5/8] put: ship a binary file and read it back")
import tempfile
from pathlib import Path
payload = b"e2b-omnigent-smoke\x00\x01binary\n"
with tempfile.NamedTemporaryFile(delete=False) as tmp:
tmp.write(payload)
local = Path(tmp.name)
try:
launcher.put(sandbox_id, local, "/tmp/oa-smoke.bin")
finally:
local.unlink(missing_ok=True)
readback = launcher.run(sandbox_id, "base64 -w0 /tmp/oa-smoke.bin", check=True)
import base64
_check(
failures,
base64.b64decode(readback.stdout.strip()) == payload,
"uploaded file bytes match read-back",
)
print("\n[6/8] keep_alive (set_timeout to max) + attach (connect + is_running)")
launcher.keep_alive(sandbox_id) # soft-fail; must not raise
_check(failures, True, f"keep_alive extended (target {resolve_max_lifetime_s() // 3600}h)")
# Fresh launcher to force a real Sandbox.connect (not the cached handle).
E2BSandboxLauncher(template=args.template).attach(sandbox_id)
_check(failures, True, "attach validated a running sandbox")
print("\n[7/8] stream_exec: combined stdout+stderr line stream")
proc = launcher.stream_exec(sandbox_id, "echo out-line; echo err-line >&2")
streamed = "".join(proc.lines)
code = proc.wait()
_check(failures, code == 0, "stream_exec wait() exit code 0")
_check(
failures,
"out-line" in streamed and "err-line" in streamed,
"stream_exec merged stdout and stderr",
)
print("\n[8/8] public egress (outbound HTTPS from inside)")
egress = launcher.run(
sandbox_id,
'python3 -c "import urllib.request as u; '
"print(u.urlopen('https://api.github.com', timeout=15).status)\"",
check=False,
)
_check(failures, "200" in egress.stdout, "outbound HTTPS reached api.github.com")
except Exception as exc:
failures.append(f"FATAL: {type(exc).__name__}: {exc}")
finally:
if sandbox_id is not None and not args.keep:
print("\n[cleanup] terminate (idempotent)")
try:
launcher.terminate(sandbox_id)
# A second terminate of an already-killed sandbox must be a no-op.
launcher.terminate(sandbox_id)
print(f" ✓ terminated {sandbox_id} (and second call was a no-op)")
except Exception as exc:
print(f" WARNING: cleanup failed for {sandbox_id}: {exc}")
elif sandbox_id is not None:
print(f"\n[cleanup] --keep set; leaving {sandbox_id} running")
print("\n" + "=" * 60)
if failures:
print("SMOKE TEST FAILED:")
for f in failures:
print(f"{f}")
return 1
print("SMOKE TEST PASSED — every E2B launcher primitive works against a live sandbox.")
return 0
if __name__ == "__main__":
raise SystemExit(main())