@providerprotocol/ai 0.0.15 → 0.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/anthropic/index.d.ts +1 -1
- package/dist/google/index.d.ts +1 -1
- package/dist/http/index.d.ts +2 -2
- package/dist/index.d.ts +22 -5
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/ollama/index.d.ts +1 -1
- package/dist/openai/index.d.ts +2 -1
- package/dist/openai/index.js.map +1 -1
- package/dist/openrouter/index.d.ts +46 -1
- package/dist/openrouter/index.js +78 -17
- package/dist/openrouter/index.js.map +1 -1
- package/dist/{provider-Bi0nyNhA.d.ts → provider-vTZ74u-w.d.ts} +1 -1
- package/dist/{retry-BatS2hjD.d.ts → retry-CMdT0kD8.d.ts} +1 -1
- package/dist/xai/index.d.ts +1 -1
- package/package.json +1 -1
package/dist/openai/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/providers/openai/transform.completions.ts","../../src/providers/openai/llm.completions.ts","../../src/providers/openai/transform.responses.ts","../../src/providers/openai/llm.responses.ts","../../src/providers/openai/types.ts","../../src/providers/openai/index.ts"],"sourcesContent":["/**\n * @fileoverview Chat Completions API Message Transformers\n *\n * This module provides transformation functions for converting between the\n * Universal Provider Protocol (UPP) message format and OpenAI's Chat Completions\n * API format. It handles both request transformation (UPP -> OpenAI) and response\n * transformation (OpenAI -> UPP), including streaming event transformation.\n *\n * Key transformations handled:\n * - Message format conversion (user, assistant, system, tool messages)\n * - Content block handling (text, images)\n * - Tool/function definition and call transformation\n * - Structured output (JSON schema) configuration\n * - Streaming state accumulation and event mapping\n *\n * @module providers/openai/transform.completions\n */\n\nimport type { LLMRequest, LLMResponse } from '../../types/llm.ts';\nimport type { Message } from '../../types/messages.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport type { Tool, ToolCall } from '../../types/tool.ts';\nimport type { TokenUsage } from '../../types/turn.ts';\nimport type { ContentBlock, TextBlock, ImageBlock } from '../../types/content.ts';\nimport {\n AssistantMessage,\n isUserMessage,\n isAssistantMessage,\n isToolResultMessage,\n} from '../../types/messages.ts';\nimport type {\n OpenAICompletionsParams,\n OpenAICompletionsRequest,\n OpenAICompletionsMessage,\n OpenAIUserContent,\n OpenAICompletionsTool,\n OpenAICompletionsResponse,\n OpenAICompletionsStreamChunk,\n OpenAIToolCall,\n} from './types.ts';\n\n/**\n * Transforms a UPP LLM request into OpenAI Chat Completions API format.\n *\n * This function converts the universal request format to OpenAI's specific\n * structure. Parameters are spread directly to support pass-through of any\n * OpenAI API fields, enabling use of new API features without library updates.\n *\n * @param request - The UPP LLM request containing messages, tools, and configuration\n * @param modelId - The OpenAI model identifier (e.g., 'gpt-4o', 'gpt-4-turbo')\n * @returns An OpenAI Chat Completions API request body\n *\n * @example\n * ```typescript\n * const openaiRequest = transformRequest({\n * messages: [userMessage('Hello!')],\n * params: { temperature: 0.7, max_tokens: 1000 },\n * config: { apiKey: 'sk-...' }\n * }, 'gpt-4o');\n * ```\n */\nexport function transformRequest(\n request: LLMRequest<OpenAICompletionsParams>,\n modelId: string\n): OpenAICompletionsRequest {\n const params = request.params ?? ({} as OpenAICompletionsParams);\n\n const openaiRequest: OpenAICompletionsRequest = {\n ...params,\n model: modelId,\n messages: transformMessages(request.messages, request.system),\n };\n\n if (request.tools && request.tools.length > 0) {\n openaiRequest.tools = request.tools.map(transformTool);\n }\n\n if (request.structure) {\n const schema: Record<string, unknown> = {\n type: 'object',\n properties: request.structure.properties,\n required: request.structure.required,\n ...(request.structure.additionalProperties !== undefined\n ? { additionalProperties: request.structure.additionalProperties }\n : { additionalProperties: false }),\n };\n if (request.structure.description) {\n schema.description = request.structure.description;\n }\n\n openaiRequest.response_format = {\n type: 'json_schema',\n json_schema: {\n name: 'json_response',\n description: request.structure.description,\n schema,\n strict: true,\n },\n };\n }\n\n return openaiRequest;\n}\n\n/**\n * Normalizes system prompt to string.\n * Converts array format to concatenated string for providers that only support strings.\n */\nfunction normalizeSystem(system: string | unknown[] | undefined): string | undefined {\n if (!system) return undefined;\n if (typeof system === 'string') return system;\n // Array format: extract text from each block and join\n return (system as Array<{text?: string}>)\n .map(block => block.text ?? '')\n .filter(text => text.length > 0)\n .join('\\n\\n');\n}\n\n/**\n * Transforms UPP messages to OpenAI Chat Completions message format.\n *\n * Handles system prompt injection as the first message and processes\n * all message types including tool result messages which may expand\n * into multiple OpenAI messages.\n *\n * @param messages - Array of UPP messages to transform\n * @param system - Optional system prompt (string or array, normalized to string)\n * @returns Array of OpenAI-formatted messages\n */\nfunction transformMessages(\n messages: Message[],\n system?: string | unknown[]\n): OpenAICompletionsMessage[] {\n const result: OpenAICompletionsMessage[] = [];\n const normalizedSystem = normalizeSystem(system);\n\n if (normalizedSystem) {\n result.push({\n role: 'system',\n content: normalizedSystem,\n });\n }\n\n for (const message of messages) {\n if (isToolResultMessage(message)) {\n const toolMessages = transformToolResults(message);\n result.push(...toolMessages);\n } else {\n const transformed = transformMessage(message);\n if (transformed) {\n result.push(transformed);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Filters content blocks to only include those with a valid type property.\n *\n * @param content - Array of content blocks to filter\n * @returns Filtered array containing only valid content blocks\n */\nfunction filterValidContent<T extends { type?: string }>(content: T[]): T[] {\n return content.filter((c) => c && typeof c.type === 'string');\n}\n\n/**\n * Transforms a single UPP message to OpenAI Chat Completions format.\n *\n * Handles user, assistant, and tool result messages. For user messages,\n * optimizes to use simple string content when possible. For assistant\n * messages, extracts text and tool calls.\n *\n * @param message - The UPP message to transform\n * @returns The transformed OpenAI message, or null if transformation fails\n */\nfunction transformMessage(message: Message): OpenAICompletionsMessage | null {\n if (isUserMessage(message)) {\n const validContent = filterValidContent(message.content);\n if (validContent.length === 1 && validContent[0]?.type === 'text') {\n return {\n role: 'user',\n content: (validContent[0] as TextBlock).text,\n };\n }\n return {\n role: 'user',\n content: validContent.map(transformContentBlock),\n };\n }\n\n if (isAssistantMessage(message)) {\n const validContent = filterValidContent(message.content);\n const textContent = validContent\n .filter((c): c is TextBlock => c.type === 'text')\n .map((c) => c.text)\n .join('');\n\n const assistantMessage: OpenAICompletionsMessage = {\n role: 'assistant',\n content: textContent || null,\n };\n\n if (message.toolCalls && message.toolCalls.length > 0) {\n (assistantMessage as { tool_calls?: OpenAIToolCall[] }).tool_calls =\n message.toolCalls.map((call) => ({\n id: call.toolCallId,\n type: 'function' as const,\n function: {\n name: call.toolName,\n arguments: JSON.stringify(call.arguments),\n },\n }));\n }\n\n return assistantMessage;\n }\n\n if (isToolResultMessage(message)) {\n const results = message.results.map((result) => ({\n role: 'tool' as const,\n tool_call_id: result.toolCallId,\n content:\n typeof result.result === 'string'\n ? result.result\n : JSON.stringify(result.result),\n }));\n\n return results[0] ?? null;\n }\n\n return null;\n}\n\n/**\n * Transforms tool result messages into multiple OpenAI tool messages.\n *\n * OpenAI requires each tool result to be sent as a separate message with\n * a `tool` role. This function expands a single UPP tool result message\n * containing multiple results into the corresponding OpenAI messages.\n *\n * @param message - The UPP message to transform (should be a tool result message)\n * @returns Array of OpenAI tool messages\n */\nexport function transformToolResults(\n message: Message\n): OpenAICompletionsMessage[] {\n if (!isToolResultMessage(message)) {\n const single = transformMessage(message);\n return single ? [single] : [];\n }\n\n return message.results.map((result) => ({\n role: 'tool' as const,\n tool_call_id: result.toolCallId,\n content:\n typeof result.result === 'string'\n ? result.result\n : JSON.stringify(result.result),\n }));\n}\n\n/**\n * Transforms a UPP content block to OpenAI user content format.\n *\n * Handles text and image content blocks. Images are converted to\n * data URLs for base64 and bytes sources, or passed through for URL sources.\n *\n * @param block - The content block to transform\n * @returns The transformed OpenAI content part\n * @throws Error if the content type is unsupported or image source type is unknown\n */\nfunction transformContentBlock(block: ContentBlock): OpenAIUserContent {\n switch (block.type) {\n case 'text':\n return { type: 'text', text: block.text };\n\n case 'image': {\n const imageBlock = block as ImageBlock;\n let url: string;\n\n if (imageBlock.source.type === 'base64') {\n url = `data:${imageBlock.mimeType};base64,${imageBlock.source.data}`;\n } else if (imageBlock.source.type === 'url') {\n url = imageBlock.source.url;\n } else if (imageBlock.source.type === 'bytes') {\n const base64 = btoa(\n Array.from(imageBlock.source.data)\n .map((b) => String.fromCharCode(b))\n .join('')\n );\n url = `data:${imageBlock.mimeType};base64,${base64}`;\n } else {\n throw new Error('Unknown image source type');\n }\n\n return {\n type: 'image_url',\n image_url: { url },\n };\n }\n\n default:\n throw new Error(`Unsupported content type: ${block.type}`);\n }\n}\n\n/**\n * Extracts OpenAI-specific options from tool metadata.\n *\n * @param tool - The tool to extract options from\n * @returns The OpenAI options if present (currently supports `strict`)\n */\nfunction extractToolOptions(tool: Tool): { strict?: boolean } {\n const openaiMeta = tool.metadata?.openai as\n | { strict?: boolean }\n | undefined;\n return { strict: openaiMeta?.strict };\n}\n\n/**\n * Transforms a UPP tool definition to OpenAI function tool format.\n *\n * OpenAI's Chat Completions API expects tools as function definitions\n * with JSON Schema parameters.\n *\n * Strict mode can be specified via tool metadata:\n * ```typescript\n * const tool: Tool = {\n * name: 'get_weather',\n * description: 'Get weather for a location',\n * parameters: {...},\n * metadata: { openai: { strict: true } },\n * run: async (params) => {...}\n * };\n * ```\n *\n * @param tool - The UPP tool definition\n * @returns The transformed OpenAI function tool\n */\nfunction transformTool(tool: Tool): OpenAICompletionsTool {\n const { strict } = extractToolOptions(tool);\n\n return {\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: {\n type: 'object',\n properties: tool.parameters.properties,\n required: tool.parameters.required,\n ...(tool.parameters.additionalProperties !== undefined\n ? { additionalProperties: tool.parameters.additionalProperties }\n : {}),\n },\n ...(strict !== undefined ? { strict } : {}),\n },\n };\n}\n\n/**\n * Transforms an OpenAI Chat Completions response to UPP LLMResponse format.\n *\n * Extracts the first choice from the response and converts it to the universal\n * format, including text content, tool calls, usage statistics, and stop reason.\n * Also attempts to parse JSON content for structured output responses.\n *\n * @param data - The raw OpenAI Chat Completions API response\n * @returns The transformed UPP LLM response\n * @throws Error if the response contains no choices\n */\nexport function transformResponse(data: OpenAICompletionsResponse): LLMResponse {\n const choice = data.choices[0];\n if (!choice) {\n throw new Error('No choices in OpenAI response');\n }\n\n const textContent: TextBlock[] = [];\n let structuredData: unknown;\n if (choice.message.content) {\n textContent.push({ type: 'text', text: choice.message.content });\n try {\n structuredData = JSON.parse(choice.message.content);\n } catch {\n // Not JSON - expected for non-structured responses\n }\n }\n let hadRefusal = false;\n if (choice.message.refusal) {\n textContent.push({ type: 'text', text: choice.message.refusal });\n hadRefusal = true;\n }\n\n const toolCalls: ToolCall[] = [];\n if (choice.message.tool_calls) {\n for (const call of choice.message.tool_calls) {\n let args: Record<string, unknown> = {};\n try {\n args = JSON.parse(call.function.arguments);\n } catch {\n // Invalid JSON - use empty object\n }\n toolCalls.push({\n toolCallId: call.id,\n toolName: call.function.name,\n arguments: args,\n });\n }\n }\n\n const message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: data.id,\n metadata: {\n openai: {\n model: data.model,\n finish_reason: choice.finish_reason,\n system_fingerprint: data.system_fingerprint,\n service_tier: data.service_tier,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: data.usage.prompt_tokens,\n outputTokens: data.usage.completion_tokens,\n totalTokens: data.usage.total_tokens,\n cacheReadTokens: data.usage.prompt_tokens_details?.cached_tokens ?? 0,\n cacheWriteTokens: 0,\n };\n\n let stopReason = 'end_turn';\n switch (choice.finish_reason) {\n case 'stop':\n stopReason = 'end_turn';\n break;\n case 'length':\n stopReason = 'max_tokens';\n break;\n case 'tool_calls':\n stopReason = 'tool_use';\n break;\n case 'content_filter':\n stopReason = 'content_filter';\n break;\n }\n if (hadRefusal && stopReason !== 'content_filter') {\n stopReason = 'content_filter';\n }\n\n return {\n message,\n usage,\n stopReason,\n data: structuredData,\n };\n}\n\n/**\n * Mutable state object for accumulating data during streaming responses.\n *\n * As streaming chunks arrive, this state object is updated to build up\n * the complete response. It tracks text content, tool calls, token usage,\n * and other metadata needed to construct the final LLMResponse.\n */\nexport interface CompletionsStreamState {\n /** Response ID from the first chunk */\n id: string;\n /** Model identifier */\n model: string;\n /** Accumulated text content */\n text: string;\n /** Map of tool call index to accumulated tool call data */\n toolCalls: Map<number, { id: string; name: string; arguments: string }>;\n /** The finish reason when streaming completes */\n finishReason: string | null;\n /** Input token count (from usage chunk) */\n inputTokens: number;\n /** Output token count (from usage chunk) */\n outputTokens: number;\n /** Number of tokens read from cache */\n cacheReadTokens: number;\n /** Whether a refusal was encountered */\n hadRefusal: boolean;\n}\n\n/**\n * Creates a fresh stream state object for a new streaming session.\n *\n * @returns A new CompletionsStreamState with all fields initialized\n */\nexport function createStreamState(): CompletionsStreamState {\n return {\n id: '',\n model: '',\n text: '',\n toolCalls: new Map(),\n finishReason: null,\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n hadRefusal: false,\n };\n}\n\n/**\n * Transforms an OpenAI streaming chunk into UPP stream events.\n *\n * Processes each chunk from the SSE stream, updating the accumulated state\n * and emitting corresponding UPP events. A single chunk may produce multiple\n * events (e.g., both text and tool call deltas).\n *\n * @param chunk - The OpenAI streaming chunk to process\n * @param state - The mutable state object to update\n * @returns Array of UPP stream events generated from this chunk\n */\nexport function transformStreamEvent(\n chunk: OpenAICompletionsStreamChunk,\n state: CompletionsStreamState\n): StreamEvent[] {\n const events: StreamEvent[] = [];\n\n if (chunk.id && !state.id) {\n state.id = chunk.id;\n events.push({ type: 'message_start', index: 0, delta: {} });\n }\n if (chunk.model) {\n state.model = chunk.model;\n }\n\n const choice = chunk.choices[0];\n if (choice) {\n if (choice.delta.content) {\n state.text += choice.delta.content;\n events.push({\n type: 'text_delta',\n index: 0,\n delta: { text: choice.delta.content },\n });\n }\n if (choice.delta.refusal) {\n state.hadRefusal = true;\n state.text += choice.delta.refusal;\n events.push({\n type: 'text_delta',\n index: 0,\n delta: { text: choice.delta.refusal },\n });\n }\n\n if (choice.delta.tool_calls) {\n for (const toolCallDelta of choice.delta.tool_calls) {\n const index = toolCallDelta.index;\n let toolCall = state.toolCalls.get(index);\n\n if (!toolCall) {\n toolCall = { id: '', name: '', arguments: '' };\n state.toolCalls.set(index, toolCall);\n }\n\n if (toolCallDelta.id) {\n toolCall.id = toolCallDelta.id;\n }\n if (toolCallDelta.function?.name) {\n toolCall.name = toolCallDelta.function.name;\n }\n if (toolCallDelta.function?.arguments) {\n toolCall.arguments += toolCallDelta.function.arguments;\n events.push({\n type: 'tool_call_delta',\n index: index,\n delta: {\n toolCallId: toolCall.id,\n toolName: toolCall.name,\n argumentsJson: toolCallDelta.function.arguments,\n },\n });\n }\n }\n }\n\n if (choice.finish_reason) {\n state.finishReason = choice.finish_reason;\n events.push({ type: 'message_stop', index: 0, delta: {} });\n }\n }\n\n if (chunk.usage) {\n state.inputTokens = chunk.usage.prompt_tokens;\n state.outputTokens = chunk.usage.completion_tokens;\n state.cacheReadTokens = chunk.usage.prompt_tokens_details?.cached_tokens ?? 0;\n }\n\n return events;\n}\n\n/**\n * Builds a complete LLMResponse from accumulated streaming state.\n *\n * Called after all streaming chunks have been processed to construct\n * the final response object with all accumulated content, tool calls,\n * and usage statistics.\n *\n * @param state - The accumulated stream state\n * @returns A complete UPP LLMResponse\n */\nexport function buildResponseFromState(state: CompletionsStreamState): LLMResponse {\n const textContent: TextBlock[] = [];\n let structuredData: unknown;\n if (state.text) {\n textContent.push({ type: 'text', text: state.text });\n try {\n structuredData = JSON.parse(state.text);\n } catch {\n // Not JSON - expected for non-structured responses\n }\n }\n\n const toolCalls: ToolCall[] = [];\n for (const [, toolCall] of state.toolCalls) {\n let args: Record<string, unknown> = {};\n if (toolCall.arguments) {\n try {\n args = JSON.parse(toolCall.arguments);\n } catch {\n // Invalid JSON - use empty object\n }\n }\n toolCalls.push({\n toolCallId: toolCall.id,\n toolName: toolCall.name,\n arguments: args,\n });\n }\n\n const message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: state.id,\n metadata: {\n openai: {\n model: state.model,\n finish_reason: state.finishReason,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.inputTokens + state.outputTokens,\n cacheReadTokens: state.cacheReadTokens,\n cacheWriteTokens: 0,\n };\n\n let stopReason = 'end_turn';\n switch (state.finishReason) {\n case 'stop':\n stopReason = 'end_turn';\n break;\n case 'length':\n stopReason = 'max_tokens';\n break;\n case 'tool_calls':\n stopReason = 'tool_use';\n break;\n case 'content_filter':\n stopReason = 'content_filter';\n break;\n }\n if (state.hadRefusal && stopReason !== 'content_filter') {\n stopReason = 'content_filter';\n }\n\n return {\n message,\n usage,\n stopReason,\n data: structuredData,\n };\n}\n","/**\n * @fileoverview OpenAI Chat Completions API Handler\n *\n * This module implements the LLM handler for OpenAI's Chat Completions API\n * (`/v1/chat/completions`). This is the legacy API that provides standard\n * chat completion functionality with function calling support.\n *\n * For the modern Responses API with built-in tools support, see `llm.responses.ts`.\n *\n * @see {@link https://platform.openai.com/docs/api-reference/chat OpenAI Chat Completions API Reference}\n * @module providers/openai/llm.completions\n */\n\nimport type { LLMHandler, BoundLLMModel, LLMRequest, LLMResponse, LLMStreamResult, LLMCapabilities } from '../../types/llm.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport type { LLMProvider } from '../../types/provider.ts';\nimport { UPPError } from '../../types/errors.ts';\nimport { resolveApiKey } from '../../http/keys.ts';\nimport { doFetch, doStreamFetch } from '../../http/fetch.ts';\nimport { parseSSEStream } from '../../http/sse.ts';\nimport { normalizeHttpError } from '../../http/errors.ts';\nimport type { OpenAICompletionsParams, OpenAICompletionsResponse, OpenAICompletionsStreamChunk } from './types.ts';\nimport {\n transformRequest,\n transformResponse,\n transformStreamEvent,\n createStreamState,\n buildResponseFromState,\n} from './transform.completions.ts';\n\n/** Base URL for OpenAI's Chat Completions API endpoint */\nconst OPENAI_API_URL = 'https://api.openai.com/v1/chat/completions';\n\n/**\n * Capability declaration for the OpenAI Chat Completions API.\n *\n * Defines what features are supported by this handler:\n * - Streaming: Real-time token-by-token response streaming via SSE\n * - Tools: Function calling for structured interactions\n * - Structured Output: JSON schema-based response formatting\n * - Image Input: Vision capabilities for image understanding\n */\nconst OPENAI_CAPABILITIES: LLMCapabilities = {\n streaming: true,\n tools: true,\n structuredOutput: true,\n imageInput: true,\n videoInput: false,\n audioInput: false,\n};\n\n/**\n * Creates an LLM handler for OpenAI's Chat Completions API.\n *\n * This factory function creates a handler that communicates with the\n * `/v1/chat/completions` endpoint. The handler supports both synchronous\n * completion requests and streaming responses.\n *\n * @returns An LLM handler configured for the Chat Completions API\n *\n * @example\n * ```typescript\n * const handler = createCompletionsLLMHandler();\n * const model = handler.bind('gpt-4o');\n *\n * // Synchronous completion\n * const response = await model.complete({\n * messages: [{ role: 'user', content: 'Hello!' }],\n * config: { apiKey: 'sk-...' }\n * });\n *\n * // Streaming completion\n * const stream = model.stream({\n * messages: [{ role: 'user', content: 'Tell me a story' }],\n * config: { apiKey: 'sk-...' }\n * });\n *\n * for await (const event of stream) {\n * if (event.type === 'text_delta') {\n * process.stdout.write(event.delta.text);\n * }\n * }\n * ```\n *\n * @see {@link createResponsesLLMHandler} for the modern Responses API handler\n */\nexport function createCompletionsLLMHandler(): LLMHandler<OpenAICompletionsParams> {\n let providerRef: LLMProvider<OpenAICompletionsParams> | null = null;\n\n return {\n _setProvider(provider: LLMProvider<OpenAICompletionsParams>) {\n providerRef = provider;\n },\n\n bind(modelId: string): BoundLLMModel<OpenAICompletionsParams> {\n // Use the injected provider reference\n if (!providerRef) {\n throw new UPPError(\n 'Provider reference not set. Handler must be used with createProvider() or have _setProvider called.',\n 'INVALID_REQUEST',\n 'openai',\n 'llm'\n );\n }\n\n const model: BoundLLMModel<OpenAICompletionsParams> = {\n modelId,\n capabilities: OPENAI_CAPABILITIES,\n\n get provider(): LLMProvider<OpenAICompletionsParams> {\n return providerRef!;\n },\n\n async complete(request: LLMRequest<OpenAICompletionsParams>): Promise<LLMResponse> {\n const apiKey = await resolveApiKey(\n request.config,\n 'OPENAI_API_KEY',\n 'openai',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? OPENAI_API_URL;\n const body = transformRequest(request, modelId);\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doFetch(\n baseUrl,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'openai',\n 'llm'\n );\n\n const data = (await response.json()) as OpenAICompletionsResponse;\n return transformResponse(data);\n },\n\n stream(request: LLMRequest<OpenAICompletionsParams>): LLMStreamResult {\n const state = createStreamState();\n let responseResolve: (value: LLMResponse) => void;\n let responseReject: (error: Error) => void;\n\n const responsePromise = new Promise<LLMResponse>((resolve, reject) => {\n responseResolve = resolve;\n responseReject = reject;\n });\n\n async function* generateEvents(): AsyncGenerator<StreamEvent, void, unknown> {\n try {\n const apiKey = await resolveApiKey(\n request.config,\n 'OPENAI_API_KEY',\n 'openai',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? OPENAI_API_URL;\n const body = transformRequest(request, modelId);\n body.stream = true;\n body.stream_options = { include_usage: true };\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doStreamFetch(\n baseUrl,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'openai',\n 'llm'\n );\n\n if (!response.ok) {\n const error = await normalizeHttpError(response, 'openai', 'llm');\n responseReject(error);\n throw error;\n }\n\n if (!response.body) {\n const error = new UPPError(\n 'No response body for streaming request',\n 'PROVIDER_ERROR',\n 'openai',\n 'llm'\n );\n responseReject(error);\n throw error;\n }\n\n for await (const data of parseSSEStream(response.body)) {\n // Skip [DONE] marker\n if (data === '[DONE]') {\n continue;\n }\n\n // Check for OpenAI error event\n if (typeof data === 'object' && data !== null) {\n const chunk = data as OpenAICompletionsStreamChunk;\n\n // Check for error in chunk\n if ('error' in chunk && chunk.error) {\n const errorData = chunk.error as { message?: string; type?: string };\n const error = new UPPError(\n errorData.message ?? 'Unknown error',\n 'PROVIDER_ERROR',\n 'openai',\n 'llm'\n );\n responseReject(error);\n throw error;\n }\n\n const uppEvents = transformStreamEvent(chunk, state);\n for (const event of uppEvents) {\n yield event;\n }\n }\n }\n\n // Build final response\n responseResolve(buildResponseFromState(state));\n } catch (error) {\n responseReject(error as Error);\n throw error;\n }\n }\n\n return {\n [Symbol.asyncIterator]() {\n return generateEvents();\n },\n response: responsePromise,\n };\n },\n };\n\n return model;\n },\n };\n}\n","/**\n * @fileoverview Responses API Message Transformers\n *\n * This module provides transformation functions for converting between the\n * Universal Provider Protocol (UPP) message format and OpenAI's Responses API\n * format. The Responses API uses a different structure than Chat Completions,\n * with input items instead of messages and support for built-in tools.\n *\n * Key differences from Chat Completions:\n * - Uses `input` array instead of `messages`\n * - Function calls are separate input items, not embedded in messages\n * - Tool results use `function_call_output` items\n * - Supports built-in tools (web search, image generation, etc.)\n * - Different streaming event structure\n *\n * @module providers/openai/transform.responses\n */\n\nimport type { LLMRequest, LLMResponse } from '../../types/llm.ts';\nimport type { Message } from '../../types/messages.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport type { Tool, ToolCall } from '../../types/tool.ts';\nimport type { TokenUsage } from '../../types/turn.ts';\nimport type { ContentBlock, TextBlock, ImageBlock, AssistantContent } from '../../types/content.ts';\nimport {\n AssistantMessage,\n isUserMessage,\n isAssistantMessage,\n isToolResultMessage,\n} from '../../types/messages.ts';\nimport type {\n OpenAIResponsesParams,\n OpenAIResponsesRequest,\n OpenAIResponsesInputItem,\n OpenAIResponsesContentPart,\n OpenAIResponsesTool,\n OpenAIResponsesToolUnion,\n OpenAIResponsesResponse,\n OpenAIResponsesStreamEvent,\n OpenAIResponsesOutputItem,\n OpenAIResponsesMessageOutput,\n OpenAIResponsesFunctionCallOutput,\n OpenAIResponsesImageGenerationOutput,\n} from './types.ts';\n\n/**\n * Transforms a UPP LLM request into OpenAI Responses API format.\n *\n * This function converts the universal request format to OpenAI's Responses API\n * structure. It merges UPP function tools with any built-in tools specified in\n * params, and handles structured output configuration.\n *\n * @param request - The UPP LLM request containing messages, tools, and configuration\n * @param modelId - The OpenAI model identifier (e.g., 'gpt-4o')\n * @returns An OpenAI Responses API request body\n *\n * @example\n * ```typescript\n * const openaiRequest = transformRequest({\n * messages: [userMessage('Search for recent news')],\n * params: {\n * max_output_tokens: 1000,\n * tools: [tools.webSearch()]\n * },\n * config: { apiKey: 'sk-...' }\n * }, 'gpt-4o');\n * ```\n */\nexport function transformRequest(\n request: LLMRequest<OpenAIResponsesParams>,\n modelId: string\n): OpenAIResponsesRequest {\n const params = request.params ?? ({} as OpenAIResponsesParams);\n\n const builtInTools = params.tools as OpenAIResponsesToolUnion[] | undefined;\n const { tools: _paramsTools, ...restParams } = params;\n\n const openaiRequest: OpenAIResponsesRequest = {\n ...restParams,\n model: modelId,\n input: transformInputItems(request.messages, request.system),\n };\n\n const functionTools: OpenAIResponsesToolUnion[] = request.tools?.map(transformTool) ?? [];\n const allTools: OpenAIResponsesToolUnion[] = [...functionTools, ...(builtInTools ?? [])];\n\n if (allTools.length > 0) {\n openaiRequest.tools = allTools;\n }\n\n if (request.structure) {\n const schema: Record<string, unknown> = {\n type: 'object',\n properties: request.structure.properties,\n required: request.structure.required,\n ...(request.structure.additionalProperties !== undefined\n ? { additionalProperties: request.structure.additionalProperties }\n : { additionalProperties: false }),\n };\n if (request.structure.description) {\n schema.description = request.structure.description;\n }\n\n openaiRequest.text = {\n format: {\n type: 'json_schema',\n name: 'json_response',\n description: request.structure.description,\n schema,\n strict: true,\n },\n };\n }\n\n return openaiRequest;\n}\n\n/**\n * Normalizes system prompt to string.\n * Converts array format to concatenated string for providers that only support strings.\n */\nfunction normalizeSystem(system: string | unknown[] | undefined): string | undefined {\n if (!system) return undefined;\n if (typeof system === 'string') return system;\n return (system as Array<{text?: string}>)\n .map(block => block.text ?? '')\n .filter(text => text.length > 0)\n .join('\\n\\n');\n}\n\n/**\n * Transforms UPP messages to Responses API input items.\n *\n * The Responses API accepts either a string (for simple prompts) or an array\n * of input items. This function optimizes by returning a string when the\n * input is a single user message with text content.\n *\n * @param messages - Array of UPP messages to transform\n * @param system - Optional system prompt (string or array, normalized to string)\n * @returns Either a string (for simple inputs) or array of input items\n */\nfunction transformInputItems(\n messages: Message[],\n system?: string | unknown[]\n): OpenAIResponsesInputItem[] | string {\n const result: OpenAIResponsesInputItem[] = [];\n const normalizedSystem = normalizeSystem(system);\n\n if (normalizedSystem) {\n result.push({\n type: 'message',\n role: 'system',\n content: normalizedSystem,\n });\n }\n\n for (const message of messages) {\n const items = transformMessage(message);\n result.push(...items);\n }\n\n if (result.length === 1 && result[0]?.type === 'message') {\n const item = result[0] as { role?: string; content?: string | unknown[] };\n if (item.role === 'user' && typeof item.content === 'string') {\n return item.content;\n }\n }\n\n return result;\n}\n\n/**\n * Filters content blocks to only include those with a valid type property.\n *\n * @param content - Array of content blocks to filter\n * @returns Filtered array containing only valid content blocks\n */\nfunction filterValidContent<T extends { type?: string }>(content: T[]): T[] {\n return content.filter((c) => c && typeof c.type === 'string');\n}\n\n/**\n * Transforms a single UPP message to Responses API input items.\n *\n * Unlike Chat Completions, the Responses API separates function calls from\n * messages. An assistant message with tool calls becomes multiple input items:\n * a message item for text content plus separate function_call items.\n *\n * @param message - The UPP message to transform\n * @returns Array of Responses API input items (may be multiple per message)\n */\nfunction transformMessage(message: Message): OpenAIResponsesInputItem[] {\n if (isUserMessage(message)) {\n const validContent = filterValidContent(message.content);\n if (validContent.length === 1 && validContent[0]?.type === 'text') {\n return [\n {\n type: 'message',\n role: 'user',\n content: (validContent[0] as TextBlock).text,\n },\n ];\n }\n return [\n {\n type: 'message',\n role: 'user',\n content: validContent.map(transformContentPart),\n },\n ];\n }\n\n if (isAssistantMessage(message)) {\n const validContent = filterValidContent(message.content);\n const items: OpenAIResponsesInputItem[] = [];\n\n const contentParts: OpenAIResponsesContentPart[] = validContent\n .filter((c): c is TextBlock => c.type === 'text')\n .map((c): OpenAIResponsesContentPart => ({\n type: 'output_text',\n text: c.text,\n }));\n\n if (contentParts.length > 0) {\n items.push({\n type: 'message',\n role: 'assistant',\n content: contentParts,\n });\n }\n\n const openaiMeta = message.metadata?.openai as\n | { functionCallItems?: Array<{ id: string; call_id: string; name: string; arguments: string }> }\n | undefined;\n const functionCallItems = openaiMeta?.functionCallItems;\n\n if (functionCallItems && functionCallItems.length > 0) {\n for (const fc of functionCallItems) {\n items.push({\n type: 'function_call',\n id: fc.id,\n call_id: fc.call_id,\n name: fc.name,\n arguments: fc.arguments,\n });\n }\n } else if (message.toolCalls && message.toolCalls.length > 0) {\n for (const call of message.toolCalls) {\n items.push({\n type: 'function_call',\n id: `fc_${call.toolCallId}`,\n call_id: call.toolCallId,\n name: call.toolName,\n arguments: JSON.stringify(call.arguments),\n });\n }\n }\n\n return items;\n }\n\n if (isToolResultMessage(message)) {\n return message.results.map((result) => ({\n type: 'function_call_output' as const,\n call_id: result.toolCallId,\n output:\n typeof result.result === 'string'\n ? result.result\n : JSON.stringify(result.result),\n }));\n }\n\n return [];\n}\n\n/**\n * Transforms a UPP content block to Responses API content part format.\n *\n * Handles text and image content blocks. The Responses API uses different\n * type names than Chat Completions (`input_text` vs `text`, `input_image` vs `image_url`).\n *\n * @param block - The content block to transform\n * @returns The transformed Responses API content part\n * @throws Error if the content type is unsupported or image source type is unknown\n */\nfunction transformContentPart(block: ContentBlock): OpenAIResponsesContentPart {\n switch (block.type) {\n case 'text':\n return { type: 'input_text', text: block.text };\n\n case 'image': {\n const imageBlock = block as ImageBlock;\n if (imageBlock.source.type === 'base64') {\n return {\n type: 'input_image',\n image_url: `data:${imageBlock.mimeType};base64,${imageBlock.source.data}`,\n };\n }\n\n if (imageBlock.source.type === 'url') {\n return {\n type: 'input_image',\n image_url: imageBlock.source.url,\n };\n }\n\n if (imageBlock.source.type === 'bytes') {\n const base64 = btoa(\n Array.from(imageBlock.source.data)\n .map((b) => String.fromCharCode(b))\n .join('')\n );\n return {\n type: 'input_image',\n image_url: `data:${imageBlock.mimeType};base64,${base64}`,\n };\n }\n\n throw new Error('Unknown image source type');\n }\n\n default:\n throw new Error(`Unsupported content type: ${block.type}`);\n }\n}\n\n/**\n * Extracts OpenAI-specific options from tool metadata.\n *\n * @param tool - The tool to extract options from\n * @returns The OpenAI options if present (currently supports `strict`)\n */\nfunction extractToolOptions(tool: Tool): { strict?: boolean } {\n const openaiMeta = tool.metadata?.openai as\n | { strict?: boolean }\n | undefined;\n return { strict: openaiMeta?.strict };\n}\n\n/**\n * Transforms a UPP tool definition to Responses API function tool format.\n *\n * The Responses API uses a flatter structure for function tools compared to\n * Chat Completions, with properties at the top level rather than nested.\n *\n * Strict mode can be specified via tool metadata:\n * ```typescript\n * const tool: Tool = {\n * name: 'get_weather',\n * description: 'Get weather for a location',\n * parameters: {...},\n * metadata: { openai: { strict: true } },\n * run: async (params) => {...}\n * };\n * ```\n *\n * @param tool - The UPP tool definition\n * @returns The transformed Responses API function tool\n */\nfunction transformTool(tool: Tool): OpenAIResponsesTool {\n const { strict } = extractToolOptions(tool);\n\n return {\n type: 'function',\n name: tool.name,\n description: tool.description,\n parameters: {\n type: 'object',\n properties: tool.parameters.properties,\n required: tool.parameters.required,\n ...(tool.parameters.additionalProperties !== undefined\n ? { additionalProperties: tool.parameters.additionalProperties }\n : {}),\n },\n ...(strict !== undefined ? { strict } : {}),\n };\n}\n\n/**\n * Transforms an OpenAI Responses API response to UPP LLMResponse format.\n *\n * Processes all output items from the response, extracting text content,\n * tool calls, and generated images. Also handles built-in tool outputs\n * like image generation results.\n *\n * @param data - The raw OpenAI Responses API response\n * @returns The transformed UPP LLM response\n */\nexport function transformResponse(data: OpenAIResponsesResponse): LLMResponse {\n const content: AssistantContent[] = [];\n const toolCalls: ToolCall[] = [];\n const functionCallItems: Array<{\n id: string;\n call_id: string;\n name: string;\n arguments: string;\n }> = [];\n let hadRefusal = false;\n let structuredData: unknown;\n\n for (const item of data.output) {\n if (item.type === 'message') {\n const messageItem = item as OpenAIResponsesMessageOutput;\n for (const part of messageItem.content) {\n if (part.type === 'output_text') {\n content.push({ type: 'text', text: part.text });\n if (structuredData === undefined) {\n try {\n structuredData = JSON.parse(part.text);\n } catch {\n // Not JSON - expected for non-structured responses\n }\n }\n } else if (part.type === 'refusal') {\n content.push({ type: 'text', text: part.refusal });\n hadRefusal = true;\n }\n }\n } else if (item.type === 'function_call') {\n const functionCall = item as OpenAIResponsesFunctionCallOutput;\n let args: Record<string, unknown> = {};\n try {\n args = JSON.parse(functionCall.arguments);\n } catch {\n // Invalid JSON - use empty object\n }\n toolCalls.push({\n toolCallId: functionCall.call_id,\n toolName: functionCall.name,\n arguments: args,\n });\n functionCallItems.push({\n id: functionCall.id,\n call_id: functionCall.call_id,\n name: functionCall.name,\n arguments: functionCall.arguments,\n });\n } else if (item.type === 'image_generation_call') {\n const imageGen = item as OpenAIResponsesImageGenerationOutput;\n if (imageGen.result) {\n content.push({\n type: 'image',\n mimeType: 'image/png',\n source: { type: 'base64', data: imageGen.result },\n } as ImageBlock);\n }\n }\n }\n\n const message = new AssistantMessage(\n content,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: data.id,\n metadata: {\n openai: {\n model: data.model,\n status: data.status,\n response_id: data.id,\n functionCallItems:\n functionCallItems.length > 0 ? functionCallItems : undefined,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: data.usage.input_tokens,\n outputTokens: data.usage.output_tokens,\n totalTokens: data.usage.total_tokens,\n cacheReadTokens: data.usage.input_tokens_details?.cached_tokens ?? 0,\n cacheWriteTokens: 0,\n };\n\n let stopReason = 'end_turn';\n if (data.status === 'completed') {\n stopReason = toolCalls.length > 0 ? 'tool_use' : 'end_turn';\n } else if (data.status === 'incomplete') {\n stopReason = data.incomplete_details?.reason === 'max_output_tokens'\n ? 'max_tokens'\n : 'end_turn';\n } else if (data.status === 'failed') {\n stopReason = 'error';\n }\n if (hadRefusal && stopReason !== 'error') {\n stopReason = 'content_filter';\n }\n\n return {\n message,\n usage,\n stopReason,\n data: structuredData,\n };\n}\n\n/**\n * Mutable state object for accumulating data during Responses API streaming.\n *\n * The Responses API has a different streaming structure than Chat Completions,\n * with events organized by output index. This state tracks content and tool\n * calls by their output index for proper reconstruction.\n */\nexport interface ResponsesStreamState {\n /** Response ID */\n id: string;\n /** Model identifier */\n model: string;\n /** Map of output index to accumulated text content */\n textByIndex: Map<number, string>;\n /** Map of output index to accumulated tool call data */\n toolCalls: Map<\n number,\n { itemId?: string; callId?: string; name?: string; arguments: string }\n >;\n /** Base64 image data from image_generation_call outputs */\n images: string[];\n /** Current response status */\n status: string;\n /** Input token count */\n inputTokens: number;\n /** Output token count */\n outputTokens: number;\n /** Number of tokens read from cache */\n cacheReadTokens: number;\n /** Whether a refusal was encountered */\n hadRefusal: boolean;\n}\n\n/**\n * Creates a fresh stream state object for a new Responses API streaming session.\n *\n * @returns A new ResponsesStreamState with all fields initialized\n */\nexport function createStreamState(): ResponsesStreamState {\n return {\n id: '',\n model: '',\n textByIndex: new Map(),\n toolCalls: new Map(),\n images: [],\n status: 'in_progress',\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n hadRefusal: false,\n };\n}\n\n/**\n * Transforms an OpenAI Responses API streaming event into UPP stream events.\n *\n * The Responses API uses a granular event structure with separate events for\n * response lifecycle, output items, and content deltas. This function maps\n * these events to the UPP streaming format.\n *\n * @param event - The Responses API streaming event to process\n * @param state - The mutable state object to update\n * @returns Array of UPP stream events generated from this event\n */\nexport function transformStreamEvent(\n event: OpenAIResponsesStreamEvent,\n state: ResponsesStreamState\n): StreamEvent[] {\n const events: StreamEvent[] = [];\n\n switch (event.type) {\n case 'response.created':\n state.id = event.response.id;\n state.model = event.response.model;\n events.push({ type: 'message_start', index: 0, delta: {} });\n break;\n\n case 'response.in_progress':\n state.status = 'in_progress';\n break;\n\n case 'response.completed':\n state.status = 'completed';\n if (event.response.usage) {\n state.inputTokens = event.response.usage.input_tokens;\n state.outputTokens = event.response.usage.output_tokens;\n state.cacheReadTokens = event.response.usage.input_tokens_details?.cached_tokens ?? 0;\n }\n events.push({ type: 'message_stop', index: 0, delta: {} });\n break;\n\n case 'response.failed':\n state.status = 'failed';\n events.push({ type: 'message_stop', index: 0, delta: {} });\n break;\n\n case 'response.output_item.added':\n if (event.item.type === 'function_call') {\n const functionCall = event.item as OpenAIResponsesFunctionCallOutput;\n const existing = state.toolCalls.get(event.output_index) ?? {\n arguments: '',\n };\n existing.itemId = functionCall.id;\n existing.callId = functionCall.call_id;\n existing.name = functionCall.name;\n if (functionCall.arguments) {\n existing.arguments = functionCall.arguments;\n }\n state.toolCalls.set(event.output_index, existing);\n }\n events.push({\n type: 'content_block_start',\n index: event.output_index,\n delta: {},\n });\n break;\n\n case 'response.output_item.done':\n if (event.item.type === 'function_call') {\n const functionCall = event.item as OpenAIResponsesFunctionCallOutput;\n const existing = state.toolCalls.get(event.output_index) ?? {\n arguments: '',\n };\n existing.itemId = functionCall.id;\n existing.callId = functionCall.call_id;\n existing.name = functionCall.name;\n if (functionCall.arguments) {\n existing.arguments = functionCall.arguments;\n }\n state.toolCalls.set(event.output_index, existing);\n } else if (event.item.type === 'image_generation_call') {\n const imageGen = event.item as OpenAIResponsesImageGenerationOutput;\n if (imageGen.result) {\n state.images.push(imageGen.result);\n }\n }\n events.push({\n type: 'content_block_stop',\n index: event.output_index,\n delta: {},\n });\n break;\n\n case 'response.output_text.delta': {\n const currentText = state.textByIndex.get(event.output_index) ?? '';\n state.textByIndex.set(event.output_index, currentText + event.delta);\n events.push({\n type: 'text_delta',\n index: event.output_index,\n delta: { text: event.delta },\n });\n break;\n }\n\n case 'response.output_text.done':\n state.textByIndex.set(event.output_index, event.text);\n break;\n\n case 'response.refusal.delta': {\n state.hadRefusal = true;\n const currentRefusal = state.textByIndex.get(event.output_index) ?? '';\n state.textByIndex.set(event.output_index, currentRefusal + event.delta);\n events.push({\n type: 'text_delta',\n index: event.output_index,\n delta: { text: event.delta },\n });\n break;\n }\n\n case 'response.refusal.done':\n state.hadRefusal = true;\n state.textByIndex.set(event.output_index, event.refusal);\n break;\n\n case 'response.function_call_arguments.delta': {\n let toolCall = state.toolCalls.get(event.output_index);\n if (!toolCall) {\n toolCall = { arguments: '' };\n state.toolCalls.set(event.output_index, toolCall);\n }\n if (event.item_id && !toolCall.itemId) {\n toolCall.itemId = event.item_id;\n }\n if (event.call_id && !toolCall.callId) {\n toolCall.callId = event.call_id;\n }\n toolCall.arguments += event.delta;\n events.push({\n type: 'tool_call_delta',\n index: event.output_index,\n delta: {\n toolCallId: toolCall.callId ?? toolCall.itemId ?? '',\n toolName: toolCall.name,\n argumentsJson: event.delta,\n },\n });\n break;\n }\n\n case 'response.function_call_arguments.done': {\n let toolCall = state.toolCalls.get(event.output_index);\n if (!toolCall) {\n toolCall = { arguments: '' };\n state.toolCalls.set(event.output_index, toolCall);\n }\n if (event.item_id) {\n toolCall.itemId = event.item_id;\n }\n if (event.call_id) {\n toolCall.callId = event.call_id;\n }\n toolCall.name = event.name;\n toolCall.arguments = event.arguments;\n break;\n }\n\n case 'error':\n break;\n\n default:\n break;\n }\n\n return events;\n}\n\n/**\n * Builds a complete LLMResponse from accumulated Responses API streaming state.\n *\n * Called after all streaming events have been processed to construct the final\n * response object with all accumulated content, tool calls, images, and usage\n * statistics.\n *\n * @param state - The accumulated stream state\n * @returns A complete UPP LLMResponse\n */\nexport function buildResponseFromState(state: ResponsesStreamState): LLMResponse {\n const content: AssistantContent[] = [];\n let structuredData: unknown;\n\n for (const [, text] of state.textByIndex) {\n if (text) {\n content.push({ type: 'text', text });\n if (structuredData === undefined) {\n try {\n structuredData = JSON.parse(text);\n } catch {\n // Not JSON - expected for non-structured responses\n }\n }\n }\n }\n\n for (const imageData of state.images) {\n content.push({\n type: 'image',\n mimeType: 'image/png',\n source: { type: 'base64', data: imageData },\n } as ImageBlock);\n }\n\n const toolCalls: ToolCall[] = [];\n const functionCallItems: Array<{\n id: string;\n call_id: string;\n name: string;\n arguments: string;\n }> = [];\n for (const [, toolCall] of state.toolCalls) {\n let args: Record<string, unknown> = {};\n if (toolCall.arguments) {\n try {\n args = JSON.parse(toolCall.arguments);\n } catch {\n // Invalid JSON - use empty object\n }\n }\n const itemId = toolCall.itemId ?? '';\n const callId = toolCall.callId ?? toolCall.itemId ?? '';\n const name = toolCall.name ?? '';\n toolCalls.push({\n toolCallId: callId,\n toolName: name,\n arguments: args,\n });\n\n if (itemId && callId && name) {\n functionCallItems.push({\n id: itemId,\n call_id: callId,\n name,\n arguments: toolCall.arguments,\n });\n }\n }\n\n const message = new AssistantMessage(\n content,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: state.id,\n metadata: {\n openai: {\n model: state.model,\n status: state.status,\n response_id: state.id,\n functionCallItems:\n functionCallItems.length > 0 ? functionCallItems : undefined,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.inputTokens + state.outputTokens,\n cacheReadTokens: state.cacheReadTokens,\n cacheWriteTokens: 0,\n };\n\n let stopReason = 'end_turn';\n if (state.status === 'completed') {\n stopReason = toolCalls.length > 0 ? 'tool_use' : 'end_turn';\n } else if (state.status === 'failed') {\n stopReason = 'error';\n }\n if (state.hadRefusal && stopReason !== 'error') {\n stopReason = 'content_filter';\n }\n\n return {\n message,\n usage,\n stopReason,\n data: structuredData,\n };\n}\n","/**\n * @fileoverview OpenAI Responses API Handler\n *\n * This module implements the LLM handler for OpenAI's modern Responses API\n * (`/v1/responses`). This is the recommended API that supports built-in tools\n * like web search, image generation, file search, code interpreter, and MCP.\n *\n * For the legacy Chat Completions API, see `llm.completions.ts`.\n *\n * @see {@link https://platform.openai.com/docs/api-reference/responses OpenAI Responses API Reference}\n * @module providers/openai/llm.responses\n */\n\nimport type { LLMHandler, BoundLLMModel, LLMRequest, LLMResponse, LLMStreamResult, LLMCapabilities } from '../../types/llm.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport type { LLMProvider } from '../../types/provider.ts';\nimport { UPPError } from '../../types/errors.ts';\nimport { resolveApiKey } from '../../http/keys.ts';\nimport { doFetch, doStreamFetch } from '../../http/fetch.ts';\nimport { parseSSEStream } from '../../http/sse.ts';\nimport { normalizeHttpError } from '../../http/errors.ts';\nimport type { OpenAIResponsesParams, OpenAIResponsesResponse, OpenAIResponsesStreamEvent, OpenAIResponseErrorEvent } from './types.ts';\nimport {\n transformRequest,\n transformResponse,\n transformStreamEvent,\n createStreamState,\n buildResponseFromState,\n} from './transform.responses.ts';\n\n/** Base URL for OpenAI's Responses API endpoint */\nconst OPENAI_RESPONSES_API_URL = 'https://api.openai.com/v1/responses';\n\n/**\n * Capability declaration for the OpenAI Responses API.\n *\n * Defines what features are supported by this handler:\n * - Streaming: Real-time token-by-token response streaming via SSE\n * - Tools: Function calling plus built-in tools (web search, code interpreter, etc.)\n * - Structured Output: JSON schema-based response formatting\n * - Image Input: Vision capabilities for image understanding\n */\nconst OPENAI_CAPABILITIES: LLMCapabilities = {\n streaming: true,\n tools: true,\n structuredOutput: true,\n imageInput: true,\n videoInput: false,\n audioInput: false,\n};\n\n/**\n * Creates an LLM handler for OpenAI's modern Responses API.\n *\n * This factory function creates a handler that communicates with the\n * `/v1/responses` endpoint. The Responses API is the modern, recommended\n * approach that supports built-in tools like web search, image generation,\n * file search, code interpreter, and MCP servers.\n *\n * @returns An LLM handler configured for the Responses API\n *\n * @example Basic usage\n * ```typescript\n * const handler = createResponsesLLMHandler();\n * const model = handler.bind('gpt-4o');\n *\n * const response = await model.complete({\n * messages: [{ role: 'user', content: 'Hello!' }],\n * config: { apiKey: 'sk-...' }\n * });\n * ```\n *\n * @example With built-in tools\n * ```typescript\n * import { tools } from './types.ts';\n *\n * const response = await model.complete({\n * messages: [{ role: 'user', content: 'What is the weather today?' }],\n * params: {\n * tools: [tools.webSearch()]\n * },\n * config: { apiKey: 'sk-...' }\n * });\n * ```\n *\n * @example Streaming responses\n * ```typescript\n * const stream = model.stream({\n * messages: [{ role: 'user', content: 'Tell me a story' }],\n * config: { apiKey: 'sk-...' }\n * });\n *\n * for await (const event of stream) {\n * if (event.type === 'text_delta') {\n * process.stdout.write(event.delta.text);\n * }\n * }\n * ```\n *\n * @see {@link createCompletionsLLMHandler} for the legacy Chat Completions API handler\n */\nexport function createResponsesLLMHandler(): LLMHandler<OpenAIResponsesParams> {\n let providerRef: LLMProvider<OpenAIResponsesParams> | null = null;\n\n return {\n _setProvider(provider: LLMProvider<OpenAIResponsesParams>) {\n providerRef = provider;\n },\n\n bind(modelId: string): BoundLLMModel<OpenAIResponsesParams> {\n // Use the injected provider reference\n if (!providerRef) {\n throw new UPPError(\n 'Provider reference not set. Handler must be used with createProvider() or have _setProvider called.',\n 'INVALID_REQUEST',\n 'openai',\n 'llm'\n );\n }\n\n const model: BoundLLMModel<OpenAIResponsesParams> = {\n modelId,\n capabilities: OPENAI_CAPABILITIES,\n\n get provider(): LLMProvider<OpenAIResponsesParams> {\n return providerRef!;\n },\n\n async complete(request: LLMRequest<OpenAIResponsesParams>): Promise<LLMResponse> {\n const apiKey = await resolveApiKey(\n request.config,\n 'OPENAI_API_KEY',\n 'openai',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? OPENAI_RESPONSES_API_URL;\n const body = transformRequest(request, modelId);\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doFetch(\n baseUrl,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'openai',\n 'llm'\n );\n\n const data = (await response.json()) as OpenAIResponsesResponse;\n\n // Check for error in response\n if (data.status === 'failed' && data.error) {\n throw new UPPError(\n data.error.message,\n 'PROVIDER_ERROR',\n 'openai',\n 'llm'\n );\n }\n\n return transformResponse(data);\n },\n\n stream(request: LLMRequest<OpenAIResponsesParams>): LLMStreamResult {\n const state = createStreamState();\n let responseResolve: (value: LLMResponse) => void;\n let responseReject: (error: Error) => void;\n\n const responsePromise = new Promise<LLMResponse>((resolve, reject) => {\n responseResolve = resolve;\n responseReject = reject;\n });\n\n async function* generateEvents(): AsyncGenerator<StreamEvent, void, unknown> {\n try {\n const apiKey = await resolveApiKey(\n request.config,\n 'OPENAI_API_KEY',\n 'openai',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? OPENAI_RESPONSES_API_URL;\n const body = transformRequest(request, modelId);\n body.stream = true;\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doStreamFetch(\n baseUrl,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'openai',\n 'llm'\n );\n\n if (!response.ok) {\n const error = await normalizeHttpError(response, 'openai', 'llm');\n responseReject(error);\n throw error;\n }\n\n if (!response.body) {\n const error = new UPPError(\n 'No response body for streaming request',\n 'PROVIDER_ERROR',\n 'openai',\n 'llm'\n );\n responseReject(error);\n throw error;\n }\n\n for await (const data of parseSSEStream(response.body)) {\n // Skip [DONE] marker\n if (data === '[DONE]') {\n continue;\n }\n\n // Check for OpenAI error event\n if (typeof data === 'object' && data !== null) {\n const event = data as OpenAIResponsesStreamEvent;\n\n // Check for error event\n if (event.type === 'error') {\n const errorEvent = event as OpenAIResponseErrorEvent;\n const error = new UPPError(\n errorEvent.error.message,\n 'PROVIDER_ERROR',\n 'openai',\n 'llm'\n );\n responseReject(error);\n throw error;\n }\n\n const uppEvents = transformStreamEvent(event, state);\n for (const uppEvent of uppEvents) {\n yield uppEvent;\n }\n }\n }\n\n // Build final response\n responseResolve(buildResponseFromState(state));\n } catch (error) {\n responseReject(error as Error);\n throw error;\n }\n }\n\n return {\n [Symbol.asyncIterator]() {\n return generateEvents();\n },\n response: responsePromise,\n };\n },\n };\n\n return model;\n },\n };\n}\n","/**\n * @fileoverview OpenAI Provider Type Definitions\n *\n * This module contains all TypeScript type definitions for the OpenAI provider,\n * including types for both the Chat Completions API and the Responses API.\n *\n * The types are organized into sections:\n * - Audio Configuration Types\n * - Web Search Configuration Types\n * - Chat Completions API Parameters and Types\n * - Responses API Parameters and Types\n * - Built-in Tools for Responses API\n * - Tool Helper Constructors\n *\n * @module providers/openai/types\n */\n\n// ============================================\n// Audio Configuration Types\n// ============================================\n\n/**\n * Audio output configuration for Chat Completions API.\n *\n * Enables audio output generation when using models that support\n * the audio modality. Requires `modalities: ['text', 'audio']`.\n */\nexport interface OpenAIAudioConfig {\n /** Audio format for the generated output */\n format: 'wav' | 'aac' | 'mp3' | 'flac' | 'opus' | 'pcm16';\n /** Voice model to use for audio generation */\n voice:\n | 'alloy'\n | 'ash'\n | 'ballad'\n | 'coral'\n | 'echo'\n | 'sage'\n | 'shimmer'\n | 'verse'\n | 'marin'\n | 'cedar';\n}\n\n// ============================================\n// Web Search Configuration Types\n// ============================================\n\n/**\n * User location for web search context in the Responses API.\n *\n * Used to localize web search results based on the user's approximate location.\n * In the Responses API, location fields are at the same level as the type field.\n *\n * @see {@link OpenAICompletionsWebSearchUserLocation} for the Chat Completions API version\n */\nexport interface OpenAIWebSearchUserLocation {\n /** Location type - must be 'approximate' */\n type: 'approximate';\n /** City name */\n city?: string;\n /** ISO 3166-1 country code (e.g., \"US\") */\n country?: string;\n /** Region/state name */\n region?: string;\n /** IANA timezone (e.g., \"America/New_York\") */\n timezone?: string;\n}\n\n/**\n * User location for web search context in the Chat Completions API.\n *\n * Used to localize web search results based on the user's approximate location.\n * In the Completions API, location fields are nested under an `approximate` object.\n *\n * @see {@link OpenAIWebSearchUserLocation} for the Responses API version\n */\nexport interface OpenAICompletionsWebSearchUserLocation {\n /** Location type - must be 'approximate' */\n type: 'approximate';\n /** Approximate location details */\n approximate: {\n /** City name */\n city?: string;\n /** ISO 3166-1 country code (e.g., \"US\") */\n country?: string;\n /** Region/state name */\n region?: string;\n /** IANA timezone (e.g., \"America/New_York\") */\n timezone?: string;\n };\n}\n\n/**\n * Web search configuration options for the Chat Completions API.\n *\n * Enables web search capabilities when using search-enabled models.\n * Use with models that support web search (e.g., gpt-4o-search-preview).\n */\nexport interface OpenAIWebSearchOptions {\n /**\n * Context size for search results\n * Controls how much context from web results to include\n */\n search_context_size?: 'low' | 'medium' | 'high';\n /** User location for localizing search results */\n user_location?: OpenAICompletionsWebSearchUserLocation | null;\n}\n\n/**\n * Parameters for the OpenAI Chat Completions API.\n *\n * These parameters are passed directly to the `/v1/chat/completions` endpoint.\n * The Chat Completions API is the legacy API for chat interactions with\n * OpenAI models. For the modern API with built-in tools, see {@link OpenAIResponsesParams}.\n *\n * @example\n * ```typescript\n * const params: OpenAICompletionsParams = {\n * temperature: 0.7,\n * max_tokens: 1000,\n * reasoning_effort: 'medium'\n * };\n * ```\n *\n * @see {@link OpenAIResponsesParams} for the modern Responses API parameters\n */\nexport interface OpenAICompletionsParams {\n /** Maximum number of tokens to generate (legacy, prefer max_completion_tokens) */\n max_tokens?: number;\n\n /** Maximum completion tokens (preferred for newer models) */\n max_completion_tokens?: number;\n\n /** Temperature for randomness (0.0 - 2.0) */\n temperature?: number;\n\n /** Top-p (nucleus) sampling (0.0 - 1.0) */\n top_p?: number;\n\n /** Frequency penalty (-2.0 - 2.0) */\n frequency_penalty?: number;\n\n /** Presence penalty (-2.0 - 2.0) */\n presence_penalty?: number;\n\n /** Custom stop sequences */\n stop?: string | string[];\n\n /** Number of completions to generate */\n n?: number;\n\n /** Enable logprobs */\n logprobs?: boolean;\n\n /** Number of top logprobs to return (0-20) */\n top_logprobs?: number;\n\n /** Seed for deterministic sampling (beta, deprecated) */\n seed?: number;\n\n /** User identifier (deprecated, use safety_identifier or prompt_cache_key) */\n user?: string;\n\n /** Logit bias map */\n logit_bias?: Record<string, number>;\n\n /** Verbosity control */\n verbosity?: 'low' | 'medium' | 'high';\n\n /** Whether to enable parallel tool calls */\n parallel_tool_calls?: boolean;\n\n /** Reasoning effort for reasoning models */\n reasoning_effort?: 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';\n\n /** Service tier */\n service_tier?: 'auto' | 'default' | 'flex' | 'scale' | 'priority';\n\n /** Store completion for distillation */\n store?: boolean;\n\n /** Metadata key-value pairs (max 16, keys max 64 chars, values max 512 chars) */\n metadata?: Record<string, string>;\n\n /** Response format for structured output */\n response_format?: OpenAIResponseFormat;\n\n /**\n * Predicted Output configuration for faster regeneration\n * Improves response times when large parts of the response are known ahead of time\n */\n prediction?: {\n type: 'content';\n content: string | Array<{ type: 'text'; text: string }>;\n };\n\n /**\n * Stable identifier for caching similar requests\n * Used to optimize cache hit rates (replaces user field)\n */\n prompt_cache_key?: string;\n\n /**\n * Retention policy for prompt cache\n * Set to \"24h\" to enable extended prompt caching up to 24 hours\n */\n prompt_cache_retention?: 'in-memory' | '24h';\n\n /**\n * Stable identifier for abuse detection\n * Recommend hashing username or email address\n */\n safety_identifier?: string;\n\n /**\n * Output modalities to generate\n * Default: [\"text\"]. Use [\"text\", \"audio\"] for audio-capable models\n */\n modalities?: Array<'text' | 'audio'>;\n\n /**\n * Audio output configuration\n * Required when modalities includes \"audio\"\n */\n audio?: OpenAIAudioConfig | null;\n\n /**\n * Web search configuration\n * Enables the model to search the web for up-to-date information\n */\n web_search_options?: OpenAIWebSearchOptions;\n}\n\n/**\n * Reference to a prompt template stored in OpenAI's system.\n *\n * Allows using pre-defined prompt templates with variable substitution.\n */\nexport interface OpenAIPromptTemplate {\n /** Prompt template ID */\n id: string;\n /** Variables to fill into the template */\n variables?: Record<string, string>;\n}\n\n/**\n * Reference to an existing conversation for the Responses API.\n *\n * Items from this conversation are prepended to the input items,\n * enabling multi-turn conversations without resending full history.\n * Cannot be used together with `previous_response_id`.\n */\nexport interface OpenAIConversation {\n /** Conversation ID */\n id: string;\n}\n\n/**\n * Parameters for the OpenAI Responses API.\n *\n * These parameters are passed directly to the `/v1/responses` endpoint.\n * The Responses API is the modern, recommended API that supports built-in\n * tools like web search, image generation, file search, and code interpreter.\n *\n * @example Basic usage\n * ```typescript\n * const params: OpenAIResponsesParams = {\n * max_output_tokens: 1000,\n * temperature: 0.7,\n * reasoning: { effort: 'medium' }\n * };\n * ```\n *\n * @example With built-in tools\n * ```typescript\n * import { tools } from './types';\n *\n * const params: OpenAIResponsesParams = {\n * max_output_tokens: 2000,\n * tools: [tools.webSearch(), tools.imageGeneration()]\n * };\n * ```\n *\n * @see {@link OpenAICompletionsParams} for the legacy Chat Completions API parameters\n */\nexport interface OpenAIResponsesParams {\n /** Maximum output tokens */\n max_output_tokens?: number;\n\n /** Temperature for randomness (0.0 - 2.0) */\n temperature?: number;\n\n /** Top-p (nucleus) sampling (0.0 - 1.0) */\n top_p?: number;\n\n /** Number of top logprobs to return (0-20) */\n top_logprobs?: number;\n\n /** Whether to enable parallel tool calls */\n parallel_tool_calls?: boolean;\n\n /** Reasoning configuration (for gpt-5 and o-series models) */\n reasoning?: {\n effort?: 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';\n /** Include summary of reasoning */\n summary?: 'auto' | 'concise' | 'detailed';\n };\n\n /** Service tier */\n service_tier?: 'auto' | 'default' | 'flex' | 'scale' | 'priority';\n\n /** Truncation strategy */\n truncation?: 'auto' | 'disabled';\n\n /**\n * Fields to include in output\n * Supported values:\n * - 'web_search_call.action.sources': Include web search sources\n * - 'code_interpreter_call.outputs': Include code execution outputs\n * - 'computer_call_output.output.image_url': Include computer call images\n * - 'file_search_call.results': Include file search results\n * - 'message.input_image.image_url': Include input image URLs\n * - 'message.output_text.logprobs': Include logprobs with messages\n * - 'reasoning.encrypted_content': Include encrypted reasoning tokens\n */\n include?: string[];\n\n /** Background processing - run response asynchronously */\n background?: boolean;\n\n /** Continue from a previous response (cannot use with conversation) */\n previous_response_id?: string;\n\n /**\n * Conversation context - items prepended to input_items\n * Cannot be used with previous_response_id\n */\n conversation?: string | OpenAIConversation;\n\n /** Store response for continuation */\n store?: boolean;\n\n /** Metadata key-value pairs (max 16, keys max 64 chars, values max 512 chars) */\n metadata?: Record<string, string>;\n\n /**\n * Maximum total calls to built-in tools in a response\n * Applies across all built-in tool calls, not per tool\n */\n max_tool_calls?: number;\n\n /**\n * Reference to a prompt template and its variables\n */\n prompt?: OpenAIPromptTemplate;\n\n /**\n * Stable identifier for caching similar requests\n * Used to optimize cache hit rates (replaces user field)\n */\n prompt_cache_key?: string;\n\n /**\n * Retention policy for prompt cache\n * Set to \"24h\" to enable extended prompt caching up to 24 hours\n */\n prompt_cache_retention?: 'in-memory' | '24h';\n\n /**\n * Stable identifier for abuse detection\n * Recommend hashing username or email address\n */\n safety_identifier?: string;\n\n /** User identifier (deprecated, use safety_identifier or prompt_cache_key) */\n user?: string;\n\n /**\n * Built-in tools for the Responses API\n * Use the tool helper constructors: tools.webSearch(), tools.imageGeneration(), etc.\n *\n * @example\n * ```ts\n * import { tools } from 'provider-protocol/openai';\n *\n * const model = llm({\n * model: openai('gpt-4o'),\n * params: {\n * tools: [\n * tools.webSearch(),\n * tools.imageGeneration({ quality: 'high' }),\n * ],\n * },\n * });\n * ```\n */\n tools?: OpenAIBuiltInTool[];\n}\n\n/**\n * The API mode for the OpenAI provider.\n *\n * - `'responses'` - Modern Responses API (recommended)\n * - `'completions'` - Legacy Chat Completions API\n */\nexport type OpenAIAPIMode = 'responses' | 'completions';\n\n/**\n * Options when creating an OpenAI model reference.\n */\nexport interface OpenAIModelOptions {\n /** Which API to use */\n api?: OpenAIAPIMode;\n}\n\n/**\n * Model reference with OpenAI-specific options.\n * Used internally to track the selected model and API mode.\n */\nexport interface OpenAIModelReference {\n /** The OpenAI model identifier (e.g., 'gpt-4o', 'o1-preview') */\n modelId: string;\n /** Optional model-specific options */\n options?: OpenAIModelOptions;\n}\n\n/**\n * Configuration options for the OpenAI provider.\n */\nexport interface OpenAIConfig {\n /** Which API to use: 'responses' (modern) or 'completions' (legacy) */\n api?: 'responses' | 'completions';\n}\n\n// ============================================\n// Chat Completions API Types\n// ============================================\n\n/**\n * Request body for the OpenAI Chat Completions API.\n *\n * This interface represents the full request structure sent to\n * `/v1/chat/completions`. Most fields are optional and passed through\n * from {@link OpenAICompletionsParams}.\n */\nexport interface OpenAICompletionsRequest {\n model: string;\n messages: OpenAICompletionsMessage[];\n temperature?: number;\n top_p?: number;\n n?: number;\n stream?: boolean;\n stream_options?: { include_usage?: boolean };\n stop?: string | string[];\n max_tokens?: number;\n max_completion_tokens?: number;\n presence_penalty?: number;\n frequency_penalty?: number;\n logit_bias?: Record<string, number>;\n logprobs?: boolean;\n top_logprobs?: number;\n user?: string;\n seed?: number;\n tools?: OpenAICompletionsTool[];\n tool_choice?: OpenAIToolChoice;\n parallel_tool_calls?: boolean;\n response_format?: OpenAIResponseFormat;\n reasoning_effort?: string;\n verbosity?: 'low' | 'medium' | 'high';\n service_tier?: string;\n store?: boolean;\n metadata?: Record<string, string>;\n /** Predicted output for faster regeneration */\n prediction?: {\n type: 'content';\n content: string | Array<{ type: 'text'; text: string }>;\n };\n /** Stable identifier for caching (replaces user) */\n prompt_cache_key?: string;\n /** Retention policy for prompt cache */\n prompt_cache_retention?: string;\n /** Stable identifier for abuse detection */\n safety_identifier?: string;\n /** Output modalities (text, audio) */\n modalities?: Array<'text' | 'audio'>;\n /** Audio output configuration */\n audio?: OpenAIAudioConfig | null;\n /** Web search configuration */\n web_search_options?: OpenAIWebSearchOptions;\n}\n\n/**\n * Union type for all message types in the Chat Completions API.\n */\nexport type OpenAICompletionsMessage =\n | OpenAISystemMessage\n | OpenAIUserMessage\n | OpenAIAssistantMessage\n | OpenAIToolMessage;\n\n/** System or developer message for setting context and instructions */\nexport interface OpenAISystemMessage {\n role: 'system' | 'developer';\n content: string;\n name?: string;\n}\n\n/** User message with text or multimodal content */\nexport interface OpenAIUserMessage {\n role: 'user';\n content: string | OpenAIUserContent[];\n name?: string;\n}\n\n/** Assistant message containing the model's response */\nexport interface OpenAIAssistantMessage {\n role: 'assistant';\n content?: string | null;\n name?: string;\n tool_calls?: OpenAIToolCall[];\n refusal?: string | null;\n}\n\n/** Tool result message providing output from a function call */\nexport interface OpenAIToolMessage {\n role: 'tool';\n content: string;\n tool_call_id: string;\n}\n\n/**\n * Union type for user content parts (text or image).\n */\nexport type OpenAIUserContent = OpenAITextContent | OpenAIImageContent;\n\n/** Text content part */\nexport interface OpenAITextContent {\n type: 'text';\n text: string;\n}\n\n/** Image content part with URL reference */\nexport interface OpenAIImageContent {\n type: 'image_url';\n image_url: {\n url: string;\n detail?: 'auto' | 'low' | 'high';\n };\n}\n\n/**\n * Tool call structure in assistant messages.\n * Represents a function call requested by the model.\n */\nexport interface OpenAIToolCall {\n id: string;\n type: 'function';\n function: {\n name: string;\n arguments: string;\n };\n}\n\n/**\n * Tool definition for the Chat Completions API.\n * Functions are defined with JSON Schema parameters.\n */\nexport interface OpenAICompletionsTool {\n type: 'function';\n function: {\n name: string;\n description: string;\n parameters: {\n type: 'object';\n properties: Record<string, unknown>;\n required?: string[];\n additionalProperties?: boolean;\n };\n strict?: boolean;\n };\n}\n\n/**\n * Tool choice options for controlling function calling behavior.\n */\nexport type OpenAIToolChoice =\n | 'none'\n | 'auto'\n | 'required'\n | { type: 'function'; function: { name: string } };\n\n/**\n * Response format options for structured output.\n */\nexport type OpenAIResponseFormat =\n | { type: 'text' }\n | { type: 'json_object' }\n | {\n type: 'json_schema';\n json_schema: {\n name: string;\n description?: string;\n schema: Record<string, unknown>;\n strict?: boolean;\n };\n };\n\n/**\n * Response structure from the Chat Completions API.\n */\nexport interface OpenAICompletionsResponse {\n id: string;\n object: 'chat.completion';\n created: number;\n model: string;\n choices: OpenAICompletionsChoice[];\n usage: OpenAIUsage;\n system_fingerprint?: string;\n service_tier?: string;\n}\n\n/** A single choice from a completion response */\nexport interface OpenAICompletionsChoice {\n index: number;\n message: OpenAIAssistantMessage;\n finish_reason: 'stop' | 'length' | 'tool_calls' | 'content_filter' | null;\n logprobs?: OpenAILogprobs | null;\n}\n\n/** Log probability information for tokens */\nexport interface OpenAILogprobs {\n content?: Array<{\n token: string;\n logprob: number;\n bytes?: number[];\n top_logprobs?: Array<{\n token: string;\n logprob: number;\n bytes?: number[];\n }>;\n }>;\n}\n\n/** Token usage statistics from the API response */\nexport interface OpenAIUsage {\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n prompt_tokens_details?: {\n cached_tokens?: number;\n audio_tokens?: number;\n };\n completion_tokens_details?: {\n reasoning_tokens?: number;\n audio_tokens?: number;\n accepted_prediction_tokens?: number;\n rejected_prediction_tokens?: number;\n };\n}\n\n/**\n * Streaming chunk structure from the Chat Completions API.\n * Sent via SSE during streaming responses.\n */\nexport interface OpenAICompletionsStreamChunk {\n id: string;\n object: 'chat.completion.chunk';\n created: number;\n model: string;\n choices: OpenAICompletionsStreamChoice[];\n usage?: OpenAIUsage | null;\n system_fingerprint?: string;\n service_tier?: string;\n}\n\n/** A streaming choice containing incremental content */\nexport interface OpenAICompletionsStreamChoice {\n index: number;\n delta: OpenAICompletionsStreamDelta;\n finish_reason: 'stop' | 'length' | 'tool_calls' | 'content_filter' | null;\n logprobs?: OpenAILogprobs | null;\n}\n\n/** Incremental content delta in a streaming chunk */\nexport interface OpenAICompletionsStreamDelta {\n role?: 'assistant';\n content?: string | null;\n tool_calls?: OpenAIStreamToolCall[];\n refusal?: string | null;\n}\n\n/** Incremental tool call data in a streaming chunk */\nexport interface OpenAIStreamToolCall {\n index: number;\n id?: string;\n type?: 'function';\n function?: {\n name?: string;\n arguments?: string;\n };\n}\n\n// ============================================\n// Responses API Types\n// ============================================\n\n/**\n * Request body for the OpenAI Responses API.\n *\n * This interface represents the full request structure sent to\n * `/v1/responses`. Supports both function tools and built-in tools.\n */\nexport interface OpenAIResponsesRequest {\n model: string;\n input: string | OpenAIResponsesInputItem[];\n instructions?: string;\n max_output_tokens?: number;\n temperature?: number;\n top_p?: number;\n top_logprobs?: number;\n stream?: boolean;\n tools?: OpenAIResponsesToolUnion[];\n tool_choice?: OpenAIResponsesToolChoice;\n parallel_tool_calls?: boolean;\n text?: OpenAIResponsesTextConfig;\n truncation?: 'auto' | 'disabled';\n store?: boolean;\n metadata?: Record<string, string>;\n reasoning?: {\n effort?: 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';\n summary?: 'auto' | 'concise' | 'detailed';\n };\n service_tier?: string;\n include?: string[];\n background?: boolean;\n previous_response_id?: string;\n /** Conversation context (cannot use with previous_response_id) */\n conversation?: string | OpenAIConversation;\n /** Maximum total calls to built-in tools */\n max_tool_calls?: number;\n /** Prompt template reference */\n prompt?: OpenAIPromptTemplate;\n /** Stable identifier for caching (replaces user) */\n prompt_cache_key?: string;\n /** Retention policy for prompt cache */\n prompt_cache_retention?: 'in-memory' | '24h';\n /** Stable identifier for abuse detection */\n safety_identifier?: string;\n /** User identifier (deprecated) */\n user?: string;\n}\n\n/**\n * Union type for all input item types in the Responses API.\n */\nexport type OpenAIResponsesInputItem =\n | OpenAIResponsesSystemItem\n | OpenAIResponsesUserItem\n | OpenAIResponsesAssistantItem\n | OpenAIResponsesFunctionCallInputItem\n | OpenAIResponsesToolResultItem;\n\n/** System or developer message input item */\nexport interface OpenAIResponsesSystemItem {\n type: 'message';\n role: 'system' | 'developer';\n content: string | OpenAIResponsesContentPart[];\n}\n\n/** User message input item */\nexport interface OpenAIResponsesUserItem {\n type: 'message';\n role: 'user';\n content: string | OpenAIResponsesContentPart[];\n}\n\n/** Assistant message input item (for conversation history) */\nexport interface OpenAIResponsesAssistantItem {\n type: 'message';\n role: 'assistant';\n content: string | OpenAIResponsesContentPart[];\n}\n\n/** Function call input item (precedes function_call_output) */\nexport interface OpenAIResponsesFunctionCallInputItem {\n type: 'function_call';\n id: string;\n call_id: string;\n name: string;\n arguments: string;\n}\n\n/** Function call output (tool result) input item */\nexport interface OpenAIResponsesToolResultItem {\n type: 'function_call_output';\n call_id: string;\n output: string;\n}\n\n/**\n * Union type for content parts in the Responses API.\n */\nexport type OpenAIResponsesContentPart =\n | OpenAIResponsesTextPart\n | OpenAIResponsesImagePart\n | OpenAIResponsesFunctionCallPart;\n\n/** Text content part (input or output) */\nexport interface OpenAIResponsesTextPart {\n type: 'input_text' | 'output_text';\n text: string;\n}\n\n/** Image content part */\nexport interface OpenAIResponsesImagePart {\n type: 'input_image';\n image_url?: string;\n image?: string;\n detail?: 'auto' | 'low' | 'high';\n}\n\n/** Function call content part (embedded in messages) */\nexport interface OpenAIResponsesFunctionCallPart {\n type: 'function_call';\n id: string;\n call_id: string;\n name: string;\n arguments: string;\n}\n\n/**\n * Function tool definition for the Responses API.\n * Uses a flatter structure than Chat Completions.\n */\nexport interface OpenAIResponsesTool {\n type: 'function';\n name: string;\n description: string;\n parameters: {\n type: 'object';\n properties: Record<string, unknown>;\n required?: string[];\n additionalProperties?: boolean;\n };\n strict?: boolean;\n}\n\n/**\n * Tool choice options for the Responses API.\n */\nexport type OpenAIResponsesToolChoice =\n | 'none'\n | 'auto'\n | 'required'\n | { type: 'function'; name: string };\n\n/**\n * Text output configuration for structured output in the Responses API.\n */\nexport interface OpenAIResponsesTextConfig {\n format?:\n | { type: 'text' }\n | { type: 'json_object' }\n | {\n type: 'json_schema';\n name: string;\n description?: string;\n schema: Record<string, unknown>;\n strict?: boolean;\n };\n}\n\n/**\n * Response structure from the Responses API.\n */\nexport interface OpenAIResponsesResponse {\n id: string;\n object: 'response';\n created_at: number;\n model: string;\n output: OpenAIResponsesOutputItem[];\n usage: OpenAIResponsesUsage;\n status: 'completed' | 'failed' | 'incomplete' | 'in_progress';\n error?: {\n code: string;\n message: string;\n };\n incomplete_details?: {\n reason: string;\n };\n}\n\n/**\n * Union type for all output item types in Responses API responses.\n */\nexport type OpenAIResponsesOutputItem =\n | OpenAIResponsesMessageOutput\n | OpenAIResponsesFunctionCallOutput\n | OpenAIResponsesImageGenerationOutput\n | OpenAIResponsesWebSearchOutput;\n\n/** Assistant message output item */\nexport interface OpenAIResponsesMessageOutput {\n type: 'message';\n id: string;\n role: 'assistant';\n content: OpenAIResponsesOutputContent[];\n status: 'completed' | 'in_progress';\n}\n\n/** Function call output item (tool call requested by model) */\nexport interface OpenAIResponsesFunctionCallOutput {\n type: 'function_call';\n id: string;\n call_id: string;\n name: string;\n arguments: string;\n status: 'completed' | 'in_progress';\n}\n\n/** Image generation output item (from built-in image generation tool) */\nexport interface OpenAIResponsesImageGenerationOutput {\n type: 'image_generation_call';\n id: string;\n result?: string;\n status: 'completed' | 'in_progress';\n}\n\n/** Web search output item (from built-in web search tool) */\nexport interface OpenAIResponsesWebSearchOutput {\n type: 'web_search_call';\n id: string;\n status: 'completed' | 'in_progress';\n}\n\n/** Output content types (text or refusal) */\nexport type OpenAIResponsesOutputContent =\n | { type: 'output_text'; text: string; annotations?: unknown[] }\n | { type: 'refusal'; refusal: string };\n\n/** Token usage statistics for Responses API */\nexport interface OpenAIResponsesUsage {\n input_tokens: number;\n output_tokens: number;\n total_tokens: number;\n input_tokens_details?: {\n cached_tokens?: number;\n text_tokens?: number;\n image_tokens?: number;\n audio_tokens?: number;\n };\n output_tokens_details?: {\n text_tokens?: number;\n reasoning_tokens?: number;\n audio_tokens?: number;\n };\n}\n\n/**\n * Union type for all streaming events from the Responses API.\n * The Responses API uses granular events for different stages of response generation.\n */\nexport type OpenAIResponsesStreamEvent =\n | OpenAIResponseCreatedEvent\n | OpenAIResponseInProgressEvent\n | OpenAIResponseCompletedEvent\n | OpenAIResponseFailedEvent\n | OpenAIResponseOutputItemAddedEvent\n | OpenAIResponseOutputItemDoneEvent\n | OpenAIResponseContentPartAddedEvent\n | OpenAIResponseContentPartDoneEvent\n | OpenAIResponseTextDeltaEvent\n | OpenAIResponseTextDoneEvent\n | OpenAIResponseRefusalDeltaEvent\n | OpenAIResponseRefusalDoneEvent\n | OpenAIResponseFunctionCallArgumentsDeltaEvent\n | OpenAIResponseFunctionCallArgumentsDoneEvent\n | OpenAIResponseErrorEvent;\n\nexport interface OpenAIResponseCreatedEvent {\n type: 'response.created';\n response: OpenAIResponsesResponse;\n}\n\nexport interface OpenAIResponseInProgressEvent {\n type: 'response.in_progress';\n response: OpenAIResponsesResponse;\n}\n\nexport interface OpenAIResponseCompletedEvent {\n type: 'response.completed';\n response: OpenAIResponsesResponse;\n}\n\nexport interface OpenAIResponseFailedEvent {\n type: 'response.failed';\n response: OpenAIResponsesResponse;\n}\n\nexport interface OpenAIResponseOutputItemAddedEvent {\n type: 'response.output_item.added';\n output_index: number;\n item: OpenAIResponsesOutputItem;\n}\n\nexport interface OpenAIResponseOutputItemDoneEvent {\n type: 'response.output_item.done';\n output_index: number;\n item: OpenAIResponsesOutputItem;\n}\n\nexport interface OpenAIResponseContentPartAddedEvent {\n type: 'response.content_part.added';\n output_index: number;\n content_index: number;\n part: OpenAIResponsesOutputContent;\n}\n\nexport interface OpenAIResponseContentPartDoneEvent {\n type: 'response.content_part.done';\n output_index: number;\n content_index: number;\n part: OpenAIResponsesOutputContent;\n}\n\nexport interface OpenAIResponseTextDeltaEvent {\n type: 'response.output_text.delta';\n output_index: number;\n content_index: number;\n delta: string;\n}\n\nexport interface OpenAIResponseTextDoneEvent {\n type: 'response.output_text.done';\n output_index: number;\n content_index: number;\n text: string;\n}\n\nexport interface OpenAIResponseRefusalDeltaEvent {\n type: 'response.refusal.delta';\n output_index: number;\n content_index: number;\n delta: string;\n}\n\nexport interface OpenAIResponseRefusalDoneEvent {\n type: 'response.refusal.done';\n output_index: number;\n content_index: number;\n refusal: string;\n}\n\nexport interface OpenAIResponseFunctionCallArgumentsDeltaEvent {\n type: 'response.function_call_arguments.delta';\n output_index: number;\n item_id: string;\n delta: string;\n call_id?: string;\n}\n\nexport interface OpenAIResponseFunctionCallArgumentsDoneEvent {\n type: 'response.function_call_arguments.done';\n output_index: number;\n item_id: string;\n name: string;\n arguments: string;\n call_id?: string;\n}\n\nexport interface OpenAIResponseErrorEvent {\n type: 'error';\n error: {\n type: string;\n code?: string;\n message: string;\n };\n}\n\n// ============================================\n// Built-in Tools for Responses API\n// ============================================\n\n/**\n * Web search tool for Responses API\n * Enables the model to search the web for up-to-date information\n */\nexport interface OpenAIWebSearchTool {\n type: 'web_search';\n /**\n * Context size for search results\n * Controls how much context from web results to include\n */\n search_context_size?: 'low' | 'medium' | 'high';\n /** User location for localizing search results */\n user_location?: OpenAIWebSearchUserLocation | null;\n}\n\n/**\n * File search tool for Responses API\n * Enables the model to search through uploaded files\n */\nexport interface OpenAIFileSearchTool {\n type: 'file_search';\n /** File search configuration */\n file_search?: {\n /** Vector store IDs to search */\n vector_store_ids: string[];\n /** Maximum number of results to return */\n max_num_results?: number;\n /** Ranking options for search results */\n ranking_options?: {\n /** Ranker to use */\n ranker?: 'auto' | 'default_2024_08_21';\n /** Score threshold (0-1) */\n score_threshold?: number;\n };\n /** Filters to apply */\n filters?: Record<string, unknown>;\n };\n}\n\n/**\n * Code interpreter container configuration\n */\nexport interface OpenAICodeInterpreterContainer {\n /** Container type - 'auto' creates a new container */\n type: 'auto';\n /** Memory limit for the container (e.g., '1g', '4g') */\n memory_limit?: string;\n /** File IDs to make available in the container */\n file_ids?: string[];\n}\n\n/**\n * Code interpreter tool for Responses API\n * Allows the model to write and run Python code\n */\nexport interface OpenAICodeInterpreterTool {\n type: 'code_interpreter';\n /** Code interpreter configuration */\n code_interpreter?: {\n /** Container configuration */\n container: string | OpenAICodeInterpreterContainer;\n };\n}\n\n/**\n * Computer tool environment configuration\n */\nexport interface OpenAIComputerEnvironment {\n /** Environment type */\n type: 'browser' | 'mac' | 'windows' | 'linux' | 'ubuntu';\n}\n\n/**\n * Computer tool for Responses API\n * Enables the model to interact with computer interfaces\n */\nexport interface OpenAIComputerTool {\n type: 'computer';\n /** Computer tool configuration */\n computer?: {\n /** Display width in pixels */\n display_width: number;\n /** Display height in pixels */\n display_height: number;\n /** Environment configuration */\n environment?: OpenAIComputerEnvironment;\n };\n}\n\n/**\n * Image generation tool for Responses API\n */\nexport interface OpenAIImageGenerationTool {\n type: 'image_generation';\n /** Background transparency */\n background?: 'transparent' | 'opaque' | 'auto';\n /** Input image formats supported */\n input_image_mask?: boolean;\n /** Model to use for generation */\n model?: string;\n /** Moderation level */\n moderation?: 'auto' | 'low';\n /** Output compression */\n output_compression?: number;\n /** Output format */\n output_format?: 'png' | 'jpeg' | 'webp';\n /** Partial images during streaming */\n partial_images?: number;\n /** Image quality */\n quality?: 'auto' | 'high' | 'medium' | 'low';\n /** Image size */\n size?: 'auto' | '1024x1024' | '1024x1536' | '1536x1024';\n}\n\n/**\n * MCP (Model Context Protocol) server configuration\n */\nexport interface OpenAIMcpServerConfig {\n /** Server URL */\n url: string;\n /** Server name for identification */\n name?: string;\n /** Tool configuration for the server */\n tool_configuration?: {\n /** Allowed tools from this server */\n allowed_tools?: string[] | { type: 'all' };\n };\n /** Headers to send with requests */\n headers?: Record<string, string>;\n /** Allowed resources */\n allowed_resources?: string[];\n /** Require approval for tool calls */\n require_approval?: 'always' | 'never' | { type: 'except'; tools: string[] };\n}\n\n/**\n * MCP tool for Responses API\n * Enables connections to MCP servers\n */\nexport interface OpenAIMcpTool {\n type: 'mcp';\n /** MCP server configurations */\n mcp?: {\n /** Server configuration */\n server: OpenAIMcpServerConfig;\n };\n}\n\n/**\n * Union type for all Responses API built-in tools\n */\nexport type OpenAIBuiltInTool =\n | OpenAIWebSearchTool\n | OpenAIFileSearchTool\n | OpenAICodeInterpreterTool\n | OpenAIComputerTool\n | OpenAIImageGenerationTool\n | OpenAIMcpTool;\n\n/**\n * Combined tool type for Responses API (built-in or function)\n */\nexport type OpenAIResponsesToolUnion = OpenAIResponsesTool | OpenAIBuiltInTool;\n\n// ============================================\n// Tool Helper Constructors\n// ============================================\n\n/**\n * Creates a web search tool configuration for the Responses API.\n *\n * The web search tool enables the model to search the web for up-to-date information.\n *\n * @param options - Optional configuration for search behavior and user location\n * @returns A web search tool configuration object\n *\n * @example\n * ```typescript\n * // Basic web search\n * const search = webSearchTool();\n *\n * // With configuration\n * const searchWithLocation = webSearchTool({\n * search_context_size: 'high',\n * user_location: {\n * type: 'approximate',\n * city: 'San Francisco',\n * country: 'US'\n * }\n * });\n * ```\n */\nexport function webSearchTool(options?: {\n search_context_size?: 'low' | 'medium' | 'high';\n user_location?: OpenAIWebSearchUserLocation | null;\n}): OpenAIWebSearchTool {\n if (options) {\n return {\n type: 'web_search',\n ...options,\n } as OpenAIWebSearchTool;\n }\n return { type: 'web_search' };\n}\n\n/**\n * Creates a file search tool configuration for the Responses API.\n *\n * The file search tool enables the model to search through files in vector stores.\n *\n * @param options - Configuration including vector store IDs and search options\n * @returns A file search tool configuration object\n *\n * @example\n * ```typescript\n * const fileSearch = fileSearchTool({\n * vector_store_ids: ['vs_abc123'],\n * max_num_results: 10\n * });\n * ```\n */\nexport function fileSearchTool(options: {\n vector_store_ids: string[];\n max_num_results?: number;\n ranking_options?: {\n ranker?: 'auto' | 'default_2024_08_21';\n score_threshold?: number;\n };\n filters?: Record<string, unknown>;\n}): OpenAIFileSearchTool {\n return {\n type: 'file_search',\n file_search: options,\n };\n}\n\n/**\n * Creates a code interpreter tool configuration for the Responses API.\n *\n * The code interpreter tool allows the model to write and execute Python code\n * in a sandboxed environment.\n *\n * @param options - Optional container configuration\n * @returns A code interpreter tool configuration object\n *\n * @example\n * ```typescript\n * // Default configuration\n * const interpreter = codeInterpreterTool();\n *\n * // With custom container settings\n * const customInterpreter = codeInterpreterTool({\n * container: {\n * type: 'auto',\n * memory_limit: '4g',\n * file_ids: ['file_abc123']\n * }\n * });\n * ```\n */\nexport function codeInterpreterTool(options?: {\n container?: string | OpenAICodeInterpreterContainer;\n}): OpenAICodeInterpreterTool {\n return {\n type: 'code_interpreter',\n ...(options?.container && { code_interpreter: { container: options.container } }),\n };\n}\n\n/**\n * Creates a computer tool configuration for the Responses API.\n *\n * The computer tool enables the model to interact with computer interfaces\n * through mouse and keyboard actions.\n *\n * @param options - Display configuration and environment settings\n * @returns A computer tool configuration object\n *\n * @example\n * ```typescript\n * const computer = computerTool({\n * display_width: 1920,\n * display_height: 1080,\n * environment: { type: 'browser' }\n * });\n * ```\n */\nexport function computerTool(options: {\n display_width: number;\n display_height: number;\n environment?: OpenAIComputerEnvironment;\n}): OpenAIComputerTool {\n return {\n type: 'computer',\n computer: options,\n };\n}\n\n/**\n * Creates an image generation tool configuration for the Responses API.\n *\n * The image generation tool allows the model to generate images based on prompts.\n *\n * @param options - Optional image generation settings\n * @returns An image generation tool configuration object\n *\n * @example\n * ```typescript\n * // Default configuration\n * const imageGen = imageGenerationTool();\n *\n * // With custom settings\n * const customImageGen = imageGenerationTool({\n * quality: 'high',\n * size: '1024x1024',\n * background: 'transparent'\n * });\n * ```\n */\nexport function imageGenerationTool(options?: {\n background?: 'transparent' | 'opaque' | 'auto';\n model?: string;\n quality?: 'auto' | 'high' | 'medium' | 'low';\n size?: 'auto' | '1024x1024' | '1024x1536' | '1536x1024';\n output_format?: 'png' | 'jpeg' | 'webp';\n}): OpenAIImageGenerationTool {\n if (options) {\n return {\n type: 'image_generation',\n ...options,\n };\n }\n return { type: 'image_generation' };\n}\n\n/**\n * Creates an MCP (Model Context Protocol) tool configuration for the Responses API.\n *\n * The MCP tool enables connections to external MCP servers, allowing the model\n * to use tools and resources provided by those servers.\n *\n * @param options - MCP server configuration\n * @returns An MCP tool configuration object\n *\n * @example\n * ```typescript\n * const mcp = mcpTool({\n * url: 'https://mcp-server.example.com',\n * name: 'my-mcp-server',\n * allowed_tools: ['tool1', 'tool2']\n * });\n * ```\n */\nexport function mcpTool(options: {\n url: string;\n name?: string;\n allowed_tools?: string[] | { type: 'all' };\n headers?: Record<string, string>;\n require_approval?: 'always' | 'never' | { type: 'except'; tools: string[] };\n}): OpenAIMcpTool {\n const { url, name, allowed_tools, headers, require_approval } = options;\n return {\n type: 'mcp',\n mcp: {\n server: {\n url,\n name,\n ...(allowed_tools && { tool_configuration: { allowed_tools } }),\n headers,\n require_approval,\n },\n },\n };\n}\n\n/**\n * Namespace object containing all tool helper constructors.\n *\n * Provides a convenient way to create built-in tool configurations\n * for the Responses API.\n *\n * @example\n * ```typescript\n * import { tools } from './types';\n *\n * const params = {\n * tools: [\n * tools.webSearch(),\n * tools.imageGeneration({ quality: 'high' }),\n * tools.codeInterpreter()\n * ]\n * };\n * ```\n */\nexport const tools = {\n /** Creates a web search tool configuration */\n webSearch: webSearchTool,\n /** Creates a file search tool configuration */\n fileSearch: fileSearchTool,\n /** Creates a code interpreter tool configuration */\n codeInterpreter: codeInterpreterTool,\n /** Creates a computer tool configuration */\n computer: computerTool,\n /** Creates an image generation tool configuration */\n imageGeneration: imageGenerationTool,\n /** Creates an MCP tool configuration */\n mcp: mcpTool,\n};\n\n/**\n * OpenAI-specific HTTP headers for API requests.\n *\n * @example\n * ```typescript\n * const headers: OpenAIHeaders = {\n * 'OpenAI-Organization': 'org-abc123',\n * 'OpenAI-Project': 'proj-xyz789',\n * };\n * ```\n */\nexport interface OpenAIHeaders {\n /** Organization ID for multi-organization accounts. */\n 'OpenAI-Organization'?: string;\n /** Project ID for project-scoped API keys. */\n 'OpenAI-Project'?: string;\n /** Client-generated request ID for tracing. */\n 'X-Client-Request-Id'?: string;\n [key: string]: string | undefined;\n}\n","/**\n * @fileoverview OpenAI Provider Factory\n *\n * This module provides the main OpenAI provider implementation that supports both\n * the modern Responses API (default) and the legacy Chat Completions API.\n *\n * @example\n * ```typescript\n * import { openai } from './providers/openai';\n * import { llm } from './core/llm';\n *\n * // Using the modern Responses API (default)\n * const model = llm({\n * model: openai('gpt-4o'),\n * params: { max_output_tokens: 1000 }\n * });\n *\n * // Using the legacy Chat Completions API\n * const legacyModel = llm({\n * model: openai('gpt-4o', { api: 'completions' }),\n * params: { max_tokens: 1000 }\n * });\n * ```\n *\n * @module providers/openai\n */\n\nimport type {\n Provider,\n ModelReference,\n LLMHandler,\n LLMProvider,\n} from '../../types/provider.ts';\nimport { createCompletionsLLMHandler } from './llm.completions.ts';\nimport { createResponsesLLMHandler } from './llm.responses.ts';\nimport type { OpenAICompletionsParams, OpenAIResponsesParams } from './types.ts';\n\n/**\n * Union type for the LLM handler that supports both API modes.\n * Used internally for the dynamic handler selection based on API mode.\n */\ntype OpenAILLMParamsUnion = OpenAICompletionsParams | OpenAIResponsesParams;\n\n/**\n * Configuration options for the OpenAI provider.\n *\n * Controls which underlying OpenAI API endpoint is used when making requests.\n * The Responses API is the modern, recommended approach while the Chat Completions\n * API provides backward compatibility with existing integrations.\n */\nexport interface OpenAIProviderOptions {\n /**\n * Which API endpoint to use for requests.\n *\n * - `'responses'` - Modern Responses API (default, recommended). Supports built-in\n * tools like web search, image generation, file search, and code interpreter.\n * - `'completions'` - Legacy Chat Completions API. Standard chat completion endpoint\n * with function calling support.\n *\n * @default 'responses'\n */\n api?: 'responses' | 'completions';\n}\n\n/**\n * OpenAI provider interface with configurable API mode.\n *\n * The provider is callable as a function to create model references, and also\n * exposes metadata about the provider and its supported modalities.\n *\n * @example Creating model references\n * ```typescript\n * // Using the modern Responses API (default, recommended)\n * const model = openai('gpt-4o');\n *\n * // Using the legacy Chat Completions API\n * const legacyModel = openai('gpt-4o', { api: 'completions' });\n *\n * // Explicit Responses API selection\n * const responsesModel = openai('gpt-4o', { api: 'responses' });\n * ```\n *\n * @see {@link OpenAIProviderOptions} for available configuration options\n * @see {@link OpenAIResponsesParams} for Responses API parameters\n * @see {@link OpenAICompletionsParams} for Chat Completions API parameters\n */\nexport interface OpenAIProvider extends Provider<OpenAIProviderOptions> {\n /**\n * Creates a model reference for the specified OpenAI model.\n *\n * @param modelId - The OpenAI model identifier (e.g., 'gpt-4o', 'gpt-4-turbo', 'o1-preview', 'gpt-4o-mini')\n * @param options - Optional provider configuration including API mode selection\n * @returns A model reference that can be used with the LLM core functions\n *\n * @example\n * ```typescript\n * const gpt4o = openai('gpt-4o');\n * const gpt4turbo = openai('gpt-4-turbo', { api: 'completions' });\n * ```\n */\n (modelId: string, options?: OpenAIProviderOptions): ModelReference<OpenAIProviderOptions>;\n\n /**\n * The provider identifier.\n * Always returns `'openai'` for this provider.\n */\n readonly name: 'openai';\n\n /**\n * The provider version following semantic versioning.\n */\n readonly version: string;\n\n /**\n * Supported modalities and their handlers.\n * Currently supports LLM modality with both Responses and Completions API handlers.\n */\n readonly modalities: {\n /** The LLM handler for text generation and chat completion */\n llm: LLMHandler<OpenAILLMParamsUnion>;\n };\n}\n\n/**\n * Factory function that creates and configures the OpenAI provider instance.\n *\n * This function initializes both the Responses API and Chat Completions API handlers,\n * sets up dynamic handler selection based on the API mode, and injects provider\n * references for spec compliance.\n *\n * @returns A fully configured OpenAI provider instance\n * @internal\n */\nfunction createOpenAIProvider(): OpenAIProvider {\n let currentApiMode: 'responses' | 'completions' = 'responses';\n\n const responsesHandler = createResponsesLLMHandler();\n const completionsHandler = createCompletionsLLMHandler();\n\n const fn = function (\n modelId: string,\n options?: OpenAIProviderOptions\n ): ModelReference<OpenAIProviderOptions> {\n const apiMode = options?.api ?? 'responses';\n currentApiMode = apiMode;\n return { modelId, provider };\n };\n\n const modalities = {\n get llm(): LLMHandler<OpenAILLMParamsUnion> {\n return currentApiMode === 'completions'\n ? (completionsHandler as unknown as LLMHandler<OpenAILLMParamsUnion>)\n : (responsesHandler as unknown as LLMHandler<OpenAILLMParamsUnion>);\n },\n };\n\n Object.defineProperties(fn, {\n name: {\n value: 'openai',\n writable: false,\n configurable: true,\n },\n version: {\n value: '1.0.0',\n writable: false,\n configurable: true,\n },\n modalities: {\n value: modalities,\n writable: false,\n configurable: true,\n },\n });\n\n const provider = fn as OpenAIProvider;\n\n responsesHandler._setProvider?.(provider as unknown as LLMProvider<OpenAIResponsesParams>);\n completionsHandler._setProvider?.(provider as unknown as LLMProvider<OpenAICompletionsParams>);\n\n return provider;\n}\n\n/**\n * The OpenAI provider instance.\n *\n * Supports both the modern Responses API (default) and the legacy Chat Completions API.\n * Use this provider to create model references for OpenAI models like GPT-4o, GPT-4 Turbo,\n * and the o1 series.\n *\n * @example Basic usage with Responses API (recommended)\n * ```typescript\n * import { openai } from './providers/openai';\n * import { llm } from './core/llm';\n *\n * const model = llm({\n * model: openai('gpt-4o'),\n * params: { max_output_tokens: 1000 }\n * });\n *\n * const turn = await model.generate('Hello!');\n * console.log(turn.response.text);\n * ```\n *\n * @example Using Chat Completions API\n * ```typescript\n * const legacyModel = llm({\n * model: openai('gpt-4o', { api: 'completions' }),\n * params: { max_tokens: 1000 }\n * });\n * ```\n *\n * @example With built-in tools (Responses API only)\n * ```typescript\n * import { openai, tools } from './providers/openai';\n *\n * const model = llm({\n * model: openai('gpt-4o'),\n * params: {\n * tools: [tools.webSearch(), tools.imageGeneration()]\n * }\n * });\n * ```\n */\nexport const openai = createOpenAIProvider();\n\n// Re-export types\nexport type {\n OpenAICompletionsParams,\n OpenAIResponsesParams,\n OpenAIConfig,\n OpenAIAPIMode,\n OpenAIModelOptions,\n OpenAIModelReference,\n // Audio and web search types\n OpenAIAudioConfig,\n OpenAIWebSearchOptions,\n OpenAIWebSearchUserLocation,\n OpenAICompletionsWebSearchUserLocation,\n // Built-in tool types\n OpenAIBuiltInTool,\n OpenAIWebSearchTool,\n OpenAIFileSearchTool,\n OpenAICodeInterpreterTool,\n OpenAICodeInterpreterContainer,\n OpenAIComputerTool,\n OpenAIComputerEnvironment,\n OpenAIImageGenerationTool,\n OpenAIMcpTool,\n OpenAIMcpServerConfig,\n OpenAIResponsesToolUnion,\n // Conversation and prompt types\n OpenAIConversation,\n OpenAIPromptTemplate,\n} from './types.ts';\n\n// Re-export tool helper constructors\nexport {\n tools,\n webSearchTool,\n fileSearchTool,\n codeInterpreterTool,\n computerTool,\n imageGenerationTool,\n mcpTool,\n} from './types.ts';\n\nexport type { OpenAIHeaders } from './types.ts';\n"],"mappings":";;;;;;;;;;;;;;;;;;AA6DO,SAAS,iBACd,SACA,SAC0B;AAC1B,QAAM,SAAS,QAAQ,UAAW,CAAC;AAEnC,QAAM,gBAA0C;AAAA,IAC9C,GAAG;AAAA,IACH,OAAO;AAAA,IACP,UAAU,kBAAkB,QAAQ,UAAU,QAAQ,MAAM;AAAA,EAC9D;AAEA,MAAI,QAAQ,SAAS,QAAQ,MAAM,SAAS,GAAG;AAC7C,kBAAc,QAAQ,QAAQ,MAAM,IAAI,aAAa;AAAA,EACvD;AAEA,MAAI,QAAQ,WAAW;AACrB,UAAM,SAAkC;AAAA,MACtC,MAAM;AAAA,MACN,YAAY,QAAQ,UAAU;AAAA,MAC9B,UAAU,QAAQ,UAAU;AAAA,MAC5B,GAAI,QAAQ,UAAU,yBAAyB,SAC3C,EAAE,sBAAsB,QAAQ,UAAU,qBAAqB,IAC/D,EAAE,sBAAsB,MAAM;AAAA,IACpC;AACA,QAAI,QAAQ,UAAU,aAAa;AACjC,aAAO,cAAc,QAAQ,UAAU;AAAA,IACzC;AAEA,kBAAc,kBAAkB;AAAA,MAC9B,MAAM;AAAA,MACN,aAAa;AAAA,QACX,MAAM;AAAA,QACN,aAAa,QAAQ,UAAU;AAAA,QAC/B;AAAA,QACA,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,gBAAgB,QAA4D;AACnF,MAAI,CAAC,OAAQ,QAAO;AACpB,MAAI,OAAO,WAAW,SAAU,QAAO;AAEvC,SAAQ,OACL,IAAI,WAAS,MAAM,QAAQ,EAAE,EAC7B,OAAO,UAAQ,KAAK,SAAS,CAAC,EAC9B,KAAK,MAAM;AAChB;AAaA,SAAS,kBACP,UACA,QAC4B;AAC5B,QAAM,SAAqC,CAAC;AAC5C,QAAM,mBAAmB,gBAAgB,MAAM;AAE/C,MAAI,kBAAkB;AACpB,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAEA,aAAW,WAAW,UAAU;AAC9B,QAAI,oBAAoB,OAAO,GAAG;AAChC,YAAM,eAAe,qBAAqB,OAAO;AACjD,aAAO,KAAK,GAAG,YAAY;AAAA,IAC7B,OAAO;AACL,YAAM,cAAc,iBAAiB,OAAO;AAC5C,UAAI,aAAa;AACf,eAAO,KAAK,WAAW;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAQA,SAAS,mBAAgD,SAAmB;AAC1E,SAAO,QAAQ,OAAO,CAAC,MAAM,KAAK,OAAO,EAAE,SAAS,QAAQ;AAC9D;AAYA,SAAS,iBAAiB,SAAmD;AAC3E,MAAI,cAAc,OAAO,GAAG;AAC1B,UAAM,eAAe,mBAAmB,QAAQ,OAAO;AACvD,QAAI,aAAa,WAAW,KAAK,aAAa,CAAC,GAAG,SAAS,QAAQ;AACjE,aAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAU,aAAa,CAAC,EAAgB;AAAA,MAC1C;AAAA,IACF;AACA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS,aAAa,IAAI,qBAAqB;AAAA,IACjD;AAAA,EACF;AAEA,MAAI,mBAAmB,OAAO,GAAG;AAC/B,UAAM,eAAe,mBAAmB,QAAQ,OAAO;AACvD,UAAM,cAAc,aACjB,OAAO,CAAC,MAAsB,EAAE,SAAS,MAAM,EAC/C,IAAI,CAAC,MAAM,EAAE,IAAI,EACjB,KAAK,EAAE;AAEV,UAAM,mBAA6C;AAAA,MACjD,MAAM;AAAA,MACN,SAAS,eAAe;AAAA,IAC1B;AAEA,QAAI,QAAQ,aAAa,QAAQ,UAAU,SAAS,GAAG;AACrD,MAAC,iBAAuD,aACtD,QAAQ,UAAU,IAAI,CAAC,UAAU;AAAA,QAC/B,IAAI,KAAK;AAAA,QACT,MAAM;AAAA,QACN,UAAU;AAAA,UACR,MAAM,KAAK;AAAA,UACX,WAAW,KAAK,UAAU,KAAK,SAAS;AAAA,QAC1C;AAAA,MACF,EAAE;AAAA,IACN;AAEA,WAAO;AAAA,EACT;AAEA,MAAI,oBAAoB,OAAO,GAAG;AAChC,UAAM,UAAU,QAAQ,QAAQ,IAAI,CAAC,YAAY;AAAA,MAC/C,MAAM;AAAA,MACN,cAAc,OAAO;AAAA,MACrB,SACE,OAAO,OAAO,WAAW,WACrB,OAAO,SACP,KAAK,UAAU,OAAO,MAAM;AAAA,IACpC,EAAE;AAEF,WAAO,QAAQ,CAAC,KAAK;AAAA,EACvB;AAEA,SAAO;AACT;AAYO,SAAS,qBACd,SAC4B;AAC5B,MAAI,CAAC,oBAAoB,OAAO,GAAG;AACjC,UAAM,SAAS,iBAAiB,OAAO;AACvC,WAAO,SAAS,CAAC,MAAM,IAAI,CAAC;AAAA,EAC9B;AAEA,SAAO,QAAQ,QAAQ,IAAI,CAAC,YAAY;AAAA,IACtC,MAAM;AAAA,IACN,cAAc,OAAO;AAAA,IACrB,SACE,OAAO,OAAO,WAAW,WACrB,OAAO,SACP,KAAK,UAAU,OAAO,MAAM;AAAA,EACpC,EAAE;AACJ;AAYA,SAAS,sBAAsB,OAAwC;AACrE,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AACH,aAAO,EAAE,MAAM,QAAQ,MAAM,MAAM,KAAK;AAAA,IAE1C,KAAK,SAAS;AACZ,YAAM,aAAa;AACnB,UAAI;AAEJ,UAAI,WAAW,OAAO,SAAS,UAAU;AACvC,cAAM,QAAQ,WAAW,QAAQ,WAAW,WAAW,OAAO,IAAI;AAAA,MACpE,WAAW,WAAW,OAAO,SAAS,OAAO;AAC3C,cAAM,WAAW,OAAO;AAAA,MAC1B,WAAW,WAAW,OAAO,SAAS,SAAS;AAC7C,cAAM,SAAS;AAAA,UACb,MAAM,KAAK,WAAW,OAAO,IAAI,EAC9B,IAAI,CAAC,MAAM,OAAO,aAAa,CAAC,CAAC,EACjC,KAAK,EAAE;AAAA,QACZ;AACA,cAAM,QAAQ,WAAW,QAAQ,WAAW,MAAM;AAAA,MACpD,OAAO;AACL,cAAM,IAAI,MAAM,2BAA2B;AAAA,MAC7C;AAEA,aAAO;AAAA,QACL,MAAM;AAAA,QACN,WAAW,EAAE,IAAI;AAAA,MACnB;AAAA,IACF;AAAA,IAEA;AACE,YAAM,IAAI,MAAM,6BAA6B,MAAM,IAAI,EAAE;AAAA,EAC7D;AACF;AAQA,SAAS,mBAAmB,MAAkC;AAC5D,QAAM,aAAa,KAAK,UAAU;AAGlC,SAAO,EAAE,QAAQ,YAAY,OAAO;AACtC;AAsBA,SAAS,cAAc,MAAmC;AACxD,QAAM,EAAE,OAAO,IAAI,mBAAmB,IAAI;AAE1C,SAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,MACR,MAAM,KAAK;AAAA,MACX,aAAa,KAAK;AAAA,MAClB,YAAY;AAAA,QACV,MAAM;AAAA,QACN,YAAY,KAAK,WAAW;AAAA,QAC5B,UAAU,KAAK,WAAW;AAAA,QAC1B,GAAI,KAAK,WAAW,yBAAyB,SACzC,EAAE,sBAAsB,KAAK,WAAW,qBAAqB,IAC7D,CAAC;AAAA,MACP;AAAA,MACA,GAAI,WAAW,SAAY,EAAE,OAAO,IAAI,CAAC;AAAA,IAC3C;AAAA,EACF;AACF;AAaO,SAAS,kBAAkB,MAA8C;AAC9E,QAAM,SAAS,KAAK,QAAQ,CAAC;AAC7B,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,+BAA+B;AAAA,EACjD;AAEA,QAAM,cAA2B,CAAC;AAClC,MAAI;AACJ,MAAI,OAAO,QAAQ,SAAS;AAC1B,gBAAY,KAAK,EAAE,MAAM,QAAQ,MAAM,OAAO,QAAQ,QAAQ,CAAC;AAC/D,QAAI;AACF,uBAAiB,KAAK,MAAM,OAAO,QAAQ,OAAO;AAAA,IACpD,QAAQ;AAAA,IAER;AAAA,EACF;AACA,MAAI,aAAa;AACjB,MAAI,OAAO,QAAQ,SAAS;AAC1B,gBAAY,KAAK,EAAE,MAAM,QAAQ,MAAM,OAAO,QAAQ,QAAQ,CAAC;AAC/D,iBAAa;AAAA,EACf;AAEA,QAAM,YAAwB,CAAC;AAC/B,MAAI,OAAO,QAAQ,YAAY;AAC7B,eAAW,QAAQ,OAAO,QAAQ,YAAY;AAC5C,UAAI,OAAgC,CAAC;AACrC,UAAI;AACF,eAAO,KAAK,MAAM,KAAK,SAAS,SAAS;AAAA,MAC3C,QAAQ;AAAA,MAER;AACA,gBAAU,KAAK;AAAA,QACb,YAAY,KAAK;AAAA,QACjB,UAAU,KAAK,SAAS;AAAA,QACxB,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,UAAU,IAAI;AAAA,IAClB;AAAA,IACA,UAAU,SAAS,IAAI,YAAY;AAAA,IACnC;AAAA,MACE,IAAI,KAAK;AAAA,MACT,UAAU;AAAA,QACR,QAAQ;AAAA,UACN,OAAO,KAAK;AAAA,UACZ,eAAe,OAAO;AAAA,UACtB,oBAAoB,KAAK;AAAA,UACzB,cAAc,KAAK;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAoB;AAAA,IACxB,aAAa,KAAK,MAAM;AAAA,IACxB,cAAc,KAAK,MAAM;AAAA,IACzB,aAAa,KAAK,MAAM;AAAA,IACxB,iBAAiB,KAAK,MAAM,uBAAuB,iBAAiB;AAAA,IACpE,kBAAkB;AAAA,EACpB;AAEA,MAAI,aAAa;AACjB,UAAQ,OAAO,eAAe;AAAA,IAC5B,KAAK;AACH,mBAAa;AACb;AAAA,IACF,KAAK;AACH,mBAAa;AACb;AAAA,IACF,KAAK;AACH,mBAAa;AACb;AAAA,IACF,KAAK;AACH,mBAAa;AACb;AAAA,EACJ;AACA,MAAI,cAAc,eAAe,kBAAkB;AACjD,iBAAa;AAAA,EACf;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM;AAAA,EACR;AACF;AAmCO,SAAS,oBAA4C;AAC1D,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,MAAM;AAAA,IACN,WAAW,oBAAI,IAAI;AAAA,IACnB,cAAc;AAAA,IACd,aAAa;AAAA,IACb,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,YAAY;AAAA,EACd;AACF;AAaO,SAAS,qBACd,OACA,OACe;AACf,QAAM,SAAwB,CAAC;AAE/B,MAAI,MAAM,MAAM,CAAC,MAAM,IAAI;AACzB,UAAM,KAAK,MAAM;AACjB,WAAO,KAAK,EAAE,MAAM,iBAAiB,OAAO,GAAG,OAAO,CAAC,EAAE,CAAC;AAAA,EAC5D;AACA,MAAI,MAAM,OAAO;AACf,UAAM,QAAQ,MAAM;AAAA,EACtB;AAEA,QAAM,SAAS,MAAM,QAAQ,CAAC;AAC9B,MAAI,QAAQ;AACV,QAAI,OAAO,MAAM,SAAS;AACxB,YAAM,QAAQ,OAAO,MAAM;AAC3B,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,OAAO;AAAA,QACP,OAAO,EAAE,MAAM,OAAO,MAAM,QAAQ;AAAA,MACtC,CAAC;AAAA,IACH;AACA,QAAI,OAAO,MAAM,SAAS;AACxB,YAAM,aAAa;AACnB,YAAM,QAAQ,OAAO,MAAM;AAC3B,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,OAAO;AAAA,QACP,OAAO,EAAE,MAAM,OAAO,MAAM,QAAQ;AAAA,MACtC,CAAC;AAAA,IACH;AAEA,QAAI,OAAO,MAAM,YAAY;AAC3B,iBAAW,iBAAiB,OAAO,MAAM,YAAY;AACnD,cAAM,QAAQ,cAAc;AAC5B,YAAI,WAAW,MAAM,UAAU,IAAI,KAAK;AAExC,YAAI,CAAC,UAAU;AACb,qBAAW,EAAE,IAAI,IAAI,MAAM,IAAI,WAAW,GAAG;AAC7C,gBAAM,UAAU,IAAI,OAAO,QAAQ;AAAA,QACrC;AAEA,YAAI,cAAc,IAAI;AACpB,mBAAS,KAAK,cAAc;AAAA,QAC9B;AACA,YAAI,cAAc,UAAU,MAAM;AAChC,mBAAS,OAAO,cAAc,SAAS;AAAA,QACzC;AACA,YAAI,cAAc,UAAU,WAAW;AACrC,mBAAS,aAAa,cAAc,SAAS;AAC7C,iBAAO,KAAK;AAAA,YACV,MAAM;AAAA,YACN;AAAA,YACA,OAAO;AAAA,cACL,YAAY,SAAS;AAAA,cACrB,UAAU,SAAS;AAAA,cACnB,eAAe,cAAc,SAAS;AAAA,YACxC;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAEA,QAAI,OAAO,eAAe;AACxB,YAAM,eAAe,OAAO;AAC5B,aAAO,KAAK,EAAE,MAAM,gBAAgB,OAAO,GAAG,OAAO,CAAC,EAAE,CAAC;AAAA,IAC3D;AAAA,EACF;AAEA,MAAI,MAAM,OAAO;AACf,UAAM,cAAc,MAAM,MAAM;AAChC,UAAM,eAAe,MAAM,MAAM;AACjC,UAAM,kBAAkB,MAAM,MAAM,uBAAuB,iBAAiB;AAAA,EAC9E;AAEA,SAAO;AACT;AAYO,SAAS,uBAAuB,OAA4C;AACjF,QAAM,cAA2B,CAAC;AAClC,MAAI;AACJ,MAAI,MAAM,MAAM;AACd,gBAAY,KAAK,EAAE,MAAM,QAAQ,MAAM,MAAM,KAAK,CAAC;AACnD,QAAI;AACF,uBAAiB,KAAK,MAAM,MAAM,IAAI;AAAA,IACxC,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,QAAM,YAAwB,CAAC;AAC/B,aAAW,CAAC,EAAE,QAAQ,KAAK,MAAM,WAAW;AAC1C,QAAI,OAAgC,CAAC;AACrC,QAAI,SAAS,WAAW;AACtB,UAAI;AACF,eAAO,KAAK,MAAM,SAAS,SAAS;AAAA,MACtC,QAAQ;AAAA,MAER;AAAA,IACF;AACA,cAAU,KAAK;AAAA,MACb,YAAY,SAAS;AAAA,MACrB,UAAU,SAAS;AAAA,MACnB,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AAEA,QAAM,UAAU,IAAI;AAAA,IAClB;AAAA,IACA,UAAU,SAAS,IAAI,YAAY;AAAA,IACnC;AAAA,MACE,IAAI,MAAM;AAAA,MACV,UAAU;AAAA,QACR,QAAQ;AAAA,UACN,OAAO,MAAM;AAAA,UACb,eAAe,MAAM;AAAA,QACvB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAoB;AAAA,IACxB,aAAa,MAAM;AAAA,IACnB,cAAc,MAAM;AAAA,IACpB,aAAa,MAAM,cAAc,MAAM;AAAA,IACvC,iBAAiB,MAAM;AAAA,IACvB,kBAAkB;AAAA,EACpB;AAEA,MAAI,aAAa;AACjB,UAAQ,MAAM,cAAc;AAAA,IAC1B,KAAK;AACH,mBAAa;AACb;AAAA,IACF,KAAK;AACH,mBAAa;AACb;AAAA,IACF,KAAK;AACH,mBAAa;AACb;AAAA,IACF,KAAK;AACH,mBAAa;AACb;AAAA,EACJ;AACA,MAAI,MAAM,cAAc,eAAe,kBAAkB;AACvD,iBAAa;AAAA,EACf;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM;AAAA,EACR;AACF;;;ACjpBA,IAAM,iBAAiB;AAWvB,IAAM,sBAAuC;AAAA,EAC3C,WAAW;AAAA,EACX,OAAO;AAAA,EACP,kBAAkB;AAAA,EAClB,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY;AACd;AAqCO,SAAS,8BAAmE;AACjF,MAAI,cAA2D;AAE/D,SAAO;AAAA,IACL,aAAa,UAAgD;AAC3D,oBAAc;AAAA,IAChB;AAAA,IAEA,KAAK,SAAyD;AAE5D,UAAI,CAAC,aAAa;AAChB,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAEA,YAAM,QAAgD;AAAA,QACpD;AAAA,QACA,cAAc;AAAA,QAEd,IAAI,WAAiD;AACnD,iBAAO;AAAA,QACT;AAAA,QAEA,MAAM,SAAS,SAAoE;AACjF,gBAAM,SAAS,MAAM;AAAA,YACnB,QAAQ;AAAA,YACR;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAEA,gBAAM,UAAU,QAAQ,OAAO,WAAW;AAC1C,gBAAM,OAAO,iBAAiB,SAAS,OAAO;AAE9C,gBAAM,UAAkC;AAAA,YACtC,gBAAgB;AAAA,YAChB,eAAe,UAAU,MAAM;AAAA,UACjC;AAEA,cAAI,QAAQ,OAAO,SAAS;AAC1B,uBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,OAAO,OAAO,GAAG;AACjE,kBAAI,UAAU,QAAW;AACvB,wBAAQ,GAAG,IAAI;AAAA,cACjB;AAAA,YACF;AAAA,UACF;AAEA,gBAAM,WAAW,MAAM;AAAA,YACrB;AAAA,YACA;AAAA,cACE,QAAQ;AAAA,cACR;AAAA,cACA,MAAM,KAAK,UAAU,IAAI;AAAA,cACzB,QAAQ,QAAQ;AAAA,YAClB;AAAA,YACA,QAAQ;AAAA,YACR;AAAA,YACA;AAAA,UACF;AAEA,gBAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,iBAAO,kBAAkB,IAAI;AAAA,QAC/B;AAAA,QAEA,OAAO,SAA+D;AACpE,gBAAM,QAAQ,kBAAkB;AAChC,cAAI;AACJ,cAAI;AAEJ,gBAAM,kBAAkB,IAAI,QAAqB,CAAC,SAAS,WAAW;AACpE,8BAAkB;AAClB,6BAAiB;AAAA,UACnB,CAAC;AAED,0BAAgB,iBAA6D;AAC3E,gBAAI;AACF,oBAAM,SAAS,MAAM;AAAA,gBACnB,QAAQ;AAAA,gBACR;AAAA,gBACA;AAAA,gBACA;AAAA,cACF;AAEA,oBAAM,UAAU,QAAQ,OAAO,WAAW;AAC1C,oBAAM,OAAO,iBAAiB,SAAS,OAAO;AAC9C,mBAAK,SAAS;AACd,mBAAK,iBAAiB,EAAE,eAAe,KAAK;AAE5C,oBAAM,UAAkC;AAAA,gBACtC,gBAAgB;AAAA,gBAChB,eAAe,UAAU,MAAM;AAAA,cACjC;AAEA,kBAAI,QAAQ,OAAO,SAAS;AAC1B,2BAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,OAAO,OAAO,GAAG;AACjE,sBAAI,UAAU,QAAW;AACvB,4BAAQ,GAAG,IAAI;AAAA,kBACjB;AAAA,gBACF;AAAA,cACF;AAEA,oBAAM,WAAW,MAAM;AAAA,gBACrB;AAAA,gBACA;AAAA,kBACE,QAAQ;AAAA,kBACR;AAAA,kBACA,MAAM,KAAK,UAAU,IAAI;AAAA,kBACzB,QAAQ,QAAQ;AAAA,gBAClB;AAAA,gBACA,QAAQ;AAAA,gBACR;AAAA,gBACA;AAAA,cACF;AAEA,kBAAI,CAAC,SAAS,IAAI;AAChB,sBAAM,QAAQ,MAAM,mBAAmB,UAAU,UAAU,KAAK;AAChE,+BAAe,KAAK;AACpB,sBAAM;AAAA,cACR;AAEA,kBAAI,CAAC,SAAS,MAAM;AAClB,sBAAM,QAAQ,IAAI;AAAA,kBAChB;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,gBACF;AACA,+BAAe,KAAK;AACpB,sBAAM;AAAA,cACR;AAEA,+BAAiB,QAAQ,eAAe,SAAS,IAAI,GAAG;AAEtD,oBAAI,SAAS,UAAU;AACrB;AAAA,gBACF;AAGA,oBAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAC7C,wBAAM,QAAQ;AAGd,sBAAI,WAAW,SAAS,MAAM,OAAO;AACnC,0BAAM,YAAY,MAAM;AACxB,0BAAM,QAAQ,IAAI;AAAA,sBAChB,UAAU,WAAW;AAAA,sBACrB;AAAA,sBACA;AAAA,sBACA;AAAA,oBACF;AACA,mCAAe,KAAK;AACpB,0BAAM;AAAA,kBACR;AAEA,wBAAM,YAAY,qBAAqB,OAAO,KAAK;AACnD,6BAAW,SAAS,WAAW;AAC7B,0BAAM;AAAA,kBACR;AAAA,gBACF;AAAA,cACF;AAGA,8BAAgB,uBAAuB,KAAK,CAAC;AAAA,YAC/C,SAAS,OAAO;AACd,6BAAe,KAAc;AAC7B,oBAAM;AAAA,YACR;AAAA,UACF;AAEA,iBAAO;AAAA,YACL,CAAC,OAAO,aAAa,IAAI;AACvB,qBAAO,eAAe;AAAA,YACxB;AAAA,YACA,UAAU;AAAA,UACZ;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;AC3MO,SAASA,kBACd,SACA,SACwB;AACxB,QAAM,SAAS,QAAQ,UAAW,CAAC;AAEnC,QAAM,eAAe,OAAO;AAC5B,QAAM,EAAE,OAAO,cAAc,GAAG,WAAW,IAAI;AAE/C,QAAM,gBAAwC;AAAA,IAC5C,GAAG;AAAA,IACH,OAAO;AAAA,IACP,OAAO,oBAAoB,QAAQ,UAAU,QAAQ,MAAM;AAAA,EAC7D;AAEA,QAAM,gBAA4C,QAAQ,OAAO,IAAIC,cAAa,KAAK,CAAC;AACxF,QAAM,WAAuC,CAAC,GAAG,eAAe,GAAI,gBAAgB,CAAC,CAAE;AAEvF,MAAI,SAAS,SAAS,GAAG;AACvB,kBAAc,QAAQ;AAAA,EACxB;AAEA,MAAI,QAAQ,WAAW;AACrB,UAAM,SAAkC;AAAA,MACtC,MAAM;AAAA,MACN,YAAY,QAAQ,UAAU;AAAA,MAC9B,UAAU,QAAQ,UAAU;AAAA,MAC5B,GAAI,QAAQ,UAAU,yBAAyB,SAC3C,EAAE,sBAAsB,QAAQ,UAAU,qBAAqB,IAC/D,EAAE,sBAAsB,MAAM;AAAA,IACpC;AACA,QAAI,QAAQ,UAAU,aAAa;AACjC,aAAO,cAAc,QAAQ,UAAU;AAAA,IACzC;AAEA,kBAAc,OAAO;AAAA,MACnB,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,aAAa,QAAQ,UAAU;AAAA,QAC/B;AAAA,QACA,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAASC,iBAAgB,QAA4D;AACnF,MAAI,CAAC,OAAQ,QAAO;AACpB,MAAI,OAAO,WAAW,SAAU,QAAO;AACvC,SAAQ,OACL,IAAI,WAAS,MAAM,QAAQ,EAAE,EAC7B,OAAO,UAAQ,KAAK,SAAS,CAAC,EAC9B,KAAK,MAAM;AAChB;AAaA,SAAS,oBACP,UACA,QACqC;AACrC,QAAM,SAAqC,CAAC;AAC5C,QAAM,mBAAmBA,iBAAgB,MAAM;AAE/C,MAAI,kBAAkB;AACpB,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAEA,aAAW,WAAW,UAAU;AAC9B,UAAM,QAAQC,kBAAiB,OAAO;AACtC,WAAO,KAAK,GAAG,KAAK;AAAA,EACtB;AAEA,MAAI,OAAO,WAAW,KAAK,OAAO,CAAC,GAAG,SAAS,WAAW;AACxD,UAAM,OAAO,OAAO,CAAC;AACrB,QAAI,KAAK,SAAS,UAAU,OAAO,KAAK,YAAY,UAAU;AAC5D,aAAO,KAAK;AAAA,IACd;AAAA,EACF;AAEA,SAAO;AACT;AAQA,SAASC,oBAAgD,SAAmB;AAC1E,SAAO,QAAQ,OAAO,CAAC,MAAM,KAAK,OAAO,EAAE,SAAS,QAAQ;AAC9D;AAYA,SAASD,kBAAiB,SAA8C;AACtE,MAAI,cAAc,OAAO,GAAG;AAC1B,UAAM,eAAeC,oBAAmB,QAAQ,OAAO;AACvD,QAAI,aAAa,WAAW,KAAK,aAAa,CAAC,GAAG,SAAS,QAAQ;AACjE,aAAO;AAAA,QACL;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAU,aAAa,CAAC,EAAgB;AAAA,QAC1C;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,MACL;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,aAAa,IAAI,oBAAoB;AAAA,MAChD;AAAA,IACF;AAAA,EACF;AAEA,MAAI,mBAAmB,OAAO,GAAG;AAC/B,UAAM,eAAeA,oBAAmB,QAAQ,OAAO;AACvD,UAAM,QAAoC,CAAC;AAE3C,UAAM,eAA6C,aAChD,OAAO,CAAC,MAAsB,EAAE,SAAS,MAAM,EAC/C,IAAI,CAAC,OAAmC;AAAA,MACvC,MAAM;AAAA,MACN,MAAM,EAAE;AAAA,IACV,EAAE;AAEJ,QAAI,aAAa,SAAS,GAAG;AAC3B,YAAM,KAAK;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAEA,UAAM,aAAa,QAAQ,UAAU;AAGrC,UAAM,oBAAoB,YAAY;AAEtC,QAAI,qBAAqB,kBAAkB,SAAS,GAAG;AACrD,iBAAW,MAAM,mBAAmB;AAClC,cAAM,KAAK;AAAA,UACT,MAAM;AAAA,UACN,IAAI,GAAG;AAAA,UACP,SAAS,GAAG;AAAA,UACZ,MAAM,GAAG;AAAA,UACT,WAAW,GAAG;AAAA,QAChB,CAAC;AAAA,MACH;AAAA,IACF,WAAW,QAAQ,aAAa,QAAQ,UAAU,SAAS,GAAG;AAC5D,iBAAW,QAAQ,QAAQ,WAAW;AACpC,cAAM,KAAK;AAAA,UACT,MAAM;AAAA,UACN,IAAI,MAAM,KAAK,UAAU;AAAA,UACzB,SAAS,KAAK;AAAA,UACd,MAAM,KAAK;AAAA,UACX,WAAW,KAAK,UAAU,KAAK,SAAS;AAAA,QAC1C,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAEA,MAAI,oBAAoB,OAAO,GAAG;AAChC,WAAO,QAAQ,QAAQ,IAAI,CAAC,YAAY;AAAA,MACtC,MAAM;AAAA,MACN,SAAS,OAAO;AAAA,MAChB,QACE,OAAO,OAAO,WAAW,WACrB,OAAO,SACP,KAAK,UAAU,OAAO,MAAM;AAAA,IACpC,EAAE;AAAA,EACJ;AAEA,SAAO,CAAC;AACV;AAYA,SAAS,qBAAqB,OAAiD;AAC7E,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AACH,aAAO,EAAE,MAAM,cAAc,MAAM,MAAM,KAAK;AAAA,IAEhD,KAAK,SAAS;AACZ,YAAM,aAAa;AACnB,UAAI,WAAW,OAAO,SAAS,UAAU;AACvC,eAAO;AAAA,UACL,MAAM;AAAA,UACN,WAAW,QAAQ,WAAW,QAAQ,WAAW,WAAW,OAAO,IAAI;AAAA,QACzE;AAAA,MACF;AAEA,UAAI,WAAW,OAAO,SAAS,OAAO;AACpC,eAAO;AAAA,UACL,MAAM;AAAA,UACN,WAAW,WAAW,OAAO;AAAA,QAC/B;AAAA,MACF;AAEA,UAAI,WAAW,OAAO,SAAS,SAAS;AACtC,cAAM,SAAS;AAAA,UACb,MAAM,KAAK,WAAW,OAAO,IAAI,EAC9B,IAAI,CAAC,MAAM,OAAO,aAAa,CAAC,CAAC,EACjC,KAAK,EAAE;AAAA,QACZ;AACA,eAAO;AAAA,UACL,MAAM;AAAA,UACN,WAAW,QAAQ,WAAW,QAAQ,WAAW,MAAM;AAAA,QACzD;AAAA,MACF;AAEA,YAAM,IAAI,MAAM,2BAA2B;AAAA,IAC7C;AAAA,IAEA;AACE,YAAM,IAAI,MAAM,6BAA6B,MAAM,IAAI,EAAE;AAAA,EAC7D;AACF;AAQA,SAASC,oBAAmB,MAAkC;AAC5D,QAAM,aAAa,KAAK,UAAU;AAGlC,SAAO,EAAE,QAAQ,YAAY,OAAO;AACtC;AAsBA,SAASJ,eAAc,MAAiC;AACtD,QAAM,EAAE,OAAO,IAAII,oBAAmB,IAAI;AAE1C,SAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM,KAAK;AAAA,IACX,aAAa,KAAK;AAAA,IAClB,YAAY;AAAA,MACV,MAAM;AAAA,MACN,YAAY,KAAK,WAAW;AAAA,MAC5B,UAAU,KAAK,WAAW;AAAA,MAC1B,GAAI,KAAK,WAAW,yBAAyB,SACzC,EAAE,sBAAsB,KAAK,WAAW,qBAAqB,IAC7D,CAAC;AAAA,IACP;AAAA,IACA,GAAI,WAAW,SAAY,EAAE,OAAO,IAAI,CAAC;AAAA,EAC3C;AACF;AAYO,SAASC,mBAAkB,MAA4C;AAC5E,QAAM,UAA8B,CAAC;AACrC,QAAM,YAAwB,CAAC;AAC/B,QAAM,oBAKD,CAAC;AACN,MAAI,aAAa;AACjB,MAAI;AAEJ,aAAW,QAAQ,KAAK,QAAQ;AAC9B,QAAI,KAAK,SAAS,WAAW;AAC3B,YAAM,cAAc;AACpB,iBAAW,QAAQ,YAAY,SAAS;AACtC,YAAI,KAAK,SAAS,eAAe;AAC/B,kBAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,KAAK,KAAK,CAAC;AAC9C,cAAI,mBAAmB,QAAW;AAChC,gBAAI;AACF,+BAAiB,KAAK,MAAM,KAAK,IAAI;AAAA,YACvC,QAAQ;AAAA,YAER;AAAA,UACF;AAAA,QACF,WAAW,KAAK,SAAS,WAAW;AAClC,kBAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,KAAK,QAAQ,CAAC;AACjD,uBAAa;AAAA,QACf;AAAA,MACF;AAAA,IACF,WAAW,KAAK,SAAS,iBAAiB;AACxC,YAAM,eAAe;AACrB,UAAI,OAAgC,CAAC;AACrC,UAAI;AACF,eAAO,KAAK,MAAM,aAAa,SAAS;AAAA,MAC1C,QAAQ;AAAA,MAER;AACA,gBAAU,KAAK;AAAA,QACb,YAAY,aAAa;AAAA,QACzB,UAAU,aAAa;AAAA,QACvB,WAAW;AAAA,MACb,CAAC;AACD,wBAAkB,KAAK;AAAA,QACrB,IAAI,aAAa;AAAA,QACjB,SAAS,aAAa;AAAA,QACtB,MAAM,aAAa;AAAA,QACnB,WAAW,aAAa;AAAA,MAC1B,CAAC;AAAA,IACH,WAAW,KAAK,SAAS,yBAAyB;AAChD,YAAM,WAAW;AACjB,UAAI,SAAS,QAAQ;AACnB,gBAAQ,KAAK;AAAA,UACX,MAAM;AAAA,UACN,UAAU;AAAA,UACV,QAAQ,EAAE,MAAM,UAAU,MAAM,SAAS,OAAO;AAAA,QAClD,CAAe;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAAU,IAAI;AAAA,IAClB;AAAA,IACA,UAAU,SAAS,IAAI,YAAY;AAAA,IACnC;AAAA,MACE,IAAI,KAAK;AAAA,MACT,UAAU;AAAA,QACR,QAAQ;AAAA,UACN,OAAO,KAAK;AAAA,UACZ,QAAQ,KAAK;AAAA,UACb,aAAa,KAAK;AAAA,UAClB,mBACE,kBAAkB,SAAS,IAAI,oBAAoB;AAAA,QACvD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAoB;AAAA,IACxB,aAAa,KAAK,MAAM;AAAA,IACxB,cAAc,KAAK,MAAM;AAAA,IACzB,aAAa,KAAK,MAAM;AAAA,IACxB,iBAAiB,KAAK,MAAM,sBAAsB,iBAAiB;AAAA,IACnE,kBAAkB;AAAA,EACpB;AAEA,MAAI,aAAa;AACjB,MAAI,KAAK,WAAW,aAAa;AAC/B,iBAAa,UAAU,SAAS,IAAI,aAAa;AAAA,EACnD,WAAW,KAAK,WAAW,cAAc;AACvC,iBAAa,KAAK,oBAAoB,WAAW,sBAC7C,eACA;AAAA,EACN,WAAW,KAAK,WAAW,UAAU;AACnC,iBAAa;AAAA,EACf;AACA,MAAI,cAAc,eAAe,SAAS;AACxC,iBAAa;AAAA,EACf;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM;AAAA,EACR;AACF;AAwCO,SAASC,qBAA0C;AACxD,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa,oBAAI,IAAI;AAAA,IACrB,WAAW,oBAAI,IAAI;AAAA,IACnB,QAAQ,CAAC;AAAA,IACT,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,YAAY;AAAA,EACd;AACF;AAaO,SAASC,sBACd,OACA,OACe;AACf,QAAM,SAAwB,CAAC;AAE/B,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AACH,YAAM,KAAK,MAAM,SAAS;AAC1B,YAAM,QAAQ,MAAM,SAAS;AAC7B,aAAO,KAAK,EAAE,MAAM,iBAAiB,OAAO,GAAG,OAAO,CAAC,EAAE,CAAC;AAC1D;AAAA,IAEF,KAAK;AACH,YAAM,SAAS;AACf;AAAA,IAEF,KAAK;AACH,YAAM,SAAS;AACf,UAAI,MAAM,SAAS,OAAO;AACxB,cAAM,cAAc,MAAM,SAAS,MAAM;AACzC,cAAM,eAAe,MAAM,SAAS,MAAM;AAC1C,cAAM,kBAAkB,MAAM,SAAS,MAAM,sBAAsB,iBAAiB;AAAA,MACtF;AACA,aAAO,KAAK,EAAE,MAAM,gBAAgB,OAAO,GAAG,OAAO,CAAC,EAAE,CAAC;AACzD;AAAA,IAEF,KAAK;AACH,YAAM,SAAS;AACf,aAAO,KAAK,EAAE,MAAM,gBAAgB,OAAO,GAAG,OAAO,CAAC,EAAE,CAAC;AACzD;AAAA,IAEF,KAAK;AACH,UAAI,MAAM,KAAK,SAAS,iBAAiB;AACvC,cAAM,eAAe,MAAM;AAC3B,cAAM,WAAW,MAAM,UAAU,IAAI,MAAM,YAAY,KAAK;AAAA,UAC1D,WAAW;AAAA,QACb;AACA,iBAAS,SAAS,aAAa;AAC/B,iBAAS,SAAS,aAAa;AAC/B,iBAAS,OAAO,aAAa;AAC7B,YAAI,aAAa,WAAW;AAC1B,mBAAS,YAAY,aAAa;AAAA,QACpC;AACA,cAAM,UAAU,IAAI,MAAM,cAAc,QAAQ;AAAA,MAClD;AACA,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,OAAO,MAAM;AAAA,QACb,OAAO,CAAC;AAAA,MACV,CAAC;AACD;AAAA,IAEF,KAAK;AACH,UAAI,MAAM,KAAK,SAAS,iBAAiB;AACvC,cAAM,eAAe,MAAM;AAC3B,cAAM,WAAW,MAAM,UAAU,IAAI,MAAM,YAAY,KAAK;AAAA,UAC1D,WAAW;AAAA,QACb;AACA,iBAAS,SAAS,aAAa;AAC/B,iBAAS,SAAS,aAAa;AAC/B,iBAAS,OAAO,aAAa;AAC7B,YAAI,aAAa,WAAW;AAC1B,mBAAS,YAAY,aAAa;AAAA,QACpC;AACA,cAAM,UAAU,IAAI,MAAM,cAAc,QAAQ;AAAA,MAClD,WAAW,MAAM,KAAK,SAAS,yBAAyB;AACtD,cAAM,WAAW,MAAM;AACvB,YAAI,SAAS,QAAQ;AACnB,gBAAM,OAAO,KAAK,SAAS,MAAM;AAAA,QACnC;AAAA,MACF;AACA,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,OAAO,MAAM;AAAA,QACb,OAAO,CAAC;AAAA,MACV,CAAC;AACD;AAAA,IAEF,KAAK,8BAA8B;AACjC,YAAM,cAAc,MAAM,YAAY,IAAI,MAAM,YAAY,KAAK;AACjE,YAAM,YAAY,IAAI,MAAM,cAAc,cAAc,MAAM,KAAK;AACnE,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,OAAO,MAAM;AAAA,QACb,OAAO,EAAE,MAAM,MAAM,MAAM;AAAA,MAC7B,CAAC;AACD;AAAA,IACF;AAAA,IAEA,KAAK;AACH,YAAM,YAAY,IAAI,MAAM,cAAc,MAAM,IAAI;AACpD;AAAA,IAEF,KAAK,0BAA0B;AAC7B,YAAM,aAAa;AACnB,YAAM,iBAAiB,MAAM,YAAY,IAAI,MAAM,YAAY,KAAK;AACpE,YAAM,YAAY,IAAI,MAAM,cAAc,iBAAiB,MAAM,KAAK;AACtE,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,OAAO,MAAM;AAAA,QACb,OAAO,EAAE,MAAM,MAAM,MAAM;AAAA,MAC7B,CAAC;AACD;AAAA,IACF;AAAA,IAEA,KAAK;AACH,YAAM,aAAa;AACnB,YAAM,YAAY,IAAI,MAAM,cAAc,MAAM,OAAO;AACvD;AAAA,IAEF,KAAK,0CAA0C;AAC7C,UAAI,WAAW,MAAM,UAAU,IAAI,MAAM,YAAY;AACrD,UAAI,CAAC,UAAU;AACb,mBAAW,EAAE,WAAW,GAAG;AAC3B,cAAM,UAAU,IAAI,MAAM,cAAc,QAAQ;AAAA,MAClD;AACA,UAAI,MAAM,WAAW,CAAC,SAAS,QAAQ;AACrC,iBAAS,SAAS,MAAM;AAAA,MAC1B;AACA,UAAI,MAAM,WAAW,CAAC,SAAS,QAAQ;AACrC,iBAAS,SAAS,MAAM;AAAA,MAC1B;AACA,eAAS,aAAa,MAAM;AAC5B,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,OAAO,MAAM;AAAA,QACb,OAAO;AAAA,UACL,YAAY,SAAS,UAAU,SAAS,UAAU;AAAA,UAClD,UAAU,SAAS;AAAA,UACnB,eAAe,MAAM;AAAA,QACvB;AAAA,MACF,CAAC;AACD;AAAA,IACF;AAAA,IAEA,KAAK,yCAAyC;AAC5C,UAAI,WAAW,MAAM,UAAU,IAAI,MAAM,YAAY;AACrD,UAAI,CAAC,UAAU;AACb,mBAAW,EAAE,WAAW,GAAG;AAC3B,cAAM,UAAU,IAAI,MAAM,cAAc,QAAQ;AAAA,MAClD;AACA,UAAI,MAAM,SAAS;AACjB,iBAAS,SAAS,MAAM;AAAA,MAC1B;AACA,UAAI,MAAM,SAAS;AACjB,iBAAS,SAAS,MAAM;AAAA,MAC1B;AACA,eAAS,OAAO,MAAM;AACtB,eAAS,YAAY,MAAM;AAC3B;AAAA,IACF;AAAA,IAEA,KAAK;AACH;AAAA,IAEF;AACE;AAAA,EACJ;AAEA,SAAO;AACT;AAYO,SAASC,wBAAuB,OAA0C;AAC/E,QAAM,UAA8B,CAAC;AACrC,MAAI;AAEJ,aAAW,CAAC,EAAE,IAAI,KAAK,MAAM,aAAa;AACxC,QAAI,MAAM;AACR,cAAQ,KAAK,EAAE,MAAM,QAAQ,KAAK,CAAC;AACnC,UAAI,mBAAmB,QAAW;AAChC,YAAI;AACF,2BAAiB,KAAK,MAAM,IAAI;AAAA,QAClC,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,aAAW,aAAa,MAAM,QAAQ;AACpC,YAAQ,KAAK;AAAA,MACX,MAAM;AAAA,MACN,UAAU;AAAA,MACV,QAAQ,EAAE,MAAM,UAAU,MAAM,UAAU;AAAA,IAC5C,CAAe;AAAA,EACjB;AAEA,QAAM,YAAwB,CAAC;AAC/B,QAAM,oBAKD,CAAC;AACN,aAAW,CAAC,EAAE,QAAQ,KAAK,MAAM,WAAW;AAC1C,QAAI,OAAgC,CAAC;AACrC,QAAI,SAAS,WAAW;AACtB,UAAI;AACF,eAAO,KAAK,MAAM,SAAS,SAAS;AAAA,MACtC,QAAQ;AAAA,MAER;AAAA,IACF;AACA,UAAM,SAAS,SAAS,UAAU;AAClC,UAAM,SAAS,SAAS,UAAU,SAAS,UAAU;AACrD,UAAM,OAAO,SAAS,QAAQ;AAC9B,cAAU,KAAK;AAAA,MACb,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,WAAW;AAAA,IACb,CAAC;AAED,QAAI,UAAU,UAAU,MAAM;AAC5B,wBAAkB,KAAK;AAAA,QACrB,IAAI;AAAA,QACJ,SAAS;AAAA,QACT;AAAA,QACA,WAAW,SAAS;AAAA,MACtB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,UAAU,IAAI;AAAA,IAClB;AAAA,IACA,UAAU,SAAS,IAAI,YAAY;AAAA,IACnC;AAAA,MACE,IAAI,MAAM;AAAA,MACV,UAAU;AAAA,QACR,QAAQ;AAAA,UACN,OAAO,MAAM;AAAA,UACb,QAAQ,MAAM;AAAA,UACd,aAAa,MAAM;AAAA,UACnB,mBACE,kBAAkB,SAAS,IAAI,oBAAoB;AAAA,QACvD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAoB;AAAA,IACxB,aAAa,MAAM;AAAA,IACnB,cAAc,MAAM;AAAA,IACpB,aAAa,MAAM,cAAc,MAAM;AAAA,IACvC,iBAAiB,MAAM;AAAA,IACvB,kBAAkB;AAAA,EACpB;AAEA,MAAI,aAAa;AACjB,MAAI,MAAM,WAAW,aAAa;AAChC,iBAAa,UAAU,SAAS,IAAI,aAAa;AAAA,EACnD,WAAW,MAAM,WAAW,UAAU;AACpC,iBAAa;AAAA,EACf;AACA,MAAI,MAAM,cAAc,eAAe,SAAS;AAC9C,iBAAa;AAAA,EACf;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM;AAAA,EACR;AACF;;;ACnyBA,IAAM,2BAA2B;AAWjC,IAAMC,uBAAuC;AAAA,EAC3C,WAAW;AAAA,EACX,OAAO;AAAA,EACP,kBAAkB;AAAA,EAClB,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY;AACd;AAoDO,SAAS,4BAA+D;AAC7E,MAAI,cAAyD;AAE7D,SAAO;AAAA,IACL,aAAa,UAA8C;AACzD,oBAAc;AAAA,IAChB;AAAA,IAEA,KAAK,SAAuD;AAE1D,UAAI,CAAC,aAAa;AAChB,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAEA,YAAM,QAA8C;AAAA,QAClD;AAAA,QACA,cAAcA;AAAA,QAEd,IAAI,WAA+C;AACjD,iBAAO;AAAA,QACT;AAAA,QAEA,MAAM,SAAS,SAAkE;AAC/E,gBAAM,SAAS,MAAM;AAAA,YACnB,QAAQ;AAAA,YACR;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAEA,gBAAM,UAAU,QAAQ,OAAO,WAAW;AAC1C,gBAAM,OAAOC,kBAAiB,SAAS,OAAO;AAE9C,gBAAM,UAAkC;AAAA,YACtC,gBAAgB;AAAA,YAChB,eAAe,UAAU,MAAM;AAAA,UACjC;AAEA,cAAI,QAAQ,OAAO,SAAS;AAC1B,uBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,OAAO,OAAO,GAAG;AACjE,kBAAI,UAAU,QAAW;AACvB,wBAAQ,GAAG,IAAI;AAAA,cACjB;AAAA,YACF;AAAA,UACF;AAEA,gBAAM,WAAW,MAAM;AAAA,YACrB;AAAA,YACA;AAAA,cACE,QAAQ;AAAA,cACR;AAAA,cACA,MAAM,KAAK,UAAU,IAAI;AAAA,cACzB,QAAQ,QAAQ;AAAA,YAClB;AAAA,YACA,QAAQ;AAAA,YACR;AAAA,YACA;AAAA,UACF;AAEA,gBAAM,OAAQ,MAAM,SAAS,KAAK;AAGlC,cAAI,KAAK,WAAW,YAAY,KAAK,OAAO;AAC1C,kBAAM,IAAI;AAAA,cACR,KAAK,MAAM;AAAA,cACX;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAEA,iBAAOC,mBAAkB,IAAI;AAAA,QAC/B;AAAA,QAEA,OAAO,SAA6D;AAClE,gBAAM,QAAQC,mBAAkB;AAChC,cAAI;AACJ,cAAI;AAEJ,gBAAM,kBAAkB,IAAI,QAAqB,CAAC,SAAS,WAAW;AACpE,8BAAkB;AAClB,6BAAiB;AAAA,UACnB,CAAC;AAED,0BAAgB,iBAA6D;AAC3E,gBAAI;AACF,oBAAM,SAAS,MAAM;AAAA,gBACnB,QAAQ;AAAA,gBACR;AAAA,gBACA;AAAA,gBACA;AAAA,cACF;AAEA,oBAAM,UAAU,QAAQ,OAAO,WAAW;AAC1C,oBAAM,OAAOF,kBAAiB,SAAS,OAAO;AAC9C,mBAAK,SAAS;AAEd,oBAAM,UAAkC;AAAA,gBACtC,gBAAgB;AAAA,gBAChB,eAAe,UAAU,MAAM;AAAA,cACjC;AAEA,kBAAI,QAAQ,OAAO,SAAS;AAC1B,2BAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,OAAO,OAAO,GAAG;AACjE,sBAAI,UAAU,QAAW;AACvB,4BAAQ,GAAG,IAAI;AAAA,kBACjB;AAAA,gBACF;AAAA,cACF;AAEA,oBAAM,WAAW,MAAM;AAAA,gBACrB;AAAA,gBACA;AAAA,kBACE,QAAQ;AAAA,kBACR;AAAA,kBACA,MAAM,KAAK,UAAU,IAAI;AAAA,kBACzB,QAAQ,QAAQ;AAAA,gBAClB;AAAA,gBACA,QAAQ;AAAA,gBACR;AAAA,gBACA;AAAA,cACF;AAEA,kBAAI,CAAC,SAAS,IAAI;AAChB,sBAAM,QAAQ,MAAM,mBAAmB,UAAU,UAAU,KAAK;AAChE,+BAAe,KAAK;AACpB,sBAAM;AAAA,cACR;AAEA,kBAAI,CAAC,SAAS,MAAM;AAClB,sBAAM,QAAQ,IAAI;AAAA,kBAChB;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,gBACF;AACA,+BAAe,KAAK;AACpB,sBAAM;AAAA,cACR;AAEA,+BAAiB,QAAQ,eAAe,SAAS,IAAI,GAAG;AAEtD,oBAAI,SAAS,UAAU;AACrB;AAAA,gBACF;AAGA,oBAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAC7C,wBAAM,QAAQ;AAGd,sBAAI,MAAM,SAAS,SAAS;AAC1B,0BAAM,aAAa;AACnB,0BAAM,QAAQ,IAAI;AAAA,sBAChB,WAAW,MAAM;AAAA,sBACjB;AAAA,sBACA;AAAA,sBACA;AAAA,oBACF;AACA,mCAAe,KAAK;AACpB,0BAAM;AAAA,kBACR;AAEA,wBAAM,YAAYG,sBAAqB,OAAO,KAAK;AACnD,6BAAW,YAAY,WAAW;AAChC,0BAAM;AAAA,kBACR;AAAA,gBACF;AAAA,cACF;AAGA,8BAAgBC,wBAAuB,KAAK,CAAC;AAAA,YAC/C,SAAS,OAAO;AACd,6BAAe,KAAc;AAC7B,oBAAM;AAAA,YACR;AAAA,UACF;AAEA,iBAAO;AAAA,YACL,CAAC,OAAO,aAAa,IAAI;AACvB,qBAAO,eAAe;AAAA,YACxB;AAAA,YACA,UAAU;AAAA,UACZ;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;ACo9BO,SAAS,cAAc,SAGN;AACtB,MAAI,SAAS;AACX,WAAO;AAAA,MACL,MAAM;AAAA,MACN,GAAG;AAAA,IACL;AAAA,EACF;AACA,SAAO,EAAE,MAAM,aAAa;AAC9B;AAkBO,SAAS,eAAe,SAQN;AACvB,SAAO;AAAA,IACL,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AACF;AA0BO,SAAS,oBAAoB,SAEN;AAC5B,SAAO;AAAA,IACL,MAAM;AAAA,IACN,GAAI,SAAS,aAAa,EAAE,kBAAkB,EAAE,WAAW,QAAQ,UAAU,EAAE;AAAA,EACjF;AACF;AAoBO,SAAS,aAAa,SAIN;AACrB,SAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,EACZ;AACF;AAuBO,SAAS,oBAAoB,SAMN;AAC5B,MAAI,SAAS;AACX,WAAO;AAAA,MACL,MAAM;AAAA,MACN,GAAG;AAAA,IACL;AAAA,EACF;AACA,SAAO,EAAE,MAAM,mBAAmB;AACpC;AAoBO,SAAS,QAAQ,SAMN;AAChB,QAAM,EAAE,KAAK,MAAM,eAAe,SAAS,iBAAiB,IAAI;AAChE,SAAO;AAAA,IACL,MAAM;AAAA,IACN,KAAK;AAAA,MACH,QAAQ;AAAA,QACN;AAAA,QACA;AAAA,QACA,GAAI,iBAAiB,EAAE,oBAAoB,EAAE,cAAc,EAAE;AAAA,QAC7D;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAqBO,IAAM,QAAQ;AAAA;AAAA,EAEnB,WAAW;AAAA;AAAA,EAEX,YAAY;AAAA;AAAA,EAEZ,iBAAiB;AAAA;AAAA,EAEjB,UAAU;AAAA;AAAA,EAEV,iBAAiB;AAAA;AAAA,EAEjB,KAAK;AACP;;;AC90CA,SAAS,uBAAuC;AAC9C,MAAI,iBAA8C;AAElD,QAAM,mBAAmB,0BAA0B;AACnD,QAAM,qBAAqB,4BAA4B;AAEvD,QAAM,KAAK,SACT,SACA,SACuC;AACvC,UAAM,UAAU,SAAS,OAAO;AAChC,qBAAiB;AACjB,WAAO,EAAE,SAAS,SAAS;AAAA,EAC7B;AAEA,QAAM,aAAa;AAAA,IACjB,IAAI,MAAwC;AAC1C,aAAO,mBAAmB,gBACrB,qBACA;AAAA,IACP;AAAA,EACF;AAEA,SAAO,iBAAiB,IAAI;AAAA,IAC1B,MAAM;AAAA,MACJ,OAAO;AAAA,MACP,UAAU;AAAA,MACV,cAAc;AAAA,IAChB;AAAA,IACA,SAAS;AAAA,MACP,OAAO;AAAA,MACP,UAAU;AAAA,MACV,cAAc;AAAA,IAChB;AAAA,IACA,YAAY;AAAA,MACV,OAAO;AAAA,MACP,UAAU;AAAA,MACV,cAAc;AAAA,IAChB;AAAA,EACF,CAAC;AAED,QAAM,WAAW;AAEjB,mBAAiB,eAAe,QAAyD;AACzF,qBAAmB,eAAe,QAA2D;AAE7F,SAAO;AACT;AA2CO,IAAM,SAAS,qBAAqB;","names":["transformRequest","transformTool","normalizeSystem","transformMessage","filterValidContent","extractToolOptions","transformResponse","createStreamState","transformStreamEvent","buildResponseFromState","OPENAI_CAPABILITIES","transformRequest","transformResponse","createStreamState","transformStreamEvent","buildResponseFromState"]}
|
|
1
|
+
{"version":3,"sources":["../../src/providers/openai/transform.completions.ts","../../src/providers/openai/llm.completions.ts","../../src/providers/openai/transform.responses.ts","../../src/providers/openai/llm.responses.ts","../../src/providers/openai/types.ts","../../src/providers/openai/index.ts"],"sourcesContent":["/**\n * @fileoverview Chat Completions API Message Transformers\n *\n * This module provides transformation functions for converting between the\n * Universal Provider Protocol (UPP) message format and OpenAI's Chat Completions\n * API format. It handles both request transformation (UPP -> OpenAI) and response\n * transformation (OpenAI -> UPP), including streaming event transformation.\n *\n * Key transformations handled:\n * - Message format conversion (user, assistant, system, tool messages)\n * - Content block handling (text, images)\n * - Tool/function definition and call transformation\n * - Structured output (JSON schema) configuration\n * - Streaming state accumulation and event mapping\n *\n * @module providers/openai/transform.completions\n */\n\nimport type { LLMRequest, LLMResponse } from '../../types/llm.ts';\nimport type { Message } from '../../types/messages.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport type { Tool, ToolCall } from '../../types/tool.ts';\nimport type { TokenUsage } from '../../types/turn.ts';\nimport type { ContentBlock, TextBlock, ImageBlock } from '../../types/content.ts';\nimport {\n AssistantMessage,\n isUserMessage,\n isAssistantMessage,\n isToolResultMessage,\n} from '../../types/messages.ts';\nimport type {\n OpenAICompletionsParams,\n OpenAICompletionsRequest,\n OpenAICompletionsMessage,\n OpenAIUserContent,\n OpenAICompletionsTool,\n OpenAICompletionsResponse,\n OpenAICompletionsStreamChunk,\n OpenAIToolCall,\n} from './types.ts';\n\n/**\n * Transforms a UPP LLM request into OpenAI Chat Completions API format.\n *\n * This function converts the universal request format to OpenAI's specific\n * structure. Parameters are spread directly to support pass-through of any\n * OpenAI API fields, enabling use of new API features without library updates.\n *\n * @param request - The UPP LLM request containing messages, tools, and configuration\n * @param modelId - The OpenAI model identifier (e.g., 'gpt-4o', 'gpt-4-turbo')\n * @returns An OpenAI Chat Completions API request body\n *\n * @example\n * ```typescript\n * const openaiRequest = transformRequest({\n * messages: [userMessage('Hello!')],\n * params: { temperature: 0.7, max_tokens: 1000 },\n * config: { apiKey: 'sk-...' }\n * }, 'gpt-4o');\n * ```\n */\nexport function transformRequest(\n request: LLMRequest<OpenAICompletionsParams>,\n modelId: string\n): OpenAICompletionsRequest {\n const params = request.params ?? ({} as OpenAICompletionsParams);\n\n const openaiRequest: OpenAICompletionsRequest = {\n ...params,\n model: modelId,\n messages: transformMessages(request.messages, request.system),\n };\n\n if (request.tools && request.tools.length > 0) {\n openaiRequest.tools = request.tools.map(transformTool);\n }\n\n if (request.structure) {\n const schema: Record<string, unknown> = {\n type: 'object',\n properties: request.structure.properties,\n required: request.structure.required,\n ...(request.structure.additionalProperties !== undefined\n ? { additionalProperties: request.structure.additionalProperties }\n : { additionalProperties: false }),\n };\n if (request.structure.description) {\n schema.description = request.structure.description;\n }\n\n openaiRequest.response_format = {\n type: 'json_schema',\n json_schema: {\n name: 'json_response',\n description: request.structure.description,\n schema,\n strict: true,\n },\n };\n }\n\n return openaiRequest;\n}\n\n/**\n * Normalizes system prompt to string.\n * Converts array format to concatenated string for providers that only support strings.\n */\nfunction normalizeSystem(system: string | unknown[] | undefined): string | undefined {\n if (!system) return undefined;\n if (typeof system === 'string') return system;\n // Array format: extract text from each block and join\n return (system as Array<{text?: string}>)\n .map(block => block.text ?? '')\n .filter(text => text.length > 0)\n .join('\\n\\n');\n}\n\n/**\n * Transforms UPP messages to OpenAI Chat Completions message format.\n *\n * Handles system prompt injection as the first message and processes\n * all message types including tool result messages which may expand\n * into multiple OpenAI messages.\n *\n * @param messages - Array of UPP messages to transform\n * @param system - Optional system prompt (string or array, normalized to string)\n * @returns Array of OpenAI-formatted messages\n */\nfunction transformMessages(\n messages: Message[],\n system?: string | unknown[]\n): OpenAICompletionsMessage[] {\n const result: OpenAICompletionsMessage[] = [];\n const normalizedSystem = normalizeSystem(system);\n\n if (normalizedSystem) {\n result.push({\n role: 'system',\n content: normalizedSystem,\n });\n }\n\n for (const message of messages) {\n if (isToolResultMessage(message)) {\n const toolMessages = transformToolResults(message);\n result.push(...toolMessages);\n } else {\n const transformed = transformMessage(message);\n if (transformed) {\n result.push(transformed);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Filters content blocks to only include those with a valid type property.\n *\n * @param content - Array of content blocks to filter\n * @returns Filtered array containing only valid content blocks\n */\nfunction filterValidContent<T extends { type?: string }>(content: T[]): T[] {\n return content.filter((c) => c && typeof c.type === 'string');\n}\n\n/**\n * Transforms a single UPP message to OpenAI Chat Completions format.\n *\n * Handles user, assistant, and tool result messages. For user messages,\n * optimizes to use simple string content when possible. For assistant\n * messages, extracts text and tool calls.\n *\n * @param message - The UPP message to transform\n * @returns The transformed OpenAI message, or null if transformation fails\n */\nfunction transformMessage(message: Message): OpenAICompletionsMessage | null {\n if (isUserMessage(message)) {\n const validContent = filterValidContent(message.content);\n if (validContent.length === 1 && validContent[0]?.type === 'text') {\n return {\n role: 'user',\n content: (validContent[0] as TextBlock).text,\n };\n }\n return {\n role: 'user',\n content: validContent.map(transformContentBlock),\n };\n }\n\n if (isAssistantMessage(message)) {\n const validContent = filterValidContent(message.content);\n const textContent = validContent\n .filter((c): c is TextBlock => c.type === 'text')\n .map((c) => c.text)\n .join('');\n\n const assistantMessage: OpenAICompletionsMessage = {\n role: 'assistant',\n content: textContent || null,\n };\n\n if (message.toolCalls && message.toolCalls.length > 0) {\n (assistantMessage as { tool_calls?: OpenAIToolCall[] }).tool_calls =\n message.toolCalls.map((call) => ({\n id: call.toolCallId,\n type: 'function' as const,\n function: {\n name: call.toolName,\n arguments: JSON.stringify(call.arguments),\n },\n }));\n }\n\n return assistantMessage;\n }\n\n if (isToolResultMessage(message)) {\n const results = message.results.map((result) => ({\n role: 'tool' as const,\n tool_call_id: result.toolCallId,\n content:\n typeof result.result === 'string'\n ? result.result\n : JSON.stringify(result.result),\n }));\n\n return results[0] ?? null;\n }\n\n return null;\n}\n\n/**\n * Transforms tool result messages into multiple OpenAI tool messages.\n *\n * OpenAI requires each tool result to be sent as a separate message with\n * a `tool` role. This function expands a single UPP tool result message\n * containing multiple results into the corresponding OpenAI messages.\n *\n * @param message - The UPP message to transform (should be a tool result message)\n * @returns Array of OpenAI tool messages\n */\nexport function transformToolResults(\n message: Message\n): OpenAICompletionsMessage[] {\n if (!isToolResultMessage(message)) {\n const single = transformMessage(message);\n return single ? [single] : [];\n }\n\n return message.results.map((result) => ({\n role: 'tool' as const,\n tool_call_id: result.toolCallId,\n content:\n typeof result.result === 'string'\n ? result.result\n : JSON.stringify(result.result),\n }));\n}\n\n/**\n * Transforms a UPP content block to OpenAI user content format.\n *\n * Handles text and image content blocks. Images are converted to\n * data URLs for base64 and bytes sources, or passed through for URL sources.\n *\n * @param block - The content block to transform\n * @returns The transformed OpenAI content part\n * @throws Error if the content type is unsupported or image source type is unknown\n */\nfunction transformContentBlock(block: ContentBlock): OpenAIUserContent {\n switch (block.type) {\n case 'text':\n return { type: 'text', text: block.text };\n\n case 'image': {\n const imageBlock = block as ImageBlock;\n let url: string;\n\n if (imageBlock.source.type === 'base64') {\n url = `data:${imageBlock.mimeType};base64,${imageBlock.source.data}`;\n } else if (imageBlock.source.type === 'url') {\n url = imageBlock.source.url;\n } else if (imageBlock.source.type === 'bytes') {\n const base64 = btoa(\n Array.from(imageBlock.source.data)\n .map((b) => String.fromCharCode(b))\n .join('')\n );\n url = `data:${imageBlock.mimeType};base64,${base64}`;\n } else {\n throw new Error('Unknown image source type');\n }\n\n return {\n type: 'image_url',\n image_url: { url },\n };\n }\n\n default:\n throw new Error(`Unsupported content type: ${block.type}`);\n }\n}\n\n/**\n * Extracts OpenAI-specific options from tool metadata.\n *\n * @param tool - The tool to extract options from\n * @returns The OpenAI options if present (currently supports `strict`)\n */\nfunction extractToolOptions(tool: Tool): { strict?: boolean } {\n const openaiMeta = tool.metadata?.openai as\n | { strict?: boolean }\n | undefined;\n return { strict: openaiMeta?.strict };\n}\n\n/**\n * Transforms a UPP tool definition to OpenAI function tool format.\n *\n * OpenAI's Chat Completions API expects tools as function definitions\n * with JSON Schema parameters.\n *\n * Strict mode can be specified via tool metadata:\n * ```typescript\n * const tool: Tool = {\n * name: 'get_weather',\n * description: 'Get weather for a location',\n * parameters: {...},\n * metadata: { openai: { strict: true } },\n * run: async (params) => {...}\n * };\n * ```\n *\n * @param tool - The UPP tool definition\n * @returns The transformed OpenAI function tool\n */\nfunction transformTool(tool: Tool): OpenAICompletionsTool {\n const { strict } = extractToolOptions(tool);\n\n return {\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: {\n type: 'object',\n properties: tool.parameters.properties,\n required: tool.parameters.required,\n ...(tool.parameters.additionalProperties !== undefined\n ? { additionalProperties: tool.parameters.additionalProperties }\n : {}),\n },\n ...(strict !== undefined ? { strict } : {}),\n },\n };\n}\n\n/**\n * Transforms an OpenAI Chat Completions response to UPP LLMResponse format.\n *\n * Extracts the first choice from the response and converts it to the universal\n * format, including text content, tool calls, usage statistics, and stop reason.\n * Also attempts to parse JSON content for structured output responses.\n *\n * @param data - The raw OpenAI Chat Completions API response\n * @returns The transformed UPP LLM response\n * @throws Error if the response contains no choices\n */\nexport function transformResponse(data: OpenAICompletionsResponse): LLMResponse {\n const choice = data.choices[0];\n if (!choice) {\n throw new Error('No choices in OpenAI response');\n }\n\n const textContent: TextBlock[] = [];\n let structuredData: unknown;\n if (choice.message.content) {\n textContent.push({ type: 'text', text: choice.message.content });\n try {\n structuredData = JSON.parse(choice.message.content);\n } catch {\n // Not JSON - expected for non-structured responses\n }\n }\n let hadRefusal = false;\n if (choice.message.refusal) {\n textContent.push({ type: 'text', text: choice.message.refusal });\n hadRefusal = true;\n }\n\n const toolCalls: ToolCall[] = [];\n if (choice.message.tool_calls) {\n for (const call of choice.message.tool_calls) {\n let args: Record<string, unknown> = {};\n try {\n args = JSON.parse(call.function.arguments);\n } catch {\n // Invalid JSON - use empty object\n }\n toolCalls.push({\n toolCallId: call.id,\n toolName: call.function.name,\n arguments: args,\n });\n }\n }\n\n const message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: data.id,\n metadata: {\n openai: {\n model: data.model,\n finish_reason: choice.finish_reason,\n system_fingerprint: data.system_fingerprint,\n service_tier: data.service_tier,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: data.usage.prompt_tokens,\n outputTokens: data.usage.completion_tokens,\n totalTokens: data.usage.total_tokens,\n cacheReadTokens: data.usage.prompt_tokens_details?.cached_tokens ?? 0,\n cacheWriteTokens: 0,\n };\n\n let stopReason = 'end_turn';\n switch (choice.finish_reason) {\n case 'stop':\n stopReason = 'end_turn';\n break;\n case 'length':\n stopReason = 'max_tokens';\n break;\n case 'tool_calls':\n stopReason = 'tool_use';\n break;\n case 'content_filter':\n stopReason = 'content_filter';\n break;\n }\n if (hadRefusal && stopReason !== 'content_filter') {\n stopReason = 'content_filter';\n }\n\n return {\n message,\n usage,\n stopReason,\n data: structuredData,\n };\n}\n\n/**\n * Mutable state object for accumulating data during streaming responses.\n *\n * As streaming chunks arrive, this state object is updated to build up\n * the complete response. It tracks text content, tool calls, token usage,\n * and other metadata needed to construct the final LLMResponse.\n */\nexport interface CompletionsStreamState {\n /** Response ID from the first chunk */\n id: string;\n /** Model identifier */\n model: string;\n /** Accumulated text content */\n text: string;\n /** Map of tool call index to accumulated tool call data */\n toolCalls: Map<number, { id: string; name: string; arguments: string }>;\n /** The finish reason when streaming completes */\n finishReason: string | null;\n /** Input token count (from usage chunk) */\n inputTokens: number;\n /** Output token count (from usage chunk) */\n outputTokens: number;\n /** Number of tokens read from cache */\n cacheReadTokens: number;\n /** Whether a refusal was encountered */\n hadRefusal: boolean;\n}\n\n/**\n * Creates a fresh stream state object for a new streaming session.\n *\n * @returns A new CompletionsStreamState with all fields initialized\n */\nexport function createStreamState(): CompletionsStreamState {\n return {\n id: '',\n model: '',\n text: '',\n toolCalls: new Map(),\n finishReason: null,\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n hadRefusal: false,\n };\n}\n\n/**\n * Transforms an OpenAI streaming chunk into UPP stream events.\n *\n * Processes each chunk from the SSE stream, updating the accumulated state\n * and emitting corresponding UPP events. A single chunk may produce multiple\n * events (e.g., both text and tool call deltas).\n *\n * @param chunk - The OpenAI streaming chunk to process\n * @param state - The mutable state object to update\n * @returns Array of UPP stream events generated from this chunk\n */\nexport function transformStreamEvent(\n chunk: OpenAICompletionsStreamChunk,\n state: CompletionsStreamState\n): StreamEvent[] {\n const events: StreamEvent[] = [];\n\n if (chunk.id && !state.id) {\n state.id = chunk.id;\n events.push({ type: 'message_start', index: 0, delta: {} });\n }\n if (chunk.model) {\n state.model = chunk.model;\n }\n\n const choice = chunk.choices[0];\n if (choice) {\n if (choice.delta.content) {\n state.text += choice.delta.content;\n events.push({\n type: 'text_delta',\n index: 0,\n delta: { text: choice.delta.content },\n });\n }\n if (choice.delta.refusal) {\n state.hadRefusal = true;\n state.text += choice.delta.refusal;\n events.push({\n type: 'text_delta',\n index: 0,\n delta: { text: choice.delta.refusal },\n });\n }\n\n if (choice.delta.tool_calls) {\n for (const toolCallDelta of choice.delta.tool_calls) {\n const index = toolCallDelta.index;\n let toolCall = state.toolCalls.get(index);\n\n if (!toolCall) {\n toolCall = { id: '', name: '', arguments: '' };\n state.toolCalls.set(index, toolCall);\n }\n\n if (toolCallDelta.id) {\n toolCall.id = toolCallDelta.id;\n }\n if (toolCallDelta.function?.name) {\n toolCall.name = toolCallDelta.function.name;\n }\n if (toolCallDelta.function?.arguments) {\n toolCall.arguments += toolCallDelta.function.arguments;\n events.push({\n type: 'tool_call_delta',\n index: index,\n delta: {\n toolCallId: toolCall.id,\n toolName: toolCall.name,\n argumentsJson: toolCallDelta.function.arguments,\n },\n });\n }\n }\n }\n\n if (choice.finish_reason) {\n state.finishReason = choice.finish_reason;\n events.push({ type: 'message_stop', index: 0, delta: {} });\n }\n }\n\n if (chunk.usage) {\n state.inputTokens = chunk.usage.prompt_tokens;\n state.outputTokens = chunk.usage.completion_tokens;\n state.cacheReadTokens = chunk.usage.prompt_tokens_details?.cached_tokens ?? 0;\n }\n\n return events;\n}\n\n/**\n * Builds a complete LLMResponse from accumulated streaming state.\n *\n * Called after all streaming chunks have been processed to construct\n * the final response object with all accumulated content, tool calls,\n * and usage statistics.\n *\n * @param state - The accumulated stream state\n * @returns A complete UPP LLMResponse\n */\nexport function buildResponseFromState(state: CompletionsStreamState): LLMResponse {\n const textContent: TextBlock[] = [];\n let structuredData: unknown;\n if (state.text) {\n textContent.push({ type: 'text', text: state.text });\n try {\n structuredData = JSON.parse(state.text);\n } catch {\n // Not JSON - expected for non-structured responses\n }\n }\n\n const toolCalls: ToolCall[] = [];\n for (const [, toolCall] of state.toolCalls) {\n let args: Record<string, unknown> = {};\n if (toolCall.arguments) {\n try {\n args = JSON.parse(toolCall.arguments);\n } catch {\n // Invalid JSON - use empty object\n }\n }\n toolCalls.push({\n toolCallId: toolCall.id,\n toolName: toolCall.name,\n arguments: args,\n });\n }\n\n const message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: state.id,\n metadata: {\n openai: {\n model: state.model,\n finish_reason: state.finishReason,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.inputTokens + state.outputTokens,\n cacheReadTokens: state.cacheReadTokens,\n cacheWriteTokens: 0,\n };\n\n let stopReason = 'end_turn';\n switch (state.finishReason) {\n case 'stop':\n stopReason = 'end_turn';\n break;\n case 'length':\n stopReason = 'max_tokens';\n break;\n case 'tool_calls':\n stopReason = 'tool_use';\n break;\n case 'content_filter':\n stopReason = 'content_filter';\n break;\n }\n if (state.hadRefusal && stopReason !== 'content_filter') {\n stopReason = 'content_filter';\n }\n\n return {\n message,\n usage,\n stopReason,\n data: structuredData,\n };\n}\n","/**\n * @fileoverview OpenAI Chat Completions API Handler\n *\n * This module implements the LLM handler for OpenAI's Chat Completions API\n * (`/v1/chat/completions`). This is the legacy API that provides standard\n * chat completion functionality with function calling support.\n *\n * For the modern Responses API with built-in tools support, see `llm.responses.ts`.\n *\n * @see {@link https://platform.openai.com/docs/api-reference/chat OpenAI Chat Completions API Reference}\n * @module providers/openai/llm.completions\n */\n\nimport type { LLMHandler, BoundLLMModel, LLMRequest, LLMResponse, LLMStreamResult, LLMCapabilities } from '../../types/llm.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport type { LLMProvider } from '../../types/provider.ts';\nimport { UPPError } from '../../types/errors.ts';\nimport { resolveApiKey } from '../../http/keys.ts';\nimport { doFetch, doStreamFetch } from '../../http/fetch.ts';\nimport { parseSSEStream } from '../../http/sse.ts';\nimport { normalizeHttpError } from '../../http/errors.ts';\nimport type { OpenAICompletionsParams, OpenAICompletionsResponse, OpenAICompletionsStreamChunk } from './types.ts';\nimport {\n transformRequest,\n transformResponse,\n transformStreamEvent,\n createStreamState,\n buildResponseFromState,\n} from './transform.completions.ts';\n\n/** Base URL for OpenAI's Chat Completions API endpoint */\nconst OPENAI_API_URL = 'https://api.openai.com/v1/chat/completions';\n\n/**\n * Capability declaration for the OpenAI Chat Completions API.\n *\n * Defines what features are supported by this handler:\n * - Streaming: Real-time token-by-token response streaming via SSE\n * - Tools: Function calling for structured interactions\n * - Structured Output: JSON schema-based response formatting\n * - Image Input: Vision capabilities for image understanding\n */\nconst OPENAI_CAPABILITIES: LLMCapabilities = {\n streaming: true,\n tools: true,\n structuredOutput: true,\n imageInput: true,\n videoInput: false,\n audioInput: false,\n};\n\n/**\n * Creates an LLM handler for OpenAI's Chat Completions API.\n *\n * This factory function creates a handler that communicates with the\n * `/v1/chat/completions` endpoint. The handler supports both synchronous\n * completion requests and streaming responses.\n *\n * @returns An LLM handler configured for the Chat Completions API\n *\n * @example\n * ```typescript\n * const handler = createCompletionsLLMHandler();\n * const model = handler.bind('gpt-4o');\n *\n * // Synchronous completion\n * const response = await model.complete({\n * messages: [{ role: 'user', content: 'Hello!' }],\n * config: { apiKey: 'sk-...' }\n * });\n *\n * // Streaming completion\n * const stream = model.stream({\n * messages: [{ role: 'user', content: 'Tell me a story' }],\n * config: { apiKey: 'sk-...' }\n * });\n *\n * for await (const event of stream) {\n * if (event.type === 'text_delta') {\n * process.stdout.write(event.delta.text);\n * }\n * }\n * ```\n *\n * @see {@link createResponsesLLMHandler} for the modern Responses API handler\n */\nexport function createCompletionsLLMHandler(): LLMHandler<OpenAICompletionsParams> {\n let providerRef: LLMProvider<OpenAICompletionsParams> | null = null;\n\n return {\n _setProvider(provider: LLMProvider<OpenAICompletionsParams>) {\n providerRef = provider;\n },\n\n bind(modelId: string): BoundLLMModel<OpenAICompletionsParams> {\n // Use the injected provider reference\n if (!providerRef) {\n throw new UPPError(\n 'Provider reference not set. Handler must be used with createProvider() or have _setProvider called.',\n 'INVALID_REQUEST',\n 'openai',\n 'llm'\n );\n }\n\n const model: BoundLLMModel<OpenAICompletionsParams> = {\n modelId,\n capabilities: OPENAI_CAPABILITIES,\n\n get provider(): LLMProvider<OpenAICompletionsParams> {\n return providerRef!;\n },\n\n async complete(request: LLMRequest<OpenAICompletionsParams>): Promise<LLMResponse> {\n const apiKey = await resolveApiKey(\n request.config,\n 'OPENAI_API_KEY',\n 'openai',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? OPENAI_API_URL;\n const body = transformRequest(request, modelId);\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doFetch(\n baseUrl,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'openai',\n 'llm'\n );\n\n const data = (await response.json()) as OpenAICompletionsResponse;\n return transformResponse(data);\n },\n\n stream(request: LLMRequest<OpenAICompletionsParams>): LLMStreamResult {\n const state = createStreamState();\n let responseResolve: (value: LLMResponse) => void;\n let responseReject: (error: Error) => void;\n\n const responsePromise = new Promise<LLMResponse>((resolve, reject) => {\n responseResolve = resolve;\n responseReject = reject;\n });\n\n async function* generateEvents(): AsyncGenerator<StreamEvent, void, unknown> {\n try {\n const apiKey = await resolveApiKey(\n request.config,\n 'OPENAI_API_KEY',\n 'openai',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? OPENAI_API_URL;\n const body = transformRequest(request, modelId);\n body.stream = true;\n body.stream_options = { include_usage: true };\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doStreamFetch(\n baseUrl,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'openai',\n 'llm'\n );\n\n if (!response.ok) {\n const error = await normalizeHttpError(response, 'openai', 'llm');\n responseReject(error);\n throw error;\n }\n\n if (!response.body) {\n const error = new UPPError(\n 'No response body for streaming request',\n 'PROVIDER_ERROR',\n 'openai',\n 'llm'\n );\n responseReject(error);\n throw error;\n }\n\n for await (const data of parseSSEStream(response.body)) {\n // Skip [DONE] marker\n if (data === '[DONE]') {\n continue;\n }\n\n // Check for OpenAI error event\n if (typeof data === 'object' && data !== null) {\n const chunk = data as OpenAICompletionsStreamChunk;\n\n // Check for error in chunk\n if ('error' in chunk && chunk.error) {\n const errorData = chunk.error as { message?: string; type?: string };\n const error = new UPPError(\n errorData.message ?? 'Unknown error',\n 'PROVIDER_ERROR',\n 'openai',\n 'llm'\n );\n responseReject(error);\n throw error;\n }\n\n const uppEvents = transformStreamEvent(chunk, state);\n for (const event of uppEvents) {\n yield event;\n }\n }\n }\n\n // Build final response\n responseResolve(buildResponseFromState(state));\n } catch (error) {\n responseReject(error as Error);\n throw error;\n }\n }\n\n return {\n [Symbol.asyncIterator]() {\n return generateEvents();\n },\n response: responsePromise,\n };\n },\n };\n\n return model;\n },\n };\n}\n","/**\n * @fileoverview Responses API Message Transformers\n *\n * This module provides transformation functions for converting between the\n * Universal Provider Protocol (UPP) message format and OpenAI's Responses API\n * format. The Responses API uses a different structure than Chat Completions,\n * with input items instead of messages and support for built-in tools.\n *\n * Key differences from Chat Completions:\n * - Uses `input` array instead of `messages`\n * - Function calls are separate input items, not embedded in messages\n * - Tool results use `function_call_output` items\n * - Supports built-in tools (web search, image generation, etc.)\n * - Different streaming event structure\n *\n * @module providers/openai/transform.responses\n */\n\nimport type { LLMRequest, LLMResponse } from '../../types/llm.ts';\nimport type { Message } from '../../types/messages.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport type { Tool, ToolCall } from '../../types/tool.ts';\nimport type { TokenUsage } from '../../types/turn.ts';\nimport type { ContentBlock, TextBlock, ImageBlock, AssistantContent } from '../../types/content.ts';\nimport {\n AssistantMessage,\n isUserMessage,\n isAssistantMessage,\n isToolResultMessage,\n} from '../../types/messages.ts';\nimport type {\n OpenAIResponsesParams,\n OpenAIResponsesRequest,\n OpenAIResponsesInputItem,\n OpenAIResponsesContentPart,\n OpenAIResponsesTool,\n OpenAIResponsesToolUnion,\n OpenAIResponsesResponse,\n OpenAIResponsesStreamEvent,\n OpenAIResponsesOutputItem,\n OpenAIResponsesMessageOutput,\n OpenAIResponsesFunctionCallOutput,\n OpenAIResponsesImageGenerationOutput,\n} from './types.ts';\n\n/**\n * Transforms a UPP LLM request into OpenAI Responses API format.\n *\n * This function converts the universal request format to OpenAI's Responses API\n * structure. It merges UPP function tools with any built-in tools specified in\n * params, and handles structured output configuration.\n *\n * @param request - The UPP LLM request containing messages, tools, and configuration\n * @param modelId - The OpenAI model identifier (e.g., 'gpt-4o')\n * @returns An OpenAI Responses API request body\n *\n * @example\n * ```typescript\n * const openaiRequest = transformRequest({\n * messages: [userMessage('Search for recent news')],\n * params: {\n * max_output_tokens: 1000,\n * tools: [tools.webSearch()]\n * },\n * config: { apiKey: 'sk-...' }\n * }, 'gpt-4o');\n * ```\n */\nexport function transformRequest(\n request: LLMRequest<OpenAIResponsesParams>,\n modelId: string\n): OpenAIResponsesRequest {\n const params = request.params ?? ({} as OpenAIResponsesParams);\n\n const builtInTools = params.tools as OpenAIResponsesToolUnion[] | undefined;\n const { tools: _paramsTools, ...restParams } = params;\n\n const openaiRequest: OpenAIResponsesRequest = {\n ...restParams,\n model: modelId,\n input: transformInputItems(request.messages, request.system),\n };\n\n const functionTools: OpenAIResponsesToolUnion[] = request.tools?.map(transformTool) ?? [];\n const allTools: OpenAIResponsesToolUnion[] = [...functionTools, ...(builtInTools ?? [])];\n\n if (allTools.length > 0) {\n openaiRequest.tools = allTools;\n }\n\n if (request.structure) {\n const schema: Record<string, unknown> = {\n type: 'object',\n properties: request.structure.properties,\n required: request.structure.required,\n ...(request.structure.additionalProperties !== undefined\n ? { additionalProperties: request.structure.additionalProperties }\n : { additionalProperties: false }),\n };\n if (request.structure.description) {\n schema.description = request.structure.description;\n }\n\n openaiRequest.text = {\n format: {\n type: 'json_schema',\n name: 'json_response',\n description: request.structure.description,\n schema,\n strict: true,\n },\n };\n }\n\n return openaiRequest;\n}\n\n/**\n * Normalizes system prompt to string.\n * Converts array format to concatenated string for providers that only support strings.\n */\nfunction normalizeSystem(system: string | unknown[] | undefined): string | undefined {\n if (!system) return undefined;\n if (typeof system === 'string') return system;\n return (system as Array<{text?: string}>)\n .map(block => block.text ?? '')\n .filter(text => text.length > 0)\n .join('\\n\\n');\n}\n\n/**\n * Transforms UPP messages to Responses API input items.\n *\n * The Responses API accepts either a string (for simple prompts) or an array\n * of input items. This function optimizes by returning a string when the\n * input is a single user message with text content.\n *\n * @param messages - Array of UPP messages to transform\n * @param system - Optional system prompt (string or array, normalized to string)\n * @returns Either a string (for simple inputs) or array of input items\n */\nfunction transformInputItems(\n messages: Message[],\n system?: string | unknown[]\n): OpenAIResponsesInputItem[] | string {\n const result: OpenAIResponsesInputItem[] = [];\n const normalizedSystem = normalizeSystem(system);\n\n if (normalizedSystem) {\n result.push({\n type: 'message',\n role: 'system',\n content: normalizedSystem,\n });\n }\n\n for (const message of messages) {\n const items = transformMessage(message);\n result.push(...items);\n }\n\n if (result.length === 1 && result[0]?.type === 'message') {\n const item = result[0] as { role?: string; content?: string | unknown[] };\n if (item.role === 'user' && typeof item.content === 'string') {\n return item.content;\n }\n }\n\n return result;\n}\n\n/**\n * Filters content blocks to only include those with a valid type property.\n *\n * @param content - Array of content blocks to filter\n * @returns Filtered array containing only valid content blocks\n */\nfunction filterValidContent<T extends { type?: string }>(content: T[]): T[] {\n return content.filter((c) => c && typeof c.type === 'string');\n}\n\n/**\n * Transforms a single UPP message to Responses API input items.\n *\n * Unlike Chat Completions, the Responses API separates function calls from\n * messages. An assistant message with tool calls becomes multiple input items:\n * a message item for text content plus separate function_call items.\n *\n * @param message - The UPP message to transform\n * @returns Array of Responses API input items (may be multiple per message)\n */\nfunction transformMessage(message: Message): OpenAIResponsesInputItem[] {\n if (isUserMessage(message)) {\n const validContent = filterValidContent(message.content);\n if (validContent.length === 1 && validContent[0]?.type === 'text') {\n return [\n {\n type: 'message',\n role: 'user',\n content: (validContent[0] as TextBlock).text,\n },\n ];\n }\n return [\n {\n type: 'message',\n role: 'user',\n content: validContent.map(transformContentPart),\n },\n ];\n }\n\n if (isAssistantMessage(message)) {\n const validContent = filterValidContent(message.content);\n const items: OpenAIResponsesInputItem[] = [];\n\n const contentParts: OpenAIResponsesContentPart[] = validContent\n .filter((c): c is TextBlock => c.type === 'text')\n .map((c): OpenAIResponsesContentPart => ({\n type: 'output_text',\n text: c.text,\n }));\n\n if (contentParts.length > 0) {\n items.push({\n type: 'message',\n role: 'assistant',\n content: contentParts,\n });\n }\n\n const openaiMeta = message.metadata?.openai as\n | { functionCallItems?: Array<{ id: string; call_id: string; name: string; arguments: string }> }\n | undefined;\n const functionCallItems = openaiMeta?.functionCallItems;\n\n if (functionCallItems && functionCallItems.length > 0) {\n for (const fc of functionCallItems) {\n items.push({\n type: 'function_call',\n id: fc.id,\n call_id: fc.call_id,\n name: fc.name,\n arguments: fc.arguments,\n });\n }\n } else if (message.toolCalls && message.toolCalls.length > 0) {\n for (const call of message.toolCalls) {\n items.push({\n type: 'function_call',\n id: `fc_${call.toolCallId}`,\n call_id: call.toolCallId,\n name: call.toolName,\n arguments: JSON.stringify(call.arguments),\n });\n }\n }\n\n return items;\n }\n\n if (isToolResultMessage(message)) {\n return message.results.map((result) => ({\n type: 'function_call_output' as const,\n call_id: result.toolCallId,\n output:\n typeof result.result === 'string'\n ? result.result\n : JSON.stringify(result.result),\n }));\n }\n\n return [];\n}\n\n/**\n * Transforms a UPP content block to Responses API content part format.\n *\n * Handles text and image content blocks. The Responses API uses different\n * type names than Chat Completions (`input_text` vs `text`, `input_image` vs `image_url`).\n *\n * @param block - The content block to transform\n * @returns The transformed Responses API content part\n * @throws Error if the content type is unsupported or image source type is unknown\n */\nfunction transformContentPart(block: ContentBlock): OpenAIResponsesContentPart {\n switch (block.type) {\n case 'text':\n return { type: 'input_text', text: block.text };\n\n case 'image': {\n const imageBlock = block as ImageBlock;\n if (imageBlock.source.type === 'base64') {\n return {\n type: 'input_image',\n image_url: `data:${imageBlock.mimeType};base64,${imageBlock.source.data}`,\n };\n }\n\n if (imageBlock.source.type === 'url') {\n return {\n type: 'input_image',\n image_url: imageBlock.source.url,\n };\n }\n\n if (imageBlock.source.type === 'bytes') {\n const base64 = btoa(\n Array.from(imageBlock.source.data)\n .map((b) => String.fromCharCode(b))\n .join('')\n );\n return {\n type: 'input_image',\n image_url: `data:${imageBlock.mimeType};base64,${base64}`,\n };\n }\n\n throw new Error('Unknown image source type');\n }\n\n default:\n throw new Error(`Unsupported content type: ${block.type}`);\n }\n}\n\n/**\n * Extracts OpenAI-specific options from tool metadata.\n *\n * @param tool - The tool to extract options from\n * @returns The OpenAI options if present (currently supports `strict`)\n */\nfunction extractToolOptions(tool: Tool): { strict?: boolean } {\n const openaiMeta = tool.metadata?.openai as\n | { strict?: boolean }\n | undefined;\n return { strict: openaiMeta?.strict };\n}\n\n/**\n * Transforms a UPP tool definition to Responses API function tool format.\n *\n * The Responses API uses a flatter structure for function tools compared to\n * Chat Completions, with properties at the top level rather than nested.\n *\n * Strict mode can be specified via tool metadata:\n * ```typescript\n * const tool: Tool = {\n * name: 'get_weather',\n * description: 'Get weather for a location',\n * parameters: {...},\n * metadata: { openai: { strict: true } },\n * run: async (params) => {...}\n * };\n * ```\n *\n * @param tool - The UPP tool definition\n * @returns The transformed Responses API function tool\n */\nfunction transformTool(tool: Tool): OpenAIResponsesTool {\n const { strict } = extractToolOptions(tool);\n\n return {\n type: 'function',\n name: tool.name,\n description: tool.description,\n parameters: {\n type: 'object',\n properties: tool.parameters.properties,\n required: tool.parameters.required,\n ...(tool.parameters.additionalProperties !== undefined\n ? { additionalProperties: tool.parameters.additionalProperties }\n : {}),\n },\n ...(strict !== undefined ? { strict } : {}),\n };\n}\n\n/**\n * Transforms an OpenAI Responses API response to UPP LLMResponse format.\n *\n * Processes all output items from the response, extracting text content,\n * tool calls, and generated images. Also handles built-in tool outputs\n * like image generation results.\n *\n * @param data - The raw OpenAI Responses API response\n * @returns The transformed UPP LLM response\n */\nexport function transformResponse(data: OpenAIResponsesResponse): LLMResponse {\n const content: AssistantContent[] = [];\n const toolCalls: ToolCall[] = [];\n const functionCallItems: Array<{\n id: string;\n call_id: string;\n name: string;\n arguments: string;\n }> = [];\n let hadRefusal = false;\n let structuredData: unknown;\n\n for (const item of data.output) {\n if (item.type === 'message') {\n const messageItem = item as OpenAIResponsesMessageOutput;\n for (const part of messageItem.content) {\n if (part.type === 'output_text') {\n content.push({ type: 'text', text: part.text });\n if (structuredData === undefined) {\n try {\n structuredData = JSON.parse(part.text);\n } catch {\n // Not JSON - expected for non-structured responses\n }\n }\n } else if (part.type === 'refusal') {\n content.push({ type: 'text', text: part.refusal });\n hadRefusal = true;\n }\n }\n } else if (item.type === 'function_call') {\n const functionCall = item as OpenAIResponsesFunctionCallOutput;\n let args: Record<string, unknown> = {};\n try {\n args = JSON.parse(functionCall.arguments);\n } catch {\n // Invalid JSON - use empty object\n }\n toolCalls.push({\n toolCallId: functionCall.call_id,\n toolName: functionCall.name,\n arguments: args,\n });\n functionCallItems.push({\n id: functionCall.id,\n call_id: functionCall.call_id,\n name: functionCall.name,\n arguments: functionCall.arguments,\n });\n } else if (item.type === 'image_generation_call') {\n const imageGen = item as OpenAIResponsesImageGenerationOutput;\n if (imageGen.result) {\n content.push({\n type: 'image',\n mimeType: 'image/png',\n source: { type: 'base64', data: imageGen.result },\n } as ImageBlock);\n }\n }\n }\n\n const message = new AssistantMessage(\n content,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: data.id,\n metadata: {\n openai: {\n model: data.model,\n status: data.status,\n response_id: data.id,\n functionCallItems:\n functionCallItems.length > 0 ? functionCallItems : undefined,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: data.usage.input_tokens,\n outputTokens: data.usage.output_tokens,\n totalTokens: data.usage.total_tokens,\n cacheReadTokens: data.usage.input_tokens_details?.cached_tokens ?? 0,\n cacheWriteTokens: 0,\n };\n\n let stopReason = 'end_turn';\n if (data.status === 'completed') {\n stopReason = toolCalls.length > 0 ? 'tool_use' : 'end_turn';\n } else if (data.status === 'incomplete') {\n stopReason = data.incomplete_details?.reason === 'max_output_tokens'\n ? 'max_tokens'\n : 'end_turn';\n } else if (data.status === 'failed') {\n stopReason = 'error';\n }\n if (hadRefusal && stopReason !== 'error') {\n stopReason = 'content_filter';\n }\n\n return {\n message,\n usage,\n stopReason,\n data: structuredData,\n };\n}\n\n/**\n * Mutable state object for accumulating data during Responses API streaming.\n *\n * The Responses API has a different streaming structure than Chat Completions,\n * with events organized by output index. This state tracks content and tool\n * calls by their output index for proper reconstruction.\n */\nexport interface ResponsesStreamState {\n /** Response ID */\n id: string;\n /** Model identifier */\n model: string;\n /** Map of output index to accumulated text content */\n textByIndex: Map<number, string>;\n /** Map of output index to accumulated tool call data */\n toolCalls: Map<\n number,\n { itemId?: string; callId?: string; name?: string; arguments: string }\n >;\n /** Base64 image data from image_generation_call outputs */\n images: string[];\n /** Current response status */\n status: string;\n /** Input token count */\n inputTokens: number;\n /** Output token count */\n outputTokens: number;\n /** Number of tokens read from cache */\n cacheReadTokens: number;\n /** Whether a refusal was encountered */\n hadRefusal: boolean;\n}\n\n/**\n * Creates a fresh stream state object for a new Responses API streaming session.\n *\n * @returns A new ResponsesStreamState with all fields initialized\n */\nexport function createStreamState(): ResponsesStreamState {\n return {\n id: '',\n model: '',\n textByIndex: new Map(),\n toolCalls: new Map(),\n images: [],\n status: 'in_progress',\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n hadRefusal: false,\n };\n}\n\n/**\n * Transforms an OpenAI Responses API streaming event into UPP stream events.\n *\n * The Responses API uses a granular event structure with separate events for\n * response lifecycle, output items, and content deltas. This function maps\n * these events to the UPP streaming format.\n *\n * @param event - The Responses API streaming event to process\n * @param state - The mutable state object to update\n * @returns Array of UPP stream events generated from this event\n */\nexport function transformStreamEvent(\n event: OpenAIResponsesStreamEvent,\n state: ResponsesStreamState\n): StreamEvent[] {\n const events: StreamEvent[] = [];\n\n switch (event.type) {\n case 'response.created':\n state.id = event.response.id;\n state.model = event.response.model;\n events.push({ type: 'message_start', index: 0, delta: {} });\n break;\n\n case 'response.in_progress':\n state.status = 'in_progress';\n break;\n\n case 'response.completed':\n state.status = 'completed';\n if (event.response.usage) {\n state.inputTokens = event.response.usage.input_tokens;\n state.outputTokens = event.response.usage.output_tokens;\n state.cacheReadTokens = event.response.usage.input_tokens_details?.cached_tokens ?? 0;\n }\n events.push({ type: 'message_stop', index: 0, delta: {} });\n break;\n\n case 'response.failed':\n state.status = 'failed';\n events.push({ type: 'message_stop', index: 0, delta: {} });\n break;\n\n case 'response.output_item.added':\n if (event.item.type === 'function_call') {\n const functionCall = event.item as OpenAIResponsesFunctionCallOutput;\n const existing = state.toolCalls.get(event.output_index) ?? {\n arguments: '',\n };\n existing.itemId = functionCall.id;\n existing.callId = functionCall.call_id;\n existing.name = functionCall.name;\n if (functionCall.arguments) {\n existing.arguments = functionCall.arguments;\n }\n state.toolCalls.set(event.output_index, existing);\n }\n events.push({\n type: 'content_block_start',\n index: event.output_index,\n delta: {},\n });\n break;\n\n case 'response.output_item.done':\n if (event.item.type === 'function_call') {\n const functionCall = event.item as OpenAIResponsesFunctionCallOutput;\n const existing = state.toolCalls.get(event.output_index) ?? {\n arguments: '',\n };\n existing.itemId = functionCall.id;\n existing.callId = functionCall.call_id;\n existing.name = functionCall.name;\n if (functionCall.arguments) {\n existing.arguments = functionCall.arguments;\n }\n state.toolCalls.set(event.output_index, existing);\n } else if (event.item.type === 'image_generation_call') {\n const imageGen = event.item as OpenAIResponsesImageGenerationOutput;\n if (imageGen.result) {\n state.images.push(imageGen.result);\n }\n }\n events.push({\n type: 'content_block_stop',\n index: event.output_index,\n delta: {},\n });\n break;\n\n case 'response.output_text.delta': {\n const currentText = state.textByIndex.get(event.output_index) ?? '';\n state.textByIndex.set(event.output_index, currentText + event.delta);\n events.push({\n type: 'text_delta',\n index: event.output_index,\n delta: { text: event.delta },\n });\n break;\n }\n\n case 'response.output_text.done':\n state.textByIndex.set(event.output_index, event.text);\n break;\n\n case 'response.refusal.delta': {\n state.hadRefusal = true;\n const currentRefusal = state.textByIndex.get(event.output_index) ?? '';\n state.textByIndex.set(event.output_index, currentRefusal + event.delta);\n events.push({\n type: 'text_delta',\n index: event.output_index,\n delta: { text: event.delta },\n });\n break;\n }\n\n case 'response.refusal.done':\n state.hadRefusal = true;\n state.textByIndex.set(event.output_index, event.refusal);\n break;\n\n case 'response.function_call_arguments.delta': {\n let toolCall = state.toolCalls.get(event.output_index);\n if (!toolCall) {\n toolCall = { arguments: '' };\n state.toolCalls.set(event.output_index, toolCall);\n }\n if (event.item_id && !toolCall.itemId) {\n toolCall.itemId = event.item_id;\n }\n if (event.call_id && !toolCall.callId) {\n toolCall.callId = event.call_id;\n }\n toolCall.arguments += event.delta;\n events.push({\n type: 'tool_call_delta',\n index: event.output_index,\n delta: {\n toolCallId: toolCall.callId ?? toolCall.itemId ?? '',\n toolName: toolCall.name,\n argumentsJson: event.delta,\n },\n });\n break;\n }\n\n case 'response.function_call_arguments.done': {\n let toolCall = state.toolCalls.get(event.output_index);\n if (!toolCall) {\n toolCall = { arguments: '' };\n state.toolCalls.set(event.output_index, toolCall);\n }\n if (event.item_id) {\n toolCall.itemId = event.item_id;\n }\n if (event.call_id) {\n toolCall.callId = event.call_id;\n }\n toolCall.name = event.name;\n toolCall.arguments = event.arguments;\n break;\n }\n\n case 'error':\n break;\n\n default:\n break;\n }\n\n return events;\n}\n\n/**\n * Builds a complete LLMResponse from accumulated Responses API streaming state.\n *\n * Called after all streaming events have been processed to construct the final\n * response object with all accumulated content, tool calls, images, and usage\n * statistics.\n *\n * @param state - The accumulated stream state\n * @returns A complete UPP LLMResponse\n */\nexport function buildResponseFromState(state: ResponsesStreamState): LLMResponse {\n const content: AssistantContent[] = [];\n let structuredData: unknown;\n\n for (const [, text] of state.textByIndex) {\n if (text) {\n content.push({ type: 'text', text });\n if (structuredData === undefined) {\n try {\n structuredData = JSON.parse(text);\n } catch {\n // Not JSON - expected for non-structured responses\n }\n }\n }\n }\n\n for (const imageData of state.images) {\n content.push({\n type: 'image',\n mimeType: 'image/png',\n source: { type: 'base64', data: imageData },\n } as ImageBlock);\n }\n\n const toolCalls: ToolCall[] = [];\n const functionCallItems: Array<{\n id: string;\n call_id: string;\n name: string;\n arguments: string;\n }> = [];\n for (const [, toolCall] of state.toolCalls) {\n let args: Record<string, unknown> = {};\n if (toolCall.arguments) {\n try {\n args = JSON.parse(toolCall.arguments);\n } catch {\n // Invalid JSON - use empty object\n }\n }\n const itemId = toolCall.itemId ?? '';\n const callId = toolCall.callId ?? toolCall.itemId ?? '';\n const name = toolCall.name ?? '';\n toolCalls.push({\n toolCallId: callId,\n toolName: name,\n arguments: args,\n });\n\n if (itemId && callId && name) {\n functionCallItems.push({\n id: itemId,\n call_id: callId,\n name,\n arguments: toolCall.arguments,\n });\n }\n }\n\n const message = new AssistantMessage(\n content,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: state.id,\n metadata: {\n openai: {\n model: state.model,\n status: state.status,\n response_id: state.id,\n functionCallItems:\n functionCallItems.length > 0 ? functionCallItems : undefined,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.inputTokens + state.outputTokens,\n cacheReadTokens: state.cacheReadTokens,\n cacheWriteTokens: 0,\n };\n\n let stopReason = 'end_turn';\n if (state.status === 'completed') {\n stopReason = toolCalls.length > 0 ? 'tool_use' : 'end_turn';\n } else if (state.status === 'failed') {\n stopReason = 'error';\n }\n if (state.hadRefusal && stopReason !== 'error') {\n stopReason = 'content_filter';\n }\n\n return {\n message,\n usage,\n stopReason,\n data: structuredData,\n };\n}\n","/**\n * @fileoverview OpenAI Responses API Handler\n *\n * This module implements the LLM handler for OpenAI's modern Responses API\n * (`/v1/responses`). This is the recommended API that supports built-in tools\n * like web search, image generation, file search, code interpreter, and MCP.\n *\n * For the legacy Chat Completions API, see `llm.completions.ts`.\n *\n * @see {@link https://platform.openai.com/docs/api-reference/responses OpenAI Responses API Reference}\n * @module providers/openai/llm.responses\n */\n\nimport type { LLMHandler, BoundLLMModel, LLMRequest, LLMResponse, LLMStreamResult, LLMCapabilities } from '../../types/llm.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport type { LLMProvider } from '../../types/provider.ts';\nimport { UPPError } from '../../types/errors.ts';\nimport { resolveApiKey } from '../../http/keys.ts';\nimport { doFetch, doStreamFetch } from '../../http/fetch.ts';\nimport { parseSSEStream } from '../../http/sse.ts';\nimport { normalizeHttpError } from '../../http/errors.ts';\nimport type { OpenAIResponsesParams, OpenAIResponsesResponse, OpenAIResponsesStreamEvent, OpenAIResponseErrorEvent } from './types.ts';\nimport {\n transformRequest,\n transformResponse,\n transformStreamEvent,\n createStreamState,\n buildResponseFromState,\n} from './transform.responses.ts';\n\n/** Base URL for OpenAI's Responses API endpoint */\nconst OPENAI_RESPONSES_API_URL = 'https://api.openai.com/v1/responses';\n\n/**\n * Capability declaration for the OpenAI Responses API.\n *\n * Defines what features are supported by this handler:\n * - Streaming: Real-time token-by-token response streaming via SSE\n * - Tools: Function calling plus built-in tools (web search, code interpreter, etc.)\n * - Structured Output: JSON schema-based response formatting\n * - Image Input: Vision capabilities for image understanding\n */\nconst OPENAI_CAPABILITIES: LLMCapabilities = {\n streaming: true,\n tools: true,\n structuredOutput: true,\n imageInput: true,\n videoInput: false,\n audioInput: false,\n};\n\n/**\n * Creates an LLM handler for OpenAI's modern Responses API.\n *\n * This factory function creates a handler that communicates with the\n * `/v1/responses` endpoint. The Responses API is the modern, recommended\n * approach that supports built-in tools like web search, image generation,\n * file search, code interpreter, and MCP servers.\n *\n * @returns An LLM handler configured for the Responses API\n *\n * @example Basic usage\n * ```typescript\n * const handler = createResponsesLLMHandler();\n * const model = handler.bind('gpt-4o');\n *\n * const response = await model.complete({\n * messages: [{ role: 'user', content: 'Hello!' }],\n * config: { apiKey: 'sk-...' }\n * });\n * ```\n *\n * @example With built-in tools\n * ```typescript\n * import { tools } from './types.ts';\n *\n * const response = await model.complete({\n * messages: [{ role: 'user', content: 'What is the weather today?' }],\n * params: {\n * tools: [tools.webSearch()]\n * },\n * config: { apiKey: 'sk-...' }\n * });\n * ```\n *\n * @example Streaming responses\n * ```typescript\n * const stream = model.stream({\n * messages: [{ role: 'user', content: 'Tell me a story' }],\n * config: { apiKey: 'sk-...' }\n * });\n *\n * for await (const event of stream) {\n * if (event.type === 'text_delta') {\n * process.stdout.write(event.delta.text);\n * }\n * }\n * ```\n *\n * @see {@link createCompletionsLLMHandler} for the legacy Chat Completions API handler\n */\nexport function createResponsesLLMHandler(): LLMHandler<OpenAIResponsesParams> {\n let providerRef: LLMProvider<OpenAIResponsesParams> | null = null;\n\n return {\n _setProvider(provider: LLMProvider<OpenAIResponsesParams>) {\n providerRef = provider;\n },\n\n bind(modelId: string): BoundLLMModel<OpenAIResponsesParams> {\n // Use the injected provider reference\n if (!providerRef) {\n throw new UPPError(\n 'Provider reference not set. Handler must be used with createProvider() or have _setProvider called.',\n 'INVALID_REQUEST',\n 'openai',\n 'llm'\n );\n }\n\n const model: BoundLLMModel<OpenAIResponsesParams> = {\n modelId,\n capabilities: OPENAI_CAPABILITIES,\n\n get provider(): LLMProvider<OpenAIResponsesParams> {\n return providerRef!;\n },\n\n async complete(request: LLMRequest<OpenAIResponsesParams>): Promise<LLMResponse> {\n const apiKey = await resolveApiKey(\n request.config,\n 'OPENAI_API_KEY',\n 'openai',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? OPENAI_RESPONSES_API_URL;\n const body = transformRequest(request, modelId);\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doFetch(\n baseUrl,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'openai',\n 'llm'\n );\n\n const data = (await response.json()) as OpenAIResponsesResponse;\n\n // Check for error in response\n if (data.status === 'failed' && data.error) {\n throw new UPPError(\n data.error.message,\n 'PROVIDER_ERROR',\n 'openai',\n 'llm'\n );\n }\n\n return transformResponse(data);\n },\n\n stream(request: LLMRequest<OpenAIResponsesParams>): LLMStreamResult {\n const state = createStreamState();\n let responseResolve: (value: LLMResponse) => void;\n let responseReject: (error: Error) => void;\n\n const responsePromise = new Promise<LLMResponse>((resolve, reject) => {\n responseResolve = resolve;\n responseReject = reject;\n });\n\n async function* generateEvents(): AsyncGenerator<StreamEvent, void, unknown> {\n try {\n const apiKey = await resolveApiKey(\n request.config,\n 'OPENAI_API_KEY',\n 'openai',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? OPENAI_RESPONSES_API_URL;\n const body = transformRequest(request, modelId);\n body.stream = true;\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doStreamFetch(\n baseUrl,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'openai',\n 'llm'\n );\n\n if (!response.ok) {\n const error = await normalizeHttpError(response, 'openai', 'llm');\n responseReject(error);\n throw error;\n }\n\n if (!response.body) {\n const error = new UPPError(\n 'No response body for streaming request',\n 'PROVIDER_ERROR',\n 'openai',\n 'llm'\n );\n responseReject(error);\n throw error;\n }\n\n for await (const data of parseSSEStream(response.body)) {\n // Skip [DONE] marker\n if (data === '[DONE]') {\n continue;\n }\n\n // Check for OpenAI error event\n if (typeof data === 'object' && data !== null) {\n const event = data as OpenAIResponsesStreamEvent;\n\n // Check for error event\n if (event.type === 'error') {\n const errorEvent = event as OpenAIResponseErrorEvent;\n const error = new UPPError(\n errorEvent.error.message,\n 'PROVIDER_ERROR',\n 'openai',\n 'llm'\n );\n responseReject(error);\n throw error;\n }\n\n const uppEvents = transformStreamEvent(event, state);\n for (const uppEvent of uppEvents) {\n yield uppEvent;\n }\n }\n }\n\n // Build final response\n responseResolve(buildResponseFromState(state));\n } catch (error) {\n responseReject(error as Error);\n throw error;\n }\n }\n\n return {\n [Symbol.asyncIterator]() {\n return generateEvents();\n },\n response: responsePromise,\n };\n },\n };\n\n return model;\n },\n };\n}\n","/**\n * @fileoverview OpenAI Provider Type Definitions\n *\n * This module contains all TypeScript type definitions for the OpenAI provider,\n * including types for both the Chat Completions API and the Responses API.\n *\n * The types are organized into sections:\n * - Audio Configuration Types\n * - Web Search Configuration Types\n * - Chat Completions API Parameters and Types\n * - Responses API Parameters and Types\n * - Built-in Tools for Responses API\n * - Tool Helper Constructors\n *\n * @module providers/openai/types\n */\n\n// ============================================\n// Audio Configuration Types\n// ============================================\n\n/**\n * Audio output configuration for Chat Completions API.\n *\n * Enables audio output generation when using models that support\n * the audio modality. Requires `modalities: ['text', 'audio']`.\n */\nexport interface OpenAIAudioConfig {\n /** Audio format for the generated output */\n format: 'wav' | 'aac' | 'mp3' | 'flac' | 'opus' | 'pcm16';\n /** Voice model to use for audio generation */\n voice:\n | 'alloy'\n | 'ash'\n | 'ballad'\n | 'coral'\n | 'echo'\n | 'sage'\n | 'shimmer'\n | 'verse'\n | 'marin'\n | 'cedar';\n}\n\n// ============================================\n// Web Search Configuration Types\n// ============================================\n\n/**\n * User location for web search context in the Responses API.\n *\n * Used to localize web search results based on the user's approximate location.\n * In the Responses API, location fields are at the same level as the type field.\n *\n * @see {@link OpenAICompletionsWebSearchUserLocation} for the Chat Completions API version\n */\nexport interface OpenAIWebSearchUserLocation {\n /** Location type - must be 'approximate' */\n type: 'approximate';\n /** City name */\n city?: string;\n /** ISO 3166-1 country code (e.g., \"US\") */\n country?: string;\n /** Region/state name */\n region?: string;\n /** IANA timezone (e.g., \"America/New_York\") */\n timezone?: string;\n}\n\n/**\n * User location for web search context in the Chat Completions API.\n *\n * Used to localize web search results based on the user's approximate location.\n * In the Completions API, location fields are nested under an `approximate` object.\n *\n * @see {@link OpenAIWebSearchUserLocation} for the Responses API version\n */\nexport interface OpenAICompletionsWebSearchUserLocation {\n /** Location type - must be 'approximate' */\n type: 'approximate';\n /** Approximate location details */\n approximate: {\n /** City name */\n city?: string;\n /** ISO 3166-1 country code (e.g., \"US\") */\n country?: string;\n /** Region/state name */\n region?: string;\n /** IANA timezone (e.g., \"America/New_York\") */\n timezone?: string;\n };\n}\n\n/**\n * Web search configuration options for the Chat Completions API.\n *\n * Enables web search capabilities when using search-enabled models.\n * Use with models that support web search (e.g., gpt-4o-search-preview).\n */\nexport interface OpenAIWebSearchOptions {\n /**\n * Context size for search results\n * Controls how much context from web results to include\n */\n search_context_size?: 'low' | 'medium' | 'high';\n /** User location for localizing search results */\n user_location?: OpenAICompletionsWebSearchUserLocation | null;\n}\n\n/**\n * Parameters for the OpenAI Chat Completions API.\n *\n * These parameters are passed directly to the `/v1/chat/completions` endpoint.\n * The Chat Completions API is the legacy API for chat interactions with\n * OpenAI models. For the modern API with built-in tools, see {@link OpenAIResponsesParams}.\n *\n * @example\n * ```typescript\n * const params: OpenAICompletionsParams = {\n * temperature: 0.7,\n * max_tokens: 1000,\n * reasoning_effort: 'medium'\n * };\n * ```\n *\n * @see {@link OpenAIResponsesParams} for the modern Responses API parameters\n */\nexport interface OpenAICompletionsParams {\n /** Maximum number of tokens to generate (legacy, prefer max_completion_tokens) */\n max_tokens?: number;\n\n /** Maximum completion tokens (preferred for newer models) */\n max_completion_tokens?: number;\n\n /** Temperature for randomness (0.0 - 2.0) */\n temperature?: number;\n\n /** Top-p (nucleus) sampling (0.0 - 1.0) */\n top_p?: number;\n\n /** Frequency penalty (-2.0 - 2.0) */\n frequency_penalty?: number;\n\n /** Presence penalty (-2.0 - 2.0) */\n presence_penalty?: number;\n\n /** Custom stop sequences */\n stop?: string | string[];\n\n /** Number of completions to generate */\n n?: number;\n\n /** Enable logprobs */\n logprobs?: boolean;\n\n /** Number of top logprobs to return (0-20) */\n top_logprobs?: number;\n\n /** Seed for deterministic sampling (beta, deprecated) */\n seed?: number;\n\n /** User identifier (deprecated, use safety_identifier or prompt_cache_key) */\n user?: string;\n\n /** Logit bias map */\n logit_bias?: Record<string, number>;\n\n /** Verbosity control */\n verbosity?: 'low' | 'medium' | 'high';\n\n /** Whether to enable parallel tool calls */\n parallel_tool_calls?: boolean;\n\n /** Reasoning effort for reasoning models */\n reasoning_effort?: 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';\n\n /** Service tier */\n service_tier?: 'auto' | 'default' | 'flex' | 'scale' | 'priority';\n\n /** Store completion for distillation */\n store?: boolean;\n\n /** Metadata key-value pairs (max 16, keys max 64 chars, values max 512 chars) */\n metadata?: Record<string, string>;\n\n /** Response format for structured output */\n response_format?: OpenAIResponseFormat;\n\n /**\n * Predicted Output configuration for faster regeneration\n * Improves response times when large parts of the response are known ahead of time\n */\n prediction?: {\n type: 'content';\n content: string | Array<{ type: 'text'; text: string }>;\n };\n\n /**\n * Stable identifier for caching similar requests\n * Used to optimize cache hit rates (replaces user field)\n */\n prompt_cache_key?: string;\n\n /**\n * Retention policy for prompt cache\n * Set to \"24h\" to enable extended prompt caching up to 24 hours\n */\n prompt_cache_retention?: 'in-memory' | '24h';\n\n /**\n * Stable identifier for abuse detection\n * Recommend hashing username or email address\n */\n safety_identifier?: string;\n\n /**\n * Output modalities to generate\n * Default: [\"text\"]. Use [\"text\", \"audio\"] for audio-capable models\n */\n modalities?: Array<'text' | 'audio'>;\n\n /**\n * Audio output configuration\n * Required when modalities includes \"audio\"\n */\n audio?: OpenAIAudioConfig | null;\n\n /**\n * Web search configuration\n * Enables the model to search the web for up-to-date information\n */\n web_search_options?: OpenAIWebSearchOptions;\n}\n\n/**\n * Reference to a prompt template stored in OpenAI's system.\n *\n * Allows using pre-defined prompt templates with variable substitution.\n */\nexport interface OpenAIPromptTemplate {\n /** Prompt template ID */\n id: string;\n /** Variables to fill into the template */\n variables?: Record<string, string>;\n}\n\n/**\n * Reference to an existing conversation for the Responses API.\n *\n * Items from this conversation are prepended to the input items,\n * enabling multi-turn conversations without resending full history.\n * Cannot be used together with `previous_response_id`.\n */\nexport interface OpenAIConversation {\n /** Conversation ID */\n id: string;\n}\n\n/**\n * Parameters for the OpenAI Responses API.\n *\n * These parameters are passed directly to the `/v1/responses` endpoint.\n * The Responses API is the modern, recommended API that supports built-in\n * tools like web search, image generation, file search, and code interpreter.\n *\n * @example Basic usage\n * ```typescript\n * const params: OpenAIResponsesParams = {\n * max_output_tokens: 1000,\n * temperature: 0.7,\n * reasoning: { effort: 'medium' }\n * };\n * ```\n *\n * @example With built-in tools\n * ```typescript\n * import { tools } from './types';\n *\n * const params: OpenAIResponsesParams = {\n * max_output_tokens: 2000,\n * tools: [tools.webSearch(), tools.imageGeneration()]\n * };\n * ```\n *\n * @see {@link OpenAICompletionsParams} for the legacy Chat Completions API parameters\n */\nexport interface OpenAIResponsesParams {\n /** Maximum output tokens */\n max_output_tokens?: number;\n\n /** Temperature for randomness (0.0 - 2.0) */\n temperature?: number;\n\n /** Top-p (nucleus) sampling (0.0 - 1.0) */\n top_p?: number;\n\n /** Number of top logprobs to return (0-20) */\n top_logprobs?: number;\n\n /** Whether to enable parallel tool calls */\n parallel_tool_calls?: boolean;\n\n /** Reasoning configuration (for gpt-5 and o-series models) */\n reasoning?: {\n effort?: 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';\n /** Include summary of reasoning */\n summary?: 'auto' | 'concise' | 'detailed';\n };\n\n /** Service tier */\n service_tier?: 'auto' | 'default' | 'flex' | 'scale' | 'priority';\n\n /** Truncation strategy */\n truncation?: 'auto' | 'disabled';\n\n /**\n * Fields to include in output\n * Supported values:\n * - 'web_search_call.action.sources': Include web search sources\n * - 'code_interpreter_call.outputs': Include code execution outputs\n * - 'computer_call_output.output.image_url': Include computer call images\n * - 'file_search_call.results': Include file search results\n * - 'message.input_image.image_url': Include input image URLs\n * - 'message.output_text.logprobs': Include logprobs with messages\n * - 'reasoning.encrypted_content': Include encrypted reasoning tokens\n */\n include?: string[];\n\n /** Background processing - run response asynchronously */\n background?: boolean;\n\n /** Continue from a previous response (cannot use with conversation) */\n previous_response_id?: string;\n\n /**\n * Conversation context - items prepended to input_items\n * Cannot be used with previous_response_id\n */\n conversation?: string | OpenAIConversation;\n\n /** Store response for continuation */\n store?: boolean;\n\n /** Metadata key-value pairs (max 16, keys max 64 chars, values max 512 chars) */\n metadata?: Record<string, string>;\n\n /**\n * Maximum total calls to built-in tools in a response\n * Applies across all built-in tool calls, not per tool\n */\n max_tool_calls?: number;\n\n /**\n * Reference to a prompt template and its variables\n */\n prompt?: OpenAIPromptTemplate;\n\n /**\n * Stable identifier for caching similar requests\n * Used to optimize cache hit rates (replaces user field)\n */\n prompt_cache_key?: string;\n\n /**\n * Retention policy for prompt cache\n * Set to \"24h\" to enable extended prompt caching up to 24 hours\n */\n prompt_cache_retention?: 'in-memory' | '24h';\n\n /**\n * Stable identifier for abuse detection\n * Recommend hashing username or email address\n */\n safety_identifier?: string;\n\n /** User identifier (deprecated, use safety_identifier or prompt_cache_key) */\n user?: string;\n\n /**\n * Built-in tools for the Responses API\n * Use the tool helper constructors: tools.webSearch(), tools.imageGeneration(), etc.\n *\n * @example\n * ```ts\n * import { tools } from 'provider-protocol/openai';\n *\n * const model = llm({\n * model: openai('gpt-4o'),\n * params: {\n * tools: [\n * tools.webSearch(),\n * tools.imageGeneration({ quality: 'high' }),\n * ],\n * },\n * });\n * ```\n */\n tools?: OpenAIBuiltInTool[];\n}\n\n/**\n * The API mode for the OpenAI provider.\n *\n * - `'responses'` - Modern Responses API (recommended)\n * - `'completions'` - Legacy Chat Completions API\n */\nexport type OpenAIAPIMode = 'responses' | 'completions';\n\n/**\n * Options when creating an OpenAI model reference.\n */\nexport interface OpenAIModelOptions {\n /** Which API to use */\n api?: OpenAIAPIMode;\n}\n\n/**\n * Model reference with OpenAI-specific options.\n * Used internally to track the selected model and API mode.\n */\nexport interface OpenAIModelReference {\n /** The OpenAI model identifier (e.g., 'gpt-4o', 'o1-preview') */\n modelId: string;\n /** Optional model-specific options */\n options?: OpenAIModelOptions;\n}\n\n/**\n * Configuration options for the OpenAI provider.\n */\nexport interface OpenAIConfig {\n /** Which API to use: 'responses' (modern) or 'completions' (legacy) */\n api?: 'responses' | 'completions';\n}\n\n// ============================================\n// Chat Completions API Types\n// ============================================\n\n/**\n * Request body for the OpenAI Chat Completions API.\n *\n * This interface represents the full request structure sent to\n * `/v1/chat/completions`. Most fields are optional and passed through\n * from {@link OpenAICompletionsParams}.\n */\nexport interface OpenAICompletionsRequest {\n model: string;\n messages: OpenAICompletionsMessage[];\n temperature?: number;\n top_p?: number;\n n?: number;\n stream?: boolean;\n stream_options?: { include_usage?: boolean };\n stop?: string | string[];\n max_tokens?: number;\n max_completion_tokens?: number;\n presence_penalty?: number;\n frequency_penalty?: number;\n logit_bias?: Record<string, number>;\n logprobs?: boolean;\n top_logprobs?: number;\n user?: string;\n seed?: number;\n tools?: OpenAICompletionsTool[];\n tool_choice?: OpenAIToolChoice;\n parallel_tool_calls?: boolean;\n response_format?: OpenAIResponseFormat;\n reasoning_effort?: string;\n verbosity?: 'low' | 'medium' | 'high';\n service_tier?: string;\n store?: boolean;\n metadata?: Record<string, string>;\n /** Predicted output for faster regeneration */\n prediction?: {\n type: 'content';\n content: string | Array<{ type: 'text'; text: string }>;\n };\n /** Stable identifier for caching (replaces user) */\n prompt_cache_key?: string;\n /** Retention policy for prompt cache */\n prompt_cache_retention?: string;\n /** Stable identifier for abuse detection */\n safety_identifier?: string;\n /** Output modalities (text, audio) */\n modalities?: Array<'text' | 'audio'>;\n /** Audio output configuration */\n audio?: OpenAIAudioConfig | null;\n /** Web search configuration */\n web_search_options?: OpenAIWebSearchOptions;\n}\n\n/**\n * Union type for all message types in the Chat Completions API.\n */\nexport type OpenAICompletionsMessage =\n | OpenAISystemMessage\n | OpenAIUserMessage\n | OpenAIAssistantMessage\n | OpenAIToolMessage;\n\n/** System or developer message for setting context and instructions */\nexport interface OpenAISystemMessage {\n role: 'system' | 'developer';\n content: string;\n name?: string;\n}\n\n/** User message with text or multimodal content */\nexport interface OpenAIUserMessage {\n role: 'user';\n content: string | OpenAIUserContent[];\n name?: string;\n}\n\n/** Assistant message containing the model's response */\nexport interface OpenAIAssistantMessage {\n role: 'assistant';\n content?: string | null;\n name?: string;\n tool_calls?: OpenAIToolCall[];\n refusal?: string | null;\n}\n\n/** Tool result message providing output from a function call */\nexport interface OpenAIToolMessage {\n role: 'tool';\n content: string;\n tool_call_id: string;\n}\n\n/**\n * Union type for user content parts (text or image).\n */\nexport type OpenAIUserContent = OpenAITextContent | OpenAIImageContent;\n\n/** Text content part */\nexport interface OpenAITextContent {\n type: 'text';\n text: string;\n}\n\n/** Image content part with URL reference */\nexport interface OpenAIImageContent {\n type: 'image_url';\n image_url: {\n url: string;\n detail?: 'auto' | 'low' | 'high';\n };\n}\n\n/**\n * Tool call structure in assistant messages.\n * Represents a function call requested by the model.\n */\nexport interface OpenAIToolCall {\n id: string;\n type: 'function';\n function: {\n name: string;\n arguments: string;\n };\n}\n\n/**\n * Tool definition for the Chat Completions API.\n * Functions are defined with JSON Schema parameters.\n */\nexport interface OpenAICompletionsTool {\n type: 'function';\n function: {\n name: string;\n description: string;\n parameters: {\n type: 'object';\n properties: Record<string, unknown>;\n required?: string[];\n additionalProperties?: boolean;\n };\n strict?: boolean;\n };\n}\n\n/**\n * Tool choice options for controlling function calling behavior.\n */\nexport type OpenAIToolChoice =\n | 'none'\n | 'auto'\n | 'required'\n | { type: 'function'; function: { name: string } };\n\n/**\n * Response format options for structured output.\n */\nexport type OpenAIResponseFormat =\n | { type: 'text' }\n | { type: 'json_object' }\n | {\n type: 'json_schema';\n json_schema: {\n name: string;\n description?: string;\n schema: Record<string, unknown>;\n strict?: boolean;\n };\n };\n\n/**\n * Response structure from the Chat Completions API.\n */\nexport interface OpenAICompletionsResponse {\n id: string;\n object: 'chat.completion';\n created: number;\n model: string;\n choices: OpenAICompletionsChoice[];\n usage: OpenAIUsage;\n system_fingerprint?: string;\n service_tier?: string;\n}\n\n/** A single choice from a completion response */\nexport interface OpenAICompletionsChoice {\n index: number;\n message: OpenAIAssistantMessage;\n finish_reason: 'stop' | 'length' | 'tool_calls' | 'content_filter' | null;\n logprobs?: OpenAILogprobs | null;\n}\n\n/** Log probability information for tokens */\nexport interface OpenAILogprobs {\n content?: Array<{\n token: string;\n logprob: number;\n bytes?: number[];\n top_logprobs?: Array<{\n token: string;\n logprob: number;\n bytes?: number[];\n }>;\n }>;\n}\n\n/** Token usage statistics from the API response */\nexport interface OpenAIUsage {\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n prompt_tokens_details?: {\n cached_tokens?: number;\n audio_tokens?: number;\n };\n completion_tokens_details?: {\n reasoning_tokens?: number;\n audio_tokens?: number;\n accepted_prediction_tokens?: number;\n rejected_prediction_tokens?: number;\n };\n}\n\n/**\n * Streaming chunk structure from the Chat Completions API.\n * Sent via SSE during streaming responses.\n */\nexport interface OpenAICompletionsStreamChunk {\n id: string;\n object: 'chat.completion.chunk';\n created: number;\n model: string;\n choices: OpenAICompletionsStreamChoice[];\n usage?: OpenAIUsage | null;\n system_fingerprint?: string;\n service_tier?: string;\n}\n\n/** A streaming choice containing incremental content */\nexport interface OpenAICompletionsStreamChoice {\n index: number;\n delta: OpenAICompletionsStreamDelta;\n finish_reason: 'stop' | 'length' | 'tool_calls' | 'content_filter' | null;\n logprobs?: OpenAILogprobs | null;\n}\n\n/** Incremental content delta in a streaming chunk */\nexport interface OpenAICompletionsStreamDelta {\n role?: 'assistant';\n content?: string | null;\n tool_calls?: OpenAIStreamToolCall[];\n refusal?: string | null;\n}\n\n/** Incremental tool call data in a streaming chunk */\nexport interface OpenAIStreamToolCall {\n index: number;\n id?: string;\n type?: 'function';\n function?: {\n name?: string;\n arguments?: string;\n };\n}\n\n// ============================================\n// Responses API Types\n// ============================================\n\n/**\n * Request body for the OpenAI Responses API.\n *\n * This interface represents the full request structure sent to\n * `/v1/responses`. Supports both function tools and built-in tools.\n */\nexport interface OpenAIResponsesRequest {\n model: string;\n input: string | OpenAIResponsesInputItem[];\n instructions?: string;\n max_output_tokens?: number;\n temperature?: number;\n top_p?: number;\n top_logprobs?: number;\n stream?: boolean;\n tools?: OpenAIResponsesToolUnion[];\n tool_choice?: OpenAIResponsesToolChoice;\n parallel_tool_calls?: boolean;\n text?: OpenAIResponsesTextConfig;\n truncation?: 'auto' | 'disabled';\n store?: boolean;\n metadata?: Record<string, string>;\n reasoning?: {\n effort?: 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';\n summary?: 'auto' | 'concise' | 'detailed';\n };\n service_tier?: string;\n include?: string[];\n background?: boolean;\n previous_response_id?: string;\n /** Conversation context (cannot use with previous_response_id) */\n conversation?: string | OpenAIConversation;\n /** Maximum total calls to built-in tools */\n max_tool_calls?: number;\n /** Prompt template reference */\n prompt?: OpenAIPromptTemplate;\n /** Stable identifier for caching (replaces user) */\n prompt_cache_key?: string;\n /** Retention policy for prompt cache */\n prompt_cache_retention?: 'in-memory' | '24h';\n /** Stable identifier for abuse detection */\n safety_identifier?: string;\n /** User identifier (deprecated) */\n user?: string;\n}\n\n/**\n * Union type for all input item types in the Responses API.\n */\nexport type OpenAIResponsesInputItem =\n | OpenAIResponsesSystemItem\n | OpenAIResponsesUserItem\n | OpenAIResponsesAssistantItem\n | OpenAIResponsesFunctionCallInputItem\n | OpenAIResponsesToolResultItem;\n\n/** System or developer message input item */\nexport interface OpenAIResponsesSystemItem {\n type: 'message';\n role: 'system' | 'developer';\n content: string | OpenAIResponsesContentPart[];\n}\n\n/** User message input item */\nexport interface OpenAIResponsesUserItem {\n type: 'message';\n role: 'user';\n content: string | OpenAIResponsesContentPart[];\n}\n\n/** Assistant message input item (for conversation history) */\nexport interface OpenAIResponsesAssistantItem {\n type: 'message';\n role: 'assistant';\n content: string | OpenAIResponsesContentPart[];\n}\n\n/** Function call input item (precedes function_call_output) */\nexport interface OpenAIResponsesFunctionCallInputItem {\n type: 'function_call';\n id: string;\n call_id: string;\n name: string;\n arguments: string;\n}\n\n/** Function call output (tool result) input item */\nexport interface OpenAIResponsesToolResultItem {\n type: 'function_call_output';\n call_id: string;\n output: string;\n}\n\n/**\n * Union type for content parts in the Responses API.\n */\nexport type OpenAIResponsesContentPart =\n | OpenAIResponsesTextPart\n | OpenAIResponsesImagePart\n | OpenAIResponsesFunctionCallPart;\n\n/** Text content part (input or output) */\nexport interface OpenAIResponsesTextPart {\n type: 'input_text' | 'output_text';\n text: string;\n}\n\n/** Image content part */\nexport interface OpenAIResponsesImagePart {\n type: 'input_image';\n image_url?: string;\n image?: string;\n detail?: 'auto' | 'low' | 'high';\n}\n\n/** Function call content part (embedded in messages) */\nexport interface OpenAIResponsesFunctionCallPart {\n type: 'function_call';\n id: string;\n call_id: string;\n name: string;\n arguments: string;\n}\n\n/**\n * Function tool definition for the Responses API.\n * Uses a flatter structure than Chat Completions.\n */\nexport interface OpenAIResponsesTool {\n type: 'function';\n name: string;\n description: string;\n parameters: {\n type: 'object';\n properties: Record<string, unknown>;\n required?: string[];\n additionalProperties?: boolean;\n };\n strict?: boolean;\n}\n\n/**\n * Tool choice options for the Responses API.\n */\nexport type OpenAIResponsesToolChoice =\n | 'none'\n | 'auto'\n | 'required'\n | { type: 'function'; name: string };\n\n/**\n * Text output configuration for structured output in the Responses API.\n */\nexport interface OpenAIResponsesTextConfig {\n format?:\n | { type: 'text' }\n | { type: 'json_object' }\n | {\n type: 'json_schema';\n name: string;\n description?: string;\n schema: Record<string, unknown>;\n strict?: boolean;\n };\n}\n\n/**\n * Response structure from the Responses API.\n */\nexport interface OpenAIResponsesResponse {\n id: string;\n object: 'response';\n created_at: number;\n model: string;\n output: OpenAIResponsesOutputItem[];\n usage: OpenAIResponsesUsage;\n status: 'completed' | 'failed' | 'incomplete' | 'in_progress';\n error?: {\n code: string;\n message: string;\n };\n incomplete_details?: {\n reason: string;\n };\n}\n\n/**\n * Union type for all output item types in Responses API responses.\n */\nexport type OpenAIResponsesOutputItem =\n | OpenAIResponsesMessageOutput\n | OpenAIResponsesFunctionCallOutput\n | OpenAIResponsesImageGenerationOutput\n | OpenAIResponsesWebSearchOutput;\n\n/** Assistant message output item */\nexport interface OpenAIResponsesMessageOutput {\n type: 'message';\n id: string;\n role: 'assistant';\n content: OpenAIResponsesOutputContent[];\n status: 'completed' | 'in_progress';\n}\n\n/** Function call output item (tool call requested by model) */\nexport interface OpenAIResponsesFunctionCallOutput {\n type: 'function_call';\n id: string;\n call_id: string;\n name: string;\n arguments: string;\n status: 'completed' | 'in_progress';\n}\n\n/** Image generation output item (from built-in image generation tool) */\nexport interface OpenAIResponsesImageGenerationOutput {\n type: 'image_generation_call';\n id: string;\n result?: string;\n status: 'completed' | 'in_progress';\n}\n\n/** Web search output item (from built-in web search tool) */\nexport interface OpenAIResponsesWebSearchOutput {\n type: 'web_search_call';\n id: string;\n status: 'completed' | 'in_progress';\n}\n\n/** Output content types (text or refusal) */\nexport type OpenAIResponsesOutputContent =\n | { type: 'output_text'; text: string; annotations?: unknown[] }\n | { type: 'refusal'; refusal: string };\n\n/** Token usage statistics for Responses API */\nexport interface OpenAIResponsesUsage {\n input_tokens: number;\n output_tokens: number;\n total_tokens: number;\n input_tokens_details?: {\n cached_tokens?: number;\n text_tokens?: number;\n image_tokens?: number;\n audio_tokens?: number;\n };\n output_tokens_details?: {\n text_tokens?: number;\n reasoning_tokens?: number;\n audio_tokens?: number;\n };\n}\n\n/**\n * Union type for all streaming events from the Responses API.\n * The Responses API uses granular events for different stages of response generation.\n */\nexport type OpenAIResponsesStreamEvent =\n | OpenAIResponseCreatedEvent\n | OpenAIResponseInProgressEvent\n | OpenAIResponseCompletedEvent\n | OpenAIResponseFailedEvent\n | OpenAIResponseOutputItemAddedEvent\n | OpenAIResponseOutputItemDoneEvent\n | OpenAIResponseContentPartAddedEvent\n | OpenAIResponseContentPartDoneEvent\n | OpenAIResponseTextDeltaEvent\n | OpenAIResponseTextDoneEvent\n | OpenAIResponseRefusalDeltaEvent\n | OpenAIResponseRefusalDoneEvent\n | OpenAIResponseFunctionCallArgumentsDeltaEvent\n | OpenAIResponseFunctionCallArgumentsDoneEvent\n | OpenAIResponseErrorEvent;\n\nexport interface OpenAIResponseCreatedEvent {\n type: 'response.created';\n response: OpenAIResponsesResponse;\n}\n\nexport interface OpenAIResponseInProgressEvent {\n type: 'response.in_progress';\n response: OpenAIResponsesResponse;\n}\n\nexport interface OpenAIResponseCompletedEvent {\n type: 'response.completed';\n response: OpenAIResponsesResponse;\n}\n\nexport interface OpenAIResponseFailedEvent {\n type: 'response.failed';\n response: OpenAIResponsesResponse;\n}\n\nexport interface OpenAIResponseOutputItemAddedEvent {\n type: 'response.output_item.added';\n output_index: number;\n item: OpenAIResponsesOutputItem;\n}\n\nexport interface OpenAIResponseOutputItemDoneEvent {\n type: 'response.output_item.done';\n output_index: number;\n item: OpenAIResponsesOutputItem;\n}\n\nexport interface OpenAIResponseContentPartAddedEvent {\n type: 'response.content_part.added';\n output_index: number;\n content_index: number;\n part: OpenAIResponsesOutputContent;\n}\n\nexport interface OpenAIResponseContentPartDoneEvent {\n type: 'response.content_part.done';\n output_index: number;\n content_index: number;\n part: OpenAIResponsesOutputContent;\n}\n\nexport interface OpenAIResponseTextDeltaEvent {\n type: 'response.output_text.delta';\n output_index: number;\n content_index: number;\n delta: string;\n}\n\nexport interface OpenAIResponseTextDoneEvent {\n type: 'response.output_text.done';\n output_index: number;\n content_index: number;\n text: string;\n}\n\nexport interface OpenAIResponseRefusalDeltaEvent {\n type: 'response.refusal.delta';\n output_index: number;\n content_index: number;\n delta: string;\n}\n\nexport interface OpenAIResponseRefusalDoneEvent {\n type: 'response.refusal.done';\n output_index: number;\n content_index: number;\n refusal: string;\n}\n\nexport interface OpenAIResponseFunctionCallArgumentsDeltaEvent {\n type: 'response.function_call_arguments.delta';\n output_index: number;\n item_id: string;\n delta: string;\n call_id?: string;\n}\n\nexport interface OpenAIResponseFunctionCallArgumentsDoneEvent {\n type: 'response.function_call_arguments.done';\n output_index: number;\n item_id: string;\n name: string;\n arguments: string;\n call_id?: string;\n}\n\nexport interface OpenAIResponseErrorEvent {\n type: 'error';\n error: {\n type: string;\n code?: string;\n message: string;\n };\n}\n\n// ============================================\n// Built-in Tools for Responses API\n// ============================================\n\n/**\n * Web search tool for Responses API\n * Enables the model to search the web for up-to-date information\n */\nexport interface OpenAIWebSearchTool {\n type: 'web_search';\n /**\n * Context size for search results\n * Controls how much context from web results to include\n */\n search_context_size?: 'low' | 'medium' | 'high';\n /** User location for localizing search results */\n user_location?: OpenAIWebSearchUserLocation | null;\n}\n\n/**\n * File search tool for Responses API\n * Enables the model to search through uploaded files\n */\nexport interface OpenAIFileSearchTool {\n type: 'file_search';\n /** File search configuration */\n file_search?: {\n /** Vector store IDs to search */\n vector_store_ids: string[];\n /** Maximum number of results to return */\n max_num_results?: number;\n /** Ranking options for search results */\n ranking_options?: {\n /** Ranker to use */\n ranker?: 'auto' | 'default_2024_08_21';\n /** Score threshold (0-1) */\n score_threshold?: number;\n };\n /** Filters to apply */\n filters?: Record<string, unknown>;\n };\n}\n\n/**\n * Code interpreter container configuration\n */\nexport interface OpenAICodeInterpreterContainer {\n /** Container type - 'auto' creates a new container */\n type: 'auto';\n /** Memory limit for the container (e.g., '1g', '4g') */\n memory_limit?: string;\n /** File IDs to make available in the container */\n file_ids?: string[];\n}\n\n/**\n * Code interpreter tool for Responses API\n * Allows the model to write and run Python code\n */\nexport interface OpenAICodeInterpreterTool {\n type: 'code_interpreter';\n /** Code interpreter configuration */\n code_interpreter?: {\n /** Container configuration */\n container: string | OpenAICodeInterpreterContainer;\n };\n}\n\n/**\n * Computer tool environment configuration\n */\nexport interface OpenAIComputerEnvironment {\n /** Environment type */\n type: 'browser' | 'mac' | 'windows' | 'linux' | 'ubuntu';\n}\n\n/**\n * Computer tool for Responses API\n * Enables the model to interact with computer interfaces\n */\nexport interface OpenAIComputerTool {\n type: 'computer';\n /** Computer tool configuration */\n computer?: {\n /** Display width in pixels */\n display_width: number;\n /** Display height in pixels */\n display_height: number;\n /** Environment configuration */\n environment?: OpenAIComputerEnvironment;\n };\n}\n\n/**\n * Image generation tool for Responses API\n */\nexport interface OpenAIImageGenerationTool {\n type: 'image_generation';\n /** Background transparency */\n background?: 'transparent' | 'opaque' | 'auto';\n /** Input image formats supported */\n input_image_mask?: boolean;\n /** Model to use for generation */\n model?: string;\n /** Moderation level */\n moderation?: 'auto' | 'low';\n /** Output compression */\n output_compression?: number;\n /** Output format */\n output_format?: 'png' | 'jpeg' | 'webp';\n /** Partial images during streaming */\n partial_images?: number;\n /** Image quality */\n quality?: 'auto' | 'high' | 'medium' | 'low';\n /** Image size */\n size?: 'auto' | '1024x1024' | '1024x1536' | '1536x1024';\n}\n\n/**\n * MCP (Model Context Protocol) server configuration\n */\nexport interface OpenAIMcpServerConfig {\n /** Server URL */\n url: string;\n /** Server name for identification */\n name?: string;\n /** Tool configuration for the server */\n tool_configuration?: {\n /** Allowed tools from this server */\n allowed_tools?: string[] | { type: 'all' };\n };\n /** Headers to send with requests */\n headers?: Record<string, string>;\n /** Allowed resources */\n allowed_resources?: string[];\n /** Require approval for tool calls */\n require_approval?: 'always' | 'never' | { type: 'except'; tools: string[] };\n}\n\n/**\n * MCP tool for Responses API\n * Enables connections to MCP servers\n */\nexport interface OpenAIMcpTool {\n type: 'mcp';\n /** MCP server configurations */\n mcp?: {\n /** Server configuration */\n server: OpenAIMcpServerConfig;\n };\n}\n\n/**\n * Union type for all Responses API built-in tools\n */\nexport type OpenAIBuiltInTool =\n | OpenAIWebSearchTool\n | OpenAIFileSearchTool\n | OpenAICodeInterpreterTool\n | OpenAIComputerTool\n | OpenAIImageGenerationTool\n | OpenAIMcpTool;\n\n/**\n * Combined tool type for Responses API (built-in or function)\n */\nexport type OpenAIResponsesToolUnion = OpenAIResponsesTool | OpenAIBuiltInTool;\n\n// ============================================\n// Tool Helper Constructors\n// ============================================\n\n/**\n * Creates a web search tool configuration for the Responses API.\n *\n * The web search tool enables the model to search the web for up-to-date information.\n *\n * @param options - Optional configuration for search behavior and user location\n * @returns A web search tool configuration object\n *\n * @example\n * ```typescript\n * // Basic web search\n * const search = webSearchTool();\n *\n * // With configuration\n * const searchWithLocation = webSearchTool({\n * search_context_size: 'high',\n * user_location: {\n * type: 'approximate',\n * city: 'San Francisco',\n * country: 'US'\n * }\n * });\n * ```\n */\nexport function webSearchTool(options?: {\n search_context_size?: 'low' | 'medium' | 'high';\n user_location?: OpenAIWebSearchUserLocation | null;\n}): OpenAIWebSearchTool {\n if (options) {\n return {\n type: 'web_search',\n ...options,\n } as OpenAIWebSearchTool;\n }\n return { type: 'web_search' };\n}\n\n/**\n * Creates a file search tool configuration for the Responses API.\n *\n * The file search tool enables the model to search through files in vector stores.\n *\n * @param options - Configuration including vector store IDs and search options\n * @returns A file search tool configuration object\n *\n * @example\n * ```typescript\n * const fileSearch = fileSearchTool({\n * vector_store_ids: ['vs_abc123'],\n * max_num_results: 10\n * });\n * ```\n */\nexport function fileSearchTool(options: {\n vector_store_ids: string[];\n max_num_results?: number;\n ranking_options?: {\n ranker?: 'auto' | 'default_2024_08_21';\n score_threshold?: number;\n };\n filters?: Record<string, unknown>;\n}): OpenAIFileSearchTool {\n return {\n type: 'file_search',\n file_search: options,\n };\n}\n\n/**\n * Creates a code interpreter tool configuration for the Responses API.\n *\n * The code interpreter tool allows the model to write and execute Python code\n * in a sandboxed environment.\n *\n * @param options - Optional container configuration\n * @returns A code interpreter tool configuration object\n *\n * @example\n * ```typescript\n * // Default configuration\n * const interpreter = codeInterpreterTool();\n *\n * // With custom container settings\n * const customInterpreter = codeInterpreterTool({\n * container: {\n * type: 'auto',\n * memory_limit: '4g',\n * file_ids: ['file_abc123']\n * }\n * });\n * ```\n */\nexport function codeInterpreterTool(options?: {\n container?: string | OpenAICodeInterpreterContainer;\n}): OpenAICodeInterpreterTool {\n return {\n type: 'code_interpreter',\n ...(options?.container && { code_interpreter: { container: options.container } }),\n };\n}\n\n/**\n * Creates a computer tool configuration for the Responses API.\n *\n * The computer tool enables the model to interact with computer interfaces\n * through mouse and keyboard actions.\n *\n * @param options - Display configuration and environment settings\n * @returns A computer tool configuration object\n *\n * @example\n * ```typescript\n * const computer = computerTool({\n * display_width: 1920,\n * display_height: 1080,\n * environment: { type: 'browser' }\n * });\n * ```\n */\nexport function computerTool(options: {\n display_width: number;\n display_height: number;\n environment?: OpenAIComputerEnvironment;\n}): OpenAIComputerTool {\n return {\n type: 'computer',\n computer: options,\n };\n}\n\n/**\n * Creates an image generation tool configuration for the Responses API.\n *\n * The image generation tool allows the model to generate images based on prompts.\n *\n * @param options - Optional image generation settings\n * @returns An image generation tool configuration object\n *\n * @example\n * ```typescript\n * // Default configuration\n * const imageGen = imageGenerationTool();\n *\n * // With custom settings\n * const customImageGen = imageGenerationTool({\n * quality: 'high',\n * size: '1024x1024',\n * background: 'transparent'\n * });\n * ```\n */\nexport function imageGenerationTool(options?: {\n background?: 'transparent' | 'opaque' | 'auto';\n model?: string;\n partial_images?: number;\n quality?: 'auto' | 'high' | 'medium' | 'low';\n size?: 'auto' | '1024x1024' | '1024x1536' | '1536x1024';\n output_format?: 'png' | 'jpeg' | 'webp';\n}): OpenAIImageGenerationTool {\n if (options) {\n return {\n type: 'image_generation',\n ...options,\n };\n }\n return { type: 'image_generation' };\n}\n\n/**\n * Creates an MCP (Model Context Protocol) tool configuration for the Responses API.\n *\n * The MCP tool enables connections to external MCP servers, allowing the model\n * to use tools and resources provided by those servers.\n *\n * @param options - MCP server configuration\n * @returns An MCP tool configuration object\n *\n * @example\n * ```typescript\n * const mcp = mcpTool({\n * url: 'https://mcp-server.example.com',\n * name: 'my-mcp-server',\n * allowed_tools: ['tool1', 'tool2']\n * });\n * ```\n */\nexport function mcpTool(options: {\n url: string;\n name?: string;\n allowed_tools?: string[] | { type: 'all' };\n headers?: Record<string, string>;\n require_approval?: 'always' | 'never' | { type: 'except'; tools: string[] };\n}): OpenAIMcpTool {\n const { url, name, allowed_tools, headers, require_approval } = options;\n return {\n type: 'mcp',\n mcp: {\n server: {\n url,\n name,\n ...(allowed_tools && { tool_configuration: { allowed_tools } }),\n headers,\n require_approval,\n },\n },\n };\n}\n\n/**\n * Namespace object containing all tool helper constructors.\n *\n * Provides a convenient way to create built-in tool configurations\n * for the Responses API.\n *\n * @example\n * ```typescript\n * import { tools } from './types';\n *\n * const params = {\n * tools: [\n * tools.webSearch(),\n * tools.imageGeneration({ quality: 'high' }),\n * tools.codeInterpreter()\n * ]\n * };\n * ```\n */\nexport const tools = {\n /** Creates a web search tool configuration */\n webSearch: webSearchTool,\n /** Creates a file search tool configuration */\n fileSearch: fileSearchTool,\n /** Creates a code interpreter tool configuration */\n codeInterpreter: codeInterpreterTool,\n /** Creates a computer tool configuration */\n computer: computerTool,\n /** Creates an image generation tool configuration */\n imageGeneration: imageGenerationTool,\n /** Creates an MCP tool configuration */\n mcp: mcpTool,\n};\n\n/**\n * OpenAI-specific HTTP headers for API requests.\n *\n * @example\n * ```typescript\n * const headers: OpenAIHeaders = {\n * 'OpenAI-Organization': 'org-abc123',\n * 'OpenAI-Project': 'proj-xyz789',\n * };\n * ```\n */\nexport interface OpenAIHeaders {\n /** Organization ID for multi-organization accounts. */\n 'OpenAI-Organization'?: string;\n /** Project ID for project-scoped API keys. */\n 'OpenAI-Project'?: string;\n /** Client-generated request ID for tracing. */\n 'X-Client-Request-Id'?: string;\n [key: string]: string | undefined;\n}\n","/**\n * @fileoverview OpenAI Provider Factory\n *\n * This module provides the main OpenAI provider implementation that supports both\n * the modern Responses API (default) and the legacy Chat Completions API.\n *\n * @example\n * ```typescript\n * import { openai } from './providers/openai';\n * import { llm } from './core/llm';\n *\n * // Using the modern Responses API (default)\n * const model = llm({\n * model: openai('gpt-4o'),\n * params: { max_output_tokens: 1000 }\n * });\n *\n * // Using the legacy Chat Completions API\n * const legacyModel = llm({\n * model: openai('gpt-4o', { api: 'completions' }),\n * params: { max_tokens: 1000 }\n * });\n * ```\n *\n * @module providers/openai\n */\n\nimport type {\n Provider,\n ModelReference,\n LLMHandler,\n LLMProvider,\n} from '../../types/provider.ts';\nimport { createCompletionsLLMHandler } from './llm.completions.ts';\nimport { createResponsesLLMHandler } from './llm.responses.ts';\nimport type { OpenAICompletionsParams, OpenAIResponsesParams } from './types.ts';\n\n/**\n * Union type for the LLM handler that supports both API modes.\n * Used internally for the dynamic handler selection based on API mode.\n */\ntype OpenAILLMParamsUnion = OpenAICompletionsParams | OpenAIResponsesParams;\n\n/**\n * Configuration options for the OpenAI provider.\n *\n * Controls which underlying OpenAI API endpoint is used when making requests.\n * The Responses API is the modern, recommended approach while the Chat Completions\n * API provides backward compatibility with existing integrations.\n */\nexport interface OpenAIProviderOptions {\n /**\n * Which API endpoint to use for requests.\n *\n * - `'responses'` - Modern Responses API (default, recommended). Supports built-in\n * tools like web search, image generation, file search, and code interpreter.\n * - `'completions'` - Legacy Chat Completions API. Standard chat completion endpoint\n * with function calling support.\n *\n * @default 'responses'\n */\n api?: 'responses' | 'completions';\n}\n\n/**\n * OpenAI provider interface with configurable API mode.\n *\n * The provider is callable as a function to create model references, and also\n * exposes metadata about the provider and its supported modalities.\n *\n * @example Creating model references\n * ```typescript\n * // Using the modern Responses API (default, recommended)\n * const model = openai('gpt-4o');\n *\n * // Using the legacy Chat Completions API\n * const legacyModel = openai('gpt-4o', { api: 'completions' });\n *\n * // Explicit Responses API selection\n * const responsesModel = openai('gpt-4o', { api: 'responses' });\n * ```\n *\n * @see {@link OpenAIProviderOptions} for available configuration options\n * @see {@link OpenAIResponsesParams} for Responses API parameters\n * @see {@link OpenAICompletionsParams} for Chat Completions API parameters\n */\nexport interface OpenAIProvider extends Provider<OpenAIProviderOptions> {\n /**\n * Creates a model reference for the specified OpenAI model.\n *\n * @param modelId - The OpenAI model identifier (e.g., 'gpt-4o', 'gpt-4-turbo', 'o1-preview', 'gpt-4o-mini')\n * @param options - Optional provider configuration including API mode selection\n * @returns A model reference that can be used with the LLM core functions\n *\n * @example\n * ```typescript\n * const gpt4o = openai('gpt-4o');\n * const gpt4turbo = openai('gpt-4-turbo', { api: 'completions' });\n * ```\n */\n (modelId: string, options?: OpenAIProviderOptions): ModelReference<OpenAIProviderOptions>;\n\n /**\n * The provider identifier.\n * Always returns `'openai'` for this provider.\n */\n readonly name: 'openai';\n\n /**\n * The provider version following semantic versioning.\n */\n readonly version: string;\n\n /**\n * Supported modalities and their handlers.\n * Currently supports LLM modality with both Responses and Completions API handlers.\n */\n readonly modalities: {\n /** The LLM handler for text generation and chat completion */\n llm: LLMHandler<OpenAILLMParamsUnion>;\n };\n}\n\n/**\n * Factory function that creates and configures the OpenAI provider instance.\n *\n * This function initializes both the Responses API and Chat Completions API handlers,\n * sets up dynamic handler selection based on the API mode, and injects provider\n * references for spec compliance.\n *\n * @returns A fully configured OpenAI provider instance\n * @internal\n */\nfunction createOpenAIProvider(): OpenAIProvider {\n let currentApiMode: 'responses' | 'completions' = 'responses';\n\n const responsesHandler = createResponsesLLMHandler();\n const completionsHandler = createCompletionsLLMHandler();\n\n const fn = function (\n modelId: string,\n options?: OpenAIProviderOptions\n ): ModelReference<OpenAIProviderOptions> {\n const apiMode = options?.api ?? 'responses';\n currentApiMode = apiMode;\n return { modelId, provider };\n };\n\n const modalities = {\n get llm(): LLMHandler<OpenAILLMParamsUnion> {\n return currentApiMode === 'completions'\n ? (completionsHandler as unknown as LLMHandler<OpenAILLMParamsUnion>)\n : (responsesHandler as unknown as LLMHandler<OpenAILLMParamsUnion>);\n },\n };\n\n Object.defineProperties(fn, {\n name: {\n value: 'openai',\n writable: false,\n configurable: true,\n },\n version: {\n value: '1.0.0',\n writable: false,\n configurable: true,\n },\n modalities: {\n value: modalities,\n writable: false,\n configurable: true,\n },\n });\n\n const provider = fn as OpenAIProvider;\n\n responsesHandler._setProvider?.(provider as unknown as LLMProvider<OpenAIResponsesParams>);\n completionsHandler._setProvider?.(provider as unknown as LLMProvider<OpenAICompletionsParams>);\n\n return provider;\n}\n\n/**\n * The OpenAI provider instance.\n *\n * Supports both the modern Responses API (default) and the legacy Chat Completions API.\n * Use this provider to create model references for OpenAI models like GPT-4o, GPT-4 Turbo,\n * and the o1 series.\n *\n * @example Basic usage with Responses API (recommended)\n * ```typescript\n * import { openai } from './providers/openai';\n * import { llm } from './core/llm';\n *\n * const model = llm({\n * model: openai('gpt-4o'),\n * params: { max_output_tokens: 1000 }\n * });\n *\n * const turn = await model.generate('Hello!');\n * console.log(turn.response.text);\n * ```\n *\n * @example Using Chat Completions API\n * ```typescript\n * const legacyModel = llm({\n * model: openai('gpt-4o', { api: 'completions' }),\n * params: { max_tokens: 1000 }\n * });\n * ```\n *\n * @example With built-in tools (Responses API only)\n * ```typescript\n * import { openai, tools } from './providers/openai';\n *\n * const model = llm({\n * model: openai('gpt-4o'),\n * params: {\n * tools: [tools.webSearch(), tools.imageGeneration()]\n * }\n * });\n * ```\n */\nexport const openai = createOpenAIProvider();\n\n// Re-export types\nexport type {\n OpenAICompletionsParams,\n OpenAIResponsesParams,\n OpenAIConfig,\n OpenAIAPIMode,\n OpenAIModelOptions,\n OpenAIModelReference,\n // Audio and web search types\n OpenAIAudioConfig,\n OpenAIWebSearchOptions,\n OpenAIWebSearchUserLocation,\n OpenAICompletionsWebSearchUserLocation,\n // Built-in tool types\n OpenAIBuiltInTool,\n OpenAIWebSearchTool,\n OpenAIFileSearchTool,\n OpenAICodeInterpreterTool,\n OpenAICodeInterpreterContainer,\n OpenAIComputerTool,\n OpenAIComputerEnvironment,\n OpenAIImageGenerationTool,\n OpenAIMcpTool,\n OpenAIMcpServerConfig,\n OpenAIResponsesToolUnion,\n // Conversation and prompt types\n OpenAIConversation,\n OpenAIPromptTemplate,\n} from './types.ts';\n\n// Re-export tool helper constructors\nexport {\n tools,\n webSearchTool,\n fileSearchTool,\n codeInterpreterTool,\n computerTool,\n imageGenerationTool,\n mcpTool,\n} from './types.ts';\n\nexport type { OpenAIHeaders } from './types.ts';\n"],"mappings":"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","names":["transformRequest","transformTool","normalizeSystem","transformMessage","filterValidContent","extractToolOptions","transformResponse","createStreamState","transformStreamEvent","buildResponseFromState","OPENAI_CAPABILITIES","transformRequest","transformResponse","createStreamState","transformStreamEvent","buildResponseFromState"]}
|