Skip to content

Commit 08a49f8

Browse files
committed
test(onboard): cover profile provider cleanup
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
1 parent 33cd1a2 commit 08a49f8

2 files changed

Lines changed: 56 additions & 42 deletions

File tree

docs/inference/set-up-vllm.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ $$nemoclaw onboard --profile <profile-id>
119119
```
120120

121121
The same profile selector works with interactive and non-interactive onboarding.
122+
NemoClaw selects the inference provider required by the profile's backend, so onboarding does not show the provider menu.
123+
If the profile's backend has no corresponding inference provider, onboarding exits before it changes runtime resources.
122124
NemoClaw rejects unknown, ambiguous, disabled, incompatible, or conflicting selections before image or model downloads begin.
123125
Before confirmation, the review screen shows the resolved profile and recipe IDs, model, immutable runtime image, support state, and estimated image and model downloads.
124126
Do not combine `--profile` with `NEMOCLAW_PROVIDER`, `NEMOCLAW_MODEL`, `NEMOCLAW_VLLM_MODEL`, `NEMOCLAW_MANAGED_CLUSTER_PEERS`, or `NEMOCLAW_VLLM_EXTRA_ARGS_JSON` overrides.

src/lib/onboard/command.test.ts

Lines changed: 54 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -687,49 +687,61 @@ describe("onboard command options", () => {
687687
}
688688
});
689689

690-
it("restores every scoped command value before exiting on a handled error (#9035)", async () => {
691-
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-handled-error-environment-"));
692-
const manifestPath = path.join(tmpDir, "agents.yaml");
693-
fs.writeFileSync(manifestPath, "agents: []\n");
694-
const env: NodeJS.ProcessEnv = {
695-
NEMOCLAW_EXTRA_AGENTS_JSON: "previous-agents",
696-
NEMOCLAW_OLLAMA_NO_AUTOSTART: "previous-autostart",
697-
NEMOCLAW_SERVING_PRESET: "previous-serving",
698-
NEMOCLAW_TOOL_DISCLOSURE: "previous-disclosure",
699-
};
700-
let environmentAtExit: NodeJS.ProcessEnv | null = null;
701-
702-
try {
703-
await expect(
704-
runOnboardCommand({
705-
flags: {
706-
agents: manifestPath,
707-
"no-ollama-autostart": true,
708-
profile: COMPATIBLE_NANO_PROFILE.id,
709-
"tool-disclosure": "direct",
710-
},
711-
env,
712-
listServingProfiles: () => [COMPATIBLE_NANO_PROFILE],
713-
runOnboard: async () => {
714-
throw invalidGatewayManagementDeclarationError("unsupported contract");
715-
},
716-
error: () => {},
717-
exit: (code): never => {
718-
environmentAtExit = { ...env };
719-
throw new Error(`exit:${code}`);
720-
},
721-
}),
722-
).rejects.toThrow("exit:1");
723-
expect(environmentAtExit).toEqual({
690+
it.each([
691+
{ providerState: "unset", previousProvider: undefined },
692+
{ providerState: "blank", previousProvider: "" },
693+
])(
694+
"restores every scoped command value before a handled-error exit when the provider is $providerState (#9035)",
695+
async ({ previousProvider }) => {
696+
const tmpDir = fs.mkdtempSync(
697+
path.join(os.tmpdir(), "nemoclaw-handled-error-environment-"),
698+
);
699+
const manifestPath = path.join(tmpDir, "agents.yaml");
700+
fs.writeFileSync(manifestPath, "agents: []\n");
701+
const env: NodeJS.ProcessEnv = {
724702
NEMOCLAW_EXTRA_AGENTS_JSON: "previous-agents",
725703
NEMOCLAW_OLLAMA_NO_AUTOSTART: "previous-autostart",
726-
NEMOCLAW_SERVING_PRESET: "previous-serving",
704+
NEMOCLAW_SERVING_PRESET: COMPATIBLE_NANO_PROFILE.id,
727705
NEMOCLAW_TOOL_DISCLOSURE: "previous-disclosure",
706+
...(previousProvider === undefined ? {} : { NEMOCLAW_PROVIDER: previousProvider }),
707+
};
708+
let environmentAtExit: NodeJS.ProcessEnv | null = null;
709+
const runOnboard = vi.fn(async () => {
710+
throw invalidGatewayManagementDeclarationError("unsupported contract");
728711
});
729-
} finally {
730-
fs.rmSync(tmpDir, { recursive: true, force: true });
731-
}
732-
});
712+
713+
try {
714+
await expect(
715+
runOnboardCommand({
716+
flags: {
717+
agents: manifestPath,
718+
"no-ollama-autostart": true,
719+
profile: COMPATIBLE_NANO_PROFILE.id,
720+
"tool-disclosure": "direct",
721+
},
722+
env,
723+
listServingProfiles: () => [COMPATIBLE_NANO_PROFILE],
724+
runOnboard,
725+
error: () => {},
726+
exit: (code): never => {
727+
environmentAtExit = { ...env };
728+
throw new Error(`exit:${code}`);
729+
},
730+
}),
731+
).rejects.toThrow("exit:1");
732+
expect(runOnboard).toHaveBeenCalledOnce();
733+
expect(environmentAtExit).toEqual({
734+
NEMOCLAW_EXTRA_AGENTS_JSON: "previous-agents",
735+
NEMOCLAW_OLLAMA_NO_AUTOSTART: "previous-autostart",
736+
NEMOCLAW_SERVING_PRESET: COMPATIBLE_NANO_PROFILE.id,
737+
NEMOCLAW_TOOL_DISCLOSURE: "previous-disclosure",
738+
...(previousProvider === undefined ? {} : { NEMOCLAW_PROVIDER: previousProvider }),
739+
});
740+
} finally {
741+
fs.rmSync(tmpDir, { recursive: true, force: true });
742+
}
743+
},
744+
);
733745

734746
it("scopes the selected catalog preset to one onboarding run (#8384)", async () => {
735747
const env: NodeJS.ProcessEnv = {};
@@ -748,7 +760,7 @@ describe("onboard command options", () => {
748760
expect(env.NEMOCLAW_SERVING_PRESET).toBeUndefined();
749761
});
750762

751-
it("selects the profile's backend provider so onboarding skips the menu (#9313)", async () => {
763+
it("selects the profile's inference provider so onboarding skips the menu (#9313)", async () => {
752764
// The preset alone only picks the model once a provider is chosen. Without
753765
// a provider the run fell through to the interactive provider menu with the
754766
// requested profile never applied.
@@ -837,7 +849,7 @@ describe("onboard command options", () => {
837849
// reports instead of accepting the flag and then asking for a provider.
838850
const withBackend = (backend: string) => ({ recipe: { backend } }) as never;
839851

840-
// Pinned against the provider menu's own key so the two cannot drift.
852+
// Uses the provider menu's exported key so the two cannot drift.
841853
expect(servingProfileProviderKey(withBackend("vllm"))).toBe(MANAGED_VLLM_PROVIDER_KEY);
842854
expect(servingProfileProviderKey(withBackend("install-llama-cpp"))).toBe("install-llama-cpp");
843855
expect(servingProfileProviderKey(withBackend("future-backend"))).toBeNull();
@@ -1061,7 +1073,7 @@ describe("onboard command options", () => {
10611073
name: "serving profile",
10621074
flags: { profile: COMPATIBLE_NANO_PROFILE.id } as OnboardFlags,
10631075
listServingProfiles: () => [COMPATIBLE_NANO_PROFILE],
1064-
keys: ["NEMOCLAW_SERVING_PRESET"],
1076+
keys: ["NEMOCLAW_PROVIDER", "NEMOCLAW_SERVING_PRESET"],
10651077
},
10661078
])("restores the $name environment when an agents manifest is invalid", async (testCase) => {
10671079
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-invalid-agents-manifest-"));

0 commit comments

Comments
 (0)