@providerprotocol/ai 0.0.11 → 0.0.13

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.
Files changed (104) hide show
  1. package/dist/anthropic/index.d.ts +51 -15
  2. package/dist/anthropic/index.js +54 -19
  3. package/dist/anthropic/index.js.map +1 -1
  4. package/dist/{chunk-SUNYWHTH.js → chunk-MOU4U3PO.js} +55 -3
  5. package/dist/chunk-MOU4U3PO.js.map +1 -0
  6. package/dist/{chunk-Y6Q7JCNP.js → chunk-MSR5P65T.js} +1 -1
  7. package/dist/chunk-MSR5P65T.js.map +1 -0
  8. package/dist/{chunk-W4BB4BG2.js → chunk-SVYROCLD.js} +31 -11
  9. package/dist/chunk-SVYROCLD.js.map +1 -0
  10. package/dist/chunk-U4JJC2YX.js +234 -0
  11. package/dist/chunk-U4JJC2YX.js.map +1 -0
  12. package/dist/{chunk-X5G4EHL7.js → chunk-Z7RBRCRN.js} +1 -1
  13. package/dist/chunk-Z7RBRCRN.js.map +1 -0
  14. package/dist/google/index.d.ts +376 -7
  15. package/dist/google/index.js +127 -15
  16. package/dist/google/index.js.map +1 -1
  17. package/dist/http/index.d.ts +222 -25
  18. package/dist/http/index.js +3 -3
  19. package/dist/index.d.ts +1482 -198
  20. package/dist/index.js +233 -49
  21. package/dist/index.js.map +1 -1
  22. package/dist/ollama/index.d.ts +92 -20
  23. package/dist/ollama/index.js +17 -7
  24. package/dist/ollama/index.js.map +1 -1
  25. package/dist/openai/index.d.ts +340 -61
  26. package/dist/openai/index.js +57 -15
  27. package/dist/openai/index.js.map +1 -1
  28. package/dist/openrouter/index.d.ts +107 -51
  29. package/dist/openrouter/index.js +36 -8
  30. package/dist/openrouter/index.js.map +1 -1
  31. package/dist/provider-mKkz7Q9U.d.ts +488 -0
  32. package/dist/retry-Dh70lgr0.d.ts +508 -0
  33. package/dist/xai/index.d.ts +97 -22
  34. package/dist/xai/index.js +55 -19
  35. package/dist/xai/index.js.map +1 -1
  36. package/package.json +8 -12
  37. package/dist/chunk-CUCRF5W6.js +0 -136
  38. package/dist/chunk-CUCRF5W6.js.map +0 -1
  39. package/dist/chunk-SUNYWHTH.js.map +0 -1
  40. package/dist/chunk-W4BB4BG2.js.map +0 -1
  41. package/dist/chunk-X5G4EHL7.js.map +0 -1
  42. package/dist/chunk-Y6Q7JCNP.js.map +0 -1
  43. package/dist/provider-CUJWjgNl.d.ts +0 -192
  44. package/dist/retry-I2661_rv.d.ts +0 -118
  45. package/src/anthropic/index.ts +0 -3
  46. package/src/core/image.ts +0 -188
  47. package/src/core/llm.ts +0 -650
  48. package/src/core/provider.ts +0 -92
  49. package/src/google/index.ts +0 -3
  50. package/src/http/errors.ts +0 -112
  51. package/src/http/fetch.ts +0 -210
  52. package/src/http/index.ts +0 -31
  53. package/src/http/keys.ts +0 -136
  54. package/src/http/retry.ts +0 -205
  55. package/src/http/sse.ts +0 -136
  56. package/src/index.ts +0 -32
  57. package/src/ollama/index.ts +0 -3
  58. package/src/openai/index.ts +0 -39
  59. package/src/openrouter/index.ts +0 -11
  60. package/src/providers/anthropic/index.ts +0 -17
  61. package/src/providers/anthropic/llm.ts +0 -196
  62. package/src/providers/anthropic/transform.ts +0 -434
  63. package/src/providers/anthropic/types.ts +0 -213
  64. package/src/providers/google/index.ts +0 -17
  65. package/src/providers/google/llm.ts +0 -203
  66. package/src/providers/google/transform.ts +0 -447
  67. package/src/providers/google/types.ts +0 -214
  68. package/src/providers/ollama/index.ts +0 -43
  69. package/src/providers/ollama/llm.ts +0 -272
  70. package/src/providers/ollama/transform.ts +0 -434
  71. package/src/providers/ollama/types.ts +0 -260
  72. package/src/providers/openai/index.ts +0 -186
  73. package/src/providers/openai/llm.completions.ts +0 -201
  74. package/src/providers/openai/llm.responses.ts +0 -211
  75. package/src/providers/openai/transform.completions.ts +0 -561
  76. package/src/providers/openai/transform.responses.ts +0 -708
  77. package/src/providers/openai/types.ts +0 -1249
  78. package/src/providers/openrouter/index.ts +0 -177
  79. package/src/providers/openrouter/llm.completions.ts +0 -201
  80. package/src/providers/openrouter/llm.responses.ts +0 -211
  81. package/src/providers/openrouter/transform.completions.ts +0 -538
  82. package/src/providers/openrouter/transform.responses.ts +0 -742
  83. package/src/providers/openrouter/types.ts +0 -717
  84. package/src/providers/xai/index.ts +0 -223
  85. package/src/providers/xai/llm.completions.ts +0 -201
  86. package/src/providers/xai/llm.messages.ts +0 -195
  87. package/src/providers/xai/llm.responses.ts +0 -211
  88. package/src/providers/xai/transform.completions.ts +0 -565
  89. package/src/providers/xai/transform.messages.ts +0 -448
  90. package/src/providers/xai/transform.responses.ts +0 -678
  91. package/src/providers/xai/types.ts +0 -938
  92. package/src/types/content.ts +0 -133
  93. package/src/types/errors.ts +0 -85
  94. package/src/types/index.ts +0 -105
  95. package/src/types/llm.ts +0 -211
  96. package/src/types/messages.ts +0 -205
  97. package/src/types/provider.ts +0 -195
  98. package/src/types/schema.ts +0 -58
  99. package/src/types/stream.ts +0 -188
  100. package/src/types/thread.ts +0 -226
  101. package/src/types/tool.ts +0 -88
  102. package/src/types/turn.ts +0 -118
  103. package/src/utils/id.ts +0 -28
  104. package/src/xai/index.ts +0 -41
