mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-18 13:30:48 +00:00
refactor: make setup the primary wizard surface
This commit is contained in:
@@ -169,7 +169,7 @@ describe("registerPreActionHooks", () => {
|
||||
expect(ensurePluginRegistryLoadedMock).toHaveBeenCalledWith({ scope: "all" });
|
||||
});
|
||||
|
||||
it("keeps onboarding and channels add manifest-first", async () => {
|
||||
it("keeps setup alias and channels add manifest-first", async () => {
|
||||
await runPreAction({
|
||||
parseArgv: ["onboard"],
|
||||
processArgv: ["node", "openclaw", "onboard"],
|
||||
|
||||
@@ -78,7 +78,7 @@ function shouldLoadPluginsForCommand(commandPath: string[], argv: string[]): boo
|
||||
if ((primary === "status" || primary === "health") && hasFlag(argv, "--json")) {
|
||||
return false;
|
||||
}
|
||||
// Onboarding/setup should stay manifest-first and load selected plugins on demand.
|
||||
// Setup wizard and channels add should stay manifest-first and load selected plugins on demand.
|
||||
if (primary === "onboard" || (primary === "channels" && secondary === "add")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Command } from "commander";
|
||||
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const onboardCommandMock = vi.fn();
|
||||
const setupWizardCommandMock = vi.fn();
|
||||
|
||||
const runtime = {
|
||||
log: vi.fn(),
|
||||
@@ -23,7 +23,7 @@ vi.mock("../../commands/onboard-provider-auth-flags.js", () => ({
|
||||
}));
|
||||
|
||||
vi.mock("../../commands/onboard.js", () => ({
|
||||
onboardCommand: onboardCommandMock,
|
||||
setupWizardCommand: setupWizardCommandMock,
|
||||
}));
|
||||
|
||||
vi.mock("../../runtime.js", () => ({
|
||||
@@ -45,13 +45,13 @@ describe("registerOnboardCommand", () => {
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
onboardCommandMock.mockResolvedValue(undefined);
|
||||
setupWizardCommandMock.mockResolvedValue(undefined);
|
||||
});
|
||||
|
||||
it("defaults installDaemon to undefined when no daemon flags are provided", async () => {
|
||||
await runCli(["onboard"]);
|
||||
|
||||
expect(onboardCommandMock).toHaveBeenCalledWith(
|
||||
expect(setupWizardCommandMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
installDaemon: undefined,
|
||||
}),
|
||||
@@ -61,7 +61,7 @@ describe("registerOnboardCommand", () => {
|
||||
|
||||
it("sets installDaemon from explicit install flags and prioritizes --skip-daemon", async () => {
|
||||
await runCli(["onboard", "--install-daemon"]);
|
||||
expect(onboardCommandMock).toHaveBeenNthCalledWith(
|
||||
expect(setupWizardCommandMock).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
expect.objectContaining({
|
||||
installDaemon: true,
|
||||
@@ -70,7 +70,7 @@ describe("registerOnboardCommand", () => {
|
||||
);
|
||||
|
||||
await runCli(["onboard", "--no-install-daemon"]);
|
||||
expect(onboardCommandMock).toHaveBeenNthCalledWith(
|
||||
expect(setupWizardCommandMock).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
expect.objectContaining({
|
||||
installDaemon: false,
|
||||
@@ -79,7 +79,7 @@ describe("registerOnboardCommand", () => {
|
||||
);
|
||||
|
||||
await runCli(["onboard", "--install-daemon", "--skip-daemon"]);
|
||||
expect(onboardCommandMock).toHaveBeenNthCalledWith(
|
||||
expect(setupWizardCommandMock).toHaveBeenNthCalledWith(
|
||||
3,
|
||||
expect.objectContaining({
|
||||
installDaemon: false,
|
||||
@@ -90,7 +90,7 @@ describe("registerOnboardCommand", () => {
|
||||
|
||||
it("parses numeric gateway port and drops invalid values", async () => {
|
||||
await runCli(["onboard", "--gateway-port", "18789"]);
|
||||
expect(onboardCommandMock).toHaveBeenNthCalledWith(
|
||||
expect(setupWizardCommandMock).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
expect.objectContaining({
|
||||
gatewayPort: 18789,
|
||||
@@ -99,7 +99,7 @@ describe("registerOnboardCommand", () => {
|
||||
);
|
||||
|
||||
await runCli(["onboard", "--gateway-port", "nope"]);
|
||||
expect(onboardCommandMock).toHaveBeenNthCalledWith(
|
||||
expect(setupWizardCommandMock).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
expect.objectContaining({
|
||||
gatewayPort: undefined,
|
||||
@@ -108,9 +108,9 @@ describe("registerOnboardCommand", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("forwards --reset-scope to onboard command options", async () => {
|
||||
it("forwards --reset-scope to setup wizard options", async () => {
|
||||
await runCli(["onboard", "--reset", "--reset-scope", "full"]);
|
||||
expect(onboardCommandMock).toHaveBeenCalledWith(
|
||||
expect(setupWizardCommandMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
reset: true,
|
||||
resetScope: "full",
|
||||
@@ -121,7 +121,7 @@ describe("registerOnboardCommand", () => {
|
||||
|
||||
it("parses --mistral-api-key and forwards mistralApiKey", async () => {
|
||||
await runCli(["onboard", "--mistral-api-key", "sk-mistral-test"]);
|
||||
expect(onboardCommandMock).toHaveBeenCalledWith(
|
||||
expect(setupWizardCommandMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
mistralApiKey: "sk-mistral-test", // pragma: allowlist secret
|
||||
}),
|
||||
@@ -131,7 +131,7 @@ describe("registerOnboardCommand", () => {
|
||||
|
||||
it("forwards --gateway-token-ref-env", async () => {
|
||||
await runCli(["onboard", "--gateway-token-ref-env", "OPENCLAW_GATEWAY_TOKEN"]);
|
||||
expect(onboardCommandMock).toHaveBeenCalledWith(
|
||||
expect(setupWizardCommandMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
gatewayTokenRefEnv: "OPENCLAW_GATEWAY_TOKEN",
|
||||
}),
|
||||
@@ -139,12 +139,12 @@ describe("registerOnboardCommand", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("reports errors via runtime on onboard command failures", async () => {
|
||||
onboardCommandMock.mockRejectedValueOnce(new Error("onboard failed"));
|
||||
it("reports errors via runtime on setup wizard command failures", async () => {
|
||||
setupWizardCommandMock.mockRejectedValueOnce(new Error("setup failed"));
|
||||
|
||||
await runCli(["onboard"]);
|
||||
|
||||
expect(runtime.error).toHaveBeenCalledWith("Error: onboard failed");
|
||||
expect(runtime.error).toHaveBeenCalledWith("Error: setup failed");
|
||||
expect(runtime.exit).toHaveBeenCalledWith(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { Command } from "commander";
|
||||
import { formatCliCommand } from "../../cli/command-format.js";
|
||||
import { formatStaticAuthChoiceChoicesForCli } from "../../commands/auth-choice-options.static.js";
|
||||
import type { GatewayDaemonRuntime } from "../../commands/daemon-runtime.js";
|
||||
import { ONBOARD_PROVIDER_AUTH_FLAGS } from "../../commands/onboard-provider-auth-flags.js";
|
||||
@@ -11,7 +12,7 @@ import type {
|
||||
SecretInputMode,
|
||||
TailscaleMode,
|
||||
} from "../../commands/onboard-types.js";
|
||||
import { onboardCommand } from "../../commands/onboard.js";
|
||||
import { setupWizardCommand } from "../../commands/onboard.js";
|
||||
import { defaultRuntime } from "../../runtime.js";
|
||||
import { formatDocsLink } from "../../terminal/links.js";
|
||||
import { theme } from "../../terminal/theme.js";
|
||||
@@ -49,11 +50,14 @@ const AUTH_CHOICE_HELP = formatStaticAuthChoiceChoicesForCli({
|
||||
export function registerOnboardCommand(program: Command) {
|
||||
const command = program
|
||||
.command("onboard")
|
||||
.description("Interactive wizard to set up the gateway, workspace, and skills")
|
||||
.addHelpText(
|
||||
"after",
|
||||
() =>
|
||||
`\n${theme.muted("Docs:")} ${formatDocsLink("/cli/onboard", "docs.openclaw.ai/cli/onboard")}\n`,
|
||||
.description('Legacy alias for "openclaw setup --wizard"')
|
||||
.addHelpText("after", () =>
|
||||
[
|
||||
"",
|
||||
`${theme.muted("Docs:")} ${formatDocsLink("/cli/setup", "docs.openclaw.ai/cli/setup")}`,
|
||||
`${theme.muted("Prefer:")} ${formatCliCommand("openclaw setup --wizard")}`,
|
||||
"",
|
||||
].join("\n"),
|
||||
)
|
||||
.option("--workspace <dir>", "Agent workspace directory (default: ~/.openclaw/workspace)")
|
||||
.option(
|
||||
@@ -132,7 +136,7 @@ export function registerOnboardCommand(program: Command) {
|
||||
});
|
||||
const gatewayPort =
|
||||
typeof opts.gatewayPort === "string" ? Number.parseInt(opts.gatewayPort, 10) : undefined;
|
||||
await onboardCommand(
|
||||
await setupWizardCommand(
|
||||
{
|
||||
workspace: opts.workspace as string | undefined,
|
||||
nonInteractive: Boolean(opts.nonInteractive),
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Command } from "commander";
|
||||
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const setupCommandMock = vi.fn();
|
||||
const onboardCommandMock = vi.fn();
|
||||
const setupWizardCommandMock = vi.fn();
|
||||
const runtime = {
|
||||
log: vi.fn(),
|
||||
error: vi.fn(),
|
||||
@@ -14,7 +14,7 @@ vi.mock("../../commands/setup.js", () => ({
|
||||
}));
|
||||
|
||||
vi.mock("../../commands/onboard.js", () => ({
|
||||
onboardCommand: onboardCommandMock,
|
||||
setupWizardCommand: setupWizardCommandMock,
|
||||
}));
|
||||
|
||||
vi.mock("../../runtime.js", () => ({
|
||||
@@ -37,7 +37,7 @@ describe("registerSetupCommand", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
setupCommandMock.mockResolvedValue(undefined);
|
||||
onboardCommandMock.mockResolvedValue(undefined);
|
||||
setupWizardCommandMock.mockResolvedValue(undefined);
|
||||
});
|
||||
|
||||
it("runs setup command by default", async () => {
|
||||
@@ -49,13 +49,13 @@ describe("registerSetupCommand", () => {
|
||||
}),
|
||||
runtime,
|
||||
);
|
||||
expect(onboardCommandMock).not.toHaveBeenCalled();
|
||||
expect(setupWizardCommandMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("runs onboard command when --wizard is set", async () => {
|
||||
it("runs setup wizard command when --wizard is set", async () => {
|
||||
await runCli(["setup", "--wizard", "--mode", "remote", "--remote-url", "wss://example"]);
|
||||
|
||||
expect(onboardCommandMock).toHaveBeenCalledWith(
|
||||
expect(setupWizardCommandMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
mode: "remote",
|
||||
remoteUrl: "wss://example",
|
||||
@@ -65,10 +65,10 @@ describe("registerSetupCommand", () => {
|
||||
expect(setupCommandMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("runs onboard command when wizard-only flags are passed explicitly", async () => {
|
||||
it("runs setup wizard command when wizard-only flags are passed explicitly", async () => {
|
||||
await runCli(["setup", "--mode", "remote", "--non-interactive"]);
|
||||
|
||||
expect(onboardCommandMock).toHaveBeenCalledWith(
|
||||
expect(setupWizardCommandMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
mode: "remote",
|
||||
nonInteractive: true,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { Command } from "commander";
|
||||
import { onboardCommand } from "../../commands/onboard.js";
|
||||
import { setupWizardCommand } from "../../commands/onboard.js";
|
||||
import { setupCommand } from "../../commands/setup.js";
|
||||
import { defaultRuntime } from "../../runtime.js";
|
||||
import { formatDocsLink } from "../../terminal/links.js";
|
||||
@@ -10,7 +10,7 @@ import { hasExplicitOptions } from "../command-options.js";
|
||||
export function registerSetupCommand(program: Command) {
|
||||
program
|
||||
.command("setup")
|
||||
.description("Initialize ~/.openclaw/openclaw.json and the agent workspace")
|
||||
.description("Initialize config/workspace or run the setup wizard")
|
||||
.addHelpText(
|
||||
"after",
|
||||
() =>
|
||||
@@ -20,8 +20,8 @@ export function registerSetupCommand(program: Command) {
|
||||
"--workspace <dir>",
|
||||
"Agent workspace directory (default: ~/.openclaw/workspace; stored as agents.defaults.workspace)",
|
||||
)
|
||||
.option("--wizard", "Run the interactive setup wizard", false)
|
||||
.option("--non-interactive", "Run the wizard without prompts", false)
|
||||
.option("--wizard", "Run the guided setup wizard", false)
|
||||
.option("--non-interactive", "Run the setup wizard without prompts", false)
|
||||
.option("--mode <mode>", "Wizard mode: local|remote")
|
||||
.option("--remote-url <url>", "Remote Gateway WebSocket URL")
|
||||
.option("--remote-token <token>", "Remote Gateway token (optional)")
|
||||
@@ -35,7 +35,7 @@ export function registerSetupCommand(program: Command) {
|
||||
"remoteToken",
|
||||
]);
|
||||
if (opts.wizard || hasWizardFlags) {
|
||||
await onboardCommand(
|
||||
await setupWizardCommand(
|
||||
{
|
||||
workspace: opts.workspace as string | undefined,
|
||||
nonInteractive: Boolean(opts.nonInteractive),
|
||||
|
||||
Reference in New Issue
Block a user