fix(discord): preserve DM lastRoute user target

This commit is contained in:
Shakker
2026-02-17 13:47:16 +00:00
parent 7884d65687
commit b0d4c9b721
2 changed files with 89 additions and 3 deletions

View File

@@ -71,6 +71,22 @@ beforeEach(() => {
resolveStorePath.mockReturnValue("/tmp/openclaw-discord-process-test-sessions.json");
});
function getLastRouteUpdate():
| { sessionKey?: string; channel?: string; to?: string; accountId?: string }
| undefined {
const params = recordInboundSession.mock.calls.at(-1)?.[0] as
| {
updateLastRoute?: {
sessionKey?: string;
channel?: string;
to?: string;
accountId?: string;
};
}
| undefined;
return params?.updateLastRoute;
}
describe("processDiscordMessage ack reactions", () => {
it("skips ack reactions for group-mentions when mentions are not required", async () => {
const ctx = await createBaseContext({
@@ -170,3 +186,70 @@ describe("processDiscordMessage ack reactions", () => {
expect(emojis).toContain("✅");
});
});
describe("processDiscordMessage session routing", () => {
it("stores DM lastRoute with user target for direct-session continuity", async () => {
const ctx = await createBaseContext({
data: { guild: null },
channelInfo: null,
channelName: undefined,
isGuildMessage: false,
isDirectMessage: true,
isGroupDm: false,
shouldRequireMention: false,
canDetectMention: false,
effectiveWasMentioned: false,
displayChannelSlug: "",
guildInfo: null,
guildSlug: "",
message: {
id: "m1",
channelId: "dm1",
timestamp: new Date().toISOString(),
attachments: [],
},
messageChannelId: "dm1",
baseSessionKey: "agent:main:discord:direct:u1",
route: {
agentId: "main",
channel: "discord",
accountId: "default",
sessionKey: "agent:main:discord:direct:u1",
mainSessionKey: "agent:main:main",
},
});
// oxlint-disable-next-line typescript/no-explicit-any
await processDiscordMessage(ctx as any);
expect(getLastRouteUpdate()).toEqual({
sessionKey: "agent:main:discord:direct:u1",
channel: "discord",
to: "user:U1",
accountId: "default",
});
});
it("stores group lastRoute with channel target", async () => {
const ctx = await createBaseContext({
baseSessionKey: "agent:main:discord:channel:c1",
route: {
agentId: "main",
channel: "discord",
accountId: "default",
sessionKey: "agent:main:discord:channel:c1",
mainSessionKey: "agent:main:main",
},
});
// oxlint-disable-next-line typescript/no-explicit-any
await processDiscordMessage(ctx as any);
expect(getLastRouteUpdate()).toEqual({
sessionKey: "agent:main:discord:channel:c1",
channel: "discord",
to: "channel:c1",
accountId: "default",
});
});
});

View File

@@ -503,6 +503,8 @@ export async function processDiscordMessage(ctx: DiscordMessagePreflightContext)
runtime.error?.(danger("discord: missing reply target"));
return;
}
// Keep DM routes user-addressed so follow-up sends resolve direct session keys.
const lastRouteTo = isDirectMessage ? `user:${author.id}` : effectiveTo;
const inboundHistory =
shouldIncludeChannelHistory && historyLimit > 0
@@ -553,15 +555,16 @@ export async function processDiscordMessage(ctx: DiscordMessagePreflightContext)
OriginatingChannel: "discord" as const,
OriginatingTo: autoThreadContext?.OriginatingTo ?? replyTarget,
});
const persistedSessionKey = ctxPayload.SessionKey ?? route.sessionKey;
await recordInboundSession({
storePath,
sessionKey: ctxPayload.SessionKey ?? route.sessionKey,
sessionKey: persistedSessionKey,
ctx: ctxPayload,
updateLastRoute: {
sessionKey: ctxPayload.SessionKey ?? route.sessionKey,
sessionKey: persistedSessionKey,
channel: "discord",
to: effectiveTo,
to: lastRouteTo,
accountId: route.accountId,
},
onRecordError: (err) => {