Skip to content
Merged
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
19 changes: 14 additions & 5 deletions bin/lib/onboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,17 @@ async function startGateway(gpu) {
async function createSandbox(gpu) {
step(3, 7, "Creating sandbox");

const nameAnswer = await prompt(" Sandbox name [my-assistant]: ");
const sandboxName = nameAnswer || "my-assistant";
const nameAnswer = await prompt(" Sandbox name (lowercase, numbers, hyphens) [my-assistant]: ");
const sandboxName = (nameAnswer || "my-assistant").trim().toLowerCase();

// Validate: RFC 1123 subdomain — lowercase alphanumeric and hyphens,
// must start and end with alphanumeric (required by Kubernetes/OpenShell)
if (!/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(sandboxName)) {
console.error(` Invalid sandbox name: '${sandboxName}'`);
console.error(" Names must be lowercase, contain only letters, numbers, and hyphens,");
console.error(" and must start and end with a letter or number.");
process.exit(1);
}

// Check if sandbox already exists in registry
const existing = registry.getSandbox(sandboxName);
Expand All @@ -162,7 +171,7 @@ async function createSandbox(gpu) {
return sandboxName;
}
// Destroy old sandbox
run(`openshell sandbox delete ${sandboxName} 2>/dev/null || true`, { ignoreError: true });
run(`openshell sandbox delete "${sandboxName}" 2>/dev/null || true`, { ignoreError: true });
registry.removeSandbox(sandboxName);
}

Expand All @@ -181,7 +190,7 @@ async function createSandbox(gpu) {
const basePolicyPath = path.join(ROOT, "nemoclaw-blueprint", "policies", "openclaw-sandbox.yaml");
const createArgs = [
`--from "${buildCtx}/Dockerfile"`,
`--name ${sandboxName}`,
`--name "${sandboxName}"`,
`--policy "${basePolicyPath}"`,
];
if (gpu && gpu.nimCapable) createArgs.push("--gpu");
Expand All @@ -195,7 +204,7 @@ async function createSandbox(gpu) {
run(`openshell sandbox create ${createArgs.join(" ")} -- env ${envArgs.join(" ")} nemoclaw-start 2>&1 | awk '/Sandbox allocated/{if(!seen){print;seen=1}next}1'`);

// Forward dashboard port separately
run(`openshell forward start --background 18789 ${sandboxName}`, { ignoreError: true });
run(`openshell forward start --background 18789 "${sandboxName}"`, { ignoreError: true });

// Clean up build context
run(`rm -rf "${buildCtx}"`, { ignoreError: true });
Expand Down
4 changes: 2 additions & 2 deletions bin/lib/policies.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ function applyPreset(sandboxName, presetName) {
let rawPolicy = "";
try {
rawPolicy = runCapture(
`openshell policy get --full ${sandboxName} 2>/dev/null`,
`openshell policy get --full "${sandboxName}" 2>/dev/null`,
{ ignoreError: true }
);
} catch {}
Expand Down Expand Up @@ -146,7 +146,7 @@ function applyPreset(sandboxName, presetName) {
fs.writeFileSync(tmpFile, merged, "utf-8");

try {
run(`openshell policy set --policy "${tmpFile}" --wait ${sandboxName}`);
run(`openshell policy set --policy "${tmpFile}" --wait "${sandboxName}"`);
console.log(` Applied preset: ${presetName}`);
} finally {
fs.unlinkSync(tmpFile);
Expand Down
10 changes: 5 additions & 5 deletions bin/nemoclaw.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,8 @@ function listSandboxes() {

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 forward start --background 18789 "${sandboxName}" 2>/dev/null || true`, { ignoreError: true });
run(`openshell sandbox connect "${sandboxName}"`);
}

function sandboxStatus(sandboxName) {
Expand All @@ -204,7 +204,7 @@ function sandboxStatus(sandboxName) {
}

// openshell info
run(`openshell sandbox get ${sandboxName} 2>/dev/null || true`, { ignoreError: true });
run(`openshell sandbox get "${sandboxName}" 2>/dev/null || true`, { ignoreError: true });

// NIM health
const nimStat = nim.nimStatus(sandboxName);
Expand All @@ -217,7 +217,7 @@ function sandboxStatus(sandboxName) {

function sandboxLogs(sandboxName, follow) {
const followFlag = follow ? " --follow" : "";
run(`openshell sandbox logs ${sandboxName}${followFlag}`);
run(`openshell sandbox logs "${sandboxName}"${followFlag}`);
}

async function sandboxPolicyAdd(sandboxName) {
Expand Down Expand Up @@ -260,7 +260,7 @@ function sandboxDestroy(sandboxName) {
nim.stopNimContainer(sandboxName);

console.log(` Deleting sandbox '${sandboxName}'...`);
run(`openshell sandbox delete ${sandboxName} 2>/dev/null || true`, { ignoreError: true });
run(`openshell sandbox delete "${sandboxName}" 2>/dev/null || true`, { ignoreError: true });

registry.removeSandbox(sandboxName);
console.log(` ✓ Sandbox '${sandboxName}' destroyed`);
Expand Down