From 4b8d3198aead45a02445f70aa37f0ea4fd1d454d Mon Sep 17 00:00:00 2001 From: peteryuqin Date: Mon, 16 Mar 2026 21:35:06 -0400 Subject: [PATCH] fix: make onboard robust when rerun after a failed install When a previous onboard attempt failed partway through, the sandbox could exist in OpenShell but not in the local registry (or vice versa). Rerunning onboard would then either try to create a duplicate sandbox (failing) or miss the existing one entirely, requiring `uninstall.sh` as a workaround. Now `createSandbox()` checks both the local registry and the actual OpenShell state. When they are out of sync: - The user sees which side has the sandbox (e.g. "found in OpenShell but not registered") - Choosing to keep it re-syncs the registry automatically - Choosing to recreate cleans up both sides before proceeding Closes #23 Signed-off-by: peteryuqin --- bin/lib/onboard.js | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/bin/lib/onboard.js b/bin/lib/onboard.js index 3e84534256..2f8ef5a468 100644 --- a/bin/lib/onboard.js +++ b/bin/lib/onboard.js @@ -130,15 +130,32 @@ async function createSandbox(gpu) { const nameAnswer = await prompt(" Sandbox name [my-assistant]: "); const sandboxName = nameAnswer || "my-assistant"; - // Check if sandbox already exists in registry - const existing = registry.getSandbox(sandboxName); - if (existing) { - const recreate = await prompt(` Sandbox '${sandboxName}' already exists. Recreate? [y/N]: `); + // Check if sandbox already exists — look at both the registry and the + // actual OpenShell state. A previous failed onboard may have created a + // sandbox in OpenShell without registering it (see #22), or vice-versa. + const existsInRegistry = !!registry.getSandbox(sandboxName); + const existsInOpenshell = !!runCapture( + `openshell sandbox status ${sandboxName} --json 2>/dev/null`, + { ignoreError: true } + ); + + if (existsInRegistry || existsInOpenshell) { + const where = existsInRegistry && existsInOpenshell + ? "registered and running" + : existsInRegistry + ? "registered (but not found in OpenShell)" + : "found in OpenShell (but not registered)"; + const recreate = await prompt(` Sandbox '${sandboxName}' already exists (${where}). Recreate? [y/N]: `); if (recreate.toLowerCase() !== "y") { console.log(" Keeping existing sandbox."); + // Sync: if it exists in OpenShell but not in the registry, register it + if (existsInOpenshell && !existsInRegistry) { + registry.registerSandbox({ name: sandboxName, gpuEnabled: !!gpu }); + console.log(` ✓ Re-registered '${sandboxName}' in local registry.`); + } return sandboxName; } - // Destroy old sandbox + // Clean up both sides before recreating run(`openshell sandbox delete ${sandboxName} 2>/dev/null || true`, { ignoreError: true }); registry.removeSandbox(sandboxName); }