@draht/ai 2026.7.13-1 → 2026.7.30
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/dist/api/anthropic-messages.d.ts.map +1 -1
- package/dist/api/anthropic-messages.js +129 -57
- package/dist/api/anthropic-messages.js.map +1 -1
- package/dist/api/azure-openai-responses.d.ts.map +1 -1
- package/dist/api/azure-openai-responses.js +26 -9
- package/dist/api/azure-openai-responses.js.map +1 -1
- package/dist/api/bedrock-converse-stream.d.ts.map +1 -1
- package/dist/api/bedrock-converse-stream.js +54 -23
- package/dist/api/bedrock-converse-stream.js.map +1 -1
- 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 +100 -0
- package/dist/api/constrained-sampling.js.map +1 -0
- package/dist/api/google-generative-ai.d.ts.map +1 -1
- package/dist/api/google-generative-ai.js +19 -13
- package/dist/api/google-generative-ai.js.map +1 -1
- package/dist/api/google-shared.d.ts +4 -3
- package/dist/api/google-shared.d.ts.map +1 -1
- package/dist/api/google-shared.js +17 -3
- package/dist/api/google-shared.js.map +1 -1
- package/dist/api/google-vertex.d.ts.map +1 -1
- package/dist/api/google-vertex.js +19 -13
- package/dist/api/google-vertex.js.map +1 -1
- package/dist/api/lazy.d.ts.map +1 -1
- package/dist/api/lazy.js +9 -10
- package/dist/api/lazy.js.map +1 -1
- package/dist/api/mistral-conversations.d.ts.map +1 -1
- package/dist/api/mistral-conversations.js +32 -19
- package/dist/api/mistral-conversations.js.map +1 -1
- package/dist/api/openai-codex-responses.d.ts +1 -0
- package/dist/api/openai-codex-responses.d.ts.map +1 -1
- package/dist/api/openai-codex-responses.js +88 -38
- package/dist/api/openai-codex-responses.js.map +1 -1
- package/dist/api/openai-completions.d.ts +8 -8
- package/dist/api/openai-completions.d.ts.map +1 -1
- package/dist/api/openai-completions.js +216 -46
- package/dist/api/openai-completions.js.map +1 -1
- package/dist/api/openai-responses-shared.d.ts +8 -1
- package/dist/api/openai-responses-shared.d.ts.map +1 -1
- package/dist/api/openai-responses-shared.js +233 -67
- package/dist/api/openai-responses-shared.js.map +1 -1
- package/dist/api/openai-responses.d.ts +1 -0
- package/dist/api/openai-responses.d.ts.map +1 -1
- package/dist/api/openai-responses.js +60 -16
- package/dist/api/openai-responses.js.map +1 -1
- package/dist/api/openrouter-images.d.ts.map +1 -1
- package/dist/api/openrouter-images.js +11 -5
- package/dist/api/openrouter-images.js.map +1 -1
- 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.map +1 -1
- package/dist/api/simple-options.js +1 -0
- package/dist/api/simple-options.js.map +1 -1
- package/dist/auth/credential-store.d.ts +2 -1
- package/dist/auth/credential-store.d.ts.map +1 -1
- package/dist/auth/credential-store.js +3 -0
- package/dist/auth/credential-store.js.map +1 -1
- package/dist/auth/helpers.d.ts +1 -0
- package/dist/auth/helpers.d.ts.map +1 -1
- package/dist/auth/helpers.js +7 -5
- package/dist/auth/helpers.js.map +1 -1
- package/dist/auth/oauth/anthropic.d.ts +9 -0
- package/dist/auth/oauth/anthropic.d.ts.map +1 -0
- package/dist/{utils → auth}/oauth/anthropic.js +51 -116
- package/dist/auth/oauth/anthropic.js.map +1 -0
- package/dist/auth/oauth/device-code.d.ts.map +1 -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/{utils → auth}/oauth/github-copilot.js +18 -77
- package/dist/auth/oauth/github-copilot.js.map +1 -0
- package/dist/auth/oauth/google-antigravity.d.ts +21 -0
- package/dist/auth/oauth/google-antigravity.d.ts.map +1 -0
- package/dist/{utils → auth}/oauth/google-antigravity.js +79 -79
- package/dist/auth/oauth/google-antigravity.js.map +1 -0
- package/dist/auth/oauth/google-gemini-cli.d.ts +21 -0
- package/dist/auth/oauth/google-gemini-cli.d.ts.map +1 -0
- package/dist/{utils → auth}/oauth/google-gemini-cli.js +79 -79
- package/dist/auth/oauth/google-gemini-cli.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 +33 -0
- package/dist/auth/oauth/load.d.ts.map +1 -0
- package/dist/auth/oauth/load.js +74 -0
- package/dist/auth/oauth/load.js.map +1 -0
- package/dist/auth/oauth/oauth-page.d.ts.map +1 -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/{utils → auth}/oauth/openai-codex.js +61 -155
- package/dist/auth/oauth/openai-codex.js.map +1 -0
- package/dist/auth/oauth/opencode-go.d.ts +14 -0
- package/dist/auth/oauth/opencode-go.d.ts.map +1 -0
- package/dist/auth/oauth/opencode-go.js +41 -0
- package/dist/auth/oauth/opencode-go.js.map +1 -0
- package/dist/auth/oauth/openrouter.d.ts +15 -0
- package/dist/auth/oauth/openrouter.d.ts.map +1 -0
- package/dist/auth/oauth/openrouter.js +277 -0
- package/dist/auth/oauth/openrouter.js.map +1 -0
- package/dist/auth/oauth/pkce.d.ts.map +1 -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 +17 -0
- package/dist/auth/oauth/xai.d.ts.map +1 -0
- package/dist/{utils → auth}/oauth/xai.js +54 -89
- package/dist/auth/oauth/xai.js.map +1 -0
- package/dist/auth/resolve.d.ts +4 -4
- package/dist/auth/resolve.d.ts.map +1 -1
- package/dist/auth/resolve.js +36 -16
- package/dist/auth/resolve.js.map +1 -1
- package/dist/auth/types.d.ts +49 -10
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/auth/types.js.map +1 -1
- package/dist/bun-oauth.d.ts +3 -0
- package/dist/bun-oauth.d.ts.map +1 -0
- package/dist/bun-oauth.js +27 -0
- package/dist/bun-oauth.js.map +1 -0
- package/dist/cli.js +58 -76
- package/dist/cli.js.map +1 -1
- package/dist/compat/extension-oauth-types.d.ts +39 -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 +2 -0
- package/dist/compat.d.ts.map +1 -1
- package/dist/compat.js +25 -8
- package/dist/compat.js.map +1 -1
- package/dist/env-api-keys.d.ts +3 -0
- package/dist/env-api-keys.d.ts.map +1 -1
- package/dist/env-api-keys.js +12 -3
- package/dist/env-api-keys.js.map +1 -1
- package/dist/image-models.generated.d.ts +75 -0
- package/dist/image-models.generated.d.ts.map +1 -1
- package/dist/image-models.generated.js +251 -176
- package/dist/image-models.generated.js.map +1 -1
- package/dist/images-models.d.ts +4 -2
- package/dist/images-models.d.ts.map +1 -1
- package/dist/images-models.js +5 -4
- package/dist/images-models.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- 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/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 +66 -30
- package/dist/models.d.ts.map +1 -1
- package/dist/models.generated.d.ts +74 -21970
- package/dist/models.generated.d.ts.map +1 -1
- package/dist/models.generated.js +4 -0
- package/dist/models.generated.js.map +1 -1
- package/dist/models.js +213 -29
- package/dist/models.js.map +1 -1
- package/dist/oauth.d.ts +2 -1
- package/dist/oauth.d.ts.map +1 -1
- package/dist/oauth.js +1 -1
- package/dist/oauth.js.map +1 -1
- package/dist/providers/all.d.ts +13 -6
- package/dist/providers/all.d.ts.map +1 -1
- package/dist/providers/all.js +13 -0
- package/dist/providers/all.js.map +1 -1
- package/dist/providers/amazon-bedrock.d.ts.map +1 -1
- package/dist/providers/amazon-bedrock.js +54 -8
- package/dist/providers/amazon-bedrock.js.map +1 -1
- package/dist/providers/amazon-bedrock.models.d.ts +3 -1931
- package/dist/providers/amazon-bedrock.models.d.ts.map +1 -1
- package/dist/providers/amazon-bedrock.models.js +3 -1838
- package/dist/providers/amazon-bedrock.models.js.map +1 -1
- package/dist/providers/ant-ling.models.d.ts +3 -85
- package/dist/providers/ant-ling.models.d.ts.map +1 -1
- package/dist/providers/ant-ling.models.js +3 -57
- package/dist/providers/ant-ling.models.js.map +1 -1
- package/dist/providers/anthropic.d.ts.map +1 -1
- package/dist/providers/anthropic.js +31 -4
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/anthropic.models.d.ts +3 -283
- package/dist/providers/anthropic.models.d.ts.map +1 -1
- package/dist/providers/anthropic.models.js +3 -252
- package/dist/providers/anthropic.models.js.map +1 -1
- package/dist/providers/azure-openai-responses.models.d.ts +3 -886
- package/dist/providers/azure-openai-responses.models.d.ts.map +1 -1
- package/dist/providers/azure-openai-responses.models.js +3 -811
- package/dist/providers/azure-openai-responses.models.js.map +1 -1
- package/dist/providers/cerebras.models.d.ts +3 -65
- package/dist/providers/cerebras.models.d.ts.map +1 -1
- package/dist/providers/cerebras.models.js +3 -56
- package/dist/providers/cerebras.models.js.map +1 -1
- package/dist/providers/cloudflare-ai-gateway.d.ts.map +1 -1
- package/dist/providers/cloudflare-ai-gateway.js +4 -3
- package/dist/providers/cloudflare-ai-gateway.js.map +1 -1
- package/dist/providers/cloudflare-ai-gateway.models.d.ts +3 -887
- package/dist/providers/cloudflare-ai-gateway.models.d.ts.map +1 -1
- package/dist/providers/cloudflare-ai-gateway.models.js +3 -755
- package/dist/providers/cloudflare-ai-gateway.models.js.map +1 -1
- package/dist/providers/cloudflare-auth.d.ts.map +1 -1
- package/dist/providers/cloudflare-auth.js +22 -26
- package/dist/providers/cloudflare-auth.js.map +1 -1
- 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.map +1 -1
- package/dist/providers/cloudflare-workers-ai.js +2 -1
- package/dist/providers/cloudflare-workers-ai.js.map +1 -1
- package/dist/providers/cloudflare-workers-ai.models.d.ts +3 -301
- package/dist/providers/cloudflare-workers-ai.models.d.ts.map +1 -1
- package/dist/providers/cloudflare-workers-ai.models.js +3 -236
- package/dist/providers/cloudflare-workers-ai.models.js.map +1 -1
- package/dist/providers/data/.manifest.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.models.d.ts +3 -62
- package/dist/providers/deepseek.models.d.ts.map +1 -1
- package/dist/providers/deepseek.models.js +3 -40
- package/dist/providers/deepseek.models.js.map +1 -1
- package/dist/providers/faux.d.ts.map +1 -1
- package/dist/providers/faux.js +4 -1
- package/dist/providers/faux.js.map +1 -1
- package/dist/providers/fireworks.models.d.ts +3 -380
- package/dist/providers/fireworks.models.d.ts.map +1 -1
- package/dist/providers/fireworks.models.js +3 -292
- package/dist/providers/fireworks.models.js.map +1 -1
- package/dist/providers/github-copilot.d.ts.map +1 -1
- package/dist/providers/github-copilot.js +11 -1
- package/dist/providers/github-copilot.js.map +1 -1
- package/dist/providers/github-copilot.models.d.ts +3 -790
- package/dist/providers/github-copilot.models.d.ts.map +1 -1
- package/dist/providers/github-copilot.models.js +3 -538
- package/dist/providers/github-copilot.models.js.map +1 -1
- package/dist/providers/google-vertex.d.ts.map +1 -1
- package/dist/providers/google-vertex.js +56 -5
- package/dist/providers/google-vertex.js.map +1 -1
- package/dist/providers/google-vertex.models.d.ts +3 -201
- package/dist/providers/google-vertex.models.d.ts.map +1 -1
- package/dist/providers/google-vertex.models.js +3 -179
- package/dist/providers/google-vertex.models.js.map +1 -1
- package/dist/providers/google.models.d.ts +3 -327
- package/dist/providers/google.models.d.ts.map +1 -1
- package/dist/providers/google.models.js +3 -285
- package/dist/providers/google.models.js.map +1 -1
- package/dist/providers/groq.models.d.ts +3 -127
- package/dist/providers/groq.models.d.ts.map +1 -1
- package/dist/providers/groq.models.js +3 -122
- package/dist/providers/groq.models.js.map +1 -1
- package/dist/providers/huggingface.models.d.ts +3 -982
- package/dist/providers/huggingface.models.d.ts.map +1 -1
- package/dist/providers/huggingface.models.js +3 -884
- package/dist/providers/huggingface.models.js.map +1 -1
- package/dist/providers/kimi-coding.d.ts.map +1 -1
- package/dist/providers/kimi-coding.js +10 -2
- package/dist/providers/kimi-coding.js.map +1 -1
- package/dist/providers/kimi-coding.models.d.ts +3 -62
- package/dist/providers/kimi-coding.models.d.ts.map +1 -1
- package/dist/providers/kimi-coding.models.js +3 -56
- package/dist/providers/kimi-coding.models.js.map +1 -1
- package/dist/providers/minimax-cn.models.d.ts +3 -53
- package/dist/providers/minimax-cn.models.d.ts.map +1 -1
- package/dist/providers/minimax-cn.models.js +3 -53
- package/dist/providers/minimax-cn.models.js.map +1 -1
- package/dist/providers/minimax.models.d.ts +3 -53
- package/dist/providers/minimax.models.d.ts.map +1 -1
- package/dist/providers/minimax.models.js +3 -53
- package/dist/providers/minimax.models.js.map +1 -1
- package/dist/providers/mistral.models.d.ts +3 -512
- package/dist/providers/mistral.models.d.ts.map +1 -1
- package/dist/providers/mistral.models.js +3 -512
- package/dist/providers/mistral.models.js.map +1 -1
- package/dist/providers/moonshotai-cn.models.d.ts +3 -233
- package/dist/providers/moonshotai-cn.models.d.ts.map +1 -1
- package/dist/providers/moonshotai-cn.models.js +3 -166
- package/dist/providers/moonshotai-cn.models.js.map +1 -1
- package/dist/providers/moonshotai.models.d.ts +3 -233
- package/dist/providers/moonshotai.models.d.ts.map +1 -1
- package/dist/providers/moonshotai.models.js +3 -166
- package/dist/providers/moonshotai.models.js.map +1 -1
- package/dist/providers/nvidia.models.d.ts +3 -562
- package/dist/providers/nvidia.models.d.ts.map +1 -1
- package/dist/providers/nvidia.models.js +3 -382
- package/dist/providers/nvidia.models.js.map +1 -1
- package/dist/providers/openai-codex.d.ts.map +1 -1
- package/dist/providers/openai-codex.js +1 -1
- package/dist/providers/openai-codex.js.map +1 -1
- package/dist/providers/openai-codex.models.d.ts +3 -187
- package/dist/providers/openai-codex.models.d.ts.map +1 -1
- package/dist/providers/openai-codex.models.js +3 -133
- package/dist/providers/openai-codex.models.js.map +1 -1
- package/dist/providers/openai.models.d.ts +3 -936
- package/dist/providers/openai.models.d.ts.map +1 -1
- package/dist/providers/openai.models.js +3 -818
- package/dist/providers/openai.models.js.map +1 -1
- package/dist/providers/opencode-go.d.ts +1 -1
- package/dist/providers/opencode-go.d.ts.map +1 -1
- package/dist/providers/opencode-go.js +15 -3
- package/dist/providers/opencode-go.js.map +1 -1
- package/dist/providers/opencode-go.models.d.ts +3 -308
- package/dist/providers/opencode-go.models.d.ts.map +1 -1
- package/dist/providers/opencode-go.models.js +3 -237
- package/dist/providers/opencode-go.models.js.map +1 -1
- package/dist/providers/opencode.models.d.ts +3 -1183
- package/dist/providers/opencode.models.d.ts.map +1 -1
- package/dist/providers/opencode.models.js +3 -977
- package/dist/providers/opencode.models.js.map +1 -1
- package/dist/providers/openrouter-images.d.ts.map +1 -1
- package/dist/providers/openrouter-images.js +10 -2
- package/dist/providers/openrouter-images.js.map +1 -1
- package/dist/providers/openrouter.d.ts.map +1 -1
- package/dist/providers/openrouter.js +10 -2
- package/dist/providers/openrouter.js.map +1 -1
- package/dist/providers/openrouter.models.d.ts +3 -5684
- package/dist/providers/openrouter.models.d.ts.map +1 -1
- package/dist/providers/openrouter.models.js +3 -4855
- package/dist/providers/openrouter.models.js.map +1 -1
- 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/together.models.d.ts +3 -597
- package/dist/providers/together.models.d.ts.map +1 -1
- package/dist/providers/together.models.js +3 -377
- package/dist/providers/together.models.js.map +1 -1
- package/dist/providers/vercel-ai-gateway.models.d.ts +3 -3255
- package/dist/providers/vercel-ai-gateway.models.d.ts.map +1 -1
- package/dist/providers/vercel-ai-gateway.models.js +3 -3191
- package/dist/providers/vercel-ai-gateway.models.js.map +1 -1
- package/dist/providers/xai.d.ts +1 -1
- package/dist/providers/xai.d.ts.map +1 -1
- package/dist/providers/xai.js +11 -3
- package/dist/providers/xai.js.map +1 -1
- package/dist/providers/xai.models.d.ts +3 -178
- package/dist/providers/xai.models.d.ts.map +1 -1
- package/dist/providers/xai.models.js +3 -146
- package/dist/providers/xai.models.js.map +1 -1
- package/dist/providers/xiaomi-token-plan-ams.models.d.ts +3 -65
- package/dist/providers/xiaomi-token-plan-ams.models.d.ts.map +1 -1
- package/dist/providers/xiaomi-token-plan-ams.models.js +3 -56
- package/dist/providers/xiaomi-token-plan-ams.models.js.map +1 -1
- package/dist/providers/xiaomi-token-plan-cn.models.d.ts +3 -65
- package/dist/providers/xiaomi-token-plan-cn.models.d.ts.map +1 -1
- package/dist/providers/xiaomi-token-plan-cn.models.js +3 -56
- package/dist/providers/xiaomi-token-plan-cn.models.js.map +1 -1
- package/dist/providers/xiaomi-token-plan-sgp.models.d.ts +3 -65
- package/dist/providers/xiaomi-token-plan-sgp.models.d.ts.map +1 -1
- package/dist/providers/xiaomi-token-plan-sgp.models.js +3 -56
- package/dist/providers/xiaomi-token-plan-sgp.models.js.map +1 -1
- package/dist/providers/xiaomi.models.d.ts +3 -128
- package/dist/providers/xiaomi.models.d.ts.map +1 -1
- package/dist/providers/xiaomi.models.js +3 -110
- package/dist/providers/xiaomi.models.js.map +1 -1
- package/dist/providers/zai-coding-cn.models.d.ts +3 -152
- package/dist/providers/zai-coding-cn.models.d.ts.map +1 -1
- package/dist/providers/zai-coding-cn.models.js +3 -111
- package/dist/providers/zai-coding-cn.models.js.map +1 -1
- package/dist/providers/zai.models.d.ts +3 -152
- package/dist/providers/zai.models.d.ts.map +1 -1
- package/dist/providers/zai.models.js +3 -111
- package/dist/providers/zai.models.js.map +1 -1
- package/dist/types.d.ts +74 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- 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/error-body.d.ts.map +1 -1
- package/dist/utils/error-body.js +8 -3
- package/dist/utils/error-body.js.map +1 -1
- package/dist/utils/estimate.d.ts.map +1 -1
- package/dist/utils/estimate.js +18 -5
- package/dist/utils/estimate.js.map +1 -1
- package/dist/utils/overflow.d.ts +1 -0
- package/dist/utils/overflow.d.ts.map +1 -1
- package/dist/utils/overflow.js +3 -0
- package/dist/utils/overflow.js.map +1 -1
- 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 +41 -0
- package/dist/utils/retry.d.ts.map +1 -1
- package/dist/utils/retry.js +83 -0
- package/dist/utils/retry.js.map +1 -1
- 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/uuid.d.ts +3 -0
- package/dist/utils/uuid.d.ts.map +1 -0
- package/dist/utils/uuid.js +47 -0
- package/dist/utils/uuid.js.map +1 -0
- package/package.json +12 -6
- package/dist/utils/oauth/anthropic.d.ts +0 -27
- package/dist/utils/oauth/anthropic.d.ts.map +0 -1
- package/dist/utils/oauth/anthropic.js.map +0 -1
- package/dist/utils/oauth/device-code.d.ts.map +0 -1
- package/dist/utils/oauth/device-code.js.map +0 -1
- package/dist/utils/oauth/github-copilot.d.ts +0 -32
- package/dist/utils/oauth/github-copilot.d.ts.map +0 -1
- package/dist/utils/oauth/github-copilot.js.map +0 -1
- package/dist/utils/oauth/google-antigravity.d.ts +0 -26
- package/dist/utils/oauth/google-antigravity.d.ts.map +0 -1
- package/dist/utils/oauth/google-antigravity.js.map +0 -1
- package/dist/utils/oauth/google-gemini-cli.d.ts +0 -26
- package/dist/utils/oauth/google-gemini-cli.d.ts.map +0 -1
- package/dist/utils/oauth/google-gemini-cli.js.map +0 -1
- package/dist/utils/oauth/index.d.ts +0 -60
- package/dist/utils/oauth/index.d.ts.map +0 -1
- package/dist/utils/oauth/index.js +0 -130
- package/dist/utils/oauth/index.js.map +0 -1
- package/dist/utils/oauth/load.d.ts +0 -6
- package/dist/utils/oauth/load.d.ts.map +0 -1
- package/dist/utils/oauth/load.js +0 -23
- package/dist/utils/oauth/load.js.map +0 -1
- package/dist/utils/oauth/oauth-page.d.ts.map +0 -1
- package/dist/utils/oauth/oauth-page.js.map +0 -1
- package/dist/utils/oauth/openai-codex.d.ts +0 -45
- package/dist/utils/oauth/openai-codex.d.ts.map +0 -1
- package/dist/utils/oauth/openai-codex.js.map +0 -1
- package/dist/utils/oauth/opencode-go.d.ts +0 -23
- package/dist/utils/oauth/opencode-go.d.ts.map +0 -1
- package/dist/utils/oauth/opencode-go.js +0 -46
- package/dist/utils/oauth/opencode-go.js.map +0 -1
- package/dist/utils/oauth/pkce.d.ts.map +0 -1
- package/dist/utils/oauth/pkce.js.map +0 -1
- package/dist/utils/oauth/types.d.ts +0 -64
- package/dist/utils/oauth/types.d.ts.map +0 -1
- package/dist/utils/oauth/types.js +0 -2
- package/dist/utils/oauth/types.js.map +0 -1
- package/dist/utils/oauth/xai.d.ts +0 -34
- package/dist/utils/oauth/xai.d.ts.map +0 -1
- package/dist/utils/oauth/xai.js.map +0 -1
- /package/dist/{utils → auth}/oauth/device-code.d.ts +0 -0
- /package/dist/{utils → auth}/oauth/device-code.js +0 -0
- /package/dist/{utils → auth}/oauth/oauth-page.d.ts +0 -0
- /package/dist/{utils → auth}/oauth/oauth-page.js +0 -0
- /package/dist/{utils → auth}/oauth/pkce.d.ts +0 -0
- /package/dist/{utils → auth}/oauth/pkce.js +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"radius.js","sourceRoot":"","sources":["../../../src/auth/oauth/radius.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Radius gateway OAuth flow.\n *\n * Radius is a pi-messages gateway. OAuth client APIs live on the configured\n * gateway; only the interactive browser authorization endpoint is discovered.\n * Model catalog loading is owned by the Radius provider.\n *\n * NOTE: This module uses node:http for the OAuth callback server.\n * It is only intended for CLI use, not browser environments.\n */\n\n// NEVER convert to top-level imports - breaks browser/Vite builds\nlet _http: typeof import(\"node:http\") | null = null;\nif (typeof process !== \"undefined\" && (process.versions?.node || process.versions?.bun)) {\n\timport(\"node:http\").then((m) => {\n\t\t_http = m;\n\t});\n}\n\nimport { normalizeRadiusGatewayUrl } from \"../../providers/radius-config.ts\";\nimport type { AuthInteraction, OAuthAuth, OAuthCredential } from \"../types.ts\";\nimport { pollOAuthDeviceCodeFlow } from \"./device-code.ts\";\nimport { oauthErrorHtml, oauthSuccessHtml } from \"./oauth-page.ts\";\nimport { generatePKCE } from \"./pkce.ts\";\n\nconst CALLBACK_HOST = \"127.0.0.1\";\nconst CALLBACK_PORT = 1456;\nconst CALLBACK_PATH = \"/oauth/callback\";\nconst REDIRECT_URI = `http://${CALLBACK_HOST}:${CALLBACK_PORT}${CALLBACK_PATH}`;\nconst TOKEN_EXPIRY_SKEW_MS = 60_000;\nconst LOGIN_METHOD_BROWSER = \"browser\";\nconst LOGIN_METHOD_DEVICE_CODE = \"device-code\";\nconst OAUTH_CLIENT_ID = \"pi-gateway\";\nconst OAUTH_SCOPE = \"gateway offline_access\";\nconst OAUTH_DEVICE_CODE_GRANT_TYPE = \"urn:ietf:params:oauth:grant-type:device_code\";\n\ntype RadiusOAuthDiscovery = {\n\tauthorizationEndpoint: string;\n};\n\ntype DeviceAuthorizationResponse = {\n\tdevice_code: string;\n\tuser_code: string;\n\tverification_uri: string;\n\texpires_in: number;\n\tinterval?: number;\n};\n\nasync function loadRadiusOAuthDiscovery(gateway: string): Promise<RadiusOAuthDiscovery> {\n\tconst response = await fetch(new URL(\"/v1/oauth\", gateway), {\n\t\theaders: { accept: \"application/json\" },\n\t});\n\n\tif (!response.ok) {\n\t\tthrow new Error(\n\t\t\t`Could not load Radius OAuth config from ${gateway}: ${response.status} ${await response.text()}`,\n\t\t);\n\t}\n\n\tconst discovery = (await response.json()) as Partial<RadiusOAuthDiscovery>;\n\tif (typeof discovery.authorizationEndpoint !== \"string\") {\n\t\tthrow new Error(`Invalid Radius OAuth config from ${gateway}`);\n\t}\n\treturn { authorizationEndpoint: discovery.authorizationEndpoint };\n}\n\nclass OAuthResponseError extends Error {\n\treadonly status: number;\n\treadonly oauthError?: string;\n\n\tconstructor(status: number, oauthError: string | undefined, description: string | undefined, message: string) {\n\t\tconst detail = oauthError\n\t\t\t? description\n\t\t\t\t? `${oauthError}: ${description}`\n\t\t\t\t: oauthError\n\t\t\t: description || String(status);\n\t\tsuper(`${message}: ${detail}`);\n\t\tthis.status = status;\n\t\tthis.oauthError = oauthError;\n\t}\n}\n\nasync function readOAuthResponseError(response: Response, message: string): Promise<OAuthResponseError> {\n\tconst text = await response.text().catch(() => \"\");\n\tlet oauthError: string | undefined;\n\tlet description: string | undefined;\n\n\tif (text) {\n\t\ttry {\n\t\t\tconst data = JSON.parse(text) as { error?: unknown; error_description?: unknown };\n\t\t\toauthError = typeof data.error === \"string\" ? data.error : undefined;\n\t\t\tdescription = typeof data.error_description === \"string\" ? data.error_description : undefined;\n\t\t} catch {\n\t\t\tdescription = text;\n\t\t}\n\t}\n\n\treturn new OAuthResponseError(response.status, oauthError, description, message);\n}\n\nasync function requestOAuthToken(\n\tgateway: string,\n\tbody: URLSearchParams,\n\tsignal?: AbortSignal,\n): Promise<OAuthCredential> {\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetch(new URL(\"/v1/oauth/token\", gateway), {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { accept: \"application/json\", \"content-type\": \"application/x-www-form-urlencoded\" },\n\t\t\tbody,\n\t\t\tsignal,\n\t\t});\n\t} catch (error) {\n\t\tif (signal?.aborted) {\n\t\t\tthrow new Error(\"Login cancelled\");\n\t\t}\n\t\tthrow error;\n\t}\n\n\tif (!response.ok) {\n\t\tthrow await readOAuthResponseError(response, \"Radius OAuth token request failed\");\n\t}\n\n\tconst data = (await response.json()) as {\n\t\taccess_token: string;\n\t\trefresh_token: string;\n\t\texpires_in: number;\n\t\tscope?: string;\n\t};\n\n\treturn {\n\t\ttype: \"oauth\",\n\t\taccess: data.access_token,\n\t\trefresh: data.refresh_token,\n\t\texpires: Date.now() + data.expires_in * 1000 - TOKEN_EXPIRY_SKEW_MS,\n\t\tscope: data.scope,\n\t};\n}\n\ntype OAuthCallbackServer = {\n\twaitForCode(): Promise<string | null>;\n\tclose(): void;\n};\n\nfunction startOAuthCallbackServer(\n\texpectedState: string,\n\tsignal: AbortSignal | undefined,\n): Promise<OAuthCallbackServer> {\n\tif (!_http) {\n\t\tthrow new Error(\"Radius OAuth is only available in Node.js environments\");\n\t}\n\n\tlet settle: (code: string | null) => void = () => {};\n\tlet settled = false;\n\tconst wait = new Promise<string | null>((resolve) => {\n\t\tsettle = resolve;\n\t});\n\tconst finish = (code: string | null) => {\n\t\tif (settled) {\n\t\t\treturn;\n\t\t}\n\t\tsettled = true;\n\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\tsettle(code);\n\t};\n\tconst onAbort = () => finish(null);\n\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\n\tconst sendPage = (response: import(\"node:http\").ServerResponse, status: number, html: string) => {\n\t\tresponse.statusCode = status;\n\t\tresponse.setHeader(\"content-type\", \"text/html; charset=utf-8\");\n\t\tresponse.end(html);\n\t};\n\n\tconst server = _http.createServer((request, response) => {\n\t\tconst url = new URL(request.url ?? \"/\", REDIRECT_URI);\n\t\tif (url.pathname !== CALLBACK_PATH) {\n\t\t\tsendPage(response, 404, oauthErrorHtml(\"Callback route not found.\"));\n\t\t\treturn;\n\t\t}\n\t\tif (url.searchParams.get(\"state\") !== expectedState) {\n\t\t\tsendPage(response, 400, oauthErrorHtml(\"OAuth state mismatch.\"));\n\t\t\treturn;\n\t\t}\n\n\t\tconst error = url.searchParams.get(\"error\");\n\t\tif (error) {\n\t\t\tsendPage(response, 400, oauthErrorHtml(url.searchParams.get(\"error_description\") ?? error));\n\t\t\tfinish(null);\n\t\t\treturn;\n\t\t}\n\n\t\tconst code = url.searchParams.get(\"code\");\n\t\tif (!code) {\n\t\t\tsendPage(response, 400, oauthErrorHtml(\"Missing authorization code.\"));\n\t\t\treturn;\n\t\t}\n\n\t\tsendPage(response, 200, oauthSuccessHtml(\"Signed in to Radius. You may now close this page.\"));\n\t\tfinish(code);\n\t});\n\n\treturn new Promise((resolve) => {\n\t\tserver\n\t\t\t.listen(CALLBACK_PORT, CALLBACK_HOST, () => {\n\t\t\t\tresolve({\n\t\t\t\t\twaitForCode: () => wait,\n\t\t\t\t\tclose: () => {\n\t\t\t\t\t\tfinish(null);\n\t\t\t\t\t\tserver.close();\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t})\n\t\t\t.once(\"error\", () => {\n\t\t\t\tfinish(null);\n\t\t\t\tresolve({ waitForCode: async () => null, close: () => {} });\n\t\t\t});\n\t});\n}\n\nasync function loginWithBrowser(\n\tgateway: string,\n\tauthorizationEndpoint: string,\n\tinteraction: AuthInteraction,\n): Promise<OAuthCredential> {\n\tconst { verifier, challenge } = await generatePKCE();\n\tconst state = crypto.randomUUID();\n\tconst authorizeUrl = new URL(authorizationEndpoint);\n\tauthorizeUrl.search = new URLSearchParams({\n\t\tresponse_type: \"code\",\n\t\tclient_id: OAUTH_CLIENT_ID,\n\t\tredirect_uri: REDIRECT_URI,\n\t\tscope: OAUTH_SCOPE,\n\t\tcode_challenge: challenge,\n\t\tcode_challenge_method: \"S256\",\n\t\thandoff: \"url\",\n\t\tstate,\n\t}).toString();\n\n\tconst callbackServer = await startOAuthCallbackServer(state, interaction.signal);\n\tinteraction.notify({ type: \"progress\", message: `Listening for OAuth callback on ${REDIRECT_URI}` });\n\tinteraction.notify({\n\t\ttype: \"auth_url\",\n\t\turl: authorizeUrl.toString(),\n\t\tinstructions: \"Continue in your browser.\",\n\t});\n\n\ttry {\n\t\tconst code = await callbackServer.waitForCode();\n\t\tif (!code) {\n\t\t\tif (interaction.signal?.aborted) {\n\t\t\t\tthrow new Error(\"Login cancelled\");\n\t\t\t}\n\t\t\tthrow new Error(\"OAuth callback did not complete.\");\n\t\t}\n\t\treturn await requestOAuthToken(\n\t\t\tgateway,\n\t\t\tnew URLSearchParams({\n\t\t\t\tgrant_type: \"authorization_code\",\n\t\t\t\tclient_id: OAUTH_CLIENT_ID,\n\t\t\t\tredirect_uri: REDIRECT_URI,\n\t\t\t\tcode,\n\t\t\t\tcode_verifier: verifier,\n\t\t\t}),\n\t\t\tinteraction.signal,\n\t\t);\n\t} finally {\n\t\tcallbackServer.close();\n\t}\n}\n\nasync function requestDeviceAuthorization(\n\tgateway: string,\n\tsignal: AbortSignal | undefined,\n): Promise<DeviceAuthorizationResponse> {\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetch(new URL(\"/v1/oauth/device\", gateway), {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { accept: \"application/json\", \"content-type\": \"application/x-www-form-urlencoded\" },\n\t\t\tbody: new URLSearchParams({ client_id: OAUTH_CLIENT_ID, scope: OAUTH_SCOPE }),\n\t\t\tsignal,\n\t\t});\n\t} catch (error) {\n\t\tif (signal?.aborted) {\n\t\t\tthrow new Error(\"Login cancelled\");\n\t\t}\n\t\tthrow error;\n\t}\n\n\tif (!response.ok) {\n\t\tthrow await readOAuthResponseError(response, \"Radius OAuth device authorization failed\");\n\t}\n\n\tconst data = (await response.json()) as Partial<DeviceAuthorizationResponse>;\n\tif (!data.device_code || !data.user_code || !data.verification_uri || !data.expires_in) {\n\t\tthrow new Error(\"Radius OAuth device authorization response is missing required fields\");\n\t}\n\n\treturn {\n\t\tdevice_code: data.device_code,\n\t\tuser_code: data.user_code,\n\t\tverification_uri: data.verification_uri,\n\t\texpires_in: data.expires_in,\n\t\tinterval: data.interval,\n\t};\n}\n\nasync function loginWithDeviceCode(gateway: string, interaction: AuthInteraction): Promise<OAuthCredential> {\n\tconst device = await requestDeviceAuthorization(gateway, interaction.signal);\n\tinteraction.notify({\n\t\ttype: \"device_code\",\n\t\tuserCode: device.user_code,\n\t\tverificationUri: device.verification_uri,\n\t\tintervalSeconds: device.interval,\n\t\texpiresInSeconds: device.expires_in,\n\t});\n\n\treturn pollOAuthDeviceCodeFlow<OAuthCredential>({\n\t\tintervalSeconds: device.interval,\n\t\texpiresInSeconds: device.expires_in,\n\t\tsignal: interaction.signal,\n\t\tpoll: async () => {\n\t\t\ttry {\n\t\t\t\tconst credentials = await requestOAuthToken(\n\t\t\t\t\tgateway,\n\t\t\t\t\tnew URLSearchParams({\n\t\t\t\t\t\tgrant_type: OAUTH_DEVICE_CODE_GRANT_TYPE,\n\t\t\t\t\t\tclient_id: OAUTH_CLIENT_ID,\n\t\t\t\t\t\tdevice_code: device.device_code,\n\t\t\t\t\t}),\n\t\t\t\t\tinteraction.signal,\n\t\t\t\t);\n\t\t\t\treturn { status: \"complete\", value: credentials };\n\t\t\t} catch (error) {\n\t\t\t\tif (!(error instanceof OAuthResponseError)) {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tswitch (error.oauthError) {\n\t\t\t\t\tcase \"authorization_pending\":\n\t\t\t\t\t\treturn { status: \"pending\" };\n\t\t\t\t\tcase \"slow_down\":\n\t\t\t\t\t\treturn { status: \"slow_down\" };\n\t\t\t\t\tcase \"expired_token\":\n\t\t\t\t\t\treturn { status: \"failed\", message: \"Device authorization expired.\" };\n\t\t\t\t\tcase \"access_denied\":\n\t\t\t\t\t\treturn { status: \"failed\", message: \"Device authorization was denied.\" };\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t});\n}\n\nexport interface RadiusOAuthOptions {\n\tname: string;\n\tgateway: string;\n}\n\nexport function createRadiusOAuth(options: RadiusOAuthOptions): OAuthAuth {\n\tconst gateway = normalizeRadiusGatewayUrl(options.gateway);\n\n\treturn {\n\t\tname: options.name,\n\n\t\tasync login(interaction): Promise<OAuthCredential> {\n\t\t\tconst loginMethod = await interaction.prompt({\n\t\t\t\ttype: \"select\",\n\t\t\t\tmessage: `Sign in to ${options.name}:`,\n\t\t\t\toptions: [\n\t\t\t\t\t{ id: LOGIN_METHOD_BROWSER, label: \"Sign in with browser (recommended)\" },\n\t\t\t\t\t{\n\t\t\t\t\t\tid: LOGIN_METHOD_DEVICE_CODE,\n\t\t\t\t\t\tlabel: \"Sign in with device code (when signing in from another device)\",\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t});\n\n\t\t\tif (loginMethod === LOGIN_METHOD_DEVICE_CODE) {\n\t\t\t\treturn loginWithDeviceCode(gateway, interaction);\n\t\t\t}\n\t\t\tif (loginMethod === LOGIN_METHOD_BROWSER) {\n\t\t\t\tconst discovery = await loadRadiusOAuthDiscovery(gateway);\n\t\t\t\treturn loginWithBrowser(gateway, discovery.authorizationEndpoint, interaction);\n\t\t\t}\n\t\t\tthrow new Error(`Unknown ${options.name} sign-in method: ${loginMethod}`);\n\t\t},\n\n\t\tasync refresh(credential, signal): Promise<OAuthCredential> {\n\t\t\tconst refreshed = await requestOAuthToken(\n\t\t\t\tgateway,\n\t\t\t\tnew URLSearchParams({\n\t\t\t\t\tgrant_type: \"refresh_token\",\n\t\t\t\t\tclient_id: OAUTH_CLIENT_ID,\n\t\t\t\t\trefresh_token: credential.refresh,\n\t\t\t\t}),\n\t\t\t\tsignal,\n\t\t\t);\n\t\t\treturn refreshed;\n\t\t},\n\n\t\tasync toAuth(credential) {\n\t\t\treturn { apiKey: credential.access };\n\t\t},\n\t};\n}\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* xAI (Grok) OAuth flow — SuperGrok / X Premium+ subscription login.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the flow the official Grok CLI uses: PKCE authorization code
|
|
5
|
+
* against auth.x.ai's OIDC discovery document. Tokens are scoped for the
|
|
6
|
+
* Grok CLI proxy (cli-chat-proxy.grok.com) rather than the pay-per-token
|
|
7
|
+
* api.x.ai endpoint, so `toAuth` routes requests there via a baseUrl
|
|
8
|
+
* override.
|
|
9
|
+
*
|
|
10
|
+
* NOTE: This module uses Node.js http.createServer for the OAuth callback
|
|
11
|
+
* server. It is only intended for CLI use, not browser environments.
|
|
12
|
+
*/
|
|
13
|
+
import type { OAuthAuth } from "../types.ts";
|
|
14
|
+
/** OAuth-authenticated requests are proxied through the Grok CLI endpoint, not api.x.ai directly. */
|
|
15
|
+
export declare const XAI_OAUTH_BASE_URL = "https://cli-chat-proxy.grok.com/v1";
|
|
16
|
+
export declare const xaiOAuth: OAuthAuth;
|
|
17
|
+
//# sourceMappingURL=xai.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xai.d.ts","sourceRoot":"","sources":["../../../src/auth/oauth/xai.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,EAAmB,SAAS,EAAmB,MAAM,aAAa,CAAC;AAoB/E,qGAAqG;AACrG,eAAO,MAAM,kBAAkB,uCAAuC,CAAC;AAqTvE,eAAO,MAAM,QAAQ,EAAE,SAUtB,CAAC"}
|
|
@@ -4,12 +4,13 @@
|
|
|
4
4
|
* Mirrors the flow the official Grok CLI uses: PKCE authorization code
|
|
5
5
|
* against auth.x.ai's OIDC discovery document. Tokens are scoped for the
|
|
6
6
|
* Grok CLI proxy (cli-chat-proxy.grok.com) rather than the pay-per-token
|
|
7
|
-
* api.x.ai endpoint, so `toAuth
|
|
7
|
+
* api.x.ai endpoint, so `toAuth` routes requests there via a baseUrl
|
|
8
|
+
* override.
|
|
8
9
|
*
|
|
9
10
|
* NOTE: This module uses Node.js http.createServer for the OAuth callback
|
|
10
11
|
* server. It is only intended for CLI use, not browser environments.
|
|
11
12
|
*/
|
|
12
|
-
import { getProviderEnvValue } from "
|
|
13
|
+
import { getProviderEnvValue } from "../../utils/provider-env.js";
|
|
13
14
|
import { oauthErrorHtml, oauthSuccessHtml } from "./oauth-page.js";
|
|
14
15
|
import { generatePKCE } from "./pkce.js";
|
|
15
16
|
let nodeApis = null;
|
|
@@ -172,6 +173,7 @@ function credentialsFromTokenPayload(data, fallbackRefresh = "") {
|
|
|
172
173
|
throw new Error("xAI token response did not include a refresh token");
|
|
173
174
|
}
|
|
174
175
|
return {
|
|
176
|
+
type: "oauth",
|
|
175
177
|
access: data.access_token,
|
|
176
178
|
refresh,
|
|
177
179
|
expires: Date.now() + (data.expires_in ?? 3600) * 1000 - REFRESH_SKEW_MS,
|
|
@@ -180,10 +182,13 @@ function credentialsFromTokenPayload(data, fallbackRefresh = "") {
|
|
|
180
182
|
/**
|
|
181
183
|
* Login with xAI OAuth (SuperGrok / X Premium+ subscription, authorization code + PKCE)
|
|
182
184
|
*/
|
|
183
|
-
|
|
185
|
+
async function loginXai(interaction) {
|
|
184
186
|
const discovery = await discoverXaiEndpoints();
|
|
185
187
|
const { verifier, challenge } = await generatePKCE();
|
|
186
188
|
const server = await startCallbackServer(verifier);
|
|
189
|
+
// The manual_code prompt races the local callback server; abort it once
|
|
190
|
+
// the flow settles so the UI can dismiss the pending input.
|
|
191
|
+
const manualAbort = new AbortController();
|
|
187
192
|
try {
|
|
188
193
|
const authParams = new URLSearchParams({
|
|
189
194
|
response_type: "code",
|
|
@@ -194,60 +199,59 @@ export async function loginXai(options) {
|
|
|
194
199
|
code_challenge_method: "S256",
|
|
195
200
|
state: verifier,
|
|
196
201
|
});
|
|
197
|
-
|
|
202
|
+
interaction.notify({
|
|
203
|
+
type: "auth_url",
|
|
198
204
|
url: `${discovery.authorizationEndpoint}?${authParams.toString()}`,
|
|
199
205
|
instructions: "Sign in with your SuperGrok or X Premium+ account. If the browser is on another machine, paste the final redirect URL here.",
|
|
200
206
|
});
|
|
201
207
|
let code;
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
208
|
+
let manualInput;
|
|
209
|
+
let manualError;
|
|
210
|
+
const manualPromise = interaction
|
|
211
|
+
.prompt({
|
|
212
|
+
type: "manual_code",
|
|
213
|
+
message: "Complete login in your browser, or paste the authorization code / redirect URL here:",
|
|
214
|
+
placeholder: server.redirectUri,
|
|
215
|
+
signal: manualAbort.signal,
|
|
216
|
+
})
|
|
217
|
+
.then((input) => {
|
|
218
|
+
manualInput = input;
|
|
219
|
+
server.cancelWait();
|
|
220
|
+
})
|
|
221
|
+
.catch((err) => {
|
|
222
|
+
manualError = err instanceof Error ? err : new Error(String(err));
|
|
223
|
+
server.cancelWait();
|
|
224
|
+
});
|
|
225
|
+
const result = await server.waitForCode();
|
|
226
|
+
if (manualError) {
|
|
227
|
+
throw manualError;
|
|
228
|
+
}
|
|
229
|
+
if (result?.code) {
|
|
230
|
+
code = result.code;
|
|
231
|
+
}
|
|
232
|
+
else if (manualInput) {
|
|
233
|
+
const parsed = parseAuthorizationInput(manualInput);
|
|
234
|
+
if (parsed.state && parsed.state !== verifier) {
|
|
235
|
+
throw new Error("OAuth state mismatch");
|
|
236
|
+
}
|
|
237
|
+
code = parsed.code;
|
|
238
|
+
}
|
|
239
|
+
if (!code) {
|
|
240
|
+
await manualPromise;
|
|
216
241
|
if (manualError) {
|
|
217
242
|
throw manualError;
|
|
218
243
|
}
|
|
219
|
-
if (
|
|
220
|
-
code = result.code;
|
|
221
|
-
}
|
|
222
|
-
else if (manualInput) {
|
|
244
|
+
if (manualInput) {
|
|
223
245
|
const parsed = parseAuthorizationInput(manualInput);
|
|
224
246
|
if (parsed.state && parsed.state !== verifier) {
|
|
225
247
|
throw new Error("OAuth state mismatch");
|
|
226
248
|
}
|
|
227
249
|
code = parsed.code;
|
|
228
250
|
}
|
|
229
|
-
if (!code) {
|
|
230
|
-
await manualPromise;
|
|
231
|
-
if (manualError) {
|
|
232
|
-
throw manualError;
|
|
233
|
-
}
|
|
234
|
-
if (manualInput) {
|
|
235
|
-
const parsed = parseAuthorizationInput(manualInput);
|
|
236
|
-
if (parsed.state && parsed.state !== verifier) {
|
|
237
|
-
throw new Error("OAuth state mismatch");
|
|
238
|
-
}
|
|
239
|
-
code = parsed.code;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
else {
|
|
244
|
-
const result = await server.waitForCode();
|
|
245
|
-
if (result?.code) {
|
|
246
|
-
code = result.code;
|
|
247
|
-
}
|
|
248
251
|
}
|
|
249
252
|
if (!code) {
|
|
250
|
-
const input = await
|
|
253
|
+
const input = await interaction.prompt({
|
|
254
|
+
type: "text",
|
|
251
255
|
message: "Paste the authorization code or full redirect URL:",
|
|
252
256
|
placeholder: server.redirectUri,
|
|
253
257
|
});
|
|
@@ -260,7 +264,7 @@ export async function loginXai(options) {
|
|
|
260
264
|
if (!code) {
|
|
261
265
|
throw new Error("Missing authorization code");
|
|
262
266
|
}
|
|
263
|
-
|
|
267
|
+
interaction.notify({ type: "progress", message: "Exchanging xAI authorization code..." });
|
|
264
268
|
const responseBody = await postForm(discovery.tokenEndpoint, {
|
|
265
269
|
grant_type: "authorization_code",
|
|
266
270
|
client_id: CLIENT_ID,
|
|
@@ -271,13 +275,14 @@ export async function loginXai(options) {
|
|
|
271
275
|
return credentialsFromTokenPayload(JSON.parse(responseBody));
|
|
272
276
|
}
|
|
273
277
|
finally {
|
|
278
|
+
manualAbort.abort();
|
|
274
279
|
server.server.close();
|
|
275
280
|
}
|
|
276
281
|
}
|
|
277
282
|
/**
|
|
278
283
|
* Refresh xAI OAuth token
|
|
279
284
|
*/
|
|
280
|
-
|
|
285
|
+
async function refreshXaiToken(refreshToken) {
|
|
281
286
|
const discovery = await discoverXaiEndpoints();
|
|
282
287
|
const responseBody = await postForm(discovery.tokenEndpoint, {
|
|
283
288
|
grant_type: "refresh_token",
|
|
@@ -287,53 +292,13 @@ export async function refreshXaiToken(refreshToken) {
|
|
|
287
292
|
return credentialsFromTokenPayload(JSON.parse(responseBody), refreshToken);
|
|
288
293
|
}
|
|
289
294
|
export const xaiOAuth = {
|
|
290
|
-
name: "xAI (Grok)",
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
try {
|
|
296
|
-
const credentials = await loginXai({
|
|
297
|
-
onAuth: (info) => callbacks.notify({ type: "auth_url", url: info.url, instructions: info.instructions }),
|
|
298
|
-
onProgress: (message) => callbacks.notify({ type: "progress", message }),
|
|
299
|
-
onPrompt: (prompt) => callbacks.prompt({ type: "text", message: prompt.message, placeholder: prompt.placeholder }),
|
|
300
|
-
onManualCodeInput: () => callbacks.prompt({
|
|
301
|
-
type: "manual_code",
|
|
302
|
-
message: "Complete login in your browser, or paste the authorization code / redirect URL here:",
|
|
303
|
-
placeholder: `http://${CALLBACK_HOST}:${CALLBACK_PORT}${CALLBACK_PATH}`,
|
|
304
|
-
signal: manualAbort.signal,
|
|
305
|
-
}),
|
|
306
|
-
});
|
|
307
|
-
return { ...credentials, type: "oauth" };
|
|
308
|
-
}
|
|
309
|
-
finally {
|
|
310
|
-
manualAbort.abort();
|
|
311
|
-
}
|
|
312
|
-
},
|
|
313
|
-
async refresh(credential) {
|
|
314
|
-
return { ...(await refreshXaiToken(credential.refresh)), type: "oauth" };
|
|
315
|
-
},
|
|
295
|
+
name: "xAI (Grok/X subscription)",
|
|
296
|
+
loginLabel: "Sign in with SuperGrok or X Premium",
|
|
297
|
+
login: loginXai,
|
|
298
|
+
refresh: (credential) => refreshXaiToken(credential.refresh),
|
|
299
|
+
/** Route subscription-authenticated requests through the Grok CLI proxy. */
|
|
316
300
|
async toAuth(credential) {
|
|
317
301
|
return { apiKey: credential.access, baseUrl: XAI_OAUTH_BASE_URL };
|
|
318
302
|
},
|
|
319
303
|
};
|
|
320
|
-
export const xaiOAuthProvider = {
|
|
321
|
-
id: "xai",
|
|
322
|
-
name: "xAI (Grok)",
|
|
323
|
-
usesCallbackServer: true,
|
|
324
|
-
async login(callbacks) {
|
|
325
|
-
return loginXai({
|
|
326
|
-
onAuth: callbacks.onAuth,
|
|
327
|
-
onPrompt: callbacks.onPrompt,
|
|
328
|
-
onProgress: callbacks.onProgress,
|
|
329
|
-
onManualCodeInput: callbacks.onManualCodeInput,
|
|
330
|
-
});
|
|
331
|
-
},
|
|
332
|
-
async refreshToken(credentials) {
|
|
333
|
-
return refreshXaiToken(credentials.refresh);
|
|
334
|
-
},
|
|
335
|
-
getApiKey(credentials) {
|
|
336
|
-
return credentials.access;
|
|
337
|
-
},
|
|
338
|
-
};
|
|
339
304
|
//# sourceMappingURL=xai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xai.js","sourceRoot":"","sources":["../../../src/auth/oauth/xai.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * xAI (Grok) OAuth flow — SuperGrok / X Premium+ subscription login.\n *\n * Mirrors the flow the official Grok CLI uses: PKCE authorization code\n * against auth.x.ai's OIDC discovery document. Tokens are scoped for the\n * Grok CLI proxy (cli-chat-proxy.grok.com) rather than the pay-per-token\n * api.x.ai endpoint, so `toAuth` routes requests there via a baseUrl\n * override.\n *\n * NOTE: This module uses Node.js http.createServer for the OAuth callback\n * server. It is only intended for CLI use, not browser environments.\n */\n\nimport type { Server } 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\ntype NodeApis = {\n\tcreateServer: typeof import(\"node:http\").createServer;\n};\n\nlet nodeApis: NodeApis | null = null;\nlet nodeApisPromise: Promise<NodeApis> | null = null;\n\nconst OAUTH_ISSUER = \"https://auth.x.ai\";\nconst DISCOVERY_URL = `${OAUTH_ISSUER}/.well-known/openid-configuration`;\nconst CLIENT_ID = \"b1a00492-073a-47ea-816f-4c329264a828\";\nconst SCOPE = \"openid profile email offline_access grok-cli:access api:access\";\nconst CALLBACK_HOST = getProviderEnvValue(\"PI_OAUTH_CALLBACK_HOST\") || \"127.0.0.1\";\nconst CALLBACK_PORT = 56121;\nconst CALLBACK_PATH = \"/callback\";\nconst REFRESH_SKEW_MS = 2 * 60 * 1000;\n\n/** OAuth-authenticated requests are proxied through the Grok CLI endpoint, not api.x.ai directly. */\nexport const XAI_OAUTH_BASE_URL = \"https://cli-chat-proxy.grok.com/v1\";\n\ntype XaiDiscovery = { authorizationEndpoint: string; tokenEndpoint: string };\ntype XaiTokenPayload = { access_token?: string; refresh_token?: string; expires_in?: number };\n\nasync function getNodeApis(): Promise<NodeApis> {\n\tif (nodeApis) return nodeApis;\n\tif (!nodeApisPromise) {\n\t\tif (typeof process === \"undefined\" || (!process.versions?.node && !process.versions?.bun)) {\n\t\t\tthrow new Error(\"xAI OAuth is only available in Node.js environments\");\n\t\t}\n\t\tnodeApisPromise = import(\"node:http\").then((httpModule) => ({\n\t\t\tcreateServer: httpModule.createServer,\n\t\t}));\n\t}\n\tnodeApis = await nodeApisPromise;\n\treturn nodeApis;\n}\n\n/** Reject discovery responses that don't point back at x.ai, in case DNS/discovery is ever compromised. */\nfunction validateXaiEndpoint(url: string): string {\n\tconst parsed = new URL(url);\n\tconst host = parsed.hostname.toLowerCase();\n\tif (parsed.protocol !== \"https:\" || (host !== \"x.ai\" && !host.endsWith(\".x.ai\"))) {\n\t\tthrow new Error(`xAI OAuth discovery returned an unexpected endpoint: ${url}`);\n\t}\n\treturn url;\n}\n\nasync function discoverXaiEndpoints(): Promise<XaiDiscovery> {\n\tconst response = await fetch(DISCOVERY_URL, { headers: { Accept: \"application/json\" } });\n\tif (!response.ok) {\n\t\tthrow new Error(`xAI OAuth discovery failed: ${response.status} ${await response.text()}`);\n\t}\n\n\tconst data = (await response.json()) as { authorization_endpoint?: string; token_endpoint?: string };\n\tif (!data.authorization_endpoint || !data.token_endpoint) {\n\t\tthrow new Error(\"xAI OAuth discovery response did not include authorization/token endpoints\");\n\t}\n\n\treturn {\n\t\tauthorizationEndpoint: validateXaiEndpoint(data.authorization_endpoint),\n\t\ttokenEndpoint: validateXaiEndpoint(data.token_endpoint),\n\t};\n}\n\nfunction parseAuthorizationInput(input: string): { code?: string; state?: string } {\n\tconst value = input.trim();\n\tif (!value) return {};\n\n\ttry {\n\t\tconst url = new URL(value);\n\t\treturn {\n\t\t\tcode: url.searchParams.get(\"code\") ?? undefined,\n\t\t\tstate: url.searchParams.get(\"state\") ?? undefined,\n\t\t};\n\t} catch {\n\t\t// not a URL\n\t}\n\n\tif (value.includes(\"code=\")) {\n\t\tconst params = new URLSearchParams(value);\n\t\treturn {\n\t\t\tcode: params.get(\"code\") ?? undefined,\n\t\t\tstate: params.get(\"state\") ?? undefined,\n\t\t};\n\t}\n\n\treturn { code: value };\n}\n\ntype CallbackServerInfo = {\n\tserver: Server;\n\tredirectUri: string;\n\tcancelWait: () => void;\n\twaitForCode: () => Promise<{ code: string; state: string } | null>;\n};\n\nasync function startCallbackServer(expectedState: string): Promise<CallbackServerInfo> {\n\tconst { createServer } = await getNodeApis();\n\n\treturn new Promise((resolve, reject) => {\n\t\tlet settleWait: ((value: { code: string; state: string } | null) => void) | undefined;\n\t\tconst waitForCodePromise = new Promise<{ code: string; state: string } | null>((resolveWait) => {\n\t\t\tlet settled = false;\n\t\t\tsettleWait = (value) => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tresolveWait(value);\n\t\t\t};\n\t\t});\n\n\t\tconst server = createServer((req, res) => {\n\t\t\ttry {\n\t\t\t\tconst url = new URL(req.url || \"\", `http://${CALLBACK_HOST}`);\n\t\t\t\tif (url.pathname !== CALLBACK_PATH) {\n\t\t\t\t\tres.writeHead(404, { \"Content-Type\": \"text/html; charset=utf-8\" });\n\t\t\t\t\tres.end(oauthErrorHtml(\"Callback route not found.\"));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst code = url.searchParams.get(\"code\");\n\t\t\t\tconst state = url.searchParams.get(\"state\");\n\t\t\t\tconst error = url.searchParams.get(\"error\");\n\n\t\t\t\tif (error) {\n\t\t\t\t\tres.writeHead(400, { \"Content-Type\": \"text/html; charset=utf-8\" });\n\t\t\t\t\tres.end(oauthErrorHtml(\"xAI authentication did not complete.\", `Error: ${error}`));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (!code || !state) {\n\t\t\t\t\tres.writeHead(400, { \"Content-Type\": \"text/html; charset=utf-8\" });\n\t\t\t\t\tres.end(oauthErrorHtml(\"Missing code or state parameter.\"));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (state !== expectedState) {\n\t\t\t\t\tres.writeHead(400, { \"Content-Type\": \"text/html; charset=utf-8\" });\n\t\t\t\t\tres.end(oauthErrorHtml(\"State mismatch.\"));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tres.writeHead(200, { \"Content-Type\": \"text/html; charset=utf-8\" });\n\t\t\t\tres.end(oauthSuccessHtml(\"xAI authentication completed. You can close this window.\"));\n\t\t\t\tsettleWait?.({ code, state });\n\t\t\t} catch {\n\t\t\t\tres.writeHead(500, { \"Content-Type\": \"text/plain; charset=utf-8\" });\n\t\t\t\tres.end(\"Internal error\");\n\t\t\t}\n\t\t});\n\n\t\tserver.on(\"error\", (err) => {\n\t\t\treject(err);\n\t\t});\n\n\t\tserver.listen(CALLBACK_PORT, CALLBACK_HOST, () => {\n\t\t\tresolve({\n\t\t\t\tserver,\n\t\t\t\tredirectUri: `http://${CALLBACK_HOST}:${CALLBACK_PORT}${CALLBACK_PATH}`,\n\t\t\t\tcancelWait: () => {\n\t\t\t\t\tsettleWait?.(null);\n\t\t\t\t},\n\t\t\t\twaitForCode: () => waitForCodePromise,\n\t\t\t});\n\t\t});\n\t});\n}\n\nasync function postForm(url: string, body: Record<string, string>): Promise<string> {\n\tconst response = await fetch(url, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\tAccept: \"application/json\",\n\t\t},\n\t\tbody: new URLSearchParams(body).toString(),\n\t\tsignal: AbortSignal.timeout(30_000),\n\t});\n\n\tconst responseBody = await response.text();\n\tif (!response.ok) {\n\t\tthrow new Error(`xAI token request failed. status=${response.status}; url=${url}; body=${responseBody}`);\n\t}\n\treturn responseBody;\n}\n\nfunction credentialsFromTokenPayload(data: XaiTokenPayload, fallbackRefresh = \"\"): OAuthCredential {\n\tif (!data.access_token) {\n\t\tthrow new Error(\"xAI token response did not include an access token\");\n\t}\n\n\tconst refresh = data.refresh_token || fallbackRefresh;\n\tif (!refresh) {\n\t\tthrow new Error(\"xAI token response did not include a refresh token\");\n\t}\n\n\treturn {\n\t\ttype: \"oauth\",\n\t\taccess: data.access_token,\n\t\trefresh,\n\t\texpires: Date.now() + (data.expires_in ?? 3600) * 1000 - REFRESH_SKEW_MS,\n\t};\n}\n\n/**\n * Login with xAI OAuth (SuperGrok / X Premium+ subscription, authorization code + PKCE)\n */\nasync function loginXai(interaction: AuthInteraction): Promise<OAuthCredential> {\n\tconst discovery = await discoverXaiEndpoints();\n\tconst { verifier, challenge } = await generatePKCE();\n\tconst server = await startCallbackServer(verifier);\n\t// The manual_code prompt races the local callback server; abort it once\n\t// the flow settles so the UI can dismiss the pending input.\n\tconst manualAbort = new AbortController();\n\n\ttry {\n\t\tconst authParams = new URLSearchParams({\n\t\t\tresponse_type: \"code\",\n\t\t\tclient_id: CLIENT_ID,\n\t\t\tredirect_uri: server.redirectUri,\n\t\t\tscope: SCOPE,\n\t\t\tcode_challenge: challenge,\n\t\t\tcode_challenge_method: \"S256\",\n\t\t\tstate: verifier,\n\t\t});\n\n\t\tinteraction.notify({\n\t\t\ttype: \"auth_url\",\n\t\t\turl: `${discovery.authorizationEndpoint}?${authParams.toString()}`,\n\t\t\tinstructions:\n\t\t\t\t\"Sign in with your SuperGrok or X Premium+ account. If the browser is on another machine, paste the final redirect URL here.\",\n\t\t});\n\n\t\tlet code: string | undefined;\n\t\tlet manualInput: string | undefined;\n\t\tlet manualError: Error | undefined;\n\n\t\tconst manualPromise = interaction\n\t\t\t.prompt({\n\t\t\t\ttype: \"manual_code\",\n\t\t\t\tmessage: \"Complete login in your browser, or paste the authorization code / redirect URL here:\",\n\t\t\t\tplaceholder: server.redirectUri,\n\t\t\t\tsignal: manualAbort.signal,\n\t\t\t})\n\t\t\t.then((input) => {\n\t\t\t\tmanualInput = input;\n\t\t\t\tserver.cancelWait();\n\t\t\t})\n\t\t\t.catch((err) => {\n\t\t\t\tmanualError = err instanceof Error ? err : new Error(String(err));\n\t\t\t\tserver.cancelWait();\n\t\t\t});\n\n\t\tconst result = await server.waitForCode();\n\n\t\tif (manualError) {\n\t\t\tthrow manualError;\n\t\t}\n\n\t\tif (result?.code) {\n\t\t\tcode = result.code;\n\t\t} else if (manualInput) {\n\t\t\tconst parsed = parseAuthorizationInput(manualInput);\n\t\t\tif (parsed.state && parsed.state !== verifier) {\n\t\t\t\tthrow new Error(\"OAuth state mismatch\");\n\t\t\t}\n\t\t\tcode = parsed.code;\n\t\t}\n\n\t\tif (!code) {\n\t\t\tawait manualPromise;\n\t\t\tif (manualError) {\n\t\t\t\tthrow manualError;\n\t\t\t}\n\t\t\tif (manualInput) {\n\t\t\t\tconst parsed = parseAuthorizationInput(manualInput);\n\t\t\t\tif (parsed.state && parsed.state !== verifier) {\n\t\t\t\t\tthrow new Error(\"OAuth state mismatch\");\n\t\t\t\t}\n\t\t\t\tcode = parsed.code;\n\t\t\t}\n\t\t}\n\n\t\tif (!code) {\n\t\t\tconst input = await interaction.prompt({\n\t\t\t\ttype: \"text\",\n\t\t\t\tmessage: \"Paste the authorization code or full redirect URL:\",\n\t\t\t\tplaceholder: server.redirectUri,\n\t\t\t});\n\t\t\tconst parsed = parseAuthorizationInput(input);\n\t\t\tif (parsed.state && parsed.state !== verifier) {\n\t\t\t\tthrow new Error(\"OAuth state mismatch\");\n\t\t\t}\n\t\t\tcode = parsed.code;\n\t\t}\n\n\t\tif (!code) {\n\t\t\tthrow new Error(\"Missing authorization code\");\n\t\t}\n\n\t\tinteraction.notify({ type: \"progress\", message: \"Exchanging xAI authorization code...\" });\n\t\tconst responseBody = await postForm(discovery.tokenEndpoint, {\n\t\t\tgrant_type: \"authorization_code\",\n\t\t\tclient_id: CLIENT_ID,\n\t\t\tcode,\n\t\t\tredirect_uri: server.redirectUri,\n\t\t\tcode_verifier: verifier,\n\t\t});\n\t\treturn credentialsFromTokenPayload(JSON.parse(responseBody) as XaiTokenPayload);\n\t} finally {\n\t\tmanualAbort.abort();\n\t\tserver.server.close();\n\t}\n}\n\n/**\n * Refresh xAI OAuth token\n */\nasync function refreshXaiToken(refreshToken: string): Promise<OAuthCredential> {\n\tconst discovery = await discoverXaiEndpoints();\n\tconst responseBody = await postForm(discovery.tokenEndpoint, {\n\t\tgrant_type: \"refresh_token\",\n\t\tclient_id: CLIENT_ID,\n\t\trefresh_token: refreshToken,\n\t});\n\treturn credentialsFromTokenPayload(JSON.parse(responseBody) as XaiTokenPayload, refreshToken);\n}\n\nexport const xaiOAuth: OAuthAuth = {\n\tname: \"xAI (Grok/X subscription)\",\n\tloginLabel: \"Sign in with SuperGrok or X Premium\",\n\tlogin: loginXai,\n\trefresh: (credential) => refreshXaiToken(credential.refresh),\n\n\t/** Route subscription-authenticated requests through the Grok CLI proxy. */\n\tasync toAuth(credential) {\n\t\treturn { apiKey: credential.access, baseUrl: XAI_OAUTH_BASE_URL };\n\t},\n};\n"]}
|
package/dist/auth/resolve.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ProviderEnv } from "../types.ts";
|
|
2
2
|
import type { AuthContext, AuthResult, CredentialStore, ProviderAuth } from "./types.ts";
|
|
3
3
|
export type ModelsErrorCode = "model_source" | "model_validation" | "provider" | "stream" | "auth" | "oauth";
|
|
4
4
|
export interface AuthResolutionOverrides {
|
|
5
5
|
apiKey?: string;
|
|
6
6
|
env?: ProviderEnv;
|
|
7
|
+
/** Require this much remaining OAuth-token validity; defaults to five minutes. */
|
|
8
|
+
minOAuthValidityMs?: number;
|
|
7
9
|
}
|
|
8
10
|
export declare class ModelsError extends Error {
|
|
9
11
|
readonly code: ModelsErrorCode;
|
|
@@ -11,8 +13,6 @@ export declare class ModelsError extends Error {
|
|
|
11
13
|
cause?: unknown;
|
|
12
14
|
});
|
|
13
15
|
}
|
|
14
|
-
/** Model shape auth resolution receives: chat or image-generation models. */
|
|
15
|
-
export type AuthModel = Model<Api> | ImagesModel<ImagesApi>;
|
|
16
16
|
/**
|
|
17
17
|
* Auth resolution shared by the `Models` and `ImagesModels` collections.
|
|
18
18
|
* A stored credential owns the provider: ambient/env is consulted only when
|
|
@@ -22,5 +22,5 @@ export type AuthModel = Model<Api> | ImagesModel<ImagesApi>;
|
|
|
22
22
|
export declare function resolveProviderAuth(provider: {
|
|
23
23
|
id: string;
|
|
24
24
|
auth: ProviderAuth;
|
|
25
|
-
},
|
|
25
|
+
}, credentials: CredentialStore, authContext: AuthContext, overrides?: AuthResolutionOverrides): Promise<AuthResult | undefined>;
|
|
26
26
|
//# sourceMappingURL=resolve.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/auth/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/auth/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,KAAK,EAGX,WAAW,EACX,UAAU,EAEV,eAAe,EAGf,YAAY,EACZ,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,eAAe,GAAG,cAAc,GAAG,kBAAkB,GAAG,UAAU,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAE7G,MAAM,WAAW,uBAAuB;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,WAAW,CAAC;IAClB,kFAAkF;IAClF,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,qBAAa,WAAY,SAAQ,KAAK;IACrC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAE/B,YAAY,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAIhF;CACD;AAUD;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACxC,QAAQ,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,YAAY,CAAA;CAAE,EAC5C,WAAW,EAAE,eAAe,EAC5B,WAAW,EAAE,WAAW,EACxB,SAAS,CAAC,EAAE,uBAAuB,GACjC,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAiCjC"}
|
package/dist/auth/resolve.js
CHANGED
|
@@ -1,20 +1,30 @@
|
|
|
1
|
+
import { formatThrownValue } from "../utils/diagnostics.js";
|
|
1
2
|
export class ModelsError extends Error {
|
|
2
3
|
constructor(code, message, options) {
|
|
3
|
-
super(message, options);
|
|
4
|
+
super(withCauseDetail(message, options?.cause), options);
|
|
4
5
|
this.name = "ModelsError";
|
|
5
6
|
this.code = code;
|
|
6
7
|
}
|
|
7
8
|
}
|
|
9
|
+
/** Callers surface `error.message` only, so keep the underlying reason in it. */
|
|
10
|
+
function withCauseDetail(message, cause) {
|
|
11
|
+
if (cause === undefined || cause === null)
|
|
12
|
+
return message;
|
|
13
|
+
const detail = formatThrownValue(cause).trim();
|
|
14
|
+
if (!detail || message.includes(detail))
|
|
15
|
+
return message;
|
|
16
|
+
return `${message}: ${detail}`;
|
|
17
|
+
}
|
|
8
18
|
/**
|
|
9
19
|
* Auth resolution shared by the `Models` and `ImagesModels` collections.
|
|
10
20
|
* A stored credential owns the provider: ambient/env is consulted only when
|
|
11
21
|
* nothing is stored. No silent env fallback after a failed refresh or for a
|
|
12
22
|
* credential type without a matching handler.
|
|
13
23
|
*/
|
|
14
|
-
export async function resolveProviderAuth(provider,
|
|
24
|
+
export async function resolveProviderAuth(provider, credentials, authContext, overrides) {
|
|
15
25
|
const requestAuthContext = overrides?.env ? overlayEnvAuthContext(authContext, overrides.env) : authContext;
|
|
16
26
|
if (overrides?.apiKey !== undefined && provider.auth.apiKey) {
|
|
17
|
-
return resolveApiKey(requestAuthContext, provider.auth.apiKey,
|
|
27
|
+
return resolveApiKey(requestAuthContext, provider.auth.apiKey, provider.id, {
|
|
18
28
|
type: "api_key",
|
|
19
29
|
key: overrides.apiKey,
|
|
20
30
|
env: overrides.env,
|
|
@@ -23,16 +33,18 @@ export async function resolveProviderAuth(provider, model, credentials, authCont
|
|
|
23
33
|
const stored = await readCredential(credentials, provider.id);
|
|
24
34
|
if (stored) {
|
|
25
35
|
if (stored.type === "oauth" && provider.auth.oauth) {
|
|
26
|
-
return resolveStoredOAuth(credentials, provider.id, provider.auth.oauth, stored);
|
|
36
|
+
return resolveStoredOAuth(credentials, provider.id, provider.auth.oauth, stored, overrides?.minOAuthValidityMs);
|
|
27
37
|
}
|
|
28
38
|
if (stored.type === "api_key" && provider.auth.apiKey) {
|
|
29
39
|
const credential = overrides?.env ? { ...stored, env: { ...stored.env, ...overrides.env } } : stored;
|
|
30
|
-
return resolveApiKey(requestAuthContext, provider.auth.apiKey,
|
|
40
|
+
return resolveApiKey(requestAuthContext, provider.auth.apiKey, provider.id, credential);
|
|
31
41
|
}
|
|
32
42
|
return undefined;
|
|
33
43
|
}
|
|
34
44
|
// Ambient (env vars, AWS profiles, ADC files).
|
|
35
|
-
return provider.auth.apiKey
|
|
45
|
+
return provider.auth.apiKey
|
|
46
|
+
? resolveApiKey(requestAuthContext, provider.auth.apiKey, provider.id, undefined)
|
|
47
|
+
: undefined;
|
|
36
48
|
}
|
|
37
49
|
function overlayEnvAuthContext(base, env) {
|
|
38
50
|
return {
|
|
@@ -40,22 +52,24 @@ function overlayEnvAuthContext(base, env) {
|
|
|
40
52
|
fileExists: (path) => base.fileExists(path),
|
|
41
53
|
};
|
|
42
54
|
}
|
|
55
|
+
const DEFAULT_OAUTH_MINIMUM_VALIDITY_MS = 5 * 60 * 1000;
|
|
43
56
|
/**
|
|
44
|
-
* OAuth resolution with double-checked locking
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* credential before release.
|
|
57
|
+
* OAuth resolution with double-checked locking: tokens with less than five
|
|
58
|
+
* minutes remaining lock, re-check expiry under the lock, refresh once
|
|
59
|
+
* globally, and persist the rotated credential before release.
|
|
48
60
|
*/
|
|
49
|
-
async function resolveStoredOAuth(credentials, providerId, oauth, stored) {
|
|
61
|
+
async function resolveStoredOAuth(credentials, providerId, oauth, stored, minOAuthValidityMs) {
|
|
62
|
+
const minimumValidityMs = Math.max(DEFAULT_OAUTH_MINIMUM_VALIDITY_MS, minOAuthValidityMs ?? 0);
|
|
63
|
+
const expiresSoon = (credential) => Date.now() + minimumValidityMs >= credential.expires;
|
|
50
64
|
let credential = stored;
|
|
51
|
-
if (
|
|
65
|
+
if (expiresSoon(credential)) {
|
|
52
66
|
// Optimistic check said expired; the authoritative check runs under the lock.
|
|
53
67
|
let post;
|
|
54
68
|
try {
|
|
55
69
|
post = await credentials.modify(providerId, async (current) => {
|
|
56
70
|
if (current?.type !== "oauth")
|
|
57
71
|
return undefined; // logged out meanwhile
|
|
58
|
-
if (
|
|
72
|
+
if (!expiresSoon(current))
|
|
59
73
|
return undefined; // another process/request refreshed
|
|
60
74
|
try {
|
|
61
75
|
return await oauth.refresh(current);
|
|
@@ -73,6 +87,12 @@ async function resolveStoredOAuth(credentials, providerId, oauth, stored) {
|
|
|
73
87
|
if (post?.type !== "oauth")
|
|
74
88
|
return undefined; // logged out meanwhile
|
|
75
89
|
credential = post;
|
|
90
|
+
// The normal five-minute window triggers a refresh but does not impose a
|
|
91
|
+
// provider contract. Explicit callers (such as bearer-token export) do
|
|
92
|
+
// require the requested minimum after the refresh.
|
|
93
|
+
if (minOAuthValidityMs !== undefined && expiresSoon(credential)) {
|
|
94
|
+
throw new ModelsError("oauth", `OAuth refresh returned a token that expires too soon for ${providerId}`);
|
|
95
|
+
}
|
|
76
96
|
}
|
|
77
97
|
try {
|
|
78
98
|
return { auth: await oauth.toAuth(credential), source: "OAuth" };
|
|
@@ -81,12 +101,12 @@ async function resolveStoredOAuth(credentials, providerId, oauth, stored) {
|
|
|
81
101
|
throw new ModelsError("oauth", `OAuth auth derivation failed for ${providerId}`, { cause: error });
|
|
82
102
|
}
|
|
83
103
|
}
|
|
84
|
-
async function resolveApiKey(authContext, apiKey,
|
|
104
|
+
async function resolveApiKey(authContext, apiKey, providerId, credential) {
|
|
85
105
|
try {
|
|
86
|
-
return await apiKey.resolve({
|
|
106
|
+
return await apiKey.resolve({ ctx: authContext, credential });
|
|
87
107
|
}
|
|
88
108
|
catch (error) {
|
|
89
|
-
throw new ModelsError("auth", `API key auth failed for provider ${
|
|
109
|
+
throw new ModelsError("auth", `API key auth failed for provider ${providerId}`, { cause: error });
|
|
90
110
|
}
|
|
91
111
|
}
|
|
92
112
|
async function readCredential(credentials, providerId) {
|
package/dist/auth/resolve.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/auth/resolve.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Api, ImagesApi, ImagesModel, Model, ProviderEnv } from \"../types.ts\";\nimport type {\n\tApiKeyAuth,\n\tApiKeyCredential,\n\tAuthContext,\n\tAuthResult,\n\tCredential,\n\tCredentialStore,\n\tOAuthAuth,\n\tOAuthCredential,\n\tProviderAuth,\n} from \"./types.ts\";\n\nexport type ModelsErrorCode = \"model_source\" | \"model_validation\" | \"provider\" | \"stream\" | \"auth\" | \"oauth\";\n\nexport interface AuthResolutionOverrides {\n\tapiKey?: string;\n\tenv?: ProviderEnv;\n}\n\nexport class ModelsError extends Error {\n\treadonly code: ModelsErrorCode;\n\n\tconstructor(code: ModelsErrorCode, message: string, options?: { cause?: unknown }) {\n\t\tsuper(message, options);\n\t\tthis.name = \"ModelsError\";\n\t\tthis.code = code;\n\t}\n}\n\n/** Model shape auth resolution receives: chat or image-generation models. */\nexport type AuthModel = Model<Api> | ImagesModel<ImagesApi>;\n\n/**\n * Auth resolution shared by the `Models` and `ImagesModels` collections.\n * A stored credential owns the provider: ambient/env is consulted only when\n * nothing is stored. No silent env fallback after a failed refresh or for a\n * credential type without a matching handler.\n */\nexport async function resolveProviderAuth(\n\tprovider: { id: string; auth: ProviderAuth },\n\tmodel: AuthModel,\n\tcredentials: CredentialStore,\n\tauthContext: AuthContext,\n\toverrides?: AuthResolutionOverrides,\n): Promise<AuthResult | undefined> {\n\tconst requestAuthContext = overrides?.env ? overlayEnvAuthContext(authContext, overrides.env) : authContext;\n\n\tif (overrides?.apiKey !== undefined && provider.auth.apiKey) {\n\t\treturn resolveApiKey(requestAuthContext, provider.auth.apiKey, model, {\n\t\t\ttype: \"api_key\",\n\t\t\tkey: overrides.apiKey,\n\t\t\tenv: overrides.env,\n\t\t});\n\t}\n\n\tconst stored = await readCredential(credentials, provider.id);\n\tif (stored) {\n\t\tif (stored.type === \"oauth\" && provider.auth.oauth) {\n\t\t\treturn resolveStoredOAuth(credentials, provider.id, provider.auth.oauth, stored);\n\t\t}\n\t\tif (stored.type === \"api_key\" && provider.auth.apiKey) {\n\t\t\tconst credential = overrides?.env ? { ...stored, env: { ...stored.env, ...overrides.env } } : stored;\n\t\t\treturn resolveApiKey(requestAuthContext, provider.auth.apiKey, model, credential);\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t// Ambient (env vars, AWS profiles, ADC files).\n\treturn provider.auth.apiKey ? resolveApiKey(requestAuthContext, provider.auth.apiKey, model, undefined) : undefined;\n}\n\nfunction overlayEnvAuthContext(base: AuthContext, env: ProviderEnv): AuthContext {\n\treturn {\n\t\tenv: async (name) => env[name] || (await base.env(name)),\n\t\tfileExists: (path) => base.fileExists(path),\n\t};\n}\n\n/**\n * OAuth resolution with double-checked locking (same pattern as today's\n * AuthStorage): valid tokens cost zero locks; expired tokens lock, re-check\n * expiry under the lock, refresh once globally, and persist the rotated\n * credential before release.\n */\nasync function resolveStoredOAuth(\n\tcredentials: CredentialStore,\n\tproviderId: string,\n\toauth: OAuthAuth,\n\tstored: OAuthCredential,\n): Promise<AuthResult | undefined> {\n\tlet credential = stored;\n\n\tif (Date.now() >= credential.expires) {\n\t\t// Optimistic check said expired; the authoritative check runs under the lock.\n\t\tlet post: Credential | undefined;\n\t\ttry {\n\t\t\tpost = await credentials.modify(providerId, async (current) => {\n\t\t\t\tif (current?.type !== \"oauth\") return undefined; // logged out meanwhile\n\t\t\t\tif (Date.now() < current.expires) return undefined; // another process/request refreshed\n\t\t\t\ttry {\n\t\t\t\t\treturn await oauth.refresh(current);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow new ModelsError(\"oauth\", `OAuth refresh failed for ${providerId}`, { cause: error });\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (error instanceof ModelsError) throw error;\n\t\t\tthrow new ModelsError(\"auth\", `Credential store modify failed for ${providerId}`, { cause: error });\n\t\t}\n\t\tif (post?.type !== \"oauth\") return undefined; // logged out meanwhile\n\t\tcredential = post;\n\t}\n\n\ttry {\n\t\treturn { auth: await oauth.toAuth(credential), source: \"OAuth\" };\n\t} catch (error) {\n\t\tthrow new ModelsError(\"oauth\", `OAuth auth derivation failed for ${providerId}`, { cause: error });\n\t}\n}\n\nasync function resolveApiKey(\n\tauthContext: AuthContext,\n\tapiKey: ApiKeyAuth,\n\tmodel: AuthModel,\n\tcredential: ApiKeyCredential | undefined,\n): Promise<AuthResult | undefined> {\n\ttry {\n\t\treturn await apiKey.resolve({ model, ctx: authContext, credential });\n\t} catch (error) {\n\t\tthrow new ModelsError(\"auth\", `API key auth failed for provider ${model.provider}`, { cause: error });\n\t}\n}\n\nasync function readCredential(credentials: CredentialStore, providerId: string): Promise<Credential | undefined> {\n\ttry {\n\t\treturn await credentials.read(providerId);\n\t} catch (error) {\n\t\tthrow new ModelsError(\"auth\", `Credential store read failed for ${providerId}`, { cause: error });\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/auth/resolve.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ProviderEnv } from \"../types.ts\";\nimport { formatThrownValue } from \"../utils/diagnostics.ts\";\nimport type {\n\tApiKeyAuth,\n\tApiKeyCredential,\n\tAuthContext,\n\tAuthResult,\n\tCredential,\n\tCredentialStore,\n\tOAuthAuth,\n\tOAuthCredential,\n\tProviderAuth,\n} from \"./types.ts\";\n\nexport type ModelsErrorCode = \"model_source\" | \"model_validation\" | \"provider\" | \"stream\" | \"auth\" | \"oauth\";\n\nexport interface AuthResolutionOverrides {\n\tapiKey?: string;\n\tenv?: ProviderEnv;\n\t/** Require this much remaining OAuth-token validity; defaults to five minutes. */\n\tminOAuthValidityMs?: number;\n}\n\nexport class ModelsError extends Error {\n\treadonly code: ModelsErrorCode;\n\n\tconstructor(code: ModelsErrorCode, message: string, options?: { cause?: unknown }) {\n\t\tsuper(withCauseDetail(message, options?.cause), options);\n\t\tthis.name = \"ModelsError\";\n\t\tthis.code = code;\n\t}\n}\n\n/** Callers surface `error.message` only, so keep the underlying reason in it. */\nfunction withCauseDetail(message: string, cause: unknown): string {\n\tif (cause === undefined || cause === null) return message;\n\tconst detail = formatThrownValue(cause).trim();\n\tif (!detail || message.includes(detail)) return message;\n\treturn `${message}: ${detail}`;\n}\n\n/**\n * Auth resolution shared by the `Models` and `ImagesModels` collections.\n * A stored credential owns the provider: ambient/env is consulted only when\n * nothing is stored. No silent env fallback after a failed refresh or for a\n * credential type without a matching handler.\n */\nexport async function resolveProviderAuth(\n\tprovider: { id: string; auth: ProviderAuth },\n\tcredentials: CredentialStore,\n\tauthContext: AuthContext,\n\toverrides?: AuthResolutionOverrides,\n): Promise<AuthResult | undefined> {\n\tconst requestAuthContext = overrides?.env ? overlayEnvAuthContext(authContext, overrides.env) : authContext;\n\n\tif (overrides?.apiKey !== undefined && provider.auth.apiKey) {\n\t\treturn resolveApiKey(requestAuthContext, provider.auth.apiKey, provider.id, {\n\t\t\ttype: \"api_key\",\n\t\t\tkey: overrides.apiKey,\n\t\t\tenv: overrides.env,\n\t\t});\n\t}\n\n\tconst stored = await readCredential(credentials, provider.id);\n\tif (stored) {\n\t\tif (stored.type === \"oauth\" && provider.auth.oauth) {\n\t\t\treturn resolveStoredOAuth(\n\t\t\t\tcredentials,\n\t\t\t\tprovider.id,\n\t\t\t\tprovider.auth.oauth,\n\t\t\t\tstored,\n\t\t\t\toverrides?.minOAuthValidityMs,\n\t\t\t);\n\t\t}\n\t\tif (stored.type === \"api_key\" && provider.auth.apiKey) {\n\t\t\tconst credential = overrides?.env ? { ...stored, env: { ...stored.env, ...overrides.env } } : stored;\n\t\t\treturn resolveApiKey(requestAuthContext, provider.auth.apiKey, provider.id, credential);\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t// Ambient (env vars, AWS profiles, ADC files).\n\treturn provider.auth.apiKey\n\t\t? resolveApiKey(requestAuthContext, provider.auth.apiKey, provider.id, undefined)\n\t\t: undefined;\n}\n\nfunction overlayEnvAuthContext(base: AuthContext, env: ProviderEnv): AuthContext {\n\treturn {\n\t\tenv: async (name) => env[name] || (await base.env(name)),\n\t\tfileExists: (path) => base.fileExists(path),\n\t};\n}\n\nconst DEFAULT_OAUTH_MINIMUM_VALIDITY_MS = 5 * 60 * 1000;\n\n/**\n * OAuth resolution with double-checked locking: tokens with less than five\n * minutes remaining lock, re-check expiry under the lock, refresh once\n * globally, and persist the rotated credential before release.\n */\nasync function resolveStoredOAuth(\n\tcredentials: CredentialStore,\n\tproviderId: string,\n\toauth: OAuthAuth,\n\tstored: OAuthCredential,\n\tminOAuthValidityMs?: number,\n): Promise<AuthResult | undefined> {\n\tconst minimumValidityMs = Math.max(DEFAULT_OAUTH_MINIMUM_VALIDITY_MS, minOAuthValidityMs ?? 0);\n\tconst expiresSoon = (credential: OAuthCredential) => Date.now() + minimumValidityMs >= credential.expires;\n\tlet credential = stored;\n\n\tif (expiresSoon(credential)) {\n\t\t// Optimistic check said expired; the authoritative check runs under the lock.\n\t\tlet post: Credential | undefined;\n\t\ttry {\n\t\t\tpost = await credentials.modify(providerId, async (current) => {\n\t\t\t\tif (current?.type !== \"oauth\") return undefined; // logged out meanwhile\n\t\t\t\tif (!expiresSoon(current)) return undefined; // another process/request refreshed\n\t\t\t\ttry {\n\t\t\t\t\treturn await oauth.refresh(current);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow new ModelsError(\"oauth\", `OAuth refresh failed for ${providerId}`, { cause: error });\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (error instanceof ModelsError) throw error;\n\t\t\tthrow new ModelsError(\"auth\", `Credential store modify failed for ${providerId}`, { cause: error });\n\t\t}\n\t\tif (post?.type !== \"oauth\") return undefined; // logged out meanwhile\n\t\tcredential = post;\n\t\t// The normal five-minute window triggers a refresh but does not impose a\n\t\t// provider contract. Explicit callers (such as bearer-token export) do\n\t\t// require the requested minimum after the refresh.\n\t\tif (minOAuthValidityMs !== undefined && expiresSoon(credential)) {\n\t\t\tthrow new ModelsError(\"oauth\", `OAuth refresh returned a token that expires too soon for ${providerId}`);\n\t\t}\n\t}\n\n\ttry {\n\t\treturn { auth: await oauth.toAuth(credential), source: \"OAuth\" };\n\t} catch (error) {\n\t\tthrow new ModelsError(\"oauth\", `OAuth auth derivation failed for ${providerId}`, { cause: error });\n\t}\n}\n\nasync function resolveApiKey(\n\tauthContext: AuthContext,\n\tapiKey: ApiKeyAuth,\n\tproviderId: string,\n\tcredential: ApiKeyCredential | undefined,\n): Promise<AuthResult | undefined> {\n\ttry {\n\t\treturn await apiKey.resolve({ ctx: authContext, credential });\n\t} catch (error) {\n\t\tthrow new ModelsError(\"auth\", `API key auth failed for provider ${providerId}`, { cause: error });\n\t}\n}\n\nasync function readCredential(credentials: CredentialStore, providerId: string): Promise<Credential | undefined> {\n\ttry {\n\t\treturn await credentials.read(providerId);\n\t} catch (error) {\n\t\tthrow new ModelsError(\"auth\", `Credential store read failed for ${providerId}`, { cause: error });\n\t}\n}\n"]}
|