Skip to content

Commit a332c26

Browse files
committed
fix(queue): preserve queued platform message ids in collect drains
Keep the latest queued platform message id when collect-mode followups synthesize a combined deferred turn. Fixes #36212
1 parent 3b6bcbf commit a332c26

2 files changed

Lines changed: 67 additions & 0 deletions

File tree

src/auto-reply/reply/queue.collect.test.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,50 @@ describe("followup queue collect routing", () => {
9797
expect(calls[0]?.originatingTo).toBe("channel:A");
9898
});
9999

100+
it("preserves the latest queued message id on collected followups", async () => {
101+
const key = `test-collect-message-id-${Date.now()}`;
102+
const calls: FollowupRun[] = [];
103+
const done = createDeferred<void>();
104+
const runFollowup = async (run: FollowupRun) => {
105+
calls.push(run);
106+
done.resolve();
107+
};
108+
const settings: QueueSettings = {
109+
mode: "collect",
110+
debounceMs: 0,
111+
cap: 50,
112+
dropPolicy: "summarize",
113+
};
114+
115+
enqueueFollowupRun(
116+
key,
117+
createRun({
118+
prompt: "first",
119+
messageId: "platform-msg-1",
120+
originatingChannel: "feishu",
121+
originatingTo: "chat:123",
122+
}),
123+
settings,
124+
);
125+
enqueueFollowupRun(
126+
key,
127+
createRun({
128+
prompt: "second",
129+
messageId: "platform-msg-2",
130+
originatingChannel: "feishu",
131+
originatingTo: "chat:123",
132+
}),
133+
settings,
134+
);
135+
136+
scheduleFollowupDrain(key, runFollowup);
137+
await done.promise;
138+
139+
expect(calls).toHaveLength(1);
140+
expect(calls[0]?.prompt).toContain("[Queued messages while agent was busy]");
141+
expect(calls[0]?.messageId).toBe("platform-msg-2");
142+
});
143+
100144
it("collects compatible items after one cross-channel drain", async () => {
101145
const key = `test-collect-after-cross-${Date.now()}`;
102146
const calls: FollowupRun[] = [];

src/auto-reply/reply/queue/drain.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ type OriginRoutingMetadata = Pick<
5454
"originatingChannel" | "originatingTo" | "originatingAccountId" | "originatingThreadId"
5555
>;
5656

57+
type OriginMessageMetadata = Pick<FollowupRun, "messageId" | "originatingReplyToId">;
58+
5759
function resolveOriginRoutingMetadata(items: FollowupRun[]): OriginRoutingMetadata {
5860
const metadata: OriginRoutingMetadata = {};
5961
for (const item of items) {
@@ -86,6 +88,23 @@ function resolveOriginRoutingMetadata(items: FollowupRun[]): OriginRoutingMetada
8688
return metadata;
8789
}
8890

91+
function resolveOriginMessageMetadata(items: FollowupRun[]): OriginMessageMetadata {
92+
const metadata: OriginMessageMetadata = {};
93+
for (let index = items.length - 1; index >= 0; index -= 1) {
94+
const item = items[index];
95+
if (!metadata.messageId && item.messageId) {
96+
metadata.messageId = item.messageId;
97+
}
98+
if (!metadata.originatingReplyToId && item.originatingReplyToId) {
99+
metadata.originatingReplyToId = item.originatingReplyToId;
100+
}
101+
if (metadata.messageId && metadata.originatingReplyToId) {
102+
break;
103+
}
104+
}
105+
return metadata;
106+
}
107+
89108
// Keep this key aligned with the fields that affect per-message authorization or
90109
// exec-context propagation in collect-mode batching. Display-only sender fields
91110
// stay out of the key so profile/name drift does not force conservative splits.
@@ -474,6 +493,7 @@ export function scheduleFollowupDrain(
474493
}
475494

476495
const routing = resolveOriginRoutingMetadata(groupItems);
496+
const messageMetadata = resolveOriginMessageMetadata(groupItems);
477497
const prompt = buildCollectPrompt({
478498
title: "[Queued messages while agent was busy]",
479499
items: groupItems,
@@ -486,6 +506,7 @@ export function scheduleFollowupDrain(
486506
run,
487507
enqueuedAt: Date.now(),
488508
...routing,
509+
...messageMetadata,
489510
...collectRuntimeMetadata(groupItems),
490511
...collectQueuedImages(groupItems),
491512
});
@@ -525,10 +546,12 @@ export function scheduleFollowupDrain(
525546
prompt: summaryPrompt,
526547
run,
527548
enqueuedAt: Date.now(),
549+
messageId: item.messageId,
528550
originatingChannel: item.originatingChannel,
529551
originatingTo: item.originatingTo,
530552
originatingAccountId: item.originatingAccountId,
531553
originatingThreadId: item.originatingThreadId,
554+
originatingReplyToId: item.originatingReplyToId,
532555
...collectSummaryRuntimeMetadata([item]),
533556
...collectQueuedImages([item]),
534557
});

0 commit comments

Comments
 (0)