/** * Timeout/Retry strategies with exponential backoff for human-in-the-loop workflows * * Provides robust retry logic specifically designed for human tier operations, * which require longer delays and more patience than AI tier operations. */ import type { Priority } from './types.js'; /** * Configuration for exponential backoff */ export interface BackoffConfig { /** Base delay in milliseconds */ baseDelayMs: number; /** Multiplier for each retry (default: 2) */ multiplier?: number; /** Maximum delay cap in milliseconds */ maxDelayMs?: number; /** Jitter factor (0-1) for randomization */ jitterFactor?: number; } /** * Configuration for retry policy */ export interface RetryConfig { /** Maximum number of retries */ maxRetries: number; /** Error types that are retryable */ retryableErrors?: string[]; /** Callback when retries are exhausted */ onExhausted?: (requestId: string, context: RetryExhaustedContext) => void | Promise; } /** * Context passed when retries are exhausted */ export interface RetryExhaustedContext { attempts: number; lastError?: Error; requestId: string; duration: number; } /** * Configuration for circuit breaker */ export interface CircuitBreakerConfig { /** Number of failures before opening circuit */ failureThreshold: number; /** Time in ms before attempting to close circuit */ resetTimeoutMs?: number; /** Time window in ms for counting failures */ windowMs?: number; /** Maximum attempts allowed in half-open state */ halfOpenMaxAttempts?: number; } /** * Configuration for SLA tracking */ export interface SLAConfig { /** Default deadline in milliseconds */ deadlineMs?: number; /** Warning threshold in milliseconds before deadline */ warningThresholdMs?: number; /** Callback when warning threshold is reached */ onWarning?: (requestId: string, context: SLAWarningContext) => void; /** Callback when SLA is violated */ onViolation?: (requestId: string, context: SLAViolationContext) => void; /** Priority-based SLA tiers */ tiers?: Record; } export interface SLAWarningContext { remainingMs: number; deadline: Date; } export interface SLAViolationContext { violatedAt: Date; deadline: Date; overdueMs: number; } /** * Options for withRetry wrapper */ export interface WithRetryOptions { /** Maximum number of retries */ maxRetries: number; /** Backoff configuration */ backoff?: BackoffConfig; /** Circuit breaker instance */ circuitBreaker?: HumanCircuitBreaker; /** SLA tracker instance */ slaTracker?: SLATracker; /** Request ID for SLA tracking */ requestId?: string; /** Callback when retries exhausted and escalation needed */ onEscalate?: (context: EscalationContext) => T | Promise; /** Use escalation result instead of throwing */ useEscalationResult?: boolean; } export interface EscalationContext { attempts: number; lastError: Error; totalDuration: number; } /** * Error thrown when retries are exhausted */ export declare class RetryError extends Error { readonly attempts: number; readonly lastError: Error; constructor(message: string, attempts: number, lastError: Error); } /** * Error thrown when circuit breaker is open */ export declare class CircuitOpenError extends Error { constructor(message?: string); } /** * Error thrown when SLA is violated */ export declare class SLAViolationError extends Error { readonly requestId: string; readonly deadline: Date; constructor(message: string, requestId: string, deadline: Date); } /** * Exponential backoff calculator with human-tier defaults * * Human tier operations require longer delays than AI tier: * - Humans need time to read, think, and respond * - Business hours affect availability * - Context switching has higher cost for humans * * @example * ```ts * const backoff = ExponentialBackoff.forHumans() * const delay = backoff.getDelayWithJitter(attemptNumber) * await sleep(delay) * ``` */ export declare class ExponentialBackoff { readonly config: Required; constructor(config: BackoffConfig); /** * Create a backoff calculator with human-appropriate defaults * - Base delay: 1 minute (humans need time) * - Max delay: 1 hour (don't wait forever) * - Jitter: 10% to prevent thundering herd */ static forHumans(overrides?: Partial): ExponentialBackoff; /** * Calculate delay for a given attempt number (0-indexed) */ getDelay(attempt: number): number; /** * Calculate delay with random jitter applied */ getDelayWithJitter(attempt: number): number; } /** * Retry policy designed for human-tier operations * * Key differences from AI-tier retry: * - More retries allowed (humans may be busy) * - BUSY is always retryable (humans have other priorities) * - Tracks retry state per request * * @example * ```ts * const policy = HumanRetryPolicy.forHumans() * if (policy.shouldRetry(attemptNumber, error)) { * // retry the request * } * ``` */ export declare class HumanRetryPolicy { readonly config: Required> & { onExhausted?: RetryConfig['onExhausted']; }; private attempts; private startTimes; constructor(config: RetryConfig); /** * Create a policy with human-appropriate defaults * - More retries (humans may be in meetings, etc.) * - BUSY is always retryable */ static forHumans(overrides?: Partial): HumanRetryPolicy; /** * Check if a retry should be attempted */ shouldRetry(currentAttempt: number, error?: Error, overrides?: { maxRetries?: number; }): boolean; /** * Record an attempt for a request */ recordAttempt(requestId: string): void; /** * Record an attempt and trigger callbacks if exhausted */ recordAttemptAsync(requestId: string): Promise; /** * Check if retries are exhausted for a request */ isExhausted(requestId: string): boolean; /** * Reset tracking for a request */ reset(requestId: string): void; } export type CircuitState = 'closed' | 'open' | 'half_open'; interface CircuitMetrics { failures: number; successes: number; state: CircuitState; failureRate: number; lastFailure?: Date; lastSuccess?: Date; } /** * Circuit breaker to protect overwhelmed human tier * * When too many requests fail (humans unavailable, timing out, etc.), * the circuit opens to prevent further requests and give humans time to recover. * * States: * - CLOSED: Normal operation, requests flow through * - OPEN: Too many failures, requests are blocked * - HALF_OPEN: Testing if humans are available again * * @example * ```ts * const breaker = new HumanCircuitBreaker({ failureThreshold: 5 }) * * if (breaker.isOpen()) { * throw new CircuitOpenError() * } * * try { * await humanRequest() * breaker.recordSuccess() * } catch (error) { * breaker.recordFailure() * throw error * } * ``` */ export declare class HumanCircuitBreaker { private _state; private failures; private successes; private lastStateChange; private halfOpenAttempts; private lastFailure?; private lastSuccess?; readonly config: Required; constructor(config: CircuitBreakerConfig); /** * Get current circuit state */ get state(): CircuitState; /** * Record a failure */ recordFailure(): void; /** * Record a success */ recordSuccess(): void; /** * Check if circuit is open (requests should be blocked) */ isOpen(): boolean; /** * Throw if circuit is open */ throwIfOpen(): void; /** * Check if an attempt can be made (for half-open state limiting) */ canAttempt(): boolean; /** * Record an attempt in half-open state */ recordAttempt(): void; /** * Check if humans are overwhelmed (high failure rate) */ isOverwhelmed(): boolean; /** * Get failure rate (0-1) */ getFailureRate(): number; /** * Get current metrics */ getMetrics(): CircuitMetrics; /** * Reset the circuit breaker */ reset(): void; } interface SLAMetrics { completed: number; violated: number; complianceRate: number; averageCompletionMs?: number; } /** * SLA tracker for monitoring human response deadlines * * Features: * - Deadline tracking per request * - Warning callbacks before deadline * - Violation callbacks after deadline * - Priority-based SLA tiers * - Compliance rate metrics * * @example * ```ts * const tracker = new SLATracker({ * deadlineMs: 300000, // 5 minutes * warningThresholdMs: 60000, // Warn at 1 minute remaining * onWarning: (id, ctx) => console.log(`SLA warning for ${id}`), * onViolation: (id, ctx) => console.log(`SLA violated for ${id}`), * }) * * tracker.track('req-1') * // ... later * if (tracker.isViolated('req-1')) { * // Handle violation * } * tracker.complete('req-1') * ``` */ export declare class SLATracker { readonly config: SLAConfig; private requests; private completedRequests; private checkInterval?; constructor(config: SLAConfig); /** * Start tracking a request */ track(requestId: string, options?: { priority?: Priority; }): { deadline: Date; remainingMs: number; }; /** * Get remaining time for a request */ getRemainingTime(requestId: string): number; /** * Check if SLA is violated for a request */ isViolated(requestId: string): boolean; /** * Mark a request as completed */ complete(requestId: string): void; /** * Get SLA metrics */ getMetrics(): SLAMetrics; /** * Stop tracking and cleanup */ destroy(): void; private getDeadlineForPriority; private startChecking; private emitWarning; private emitViolation; } /** * Wrap an operation with retry logic, circuit breaker, and SLA tracking * * This is the main entry point for adding retry logic to human-tier operations. * * @example * ```ts * const result = await withRetry( * () => human.ask({ question: 'What should we do?' }), * { * maxRetries: 3, * backoff: { baseDelayMs: 60000 }, * onEscalate: (ctx) => escalateToManager(ctx), * } * ) * ``` */ export declare function withRetry(operation: () => T | Promise, options: WithRetryOptions): Promise; export {}; //# sourceMappingURL=timeout-retry.d.ts.map