@ny4n/ai 0.0.0-stage → 1.0.0
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/LICENSE +21 -0
- package/README.md +1940 -2
- 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 +1310 -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-config.d.ts +15 -0
- package/dist/api/azure-openai-config.d.ts.map +1 -0
- package/dist/api/azure-openai-config.js +76 -0
- package/dist/api/azure-openai-config.js.map +1 -0
- package/dist/api/azure-openai-responses.d.ts +14 -0
- package/dist/api/azure-openai-responses.d.ts.map +1 -0
- package/dist/api/azure-openai-responses.js +194 -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 +1147 -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/classifier-shared.d.ts +21 -0
- package/dist/api/classifier-shared.d.ts.map +1 -0
- package/dist/api/classifier-shared.js +98 -0
- package/dist/api/classifier-shared.js.map +1 -0
- package/dist/api/cloudflare-ai-binding.d.ts +77 -0
- package/dist/api/cloudflare-ai-binding.d.ts.map +1 -0
- package/dist/api/cloudflare-ai-binding.js +72 -0
- package/dist/api/cloudflare-ai-binding.js.map +1 -0
- package/dist/api/cloudflare-workers-ai-system-one.d.ts +4 -0
- package/dist/api/cloudflare-workers-ai-system-one.d.ts.map +1 -0
- package/dist/api/cloudflare-workers-ai-system-one.js +49 -0
- package/dist/api/cloudflare-workers-ai-system-one.js.map +1 -0
- package/dist/api/cloudflare-workers-ai-system-one.lazy.d.ts +3 -0
- package/dist/api/cloudflare-workers-ai-system-one.lazy.d.ts.map +1 -0
- package/dist/api/cloudflare-workers-ai-system-one.lazy.js +4 -0
- package/dist/api/cloudflare-workers-ai-system-one.lazy.js.map +1 -0
- package/dist/api/cloudflare.d.ts +11 -0
- package/dist/api/cloudflare.d.ts.map +1 -0
- package/dist/api/cloudflare.js +11 -0
- package/dist/api/cloudflare.js.map +1 -0
- package/dist/api/constrained-sampling.d.ts +26 -0
- package/dist/api/constrained-sampling.d.ts.map +1 -0
- package/dist/api/constrained-sampling.js +233 -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 +370 -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 +93 -0
- package/dist/api/google-shared.d.ts.map +1 -0
- package/dist/api/google-shared.js +451 -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 +431 -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 +19 -0
- package/dist/api/lazy.d.ts.map +1 -0
- package/dist/api/lazy.js +71 -0
- package/dist/api/lazy.js.map +1 -0
- package/dist/api/llama-cpp-classify.d.ts +33 -0
- package/dist/api/llama-cpp-classify.d.ts.map +1 -0
- package/dist/api/llama-cpp-classify.js +367 -0
- package/dist/api/llama-cpp-classify.js.map +1 -0
- package/dist/api/llama-cpp-classify.lazy.d.ts +3 -0
- package/dist/api/llama-cpp-classify.lazy.d.ts.map +1 -0
- package/dist/api/llama-cpp-classify.lazy.js +4 -0
- package/dist/api/llama-cpp-classify.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 +766 -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 +1321 -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 +26 -0
- package/dist/api/openai-completions.d.ts.map +1 -0
- package/dist/api/openai-completions.js +1345 -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-decisions.d.ts +4 -0
- package/dist/api/openai-decisions.d.ts.map +1 -0
- package/dist/api/openai-decisions.js +162 -0
- package/dist/api/openai-decisions.js.map +1 -0
- package/dist/api/openai-decisions.lazy.d.ts +3 -0
- package/dist/api/openai-decisions.lazy.d.ts.map +1 -0
- package/dist/api/openai-decisions.lazy.js +4 -0
- package/dist/api/openai-decisions.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 +704 -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 +314 -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 +4 -0
- package/dist/api/openrouter-images.d.ts.map +1 -0
- package/dist/api/openrouter-images.js +133 -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/simple-options.d.ts +16 -0
- package/dist/api/simple-options.d.ts.map +1 -0
- package/dist/api/simple-options.js +73 -0
- package/dist/api/simple-options.js.map +1 -0
- package/dist/api/system-one-shared.d.ts +22 -0
- package/dist/api/system-one-shared.d.ts.map +1 -0
- package/dist/api/system-one-shared.js +99 -0
- package/dist/api/system-one-shared.js.map +1 -0
- package/dist/api/transform-messages.d.ts +8 -0
- package/dist/api/transform-messages.d.ts.map +1 -0
- package/dist/api/transform-messages.js +201 -0
- package/dist/api/transform-messages.js.map +1 -0
- package/dist/api/typesafe-system-one.d.ts +4 -0
- package/dist/api/typesafe-system-one.d.ts.map +1 -0
- package/dist/api/typesafe-system-one.js +20 -0
- package/dist/api/typesafe-system-one.js.map +1 -0
- package/dist/api/typesafe-system-one.lazy.d.ts +3 -0
- package/dist/api/typesafe-system-one.lazy.d.ts.map +1 -0
- package/dist/api/typesafe-system-one.lazy.js +4 -0
- package/dist/api/typesafe-system-one.lazy.js.map +1 -0
- package/dist/api-options.d.ts +39 -0
- package/dist/api-options.d.ts.map +1 -0
- package/dist/api-options.js +9 -0
- package/dist/api-options.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 +51 -0
- package/dist/auth/credential-store.js.map +1 -0
- package/dist/auth/helpers.d.ts +22 -0
- package/dist/auth/helpers.d.ts.map +1 -0
- package/dist/auth/helpers.js +53 -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 +257 -0
- package/dist/auth/oauth/anthropic.js.map +1 -0
- package/dist/auth/oauth/callback-server.d.ts +55 -0
- package/dist/auth/oauth/callback-server.d.ts.map +1 -0
- package/dist/auth/oauth/callback-server.js +146 -0
- package/dist/auth/oauth/callback-server.js.map +1 -0
- package/dist/auth/oauth/device-code.d.ts +24 -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 +392 -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 +248 -0
- package/dist/auth/oauth/kimi-coding.js.map +1 -0
- package/dist/auth/oauth/load.d.ts +23 -0
- package/dist/auth/oauth/load.d.ts.map +1 -0
- package/dist/auth/oauth/load.js +64 -0
- package/dist/auth/oauth/load.js.map +1 -0
- package/dist/auth/oauth/meta.d.ts +17 -0
- package/dist/auth/oauth/meta.d.ts.map +1 -0
- package/dist/auth/oauth/meta.js +190 -0
- package/dist/auth/oauth/meta.js.map +1 -0
- package/dist/auth/oauth/openai-chatgpt.d.ts +9 -0
- package/dist/auth/oauth/openai-chatgpt.d.ts.map +1 -0
- package/dist/auth/oauth/openai-chatgpt.js +263 -0
- package/dist/auth/oauth/openai-chatgpt.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 +346 -0
- package/dist/auth/oauth/openai-codex.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 +158 -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/xai.d.ts +6 -0
- package/dist/auth/oauth/xai.d.ts.map +1 -0
- package/dist/auth/oauth/xai.js +190 -0
- package/dist/auth/oauth/xai.js.map +1 -0
- package/dist/auth/resolve.d.ts +36 -0
- package/dist/auth/resolve.d.ts.map +1 -0
- package/dist/auth/resolve.js +140 -0
- package/dist/auth/resolve.js.map +1 -0
- package/dist/auth/types.d.ts +245 -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 +23 -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 +115 -0
- package/dist/cli.js.map +1 -0
- 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 +66 -0
- package/dist/compat.d.ts.map +1 -0
- package/dist/compat.js +199 -0
- package/dist/compat.js.map +1 -0
- package/dist/contracts/index.d.ts +30 -0
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +12 -0
- package/dist/contracts/index.js.map +1 -0
- package/dist/env-api-keys.d.ts +26 -0
- package/dist/env-api-keys.d.ts.map +1 -0
- package/dist/env-api-keys.js +162 -0
- package/dist/env-api-keys.js.map +1 -0
- package/dist/image-models.d.ts +21 -0
- package/dist/image-models.d.ts.map +1 -0
- package/dist/image-models.js +24 -0
- package/dist/image-models.js.map +1 -0
- package/dist/images-api-registry.d.ts +14 -0
- package/dist/images-api-registry.d.ts.map +1 -0
- package/dist/images-api-registry.js +22 -0
- package/dist/images-api-registry.js.map +1 -0
- package/dist/images.d.ts +9 -0
- package/dist/images.d.ts.map +1 -0
- package/dist/images.js +19 -0
- package/dist/images.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -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 +33 -0
- package/dist/model-catalog.d.ts.map +1 -0
- package/dist/model-catalog.js +16 -0
- package/dist/model-catalog.js.map +1 -0
- package/dist/models-store.d.ts +30 -0
- package/dist/models-store.d.ts.map +1 -0
- package/dist/models-store.js +17 -0
- package/dist/models-store.js.map +1 -0
- package/dist/models.d.ts +250 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.generated.d.ts +171 -0
- package/dist/models.generated.d.ts.map +1 -0
- package/dist/models.generated.js +173 -0
- package/dist/models.generated.js.map +1 -0
- package/dist/models.js +644 -0
- package/dist/models.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/all.d.ts +31 -0
- package/dist/providers/all.d.ts.map +1 -0
- package/dist/providers/all.js +134 -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 +93 -0
- package/dist/providers/amazon-bedrock.js.map +1 -0
- package/dist/providers/amazon-bedrock.models.d.ts +6 -0
- package/dist/providers/amazon-bedrock.models.d.ts.map +1 -0
- package/dist/providers/amazon-bedrock.models.js +8 -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 +6 -0
- package/dist/providers/ant-ling.models.d.ts.map +1 -0
- package/dist/providers/ant-ling.models.js +8 -0
- package/dist/providers/ant-ling.models.js.map +1 -0
- package/dist/providers/anthropic.d.ts +3 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +78 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/anthropic.models.d.ts +6 -0
- package/dist/providers/anthropic.models.d.ts.map +1 -0
- package/dist/providers/anthropic.models.js +8 -0
- package/dist/providers/anthropic.models.js.map +1 -0
- package/dist/providers/azure.d.ts +3 -0
- package/dist/providers/azure.d.ts.map +1 -0
- package/dist/providers/azure.js +46 -0
- package/dist/providers/azure.js.map +1 -0
- package/dist/providers/azure.models.d.ts +6 -0
- package/dist/providers/azure.models.d.ts.map +1 -0
- package/dist/providers/azure.models.js +8 -0
- package/dist/providers/azure.models.js.map +1 -0
- package/dist/providers/baseten.d.ts +3 -0
- package/dist/providers/baseten.d.ts.map +1 -0
- package/dist/providers/baseten.js +15 -0
- package/dist/providers/baseten.js.map +1 -0
- package/dist/providers/baseten.models.d.ts +6 -0
- package/dist/providers/baseten.models.d.ts.map +1 -0
- package/dist/providers/baseten.models.js +8 -0
- package/dist/providers/baseten.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 +6 -0
- package/dist/providers/cerebras.models.d.ts.map +1 -0
- package/dist/providers/cerebras.models.js +8 -0
- package/dist/providers/cerebras.models.js.map +1 -0
- package/dist/providers/cloudflare-ai-gateway.d.ts +5 -0
- package/dist/providers/cloudflare-ai-gateway.d.ts.map +1 -0
- package/dist/providers/cloudflare-ai-gateway.js +25 -0
- package/dist/providers/cloudflare-ai-gateway.js.map +1 -0
- package/dist/providers/cloudflare-ai-gateway.models.d.ts +6 -0
- package/dist/providers/cloudflare-ai-gateway.models.d.ts.map +1 -0
- package/dist/providers/cloudflare-ai-gateway.models.js +8 -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 +86 -0
- package/dist/providers/cloudflare-auth.js.map +1 -0
- package/dist/providers/cloudflare-stream.d.ts +12 -0
- package/dist/providers/cloudflare-stream.d.ts.map +1 -0
- package/dist/providers/cloudflare-stream.js +27 -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 +22 -0
- package/dist/providers/cloudflare-workers-ai.js.map +1 -0
- package/dist/providers/cloudflare-workers-ai.models.d.ts +6 -0
- package/dist/providers/cloudflare-workers-ai.models.d.ts.map +1 -0
- package/dist/providers/cloudflare-workers-ai.models.js +8 -0
- package/dist/providers/cloudflare-workers-ai.models.js.map +1 -0
- 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.json +1 -0
- package/dist/providers/data/baseten.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/meta.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-individual.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/typesafe.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 +6 -0
- package/dist/providers/deepseek.models.d.ts.map +1 -0
- package/dist/providers/deepseek.models.js +8 -0
- package/dist/providers/deepseek.models.js.map +1 -0
- package/dist/providers/faux.d.ts +103 -0
- package/dist/providers/faux.d.ts.map +1 -0
- package/dist/providers/faux.js +506 -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 +6 -0
- package/dist/providers/fireworks.models.d.ts.map +1 -0
- package/dist/providers/fireworks.models.js +8 -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 +6 -0
- package/dist/providers/github-copilot.models.d.ts.map +1 -0
- package/dist/providers/github-copilot.models.js +8 -0
- package/dist/providers/github-copilot.models.js.map +1 -0
- package/dist/providers/google-vertex.d.ts +3 -0
- package/dist/providers/google-vertex.d.ts.map +1 -0
- package/dist/providers/google-vertex.js +94 -0
- package/dist/providers/google-vertex.js.map +1 -0
- package/dist/providers/google-vertex.models.d.ts +6 -0
- package/dist/providers/google-vertex.models.d.ts.map +1 -0
- package/dist/providers/google-vertex.models.js +8 -0
- package/dist/providers/google-vertex.models.js.map +1 -0
- package/dist/providers/google.d.ts +3 -0
- package/dist/providers/google.d.ts.map +1 -0
- package/dist/providers/google.js +15 -0
- package/dist/providers/google.js.map +1 -0
- package/dist/providers/google.models.d.ts +6 -0
- package/dist/providers/google.models.d.ts.map +1 -0
- package/dist/providers/google.models.js +8 -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 +6 -0
- package/dist/providers/groq.models.d.ts.map +1 -0
- package/dist/providers/groq.models.js +8 -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 +6 -0
- package/dist/providers/huggingface.models.d.ts.map +1 -0
- package/dist/providers/huggingface.models.js +8 -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 +24 -0
- package/dist/providers/kimi-coding.js.map +1 -0
- package/dist/providers/kimi-coding.models.d.ts +6 -0
- package/dist/providers/kimi-coding.models.d.ts.map +1 -0
- package/dist/providers/kimi-coding.models.js +8 -0
- package/dist/providers/kimi-coding.models.js.map +1 -0
- package/dist/providers/meta.d.ts +3 -0
- package/dist/providers/meta.d.ts.map +1 -0
- package/dist/providers/meta.js +24 -0
- package/dist/providers/meta.js.map +1 -0
- package/dist/providers/meta.models.d.ts +6 -0
- package/dist/providers/meta.models.d.ts.map +1 -0
- package/dist/providers/meta.models.js +8 -0
- package/dist/providers/meta.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 +6 -0
- package/dist/providers/minimax-cn.models.d.ts.map +1 -0
- package/dist/providers/minimax-cn.models.js +8 -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 +6 -0
- package/dist/providers/minimax.models.d.ts.map +1 -0
- package/dist/providers/minimax.models.js +8 -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 +6 -0
- package/dist/providers/mistral.models.d.ts.map +1 -0
- package/dist/providers/mistral.models.js +8 -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 +6 -0
- package/dist/providers/moonshotai-cn.models.d.ts.map +1 -0
- package/dist/providers/moonshotai-cn.models.js +8 -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 +6 -0
- package/dist/providers/moonshotai.models.d.ts.map +1 -0
- package/dist/providers/moonshotai.models.js +8 -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 +6 -0
- package/dist/providers/nvidia.models.d.ts.map +1 -0
- package/dist/providers/nvidia.models.js +8 -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 +22 -0
- package/dist/providers/openai-codex.js.map +1 -0
- package/dist/providers/openai-codex.models.d.ts +6 -0
- package/dist/providers/openai-codex.models.d.ts.map +1 -0
- package/dist/providers/openai-codex.models.js +8 -0
- package/dist/providers/openai-codex.models.js.map +1 -0
- package/dist/providers/openai.d.ts +3 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +33 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/openai.models.d.ts +6 -0
- package/dist/providers/openai.models.d.ts.map +1 -0
- package/dist/providers/openai.models.js +8 -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 +21 -0
- package/dist/providers/opencode-go.js.map +1 -0
- package/dist/providers/opencode-go.models.d.ts +6 -0
- package/dist/providers/opencode-go.models.d.ts.map +1 -0
- package/dist/providers/opencode-go.models.js +8 -0
- package/dist/providers/opencode-go.models.js.map +1 -0
- package/dist/providers/opencode-headers.d.ts +4 -0
- package/dist/providers/opencode-headers.d.ts.map +1 -0
- package/dist/providers/opencode-headers.js +22 -0
- package/dist/providers/opencode-headers.js.map +1 -0
- package/dist/providers/opencode.d.ts +5 -0
- package/dist/providers/opencode.d.ts.map +1 -0
- package/dist/providers/opencode.js +26 -0
- package/dist/providers/opencode.js.map +1 -0
- package/dist/providers/opencode.models.d.ts +6 -0
- package/dist/providers/opencode.models.d.ts.map +1 -0
- package/dist/providers/opencode.models.js +8 -0
- package/dist/providers/opencode.models.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 +36 -0
- package/dist/providers/openrouter.js.map +1 -0
- package/dist/providers/openrouter.models.d.ts +6 -0
- package/dist/providers/openrouter.models.d.ts.map +1 -0
- package/dist/providers/openrouter.models.js +8 -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 +6 -0
- package/dist/providers/qwen-token-plan-cn.models.d.ts.map +1 -0
- package/dist/providers/qwen-token-plan-cn.models.js +8 -0
- package/dist/providers/qwen-token-plan-cn.models.js.map +1 -0
- package/dist/providers/qwen-token-plan-individual.d.ts +3 -0
- package/dist/providers/qwen-token-plan-individual.d.ts.map +1 -0
- package/dist/providers/qwen-token-plan-individual.js +15 -0
- package/dist/providers/qwen-token-plan-individual.js.map +1 -0
- package/dist/providers/qwen-token-plan-individual.models.d.ts +6 -0
- package/dist/providers/qwen-token-plan-individual.models.d.ts.map +1 -0
- package/dist/providers/qwen-token-plan-individual.models.js +8 -0
- package/dist/providers/qwen-token-plan-individual.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 +6 -0
- package/dist/providers/qwen-token-plan.models.d.ts.map +1 -0
- package/dist/providers/qwen-token-plan.models.js +8 -0
- package/dist/providers/qwen-token-plan.models.js.map +1 -0
- package/dist/providers/together.d.ts +3 -0
- package/dist/providers/together.d.ts.map +1 -0
- package/dist/providers/together.js +15 -0
- package/dist/providers/together.js.map +1 -0
- package/dist/providers/together.models.d.ts +6 -0
- package/dist/providers/together.models.d.ts.map +1 -0
- package/dist/providers/together.models.js +8 -0
- package/dist/providers/together.models.js.map +1 -0
- package/dist/providers/typesafe.d.ts +3 -0
- package/dist/providers/typesafe.d.ts.map +1 -0
- package/dist/providers/typesafe.js +18 -0
- package/dist/providers/typesafe.js.map +1 -0
- package/dist/providers/typesafe.models.d.ts +6 -0
- package/dist/providers/typesafe.models.d.ts.map +1 -0
- package/dist/providers/typesafe.models.js +8 -0
- package/dist/providers/typesafe.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 +18 -0
- package/dist/providers/vercel-ai-gateway.js.map +1 -0
- package/dist/providers/vercel-ai-gateway.models.d.ts +6 -0
- package/dist/providers/vercel-ai-gateway.models.d.ts.map +1 -0
- package/dist/providers/vercel-ai-gateway.models.js +8 -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 +24 -0
- package/dist/providers/xai.js.map +1 -0
- package/dist/providers/xai.models.d.ts +6 -0
- package/dist/providers/xai.models.d.ts.map +1 -0
- package/dist/providers/xai.models.js +8 -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 +6 -0
- package/dist/providers/xiaomi-token-plan-ams.models.d.ts.map +1 -0
- package/dist/providers/xiaomi-token-plan-ams.models.js +8 -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 +6 -0
- package/dist/providers/xiaomi-token-plan-cn.models.d.ts.map +1 -0
- package/dist/providers/xiaomi-token-plan-cn.models.js +8 -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 +6 -0
- package/dist/providers/xiaomi-token-plan-sgp.models.d.ts.map +1 -0
- package/dist/providers/xiaomi-token-plan-sgp.models.js +8 -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 +6 -0
- package/dist/providers/xiaomi.models.d.ts.map +1 -0
- package/dist/providers/xiaomi.models.js +8 -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 +6 -0
- package/dist/providers/zai-coding-cn.models.d.ts.map +1 -0
- package/dist/providers/zai-coding-cn.models.js +8 -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 +6 -0
- package/dist/providers/zai.models.d.ts.map +1 -0
- package/dist/providers/zai.models.js +8 -0
- package/dist/providers/zai.models.js.map +1 -0
- package/dist/schemas/compat-schema.d.ts +338 -0
- package/dist/schemas/compat-schema.d.ts.map +1 -0
- package/dist/schemas/compat-schema.js +375 -0
- package/dist/schemas/compat-schema.js.map +1 -0
- package/dist/schemas/model-schema.d.ts +91 -0
- package/dist/schemas/model-schema.d.ts.map +1 -0
- package/dist/schemas/model-schema.js +55 -0
- package/dist/schemas/model-schema.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/types.d.ts +645 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -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/abort.d.ts +8 -0
- package/dist/utils/abort.d.ts.map +1 -0
- package/dist/utils/abort.js +49 -0
- package/dist/utils/abort.js.map +1 -0
- package/dist/utils/assistant-message-frame.d.ts +77 -0
- package/dist/utils/assistant-message-frame.d.ts.map +1 -0
- package/dist/utils/assistant-message-frame.js +425 -0
- package/dist/utils/assistant-message-frame.js.map +1 -0
- package/dist/utils/diagnostics.d.ts +20 -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 +133 -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 +95 -0
- package/dist/utils/estimate.js.map +1 -0
- package/dist/utils/event-stream.d.ts +30 -0
- package/dist/utils/event-stream.d.ts.map +1 -0
- package/dist/utils/event-stream.js +124 -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 +20 -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/model-operations.d.ts +34 -0
- package/dist/utils/model-operations.d.ts.map +1 -0
- package/dist/utils/model-operations.js +129 -0
- package/dist/utils/model-operations.js.map +1 -0
- package/dist/utils/models-error.d.ts +8 -0
- package/dist/utils/models-error.d.ts.map +1 -0
- package/dist/utils/models-error.js +19 -0
- package/dist/utils/models-error.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 +133 -0
- package/dist/utils/node-http-proxy.js.map +1 -0
- package/dist/utils/nyan-user-agent.d.ts +2 -0
- package/dist/utils/nyan-user-agent.d.ts.map +1 -0
- package/dist/utils/nyan-user-agent.js +12 -0
- package/dist/utils/nyan-user-agent.js.map +1 -0
- package/dist/utils/oauth-page.d.ts +3 -0
- package/dist/utils/oauth-page.d.ts.map +1 -0
- package/dist/utils/oauth-page.js +105 -0
- package/dist/utils/oauth-page.js.map +1 -0
- package/dist/utils/overflow.d.ts +69 -0
- package/dist/utils/overflow.d.ts.map +1 -0
- package/dist/utils/overflow.js +179 -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 +18 -0
- package/dist/utils/provider-retry.d.ts.map +1 -0
- package/dist/utils/provider-retry.js +97 -0
- package/dist/utils/provider-retry.js.map +1 -0
- package/dist/utils/retry.d.ts +58 -0
- package/dist/utils/retry.d.ts.map +1 -0
- package/dist/utils/retry.js +196 -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/sleep.d.ts +2 -0
- package/dist/utils/sleep.d.ts.map +1 -0
- package/dist/utils/sleep.js +15 -0
- package/dist/utils/sleep.js.map +1 -0
- package/dist/utils/text.d.ts +14 -0
- package/dist/utils/text.d.ts.map +1 -0
- package/dist/utils/text.js +36 -0
- package/dist/utils/text.js.map +1 -0
- package/dist/utils/transcript.d.ts +87 -0
- package/dist/utils/transcript.d.ts.map +1 -0
- package/dist/utils/transcript.js +207 -0
- package/dist/utils/transcript.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 +42 -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 +309 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +113 -5
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anthropic OAuth flow (Claude Pro/Max)
|
|
3
|
+
*
|
|
4
|
+
* NOTE: This module uses Node.js http.createServer for the OAuth callback server.
|
|
5
|
+
* It is only intended for CLI use, not browser environments.
|
|
6
|
+
*/
|
|
7
|
+
import { getProviderEnvValue } from "../../utils/provider-env.js";
|
|
8
|
+
import { startOAuthCallbackServer, waitForCallbackOrManualInput } from "./callback-server.js";
|
|
9
|
+
import { generatePKCE } from "./pkce.js";
|
|
10
|
+
const decode = (s) => atob(s);
|
|
11
|
+
const CLIENT_ID = decode("OWQxYzI1MGEtZTYxYi00NGQ5LTg4ZWQtNTk0NGQxOTYyZjVl");
|
|
12
|
+
const AUTHORIZE_URL = "https://claude.ai/oauth/authorize";
|
|
13
|
+
const TOKEN_URL = "https://platform.claude.com/v1/oauth/token";
|
|
14
|
+
const CALLBACK_HOST = getProviderEnvValue("NYAN_OAUTH_CALLBACK_HOST") || "127.0.0.1";
|
|
15
|
+
// Preferred so the port can be forwarded into containers or over SSH. Anthropic accepts any loopback port,
|
|
16
|
+
// so login falls back to a free port when this one cannot be bound.
|
|
17
|
+
const CALLBACK_PORT = 53692;
|
|
18
|
+
const CALLBACK_PATH = "/callback";
|
|
19
|
+
const REDIRECT_URI = `http://localhost:${CALLBACK_PORT}${CALLBACK_PATH}`;
|
|
20
|
+
const COPY_CODE_REDIRECT_URI = "https://platform.claude.com/oauth/code/callback";
|
|
21
|
+
const ANTHROPIC_BROWSER_LOGIN_METHOD = "browser";
|
|
22
|
+
const ANTHROPIC_COPY_CODE_LOGIN_METHOD = "copy_code";
|
|
23
|
+
const SCOPES = "org:create_api_key user:profile user:inference user:sessions:claude_code user:mcp_servers user:file_upload";
|
|
24
|
+
function parseAuthorizationInput(input) {
|
|
25
|
+
const value = input.trim();
|
|
26
|
+
if (!value)
|
|
27
|
+
return {};
|
|
28
|
+
try {
|
|
29
|
+
const url = new URL(value);
|
|
30
|
+
return {
|
|
31
|
+
code: url.searchParams.get("code") ?? undefined,
|
|
32
|
+
state: url.searchParams.get("state") ?? undefined,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// not a URL
|
|
37
|
+
}
|
|
38
|
+
if (value.includes("#")) {
|
|
39
|
+
const [code, state] = value.split("#", 2);
|
|
40
|
+
return { code, state };
|
|
41
|
+
}
|
|
42
|
+
if (value.includes("code=")) {
|
|
43
|
+
const params = new URLSearchParams(value);
|
|
44
|
+
return {
|
|
45
|
+
code: params.get("code") ?? undefined,
|
|
46
|
+
state: params.get("state") ?? undefined,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return { code: value };
|
|
50
|
+
}
|
|
51
|
+
function formatErrorDetails(error) {
|
|
52
|
+
if (error instanceof Error) {
|
|
53
|
+
const details = [`${error.name}: ${error.message}`];
|
|
54
|
+
const errorWithCode = error;
|
|
55
|
+
if (errorWithCode.code)
|
|
56
|
+
details.push(`code=${errorWithCode.code}`);
|
|
57
|
+
if (typeof errorWithCode.errno !== "undefined")
|
|
58
|
+
details.push(`errno=${String(errorWithCode.errno)}`);
|
|
59
|
+
if (typeof error.cause !== "undefined") {
|
|
60
|
+
details.push(`cause=${formatErrorDetails(error.cause)}`);
|
|
61
|
+
}
|
|
62
|
+
if (error.stack) {
|
|
63
|
+
details.push(`stack=${error.stack}`);
|
|
64
|
+
}
|
|
65
|
+
return details.join("; ");
|
|
66
|
+
}
|
|
67
|
+
return String(error);
|
|
68
|
+
}
|
|
69
|
+
async function postJson(url, body, signal) {
|
|
70
|
+
const response = await fetch(url, {
|
|
71
|
+
method: "POST",
|
|
72
|
+
headers: {
|
|
73
|
+
"Content-Type": "application/json",
|
|
74
|
+
Accept: "application/json",
|
|
75
|
+
},
|
|
76
|
+
body: JSON.stringify(body),
|
|
77
|
+
signal: AbortSignal.any([signal, AbortSignal.timeout(30_000)]),
|
|
78
|
+
});
|
|
79
|
+
const responseBody = await response.text();
|
|
80
|
+
if (!response.ok) {
|
|
81
|
+
throw new Error(`HTTP request failed. status=${response.status}; url=${url}; body=${responseBody}`);
|
|
82
|
+
}
|
|
83
|
+
return responseBody;
|
|
84
|
+
}
|
|
85
|
+
async function exchangeAuthorizationCode(code, state, verifier, redirectUri, signal) {
|
|
86
|
+
let responseBody;
|
|
87
|
+
try {
|
|
88
|
+
responseBody = await postJson(TOKEN_URL, {
|
|
89
|
+
grant_type: "authorization_code",
|
|
90
|
+
client_id: CLIENT_ID,
|
|
91
|
+
code,
|
|
92
|
+
state,
|
|
93
|
+
redirect_uri: redirectUri,
|
|
94
|
+
code_verifier: verifier,
|
|
95
|
+
}, signal);
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
throw new Error(`Token exchange request failed. url=${TOKEN_URL}; redirect_uri=${redirectUri}; response_type=authorization_code; details=${formatErrorDetails(error)}`);
|
|
99
|
+
}
|
|
100
|
+
let tokenData;
|
|
101
|
+
try {
|
|
102
|
+
tokenData = JSON.parse(responseBody);
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
throw new Error(`Token exchange returned invalid JSON. url=${TOKEN_URL}; body=${responseBody}; details=${formatErrorDetails(error)}`);
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
type: "oauth",
|
|
109
|
+
refresh: tokenData.refresh_token,
|
|
110
|
+
access: tokenData.access_token,
|
|
111
|
+
expires: Date.now() + tokenData.expires_in * 1000 - 5 * 60 * 1000,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
async function loginAnthropic(interaction) {
|
|
115
|
+
const { verifier, challenge } = await generatePKCE();
|
|
116
|
+
const startCallbackServer = (port) => startOAuthCallbackServer({
|
|
117
|
+
providerName: "Anthropic",
|
|
118
|
+
host: CALLBACK_HOST,
|
|
119
|
+
port,
|
|
120
|
+
path: CALLBACK_PATH,
|
|
121
|
+
redirectHost: "localhost",
|
|
122
|
+
state: verifier,
|
|
123
|
+
complete: async (code) => code,
|
|
124
|
+
signal: interaction.signal,
|
|
125
|
+
});
|
|
126
|
+
// Without a callback server, login continues with the pasted redirect URL.
|
|
127
|
+
const callback = await startCallbackServer(CALLBACK_PORT)
|
|
128
|
+
.catch(() => startCallbackServer(0))
|
|
129
|
+
.catch(() => undefined);
|
|
130
|
+
const redirectUri = callback?.redirectUri ?? REDIRECT_URI;
|
|
131
|
+
try {
|
|
132
|
+
const authParams = new URLSearchParams({
|
|
133
|
+
code: "true",
|
|
134
|
+
client_id: CLIENT_ID,
|
|
135
|
+
response_type: "code",
|
|
136
|
+
redirect_uri: redirectUri,
|
|
137
|
+
scope: SCOPES,
|
|
138
|
+
code_challenge: challenge,
|
|
139
|
+
code_challenge_method: "S256",
|
|
140
|
+
state: verifier,
|
|
141
|
+
});
|
|
142
|
+
interaction.notify({
|
|
143
|
+
type: "auth_url",
|
|
144
|
+
url: `${AUTHORIZE_URL}?${authParams.toString()}`,
|
|
145
|
+
instructions: "Complete login in your browser. If the browser is on another machine, paste the final redirect URL here.",
|
|
146
|
+
});
|
|
147
|
+
const result = await waitForCallbackOrManualInput(interaction, callback, {
|
|
148
|
+
message: "Complete login in your browser, or paste the authorization code / redirect URL here:",
|
|
149
|
+
placeholder: redirectUri,
|
|
150
|
+
});
|
|
151
|
+
let code;
|
|
152
|
+
let state = verifier;
|
|
153
|
+
if (result.type === "callback") {
|
|
154
|
+
code = result.value;
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
const parsed = parseAuthorizationInput(result.input);
|
|
158
|
+
if (parsed.state && parsed.state !== verifier)
|
|
159
|
+
throw new Error("OAuth state mismatch");
|
|
160
|
+
code = parsed.code;
|
|
161
|
+
state = parsed.state ?? verifier;
|
|
162
|
+
}
|
|
163
|
+
if (!code)
|
|
164
|
+
throw new Error("Missing authorization code");
|
|
165
|
+
interaction.notify({ type: "progress", message: "Exchanging authorization code for tokens..." });
|
|
166
|
+
return await exchangeAuthorizationCode(code, state, verifier, redirectUri, interaction.signal);
|
|
167
|
+
}
|
|
168
|
+
finally {
|
|
169
|
+
callback?.close();
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
async function loginAnthropicCopyCode(interaction) {
|
|
173
|
+
const { verifier, challenge } = await generatePKCE();
|
|
174
|
+
const authParams = new URLSearchParams({
|
|
175
|
+
code: "true",
|
|
176
|
+
client_id: CLIENT_ID,
|
|
177
|
+
response_type: "code",
|
|
178
|
+
redirect_uri: COPY_CODE_REDIRECT_URI,
|
|
179
|
+
scope: SCOPES,
|
|
180
|
+
code_challenge: challenge,
|
|
181
|
+
code_challenge_method: "S256",
|
|
182
|
+
state: verifier,
|
|
183
|
+
});
|
|
184
|
+
interaction.notify({
|
|
185
|
+
type: "auth_url",
|
|
186
|
+
url: `${AUTHORIZE_URL}?${authParams.toString()}`,
|
|
187
|
+
instructions: "Complete login in your browser, then copy the code Anthropic shows and paste it here.",
|
|
188
|
+
});
|
|
189
|
+
const input = await interaction.prompt({
|
|
190
|
+
type: "manual_code",
|
|
191
|
+
message: "Paste the code Anthropic shows after you sign in:",
|
|
192
|
+
placeholder: "code#state",
|
|
193
|
+
signal: interaction.signal,
|
|
194
|
+
});
|
|
195
|
+
const parsed = parseAuthorizationInput(input);
|
|
196
|
+
if (parsed.state && parsed.state !== verifier)
|
|
197
|
+
throw new Error("OAuth state mismatch");
|
|
198
|
+
if (!parsed.code)
|
|
199
|
+
throw new Error("Missing authorization code");
|
|
200
|
+
interaction.notify({ type: "progress", message: "Exchanging authorization code for tokens..." });
|
|
201
|
+
return await exchangeAuthorizationCode(parsed.code, parsed.state ?? verifier, verifier, COPY_CODE_REDIRECT_URI, interaction.signal);
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Refresh Anthropic OAuth token
|
|
205
|
+
*/
|
|
206
|
+
async function refreshAnthropicToken(refreshToken, signal) {
|
|
207
|
+
let responseBody;
|
|
208
|
+
try {
|
|
209
|
+
responseBody = await postJson(TOKEN_URL, {
|
|
210
|
+
grant_type: "refresh_token",
|
|
211
|
+
client_id: CLIENT_ID,
|
|
212
|
+
refresh_token: refreshToken,
|
|
213
|
+
}, signal);
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
throw new Error(`Anthropic token refresh request failed. url=${TOKEN_URL}; details=${formatErrorDetails(error)}`);
|
|
217
|
+
}
|
|
218
|
+
let data;
|
|
219
|
+
try {
|
|
220
|
+
data = JSON.parse(responseBody);
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
throw new Error(`Anthropic token refresh returned invalid JSON. url=${TOKEN_URL}; body=${responseBody}; details=${formatErrorDetails(error)}`);
|
|
224
|
+
}
|
|
225
|
+
return {
|
|
226
|
+
type: "oauth",
|
|
227
|
+
refresh: data.refresh_token,
|
|
228
|
+
access: data.access_token,
|
|
229
|
+
expires: Date.now() + data.expires_in * 1000 - 5 * 60 * 1000,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
export const anthropicOAuth = {
|
|
233
|
+
name: "Anthropic (Claude Pro/Max)",
|
|
234
|
+
isSubscription: true,
|
|
235
|
+
async login(interaction) {
|
|
236
|
+
const method = await interaction.prompt({
|
|
237
|
+
type: "select",
|
|
238
|
+
message: "Select Anthropic login method:",
|
|
239
|
+
options: [
|
|
240
|
+
{ id: ANTHROPIC_BROWSER_LOGIN_METHOD, label: "Browser login (default)" },
|
|
241
|
+
{ id: ANTHROPIC_COPY_CODE_LOGIN_METHOD, label: "Copy code login (headless)" },
|
|
242
|
+
],
|
|
243
|
+
});
|
|
244
|
+
if (method === ANTHROPIC_COPY_CODE_LOGIN_METHOD) {
|
|
245
|
+
return loginAnthropicCopyCode(interaction);
|
|
246
|
+
}
|
|
247
|
+
if (method !== ANTHROPIC_BROWSER_LOGIN_METHOD) {
|
|
248
|
+
throw new Error(`Unknown Anthropic login method: ${method}`);
|
|
249
|
+
}
|
|
250
|
+
return loginAnthropic(interaction);
|
|
251
|
+
},
|
|
252
|
+
refresh: (credential, signal) => refreshAnthropicToken(credential.refresh, signal),
|
|
253
|
+
async toAuth(credential) {
|
|
254
|
+
return { apiKey: credential.access };
|
|
255
|
+
},
|
|
256
|
+
};
|
|
257
|
+
//# sourceMappingURL=anthropic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../../src/auth/oauth/anthropic.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Anthropic OAuth flow (Claude Pro/Max)\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 { getProviderEnvValue } from \"../../utils/provider-env.ts\";\nimport type { OAuthAuth, OAuthCredential, ProviderAuthInteraction } from \"../types.ts\";\nimport { startOAuthCallbackServer, waitForCallbackOrManualInput } from \"./callback-server.ts\";\nimport { generatePKCE } from \"./pkce.ts\";\n\nconst decode = (s: string) => atob(s);\nconst CLIENT_ID = decode(\"OWQxYzI1MGEtZTYxYi00NGQ5LTg4ZWQtNTk0NGQxOTYyZjVl\");\nconst AUTHORIZE_URL = \"https://claude.ai/oauth/authorize\";\nconst TOKEN_URL = \"https://platform.claude.com/v1/oauth/token\";\nconst CALLBACK_HOST = getProviderEnvValue(\"NYAN_OAUTH_CALLBACK_HOST\") || \"127.0.0.1\";\n// Preferred so the port can be forwarded into containers or over SSH. Anthropic accepts any loopback port,\n// so login falls back to a free port when this one cannot be bound.\nconst CALLBACK_PORT = 53692;\nconst CALLBACK_PATH = \"/callback\";\nconst REDIRECT_URI = `http://localhost:${CALLBACK_PORT}${CALLBACK_PATH}`;\nconst COPY_CODE_REDIRECT_URI = \"https://platform.claude.com/oauth/code/callback\";\nconst ANTHROPIC_BROWSER_LOGIN_METHOD = \"browser\";\nconst ANTHROPIC_COPY_CODE_LOGIN_METHOD = \"copy_code\";\nconst SCOPES =\n\t\"org:create_api_key user:profile user:inference user:sessions:claude_code user:mcp_servers user:file_upload\";\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(\"#\")) {\n\t\tconst [code, state] = value.split(\"#\", 2);\n\t\treturn { code, state };\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\nfunction formatErrorDetails(error: unknown): string {\n\tif (error instanceof Error) {\n\t\tconst details: string[] = [`${error.name}: ${error.message}`];\n\t\tconst errorWithCode = error as Error & { code?: string; errno?: number | string; cause?: unknown };\n\t\tif (errorWithCode.code) details.push(`code=${errorWithCode.code}`);\n\t\tif (typeof errorWithCode.errno !== \"undefined\") details.push(`errno=${String(errorWithCode.errno)}`);\n\t\tif (typeof error.cause !== \"undefined\") {\n\t\t\tdetails.push(`cause=${formatErrorDetails(error.cause)}`);\n\t\t}\n\t\tif (error.stack) {\n\t\t\tdetails.push(`stack=${error.stack}`);\n\t\t}\n\t\treturn details.join(\"; \");\n\t}\n\treturn String(error);\n}\n\nasync function postJson(url: string, body: Record<string, string | number>, signal: AbortSignal): Promise<string> {\n\tconst response = await fetch(url, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\tAccept: \"application/json\",\n\t\t},\n\t\tbody: JSON.stringify(body),\n\t\tsignal: AbortSignal.any([signal, AbortSignal.timeout(30_000)]),\n\t});\n\n\tconst responseBody = await response.text();\n\n\tif (!response.ok) {\n\t\tthrow new Error(`HTTP request failed. status=${response.status}; url=${url}; body=${responseBody}`);\n\t}\n\n\treturn responseBody;\n}\n\nasync function exchangeAuthorizationCode(\n\tcode: string,\n\tstate: string,\n\tverifier: string,\n\tredirectUri: string,\n\tsignal: AbortSignal,\n): Promise<OAuthCredential> {\n\tlet responseBody: string;\n\ttry {\n\t\tresponseBody = await postJson(\n\t\t\tTOKEN_URL,\n\t\t\t{\n\t\t\t\tgrant_type: \"authorization_code\",\n\t\t\t\tclient_id: CLIENT_ID,\n\t\t\t\tcode,\n\t\t\t\tstate,\n\t\t\t\tredirect_uri: redirectUri,\n\t\t\t\tcode_verifier: verifier,\n\t\t\t},\n\t\t\tsignal,\n\t\t);\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`Token exchange request failed. url=${TOKEN_URL}; redirect_uri=${redirectUri}; response_type=authorization_code; details=${formatErrorDetails(error)}`,\n\t\t);\n\t}\n\n\tlet tokenData: { access_token: string; refresh_token: string; expires_in: number };\n\ttry {\n\t\ttokenData = JSON.parse(responseBody) as { access_token: string; refresh_token: string; expires_in: number };\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`Token exchange returned invalid JSON. url=${TOKEN_URL}; body=${responseBody}; details=${formatErrorDetails(error)}`,\n\t\t);\n\t}\n\n\treturn {\n\t\ttype: \"oauth\",\n\t\trefresh: tokenData.refresh_token,\n\t\taccess: tokenData.access_token,\n\t\texpires: Date.now() + tokenData.expires_in * 1000 - 5 * 60 * 1000,\n\t};\n}\n\nasync function loginAnthropic(interaction: ProviderAuthInteraction): Promise<OAuthCredential> {\n\tconst { verifier, challenge } = await generatePKCE();\n\tconst startCallbackServer = (port: number) =>\n\t\tstartOAuthCallbackServer({\n\t\t\tproviderName: \"Anthropic\",\n\t\t\thost: CALLBACK_HOST,\n\t\t\tport,\n\t\t\tpath: CALLBACK_PATH,\n\t\t\tredirectHost: \"localhost\",\n\t\t\tstate: verifier,\n\t\t\tcomplete: async (code) => code,\n\t\t\tsignal: interaction.signal,\n\t\t});\n\t// Without a callback server, login continues with the pasted redirect URL.\n\tconst callback = await startCallbackServer(CALLBACK_PORT)\n\t\t.catch(() => startCallbackServer(0))\n\t\t.catch(() => undefined);\n\tconst redirectUri = callback?.redirectUri ?? REDIRECT_URI;\n\n\ttry {\n\t\tconst authParams = new URLSearchParams({\n\t\t\tcode: \"true\",\n\t\t\tclient_id: CLIENT_ID,\n\t\t\tresponse_type: \"code\",\n\t\t\tredirect_uri: redirectUri,\n\t\t\tscope: SCOPES,\n\t\t\tcode_challenge: challenge,\n\t\t\tcode_challenge_method: \"S256\",\n\t\t\tstate: verifier,\n\t\t});\n\t\tinteraction.notify({\n\t\t\ttype: \"auth_url\",\n\t\t\turl: `${AUTHORIZE_URL}?${authParams.toString()}`,\n\t\t\tinstructions:\n\t\t\t\t\"Complete login in your browser. If the browser is on another machine, paste the final redirect URL here.\",\n\t\t});\n\n\t\tconst result = await waitForCallbackOrManualInput(interaction, callback, {\n\t\t\tmessage: \"Complete login in your browser, or paste the authorization code / redirect URL here:\",\n\t\t\tplaceholder: redirectUri,\n\t\t});\n\t\tlet code: string | undefined;\n\t\tlet state = verifier;\n\t\tif (result.type === \"callback\") {\n\t\t\tcode = result.value;\n\t\t} else {\n\t\t\tconst parsed = parseAuthorizationInput(result.input);\n\t\t\tif (parsed.state && parsed.state !== verifier) throw new Error(\"OAuth state mismatch\");\n\t\t\tcode = parsed.code;\n\t\t\tstate = parsed.state ?? verifier;\n\t\t}\n\n\t\tif (!code) throw new Error(\"Missing authorization code\");\n\t\tinteraction.notify({ type: \"progress\", message: \"Exchanging authorization code for tokens...\" });\n\t\treturn await exchangeAuthorizationCode(code, state, verifier, redirectUri, interaction.signal);\n\t} finally {\n\t\tcallback?.close();\n\t}\n}\n\nasync function loginAnthropicCopyCode(interaction: ProviderAuthInteraction): Promise<OAuthCredential> {\n\tconst { verifier, challenge } = await generatePKCE();\n\tconst authParams = new URLSearchParams({\n\t\tcode: \"true\",\n\t\tclient_id: CLIENT_ID,\n\t\tresponse_type: \"code\",\n\t\tredirect_uri: COPY_CODE_REDIRECT_URI,\n\t\tscope: SCOPES,\n\t\tcode_challenge: challenge,\n\t\tcode_challenge_method: \"S256\",\n\t\tstate: verifier,\n\t});\n\tinteraction.notify({\n\t\ttype: \"auth_url\",\n\t\turl: `${AUTHORIZE_URL}?${authParams.toString()}`,\n\t\tinstructions: \"Complete login in your browser, then copy the code Anthropic shows and paste it here.\",\n\t});\n\n\tconst input = await interaction.prompt({\n\t\ttype: \"manual_code\",\n\t\tmessage: \"Paste the code Anthropic shows after you sign in:\",\n\t\tplaceholder: \"code#state\",\n\t\tsignal: interaction.signal,\n\t});\n\tconst parsed = parseAuthorizationInput(input);\n\tif (parsed.state && parsed.state !== verifier) throw new Error(\"OAuth state mismatch\");\n\tif (!parsed.code) throw new Error(\"Missing authorization code\");\n\tinteraction.notify({ type: \"progress\", message: \"Exchanging authorization code for tokens...\" });\n\treturn await exchangeAuthorizationCode(\n\t\tparsed.code,\n\t\tparsed.state ?? verifier,\n\t\tverifier,\n\t\tCOPY_CODE_REDIRECT_URI,\n\t\tinteraction.signal,\n\t);\n}\n\n/**\n * Refresh Anthropic OAuth token\n */\nasync function refreshAnthropicToken(refreshToken: string, signal: AbortSignal): Promise<OAuthCredential> {\n\tlet responseBody: string;\n\ttry {\n\t\tresponseBody = await postJson(\n\t\t\tTOKEN_URL,\n\t\t\t{\n\t\t\t\tgrant_type: \"refresh_token\",\n\t\t\t\tclient_id: CLIENT_ID,\n\t\t\t\trefresh_token: refreshToken,\n\t\t\t},\n\t\t\tsignal,\n\t\t);\n\t} catch (error) {\n\t\tthrow new Error(`Anthropic token refresh request failed. url=${TOKEN_URL}; details=${formatErrorDetails(error)}`);\n\t}\n\n\tlet data: { access_token: string; refresh_token: string; expires_in: number; scope?: string };\n\ttry {\n\t\tdata = JSON.parse(responseBody) as {\n\t\t\taccess_token: string;\n\t\t\trefresh_token: string;\n\t\t\texpires_in: number;\n\t\t\tscope?: string;\n\t\t};\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`Anthropic token refresh returned invalid JSON. url=${TOKEN_URL}; body=${responseBody}; details=${formatErrorDetails(error)}`,\n\t\t);\n\t}\n\n\treturn {\n\t\ttype: \"oauth\",\n\t\trefresh: data.refresh_token,\n\t\taccess: data.access_token,\n\t\texpires: Date.now() + data.expires_in * 1000 - 5 * 60 * 1000,\n\t};\n}\n\nexport const anthropicOAuth: OAuthAuth = {\n\tname: \"Anthropic (Claude Pro/Max)\",\n\tisSubscription: true,\n\n\tasync login(interaction) {\n\t\tconst method = await interaction.prompt({\n\t\t\ttype: \"select\",\n\t\t\tmessage: \"Select Anthropic login method:\",\n\t\t\toptions: [\n\t\t\t\t{ id: ANTHROPIC_BROWSER_LOGIN_METHOD, label: \"Browser login (default)\" },\n\t\t\t\t{ id: ANTHROPIC_COPY_CODE_LOGIN_METHOD, label: \"Copy code login (headless)\" },\n\t\t\t],\n\t\t});\n\n\t\tif (method === ANTHROPIC_COPY_CODE_LOGIN_METHOD) {\n\t\t\treturn loginAnthropicCopyCode(interaction);\n\t\t}\n\t\tif (method !== ANTHROPIC_BROWSER_LOGIN_METHOD) {\n\t\t\tthrow new Error(`Unknown Anthropic login method: ${method}`);\n\t\t}\n\n\t\treturn loginAnthropic(interaction);\n\t},\n\n\trefresh: (credential, signal) => refreshAnthropicToken(credential.refresh, signal),\n\n\tasync toAuth(credential) {\n\t\treturn { apiKey: credential.access };\n\t},\n};\n"]}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loopback OAuth redirect handler shared by the browser sign-in flows.
|
|
3
|
+
*
|
|
4
|
+
* NOTE: This module uses node:http. It is only reachable through the lazily
|
|
5
|
+
* loaded OAuth flow modules, never from browser-facing entry points.
|
|
6
|
+
*/
|
|
7
|
+
import type { ProviderAuthInteraction } from "../types.ts";
|
|
8
|
+
export interface OAuthCallbackServerOptions<T> {
|
|
9
|
+
/** Provider name used on the browser page, for example `OpenAI`. */
|
|
10
|
+
providerName: string;
|
|
11
|
+
/** Address to listen on. */
|
|
12
|
+
host: string;
|
|
13
|
+
/** Port to listen on; `0` picks a free port. */
|
|
14
|
+
port: number;
|
|
15
|
+
path: string;
|
|
16
|
+
/** Host in `redirectUri` when it differs from `host`, for example `localhost`. */
|
|
17
|
+
redirectHost?: string;
|
|
18
|
+
/** Expected `state` parameter. Omit when the provider does not send one. */
|
|
19
|
+
state?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Finishes the sign-in with the received code before the browser page is sent, so the page can
|
|
22
|
+
* show exchange failures. Pass `async (code) => code` to exchange the code later.
|
|
23
|
+
*/
|
|
24
|
+
complete: (code: string) => Promise<T>;
|
|
25
|
+
signal?: AbortSignal;
|
|
26
|
+
timeoutMs?: number;
|
|
27
|
+
}
|
|
28
|
+
export interface OAuthCallbackServer<T> {
|
|
29
|
+
redirectUri: string;
|
|
30
|
+
/**
|
|
31
|
+
* Resolves with the result of `complete`, or `undefined` after `cancel()`. Rejects when the provider
|
|
32
|
+
* redirects with an error, `complete` fails, the signal aborts, or the timeout elapses.
|
|
33
|
+
*/
|
|
34
|
+
wait(): Promise<T | undefined>;
|
|
35
|
+
/** Stop waiting for the browser unless a callback is already being completed. */
|
|
36
|
+
cancel(): void;
|
|
37
|
+
close(): void;
|
|
38
|
+
}
|
|
39
|
+
export declare function startOAuthCallbackServer<T>(options: OAuthCallbackServerOptions<T>): Promise<OAuthCallbackServer<T>>;
|
|
40
|
+
/**
|
|
41
|
+
* Wait for the browser callback, or for the user to paste the code or redirect URL when the browser
|
|
42
|
+
* cannot reach the loopback server (for example over SSH). Without a callback server only the manual
|
|
43
|
+
* prompt is used.
|
|
44
|
+
*/
|
|
45
|
+
export declare function waitForCallbackOrManualInput<T>(interaction: ProviderAuthInteraction, callback: OAuthCallbackServer<T> | undefined, prompt: {
|
|
46
|
+
message: string;
|
|
47
|
+
placeholder: string;
|
|
48
|
+
}): Promise<{
|
|
49
|
+
type: "callback";
|
|
50
|
+
value: T;
|
|
51
|
+
} | {
|
|
52
|
+
type: "manual";
|
|
53
|
+
input: string;
|
|
54
|
+
}>;
|
|
55
|
+
//# sourceMappingURL=callback-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"callback-server.d.ts","sourceRoot":"","sources":["../../../src/auth/oauth/callback-server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAE3D,MAAM,WAAW,0BAA0B,CAAC,CAAC;IAC5C,oEAAoE;IACpE,YAAY,EAAE,MAAM,CAAC;IACrB,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,kFAAkF;IAClF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IACvC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB,CAAC,CAAC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,IAAI,IAAI,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAC/B,iFAAiF;IACjF,MAAM,IAAI,IAAI,CAAC;IACf,KAAK,IAAI,IAAI,CAAC;CACd;AAOD,wBAAsB,wBAAwB,CAAC,CAAC,EAC/C,OAAO,EAAE,0BAA0B,CAAC,CAAC,CAAC,GACpC,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAgGjC;AAED;;;;GAIG;AACH,wBAAsB,4BAA4B,CAAC,CAAC,EACnD,WAAW,EAAE,uBAAuB,EACpC,QAAQ,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,SAAS,EAC5C,MAAM,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAC9C,OAAO,CAAC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAwB7E"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loopback OAuth redirect handler shared by the browser sign-in flows.
|
|
3
|
+
*
|
|
4
|
+
* NOTE: This module uses node:http. It is only reachable through the lazily
|
|
5
|
+
* loaded OAuth flow modules, never from browser-facing entry points.
|
|
6
|
+
*/
|
|
7
|
+
import { createServer } from "node:http";
|
|
8
|
+
import { oauthErrorHtml, oauthSuccessHtml } from "../../utils/oauth-page.js";
|
|
9
|
+
function sendPage(response, status, html) {
|
|
10
|
+
response.writeHead(status, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store" });
|
|
11
|
+
response.end(html);
|
|
12
|
+
}
|
|
13
|
+
export async function startOAuthCallbackServer(options) {
|
|
14
|
+
const { providerName, signal } = options;
|
|
15
|
+
if (signal?.aborted)
|
|
16
|
+
throw new Error("Login cancelled");
|
|
17
|
+
let resolveWait = () => { };
|
|
18
|
+
let rejectWait = () => { };
|
|
19
|
+
const waitPromise = new Promise((resolve, reject) => {
|
|
20
|
+
resolveWait = resolve;
|
|
21
|
+
rejectWait = reject;
|
|
22
|
+
});
|
|
23
|
+
// A cancelled or closed wait may never be observed.
|
|
24
|
+
waitPromise.catch(() => undefined);
|
|
25
|
+
let claimed = false;
|
|
26
|
+
let settled = false;
|
|
27
|
+
let timer;
|
|
28
|
+
const onAbort = () => finish({ error: new Error("Login cancelled") });
|
|
29
|
+
const finish = (result) => {
|
|
30
|
+
if (settled)
|
|
31
|
+
return;
|
|
32
|
+
settled = true;
|
|
33
|
+
if (timer)
|
|
34
|
+
clearTimeout(timer);
|
|
35
|
+
signal?.removeEventListener("abort", onAbort);
|
|
36
|
+
if ("error" in result)
|
|
37
|
+
rejectWait(result.error);
|
|
38
|
+
else
|
|
39
|
+
resolveWait(result.value);
|
|
40
|
+
};
|
|
41
|
+
const server = createServer((request, response) => {
|
|
42
|
+
void (async () => {
|
|
43
|
+
const url = new URL(request.url ?? "/", "http://localhost");
|
|
44
|
+
if (request.method !== "GET" || url.pathname !== options.path) {
|
|
45
|
+
sendPage(response, 404, oauthErrorHtml("Callback route not found."));
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (options.state !== undefined && url.searchParams.get("state") !== options.state) {
|
|
49
|
+
sendPage(response, 400, oauthErrorHtml("State mismatch."));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (claimed || settled) {
|
|
53
|
+
sendPage(response, 409, oauthErrorHtml("This sign-in has already been handled."));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const error = url.searchParams.get("error");
|
|
57
|
+
if (error) {
|
|
58
|
+
const description = url.searchParams.get("error_description") ?? error;
|
|
59
|
+
sendPage(response, 400, oauthErrorHtml(`${providerName} authorization failed.`, description));
|
|
60
|
+
finish({ error: new Error(`${providerName} authorization failed: ${description}`) });
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const code = url.searchParams.get("code");
|
|
64
|
+
if (!code) {
|
|
65
|
+
sendPage(response, 400, oauthErrorHtml("Missing authorization code."));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
claimed = true;
|
|
69
|
+
try {
|
|
70
|
+
const value = await options.complete(code);
|
|
71
|
+
sendPage(response, 200, oauthSuccessHtml(`Signed in to ${providerName}. You may now close this page.`));
|
|
72
|
+
finish({ value });
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
const failure = error instanceof Error ? error : new Error(String(error));
|
|
76
|
+
sendPage(response, 502, oauthErrorHtml(`${providerName} sign-in failed.`, failure.message));
|
|
77
|
+
finish({ error: failure });
|
|
78
|
+
}
|
|
79
|
+
})();
|
|
80
|
+
});
|
|
81
|
+
await new Promise((resolve, reject) => {
|
|
82
|
+
server.once("error", reject);
|
|
83
|
+
server.listen(options.port, options.host, () => {
|
|
84
|
+
server.off("error", reject);
|
|
85
|
+
resolve();
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
const address = server.address();
|
|
89
|
+
if (!address || typeof address === "string") {
|
|
90
|
+
server.close();
|
|
91
|
+
throw new Error("OAuth callback server did not bind to TCP");
|
|
92
|
+
}
|
|
93
|
+
server.on("error", (error) => finish({ error }));
|
|
94
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
95
|
+
if (options.timeoutMs !== undefined) {
|
|
96
|
+
timer = setTimeout(() => finish({ error: new Error(`${providerName} sign-in timed out`) }), options.timeoutMs);
|
|
97
|
+
}
|
|
98
|
+
const redirectHost = options.redirectHost ?? options.host;
|
|
99
|
+
return {
|
|
100
|
+
redirectUri: `http://${redirectHost.includes(":") ? `[${redirectHost}]` : redirectHost}:${address.port}${options.path}`,
|
|
101
|
+
wait: () => waitPromise,
|
|
102
|
+
cancel: () => {
|
|
103
|
+
if (!claimed)
|
|
104
|
+
finish({ value: undefined });
|
|
105
|
+
},
|
|
106
|
+
close: () => {
|
|
107
|
+
finish({ error: new Error("OAuth callback server closed") });
|
|
108
|
+
server.close();
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Wait for the browser callback, or for the user to paste the code or redirect URL when the browser
|
|
114
|
+
* cannot reach the loopback server (for example over SSH). Without a callback server only the manual
|
|
115
|
+
* prompt is used.
|
|
116
|
+
*/
|
|
117
|
+
export async function waitForCallbackOrManualInput(interaction, callback, prompt) {
|
|
118
|
+
const manualAbort = new AbortController();
|
|
119
|
+
let manualError;
|
|
120
|
+
const manual = interaction
|
|
121
|
+
.prompt({ type: "manual_code", ...prompt, signal: manualAbort.signal })
|
|
122
|
+
.then((input) => {
|
|
123
|
+
callback?.cancel();
|
|
124
|
+
return input;
|
|
125
|
+
})
|
|
126
|
+
.catch((error) => {
|
|
127
|
+
manualError = error instanceof Error ? error : new Error(String(error));
|
|
128
|
+
callback?.cancel();
|
|
129
|
+
return undefined;
|
|
130
|
+
});
|
|
131
|
+
try {
|
|
132
|
+
const value = await callback?.wait();
|
|
133
|
+
if (manualError)
|
|
134
|
+
throw manualError;
|
|
135
|
+
if (value !== undefined)
|
|
136
|
+
return { type: "callback", value };
|
|
137
|
+
const input = await manual;
|
|
138
|
+
if (manualError)
|
|
139
|
+
throw manualError;
|
|
140
|
+
return { type: "manual", input: input ?? "" };
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
manualAbort.abort();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=callback-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"callback-server.js","sourceRoot":"","sources":["../../../src/auth/oauth/callback-server.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Loopback OAuth redirect handler shared by the browser sign-in flows.\n *\n * NOTE: This module uses node:http. It is only reachable through the lazily\n * loaded OAuth flow modules, never from browser-facing entry points.\n */\n\nimport { createServer, type ServerResponse } from \"node:http\";\nimport { oauthErrorHtml, oauthSuccessHtml } from \"../../utils/oauth-page.ts\";\nimport type { ProviderAuthInteraction } from \"../types.ts\";\n\nexport interface OAuthCallbackServerOptions<T> {\n\t/** Provider name used on the browser page, for example `OpenAI`. */\n\tproviderName: string;\n\t/** Address to listen on. */\n\thost: string;\n\t/** Port to listen on; `0` picks a free port. */\n\tport: number;\n\tpath: string;\n\t/** Host in `redirectUri` when it differs from `host`, for example `localhost`. */\n\tredirectHost?: string;\n\t/** Expected `state` parameter. Omit when the provider does not send one. */\n\tstate?: string;\n\t/**\n\t * Finishes the sign-in with the received code before the browser page is sent, so the page can\n\t * show exchange failures. Pass `async (code) => code` to exchange the code later.\n\t */\n\tcomplete: (code: string) => Promise<T>;\n\tsignal?: AbortSignal;\n\ttimeoutMs?: number;\n}\n\nexport interface OAuthCallbackServer<T> {\n\tredirectUri: string;\n\t/**\n\t * Resolves with the result of `complete`, or `undefined` after `cancel()`. Rejects when the provider\n\t * redirects with an error, `complete` fails, the signal aborts, or the timeout elapses.\n\t */\n\twait(): Promise<T | undefined>;\n\t/** Stop waiting for the browser unless a callback is already being completed. */\n\tcancel(): void;\n\tclose(): void;\n}\n\nfunction sendPage(response: ServerResponse, status: number, html: string): void {\n\tresponse.writeHead(status, { \"content-type\": \"text/html; charset=utf-8\", \"cache-control\": \"no-store\" });\n\tresponse.end(html);\n}\n\nexport async function startOAuthCallbackServer<T>(\n\toptions: OAuthCallbackServerOptions<T>,\n): Promise<OAuthCallbackServer<T>> {\n\tconst { providerName, signal } = options;\n\tif (signal?.aborted) throw new Error(\"Login cancelled\");\n\n\tlet resolveWait: (value: T | undefined) => void = () => {};\n\tlet rejectWait: (error: Error) => void = () => {};\n\tconst waitPromise = new Promise<T | undefined>((resolve, reject) => {\n\t\tresolveWait = resolve;\n\t\trejectWait = reject;\n\t});\n\t// A cancelled or closed wait may never be observed.\n\twaitPromise.catch(() => undefined);\n\n\tlet claimed = false;\n\tlet settled = false;\n\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\tconst onAbort = () => finish({ error: new Error(\"Login cancelled\") });\n\tconst finish = (result: { value: T | undefined } | { error: Error }): void => {\n\t\tif (settled) return;\n\t\tsettled = true;\n\t\tif (timer) clearTimeout(timer);\n\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\tif (\"error\" in result) rejectWait(result.error);\n\t\telse resolveWait(result.value);\n\t};\n\n\tconst server = createServer((request, response) => {\n\t\tvoid (async () => {\n\t\t\tconst url = new URL(request.url ?? \"/\", \"http://localhost\");\n\t\t\tif (request.method !== \"GET\" || url.pathname !== options.path) {\n\t\t\t\tsendPage(response, 404, oauthErrorHtml(\"Callback route not found.\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (options.state !== undefined && url.searchParams.get(\"state\") !== options.state) {\n\t\t\t\tsendPage(response, 400, oauthErrorHtml(\"State mismatch.\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (claimed || settled) {\n\t\t\t\tsendPage(response, 409, oauthErrorHtml(\"This sign-in has already been handled.\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst error = url.searchParams.get(\"error\");\n\t\t\tif (error) {\n\t\t\t\tconst description = url.searchParams.get(\"error_description\") ?? error;\n\t\t\t\tsendPage(response, 400, oauthErrorHtml(`${providerName} authorization failed.`, description));\n\t\t\t\tfinish({ error: new Error(`${providerName} authorization failed: ${description}`) });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst code = url.searchParams.get(\"code\");\n\t\t\tif (!code) {\n\t\t\t\tsendPage(response, 400, oauthErrorHtml(\"Missing authorization code.\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tclaimed = true;\n\t\t\ttry {\n\t\t\t\tconst value = await options.complete(code);\n\t\t\t\tsendPage(response, 200, oauthSuccessHtml(`Signed in to ${providerName}. You may now close this page.`));\n\t\t\t\tfinish({ value });\n\t\t\t} catch (error) {\n\t\t\t\tconst failure = error instanceof Error ? error : new Error(String(error));\n\t\t\t\tsendPage(response, 502, oauthErrorHtml(`${providerName} sign-in failed.`, failure.message));\n\t\t\t\tfinish({ error: failure });\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(options.port, options.host, () => {\n\t\t\tserver.off(\"error\", reject);\n\t\t\tresolve();\n\t\t});\n\t});\n\tconst address = server.address();\n\tif (!address || typeof address === \"string\") {\n\t\tserver.close();\n\t\tthrow new Error(\"OAuth callback server did not bind to TCP\");\n\t}\n\n\tserver.on(\"error\", (error) => finish({ error }));\n\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\tif (options.timeoutMs !== undefined) {\n\t\ttimer = setTimeout(() => finish({ error: new Error(`${providerName} sign-in timed out`) }), options.timeoutMs);\n\t}\n\tconst redirectHost = options.redirectHost ?? options.host;\n\treturn {\n\t\tredirectUri: `http://${redirectHost.includes(\":\") ? `[${redirectHost}]` : redirectHost}:${address.port}${options.path}`,\n\t\twait: () => waitPromise,\n\t\tcancel: () => {\n\t\t\tif (!claimed) finish({ value: undefined });\n\t\t},\n\t\tclose: () => {\n\t\t\tfinish({ error: new Error(\"OAuth callback server closed\") });\n\t\t\tserver.close();\n\t\t},\n\t};\n}\n\n/**\n * Wait for the browser callback, or for the user to paste the code or redirect URL when the browser\n * cannot reach the loopback server (for example over SSH). Without a callback server only the manual\n * prompt is used.\n */\nexport async function waitForCallbackOrManualInput<T>(\n\tinteraction: ProviderAuthInteraction,\n\tcallback: OAuthCallbackServer<T> | undefined,\n\tprompt: { message: string; placeholder: string },\n): Promise<{ type: \"callback\"; value: T } | { type: \"manual\"; input: string }> {\n\tconst manualAbort = new AbortController();\n\tlet manualError: Error | undefined;\n\tconst manual = interaction\n\t\t.prompt({ type: \"manual_code\", ...prompt, signal: manualAbort.signal })\n\t\t.then((input) => {\n\t\t\tcallback?.cancel();\n\t\t\treturn input;\n\t\t})\n\t\t.catch((error: unknown) => {\n\t\t\tmanualError = error instanceof Error ? error : new Error(String(error));\n\t\t\tcallback?.cancel();\n\t\t\treturn undefined;\n\t\t});\n\ttry {\n\t\tconst value = await callback?.wait();\n\t\tif (manualError) throw manualError;\n\t\tif (value !== undefined) return { type: \"callback\", value };\n\t\tconst input = await manual;\n\t\tif (manualError) throw manualError;\n\t\treturn { type: \"manual\", input: input ?? \"\" };\n\t} finally {\n\t\tmanualAbort.abort();\n\t}\n}\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
type OAuthDeviceCodeIncompletePollResult = {
|
|
2
|
+
status: "pending";
|
|
3
|
+
} | {
|
|
4
|
+
status: "slow_down";
|
|
5
|
+
intervalSeconds?: number;
|
|
6
|
+
} | {
|
|
7
|
+
status: "failed";
|
|
8
|
+
message: string;
|
|
9
|
+
};
|
|
10
|
+
export type OAuthDeviceCodePollResult<T> = OAuthDeviceCodeIncompletePollResult | {
|
|
11
|
+
status: "complete";
|
|
12
|
+
value: T;
|
|
13
|
+
};
|
|
14
|
+
export type OAuthDeviceCodePollOptions<T> = {
|
|
15
|
+
intervalSeconds?: number;
|
|
16
|
+
expiresInSeconds?: number;
|
|
17
|
+
waitBeforeFirstPoll?: boolean;
|
|
18
|
+
poll: () => Promise<OAuthDeviceCodePollResult<T>>;
|
|
19
|
+
signal: AbortSignal;
|
|
20
|
+
};
|
|
21
|
+
export declare function abortableSleep(ms: number, signal: AbortSignal, cancelMessage: string): Promise<void>;
|
|
22
|
+
export declare function pollOAuthDeviceCodeFlow<T>(options: OAuthDeviceCodePollOptions<T>): Promise<T>;
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=device-code.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-code.d.ts","sourceRoot":"","sources":["../../../src/auth/oauth/device-code.ts"],"names":[],"mappings":"AAUA,KAAK,mCAAmC,GACrC;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,GACjD;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC,MAAM,MAAM,yBAAyB,CAAC,CAAC,IAAI,mCAAmC,GAAG;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,CAAC;AAElH,MAAM,MAAM,0BAA0B,CAAC,CAAC,IAAI;IAC3C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,IAAI,EAAE,MAAM,OAAO,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,MAAM,EAAE,WAAW,CAAC;CACpB,CAAC;AAEF,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBpG;AAED,wBAAsB,uBAAuB,CAAC,CAAC,EAAE,OAAO,EAAE,0BAA0B,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAoDnG"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
const CANCEL_MESSAGE = "Login cancelled";
|
|
2
|
+
const TIMEOUT_MESSAGE = "Device flow timed out";
|
|
3
|
+
const SLOW_DOWN_TIMEOUT_MESSAGE = "Device flow timed out after one or more slow_down responses. This is often caused by clock drift in WSL or VM environments. Please sync or restart the VM clock and try again.";
|
|
4
|
+
const MINIMUM_INTERVAL_MS = 1000;
|
|
5
|
+
// RFC 8628 section 3.2: if the authorization server omits `interval`, the client must use 5 seconds.
|
|
6
|
+
const DEFAULT_POLL_INTERVAL_SECONDS = 5;
|
|
7
|
+
// RFC 8628 section 3.5: `slow_down` means the polling interval must increase by 5 seconds.
|
|
8
|
+
const SLOW_DOWN_INTERVAL_INCREMENT_MS = 5000;
|
|
9
|
+
export function abortableSleep(ms, signal, cancelMessage) {
|
|
10
|
+
return new Promise((resolve, reject) => {
|
|
11
|
+
if (signal.aborted) {
|
|
12
|
+
reject(new Error(cancelMessage));
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const onAbort = () => {
|
|
16
|
+
clearTimeout(timeout);
|
|
17
|
+
reject(new Error(cancelMessage));
|
|
18
|
+
};
|
|
19
|
+
const timeout = setTimeout(() => {
|
|
20
|
+
signal.removeEventListener("abort", onAbort);
|
|
21
|
+
resolve();
|
|
22
|
+
}, ms);
|
|
23
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
export async function pollOAuthDeviceCodeFlow(options) {
|
|
27
|
+
const deadline = typeof options.expiresInSeconds === "number"
|
|
28
|
+
? Date.now() + options.expiresInSeconds * 1000
|
|
29
|
+
: Number.POSITIVE_INFINITY;
|
|
30
|
+
let intervalMs = Math.max(MINIMUM_INTERVAL_MS, Math.floor((options.intervalSeconds ?? DEFAULT_POLL_INTERVAL_SECONDS) * 1000));
|
|
31
|
+
let slowDownResponses = 0;
|
|
32
|
+
if (options.waitBeforeFirstPoll) {
|
|
33
|
+
const remainingMs = deadline - Date.now();
|
|
34
|
+
if (remainingMs > 0) {
|
|
35
|
+
await abortableSleep(Math.min(intervalMs, remainingMs), options.signal, CANCEL_MESSAGE);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
while (Date.now() < deadline) {
|
|
39
|
+
if (options.signal.aborted) {
|
|
40
|
+
throw new Error(CANCEL_MESSAGE);
|
|
41
|
+
}
|
|
42
|
+
const result = await options.poll();
|
|
43
|
+
if (result.status === "complete") {
|
|
44
|
+
return result.value;
|
|
45
|
+
}
|
|
46
|
+
if (result.status === "failed") {
|
|
47
|
+
throw new Error(result.message);
|
|
48
|
+
}
|
|
49
|
+
if (result.status === "slow_down") {
|
|
50
|
+
slowDownResponses += 1;
|
|
51
|
+
// Use the server-provided interval when given (GitHub reports the new required minimum
|
|
52
|
+
// in `interval`); trusting only a client-tracked value risks polling early forever under
|
|
53
|
+
// WSL/VM clock drift. Otherwise apply RFC 8628 section 3.5: increase by 5 seconds.
|
|
54
|
+
intervalMs =
|
|
55
|
+
typeof result.intervalSeconds === "number" &&
|
|
56
|
+
Number.isFinite(result.intervalSeconds) &&
|
|
57
|
+
result.intervalSeconds > 0
|
|
58
|
+
? Math.max(MINIMUM_INTERVAL_MS, Math.floor(result.intervalSeconds * 1000))
|
|
59
|
+
: Math.max(MINIMUM_INTERVAL_MS, intervalMs + SLOW_DOWN_INTERVAL_INCREMENT_MS);
|
|
60
|
+
}
|
|
61
|
+
const remainingMs = deadline - Date.now();
|
|
62
|
+
if (remainingMs <= 0) {
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
await abortableSleep(Math.min(intervalMs, remainingMs), options.signal, CANCEL_MESSAGE);
|
|
66
|
+
}
|
|
67
|
+
throw new Error(slowDownResponses > 0 ? SLOW_DOWN_TIMEOUT_MESSAGE : TIMEOUT_MESSAGE);
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=device-code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-code.js","sourceRoot":"","sources":["../../../src/auth/oauth/device-code.ts"],"names":[],"mappings":"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","sourcesContent":["const CANCEL_MESSAGE = \"Login cancelled\";\nconst TIMEOUT_MESSAGE = \"Device flow timed out\";\nconst SLOW_DOWN_TIMEOUT_MESSAGE =\n\t\"Device flow timed out after one or more slow_down responses. This is often caused by clock drift in WSL or VM environments. Please sync or restart the VM clock and try again.\";\nconst MINIMUM_INTERVAL_MS = 1000;\n// RFC 8628 section 3.2: if the authorization server omits `interval`, the client must use 5 seconds.\nconst DEFAULT_POLL_INTERVAL_SECONDS = 5;\n// RFC 8628 section 3.5: `slow_down` means the polling interval must increase by 5 seconds.\nconst SLOW_DOWN_INTERVAL_INCREMENT_MS = 5000;\n\ntype OAuthDeviceCodeIncompletePollResult =\n\t| { status: \"pending\" }\n\t| { status: \"slow_down\"; intervalSeconds?: number }\n\t| { status: \"failed\"; message: string };\n\nexport type OAuthDeviceCodePollResult<T> = OAuthDeviceCodeIncompletePollResult | { status: \"complete\"; value: T };\n\nexport type OAuthDeviceCodePollOptions<T> = {\n\tintervalSeconds?: number;\n\texpiresInSeconds?: number;\n\twaitBeforeFirstPoll?: boolean;\n\tpoll: () => Promise<OAuthDeviceCodePollResult<T>>;\n\tsignal: AbortSignal;\n};\n\nexport function abortableSleep(ms: number, signal: AbortSignal, cancelMessage: string): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tif (signal.aborted) {\n\t\t\treject(new Error(cancelMessage));\n\t\t\treturn;\n\t\t}\n\n\t\tconst onAbort = () => {\n\t\t\tclearTimeout(timeout);\n\t\t\treject(new Error(cancelMessage));\n\t\t};\n\t\tconst timeout = setTimeout(() => {\n\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t\tresolve();\n\t\t}, ms);\n\n\t\tsignal.addEventListener(\"abort\", onAbort, { once: true });\n\t});\n}\n\nexport async function pollOAuthDeviceCodeFlow<T>(options: OAuthDeviceCodePollOptions<T>): Promise<T> {\n\tconst deadline =\n\t\ttypeof options.expiresInSeconds === \"number\"\n\t\t\t? Date.now() + options.expiresInSeconds * 1000\n\t\t\t: Number.POSITIVE_INFINITY;\n\tlet intervalMs = Math.max(\n\t\tMINIMUM_INTERVAL_MS,\n\t\tMath.floor((options.intervalSeconds ?? DEFAULT_POLL_INTERVAL_SECONDS) * 1000),\n\t);\n\n\tlet slowDownResponses = 0;\n\tif (options.waitBeforeFirstPoll) {\n\t\tconst remainingMs = deadline - Date.now();\n\t\tif (remainingMs > 0) {\n\t\t\tawait abortableSleep(Math.min(intervalMs, remainingMs), options.signal, CANCEL_MESSAGE);\n\t\t}\n\t}\n\n\twhile (Date.now() < deadline) {\n\t\tif (options.signal.aborted) {\n\t\t\tthrow new Error(CANCEL_MESSAGE);\n\t\t}\n\n\t\tconst result = await options.poll();\n\t\tif (result.status === \"complete\") {\n\t\t\treturn result.value;\n\t\t}\n\t\tif (result.status === \"failed\") {\n\t\t\tthrow new Error(result.message);\n\t\t}\n\t\tif (result.status === \"slow_down\") {\n\t\t\tslowDownResponses += 1;\n\t\t\t// Use the server-provided interval when given (GitHub reports the new required minimum\n\t\t\t// in `interval`); trusting only a client-tracked value risks polling early forever under\n\t\t\t// WSL/VM clock drift. Otherwise apply RFC 8628 section 3.5: increase by 5 seconds.\n\t\t\tintervalMs =\n\t\t\t\ttypeof result.intervalSeconds === \"number\" &&\n\t\t\t\tNumber.isFinite(result.intervalSeconds) &&\n\t\t\t\tresult.intervalSeconds > 0\n\t\t\t\t\t? Math.max(MINIMUM_INTERVAL_MS, Math.floor(result.intervalSeconds * 1000))\n\t\t\t\t\t: Math.max(MINIMUM_INTERVAL_MS, intervalMs + SLOW_DOWN_INTERVAL_INCREMENT_MS);\n\t\t}\n\n\t\tconst remainingMs = deadline - Date.now();\n\t\tif (remainingMs <= 0) {\n\t\t\tbreak;\n\t\t}\n\n\t\tawait abortableSleep(Math.min(intervalMs, remainingMs), options.signal, CANCEL_MESSAGE);\n\t}\n\n\tthrow new Error(slowDownResponses > 0 ? SLOW_DOWN_TIMEOUT_MESSAGE : TIMEOUT_MESSAGE);\n}\n"]}
|