Reformat files. Make thenable iterator generic

This commit is contained in:
2026-02-04 04:32:50 +00:00
parent af440dcbc7
commit e68427e53d
8 changed files with 202 additions and 111 deletions

136
src/gpt/gpt.ts Normal file
View File

@@ -0,0 +1,136 @@
import { SSESession } from '../utils/sse-session.js';
import { EventEmitter } from '../utils/event-emitter.js';
import { GPTResponseIterator, type ToolCall, type ToolDefinition } from './gpt-response.js';
export type GPTEventMap = {
/**
* Emitted when a message is sent
*/
messageSent: { mesasge: string };
/**
* Emitted when a message chunk is received
*/
messageChunkReceived: { chunk: string };
/**
* Emitted when a response is received
*/
responseReceived: { response: string };
/**
* Emitted when a tool is called
*/
toolCalled: { toolName: string; arguments: Record<string, unknown>; result: unknown };
}
export type GPTConfig = {
/**
* The API key to use for the GPT API
*/
apiKey: string;
/**
* The API URL to use for the GPT API
*/
apiUrl: string;
/**
* The model to use for the GPT API
*/
model: string;
}
/**
* Message types that can be sent to the GPT API
*/
export type Message =
| {
role: 'user' | 'system';
content: string;
}
| {
role: 'assistant';
content: string | null;
tool_calls?: ToolCall[];
}
| {
role: 'tool';
tool_call_id: string;
name: string;
content: string;
};
/**
* Request configuration for GPT API calls
*/
export type GPTRequest = {
/**
* The messages to send to the GPT API
*/
messages: Message[];
/**
* Optional tool definitions for function calling
*/
tools?: ToolDefinition[];
/**
* Controls which (if any) tool is called by the model
* - 'auto' (default): model decides whether to call a tool
* - 'none': model will not call any tools
* - { type: 'function', function: { name: 'tool_name' } }: forces a specific tool call
*/
tool_choice?: 'auto' | 'none' | { type: 'function'; function: { name: string } };
}
export class GPT extends EventEmitter<GPTEventMap> {
constructor(public config: GPTConfig) {
super();
}
/**
* Sends a message to the GPT API
* @param message - The message to send
* @returns The response from the GPT API
*/
send(request: GPTRequest): GPTResponseIterator {
const config = this.config;
const lazyIterator = (async function* () {
// Build the API request body
const requestBody: Record<string, unknown> = {
model: config.model,
messages: request.messages,
stream: true,
};
// Add tools if provided
if (request.tools && request.tools.length > 0) {
requestBody.tools = request.tools;
}
// Add tool_choice if provided
if (request.tool_choice) {
requestBody.tool_choice = request.tool_choice;
}
const session = await SSESession.from(config.apiUrl, {
headers: {
Authorization: `Bearer ${config.apiKey}`,
},
method: 'POST',
body: JSON.stringify(requestBody),
});
if (!session.messages) {
throw new Error('Failed to create SSE session');
}
yield* session.messages;
})();
return new GPTResponseIterator(lazyIterator);
}
}