Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion ci/source-architecture-budget.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"src/lib/actions/uninstall/run-plan.ts": 26,
"src/lib/inference/onboard-probes.ts": 20,
"src/lib/inference/vllm.ts": 21,
"src/lib/onboard.ts": 211,
"src/lib/onboard.ts": 210,
"src/lib/onboard/machine/handlers/sandbox.ts": 21,
"src/lib/sandbox/config.ts": 22,
"src/lib/shields/index.ts": 23
Expand Down
60 changes: 29 additions & 31 deletions src/lib/onboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,6 @@ const {
runSandboxProviderPreDeleteCleanup,
} =
require("./onboard/sandbox-provider-cleanup") as typeof import("./onboard/sandbox-provider-cleanup");
const nameValidation: typeof import("./name-validation") = require("./name-validation");
const { getNameValidationGuidance } = nameValidation;
const docker: typeof import("./adapters/docker") = require("./adapters/docker");
const {
dockerContainerInspectFormat,
Expand Down Expand Up @@ -238,7 +236,6 @@ const {
prepareOllamaModel,
printOllamaExposureWarning,
promptOllamaModel,
startOllamaAuthProxy,
} = require("./inference/ollama/proxy");
const {
installOllamaOnWindowsHost,
Expand Down Expand Up @@ -441,7 +438,6 @@ const sandboxRecreateTransaction: typeof import("./onboard/sandbox-recreate-tran
const sandboxRegistration: typeof import("./onboard/sandbox-registration") =
require("./onboard/sandbox-registration");
const {
RESERVED_SANDBOX_NAMES,
formatSandboxAgentName,
getAgentInferenceProviderOptions,
getDefaultSandboxNameForAgent,
Expand Down Expand Up @@ -3733,8 +3729,13 @@ async function runOnboard(opts: OnboardOptions = {}): Promise<void> {
);
setOnboardBrandingAgent(opts.agent || process.env.NEMOCLAW_AGENT || null);
AUTO_YES = opts.autoYes === true || process.env.NEMOCLAW_YES === "1";
// biome-ignore format: keep src/lib/onboard.ts net-neutral for growth guardrail.
const { fresh, nonInteractive, requestedFromDockerfile, requestedSandboxName, cannotPrompt, resume } = onboardEntryOptions.resolveOnboardRunEntryOptions(opts, process.env, onboardSession.loadSession()?.status ?? null, isNonInteractiveEnv, { validateName, reservedSandboxNames: RESERVED_SANDBOX_NAMES, cliDisplayName, getNameValidationGuidance, error: (message) => console.error(message), exitProcess: (code) => process.exit(code) });
const entryOptions = onboardEntryOptions.resolveDefaultRunEntryOptions(
opts,
onboardSession.loadSession()?.status ?? null,
validateName,
);
const { fresh, nonInteractive, cannotPrompt, resume } = entryOptions;
const { requestedFromDockerfile, requestedSandboxName } = entryOptions;
Comment on lines +3732 to +3738

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

ast-grep outline src/lib/onboard.ts --match runOnboard --view expanded

rg -n -C 3 \
  --glob '*.{test,spec}.ts' \
  'runOnboard|resolveDefaultRunEntryOptions|createDefaultProviderReviewDeps|resolveOnboardRunEntryOptions|createProviderReviewDeps' \
  .

rg -n -C 3 \
  'resolveDefaultRunEntryOptions|createDefaultProviderReviewDeps|resolveOnboardRunEntryOptions|createProviderReviewDeps' \
  src

Repository: NVIDIA/NemoClaw

Length of output: 50372


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- relevant files ---'
git ls-files \
  'src/lib/onboard*' \
  'test/*onboard*' \
  'src/lib/actions/*onboard*' \
  'src/commands/*onboard*' |
  rg '(entry-options|setup-inference|onboard(\.test)?|lifecycle|resume|inference|provider)' |
  head -200

printf '%s\n' '--- exact symbol references in source and tests ---'
rg -n --glob '*.ts' \
  'resolveDefaultRunEntryOptions|createDefaultProviderReviewDeps|resolveOnboardRunEntryOptions|createProviderReviewDeps' \
  src test

printf '%s\n' '--- runOnboard definitions and calls ---'
rg -n -C 8 --glob '*.ts' \
  'function runOnboard|const runOnboard|wrapOnboard\(runOnboard|createDefaultProviderReviewDeps' \
  src/lib/onboard.ts src/lib/onboard test src/commands

printf '%s\n' '--- focused test filenames ---'
git ls-files '*test.ts' |
  while read -r f; do
    if rg -q 'resolveDefaultRunEntryOptions|createDefaultProviderReviewDeps|resolveOnboardRunEntryOptions|createProviderReviewDeps' "$f"; then
      printf '%s\n' "$f"
    fi
  done

Repository: NVIDIA/NemoClaw

Length of output: 9447


🏁 Script executed:

#!/bin/bash
set -u

printf '%s\n' '--- entry-options implementation ---'
cat -n src/lib/onboard/entry-options.ts | sed -n '1,180p'

printf '%s\n' '--- setup-inference implementation ---'
cat -n src/lib/onboard/setup-inference.ts | sed -n '1,130p'

printf '%s\n' '--- runOnboard entry wiring ---'
cat -n src/lib/onboard.ts | sed -n '3690,3765p'
cat -n src/lib/onboard.ts | sed -n '4035,4105p'

printf '%s\n' '--- exact symbol references ---'
rg -n --glob '*.ts' \
  'resolveDefaultRunEntryOptions|createDefaultProviderReviewDeps|resolveOnboardRunEntryOptions|createProviderReviewDeps' \
  src test || true

printf '%s\n' '--- candidate direct onboarding tests ---'
for f in \
  src/lib/onboard/entry-options.test.ts \
  src/lib/onboard/setup-inference.test.ts \
  src/lib/onboard/command.test.ts \
  src/lib/onboard/command-support.test.ts \
  src/commands/onboard.test.ts \
  src/lib/actions/onboard.test.ts \
  test/onboard-lifecycle.test.ts
do
  if [ -f "$f" ]; then
    printf '\n--- %s ---\n' "$f"
    rg -n -C 5 \
      'fresh|resume|provider|inference|entry|factory|dependency|runOnboard|onboard' \
      "$f" | head -240 || true
  fi
done

Repository: NVIDIA/NemoClaw

Length of output: 50371


🏁 Script executed:

#!/bin/bash
set -u

printf '%s\n' '--- lifecycle test structure and assertions ---'
rg -n -C 4 \
  'describe|it\(|runOnboardEntrypoint|resume|fresh|provider|inference|sandboxName|mode|calls|events' \
  test/onboard-lifecycle.test.ts | head -320 || true

printf '%s\n' '--- entry-options test imports and test list ---'
sed -n '1,330p' src/lib/onboard/entry-options.test.ts |
  rg -n '^(import|describe|  it|  it\.each|  \}\)|export)|resolveDefault|resolveOnboard' || true

printf '%s\n' '--- setup-inference test imports and test list ---'
cat -n src/lib/onboard/setup-inference.test.ts | sed -n '1,190p'

printf '%s\n' '--- provider-review recovery test references ---'
rg -n -C 8 \
  'createProviderReviewDeps|providerReviewDeps|prepareLocalProviderForInference|checkpointSandboxIdentity' \
  src/lib/onboard/machine/handlers/provider-review-recovery.test.ts || true

printf '%s\n' '--- targeted diff summary ---'
git diff --stat -- src/lib/onboard.ts src/lib/onboard/entry-options.ts src/lib/onboard/setup-inference.ts \
  src/lib/onboard/entry-options.test.ts src/lib/onboard/setup-inference.test.ts || true

Repository: NVIDIA/NemoClaw

Length of output: 27071


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
import re

symbols = (
    "resolveDefaultRunEntryOptions",
    "createDefaultProviderReviewDeps",
    "resolveOnboardRunEntryOptions",
    "createProviderReviewDeps",
)

for symbol in symbols:
    refs = []
    for path in Path("src").rglob("*.ts"):
        text = path.read_text(encoding="utf-8")
        for line_no, line in enumerate(text.splitlines(), 1):
            if re.search(rf"\b{re.escape(symbol)}\b", line):
                refs.append(f"{path}:{line_no}")
    print(f"{symbol}:")
    for ref in refs:
        print(f"  {ref}")
    if not refs:
        print("  <none>")
PY

Repository: NVIDIA/NemoClaw

Length of output: 1098


Add public-entrypoint coverage for the default onboarding factories.

Existing tests cover lower-level resolvers and lifecycle behavior, but they do not prove that public fresh, resumed, and provider-review flows use resolveDefaultRunEntryOptions and createDefaultProviderReviewDeps. Add boundary assertions for their default dependencies and failure behavior.

📍 Affects 3 files
  • src/lib/onboard.ts#L3732-L3738 (this comment)
  • src/lib/onboard/entry-options.ts#L104-L118
  • src/lib/onboard/setup-inference.ts#L70-L86
  • src/lib/onboard.ts#L4074-L4077
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/onboard.ts` around lines 3732 - 3738, Add public-entrypoint tests
covering fresh, resumed, and provider-review onboarding flows. In
src/lib/onboard.ts:3732-3738, verify public flows use
resolveDefaultRunEntryOptions; in src/lib/onboard.ts:4074-4077, verify
provider-review uses createDefaultProviderReviewDeps and preserves expected
failure behavior. Add corresponding boundary coverage around
setup-inference.ts:70-86 and entry-options.ts:104-118, including default
dependency behavior and failures without changing the lower-level resolver
tests.

Source: Path instructions

NON_INTERACTIVE = nonInteractive;
RECREATE_SANDBOX = opts.recreateSandbox || process.env.NEMOCLAW_RECREATE_SANDBOX === "1";
_preflightDashboardPort =
Expand Down Expand Up @@ -4064,24 +4065,22 @@ async function runOnboard(opts: OnboardOptions = {}): Promise<void> {
requestedSandboxName,
checkpointedSandboxName,
selectedMessagingChannels,
assertSandboxNameAllowed: (sandboxName) => {
if (!RESERVED_SANDBOX_NAMES.has(sandboxName)) return;
console.error(
` Reserved name in resumed session: '${sandboxName}' is a ${cliDisplayName()} CLI command.`,
);
console.error(" Start a fresh onboard with --name <sandbox> to choose a different name.");
process.exit(1);
},
assertSandboxNameAllowed: onboardEntryOptions.assertDefaultSandboxNameAllowed,
});
// biome-ignore format: keep src/lib/onboard.ts net-neutral for growth guardrail.
const runCoreGatewayOpenshell = setupInferenceFactory.createGatewayScopedOpenshellRunner(runOpenshell, GATEWAY_NAME);
// biome-ignore format: keep src/lib/onboard.ts net-neutral for growth guardrail.
const endpointProvenance = { endpointSource: opts.endpointSource, endpointSourceProvider: opts.rebuildRegistryInferenceRoute?.route.provider ?? null, endpointSourceEndpointUrl: opts.rebuildRegistryInferenceRoute?.route.endpointUrl ?? null, getSandboxRegistryEntry: registry.getSandbox };
// biome-ignore format: keep src/lib/onboard.ts net-neutral for growth guardrail.
// biome-ignore format: keep src/lib/onboard.ts net-neutral for growth guardrail.
const providerReviewDeps = setupInferenceFactory.createProviderReviewDeps(onboardSession.updateSession, onboardSessionBootstrap.checkpointSandboxName, { shouldFrontOllamaWithProxy, startOllamaAuthProxy, getOllamaProxyToken, persistAndProbeOllamaProxy }, process.exit, console.error);
// biome-ignore format: keep src/lib/onboard.ts net-neutral for growth guardrail.
const coreFlowPhases = createCoreOnboardFlowPhases<InitialOnboardFlowContext, unknown, MessagingChannelConfig, import("./resources-cmd").ResourceProfile>({
const providerReviewDeps = setupInferenceFactory.createDefaultProviderReviewDeps(
onboardSession.updateSession,
onboardSessionBootstrap.checkpointSandboxName,
);
const coreFlowPhases = createCoreOnboardFlowPhases<
InitialOnboardFlowContext,
unknown,
MessagingChannelConfig,
import("./resources-cmd").ResourceProfile
>({
// biome-ignore format: keep src/lib/onboard.ts net-neutral for growth guardrail.
resumeProvider: { isNonInteractive, isRoutedInferenceProvider, providerExistsInGateway, replaceNamedCredential, resumeManagedLlamaCppRuntime: (sandboxName) => setupNimFlow.resumeManagedLlamaCppRuntime(sandboxName, { gatewayPort: GATEWAY_PORT, runtimeProvider: setupNimFlow.resolveCurrentRuntimeProviderBundle() }) },
providerInference: {
Expand Down Expand Up @@ -4220,19 +4219,18 @@ async function runOnboard(opts: OnboardOptions = {}): Promise<void> {
planRegisteredExtraProviders: (gatewayName) =>
planRegisteredExtraProviders(gatewayName, { runOpenshell }),
resolveSandboxCreateIntent: sandboxCreateIntentResolver.resolve,
createSandbox: preparedDcodeRuntime.bindCreateSandbox(
(...createArgs) =>
withDashboardPortReservationScope((dashboardPortReservationScope) =>
createSandboxWithBaseImageResolution(
baseImageResolutionContext,
onboardingComputePlan,
opts.managedWorkloadRebuild ?? null,
opts.tempManagedRuntime === true,
opts.tempManagedRuntimeCatalog ?? null,
dashboardPortReservationScope,
...createArgs,
),
createSandbox: preparedDcodeRuntime.bindCreateSandbox((...createArgs) =>
withDashboardPortReservationScope((dashboardPortReservationScope) =>
createSandboxWithBaseImageResolution(
baseImageResolutionContext,
onboardingComputePlan,
opts.managedWorkloadRebuild ?? null,
opts.tempManagedRuntime === true,
opts.tempManagedRuntimeCatalog ?? null,
dashboardPortReservationScope,
...createArgs,
),
),
),
updateSandboxRegistry: (name, updates) => registry.updateSandbox(name, updates),
getSandboxAgentRegistryFields,
Expand Down
29 changes: 29 additions & 0 deletions src/lib/onboard/entry-options.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

import { isNonInteractiveEnv } from "../core/non-interactive";
import { getNameValidationGuidance } from "../name-validation";
import { cliDisplayName } from "./branding";
import { RESERVED_SANDBOX_NAMES } from "./sandbox-agent";
import {
requireStationExpressResumeIntent,
type StationExpressSessionLike,
Expand Down Expand Up @@ -96,6 +100,31 @@ export function resolveOnboardRunEntryOptions(
}),
};
}

export function resolveDefaultRunEntryOptions(
options: OnboardEntryOptionsInput["opts"] & { autoYes?: boolean; nonInteractive?: boolean },
persistedSessionStatus: string | null,
validateSandboxName: OnboardEntryOptionsDeps["validateName"],
env: NodeJS.ProcessEnv = process.env,
) {
return resolveOnboardRunEntryOptions(options, env, persistedSessionStatus, isNonInteractiveEnv, {
validateName: validateSandboxName,
reservedSandboxNames: RESERVED_SANDBOX_NAMES,
cliDisplayName,
getNameValidationGuidance,
error: (message) => console.error(message),
exitProcess: (code) => process.exit(code),
});
}

export function assertDefaultSandboxNameAllowed(sandboxName: string): void {
if (!RESERVED_SANDBOX_NAMES.has(sandboxName)) return;
console.error(
` Reserved name in resumed session: '${sandboxName}' is a ${cliDisplayName()} CLI command.`,
);
console.error(" Start a fresh onboard with --name <sandbox> to choose a different name.");
process.exit(1);
}
interface StationExpressSessionLifecycle {
loadSession(): StationExpressSessionLike | null;
reconcileStationExpressReceiptRetirement(generation: string): void;
Expand Down
24 changes: 24 additions & 0 deletions src/lib/onboard/setup-inference.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,19 @@ import {
} from "../inference/gateway-route-compatibility";
import { withGatewayRouteMutationLock } from "../inference/gateway-route-mutation-lock";
import { getManagedVllmProviderBinding } from "../inference/local";
import {
getOllamaProxyToken,
persistAndProbeOllamaProxy,
startOllamaAuthProxy,
} from "../inference/ollama/proxy";
import {
assertNoExplicitOpenShellGatewayEndpoint,
assertNoOpenShellGatewayEndpointOverride,
type OpenShellGatewayEndpointEnvironment,
} from "../openshell-gateway-endpoint-guard";
import { withSandboxMutationLock } from "../state/mcp-lifecycle-lock";
import type { Session } from "../state/onboard-session";
import { shouldFrontOllamaWithProxy } from "./local-inference-topology";

export { assertNoOpenShellGatewayEndpointOverride };

Expand Down Expand Up @@ -61,6 +67,24 @@ export function createProviderReviewDeps(
};
}

export function createDefaultProviderReviewDeps(
updateSession: Parameters<typeof createProviderReviewDeps>[0],
checkpointSandboxName: Parameters<typeof createProviderReviewDeps>[1],
) {
return createProviderReviewDeps(
updateSession,
checkpointSandboxName,
{
shouldFrontOllamaWithProxy,
startOllamaAuthProxy,
getOllamaProxyToken,
persistAndProbeOllamaProxy,
},
process.exit,
console.error,
);
}

import type { HermesAuthMethod } from "./hermes-auth";

function matchesOnboardEndpoint(
Expand Down
Loading