fix: keep channel typing active during long inference (#25886, thanks @stakeswky)

Co-authored-by: stakeswky <stakeswky@users.noreply.github.com>
This commit is contained in:
Peter Steinberger
2026-02-25 02:03:15 +00:00
parent dcd90438ec
commit e0201c2774
10 changed files with 111 additions and 16 deletions

View File

@@ -10,9 +10,15 @@ export function createTypingCallbacks(params: {
stop?: () => Promise<void>;
onStartError: (err: unknown) => void;
onStopError?: (err: unknown) => void;
keepaliveIntervalMs?: number;
}): TypingCallbacks {
const stop = params.stop;
const onReplyStart = async () => {
const keepaliveIntervalMs = params.keepaliveIntervalMs ?? 3_000;
let keepaliveTimer: ReturnType<typeof setInterval> | undefined;
let keepaliveStartInFlight = false;
let stopSent = false;
const fireStart = async () => {
try {
await params.start();
} catch (err) {
@@ -20,11 +26,41 @@ export function createTypingCallbacks(params: {
}
};
const fireStop = stop
? () => {
void stop().catch((err) => (params.onStopError ?? params.onStartError)(err));
const clearKeepalive = () => {
if (!keepaliveTimer) {
return;
}
clearInterval(keepaliveTimer);
keepaliveTimer = undefined;
keepaliveStartInFlight = false;
};
const onReplyStart = async () => {
stopSent = false;
clearKeepalive();
await fireStart();
if (keepaliveIntervalMs <= 0) {
return;
}
keepaliveTimer = setInterval(() => {
if (keepaliveStartInFlight) {
return;
}
: undefined;
keepaliveStartInFlight = true;
void fireStart().finally(() => {
keepaliveStartInFlight = false;
});
}, keepaliveIntervalMs);
};
const fireStop = () => {
clearKeepalive();
if (!stop || stopSent) {
return;
}
stopSent = true;
void stop().catch((err) => (params.onStopError ?? params.onStartError)(err));
};
return { onReplyStart, onIdle: fireStop, onCleanup: fireStop };
}