Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 34 additions & 2 deletions bin/nemoclaw.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const { parseGatewayInference } = require("./lib/inference-config");

const GLOBAL_COMMANDS = new Set([
"onboard", "list", "deploy", "setup", "setup-spark",
"start", "stop", "status", "debug", "uninstall",
"start", "stop", "status", "reconnect", "debug", "uninstall",
"help", "--help", "-h", "--version", "-v",
]);

Expand Down Expand Up @@ -134,7 +134,7 @@ async function recoverNamedGatewayRuntime() {
}

const shouldStartGateway = [before.state, after.state].some((state) =>
["named_unhealthy", "named_unreachable", "connected_other"].includes(state)
["named_unhealthy", "named_unreachable", "connected_other", "missing_named"].includes(state)
);

if (shouldStartGateway) {
Expand Down Expand Up @@ -557,6 +557,25 @@ function listSandboxes() {
console.log("");
}

function resolveReconnectSandboxName(requestedName) {
const sandboxName = requestedName || registry.getDefault();
if (!sandboxName) {
console.error(" No sandbox registered. Run `nemoclaw onboard` to create one first.");
process.exit(1);
}
validateName(sandboxName, "sandbox name");

if (requestedName) {
const existingSandbox = registry.getSandbox(sandboxName);
if (!existingSandbox) {
console.error(` Unknown sandbox '${sandboxName}'.`);
console.error(" Use `nemoclaw list` to view registered sandboxes.");
process.exit(1);
}
}
return sandboxName;
}

// ── Sandbox-scoped actions ───────────────────────────────────────

async function sandboxConnect(sandboxName) {
Expand All @@ -571,6 +590,17 @@ async function sandboxConnect(sandboxName) {
exitWithSpawnResult(result);
}

async function reconnect(args = []) {
if (args.length > 1) {
console.error(" Too many positional arguments for `reconnect`.");
console.error(" Usage: `nemoclaw reconnect [sandbox-name]`.");
process.exit(1);
}
const sandboxName = resolveReconnectSandboxName(args[0]);
console.log(` Reconnecting to sandbox '${sandboxName}'...`);
await sandboxConnect(sandboxName);
}

// eslint-disable-next-line complexity
async function sandboxStatus(sandboxName) {
const sb = registry.getSandbox(sandboxName);
Expand Down Expand Up @@ -721,6 +751,7 @@ function help() {

${G}Sandbox Management:${R}
${B}nemoclaw list${R} List all sandboxes
nemoclaw reconnect ${D}[name]${R} Recover the default or named sandbox after a reboot
nemoclaw <name> connect Shell into a running sandbox
nemoclaw <name> status Sandbox health + NIM status
nemoclaw <name> logs ${D}[--follow]${R} Stream sandbox logs
Expand Down Expand Up @@ -778,6 +809,7 @@ const [cmd, ...args] = process.argv.slice(2);
case "start": await start(); break;
case "stop": stop(); break;
case "status": showStatus(); break;
case "reconnect": await reconnect(args); break;
case "debug": debug(args); break;
case "uninstall": uninstall(args); break;
case "list": listSandboxes(); break;
Expand Down
Loading