const CANCELED_REQUEST_TTL_MS = 10 * 60 * 1000; type ActiveClawdRequest = { controller: AbortController; expiresAt: number; }; const registry = globalThis as typeof globalThis & { __activeClawdRequests?: Map; __canceledClawdRequests?: Map; }; const activeRequests = registry.__activeClawdRequests || new Map(); const canceledRequests = registry.__canceledClawdRequests || new Map(); registry.__activeClawdRequests = activeRequests; registry.__canceledClawdRequests = canceledRequests; function cleanupExpiredClawdRequests(now = Date.now()) { for (const [key, request] of activeRequests.entries()) { if (request.expiresAt <= now) { activeRequests.delete(key); } } for (const [key, expiresAt] of canceledRequests.entries()) { if (expiresAt <= now) { canceledRequests.delete(key); } } } export function buildClawdCancelKey({ userId, chatId, userMessageId, }: { userId: string; chatId: string; userMessageId: string; }) { return `${userId}:${chatId}:${userMessageId}`; } export function registerActiveClawdRequest( key: string, controller: AbortController, timeoutMs: number ) { cleanupExpiredClawdRequests(); activeRequests.set(key, { controller, expiresAt: Date.now() + Math.max(timeoutMs, CANCELED_REQUEST_TTL_MS), }); } export function unregisterActiveClawdRequest(key: string) { activeRequests.delete(key); } export function hasActiveClawdRequest(key: string) { cleanupExpiredClawdRequests(); return activeRequests.has(key); } export function cancelClawdRequest(key: string) { cleanupExpiredClawdRequests(); canceledRequests.set(key, Date.now() + CANCELED_REQUEST_TTL_MS); const activeRequest = activeRequests.get(key); if (activeRequest && !activeRequest.controller.signal.aborted) { activeRequest.controller.abort(); } return Boolean(activeRequest); } export function isClawdRequestCanceled(key: string) { cleanupExpiredClawdRequests(); const expiresAt = canceledRequests.get(key); if (!expiresAt) return false; if (expiresAt <= Date.now()) { canceledRequests.delete(key); return false; } return true; } export function clearClawdRequestCancellation(key: string) { canceledRequests.delete(key); }