/** One unit of work that was interrupted by a rate limit and should be resumed * once the limit window resets. `direct` = an interactive conversation (resumed by * re-routing a message into the channel's pooled session); `thread` = a thread * pipeline (resumed via continueThread). */ interface ResumeEntryBase { /** Opaque provider key. Missing/null entries are legacy and wait for every provider to clear. */ provider?: string | null; channel: string; userMessage: string; recordedAt: number; } export type ResumeEntry = (ResumeEntryBase & { kind: 'direct'; }) | (ResumeEntryBase & { kind: 'thread'; threadId: string; }); export interface ProviderResumeCounts { sessions: number; threads: number; } export interface ResumePersistence { save: (entries: ResumeEntry[]) => Promise; load: () => Promise; } declare function initResumeRegistry(persistence: ResumePersistence, onChange?: () => void): Promise; /** Record an interrupted session/thread for later resume. Idempotent per key * (direct→channel, thread→threadId): a newer record overwrites the older one. */ declare function recordResume(entry: ResumeEntry): void; /** Cancel a queued direct resume — the user declining the auto-continue for that channel. */ declare function removeDirectResume(channel: string): boolean; declare function removeThreadResume(threadId: string): boolean; /** Drain the registry: return all pending entries and clear (persists the empty list). * "take + clear" is atomic so each entry is dispatched at most once. */ declare function takeAllResumes(): ResumeEntry[]; declare function takeReadyResumes(activeProviders: string[]): ResumeEntry[]; declare function getResumeCountsByProvider(): Record; declare function getResumeCount(): number; declare function _testReset(): void; export { initResumeRegistry, recordResume, removeDirectResume, removeThreadResume, takeAllResumes, takeReadyResumes, getResumeCountsByProvider, getResumeCount, _testReset, };