feat: add manual onboarding flow alias
This commit is contained in:
@@ -16,6 +16,10 @@ Related:
|
|||||||
```bash
|
```bash
|
||||||
clawdbot onboard
|
clawdbot onboard
|
||||||
clawdbot onboard --flow quickstart
|
clawdbot onboard --flow quickstart
|
||||||
|
clawdbot onboard --flow manual
|
||||||
clawdbot onboard --mode remote --remote-url ws://gateway-host:18789
|
clawdbot onboard --mode remote --remote-url ws://gateway-host:18789
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Flow notes:
|
||||||
|
- `quickstart`: minimal prompts, auto-generates a gateway token.
|
||||||
|
- `manual`: full prompts for port/bind/auth (alias of `advanced`).
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export function registerOnboardCommand(program: Command) {
|
|||||||
"Acknowledge that agents are powerful and full system access is risky (required for --non-interactive)",
|
"Acknowledge that agents are powerful and full system access is risky (required for --non-interactive)",
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
.option("--flow <flow>", "Wizard flow: quickstart|advanced")
|
.option("--flow <flow>", "Wizard flow: quickstart|advanced|manual")
|
||||||
.option("--mode <mode>", "Wizard mode: local|remote")
|
.option("--mode <mode>", "Wizard mode: local|remote")
|
||||||
.option(
|
.option(
|
||||||
"--auth-choice <choice>",
|
"--auth-choice <choice>",
|
||||||
@@ -106,7 +106,7 @@ export function registerOnboardCommand(program: Command) {
|
|||||||
workspace: opts.workspace as string | undefined,
|
workspace: opts.workspace as string | undefined,
|
||||||
nonInteractive: Boolean(opts.nonInteractive),
|
nonInteractive: Boolean(opts.nonInteractive),
|
||||||
acceptRisk: Boolean(opts.acceptRisk),
|
acceptRisk: Boolean(opts.acceptRisk),
|
||||||
flow: opts.flow as "quickstart" | "advanced" | undefined,
|
flow: opts.flow as "quickstart" | "advanced" | "manual" | undefined,
|
||||||
mode: opts.mode as "local" | "remote" | undefined,
|
mode: opts.mode as "local" | "remote" | undefined,
|
||||||
authChoice: opts.authChoice as AuthChoice | undefined,
|
authChoice: opts.authChoice as AuthChoice | undefined,
|
||||||
tokenProvider: opts.tokenProvider as string | undefined,
|
tokenProvider: opts.tokenProvider as string | undefined,
|
||||||
|
|||||||
@@ -42,7 +42,8 @@ export type ProviderChoice = ChannelChoice;
|
|||||||
|
|
||||||
export type OnboardOptions = {
|
export type OnboardOptions = {
|
||||||
mode?: OnboardMode;
|
mode?: OnboardMode;
|
||||||
flow?: "quickstart" | "advanced";
|
/** "manual" is an alias for "advanced". */
|
||||||
|
flow?: "quickstart" | "advanced" | "manual";
|
||||||
workspace?: string;
|
workspace?: string;
|
||||||
nonInteractive?: boolean;
|
nonInteractive?: boolean;
|
||||||
/** Required for non-interactive onboarding; skips the interactive risk prompt when true. */
|
/** Required for non-interactive onboarding; skips the interactive risk prompt when true. */
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ import type { OnboardOptions } from "./onboard-types.js";
|
|||||||
export async function onboardCommand(opts: OnboardOptions, runtime: RuntimeEnv = defaultRuntime) {
|
export async function onboardCommand(opts: OnboardOptions, runtime: RuntimeEnv = defaultRuntime) {
|
||||||
assertSupportedRuntime(runtime);
|
assertSupportedRuntime(runtime);
|
||||||
const authChoice = opts.authChoice === "oauth" ? ("setup-token" as const) : opts.authChoice;
|
const authChoice = opts.authChoice === "oauth" ? ("setup-token" as const) : opts.authChoice;
|
||||||
const normalizedOpts = authChoice === opts.authChoice ? opts : { ...opts, authChoice };
|
const flow = opts.flow === "manual" ? ("advanced" as const) : opts.flow;
|
||||||
|
const normalizedOpts =
|
||||||
|
authChoice === opts.authChoice && flow === opts.flow ? opts : { ...opts, authChoice, flow };
|
||||||
|
|
||||||
if (normalizedOpts.nonInteractive && normalizedOpts.acceptRisk !== true) {
|
if (normalizedOpts.nonInteractive && normalizedOpts.acceptRisk !== true) {
|
||||||
runtime.error(
|
runtime.error(
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ export async function configureGatewayForOnboarding(
|
|||||||
const tokenInput = await prompter.text({
|
const tokenInput = await prompter.text({
|
||||||
message: "Gateway token (blank to generate)",
|
message: "Gateway token (blank to generate)",
|
||||||
placeholder: "Needed for multi-machine or non-loopback access",
|
placeholder: "Needed for multi-machine or non-loopback access",
|
||||||
initialValue: quickstartGateway.token ?? randomToken(),
|
initialValue: quickstartGateway.token ?? "",
|
||||||
});
|
});
|
||||||
gatewayToken = String(tokenInput).trim() || randomToken();
|
gatewayToken = String(tokenInput).trim() || randomToken();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,10 +82,9 @@ export async function runOnboardingWizard(
|
|||||||
const snapshot = await readConfigFileSnapshot();
|
const snapshot = await readConfigFileSnapshot();
|
||||||
let baseConfig: ClawdbotConfig = snapshot.valid ? snapshot.config : {};
|
let baseConfig: ClawdbotConfig = snapshot.valid ? snapshot.config : {};
|
||||||
|
|
||||||
if (snapshot.exists) {
|
if (snapshot.exists && !snapshot.valid) {
|
||||||
const title = snapshot.valid ? "Existing config detected" : "Invalid config";
|
await prompter.note(summarizeExistingConfig(baseConfig), "Invalid config");
|
||||||
await prompter.note(summarizeExistingConfig(baseConfig), title);
|
if (snapshot.issues.length > 0) {
|
||||||
if (!snapshot.valid && snapshot.issues.length > 0) {
|
|
||||||
await prompter.note(
|
await prompter.note(
|
||||||
[
|
[
|
||||||
...snapshot.issues.map((iss) => `- ${iss.path}: ${iss.message}`),
|
...snapshot.issues.map((iss) => `- ${iss.path}: ${iss.message}`),
|
||||||
@@ -95,8 +94,6 @@ export async function runOnboardingWizard(
|
|||||||
"Config issues",
|
"Config issues",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!snapshot.valid) {
|
|
||||||
await prompter.outro(
|
await prompter.outro(
|
||||||
`Config invalid. Run \`${formatCliCommand("clawdbot doctor")}\` to repair it, then re-run onboarding.`,
|
`Config invalid. Run \`${formatCliCommand("clawdbot doctor")}\` to repair it, then re-run onboarding.`,
|
||||||
);
|
);
|
||||||
@@ -104,6 +101,45 @@ export async function runOnboardingWizard(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const quickstartHint = `Configure details later via ${formatCliCommand("clawdbot configure")}.`;
|
||||||
|
const manualHint = "Configure port, network, Tailscale, and auth options.";
|
||||||
|
const explicitFlowRaw = opts.flow?.trim();
|
||||||
|
const normalizedExplicitFlow = explicitFlowRaw === "manual" ? "advanced" : explicitFlowRaw;
|
||||||
|
if (
|
||||||
|
normalizedExplicitFlow &&
|
||||||
|
normalizedExplicitFlow !== "quickstart" &&
|
||||||
|
normalizedExplicitFlow !== "advanced"
|
||||||
|
) {
|
||||||
|
runtime.error("Invalid --flow (use quickstart, manual, or advanced).");
|
||||||
|
runtime.exit(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const explicitFlow: WizardFlow | undefined =
|
||||||
|
normalizedExplicitFlow === "quickstart" || normalizedExplicitFlow === "advanced"
|
||||||
|
? normalizedExplicitFlow
|
||||||
|
: undefined;
|
||||||
|
let flow: WizardFlow =
|
||||||
|
explicitFlow ??
|
||||||
|
((await prompter.select({
|
||||||
|
message: "Onboarding mode",
|
||||||
|
options: [
|
||||||
|
{ value: "quickstart", label: "QuickStart", hint: quickstartHint },
|
||||||
|
{ value: "advanced", label: "Manual", hint: manualHint },
|
||||||
|
],
|
||||||
|
initialValue: "quickstart",
|
||||||
|
})) as "quickstart" | "advanced");
|
||||||
|
|
||||||
|
if (opts.mode === "remote" && flow === "quickstart") {
|
||||||
|
await prompter.note(
|
||||||
|
"QuickStart only supports local gateways. Switching to Manual mode.",
|
||||||
|
"QuickStart",
|
||||||
|
);
|
||||||
|
flow = "advanced";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snapshot.exists) {
|
||||||
|
await prompter.note(summarizeExistingConfig(baseConfig), "Existing config detected");
|
||||||
|
|
||||||
const action = (await prompter.select({
|
const action = (await prompter.select({
|
||||||
message: "Config handling",
|
message: "Config handling",
|
||||||
options: [
|
options: [
|
||||||
@@ -134,37 +170,6 @@ export async function runOnboardingWizard(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const quickstartHint = `Configure details later via ${formatCliCommand("clawdbot configure")}.`;
|
|
||||||
const advancedHint = "Configure port, network, Tailscale, and auth options.";
|
|
||||||
const explicitFlowRaw = opts.flow?.trim();
|
|
||||||
if (explicitFlowRaw && explicitFlowRaw !== "quickstart" && explicitFlowRaw !== "advanced") {
|
|
||||||
runtime.error("Invalid --flow (use quickstart or advanced).");
|
|
||||||
runtime.exit(1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const explicitFlow: WizardFlow | undefined =
|
|
||||||
explicitFlowRaw === "quickstart" || explicitFlowRaw === "advanced"
|
|
||||||
? explicitFlowRaw
|
|
||||||
: undefined;
|
|
||||||
let flow: WizardFlow =
|
|
||||||
explicitFlow ??
|
|
||||||
((await prompter.select({
|
|
||||||
message: "Onboarding mode",
|
|
||||||
options: [
|
|
||||||
{ value: "quickstart", label: "QuickStart", hint: quickstartHint },
|
|
||||||
{ value: "advanced", label: "Advanced", hint: advancedHint },
|
|
||||||
],
|
|
||||||
initialValue: "quickstart",
|
|
||||||
})) as "quickstart" | "advanced");
|
|
||||||
|
|
||||||
if (opts.mode === "remote" && flow === "quickstart") {
|
|
||||||
await prompter.note(
|
|
||||||
"QuickStart only supports local gateways. Switching to Advanced mode.",
|
|
||||||
"QuickStart",
|
|
||||||
);
|
|
||||||
flow = "advanced";
|
|
||||||
}
|
|
||||||
|
|
||||||
const quickstartGateway: QuickstartGatewayDefaults = (() => {
|
const quickstartGateway: QuickstartGatewayDefaults = (() => {
|
||||||
const hasExisting =
|
const hasExisting =
|
||||||
typeof baseConfig.gateway?.port === "number" ||
|
typeof baseConfig.gateway?.port === "number" ||
|
||||||
|
|||||||
Reference in New Issue
Block a user