1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
| export interface AIProvider { readonly name: string; createMessage(params: MessageCreateParams): Promise<MessageResponse>; createMessageStream(params: MessageCreateParams): Promise<Response>; }
export class AnthropicProvider implements AIProvider { readonly name = "anthropic"; private client: ApiClient;
constructor(config: { apiKey: string; baseUrl?: string }) { this.client = new ApiClient({ apiKey: config.apiKey, baseUrl: config.baseUrl, }); }
async createMessage(params: MessageCreateParams): Promise<MessageResponse> { return this.client.createMessage(params); }
async createMessageStream(params: MessageCreateParams): Promise<Response> { const response = await fetch(`${this.client.baseUrl}/messages`, { method: "POST", headers: this.client.headers, body: JSON.stringify({ ...params, stream: true }), }); return response; } }
export class OpenAICompatibleProvider implements AIProvider { readonly name = "openai-compatible"; private apiKey: string; private baseUrl: string;
constructor(config: { apiKey: string; baseUrl: string }) { this.apiKey = config.apiKey; this.baseUrl = config.baseUrl; }
async createMessage(params: MessageCreateParams): Promise<MessageResponse> { const openaiParams = this.convertToOpenAI(params); const response = await fetch(`${this.baseUrl}/chat/completions`, { method: "POST", headers: { "Authorization": `Bearer ${this.apiKey}`, "Content-Type": "application/json", }, body: JSON.stringify(openaiParams), }); const data = await response.json(); return this.convertFromOpenAI(data); }
private convertToOpenAI(params: MessageCreateParams): unknown { return { model: params.model, max_tokens: params.max_tokens, messages: params.messages.map(m => ({ role: m.role, content: typeof m.content === "string" ? m.content : JSON.stringify(m.content), })), tools: params.tools?.map(t => ({ type: "function", function: { name: t.name, description: t.description, parameters: t.input_schema, }, })), }; }
private convertFromOpenAI(data: any): MessageResponse { const choice = data.choices[0]; return { id: data.id, type: "message", role: "assistant", model: data.model, content: [{ type: "text", text: choice.message.content }], stop_reason: choice.finish_reason === "tool_calls" ? "tool_use" : "end_turn", stop_sequence: null, usage: { input_tokens: data.usage?.prompt_tokens ?? 0, output_tokens: data.usage?.completion_tokens ?? 0, }, }; } }
export function createProvider(config: AgentConfig): AIProvider { if (config.baseUrl?.includes("openai.com")) { return new OpenAICompatibleProvider({ apiKey: config.apiKey!, baseUrl: config.baseUrl, }); } return new AnthropicProvider({ apiKey: config.apiKey!, baseUrl: config.baseUrl, }); }
|