diff --git a/src/auto-reply/reply/typing.ts b/src/auto-reply/reply/typing.ts index 82e3d762240..43174024606 100644 --- a/src/auto-reply/reply/typing.ts +++ b/src/auto-reply/reply/typing.ts @@ -61,6 +61,10 @@ export function createTypingController(params: { clearTimeout(typingTtlTimer); typingTtlTimer = undefined; } + if (dispatchIdleTimer) { + clearTimeout(dispatchIdleTimer); + dispatchIdleTimer = undefined; + } typingLoop.stop(); // Notify the channel to stop its typing indicator (e.g., on NO_REPLY). // This fires only once (sealed prevents re-entry). @@ -177,13 +181,28 @@ export function createTypingController(params: { await startTypingLoop(); }; + let dispatchIdleTimer: NodeJS.Timeout | undefined; + const DISPATCH_IDLE_GRACE_MS = 10_000; + const markRunComplete = () => { runComplete = true; maybeStopOnIdle(); + if (!sealed && !dispatchIdle) { + dispatchIdleTimer = setTimeout(() => { + if (!sealed && !dispatchIdle) { + log?.("typing: dispatch idle not received after run complete; forcing cleanup"); + cleanup(); + } + }, DISPATCH_IDLE_GRACE_MS); + } }; const markDispatchIdle = () => { dispatchIdle = true; + if (dispatchIdleTimer) { + clearTimeout(dispatchIdleTimer); + dispatchIdleTimer = undefined; + } maybeStopOnIdle(); };