UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

129 lines (128 loc) • 5.48 kB
import { l as normalizeOptionalString } from "./string-coerce-1VuiLaaR.mjs"; import { r as normalizeOptionalAccountId } from "./account-id-ifCOO7_9.mjs"; import { r as assertSecretOwnerAvailable } from "./runtime-degraded-state-Dyd8aD2x.mjs"; import { t as getChannelPlugin } from "./registry-Bcrk1FVy.mjs"; import "./plugins-BXkKReMp.mjs"; import { r as listRuntimeVisibleChannelPlugins } from "./runtime-visible-channels-CY9AX3-A.mjs"; import { t as MessageActionDeniedError } from "./message-action-denial-DOmE5Ll7.mjs"; import { r as resolveOutboundChannelPlugin } from "./channel-resolution-Cdc2q6Ze.mjs"; import { n as resolveChannelAccount, t as channelHasConfiguredState } from "./account-resolution-DCHDXWZ0.mjs"; import { t as isAccountEnabled } from "./account-enabled-ClTLgAXM.mjs"; import { t as isConfiguredChannel } from "./channel-selection-Bo7WWFSi.mjs"; import { i as resolveChannelDefaultAccountId } from "./helpers-COTq3ATj.mjs"; import { o as isChannelAccountExplicitlyDisabled } from "./account-state-DKq2LxPe.mjs"; import { o as resolveChannelAccountEnabled } from "./account-summary-CbGNBm_x.mjs"; //#region src/infra/outbound/message-account-selection.ts /** * Binds a caller-supplied message account to one listed channel account. * Host-derived defaults and binding accounts bypass this helper by design. */ async function validateExplicitMessageAccountSelection(params) { const rawAccountId = normalizeOptionalString(params.accountId); if (!rawAccountId) return; const accountId = normalizeOptionalAccountId(rawAccountId); if (!accountId) throw new MessageActionDeniedError(`Invalid account ID "${rawAccountId}".`, "message_account_invalid", "message-account:valid"); const channel = normalizeOptionalString(params.channel); if (!channel) return accountId; const plugin = params.plugin ?? resolveOutboundChannelPlugin({ channel, cfg: params.cfg }) ?? getChannelPlugin(channel); if (!plugin) return accountId; let listedAccountId = plugin.config.listAccountIds(params.cfg).find((candidate) => normalizeOptionalAccountId(candidate) === accountId); if (!listedAccountId) { const defaultAccountId = resolveChannelDefaultAccountId({ plugin, cfg: params.cfg }); if (normalizeOptionalAccountId(defaultAccountId) === accountId) listedAccountId = defaultAccountId; } if (!listedAccountId) throw new MessageActionDeniedError(`Unknown account "${rawAccountId}" for channel ${channel}.`, "message_account_unknown", "message-account:known"); const assertAccountEnabled = (isResolvedEnabled) => { if (isChannelAccountExplicitlyDisabled({ cfg: params.cfg, channel: plugin.id, accountId: listedAccountId }) || isResolvedEnabled && !isResolvedEnabled()) throw new MessageActionDeniedError(`Account "${listedAccountId}" for channel ${channel} is disabled.`, "message_account_disabled", "message-account:enabled"); }; assertAccountEnabled(); if (params.checkResolvedAccount !== false) { assertSecretOwnerAvailable("account", `${plugin.id}:${accountId}`); const account = await resolveChannelAccount({ plugin, cfg: params.cfg, accountId }); assertSecretOwnerAvailable("account", `${plugin.id}:${accountId}`); assertAccountEnabled(() => resolveChannelAccountEnabled({ plugin, account, cfg: params.cfg })); } return accountId; } /** Checks configured and enabled state after channel availability is resolved. */ async function isPotentialConfiguredMessageChannel(params) { const channelConfig = params.cfg.channels?.[params.plugin.id]; if (!Array.isArray(channelConfig) && !isAccountEnabled(channelConfig)) return false; if (isConfiguredChannel(params.cfg, params.plugin.id)) return true; try { return await channelHasConfiguredState({ plugin: params.plugin, cfg: params.cfg, env: process.env }) === true; } catch { return false; } } /** * Plans an unscoped broadcast before SecretRefs are resolved. Rejected routes * stay in candidateChannels for per-channel errors but cannot expose secrets. * Host-derived binding/default accounts do not use this explicit-account plan. */ async function resolveMessageBroadcastAccountPlan(params) { const accountId = await validateExplicitMessageAccountSelection({ cfg: params.cfg, accountId: params.accountId, checkResolvedAccount: false }); if (!accountId) return; const candidatePlugins = []; for (const plugin of listRuntimeVisibleChannelPlugins()) if (resolveOutboundChannelPlugin({ channel: plugin.id, cfg: params.cfg }) && await isPotentialConfiguredMessageChannel({ cfg: params.cfg, plugin })) candidatePlugins.push(plugin); const secretChannels = []; for (const plugin of candidatePlugins) try { await validateExplicitMessageAccountSelection({ cfg: params.cfg, channel: plugin.id, accountId, plugin, checkResolvedAccount: false }); const inspection = plugin.config.inspectAccount?.(params.cfg, accountId); const account = inspection ?? await resolveChannelAccount({ plugin, cfg: params.cfg, accountId }); if (account !== void 0 && (inspection != null ? isAccountEnabled(inspection) : resolveChannelAccountEnabled({ plugin, account, cfg: params.cfg }))) secretChannels.push(plugin.id); } catch {} return { accountId, candidateChannels: candidatePlugins.map((plugin) => plugin.id), secretChannels }; } //#endregion export { resolveMessageBroadcastAccountPlan as n, validateExplicitMessageAccountSelection as r, isPotentialConfiguredMessageChannel as t };