mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 07:20:45 +00:00
refactor: share onboarding secret prompt flows
This commit is contained in:
@@ -1,16 +1,14 @@
|
||||
import {
|
||||
buildSingleChannelSecretPromptState,
|
||||
formatDocsLink,
|
||||
hasConfiguredSecretInput,
|
||||
mapAllowFromEntries,
|
||||
mergeAllowFromEntries,
|
||||
patchScopedAccountConfig,
|
||||
promptSingleChannelSecretInput,
|
||||
runSingleChannelSecretStep,
|
||||
resolveAccountIdForConfigure,
|
||||
DEFAULT_ACCOUNT_ID,
|
||||
normalizeAccountId,
|
||||
setTopLevelChannelDmPolicyWithAllowFrom,
|
||||
type SecretInput,
|
||||
type ChannelOnboardingAdapter,
|
||||
type ChannelOnboardingDmPolicy,
|
||||
type OpenClawConfig,
|
||||
@@ -190,12 +188,6 @@ export const nextcloudTalkOnboardingAdapter: ChannelOnboardingAdapter = {
|
||||
hasConfiguredSecretInput(resolvedAccount.config.botSecret) ||
|
||||
resolvedAccount.config.botSecretFile,
|
||||
);
|
||||
const secretPromptState = buildSingleChannelSecretPromptState({
|
||||
accountConfigured,
|
||||
hasConfigToken: hasConfigSecret,
|
||||
allowEnv,
|
||||
envValue: process.env.NEXTCLOUD_TALK_BOT_SECRET,
|
||||
});
|
||||
|
||||
let baseUrl = resolvedAccount.baseUrl;
|
||||
if (!baseUrl) {
|
||||
@@ -216,32 +208,35 @@ export const nextcloudTalkOnboardingAdapter: ChannelOnboardingAdapter = {
|
||||
).trim();
|
||||
}
|
||||
|
||||
let secret: SecretInput | null = null;
|
||||
if (!accountConfigured) {
|
||||
await noteNextcloudTalkSecretHelp(prompter);
|
||||
}
|
||||
|
||||
const secretResult = await promptSingleChannelSecretInput({
|
||||
const secretStep = await runSingleChannelSecretStep({
|
||||
cfg: next,
|
||||
prompter,
|
||||
providerHint: "nextcloud-talk",
|
||||
credentialLabel: "bot secret",
|
||||
accountConfigured: secretPromptState.accountConfigured,
|
||||
canUseEnv: secretPromptState.canUseEnv,
|
||||
hasConfigToken: secretPromptState.hasConfigToken,
|
||||
accountConfigured,
|
||||
hasConfigToken: hasConfigSecret,
|
||||
allowEnv,
|
||||
envValue: process.env.NEXTCLOUD_TALK_BOT_SECRET,
|
||||
envPrompt: "NEXTCLOUD_TALK_BOT_SECRET detected. Use env var?",
|
||||
keepPrompt: "Nextcloud Talk bot secret already configured. Keep it?",
|
||||
inputPrompt: "Enter Nextcloud Talk bot secret",
|
||||
preferredEnvVar: "NEXTCLOUD_TALK_BOT_SECRET",
|
||||
onMissingConfigured: async () => await noteNextcloudTalkSecretHelp(prompter),
|
||||
applyUseEnv: async (cfg) =>
|
||||
setNextcloudTalkAccountConfig(cfg as CoreConfig, accountId, {
|
||||
baseUrl,
|
||||
}),
|
||||
applySet: async (cfg, value) =>
|
||||
setNextcloudTalkAccountConfig(cfg as CoreConfig, accountId, {
|
||||
baseUrl,
|
||||
botSecret: value,
|
||||
}),
|
||||
});
|
||||
if (secretResult.action === "set") {
|
||||
secret = secretResult.value;
|
||||
}
|
||||
next = secretStep.cfg;
|
||||
|
||||
if (secretResult.action === "use-env" || secret || baseUrl !== resolvedAccount.baseUrl) {
|
||||
if (secretStep.action === "keep" && baseUrl !== resolvedAccount.baseUrl) {
|
||||
next = setNextcloudTalkAccountConfig(next, accountId, {
|
||||
baseUrl,
|
||||
...(secret ? { botSecret: secret } : {}),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -262,26 +257,28 @@ export const nextcloudTalkOnboardingAdapter: ChannelOnboardingAdapter = {
|
||||
validate: (value) => (String(value ?? "").trim() ? undefined : "Required"),
|
||||
}),
|
||||
).trim();
|
||||
const apiPasswordResult = await promptSingleChannelSecretInput({
|
||||
const apiPasswordStep = await runSingleChannelSecretStep({
|
||||
cfg: next,
|
||||
prompter,
|
||||
providerHint: "nextcloud-talk-api",
|
||||
credentialLabel: "API password",
|
||||
...buildSingleChannelSecretPromptState({
|
||||
accountConfigured: Boolean(existingApiUser && existingApiPasswordConfigured),
|
||||
hasConfigToken: existingApiPasswordConfigured,
|
||||
allowEnv: false,
|
||||
}),
|
||||
accountConfigured: Boolean(existingApiUser && existingApiPasswordConfigured),
|
||||
hasConfigToken: existingApiPasswordConfigured,
|
||||
allowEnv: false,
|
||||
envPrompt: "",
|
||||
keepPrompt: "Nextcloud Talk API password already configured. Keep it?",
|
||||
inputPrompt: "Enter Nextcloud Talk API password",
|
||||
preferredEnvVar: "NEXTCLOUD_TALK_API_PASSWORD",
|
||||
applySet: async (cfg, value) =>
|
||||
setNextcloudTalkAccountConfig(cfg as CoreConfig, accountId, {
|
||||
apiUser,
|
||||
apiPassword: value,
|
||||
}),
|
||||
});
|
||||
const apiPassword = apiPasswordResult.action === "set" ? apiPasswordResult.value : undefined;
|
||||
next = setNextcloudTalkAccountConfig(next, accountId, {
|
||||
apiUser,
|
||||
...(apiPassword ? { apiPassword } : {}),
|
||||
});
|
||||
next =
|
||||
apiPasswordStep.action === "keep"
|
||||
? setNextcloudTalkAccountConfig(next, accountId, { apiUser })
|
||||
: apiPasswordStep.cfg;
|
||||
}
|
||||
|
||||
if (forceAllowFrom) {
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
mergeAllowFromEntries,
|
||||
normalizeAccountId,
|
||||
promptSingleChannelSecretInput,
|
||||
runSingleChannelSecretStep,
|
||||
resolveAccountIdForConfigure,
|
||||
setTopLevelChannelDmPolicyWithAllowFrom,
|
||||
} from "openclaw/plugin-sdk/zalo";
|
||||
@@ -255,80 +256,66 @@ export const zaloOnboardingAdapter: ChannelOnboardingAdapter = {
|
||||
const hasConfigToken = Boolean(
|
||||
hasConfiguredSecretInput(resolvedAccount.config.botToken) || resolvedAccount.config.tokenFile,
|
||||
);
|
||||
const tokenPromptState = buildSingleChannelSecretPromptState({
|
||||
accountConfigured,
|
||||
hasConfigToken,
|
||||
allowEnv,
|
||||
envValue: process.env.ZALO_BOT_TOKEN,
|
||||
});
|
||||
|
||||
let token: SecretInput | null = null;
|
||||
if (!accountConfigured) {
|
||||
await noteZaloTokenHelp(prompter);
|
||||
}
|
||||
const tokenResult = await promptSingleChannelSecretInput({
|
||||
const tokenStep = await runSingleChannelSecretStep({
|
||||
cfg: next,
|
||||
prompter,
|
||||
providerHint: "zalo",
|
||||
credentialLabel: "bot token",
|
||||
accountConfigured: tokenPromptState.accountConfigured,
|
||||
canUseEnv: tokenPromptState.canUseEnv,
|
||||
hasConfigToken: tokenPromptState.hasConfigToken,
|
||||
accountConfigured,
|
||||
hasConfigToken,
|
||||
allowEnv,
|
||||
envValue: process.env.ZALO_BOT_TOKEN,
|
||||
envPrompt: "ZALO_BOT_TOKEN detected. Use env var?",
|
||||
keepPrompt: "Zalo token already configured. Keep it?",
|
||||
inputPrompt: "Enter Zalo bot token",
|
||||
preferredEnvVar: "ZALO_BOT_TOKEN",
|
||||
});
|
||||
if (tokenResult.action === "set") {
|
||||
token = tokenResult.value;
|
||||
}
|
||||
if (tokenResult.action === "use-env" && zaloAccountId === DEFAULT_ACCOUNT_ID) {
|
||||
next = {
|
||||
...next,
|
||||
channels: {
|
||||
...next.channels,
|
||||
zalo: {
|
||||
...next.channels?.zalo,
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
}
|
||||
|
||||
if (token) {
|
||||
if (zaloAccountId === DEFAULT_ACCOUNT_ID) {
|
||||
next = {
|
||||
...next,
|
||||
channels: {
|
||||
...next.channels,
|
||||
zalo: {
|
||||
...next.channels?.zalo,
|
||||
enabled: true,
|
||||
botToken: token,
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
} else {
|
||||
next = {
|
||||
...next,
|
||||
channels: {
|
||||
...next.channels,
|
||||
zalo: {
|
||||
...next.channels?.zalo,
|
||||
enabled: true,
|
||||
accounts: {
|
||||
...next.channels?.zalo?.accounts,
|
||||
[zaloAccountId]: {
|
||||
...next.channels?.zalo?.accounts?.[zaloAccountId],
|
||||
onMissingConfigured: async () => await noteZaloTokenHelp(prompter),
|
||||
applyUseEnv: async (cfg) =>
|
||||
zaloAccountId === DEFAULT_ACCOUNT_ID
|
||||
? ({
|
||||
...cfg,
|
||||
channels: {
|
||||
...cfg.channels,
|
||||
zalo: {
|
||||
...cfg.channels?.zalo,
|
||||
enabled: true,
|
||||
botToken: token,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
}
|
||||
}
|
||||
} as OpenClawConfig)
|
||||
: cfg,
|
||||
applySet: async (cfg, value) =>
|
||||
zaloAccountId === DEFAULT_ACCOUNT_ID
|
||||
? ({
|
||||
...cfg,
|
||||
channels: {
|
||||
...cfg.channels,
|
||||
zalo: {
|
||||
...cfg.channels?.zalo,
|
||||
enabled: true,
|
||||
botToken: value,
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig)
|
||||
: ({
|
||||
...cfg,
|
||||
channels: {
|
||||
...cfg.channels,
|
||||
zalo: {
|
||||
...cfg.channels?.zalo,
|
||||
enabled: true,
|
||||
accounts: {
|
||||
...cfg.channels?.zalo?.accounts,
|
||||
[zaloAccountId]: {
|
||||
...cfg.channels?.zalo?.accounts?.[zaloAccountId],
|
||||
enabled: true,
|
||||
botToken: value,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig),
|
||||
});
|
||||
next = tokenStep.cfg;
|
||||
|
||||
const wantsWebhook = await prompter.confirm({
|
||||
message: "Use webhook mode for Zalo?",
|
||||
|
||||
@@ -20,15 +20,14 @@ import type { ChannelOnboardingAdapter, ChannelOnboardingDmPolicy } from "../onb
|
||||
import { configureChannelAccessWithAllowlist } from "./channel-access-configure.js";
|
||||
import {
|
||||
applySingleTokenPromptResult,
|
||||
buildSingleChannelSecretPromptState,
|
||||
parseMentionOrPrefixedId,
|
||||
noteChannelLookupFailure,
|
||||
noteChannelLookupSummary,
|
||||
patchChannelConfigForAccount,
|
||||
promptLegacyChannelAllowFrom,
|
||||
promptSingleChannelSecretInput,
|
||||
resolveAccountIdForConfigure,
|
||||
resolveOnboardingAccountId,
|
||||
runSingleChannelSecretStep,
|
||||
setAccountGroupPolicyForChannel,
|
||||
setLegacyChannelDmPolicyWithAllowFrom,
|
||||
setOnboardingChannelEnabled,
|
||||
@@ -179,52 +178,39 @@ export const discordOnboardingAdapter: ChannelOnboardingAdapter = {
|
||||
accountId: discordAccountId,
|
||||
});
|
||||
const allowEnv = discordAccountId === DEFAULT_ACCOUNT_ID;
|
||||
const tokenPromptState = buildSingleChannelSecretPromptState({
|
||||
accountConfigured: Boolean(resolvedAccount.token),
|
||||
hasConfigToken: hasConfiguredSecretInput(resolvedAccount.config.token),
|
||||
allowEnv,
|
||||
envValue: process.env.DISCORD_BOT_TOKEN,
|
||||
});
|
||||
|
||||
if (!tokenPromptState.accountConfigured) {
|
||||
await noteDiscordTokenHelp(prompter);
|
||||
}
|
||||
|
||||
const tokenResult = await promptSingleChannelSecretInput({
|
||||
const tokenStep = await runSingleChannelSecretStep({
|
||||
cfg: next,
|
||||
prompter,
|
||||
providerHint: "discord",
|
||||
credentialLabel: "Discord bot token",
|
||||
secretInputMode: options?.secretInputMode,
|
||||
accountConfigured: tokenPromptState.accountConfigured,
|
||||
canUseEnv: tokenPromptState.canUseEnv,
|
||||
hasConfigToken: tokenPromptState.hasConfigToken,
|
||||
accountConfigured: Boolean(resolvedAccount.token),
|
||||
hasConfigToken: hasConfiguredSecretInput(resolvedAccount.config.token),
|
||||
allowEnv,
|
||||
envValue: process.env.DISCORD_BOT_TOKEN,
|
||||
envPrompt: "DISCORD_BOT_TOKEN detected. Use env var?",
|
||||
keepPrompt: "Discord token already configured. Keep it?",
|
||||
inputPrompt: "Enter Discord bot token",
|
||||
preferredEnvVar: allowEnv ? "DISCORD_BOT_TOKEN" : undefined,
|
||||
onMissingConfigured: async () => await noteDiscordTokenHelp(prompter),
|
||||
applyUseEnv: async (cfg) =>
|
||||
applySingleTokenPromptResult({
|
||||
cfg,
|
||||
channel: "discord",
|
||||
accountId: discordAccountId,
|
||||
tokenPatchKey: "token",
|
||||
tokenResult: { useEnv: true, token: null },
|
||||
}),
|
||||
applySet: async (cfg, value) =>
|
||||
applySingleTokenPromptResult({
|
||||
cfg,
|
||||
channel: "discord",
|
||||
accountId: discordAccountId,
|
||||
tokenPatchKey: "token",
|
||||
tokenResult: { useEnv: false, token: value },
|
||||
}),
|
||||
});
|
||||
|
||||
let resolvedTokenForAllowlist: string | undefined;
|
||||
if (tokenResult.action === "use-env") {
|
||||
next = applySingleTokenPromptResult({
|
||||
cfg: next,
|
||||
channel: "discord",
|
||||
accountId: discordAccountId,
|
||||
tokenPatchKey: "token",
|
||||
tokenResult: { useEnv: true, token: null },
|
||||
});
|
||||
resolvedTokenForAllowlist = process.env.DISCORD_BOT_TOKEN?.trim() || undefined;
|
||||
} else if (tokenResult.action === "set") {
|
||||
next = applySingleTokenPromptResult({
|
||||
cfg: next,
|
||||
channel: "discord",
|
||||
accountId: discordAccountId,
|
||||
tokenPatchKey: "token",
|
||||
tokenResult: { useEnv: false, token: tokenResult.value },
|
||||
});
|
||||
resolvedTokenForAllowlist = tokenResult.resolvedValue;
|
||||
}
|
||||
next = tokenStep.cfg;
|
||||
|
||||
const currentEntries = Object.entries(resolvedAccount.config.guilds ?? {}).flatMap(
|
||||
([guildKey, value]) => {
|
||||
@@ -261,7 +247,7 @@ export const discordOnboardingAdapter: ChannelOnboardingAdapter = {
|
||||
input,
|
||||
resolved: false,
|
||||
}));
|
||||
const activeToken = accountWithTokens.token || resolvedTokenForAllowlist || "";
|
||||
const activeToken = accountWithTokens.token || tokenStep.resolvedValue || "";
|
||||
if (activeToken && entries.length > 0) {
|
||||
try {
|
||||
resolved = await resolveDiscordChannelAllowlist({
|
||||
|
||||
@@ -482,6 +482,82 @@ export type SingleChannelSecretInputPromptResult =
|
||||
| { action: "use-env" }
|
||||
| { action: "set"; value: SecretInput; resolvedValue: string };
|
||||
|
||||
export async function runSingleChannelSecretStep(params: {
|
||||
cfg: OpenClawConfig;
|
||||
prompter: Pick<WizardPrompter, "confirm" | "text" | "select" | "note">;
|
||||
providerHint: string;
|
||||
credentialLabel: string;
|
||||
secretInputMode?: "plaintext" | "ref";
|
||||
accountConfigured: boolean;
|
||||
hasConfigToken: boolean;
|
||||
allowEnv: boolean;
|
||||
envValue?: string;
|
||||
envPrompt: string;
|
||||
keepPrompt: string;
|
||||
inputPrompt: string;
|
||||
preferredEnvVar?: string;
|
||||
onMissingConfigured?: () => Promise<void>;
|
||||
applyUseEnv?: (cfg: OpenClawConfig) => OpenClawConfig | Promise<OpenClawConfig>;
|
||||
applySet?: (
|
||||
cfg: OpenClawConfig,
|
||||
value: SecretInput,
|
||||
resolvedValue: string,
|
||||
) => OpenClawConfig | Promise<OpenClawConfig>;
|
||||
}): Promise<{
|
||||
cfg: OpenClawConfig;
|
||||
action: SingleChannelSecretInputPromptResult["action"];
|
||||
resolvedValue?: string;
|
||||
}> {
|
||||
const promptState = buildSingleChannelSecretPromptState({
|
||||
accountConfigured: params.accountConfigured,
|
||||
hasConfigToken: params.hasConfigToken,
|
||||
allowEnv: params.allowEnv,
|
||||
envValue: params.envValue,
|
||||
});
|
||||
|
||||
if (!promptState.accountConfigured && params.onMissingConfigured) {
|
||||
await params.onMissingConfigured();
|
||||
}
|
||||
|
||||
const result = await promptSingleChannelSecretInput({
|
||||
cfg: params.cfg,
|
||||
prompter: params.prompter,
|
||||
providerHint: params.providerHint,
|
||||
credentialLabel: params.credentialLabel,
|
||||
secretInputMode: params.secretInputMode,
|
||||
accountConfigured: promptState.accountConfigured,
|
||||
canUseEnv: promptState.canUseEnv,
|
||||
hasConfigToken: promptState.hasConfigToken,
|
||||
envPrompt: params.envPrompt,
|
||||
keepPrompt: params.keepPrompt,
|
||||
inputPrompt: params.inputPrompt,
|
||||
preferredEnvVar: params.preferredEnvVar,
|
||||
});
|
||||
|
||||
if (result.action === "use-env") {
|
||||
return {
|
||||
cfg: params.applyUseEnv ? await params.applyUseEnv(params.cfg) : params.cfg,
|
||||
action: result.action,
|
||||
resolvedValue: params.envValue?.trim() || undefined,
|
||||
};
|
||||
}
|
||||
|
||||
if (result.action === "set") {
|
||||
return {
|
||||
cfg: params.applySet
|
||||
? await params.applySet(params.cfg, result.value, result.resolvedValue)
|
||||
: params.cfg,
|
||||
action: result.action,
|
||||
resolvedValue: result.resolvedValue,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
cfg: params.cfg,
|
||||
action: result.action,
|
||||
};
|
||||
}
|
||||
|
||||
export async function promptSingleChannelSecretInput(params: {
|
||||
cfg: OpenClawConfig;
|
||||
prompter: Pick<WizardPrompter, "confirm" | "text" | "select" | "note">;
|
||||
|
||||
@@ -14,15 +14,14 @@ 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,
|
||||
patchChannelConfigForAccount,
|
||||
promptLegacyChannelAllowFrom,
|
||||
promptSingleChannelSecretInput,
|
||||
resolveAccountIdForConfigure,
|
||||
resolveOnboardingAccountId,
|
||||
runSingleChannelSecretStep,
|
||||
setAccountGroupPolicyForChannel,
|
||||
setLegacyChannelDmPolicyWithAllowFrom,
|
||||
setOnboardingChannelEnabled,
|
||||
@@ -235,18 +234,6 @@ export const slackOnboardingAdapter: ChannelOnboardingAdapter = {
|
||||
const accountConfigured =
|
||||
Boolean(resolvedAccount.botToken && resolvedAccount.appToken) || hasConfigTokens;
|
||||
const allowEnv = slackAccountId === DEFAULT_ACCOUNT_ID;
|
||||
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({
|
||||
@@ -257,54 +244,56 @@ export const slackOnboardingAdapter: ChannelOnboardingAdapter = {
|
||||
if (!accountConfigured) {
|
||||
await noteSlackTokenHelp(prompter, slackBotName);
|
||||
}
|
||||
const botTokenResult = await promptSingleChannelSecretInput({
|
||||
const botTokenStep = await runSingleChannelSecretStep({
|
||||
cfg: next,
|
||||
prompter,
|
||||
providerHint: "slack-bot",
|
||||
credentialLabel: "Slack bot token",
|
||||
secretInputMode: options?.secretInputMode,
|
||||
accountConfigured: botPromptState.accountConfigured,
|
||||
canUseEnv: botPromptState.canUseEnv,
|
||||
hasConfigToken: botPromptState.hasConfigToken,
|
||||
accountConfigured: Boolean(resolvedAccount.botToken) || hasConfiguredBotToken,
|
||||
hasConfigToken: hasConfiguredBotToken,
|
||||
allowEnv,
|
||||
envValue: process.env.SLACK_BOT_TOKEN,
|
||||
envPrompt: "SLACK_BOT_TOKEN detected. Use env var?",
|
||||
keepPrompt: "Slack bot token already configured. Keep it?",
|
||||
inputPrompt: "Enter Slack bot token (xoxb-...)",
|
||||
preferredEnvVar: allowEnv ? "SLACK_BOT_TOKEN" : undefined,
|
||||
applySet: async (cfg, value) =>
|
||||
patchChannelConfigForAccount({
|
||||
cfg,
|
||||
channel: "slack",
|
||||
accountId: slackAccountId,
|
||||
patch: { botToken: value },
|
||||
}),
|
||||
});
|
||||
if (botTokenResult.action === "use-env") {
|
||||
resolvedBotTokenForAllowlist = process.env.SLACK_BOT_TOKEN?.trim() || undefined;
|
||||
} else if (botTokenResult.action === "set") {
|
||||
next = patchChannelConfigForAccount({
|
||||
cfg: next,
|
||||
channel: "slack",
|
||||
accountId: slackAccountId,
|
||||
patch: { botToken: botTokenResult.value },
|
||||
});
|
||||
resolvedBotTokenForAllowlist = botTokenResult.resolvedValue;
|
||||
next = botTokenStep.cfg;
|
||||
if (botTokenStep.resolvedValue) {
|
||||
resolvedBotTokenForAllowlist = botTokenStep.resolvedValue;
|
||||
}
|
||||
|
||||
const appTokenResult = await promptSingleChannelSecretInput({
|
||||
const appTokenStep = await runSingleChannelSecretStep({
|
||||
cfg: next,
|
||||
prompter,
|
||||
providerHint: "slack-app",
|
||||
credentialLabel: "Slack app token",
|
||||
secretInputMode: options?.secretInputMode,
|
||||
accountConfigured: appPromptState.accountConfigured,
|
||||
canUseEnv: appPromptState.canUseEnv,
|
||||
hasConfigToken: appPromptState.hasConfigToken,
|
||||
accountConfigured: Boolean(resolvedAccount.appToken) || hasConfiguredAppToken,
|
||||
hasConfigToken: hasConfiguredAppToken,
|
||||
allowEnv,
|
||||
envValue: process.env.SLACK_APP_TOKEN,
|
||||
envPrompt: "SLACK_APP_TOKEN detected. Use env var?",
|
||||
keepPrompt: "Slack app token already configured. Keep it?",
|
||||
inputPrompt: "Enter Slack app token (xapp-...)",
|
||||
preferredEnvVar: allowEnv ? "SLACK_APP_TOKEN" : undefined,
|
||||
applySet: async (cfg, value) =>
|
||||
patchChannelConfigForAccount({
|
||||
cfg,
|
||||
channel: "slack",
|
||||
accountId: slackAccountId,
|
||||
patch: { appToken: value },
|
||||
}),
|
||||
});
|
||||
if (appTokenResult.action === "set") {
|
||||
next = patchChannelConfigForAccount({
|
||||
cfg: next,
|
||||
channel: "slack",
|
||||
accountId: slackAccountId,
|
||||
patch: { appToken: appTokenResult.value },
|
||||
});
|
||||
}
|
||||
next = appTokenStep.cfg;
|
||||
|
||||
next = await configureChannelAccessWithAllowlist({
|
||||
cfg: next,
|
||||
|
||||
@@ -14,12 +14,11 @@ import { fetchTelegramChatId } from "../../telegram/api.js";
|
||||
import type { ChannelOnboardingAdapter, ChannelOnboardingDmPolicy } from "../onboarding-types.js";
|
||||
import {
|
||||
applySingleTokenPromptResult,
|
||||
buildSingleChannelSecretPromptState,
|
||||
patchChannelConfigForAccount,
|
||||
promptSingleChannelSecretInput,
|
||||
promptResolvedAllowFrom,
|
||||
resolveAccountIdForConfigure,
|
||||
resolveOnboardingAccountId,
|
||||
runSingleChannelSecretStep,
|
||||
setChannelDmPolicyWithAllowFrom,
|
||||
setOnboardingChannelEnabled,
|
||||
splitOnboardingEntries,
|
||||
@@ -194,59 +193,46 @@ export const telegramOnboardingAdapter: ChannelOnboardingAdapter = {
|
||||
const hasConfigToken =
|
||||
hasConfiguredBotToken || Boolean(resolvedAccount.config.tokenFile?.trim());
|
||||
const allowEnv = telegramAccountId === DEFAULT_ACCOUNT_ID;
|
||||
const tokenPromptState = buildSingleChannelSecretPromptState({
|
||||
accountConfigured: Boolean(resolvedAccount.token) || hasConfigToken,
|
||||
hasConfigToken,
|
||||
allowEnv,
|
||||
envValue: process.env.TELEGRAM_BOT_TOKEN,
|
||||
});
|
||||
|
||||
if (!tokenPromptState.accountConfigured) {
|
||||
await noteTelegramTokenHelp(prompter);
|
||||
}
|
||||
|
||||
const tokenResult = await promptSingleChannelSecretInput({
|
||||
const tokenStep = await runSingleChannelSecretStep({
|
||||
cfg: next,
|
||||
prompter,
|
||||
providerHint: "telegram",
|
||||
credentialLabel: "Telegram bot token",
|
||||
secretInputMode: options?.secretInputMode,
|
||||
accountConfigured: tokenPromptState.accountConfigured,
|
||||
canUseEnv: tokenPromptState.canUseEnv,
|
||||
hasConfigToken: tokenPromptState.hasConfigToken,
|
||||
accountConfigured: Boolean(resolvedAccount.token) || hasConfigToken,
|
||||
hasConfigToken,
|
||||
allowEnv,
|
||||
envValue: process.env.TELEGRAM_BOT_TOKEN,
|
||||
envPrompt: "TELEGRAM_BOT_TOKEN detected. Use env var?",
|
||||
keepPrompt: "Telegram token already configured. Keep it?",
|
||||
inputPrompt: "Enter Telegram bot token",
|
||||
preferredEnvVar: allowEnv ? "TELEGRAM_BOT_TOKEN" : undefined,
|
||||
onMissingConfigured: async () => await noteTelegramTokenHelp(prompter),
|
||||
applyUseEnv: async (cfg) =>
|
||||
applySingleTokenPromptResult({
|
||||
cfg,
|
||||
channel: "telegram",
|
||||
accountId: telegramAccountId,
|
||||
tokenPatchKey: "botToken",
|
||||
tokenResult: { useEnv: true, token: null },
|
||||
}),
|
||||
applySet: async (cfg, value) =>
|
||||
applySingleTokenPromptResult({
|
||||
cfg,
|
||||
channel: "telegram",
|
||||
accountId: telegramAccountId,
|
||||
tokenPatchKey: "botToken",
|
||||
tokenResult: { useEnv: false, token: value },
|
||||
}),
|
||||
});
|
||||
|
||||
let resolvedTokenForAllowFrom: string | undefined;
|
||||
if (tokenResult.action === "use-env") {
|
||||
next = applySingleTokenPromptResult({
|
||||
cfg: next,
|
||||
channel: "telegram",
|
||||
accountId: telegramAccountId,
|
||||
tokenPatchKey: "botToken",
|
||||
tokenResult: { useEnv: true, token: null },
|
||||
});
|
||||
resolvedTokenForAllowFrom = process.env.TELEGRAM_BOT_TOKEN?.trim() || undefined;
|
||||
} else if (tokenResult.action === "set") {
|
||||
next = applySingleTokenPromptResult({
|
||||
cfg: next,
|
||||
channel: "telegram",
|
||||
accountId: telegramAccountId,
|
||||
tokenPatchKey: "botToken",
|
||||
tokenResult: { useEnv: false, token: tokenResult.value },
|
||||
});
|
||||
resolvedTokenForAllowFrom = tokenResult.resolvedValue;
|
||||
}
|
||||
next = tokenStep.cfg;
|
||||
|
||||
if (forceAllowFrom) {
|
||||
next = await promptTelegramAllowFrom({
|
||||
cfg: next,
|
||||
prompter,
|
||||
accountId: telegramAccountId,
|
||||
tokenOverride: resolvedTokenForAllowFrom,
|
||||
tokenOverride: tokenStep.resolvedValue,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ export {
|
||||
buildSingleChannelSecretPromptState,
|
||||
promptAccountId,
|
||||
promptSingleChannelSecretInput,
|
||||
runSingleChannelSecretStep,
|
||||
resolveAccountIdForConfigure,
|
||||
} from "../channels/plugins/onboarding/helpers.js";
|
||||
export {
|
||||
|
||||
@@ -27,6 +27,7 @@ export {
|
||||
mergeAllowFromEntries,
|
||||
promptAccountId,
|
||||
promptSingleChannelSecretInput,
|
||||
runSingleChannelSecretStep,
|
||||
resolveAccountIdForConfigure,
|
||||
setTopLevelChannelDmPolicyWithAllowFrom,
|
||||
} from "../channels/plugins/onboarding/helpers.js";
|
||||
|
||||
@@ -21,6 +21,7 @@ export {
|
||||
mergeAllowFromEntries,
|
||||
promptAccountId,
|
||||
promptSingleChannelSecretInput,
|
||||
runSingleChannelSecretStep,
|
||||
resolveAccountIdForConfigure,
|
||||
setTopLevelChannelDmPolicyWithAllowFrom,
|
||||
} from "../channels/plugins/onboarding/helpers.js";
|
||||
|
||||
Reference in New Issue
Block a user