Files
openclaw/src/channels/typing.ts
2026-02-25 14:49:21 +02:00

60 lines
1.4 KiB
TypeScript

import { createTypingKeepaliveLoop } from "./typing-lifecycle.js";
export type TypingCallbacks = {
onReplyStart: () => Promise<void>;
onIdle?: () => void;
/** Called when the typing controller is cleaned up (e.g., on NO_REPLY). */
onCleanup?: () => void;
};
export function createTypingCallbacks(params: {
start: () => Promise<void>;
stop?: () => Promise<void>;
onStartError: (err: unknown) => void;
onStopError?: (err: unknown) => void;
keepaliveIntervalMs?: number;
}): TypingCallbacks {
const stop = params.stop;
const keepaliveIntervalMs = params.keepaliveIntervalMs ?? 3_000;
let stopSent = false;
let closed = false;
const fireStart = async () => {
if (closed) {
return;
}
try {
await params.start();
} catch (err) {
params.onStartError(err);
}
};
const keepaliveLoop = createTypingKeepaliveLoop({
intervalMs: keepaliveIntervalMs,
onTick: fireStart,
});
const onReplyStart = async () => {
if (closed) {
return;
}
stopSent = false;
keepaliveLoop.stop();
await fireStart();
keepaliveLoop.start();
};
const fireStop = () => {
closed = true;
keepaliveLoop.stop();
if (!stop || stopSent) {
return;
}
stopSent = true;
void stop().catch((err) => (params.onStopError ?? params.onStartError)(err));
};
return { onReplyStart, onIdle: fireStop, onCleanup: fireStop };
}