@code-yeongyu/senpi-ai 2026.7.25-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 +1663 -0
- 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 +1626 -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 +242 -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 +939 -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/api/cloudflare.d.ts +12 -0
- package/dist/api/cloudflare.d.ts.map +1 -0
- package/dist/api/cloudflare.js +22 -0
- package/dist/api/cloudflare.js.map +1 -0
- package/dist/api/constrained-sampling.d.ts +17 -0
- package/dist/api/constrained-sampling.d.ts.map +1 -0
- package/dist/api/constrained-sampling.js +104 -0
- package/dist/api/constrained-sampling.js.map +1 -0
- package/dist/api/github-copilot-headers.d.ts +8 -0
- package/dist/api/github-copilot-headers.d.ts.map +1 -0
- package/dist/api/github-copilot-headers.js +29 -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 +440 -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 +70 -0
- package/dist/api/google-shared.d.ts.map +1 -0
- package/dist/api/google-shared.js +360 -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 +485 -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 +85 -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 +566 -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/api/openai-codex-responses.d.ts +31 -0
- package/dist/api/openai-codex-responses.d.ts.map +1 -0
- package/dist/api/openai-codex-responses.js +1326 -0
- 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/api/openai-completions.d.ts +22 -0
- package/dist/api/openai-completions.d.ts.map +1 -0
- package/dist/api/openai-completions.js +1384 -0
- 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 +3 -0
- package/dist/api/openai-prompt-cache.d.ts.map +1 -0
- package/dist/api/openai-prompt-cache.js +10 -0
- package/dist/api/openai-prompt-cache.js.map +1 -0
- package/dist/api/openai-responses-shared.d.ts +29 -0
- package/dist/api/openai-responses-shared.d.ts.map +1 -0
- package/dist/api/openai-responses-shared.js +730 -0
- package/dist/api/openai-responses-shared.js.map +1 -0
- package/dist/api/openai-responses.d.ts +14 -0
- package/dist/api/openai-responses.d.ts.map +1 -0
- package/dist/api/openai-responses.js +696 -0
- 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/api/openrouter-images.js +131 -0
- 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/pi-messages.d.ts +97 -0
- package/dist/api/pi-messages.d.ts.map +1 -0
- package/dist/api/pi-messages.js +305 -0
- package/dist/api/pi-messages.js.map +1 -0
- package/dist/api/pi-messages.lazy.d.ts +3 -0
- package/dist/api/pi-messages.lazy.d.ts.map +1 -0
- package/dist/api/pi-messages.lazy.js +3 -0
- package/dist/api/pi-messages.lazy.js.map +1 -0
- package/dist/api/simple-options.d.ts +33 -0
- package/dist/api/simple-options.d.ts.map +1 -0
- package/dist/api/simple-options.js +177 -0
- package/dist/api/simple-options.js.map +1 -0
- package/dist/api/transform-messages.d.ts +23 -0
- package/dist/api/transform-messages.d.ts.map +1 -0
- package/dist/api/transform-messages.js +255 -0
- package/dist/api/transform-messages.js.map +1 -0
- package/dist/api-registry.d.ts +34 -0
- package/dist/api-registry.d.ts.map +1 -0
- package/dist/api-registry.js +96 -0
- package/dist/api-registry.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 +17 -0
- package/dist/auth/credential-store.d.ts.map +1 -0
- package/dist/auth/credential-store.js +42 -0
- package/dist/auth/credential-store.js.map +1 -0
- package/dist/auth/helpers.d.ts +21 -0
- package/dist/auth/helpers.d.ts.map +1 -0
- package/dist/auth/helpers.js +48 -0
- package/dist/auth/helpers.js.map +1 -0
- package/dist/auth/oauth/anthropic.d.ts +9 -0
- package/dist/auth/oauth/anthropic.d.ts.map +1 -0
- package/dist/auth/oauth/anthropic.js +302 -0
- package/dist/auth/oauth/anthropic.js.map +1 -0
- package/dist/auth/oauth/device-code.d.ts +23 -0
- package/dist/auth/oauth/device-code.d.ts.map +1 -0
- package/dist/auth/oauth/device-code.js +69 -0
- package/dist/auth/oauth/device-code.js.map +1 -0
- package/dist/auth/oauth/github-copilot.d.ts +6 -0
- package/dist/auth/oauth/github-copilot.d.ts.map +1 -0
- package/dist/auth/oauth/github-copilot.js +312 -0
- package/dist/auth/oauth/github-copilot.js.map +1 -0
- package/dist/auth/oauth/kimi-coding.d.ts +10 -0
- package/dist/auth/oauth/kimi-coding.d.ts.map +1 -0
- package/dist/auth/oauth/kimi-coding.js +249 -0
- package/dist/auth/oauth/kimi-coding.js.map +1 -0
- package/dist/auth/oauth/load.d.ts +27 -0
- package/dist/auth/oauth/load.d.ts.map +1 -0
- package/dist/auth/oauth/load.js +59 -0
- package/dist/auth/oauth/load.js.map +1 -0
- package/dist/auth/oauth/oauth-page.d.ts +3 -0
- package/dist/auth/oauth/oauth-page.d.ts.map +1 -0
- package/dist/auth/oauth/oauth-page.js +105 -0
- package/dist/auth/oauth/oauth-page.js.map +1 -0
- package/dist/auth/oauth/openai-codex.d.ts +9 -0
- package/dist/auth/oauth/openai-codex.d.ts.map +1 -0
- package/dist/auth/oauth/openai-codex.js +427 -0
- package/dist/auth/oauth/openai-codex.js.map +1 -0
- package/dist/auth/oauth/openrouter.d.ts +13 -0
- package/dist/auth/oauth/openrouter.d.ts.map +1 -0
- package/dist/auth/oauth/openrouter.js +222 -0
- package/dist/auth/oauth/openrouter.js.map +1 -0
- package/dist/auth/oauth/pkce.d.ts +13 -0
- package/dist/auth/oauth/pkce.d.ts.map +1 -0
- package/dist/auth/oauth/pkce.js +31 -0
- package/dist/auth/oauth/pkce.js.map +1 -0
- package/dist/auth/oauth/radius.d.ts +17 -0
- package/dist/auth/oauth/radius.d.ts.map +1 -0
- package/dist/auth/oauth/radius.js +318 -0
- package/dist/auth/oauth/radius.js.map +1 -0
- package/dist/auth/oauth/xai.d.ts +6 -0
- package/dist/auth/oauth/xai.d.ts.map +1 -0
- package/dist/auth/oauth/xai.js +189 -0
- package/dist/auth/oauth/xai.js.map +1 -0
- package/dist/auth/resolve.d.ts +24 -0
- package/dist/auth/resolve.d.ts.map +1 -0
- package/dist/auth/resolve.js +112 -0
- package/dist/auth/resolve.js.map +1 -0
- package/dist/auth/types.d.ts +219 -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 +5 -0
- package/dist/bedrock-provider.d.ts.map +1 -0
- package/dist/bedrock-provider.js +6 -0
- package/dist/bedrock-provider.js.map +1 -0
- package/dist/bun-oauth.d.ts +3 -0
- package/dist/bun-oauth.d.ts.map +1 -0
- package/dist/bun-oauth.js +21 -0
- package/dist/bun-oauth.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +112 -0
- package/dist/cli.js.map +1 -0
- package/dist/compat/extension-oauth-types.d.ts +42 -0
- package/dist/compat/extension-oauth-types.d.ts.map +1 -0
- package/dist/compat/extension-oauth-types.js +2 -0
- package/dist/compat/extension-oauth-types.js.map +1 -0
- package/dist/compat.d.ts +53 -0
- package/dist/compat.d.ts.map +1 -0
- package/dist/compat.js +176 -0
- package/dist/compat.js.map +1 -0
- package/dist/context-provenance.d.ts +16 -0
- package/dist/context-provenance.d.ts.map +1 -0
- package/dist/context-provenance.js +32 -0
- package/dist/context-provenance.js.map +1 -0
- package/dist/env-api-keys.d.ts +21 -0
- package/dist/env-api-keys.d.ts.map +1 -0
- package/dist/env-api-keys.js +155 -0
- package/dist/env-api-keys.js.map +1 -0
- package/dist/image-models.d.ts +10 -0
- package/dist/image-models.d.ts.map +1 -0
- package/dist/image-models.generated.d.ts +605 -0
- package/dist/image-models.generated.d.ts.map +1 -0
- package/dist/image-models.generated.js +607 -0
- package/dist/image-models.generated.js.map +1 -0
- package/dist/image-models.js +23 -0
- package/dist/image-models.js.map +1 -0
- package/dist/images-api-registry.d.ts +31 -0
- package/dist/images-api-registry.d.ts.map +1 -0
- package/dist/images-api-registry.js +87 -0
- package/dist/images-api-registry.js.map +1 -0
- package/dist/images-models.d.ts +95 -0
- package/dist/images-models.d.ts.map +1 -0
- package/dist/images-models.js +140 -0
- package/dist/images-models.js.map +1 -0
- package/dist/images.d.ts +4 -0
- package/dist/images.d.ts.map +1 -0
- package/dist/images.js +14 -0
- package/dist/images.js.map +1 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +32 -0
- package/dist/index.js.map +1 -0
- 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/model-catalog.d.ts +17 -0
- package/dist/model-catalog.d.ts.map +1 -0
- package/dist/model-catalog.js +4 -0
- package/dist/model-catalog.js.map +1 -0
- package/dist/model.d.ts +27 -0
- package/dist/model.d.ts.map +1 -0
- package/dist/model.js +2 -0
- package/dist/model.js.map +1 -0
- package/dist/models-store.d.ts +32 -0
- package/dist/models-store.d.ts.map +1 -0
- package/dist/models-store.js +16 -0
- package/dist/models-store.js.map +1 -0
- package/dist/models.d.ts +179 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.generated.d.ts +79 -0
- package/dist/models.generated.d.ts.map +1 -0
- package/dist/models.generated.js +81 -0
- package/dist/models.generated.js.map +1 -0
- package/dist/models.js +449 -0
- package/dist/models.js.map +1 -0
- package/dist/node/provider-scope.d.ts +12 -0
- package/dist/node/provider-scope.d.ts.map +1 -0
- package/dist/node/provider-scope.js +34 -0
- package/dist/node/provider-scope.js.map +1 -0
- package/dist/oauth.d.ts +3 -0
- package/dist/oauth.d.ts.map +1 -0
- package/dist/oauth.js +2 -0
- package/dist/oauth.js.map +1 -0
- package/dist/providers/alibaba-token-plan.d.ts +3 -0
- package/dist/providers/alibaba-token-plan.d.ts.map +1 -0
- package/dist/providers/alibaba-token-plan.js +15 -0
- package/dist/providers/alibaba-token-plan.js.map +1 -0
- package/dist/providers/alibaba-token-plan.models.d.ts +4 -0
- package/dist/providers/alibaba-token-plan.models.d.ts.map +1 -0
- package/dist/providers/alibaba-token-plan.models.js +6 -0
- package/dist/providers/alibaba-token-plan.models.js.map +1 -0
- package/dist/providers/all.d.ts +28 -0
- package/dist/providers/all.d.ts.map +1 -0
- package/dist/providers/all.js +162 -0
- package/dist/providers/all.js.map +1 -0
- package/dist/providers/amazon-bedrock.d.ts +3 -0
- package/dist/providers/amazon-bedrock.d.ts.map +1 -0
- package/dist/providers/amazon-bedrock.js +85 -0
- package/dist/providers/amazon-bedrock.js.map +1 -0
- package/dist/providers/amazon-bedrock.models.d.ts +4 -0
- package/dist/providers/amazon-bedrock.models.d.ts.map +1 -0
- package/dist/providers/amazon-bedrock.models.js +6 -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 +4 -0
- package/dist/providers/ant-ling.models.d.ts.map +1 -0
- package/dist/providers/ant-ling.models.js +6 -0
- package/dist/providers/ant-ling.models.js.map +1 -0
- package/dist/providers/anthropic.d.ts +7 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +50 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/anthropic.models.d.ts +4 -0
- package/dist/providers/anthropic.models.d.ts.map +1 -0
- package/dist/providers/anthropic.models.js +6 -0
- package/dist/providers/anthropic.models.js.map +1 -0
- package/dist/providers/azure-openai-responses.d.ts +3 -0
- package/dist/providers/azure-openai-responses.d.ts.map +1 -0
- package/dist/providers/azure-openai-responses.js +14 -0
- package/dist/providers/azure-openai-responses.js.map +1 -0
- package/dist/providers/azure-openai-responses.models.d.ts +4 -0
- package/dist/providers/azure-openai-responses.models.d.ts.map +1 -0
- package/dist/providers/azure-openai-responses.models.js +6 -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 +4 -0
- package/dist/providers/cerebras.models.d.ts.map +1 -0
- package/dist/providers/cerebras.models.js +6 -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 +21 -0
- package/dist/providers/cloudflare-ai-gateway.js.map +1 -0
- package/dist/providers/cloudflare-ai-gateway.models.d.ts +4 -0
- package/dist/providers/cloudflare-ai-gateway.models.d.ts.map +1 -0
- package/dist/providers/cloudflare-ai-gateway.models.js +6 -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 +81 -0
- package/dist/providers/cloudflare-auth.js.map +1 -0
- package/dist/providers/cloudflare-stream.d.ts +8 -0
- package/dist/providers/cloudflare-stream.d.ts.map +1 -0
- package/dist/providers/cloudflare-stream.js +21 -0
- package/dist/providers/cloudflare-stream.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 +15 -0
- package/dist/providers/cloudflare-workers-ai.js.map +1 -0
- package/dist/providers/cloudflare-workers-ai.models.d.ts +4 -0
- package/dist/providers/cloudflare-workers-ai.models.d.ts.map +1 -0
- package/dist/providers/cloudflare-workers-ai.models.js +6 -0
- package/dist/providers/cloudflare-workers-ai.models.js.map +1 -0
- package/dist/providers/data/.manifest.json +1 -0
- package/dist/providers/data/alibaba-token-plan.json +1 -0
- package/dist/providers/data/amazon-bedrock.json +1 -0
- package/dist/providers/data/ant-ling.json +1 -0
- package/dist/providers/data/anthropic.json +1 -0
- package/dist/providers/data/azure-openai-responses.json +1 -0
- package/dist/providers/data/cerebras.json +1 -0
- package/dist/providers/data/cloudflare-ai-gateway.json +1 -0
- package/dist/providers/data/cloudflare-workers-ai.json +1 -0
- package/dist/providers/data/deepseek.json +1 -0
- package/dist/providers/data/fireworks.json +1 -0
- package/dist/providers/data/github-copilot.json +1 -0
- package/dist/providers/data/google-vertex.json +1 -0
- package/dist/providers/data/google.json +1 -0
- package/dist/providers/data/groq.json +1 -0
- package/dist/providers/data/huggingface.json +1 -0
- package/dist/providers/data/kimi-coding.json +1 -0
- package/dist/providers/data/minimax-cn.json +1 -0
- package/dist/providers/data/minimax.json +1 -0
- package/dist/providers/data/mistral.json +1 -0
- package/dist/providers/data/moonshotai-cn.json +1 -0
- package/dist/providers/data/moonshotai.json +1 -0
- package/dist/providers/data/nvidia.json +1 -0
- package/dist/providers/data/openai-codex.json +1 -0
- package/dist/providers/data/openai.json +1 -0
- package/dist/providers/data/opencode-go.json +1 -0
- package/dist/providers/data/opencode.json +1 -0
- package/dist/providers/data/openrouter.json +1 -0
- package/dist/providers/data/qwen-token-plan-cn.json +1 -0
- package/dist/providers/data/qwen-token-plan.json +1 -0
- package/dist/providers/data/together.json +1 -0
- package/dist/providers/data/vercel-ai-gateway.json +1 -0
- package/dist/providers/data/xai.json +1 -0
- package/dist/providers/data/xiaomi-token-plan-ams.json +1 -0
- package/dist/providers/data/xiaomi-token-plan-cn.json +1 -0
- package/dist/providers/data/xiaomi-token-plan-sgp.json +1 -0
- package/dist/providers/data/xiaomi.json +1 -0
- package/dist/providers/data/zai-coding-cn.json +1 -0
- package/dist/providers/data/zai.json +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 +4 -0
- package/dist/providers/deepseek.models.d.ts.map +1 -0
- package/dist/providers/deepseek.models.js +6 -0
- package/dist/providers/deepseek.models.js.map +1 -0
- package/dist/providers/faux.d.ts +116 -0
- package/dist/providers/faux.d.ts.map +1 -0
- package/dist/providers/faux.js +466 -0
- package/dist/providers/faux.js.map +1 -0
- 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 +4 -0
- package/dist/providers/fireworks.models.d.ts.map +1 -0
- package/dist/providers/fireworks.models.js +6 -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 +35 -0
- package/dist/providers/github-copilot.js.map +1 -0
- package/dist/providers/github-copilot.models.d.ts +4 -0
- package/dist/providers/github-copilot.models.d.ts.map +1 -0
- package/dist/providers/github-copilot.models.js +6 -0
- package/dist/providers/github-copilot.models.js.map +1 -0
- package/dist/providers/google-shared.d.ts +2 -0
- package/dist/providers/google-shared.d.ts.map +1 -0
- package/dist/providers/google-shared.js +2 -0
- package/dist/providers/google-shared.js.map +1 -0
- package/dist/providers/google-vertex.d.ts +7 -0
- package/dist/providers/google-vertex.d.ts.map +1 -0
- package/dist/providers/google-vertex.js +89 -0
- package/dist/providers/google-vertex.js.map +1 -0
- package/dist/providers/google-vertex.models.d.ts +4 -0
- package/dist/providers/google-vertex.models.d.ts.map +1 -0
- package/dist/providers/google-vertex.models.js +6 -0
- package/dist/providers/google-vertex.models.js.map +1 -0
- package/dist/providers/google.d.ts +7 -0
- package/dist/providers/google.d.ts.map +1 -0
- package/dist/providers/google.js +18 -0
- package/dist/providers/google.js.map +1 -0
- package/dist/providers/google.models.d.ts +4 -0
- package/dist/providers/google.models.d.ts.map +1 -0
- package/dist/providers/google.models.js +6 -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 +4 -0
- package/dist/providers/groq.models.d.ts.map +1 -0
- package/dist/providers/groq.models.js +6 -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 +4 -0
- package/dist/providers/huggingface.models.d.ts.map +1 -0
- package/dist/providers/huggingface.models.js +6 -0
- package/dist/providers/huggingface.models.js.map +1 -0
- package/dist/providers/images/register-builtins.d.ts +4 -0
- 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 +23 -0
- package/dist/providers/kimi-coding.js.map +1 -0
- package/dist/providers/kimi-coding.models.d.ts +4 -0
- package/dist/providers/kimi-coding.models.d.ts.map +1 -0
- package/dist/providers/kimi-coding.models.js +6 -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 +4 -0
- package/dist/providers/minimax-cn.models.d.ts.map +1 -0
- package/dist/providers/minimax-cn.models.js +6 -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 +4 -0
- package/dist/providers/minimax.models.d.ts.map +1 -0
- package/dist/providers/minimax.models.js +6 -0
- package/dist/providers/minimax.models.js.map +1 -0
- package/dist/providers/mistral.d.ts +3 -0
- package/dist/providers/mistral.d.ts.map +1 -0
- package/dist/providers/mistral.js +15 -0
- package/dist/providers/mistral.js.map +1 -0
- package/dist/providers/mistral.models.d.ts +4 -0
- package/dist/providers/mistral.models.d.ts.map +1 -0
- package/dist/providers/mistral.models.js +6 -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 +4 -0
- package/dist/providers/moonshotai-cn.models.d.ts.map +1 -0
- package/dist/providers/moonshotai-cn.models.js +6 -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 +4 -0
- package/dist/providers/moonshotai.models.d.ts.map +1 -0
- package/dist/providers/moonshotai.models.js +6 -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 +4 -0
- package/dist/providers/nvidia.models.d.ts.map +1 -0
- package/dist/providers/nvidia.models.js +6 -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 +4 -0
- package/dist/providers/openai-codex.models.d.ts.map +1 -0
- package/dist/providers/openai-codex.models.js +6 -0
- package/dist/providers/openai-codex.models.js.map +1 -0
- package/dist/providers/openai-completions.d.ts +3 -0
- package/dist/providers/openai-completions.d.ts.map +1 -0
- package/dist/providers/openai-completions.js +2 -0
- package/dist/providers/openai-completions.js.map +1 -0
- package/dist/providers/openai-responses-shared.d.ts +2 -0
- package/dist/providers/openai-responses-shared.d.ts.map +1 -0
- package/dist/providers/openai-responses-shared.js +2 -0
- package/dist/providers/openai-responses-shared.js.map +1 -0
- package/dist/providers/openai-responses.d.ts +3 -0
- package/dist/providers/openai-responses.d.ts.map +1 -0
- package/dist/providers/openai-responses.js +2 -0
- package/dist/providers/openai-responses.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 +4 -0
- package/dist/providers/openai.models.d.ts.map +1 -0
- package/dist/providers/openai.models.js +6 -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 +20 -0
- package/dist/providers/opencode-go.js.map +1 -0
- package/dist/providers/opencode-go.models.d.ts +4 -0
- package/dist/providers/opencode-go.models.d.ts.map +1 -0
- package/dist/providers/opencode-go.models.js +6 -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 +4 -0
- package/dist/providers/opencode.models.d.ts.map +1 -0
- package/dist/providers/opencode.models.js +6 -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 +22 -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 +23 -0
- package/dist/providers/openrouter.js.map +1 -0
- package/dist/providers/openrouter.models.d.ts +4 -0
- package/dist/providers/openrouter.models.d.ts.map +1 -0
- package/dist/providers/openrouter.models.js +6 -0
- package/dist/providers/openrouter.models.js.map +1 -0
- package/dist/providers/qwen-token-plan-cn.d.ts +3 -0
- package/dist/providers/qwen-token-plan-cn.d.ts.map +1 -0
- package/dist/providers/qwen-token-plan-cn.js +15 -0
- package/dist/providers/qwen-token-plan-cn.js.map +1 -0
- package/dist/providers/qwen-token-plan-cn.models.d.ts +4 -0
- package/dist/providers/qwen-token-plan-cn.models.d.ts.map +1 -0
- package/dist/providers/qwen-token-plan-cn.models.js +6 -0
- package/dist/providers/qwen-token-plan-cn.models.js.map +1 -0
- package/dist/providers/qwen-token-plan.d.ts +3 -0
- package/dist/providers/qwen-token-plan.d.ts.map +1 -0
- package/dist/providers/qwen-token-plan.js +15 -0
- package/dist/providers/qwen-token-plan.js.map +1 -0
- package/dist/providers/qwen-token-plan.models.d.ts +4 -0
- package/dist/providers/qwen-token-plan.models.d.ts.map +1 -0
- package/dist/providers/qwen-token-plan.models.js +6 -0
- package/dist/providers/qwen-token-plan.models.js.map +1 -0
- package/dist/providers/radius-config.d.ts +26 -0
- package/dist/providers/radius-config.d.ts.map +1 -0
- package/dist/providers/radius-config.js +63 -0
- package/dist/providers/radius-config.js.map +1 -0
- package/dist/providers/radius.d.ts +9 -0
- package/dist/providers/radius.d.ts.map +1 -0
- package/dist/providers/radius.js +54 -0
- package/dist/providers/radius.js.map +1 -0
- package/dist/providers/register-builtins.d.ts +2 -0
- package/dist/providers/register-builtins.d.ts.map +1 -0
- package/dist/providers/register-builtins.js +2 -0
- package/dist/providers/register-builtins.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 +4 -0
- package/dist/providers/together.models.d.ts.map +1 -0
- package/dist/providers/together.models.js +6 -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 +4 -0
- package/dist/providers/vercel-ai-gateway.models.d.ts.map +1 -0
- package/dist/providers/vercel-ai-gateway.models.js +6 -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 +27 -0
- package/dist/providers/xai.js.map +1 -0
- package/dist/providers/xai.models.d.ts +4 -0
- package/dist/providers/xai.models.d.ts.map +1 -0
- package/dist/providers/xai.models.js +6 -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 +4 -0
- package/dist/providers/xiaomi-token-plan-ams.models.d.ts.map +1 -0
- package/dist/providers/xiaomi-token-plan-ams.models.js +6 -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 +4 -0
- package/dist/providers/xiaomi-token-plan-cn.models.d.ts.map +1 -0
- package/dist/providers/xiaomi-token-plan-cn.models.js +6 -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 +4 -0
- package/dist/providers/xiaomi-token-plan-sgp.models.d.ts.map +1 -0
- package/dist/providers/xiaomi-token-plan-sgp.models.js +6 -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 +4 -0
- package/dist/providers/xiaomi.models.d.ts.map +1 -0
- package/dist/providers/xiaomi.models.js +6 -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 +4 -0
- package/dist/providers/zai-coding-cn.models.d.ts.map +1 -0
- package/dist/providers/zai-coding-cn.models.js +6 -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 +4 -0
- package/dist/providers/zai.models.d.ts.map +1 -0
- package/dist/providers/zai.models.js +6 -0
- package/dist/providers/zai.models.js.map +1 -0
- package/dist/session-resources.d.ts +4 -0
- package/dist/session-resources.d.ts.map +1 -0
- package/dist/session-resources.js +22 -0
- package/dist/session-resources.js.map +1 -0
- package/dist/stream.d.ts +2 -0
- package/dist/stream.d.ts.map +1 -0
- package/dist/stream.js +2 -0
- package/dist/stream.js.map +1 -0
- package/dist/tool-call-middleware/context-transformer.d.ts +22 -0
- package/dist/tool-call-middleware/context-transformer.d.ts.map +1 -0
- package/dist/tool-call-middleware/context-transformer.js +182 -0
- package/dist/tool-call-middleware/context-transformer.js.map +1 -0
- package/dist/tool-call-middleware/index.d.ts +14 -0
- package/dist/tool-call-middleware/index.d.ts.map +1 -0
- package/dist/tool-call-middleware/index.js +37 -0
- package/dist/tool-call-middleware/index.js.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/coerce-parameters.d.ts +9 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/coerce-parameters.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/coerce-parameters.js +92 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/coerce-parameters.js.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/format.d.ts +7 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/format.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/format.js +54 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/format.js.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/index.d.ts +4 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/index.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/index.js +4 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/index.js.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/invoke-match.d.ts +7 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/invoke-match.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/invoke-match.js +16 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/invoke-match.js.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/invoke-protocol.d.ts +19 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/invoke-protocol.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/invoke-protocol.js +8 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/invoke-protocol.js.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/invoke-stream-helpers.d.ts +20 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/invoke-stream-helpers.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/invoke-stream-helpers.js +79 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/invoke-stream-helpers.js.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/invoke-tag-scanner.d.ts +14 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/invoke-tag-scanner.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/invoke-tag-scanner.js +42 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/invoke-tag-scanner.js.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/invoke-tag-syntax.d.ts +38 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/invoke-tag-syntax.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/invoke-tag-syntax.js +210 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/invoke-tag-syntax.js.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/parse.d.ts +6 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/parse.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/parse.js +49 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/parse.js.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/recovery-stream.d.ts +9 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/recovery-stream.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/recovery-stream.js +231 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/recovery-stream.js.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/recovery-wrapper-state.d.ts +38 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/recovery-wrapper-state.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/recovery-wrapper-state.js +84 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/recovery-wrapper-state.js.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/stream-boundary.d.ts +13 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/stream-boundary.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/stream-boundary.js +107 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/stream-boundary.js.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/stream.d.ts +7 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/stream.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/stream.js +214 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/stream.js.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/tool-resolver.d.ts +4 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/tool-resolver.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/tool-resolver.js +17 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/tool-resolver.js.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/xml-entities.d.ts +5 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/xml-entities.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/xml-entities.js +34 -0
- package/dist/tool-call-middleware/protocols/anthropic-xml/xml-entities.js.map +1 -0
- package/dist/tool-call-middleware/protocols/antml/coerce-parameters.d.ts +15 -0
- package/dist/tool-call-middleware/protocols/antml/coerce-parameters.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/antml/coerce-parameters.js +198 -0
- package/dist/tool-call-middleware/protocols/antml/coerce-parameters.js.map +1 -0
- package/dist/tool-call-middleware/protocols/antml/config.d.ts +3 -0
- package/dist/tool-call-middleware/protocols/antml/config.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/antml/config.js +8 -0
- package/dist/tool-call-middleware/protocols/antml/config.js.map +1 -0
- package/dist/tool-call-middleware/protocols/antml/format.d.ts +6 -0
- package/dist/tool-call-middleware/protocols/antml/format.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/antml/format.js +33 -0
- package/dist/tool-call-middleware/protocols/antml/format.js.map +1 -0
- package/dist/tool-call-middleware/protocols/antml/index.d.ts +7 -0
- package/dist/tool-call-middleware/protocols/antml/index.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/antml/index.js +7 -0
- package/dist/tool-call-middleware/protocols/antml/index.js.map +1 -0
- package/dist/tool-call-middleware/protocols/antml/parse.d.ts +4 -0
- package/dist/tool-call-middleware/protocols/antml/parse.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/antml/parse.js +6 -0
- package/dist/tool-call-middleware/protocols/antml/parse.js.map +1 -0
- package/dist/tool-call-middleware/protocols/antml/recovery-stream.d.ts +5 -0
- package/dist/tool-call-middleware/protocols/antml/recovery-stream.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/antml/recovery-stream.js +6 -0
- package/dist/tool-call-middleware/protocols/antml/recovery-stream.js.map +1 -0
- package/dist/tool-call-middleware/protocols/antml/repair.d.ts +12 -0
- package/dist/tool-call-middleware/protocols/antml/repair.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/antml/repair.js +46 -0
- package/dist/tool-call-middleware/protocols/antml/repair.js.map +1 -0
- package/dist/tool-call-middleware/protocols/antml/stream.d.ts +4 -0
- package/dist/tool-call-middleware/protocols/antml/stream.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/antml/stream.js +6 -0
- package/dist/tool-call-middleware/protocols/antml/stream.js.map +1 -0
- package/dist/tool-call-middleware/protocols/gemma4.d.ts +28 -0
- package/dist/tool-call-middleware/protocols/gemma4.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/gemma4.js +663 -0
- package/dist/tool-call-middleware/protocols/gemma4.js.map +1 -0
- package/dist/tool-call-middleware/protocols/hermes.d.ts +21 -0
- package/dist/tool-call-middleware/protocols/hermes.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/hermes.js +69 -0
- package/dist/tool-call-middleware/protocols/hermes.js.map +1 -0
- package/dist/tool-call-middleware/protocols/json-mix.d.ts +12 -0
- package/dist/tool-call-middleware/protocols/json-mix.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/json-mix.js +704 -0
- package/dist/tool-call-middleware/protocols/json-mix.js.map +1 -0
- package/dist/tool-call-middleware/protocols/morph-xml.d.ts +15 -0
- package/dist/tool-call-middleware/protocols/morph-xml.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/morph-xml.js +957 -0
- package/dist/tool-call-middleware/protocols/morph-xml.js.map +1 -0
- package/dist/tool-call-middleware/protocols/xml-tool-tag-scanner.d.ts +14 -0
- package/dist/tool-call-middleware/protocols/xml-tool-tag-scanner.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/xml-tool-tag-scanner.js +54 -0
- package/dist/tool-call-middleware/protocols/xml-tool-tag-scanner.js.map +1 -0
- package/dist/tool-call-middleware/protocols/yaml-xml.d.ts +8 -0
- package/dist/tool-call-middleware/protocols/yaml-xml.d.ts.map +1 -0
- package/dist/tool-call-middleware/protocols/yaml-xml.js +328 -0
- package/dist/tool-call-middleware/protocols/yaml-xml.js.map +1 -0
- package/dist/tool-call-middleware/recovery-code-mask.d.ts +19 -0
- package/dist/tool-call-middleware/recovery-code-mask.d.ts.map +1 -0
- package/dist/tool-call-middleware/recovery-code-mask.js +185 -0
- package/dist/tool-call-middleware/recovery-code-mask.js.map +1 -0
- package/dist/tool-call-middleware/recovery-content-lifecycle.d.ts +11 -0
- package/dist/tool-call-middleware/recovery-content-lifecycle.d.ts.map +1 -0
- package/dist/tool-call-middleware/recovery-content-lifecycle.js +24 -0
- package/dist/tool-call-middleware/recovery-content-lifecycle.js.map +1 -0
- package/dist/tool-call-middleware/recovery-diagnostics.d.ts +4 -0
- package/dist/tool-call-middleware/recovery-diagnostics.d.ts.map +1 -0
- package/dist/tool-call-middleware/recovery-diagnostics.js +13 -0
- package/dist/tool-call-middleware/recovery-diagnostics.js.map +1 -0
- package/dist/tool-call-middleware/recovery-event-stream.d.ts +15 -0
- package/dist/tool-call-middleware/recovery-event-stream.d.ts.map +1 -0
- package/dist/tool-call-middleware/recovery-event-stream.js +37 -0
- package/dist/tool-call-middleware/recovery-event-stream.js.map +1 -0
- package/dist/tool-call-middleware/recovery-message-snapshot.d.ts +4 -0
- package/dist/tool-call-middleware/recovery-message-snapshot.d.ts.map +1 -0
- package/dist/tool-call-middleware/recovery-message-snapshot.js +61 -0
- package/dist/tool-call-middleware/recovery-message-snapshot.js.map +1 -0
- package/dist/tool-call-middleware/recovery-native-projection.d.ts +29 -0
- package/dist/tool-call-middleware/recovery-native-projection.d.ts.map +1 -0
- package/dist/tool-call-middleware/recovery-native-projection.js +148 -0
- package/dist/tool-call-middleware/recovery-native-projection.js.map +1 -0
- package/dist/tool-call-middleware/recovery-stream-failure.d.ts +5 -0
- package/dist/tool-call-middleware/recovery-stream-failure.d.ts.map +1 -0
- package/dist/tool-call-middleware/recovery-stream-failure.js +36 -0
- package/dist/tool-call-middleware/recovery-stream-failure.js.map +1 -0
- package/dist/tool-call-middleware/recovery-stream-terminal.d.ts +15 -0
- package/dist/tool-call-middleware/recovery-stream-terminal.d.ts.map +1 -0
- package/dist/tool-call-middleware/recovery-stream-terminal.js +88 -0
- package/dist/tool-call-middleware/recovery-stream-terminal.js.map +1 -0
- package/dist/tool-call-middleware/recovery-stream-wrapper.d.ts +3 -0
- package/dist/tool-call-middleware/recovery-stream-wrapper.d.ts.map +1 -0
- package/dist/tool-call-middleware/recovery-stream-wrapper.js +233 -0
- package/dist/tool-call-middleware/recovery-stream-wrapper.js.map +1 -0
- package/dist/tool-call-middleware/recovery-text-projection.d.ts +23 -0
- package/dist/tool-call-middleware/recovery-text-projection.d.ts.map +1 -0
- package/dist/tool-call-middleware/recovery-text-projection.js +77 -0
- package/dist/tool-call-middleware/recovery-text-projection.js.map +1 -0
- package/dist/tool-call-middleware/stream-message-metadata.d.ts +5 -0
- package/dist/tool-call-middleware/stream-message-metadata.d.ts.map +1 -0
- package/dist/tool-call-middleware/stream-message-metadata.js +63 -0
- package/dist/tool-call-middleware/stream-message-metadata.js.map +1 -0
- package/dist/tool-call-middleware/stream-thinking-projection.d.ts +13 -0
- package/dist/tool-call-middleware/stream-thinking-projection.d.ts.map +1 -0
- package/dist/tool-call-middleware/stream-thinking-projection.js +52 -0
- package/dist/tool-call-middleware/stream-thinking-projection.js.map +1 -0
- package/dist/tool-call-middleware/stream-wrapper-shared.d.ts +41 -0
- package/dist/tool-call-middleware/stream-wrapper-shared.d.ts.map +1 -0
- package/dist/tool-call-middleware/stream-wrapper-shared.js +209 -0
- package/dist/tool-call-middleware/stream-wrapper-shared.js.map +1 -0
- package/dist/tool-call-middleware/stream-wrapper.d.ts +4 -0
- package/dist/tool-call-middleware/stream-wrapper.d.ts.map +1 -0
- package/dist/tool-call-middleware/stream-wrapper.js +121 -0
- package/dist/tool-call-middleware/stream-wrapper.js.map +1 -0
- package/dist/tool-call-middleware/types.d.ts +109 -0
- package/dist/tool-call-middleware/types.d.ts.map +1 -0
- package/dist/tool-call-middleware/types.js +2 -0
- package/dist/tool-call-middleware/types.js.map +1 -0
- package/dist/types.d.ts +762 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/abort-signals.d.ts +6 -0
- package/dist/utils/abort-signals.d.ts.map +1 -0
- package/dist/utils/abort-signals.js +34 -0
- package/dist/utils/abort-signals.js.map +1 -0
- package/dist/utils/deferred-tools.d.ts +9 -0
- package/dist/utils/deferred-tools.d.ts.map +1 -0
- package/dist/utils/deferred-tools.js +36 -0
- package/dist/utils/deferred-tools.js.map +1 -0
- package/dist/utils/diagnostics.d.ts +19 -0
- package/dist/utils/diagnostics.d.ts.map +1 -0
- package/dist/utils/diagnostics.js +25 -0
- package/dist/utils/diagnostics.js.map +1 -0
- package/dist/utils/error-body.d.ts +25 -0
- package/dist/utils/error-body.d.ts.map +1 -0
- package/dist/utils/error-body.js +114 -0
- package/dist/utils/error-body.js.map +1 -0
- package/dist/utils/estimate.d.ts +17 -0
- package/dist/utils/estimate.d.ts.map +1 -0
- package/dist/utils/estimate.js +119 -0
- package/dist/utils/estimate.js.map +1 -0
- package/dist/utils/event-stream.d.ts +24 -0
- package/dist/utils/event-stream.d.ts.map +1 -0
- package/dist/utils/event-stream.js +117 -0
- package/dist/utils/event-stream.js.map +1 -0
- package/dist/utils/hash.d.ts +3 -0
- package/dist/utils/hash.d.ts.map +1 -0
- package/dist/utils/hash.js +14 -0
- package/dist/utils/hash.js.map +1 -0
- package/dist/utils/headers.d.ts +4 -0
- package/dist/utils/headers.d.ts.map +1 -0
- package/dist/utils/headers.js +18 -0
- package/dist/utils/headers.js.map +1 -0
- package/dist/utils/json-parse.d.ts +16 -0
- package/dist/utils/json-parse.d.ts.map +1 -0
- package/dist/utils/json-parse.js +113 -0
- package/dist/utils/json-parse.js.map +1 -0
- package/dist/utils/node-http-proxy.d.ts +4 -0
- package/dist/utils/node-http-proxy.d.ts.map +1 -0
- package/dist/utils/node-http-proxy.js +92 -0
- package/dist/utils/node-http-proxy.js.map +1 -0
- package/dist/utils/openai-codex-auth.d.ts +11 -0
- package/dist/utils/openai-codex-auth.d.ts.map +1 -0
- package/dist/utils/openai-codex-auth.js +30 -0
- package/dist/utils/openai-codex-auth.js.map +1 -0
- package/dist/utils/overflow.d.ts +55 -0
- package/dist/utils/overflow.d.ts.map +1 -0
- package/dist/utils/overflow.js +155 -0
- package/dist/utils/overflow.js.map +1 -0
- package/dist/utils/provider-env.d.ts +7 -0
- package/dist/utils/provider-env.d.ts.map +1 -0
- package/dist/utils/provider-env.js +44 -0
- package/dist/utils/provider-env.js.map +1 -0
- package/dist/utils/provider-retry.d.ts +16 -0
- package/dist/utils/provider-retry.d.ts.map +1 -0
- package/dist/utils/provider-retry.js +94 -0
- package/dist/utils/provider-retry.js.map +1 -0
- package/dist/utils/retry.d.ts +53 -0
- package/dist/utils/retry.d.ts.map +1 -0
- package/dist/utils/retry.js +177 -0
- package/dist/utils/retry.js.map +1 -0
- package/dist/utils/sanitize-unicode.d.ts +22 -0
- package/dist/utils/sanitize-unicode.d.ts.map +1 -0
- package/dist/utils/sanitize-unicode.js +26 -0
- package/dist/utils/sanitize-unicode.js.map +1 -0
- package/dist/utils/server-fallback-receipt.d.ts +30 -0
- package/dist/utils/server-fallback-receipt.d.ts.map +1 -0
- package/dist/utils/server-fallback-receipt.js +70 -0
- package/dist/utils/server-fallback-receipt.js.map +1 -0
- package/dist/utils/stop-details.d.ts +4 -0
- package/dist/utils/stop-details.d.ts.map +1 -0
- package/dist/utils/stop-details.js +6 -0
- package/dist/utils/stop-details.js.map +1 -0
- package/dist/utils/text.d.ts +6 -0
- package/dist/utils/text.d.ts.map +1 -0
- package/dist/utils/text.js +10 -0
- package/dist/utils/text.js.map +1 -0
- package/dist/utils/tool-choice-fallback.d.ts +5 -0
- package/dist/utils/tool-choice-fallback.d.ts.map +1 -0
- package/dist/utils/tool-choice-fallback.js +41 -0
- package/dist/utils/tool-choice-fallback.js.map +1 -0
- package/dist/utils/tool-pair-repair.d.ts +5 -0
- package/dist/utils/tool-pair-repair.d.ts.map +1 -0
- package/dist/utils/tool-pair-repair.js +70 -0
- package/dist/utils/tool-pair-repair.js.map +1 -0
- package/dist/utils/tool-schema-compat.d.ts +19 -0
- package/dist/utils/tool-schema-compat.d.ts.map +1 -0
- package/dist/utils/tool-schema-compat.js +215 -0
- package/dist/utils/tool-schema-compat.js.map +1 -0
- package/dist/utils/typebox-helpers.d.ts +17 -0
- package/dist/utils/typebox-helpers.d.ts.map +1 -0
- package/dist/utils/typebox-helpers.js +21 -0
- package/dist/utils/typebox-helpers.js.map +1 -0
- package/dist/utils/uuid.d.ts +3 -0
- package/dist/utils/uuid.d.ts.map +1 -0
- package/dist/utils/uuid.js +50 -0
- package/dist/utils/uuid.js.map +1 -0
- package/dist/utils/validation.d.ts +18 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +269 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +110 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenRouter OAuth PKCE flow.
|
|
3
|
+
*
|
|
4
|
+
* OpenRouter exchanges an authorization code for a permanent, user-controlled
|
|
5
|
+
* API key rather than an expiring access/refresh token pair. The callback is
|
|
6
|
+
* handled by a one-shot loopback server on an ephemeral port.
|
|
7
|
+
*
|
|
8
|
+
* NOTE: This module uses Node.js http.createServer for the OAuth callback server.
|
|
9
|
+
* It is only intended for CLI use, not browser environments.
|
|
10
|
+
*/
|
|
11
|
+
import { createServer } from "node:http";
|
|
12
|
+
import { getProviderEnvValue } from "../../utils/provider-env.js";
|
|
13
|
+
import { oauthErrorHtml, oauthSuccessHtml } from "./oauth-page.js";
|
|
14
|
+
import { generatePKCE } from "./pkce.js";
|
|
15
|
+
const AUTHORIZE_URL = "https://openrouter.ai/auth";
|
|
16
|
+
const TOKEN_URL = "https://openrouter.ai/api/v1/auth/keys";
|
|
17
|
+
const LOGIN_TIMEOUT_MS = 5 * 60 * 1000;
|
|
18
|
+
const TOKEN_EXCHANGE_TIMEOUT_MS = 30_000;
|
|
19
|
+
function getCallbackHost() {
|
|
20
|
+
return getProviderEnvValue("PI_OAUTH_CALLBACK_HOST") || "127.0.0.1";
|
|
21
|
+
}
|
|
22
|
+
function sendHtml(response, status, html) {
|
|
23
|
+
response.statusCode = status;
|
|
24
|
+
response.setHeader("content-type", "text/html; charset=utf-8");
|
|
25
|
+
response.setHeader("cache-control", "no-store");
|
|
26
|
+
response.end(html);
|
|
27
|
+
}
|
|
28
|
+
function errorDetail(body) {
|
|
29
|
+
if (typeof body.error_description === "string")
|
|
30
|
+
return body.error_description;
|
|
31
|
+
if (typeof body.message === "string")
|
|
32
|
+
return body.message;
|
|
33
|
+
if (typeof body.error === "string")
|
|
34
|
+
return body.error;
|
|
35
|
+
if (body.error && typeof body.error === "object" && !Array.isArray(body.error)) {
|
|
36
|
+
const message = body.error.message;
|
|
37
|
+
if (typeof message === "string")
|
|
38
|
+
return message;
|
|
39
|
+
}
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
async function exchangeAuthorizationCode(code, verifier, signal) {
|
|
43
|
+
if (signal?.aborted)
|
|
44
|
+
throw new Error("Login cancelled");
|
|
45
|
+
const controller = new AbortController();
|
|
46
|
+
const onAbort = () => controller.abort(signal?.reason);
|
|
47
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
48
|
+
const timeout = setTimeout(() => controller.abort(new Error("OpenRouter OAuth token exchange timed out")), TOKEN_EXCHANGE_TIMEOUT_MS);
|
|
49
|
+
let response;
|
|
50
|
+
let body = {};
|
|
51
|
+
try {
|
|
52
|
+
response = await fetch(TOKEN_URL, {
|
|
53
|
+
method: "POST",
|
|
54
|
+
headers: { accept: "application/json", "content-type": "application/json" },
|
|
55
|
+
body: JSON.stringify({ code, code_verifier: verifier, code_challenge_method: "S256" }),
|
|
56
|
+
signal: controller.signal,
|
|
57
|
+
});
|
|
58
|
+
try {
|
|
59
|
+
const parsed = (await response.json());
|
|
60
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed))
|
|
61
|
+
body = parsed;
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
if (response.ok)
|
|
65
|
+
throw new Error("OpenRouter OAuth returned invalid JSON");
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
if (signal?.aborted)
|
|
70
|
+
throw new Error("Login cancelled");
|
|
71
|
+
if (controller.signal.aborted)
|
|
72
|
+
throw new Error("OpenRouter OAuth token exchange timed out");
|
|
73
|
+
throw error;
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
clearTimeout(timeout);
|
|
77
|
+
signal?.removeEventListener("abort", onAbort);
|
|
78
|
+
}
|
|
79
|
+
if (!response.ok) {
|
|
80
|
+
const detail = errorDetail(body);
|
|
81
|
+
throw new Error(`OpenRouter OAuth key exchange failed (HTTP ${response.status})${detail ? `: ${detail}` : ""}`);
|
|
82
|
+
}
|
|
83
|
+
if (typeof body.key !== "string" || body.key.length === 0) {
|
|
84
|
+
throw new Error('OpenRouter OAuth response carries no "key"');
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
type: "oauth",
|
|
88
|
+
access: body.key,
|
|
89
|
+
refresh: "",
|
|
90
|
+
expires: Number.MAX_SAFE_INTEGER,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
async function startCallbackServer(callbackPath, verifier, signal) {
|
|
94
|
+
if (signal?.aborted)
|
|
95
|
+
throw new Error("Login cancelled");
|
|
96
|
+
const callbackHost = getCallbackHost();
|
|
97
|
+
let resolveCredential = () => { };
|
|
98
|
+
let rejectCredential = () => { };
|
|
99
|
+
const credential = new Promise((resolve, reject) => {
|
|
100
|
+
resolveCredential = resolve;
|
|
101
|
+
rejectCredential = reject;
|
|
102
|
+
});
|
|
103
|
+
let server;
|
|
104
|
+
let claimed = false;
|
|
105
|
+
let settled = false;
|
|
106
|
+
let timeout;
|
|
107
|
+
let onAbort;
|
|
108
|
+
const finish = (result) => {
|
|
109
|
+
if (settled)
|
|
110
|
+
return;
|
|
111
|
+
settled = true;
|
|
112
|
+
if (timeout)
|
|
113
|
+
clearTimeout(timeout);
|
|
114
|
+
if (onAbort)
|
|
115
|
+
signal?.removeEventListener("abort", onAbort);
|
|
116
|
+
server.close();
|
|
117
|
+
if ("credential" in result)
|
|
118
|
+
resolveCredential(result.credential);
|
|
119
|
+
else
|
|
120
|
+
rejectCredential(result.error);
|
|
121
|
+
};
|
|
122
|
+
server = createServer((request, response) => {
|
|
123
|
+
void (async () => {
|
|
124
|
+
const requestUrl = new URL(request.url ?? "/", `http://${callbackHost}`);
|
|
125
|
+
if (request.method !== "GET" || requestUrl.pathname !== callbackPath) {
|
|
126
|
+
sendHtml(response, 404, oauthErrorHtml("OAuth callback route not found."));
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (claimed || settled) {
|
|
130
|
+
sendHtml(response, 409, oauthErrorHtml("This OAuth callback has already been used."));
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const oauthError = requestUrl.searchParams.get("error");
|
|
134
|
+
if (oauthError) {
|
|
135
|
+
const description = requestUrl.searchParams.get("error_description") ?? oauthError;
|
|
136
|
+
sendHtml(response, 400, oauthErrorHtml("OpenRouter authorization was denied.", description));
|
|
137
|
+
finish({ error: new Error(`OpenRouter authorization failed: ${description}`) });
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
const code = requestUrl.searchParams.get("code");
|
|
141
|
+
if (!code) {
|
|
142
|
+
sendHtml(response, 400, oauthErrorHtml("OpenRouter returned no authorization code."));
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
claimed = true;
|
|
146
|
+
try {
|
|
147
|
+
const result = await exchangeAuthorizationCode(code, verifier, signal);
|
|
148
|
+
sendHtml(response, 200, oauthSuccessHtml("Signed in to OpenRouter. You may now close this page."));
|
|
149
|
+
finish({ credential: result });
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
const message = error instanceof Error ? error.message : "Unknown token exchange error";
|
|
153
|
+
sendHtml(response, 502, oauthErrorHtml("OpenRouter key exchange failed.", message));
|
|
154
|
+
finish({ error: error instanceof Error ? error : new Error(message) });
|
|
155
|
+
}
|
|
156
|
+
})();
|
|
157
|
+
});
|
|
158
|
+
await new Promise((resolve, reject) => {
|
|
159
|
+
server.once("error", reject);
|
|
160
|
+
server.listen(0, callbackHost, () => {
|
|
161
|
+
server.removeListener("error", reject);
|
|
162
|
+
resolve();
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
server.on("error", (error) => finish({ error }));
|
|
166
|
+
onAbort = () => finish({ error: new Error("Login cancelled") });
|
|
167
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
168
|
+
if (signal?.aborted) {
|
|
169
|
+
signal.removeEventListener("abort", onAbort);
|
|
170
|
+
server.close();
|
|
171
|
+
throw new Error("Login cancelled");
|
|
172
|
+
}
|
|
173
|
+
timeout = setTimeout(() => finish({ error: new Error("OpenRouter OAuth login timed out") }), LOGIN_TIMEOUT_MS);
|
|
174
|
+
const address = server.address();
|
|
175
|
+
if (!address || typeof address === "string") {
|
|
176
|
+
finish({ error: new Error("Could not determine the OpenRouter OAuth callback port") });
|
|
177
|
+
throw new Error("Could not determine the OpenRouter OAuth callback port");
|
|
178
|
+
}
|
|
179
|
+
return {
|
|
180
|
+
callbackUrl: `http://${callbackHost}:${address.port}${callbackPath}`,
|
|
181
|
+
credential,
|
|
182
|
+
close: () => finish({ error: new Error("Login cancelled") }),
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
async function loginOpenRouter(interaction) {
|
|
186
|
+
const { verifier, challenge } = await generatePKCE();
|
|
187
|
+
const callbackPath = `/oauth/callback/${crypto.randomUUID()}`;
|
|
188
|
+
const callback = await startCallbackServer(callbackPath, verifier, interaction.signal);
|
|
189
|
+
const authorizeUrl = new URL(AUTHORIZE_URL);
|
|
190
|
+
authorizeUrl.search = new URLSearchParams({
|
|
191
|
+
callback_url: callback.callbackUrl,
|
|
192
|
+
code_challenge: challenge,
|
|
193
|
+
code_challenge_method: "S256",
|
|
194
|
+
}).toString();
|
|
195
|
+
interaction.notify({
|
|
196
|
+
type: "progress",
|
|
197
|
+
message: `Listening for OpenRouter OAuth callback on ${callback.callbackUrl}`,
|
|
198
|
+
});
|
|
199
|
+
interaction.notify({
|
|
200
|
+
type: "auth_url",
|
|
201
|
+
url: authorizeUrl.toString(),
|
|
202
|
+
instructions: "Complete sign-in in your browser.",
|
|
203
|
+
});
|
|
204
|
+
try {
|
|
205
|
+
return await callback.credential;
|
|
206
|
+
}
|
|
207
|
+
finally {
|
|
208
|
+
callback.close();
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
export const openRouterOAuth = {
|
|
212
|
+
name: "OpenRouter OAuth",
|
|
213
|
+
loginLabel: "Sign in with OpenRouter",
|
|
214
|
+
login: loginOpenRouter,
|
|
215
|
+
async refresh(credential) {
|
|
216
|
+
return credential;
|
|
217
|
+
},
|
|
218
|
+
async toAuth(credential) {
|
|
219
|
+
return { apiKey: credential.access };
|
|
220
|
+
},
|
|
221
|
+
};
|
|
222
|
+
//# sourceMappingURL=openrouter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openrouter.js","sourceRoot":"","sources":["../../../src/auth/oauth/openrouter.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * OpenRouter OAuth PKCE flow.\n *\n * OpenRouter exchanges an authorization code for a permanent, user-controlled\n * API key rather than an expiring access/refresh token pair. The callback is\n * handled by a one-shot loopback server on an ephemeral port.\n *\n * NOTE: This module uses Node.js http.createServer for the OAuth callback server.\n * It is only intended for CLI use, not browser environments.\n */\n\nimport { createServer, type Server, type ServerResponse } from \"node:http\";\nimport { getProviderEnvValue } from \"../../utils/provider-env.ts\";\nimport type { AuthInteraction, OAuthAuth, OAuthCredential } from \"../types.ts\";\nimport { oauthErrorHtml, oauthSuccessHtml } from \"./oauth-page.ts\";\nimport { generatePKCE } from \"./pkce.ts\";\n\nconst AUTHORIZE_URL = \"https://openrouter.ai/auth\";\nconst TOKEN_URL = \"https://openrouter.ai/api/v1/auth/keys\";\nconst LOGIN_TIMEOUT_MS = 5 * 60 * 1000;\nconst TOKEN_EXCHANGE_TIMEOUT_MS = 30_000;\n\nfunction getCallbackHost(): string {\n\treturn getProviderEnvValue(\"PI_OAUTH_CALLBACK_HOST\") || \"127.0.0.1\";\n}\n\ntype JsonObject = Record<string, unknown>;\n\ntype OpenRouterCallbackServer = {\n\tcallbackUrl: string;\n\tcredential: Promise<OAuthCredential>;\n\tclose(): void;\n};\n\nfunction sendHtml(response: ServerResponse, status: number, html: string): void {\n\tresponse.statusCode = status;\n\tresponse.setHeader(\"content-type\", \"text/html; charset=utf-8\");\n\tresponse.setHeader(\"cache-control\", \"no-store\");\n\tresponse.end(html);\n}\n\nfunction errorDetail(body: JsonObject): string | undefined {\n\tif (typeof body.error_description === \"string\") return body.error_description;\n\tif (typeof body.message === \"string\") return body.message;\n\tif (typeof body.error === \"string\") return body.error;\n\tif (body.error && typeof body.error === \"object\" && !Array.isArray(body.error)) {\n\t\tconst message = (body.error as JsonObject).message;\n\t\tif (typeof message === \"string\") return message;\n\t}\n\treturn undefined;\n}\n\nasync function exchangeAuthorizationCode(\n\tcode: string,\n\tverifier: string,\n\tsignal?: AbortSignal,\n): Promise<OAuthCredential> {\n\tif (signal?.aborted) throw new Error(\"Login cancelled\");\n\tconst controller = new AbortController();\n\tconst onAbort = () => controller.abort(signal?.reason);\n\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\tconst timeout = setTimeout(\n\t\t() => controller.abort(new Error(\"OpenRouter OAuth token exchange timed out\")),\n\t\tTOKEN_EXCHANGE_TIMEOUT_MS,\n\t);\n\n\tlet response: Response;\n\tlet body: JsonObject = {};\n\ttry {\n\t\tresponse = await fetch(TOKEN_URL, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { accept: \"application/json\", \"content-type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({ code, code_verifier: verifier, code_challenge_method: \"S256\" }),\n\t\t\tsignal: controller.signal,\n\t\t});\n\t\ttry {\n\t\t\tconst parsed = (await response.json()) as unknown;\n\t\t\tif (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) body = parsed as JsonObject;\n\t\t} catch {\n\t\t\tif (response.ok) throw new Error(\"OpenRouter OAuth returned invalid JSON\");\n\t\t}\n\t} catch (error) {\n\t\tif (signal?.aborted) throw new Error(\"Login cancelled\");\n\t\tif (controller.signal.aborted) throw new Error(\"OpenRouter OAuth token exchange timed out\");\n\t\tthrow error;\n\t} finally {\n\t\tclearTimeout(timeout);\n\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t}\n\n\tif (!response.ok) {\n\t\tconst detail = errorDetail(body);\n\t\tthrow new Error(`OpenRouter OAuth key exchange failed (HTTP ${response.status})${detail ? `: ${detail}` : \"\"}`);\n\t}\n\n\tif (typeof body.key !== \"string\" || body.key.length === 0) {\n\t\tthrow new Error('OpenRouter OAuth response carries no \"key\"');\n\t}\n\n\treturn {\n\t\ttype: \"oauth\",\n\t\taccess: body.key,\n\t\trefresh: \"\",\n\t\texpires: Number.MAX_SAFE_INTEGER,\n\t};\n}\n\nasync function startCallbackServer(\n\tcallbackPath: string,\n\tverifier: string,\n\tsignal?: AbortSignal,\n): Promise<OpenRouterCallbackServer> {\n\tif (signal?.aborted) throw new Error(\"Login cancelled\");\n\tconst callbackHost = getCallbackHost();\n\tlet resolveCredential: (credential: OAuthCredential) => void = () => {};\n\tlet rejectCredential: (error: Error) => void = () => {};\n\tconst credential = new Promise<OAuthCredential>((resolve, reject) => {\n\t\tresolveCredential = resolve;\n\t\trejectCredential = reject;\n\t});\n\n\tlet server: Server;\n\tlet claimed = false;\n\tlet settled = false;\n\tlet timeout: ReturnType<typeof setTimeout> | undefined;\n\tlet onAbort: (() => void) | undefined;\n\n\tconst finish = (result: { credential: OAuthCredential } | { error: Error }): void => {\n\t\tif (settled) return;\n\t\tsettled = true;\n\t\tif (timeout) clearTimeout(timeout);\n\t\tif (onAbort) signal?.removeEventListener(\"abort\", onAbort);\n\t\tserver.close();\n\t\tif (\"credential\" in result) resolveCredential(result.credential);\n\t\telse rejectCredential(result.error);\n\t};\n\n\tserver = createServer((request, response) => {\n\t\tvoid (async () => {\n\t\t\tconst requestUrl = new URL(request.url ?? \"/\", `http://${callbackHost}`);\n\t\t\tif (request.method !== \"GET\" || requestUrl.pathname !== callbackPath) {\n\t\t\t\tsendHtml(response, 404, oauthErrorHtml(\"OAuth callback route not found.\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (claimed || settled) {\n\t\t\t\tsendHtml(response, 409, oauthErrorHtml(\"This OAuth callback has already been used.\"));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst oauthError = requestUrl.searchParams.get(\"error\");\n\t\t\tif (oauthError) {\n\t\t\t\tconst description = requestUrl.searchParams.get(\"error_description\") ?? oauthError;\n\t\t\t\tsendHtml(response, 400, oauthErrorHtml(\"OpenRouter authorization was denied.\", description));\n\t\t\t\tfinish({ error: new Error(`OpenRouter authorization failed: ${description}`) });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst code = requestUrl.searchParams.get(\"code\");\n\t\t\tif (!code) {\n\t\t\t\tsendHtml(response, 400, oauthErrorHtml(\"OpenRouter returned no authorization code.\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tclaimed = true;\n\n\t\t\ttry {\n\t\t\t\tconst result = await exchangeAuthorizationCode(code, verifier, signal);\n\t\t\t\tsendHtml(response, 200, oauthSuccessHtml(\"Signed in to OpenRouter. You may now close this page.\"));\n\t\t\t\tfinish({ credential: result });\n\t\t\t} catch (error) {\n\t\t\t\tconst message = error instanceof Error ? error.message : \"Unknown token exchange error\";\n\t\t\t\tsendHtml(response, 502, oauthErrorHtml(\"OpenRouter key exchange failed.\", message));\n\t\t\t\tfinish({ error: error instanceof Error ? error : new Error(message) });\n\t\t\t}\n\t\t})();\n\t});\n\n\tawait new Promise<void>((resolve, reject) => {\n\t\tserver.once(\"error\", reject);\n\t\tserver.listen(0, callbackHost, () => {\n\t\t\tserver.removeListener(\"error\", reject);\n\t\t\tresolve();\n\t\t});\n\t});\n\n\tserver.on(\"error\", (error) => finish({ error }));\n\tonAbort = () => finish({ error: new Error(\"Login cancelled\") });\n\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\tif (signal?.aborted) {\n\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\tserver.close();\n\t\tthrow new Error(\"Login cancelled\");\n\t}\n\ttimeout = setTimeout(() => finish({ error: new Error(\"OpenRouter OAuth login timed out\") }), LOGIN_TIMEOUT_MS);\n\n\tconst address = server.address();\n\tif (!address || typeof address === \"string\") {\n\t\tfinish({ error: new Error(\"Could not determine the OpenRouter OAuth callback port\") });\n\t\tthrow new Error(\"Could not determine the OpenRouter OAuth callback port\");\n\t}\n\n\treturn {\n\t\tcallbackUrl: `http://${callbackHost}:${address.port}${callbackPath}`,\n\t\tcredential,\n\t\tclose: () => finish({ error: new Error(\"Login cancelled\") }),\n\t};\n}\n\nasync function loginOpenRouter(interaction: AuthInteraction): Promise<OAuthCredential> {\n\tconst { verifier, challenge } = await generatePKCE();\n\tconst callbackPath = `/oauth/callback/${crypto.randomUUID()}`;\n\tconst callback = await startCallbackServer(callbackPath, verifier, interaction.signal);\n\tconst authorizeUrl = new URL(AUTHORIZE_URL);\n\tauthorizeUrl.search = new URLSearchParams({\n\t\tcallback_url: callback.callbackUrl,\n\t\tcode_challenge: challenge,\n\t\tcode_challenge_method: \"S256\",\n\t}).toString();\n\n\tinteraction.notify({\n\t\ttype: \"progress\",\n\t\tmessage: `Listening for OpenRouter OAuth callback on ${callback.callbackUrl}`,\n\t});\n\tinteraction.notify({\n\t\ttype: \"auth_url\",\n\t\turl: authorizeUrl.toString(),\n\t\tinstructions: \"Complete sign-in in your browser.\",\n\t});\n\n\ttry {\n\t\treturn await callback.credential;\n\t} finally {\n\t\tcallback.close();\n\t}\n}\n\nexport const openRouterOAuth: OAuthAuth = {\n\tname: \"OpenRouter OAuth\",\n\tloginLabel: \"Sign in with OpenRouter\",\n\tlogin: loginOpenRouter,\n\tasync refresh(credential) {\n\t\treturn credential;\n\t},\n\tasync toAuth(credential) {\n\t\treturn { apiKey: credential.access };\n\t},\n};\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PKCE utilities using Web Crypto API.
|
|
3
|
+
* Works in both Node.js 20+ and browsers.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Generate PKCE code verifier and challenge.
|
|
7
|
+
* Uses Web Crypto API for cross-platform compatibility.
|
|
8
|
+
*/
|
|
9
|
+
export declare function generatePKCE(): Promise<{
|
|
10
|
+
verifier: string;
|
|
11
|
+
challenge: string;
|
|
12
|
+
}>;
|
|
13
|
+
//# sourceMappingURL=pkce.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pkce.d.ts","sourceRoot":"","sources":["../../../src/auth/oauth/pkce.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAaH;;;GAGG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAarF"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PKCE utilities using Web Crypto API.
|
|
3
|
+
* Works in both Node.js 20+ and browsers.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Encode bytes as base64url string.
|
|
7
|
+
*/
|
|
8
|
+
function base64urlEncode(bytes) {
|
|
9
|
+
let binary = "";
|
|
10
|
+
for (const byte of bytes) {
|
|
11
|
+
binary += String.fromCharCode(byte);
|
|
12
|
+
}
|
|
13
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Generate PKCE code verifier and challenge.
|
|
17
|
+
* Uses Web Crypto API for cross-platform compatibility.
|
|
18
|
+
*/
|
|
19
|
+
export async function generatePKCE() {
|
|
20
|
+
// Generate random verifier
|
|
21
|
+
const verifierBytes = new Uint8Array(32);
|
|
22
|
+
crypto.getRandomValues(verifierBytes);
|
|
23
|
+
const verifier = base64urlEncode(verifierBytes);
|
|
24
|
+
// Compute SHA-256 challenge
|
|
25
|
+
const encoder = new TextEncoder();
|
|
26
|
+
const data = encoder.encode(verifier);
|
|
27
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
28
|
+
const challenge = base64urlEncode(new Uint8Array(hashBuffer));
|
|
29
|
+
return { verifier, challenge };
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=pkce.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pkce.js","sourceRoot":"","sources":["../../../src/auth/oauth/pkce.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,SAAS,eAAe,CAAC,KAAiB;IACzC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AAC/E,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY;IACjC,2BAA2B;IAC3B,MAAM,aAAa,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;IACzC,MAAM,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;IACtC,MAAM,QAAQ,GAAG,eAAe,CAAC,aAAa,CAAC,CAAC;IAEhD,4BAA4B;IAC5B,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACtC,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC/D,MAAM,SAAS,GAAG,eAAe,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;IAE9D,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;AAChC,CAAC","sourcesContent":["/**\n * PKCE utilities using Web Crypto API.\n * Works in both Node.js 20+ and browsers.\n */\n\n/**\n * Encode bytes as base64url string.\n */\nfunction base64urlEncode(bytes: Uint8Array): string {\n\tlet binary = \"\";\n\tfor (const byte of bytes) {\n\t\tbinary += String.fromCharCode(byte);\n\t}\n\treturn btoa(binary).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=/g, \"\");\n}\n\n/**\n * Generate PKCE code verifier and challenge.\n * Uses Web Crypto API for cross-platform compatibility.\n */\nexport async function generatePKCE(): Promise<{ verifier: string; challenge: string }> {\n\t// Generate random verifier\n\tconst verifierBytes = new Uint8Array(32);\n\tcrypto.getRandomValues(verifierBytes);\n\tconst verifier = base64urlEncode(verifierBytes);\n\n\t// Compute SHA-256 challenge\n\tconst encoder = new TextEncoder();\n\tconst data = encoder.encode(verifier);\n\tconst hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n\tconst challenge = base64urlEncode(new Uint8Array(hashBuffer));\n\n\treturn { verifier, challenge };\n}\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Radius gateway OAuth flow.
|
|
3
|
+
*
|
|
4
|
+
* Radius is a pi-messages gateway. OAuth client APIs live on the configured
|
|
5
|
+
* gateway; only the interactive browser authorization endpoint is discovered.
|
|
6
|
+
* Model catalog loading is owned by the Radius provider.
|
|
7
|
+
*
|
|
8
|
+
* NOTE: This module uses node:http for the OAuth callback server.
|
|
9
|
+
* It is only intended for CLI use, not browser environments.
|
|
10
|
+
*/
|
|
11
|
+
import type { OAuthAuth } from "../types.ts";
|
|
12
|
+
export interface RadiusOAuthOptions {
|
|
13
|
+
name: string;
|
|
14
|
+
gateway: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function createRadiusOAuth(options: RadiusOAuthOptions): OAuthAuth;
|
|
17
|
+
//# sourceMappingURL=radius.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"radius.d.ts","sourceRoot":"","sources":["../../../src/auth/oauth/radius.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAWH,OAAO,KAAK,EAAmB,SAAS,EAAmB,MAAM,aAAa,CAAC;AAgV/E,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,SAAS,CA8CxE"}
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Radius gateway OAuth flow.
|
|
3
|
+
*
|
|
4
|
+
* Radius is a pi-messages gateway. OAuth client APIs live on the configured
|
|
5
|
+
* gateway; only the interactive browser authorization endpoint is discovered.
|
|
6
|
+
* Model catalog loading is owned by the Radius provider.
|
|
7
|
+
*
|
|
8
|
+
* NOTE: This module uses node:http for the OAuth callback server.
|
|
9
|
+
* It is only intended for CLI use, not browser environments.
|
|
10
|
+
*/
|
|
11
|
+
// NEVER convert to top-level imports - breaks browser/Vite builds
|
|
12
|
+
let _http = null;
|
|
13
|
+
if (typeof process !== "undefined" && (process.versions?.node || process.versions?.bun)) {
|
|
14
|
+
import("node:http").then((m) => {
|
|
15
|
+
_http = m;
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
import { normalizeRadiusGatewayUrl } from "../../providers/radius-config.js";
|
|
19
|
+
import { pollOAuthDeviceCodeFlow } from "./device-code.js";
|
|
20
|
+
import { oauthErrorHtml, oauthSuccessHtml } from "./oauth-page.js";
|
|
21
|
+
import { generatePKCE } from "./pkce.js";
|
|
22
|
+
const CALLBACK_HOST = "127.0.0.1";
|
|
23
|
+
const CALLBACK_PORT = 1456;
|
|
24
|
+
const CALLBACK_PATH = "/oauth/callback";
|
|
25
|
+
const REDIRECT_URI = `http://${CALLBACK_HOST}:${CALLBACK_PORT}${CALLBACK_PATH}`;
|
|
26
|
+
const TOKEN_EXPIRY_SKEW_MS = 60_000;
|
|
27
|
+
const LOGIN_METHOD_BROWSER = "browser";
|
|
28
|
+
const LOGIN_METHOD_DEVICE_CODE = "device-code";
|
|
29
|
+
const OAUTH_CLIENT_ID = "pi-gateway";
|
|
30
|
+
const OAUTH_SCOPE = "gateway offline_access";
|
|
31
|
+
const OAUTH_DEVICE_CODE_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code";
|
|
32
|
+
async function loadRadiusOAuthDiscovery(gateway) {
|
|
33
|
+
const response = await fetch(new URL("/v1/oauth", gateway), {
|
|
34
|
+
headers: { accept: "application/json" },
|
|
35
|
+
});
|
|
36
|
+
if (!response.ok) {
|
|
37
|
+
throw new Error(`Could not load Radius OAuth config from ${gateway}: ${response.status} ${await response.text()}`);
|
|
38
|
+
}
|
|
39
|
+
const discovery = (await response.json());
|
|
40
|
+
if (typeof discovery.authorizationEndpoint !== "string") {
|
|
41
|
+
throw new Error(`Invalid Radius OAuth config from ${gateway}`);
|
|
42
|
+
}
|
|
43
|
+
return { authorizationEndpoint: discovery.authorizationEndpoint };
|
|
44
|
+
}
|
|
45
|
+
class OAuthResponseError extends Error {
|
|
46
|
+
constructor(status, oauthError, description, message) {
|
|
47
|
+
const detail = oauthError
|
|
48
|
+
? description
|
|
49
|
+
? `${oauthError}: ${description}`
|
|
50
|
+
: oauthError
|
|
51
|
+
: description || String(status);
|
|
52
|
+
super(`${message}: ${detail}`);
|
|
53
|
+
this.status = status;
|
|
54
|
+
this.oauthError = oauthError;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async function readOAuthResponseError(response, message) {
|
|
58
|
+
const text = await response.text().catch(() => "");
|
|
59
|
+
let oauthError;
|
|
60
|
+
let description;
|
|
61
|
+
if (text) {
|
|
62
|
+
try {
|
|
63
|
+
const data = JSON.parse(text);
|
|
64
|
+
oauthError = typeof data.error === "string" ? data.error : undefined;
|
|
65
|
+
description = typeof data.error_description === "string" ? data.error_description : undefined;
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
description = text;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return new OAuthResponseError(response.status, oauthError, description, message);
|
|
72
|
+
}
|
|
73
|
+
async function requestOAuthToken(gateway, body, signal) {
|
|
74
|
+
let response;
|
|
75
|
+
try {
|
|
76
|
+
response = await fetch(new URL("/v1/oauth/token", gateway), {
|
|
77
|
+
method: "POST",
|
|
78
|
+
headers: { accept: "application/json", "content-type": "application/x-www-form-urlencoded" },
|
|
79
|
+
body,
|
|
80
|
+
signal,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
if (signal?.aborted) {
|
|
85
|
+
throw new Error("Login cancelled");
|
|
86
|
+
}
|
|
87
|
+
throw error;
|
|
88
|
+
}
|
|
89
|
+
if (!response.ok) {
|
|
90
|
+
throw await readOAuthResponseError(response, "Radius OAuth token request failed");
|
|
91
|
+
}
|
|
92
|
+
const data = (await response.json());
|
|
93
|
+
return {
|
|
94
|
+
type: "oauth",
|
|
95
|
+
access: data.access_token,
|
|
96
|
+
refresh: data.refresh_token,
|
|
97
|
+
expires: Date.now() + data.expires_in * 1000 - TOKEN_EXPIRY_SKEW_MS,
|
|
98
|
+
scope: data.scope,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function startOAuthCallbackServer(expectedState, signal) {
|
|
102
|
+
if (!_http) {
|
|
103
|
+
throw new Error("Radius OAuth is only available in Node.js environments");
|
|
104
|
+
}
|
|
105
|
+
let settle = () => { };
|
|
106
|
+
let settled = false;
|
|
107
|
+
const wait = new Promise((resolve) => {
|
|
108
|
+
settle = resolve;
|
|
109
|
+
});
|
|
110
|
+
const finish = (code) => {
|
|
111
|
+
if (settled) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
settled = true;
|
|
115
|
+
signal?.removeEventListener("abort", onAbort);
|
|
116
|
+
settle(code);
|
|
117
|
+
};
|
|
118
|
+
const onAbort = () => finish(null);
|
|
119
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
120
|
+
const sendPage = (response, status, html) => {
|
|
121
|
+
response.statusCode = status;
|
|
122
|
+
response.setHeader("content-type", "text/html; charset=utf-8");
|
|
123
|
+
response.end(html);
|
|
124
|
+
};
|
|
125
|
+
const server = _http.createServer((request, response) => {
|
|
126
|
+
const url = new URL(request.url ?? "/", REDIRECT_URI);
|
|
127
|
+
if (url.pathname !== CALLBACK_PATH) {
|
|
128
|
+
sendPage(response, 404, oauthErrorHtml("Callback route not found."));
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (url.searchParams.get("state") !== expectedState) {
|
|
132
|
+
sendPage(response, 400, oauthErrorHtml("OAuth state mismatch."));
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const error = url.searchParams.get("error");
|
|
136
|
+
if (error) {
|
|
137
|
+
sendPage(response, 400, oauthErrorHtml(url.searchParams.get("error_description") ?? error));
|
|
138
|
+
finish(null);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const code = url.searchParams.get("code");
|
|
142
|
+
if (!code) {
|
|
143
|
+
sendPage(response, 400, oauthErrorHtml("Missing authorization code."));
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
sendPage(response, 200, oauthSuccessHtml("Signed in to Radius. You may now close this page."));
|
|
147
|
+
finish(code);
|
|
148
|
+
});
|
|
149
|
+
return new Promise((resolve) => {
|
|
150
|
+
server
|
|
151
|
+
.listen(CALLBACK_PORT, CALLBACK_HOST, () => {
|
|
152
|
+
resolve({
|
|
153
|
+
waitForCode: () => wait,
|
|
154
|
+
close: () => {
|
|
155
|
+
finish(null);
|
|
156
|
+
server.close();
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
})
|
|
160
|
+
.once("error", () => {
|
|
161
|
+
finish(null);
|
|
162
|
+
resolve({ waitForCode: async () => null, close: () => { } });
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
async function loginWithBrowser(gateway, authorizationEndpoint, interaction) {
|
|
167
|
+
const { verifier, challenge } = await generatePKCE();
|
|
168
|
+
const state = crypto.randomUUID();
|
|
169
|
+
const authorizeUrl = new URL(authorizationEndpoint);
|
|
170
|
+
authorizeUrl.search = new URLSearchParams({
|
|
171
|
+
response_type: "code",
|
|
172
|
+
client_id: OAUTH_CLIENT_ID,
|
|
173
|
+
redirect_uri: REDIRECT_URI,
|
|
174
|
+
scope: OAUTH_SCOPE,
|
|
175
|
+
code_challenge: challenge,
|
|
176
|
+
code_challenge_method: "S256",
|
|
177
|
+
handoff: "url",
|
|
178
|
+
state,
|
|
179
|
+
}).toString();
|
|
180
|
+
const callbackServer = await startOAuthCallbackServer(state, interaction.signal);
|
|
181
|
+
interaction.notify({ type: "progress", message: `Listening for OAuth callback on ${REDIRECT_URI}` });
|
|
182
|
+
interaction.notify({
|
|
183
|
+
type: "auth_url",
|
|
184
|
+
url: authorizeUrl.toString(),
|
|
185
|
+
instructions: "Continue in your browser.",
|
|
186
|
+
});
|
|
187
|
+
try {
|
|
188
|
+
const code = await callbackServer.waitForCode();
|
|
189
|
+
if (!code) {
|
|
190
|
+
if (interaction.signal?.aborted) {
|
|
191
|
+
throw new Error("Login cancelled");
|
|
192
|
+
}
|
|
193
|
+
throw new Error("OAuth callback did not complete.");
|
|
194
|
+
}
|
|
195
|
+
return await requestOAuthToken(gateway, new URLSearchParams({
|
|
196
|
+
grant_type: "authorization_code",
|
|
197
|
+
client_id: OAUTH_CLIENT_ID,
|
|
198
|
+
redirect_uri: REDIRECT_URI,
|
|
199
|
+
code,
|
|
200
|
+
code_verifier: verifier,
|
|
201
|
+
}), interaction.signal);
|
|
202
|
+
}
|
|
203
|
+
finally {
|
|
204
|
+
callbackServer.close();
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
async function requestDeviceAuthorization(gateway, signal) {
|
|
208
|
+
let response;
|
|
209
|
+
try {
|
|
210
|
+
response = await fetch(new URL("/v1/oauth/device", gateway), {
|
|
211
|
+
method: "POST",
|
|
212
|
+
headers: { accept: "application/json", "content-type": "application/x-www-form-urlencoded" },
|
|
213
|
+
body: new URLSearchParams({ client_id: OAUTH_CLIENT_ID, scope: OAUTH_SCOPE }),
|
|
214
|
+
signal,
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
if (signal?.aborted) {
|
|
219
|
+
throw new Error("Login cancelled");
|
|
220
|
+
}
|
|
221
|
+
throw error;
|
|
222
|
+
}
|
|
223
|
+
if (!response.ok) {
|
|
224
|
+
throw await readOAuthResponseError(response, "Radius OAuth device authorization failed");
|
|
225
|
+
}
|
|
226
|
+
const data = (await response.json());
|
|
227
|
+
if (!data.device_code || !data.user_code || !data.verification_uri || !data.expires_in) {
|
|
228
|
+
throw new Error("Radius OAuth device authorization response is missing required fields");
|
|
229
|
+
}
|
|
230
|
+
return {
|
|
231
|
+
device_code: data.device_code,
|
|
232
|
+
user_code: data.user_code,
|
|
233
|
+
verification_uri: data.verification_uri,
|
|
234
|
+
expires_in: data.expires_in,
|
|
235
|
+
interval: data.interval,
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
async function loginWithDeviceCode(gateway, interaction) {
|
|
239
|
+
const device = await requestDeviceAuthorization(gateway, interaction.signal);
|
|
240
|
+
interaction.notify({
|
|
241
|
+
type: "device_code",
|
|
242
|
+
userCode: device.user_code,
|
|
243
|
+
verificationUri: device.verification_uri,
|
|
244
|
+
intervalSeconds: device.interval,
|
|
245
|
+
expiresInSeconds: device.expires_in,
|
|
246
|
+
});
|
|
247
|
+
return pollOAuthDeviceCodeFlow({
|
|
248
|
+
intervalSeconds: device.interval,
|
|
249
|
+
expiresInSeconds: device.expires_in,
|
|
250
|
+
signal: interaction.signal,
|
|
251
|
+
poll: async () => {
|
|
252
|
+
try {
|
|
253
|
+
const credentials = await requestOAuthToken(gateway, new URLSearchParams({
|
|
254
|
+
grant_type: OAUTH_DEVICE_CODE_GRANT_TYPE,
|
|
255
|
+
client_id: OAUTH_CLIENT_ID,
|
|
256
|
+
device_code: device.device_code,
|
|
257
|
+
}), interaction.signal);
|
|
258
|
+
return { status: "complete", value: credentials };
|
|
259
|
+
}
|
|
260
|
+
catch (error) {
|
|
261
|
+
if (!(error instanceof OAuthResponseError)) {
|
|
262
|
+
throw error;
|
|
263
|
+
}
|
|
264
|
+
switch (error.oauthError) {
|
|
265
|
+
case "authorization_pending":
|
|
266
|
+
return { status: "pending" };
|
|
267
|
+
case "slow_down":
|
|
268
|
+
return { status: "slow_down" };
|
|
269
|
+
case "expired_token":
|
|
270
|
+
return { status: "failed", message: "Device authorization expired." };
|
|
271
|
+
case "access_denied":
|
|
272
|
+
return { status: "failed", message: "Device authorization was denied." };
|
|
273
|
+
default:
|
|
274
|
+
throw error;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
export function createRadiusOAuth(options) {
|
|
281
|
+
const gateway = normalizeRadiusGatewayUrl(options.gateway);
|
|
282
|
+
return {
|
|
283
|
+
name: options.name,
|
|
284
|
+
async login(interaction) {
|
|
285
|
+
const loginMethod = await interaction.prompt({
|
|
286
|
+
type: "select",
|
|
287
|
+
message: `Sign in to ${options.name}:`,
|
|
288
|
+
options: [
|
|
289
|
+
{ id: LOGIN_METHOD_BROWSER, label: "Sign in with browser (recommended)" },
|
|
290
|
+
{
|
|
291
|
+
id: LOGIN_METHOD_DEVICE_CODE,
|
|
292
|
+
label: "Sign in with device code (when signing in from another device)",
|
|
293
|
+
},
|
|
294
|
+
],
|
|
295
|
+
});
|
|
296
|
+
if (loginMethod === LOGIN_METHOD_DEVICE_CODE) {
|
|
297
|
+
return loginWithDeviceCode(gateway, interaction);
|
|
298
|
+
}
|
|
299
|
+
if (loginMethod === LOGIN_METHOD_BROWSER) {
|
|
300
|
+
const discovery = await loadRadiusOAuthDiscovery(gateway);
|
|
301
|
+
return loginWithBrowser(gateway, discovery.authorizationEndpoint, interaction);
|
|
302
|
+
}
|
|
303
|
+
throw new Error(`Unknown ${options.name} sign-in method: ${loginMethod}`);
|
|
304
|
+
},
|
|
305
|
+
async refresh(credential, signal) {
|
|
306
|
+
const refreshed = await requestOAuthToken(gateway, new URLSearchParams({
|
|
307
|
+
grant_type: "refresh_token",
|
|
308
|
+
client_id: OAUTH_CLIENT_ID,
|
|
309
|
+
refresh_token: credential.refresh,
|
|
310
|
+
}), signal);
|
|
311
|
+
return refreshed;
|
|
312
|
+
},
|
|
313
|
+
async toAuth(credential) {
|
|
314
|
+
return { apiKey: credential.access };
|
|
315
|
+
},
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
//# sourceMappingURL=radius.js.map
|