@@ -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":["import 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 * Transform UPP request to OpenAI Chat Completions format\n *\n * Params are spread directly to allow pass-through of any OpenAI API fields,\n * even those not explicitly defined in our type. This enables developers to\n * use new API features without waiting for library updates.\n */\nexport function transformRequest(\n request: LLMRequest<OpenAICompletionsParams>,\n modelId: string\n): OpenAICompletionsRequest {\n const params = request.params ?? ({} as OpenAICompletionsParams);\n\n // Spread params to pass through all fields, then set required fields\n const openaiRequest: OpenAICompletionsRequest = {\n ...params,\n model: modelId,\n messages: transformMessages(request.messages, request.system),\n };\n\n // Tools come from request, not params\n if (request.tools && request.tools.length > 0) {\n openaiRequest.tools = request.tools.map(transformTool);\n }\n\n // Structured output via response_format (overrides params.response_format if set)\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 * Transform messages including system prompt\n */\nfunction transformMessages(\n messages: Message[],\n system?: string\n): OpenAICompletionsMessage[] {\n const result: OpenAICompletionsMessage[] = [];\n\n // Add system message first if present\n if (system) {\n result.push({\n role: 'system',\n content: system,\n });\n }\n\n // Transform each message\n for (const message of messages) {\n // Handle tool result messages specially - they need to produce multiple 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 * Filter to only valid content blocks with a type property\n */\nfunction filterValidContent<T extends { type?: string }>(content: T[]): T[] {\n return content.filter((c) => c && typeof c.type === 'string');\n}\n\n/**\n * Transform a UPP Message to OpenAI format\n */\nfunction transformMessage(message: Message): OpenAICompletionsMessage | null {\n if (isUserMessage(message)) {\n const validContent = filterValidContent(message.content);\n // Check if we can use simple string 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 // Extract text 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 // Add tool calls if present\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 // Tool results are sent as individual tool messages\n // Return the first one and handle multiple in a different way\n // Actually, we need to return multiple messages for multiple tool results\n // This is handled by the caller - transform each result to a 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 // For now, return the first result - caller should handle multiple\n return results[0] ?? null;\n }\n\n return null;\n}\n\n/**\n * Transform multiple tool results to 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 * Transform a content block to OpenAI format\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 // Convert bytes to base64\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 * Transform a UPP Tool to OpenAI format\n */\nfunction transformTool(tool: Tool): OpenAICompletionsTool {\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 },\n };\n}\n\n/**\n * Transform OpenAI response to UPP LLMResponse\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 // Extract text content\n const textContent: TextBlock[] = [];\n let structuredData: unknown;\n if (choice.message.content) {\n textContent.push({ type: 'text', text: choice.message.content });\n // Try to parse as JSON for structured output (native JSON mode)\n try {\n structuredData = JSON.parse(choice.message.content);\n } catch {\n // Not valid JSON - that's fine, might not be structured output\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 // Extract tool calls\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 };\n\n // Map finish reason to stop reason\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 * State for accumulating streaming response\n */\nexport interface CompletionsStreamState {\n id: string;\n model: string;\n text: string;\n toolCalls: Map<number, { id: string; name: string; arguments: string }>;\n finishReason: string | null;\n inputTokens: number;\n outputTokens: number;\n hadRefusal: boolean;\n}\n\n/**\n * Create initial stream state\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 hadRefusal: false,\n };\n}\n\n/**\n * Transform OpenAI stream chunk to UPP StreamEvent\n * Returns array since one chunk may produce multiple events\n */\nexport function transformStreamEvent(\n chunk: OpenAICompletionsStreamChunk,\n state: CompletionsStreamState\n): StreamEvent[] {\n const events: StreamEvent[] = [];\n\n // Update state with basic info\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 // Process choices\n const choice = chunk.choices[0];\n if (choice) {\n // Text delta\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 // Tool call deltas\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 // Finish reason\n if (choice.finish_reason) {\n state.finishReason = choice.finish_reason;\n events.push({ type: 'message_stop', index: 0, delta: {} });\n }\n }\n\n // Usage info (usually comes at the end with stream_options.include_usage)\n if (chunk.usage) {\n state.inputTokens = chunk.usage.prompt_tokens;\n state.outputTokens = chunk.usage.completion_tokens;\n }\n\n return events;\n}\n\n/**\n * Build LLMResponse from accumulated stream state\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 to parse as JSON for structured output (native JSON mode)\n try {\n structuredData = JSON.parse(state.text);\n } catch {\n // Not valid JSON - that's fine, might not be structured output\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 };\n\n // Map finish reason to stop reason\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","import 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\nconst OPENAI_API_URL = 'https://api.openai.com/v1/chat/completions';\n\n/**\n * OpenAI API capabilities\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 * Create OpenAI Chat Completions LLM handler\n */\nexport function createCompletionsLLMHandler(): LLMHandler<OpenAICompletionsParams> {\n // Provider reference injected by createProvider() or OpenAI's custom factory\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 response = await doFetch(\n baseUrl,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\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 response = await doStreamFetch(\n baseUrl,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\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","import 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 * Transform UPP request to OpenAI Responses API format\n *\n * Params are spread directly to allow pass-through of any OpenAI API fields,\n * even those not explicitly defined in our type. This enables developers to\n * use new API features without waiting for library updates.\n */\nexport function transformRequest(\n request: LLMRequest<OpenAIResponsesParams>,\n modelId: string\n): OpenAIResponsesRequest {\n const params = request.params ?? ({} as OpenAIResponsesParams);\n\n // Extract built-in tools from params before spreading\n const builtInTools = params.tools as OpenAIResponsesToolUnion[] | undefined;\n const { tools: _paramsTools, ...restParams } = params;\n\n // Spread params to pass through all fields, then set required fields\n const openaiRequest: OpenAIResponsesRequest = {\n ...restParams,\n model: modelId,\n input: transformInputItems(request.messages, request.system),\n };\n\n // Merge tools: UPP function tools from request + built-in tools from params\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 // Structured output via text.format (overrides params.text if set)\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 * Transform messages to Responses API input items\n */\nfunction transformInputItems(\n messages: Message[],\n system?: string\n): OpenAIResponsesInputItem[] | string {\n const result: OpenAIResponsesInputItem[] = [];\n\n if (system) {\n result.push({\n type: 'message',\n role: 'system',\n content: system,\n });\n }\n\n for (const message of messages) {\n const items = transformMessage(message);\n result.push(...items);\n }\n\n // If there's only one user message with simple text, return as string\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 * Filter to only valid content blocks with a type property\n */\nfunction filterValidContent<T extends { type?: string }>(content: T[]): T[] {\n return content.filter((c) => c && typeof c.type === 'string');\n}\n\n/**\n * Transform a UPP Message to OpenAI Responses API input items\n */\nfunction transformMessage(message: Message): OpenAIResponsesInputItem[] {\n if (isUserMessage(message)) {\n const validContent = filterValidContent(message.content);\n // Check if we can use simple string 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 // Add message content - only text parts for assistant messages\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 // Add assistant message if we have text content\n if (contentParts.length > 0) {\n items.push({\n type: 'message',\n role: 'assistant',\n content: contentParts,\n });\n }\n\n // Add function_call items for each tool call (must precede function_call_output)\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 // Tool results are function_call_output items\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 * Transform a content block to Responses API format\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 // Convert bytes to base64\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 * Transform a UPP Tool to Responses API format\n */\nfunction transformTool(tool: Tool): OpenAIResponsesTool {\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 };\n}\n\n/**\n * Transform OpenAI Responses API response to UPP LLMResponse\n */\nexport function transformResponse(data: OpenAIResponsesResponse): LLMResponse {\n // Extract content and tool calls from output items\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 // Try to parse as JSON for structured output (native JSON mode)\n if (structuredData === undefined) {\n try {\n structuredData = JSON.parse(part.text);\n } catch {\n // Not valid JSON - that's fine, might not be structured output\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 };\n\n // Map status to stop reason\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 * State for accumulating streaming response\n */\nexport interface ResponsesStreamState {\n id: string;\n model: string;\n textByIndex: Map<number, string>;\n toolCalls: Map<\n number,\n { itemId?: string; callId?: string; name?: string; arguments: string }\n >;\n images: string[]; // Base64 image data from image_generation_call outputs\n status: string;\n inputTokens: number;\n outputTokens: number;\n hadRefusal: boolean;\n}\n\n/**\n * Create initial stream state\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 hadRefusal: false,\n };\n}\n\n/**\n * Transform OpenAI Responses API stream event to UPP StreamEvent\n * Returns array since one event may produce multiple UPP events\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 }\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 // Accumulate text\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 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 // Accumulate function call arguments\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 // Finalize function call\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 // Error events are handled at the handler level\n break;\n\n default:\n // Ignore other events\n break;\n }\n\n return events;\n}\n\n/**\n * Build LLMResponse from accumulated stream state\n */\nexport function buildResponseFromState(state: ResponsesStreamState): LLMResponse {\n const content: AssistantContent[] = [];\n let structuredData: unknown;\n\n // Combine all text content\n for (const [, text] of state.textByIndex) {\n if (text) {\n content.push({ type: 'text', text });\n // Try to parse as JSON for structured output (native JSON mode)\n if (structuredData === undefined) {\n try {\n structuredData = JSON.parse(text);\n } catch {\n // Not valid JSON - that's fine, might not be structured output\n }\n }\n }\n }\n\n // Add any generated images\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 // Store response_id for multi-turn tool calling\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 };\n\n // Map status to stop reason\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","import 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\nconst OPENAI_RESPONSES_API_URL = 'https://api.openai.com/v1/responses';\n\n/**\n * OpenAI API capabilities\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 * Create OpenAI Responses API LLM handler\n */\nexport function createResponsesLLMHandler(): LLMHandler<OpenAIResponsesParams> {\n // Provider reference injected by createProvider() or OpenAI's custom factory\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 response = await doFetch(\n baseUrl,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\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 response = await doStreamFetch(\n baseUrl,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\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// Audio Configuration Types\n// ============================================\n\n/**\n * Audio output configuration for Chat Completions\n */\nexport interface OpenAIAudioConfig {\n /** Audio format */\n format: 'wav' | 'aac' | 'mp3' | 'flac' | 'opus' | 'pcm16';\n /** Voice 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 (Responses API format)\n * Fields are at the same level as type\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 (Chat Completions API format)\n * Fields are nested under 'approximate' object\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 options for Chat Completions API\n * Use with gpt-5-search-api-* models\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 * OpenAI Chat Completions API parameters\n * These are passed through to the /v1/chat/completions endpoint\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 * Prompt template reference for Responses API\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 * Conversation reference for Responses API\n * Items from this conversation are prepended to input_items\n */\nexport interface OpenAIConversation {\n /** Conversation ID */\n id: string;\n}\n\n/**\n * OpenAI Responses API parameters\n * These are passed through to the /v1/responses endpoint\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 * API mode for OpenAI provider\n */\nexport type OpenAIAPIMode = 'responses' | 'completions';\n\n/**\n * Model options when creating a 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 */\nexport interface OpenAIModelReference {\n modelId: string;\n options?: OpenAIModelOptions;\n}\n\n/**\n * OpenAI provider configuration\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 * Chat Completions API request body\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 * Chat Completions message format\n */\nexport type OpenAICompletionsMessage =\n | OpenAISystemMessage\n | OpenAIUserMessage\n | OpenAIAssistantMessage\n | OpenAIToolMessage;\n\nexport interface OpenAISystemMessage {\n role: 'system' | 'developer';\n content: string;\n name?: string;\n}\n\nexport interface OpenAIUserMessage {\n role: 'user';\n content: string | OpenAIUserContent[];\n name?: string;\n}\n\nexport interface OpenAIAssistantMessage {\n role: 'assistant';\n content?: string | null;\n name?: string;\n tool_calls?: OpenAIToolCall[];\n refusal?: string | null;\n}\n\nexport interface OpenAIToolMessage {\n role: 'tool';\n content: string;\n tool_call_id: string;\n}\n\n/**\n * User content types\n */\nexport type OpenAIUserContent = OpenAITextContent | OpenAIImageContent;\n\nexport interface OpenAITextContent {\n type: 'text';\n text: string;\n}\n\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 format\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 Chat Completions\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\n */\nexport type OpenAIToolChoice =\n | 'none'\n | 'auto'\n | 'required'\n | { type: 'function'; function: { name: string } };\n\n/**\n * Response format\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 * Chat Completions response format\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\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\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\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 * Chat Completions streaming event types\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\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\nexport interface OpenAICompletionsStreamDelta {\n role?: 'assistant';\n content?: string | null;\n tool_calls?: OpenAIStreamToolCall[];\n refusal?: string | null;\n}\n\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 * Responses API request body\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 * Responses API input item\n */\nexport type OpenAIResponsesInputItem =\n | OpenAIResponsesSystemItem\n | OpenAIResponsesUserItem\n | OpenAIResponsesAssistantItem\n | OpenAIResponsesFunctionCallInputItem\n | OpenAIResponsesToolResultItem;\n\nexport interface OpenAIResponsesSystemItem {\n type: 'message';\n role: 'system' | 'developer';\n content: string | OpenAIResponsesContentPart[];\n}\n\nexport interface OpenAIResponsesUserItem {\n type: 'message';\n role: 'user';\n content: string | OpenAIResponsesContentPart[];\n}\n\nexport interface OpenAIResponsesAssistantItem {\n type: 'message';\n role: 'assistant';\n content: string | OpenAIResponsesContentPart[];\n}\n\nexport interface OpenAIResponsesFunctionCallInputItem {\n type: 'function_call';\n id: string;\n call_id: string;\n name: string;\n arguments: string;\n}\n\nexport interface OpenAIResponsesToolResultItem {\n type: 'function_call_output';\n call_id: string;\n output: string;\n}\n\n/**\n * Content parts for Responses API\n */\nexport type OpenAIResponsesContentPart =\n | OpenAIResponsesTextPart\n | OpenAIResponsesImagePart\n | OpenAIResponsesFunctionCallPart;\n\nexport interface OpenAIResponsesTextPart {\n type: 'input_text' | 'output_text';\n text: string;\n}\n\nexport interface OpenAIResponsesImagePart {\n type: 'input_image';\n image_url?: string;\n image?: string; // base64\n detail?: 'auto' | 'low' | 'high';\n}\n\nexport interface OpenAIResponsesFunctionCallPart {\n type: 'function_call';\n id: string;\n call_id: string;\n name: string;\n arguments: string;\n}\n\n/**\n * Tool definition for Responses API\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 for Responses API\n */\nexport type OpenAIResponsesToolChoice =\n | 'none'\n | 'auto'\n | 'required'\n | { type: 'function'; name: string };\n\n/**\n * Text configuration for structured output\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 * Responses API response format\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\nexport type OpenAIResponsesOutputItem =\n | OpenAIResponsesMessageOutput\n | OpenAIResponsesFunctionCallOutput\n | OpenAIResponsesImageGenerationOutput\n | OpenAIResponsesWebSearchOutput;\n\nexport interface OpenAIResponsesMessageOutput {\n type: 'message';\n id: string;\n role: 'assistant';\n content: OpenAIResponsesOutputContent[];\n status: 'completed' | 'in_progress';\n}\n\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\nexport interface OpenAIResponsesImageGenerationOutput {\n type: 'image_generation_call';\n id: string;\n result?: string;\n status: 'completed' | 'in_progress';\n}\n\nexport interface OpenAIResponsesWebSearchOutput {\n type: 'web_search_call';\n id: string;\n status: 'completed' | 'in_progress';\n}\n\nexport type OpenAIResponsesOutputContent =\n | { type: 'output_text'; text: string; annotations?: unknown[] }\n | { type: 'refusal'; refusal: string };\n\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 * Responses API streaming event types\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 * Helper to create a web search tool\n * Note: Configuration options are passed at the top level, not nested\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 * Helper to create a file search tool\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 * Helper to create a code interpreter tool\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 * Helper to create a computer tool\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 * Helper to create an image generation tool\n * Note: Configuration options are passed at the top level, not nested\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 * Helper to create an MCP tool\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 for tool helper constructors\n */\nexport const tools = {\n webSearch: webSearchTool,\n fileSearch: fileSearchTool,\n codeInterpreter: codeInterpreterTool,\n computer: computerTool,\n imageGeneration: imageGenerationTool,\n mcp: mcpTool,\n};\n","import 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, OpenAIConfig } from './types.ts';\n\n/** Union type for modalities interface */\ntype OpenAILLMParamsUnion = OpenAICompletionsParams | OpenAIResponsesParams;\n\n/**\n * OpenAI provider options\n */\nexport interface OpenAIProviderOptions {\n /**\n * Which API to use:\n * - 'responses': Modern Responses API (default, recommended)\n * - 'completions': Legacy Chat Completions API\n */\n api?: 'responses' | 'completions';\n}\n\n/**\n * OpenAI provider with configurable API mode\n *\n * @example\n * // Using the modern Responses API (default)\n * const model = openai('gpt-4o');\n *\n * @example\n * // Using the legacy Chat Completions API\n * const model = openai('gpt-4o', { api: 'completions' });\n *\n * @example\n * // Explicit Responses API\n * const model = openai('gpt-4o', { api: 'responses' });\n */\nexport interface OpenAIProvider extends Provider<OpenAIProviderOptions> {\n /**\n * Create a model reference\n * @param modelId - The model identifier (e.g., 'gpt-4o', 'gpt-4-turbo', 'o1-preview')\n * @param options - Provider options including API selection\n */\n (modelId: string, options?: OpenAIProviderOptions): ModelReference<OpenAIProviderOptions>;\n\n /** Provider name */\n readonly name: 'openai';\n\n /** Provider version */\n readonly version: string;\n\n /** Supported modalities */\n readonly modalities: {\n llm: LLMHandler<OpenAILLMParamsUnion>;\n };\n}\n\n/**\n * Create the OpenAI provider\n */\nfunction createOpenAIProvider(): OpenAIProvider {\n // Track which API mode is currently active for the modalities\n let currentApiMode: 'responses' | 'completions' = 'responses';\n\n // Create handlers eagerly so we can inject provider reference\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 // Create a dynamic modalities object that returns the correct handler\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 // Define properties\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 // Inject provider reference into both handlers (spec compliance)\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 * OpenAI provider\n *\n * Supports both the modern Responses API (default) and legacy Chat Completions API.\n *\n * @example\n * ```ts\n * import { openai } from './providers/openai';\n * import { llm } from './core/llm';\n *\n * // Using Responses API (default, modern, recommended)\n * const model = llm({\n * model: openai('gpt-4o'),\n * params: { max_tokens: 1000 }\n * });\n *\n * // Using Chat Completions API (legacy)\n * const legacyModel = llm({\n * model: openai('gpt-4o', { api: 'completions' }),\n * params: { max_tokens: 1000 }\n * });\n *\n * // Generate\n * const turn = await model.generate('Hello!');\n * console.log(turn.response.text);\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"],"mappings":"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","names":["transformRequest","transformTool","transformMessage","filterValidContent","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 response = await doFetch(\n baseUrl,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\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 response = await doStreamFetch(\n baseUrl,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\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 response = await doFetch(\n baseUrl,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\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 response = await doStreamFetch(\n baseUrl,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\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 * @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"],"mappings":"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","names":["transformRequest","transformTool","normalizeSystem","transformMessage","filterValidContent","extractToolOptions","transformResponse","createStreamState","transformStreamEvent","buildResponseFromState","OPENAI_CAPABILITIES","transformRequest","transformResponse","createStreamState","transformStreamEvent","buildResponseFromState"]}