- 移除 radix-ui、clsx、tailwind-merge、class-variance-authority、react-router-dom - 前后端全面适配 MUI 组件,清理残留 Tailwind 工具类引用 - 优化 Agent Loop 引擎、IPC 处理器、Provider Adapter 等后端模块 - 新增 Agent 网络工具通用设计文档 v2
99 lines
2.5 KiB
TypeScript
99 lines
2.5 KiB
TypeScript
/**
|
|
* 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<MetonaResponse>;
|
|
abstract chatStream(request: MetonaRequest): AsyncIterable<MetonaStreamEvent>;
|
|
|
|
async healthCheck(): Promise<boolean> {
|
|
try {
|
|
await this.listModels();
|
|
return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
async listModels(): Promise<string[]> {
|
|
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('ECONNREFUSED') || msg.includes('ENOTFOUND') || msg.includes('ECONNRESET')) {
|
|
return {
|
|
code: MetonaErrorCode.NETWORK_ERROR,
|
|
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,
|
|
};
|
|
}
|
|
}
|