/** * Provider Adapter — 基类 * * 所有 Provider 适配器共享的基类逻辑: * - 请求超时处理 * - 错误映射到 MetonaError * - 流式事件标准化 */ import type { IMetonaProviderAdapter, AdapterConfig, MetonaRequest, MetonaResponse, MetonaStreamEvent, MetonaError, } from '../types'; import { MetonaErrorCode } from '../types'; export abstract class BaseAdapter implements IMetonaProviderAdapter { abstract readonly provider: string; abstract readonly supportedModels: string[]; abstract readonly supportsToolCalling: boolean; abstract readonly supportsThinking: boolean; constructor(protected config: AdapterConfig) {} abstract chat(request: MetonaRequest): Promise; abstract chatStream(request: MetonaRequest): AsyncIterable; async healthCheck(): Promise { try { await this.listModels?.(); return true; } catch { return false; } } async listModels(): Promise { return this.supportedModels; } /** * 将原生错误映射为 MetonaError */ protected mapError(error: unknown): MetonaError { if (error instanceof Error) { const msg = error.message.toLowerCase(); if (msg.includes('timeout') || msg.includes('ETIMEDOUT')) { return { code: MetonaErrorCode.NETWORK_TIMEOUT, message: error.message, provider: this.provider, retryable: true, retryAfterMs: 3000, }; } if (msg.includes('401') || msg.includes('unauthorized')) { return { code: MetonaErrorCode.AUTH_INVALID, message: 'API key 无效或已过期', provider: this.provider, retryable: false, }; } if (msg.includes('429') || msg.includes('rate limit')) { return { code: MetonaErrorCode.RATE_LIMITED, message: '请求过于频繁,请稍后重试', provider: this.provider, retryable: true, retryAfterMs: 5000, }; } } return { code: MetonaErrorCode.UNKNOWN, message: error instanceof Error ? error.message : 'Unknown error', provider: this.provider, retryable: false, }; } }