feat: add quickstart onboarding defaults

This commit is contained in:
Peter Steinberger
2026-01-08 11:54:40 +01:00
parent f24a4626e3
commit a483e58860
10 changed files with 431 additions and 130 deletions

View File

@@ -470,10 +470,69 @@ async function maybeConfigureDmPolicies(params: {
return cfg;
}
async function promptTelegramAllowFrom(params: {
cfg: ClawdbotConfig;
prompter: WizardPrompter;
accountId: string;
}): Promise<ClawdbotConfig> {
const { cfg, prompter, accountId } = params;
const resolved = resolveTelegramAccount({ cfg, accountId });
const existingAllowFrom = resolved.config.allowFrom ?? [];
const entry = await prompter.text({
message: "Telegram allowFrom (user id)",
placeholder: "123456789",
initialValue: existingAllowFrom[0]
? String(existingAllowFrom[0])
: undefined,
validate: (value) => {
const raw = String(value ?? "").trim();
if (!raw) return "Required";
if (!/^\d+$/.test(raw)) return "Use a numeric Telegram user id";
return undefined;
},
});
const normalized = String(entry).trim();
const merged = [
...existingAllowFrom.map((item) => String(item).trim()).filter(Boolean),
normalized,
];
const unique = [...new Set(merged)];
if (accountId === DEFAULT_ACCOUNT_ID) {
return {
...cfg,
telegram: {
...cfg.telegram,
enabled: true,
dmPolicy: "allowlist",
allowFrom: unique,
},
};
}
return {
...cfg,
telegram: {
...cfg.telegram,
enabled: true,
accounts: {
...cfg.telegram?.accounts,
[accountId]: {
...cfg.telegram?.accounts?.[accountId],
enabled: cfg.telegram?.accounts?.[accountId]?.enabled ?? true,
dmPolicy: "allowlist",
allowFrom: unique,
},
},
},
};
}
async function promptWhatsAppAllowFrom(
cfg: ClawdbotConfig,
_runtime: RuntimeEnv,
prompter: WizardPrompter,
options?: { forceAllowlist?: boolean },
): Promise<ClawdbotConfig> {
const existingPolicy = cfg.whatsapp?.dmPolicy ?? "pairing";
const existingAllowFrom = cfg.whatsapp?.allowFrom ?? [];
@@ -481,6 +540,47 @@ async function promptWhatsAppAllowFrom(
existingAllowFrom.length > 0 ? existingAllowFrom.join(", ") : "unset";
const existingResponsePrefix = cfg.messages?.responsePrefix;
if (options?.forceAllowlist) {
const entry = await prompter.text({
message: "Your WhatsApp number (E.164)",
placeholder: "+15555550123",
initialValue: existingAllowFrom[0],
validate: (value) => {
const raw = String(value ?? "").trim();
if (!raw) return "Required";
const normalized = normalizeE164(raw);
if (!normalized) return `Invalid number: ${raw}`;
return undefined;
},
});
const normalized = normalizeE164(String(entry).trim());
const merged = [
...existingAllowFrom
.filter((item) => item !== "*")
.map((item) => normalizeE164(item))
.filter(Boolean),
normalized,
];
const unique = [...new Set(merged.filter(Boolean))];
let next = setWhatsAppSelfChatMode(cfg, true);
next = setWhatsAppDmPolicy(next, "allowlist");
next = setWhatsAppAllowFrom(next, unique);
if (existingResponsePrefix === undefined) {
next = setMessagesResponsePrefix(next, "[clawdbot]");
}
await prompter.note(
[
"Allowlist mode enabled.",
`- allowFrom includes ${normalized}`,
existingResponsePrefix === undefined
? "- responsePrefix set to [clawdbot]"
: "- responsePrefix left unchanged",
].join("\n"),
"WhatsApp allowlist",
);
return next;
}
await prompter.note(
[
"WhatsApp direct chats are gated by `whatsapp.dmPolicy` + `whatsapp.allowFrom`.",
@@ -562,7 +662,7 @@ async function promptWhatsAppAllowFrom(
}
if (policy === "disabled") return next;
const options =
const allowOptions =
existingAllowFrom.length > 0
? ([
{ value: "keep", label: "Keep current allowFrom" },
@@ -579,8 +679,11 @@ async function promptWhatsAppAllowFrom(
const mode = (await prompter.select({
message: "WhatsApp allowFrom (optional pre-allowlist)",
options: options.map((opt) => ({ value: opt.value, label: opt.label })),
})) as (typeof options)[number]["value"];
options: allowOptions.map((opt) => ({
value: opt.value,
label: opt.label,
})),
})) as (typeof allowOptions)[number]["value"];
if (mode === "keep") {
// Keep allowFrom as-is.
@@ -631,6 +734,8 @@ type SetupProvidersOptions = {
whatsappAccountId?: string;
promptWhatsAppAccountId?: boolean;
onWhatsAppAccountId?: (accountId: string) => void;
forceAllowFromProviders?: ProviderChoice[];
skipDmPolicyPrompt?: boolean;
};
export async function setupProviders(
@@ -639,6 +744,12 @@ export async function setupProviders(
prompter: WizardPrompter,
options?: SetupProvidersOptions,
): Promise<ClawdbotConfig> {
const forceAllowFromProviders = new Set(
options?.forceAllowFromProviders ?? [],
);
const forceTelegramAllowFrom = forceAllowFromProviders.has("telegram");
const forceWhatsAppAllowFrom = forceAllowFromProviders.has("whatsapp");
let whatsappAccountId =
options?.whatsappAccountId?.trim() || resolveDefaultWhatsAppAccountId(cfg);
let whatsappLinked = await detectWhatsAppLinked(cfg, whatsappAccountId);
@@ -854,7 +965,9 @@ export async function setupProviders(
);
}
next = await promptWhatsAppAllowFrom(next, runtime, prompter);
next = await promptWhatsAppAllowFrom(next, runtime, prompter, {
forceAllowlist: forceWhatsAppAllowFrom,
});
}
if (selection.includes("telegram")) {
@@ -962,6 +1075,14 @@ export async function setupProviders(
};
}
}
if (forceTelegramAllowFrom) {
next = await promptTelegramAllowFrom({
cfg: next,
prompter,
accountId: telegramAccountId,
});
}
}
if (selection.includes("discord")) {
@@ -1414,7 +1535,9 @@ export async function setupProviders(
);
}
next = await maybeConfigureDmPolicies({ cfg: next, selection, prompter });
if (!options?.skipDmPolicyPrompt) {
next = await maybeConfigureDmPolicies({ cfg: next, selection, prompter });
}
if (options?.allowDisable) {
if (!selection.includes("telegram") && telegramConfigured) {