From a3961d098af23e6e96bb43302f090141fe183c05 Mon Sep 17 00:00:00 2001 From: Tak Hoffman <781889+Takhoffman@users.noreply.github.com> Date: Fri, 27 Mar 2026 21:30:24 -0500 Subject: [PATCH] fix(regression): preserve mattermost reaction channel routing --- .../mattermost/src/mattermost/monitor.test.ts | 24 +++++++++++++++++++ .../mattermost/src/mattermost/monitor.ts | 9 ++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/extensions/mattermost/src/mattermost/monitor.test.ts b/extensions/mattermost/src/mattermost/monitor.test.ts index c36011d9589..eafa12294d6 100644 --- a/extensions/mattermost/src/mattermost/monitor.test.ts +++ b/extensions/mattermost/src/mattermost/monitor.test.ts @@ -3,6 +3,7 @@ import type { OpenClawConfig } from "../../runtime-api.js"; import { resolveMattermostAccount } from "./accounts.js"; import { evaluateMattermostMentionGate, + resolveMattermostReactionChannelId, resolveMattermostEffectiveReplyToId, resolveMattermostReplyRootId, resolveMattermostThreadSessionContext, @@ -274,3 +275,26 @@ describe("resolveMattermostThreadSessionContext", () => { }); }); }); + +describe("resolveMattermostReactionChannelId", () => { + it("prefers broadcast channel_id when present", () => { + expect( + resolveMattermostReactionChannelId({ + broadcast: { channel_id: "chan-broadcast" }, + data: { channel_id: "chan-data" }, + }), + ).toBe("chan-broadcast"); + }); + + it("falls back to data.channel_id when broadcast channel_id is missing", () => { + expect( + resolveMattermostReactionChannelId({ + data: { channel_id: "chan-data" }, + }), + ).toBe("chan-data"); + }); + + it("returns undefined when neither payload location includes channel_id", () => { + expect(resolveMattermostReactionChannelId({})).toBeUndefined(); + }); +}); diff --git a/extensions/mattermost/src/mattermost/monitor.ts b/extensions/mattermost/src/mattermost/monitor.ts index 256d41fde5d..af83ef4144f 100644 --- a/extensions/mattermost/src/mattermost/monitor.ts +++ b/extensions/mattermost/src/mattermost/monitor.ts @@ -212,6 +212,13 @@ export function resolveMattermostThreadSessionContext(params: { parentSessionKey: threadKeys.parentSessionKey, }; } + +export function resolveMattermostReactionChannelId( + payload: Pick, +): string | undefined { + return payload.broadcast?.channel_id?.trim() || payload.data?.channel_id?.trim() || undefined; +} + function buildMattermostAttachmentPlaceholder(mediaList: MattermostMediaInfo[]): string { if (mediaList.length === 0) { return ""; @@ -1492,7 +1499,7 @@ export async function monitorMattermostProvider(opts: MonitorMattermostOpts = {} const senderName = senderInfo?.username?.trim() || userId; // Resolve the channel from broadcast or post to route to the correct agent session - const channelId = payload.broadcast?.channel_id; + const channelId = resolveMattermostReactionChannelId(payload); if (!channelId) { // Without a channel id we cannot verify DM/group policies — drop to be safe logVerboseMessage(