Skip to content

Commit b32d4c5

Browse files
committed
fix: avoid media completion fallback while announce pending
1 parent fd86ab2 commit b32d4c5

2 files changed

Lines changed: 62 additions & 1 deletion

File tree

src/agents/subagent-announce-delivery.test.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1271,6 +1271,48 @@ describe("deliverSubagentAnnouncement completion delivery", () => {
12711271
);
12721272
});
12731273

1274+
it("does not fallback while generated media announce-agent run is still pending", async () => {
1275+
const callGateway = createGatewayMock({
1276+
runId: "video_generate:task-123:ok",
1277+
status: "accepted",
1278+
acceptedAt: Date.now(),
1279+
});
1280+
const sendMessage = createSendMessageMock();
1281+
const result = await deliverSlackChannelAnnouncement({
1282+
callGateway,
1283+
sendMessage,
1284+
sessionId: "requester-session-channel",
1285+
isActive: false,
1286+
expectsCompletionMessage: true,
1287+
directIdempotencyKey: "announce-channel-media-pending",
1288+
sourceTool: "video_generate",
1289+
internalEvents: [
1290+
{
1291+
type: "task_completion",
1292+
source: "video_generation",
1293+
childSessionKey: "video_generate:task-123",
1294+
childSessionId: "task-123",
1295+
announceType: "video generation task",
1296+
taskLabel: "lobster trailer",
1297+
status: "ok",
1298+
statusLabel: "completed successfully",
1299+
result: "Generated 1 video.\nMEDIA:/tmp/lobster-trailer.mp4",
1300+
mediaUrls: ["/tmp/lobster-trailer.mp4"],
1301+
replyInstruction: "Deliver the generated video through the message tool.",
1302+
},
1303+
],
1304+
});
1305+
1306+
expect(result).toEqual(
1307+
expect.objectContaining({
1308+
delivered: true,
1309+
path: "direct",
1310+
}),
1311+
);
1312+
expect(callGateway).toHaveBeenCalled();
1313+
expect(sendMessage).not.toHaveBeenCalled();
1314+
});
1315+
12741316
it("uses a direct channel fallback when announce-agent returns no visible output", async () => {
12751317
const callGateway = createGatewayMock({
12761318
result: {

src/agents/subagent-announce-delivery.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,14 @@ function hasGatewayAgentMessagingToolDelivery(response: unknown): boolean {
689689
return Boolean(result && hasMessagingToolDeliveryEvidence(result));
690690
}
691691

692+
function isGatewayAgentRunPending(response: unknown): boolean {
693+
if (!response || typeof response !== "object") {
694+
return false;
695+
}
696+
const status = (response as { status?: unknown }).status;
697+
return status === "accepted" || status === "in_flight" || status === "started";
698+
}
699+
692700
function inferCompletionChatType(params: {
693701
requesterSessionKey: string;
694702
targetRequesterSessionKey: string;
@@ -1047,7 +1055,11 @@ async function sendSubagentAnnounceDirectly(params: {
10471055
throw err;
10481056
}
10491057

1050-
if (shouldSendCompletionFallback(directAnnounceResponse, completionFallbackText)) {
1058+
const directAnnounceStillPending = isGatewayAgentRunPending(directAnnounceResponse);
1059+
if (
1060+
!directAnnounceStillPending &&
1061+
shouldSendCompletionFallback(directAnnounceResponse, completionFallbackText)
1062+
) {
10511063
const didFallback = await sendCompletionFallback({
10521064
cfg,
10531065
channel: deliveryTarget.channel,
@@ -1068,6 +1080,13 @@ async function sendSubagentAnnounceDirectly(params: {
10681080
}
10691081
}
10701082

1083+
if (directAnnounceStillPending) {
1084+
return {
1085+
delivered: true,
1086+
path: "direct",
1087+
};
1088+
}
1089+
10711090
if (
10721091
requiresMessageToolDelivery &&
10731092
!hasGatewayAgentMessagingToolDelivery(directAnnounceResponse)

0 commit comments

Comments
 (0)