import { Logger } from "./Logger"; const BAIDU_AIP_HOST = "https://aip.baidubce.com"; const BAIDU_AIP_OAUTH_HOST = BAIDU_AIP_HOST + "/oauth/2.0/token"; export interface ErnieMessage { role: "user" | "assistant"; content: string } export interface ErnieChatBody { messages: ErnieMessage[]; stream?: boolean; system?: string } export class ErnieAPI { static instances: Map = new Map() private clientId?: string; private clientSecret?: string; private accessToken?: string; private expiresIn?: number; constructor(clientId: string, clientSecret: string) { this.clientId = clientId this.clientSecret = clientSecret this.accessToken = undefined; this.expiresIn = undefined; } static async getInstance(clientId: string, clientSecret: string): Promise { if (!ErnieAPI.instances.get(clientId)) { const ernieAPI = new ErnieAPI(clientId, clientSecret); await ernieAPI.initialize() ErnieAPI.instances.set(clientId, ernieAPI); } return ErnieAPI.instances.get(clientId) as ErnieAPI } private async initialize() { await this.fetchAccessToken(); } private async fetchAccessToken() { if (!this.clientId || !this.clientSecret) { throw new Error('Client ID and Client Secret are required'); } const url = BAIDU_AIP_OAUTH_HOST const params = new URLSearchParams(); params.append('grant_type', 'client_credentials'); params.append('client_id', this.clientId); params.append('client_secret', this.clientSecret); try { const response = await fetch(url, { method: 'POST', body: params }); const data = await response.json(); // Logger.info('Fetching access token:', data); if (response.ok) { if (data.error) { throw new Error(`Error fetching access token: ${data.error_description}`); } this.accessToken = data.access_token; Logger.debug('Access token fetched:', this.accessToken); this.expiresIn = Date.now() + (data.expires_in * 1000); // Convert seconds to milliseconds let expiresIn = this.expiresIn if (expiresIn > 0x7FFFFFFF) { expiresIn = 0x7FFFFFFF - 1 } setTimeout(async () => { await this.fetchAccessToken() }, expiresIn) } else { throw new Error(`Failed to fetch access token: ${data.error_description}`); } } catch (error) { Logger.error('Error fetching access token:', error); throw error; } } async request(params: { method: "GET" | "POST" | "PUT" | "DELETE", url: string, data?: any, }): Promise { const url = BAIDU_AIP_HOST + params.url + "?access_token=" + this.accessToken // Logger.debug('Request:', url, params.data); const response = await fetch(url, { method: params.method, headers: { 'Content-Type': 'application/json' }, body: params.data ? JSON.stringify(params.data) : "" }); return response } }