Onboard: address profile picker review feedback

This commit is contained in:
Tak Hoffman 2026-03-05 17:41:38 -06:00
parent cf7c36ac65
commit 70c5f75fb4
4 changed files with 57 additions and 12 deletions

View File

@ -4,6 +4,13 @@ import type { GatewayDaemonRuntime } from "./daemon-runtime.js";
export type { ToolProfileId } from "../config/types.tools.js";
export const VALID_TOOLS_PROFILES = new Set<ToolProfileId>([
"minimal",
"coding",
"messaging",
"full",
]);
export type OnboardMode = "local" | "remote";
export type AuthChoice =
// Legacy alias for `setup-token` (kept for backwards CLI compatibility).

View File

@ -8,10 +8,9 @@ import { isDeprecatedAuthChoice, normalizeLegacyOnboardAuthChoice } from "./auth
import { DEFAULT_WORKSPACE, handleReset } from "./onboard-helpers.js";
import { runInteractiveOnboarding } from "./onboard-interactive.js";
import { runNonInteractiveOnboarding } from "./onboard-non-interactive.js";
import type { OnboardOptions, ResetScope } from "./onboard-types.js";
import { VALID_TOOLS_PROFILES, type OnboardOptions, type ResetScope } from "./onboard-types.js";
const VALID_RESET_SCOPES = new Set<ResetScope>(["config", "config+creds+sessions", "full"]);
const VALID_TOOLS_PROFILES = new Set(["minimal", "coding", "messaging", "full"]);
export async function onboardCommand(opts: OnboardOptions, runtime: RuntimeEnv = defaultRuntime) {
assertSupportedRuntime(runtime);

View File

@ -275,7 +275,7 @@ describe("runOnboardingWizard", () => {
expect(prompter.outro).toHaveBeenCalled();
});
it("skips prompts and setup steps when flags are set", async () => {
it("skips channel/skill/health setup but still prompts for tool profile", async () => {
const select = vi.fn(async (params: WizardSelectParams<unknown>) => {
if (params.message === "Tool access profile") {
return "messaging";
@ -599,4 +599,40 @@ describe("runOnboardingWizard", () => {
}),
);
});
it("ignores invalid toolsProfile option and still prompts for a valid profile", async () => {
writeConfigFile.mockClear();
const select = vi.fn(async (params: WizardSelectParams<unknown>) => {
if (params.message === "Tool access profile") {
return "messaging";
}
return "quickstart";
}) as unknown as WizardPrompter["select"];
const prompter = buildWizardPrompter({ select });
await runOnboardingWizard(
{
acceptRisk: true,
flow: "quickstart",
mode: "local",
toolsProfile: "invalid" as never,
authChoice: "skip",
installDaemon: false,
skipProviders: true,
skipSkills: true,
skipHealth: true,
skipUi: true,
},
createRuntime(),
prompter,
);
expect(select).toHaveBeenCalledWith(
expect.objectContaining({
message: "Tool access profile",
}),
);
const firstWrite = writeConfigFile.mock.calls[0]?.[0] as { tools?: { profile?: string } };
expect(firstWrite?.tools?.profile).toBe("messaging");
});
});

View File

@ -1,10 +1,11 @@
import { formatCliCommand } from "../cli/command-format.js";
import type {
GatewayAuthChoice,
OnboardMode,
OnboardOptions,
ResetScope,
ToolProfileId,
import {
VALID_TOOLS_PROFILES,
type GatewayAuthChoice,
type OnboardMode,
type OnboardOptions,
type ResetScope,
type ToolProfileId,
} from "../commands/onboard-types.js";
import type { OpenClawConfig } from "../config/config.js";
import {
@ -71,8 +72,6 @@ async function requireRiskAcknowledgement(params: {
}
}
const VALID_TOOLS_PROFILES = new Set<ToolProfileId>(["minimal", "coding", "messaging", "full"]);
const TOOL_PROFILE_CHOICES: Array<{ value: ToolProfileId; label: string; hint: string }> = [
{
value: "messaging",
@ -438,8 +437,12 @@ export async function runOnboardingWizard(
? existingToolsProfile
: undefined
: undefined;
const explicitToolsProfile =
typeof opts.toolsProfile === "string" && VALID_TOOLS_PROFILES.has(opts.toolsProfile)
? opts.toolsProfile
: undefined;
const toolsProfile =
opts.toolsProfile ??
explicitToolsProfile ??
(await prompter.select({
message: "Tool access profile",
options: TOOL_PROFILE_CHOICES,