UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

242 lines (241 loc) 9.76 kB
import "./session-key-BnWWjqNc.js"; import { n as normalizeAccountId, t as DEFAULT_ACCOUNT_ID } from "./account-id-CETVCrTz.js"; import { t as resolveSingleAccountPromotion } from "./setup-promotion-helpers-Cie2zGX6.js"; //#region src/channels/plugins/setup-helpers.ts function getChannelSection(cfg, channelKey) { const section = cfg.channels?.[channelKey]; return section && typeof section === "object" ? section : void 0; } function writeChannelSection(cfg, channelKey, section) { return { ...cfg, channels: { ...cfg.channels, [channelKey]: section } }; } function applyAccountNameToChannelSection(params) { const trimmed = params.name?.trim(); if (!trimmed) return params.cfg; const accountId = normalizeAccountId(params.accountId); const base = getChannelSection(params.cfg, params.channelKey); const accounts = base?.accounts ?? {}; if (!(params.alwaysUseAccounts || accountId !== "default" || Object.keys(accounts).length > 0)) return writeChannelSection(params.cfg, params.channelKey, { ...base, name: trimmed }); const baseWithoutName = accountId === "default" ? (({ name: _ignored, ...rest }) => rest)(base ?? {}) : base ?? {}; return writeChannelSection(params.cfg, params.channelKey, { ...baseWithoutName, accounts: { ...accounts, [accountId]: { ...accounts[accountId], name: trimmed } } }); } /** Moves a root-level channel name into `accounts.default` before adding named accounts. */ function migrateBaseNameToDefaultAccount(params) { if (params.alwaysUseAccounts) return params.cfg; const base = getChannelSection(params.cfg, params.channelKey); const baseName = base?.name?.trim(); if (!baseName) return params.cfg; const accounts = { ...base?.accounts }; const defaultAccount = accounts["default"] ?? {}; if (!defaultAccount.name) accounts[DEFAULT_ACCOUNT_ID] = { ...defaultAccount, name: baseName }; const { name: _ignored, ...rest } = base ?? {}; return writeChannelSection(params.cfg, params.channelKey, { ...rest, accounts }); } /** Applies setup-time account naming and optional root-name migration in one step. */ function prepareScopedSetupConfig(params) { const namedConfig = applyAccountNameToChannelSection({ cfg: params.cfg, channelKey: params.channelKey, accountId: params.accountId, name: params.name, alwaysUseAccounts: params.alwaysUseAccounts }); if (!params.migrateBaseName || normalizeAccountId(params.accountId) === "default") return namedConfig; return migrateBaseNameToDefaultAccount({ cfg: namedConfig, channelKey: params.channelKey, alwaysUseAccounts: params.alwaysUseAccounts }); } /** Applies a setup patch using account-scoped config semantics. */ function applySetupAccountConfigPatch(params) { return patchScopedAccountConfig(params); } /** Creates a setup adapter that turns validated setup input into an account config patch. */ function createPatchedAccountSetupAdapter(params) { return { resolveAccountId: ({ accountId }) => normalizeAccountId(accountId), applyAccountName: ({ cfg, accountId, name }) => prepareScopedSetupConfig({ cfg, channelKey: params.channelKey, accountId, name, alwaysUseAccounts: params.alwaysUseAccounts }), validateInput: params.validateInput, applyAccountConfig: ({ cfg, accountId, input }) => { const next = prepareScopedSetupConfig({ cfg, channelKey: params.channelKey, accountId, name: input.name, alwaysUseAccounts: params.alwaysUseAccounts, migrateBaseName: !params.alwaysUseAccounts }); const patch = params.buildPatch(input); return patchScopedAccountConfig({ cfg: next, channelKey: params.channelKey, accountId, patch, accountPatch: patch, ensureChannelEnabled: params.ensureChannelEnabled ?? !params.alwaysUseAccounts, ensureAccountEnabled: params.ensureAccountEnabled ?? true, scopeDefaultToAccounts: params.alwaysUseAccounts }); } }; } function hasPresentSetupValue(value) { if (typeof value === "string") return value.trim().length > 0; return value !== void 0 && value !== null; } function createSetupInputPresenceValidator(params) { return (inputParams) => { if (params.defaultAccountOnlyEnvError && inputParams.input.useEnv && inputParams.accountId !== "default") return params.defaultAccountOnlyEnvError; if (!inputParams.input.useEnv) { const inputRecord = inputParams.input; for (const requirement of params.whenNotUseEnv ?? []) { if (requirement.someOf.some((key) => hasPresentSetupValue(inputRecord[key]))) continue; return requirement.message; } } return params.validate?.(inputParams) ?? null; }; } /** Creates a setup adapter that supports env-backed default account auth and patched credentials. */ function createEnvPatchedAccountSetupAdapter(params) { return createPatchedAccountSetupAdapter({ channelKey: params.channelKey, alwaysUseAccounts: params.alwaysUseAccounts, ensureChannelEnabled: params.ensureChannelEnabled, ensureAccountEnabled: params.ensureAccountEnabled, validateInput: (inputParams) => { if (inputParams.input.useEnv && inputParams.accountId !== "default") return params.defaultAccountOnlyEnvError; if (!inputParams.input.useEnv && !params.hasCredentials(inputParams.input)) return params.missingCredentialError; return params.validateInput?.(inputParams) ?? null; }, buildPatch: params.buildPatch }); } /** Patches channel config at root for default accounts or under `accounts.<id>` for named accounts. */ function patchScopedAccountConfig(params) { const accountId = normalizeAccountId(params.accountId); const base = getChannelSection(params.cfg, params.channelKey); const ensureChannelEnabled = params.ensureChannelEnabled ?? true; const ensureAccountEnabled = params.ensureAccountEnabled ?? ensureChannelEnabled; const patch = params.patch; const accountPatch = params.accountPatch ?? patch; const clearFields = (record) => { if (!params.clearFields?.length) return record; const cleared = { ...record }; for (const field of params.clearFields) delete cleared[field]; return cleared; }; if (accountId === "default" && !params.scopeDefaultToAccounts) return writeChannelSection(params.cfg, params.channelKey, { ...clearFields(base ?? {}), ...ensureChannelEnabled ? { enabled: true } : {}, ...patch }); const accounts = base?.accounts ?? {}; const existingAccount = clearFields(accounts[accountId] ?? {}); return writeChannelSection(params.cfg, params.channelKey, { ...base, ...ensureChannelEnabled ? { enabled: true } : {}, accounts: { ...accounts, [accountId]: { ...existingAccount, ...ensureAccountEnabled ? { enabled: typeof existingAccount.enabled === "boolean" ? existingAccount.enabled : true } : {}, ...accountPatch } } }); } function moveSingleAccountKeysIntoAccount(params) { const nextAccount = { ...params.baseAccount }; const nextChannel = { ...params.channel }; for (const key of params.keysToMove) { if (!(key in nextAccount)) { const value = params.channel[key]; nextAccount[key] = value && typeof value === "object" ? structuredClone(value) : value; } delete nextChannel[key]; } return writeChannelSection(params.cfg, params.channelKey, { ...nextChannel, accounts: { ...params.accounts, [params.targetAccountId]: nextAccount } }); } function resolveExistingAccountKey(accounts, targetAccountId) { return Object.keys(accounts).find((key) => normalizeAccountId(key) === targetAccountId) ?? targetAccountId; } function resolveSingleAccountPromotionTarget(params) { const pluginTarget = params.setupSurface?.resolveSingleAccountPromotionTarget?.({ channel: params.channel }); if (pluginTarget?.trim()) return normalizeAccountId(pluginTarget); const accounts = params.channel.accounts ?? {}; const normalizedDefaultAccount = typeof params.channel.defaultAccount === "string" && params.channel.defaultAccount.trim() ? normalizeAccountId(params.channel.defaultAccount) : void 0; if (normalizedDefaultAccount) return Object.keys(accounts).find((accountId) => normalizeAccountId(accountId) === normalizedDefaultAccount) ?? "default"; const namedAccounts = Object.keys(accounts).filter(Boolean); return namedAccounts.length === 1 ? namedAccounts[0] ?? "default" : DEFAULT_ACCOUNT_ID; } /** * Promotes legacy single-account channel fields into the account map for multi-account setup. */ function moveSingleAccountChannelSectionToDefaultAccount(params) { const base = getChannelSection(params.cfg, params.channelKey); if (!base) return params.cfg; const accounts = base.accounts ?? {}; const hasAccounts = Object.keys(accounts).length > 0; const promotion = resolveSingleAccountPromotion({ channelKey: params.channelKey, channel: base, setupSurface: params.setupSurface, includeSetupKeys: true }); if (promotion.kind === "preserve-root") return params.cfg; const { keysToMove } = promotion; if (hasAccounts && keysToMove.length === 0) return params.cfg; const resolvedTargetAccountKey = resolveExistingAccountKey(accounts, hasAccounts ? resolveSingleAccountPromotionTarget({ channel: base, setupSurface: params.setupSurface }) : DEFAULT_ACCOUNT_ID); return moveSingleAccountKeysIntoAccount({ cfg: params.cfg, channelKey: params.channelKey, channel: base, accounts, keysToMove, targetAccountId: resolvedTargetAccountKey, baseAccount: accounts[resolvedTargetAccountKey] }); } //#endregion export { createSetupInputPresenceValidator as a, patchScopedAccountConfig as c, createPatchedAccountSetupAdapter as i, prepareScopedSetupConfig as l, applySetupAccountConfigPatch as n, migrateBaseNameToDefaultAccount as o, createEnvPatchedAccountSetupAdapter as r, moveSingleAccountChannelSectionToDefaultAccount as s, applyAccountNameToChannelSection as t };