From 9529d2e161c793045372050af562070cd833d289 Mon Sep 17 00:00:00 2001 From: Gustavo Madeira Santana Date: Sun, 5 Apr 2026 14:59:15 -0400 Subject: [PATCH] fix(matrix): use DM session key for flat notices --- .../matrix/src/matrix/monitor/handler.test.ts | 59 +++++++++++++++++++ .../matrix/src/matrix/monitor/handler.ts | 4 +- 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/extensions/matrix/src/matrix/monitor/handler.test.ts b/extensions/matrix/src/matrix/monitor/handler.test.ts index 05d5f457928..d652840cdb6 100644 --- a/extensions/matrix/src/matrix/monitor/handler.test.ts +++ b/extensions/matrix/src/matrix/monitor/handler.test.ts @@ -747,6 +747,65 @@ describe("matrix monitor handler pairing account scope", () => { } }); + it("checks flat DM collision notices against the current DM session key", async () => { + const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "matrix-dm-flat-notice-")); + const storePath = path.join(tempDir, "sessions.json"); + const sendNotice = vi.fn(async () => "$notice"); + + try { + await recordSessionMetaFromInbound({ + storePath, + sessionKey: "agent:ops:matrix:direct:@user:example.org", + ctx: { + SessionKey: "agent:ops:matrix:direct:@user:example.org", + AccountId: "ops", + ChatType: "direct", + Provider: "matrix", + Surface: "matrix", + From: "matrix:@user:example.org", + To: "room:!other:example.org", + NativeChannelId: "!other:example.org", + OriginatingChannel: "matrix", + OriginatingTo: "room:!other:example.org", + }, + }); + + const { handler } = createMatrixHandlerTestHarness({ + isDirectMessage: true, + resolveStorePath: () => storePath, + resolveAgentRoute: () => ({ + agentId: "ops", + channel: "matrix", + accountId: "ops", + sessionKey: "agent:ops:matrix:direct:@user:example.org", + mainSessionKey: "agent:ops:main", + matchedBy: "binding.account" as const, + }), + client: { + sendMessage: sendNotice, + }, + }); + + await handler( + "!dm:example.org", + createMatrixTextMessageEvent({ + eventId: "$dm-flat-1", + body: "follow up", + }), + ); + + expect(sendNotice).toHaveBeenCalledWith( + "!dm:example.org", + expect.objectContaining({ + msgtype: "m.notice", + body: expect.stringContaining("channels.matrix.dm.sessionScope"), + }), + ); + } finally { + fs.rmSync(tempDir, { recursive: true, force: true }); + } + }); + it("checks threaded DM collision notices against the parent DM session", async () => { const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "matrix-dm-thread-notice-")); const storePath = path.join(tempDir, "sessions.json"); diff --git a/extensions/matrix/src/matrix/monitor/handler.ts b/extensions/matrix/src/matrix/monitor/handler.ts index 15866cb7674..190bef919fd 100644 --- a/extensions/matrix/src/matrix/monitor/handler.ts +++ b/extensions/matrix/src/matrix/monitor/handler.ts @@ -1104,7 +1104,9 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam storePath, sessionKey: _route.sessionKey, }); - const sharedDmNoticeSessionKey = _route.mainSessionKey || _route.sessionKey; + const sharedDmNoticeSessionKey = threadTarget + ? _route.mainSessionKey || _route.sessionKey + : _route.sessionKey; const sharedDmContextNotice = isDirectMessage ? hasExplicitSessionBinding ? null