Skip to content

Commit 1e07aa0

Browse files
committed
fix: deliver compaction.notifyUser notices via routeReply fallback
When compaction.notifyUser is enabled but no active streaming turn callback (onBlockReply) is available, sendCompactionNotice now falls back to routing the notice through the canonical session outbound path (routeReply) instead of silently returning. This fixes the issue where async/preflight compactions (triggered outside of active inbound-driven streaming reply turns) produce no user-visible notice even when notifyUser: true is configured. Fixes #88933
1 parent 61ffd6b commit 1e07aa0

1 file changed

Lines changed: 45 additions & 7 deletions

File tree

src/auto-reply/reply/agent-runner-execution.ts

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,12 @@ import {
109109
} from "./provider-request-error-classifier.js";
110110
import type { FollowupRun } from "./queue.js";
111111
import { createBlockReplyDeliveryHandler } from "./reply-delivery.js";
112+
import type { ReplyDispatchKind } from "./reply-dispatcher.types.js";
112113
import type { ReplyMediaContext } from "./reply-media-paths.js";
113114
import { createReplyMediaContext } from "./reply-media-paths.runtime.js";
114115
import type { ReplyOperation } from "./reply-run-registry.js";
115116
import { isReplyProfilerEnabled } from "./reply-timing-tracker.js";
117+
import { isRoutableChannel, routeReply } from "./route-reply.runtime.js";
116118
import type { TypingSignaler } from "./typing-mode.js";
117119

118120
// Maximum number of LiveSessionModelSwitchError retries before surfacing a
@@ -1564,9 +1566,6 @@ export async function runAgentTurnWithFallback(params: {
15641566
const shouldNotifyUserAboutCompaction =
15651567
runtimeConfig?.agents?.defaults?.compaction?.notifyUser === true;
15661568
const sendCompactionNotice = async (phase: "start" | "end" | "incomplete") => {
1567-
if (!params.opts?.onBlockReply) {
1568-
return;
1569-
}
15701569
const text =
15711570
phase === "start"
15721571
? "🧹 Compacting context..."
@@ -1579,12 +1578,51 @@ export async function runAgentTurnWithFallback(params: {
15791578
replyToCurrent: true,
15801579
isCompactionNotice: true,
15811580
});
1581+
1582+
// Primary path: deliver through the active turn's streaming callback.
1583+
if (params.opts?.onBlockReply) {
1584+
try {
1585+
await params.opts.onBlockReply(noticePayload);
1586+
} catch (err) {
1587+
logVerbose(`compaction ${phase} notice delivery failed (non-fatal): ${String(err)}`);
1588+
}
1589+
return;
1590+
}
1591+
1592+
// Fallback path: deliver through the canonical session outbound path when
1593+
// no active streaming turn is available (e.g. async / preflight compactions).
1594+
// Only send when notifyUser is enabled and the channel is routable.
1595+
if (!shouldNotifyUserAboutCompaction) {
1596+
return;
1597+
}
1598+
const channel = params.sessionCtx.Surface ?? params.sessionCtx.Provider;
1599+
if (!channel || !isRoutableChannel(channel)) {
1600+
return;
1601+
}
1602+
const to = params.sessionCtx.OriginatingTo ?? params.sessionCtx.To;
1603+
if (!to) {
1604+
return;
1605+
}
1606+
15821607
try {
1583-
await params.opts.onBlockReply(noticePayload);
1608+
const replyKind: ReplyDispatchKind = "block";
1609+
await routeReply({
1610+
payload: noticePayload,
1611+
channel,
1612+
to,
1613+
sessionKey: params.sessionKey,
1614+
accountId: params.sessionCtx.AccountId,
1615+
requesterSenderId: params.sessionCtx.SenderId,
1616+
requesterSenderName: params.sessionCtx.SenderName,
1617+
requesterSenderUsername: params.sessionCtx.SenderUsername,
1618+
requesterSenderE164: params.sessionCtx.SenderE164,
1619+
threadId: params.followupRun.originatingThreadId ?? params.sessionCtx.MessageThreadId,
1620+
cfg: runtimeConfig,
1621+
replyKind,
1622+
runId: params.followupRun.run.runId,
1623+
});
15841624
} catch (err) {
1585-
// Non-critical notice delivery failure should not bubble out of the
1586-
// fire-and-forget event handler.
1587-
logVerbose(`compaction ${phase} notice delivery failed (non-fatal): ${String(err)}`);
1625+
logVerbose(`compaction ${phase} notice route-reply failed (non-fatal): ${String(err)}`);
15881626
}
15891627
};
15901628
const readCompactionHookMessages = (value: unknown): string[] => {

0 commit comments

Comments
 (0)