From 6de04567382f6dfa09e5045be88e98ca04293f7f Mon Sep 17 00:00:00 2001 From: Gustavo Madeira Santana Date: Mon, 9 Mar 2026 04:28:42 -0400 Subject: [PATCH] Matrix: extract inbound route resolution --- .../matrix/src/matrix/monitor/handler.ts | 55 +++---------- extensions/matrix/src/matrix/monitor/route.ts | 80 +++++++++++++++++++ 2 files changed, 90 insertions(+), 45 deletions(-) create mode 100644 extensions/matrix/src/matrix/monitor/route.ts diff --git a/extensions/matrix/src/matrix/monitor/handler.ts b/extensions/matrix/src/matrix/monitor/handler.ts index 9586a76736d..07b20d95b48 100644 --- a/extensions/matrix/src/matrix/monitor/handler.ts +++ b/extensions/matrix/src/matrix/monitor/handler.ts @@ -3,11 +3,8 @@ import { createTypingCallbacks, ensureConfiguredAcpRouteReady, formatAllowlistMatchMeta, - getSessionBindingService, logInboundDrop, logTypingFailure, - resolveAgentIdFromSessionKey, - resolveConfiguredAcpRoute, resolveControlCommandGate, type PluginRuntime, type ReplyPayload, @@ -32,6 +29,7 @@ import { resolveMentions } from "./mentions.js"; import { handleInboundMatrixReaction } from "./reaction-events.js"; import { deliverMatrixReplies } from "./replies.js"; import { resolveMatrixRoomConfig } from "./rooms.js"; +import { resolveMatrixInboundRoute } from "./route.js"; import { createMatrixThreadContextResolver } from "./thread-context.js"; import { resolveMatrixThreadRootId, resolveMatrixThreadTarget } from "./threads.js"; import type { MatrixRawEvent, RoomMessageEventContent } from "./types.js"; @@ -512,38 +510,18 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam ? await resolveThreadContext({ roomId, threadRootId }) : undefined; - const baseRoute = core.channel.routing.resolveAgentRoute({ + const { route, configuredBinding } = resolveMatrixInboundRoute({ cfg, - channel: "matrix", accountId, - peer: { - kind: isDirectMessage ? "direct" : "channel", - id: isDirectMessage ? senderId : roomId, - }, + roomId, + senderId, + isDirectMessage, + messageId, + threadRootId, + eventTs: eventTs ?? undefined, + resolveAgentRoute: core.channel.routing.resolveAgentRoute, }); - const bindingConversationId = - threadRootId && threadRootId !== messageId ? threadRootId : roomId; - const bindingParentConversationId = bindingConversationId === roomId ? undefined : roomId; - const sessionBindingService = getSessionBindingService(); - const runtimeBinding = sessionBindingService.resolveByConversation({ - channel: "matrix", - accountId, - conversationId: bindingConversationId, - parentConversationId: bindingParentConversationId, - }); - const configuredRoute = - runtimeBinding == null - ? resolveConfiguredAcpRoute({ - cfg, - route: baseRoute, - channel: "matrix", - accountId, - conversationId: bindingConversationId, - parentConversationId: bindingParentConversationId, - }) - : null; - const configuredBinding = configuredRoute?.configuredBinding ?? null; - if (!runtimeBinding && configuredBinding) { + if (configuredBinding) { const ensured = await ensureConfiguredAcpRouteReady({ cfg, configuredBinding, @@ -558,19 +536,6 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam return; } } - const boundSessionKey = runtimeBinding?.targetSessionKey?.trim(); - const route = - runtimeBinding && boundSessionKey - ? { - ...baseRoute, - sessionKey: boundSessionKey, - agentId: resolveAgentIdFromSessionKey(boundSessionKey) || baseRoute.agentId, - matchedBy: "binding.channel" as const, - } - : (configuredRoute?.route ?? baseRoute); - if (runtimeBinding) { - sessionBindingService.touch(runtimeBinding.bindingId, eventTs); - } const envelopeFrom = isDirectMessage ? senderName : (roomName ?? roomId); const textWithId = `${bodyText}\n[matrix event id: ${messageId} room: ${roomId}]`; const storePath = core.channel.session.resolveStorePath(cfg.session?.store, { diff --git a/extensions/matrix/src/matrix/monitor/route.ts b/extensions/matrix/src/matrix/monitor/route.ts new file mode 100644 index 00000000000..11eb5077ecc --- /dev/null +++ b/extensions/matrix/src/matrix/monitor/route.ts @@ -0,0 +1,80 @@ +import { + getSessionBindingService, + resolveAgentIdFromSessionKey, + resolveConfiguredAcpRoute, + type PluginRuntime, +} from "openclaw/plugin-sdk/matrix"; +import type { CoreConfig } from "../../types.js"; + +type MatrixResolvedRoute = ReturnType; + +export function resolveMatrixInboundRoute(params: { + cfg: CoreConfig; + accountId: string; + roomId: string; + senderId: string; + isDirectMessage: boolean; + messageId: string; + threadRootId?: string; + eventTs?: number; + resolveAgentRoute: PluginRuntime["channel"]["routing"]["resolveAgentRoute"]; +}): { + route: MatrixResolvedRoute; + configuredBinding: ReturnType["configuredBinding"]; +} { + const baseRoute = params.resolveAgentRoute({ + cfg: params.cfg, + channel: "matrix", + accountId: params.accountId, + peer: { + kind: params.isDirectMessage ? "direct" : "channel", + id: params.isDirectMessage ? params.senderId : params.roomId, + }, + }); + const bindingConversationId = + params.threadRootId && params.threadRootId !== params.messageId + ? params.threadRootId + : params.roomId; + const bindingParentConversationId = + bindingConversationId === params.roomId ? undefined : params.roomId; + const sessionBindingService = getSessionBindingService(); + const runtimeBinding = sessionBindingService.resolveByConversation({ + channel: "matrix", + accountId: params.accountId, + conversationId: bindingConversationId, + parentConversationId: bindingParentConversationId, + }); + const boundSessionKey = runtimeBinding?.targetSessionKey?.trim(); + + if (runtimeBinding) { + sessionBindingService.touch(runtimeBinding.bindingId, params.eventTs); + } + if (runtimeBinding && boundSessionKey) { + return { + route: { + ...baseRoute, + sessionKey: boundSessionKey, + agentId: resolveAgentIdFromSessionKey(boundSessionKey) || baseRoute.agentId, + matchedBy: "binding.channel", + }, + configuredBinding: null, + }; + } + + const configuredRoute = + runtimeBinding == null + ? resolveConfiguredAcpRoute({ + cfg: params.cfg, + route: baseRoute, + channel: "matrix", + accountId: params.accountId, + conversationId: bindingConversationId, + parentConversationId: bindingParentConversationId, + }) + : null; + + return { + route: configuredRoute?.route ?? baseRoute, + configuredBinding: configuredRoute?.configuredBinding ?? null, + }; +}