From 85c75f6573088d795aa2e48335d21746884e98ba Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 7 Apr 2026 09:39:56 +0100 Subject: [PATCH] refactor: dedupe auto-reply string helpers --- src/auto-reply/reply/block-streaming.ts | 15 +++------------ src/auto-reply/reply/groups.ts | 19 ++++--------------- src/auto-reply/reply/inbound-dedupe.ts | 7 +++---- src/auto-reply/reply/origin-routing.ts | 8 ++------ src/auto-reply/reply/reply-threading.ts | 11 ++--------- src/channels/registry.ts | 10 +++------- src/gateway/server-mobile-nodes.ts | 15 ++++++--------- 7 files changed, 23 insertions(+), 62 deletions(-) diff --git a/src/auto-reply/reply/block-streaming.ts b/src/auto-reply/reply/block-streaming.ts index 4142216d77d..686c0fa724d 100644 --- a/src/auto-reply/reply/block-streaming.ts +++ b/src/auto-reply/reply/block-streaming.ts @@ -11,23 +11,14 @@ const DEFAULT_BLOCK_STREAM_MIN = 800; const DEFAULT_BLOCK_STREAM_MAX = 1200; const DEFAULT_BLOCK_STREAM_COALESCE_IDLE_MS = 1000; -function normalizeChunkProvider(provider?: string): TextChunkProvider | undefined { - if (!provider) { - return undefined; - } - const normalized = normalizeMessageChannel(provider); - if (!normalized) { - return undefined; - } - return normalized as TextChunkProvider; -} - function resolveProviderChunkContext( cfg: OpenClawConfig | undefined, provider?: string, accountId?: string | null, ) { - const providerKey = normalizeChunkProvider(provider); + const providerKey = provider + ? (normalizeMessageChannel(provider) as TextChunkProvider | undefined) + : undefined; const providerId = providerKey ? normalizeChannelId(providerKey) : null; const providerChunkLimit = providerId ? getChannelPlugin(providerId)?.outbound?.textChunkLimit diff --git a/src/auto-reply/reply/groups.ts b/src/auto-reply/reply/groups.ts index 5e1e61616bb..e596dd9201d 100644 --- a/src/auto-reply/reply/groups.ts +++ b/src/auto-reply/reply/groups.ts @@ -14,21 +14,8 @@ function loadGroupsRuntime() { return groupsRuntimePromise; } -function resolveGroupId(raw: string | undefined | null): string | undefined { - const trimmed = (raw ?? "").trim(); - return extractExplicitGroupId(trimmed) ?? (trimmed || undefined); -} - -function resolveLooseChannelId(raw?: string | null): string | null { - const normalized = normalizeOptionalString(raw)?.toLowerCase(); - if (!normalized) { - return null; - } - return normalized; -} - async function resolveRuntimeChannelId(raw?: string | null): Promise { - const normalized = resolveLooseChannelId(raw); + const normalized = normalizeOptionalString(raw)?.toLowerCase(); if (!normalized) { return null; } @@ -58,7 +45,9 @@ export async function resolveGroupRequireMention(params: { if (!channel) { return true; } - const groupId = groupResolution?.id ?? resolveGroupId(ctx.From); + const rawGroupId = (ctx.From ?? "").trim(); + const groupId = + groupResolution?.id ?? extractExplicitGroupId(rawGroupId) ?? (rawGroupId || undefined); const groupChannel = normalizeOptionalString(ctx.GroupChannel) ?? normalizeOptionalString(ctx.GroupSubject); const groupSpace = normalizeOptionalString(ctx.GroupSpace); diff --git a/src/auto-reply/reply/inbound-dedupe.ts b/src/auto-reply/reply/inbound-dedupe.ts index f297fcd2150..a68e59984f0 100644 --- a/src/auto-reply/reply/inbound-dedupe.ts +++ b/src/auto-reply/reply/inbound-dedupe.ts @@ -18,9 +18,6 @@ const inboundDedupeCache: DedupeCache = resolveGlobalDedupeCache(INBOUND_DEDUPE_ maxSize: DEFAULT_INBOUND_DEDUPE_MAX, }); -const normalizeProvider = (value?: string | null) => - normalizeOptionalString(value)?.toLowerCase() || ""; - const resolveInboundPeerId = (ctx: MsgContext) => ctx.OriginatingTo ?? ctx.To ?? ctx.From ?? ctx.SessionKey; @@ -44,7 +41,9 @@ function resolveInboundDedupeSessionScope(ctx: MsgContext): string { } export function buildInboundDedupeKey(ctx: MsgContext): string | null { - const provider = normalizeProvider(ctx.OriginatingChannel ?? ctx.Provider ?? ctx.Surface); + const provider = + normalizeOptionalString(ctx.OriginatingChannel ?? ctx.Provider ?? ctx.Surface)?.toLowerCase() || + ""; const messageId = normalizeOptionalString(ctx.MessageSid); if (!provider || !messageId) { return null; diff --git a/src/auto-reply/reply/origin-routing.ts b/src/auto-reply/reply/origin-routing.ts index b06af9607ea..55c1937d1cf 100644 --- a/src/auto-reply/reply/origin-routing.ts +++ b/src/auto-reply/reply/origin-routing.ts @@ -1,17 +1,13 @@ import { normalizeOptionalString } from "../../shared/string-coerce.js"; import type { OriginatingChannelType } from "../templating.js"; -function normalizeProviderValue(value?: string): string | undefined { - const normalized = normalizeOptionalString(value)?.toLowerCase(); - return normalized || undefined; -} - export function resolveOriginMessageProvider(params: { originatingChannel?: OriginatingChannelType; provider?: string; }): string | undefined { return ( - normalizeProviderValue(params.originatingChannel) ?? normalizeProviderValue(params.provider) + normalizeOptionalString(params.originatingChannel)?.toLowerCase() ?? + normalizeOptionalString(params.provider)?.toLowerCase() ); } diff --git a/src/auto-reply/reply/reply-threading.ts b/src/auto-reply/reply/reply-threading.ts index 47ad90326d5..e4957256a5a 100644 --- a/src/auto-reply/reply/reply-threading.ts +++ b/src/auto-reply/reply/reply-threading.ts @@ -23,20 +23,13 @@ function normalizeReplyToModeChatType( : undefined; } -function resolveReplyToModeChannelKey(channel?: OriginatingChannelType): string | undefined { - const normalized = normalizePluginChannelId(channel); - if (normalized) { - return normalized; - } - return normalizeOptionalString(channel)?.toLowerCase(); -} - export function resolveConfiguredReplyToMode( cfg: OpenClawConfig, channel?: OriginatingChannelType, chatType?: string | null, ): ReplyToMode { - const provider = resolveReplyToModeChannelKey(channel); + const provider = + normalizePluginChannelId(channel) ?? normalizeOptionalString(channel)?.toLowerCase(); if (!provider) { return "all"; } diff --git a/src/channels/registry.ts b/src/channels/registry.ts index c592ead089a..7ee9b557dcb 100644 --- a/src/channels/registry.ts +++ b/src/channels/registry.ts @@ -45,18 +45,14 @@ function findRegisteredChannelPluginEntry( function findRegisteredChannelPluginEntryById( id: string, ): RegisteredChannelPluginEntry | undefined { - const normalizedId = normalizeChannelKey(id); + const normalizedId = normalizeOptionalString(id)?.toLowerCase(); if (!normalizedId) { return undefined; } return listRegisteredChannelPluginEntries().find( - (entry) => normalizeChannelKey(entry.plugin.id) === normalizedId, + (entry) => normalizeOptionalString(entry.plugin.id)?.toLowerCase() === normalizedId, ); } - -const normalizeChannelKey = (raw?: string | null): string | undefined => { - return normalizeOptionalString(raw)?.toLowerCase(); -}; export { CHAT_CHANNEL_ALIASES, getChatChannelMeta, @@ -76,7 +72,7 @@ export function normalizeChannelId(raw?: string | null): ChatChannelId | null { // Keep this light: we do not import channel plugins here (those are "heavy" and can pull in // monitors, web login, etc). The plugin registry must be initialized first. export function normalizeAnyChannelId(raw?: string | null): ChannelId | null { - const key = normalizeChannelKey(raw); + const key = normalizeOptionalString(raw)?.toLowerCase(); if (!key) { return null; } diff --git a/src/gateway/server-mobile-nodes.ts b/src/gateway/server-mobile-nodes.ts index 2352b340ec1..38187b1d332 100644 --- a/src/gateway/server-mobile-nodes.ts +++ b/src/gateway/server-mobile-nodes.ts @@ -1,15 +1,12 @@ import { normalizeOptionalString } from "../shared/string-coerce.js"; import type { NodeRegistry } from "./node-registry.js"; -const isMobilePlatform = (platform: unknown): boolean => { - const p = normalizeOptionalString(platform)?.toLowerCase() ?? ""; - if (!p) { - return false; - } - return p.startsWith("ios") || p.startsWith("ipados") || p.startsWith("android"); -}; - export function hasConnectedMobileNode(registry: NodeRegistry): boolean { const connected = registry.listConnected(); - return connected.some((n) => isMobilePlatform(n.platform)); + return connected.some((n) => { + const platform = normalizeOptionalString(n.platform)?.toLowerCase() ?? ""; + return ( + platform.startsWith("ios") || platform.startsWith("ipados") || platform.startsWith("android") + ); + }); }