@mariozechner/pi-ai 0.48.0 → 0.49.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +23 -2
  2. package/dist/index.d.ts +0 -1
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +0 -1
  5. package/dist/index.js.map +1 -1
  6. package/dist/models.generated.d.ts +0 -17
  7. package/dist/models.generated.d.ts.map +1 -1
  8. package/dist/models.generated.js +17 -34
  9. package/dist/models.generated.js.map +1 -1
  10. package/dist/providers/amazon-bedrock.d.ts.map +1 -1
  11. package/dist/providers/amazon-bedrock.js +9 -7
  12. package/dist/providers/amazon-bedrock.js.map +1 -1
  13. package/dist/providers/anthropic.d.ts.map +1 -1
  14. package/dist/providers/anthropic.js +33 -19
  15. package/dist/providers/anthropic.js.map +1 -1
  16. package/dist/providers/google-gemini-cli.d.ts.map +1 -1
  17. package/dist/providers/google-gemini-cli.js +2 -28
  18. package/dist/providers/google-gemini-cli.js.map +1 -1
  19. package/dist/providers/google-shared.d.ts +1 -1
  20. package/dist/providers/google-shared.d.ts.map +1 -1
  21. package/dist/providers/google-shared.js +8 -3
  22. package/dist/providers/google-shared.js.map +1 -1
  23. package/dist/providers/google-vertex.d.ts.map +1 -1
  24. package/dist/providers/google-vertex.js +1 -0
  25. package/dist/providers/google-vertex.js.map +1 -1
  26. package/dist/providers/google.d.ts.map +1 -1
  27. package/dist/providers/google.js +1 -0
  28. package/dist/providers/google.js.map +1 -1
  29. package/dist/providers/openai-codex-responses.d.ts.map +1 -1
  30. package/dist/providers/openai-codex-responses.js +21 -26
  31. package/dist/providers/openai-codex-responses.js.map +1 -1
  32. package/dist/providers/openai-completions.d.ts.map +1 -1
  33. package/dist/providers/openai-completions.js +17 -7
  34. package/dist/providers/openai-completions.js.map +1 -1
  35. package/dist/providers/openai-responses.d.ts.map +1 -1
  36. package/dist/providers/openai-responses.js +36 -3
  37. package/dist/providers/openai-responses.js.map +1 -1
  38. package/dist/providers/transform-messages.d.ts +7 -2
  39. package/dist/providers/transform-messages.d.ts.map +1 -1
  40. package/dist/providers/transform-messages.js +37 -29
  41. package/dist/providers/transform-messages.js.map +1 -1
  42. package/dist/stream.d.ts.map +1 -1
  43. package/dist/stream.js +48 -19
  44. package/dist/stream.js.map +1 -1
  45. package/dist/types.d.ts +13 -4
  46. package/dist/types.d.ts.map +1 -1
  47. package/dist/types.js.map +1 -1
  48. package/package.json +1 -1
  49. package/dist/constants.d.ts +0 -6
  50. package/dist/constants.d.ts.map +0 -1
  51. package/dist/constants.js +0 -14
  52. package/dist/constants.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"openai-responses.js","sourceRoot":"","sources":["../../src/providers/openai-responses.ts"],"names":[],"mappings":"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","sourcesContent":["import OpenAI from \"openai\";\nimport type {\n\tTool as OpenAITool,\n\tResponseCreateParamsStreaming,\n\tResponseFunctionToolCall,\n\tResponseInput,\n\tResponseInputContent,\n\tResponseInputImage,\n\tResponseInputText,\n\tResponseOutputMessage,\n\tResponseReasoningItem,\n} from \"openai/resources/responses/responses.js\";\nimport { calculateCost } from \"../models.js\";\nimport { getEnvApiKey } from \"../stream.js\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tContext,\n\tModel,\n\tStopReason,\n\tStreamFunction,\n\tStreamOptions,\n\tTextContent,\n\tThinkingContent,\n\tTool,\n\tToolCall,\n\tUsage,\n} from \"../types.js\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.js\";\nimport { parseStreamingJson } from \"../utils/json-parse.js\";\nimport { sanitizeSurrogates } from \"../utils/sanitize-unicode.js\";\nimport { transformMessages } from \"./transform-messages.js\";\n\n/** Fast deterministic hash to shorten long strings */\nfunction shortHash(str: string): string {\n\tlet h1 = 0xdeadbeef;\n\tlet h2 = 0x41c6ce57;\n\tfor (let i = 0; i < str.length; i++) {\n\t\tconst ch = str.charCodeAt(i);\n\t\th1 = Math.imul(h1 ^ ch, 2654435761);\n\t\th2 = Math.imul(h2 ^ ch, 1597334677);\n\t}\n\th1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);\n\th2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);\n\treturn (h2 >>> 0).toString(36) + (h1 >>> 0).toString(36);\n}\n\n// OpenAI Responses-specific options\nexport interface OpenAIResponsesOptions extends StreamOptions {\n\treasoningEffort?: \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\n\treasoningSummary?: \"auto\" | \"detailed\" | \"concise\" | null;\n\tserviceTier?: ResponseCreateParamsStreaming[\"service_tier\"];\n}\n\n/**\n * Generate function for OpenAI Responses API\n */\nexport const streamOpenAIResponses: StreamFunction<\"openai-responses\"> = (\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\toptions?: OpenAIResponsesOptions,\n): AssistantMessageEventStream => {\n\tconst stream = new AssistantMessageEventStream();\n\n\t// Start async processing\n\t(async () => {\n\t\tconst output: AssistantMessage = {\n\t\t\trole: \"assistant\",\n\t\t\tcontent: [],\n\t\t\tapi: \"openai-responses\" as Api,\n\t\t\tprovider: model.provider,\n\t\t\tmodel: model.id,\n\t\t\tusage: {\n\t\t\t\tinput: 0,\n\t\t\t\toutput: 0,\n\t\t\t\tcacheRead: 0,\n\t\t\t\tcacheWrite: 0,\n\t\t\t\ttotalTokens: 0,\n\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t},\n\t\t\tstopReason: \"stop\",\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\n\t\ttry {\n\t\t\t// Create OpenAI client\n\t\t\tconst apiKey = options?.apiKey || getEnvApiKey(model.provider) || \"\";\n\t\t\tconst client = createClient(model, context, apiKey);\n\t\t\tconst params = buildParams(model, context, options);\n\t\t\tconst openaiStream = await client.responses.create(\n\t\t\t\tparams,\n\t\t\t\toptions?.signal ? { signal: options.signal } : undefined,\n\t\t\t);\n\t\t\tstream.push({ type: \"start\", partial: output });\n\n\t\t\tlet currentItem: ResponseReasoningItem | ResponseOutputMessage | ResponseFunctionToolCall | null = null;\n\t\t\tlet currentBlock: ThinkingContent | TextContent | (ToolCall & { partialJson: string }) | null = null;\n\t\t\tconst blocks = output.content;\n\t\t\tconst blockIndex = () => blocks.length - 1;\n\n\t\t\tfor await (const event of openaiStream) {\n\t\t\t\t// Handle output item start\n\t\t\t\tif (event.type === \"response.output_item.added\") {\n\t\t\t\t\tconst item = event.item;\n\t\t\t\t\tif (item.type === \"reasoning\") {\n\t\t\t\t\t\tcurrentItem = item;\n\t\t\t\t\t\tcurrentBlock = { type: \"thinking\", thinking: \"\" };\n\t\t\t\t\t\toutput.content.push(currentBlock);\n\t\t\t\t\t\tstream.push({ type: \"thinking_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t\t\t} else if (item.type === \"message\") {\n\t\t\t\t\t\tcurrentItem = item;\n\t\t\t\t\t\tcurrentBlock = { type: \"text\", text: \"\" };\n\t\t\t\t\t\toutput.content.push(currentBlock);\n\t\t\t\t\t\tstream.push({ type: \"text_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t\t\t} else if (item.type === \"function_call\") {\n\t\t\t\t\t\tcurrentItem = item;\n\t\t\t\t\t\tcurrentBlock = {\n\t\t\t\t\t\t\ttype: \"toolCall\",\n\t\t\t\t\t\t\tid: `${item.call_id}|${item.id}`,\n\t\t\t\t\t\t\tname: item.name,\n\t\t\t\t\t\t\targuments: {},\n\t\t\t\t\t\t\tpartialJson: item.arguments || \"\",\n\t\t\t\t\t\t};\n\t\t\t\t\t\toutput.content.push(currentBlock);\n\t\t\t\t\t\tstream.push({ type: \"toolcall_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Handle reasoning summary deltas\n\t\t\t\telse if (event.type === \"response.reasoning_summary_part.added\") {\n\t\t\t\t\tif (currentItem && currentItem.type === \"reasoning\") {\n\t\t\t\t\t\tcurrentItem.summary = currentItem.summary || [];\n\t\t\t\t\t\tcurrentItem.summary.push(event.part);\n\t\t\t\t\t}\n\t\t\t\t} else if (event.type === \"response.reasoning_summary_text.delta\") {\n\t\t\t\t\tif (\n\t\t\t\t\t\tcurrentItem &&\n\t\t\t\t\t\tcurrentItem.type === \"reasoning\" &&\n\t\t\t\t\t\tcurrentBlock &&\n\t\t\t\t\t\tcurrentBlock.type === \"thinking\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tcurrentItem.summary = currentItem.summary || [];\n\t\t\t\t\t\tconst lastPart = currentItem.summary[currentItem.summary.length - 1];\n\t\t\t\t\t\tif (lastPart) {\n\t\t\t\t\t\t\tcurrentBlock.thinking += event.delta;\n\t\t\t\t\t\t\tlastPart.text += event.delta;\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"thinking_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\tdelta: event.delta,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Add a new line between summary parts (hack...)\n\t\t\t\telse if (event.type === \"response.reasoning_summary_part.done\") {\n\t\t\t\t\tif (\n\t\t\t\t\t\tcurrentItem &&\n\t\t\t\t\t\tcurrentItem.type === \"reasoning\" &&\n\t\t\t\t\t\tcurrentBlock &&\n\t\t\t\t\t\tcurrentBlock.type === \"thinking\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tcurrentItem.summary = currentItem.summary || [];\n\t\t\t\t\t\tconst lastPart = currentItem.summary[currentItem.summary.length - 1];\n\t\t\t\t\t\tif (lastPart) {\n\t\t\t\t\t\t\tcurrentBlock.thinking += \"\\n\\n\";\n\t\t\t\t\t\t\tlastPart.text += \"\\n\\n\";\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"thinking_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\tdelta: \"\\n\\n\",\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Handle text output deltas\n\t\t\t\telse if (event.type === \"response.content_part.added\") {\n\t\t\t\t\tif (currentItem && currentItem.type === \"message\") {\n\t\t\t\t\t\tcurrentItem.content = currentItem.content || [];\n\t\t\t\t\t\t// Filter out ReasoningText, only accept output_text and refusal\n\t\t\t\t\t\tif (event.part.type === \"output_text\" || event.part.type === \"refusal\") {\n\t\t\t\t\t\t\tcurrentItem.content.push(event.part);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (event.type === \"response.output_text.delta\") {\n\t\t\t\t\tif (currentItem && currentItem.type === \"message\" && currentBlock && currentBlock.type === \"text\") {\n\t\t\t\t\t\tconst lastPart = currentItem.content[currentItem.content.length - 1];\n\t\t\t\t\t\tif (lastPart && lastPart.type === \"output_text\") {\n\t\t\t\t\t\t\tcurrentBlock.text += event.delta;\n\t\t\t\t\t\t\tlastPart.text += event.delta;\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"text_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\tdelta: event.delta,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (event.type === \"response.refusal.delta\") {\n\t\t\t\t\tif (currentItem && currentItem.type === \"message\" && currentBlock && currentBlock.type === \"text\") {\n\t\t\t\t\t\tconst lastPart = currentItem.content[currentItem.content.length - 1];\n\t\t\t\t\t\tif (lastPart && lastPart.type === \"refusal\") {\n\t\t\t\t\t\t\tcurrentBlock.text += event.delta;\n\t\t\t\t\t\t\tlastPart.refusal += event.delta;\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"text_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\tdelta: event.delta,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Handle function call argument deltas\n\t\t\t\telse if (event.type === \"response.function_call_arguments.delta\") {\n\t\t\t\t\tif (\n\t\t\t\t\t\tcurrentItem &&\n\t\t\t\t\t\tcurrentItem.type === \"function_call\" &&\n\t\t\t\t\t\tcurrentBlock &&\n\t\t\t\t\t\tcurrentBlock.type === \"toolCall\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tcurrentBlock.partialJson += event.delta;\n\t\t\t\t\t\tcurrentBlock.arguments = parseStreamingJson(currentBlock.partialJson);\n\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\ttype: \"toolcall_delta\",\n\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\tdelta: event.delta,\n\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Handle output item completion\n\t\t\t\telse if (event.type === \"response.output_item.done\") {\n\t\t\t\t\tconst item = event.item;\n\n\t\t\t\t\tif (item.type === \"reasoning\" && currentBlock && currentBlock.type === \"thinking\") {\n\t\t\t\t\t\tcurrentBlock.thinking = item.summary?.map((s) => s.text).join(\"\\n\\n\") || \"\";\n\t\t\t\t\t\tcurrentBlock.thinkingSignature = JSON.stringify(item);\n\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\ttype: \"thinking_end\",\n\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\tcontent: currentBlock.thinking,\n\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tcurrentBlock = null;\n\t\t\t\t\t} else if (item.type === \"message\" && currentBlock && currentBlock.type === \"text\") {\n\t\t\t\t\t\tcurrentBlock.text = item.content.map((c) => (c.type === \"output_text\" ? c.text : c.refusal)).join(\"\");\n\t\t\t\t\t\tcurrentBlock.textSignature = item.id;\n\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\ttype: \"text_end\",\n\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\tcontent: currentBlock.text,\n\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tcurrentBlock = null;\n\t\t\t\t\t} else if (item.type === \"function_call\") {\n\t\t\t\t\t\tconst toolCall: ToolCall = {\n\t\t\t\t\t\t\ttype: \"toolCall\",\n\t\t\t\t\t\t\tid: `${item.call_id}|${item.id}`,\n\t\t\t\t\t\t\tname: item.name,\n\t\t\t\t\t\t\targuments: JSON.parse(item.arguments),\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tstream.push({ type: \"toolcall_end\", contentIndex: blockIndex(), toolCall, partial: output });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Handle completion\n\t\t\t\telse if (event.type === \"response.completed\") {\n\t\t\t\t\tconst response = event.response;\n\t\t\t\t\tif (response?.usage) {\n\t\t\t\t\t\tconst cachedTokens = response.usage.input_tokens_details?.cached_tokens || 0;\n\t\t\t\t\t\toutput.usage = {\n\t\t\t\t\t\t\t// OpenAI includes cached tokens in input_tokens, so subtract to get non-cached input\n\t\t\t\t\t\t\tinput: (response.usage.input_tokens || 0) - cachedTokens,\n\t\t\t\t\t\t\toutput: response.usage.output_tokens || 0,\n\t\t\t\t\t\t\tcacheRead: cachedTokens,\n\t\t\t\t\t\t\tcacheWrite: 0,\n\t\t\t\t\t\t\ttotalTokens: response.usage.total_tokens || 0,\n\t\t\t\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\tcalculateCost(model, output.usage);\n\t\t\t\t\tapplyServiceTierPricing(output.usage, response?.service_tier ?? options?.serviceTier);\n\t\t\t\t\t// Map status to stop reason\n\t\t\t\t\toutput.stopReason = mapStopReason(response?.status);\n\t\t\t\t\tif (output.content.some((b) => b.type === \"toolCall\") && output.stopReason === \"stop\") {\n\t\t\t\t\t\toutput.stopReason = \"toolUse\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Handle errors\n\t\t\t\telse if (event.type === \"error\") {\n\t\t\t\t\tthrow new Error(`Error Code ${event.code}: ${event.message}` || \"Unknown error\");\n\t\t\t\t} else if (event.type === \"response.failed\") {\n\t\t\t\t\tthrow new Error(\"Unknown error\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (options?.signal?.aborted) {\n\t\t\t\tthrow new Error(\"Request was aborted\");\n\t\t\t}\n\n\t\t\tif (output.stopReason === \"aborted\" || output.stopReason === \"error\") {\n\t\t\t\tthrow new Error(\"An unkown error ocurred\");\n\t\t\t}\n\n\t\t\tstream.push({ type: \"done\", reason: output.stopReason, message: output });\n\t\t\tstream.end();\n\t\t} catch (error) {\n\t\t\tfor (const block of output.content) delete (block as any).index;\n\t\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\t\toutput.errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n\t\t\tstream.push({ type: \"error\", reason: output.stopReason, error: output });\n\t\t\tstream.end();\n\t\t}\n\t})();\n\n\treturn stream;\n};\n\nfunction createClient(model: Model<\"openai-responses\">, context: Context, apiKey?: string) {\n\tif (!apiKey) {\n\t\tif (!process.env.OPENAI_API_KEY) {\n\t\t\tthrow new Error(\n\t\t\t\t\"OpenAI API key is required. Set OPENAI_API_KEY environment variable or pass it as an argument.\",\n\t\t\t);\n\t\t}\n\t\tapiKey = process.env.OPENAI_API_KEY;\n\t}\n\n\tconst headers = { ...model.headers };\n\tif (model.provider === \"github-copilot\") {\n\t\t// Copilot expects X-Initiator to indicate whether the request is user-initiated\n\t\t// or agent-initiated (e.g. follow-up after assistant/tool messages). If there is\n\t\t// no prior message, default to user-initiated.\n\t\tconst messages = context.messages || [];\n\t\tconst lastMessage = messages[messages.length - 1];\n\t\tconst isAgentCall = lastMessage ? lastMessage.role !== \"user\" : false;\n\t\theaders[\"X-Initiator\"] = isAgentCall ? \"agent\" : \"user\";\n\t\theaders[\"Openai-Intent\"] = \"conversation-edits\";\n\n\t\t// Copilot requires this header when sending images\n\t\tconst hasImages = messages.some((msg) => {\n\t\t\tif (msg.role === \"user\" && Array.isArray(msg.content)) {\n\t\t\t\treturn msg.content.some((c) => c.type === \"image\");\n\t\t\t}\n\t\t\tif (msg.role === \"toolResult\" && Array.isArray(msg.content)) {\n\t\t\t\treturn msg.content.some((c) => c.type === \"image\");\n\t\t\t}\n\t\t\treturn false;\n\t\t});\n\t\tif (hasImages) {\n\t\t\theaders[\"Copilot-Vision-Request\"] = \"true\";\n\t\t}\n\t}\n\n\treturn new OpenAI({\n\t\tapiKey,\n\t\tbaseURL: model.baseUrl,\n\t\tdangerouslyAllowBrowser: true,\n\t\tdefaultHeaders: headers,\n\t});\n}\n\nfunction buildParams(model: Model<\"openai-responses\">, context: Context, options?: OpenAIResponsesOptions) {\n\tconst messages = convertMessages(model, context);\n\n\tconst params: ResponseCreateParamsStreaming = {\n\t\tmodel: model.id,\n\t\tinput: messages,\n\t\tstream: true,\n\t\tprompt_cache_key: options?.sessionId,\n\t};\n\n\tif (options?.maxTokens) {\n\t\tparams.max_output_tokens = options?.maxTokens;\n\t}\n\n\tif (options?.temperature !== undefined) {\n\t\tparams.temperature = options?.temperature;\n\t}\n\n\tif (options?.serviceTier !== undefined) {\n\t\tparams.service_tier = options.serviceTier;\n\t}\n\n\tif (context.tools) {\n\t\tparams.tools = convertTools(context.tools);\n\t}\n\n\tif (model.reasoning) {\n\t\tif (options?.reasoningEffort || options?.reasoningSummary) {\n\t\t\tparams.reasoning = {\n\t\t\t\teffort: options?.reasoningEffort || \"medium\",\n\t\t\t\tsummary: options?.reasoningSummary || \"auto\",\n\t\t\t};\n\t\t\tparams.include = [\"reasoning.encrypted_content\"];\n\t\t} else {\n\t\t\tif (model.name.startsWith(\"gpt-5\")) {\n\t\t\t\t// Jesus Christ, see https://community.openai.com/t/need-reasoning-false-option-for-gpt-5/1351588/7\n\t\t\t\tmessages.push({\n\t\t\t\t\trole: \"developer\",\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"input_text\",\n\t\t\t\t\t\t\ttext: \"# Juice: 0 !important\",\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn params;\n}\n\nfunction convertMessages(model: Model<\"openai-responses\">, context: Context): ResponseInput {\n\tconst messages: ResponseInput = [];\n\n\tconst transformedMessages = transformMessages(context.messages, model);\n\n\tif (context.systemPrompt) {\n\t\tconst role = model.reasoning ? \"developer\" : \"system\";\n\t\tmessages.push({\n\t\t\trole,\n\t\t\tcontent: sanitizeSurrogates(context.systemPrompt),\n\t\t});\n\t}\n\n\tlet msgIndex = 0;\n\tfor (const msg of transformedMessages) {\n\t\tif (msg.role === \"user\") {\n\t\t\tif (typeof msg.content === \"string\") {\n\t\t\t\tmessages.push({\n\t\t\t\t\trole: \"user\",\n\t\t\t\t\tcontent: [{ type: \"input_text\", text: sanitizeSurrogates(msg.content) }],\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst content: ResponseInputContent[] = msg.content.map((item): ResponseInputContent => {\n\t\t\t\t\tif (item.type === \"text\") {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: \"input_text\",\n\t\t\t\t\t\t\ttext: sanitizeSurrogates(item.text),\n\t\t\t\t\t\t} satisfies ResponseInputText;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: \"input_image\",\n\t\t\t\t\t\t\tdetail: \"auto\",\n\t\t\t\t\t\t\timage_url: `data:${item.mimeType};base64,${item.data}`,\n\t\t\t\t\t\t} satisfies ResponseInputImage;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tconst filteredContent = !model.input.includes(\"image\")\n\t\t\t\t\t? content.filter((c) => c.type !== \"input_image\")\n\t\t\t\t\t: content;\n\t\t\t\tif (filteredContent.length === 0) continue;\n\t\t\t\tmessages.push({\n\t\t\t\t\trole: \"user\",\n\t\t\t\t\tcontent: filteredContent,\n\t\t\t\t});\n\t\t\t}\n\t\t} else if (msg.role === \"assistant\") {\n\t\t\tconst output: ResponseInput = [];\n\n\t\t\tfor (const block of msg.content) {\n\t\t\t\t// Do not submit thinking blocks if the completion had an error (i.e. abort)\n\t\t\t\tif (block.type === \"thinking\" && msg.stopReason !== \"error\") {\n\t\t\t\t\tif (block.thinkingSignature) {\n\t\t\t\t\t\tconst reasoningItem = JSON.parse(block.thinkingSignature);\n\t\t\t\t\t\toutput.push(reasoningItem);\n\t\t\t\t\t}\n\t\t\t\t} else if (block.type === \"text\") {\n\t\t\t\t\tconst textBlock = block as TextContent;\n\t\t\t\t\t// OpenAI requires id to be max 64 characters\n\t\t\t\t\tlet msgId = textBlock.textSignature;\n\t\t\t\t\tif (!msgId) {\n\t\t\t\t\t\tmsgId = `msg_${msgIndex}`;\n\t\t\t\t\t} else if (msgId.length > 64) {\n\t\t\t\t\t\tmsgId = `msg_${shortHash(msgId)}`;\n\t\t\t\t\t}\n\t\t\t\t\toutput.push({\n\t\t\t\t\t\ttype: \"message\",\n\t\t\t\t\t\trole: \"assistant\",\n\t\t\t\t\t\tcontent: [{ type: \"output_text\", text: sanitizeSurrogates(textBlock.text), annotations: [] }],\n\t\t\t\t\t\tstatus: \"completed\",\n\t\t\t\t\t\tid: msgId,\n\t\t\t\t\t} satisfies ResponseOutputMessage);\n\t\t\t\t\t// Do not submit toolcall blocks if the completion had an error (i.e. abort)\n\t\t\t\t} else if (block.type === \"toolCall\" && msg.stopReason !== \"error\") {\n\t\t\t\t\tconst toolCall = block as ToolCall;\n\t\t\t\t\toutput.push({\n\t\t\t\t\t\ttype: \"function_call\",\n\t\t\t\t\t\tid: toolCall.id.split(\"|\")[1],\n\t\t\t\t\t\tcall_id: toolCall.id.split(\"|\")[0],\n\t\t\t\t\t\tname: toolCall.name,\n\t\t\t\t\t\targuments: JSON.stringify(toolCall.arguments),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (output.length === 0) continue;\n\t\t\tmessages.push(...output);\n\t\t} else if (msg.role === \"toolResult\") {\n\t\t\t// Extract text and image content\n\t\t\tconst textResult = msg.content\n\t\t\t\t.filter((c) => c.type === \"text\")\n\t\t\t\t.map((c) => (c as any).text)\n\t\t\t\t.join(\"\\n\");\n\t\t\tconst hasImages = msg.content.some((c) => c.type === \"image\");\n\n\t\t\t// Always send function_call_output with text (or placeholder if only images)\n\t\t\tconst hasText = textResult.length > 0;\n\t\t\tmessages.push({\n\t\t\t\ttype: \"function_call_output\",\n\t\t\t\tcall_id: msg.toolCallId.split(\"|\")[0],\n\t\t\t\toutput: sanitizeSurrogates(hasText ? textResult : \"(see attached image)\"),\n\t\t\t});\n\n\t\t\t// If there are images and model supports them, send a follow-up user message with images\n\t\t\tif (hasImages && model.input.includes(\"image\")) {\n\t\t\t\tconst contentParts: ResponseInputContent[] = [];\n\n\t\t\t\t// Add text prefix\n\t\t\t\tcontentParts.push({\n\t\t\t\t\ttype: \"input_text\",\n\t\t\t\t\ttext: \"Attached image(s) from tool result:\",\n\t\t\t\t} satisfies ResponseInputText);\n\n\t\t\t\t// Add images\n\t\t\t\tfor (const block of msg.content) {\n\t\t\t\t\tif (block.type === \"image\") {\n\t\t\t\t\t\tcontentParts.push({\n\t\t\t\t\t\t\ttype: \"input_image\",\n\t\t\t\t\t\t\tdetail: \"auto\",\n\t\t\t\t\t\t\timage_url: `data:${(block as any).mimeType};base64,${(block as any).data}`,\n\t\t\t\t\t\t} satisfies ResponseInputImage);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tmessages.push({\n\t\t\t\t\trole: \"user\",\n\t\t\t\t\tcontent: contentParts,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tmsgIndex++;\n\t}\n\n\treturn messages;\n}\n\nfunction convertTools(tools: Tool[]): OpenAITool[] {\n\treturn tools.map((tool) => ({\n\t\ttype: \"function\",\n\t\tname: tool.name,\n\t\tdescription: tool.description,\n\t\tparameters: tool.parameters as any, // TypeBox already generates JSON Schema\n\t\tstrict: false,\n\t}));\n}\n\nfunction getServiceTierCostMultiplier(serviceTier: ResponseCreateParamsStreaming[\"service_tier\"] | undefined): number {\n\tswitch (serviceTier) {\n\t\tcase \"flex\":\n\t\t\treturn 0.5;\n\t\tcase \"priority\":\n\t\t\treturn 2;\n\t\tdefault:\n\t\t\treturn 1;\n\t}\n}\n\nfunction applyServiceTierPricing(usage: Usage, serviceTier: ResponseCreateParamsStreaming[\"service_tier\"] | undefined) {\n\tconst multiplier = getServiceTierCostMultiplier(serviceTier);\n\tif (multiplier === 1) return;\n\n\tusage.cost.input *= multiplier;\n\tusage.cost.output *= multiplier;\n\tusage.cost.cacheRead *= multiplier;\n\tusage.cost.cacheWrite *= multiplier;\n\tusage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;\n}\n\nfunction mapStopReason(status: OpenAI.Responses.ResponseStatus | undefined): StopReason {\n\tif (!status) return \"stop\";\n\tswitch (status) {\n\t\tcase \"completed\":\n\t\t\treturn \"stop\";\n\t\tcase \"incomplete\":\n\t\t\treturn \"length\";\n\t\tcase \"failed\":\n\t\tcase \"cancelled\":\n\t\t\treturn \"error\";\n\t\t// These two are wonky ...\n\t\tcase \"in_progress\":\n\t\tcase \"queued\":\n\t\t\treturn \"stop\";\n\t\tdefault: {\n\t\t\tconst _exhaustive: never = status;\n\t\t\tthrow new Error(`Unhandled stop reason: ${_exhaustive}`);\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"openai-responses.js","sourceRoot":"","sources":["../../src/providers/openai-responses.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAY5B,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAe5C,OAAO,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D,sDAAsD;AACtD,SAAS,SAAS,CAAC,GAAW,EAAU;IACvC,IAAI,EAAE,GAAG,UAAU,CAAC;IACpB,IAAI,EAAE,GAAG,UAAU,CAAC;IACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,EAAE,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAC7B,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,EAAE,UAAU,CAAC,CAAC;QACpC,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,EAAE,UAAU,CAAC,CAAC;IACrC,CAAC;IACD,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;IACvF,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;IACvF,OAAO,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAAA,CACzD;AASD;;GAEG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAuC,CACxE,KAAgC,EAChC,OAAgB,EAChB,OAAgC,EACF,EAAE,CAAC;IACjC,MAAM,MAAM,GAAG,IAAI,2BAA2B,EAAE,CAAC;IAEjD,yBAAyB;IACzB,CAAC,KAAK,IAAI,EAAE,CAAC;QACZ,MAAM,MAAM,GAAqB;YAChC,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,EAAE;YACX,GAAG,EAAE,kBAAyB;YAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,KAAK,EAAE,KAAK,CAAC,EAAE;YACf,KAAK,EAAE;gBACN,KAAK,EAAE,CAAC;gBACR,MAAM,EAAE,CAAC;gBACT,SAAS,EAAE,CAAC;gBACZ,UAAU,EAAE,CAAC;gBACb,WAAW,EAAE,CAAC;gBACd,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE;aACpE;YACD,UAAU,EAAE,MAAM;YAClB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACrB,CAAC;QAEF,IAAI,CAAC;YACJ,uBAAuB;YACvB,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,YAAY,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACrE,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;YACpD,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;YACpD,OAAO,EAAE,SAAS,EAAE,CAAC,MAAM,CAAC,CAAC;YAC7B,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,MAAM,CACjD,MAAM,EACN,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,CACxD,CAAC;YACF,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;YAEhD,IAAI,WAAW,GAAoF,IAAI,CAAC;YACxG,IAAI,YAAY,GAAgF,IAAI,CAAC;YACrG,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC;YAC9B,MAAM,UAAU,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;YAE3C,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,YAAY,EAAE,CAAC;gBACxC,2BAA2B;gBAC3B,IAAI,KAAK,CAAC,IAAI,KAAK,4BAA4B,EAAE,CAAC;oBACjD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;oBACxB,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;wBAC/B,WAAW,GAAG,IAAI,CAAC;wBACnB,YAAY,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;wBAClD,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;wBAClC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,YAAY,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;oBACtF,CAAC;yBAAM,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;wBACpC,WAAW,GAAG,IAAI,CAAC;wBACnB,YAAY,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;wBAC1C,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;wBAClC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;oBAClF,CAAC;yBAAM,IAAI,IAAI,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;wBAC1C,WAAW,GAAG,IAAI,CAAC;wBACnB,YAAY,GAAG;4BACd,IAAI,EAAE,UAAU;4BAChB,EAAE,EAAE,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,EAAE,EAAE;4BAChC,IAAI,EAAE,IAAI,CAAC,IAAI;4BACf,SAAS,EAAE,EAAE;4BACb,WAAW,EAAE,IAAI,CAAC,SAAS,IAAI,EAAE;yBACjC,CAAC;wBACF,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;wBAClC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,YAAY,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;oBACtF,CAAC;gBACF,CAAC;gBACD,kCAAkC;qBAC7B,IAAI,KAAK,CAAC,IAAI,KAAK,uCAAuC,EAAE,CAAC;oBACjE,IAAI,WAAW,IAAI,WAAW,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;wBACrD,WAAW,CAAC,OAAO,GAAG,WAAW,CAAC,OAAO,IAAI,EAAE,CAAC;wBAChD,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBACtC,CAAC;gBACF,CAAC;qBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,uCAAuC,EAAE,CAAC;oBACnE,IACC,WAAW;wBACX,WAAW,CAAC,IAAI,KAAK,WAAW;wBAChC,YAAY;wBACZ,YAAY,CAAC,IAAI,KAAK,UAAU,EAC/B,CAAC;wBACF,WAAW,CAAC,OAAO,GAAG,WAAW,CAAC,OAAO,IAAI,EAAE,CAAC;wBAChD,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;wBACrE,IAAI,QAAQ,EAAE,CAAC;4BACd,YAAY,CAAC,QAAQ,IAAI,KAAK,CAAC,KAAK,CAAC;4BACrC,QAAQ,CAAC,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC;4BAC7B,MAAM,CAAC,IAAI,CAAC;gCACX,IAAI,EAAE,gBAAgB;gCACtB,YAAY,EAAE,UAAU,EAAE;gCAC1B,KAAK,EAAE,KAAK,CAAC,KAAK;gCAClB,OAAO,EAAE,MAAM;6BACf,CAAC,CAAC;wBACJ,CAAC;oBACF,CAAC;gBACF,CAAC;gBACD,iDAAiD;qBAC5C,IAAI,KAAK,CAAC,IAAI,KAAK,sCAAsC,EAAE,CAAC;oBAChE,IACC,WAAW;wBACX,WAAW,CAAC,IAAI,KAAK,WAAW;wBAChC,YAAY;wBACZ,YAAY,CAAC,IAAI,KAAK,UAAU,EAC/B,CAAC;wBACF,WAAW,CAAC,OAAO,GAAG,WAAW,CAAC,OAAO,IAAI,EAAE,CAAC;wBAChD,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;wBACrE,IAAI,QAAQ,EAAE,CAAC;4BACd,YAAY,CAAC,QAAQ,IAAI,MAAM,CAAC;4BAChC,QAAQ,CAAC,IAAI,IAAI,MAAM,CAAC;4BACxB,MAAM,CAAC,IAAI,CAAC;gCACX,IAAI,EAAE,gBAAgB;gCACtB,YAAY,EAAE,UAAU,EAAE;gCAC1B,KAAK,EAAE,MAAM;gCACb,OAAO,EAAE,MAAM;6BACf,CAAC,CAAC;wBACJ,CAAC;oBACF,CAAC;gBACF,CAAC;gBACD,4BAA4B;qBACvB,IAAI,KAAK,CAAC,IAAI,KAAK,6BAA6B,EAAE,CAAC;oBACvD,IAAI,WAAW,IAAI,WAAW,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;wBACnD,WAAW,CAAC,OAAO,GAAG,WAAW,CAAC,OAAO,IAAI,EAAE,CAAC;wBAChD,gEAAgE;wBAChE,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,aAAa,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;4BACxE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;wBACtC,CAAC;oBACF,CAAC;gBACF,CAAC;qBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,4BAA4B,EAAE,CAAC;oBACxD,IAAI,WAAW,IAAI,WAAW,CAAC,IAAI,KAAK,SAAS,IAAI,YAAY,IAAI,YAAY,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;wBACnG,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;wBACrE,IAAI,QAAQ,IAAI,QAAQ,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;4BACjD,YAAY,CAAC,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC;4BACjC,QAAQ,CAAC,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC;4BAC7B,MAAM,CAAC,IAAI,CAAC;gCACX,IAAI,EAAE,YAAY;gCAClB,YAAY,EAAE,UAAU,EAAE;gCAC1B,KAAK,EAAE,KAAK,CAAC,KAAK;gCAClB,OAAO,EAAE,MAAM;6BACf,CAAC,CAAC;wBACJ,CAAC;oBACF,CAAC;gBACF,CAAC;qBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,wBAAwB,EAAE,CAAC;oBACpD,IAAI,WAAW,IAAI,WAAW,CAAC,IAAI,KAAK,SAAS,IAAI,YAAY,IAAI,YAAY,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;wBACnG,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;wBACrE,IAAI,QAAQ,IAAI,QAAQ,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;4BAC7C,YAAY,CAAC,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC;4BACjC,QAAQ,CAAC,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC;4BAChC,MAAM,CAAC,IAAI,CAAC;gCACX,IAAI,EAAE,YAAY;gCAClB,YAAY,EAAE,UAAU,EAAE;gCAC1B,KAAK,EAAE,KAAK,CAAC,KAAK;gCAClB,OAAO,EAAE,MAAM;6BACf,CAAC,CAAC;wBACJ,CAAC;oBACF,CAAC;gBACF,CAAC;gBACD,uCAAuC;qBAClC,IAAI,KAAK,CAAC,IAAI,KAAK,wCAAwC,EAAE,CAAC;oBAClE,IACC,WAAW;wBACX,WAAW,CAAC,IAAI,KAAK,eAAe;wBACpC,YAAY;wBACZ,YAAY,CAAC,IAAI,KAAK,UAAU,EAC/B,CAAC;wBACF,YAAY,CAAC,WAAW,IAAI,KAAK,CAAC,KAAK,CAAC;wBACxC,YAAY,CAAC,SAAS,GAAG,kBAAkB,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;wBACtE,MAAM,CAAC,IAAI,CAAC;4BACX,IAAI,EAAE,gBAAgB;4BACtB,YAAY,EAAE,UAAU,EAAE;4BAC1B,KAAK,EAAE,KAAK,CAAC,KAAK;4BAClB,OAAO,EAAE,MAAM;yBACf,CAAC,CAAC;oBACJ,CAAC;gBACF,CAAC;gBACD,gCAAgC;qBAC3B,IAAI,KAAK,CAAC,IAAI,KAAK,2BAA2B,EAAE,CAAC;oBACrD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;oBAExB,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,IAAI,YAAY,IAAI,YAAY,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;wBACnF,YAAY,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;wBAC5E,YAAY,CAAC,iBAAiB,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;wBACtD,MAAM,CAAC,IAAI,CAAC;4BACX,IAAI,EAAE,cAAc;4BACpB,YAAY,EAAE,UAAU,EAAE;4BAC1B,OAAO,EAAE,YAAY,CAAC,QAAQ;4BAC9B,OAAO,EAAE,MAAM;yBACf,CAAC,CAAC;wBACH,YAAY,GAAG,IAAI,CAAC;oBACrB,CAAC;yBAAM,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,YAAY,IAAI,YAAY,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;wBACpF,YAAY,CAAC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;wBACtG,YAAY,CAAC,aAAa,GAAG,IAAI,CAAC,EAAE,CAAC;wBACrC,MAAM,CAAC,IAAI,CAAC;4BACX,IAAI,EAAE,UAAU;4BAChB,YAAY,EAAE,UAAU,EAAE;4BAC1B,OAAO,EAAE,YAAY,CAAC,IAAI;4BAC1B,OAAO,EAAE,MAAM;yBACf,CAAC,CAAC;wBACH,YAAY,GAAG,IAAI,CAAC;oBACrB,CAAC;yBAAM,IAAI,IAAI,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;wBAC1C,MAAM,QAAQ,GAAa;4BAC1B,IAAI,EAAE,UAAU;4BAChB,EAAE,EAAE,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,EAAE,EAAE;4BAChC,IAAI,EAAE,IAAI,CAAC,IAAI;4BACf,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;yBACrC,CAAC;wBAEF,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,YAAY,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;oBAC9F,CAAC;gBACF,CAAC;gBACD,oBAAoB;qBACf,IAAI,KAAK,CAAC,IAAI,KAAK,oBAAoB,EAAE,CAAC;oBAC9C,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;oBAChC,IAAI,QAAQ,EAAE,KAAK,EAAE,CAAC;wBACrB,MAAM,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,oBAAoB,EAAE,aAAa,IAAI,CAAC,CAAC;wBAC7E,MAAM,CAAC,KAAK,GAAG;4BACd,qFAAqF;4BACrF,KAAK,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,YAAY,IAAI,CAAC,CAAC,GAAG,YAAY;4BACxD,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,aAAa,IAAI,CAAC;4BACzC,SAAS,EAAE,YAAY;4BACvB,UAAU,EAAE,CAAC;4BACb,WAAW,EAAE,QAAQ,CAAC,KAAK,CAAC,YAAY,IAAI,CAAC;4BAC7C,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE;yBACpE,CAAC;oBACH,CAAC;oBACD,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;oBACnC,uBAAuB,CAAC,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,YAAY,IAAI,OAAO,EAAE,WAAW,CAAC,CAAC;oBACtF,4BAA4B;oBAC5B,MAAM,CAAC,UAAU,GAAG,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;oBACpD,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,IAAI,MAAM,CAAC,UAAU,KAAK,MAAM,EAAE,CAAC;wBACvF,MAAM,CAAC,UAAU,GAAG,SAAS,CAAC;oBAC/B,CAAC;gBACF,CAAC;gBACD,gBAAgB;qBACX,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;oBACjC,MAAM,IAAI,KAAK,CAAC,cAAc,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,IAAI,eAAe,CAAC,CAAC;gBAClF,CAAC;qBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;oBAC7C,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;gBAClC,CAAC;YACF,CAAC;YAED,IAAI,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;gBAC9B,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;YACxC,CAAC;YAED,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,IAAI,MAAM,CAAC,UAAU,KAAK,OAAO,EAAE,CAAC;gBACtE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;YAC5C,CAAC;YAED,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;YAC1E,MAAM,CAAC,GAAG,EAAE,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,OAAO;gBAAE,OAAQ,KAAa,CAAC,KAAK,CAAC;YAChE,MAAM,CAAC,UAAU,GAAG,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;YACnE,MAAM,CAAC,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YACrF,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;YACzE,MAAM,CAAC,GAAG,EAAE,CAAC;QACd,CAAC;IAAA,CACD,CAAC,EAAE,CAAC;IAEL,OAAO,MAAM,CAAC;AAAA,CACd,CAAC;AAEF,SAAS,YAAY,CAAC,KAAgC,EAAE,OAAgB,EAAE,MAAe,EAAE;IAC1F,IAAI,CAAC,MAAM,EAAE,CAAC;QACb,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CACd,gGAAgG,CAChG,CAAC;QACH,CAAC;QACD,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IACrC,CAAC;IAED,MAAM,OAAO,GAAG,EAAE,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC;IACrC,IAAI,KAAK,CAAC,QAAQ,KAAK,gBAAgB,EAAE,CAAC;QACzC,gFAAgF;QAChF,iFAAiF;QACjF,+CAA+C;QAC/C,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC;QACxC,MAAM,WAAW,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAClD,MAAM,WAAW,GAAG,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;QACtE,OAAO,CAAC,aAAa,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;QACxD,OAAO,CAAC,eAAe,CAAC,GAAG,oBAAoB,CAAC;QAEhD,mDAAmD;QACnD,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC;YACxC,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBACvD,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;YACpD,CAAC;YACD,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC7D,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;YACpD,CAAC;YACD,OAAO,KAAK,CAAC;QAAA,CACb,CAAC,CAAC;QACH,IAAI,SAAS,EAAE,CAAC;YACf,OAAO,CAAC,wBAAwB,CAAC,GAAG,MAAM,CAAC;QAC5C,CAAC;IACF,CAAC;IAED,OAAO,IAAI,MAAM,CAAC;QACjB,MAAM;QACN,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,uBAAuB,EAAE,IAAI;QAC7B,cAAc,EAAE,OAAO;KACvB,CAAC,CAAC;AAAA,CACH;AAED,SAAS,WAAW,CAAC,KAAgC,EAAE,OAAgB,EAAE,OAAgC,EAAE;IAC1G,MAAM,QAAQ,GAAG,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAEjD,MAAM,MAAM,GAAkC;QAC7C,KAAK,EAAE,KAAK,CAAC,EAAE;QACf,KAAK,EAAE,QAAQ;QACf,MAAM,EAAE,IAAI;QACZ,gBAAgB,EAAE,OAAO,EAAE,SAAS;KACpC,CAAC;IAEF,IAAI,OAAO,EAAE,SAAS,EAAE,CAAC;QACxB,MAAM,CAAC,iBAAiB,GAAG,OAAO,EAAE,SAAS,CAAC;IAC/C,CAAC;IAED,IAAI,OAAO,EAAE,WAAW,KAAK,SAAS,EAAE,CAAC;QACxC,MAAM,CAAC,WAAW,GAAG,OAAO,EAAE,WAAW,CAAC;IAC3C,CAAC;IAED,IAAI,OAAO,EAAE,WAAW,KAAK,SAAS,EAAE,CAAC;QACxC,MAAM,CAAC,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;IAC3C,CAAC;IAED,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QACnB,MAAM,CAAC,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC5C,CAAC;IAED,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QACrB,IAAI,OAAO,EAAE,eAAe,IAAI,OAAO,EAAE,gBAAgB,EAAE,CAAC;YAC3D,MAAM,CAAC,SAAS,GAAG;gBAClB,MAAM,EAAE,OAAO,EAAE,eAAe,IAAI,QAAQ;gBAC5C,OAAO,EAAE,OAAO,EAAE,gBAAgB,IAAI,MAAM;aAC5C,CAAC;YACF,MAAM,CAAC,OAAO,GAAG,CAAC,6BAA6B,CAAC,CAAC;QAClD,CAAC;aAAM,CAAC;YACP,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;gBACpC,mGAAmG;gBACnG,QAAQ,CAAC,IAAI,CAAC;oBACb,IAAI,EAAE,WAAW;oBACjB,OAAO,EAAE;wBACR;4BACC,IAAI,EAAE,YAAY;4BAClB,IAAI,EAAE,uBAAuB;yBAC7B;qBACD;iBACD,CAAC,CAAC;YACJ,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,MAAM,CAAC;AAAA,CACd;AAED,SAAS,eAAe,CAAC,KAAgC,EAAE,OAAgB,EAAiB;IAC3F,MAAM,QAAQ,GAAkB,EAAE,CAAC;IAEnC,MAAM,mBAAmB,GAAG,CAAC,EAAU,EAAU,EAAE,CAAC;QACnD,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,cAAc,EAAE,UAAU,CAAC,CAAC,CAAC;QACzE,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC;YAAE,OAAO,EAAE,CAAC;QACrD,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,OAAO,EAAE,CAAC;QACjC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACvC,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;QAC/D,IAAI,eAAe,GAAG,MAAM,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;QAC7D,2DAA2D;QAC3D,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACvC,eAAe,GAAG,MAAM,eAAe,EAAE,CAAC;QAC3C,CAAC;QACD,MAAM,gBAAgB,GAAG,eAAe,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC;QACtG,MAAM,gBAAgB,GAAG,eAAe,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC;QACtG,OAAO,GAAG,gBAAgB,IAAI,gBAAgB,EAAE,CAAC;IAAA,CACjD,CAAC;IAEF,MAAM,mBAAmB,GAAG,iBAAiB,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,mBAAmB,CAAC,CAAC;IAE5F,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;QAC1B,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC;QACtD,QAAQ,CAAC,IAAI,CAAC;YACb,IAAI;YACJ,OAAO,EAAE,kBAAkB,CAAC,OAAO,CAAC,YAAY,CAAC;SACjD,CAAC,CAAC;IACJ,CAAC;IAED,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,KAAK,MAAM,GAAG,IAAI,mBAAmB,EAAE,CAAC;QACvC,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACzB,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;gBACrC,QAAQ,CAAC,IAAI,CAAC;oBACb,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;iBACxE,CAAC,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACP,MAAM,OAAO,GAA2B,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAwB,EAAE,CAAC;oBACvF,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;wBAC1B,OAAO;4BACN,IAAI,EAAE,YAAY;4BAClB,IAAI,EAAE,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC;yBACP,CAAC;oBAC/B,CAAC;yBAAM,CAAC;wBACP,OAAO;4BACN,IAAI,EAAE,aAAa;4BACnB,MAAM,EAAE,MAAM;4BACd,SAAS,EAAE,QAAQ,IAAI,CAAC,QAAQ,WAAW,IAAI,CAAC,IAAI,EAAE;yBACzB,CAAC;oBAChC,CAAC;gBAAA,CACD,CAAC,CAAC;gBACH,MAAM,eAAe,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC;oBACrD,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,CAAC;oBACjD,CAAC,CAAC,OAAO,CAAC;gBACX,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC;oBAAE,SAAS;gBAC3C,QAAQ,CAAC,IAAI,CAAC;oBACb,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE,eAAe;iBACxB,CAAC,CAAC;YACJ,CAAC;QACF,CAAC;aAAM,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YACrC,MAAM,MAAM,GAAkB,EAAE,CAAC;YACjC,MAAM,sBAAsB,GAAG,KAAK,CAAC,MAAM,EAAE,sBAAsB,IAAI,KAAK,CAAC;YAC7E,IAAI,YAAY,GAAG,KAAK,CAAC;YACzB,IAAI,qBAAqB,GAAG,GAAG,CAAC,UAAU,KAAK,OAAO,CAAC;YACvD,IAAI,cAAc,GAAG,GAAG,CAAC,UAAU,KAAK,OAAO,CAAC;YAChD,IAAI,sBAAsB,EAAE,CAAC;gBAC5B,YAAY,GAAG,GAAG,CAAC,UAAU,KAAK,OAAO,IAAI,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC;gBAC1E,MAAM,gBAAgB,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CACxC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,IAAK,CAAiB,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAChG,CAAC;gBACF,qBAAqB,GAAG,CAAC,YAAY,IAAI,gBAAgB,CAAC;gBAC1D,cAAc,GAAG,CAAC,YAAY,CAAC;YAChC,CAAC;YAED,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;gBACjC,4EAA4E;gBAC5E,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,IAAI,qBAAqB,EAAE,CAAC;oBACxD,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAC;wBAC7B,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;wBAC1D,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;oBAC5B,CAAC;gBACF,CAAC;qBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;oBAClC,MAAM,SAAS,GAAG,KAAoB,CAAC;oBACvC,6CAA6C;oBAC7C,IAAI,KAAK,GAAG,SAAS,CAAC,aAAa,CAAC;oBACpC,IAAI,CAAC,KAAK,EAAE,CAAC;wBACZ,KAAK,GAAG,OAAO,QAAQ,EAAE,CAAC;oBAC3B,CAAC;oBACD,uEAAuE;oBACvE,oGAAoG;oBACpG,IAAI,sBAAsB,IAAI,YAAY,EAAE,CAAC;wBAC5C,KAAK,GAAG,OAAO,QAAQ,IAAI,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;oBACxD,CAAC;yBAAM,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;wBAC9B,KAAK,GAAG,OAAO,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;oBACnC,CAAC;oBACD,MAAM,CAAC,IAAI,CAAC;wBACX,IAAI,EAAE,SAAS;wBACf,IAAI,EAAE,WAAW;wBACjB,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,kBAAkB,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;wBAC7F,MAAM,EAAE,WAAW;wBACnB,EAAE,EAAE,KAAK;qBACuB,CAAC,CAAC;oBACnC,4EAA4E;gBAC7E,CAAC;qBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,IAAI,cAAc,EAAE,CAAC;oBACxD,MAAM,QAAQ,GAAG,KAAiB,CAAC;oBACnC,MAAM,CAAC,IAAI,CAAC;wBACX,IAAI,EAAE,eAAe;wBACrB,EAAE,EAAE,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;wBAC7B,OAAO,EAAE,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;wBAClC,IAAI,EAAE,QAAQ,CAAC,IAAI;wBACnB,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC;qBAC7C,CAAC,CAAC;gBACJ,CAAC;YACF,CAAC;YACD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;gBAAE,SAAS;YAClC,QAAQ,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;QAC1B,CAAC;aAAM,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YACtC,iCAAiC;YACjC,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO;iBAC5B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;iBAChC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAE,CAAS,CAAC,IAAI,CAAC;iBAC3B,IAAI,CAAC,IAAI,CAAC,CAAC;YACb,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;YAE9D,6EAA6E;YAC7E,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;YACtC,QAAQ,CAAC,IAAI,CAAC;gBACb,IAAI,EAAE,sBAAsB;gBAC5B,OAAO,EAAE,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;gBACrC,MAAM,EAAE,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,sBAAsB,CAAC;aACzE,CAAC,CAAC;YAEH,yFAAyF;YACzF,IAAI,SAAS,IAAI,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBAChD,MAAM,YAAY,GAA2B,EAAE,CAAC;gBAEhD,kBAAkB;gBAClB,YAAY,CAAC,IAAI,CAAC;oBACjB,IAAI,EAAE,YAAY;oBAClB,IAAI,EAAE,qCAAqC;iBACf,CAAC,CAAC;gBAE/B,aAAa;gBACb,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;oBACjC,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;wBAC5B,YAAY,CAAC,IAAI,CAAC;4BACjB,IAAI,EAAE,aAAa;4BACnB,MAAM,EAAE,MAAM;4BACd,SAAS,EAAE,QAAS,KAAa,CAAC,QAAQ,WAAY,KAAa,CAAC,IAAI,EAAE;yBAC7C,CAAC,CAAC;oBACjC,CAAC;gBACF,CAAC;gBAED,QAAQ,CAAC,IAAI,CAAC;oBACb,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE,YAAY;iBACrB,CAAC,CAAC;YACJ,CAAC;QACF,CAAC;QACD,QAAQ,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,QAAQ,CAAC;AAAA,CAChB;AAED,SAAS,YAAY,CAAC,KAAa,EAAgB;IAClD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC3B,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,UAAU,EAAE,IAAI,CAAC,UAAiB,EAAE,wCAAwC;QAC5E,MAAM,EAAE,KAAK;KACb,CAAC,CAAC,CAAC;AAAA,CACJ;AAED,SAAS,4BAA4B,CAAC,WAAsE,EAAU;IACrH,QAAQ,WAAW,EAAE,CAAC;QACrB,KAAK,MAAM;YACV,OAAO,GAAG,CAAC;QACZ,KAAK,UAAU;YACd,OAAO,CAAC,CAAC;QACV;YACC,OAAO,CAAC,CAAC;IACX,CAAC;AAAA,CACD;AAED,SAAS,uBAAuB,CAAC,KAAY,EAAE,WAAsE,EAAE;IACtH,MAAM,UAAU,GAAG,4BAA4B,CAAC,WAAW,CAAC,CAAC;IAC7D,IAAI,UAAU,KAAK,CAAC;QAAE,OAAO;IAE7B,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,UAAU,CAAC;IAC/B,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,UAAU,CAAC;IAChC,KAAK,CAAC,IAAI,CAAC,SAAS,IAAI,UAAU,CAAC;IACnC,KAAK,CAAC,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC;IACpC,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC;AAAA,CACvG;AAED,SAAS,aAAa,CAAC,MAAmD,EAAc;IACvF,IAAI,CAAC,MAAM;QAAE,OAAO,MAAM,CAAC;IAC3B,QAAQ,MAAM,EAAE,CAAC;QAChB,KAAK,WAAW;YACf,OAAO,MAAM,CAAC;QACf,KAAK,YAAY;YAChB,OAAO,QAAQ,CAAC;QACjB,KAAK,QAAQ,CAAC;QACd,KAAK,WAAW;YACf,OAAO,OAAO,CAAC;QAChB,0BAA0B;QAC1B,KAAK,aAAa,CAAC;QACnB,KAAK,QAAQ;YACZ,OAAO,MAAM,CAAC;QACf,SAAS,CAAC;YACT,MAAM,WAAW,GAAU,MAAM,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,0BAA0B,WAAW,EAAE,CAAC,CAAC;QAC1D,CAAC;IACF,CAAC;AAAA,CACD","sourcesContent":["import OpenAI from \"openai\";\nimport type {\n\tTool as OpenAITool,\n\tResponseCreateParamsStreaming,\n\tResponseFunctionToolCall,\n\tResponseInput,\n\tResponseInputContent,\n\tResponseInputImage,\n\tResponseInputText,\n\tResponseOutputMessage,\n\tResponseReasoningItem,\n} from \"openai/resources/responses/responses.js\";\nimport { calculateCost } from \"../models.js\";\nimport { getEnvApiKey } from \"../stream.js\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tContext,\n\tModel,\n\tStopReason,\n\tStreamFunction,\n\tStreamOptions,\n\tTextContent,\n\tThinkingContent,\n\tTool,\n\tToolCall,\n\tUsage,\n} from \"../types.js\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.js\";\nimport { parseStreamingJson } from \"../utils/json-parse.js\";\nimport { sanitizeSurrogates } from \"../utils/sanitize-unicode.js\";\nimport { transformMessages } from \"./transform-messages.js\";\n\n/** Fast deterministic hash to shorten long strings */\nfunction shortHash(str: string): string {\n\tlet h1 = 0xdeadbeef;\n\tlet h2 = 0x41c6ce57;\n\tfor (let i = 0; i < str.length; i++) {\n\t\tconst ch = str.charCodeAt(i);\n\t\th1 = Math.imul(h1 ^ ch, 2654435761);\n\t\th2 = Math.imul(h2 ^ ch, 1597334677);\n\t}\n\th1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);\n\th2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);\n\treturn (h2 >>> 0).toString(36) + (h1 >>> 0).toString(36);\n}\n\n// OpenAI Responses-specific options\nexport interface OpenAIResponsesOptions extends StreamOptions {\n\treasoningEffort?: \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\n\treasoningSummary?: \"auto\" | \"detailed\" | \"concise\" | null;\n\tserviceTier?: ResponseCreateParamsStreaming[\"service_tier\"];\n}\n\n/**\n * Generate function for OpenAI Responses API\n */\nexport const streamOpenAIResponses: StreamFunction<\"openai-responses\"> = (\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\toptions?: OpenAIResponsesOptions,\n): AssistantMessageEventStream => {\n\tconst stream = new AssistantMessageEventStream();\n\n\t// Start async processing\n\t(async () => {\n\t\tconst output: AssistantMessage = {\n\t\t\trole: \"assistant\",\n\t\t\tcontent: [],\n\t\t\tapi: \"openai-responses\" as Api,\n\t\t\tprovider: model.provider,\n\t\t\tmodel: model.id,\n\t\t\tusage: {\n\t\t\t\tinput: 0,\n\t\t\t\toutput: 0,\n\t\t\t\tcacheRead: 0,\n\t\t\t\tcacheWrite: 0,\n\t\t\t\ttotalTokens: 0,\n\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t},\n\t\t\tstopReason: \"stop\",\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\n\t\ttry {\n\t\t\t// Create OpenAI client\n\t\t\tconst apiKey = options?.apiKey || getEnvApiKey(model.provider) || \"\";\n\t\t\tconst client = createClient(model, context, apiKey);\n\t\t\tconst params = buildParams(model, context, options);\n\t\t\toptions?.onPayload?.(params);\n\t\t\tconst openaiStream = await client.responses.create(\n\t\t\t\tparams,\n\t\t\t\toptions?.signal ? { signal: options.signal } : undefined,\n\t\t\t);\n\t\t\tstream.push({ type: \"start\", partial: output });\n\n\t\t\tlet currentItem: ResponseReasoningItem | ResponseOutputMessage | ResponseFunctionToolCall | null = null;\n\t\t\tlet currentBlock: ThinkingContent | TextContent | (ToolCall & { partialJson: string }) | null = null;\n\t\t\tconst blocks = output.content;\n\t\t\tconst blockIndex = () => blocks.length - 1;\n\n\t\t\tfor await (const event of openaiStream) {\n\t\t\t\t// Handle output item start\n\t\t\t\tif (event.type === \"response.output_item.added\") {\n\t\t\t\t\tconst item = event.item;\n\t\t\t\t\tif (item.type === \"reasoning\") {\n\t\t\t\t\t\tcurrentItem = item;\n\t\t\t\t\t\tcurrentBlock = { type: \"thinking\", thinking: \"\" };\n\t\t\t\t\t\toutput.content.push(currentBlock);\n\t\t\t\t\t\tstream.push({ type: \"thinking_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t\t\t} else if (item.type === \"message\") {\n\t\t\t\t\t\tcurrentItem = item;\n\t\t\t\t\t\tcurrentBlock = { type: \"text\", text: \"\" };\n\t\t\t\t\t\toutput.content.push(currentBlock);\n\t\t\t\t\t\tstream.push({ type: \"text_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t\t\t} else if (item.type === \"function_call\") {\n\t\t\t\t\t\tcurrentItem = item;\n\t\t\t\t\t\tcurrentBlock = {\n\t\t\t\t\t\t\ttype: \"toolCall\",\n\t\t\t\t\t\t\tid: `${item.call_id}|${item.id}`,\n\t\t\t\t\t\t\tname: item.name,\n\t\t\t\t\t\t\targuments: {},\n\t\t\t\t\t\t\tpartialJson: item.arguments || \"\",\n\t\t\t\t\t\t};\n\t\t\t\t\t\toutput.content.push(currentBlock);\n\t\t\t\t\t\tstream.push({ type: \"toolcall_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Handle reasoning summary deltas\n\t\t\t\telse if (event.type === \"response.reasoning_summary_part.added\") {\n\t\t\t\t\tif (currentItem && currentItem.type === \"reasoning\") {\n\t\t\t\t\t\tcurrentItem.summary = currentItem.summary || [];\n\t\t\t\t\t\tcurrentItem.summary.push(event.part);\n\t\t\t\t\t}\n\t\t\t\t} else if (event.type === \"response.reasoning_summary_text.delta\") {\n\t\t\t\t\tif (\n\t\t\t\t\t\tcurrentItem &&\n\t\t\t\t\t\tcurrentItem.type === \"reasoning\" &&\n\t\t\t\t\t\tcurrentBlock &&\n\t\t\t\t\t\tcurrentBlock.type === \"thinking\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tcurrentItem.summary = currentItem.summary || [];\n\t\t\t\t\t\tconst lastPart = currentItem.summary[currentItem.summary.length - 1];\n\t\t\t\t\t\tif (lastPart) {\n\t\t\t\t\t\t\tcurrentBlock.thinking += event.delta;\n\t\t\t\t\t\t\tlastPart.text += event.delta;\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"thinking_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\tdelta: event.delta,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Add a new line between summary parts (hack...)\n\t\t\t\telse if (event.type === \"response.reasoning_summary_part.done\") {\n\t\t\t\t\tif (\n\t\t\t\t\t\tcurrentItem &&\n\t\t\t\t\t\tcurrentItem.type === \"reasoning\" &&\n\t\t\t\t\t\tcurrentBlock &&\n\t\t\t\t\t\tcurrentBlock.type === \"thinking\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tcurrentItem.summary = currentItem.summary || [];\n\t\t\t\t\t\tconst lastPart = currentItem.summary[currentItem.summary.length - 1];\n\t\t\t\t\t\tif (lastPart) {\n\t\t\t\t\t\t\tcurrentBlock.thinking += \"\\n\\n\";\n\t\t\t\t\t\t\tlastPart.text += \"\\n\\n\";\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"thinking_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\tdelta: \"\\n\\n\",\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Handle text output deltas\n\t\t\t\telse if (event.type === \"response.content_part.added\") {\n\t\t\t\t\tif (currentItem && currentItem.type === \"message\") {\n\t\t\t\t\t\tcurrentItem.content = currentItem.content || [];\n\t\t\t\t\t\t// Filter out ReasoningText, only accept output_text and refusal\n\t\t\t\t\t\tif (event.part.type === \"output_text\" || event.part.type === \"refusal\") {\n\t\t\t\t\t\t\tcurrentItem.content.push(event.part);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (event.type === \"response.output_text.delta\") {\n\t\t\t\t\tif (currentItem && currentItem.type === \"message\" && currentBlock && currentBlock.type === \"text\") {\n\t\t\t\t\t\tconst lastPart = currentItem.content[currentItem.content.length - 1];\n\t\t\t\t\t\tif (lastPart && lastPart.type === \"output_text\") {\n\t\t\t\t\t\t\tcurrentBlock.text += event.delta;\n\t\t\t\t\t\t\tlastPart.text += event.delta;\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"text_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\tdelta: event.delta,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (event.type === \"response.refusal.delta\") {\n\t\t\t\t\tif (currentItem && currentItem.type === \"message\" && currentBlock && currentBlock.type === \"text\") {\n\t\t\t\t\t\tconst lastPart = currentItem.content[currentItem.content.length - 1];\n\t\t\t\t\t\tif (lastPart && lastPart.type === \"refusal\") {\n\t\t\t\t\t\t\tcurrentBlock.text += event.delta;\n\t\t\t\t\t\t\tlastPart.refusal += event.delta;\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"text_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\t\tdelta: event.delta,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Handle function call argument deltas\n\t\t\t\telse if (event.type === \"response.function_call_arguments.delta\") {\n\t\t\t\t\tif (\n\t\t\t\t\t\tcurrentItem &&\n\t\t\t\t\t\tcurrentItem.type === \"function_call\" &&\n\t\t\t\t\t\tcurrentBlock &&\n\t\t\t\t\t\tcurrentBlock.type === \"toolCall\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tcurrentBlock.partialJson += event.delta;\n\t\t\t\t\t\tcurrentBlock.arguments = parseStreamingJson(currentBlock.partialJson);\n\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\ttype: \"toolcall_delta\",\n\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\tdelta: event.delta,\n\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Handle output item completion\n\t\t\t\telse if (event.type === \"response.output_item.done\") {\n\t\t\t\t\tconst item = event.item;\n\n\t\t\t\t\tif (item.type === \"reasoning\" && currentBlock && currentBlock.type === \"thinking\") {\n\t\t\t\t\t\tcurrentBlock.thinking = item.summary?.map((s) => s.text).join(\"\\n\\n\") || \"\";\n\t\t\t\t\t\tcurrentBlock.thinkingSignature = JSON.stringify(item);\n\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\ttype: \"thinking_end\",\n\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\tcontent: currentBlock.thinking,\n\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tcurrentBlock = null;\n\t\t\t\t\t} else if (item.type === \"message\" && currentBlock && currentBlock.type === \"text\") {\n\t\t\t\t\t\tcurrentBlock.text = item.content.map((c) => (c.type === \"output_text\" ? c.text : c.refusal)).join(\"\");\n\t\t\t\t\t\tcurrentBlock.textSignature = item.id;\n\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\ttype: \"text_end\",\n\t\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\t\tcontent: currentBlock.text,\n\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tcurrentBlock = null;\n\t\t\t\t\t} else if (item.type === \"function_call\") {\n\t\t\t\t\t\tconst toolCall: ToolCall = {\n\t\t\t\t\t\t\ttype: \"toolCall\",\n\t\t\t\t\t\t\tid: `${item.call_id}|${item.id}`,\n\t\t\t\t\t\t\tname: item.name,\n\t\t\t\t\t\t\targuments: JSON.parse(item.arguments),\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tstream.push({ type: \"toolcall_end\", contentIndex: blockIndex(), toolCall, partial: output });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Handle completion\n\t\t\t\telse if (event.type === \"response.completed\") {\n\t\t\t\t\tconst response = event.response;\n\t\t\t\t\tif (response?.usage) {\n\t\t\t\t\t\tconst cachedTokens = response.usage.input_tokens_details?.cached_tokens || 0;\n\t\t\t\t\t\toutput.usage = {\n\t\t\t\t\t\t\t// OpenAI includes cached tokens in input_tokens, so subtract to get non-cached input\n\t\t\t\t\t\t\tinput: (response.usage.input_tokens || 0) - cachedTokens,\n\t\t\t\t\t\t\toutput: response.usage.output_tokens || 0,\n\t\t\t\t\t\t\tcacheRead: cachedTokens,\n\t\t\t\t\t\t\tcacheWrite: 0,\n\t\t\t\t\t\t\ttotalTokens: response.usage.total_tokens || 0,\n\t\t\t\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\tcalculateCost(model, output.usage);\n\t\t\t\t\tapplyServiceTierPricing(output.usage, response?.service_tier ?? options?.serviceTier);\n\t\t\t\t\t// Map status to stop reason\n\t\t\t\t\toutput.stopReason = mapStopReason(response?.status);\n\t\t\t\t\tif (output.content.some((b) => b.type === \"toolCall\") && output.stopReason === \"stop\") {\n\t\t\t\t\t\toutput.stopReason = \"toolUse\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Handle errors\n\t\t\t\telse if (event.type === \"error\") {\n\t\t\t\t\tthrow new Error(`Error Code ${event.code}: ${event.message}` || \"Unknown error\");\n\t\t\t\t} else if (event.type === \"response.failed\") {\n\t\t\t\t\tthrow new Error(\"Unknown error\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (options?.signal?.aborted) {\n\t\t\t\tthrow new Error(\"Request was aborted\");\n\t\t\t}\n\n\t\t\tif (output.stopReason === \"aborted\" || output.stopReason === \"error\") {\n\t\t\t\tthrow new Error(\"An unkown error ocurred\");\n\t\t\t}\n\n\t\t\tstream.push({ type: \"done\", reason: output.stopReason, message: output });\n\t\t\tstream.end();\n\t\t} catch (error) {\n\t\t\tfor (const block of output.content) delete (block as any).index;\n\t\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\t\toutput.errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n\t\t\tstream.push({ type: \"error\", reason: output.stopReason, error: output });\n\t\t\tstream.end();\n\t\t}\n\t})();\n\n\treturn stream;\n};\n\nfunction createClient(model: Model<\"openai-responses\">, context: Context, apiKey?: string) {\n\tif (!apiKey) {\n\t\tif (!process.env.OPENAI_API_KEY) {\n\t\t\tthrow new Error(\n\t\t\t\t\"OpenAI API key is required. Set OPENAI_API_KEY environment variable or pass it as an argument.\",\n\t\t\t);\n\t\t}\n\t\tapiKey = process.env.OPENAI_API_KEY;\n\t}\n\n\tconst headers = { ...model.headers };\n\tif (model.provider === \"github-copilot\") {\n\t\t// Copilot expects X-Initiator to indicate whether the request is user-initiated\n\t\t// or agent-initiated (e.g. follow-up after assistant/tool messages). If there is\n\t\t// no prior message, default to user-initiated.\n\t\tconst messages = context.messages || [];\n\t\tconst lastMessage = messages[messages.length - 1];\n\t\tconst isAgentCall = lastMessage ? lastMessage.role !== \"user\" : false;\n\t\theaders[\"X-Initiator\"] = isAgentCall ? \"agent\" : \"user\";\n\t\theaders[\"Openai-Intent\"] = \"conversation-edits\";\n\n\t\t// Copilot requires this header when sending images\n\t\tconst hasImages = messages.some((msg) => {\n\t\t\tif (msg.role === \"user\" && Array.isArray(msg.content)) {\n\t\t\t\treturn msg.content.some((c) => c.type === \"image\");\n\t\t\t}\n\t\t\tif (msg.role === \"toolResult\" && Array.isArray(msg.content)) {\n\t\t\t\treturn msg.content.some((c) => c.type === \"image\");\n\t\t\t}\n\t\t\treturn false;\n\t\t});\n\t\tif (hasImages) {\n\t\t\theaders[\"Copilot-Vision-Request\"] = \"true\";\n\t\t}\n\t}\n\n\treturn new OpenAI({\n\t\tapiKey,\n\t\tbaseURL: model.baseUrl,\n\t\tdangerouslyAllowBrowser: true,\n\t\tdefaultHeaders: headers,\n\t});\n}\n\nfunction buildParams(model: Model<\"openai-responses\">, context: Context, options?: OpenAIResponsesOptions) {\n\tconst messages = convertMessages(model, context);\n\n\tconst params: ResponseCreateParamsStreaming = {\n\t\tmodel: model.id,\n\t\tinput: messages,\n\t\tstream: true,\n\t\tprompt_cache_key: options?.sessionId,\n\t};\n\n\tif (options?.maxTokens) {\n\t\tparams.max_output_tokens = options?.maxTokens;\n\t}\n\n\tif (options?.temperature !== undefined) {\n\t\tparams.temperature = options?.temperature;\n\t}\n\n\tif (options?.serviceTier !== undefined) {\n\t\tparams.service_tier = options.serviceTier;\n\t}\n\n\tif (context.tools) {\n\t\tparams.tools = convertTools(context.tools);\n\t}\n\n\tif (model.reasoning) {\n\t\tif (options?.reasoningEffort || options?.reasoningSummary) {\n\t\t\tparams.reasoning = {\n\t\t\t\teffort: options?.reasoningEffort || \"medium\",\n\t\t\t\tsummary: options?.reasoningSummary || \"auto\",\n\t\t\t};\n\t\t\tparams.include = [\"reasoning.encrypted_content\"];\n\t\t} else {\n\t\t\tif (model.name.startsWith(\"gpt-5\")) {\n\t\t\t\t// Jesus Christ, see https://community.openai.com/t/need-reasoning-false-option-for-gpt-5/1351588/7\n\t\t\t\tmessages.push({\n\t\t\t\t\trole: \"developer\",\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"input_text\",\n\t\t\t\t\t\t\ttext: \"# Juice: 0 !important\",\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn params;\n}\n\nfunction convertMessages(model: Model<\"openai-responses\">, context: Context): ResponseInput {\n\tconst messages: ResponseInput = [];\n\n\tconst normalizeToolCallId = (id: string): string => {\n\t\tconst allowedProviders = new Set([\"openai\", \"openai-codex\", \"opencode\"]);\n\t\tif (!allowedProviders.has(model.provider)) return id;\n\t\tif (!id.includes(\"|\")) return id;\n\t\tconst [callId, itemId] = id.split(\"|\");\n\t\tconst sanitizedCallId = callId.replace(/[^a-zA-Z0-9_-]/g, \"_\");\n\t\tlet sanitizedItemId = itemId.replace(/[^a-zA-Z0-9_-]/g, \"_\");\n\t\t// OpenAI Responses API requires item id to start with \"fc\"\n\t\tif (!sanitizedItemId.startsWith(\"fc\")) {\n\t\t\tsanitizedItemId = `fc_${sanitizedItemId}`;\n\t\t}\n\t\tconst normalizedCallId = sanitizedCallId.length > 64 ? sanitizedCallId.slice(0, 64) : sanitizedCallId;\n\t\tconst normalizedItemId = sanitizedItemId.length > 64 ? sanitizedItemId.slice(0, 64) : sanitizedItemId;\n\t\treturn `${normalizedCallId}|${normalizedItemId}`;\n\t};\n\n\tconst transformedMessages = transformMessages(context.messages, model, normalizeToolCallId);\n\n\tif (context.systemPrompt) {\n\t\tconst role = model.reasoning ? \"developer\" : \"system\";\n\t\tmessages.push({\n\t\t\trole,\n\t\t\tcontent: sanitizeSurrogates(context.systemPrompt),\n\t\t});\n\t}\n\n\tlet msgIndex = 0;\n\tfor (const msg of transformedMessages) {\n\t\tif (msg.role === \"user\") {\n\t\t\tif (typeof msg.content === \"string\") {\n\t\t\t\tmessages.push({\n\t\t\t\t\trole: \"user\",\n\t\t\t\t\tcontent: [{ type: \"input_text\", text: sanitizeSurrogates(msg.content) }],\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst content: ResponseInputContent[] = msg.content.map((item): ResponseInputContent => {\n\t\t\t\t\tif (item.type === \"text\") {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: \"input_text\",\n\t\t\t\t\t\t\ttext: sanitizeSurrogates(item.text),\n\t\t\t\t\t\t} satisfies ResponseInputText;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: \"input_image\",\n\t\t\t\t\t\t\tdetail: \"auto\",\n\t\t\t\t\t\t\timage_url: `data:${item.mimeType};base64,${item.data}`,\n\t\t\t\t\t\t} satisfies ResponseInputImage;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tconst filteredContent = !model.input.includes(\"image\")\n\t\t\t\t\t? content.filter((c) => c.type !== \"input_image\")\n\t\t\t\t\t: content;\n\t\t\t\tif (filteredContent.length === 0) continue;\n\t\t\t\tmessages.push({\n\t\t\t\t\trole: \"user\",\n\t\t\t\t\tcontent: filteredContent,\n\t\t\t\t});\n\t\t\t}\n\t\t} else if (msg.role === \"assistant\") {\n\t\t\tconst output: ResponseInput = [];\n\t\t\tconst strictResponsesPairing = model.compat?.strictResponsesPairing ?? false;\n\t\t\tlet isIncomplete = false;\n\t\t\tlet shouldReplayReasoning = msg.stopReason !== \"error\";\n\t\t\tlet allowToolCalls = msg.stopReason !== \"error\";\n\t\t\tif (strictResponsesPairing) {\n\t\t\t\tisIncomplete = msg.stopReason === \"error\" || msg.stopReason === \"aborted\";\n\t\t\t\tconst hasPairedContent = msg.content.some(\n\t\t\t\t\t(b) => b.type === \"toolCall\" || (b.type === \"text\" && (b as TextContent).text.trim().length > 0),\n\t\t\t\t);\n\t\t\t\tshouldReplayReasoning = !isIncomplete && hasPairedContent;\n\t\t\t\tallowToolCalls = !isIncomplete;\n\t\t\t}\n\n\t\t\tfor (const block of msg.content) {\n\t\t\t\t// Do not submit thinking blocks if the completion had an error (i.e. abort)\n\t\t\t\tif (block.type === \"thinking\" && shouldReplayReasoning) {\n\t\t\t\t\tif (block.thinkingSignature) {\n\t\t\t\t\t\tconst reasoningItem = JSON.parse(block.thinkingSignature);\n\t\t\t\t\t\toutput.push(reasoningItem);\n\t\t\t\t\t}\n\t\t\t\t} else if (block.type === \"text\") {\n\t\t\t\t\tconst textBlock = block as TextContent;\n\t\t\t\t\t// OpenAI requires id to be max 64 characters\n\t\t\t\t\tlet msgId = textBlock.textSignature;\n\t\t\t\t\tif (!msgId) {\n\t\t\t\t\t\tmsgId = `msg_${msgIndex}`;\n\t\t\t\t\t}\n\t\t\t\t\t// For incomplete turns, never replay the original message id (if any).\n\t\t\t\t\t// Generate a stable synthetic id so strict pairing providers do not expect a paired reasoning item.\n\t\t\t\t\tif (strictResponsesPairing && isIncomplete) {\n\t\t\t\t\t\tmsgId = `msg_${msgIndex}_${shortHash(textBlock.text)}`;\n\t\t\t\t\t} else if (msgId.length > 64) {\n\t\t\t\t\t\tmsgId = `msg_${shortHash(msgId)}`;\n\t\t\t\t\t}\n\t\t\t\t\toutput.push({\n\t\t\t\t\t\ttype: \"message\",\n\t\t\t\t\t\trole: \"assistant\",\n\t\t\t\t\t\tcontent: [{ type: \"output_text\", text: sanitizeSurrogates(textBlock.text), annotations: [] }],\n\t\t\t\t\t\tstatus: \"completed\",\n\t\t\t\t\t\tid: msgId,\n\t\t\t\t\t} satisfies ResponseOutputMessage);\n\t\t\t\t\t// Do not submit toolcall blocks if the completion had an error (i.e. abort)\n\t\t\t\t} else if (block.type === \"toolCall\" && allowToolCalls) {\n\t\t\t\t\tconst toolCall = block as ToolCall;\n\t\t\t\t\toutput.push({\n\t\t\t\t\t\ttype: \"function_call\",\n\t\t\t\t\t\tid: toolCall.id.split(\"|\")[1],\n\t\t\t\t\t\tcall_id: toolCall.id.split(\"|\")[0],\n\t\t\t\t\t\tname: toolCall.name,\n\t\t\t\t\t\targuments: JSON.stringify(toolCall.arguments),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (output.length === 0) continue;\n\t\t\tmessages.push(...output);\n\t\t} else if (msg.role === \"toolResult\") {\n\t\t\t// Extract text and image content\n\t\t\tconst textResult = msg.content\n\t\t\t\t.filter((c) => c.type === \"text\")\n\t\t\t\t.map((c) => (c as any).text)\n\t\t\t\t.join(\"\\n\");\n\t\t\tconst hasImages = msg.content.some((c) => c.type === \"image\");\n\n\t\t\t// Always send function_call_output with text (or placeholder if only images)\n\t\t\tconst hasText = textResult.length > 0;\n\t\t\tmessages.push({\n\t\t\t\ttype: \"function_call_output\",\n\t\t\t\tcall_id: msg.toolCallId.split(\"|\")[0],\n\t\t\t\toutput: sanitizeSurrogates(hasText ? textResult : \"(see attached image)\"),\n\t\t\t});\n\n\t\t\t// If there are images and model supports them, send a follow-up user message with images\n\t\t\tif (hasImages && model.input.includes(\"image\")) {\n\t\t\t\tconst contentParts: ResponseInputContent[] = [];\n\n\t\t\t\t// Add text prefix\n\t\t\t\tcontentParts.push({\n\t\t\t\t\ttype: \"input_text\",\n\t\t\t\t\ttext: \"Attached image(s) from tool result:\",\n\t\t\t\t} satisfies ResponseInputText);\n\n\t\t\t\t// Add images\n\t\t\t\tfor (const block of msg.content) {\n\t\t\t\t\tif (block.type === \"image\") {\n\t\t\t\t\t\tcontentParts.push({\n\t\t\t\t\t\t\ttype: \"input_image\",\n\t\t\t\t\t\t\tdetail: \"auto\",\n\t\t\t\t\t\t\timage_url: `data:${(block as any).mimeType};base64,${(block as any).data}`,\n\t\t\t\t\t\t} satisfies ResponseInputImage);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tmessages.push({\n\t\t\t\t\trole: \"user\",\n\t\t\t\t\tcontent: contentParts,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tmsgIndex++;\n\t}\n\n\treturn messages;\n}\n\nfunction convertTools(tools: Tool[]): OpenAITool[] {\n\treturn tools.map((tool) => ({\n\t\ttype: \"function\",\n\t\tname: tool.name,\n\t\tdescription: tool.description,\n\t\tparameters: tool.parameters as any, // TypeBox already generates JSON Schema\n\t\tstrict: false,\n\t}));\n}\n\nfunction getServiceTierCostMultiplier(serviceTier: ResponseCreateParamsStreaming[\"service_tier\"] | undefined): number {\n\tswitch (serviceTier) {\n\t\tcase \"flex\":\n\t\t\treturn 0.5;\n\t\tcase \"priority\":\n\t\t\treturn 2;\n\t\tdefault:\n\t\t\treturn 1;\n\t}\n}\n\nfunction applyServiceTierPricing(usage: Usage, serviceTier: ResponseCreateParamsStreaming[\"service_tier\"] | undefined) {\n\tconst multiplier = getServiceTierCostMultiplier(serviceTier);\n\tif (multiplier === 1) return;\n\n\tusage.cost.input *= multiplier;\n\tusage.cost.output *= multiplier;\n\tusage.cost.cacheRead *= multiplier;\n\tusage.cost.cacheWrite *= multiplier;\n\tusage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;\n}\n\nfunction mapStopReason(status: OpenAI.Responses.ResponseStatus | undefined): StopReason {\n\tif (!status) return \"stop\";\n\tswitch (status) {\n\t\tcase \"completed\":\n\t\t\treturn \"stop\";\n\t\tcase \"incomplete\":\n\t\t\treturn \"length\";\n\t\tcase \"failed\":\n\t\tcase \"cancelled\":\n\t\t\treturn \"error\";\n\t\t// These two are wonky ...\n\t\tcase \"in_progress\":\n\t\tcase \"queued\":\n\t\t\treturn \"stop\";\n\t\tdefault: {\n\t\t\tconst _exhaustive: never = status;\n\t\t\tthrow new Error(`Unhandled stop reason: ${_exhaustive}`);\n\t\t}\n\t}\n}\n"]}
@@ -1,3 +1,8 @@
1
- import type { Api, Message, Model } from "../types.js";
2
- export declare function transformMessages<TApi extends Api>(messages: Message[], model: Model<TApi>): Message[];
1
+ import type { Api, AssistantMessage, Message, Model } from "../types.js";
2
+ /**
3
+ * Normalize tool call ID for cross-provider compatibility.
4
+ * OpenAI Responses API generates IDs that are 450+ chars with special characters like `|`.
5
+ * Anthropic APIs require IDs matching ^[a-zA-Z0-9_-]+$ (max 64 chars).
6
+ */
7
+ export declare function transformMessages<TApi extends Api>(messages: Message[], model: Model<TApi>, normalizeToolCallId?: (id: string, model: Model<TApi>, source: AssistantMessage) => string): Message[];
3
8
  //# sourceMappingURL=transform-messages.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"transform-messages.d.ts","sourceRoot":"","sources":["../../src/providers/transform-messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAoB,OAAO,EAAE,KAAK,EAA+B,MAAM,aAAa,CAAC;AAWtG,wBAAgB,iBAAiB,CAAC,IAAI,SAAS,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,EAAE,CAkJtG","sourcesContent":["import type { Api, AssistantMessage, Message, Model, ToolCall, ToolResultMessage } from \"../types.js\";\n\n/**\n * Normalize tool call ID for cross-provider compatibility.\n * OpenAI Responses API generates IDs that are 450+ chars with special characters like `|`.\n * Anthropic APIs require IDs matching ^[a-zA-Z0-9_-]+$ (max 64 chars).\n */\nfunction normalizeToolCallId(id: string): string {\n\treturn id.replace(/[^a-zA-Z0-9_-]/g, \"\").slice(0, 40);\n}\n\nexport function transformMessages<TApi extends Api>(messages: Message[], model: Model<TApi>): Message[] {\n\t// Build a map of original tool call IDs to normalized IDs for github-copilot cross-API switches\n\tconst toolCallIdMap = new Map<string, string>();\n\n\t// First pass: transform messages (thinking blocks, tool call ID normalization)\n\tconst transformed = messages.map((msg) => {\n\t\t// User messages pass through unchanged\n\t\tif (msg.role === \"user\") {\n\t\t\treturn msg;\n\t\t}\n\n\t\t// Handle toolResult messages - normalize toolCallId if we have a mapping\n\t\tif (msg.role === \"toolResult\") {\n\t\t\tconst normalizedId = toolCallIdMap.get(msg.toolCallId);\n\t\t\tif (normalizedId && normalizedId !== msg.toolCallId) {\n\t\t\t\treturn { ...msg, toolCallId: normalizedId };\n\t\t\t}\n\t\t\treturn msg;\n\t\t}\n\n\t\t// Assistant messages need transformation check\n\t\tif (msg.role === \"assistant\") {\n\t\t\tconst assistantMsg = msg as AssistantMessage;\n\n\t\t\t// If message is from the same provider and API, keep as is\n\t\t\tif (assistantMsg.provider === model.provider && assistantMsg.api === model.api) {\n\t\t\t\treturn msg;\n\t\t\t}\n\n\t\t\t// Check if we need to normalize tool call IDs\n\t\t\t// Anthropic APIs require IDs matching ^[a-zA-Z0-9_-]+$ (max 64 chars)\n\t\t\t// OpenAI Responses API generates IDs with `|` and 450+ chars\n\t\t\t// GitHub Copilot routes to Anthropic for Claude models\n\t\t\tconst targetRequiresStrictIds = model.api === \"anthropic-messages\" || model.provider === \"github-copilot\";\n\t\t\tconst crossProviderSwitch = assistantMsg.provider !== model.provider;\n\t\t\tconst copilotCrossApiSwitch =\n\t\t\t\tassistantMsg.provider === \"github-copilot\" &&\n\t\t\t\tmodel.provider === \"github-copilot\" &&\n\t\t\t\tassistantMsg.api !== model.api;\n\t\t\tconst needsToolCallIdNormalization = targetRequiresStrictIds && (crossProviderSwitch || copilotCrossApiSwitch);\n\n\t\t\t// Transform message from different provider/model\n\t\t\tconst transformedContent = assistantMsg.content.flatMap((block) => {\n\t\t\t\tif (block.type === \"thinking\") {\n\t\t\t\t\t// Skip empty thinking blocks, convert others to plain text\n\t\t\t\t\tif (!block.thinking || block.thinking.trim() === \"\") return [];\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\ttext: block.thinking,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\t// Normalize tool call IDs when target API requires strict format\n\t\t\t\tif (block.type === \"toolCall\" && needsToolCallIdNormalization) {\n\t\t\t\t\tconst toolCall = block as ToolCall;\n\t\t\t\t\tconst normalizedId = normalizeToolCallId(toolCall.id);\n\t\t\t\t\tif (normalizedId !== toolCall.id) {\n\t\t\t\t\t\ttoolCallIdMap.set(toolCall.id, normalizedId);\n\t\t\t\t\t\treturn { ...toolCall, id: normalizedId };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// All other blocks pass through unchanged\n\t\t\t\treturn block;\n\t\t\t});\n\n\t\t\t// Return transformed assistant message\n\t\t\treturn {\n\t\t\t\t...assistantMsg,\n\t\t\t\tcontent: transformedContent,\n\t\t\t};\n\t\t}\n\t\treturn msg;\n\t});\n\n\t// Second pass: insert synthetic empty tool results for orphaned tool calls\n\t// This preserves thinking signatures and satisfies API requirements\n\tconst result: Message[] = [];\n\tlet pendingToolCalls: ToolCall[] = [];\n\tlet existingToolResultIds = new Set<string>();\n\n\tfor (let i = 0; i < transformed.length; i++) {\n\t\tconst msg = transformed[i];\n\n\t\tif (msg.role === \"assistant\") {\n\t\t\t// If we have pending orphaned tool calls from a previous assistant, insert synthetic results now\n\t\t\tif (pendingToolCalls.length > 0) {\n\t\t\t\tfor (const tc of pendingToolCalls) {\n\t\t\t\t\tif (!existingToolResultIds.has(tc.id)) {\n\t\t\t\t\t\tresult.push({\n\t\t\t\t\t\t\trole: \"toolResult\",\n\t\t\t\t\t\t\ttoolCallId: tc.id,\n\t\t\t\t\t\t\ttoolName: tc.name,\n\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"No result provided\" }],\n\t\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\t} as ToolResultMessage);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tpendingToolCalls = [];\n\t\t\t\texistingToolResultIds = new Set();\n\t\t\t}\n\n\t\t\t// Track tool calls from this assistant message\n\t\t\tconst assistantMsg = msg as AssistantMessage;\n\t\t\tconst toolCalls = assistantMsg.content.filter((b) => b.type === \"toolCall\") as ToolCall[];\n\t\t\tif (toolCalls.length > 0) {\n\t\t\t\tpendingToolCalls = toolCalls;\n\t\t\t\texistingToolResultIds = new Set();\n\t\t\t}\n\n\t\t\t// Skip empty assistant messages (no content and no tool calls)\n\t\t\t// This handles error responses (e.g., 429/500) that produced no content\n\t\t\t// All providers already filter these in convertMessages, but we do it here\n\t\t\t// centrally to prevent issues with the tool_use -> tool_result chain\n\t\t\tif (assistantMsg.content.length === 0 && toolCalls.length === 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tresult.push(msg);\n\t\t} else if (msg.role === \"toolResult\") {\n\t\t\texistingToolResultIds.add(msg.toolCallId);\n\t\t\tresult.push(msg);\n\t\t} else if (msg.role === \"user\") {\n\t\t\t// User message interrupts tool flow - insert synthetic results for orphaned calls\n\t\t\tif (pendingToolCalls.length > 0) {\n\t\t\t\tfor (const tc of pendingToolCalls) {\n\t\t\t\t\tif (!existingToolResultIds.has(tc.id)) {\n\t\t\t\t\t\tresult.push({\n\t\t\t\t\t\t\trole: \"toolResult\",\n\t\t\t\t\t\t\ttoolCallId: tc.id,\n\t\t\t\t\t\t\ttoolName: tc.name,\n\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"No result provided\" }],\n\t\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\t} as ToolResultMessage);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tpendingToolCalls = [];\n\t\t\t\texistingToolResultIds = new Set();\n\t\t\t}\n\t\t\tresult.push(msg);\n\t\t} else {\n\t\t\tresult.push(msg);\n\t\t}\n\t}\n\n\treturn result;\n}\n"]}
1
+ {"version":3,"file":"transform-messages.d.ts","sourceRoot":"","sources":["../../src/providers/transform-messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,gBAAgB,EAAE,OAAO,EAAE,KAAK,EAA+B,MAAM,aAAa,CAAC;AAEtG;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,SAAS,GAAG,EACjD,QAAQ,EAAE,OAAO,EAAE,EACnB,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAClB,mBAAmB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,gBAAgB,KAAK,MAAM,GACxF,OAAO,EAAE,CA+JX","sourcesContent":["import type { Api, AssistantMessage, Message, Model, ToolCall, ToolResultMessage } from \"../types.js\";\n\n/**\n * Normalize tool call ID for cross-provider compatibility.\n * OpenAI Responses API generates IDs that are 450+ chars with special characters like `|`.\n * Anthropic APIs require IDs matching ^[a-zA-Z0-9_-]+$ (max 64 chars).\n */\nexport function transformMessages<TApi extends Api>(\n\tmessages: Message[],\n\tmodel: Model<TApi>,\n\tnormalizeToolCallId?: (id: string, model: Model<TApi>, source: AssistantMessage) => string,\n): Message[] {\n\t// Build a map of original tool call IDs to normalized IDs\n\tconst toolCallIdMap = new Map<string, string>();\n\n\t// First pass: transform messages (thinking blocks, tool call ID normalization)\n\tconst transformed = messages.map((msg) => {\n\t\t// User messages pass through unchanged\n\t\tif (msg.role === \"user\") {\n\t\t\treturn msg;\n\t\t}\n\n\t\t// Handle toolResult messages - normalize toolCallId if we have a mapping\n\t\tif (msg.role === \"toolResult\") {\n\t\t\tconst normalizedId = toolCallIdMap.get(msg.toolCallId);\n\t\t\tif (normalizedId && normalizedId !== msg.toolCallId) {\n\t\t\t\treturn { ...msg, toolCallId: normalizedId };\n\t\t\t}\n\t\t\treturn msg;\n\t\t}\n\n\t\t// Assistant messages need transformation check\n\t\tif (msg.role === \"assistant\") {\n\t\t\tconst assistantMsg = msg as AssistantMessage;\n\t\t\tconst isSameModel =\n\t\t\t\tassistantMsg.provider === model.provider &&\n\t\t\t\tassistantMsg.api === model.api &&\n\t\t\t\tassistantMsg.model === model.id;\n\n\t\t\tconst transformedContent = assistantMsg.content.flatMap((block) => {\n\t\t\t\tif (block.type === \"thinking\") {\n\t\t\t\t\t// For same model: keep thinking blocks with signatures (needed for replay)\n\t\t\t\t\t// even if the thinking text is empty (OpenAI encrypted reasoning)\n\t\t\t\t\tif (isSameModel && block.thinkingSignature) return block;\n\t\t\t\t\t// Skip empty thinking blocks, convert others to plain text\n\t\t\t\t\tif (!block.thinking || block.thinking.trim() === \"\") return [];\n\t\t\t\t\tif (isSameModel) return block;\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\ttext: block.thinking,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tif (block.type === \"text\") {\n\t\t\t\t\tif (isSameModel) return block;\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\ttext: block.text,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tif (block.type === \"toolCall\") {\n\t\t\t\t\tconst toolCall = block as ToolCall;\n\t\t\t\t\tlet normalizedToolCall: ToolCall = toolCall;\n\n\t\t\t\t\tif (!isSameModel && toolCall.thoughtSignature) {\n\t\t\t\t\t\tnormalizedToolCall = { ...toolCall };\n\t\t\t\t\t\tdelete (normalizedToolCall as { thoughtSignature?: string }).thoughtSignature;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!isSameModel && normalizeToolCallId) {\n\t\t\t\t\t\tconst normalizedId = normalizeToolCallId(toolCall.id, model, assistantMsg);\n\t\t\t\t\t\tif (normalizedId !== toolCall.id) {\n\t\t\t\t\t\t\ttoolCallIdMap.set(toolCall.id, normalizedId);\n\t\t\t\t\t\t\tnormalizedToolCall = { ...normalizedToolCall, id: normalizedId };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn normalizedToolCall;\n\t\t\t\t}\n\n\t\t\t\treturn block;\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\t...assistantMsg,\n\t\t\t\tcontent: transformedContent,\n\t\t\t};\n\t\t}\n\t\treturn msg;\n\t});\n\n\t// Second pass: insert synthetic empty tool results for orphaned tool calls\n\t// This preserves thinking signatures and satisfies API requirements\n\tconst result: Message[] = [];\n\tlet pendingToolCalls: ToolCall[] = [];\n\tlet existingToolResultIds = new Set<string>();\n\n\tfor (let i = 0; i < transformed.length; i++) {\n\t\tconst msg = transformed[i];\n\n\t\tif (msg.role === \"assistant\") {\n\t\t\t// If we have pending orphaned tool calls from a previous assistant, insert synthetic results now\n\t\t\tif (pendingToolCalls.length > 0) {\n\t\t\t\tfor (const tc of pendingToolCalls) {\n\t\t\t\t\tif (!existingToolResultIds.has(tc.id)) {\n\t\t\t\t\t\tresult.push({\n\t\t\t\t\t\t\trole: \"toolResult\",\n\t\t\t\t\t\t\ttoolCallId: tc.id,\n\t\t\t\t\t\t\ttoolName: tc.name,\n\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"No result provided\" }],\n\t\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\t} as ToolResultMessage);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tpendingToolCalls = [];\n\t\t\t\texistingToolResultIds = new Set();\n\t\t\t}\n\n\t\t\t// Track tool calls from this assistant message\n\t\t\t// Don't track tool calls from errored messages - they will be dropped by\n\t\t\t// provider-specific converters, so we shouldn't create synthetic results for them\n\t\t\tconst assistantMsg = msg as AssistantMessage;\n\t\t\tconst toolCalls =\n\t\t\t\tassistantMsg.stopReason === \"error\"\n\t\t\t\t\t? []\n\t\t\t\t\t: (assistantMsg.content.filter((b) => b.type === \"toolCall\") as ToolCall[]);\n\t\t\tif (toolCalls.length > 0) {\n\t\t\t\tpendingToolCalls = toolCalls;\n\t\t\t\texistingToolResultIds = new Set();\n\t\t\t}\n\n\t\t\t// Skip empty assistant messages (no content and no tool calls)\n\t\t\t// This handles error responses (e.g., 429/500) that produced no content\n\t\t\t// All providers already filter these in convertMessages, but we do it here\n\t\t\t// centrally to prevent issues with the tool_use -> tool_result chain\n\t\t\tif (assistantMsg.content.length === 0 && toolCalls.length === 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tresult.push(msg);\n\t\t} else if (msg.role === \"toolResult\") {\n\t\t\texistingToolResultIds.add(msg.toolCallId);\n\t\t\tresult.push(msg);\n\t\t} else if (msg.role === \"user\") {\n\t\t\t// User message interrupts tool flow - insert synthetic results for orphaned calls\n\t\t\tif (pendingToolCalls.length > 0) {\n\t\t\t\tfor (const tc of pendingToolCalls) {\n\t\t\t\t\tif (!existingToolResultIds.has(tc.id)) {\n\t\t\t\t\t\tresult.push({\n\t\t\t\t\t\t\trole: \"toolResult\",\n\t\t\t\t\t\t\ttoolCallId: tc.id,\n\t\t\t\t\t\t\ttoolName: tc.name,\n\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"No result provided\" }],\n\t\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\t} as ToolResultMessage);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tpendingToolCalls = [];\n\t\t\t\texistingToolResultIds = new Set();\n\t\t\t}\n\t\t\tresult.push(msg);\n\t\t} else {\n\t\t\tresult.push(msg);\n\t\t}\n\t}\n\n\treturn result;\n}\n"]}
@@ -3,11 +3,8 @@
3
3
  * OpenAI Responses API generates IDs that are 450+ chars with special characters like `|`.
4
4
  * Anthropic APIs require IDs matching ^[a-zA-Z0-9_-]+$ (max 64 chars).
5
5
  */
6
- function normalizeToolCallId(id) {
7
- return id.replace(/[^a-zA-Z0-9_-]/g, "").slice(0, 40);
8
- }
9
- export function transformMessages(messages, model) {
10
- // Build a map of original tool call IDs to normalized IDs for github-copilot cross-API switches
6
+ export function transformMessages(messages, model, normalizeToolCallId) {
7
+ // Build a map of original tool call IDs to normalized IDs
11
8
  const toolCallIdMap = new Map();
12
9
  // First pass: transform messages (thinking blocks, tool call ID normalization)
13
10
  const transformed = messages.map((msg) => {
@@ -26,44 +23,51 @@ export function transformMessages(messages, model) {
26
23
  // Assistant messages need transformation check
27
24
  if (msg.role === "assistant") {
28
25
  const assistantMsg = msg;
29
- // If message is from the same provider and API, keep as is
30
- if (assistantMsg.provider === model.provider && assistantMsg.api === model.api) {
31
- return msg;
32
- }
33
- // Check if we need to normalize tool call IDs
34
- // Anthropic APIs require IDs matching ^[a-zA-Z0-9_-]+$ (max 64 chars)
35
- // OpenAI Responses API generates IDs with `|` and 450+ chars
36
- // GitHub Copilot routes to Anthropic for Claude models
37
- const targetRequiresStrictIds = model.api === "anthropic-messages" || model.provider === "github-copilot";
38
- const crossProviderSwitch = assistantMsg.provider !== model.provider;
39
- const copilotCrossApiSwitch = assistantMsg.provider === "github-copilot" &&
40
- model.provider === "github-copilot" &&
41
- assistantMsg.api !== model.api;
42
- const needsToolCallIdNormalization = targetRequiresStrictIds && (crossProviderSwitch || copilotCrossApiSwitch);
43
- // Transform message from different provider/model
26
+ const isSameModel = assistantMsg.provider === model.provider &&
27
+ assistantMsg.api === model.api &&
28
+ assistantMsg.model === model.id;
44
29
  const transformedContent = assistantMsg.content.flatMap((block) => {
45
30
  if (block.type === "thinking") {
31
+ // For same model: keep thinking blocks with signatures (needed for replay)
32
+ // even if the thinking text is empty (OpenAI encrypted reasoning)
33
+ if (isSameModel && block.thinkingSignature)
34
+ return block;
46
35
  // Skip empty thinking blocks, convert others to plain text
47
36
  if (!block.thinking || block.thinking.trim() === "")
48
37
  return [];
38
+ if (isSameModel)
39
+ return block;
49
40
  return {
50
41
  type: "text",
51
42
  text: block.thinking,
52
43
  };
53
44
  }
54
- // Normalize tool call IDs when target API requires strict format
55
- if (block.type === "toolCall" && needsToolCallIdNormalization) {
45
+ if (block.type === "text") {
46
+ if (isSameModel)
47
+ return block;
48
+ return {
49
+ type: "text",
50
+ text: block.text,
51
+ };
52
+ }
53
+ if (block.type === "toolCall") {
56
54
  const toolCall = block;
57
- const normalizedId = normalizeToolCallId(toolCall.id);
58
- if (normalizedId !== toolCall.id) {
59
- toolCallIdMap.set(toolCall.id, normalizedId);
60
- return { ...toolCall, id: normalizedId };
55
+ let normalizedToolCall = toolCall;
56
+ if (!isSameModel && toolCall.thoughtSignature) {
57
+ normalizedToolCall = { ...toolCall };
58
+ delete normalizedToolCall.thoughtSignature;
59
+ }
60
+ if (!isSameModel && normalizeToolCallId) {
61
+ const normalizedId = normalizeToolCallId(toolCall.id, model, assistantMsg);
62
+ if (normalizedId !== toolCall.id) {
63
+ toolCallIdMap.set(toolCall.id, normalizedId);
64
+ normalizedToolCall = { ...normalizedToolCall, id: normalizedId };
65
+ }
61
66
  }
67
+ return normalizedToolCall;
62
68
  }
63
- // All other blocks pass through unchanged
64
69
  return block;
65
70
  });
66
- // Return transformed assistant message
67
71
  return {
68
72
  ...assistantMsg,
69
73
  content: transformedContent,
@@ -97,8 +101,12 @@ export function transformMessages(messages, model) {
97
101
  existingToolResultIds = new Set();
98
102
  }
99
103
  // Track tool calls from this assistant message
104
+ // Don't track tool calls from errored messages - they will be dropped by
105
+ // provider-specific converters, so we shouldn't create synthetic results for them
100
106
  const assistantMsg = msg;
101
- const toolCalls = assistantMsg.content.filter((b) => b.type === "toolCall");
107
+ const toolCalls = assistantMsg.stopReason === "error"
108
+ ? []
109
+ : assistantMsg.content.filter((b) => b.type === "toolCall");
102
110
  if (toolCalls.length > 0) {
103
111
  pendingToolCalls = toolCalls;
104
112
  existingToolResultIds = new Set();
@@ -1 +1 @@
1
- {"version":3,"file":"transform-messages.js","sourceRoot":"","sources":["../../src/providers/transform-messages.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Api, AssistantMessage, Message, Model, ToolCall, ToolResultMessage } from \"../types.js\";\n\n/**\n * Normalize tool call ID for cross-provider compatibility.\n * OpenAI Responses API generates IDs that are 450+ chars with special characters like `|`.\n * Anthropic APIs require IDs matching ^[a-zA-Z0-9_-]+$ (max 64 chars).\n */\nfunction normalizeToolCallId(id: string): string {\n\treturn id.replace(/[^a-zA-Z0-9_-]/g, \"\").slice(0, 40);\n}\n\nexport function transformMessages<TApi extends Api>(messages: Message[], model: Model<TApi>): Message[] {\n\t// Build a map of original tool call IDs to normalized IDs for github-copilot cross-API switches\n\tconst toolCallIdMap = new Map<string, string>();\n\n\t// First pass: transform messages (thinking blocks, tool call ID normalization)\n\tconst transformed = messages.map((msg) => {\n\t\t// User messages pass through unchanged\n\t\tif (msg.role === \"user\") {\n\t\t\treturn msg;\n\t\t}\n\n\t\t// Handle toolResult messages - normalize toolCallId if we have a mapping\n\t\tif (msg.role === \"toolResult\") {\n\t\t\tconst normalizedId = toolCallIdMap.get(msg.toolCallId);\n\t\t\tif (normalizedId && normalizedId !== msg.toolCallId) {\n\t\t\t\treturn { ...msg, toolCallId: normalizedId };\n\t\t\t}\n\t\t\treturn msg;\n\t\t}\n\n\t\t// Assistant messages need transformation check\n\t\tif (msg.role === \"assistant\") {\n\t\t\tconst assistantMsg = msg as AssistantMessage;\n\n\t\t\t// If message is from the same provider and API, keep as is\n\t\t\tif (assistantMsg.provider === model.provider && assistantMsg.api === model.api) {\n\t\t\t\treturn msg;\n\t\t\t}\n\n\t\t\t// Check if we need to normalize tool call IDs\n\t\t\t// Anthropic APIs require IDs matching ^[a-zA-Z0-9_-]+$ (max 64 chars)\n\t\t\t// OpenAI Responses API generates IDs with `|` and 450+ chars\n\t\t\t// GitHub Copilot routes to Anthropic for Claude models\n\t\t\tconst targetRequiresStrictIds = model.api === \"anthropic-messages\" || model.provider === \"github-copilot\";\n\t\t\tconst crossProviderSwitch = assistantMsg.provider !== model.provider;\n\t\t\tconst copilotCrossApiSwitch =\n\t\t\t\tassistantMsg.provider === \"github-copilot\" &&\n\t\t\t\tmodel.provider === \"github-copilot\" &&\n\t\t\t\tassistantMsg.api !== model.api;\n\t\t\tconst needsToolCallIdNormalization = targetRequiresStrictIds && (crossProviderSwitch || copilotCrossApiSwitch);\n\n\t\t\t// Transform message from different provider/model\n\t\t\tconst transformedContent = assistantMsg.content.flatMap((block) => {\n\t\t\t\tif (block.type === \"thinking\") {\n\t\t\t\t\t// Skip empty thinking blocks, convert others to plain text\n\t\t\t\t\tif (!block.thinking || block.thinking.trim() === \"\") return [];\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\ttext: block.thinking,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\t// Normalize tool call IDs when target API requires strict format\n\t\t\t\tif (block.type === \"toolCall\" && needsToolCallIdNormalization) {\n\t\t\t\t\tconst toolCall = block as ToolCall;\n\t\t\t\t\tconst normalizedId = normalizeToolCallId(toolCall.id);\n\t\t\t\t\tif (normalizedId !== toolCall.id) {\n\t\t\t\t\t\ttoolCallIdMap.set(toolCall.id, normalizedId);\n\t\t\t\t\t\treturn { ...toolCall, id: normalizedId };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// All other blocks pass through unchanged\n\t\t\t\treturn block;\n\t\t\t});\n\n\t\t\t// Return transformed assistant message\n\t\t\treturn {\n\t\t\t\t...assistantMsg,\n\t\t\t\tcontent: transformedContent,\n\t\t\t};\n\t\t}\n\t\treturn msg;\n\t});\n\n\t// Second pass: insert synthetic empty tool results for orphaned tool calls\n\t// This preserves thinking signatures and satisfies API requirements\n\tconst result: Message[] = [];\n\tlet pendingToolCalls: ToolCall[] = [];\n\tlet existingToolResultIds = new Set<string>();\n\n\tfor (let i = 0; i < transformed.length; i++) {\n\t\tconst msg = transformed[i];\n\n\t\tif (msg.role === \"assistant\") {\n\t\t\t// If we have pending orphaned tool calls from a previous assistant, insert synthetic results now\n\t\t\tif (pendingToolCalls.length > 0) {\n\t\t\t\tfor (const tc of pendingToolCalls) {\n\t\t\t\t\tif (!existingToolResultIds.has(tc.id)) {\n\t\t\t\t\t\tresult.push({\n\t\t\t\t\t\t\trole: \"toolResult\",\n\t\t\t\t\t\t\ttoolCallId: tc.id,\n\t\t\t\t\t\t\ttoolName: tc.name,\n\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"No result provided\" }],\n\t\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\t} as ToolResultMessage);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tpendingToolCalls = [];\n\t\t\t\texistingToolResultIds = new Set();\n\t\t\t}\n\n\t\t\t// Track tool calls from this assistant message\n\t\t\tconst assistantMsg = msg as AssistantMessage;\n\t\t\tconst toolCalls = assistantMsg.content.filter((b) => b.type === \"toolCall\") as ToolCall[];\n\t\t\tif (toolCalls.length > 0) {\n\t\t\t\tpendingToolCalls = toolCalls;\n\t\t\t\texistingToolResultIds = new Set();\n\t\t\t}\n\n\t\t\t// Skip empty assistant messages (no content and no tool calls)\n\t\t\t// This handles error responses (e.g., 429/500) that produced no content\n\t\t\t// All providers already filter these in convertMessages, but we do it here\n\t\t\t// centrally to prevent issues with the tool_use -> tool_result chain\n\t\t\tif (assistantMsg.content.length === 0 && toolCalls.length === 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tresult.push(msg);\n\t\t} else if (msg.role === \"toolResult\") {\n\t\t\texistingToolResultIds.add(msg.toolCallId);\n\t\t\tresult.push(msg);\n\t\t} else if (msg.role === \"user\") {\n\t\t\t// User message interrupts tool flow - insert synthetic results for orphaned calls\n\t\t\tif (pendingToolCalls.length > 0) {\n\t\t\t\tfor (const tc of pendingToolCalls) {\n\t\t\t\t\tif (!existingToolResultIds.has(tc.id)) {\n\t\t\t\t\t\tresult.push({\n\t\t\t\t\t\t\trole: \"toolResult\",\n\t\t\t\t\t\t\ttoolCallId: tc.id,\n\t\t\t\t\t\t\ttoolName: tc.name,\n\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"No result provided\" }],\n\t\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\t} as ToolResultMessage);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tpendingToolCalls = [];\n\t\t\t\texistingToolResultIds = new Set();\n\t\t\t}\n\t\t\tresult.push(msg);\n\t\t} else {\n\t\t\tresult.push(msg);\n\t\t}\n\t}\n\n\treturn result;\n}\n"]}
1
+ {"version":3,"file":"transform-messages.js","sourceRoot":"","sources":["../../src/providers/transform-messages.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Api, AssistantMessage, Message, Model, ToolCall, ToolResultMessage } from \"../types.js\";\n\n/**\n * Normalize tool call ID for cross-provider compatibility.\n * OpenAI Responses API generates IDs that are 450+ chars with special characters like `|`.\n * Anthropic APIs require IDs matching ^[a-zA-Z0-9_-]+$ (max 64 chars).\n */\nexport function transformMessages<TApi extends Api>(\n\tmessages: Message[],\n\tmodel: Model<TApi>,\n\tnormalizeToolCallId?: (id: string, model: Model<TApi>, source: AssistantMessage) => string,\n): Message[] {\n\t// Build a map of original tool call IDs to normalized IDs\n\tconst toolCallIdMap = new Map<string, string>();\n\n\t// First pass: transform messages (thinking blocks, tool call ID normalization)\n\tconst transformed = messages.map((msg) => {\n\t\t// User messages pass through unchanged\n\t\tif (msg.role === \"user\") {\n\t\t\treturn msg;\n\t\t}\n\n\t\t// Handle toolResult messages - normalize toolCallId if we have a mapping\n\t\tif (msg.role === \"toolResult\") {\n\t\t\tconst normalizedId = toolCallIdMap.get(msg.toolCallId);\n\t\t\tif (normalizedId && normalizedId !== msg.toolCallId) {\n\t\t\t\treturn { ...msg, toolCallId: normalizedId };\n\t\t\t}\n\t\t\treturn msg;\n\t\t}\n\n\t\t// Assistant messages need transformation check\n\t\tif (msg.role === \"assistant\") {\n\t\t\tconst assistantMsg = msg as AssistantMessage;\n\t\t\tconst isSameModel =\n\t\t\t\tassistantMsg.provider === model.provider &&\n\t\t\t\tassistantMsg.api === model.api &&\n\t\t\t\tassistantMsg.model === model.id;\n\n\t\t\tconst transformedContent = assistantMsg.content.flatMap((block) => {\n\t\t\t\tif (block.type === \"thinking\") {\n\t\t\t\t\t// For same model: keep thinking blocks with signatures (needed for replay)\n\t\t\t\t\t// even if the thinking text is empty (OpenAI encrypted reasoning)\n\t\t\t\t\tif (isSameModel && block.thinkingSignature) return block;\n\t\t\t\t\t// Skip empty thinking blocks, convert others to plain text\n\t\t\t\t\tif (!block.thinking || block.thinking.trim() === \"\") return [];\n\t\t\t\t\tif (isSameModel) return block;\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\ttext: block.thinking,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tif (block.type === \"text\") {\n\t\t\t\t\tif (isSameModel) return block;\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\ttext: block.text,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tif (block.type === \"toolCall\") {\n\t\t\t\t\tconst toolCall = block as ToolCall;\n\t\t\t\t\tlet normalizedToolCall: ToolCall = toolCall;\n\n\t\t\t\t\tif (!isSameModel && toolCall.thoughtSignature) {\n\t\t\t\t\t\tnormalizedToolCall = { ...toolCall };\n\t\t\t\t\t\tdelete (normalizedToolCall as { thoughtSignature?: string }).thoughtSignature;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!isSameModel && normalizeToolCallId) {\n\t\t\t\t\t\tconst normalizedId = normalizeToolCallId(toolCall.id, model, assistantMsg);\n\t\t\t\t\t\tif (normalizedId !== toolCall.id) {\n\t\t\t\t\t\t\ttoolCallIdMap.set(toolCall.id, normalizedId);\n\t\t\t\t\t\t\tnormalizedToolCall = { ...normalizedToolCall, id: normalizedId };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn normalizedToolCall;\n\t\t\t\t}\n\n\t\t\t\treturn block;\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\t...assistantMsg,\n\t\t\t\tcontent: transformedContent,\n\t\t\t};\n\t\t}\n\t\treturn msg;\n\t});\n\n\t// Second pass: insert synthetic empty tool results for orphaned tool calls\n\t// This preserves thinking signatures and satisfies API requirements\n\tconst result: Message[] = [];\n\tlet pendingToolCalls: ToolCall[] = [];\n\tlet existingToolResultIds = new Set<string>();\n\n\tfor (let i = 0; i < transformed.length; i++) {\n\t\tconst msg = transformed[i];\n\n\t\tif (msg.role === \"assistant\") {\n\t\t\t// If we have pending orphaned tool calls from a previous assistant, insert synthetic results now\n\t\t\tif (pendingToolCalls.length > 0) {\n\t\t\t\tfor (const tc of pendingToolCalls) {\n\t\t\t\t\tif (!existingToolResultIds.has(tc.id)) {\n\t\t\t\t\t\tresult.push({\n\t\t\t\t\t\t\trole: \"toolResult\",\n\t\t\t\t\t\t\ttoolCallId: tc.id,\n\t\t\t\t\t\t\ttoolName: tc.name,\n\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"No result provided\" }],\n\t\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\t} as ToolResultMessage);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tpendingToolCalls = [];\n\t\t\t\texistingToolResultIds = new Set();\n\t\t\t}\n\n\t\t\t// Track tool calls from this assistant message\n\t\t\t// Don't track tool calls from errored messages - they will be dropped by\n\t\t\t// provider-specific converters, so we shouldn't create synthetic results for them\n\t\t\tconst assistantMsg = msg as AssistantMessage;\n\t\t\tconst toolCalls =\n\t\t\t\tassistantMsg.stopReason === \"error\"\n\t\t\t\t\t? []\n\t\t\t\t\t: (assistantMsg.content.filter((b) => b.type === \"toolCall\") as ToolCall[]);\n\t\t\tif (toolCalls.length > 0) {\n\t\t\t\tpendingToolCalls = toolCalls;\n\t\t\t\texistingToolResultIds = new Set();\n\t\t\t}\n\n\t\t\t// Skip empty assistant messages (no content and no tool calls)\n\t\t\t// This handles error responses (e.g., 429/500) that produced no content\n\t\t\t// All providers already filter these in convertMessages, but we do it here\n\t\t\t// centrally to prevent issues with the tool_use -> tool_result chain\n\t\t\tif (assistantMsg.content.length === 0 && toolCalls.length === 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tresult.push(msg);\n\t\t} else if (msg.role === \"toolResult\") {\n\t\t\texistingToolResultIds.add(msg.toolCallId);\n\t\t\tresult.push(msg);\n\t\t} else if (msg.role === \"user\") {\n\t\t\t// User message interrupts tool flow - insert synthetic results for orphaned calls\n\t\t\tif (pendingToolCalls.length > 0) {\n\t\t\t\tfor (const tc of pendingToolCalls) {\n\t\t\t\t\tif (!existingToolResultIds.has(tc.id)) {\n\t\t\t\t\t\tresult.push({\n\t\t\t\t\t\t\trole: \"toolResult\",\n\t\t\t\t\t\t\ttoolCallId: tc.id,\n\t\t\t\t\t\t\ttoolName: tc.name,\n\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"No result provided\" }],\n\t\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t\t} as ToolResultMessage);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tpendingToolCalls = [];\n\t\t\t\texistingToolResultIds = new Set();\n\t\t\t}\n\t\t\tresult.push(msg);\n\t\t} else {\n\t\t\tresult.push(msg);\n\t\t}\n\t}\n\n\treturn result;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EACX,GAAG,EACH,gBAAgB,EAChB,2BAA2B,EAC3B,OAAO,EACP,aAAa,EACb,KAAK,EACL,aAAa,EACb,mBAAmB,EAGnB,MAAM,YAAY,CAAC;AAoBpB;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,CAAC;AAC1E,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAyDnE,wBAAgB,MAAM,CAAC,IAAI,SAAS,GAAG,EACtC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,aAAa,CAAC,IAAI,CAAC,GAC3B,2BAA2B,CA6C7B;AAED,wBAAsB,QAAQ,CAAC,IAAI,SAAS,GAAG,EAC9C,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,aAAa,CAAC,IAAI,CAAC,GAC3B,OAAO,CAAC,gBAAgB,CAAC,CAG3B;AAED,wBAAgB,YAAY,CAAC,IAAI,SAAS,GAAG,EAC5C,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,mBAAmB,GAC3B,2BAA2B,CAkB7B;AAED,wBAAsB,cAAc,CAAC,IAAI,SAAS,GAAG,EACpD,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,mBAAmB,GAC3B,OAAO,CAAC,gBAAgB,CAAC,CAG3B","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { supportsXhigh } from \"./models.js\";\nimport { type BedrockOptions, streamBedrock } from \"./providers/amazon-bedrock.js\";\nimport { type AnthropicOptions, streamAnthropic } from \"./providers/anthropic.js\";\nimport { type GoogleOptions, streamGoogle } from \"./providers/google.js\";\nimport {\n\ttype GoogleGeminiCliOptions,\n\ttype GoogleThinkingLevel,\n\tstreamGoogleGeminiCli,\n} from \"./providers/google-gemini-cli.js\";\nimport { type GoogleVertexOptions, streamGoogleVertex } from \"./providers/google-vertex.js\";\nimport { type OpenAICodexResponsesOptions, streamOpenAICodexResponses } from \"./providers/openai-codex-responses.js\";\nimport { type OpenAICompletionsOptions, streamOpenAICompletions } from \"./providers/openai-completions.js\";\nimport { type OpenAIResponsesOptions, streamOpenAIResponses } from \"./providers/openai-responses.js\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tAssistantMessageEventStream,\n\tContext,\n\tKnownProvider,\n\tModel,\n\tOptionsForApi,\n\tSimpleStreamOptions,\n\tThinkingBudgets,\n\tThinkingLevel,\n} from \"./types.js\";\n\nlet cachedVertexAdcCredentialsExists: boolean | null = null;\n\nfunction hasVertexAdcCredentials(): boolean {\n\tif (cachedVertexAdcCredentialsExists === null) {\n\t\t// Check GOOGLE_APPLICATION_CREDENTIALS env var first (standard way)\n\t\tconst gacPath = process.env.GOOGLE_APPLICATION_CREDENTIALS;\n\t\tif (gacPath) {\n\t\t\tcachedVertexAdcCredentialsExists = existsSync(gacPath);\n\t\t} else {\n\t\t\t// Fall back to default ADC path (lazy evaluation)\n\t\t\tcachedVertexAdcCredentialsExists = existsSync(\n\t\t\t\tjoin(homedir(), \".config\", \"gcloud\", \"application_default_credentials.json\"),\n\t\t\t);\n\t\t}\n\t}\n\treturn cachedVertexAdcCredentialsExists;\n}\n\n/**\n * Get API key for provider from known environment variables, e.g. OPENAI_API_KEY.\n *\n * Will not return API keys for providers that require OAuth tokens.\n */\nexport function getEnvApiKey(provider: KnownProvider): string | undefined;\nexport function getEnvApiKey(provider: string): string | undefined;\nexport function getEnvApiKey(provider: any): string | undefined {\n\t// Fall back to environment variables\n\tif (provider === \"github-copilot\") {\n\t\treturn process.env.COPILOT_GITHUB_TOKEN || process.env.GH_TOKEN || process.env.GITHUB_TOKEN;\n\t}\n\n\t// ANTHROPIC_OAUTH_TOKEN takes precedence over ANTHROPIC_API_KEY\n\tif (provider === \"anthropic\") {\n\t\treturn process.env.ANTHROPIC_OAUTH_TOKEN || process.env.ANTHROPIC_API_KEY;\n\t}\n\n\t// Vertex AI uses Application Default Credentials, not API keys.\n\t// Auth is configured via `gcloud auth application-default login`.\n\tif (provider === \"google-vertex\") {\n\t\tconst hasCredentials = hasVertexAdcCredentials();\n\t\tconst hasProject = !!(process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT);\n\t\tconst hasLocation = !!process.env.GOOGLE_CLOUD_LOCATION;\n\n\t\tif (hasCredentials && hasProject && hasLocation) {\n\t\t\treturn \"<authenticated>\";\n\t\t}\n\t}\n\n\tif (provider === \"amazon-bedrock\") {\n\t\t// Amazon Bedrock supports multiple credential sources:\n\t\t// 1. AWS_PROFILE - named profile from ~/.aws/credentials\n\t\t// 2. AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY - standard IAM keys\n\t\t// 3. AWS_BEARER_TOKEN_BEDROCK - Bedrock API keys (bearer token)\n\t\tif (\n\t\t\tprocess.env.AWS_PROFILE ||\n\t\t\t(process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) ||\n\t\t\tprocess.env.AWS_BEARER_TOKEN_BEDROCK\n\t\t) {\n\t\t\treturn \"<authenticated>\";\n\t\t}\n\t}\n\n\tconst envMap: Record<string, string> = {\n\t\topenai: \"OPENAI_API_KEY\",\n\t\tgoogle: \"GEMINI_API_KEY\",\n\t\tgroq: \"GROQ_API_KEY\",\n\t\tcerebras: \"CEREBRAS_API_KEY\",\n\t\txai: \"XAI_API_KEY\",\n\t\topenrouter: \"OPENROUTER_API_KEY\",\n\t\t\"vercel-ai-gateway\": \"AI_GATEWAY_API_KEY\",\n\t\tzai: \"ZAI_API_KEY\",\n\t\tmistral: \"MISTRAL_API_KEY\",\n\t\tminimax: \"MINIMAX_API_KEY\",\n\t\t\"minimax-cn\": \"MINIMAX_CN_API_KEY\",\n\t\topencode: \"OPENCODE_API_KEY\",\n\t};\n\n\tconst envVar = envMap[provider];\n\treturn envVar ? process.env[envVar] : undefined;\n}\n\nexport function stream<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: OptionsForApi<TApi>,\n): AssistantMessageEventStream {\n\t// Vertex AI uses Application Default Credentials, not API keys\n\tif (model.api === \"google-vertex\") {\n\t\treturn streamGoogleVertex(model as Model<\"google-vertex\">, context, options as GoogleVertexOptions);\n\t} else if (model.api === \"bedrock-converse-stream\") {\n\t\t// Bedrock doesn't have any API keys instead it sources credentials from standard AWS env variables or from given AWS profile.\n\t\treturn streamBedrock(model as Model<\"bedrock-converse-stream\">, context, (options || {}) as BedrockOptions);\n\t}\n\n\tconst apiKey = options?.apiKey || getEnvApiKey(model.provider);\n\tif (!apiKey) {\n\t\tthrow new Error(`No API key for provider: ${model.provider}`);\n\t}\n\tconst providerOptions = { ...options, apiKey };\n\n\tconst api: Api = model.api;\n\tswitch (api) {\n\t\tcase \"anthropic-messages\":\n\t\t\treturn streamAnthropic(model as Model<\"anthropic-messages\">, context, providerOptions);\n\n\t\tcase \"openai-completions\":\n\t\t\treturn streamOpenAICompletions(model as Model<\"openai-completions\">, context, providerOptions as any);\n\n\t\tcase \"openai-responses\":\n\t\t\treturn streamOpenAIResponses(model as Model<\"openai-responses\">, context, providerOptions as any);\n\n\t\tcase \"openai-codex-responses\":\n\t\t\treturn streamOpenAICodexResponses(model as Model<\"openai-codex-responses\">, context, providerOptions as any);\n\n\t\tcase \"google-generative-ai\":\n\t\t\treturn streamGoogle(model as Model<\"google-generative-ai\">, context, providerOptions);\n\n\t\tcase \"google-gemini-cli\":\n\t\t\treturn streamGoogleGeminiCli(\n\t\t\t\tmodel as Model<\"google-gemini-cli\">,\n\t\t\t\tcontext,\n\t\t\t\tproviderOptions as GoogleGeminiCliOptions,\n\t\t\t);\n\n\t\tdefault: {\n\t\t\t// This should never be reached if all Api cases are handled\n\t\t\tconst _exhaustive: never = api;\n\t\t\tthrow new Error(`Unhandled API: ${_exhaustive}`);\n\t\t}\n\t}\n}\n\nexport async function complete<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: OptionsForApi<TApi>,\n): Promise<AssistantMessage> {\n\tconst s = stream(model, context, options);\n\treturn s.result();\n}\n\nexport function streamSimple<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream {\n\t// Vertex AI uses Application Default Credentials, not API keys\n\tif (model.api === \"google-vertex\") {\n\t\tconst providerOptions = mapOptionsForApi(model, options, undefined);\n\t\treturn stream(model, context, providerOptions);\n\t} else if (model.api === \"bedrock-converse-stream\") {\n\t\t// Bedrock doesn't have any API keys instead it sources credentials from standard AWS env variables or from given AWS profile.\n\t\tconst providerOptions = mapOptionsForApi(model, options, undefined);\n\t\treturn stream(model, context, providerOptions);\n\t}\n\n\tconst apiKey = options?.apiKey || getEnvApiKey(model.provider);\n\tif (!apiKey) {\n\t\tthrow new Error(`No API key for provider: ${model.provider}`);\n\t}\n\n\tconst providerOptions = mapOptionsForApi(model, options, apiKey);\n\treturn stream(model, context, providerOptions);\n}\n\nexport async function completeSimple<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): Promise<AssistantMessage> {\n\tconst s = streamSimple(model, context, options);\n\treturn s.result();\n}\n\nfunction mapOptionsForApi<TApi extends Api>(\n\tmodel: Model<TApi>,\n\toptions?: SimpleStreamOptions,\n\tapiKey?: string,\n): OptionsForApi<TApi> {\n\tconst base = {\n\t\ttemperature: options?.temperature,\n\t\tmaxTokens: options?.maxTokens || Math.min(model.maxTokens, 32000),\n\t\tsignal: options?.signal,\n\t\tapiKey: apiKey || options?.apiKey,\n\t\tsessionId: options?.sessionId,\n\t};\n\n\t// Helper to clamp xhigh to high for providers that don't support it\n\tconst clampReasoning = (effort: ThinkingLevel | undefined) => (effort === \"xhigh\" ? \"high\" : effort);\n\n\tswitch (model.api) {\n\t\tcase \"anthropic-messages\": {\n\t\t\t// Explicitly disable thinking when reasoning is not specified\n\t\t\tif (!options?.reasoning) {\n\t\t\t\treturn { ...base, thinkingEnabled: false } satisfies AnthropicOptions;\n\t\t\t}\n\n\t\t\t// Claude requires max_tokens > thinking.budget_tokens\n\t\t\t// So we need to ensure maxTokens accounts for both thinking and output\n\t\t\tconst defaultBudgets: ThinkingBudgets = {\n\t\t\t\tminimal: 1024,\n\t\t\t\tlow: 2048,\n\t\t\t\tmedium: 8192,\n\t\t\t\thigh: 16384,\n\t\t\t};\n\t\t\tconst budgets = { ...defaultBudgets, ...options?.thinkingBudgets };\n\n\t\t\tconst minOutputTokens = 1024;\n\t\t\tconst level = clampReasoning(options.reasoning)!;\n\t\t\tlet thinkingBudget = budgets[level]!;\n\t\t\t// Caller's maxTokens is the desired output; add thinking budget on top, capped at model limit\n\t\t\tconst maxTokens = Math.min((base.maxTokens || 0) + thinkingBudget, model.maxTokens);\n\n\t\t\t// If not enough room for thinking + output, reduce thinking budget\n\t\t\tif (maxTokens <= thinkingBudget) {\n\t\t\t\tthinkingBudget = Math.max(0, maxTokens - minOutputTokens);\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tmaxTokens,\n\t\t\t\tthinkingEnabled: true,\n\t\t\t\tthinkingBudgetTokens: thinkingBudget,\n\t\t\t} satisfies AnthropicOptions;\n\t\t}\n\n\t\tcase \"bedrock-converse-stream\":\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\treasoning: options?.reasoning,\n\t\t\t\tthinkingBudgets: options?.thinkingBudgets,\n\t\t\t} satisfies BedrockOptions;\n\n\t\tcase \"openai-completions\":\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\treasoningEffort: supportsXhigh(model) ? options?.reasoning : clampReasoning(options?.reasoning),\n\t\t\t} satisfies OpenAICompletionsOptions;\n\n\t\tcase \"openai-responses\":\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\treasoningEffort: supportsXhigh(model) ? options?.reasoning : clampReasoning(options?.reasoning),\n\t\t\t} satisfies OpenAIResponsesOptions;\n\n\t\tcase \"openai-codex-responses\":\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\treasoningEffort: supportsXhigh(model) ? options?.reasoning : clampReasoning(options?.reasoning),\n\t\t\t} satisfies OpenAICodexResponsesOptions;\n\n\t\tcase \"google-generative-ai\": {\n\t\t\t// Explicitly disable thinking when reasoning is not specified\n\t\t\t// This is needed because Gemini has \"dynamic thinking\" enabled by default\n\t\t\tif (!options?.reasoning) {\n\t\t\t\treturn { ...base, thinking: { enabled: false } } satisfies GoogleOptions;\n\t\t\t}\n\n\t\t\tconst googleModel = model as Model<\"google-generative-ai\">;\n\t\t\tconst effort = clampReasoning(options.reasoning)!;\n\n\t\t\t// Gemini 3 models use thinkingLevel exclusively instead of thinkingBudget.\n\t\t\t// https://ai.google.dev/gemini-api/docs/thinking#set-budget\n\t\t\tif (isGemini3ProModel(googleModel) || isGemini3FlashModel(googleModel)) {\n\t\t\t\treturn {\n\t\t\t\t\t...base,\n\t\t\t\t\tthinking: {\n\t\t\t\t\t\tenabled: true,\n\t\t\t\t\t\tlevel: getGemini3ThinkingLevel(effort, googleModel),\n\t\t\t\t\t},\n\t\t\t\t} satisfies GoogleOptions;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tthinking: {\n\t\t\t\t\tenabled: true,\n\t\t\t\t\tbudgetTokens: getGoogleBudget(googleModel, effort, options?.thinkingBudgets),\n\t\t\t\t},\n\t\t\t} satisfies GoogleOptions;\n\t\t}\n\n\t\tcase \"google-gemini-cli\": {\n\t\t\tif (!options?.reasoning) {\n\t\t\t\treturn { ...base, thinking: { enabled: false } } satisfies GoogleGeminiCliOptions;\n\t\t\t}\n\n\t\t\tconst effort = clampReasoning(options.reasoning)!;\n\n\t\t\t// Gemini 3 models use thinkingLevel instead of thinkingBudget\n\t\t\tif (model.id.includes(\"3-pro\") || model.id.includes(\"3-flash\")) {\n\t\t\t\treturn {\n\t\t\t\t\t...base,\n\t\t\t\t\tthinking: {\n\t\t\t\t\t\tenabled: true,\n\t\t\t\t\t\tlevel: getGeminiCliThinkingLevel(effort, model.id),\n\t\t\t\t\t},\n\t\t\t\t} satisfies GoogleGeminiCliOptions;\n\t\t\t}\n\n\t\t\t// Models using thinkingBudget (Gemini 2.x, Claude via Antigravity)\n\t\t\t// Claude requires max_tokens > thinking.budget_tokens\n\t\t\t// So we need to ensure maxTokens accounts for both thinking and output\n\t\t\tconst defaultBudgets: ThinkingBudgets = {\n\t\t\t\tminimal: 1024,\n\t\t\t\tlow: 2048,\n\t\t\t\tmedium: 8192,\n\t\t\t\thigh: 16384,\n\t\t\t};\n\t\t\tconst budgets = { ...defaultBudgets, ...options?.thinkingBudgets };\n\n\t\t\tconst minOutputTokens = 1024;\n\t\t\tlet thinkingBudget = budgets[effort]!;\n\t\t\t// Caller's maxTokens is the desired output; add thinking budget on top, capped at model limit\n\t\t\tconst maxTokens = Math.min((base.maxTokens || 0) + thinkingBudget, model.maxTokens);\n\n\t\t\t// If not enough room for thinking + output, reduce thinking budget\n\t\t\tif (maxTokens <= thinkingBudget) {\n\t\t\t\tthinkingBudget = Math.max(0, maxTokens - minOutputTokens);\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tmaxTokens,\n\t\t\t\tthinking: {\n\t\t\t\t\tenabled: true,\n\t\t\t\t\tbudgetTokens: thinkingBudget,\n\t\t\t\t},\n\t\t\t} satisfies GoogleGeminiCliOptions;\n\t\t}\n\n\t\tcase \"google-vertex\": {\n\t\t\t// Explicitly disable thinking when reasoning is not specified\n\t\t\tif (!options?.reasoning) {\n\t\t\t\treturn { ...base, thinking: { enabled: false } } satisfies GoogleVertexOptions;\n\t\t\t}\n\n\t\t\tconst vertexModel = model as Model<\"google-vertex\">;\n\t\t\tconst effort = clampReasoning(options.reasoning)!;\n\t\t\tconst geminiModel = vertexModel as unknown as Model<\"google-generative-ai\">;\n\n\t\t\tif (isGemini3ProModel(geminiModel) || isGemini3FlashModel(geminiModel)) {\n\t\t\t\treturn {\n\t\t\t\t\t...base,\n\t\t\t\t\tthinking: {\n\t\t\t\t\t\tenabled: true,\n\t\t\t\t\t\tlevel: getGemini3ThinkingLevel(effort, geminiModel),\n\t\t\t\t\t},\n\t\t\t\t} satisfies GoogleVertexOptions;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tthinking: {\n\t\t\t\t\tenabled: true,\n\t\t\t\t\tbudgetTokens: getGoogleBudget(geminiModel, effort, options?.thinkingBudgets),\n\t\t\t\t},\n\t\t\t} satisfies GoogleVertexOptions;\n\t\t}\n\n\t\tdefault: {\n\t\t\t// Exhaustiveness check\n\t\t\tconst _exhaustive: never = model.api;\n\t\t\tthrow new Error(`Unhandled API in mapOptionsForApi: ${_exhaustive}`);\n\t\t}\n\t}\n}\n\ntype ClampedThinkingLevel = Exclude<ThinkingLevel, \"xhigh\">;\n\nfunction isGemini3ProModel(model: Model<\"google-generative-ai\">): boolean {\n\t// Covers gemini-3-pro, gemini-3-pro-preview, and possible other prefixed ids in the future\n\treturn model.id.includes(\"3-pro\");\n}\n\nfunction isGemini3FlashModel(model: Model<\"google-generative-ai\">): boolean {\n\t// Covers gemini-3-flash, gemini-3-flash-preview, and possible other prefixed ids in the future\n\treturn model.id.includes(\"3-flash\");\n}\n\nfunction getGemini3ThinkingLevel(\n\teffort: ClampedThinkingLevel,\n\tmodel: Model<\"google-generative-ai\">,\n): GoogleThinkingLevel {\n\tif (isGemini3ProModel(model)) {\n\t\t// Gemini 3 Pro only supports LOW/HIGH (for now)\n\t\tswitch (effort) {\n\t\t\tcase \"minimal\":\n\t\t\tcase \"low\":\n\t\t\t\treturn \"LOW\";\n\t\t\tcase \"medium\":\n\t\t\tcase \"high\":\n\t\t\t\treturn \"HIGH\";\n\t\t}\n\t}\n\t// Gemini 3 Flash supports all four levels\n\tswitch (effort) {\n\t\tcase \"minimal\":\n\t\t\treturn \"MINIMAL\";\n\t\tcase \"low\":\n\t\t\treturn \"LOW\";\n\t\tcase \"medium\":\n\t\t\treturn \"MEDIUM\";\n\t\tcase \"high\":\n\t\t\treturn \"HIGH\";\n\t}\n}\n\nfunction getGeminiCliThinkingLevel(effort: ClampedThinkingLevel, modelId: string): GoogleThinkingLevel {\n\tif (modelId.includes(\"3-pro\")) {\n\t\t// Gemini 3 Pro only supports LOW/HIGH (for now)\n\t\tswitch (effort) {\n\t\t\tcase \"minimal\":\n\t\t\tcase \"low\":\n\t\t\t\treturn \"LOW\";\n\t\t\tcase \"medium\":\n\t\t\tcase \"high\":\n\t\t\t\treturn \"HIGH\";\n\t\t}\n\t}\n\t// Gemini 3 Flash supports all four levels\n\tswitch (effort) {\n\t\tcase \"minimal\":\n\t\t\treturn \"MINIMAL\";\n\t\tcase \"low\":\n\t\t\treturn \"LOW\";\n\t\tcase \"medium\":\n\t\t\treturn \"MEDIUM\";\n\t\tcase \"high\":\n\t\t\treturn \"HIGH\";\n\t}\n}\n\nfunction getGoogleBudget(\n\tmodel: Model<\"google-generative-ai\">,\n\teffort: ClampedThinkingLevel,\n\tcustomBudgets?: ThinkingBudgets,\n): number {\n\t// Custom budgets take precedence if provided for this level\n\tif (customBudgets?.[effort] !== undefined) {\n\t\treturn customBudgets[effort]!;\n\t}\n\n\t// See https://ai.google.dev/gemini-api/docs/thinking#set-budget\n\tif (model.id.includes(\"2.5-pro\")) {\n\t\tconst budgets: Record<ClampedThinkingLevel, number> = {\n\t\t\tminimal: 128,\n\t\t\tlow: 2048,\n\t\t\tmedium: 8192,\n\t\t\thigh: 32768,\n\t\t};\n\t\treturn budgets[effort];\n\t}\n\n\tif (model.id.includes(\"2.5-flash\")) {\n\t\t// Covers 2.5-flash-lite as well\n\t\tconst budgets: Record<ClampedThinkingLevel, number> = {\n\t\t\tminimal: 128,\n\t\t\tlow: 2048,\n\t\t\tmedium: 8192,\n\t\t\thigh: 24576,\n\t\t};\n\t\treturn budgets[effort];\n\t}\n\n\t// Unknown model - use dynamic\n\treturn -1;\n}\n"]}
1
+ {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EACX,GAAG,EACH,gBAAgB,EAChB,2BAA2B,EAC3B,OAAO,EACP,aAAa,EACb,KAAK,EACL,aAAa,EACb,mBAAmB,EAGnB,MAAM,YAAY,CAAC;AAoBpB;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,CAAC;AAC1E,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAyDnE,wBAAgB,MAAM,CAAC,IAAI,SAAS,GAAG,EACtC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,aAAa,CAAC,IAAI,CAAC,GAC3B,2BAA2B,CA6C7B;AAED,wBAAsB,QAAQ,CAAC,IAAI,SAAS,GAAG,EAC9C,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,aAAa,CAAC,IAAI,CAAC,GAC3B,OAAO,CAAC,gBAAgB,CAAC,CAG3B;AAED,wBAAgB,YAAY,CAAC,IAAI,SAAS,GAAG,EAC5C,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,mBAAmB,GAC3B,2BAA2B,CAkB7B;AAED,wBAAsB,cAAc,CAAC,IAAI,SAAS,GAAG,EACpD,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAClB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,mBAAmB,GAC3B,OAAO,CAAC,gBAAgB,CAAC,CAG3B","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { supportsXhigh } from \"./models.js\";\nimport { type BedrockOptions, streamBedrock } from \"./providers/amazon-bedrock.js\";\nimport { type AnthropicOptions, streamAnthropic } from \"./providers/anthropic.js\";\nimport { type GoogleOptions, streamGoogle } from \"./providers/google.js\";\nimport {\n\ttype GoogleGeminiCliOptions,\n\ttype GoogleThinkingLevel,\n\tstreamGoogleGeminiCli,\n} from \"./providers/google-gemini-cli.js\";\nimport { type GoogleVertexOptions, streamGoogleVertex } from \"./providers/google-vertex.js\";\nimport { type OpenAICodexResponsesOptions, streamOpenAICodexResponses } from \"./providers/openai-codex-responses.js\";\nimport { type OpenAICompletionsOptions, streamOpenAICompletions } from \"./providers/openai-completions.js\";\nimport { type OpenAIResponsesOptions, streamOpenAIResponses } from \"./providers/openai-responses.js\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tAssistantMessageEventStream,\n\tContext,\n\tKnownProvider,\n\tModel,\n\tOptionsForApi,\n\tSimpleStreamOptions,\n\tThinkingBudgets,\n\tThinkingLevel,\n} from \"./types.js\";\n\nlet cachedVertexAdcCredentialsExists: boolean | null = null;\n\nfunction hasVertexAdcCredentials(): boolean {\n\tif (cachedVertexAdcCredentialsExists === null) {\n\t\t// Check GOOGLE_APPLICATION_CREDENTIALS env var first (standard way)\n\t\tconst gacPath = process.env.GOOGLE_APPLICATION_CREDENTIALS;\n\t\tif (gacPath) {\n\t\t\tcachedVertexAdcCredentialsExists = existsSync(gacPath);\n\t\t} else {\n\t\t\t// Fall back to default ADC path (lazy evaluation)\n\t\t\tcachedVertexAdcCredentialsExists = existsSync(\n\t\t\t\tjoin(homedir(), \".config\", \"gcloud\", \"application_default_credentials.json\"),\n\t\t\t);\n\t\t}\n\t}\n\treturn cachedVertexAdcCredentialsExists;\n}\n\n/**\n * Get API key for provider from known environment variables, e.g. OPENAI_API_KEY.\n *\n * Will not return API keys for providers that require OAuth tokens.\n */\nexport function getEnvApiKey(provider: KnownProvider): string | undefined;\nexport function getEnvApiKey(provider: string): string | undefined;\nexport function getEnvApiKey(provider: any): string | undefined {\n\t// Fall back to environment variables\n\tif (provider === \"github-copilot\") {\n\t\treturn process.env.COPILOT_GITHUB_TOKEN || process.env.GH_TOKEN || process.env.GITHUB_TOKEN;\n\t}\n\n\t// ANTHROPIC_OAUTH_TOKEN takes precedence over ANTHROPIC_API_KEY\n\tif (provider === \"anthropic\") {\n\t\treturn process.env.ANTHROPIC_OAUTH_TOKEN || process.env.ANTHROPIC_API_KEY;\n\t}\n\n\t// Vertex AI uses Application Default Credentials, not API keys.\n\t// Auth is configured via `gcloud auth application-default login`.\n\tif (provider === \"google-vertex\") {\n\t\tconst hasCredentials = hasVertexAdcCredentials();\n\t\tconst hasProject = !!(process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT);\n\t\tconst hasLocation = !!process.env.GOOGLE_CLOUD_LOCATION;\n\n\t\tif (hasCredentials && hasProject && hasLocation) {\n\t\t\treturn \"<authenticated>\";\n\t\t}\n\t}\n\n\tif (provider === \"amazon-bedrock\") {\n\t\t// Amazon Bedrock supports multiple credential sources:\n\t\t// 1. AWS_PROFILE - named profile from ~/.aws/credentials\n\t\t// 2. AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY - standard IAM keys\n\t\t// 3. AWS_BEARER_TOKEN_BEDROCK - Bedrock API keys (bearer token)\n\t\tif (\n\t\t\tprocess.env.AWS_PROFILE ||\n\t\t\t(process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) ||\n\t\t\tprocess.env.AWS_BEARER_TOKEN_BEDROCK\n\t\t) {\n\t\t\treturn \"<authenticated>\";\n\t\t}\n\t}\n\n\tconst envMap: Record<string, string> = {\n\t\topenai: \"OPENAI_API_KEY\",\n\t\tgoogle: \"GEMINI_API_KEY\",\n\t\tgroq: \"GROQ_API_KEY\",\n\t\tcerebras: \"CEREBRAS_API_KEY\",\n\t\txai: \"XAI_API_KEY\",\n\t\topenrouter: \"OPENROUTER_API_KEY\",\n\t\t\"vercel-ai-gateway\": \"AI_GATEWAY_API_KEY\",\n\t\tzai: \"ZAI_API_KEY\",\n\t\tmistral: \"MISTRAL_API_KEY\",\n\t\tminimax: \"MINIMAX_API_KEY\",\n\t\t\"minimax-cn\": \"MINIMAX_CN_API_KEY\",\n\t\topencode: \"OPENCODE_API_KEY\",\n\t};\n\n\tconst envVar = envMap[provider];\n\treturn envVar ? process.env[envVar] : undefined;\n}\n\nexport function stream<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: OptionsForApi<TApi>,\n): AssistantMessageEventStream {\n\t// Vertex AI uses Application Default Credentials, not API keys\n\tif (model.api === \"google-vertex\") {\n\t\treturn streamGoogleVertex(model as Model<\"google-vertex\">, context, options as GoogleVertexOptions);\n\t} else if (model.api === \"bedrock-converse-stream\") {\n\t\t// Bedrock doesn't have any API keys instead it sources credentials from standard AWS env variables or from given AWS profile.\n\t\treturn streamBedrock(model as Model<\"bedrock-converse-stream\">, context, (options || {}) as BedrockOptions);\n\t}\n\n\tconst apiKey = options?.apiKey || getEnvApiKey(model.provider);\n\tif (!apiKey) {\n\t\tthrow new Error(`No API key for provider: ${model.provider}`);\n\t}\n\tconst providerOptions = { ...options, apiKey };\n\n\tconst api: Api = model.api;\n\tswitch (api) {\n\t\tcase \"anthropic-messages\":\n\t\t\treturn streamAnthropic(model as Model<\"anthropic-messages\">, context, providerOptions);\n\n\t\tcase \"openai-completions\":\n\t\t\treturn streamOpenAICompletions(model as Model<\"openai-completions\">, context, providerOptions as any);\n\n\t\tcase \"openai-responses\":\n\t\t\treturn streamOpenAIResponses(model as Model<\"openai-responses\">, context, providerOptions as any);\n\n\t\tcase \"openai-codex-responses\":\n\t\t\treturn streamOpenAICodexResponses(model as Model<\"openai-codex-responses\">, context, providerOptions as any);\n\n\t\tcase \"google-generative-ai\":\n\t\t\treturn streamGoogle(model as Model<\"google-generative-ai\">, context, providerOptions);\n\n\t\tcase \"google-gemini-cli\":\n\t\t\treturn streamGoogleGeminiCli(\n\t\t\t\tmodel as Model<\"google-gemini-cli\">,\n\t\t\t\tcontext,\n\t\t\t\tproviderOptions as GoogleGeminiCliOptions,\n\t\t\t);\n\n\t\tdefault: {\n\t\t\t// This should never be reached if all Api cases are handled\n\t\t\tconst _exhaustive: never = api;\n\t\t\tthrow new Error(`Unhandled API: ${_exhaustive}`);\n\t\t}\n\t}\n}\n\nexport async function complete<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: OptionsForApi<TApi>,\n): Promise<AssistantMessage> {\n\tconst s = stream(model, context, options);\n\treturn s.result();\n}\n\nexport function streamSimple<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream {\n\t// Vertex AI uses Application Default Credentials, not API keys\n\tif (model.api === \"google-vertex\") {\n\t\tconst providerOptions = mapOptionsForApi(model, options, undefined);\n\t\treturn stream(model, context, providerOptions);\n\t} else if (model.api === \"bedrock-converse-stream\") {\n\t\t// Bedrock doesn't have any API keys instead it sources credentials from standard AWS env variables or from given AWS profile.\n\t\tconst providerOptions = mapOptionsForApi(model, options, undefined);\n\t\treturn stream(model, context, providerOptions);\n\t}\n\n\tconst apiKey = options?.apiKey || getEnvApiKey(model.provider);\n\tif (!apiKey) {\n\t\tthrow new Error(`No API key for provider: ${model.provider}`);\n\t}\n\n\tconst providerOptions = mapOptionsForApi(model, options, apiKey);\n\treturn stream(model, context, providerOptions);\n}\n\nexport async function completeSimple<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): Promise<AssistantMessage> {\n\tconst s = streamSimple(model, context, options);\n\treturn s.result();\n}\n\nfunction mapOptionsForApi<TApi extends Api>(\n\tmodel: Model<TApi>,\n\toptions?: SimpleStreamOptions,\n\tapiKey?: string,\n): OptionsForApi<TApi> {\n\tconst base = {\n\t\ttemperature: options?.temperature,\n\t\tmaxTokens: options?.maxTokens || Math.min(model.maxTokens, 32000),\n\t\tsignal: options?.signal,\n\t\tapiKey: apiKey || options?.apiKey,\n\t\tsessionId: options?.sessionId,\n\t};\n\n\t// Helper to clamp xhigh to high for providers that don't support it\n\tconst clampReasoning = (effort: ThinkingLevel | undefined) => (effort === \"xhigh\" ? \"high\" : effort);\n\n\t/**\n\t * Adjust maxTokens to account for thinking budget.\n\t * APIs like Anthropic and Bedrock require max_tokens > thinking.budget_tokens.\n\t * Returns { adjustedMaxTokens, adjustedThinkingBudget }\n\t */\n\tconst adjustMaxTokensForThinking = (\n\t\tbaseMaxTokens: number,\n\t\tmodelMaxTokens: number,\n\t\treasoningLevel: ThinkingLevel,\n\t\tcustomBudgets?: ThinkingBudgets,\n\t): { maxTokens: number; thinkingBudget: number } => {\n\t\tconst defaultBudgets: ThinkingBudgets = {\n\t\t\tminimal: 1024,\n\t\t\tlow: 2048,\n\t\t\tmedium: 8192,\n\t\t\thigh: 16384,\n\t\t};\n\t\tconst budgets = { ...defaultBudgets, ...customBudgets };\n\n\t\tconst minOutputTokens = 1024;\n\t\tconst level = clampReasoning(reasoningLevel)!;\n\t\tlet thinkingBudget = budgets[level]!;\n\t\t// Caller's maxTokens is the desired output; add thinking budget on top, capped at model limit\n\t\tconst maxTokens = Math.min(baseMaxTokens + thinkingBudget, modelMaxTokens);\n\n\t\t// If not enough room for thinking + output, reduce thinking budget\n\t\tif (maxTokens <= thinkingBudget) {\n\t\t\tthinkingBudget = Math.max(0, maxTokens - minOutputTokens);\n\t\t}\n\n\t\treturn { maxTokens, thinkingBudget };\n\t};\n\n\tswitch (model.api) {\n\t\tcase \"anthropic-messages\": {\n\t\t\t// Explicitly disable thinking when reasoning is not specified\n\t\t\tif (!options?.reasoning) {\n\t\t\t\treturn { ...base, thinkingEnabled: false } satisfies AnthropicOptions;\n\t\t\t}\n\n\t\t\t// Claude requires max_tokens > thinking.budget_tokens\n\t\t\t// So we need to ensure maxTokens accounts for both thinking and output\n\t\t\tconst adjusted = adjustMaxTokensForThinking(\n\t\t\t\tbase.maxTokens || 0,\n\t\t\t\tmodel.maxTokens,\n\t\t\t\toptions.reasoning,\n\t\t\t\toptions?.thinkingBudgets,\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tmaxTokens: adjusted.maxTokens,\n\t\t\t\tthinkingEnabled: true,\n\t\t\t\tthinkingBudgetTokens: adjusted.thinkingBudget,\n\t\t\t} satisfies AnthropicOptions;\n\t\t}\n\n\t\tcase \"bedrock-converse-stream\": {\n\t\t\t// Explicitly disable thinking when reasoning is not specified\n\t\t\tif (!options?.reasoning) {\n\t\t\t\treturn { ...base, reasoning: undefined } satisfies BedrockOptions;\n\t\t\t}\n\n\t\t\t// Claude requires max_tokens > thinking.budget_tokens (same as Anthropic direct API)\n\t\t\t// So we need to ensure maxTokens accounts for both thinking and output\n\t\t\tif (model.id.includes(\"anthropic.claude\") || model.id.includes(\"anthropic/claude\")) {\n\t\t\t\tconst adjusted = adjustMaxTokensForThinking(\n\t\t\t\t\tbase.maxTokens || 0,\n\t\t\t\t\tmodel.maxTokens,\n\t\t\t\t\toptions.reasoning,\n\t\t\t\t\toptions?.thinkingBudgets,\n\t\t\t\t);\n\n\t\t\t\treturn {\n\t\t\t\t\t...base,\n\t\t\t\t\tmaxTokens: adjusted.maxTokens,\n\t\t\t\t\treasoning: options.reasoning,\n\t\t\t\t\tthinkingBudgets: {\n\t\t\t\t\t\t...(options?.thinkingBudgets || {}),\n\t\t\t\t\t\t[clampReasoning(options.reasoning)!]: adjusted.thinkingBudget,\n\t\t\t\t\t},\n\t\t\t\t} satisfies BedrockOptions;\n\t\t\t}\n\n\t\t\t// Non-Claude models - pass through\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\treasoning: options?.reasoning,\n\t\t\t\tthinkingBudgets: options?.thinkingBudgets,\n\t\t\t} satisfies BedrockOptions;\n\t\t}\n\n\t\tcase \"openai-completions\":\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\treasoningEffort: supportsXhigh(model) ? options?.reasoning : clampReasoning(options?.reasoning),\n\t\t\t} satisfies OpenAICompletionsOptions;\n\n\t\tcase \"openai-responses\":\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\treasoningEffort: supportsXhigh(model) ? options?.reasoning : clampReasoning(options?.reasoning),\n\t\t\t} satisfies OpenAIResponsesOptions;\n\n\t\tcase \"openai-codex-responses\":\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\treasoningEffort: supportsXhigh(model) ? options?.reasoning : clampReasoning(options?.reasoning),\n\t\t\t} satisfies OpenAICodexResponsesOptions;\n\n\t\tcase \"google-generative-ai\": {\n\t\t\t// Explicitly disable thinking when reasoning is not specified\n\t\t\t// This is needed because Gemini has \"dynamic thinking\" enabled by default\n\t\t\tif (!options?.reasoning) {\n\t\t\t\treturn { ...base, thinking: { enabled: false } } satisfies GoogleOptions;\n\t\t\t}\n\n\t\t\tconst googleModel = model as Model<\"google-generative-ai\">;\n\t\t\tconst effort = clampReasoning(options.reasoning)!;\n\n\t\t\t// Gemini 3 models use thinkingLevel exclusively instead of thinkingBudget.\n\t\t\t// https://ai.google.dev/gemini-api/docs/thinking#set-budget\n\t\t\tif (isGemini3ProModel(googleModel) || isGemini3FlashModel(googleModel)) {\n\t\t\t\treturn {\n\t\t\t\t\t...base,\n\t\t\t\t\tthinking: {\n\t\t\t\t\t\tenabled: true,\n\t\t\t\t\t\tlevel: getGemini3ThinkingLevel(effort, googleModel),\n\t\t\t\t\t},\n\t\t\t\t} satisfies GoogleOptions;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tthinking: {\n\t\t\t\t\tenabled: true,\n\t\t\t\t\tbudgetTokens: getGoogleBudget(googleModel, effort, options?.thinkingBudgets),\n\t\t\t\t},\n\t\t\t} satisfies GoogleOptions;\n\t\t}\n\n\t\tcase \"google-gemini-cli\": {\n\t\t\tif (!options?.reasoning) {\n\t\t\t\treturn { ...base, thinking: { enabled: false } } satisfies GoogleGeminiCliOptions;\n\t\t\t}\n\n\t\t\tconst effort = clampReasoning(options.reasoning)!;\n\n\t\t\t// Gemini 3 models use thinkingLevel instead of thinkingBudget\n\t\t\tif (model.id.includes(\"3-pro\") || model.id.includes(\"3-flash\")) {\n\t\t\t\treturn {\n\t\t\t\t\t...base,\n\t\t\t\t\tthinking: {\n\t\t\t\t\t\tenabled: true,\n\t\t\t\t\t\tlevel: getGeminiCliThinkingLevel(effort, model.id),\n\t\t\t\t\t},\n\t\t\t\t} satisfies GoogleGeminiCliOptions;\n\t\t\t}\n\n\t\t\t// Models using thinkingBudget (Gemini 2.x, Claude via Antigravity)\n\t\t\t// Claude requires max_tokens > thinking.budget_tokens\n\t\t\t// So we need to ensure maxTokens accounts for both thinking and output\n\t\t\tconst defaultBudgets: ThinkingBudgets = {\n\t\t\t\tminimal: 1024,\n\t\t\t\tlow: 2048,\n\t\t\t\tmedium: 8192,\n\t\t\t\thigh: 16384,\n\t\t\t};\n\t\t\tconst budgets = { ...defaultBudgets, ...options?.thinkingBudgets };\n\n\t\t\tconst minOutputTokens = 1024;\n\t\t\tlet thinkingBudget = budgets[effort]!;\n\t\t\t// Caller's maxTokens is the desired output; add thinking budget on top, capped at model limit\n\t\t\tconst maxTokens = Math.min((base.maxTokens || 0) + thinkingBudget, model.maxTokens);\n\n\t\t\t// If not enough room for thinking + output, reduce thinking budget\n\t\t\tif (maxTokens <= thinkingBudget) {\n\t\t\t\tthinkingBudget = Math.max(0, maxTokens - minOutputTokens);\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tmaxTokens,\n\t\t\t\tthinking: {\n\t\t\t\t\tenabled: true,\n\t\t\t\t\tbudgetTokens: thinkingBudget,\n\t\t\t\t},\n\t\t\t} satisfies GoogleGeminiCliOptions;\n\t\t}\n\n\t\tcase \"google-vertex\": {\n\t\t\t// Explicitly disable thinking when reasoning is not specified\n\t\t\tif (!options?.reasoning) {\n\t\t\t\treturn { ...base, thinking: { enabled: false } } satisfies GoogleVertexOptions;\n\t\t\t}\n\n\t\t\tconst vertexModel = model as Model<\"google-vertex\">;\n\t\t\tconst effort = clampReasoning(options.reasoning)!;\n\t\t\tconst geminiModel = vertexModel as unknown as Model<\"google-generative-ai\">;\n\n\t\t\tif (isGemini3ProModel(geminiModel) || isGemini3FlashModel(geminiModel)) {\n\t\t\t\treturn {\n\t\t\t\t\t...base,\n\t\t\t\t\tthinking: {\n\t\t\t\t\t\tenabled: true,\n\t\t\t\t\t\tlevel: getGemini3ThinkingLevel(effort, geminiModel),\n\t\t\t\t\t},\n\t\t\t\t} satisfies GoogleVertexOptions;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tthinking: {\n\t\t\t\t\tenabled: true,\n\t\t\t\t\tbudgetTokens: getGoogleBudget(geminiModel, effort, options?.thinkingBudgets),\n\t\t\t\t},\n\t\t\t} satisfies GoogleVertexOptions;\n\t\t}\n\n\t\tdefault: {\n\t\t\t// Exhaustiveness check\n\t\t\tconst _exhaustive: never = model.api;\n\t\t\tthrow new Error(`Unhandled API in mapOptionsForApi: ${_exhaustive}`);\n\t\t}\n\t}\n}\n\ntype ClampedThinkingLevel = Exclude<ThinkingLevel, \"xhigh\">;\n\nfunction isGemini3ProModel(model: Model<\"google-generative-ai\">): boolean {\n\t// Covers gemini-3-pro, gemini-3-pro-preview, and possible other prefixed ids in the future\n\treturn model.id.includes(\"3-pro\");\n}\n\nfunction isGemini3FlashModel(model: Model<\"google-generative-ai\">): boolean {\n\t// Covers gemini-3-flash, gemini-3-flash-preview, and possible other prefixed ids in the future\n\treturn model.id.includes(\"3-flash\");\n}\n\nfunction getGemini3ThinkingLevel(\n\teffort: ClampedThinkingLevel,\n\tmodel: Model<\"google-generative-ai\">,\n): GoogleThinkingLevel {\n\tif (isGemini3ProModel(model)) {\n\t\t// Gemini 3 Pro only supports LOW/HIGH (for now)\n\t\tswitch (effort) {\n\t\t\tcase \"minimal\":\n\t\t\tcase \"low\":\n\t\t\t\treturn \"LOW\";\n\t\t\tcase \"medium\":\n\t\t\tcase \"high\":\n\t\t\t\treturn \"HIGH\";\n\t\t}\n\t}\n\t// Gemini 3 Flash supports all four levels\n\tswitch (effort) {\n\t\tcase \"minimal\":\n\t\t\treturn \"MINIMAL\";\n\t\tcase \"low\":\n\t\t\treturn \"LOW\";\n\t\tcase \"medium\":\n\t\t\treturn \"MEDIUM\";\n\t\tcase \"high\":\n\t\t\treturn \"HIGH\";\n\t}\n}\n\nfunction getGeminiCliThinkingLevel(effort: ClampedThinkingLevel, modelId: string): GoogleThinkingLevel {\n\tif (modelId.includes(\"3-pro\")) {\n\t\t// Gemini 3 Pro only supports LOW/HIGH (for now)\n\t\tswitch (effort) {\n\t\t\tcase \"minimal\":\n\t\t\tcase \"low\":\n\t\t\t\treturn \"LOW\";\n\t\t\tcase \"medium\":\n\t\t\tcase \"high\":\n\t\t\t\treturn \"HIGH\";\n\t\t}\n\t}\n\t// Gemini 3 Flash supports all four levels\n\tswitch (effort) {\n\t\tcase \"minimal\":\n\t\t\treturn \"MINIMAL\";\n\t\tcase \"low\":\n\t\t\treturn \"LOW\";\n\t\tcase \"medium\":\n\t\t\treturn \"MEDIUM\";\n\t\tcase \"high\":\n\t\t\treturn \"HIGH\";\n\t}\n}\n\nfunction getGoogleBudget(\n\tmodel: Model<\"google-generative-ai\">,\n\teffort: ClampedThinkingLevel,\n\tcustomBudgets?: ThinkingBudgets,\n): number {\n\t// Custom budgets take precedence if provided for this level\n\tif (customBudgets?.[effort] !== undefined) {\n\t\treturn customBudgets[effort]!;\n\t}\n\n\t// See https://ai.google.dev/gemini-api/docs/thinking#set-budget\n\tif (model.id.includes(\"2.5-pro\")) {\n\t\tconst budgets: Record<ClampedThinkingLevel, number> = {\n\t\t\tminimal: 128,\n\t\t\tlow: 2048,\n\t\t\tmedium: 8192,\n\t\t\thigh: 32768,\n\t\t};\n\t\treturn budgets[effort];\n\t}\n\n\tif (model.id.includes(\"2.5-flash\")) {\n\t\t// Covers 2.5-flash-lite as well\n\t\tconst budgets: Record<ClampedThinkingLevel, number> = {\n\t\t\tminimal: 128,\n\t\t\tlow: 2048,\n\t\t\tmedium: 8192,\n\t\t\thigh: 24576,\n\t\t};\n\t\treturn budgets[effort];\n\t}\n\n\t// Unknown model - use dynamic\n\treturn -1;\n}\n"]}