refactor: share scoped account accessor adapters

This commit is contained in:
Peter Steinberger
2026-03-22 20:04:22 +00:00
parent 8aca2fdc73
commit fa13c2960e
21 changed files with 126 additions and 57 deletions

View File

@@ -1,5 +1,8 @@
import { formatNormalizedAllowFromEntries } from "openclaw/plugin-sdk/allow-from";
import { createScopedChannelConfigAdapter } from "openclaw/plugin-sdk/channel-config-helpers";
import {
adaptScopedAccountAccessor,
createScopedChannelConfigAdapter,
} from "openclaw/plugin-sdk/channel-config-helpers";
import { buildChannelConfigSchema } from "openclaw/plugin-sdk/channel-config-schema";
import type { ChannelPlugin } from "openclaw/plugin-sdk/core";
import {
@@ -30,7 +33,7 @@ const meta = {
const bluebubblesConfigAdapter = createScopedChannelConfigAdapter<ResolvedBlueBubblesAccount>({
sectionKey: "bluebubbles",
listAccountIds: listBlueBubblesAccountIds,
resolveAccount: (cfg, accountId) => resolveBlueBubblesAccount({ cfg, accountId }),
resolveAccount: adaptScopedAccountAccessor(resolveBlueBubblesAccount),
defaultAccountId: resolveDefaultBlueBubblesAccountId,
clearBaseFields: ["serverUrl", "password", "name", "webhookPath"],
resolveAllowFrom: (account: ResolvedBlueBubblesAccount) => account.config.allowFrom,

View File

@@ -1,5 +1,6 @@
import { formatNormalizedAllowFromEntries } from "openclaw/plugin-sdk/allow-from";
import {
adaptScopedAccountAccessor,
createScopedChannelConfigAdapter,
createScopedDmSecurityResolver,
} from "openclaw/plugin-sdk/channel-config-helpers";
@@ -57,7 +58,7 @@ const loadBlueBubblesChannelRuntime = createLazyRuntimeNamedExport(
const bluebubblesConfigAdapter = createScopedChannelConfigAdapter<ResolvedBlueBubblesAccount>({
sectionKey: "bluebubbles",
listAccountIds: listBlueBubblesAccountIds,
resolveAccount: (cfg, accountId) => resolveBlueBubblesAccount({ cfg, accountId }),
resolveAccount: adaptScopedAccountAccessor(resolveBlueBubblesAccount),
defaultAccountId: resolveDefaultBlueBubblesAccountId,
clearBaseFields: ["serverUrl", "password", "name", "webhookPath"],
resolveAllowFrom: (account: ResolvedBlueBubblesAccount) => account.config.allowFrom,

View File

@@ -1,4 +1,5 @@
import { formatAllowFromLowercase } from "openclaw/plugin-sdk/allow-from";
import { adaptScopedAccountAccessor } from "openclaw/plugin-sdk/channel-config-helpers";
import { createChannelPluginBase } from "openclaw/plugin-sdk/core";
import { inspectDiscordAccount } from "./account-inspect.js";
import {
@@ -29,8 +30,8 @@ export const discordSetupWizard = createDiscordSetupWizardProxy(
export const discordConfigAdapter = createScopedChannelConfigAdapter<ResolvedDiscordAccount>({
sectionKey: DISCORD_CHANNEL,
listAccountIds: listDiscordAccountIds,
resolveAccount: (cfg, accountId) => resolveDiscordAccount({ cfg, accountId }),
inspectAccount: (cfg, accountId) => inspectDiscordAccount({ cfg, accountId }),
resolveAccount: adaptScopedAccountAccessor(resolveDiscordAccount),
inspectAccount: adaptScopedAccountAccessor(inspectDiscordAccount),
defaultAccountId: resolveDefaultDiscordAccountId,
clearBaseFields: ["token", "name"],
resolveAllowFrom: (account: ResolvedDiscordAccount) => account.config.dm?.allowFrom,

View File

@@ -1,6 +1,9 @@
import { formatAllowFromLowercase } from "openclaw/plugin-sdk/allow-from";
import { createMessageToolCardSchema } from "openclaw/plugin-sdk/channel-actions";
import { createHybridChannelConfigAdapter } from "openclaw/plugin-sdk/channel-config-helpers";
import {
adaptScopedAccountAccessor,
createHybridChannelConfigAdapter,
} from "openclaw/plugin-sdk/channel-config-helpers";
import type {
ChannelMessageActionAdapter,
ChannelMessageToolDiscovery,
@@ -164,7 +167,7 @@ const feishuConfigAdapter = createHybridChannelConfigAdapter<
>({
sectionKey: "feishu",
listAccountIds: listFeishuAccountIds,
resolveAccount: (cfg, accountId) => resolveFeishuAccount({ cfg, accountId }),
resolveAccount: adaptScopedAccountAccessor(resolveFeishuAccount),
defaultAccountId: resolveDefaultFeishuAccountId,
clearBaseFields: [],
resolveAllowFrom: (account) => account.config.allowFrom,

View File

@@ -1,5 +1,8 @@
import { formatNormalizedAllowFromEntries } from "openclaw/plugin-sdk/allow-from";
import { createScopedChannelConfigAdapter } from "openclaw/plugin-sdk/channel-config-helpers";
import {
adaptScopedAccountAccessor,
createScopedChannelConfigAdapter,
} from "openclaw/plugin-sdk/channel-config-helpers";
import {
composeWarningCollectors,
createAllowlistProviderGroupPolicyWarningCollector,
@@ -65,7 +68,7 @@ const formatAllowFromEntry = (entry: string) =>
const googleChatConfigAdapter = createScopedChannelConfigAdapter<ResolvedGoogleChatAccount>({
sectionKey: "googlechat",
listAccountIds: listGoogleChatAccountIds,
resolveAccount: (cfg, accountId) => resolveGoogleChatAccount({ cfg, accountId }),
resolveAccount: adaptScopedAccountAccessor(resolveGoogleChatAccount),
defaultAccountId: resolveDefaultGoogleChatAccountId,
clearBaseFields: [
"serviceAccount",
@@ -166,16 +169,16 @@ export const googlechatPlugin = createChatChannelPlugin({
},
directory: createChannelDirectoryAdapter({
listPeers: async (params) =>
listResolvedDirectoryUserEntriesFromAllowFrom({
listResolvedDirectoryUserEntriesFromAllowFrom<ResolvedGoogleChatAccount>({
...params,
resolveAccount: (cfg, accountId) => resolveGoogleChatAccount({ cfg, accountId }),
resolveAccount: adaptScopedAccountAccessor(resolveGoogleChatAccount),
resolveAllowFrom: (account) => account.config.dm?.allowFrom,
normalizeId: (entry) => normalizeGoogleChatTarget(entry) ?? entry,
}),
listGroups: async (params) =>
listResolvedDirectoryGroupEntriesFromMapKeys({
listResolvedDirectoryGroupEntriesFromMapKeys<ResolvedGoogleChatAccount>({
...params,
resolveAccount: (cfg, accountId) => resolveGoogleChatAccount({ cfg, accountId }),
resolveAccount: adaptScopedAccountAccessor(resolveGoogleChatAccount),
resolveGroups: (account) => account.config.groups,
}),
}),

View File

@@ -1,4 +1,5 @@
import {
adaptScopedAccountAccessor,
createScopedChannelConfigAdapter,
createScopedDmSecurityResolver,
formatTrimmedAllowFromEntries,
@@ -32,7 +33,7 @@ export const imessageSetupWizard = createIMessageSetupWizardProxy(
export const imessageConfigAdapter = createScopedChannelConfigAdapter<ResolvedIMessageAccount>({
sectionKey: IMESSAGE_CHANNEL,
listAccountIds: listIMessageAccountIds,
resolveAccount: (cfg, accountId) => resolveIMessageAccount({ cfg, accountId }),
resolveAccount: adaptScopedAccountAccessor(resolveIMessageAccount),
defaultAccountId: resolveDefaultIMessageAccountId,
clearBaseFields: ["cliPath", "dbPath", "service", "region", "name"],
resolveAllowFrom: (account: ResolvedIMessageAccount) => account.config.allowFrom,

View File

@@ -1,5 +1,6 @@
import { formatNormalizedAllowFromEntries } from "openclaw/plugin-sdk/allow-from";
import {
adaptScopedAccountAccessor,
createScopedChannelConfigAdapter,
createScopedDmSecurityResolver,
} from "openclaw/plugin-sdk/channel-config-helpers";
@@ -64,7 +65,7 @@ const ircConfigAdapter = createScopedChannelConfigAdapter<
>({
sectionKey: "irc",
listAccountIds: listIrcAccountIds,
resolveAccount: (cfg, accountId) => resolveIrcAccount({ cfg, accountId }),
resolveAccount: adaptScopedAccountAccessor(resolveIrcAccount),
defaultAccountId: resolveDefaultIrcAccountId,
clearBaseFields: [
"name",
@@ -237,11 +238,10 @@ export const ircPlugin: ChannelPlugin<ResolvedIrcAccount, IrcProbe> = {
},
directory: createChannelDirectoryAdapter({
listPeers: async (params) =>
listResolvedDirectoryEntriesFromSources({
listResolvedDirectoryEntriesFromSources<ResolvedIrcAccount>({
...params,
kind: "user",
resolveAccount: (cfg, accountId) =>
resolveIrcAccount({ cfg: cfg as CoreConfig, accountId }),
resolveAccount: adaptScopedAccountAccessor(resolveIrcAccount),
resolveSources: (account) => [
account.config.allowFrom ?? [],
account.config.groupAllowFrom ?? [],
@@ -250,11 +250,10 @@ export const ircPlugin: ChannelPlugin<ResolvedIrcAccount, IrcProbe> = {
normalizeId: (entry) => normalizePairingTarget(entry) || null,
}),
listGroups: async (params) => {
const entries = listResolvedDirectoryEntriesFromSources({
const entries = listResolvedDirectoryEntriesFromSources<ResolvedIrcAccount>({
...params,
kind: "group",
resolveAccount: (cfg, accountId) =>
resolveIrcAccount({ cfg: cfg as CoreConfig, accountId }),
resolveAccount: adaptScopedAccountAccessor(resolveIrcAccount),
resolveSources: (account) => [
account.config.channels ?? [],
Object.keys(account.config.groups ?? {}),

View File

@@ -1,4 +1,5 @@
import {
adaptScopedAccountAccessor,
createScopedChannelConfigAdapter,
createScopedDmSecurityResolver,
} from "openclaw/plugin-sdk/channel-config-helpers";
@@ -77,7 +78,7 @@ const matrixConfigAdapter = createScopedChannelConfigAdapter<
>({
sectionKey: "matrix",
listAccountIds: listMatrixAccountIds,
resolveAccount: (cfg, accountId) => resolveMatrixAccount({ cfg, accountId }),
resolveAccount: adaptScopedAccountAccessor(resolveMatrixAccount),
resolveAccessorAccount: ({ cfg, accountId }) =>
resolveMatrixAccountConfig({ cfg: cfg as CoreConfig, accountId }),
defaultAccountId: resolveDefaultMatrixAccountId,
@@ -238,9 +239,10 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
resolveToolPolicy: resolveMatrixGroupToolPolicy,
},
threading: {
resolveReplyToMode: createScopedAccountReplyToModeResolver({
resolveAccount: (cfg, accountId) =>
resolveMatrixAccountConfig({ cfg: cfg as CoreConfig, accountId }),
resolveReplyToMode: createScopedAccountReplyToModeResolver<
ReturnType<typeof resolveMatrixAccountConfig>
>({
resolveAccount: adaptScopedAccountAccessor(resolveMatrixAccountConfig),
resolveReplyToMode: (account) => account.replyToMode,
}),
buildToolContext: ({ context, hasRepliedRef }) => {
@@ -277,11 +279,10 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
},
directory: createChannelDirectoryAdapter({
listPeers: async (params) => {
const entries = listResolvedDirectoryEntriesFromSources({
const entries = listResolvedDirectoryEntriesFromSources<ResolvedMatrixAccount>({
...params,
kind: "user",
resolveAccount: (cfg, accountId) =>
resolveMatrixAccount({ cfg: cfg as CoreConfig, accountId }),
resolveAccount: adaptScopedAccountAccessor(resolveMatrixAccount),
resolveSources: (account) => [
account.config.dm?.allowFrom ?? [],
account.config.groupAllowFrom ?? [],
@@ -306,11 +307,10 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
});
},
listGroups: async (params) =>
listResolvedDirectoryEntriesFromSources({
listResolvedDirectoryEntriesFromSources<ResolvedMatrixAccount>({
...params,
kind: "group",
resolveAccount: (cfg, accountId) =>
resolveMatrixAccount({ cfg: cfg as CoreConfig, accountId }),
resolveAccount: adaptScopedAccountAccessor(resolveMatrixAccount),
resolveSources: (account) => [
Object.keys(account.config.groups ?? account.config.rooms ?? {}),
],

View File

@@ -1,6 +1,7 @@
import { formatNormalizedAllowFromEntries } from "openclaw/plugin-sdk/allow-from";
import { createMessageToolButtonsSchema } from "openclaw/plugin-sdk/channel-actions";
import {
adaptScopedAccountAccessor,
createScopedChannelConfigAdapter,
createScopedDmSecurityResolver,
} from "openclaw/plugin-sdk/channel-config-helpers";
@@ -266,7 +267,7 @@ function formatAllowEntry(entry: string): string {
const mattermostConfigAdapter = createScopedChannelConfigAdapter<ResolvedMattermostAccount>({
sectionKey: "mattermost",
listAccountIds: listMattermostAccountIds,
resolveAccount: (cfg, accountId) => resolveMattermostAccount({ cfg, accountId }),
resolveAccount: adaptScopedAccountAccessor(resolveMattermostAccount),
defaultAccountId: resolveDefaultMattermostAccountId,
clearBaseFields: ["botToken", "baseUrl", "name"],
resolveAllowFrom: (account: ResolvedMattermostAccount) => account.config.allowFrom,

View File

@@ -1,5 +1,6 @@
import { formatAllowFromLowercase } from "openclaw/plugin-sdk/allow-from";
import {
adaptScopedAccountAccessor,
createScopedChannelConfigAdapter,
createScopedDmSecurityResolver,
} from "openclaw/plugin-sdk/channel-config-helpers";
@@ -59,7 +60,7 @@ const nextcloudTalkConfigAdapter = createScopedChannelConfigAdapter<
>({
sectionKey: "nextcloud-talk",
listAccountIds: listNextcloudTalkAccountIds,
resolveAccount: (cfg, accountId) => resolveNextcloudTalkAccount({ cfg, accountId }),
resolveAccount: adaptScopedAccountAccessor(resolveNextcloudTalkAccount),
defaultAccountId: resolveDefaultNextcloudTalkAccountId,
clearBaseFields: ["botSecret", "botSecretFile", "baseUrl", "name"],
resolveAllowFrom: (account) => account.config.allowFrom,

View File

@@ -1,4 +1,5 @@
import {
adaptScopedAccountAccessor,
createScopedChannelConfigAdapter,
createScopedDmSecurityResolver,
} from "openclaw/plugin-sdk/channel-config-helpers";
@@ -32,7 +33,7 @@ export const signalSetupWizard = createSignalSetupWizardProxy(
export const signalConfigAdapter = createScopedChannelConfigAdapter<ResolvedSignalAccount>({
sectionKey: SIGNAL_CHANNEL,
listAccountIds: listSignalAccountIds,
resolveAccount: (cfg, accountId) => resolveSignalAccount({ cfg, accountId }),
resolveAccount: adaptScopedAccountAccessor(resolveSignalAccount),
defaultAccountId: resolveDefaultSignalAccountId,
clearBaseFields: ["account", "httpUrl", "httpHost", "httpPort", "cliPath", "name"],
resolveAllowFrom: (account: ResolvedSignalAccount) => account.config.allowFrom,

View File

@@ -3,7 +3,10 @@ import {
createAccountScopedAllowlistNameResolver,
createFlatAllowlistOverrideResolver,
} from "openclaw/plugin-sdk/allowlist-config-edit";
import { createScopedDmSecurityResolver } from "openclaw/plugin-sdk/channel-config-helpers";
import {
adaptScopedAccountAccessor,
createScopedDmSecurityResolver,
} from "openclaw/plugin-sdk/channel-config-helpers";
import {
createPairingPrefixStripper,
createTextPairingAdapter,
@@ -389,8 +392,8 @@ export const slackPlugin: ChannelPlugin<ResolvedSlackAccount> = {
resolveToolPolicy: resolveSlackGroupToolPolicy,
},
threading: {
resolveReplyToMode: createScopedAccountReplyToModeResolver({
resolveAccount: (cfg, accountId) => resolveSlackAccount({ cfg, accountId }),
resolveReplyToMode: createScopedAccountReplyToModeResolver<ResolvedSlackAccount>({
resolveAccount: adaptScopedAccountAccessor(resolveSlackAccount),
resolveReplyToMode: (account, chatType) => resolveSlackReplyToMode(account, chatType),
}),
allowExplicitReplyTagsWhenOff: false,

View File

@@ -1,3 +1,4 @@
import { adaptScopedAccountAccessor } from "openclaw/plugin-sdk/channel-config-helpers";
import {
noteChannelLookupFailure,
noteChannelLookupSummary,
@@ -12,7 +13,11 @@ import type {
ChannelSetupWizardAllowFromEntry,
} from "openclaw/plugin-sdk/setup";
import { formatDocsLink } from "openclaw/plugin-sdk/setup-tools";
import { resolveDefaultSlackAccountId, resolveSlackAccount } from "./accounts.js";
import {
resolveDefaultSlackAccountId,
resolveSlackAccount,
type ResolvedSlackAccount,
} from "./accounts.js";
import { resolveSlackChannelAllowlist } from "./resolve-channels.js";
import { resolveSlackUserAllowlist } from "./resolve-users.js";
import { createSlackSetupWizardBase } from "./setup-core.js";
@@ -58,13 +63,13 @@ async function promptSlackAllowFrom(params: {
normalizeId: (id) => id.toUpperCase(),
});
return await promptLegacyChannelAllowFromForAccount({
return await promptLegacyChannelAllowFromForAccount<ResolvedSlackAccount>({
cfg: params.cfg,
channel,
prompter: params.prompter,
accountId: params.accountId,
defaultAccountId: resolveDefaultSlackAccountId(params.cfg),
resolveAccount: (cfg, accountId) => resolveSlackAccount({ cfg, accountId }),
resolveAccount: adaptScopedAccountAccessor(resolveSlackAccount),
resolveExisting: (_account, cfg) =>
cfg.channels?.slack?.allowFrom ?? cfg.channels?.slack?.dm?.allowFrom ?? [],
resolveToken: (account) => account.userToken ?? account.botToken ?? "",

View File

@@ -1,5 +1,8 @@
import { formatAllowFromLowercase } from "openclaw/plugin-sdk/allow-from";
import { createScopedChannelConfigAdapter } from "openclaw/plugin-sdk/channel-config-helpers";
import {
adaptScopedAccountAccessor,
createScopedChannelConfigAdapter,
} from "openclaw/plugin-sdk/channel-config-helpers";
import { createChannelPluginBase } from "openclaw/plugin-sdk/core";
import {
formatDocsLink,
@@ -145,8 +148,8 @@ export function isSlackSetupAccountConfigured(account: ResolvedSlackAccount): bo
export const slackConfigAdapter = createScopedChannelConfigAdapter<ResolvedSlackAccount>({
sectionKey: SLACK_CHANNEL,
listAccountIds: listSlackAccountIds,
resolveAccount: (cfg, accountId) => resolveSlackAccount({ cfg, accountId }),
inspectAccount: (cfg, accountId) => inspectSlackAccount({ cfg, accountId }),
resolveAccount: adaptScopedAccountAccessor(resolveSlackAccount),
inspectAccount: adaptScopedAccountAccessor(inspectSlackAccount),
defaultAccountId: resolveDefaultSlackAccountId,
clearBaseFields: ["botToken", "appToken", "name"],
resolveAllowFrom: (account: ResolvedSlackAccount) => account.dm?.allowFrom,

View File

@@ -1,5 +1,8 @@
import { formatAllowFromLowercase } from "openclaw/plugin-sdk/allow-from";
import { createScopedChannelConfigAdapter } from "openclaw/plugin-sdk/channel-config-helpers";
import {
adaptScopedAccountAccessor,
createScopedChannelConfigAdapter,
} from "openclaw/plugin-sdk/channel-config-helpers";
import { createChannelPluginBase } from "openclaw/plugin-sdk/core";
import {
buildChannelConfigSchema,
@@ -56,8 +59,8 @@ export function formatDuplicateTelegramTokenReason(params: {
export const telegramConfigAdapter = createScopedChannelConfigAdapter<ResolvedTelegramAccount>({
sectionKey: TELEGRAM_CHANNEL,
listAccountIds: listTelegramAccountIds,
resolveAccount: (cfg, accountId) => resolveTelegramAccount({ cfg, accountId }),
inspectAccount: (cfg, accountId) => inspectTelegramAccount({ cfg, accountId }),
resolveAccount: adaptScopedAccountAccessor(resolveTelegramAccount),
inspectAccount: adaptScopedAccountAccessor(inspectTelegramAccount),
defaultAccountId: resolveDefaultTelegramAccountId,
clearBaseFields: ["botToken", "tokenFile", "name"],
resolveAllowFrom: (account: ResolvedTelegramAccount) => account.config.allowFrom,

View File

@@ -1,15 +1,16 @@
import { adaptScopedAccountAccessor } from "openclaw/plugin-sdk/channel-config-helpers";
import {
listResolvedDirectoryGroupEntriesFromMapKeys,
listResolvedDirectoryUserEntriesFromAllowFrom,
type DirectoryConfigParams,
} from "openclaw/plugin-sdk/directory-runtime";
import { resolveWhatsAppAccount } from "./accounts.js";
import { resolveWhatsAppAccount, type ResolvedWhatsAppAccount } from "./accounts.js";
import { isWhatsAppGroupJid, normalizeWhatsAppTarget } from "./normalize.js";
export async function listWhatsAppDirectoryPeersFromConfig(params: DirectoryConfigParams) {
return listResolvedDirectoryUserEntriesFromAllowFrom({
return listResolvedDirectoryUserEntriesFromAllowFrom<ResolvedWhatsAppAccount>({
...params,
resolveAccount: (cfg, accountId) => resolveWhatsAppAccount({ cfg, accountId }),
resolveAccount: adaptScopedAccountAccessor(resolveWhatsAppAccount),
resolveAllowFrom: (account) => account.allowFrom,
normalizeId: (entry) => {
const normalized = normalizeWhatsAppTarget(entry);
@@ -22,9 +23,9 @@ export async function listWhatsAppDirectoryPeersFromConfig(params: DirectoryConf
}
export async function listWhatsAppDirectoryGroupsFromConfig(params: DirectoryConfigParams) {
return listResolvedDirectoryGroupEntriesFromMapKeys({
return listResolvedDirectoryGroupEntriesFromMapKeys<ResolvedWhatsAppAccount>({
...params,
resolveAccount: (cfg, accountId) => resolveWhatsAppAccount({ cfg, accountId }),
resolveAccount: adaptScopedAccountAccessor(resolveWhatsAppAccount),
resolveGroups: (account) => account.groups,
});
}

View File

@@ -1,4 +1,5 @@
import {
adaptScopedAccountAccessor,
createScopedChannelConfigAdapter,
createScopedDmSecurityResolver,
} from "openclaw/plugin-sdk/channel-config-helpers";
@@ -36,7 +37,7 @@ export const whatsappSetupWizardProxy = createWhatsAppSetupWizardProxy(
const whatsappConfigAdapter = createScopedChannelConfigAdapter<ResolvedWhatsAppAccount>({
sectionKey: WHATSAPP_CHANNEL,
listAccountIds: listWhatsAppAccountIds,
resolveAccount: (cfg, accountId) => resolveWhatsAppAccount({ cfg, accountId }),
resolveAccount: adaptScopedAccountAccessor(resolveWhatsAppAccount),
defaultAccountId: resolveDefaultWhatsAppAccountId,
clearBaseFields: [],
allowTopLevel: false,

View File

@@ -1,4 +1,5 @@
import {
adaptScopedAccountAccessor,
createScopedChannelConfigAdapter,
createScopedDmSecurityResolver,
mapAllowFromEntries,
@@ -68,7 +69,7 @@ const loadZaloChannelRuntime = createLazyRuntimeModule(() => import("./channel.r
const zaloConfigAdapter = createScopedChannelConfigAdapter<ResolvedZaloAccount>({
sectionKey: "zalo",
listAccountIds: listZaloAccountIds,
resolveAccount: (cfg, accountId) => resolveZaloAccount({ cfg, accountId }),
resolveAccount: adaptScopedAccountAccessor(resolveZaloAccount),
defaultAccountId: resolveDefaultZaloAccountId,
clearBaseFields: ["botToken", "tokenFile", "name"],
resolveAllowFrom: (account: ResolvedZaloAccount) => account.config.allowFrom,
@@ -167,9 +168,9 @@ export const zaloPlugin: ChannelPlugin<ResolvedZaloAccount> = {
},
directory: createChannelDirectoryAdapter({
listPeers: async (params) =>
listResolvedDirectoryUserEntriesFromAllowFrom({
listResolvedDirectoryUserEntriesFromAllowFrom<ResolvedZaloAccount>({
...params,
resolveAccount: (cfg, accountId) => resolveZaloAccount({ cfg, accountId }),
resolveAccount: adaptScopedAccountAccessor(resolveZaloAccount),
resolveAllowFrom: (account) => account.config.allowFrom,
normalizeId: (entry) => entry.trim().replace(/^(zalo|zl):/i, ""),
}),

View File

@@ -1,4 +1,7 @@
import { createScopedChannelConfigAdapter } from "openclaw/plugin-sdk/channel-config-helpers";
import {
adaptScopedAccountAccessor,
createScopedChannelConfigAdapter,
} from "openclaw/plugin-sdk/channel-config-helpers";
import type { ChannelPlugin } from "../runtime-api.js";
import { buildChannelConfigSchema, formatAllowFromLowercase } from "../runtime-api.js";
import {
@@ -25,7 +28,7 @@ export const zalouserMeta = {
const zalouserConfigAdapter = createScopedChannelConfigAdapter<ResolvedZalouserAccount>({
sectionKey: "zalouser",
listAccountIds: listZalouserAccountIds,
resolveAccount: (cfg, accountId) => resolveZalouserAccountSync({ cfg, accountId }),
resolveAccount: adaptScopedAccountAccessor(resolveZalouserAccountSync),
defaultAccountId: resolveDefaultZalouserAccountId,
clearBaseFields: [
"profile",

View File

@@ -1,5 +1,6 @@
import { describe, expect, it } from "vitest";
import {
adaptScopedAccountAccessor,
createScopedAccountConfigAccessors,
createScopedChannelConfigAdapter,
createScopedChannelConfigBase,
@@ -37,6 +38,33 @@ describe("resolveOptionalConfigString", () => {
});
});
describe("adaptScopedAccountAccessor", () => {
it("binds positional callback args into the shared account context object", () => {
const accessor = adaptScopedAccountAccessor(({ cfg, accountId }) => ({
channel: cfg.channels?.demo,
accountId: accountId ?? "default",
}));
expect(
accessor(
{
channels: {
demo: {
enabled: true,
},
},
},
"alt",
),
).toEqual({
channel: {
enabled: true,
},
accountId: "alt",
});
});
});
describe("createScopedAccountConfigAccessors", () => {
it("maps allowFrom and defaultTo from the resolved account", () => {
const accessors = createScopedAccountConfigAccessors({

View File

@@ -57,6 +57,13 @@ export function resolveOptionalConfigString(
return normalized || undefined;
}
/** Adapt `{ cfg, accountId }` accessors to callback sites that pass positional args. */
export function adaptScopedAccountAccessor<Result, Config extends OpenClawConfig = OpenClawConfig>(
accessor: (params: { cfg: Config; accountId?: string | null }) => Result,
): (cfg: Config, accountId?: string | null) => Result {
return (cfg, accountId) => accessor({ cfg, accountId });
}
/** Build the shared allowlist/default target adapter surface for account-scoped channel configs. */
export function createScopedAccountConfigAccessors<
ResolvedAccount,