/**
 * General-purpose retry utility with exponential backoff.
 *
 * This module provides a shared, dependency-free retry primitive for use
 * anywhere in the CLEO core. Unlike the agent-specific retry in
 * `agents/retry.ts`, this utility has no database coupling and is safe to
 * import from any layer.
 *
 * Default schedule (3 attempts, task T040 spec):
 * - Attempt 1: immediate (0 ms delay before retry)
 * - Attempt 2: 2 000 ms delay before retry
 * - Attempt 3: 4 000 ms delay before retry
 * - After attempt 3: throw last error
 *
 * @module lib/retry
 */
/**
 * A predicate or pattern used to decide whether an error is retryable.
 *
 * - `RegExp` — matched against `error.message` (or `String(error)`)
 * - `(error: unknown) => boolean` — arbitrary predicate function
 */
export type RetryablePredicate = RegExp | ((error: unknown) => boolean);
/**
 * Options that control retry behavior for {@link withRetry}.
 */
export interface RetryOptions {
    /**
     * Maximum total number of attempts (initial + retries).
     *
     * @default 3
     */
    maxAttempts?: number;
    /**
     * Delay before the second attempt in milliseconds.
     * Each subsequent delay is `baseDelayMs * 2^(attempt - 1)`.
     *
     * @default 2000
     */
    baseDelayMs?: number;
    /**
     * Upper bound on computed delay in milliseconds.
     * Prevents unbounded growth with many retries.
     *
     * @default 30000
     */
    maxDelayMs?: number;
    /**
     * Explicit list of patterns or predicates that identify retryable errors.
     *
     * When provided, ONLY errors matching at least one entry are retried.
     * Errors that match none of the entries cause immediate failure.
     *
     * When omitted, all errors are treated as retryable (up to `maxAttempts`).
     */
    retryableErrors?: ReadonlyArray<RetryablePredicate>;
}
/**
 * Metadata attached to errors thrown after all retry attempts are exhausted.
 *
 * The last error from the final attempt is augmented with these fields so
 * callers can distinguish a retry-exhausted failure from a first-attempt one.
 */
export interface RetryContext {
    /** Total number of attempts made (always equal to `maxAttempts`). */
    attempts: number;
    /** Cumulative delay applied across all retry waits in milliseconds. */
    totalDelayMs: number;
}
/**
 * Execute an async function with automatic retry and exponential backoff.
 *
 * @remarks
 * The function is called up to `maxAttempts` times. After the first failure,
 * the utility waits `baseDelayMs` milliseconds, then retries. Each subsequent
 * wait doubles: `baseDelayMs * 2^(attempt - 1)`, capped at `maxDelayMs`.
 *
 * If `retryableErrors` is supplied, only errors matching at least one entry
 * are retried; other errors cause immediate re-throw.
 *
 * On final failure the original error is re-thrown. Use {@link RetryContext}
 * fields (attached to the error) to inspect retry metadata.
 *
 * @example
 * ```ts
 * // Basic usage — 3 attempts with 0 ms / 2 000 ms / 4 000 ms delays
 * const data = await withRetry(() => fetchFromApi());
 *
 * // Custom retry window — only on network errors
 * const result = await withRetry(
 *   () => db.query(sql),
 *   {
 *     maxAttempts: 5,
 *     baseDelayMs: 500,
 *     retryableErrors: [/SQLITE_BUSY/, /database is locked/i],
 *   },
 * );
 * ```
 *
 * @typeParam T - The resolved type of the async function
 * @param fn - Async factory that is called on each attempt.
 * @param options - Optional retry configuration.
 * @returns Resolved value of `fn` on success.
 * @throws The last error thrown by `fn`, augmented with {@link RetryContext}
 *   fields (`attempts`, `totalDelayMs`).
 */
export declare function withRetry<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T>;
/**
 * Compute the wait time before the next attempt.
 *
 * @remarks
 * Formula: `min(baseDelayMs * 2^(attempt - 1), maxDelayMs)`.
 * On the first retry (`attempt === 1`) the delay is `baseDelayMs * 1 = baseDelayMs`.
 *
 * @example
 * ```ts
 * computeDelay(1, 2000, 30000); // 2000
 * computeDelay(2, 2000, 30000); // 4000
 * computeDelay(3, 2000, 30000); // 8000
 * ```
 *
 * @param attempt - The 1-based attempt number that just failed.
 * @param baseDelayMs - Base delay in milliseconds.
 * @param maxDelayMs - Maximum allowed delay in milliseconds.
 * @returns Delay in milliseconds before the next attempt.
 */
export declare function computeDelay(attempt: number, baseDelayMs: number, maxDelayMs: number): number;
//# sourceMappingURL=retry.d.ts.map