/**
 * Centralized 429/rate-limit error detection.
 * Checks error message for common rate-limit indicators across LLM providers.
 */
export function isRateLimitError(err) {
    if (!(err instanceof Error))
        return false;
    const msg = err.message.toLowerCase(); // totem-ignore #894 — centralized detector
    return msg.includes('429') || msg.includes('too many requests') || msg.includes('rate limit');
}
/**
 * Wraps an async function with exponential backoff retry on 429 errors.
 */
export async function withRetry(fn, opts) {
    const maxRetries = opts?.maxRetries ?? 3;
    const baseDelay = opts?.baseDelayMs ?? 2000;
    for (let attempt = 0; attempt <= maxRetries; attempt++) {
        try {
            return await fn();
        }
        catch (err) {
            if (!isRateLimitError(err) || attempt === maxRetries)
                throw err;
            const jitter = Math.random() * 0.5 + 0.75; // 0.75x–1.25x randomization
            const delay = Math.round(baseDelay * Math.pow(2, attempt) * jitter);
            opts?.onRetry?.(attempt + 1, delay);
            await new Promise((resolve) => setTimeout(resolve, delay));
        }
    }
    throw new Error('[Totem Error] Retry loop failed to complete unexpectedly.'); // totem-ignore #894 — dead code guard
}
//# sourceMappingURL=retry.js.map