@providerprotocol/ai 0.0.8 → 0.0.9

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.
@@ -817,6 +817,7 @@ function createStreamState2() {
817
817
  model: "",
818
818
  textByIndex: /* @__PURE__ */ new Map(),
819
819
  toolCalls: /* @__PURE__ */ new Map(),
820
+ images: [],
820
821
  status: "in_progress",
821
822
  inputTokens: 0,
822
823
  outputTokens: 0,
@@ -879,6 +880,11 @@ function transformStreamEvent2(event, state) {
879
880
  existing.arguments = functionCall.arguments;
880
881
  }
881
882
  state.toolCalls.set(event.output_index, existing);
883
+ } else if (event.item.type === "image_generation_call") {
884
+ const imageGen = event.item;
885
+ if (imageGen.result) {
886
+ state.images.push(imageGen.result);
887
+ }
882
888
  }
883
889
  events.push({
884
890
  type: "content_block_stop",
@@ -961,11 +967,11 @@ function transformStreamEvent2(event, state) {
961
967
  return events;
962
968
  }
963
969
  function buildResponseFromState2(state) {
964
- const textContent = [];
970
+ const content = [];
965
971
  let structuredData;
966
972
  for (const [, text] of state.textByIndex) {
967
973
  if (text) {
968
- textContent.push({ type: "text", text });
974
+ content.push({ type: "text", text });
969
975
  if (structuredData === void 0) {
970
976
  try {
971
977
  structuredData = JSON.parse(text);
@@ -974,6 +980,13 @@ function buildResponseFromState2(state) {
974
980
  }
975
981
  }
976
982
  }
983
+ for (const imageData of state.images) {
984
+ content.push({
985
+ type: "image",
986
+ mimeType: "image/png",
987
+ source: { type: "base64", data: imageData }
988
+ });
989
+ }
977
990
  const toolCalls = [];
978
991
  const functionCallItems = [];
979
992
  for (const [, toolCall] of state.toolCalls) {
@@ -1002,7 +1015,7 @@ function buildResponseFromState2(state) {
1002
1015
  }
1003
1016
  }
1004
1017
  const message = new AssistantMessage(
1005
- textContent,
1018
+ content,
1006
1019
  toolCalls.length > 0 ? toolCalls : void 0,
1007
1020
  {
1008
1021
  id: state.id,
@@ -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 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 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 }\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 textContent: TextBlock[] = [];\n let structuredData: unknown;\n\n // Combine all text content\n for (const [, text] of state.textByIndex) {\n if (text) {\n textContent.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 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 textContent,\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\n * Requires type: 'approximate' with location fields at the same level\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 * Web search options for Chat Completions API\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?: OpenAIWebSearchUserLocation | 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 // 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":["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\n * Requires type: 'approximate' with location fields at the same level\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 * Web search options for Chat Completions API\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?: OpenAIWebSearchUserLocation | 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 // 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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@providerprotocol/ai",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
4
  "description": "UPP: Unified Provider Protocol for AI inference",
5
5
  "license": "MIT",
6
6
  "homepage": "https://providerprotocol.org",
@@ -404,6 +404,7 @@ export interface ResponsesStreamState {
404
404
  number,
405
405
  { itemId?: string; callId?: string; name?: string; arguments: string }
406
406
  >;
407
+ images: string[]; // Base64 image data from image_generation_call outputs
407
408
  status: string;
408
409
  inputTokens: number;
409
410
  outputTokens: number;
@@ -419,6 +420,7 @@ export function createStreamState(): ResponsesStreamState {
419
420
  model: '',
420
421
  textByIndex: new Map(),
421
422
  toolCalls: new Map(),
423
+ images: [],
422
424
  status: 'in_progress',
423
425
  inputTokens: 0,
424
426
  outputTokens: 0,
@@ -495,6 +497,11 @@ export function transformStreamEvent(
495
497
  existing.arguments = functionCall.arguments;
496
498
  }
497
499
  state.toolCalls.set(event.output_index, existing);
500
+ } else if (event.item.type === 'image_generation_call') {
501
+ const imageGen = event.item as OpenAIResponsesImageGenerationOutput;
502
+ if (imageGen.result) {
503
+ state.images.push(imageGen.result);
504
+ }
498
505
  }
499
506
  events.push({
500
507
  type: 'content_block_stop',
@@ -595,13 +602,13 @@ export function transformStreamEvent(
595
602
  * Build LLMResponse from accumulated stream state
596
603
  */
597
604
  export function buildResponseFromState(state: ResponsesStreamState): LLMResponse {
598
- const textContent: TextBlock[] = [];
605
+ const content: AssistantContent[] = [];
599
606
  let structuredData: unknown;
600
607
 
601
608
  // Combine all text content
602
609
  for (const [, text] of state.textByIndex) {
603
610
  if (text) {
604
- textContent.push({ type: 'text', text });
611
+ content.push({ type: 'text', text });
605
612
  // Try to parse as JSON for structured output (native JSON mode)
606
613
  if (structuredData === undefined) {
607
614
  try {
@@ -613,6 +620,15 @@ export function buildResponseFromState(state: ResponsesStreamState): LLMResponse
613
620
  }
614
621
  }
615
622
 
623
+ // Add any generated images
624
+ for (const imageData of state.images) {
625
+ content.push({
626
+ type: 'image',
627
+ mimeType: 'image/png',
628
+ source: { type: 'base64', data: imageData },
629
+ } as ImageBlock);
630
+ }
631
+
616
632
  const toolCalls: ToolCall[] = [];
617
633
  const functionCallItems: Array<{
618
634
  id: string;
@@ -649,7 +665,7 @@ export function buildResponseFromState(state: ResponsesStreamState): LLMResponse
649
665
  }
650
666
 
651
667
  const message = new AssistantMessage(
652
- textContent,
668
+ content,
653
669
  toolCalls.length > 0 ? toolCalls : undefined,
654
670
  {
655
671
  id: state.id,