diff --git a/brev/welcome-ui/server.py b/brev/welcome-ui/server.py index a18f1ee..90afc80 100644 --- a/brev/welcome-ui/server.py +++ b/brev/welcome-ui/server.py @@ -20,7 +20,7 @@ REPO_ROOT = os.environ.get("REPO_ROOT", os.path.join(ROOT, "..", "..")) SANDBOX_DIR = os.path.join(REPO_ROOT, "sandboxes", "nemoclaw") NEMOCLAW_IMAGE = "ghcr.io/nvidia/nemoclaw-community/sandboxes/nemoclaw:local" -POLICY_FILE = os.path.join(SANDBOX_DIR, "policy.yaml") +# POLICY_FILE = os.path.join(SANDBOX_DIR, "policy.yaml") LOG_FILE = "/tmp/nemoclaw-sandbox-create.log" BREV_ENV_ID = os.environ.get("BREV_ENV_ID", "") @@ -114,7 +114,7 @@ def _cleanup_existing_sandbox(): pass -def _run_sandbox_create(brev_ui_url: str): +def _run_sandbox_create(): """Background thread: runs nemoclaw sandbox create and monitors until ready.""" global _sandbox_state @@ -125,6 +125,8 @@ def _run_sandbox_create(brev_ui_url: str): _cleanup_existing_sandbox() + chat_ui_url = _build_openclaw_url(token=None) + env = os.environ.copy() # Use `env` to inject vars into the sandbox command. Avoids the # nemoclaw -e flag which has a quoting bug that causes SSH to @@ -135,11 +137,10 @@ def _run_sandbox_create(brev_ui_url: str): "nemoclaw", "sandbox", "create", "--name", "nemoclaw", "--from", NEMOCLAW_IMAGE, - "--policy", POLICY_FILE, "--forward", "18789", "--", "env", - f"BREV_UI_URL={brev_ui_url}", + f"CHAT_UI_URL={chat_ui_url}", "nemoclaw-start", ] @@ -264,11 +265,10 @@ def _handle_install_openclaw(self): "error": "Sandbox is already running", }) - brev_ui_url = f"http://{self.headers.get('Host', 'localhost:8080')}" + _maybe_detect_brev_id(self.headers.get("Host", "")) thread = threading.Thread( target=_run_sandbox_create, - args=(brev_ui_url,), daemon=True, ) thread.start() diff --git a/sandboxes/nemoclaw/README.md b/sandboxes/nemoclaw/README.md index b540b4b..3fde1df 100644 --- a/sandboxes/nemoclaw/README.md +++ b/sandboxes/nemoclaw/README.md @@ -28,11 +28,21 @@ docker build -t nemoclaw sandboxes/nemoclaw/ ```bash nemoclaw sandbox create --from sandboxes/nemoclaw \ --forward 18789 \ - -- nemoclaw-start + -- env CHAT_UI_URL=http://127.0.0.1:18789 \ + nemoclaw-start ``` The `--from ` flag builds the image and imports it into the cluster automatically. +`CHAT_UI_URL` is the URL where the chat UI will be accessed. The origin is +added to `allowedOrigins` so the browser can authenticate without the slow +device-pairing fallback. Examples: + +| Environment | `CHAT_UI_URL` | +|---|---| +| Local | `http://127.0.0.1:18789` | +| Brev | `https://187890-.brevlab.com` | + `nemoclaw-start` then: 1. Substitutes `__NVIDIA_*_API_KEY__` placeholders in the bundled JS with runtime environment variables (if provided) diff --git a/sandboxes/nemoclaw/nemoclaw-start.sh b/sandboxes/nemoclaw/nemoclaw-start.sh index 8763aad..74ad006 100644 --- a/sandboxes/nemoclaw/nemoclaw-start.sh +++ b/sandboxes/nemoclaw/nemoclaw-start.sh @@ -10,14 +10,20 @@ # placeholder API keys. At startup this script substitutes the real keys from # environment variables into the bundled JS, then launches the gateway. # -# Required env vars (for NVIDIA model endpoints): +# Required env vars: +# CHAT_UI_URL — URL where the chat UI will be accessed +# (e.g. http://127.0.0.1:18789 for local, +# https://187890-.brevlab.com for Brev) +# +# Optional env vars (for NVIDIA model endpoints): # NVIDIA_INFERENCE_API_KEY — key for inference-api.nvidia.com # NVIDIA_INTEGRATE_API_KEY — key for integrate.api.nvidia.com # # Usage (env vars inlined via env command to avoid nemoclaw -e quoting bug): # nemoclaw sandbox create --name nemoclaw --from sandboxes/nemoclaw/ \ # --forward 18789 \ -# -- env NVIDIA_INFERENCE_API_KEY= \ +# -- env CHAT_UI_URL=http://127.0.0.1:18789 \ +# NVIDIA_INFERENCE_API_KEY= \ # NVIDIA_INTEGRATE_API_KEY= \ # nemoclaw-start set -euo pipefail @@ -75,25 +81,27 @@ export NVIDIA_API_KEY=" " GATEWAY_PORT=18789 -# Derive the Brev environment ID so we can build the correct gateway origin. -# BREV_UI_URL (if set) points at the *welcome UI* port, not the gateway port, -# so we must always compute the gateway origin separately. -if [ -z "${BREV_ENV_ID:-}" ] && [ -n "${BREV_UI_URL:-}" ]; then - BREV_ENV_ID=$(echo "$BREV_UI_URL" | sed -n 's|.*//[0-9]*-\([^.]*\)\.brevlab\.com.*|\1|p') -fi - -if [ -n "${BREV_ENV_ID:-}" ]; then - export OPENCLAW_ORIGIN="https://${GATEWAY_PORT}0-${BREV_ENV_ID}.brevlab.com" -else - export OPENCLAW_ORIGIN="http://127.0.0.1:${GATEWAY_PORT}" +if [ -z "${CHAT_UI_URL:-}" ]; then + echo "Error: CHAT_UI_URL environment variable is required." >&2 + echo "Set it to the URL where the chat UI will be accessed, e.g.:" >&2 + echo " Local: CHAT_UI_URL=http://127.0.0.1:18789" >&2 + echo " Brev: CHAT_UI_URL=https://187890-.brevlab.com" >&2 + exit 1 fi python3 -c " import json, os +from urllib.parse import urlparse cfg = json.load(open(os.environ['HOME'] + '/.openclaw/openclaw.json')) +local = 'http://127.0.0.1:${GATEWAY_PORT}' +parsed = urlparse(os.environ['CHAT_UI_URL']) +chat_origin = f'{parsed.scheme}://{parsed.netloc}' +origins = [local] +if chat_origin != local: + origins.append(chat_origin) cfg['gateway']['controlUi'] = { 'allowInsecureAuth': True, - 'allowedOrigins': [os.environ['OPENCLAW_ORIGIN']] + 'allowedOrigins': origins, } json.dump(cfg, open(os.environ['HOME'] + '/.openclaw/openclaw.json', 'w'), indent=2) " @@ -115,12 +123,20 @@ nohup openclaw gateway > /tmp/gateway.log 2>&1 & CONFIG_FILE="${HOME}/.openclaw/openclaw.json" token=$(grep -o '"token"\s*:\s*"[^"]*"' "${CONFIG_FILE}" 2>/dev/null | head -1 | cut -d'"' -f4 || true) -echo "" -echo "OpenClaw gateway starting in background." -echo " Logs: /tmp/gateway.log" +CHAT_UI_BASE="${CHAT_UI_URL%/}" if [ -n "${token}" ]; then - echo " UI: http://127.0.0.1:18789/?token=${token}" + LOCAL_URL="http://127.0.0.1:18789/?token=${token}" + CHAT_URL="${CHAT_UI_BASE}/?token=${token}" else - echo " UI: http://127.0.0.1:18789/" + LOCAL_URL="http://127.0.0.1:18789/" + CHAT_URL="${CHAT_UI_BASE}/" +fi + +echo "" +echo "OpenClaw gateway starting in background." +echo " Logs: /tmp/gateway.log" +echo " UI: ${CHAT_URL}" +if [ "${CHAT_UI_BASE}" != "http://127.0.0.1:18789" ]; then + echo " Local: ${LOCAL_URL}" fi echo ""