/** * Unified Retry Utilities * * Provides a centralized retry mechanism for all async operations that may fail * due to transient errors (network timeouts, resource locks, rate limits, etc). * * @module utils/retry * * @example * ```typescript * import { retryAsync, isRetryableError } from '../utils/retry.js'; * * const result = await retryAsync( * () => llmClient.generate(prompt), * { maxRetries: 3, operation: 'llm-generate' } * ); * ``` */ export interface RetryOptions { /** Maximum number of retry attempts (default: 3) */ maxRetries?: number; /** Initial delay in ms before first retry (default: 1000) */ initialDelayMs?: number; /** Maximum delay in ms between retries (default: 30000) */ maxDelayMs?: number; /** Backoff multiplier (default: 2 for exponential) */ backoffMultiplier?: number; /** Operation name for logging */ operation?: string; /** Logger instance (optional, defaults to console) */ logger?: RetryLogger; isRetryable?: (_error: unknown) => boolean; } export interface RetryLogger { warn?: (_message: string) => void; info?: (_message: string) => void; debug?: (_message: string) => void; } export interface RetryResult { /** The result value if successful */ value: T; /** Number of attempts made (including successful one) */ attempts: number; /** Total time spent in ms */ totalTimeMs: number; } /** * Determines if an error is retryable based on common patterns. * * @param error - The error to check * @returns true if the error is likely transient and worth retrying */ export declare function isRetryableError(error: unknown): boolean; /** * Execute an async function with automatic retry on failure. * * Uses exponential backoff with configurable parameters. * Automatically detects retryable errors (timeouts, rate limits, etc). * * @param fn - The async function to execute * @param options - Retry configuration * @returns The result of the function * @throws The last error if all retries fail */ export declare function retryAsync(fn: () => Promise, options?: RetryOptions): Promise; /** * Execute an async function with retry, returning detailed result info. * * @param fn - The async function to execute * @param options - Retry configuration * @returns Detailed result including attempts and timing */ export declare function retryAsyncWithInfo(fn: () => Promise, options?: RetryOptions): Promise>; /** * Create a retry wrapper for a function. * Useful for wrapping LLM calls or API clients. * * @param fn - The async function to wrap * @param options - Default retry configuration * @returns A wrapped function with retry built-in */ export declare function withRetry(fn: (...args: Args) => Promise, options?: RetryOptions): (...args: Args) => Promise; /** * Retry an LLM API call with appropriate defaults. * LLM calls often timeout or hit rate limits. */ export declare function retryLLMCall(fn: () => Promise, operation?: string): Promise; /** * Retry a file operation with appropriate defaults. * File operations may fail due to locks or concurrent access. */ export declare function retryFileOperation(fn: () => Promise, operation?: string): Promise; /** * Retry a network request with appropriate defaults. * Network requests may fail due to transient connectivity issues. */ export declare function retryNetworkRequest(fn: () => Promise, operation?: string): Promise; /** Minimum samples needed before trusting learned timeout values */ export declare const MIN_SAMPLES = 3; /** Number of recent completion durations to consider */ export declare const LOOKBACK_WINDOW = 50; /** Safety multiplier applied to P95 */ export declare const SAFETY_MULTIPLIER = 1.5; /** Absolute minimum timeout — never go below this (10s) */ export declare const MIN_TIMEOUT_MS = 10000; /** Absolute maximum timeout cap — never exceed this (5min) */ export declare const MAX_TIMEOUT_MS = 300000; /** Maximum retry attempts for workflow timeout */ export declare const MAX_TIMEOUT_RETRIES = 2; /** Backoff multiplier for retry schedule */ export declare const RETRY_BACKOFF_MULTIPLIER = 2; /** * Interface for a data source that provides historical workflow durations. * Compatible with WorkflowStore's getCompletionDurations API. * This is the primary interface used by WorkflowManager. */ export interface DurationDataSource { getCompletionDurations(workflowType: string, limit: number): number[]; } /** * Interface for duration history storage (simpler alternative). */ export interface DurationHistorySource { /** Get recent completion durations in ms */ getDurations(limit: number): number[]; /** Record a new completion duration */ recordDuration(durationMs: number): void; } /** * Options for adaptive retry with dynamic timeout. */ export interface AdaptiveRetryOptions extends RetryOptions { /** Source for historical duration data */ durationHistory?: DurationHistorySource; /** Minimum samples before using adaptive timeout */ minSamples?: number; /** Percentile to use (default: 95) */ percentile?: number; /** Safety multiplier for computed timeout (default: 1.5) */ safetyMultiplier?: number; /** Minimum allowed timeout in ms (default: 10000) */ minTimeoutMs?: number; /** Maximum allowed timeout in ms (default: 300000) */ maxTimeoutMs?: number; } /** * Calculates P95 (or any percentile) from an array of numbers. * Falls back to median for small samples (< 10). * * @param values - Array of duration values * @param p - Percentile to compute (0-100) * @returns The computed percentile value */ export declare function percentile(values: number[], p: number): number; /** * Clamp timeout to safe bounds. */ export declare function clampTimeout(ms: number): number; /** * Computes an adaptive timeout for a workflow type based on historical data. * * Algorithm: * 1. Fetch last LOOKBACK_WINDOW completion durations * 2. If < MIN_SAMPLES: fall back to the provided defaultTimeout * 3. Otherwise: P95(durations) × SAFETY_MULTIPLIER * 4. Clamp to [MIN_TIMEOUT_MS, MAX_TIMEOUT_MS] * * This is the primary function used by WorkflowManager. * * @param dataSource - Source for historical duration data * @param workflowType - e.g. 'correction-observer' * @param defaultTimeout - Fallback when insufficient data (from spec) * @returns Computed timeout in milliseconds */ export declare function computeDynamicTimeout(dataSource: DurationDataSource, workflowType: string, defaultTimeout: number): number; /** * Computes retry timeout schedule for a workflow. * Returns an array of timeout values for each attempt (including initial). * * Example output: [30000, 60000, 120000] for 3 attempts with base 30s * * @param baseTimeoutMs - Base timeout in milliseconds * @param maxRetries - Maximum retry attempts (default: MAX_TIMEOUT_RETRIES) * @returns Array of timeout values for each attempt */ export declare function computeRetrySchedule(baseTimeoutMs: number, maxRetries?: number): number[]; /** * Compute adaptive timeout from historical data (simplified API). * Alternative to computeDynamicTimeout for simpler use cases. */ export declare function computeAdaptiveTimeout(history: number[], fallbackMs: number, options?: { minSamples?: number; percentile?: number; safetyMultiplier?: number; minTimeoutMs?: number; maxTimeoutMs?: number; }): number; /** * Execute an async function with adaptive timeout and retry. * * Combines: * 1. Dynamic timeout based on P95 of historical completions * 2. Exponential backoff on retry * 3. Automatic duration recording after success * * @param fn - The async function to execute * @param options - Configuration including history source * @returns The result of the function */ export declare function retryWithAdaptiveTimeout(fn: () => Promise, options?: AdaptiveRetryOptions): Promise;