/**
 * Error injection utilities for testing retry middleware behavior e2e.
 *
 * Provides pre-defined error scenarios that can be injected into mock streams
 * to test how the retry middleware handles different provider errors.
 */
/**
 * Pre-defined error scenarios for testing.
 */
export const ERROR_SCENARIOS = {
    rate_limit: {
        name: "Rate Limit (429)",
        description: "Rate limit error that succeeds after 2 retries",
        errors: [
            {
                type: "rate_limit_error",
                message: "Rate limit exceeded. Please try again later.",
            },
            {
                type: "rate_limit_error",
                message: "Rate limit exceeded. Please try again later.",
            },
        ],
        eventuallySucceeds: true,
        successContent: "✅ Successfully recovered from rate limiting! This demonstrates the retry middleware handling transient errors.",
    },
    overloaded: {
        name: "Overloaded (529)",
        description: "Server overloaded error that succeeds after 1 retry",
        errors: [
            {
                type: "overloaded_error",
                message: "The server is currently overloaded. Please try again.",
            },
        ],
        eventuallySucceeds: true,
        successContent: "✅ Successfully recovered from server overload! The retry logic waited and tried again.",
    },
    timeout: {
        name: "Timeout",
        description: "Timeout error that succeeds after 2 retries",
        errors: [
            {
                type: "api_error",
                message: "ETIMEDOUT: Connection timed out",
            },
            {
                type: "api_error",
                message: "ETIMEDOUT: Connection timed out",
            },
        ],
        eventuallySucceeds: true,
        successContent: "✅ Successfully recovered from timeout errors! Network issues were resolved.",
    },
    auth_failure: {
        name: "Authentication Error (401)",
        description: "Non-retryable authentication error",
        errors: [
            {
                type: "authentication_error",
                message: "Invalid API key provided.",
            },
        ],
        eventuallySucceeds: false,
    },
    permission_denied: {
        name: "Permission Error (403)",
        description: "Non-retryable permission error",
        errors: [
            {
                type: "permission_error",
                message: "Access denied. Your API key does not have permission to access this resource.",
            },
        ],
        eventuallySucceeds: false,
    },
    invalid_request: {
        name: "Invalid Request Error (400)",
        description: "Non-retryable invalid request error",
        errors: [
            {
                type: "invalid_request_error",
                message: "Invalid request: malformed input parameters.",
            },
        ],
        eventuallySucceeds: false,
    },
    max_retries: {
        name: "Exhausted Retries",
        description: "Rate limit error that exhausts all retry attempts",
        errors: [
            {
                type: "rate_limit_error",
                message: "Rate limit exceeded",
            },
        ],
        eventuallySucceeds: false,
    },
    mixed_errors: {
        name: "Mixed Error Types",
        description: "Different error types across retries (overloaded, then timeout)",
        errors: [
            {
                type: "overloaded_error",
                message: "Server overloaded",
            },
            {
                type: "api_error",
                message: "ETIMEDOUT: Connection timed out",
            },
        ],
        eventuallySucceeds: true,
        successContent: "✅ Successfully recovered from multiple different error types! The retry middleware handled mixed errors gracefully.",
    },
    partial_stream: {
        name: "Partial Stream Success",
        description: "Stream succeeds partially, then fails with timeout",
        errors: [
            {
                type: "api_error",
                message: "Connection lost mid-stream",
                delayMs: 100, // Simulate some successful streaming first
            },
        ],
        eventuallySucceeds: true,
        successContent: "✅ Successfully recovered from mid-stream failure! The retry middleware restarted the stream from the beginning.",
    },
    thrown_timeout: {
        name: "Thrown Timeout Error",
        description: "Throws timeout error (tests catch block instead of error chunks)",
        errors: [
            {
                type: "api_error",
                message: "ETIMEDOUT: Connection timed out",
                shouldThrow: true,
            },
            {
                type: "api_error",
                message: "ETIMEDOUT: Connection timed out",
                shouldThrow: true,
            },
        ],
        eventuallySucceeds: true,
        successContent: "✅ Successfully recovered from thrown timeout errors! The catch block handled stream failures correctly.",
    },
    thrown_network: {
        name: "Thrown Network Error",
        description: "Throws network error during streaming",
        errors: [
            {
                type: "api_error",
                message: "ECONNRESET: Connection reset by peer",
                shouldThrow: true,
            },
        ],
        eventuallySucceeds: true,
        successContent: "✅ Successfully recovered from thrown network error! Stream was restarted after connection drop.",
    },
    mixed_throw_and_chunk: {
        name: "Mixed Thrown and Chunk Errors",
        description: "First error is a chunk, second error is thrown",
        errors: [
            {
                type: "rate_limit_error",
                message: "Rate limit exceeded",
                shouldThrow: false, // Send as error chunk
            },
            {
                type: "api_error",
                message: "ETIMEDOUT: Connection timed out",
                shouldThrow: true, // Throw this one
            },
        ],
        eventuallySucceeds: true,
        successContent: "✅ Successfully recovered from mixed error types! Both error chunks and thrown errors were handled.",
    },
};
/**
 * Generates an error chunk in the AI SDK format.
 *
 * @param errorType - Standardized error type (e.g., "rate_limit_error")
 * @param message - Error message
 * @returns Error chunk ready to be injected into a stream
 */
