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
10 changes: 4 additions & 6 deletions src/lib/onboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ import type {
OpenShellInstallResult,
} from "./onboard/openshell-install";
import { decidePolicyCarryForward } from "./onboard/policy-carryforward";
import { resolveSandboxGpuMode, type SandboxGpuFlag, type SandboxGpuMode } from "./onboard/sandbox-gpu-mode";
import type { SelectionDrift } from "./onboard/selection-drift";
import type {
ModelCatalogFetchResult,
Expand Down Expand Up @@ -1240,9 +1241,6 @@ function shouldAllowOpenshellAboveBlueprintMax(
return shouldUseOpenshellDevChannel(platform, env) && isOpenshellDevVersion(versionOutput);
}

type SandboxGpuMode = "auto" | "1" | "0";
type SandboxGpuFlag = "enable" | "disable" | null;

type SandboxGpuConfig = {
mode: SandboxGpuMode;
hostGpuDetected: boolean;
Expand Down Expand Up @@ -1287,9 +1285,7 @@ function resolveSandboxGpuConfig(
errors.push("NEMOCLAW_SANDBOX_GPU must be one of: auto, 1, 0.");
}

let mode: SandboxGpuMode = envMode ?? "auto";
if (options.flag === "enable") mode = "1";
if (options.flag === "disable") mode = "0";
let mode = resolveSandboxGpuMode({ envMode, gpu, flag: options.flag });

const device = (options.device ?? env.NEMOCLAW_SANDBOX_GPU_DEVICE ?? "").trim() || null;
if (device && mode === "0") {
Expand Down Expand Up @@ -10035,6 +10031,8 @@ async function onboard(opts: OnboardOptions = {}): Promise<void> {
? " GPU passthrough requested; passing --gpu to OpenShell gateway and sandbox creation."
: " NVIDIA GPU detected; enabling OpenShell GPU passthrough. Use --no-gpu to opt out.",
);
} else if (gpu?.platform === "jetson") {
note(" GPU sandbox passthrough disabled by default on Jetson.");
} else if (process.platform === "linux") {
// Hint when hardware is present but drivers are missing.
try {
Expand Down
20 changes: 20 additions & 0 deletions src/lib/onboard/sandbox-gpu-mode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

import type { GpuDetection } from "../inference/nim";

export type SandboxGpuMode = "auto" | "1" | "0";
export type SandboxGpuFlag = "enable" | "disable" | null;

export function resolveSandboxGpuMode(args: {
envMode: SandboxGpuMode | null;
gpu: GpuDetection | null | undefined;
flag?: SandboxGpuFlag;
}): SandboxGpuMode {
let mode: SandboxGpuMode = args.envMode ?? "auto";
// GPU sandbox passthrough does not currently work on Jetson; disable by default
if (args.gpu?.platform === "jetson" && args.envMode === null) mode = "0";
if (args.flag === "enable") mode = "1";
if (args.flag === "disable") mode = "0";
return mode;
}
11 changes: 11 additions & 0 deletions test/onboard.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,17 @@ describe("onboard helpers", () => {
expect(forced.errors.join("\n")).toContain("no NVIDIA GPU");
});

it("defaults to CPU sandbox on Jetson when NEMOCLAW_SANDBOX_GPU is unset", () => {
const jetson = { type: "nvidia", platform: "jetson" as const };
expect(resolveSandboxGpuConfig(jetson, { env: {} }).sandboxGpuEnabled).toBe(false);
// Explicit env opt-in still wins over the platform default.
expect(
resolveSandboxGpuConfig(jetson, { env: { NEMOCLAW_SANDBOX_GPU: "1" } }).sandboxGpuEnabled,
).toBe(true);
// --gpu also overrides the platform default.
expect(resolveSandboxGpuConfig(jetson, { flag: "enable", env: {} }).mode).toBe("1");
});

it("resumes sandbox GPU auto mode without turning CPU fallback into explicit opt-out", () => {
const resumedAuto = getResumeSandboxGpuOverrides(
{ sandboxGpuMode: "auto", sandboxGpuDevice: null },
Expand Down
Loading