import { extractStructuredHttpErrorPayload, parseStreamErrorPayload } from '../contracts/model-stream.js';
export class ShortcutXLHttpStreamError extends Error {
    details;
    constructor(message, details) {
        super(message);
        this.name = 'ShortcutXLHttpStreamError';
        this.details = details;
    }
}
export async function buildHttpStreamError(response) {
    const rawBody = await response.text();
    let parsedBody;
    try {
        parsedBody = rawBody ? JSON.parse(rawBody) : undefined;
    }
    catch {
        parsedBody = undefined;
    }
    const payload = extractStructuredHttpErrorPayload(parsedBody);
    const message = typeof payload?.message === 'string'
        ? payload.message
        : `ShortcutXL runtime stream failed: ${response.status}${rawBody ? ` ${rawBody}` : ''}`;
    return new ShortcutXLHttpStreamError(message, parseStreamErrorPayload(payload, response.status) ?? { status: response.status });
}
function isRetryableStatus(status) {
    return status === 408 || status === 429 || (status !== undefined && status >= 500);
}
export function streamErrorDetails(error) {
    return error instanceof ShortcutXLHttpStreamError ? error.details : undefined;
}
export function isRetryableStreamError(error) {
    if (error instanceof Error && error.name === 'AbortError') {
        return false;
    }
    const details = streamErrorDetails(error);
    if (details?.retryable !== undefined) {
        return details.retryable;
    }
    if (isRetryableStatus(details?.status)) {
        return true;
    }
    return !(error instanceof ShortcutXLHttpStreamError);
}
export function computeRetryDelayMs(error, attempt, baseDelayMs, maxDelayMs, serverMaxDelayMs) {
    const requested = streamErrorDetails(error)?.retryAfterMs;
    if (requested !== undefined && requested >= 0) {
        // Server-directed delays use their own (higher) ceiling so a recovering
        // provider's explicit hint isn't truncated to the client backoff cap.
        return Math.min(requested, serverMaxDelayMs);
    }
    return Math.min(maxDelayMs, baseDelayMs * 2 ** Math.max(0, attempt - 1));
}
//# sourceMappingURL=stream-errors.js.map