/** * withRetry — provider decorator that retries failed calls. * * Pattern: Decorator (GoF) — wraps an `LLMProvider` and adds retry * policy without changing its interface. * Role: Outer ring (Hexagonal). Composable: `withRetry(withFallback(...))`. * * Retries `complete()` on transient failures with exponential backoff. * `stream()` is delegated as-is — once tokens start flowing the * pipeline is stateful and cannot safely be restarted. If you need * retry semantics for streaming, fall back to `complete()` or * implement custom resumability at the consumer. * * Default policy: * • maxAttempts: 3 (initial + 2 retries) * • backoff: exponential — 200ms, 400ms, 800ms * • shouldRetry: rejects 4xx-class errors (client mistakes don't * benefit from retry) and AbortError; retries 5xx, * network errors, and unknown shapes. */ import type { LLMProvider } from '../adapters/types.js'; export interface WithRetryOptions { /** Total attempts including the first. Default 3. Must be >= 1. */ readonly maxAttempts?: number; /** Initial delay in ms before the first retry. Default 200. */ readonly initialDelayMs?: number; /** Multiplier between attempts. Default 2 (200ms → 400ms → 800ms). */ readonly backoffFactor?: number; /** Maximum delay cap in ms. Default 10_000. */ readonly maxDelayMs?: number; /** * Predicate to decide whether an error is worth retrying. Default * skips AbortError + HTTP 4xx; retries everything else. Override * to add provider-specific signals (e.g., 429 with Retry-After). */ readonly shouldRetry?: (error: unknown, attempt: number) => boolean; /** * Hook invoked before each retry. Useful for logging in standalone * (non-agentfootprint) use. Receives the attempt number that's about * to start (so attempt 2 = first retry). * * You do NOT need this to get retry telemetry inside a run: since v7.8 * the in-run LLM call sites hand this decorator an `LLMCallHooks` and * translate its reports into `agentfootprint.error.retried` / * `agentfootprint.error.recovered` events, stamped with the real * `runId`/`runtimeStageId`. This hook is the consumer-owned escape * hatch and its contract is unchanged. */ readonly onRetry?: (error: unknown, attempt: number, delayMs: number) => void; } /** * Wrap a provider so its `complete()` retries transient failures. * * @example * import { withRetry } from 'agentfootprint/resilience'; * import { anthropic } from 'agentfootprint/llm-providers'; * * const robust = withRetry(anthropic({ apiKey }), { * maxAttempts: 5, * onRetry: (err, attempt, ms) => console.warn(`retry ${attempt} in ${ms}ms`, err), * }); */ export declare function withRetry(provider: LLMProvider, options?: WithRetryOptions): LLMProvider; /** * Skip retry for AbortError + 4xx-class errors. Retry on everything * else (network errors, 5xx, unknown shapes). Provider adapters that * surface HTTP status should set `error.status` for this to work; the * predicate falls back to retrying when status is unknown (better to * retry once than to surface a flaky failure). * * Exported (module-level, NOT on the resilience barrel) as the single * source of truth for the decorators' transience policy — shared by * `withCredentialRetry` (identity) so "what counts as transient" never * drifts between the LLM and credential retry wrappers. */ export declare function defaultShouldRetry(err: unknown, _attempt: number): boolean; //# sourceMappingURL=withRetry.d.ts.map