export function createErrorChunk(errorType, message) {
    return {
        type: "error",
        error: {
            type: errorType,
            message,
            // Include some provider-specific fields for realism
            ...(errorType === "rate_limit_error" && {
                statusCode: 429,
                headers: {
                    "retry-after": "5",
                },
            }),
            ...(errorType === "overloaded_error" && {
                statusCode: 529,
            }),
            ...(errorType === "authentication_error" && {
                statusCode: 401,
            }),
            ...(errorType === "permission_error" && {
                statusCode: 403,
            }),
            ...(errorType === "invalid_request_error" && {
                statusCode: 400,
            }),
        },
    };
}
/**
 * Generates mock chunks for an error scenario.
 *
 * Creates a sequence of chunks that includes:
 * - Initial step-start
 * - Text content (if partial success before error)
 * - Error chunk
 * - Success chunks (if eventuallySucceeds is true)
 * - Final step-finish/finish chunks
 *
 * @param scenario - The error scenario to generate chunks for
 * @param attemptNumber - Current retry attempt (0-indexed, 0 = first attempt)
 * @returns Array of chunks ready to be streamed
 */
export function generateErrorScenarioChunks(scenario, attemptNumber) {
    const chunks = [];
    // Check if we should inject an error for this attempt
    // If eventuallySucceeds is false, keep repeating the last error
    const errorIndex = scenario.eventuallySucceeds
        ? attemptNumber
        : Math.min(attemptNumber, scenario.errors.length - 1);
    if (errorIndex < scenario.errors.length) {
        const error = scenario.errors[errorIndex];
        // TypeScript safety: ensure error exists
        if (!error) {
            throw new Error(`Error scenario missing error at index ${errorIndex}`);
        }
        // If this error has a delay, add some success content first
        if (error.delayMs) {
            const index = chunks.length;
            chunks.push({
                type: "content_block_start",
                index,
                content_block: {
                    type: "text",
                },
            });
            chunks.push({
                type: "content_block_delta",
                index,
                delta: {
                    type: "text_delta",
                    text: "Streaming started successfully... (simulating partial success before error)",
                },
            });
            chunks.push({
                type: "content_block_stop",
                index,
            });
        }
        // Check if we should throw or send error chunk
        if (error.shouldThrow) {
            // Return a special marker that tells the stream generator to throw
            chunks.push({
                __shouldThrow: true,
                error: new Error(error.message),
            });
        }
        else {
            // Add the error chunk
            chunks.push(createErrorChunk(error.type, error.message));
        }
    }
    else if (scenario.eventuallySucceeds &&
        attemptNumber >= scenario.errors.length) {
        // All errors exhausted, return success
        const successText = scenario.successContent || "Successfully recovered after retry attempts.";
        // Split success content into chunks
        const words = successText.split(" ");
        const index = chunks.length;
        chunks.push({
            type: "content_block_start",
            index,
            content_block: {
                type: "text",
            },
        });
        for (const word of words) {
            chunks.push({
                type: "content_block_delta",
                index,
                delta: {
                    type: "text_delta",
                    text: word + " ",
                },
            });
        }
        chunks.push({
            type: "content_block_stop",
            index,
        });
        // Add finish chunks
        // chunks.push(
        //   {
        //     type: "step-finish",
        //     finishReason: "stop",
        //     usage: { promptTokens: 10, completionTokens: 50, totalTokens: 60 },
        //     request: {},
        //     response: {
        //       id: `aitxt-success-${attemptNumber}`,
        //       modelId: "test-model",
        //       headers: {},
        //     },
        //     warnings: [],
        //     isContinued: false,
        //     messageId: `msg-success-${attemptNumber}`,
        //   },
        //   {
        //     type: "finish",
        //     finishReason: "stop",
        //     usage: { promptTokens: 10, completionTokens: 50, totalTokens: 60 },
        //     response: {
        //       id: `aitxt-success-${attemptNumber}`,
        //       modelId: "test-model",
        //       headers: {},
        //     },
        //   },
        // );
    }
    return chunks;
}
//# sourceMappingURL=error-mocks.js.map