From 6647d02846d3ec854fa8648382b724d8500a4021 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 7 Mar 2026 23:09:05 +0000 Subject: [PATCH] refactor: share dock config adapter helper scaffolding --- extensions/nostr/src/channel.ts | 5 +-- src/channels/dock.test.ts | 22 +++++++++ src/channels/dock.ts | 80 +++++++++++++++------------------ src/plugin-sdk/nostr.ts | 1 + 4 files changed, 61 insertions(+), 47 deletions(-) diff --git a/extensions/nostr/src/channel.ts b/extensions/nostr/src/channel.ts index 1757d14c43d..20de320a3d1 100644 --- a/extensions/nostr/src/channel.ts +++ b/extensions/nostr/src/channel.ts @@ -4,6 +4,7 @@ import { createDefaultChannelRuntimeState, DEFAULT_ACCOUNT_ID, formatPairingApproveHint, + mapAllowFromEntries, type ChannelPlugin, } from "openclaw/plugin-sdk/nostr"; import type { NostrProfile } from "./config-schema.js"; @@ -56,9 +57,7 @@ export const nostrPlugin: ChannelPlugin = { publicKey: account.publicKey, }), resolveAllowFrom: ({ cfg, accountId }) => - (resolveNostrAccount({ cfg, accountId }).config.allowFrom ?? []).map((entry) => - String(entry), - ), + mapAllowFromEntries(resolveNostrAccount({ cfg, accountId }).config.allowFrom), formatAllowFrom: ({ allowFrom }) => allowFrom .map((entry) => String(entry).trim()) diff --git a/src/channels/dock.test.ts b/src/channels/dock.test.ts index e3d00824c3b..99e3947be9b 100644 --- a/src/channels/dock.test.ts +++ b/src/channels/dock.test.ts @@ -169,4 +169,26 @@ describe("channels dock", () => { }), ).toBe(false); }); + + it("dock config readers coerce numeric allowFrom/defaultTo entries through shared helpers", () => { + const telegramDock = getChannelDock("telegram"); + const signalDock = getChannelDock("signal"); + const cfg = { + channels: { + telegram: { + allowFrom: [12345], + defaultTo: 67890, + }, + signal: { + allowFrom: [14155550100], + defaultTo: 42, + }, + }, + } as unknown as OpenClawConfig; + + expect(telegramDock?.config?.resolveAllowFrom?.({ cfg })).toEqual(["12345"]); + expect(telegramDock?.config?.resolveDefaultTo?.({ cfg })).toBe("67890"); + expect(signalDock?.config?.resolveAllowFrom?.({ cfg })).toEqual(["14155550100"]); + expect(signalDock?.config?.resolveDefaultTo?.({ cfg })).toBe("42"); + }); }); diff --git a/src/channels/dock.ts b/src/channels/dock.ts index 6f359fd96f0..52965790beb 100644 --- a/src/channels/dock.ts +++ b/src/channels/dock.ts @@ -4,6 +4,12 @@ import { } from "../config/group-policy.js"; import { inspectDiscordAccount } from "../discord/account-inspect.js"; import { + formatAllowFromLowercase, + formatNormalizedAllowFromEntries, +} from "../plugin-sdk/allow-from.js"; +import { + mapAllowFromEntries, + resolveOptionalConfigString, formatTrimmedAllowFromEntries, formatWhatsAppConfigAllowFromEntries, resolveIMessageConfigAllowFrom, @@ -82,18 +88,6 @@ type ChannelDockStreaming = { }; }; -const formatLower = (allowFrom: Array) => - allowFrom - .map((entry) => String(entry).trim()) - .filter(Boolean) - .map((entry) => entry.toLowerCase()); - -const stringifyAllowFrom = (allowFrom: Array) => - allowFrom.map((entry) => String(entry)); - -const trimAllowFromEntries = (allowFrom: Array) => - allowFrom.map((entry) => String(entry).trim()).filter(Boolean); - const DEFAULT_OUTBOUND_TEXT_CHUNK_LIMIT_4000 = { textChunkLimit: 4000 }; const DEFAULT_BLOCK_STREAMING_COALESCE = { @@ -104,12 +98,15 @@ function formatAllowFromWithReplacements( allowFrom: Array, replacements: RegExp[], ): string[] { - return trimAllowFromEntries(allowFrom).map((entry) => { - let normalized = entry; - for (const replacement of replacements) { - normalized = normalized.replace(replacement, ""); - } - return normalized.toLowerCase(); + return formatNormalizedAllowFromEntries({ + allowFrom, + normalizeEntry: (entry) => { + let normalized = entry; + for (const replacement of replacements) { + normalized = normalized.replace(replacement, ""); + } + return normalized.toLowerCase(); + }, }); } @@ -249,15 +246,14 @@ const DOCKS: Record = { outbound: DEFAULT_OUTBOUND_TEXT_CHUNK_LIMIT_4000, config: { resolveAllowFrom: ({ cfg, accountId }) => - stringifyAllowFrom(inspectTelegramAccount({ cfg, accountId }).config.allowFrom ?? []), + mapAllowFromEntries(inspectTelegramAccount({ cfg, accountId }).config.allowFrom), formatAllowFrom: ({ allowFrom }) => - trimAllowFromEntries(allowFrom) - .map((entry) => entry.replace(/^(telegram|tg):/i, "")) - .map((entry) => entry.toLowerCase()), - resolveDefaultTo: ({ cfg, accountId }) => { - const val = inspectTelegramAccount({ cfg, accountId }).config.defaultTo; - return val != null ? String(val) : undefined; - }, + formatAllowFromLowercase({ + allowFrom, + stripPrefixRe: /^(telegram|tg):/i, + }), + resolveDefaultTo: ({ cfg, accountId }) => + resolveOptionalConfigString(inspectTelegramAccount({ cfg, accountId }).config.defaultTo), }, groups: { resolveRequireMention: resolveTelegramGroupRequireMention, @@ -339,13 +335,11 @@ const DOCKS: Record = { config: { resolveAllowFrom: ({ cfg, accountId }) => { const account = inspectDiscordAccount({ cfg, accountId }); - return (account.config.allowFrom ?? account.config.dm?.allowFrom ?? []).map((entry) => - String(entry), - ); + return mapAllowFromEntries(account.config.allowFrom ?? account.config.dm?.allowFrom); }, formatAllowFrom: ({ allowFrom }) => formatDiscordAllowFrom(allowFrom), resolveDefaultTo: ({ cfg, accountId }) => - inspectDiscordAccount({ cfg, accountId }).config.defaultTo?.trim() || undefined, + resolveOptionalConfigString(inspectDiscordAccount({ cfg, accountId }).config.defaultTo), }, groups: { resolveRequireMention: resolveDiscordGroupRequireMention, @@ -378,7 +372,7 @@ const DOCKS: Record = { resolveAllowFrom: ({ cfg, accountId }) => { const channel = cfg.channels?.irc; const account = resolveCaseInsensitiveAccount(channel?.accounts, accountId); - return (account?.allowFrom ?? channel?.allowFrom ?? []).map((entry) => String(entry)); + return mapAllowFromEntries(account?.allowFrom ?? channel?.allowFrom); }, formatAllowFrom: ({ allowFrom }) => formatAllowFromWithReplacements(allowFrom, [/^irc:/i, /^user:/i]), @@ -440,9 +434,7 @@ const DOCKS: Record = { } | undefined; const account = resolveCaseInsensitiveAccount(channel?.accounts, accountId); - return (account?.dm?.allowFrom ?? channel?.dm?.allowFrom ?? []).map((entry) => - String(entry), - ); + return mapAllowFromEntries(account?.dm?.allowFrom ?? channel?.dm?.allowFrom); }, formatAllowFrom: ({ allowFrom }) => formatAllowFromWithReplacements(allowFrom, [ @@ -481,13 +473,11 @@ const DOCKS: Record = { config: { resolveAllowFrom: ({ cfg, accountId }) => { const account = inspectSlackAccount({ cfg, accountId }); - return (account.config.allowFrom ?? account.dm?.allowFrom ?? []).map((entry) => - String(entry), - ); + return mapAllowFromEntries(account.config.allowFrom ?? account.dm?.allowFrom); }, - formatAllowFrom: ({ allowFrom }) => formatLower(allowFrom), + formatAllowFrom: ({ allowFrom }) => formatAllowFromLowercase({ allowFrom }), resolveDefaultTo: ({ cfg, accountId }) => - inspectSlackAccount({ cfg, accountId }).config.defaultTo?.trim() || undefined, + resolveOptionalConfigString(inspectSlackAccount({ cfg, accountId }).config.defaultTo), }, groups: { resolveRequireMention: resolveSlackGroupRequireMention, @@ -514,13 +504,15 @@ const DOCKS: Record = { streaming: DEFAULT_BLOCK_STREAMING_COALESCE, config: { resolveAllowFrom: ({ cfg, accountId }) => - stringifyAllowFrom(resolveSignalAccount({ cfg, accountId }).config.allowFrom ?? []), + mapAllowFromEntries(resolveSignalAccount({ cfg, accountId }).config.allowFrom), formatAllowFrom: ({ allowFrom }) => - trimAllowFromEntries(allowFrom) - .map((entry) => (entry === "*" ? "*" : normalizeE164(entry.replace(/^signal:/i, "")))) - .filter(Boolean), + formatNormalizedAllowFromEntries({ + allowFrom, + normalizeEntry: (entry) => + entry === "*" ? "*" : normalizeE164(entry.replace(/^signal:/i, "")), + }), resolveDefaultTo: ({ cfg, accountId }) => - resolveSignalAccount({ cfg, accountId }).config.defaultTo?.trim() || undefined, + resolveOptionalConfigString(resolveSignalAccount({ cfg, accountId }).config.defaultTo), }, threading: { buildToolContext: ({ context, hasRepliedRef }) => diff --git a/src/plugin-sdk/nostr.ts b/src/plugin-sdk/nostr.ts index 1eee82f518a..381e5e71a8a 100644 --- a/src/plugin-sdk/nostr.ts +++ b/src/plugin-sdk/nostr.ts @@ -17,3 +17,4 @@ export { createDefaultChannelRuntimeState, } from "./status-helpers.js"; export { createFixedWindowRateLimiter } from "./webhook-memory-guards.js"; +export { mapAllowFromEntries } from "./channel-config-helpers.js";