diff --git a/src/agents/tools/sessions-send-helpers.test.ts b/src/agents/tools/sessions-send-helpers.test.ts index b08c6d89e71..b66ce99b42d 100644 --- a/src/agents/tools/sessions-send-helpers.test.ts +++ b/src/agents/tools/sessions-send-helpers.test.ts @@ -51,6 +51,28 @@ describe("resolveAnnounceTargetFromKey", () => { }, }, }, + { + pluginId: "matrix", + source: "test", + plugin: { + id: "matrix", + meta: { + id: "matrix", + label: "Matrix", + selectionLabel: "Matrix", + docsPath: "/channels/matrix", + blurb: "Matrix test stub.", + }, + capabilities: { chatTypes: ["direct", "channel", "thread"] }, + messaging: { + resolveSessionTarget: ({ id }: { id: string }) => `channel:${id}`, + }, + config: { + listAccountIds: () => ["default"], + resolveAccount: () => ({}), + }, + }, + }, { pluginId: "telegram", source: "test", @@ -107,4 +129,16 @@ describe("resolveAnnounceTargetFromKey", () => { threadId: "1699999999.0001", }); }); + + it("preserves colon-delimited matrix ids for channel and thread targets", () => { + expect( + resolveAnnounceTargetFromKey( + "agent:main:matrix:channel:!room:example.org:thread:$AbC123:example.org", + ), + ).toEqual({ + channel: "matrix", + to: "channel:!room:example.org", + threadId: "$AbC123:example.org", + }); + }); }); diff --git a/src/agents/tools/sessions-send-helpers.ts b/src/agents/tools/sessions-send-helpers.ts index cb104204e3c..db2d24293aa 100644 --- a/src/agents/tools/sessions-send-helpers.ts +++ b/src/agents/tools/sessions-send-helpers.ts @@ -4,6 +4,7 @@ import { } from "../../channels/plugins/index.js"; import { normalizeChannelId as normalizeChatChannelId } from "../../channels/registry.js"; import type { OpenClawConfig } from "../../config/config.js"; +import { parseSessionThreadInfo } from "../../config/sessions/delivery-info.js"; const ANNOUNCE_SKIP_TOKEN = "ANNOUNCE_SKIP"; const REPLY_SKIP_TOKEN = "REPLY_SKIP"; @@ -28,20 +29,9 @@ export function resolveAnnounceTargetFromKey(sessionKey: string): AnnounceTarget return null; } - // Extract topic/thread ID from rest (supports both :topic: and :thread:) - // Telegram uses :topic:, other platforms use :thread: - let threadId: string | undefined; const restJoined = rest.join(":"); - const topicMatch = restJoined.match(/:topic:([^:]+)$/); - const threadMatch = restJoined.match(/:thread:([^:]+)$/); - const match = topicMatch || threadMatch; - - if (match) { - threadId = match[1]; // Keep as string to match AgentCommandOpts.threadId - } - - // Remove :topic:N or :thread:N suffix from ID for target - const id = match ? restJoined.replace(/:(topic|thread):[^:]+$/, "") : restJoined.trim(); + const { baseSessionKey, threadId } = parseSessionThreadInfo(restJoined); + const id = (baseSessionKey ?? restJoined).trim(); if (!id) { return null; diff --git a/src/config/sessions/delivery-info.test.ts b/src/config/sessions/delivery-info.test.ts index 9a435c38a7a..88c01c5a0d1 100644 --- a/src/config/sessions/delivery-info.test.ts +++ b/src/config/sessions/delivery-info.test.ts @@ -44,6 +44,14 @@ describe("extractDeliveryInfo", () => { baseSessionKey: "agent:main:slack:channel:C1", threadId: "123.456", }); + expect( + parseSessionThreadInfo( + "agent:main:matrix:channel:!room:example.org:thread:$AbC123:example.org", + ), + ).toEqual({ + baseSessionKey: "agent:main:matrix:channel:!room:example.org", + threadId: "$AbC123:example.org", + }); expect(parseSessionThreadInfo("agent:main:telegram:dm:user-1")).toEqual({ baseSessionKey: "agent:main:telegram:dm:user-1", threadId: undefined,