Skip to content

Commit 02f8fb7

Browse files
committed
fix(channels): clear canonical stale routes
1 parent 8477a67 commit 02f8fb7

4 files changed

Lines changed: 37 additions & 1 deletion

File tree

src/auto-reply/reply/session-delivery.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ export function maybeRetireLegacyMainDeliveryRoute(params: {
220220
return undefined;
221221
}
222222
if (
223+
legacyMain.route === undefined &&
223224
legacyMain.deliveryContext === undefined &&
224225
legacyMain.lastChannel === undefined &&
225226
legacyMain.lastTo === undefined &&
@@ -232,6 +233,7 @@ export function maybeRetireLegacyMainDeliveryRoute(params: {
232233
key: canonicalMainSessionKey,
233234
entry: {
234235
...legacyMain,
236+
route: undefined,
235237
deliveryContext: undefined,
236238
lastChannel: undefined,
237239
lastTo: undefined,

src/auto-reply/reply/session.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3485,6 +3485,7 @@ describe("initSessionState dmScope delivery migration", () => {
34853485
SessionEntry
34863486
>;
34873487
expect(persisted["agent:main:main"]?.sessionId).toBe("legacy-main");
3488+
expect(persisted["agent:main:main"]?.route).toBeUndefined();
34883489
expect(persisted["agent:main:main"]?.deliveryContext).toBeUndefined();
34893490
expect(persisted["agent:main:main"]?.lastChannel).toBeUndefined();
34903491
expect(persisted["agent:main:main"]?.lastTo).toBeUndefined();
@@ -3556,6 +3557,12 @@ describe("initSessionState internal channel routing preservation", () => {
35563557
accountId: "default",
35573558
threadId: "stale-root",
35583559
},
3560+
route: {
3561+
channel: "mattermost",
3562+
accountId: "default",
3563+
target: { to: "channel:CHAN1" },
3564+
thread: { id: "stale-root", kind: "thread", source: "session" },
3565+
},
35593566
origin: {
35603567
provider: "mattermost",
35613568
to: "channel:CHAN1",
@@ -3586,6 +3593,11 @@ describe("initSessionState internal channel routing preservation", () => {
35863593
to: "channel:CHAN1",
35873594
accountId: "default",
35883595
});
3596+
expect(result.sessionEntry.route).toEqual({
3597+
channel: "mattermost",
3598+
accountId: "default",
3599+
target: { to: "channel:CHAN1" },
3600+
});
35893601
expect(result.sessionEntry.origin).toEqual({
35903602
provider: "mattermost",
35913603
to: "channel:CHAN1",
@@ -3602,6 +3614,11 @@ describe("initSessionState internal channel routing preservation", () => {
36023614
to: "channel:CHAN1",
36033615
accountId: "default",
36043616
});
3617+
expect(persisted[sessionKey]?.route).toEqual({
3618+
channel: "mattermost",
3619+
accountId: "default",
3620+
target: { to: "channel:CHAN1" },
3621+
});
36053622
expect(persisted[sessionKey]?.origin).toEqual({
36063623
provider: "mattermost",
36073624
to: "channel:CHAN1",

src/auto-reply/reply/session.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,10 @@ import {
5151
normalizeOptionalLowercaseString,
5252
normalizeOptionalString,
5353
} from "../../shared/string-coerce.js";
54-
import { normalizeSessionDeliveryFields } from "../../utils/delivery-context.shared.js";
54+
import {
55+
normalizeDeliveryChannelRoute,
56+
normalizeSessionDeliveryFields,
57+
} from "../../utils/delivery-context.shared.js";
5558
import { resolveCommandTurnTargetSessionKey } from "../command-turn-context.js";
5659
import { normalizeCommandBody } from "../commands-registry.js";
5760
import type { MsgContext, TemplateContext } from "../templating.js";
@@ -79,6 +82,15 @@ function loadSessionArchiveRuntime() {
7982
return sessionArchiveRuntimeLoader.load();
8083
}
8184

85+
function stripThreadFromSessionRoute(route: SessionEntry["route"]): SessionEntry["route"] {
86+
const normalized = normalizeDeliveryChannelRoute(route);
87+
if (!normalized?.thread) {
88+
return normalized;
89+
}
90+
const { thread: _drop, ...withoutThread } = normalized;
91+
return Object.keys(withoutThread).length > 0 ? withoutThread : undefined;
92+
}
93+
8294
type ReplySessionEndReason = Extract<
8395
PluginHookSessionEndReason,
8496
"new" | "reset" | "idle" | "daily" | "unknown"
@@ -606,6 +618,7 @@ export async function initSessionState(params: {
606618
(isThread ? baseEntry?.lastThreadId : undefined));
607619
const deliveryFields = isSystemEvent
608620
? normalizeSessionDeliveryFields({
621+
route: isThread ? baseEntry?.route : stripThreadFromSessionRoute(baseEntry?.route),
609622
channel: baseEntry?.channel,
610623
lastChannel: baseEntry?.lastChannel,
611624
lastTo: baseEntry?.lastTo,
@@ -680,6 +693,7 @@ export async function initSessionState(params: {
680693
space: baseEntry?.space,
681694
groupActivation: entry?.groupActivation,
682695
groupActivationNeedsSystemIntro: entry?.groupActivationNeedsSystemIntro,
696+
route: deliveryFields.route,
683697
deliveryContext: deliveryFields.deliveryContext,
684698
// Track originating channel for subagent announce routing.
685699
lastChannel,
@@ -700,6 +714,7 @@ export async function initSessionState(params: {
700714
if (isSystemEvent && !isThread) {
701715
sessionEntry = {
702716
...sessionEntry,
717+
route: stripThreadFromSessionRoute(sessionEntry.route),
703718
lastThreadId: undefined,
704719
deliveryContext: stripThreadIdFromDeliveryContext(sessionEntry.deliveryContext),
705720
origin: stripThreadIdFromOrigin(sessionEntry.origin),

src/gateway/server-methods/chat.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import {
4747
saveMediaBuffer,
4848
} from "../../media/store.js";
4949
import { createChannelMessageReplyPipeline } from "../../plugin-sdk/channel-message.js";
50+
import type { ChannelRouteRef } from "../../plugin-sdk/channel-route.js";
5051
import { isPluginOwnedSessionBindingRecord } from "../../plugins/conversation-binding.js";
5152
import { getGlobalHookRunner } from "../../plugins/hook-runner-global.js";
5253
import { normalizeInputProvenance, type InputProvenance } from "../../sessions/input-provenance.js";
@@ -278,6 +279,7 @@ const CHANNEL_AGNOSTIC_SESSION_SCOPES = new Set([
278279
const CHANNEL_SCOPED_SESSION_SHAPES = new Set(["direct", "dm", "group", "channel"]);
279280

280281
type ChatSendDeliveryEntry = {
282+
route?: ChannelRouteRef;
281283
deliveryContext?: {
282284
channel?: string;
283285
to?: string;

0 commit comments

Comments
 (0)