@robota-sdk/openai
Version:
OpenAI integration for Robota SDK - GPT-4, GPT-3.5, function calling, and tool integration with OpenAI's API
293 lines (287 loc) • 9.66 kB
text/typescript
import OpenAI from 'openai';
import { ProviderOptions, BaseAIProvider, Context, ModelResponse, StreamingResponseChunk, UniversalMessage } from '@robota-sdk/core';
import { FunctionSchema } from '@robota-sdk/tools';
/**
* OpenAI provider options
*/
interface OpenAIProviderOptions extends ProviderOptions {
/**
* Model name to use (default: gpt-3.5-turbo)
*/
model: string;
/**
* Temperature (0~1)
*/
temperature?: number;
/**
* Maximum number of tokens
*/
maxTokens?: number;
/**
* OpenAI API key (optional: not required when using client)
*/
apiKey?: string;
/**
* OpenAI organization ID (optional)
*/
organization?: string;
/**
* API request timeout (milliseconds)
*/
timeout?: number;
/**
* API base URL (default: 'https://api.openai.com/v1')
*/
baseURL?: string;
/**
* Response format (default: 'text')
* - 'text': Plain text response
* - 'json_object': Legacy JSON mode (requires system message)
* - 'json_schema': Structured Outputs with schema validation
*/
responseFormat?: 'text' | 'json_object' | 'json_schema';
/**
* JSON schema for structured outputs (required when responseFormat is 'json_schema')
*/
jsonSchema?: {
name: string;
description?: string;
schema?: Record<string, unknown>;
strict?: boolean;
};
/**
* OpenAI client instance (required)
*/
client: OpenAI;
/**
* Enable API payload logging to files
* When enabled, saves API request payloads to log files
*
* @defaultValue false
*/
enablePayloadLogging?: boolean;
/**
* Directory path for storing API payload log files
*
* @defaultValue './logs/api-payloads'
*/
payloadLogDir?: string;
/**
* Include timestamp in payload log filenames
*
* @defaultValue true
*/
includeTimestampInLogFiles?: boolean;
}
/**
* OpenAI AI provider implementation for Robota
*
* Provides integration with OpenAI's GPT models and other services.
* Extends BaseAIProvider for common functionality and tool calling support.
*
* @see {@link ../../../apps/examples/03-integrations | Provider Integration Examples}
*
* @public
*/
declare class OpenAIProvider extends BaseAIProvider {
/**
* Provider identifier name
* @readonly
*/
readonly name: string;
/**
* OpenAI client instance
* @internal
*/
private readonly client;
/**
* Client type identifier
* @readonly
*/
readonly type: string;
/**
* OpenAI client instance (alias for backwards compatibility)
* @readonly
* @deprecated Use the private client property instead
*/
readonly instance: OpenAI;
/**
* Provider configuration options
* @readonly
*/
readonly options: OpenAIProviderOptions;
/**
* Payload logger for API request logging
* @internal
*/
private readonly payloadLogger;
/**
* Create a new OpenAI provider instance
*
* @param options - Configuration options for the OpenAI provider
*
* @throws {Error} When client is not provided in options
*/
constructor(options: OpenAIProviderOptions);
/**
* Convert function definitions to OpenAI tool format
*
* Transforms universal function definitions into OpenAI's specific tool format
* required by the Chat Completions API.
*
* @param functions - Array of universal function definitions
* @returns Array of OpenAI-formatted tools
*/
formatFunctions(functions: FunctionSchema[]): OpenAI.Chat.ChatCompletionTool[];
/**
* Filter conversation history for OpenAI API compatibility
*
* Converts messages to OpenAI format and filters out invalid tool messages.
*
* @param messages - Array of messages to filter
* @returns OpenAI-formatted messages array
*/
private filterHistory;
/**
* Configure tools for OpenAI API request
*
* Transforms function schemas into OpenAI tool format and sets tool_choice.
*
* @param tools - Array of function schemas
* @returns OpenAI tool configuration object
*/
protected configureTools(tools?: FunctionSchema[]): {
tools: OpenAI.Chat.ChatCompletionTool[];
tool_choice: 'auto';
} | undefined;
/**
* Send a chat request to OpenAI and receive a complete response
*
* Processes the provided context and sends it to OpenAI's Chat Completions API.
* Handles message format conversion, error handling, and response parsing.
*
* @param model - Model name to use (e.g., 'gpt-4', 'gpt-3.5-turbo')
* @param context - Context object containing messages and system prompt
* @param options - Optional generation parameters and tools
* @returns Promise resolving to the model's response
*
* @throws {Error} When context is invalid
* @throws {Error} When messages array is invalid
* @throws {Error} When message format conversion fails
* @throws {Error} When OpenAI API call fails
*/
chat(model: string, context: Context, options?: any): Promise<ModelResponse>;
/**
* Convert OpenAI API response to universal ModelResponse format
*
* Transforms the OpenAI-specific response format into the standard format
* used across all providers in Robota.
*
* @param response - Raw response from OpenAI Chat Completions API
* @returns Parsed model response in universal format
*
* @internal
*/
parseResponse(response: OpenAI.Chat.ChatCompletion): ModelResponse;
/**
* Convert OpenAI streaming response chunk to universal format
*
* Transforms individual chunks from OpenAI's streaming response into the
* standard StreamingResponseChunk format used across all providers.
*
* @param chunk - Raw chunk from OpenAI streaming API
* @returns Parsed streaming response chunk
*
* @internal
*/
parseStreamingChunk(chunk: OpenAI.Chat.ChatCompletionChunk): StreamingResponseChunk;
/**
* Send a streaming chat request to OpenAI and receive response chunks
*
* Similar to chat() but returns an async iterator that yields response chunks
* as they arrive from OpenAI's streaming API. Useful for real-time display
* of responses or handling large responses incrementally.
*
* @param model - Model name to use
* @param context - Context object containing messages and system prompt
* @param options - Optional generation parameters and tools
* @returns Async generator yielding response chunks
*
* @throws {Error} When context is invalid
* @throws {Error} When messages array is invalid
* @throws {Error} When message format conversion fails
* @throws {Error} When OpenAI streaming API call fails
*
* @see {@link ../../../apps/examples/01-basic | Basic Usage Examples}
*/
chatStream(model: string, context: Context, options?: any): AsyncGenerator<StreamingResponseChunk, void, unknown>;
/**
* Release resources and close connections
*
* Performs cleanup operations when the provider is no longer needed.
* OpenAI client doesn't require explicit cleanup, so this is a no-op.
*
* @returns Promise that resolves when cleanup is complete
*/
close(): Promise<void>;
}
/**
* OpenAI ConversationHistory adapter
*
* Converts UniversalMessage to OpenAI Chat Completions API format
*/
declare class OpenAIConversationAdapter {
/**
* Filter messages for OpenAI compatibility
*
* OpenAI has specific requirements:
* - Tool messages must have valid toolCallId
* - Messages must be in proper sequence
* - Tool messages without toolCallId should be excluded
*/
static filterMessagesForOpenAI(messages: UniversalMessage[]): UniversalMessage[];
/**
* Convert UniversalMessage array to OpenAI message format
* Now properly handles tool messages for OpenAI's tool calling feature
*/
static toOpenAIFormat(messages: UniversalMessage[]): OpenAI.Chat.ChatCompletionMessageParam[];
/**
* Convert a single UniversalMessage to OpenAI format
* Handles all message types including tool messages
*/
static convertMessage(msg: UniversalMessage): OpenAI.Chat.ChatCompletionMessageParam;
/**
* Add system prompt to message array if needed
*/
static addSystemPromptIfNeeded(messages: OpenAI.Chat.ChatCompletionMessageParam[], systemPrompt?: string): OpenAI.Chat.ChatCompletionMessageParam[];
}
/**
* Utility class for logging OpenAI API payloads to files
*/
declare class PayloadLogger {
private readonly enabled;
private readonly logDir;
private readonly includeTimestamp;
constructor(enabled?: boolean, logDir?: string, includeTimestamp?: boolean);
/**
* Log API payload to file
* @param payload - The API request payload
* @param type - Type of request ('chat' or 'stream')
*/
logPayload(payload: any, type?: 'chat' | 'stream'): Promise<void>;
/**
* Ensure log directory exists
*/
private ensureLogDirectoryExists;
/**
* Sanitize payload to remove sensitive information
* @param payload - Raw payload object
* @returns Sanitized payload
*/
private sanitizePayload;
/**
* Check if logging is enabled
*/
isEnabled(): boolean;
}
export { OpenAIConversationAdapter, OpenAIProvider, type OpenAIProviderOptions, PayloadLogger };