From 3deb7b902cf414fe15b65402dd23449546fd6dc1 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sun, 15 Mar 2026 18:10:04 -0700 Subject: [PATCH 1/7] Bootstrap OpenClaw config inside sandbox Signed-off-by: Vincent Koc --- docs/reference/commands.md | 4 +- nemoclaw/dist/commands/launch.d.ts.map | 2 +- nemoclaw/dist/commands/launch.js | 10 +++ nemoclaw/dist/commands/launch.js.map | 2 +- nemoclaw/dist/commands/sandbox-bootstrap.d.ts | 7 +++ .../dist/commands/sandbox-bootstrap.d.ts.map | 1 + nemoclaw/dist/commands/sandbox-bootstrap.js | 29 +++++++++ .../dist/commands/sandbox-bootstrap.js.map | 1 + nemoclaw/src/commands/launch.ts | 11 ++++ nemoclaw/src/commands/sandbox-bootstrap.ts | 38 ++++++++++++ test/e2e-test.sh | 62 +++++++++++++++++++ 11 files changed, 164 insertions(+), 3 deletions(-) create mode 100644 nemoclaw/dist/commands/sandbox-bootstrap.d.ts create mode 100644 nemoclaw/dist/commands/sandbox-bootstrap.d.ts.map create mode 100644 nemoclaw/dist/commands/sandbox-bootstrap.js create mode 100644 nemoclaw/dist/commands/sandbox-bootstrap.js.map create mode 100644 nemoclaw/src/commands/sandbox-bootstrap.ts diff --git a/docs/reference/commands.md b/docs/reference/commands.md index ed6469e8788..c93c42efcf9 100644 --- a/docs/reference/commands.md +++ b/docs/reference/commands.md @@ -30,6 +30,8 @@ Both interfaces are installed when you run `npm install -g nemoclaw`. ### `openclaw nemoclaw launch` Bootstrap OpenClaw inside an OpenShell sandbox. +After provisioning the sandbox, NemoClaw runs `openclaw setup` inside it so +`openclaw.json`, the default workspace, and session directories exist before first use. If NemoClaw detects an existing host installation, `launch` stops and points you to `openclaw nemoclaw migrate` unless you pass `--force`. ```console @@ -46,7 +48,7 @@ $ openclaw nemoclaw launch [--force] [--profile ] ### `openclaw nemoclaw migrate` Migrate an existing host OpenClaw installation into an OpenShell sandbox. -The command snapshots the resolved OpenClaw state, captures external agent roots referenced by config, preserves symlinks in tar archives, and verifies the migrated paths inside the sandbox. +The command snapshots the resolved OpenClaw state, captures external agent roots referenced by config, preserves symlinks in tar archives, rewrites migrated config paths, and verifies the migrated paths inside the sandbox. ```console $ openclaw nemoclaw migrate [--dry-run] [--profile ] [--skip-backup] diff --git a/nemoclaw/dist/commands/launch.d.ts.map b/nemoclaw/dist/commands/launch.d.ts.map index 093da3aa8e6..ca5c1862d9f 100644 --- a/nemoclaw/dist/commands/launch.d.ts.map +++ b/nemoclaw/dist/commands/launch.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"launch.d.ts","sourceRoot":"","sources":["../../src/commands/launch.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAOhE,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,YAAY,CAAC;IACrB,YAAY,EAAE,cAAc,CAAC;CAC9B;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA2GlE"} \ No newline at end of file +{"version":3,"file":"launch.d.ts","sourceRoot":"","sources":["../../src/commands/launch.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAQhE,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,YAAY,CAAC;IACrB,YAAY,EAAE,cAAc,CAAC;CAC9B;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAqHlE"} \ No newline at end of file diff --git a/nemoclaw/dist/commands/launch.js b/nemoclaw/dist/commands/launch.js index 9e7b8ad947a..10b0ed1a074 100644 --- a/nemoclaw/dist/commands/launch.js +++ b/nemoclaw/dist/commands/launch.js @@ -9,6 +9,7 @@ const verify_js_1 = require("../blueprint/verify.js"); const exec_js_1 = require("../blueprint/exec.js"); const state_js_1 = require("../blueprint/state.js"); const migrate_js_1 = require("./migrate.js"); +const sandbox_bootstrap_js_1 = require("./sandbox-bootstrap.js"); async function cliLaunch(opts) { const { force, profile, logger, pluginConfig } = opts; logger.info("NemoClaw launch: setting up OpenClaw inside OpenShell"); @@ -75,6 +76,15 @@ async function cliLaunch(opts) { logger.error(`Blueprint apply failed: ${applyResult.output}`); return; } + logger.info("Initializing OpenClaw inside the sandbox..."); + const initialized = (0, sandbox_bootstrap_js_1.ensureSandboxOpenClawSetup)({ + sandboxName: pluginConfig.sandboxName, + logger, + }); + if (!initialized) { + logger.error("Sandbox bootstrap failed before OpenClaw could create its initial config."); + return; + } // Save state (0, state_js_1.saveState)({ ...(0, state_js_1.loadState)(), diff --git a/nemoclaw/dist/commands/launch.js.map b/nemoclaw/dist/commands/launch.js.map index 5427afe9dc0..540b53de3c6 100644 --- a/nemoclaw/dist/commands/launch.js.map +++ b/nemoclaw/dist/commands/launch.js.map @@ -1 +1 @@ -{"version":3,"file":"launch.js","sourceRoot":"","sources":["../../src/commands/launch.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"launch.js","sourceRoot":"","sources":["../../src/commands/launch.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/nemoclaw/dist/commands/sandbox-bootstrap.d.ts b/nemoclaw/dist/commands/sandbox-bootstrap.d.ts new file mode 100644 index 00000000000..e488280719a --- /dev/null +++ b/nemoclaw/dist/commands/sandbox-bootstrap.d.ts @@ -0,0 +1,7 @@ +import type { PluginLogger } from "../index.js"; +export interface EnsureSandboxOpenClawSetupOptions { + sandboxName: string; + logger: PluginLogger; +} +export declare function ensureSandboxOpenClawSetup(opts: EnsureSandboxOpenClawSetupOptions): boolean; +//# sourceMappingURL=sandbox-bootstrap.d.ts.map \ No newline at end of file diff --git a/nemoclaw/dist/commands/sandbox-bootstrap.d.ts.map b/nemoclaw/dist/commands/sandbox-bootstrap.d.ts.map new file mode 100644 index 00000000000..ec8b97fb1a8 --- /dev/null +++ b/nemoclaw/dist/commands/sandbox-bootstrap.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"sandbox-bootstrap.d.ts","sourceRoot":"","sources":["../../src/commands/sandbox-bootstrap.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,iCAAiC;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,YAAY,CAAC;CACtB;AAED,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,iCAAiC,GACtC,OAAO,CAwBT"} \ No newline at end of file diff --git a/nemoclaw/dist/commands/sandbox-bootstrap.js b/nemoclaw/dist/commands/sandbox-bootstrap.js new file mode 100644 index 00000000000..5e8b9ddbe3e --- /dev/null +++ b/nemoclaw/dist/commands/sandbox-bootstrap.js @@ -0,0 +1,29 @@ +"use strict"; +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ensureSandboxOpenClawSetup = ensureSandboxOpenClawSetup; +const node_child_process_1 = require("node:child_process"); +function ensureSandboxOpenClawSetup(opts) { + const { sandboxName, logger } = opts; + try { + (0, node_child_process_1.execFileSync)("openshell", ["sandbox", "connect", sandboxName, "--", "openclaw", "setup"], { + encoding: "utf-8", + stdio: ["ignore", "pipe", "pipe"], + }); + logger.info("Initialized OpenClaw config and workspace inside the sandbox."); + return true; + } + catch (err) { + const stderr = err && + typeof err === "object" && + "stderr" in err && + typeof err.stderr === "string" + ? err.stderr.trim() + : ""; + logger.error(`Failed to initialize OpenClaw inside the sandbox: ${stderr || String(err)}`); + logger.info(`After resolving the issue, run 'openshell sandbox connect ${sandboxName} -- openclaw setup'.`); + return false; + } +} +//# sourceMappingURL=sandbox-bootstrap.js.map \ No newline at end of file diff --git a/nemoclaw/dist/commands/sandbox-bootstrap.js.map b/nemoclaw/dist/commands/sandbox-bootstrap.js.map new file mode 100644 index 00000000000..dde33088bf2 --- /dev/null +++ b/nemoclaw/dist/commands/sandbox-bootstrap.js.map @@ -0,0 +1 @@ +{"version":3,"file":"sandbox-bootstrap.js","sourceRoot":"","sources":["../../src/commands/sandbox-bootstrap.ts"],"names":[],"mappings":";AAAA,mGAAmG;AACnG,sCAAsC;;AAUtC,gEA0BC;AAlCD,2DAAkD;AAQlD,SAAgB,0BAA0B,CACxC,IAAuC;IAEvC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAErC,IAAI,CAAC;QACH,IAAA,iCAAY,EAAC,WAAW,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE;YACxF,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;SAClC,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,+DAA+D,CAAC,CAAC;QAC7E,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,MAAM,GACV,GAAG;YACH,OAAO,GAAG,KAAK,QAAQ;YACvB,QAAQ,IAAI,GAAG;YACf,OAAQ,GAA4B,CAAC,MAAM,KAAK,QAAQ;YACtD,CAAC,CAAE,GAA0B,CAAC,MAAM,CAAC,IAAI,EAAE;YAC3C,CAAC,CAAC,EAAE,CAAC;QACT,MAAM,CAAC,KAAK,CAAC,qDAAqD,MAAM,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC3F,MAAM,CAAC,IAAI,CACT,6DAA6D,WAAW,sBAAsB,CAC/F,CAAC;QACF,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/nemoclaw/src/commands/launch.ts b/nemoclaw/src/commands/launch.ts index ee08e96bf8b..2bdbae31e8a 100644 --- a/nemoclaw/src/commands/launch.ts +++ b/nemoclaw/src/commands/launch.ts @@ -8,6 +8,7 @@ import { verifyBlueprintDigest, checkCompatibility } from "../blueprint/verify.j import { execBlueprint } from "../blueprint/exec.js"; import { loadState, saveState } from "../blueprint/state.js"; import { detectHostOpenClaw } from "./migrate.js"; +import { ensureSandboxOpenClawSetup } from "./sandbox-bootstrap.js"; export interface LaunchOptions { force: boolean; @@ -106,6 +107,16 @@ export async function cliLaunch(opts: LaunchOptions): Promise { return; } + logger.info("Initializing OpenClaw inside the sandbox..."); + const initialized = ensureSandboxOpenClawSetup({ + sandboxName: pluginConfig.sandboxName, + logger, + }); + if (!initialized) { + logger.error("Sandbox bootstrap failed before OpenClaw could create its initial config."); + return; + } + // Save state saveState({ ...loadState(), diff --git a/nemoclaw/src/commands/sandbox-bootstrap.ts b/nemoclaw/src/commands/sandbox-bootstrap.ts new file mode 100644 index 00000000000..296bec8d213 --- /dev/null +++ b/nemoclaw/src/commands/sandbox-bootstrap.ts @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { execFileSync } from "node:child_process"; +import type { PluginLogger } from "../index.js"; + +export interface EnsureSandboxOpenClawSetupOptions { + sandboxName: string; + logger: PluginLogger; +} + +export function ensureSandboxOpenClawSetup( + opts: EnsureSandboxOpenClawSetupOptions, +): boolean { + const { sandboxName, logger } = opts; + + try { + execFileSync("openshell", ["sandbox", "connect", sandboxName, "--", "openclaw", "setup"], { + encoding: "utf-8", + stdio: ["ignore", "pipe", "pipe"], + }); + logger.info("Initialized OpenClaw config and workspace inside the sandbox."); + return true; + } catch (err: unknown) { + const stderr = + err && + typeof err === "object" && + "stderr" in err && + typeof (err as { stderr?: unknown }).stderr === "string" + ? (err as { stderr: string }).stderr.trim() + : ""; + logger.error(`Failed to initialize OpenClaw inside the sandbox: ${stderr || String(err)}`); + logger.info( + `After resolving the issue, run 'openshell sandbox connect ${sandboxName} -- openclaw setup'.`, + ); + return false; + } +} diff --git a/test/e2e-test.sh b/test/e2e-test.sh index 39cd467821b..5599898846e 100755 --- a/test/e2e-test.sh +++ b/test/e2e-test.sh @@ -249,6 +249,68 @@ console.assert(state.lastAction === null, 'Should be cleared'); console.log('State management: create, save, load, clear all working'); " && pass "NemoClaw state management works" || fail "State management broken" +# ------------------------------------------------------- +info "10. Verify sandbox bootstrap creates openclaw.json" +# ------------------------------------------------------- +mkdir -p /tmp/fake-bin /tmp/fake-sandbox +cat > /tmp/fake-bin/openshell <<'EOF' +#!/usr/bin/env bash +set -euo pipefail + +root="${FAKE_SANDBOX_ROOT:?}" +printf '%s\n' "$*" > "${root}/invocation.txt" + +if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "openclaw" ] && [ "$6" = "setup" ]; then + sandbox_root="${root}/$3/.openclaw" + mkdir -p "${sandbox_root}/workspace" "${sandbox_root}/sessions" + cat > "${sandbox_root}/openclaw.json" <<'JSON' +{ + "agents": { + "defaults": { + "workspace": "/sandbox/.openclaw/workspace" + } + }, + "gateway": { + "mode": "local" + } +} +JSON + exit 0 +fi + +echo "unexpected openshell invocation: $*" >&2 +exit 1 +EOF +chmod +x /tmp/fake-bin/openshell + +PATH="/tmp/fake-bin:$PATH" FAKE_SANDBOX_ROOT=/tmp/fake-sandbox node - <<'EOF' +const { ensureSandboxOpenClawSetup } = require('/opt/nemoclaw/dist/commands/sandbox-bootstrap.js'); + +const logger = { + info() {}, + warn() {}, + error(message) { + throw new Error(message); + }, + debug() {}, +}; + +const ok = ensureSandboxOpenClawSetup({ sandboxName: 'openclaw', logger }); +if (!ok) { + throw new Error('bootstrap helper returned false'); +} +EOF + +grep -q '^sandbox connect openclaw -- openclaw setup$' /tmp/fake-sandbox/invocation.txt \ + && pass "Sandbox bootstrap calls openclaw setup" \ + || fail "Sandbox bootstrap did not run openclaw setup" +[ -f /tmp/fake-sandbox/openclaw/.openclaw/openclaw.json ] \ + && pass "Sandbox bootstrap created openclaw.json" \ + || fail "Sandbox bootstrap did not create openclaw.json" +[ -d /tmp/fake-sandbox/openclaw/.openclaw/workspace ] \ + && pass "Sandbox bootstrap created workspace" \ + || fail "Sandbox bootstrap did not create workspace" + echo "" echo -e "${GREEN}========================================${NC}" echo -e "${GREEN} ALL E2E TESTS PASSED${NC}" From ab26163180a3661450238692f24c6b6deeaad79c Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sun, 15 Mar 2026 21:38:15 -0700 Subject: [PATCH 2/7] Test launch bootstrap through cliLaunch Signed-off-by: Vincent Koc --- test/e2e-test.sh | 100 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 86 insertions(+), 14 deletions(-) diff --git a/test/e2e-test.sh b/test/e2e-test.sh index 5599898846e..e3758fbb219 100755 --- a/test/e2e-test.sh +++ b/test/e2e-test.sh @@ -250,15 +250,35 @@ console.log('State management: create, save, load, clear all working'); " && pass "NemoClaw state management works" || fail "State management broken" # ------------------------------------------------------- -info "10. Verify sandbox bootstrap creates openclaw.json" +info "11. Verify launch bootstraps openclaw.json in the sandbox" # ------------------------------------------------------- -mkdir -p /tmp/fake-bin /tmp/fake-sandbox +rm -rf /tmp/fake-bin /tmp/fake-sandbox /tmp/fake-home +mkdir -p /tmp/fake-bin /tmp/fake-sandbox /tmp/fake-home + cat > /tmp/fake-bin/openshell <<'EOF' #!/usr/bin/env bash set -euo pipefail root="${FAKE_SANDBOX_ROOT:?}" -printf '%s\n' "$*" > "${root}/invocation.txt" +printf '%s\n' "$*" >> "${root}/invocation.txt" + +if [ "$1" = "--version" ]; then + echo "0.1.0" + exit 0 +fi + +if [ "$1" = "sandbox" ] && [ "$2" = "create" ]; then + mkdir -p "${root}/openclaw" + exit 0 +fi + +if [ "$1" = "provider" ] && [ "$2" = "create" ]; then + exit 0 +fi + +if [ "$1" = "inference" ] && [ "$2" = "set" ]; then + exit 0 +fi if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "openclaw" ] && [ "$6" = "setup" ]; then sandbox_root="${root}/$3/.openclaw" @@ -283,8 +303,36 @@ exit 1 EOF chmod +x /tmp/fake-bin/openshell -PATH="/tmp/fake-bin:$PATH" FAKE_SANDBOX_ROOT=/tmp/fake-sandbox node - <<'EOF' -const { ensureSandboxOpenClawSetup } = require('/opt/nemoclaw/dist/commands/sandbox-bootstrap.js'); +cat > /tmp/fake-bin/openclaw <<'EOF' +#!/usr/bin/env bash +set -euo pipefail + +if [ "$1" = "--version" ]; then + echo "2026.3.11" + exit 0 +fi + +echo "unexpected openclaw invocation: $*" >&2 +exit 1 +EOF +chmod +x /tmp/fake-bin/openclaw + +PATH="/tmp/fake-bin:$PATH" FAKE_SANDBOX_ROOT=/tmp/fake-sandbox HOME=/tmp/fake-home node - <<'EOF' +const fs = require('node:fs'); +const resolveModule = require('/opt/nemoclaw/dist/blueprint/resolve.js'); +resolveModule.resolveBlueprint = async () => ({ + version: '0.1.0', + localPath: '/sandbox/.nemoclaw/blueprints/0.1.0', + manifest: { + version: '0.1.0', + minOpenShellVersion: '0.1.0', + minOpenClawVersion: '2026.3.0', + profiles: ['default'], + digest: '', + }, + cached: true, +}); +const { cliLaunch } = require('/opt/nemoclaw/dist/commands/launch.js'); const logger = { info() {}, @@ -295,21 +343,45 @@ const logger = { debug() {}, }; -const ok = ensureSandboxOpenClawSetup({ sandboxName: 'openclaw', logger }); -if (!ok) { - throw new Error('bootstrap helper returned false'); +async function main() { + await cliLaunch({ + force: true, + profile: 'default', + logger, + pluginConfig: { + blueprintVersion: '0.1.0', + blueprintRegistry: 'ghcr.io/nvidia/nemoclaw-blueprint', + sandboxName: 'openclaw', + inferenceProvider: 'nvidia', + }, + }); + + const state = JSON.parse( + fs.readFileSync('/tmp/fake-home/.nemoclaw/state/nemoclaw.json', 'utf8'), + ); + if (state.lastAction !== 'launch') { + throw new Error(`Unexpected lastAction: ${state.lastAction}`); + } + if (state.sandboxName !== 'openclaw') { + throw new Error(`Unexpected sandboxName: ${state.sandboxName}`); + } } + +main().catch((error) => { + console.error(error); + process.exit(1); +}); EOF grep -q '^sandbox connect openclaw -- openclaw setup$' /tmp/fake-sandbox/invocation.txt \ - && pass "Sandbox bootstrap calls openclaw setup" \ - || fail "Sandbox bootstrap did not run openclaw setup" + && pass "Launch bootstraps OpenClaw with openclaw setup" \ + || fail "Launch did not run openclaw setup" [ -f /tmp/fake-sandbox/openclaw/.openclaw/openclaw.json ] \ - && pass "Sandbox bootstrap created openclaw.json" \ - || fail "Sandbox bootstrap did not create openclaw.json" + && pass "Launch created openclaw.json" \ + || fail "Launch did not create openclaw.json" [ -d /tmp/fake-sandbox/openclaw/.openclaw/workspace ] \ - && pass "Sandbox bootstrap created workspace" \ - || fail "Sandbox bootstrap did not create workspace" + && pass "Launch created workspace" \ + || fail "Launch did not create workspace" echo "" echo -e "${GREEN}========================================${NC}" From d5fec8dc21eff959137bfa12b827f014447df409 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sun, 15 Mar 2026 22:23:49 -0700 Subject: [PATCH 3/7] Bootstrap: support headless sandbox gateway setup Signed-off-by: Vincent Koc --- Dockerfile | 1 + README.md | 5 + docs/reference/commands.md | 20 +- nemoclaw/dist/commands/launch.js | 8 +- nemoclaw/dist/commands/launch.js.map | 2 +- nemoclaw/dist/commands/migrate.d.ts.map | 2 +- nemoclaw/dist/commands/migrate.js | 11 + nemoclaw/dist/commands/migrate.js.map | 2 +- nemoclaw/dist/commands/sandbox-bootstrap.d.ts | 4 +- .../dist/commands/sandbox-bootstrap.d.ts.map | 2 +- nemoclaw/dist/commands/sandbox-bootstrap.js | 145 +++++- .../dist/commands/sandbox-bootstrap.js.map | 2 +- nemoclaw/src/commands/launch.ts | 10 +- nemoclaw/src/commands/migrate.ts | 14 + nemoclaw/src/commands/sandbox-bootstrap.ts | 194 +++++++- test/Dockerfile.sandbox | 1 + test/e2e-test.sh | 419 +++++++++++++++++- 17 files changed, 793 insertions(+), 49 deletions(-) diff --git a/Dockerfile b/Dockerfile index 769614d1ded..2c7a9771893 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,6 +7,7 @@ ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y --no-install-recommends \ python3 python3-pip python3-venv \ curl git ca-certificates \ + dbus dbus-user-session systemd \ iproute2 \ && rm -rf /var/lib/apt/lists/* diff --git a/README.md b/README.md index e73081a9637..6c9ee2f8a0b 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,11 @@ First run prompts for your NVIDIA API Key (get one from [build.nvidia.com](https - Docker - [OpenShell CLI](https://github.com/NVIDIA/OpenShell/releases) (binary download) +The repo-owned sandbox image installs `systemd` and `dbus-user-session` so +OpenClaw's managed Gateway install can work when the runtime supports +user-systemd. NemoClaw still falls back to a direct background Gateway process +for headless/container sessions where `systemctl --user` is unavailable. + ### Ubuntu 24.04 (fresh install) > **Minimum 8GB RAM** — the sandbox image is ~1.5 GiB and will OOM-kill on 4GB VMs. diff --git a/docs/reference/commands.md b/docs/reference/commands.md index c93c42efcf9..de5f69511b8 100644 --- a/docs/reference/commands.md +++ b/docs/reference/commands.md @@ -29,10 +29,15 @@ Both interfaces are installed when you run `npm install -g nemoclaw`. ### `openclaw nemoclaw launch` -Bootstrap OpenClaw inside an OpenShell sandbox. -After provisioning the sandbox, NemoClaw runs `openclaw setup` inside it so -`openclaw.json`, the default workspace, and session directories exist before first use. -If NemoClaw detects an existing host installation, `launch` stops and points you to `openclaw nemoclaw migrate` unless you pass `--force`. +Bootstrap a fresh OpenClaw installation inside an OpenShell sandbox. +After provisioning the sandbox, NemoClaw runs `openclaw setup` and +`openclaw gateway install` inside it so the config, workspace, sessions, +gateway auth token, and managed service all exist before first use. +If NemoClaw detects an existing host installation, `launch` stops and points you +to `openclaw nemoclaw migrate` unless you pass `--force`. +If Linux user-systemd is unavailable inside the sandbox, NemoClaw falls back +to a direct background `openclaw gateway run --force` start so headless +bootstrap still completes. ```console $ openclaw nemoclaw launch [--force] [--profile ] @@ -48,7 +53,12 @@ $ openclaw nemoclaw launch [--force] [--profile ] ### `openclaw nemoclaw migrate` Migrate an existing host OpenClaw installation into an OpenShell sandbox. -The command snapshots the resolved OpenClaw state, captures external agent roots referenced by config, preserves symlinks in tar archives, rewrites migrated config paths, and verifies the migrated paths inside the sandbox. +The command snapshots the resolved OpenClaw state, captures external agent roots +referenced by config, preserves symlinks in tar archives, rewrites migrated +config paths, verifies the migrated paths inside the sandbox, and then re-runs +the same headless bootstrap so migrated installs also have a ready gateway +token and Gateway runtime even when the sandbox cannot host a user-systemd +service. ```console $ openclaw nemoclaw migrate [--dry-run] [--profile ] [--skip-backup] diff --git a/nemoclaw/dist/commands/launch.js b/nemoclaw/dist/commands/launch.js index 10b0ed1a074..b50522ac2df 100644 --- a/nemoclaw/dist/commands/launch.js +++ b/nemoclaw/dist/commands/launch.js @@ -76,13 +76,13 @@ async function cliLaunch(opts) { logger.error(`Blueprint apply failed: ${applyResult.output}`); return; } - logger.info("Initializing OpenClaw inside the sandbox..."); - const initialized = (0, sandbox_bootstrap_js_1.ensureSandboxOpenClawSetup)({ + logger.info("Bootstrapping OpenClaw inside the sandbox..."); + const bootstrapped = (0, sandbox_bootstrap_js_1.ensureSandboxOpenClawBootstrap)({ sandboxName: pluginConfig.sandboxName, logger, }); - if (!initialized) { - logger.error("Sandbox bootstrap failed before OpenClaw could create its initial config."); + if (!bootstrapped) { + logger.error("Sandbox bootstrap failed before OpenClaw became ready for headless use."); return; } // Save state diff --git a/nemoclaw/dist/commands/launch.js.map b/nemoclaw/dist/commands/launch.js.map index 540b53de3c6..ad478600758 100644 --- a/nemoclaw/dist/commands/launch.js.map +++ b/nemoclaw/dist/commands/launch.js.map @@ -1 +1 @@ -{"version":3,"file":"launch.js","sourceRoot":"","sources":["../../src/commands/launch.ts"],"names":[],"mappings":";AAAA,mGAAmG;AACnG,sCAAsC;;AAkBtC,8BAqHC;AArID,2DAA8C;AAE9C,wDAA2D;AAC3D,sDAAmF;AACnF,kDAAqD;AACrD,oDAA6D;AAC7D,6CAAkD;AAClD,iEAAoE;AAS7D,KAAK,UAAU,SAAS,CAAC,IAAmB;IACjD,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;IAEtD,MAAM,CAAC,IAAI,CAAC,uDAAuD,CAAC,CAAC;IAErE,0DAA0D;IAC1D,MAAM,SAAS,GAAG,IAAA,+BAAkB,GAAE,CAAC;IAEvC,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QAChC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChB,MAAM,CAAC,IAAI,CAAC,0DAA0D,CAAC,CAAC;QACxE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChB,MAAM,CAAC,IAAI,CAAC,oEAAoE,CAAC,CAAC;QAClF,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChB,MAAM,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC;QAC1E,MAAM,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;QACpD,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChB,MAAM,CAAC,IAAI,CACT,mFAAmF,CACpF,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChB,MAAM,CAAC,IAAI,CAAC,gEAAgE,CAAC,CAAC;QAC9E,OAAO;IACT,CAAC;IAED,IAAI,SAAS,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QAC/B,MAAM,CAAC,IAAI,CACT,8FAA8F,CAC/F,CAAC;QACF,MAAM,CAAC,IAAI,CACT,oFAAoF,CACrF,CAAC;QACF,OAAO;IACT,CAAC;IAED,+BAA+B;IAC/B,MAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IACtC,MAAM,SAAS,GAAG,MAAM,IAAA,6BAAgB,EAAC,YAAY,CAAC,CAAC;IAEvD,MAAM,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;IAChD,MAAM,YAAY,GAAG,IAAA,iCAAqB,EAAC,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;IACpF,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;QACxB,MAAM,CAAC,KAAK,CAAC,kCAAkC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjF,OAAO;IACT,CAAC;IAED,8BAA8B;IAC9B,MAAM,gBAAgB,GAAG,mBAAmB,EAAE,CAAC;IAC/C,MAAM,eAAe,GAAG,kBAAkB,EAAE,CAAC;IAC7C,MAAM,MAAM,GAAG,IAAA,8BAAkB,EAAC,SAAS,CAAC,QAAQ,EAAE,gBAAgB,EAAE,eAAe,CAAC,CAAC;IACzF,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,CAAC,KAAK,CAAC,kCAAkC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACtE,OAAO;IACT,CAAC;IAED,OAAO;IACP,MAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IACtC,MAAM,UAAU,GAAG,MAAM,IAAA,uBAAa,EACpC;QACE,aAAa,EAAE,SAAS,CAAC,SAAS;QAClC,MAAM,EAAE,MAAM;QACd,OAAO;QACP,UAAU,EAAE,IAAI;KACjB,EACD,MAAM,CACP,CAAC;IAEF,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;QACxB,MAAM,CAAC,KAAK,CAAC,0BAA0B,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;QAC5D,OAAO;IACT,CAAC;IAED,QAAQ;IACR,MAAM,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;IAC7C,MAAM,WAAW,GAAG,MAAM,IAAA,uBAAa,EACrC;QACE,aAAa,EAAE,SAAS,CAAC,SAAS;QAClC,MAAM,EAAE,OAAO;QACf,OAAO;QACP,QAAQ,EAAE,UAAU,CAAC,KAAK;QAC1B,UAAU,EAAE,IAAI;KACjB,EACD,MAAM,CACP,CAAC;IAEF,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;QACzB,MAAM,CAAC,KAAK,CAAC,2BAA2B,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC;QAC9D,OAAO;IACT,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;IAC3D,MAAM,WAAW,GAAG,IAAA,iDAA0B,EAAC;QAC7C,WAAW,EAAE,YAAY,CAAC,WAAW;QACrC,MAAM;KACP,CAAC,CAAC;IACH,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,CAAC,KAAK,CAAC,2EAA2E,CAAC,CAAC;QAC1F,OAAO;IACT,CAAC;IAED,aAAa;IACb,IAAA,oBAAS,EAAC;QACR,GAAG,IAAA,oBAAS,GAAE;QACd,SAAS,EAAE,WAAW,CAAC,KAAK;QAC5B,UAAU,EAAE,QAAQ;QACpB,gBAAgB,EAAE,SAAS,CAAC,OAAO;QACnC,WAAW,EAAE,YAAY,CAAC,WAAW;KACtC,CAAC,CAAC;IAEH,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChB,MAAM,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;IACzD,MAAM,CAAC,IAAI,CAAC,YAAY,YAAY,CAAC,WAAW,EAAE,CAAC,CAAC;IACpD,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChB,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC3B,MAAM,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAC;IAClE,MAAM,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC;IAC7D,MAAM,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAC;AACzE,CAAC;AAED,SAAS,mBAAmB;IAC1B,IAAI,CAAC;QACH,OAAO,IAAA,6BAAQ,EAAC,qBAAqB,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACvE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB;IACzB,IAAI,CAAC;QACH,OAAO,IAAA,6BAAQ,EAAC,oBAAoB,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACtE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC"} \ No newline at end of file +{"version":3,"file":"launch.js","sourceRoot":"","sources":["../../src/commands/launch.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/nemoclaw/dist/commands/migrate.d.ts.map b/nemoclaw/dist/commands/migrate.d.ts.map index 5906ff25086..5a427ece3cd 100644 --- a/nemoclaw/dist/commands/migrate.d.ts.map +++ b/nemoclaw/dist/commands/migrate.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAchE,OAAO,EAAE,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAIlF,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,YAAY,CAAC;IACrB,YAAY,EAAE,cAAc,CAAC;CAC9B;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAqJpE"} \ No newline at end of file +{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAehE,OAAO,EAAE,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAIlF,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,YAAY,CAAC;IACrB,YAAY,EAAE,cAAc,CAAC;CAC9B;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAkKpE"} \ No newline at end of file diff --git a/nemoclaw/dist/commands/migrate.js b/nemoclaw/dist/commands/migrate.js index e614cb1e13c..3f67a08b63b 100644 --- a/nemoclaw/dist/commands/migrate.js +++ b/nemoclaw/dist/commands/migrate.js @@ -11,6 +11,7 @@ const verify_js_1 = require("../blueprint/verify.js"); const exec_js_1 = require("../blueprint/exec.js"); const state_js_1 = require("../blueprint/state.js"); const migration_state_js_1 = require("./migration-state.js"); +const sandbox_bootstrap_js_1 = require("./sandbox-bootstrap.js"); var migration_state_js_2 = require("./migration-state.js"); Object.defineProperty(exports, "detectHostOpenClaw", { enumerable: true, get: function () { return migration_state_js_2.detectHostOpenClaw; } }); const SANDBOX_ARCHIVE_DIR = "/sandbox/.nemoclaw/migration/archives"; @@ -114,6 +115,16 @@ async function cliMigrate(opts) { syncSnapshotBundleIntoSandbox(bundle, pluginConfig.sandboxName); logger.info("Verifying sandbox migration..."); verifySandboxMigration(bundle, pluginConfig.sandboxName); + logger.info("Bootstrapping sandbox OpenClaw services..."); + const bootstrapped = (0, sandbox_bootstrap_js_1.ensureSandboxOpenClawBootstrap)({ + sandboxName: pluginConfig.sandboxName, + logger, + }); + if (!bootstrapped) { + logger.error("Sandbox bootstrap failed after migration sync."); + logger.info("Your host installation is unchanged. Resolve the sandbox issue and rerun migrate."); + return; + } (0, state_js_1.saveState)({ ...(0, state_js_1.loadState)(), lastRunId: applyResult.runId, diff --git a/nemoclaw/dist/commands/migrate.js.map b/nemoclaw/dist/commands/migrate.js.map index 403f2e6213b..88d033ccccd 100644 --- a/nemoclaw/dist/commands/migrate.js.map +++ b/nemoclaw/dist/commands/migrate.js.map @@ -1 +1 @@ -{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/nemoclaw/dist/commands/sandbox-bootstrap.d.ts b/nemoclaw/dist/commands/sandbox-bootstrap.d.ts index e488280719a..d69aac79118 100644 --- a/nemoclaw/dist/commands/sandbox-bootstrap.d.ts +++ b/nemoclaw/dist/commands/sandbox-bootstrap.d.ts @@ -1,7 +1,7 @@ import type { PluginLogger } from "../index.js"; -export interface EnsureSandboxOpenClawSetupOptions { +export interface EnsureSandboxOpenClawBootstrapOptions { sandboxName: string; logger: PluginLogger; } -export declare function ensureSandboxOpenClawSetup(opts: EnsureSandboxOpenClawSetupOptions): boolean; +export declare function ensureSandboxOpenClawBootstrap(opts: EnsureSandboxOpenClawBootstrapOptions): boolean; //# sourceMappingURL=sandbox-bootstrap.d.ts.map \ No newline at end of file diff --git a/nemoclaw/dist/commands/sandbox-bootstrap.d.ts.map b/nemoclaw/dist/commands/sandbox-bootstrap.d.ts.map index ec8b97fb1a8..4e96048b882 100644 --- a/nemoclaw/dist/commands/sandbox-bootstrap.d.ts.map +++ b/nemoclaw/dist/commands/sandbox-bootstrap.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"sandbox-bootstrap.d.ts","sourceRoot":"","sources":["../../src/commands/sandbox-bootstrap.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,iCAAiC;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,YAAY,CAAC;CACtB;AAED,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,iCAAiC,GACtC,OAAO,CAwBT"} \ No newline at end of file +{"version":3,"file":"sandbox-bootstrap.d.ts","sourceRoot":"","sources":["../../src/commands/sandbox-bootstrap.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,qCAAqC;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,YAAY,CAAC;CACtB;AAgJD,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,qCAAqC,GAC1C,OAAO,CAgDT"} \ No newline at end of file diff --git a/nemoclaw/dist/commands/sandbox-bootstrap.js b/nemoclaw/dist/commands/sandbox-bootstrap.js index 5e8b9ddbe3e..32d0ae46af8 100644 --- a/nemoclaw/dist/commands/sandbox-bootstrap.js +++ b/nemoclaw/dist/commands/sandbox-bootstrap.js @@ -2,28 +2,149 @@ // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 Object.defineProperty(exports, "__esModule", { value: true }); -exports.ensureSandboxOpenClawSetup = ensureSandboxOpenClawSetup; +exports.ensureSandboxOpenClawBootstrap = ensureSandboxOpenClawBootstrap; const node_child_process_1 = require("node:child_process"); -function ensureSandboxOpenClawSetup(opts) { - const { sandboxName, logger } = opts; +function isSystemdUnavailableDetail(detail) { + const normalized = detail.toLowerCase(); + return (normalized.includes("systemctl --user unavailable") || + normalized.includes("systemctl not available") || + normalized.includes("systemd user services are required") || + normalized.includes("failed to connect to bus") || + normalized.includes("dbus_session_bus_address") || + normalized.includes("xdg_runtime_dir")); +} +function readExecStream(value) { + if (typeof value === "string") { + return value.trim(); + } + if (value instanceof Buffer) { + return value.toString("utf-8").trim(); + } + return ""; +} +function runSandboxOpenClawCommand(sandboxName, args) { try { - (0, node_child_process_1.execFileSync)("openshell", ["sandbox", "connect", sandboxName, "--", "openclaw", "setup"], { + const stdout = (0, node_child_process_1.execFileSync)("openshell", ["sandbox", "connect", sandboxName, "--", "openclaw", ...args], { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"], }); - logger.info("Initialized OpenClaw config and workspace inside the sandbox."); - return true; + return { + ok: true, + stdout: stdout.trim(), + stderr: "", + detail: stdout.trim(), + }; } catch (err) { - const stderr = err && - typeof err === "object" && - "stderr" in err && - typeof err.stderr === "string" - ? err.stderr.trim() + const stderr = err && typeof err === "object" && "stderr" in err + ? readExecStream(err.stderr) : ""; - logger.error(`Failed to initialize OpenClaw inside the sandbox: ${stderr || String(err)}`); + const stdout = err && typeof err === "object" && "stdout" in err + ? readExecStream(err.stdout) + : ""; + const detail = stderr || stdout || String(err); + return { + ok: false, + stdout, + stderr, + detail, + }; + } +} +function parseGatewayInstallJson(stdout) { + if (!stdout) { + return null; + } + try { + return JSON.parse(stdout); + } + catch { + return null; + } +} +function runSandboxShellCommand(sandboxName, script) { + try { + const stdout = (0, node_child_process_1.execFileSync)("openshell", ["sandbox", "connect", sandboxName, "--", "sh", "-lc", script], { + encoding: "utf-8", + stdio: ["ignore", "pipe", "pipe"], + }); + return { + ok: true, + stdout: stdout.trim(), + stderr: "", + detail: stdout.trim(), + }; + } + catch (err) { + const stderr = err && typeof err === "object" && "stderr" in err + ? readExecStream(err.stderr) + : ""; + const stdout = err && typeof err === "object" && "stdout" in err + ? readExecStream(err.stdout) + : ""; + const detail = stderr || stdout || String(err); + return { + ok: false, + stdout, + stderr, + detail, + }; + } +} +function startSandboxGatewayWithoutSystemd(sandboxName, logger) { + logger.warn("Sandbox user-systemd is unavailable. Falling back to a direct background Gateway process."); + return runSandboxShellCommand(sandboxName, [ + 'mkdir -p "$HOME/.openclaw/logs"', + 'if ! openclaw gateway status --deep --require-rpc >/dev/null 2>&1; then', + ' nohup openclaw gateway run --force >"$HOME/.openclaw/logs/gateway.log" 2>&1 < /dev/null &', + "fi", + "for i in 1 2 3 4 5 6 7 8; do", + " if openclaw gateway status --deep --require-rpc >/dev/null 2>&1; then", + ' echo "gateway-ready"', + " exit 0", + " fi", + " sleep 2", + "done", + 'echo "gateway-not-ready" >&2', + "exit 1", + ].join("\n")); +} +function ensureSandboxOpenClawBootstrap(opts) { + const { sandboxName, logger } = opts; + const setup = runSandboxOpenClawCommand(sandboxName, ["setup"]); + if (!setup.ok) { + logger.error(`Failed to initialize OpenClaw inside the sandbox: ${setup.detail}`); logger.info(`After resolving the issue, run 'openshell sandbox connect ${sandboxName} -- openclaw setup'.`); return false; } + // Keep bootstrap headless. `gateway install` auto-generates and persists a + // gateway token when one is missing, then installs the managed service. + const install = runSandboxOpenClawCommand(sandboxName, ["gateway", "install", "--json"]); + const parsed = parseGatewayInstallJson(install.stdout); + const installFailure = !install.ok || parsed?.ok === false; + const installFailureDetail = parsed?.message || install.detail || "Sandbox Gateway install failed."; + if (installFailure && isSystemdUnavailableDetail(installFailureDetail)) { + const fallback = startSandboxGatewayWithoutSystemd(sandboxName, logger); + if (!fallback.ok) { + logger.error(`Failed to start the sandbox Gateway without systemd: ${fallback.detail}`); + logger.info(`After resolving the issue, run 'openshell sandbox connect ${sandboxName} -- openclaw gateway run --force'.`); + return false; + } + for (const warning of parsed?.warnings ?? []) { + logger.warn(warning); + } + logger.info("Initialized OpenClaw config and started the Gateway directly inside the sandbox."); + return true; + } + if (installFailure) { + logger.error(`Failed to install the sandbox Gateway service: ${installFailureDetail}`); + logger.info(`After resolving the issue, run 'openshell sandbox connect ${sandboxName} -- openclaw gateway install'.`); + return false; + } + for (const warning of parsed?.warnings ?? []) { + logger.warn(warning); + } + logger.info("Initialized OpenClaw config and installed the Gateway service inside the sandbox."); + return true; } //# sourceMappingURL=sandbox-bootstrap.js.map \ No newline at end of file diff --git a/nemoclaw/dist/commands/sandbox-bootstrap.js.map b/nemoclaw/dist/commands/sandbox-bootstrap.js.map index dde33088bf2..1ba999b4079 100644 --- a/nemoclaw/dist/commands/sandbox-bootstrap.js.map +++ b/nemoclaw/dist/commands/sandbox-bootstrap.js.map @@ -1 +1 @@ -{"version":3,"file":"sandbox-bootstrap.js","sourceRoot":"","sources":["../../src/commands/sandbox-bootstrap.ts"],"names":[],"mappings":";AAAA,mGAAmG;AACnG,sCAAsC;;AAUtC,gEA0BC;AAlCD,2DAAkD;AAQlD,SAAgB,0BAA0B,CACxC,IAAuC;IAEvC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAErC,IAAI,CAAC;QACH,IAAA,iCAAY,EAAC,WAAW,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE;YACxF,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;SAClC,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,+DAA+D,CAAC,CAAC;QAC7E,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,MAAM,GACV,GAAG;YACH,OAAO,GAAG,KAAK,QAAQ;YACvB,QAAQ,IAAI,GAAG;YACf,OAAQ,GAA4B,CAAC,MAAM,KAAK,QAAQ;YACtD,CAAC,CAAE,GAA0B,CAAC,MAAM,CAAC,IAAI,EAAE;YAC3C,CAAC,CAAC,EAAE,CAAC;QACT,MAAM,CAAC,KAAK,CAAC,qDAAqD,MAAM,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC3F,MAAM,CAAC,IAAI,CACT,6DAA6D,WAAW,sBAAsB,CAC/F,CAAC;QACF,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"} \ No newline at end of file +{"version":3,"file":"sandbox-bootstrap.js","sourceRoot":"","sources":["../../src/commands/sandbox-bootstrap.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/nemoclaw/src/commands/launch.ts b/nemoclaw/src/commands/launch.ts index 2bdbae31e8a..c64063e7aa9 100644 --- a/nemoclaw/src/commands/launch.ts +++ b/nemoclaw/src/commands/launch.ts @@ -8,7 +8,7 @@ import { verifyBlueprintDigest, checkCompatibility } from "../blueprint/verify.j import { execBlueprint } from "../blueprint/exec.js"; import { loadState, saveState } from "../blueprint/state.js"; import { detectHostOpenClaw } from "./migrate.js"; -import { ensureSandboxOpenClawSetup } from "./sandbox-bootstrap.js"; +import { ensureSandboxOpenClawBootstrap } from "./sandbox-bootstrap.js"; export interface LaunchOptions { force: boolean; @@ -107,13 +107,13 @@ export async function cliLaunch(opts: LaunchOptions): Promise { return; } - logger.info("Initializing OpenClaw inside the sandbox..."); - const initialized = ensureSandboxOpenClawSetup({ + logger.info("Bootstrapping OpenClaw inside the sandbox..."); + const bootstrapped = ensureSandboxOpenClawBootstrap({ sandboxName: pluginConfig.sandboxName, logger, }); - if (!initialized) { - logger.error("Sandbox bootstrap failed before OpenClaw could create its initial config."); + if (!bootstrapped) { + logger.error("Sandbox bootstrap failed before OpenClaw became ready for headless use."); return; } diff --git a/nemoclaw/src/commands/migrate.ts b/nemoclaw/src/commands/migrate.ts index 55869327b6c..5366b4663d9 100644 --- a/nemoclaw/src/commands/migrate.ts +++ b/nemoclaw/src/commands/migrate.ts @@ -16,6 +16,7 @@ import { loadSnapshotManifest, type SnapshotBundle, } from "./migration-state.js"; +import { ensureSandboxOpenClawBootstrap } from "./sandbox-bootstrap.js"; export { detectHostOpenClaw, type HostOpenClawState } from "./migration-state.js"; @@ -145,6 +146,19 @@ export async function cliMigrate(opts: MigrateOptions): Promise { logger.info("Verifying sandbox migration..."); verifySandboxMigration(bundle, pluginConfig.sandboxName); + logger.info("Bootstrapping sandbox OpenClaw services..."); + const bootstrapped = ensureSandboxOpenClawBootstrap({ + sandboxName: pluginConfig.sandboxName, + logger, + }); + if (!bootstrapped) { + logger.error("Sandbox bootstrap failed after migration sync."); + logger.info( + "Your host installation is unchanged. Resolve the sandbox issue and rerun migrate.", + ); + return; + } + saveState({ ...loadState(), lastRunId: applyResult.runId, diff --git a/nemoclaw/src/commands/sandbox-bootstrap.ts b/nemoclaw/src/commands/sandbox-bootstrap.ts index 296bec8d213..06cf287617a 100644 --- a/nemoclaw/src/commands/sandbox-bootstrap.ts +++ b/nemoclaw/src/commands/sandbox-bootstrap.ts @@ -4,35 +4,201 @@ import { execFileSync } from "node:child_process"; import type { PluginLogger } from "../index.js"; -export interface EnsureSandboxOpenClawSetupOptions { +export interface EnsureSandboxOpenClawBootstrapOptions { sandboxName: string; logger: PluginLogger; } -export function ensureSandboxOpenClawSetup( - opts: EnsureSandboxOpenClawSetupOptions, -): boolean { - const { sandboxName, logger } = opts; +type SandboxOpenClawCommandResult = { + ok: boolean; + stdout: string; + stderr: string; + detail: string; +}; + +type GatewayInstallJson = { + ok?: boolean; + message?: string; + warnings?: string[]; +}; +function isSystemdUnavailableDetail(detail: string): boolean { + const normalized = detail.toLowerCase(); + return ( + normalized.includes("systemctl --user unavailable") || + normalized.includes("systemctl not available") || + normalized.includes("systemd user services are required") || + normalized.includes("failed to connect to bus") || + normalized.includes("dbus_session_bus_address") || + normalized.includes("xdg_runtime_dir") + ); +} + +function readExecStream(value: unknown): string { + if (typeof value === "string") { + return value.trim(); + } + if (value instanceof Buffer) { + return value.toString("utf-8").trim(); + } + return ""; +} + +function runSandboxOpenClawCommand( + sandboxName: string, + args: string[], +): SandboxOpenClawCommandResult { try { - execFileSync("openshell", ["sandbox", "connect", sandboxName, "--", "openclaw", "setup"], { + const stdout = execFileSync("openshell", ["sandbox", "connect", sandboxName, "--", "openclaw", ...args], { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"], }); - logger.info("Initialized OpenClaw config and workspace inside the sandbox."); - return true; + return { + ok: true, + stdout: stdout.trim(), + stderr: "", + detail: stdout.trim(), + }; + } catch (err: unknown) { + const stderr = + err && typeof err === "object" && "stderr" in err + ? readExecStream((err as { stderr?: unknown }).stderr) + : ""; + const stdout = + err && typeof err === "object" && "stdout" in err + ? readExecStream((err as { stdout?: unknown }).stdout) + : ""; + const detail = stderr || stdout || String(err); + return { + ok: false, + stdout, + stderr, + detail, + }; + } +} + +function parseGatewayInstallJson(stdout: string): GatewayInstallJson | null { + if (!stdout) { + return null; + } + try { + return JSON.parse(stdout) as GatewayInstallJson; + } catch { + return null; + } +} + +function runSandboxShellCommand(sandboxName: string, script: string): SandboxOpenClawCommandResult { + try { + const stdout = execFileSync( + "openshell", + ["sandbox", "connect", sandboxName, "--", "sh", "-lc", script], + { + encoding: "utf-8", + stdio: ["ignore", "pipe", "pipe"], + }, + ); + return { + ok: true, + stdout: stdout.trim(), + stderr: "", + detail: stdout.trim(), + }; } catch (err: unknown) { const stderr = - err && - typeof err === "object" && - "stderr" in err && - typeof (err as { stderr?: unknown }).stderr === "string" - ? (err as { stderr: string }).stderr.trim() + err && typeof err === "object" && "stderr" in err + ? readExecStream((err as { stderr?: unknown }).stderr) + : ""; + const stdout = + err && typeof err === "object" && "stdout" in err + ? readExecStream((err as { stdout?: unknown }).stdout) : ""; - logger.error(`Failed to initialize OpenClaw inside the sandbox: ${stderr || String(err)}`); + const detail = stderr || stdout || String(err); + return { + ok: false, + stdout, + stderr, + detail, + }; + } +} + +function startSandboxGatewayWithoutSystemd( + sandboxName: string, + logger: PluginLogger, +): SandboxOpenClawCommandResult { + logger.warn( + "Sandbox user-systemd is unavailable. Falling back to a direct background Gateway process.", + ); + return runSandboxShellCommand( + sandboxName, + [ + 'mkdir -p "$HOME/.openclaw/logs"', + 'if ! openclaw gateway status --deep --require-rpc >/dev/null 2>&1; then', + ' nohup openclaw gateway run --force >"$HOME/.openclaw/logs/gateway.log" 2>&1 < /dev/null &', + "fi", + "for i in 1 2 3 4 5 6 7 8; do", + " if openclaw gateway status --deep --require-rpc >/dev/null 2>&1; then", + ' echo "gateway-ready"', + " exit 0", + " fi", + " sleep 2", + "done", + 'echo "gateway-not-ready" >&2', + "exit 1", + ].join("\n"), + ); +} + +export function ensureSandboxOpenClawBootstrap( + opts: EnsureSandboxOpenClawBootstrapOptions, +): boolean { + const { sandboxName, logger } = opts; + + const setup = runSandboxOpenClawCommand(sandboxName, ["setup"]); + if (!setup.ok) { + logger.error(`Failed to initialize OpenClaw inside the sandbox: ${setup.detail}`); logger.info( `After resolving the issue, run 'openshell sandbox connect ${sandboxName} -- openclaw setup'.`, ); return false; } + + // Keep bootstrap headless. `gateway install` auto-generates and persists a + // gateway token when one is missing, then installs the managed service. + const install = runSandboxOpenClawCommand(sandboxName, ["gateway", "install", "--json"]); + const parsed = parseGatewayInstallJson(install.stdout); + const installFailure = !install.ok || parsed?.ok === false; + const installFailureDetail = parsed?.message || install.detail || "Sandbox Gateway install failed."; + + if (installFailure && isSystemdUnavailableDetail(installFailureDetail)) { + const fallback = startSandboxGatewayWithoutSystemd(sandboxName, logger); + if (!fallback.ok) { + logger.error(`Failed to start the sandbox Gateway without systemd: ${fallback.detail}`); + logger.info( + `After resolving the issue, run 'openshell sandbox connect ${sandboxName} -- openclaw gateway run --force'.`, + ); + return false; + } + for (const warning of parsed?.warnings ?? []) { + logger.warn(warning); + } + logger.info("Initialized OpenClaw config and started the Gateway directly inside the sandbox."); + return true; + } + + if (installFailure) { + logger.error(`Failed to install the sandbox Gateway service: ${installFailureDetail}`); + logger.info( + `After resolving the issue, run 'openshell sandbox connect ${sandboxName} -- openclaw gateway install'.`, + ); + return false; + } + for (const warning of parsed?.warnings ?? []) { + logger.warn(warning); + } + + logger.info("Initialized OpenClaw config and installed the Gateway service inside the sandbox."); + return true; } diff --git a/test/Dockerfile.sandbox b/test/Dockerfile.sandbox index cf0ef49a9d2..31a314be3a1 100644 --- a/test/Dockerfile.sandbox +++ b/test/Dockerfile.sandbox @@ -9,6 +9,7 @@ ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y --no-install-recommends \ python3 python3-pip python3-venv \ curl git ca-certificates \ + dbus dbus-user-session systemd \ iproute2 \ && rm -rf /var/lib/apt/lists/* diff --git a/test/e2e-test.sh b/test/e2e-test.sh index e3758fbb219..cbb349665ce 100755 --- a/test/e2e-test.sh +++ b/test/e2e-test.sh @@ -250,7 +250,199 @@ console.log('State management: create, save, load, clear all working'); " && pass "NemoClaw state management works" || fail "State management broken" # ------------------------------------------------------- -info "11. Verify launch bootstraps openclaw.json in the sandbox" +info "11. Verify headless sandbox bootstrap seeds config and gateway service" +# ------------------------------------------------------- +rm -rf /tmp/fake-bin /tmp/fake-sandbox +mkdir -p /tmp/fake-bin /tmp/fake-sandbox + +cat > /tmp/fake-bin/openshell <<'EOF' +#!/usr/bin/env bash +set -euo pipefail + +root="${FAKE_SANDBOX_ROOT:?}" +printf '%s\n' "$*" >> "${root}/invocation.txt" + +if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "openclaw" ] && [ "$6" = "setup" ]; then + sandbox_root="${root}/$3/.openclaw" + mkdir -p "${sandbox_root}/workspace" "${sandbox_root}/sessions" + cat > "${sandbox_root}/openclaw.json" <<'JSON' +{ + "agents": { + "defaults": { + "workspace": "/sandbox/.openclaw/workspace" + } + }, + "gateway": { + "mode": "local" + } +} +JSON + exit 0 +fi + +if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "openclaw" ] && [ "$6" = "gateway" ] && [ "$7" = "install" ] && [ "$8" = "--json" ]; then + sandbox_root="${root}/$3/.openclaw" + mkdir -p "${sandbox_root}/systemd" + cat > "${sandbox_root}/openclaw.json" <<'JSON' +{ + "agents": { + "defaults": { + "workspace": "/sandbox/.openclaw/workspace" + } + }, + "gateway": { + "mode": "local", + "auth": { + "mode": "token", + "token": "sandbox-token-123" + } + } +} +JSON + touch "${sandbox_root}/systemd/openclaw-gateway.service" + cat <<'JSON' +{"ok":true,"result":"installed","message":"Gateway service installed.","warnings":["No gateway token found. Auto-generated one and saving to config."]} +JSON + exit 0 +fi + +echo "unexpected openshell invocation: $*" >&2 +exit 1 +EOF +chmod +x /tmp/fake-bin/openshell + +PATH="/tmp/fake-bin:$PATH" FAKE_SANDBOX_ROOT=/tmp/fake-sandbox node - <<'EOF' +const { ensureSandboxOpenClawBootstrap } = require('/opt/nemoclaw/dist/commands/sandbox-bootstrap.js'); + +const logger = { + info() {}, + warn() {}, + error(message) { + throw new Error(message); + }, + debug() {}, +}; + +const ok = ensureSandboxOpenClawBootstrap({ sandboxName: 'openclaw', logger }); +if (!ok) { + throw new Error('bootstrap helper returned false'); +} +EOF + +grep -q '^sandbox connect openclaw -- openclaw setup$' /tmp/fake-sandbox/invocation.txt \ + && pass "Headless bootstrap runs openclaw setup" \ + || fail "Headless bootstrap did not run openclaw setup" +grep -q '^sandbox connect openclaw -- openclaw gateway install --json$' /tmp/fake-sandbox/invocation.txt \ + && pass "Headless bootstrap runs gateway install --json" \ + || fail "Headless bootstrap did not run gateway install --json" +grep -q '"token": "sandbox-token-123"' /tmp/fake-sandbox/openclaw/.openclaw/openclaw.json \ + && pass "Headless bootstrap seeded gateway auth token" \ + || fail "Headless bootstrap did not seed gateway auth token" +[ -f /tmp/fake-sandbox/openclaw/.openclaw/systemd/openclaw-gateway.service ] \ + && pass "Headless bootstrap created gateway service marker" \ + || fail "Headless bootstrap did not create gateway service marker" + +# ------------------------------------------------------- +info "12. Verify headless bootstrap falls back when user-systemd is unavailable" +# ------------------------------------------------------- +rm -rf /tmp/fake-bin /tmp/fake-sandbox +mkdir -p /tmp/fake-bin /tmp/fake-sandbox + +cat > /tmp/fake-bin/openshell <<'EOF' +#!/usr/bin/env bash +set -euo pipefail + +root="${FAKE_SANDBOX_ROOT:?}" +printf '%s\n' "$*" >> "${root}/invocation.txt" + +if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "openclaw" ] && [ "$6" = "setup" ]; then + sandbox_root="${root}/$3/.openclaw" + mkdir -p "${sandbox_root}/workspace" "${sandbox_root}/sessions" + cat > "${sandbox_root}/openclaw.json" <<'JSON' +{ + "agents": { + "defaults": { + "workspace": "/sandbox/.openclaw/workspace" + } + }, + "gateway": { + "mode": "local" + } +} +JSON + exit 0 +fi + +if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "openclaw" ] && [ "$6" = "gateway" ] && [ "$7" = "install" ] && [ "$8" = "--json" ]; then + sandbox_root="${root}/$3/.openclaw" + cat > "${sandbox_root}/openclaw.json" <<'JSON' +{ + "agents": { + "defaults": { + "workspace": "/sandbox/.openclaw/workspace" + } + }, + "gateway": { + "mode": "local", + "auth": { + "mode": "token", + "token": "fallback-token-789" + } + } +} +JSON + cat <<'JSON' +{"ok":false,"message":"systemctl --user unavailable: Failed to connect to bus","warnings":["No gateway token found. Auto-generated one and saving to config."]} +JSON + exit 0 +fi + +if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "sh" ] && [ "$6" = "-lc" ]; then + sandbox_root="${root}/$3/.openclaw" + mkdir -p "${sandbox_root}/logs" + touch "${sandbox_root}/logs/gateway.log" + echo "gateway-ready" + exit 0 +fi + +echo "unexpected openshell invocation: $*" >&2 +exit 1 +EOF +chmod +x /tmp/fake-bin/openshell + +PATH="/tmp/fake-bin:$PATH" FAKE_SANDBOX_ROOT=/tmp/fake-sandbox node - <<'EOF' +const { ensureSandboxOpenClawBootstrap } = require('/opt/nemoclaw/dist/commands/sandbox-bootstrap.js'); + +const logger = { + info() {}, + warn() {}, + error(message) { + throw new Error(message); + }, + debug() {}, +}; + +const ok = ensureSandboxOpenClawBootstrap({ sandboxName: 'openclaw', logger }); +if (!ok) { + throw new Error('fallback bootstrap helper returned false'); +} +EOF + +grep -q '^sandbox connect openclaw -- openclaw gateway install --json$' /tmp/fake-sandbox/invocation.txt \ + && pass "Fallback bootstrap still attempts gateway install first" \ + || fail "Fallback bootstrap did not attempt gateway install first" +grep -q '^sandbox connect openclaw -- sh -lc ' /tmp/fake-sandbox/invocation.txt \ + && pass "Fallback bootstrap starts direct gateway process" \ + || fail "Fallback bootstrap did not start direct gateway process" +grep -q '"token": "fallback-token-789"' /tmp/fake-sandbox/openclaw/.openclaw/openclaw.json \ + && pass "Fallback bootstrap preserves generated gateway auth token" \ + || fail "Fallback bootstrap did not preserve gateway auth token" +[ -f /tmp/fake-sandbox/openclaw/.openclaw/logs/gateway.log ] \ + && pass "Fallback bootstrap created gateway log path" \ + || fail "Fallback bootstrap did not create gateway log path" + +# ------------------------------------------------------- +info "13. Verify launch runs the full headless bootstrap sequence" # ------------------------------------------------------- rm -rf /tmp/fake-bin /tmp/fake-sandbox /tmp/fake-home mkdir -p /tmp/fake-bin /tmp/fake-sandbox /tmp/fake-home @@ -298,6 +490,32 @@ JSON exit 0 fi +if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "openclaw" ] && [ "$6" = "gateway" ] && [ "$7" = "install" ] && [ "$8" = "--json" ]; then + sandbox_root="${root}/$3/.openclaw" + mkdir -p "${sandbox_root}/systemd" + cat > "${sandbox_root}/openclaw.json" <<'JSON' +{ + "agents": { + "defaults": { + "workspace": "/sandbox/.openclaw/workspace" + } + }, + "gateway": { + "mode": "local", + "auth": { + "mode": "token", + "token": "sandbox-token-123" + } + } +} +JSON + touch "${sandbox_root}/systemd/openclaw-gateway.service" + cat <<'JSON' +{"ok":true,"result":"installed","message":"Gateway service installed."} +JSON + exit 0 +fi + echo "unexpected openshell invocation: $*" >&2 exit 1 EOF @@ -374,7 +592,7 @@ main().catch((error) => { EOF grep -q '^sandbox connect openclaw -- openclaw setup$' /tmp/fake-sandbox/invocation.txt \ - && pass "Launch bootstraps OpenClaw with openclaw setup" \ + && pass "Launch runs openclaw setup" \ || fail "Launch did not run openclaw setup" [ -f /tmp/fake-sandbox/openclaw/.openclaw/openclaw.json ] \ && pass "Launch created openclaw.json" \ @@ -382,6 +600,203 @@ grep -q '^sandbox connect openclaw -- openclaw setup$' /tmp/fake-sandbox/invocat [ -d /tmp/fake-sandbox/openclaw/.openclaw/workspace ] \ && pass "Launch created workspace" \ || fail "Launch did not create workspace" +grep -q '^sandbox connect openclaw -- openclaw gateway install --json$' /tmp/fake-sandbox/invocation.txt \ + && pass "Launch runs gateway install --json" \ + || fail "Launch did not run gateway install --json" +[ -f /tmp/fake-sandbox/openclaw/.openclaw/systemd/openclaw-gateway.service ] \ + && pass "Launch created gateway service marker" \ + || fail "Launch did not create gateway service marker" + +# ------------------------------------------------------- +info "14. Verify migrate reruns the headless bootstrap sequence" +# ------------------------------------------------------- +rm -rf /tmp/fake-bin /tmp/fake-sandbox /tmp/fake-home +mkdir -p /tmp/fake-bin /tmp/fake-sandbox /tmp/fake-home/.openclaw/workspace +mkdir -p /tmp/fake-home/.openclaw/extensions /tmp/fake-home/.openclaw/skills /tmp/fake-home/.openclaw/hooks + +cat > /tmp/fake-home/.openclaw/openclaw.json <<'JSON' +{ + "agents": { + "defaults": { + "workspace": "/tmp/fake-home/.openclaw/workspace" + } + }, + "gateway": { + "mode": "local" + } +} +JSON +echo "migrated-workspace-file" > /tmp/fake-home/.openclaw/workspace/project.md + +cat > /tmp/fake-bin/openshell <<'EOF' +#!/usr/bin/env bash +set -euo pipefail + +root="${FAKE_SANDBOX_ROOT:?}" +printf '%s\n' "$*" >> "${root}/invocation.txt" + +if [ "$1" = "sandbox" ] && [ "$2" = "create" ]; then + mkdir -p "${root}/openclaw" + exit 0 +fi + +if [ "$1" = "provider" ] && [ "$2" = "create" ]; then + exit 0 +fi + +if [ "$1" = "inference" ] && [ "$2" = "set" ]; then + exit 0 +fi + +if [ "$1" = "sandbox" ] && [ "$2" = "cp" ]; then + sandbox_name="${4%%:*}" + sandbox_path="${4#*:}" + target_path="${root}/${sandbox_name}${sandbox_path#/sandbox}" + mkdir -p "$(dirname "${target_path}")" + cp "$3" "${target_path}" + exit 0 +fi + +if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "sh" ] && [ "$6" = "-lc" ]; then + sandbox_home="${root}/$3" + translated_script="${7//\/sandbox/${sandbox_home}}" + sh -lc "${translated_script}" + exit 0 +fi + +if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "node" ] && [ "$6" = "-e" ]; then + sandbox_home="${root}/$3" + translated_script="${7//\/sandbox/${sandbox_home}}" + node -e "${translated_script}" + exit 0 +fi + +if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "openclaw" ] && [ "$6" = "setup" ]; then + sandbox_root="${root}/$3/.openclaw" + mkdir -p "${sandbox_root}/workspace" "${sandbox_root}/sessions" + if [ ! -f "${sandbox_root}/openclaw.json" ]; then + cat > "${sandbox_root}/openclaw.json" <<'JSON' +{ + "agents": { + "defaults": { + "workspace": "/sandbox/.openclaw/workspace" + } + }, + "gateway": { + "mode": "local" + } +} +JSON + fi + exit 0 +fi + +if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "openclaw" ] && [ "$6" = "gateway" ] && [ "$7" = "install" ] && [ "$8" = "--json" ]; then + sandbox_root="${root}/$3/.openclaw" + mkdir -p "${sandbox_root}/systemd" + cat > "${sandbox_root}/openclaw.json" <<'JSON' +{ + "agents": { + "defaults": { + "workspace": "/sandbox/.openclaw/workspace" + } + }, + "gateway": { + "mode": "local", + "auth": { + "mode": "token", + "token": "migrated-token-456" + } + } +} +JSON + touch "${sandbox_root}/systemd/openclaw-gateway.service" + cat <<'JSON' +{"ok":true,"result":"installed","message":"Gateway service installed."} +JSON + exit 0 +fi + +echo "unexpected openshell invocation: $*" >&2 +exit 1 +EOF +chmod +x /tmp/fake-bin/openshell + +PATH="/tmp/fake-bin:$PATH" FAKE_SANDBOX_ROOT=/tmp/fake-sandbox HOME=/tmp/fake-home node - <<'EOF' +const fs = require('node:fs'); +const resolveModule = require('/opt/nemoclaw/dist/blueprint/resolve.js'); +resolveModule.resolveBlueprint = async () => ({ + version: '0.1.0', + localPath: '/sandbox/.nemoclaw/blueprints/0.1.0', + manifest: { + version: '0.1.0', + minOpenShellVersion: '0.1.0', + minOpenClawVersion: '2026.3.0', + profiles: ['default'], + digest: '', + }, + cached: true, +}); +const { cliMigrate } = require('/opt/nemoclaw/dist/commands/migrate.js'); + +const logger = { + info() {}, + warn() {}, + error(message) { + throw new Error(message); + }, + debug() {}, +}; + +async function main() { + await cliMigrate({ + dryRun: false, + profile: 'default', + skipBackup: true, + logger, + pluginConfig: { + blueprintVersion: '0.1.0', + blueprintRegistry: 'ghcr.io/nvidia/nemoclaw-blueprint', + sandboxName: 'openclaw', + inferenceProvider: 'nvidia', + }, + }); + + const state = JSON.parse( + fs.readFileSync('/tmp/fake-home/.nemoclaw/state/nemoclaw.json', 'utf8'), + ); + if (state.lastAction !== 'migrate') { + throw new Error(`Unexpected lastAction: ${state.lastAction}`); + } + if (state.sandboxName !== 'openclaw') { + throw new Error(`Unexpected sandboxName: ${state.sandboxName}`); + } +} + +main().catch((error) => { + console.error(error); + process.exit(1); +}); +EOF + +grep -Eq '^sandbox cp .+ openclaw:/sandbox/\.nemoclaw/migration/archives/state\.tar$' /tmp/fake-sandbox/invocation.txt \ + && pass "Migrate copies state archive into the sandbox" \ + || fail "Migrate did not copy the state archive into the sandbox" +grep -q '^sandbox connect openclaw -- sh -lc ' /tmp/fake-sandbox/invocation.txt \ + && pass "Migrate extracts archives inside the sandbox" \ + || fail "Migrate did not extract archives inside the sandbox" +grep -q '^sandbox connect openclaw -- openclaw setup$' /tmp/fake-sandbox/invocation.txt \ + && pass "Migrate reruns openclaw setup" \ + || fail "Migrate did not rerun openclaw setup" +grep -q '^sandbox connect openclaw -- openclaw gateway install --json$' /tmp/fake-sandbox/invocation.txt \ + && pass "Migrate reruns gateway install --json" \ + || fail "Migrate did not rerun gateway install --json" +[ -f /tmp/fake-sandbox/openclaw/.openclaw/workspace/project.md ] \ + && pass "Migrate restores workspace files into the sandbox" \ + || fail "Migrate did not restore workspace files into the sandbox" +grep -q '"token": "migrated-token-456"' /tmp/fake-sandbox/openclaw/.openclaw/openclaw.json \ + && pass "Migrate leaves sandbox with a gateway auth token" \ + || fail "Migrate did not leave the sandbox with a gateway auth token" echo "" echo -e "${GREEN}========================================${NC}" From 9d91690a1ae47038b70015f9cb070e7334b658eb Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sun, 15 Mar 2026 22:56:20 -0700 Subject: [PATCH 4/7] Setup: bootstrap OpenClaw inside new sandboxes Signed-off-by: Vincent Koc --- bin/lib/onboard.js | 11 ++- bin/nemoclaw.js | 4 +- scripts/bootstrap-sandbox-openclaw.sh | 104 ++++++++++++++++++++++++++ scripts/setup.sh | 3 + 4 files changed, 114 insertions(+), 8 deletions(-) create mode 100644 scripts/bootstrap-sandbox-openclaw.sh diff --git a/bin/lib/onboard.js b/bin/lib/onboard.js index afab310e2c8..c0806e7b882 100644 --- a/bin/lib/onboard.js +++ b/bin/lib/onboard.js @@ -360,12 +360,11 @@ async function setupInference(sandboxName, model, provider) { async function setupOpenclaw(sandboxName) { step(6, 7, "Setting up OpenClaw inside sandbox"); - // sandbox create with a command runs it inside the sandbox then exits. - // Since the sandbox already exists, we create a throwaway connect + command - // by using sandbox create --no-keep with the same image to exec into it. - // Simpler: just use sandbox connect which opens a shell — but it doesn't - // support passing commands. So we run the setup on next connect instead. - console.log(" ✓ OpenClaw gateway launched inside sandbox"); + // `openshell sandbox create ... -- ` only helps during allocation. + // Once the sandbox already exists, use the post-create bootstrap helper to + // initialize OpenClaw and seed the Gateway before first connect. + run(`bash "${path.join(SCRIPTS, "bootstrap-sandbox-openclaw.sh")}" "${sandboxName}"`); + console.log(" ✓ OpenClaw configured"); } // ── Step 7: Policy presets ─────────────────────────────────────── diff --git a/bin/nemoclaw.js b/bin/nemoclaw.js index 30772b0c0b7..211a8f32462 100755 --- a/bin/nemoclaw.js +++ b/bin/nemoclaw.js @@ -129,7 +129,7 @@ async function deploy(instanceName) { console.log(""); console.log(" Connecting to sandbox..."); console.log(""); - run(`ssh -t -o StrictHostKeyChecking=no -o LogLevel=ERROR ${name} 'cd /home/ubuntu/nemoclaw && set -a && . .env && set +a && openshell sandbox connect nemoclaw'`); + run(`ssh -t -o StrictHostKeyChecking=no -o LogLevel=ERROR ${name} 'cd /home/ubuntu/nemoclaw && set -a && . .env && set +a && openshell sandbox connect nemoclaw -- nemoclaw-shell'`); } async function start() { @@ -229,7 +229,7 @@ function egg(instanceName) { function sandboxConnect(sandboxName) { // Ensure port forward is alive before connecting run(`openshell forward start --background 18789 ${sandboxName} 2>/dev/null || true`, { ignoreError: true }); - run(`openshell sandbox connect ${sandboxName}`); + run(`openshell sandbox connect ${sandboxName} -- nemoclaw-shell`); } function sandboxStatus(sandboxName) { diff --git a/scripts/bootstrap-sandbox-openclaw.sh b/scripts/bootstrap-sandbox-openclaw.sh new file mode 100644 index 00000000000..5a3919d0c9d --- /dev/null +++ b/scripts/bootstrap-sandbox-openclaw.sh @@ -0,0 +1,104 @@ +#!/usr/bin/env bash +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +set -euo pipefail + +sandbox_name="${1:-}" +if [ -z "$sandbox_name" ]; then + echo "usage: bootstrap-sandbox-openclaw.sh " >&2 + exit 1 +fi + +info() { printf ' %s\n' "$1"; } +warn() { printf ' WARN: %s\n' "$1" >&2; } +fail() { printf ' ERROR: %s\n' "$1" >&2; exit 1; } + +run_in_sandbox() { + openshell sandbox connect "$sandbox_name" -- nemoclaw-shell "$@" +} + +run_setup() { + info "Initializing OpenClaw config inside sandbox..." + run_in_sandbox openclaw setup >/dev/null +} + +run_gateway_fallback() { + warn "user-systemd unavailable; starting Gateway directly" + run_in_sandbox sh -lc ' +mkdir -p "$HOME/.openclaw/logs" +if ! openclaw gateway status --deep --require-rpc >/dev/null 2>&1; then + nohup openclaw gateway run --force >"$HOME/.openclaw/logs/gateway.log" 2>&1 < /dev/null & +fi +for i in 1 2 3 4 5 6 7 8; do + if openclaw gateway status --deep --require-rpc >/dev/null 2>&1; then + exit 0 + fi + sleep 2 +done +exit 1 +' +} + +run_gateway_install() { + local gateway_json + info "Installing managed Gateway inside sandbox..." + gateway_json="$(run_in_sandbox openclaw gateway install --json)" + printf '%s\n' "$gateway_json" + + GATEWAY_JSON="$gateway_json" python3 - <<'PY' +import json, os, sys + +raw = os.environ.get("GATEWAY_JSON", "").strip() +try: + data = json.loads(raw) if raw else {} +except json.JSONDecodeError: + print("invalid-json") + sys.exit(2) + +for warning in data.get("warnings", []): + print(f"warning:{warning}") + +if data.get("ok") is True: + sys.exit(0) + +msg = str(data.get("message") or data.get("error") or "") +normalized = msg.lower() +need_fallback = any(token in normalized for token in [ + "systemctl --user unavailable", + "systemctl not available", + "systemd user services are required", + "failed to connect to bus", + "dbus_session_bus_address", + "xdg_runtime_dir", + "system has not been booted with systemd", +]) +print(f"fallback:{'1' if need_fallback else '0'}") +print(f"message:{msg}") +sys.exit(1) +PY +} + +run_setup + +gateway_output="$(run_gateway_install 2>&1)" || gateway_rc=$? +gateway_rc="${gateway_rc:-0}" +printf '%s\n' "$gateway_output" + +if [ "$gateway_rc" -eq 0 ]; then + info "Gateway initialized successfully." + exit 0 +fi + +if printf '%s\n' "$gateway_output" | grep -q '^fallback:1$'; then + run_gateway_fallback || fail "Gateway fallback failed" + info "Gateway initialized with direct background process." + exit 0 +fi + +message="$(printf '%s\n' "$gateway_output" | sed -n 's/^message://p' | tail -1)" +if [ -n "$message" ]; then + fail "$message" +fi + +fail "Gateway initialization failed" diff --git a/scripts/setup.sh b/scripts/setup.sh index 991eb84e9c2..0cc54fc6d1e 100755 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -184,6 +184,9 @@ if ! echo "$SANDBOX_LINE" | grep -q "Ready"; then fail "Sandbox created but not Ready (phase: ${SANDBOX_PHASE:-unknown}). Check 'openshell sandbox get nemoclaw'." fi +info "Bootstrapping OpenClaw inside sandbox..." +bash "$SCRIPT_DIR/bootstrap-sandbox-openclaw.sh" nemoclaw + # 6. Done echo "" info "Setup complete!" From 72babb664342cf9116668dbe3264d5d14c110bd7 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Mon, 16 Mar 2026 00:00:39 -0700 Subject: [PATCH 5/7] refactor: replace sandbox systemd with pid-managed gateway Signed-off-by: Vincent Koc --- Dockerfile | 19 +- README.md | 16 +- docs/reference/commands.md | 17 +- .../dist/commands/sandbox-bootstrap.d.ts.map | 2 +- nemoclaw/dist/commands/sandbox-bootstrap.js | 73 +++---- .../dist/commands/sandbox-bootstrap.js.map | 2 +- nemoclaw/src/commands/sandbox-bootstrap.ts | 91 ++++----- scripts/bootstrap-sandbox-openclaw.sh | 26 ++- scripts/nemoclaw-gateway.sh | 167 ++++++++++++++++ scripts/nemoclaw-shell.sh | 16 ++ test/Dockerfile.sandbox | 14 +- test/e2e-test.sh | 186 ++++++------------ 12 files changed, 390 insertions(+), 239 deletions(-) create mode 100755 scripts/nemoclaw-gateway.sh create mode 100644 scripts/nemoclaw-shell.sh diff --git a/Dockerfile b/Dockerfile index 2c7a9771893..00b2ef433af 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,11 +3,11 @@ FROM node:22-slim ENV DEBIAN_FRONTEND=noninteractive +ENV HOME=/sandbox RUN apt-get update && apt-get install -y --no-install-recommends \ python3 python3-pip python3-venv \ curl git ca-certificates \ - dbus dbus-user-session systemd \ iproute2 \ && rm -rf /var/lib/apt/lists/* @@ -36,12 +36,13 @@ RUN npm install --omit=dev RUN mkdir -p /sandbox/.nemoclaw/blueprints/0.1.0 \ && cp -r /opt/nemoclaw-blueprint/* /sandbox/.nemoclaw/blueprints/0.1.0/ -# Copy startup script +# Copy startup scripts and force read+execute bits for the sandbox user. COPY scripts/nemoclaw-start.sh /usr/local/bin/nemoclaw-start -RUN chmod +x /usr/local/bin/nemoclaw-start +COPY scripts/nemoclaw-shell.sh /usr/local/bin/nemoclaw-shell +COPY scripts/nemoclaw-gateway.sh /usr/local/bin/nemoclaw-gateway.sh +RUN chmod 755 /usr/local/bin/nemoclaw-start /usr/local/bin/nemoclaw-shell /usr/local/bin/nemoclaw-gateway.sh WORKDIR /sandbox -USER sandbox # Pre-create OpenClaw directories RUN mkdir -p /sandbox/.openclaw/agents/main/agent \ @@ -61,13 +62,13 @@ config = { \ 'models': [{'id': 'nemotron-3-super-120b-a12b', 'name': 'NVIDIA Nemotron 3 Super 120B', 'reasoning': False, 'input': ['text'], 'cost': {'input': 0, 'output': 0, 'cacheRead': 0, 'cacheWrite': 0}, 'contextWindow': 131072, 'maxTokens': 4096}] \ }}} \ }; \ -path = os.path.expanduser('~/.openclaw/openclaw.json'); \ +path = '/sandbox/.openclaw/openclaw.json'; \ json.dump(config, open(path, 'w'), indent=2); \ os.chmod(path, 0o600)" +RUN chown -R sandbox:sandbox /sandbox/.openclaw /sandbox/.nemoclaw # Install NemoClaw plugin into OpenClaw -RUN openclaw doctor --fix > /dev/null 2>&1 || true \ - && openclaw plugins install /opt/nemoclaw > /dev/null 2>&1 || true +RUN runuser -u sandbox -- env HOME=/sandbox openclaw doctor --fix > /dev/null 2>&1 || true \ + && runuser -u sandbox -- env HOME=/sandbox openclaw plugins install /opt/nemoclaw > /dev/null 2>&1 || true -ENTRYPOINT ["/bin/bash"] -CMD [] +USER sandbox diff --git a/README.md b/README.md index 6c9ee2f8a0b..8200d9c6572 100644 --- a/README.md +++ b/README.md @@ -22,10 +22,12 @@ First run prompts for your NVIDIA API Key (get one from [build.nvidia.com](https - Docker - [OpenShell CLI](https://github.com/NVIDIA/OpenShell/releases) (binary download) -The repo-owned sandbox image installs `systemd` and `dbus-user-session` so -OpenClaw's managed Gateway install can work when the runtime supports -user-systemd. NemoClaw still falls back to a direct background Gateway process -for headless/container sessions where `systemctl --user` is unavailable. +The repo-owned sandbox image stays simple and non-root at rest. +Headless bootstrap runs `openclaw setup`, then `nemoclaw-gateway.sh ensure` +inside the sandbox. That helper uses `~/.openclaw/run/gateway.pid` and +`~/.openclaw/run/gateway.lock` to keep exactly one direct +`openclaw gateway run --force` process alive without requiring systemd or +root-only service installation. ### Ubuntu 24.04 (fresh install) @@ -184,7 +186,7 @@ Without tmux, run these in two terminals: openshell term # Terminal 2 — agent -openshell sandbox connect nemoclaw +openshell sandbox connect nemoclaw -- nemoclaw-shell export NVIDIA_API_KEY=nvapi-... nemoclaw-start openclaw agent --agent main --local --session-id live @@ -227,7 +229,9 @@ nemoclaw-blueprint/ Versioned blueprint artifact (separate relea |--------|---------| | `scripts/setup.sh` | Host-side setup — gateway, providers, inference route, sandbox | | `scripts/brev-setup.sh` | Brev bootstrap — installs prerequisites, then runs `setup.sh` | -| `scripts/nemoclaw-start.sh` | Sandbox entrypoint — configures OpenClaw, installs plugin | +| `scripts/nemoclaw-shell.sh` | Thin shell wrapper — runs commands inside the sandbox as the current user | +| `scripts/nemoclaw-gateway.sh` | Gateway process manager — `ensure`, `status`, `stop` using PID + lock files | +| `scripts/nemoclaw-start.sh` | Sandbox startup helper — configures OpenClaw, installs plugin | | `scripts/walkthrough.sh` | Split-screen walkthrough — agent + TUI approval flow | | `scripts/fix-coredns.sh` | CoreDNS patch for Colima environments | diff --git a/docs/reference/commands.md b/docs/reference/commands.md index de5f69511b8..91976804d03 100644 --- a/docs/reference/commands.md +++ b/docs/reference/commands.md @@ -31,13 +31,13 @@ Both interfaces are installed when you run `npm install -g nemoclaw`. Bootstrap a fresh OpenClaw installation inside an OpenShell sandbox. After provisioning the sandbox, NemoClaw runs `openclaw setup` and -`openclaw gateway install` inside it so the config, workspace, sessions, -gateway auth token, and managed service all exist before first use. +`nemoclaw-gateway.sh ensure` inside it so the config, workspace, sessions, +gateway auth token, and direct Gateway process all exist before first use. If NemoClaw detects an existing host installation, `launch` stops and points you to `openclaw nemoclaw migrate` unless you pass `--force`. -If Linux user-systemd is unavailable inside the sandbox, NemoClaw falls back -to a direct background `openclaw gateway run --force` start so headless -bootstrap still completes. +The Gateway manager uses `~/.openclaw/run/gateway.pid` and +`~/.openclaw/run/gateway.lock` so headless bootstrap stays non-interactive and +does not depend on systemd or root-only service installation. ```console $ openclaw nemoclaw launch [--force] [--profile ] @@ -57,8 +57,7 @@ The command snapshots the resolved OpenClaw state, captures external agent roots referenced by config, preserves symlinks in tar archives, rewrites migrated config paths, verifies the migrated paths inside the sandbox, and then re-runs the same headless bootstrap so migrated installs also have a ready gateway -token and Gateway runtime even when the sandbox cannot host a user-systemd -service. +token and Gateway runtime after cutover. ```console $ openclaw nemoclaw migrate [--dry-run] [--profile ] [--skip-backup] @@ -75,7 +74,9 @@ $ openclaw nemoclaw migrate [--dry-run] [--profile ] [--skip-backup] ### `nemoclaw connect` -Open an interactive shell inside the OpenClaw sandbox. +Open an interactive shell inside the OpenClaw sandbox as the `sandbox` user. +This routes through `nemoclaw-shell`, which is a thin shell wrapper used by the +host-side bootstrap helpers. ```console $ nemoclaw my-assistant connect diff --git a/nemoclaw/dist/commands/sandbox-bootstrap.d.ts.map b/nemoclaw/dist/commands/sandbox-bootstrap.d.ts.map index 4e96048b882..1bc7df9aeab 100644 --- a/nemoclaw/dist/commands/sandbox-bootstrap.d.ts.map +++ b/nemoclaw/dist/commands/sandbox-bootstrap.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"sandbox-bootstrap.d.ts","sourceRoot":"","sources":["../../src/commands/sandbox-bootstrap.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,qCAAqC;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,YAAY,CAAC;CACtB;AAgJD,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,qCAAqC,GAC1C,OAAO,CAgDT"} \ No newline at end of file +{"version":3,"file":"sandbox-bootstrap.d.ts","sourceRoot":"","sources":["../../src/commands/sandbox-bootstrap.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIhD,MAAM,WAAW,qCAAqC;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,YAAY,CAAC;CACtB;AAkJD,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,qCAAqC,GAC1C,OAAO,CA8CT"} \ No newline at end of file diff --git a/nemoclaw/dist/commands/sandbox-bootstrap.js b/nemoclaw/dist/commands/sandbox-bootstrap.js index 32d0ae46af8..0b0117f4e49 100644 --- a/nemoclaw/dist/commands/sandbox-bootstrap.js +++ b/nemoclaw/dist/commands/sandbox-bootstrap.js @@ -4,6 +4,9 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.ensureSandboxOpenClawBootstrap = ensureSandboxOpenClawBootstrap; const node_child_process_1 = require("node:child_process"); +const node_fs_1 = require("node:fs"); +const node_os_1 = require("node:os"); +const node_path_1 = require("node:path"); function isSystemdUnavailableDetail(detail) { const normalized = detail.toLowerCase(); return (normalized.includes("systemctl --user unavailable") || @@ -22,9 +25,24 @@ function readExecStream(value) { } return ""; } -function runSandboxOpenClawCommand(sandboxName, args) { +function runSandboxSshCommand(sandboxName, remoteArgs) { + const tmpDir = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "nemoclaw-ssh-")); + const configPath = (0, node_path_1.join)(tmpDir, "config"); try { - const stdout = (0, node_child_process_1.execFileSync)("openshell", ["sandbox", "connect", sandboxName, "--", "openclaw", ...args], { + const sshConfig = (0, node_child_process_1.execFileSync)("openshell", ["sandbox", "ssh-config", sandboxName], { + encoding: "utf-8", + stdio: ["ignore", "pipe", "pipe"], + }); + (0, node_fs_1.writeFileSync)(configPath, sshConfig, { mode: 0o600 }); + const host = sshConfig + .split("\n") + .map((line) => line.trim()) + .find((line) => line.startsWith("Host ")) + ?.split(/\s+/)[1] || `openshell-${sandboxName}`; + const remoteCommand = remoteArgs + .map((arg) => `'${arg.replaceAll("'", `'\\''`)}'`) + .join(" "); + const stdout = (0, node_child_process_1.execFileSync)("ssh", ["-F", configPath, host, remoteCommand], { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"], }); @@ -50,6 +68,12 @@ function runSandboxOpenClawCommand(sandboxName, args) { detail, }; } + finally { + (0, node_fs_1.rmSync)(tmpDir, { recursive: true, force: true }); + } +} +function runSandboxOpenClawCommand(sandboxName, args) { + return runSandboxSshCommand(sandboxName, ["nemoclaw-shell", "openclaw", ...args]); } function parseGatewayInstallJson(stdout) { if (!stdout) { @@ -63,43 +87,20 @@ function parseGatewayInstallJson(stdout) { } } function runSandboxShellCommand(sandboxName, script) { - try { - const stdout = (0, node_child_process_1.execFileSync)("openshell", ["sandbox", "connect", sandboxName, "--", "sh", "-lc", script], { - encoding: "utf-8", - stdio: ["ignore", "pipe", "pipe"], - }); - return { - ok: true, - stdout: stdout.trim(), - stderr: "", - detail: stdout.trim(), - }; - } - catch (err) { - const stderr = err && typeof err === "object" && "stderr" in err - ? readExecStream(err.stderr) - : ""; - const stdout = err && typeof err === "object" && "stdout" in err - ? readExecStream(err.stdout) - : ""; - const detail = stderr || stdout || String(err); - return { - ok: false, - stdout, - stderr, - detail, - }; - } + return runSandboxSshCommand(sandboxName, ["nemoclaw-shell", "sh", "-lc", script]); +} +function manualSandboxCommandHint(sandboxName, command) { + return `openshell sandbox ssh-config ${sandboxName} > /tmp/${sandboxName}.ssh && ssh -F /tmp/${sandboxName}.ssh openshell-${sandboxName} nemoclaw-shell ${command}`; } function startSandboxGatewayWithoutSystemd(sandboxName, logger) { - logger.warn("Sandbox user-systemd is unavailable. Falling back to a direct background Gateway process."); + logger.warn("Sandbox user-systemd is unavailable, likely because the sandbox was not booted with systemd. Falling back to a direct background Gateway process."); return runSandboxShellCommand(sandboxName, [ 'mkdir -p "$HOME/.openclaw/logs"', - 'if ! openclaw gateway status --deep --require-rpc >/dev/null 2>&1; then', - ' nohup openclaw gateway run --force >"$HOME/.openclaw/logs/gateway.log" 2>&1 < /dev/null &', + 'if ! openclaw gateway status --deep >/dev/null 2>&1; then', + ' nohup openclaw gateway run >"$HOME/.openclaw/logs/gateway.log" 2>&1 < /dev/null &', "fi", "for i in 1 2 3 4 5 6 7 8; do", - " if openclaw gateway status --deep --require-rpc >/dev/null 2>&1; then", + " if openclaw gateway status --deep >/dev/null 2>&1; then", ' echo "gateway-ready"', " exit 0", " fi", @@ -114,7 +115,7 @@ function ensureSandboxOpenClawBootstrap(opts) { const setup = runSandboxOpenClawCommand(sandboxName, ["setup"]); if (!setup.ok) { logger.error(`Failed to initialize OpenClaw inside the sandbox: ${setup.detail}`); - logger.info(`After resolving the issue, run 'openshell sandbox connect ${sandboxName} -- openclaw setup'.`); + logger.info(`After resolving the issue, run '${manualSandboxCommandHint(sandboxName, "openclaw setup")}'.`); return false; } // Keep bootstrap headless. `gateway install` auto-generates and persists a @@ -127,7 +128,7 @@ function ensureSandboxOpenClawBootstrap(opts) { const fallback = startSandboxGatewayWithoutSystemd(sandboxName, logger); if (!fallback.ok) { logger.error(`Failed to start the sandbox Gateway without systemd: ${fallback.detail}`); - logger.info(`After resolving the issue, run 'openshell sandbox connect ${sandboxName} -- openclaw gateway run --force'.`); + logger.info(`After resolving the issue, run '${manualSandboxCommandHint(sandboxName, "openclaw gateway run")}'.`); return false; } for (const warning of parsed?.warnings ?? []) { @@ -138,7 +139,7 @@ function ensureSandboxOpenClawBootstrap(opts) { } if (installFailure) { logger.error(`Failed to install the sandbox Gateway service: ${installFailureDetail}`); - logger.info(`After resolving the issue, run 'openshell sandbox connect ${sandboxName} -- openclaw gateway install'.`); + logger.info(`After resolving the issue, run '${manualSandboxCommandHint(sandboxName, "openclaw gateway install")}'.`); return false; } for (const warning of parsed?.warnings ?? []) { diff --git a/nemoclaw/dist/commands/sandbox-bootstrap.js.map b/nemoclaw/dist/commands/sandbox-bootstrap.js.map index 1ba999b4079..70130a5c232 100644 --- a/nemoclaw/dist/commands/sandbox-bootstrap.js.map +++ b/nemoclaw/dist/commands/sandbox-bootstrap.js.map @@ -1 +1 @@ -{"version":3,"file":"sandbox-bootstrap.js","sourceRoot":"","sources":["../../src/commands/sandbox-bootstrap.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"sandbox-bootstrap.js","sourceRoot":"","sources":["../../src/commands/sandbox-bootstrap.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/nemoclaw/src/commands/sandbox-bootstrap.ts b/nemoclaw/src/commands/sandbox-bootstrap.ts index 06cf287617a..1a0840a35b5 100644 --- a/nemoclaw/src/commands/sandbox-bootstrap.ts +++ b/nemoclaw/src/commands/sandbox-bootstrap.ts @@ -2,7 +2,10 @@ // SPDX-License-Identifier: Apache-2.0 import { execFileSync } from "node:child_process"; +import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; import type { PluginLogger } from "../index.js"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; export interface EnsureSandboxOpenClawBootstrapOptions { sandboxName: string; @@ -44,12 +47,32 @@ function readExecStream(value: unknown): string { return ""; } -function runSandboxOpenClawCommand( +function runSandboxSshCommand( sandboxName: string, - args: string[], + remoteArgs: string[], ): SandboxOpenClawCommandResult { + const tmpDir = mkdtempSync(join(tmpdir(), "nemoclaw-ssh-")); + const configPath = join(tmpDir, "config"); + try { - const stdout = execFileSync("openshell", ["sandbox", "connect", sandboxName, "--", "openclaw", ...args], { + const sshConfig = execFileSync("openshell", ["sandbox", "ssh-config", sandboxName], { + encoding: "utf-8", + stdio: ["ignore", "pipe", "pipe"], + }); + writeFileSync(configPath, sshConfig, { mode: 0o600 }); + + const host = + sshConfig + .split("\n") + .map((line) => line.trim()) + .find((line) => line.startsWith("Host ")) + ?.split(/\s+/)[1] || `openshell-${sandboxName}`; + + const remoteCommand = remoteArgs + .map((arg) => `'${arg.replaceAll("'", `'\\''`)}'`) + .join(" "); + + const stdout = execFileSync("ssh", ["-F", configPath, host, remoteCommand], { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"], }); @@ -75,9 +98,18 @@ function runSandboxOpenClawCommand( stderr, detail, }; + } finally { + rmSync(tmpDir, { recursive: true, force: true }); } } +function runSandboxOpenClawCommand( + sandboxName: string, + args: string[], +): SandboxOpenClawCommandResult { + return runSandboxSshCommand(sandboxName, ["nemoclaw-shell", "openclaw", ...args]); +} + function parseGatewayInstallJson(stdout: string): GatewayInstallJson | null { if (!stdout) { return null; @@ -90,38 +122,11 @@ function parseGatewayInstallJson(stdout: string): GatewayInstallJson | null { } function runSandboxShellCommand(sandboxName: string, script: string): SandboxOpenClawCommandResult { - try { - const stdout = execFileSync( - "openshell", - ["sandbox", "connect", sandboxName, "--", "sh", "-lc", script], - { - encoding: "utf-8", - stdio: ["ignore", "pipe", "pipe"], - }, - ); - return { - ok: true, - stdout: stdout.trim(), - stderr: "", - detail: stdout.trim(), - }; - } catch (err: unknown) { - const stderr = - err && typeof err === "object" && "stderr" in err - ? readExecStream((err as { stderr?: unknown }).stderr) - : ""; - const stdout = - err && typeof err === "object" && "stdout" in err - ? readExecStream((err as { stdout?: unknown }).stdout) - : ""; - const detail = stderr || stdout || String(err); - return { - ok: false, - stdout, - stderr, - detail, - }; - } + return runSandboxSshCommand(sandboxName, ["nemoclaw-shell", "sh", "-lc", script]); +} + +function manualSandboxCommandHint(sandboxName: string, command: string): string { + return `openshell sandbox ssh-config ${sandboxName} > /tmp/${sandboxName}.ssh && ssh -F /tmp/${sandboxName}.ssh openshell-${sandboxName} nemoclaw-shell ${command}`; } function startSandboxGatewayWithoutSystemd( @@ -129,17 +134,17 @@ function startSandboxGatewayWithoutSystemd( logger: PluginLogger, ): SandboxOpenClawCommandResult { logger.warn( - "Sandbox user-systemd is unavailable. Falling back to a direct background Gateway process.", + "Sandbox user-systemd is unavailable, likely because the sandbox was not booted with systemd. Falling back to a direct background Gateway process.", ); return runSandboxShellCommand( sandboxName, [ 'mkdir -p "$HOME/.openclaw/logs"', - 'if ! openclaw gateway status --deep --require-rpc >/dev/null 2>&1; then', - ' nohup openclaw gateway run --force >"$HOME/.openclaw/logs/gateway.log" 2>&1 < /dev/null &', + 'if ! openclaw gateway status --deep >/dev/null 2>&1; then', + ' nohup openclaw gateway run >"$HOME/.openclaw/logs/gateway.log" 2>&1 < /dev/null &', "fi", "for i in 1 2 3 4 5 6 7 8; do", - " if openclaw gateway status --deep --require-rpc >/dev/null 2>&1; then", + " if openclaw gateway status --deep >/dev/null 2>&1; then", ' echo "gateway-ready"', " exit 0", " fi", @@ -159,9 +164,7 @@ export function ensureSandboxOpenClawBootstrap( const setup = runSandboxOpenClawCommand(sandboxName, ["setup"]); if (!setup.ok) { logger.error(`Failed to initialize OpenClaw inside the sandbox: ${setup.detail}`); - logger.info( - `After resolving the issue, run 'openshell sandbox connect ${sandboxName} -- openclaw setup'.`, - ); + logger.info(`After resolving the issue, run '${manualSandboxCommandHint(sandboxName, "openclaw setup")}'.`); return false; } @@ -177,7 +180,7 @@ export function ensureSandboxOpenClawBootstrap( if (!fallback.ok) { logger.error(`Failed to start the sandbox Gateway without systemd: ${fallback.detail}`); logger.info( - `After resolving the issue, run 'openshell sandbox connect ${sandboxName} -- openclaw gateway run --force'.`, + `After resolving the issue, run '${manualSandboxCommandHint(sandboxName, "openclaw gateway run")}'.`, ); return false; } @@ -191,7 +194,7 @@ export function ensureSandboxOpenClawBootstrap( if (installFailure) { logger.error(`Failed to install the sandbox Gateway service: ${installFailureDetail}`); logger.info( - `After resolving the issue, run 'openshell sandbox connect ${sandboxName} -- openclaw gateway install'.`, + `After resolving the issue, run '${manualSandboxCommandHint(sandboxName, "openclaw gateway install")}'.`, ); return false; } diff --git a/scripts/bootstrap-sandbox-openclaw.sh b/scripts/bootstrap-sandbox-openclaw.sh index 5a3919d0c9d..528592e0b9a 100644 --- a/scripts/bootstrap-sandbox-openclaw.sh +++ b/scripts/bootstrap-sandbox-openclaw.sh @@ -15,7 +15,23 @@ warn() { printf ' WARN: %s\n' "$1" >&2; } fail() { printf ' ERROR: %s\n' "$1" >&2; exit 1; } run_in_sandbox() { - openshell sandbox connect "$sandbox_name" -- nemoclaw-shell "$@" + local cfg host rc remote_cmd + cfg="$(mktemp)" + openshell sandbox ssh-config "$sandbox_name" >"$cfg" + host="$(awk '/^Host / { print $2; exit }' "$cfg")" + if [ -z "$host" ]; then + host="openshell-${sandbox_name}" + fi + remote_cmd="nemoclaw-shell" + for arg in "$@"; do + remote_cmd+=" '$(printf "%s" "$arg" | sed "s/'/'\\\\''/g")'" + done + set +e + ssh -F "$cfg" "$host" "$remote_cmd" + rc=$? + set -e + rm -f "$cfg" + return "$rc" } run_setup() { @@ -24,14 +40,14 @@ run_setup() { } run_gateway_fallback() { - warn "user-systemd unavailable; starting Gateway directly" + warn "user-systemd unavailable, likely because the sandbox was not booted with systemd; starting Gateway directly" run_in_sandbox sh -lc ' mkdir -p "$HOME/.openclaw/logs" -if ! openclaw gateway status --deep --require-rpc >/dev/null 2>&1; then - nohup openclaw gateway run --force >"$HOME/.openclaw/logs/gateway.log" 2>&1 < /dev/null & +if ! openclaw gateway status --deep >/dev/null 2>&1; then + nohup openclaw gateway run >"$HOME/.openclaw/logs/gateway.log" 2>&1 < /dev/null & fi for i in 1 2 3 4 5 6 7 8; do - if openclaw gateway status --deep --require-rpc >/dev/null 2>&1; then + if openclaw gateway status --deep >/dev/null 2>&1; then exit 0 fi sleep 2 diff --git a/scripts/nemoclaw-gateway.sh b/scripts/nemoclaw-gateway.sh new file mode 100755 index 00000000000..1d9ba59dcb5 --- /dev/null +++ b/scripts/nemoclaw-gateway.sh @@ -0,0 +1,167 @@ +#!/usr/bin/env bash +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +set -euo pipefail + +command_name="${1:-ensure}" + +RUNDIR="${HOME}/.openclaw/run" +LOGDIR="${HOME}/.openclaw/logs" +PIDFILE="${RUNDIR}/gateway.pid" +LOCKFILE="${RUNDIR}/gateway.lock" +LOGFILE="${LOGDIR}/gateway.log" + +mkdir -p "$RUNDIR" "$LOGDIR" + +info() { printf '%s\n' "$1"; } +warn() { printf 'WARN: %s\n' "$1" >&2; } +fail() { printf 'ERROR: %s\n' "$1" >&2; exit 1; } + +read_pid() { + if [ -f "$PIDFILE" ]; then + tr -d '\n' <"$PIDFILE" + fi +} + +pid_running() { + local pid="${1:-}" + [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null +} + +gateway_healthy() { + openclaw gateway status --deep >/dev/null 2>&1 +} + +clear_stale_pidfile() { + local pid + pid="$(read_pid || true)" + if [ -n "$pid" ] && ! pid_running "$pid"; then + rm -f "$PIDFILE" + fi +} + +acquire_lock() { + if ( set -o noclobber; printf '%s\n' "$$" >"$LOCKFILE" ) 2>/dev/null; then + trap 'rm -f "$LOCKFILE"' EXIT INT TERM + return 0 + fi + + local lock_pid="" + if [ -f "$LOCKFILE" ]; then + lock_pid="$(tr -d '\n' <"$LOCKFILE" 2>/dev/null || true)" + fi + if [ -n "$lock_pid" ] && pid_running "$lock_pid"; then + for _ in 1 2 3 4 5 6 7 8; do + if gateway_healthy; then + return 0 + fi + sleep 1 + done + fail "gateway bootstrap is already running under PID ${lock_pid}" + fi + + printf '%s\n' "$$" >"$LOCKFILE" + trap 'rm -f "$LOCKFILE"' EXIT INT TERM +} + +start_gateway() { + nohup openclaw gateway run >"$LOGFILE" 2>&1 < /dev/null & + local pid=$! + printf '%s\n' "$pid" >"$PIDFILE" + info "started-gateway:${pid}" +} + +ensure_gateway() { + acquire_lock + clear_stale_pidfile + + if gateway_healthy; then + local existing_pid + existing_pid="$(read_pid || true)" + if [ -n "$existing_pid" ] && pid_running "$existing_pid"; then + info "gateway-ready:${existing_pid}" + else + info "gateway-ready:external" + fi + return 0 + fi + + local pid + pid="$(read_pid || true)" + if [ -z "$pid" ] || ! pid_running "$pid"; then + start_gateway + pid="$(read_pid || true)" + fi + + for _ in 1 2 3 4 5 6 7 8; do + if gateway_healthy; then + info "gateway-ready:${pid:-unknown}" + return 0 + fi + if [ -n "$pid" ] && ! pid_running "$pid"; then + warn "gateway process exited before becoming healthy" + break + fi + sleep 2 + done + + fail "gateway failed to become healthy; see ${LOGFILE}" +} + +status_gateway() { + clear_stale_pidfile + local pid + pid="$(read_pid || true)" + local state="stopped" + if [ -n "$pid" ] && pid_running "$pid"; then + state="running" + fi + local health="unhealthy" + if gateway_healthy; then + health="healthy" + fi + printf 'state=%s\n' "$state" + printf 'health=%s\n' "$health" + printf 'pid=%s\n' "${pid:-}" + printf 'log=%s\n' "$LOGFILE" +} + +stop_gateway() { + clear_stale_pidfile + local pid + pid="$(read_pid || true)" + if [ -z "$pid" ]; then + info "gateway-not-running" + return 0 + fi + if pid_running "$pid"; then + kill "$pid" 2>/dev/null || true + for _ in 1 2 3 4 5; do + if ! pid_running "$pid"; then + break + fi + sleep 1 + done + if pid_running "$pid"; then + kill -9 "$pid" 2>/dev/null || true + fi + fi + rm -f "$PIDFILE" + info "gateway-stopped:${pid}" +} + +case "$command_name" in + ensure) + ensure_gateway + ;; + status) + status_gateway + ;; + stop) + stop_gateway + ;; + *) + fail "usage: nemoclaw-gateway.sh [ensure|status|stop]" + ;; +esac diff --git a/scripts/nemoclaw-shell.sh b/scripts/nemoclaw-shell.sh new file mode 100644 index 00000000000..cbc4d131364 --- /dev/null +++ b/scripts/nemoclaw-shell.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +set -euo pipefail + +current_user="$(id -un)" +current_home="$(getent passwd "$current_user" | cut -d: -f6)" +current_shell="$(getent passwd "$current_user" | cut -d: -f7)" + +export HOME="${HOME:-$current_home}" +if [ "$#" -gt 0 ]; then + exec "$@" +fi + +exec "${current_shell}" -il diff --git a/test/Dockerfile.sandbox b/test/Dockerfile.sandbox index 31a314be3a1..7d963efb9af 100644 --- a/test/Dockerfile.sandbox +++ b/test/Dockerfile.sandbox @@ -5,11 +5,11 @@ FROM node:22-slim ENV DEBIAN_FRONTEND=noninteractive +ENV HOME=/sandbox RUN apt-get update && apt-get install -y --no-install-recommends \ python3 python3-pip python3-venv \ curl git ca-certificates \ - dbus dbus-user-session systemd \ iproute2 \ && rm -rf /var/lib/apt/lists/* @@ -32,6 +32,10 @@ COPY nemoclaw-blueprint/ /opt/nemoclaw-blueprint/ WORKDIR /opt/nemoclaw RUN npm install && rm -rf dist && npx tsc +COPY scripts/nemoclaw-shell.sh /usr/local/bin/nemoclaw-shell +COPY scripts/nemoclaw-gateway.sh /usr/local/bin/nemoclaw-gateway.sh +RUN chmod +x /usr/local/bin/nemoclaw-shell /usr/local/bin/nemoclaw-gateway.sh + # Patch OpenClaw's nvidia provider to replace Meta Llama 3.3 70B with # Nemotron 3 Super 120B. OpenClaw's embedded agent has a hardcoded model # catalog that doesn't include Nemotron 3 Super yet. This replaces the @@ -56,7 +60,7 @@ RUN mkdir -p /sandbox/.nemoclaw/blueprints/0.1.0 \ && cp -r /opt/nemoclaw-blueprint/* /sandbox/.nemoclaw/blueprints/0.1.0/ WORKDIR /sandbox -USER sandbox +USER root # Simulate a host OpenClaw installation for migration testing. # Keep the legacy ~/.openclaw fixture for the blueprint snapshot tests. @@ -92,7 +96,7 @@ RUN mkdir -p /sandbox/.openclaw/workspace /sandbox/.openclaw/extensions /sandbox # - external workspace/agentDir/skills dir under /sandbox/clawd # - symlink inside the workspace to verify tar-based preservation RUN mkdir -p /sandbox/openclaw-state/extensions /sandbox/openclaw-state/skills /sandbox/openclaw-state/hooks/demo-hook \ - /sandbox/clawd/main-workspace /sandbox/clawd/main-agent /sandbox/clawd/skills-extra /sandbox/config \ + /sandbox/clawd/main-workspace /sandbox/clawd/main-agent /sandbox/clawd/skills-extra /sandbox/config \ && printf '%s\n' \ '{' \ ' "agents": {' \ @@ -125,5 +129,5 @@ RUN mkdir -p /sandbox/openclaw-state/extensions /sandbox/openclaw-state/skills / && printf '%s\n' 'managed-skill' > /sandbox/openclaw-state/skills/test.md \ && printf '%s\n' '---' 'name: override-hook' 'description: Override hook fixture' '---' > /sandbox/openclaw-state/hooks/demo-hook/HOOK.md \ && printf '%s\n' 'export default async function overrideHook() {}' > /sandbox/openclaw-state/hooks/demo-hook/handler.js - -ENTRYPOINT ["/bin/bash"] +RUN chown -R sandbox:sandbox /sandbox +USER sandbox diff --git a/test/e2e-test.sh b/test/e2e-test.sh index cbb349665ce..880b3d154a2 100755 --- a/test/e2e-test.sh +++ b/test/e2e-test.sh @@ -250,7 +250,7 @@ console.log('State management: create, save, load, clear all working'); " && pass "NemoClaw state management works" || fail "State management broken" # ------------------------------------------------------- -info "11. Verify headless sandbox bootstrap seeds config and gateway service" +info "11. Verify headless sandbox bootstrap seeds config and gateway process" # ------------------------------------------------------- rm -rf /tmp/fake-bin /tmp/fake-sandbox mkdir -p /tmp/fake-bin /tmp/fake-sandbox @@ -262,7 +262,7 @@ set -euo pipefail root="${FAKE_SANDBOX_ROOT:?}" printf '%s\n' "$*" >> "${root}/invocation.txt" -if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "openclaw" ] && [ "$6" = "setup" ]; then +if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "nemoclaw-shell" ] && [ "$6" = "openclaw" ] && [ "$7" = "setup" ]; then sandbox_root="${root}/$3/.openclaw" mkdir -p "${sandbox_root}/workspace" "${sandbox_root}/sessions" cat > "${sandbox_root}/openclaw.json" <<'JSON' @@ -280,9 +280,9 @@ JSON exit 0 fi -if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "openclaw" ] && [ "$6" = "gateway" ] && [ "$7" = "install" ] && [ "$8" = "--json" ]; then +if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "nemoclaw-shell" ] && [ "$6" = "nemoclaw-gateway.sh" ] && [ "$7" = "ensure" ]; then sandbox_root="${root}/$3/.openclaw" - mkdir -p "${sandbox_root}/systemd" + mkdir -p "${sandbox_root}/run" "${sandbox_root}/logs" cat > "${sandbox_root}/openclaw.json" <<'JSON' { "agents": { @@ -299,10 +299,9 @@ if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = " } } JSON - touch "${sandbox_root}/systemd/openclaw-gateway.service" - cat <<'JSON' -{"ok":true,"result":"installed","message":"Gateway service installed.","warnings":["No gateway token found. Auto-generated one and saving to config."]} -JSON + echo "4242" > "${sandbox_root}/run/gateway.pid" + touch "${sandbox_root}/logs/gateway.log" + echo "gateway-ready:4242" exit 0 fi @@ -329,117 +328,58 @@ if (!ok) { } EOF -grep -q '^sandbox connect openclaw -- openclaw setup$' /tmp/fake-sandbox/invocation.txt \ +grep -q '^sandbox connect openclaw -- nemoclaw-shell openclaw setup$' /tmp/fake-sandbox/invocation.txt \ && pass "Headless bootstrap runs openclaw setup" \ || fail "Headless bootstrap did not run openclaw setup" -grep -q '^sandbox connect openclaw -- openclaw gateway install --json$' /tmp/fake-sandbox/invocation.txt \ - && pass "Headless bootstrap runs gateway install --json" \ - || fail "Headless bootstrap did not run gateway install --json" +grep -q '^sandbox connect openclaw -- nemoclaw-shell nemoclaw-gateway.sh ensure$' /tmp/fake-sandbox/invocation.txt \ + && pass "Headless bootstrap ensures the Gateway process" \ + || fail "Headless bootstrap did not ensure the Gateway process" grep -q '"token": "sandbox-token-123"' /tmp/fake-sandbox/openclaw/.openclaw/openclaw.json \ && pass "Headless bootstrap seeded gateway auth token" \ || fail "Headless bootstrap did not seed gateway auth token" -[ -f /tmp/fake-sandbox/openclaw/.openclaw/systemd/openclaw-gateway.service ] \ - && pass "Headless bootstrap created gateway service marker" \ - || fail "Headless bootstrap did not create gateway service marker" +[ -f /tmp/fake-sandbox/openclaw/.openclaw/run/gateway.pid ] \ + && pass "Headless bootstrap created gateway pid file" \ + || fail "Headless bootstrap did not create gateway pid file" # ------------------------------------------------------- -info "12. Verify headless bootstrap falls back when user-systemd is unavailable" +info "12. Verify the Gateway manager reuses a healthy process via PID file" # ------------------------------------------------------- -rm -rf /tmp/fake-bin /tmp/fake-sandbox -mkdir -p /tmp/fake-bin /tmp/fake-sandbox +rm -rf /tmp/fake-bin /tmp/fake-home /tmp/fake-health +mkdir -p /tmp/fake-bin /tmp/fake-home/.openclaw/run /tmp/fake-home/.openclaw/logs -cat > /tmp/fake-bin/openshell <<'EOF' +cat > /tmp/fake-bin/openclaw <<'EOF' #!/usr/bin/env bash set -euo pipefail -root="${FAKE_SANDBOX_ROOT:?}" -printf '%s\n' "$*" >> "${root}/invocation.txt" +printf '%s\n' "$*" >> /tmp/fake-openclaw.invocation.txt -if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "openclaw" ] && [ "$6" = "setup" ]; then - sandbox_root="${root}/$3/.openclaw" - mkdir -p "${sandbox_root}/workspace" "${sandbox_root}/sessions" - cat > "${sandbox_root}/openclaw.json" <<'JSON' -{ - "agents": { - "defaults": { - "workspace": "/sandbox/.openclaw/workspace" - } - }, - "gateway": { - "mode": "local" - } -} -JSON - exit 0 +if [ "$1" = "gateway" ] && [ "$2" = "status" ] && [ "$3" = "--deep" ] && [ "$4" = "--require-rpc" ]; then + [ -f /tmp/fake-health ] && exit 0 + exit 1 fi -if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "openclaw" ] && [ "$6" = "gateway" ] && [ "$7" = "install" ] && [ "$8" = "--json" ]; then - sandbox_root="${root}/$3/.openclaw" - cat > "${sandbox_root}/openclaw.json" <<'JSON' -{ - "agents": { - "defaults": { - "workspace": "/sandbox/.openclaw/workspace" - } - }, - "gateway": { - "mode": "local", - "auth": { - "mode": "token", - "token": "fallback-token-789" - } - } -} -JSON - cat <<'JSON' -{"ok":false,"message":"systemctl --user unavailable: Failed to connect to bus","warnings":["No gateway token found. Auto-generated one and saving to config."]} -JSON - exit 0 -fi - -if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "sh" ] && [ "$6" = "-lc" ]; then - sandbox_root="${root}/$3/.openclaw" - mkdir -p "${sandbox_root}/logs" - touch "${sandbox_root}/logs/gateway.log" - echo "gateway-ready" - exit 0 +if [ "$1" = "gateway" ] && [ "$2" = "run" ] && [ "$3" = "--force" ]; then + touch /tmp/fake-health + while true; do sleep 60; done fi -echo "unexpected openshell invocation: $*" >&2 +echo "unexpected openclaw invocation: $*" >&2 exit 1 EOF -chmod +x /tmp/fake-bin/openshell - -PATH="/tmp/fake-bin:$PATH" FAKE_SANDBOX_ROOT=/tmp/fake-sandbox node - <<'EOF' -const { ensureSandboxOpenClawBootstrap } = require('/opt/nemoclaw/dist/commands/sandbox-bootstrap.js'); - -const logger = { - info() {}, - warn() {}, - error(message) { - throw new Error(message); - }, - debug() {}, -}; - -const ok = ensureSandboxOpenClawBootstrap({ sandboxName: 'openclaw', logger }); -if (!ok) { - throw new Error('fallback bootstrap helper returned false'); -} -EOF +chmod +x /tmp/fake-bin/openclaw -grep -q '^sandbox connect openclaw -- openclaw gateway install --json$' /tmp/fake-sandbox/invocation.txt \ - && pass "Fallback bootstrap still attempts gateway install first" \ - || fail "Fallback bootstrap did not attempt gateway install first" -grep -q '^sandbox connect openclaw -- sh -lc ' /tmp/fake-sandbox/invocation.txt \ - && pass "Fallback bootstrap starts direct gateway process" \ - || fail "Fallback bootstrap did not start direct gateway process" -grep -q '"token": "fallback-token-789"' /tmp/fake-sandbox/openclaw/.openclaw/openclaw.json \ - && pass "Fallback bootstrap preserves generated gateway auth token" \ - || fail "Fallback bootstrap did not preserve gateway auth token" -[ -f /tmp/fake-sandbox/openclaw/.openclaw/logs/gateway.log ] \ - && pass "Fallback bootstrap created gateway log path" \ - || fail "Fallback bootstrap did not create gateway log path" +HOME=/tmp/fake-home PATH="/tmp/fake-bin:$PATH" /usr/local/bin/nemoclaw-gateway.sh ensure >/tmp/gateway-ensure-1.out +pid1="$(cat /tmp/fake-home/.openclaw/run/gateway.pid)" +HOME=/tmp/fake-home PATH="/tmp/fake-bin:$PATH" /usr/local/bin/nemoclaw-gateway.sh ensure >/tmp/gateway-ensure-2.out +pid2="$(cat /tmp/fake-home/.openclaw/run/gateway.pid)" +[ "$pid1" = "$pid2" ] || fail "Gateway manager changed pid across repeated ensure calls" +kill "$pid1" 2>/dev/null || true +grep -c '^gateway run --force$' /tmp/fake-openclaw.invocation.txt | grep -q '^1$' \ + && pass "Gateway manager starts only one process for repeated ensure calls" \ + || fail "Gateway manager started duplicate processes" +[ -f /tmp/fake-home/.openclaw/run/gateway.pid ] \ + && pass "Gateway manager records the process pid" \ + || fail "Gateway manager did not record the process pid" # ------------------------------------------------------- info "13. Verify launch runs the full headless bootstrap sequence" @@ -472,7 +412,7 @@ if [ "$1" = "inference" ] && [ "$2" = "set" ]; then exit 0 fi -if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "openclaw" ] && [ "$6" = "setup" ]; then +if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "nemoclaw-shell" ] && [ "$6" = "openclaw" ] && [ "$7" = "setup" ]; then sandbox_root="${root}/$3/.openclaw" mkdir -p "${sandbox_root}/workspace" "${sandbox_root}/sessions" cat > "${sandbox_root}/openclaw.json" <<'JSON' @@ -490,9 +430,9 @@ JSON exit 0 fi -if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "openclaw" ] && [ "$6" = "gateway" ] && [ "$7" = "install" ] && [ "$8" = "--json" ]; then +if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "nemoclaw-shell" ] && [ "$6" = "nemoclaw-gateway.sh" ] && [ "$7" = "ensure" ]; then sandbox_root="${root}/$3/.openclaw" - mkdir -p "${sandbox_root}/systemd" + mkdir -p "${sandbox_root}/run" "${sandbox_root}/logs" cat > "${sandbox_root}/openclaw.json" <<'JSON' { "agents": { @@ -509,10 +449,9 @@ if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = " } } JSON - touch "${sandbox_root}/systemd/openclaw-gateway.service" - cat <<'JSON' -{"ok":true,"result":"installed","message":"Gateway service installed."} -JSON + echo "31337" > "${sandbox_root}/run/gateway.pid" + touch "${sandbox_root}/logs/gateway.log" + echo "gateway-ready:31337" exit 0 fi @@ -591,7 +530,7 @@ main().catch((error) => { }); EOF -grep -q '^sandbox connect openclaw -- openclaw setup$' /tmp/fake-sandbox/invocation.txt \ +grep -q '^sandbox connect openclaw -- nemoclaw-shell openclaw setup$' /tmp/fake-sandbox/invocation.txt \ && pass "Launch runs openclaw setup" \ || fail "Launch did not run openclaw setup" [ -f /tmp/fake-sandbox/openclaw/.openclaw/openclaw.json ] \ @@ -600,12 +539,12 @@ grep -q '^sandbox connect openclaw -- openclaw setup$' /tmp/fake-sandbox/invocat [ -d /tmp/fake-sandbox/openclaw/.openclaw/workspace ] \ && pass "Launch created workspace" \ || fail "Launch did not create workspace" -grep -q '^sandbox connect openclaw -- openclaw gateway install --json$' /tmp/fake-sandbox/invocation.txt \ - && pass "Launch runs gateway install --json" \ - || fail "Launch did not run gateway install --json" -[ -f /tmp/fake-sandbox/openclaw/.openclaw/systemd/openclaw-gateway.service ] \ - && pass "Launch created gateway service marker" \ - || fail "Launch did not create gateway service marker" +grep -q '^sandbox connect openclaw -- nemoclaw-shell nemoclaw-gateway.sh ensure$' /tmp/fake-sandbox/invocation.txt \ + && pass "Launch ensures the Gateway process" \ + || fail "Launch did not ensure the Gateway process" +[ -f /tmp/fake-sandbox/openclaw/.openclaw/run/gateway.pid ] \ + && pass "Launch created gateway pid file" \ + || fail "Launch did not create gateway pid file" # ------------------------------------------------------- info "14. Verify migrate reruns the headless bootstrap sequence" @@ -671,7 +610,7 @@ if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = " exit 0 fi -if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "openclaw" ] && [ "$6" = "setup" ]; then +if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "nemoclaw-shell" ] && [ "$6" = "openclaw" ] && [ "$7" = "setup" ]; then sandbox_root="${root}/$3/.openclaw" mkdir -p "${sandbox_root}/workspace" "${sandbox_root}/sessions" if [ ! -f "${sandbox_root}/openclaw.json" ]; then @@ -691,9 +630,9 @@ JSON exit 0 fi -if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "openclaw" ] && [ "$6" = "gateway" ] && [ "$7" = "install" ] && [ "$8" = "--json" ]; then +if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "nemoclaw-shell" ] && [ "$6" = "nemoclaw-gateway.sh" ] && [ "$7" = "ensure" ]; then sandbox_root="${root}/$3/.openclaw" - mkdir -p "${sandbox_root}/systemd" + mkdir -p "${sandbox_root}/run" "${sandbox_root}/logs" cat > "${sandbox_root}/openclaw.json" <<'JSON' { "agents": { @@ -710,10 +649,9 @@ if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = " } } JSON - touch "${sandbox_root}/systemd/openclaw-gateway.service" - cat <<'JSON' -{"ok":true,"result":"installed","message":"Gateway service installed."} -JSON + echo "5150" > "${sandbox_root}/run/gateway.pid" + touch "${sandbox_root}/logs/gateway.log" + echo "gateway-ready:5150" exit 0 fi @@ -785,12 +723,12 @@ grep -Eq '^sandbox cp .+ openclaw:/sandbox/\.nemoclaw/migration/archives/state\. grep -q '^sandbox connect openclaw -- sh -lc ' /tmp/fake-sandbox/invocation.txt \ && pass "Migrate extracts archives inside the sandbox" \ || fail "Migrate did not extract archives inside the sandbox" -grep -q '^sandbox connect openclaw -- openclaw setup$' /tmp/fake-sandbox/invocation.txt \ +grep -q '^sandbox connect openclaw -- nemoclaw-shell openclaw setup$' /tmp/fake-sandbox/invocation.txt \ && pass "Migrate reruns openclaw setup" \ || fail "Migrate did not rerun openclaw setup" -grep -q '^sandbox connect openclaw -- openclaw gateway install --json$' /tmp/fake-sandbox/invocation.txt \ - && pass "Migrate reruns gateway install --json" \ - || fail "Migrate did not rerun gateway install --json" +grep -q '^sandbox connect openclaw -- nemoclaw-shell nemoclaw-gateway.sh ensure$' /tmp/fake-sandbox/invocation.txt \ + && pass "Migrate reruns Gateway ensure" \ + || fail "Migrate did not rerun Gateway ensure" [ -f /tmp/fake-sandbox/openclaw/.openclaw/workspace/project.md ] \ && pass "Migrate restores workspace files into the sandbox" \ || fail "Migrate did not restore workspace files into the sandbox" From 15a41c113280ba24c23b656022700758c7cfd9de Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 16 Mar 2026 00:54:41 -0700 Subject: [PATCH 6/7] feat: cache nemoclaw runtime prompt updates (cherry picked from commit 0662c8cc12ca42c6791a771be5d3e5f4fe14bbd9) --- nemoclaw/dist/commands/onboard.d.ts.map | 2 +- nemoclaw/dist/commands/onboard.js | 8 +- nemoclaw/dist/commands/onboard.js.map | 2 +- nemoclaw/dist/commands/slash.d.ts | 4 +- nemoclaw/dist/commands/slash.d.ts.map | 2 +- nemoclaw/dist/commands/slash.js | 31 ++- nemoclaw/dist/commands/slash.js.map | 2 +- nemoclaw/dist/index.d.ts | 2 +- nemoclaw/dist/index.d.ts.map | 2 +- nemoclaw/dist/index.js | 10 +- nemoclaw/dist/index.js.map | 2 +- nemoclaw/dist/runtime-context.d.ts | 11 + nemoclaw/dist/runtime-context.d.ts.map | 1 + nemoclaw/dist/runtime-context.js | 262 +++++++++++++++++ nemoclaw/dist/runtime-context.js.map | 1 + nemoclaw/src/commands/slash.ts | 39 ++- nemoclaw/src/index.ts | 14 +- nemoclaw/src/runtime-context.ts | 356 ++++++++++++++++++++++++ 18 files changed, 722 insertions(+), 29 deletions(-) create mode 100644 nemoclaw/dist/runtime-context.d.ts create mode 100644 nemoclaw/dist/runtime-context.d.ts.map create mode 100644 nemoclaw/dist/runtime-context.js create mode 100644 nemoclaw/dist/runtime-context.js.map create mode 100644 nemoclaw/src/runtime-context.ts diff --git a/nemoclaw/dist/commands/onboard.d.ts.map b/nemoclaw/dist/commands/onboard.d.ts.map index 031bf9de007..abe2a027eab 100644 --- a/nemoclaw/dist/commands/onboard.d.ts.map +++ b/nemoclaw/dist/commands/onboard.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"onboard.d.ts","sourceRoot":"","sources":["../../src/commands/onboard.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAUhE,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,YAAY,CAAC;IACrB,YAAY,EAAE,cAAc,CAAC;CAC9B;AAoHD,wBAAsB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAuQpE"} \ No newline at end of file +{"version":3,"file":"onboard.d.ts","sourceRoot":"","sources":["../../src/commands/onboard.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAUhE,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,YAAY,CAAC;IACrB,YAAY,EAAE,cAAc,CAAC;CAC9B;AAyHD,wBAAsB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA8QpE"} \ No newline at end of file diff --git a/nemoclaw/dist/commands/onboard.js b/nemoclaw/dist/commands/onboard.js index 8ca66648b2d..154140648f2 100644 --- a/nemoclaw/dist/commands/onboard.js +++ b/nemoclaw/dist/commands/onboard.js @@ -71,7 +71,10 @@ function isNonInteractive(opts) { return true; } function endpointRequiresApiKey(endpointType) { - return endpointType === "build" || endpointType === "ncp" || endpointType === "nim-local" || endpointType === "custom"; + return (endpointType === "build" || + endpointType === "ncp" || + endpointType === "nim-local" || + endpointType === "custom"); } function defaultCredentialForEndpoint(endpointType) { switch (endpointType) { @@ -188,7 +191,8 @@ async function cliOnboard(opts) { case "ncp": ncpPartner = opts.ncpPartner ?? (await (0, prompt_js_1.promptInput)("NCP partner name")); endpointUrl = - opts.endpointUrl ?? (await (0, prompt_js_1.promptInput)("NCP endpoint URL (e.g., https://partner.api.nvidia.com/v1)")); + opts.endpointUrl ?? + (await (0, prompt_js_1.promptInput)("NCP endpoint URL (e.g., https://partner.api.nvidia.com/v1)")); break; case "nim-local": endpointUrl = diff --git a/nemoclaw/dist/commands/onboard.js.map b/nemoclaw/dist/commands/onboard.js.map index 5a83a78ecb3..8981b6289f2 100644 --- a/nemoclaw/dist/commands/onboard.js.map +++ b/nemoclaw/dist/commands/onboard.js.map @@ -1 +1 @@ -{"version":3,"file":"onboard.js","sourceRoot":"","sources":["../../src/commands/onboard.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"onboard.js","sourceRoot":"","sources":["../../src/commands/onboard.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/nemoclaw/dist/commands/slash.d.ts b/nemoclaw/dist/commands/slash.d.ts index f1c5661093f..ea518c73298 100644 --- a/nemoclaw/dist/commands/slash.d.ts +++ b/nemoclaw/dist/commands/slash.d.ts @@ -6,6 +6,6 @@ * /nemoclaw eject - rollback to host installation * /nemoclaw - show help */ -import type { PluginCommandContext, PluginCommandResult, OpenClawPluginApi } from "../index.js"; -export declare function handleSlashCommand(ctx: PluginCommandContext, _api: OpenClawPluginApi): PluginCommandResult; +import type { PluginCommandContext, PluginCommandResult, OpenClawPluginApi, NemoClawConfig } from "../index.js"; +export declare function handleSlashCommand(ctx: PluginCommandContext, _api: OpenClawPluginApi, pluginConfig: NemoClawConfig): PluginCommandResult | Promise; //# sourceMappingURL=slash.d.ts.map \ No newline at end of file diff --git a/nemoclaw/dist/commands/slash.d.ts.map b/nemoclaw/dist/commands/slash.d.ts.map index ff6015318b2..39d05ad8300 100644 --- a/nemoclaw/dist/commands/slash.d.ts.map +++ b/nemoclaw/dist/commands/slash.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"slash.d.ts","sourceRoot":"","sources":["../../src/commands/slash.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIhG,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,oBAAoB,EACzB,IAAI,EAAE,iBAAiB,GACtB,mBAAmB,CAarB"} \ No newline at end of file +{"version":3,"file":"slash.d.ts","sourceRoot":"","sources":["../../src/commands/slash.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,cAAc,EACf,MAAM,aAAa,CAAC;AAKrB,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,oBAAoB,EACzB,IAAI,EAAE,iBAAiB,EACvB,YAAY,EAAE,cAAc,GAC3B,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAapD"} \ No newline at end of file diff --git a/nemoclaw/dist/commands/slash.js b/nemoclaw/dist/commands/slash.js index a7900d3096e..ff7e31bb304 100644 --- a/nemoclaw/dist/commands/slash.js +++ b/nemoclaw/dist/commands/slash.js @@ -5,11 +5,12 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.handleSlashCommand = handleSlashCommand; const state_js_1 = require("../blueprint/state.js"); const config_js_1 = require("../onboard/config.js"); -function handleSlashCommand(ctx, _api) { +const runtime_context_js_1 = require("../runtime-context.js"); +function handleSlashCommand(ctx, _api, pluginConfig) { const subcommand = ctx.args?.trim().split(/\s+/)[0] ?? ""; switch (subcommand) { case "status": - return slashStatus(); + return slashStatus(pluginConfig); case "eject": return slashEject(); case "onboard": @@ -23,10 +24,14 @@ function slashHelp() { text: [ "**NemoClaw**", "", + "OpenClaw runs inside an OpenShell sandbox.", + "Expect sandboxed filesystem/process access and deny-by-default outbound network.", + "Use `openshell term` to watch policy approvals or denials live.", + "", "Usage: `/nemoclaw `", "", "Subcommands:", - " `status` - Show sandbox, blueprint, and inference state", + " `status` - Show sandbox, blueprint, and live restriction summary", " `eject` - Show rollback instructions", " `onboard` - Show onboarding status and instructions", "", @@ -39,11 +44,22 @@ function slashHelp() { ].join("\n"), }; } -function slashStatus() { +async function slashStatus(pluginConfig) { const state = (0, state_js_1.loadState)(); + const runtime = await (0, runtime_context_js_1.getRuntimeSummary)(pluginConfig); if (!state.lastAction) { return { - text: "**NemoClaw**: No operations performed yet. Run `openclaw nemoclaw launch` or `openclaw nemoclaw migrate` to get started.", + text: [ + "**NemoClaw**: No operations performed yet.", + "Run `openclaw nemoclaw launch` or `openclaw nemoclaw migrate` to get started.", + "", + `Sandbox: ${runtime.sandboxName}`, + runtime.sandboxPhase ? `Phase: ${runtime.sandboxPhase}` : null, + "Restrictions:", + ...runtime.networkLines.slice(0, 2).map((line) => `- ${line}`), + ] + .filter(Boolean) + .join("\n"), }; } const lines = [ @@ -53,7 +69,12 @@ function slashStatus() { `Blueprint: ${state.blueprintVersion ?? "unknown"}`, `Run ID: ${state.lastRunId ?? "none"}`, `Sandbox: ${state.sandboxName ?? "none"}`, + runtime.sandboxPhase ? `Phase: ${runtime.sandboxPhase}` : null, `Updated: ${state.updatedAt}`, + "", + "Restrictions:", + ...runtime.networkLines.map((line) => `- ${line}`), + ...runtime.filesystemLines.map((line) => `- ${line}`), ]; if (state.migrationSnapshot) { lines.push("", `Rollback snapshot: ${state.migrationSnapshot}`); diff --git a/nemoclaw/dist/commands/slash.js.map b/nemoclaw/dist/commands/slash.js.map index 13b84101ad2..240dcff92a9 100644 --- a/nemoclaw/dist/commands/slash.js.map +++ b/nemoclaw/dist/commands/slash.js.map @@ -1 +1 @@ -{"version":3,"file":"slash.js","sourceRoot":"","sources":["../../src/commands/slash.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"slash.js","sourceRoot":"","sources":["../../src/commands/slash.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/nemoclaw/dist/index.d.ts b/nemoclaw/dist/index.d.ts index 1ad200e605c..7704b29a103 100644 --- a/nemoclaw/dist/index.d.ts +++ b/nemoclaw/dist/index.d.ts @@ -113,7 +113,7 @@ export interface OpenClawPluginApi { registerProvider: (provider: ProviderPlugin) => void; registerService: (service: PluginService) => void; resolvePath: (input: string) => string; - on: (hookName: string, handler: (...args: unknown[]) => void) => void; + on: (hookName: string, handler: (...args: unknown[]) => Promise) => void; } export interface NemoClawConfig { blueprintVersion: string; diff --git a/nemoclaw/dist/index.d.ts.map b/nemoclaw/dist/index.d.ts.map index d775191d583..6f0082a0cff 100644 --- a/nemoclaw/dist/index.d.ts.map +++ b/nemoclaw/dist/index.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/nemoclaw/dist/index.js b/nemoclaw/dist/index.js index 9268d4b7c60..2f78a87239b 100644 --- a/nemoclaw/dist/index.js +++ b/nemoclaw/dist/index.js @@ -7,6 +7,7 @@ exports.default = register; const cli_js_1 = require("./cli.js"); const slash_js_1 = require("./commands/slash.js"); const config_js_1 = require("./onboard/config.js"); +const runtime_context_js_1 = require("./runtime-context.js"); const DEFAULT_PLUGIN_CONFIG = { blueprintVersion: "latest", blueprintRegistry: "ghcr.io/nvidia/nemoclaw-blueprint", @@ -34,18 +35,21 @@ function getPluginConfig(api) { // Plugin entry point // --------------------------------------------------------------------------- function register(api) { + const pluginConfig = getPluginConfig(api); // 1. Register /nemoclaw slash command (chat interface) api.registerCommand({ name: "nemoclaw", - description: "NemoClaw sandbox management (status, eject).", + description: "NemoClaw sandbox status, restrictions, and rollback.", acceptsArgs: true, - handler: (ctx) => (0, slash_js_1.handleSlashCommand)(ctx, api), + handler: (ctx) => (0, slash_js_1.handleSlashCommand)(ctx, api, pluginConfig), }); // 2. Register `openclaw nemoclaw` CLI subcommands (commander.js) api.registerCli((cliCtx) => { (0, cli_js_1.registerCliCommands)(cliCtx, api); }, { commands: ["nemoclaw"] }); - // 3. Register nvidia-nim provider — use onboard config if available + // 3. Inject live OpenShell sandbox restrictions into agent turns. + (0, runtime_context_js_1.registerRuntimeContext)(api, pluginConfig); + // 4. Register nvidia-nim provider — use onboard config if available const onboardCfg = (0, config_js_1.loadOnboardConfig)(); const providerCredentialEnv = onboardCfg?.credentialEnv ?? "NVIDIA_API_KEY"; const providerLabel = onboardCfg diff --git a/nemoclaw/dist/index.js.map b/nemoclaw/dist/index.js.map index e45a1adab07..bea4f610b3f 100644 --- a/nemoclaw/dist/index.js.map +++ b/nemoclaw/dist/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,mGAAmG;AACnG,sCAAsC;;AAwJtC,0CAoBC;AAMD,2BAqFC;AA1PD,qCAA+C;AAC/C,kDAAyD;AACzD,mDAAwD;AACxD,6DAA8D;AAiI9D,MAAM,qBAAqB,GAAmB;IAC5C,gBAAgB,EAAE,QAAQ;IAC1B,iBAAiB,EAAE,mCAAmC;IACtD,WAAW,EAAE,UAAU;IACvB,iBAAiB,EAAE,QAAQ;CAC5B,CAAC;AAEF,SAAgB,eAAe,CAAC,GAAsB;IACpD,MAAM,GAAG,GAAG,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC;IACnC,OAAO;QACL,gBAAgB,EACd,OAAO,GAAG,CAAC,kBAAkB,CAAC,KAAK,QAAQ;YACzC,CAAC,CAAC,GAAG,CAAC,kBAAkB,CAAC;YACzB,CAAC,CAAC,qBAAqB,CAAC,gBAAgB;QAC5C,iBAAiB,EACf,OAAO,GAAG,CAAC,mBAAmB,CAAC,KAAK,QAAQ;YAC1C,CAAC,CAAC,GAAG,CAAC,mBAAmB,CAAC;YAC1B,CAAC,CAAC,qBAAqB,CAAC,iBAAiB;QAC7C,WAAW,EACT,OAAO,GAAG,CAAC,aAAa,CAAC,KAAK,QAAQ;YACpC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC;YACpB,CAAC,CAAC,qBAAqB,CAAC,WAAW;QACvC,iBAAiB,EACf,OAAO,GAAG,CAAC,mBAAmB,CAAC,KAAK,QAAQ;YAC1C,CAAC,CAAC,GAAG,CAAC,mBAAmB,CAAC;YAC1B,CAAC,CAAC,qBAAqB,CAAC,iBAAiB;KAC9C,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E,SAAwB,QAAQ,CAAC,GAAsB;IACrD,MAAM,YAAY,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IAE1C,uDAAuD;IACvD,GAAG,CAAC,eAAe,CAAC;QAClB,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE,sDAAsD;QACnE,WAAW,EAAE,IAAI;QACjB,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,IAAA,6BAAkB,EAAC,GAAG,EAAE,GAAG,EAAE,YAAY,CAAC;KAC7D,CAAC,CAAC;IAEH,iEAAiE;IACjE,GAAG,CAAC,WAAW,CACb,CAAC,MAAM,EAAE,EAAE;QACT,IAAA,4BAAmB,EAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACnC,CAAC,EACD,EAAE,QAAQ,EAAE,CAAC,UAAU,CAAC,EAAE,CAC3B,CAAC;IAEF,kEAAkE;IAClE,IAAA,2CAAsB,EAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAE1C,oEAAoE;IACpE,MAAM,UAAU,GAAG,IAAA,6BAAiB,GAAE,CAAC;IACvC,MAAM,qBAAqB,GAAG,UAAU,EAAE,aAAa,IAAI,gBAAgB,CAAC;IAC5E,MAAM,aAAa,GAAG,UAAU;QAC9B,CAAC,CAAC,eAAe,UAAU,CAAC,YAAY,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,UAAU,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG;QACxG,CAAC,CAAC,+BAA+B,CAAC;IAEpC,GAAG,CAAC,gBAAgB,CAAC;QACnB,EAAE,EAAE,YAAY;QAChB,KAAK,EAAE,aAAa;QACpB,QAAQ,EAAE,+BAA+B;QACzC,OAAO,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC;QAC1B,OAAO,EAAE,CAAC,qBAAqB,CAAC;QAChC,MAAM,EAAE;YACN,IAAI,EAAE;gBACJ;oBACE,EAAE,EAAE,mCAAmC;oBACvC,KAAK,EAAE,oCAAoC;oBAC3C,aAAa,EAAE,MAAM;oBACrB,SAAS,EAAE,IAAI;iBAChB;gBACD;oBACE,EAAE,EAAE,yCAAyC;oBAC7C,KAAK,EAAE,qBAAqB;oBAC5B,aAAa,EAAE,MAAM;oBACrB,SAAS,EAAE,IAAI;iBAChB;gBACD;oBACE,EAAE,EAAE,0CAA0C;oBAC9C,KAAK,EAAE,yBAAyB;oBAChC,aAAa,EAAE,MAAM;oBACrB,SAAS,EAAE,IAAI;iBAChB;gBACD;oBACE,EAAE,EAAE,gCAAgC;oBACpC,KAAK,EAAE,qBAAqB;oBAC5B,aAAa,EAAE,MAAM;oBACrB,SAAS,EAAE,IAAI;iBAChB;aACF;SACF;QACD,IAAI,EAAE;YACJ;gBACE,IAAI,EAAE,QAAQ;gBACd,MAAM,EAAE,qBAAqB;gBAC7B,UAAU,EAAE,eAAe;gBAC3B,KAAK,EAAE,mBAAmB,qBAAqB,GAAG;aACnD;SACF;KACF,CAAC,CAAC;IAEH,MAAM,cAAc,GAAG,UAAU,EAAE,YAAY,IAAI,kBAAkB,CAAC;IACtE,MAAM,WAAW,GAAG,UAAU,EAAE,KAAK,IAAI,mCAAmC,CAAC;IAE7E,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpB,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,2DAA2D,CAAC,CAAC;IAC7E,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,2DAA2D,CAAC,CAAC;IAC7E,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,2DAA2D,CAAC,CAAC;IAC7E,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,mBAAmB,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IACjE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,mBAAmB,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IAC9D,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,2DAA2D,CAAC,CAAC;IAC7E,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,2DAA2D,CAAC,CAAC;IAC7E,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACtB,CAAC"} \ No newline at end of file diff --git a/nemoclaw/dist/runtime-context.d.ts b/nemoclaw/dist/runtime-context.d.ts new file mode 100644 index 00000000000..f21dac91f81 --- /dev/null +++ b/nemoclaw/dist/runtime-context.d.ts @@ -0,0 +1,11 @@ +import type { NemoClawConfig, OpenClawPluginApi } from "./index.js"; +type RuntimeSummary = { + sandboxName: string; + sandboxPhase: string | null; + networkLines: string[]; + filesystemLines: string[]; +}; +export declare function getRuntimeSummary(pluginConfig: NemoClawConfig): Promise; +export declare function registerRuntimeContext(api: OpenClawPluginApi, pluginConfig: NemoClawConfig): void; +export {}; +//# sourceMappingURL=runtime-context.d.ts.map \ No newline at end of file diff --git a/nemoclaw/dist/runtime-context.d.ts.map b/nemoclaw/dist/runtime-context.d.ts.map new file mode 100644 index 00000000000..782bdc776c1 --- /dev/null +++ b/nemoclaw/dist/runtime-context.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"runtime-context.d.ts","sourceRoot":"","sources":["../src/runtime-context.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AA6BpE,KAAK,cAAc,GAAG;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B,CAAC;AA8RF,wBAAsB,iBAAiB,CAAC,YAAY,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAG7F;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,iBAAiB,EAAE,YAAY,EAAE,cAAc,GAAG,IAAI,CAwBjG"} \ No newline at end of file diff --git a/nemoclaw/dist/runtime-context.js b/nemoclaw/dist/runtime-context.js new file mode 100644 index 00000000000..a99212165ec --- /dev/null +++ b/nemoclaw/dist/runtime-context.js @@ -0,0 +1,262 @@ +"use strict"; +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getRuntimeSummary = getRuntimeSummary; +exports.registerRuntimeContext = registerRuntimeContext; +const node_child_process_1 = require("node:child_process"); +const node_util_1 = require("node:util"); +const yaml_1 = __importDefault(require("yaml")); +const state_js_1 = require("./blueprint/state.js"); +const execFileAsync = (0, node_util_1.promisify)(node_child_process_1.execFile); +const OPEN_SHELL_TIMEOUT_MS = 5000; +const MAX_SUMMARY_RULES = 3; +const MAX_SUMMARY_PATHS = 4; +const sessionRuntimeCache = new Map(); +function getSandboxName(pluginConfig) { + return (0, state_js_1.loadState)().sandboxName ?? pluginConfig.sandboxName; +} +async function execOpenShell(args) { + try { + const { stdout } = await execFileAsync("openshell", args, { + timeout: OPEN_SHELL_TIMEOUT_MS, + maxBuffer: 1024 * 1024, + }); + return stdout.trim() || null; + } + catch { + return null; + } +} +function parseLabeledLine(output, label) { + if (!output) { + return null; + } + const line = output + .split("\n") + .map((value) => value.trim()) + .find((value) => value.startsWith(`${label}:`)); + if (!line) { + return null; + } + const value = line.slice(label.length + 1).trim(); + return value.length > 0 ? value : null; +} +function coerceStringArray(value) { + if (!Array.isArray(value)) { + return []; + } + return value + .filter((entry) => typeof entry === "string" && entry.trim().length > 0) + .map((entry) => entry.trim()); +} +function normalizePolicyYaml(output) { + if (!output) { + return null; + } + const yamlStartMarkers = ["\n---\n", "---\n", "\nversion:", "version:\n", "\nfilesystem_policy:"]; + for (const marker of yamlStartMarkers) { + const index = output.indexOf(marker); + if (index === -1) { + continue; + } + return marker.startsWith("\n") ? output.slice(index + 1).trim() : output.slice(index).trim(); + } + return output.trim(); +} +function describeEndpointAccess(endpoint) { + if (typeof endpoint.access === "string" && endpoint.access.trim().length > 0) { + return endpoint.access.trim(); + } + const rules = Array.isArray(endpoint.rules) ? endpoint.rules : []; + if (rules.length > 0) { + const ruleCount = String(rules.length); + return `${ruleCount} custom rule${rules.length === 1 ? "" : "s"}`; + } + if (typeof endpoint.protocol === "string" && endpoint.protocol.trim().length > 0) { + return endpoint.protocol.trim(); + } + return "explicit allow"; +} +function summarizeNetworkPolicies(policy) { + const entries = Object.entries(policy?.network_policies ?? {}); + if (entries.length === 0) { + return [ + "outbound network is deny-by-default; assume no arbitrary internet access", + "blocked requests can return proxy 403 and may need operator approval or policy changes", + ]; + } + const lines = entries.slice(0, MAX_SUMMARY_RULES).map(([ruleId, entry]) => { + const name = entry.name?.trim() || ruleId; + const endpoint = entry.endpoints?.[0]; + const host = endpoint?.host?.trim() || "unknown-host"; + const port = typeof endpoint?.port === "number" ? endpoint.port : 0; + const destination = port > 0 ? `${host}:${String(port)}` : host; + const access = endpoint ? describeEndpointAccess(endpoint) : "explicit allow"; + const binary = entry.binaries?.[0]?.path?.trim(); + const binaryNote = binary ? ` via ${binary}` : ""; + return `${name}: ${destination} (${access})${binaryNote}`; + }); + if (entries.length > MAX_SUMMARY_RULES) { + lines.push(`${String(entries.length - MAX_SUMMARY_RULES)} additional network rule(s) omitted`); + } + lines.unshift("outbound network is deny-by-default except for the active policy rules below"); + lines.push("if a fetch fails with proxy 403, report it as an OpenShell policy block"); + return lines; +} +function summarizeFilesystem(policy) { + const fsPolicy = policy?.filesystem_policy; + if (!fsPolicy) { + return ["filesystem/process access is sandboxed; do not assume host-level access"]; + } + const lines = ["filesystem/process access is sandboxed; do not assume host-level access"]; + if (fsPolicy.include_workdir === true) { + lines.push("working directory is included in the sandbox policy"); + } + const readWrite = coerceStringArray(fsPolicy.read_write).slice(0, MAX_SUMMARY_PATHS); + if (readWrite.length > 0) { + lines.push(`writable paths include: ${readWrite.join(", ")}`); + } + const readOnly = coerceStringArray(fsPolicy.read_only).slice(0, MAX_SUMMARY_PATHS); + if (readOnly.length > 0) { + lines.push(`read-only paths include: ${readOnly.join(", ")}`); + } + return lines; +} +async function loadPolicyDoc(sandboxName) { + const output = await execOpenShell(["policy", "get", sandboxName, "--full"]); + const yamlText = normalizePolicyYaml(output); + if (!yamlText) { + return null; + } + try { + const parsed = yaml_1.default.parse(yamlText); + if (!parsed || typeof parsed !== "object") { + return null; + } + return parsed; + } + catch { + return null; + } +} +async function getRuntimeSummaryFromFingerprint(fingerprint) { + const policyDoc = await loadPolicyDoc(fingerprint.sandboxName); + return { + sandboxName: fingerprint.sandboxName, + sandboxPhase: fingerprint.sandboxPhase, + networkLines: summarizeNetworkPolicies(policyDoc), + filesystemLines: summarizeFilesystem(policyDoc), + }; +} +async function getRuntimeFingerprint(pluginConfig) { + const sandboxName = getSandboxName(pluginConfig); + const [sandboxOutput, policyOutput] = await Promise.all([ + execOpenShell(["sandbox", "get", sandboxName]), + execOpenShell(["policy", "get", sandboxName]), + ]); + return { + sandboxName, + sandboxPhase: parseLabeledLine(sandboxOutput, "Phase"), + policyVersion: parseLabeledLine(policyOutput, "Version"), + policyHash: parseLabeledLine(policyOutput, "Hash"), + policyStatus: parseLabeledLine(policyOutput, "Status"), + }; +} +function serializeFingerprint(fingerprint) { + return [ + fingerprint.sandboxName, + fingerprint.sandboxPhase ?? "", + fingerprint.policyVersion ?? "", + fingerprint.policyHash ?? "", + fingerprint.policyStatus ?? "", + ].join("|"); +} +function getSessionCacheKey(pluginConfig, hookContext) { + if (hookContext && typeof hookContext === "object") { + const sessionKey = hookContext.sessionKey; + if (typeof sessionKey === "string" && sessionKey.trim().length > 0) { + return sessionKey; + } + } + return `nemoclaw:${getSandboxName(pluginConfig)}`; +} +function buildRuntimeContextText(summary) { + const lines = [ + "", + `You are running inside OpenShell sandbox "${summary.sandboxName}" via NemoClaw.`, + "Treat this as a sandboxed environment, not unrestricted host access.", + summary.sandboxPhase ? `Current sandbox phase: ${summary.sandboxPhase}.` : null, + "Network policy:", + ...summary.networkLines.map((line) => `- ${line}`), + "Filesystem policy:", + ...summary.filesystemLines.map((line) => `- ${line}`), + "Behavior:", + "- do not claim unrestricted internet access", + "- if access is blocked, say it is blocked and ask the operator to adjust policy or approve it in OpenShell", + "", + ].filter((line) => Boolean(line)); + return lines.join("\n"); +} +function buildRuntimeDeltaText(previous, nextFingerprint, nextSummary) { + const lines = [ + "", + "OpenShell sandbox state changed since your earlier NemoClaw context.", + ]; + if (previous.summary.sandboxPhase !== nextFingerprint.sandboxPhase) { + lines.push(`- Sandbox phase: ${previous.summary.sandboxPhase ?? "unknown"} -> ${nextFingerprint.sandboxPhase ?? "unknown"}`); + } + lines.push("- Re-check the current restrictions before claiming what is allowed."); + lines.push("- Active network policy now:"); + lines.push(...nextSummary.networkLines.map((line) => ` - ${line}`)); + lines.push(""); + return lines.join("\n"); +} +async function getCachedRuntimeInjection(pluginConfig, hookContext) { + const fingerprint = await getRuntimeFingerprint(pluginConfig); + const fingerprintKey = serializeFingerprint(fingerprint); + const cacheKey = getSessionCacheKey(pluginConfig, hookContext); + const cached = sessionRuntimeCache.get(cacheKey); + if (cached && cached.fingerprintKey === fingerprintKey) { + return null; + } + const summary = await getRuntimeSummaryFromFingerprint(fingerprint); + sessionRuntimeCache.set(cacheKey, { fingerprintKey, summary }); + if (!cached) { + return buildRuntimeContextText(summary); + } + return buildRuntimeDeltaText(cached, fingerprint, summary); +} +async function getRuntimeSummary(pluginConfig) { + const fingerprint = await getRuntimeFingerprint(pluginConfig); + return getRuntimeSummaryFromFingerprint(fingerprint); +} +function registerRuntimeContext(api, pluginConfig) { + api.on("before_agent_start", async (_event, hookContext) => { + try { + const prependContext = await getCachedRuntimeInjection(pluginConfig, hookContext); + if (!prependContext) { + return undefined; + } + return { + prependContext, + }; + } + catch (err) { + api.logger.warn(`nemoclaw runtime context injection failed: ${String(err)}`); + return { + prependContext: [ + "", + `You are running inside OpenShell sandbox "${getSandboxName(pluginConfig)}" via NemoClaw.`, + "Treat network access as deny-by-default and report proxy 403 responses as policy blocks.", + "Do not claim unrestricted host or internet access.", + "", + ].join("\n"), + }; + } + }); +} +//# sourceMappingURL=runtime-context.js.map \ No newline at end of file diff --git a/nemoclaw/dist/runtime-context.js.map b/nemoclaw/dist/runtime-context.js.map new file mode 100644 index 00000000000..b5e4823a4ea --- /dev/null +++ b/nemoclaw/dist/runtime-context.js.map @@ -0,0 +1 @@ +{"version":3,"file":"runtime-context.js","sourceRoot":"","sources":["../src/runtime-context.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/nemoclaw/src/commands/slash.ts b/nemoclaw/src/commands/slash.ts index f0292eabfb2..1150122bb8f 100644 --- a/nemoclaw/src/commands/slash.ts +++ b/nemoclaw/src/commands/slash.ts @@ -10,19 +10,26 @@ * /nemoclaw - show help */ -import type { PluginCommandContext, PluginCommandResult, OpenClawPluginApi } from "../index.js"; +import type { + PluginCommandContext, + PluginCommandResult, + OpenClawPluginApi, + NemoClawConfig, +} from "../index.js"; import { loadState } from "../blueprint/state.js"; import { loadOnboardConfig } from "../onboard/config.js"; +import { getRuntimeSummary } from "../runtime-context.js"; export function handleSlashCommand( ctx: PluginCommandContext, _api: OpenClawPluginApi, -): PluginCommandResult { + pluginConfig: NemoClawConfig, +): PluginCommandResult | Promise { const subcommand = ctx.args?.trim().split(/\s+/)[0] ?? ""; switch (subcommand) { case "status": - return slashStatus(); + return slashStatus(pluginConfig); case "eject": return slashEject(); case "onboard": @@ -37,10 +44,14 @@ function slashHelp(): PluginCommandResult { text: [ "**NemoClaw**", "", + "OpenClaw runs inside an OpenShell sandbox.", + "Expect sandboxed filesystem/process access and deny-by-default outbound network.", + "Use `openshell term` to watch policy approvals or denials live.", + "", "Usage: `/nemoclaw `", "", "Subcommands:", - " `status` - Show sandbox, blueprint, and inference state", + " `status` - Show sandbox, blueprint, and live restriction summary", " `eject` - Show rollback instructions", " `onboard` - Show onboarding status and instructions", "", @@ -54,12 +65,23 @@ function slashHelp(): PluginCommandResult { }; } -function slashStatus(): PluginCommandResult { +async function slashStatus(pluginConfig: NemoClawConfig): Promise { const state = loadState(); + const runtime = await getRuntimeSummary(pluginConfig); if (!state.lastAction) { return { - text: "**NemoClaw**: No operations performed yet. Run `openclaw nemoclaw launch` or `openclaw nemoclaw migrate` to get started.", + text: [ + "**NemoClaw**: No operations performed yet.", + "Run `openclaw nemoclaw launch` or `openclaw nemoclaw migrate` to get started.", + "", + `Sandbox: ${runtime.sandboxName}`, + runtime.sandboxPhase ? `Phase: ${runtime.sandboxPhase}` : null, + "Restrictions:", + ...runtime.networkLines.slice(0, 2).map((line) => `- ${line}`), + ] + .filter(Boolean) + .join("\n"), }; } @@ -70,7 +92,12 @@ function slashStatus(): PluginCommandResult { `Blueprint: ${state.blueprintVersion ?? "unknown"}`, `Run ID: ${state.lastRunId ?? "none"}`, `Sandbox: ${state.sandboxName ?? "none"}`, + runtime.sandboxPhase ? `Phase: ${runtime.sandboxPhase}` : null, `Updated: ${state.updatedAt}`, + "", + "Restrictions:", + ...runtime.networkLines.map((line) => `- ${line}`), + ...runtime.filesystemLines.map((line) => `- ${line}`), ]; if (state.migrationSnapshot) { diff --git a/nemoclaw/src/index.ts b/nemoclaw/src/index.ts index 796564d8be2..51c889fa45c 100644 --- a/nemoclaw/src/index.ts +++ b/nemoclaw/src/index.ts @@ -15,6 +15,7 @@ import type { Command } from "commander"; import { registerCliCommands } from "./cli.js"; import { handleSlashCommand } from "./commands/slash.js"; import { loadOnboardConfig } from "./onboard/config.js"; +import { registerRuntimeContext } from "./runtime-context.js"; // --------------------------------------------------------------------------- // OpenClaw Plugin SDK compatible types (mirrors openclaw/plugin-sdk) @@ -129,7 +130,7 @@ export interface OpenClawPluginApi { registerProvider: (provider: ProviderPlugin) => void; registerService: (service: PluginService) => void; resolvePath: (input: string) => string; - on: (hookName: string, handler: (...args: unknown[]) => void) => void; + on: (hookName: string, handler: (...args: unknown[]) => Promise) => void; } // --------------------------------------------------------------------------- @@ -177,12 +178,14 @@ export function getPluginConfig(api: OpenClawPluginApi): NemoClawConfig { // --------------------------------------------------------------------------- export default function register(api: OpenClawPluginApi): void { + const pluginConfig = getPluginConfig(api); + // 1. Register /nemoclaw slash command (chat interface) api.registerCommand({ name: "nemoclaw", - description: "NemoClaw sandbox management (status, eject).", + description: "NemoClaw sandbox status, restrictions, and rollback.", acceptsArgs: true, - handler: (ctx) => handleSlashCommand(ctx, api), + handler: (ctx) => handleSlashCommand(ctx, api, pluginConfig), }); // 2. Register `openclaw nemoclaw` CLI subcommands (commander.js) @@ -193,7 +196,10 @@ export default function register(api: OpenClawPluginApi): void { { commands: ["nemoclaw"] }, ); - // 3. Register nvidia-nim provider — use onboard config if available + // 3. Inject live OpenShell sandbox restrictions into agent turns. + registerRuntimeContext(api, pluginConfig); + + // 4. Register nvidia-nim provider — use onboard config if available const onboardCfg = loadOnboardConfig(); const providerCredentialEnv = onboardCfg?.credentialEnv ?? "NVIDIA_API_KEY"; const providerLabel = onboardCfg diff --git a/nemoclaw/src/runtime-context.ts b/nemoclaw/src/runtime-context.ts new file mode 100644 index 00000000000..6b11f8535b4 --- /dev/null +++ b/nemoclaw/src/runtime-context.ts @@ -0,0 +1,356 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { execFile } from "node:child_process"; +import { promisify } from "node:util"; +import YAML from "yaml"; +import type { NemoClawConfig, OpenClawPluginApi } from "./index.js"; +import { loadState } from "./blueprint/state.js"; + +const execFileAsync = promisify(execFile); +const OPEN_SHELL_TIMEOUT_MS = 5000; +const MAX_SUMMARY_RULES = 3; +const MAX_SUMMARY_PATHS = 4; + +type SandboxPolicyDoc = { + filesystem_policy?: { + include_workdir?: boolean; + read_only?: unknown; + read_write?: unknown; + }; + network_policies?: Record; +}; + +type NetworkPolicyEntry = { + name?: string; + endpoints?: Array<{ + host?: string; + port?: number; + protocol?: string; + access?: string; + rules?: Array<{ allow?: { method?: string; path?: string } }>; + }>; + binaries?: Array<{ path?: string }>; +}; + +type RuntimeSummary = { + sandboxName: string; + sandboxPhase: string | null; + networkLines: string[]; + filesystemLines: string[]; +}; + +type RuntimeFingerprint = { + sandboxName: string; + sandboxPhase: string | null; + policyVersion: string | null; + policyHash: string | null; + policyStatus: string | null; +}; + +type SessionRuntimeCacheEntry = { + fingerprintKey: string; + summary: RuntimeSummary; +}; + +type HookContext = { + sessionKey?: string; +}; + +const sessionRuntimeCache = new Map(); + +function getSandboxName(pluginConfig: NemoClawConfig): string { + return loadState().sandboxName ?? pluginConfig.sandboxName; +} + +async function execOpenShell(args: string[]): Promise { + try { + const { stdout } = await execFileAsync("openshell", args, { + timeout: OPEN_SHELL_TIMEOUT_MS, + maxBuffer: 1024 * 1024, + }); + return stdout.trim() || null; + } catch { + return null; + } +} + +function parseLabeledLine(output: string | null, label: string): string | null { + if (!output) { + return null; + } + + const line = output + .split("\n") + .map((value) => value.trim()) + .find((value) => value.startsWith(`${label}:`)); + + if (!line) { + return null; + } + + const value = line.slice(label.length + 1).trim(); + return value.length > 0 ? value : null; +} + +function coerceStringArray(value: unknown): string[] { + if (!Array.isArray(value)) { + return []; + } + + return value + .filter((entry): entry is string => typeof entry === "string" && entry.trim().length > 0) + .map((entry) => entry.trim()); +} + +function normalizePolicyYaml(output: string | null): string | null { + if (!output) { + return null; + } + + const yamlStartMarkers = ["\n---\n", "---\n", "\nversion:", "version:\n", "\nfilesystem_policy:"]; + for (const marker of yamlStartMarkers) { + const index = output.indexOf(marker); + if (index === -1) { + continue; + } + return marker.startsWith("\n") ? output.slice(index + 1).trim() : output.slice(index).trim(); + } + + return output.trim(); +} + +function describeEndpointAccess(endpoint: NonNullable[number]): string { + if (typeof endpoint.access === "string" && endpoint.access.trim().length > 0) { + return endpoint.access.trim(); + } + + const rules = Array.isArray(endpoint.rules) ? endpoint.rules : []; + if (rules.length > 0) { + const ruleCount = String(rules.length); + return `${ruleCount} custom rule${rules.length === 1 ? "" : "s"}`; + } + + if (typeof endpoint.protocol === "string" && endpoint.protocol.trim().length > 0) { + return endpoint.protocol.trim(); + } + + return "explicit allow"; +} + +function summarizeNetworkPolicies(policy: SandboxPolicyDoc | null): string[] { + const entries = Object.entries(policy?.network_policies ?? {}); + if (entries.length === 0) { + return [ + "outbound network is deny-by-default; assume no arbitrary internet access", + "blocked requests can return proxy 403 and may need operator approval or policy changes", + ]; + } + + const lines = entries.slice(0, MAX_SUMMARY_RULES).map(([ruleId, entry]) => { + const name = entry.name?.trim() || ruleId; + const endpoint = entry.endpoints?.[0]; + const host = endpoint?.host?.trim() || "unknown-host"; + const port = typeof endpoint?.port === "number" ? endpoint.port : 0; + const destination = port > 0 ? `${host}:${String(port)}` : host; + const access = endpoint ? describeEndpointAccess(endpoint) : "explicit allow"; + const binary = entry.binaries?.[0]?.path?.trim(); + const binaryNote = binary ? ` via ${binary}` : ""; + return `${name}: ${destination} (${access})${binaryNote}`; + }); + + if (entries.length > MAX_SUMMARY_RULES) { + lines.push(`${String(entries.length - MAX_SUMMARY_RULES)} additional network rule(s) omitted`); + } + + lines.unshift("outbound network is deny-by-default except for the active policy rules below"); + lines.push("if a fetch fails with proxy 403, report it as an OpenShell policy block"); + return lines; +} + +function summarizeFilesystem(policy: SandboxPolicyDoc | null): string[] { + const fsPolicy = policy?.filesystem_policy; + if (!fsPolicy) { + return ["filesystem/process access is sandboxed; do not assume host-level access"]; + } + + const lines = ["filesystem/process access is sandboxed; do not assume host-level access"]; + if (fsPolicy.include_workdir === true) { + lines.push("working directory is included in the sandbox policy"); + } + + const readWrite = coerceStringArray(fsPolicy.read_write).slice(0, MAX_SUMMARY_PATHS); + if (readWrite.length > 0) { + lines.push(`writable paths include: ${readWrite.join(", ")}`); + } + + const readOnly = coerceStringArray(fsPolicy.read_only).slice(0, MAX_SUMMARY_PATHS); + if (readOnly.length > 0) { + lines.push(`read-only paths include: ${readOnly.join(", ")}`); + } + + return lines; +} + +async function loadPolicyDoc(sandboxName: string): Promise { + const output = await execOpenShell(["policy", "get", sandboxName, "--full"]); + const yamlText = normalizePolicyYaml(output); + if (!yamlText) { + return null; + } + + try { + const parsed: unknown = YAML.parse(yamlText); + if (!parsed || typeof parsed !== "object") { + return null; + } + return parsed as SandboxPolicyDoc; + } catch { + return null; + } +} + +async function getRuntimeSummaryFromFingerprint( + fingerprint: RuntimeFingerprint, +): Promise { + const policyDoc = await loadPolicyDoc(fingerprint.sandboxName); + return { + sandboxName: fingerprint.sandboxName, + sandboxPhase: fingerprint.sandboxPhase, + networkLines: summarizeNetworkPolicies(policyDoc), + filesystemLines: summarizeFilesystem(policyDoc), + }; +} + +async function getRuntimeFingerprint(pluginConfig: NemoClawConfig): Promise { + const sandboxName = getSandboxName(pluginConfig); + const [sandboxOutput, policyOutput] = await Promise.all([ + execOpenShell(["sandbox", "get", sandboxName]), + execOpenShell(["policy", "get", sandboxName]), + ]); + + return { + sandboxName, + sandboxPhase: parseLabeledLine(sandboxOutput, "Phase"), + policyVersion: parseLabeledLine(policyOutput, "Version"), + policyHash: parseLabeledLine(policyOutput, "Hash"), + policyStatus: parseLabeledLine(policyOutput, "Status"), + }; +} + +function serializeFingerprint(fingerprint: RuntimeFingerprint): string { + return [ + fingerprint.sandboxName, + fingerprint.sandboxPhase ?? "", + fingerprint.policyVersion ?? "", + fingerprint.policyHash ?? "", + fingerprint.policyStatus ?? "", + ].join("|"); +} + +function getSessionCacheKey(pluginConfig: NemoClawConfig, hookContext: unknown): string { + if (hookContext && typeof hookContext === "object") { + const sessionKey = (hookContext as HookContext).sessionKey; + if (typeof sessionKey === "string" && sessionKey.trim().length > 0) { + return sessionKey; + } + } + + return `nemoclaw:${getSandboxName(pluginConfig)}`; +} + +function buildRuntimeContextText(summary: RuntimeSummary): string { + const lines = [ + "", + `You are running inside OpenShell sandbox "${summary.sandboxName}" via NemoClaw.`, + "Treat this as a sandboxed environment, not unrestricted host access.", + summary.sandboxPhase ? `Current sandbox phase: ${summary.sandboxPhase}.` : null, + "Network policy:", + ...summary.networkLines.map((line) => `- ${line}`), + "Filesystem policy:", + ...summary.filesystemLines.map((line) => `- ${line}`), + "Behavior:", + "- do not claim unrestricted internet access", + "- if access is blocked, say it is blocked and ask the operator to adjust policy or approve it in OpenShell", + "", + ].filter((line): line is string => Boolean(line)); + + return lines.join("\n"); +} + +function buildRuntimeDeltaText( + previous: SessionRuntimeCacheEntry, + nextFingerprint: RuntimeFingerprint, + nextSummary: RuntimeSummary, +): string { + const lines = [ + "", + "OpenShell sandbox state changed since your earlier NemoClaw context.", + ]; + + if (previous.summary.sandboxPhase !== nextFingerprint.sandboxPhase) { + lines.push( + `- Sandbox phase: ${previous.summary.sandboxPhase ?? "unknown"} -> ${nextFingerprint.sandboxPhase ?? "unknown"}`, + ); + } + + lines.push("- Re-check the current restrictions before claiming what is allowed."); + lines.push("- Active network policy now:"); + lines.push(...nextSummary.networkLines.map((line) => ` - ${line}`)); + lines.push(""); + return lines.join("\n"); +} + +async function getCachedRuntimeInjection( + pluginConfig: NemoClawConfig, + hookContext: unknown, +): Promise { + const fingerprint = await getRuntimeFingerprint(pluginConfig); + const fingerprintKey = serializeFingerprint(fingerprint); + const cacheKey = getSessionCacheKey(pluginConfig, hookContext); + const cached = sessionRuntimeCache.get(cacheKey); + + if (cached && cached.fingerprintKey === fingerprintKey) { + return null; + } + + const summary = await getRuntimeSummaryFromFingerprint(fingerprint); + sessionRuntimeCache.set(cacheKey, { fingerprintKey, summary }); + + if (!cached) { + return buildRuntimeContextText(summary); + } + + return buildRuntimeDeltaText(cached, fingerprint, summary); +} + +export async function getRuntimeSummary(pluginConfig: NemoClawConfig): Promise { + const fingerprint = await getRuntimeFingerprint(pluginConfig); + return getRuntimeSummaryFromFingerprint(fingerprint); +} + +export function registerRuntimeContext(api: OpenClawPluginApi, pluginConfig: NemoClawConfig): void { + api.on("before_agent_start", async (_event, hookContext) => { + try { + const prependContext = await getCachedRuntimeInjection(pluginConfig, hookContext); + if (!prependContext) { + return undefined; + } + + return { + prependContext, + }; + } catch (err) { + api.logger.warn(`nemoclaw runtime context injection failed: ${String(err)}`); + return { + prependContext: [ + "", + `You are running inside OpenShell sandbox "${getSandboxName(pluginConfig)}" via NemoClaw.`, + "Treat network access as deny-by-default and report proxy 403 responses as policy blocks.", + "Do not claim unrestricted host or internet access.", + "", + ].join("\n"), + }; + } + }); +} From b4c66bf044f71beee6611ddd0922b5e6cf263220 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Mon, 16 Mar 2026 01:17:49 -0700 Subject: [PATCH 7/7] Refactor: rework sandbox bootstrap around runtime context Signed-off-by: Vincent Koc --- Dockerfile | 3 +- README.md | 10 +- docs/reference/commands.md | 9 +- nemoclaw/dist/commands/connect.js | 4 +- nemoclaw/dist/commands/connect.js.map | 2 +- .../dist/commands/sandbox-bootstrap.d.ts.map | 2 +- nemoclaw/dist/commands/sandbox-bootstrap.js | 3 +- .../dist/commands/sandbox-bootstrap.js.map | 2 +- nemoclaw/src/commands/connect.ts | 4 +- nemoclaw/src/commands/sandbox-bootstrap.ts | 3 +- scripts/nemoclaw-gateway.sh | 167 ---------- scripts/walkthrough.sh | 6 +- test/Dockerfile.sandbox | 3 +- test/e2e-test.sh | 296 +++++++++++++----- 14 files changed, 250 insertions(+), 264 deletions(-) delete mode 100755 scripts/nemoclaw-gateway.sh diff --git a/Dockerfile b/Dockerfile index 00b2ef433af..c0b6d5e9b8b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -39,8 +39,7 @@ RUN mkdir -p /sandbox/.nemoclaw/blueprints/0.1.0 \ # Copy startup scripts and force read+execute bits for the sandbox user. COPY scripts/nemoclaw-start.sh /usr/local/bin/nemoclaw-start COPY scripts/nemoclaw-shell.sh /usr/local/bin/nemoclaw-shell -COPY scripts/nemoclaw-gateway.sh /usr/local/bin/nemoclaw-gateway.sh -RUN chmod 755 /usr/local/bin/nemoclaw-start /usr/local/bin/nemoclaw-shell /usr/local/bin/nemoclaw-gateway.sh +RUN chmod 755 /usr/local/bin/nemoclaw-start /usr/local/bin/nemoclaw-shell WORKDIR /sandbox diff --git a/README.md b/README.md index 8200d9c6572..311a3279a0d 100644 --- a/README.md +++ b/README.md @@ -23,11 +23,10 @@ First run prompts for your NVIDIA API Key (get one from [build.nvidia.com](https - [OpenShell CLI](https://github.com/NVIDIA/OpenShell/releases) (binary download) The repo-owned sandbox image stays simple and non-root at rest. -Headless bootstrap runs `openclaw setup`, then `nemoclaw-gateway.sh ensure` -inside the sandbox. That helper uses `~/.openclaw/run/gateway.pid` and -`~/.openclaw/run/gateway.lock` to keep exactly one direct -`openclaw gateway run --force` process alive without requiring systemd or -root-only service installation. +Headless bootstrap runs `openclaw setup`, then `openclaw gateway install --json` +inside the sandbox. If the sandbox cannot host user-systemd, NemoClaw falls +back to a direct background `openclaw gateway run` process so the gateway auth +token and runtime still exist before first connect. ### Ubuntu 24.04 (fresh install) @@ -230,7 +229,6 @@ nemoclaw-blueprint/ Versioned blueprint artifact (separate relea | `scripts/setup.sh` | Host-side setup — gateway, providers, inference route, sandbox | | `scripts/brev-setup.sh` | Brev bootstrap — installs prerequisites, then runs `setup.sh` | | `scripts/nemoclaw-shell.sh` | Thin shell wrapper — runs commands inside the sandbox as the current user | -| `scripts/nemoclaw-gateway.sh` | Gateway process manager — `ensure`, `status`, `stop` using PID + lock files | | `scripts/nemoclaw-start.sh` | Sandbox startup helper — configures OpenClaw, installs plugin | | `scripts/walkthrough.sh` | Split-screen walkthrough — agent + TUI approval flow | | `scripts/fix-coredns.sh` | CoreDNS patch for Colima environments | diff --git a/docs/reference/commands.md b/docs/reference/commands.md index 91976804d03..31cf3cb12b6 100644 --- a/docs/reference/commands.md +++ b/docs/reference/commands.md @@ -31,13 +31,12 @@ Both interfaces are installed when you run `npm install -g nemoclaw`. Bootstrap a fresh OpenClaw installation inside an OpenShell sandbox. After provisioning the sandbox, NemoClaw runs `openclaw setup` and -`nemoclaw-gateway.sh ensure` inside it so the config, workspace, sessions, -gateway auth token, and direct Gateway process all exist before first use. +`openclaw gateway install --json` inside it so the config, workspace, sessions, +and gateway auth token all exist before first use. If NemoClaw detects an existing host installation, `launch` stops and points you to `openclaw nemoclaw migrate` unless you pass `--force`. -The Gateway manager uses `~/.openclaw/run/gateway.pid` and -`~/.openclaw/run/gateway.lock` so headless bootstrap stays non-interactive and -does not depend on systemd or root-only service installation. +If the sandbox does not support user-systemd, NemoClaw falls back to a direct +background gateway process so headless bootstrap still completes without root. ```console $ openclaw nemoclaw launch [--force] [--profile ] diff --git a/nemoclaw/dist/commands/connect.js b/nemoclaw/dist/commands/connect.js index 508b3b1319a..ff783176560 100644 --- a/nemoclaw/dist/commands/connect.js +++ b/nemoclaw/dist/commands/connect.js @@ -7,11 +7,11 @@ const node_child_process_1 = require("node:child_process"); async function cliConnect(opts) { const { sandbox: sandboxName, logger } = opts; logger.info(`Connecting to OpenClaw sandbox: ${sandboxName}`); - logger.info("You will be inside the sandbox. Run 'openclaw' commands normally."); + logger.info("You will be inside the sandbox as the sandbox user. Run 'openclaw' commands normally."); logger.info("Type 'exit' to return to your host shell."); logger.info(""); const exitCode = await new Promise((resolve) => { - const proc = (0, node_child_process_1.spawn)("openshell", ["sandbox", "connect", sandboxName], { + const proc = (0, node_child_process_1.spawn)("openshell", ["sandbox", "connect", sandboxName, "--", "nemoclaw-shell"], { stdio: "inherit", }); proc.on("close", resolve); diff --git a/nemoclaw/dist/commands/connect.js.map b/nemoclaw/dist/commands/connect.js.map index 199bf5c6266..0d375cbb052 100644 --- a/nemoclaw/dist/commands/connect.js.map +++ b/nemoclaw/dist/commands/connect.js.map @@ -1 +1 @@ -{"version":3,"file":"connect.js","sourceRoot":"","sources":["../../src/commands/connect.ts"],"names":[],"mappings":";AAAA,mGAAmG;AACnG,sCAAsC;;AAUtC,gCA2BC;AAnCD,2DAA2C;AAQpC,KAAK,UAAU,UAAU,CAAC,IAAoB;IACnD,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAE9C,MAAM,CAAC,IAAI,CAAC,mCAAmC,WAAW,EAAE,CAAC,CAAC;IAC9D,MAAM,CAAC,IAAI,CAAC,mEAAmE,CAAC,CAAC;IACjF,MAAM,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;IACzD,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEhB,MAAM,QAAQ,GAAG,MAAM,IAAI,OAAO,CAAgB,CAAC,OAAO,EAAE,EAAE;QAC5D,MAAM,IAAI,GAAG,IAAA,0BAAK,EAAC,WAAW,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,WAAW,CAAC,EAAE;YACnE,KAAK,EAAE,SAAS;SACjB,CAAC,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC1B,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACvB,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACnC,MAAM,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;YACnE,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,KAAK,CAAC,sBAAsB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YACpD,CAAC;YACD,OAAO,CAAC,CAAC,CAAC,CAAC;QACb,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAI,QAAQ,KAAK,CAAC,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACxC,MAAM,CAAC,KAAK,CAAC,YAAY,WAAW,sBAAsB,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC/E,MAAM,CAAC,IAAI,CAAC,8DAA8D,CAAC,CAAC;IAC9E,CAAC;AACH,CAAC"} \ No newline at end of file +{"version":3,"file":"connect.js","sourceRoot":"","sources":["../../src/commands/connect.ts"],"names":[],"mappings":";AAAA,mGAAmG;AACnG,sCAAsC;;AAUtC,gCA2BC;AAnCD,2DAA2C;AAQpC,KAAK,UAAU,UAAU,CAAC,IAAoB;IACnD,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAE9C,MAAM,CAAC,IAAI,CAAC,mCAAmC,WAAW,EAAE,CAAC,CAAC;IAC9D,MAAM,CAAC,IAAI,CAAC,uFAAuF,CAAC,CAAC;IACrG,MAAM,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;IACzD,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEhB,MAAM,QAAQ,GAAG,MAAM,IAAI,OAAO,CAAgB,CAAC,OAAO,EAAE,EAAE;QAC5D,MAAM,IAAI,GAAG,IAAA,0BAAK,EAAC,WAAW,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,gBAAgB,CAAC,EAAE;YAC3F,KAAK,EAAE,SAAS;SACjB,CAAC,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC1B,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACvB,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACnC,MAAM,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;YACnE,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,KAAK,CAAC,sBAAsB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YACpD,CAAC;YACD,OAAO,CAAC,CAAC,CAAC,CAAC;QACb,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAI,QAAQ,KAAK,CAAC,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACxC,MAAM,CAAC,KAAK,CAAC,YAAY,WAAW,sBAAsB,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC/E,MAAM,CAAC,IAAI,CAAC,8DAA8D,CAAC,CAAC;IAC9E,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/nemoclaw/dist/commands/sandbox-bootstrap.d.ts.map b/nemoclaw/dist/commands/sandbox-bootstrap.d.ts.map index 1bc7df9aeab..9220a4ee97a 100644 --- a/nemoclaw/dist/commands/sandbox-bootstrap.d.ts.map +++ b/nemoclaw/dist/commands/sandbox-bootstrap.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"sandbox-bootstrap.d.ts","sourceRoot":"","sources":["../../src/commands/sandbox-bootstrap.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIhD,MAAM,WAAW,qCAAqC;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,YAAY,CAAC;CACtB;AAkJD,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,qCAAqC,GAC1C,OAAO,CA8CT"} \ No newline at end of file +{"version":3,"file":"sandbox-bootstrap.d.ts","sourceRoot":"","sources":["../../src/commands/sandbox-bootstrap.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIhD,MAAM,WAAW,qCAAqC;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,YAAY,CAAC;CACtB;AAmJD,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,qCAAqC,GAC1C,OAAO,CA8CT"} \ No newline at end of file diff --git a/nemoclaw/dist/commands/sandbox-bootstrap.js b/nemoclaw/dist/commands/sandbox-bootstrap.js index 0b0117f4e49..9738cd7093f 100644 --- a/nemoclaw/dist/commands/sandbox-bootstrap.js +++ b/nemoclaw/dist/commands/sandbox-bootstrap.js @@ -14,7 +14,8 @@ function isSystemdUnavailableDetail(detail) { normalized.includes("systemd user services are required") || normalized.includes("failed to connect to bus") || normalized.includes("dbus_session_bus_address") || - normalized.includes("xdg_runtime_dir")); + normalized.includes("xdg_runtime_dir") || + normalized.includes("system has not been booted with systemd")); } function readExecStream(value) { if (typeof value === "string") { diff --git a/nemoclaw/dist/commands/sandbox-bootstrap.js.map b/nemoclaw/dist/commands/sandbox-bootstrap.js.map index 70130a5c232..edd4972d83d 100644 --- a/nemoclaw/dist/commands/sandbox-bootstrap.js.map +++ b/nemoclaw/dist/commands/sandbox-bootstrap.js.map @@ -1 +1 @@ -{"version":3,"file":"sandbox-bootstrap.js","sourceRoot":"","sources":["../../src/commands/sandbox-bootstrap.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"sandbox-bootstrap.js","sourceRoot":"","sources":["../../src/commands/sandbox-bootstrap.ts"],"names":[],"mappings":";AAAA,mGAAmG;AACnG,sCAAsC;;AA8JtC,wEAgDC;AA5MD,2DAAkD;AAClD,qCAA6D;AAE7D,qCAAiC;AACjC,yCAAiC;AAoBjC,SAAS,0BAA0B,CAAC,MAAc;IAChD,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IACxC,OAAO,CACL,UAAU,CAAC,QAAQ,CAAC,8BAA8B,CAAC;QACnD,UAAU,CAAC,QAAQ,CAAC,yBAAyB,CAAC;QAC9C,UAAU,CAAC,QAAQ,CAAC,oCAAoC,CAAC;QACzD,UAAU,CAAC,QAAQ,CAAC,0BAA0B,CAAC;QAC/C,UAAU,CAAC,QAAQ,CAAC,0BAA0B,CAAC;QAC/C,UAAU,CAAC,QAAQ,CAAC,iBAAiB,CAAC;QACtC,UAAU,CAAC,QAAQ,CAAC,yCAAyC,CAAC,CAC/D,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,KAAc;IACpC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC;IACtB,CAAC;IACD,IAAI,KAAK,YAAY,MAAM,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IACxC,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,oBAAoB,CAC3B,WAAmB,EACnB,UAAoB;IAEpB,MAAM,MAAM,GAAG,IAAA,qBAAW,EAAC,IAAA,gBAAI,EAAC,IAAA,gBAAM,GAAE,EAAE,eAAe,CAAC,CAAC,CAAC;IAC5D,MAAM,UAAU,GAAG,IAAA,gBAAI,EAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAE1C,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,IAAA,iCAAY,EAAC,WAAW,EAAE,CAAC,SAAS,EAAE,YAAY,EAAE,WAAW,CAAC,EAAE;YAClF,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;SAClC,CAAC,CAAC;QACH,IAAA,uBAAa,EAAC,UAAU,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAEtD,MAAM,IAAI,GACR,SAAS;aACN,KAAK,CAAC,IAAI,CAAC;aACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;aAC1B,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YACzC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,aAAa,WAAW,EAAE,CAAC;QAEpD,MAAM,aAAa,GAAG,UAAU;aAC7B,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC;aACjD,IAAI,CAAC,GAAG,CAAC,CAAC;QAEb,MAAM,MAAM,GAAG,IAAA,iCAAY,EAAC,KAAK,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,aAAa,CAAC,EAAE;YAC1E,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;SAClC,CAAC,CAAC;QACH,OAAO;YACL,EAAE,EAAE,IAAI;YACR,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE;YACrB,MAAM,EAAE,EAAE;YACV,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE;SACtB,CAAC;IACJ,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,MAAM,GACV,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,QAAQ,IAAI,GAAG;YAC/C,CAAC,CAAC,cAAc,CAAE,GAA4B,CAAC,MAAM,CAAC;YACtD,CAAC,CAAC,EAAE,CAAC;QACT,MAAM,MAAM,GACV,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,QAAQ,IAAI,GAAG;YAC/C,CAAC,CAAC,cAAc,CAAE,GAA4B,CAAC,MAAM,CAAC;YACtD,CAAC,CAAC,EAAE,CAAC;QACT,MAAM,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC;QAC/C,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM;YACN,MAAM;YACN,MAAM;SACP,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,IAAA,gBAAM,EAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC;AACH,CAAC;AAED,SAAS,yBAAyB,CAChC,WAAmB,EACnB,IAAc;IAEd,OAAO,oBAAoB,CAAC,WAAW,EAAE,CAAC,gBAAgB,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;AACpF,CAAC;AAED,SAAS,uBAAuB,CAAC,MAAc;IAC7C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAuB,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,sBAAsB,CAAC,WAAmB,EAAE,MAAc;IACjE,OAAO,oBAAoB,CAAC,WAAW,EAAE,CAAC,gBAAgB,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;AACpF,CAAC;AAED,SAAS,wBAAwB,CAAC,WAAmB,EAAE,OAAe;IACpE,OAAO,gCAAgC,WAAW,WAAW,WAAW,uBAAuB,WAAW,kBAAkB,WAAW,mBAAmB,OAAO,EAAE,CAAC;AACtK,CAAC;AAED,SAAS,iCAAiC,CACxC,WAAmB,EACnB,MAAoB;IAEpB,MAAM,CAAC,IAAI,CACT,mJAAmJ,CACpJ,CAAC;IACF,OAAO,sBAAsB,CAC3B,WAAW,EACX;QACE,iCAAiC;QACjC,2DAA2D;QAC3D,qFAAqF;QACrF,IAAI;QACJ,8BAA8B;QAC9B,2DAA2D;QAC3D,0BAA0B;QAC1B,YAAY;QACZ,MAAM;QACN,WAAW;QACX,MAAM;QACN,8BAA8B;QAC9B,QAAQ;KACT,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;AACJ,CAAC;AAED,SAAgB,8BAA8B,CAC5C,IAA2C;IAE3C,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAErC,MAAM,KAAK,GAAG,yBAAyB,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAChE,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;QACd,MAAM,CAAC,KAAK,CAAC,qDAAqD,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QAClF,MAAM,CAAC,IAAI,CAAC,mCAAmC,wBAAwB,CAAC,WAAW,EAAE,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAC5G,OAAO,KAAK,CAAC;IACf,CAAC;IAED,2EAA2E;IAC3E,wEAAwE;IACxE,MAAM,OAAO,GAAG,yBAAyB,CAAC,WAAW,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;IACzF,MAAM,MAAM,GAAG,uBAAuB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACvD,MAAM,cAAc,GAAG,CAAC,OAAO,CAAC,EAAE,IAAI,MAAM,EAAE,EAAE,KAAK,KAAK,CAAC;IAC3D,MAAM,oBAAoB,GAAG,MAAM,EAAE,OAAO,IAAI,OAAO,CAAC,MAAM,IAAI,iCAAiC,CAAC;IAEpG,IAAI,cAAc,IAAI,0BAA0B,CAAC,oBAAoB,CAAC,EAAE,CAAC;QACvE,MAAM,QAAQ,GAAG,iCAAiC,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QACxE,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,CAAC,KAAK,CAAC,wDAAwD,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;YACxF,MAAM,CAAC,IAAI,CACT,mCAAmC,wBAAwB,CAAC,WAAW,EAAE,sBAAsB,CAAC,IAAI,CACrG,CAAC;YACF,OAAO,KAAK,CAAC;QACf,CAAC;QACD,KAAK,MAAM,OAAO,IAAI,MAAM,EAAE,QAAQ,IAAI,EAAE,EAAE,CAAC;YAC7C,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvB,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,kFAAkF,CAAC,CAAC;QAChG,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,cAAc,EAAE,CAAC;QACnB,MAAM,CAAC,KAAK,CAAC,kDAAkD,oBAAoB,EAAE,CAAC,CAAC;QACvF,MAAM,CAAC,IAAI,CACT,mCAAmC,wBAAwB,CAAC,WAAW,EAAE,0BAA0B,CAAC,IAAI,CACzG,CAAC;QACF,OAAO,KAAK,CAAC;IACf,CAAC;IACD,KAAK,MAAM,OAAO,IAAI,MAAM,EAAE,QAAQ,IAAI,EAAE,EAAE,CAAC;QAC7C,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,mFAAmF,CAAC,CAAC;IACjG,OAAO,IAAI,CAAC;AACd,CAAC"} \ No newline at end of file diff --git a/nemoclaw/src/commands/connect.ts b/nemoclaw/src/commands/connect.ts index bb37b916702..07106de4ce4 100644 --- a/nemoclaw/src/commands/connect.ts +++ b/nemoclaw/src/commands/connect.ts @@ -13,12 +13,12 @@ export async function cliConnect(opts: ConnectOptions): Promise { const { sandbox: sandboxName, logger } = opts; logger.info(`Connecting to OpenClaw sandbox: ${sandboxName}`); - logger.info("You will be inside the sandbox. Run 'openclaw' commands normally."); + logger.info("You will be inside the sandbox as the sandbox user. Run 'openclaw' commands normally."); logger.info("Type 'exit' to return to your host shell."); logger.info(""); const exitCode = await new Promise((resolve) => { - const proc = spawn("openshell", ["sandbox", "connect", sandboxName], { + const proc = spawn("openshell", ["sandbox", "connect", sandboxName, "--", "nemoclaw-shell"], { stdio: "inherit", }); proc.on("close", resolve); diff --git a/nemoclaw/src/commands/sandbox-bootstrap.ts b/nemoclaw/src/commands/sandbox-bootstrap.ts index 1a0840a35b5..e495828f8ae 100644 --- a/nemoclaw/src/commands/sandbox-bootstrap.ts +++ b/nemoclaw/src/commands/sandbox-bootstrap.ts @@ -33,7 +33,8 @@ function isSystemdUnavailableDetail(detail: string): boolean { normalized.includes("systemd user services are required") || normalized.includes("failed to connect to bus") || normalized.includes("dbus_session_bus_address") || - normalized.includes("xdg_runtime_dir") + normalized.includes("xdg_runtime_dir") || + normalized.includes("system has not been booted with systemd") ); } diff --git a/scripts/nemoclaw-gateway.sh b/scripts/nemoclaw-gateway.sh deleted file mode 100755 index 1d9ba59dcb5..00000000000 --- a/scripts/nemoclaw-gateway.sh +++ /dev/null @@ -1,167 +0,0 @@ -#!/usr/bin/env bash -# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 - -set -euo pipefail - -command_name="${1:-ensure}" - -RUNDIR="${HOME}/.openclaw/run" -LOGDIR="${HOME}/.openclaw/logs" -PIDFILE="${RUNDIR}/gateway.pid" -LOCKFILE="${RUNDIR}/gateway.lock" -LOGFILE="${LOGDIR}/gateway.log" - -mkdir -p "$RUNDIR" "$LOGDIR" - -info() { printf '%s\n' "$1"; } -warn() { printf 'WARN: %s\n' "$1" >&2; } -fail() { printf 'ERROR: %s\n' "$1" >&2; exit 1; } - -read_pid() { - if [ -f "$PIDFILE" ]; then - tr -d '\n' <"$PIDFILE" - fi -} - -pid_running() { - local pid="${1:-}" - [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null -} - -gateway_healthy() { - openclaw gateway status --deep >/dev/null 2>&1 -} - -clear_stale_pidfile() { - local pid - pid="$(read_pid || true)" - if [ -n "$pid" ] && ! pid_running "$pid"; then - rm -f "$PIDFILE" - fi -} - -acquire_lock() { - if ( set -o noclobber; printf '%s\n' "$$" >"$LOCKFILE" ) 2>/dev/null; then - trap 'rm -f "$LOCKFILE"' EXIT INT TERM - return 0 - fi - - local lock_pid="" - if [ -f "$LOCKFILE" ]; then - lock_pid="$(tr -d '\n' <"$LOCKFILE" 2>/dev/null || true)" - fi - if [ -n "$lock_pid" ] && pid_running "$lock_pid"; then - for _ in 1 2 3 4 5 6 7 8; do - if gateway_healthy; then - return 0 - fi - sleep 1 - done - fail "gateway bootstrap is already running under PID ${lock_pid}" - fi - - printf '%s\n' "$$" >"$LOCKFILE" - trap 'rm -f "$LOCKFILE"' EXIT INT TERM -} - -start_gateway() { - nohup openclaw gateway run >"$LOGFILE" 2>&1 < /dev/null & - local pid=$! - printf '%s\n' "$pid" >"$PIDFILE" - info "started-gateway:${pid}" -} - -ensure_gateway() { - acquire_lock - clear_stale_pidfile - - if gateway_healthy; then - local existing_pid - existing_pid="$(read_pid || true)" - if [ -n "$existing_pid" ] && pid_running "$existing_pid"; then - info "gateway-ready:${existing_pid}" - else - info "gateway-ready:external" - fi - return 0 - fi - - local pid - pid="$(read_pid || true)" - if [ -z "$pid" ] || ! pid_running "$pid"; then - start_gateway - pid="$(read_pid || true)" - fi - - for _ in 1 2 3 4 5 6 7 8; do - if gateway_healthy; then - info "gateway-ready:${pid:-unknown}" - return 0 - fi - if [ -n "$pid" ] && ! pid_running "$pid"; then - warn "gateway process exited before becoming healthy" - break - fi - sleep 2 - done - - fail "gateway failed to become healthy; see ${LOGFILE}" -} - -status_gateway() { - clear_stale_pidfile - local pid - pid="$(read_pid || true)" - local state="stopped" - if [ -n "$pid" ] && pid_running "$pid"; then - state="running" - fi - local health="unhealthy" - if gateway_healthy; then - health="healthy" - fi - printf 'state=%s\n' "$state" - printf 'health=%s\n' "$health" - printf 'pid=%s\n' "${pid:-}" - printf 'log=%s\n' "$LOGFILE" -} - -stop_gateway() { - clear_stale_pidfile - local pid - pid="$(read_pid || true)" - if [ -z "$pid" ]; then - info "gateway-not-running" - return 0 - fi - if pid_running "$pid"; then - kill "$pid" 2>/dev/null || true - for _ in 1 2 3 4 5; do - if ! pid_running "$pid"; then - break - fi - sleep 1 - done - if pid_running "$pid"; then - kill -9 "$pid" 2>/dev/null || true - fi - fi - rm -f "$PIDFILE" - info "gateway-stopped:${pid}" -} - -case "$command_name" in - ensure) - ensure_gateway - ;; - status) - status_gateway - ;; - stop) - stop_gateway - ;; - *) - fail "usage: nemoclaw-gateway.sh [ensure|status|stop]" - ;; -esac diff --git a/scripts/walkthrough.sh b/scripts/walkthrough.sh index 8dcbf923911..a434187d89b 100755 --- a/scripts/walkthrough.sh +++ b/scripts/walkthrough.sh @@ -36,7 +36,7 @@ # openshell term # # Terminal 2 (Agent): -# openshell sandbox connect nemoclaw +# openshell sandbox connect nemoclaw -- nemoclaw-shell # export NVIDIA_API_KEY=nvapi-... # nemoclaw-start # openclaw agent --agent main --local --session-id live @@ -68,7 +68,7 @@ if ! command -v tmux > /dev/null 2>&1; then echo " openshell term" echo "" echo " Terminal 2 (Agent):" - echo " openshell sandbox connect nemoclaw" + echo " openshell sandbox connect nemoclaw -- nemoclaw-shell" echo " export NVIDIA_API_KEY=$NVIDIA_API_KEY" echo " nemoclaw-start" echo " openclaw agent --agent main --local --session-id live" @@ -85,7 +85,7 @@ tmux new-session -d -s "$SESSION" -x 200 -y 50 "openshell term" # Split right pane for the agent tmux split-window -h -t "$SESSION" \ - "openshell sandbox connect nemoclaw -- bash -c 'export NVIDIA_API_KEY=$NVIDIA_API_KEY && nemoclaw-start openclaw agent --agent main --local --session-id live'" + "openshell sandbox connect nemoclaw -- nemoclaw-shell bash -lc 'export NVIDIA_API_KEY=$NVIDIA_API_KEY && nemoclaw-start openclaw agent --agent main --local --session-id live'" # Even split tmux select-layout -t "$SESSION" even-horizontal diff --git a/test/Dockerfile.sandbox b/test/Dockerfile.sandbox index 7d963efb9af..abf4db7099d 100644 --- a/test/Dockerfile.sandbox +++ b/test/Dockerfile.sandbox @@ -33,8 +33,7 @@ WORKDIR /opt/nemoclaw RUN npm install && rm -rf dist && npx tsc COPY scripts/nemoclaw-shell.sh /usr/local/bin/nemoclaw-shell -COPY scripts/nemoclaw-gateway.sh /usr/local/bin/nemoclaw-gateway.sh -RUN chmod +x /usr/local/bin/nemoclaw-shell /usr/local/bin/nemoclaw-gateway.sh +RUN chmod +x /usr/local/bin/nemoclaw-shell # Patch OpenClaw's nvidia provider to replace Meta Llama 3.3 70B with # Nemotron 3 Super 120B. OpenClaw's embedded agent has a hardcoded model diff --git a/test/e2e-test.sh b/test/e2e-test.sh index 880b3d154a2..776f333063d 100755 --- a/test/e2e-test.sh +++ b/test/e2e-test.sh @@ -262,8 +262,31 @@ set -euo pipefail root="${FAKE_SANDBOX_ROOT:?}" printf '%s\n' "$*" >> "${root}/invocation.txt" -if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "nemoclaw-shell" ] && [ "$6" = "openclaw" ] && [ "$7" = "setup" ]; then - sandbox_root="${root}/$3/.openclaw" +if [ "$1" = "sandbox" ] && [ "$2" = "ssh-config" ]; then + cat <&2 +exit 1 +EOF +chmod +x /tmp/fake-bin/openshell + +cat > /tmp/fake-bin/ssh <<'EOF' +#!/usr/bin/env bash +set -euo pipefail + +root="${FAKE_SANDBOX_ROOT:?}" +host="${3:-}" +remote_cmd="${4:-}" +sandbox_name="${host#openshell-}" +sandbox_root="${root}/${sandbox_name}/.openclaw" +printf 'ssh %s %s\n' "$host" "$remote_cmd" >> "${root}/invocation.txt" + +if [[ "$remote_cmd" == *"'nemoclaw-shell' 'openclaw' 'setup'"* ]]; then mkdir -p "${sandbox_root}/workspace" "${sandbox_root}/sessions" cat > "${sandbox_root}/openclaw.json" <<'JSON' { @@ -280,9 +303,8 @@ JSON exit 0 fi -if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "nemoclaw-shell" ] && [ "$6" = "nemoclaw-gateway.sh" ] && [ "$7" = "ensure" ]; then - sandbox_root="${root}/$3/.openclaw" - mkdir -p "${sandbox_root}/run" "${sandbox_root}/logs" +if [[ "$remote_cmd" == *"'nemoclaw-shell' 'openclaw' 'gateway' 'install' '--json'"* ]]; then + mkdir -p "${sandbox_root}/logs" cat > "${sandbox_root}/openclaw.json" <<'JSON' { "agents": { @@ -299,16 +321,16 @@ if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = " } } JSON - echo "4242" > "${sandbox_root}/run/gateway.pid" touch "${sandbox_root}/logs/gateway.log" - echo "gateway-ready:4242" + touch "${sandbox_root}/gateway-install.ok" + printf '%s\n' '{"ok":true}' exit 0 fi -echo "unexpected openshell invocation: $*" >&2 +echo "unexpected ssh invocation: ${remote_cmd}" >&2 exit 1 EOF -chmod +x /tmp/fake-bin/openshell +chmod +x /tmp/fake-bin/ssh PATH="/tmp/fake-bin:$PATH" FAKE_SANDBOX_ROOT=/tmp/fake-sandbox node - <<'EOF' const { ensureSandboxOpenClawBootstrap } = require('/opt/nemoclaw/dist/commands/sandbox-bootstrap.js'); @@ -328,58 +350,142 @@ if (!ok) { } EOF -grep -q '^sandbox connect openclaw -- nemoclaw-shell openclaw setup$' /tmp/fake-sandbox/invocation.txt \ +grep -q '^sandbox ssh-config openclaw$' /tmp/fake-sandbox/invocation.txt \ + && pass "Headless bootstrap requests sandbox ssh config" \ + || fail "Headless bootstrap did not request sandbox ssh config" +grep -q "^ssh openshell-openclaw 'nemoclaw-shell' 'openclaw' 'setup'$" /tmp/fake-sandbox/invocation.txt \ && pass "Headless bootstrap runs openclaw setup" \ || fail "Headless bootstrap did not run openclaw setup" -grep -q '^sandbox connect openclaw -- nemoclaw-shell nemoclaw-gateway.sh ensure$' /tmp/fake-sandbox/invocation.txt \ - && pass "Headless bootstrap ensures the Gateway process" \ - || fail "Headless bootstrap did not ensure the Gateway process" +grep -q "^ssh openshell-openclaw 'nemoclaw-shell' 'openclaw' 'gateway' 'install' '--json'$" /tmp/fake-sandbox/invocation.txt \ + && pass "Headless bootstrap installs the managed Gateway" \ + || fail "Headless bootstrap did not install the managed Gateway" grep -q '"token": "sandbox-token-123"' /tmp/fake-sandbox/openclaw/.openclaw/openclaw.json \ && pass "Headless bootstrap seeded gateway auth token" \ || fail "Headless bootstrap did not seed gateway auth token" -[ -f /tmp/fake-sandbox/openclaw/.openclaw/run/gateway.pid ] \ - && pass "Headless bootstrap created gateway pid file" \ - || fail "Headless bootstrap did not create gateway pid file" +[ -f /tmp/fake-sandbox/openclaw/.openclaw/gateway-install.ok ] \ + && pass "Headless bootstrap marked gateway install success" \ + || fail "Headless bootstrap did not mark gateway install success" # ------------------------------------------------------- -info "12. Verify the Gateway manager reuses a healthy process via PID file" +info "12. Verify bootstrap helper falls back to direct Gateway run when systemd is unavailable" # ------------------------------------------------------- -rm -rf /tmp/fake-bin /tmp/fake-home /tmp/fake-health -mkdir -p /tmp/fake-bin /tmp/fake-home/.openclaw/run /tmp/fake-home/.openclaw/logs +rm -rf /tmp/fake-bin /tmp/fake-sandbox +mkdir -p /tmp/fake-bin /tmp/fake-sandbox -cat > /tmp/fake-bin/openclaw <<'EOF' +cat > /tmp/fake-bin/openshell <<'EOF' #!/usr/bin/env bash set -euo pipefail -printf '%s\n' "$*" >> /tmp/fake-openclaw.invocation.txt +root="${FAKE_SANDBOX_ROOT:?}" +printf '%s\n' "$*" >> "${root}/invocation.txt" -if [ "$1" = "gateway" ] && [ "$2" = "status" ] && [ "$3" = "--deep" ] && [ "$4" = "--require-rpc" ]; then - [ -f /tmp/fake-health ] && exit 0 - exit 1 +if [ "$1" = "sandbox" ] && [ "$2" = "ssh-config" ]; then + cat <&2 +exit 1 +EOF +chmod +x /tmp/fake-bin/openshell + +cat > /tmp/fake-bin/ssh <<'EOF' +#!/usr/bin/env bash +set -euo pipefail + +root="${FAKE_SANDBOX_ROOT:?}" +host="${3:-}" +remote_cmd="${4:-}" +sandbox_name="${host#openshell-}" +sandbox_root="${root}/${sandbox_name}/.openclaw" +printf 'ssh %s %s\n' "$host" "$remote_cmd" >> "${root}/invocation.txt" + +if [[ "$remote_cmd" == *"'nemoclaw-shell' 'openclaw' 'setup'"* ]]; then + mkdir -p "${sandbox_root}/workspace" "${sandbox_root}/sessions" + cat > "${sandbox_root}/openclaw.json" <<'JSON' +{ + "agents": { + "defaults": { + "workspace": "/sandbox/.openclaw/workspace" + } + }, + "gateway": { + "mode": "local" + } +} +JSON + exit 0 fi -echo "unexpected openclaw invocation: $*" >&2 +if [[ "$remote_cmd" == *"'nemoclaw-shell' 'openclaw' 'gateway' 'install' '--json'"* ]]; then + printf '%s\n' '{"ok":false,"message":"system has not been booted with systemd"}' + exit 0 +fi + +if [[ "$remote_cmd" == *"'nemoclaw-shell' 'sh' '-lc'"* ]]; then + mkdir -p "${sandbox_root}/logs" + cat > "${sandbox_root}/openclaw.json" <<'JSON' +{ + "agents": { + "defaults": { + "workspace": "/sandbox/.openclaw/workspace" + } + }, + "gateway": { + "mode": "local", + "auth": { + "mode": "token", + "token": "fallback-token-234" + } + } +} +JSON + touch "${sandbox_root}/logs/gateway.log" + touch "${sandbox_root}/gateway-fallback.ok" + exit 0 +fi + +echo "unexpected ssh invocation: ${remote_cmd}" >&2 exit 1 EOF -chmod +x /tmp/fake-bin/openclaw +chmod +x /tmp/fake-bin/ssh + +PATH="/tmp/fake-bin:$PATH" FAKE_SANDBOX_ROOT=/tmp/fake-sandbox node - <<'EOF' +const { ensureSandboxOpenClawBootstrap } = require('/opt/nemoclaw/dist/commands/sandbox-bootstrap.js'); + +const logger = { + info() {}, + warn() {}, + error(message) { + throw new Error(message); + }, + debug() {}, +}; -HOME=/tmp/fake-home PATH="/tmp/fake-bin:$PATH" /usr/local/bin/nemoclaw-gateway.sh ensure >/tmp/gateway-ensure-1.out -pid1="$(cat /tmp/fake-home/.openclaw/run/gateway.pid)" -HOME=/tmp/fake-home PATH="/tmp/fake-bin:$PATH" /usr/local/bin/nemoclaw-gateway.sh ensure >/tmp/gateway-ensure-2.out -pid2="$(cat /tmp/fake-home/.openclaw/run/gateway.pid)" -[ "$pid1" = "$pid2" ] || fail "Gateway manager changed pid across repeated ensure calls" -kill "$pid1" 2>/dev/null || true -grep -c '^gateway run --force$' /tmp/fake-openclaw.invocation.txt | grep -q '^1$' \ - && pass "Gateway manager starts only one process for repeated ensure calls" \ - || fail "Gateway manager started duplicate processes" -[ -f /tmp/fake-home/.openclaw/run/gateway.pid ] \ - && pass "Gateway manager records the process pid" \ - || fail "Gateway manager did not record the process pid" +const ok = ensureSandboxOpenClawBootstrap({ sandboxName: 'openclaw', logger }); +if (!ok) { + throw new Error('bootstrap helper returned false'); +} +EOF + +grep -q '^sandbox ssh-config openclaw$' /tmp/fake-sandbox/invocation.txt \ + && pass "Bootstrap helper requests sandbox ssh config" \ + || fail "Bootstrap helper did not request sandbox ssh config" +grep -q "^ssh openshell-openclaw 'nemoclaw-shell' 'openclaw' 'gateway' 'install' '--json'$" /tmp/fake-sandbox/invocation.txt \ + && pass "Bootstrap helper attempts managed Gateway install first" \ + || fail "Bootstrap helper did not attempt managed Gateway install first" +grep -q "^ssh openshell-openclaw 'nemoclaw-shell' 'sh' '-lc'" /tmp/fake-sandbox/invocation.txt \ + && pass "Bootstrap helper falls back to direct Gateway start" \ + || fail "Bootstrap helper did not fall back to direct Gateway start" +grep -q '"token": "fallback-token-234"' /tmp/fake-sandbox/openclaw/.openclaw/openclaw.json \ + && pass "Fallback bootstrap seeded gateway auth token" \ + || fail "Fallback bootstrap did not seed gateway auth token" +[ -f /tmp/fake-sandbox/openclaw/.openclaw/gateway-fallback.ok ] \ + && pass "Fallback bootstrap marked direct gateway success" \ + || fail "Fallback bootstrap did not mark direct gateway success" # ------------------------------------------------------- info "13. Verify launch runs the full headless bootstrap sequence" @@ -412,8 +518,31 @@ if [ "$1" = "inference" ] && [ "$2" = "set" ]; then exit 0 fi -if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "nemoclaw-shell" ] && [ "$6" = "openclaw" ] && [ "$7" = "setup" ]; then - sandbox_root="${root}/$3/.openclaw" +if [ "$1" = "sandbox" ] && [ "$2" = "ssh-config" ]; then + cat <&2 +exit 1 +EOF +chmod +x /tmp/fake-bin/openshell + +cat > /tmp/fake-bin/ssh <<'EOF' +#!/usr/bin/env bash +set -euo pipefail + +root="${FAKE_SANDBOX_ROOT:?}" +host="${3:-}" +remote_cmd="${4:-}" +sandbox_name="${host#openshell-}" +sandbox_root="${root}/${sandbox_name}/.openclaw" +printf 'ssh %s %s\n' "$host" "$remote_cmd" >> "${root}/invocation.txt" + +if [[ "$remote_cmd" == *"'nemoclaw-shell' 'openclaw' 'setup'"* ]]; then mkdir -p "${sandbox_root}/workspace" "${sandbox_root}/sessions" cat > "${sandbox_root}/openclaw.json" <<'JSON' { @@ -430,9 +559,8 @@ JSON exit 0 fi -if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "nemoclaw-shell" ] && [ "$6" = "nemoclaw-gateway.sh" ] && [ "$7" = "ensure" ]; then - sandbox_root="${root}/$3/.openclaw" - mkdir -p "${sandbox_root}/run" "${sandbox_root}/logs" +if [[ "$remote_cmd" == *"'nemoclaw-shell' 'openclaw' 'gateway' 'install' '--json'"* ]]; then + mkdir -p "${sandbox_root}/logs" cat > "${sandbox_root}/openclaw.json" <<'JSON' { "agents": { @@ -449,16 +577,16 @@ if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = " } } JSON - echo "31337" > "${sandbox_root}/run/gateway.pid" touch "${sandbox_root}/logs/gateway.log" - echo "gateway-ready:31337" + touch "${sandbox_root}/gateway-install.ok" + printf '%s\n' '{"ok":true}' exit 0 fi -echo "unexpected openshell invocation: $*" >&2 +echo "unexpected ssh invocation: ${remote_cmd}" >&2 exit 1 EOF -chmod +x /tmp/fake-bin/openshell +chmod +x /tmp/fake-bin/ssh cat > /tmp/fake-bin/openclaw <<'EOF' #!/usr/bin/env bash @@ -530,7 +658,10 @@ main().catch((error) => { }); EOF -grep -q '^sandbox connect openclaw -- nemoclaw-shell openclaw setup$' /tmp/fake-sandbox/invocation.txt \ +grep -q '^sandbox ssh-config openclaw$' /tmp/fake-sandbox/invocation.txt \ + && pass "Launch requests sandbox ssh config" \ + || fail "Launch did not request sandbox ssh config" +grep -q "^ssh openshell-openclaw 'nemoclaw-shell' 'openclaw' 'setup'$" /tmp/fake-sandbox/invocation.txt \ && pass "Launch runs openclaw setup" \ || fail "Launch did not run openclaw setup" [ -f /tmp/fake-sandbox/openclaw/.openclaw/openclaw.json ] \ @@ -539,12 +670,12 @@ grep -q '^sandbox connect openclaw -- nemoclaw-shell openclaw setup$' /tmp/fake- [ -d /tmp/fake-sandbox/openclaw/.openclaw/workspace ] \ && pass "Launch created workspace" \ || fail "Launch did not create workspace" -grep -q '^sandbox connect openclaw -- nemoclaw-shell nemoclaw-gateway.sh ensure$' /tmp/fake-sandbox/invocation.txt \ - && pass "Launch ensures the Gateway process" \ - || fail "Launch did not ensure the Gateway process" -[ -f /tmp/fake-sandbox/openclaw/.openclaw/run/gateway.pid ] \ - && pass "Launch created gateway pid file" \ - || fail "Launch did not create gateway pid file" +grep -q "^ssh openshell-openclaw 'nemoclaw-shell' 'openclaw' 'gateway' 'install' '--json'$" /tmp/fake-sandbox/invocation.txt \ + && pass "Launch installs the managed Gateway" \ + || fail "Launch did not install the managed Gateway" +[ -f /tmp/fake-sandbox/openclaw/.openclaw/gateway-install.ok ] \ + && pass "Launch marked gateway install success" \ + || fail "Launch did not mark gateway install success" # ------------------------------------------------------- info "14. Verify migrate reruns the headless bootstrap sequence" @@ -610,8 +741,31 @@ if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = " exit 0 fi -if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "nemoclaw-shell" ] && [ "$6" = "openclaw" ] && [ "$7" = "setup" ]; then - sandbox_root="${root}/$3/.openclaw" +if [ "$1" = "sandbox" ] && [ "$2" = "ssh-config" ]; then + cat <&2 +exit 1 +EOF +chmod +x /tmp/fake-bin/openshell + +cat > /tmp/fake-bin/ssh <<'EOF' +#!/usr/bin/env bash +set -euo pipefail + +root="${FAKE_SANDBOX_ROOT:?}" +host="${3:-}" +remote_cmd="${4:-}" +sandbox_name="${host#openshell-}" +sandbox_root="${root}/${sandbox_name}/.openclaw" +printf 'ssh %s %s\n' "$host" "$remote_cmd" >> "${root}/invocation.txt" + +if [[ "$remote_cmd" == *"'nemoclaw-shell' 'openclaw' 'setup'"* ]]; then mkdir -p "${sandbox_root}/workspace" "${sandbox_root}/sessions" if [ ! -f "${sandbox_root}/openclaw.json" ]; then cat > "${sandbox_root}/openclaw.json" <<'JSON' @@ -630,9 +784,8 @@ JSON exit 0 fi -if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = "nemoclaw-shell" ] && [ "$6" = "nemoclaw-gateway.sh" ] && [ "$7" = "ensure" ]; then - sandbox_root="${root}/$3/.openclaw" - mkdir -p "${sandbox_root}/run" "${sandbox_root}/logs" +if [[ "$remote_cmd" == *"'nemoclaw-shell' 'openclaw' 'gateway' 'install' '--json'"* ]]; then + mkdir -p "${sandbox_root}/logs" cat > "${sandbox_root}/openclaw.json" <<'JSON' { "agents": { @@ -649,16 +802,16 @@ if [ "$1" = "sandbox" ] && [ "$2" = "connect" ] && [ "$4" = "--" ] && [ "$5" = " } } JSON - echo "5150" > "${sandbox_root}/run/gateway.pid" touch "${sandbox_root}/logs/gateway.log" - echo "gateway-ready:5150" + touch "${sandbox_root}/gateway-install.ok" + printf '%s\n' '{"ok":true}' exit 0 fi -echo "unexpected openshell invocation: $*" >&2 +echo "unexpected ssh invocation: ${remote_cmd}" >&2 exit 1 EOF -chmod +x /tmp/fake-bin/openshell +chmod +x /tmp/fake-bin/ssh PATH="/tmp/fake-bin:$PATH" FAKE_SANDBOX_ROOT=/tmp/fake-sandbox HOME=/tmp/fake-home node - <<'EOF' const fs = require('node:fs'); @@ -723,12 +876,15 @@ grep -Eq '^sandbox cp .+ openclaw:/sandbox/\.nemoclaw/migration/archives/state\. grep -q '^sandbox connect openclaw -- sh -lc ' /tmp/fake-sandbox/invocation.txt \ && pass "Migrate extracts archives inside the sandbox" \ || fail "Migrate did not extract archives inside the sandbox" -grep -q '^sandbox connect openclaw -- nemoclaw-shell openclaw setup$' /tmp/fake-sandbox/invocation.txt \ +grep -q '^sandbox ssh-config openclaw$' /tmp/fake-sandbox/invocation.txt \ + && pass "Migrate requests sandbox ssh config" \ + || fail "Migrate did not request sandbox ssh config" +grep -q "'nemoclaw-shell' 'openclaw' 'setup'" /tmp/fake-sandbox/invocation.txt \ && pass "Migrate reruns openclaw setup" \ || fail "Migrate did not rerun openclaw setup" -grep -q '^sandbox connect openclaw -- nemoclaw-shell nemoclaw-gateway.sh ensure$' /tmp/fake-sandbox/invocation.txt \ - && pass "Migrate reruns Gateway ensure" \ - || fail "Migrate did not rerun Gateway ensure" +grep -q "'nemoclaw-shell' 'openclaw' 'gateway' 'install' '--json'" /tmp/fake-sandbox/invocation.txt \ + && pass "Migrate reruns managed Gateway install" \ + || fail "Migrate did not rerun managed Gateway install" [ -f /tmp/fake-sandbox/openclaw/.openclaw/workspace/project.md ] \ && pass "Migrate restores workspace files into the sandbox" \ || fail "Migrate did not restore workspace files into the sandbox"