@providerprotocol/ai 0.0.39 → 0.0.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +269 -34
- package/dist/anthropic/index.d.ts +3 -3
- package/dist/anthropic/index.js +7 -5
- package/dist/anthropic/index.js.map +1 -1
- package/dist/cerebras/index.d.ts +3 -3
- package/dist/cerebras/index.js +7 -5
- package/dist/cerebras/index.js.map +1 -1
- package/dist/{chunk-WU4U6IHF.js → chunk-6QCV4WXF.js} +4 -13
- package/dist/chunk-6QCV4WXF.js.map +1 -0
- package/dist/{chunk-5XPRVUOK.js → chunk-AC3VHSZJ.js} +2 -2
- package/dist/{chunk-5XPRVUOK.js.map → chunk-AC3VHSZJ.js.map} +1 -1
- package/dist/{chunk-ZDYEDI2A.js → chunk-CWGTARDE.js} +2 -2
- package/dist/{chunk-KNBODIQU.js → chunk-DI47UY2H.js} +2 -2
- package/dist/{chunk-KNBODIQU.js.map → chunk-DI47UY2H.js.map} +1 -1
- package/dist/{chunk-IDZR4ROP.js → chunk-EHR3LIPS.js} +2 -2
- package/dist/{chunk-IDZR4ROP.js.map → chunk-EHR3LIPS.js.map} +1 -1
- package/dist/chunk-EY2LLDGY.js +94 -0
- package/dist/chunk-EY2LLDGY.js.map +1 -0
- package/dist/{chunk-MJI74VEJ.js → chunk-F5ENANMJ.js} +18 -2
- package/dist/chunk-F5ENANMJ.js.map +1 -0
- package/dist/chunk-IKJH5ZSJ.js +1 -0
- package/dist/chunk-IKJH5ZSJ.js.map +1 -0
- package/dist/{chunk-IIMTP3XC.js → chunk-KBI45OXI.js} +2 -2
- package/dist/{chunk-SAMIK4WZ.js → chunk-KVUOTFYZ.js} +2 -2
- package/dist/{chunk-U6M3MXNI.js → chunk-L6QWKFGE.js} +3 -2
- package/dist/chunk-L6QWKFGE.js.map +1 -0
- package/dist/{chunk-RDC5GYST.js → chunk-N4LAFGLX.js} +7 -7
- package/dist/{chunk-ZKNPQBIE.js → chunk-R3T2IYOU.js} +5 -3
- package/dist/{chunk-ZKNPQBIE.js.map → chunk-R3T2IYOU.js.map} +1 -1
- package/dist/chunk-U2G5PHHL.js +25 -0
- package/dist/chunk-U2G5PHHL.js.map +1 -0
- package/dist/{chunk-SBGZJVTJ.js → chunk-VQZPADW6.js} +100 -33
- package/dist/chunk-VQZPADW6.js.map +1 -0
- package/dist/{chunk-O32SBS6S.js → chunk-XTWBAL42.js} +2 -2
- package/dist/{chunk-O32SBS6S.js.map → chunk-XTWBAL42.js.map} +1 -1
- package/dist/{chunk-WNB5PSY6.js → chunk-ZMESKGUY.js} +2 -2
- package/dist/{chunk-7ULSRWDH.js → chunk-ZSZVWLGE.js} +2 -2
- package/dist/{embedding-iNQCeXfk.d.ts → embedding-ts1npsDg.d.ts} +1 -1
- package/dist/google/index.d.ts +38 -4
- package/dist/google/index.js +5 -4
- package/dist/google/index.js.map +1 -1
- package/dist/groq/index.d.ts +3 -3
- package/dist/groq/index.js +7 -5
- package/dist/groq/index.js.map +1 -1
- package/dist/http/index.d.ts +5 -5
- package/dist/http/index.js +19 -22
- package/dist/{image-stream-ARno6XlS.d.ts → image-stream-BPml2YZZ.d.ts} +1 -1
- package/dist/index.d.ts +8 -8
- package/dist/index.js +306 -112
- package/dist/index.js.map +1 -1
- package/dist/{llm-CZqlijjK.d.ts → llm-BWLaTzzY.d.ts} +75 -29
- package/dist/middleware/logging/index.d.ts +3 -3
- package/dist/middleware/logging/index.js +3 -0
- package/dist/middleware/logging/index.js.map +1 -1
- package/dist/middleware/parsed-object/index.d.ts +3 -3
- package/dist/middleware/parsed-object/index.js +5 -1
- package/dist/middleware/parsed-object/index.js.map +1 -1
- package/dist/middleware/persistence/index.d.ts +3 -3
- package/dist/middleware/persistence/index.js +3 -2
- package/dist/middleware/persistence/index.js.map +1 -1
- package/dist/middleware/pipeline/index.d.ts +195 -0
- package/dist/middleware/pipeline/index.js +61 -0
- package/dist/middleware/pipeline/index.js.map +1 -0
- package/dist/middleware/pubsub/index.d.ts +13 -11
- package/dist/middleware/pubsub/index.js +31 -5
- package/dist/middleware/pubsub/index.js.map +1 -1
- package/dist/middleware/pubsub/server/express/index.d.ts +3 -3
- package/dist/middleware/pubsub/server/express/index.js +2 -2
- package/dist/middleware/pubsub/server/fastify/index.d.ts +3 -3
- package/dist/middleware/pubsub/server/fastify/index.js +2 -2
- package/dist/middleware/pubsub/server/h3/index.d.ts +3 -3
- package/dist/middleware/pubsub/server/h3/index.js +2 -2
- package/dist/middleware/pubsub/server/index.d.ts +50 -9
- package/dist/middleware/pubsub/server/index.js +5 -5
- package/dist/middleware/pubsub/server/index.js.map +1 -1
- package/dist/middleware/pubsub/server/webapi/index.d.ts +3 -3
- package/dist/middleware/pubsub/server/webapi/index.js +2 -2
- package/dist/moonshot/index.d.ts +3 -3
- package/dist/moonshot/index.js +7 -5
- package/dist/moonshot/index.js.map +1 -1
- package/dist/ollama/index.d.ts +24 -4
- package/dist/ollama/index.js +5 -4
- package/dist/ollama/index.js.map +1 -1
- package/dist/openai/index.d.ts +65 -4
- package/dist/openai/index.js +7 -5
- package/dist/openai/index.js.map +1 -1
- package/dist/openrouter/index.d.ts +4 -4
- package/dist/openrouter/index.js +7 -5
- package/dist/openrouter/index.js.map +1 -1
- package/dist/proxy/index.d.ts +5 -5
- package/dist/proxy/index.js +16 -15
- package/dist/proxy/index.js.map +1 -1
- package/dist/proxy/server/express/index.d.ts +8 -9
- package/dist/proxy/server/express/index.js +4 -3
- package/dist/proxy/server/fastify/index.d.ts +8 -9
- package/dist/proxy/server/fastify/index.js +4 -3
- package/dist/proxy/server/h3/index.d.ts +8 -9
- package/dist/proxy/server/h3/index.js +4 -3
- package/dist/proxy/server/index.d.ts +5 -5
- package/dist/proxy/server/index.js +14 -13
- package/dist/proxy/server/webapi/index.d.ts +8 -9
- package/dist/proxy/server/webapi/index.js +4 -3
- package/dist/responses/index.d.ts +3 -3
- package/dist/responses/index.js +7 -5
- package/dist/responses/index.js.map +1 -1
- package/dist/retry-DVfdPLIB.d.ts +322 -0
- package/dist/{stream-DVVUIKpz.d.ts → stream-bBd_4Ipu.d.ts} +27 -4
- package/dist/{tool-D22EhP5F.d.ts → tool-BmAfKNBq.d.ts} +1 -1
- package/dist/{types-CyXF0J7C.d.ts → types-nTwlpyJE.d.ts} +13 -1
- package/dist/utils/index.d.ts +66 -2
- package/dist/utils/index.js +13 -0
- package/dist/xai/index.d.ts +3 -3
- package/dist/xai/index.js +7 -5
- package/dist/xai/index.js.map +1 -1
- package/package.json +6 -1
- package/dist/chunk-ARVM24K2.js +0 -128
- package/dist/chunk-ARVM24K2.js.map +0 -1
- package/dist/chunk-MJI74VEJ.js.map +0 -1
- package/dist/chunk-SBGZJVTJ.js.map +0 -1
- package/dist/chunk-U6M3MXNI.js.map +0 -1
- package/dist/chunk-WU4U6IHF.js.map +0 -1
- package/dist/chunk-Y5H7C5J4.js +0 -263
- package/dist/chunk-Y5H7C5J4.js.map +0 -1
- package/dist/retry-C1eJbEMV.d.ts +0 -531
- /package/dist/{chunk-ZDYEDI2A.js.map → chunk-CWGTARDE.js.map} +0 -0
- /package/dist/{chunk-IIMTP3XC.js.map → chunk-KBI45OXI.js.map} +0 -0
- /package/dist/{chunk-SAMIK4WZ.js.map → chunk-KVUOTFYZ.js.map} +0 -0
- /package/dist/{chunk-RDC5GYST.js.map → chunk-N4LAFGLX.js.map} +0 -0
- /package/dist/{chunk-WNB5PSY6.js.map → chunk-ZMESKGUY.js.map} +0 -0
- /package/dist/{chunk-7ULSRWDH.js.map → chunk-ZSZVWLGE.js.map} +0 -0
package/dist/responses/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from "../chunk-TUTYMOBL.js";
|
|
7
7
|
import {
|
|
8
8
|
resolveApiKey
|
|
9
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-EY2LLDGY.js";
|
|
10
10
|
import {
|
|
11
11
|
createProvider
|
|
12
12
|
} from "../chunk-JA3UZALR.js";
|
|
@@ -14,18 +14,20 @@ import {
|
|
|
14
14
|
doFetch,
|
|
15
15
|
doStreamFetch,
|
|
16
16
|
normalizeHttpError
|
|
17
|
-
} from "../chunk-
|
|
17
|
+
} from "../chunk-VQZPADW6.js";
|
|
18
18
|
import {
|
|
19
19
|
StreamEventType,
|
|
20
20
|
objectDelta
|
|
21
|
-
} from "../chunk-
|
|
21
|
+
} from "../chunk-F5ENANMJ.js";
|
|
22
22
|
import {
|
|
23
23
|
AssistantMessage,
|
|
24
|
-
generateId,
|
|
25
24
|
isAssistantMessage,
|
|
26
25
|
isToolResultMessage,
|
|
27
26
|
isUserMessage
|
|
28
|
-
} from "../chunk-
|
|
27
|
+
} from "../chunk-6QCV4WXF.js";
|
|
28
|
+
import {
|
|
29
|
+
generateId
|
|
30
|
+
} from "../chunk-U2G5PHHL.js";
|
|
29
31
|
import {
|
|
30
32
|
toError
|
|
31
33
|
} from "../chunk-GIDT7C6I.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/providers/responses/transform.ts","../../src/providers/responses/llm.ts","../../src/providers/responses/index.ts"],"sourcesContent":["/**\n * @fileoverview OpenResponses API Message Transformers\n *\n * This module provides transformation functions for converting between the\n * Universal Provider Protocol (UPP) message format and the OpenResponses API\n * format. The OpenResponses spec uses items as atomic units with defined\n * state machines and streaming updates.\n *\n * Key concepts:\n * - Uses `input` array of items instead of `messages`\n * - Function calls are separate input items\n * - Tool results use `function_call_output` items\n * - Supports multimodal inputs: text, images, files (documents), video\n *\n * @module providers/responses/transform\n */\n\nimport type { LLMRequest, LLMResponse } from '../../types/llm.ts';\nimport type { Message } from '../../types/messages.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport { StreamEventType } from '../../types/stream.ts';\nimport type { Tool, ToolCall } from '../../types/tool.ts';\nimport type { TokenUsage } from '../../types/turn.ts';\nimport type {\n ContentBlock,\n TextBlock,\n ImageBlock,\n DocumentBlock,\n VideoBlock,\n AudioBlock,\n AssistantContent,\n} from '../../types/content.ts';\nimport {\n AssistantMessage,\n isUserMessage,\n isAssistantMessage,\n isToolResultMessage,\n} from '../../types/messages.ts';\nimport { UPPError, ErrorCode, ModalityType } from '../../types/errors.ts';\nimport { generateId } from '../../utils/id.ts';\nimport type {\n ResponsesParams,\n ResponsesRequest,\n ResponsesInputItem,\n ResponsesContentPart,\n ResponsesFunctionTool,\n ResponsesToolUnion,\n ResponsesResponse,\n ResponsesStreamEvent,\n ResponsesReasoningOutput,\n ResponsesFunctionCallOutput,\n} from './types.ts';\n\n/**\n * Normalizes system prompt to string.\n */\nfunction normalizeSystem(system: string | unknown[] | undefined): string | undefined {\n if (system === undefined || system === null) return undefined;\n if (typeof system === 'string') return system;\n if (!Array.isArray(system)) {\n throw new UPPError(\n 'System prompt must be a string or an array of text blocks',\n ErrorCode.InvalidRequest,\n 'responses',\n ModalityType.LLM\n );\n }\n\n const texts: string[] = [];\n for (const block of system) {\n if (!block || typeof block !== 'object' || !('text' in block)) {\n throw new UPPError(\n 'System prompt array must contain objects with a text field',\n ErrorCode.InvalidRequest,\n 'responses',\n ModalityType.LLM\n );\n }\n const textValue = (block as { text?: unknown }).text;\n if (typeof textValue !== 'string') {\n throw new UPPError(\n 'System prompt text must be a string',\n ErrorCode.InvalidRequest,\n 'responses',\n ModalityType.LLM\n );\n }\n if (textValue.length > 0) {\n texts.push(textValue);\n }\n }\n\n return texts.length > 0 ? texts.join('\\n\\n') : undefined;\n}\n\n/**\n * Filters content blocks to only include those with a valid 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 * Transforms a UPP content block to OpenResponses content part format.\n * Supports text, image, document, video, and audio content types.\n */\nfunction transformContentPart(block: ContentBlock): ResponsesContentPart {\n switch (block.type) {\n case 'text':\n return { type: 'input_text', text: block.text };\n\n case 'image': {\n const imageBlock = block as ImageBlock;\n if (imageBlock.source.type === 'base64') {\n return {\n type: 'input_image',\n image_url: `data:${imageBlock.mimeType};base64,${imageBlock.source.data}`,\n };\n }\n\n if (imageBlock.source.type === 'url') {\n return {\n type: 'input_image',\n image_url: imageBlock.source.url,\n };\n }\n\n if (imageBlock.source.type === 'bytes') {\n const base64 = Buffer.from(imageBlock.source.data).toString('base64');\n return {\n type: 'input_image',\n image_url: `data:${imageBlock.mimeType};base64,${base64}`,\n };\n }\n\n throw new UPPError(\n 'Unknown image source type',\n ErrorCode.InvalidRequest,\n 'responses',\n ModalityType.LLM\n );\n }\n\n case 'document': {\n const documentBlock = block as DocumentBlock;\n\n if (documentBlock.source.type === 'base64') {\n return {\n type: 'input_file',\n filename: documentBlock.title ?? 'document',\n file_data: `data:${documentBlock.mimeType};base64,${documentBlock.source.data}`,\n };\n }\n\n if (documentBlock.source.type === 'url') {\n return {\n type: 'input_file',\n file_url: documentBlock.source.url,\n };\n }\n\n if (documentBlock.source.type === 'text') {\n const base64 = Buffer.from(documentBlock.source.data).toString('base64');\n return {\n type: 'input_file',\n filename: documentBlock.title ?? 'document.txt',\n file_data: `data:text/plain;base64,${base64}`,\n };\n }\n\n throw new UPPError(\n 'Unknown document source type',\n ErrorCode.InvalidRequest,\n 'responses',\n ModalityType.LLM\n );\n }\n\n case 'video': {\n const videoBlock = block as VideoBlock;\n const base64 = Buffer.from(videoBlock.data).toString('base64');\n return {\n type: 'input_video' as ResponsesContentPart['type'],\n video: `data:${videoBlock.mimeType};base64,${base64}`,\n } as ResponsesContentPart;\n }\n\n case 'audio': {\n const audioBlock = block as AudioBlock;\n const base64 = Buffer.from(audioBlock.data).toString('base64');\n return {\n type: 'input_file',\n filename: 'audio',\n file_data: `data:${audioBlock.mimeType};base64,${base64}`,\n };\n }\n\n default:\n throw new UPPError(\n `Unsupported content type: ${block.type}`,\n ErrorCode.InvalidRequest,\n 'responses',\n ModalityType.LLM\n );\n }\n}\n\n/**\n * Transforms a single UPP message to OpenResponses input items.\n */\nfunction transformMessage(message: Message): ResponsesInputItem[] {\n if (isUserMessage(message)) {\n const validContent = filterValidContent(message.content);\n if (validContent.length === 1 && validContent[0]?.type === 'text') {\n return [\n {\n type: 'message',\n role: 'user',\n content: (validContent[0] as TextBlock).text,\n },\n ];\n }\n return [\n {\n type: 'message',\n role: 'user',\n content: validContent.map(transformContentPart),\n },\n ];\n }\n\n if (isAssistantMessage(message)) {\n const validContent = filterValidContent(message.content);\n const items: ResponsesInputItem[] = [];\n\n const contentParts: ResponsesContentPart[] = validContent\n .filter((c): c is TextBlock => c.type === 'text')\n .map((c): ResponsesContentPart => ({\n type: 'output_text',\n text: c.text,\n }));\n\n if (contentParts.length > 0) {\n items.push({\n type: 'message',\n role: 'assistant',\n content: contentParts,\n });\n }\n\n const responsesMeta = message.metadata?.responses as\n | {\n functionCallItems?: Array<{ id: string; call_id: string; name: string; arguments: string }>;\n reasoningEncryptedContent?: string;\n }\n | undefined;\n const functionCallItems = responsesMeta?.functionCallItems;\n\n if (responsesMeta?.reasoningEncryptedContent) {\n try {\n const reasoningData = JSON.parse(responsesMeta.reasoningEncryptedContent) as {\n id: string;\n summary: Array<{ type: 'summary_text'; text: string }>;\n encrypted_content?: string;\n };\n items.push({\n type: 'reasoning',\n id: reasoningData.id,\n summary: reasoningData.summary,\n encrypted_content: reasoningData.encrypted_content,\n });\n } catch {\n // Invalid JSON - skip reasoning item\n }\n }\n\n if (functionCallItems && functionCallItems.length > 0) {\n for (const fc of functionCallItems) {\n items.push({\n type: 'function_call',\n id: fc.id,\n call_id: fc.call_id,\n name: fc.name,\n arguments: fc.arguments,\n });\n }\n } else if (message.toolCalls && message.toolCalls.length > 0) {\n for (const call of message.toolCalls) {\n items.push({\n type: 'function_call',\n id: `fc_${call.toolCallId}`,\n call_id: call.toolCallId,\n name: call.toolName,\n arguments: JSON.stringify(call.arguments),\n });\n }\n }\n\n return items;\n }\n\n if (isToolResultMessage(message)) {\n return message.results.map((result) => ({\n type: 'function_call_output' as const,\n call_id: result.toolCallId,\n output:\n typeof result.result === 'string'\n ? result.result\n : JSON.stringify(result.result),\n }));\n }\n\n return [];\n}\n\n/**\n * Transforms UPP messages to OpenResponses input items.\n */\nfunction transformInputItems(\n messages: Message[],\n system?: string | unknown[]\n): ResponsesInputItem[] | string {\n const result: ResponsesInputItem[] = [];\n const normalizedSystem = normalizeSystem(system);\n\n if (normalizedSystem) {\n result.push({\n type: 'message',\n role: 'system',\n content: normalizedSystem,\n });\n }\n\n for (const message of messages) {\n const items = transformMessage(message);\n result.push(...items);\n }\n\n if (result.length === 1 && result[0]?.type === 'message') {\n const item = result[0] as { role?: string; content?: string | unknown[] };\n if (item.role === 'user' && typeof item.content === 'string') {\n return item.content;\n }\n }\n\n return result;\n}\n\n/**\n * Extracts provider-specific options from tool metadata.\n */\nfunction extractToolOptions(tool: Tool): { strict?: boolean } {\n const meta = tool.metadata?.responses as { strict?: boolean } | undefined;\n return { strict: meta?.strict };\n}\n\n/**\n * Transforms a UPP tool definition to OpenResponses function tool format.\n */\nfunction transformTool(tool: Tool): ResponsesFunctionTool {\n const { strict } = extractToolOptions(tool);\n\n return {\n type: 'function',\n name: tool.name,\n description: tool.description,\n parameters: {\n type: 'object',\n properties: tool.parameters.properties,\n required: tool.parameters.required,\n ...(tool.parameters.additionalProperties !== undefined\n ? { additionalProperties: tool.parameters.additionalProperties }\n : {}),\n },\n ...(strict !== undefined ? { strict } : {}),\n };\n}\n\n/**\n * Transforms a UPP LLM request into OpenResponses API format.\n *\n * @param request - The UPP LLM request\n * @param modelId - The model identifier\n * @returns An OpenResponses API request body\n */\nexport function transformRequest(\n request: LLMRequest<ResponsesParams>,\n modelId: string\n): ResponsesRequest {\n const params = request.params ?? ({} as ResponsesParams);\n const { tools: builtInTools, ...restParams } = params;\n\n const responsesRequest: ResponsesRequest = {\n ...restParams,\n model: modelId,\n input: transformInputItems(request.messages, request.system),\n };\n\n const functionTools: ResponsesToolUnion[] = request.tools?.map(transformTool) ?? [];\n const allTools: ResponsesToolUnion[] = [\n ...functionTools,\n ...(builtInTools ?? []),\n ];\n\n if (allTools.length > 0) {\n responsesRequest.tools = allTools;\n }\n\n if (request.structure) {\n const schema: Record<string, unknown> = {\n type: 'object',\n properties: request.structure.properties,\n required: request.structure.required,\n ...(request.structure.additionalProperties !== undefined\n ? { additionalProperties: request.structure.additionalProperties }\n : { additionalProperties: false }),\n };\n if (request.structure.description) {\n schema.description = request.structure.description;\n }\n\n responsesRequest.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 responsesRequest;\n}\n\n/**\n * Transforms an OpenResponses API response to UPP LLMResponse format.\n */\nexport function transformResponse(data: ResponsesResponse): LLMResponse {\n const content: AssistantContent[] = [];\n const toolCalls: ToolCall[] = [];\n const functionCallItems: Array<{\n id: string;\n call_id: string;\n name: string;\n arguments: string;\n }> = [];\n let hadRefusal = false;\n let structuredData: unknown;\n let reasoningEncryptedContent: string | undefined;\n\n for (const item of data.output) {\n if (item.type === 'message') {\n const messageItem = item;\n for (const part of messageItem.content) {\n if (part.type === 'output_text') {\n content.push({ type: 'text', text: part.text });\n if (structuredData === undefined) {\n try {\n structuredData = JSON.parse(part.text);\n } catch {\n // Not JSON - expected for non-structured responses\n }\n }\n } else if (part.type === 'refusal') {\n content.push({ type: 'text', text: part.refusal });\n hadRefusal = true;\n }\n }\n } else if (item.type === 'function_call') {\n const functionCall = item as ResponsesFunctionCallOutput;\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 === 'reasoning') {\n const reasoningItem = item as ResponsesReasoningOutput;\n const reasoningText = reasoningItem.summary\n .filter((s): s is { type: 'summary_text'; text: string } => s.type === 'summary_text')\n .map((s) => s.text)\n .join('');\n if (reasoningText) {\n content.push({ type: 'reasoning', text: reasoningText });\n }\n reasoningEncryptedContent = JSON.stringify({\n id: reasoningItem.id,\n summary: reasoningItem.summary,\n encrypted_content: reasoningItem.encrypted_content,\n });\n }\n }\n\n const responseId = data.id || generateId();\n const message = new AssistantMessage(\n content,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: responseId,\n metadata: {\n responses: {\n model: data.model,\n status: data.status,\n response_id: responseId,\n functionCallItems:\n functionCallItems.length > 0 ? functionCallItems : undefined,\n reasoningEncryptedContent,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: data.usage.input_tokens,\n outputTokens: data.usage.output_tokens,\n totalTokens: data.usage.total_tokens,\n cacheReadTokens: data.usage.input_tokens_details?.cached_tokens ?? 0,\n cacheWriteTokens: 0,\n };\n\n let stopReason = 'end_turn';\n if (data.status === 'completed') {\n stopReason = toolCalls.length > 0 ? 'tool_use' : 'end_turn';\n } else if (data.status === 'incomplete') {\n stopReason = data.incomplete_details?.reason === 'max_output_tokens'\n ? 'max_tokens'\n : 'end_turn';\n } else if (data.status === 'failed') {\n stopReason = 'error';\n }\n if (hadRefusal && stopReason !== 'error') {\n stopReason = 'content_filter';\n }\n\n return {\n message,\n usage,\n stopReason,\n data: structuredData,\n };\n}\n\n// ============================================\n// Streaming State Management\n// ============================================\n\n/**\n * Mutable state for accumulating streaming data.\n */\nexport interface StreamState {\n id: string;\n model: string;\n textByIndex: Map<number, string>;\n reasoningByIndex: Map<number, string>;\n toolCalls: Map<\n number,\n { itemId?: string; callId?: string; name?: string; arguments: string }\n >;\n status: string;\n incompleteReason?: string;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n hadRefusal: boolean;\n reasoningEncryptedContent?: string;\n}\n\n/**\n * Creates a fresh stream state object.\n */\nexport function createStreamState(): StreamState {\n return {\n id: '',\n model: '',\n textByIndex: new Map(),\n reasoningByIndex: new Map(),\n toolCalls: new Map(),\n status: 'in_progress',\n incompleteReason: undefined,\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n hadRefusal: false,\n };\n}\n\n/**\n * Transforms an OpenResponses streaming event into UPP stream events.\n */\nexport function transformStreamEvent(\n event: ResponsesStreamEvent,\n state: StreamState\n): StreamEvent[] {\n const events: StreamEvent[] = [];\n\n const updateFromResponse = (response: ResponsesResponse): void => {\n state.id = response.id || state.id;\n state.model = response.model || state.model;\n state.status = response.status;\n if (response.incomplete_details?.reason) {\n state.incompleteReason = response.incomplete_details.reason;\n } else if (response.status !== 'incomplete') {\n state.incompleteReason = undefined;\n }\n if (response.usage) {\n state.inputTokens = response.usage.input_tokens;\n state.outputTokens = response.usage.output_tokens;\n state.cacheReadTokens = response.usage.input_tokens_details?.cached_tokens ?? 0;\n }\n };\n\n switch (event.type) {\n case 'response.created':\n updateFromResponse(event.response);\n events.push({ type: StreamEventType.MessageStart, index: 0, delta: {} });\n break;\n\n case 'response.queued':\n case 'response.in_progress':\n updateFromResponse(event.response);\n break;\n\n case 'response.completed':\n updateFromResponse(event.response);\n events.push({ type: StreamEventType.MessageStop, index: 0, delta: {} });\n break;\n\n case 'response.failed':\n case 'response.incomplete':\n updateFromResponse(event.response);\n events.push({ type: StreamEventType.MessageStop, 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 ResponsesFunctionCallOutput;\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: StreamEventType.ContentBlockStart,\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 ResponsesFunctionCallOutput;\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 === 'reasoning') {\n const reasoningItem = event.item as ResponsesReasoningOutput;\n state.reasoningEncryptedContent = JSON.stringify({\n id: reasoningItem.id,\n summary: reasoningItem.summary,\n encrypted_content: reasoningItem.encrypted_content,\n });\n }\n events.push({\n type: StreamEventType.ContentBlockStop,\n index: event.output_index,\n delta: {},\n });\n break;\n\n case 'response.output_text.delta': {\n const currentText = state.textByIndex.get(event.output_index) ?? '';\n state.textByIndex.set(event.output_index, currentText + event.delta);\n events.push({\n type: StreamEventType.TextDelta,\n index: event.output_index,\n delta: { text: event.delta },\n });\n break;\n }\n\n case 'response.output_text.done':\n state.textByIndex.set(event.output_index, event.text);\n break;\n\n case 'response.refusal.delta': {\n state.hadRefusal = true;\n const currentRefusal = state.textByIndex.get(event.output_index) ?? '';\n state.textByIndex.set(event.output_index, currentRefusal + event.delta);\n events.push({\n type: StreamEventType.TextDelta,\n index: event.output_index,\n delta: { text: event.delta },\n });\n break;\n }\n\n case 'response.refusal.done':\n state.hadRefusal = true;\n state.textByIndex.set(event.output_index, event.refusal);\n break;\n\n case 'response.function_call_arguments.delta': {\n let toolCall = state.toolCalls.get(event.output_index);\n if (!toolCall) {\n toolCall = { arguments: '' };\n state.toolCalls.set(event.output_index, toolCall);\n }\n if (event.item_id && !toolCall.itemId) {\n toolCall.itemId = event.item_id;\n }\n if (event.call_id && !toolCall.callId) {\n toolCall.callId = event.call_id;\n }\n toolCall.arguments += event.delta;\n events.push({\n type: StreamEventType.ToolCallDelta,\n index: event.output_index,\n delta: {\n toolCallId: toolCall.callId ?? toolCall.itemId ?? '',\n toolName: toolCall.name,\n argumentsJson: event.delta,\n },\n });\n break;\n }\n\n case 'response.function_call_arguments.done': {\n let toolCall = state.toolCalls.get(event.output_index);\n if (!toolCall) {\n toolCall = { arguments: '' };\n state.toolCalls.set(event.output_index, toolCall);\n }\n if (event.item_id) {\n toolCall.itemId = event.item_id;\n }\n if (event.call_id) {\n toolCall.callId = event.call_id;\n }\n toolCall.name = event.name;\n toolCall.arguments = event.arguments;\n break;\n }\n\n case 'response.reasoning_summary_text.delta': {\n const currentReasoning = state.reasoningByIndex.get(event.output_index) ?? '';\n state.reasoningByIndex.set(event.output_index, currentReasoning + event.delta);\n events.push({\n type: StreamEventType.ReasoningDelta,\n index: event.output_index,\n delta: { text: event.delta },\n });\n break;\n }\n\n case 'response.reasoning_summary_text.done':\n state.reasoningByIndex.set(event.output_index, event.text);\n break;\n\n case 'error':\n break;\n\n default:\n break;\n }\n\n return events;\n}\n\n/**\n * Builds a complete LLMResponse from accumulated streaming state.\n */\nexport function buildResponseFromState(state: StreamState): LLMResponse {\n const content: AssistantContent[] = [];\n let structuredData: unknown;\n\n const orderedReasoningEntries = [...state.reasoningByIndex.entries()].sort(\n ([leftIndex], [rightIndex]) => leftIndex - rightIndex\n );\n for (const [, reasoning] of orderedReasoningEntries) {\n if (reasoning) {\n content.push({ type: 'reasoning', text: reasoning });\n }\n }\n\n const orderedTextEntries = [...state.textByIndex.entries()].sort(\n ([leftIndex], [rightIndex]) => leftIndex - rightIndex\n );\n for (const [, text] of orderedTextEntries) {\n if (text) {\n content.push({ type: 'text', text });\n if (structuredData === undefined) {\n try {\n structuredData = JSON.parse(text);\n } catch {\n // Not JSON - expected for non-structured responses\n }\n }\n }\n }\n\n const toolCalls: ToolCall[] = [];\n const functionCallItems: Array<{\n id: string;\n call_id: string;\n name: string;\n arguments: string;\n }> = [];\n const orderedToolEntries = [...state.toolCalls.entries()].sort(\n ([leftIndex], [rightIndex]) => leftIndex - rightIndex\n );\n for (const [, toolCall] of orderedToolEntries) {\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 if (!name || !callId) {\n continue;\n }\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 responseId = state.id || generateId();\n const message = new AssistantMessage(\n content,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: responseId,\n metadata: {\n responses: {\n model: state.model,\n status: state.status,\n response_id: responseId,\n functionCallItems:\n functionCallItems.length > 0 ? functionCallItems : undefined,\n reasoningEncryptedContent: state.reasoningEncryptedContent,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.inputTokens + state.outputTokens,\n cacheReadTokens: state.cacheReadTokens,\n cacheWriteTokens: 0,\n };\n\n let stopReason = 'end_turn';\n if (state.status === 'completed') {\n stopReason = toolCalls.length > 0 ? 'tool_use' : 'end_turn';\n } else if (state.status === 'incomplete') {\n stopReason = state.incompleteReason === 'max_output_tokens' ? 'max_tokens' : 'end_turn';\n } else if (state.status === 'failed') {\n stopReason = 'error';\n }\n if (state.hadRefusal && stopReason !== 'error') {\n stopReason = 'content_filter';\n }\n\n return {\n message,\n usage,\n stopReason,\n data: structuredData,\n };\n}\n","/**\n * @fileoverview OpenResponses API Handler\n *\n * This module implements the LLM handler for any OpenResponses-compatible server.\n * The OpenResponses specification enables multi-provider, interoperable LLM interfaces\n * based on the OpenAI Responses API.\n *\n * The handler accepts a configurable host URL, making it work with:\n * - OpenAI (`https://api.openai.com/v1`)\n * - OpenRouter (`https://openrouter.ai/api/v1`)\n * - Self-hosted servers\n * - Any OpenResponses-compatible endpoint\n *\n * @see {@link https://www.openresponses.org OpenResponses Specification}\n * @module providers/responses/llm\n */\n\nimport type { BoundLLMModel, LLMRequest, LLMResponse, LLMStreamResult, LLMCapabilities } from '../../types/llm.ts';\nimport type { LLMHandler, LLMProvider } from '../../types/provider.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport { StreamEventType, objectDelta } from '../../types/stream.ts';\nimport { UPPError, ErrorCode, ModalityType } 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 { parseJsonResponse } from '../../http/json.ts';\nimport { toError } from '../../utils/error.ts';\nimport type {\n ResponsesParams,\n ResponsesResponse,\n ResponsesStreamEvent,\n ResponsesErrorEvent,\n} from './types.ts';\nimport {\n transformRequest,\n transformResponse,\n transformStreamEvent,\n createStreamState,\n buildResponseFromState,\n} from './transform.ts';\n\n/**\n * Internal context for handler configuration.\n * Stored on the model reference via providerConfig.\n */\ninterface ResponsesHandlerContext {\n host: string;\n apiKeyEnv: string;\n}\n\n/**\n * Capability declaration for the OpenResponses API.\n *\n * Defines what features are supported by this handler:\n * - Streaming: Real-time token-by-token response streaming via SSE\n * - Tools: Function calling support\n * - Structured Output: JSON schema-based response formatting\n * - Image Input: Vision capabilities for image understanding\n * - Document Input: File/document support\n * - Video Input: Video content support (per OpenResponses spec)\n * - Audio Input: Audio content support (as file upload)\n */\nconst RESPONSES_CAPABILITIES: LLMCapabilities = {\n streaming: true,\n tools: true,\n structuredOutput: true,\n imageInput: true,\n documentInput: true,\n videoInput: true,\n audioInput: true,\n};\n\n/**\n * Extracts the handler context from the request config.\n * The context is stored in providerConfig when creating the model reference.\n */\nfunction extractContext(request: LLMRequest<ResponsesParams>): ResponsesHandlerContext {\n const config = request.config;\n const responsesConfig = (config as { _responsesContext?: ResponsesHandlerContext })._responsesContext;\n\n if (!responsesConfig) {\n throw new UPPError(\n 'OpenResponses provider requires host configuration. Use responses(modelId, { host: \"...\" })',\n ErrorCode.InvalidRequest,\n 'responses',\n ModalityType.LLM\n );\n }\n\n return responsesConfig;\n}\n\n/**\n * Creates an LLM handler for OpenResponses-compatible servers.\n *\n * This factory function creates a handler that communicates with any\n * server implementing the OpenResponses specification. The host URL\n * and API key environment variable are configured via provider options.\n *\n * @returns An LLM handler configured for the OpenResponses API\n *\n * @example Basic usage with OpenAI\n * ```typescript\n * const handler = createLLMHandler();\n * // Host is configured via provider options when creating model reference\n * ```\n */\nexport function createLLMHandler(): LLMHandler<ResponsesParams> {\n let providerRef: LLMProvider<ResponsesParams> | null = null;\n\n return {\n _setProvider(provider: LLMProvider<ResponsesParams>) {\n providerRef = provider;\n },\n\n bind(modelId: string): BoundLLMModel<ResponsesParams> {\n if (!providerRef) {\n throw new UPPError(\n 'Provider reference not set. Handler must be used with createProvider() or have _setProvider called.',\n ErrorCode.InvalidRequest,\n 'responses',\n ModalityType.LLM\n );\n }\n\n const model: BoundLLMModel<ResponsesParams> = {\n modelId,\n capabilities: RESPONSES_CAPABILITIES,\n\n get provider(): LLMProvider<ResponsesParams> {\n return providerRef!;\n },\n\n async complete(request: LLMRequest<ResponsesParams>): Promise<LLMResponse> {\n const context = extractContext(request);\n const apiKey = await resolveApiKey(\n request.config,\n context.apiKeyEnv,\n 'responses',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? `${context.host}/responses`;\n const body = transformRequest(request, modelId);\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doFetch(\n baseUrl,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'responses',\n 'llm'\n );\n\n const data = await parseJsonResponse<ResponsesResponse>(response, 'responses', 'llm');\n\n if (data.status === 'failed') {\n const message = data.error?.message ?? 'Provider returned a failed response.';\n throw new UPPError(\n message,\n ErrorCode.ProviderError,\n 'responses',\n ModalityType.LLM\n );\n }\n\n return transformResponse(data);\n },\n\n stream(request: LLMRequest<ResponsesParams>): 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 context = extractContext(request);\n const apiKey = await resolveApiKey(\n request.config,\n context.apiKeyEnv,\n 'responses',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? `${context.host}/responses`;\n const body = transformRequest(request, modelId);\n body.stream = true;\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n Accept: 'text/event-stream',\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doStreamFetch(\n baseUrl,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'responses',\n 'llm'\n );\n\n if (!response.ok) {\n const error = await normalizeHttpError(response, 'responses', '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 ErrorCode.ProviderError,\n 'responses',\n ModalityType.LLM\n );\n responseReject(error);\n throw error;\n }\n\n for await (const data of parseSSEStream(response.body)) {\n if (data === '[DONE]') {\n continue;\n }\n\n if (typeof data === 'object' && data !== null) {\n const event = data as ResponsesStreamEvent;\n\n if (event.type === 'error') {\n const errorEvent = event as ResponsesErrorEvent;\n const error = new UPPError(\n errorEvent.error.message,\n ErrorCode.ProviderError,\n 'responses',\n ModalityType.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 if (request.structure && uppEvent.type === StreamEventType.TextDelta) {\n yield objectDelta(uppEvent.delta.text ?? '', uppEvent.index);\n }\n }\n }\n }\n\n responseResolve(buildResponseFromState(state));\n } catch (error) {\n const err = toError(error);\n responseReject(err);\n throw err;\n }\n }\n\n return {\n [Symbol.asyncIterator]() {\n return generateEvents();\n },\n response: responsePromise,\n };\n },\n };\n\n return model;\n },\n };\n}\n","/**\n * @fileoverview OpenResponses Provider\n *\n * Implements support for the OpenResponses specification - an open-source,\n * multi-provider standard for interoperable LLM interfaces.\n *\n * The OpenResponses provider allows connecting to any server implementing\n * the OpenResponses API specification, including OpenAI, OpenRouter,\n * and self-hosted implementations.\n *\n * @see {@link https://www.openresponses.org OpenResponses Specification}\n * @module providers/responses\n */\n\nimport type { Provider, ModelReference, ProviderConfig } from '../../types/provider.ts';\nimport { createProvider } from '../../core/provider.ts';\nimport { createLLMHandler } from './llm.ts';\nimport type { ResponsesProviderOptions } from './types.ts';\n\n/**\n * Extended config interface that includes the internal responses context.\n */\ninterface ResponsesProviderConfig extends ProviderConfig {\n _responsesContext?: {\n host: string;\n apiKeyEnv: string;\n };\n}\n\n/**\n * Type alias for the OpenResponses provider with its options.\n */\nexport type ResponsesProvider = Provider<ResponsesProviderOptions>;\n\n/**\n * OpenResponses provider singleton.\n *\n * Implements the OpenResponses specification for multi-provider, interoperable\n * LLM interfaces. This provider works with any server implementing the\n * OpenResponses API, including:\n *\n * - OpenAI (`https://api.openai.com/v1`)\n * - OpenRouter (`https://openrouter.ai/api/v1`)\n * - Self-hosted servers\n * - Any OpenResponses-compatible endpoint\n *\n * @example Using with OpenAI\n * ```typescript\n * import { responses } from './providers/responses';\n * import { llm } from './core/llm';\n *\n * const model = llm({\n * model: responses('gpt-5.2', { host: 'https://api.openai.com/v1' }),\n * params: { max_output_tokens: 1000 }\n * });\n *\n * const turn = await model.generate('Hello!');\n * console.log(turn.response.text);\n * ```\n *\n * @example Using with OpenRouter\n * ```typescript\n * const model = llm({\n * model: responses('openai/gpt-4o', {\n * host: 'https://openrouter.ai/api/v1',\n * apiKeyEnv: 'OPENROUTER_API_KEY'\n * }),\n * params: { max_output_tokens: 1000 }\n * });\n * ```\n *\n * @example Using with a self-hosted server\n * ```typescript\n * const model = llm({\n * model: responses('llama-3.3-70b', {\n * host: 'http://localhost:8080/v1',\n * apiKeyEnv: 'LOCAL_API_KEY'\n * }),\n * params: { max_output_tokens: 1000 }\n * });\n * ```\n *\n * @see {@link https://www.openresponses.org OpenResponses Specification}\n */\nexport const responses = createProvider<ResponsesProviderOptions>({\n name: 'responses',\n version: '1.0.0',\n handlers: {\n llm: createLLMHandler(),\n },\n createModelReference: (\n modelId: string,\n options: ResponsesProviderOptions | undefined,\n provider: Provider<ResponsesProviderOptions>\n ): ModelReference<ResponsesProviderOptions> => {\n if (!options?.host) {\n throw new Error(\n 'OpenResponses provider requires a host option. Usage: responses(\"model-id\", { host: \"https://api.example.com/v1\" })'\n );\n }\n\n const providerConfig: ResponsesProviderConfig = {\n _responsesContext: {\n host: options.host,\n apiKeyEnv: options.apiKeyEnv ?? 'OPENRESPONSES_API_KEY',\n },\n };\n\n return {\n modelId,\n provider,\n options,\n providerConfig,\n };\n },\n}) as ResponsesProvider;\n\nexport type {\n ResponsesProviderOptions,\n ResponsesParams,\n ResponsesRequest,\n ResponsesResponse,\n ResponsesStreamEvent,\n ResponsesUsage,\n ResponsesInputItem,\n ResponsesOutputItem,\n ResponsesContentPart,\n ResponsesFunctionTool,\n ResponsesBuiltInTool,\n ResponsesToolUnion,\n ResponsesHeaders,\n} from './types.ts';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwDA,SAAS,gBAAgB,QAA4D;AACnF,MAAI,WAAW,UAAa,WAAW,KAAM,QAAO;AACpD,MAAI,OAAO,WAAW,SAAU,QAAO;AACvC,MAAI,CAAC,MAAM,QAAQ,MAAM,GAAG;AAC1B,UAAM,IAAI;AAAA,MACR;AAAA,MACA,UAAU;AAAA,MACV;AAAA,MACA,aAAa;AAAA,IACf;AAAA,EACF;AAEA,QAAM,QAAkB,CAAC;AACzB,aAAW,SAAS,QAAQ;AAC1B,QAAI,CAAC,SAAS,OAAO,UAAU,YAAY,EAAE,UAAU,QAAQ;AAC7D,YAAM,IAAI;AAAA,QACR;AAAA,QACA,UAAU;AAAA,QACV;AAAA,QACA,aAAa;AAAA,MACf;AAAA,IACF;AACA,UAAM,YAAa,MAA6B;AAChD,QAAI,OAAO,cAAc,UAAU;AACjC,YAAM,IAAI;AAAA,QACR;AAAA,QACA,UAAU;AAAA,QACV;AAAA,QACA,aAAa;AAAA,MACf;AAAA,IACF;AACA,QAAI,UAAU,SAAS,GAAG;AACxB,YAAM,KAAK,SAAS;AAAA,IACtB;AAAA,EACF;AAEA,SAAO,MAAM,SAAS,IAAI,MAAM,KAAK,MAAM,IAAI;AACjD;AAKA,SAAS,mBAAgD,SAAmB;AAC1E,SAAO,QAAQ,OAAO,CAAC,MAAM,KAAK,OAAO,EAAE,SAAS,QAAQ;AAC9D;AAMA,SAAS,qBAAqB,OAA2C;AACvE,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AACH,aAAO,EAAE,MAAM,cAAc,MAAM,MAAM,KAAK;AAAA,IAEhD,KAAK,SAAS;AACZ,YAAM,aAAa;AACnB,UAAI,WAAW,OAAO,SAAS,UAAU;AACvC,eAAO;AAAA,UACL,MAAM;AAAA,UACN,WAAW,QAAQ,WAAW,QAAQ,WAAW,WAAW,OAAO,IAAI;AAAA,QACzE;AAAA,MACF;AAEA,UAAI,WAAW,OAAO,SAAS,OAAO;AACpC,eAAO;AAAA,UACL,MAAM;AAAA,UACN,WAAW,WAAW,OAAO;AAAA,QAC/B;AAAA,MACF;AAEA,UAAI,WAAW,OAAO,SAAS,SAAS;AACtC,cAAM,SAAS,OAAO,KAAK,WAAW,OAAO,IAAI,EAAE,SAAS,QAAQ;AACpE,eAAO;AAAA,UACL,MAAM;AAAA,UACN,WAAW,QAAQ,WAAW,QAAQ,WAAW,MAAM;AAAA,QACzD;AAAA,MACF;AAEA,YAAM,IAAI;AAAA,QACR;AAAA,QACA,UAAU;AAAA,QACV;AAAA,QACA,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IAEA,KAAK,YAAY;AACf,YAAM,gBAAgB;AAEtB,UAAI,cAAc,OAAO,SAAS,UAAU;AAC1C,eAAO;AAAA,UACL,MAAM;AAAA,UACN,UAAU,cAAc,SAAS;AAAA,UACjC,WAAW,QAAQ,cAAc,QAAQ,WAAW,cAAc,OAAO,IAAI;AAAA,QAC/E;AAAA,MACF;AAEA,UAAI,cAAc,OAAO,SAAS,OAAO;AACvC,eAAO;AAAA,UACL,MAAM;AAAA,UACN,UAAU,cAAc,OAAO;AAAA,QACjC;AAAA,MACF;AAEA,UAAI,cAAc,OAAO,SAAS,QAAQ;AACxC,cAAM,SAAS,OAAO,KAAK,cAAc,OAAO,IAAI,EAAE,SAAS,QAAQ;AACvE,eAAO;AAAA,UACL,MAAM;AAAA,UACN,UAAU,cAAc,SAAS;AAAA,UACjC,WAAW,0BAA0B,MAAM;AAAA,QAC7C;AAAA,MACF;AAEA,YAAM,IAAI;AAAA,QACR;AAAA,QACA,UAAU;AAAA,QACV;AAAA,QACA,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IAEA,KAAK,SAAS;AACZ,YAAM,aAAa;AACnB,YAAM,SAAS,OAAO,KAAK,WAAW,IAAI,EAAE,SAAS,QAAQ;AAC7D,aAAO;AAAA,QACL,MAAM;AAAA,QACN,OAAO,QAAQ,WAAW,QAAQ,WAAW,MAAM;AAAA,MACrD;AAAA,IACF;AAAA,IAEA,KAAK,SAAS;AACZ,YAAM,aAAa;AACnB,YAAM,SAAS,OAAO,KAAK,WAAW,IAAI,EAAE,SAAS,QAAQ;AAC7D,aAAO;AAAA,QACL,MAAM;AAAA,QACN,UAAU;AAAA,QACV,WAAW,QAAQ,WAAW,QAAQ,WAAW,MAAM;AAAA,MACzD;AAAA,IACF;AAAA,IAEA;AACE,YAAM,IAAI;AAAA,QACR,6BAA6B,MAAM,IAAI;AAAA,QACvC,UAAU;AAAA,QACV;AAAA,QACA,aAAa;AAAA,MACf;AAAA,EACJ;AACF;AAKA,SAAS,iBAAiB,SAAwC;AAChE,MAAI,cAAc,OAAO,GAAG;AAC1B,UAAM,eAAe,mBAAmB,QAAQ,OAAO;AACvD,QAAI,aAAa,WAAW,KAAK,aAAa,CAAC,GAAG,SAAS,QAAQ;AACjE,aAAO;AAAA,QACL;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAU,aAAa,CAAC,EAAgB;AAAA,QAC1C;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,MACL;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,aAAa,IAAI,oBAAoB;AAAA,MAChD;AAAA,IACF;AAAA,EACF;AAEA,MAAI,mBAAmB,OAAO,GAAG;AAC/B,UAAM,eAAe,mBAAmB,QAAQ,OAAO;AACvD,UAAM,QAA8B,CAAC;AAErC,UAAM,eAAuC,aAC1C,OAAO,CAAC,MAAsB,EAAE,SAAS,MAAM,EAC/C,IAAI,CAAC,OAA6B;AAAA,MACjC,MAAM;AAAA,MACN,MAAM,EAAE;AAAA,IACV,EAAE;AAEJ,QAAI,aAAa,SAAS,GAAG;AAC3B,YAAM,KAAK;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAEA,UAAM,gBAAgB,QAAQ,UAAU;AAMxC,UAAM,oBAAoB,eAAe;AAEzC,QAAI,eAAe,2BAA2B;AAC5C,UAAI;AACF,cAAM,gBAAgB,KAAK,MAAM,cAAc,yBAAyB;AAKxE,cAAM,KAAK;AAAA,UACT,MAAM;AAAA,UACN,IAAI,cAAc;AAAA,UAClB,SAAS,cAAc;AAAA,UACvB,mBAAmB,cAAc;AAAA,QACnC,CAAC;AAAA,MACH,QAAQ;AAAA,MAER;AAAA,IACF;AAEA,QAAI,qBAAqB,kBAAkB,SAAS,GAAG;AACrD,iBAAW,MAAM,mBAAmB;AAClC,cAAM,KAAK;AAAA,UACT,MAAM;AAAA,UACN,IAAI,GAAG;AAAA,UACP,SAAS,GAAG;AAAA,UACZ,MAAM,GAAG;AAAA,UACT,WAAW,GAAG;AAAA,QAChB,CAAC;AAAA,MACH;AAAA,IACF,WAAW,QAAQ,aAAa,QAAQ,UAAU,SAAS,GAAG;AAC5D,iBAAW,QAAQ,QAAQ,WAAW;AACpC,cAAM,KAAK;AAAA,UACT,MAAM;AAAA,UACN,IAAI,MAAM,KAAK,UAAU;AAAA,UACzB,SAAS,KAAK;AAAA,UACd,MAAM,KAAK;AAAA,UACX,WAAW,KAAK,UAAU,KAAK,SAAS;AAAA,QAC1C,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAEA,MAAI,oBAAoB,OAAO,GAAG;AAChC,WAAO,QAAQ,QAAQ,IAAI,CAAC,YAAY;AAAA,MACtC,MAAM;AAAA,MACN,SAAS,OAAO;AAAA,MAChB,QACE,OAAO,OAAO,WAAW,WACrB,OAAO,SACP,KAAK,UAAU,OAAO,MAAM;AAAA,IACpC,EAAE;AAAA,EACJ;AAEA,SAAO,CAAC;AACV;AAKA,SAAS,oBACP,UACA,QAC+B;AAC/B,QAAM,SAA+B,CAAC;AACtC,QAAM,mBAAmB,gBAAgB,MAAM;AAE/C,MAAI,kBAAkB;AACpB,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAEA,aAAW,WAAW,UAAU;AAC9B,UAAM,QAAQ,iBAAiB,OAAO;AACtC,WAAO,KAAK,GAAG,KAAK;AAAA,EACtB;AAEA,MAAI,OAAO,WAAW,KAAK,OAAO,CAAC,GAAG,SAAS,WAAW;AACxD,UAAM,OAAO,OAAO,CAAC;AACrB,QAAI,KAAK,SAAS,UAAU,OAAO,KAAK,YAAY,UAAU;AAC5D,aAAO,KAAK;AAAA,IACd;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,mBAAmB,MAAkC;AAC5D,QAAM,OAAO,KAAK,UAAU;AAC5B,SAAO,EAAE,QAAQ,MAAM,OAAO;AAChC;AAKA,SAAS,cAAc,MAAmC;AACxD,QAAM,EAAE,OAAO,IAAI,mBAAmB,IAAI;AAE1C,SAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM,KAAK;AAAA,IACX,aAAa,KAAK;AAAA,IAClB,YAAY;AAAA,MACV,MAAM;AAAA,MACN,YAAY,KAAK,WAAW;AAAA,MAC5B,UAAU,KAAK,WAAW;AAAA,MAC1B,GAAI,KAAK,WAAW,yBAAyB,SACzC,EAAE,sBAAsB,KAAK,WAAW,qBAAqB,IAC7D,CAAC;AAAA,IACP;AAAA,IACA,GAAI,WAAW,SAAY,EAAE,OAAO,IAAI,CAAC;AAAA,EAC3C;AACF;AASO,SAAS,iBACd,SACA,SACkB;AAClB,QAAM,SAAS,QAAQ,UAAW,CAAC;AACnC,QAAM,EAAE,OAAO,cAAc,GAAG,WAAW,IAAI;AAE/C,QAAM,mBAAqC;AAAA,IACzC,GAAG;AAAA,IACH,OAAO;AAAA,IACP,OAAO,oBAAoB,QAAQ,UAAU,QAAQ,MAAM;AAAA,EAC7D;AAEA,QAAM,gBAAsC,QAAQ,OAAO,IAAI,aAAa,KAAK,CAAC;AAClF,QAAM,WAAiC;AAAA,IACrC,GAAG;AAAA,IACH,GAAI,gBAAgB,CAAC;AAAA,EACvB;AAEA,MAAI,SAAS,SAAS,GAAG;AACvB,qBAAiB,QAAQ;AAAA,EAC3B;AAEA,MAAI,QAAQ,WAAW;AACrB,UAAM,SAAkC;AAAA,MACtC,MAAM;AAAA,MACN,YAAY,QAAQ,UAAU;AAAA,MAC9B,UAAU,QAAQ,UAAU;AAAA,MAC5B,GAAI,QAAQ,UAAU,yBAAyB,SAC3C,EAAE,sBAAsB,QAAQ,UAAU,qBAAqB,IAC/D,EAAE,sBAAsB,MAAM;AAAA,IACpC;AACA,QAAI,QAAQ,UAAU,aAAa;AACjC,aAAO,cAAc,QAAQ,UAAU;AAAA,IACzC;AAEA,qBAAiB,OAAO;AAAA,MACtB,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,aAAa,QAAQ,UAAU;AAAA,QAC/B;AAAA,QACA,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,kBAAkB,MAAsC;AACtE,QAAM,UAA8B,CAAC;AACrC,QAAM,YAAwB,CAAC;AAC/B,QAAM,oBAKD,CAAC;AACN,MAAI,aAAa;AACjB,MAAI;AACJ,MAAI;AAEJ,aAAW,QAAQ,KAAK,QAAQ;AAC9B,QAAI,KAAK,SAAS,WAAW;AAC3B,YAAM,cAAc;AACpB,iBAAW,QAAQ,YAAY,SAAS;AACtC,YAAI,KAAK,SAAS,eAAe;AAC/B,kBAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,KAAK,KAAK,CAAC;AAC9C,cAAI,mBAAmB,QAAW;AAChC,gBAAI;AACF,+BAAiB,KAAK,MAAM,KAAK,IAAI;AAAA,YACvC,QAAQ;AAAA,YAER;AAAA,UACF;AAAA,QACF,WAAW,KAAK,SAAS,WAAW;AAClC,kBAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,KAAK,QAAQ,CAAC;AACjD,uBAAa;AAAA,QACf;AAAA,MACF;AAAA,IACF,WAAW,KAAK,SAAS,iBAAiB;AACxC,YAAM,eAAe;AACrB,UAAI,OAAgC,CAAC;AACrC,UAAI;AACF,eAAO,KAAK,MAAM,aAAa,SAAS;AAAA,MAC1C,QAAQ;AAAA,MAER;AACA,gBAAU,KAAK;AAAA,QACb,YAAY,aAAa;AAAA,QACzB,UAAU,aAAa;AAAA,QACvB,WAAW;AAAA,MACb,CAAC;AACD,wBAAkB,KAAK;AAAA,QACrB,IAAI,aAAa;AAAA,QACjB,SAAS,aAAa;AAAA,QACtB,MAAM,aAAa;AAAA,QACnB,WAAW,aAAa;AAAA,MAC1B,CAAC;AAAA,IACH,WAAW,KAAK,SAAS,aAAa;AACpC,YAAM,gBAAgB;AACtB,YAAM,gBAAgB,cAAc,QACjC,OAAO,CAAC,MAAmD,EAAE,SAAS,cAAc,EACpF,IAAI,CAAC,MAAM,EAAE,IAAI,EACjB,KAAK,EAAE;AACV,UAAI,eAAe;AACjB,gBAAQ,KAAK,EAAE,MAAM,aAAa,MAAM,cAAc,CAAC;AAAA,MACzD;AACA,kCAA4B,KAAK,UAAU;AAAA,QACzC,IAAI,cAAc;AAAA,QAClB,SAAS,cAAc;AAAA,QACvB,mBAAmB,cAAc;AAAA,MACnC,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,aAAa,KAAK,MAAM,WAAW;AACzC,QAAM,UAAU,IAAI;AAAA,IAClB;AAAA,IACA,UAAU,SAAS,IAAI,YAAY;AAAA,IACnC;AAAA,MACE,IAAI;AAAA,MACJ,UAAU;AAAA,QACR,WAAW;AAAA,UACT,OAAO,KAAK;AAAA,UACZ,QAAQ,KAAK;AAAA,UACb,aAAa;AAAA,UACb,mBACE,kBAAkB,SAAS,IAAI,oBAAoB;AAAA,UACrD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAoB;AAAA,IACxB,aAAa,KAAK,MAAM;AAAA,IACxB,cAAc,KAAK,MAAM;AAAA,IACzB,aAAa,KAAK,MAAM;AAAA,IACxB,iBAAiB,KAAK,MAAM,sBAAsB,iBAAiB;AAAA,IACnE,kBAAkB;AAAA,EACpB;AAEA,MAAI,aAAa;AACjB,MAAI,KAAK,WAAW,aAAa;AAC/B,iBAAa,UAAU,SAAS,IAAI,aAAa;AAAA,EACnD,WAAW,KAAK,WAAW,cAAc;AACvC,iBAAa,KAAK,oBAAoB,WAAW,sBAC7C,eACA;AAAA,EACN,WAAW,KAAK,WAAW,UAAU;AACnC,iBAAa;AAAA,EACf;AACA,MAAI,cAAc,eAAe,SAAS;AACxC,iBAAa;AAAA,EACf;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM;AAAA,EACR;AACF;AA8BO,SAAS,oBAAiC;AAC/C,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,aAAa,oBAAI,IAAI;AAAA,IACrB,kBAAkB,oBAAI,IAAI;AAAA,IAC1B,WAAW,oBAAI,IAAI;AAAA,IACnB,QAAQ;AAAA,IACR,kBAAkB;AAAA,IAClB,aAAa;AAAA,IACb,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,YAAY;AAAA,EACd;AACF;AAKO,SAAS,qBACd,OACA,OACe;AACf,QAAM,SAAwB,CAAC;AAE/B,QAAM,qBAAqB,CAAC,aAAsC;AAChE,UAAM,KAAK,SAAS,MAAM,MAAM;AAChC,UAAM,QAAQ,SAAS,SAAS,MAAM;AACtC,UAAM,SAAS,SAAS;AACxB,QAAI,SAAS,oBAAoB,QAAQ;AACvC,YAAM,mBAAmB,SAAS,mBAAmB;AAAA,IACvD,WAAW,SAAS,WAAW,cAAc;AAC3C,YAAM,mBAAmB;AAAA,IAC3B;AACA,QAAI,SAAS,OAAO;AAClB,YAAM,cAAc,SAAS,MAAM;AACnC,YAAM,eAAe,SAAS,MAAM;AACpC,YAAM,kBAAkB,SAAS,MAAM,sBAAsB,iBAAiB;AAAA,IAChF;AAAA,EACF;AAEA,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AACH,yBAAmB,MAAM,QAAQ;AACjC,aAAO,KAAK,EAAE,MAAM,gBAAgB,cAAc,OAAO,GAAG,OAAO,CAAC,EAAE,CAAC;AACvE;AAAA,IAEF,KAAK;AAAA,IACL,KAAK;AACH,yBAAmB,MAAM,QAAQ;AACjC;AAAA,IAEF,KAAK;AACH,yBAAmB,MAAM,QAAQ;AACjC,aAAO,KAAK,EAAE,MAAM,gBAAgB,aAAa,OAAO,GAAG,OAAO,CAAC,EAAE,CAAC;AACtE;AAAA,IAEF,KAAK;AAAA,IACL,KAAK;AACH,yBAAmB,MAAM,QAAQ;AACjC,aAAO,KAAK,EAAE,MAAM,gBAAgB,aAAa,OAAO,GAAG,OAAO,CAAC,EAAE,CAAC;AACtE;AAAA,IAEF,KAAK;AACH,UAAI,MAAM,KAAK,SAAS,iBAAiB;AACvC,cAAM,eAAe,MAAM;AAC3B,cAAM,WAAW,MAAM,UAAU,IAAI,MAAM,YAAY,KAAK;AAAA,UAC1D,WAAW;AAAA,QACb;AACA,iBAAS,SAAS,aAAa;AAC/B,iBAAS,SAAS,aAAa;AAC/B,iBAAS,OAAO,aAAa;AAC7B,YAAI,aAAa,WAAW;AAC1B,mBAAS,YAAY,aAAa;AAAA,QACpC;AACA,cAAM,UAAU,IAAI,MAAM,cAAc,QAAQ;AAAA,MAClD;AACA,aAAO,KAAK;AAAA,QACV,MAAM,gBAAgB;AAAA,QACtB,OAAO,MAAM;AAAA,QACb,OAAO,CAAC;AAAA,MACV,CAAC;AACD;AAAA,IAEF,KAAK;AACH,UAAI,MAAM,KAAK,SAAS,iBAAiB;AACvC,cAAM,eAAe,MAAM;AAC3B,cAAM,WAAW,MAAM,UAAU,IAAI,MAAM,YAAY,KAAK;AAAA,UAC1D,WAAW;AAAA,QACb;AACA,iBAAS,SAAS,aAAa;AAC/B,iBAAS,SAAS,aAAa;AAC/B,iBAAS,OAAO,aAAa;AAC7B,YAAI,aAAa,WAAW;AAC1B,mBAAS,YAAY,aAAa;AAAA,QACpC;AACA,cAAM,UAAU,IAAI,MAAM,cAAc,QAAQ;AAAA,MAClD,WAAW,MAAM,KAAK,SAAS,aAAa;AAC1C,cAAM,gBAAgB,MAAM;AAC5B,cAAM,4BAA4B,KAAK,UAAU;AAAA,UAC/C,IAAI,cAAc;AAAA,UAClB,SAAS,cAAc;AAAA,UACvB,mBAAmB,cAAc;AAAA,QACnC,CAAC;AAAA,MACH;AACA,aAAO,KAAK;AAAA,QACV,MAAM,gBAAgB;AAAA,QACtB,OAAO,MAAM;AAAA,QACb,OAAO,CAAC;AAAA,MACV,CAAC;AACD;AAAA,IAEF,KAAK,8BAA8B;AACjC,YAAM,cAAc,MAAM,YAAY,IAAI,MAAM,YAAY,KAAK;AACjE,YAAM,YAAY,IAAI,MAAM,cAAc,cAAc,MAAM,KAAK;AACnE,aAAO,KAAK;AAAA,QACV,MAAM,gBAAgB;AAAA,QACtB,OAAO,MAAM;AAAA,QACb,OAAO,EAAE,MAAM,MAAM,MAAM;AAAA,MAC7B,CAAC;AACD;AAAA,IACF;AAAA,IAEA,KAAK;AACH,YAAM,YAAY,IAAI,MAAM,cAAc,MAAM,IAAI;AACpD;AAAA,IAEF,KAAK,0BAA0B;AAC7B,YAAM,aAAa;AACnB,YAAM,iBAAiB,MAAM,YAAY,IAAI,MAAM,YAAY,KAAK;AACpE,YAAM,YAAY,IAAI,MAAM,cAAc,iBAAiB,MAAM,KAAK;AACtE,aAAO,KAAK;AAAA,QACV,MAAM,gBAAgB;AAAA,QACtB,OAAO,MAAM;AAAA,QACb,OAAO,EAAE,MAAM,MAAM,MAAM;AAAA,MAC7B,CAAC;AACD;AAAA,IACF;AAAA,IAEA,KAAK;AACH,YAAM,aAAa;AACnB,YAAM,YAAY,IAAI,MAAM,cAAc,MAAM,OAAO;AACvD;AAAA,IAEF,KAAK,0CAA0C;AAC7C,UAAI,WAAW,MAAM,UAAU,IAAI,MAAM,YAAY;AACrD,UAAI,CAAC,UAAU;AACb,mBAAW,EAAE,WAAW,GAAG;AAC3B,cAAM,UAAU,IAAI,MAAM,cAAc,QAAQ;AAAA,MAClD;AACA,UAAI,MAAM,WAAW,CAAC,SAAS,QAAQ;AACrC,iBAAS,SAAS,MAAM;AAAA,MAC1B;AACA,UAAI,MAAM,WAAW,CAAC,SAAS,QAAQ;AACrC,iBAAS,SAAS,MAAM;AAAA,MAC1B;AACA,eAAS,aAAa,MAAM;AAC5B,aAAO,KAAK;AAAA,QACV,MAAM,gBAAgB;AAAA,QACtB,OAAO,MAAM;AAAA,QACb,OAAO;AAAA,UACL,YAAY,SAAS,UAAU,SAAS,UAAU;AAAA,UAClD,UAAU,SAAS;AAAA,UACnB,eAAe,MAAM;AAAA,QACvB;AAAA,MACF,CAAC;AACD;AAAA,IACF;AAAA,IAEA,KAAK,yCAAyC;AAC5C,UAAI,WAAW,MAAM,UAAU,IAAI,MAAM,YAAY;AACrD,UAAI,CAAC,UAAU;AACb,mBAAW,EAAE,WAAW,GAAG;AAC3B,cAAM,UAAU,IAAI,MAAM,cAAc,QAAQ;AAAA,MAClD;AACA,UAAI,MAAM,SAAS;AACjB,iBAAS,SAAS,MAAM;AAAA,MAC1B;AACA,UAAI,MAAM,SAAS;AACjB,iBAAS,SAAS,MAAM;AAAA,MAC1B;AACA,eAAS,OAAO,MAAM;AACtB,eAAS,YAAY,MAAM;AAC3B;AAAA,IACF;AAAA,IAEA,KAAK,yCAAyC;AAC5C,YAAM,mBAAmB,MAAM,iBAAiB,IAAI,MAAM,YAAY,KAAK;AAC3E,YAAM,iBAAiB,IAAI,MAAM,cAAc,mBAAmB,MAAM,KAAK;AAC7E,aAAO,KAAK;AAAA,QACV,MAAM,gBAAgB;AAAA,QACtB,OAAO,MAAM;AAAA,QACb,OAAO,EAAE,MAAM,MAAM,MAAM;AAAA,MAC7B,CAAC;AACD;AAAA,IACF;AAAA,IAEA,KAAK;AACH,YAAM,iBAAiB,IAAI,MAAM,cAAc,MAAM,IAAI;AACzD;AAAA,IAEF,KAAK;AACH;AAAA,IAEF;AACE;AAAA,EACJ;AAEA,SAAO;AACT;AAKO,SAAS,uBAAuB,OAAiC;AACtE,QAAM,UAA8B,CAAC;AACrC,MAAI;AAEJ,QAAM,0BAA0B,CAAC,GAAG,MAAM,iBAAiB,QAAQ,CAAC,EAAE;AAAA,IACpE,CAAC,CAAC,SAAS,GAAG,CAAC,UAAU,MAAM,YAAY;AAAA,EAC7C;AACA,aAAW,CAAC,EAAE,SAAS,KAAK,yBAAyB;AACnD,QAAI,WAAW;AACb,cAAQ,KAAK,EAAE,MAAM,aAAa,MAAM,UAAU,CAAC;AAAA,IACrD;AAAA,EACF;AAEA,QAAM,qBAAqB,CAAC,GAAG,MAAM,YAAY,QAAQ,CAAC,EAAE;AAAA,IAC1D,CAAC,CAAC,SAAS,GAAG,CAAC,UAAU,MAAM,YAAY;AAAA,EAC7C;AACA,aAAW,CAAC,EAAE,IAAI,KAAK,oBAAoB;AACzC,QAAI,MAAM;AACR,cAAQ,KAAK,EAAE,MAAM,QAAQ,KAAK,CAAC;AACnC,UAAI,mBAAmB,QAAW;AAChC,YAAI;AACF,2BAAiB,KAAK,MAAM,IAAI;AAAA,QAClC,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,YAAwB,CAAC;AAC/B,QAAM,oBAKD,CAAC;AACN,QAAM,qBAAqB,CAAC,GAAG,MAAM,UAAU,QAAQ,CAAC,EAAE;AAAA,IACxD,CAAC,CAAC,SAAS,GAAG,CAAC,UAAU,MAAM,YAAY;AAAA,EAC7C;AACA,aAAW,CAAC,EAAE,QAAQ,KAAK,oBAAoB;AAC7C,QAAI,OAAgC,CAAC;AACrC,QAAI,SAAS,WAAW;AACtB,UAAI;AACF,eAAO,KAAK,MAAM,SAAS,SAAS;AAAA,MACtC,QAAQ;AAAA,MAER;AAAA,IACF;AACA,UAAM,SAAS,SAAS,UAAU;AAClC,UAAM,SAAS,SAAS,UAAU,SAAS,UAAU;AACrD,UAAM,OAAO,SAAS,QAAQ;AAC9B,QAAI,CAAC,QAAQ,CAAC,QAAQ;AACpB;AAAA,IACF;AACA,cAAU,KAAK;AAAA,MACb,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,WAAW;AAAA,IACb,CAAC;AAED,QAAI,UAAU,UAAU,MAAM;AAC5B,wBAAkB,KAAK;AAAA,QACrB,IAAI;AAAA,QACJ,SAAS;AAAA,QACT;AAAA,QACA,WAAW,SAAS;AAAA,MACtB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,aAAa,MAAM,MAAM,WAAW;AAC1C,QAAM,UAAU,IAAI;AAAA,IAClB;AAAA,IACA,UAAU,SAAS,IAAI,YAAY;AAAA,IACnC;AAAA,MACE,IAAI;AAAA,MACJ,UAAU;AAAA,QACR,WAAW;AAAA,UACT,OAAO,MAAM;AAAA,UACb,QAAQ,MAAM;AAAA,UACd,aAAa;AAAA,UACb,mBACE,kBAAkB,SAAS,IAAI,oBAAoB;AAAA,UACrD,2BAA2B,MAAM;AAAA,QACnC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAoB;AAAA,IACxB,aAAa,MAAM;AAAA,IACnB,cAAc,MAAM;AAAA,IACpB,aAAa,MAAM,cAAc,MAAM;AAAA,IACvC,iBAAiB,MAAM;AAAA,IACvB,kBAAkB;AAAA,EACpB;AAEA,MAAI,aAAa;AACjB,MAAI,MAAM,WAAW,aAAa;AAChC,iBAAa,UAAU,SAAS,IAAI,aAAa;AAAA,EACnD,WAAW,MAAM,WAAW,cAAc;AACxC,iBAAa,MAAM,qBAAqB,sBAAsB,eAAe;AAAA,EAC/E,WAAW,MAAM,WAAW,UAAU;AACpC,iBAAa;AAAA,EACf;AACA,MAAI,MAAM,cAAc,eAAe,SAAS;AAC9C,iBAAa;AAAA,EACf;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM;AAAA,EACR;AACF;;;ACh1BA,IAAM,yBAA0C;AAAA,EAC9C,WAAW;AAAA,EACX,OAAO;AAAA,EACP,kBAAkB;AAAA,EAClB,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,YAAY;AACd;AAMA,SAAS,eAAe,SAA+D;AACrF,QAAM,SAAS,QAAQ;AACvB,QAAM,kBAAmB,OAA2D;AAEpF,MAAI,CAAC,iBAAiB;AACpB,UAAM,IAAI;AAAA,MACR;AAAA,MACA,UAAU;AAAA,MACV;AAAA,MACA,aAAa;AAAA,IACf;AAAA,EACF;AAEA,SAAO;AACT;AAiBO,SAAS,mBAAgD;AAC9D,MAAI,cAAmD;AAEvD,SAAO;AAAA,IACL,aAAa,UAAwC;AACnD,oBAAc;AAAA,IAChB;AAAA,IAEA,KAAK,SAAiD;AACpD,UAAI,CAAC,aAAa;AAChB,cAAM,IAAI;AAAA,UACR;AAAA,UACA,UAAU;AAAA,UACV;AAAA,UACA,aAAa;AAAA,QACf;AAAA,MACF;AAEA,YAAM,QAAwC;AAAA,QAC5C;AAAA,QACA,cAAc;AAAA,QAEd,IAAI,WAAyC;AAC3C,iBAAO;AAAA,QACT;AAAA,QAEA,MAAM,SAAS,SAA4D;AACzE,gBAAM,UAAU,eAAe,OAAO;AACtC,gBAAM,SAAS,MAAM;AAAA,YACnB,QAAQ;AAAA,YACR,QAAQ;AAAA,YACR;AAAA,YACA;AAAA,UACF;AAEA,gBAAM,UAAU,QAAQ,OAAO,WAAW,GAAG,QAAQ,IAAI;AACzD,gBAAM,OAAO,iBAAiB,SAAS,OAAO;AAE9C,gBAAM,UAAkC;AAAA,YACtC,gBAAgB;AAAA,YAChB,eAAe,UAAU,MAAM;AAAA,UACjC;AAEA,cAAI,QAAQ,OAAO,SAAS;AAC1B,uBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,OAAO,OAAO,GAAG;AACjE,kBAAI,UAAU,QAAW;AACvB,wBAAQ,GAAG,IAAI;AAAA,cACjB;AAAA,YACF;AAAA,UACF;AAEA,gBAAM,WAAW,MAAM;AAAA,YACrB;AAAA,YACA;AAAA,cACE,QAAQ;AAAA,cACR;AAAA,cACA,MAAM,KAAK,UAAU,IAAI;AAAA,cACzB,QAAQ,QAAQ;AAAA,YAClB;AAAA,YACA,QAAQ;AAAA,YACR;AAAA,YACA;AAAA,UACF;AAEA,gBAAM,OAAO,MAAM,kBAAqC,UAAU,aAAa,KAAK;AAEpF,cAAI,KAAK,WAAW,UAAU;AAC5B,kBAAM,UAAU,KAAK,OAAO,WAAW;AACvC,kBAAM,IAAI;AAAA,cACR;AAAA,cACA,UAAU;AAAA,cACV;AAAA,cACA,aAAa;AAAA,YACf;AAAA,UACF;AAEA,iBAAO,kBAAkB,IAAI;AAAA,QAC/B;AAAA,QAEA,OAAO,SAAuD;AAC5D,gBAAM,QAAQ,kBAAkB;AAChC,cAAI;AACJ,cAAI;AAEJ,gBAAM,kBAAkB,IAAI,QAAqB,CAAC,SAAS,WAAW;AACpE,8BAAkB;AAClB,6BAAiB;AAAA,UACnB,CAAC;AAED,0BAAgB,iBAA6D;AAC3E,gBAAI;AACF,oBAAM,UAAU,eAAe,OAAO;AACtC,oBAAM,SAAS,MAAM;AAAA,gBACnB,QAAQ;AAAA,gBACR,QAAQ;AAAA,gBACR;AAAA,gBACA;AAAA,cACF;AAEA,oBAAM,UAAU,QAAQ,OAAO,WAAW,GAAG,QAAQ,IAAI;AACzD,oBAAM,OAAO,iBAAiB,SAAS,OAAO;AAC9C,mBAAK,SAAS;AAEd,oBAAM,UAAkC;AAAA,gBACtC,gBAAgB;AAAA,gBAChB,eAAe,UAAU,MAAM;AAAA,gBAC/B,QAAQ;AAAA,cACV;AAEA,kBAAI,QAAQ,OAAO,SAAS;AAC1B,2BAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,OAAO,OAAO,GAAG;AACjE,sBAAI,UAAU,QAAW;AACvB,4BAAQ,GAAG,IAAI;AAAA,kBACjB;AAAA,gBACF;AAAA,cACF;AAEA,oBAAM,WAAW,MAAM;AAAA,gBACrB;AAAA,gBACA;AAAA,kBACE,QAAQ;AAAA,kBACR;AAAA,kBACA,MAAM,KAAK,UAAU,IAAI;AAAA,kBACzB,QAAQ,QAAQ;AAAA,gBAClB;AAAA,gBACA,QAAQ;AAAA,gBACR;AAAA,gBACA;AAAA,cACF;AAEA,kBAAI,CAAC,SAAS,IAAI;AAChB,sBAAM,QAAQ,MAAM,mBAAmB,UAAU,aAAa,KAAK;AACnE,+BAAe,KAAK;AACpB,sBAAM;AAAA,cACR;AAEA,kBAAI,CAAC,SAAS,MAAM;AAClB,sBAAM,QAAQ,IAAI;AAAA,kBAChB;AAAA,kBACA,UAAU;AAAA,kBACV;AAAA,kBACA,aAAa;AAAA,gBACf;AACA,+BAAe,KAAK;AACpB,sBAAM;AAAA,cACR;AAEA,+BAAiB,QAAQ,eAAe,SAAS,IAAI,GAAG;AACtD,oBAAI,SAAS,UAAU;AACrB;AAAA,gBACF;AAEA,oBAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAC7C,wBAAM,QAAQ;AAEd,sBAAI,MAAM,SAAS,SAAS;AAC1B,0BAAM,aAAa;AACnB,0BAAM,QAAQ,IAAI;AAAA,sBAChB,WAAW,MAAM;AAAA,sBACjB,UAAU;AAAA,sBACV;AAAA,sBACA,aAAa;AAAA,oBACf;AACA,mCAAe,KAAK;AACpB,0BAAM;AAAA,kBACR;AAEA,wBAAM,YAAY,qBAAqB,OAAO,KAAK;AACnD,6BAAW,YAAY,WAAW;AAChC,0BAAM;AACN,wBAAI,QAAQ,aAAa,SAAS,SAAS,gBAAgB,WAAW;AACpE,4BAAM,YAAY,SAAS,MAAM,QAAQ,IAAI,SAAS,KAAK;AAAA,oBAC7D;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AAEA,8BAAgB,uBAAuB,KAAK,CAAC;AAAA,YAC/C,SAAS,OAAO;AACd,oBAAM,MAAM,QAAQ,KAAK;AACzB,6BAAe,GAAG;AAClB,oBAAM;AAAA,YACR;AAAA,UACF;AAEA,iBAAO;AAAA,YACL,CAAC,OAAO,aAAa,IAAI;AACvB,qBAAO,eAAe;AAAA,YACxB;AAAA,YACA,UAAU;AAAA,UACZ;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;AC7NO,IAAM,YAAY,eAAyC;AAAA,EAChE,MAAM;AAAA,EACN,SAAS;AAAA,EACT,UAAU;AAAA,IACR,KAAK,iBAAiB;AAAA,EACxB;AAAA,EACA,sBAAsB,CACpB,SACA,SACA,aAC6C;AAC7C,QAAI,CAAC,SAAS,MAAM;AAClB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,iBAA0C;AAAA,MAC9C,mBAAmB;AAAA,QACjB,MAAM,QAAQ;AAAA,QACd,WAAW,QAAQ,aAAa;AAAA,MAClC;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF,CAAC;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/providers/responses/transform.ts","../../src/providers/responses/llm.ts","../../src/providers/responses/index.ts"],"sourcesContent":["/**\n * @fileoverview OpenResponses API Message Transformers\n *\n * This module provides transformation functions for converting between the\n * Universal Provider Protocol (UPP) message format and the OpenResponses API\n * format. The OpenResponses spec uses items as atomic units with defined\n * state machines and streaming updates.\n *\n * Key concepts:\n * - Uses `input` array of items instead of `messages`\n * - Function calls are separate input items\n * - Tool results use `function_call_output` items\n * - Supports multimodal inputs: text, images, files (documents), video\n *\n * @module providers/responses/transform\n */\n\nimport type { LLMRequest, LLMResponse } from '../../types/llm.ts';\nimport type { Message } from '../../types/messages.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport { StreamEventType } from '../../types/stream.ts';\nimport type { Tool, ToolCall } from '../../types/tool.ts';\nimport type { TokenUsage } from '../../types/turn.ts';\nimport type {\n ContentBlock,\n TextBlock,\n ImageBlock,\n DocumentBlock,\n VideoBlock,\n AudioBlock,\n AssistantContent,\n} from '../../types/content.ts';\nimport {\n AssistantMessage,\n isUserMessage,\n isAssistantMessage,\n isToolResultMessage,\n} from '../../types/messages.ts';\nimport { UPPError, ErrorCode, ModalityType } from '../../types/errors.ts';\nimport { generateId } from '../../utils/id.ts';\nimport type {\n ResponsesParams,\n ResponsesRequest,\n ResponsesInputItem,\n ResponsesContentPart,\n ResponsesFunctionTool,\n ResponsesToolUnion,\n ResponsesResponse,\n ResponsesStreamEvent,\n ResponsesReasoningOutput,\n ResponsesFunctionCallOutput,\n} from './types.ts';\n\n/**\n * Normalizes system prompt to string.\n */\nfunction normalizeSystem(system: string | unknown[] | undefined): string | undefined {\n if (system === undefined || system === null) return undefined;\n if (typeof system === 'string') return system;\n if (!Array.isArray(system)) {\n throw new UPPError(\n 'System prompt must be a string or an array of text blocks',\n ErrorCode.InvalidRequest,\n 'responses',\n ModalityType.LLM\n );\n }\n\n const texts: string[] = [];\n for (const block of system) {\n if (!block || typeof block !== 'object' || !('text' in block)) {\n throw new UPPError(\n 'System prompt array must contain objects with a text field',\n ErrorCode.InvalidRequest,\n 'responses',\n ModalityType.LLM\n );\n }\n const textValue = (block as { text?: unknown }).text;\n if (typeof textValue !== 'string') {\n throw new UPPError(\n 'System prompt text must be a string',\n ErrorCode.InvalidRequest,\n 'responses',\n ModalityType.LLM\n );\n }\n if (textValue.length > 0) {\n texts.push(textValue);\n }\n }\n\n return texts.length > 0 ? texts.join('\\n\\n') : undefined;\n}\n\n/**\n * Filters content blocks to only include those with a valid 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 * Transforms a UPP content block to OpenResponses content part format.\n * Supports text, image, document, video, and audio content types.\n */\nfunction transformContentPart(block: ContentBlock): ResponsesContentPart {\n switch (block.type) {\n case 'text':\n return { type: 'input_text', text: block.text };\n\n case 'image': {\n const imageBlock = block as ImageBlock;\n if (imageBlock.source.type === 'base64') {\n return {\n type: 'input_image',\n image_url: `data:${imageBlock.mimeType};base64,${imageBlock.source.data}`,\n };\n }\n\n if (imageBlock.source.type === 'url') {\n return {\n type: 'input_image',\n image_url: imageBlock.source.url,\n };\n }\n\n if (imageBlock.source.type === 'bytes') {\n const base64 = Buffer.from(imageBlock.source.data).toString('base64');\n return {\n type: 'input_image',\n image_url: `data:${imageBlock.mimeType};base64,${base64}`,\n };\n }\n\n throw new UPPError(\n 'Unknown image source type',\n ErrorCode.InvalidRequest,\n 'responses',\n ModalityType.LLM\n );\n }\n\n case 'document': {\n const documentBlock = block as DocumentBlock;\n\n if (documentBlock.source.type === 'base64') {\n return {\n type: 'input_file',\n filename: documentBlock.title ?? 'document',\n file_data: `data:${documentBlock.mimeType};base64,${documentBlock.source.data}`,\n };\n }\n\n if (documentBlock.source.type === 'url') {\n return {\n type: 'input_file',\n file_url: documentBlock.source.url,\n };\n }\n\n if (documentBlock.source.type === 'text') {\n const base64 = Buffer.from(documentBlock.source.data).toString('base64');\n return {\n type: 'input_file',\n filename: documentBlock.title ?? 'document.txt',\n file_data: `data:text/plain;base64,${base64}`,\n };\n }\n\n throw new UPPError(\n 'Unknown document source type',\n ErrorCode.InvalidRequest,\n 'responses',\n ModalityType.LLM\n );\n }\n\n case 'video': {\n const videoBlock = block as VideoBlock;\n const base64 = Buffer.from(videoBlock.data).toString('base64');\n return {\n type: 'input_video' as ResponsesContentPart['type'],\n video: `data:${videoBlock.mimeType};base64,${base64}`,\n } as ResponsesContentPart;\n }\n\n case 'audio': {\n const audioBlock = block as AudioBlock;\n const base64 = Buffer.from(audioBlock.data).toString('base64');\n return {\n type: 'input_file',\n filename: 'audio',\n file_data: `data:${audioBlock.mimeType};base64,${base64}`,\n };\n }\n\n default:\n throw new UPPError(\n `Unsupported content type: ${block.type}`,\n ErrorCode.InvalidRequest,\n 'responses',\n ModalityType.LLM\n );\n }\n}\n\n/**\n * Transforms a single UPP message to OpenResponses input items.\n */\nfunction transformMessage(message: Message): ResponsesInputItem[] {\n if (isUserMessage(message)) {\n const validContent = filterValidContent(message.content);\n if (validContent.length === 1 && validContent[0]?.type === 'text') {\n return [\n {\n type: 'message',\n role: 'user',\n content: (validContent[0] as TextBlock).text,\n },\n ];\n }\n return [\n {\n type: 'message',\n role: 'user',\n content: validContent.map(transformContentPart),\n },\n ];\n }\n\n if (isAssistantMessage(message)) {\n const validContent = filterValidContent(message.content);\n const items: ResponsesInputItem[] = [];\n\n const contentParts: ResponsesContentPart[] = validContent\n .filter((c): c is TextBlock => c.type === 'text')\n .map((c): ResponsesContentPart => ({\n type: 'output_text',\n text: c.text,\n }));\n\n if (contentParts.length > 0) {\n items.push({\n type: 'message',\n role: 'assistant',\n content: contentParts,\n });\n }\n\n const responsesMeta = message.metadata?.responses as\n | {\n functionCallItems?: Array<{ id: string; call_id: string; name: string; arguments: string }>;\n reasoningEncryptedContent?: string;\n }\n | undefined;\n const functionCallItems = responsesMeta?.functionCallItems;\n\n if (responsesMeta?.reasoningEncryptedContent) {\n try {\n const reasoningData = JSON.parse(responsesMeta.reasoningEncryptedContent) as {\n id: string;\n summary: Array<{ type: 'summary_text'; text: string }>;\n encrypted_content?: string;\n };\n items.push({\n type: 'reasoning',\n id: reasoningData.id,\n summary: reasoningData.summary,\n encrypted_content: reasoningData.encrypted_content,\n });\n } catch {\n // Invalid JSON - skip reasoning item\n }\n }\n\n if (functionCallItems && functionCallItems.length > 0) {\n for (const fc of functionCallItems) {\n items.push({\n type: 'function_call',\n id: fc.id,\n call_id: fc.call_id,\n name: fc.name,\n arguments: fc.arguments,\n });\n }\n } else if (message.toolCalls && message.toolCalls.length > 0) {\n for (const call of message.toolCalls) {\n items.push({\n type: 'function_call',\n id: `fc_${call.toolCallId}`,\n call_id: call.toolCallId,\n name: call.toolName,\n arguments: JSON.stringify(call.arguments),\n });\n }\n }\n\n return items;\n }\n\n if (isToolResultMessage(message)) {\n return message.results.map((result) => ({\n type: 'function_call_output' as const,\n call_id: result.toolCallId,\n output:\n typeof result.result === 'string'\n ? result.result\n : JSON.stringify(result.result),\n }));\n }\n\n return [];\n}\n\n/**\n * Transforms UPP messages to OpenResponses input items.\n */\nfunction transformInputItems(\n messages: Message[],\n system?: string | unknown[]\n): ResponsesInputItem[] | string {\n const result: ResponsesInputItem[] = [];\n const normalizedSystem = normalizeSystem(system);\n\n if (normalizedSystem) {\n result.push({\n type: 'message',\n role: 'system',\n content: normalizedSystem,\n });\n }\n\n for (const message of messages) {\n const items = transformMessage(message);\n result.push(...items);\n }\n\n if (result.length === 1 && result[0]?.type === 'message') {\n const item = result[0] as { role?: string; content?: string | unknown[] };\n if (item.role === 'user' && typeof item.content === 'string') {\n return item.content;\n }\n }\n\n return result;\n}\n\n/**\n * Extracts provider-specific options from tool metadata.\n */\nfunction extractToolOptions(tool: Tool): { strict?: boolean } {\n const meta = tool.metadata?.responses as { strict?: boolean } | undefined;\n return { strict: meta?.strict };\n}\n\n/**\n * Transforms a UPP tool definition to OpenResponses function tool format.\n */\nfunction transformTool(tool: Tool): ResponsesFunctionTool {\n const { strict } = extractToolOptions(tool);\n\n return {\n type: 'function',\n name: tool.name,\n description: tool.description,\n parameters: {\n type: 'object',\n properties: tool.parameters.properties,\n required: tool.parameters.required,\n ...(tool.parameters.additionalProperties !== undefined\n ? { additionalProperties: tool.parameters.additionalProperties }\n : {}),\n },\n ...(strict !== undefined ? { strict } : {}),\n };\n}\n\n/**\n * Transforms a UPP LLM request into OpenResponses API format.\n *\n * @param request - The UPP LLM request\n * @param modelId - The model identifier\n * @returns An OpenResponses API request body\n */\nexport function transformRequest(\n request: LLMRequest<ResponsesParams>,\n modelId: string\n): ResponsesRequest {\n const params = request.params ?? ({} as ResponsesParams);\n const { tools: builtInTools, ...restParams } = params;\n\n const responsesRequest: ResponsesRequest = {\n ...restParams,\n model: modelId,\n input: transformInputItems(request.messages, request.system),\n };\n\n const functionTools: ResponsesToolUnion[] = request.tools?.map(transformTool) ?? [];\n const allTools: ResponsesToolUnion[] = [\n ...functionTools,\n ...(builtInTools ?? []),\n ];\n\n if (allTools.length > 0) {\n responsesRequest.tools = allTools;\n }\n\n if (request.structure) {\n const schema: Record<string, unknown> = {\n type: 'object',\n properties: request.structure.properties,\n required: request.structure.required,\n ...(request.structure.additionalProperties !== undefined\n ? { additionalProperties: request.structure.additionalProperties }\n : { additionalProperties: false }),\n };\n if (request.structure.description) {\n schema.description = request.structure.description;\n }\n\n responsesRequest.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 responsesRequest;\n}\n\n/**\n * Transforms an OpenResponses API response to UPP LLMResponse format.\n */\nexport function transformResponse(data: ResponsesResponse): LLMResponse {\n const content: AssistantContent[] = [];\n const toolCalls: ToolCall[] = [];\n const functionCallItems: Array<{\n id: string;\n call_id: string;\n name: string;\n arguments: string;\n }> = [];\n let hadRefusal = false;\n let structuredData: unknown;\n let reasoningEncryptedContent: string | undefined;\n\n for (const item of data.output) {\n if (item.type === 'message') {\n const messageItem = item;\n for (const part of messageItem.content) {\n if (part.type === 'output_text') {\n content.push({ type: 'text', text: part.text });\n if (structuredData === undefined) {\n try {\n structuredData = JSON.parse(part.text);\n } catch {\n // Not JSON - expected for non-structured responses\n }\n }\n } else if (part.type === 'refusal') {\n content.push({ type: 'text', text: part.refusal });\n hadRefusal = true;\n }\n }\n } else if (item.type === 'function_call') {\n const functionCall = item as ResponsesFunctionCallOutput;\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 === 'reasoning') {\n const reasoningItem = item as ResponsesReasoningOutput;\n const reasoningText = reasoningItem.summary\n .filter((s): s is { type: 'summary_text'; text: string } => s.type === 'summary_text')\n .map((s) => s.text)\n .join('');\n if (reasoningText) {\n content.push({ type: 'reasoning', text: reasoningText });\n }\n reasoningEncryptedContent = JSON.stringify({\n id: reasoningItem.id,\n summary: reasoningItem.summary,\n encrypted_content: reasoningItem.encrypted_content,\n });\n }\n }\n\n const responseId = data.id || generateId();\n const message = new AssistantMessage(\n content,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: responseId,\n metadata: {\n responses: {\n model: data.model,\n status: data.status,\n response_id: responseId,\n functionCallItems:\n functionCallItems.length > 0 ? functionCallItems : undefined,\n reasoningEncryptedContent,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: data.usage.input_tokens,\n outputTokens: data.usage.output_tokens,\n totalTokens: data.usage.total_tokens,\n cacheReadTokens: data.usage.input_tokens_details?.cached_tokens ?? 0,\n cacheWriteTokens: 0,\n };\n\n let stopReason = 'end_turn';\n if (data.status === 'completed') {\n stopReason = toolCalls.length > 0 ? 'tool_use' : 'end_turn';\n } else if (data.status === 'incomplete') {\n stopReason = data.incomplete_details?.reason === 'max_output_tokens'\n ? 'max_tokens'\n : 'end_turn';\n } else if (data.status === 'failed') {\n stopReason = 'error';\n }\n if (hadRefusal && stopReason !== 'error') {\n stopReason = 'content_filter';\n }\n\n return {\n message,\n usage,\n stopReason,\n data: structuredData,\n };\n}\n\n// ============================================\n// Streaming State Management\n// ============================================\n\n/**\n * Mutable state for accumulating streaming data.\n */\nexport interface StreamState {\n id: string;\n model: string;\n textByIndex: Map<number, string>;\n reasoningByIndex: Map<number, string>;\n toolCalls: Map<\n number,\n { itemId?: string; callId?: string; name?: string; arguments: string }\n >;\n status: string;\n incompleteReason?: string;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n hadRefusal: boolean;\n reasoningEncryptedContent?: string;\n}\n\n/**\n * Creates a fresh stream state object.\n */\nexport function createStreamState(): StreamState {\n return {\n id: '',\n model: '',\n textByIndex: new Map(),\n reasoningByIndex: new Map(),\n toolCalls: new Map(),\n status: 'in_progress',\n incompleteReason: undefined,\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n hadRefusal: false,\n };\n}\n\n/**\n * Transforms an OpenResponses streaming event into UPP stream events.\n */\nexport function transformStreamEvent(\n event: ResponsesStreamEvent,\n state: StreamState\n): StreamEvent[] {\n const events: StreamEvent[] = [];\n\n const updateFromResponse = (response: ResponsesResponse): void => {\n state.id = response.id || state.id;\n state.model = response.model || state.model;\n state.status = response.status;\n if (response.incomplete_details?.reason) {\n state.incompleteReason = response.incomplete_details.reason;\n } else if (response.status !== 'incomplete') {\n state.incompleteReason = undefined;\n }\n if (response.usage) {\n state.inputTokens = response.usage.input_tokens;\n state.outputTokens = response.usage.output_tokens;\n state.cacheReadTokens = response.usage.input_tokens_details?.cached_tokens ?? 0;\n }\n };\n\n switch (event.type) {\n case 'response.created':\n updateFromResponse(event.response);\n events.push({ type: StreamEventType.MessageStart, index: 0, delta: {} });\n break;\n\n case 'response.queued':\n case 'response.in_progress':\n updateFromResponse(event.response);\n break;\n\n case 'response.completed':\n updateFromResponse(event.response);\n events.push({ type: StreamEventType.MessageStop, index: 0, delta: {} });\n break;\n\n case 'response.failed':\n case 'response.incomplete':\n updateFromResponse(event.response);\n events.push({ type: StreamEventType.MessageStop, 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 ResponsesFunctionCallOutput;\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: StreamEventType.ContentBlockStart,\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 ResponsesFunctionCallOutput;\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 === 'reasoning') {\n const reasoningItem = event.item as ResponsesReasoningOutput;\n state.reasoningEncryptedContent = JSON.stringify({\n id: reasoningItem.id,\n summary: reasoningItem.summary,\n encrypted_content: reasoningItem.encrypted_content,\n });\n }\n events.push({\n type: StreamEventType.ContentBlockStop,\n index: event.output_index,\n delta: {},\n });\n break;\n\n case 'response.output_text.delta': {\n const currentText = state.textByIndex.get(event.output_index) ?? '';\n state.textByIndex.set(event.output_index, currentText + event.delta);\n events.push({\n type: StreamEventType.TextDelta,\n index: event.output_index,\n delta: { text: event.delta },\n });\n break;\n }\n\n case 'response.output_text.done':\n state.textByIndex.set(event.output_index, event.text);\n break;\n\n case 'response.refusal.delta': {\n state.hadRefusal = true;\n const currentRefusal = state.textByIndex.get(event.output_index) ?? '';\n state.textByIndex.set(event.output_index, currentRefusal + event.delta);\n events.push({\n type: StreamEventType.TextDelta,\n index: event.output_index,\n delta: { text: event.delta },\n });\n break;\n }\n\n case 'response.refusal.done':\n state.hadRefusal = true;\n state.textByIndex.set(event.output_index, event.refusal);\n break;\n\n case 'response.function_call_arguments.delta': {\n let toolCall = state.toolCalls.get(event.output_index);\n if (!toolCall) {\n toolCall = { arguments: '' };\n state.toolCalls.set(event.output_index, toolCall);\n }\n if (event.item_id && !toolCall.itemId) {\n toolCall.itemId = event.item_id;\n }\n if (event.call_id && !toolCall.callId) {\n toolCall.callId = event.call_id;\n }\n toolCall.arguments += event.delta;\n events.push({\n type: StreamEventType.ToolCallDelta,\n index: event.output_index,\n delta: {\n toolCallId: toolCall.callId ?? toolCall.itemId ?? '',\n toolName: toolCall.name,\n argumentsJson: event.delta,\n },\n });\n break;\n }\n\n case 'response.function_call_arguments.done': {\n let toolCall = state.toolCalls.get(event.output_index);\n if (!toolCall) {\n toolCall = { arguments: '' };\n state.toolCalls.set(event.output_index, toolCall);\n }\n if (event.item_id) {\n toolCall.itemId = event.item_id;\n }\n if (event.call_id) {\n toolCall.callId = event.call_id;\n }\n toolCall.name = event.name;\n toolCall.arguments = event.arguments;\n break;\n }\n\n case 'response.reasoning_summary_text.delta': {\n const currentReasoning = state.reasoningByIndex.get(event.output_index) ?? '';\n state.reasoningByIndex.set(event.output_index, currentReasoning + event.delta);\n events.push({\n type: StreamEventType.ReasoningDelta,\n index: event.output_index,\n delta: { text: event.delta },\n });\n break;\n }\n\n case 'response.reasoning_summary_text.done':\n state.reasoningByIndex.set(event.output_index, event.text);\n break;\n\n case 'error':\n break;\n\n default:\n break;\n }\n\n return events;\n}\n\n/**\n * Builds a complete LLMResponse from accumulated streaming state.\n */\nexport function buildResponseFromState(state: StreamState): LLMResponse {\n const content: AssistantContent[] = [];\n let structuredData: unknown;\n\n const orderedReasoningEntries = [...state.reasoningByIndex.entries()].sort(\n ([leftIndex], [rightIndex]) => leftIndex - rightIndex\n );\n for (const [, reasoning] of orderedReasoningEntries) {\n if (reasoning) {\n content.push({ type: 'reasoning', text: reasoning });\n }\n }\n\n const orderedTextEntries = [...state.textByIndex.entries()].sort(\n ([leftIndex], [rightIndex]) => leftIndex - rightIndex\n );\n for (const [, text] of orderedTextEntries) {\n if (text) {\n content.push({ type: 'text', text });\n if (structuredData === undefined) {\n try {\n structuredData = JSON.parse(text);\n } catch {\n // Not JSON - expected for non-structured responses\n }\n }\n }\n }\n\n const toolCalls: ToolCall[] = [];\n const functionCallItems: Array<{\n id: string;\n call_id: string;\n name: string;\n arguments: string;\n }> = [];\n const orderedToolEntries = [...state.toolCalls.entries()].sort(\n ([leftIndex], [rightIndex]) => leftIndex - rightIndex\n );\n for (const [, toolCall] of orderedToolEntries) {\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 if (!name || !callId) {\n continue;\n }\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 responseId = state.id || generateId();\n const message = new AssistantMessage(\n content,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: responseId,\n metadata: {\n responses: {\n model: state.model,\n status: state.status,\n response_id: responseId,\n functionCallItems:\n functionCallItems.length > 0 ? functionCallItems : undefined,\n reasoningEncryptedContent: state.reasoningEncryptedContent,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.inputTokens + state.outputTokens,\n cacheReadTokens: state.cacheReadTokens,\n cacheWriteTokens: 0,\n };\n\n let stopReason = 'end_turn';\n if (state.status === 'completed') {\n stopReason = toolCalls.length > 0 ? 'tool_use' : 'end_turn';\n } else if (state.status === 'incomplete') {\n stopReason = state.incompleteReason === 'max_output_tokens' ? 'max_tokens' : 'end_turn';\n } else if (state.status === 'failed') {\n stopReason = 'error';\n }\n if (state.hadRefusal && stopReason !== 'error') {\n stopReason = 'content_filter';\n }\n\n return {\n message,\n usage,\n stopReason,\n data: structuredData,\n };\n}\n","/**\n * @fileoverview OpenResponses API Handler\n *\n * This module implements the LLM handler for any OpenResponses-compatible server.\n * The OpenResponses specification enables multi-provider, interoperable LLM interfaces\n * based on the OpenAI Responses API.\n *\n * The handler accepts a configurable host URL, making it work with:\n * - OpenAI (`https://api.openai.com/v1`)\n * - OpenRouter (`https://openrouter.ai/api/v1`)\n * - Self-hosted servers\n * - Any OpenResponses-compatible endpoint\n *\n * @see {@link https://www.openresponses.org OpenResponses Specification}\n * @module providers/responses/llm\n */\n\nimport type { BoundLLMModel, LLMRequest, LLMResponse, LLMStreamResult, LLMCapabilities } from '../../types/llm.ts';\nimport type { LLMHandler, LLMProvider } from '../../types/provider.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport { StreamEventType, objectDelta } from '../../types/stream.ts';\nimport { UPPError, ErrorCode, ModalityType } 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 { parseJsonResponse } from '../../http/json.ts';\nimport { toError } from '../../utils/error.ts';\nimport type {\n ResponsesParams,\n ResponsesResponse,\n ResponsesStreamEvent,\n ResponsesErrorEvent,\n} from './types.ts';\nimport {\n transformRequest,\n transformResponse,\n transformStreamEvent,\n createStreamState,\n buildResponseFromState,\n} from './transform.ts';\n\n/**\n * Internal context for handler configuration.\n * Stored on the model reference via providerConfig.\n */\ninterface ResponsesHandlerContext {\n host: string;\n apiKeyEnv: string;\n}\n\n/**\n * Capability declaration for the OpenResponses API.\n *\n * Defines what features are supported by this handler:\n * - Streaming: Real-time token-by-token response streaming via SSE\n * - Tools: Function calling support\n * - Structured Output: JSON schema-based response formatting\n * - Image Input: Vision capabilities for image understanding\n * - Document Input: File/document support\n * - Video Input: Video content support (per OpenResponses spec)\n * - Audio Input: Audio content support (as file upload)\n */\nconst RESPONSES_CAPABILITIES: LLMCapabilities = {\n streaming: true,\n tools: true,\n structuredOutput: true,\n imageInput: true,\n documentInput: true,\n videoInput: true,\n audioInput: true,\n};\n\n/**\n * Extracts the handler context from the request config.\n * The context is stored in providerConfig when creating the model reference.\n */\nfunction extractContext(request: LLMRequest<ResponsesParams>): ResponsesHandlerContext {\n const config = request.config;\n const responsesConfig = (config as { _responsesContext?: ResponsesHandlerContext })._responsesContext;\n\n if (!responsesConfig) {\n throw new UPPError(\n 'OpenResponses provider requires host configuration. Use responses(modelId, { host: \"...\" })',\n ErrorCode.InvalidRequest,\n 'responses',\n ModalityType.LLM\n );\n }\n\n return responsesConfig;\n}\n\n/**\n * Creates an LLM handler for OpenResponses-compatible servers.\n *\n * This factory function creates a handler that communicates with any\n * server implementing the OpenResponses specification. The host URL\n * and API key environment variable are configured via provider options.\n *\n * @returns An LLM handler configured for the OpenResponses API\n *\n * @example Basic usage with OpenAI\n * ```typescript\n * const handler = createLLMHandler();\n * // Host is configured via provider options when creating model reference\n * ```\n */\nexport function createLLMHandler(): LLMHandler<ResponsesParams> {\n let providerRef: LLMProvider<ResponsesParams> | null = null;\n\n return {\n _setProvider(provider: LLMProvider<ResponsesParams>) {\n providerRef = provider;\n },\n\n bind(modelId: string): BoundLLMModel<ResponsesParams> {\n if (!providerRef) {\n throw new UPPError(\n 'Provider reference not set. Handler must be used with createProvider() or have _setProvider called.',\n ErrorCode.InvalidRequest,\n 'responses',\n ModalityType.LLM\n );\n }\n\n const model: BoundLLMModel<ResponsesParams> = {\n modelId,\n capabilities: RESPONSES_CAPABILITIES,\n\n get provider(): LLMProvider<ResponsesParams> {\n return providerRef!;\n },\n\n async complete(request: LLMRequest<ResponsesParams>): Promise<LLMResponse> {\n const context = extractContext(request);\n const apiKey = await resolveApiKey(\n request.config,\n context.apiKeyEnv,\n 'responses',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? `${context.host}/responses`;\n const body = transformRequest(request, modelId);\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doFetch(\n baseUrl,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'responses',\n 'llm'\n );\n\n const data = await parseJsonResponse<ResponsesResponse>(response, 'responses', 'llm');\n\n if (data.status === 'failed') {\n const message = data.error?.message ?? 'Provider returned a failed response.';\n throw new UPPError(\n message,\n ErrorCode.ProviderError,\n 'responses',\n ModalityType.LLM\n );\n }\n\n return transformResponse(data);\n },\n\n stream(request: LLMRequest<ResponsesParams>): 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 context = extractContext(request);\n const apiKey = await resolveApiKey(\n request.config,\n context.apiKeyEnv,\n 'responses',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? `${context.host}/responses`;\n const body = transformRequest(request, modelId);\n body.stream = true;\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n Accept: 'text/event-stream',\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doStreamFetch(\n baseUrl,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'responses',\n 'llm'\n );\n\n if (!response.ok) {\n const error = await normalizeHttpError(response, 'responses', '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 ErrorCode.ProviderError,\n 'responses',\n ModalityType.LLM\n );\n responseReject(error);\n throw error;\n }\n\n for await (const data of parseSSEStream(response.body)) {\n if (data === '[DONE]') {\n continue;\n }\n\n if (typeof data === 'object' && data !== null) {\n const event = data as ResponsesStreamEvent;\n\n if (event.type === 'error') {\n const errorEvent = event as ResponsesErrorEvent;\n const error = new UPPError(\n errorEvent.error.message,\n ErrorCode.ProviderError,\n 'responses',\n ModalityType.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 if (request.structure && uppEvent.type === StreamEventType.TextDelta) {\n yield objectDelta(uppEvent.delta.text ?? '', uppEvent.index);\n }\n }\n }\n }\n\n responseResolve(buildResponseFromState(state));\n } catch (error) {\n const err = toError(error);\n responseReject(err);\n throw err;\n }\n }\n\n return {\n [Symbol.asyncIterator]() {\n return generateEvents();\n },\n response: responsePromise,\n };\n },\n };\n\n return model;\n },\n };\n}\n","/**\n * @fileoverview OpenResponses Provider\n *\n * Implements support for the OpenResponses specification - an open-source,\n * multi-provider standard for interoperable LLM interfaces.\n *\n * The OpenResponses provider allows connecting to any server implementing\n * the OpenResponses API specification, including OpenAI, OpenRouter,\n * and self-hosted implementations.\n *\n * @see {@link https://www.openresponses.org OpenResponses Specification}\n * @module providers/responses\n */\n\nimport type { Provider, ModelReference, ProviderConfig } from '../../types/provider.ts';\nimport { createProvider } from '../../core/provider.ts';\nimport { createLLMHandler } from './llm.ts';\nimport type { ResponsesProviderOptions } from './types.ts';\n\n/**\n * Extended config interface that includes the internal responses context.\n */\ninterface ResponsesProviderConfig extends ProviderConfig {\n _responsesContext?: {\n host: string;\n apiKeyEnv: string;\n };\n}\n\n/**\n * Type alias for the OpenResponses provider with its options.\n */\nexport type ResponsesProvider = Provider<ResponsesProviderOptions>;\n\n/**\n * OpenResponses provider singleton.\n *\n * Implements the OpenResponses specification for multi-provider, interoperable\n * LLM interfaces. This provider works with any server implementing the\n * OpenResponses API, including:\n *\n * - OpenAI (`https://api.openai.com/v1`)\n * - OpenRouter (`https://openrouter.ai/api/v1`)\n * - Self-hosted servers\n * - Any OpenResponses-compatible endpoint\n *\n * @example Using with OpenAI\n * ```typescript\n * import { responses } from './providers/responses';\n * import { llm } from './core/llm';\n *\n * const model = llm({\n * model: responses('gpt-5.2', { host: 'https://api.openai.com/v1' }),\n * params: { max_output_tokens: 1000 }\n * });\n *\n * const turn = await model.generate('Hello!');\n * console.log(turn.response.text);\n * ```\n *\n * @example Using with OpenRouter\n * ```typescript\n * const model = llm({\n * model: responses('openai/gpt-4o', {\n * host: 'https://openrouter.ai/api/v1',\n * apiKeyEnv: 'OPENROUTER_API_KEY'\n * }),\n * params: { max_output_tokens: 1000 }\n * });\n * ```\n *\n * @example Using with a self-hosted server\n * ```typescript\n * const model = llm({\n * model: responses('llama-3.3-70b', {\n * host: 'http://localhost:8080/v1',\n * apiKeyEnv: 'LOCAL_API_KEY'\n * }),\n * params: { max_output_tokens: 1000 }\n * });\n * ```\n *\n * @see {@link https://www.openresponses.org OpenResponses Specification}\n */\nexport const responses = createProvider<ResponsesProviderOptions>({\n name: 'responses',\n version: '1.0.0',\n handlers: {\n llm: createLLMHandler(),\n },\n createModelReference: (\n modelId: string,\n options: ResponsesProviderOptions | undefined,\n provider: Provider<ResponsesProviderOptions>\n ): ModelReference<ResponsesProviderOptions> => {\n if (!options?.host) {\n throw new Error(\n 'OpenResponses provider requires a host option. Usage: responses(\"model-id\", { host: \"https://api.example.com/v1\" })'\n );\n }\n\n const providerConfig: ResponsesProviderConfig = {\n _responsesContext: {\n host: options.host,\n apiKeyEnv: options.apiKeyEnv ?? 'OPENRESPONSES_API_KEY',\n },\n };\n\n return {\n modelId,\n provider,\n options,\n providerConfig,\n };\n },\n}) as ResponsesProvider;\n\nexport type {\n ResponsesProviderOptions,\n ResponsesParams,\n ResponsesRequest,\n ResponsesResponse,\n ResponsesStreamEvent,\n ResponsesUsage,\n ResponsesInputItem,\n ResponsesOutputItem,\n ResponsesContentPart,\n ResponsesFunctionTool,\n ResponsesBuiltInTool,\n ResponsesToolUnion,\n ResponsesHeaders,\n} from './types.ts';\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
import { K as KeyStrategy, c as ProviderConfig, f as Modality, R as RetryStrategyFactory } from './llm-BWLaTzzY.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* API key management strategies for load balancing and dynamic key selection.
|
|
5
|
+
* @module http/keys
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Creates a key strategy that distributes API requests across multiple keys
|
|
10
|
+
* using round-robin selection.
|
|
11
|
+
*
|
|
12
|
+
* Each call to `getKey()` returns the next key in sequence, cycling back to
|
|
13
|
+
* the first key after reaching the end. This provides even distribution of requests
|
|
14
|
+
* across all available keys, which is useful for:
|
|
15
|
+
* - Spreading rate limits across multiple API keys
|
|
16
|
+
* - Load balancing between different accounts
|
|
17
|
+
* - Maximizing throughput when multiple keys are available
|
|
18
|
+
*
|
|
19
|
+
* @param keys - Array of API keys to rotate through
|
|
20
|
+
* @returns A {@link KeyStrategy} that cycles through the provided keys
|
|
21
|
+
* @throws {Error} When the keys array is empty
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const keys = roundRobinKeys([
|
|
26
|
+
* 'sk-key-1',
|
|
27
|
+
* 'sk-key-2',
|
|
28
|
+
* 'sk-key-3'
|
|
29
|
+
* ]);
|
|
30
|
+
*
|
|
31
|
+
* keys.getKey(); // Returns 'sk-key-1'
|
|
32
|
+
* keys.getKey(); // Returns 'sk-key-2'
|
|
33
|
+
* keys.getKey(); // Returns 'sk-key-3'
|
|
34
|
+
* keys.getKey(); // Returns 'sk-key-1' (cycles back)
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
declare function roundRobinKeys(keys: string[]): KeyStrategy;
|
|
38
|
+
/**
|
|
39
|
+
* Creates a key strategy that selects API keys using weighted random probability.
|
|
40
|
+
*
|
|
41
|
+
* Each key is assigned a weight that determines its probability of being selected.
|
|
42
|
+
* Higher weights mean higher selection probability. This is useful for:
|
|
43
|
+
* - Preferring higher-tier API keys with better rate limits
|
|
44
|
+
* - Gradually migrating traffic between old and new keys
|
|
45
|
+
* - A/B testing different API accounts
|
|
46
|
+
* - Directing more traffic to keys with higher quotas
|
|
47
|
+
*
|
|
48
|
+
* The selection probability for each key is: weight / totalWeight
|
|
49
|
+
*
|
|
50
|
+
* @param keys - Array of key-weight pairs defining selection probabilities
|
|
51
|
+
* @returns A {@link KeyStrategy} that selects keys by weighted probability
|
|
52
|
+
* @throws {Error} When the keys array is empty
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* const keys = weightedKeys([
|
|
57
|
+
* { key: 'sk-premium', weight: 70 }, // 70% of requests
|
|
58
|
+
* { key: 'sk-standard', weight: 20 }, // 20% of requests
|
|
59
|
+
* { key: 'sk-backup', weight: 10 } // 10% of requests
|
|
60
|
+
* ]);
|
|
61
|
+
*
|
|
62
|
+
* // Configure provider with weighted key selection
|
|
63
|
+
* const provider = createOpenAI({
|
|
64
|
+
* apiKey: keys
|
|
65
|
+
* });
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
declare function weightedKeys(keys: Array<{
|
|
69
|
+
key: string;
|
|
70
|
+
weight: number;
|
|
71
|
+
}>): KeyStrategy;
|
|
72
|
+
/**
|
|
73
|
+
* Creates a key strategy that delegates key selection to a user-provided function,
|
|
74
|
+
* enabling advanced scenarios such as:
|
|
75
|
+
* - Fetching keys from a secrets manager (AWS Secrets Manager, HashiCorp Vault)
|
|
76
|
+
* - Rotating keys based on external state or configuration
|
|
77
|
+
* - Selecting keys based on request context or time of day
|
|
78
|
+
* - Implementing custom load balancing algorithms
|
|
79
|
+
*
|
|
80
|
+
* The selector function can be synchronous or asynchronous.
|
|
81
|
+
*
|
|
82
|
+
* @param selector - Function that returns an API key (sync or async)
|
|
83
|
+
* @returns A {@link KeyStrategy} that delegates to the selector function
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* // Fetch key from environment based on current mode
|
|
88
|
+
* const envKey = dynamicKey(() => {
|
|
89
|
+
* return process.env.NODE_ENV === 'production'
|
|
90
|
+
* ? process.env.PROD_API_KEY!
|
|
91
|
+
* : process.env.DEV_API_KEY!;
|
|
92
|
+
* });
|
|
93
|
+
*
|
|
94
|
+
* // Async key fetching from a secrets manager
|
|
95
|
+
* const vaultKey = dynamicKey(async () => {
|
|
96
|
+
* const secret = await vault.read('secret/openai');
|
|
97
|
+
* return secret.data.apiKey;
|
|
98
|
+
* });
|
|
99
|
+
*
|
|
100
|
+
* // Time-based key rotation
|
|
101
|
+
* const timedKey = dynamicKey(() => {
|
|
102
|
+
* const hour = new Date().getHours();
|
|
103
|
+
* return hour < 12 ? morningKey : afternoonKey;
|
|
104
|
+
* });
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
declare function dynamicKey(selector: () => string | Promise<string>): KeyStrategy;
|
|
108
|
+
/**
|
|
109
|
+
* Masks an API key for safe logging.
|
|
110
|
+
* Shows first 4 and last 4 characters with ellipsis, or '***' for short keys.
|
|
111
|
+
*
|
|
112
|
+
* @param key - The API key to mask
|
|
113
|
+
* @returns Masked key like "sk-ab...yz12" or "***" for short keys
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* maskApiKey('sk-abc123def456xyz789'); // 'sk-a...z789'
|
|
118
|
+
* maskApiKey('short'); // '***'
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
declare function maskApiKey(key: string): string;
|
|
122
|
+
/**
|
|
123
|
+
* Resolves an API key from provider configuration with multiple fallback options.
|
|
124
|
+
*
|
|
125
|
+
* This function handles various key specification methods in priority order:
|
|
126
|
+
* 1. Direct string key in config.apiKey
|
|
127
|
+
* 2. Function returning a key (sync or async) in config.apiKey
|
|
128
|
+
* 3. KeyStrategy instance in config.apiKey (roundRobinKeys, weightedKeys, dynamicKey)
|
|
129
|
+
* 4. Environment variable fallback (if envVar parameter is provided)
|
|
130
|
+
*
|
|
131
|
+
* @param config - Provider configuration containing the apiKey option
|
|
132
|
+
* @param envVar - Optional environment variable name to check as fallback
|
|
133
|
+
* @param provider - Provider identifier for error context (default: 'unknown')
|
|
134
|
+
* @param modality - Request modality for error context (default: 'llm')
|
|
135
|
+
* @returns The resolved API key string
|
|
136
|
+
*
|
|
137
|
+
* @throws {UPPError} AUTHENTICATION_FAILED - When no valid key is found
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```typescript
|
|
141
|
+
* // Direct key in config
|
|
142
|
+
* const key1 = await resolveApiKey({ apiKey: 'sk-...' }, 'OPENAI_API_KEY', 'openai');
|
|
143
|
+
*
|
|
144
|
+
* // Function-based key
|
|
145
|
+
* const key2 = await resolveApiKey({ apiKey: () => getKeyFromVault() }, undefined, 'anthropic');
|
|
146
|
+
*
|
|
147
|
+
* // KeyStrategy instance
|
|
148
|
+
* const key3 = await resolveApiKey({
|
|
149
|
+
* apiKey: roundRobinKeys(['sk-1', 'sk-2', 'sk-3'])
|
|
150
|
+
* }, 'OPENAI_API_KEY', 'openai');
|
|
151
|
+
*
|
|
152
|
+
* // Environment variable fallback
|
|
153
|
+
* const key4 = await resolveApiKey({}, 'ANTHROPIC_API_KEY', 'anthropic');
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
declare function resolveApiKey(config: ProviderConfig, envVar?: string, provider?: string, modality?: Modality): Promise<string>;
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Retry strategy factories for handling transient failures in HTTP requests.
|
|
160
|
+
*
|
|
161
|
+
* All strategies use the factory pattern to ensure each request gets an
|
|
162
|
+
* isolated instance, preventing state sharing between concurrent requests.
|
|
163
|
+
*
|
|
164
|
+
* @module http/retry
|
|
165
|
+
*/
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Options for exponential backoff retry strategy.
|
|
169
|
+
*/
|
|
170
|
+
interface ExponentialBackoffOptions {
|
|
171
|
+
/** Maximum number of retry attempts (default: 3) */
|
|
172
|
+
maxAttempts?: number;
|
|
173
|
+
/** Initial delay in milliseconds (default: 1000) */
|
|
174
|
+
baseDelay?: number;
|
|
175
|
+
/** Maximum delay cap in milliseconds (default: 30000) */
|
|
176
|
+
maxDelay?: number;
|
|
177
|
+
/** Whether to add random jitter to delays (default: true) */
|
|
178
|
+
jitter?: boolean;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Creates an exponential backoff retry strategy.
|
|
182
|
+
*
|
|
183
|
+
* The delay between retries doubles with each attempt, helping to:
|
|
184
|
+
* - Avoid overwhelming servers during outages
|
|
185
|
+
* - Reduce thundering herd effects when many clients retry simultaneously
|
|
186
|
+
* - Give transient issues time to resolve
|
|
187
|
+
*
|
|
188
|
+
* Delay formula: min(baseDelay * 2^(attempt-1), maxDelay)
|
|
189
|
+
* With jitter: delay * random(0.5, 1.0)
|
|
190
|
+
*
|
|
191
|
+
* Only retries on transient errors: RATE_LIMITED, NETWORK_ERROR, TIMEOUT, PROVIDER_ERROR
|
|
192
|
+
*
|
|
193
|
+
* @param options - Configuration options
|
|
194
|
+
* @returns A factory that creates fresh strategy instances per request
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* ```typescript
|
|
198
|
+
* // Default configuration (3 retries, 1s base, 30s max, jitter enabled)
|
|
199
|
+
* const retry = exponentialBackoff();
|
|
200
|
+
*
|
|
201
|
+
* // Custom configuration
|
|
202
|
+
* const customRetry = exponentialBackoff({
|
|
203
|
+
* maxAttempts: 5, // Up to 5 retry attempts
|
|
204
|
+
* baseDelay: 500, // Start with 500ms delay
|
|
205
|
+
* maxDelay: 60000, // Cap at 60 seconds
|
|
206
|
+
* jitter: false // Disable random jitter
|
|
207
|
+
* });
|
|
208
|
+
*
|
|
209
|
+
* // Use with provider
|
|
210
|
+
* const provider = createOpenAI({
|
|
211
|
+
* retryStrategy: customRetry
|
|
212
|
+
* });
|
|
213
|
+
* ```
|
|
214
|
+
*/
|
|
215
|
+
declare function exponentialBackoff(options?: ExponentialBackoffOptions): RetryStrategyFactory;
|
|
216
|
+
/**
|
|
217
|
+
* Options for linear backoff retry strategy.
|
|
218
|
+
*/
|
|
219
|
+
interface LinearBackoffOptions {
|
|
220
|
+
/** Maximum number of retry attempts (default: 3) */
|
|
221
|
+
maxAttempts?: number;
|
|
222
|
+
/** Base delay multiplier in milliseconds (default: 1000) */
|
|
223
|
+
delay?: number;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Creates a linear backoff retry strategy.
|
|
227
|
+
*
|
|
228
|
+
* Unlike exponential backoff, linear backoff increases delays at a constant rate:
|
|
229
|
+
* - Attempt 1: delay * 1 (e.g., 1000ms)
|
|
230
|
+
* - Attempt 2: delay * 2 (e.g., 2000ms)
|
|
231
|
+
* - Attempt 3: delay * 3 (e.g., 3000ms)
|
|
232
|
+
*
|
|
233
|
+
* This strategy is simpler and more predictable than exponential backoff,
|
|
234
|
+
* suitable for scenarios where gradual delay increase is preferred over
|
|
235
|
+
* aggressive backoff.
|
|
236
|
+
*
|
|
237
|
+
* Only retries on transient errors: RATE_LIMITED, NETWORK_ERROR, TIMEOUT, PROVIDER_ERROR
|
|
238
|
+
*
|
|
239
|
+
* @param options - Configuration options
|
|
240
|
+
* @returns A factory that creates fresh strategy instances per request
|
|
241
|
+
*
|
|
242
|
+
* @example
|
|
243
|
+
* ```typescript
|
|
244
|
+
* // Default configuration (3 retries, 1s delay increment)
|
|
245
|
+
* const retry = linearBackoff();
|
|
246
|
+
*
|
|
247
|
+
* // Custom configuration
|
|
248
|
+
* const customRetry = linearBackoff({
|
|
249
|
+
* maxAttempts: 4, // Up to 4 retry attempts
|
|
250
|
+
* delay: 2000 // 2s, 4s, 6s, 8s delays
|
|
251
|
+
* });
|
|
252
|
+
*
|
|
253
|
+
* // Use with provider
|
|
254
|
+
* const provider = createAnthropic({
|
|
255
|
+
* retryStrategy: customRetry
|
|
256
|
+
* });
|
|
257
|
+
* ```
|
|
258
|
+
*/
|
|
259
|
+
declare function linearBackoff(options?: LinearBackoffOptions): RetryStrategyFactory;
|
|
260
|
+
/**
|
|
261
|
+
* Creates a no-retry strategy that fails immediately on any error.
|
|
262
|
+
*
|
|
263
|
+
* Use this strategy when:
|
|
264
|
+
* - Retries are handled at a higher level in your application
|
|
265
|
+
* - You want immediate failure feedback
|
|
266
|
+
* - The operation is not idempotent
|
|
267
|
+
* - Time sensitivity requires fast failure
|
|
268
|
+
*
|
|
269
|
+
* @returns A factory that creates no-retry strategy instances
|
|
270
|
+
*
|
|
271
|
+
* @example
|
|
272
|
+
* ```typescript
|
|
273
|
+
* // Disable retries for time-sensitive operations
|
|
274
|
+
* const provider = createOpenAI({
|
|
275
|
+
* retryStrategy: noRetry()
|
|
276
|
+
* });
|
|
277
|
+
* ```
|
|
278
|
+
*/
|
|
279
|
+
declare function noRetry(): RetryStrategyFactory;
|
|
280
|
+
/**
|
|
281
|
+
* Options for retry-after strategy.
|
|
282
|
+
*/
|
|
283
|
+
interface RetryAfterStrategyOptions {
|
|
284
|
+
/** Maximum number of retry attempts (default: 3) */
|
|
285
|
+
maxAttempts?: number;
|
|
286
|
+
/** Delay in ms when no Retry-After header is present (default: 5000) */
|
|
287
|
+
fallbackDelay?: number;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Creates a retry strategy that respects server-provided Retry-After headers.
|
|
291
|
+
*
|
|
292
|
+
* When servers return a 429 (Too Many Requests) response, they often include
|
|
293
|
+
* a Retry-After header indicating when the client should retry. This strategy
|
|
294
|
+
* uses that information for precise retry timing.
|
|
295
|
+
*
|
|
296
|
+
* Benefits over fixed backoff strategies:
|
|
297
|
+
* - Follows server recommendations for optimal retry timing
|
|
298
|
+
* - Avoids retrying too early and wasting requests
|
|
299
|
+
* - Adapts to dynamic rate limit windows
|
|
300
|
+
*
|
|
301
|
+
* If no Retry-After header is provided, falls back to a configurable delay.
|
|
302
|
+
* Only retries on RATE_LIMITED errors.
|
|
303
|
+
*
|
|
304
|
+
* @param options - Configuration options
|
|
305
|
+
* @returns A factory that creates fresh strategy instances per request
|
|
306
|
+
*
|
|
307
|
+
* @example
|
|
308
|
+
* ```typescript
|
|
309
|
+
* // Use server-recommended retry timing
|
|
310
|
+
* const retryAfter = retryAfterStrategy({
|
|
311
|
+
* maxAttempts: 5, // Retry up to 5 times
|
|
312
|
+
* fallbackDelay: 10000 // 10s fallback if no header
|
|
313
|
+
* });
|
|
314
|
+
*
|
|
315
|
+
* const provider = createOpenAI({
|
|
316
|
+
* retryStrategy: retryAfter
|
|
317
|
+
* });
|
|
318
|
+
* ```
|
|
319
|
+
*/
|
|
320
|
+
declare function retryAfterStrategy(options?: RetryAfterStrategyOptions): RetryStrategyFactory;
|
|
321
|
+
|
|
322
|
+
export { type ExponentialBackoffOptions as E, type LinearBackoffOptions as L, type RetryAfterStrategyOptions as R, roundRobinKeys as a, retryAfterStrategy as b, dynamicKey as d, exponentialBackoff as e, linearBackoff as l, maskApiKey as m, noRetry as n, resolveApiKey as r, weightedKeys as w };
|