mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-24 07:31:44 +00:00
fix(matrix): preserve stable DM peer metadata
This commit is contained in:
@@ -778,10 +778,11 @@ describe("matrix monitor handler pairing account scope", () => {
|
||||
ChatType: "direct",
|
||||
Provider: "matrix",
|
||||
Surface: "matrix",
|
||||
From: "matrix:@user:example.org",
|
||||
To: "room:@user:example.org",
|
||||
From: "matrix:@other:example.org",
|
||||
To: "room:@other:example.org",
|
||||
NativeDirectUserId: "@user:example.org",
|
||||
OriginatingChannel: "matrix",
|
||||
OriginatingTo: "room:@user:example.org",
|
||||
OriginatingTo: "room:@other:example.org",
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -1160,6 +1160,7 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam
|
||||
CommandAuthorized: commandAuthorized,
|
||||
CommandSource: "text" as const,
|
||||
NativeChannelId: roomId,
|
||||
NativeDirectUserId: isDirectMessage ? senderId : undefined,
|
||||
OriginatingChannel: "matrix" as const,
|
||||
OriginatingTo: `room:${roomId}`,
|
||||
});
|
||||
|
||||
@@ -48,6 +48,7 @@ type MatrixStoredSessionEntryLike = {
|
||||
from?: unknown;
|
||||
to?: unknown;
|
||||
nativeChannelId?: unknown;
|
||||
nativeDirectUserId?: unknown;
|
||||
accountId?: unknown;
|
||||
chatType?: unknown;
|
||||
};
|
||||
@@ -80,16 +81,18 @@ export function resolveMatrixStoredSessionMeta(entry?: MatrixStoredSessionEntryL
|
||||
originNativeChannelId: entry.origin?.nativeChannelId,
|
||||
originTo: entry.origin?.to,
|
||||
});
|
||||
const directUserId = resolveMatrixDirectUserId({
|
||||
from: trimMaybeString(entry.origin?.from),
|
||||
to:
|
||||
(roomId ? `room:${roomId}` : undefined) ??
|
||||
trimMaybeString(entry.deliveryContext?.to) ??
|
||||
trimMaybeString(entry.lastTo) ??
|
||||
trimMaybeString(entry.origin?.to),
|
||||
chatType:
|
||||
trimMaybeString(entry.origin?.chatType) ?? trimMaybeString(entry.chatType) ?? undefined,
|
||||
});
|
||||
const directUserId =
|
||||
trimMaybeString(entry.origin?.nativeDirectUserId) ??
|
||||
resolveMatrixDirectUserId({
|
||||
from: trimMaybeString(entry.origin?.from),
|
||||
to:
|
||||
(roomId ? `room:${roomId}` : undefined) ??
|
||||
trimMaybeString(entry.deliveryContext?.to) ??
|
||||
trimMaybeString(entry.lastTo) ??
|
||||
trimMaybeString(entry.origin?.to),
|
||||
chatType:
|
||||
trimMaybeString(entry.origin?.chatType) ?? trimMaybeString(entry.chatType) ?? undefined,
|
||||
});
|
||||
if (!channel && !accountId && !roomId && !directUserId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -196,17 +196,18 @@ describe("resolveMatrixOutboundSessionRoute", () => {
|
||||
chatType: "direct",
|
||||
origin: {
|
||||
chatType: "direct",
|
||||
from: "matrix:@alice:example.org",
|
||||
to: "room:@alice:example.org",
|
||||
from: "matrix:@bob:example.org",
|
||||
to: "room:@bob:example.org",
|
||||
nativeChannelId: "!dm:example.org",
|
||||
nativeDirectUserId: "@alice:example.org",
|
||||
accountId: "ops",
|
||||
},
|
||||
deliveryContext: {
|
||||
channel: "matrix",
|
||||
to: "room:@alice:example.org",
|
||||
to: "room:@bob:example.org",
|
||||
accountId: "ops",
|
||||
},
|
||||
lastTo: "room:@alice:example.org",
|
||||
lastTo: "room:@bob:example.org",
|
||||
lastAccountId: "ops",
|
||||
},
|
||||
});
|
||||
@@ -246,6 +247,65 @@ describe("resolveMatrixOutboundSessionRoute", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("does not reuse the canonical DM room for a different Matrix user after latest metadata drift", () => {
|
||||
const storePath = createTempStore({
|
||||
"agent:main:matrix:channel:!dm:example.org": {
|
||||
sessionId: "sess-1",
|
||||
updatedAt: Date.now(),
|
||||
chatType: "direct",
|
||||
origin: {
|
||||
chatType: "direct",
|
||||
from: "matrix:@bob:example.org",
|
||||
to: "room:@bob:example.org",
|
||||
nativeChannelId: "!dm:example.org",
|
||||
nativeDirectUserId: "@alice:example.org",
|
||||
accountId: "ops",
|
||||
},
|
||||
deliveryContext: {
|
||||
channel: "matrix",
|
||||
to: "room:@bob:example.org",
|
||||
accountId: "ops",
|
||||
},
|
||||
lastTo: "room:@bob:example.org",
|
||||
lastAccountId: "ops",
|
||||
},
|
||||
});
|
||||
const cfg = {
|
||||
session: {
|
||||
store: storePath,
|
||||
},
|
||||
channels: {
|
||||
matrix: {
|
||||
dm: {
|
||||
sessionScope: "per-room",
|
||||
},
|
||||
},
|
||||
},
|
||||
} satisfies OpenClawConfig;
|
||||
|
||||
const route = resolveMatrixOutboundSessionRoute({
|
||||
cfg,
|
||||
agentId: "main",
|
||||
accountId: "ops",
|
||||
currentSessionKey: "agent:main:matrix:channel:!dm:example.org",
|
||||
target: "@bob:example.org",
|
||||
resolvedTarget: {
|
||||
to: "@bob:example.org",
|
||||
kind: "user",
|
||||
source: "normalized",
|
||||
},
|
||||
});
|
||||
|
||||
expect(route).toMatchObject({
|
||||
sessionKey: "agent:main:main",
|
||||
baseSessionKey: "agent:main:main",
|
||||
peer: { kind: "direct", id: "@bob:example.org" },
|
||||
chatType: "direct",
|
||||
from: "matrix:@bob:example.org",
|
||||
to: "room:@bob:example.org",
|
||||
});
|
||||
});
|
||||
|
||||
it("uses the effective default Matrix account when accountId is omitted", () => {
|
||||
const storePath = createTempStore({
|
||||
"agent:main:matrix:channel:!dm:example.org": {
|
||||
|
||||
@@ -161,6 +161,8 @@ export type MsgContext = {
|
||||
MessageThreadId?: string | number;
|
||||
/** Platform-native channel/conversation id (e.g. Slack DM channel "D…" id). */
|
||||
NativeChannelId?: string;
|
||||
/** Stable provider-native direct-peer id when a DM room/user mapping must survive later writes. */
|
||||
NativeDirectUserId?: string;
|
||||
/** Telegram forum supergroup marker. */
|
||||
IsForum?: boolean;
|
||||
/** Warning: DM has topics enabled but this message is not in a topic. */
|
||||
|
||||
@@ -35,6 +35,9 @@ const mergeOrigin = (
|
||||
if (next?.nativeChannelId) {
|
||||
merged.nativeChannelId = next.nativeChannelId;
|
||||
}
|
||||
if (next?.nativeDirectUserId) {
|
||||
merged.nativeDirectUserId = next.nativeDirectUserId;
|
||||
}
|
||||
if (next?.accountId) {
|
||||
merged.accountId = next.accountId;
|
||||
}
|
||||
@@ -57,6 +60,7 @@ export function deriveSessionOrigin(ctx: MsgContext): SessionOrigin | undefined
|
||||
const to =
|
||||
(typeof ctx.OriginatingTo === "string" ? ctx.OriginatingTo : ctx.To)?.trim() ?? undefined;
|
||||
const nativeChannelId = ctx.NativeChannelId?.trim();
|
||||
const nativeDirectUserId = ctx.NativeDirectUserId?.trim();
|
||||
const accountId = ctx.AccountId?.trim();
|
||||
const threadId = ctx.MessageThreadId ?? undefined;
|
||||
|
||||
@@ -82,6 +86,9 @@ export function deriveSessionOrigin(ctx: MsgContext): SessionOrigin | undefined
|
||||
if (nativeChannelId) {
|
||||
origin.nativeChannelId = nativeChannelId;
|
||||
}
|
||||
if (nativeDirectUserId) {
|
||||
origin.nativeDirectUserId = nativeDirectUserId;
|
||||
}
|
||||
if (accountId) {
|
||||
origin.accountId = accountId;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ export type SessionOrigin = {
|
||||
from?: string;
|
||||
to?: string;
|
||||
nativeChannelId?: string;
|
||||
nativeDirectUserId?: string;
|
||||
accountId?: string;
|
||||
threadId?: string | number;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user