Fix Discord session routing continuity (enable lastRoute for groups)\n\nPreviously, 'updateLastRoute' was only enabled for Direct Messages.\nThis meant that group/channel sessions did not update their routing\nmetadata (last channel/to/accountId) in 'session-meta.json'.\n\nIf the bot restarted or a proactive cron job tried to send a message\nto a group session using 'sessions_send' without an explicit 'to' field,\nit would fail because 'lastRoute' was missing or stale.\n\nFix: Enable 'updateLastRoute' for all Discord messages (Group + DM),\nensuring the session store always has the latest valid routing target.

This commit is contained in:
Rain
2026-02-16 20:58:30 +08:00
committed by Peter Steinberger
parent dbe2ab6f62
commit b90d7625e5
2 changed files with 76 additions and 8 deletions

View File

@@ -557,14 +557,12 @@ export async function processDiscordMessage(ctx: DiscordMessagePreflightContext)
storePath,
sessionKey: ctxPayload.SessionKey ?? route.sessionKey,
ctx: ctxPayload,
updateLastRoute: isDirectMessage
? {
sessionKey: route.mainSessionKey,
channel: "discord",
to: `user:${author.id}`,
accountId: route.accountId,
}
: undefined,
updateLastRoute: {
sessionKey: ctxPayload.SessionKey ?? route.sessionKey,
channel: "discord",
to: effectiveTo,
accountId: route.accountId,
},
onRecordError: (err) => {
logVerbose(`discord: failed updating session meta: ${String(err)}`);
},

View File

@@ -0,0 +1,70 @@
import { describe, it, expect } from "vitest";
import { buildAgentSessionKey } from "./resolve-route.js";
describe("Discord Session Key Continuity", () => {
const agentId = "main";
const channel = "discord";
const accountId = "default";
it("generates distinct keys for DM vs Channel (dmScope=main)", () => {
// Scenario: Default config (dmScope=main)
const dmKey = buildAgentSessionKey({
agentId,
channel,
accountId,
peer: { kind: "direct", id: "user123" },
dmScope: "main",
});
const groupKey = buildAgentSessionKey({
agentId,
channel,
accountId,
peer: { kind: "channel", id: "channel456" },
dmScope: "main",
});
expect(dmKey).toBe("agent:main:main");
expect(groupKey).toBe("agent:main:discord:channel:channel456");
expect(dmKey).not.toBe(groupKey);
});
it("generates distinct keys for DM vs Channel (dmScope=per-peer)", () => {
// Scenario: Multi-user bot config
const dmKey = buildAgentSessionKey({
agentId,
channel,
accountId,
peer: { kind: "direct", id: "user123" },
dmScope: "per-peer",
});
const groupKey = buildAgentSessionKey({
agentId,
channel,
accountId,
peer: { kind: "channel", id: "channel456" },
dmScope: "per-peer",
});
expect(dmKey).toBe("agent:main:direct:user123");
expect(groupKey).toBe("agent:main:discord:channel:channel456");
expect(dmKey).not.toBe(groupKey);
});
it("handles empty/invalid IDs safely without collision", () => {
// If ID is missing, does it collide?
const missingIdKey = buildAgentSessionKey({
agentId,
channel,
accountId,
peer: { kind: "channel", id: "" }, // Empty string
dmScope: "main",
});
expect(missingIdKey).toContain("unknown");
// Should still be distinct from main
expect(missingIdKey).not.toBe("agent:main:main");
});
});