Reformat files. Make thenable iterator generic
This commit is contained in:
136
src/gpt/gpt.ts
Normal file
136
src/gpt/gpt.ts
Normal 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user