/** Sleep `ms`, but wake early if `signal` fires — so a long back-off (e.g. a * rate-limit wait) never swallows Ctrl+C. Resolves either way. */ export declare const waitMs: (ms: number, signal: AbortSignal) => Promise; /** Resolve `p`, but reject with a TimeoutError if it takes longer than `ms`. * The underlying promise is left to settle on its own (we just stop waiting), * so a slow black-box call can never wedge the caller. */ export declare function withTimeout(p: Promise, ms: number, label?: string): Promise; /** An HTTP error the caller tagged as transient. `.fatal` skips all retries; * `.throttle` (a 429/503 rate-limit or overload) is retried indefinitely and * does NOT consume the bounded attempt budget — the server told us to wait, not * to give up. `.retryAfterMs` carries a server-suggested delay when present. */ export type HttpError = Error & { fatal?: boolean; throttle?: boolean; retryAfterMs?: number; }; /** What every network call in this trainer needs from its caller: how to be * cancelled, and (optionally) where to report a rate-limit wait. */ export interface HttpOptions { signal: AbortSignal; /** Called after each throttle wait, so a 429 back-off reads as "waiting" * rather than a silent hang. Omitted ⇒ the wait is silent. */ onThrottle?: (waitMsAmount: number, label: string) => void; } /** Wrap a throttle notice so a STORM of 429s logs at most one notice every * `minGapMs`. Without the gap a busy server produces a wall of identical * "waiting…" lines that pushes the real log out of the scrollback. */ export declare function throttleNotifier(fn: (waitMsAmount: number, label: string) => void, minGapMs?: number): (waitMsAmount: number, label: string) => void; /** Retry `fn` with exponential backoff. * * Three error classes: * • `.fatal` / AbortError → rethrown immediately (never retried). * • `.throttle` (429/503) → the server is rate-limiting/overloaded. We are * NOT failing — we WAIT (honouring Retry-After, else capped exponential * back-off with jitter) and retry WITHOUT consuming an attempt, so a * throttled request holds on until it succeeds rather than being dropped. * Only a shutdown breaks this loop. * • anything else → a genuine transient error, retried up to `tries` * with exponential back-off before giving up. * * `onFail` is called after each non-throttle failed attempt; `onThrottle` after * each throttle wait (for a "waiting…" notice). */ export declare function retry(label: string, fn: () => Promise, tries: number, opts: HttpOptions & { onFail?: (attempt: number, err: Error) => void; }): Promise; /** Classify a non-OK HTTP response into an {@link HttpError} for {@link retry}: * • 429 / 503 → THROTTLE (rate-limited / overloaded): retried indefinitely, * honouring a Retry-After header (seconds or an HTTP-date) when present. * • other 5xx → transient: retried up to the caller's attempt budget. * • other 4xx → FATAL: a real client error (404, 401, …) — not retried. * Never throttles forever silently: the wait is interruptible by shutdown. */ export declare function httpError(res: Response): HttpError; /** GET a URL and parse JSON, with the shared retry policy: rate-limits (429/503) * WAIT indefinitely (surfaced through `opts.onThrottle`), other 4xx is fatal, * other 5xx retried up to DOWNLOAD_TRIES. Used by every dataset LISTING call so * all share the same never-drop-on-throttle behaviour. */ export declare function getJson(url: string, label: string, opts: HttpOptions): Promise; /** The `rel="next"` URL of an RFC 5988 Link header, or null. */ export declare function nextLink(header: string | null): string | null; /** GET a paginated JSON ARRAY, following `Link: rel="next"` to the end. * * A LISTING THAT STOPS EARLY IS INVISIBLE, and that is why this exists. * Hugging Face caps a tree listing at 1,000 entries and hands back a next * link (verified: allenai/c4 returns exactly 1,000 plus a link). A caller that * ignores it gets a work-list silently missing everything past the first page, * trains it, marks those units complete, and thereafter reports the corpus * "already trained". No error at any point. Following the links is the only * way the work-list can be trusted to be the whole work-list. * * `maxPages` is a runaway guard, not a limit anyone should hit; exceeding it * throws rather than returning a partial list, for exactly the reason above. */ export declare function getJsonPaged(url: string, label: string, opts: HttpOptions, maxPages?: number): Promise; /** Advertised transfer size of `url`, used only to reserve cache room. Like any * `content-length` this is the ON-THE-WIRE size, so for a content-coded source * (GitHub raw gzips JSON ~14x) it UNDER-estimates the file that lands on disk. * That is tolerable here because the cache ceiling is a budget, not a * correctness property — a run may overshoot MAX_CACHE_GB by the compression * ratio of one in-flight file, and each file is deleted as soon as it is * consumed. It must NOT be reused as an integrity check; see downloadFile. * * Rate-limits wait; other 4xx is fatal; total failure → the caller's catch. */ export declare function headSize(url: string, opts: HttpOptions): Promise;