/**
 * API Key Tester Service
 * Shared module for testing API key connectivity across different provider types.
 * Used by both manual testing (litellm-api-routes.ts) and health check service.
 */
/**
 * Validate API base URL format
 * Note: This is a local development tool, so we allow localhost and internal networks
 * for users who run local API gateways or proxies.
 * @param url - The URL to validate
 * @returns Object with valid flag and optional error message
 */
export function validateApiBaseUrl(url) {
    try {
        const parsed = new URL(url);
        // Must be HTTP or HTTPS
        if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {
            return { valid: false, error: 'URL must use HTTP or HTTPS protocol' };
        }
        return { valid: true };
    }
    catch {
        return { valid: false, error: 'Invalid URL format' };
    }
}
/**
 * Get default API base URL for a provider type
 */
export function getDefaultApiBase(providerType) {
    const defaults = {
        openai: 'https://api.openai.com/v1',
        anthropic: 'https://api.anthropic.com/v1',
        custom: 'https://api.openai.com/v1', // Assume OpenAI-compatible by default
    };
    return defaults[providerType] || defaults.openai;
}
/**
 * Test API key connection by making a minimal API request
 * @param providerType - The type of provider (openai, anthropic, custom)
 * @param apiBase - The base URL for the API
 * @param apiKey - The API key to test
 * @param timeout - Timeout in milliseconds (default: 10000)
 * @returns TestResult indicating if the key is valid
 */
export async function testApiKeyConnection(providerType, apiBase, apiKey, timeout = 10000) {
    // Validate URL to prevent SSRF
    const urlValidation = validateApiBaseUrl(apiBase);
    if (!urlValidation.valid) {
        return { valid: false, error: urlValidation.error };
    }
    // Normalize apiBase: remove trailing slashes to prevent URL construction issues
    // e.g., "https://api.openai.com/v1/" -> "https://api.openai.com/v1"
    const normalizedApiBase = apiBase.replace(/\/+$/, '');
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), timeout);
    const startTime = Date.now();
    try {
        if (providerType === 'anthropic') {
            // Anthropic format: Use /v1/models endpoint (no cost, no model dependency)
            // This validates the API key without making a billable request
            const response = await fetch(`${normalizedApiBase}/models`, {
                method: 'GET',
                headers: {
                    'x-api-key': apiKey,
                    'anthropic-version': '2023-06-01',
                },
                signal: controller.signal,
            });
            clearTimeout(timeoutId);
            const latencyMs = Date.now() - startTime;
            if (response.ok) {
                return { valid: true, latencyMs };
            }
            // Parse error response
            const errorBody = await response.json().catch(() => ({}));
            const errorMessage = errorBody?.error?.message || response.statusText;
            // 401 = invalid API key
            if (response.status === 401) {
                return { valid: false, error: 'Invalid API key' };
            }
            if (response.status === 403) {
                return { valid: false, error: 'Access denied - check API key permissions' };
            }
            if (response.status === 429) {
                // Rate limited means the key is valid but being throttled
                return { valid: true, latencyMs };
            }
            return { valid: false, error: errorMessage };
        }
        else {
            // OpenAI-compatible format: GET /v{N}/models
            // Detect if URL already ends with a version pattern like /v1, /v2, /v4, etc.
            const hasVersionSuffix = /\/v\d+$/.test(normalizedApiBase);
            const modelsUrl = hasVersionSuffix ? `${normalizedApiBase}/models` : `${normalizedApiBase}/v1/models`;
            const response = await fetch(modelsUrl, {
                method: 'GET',
                headers: {
                    'Authorization': `Bearer ${apiKey}`,
                },
                signal: controller.signal,
            });
            clearTimeout(timeoutId);
            const latencyMs = Date.now() - startTime;
            if (response.ok) {
                return { valid: true, latencyMs };
            }
            // Parse error response
            const errorBody = await response.json().catch(() => ({}));
            const errorMessage = errorBody?.error?.message || response.statusText;
            if (response.status === 401) {
                return { valid: false, error: 'Invalid API key' };
            }
            if (response.status === 403) {
                return { valid: false, error: 'Access denied - check API key permissions' };
            }
            if (response.status === 429) {
                // Rate limited means the key is valid but being throttled
                return { valid: true, latencyMs };
            }
            return { valid: false, error: errorMessage };
        }
    }
    catch (err) {
        clearTimeout(timeoutId);
        if (err.name === 'AbortError') {
            return { valid: false, error: 'Connection timed out' };
        }
        return { valid: false, error: `Connection failed: ${err.message}` };
    }
}
//# sourceMappingURL=api-key-tester.js.map