@earendil-works/pi-ai 0.79.10 → 0.80.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +646 -521
- package/dist/api/anthropic-messages.d.ts +71 -0
- package/dist/api/anthropic-messages.d.ts.map +1 -0
- package/dist/api/anthropic-messages.js +963 -0
- package/dist/api/anthropic-messages.js.map +1 -0
- package/dist/api/anthropic-messages.lazy.d.ts +3 -0
- package/dist/api/anthropic-messages.lazy.d.ts.map +1 -0
- package/dist/api/anthropic-messages.lazy.js +3 -0
- package/dist/api/anthropic-messages.lazy.js.map +1 -0
- package/dist/api/azure-openai-responses.d.ts +15 -0
- package/dist/api/azure-openai-responses.d.ts.map +1 -0
- package/dist/api/azure-openai-responses.js +225 -0
- package/dist/api/azure-openai-responses.js.map +1 -0
- package/dist/api/azure-openai-responses.lazy.d.ts +3 -0
- package/dist/api/azure-openai-responses.lazy.d.ts.map +1 -0
- package/dist/api/azure-openai-responses.lazy.js +3 -0
- package/dist/api/azure-openai-responses.lazy.js.map +1 -0
- package/dist/api/bedrock-converse-stream.d.ts +38 -0
- package/dist/api/bedrock-converse-stream.d.ts.map +1 -0
- package/dist/api/bedrock-converse-stream.js +863 -0
- package/dist/api/bedrock-converse-stream.js.map +1 -0
- package/dist/api/bedrock-converse-stream.lazy.d.ts +9 -0
- package/dist/api/bedrock-converse-stream.lazy.d.ts.map +1 -0
- package/dist/api/bedrock-converse-stream.lazy.js +30 -0
- package/dist/api/bedrock-converse-stream.lazy.js.map +1 -0
- package/dist/{providers → api}/cloudflare.d.ts +0 -4
- package/dist/api/cloudflare.d.ts.map +1 -0
- package/dist/{providers → api}/cloudflare.js +0 -18
- package/dist/api/cloudflare.js.map +1 -0
- package/dist/api/github-copilot-headers.d.ts.map +1 -0
- package/dist/api/github-copilot-headers.js.map +1 -0
- package/dist/api/google-generative-ai.d.ts +13 -0
- package/dist/api/google-generative-ai.d.ts.map +1 -0
- package/dist/api/google-generative-ai.js +405 -0
- package/dist/api/google-generative-ai.js.map +1 -0
- package/dist/api/google-generative-ai.lazy.d.ts +3 -0
- package/dist/api/google-generative-ai.lazy.d.ts.map +1 -0
- package/dist/api/google-generative-ai.lazy.js +3 -0
- package/dist/api/google-generative-ai.lazy.js.map +1 -0
- package/dist/api/google-shared.d.ts.map +1 -0
- package/dist/api/google-shared.js.map +1 -0
- package/dist/api/google-vertex.d.ts +15 -0
- package/dist/api/google-vertex.d.ts.map +1 -0
- package/dist/api/google-vertex.js +454 -0
- package/dist/api/google-vertex.js.map +1 -0
- package/dist/api/google-vertex.lazy.d.ts +3 -0
- package/dist/api/google-vertex.lazy.d.ts.map +1 -0
- package/dist/api/google-vertex.lazy.js +3 -0
- package/dist/api/google-vertex.lazy.js.map +1 -0
- package/dist/api/lazy.d.ts +15 -0
- package/dist/api/lazy.d.ts.map +1 -0
- package/dist/api/lazy.js +59 -0
- package/dist/api/lazy.js.map +1 -0
- package/dist/api/mistral-conversations.d.ts +25 -0
- package/dist/api/mistral-conversations.d.ts.map +1 -0
- package/dist/api/mistral-conversations.js +555 -0
- package/dist/api/mistral-conversations.js.map +1 -0
- package/dist/api/mistral-conversations.lazy.d.ts +3 -0
- package/dist/api/mistral-conversations.lazy.d.ts.map +1 -0
- package/dist/api/mistral-conversations.lazy.js +3 -0
- package/dist/api/mistral-conversations.lazy.js.map +1 -0
- package/dist/{providers → api}/openai-codex-responses.d.ts +2 -3
- package/dist/api/openai-codex-responses.d.ts.map +1 -0
- package/dist/{providers → api}/openai-codex-responses.js +66 -45
- package/dist/api/openai-codex-responses.js.map +1 -0
- package/dist/api/openai-codex-responses.lazy.d.ts +3 -0
- package/dist/api/openai-codex-responses.lazy.d.ts.map +1 -0
- package/dist/api/openai-codex-responses.lazy.js +3 -0
- package/dist/api/openai-codex-responses.lazy.js.map +1 -0
- package/dist/{providers → api}/openai-completions.d.ts +2 -3
- package/dist/api/openai-completions.d.ts.map +1 -0
- package/dist/{providers → api}/openai-completions.js +32 -37
- package/dist/api/openai-completions.js.map +1 -0
- package/dist/api/openai-completions.lazy.d.ts +3 -0
- package/dist/api/openai-completions.lazy.d.ts.map +1 -0
- package/dist/api/openai-completions.lazy.js +3 -0
- package/dist/api/openai-completions.lazy.js.map +1 -0
- package/dist/api/openai-prompt-cache.d.ts.map +1 -0
- package/dist/api/openai-prompt-cache.js.map +1 -0
- package/dist/api/openai-responses-shared.d.ts.map +1 -0
- package/dist/{providers → api}/openai-responses-shared.js +37 -29
- package/dist/api/openai-responses-shared.js.map +1 -0
- package/dist/{providers → api}/openai-responses.d.ts +2 -3
- package/dist/api/openai-responses.d.ts.map +1 -0
- package/dist/{providers → api}/openai-responses.js +27 -32
- package/dist/api/openai-responses.js.map +1 -0
- package/dist/api/openai-responses.lazy.d.ts +3 -0
- package/dist/api/openai-responses.lazy.d.ts.map +1 -0
- package/dist/api/openai-responses.lazy.js +3 -0
- package/dist/api/openai-responses.lazy.js.map +1 -0
- package/dist/api/openrouter-images.d.ts +3 -0
- package/dist/api/openrouter-images.d.ts.map +1 -0
- package/dist/{providers/images/openrouter.js → api/openrouter-images.js} +5 -15
- package/dist/api/openrouter-images.js.map +1 -0
- package/dist/api/openrouter-images.lazy.d.ts +3 -0
- package/dist/api/openrouter-images.lazy.d.ts.map +1 -0
- package/dist/api/openrouter-images.lazy.js +4 -0
- package/dist/api/openrouter-images.lazy.js.map +1 -0
- package/dist/api/simple-options.d.ts.map +1 -0
- package/dist/api/simple-options.js.map +1 -0
- package/dist/api/transform-messages.d.ts.map +1 -0
- package/dist/api/transform-messages.js.map +1 -0
- package/dist/auth/context.d.ts +7 -0
- package/dist/auth/context.d.ts.map +1 -0
- package/dist/auth/context.js +42 -0
- package/dist/auth/context.js.map +1 -0
- package/dist/auth/credential-store.d.ts +16 -0
- package/dist/auth/credential-store.d.ts.map +1 -0
- package/dist/auth/credential-store.js +37 -0
- package/dist/auth/credential-store.js.map +1 -0
- package/dist/auth/helpers.d.ts +20 -0
- package/dist/auth/helpers.d.ts.map +1 -0
- package/dist/auth/helpers.js +46 -0
- package/dist/auth/helpers.js.map +1 -0
- package/dist/auth/resolve.d.ts +26 -0
- package/dist/auth/resolve.d.ts.map +1 -0
- package/dist/auth/resolve.js +101 -0
- package/dist/auth/resolve.js.map +1 -0
- package/dist/auth/types.d.ts +180 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +2 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/bedrock-provider.d.ts +2 -4
- package/dist/bedrock-provider.d.ts.map +1 -1
- package/dist/bedrock-provider.js +3 -4
- package/dist/bedrock-provider.js.map +1 -1
- package/dist/compat.d.ts +65 -0
- package/dist/compat.d.ts.map +1 -0
- package/dist/compat.js +182 -0
- package/dist/compat.js.map +1 -0
- package/dist/images-api-registry.d.ts +0 -1
- package/dist/images-api-registry.d.ts.map +1 -1
- package/dist/images-api-registry.js +0 -3
- package/dist/images-api-registry.js.map +1 -1
- package/dist/images-models.d.ts +93 -0
- package/dist/images-models.d.ts.map +1 -0
- package/dist/images-models.js +141 -0
- package/dist/images-models.js.map +1 -0
- package/dist/images.d.ts +1 -0
- package/dist/images.d.ts.map +1 -1
- package/dist/images.js +1 -0
- package/dist/images.js.map +1 -1
- package/dist/index.d.ts +29 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -4
- package/dist/index.js.map +1 -1
- package/dist/legacy-api-aliases.d.ts +42 -0
- package/dist/legacy-api-aliases.d.ts.map +1 -0
- package/dist/legacy-api-aliases.js +49 -0
- package/dist/legacy-api-aliases.js.map +1 -0
- package/dist/models.d.ts +133 -9
- package/dist/models.d.ts.map +1 -1
- package/dist/models.generated.d.ts +1766 -156
- package/dist/models.generated.d.ts.map +1 -1
- package/dist/models.generated.js +70 -17172
- package/dist/models.generated.js.map +1 -1
- package/dist/models.js +181 -17
- package/dist/models.js.map +1 -1
- package/dist/providers/all.d.ts +21 -0
- package/dist/providers/all.d.ts.map +1 -0
- package/dist/providers/all.js +114 -0
- package/dist/providers/all.js.map +1 -0
- package/dist/providers/amazon-bedrock.d.ts +2 -38
- package/dist/providers/amazon-bedrock.d.ts.map +1 -1
- package/dist/providers/amazon-bedrock.js +35 -865
- package/dist/providers/amazon-bedrock.js.map +1 -1
- package/dist/providers/amazon-bedrock.models.d.ts +1718 -0
- package/dist/providers/amazon-bedrock.models.d.ts.map +1 -0
- package/dist/providers/amazon-bedrock.models.js +1675 -0
- package/dist/providers/amazon-bedrock.models.js.map +1 -0
- package/dist/providers/ant-ling.d.ts +3 -0
- package/dist/providers/ant-ling.d.ts.map +1 -0
- package/dist/providers/ant-ling.js +15 -0
- package/dist/providers/ant-ling.js.map +1 -0
- package/dist/providers/ant-ling.models.d.ts +86 -0
- package/dist/providers/ant-ling.models.d.ts.map +1 -0
- package/dist/providers/ant-ling.models.js +60 -0
- package/dist/providers/ant-ling.models.js.map +1 -0
- package/dist/providers/anthropic.d.ts +2 -71
- package/dist/providers/anthropic.d.ts.map +1 -1
- package/dist/providers/anthropic.js +17 -973
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/anthropic.models.d.ts +458 -0
- package/dist/providers/anthropic.models.d.ts.map +1 -0
- package/dist/providers/anthropic.models.js +439 -0
- package/dist/providers/anthropic.models.js.map +1 -0
- package/dist/providers/azure-openai-responses.d.ts +2 -15
- package/dist/providers/azure-openai-responses.d.ts.map +1 -1
- package/dist/providers/azure-openai-responses.js +11 -230
- package/dist/providers/azure-openai-responses.js.map +1 -1
- package/dist/providers/azure-openai-responses.models.d.ts +804 -0
- package/dist/providers/azure-openai-responses.models.d.ts.map +1 -0
- package/dist/providers/azure-openai-responses.models.js +743 -0
- package/dist/providers/azure-openai-responses.models.js.map +1 -0
- package/dist/providers/cerebras.d.ts +3 -0
- package/dist/providers/cerebras.d.ts.map +1 -0
- package/dist/providers/cerebras.js +15 -0
- package/dist/providers/cerebras.js.map +1 -0
- package/dist/providers/cerebras.models.d.ts +45 -0
- package/dist/providers/cerebras.models.d.ts.map +1 -0
- package/dist/providers/cerebras.models.js +41 -0
- package/dist/providers/cerebras.models.js.map +1 -0
- package/dist/providers/cloudflare-ai-gateway.d.ts +3 -0
- package/dist/providers/cloudflare-ai-gateway.d.ts.map +1 -0
- package/dist/providers/cloudflare-ai-gateway.js +20 -0
- package/dist/providers/cloudflare-ai-gateway.js.map +1 -0
- package/dist/providers/cloudflare-ai-gateway.models.d.ts +765 -0
- package/dist/providers/cloudflare-ai-gateway.models.d.ts.map +1 -0
- package/dist/providers/cloudflare-ai-gateway.models.js +666 -0
- package/dist/providers/cloudflare-ai-gateway.models.js.map +1 -0
- package/dist/providers/cloudflare-auth.d.ts +4 -0
- package/dist/providers/cloudflare-auth.d.ts.map +1 -0
- package/dist/providers/cloudflare-auth.js +85 -0
- package/dist/providers/cloudflare-auth.js.map +1 -0
- package/dist/providers/cloudflare-workers-ai.d.ts +3 -0
- package/dist/providers/cloudflare-workers-ai.d.ts.map +1 -0
- package/dist/providers/cloudflare-workers-ai.js +14 -0
- package/dist/providers/cloudflare-workers-ai.js.map +1 -0
- package/dist/providers/cloudflare-workers-ai.models.d.ts +302 -0
- package/dist/providers/cloudflare-workers-ai.models.d.ts.map +1 -0
- package/dist/providers/cloudflare-workers-ai.models.js +239 -0
- package/dist/providers/cloudflare-workers-ai.models.js.map +1 -0
- package/dist/providers/deepseek.d.ts +3 -0
- package/dist/providers/deepseek.d.ts.map +1 -0
- package/dist/providers/deepseek.js +15 -0
- package/dist/providers/deepseek.js.map +1 -0
- package/dist/providers/deepseek.models.d.ts +63 -0
- package/dist/providers/deepseek.models.d.ts.map +1 -0
- package/dist/providers/deepseek.models.js +43 -0
- package/dist/providers/deepseek.models.js.map +1 -0
- package/dist/providers/faux.d.ts +43 -2
- package/dist/providers/faux.d.ts.map +1 -1
- package/dist/providers/faux.js +34 -7
- package/dist/providers/faux.js.map +1 -1
- package/dist/providers/fireworks.d.ts +3 -0
- package/dist/providers/fireworks.d.ts.map +1 -0
- package/dist/providers/fireworks.js +19 -0
- package/dist/providers/fireworks.js.map +1 -0
- package/dist/providers/fireworks.models.d.ts +353 -0
- package/dist/providers/fireworks.models.d.ts.map +1 -0
- package/dist/providers/fireworks.models.js +276 -0
- package/dist/providers/fireworks.models.js.map +1 -0
- package/dist/providers/github-copilot.d.ts +3 -0
- package/dist/providers/github-copilot.d.ts.map +1 -0
- package/dist/providers/github-copilot.js +25 -0
- package/dist/providers/github-copilot.js.map +1 -0
- package/dist/providers/github-copilot.models.d.ts +616 -0
- package/dist/providers/github-copilot.models.d.ts.map +1 -0
- package/dist/providers/github-copilot.models.js +426 -0
- package/dist/providers/github-copilot.models.js.map +1 -0
- package/dist/providers/google-vertex.d.ts +2 -15
- package/dist/providers/google-vertex.d.ts.map +1 -1
- package/dist/providers/google-vertex.js +30 -455
- package/dist/providers/google-vertex.js.map +1 -1
- package/dist/providers/google-vertex.models.d.ts +202 -0
- package/dist/providers/google-vertex.models.d.ts.map +1 -0
- package/dist/providers/google-vertex.models.js +182 -0
- package/dist/providers/google-vertex.models.js.map +1 -0
- package/dist/providers/google.d.ts +2 -13
- package/dist/providers/google.d.ts.map +1 -1
- package/dist/providers/google.js +12 -408
- package/dist/providers/google.js.map +1 -1
- package/dist/providers/google.models.d.ts +328 -0
- package/dist/providers/google.models.d.ts.map +1 -0
- package/dist/providers/google.models.js +288 -0
- package/dist/providers/google.models.js.map +1 -0
- package/dist/providers/groq.d.ts +3 -0
- package/dist/providers/groq.d.ts.map +1 -0
- package/dist/providers/groq.js +15 -0
- package/dist/providers/groq.js.map +1 -0
- package/dist/providers/groq.models.d.ts +128 -0
- package/dist/providers/groq.models.d.ts.map +1 -0
- package/dist/providers/groq.models.js +125 -0
- package/dist/providers/groq.models.js.map +1 -0
- package/dist/providers/huggingface.d.ts +3 -0
- package/dist/providers/huggingface.d.ts.map +1 -0
- package/dist/providers/huggingface.js +15 -0
- package/dist/providers/huggingface.js.map +1 -0
- package/dist/providers/huggingface.models.d.ts +883 -0
- package/dist/providers/huggingface.models.d.ts.map +1 -0
- package/dist/providers/huggingface.models.js +797 -0
- package/dist/providers/huggingface.models.js.map +1 -0
- package/dist/providers/images/{openrouter.d.ts → register-builtins.d.ts} +2 -2
- package/dist/providers/images/register-builtins.d.ts.map +1 -0
- package/dist/providers/images/register-builtins.js +34 -0
- package/dist/providers/images/register-builtins.js.map +1 -0
- package/dist/providers/kimi-coding.d.ts +3 -0
- package/dist/providers/kimi-coding.d.ts.map +1 -0
- package/dist/providers/kimi-coding.js +15 -0
- package/dist/providers/kimi-coding.js.map +1 -0
- package/dist/providers/kimi-coding.models.d.ts +63 -0
- package/dist/providers/kimi-coding.models.d.ts.map +1 -0
- package/dist/providers/kimi-coding.models.js +59 -0
- package/dist/providers/kimi-coding.models.js.map +1 -0
- package/dist/providers/minimax-cn.d.ts +3 -0
- package/dist/providers/minimax-cn.d.ts.map +1 -0
- package/dist/providers/minimax-cn.js +15 -0
- package/dist/providers/minimax-cn.js.map +1 -0
- package/dist/providers/minimax-cn.models.d.ts +54 -0
- package/dist/providers/minimax-cn.models.d.ts.map +1 -0
- package/dist/providers/minimax-cn.models.js +56 -0
- package/dist/providers/minimax-cn.models.js.map +1 -0
- package/dist/providers/minimax.d.ts +3 -0
- package/dist/providers/minimax.d.ts.map +1 -0
- package/dist/providers/minimax.js +15 -0
- package/dist/providers/minimax.js.map +1 -0
- package/dist/providers/minimax.models.d.ts +54 -0
- package/dist/providers/minimax.models.d.ts.map +1 -0
- package/dist/providers/minimax.models.js +56 -0
- package/dist/providers/minimax.models.js.map +1 -0
- package/dist/providers/mistral.d.ts +2 -25
- package/dist/providers/mistral.d.ts.map +1 -1
- package/dist/providers/mistral.js +12 -560
- package/dist/providers/mistral.js.map +1 -1
- package/dist/providers/mistral.models.d.ts +513 -0
- package/dist/providers/mistral.models.d.ts.map +1 -0
- package/dist/providers/mistral.models.js +515 -0
- package/dist/providers/mistral.models.js.map +1 -0
- package/dist/providers/moonshotai-cn.d.ts +3 -0
- package/dist/providers/moonshotai-cn.d.ts.map +1 -0
- package/dist/providers/moonshotai-cn.js +15 -0
- package/dist/providers/moonshotai-cn.js.map +1 -0
- package/dist/providers/moonshotai-cn.models.d.ts +234 -0
- package/dist/providers/moonshotai-cn.models.d.ts.map +1 -0
- package/dist/providers/moonshotai-cn.models.js +169 -0
- package/dist/providers/moonshotai-cn.models.js.map +1 -0
- package/dist/providers/moonshotai.d.ts +3 -0
- package/dist/providers/moonshotai.d.ts.map +1 -0
- package/dist/providers/moonshotai.js +15 -0
- package/dist/providers/moonshotai.js.map +1 -0
- package/dist/providers/moonshotai.models.d.ts +234 -0
- package/dist/providers/moonshotai.models.d.ts.map +1 -0
- package/dist/providers/moonshotai.models.js +169 -0
- package/dist/providers/moonshotai.models.js.map +1 -0
- package/dist/providers/nvidia.d.ts +3 -0
- package/dist/providers/nvidia.d.ts.map +1 -0
- package/dist/providers/nvidia.js +15 -0
- package/dist/providers/nvidia.js.map +1 -0
- package/dist/providers/nvidia.models.d.ts +535 -0
- package/dist/providers/nvidia.models.d.ts.map +1 -0
- package/dist/providers/nvidia.models.js +366 -0
- package/dist/providers/nvidia.models.js.map +1 -0
- package/dist/providers/openai-codex.d.ts +3 -0
- package/dist/providers/openai-codex.d.ts.map +1 -0
- package/dist/providers/openai-codex.js +18 -0
- package/dist/providers/openai-codex.js.map +1 -0
- package/dist/providers/openai-codex.models.d.ts +87 -0
- package/dist/providers/openai-codex.models.d.ts.map +1 -0
- package/dist/providers/openai-codex.models.js +77 -0
- package/dist/providers/openai-codex.models.js.map +1 -0
- package/dist/providers/openai.d.ts +3 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +15 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/openai.models.d.ts +805 -0
- package/dist/providers/openai.models.d.ts.map +1 -0
- package/dist/providers/openai.models.js +743 -0
- package/dist/providers/openai.models.js.map +1 -0
- package/dist/providers/opencode-go.d.ts +3 -0
- package/dist/providers/opencode-go.d.ts.map +1 -0
- package/dist/providers/opencode-go.js +18 -0
- package/dist/providers/opencode-go.js.map +1 -0
- package/dist/providers/opencode-go.models.d.ts +309 -0
- package/dist/providers/opencode-go.models.d.ts.map +1 -0
- package/dist/providers/opencode-go.models.js +240 -0
- package/dist/providers/opencode-go.models.js.map +1 -0
- package/dist/providers/opencode.d.ts +3 -0
- package/dist/providers/opencode.d.ts.map +1 -0
- package/dist/providers/opencode.js +22 -0
- package/dist/providers/opencode.js.map +1 -0
- package/dist/providers/opencode.models.d.ts +976 -0
- package/dist/providers/opencode.models.d.ts.map +1 -0
- package/dist/providers/opencode.models.js +815 -0
- package/dist/providers/opencode.models.js.map +1 -0
- package/dist/providers/openrouter-images.d.ts +3 -0
- package/dist/providers/openrouter-images.d.ts.map +1 -0
- package/dist/providers/openrouter-images.js +14 -0
- package/dist/providers/openrouter-images.js.map +1 -0
- package/dist/providers/openrouter.d.ts +3 -0
- package/dist/providers/openrouter.d.ts.map +1 -0
- package/dist/providers/openrouter.js +15 -0
- package/dist/providers/openrouter.js.map +1 -0
- package/dist/providers/openrouter.models.d.ts +5405 -0
- package/dist/providers/openrouter.models.d.ts.map +1 -0
- package/dist/providers/openrouter.models.js +4635 -0
- package/dist/providers/openrouter.models.js.map +1 -0
- package/dist/providers/together.d.ts +3 -0
- package/dist/providers/together.d.ts.map +1 -0
- package/dist/providers/together.js +15 -0
- package/dist/providers/together.js.map +1 -0
- package/dist/providers/together.models.d.ts +567 -0
- package/dist/providers/together.models.d.ts.map +1 -0
- package/dist/providers/together.models.js +361 -0
- package/dist/providers/together.models.js.map +1 -0
- package/dist/providers/vercel-ai-gateway.d.ts +3 -0
- package/dist/providers/vercel-ai-gateway.d.ts.map +1 -0
- package/dist/providers/vercel-ai-gateway.js +15 -0
- package/dist/providers/vercel-ai-gateway.js.map +1 -0
- package/dist/providers/vercel-ai-gateway.models.d.ts +2938 -0
- package/dist/providers/vercel-ai-gateway.models.d.ts.map +1 -0
- package/dist/providers/vercel-ai-gateway.models.js +2897 -0
- package/dist/providers/vercel-ai-gateway.models.js.map +1 -0
- package/dist/providers/xai.d.ts +3 -0
- package/dist/providers/xai.d.ts.map +1 -0
- package/dist/providers/xai.js +15 -0
- package/dist/providers/xai.js.map +1 -0
- package/dist/providers/xai.models.d.ts +157 -0
- package/dist/providers/xai.models.d.ts.map +1 -0
- package/dist/providers/xai.models.js +131 -0
- package/dist/providers/xai.models.js.map +1 -0
- package/dist/providers/xiaomi-token-plan-ams.d.ts +3 -0
- package/dist/providers/xiaomi-token-plan-ams.d.ts.map +1 -0
- package/dist/providers/xiaomi-token-plan-ams.js +15 -0
- package/dist/providers/xiaomi-token-plan-ams.js.map +1 -0
- package/dist/providers/xiaomi-token-plan-ams.models.d.ts +108 -0
- package/dist/providers/xiaomi-token-plan-ams.models.d.ts.map +1 -0
- package/dist/providers/xiaomi-token-plan-ams.models.js +95 -0
- package/dist/providers/xiaomi-token-plan-ams.models.js.map +1 -0
- package/dist/providers/xiaomi-token-plan-cn.d.ts +3 -0
- package/dist/providers/xiaomi-token-plan-cn.d.ts.map +1 -0
- package/dist/providers/xiaomi-token-plan-cn.js +15 -0
- package/dist/providers/xiaomi-token-plan-cn.js.map +1 -0
- package/dist/providers/xiaomi-token-plan-cn.models.d.ts +108 -0
- package/dist/providers/xiaomi-token-plan-cn.models.d.ts.map +1 -0
- package/dist/providers/xiaomi-token-plan-cn.models.js +95 -0
- package/dist/providers/xiaomi-token-plan-cn.models.js.map +1 -0
- package/dist/providers/xiaomi-token-plan-sgp.d.ts +3 -0
- package/dist/providers/xiaomi-token-plan-sgp.d.ts.map +1 -0
- package/dist/providers/xiaomi-token-plan-sgp.js +15 -0
- package/dist/providers/xiaomi-token-plan-sgp.js.map +1 -0
- package/dist/providers/xiaomi-token-plan-sgp.models.d.ts +108 -0
- package/dist/providers/xiaomi-token-plan-sgp.models.d.ts.map +1 -0
- package/dist/providers/xiaomi-token-plan-sgp.models.js +95 -0
- package/dist/providers/xiaomi-token-plan-sgp.models.js.map +1 -0
- package/dist/providers/xiaomi.d.ts +3 -0
- package/dist/providers/xiaomi.d.ts.map +1 -0
- package/dist/providers/xiaomi.js +15 -0
- package/dist/providers/xiaomi.js.map +1 -0
- package/dist/providers/xiaomi.models.d.ts +129 -0
- package/dist/providers/xiaomi.models.d.ts.map +1 -0
- package/dist/providers/xiaomi.models.js +113 -0
- package/dist/providers/xiaomi.models.js.map +1 -0
- package/dist/providers/zai-coding-cn.d.ts +3 -0
- package/dist/providers/zai-coding-cn.d.ts.map +1 -0
- package/dist/providers/zai-coding-cn.js +15 -0
- package/dist/providers/zai-coding-cn.js.map +1 -0
- package/dist/providers/zai-coding-cn.models.d.ts +153 -0
- package/dist/providers/zai-coding-cn.models.d.ts.map +1 -0
- package/dist/providers/zai-coding-cn.models.js +114 -0
- package/dist/providers/zai-coding-cn.models.js.map +1 -0
- package/dist/providers/zai.d.ts +3 -0
- package/dist/providers/zai.d.ts.map +1 -0
- package/dist/providers/zai.js +15 -0
- package/dist/providers/zai.js.map +1 -0
- package/dist/providers/zai.models.d.ts +153 -0
- package/dist/providers/zai.models.d.ts.map +1 -0
- package/dist/providers/zai.models.js +114 -0
- package/dist/providers/zai.models.js.map +1 -0
- package/dist/types.d.ts +67 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/headers.d.ts +2 -0
- package/dist/utils/headers.d.ts.map +1 -1
- package/dist/utils/headers.js +10 -0
- package/dist/utils/headers.js.map +1 -1
- package/dist/utils/oauth/anthropic.d.ts +2 -0
- package/dist/utils/oauth/anthropic.d.ts.map +1 -1
- package/dist/utils/oauth/anthropic.js +31 -0
- package/dist/utils/oauth/anthropic.js.map +1 -1
- package/dist/utils/oauth/github-copilot.d.ts +2 -0
- package/dist/utils/oauth/github-copilot.d.ts.map +1 -1
- package/dist/utils/oauth/github-copilot.js +33 -2
- package/dist/utils/oauth/github-copilot.js.map +1 -1
- package/dist/utils/oauth/load.d.ts +5 -0
- package/dist/utils/oauth/load.d.ts.map +1 -0
- package/dist/utils/oauth/load.js +22 -0
- package/dist/utils/oauth/load.js.map +1 -0
- package/dist/utils/oauth/openai-codex.d.ts +2 -0
- package/dist/utils/oauth/openai-codex.d.ts.map +1 -1
- package/dist/utils/oauth/openai-codex.js +49 -0
- package/dist/utils/oauth/openai-codex.js.map +1 -1
- package/package.json +15 -42
- package/dist/api-registry.d.ts +0 -20
- package/dist/api-registry.d.ts.map +0 -1
- package/dist/api-registry.js +0 -44
- package/dist/api-registry.js.map +0 -1
- package/dist/base.d.ts +0 -30
- package/dist/base.d.ts.map +0 -1
- package/dist/base.js +0 -18
- package/dist/base.js.map +0 -1
- package/dist/providers/cloudflare.d.ts.map +0 -1
- package/dist/providers/cloudflare.js.map +0 -1
- package/dist/providers/github-copilot-headers.d.ts.map +0 -1
- package/dist/providers/github-copilot-headers.js.map +0 -1
- package/dist/providers/google-shared.d.ts.map +0 -1
- package/dist/providers/google-shared.js.map +0 -1
- package/dist/providers/images/openrouter.d.ts.map +0 -1
- package/dist/providers/images/openrouter.js.map +0 -1
- package/dist/providers/openai-codex-responses.d.ts.map +0 -1
- package/dist/providers/openai-codex-responses.js.map +0 -1
- package/dist/providers/openai-completions.d.ts.map +0 -1
- package/dist/providers/openai-completions.js.map +0 -1
- package/dist/providers/openai-prompt-cache.d.ts.map +0 -1
- package/dist/providers/openai-prompt-cache.js.map +0 -1
- package/dist/providers/openai-responses-shared.d.ts.map +0 -1
- package/dist/providers/openai-responses-shared.js.map +0 -1
- package/dist/providers/openai-responses.d.ts.map +0 -1
- package/dist/providers/openai-responses.js.map +0 -1
- package/dist/providers/register-builtins.d.ts +0 -37
- package/dist/providers/register-builtins.d.ts.map +0 -1
- package/dist/providers/register-builtins.js +0 -191
- package/dist/providers/register-builtins.js.map +0 -1
- package/dist/providers/simple-options.d.ts.map +0 -1
- package/dist/providers/simple-options.js.map +0 -1
- package/dist/providers/transform-messages.d.ts.map +0 -1
- package/dist/providers/transform-messages.js.map +0 -1
- package/dist/stream.d.ts +0 -6
- package/dist/stream.d.ts.map +0 -1
- package/dist/stream.js +0 -37
- package/dist/stream.js.map +0 -1
- /package/dist/{providers → api}/github-copilot-headers.d.ts +0 -0
- /package/dist/{providers → api}/github-copilot-headers.js +0 -0
- /package/dist/{providers → api}/google-shared.d.ts +0 -0
- /package/dist/{providers → api}/google-shared.js +0 -0
- /package/dist/{providers → api}/openai-prompt-cache.d.ts +0 -0
- /package/dist/{providers → api}/openai-prompt-cache.js +0 -0
- /package/dist/{providers → api}/openai-responses-shared.d.ts +0 -0
- /package/dist/{providers → api}/simple-options.d.ts +0 -0
- /package/dist/{providers → api}/simple-options.js +0 -0
- /package/dist/{providers → api}/transform-messages.d.ts +0 -0
- /package/dist/{providers → api}/transform-messages.js +0 -0
|
@@ -220,8 +220,39 @@ export function convertResponsesTools(tools, options) {
|
|
|
220
220
|
export async function processResponsesStream(openaiStream, output, stream, model, options) {
|
|
221
221
|
let currentItem = null;
|
|
222
222
|
let currentBlock = null;
|
|
223
|
+
let sawTerminalResponseEvent = false;
|
|
223
224
|
const blocks = output.content;
|
|
224
225
|
const blockIndex = () => blocks.length - 1;
|
|
226
|
+
const finalizeResponse = (response) => {
|
|
227
|
+
sawTerminalResponseEvent = true;
|
|
228
|
+
if (response?.id) {
|
|
229
|
+
output.responseId = response.id;
|
|
230
|
+
}
|
|
231
|
+
if (response?.usage) {
|
|
232
|
+
const cachedTokens = response.usage.input_tokens_details?.cached_tokens || 0;
|
|
233
|
+
output.usage = {
|
|
234
|
+
// OpenAI includes cached tokens in input_tokens, so subtract to get non-cached input
|
|
235
|
+
input: (response.usage.input_tokens || 0) - cachedTokens,
|
|
236
|
+
output: response.usage.output_tokens || 0,
|
|
237
|
+
cacheRead: cachedTokens,
|
|
238
|
+
cacheWrite: 0,
|
|
239
|
+
totalTokens: response.usage.total_tokens || 0,
|
|
240
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
calculateCost(model, output.usage);
|
|
244
|
+
if (options?.applyServiceTierPricing) {
|
|
245
|
+
const serviceTier = options.resolveServiceTier
|
|
246
|
+
? options.resolveServiceTier(response?.service_tier, options.serviceTier)
|
|
247
|
+
: (response?.service_tier ?? options.serviceTier);
|
|
248
|
+
options.applyServiceTierPricing(output.usage, serviceTier);
|
|
249
|
+
}
|
|
250
|
+
// Map status to stop reason
|
|
251
|
+
output.stopReason = mapStopReason(response?.status);
|
|
252
|
+
if (output.content.some((b) => b.type === "toolCall") && output.stopReason === "stop") {
|
|
253
|
+
output.stopReason = "toolUse";
|
|
254
|
+
}
|
|
255
|
+
};
|
|
225
256
|
for await (const event of openaiStream) {
|
|
226
257
|
if (event.type === "response.created") {
|
|
227
258
|
output.responseId = event.response.id;
|
|
@@ -428,40 +459,14 @@ export async function processResponsesStream(openaiStream, output, stream, model
|
|
|
428
459
|
stream.push({ type: "toolcall_end", contentIndex: blockIndex(), toolCall, partial: output });
|
|
429
460
|
}
|
|
430
461
|
}
|
|
431
|
-
else if (event.type === "response.completed") {
|
|
432
|
-
|
|
433
|
-
if (response?.id) {
|
|
434
|
-
output.responseId = response.id;
|
|
435
|
-
}
|
|
436
|
-
if (response?.usage) {
|
|
437
|
-
const cachedTokens = response.usage.input_tokens_details?.cached_tokens || 0;
|
|
438
|
-
output.usage = {
|
|
439
|
-
// OpenAI includes cached tokens in input_tokens, so subtract to get non-cached input
|
|
440
|
-
input: (response.usage.input_tokens || 0) - cachedTokens,
|
|
441
|
-
output: response.usage.output_tokens || 0,
|
|
442
|
-
cacheRead: cachedTokens,
|
|
443
|
-
cacheWrite: 0,
|
|
444
|
-
totalTokens: response.usage.total_tokens || 0,
|
|
445
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
446
|
-
};
|
|
447
|
-
}
|
|
448
|
-
calculateCost(model, output.usage);
|
|
449
|
-
if (options?.applyServiceTierPricing) {
|
|
450
|
-
const serviceTier = options.resolveServiceTier
|
|
451
|
-
? options.resolveServiceTier(response?.service_tier, options.serviceTier)
|
|
452
|
-
: (response?.service_tier ?? options.serviceTier);
|
|
453
|
-
options.applyServiceTierPricing(output.usage, serviceTier);
|
|
454
|
-
}
|
|
455
|
-
// Map status to stop reason
|
|
456
|
-
output.stopReason = mapStopReason(response?.status);
|
|
457
|
-
if (output.content.some((b) => b.type === "toolCall") && output.stopReason === "stop") {
|
|
458
|
-
output.stopReason = "toolUse";
|
|
459
|
-
}
|
|
462
|
+
else if (event.type === "response.completed" || event.type === "response.incomplete") {
|
|
463
|
+
finalizeResponse(event.response);
|
|
460
464
|
}
|
|
461
465
|
else if (event.type === "error") {
|
|
462
466
|
throw new Error(`Error Code ${event.code}: ${event.message}` || "Unknown error");
|
|
463
467
|
}
|
|
464
468
|
else if (event.type === "response.failed") {
|
|
469
|
+
sawTerminalResponseEvent = true;
|
|
465
470
|
const error = event.response?.error;
|
|
466
471
|
const details = event.response?.incomplete_details;
|
|
467
472
|
const msg = error
|
|
@@ -472,6 +477,9 @@ export async function processResponsesStream(openaiStream, output, stream, model
|
|
|
472
477
|
throw new Error(msg);
|
|
473
478
|
}
|
|
474
479
|
}
|
|
480
|
+
if (!sawTerminalResponseEvent) {
|
|
481
|
+
throw new Error("OpenAI Responses stream ended before a terminal response event");
|
|
482
|
+
}
|
|
475
483
|
}
|
|
476
484
|
function mapStopReason(status) {
|
|
477
485
|
if (!status)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-responses-shared.js","sourceRoot":"","sources":["../../src/api/openai-responses-shared.ts"],"names":[],"mappings":"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","sourcesContent":["import type OpenAI from \"openai\";\nimport type {\n\tTool as OpenAITool,\n\tResponseCreateParamsStreaming,\n\tResponseFunctionCallOutputItemList,\n\tResponseFunctionToolCall,\n\tResponseInput,\n\tResponseInputContent,\n\tResponseInputImage,\n\tResponseInputText,\n\tResponseOutputMessage,\n\tResponseReasoningItem,\n\tResponseStreamEvent,\n} from \"openai/resources/responses/responses.js\";\nimport { calculateCost } from \"../models.ts\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tContext,\n\tImageContent,\n\tModel,\n\tStopReason,\n\tTextContent,\n\tTextSignatureV1,\n\tThinkingContent,\n\tTool,\n\tToolCall,\n\tUsage,\n} from \"../types.ts\";\nimport type { AssistantMessageEventStream } from \"../utils/event-stream.ts\";\nimport { shortHash } from \"../utils/hash.ts\";\nimport { parseStreamingJson } from \"../utils/json-parse.ts\";\nimport { sanitizeSurrogates } from \"../utils/sanitize-unicode.ts\";\nimport { transformMessages } from \"./transform-messages.ts\";\n\n// =============================================================================\n// Utilities\n// =============================================================================\n\nfunction encodeTextSignatureV1(id: string, phase?: TextSignatureV1[\"phase\"]): string {\n\tconst payload: TextSignatureV1 = { v: 1, id };\n\tif (phase) payload.phase = phase;\n\treturn JSON.stringify(payload);\n}\n\nfunction parseTextSignature(\n\tsignature: string | undefined,\n): { id: string; phase?: TextSignatureV1[\"phase\"] } | undefined {\n\tif (!signature) return undefined;\n\tif (signature.startsWith(\"{\")) {\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(signature) as Partial<TextSignatureV1>;\n\t\t\tif (parsed.v === 1 && typeof parsed.id === \"string\") {\n\t\t\t\tif (parsed.phase === \"commentary\" || parsed.phase === \"final_answer\") {\n\t\t\t\t\treturn { id: parsed.id, phase: parsed.phase };\n\t\t\t\t}\n\t\t\t\treturn { id: parsed.id };\n\t\t\t}\n\t\t} catch {\n\t\t\t// Fall through to legacy plain-string handling.\n\t\t}\n\t}\n\treturn { id: signature };\n}\n\nexport interface OpenAIResponsesStreamOptions {\n\tserviceTier?: ResponseCreateParamsStreaming[\"service_tier\"];\n\tresolveServiceTier?: (\n\t\tresponseServiceTier: ResponseCreateParamsStreaming[\"service_tier\"] | undefined,\n\t\trequestServiceTier: ResponseCreateParamsStreaming[\"service_tier\"] | undefined,\n\t) => ResponseCreateParamsStreaming[\"service_tier\"] | undefined;\n\tapplyServiceTierPricing?: (\n\t\tusage: Usage,\n\t\tserviceTier: ResponseCreateParamsStreaming[\"service_tier\"] | undefined,\n\t) => void;\n}\n\nexport interface ConvertResponsesMessagesOptions {\n\tincludeSystemPrompt?: boolean;\n}\n\nexport interface ConvertResponsesToolsOptions {\n\tstrict?: boolean | null;\n}\n\n// =============================================================================\n// Message conversion\n// =============================================================================\n\nexport function convertResponsesMessages<TApi extends Api>(\n\tmodel: Model<TApi>,\n\tcontext: Context,\n\tallowedToolCallProviders: ReadonlySet<string>,\n\toptions?: ConvertResponsesMessagesOptions,\n): ResponseInput {\n\tconst messages: ResponseInput = [];\n\n\tconst normalizeIdPart = (part: string): string => {\n\t\tconst sanitized = part.replace(/[^a-zA-Z0-9_-]/g, \"_\");\n\t\tconst normalized = sanitized.length > 64 ? sanitized.slice(0, 64) : sanitized;\n\t\treturn normalized.replace(/_+$/, \"\");\n\t};\n\n\tconst buildForeignResponsesItemId = (itemId: string): string => {\n\t\tconst normalized = `fc_${shortHash(itemId)}`;\n\t\treturn normalized.length > 64 ? normalized.slice(0, 64) : normalized;\n\t};\n\n\tconst normalizeToolCallId = (id: string, _targetModel: Model<TApi>, source: AssistantMessage): string => {\n\t\tif (!allowedToolCallProviders.has(model.provider)) return normalizeIdPart(id);\n\t\tif (!id.includes(\"|\")) return normalizeIdPart(id);\n\t\tconst [callId, itemId] = id.split(\"|\");\n\t\tconst normalizedCallId = normalizeIdPart(callId);\n\t\tconst isForeignToolCall = source.provider !== model.provider || source.api !== model.api;\n\t\tlet normalizedItemId = isForeignToolCall ? buildForeignResponsesItemId(itemId) : normalizeIdPart(itemId);\n\t\t// OpenAI Responses API requires item id to start with \"fc\"\n\t\tif (!normalizedItemId.startsWith(\"fc_\")) {\n\t\t\tnormalizedItemId = normalizeIdPart(`fc_${normalizedItemId}`);\n\t\t}\n\t\treturn `${normalizedCallId}|${normalizedItemId}`;\n\t};\n\n\tconst transformedMessages = transformMessages(context.messages, model, normalizeToolCallId);\n\n\tconst includeSystemPrompt = options?.includeSystemPrompt ?? true;\n\tif (includeSystemPrompt && context.systemPrompt) {\n\t\tconst compat = model.compat as { supportsDeveloperRole?: boolean } | undefined;\n\t\tconst role = model.reasoning && compat?.supportsDeveloperRole !== false ? \"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}\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: \"input_image\",\n\t\t\t\t\t\tdetail: \"auto\",\n\t\t\t\t\t\timage_url: `data:${item.mimeType};base64,${item.data}`,\n\t\t\t\t\t} satisfies ResponseInputImage;\n\t\t\t\t});\n\t\t\t\tif (content.length === 0) continue;\n\t\t\t\tmessages.push({\n\t\t\t\t\trole: \"user\",\n\t\t\t\t\tcontent,\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 assistantMsg = msg as AssistantMessage;\n\t\t\tconst isDifferentModel =\n\t\t\t\tassistantMsg.model !== model.id &&\n\t\t\t\tassistantMsg.provider === model.provider &&\n\t\t\t\tassistantMsg.api === model.api;\n\t\t\tlet textBlockIndex = 0;\n\n\t\t\tfor (const block of msg.content) {\n\t\t\t\tif (block.type === \"thinking\") {\n\t\t\t\t\tif (block.thinkingSignature) {\n\t\t\t\t\t\tconst reasoningItem = JSON.parse(block.thinkingSignature) as ResponseReasoningItem;\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\tconst parsedSignature = parseTextSignature(textBlock.textSignature);\n\t\t\t\t\tconst fallbackMessageId =\n\t\t\t\t\t\ttextBlockIndex === 0 ? `msg_pi_${msgIndex}` : `msg_pi_${msgIndex}_${textBlockIndex}`;\n\t\t\t\t\ttextBlockIndex++;\n\t\t\t\t\t// OpenAI requires id to be max 64 characters\n\t\t\t\t\tlet msgId = parsedSignature?.id;\n\t\t\t\t\tif (!msgId) {\n\t\t\t\t\t\tmsgId = fallbackMessageId;\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\tphase: parsedSignature?.phase,\n\t\t\t\t\t} satisfies ResponseOutputMessage);\n\t\t\t\t} else if (block.type === \"toolCall\") {\n\t\t\t\t\tconst toolCall = block as ToolCall;\n\t\t\t\t\tconst [callId, itemIdRaw] = toolCall.id.split(\"|\");\n\t\t\t\t\tlet itemId: string | undefined = itemIdRaw;\n\n\t\t\t\t\t// For different-model messages, set id to undefined to avoid pairing validation.\n\t\t\t\t\t// OpenAI tracks which fc_xxx IDs were paired with rs_xxx reasoning items.\n\t\t\t\t\t// By omitting the id, we avoid triggering that validation (like cross-provider does).\n\t\t\t\t\tif (isDifferentModel && itemId?.startsWith(\"fc_\")) {\n\t\t\t\t\t\titemId = undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\toutput.push({\n\t\t\t\t\t\ttype: \"function_call\",\n\t\t\t\t\t\tid: itemId,\n\t\t\t\t\t\tcall_id: callId,\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\tconst textResult = msg.content\n\t\t\t\t.filter((c): c is TextContent => c.type === \"text\")\n\t\t\t\t.map((c) => c.text)\n\t\t\t\t.join(\"\\n\");\n\t\t\tconst hasImages = msg.content.some((c): c is ImageContent => c.type === \"image\");\n\t\t\tconst hasText = textResult.length > 0;\n\t\t\tconst [callId] = msg.toolCallId.split(\"|\");\n\n\t\t\tlet output: string | ResponseFunctionCallOutputItemList;\n\t\t\tif (hasImages && model.input.includes(\"image\")) {\n\t\t\t\tconst contentParts: ResponseFunctionCallOutputItemList = [];\n\n\t\t\t\tif (hasText) {\n\t\t\t\t\tcontentParts.push({\n\t\t\t\t\t\ttype: \"input_text\",\n\t\t\t\t\t\ttext: sanitizeSurrogates(textResult),\n\t\t\t\t\t});\n\t\t\t\t}\n\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.mimeType};base64,${block.data}`,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\toutput = contentParts;\n\t\t\t} else {\n\t\t\t\toutput = sanitizeSurrogates(hasText ? textResult : \"(see attached image)\");\n\t\t\t}\n\n\t\t\tmessages.push({\n\t\t\t\ttype: \"function_call_output\",\n\t\t\t\tcall_id: callId,\n\t\t\t\toutput,\n\t\t\t});\n\t\t}\n\t\tmsgIndex++;\n\t}\n\n\treturn messages;\n}\n\n// =============================================================================\n// Tool conversion\n// =============================================================================\n\nexport function convertResponsesTools(tools: Tool[], options?: ConvertResponsesToolsOptions): OpenAITool[] {\n\tconst strict = options?.strict === undefined ? false : options.strict;\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,\n\t}));\n}\n\n// =============================================================================\n// Stream processing\n// =============================================================================\n\nexport async function processResponsesStream<TApi extends Api>(\n\topenaiStream: AsyncIterable<ResponseStreamEvent>,\n\toutput: AssistantMessage,\n\tstream: AssistantMessageEventStream,\n\tmodel: Model<TApi>,\n\toptions?: OpenAIResponsesStreamOptions,\n): Promise<void> {\n\tlet currentItem: ResponseReasoningItem | ResponseOutputMessage | ResponseFunctionToolCall | null = null;\n\tlet currentBlock: ThinkingContent | TextContent | (ToolCall & { partialJson: string }) | null = null;\n\tlet sawTerminalResponseEvent = false;\n\tconst blocks = output.content;\n\tconst blockIndex = () => blocks.length - 1;\n\tconst finalizeResponse = (\n\t\tresponse: Extract<ResponseStreamEvent, { type: \"response.completed\" | \"response.incomplete\" }>[\"response\"],\n\t): void => {\n\t\tsawTerminalResponseEvent = true;\n\t\tif (response?.id) {\n\t\t\toutput.responseId = response.id;\n\t\t}\n\t\tif (response?.usage) {\n\t\t\tconst cachedTokens = response.usage.input_tokens_details?.cached_tokens || 0;\n\t\t\toutput.usage = {\n\t\t\t\t// OpenAI includes cached tokens in input_tokens, so subtract to get non-cached input\n\t\t\t\tinput: (response.usage.input_tokens || 0) - cachedTokens,\n\t\t\t\toutput: response.usage.output_tokens || 0,\n\t\t\t\tcacheRead: cachedTokens,\n\t\t\t\tcacheWrite: 0,\n\t\t\t\ttotalTokens: response.usage.total_tokens || 0,\n\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t};\n\t\t}\n\t\tcalculateCost(model, output.usage);\n\t\tif (options?.applyServiceTierPricing) {\n\t\t\tconst serviceTier = options.resolveServiceTier\n\t\t\t\t? options.resolveServiceTier(response?.service_tier, options.serviceTier)\n\t\t\t\t: (response?.service_tier ?? options.serviceTier);\n\t\t\toptions.applyServiceTierPricing(output.usage, serviceTier);\n\t\t}\n\t\t// Map status to stop reason\n\t\toutput.stopReason = mapStopReason(response?.status);\n\t\tif (output.content.some((b) => b.type === \"toolCall\") && output.stopReason === \"stop\") {\n\t\t\toutput.stopReason = \"toolUse\";\n\t\t}\n\t};\n\n\tfor await (const event of openaiStream) {\n\t\tif (event.type === \"response.created\") {\n\t\t\toutput.responseId = event.response.id;\n\t\t} else if (event.type === \"response.output_item.added\") {\n\t\t\tconst item = event.item;\n\t\t\tif (item.type === \"reasoning\") {\n\t\t\t\tcurrentItem = item;\n\t\t\t\tcurrentBlock = { type: \"thinking\", thinking: \"\" };\n\t\t\t\toutput.content.push(currentBlock);\n\t\t\t\tstream.push({ type: \"thinking_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t} else if (item.type === \"message\") {\n\t\t\t\tcurrentItem = item;\n\t\t\t\tcurrentBlock = { type: \"text\", text: \"\" };\n\t\t\t\toutput.content.push(currentBlock);\n\t\t\t\tstream.push({ type: \"text_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t} else if (item.type === \"function_call\") {\n\t\t\t\tcurrentItem = item;\n\t\t\t\tcurrentBlock = {\n\t\t\t\t\ttype: \"toolCall\",\n\t\t\t\t\tid: `${item.call_id}|${item.id}`,\n\t\t\t\t\tname: item.name,\n\t\t\t\t\targuments: {},\n\t\t\t\t\tpartialJson: item.arguments || \"\",\n\t\t\t\t};\n\t\t\t\toutput.content.push(currentBlock);\n\t\t\t\tstream.push({ type: \"toolcall_start\", contentIndex: blockIndex(), partial: output });\n\t\t\t}\n\t\t} else if (event.type === \"response.reasoning_summary_part.added\") {\n\t\t\tif (currentItem && currentItem.type === \"reasoning\") {\n\t\t\t\tcurrentItem.summary = currentItem.summary || [];\n\t\t\t\tcurrentItem.summary.push(event.part);\n\t\t\t}\n\t\t} else if (event.type === \"response.reasoning_summary_text.delta\") {\n\t\t\tif (currentItem?.type === \"reasoning\" && currentBlock?.type === \"thinking\") {\n\t\t\t\tcurrentItem.summary = currentItem.summary || [];\n\t\t\t\tconst lastPart = currentItem.summary[currentItem.summary.length - 1];\n\t\t\t\tif (lastPart) {\n\t\t\t\t\tcurrentBlock.thinking += event.delta;\n\t\t\t\t\tlastPart.text += event.delta;\n\t\t\t\t\tstream.push({\n\t\t\t\t\t\ttype: \"thinking_delta\",\n\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\tdelta: event.delta,\n\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (event.type === \"response.reasoning_summary_part.done\") {\n\t\t\tif (currentItem?.type === \"reasoning\" && currentBlock?.type === \"thinking\") {\n\t\t\t\tcurrentItem.summary = currentItem.summary || [];\n\t\t\t\tconst lastPart = currentItem.summary[currentItem.summary.length - 1];\n\t\t\t\tif (lastPart) {\n\t\t\t\t\tcurrentBlock.thinking += \"\\n\\n\";\n\t\t\t\t\tlastPart.text += \"\\n\\n\";\n\t\t\t\t\tstream.push({\n\t\t\t\t\t\ttype: \"thinking_delta\",\n\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\tdelta: \"\\n\\n\",\n\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (event.type === \"response.reasoning_text.delta\") {\n\t\t\tif (currentItem?.type === \"reasoning\" && currentBlock?.type === \"thinking\") {\n\t\t\t\tcurrentBlock.thinking += event.delta;\n\t\t\t\tstream.push({\n\t\t\t\t\ttype: \"thinking_delta\",\n\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\tdelta: event.delta,\n\t\t\t\t\tpartial: output,\n\t\t\t\t});\n\t\t\t}\n\t\t} else if (event.type === \"response.content_part.added\") {\n\t\t\tif (currentItem?.type === \"message\") {\n\t\t\t\tcurrentItem.content = currentItem.content || [];\n\t\t\t\t// Filter out ReasoningText, only accept output_text and refusal\n\t\t\t\tif (event.part.type === \"output_text\" || event.part.type === \"refusal\") {\n\t\t\t\t\tcurrentItem.content.push(event.part);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (event.type === \"response.output_text.delta\") {\n\t\t\tif (currentItem?.type === \"message\" && currentBlock?.type === \"text\") {\n\t\t\t\tif (!currentItem.content || currentItem.content.length === 0) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst lastPart = currentItem.content[currentItem.content.length - 1];\n\t\t\t\tif (lastPart?.type === \"output_text\") {\n\t\t\t\t\tcurrentBlock.text += event.delta;\n\t\t\t\t\tlastPart.text += event.delta;\n\t\t\t\t\tstream.push({\n\t\t\t\t\t\ttype: \"text_delta\",\n\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\tdelta: event.delta,\n\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (event.type === \"response.refusal.delta\") {\n\t\t\tif (currentItem?.type === \"message\" && currentBlock?.type === \"text\") {\n\t\t\t\tif (!currentItem.content || currentItem.content.length === 0) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst lastPart = currentItem.content[currentItem.content.length - 1];\n\t\t\t\tif (lastPart?.type === \"refusal\") {\n\t\t\t\t\tcurrentBlock.text += event.delta;\n\t\t\t\t\tlastPart.refusal += event.delta;\n\t\t\t\t\tstream.push({\n\t\t\t\t\t\ttype: \"text_delta\",\n\t\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\t\tdelta: event.delta,\n\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (event.type === \"response.function_call_arguments.delta\") {\n\t\t\tif (currentItem?.type === \"function_call\" && currentBlock?.type === \"toolCall\") {\n\t\t\t\tcurrentBlock.partialJson += event.delta;\n\t\t\t\tcurrentBlock.arguments = parseStreamingJson(currentBlock.partialJson);\n\t\t\t\tstream.push({\n\t\t\t\t\ttype: \"toolcall_delta\",\n\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\tdelta: event.delta,\n\t\t\t\t\tpartial: output,\n\t\t\t\t});\n\t\t\t}\n\t\t} else if (event.type === \"response.function_call_arguments.done\") {\n\t\t\tif (currentItem?.type === \"function_call\" && currentBlock?.type === \"toolCall\") {\n\t\t\t\tconst previousPartialJson = currentBlock.partialJson;\n\t\t\t\tcurrentBlock.partialJson = event.arguments;\n\t\t\t\tcurrentBlock.arguments = parseStreamingJson(currentBlock.partialJson);\n\n\t\t\t\tif (event.arguments.startsWith(previousPartialJson)) {\n\t\t\t\t\tconst delta = event.arguments.slice(previousPartialJson.length);\n\t\t\t\t\tif (delta.length > 0) {\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,\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}\n\t\t} else if (event.type === \"response.output_item.done\") {\n\t\t\tconst item = event.item;\n\n\t\t\tif (item.type === \"reasoning\" && currentBlock?.type === \"thinking\") {\n\t\t\t\tconst summaryText = item.summary?.map((s) => s.text).join(\"\\n\\n\") || \"\";\n\t\t\t\tconst contentText = item.content?.map((c) => c.text).join(\"\\n\\n\") || \"\";\n\t\t\t\tcurrentBlock.thinking = summaryText || contentText || currentBlock.thinking;\n\t\t\t\tcurrentBlock.thinkingSignature = JSON.stringify(item);\n\t\t\t\tstream.push({\n\t\t\t\t\ttype: \"thinking_end\",\n\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\tcontent: currentBlock.thinking,\n\t\t\t\t\tpartial: output,\n\t\t\t\t});\n\t\t\t\tcurrentBlock = null;\n\t\t\t} else if (item.type === \"message\" && currentBlock?.type === \"text\") {\n\t\t\t\tcurrentBlock.text =\n\t\t\t\t\titem.content?.map((c) => (c.type === \"output_text\" ? c.text : c.refusal)).join(\"\") || \"\";\n\t\t\t\tcurrentBlock.textSignature = encodeTextSignatureV1(item.id, item.phase ?? undefined);\n\t\t\t\tstream.push({\n\t\t\t\t\ttype: \"text_end\",\n\t\t\t\t\tcontentIndex: blockIndex(),\n\t\t\t\t\tcontent: currentBlock.text,\n\t\t\t\t\tpartial: output,\n\t\t\t\t});\n\t\t\t\tcurrentBlock = null;\n\t\t\t} else if (item.type === \"function_call\") {\n\t\t\t\tconst args =\n\t\t\t\t\tcurrentBlock?.type === \"toolCall\" && currentBlock.partialJson\n\t\t\t\t\t\t? parseStreamingJson(currentBlock.partialJson)\n\t\t\t\t\t\t: parseStreamingJson(item.arguments || \"{}\");\n\n\t\t\t\tlet toolCall: ToolCall;\n\t\t\t\tif (currentBlock?.type === \"toolCall\") {\n\t\t\t\t\t// Finalize in-place and strip the scratch buffer so replay only\n\t\t\t\t\t// carries parsed arguments.\n\t\t\t\t\tcurrentBlock.arguments = args;\n\t\t\t\t\tdelete (currentBlock as { partialJson?: string }).partialJson;\n\t\t\t\t\ttoolCall = currentBlock;\n\t\t\t\t} else {\n\t\t\t\t\ttoolCall = {\n\t\t\t\t\t\ttype: \"toolCall\",\n\t\t\t\t\t\tid: `${item.call_id}|${item.id}`,\n\t\t\t\t\t\tname: item.name,\n\t\t\t\t\t\targuments: args,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tcurrentBlock = null;\n\t\t\t\tstream.push({ type: \"toolcall_end\", contentIndex: blockIndex(), toolCall, partial: output });\n\t\t\t}\n\t\t} else if (event.type === \"response.completed\" || event.type === \"response.incomplete\") {\n\t\t\tfinalizeResponse(event.response);\n\t\t} else if (event.type === \"error\") {\n\t\t\tthrow new Error(`Error Code ${event.code}: ${event.message}` || \"Unknown error\");\n\t\t} else if (event.type === \"response.failed\") {\n\t\t\tsawTerminalResponseEvent = true;\n\t\t\tconst error = event.response?.error;\n\t\t\tconst details = event.response?.incomplete_details;\n\t\t\tconst msg = error\n\t\t\t\t? `${error.code || \"unknown\"}: ${error.message || \"no message\"}`\n\t\t\t\t: details?.reason\n\t\t\t\t\t? `incomplete: ${details.reason}`\n\t\t\t\t\t: \"Unknown error (no error details in response)\";\n\t\t\tthrow new Error(msg);\n\t\t}\n\t}\n\tif (!sawTerminalResponseEvent) {\n\t\tthrow new Error(\"OpenAI Responses stream ended before a terminal response event\");\n\t}\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"]}
|
|
@@ -8,7 +8,6 @@ export interface OpenAIResponsesOptions extends StreamOptions {
|
|
|
8
8
|
/**
|
|
9
9
|
* Generate function for OpenAI Responses API
|
|
10
10
|
*/
|
|
11
|
-
export declare const
|
|
12
|
-
export declare const
|
|
13
|
-
export declare function register(): void;
|
|
11
|
+
export declare const stream: StreamFunction<"openai-responses", OpenAIResponsesOptions>;
|
|
12
|
+
export declare const streamSimple: StreamFunction<"openai-responses", SimpleStreamOptions>;
|
|
14
13
|
//# sourceMappingURL=openai-responses.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-responses.d.ts","sourceRoot":"","sources":["../../src/api/openai-responses.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,yCAAyC,CAAC;AAE7F,OAAO,KAAK,EASX,mBAAmB,EACnB,cAAc,EACd,aAAa,EAEb,MAAM,aAAa,CAAC;AAwErB,MAAM,WAAW,sBAAuB,SAAQ,aAAa;IAC5D,eAAe,CAAC,EAAE,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IAClE,gBAAgB,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,IAAI,CAAC;IAC1D,WAAW,CAAC,EAAE,6BAA6B,CAAC,cAAc,CAAC,CAAC;CAC5D;AAED;;GAEG;AACH,eAAO,MAAM,MAAM,EAAE,cAAc,CAAC,kBAAkB,EAAE,sBAAsB,CA4E7E,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,cAAc,CAAC,kBAAkB,EAAE,mBAAmB,CAehF,CAAC","sourcesContent":["import OpenAI from \"openai\";\nimport type { ResponseCreateParamsStreaming } from \"openai/resources/responses/responses.js\";\nimport { clampThinkingLevel } from \"../models.ts\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tCacheRetention,\n\tContext,\n\tModel,\n\tOpenAIResponsesCompat,\n\tProviderEnv,\n\tProviderHeaders,\n\tSimpleStreamOptions,\n\tStreamFunction,\n\tStreamOptions,\n\tUsage,\n} from \"../types.ts\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.ts\";\nimport { headersToRecord } from \"../utils/headers.ts\";\nimport { getProviderEnvValue } from \"../utils/provider-env.ts\";\nimport { buildCopilotDynamicHeaders, hasCopilotVisionInput } from \"./github-copilot-headers.ts\";\nimport { clampOpenAIPromptCacheKey } from \"./openai-prompt-cache.ts\";\nimport { convertResponsesMessages, convertResponsesTools, processResponsesStream } from \"./openai-responses-shared.ts\";\nimport { buildBaseOptions } from \"./simple-options.ts\";\n\nconst OPENAI_TOOL_CALL_PROVIDERS = new Set([\"openai\", \"openai-codex\", \"opencode\"]);\n\nfunction hasHeader(headers: ProviderHeaders | undefined, name: string): boolean {\n\tif (!headers) return false;\n\tconst expected = name.toLowerCase();\n\tfor (const [key, value] of Object.entries(headers)) {\n\t\tif (key.toLowerCase() === expected && value !== null && value.trim().length > 0) return true;\n\t}\n\treturn false;\n}\n\nfunction getClientApiKey(provider: string, apiKey: string | undefined, headers: ProviderHeaders | undefined): string {\n\tif (apiKey) return apiKey;\n\tif (hasHeader(headers, \"authorization\") || hasHeader(headers, \"cf-aig-authorization\")) return \"unused\";\n\tthrow new Error(`No API key for provider: ${provider}`);\n}\n\n/**\n * Resolve cache retention preference.\n * Defaults to \"short\" and uses PI_CACHE_RETENTION for backward compatibility.\n */\nfunction resolveCacheRetention(cacheRetention?: CacheRetention, env?: ProviderEnv): CacheRetention {\n\tif (cacheRetention) {\n\t\treturn cacheRetention;\n\t}\n\tif (getProviderEnvValue(\"PI_CACHE_RETENTION\", env) === \"long\") {\n\t\treturn \"long\";\n\t}\n\treturn \"short\";\n}\n\nfunction getCompat(model: Model<\"openai-responses\">): Required<OpenAIResponsesCompat> {\n\treturn {\n\t\tsupportsDeveloperRole: model.compat?.supportsDeveloperRole ?? true,\n\t\tsendSessionIdHeader: model.compat?.sendSessionIdHeader ?? true,\n\t\tsupportsLongCacheRetention: model.compat?.supportsLongCacheRetention ?? true,\n\t};\n}\n\nfunction getPromptCacheRetention(\n\tcompat: Required<OpenAIResponsesCompat>,\n\tcacheRetention: CacheRetention,\n): \"24h\" | undefined {\n\treturn cacheRetention === \"long\" && compat.supportsLongCacheRetention ? \"24h\" : undefined;\n}\n\nfunction formatOpenAIResponsesError(error: unknown): string {\n\tif (error instanceof Error) {\n\t\tconst status = (error as Error & { status?: unknown }).status;\n\t\tconst statusCode = typeof status === \"number\" ? status : undefined;\n\t\tif (statusCode !== undefined) {\n\t\t\treturn `OpenAI API error (${statusCode}): ${error.message}`;\n\t\t}\n\t\treturn error.message;\n\t}\n\ttry {\n\t\treturn JSON.stringify(error);\n\t} catch {\n\t\treturn String(error);\n\t}\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 stream: StreamFunction<\"openai-responses\", OpenAIResponsesOptions> = (\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: model.api 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 = getClientApiKey(model.provider, options?.apiKey, options?.headers);\n\t\t\tconst cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);\n\t\t\tconst cacheSessionId = cacheRetention === \"none\" ? undefined : options?.sessionId;\n\t\t\tconst client = createClient(model, context, apiKey, options?.headers, cacheSessionId);\n\t\t\tlet params = buildParams(model, context, options);\n\t\t\tconst nextParams = await options?.onPayload?.(params, model);\n\t\t\tif (nextParams !== undefined) {\n\t\t\t\tparams = nextParams as ResponseCreateParamsStreaming;\n\t\t\t}\n\t\t\tconst requestOptions = {\n\t\t\t\t...(options?.signal ? { signal: options.signal } : {}),\n\t\t\t\t...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),\n\t\t\t\tmaxRetries: options?.maxRetries ?? 0,\n\t\t\t};\n\t\t\tconst { data: openaiStream, response } = await client.responses.create(params, requestOptions).withResponse();\n\t\t\tawait options?.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);\n\t\t\tstream.push({ type: \"start\", partial: output });\n\n\t\t\tawait processResponsesStream(openaiStream, output, stream, model, {\n\t\t\t\tserviceTier: options?.serviceTier,\n\t\t\t\tapplyServiceTierPricing: (usage, serviceTier) => applyServiceTierPricing(usage, serviceTier, model),\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 unknown error occurred\");\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) {\n\t\t\t\tdelete (block as { index?: number }).index;\n\t\t\t\t// partialJson is only a streaming scratch buffer; never persist it.\n\t\t\t\tdelete (block as { partialJson?: string }).partialJson;\n\t\t\t}\n\t\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\t\toutput.errorMessage = formatOpenAIResponsesError(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\nexport const streamSimple: StreamFunction<\"openai-responses\", SimpleStreamOptions> = (\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream => {\n\tgetClientApiKey(model.provider, options?.apiKey, options?.headers);\n\n\tconst base = buildBaseOptions(model, options, options?.apiKey);\n\tconst clampedReasoning = options?.reasoning ? clampThinkingLevel(model, options.reasoning) : undefined;\n\tconst reasoningEffort = clampedReasoning === \"off\" ? undefined : clampedReasoning;\n\n\treturn stream(model, context, {\n\t\t...base,\n\t\treasoningEffort,\n\t} satisfies OpenAIResponsesOptions);\n};\n\nfunction createClient(\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\tapiKey: string,\n\toptionsHeaders?: ProviderHeaders,\n\tsessionId?: string,\n) {\n\tconst compat = getCompat(model);\n\tconst headers: ProviderHeaders = { ...model.headers };\n\tif (model.provider === \"github-copilot\") {\n\t\tconst hasImages = hasCopilotVisionInput(context.messages);\n\t\tconst copilotHeaders = buildCopilotDynamicHeaders({\n\t\t\tmessages: context.messages,\n\t\t\thasImages,\n\t\t});\n\t\tObject.assign(headers, copilotHeaders);\n\t}\n\n\tif (sessionId) {\n\t\tif (compat.sendSessionIdHeader) {\n\t\t\theaders.session_id = sessionId;\n\t\t}\n\t\theaders[\"x-client-request-id\"] = sessionId;\n\t}\n\n\t// Merge options headers last so they can override defaults\n\tif (optionsHeaders) {\n\t\tObject.assign(headers, optionsHeaders);\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 = convertResponsesMessages(model, context, OPENAI_TOOL_CALL_PROVIDERS);\n\n\tconst cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);\n\tconst compat = getCompat(model);\n\tconst params: ResponseCreateParamsStreaming = {\n\t\tmodel: model.id,\n\t\tinput: messages,\n\t\tstream: true,\n\t\tprompt_cache_key: cacheRetention === \"none\" ? undefined : clampOpenAIPromptCacheKey(options?.sessionId),\n\t\tprompt_cache_retention: getPromptCacheRetention(compat, cacheRetention),\n\t\tstore: false,\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 && context.tools.length > 0) {\n\t\tparams.tools = convertResponsesTools(context.tools);\n\t}\n\n\tif (model.reasoning) {\n\t\tif (options?.reasoningEffort || options?.reasoningSummary) {\n\t\t\tconst effort = options?.reasoningEffort\n\t\t\t\t? (model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort)\n\t\t\t\t: \"medium\";\n\t\t\tparams.reasoning = {\n\t\t\t\teffort: effort as NonNullable<typeof params.reasoning>[\"effort\"],\n\t\t\t\tsummary: options?.reasoningSummary || \"auto\",\n\t\t\t};\n\t\t\tparams.include = [\"reasoning.encrypted_content\"];\n\t\t} else if (model.provider !== \"github-copilot\" && model.thinkingLevelMap?.off !== null) {\n\t\t\tparams.reasoning = {\n\t\t\t\teffort: (model.thinkingLevelMap?.off ?? \"none\") as NonNullable<typeof params.reasoning>[\"effort\"],\n\t\t\t};\n\t\t}\n\t}\n\n\treturn params;\n}\n\nfunction getServiceTierCostMultiplier(\n\tmodel: Pick<Model<\"openai-responses\">, \"id\">,\n\tserviceTier: ResponseCreateParamsStreaming[\"service_tier\"] | undefined,\n): number {\n\tswitch (serviceTier) {\n\t\tcase \"flex\":\n\t\t\treturn 0.5;\n\t\tcase \"priority\":\n\t\t\treturn model.id === \"gpt-5.5\" ? 2.5 : 2;\n\t\tdefault:\n\t\t\treturn 1;\n\t}\n}\n\nfunction applyServiceTierPricing(\n\tusage: Usage,\n\tserviceTier: ResponseCreateParamsStreaming[\"service_tier\"] | undefined,\n\tmodel: Pick<Model<\"openai-responses\">, \"id\">,\n) {\n\tconst multiplier = getServiceTierCostMultiplier(model, 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"]}
|
|
@@ -1,15 +1,30 @@
|
|
|
1
1
|
import OpenAI from "openai";
|
|
2
|
-
import { registerApiProvider } from "../api-registry.js";
|
|
3
2
|
import { clampThinkingLevel } from "../models.js";
|
|
4
3
|
import { AssistantMessageEventStream } from "../utils/event-stream.js";
|
|
5
4
|
import { headersToRecord } from "../utils/headers.js";
|
|
6
5
|
import { getProviderEnvValue } from "../utils/provider-env.js";
|
|
7
|
-
import { isCloudflareProvider, resolveCloudflareBaseUrl } from "./cloudflare.js";
|
|
8
6
|
import { buildCopilotDynamicHeaders, hasCopilotVisionInput } from "./github-copilot-headers.js";
|
|
9
7
|
import { clampOpenAIPromptCacheKey } from "./openai-prompt-cache.js";
|
|
10
8
|
import { convertResponsesMessages, convertResponsesTools, processResponsesStream } from "./openai-responses-shared.js";
|
|
11
9
|
import { buildBaseOptions } from "./simple-options.js";
|
|
12
10
|
const OPENAI_TOOL_CALL_PROVIDERS = new Set(["openai", "openai-codex", "opencode"]);
|
|
11
|
+
function hasHeader(headers, name) {
|
|
12
|
+
if (!headers)
|
|
13
|
+
return false;
|
|
14
|
+
const expected = name.toLowerCase();
|
|
15
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
16
|
+
if (key.toLowerCase() === expected && value !== null && value.trim().length > 0)
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
function getClientApiKey(provider, apiKey, headers) {
|
|
22
|
+
if (apiKey)
|
|
23
|
+
return apiKey;
|
|
24
|
+
if (hasHeader(headers, "authorization") || hasHeader(headers, "cf-aig-authorization"))
|
|
25
|
+
return "unused";
|
|
26
|
+
throw new Error(`No API key for provider: ${provider}`);
|
|
27
|
+
}
|
|
13
28
|
/**
|
|
14
29
|
* Resolve cache retention preference.
|
|
15
30
|
* Defaults to "short" and uses PI_CACHE_RETENTION for backward compatibility.
|
|
@@ -52,7 +67,7 @@ function formatOpenAIResponsesError(error) {
|
|
|
52
67
|
/**
|
|
53
68
|
* Generate function for OpenAI Responses API
|
|
54
69
|
*/
|
|
55
|
-
export const
|
|
70
|
+
export const stream = (model, context, options) => {
|
|
56
71
|
const stream = new AssistantMessageEventStream();
|
|
57
72
|
// Start async processing
|
|
58
73
|
(async () => {
|
|
@@ -75,13 +90,10 @@ export const streamOpenAIResponses = (model, context, options) => {
|
|
|
75
90
|
};
|
|
76
91
|
try {
|
|
77
92
|
// Create OpenAI client
|
|
78
|
-
const apiKey = options?.apiKey;
|
|
79
|
-
if (!apiKey) {
|
|
80
|
-
throw new Error(`No API key for provider: ${model.provider}`);
|
|
81
|
-
}
|
|
93
|
+
const apiKey = getClientApiKey(model.provider, options?.apiKey, options?.headers);
|
|
82
94
|
const cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);
|
|
83
95
|
const cacheSessionId = cacheRetention === "none" ? undefined : options?.sessionId;
|
|
84
|
-
const client = createClient(model, context, apiKey, options?.headers, cacheSessionId
|
|
96
|
+
const client = createClient(model, context, apiKey, options?.headers, cacheSessionId);
|
|
85
97
|
let params = buildParams(model, context, options);
|
|
86
98
|
const nextParams = await options?.onPayload?.(params, model);
|
|
87
99
|
if (nextParams !== undefined) {
|
|
@@ -122,27 +134,17 @@ export const streamOpenAIResponses = (model, context, options) => {
|
|
|
122
134
|
})();
|
|
123
135
|
return stream;
|
|
124
136
|
};
|
|
125
|
-
export const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
throw new Error(`No API key for provider: ${model.provider}`);
|
|
129
|
-
}
|
|
130
|
-
const base = buildBaseOptions(model, options, apiKey);
|
|
137
|
+
export const streamSimple = (model, context, options) => {
|
|
138
|
+
getClientApiKey(model.provider, options?.apiKey, options?.headers);
|
|
139
|
+
const base = buildBaseOptions(model, options, options?.apiKey);
|
|
131
140
|
const clampedReasoning = options?.reasoning ? clampThinkingLevel(model, options.reasoning) : undefined;
|
|
132
141
|
const reasoningEffort = clampedReasoning === "off" ? undefined : clampedReasoning;
|
|
133
|
-
return
|
|
142
|
+
return stream(model, context, {
|
|
134
143
|
...base,
|
|
135
144
|
reasoningEffort,
|
|
136
145
|
});
|
|
137
146
|
};
|
|
138
|
-
|
|
139
|
-
registerApiProvider({
|
|
140
|
-
api: "openai-responses",
|
|
141
|
-
stream: streamOpenAIResponses,
|
|
142
|
-
streamSimple: streamSimpleOpenAIResponses,
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
function createClient(model, context, apiKey, optionsHeaders, sessionId, env) {
|
|
147
|
+
function createClient(model, context, apiKey, optionsHeaders, sessionId) {
|
|
146
148
|
const compat = getCompat(model);
|
|
147
149
|
const headers = { ...model.headers };
|
|
148
150
|
if (model.provider === "github-copilot") {
|
|
@@ -163,18 +165,11 @@ function createClient(model, context, apiKey, optionsHeaders, sessionId, env) {
|
|
|
163
165
|
if (optionsHeaders) {
|
|
164
166
|
Object.assign(headers, optionsHeaders);
|
|
165
167
|
}
|
|
166
|
-
const defaultHeaders = model.provider === "cloudflare-ai-gateway"
|
|
167
|
-
? {
|
|
168
|
-
...headers,
|
|
169
|
-
Authorization: headers.Authorization ?? null,
|
|
170
|
-
"cf-aig-authorization": `Bearer ${apiKey}`,
|
|
171
|
-
}
|
|
172
|
-
: headers;
|
|
173
168
|
return new OpenAI({
|
|
174
169
|
apiKey,
|
|
175
|
-
baseURL:
|
|
170
|
+
baseURL: model.baseUrl,
|
|
176
171
|
dangerouslyAllowBrowser: true,
|
|
177
|
-
defaultHeaders,
|
|
172
|
+
defaultHeaders: headers,
|
|
178
173
|
});
|
|
179
174
|
}
|
|
180
175
|
function buildParams(model, context, options) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-responses.js","sourceRoot":"","sources":["../../src/api/openai-responses.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAelD,OAAO,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,0BAA0B,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAChG,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AACvH,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvD,MAAM,0BAA0B,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,cAAc,EAAE,UAAU,CAAC,CAAC,CAAC;AAEnF,SAAS,SAAS,CAAC,OAAoC,EAAE,IAAY,EAAW;IAC/E,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACpC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACpD,IAAI,GAAG,CAAC,WAAW,EAAE,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;IAC9F,CAAC;IACD,OAAO,KAAK,CAAC;AAAA,CACb;AAED,SAAS,eAAe,CAAC,QAAgB,EAAE,MAA0B,EAAE,OAAoC,EAAU;IACpH,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,IAAI,SAAS,CAAC,OAAO,EAAE,eAAe,CAAC,IAAI,SAAS,CAAC,OAAO,EAAE,sBAAsB,CAAC;QAAE,OAAO,QAAQ,CAAC;IACvG,MAAM,IAAI,KAAK,CAAC,4BAA4B,QAAQ,EAAE,CAAC,CAAC;AAAA,CACxD;AAED;;;GAGG;AACH,SAAS,qBAAqB,CAAC,cAA+B,EAAE,GAAiB,EAAkB;IAClG,IAAI,cAAc,EAAE,CAAC;QACpB,OAAO,cAAc,CAAC;IACvB,CAAC;IACD,IAAI,mBAAmB,CAAC,oBAAoB,EAAE,GAAG,CAAC,KAAK,MAAM,EAAE,CAAC;QAC/D,OAAO,MAAM,CAAC;IACf,CAAC;IACD,OAAO,OAAO,CAAC;AAAA,CACf;AAED,SAAS,SAAS,CAAC,KAAgC,EAAmC;IACrF,OAAO;QACN,qBAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,qBAAqB,IAAI,IAAI;QAClE,mBAAmB,EAAE,KAAK,CAAC,MAAM,EAAE,mBAAmB,IAAI,IAAI;QAC9D,0BAA0B,EAAE,KAAK,CAAC,MAAM,EAAE,0BAA0B,IAAI,IAAI;KAC5E,CAAC;AAAA,CACF;AAED,SAAS,uBAAuB,CAC/B,MAAuC,EACvC,cAA8B,EACV;IACpB,OAAO,cAAc,KAAK,MAAM,IAAI,MAAM,CAAC,0BAA0B,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAAA,CAC1F;AAED,SAAS,0BAA0B,CAAC,KAAc,EAAU;IAC3D,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAI,KAAsC,CAAC,MAAM,CAAC;QAC9D,MAAM,UAAU,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;QACnE,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO,qBAAqB,UAAU,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC;QAC7D,CAAC;QACD,OAAO,KAAK,CAAC,OAAO,CAAC;IACtB,CAAC;IACD,IAAI,CAAC;QACJ,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;AAAA,CACD;AASD;;GAEG;AACH,MAAM,CAAC,MAAM,MAAM,GAA+D,CACjF,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,KAAK,CAAC,GAAU;YACrB,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,eAAe,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;YAClF,MAAM,cAAc,GAAG,qBAAqB,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;YACpF,MAAM,cAAc,GAAG,cAAc,KAAK,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,EAAE,SAAS,CAAC;YAClF,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC;YACtF,IAAI,MAAM,GAAG,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;YAClD,MAAM,UAAU,GAAG,MAAM,OAAO,EAAE,SAAS,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAC7D,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;gBAC9B,MAAM,GAAG,UAA2C,CAAC;YACtD,CAAC;YACD,MAAM,cAAc,GAAG;gBACtB,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtD,GAAG,CAAC,OAAO,EAAE,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC3E,UAAU,EAAE,OAAO,EAAE,UAAU,IAAI,CAAC;aACpC,CAAC;YACF,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,YAAY,EAAE,CAAC;YAC9G,MAAM,OAAO,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,eAAe,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YAC5G,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;YAEhD,MAAM,sBAAsB,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE;gBACjE,WAAW,EAAE,OAAO,EAAE,WAAW;gBACjC,uBAAuB,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,CAAC,uBAAuB,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,CAAC;aACnG,CAAC,CAAC;YAEH,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,2BAA2B,CAAC,CAAC;YAC9C,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,EAAE,CAAC;gBACpC,OAAQ,KAA4B,CAAC,KAAK,CAAC;gBAC3C,oEAAoE;gBACpE,OAAQ,KAAkC,CAAC,WAAW,CAAC;YACxD,CAAC;YACD,MAAM,CAAC,UAAU,GAAG,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;YACnE,MAAM,CAAC,YAAY,GAAG,0BAA0B,CAAC,KAAK,CAAC,CAAC;YACxD,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,MAAM,CAAC,MAAM,YAAY,GAA4D,CACpF,KAAgC,EAChC,OAAgB,EAChB,OAA6B,EACC,EAAE,CAAC;IACjC,eAAe,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAEnE,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC/D,MAAM,gBAAgB,GAAG,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACvG,MAAM,eAAe,GAAG,gBAAgB,KAAK,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC;IAElF,OAAO,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE;QAC7B,GAAG,IAAI;QACP,eAAe;KACkB,CAAC,CAAC;AAAA,CACpC,CAAC;AAEF,SAAS,YAAY,CACpB,KAAgC,EAChC,OAAgB,EAChB,MAAc,EACd,cAAgC,EAChC,SAAkB,EACjB;IACD,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAChC,MAAM,OAAO,GAAoB,EAAE,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC;IACtD,IAAI,KAAK,CAAC,QAAQ,KAAK,gBAAgB,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,qBAAqB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC1D,MAAM,cAAc,GAAG,0BAA0B,CAAC;YACjD,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,SAAS;SACT,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IACxC,CAAC;IAED,IAAI,SAAS,EAAE,CAAC;QACf,IAAI,MAAM,CAAC,mBAAmB,EAAE,CAAC;YAChC,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;QAChC,CAAC;QACD,OAAO,CAAC,qBAAqB,CAAC,GAAG,SAAS,CAAC;IAC5C,CAAC;IAED,2DAA2D;IAC3D,IAAI,cAAc,EAAE,CAAC;QACpB,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IACxC,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,wBAAwB,CAAC,KAAK,EAAE,OAAO,EAAE,0BAA0B,CAAC,CAAC;IAEtF,MAAM,cAAc,GAAG,qBAAqB,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;IACpF,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAChC,MAAM,MAAM,GAAkC;QAC7C,KAAK,EAAE,KAAK,CAAC,EAAE;QACf,KAAK,EAAE,QAAQ;QACf,MAAM,EAAE,IAAI;QACZ,gBAAgB,EAAE,cAAc,KAAK,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,yBAAyB,CAAC,OAAO,EAAE,SAAS,CAAC;QACvG,sBAAsB,EAAE,uBAAuB,CAAC,MAAM,EAAE,cAAc,CAAC;QACvE,KAAK,EAAE,KAAK;KACZ,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,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/C,MAAM,CAAC,KAAK,GAAG,qBAAqB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QACrB,IAAI,OAAO,EAAE,eAAe,IAAI,OAAO,EAAE,gBAAgB,EAAE,CAAC;YAC3D,MAAM,MAAM,GAAG,OAAO,EAAE,eAAe;gBACtC,CAAC,CAAC,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,OAAO,CAAC,eAAe,CAAC;gBAChF,CAAC,CAAC,QAAQ,CAAC;YACZ,MAAM,CAAC,SAAS,GAAG;gBAClB,MAAM,EAAE,MAAwD;gBAChE,OAAO,EAAE,OAAO,EAAE,gBAAgB,IAAI,MAAM;aAC5C,CAAC;YACF,MAAM,CAAC,OAAO,GAAG,CAAC,6BAA6B,CAAC,CAAC;QAClD,CAAC;aAAM,IAAI,KAAK,CAAC,QAAQ,KAAK,gBAAgB,IAAI,KAAK,CAAC,gBAAgB,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC;YACxF,MAAM,CAAC,SAAS,GAAG;gBAClB,MAAM,EAAE,CAAC,KAAK,CAAC,gBAAgB,EAAE,GAAG,IAAI,MAAM,CAAmD;aACjG,CAAC;QACH,CAAC;IACF,CAAC;IAED,OAAO,MAAM,CAAC;AAAA,CACd;AAED,SAAS,4BAA4B,CACpC,KAA4C,EAC5C,WAAsE,EAC7D;IACT,QAAQ,WAAW,EAAE,CAAC;QACrB,KAAK,MAAM;YACV,OAAO,GAAG,CAAC;QACZ,KAAK,UAAU;YACd,OAAO,KAAK,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACzC;YACC,OAAO,CAAC,CAAC;IACX,CAAC;AAAA,CACD;AAED,SAAS,uBAAuB,CAC/B,KAAY,EACZ,WAAsE,EACtE,KAA4C,EAC3C;IACD,MAAM,UAAU,GAAG,4BAA4B,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IACpE,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","sourcesContent":["import OpenAI from \"openai\";\nimport type { ResponseCreateParamsStreaming } from \"openai/resources/responses/responses.js\";\nimport { clampThinkingLevel } from \"../models.ts\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tCacheRetention,\n\tContext,\n\tModel,\n\tOpenAIResponsesCompat,\n\tProviderEnv,\n\tProviderHeaders,\n\tSimpleStreamOptions,\n\tStreamFunction,\n\tStreamOptions,\n\tUsage,\n} from \"../types.ts\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.ts\";\nimport { headersToRecord } from \"../utils/headers.ts\";\nimport { getProviderEnvValue } from \"../utils/provider-env.ts\";\nimport { buildCopilotDynamicHeaders, hasCopilotVisionInput } from \"./github-copilot-headers.ts\";\nimport { clampOpenAIPromptCacheKey } from \"./openai-prompt-cache.ts\";\nimport { convertResponsesMessages, convertResponsesTools, processResponsesStream } from \"./openai-responses-shared.ts\";\nimport { buildBaseOptions } from \"./simple-options.ts\";\n\nconst OPENAI_TOOL_CALL_PROVIDERS = new Set([\"openai\", \"openai-codex\", \"opencode\"]);\n\nfunction hasHeader(headers: ProviderHeaders | undefined, name: string): boolean {\n\tif (!headers) return false;\n\tconst expected = name.toLowerCase();\n\tfor (const [key, value] of Object.entries(headers)) {\n\t\tif (key.toLowerCase() === expected && value !== null && value.trim().length > 0) return true;\n\t}\n\treturn false;\n}\n\nfunction getClientApiKey(provider: string, apiKey: string | undefined, headers: ProviderHeaders | undefined): string {\n\tif (apiKey) return apiKey;\n\tif (hasHeader(headers, \"authorization\") || hasHeader(headers, \"cf-aig-authorization\")) return \"unused\";\n\tthrow new Error(`No API key for provider: ${provider}`);\n}\n\n/**\n * Resolve cache retention preference.\n * Defaults to \"short\" and uses PI_CACHE_RETENTION for backward compatibility.\n */\nfunction resolveCacheRetention(cacheRetention?: CacheRetention, env?: ProviderEnv): CacheRetention {\n\tif (cacheRetention) {\n\t\treturn cacheRetention;\n\t}\n\tif (getProviderEnvValue(\"PI_CACHE_RETENTION\", env) === \"long\") {\n\t\treturn \"long\";\n\t}\n\treturn \"short\";\n}\n\nfunction getCompat(model: Model<\"openai-responses\">): Required<OpenAIResponsesCompat> {\n\treturn {\n\t\tsupportsDeveloperRole: model.compat?.supportsDeveloperRole ?? true,\n\t\tsendSessionIdHeader: model.compat?.sendSessionIdHeader ?? true,\n\t\tsupportsLongCacheRetention: model.compat?.supportsLongCacheRetention ?? true,\n\t};\n}\n\nfunction getPromptCacheRetention(\n\tcompat: Required<OpenAIResponsesCompat>,\n\tcacheRetention: CacheRetention,\n): \"24h\" | undefined {\n\treturn cacheRetention === \"long\" && compat.supportsLongCacheRetention ? \"24h\" : undefined;\n}\n\nfunction formatOpenAIResponsesError(error: unknown): string {\n\tif (error instanceof Error) {\n\t\tconst status = (error as Error & { status?: unknown }).status;\n\t\tconst statusCode = typeof status === \"number\" ? status : undefined;\n\t\tif (statusCode !== undefined) {\n\t\t\treturn `OpenAI API error (${statusCode}): ${error.message}`;\n\t\t}\n\t\treturn error.message;\n\t}\n\ttry {\n\t\treturn JSON.stringify(error);\n\t} catch {\n\t\treturn String(error);\n\t}\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 stream: StreamFunction<\"openai-responses\", OpenAIResponsesOptions> = (\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: model.api 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 = getClientApiKey(model.provider, options?.apiKey, options?.headers);\n\t\t\tconst cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);\n\t\t\tconst cacheSessionId = cacheRetention === \"none\" ? undefined : options?.sessionId;\n\t\t\tconst client = createClient(model, context, apiKey, options?.headers, cacheSessionId);\n\t\t\tlet params = buildParams(model, context, options);\n\t\t\tconst nextParams = await options?.onPayload?.(params, model);\n\t\t\tif (nextParams !== undefined) {\n\t\t\t\tparams = nextParams as ResponseCreateParamsStreaming;\n\t\t\t}\n\t\t\tconst requestOptions = {\n\t\t\t\t...(options?.signal ? { signal: options.signal } : {}),\n\t\t\t\t...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),\n\t\t\t\tmaxRetries: options?.maxRetries ?? 0,\n\t\t\t};\n\t\t\tconst { data: openaiStream, response } = await client.responses.create(params, requestOptions).withResponse();\n\t\t\tawait options?.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);\n\t\t\tstream.push({ type: \"start\", partial: output });\n\n\t\t\tawait processResponsesStream(openaiStream, output, stream, model, {\n\t\t\t\tserviceTier: options?.serviceTier,\n\t\t\t\tapplyServiceTierPricing: (usage, serviceTier) => applyServiceTierPricing(usage, serviceTier, model),\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 unknown error occurred\");\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) {\n\t\t\t\tdelete (block as { index?: number }).index;\n\t\t\t\t// partialJson is only a streaming scratch buffer; never persist it.\n\t\t\t\tdelete (block as { partialJson?: string }).partialJson;\n\t\t\t}\n\t\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\t\toutput.errorMessage = formatOpenAIResponsesError(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\nexport const streamSimple: StreamFunction<\"openai-responses\", SimpleStreamOptions> = (\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream => {\n\tgetClientApiKey(model.provider, options?.apiKey, options?.headers);\n\n\tconst base = buildBaseOptions(model, options, options?.apiKey);\n\tconst clampedReasoning = options?.reasoning ? clampThinkingLevel(model, options.reasoning) : undefined;\n\tconst reasoningEffort = clampedReasoning === \"off\" ? undefined : clampedReasoning;\n\n\treturn stream(model, context, {\n\t\t...base,\n\t\treasoningEffort,\n\t} satisfies OpenAIResponsesOptions);\n};\n\nfunction createClient(\n\tmodel: Model<\"openai-responses\">,\n\tcontext: Context,\n\tapiKey: string,\n\toptionsHeaders?: ProviderHeaders,\n\tsessionId?: string,\n) {\n\tconst compat = getCompat(model);\n\tconst headers: ProviderHeaders = { ...model.headers };\n\tif (model.provider === \"github-copilot\") {\n\t\tconst hasImages = hasCopilotVisionInput(context.messages);\n\t\tconst copilotHeaders = buildCopilotDynamicHeaders({\n\t\t\tmessages: context.messages,\n\t\t\thasImages,\n\t\t});\n\t\tObject.assign(headers, copilotHeaders);\n\t}\n\n\tif (sessionId) {\n\t\tif (compat.sendSessionIdHeader) {\n\t\t\theaders.session_id = sessionId;\n\t\t}\n\t\theaders[\"x-client-request-id\"] = sessionId;\n\t}\n\n\t// Merge options headers last so they can override defaults\n\tif (optionsHeaders) {\n\t\tObject.assign(headers, optionsHeaders);\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 = convertResponsesMessages(model, context, OPENAI_TOOL_CALL_PROVIDERS);\n\n\tconst cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);\n\tconst compat = getCompat(model);\n\tconst params: ResponseCreateParamsStreaming = {\n\t\tmodel: model.id,\n\t\tinput: messages,\n\t\tstream: true,\n\t\tprompt_cache_key: cacheRetention === \"none\" ? undefined : clampOpenAIPromptCacheKey(options?.sessionId),\n\t\tprompt_cache_retention: getPromptCacheRetention(compat, cacheRetention),\n\t\tstore: false,\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 && context.tools.length > 0) {\n\t\tparams.tools = convertResponsesTools(context.tools);\n\t}\n\n\tif (model.reasoning) {\n\t\tif (options?.reasoningEffort || options?.reasoningSummary) {\n\t\t\tconst effort = options?.reasoningEffort\n\t\t\t\t? (model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort)\n\t\t\t\t: \"medium\";\n\t\t\tparams.reasoning = {\n\t\t\t\teffort: effort as NonNullable<typeof params.reasoning>[\"effort\"],\n\t\t\t\tsummary: options?.reasoningSummary || \"auto\",\n\t\t\t};\n\t\t\tparams.include = [\"reasoning.encrypted_content\"];\n\t\t} else if (model.provider !== \"github-copilot\" && model.thinkingLevelMap?.off !== null) {\n\t\t\tparams.reasoning = {\n\t\t\t\teffort: (model.thinkingLevelMap?.off ?? \"none\") as NonNullable<typeof params.reasoning>[\"effort\"],\n\t\t\t};\n\t\t}\n\t}\n\n\treturn params;\n}\n\nfunction getServiceTierCostMultiplier(\n\tmodel: Pick<Model<\"openai-responses\">, \"id\">,\n\tserviceTier: ResponseCreateParamsStreaming[\"service_tier\"] | undefined,\n): number {\n\tswitch (serviceTier) {\n\t\tcase \"flex\":\n\t\t\treturn 0.5;\n\t\tcase \"priority\":\n\t\t\treturn model.id === \"gpt-5.5\" ? 2.5 : 2;\n\t\tdefault:\n\t\t\treturn 1;\n\t}\n}\n\nfunction applyServiceTierPricing(\n\tusage: Usage,\n\tserviceTier: ResponseCreateParamsStreaming[\"service_tier\"] | undefined,\n\tmodel: Pick<Model<\"openai-responses\">, \"id\">,\n) {\n\tconst multiplier = getServiceTierCostMultiplier(model, 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"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-responses.lazy.d.ts","sourceRoot":"","sources":["../../src/api/openai-responses.lazy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGnD,eAAO,MAAM,kBAAkB,uBAAwE,CAAC","sourcesContent":["import type { ProviderStreams } from \"../types.ts\";\nimport { lazyApi } from \"./lazy.ts\";\n\nexport const openAIResponsesApi = (): ProviderStreams => lazyApi(() => import(\"./openai-responses.ts\"));\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-responses.lazy.js","sourceRoot":"","sources":["../../src/api/openai-responses.lazy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAoB,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAC,CAAC","sourcesContent":["import type { ProviderStreams } from \"../types.ts\";\nimport { lazyApi } from \"./lazy.ts\";\n\nexport const openAIResponsesApi = (): ProviderStreams => lazyApi(() => import(\"./openai-responses.ts\"));\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openrouter-images.d.ts","sourceRoot":"","sources":["../../src/api/openrouter-images.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAIX,cAAc,EAEd,aAAa,EAGb,MAAM,aAAa,CAAC;AAoBrB,eAAO,MAAM,cAAc,EAAE,cAAc,CAAC,mBAAmB,EAAE,aAAa,CAmE7E,CAAC","sourcesContent":["import OpenAI from \"openai\";\nimport type {\n\tChatCompletion,\n\tChatCompletionContentPart,\n\tChatCompletionContentPartImage,\n\tChatCompletionContentPartText,\n\tChatCompletionCreateParamsNonStreaming,\n} from \"openai/resources/chat/completions.js\";\nimport type {\n\tAssistantImages,\n\tImageContent,\n\tImagesContext,\n\tImagesFunction,\n\tImagesModel,\n\tImagesOptions,\n\tProviderHeaders,\n\tTextContent,\n} from \"../types.ts\";\nimport { headersToRecord, providerHeadersToRecord } from \"../utils/headers.ts\";\nimport { sanitizeSurrogates } from \"../utils/sanitize-unicode.ts\";\n\ninterface OpenRouterGeneratedImage {\n\timage_url?: string | { url?: string };\n}\n\ntype OpenRouterImageGenerationMessage = ChatCompletion[\"choices\"][number][\"message\"] & {\n\timages?: OpenRouterGeneratedImage[];\n};\n\ntype OpenRouterImageGenerationChoice = ChatCompletion[\"choices\"][number] & {\n\tmessage: OpenRouterImageGenerationMessage;\n};\n\ntype OpenRouterImageGenerationResponse = ChatCompletion & {\n\tchoices: OpenRouterImageGenerationChoice[];\n};\n\nexport const generateImages: ImagesFunction<\"openrouter-images\", ImagesOptions> = async (\n\tmodel: ImagesModel<\"openrouter-images\">,\n\tcontext: ImagesContext,\n\toptions?: ImagesOptions,\n) => {\n\tconst output: AssistantImages = {\n\t\tapi: model.api,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\toutput: [],\n\t\tstopReason: \"stop\",\n\t\ttimestamp: Date.now(),\n\t};\n\n\ttry {\n\t\tconst apiKey = options?.apiKey;\n\t\tif (!apiKey) {\n\t\t\tthrow new Error(`No API key for provider: ${model.provider}`);\n\t\t}\n\t\tconst client = createClient(model, apiKey, options?.headers);\n\t\tlet params = buildParams(model, context);\n\t\tconst nextParams = await options?.onPayload?.(params, model);\n\t\tif (nextParams !== undefined) {\n\t\t\tparams = nextParams as typeof params;\n\t\t}\n\t\tconst requestOptions = {\n\t\t\t...(options?.signal ? { signal: options.signal } : {}),\n\t\t\t...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),\n\t\t\tmaxRetries: options?.maxRetries ?? 0,\n\t\t};\n\t\tconst { data: response, response: rawResponse } = await client.chat.completions\n\t\t\t.create(params as unknown as ChatCompletionCreateParamsNonStreaming, requestOptions)\n\t\t\t.withResponse();\n\t\tawait options?.onResponse?.({ status: rawResponse.status, headers: headersToRecord(rawResponse.headers) }, model);\n\n\t\tconst imageResponse = response as OpenRouterImageGenerationResponse;\n\t\toutput.responseId = imageResponse.id;\n\t\tif (imageResponse.usage) {\n\t\t\toutput.usage = parseUsage(imageResponse.usage, model);\n\t\t}\n\n\t\tconst choice = imageResponse.choices[0];\n\t\tif (choice) {\n\t\t\tconst content = choice.message.content;\n\t\t\tif (typeof content === \"string\" && content.length > 0) {\n\t\t\t\toutput.output.push({ type: \"text\", text: content } satisfies TextContent);\n\t\t\t}\n\n\t\t\tfor (const image of choice.message.images ?? []) {\n\t\t\t\tconst imageUrl = typeof image.image_url === \"string\" ? image.image_url : image.image_url?.url;\n\t\t\t\tif (!imageUrl?.startsWith(\"data:\")) continue;\n\t\t\t\tconst matches = imageUrl.match(/^data:([^;]+);base64,(.+)$/);\n\t\t\t\tif (!matches) continue;\n\t\t\t\toutput.output.push({\n\t\t\t\t\ttype: \"image\",\n\t\t\t\t\tmimeType: matches[1],\n\t\t\t\t\tdata: matches[2],\n\t\t\t\t} satisfies ImageContent);\n\t\t\t}\n\t\t}\n\n\t\treturn output;\n\t} catch (error) {\n\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\toutput.errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n\t\treturn output;\n\t}\n};\n\nfunction createClient(\n\tmodel: ImagesModel<\"openrouter-images\">,\n\tapiKey: string,\n\toptionsHeaders?: ProviderHeaders,\n): OpenAI {\n\treturn new OpenAI({\n\t\tapiKey,\n\t\tbaseURL: model.baseUrl,\n\t\tdangerouslyAllowBrowser: true,\n\t\tdefaultHeaders: providerHeadersToRecord({ ...model.headers, ...optionsHeaders }),\n\t});\n}\n\ntype OpenRouterImagesCreateParams = Omit<ChatCompletionCreateParamsNonStreaming, \"modalities\"> & {\n\tmodalities: Array<\"image\" | \"text\">;\n};\n\nfunction buildParams(model: ImagesModel<\"openrouter-images\">, context: ImagesContext): OpenRouterImagesCreateParams {\n\tconst content: ChatCompletionContentPart[] = context.input.map((item): ChatCompletionContentPart => {\n\t\tif (item.type === \"text\") {\n\t\t\treturn {\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: sanitizeSurrogates(item.text),\n\t\t\t} satisfies ChatCompletionContentPartText;\n\t\t}\n\t\treturn {\n\t\t\ttype: \"image_url\",\n\t\t\timage_url: {\n\t\t\t\turl: `data:${item.mimeType};base64,${item.data}`,\n\t\t\t},\n\t\t} satisfies ChatCompletionContentPartImage;\n\t});\n\n\treturn {\n\t\tmodel: model.id,\n\t\tmessages: [\n\t\t\t{\n\t\t\t\trole: \"user\" as const,\n\t\t\t\tcontent,\n\t\t\t},\n\t\t],\n\t\tstream: false,\n\t\tmodalities: model.output.includes(\"text\") ? [\"image\", \"text\"] : [\"image\"],\n\t};\n}\n\nfunction parseUsage(\n\trawUsage: {\n\t\tprompt_tokens?: number;\n\t\tcompletion_tokens?: number;\n\t\tprompt_tokens_details?: { cached_tokens?: number; cache_write_tokens?: number };\n\t},\n\tmodel: ImagesModel<\"openrouter-images\">,\n) {\n\tconst promptTokens = rawUsage.prompt_tokens || 0;\n\tconst reportedCachedTokens = rawUsage.prompt_tokens_details?.cached_tokens || 0;\n\tconst cacheWriteTokens = rawUsage.prompt_tokens_details?.cache_write_tokens || 0;\n\tconst cacheReadTokens =\n\t\tcacheWriteTokens > 0 ? Math.max(0, reportedCachedTokens - cacheWriteTokens) : reportedCachedTokens;\n\tconst input = Math.max(0, promptTokens - cacheReadTokens - cacheWriteTokens);\n\tconst output = rawUsage.completion_tokens || 0;\n\tconst usage = {\n\t\tinput,\n\t\toutput,\n\t\tcacheRead: cacheReadTokens,\n\t\tcacheWrite: cacheWriteTokens,\n\t\ttotalTokens: input + output + cacheReadTokens + cacheWriteTokens,\n\t\tcost: {\n\t\t\tinput: (model.cost.input / 1000000) * input,\n\t\t\toutput: (model.cost.output / 1000000) * output,\n\t\t\tcacheRead: (model.cost.cacheRead / 1000000) * cacheReadTokens,\n\t\t\tcacheWrite: (model.cost.cacheWrite / 1000000) * cacheWriteTokens,\n\t\t\ttotal: 0,\n\t\t},\n\t};\n\tusage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;\n\treturn usage;\n}\n"]}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import OpenAI from "openai";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
export const generateImagesOpenRouter = async (model, context, options) => {
|
|
2
|
+
import { headersToRecord, providerHeadersToRecord } from "../utils/headers.js";
|
|
3
|
+
import { sanitizeSurrogates } from "../utils/sanitize-unicode.js";
|
|
4
|
+
export const generateImages = async (model, context, options) => {
|
|
6
5
|
const output = {
|
|
7
6
|
api: model.api,
|
|
8
7
|
provider: model.provider,
|
|
@@ -64,21 +63,12 @@ export const generateImagesOpenRouter = async (model, context, options) => {
|
|
|
64
63
|
return output;
|
|
65
64
|
}
|
|
66
65
|
};
|
|
67
|
-
export function register() {
|
|
68
|
-
registerImagesApiProvider({
|
|
69
|
-
api: "openrouter-images",
|
|
70
|
-
generateImages: generateImagesOpenRouter,
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
66
|
function createClient(model, apiKey, optionsHeaders) {
|
|
74
67
|
return new OpenAI({
|
|
75
68
|
apiKey,
|
|
76
69
|
baseURL: model.baseUrl,
|
|
77
70
|
dangerouslyAllowBrowser: true,
|
|
78
|
-
defaultHeaders: {
|
|
79
|
-
...model.headers,
|
|
80
|
-
...optionsHeaders,
|
|
81
|
-
},
|
|
71
|
+
defaultHeaders: providerHeadersToRecord({ ...model.headers, ...optionsHeaders }),
|
|
82
72
|
});
|
|
83
73
|
}
|
|
84
74
|
function buildParams(model, context) {
|
|
@@ -132,4 +122,4 @@ function parseUsage(rawUsage, model) {
|
|
|
132
122
|
usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
|
|
133
123
|
return usage;
|
|
134
124
|
}
|
|
135
|
-
//# sourceMappingURL=openrouter.js.map
|
|
125
|
+
//# sourceMappingURL=openrouter-images.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openrouter-images.js","sourceRoot":"","sources":["../../src/api/openrouter-images.ts"],"names":[],"mappings":"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","sourcesContent":["import OpenAI from \"openai\";\nimport type {\n\tChatCompletion,\n\tChatCompletionContentPart,\n\tChatCompletionContentPartImage,\n\tChatCompletionContentPartText,\n\tChatCompletionCreateParamsNonStreaming,\n} from \"openai/resources/chat/completions.js\";\nimport type {\n\tAssistantImages,\n\tImageContent,\n\tImagesContext,\n\tImagesFunction,\n\tImagesModel,\n\tImagesOptions,\n\tProviderHeaders,\n\tTextContent,\n} from \"../types.ts\";\nimport { headersToRecord, providerHeadersToRecord } from \"../utils/headers.ts\";\nimport { sanitizeSurrogates } from \"../utils/sanitize-unicode.ts\";\n\ninterface OpenRouterGeneratedImage {\n\timage_url?: string | { url?: string };\n}\n\ntype OpenRouterImageGenerationMessage = ChatCompletion[\"choices\"][number][\"message\"] & {\n\timages?: OpenRouterGeneratedImage[];\n};\n\ntype OpenRouterImageGenerationChoice = ChatCompletion[\"choices\"][number] & {\n\tmessage: OpenRouterImageGenerationMessage;\n};\n\ntype OpenRouterImageGenerationResponse = ChatCompletion & {\n\tchoices: OpenRouterImageGenerationChoice[];\n};\n\nexport const generateImages: ImagesFunction<\"openrouter-images\", ImagesOptions> = async (\n\tmodel: ImagesModel<\"openrouter-images\">,\n\tcontext: ImagesContext,\n\toptions?: ImagesOptions,\n) => {\n\tconst output: AssistantImages = {\n\t\tapi: model.api,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\toutput: [],\n\t\tstopReason: \"stop\",\n\t\ttimestamp: Date.now(),\n\t};\n\n\ttry {\n\t\tconst apiKey = options?.apiKey;\n\t\tif (!apiKey) {\n\t\t\tthrow new Error(`No API key for provider: ${model.provider}`);\n\t\t}\n\t\tconst client = createClient(model, apiKey, options?.headers);\n\t\tlet params = buildParams(model, context);\n\t\tconst nextParams = await options?.onPayload?.(params, model);\n\t\tif (nextParams !== undefined) {\n\t\t\tparams = nextParams as typeof params;\n\t\t}\n\t\tconst requestOptions = {\n\t\t\t...(options?.signal ? { signal: options.signal } : {}),\n\t\t\t...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),\n\t\t\tmaxRetries: options?.maxRetries ?? 0,\n\t\t};\n\t\tconst { data: response, response: rawResponse } = await client.chat.completions\n\t\t\t.create(params as unknown as ChatCompletionCreateParamsNonStreaming, requestOptions)\n\t\t\t.withResponse();\n\t\tawait options?.onResponse?.({ status: rawResponse.status, headers: headersToRecord(rawResponse.headers) }, model);\n\n\t\tconst imageResponse = response as OpenRouterImageGenerationResponse;\n\t\toutput.responseId = imageResponse.id;\n\t\tif (imageResponse.usage) {\n\t\t\toutput.usage = parseUsage(imageResponse.usage, model);\n\t\t}\n\n\t\tconst choice = imageResponse.choices[0];\n\t\tif (choice) {\n\t\t\tconst content = choice.message.content;\n\t\t\tif (typeof content === \"string\" && content.length > 0) {\n\t\t\t\toutput.output.push({ type: \"text\", text: content } satisfies TextContent);\n\t\t\t}\n\n\t\t\tfor (const image of choice.message.images ?? []) {\n\t\t\t\tconst imageUrl = typeof image.image_url === \"string\" ? image.image_url : image.image_url?.url;\n\t\t\t\tif (!imageUrl?.startsWith(\"data:\")) continue;\n\t\t\t\tconst matches = imageUrl.match(/^data:([^;]+);base64,(.+)$/);\n\t\t\t\tif (!matches) continue;\n\t\t\t\toutput.output.push({\n\t\t\t\t\ttype: \"image\",\n\t\t\t\t\tmimeType: matches[1],\n\t\t\t\t\tdata: matches[2],\n\t\t\t\t} satisfies ImageContent);\n\t\t\t}\n\t\t}\n\n\t\treturn output;\n\t} catch (error) {\n\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\toutput.errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n\t\treturn output;\n\t}\n};\n\nfunction createClient(\n\tmodel: ImagesModel<\"openrouter-images\">,\n\tapiKey: string,\n\toptionsHeaders?: ProviderHeaders,\n): OpenAI {\n\treturn new OpenAI({\n\t\tapiKey,\n\t\tbaseURL: model.baseUrl,\n\t\tdangerouslyAllowBrowser: true,\n\t\tdefaultHeaders: providerHeadersToRecord({ ...model.headers, ...optionsHeaders }),\n\t});\n}\n\ntype OpenRouterImagesCreateParams = Omit<ChatCompletionCreateParamsNonStreaming, \"modalities\"> & {\n\tmodalities: Array<\"image\" | \"text\">;\n};\n\nfunction buildParams(model: ImagesModel<\"openrouter-images\">, context: ImagesContext): OpenRouterImagesCreateParams {\n\tconst content: ChatCompletionContentPart[] = context.input.map((item): ChatCompletionContentPart => {\n\t\tif (item.type === \"text\") {\n\t\t\treturn {\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: sanitizeSurrogates(item.text),\n\t\t\t} satisfies ChatCompletionContentPartText;\n\t\t}\n\t\treturn {\n\t\t\ttype: \"image_url\",\n\t\t\timage_url: {\n\t\t\t\turl: `data:${item.mimeType};base64,${item.data}`,\n\t\t\t},\n\t\t} satisfies ChatCompletionContentPartImage;\n\t});\n\n\treturn {\n\t\tmodel: model.id,\n\t\tmessages: [\n\t\t\t{\n\t\t\t\trole: \"user\" as const,\n\t\t\t\tcontent,\n\t\t\t},\n\t\t],\n\t\tstream: false,\n\t\tmodalities: model.output.includes(\"text\") ? [\"image\", \"text\"] : [\"image\"],\n\t};\n}\n\nfunction parseUsage(\n\trawUsage: {\n\t\tprompt_tokens?: number;\n\t\tcompletion_tokens?: number;\n\t\tprompt_tokens_details?: { cached_tokens?: number; cache_write_tokens?: number };\n\t},\n\tmodel: ImagesModel<\"openrouter-images\">,\n) {\n\tconst promptTokens = rawUsage.prompt_tokens || 0;\n\tconst reportedCachedTokens = rawUsage.prompt_tokens_details?.cached_tokens || 0;\n\tconst cacheWriteTokens = rawUsage.prompt_tokens_details?.cache_write_tokens || 0;\n\tconst cacheReadTokens =\n\t\tcacheWriteTokens > 0 ? Math.max(0, reportedCachedTokens - cacheWriteTokens) : reportedCachedTokens;\n\tconst input = Math.max(0, promptTokens - cacheReadTokens - cacheWriteTokens);\n\tconst output = rawUsage.completion_tokens || 0;\n\tconst usage = {\n\t\tinput,\n\t\toutput,\n\t\tcacheRead: cacheReadTokens,\n\t\tcacheWrite: cacheWriteTokens,\n\t\ttotalTokens: input + output + cacheReadTokens + cacheWriteTokens,\n\t\tcost: {\n\t\t\tinput: (model.cost.input / 1000000) * input,\n\t\t\toutput: (model.cost.output / 1000000) * output,\n\t\t\tcacheRead: (model.cost.cacheRead / 1000000) * cacheReadTokens,\n\t\t\tcacheWrite: (model.cost.cacheWrite / 1000000) * cacheWriteTokens,\n\t\t\ttotal: 0,\n\t\t},\n\t};\n\tusage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;\n\treturn usage;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openrouter-images.lazy.d.ts","sourceRoot":"","sources":["../../src/api/openrouter-images.lazy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,cAAc,EAAE,MAAM,aAAa,CAAC;AAE/D,eAAO,MAAM,mBAAmB,sBAO9B,CAAC","sourcesContent":["import type { ImagesModel, ProviderImages } from \"../types.ts\";\n\nexport const openrouterImagesApi = (): ProviderImages => ({\n\tgenerateImages: async (model, context, options) =>\n\t\t(await import(\"./openrouter-images.ts\")).generateImages(\n\t\t\tmodel as ImagesModel<\"openrouter-images\">,\n\t\t\tcontext,\n\t\t\toptions,\n\t\t),\n});\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openrouter-images.lazy.js","sourceRoot":"","sources":["../../src/api/openrouter-images.lazy.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAmB,EAAE,CAAC,CAAC;IACzD,cAAc,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,CACjD,CAAC,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAC,CAAC,cAAc,CACtD,KAAyC,EACzC,OAAO,EACP,OAAO,CACP;CACF,CAAC,CAAC","sourcesContent":["import type { ImagesModel, ProviderImages } from \"../types.ts\";\n\nexport const openrouterImagesApi = (): ProviderImages => ({\n\tgenerateImages: async (model, context, options) =>\n\t\t(await import(\"./openrouter-images.ts\")).generateImages(\n\t\t\tmodel as ImagesModel<\"openrouter-images\">,\n\t\t\tcontext,\n\t\t\toptions,\n\t\t),\n});\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"simple-options.d.ts","sourceRoot":"","sources":["../../src/api/simple-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,mBAAmB,EAAE,aAAa,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAElH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,EAAE,mBAAmB,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,aAAa,CAmBlH;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,SAAS,GAAG,OAAO,CAAC,aAAa,EAAE,OAAO,CAAC,GAAG,SAAS,CAE7G;AAED,wBAAgB,0BAA0B,CAEzC,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,cAAc,EAAE,MAAM,EACtB,cAAc,EAAE,aAAa,EAC7B,aAAa,CAAC,EAAE,eAAe,GAC7B;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CAoB/C","sourcesContent":["import type { Api, Model, SimpleStreamOptions, StreamOptions, ThinkingBudgets, ThinkingLevel } from \"../types.ts\";\n\nexport function buildBaseOptions(_model: Model<Api>, options?: SimpleStreamOptions, apiKey?: string): StreamOptions {\n\treturn {\n\t\ttemperature: options?.temperature,\n\t\tmaxTokens: options?.maxTokens,\n\t\tsignal: options?.signal,\n\t\tapiKey: apiKey || options?.apiKey,\n\t\ttransport: options?.transport,\n\t\tcacheRetention: options?.cacheRetention,\n\t\tsessionId: options?.sessionId,\n\t\theaders: options?.headers,\n\t\tonPayload: options?.onPayload,\n\t\tonResponse: options?.onResponse,\n\t\ttimeoutMs: options?.timeoutMs,\n\t\twebsocketConnectTimeoutMs: options?.websocketConnectTimeoutMs,\n\t\tmaxRetries: options?.maxRetries,\n\t\tmaxRetryDelayMs: options?.maxRetryDelayMs,\n\t\tmetadata: options?.metadata,\n\t\tenv: options?.env,\n\t};\n}\n\nexport function clampReasoning(effort: ThinkingLevel | undefined): Exclude<ThinkingLevel, \"xhigh\"> | undefined {\n\treturn effort === \"xhigh\" ? \"high\" : effort;\n}\n\nexport function adjustMaxTokensForThinking(\n\t// Undefined means no explicit caller cap. Use the model cap and fit thinking inside it.\n\tbaseMaxTokens: number | undefined,\n\tmodelMaxTokens: number,\n\treasoningLevel: ThinkingLevel,\n\tcustomBudgets?: ThinkingBudgets,\n): { maxTokens: number; thinkingBudget: number } {\n\tconst defaultBudgets: ThinkingBudgets = {\n\t\tminimal: 1024,\n\t\tlow: 2048,\n\t\tmedium: 8192,\n\t\thigh: 16384,\n\t};\n\tconst budgets = { ...defaultBudgets, ...customBudgets };\n\n\tconst minOutputTokens = 1024;\n\tconst level = clampReasoning(reasoningLevel)!;\n\tlet thinkingBudget = budgets[level]!;\n\tconst maxTokens =\n\t\tbaseMaxTokens === undefined ? modelMaxTokens : Math.min(baseMaxTokens + thinkingBudget, modelMaxTokens);\n\n\tif (maxTokens <= thinkingBudget) {\n\t\tthinkingBudget = Math.max(0, maxTokens - minOutputTokens);\n\t}\n\n\treturn { maxTokens, thinkingBudget };\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"simple-options.js","sourceRoot":"","sources":["../../src/api/simple-options.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,gBAAgB,CAAC,MAAkB,EAAE,OAA6B,EAAE,MAAe,EAAiB;IACnH,OAAO;QACN,WAAW,EAAE,OAAO,EAAE,WAAW;QACjC,SAAS,EAAE,OAAO,EAAE,SAAS;QAC7B,MAAM,EAAE,OAAO,EAAE,MAAM;QACvB,MAAM,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM;QACjC,SAAS,EAAE,OAAO,EAAE,SAAS;QAC7B,cAAc,EAAE,OAAO,EAAE,cAAc;QACvC,SAAS,EAAE,OAAO,EAAE,SAAS;QAC7B,OAAO,EAAE,OAAO,EAAE,OAAO;QACzB,SAAS,EAAE,OAAO,EAAE,SAAS;QAC7B,UAAU,EAAE,OAAO,EAAE,UAAU;QAC/B,SAAS,EAAE,OAAO,EAAE,SAAS;QAC7B,yBAAyB,EAAE,OAAO,EAAE,yBAAyB;QAC7D,UAAU,EAAE,OAAO,EAAE,UAAU;QAC/B,eAAe,EAAE,OAAO,EAAE,eAAe;QACzC,QAAQ,EAAE,OAAO,EAAE,QAAQ;QAC3B,GAAG,EAAE,OAAO,EAAE,GAAG;KACjB,CAAC;AAAA,CACF;AAED,MAAM,UAAU,cAAc,CAAC,MAAiC,EAA+C;IAC9G,OAAO,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;AAAA,CAC5C;AAED,MAAM,UAAU,0BAA0B;AACzC,wFAAwF;AACxF,aAAiC,EACjC,cAAsB,EACtB,cAA6B,EAC7B,aAA+B,EACiB;IAChD,MAAM,cAAc,GAAoB;QACvC,OAAO,EAAE,IAAI;QACb,GAAG,EAAE,IAAI;QACT,MAAM,EAAE,IAAI;QACZ,IAAI,EAAE,KAAK;KACX,CAAC;IACF,MAAM,OAAO,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,aAAa,EAAE,CAAC;IAExD,MAAM,eAAe,GAAG,IAAI,CAAC;IAC7B,MAAM,KAAK,GAAG,cAAc,CAAC,cAAc,CAAE,CAAC;IAC9C,IAAI,cAAc,GAAG,OAAO,CAAC,KAAK,CAAE,CAAC;IACrC,MAAM,SAAS,GACd,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,GAAG,cAAc,EAAE,cAAc,CAAC,CAAC;IAEzG,IAAI,SAAS,IAAI,cAAc,EAAE,CAAC;QACjC,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,eAAe,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC;AAAA,CACrC","sourcesContent":["import type { Api, Model, SimpleStreamOptions, StreamOptions, ThinkingBudgets, ThinkingLevel } from \"../types.ts\";\n\nexport function buildBaseOptions(_model: Model<Api>, options?: SimpleStreamOptions, apiKey?: string): StreamOptions {\n\treturn {\n\t\ttemperature: options?.temperature,\n\t\tmaxTokens: options?.maxTokens,\n\t\tsignal: options?.signal,\n\t\tapiKey: apiKey || options?.apiKey,\n\t\ttransport: options?.transport,\n\t\tcacheRetention: options?.cacheRetention,\n\t\tsessionId: options?.sessionId,\n\t\theaders: options?.headers,\n\t\tonPayload: options?.onPayload,\n\t\tonResponse: options?.onResponse,\n\t\ttimeoutMs: options?.timeoutMs,\n\t\twebsocketConnectTimeoutMs: options?.websocketConnectTimeoutMs,\n\t\tmaxRetries: options?.maxRetries,\n\t\tmaxRetryDelayMs: options?.maxRetryDelayMs,\n\t\tmetadata: options?.metadata,\n\t\tenv: options?.env,\n\t};\n}\n\nexport function clampReasoning(effort: ThinkingLevel | undefined): Exclude<ThinkingLevel, \"xhigh\"> | undefined {\n\treturn effort === \"xhigh\" ? \"high\" : effort;\n}\n\nexport function adjustMaxTokensForThinking(\n\t// Undefined means no explicit caller cap. Use the model cap and fit thinking inside it.\n\tbaseMaxTokens: number | undefined,\n\tmodelMaxTokens: number,\n\treasoningLevel: ThinkingLevel,\n\tcustomBudgets?: ThinkingBudgets,\n): { maxTokens: number; thinkingBudget: number } {\n\tconst defaultBudgets: ThinkingBudgets = {\n\t\tminimal: 1024,\n\t\tlow: 2048,\n\t\tmedium: 8192,\n\t\thigh: 16384,\n\t};\n\tconst budgets = { ...defaultBudgets, ...customBudgets };\n\n\tconst minOutputTokens = 1024;\n\tconst level = clampReasoning(reasoningLevel)!;\n\tlet thinkingBudget = budgets[level]!;\n\tconst maxTokens =\n\t\tbaseMaxTokens === undefined ? modelMaxTokens : Math.min(baseMaxTokens + thinkingBudget, modelMaxTokens);\n\n\tif (maxTokens <= thinkingBudget) {\n\t\tthinkingBudget = Math.max(0, maxTokens - minOutputTokens);\n\t}\n\n\treturn { maxTokens, thinkingBudget };\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transform-messages.d.ts","sourceRoot":"","sources":["../../src/api/transform-messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,GAAG,EACH,gBAAgB,EAEhB,OAAO,EACP,KAAK,EAIL,MAAM,aAAa,CAAC;AAiDrB;;;;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,CAwJX","sourcesContent":["import type {\n\tApi,\n\tAssistantMessage,\n\tImageContent,\n\tMessage,\n\tModel,\n\tTextContent,\n\tToolCall,\n\tToolResultMessage,\n} from \"../types.ts\";\n\nconst NON_VISION_USER_IMAGE_PLACEHOLDER = \"(image omitted: model does not support images)\";\nconst NON_VISION_TOOL_IMAGE_PLACEHOLDER = \"(tool image omitted: model does not support images)\";\n\nfunction replaceImagesWithPlaceholder(content: (TextContent | ImageContent)[], placeholder: string): TextContent[] {\n\tconst result: TextContent[] = [];\n\tlet previousWasPlaceholder = false;\n\n\tfor (const block of content) {\n\t\tif (block.type === \"image\") {\n\t\t\tif (!previousWasPlaceholder) {\n\t\t\t\tresult.push({ type: \"text\", text: placeholder });\n\t\t\t}\n\t\t\tpreviousWasPlaceholder = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\tresult.push(block);\n\t\tpreviousWasPlaceholder = block.text === placeholder;\n\t}\n\n\treturn result;\n}\n\nfunction downgradeUnsupportedImages<TApi extends Api>(messages: Message[], model: Model<TApi>): Message[] {\n\tif (model.input.includes(\"image\")) {\n\t\treturn messages;\n\t}\n\n\treturn messages.map((msg) => {\n\t\tif (msg.role === \"user\" && Array.isArray(msg.content)) {\n\t\t\treturn {\n\t\t\t\t...msg,\n\t\t\t\tcontent: replaceImagesWithPlaceholder(msg.content, NON_VISION_USER_IMAGE_PLACEHOLDER),\n\t\t\t};\n\t\t}\n\n\t\tif (msg.role === \"toolResult\") {\n\t\t\treturn {\n\t\t\t\t...msg,\n\t\t\t\tcontent: replaceImagesWithPlaceholder(msg.content, NON_VISION_TOOL_IMAGE_PLACEHOLDER),\n\t\t\t};\n\t\t}\n\n\t\treturn msg;\n\t});\n}\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\tconst imageAwareMessages = downgradeUnsupportedImages(messages, model);\n\n\t// First pass: transform messages (unsupported image downgrade, thinking blocks, tool call ID normalization)\n\tconst transformed = imageAwareMessages.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// Redacted thinking is opaque encrypted content, only valid for the same model.\n\t\t\t\t\t// Drop it for cross-model to avoid API errors.\n\t\t\t\t\tif (block.redacted) {\n\t\t\t\t\t\treturn isSameModel ? block : [];\n\t\t\t\t\t}\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\tconst insertSyntheticToolResults = () => {\n\t\tif (pendingToolCalls.length > 0) {\n\t\t\tfor (const tc of pendingToolCalls) {\n\t\t\t\tif (!existingToolResultIds.has(tc.id)) {\n\t\t\t\t\tresult.push({\n\t\t\t\t\t\trole: \"toolResult\",\n\t\t\t\t\t\ttoolCallId: tc.id,\n\t\t\t\t\t\ttoolName: tc.name,\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"No result provided\" }],\n\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t} as ToolResultMessage);\n\t\t\t\t}\n\t\t\t}\n\t\t\tpendingToolCalls = [];\n\t\t\texistingToolResultIds = new Set();\n\t\t}\n\t};\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\tinsertSyntheticToolResults();\n\n\t\t\t// Skip errored/aborted assistant messages entirely.\n\t\t\t// These are incomplete turns that shouldn't be replayed:\n\t\t\t// - May have partial content (reasoning without message, incomplete tool calls)\n\t\t\t// - Replaying them can cause API errors (e.g., OpenAI \"reasoning without following item\")\n\t\t\t// - The model should retry from the last valid state\n\t\t\tconst assistantMsg = msg as AssistantMessage;\n\t\t\tif (assistantMsg.stopReason === \"error\" || assistantMsg.stopReason === \"aborted\") {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Track tool calls from this assistant message\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\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\tinsertSyntheticToolResults();\n\t\t\tresult.push(msg);\n\t\t} else {\n\t\t\tresult.push(msg);\n\t\t}\n\t}\n\n\t// If the conversation ends with unresolved tool calls, synthesize results now.\n\tinsertSyntheticToolResults();\n\n\treturn result;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transform-messages.js","sourceRoot":"","sources":["../../src/api/transform-messages.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n\tApi,\n\tAssistantMessage,\n\tImageContent,\n\tMessage,\n\tModel,\n\tTextContent,\n\tToolCall,\n\tToolResultMessage,\n} from \"../types.ts\";\n\nconst NON_VISION_USER_IMAGE_PLACEHOLDER = \"(image omitted: model does not support images)\";\nconst NON_VISION_TOOL_IMAGE_PLACEHOLDER = \"(tool image omitted: model does not support images)\";\n\nfunction replaceImagesWithPlaceholder(content: (TextContent | ImageContent)[], placeholder: string): TextContent[] {\n\tconst result: TextContent[] = [];\n\tlet previousWasPlaceholder = false;\n\n\tfor (const block of content) {\n\t\tif (block.type === \"image\") {\n\t\t\tif (!previousWasPlaceholder) {\n\t\t\t\tresult.push({ type: \"text\", text: placeholder });\n\t\t\t}\n\t\t\tpreviousWasPlaceholder = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\tresult.push(block);\n\t\tpreviousWasPlaceholder = block.text === placeholder;\n\t}\n\n\treturn result;\n}\n\nfunction downgradeUnsupportedImages<TApi extends Api>(messages: Message[], model: Model<TApi>): Message[] {\n\tif (model.input.includes(\"image\")) {\n\t\treturn messages;\n\t}\n\n\treturn messages.map((msg) => {\n\t\tif (msg.role === \"user\" && Array.isArray(msg.content)) {\n\t\t\treturn {\n\t\t\t\t...msg,\n\t\t\t\tcontent: replaceImagesWithPlaceholder(msg.content, NON_VISION_USER_IMAGE_PLACEHOLDER),\n\t\t\t};\n\t\t}\n\n\t\tif (msg.role === \"toolResult\") {\n\t\t\treturn {\n\t\t\t\t...msg,\n\t\t\t\tcontent: replaceImagesWithPlaceholder(msg.content, NON_VISION_TOOL_IMAGE_PLACEHOLDER),\n\t\t\t};\n\t\t}\n\n\t\treturn msg;\n\t});\n}\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\tconst imageAwareMessages = downgradeUnsupportedImages(messages, model);\n\n\t// First pass: transform messages (unsupported image downgrade, thinking blocks, tool call ID normalization)\n\tconst transformed = imageAwareMessages.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// Redacted thinking is opaque encrypted content, only valid for the same model.\n\t\t\t\t\t// Drop it for cross-model to avoid API errors.\n\t\t\t\t\tif (block.redacted) {\n\t\t\t\t\t\treturn isSameModel ? block : [];\n\t\t\t\t\t}\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\tconst insertSyntheticToolResults = () => {\n\t\tif (pendingToolCalls.length > 0) {\n\t\t\tfor (const tc of pendingToolCalls) {\n\t\t\t\tif (!existingToolResultIds.has(tc.id)) {\n\t\t\t\t\tresult.push({\n\t\t\t\t\t\trole: \"toolResult\",\n\t\t\t\t\t\ttoolCallId: tc.id,\n\t\t\t\t\t\ttoolName: tc.name,\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"No result provided\" }],\n\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t} as ToolResultMessage);\n\t\t\t\t}\n\t\t\t}\n\t\t\tpendingToolCalls = [];\n\t\t\texistingToolResultIds = new Set();\n\t\t}\n\t};\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\tinsertSyntheticToolResults();\n\n\t\t\t// Skip errored/aborted assistant messages entirely.\n\t\t\t// These are incomplete turns that shouldn't be replayed:\n\t\t\t// - May have partial content (reasoning without message, incomplete tool calls)\n\t\t\t// - Replaying them can cause API errors (e.g., OpenAI \"reasoning without following item\")\n\t\t\t// - The model should retry from the last valid state\n\t\t\tconst assistantMsg = msg as AssistantMessage;\n\t\t\tif (assistantMsg.stopReason === \"error\" || assistantMsg.stopReason === \"aborted\") {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Track tool calls from this assistant message\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\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\tinsertSyntheticToolResults();\n\t\t\tresult.push(msg);\n\t\t} else {\n\t\t\tresult.push(msg);\n\t\t}\n\t}\n\n\t// If the conversation ends with unresolved tool calls, synthesize results now.\n\tinsertSyntheticToolResults();\n\n\treturn result;\n}\n"]}
|