bolt.diy/app/components/settings/providers/service-status/base-provider.ts
2025-01-30 01:58:47 +01:00

122 lines
3.4 KiB
TypeScript

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<string, string>,
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<StatusCheckResult>;
}