import type { RequestContext } from '../../utils/internal/requestContext.js';
/** Configuration for {@link withRetry}. */
export interface RetryOptions {
    /**
     * Base delay in milliseconds before the first retry.
     * Subsequent delays are `baseDelayMs * 2^attempt`. Default: `1000`.
     *
     * Calibrate to the upstream's recovery time:
     * - 200–500ms for ephemeral failures (connection pool)
     * - 1–2s for rate-limited APIs
     * - 2–5s for service degradation / outages
     */
    baseDelayMs?: number;
    /**
     * Log bindings for correlated logging. When provided, retry log entries
     * include `requestId`, `traceId`, etc. Passing the handler `Context` is
     * safe — the logger strips non-serializable fields (`signal`, `log`,
     * `state`, protocol method handles) before pino sees them.
     */
    context?: RequestContext;
    /**
     * Custom predicate to determine if an error is transient and should be
     * retried. When provided, this **replaces** the default predicate entirely
     * (including the `data.retryable === false` opt-out). Return `true` to
     * retry, `false` to fail immediately.
     *
     * Use this only when you need fully custom classification logic. For the
     * common case of opting a single throw site out of retry, set
     * `data.retryable: false` on the thrown `McpError` instead — the default
     * predicate handles it automatically.
     */
    isTransient?: (error: unknown) => boolean;
    /**
     * Jitter factor applied to each delay. `0` = no jitter, `1` = full jitter
     * (delay randomized between 0 and calculated delay). Default: `0.25`.
     */
    jitter?: number;
    /**
     * Maximum delay cap in milliseconds. Prevents unbounded growth on high
     * retry counts. Default: `30000` (30s).
     */
    maxDelayMs?: number;
    /**
     * Maximum number of retry attempts after the initial call.
     * Total attempts = `maxRetries + 1`. Default: `3`.
     */
    maxRetries?: number;
    /**
     * Operation name for structured log messages. Used in log context and
     * enriched error messages on exhaustion.
     */
    operation?: string;
    /**
     * Optional AbortSignal. When aborted, the retry loop exits immediately
     * without further attempts.
     */
    signal?: AbortSignal;
}
/**
 * Executes `fn` with retry logic and exponential backoff.
 *
 * The retry boundary should wrap the **full pipeline** — HTTP fetch, response
 * parsing, and validation — not just the network call. This ensures that
 * transient upstream errors (e.g., HTTP 200 with an error body) are retried.
 *
 * **Deterministic-failure opt-out.** When the thrown `McpError` carries
 * `data.retryable === false`, the default predicate treats it as non-transient
 * and fails immediately — even for `Timeout`/`ServiceUnavailable`/`RateLimited`
 * codes. Use this at the throw site (or let the error contract auto-populate it
 * via `ctx.fail`) for failures that can never succeed on retry (oversized query,
 * malformed request surfaced as HTTP 200 + error body, etc.).
 *
 * When retries exhaust, the final error is enriched with attempt count in both
 * the message and structured data, so callers know retries were already attempted.
 *
 * @typeParam T - Return type of the operation.
 * @param fn - The async operation to execute with retries.
 * @param options - Retry configuration. All fields optional with sensible defaults.
 * @returns The result of `fn` on success.
 * @throws The enriched final error when all attempts are exhausted, or the original
 *   error immediately if it is not classified as transient.
 *
 * @example
 * ```ts
 * // Service method — retry covers fetch + parse
 * async function fetchStudy(id: string, ctx: Context): Promise<Study> {
 *   return withRetry(
 *     async () => {
 *       const text = await apiClient.get(`/studies/${id}`);
 *       return responseHandler.parse<Study>(text);
 *     },
 *     { operation: 'fetchStudy', context: ctx, baseDelayMs: 1000 },
 *   );
 * }
 * ```
 */
export declare function withRetry<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T>;
//# sourceMappingURL=retry.d.ts.map