import type { ProviderConfig, StatusCheckResult, ApiResponse } from './types'; export abstract class BaseProviderChecker { protected config: ProviderConfig; constructor(config: ProviderConfig) { this.config = config; } protected async checkApiEndpoint( url: string, headers?: Record, testModel?: string, ): Promise<{ ok: boolean; status: number | string; message?: string; responseTime: number }> { try { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 10000); const startTime = performance.now(); // Add common headers const processedHeaders = { 'Content-Type': 'application/json', ...headers, }; const response = await fetch(url, { method: 'GET', headers: processedHeaders, signal: controller.signal, }); const endTime = performance.now(); const responseTime = endTime - startTime; clearTimeout(timeoutId); const data = (await response.json()) as ApiResponse; if (!response.ok) { let errorMessage = `API returned status: ${response.status}`; if (data.error?.message) { errorMessage = data.error.message; } else if (data.message) { errorMessage = data.message; } return { ok: false, status: response.status, message: errorMessage, responseTime, }; } // Different providers have different model list formats let models: string[] = []; if (Array.isArray(data)) { models = data.map((model: { id?: string; name?: string }) => model.id || model.name || ''); } else if (data.data && Array.isArray(data.data)) { models = data.data.map((model) => model.id || model.name || ''); } else if (data.models && Array.isArray(data.models)) { models = data.models.map((model) => model.id || model.name || ''); } else if (data.model) { models = [data.model]; } if (!testModel || models.length > 0) { return { ok: true, status: response.status, responseTime, message: 'API key is valid', }; } if (testModel && !models.includes(testModel)) { return { ok: true, status: 'model_not_found', message: `API key is valid (test model ${testModel} not found in ${models.length} available models)`, responseTime, }; } return { ok: true, status: response.status, message: 'API key is valid', responseTime, }; } catch (error) { console.error(`Error checking API endpoint ${url}:`, error); return { ok: false, status: error instanceof Error ? error.message : 'Unknown error', message: error instanceof Error ? `Connection failed: ${error.message}` : 'Connection failed', responseTime: 0, }; } } protected async checkEndpoint(url: string): Promise<'reachable' | 'unreachable'> { try { const response = await fetch(url, { mode: 'no-cors', headers: { Accept: 'text/html', }, }); return response.type === 'opaque' ? 'reachable' : 'unreachable'; } catch (error) { console.error(`Error checking ${url}:`, error); return 'unreachable'; } } abstract checkStatus(): Promise; }