Skip to content
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
6737a62
fix(onboard): refuse gateway recreate when live sandboxes exist
laitingsheng Jun 1, 2026
ab5648a
fixup: address review (extract live-row helper, wire-up test, docs, c…
laitingsheng Jun 1, 2026
84bdda8
fix(onboard): narrow refuse-recreate to confirmed stale drift only
laitingsheng Jun 1, 2026
429eb9f
Merge branch 'main' into fix/4422-refuse-gateway-drift-on-live-sandbox
laitingsheng Jun 1, 2026
0ef1f56
refactor(state): introduce getGatewayName resolver for parallel-gatew…
laitingsheng Jun 1, 2026
a1c55fe
feat(registry): track per-sandbox gateway name with singleton backfill
laitingsheng Jun 1, 2026
fa45507
refactor(state): single source for gateway name + tighten registry ac…
laitingsheng Jun 1, 2026
fdddf53
refactor(state): replace remaining hard-coded gateway names with DEFA…
laitingsheng Jun 1, 2026
48e58ae
refactor(state): persist + validate gatewayName at registry boundary
laitingsheng Jun 1, 2026
b9e28ba
fix(state): inline gatewayName validation to drop runner dep on platform
laitingsheng Jun 1, 2026
7cf4f48
refactor(state): default getSandboxGatewayName + migrate reused entri…
laitingsheng Jun 1, 2026
8b085b1
refactor(state): return null for unknown and corrupt gatewayName look…
laitingsheng Jun 1, 2026
ca876d6
refactor(state): route accessor diagnostics to stderr and cover reuse…
laitingsheng Jun 1, 2026
6bb247f
test(state): load registry after HOME mutation and ensure regfile par…
laitingsheng Jun 1, 2026
8fc38b0
refactor(state): relocate gateway-name accessor and route remaining s…
laitingsheng Jun 1, 2026
2d1292f
refactor(state): route gateway-state recovery hints and regex through…
laitingsheng Jun 1, 2026
1978b74
fix(state): inject active gateway name into reuse migration instead o…
laitingsheng Jun 1, 2026
196725f
fix(state): drop unused DEFAULT_GATEWAY_NAME import from registry
laitingsheng Jun 1, 2026
13d43ab
merge: resolve main into fix/4422-refuse-gateway-drift-on-live-sandbox
laitingsheng Jun 2, 2026
79ca81b
Merge branch 'main' into fix/4422-refuse-gateway-drift-on-live-sandbox
cv Jun 2, 2026
897e8aa
merge: resolve origin/main into branch by adopting main state
laitingsheng Jun 5, 2026
40042b8
test(e2e): add concurrent-gateway-ports E2E and expand advisor catalog
laitingsheng Jun 5, 2026
404de0c
fix(e2e): add missing fake OpenAI server heredoc + readiness poll
laitingsheng Jun 5, 2026
ac1c1a9
fix(ci): install NemoClaw before concurrent-gateway-ports E2E
laitingsheng Jun 5, 2026
00a243e
fix(e2e): use custom provider + clear default sandbox before stages
laitingsheng Jun 5, 2026
88a8385
fix(e2e): parse dashboard URL across lines + read phase from openshel…
laitingsheng Jun 5, 2026
f502f98
fix(onboard): skip gateway retire when foreign-active per-port gatewa…
laitingsheng Jun 5, 2026
9de4b99
fix(onboard): preserve foreign sandbox's dashboard forward during pre…
laitingsheng Jun 5, 2026
3ce01f0
fix(e2e): retry verify_sandbox_alive on Provisioning until Ready or t…
laitingsheng Jun 5, 2026
939a182
fix(e2e): query each sandbox via its own gateway in verify_sandbox_alive
laitingsheng Jun 5, 2026
beb9014
Merge branch 'main' into fix/4422-refuse-gateway-drift-on-live-sandbox
laitingsheng Jun 5, 2026
69dcdef
refactor(onboard): extract orphaned dashboard forward cleanup helper
laitingsheng Jun 5, 2026
c1e28bd
Merge remote-tracking branch 'origin/main' into fix/4422-refuse-gatew…
cv Jun 5, 2026
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
3 changes: 2 additions & 1 deletion src/lib/actions/inference-set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
writeSandboxConfig,
} from "../sandbox/config";
import { appendAuditEntry } from "../shields/audit";
import { DEFAULT_GATEWAY_NAME } from "../state/gateway-name";
import * as onboardSession from "../state/onboard-session";
import * as registry from "../state/registry";
import type { SandboxEntry } from "../state/registry";
Expand Down Expand Up @@ -300,7 +301,7 @@ function openshellInferenceSetArgs(options: {
"inference",
"set",
"-g",
"nemoclaw",
DEFAULT_GATEWAY_NAME,
"--provider",
options.provider,
"--model",
Expand Down
3 changes: 1 addition & 2 deletions src/lib/actions/sandbox/connect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,13 @@ import {
import { getNamedGatewayLifecycleState } from "../../gateway-runtime-action";
import { runSetupDnsProxy } from "../dns";
import { ensureLiveSandboxOrExit, printGatewayLifecycleHint } from "./gateway-state";
import { DEFAULT_GATEWAY_NAME as NEMOCLAW_GATEWAY_NAME } from "../../state/gateway-name";
import { checkAndRecoverSandboxProcesses } from "./process-recovery";
import {
applyOpenShellVmDnsMonkeypatch,
shouldApplyVmDnsMonkeypatch,
} from "./vm-dns-monkeypatch";

const NEMOCLAW_GATEWAY_NAME = "nemoclaw";

export type SandboxConnectOptions = {
probeOnly?: boolean;
};
Expand Down
2 changes: 1 addition & 1 deletion src/lib/actions/sandbox/destroy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { stopStaleDashboardListeners } from "../../onboard/stale-gateway-cleanup
import { stopHostGatewayProcesses } from "../../onboard/host-gateway-process";
import { parseLiveSandboxNames } from "../../runtime-recovery";
import { killTimer as defaultKillShieldsTimer } from "../../shields/timer-control";
import { DEFAULT_GATEWAY_NAME as NEMOCLAW_GATEWAY_NAME } from "../../state/gateway-name";
import type { Session } from "../../state/onboard-session";
import * as onboardSession from "../../state/onboard-session";
import { resolveNemoclawStateDir } from "../../state/paths";
Expand Down Expand Up @@ -78,7 +79,6 @@ type RemoveShieldsStateDeps = {
warn?: (message: string) => void;
};

const NEMOCLAW_GATEWAY_NAME = "nemoclaw";
const DASHBOARD_FORWARD_PORT = String(DASHBOARD_PORT);

function cleanupGatewayAfterLastSandbox(): void {
Expand Down
3 changes: 1 addition & 2 deletions src/lib/actions/sandbox/doctor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,10 @@ import { ROOT } from "../../runner";
import { parseLiveSandboxNames } from "../../runtime-recovery";
import * as sandboxVersion from "../../sandbox/version";
import * as shields from "../../shields";
import { DEFAULT_GATEWAY_NAME as NEMOCLAW_GATEWAY_NAME } from "../../state/gateway-name";
import { buildStatusCommandDeps } from "../../status-command-deps";
import { B, D, G, R, RD, YW } from "../../cli/terminal-style";

const NEMOCLAW_GATEWAY_NAME = "nemoclaw";

type DoctorStatus = "ok" | "warn" | "fail" | "info";

export type DoctorCheck = {
Expand Down
21 changes: 11 additions & 10 deletions src/lib/actions/sandbox/gateway-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import path from "node:path";

import { CLI_DISPLAY_NAME, CLI_NAME } from "../../cli/branding";
import { parseSandboxPhase } from "../../state/gateway";
import { DEFAULT_GATEWAY_NAME } from "../../state/gateway-name";
import {
getNamedGatewayLifecycleState,
recoverNamedGatewayRuntime,
Expand Down Expand Up @@ -215,7 +216,7 @@ export function reconcileMissingAgainstNamedGateway(
): SandboxGatewayState {
const lifecycle = getNamedGatewayLifecycleState();
if (lifecycle.state === "connected_other") {
runOpenshell(["gateway", "select", "nemoclaw"], {
runOpenshell(["gateway", "select", DEFAULT_GATEWAY_NAME], {
ignoreError: true,
timeout: OPENSHELL_OPERATION_TIMEOUT_MS,
});
Expand Down Expand Up @@ -257,12 +258,12 @@ export function printWrongGatewayActiveGuidance(
activeGateway: string | null | undefined,
writer: (message: string) => void = console.error,
): void {
const other = activeGateway && activeGateway !== "nemoclaw" ? activeGateway : "another gateway";
const other = activeGateway && activeGateway !== DEFAULT_GATEWAY_NAME ? activeGateway : "another gateway";
writer(
` Sandbox '${sandboxName}' is registered against the ${CLI_DISPLAY_NAME} gateway, but the currently active OpenShell gateway is '${other}'. Your sandbox has NOT been removed.`,
);
writer(" Switch gateways and retry:");
writer(" openshell gateway select nemoclaw");
writer(` openshell gateway select ${DEFAULT_GATEWAY_NAME}`);
writer(` Then re-run: ${CLI_NAME} ${sandboxName} connect`);
}

Expand All @@ -278,7 +279,7 @@ export function printGatewayLifecycleHint(
` The selected ${CLI_DISPLAY_NAME} gateway is no longer configured or its metadata/runtime has been lost.`,
);
writer(
" Start the gateway again with `openshell gateway start --name nemoclaw` before expecting existing sandboxes to reconnect.",
` Start the gateway again with \`openshell gateway start --name ${DEFAULT_GATEWAY_NAME}\` before expecting existing sandboxes to reconnect.`,
);
writer(
" If the gateway has to be rebuilt from scratch, recreate the affected sandbox afterward.",
Expand All @@ -287,14 +288,14 @@ export function printGatewayLifecycleHint(
}
if (
/Connection refused|client error \(Connect\)|tcp connect error/i.test(cleanOutput) &&
/Gateway:\s+nemoclaw/i.test(cleanOutput)
new RegExp(`Gateway:\\s+${DEFAULT_GATEWAY_NAME}`, "i").test(cleanOutput)
) {
writer(
" The selected NemoClaw gateway exists in metadata, but its API is refusing connections after restart.",
` The selected ${CLI_DISPLAY_NAME} gateway exists in metadata, but its API is refusing connections after restart.`,
);
writer(" This usually means the gateway runtime did not come back cleanly after the restart.");
writer(
" Retry `openshell gateway start --name nemoclaw`; if it stays in this state, rebuild the gateway before expecting existing sandboxes to reconnect.",
` Retry \`openshell gateway start --name ${DEFAULT_GATEWAY_NAME}\`; if it stays in this state, rebuild the gateway before expecting existing sandboxes to reconnect.`,
);
return;
}
Expand Down Expand Up @@ -363,7 +364,7 @@ export async function getReconciledSandboxGatewayState(
}
if (
/Connection refused|client error \(Connect\)|tcp connect error/i.test(latestStatus) &&
/Gateway:\s+nemoclaw/i.test(latestStatus)
new RegExp(`Gateway:\\s+${DEFAULT_GATEWAY_NAME}`, "i").test(latestStatus)
) {
return {
state: "gateway_unreachable_after_restart",
Expand Down Expand Up @@ -474,7 +475,7 @@ export async function ensureLiveSandboxOrExit(
console.error(lookup.output);
}
console.error(
" Retry `openshell gateway start --name nemoclaw` and verify `openshell status` is healthy before reconnecting.",
` Retry \`openshell gateway start --name ${DEFAULT_GATEWAY_NAME}\` and verify \`openshell status\` is healthy before reconnecting.`,
);
console.error(
" If the gateway never becomes healthy, rebuild the gateway and then recreate the affected sandbox.",
Expand All @@ -489,7 +490,7 @@ export async function ensureLiveSandboxOrExit(
console.error(lookup.output);
}
console.error(
" Start the gateway again with `openshell gateway start --name nemoclaw` before retrying.",
` Start the gateway again with \`openshell gateway start --name ${DEFAULT_GATEWAY_NAME}\` before retrying.`,
);
console.error(
" If the gateway had to be rebuilt from scratch, recreate the affected sandbox afterward.",
Expand Down
3 changes: 1 addition & 2 deletions src/lib/actions/sandbox/snapshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { ROOT, run, shellQuote, validateName } from "../../runner";
import { parseLiveSandboxNames } from "../../runtime-recovery";
import { isShieldsDown } from "../../shields";
import { isGatewayHealthy } from "../../state/gateway";
import { DEFAULT_GATEWAY_NAME as NEMOCLAW_GATEWAY_NAME } from "../../state/gateway-name";
import type { SandboxEntry } from "../../state/registry";
import * as registry from "../../state/registry";
import * as sandboxState from "../../state/sandbox";
Expand All @@ -27,8 +28,6 @@ const B = useColor ? "\x1b[1m" : "";
const D = useColor ? "\x1b[2m" : "";
const R = useColor ? "\x1b[0m" : "";

const NEMOCLAW_GATEWAY_NAME = "nemoclaw";

export type SnapshotRequest =
| { kind: "help" }
| { kind: "create"; name?: string }
Expand Down
4 changes: 2 additions & 2 deletions src/lib/actions/uninstall/run-plan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import path from "node:path";
import { dockerSpawnSync } from "../../adapters/docker/exec";
import { getAgentBranding, type AgentBranding } from "../../cli/branding";
import { sleepMs } from "../../core/wait";
import { defaultUninstallPaths, NEMOCLAW_OLLAMA_MODELS, NEMOCLAW_PROVIDERS, type UninstallPaths } from "../../domain/uninstall/paths";
import { DEFAULT_GATEWAY_NAME, defaultUninstallPaths, NEMOCLAW_OLLAMA_MODELS, NEMOCLAW_PROVIDERS, type UninstallPaths } from "../../domain/uninstall/paths";
import { buildUninstallPlan, type UninstallPlan } from "../../domain/uninstall/plan";
import { stopHostGatewayProcesses } from "../../onboard/host-gateway-process";
import { stopStaleDashboardListeners } from "../../onboard/stale-gateway-cleanup";
Expand Down Expand Up @@ -470,7 +470,7 @@ function removeOpenShellResources(options: UninstallRunOptions, runtime: Uninsta
for (const provider of NEMOCLAW_PROVIDERS) {
runOptional(runtime, `Deleted provider '${provider}'`, "openshell", ["provider", "delete", provider]);
}
const gatewayLabel = options.gatewayName || "nemoclaw";
const gatewayLabel = options.gatewayName || DEFAULT_GATEWAY_NAME;
runOptional(
runtime,
`Destroyed gateway '${gatewayLabel}'`,
Expand Down
3 changes: 1 addition & 2 deletions src/lib/adapters/openshell/gateway-drift.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@
import { CLI_DISPLAY_NAME, CLI_NAME } from "../../cli/branding";
import { isOpenShellProtobufSchemaMismatch } from "../../runtime-recovery";
import { isGatewayHealthy } from "../../state/gateway";
import { DEFAULT_GATEWAY_NAME } from "../../state/gateway-name";
import { dockerContainerInspectFormat } from "../docker";
import { stripAnsi } from "./client";
import { captureOpenshell, getInstalledOpenshellVersionOrNull } from "./runtime";
import { OPENSHELL_PROBE_TIMEOUT_MS } from "./timeouts";

const DEFAULT_GATEWAY_NAME = "nemoclaw";

export type GatewayClusterImageDrift = {
containerName: string;
currentImage: string;
Expand Down
3 changes: 2 additions & 1 deletion src/lib/credentials/command-support.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import { recoverNamedGatewayRuntime } from "../actions/global";
import { CLI_DISPLAY_NAME, CLI_NAME } from "../cli/branding";
import { DEFAULT_GATEWAY_NAME } from "../state/gateway-name";

// Suffixes that mark per-sandbox messaging integrations in the gateway's
// provider list. These are managed by `channels`, not `credentials`.
Expand Down Expand Up @@ -34,7 +35,7 @@ export function credentialsGatewayRecoveryFailureLines(kind: "query" | "reach"):
const action = kind === "query" ? "query" : "reach";
return [
` Could not ${action} the ${CLI_DISPLAY_NAME} OpenShell gateway. Is it running?`,
` Run 'openshell gateway start --name nemoclaw' or '${CLI_NAME} onboard' first.`,
` Run 'openshell gateway start --name ${DEFAULT_GATEWAY_NAME}' or '${CLI_NAME} onboard' first.`,
];
}

Expand Down
4 changes: 3 additions & 1 deletion src/lib/domain/uninstall/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@

import path from "node:path";

export const DEFAULT_GATEWAY_NAME = "nemoclaw";
import { DEFAULT_GATEWAY_NAME } from "../../state/gateway-name";

export { DEFAULT_GATEWAY_NAME };
export const NEMOCLAW_PROVIDERS = [
"nvidia-nim",
"vllm-local",
Expand Down
19 changes: 10 additions & 9 deletions src/lib/gateway-runtime-action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ const { startGatewayForRecovery } = require("./onboard") as {
import { OPENSHELL_OPERATION_TIMEOUT_MS, OPENSHELL_PROBE_TIMEOUT_MS } from "./adapters/openshell/timeouts";
import { stripAnsi } from "./adapters/openshell/client";
import { captureOpenshell, runOpenshell } from "./adapters/openshell/runtime";
import { DEFAULT_GATEWAY_NAME } from "./state/gateway-name";

function hasNamedGateway(output = ""): boolean {
return stripAnsi(output).includes("Gateway: nemoclaw");
return stripAnsi(output).includes(`Gateway: ${DEFAULT_GATEWAY_NAME}`);
}

function getActiveGatewayName(output = ""): string | null {
Expand All @@ -19,7 +20,7 @@ function getActiveGatewayName(output = ""): string | null {

export function getNamedGatewayLifecycleState() {
const status = captureOpenshell(["status"], { timeout: OPENSHELL_PROBE_TIMEOUT_MS });
const gatewayInfo = captureOpenshell(["gateway", "info", "-g", "nemoclaw"], {
const gatewayInfo = captureOpenshell(["gateway", "info", "-g", DEFAULT_GATEWAY_NAME], {
timeout: OPENSHELL_PROBE_TIMEOUT_MS,
});
const cleanStatus = stripAnsi(status.output);
Expand All @@ -29,23 +30,23 @@ export function getNamedGatewayLifecycleState() {
const refusing = /Connection refused|client error \(Connect\)|tcp connect error/i.test(
cleanStatus,
);
if (connected && activeGateway === "nemoclaw" && named) {
if (connected && activeGateway === DEFAULT_GATEWAY_NAME && named) {
return {
state: "healthy_named",
status: status.output,
gatewayInfo: gatewayInfo.output,
activeGateway,
};
}
if (activeGateway === "nemoclaw" && named && refusing) {
if (activeGateway === DEFAULT_GATEWAY_NAME && named && refusing) {
return {
state: "named_unreachable",
status: status.output,
gatewayInfo: gatewayInfo.output,
activeGateway,
};
}
if (activeGateway === "nemoclaw" && named) {
if (activeGateway === DEFAULT_GATEWAY_NAME && named) {
return {
state: "named_unhealthy",
status: status.output,
Expand Down Expand Up @@ -93,13 +94,13 @@ export async function recoverNamedGatewayRuntime(options: RecoverNamedGatewayRun
return { recovered: false, before, after: before, attempted: false };
}

runOpenshell(["gateway", "select", "nemoclaw"], {
runOpenshell(["gateway", "select", DEFAULT_GATEWAY_NAME], {
ignoreError: true,
timeout: OPENSHELL_OPERATION_TIMEOUT_MS,
});
let after = getNamedGatewayLifecycleState();
if (after.state === "healthy_named") {
process.env.OPENSHELL_GATEWAY = "nemoclaw";
process.env.OPENSHELL_GATEWAY = DEFAULT_GATEWAY_NAME;
return { recovered: true, before, after, attempted: true, via: "select" };
}

Expand All @@ -115,13 +116,13 @@ export async function recoverNamedGatewayRuntime(options: RecoverNamedGatewayRun
// Fall through to the lifecycle re-check below so we preserve the
// existing recovery result shape and emit the correct classification.
}
runOpenshell(["gateway", "select", "nemoclaw"], {
runOpenshell(["gateway", "select", DEFAULT_GATEWAY_NAME], {
ignoreError: true,
timeout: OPENSHELL_OPERATION_TIMEOUT_MS,
});
after = getNamedGatewayLifecycleState();
if (after.state === "healthy_named") {
process.env.OPENSHELL_GATEWAY = "nemoclaw";
process.env.OPENSHELL_GATEWAY = DEFAULT_GATEWAY_NAME;
return { recovered: true, before, after, attempted: true, via: "start" };
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/lib/inference/live.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import type { CaptureOpenshellResult } from "../adapters/openshell/client";
import { stripAnsi } from "../adapters/openshell/client";
import { DEFAULT_GATEWAY_NAME } from "../state/gateway-name";
import { parseGatewayInference, type GatewayInference } from "./config";

type CaptureLiveInference = (
Expand All @@ -26,7 +27,7 @@ export function getLiveGatewayInference(
opts: { timeout?: number } = {},
): LiveGatewayInferenceResult {
const attempts = [
["inference", "get", "-g", "nemoclaw"],
["inference", "get", "-g", DEFAULT_GATEWAY_NAME],
["inference", "get"],
];
let last: LiveGatewayInferenceResult = {
Expand Down
3 changes: 2 additions & 1 deletion src/lib/inventory/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { CLI_NAME } from "../cli/branding";
import type { GatewayInference } from "../inference/config";
import { redactFull } from "../security/redact";
import { DEFAULT_GATEWAY_NAME } from "../state/gateway-name";

export interface SandboxEntry {
name: string;
Expand Down Expand Up @@ -453,7 +454,7 @@ export function showStatusCommand(deps: ShowStatusCommandDeps): void {
const detail = health.reason ? ` (${health.reason})` : "";
log(` gateway: down [${health.state}]${detail}`);
log(
` Run 'openshell gateway start --name nemoclaw' or 'nemoclaw onboard --resume' to recover.`,
` Run 'openshell gateway start --name ${DEFAULT_GATEWAY_NAME}' or 'nemoclaw onboard --resume' to recover.`,
);
process.exitCode = 1;
}
Expand Down
8 changes: 4 additions & 4 deletions src/lib/onboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ const USE_COLOR = !process.env.NO_COLOR && !!process.stdout.isTTY;
const DIM = USE_COLOR ? "\x1b[2m" : "";
const RESET = USE_COLOR ? "\x1b[0m" : "";
let OPENSHELL_BIN: string | null = null;
const GATEWAY_NAME = "nemoclaw";
const GATEWAY_NAME = gatewayState.getGatewayName(GATEWAY_PORT);
const OPENCLAW_LAUNCH_AGENT_PLIST = "~/Library/LaunchAgents/ai.openclaw.gateway.plist";

const BRAVE_SEARCH_HELP_URL = "https://brave.com/search/api/";
Expand Down Expand Up @@ -2755,9 +2755,9 @@ const { getSandboxRuntimeRegistryFields, hasSandboxGpuDrift, updateReusedSandbox
isLinuxDockerDriverGatewayEnabled,
getInstalledOpenshellVersion,
runCaptureOpenshell,
getActiveGatewayName: () => GATEWAY_NAME,
});


// ── Step 5: Sandbox ──────────────────────────────────────────────

async function createSandbox(
Expand Down Expand Up @@ -3797,7 +3797,7 @@ async function createSandbox(
// openshell tags images with seconds; buildId is ms. Parse actual tag from output. Fixes #2672.
const resolvedImageTag = resolveSandboxImageTagFromCreateOutput(createResult.output, buildId);

const sandboxRuntimeFields = getSandboxRuntimeRegistryFields(effectiveSandboxGpuConfig);
const sandboxRuntimeFields = getSandboxRuntimeRegistryFields(effectiveSandboxGpuConfig, GATEWAY_NAME);
registry.registerSandbox({
name: sandboxName,
model: model || null,
Expand Down Expand Up @@ -6624,7 +6624,7 @@ async function onboard(opts: OnboardOptions = {}): Promise<void> {
session = onboardSession.saveSession(
onboardSession.createSession({
mode: isNonInteractive() ? "non-interactive" : "interactive",
metadata: { gatewayName: "nemoclaw", fromDockerfile: fromDockerfile || null },
metadata: { gatewayName: GATEWAY_NAME, fromDockerfile: fromDockerfile || null },
}),
);
}
Expand Down
3 changes: 2 additions & 1 deletion src/lib/onboard/docker-gpu-patch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
dockerRunDetached,
dockerStop,
} from "../adapters/docker";
import { DEFAULT_GATEWAY_NAME } from "../state/gateway-name";
import { envInt } from "./env";

export const OPENSHELL_MANAGED_BY_LABEL = "openshell.ai/managed-by";
Expand Down Expand Up @@ -1253,7 +1254,7 @@ export function collectDockerGpuPatchDiagnostics(
const captures: Array<[string, string[]]> = [
["openshell-sandbox-get.txt", ["sandbox", "get", sandboxName]],
["openshell-sandbox-list.txt", ["sandbox", "list"]],
["openshell-logs.txt", ["doctor", "logs", "--name", "nemoclaw"]],
["openshell-logs.txt", ["doctor", "logs", "--name", DEFAULT_GATEWAY_NAME]],
];
for (const [fileName, args] of captures) {
try {
Expand Down
Loading
Loading