mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 20:40:43 +00:00
refactor: unify onboarding secret-input prompt state wiring
This commit is contained in:
@@ -20,6 +20,7 @@ import type { ChannelOnboardingAdapter, ChannelOnboardingDmPolicy } from "../onb
|
||||
import { configureChannelAccessWithAllowlist } from "./channel-access-configure.js";
|
||||
import {
|
||||
applySingleTokenPromptResult,
|
||||
buildSingleChannelSecretPromptState,
|
||||
parseMentionOrPrefixedId,
|
||||
noteChannelLookupFailure,
|
||||
noteChannelLookupSummary,
|
||||
@@ -177,12 +178,15 @@ export const discordOnboardingAdapter: ChannelOnboardingAdapter = {
|
||||
cfg: next,
|
||||
accountId: discordAccountId,
|
||||
});
|
||||
const hasConfigToken = hasConfiguredSecretInput(resolvedAccount.config.token);
|
||||
const accountConfigured = Boolean(resolvedAccount.token) || hasConfigToken;
|
||||
const allowEnv = discordAccountId === DEFAULT_ACCOUNT_ID;
|
||||
const canUseEnv = allowEnv && !hasConfigToken && Boolean(process.env.DISCORD_BOT_TOKEN?.trim());
|
||||
const tokenPromptState = buildSingleChannelSecretPromptState({
|
||||
accountConfigured: Boolean(resolvedAccount.token),
|
||||
hasConfigToken: hasConfiguredSecretInput(resolvedAccount.config.token),
|
||||
allowEnv,
|
||||
envValue: process.env.DISCORD_BOT_TOKEN,
|
||||
});
|
||||
|
||||
if (!accountConfigured) {
|
||||
if (!tokenPromptState.accountConfigured) {
|
||||
await noteDiscordTokenHelp(prompter);
|
||||
}
|
||||
|
||||
@@ -192,9 +196,9 @@ export const discordOnboardingAdapter: ChannelOnboardingAdapter = {
|
||||
providerHint: "discord",
|
||||
credentialLabel: "Discord bot token",
|
||||
secretInputMode: options?.secretInputMode,
|
||||
accountConfigured,
|
||||
canUseEnv,
|
||||
hasConfigToken,
|
||||
accountConfigured: tokenPromptState.accountConfigured,
|
||||
canUseEnv: tokenPromptState.canUseEnv,
|
||||
hasConfigToken: tokenPromptState.hasConfigToken,
|
||||
envPrompt: "DISCORD_BOT_TOKEN detected. Use env var?",
|
||||
keepPrompt: "Discord token already configured. Keep it?",
|
||||
inputPrompt: "Enter Discord bot token",
|
||||
|
||||
@@ -9,6 +9,7 @@ vi.mock("../../../plugin-sdk/onboarding.js", () => ({
|
||||
|
||||
import {
|
||||
applySingleTokenPromptResult,
|
||||
buildSingleChannelSecretPromptState,
|
||||
normalizeAllowFromEntries,
|
||||
noteChannelLookupFailure,
|
||||
noteChannelLookupSummary,
|
||||
@@ -104,6 +105,38 @@ async function runPromptSingleToken(params: {
|
||||
});
|
||||
}
|
||||
|
||||
describe("buildSingleChannelSecretPromptState", () => {
|
||||
it("enables env path only when env is present and no config token exists", () => {
|
||||
expect(
|
||||
buildSingleChannelSecretPromptState({
|
||||
accountConfigured: false,
|
||||
hasConfigToken: false,
|
||||
allowEnv: true,
|
||||
envValue: "token-from-env",
|
||||
}),
|
||||
).toEqual({
|
||||
accountConfigured: false,
|
||||
hasConfigToken: false,
|
||||
canUseEnv: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("disables env path when config token already exists", () => {
|
||||
expect(
|
||||
buildSingleChannelSecretPromptState({
|
||||
accountConfigured: true,
|
||||
hasConfigToken: true,
|
||||
allowEnv: true,
|
||||
envValue: "token-from-env",
|
||||
}),
|
||||
).toEqual({
|
||||
accountConfigured: true,
|
||||
hasConfigToken: true,
|
||||
canUseEnv: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
async function runPromptLegacyAllowFrom(params: {
|
||||
cfg?: OpenClawConfig;
|
||||
channel: "discord" | "slack";
|
||||
|
||||
@@ -452,6 +452,23 @@ export function applySingleTokenPromptResult(params: {
|
||||
return next;
|
||||
}
|
||||
|
||||
export function buildSingleChannelSecretPromptState(params: {
|
||||
accountConfigured: boolean;
|
||||
hasConfigToken: boolean;
|
||||
allowEnv: boolean;
|
||||
envValue?: string;
|
||||
}): {
|
||||
accountConfigured: boolean;
|
||||
hasConfigToken: boolean;
|
||||
canUseEnv: boolean;
|
||||
} {
|
||||
return {
|
||||
accountConfigured: params.accountConfigured,
|
||||
hasConfigToken: params.hasConfigToken,
|
||||
canUseEnv: params.allowEnv && Boolean(params.envValue?.trim()) && !params.hasConfigToken,
|
||||
};
|
||||
}
|
||||
|
||||
export async function promptSingleChannelToken(params: {
|
||||
prompter: Pick<WizardPrompter, "confirm" | "text">;
|
||||
accountConfigured: boolean;
|
||||
|
||||
@@ -14,6 +14,7 @@ import type { WizardPrompter } from "../../../wizard/prompts.js";
|
||||
import type { ChannelOnboardingAdapter, ChannelOnboardingDmPolicy } from "../onboarding-types.js";
|
||||
import { configureChannelAccessWithAllowlist } from "./channel-access-configure.js";
|
||||
import {
|
||||
buildSingleChannelSecretPromptState,
|
||||
parseMentionOrPrefixedId,
|
||||
noteChannelLookupFailure,
|
||||
noteChannelLookupSummary,
|
||||
@@ -234,10 +235,18 @@ export const slackOnboardingAdapter: ChannelOnboardingAdapter = {
|
||||
const accountConfigured =
|
||||
Boolean(resolvedAccount.botToken && resolvedAccount.appToken) || hasConfigTokens;
|
||||
const allowEnv = slackAccountId === DEFAULT_ACCOUNT_ID;
|
||||
const canUseBotEnv =
|
||||
allowEnv && !hasConfiguredBotToken && Boolean(process.env.SLACK_BOT_TOKEN?.trim());
|
||||
const canUseAppEnv =
|
||||
allowEnv && !hasConfiguredAppToken && Boolean(process.env.SLACK_APP_TOKEN?.trim());
|
||||
const botPromptState = buildSingleChannelSecretPromptState({
|
||||
accountConfigured: Boolean(resolvedAccount.botToken) || hasConfiguredBotToken,
|
||||
hasConfigToken: hasConfiguredBotToken,
|
||||
allowEnv,
|
||||
envValue: process.env.SLACK_BOT_TOKEN,
|
||||
});
|
||||
const appPromptState = buildSingleChannelSecretPromptState({
|
||||
accountConfigured: Boolean(resolvedAccount.appToken) || hasConfiguredAppToken,
|
||||
hasConfigToken: hasConfiguredAppToken,
|
||||
allowEnv,
|
||||
envValue: process.env.SLACK_APP_TOKEN,
|
||||
});
|
||||
let resolvedBotTokenForAllowlist = resolvedAccount.botToken;
|
||||
const slackBotName = String(
|
||||
await prompter.text({
|
||||
@@ -254,9 +263,9 @@ export const slackOnboardingAdapter: ChannelOnboardingAdapter = {
|
||||
providerHint: "slack-bot",
|
||||
credentialLabel: "Slack bot token",
|
||||
secretInputMode: options?.secretInputMode,
|
||||
accountConfigured: Boolean(resolvedAccount.botToken) || hasConfiguredBotToken,
|
||||
canUseEnv: canUseBotEnv,
|
||||
hasConfigToken: hasConfiguredBotToken,
|
||||
accountConfigured: botPromptState.accountConfigured,
|
||||
canUseEnv: botPromptState.canUseEnv,
|
||||
hasConfigToken: botPromptState.hasConfigToken,
|
||||
envPrompt: "SLACK_BOT_TOKEN detected. Use env var?",
|
||||
keepPrompt: "Slack bot token already configured. Keep it?",
|
||||
inputPrompt: "Enter Slack bot token (xoxb-...)",
|
||||
@@ -280,9 +289,9 @@ export const slackOnboardingAdapter: ChannelOnboardingAdapter = {
|
||||
providerHint: "slack-app",
|
||||
credentialLabel: "Slack app token",
|
||||
secretInputMode: options?.secretInputMode,
|
||||
accountConfigured: Boolean(resolvedAccount.appToken) || hasConfiguredAppToken,
|
||||
canUseEnv: canUseAppEnv,
|
||||
hasConfigToken: hasConfiguredAppToken,
|
||||
accountConfigured: appPromptState.accountConfigured,
|
||||
canUseEnv: appPromptState.canUseEnv,
|
||||
hasConfigToken: appPromptState.hasConfigToken,
|
||||
envPrompt: "SLACK_APP_TOKEN detected. Use env var?",
|
||||
keepPrompt: "Slack app token already configured. Keep it?",
|
||||
inputPrompt: "Enter Slack app token (xapp-...)",
|
||||
|
||||
@@ -14,6 +14,7 @@ import { fetchTelegramChatId } from "../../telegram/api.js";
|
||||
import type { ChannelOnboardingAdapter, ChannelOnboardingDmPolicy } from "../onboarding-types.js";
|
||||
import {
|
||||
applySingleTokenPromptResult,
|
||||
buildSingleChannelSecretPromptState,
|
||||
patchChannelConfigForAccount,
|
||||
promptSingleChannelSecretInput,
|
||||
promptResolvedAllowFrom,
|
||||
@@ -192,12 +193,15 @@ export const telegramOnboardingAdapter: ChannelOnboardingAdapter = {
|
||||
const hasConfiguredBotToken = hasConfiguredSecretInput(resolvedAccount.config.botToken);
|
||||
const hasConfigToken =
|
||||
hasConfiguredBotToken || Boolean(resolvedAccount.config.tokenFile?.trim());
|
||||
const accountConfigured = Boolean(resolvedAccount.token) || hasConfigToken;
|
||||
const allowEnv = telegramAccountId === DEFAULT_ACCOUNT_ID;
|
||||
const canUseEnv =
|
||||
allowEnv && !hasConfigToken && Boolean(process.env.TELEGRAM_BOT_TOKEN?.trim());
|
||||
const tokenPromptState = buildSingleChannelSecretPromptState({
|
||||
accountConfigured: Boolean(resolvedAccount.token) || hasConfigToken,
|
||||
hasConfigToken,
|
||||
allowEnv,
|
||||
envValue: process.env.TELEGRAM_BOT_TOKEN,
|
||||
});
|
||||
|
||||
if (!accountConfigured) {
|
||||
if (!tokenPromptState.accountConfigured) {
|
||||
await noteTelegramTokenHelp(prompter);
|
||||
}
|
||||
|
||||
@@ -207,9 +211,9 @@ export const telegramOnboardingAdapter: ChannelOnboardingAdapter = {
|
||||
providerHint: "telegram",
|
||||
credentialLabel: "Telegram bot token",
|
||||
secretInputMode: options?.secretInputMode,
|
||||
accountConfigured,
|
||||
canUseEnv,
|
||||
hasConfigToken,
|
||||
accountConfigured: tokenPromptState.accountConfigured,
|
||||
canUseEnv: tokenPromptState.canUseEnv,
|
||||
hasConfigToken: tokenPromptState.hasConfigToken,
|
||||
envPrompt: "TELEGRAM_BOT_TOKEN detected. Use env var?",
|
||||
keepPrompt: "Telegram token already configured. Keep it?",
|
||||
inputPrompt: "Enter Telegram bot token",
|
||||
|
||||
Reference in New Issue
Block a user