import type { LLMProvider } from '../types/provider/index.js'; import { type BackoffPolicy } from '../utils/backoff.js'; import type { Logger } from '../utils/logger.js'; /** * `BackoffPolicy` plus the provider-specific parts: how many attempts, and * how long a server-directed wait may be honoured for. * * The curve itself lives in `utils/backoff.ts` and is shared with the tool * executor's in-loop retry — which had no backoff at all while this one was * being careful about jitter two directories away. */ export interface ProviderRetryConfig extends BackoffPolicy { /** Retry attempts AFTER the initial try. `0` disables retrying. */ readonly maxRetries: number; /** * Cap on a server-directed `Retry-After`. A provider asking for 15 * minutes should not silently park an interactive run for 15 minutes; * past this we surface the error and let the caller decide. * * "Surface" is the whole of it: there is no shorter retry underneath. A * server that named a wait has said something specific, and answering it * with a half-second backoff neither honours the wait nor tells anyone it * was refused. The error carries `retryAfterMs`, so a host that wants to * come back in fifteen minutes can — that decision is above this loop. * * Raise it to let the turn sleep longer; a request under the ceiling is * still slept exactly as instructed. */ readonly maxRetryAfterMs: number; } export declare const DEFAULT_PROVIDER_RETRY: ProviderRetryConfig; export interface WithProviderRetryOptions { /** Additional live admission policy, checked before scheduling a retry. */ readonly canRetry?: () => boolean; readonly config?: Partial; readonly log?: Logger; /** Seam for deterministic tests. */ readonly random?: () => number; readonly sleepFn?: (ms: number, signal?: AbortSignal) => Promise; } /** * Wrap a provider so transient failures are retried with exponential * backoff and full jitter. * * **Retry only before the first content chunk.** Once a delta has been * yielded the consumer has already emitted `text_delta` events and * appended to its buffer, so restarting the request would duplicate * output. A mid-stream failure is therefore surfaced, not retried — the * existing stream-error path in `streamProviderTurn` handles it (and can * still salvage a truncated tool call). This is the whole reason the * retry lives in a decorator rather than inside the loop: the loop cannot * un-emit. * * Aborts propagate untouched so a Stop still settles the turn as * `cancelled` rather than being mistaken for a transport failure. */ export declare function withProviderRetry(provider: LLMProvider, options?: WithProviderRetryOptions): LLMProvider; //# sourceMappingURL=retry.d.ts.map