fix(channels): pin dm main route owners

This commit is contained in:
Vincent Koc
2026-05-01 04:38:23 -07:00
parent 1076d6c124
commit f6a1d70080
5 changed files with 167 additions and 1 deletions

View File

@@ -190,6 +190,44 @@ describe("matrix monitor handler pairing account scope", () => {
}
});
it("pins direct-message main route updates to the configured owner", async () => {
const { handler, recordInboundSession } = createMatrixHandlerTestHarness({
cfg: {
channels: {
matrix: {
dm: { allowFrom: ["@owner:example.org"] },
},
},
},
dmPolicy: "allowlist",
allowFrom: ["@owner:example.org"],
allowFromResolvedEntries: [{ input: "@owner:example.org", id: "@owner:example.org" }],
isDirectMessage: true,
});
await handler(
"!dm:example.org",
createMatrixTextMessageEvent({
eventId: "$owner-dm",
sender: "@owner:example.org",
body: "hello",
}),
);
expect(recordInboundSession).toHaveBeenCalledWith(
expect.objectContaining({
updateLastRoute: expect.objectContaining({
channel: "matrix",
to: "room:!dm:example.org",
mainDmOwnerPin: expect.objectContaining({
ownerRecipient: "@owner:example.org",
senderRecipient: "@owner:example.org",
}),
}),
}),
);
});
it("sends pairing reminders for pending requests with cooldown", async () => {
vi.useFakeTimers();
vi.setSystemTime(new Date("2026-03-01T10:00:00.000Z"));

View File

@@ -5,6 +5,7 @@ import {
} from "openclaw/plugin-sdk/context-visibility-runtime";
import { hasFinalInboundReplyDispatch } from "openclaw/plugin-sdk/inbound-reply-dispatch";
import type { GetReplyOptions } from "openclaw/plugin-sdk/reply-runtime";
import { resolvePinnedMainDmOwnerFromAllowlist } from "openclaw/plugin-sdk/security-runtime";
import {
loadSessionStore,
resolveSessionStoreEntry,
@@ -38,7 +39,7 @@ import { MATRIX_OPENCLAW_FINALIZED_PREVIEW_KEY } from "../send/types.js";
import { resolveMatrixStoredSessionMeta } from "../session-store-metadata.js";
import { resolveMatrixMonitorAccessState } from "./access-state.js";
import { resolveMatrixAckReactionConfig } from "./ack-config.js";
import { resolveMatrixAllowListMatch } from "./allowlist.js";
import { normalizeMatrixUserId, resolveMatrixAllowListMatch } from "./allowlist.js";
import {
resolveMatrixMonitorLiveUserAllowlist,
type MatrixResolvedAllowlistEntry,
@@ -1828,6 +1829,13 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam
onReplyStart: typingCallbacks.onReplyStart,
onIdle: typingCallbacks.onIdle,
});
const pinnedMainDmOwner = isDirectMessage
? resolvePinnedMainDmOwnerFromAllowlist({
dmScope: cfg.session?.dmScope,
allowFrom: liveDmAllowFrom,
normalizeEntry: normalizeMatrixUserId,
})
: null;
const turnResult = await core.channel.turn.run({
channel: "matrix",
@@ -1855,6 +1863,23 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam
channel: "matrix",
to: `room:${roomId}`,
accountId: _route.accountId,
mainDmOwnerPin: pinnedMainDmOwner
? {
ownerRecipient: pinnedMainDmOwner,
senderRecipient: normalizeMatrixUserId(senderId),
onSkip: ({
ownerRecipient,
senderRecipient,
}: {
ownerRecipient: string;
senderRecipient: string;
}) => {
logVerboseMessage(
`matrix: skip main-session last route for ${senderRecipient} (pinned owner ${ownerRecipient})`,
);
},
}
: undefined,
}
: undefined,
onRecordError: (err) => {