From d6fbed7904f51e6981c7a58f956bf9a50713ac69 Mon Sep 17 00:00:00 2001 From: lbo728 Date: Fri, 20 Feb 2026 11:25:16 +0900 Subject: [PATCH] fix: prevent whatsapp fallback for webchat sessions Fixes #21444 When connecting via Hub Chat/webchat, the runtime channel was incorrectly defaulting to 'whatsapp' instead of being omitted or set to 'webchat'. Root cause: The channel resolution fallback chain (OriginatingChannel -> Surface -> Provider) would use Provider even for webchat sessions, where Provider may be unrelated (e.g., the user's default configured channel). Changes: - Add explicit webchat detection before falling back to Provider - Skip Provider fallback when Surface is 'webchat' or Provider is 'webchat' - Channel field is now undefined for webchat sessions (no incorrect label) This ensures webchat sessions don't receive WhatsApp-specific formatting hints (no markdown tables, no headers) and fixes the runtime label. --- src/auto-reply/reply/inbound-meta.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/auto-reply/reply/inbound-meta.ts b/src/auto-reply/reply/inbound-meta.ts index 1304f7d54f8..bbcbc5dabac 100644 --- a/src/auto-reply/reply/inbound-meta.ts +++ b/src/auto-reply/reply/inbound-meta.ts @@ -19,10 +19,27 @@ export function buildInboundMetaSystemPrompt(ctx: TemplateContext): string { // Per-message identifiers (message_id, reply_to_id, sender_id) are also excluded here: they change // on every turn and would bust prefix-based prompt caches on local model providers. They are // included in the user-role conversation info block via buildInboundUserContextPrefix() instead. + + // Resolve channel identity: prefer explicit channel, then surface, then provider. + // For webchat/Hub Chat sessions (when Surface is 'webchat' or undefined with no real channel), + // omit the channel field entirely rather than falling back to an unrelated provider. + let channelValue = safeTrim(ctx.OriginatingChannel) ?? safeTrim(ctx.Surface); + if (!channelValue) { + // Only fall back to Provider if it represents a real messaging channel. + // For webchat/internal sessions, ctx.Provider may be unrelated (e.g., the user's configured + // default channel), so skip it to avoid incorrect runtime labels like "channel=whatsapp". + const provider = safeTrim(ctx.Provider); + // Check if provider is "webchat" or if we're in an internal/webchat context + if (provider !== "webchat" && ctx.Surface !== "webchat") { + channelValue = provider; + } + // Otherwise leave channelValue undefined (no channel label) + } + const payload = { schema: "openclaw.inbound_meta.v1", chat_id: safeTrim(ctx.OriginatingTo), - channel: safeTrim(ctx.OriginatingChannel) ?? safeTrim(ctx.Surface) ?? safeTrim(ctx.Provider), + channel: channelValue, provider: safeTrim(ctx.Provider), surface: safeTrim(ctx.Surface), chat_type: chatType ?? (isDirect ? "direct" : undefined),