mirror of https://github.com/openclaw/openclaw.git
refactor: share channel setup status helpers
This commit is contained in:
parent
583bea001c
commit
5c8ea0a175
|
|
@ -283,6 +283,11 @@ helpers from `openclaw/plugin-sdk/setup`: `createPromptParsedAllowFromForAccount
|
|||
`createTopLevelChannelParsedAllowFromPrompt(...)`, and
|
||||
`createNestedChannelParsedAllowFromPrompt(...)`.
|
||||
|
||||
For channel setup status blocks that only vary by labels, scores, and optional
|
||||
extra lines, prefer `createStandardChannelSetupStatus(...)` from
|
||||
`openclaw/plugin-sdk/setup` instead of hand-rolling the same `status` object in
|
||||
each plugin.
|
||||
|
||||
For optional setup surfaces that should only appear in certain contexts, use
|
||||
`createOptionalChannelSetupSurface` from `openclaw/plugin-sdk/channel-setup`:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import {
|
||||
createAllowFromSection,
|
||||
createPromptParsedAllowFromForAccount,
|
||||
createStandardChannelSetupStatus,
|
||||
DEFAULT_ACCOUNT_ID,
|
||||
formatDocsLink,
|
||||
type ChannelSetupDmPolicy,
|
||||
|
|
@ -143,20 +144,21 @@ export const blueBubblesSetupWizard: ChannelSetupWizard = {
|
|||
channel,
|
||||
stepOrder: "text-first",
|
||||
status: {
|
||||
configuredLabel: "configured",
|
||||
unconfiguredLabel: "needs setup",
|
||||
configuredHint: "configured",
|
||||
unconfiguredHint: "iMessage via BlueBubbles app",
|
||||
configuredScore: 1,
|
||||
unconfiguredScore: 0,
|
||||
resolveConfigured: ({ cfg }) =>
|
||||
listBlueBubblesAccountIds(cfg).some((accountId) => {
|
||||
const account = resolveBlueBubblesAccount({ cfg, accountId });
|
||||
return account.configured;
|
||||
}),
|
||||
resolveStatusLines: ({ configured }) => [
|
||||
`BlueBubbles: ${configured ? "configured" : "needs setup"}`,
|
||||
],
|
||||
...createStandardChannelSetupStatus({
|
||||
channelLabel: "BlueBubbles",
|
||||
configuredLabel: "configured",
|
||||
unconfiguredLabel: "needs setup",
|
||||
configuredHint: "configured",
|
||||
unconfiguredHint: "iMessage via BlueBubbles app",
|
||||
configuredScore: 1,
|
||||
unconfiguredScore: 0,
|
||||
includeStatusLine: true,
|
||||
resolveConfigured: ({ cfg }) =>
|
||||
listBlueBubblesAccountIds(cfg).some((accountId) => {
|
||||
const account = resolveBlueBubblesAccount({ cfg, accountId });
|
||||
return account.configured;
|
||||
}),
|
||||
}),
|
||||
resolveSelectionHint: ({ configured }) =>
|
||||
configured ? "configured" : "iMessage via BlueBubbles app",
|
||||
},
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import type {
|
|||
ChannelSetupDmPolicy,
|
||||
ChannelSetupWizard,
|
||||
} from "openclaw/plugin-sdk/setup-runtime";
|
||||
import { createStandardChannelSetupStatus } from "openclaw/plugin-sdk/setup-runtime";
|
||||
import { formatDocsLink } from "openclaw/plugin-sdk/setup-tools";
|
||||
import {
|
||||
inspectDiscordSetupAccount,
|
||||
|
|
@ -99,7 +100,8 @@ export function createDiscordSetupWizardBase(handlers: {
|
|||
|
||||
return {
|
||||
channel,
|
||||
status: {
|
||||
status: createStandardChannelSetupStatus({
|
||||
channelLabel: "Discord",
|
||||
configuredLabel: "configured",
|
||||
unconfiguredLabel: "needs token",
|
||||
configuredHint: "configured",
|
||||
|
|
@ -111,7 +113,7 @@ export function createDiscordSetupWizardBase(handlers: {
|
|||
const account = inspectDiscordSetupAccount({ cfg, accountId });
|
||||
return account.configured;
|
||||
}),
|
||||
},
|
||||
}),
|
||||
credentials: [
|
||||
{
|
||||
inputKey: "token",
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import {
|
|||
applySetupAccountConfigPatch,
|
||||
createNestedChannelParsedAllowFromPrompt,
|
||||
createNestedChannelDmPolicy,
|
||||
createStandardChannelSetupStatus,
|
||||
DEFAULT_ACCOUNT_ID,
|
||||
formatDocsLink,
|
||||
mergeAllowFromEntries,
|
||||
|
|
@ -51,22 +52,18 @@ export { googlechatSetupAdapter } from "./setup-core.js";
|
|||
|
||||
export const googlechatSetupWizard: ChannelSetupWizard = {
|
||||
channel,
|
||||
status: {
|
||||
status: createStandardChannelSetupStatus({
|
||||
channelLabel: "Google Chat",
|
||||
configuredLabel: "configured",
|
||||
unconfiguredLabel: "needs service account",
|
||||
configuredHint: "configured",
|
||||
unconfiguredHint: "needs auth",
|
||||
includeStatusLine: true,
|
||||
resolveConfigured: ({ cfg }) =>
|
||||
listGoogleChatAccountIds(cfg).some(
|
||||
(accountId) => resolveGoogleChatAccount({ cfg, accountId }).credentialSource !== "none",
|
||||
),
|
||||
resolveStatusLines: ({ cfg }) => {
|
||||
const configured = listGoogleChatAccountIds(cfg).some(
|
||||
(accountId) => resolveGoogleChatAccount({ cfg, accountId }).credentialSource !== "none",
|
||||
);
|
||||
return [`Google Chat: ${configured ? "configured" : "needs service account"}`];
|
||||
},
|
||||
},
|
||||
}),
|
||||
introNote: {
|
||||
title: "Google Chat setup",
|
||||
lines: [
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/routing";
|
|||
import {
|
||||
createAllowFromSection,
|
||||
createPromptParsedAllowFromForAccount,
|
||||
createStandardChannelSetupStatus,
|
||||
setSetupChannelEnabled,
|
||||
} from "openclaw/plugin-sdk/setup";
|
||||
import type { ChannelSetupDmPolicy } from "openclaw/plugin-sdk/setup";
|
||||
|
|
@ -168,21 +169,20 @@ const ircDmPolicy: ChannelSetupDmPolicy = {
|
|||
|
||||
export const ircSetupWizard: ChannelSetupWizard = {
|
||||
channel,
|
||||
status: {
|
||||
status: createStandardChannelSetupStatus({
|
||||
channelLabel: "IRC",
|
||||
configuredLabel: "configured",
|
||||
unconfiguredLabel: "needs host + nick",
|
||||
configuredHint: "configured",
|
||||
unconfiguredHint: "needs host + nick",
|
||||
configuredScore: 1,
|
||||
unconfiguredScore: 0,
|
||||
includeStatusLine: true,
|
||||
resolveConfigured: ({ cfg }) =>
|
||||
listIrcAccountIds(cfg as CoreConfig).some(
|
||||
(accountId) => resolveIrcAccount({ cfg: cfg as CoreConfig, accountId }).configured,
|
||||
),
|
||||
resolveStatusLines: ({ configured }) => [
|
||||
`IRC: ${configured ? "configured" : "needs host + nick"}`,
|
||||
],
|
||||
},
|
||||
}),
|
||||
introNote: {
|
||||
title: "IRC setup",
|
||||
lines: [
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
import { createAllowFromSection, createTopLevelChannelDmPolicy } from "openclaw/plugin-sdk/setup";
|
||||
import {
|
||||
createAllowFromSection,
|
||||
createStandardChannelSetupStatus,
|
||||
createTopLevelChannelDmPolicy,
|
||||
} from "openclaw/plugin-sdk/setup";
|
||||
import {
|
||||
DEFAULT_ACCOUNT_ID,
|
||||
formatDocsLink,
|
||||
|
|
@ -47,20 +51,19 @@ export { lineSetupAdapter } from "./setup-core.js";
|
|||
|
||||
export const lineSetupWizard: ChannelSetupWizard = {
|
||||
channel,
|
||||
status: {
|
||||
status: createStandardChannelSetupStatus({
|
||||
channelLabel: "LINE",
|
||||
configuredLabel: "configured",
|
||||
unconfiguredLabel: "needs token + secret",
|
||||
configuredHint: "configured",
|
||||
unconfiguredHint: "needs token + secret",
|
||||
configuredScore: 1,
|
||||
unconfiguredScore: 0,
|
||||
includeStatusLine: true,
|
||||
resolveConfigured: ({ cfg }) =>
|
||||
listLineAccountIds(cfg).some((accountId) => isLineConfigured(cfg, accountId)),
|
||||
resolveStatusLines: ({ cfg, configured }) => [
|
||||
`LINE: ${configured ? "configured" : "needs token + secret"}`,
|
||||
`Accounts: ${listLineAccountIds(cfg).length || 0}`,
|
||||
],
|
||||
},
|
||||
resolveExtraStatusLines: ({ cfg }) => [`Accounts: ${listLineAccountIds(cfg).length || 0}`],
|
||||
}),
|
||||
introNote: {
|
||||
title: "LINE Messaging API",
|
||||
lines: LINE_SETUP_HELP_LINES,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
import { type ChannelSetupWizard } from "openclaw/plugin-sdk/setup";
|
||||
import { formatDocsLink } from "openclaw/plugin-sdk/setup";
|
||||
import {
|
||||
createStandardChannelSetupStatus,
|
||||
formatDocsLink,
|
||||
type ChannelSetupWizard,
|
||||
} from "openclaw/plugin-sdk/setup";
|
||||
import { listMattermostAccountIds } from "./mattermost/accounts.js";
|
||||
import { normalizeMattermostBaseUrl } from "./mattermost/client.js";
|
||||
import {
|
||||
|
|
@ -19,7 +22,8 @@ export { mattermostSetupAdapter } from "./setup-core.js";
|
|||
|
||||
export const mattermostSetupWizard: ChannelSetupWizard = {
|
||||
channel,
|
||||
status: {
|
||||
status: createStandardChannelSetupStatus({
|
||||
channelLabel: "Mattermost",
|
||||
configuredLabel: "configured",
|
||||
unconfiguredLabel: "needs token + url",
|
||||
configuredHint: "configured",
|
||||
|
|
@ -30,7 +34,7 @@ export const mattermostSetupWizard: ChannelSetupWizard = {
|
|||
listMattermostAccountIds(cfg).some((accountId) =>
|
||||
isMattermostConfigured(resolveMattermostAccountWithSecrets(cfg, accountId)),
|
||||
),
|
||||
},
|
||||
}),
|
||||
introNote: {
|
||||
title: "Mattermost bot token",
|
||||
lines: [
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import {
|
|||
createTopLevelChannelAllowFromSetter,
|
||||
createTopLevelChannelDmPolicy,
|
||||
createTopLevelChannelGroupPolicySetter,
|
||||
createStandardChannelSetupStatus,
|
||||
DEFAULT_ACCOUNT_ID,
|
||||
formatDocsLink,
|
||||
mergeAllowFromEntries,
|
||||
|
|
@ -274,26 +275,19 @@ export const msteamsSetupWizard: ChannelSetupWizard = {
|
|||
channel,
|
||||
resolveAccountIdForConfigure: () => DEFAULT_ACCOUNT_ID,
|
||||
resolveShouldPromptAccountIds: () => false,
|
||||
status: {
|
||||
status: createStandardChannelSetupStatus({
|
||||
channelLabel: "MS Teams",
|
||||
configuredLabel: "configured",
|
||||
unconfiguredLabel: "needs app credentials",
|
||||
configuredHint: "configured",
|
||||
unconfiguredHint: "needs app creds",
|
||||
configuredScore: 2,
|
||||
unconfiguredScore: 0,
|
||||
resolveConfigured: ({ cfg }) => {
|
||||
return (
|
||||
Boolean(resolveMSTeamsCredentials(cfg.channels?.msteams)) ||
|
||||
hasConfiguredMSTeamsCredentials(cfg.channels?.msteams)
|
||||
);
|
||||
},
|
||||
resolveStatusLines: ({ cfg }) => {
|
||||
const configured =
|
||||
Boolean(resolveMSTeamsCredentials(cfg.channels?.msteams)) ||
|
||||
hasConfiguredMSTeamsCredentials(cfg.channels?.msteams);
|
||||
return [`MS Teams: ${configured ? "configured" : "needs app credentials"}`];
|
||||
},
|
||||
},
|
||||
includeStatusLine: true,
|
||||
resolveConfigured: ({ cfg }) =>
|
||||
Boolean(resolveMSTeamsCredentials(cfg.channels?.msteams)) ||
|
||||
hasConfiguredMSTeamsCredentials(cfg.channels?.msteams),
|
||||
}),
|
||||
credentials: [],
|
||||
finalize: async ({ cfg, prompter }) => {
|
||||
const resolved = resolveMSTeamsCredentials(cfg.channels?.msteams);
|
||||
|
|
|
|||
|
|
@ -2,9 +2,12 @@ import type { ChannelSetupInput } from "openclaw/plugin-sdk/channel-setup";
|
|||
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/routing";
|
||||
import { hasConfiguredSecretInput } from "openclaw/plugin-sdk/secret-input";
|
||||
import { setSetupChannelEnabled } from "openclaw/plugin-sdk/setup";
|
||||
import { type ChannelSetupWizard } from "openclaw/plugin-sdk/setup";
|
||||
import { formatDocsLink } from "openclaw/plugin-sdk/setup";
|
||||
import {
|
||||
createStandardChannelSetupStatus,
|
||||
formatDocsLink,
|
||||
setSetupChannelEnabled,
|
||||
type ChannelSetupWizard,
|
||||
} from "openclaw/plugin-sdk/setup";
|
||||
import { listNextcloudTalkAccountIds, resolveNextcloudTalkAccount } from "./accounts.js";
|
||||
import {
|
||||
clearNextcloudTalkAccountFields,
|
||||
|
|
@ -22,7 +25,8 @@ const CONFIGURE_API_FLAG = "__nextcloudTalkConfigureApiCredentials";
|
|||
export const nextcloudTalkSetupWizard: ChannelSetupWizard = {
|
||||
channel,
|
||||
stepOrder: "text-first",
|
||||
status: {
|
||||
status: createStandardChannelSetupStatus({
|
||||
channelLabel: "Nextcloud Talk",
|
||||
configuredLabel: "configured",
|
||||
unconfiguredLabel: "needs setup",
|
||||
configuredHint: "configured",
|
||||
|
|
@ -34,7 +38,7 @@ export const nextcloudTalkSetupWizard: ChannelSetupWizard = {
|
|||
const account = resolveNextcloudTalkAccount({ cfg: cfg as CoreConfig, accountId });
|
||||
return Boolean(account.secret && account.baseUrl);
|
||||
}),
|
||||
},
|
||||
}),
|
||||
introNote: {
|
||||
title: "Nextcloud Talk bot setup",
|
||||
lines: [
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/routing";
|
|||
import {
|
||||
createTopLevelChannelParsedAllowFromPrompt,
|
||||
createTopLevelChannelDmPolicy,
|
||||
createStandardChannelSetupStatus,
|
||||
mergeAllowFromEntries,
|
||||
parseSetupEntriesWithParser,
|
||||
patchTopLevelChannelConfigSection,
|
||||
|
|
@ -139,22 +140,21 @@ export const nostrSetupWizard: ChannelSetupWizard = {
|
|||
channel,
|
||||
resolveAccountIdForConfigure: () => DEFAULT_ACCOUNT_ID,
|
||||
resolveShouldPromptAccountIds: () => false,
|
||||
status: {
|
||||
status: createStandardChannelSetupStatus({
|
||||
channelLabel: "Nostr",
|
||||
configuredLabel: "configured",
|
||||
unconfiguredLabel: "needs private key",
|
||||
configuredHint: "configured",
|
||||
unconfiguredHint: "needs private key",
|
||||
configuredScore: 1,
|
||||
unconfiguredScore: 0,
|
||||
includeStatusLine: true,
|
||||
resolveConfigured: ({ cfg }) => resolveNostrAccount({ cfg }).configured,
|
||||
resolveStatusLines: ({ cfg, configured }) => {
|
||||
resolveExtraStatusLines: ({ cfg }) => {
|
||||
const account = resolveNostrAccount({ cfg });
|
||||
return [
|
||||
`Nostr: ${configured ? "configured" : "needs private key"}`,
|
||||
`Relays: ${account.relays.length || DEFAULT_RELAYS.length}`,
|
||||
];
|
||||
return [`Relays: ${account.relays.length || DEFAULT_RELAYS.length}`];
|
||||
},
|
||||
},
|
||||
}),
|
||||
introNote: {
|
||||
title: "Nostr setup",
|
||||
lines: NOSTR_SETUP_HELP_LINES,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import {
|
|||
createAccountScopedAllowFromSection,
|
||||
createAccountScopedGroupAccessSection,
|
||||
createLegacyCompatChannelDmPolicy,
|
||||
createStandardChannelSetupStatus,
|
||||
DEFAULT_ACCOUNT_ID,
|
||||
createEnvPatchedAccountSetupAdapter,
|
||||
hasConfiguredSecretInput,
|
||||
|
|
@ -119,7 +120,8 @@ export function createSlackSetupWizardBase(handlers: {
|
|||
|
||||
return {
|
||||
channel,
|
||||
status: {
|
||||
status: createStandardChannelSetupStatus({
|
||||
channelLabel: "Slack",
|
||||
configuredLabel: "configured",
|
||||
unconfiguredLabel: "needs tokens",
|
||||
configuredHint: "configured",
|
||||
|
|
@ -131,7 +133,7 @@ export function createSlackSetupWizardBase(handlers: {
|
|||
const account = inspectSlackAccount({ cfg, accountId });
|
||||
return account.configured;
|
||||
}),
|
||||
},
|
||||
}),
|
||||
introNote: {
|
||||
title: "Slack socket mode tokens",
|
||||
lines: buildSlackSetupLines(),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import {
|
||||
createAllowFromSection,
|
||||
createStandardChannelSetupStatus,
|
||||
DEFAULT_ACCOUNT_ID,
|
||||
formatDocsLink,
|
||||
mergeAllowFromEntries,
|
||||
|
|
@ -176,20 +177,19 @@ export const synologyChatSetupAdapter: ChannelSetupAdapter = {
|
|||
|
||||
export const synologyChatSetupWizard: ChannelSetupWizard = {
|
||||
channel,
|
||||
status: {
|
||||
status: createStandardChannelSetupStatus({
|
||||
channelLabel: "Synology Chat",
|
||||
configuredLabel: "configured",
|
||||
unconfiguredLabel: "needs token + incoming webhook",
|
||||
configuredHint: "configured",
|
||||
unconfiguredHint: "needs token + incoming webhook",
|
||||
configuredScore: 1,
|
||||
unconfiguredScore: 0,
|
||||
includeStatusLine: true,
|
||||
resolveConfigured: ({ cfg }) =>
|
||||
listAccountIds(cfg).some((accountId) => isSynologyChatConfigured(cfg, accountId)),
|
||||
resolveStatusLines: ({ cfg, configured }) => [
|
||||
`Synology Chat: ${configured ? "configured" : "needs token + incoming webhook"}`,
|
||||
`Accounts: ${listAccountIds(cfg).length || 0}`,
|
||||
],
|
||||
},
|
||||
resolveExtraStatusLines: ({ cfg }) => [`Accounts: ${listAccountIds(cfg).length || 0}`],
|
||||
}),
|
||||
introNote: {
|
||||
title: "Synology Chat webhook setup",
|
||||
lines: SYNOLOGY_SETUP_HELP_LINES,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import {
|
||||
createAllowFromSection,
|
||||
createStandardChannelSetupStatus,
|
||||
DEFAULT_ACCOUNT_ID,
|
||||
hasConfiguredSecretInput,
|
||||
type OpenClawConfig,
|
||||
|
|
@ -92,7 +93,8 @@ const dmPolicy: ChannelSetupDmPolicy = {
|
|||
|
||||
export const telegramSetupWizard: ChannelSetupWizard = {
|
||||
channel,
|
||||
status: {
|
||||
status: createStandardChannelSetupStatus({
|
||||
channelLabel: "Telegram",
|
||||
configuredLabel: "configured",
|
||||
unconfiguredLabel: "needs token",
|
||||
configuredHint: "recommended · configured",
|
||||
|
|
@ -104,7 +106,7 @@ export const telegramSetupWizard: ChannelSetupWizard = {
|
|||
const account = inspectTelegramAccount({ cfg, accountId });
|
||||
return account.configured;
|
||||
}),
|
||||
},
|
||||
}),
|
||||
prepare: async ({ cfg, accountId, credentialValues }) => ({
|
||||
cfg: ensureTelegramDefaultGroupMentionGate(cfg, accountId),
|
||||
credentialValues,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import {
|
||||
buildSingleChannelSecretPromptState,
|
||||
createTopLevelChannelDmPolicy,
|
||||
createStandardChannelSetupStatus,
|
||||
DEFAULT_ACCOUNT_ID,
|
||||
formatDocsLink,
|
||||
hasConfiguredSecretInput,
|
||||
|
|
@ -195,13 +196,15 @@ export { zaloSetupAdapter } from "./setup-core.js";
|
|||
|
||||
export const zaloSetupWizard: ChannelSetupWizard = {
|
||||
channel,
|
||||
status: {
|
||||
status: createStandardChannelSetupStatus({
|
||||
channelLabel: "Zalo",
|
||||
configuredLabel: "configured",
|
||||
unconfiguredLabel: "needs token",
|
||||
configuredHint: "recommended · configured",
|
||||
unconfiguredHint: "recommended · newcomer-friendly",
|
||||
configuredScore: 1,
|
||||
unconfiguredScore: 10,
|
||||
includeStatusLine: true,
|
||||
resolveConfigured: ({ cfg }) =>
|
||||
listZaloAccountIds(cfg).some((accountId) => {
|
||||
const account = resolveZaloAccount({
|
||||
|
|
@ -215,11 +218,7 @@ export const zaloSetupWizard: ChannelSetupWizard = {
|
|||
Boolean(account.config.tokenFile?.trim())
|
||||
);
|
||||
}),
|
||||
resolveStatusLines: ({ cfg, configured }) => {
|
||||
void cfg;
|
||||
return [`Zalo: ${configured ? "configured" : "needs token"}`];
|
||||
},
|
||||
},
|
||||
}),
|
||||
credentials: [],
|
||||
finalize: async ({ cfg, accountId, forceAllowFrom, options, prompter }) => {
|
||||
let next = cfg;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import {
|
|||
createLegacyCompatChannelDmPolicy,
|
||||
createNestedChannelParsedAllowFromPrompt,
|
||||
createPromptParsedAllowFromForAccount,
|
||||
createStandardChannelSetupStatus,
|
||||
createNestedChannelAllowFromSetter,
|
||||
createNestedChannelDmPolicy,
|
||||
createNestedChannelDmPolicySetter,
|
||||
|
|
@ -1816,6 +1817,46 @@ describe("normalizeAllowFromEntries", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("createStandardChannelSetupStatus", () => {
|
||||
it("returns the shared status fields without status lines by default", async () => {
|
||||
const status = createStandardChannelSetupStatus({
|
||||
channelLabel: "Demo",
|
||||
configuredLabel: "configured",
|
||||
unconfiguredLabel: "needs token",
|
||||
configuredHint: "ready",
|
||||
unconfiguredHint: "missing token",
|
||||
configuredScore: 2,
|
||||
unconfiguredScore: 0,
|
||||
resolveConfigured: ({ cfg }) => Boolean(cfg.channels?.demo),
|
||||
});
|
||||
|
||||
expect(status.configuredHint).toBe("ready");
|
||||
expect(status.unconfiguredHint).toBe("missing token");
|
||||
expect(status.configuredScore).toBe(2);
|
||||
expect(status.unconfiguredScore).toBe(0);
|
||||
expect(await status.resolveConfigured({ cfg: { channels: { demo: {} } } })).toBe(true);
|
||||
expect(status.resolveStatusLines).toBeUndefined();
|
||||
});
|
||||
|
||||
it("builds the default status line plus extra lines when requested", async () => {
|
||||
const status = createStandardChannelSetupStatus({
|
||||
channelLabel: "Demo",
|
||||
configuredLabel: "configured",
|
||||
unconfiguredLabel: "needs token",
|
||||
includeStatusLine: true,
|
||||
resolveConfigured: ({ cfg }) => Boolean(cfg.channels?.demo),
|
||||
resolveExtraStatusLines: ({ configured }) => [`Configured: ${configured ? "yes" : "no"}`],
|
||||
});
|
||||
|
||||
expect(
|
||||
await status.resolveStatusLines?.({
|
||||
cfg: { channels: { demo: {} } },
|
||||
configured: true,
|
||||
}),
|
||||
).toEqual(["Demo: configured", "Configured: yes"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("resolveSetupAccountId", () => {
|
||||
it("normalizes provided account ids", () => {
|
||||
expect(
|
||||
|
|
|
|||
|
|
@ -13,7 +13,11 @@ import type {
|
|||
PromptAccountId,
|
||||
PromptAccountIdParams,
|
||||
} from "./setup-wizard-types.js";
|
||||
import type { ChannelSetupWizard, ChannelSetupWizardAllowFromEntry } from "./setup-wizard.js";
|
||||
import type {
|
||||
ChannelSetupWizard,
|
||||
ChannelSetupWizardAllowFromEntry,
|
||||
ChannelSetupWizardStatus,
|
||||
} from "./setup-wizard.js";
|
||||
|
||||
let providerAuthInputPromise:
|
||||
| Promise<Pick<typeof import("../../plugins/provider-auth-ref.js"), "promptSecretRefForSetup">>
|
||||
|
|
@ -156,6 +160,50 @@ export function normalizeAllowFromEntries(
|
|||
return [...new Set(normalized)];
|
||||
}
|
||||
|
||||
export function createStandardChannelSetupStatus(params: {
|
||||
channelLabel: string;
|
||||
configuredLabel: string;
|
||||
unconfiguredLabel: string;
|
||||
configuredHint?: string;
|
||||
unconfiguredHint?: string;
|
||||
configuredScore?: number;
|
||||
unconfiguredScore?: number;
|
||||
includeStatusLine?: boolean;
|
||||
resolveConfigured: ChannelSetupWizardStatus["resolveConfigured"];
|
||||
resolveExtraStatusLines?: (params: {
|
||||
cfg: OpenClawConfig;
|
||||
configured: boolean;
|
||||
}) => string[] | Promise<string[]>;
|
||||
}): ChannelSetupWizardStatus {
|
||||
const status: ChannelSetupWizardStatus = {
|
||||
configuredLabel: params.configuredLabel,
|
||||
unconfiguredLabel: params.unconfiguredLabel,
|
||||
resolveConfigured: params.resolveConfigured,
|
||||
...(params.configuredHint ? { configuredHint: params.configuredHint } : {}),
|
||||
...(params.unconfiguredHint ? { unconfiguredHint: params.unconfiguredHint } : {}),
|
||||
...(typeof params.configuredScore === "number"
|
||||
? { configuredScore: params.configuredScore }
|
||||
: {}),
|
||||
...(typeof params.unconfiguredScore === "number"
|
||||
? { unconfiguredScore: params.unconfiguredScore }
|
||||
: {}),
|
||||
};
|
||||
|
||||
if (params.includeStatusLine || params.resolveExtraStatusLines) {
|
||||
status.resolveStatusLines = async ({ cfg, configured }) => {
|
||||
const lines = params.includeStatusLine
|
||||
? [
|
||||
`${params.channelLabel}: ${configured ? params.configuredLabel : params.unconfiguredLabel}`,
|
||||
]
|
||||
: [];
|
||||
const extraLines = (await params.resolveExtraStatusLines?.({ cfg, configured })) ?? [];
|
||||
return [...lines, ...extraLines];
|
||||
};
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
export function resolveSetupAccountId(params: {
|
||||
accountId?: string;
|
||||
defaultAccountId: string;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ export {
|
|||
createAccountScopedAllowFromSection,
|
||||
createAccountScopedGroupAccessSection,
|
||||
createLegacyCompatChannelDmPolicy,
|
||||
createStandardChannelSetupStatus,
|
||||
parseMentionOrPrefixedId,
|
||||
patchChannelConfigForAccount,
|
||||
promptLegacyChannelAllowFromForAccount,
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ export {
|
|||
createLegacyCompatChannelDmPolicy,
|
||||
createNestedChannelParsedAllowFromPrompt,
|
||||
createPromptParsedAllowFromForAccount,
|
||||
createStandardChannelSetupStatus,
|
||||
createNestedChannelAllowFromSetter,
|
||||
createNestedChannelDmPolicy,
|
||||
createNestedChannelDmPolicySetter,
|
||||
|
|
|
|||
Loading…
Reference in New Issue