@vib-rato/ai 0.16.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/CHANGELOG.md +3354 -0
- package/README.md +1194 -0
- package/dist/types/adapter-internals/provider-safety-stop.d.ts +45 -0
- package/dist/types/api-registry.d.ts +30 -0
- package/dist/types/auth-broker/client.d.ts +80 -0
- package/dist/types/auth-broker/index.d.ts +5 -0
- package/dist/types/auth-broker/redact.d.ts +7 -0
- package/dist/types/auth-broker/refresher.d.ts +25 -0
- package/dist/types/auth-broker/remote-store.d.ts +153 -0
- package/dist/types/auth-broker/server.d.ts +32 -0
- package/dist/types/auth-broker/types.d.ts +132 -0
- package/dist/types/auth-broker/wire-schemas.d.ts +555 -0
- package/dist/types/auth-gateway/http.d.ts +40 -0
- package/dist/types/auth-gateway/index.d.ts +3 -0
- package/dist/types/auth-gateway/server.d.ts +70 -0
- package/dist/types/auth-gateway/types.d.ts +129 -0
- package/dist/types/auth-storage.d.ts +1074 -0
- package/dist/types/cli.d.ts +2 -0
- package/dist/types/codex-tools.d.ts +4 -0
- package/dist/types/context-cap-policy.d.ts +68 -0
- package/dist/types/core.d.ts +35 -0
- package/dist/types/index.d.ts +55 -0
- package/dist/types/model-cache.d.ts +24 -0
- package/dist/types/model-manager.d.ts +77 -0
- package/dist/types/model-pricing.d.ts +3 -0
- package/dist/types/model-retirements.d.ts +6 -0
- package/dist/types/model-thinking.d.ts +100 -0
- package/dist/types/models.d.ts +21 -0
- package/dist/types/openai-completions-compat.d.ts +34 -0
- package/dist/types/provider-details.d.ts +24 -0
- package/dist/types/provider-models/bundled-references.d.ts +4 -0
- package/dist/types/provider-models/descriptors.d.ts +48 -0
- package/dist/types/provider-models/google.d.ts +20 -0
- package/dist/types/provider-models/index.d.ts +5 -0
- package/dist/types/provider-models/ollama.d.ts +7 -0
- package/dist/types/provider-models/openai-compat.d.ts +293 -0
- package/dist/types/provider-models/special.d.ts +29 -0
- package/dist/types/providers/amazon-bedrock.d.ts +60 -0
- package/dist/types/providers/anthropic-messages-server-schema.d.ts +450 -0
- package/dist/types/providers/anthropic-messages-server.d.ts +17 -0
- package/dist/types/providers/anthropic.d.ts +280 -0
- package/dist/types/providers/aws-credential-config.d.ts +19 -0
- package/dist/types/providers/aws-credentials.d.ts +43 -0
- package/dist/types/providers/aws-eventstream.d.ts +38 -0
- package/dist/types/providers/aws-sigv4.d.ts +55 -0
- package/dist/types/providers/azure-openai-responses.d.ts +22 -0
- package/dist/types/providers/composer-discipline.d.ts +32 -0
- package/dist/types/providers/cursor/client-version.d.ts +10 -0
- package/dist/types/providers/cursor/exec-modern.d.ts +98 -0
- package/dist/types/providers/cursor/gen/agent_pb.d.ts +16769 -0
- package/dist/types/providers/cursor-pi-args.d.ts +119 -0
- package/dist/types/providers/cursor.d.ts +72 -0
- package/dist/types/providers/dashscope-token-plan-headers.d.ts +57 -0
- package/dist/types/providers/error-message.d.ts +27 -0
- package/dist/types/providers/github-copilot-headers.d.ts +40 -0
- package/dist/types/providers/gitlab-duo.d.ts +27 -0
- package/dist/types/providers/google-auth.d.ts +26 -0
- package/dist/types/providers/google-gemini-cli.d.ts +75 -0
- package/dist/types/providers/google-gemini-headers.d.ts +43 -0
- package/dist/types/providers/google-shared.d.ts +183 -0
- package/dist/types/providers/google-types.d.ts +138 -0
- package/dist/types/providers/google-vertex.d.ts +11 -0
- package/dist/types/providers/google.d.ts +4 -0
- package/dist/types/providers/grammar.d.ts +1 -0
- package/dist/types/providers/kimi.d.ts +27 -0
- package/dist/types/providers/kiro-api-key.d.ts +50 -0
- package/dist/types/providers/kiro-codewhisperer.d.ts +11 -0
- package/dist/types/providers/mock.d.ts +189 -0
- package/dist/types/providers/ollama.d.ts +41 -0
- package/dist/types/providers/openai-anthropic-shim.d.ts +31 -0
- package/dist/types/providers/openai-bounded-rate-limits.d.ts +3 -0
- package/dist/types/providers/openai-chat-server-schema.d.ts +1733 -0
- package/dist/types/providers/openai-chat-server.d.ts +16 -0
- package/dist/types/providers/openai-codex/constants.d.ts +26 -0
- package/dist/types/providers/openai-codex/request-transformer.d.ts +50 -0
- package/dist/types/providers/openai-codex/response-handler.d.ts +18 -0
- package/dist/types/providers/openai-codex-responses.d.ts +71 -0
- package/dist/types/providers/openai-completions-compat.d.ts +6 -0
- package/dist/types/providers/openai-completions.d.ts +35 -0
- package/dist/types/providers/openai-opencodex-responses.d.ts +10 -0
- package/dist/types/providers/openai-request-transform.d.ts +4 -0
- package/dist/types/providers/openai-responses-server-schema.d.ts +392 -0
- package/dist/types/providers/openai-responses-server.d.ts +17 -0
- package/dist/types/providers/openai-responses-shared.d.ts +106 -0
- package/dist/types/providers/openai-responses.d.ts +37 -0
- package/dist/types/providers/pi-native-client.d.ts +29 -0
- package/dist/types/providers/pi-native-server.d.ts +60 -0
- package/dist/types/providers/register-builtins.d.ts +59 -0
- package/dist/types/providers/synthetic.d.ts +26 -0
- package/dist/types/providers/transform-messages.d.ts +33 -0
- package/dist/types/providers/vision-guard.d.ts +8 -0
- package/dist/types/rate-limit-utils.d.ts +19 -0
- package/dist/types/stream.d.ts +45 -0
- package/dist/types/types.d.ts +1073 -0
- package/dist/types/usage/claude.d.ts +3 -0
- package/dist/types/usage/gemini.d.ts +2 -0
- package/dist/types/usage/github-copilot.d.ts +7 -0
- package/dist/types/usage/google-antigravity.d.ts +2 -0
- package/dist/types/usage/grok-cli.d.ts +17 -0
- package/dist/types/usage/kimi.d.ts +4 -0
- package/dist/types/usage/minimax-code.d.ts +2 -0
- package/dist/types/usage/openai-codex.d.ts +3 -0
- package/dist/types/usage/shared.d.ts +1 -0
- package/dist/types/usage/zai.d.ts +2 -0
- package/dist/types/usage.d.ts +264 -0
- package/dist/types/utils/abort.d.ts +19 -0
- package/dist/types/utils/anthropic-auth.d.ts +39 -0
- package/dist/types/utils/block-symbols.d.ts +6 -0
- package/dist/types/utils/discovery/antigravity.d.ts +67 -0
- package/dist/types/utils/discovery/codex.d.ts +38 -0
- package/dist/types/utils/discovery/cursor.d.ts +49 -0
- package/dist/types/utils/discovery/gemini.d.ts +25 -0
- package/dist/types/utils/discovery/index.d.ts +4 -0
- package/dist/types/utils/discovery/openai-compatible.d.ts +81 -0
- package/dist/types/utils/event-stream.d.ts +41 -0
- package/dist/types/utils/fallback-transport.d.ts +110 -0
- package/dist/types/utils/fireworks-model-id.d.ts +10 -0
- package/dist/types/utils/foundry.d.ts +11 -0
- package/dist/types/utils/h2-fetch.d.ts +22 -0
- package/dist/types/utils/http-inspector.d.ts +59 -0
- package/dist/types/utils/idle-iterator.d.ts +122 -0
- package/dist/types/utils/json-parse.d.ts +98 -0
- package/dist/types/utils/oauth/alibaba-token-plan.d.ts +19 -0
- package/dist/types/utils/oauth/anthropic.d.ts +41 -0
- package/dist/types/utils/oauth/api-key-login.d.ts +38 -0
- package/dist/types/utils/oauth/api-key-validation.d.ts +39 -0
- package/dist/types/utils/oauth/bizrouter.d.ts +1 -0
- package/dist/types/utils/oauth/callback-server.d.ts +80 -0
- package/dist/types/utils/oauth/cerebras.d.ts +1 -0
- package/dist/types/utils/oauth/cloudflare-ai-gateway.d.ts +18 -0
- package/dist/types/utils/oauth/commandcode.d.ts +1 -0
- package/dist/types/utils/oauth/cursor.d.ts +15 -0
- package/dist/types/utils/oauth/deepinfra.d.ts +1 -0
- package/dist/types/utils/oauth/deepseek.d.ts +10 -0
- package/dist/types/utils/oauth/firepass.d.ts +1 -0
- package/dist/types/utils/oauth/fireworks.d.ts +1 -0
- package/dist/types/utils/oauth/fugu.d.ts +1 -0
- package/dist/types/utils/oauth/github-copilot.d.ts +38 -0
- package/dist/types/utils/oauth/gitlab-duo.d.ts +3 -0
- package/dist/types/utils/oauth/glm-zcode.d.ts +71 -0
- package/dist/types/utils/oauth/google-antigravity.d.ts +11 -0
- package/dist/types/utils/oauth/google-gemini-cli.d.ts +10 -0
- package/dist/types/utils/oauth/google-oauth-shared.d.ts +28 -0
- package/dist/types/utils/oauth/huggingface.d.ts +19 -0
- package/dist/types/utils/oauth/index.d.ts +39 -0
- package/dist/types/utils/oauth/kagi.d.ts +17 -0
- package/dist/types/utils/oauth/kilo.d.ts +5 -0
- package/dist/types/utils/oauth/kimi.d.ts +17 -0
- package/dist/types/utils/oauth/kiro.d.ts +71 -0
- package/dist/types/utils/oauth/litellm.d.ts +18 -0
- package/dist/types/utils/oauth/lm-studio.d.ts +17 -0
- package/dist/types/utils/oauth/mara.d.ts +1 -0
- package/dist/types/utils/oauth/minimax-code.d.ts +28 -0
- package/dist/types/utils/oauth/moonshot.d.ts +1 -0
- package/dist/types/utils/oauth/nanogpt.d.ts +1 -0
- package/dist/types/utils/oauth/nvidia.d.ts +18 -0
- package/dist/types/utils/oauth/ollama-cloud.d.ts +2 -0
- package/dist/types/utils/oauth/ollama.d.ts +18 -0
- package/dist/types/utils/oauth/openai-codex.d.ts +21 -0
- package/dist/types/utils/oauth/opencode.d.ts +18 -0
- package/dist/types/utils/oauth/opengateway.d.ts +1 -0
- package/dist/types/utils/oauth/openrouter.d.ts +1 -0
- package/dist/types/utils/oauth/parallel.d.ts +17 -0
- package/dist/types/utils/oauth/perplexity.d.ts +4 -0
- package/dist/types/utils/oauth/pkce.d.ts +8 -0
- package/dist/types/utils/oauth/qianfan.d.ts +17 -0
- package/dist/types/utils/oauth/qwen-portal.d.ts +19 -0
- package/dist/types/utils/oauth/sglang.d.ts +16 -0
- package/dist/types/utils/oauth/synthetic.d.ts +1 -0
- package/dist/types/utils/oauth/tavily.d.ts +17 -0
- package/dist/types/utils/oauth/together.d.ts +1 -0
- package/dist/types/utils/oauth/types.d.ts +56 -0
- package/dist/types/utils/oauth/venice.d.ts +18 -0
- package/dist/types/utils/oauth/vercel-ai-gateway.d.ts +18 -0
- package/dist/types/utils/oauth/vllm.d.ts +16 -0
- package/dist/types/utils/oauth/xai.d.ts +30 -0
- package/dist/types/utils/oauth/xiaomi.d.ts +25 -0
- package/dist/types/utils/oauth/zai.d.ts +18 -0
- package/dist/types/utils/oauth/zenmux.d.ts +1 -0
- package/dist/types/utils/overflow.d.ts +14 -0
- package/dist/types/utils/parse-bind.d.ts +26 -0
- package/dist/types/utils/provider-response.d.ts +6 -0
- package/dist/types/utils/provider-safety-stop.d.ts +8 -0
- package/dist/types/utils/proxy.d.ts +7 -0
- package/dist/types/utils/retry-after.d.ts +3 -0
- package/dist/types/utils/retry-budget.d.ts +1 -0
- package/dist/types/utils/retry.d.ts +29 -0
- package/dist/types/utils/schema/adapt.d.ts +24 -0
- package/dist/types/utils/schema/compatibility.d.ts +30 -0
- package/dist/types/utils/schema/dereference.d.ts +11 -0
- package/dist/types/utils/schema/draft.d.ts +10 -0
- package/dist/types/utils/schema/equality.d.ts +4 -0
- package/dist/types/utils/schema/fields.d.ts +49 -0
- package/dist/types/utils/schema/index.d.ts +14 -0
- package/dist/types/utils/schema/json-schema-validator.d.ts +12 -0
- package/dist/types/utils/schema/meta-validator.d.ts +2 -0
- package/dist/types/utils/schema/normalize.d.ts +93 -0
- package/dist/types/utils/schema/root-combinator.d.ts +12 -0
- package/dist/types/utils/schema/spill.d.ts +8 -0
- package/dist/types/utils/schema/stamps.d.ts +25 -0
- package/dist/types/utils/schema/types.d.ts +4 -0
- package/dist/types/utils/schema/wire.d.ts +54 -0
- package/dist/types/utils/schema/zod-decontaminate.d.ts +31 -0
- package/dist/types/utils/sse-debug.d.ts +10 -0
- package/dist/types/utils/tool-call-healing.d.ts +80 -0
- package/dist/types/utils/tool-choice-capability.d.ts +57 -0
- package/dist/types/utils/tool-choice.d.ts +50 -0
- package/dist/types/utils/validation.d.ts +17 -0
- package/dist/types/utils.d.ts +117 -0
- package/package.json +152 -0
- package/src/adapter-internals/provider-safety-stop.d.ts +45 -0
- package/src/adapter-internals/provider-safety-stop.ts +156 -0
- package/src/api-registry.d.ts +30 -0
- package/src/api-registry.ts +96 -0
- package/src/auth-broker/client.ts +444 -0
- package/src/auth-broker/index.ts +5 -0
- package/src/auth-broker/redact.ts +39 -0
- package/src/auth-broker/refresher.ts +130 -0
- package/src/auth-broker/remote-store.ts +1576 -0
- package/src/auth-broker/server.ts +764 -0
- package/src/auth-broker/types.ts +164 -0
- package/src/auth-broker/wire-schemas.ts +261 -0
- package/src/auth-gateway/http.ts +198 -0
- package/src/auth-gateway/index.ts +3 -0
- package/src/auth-gateway/server.ts +1315 -0
- package/src/auth-gateway/types.ts +160 -0
- package/src/auth-storage.ts +7312 -0
- package/src/cli.ts +269 -0
- package/src/codex-tools.d.ts +4 -0
- package/src/codex-tools.ts +24 -0
- package/src/context-cap-policy.d.ts +68 -0
- package/src/context-cap-policy.ts +123 -0
- package/src/core.ts +44 -0
- package/src/index.ts +61 -0
- package/src/model-cache.ts +236 -0
- package/src/model-manager.ts +744 -0
- package/src/model-pricing.d.ts +3 -0
- package/src/model-pricing.ts +68 -0
- package/src/model-retirements.d.ts +6 -0
- package/src/model-retirements.ts +19 -0
- package/src/model-thinking.d.ts +100 -0
- package/src/model-thinking.ts +1054 -0
- package/src/models.d.ts +21 -0
- package/src/models.json +94672 -0
- package/src/models.json.d.ts +9 -0
- package/src/models.ts +126 -0
- package/src/openai-completions-compat.d.ts +34 -0
- package/src/openai-completions-compat.ts +383 -0
- package/src/prompts/composer-bash-policy-recovery.md +1 -0
- package/src/prompts/cursor-composer-bash-policy-recovery.md +1 -0
- package/src/prompts/cursor-composer-edit-discipline.md +7 -0
- package/src/prompts/turn-aborted-guidance.md +4 -0
- package/src/provider-details.ts +90 -0
- package/src/provider-models/bundled-references.ts +38 -0
- package/src/provider-models/descriptors.ts +392 -0
- package/src/provider-models/google.ts +92 -0
- package/src/provider-models/index.ts +5 -0
- package/src/provider-models/ollama.ts +159 -0
- package/src/provider-models/openai-compat.ts +2920 -0
- package/src/provider-models/special.ts +185 -0
- package/src/providers/amazon-bedrock.d.ts +60 -0
- package/src/providers/amazon-bedrock.ts +939 -0
- package/src/providers/anthropic-messages-server-schema.ts +229 -0
- package/src/providers/anthropic-messages-server.ts +839 -0
- package/src/providers/anthropic.d.ts +280 -0
- package/src/providers/anthropic.ts +4421 -0
- package/src/providers/aws-credential-config.d.ts +19 -0
- package/src/providers/aws-credential-config.ts +179 -0
- package/src/providers/aws-credentials.d.ts +43 -0
- package/src/providers/aws-credentials.ts +457 -0
- package/src/providers/aws-eventstream.d.ts +38 -0
- package/src/providers/aws-eventstream.ts +185 -0
- package/src/providers/aws-sigv4.d.ts +55 -0
- package/src/providers/aws-sigv4.ts +218 -0
- package/src/providers/azure-openai-responses.d.ts +22 -0
- package/src/providers/azure-openai-responses.ts +447 -0
- package/src/providers/composer-discipline.d.ts +32 -0
- package/src/providers/composer-discipline.ts +95 -0
- package/src/providers/cursor/client-version.d.ts +10 -0
- package/src/providers/cursor/client-version.ts +10 -0
- package/src/providers/cursor/exec-modern.d.ts +98 -0
- package/src/providers/cursor/exec-modern.ts +497 -0
- package/src/providers/cursor/gen/agent_pb.d.ts +16769 -0
- package/src/providers/cursor/gen/agent_pb.ts +19780 -0
- package/src/providers/cursor/proto/agent.proto +4533 -0
- package/src/providers/cursor/proto/buf.gen.yaml +6 -0
- package/src/providers/cursor/proto/buf.yaml +17 -0
- package/src/providers/cursor-pi-args.d.ts +119 -0
- package/src/providers/cursor-pi-args.ts +187 -0
- package/src/providers/cursor.d.ts +72 -0
- package/src/providers/cursor.ts +3396 -0
- package/src/providers/dashscope-token-plan-headers.d.ts +57 -0
- package/src/providers/dashscope-token-plan-headers.ts +84 -0
- package/src/providers/error-message.d.ts +27 -0
- package/src/providers/error-message.ts +21 -0
- package/src/providers/github-copilot-headers.d.ts +40 -0
- package/src/providers/github-copilot-headers.ts +140 -0
- package/src/providers/gitlab-duo.d.ts +27 -0
- package/src/providers/gitlab-duo.ts +393 -0
- package/src/providers/google-auth.d.ts +26 -0
- package/src/providers/google-auth.ts +262 -0
- package/src/providers/google-gemini-cli.d.ts +75 -0
- package/src/providers/google-gemini-cli.ts +969 -0
- package/src/providers/google-gemini-headers.d.ts +43 -0
- package/src/providers/google-gemini-headers.ts +100 -0
- package/src/providers/google-shared.d.ts +183 -0
- package/src/providers/google-shared.ts +1105 -0
- package/src/providers/google-types.d.ts +138 -0
- package/src/providers/google-types.ts +167 -0
- package/src/providers/google-vertex.d.ts +11 -0
- package/src/providers/google-vertex.ts +124 -0
- package/src/providers/google.d.ts +4 -0
- package/src/providers/google.ts +41 -0
- package/src/providers/grammar.d.ts +1 -0
- package/src/providers/grammar.ts +70 -0
- package/src/providers/kimi.d.ts +27 -0
- package/src/providers/kimi.ts +52 -0
- package/src/providers/kiro-api-key.d.ts +50 -0
- package/src/providers/kiro-api-key.ts +786 -0
- package/src/providers/kiro-codewhisperer.d.ts +11 -0
- package/src/providers/kiro-codewhisperer.ts +600 -0
- package/src/providers/mock.ts +526 -0
- package/src/providers/ollama.d.ts +41 -0
- package/src/providers/ollama.ts +645 -0
- package/src/providers/openai-anthropic-shim.d.ts +31 -0
- package/src/providers/openai-anthropic-shim.ts +156 -0
- package/src/providers/openai-bounded-rate-limits.d.ts +3 -0
- package/src/providers/openai-bounded-rate-limits.ts +57 -0
- package/src/providers/openai-chat-server-schema.ts +254 -0
- package/src/providers/openai-chat-server.ts +724 -0
- package/src/providers/openai-codex/constants.d.ts +26 -0
- package/src/providers/openai-codex/constants.ts +43 -0
- package/src/providers/openai-codex/request-transformer.d.ts +50 -0
- package/src/providers/openai-codex/request-transformer.ts +219 -0
- package/src/providers/openai-codex/response-handler.d.ts +18 -0
- package/src/providers/openai-codex/response-handler.ts +111 -0
- package/src/providers/openai-codex-responses.d.ts +71 -0
- package/src/providers/openai-codex-responses.ts +3288 -0
- package/src/providers/openai-completions-compat.d.ts +6 -0
- package/src/providers/openai-completions-compat.ts +6 -0
- package/src/providers/openai-completions.d.ts +35 -0
- package/src/providers/openai-completions.ts +2294 -0
- package/src/providers/openai-opencodex-responses.ts +174 -0
- package/src/providers/openai-request-transform.d.ts +4 -0
- package/src/providers/openai-request-transform.ts +136 -0
- package/src/providers/openai-responses-server-schema.ts +290 -0
- package/src/providers/openai-responses-server.ts +1268 -0
- package/src/providers/openai-responses-shared.d.ts +106 -0
- package/src/providers/openai-responses-shared.ts +1253 -0
- package/src/providers/openai-responses.d.ts +37 -0
- package/src/providers/openai-responses.ts +989 -0
- package/src/providers/pi-native-client.d.ts +29 -0
- package/src/providers/pi-native-client.ts +243 -0
- package/src/providers/pi-native-server.ts +488 -0
- package/src/providers/register-builtins.d.ts +59 -0
- package/src/providers/register-builtins.ts +544 -0
- package/src/providers/synthetic.d.ts +26 -0
- package/src/providers/synthetic.ts +50 -0
- package/src/providers/transform-messages.d.ts +33 -0
- package/src/providers/transform-messages.ts +408 -0
- package/src/providers/vision-guard.d.ts +8 -0
- package/src/providers/vision-guard.ts +31 -0
- package/src/rate-limit-utils.d.ts +19 -0
- package/src/rate-limit-utils.ts +102 -0
- package/src/stream.d.ts +45 -0
- package/src/stream.ts +1306 -0
- package/src/types.d.ts +1073 -0
- package/src/types.ts +1305 -0
- package/src/usage/claude.ts +449 -0
- package/src/usage/gemini.ts +250 -0
- package/src/usage/github-copilot.ts +421 -0
- package/src/usage/google-antigravity.ts +201 -0
- package/src/usage/grok-cli.ts +259 -0
- package/src/usage/kimi.ts +285 -0
- package/src/usage/minimax-code.ts +31 -0
- package/src/usage/openai-codex.ts +503 -0
- package/src/usage/shared.ts +10 -0
- package/src/usage/zai.ts +247 -0
- package/src/usage.ts +190 -0
- package/src/utils/abort.d.ts +19 -0
- package/src/utils/abort.ts +51 -0
- package/src/utils/anthropic-auth.ts +95 -0
- package/src/utils/block-symbols.d.ts +6 -0
- package/src/utils/block-symbols.ts +11 -0
- package/src/utils/discovery/antigravity.ts +275 -0
- package/src/utils/discovery/codex.ts +362 -0
- package/src/utils/discovery/cursor.ts +388 -0
- package/src/utils/discovery/gemini.ts +248 -0
- package/src/utils/discovery/index.ts +4 -0
- package/src/utils/discovery/openai-compatible.ts +379 -0
- package/src/utils/event-stream.d.ts +41 -0
- package/src/utils/event-stream.ts +269 -0
- package/src/utils/fallback-transport.d.ts +110 -0
- package/src/utils/fallback-transport.ts +411 -0
- package/src/utils/fireworks-model-id.d.ts +10 -0
- package/src/utils/fireworks-model-id.ts +30 -0
- package/src/utils/foundry.d.ts +11 -0
- package/src/utils/foundry.ts +18 -0
- package/src/utils/h2-fetch.ts +60 -0
- package/src/utils/http-inspector.d.ts +59 -0
- package/src/utils/http-inspector.ts +380 -0
- package/src/utils/idle-iterator.d.ts +122 -0
- package/src/utils/idle-iterator.ts +410 -0
- package/src/utils/json-parse.d.ts +98 -0
- package/src/utils/json-parse.ts +607 -0
- package/src/utils/oauth/alibaba-token-plan.ts +60 -0
- package/src/utils/oauth/anthropic.ts +233 -0
- package/src/utils/oauth/api-key-login.ts +98 -0
- package/src/utils/oauth/api-key-validation.ts +344 -0
- package/src/utils/oauth/bizrouter.ts +15 -0
- package/src/utils/oauth/callback-server.d.ts +80 -0
- package/src/utils/oauth/callback-server.ts +359 -0
- package/src/utils/oauth/cerebras.ts +16 -0
- package/src/utils/oauth/cloudflare-ai-gateway.ts +48 -0
- package/src/utils/oauth/commandcode.ts +17 -0
- package/src/utils/oauth/cursor.ts +157 -0
- package/src/utils/oauth/deepinfra.ts +15 -0
- package/src/utils/oauth/deepseek.ts +53 -0
- package/src/utils/oauth/firepass.ts +24 -0
- package/src/utils/oauth/fireworks.ts +15 -0
- package/src/utils/oauth/fugu.ts +15 -0
- package/src/utils/oauth/github-copilot.d.ts +38 -0
- package/src/utils/oauth/github-copilot.ts +362 -0
- package/src/utils/oauth/gitlab-duo.ts +123 -0
- package/src/utils/oauth/glm-zcode.d.ts +71 -0
- package/src/utils/oauth/glm-zcode.ts +433 -0
- package/src/utils/oauth/google-antigravity.ts +200 -0
- package/src/utils/oauth/google-gemini-cli.ts +256 -0
- package/src/utils/oauth/google-oauth-shared.ts +110 -0
- package/src/utils/oauth/huggingface.ts +62 -0
- package/src/utils/oauth/index.ts +558 -0
- package/src/utils/oauth/kagi.ts +47 -0
- package/src/utils/oauth/kilo.ts +87 -0
- package/src/utils/oauth/kimi.d.ts +17 -0
- package/src/utils/oauth/kimi.ts +275 -0
- package/src/utils/oauth/kiro.ts +448 -0
- package/src/utils/oauth/litellm.ts +47 -0
- package/src/utils/oauth/lm-studio.ts +38 -0
- package/src/utils/oauth/mara.ts +16 -0
- package/src/utils/oauth/minimax-code.ts +78 -0
- package/src/utils/oauth/moonshot.ts +16 -0
- package/src/utils/oauth/nanogpt.ts +15 -0
- package/src/utils/oauth/nvidia.ts +70 -0
- package/src/utils/oauth/oauth.html +199 -0
- package/src/utils/oauth/ollama-cloud.ts +28 -0
- package/src/utils/oauth/ollama.ts +47 -0
- package/src/utils/oauth/openai-codex.ts +299 -0
- package/src/utils/oauth/opencode.ts +49 -0
- package/src/utils/oauth/opengateway.ts +15 -0
- package/src/utils/oauth/openrouter.ts +16 -0
- package/src/utils/oauth/parallel.ts +46 -0
- package/src/utils/oauth/perplexity.ts +225 -0
- package/src/utils/oauth/pkce.ts +18 -0
- package/src/utils/oauth/qianfan.ts +58 -0
- package/src/utils/oauth/qwen-portal.ts +60 -0
- package/src/utils/oauth/sglang.ts +42 -0
- package/src/utils/oauth/synthetic.ts +15 -0
- package/src/utils/oauth/tavily.ts +46 -0
- package/src/utils/oauth/together.ts +16 -0
- package/src/utils/oauth/types.d.ts +56 -0
- package/src/utils/oauth/types.ts +122 -0
- package/src/utils/oauth/venice.ts +59 -0
- package/src/utils/oauth/vercel-ai-gateway.ts +47 -0
- package/src/utils/oauth/vllm.ts +42 -0
- package/src/utils/oauth/xai.ts +246 -0
- package/src/utils/oauth/xiaomi.ts +199 -0
- package/src/utils/oauth/zai.ts +60 -0
- package/src/utils/oauth/zenmux.ts +15 -0
- package/src/utils/overflow.ts +275 -0
- package/src/utils/parse-bind.ts +81 -0
- package/src/utils/provider-response.d.ts +6 -0
- package/src/utils/provider-response.ts +30 -0
- package/src/utils/provider-safety-stop.ts +8 -0
- package/src/utils/proxy.d.ts +7 -0
- package/src/utils/proxy.ts +652 -0
- package/src/utils/retry-after.d.ts +3 -0
- package/src/utils/retry-after.ts +110 -0
- package/src/utils/retry-budget.d.ts +1 -0
- package/src/utils/retry-budget.ts +4 -0
- package/src/utils/retry.d.ts +29 -0
- package/src/utils/retry.ts +67 -0
- package/src/utils/schema/CONSTRAINTS.md +164 -0
- package/src/utils/schema/adapt.d.ts +24 -0
- package/src/utils/schema/adapt.ts +36 -0
- package/src/utils/schema/compatibility.d.ts +30 -0
- package/src/utils/schema/compatibility.ts +435 -0
- package/src/utils/schema/dereference.d.ts +11 -0
- package/src/utils/schema/dereference.ts +98 -0
- package/src/utils/schema/draft.d.ts +10 -0
- package/src/utils/schema/draft.ts +341 -0
- package/src/utils/schema/equality.d.ts +4 -0
- package/src/utils/schema/equality.ts +97 -0
- package/src/utils/schema/fields.d.ts +49 -0
- package/src/utils/schema/fields.ts +190 -0
- package/src/utils/schema/index.d.ts +14 -0
- package/src/utils/schema/index.ts +14 -0
- package/src/utils/schema/json-schema-validator.d.ts +12 -0
- package/src/utils/schema/json-schema-validator.ts +577 -0
- package/src/utils/schema/meta-validator.d.ts +2 -0
- package/src/utils/schema/meta-validator.ts +167 -0
- package/src/utils/schema/normalize.d.ts +93 -0
- package/src/utils/schema/normalize.ts +1588 -0
- package/src/utils/schema/root-combinator.d.ts +12 -0
- package/src/utils/schema/root-combinator.ts +143 -0
- package/src/utils/schema/spill.d.ts +8 -0
- package/src/utils/schema/spill.ts +43 -0
- package/src/utils/schema/stamps.d.ts +25 -0
- package/src/utils/schema/stamps.ts +97 -0
- package/src/utils/schema/types.d.ts +4 -0
- package/src/utils/schema/types.ts +11 -0
- package/src/utils/schema/wire.d.ts +54 -0
- package/src/utils/schema/wire.ts +213 -0
- package/src/utils/schema/zod-decontaminate.d.ts +31 -0
- package/src/utils/schema/zod-decontaminate.ts +331 -0
- package/src/utils/sse-debug.d.ts +10 -0
- package/src/utils/sse-debug.ts +289 -0
- package/src/utils/tool-call-healing.d.ts +80 -0
- package/src/utils/tool-call-healing.ts +298 -0
- package/src/utils/tool-choice-capability.d.ts +57 -0
- package/src/utils/tool-choice-capability.ts +633 -0
- package/src/utils/tool-choice.d.ts +50 -0
- package/src/utils/tool-choice.ts +99 -0
- package/src/utils/validation.ts +1080 -0
- package/src/utils.d.ts +117 -0
- package/src/utils.ts +523 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { OAuthController, OAuthCredentials } from "./types";
|
|
2
|
+
export type CallbackResult = {
|
|
3
|
+
code: string;
|
|
4
|
+
state: string;
|
|
5
|
+
};
|
|
6
|
+
export interface OAuthCallbackFlowOptions {
|
|
7
|
+
preferredPort: number;
|
|
8
|
+
callbackPath?: string;
|
|
9
|
+
callbackHostname?: string;
|
|
10
|
+
/** Local listener hostname; defaults to callbackHostname when omitted. */
|
|
11
|
+
callbackBindHostname?: string;
|
|
12
|
+
/** Exact redirect URI advertised to the provider; disables port fallback. */
|
|
13
|
+
redirectUri?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Do not bind a local listener at all. The provider redirects somewhere this
|
|
16
|
+
* process cannot observe (a hosted "copy this code" page, a custom protocol),
|
|
17
|
+
* so the code arrives by paste instead. Requires both `redirectUri` and an
|
|
18
|
+
* `onManualCodeInput` handler on the controller.
|
|
19
|
+
*/
|
|
20
|
+
skipCallbackServer?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Expected authorization-server issuer recorded from validated metadata
|
|
23
|
+
* (RFC 9207 / MCP 2026-07-28). When set, a present `iss` that differs
|
|
24
|
+
* rejects the response before any other parameter is acted on.
|
|
25
|
+
*/
|
|
26
|
+
expectedIssuer?: string;
|
|
27
|
+
/**
|
|
28
|
+
* `authorization_response_iss_parameter_supported` from the same metadata.
|
|
29
|
+
* When true, a response WITHOUT `iss` is rejected.
|
|
30
|
+
*/
|
|
31
|
+
issuerResponseIssSupported?: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Abstract base class for OAuth flows with local callback servers.
|
|
35
|
+
*/
|
|
36
|
+
export declare abstract class OAuthCallbackFlow {
|
|
37
|
+
#private;
|
|
38
|
+
ctrl: OAuthController;
|
|
39
|
+
preferredPort: number;
|
|
40
|
+
callbackPath: string;
|
|
41
|
+
callbackHostname: string;
|
|
42
|
+
callbackBindHostname: string;
|
|
43
|
+
redirectUri?: string;
|
|
44
|
+
expectedIssuer?: string;
|
|
45
|
+
issuerResponseIssSupported?: boolean;
|
|
46
|
+
constructor(ctrl: OAuthController, preferredPortOrOptions: number | OAuthCallbackFlowOptions, callbackPath?: string);
|
|
47
|
+
/**
|
|
48
|
+
* Generate provider-specific authorization URL.
|
|
49
|
+
* @param state - CSRF state token
|
|
50
|
+
* @param redirectUri - The actual redirect URI to use (may differ from expected if port fallback occurred)
|
|
51
|
+
* @returns Authorization URL and optional instructions
|
|
52
|
+
*/
|
|
53
|
+
abstract generateAuthUrl(state: string, redirectUri: string): Promise<{
|
|
54
|
+
url: string;
|
|
55
|
+
instructions?: string;
|
|
56
|
+
}>;
|
|
57
|
+
/**
|
|
58
|
+
* Exchange authorization code for OAuth tokens.
|
|
59
|
+
* @param code - Authorization code from callback
|
|
60
|
+
* @param state - CSRF state token
|
|
61
|
+
* @param redirectUri - The actual redirect URI used (must match authorization request)
|
|
62
|
+
* @returns OAuth credentials
|
|
63
|
+
*/
|
|
64
|
+
abstract exchangeToken(code: string, state: string, redirectUri: string): Promise<OAuthCredentials>;
|
|
65
|
+
/**
|
|
66
|
+
* Generate CSRF state token. Override if provider needs custom state generation.
|
|
67
|
+
*/
|
|
68
|
+
generateState(): string;
|
|
69
|
+
/**
|
|
70
|
+
* Execute the OAuth login flow.
|
|
71
|
+
*/
|
|
72
|
+
login(): Promise<OAuthCredentials>;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Parse a redirect URL or code string to extract code and state.
|
|
76
|
+
*/
|
|
77
|
+
export declare function parseCallbackInput(input: string): {
|
|
78
|
+
code?: string;
|
|
79
|
+
state?: string;
|
|
80
|
+
};
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Abstract base class for OAuth flows with local callback servers.
|
|
3
|
+
*
|
|
4
|
+
* Handles:
|
|
5
|
+
* - Port allocation (tries expected port, falls back to random)
|
|
6
|
+
* - Callback server setup and request handling
|
|
7
|
+
* - Opting out of the local listener entirely (`skipCallbackServer`) for
|
|
8
|
+
* providers that redirect somewhere this process cannot observe
|
|
9
|
+
* - Common OAuth flow logic
|
|
10
|
+
*
|
|
11
|
+
* Providers extend this and implement:
|
|
12
|
+
* - generateAuthUrl(): Build provider-specific authorization URL
|
|
13
|
+
* - exchangeToken(): Exchange authorization code for tokens
|
|
14
|
+
*/
|
|
15
|
+
import templateHtml from "./oauth.html" with { type: "text" };
|
|
16
|
+
import type { OAuthController, OAuthCredentials } from "./types";
|
|
17
|
+
|
|
18
|
+
const DEFAULT_TIMEOUT = 300_000;
|
|
19
|
+
const DEFAULT_HOSTNAME = "localhost";
|
|
20
|
+
const CALLBACK_PATH = "/callback";
|
|
21
|
+
|
|
22
|
+
export type CallbackResult = { code: string; state: string };
|
|
23
|
+
|
|
24
|
+
export interface OAuthCallbackFlowOptions {
|
|
25
|
+
preferredPort: number;
|
|
26
|
+
callbackPath?: string;
|
|
27
|
+
callbackHostname?: string;
|
|
28
|
+
/** Local listener hostname; defaults to callbackHostname when omitted. */
|
|
29
|
+
callbackBindHostname?: string;
|
|
30
|
+
/** Exact redirect URI advertised to the provider; disables port fallback. */
|
|
31
|
+
redirectUri?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Do not bind a local listener at all. The provider redirects somewhere this
|
|
34
|
+
* process cannot observe (a hosted "copy this code" page, a custom protocol),
|
|
35
|
+
* so the code arrives by paste instead. Requires both `redirectUri` and an
|
|
36
|
+
* `onManualCodeInput` handler on the controller.
|
|
37
|
+
*/
|
|
38
|
+
skipCallbackServer?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Expected authorization-server issuer recorded from validated metadata
|
|
41
|
+
* (RFC 9207 / MCP 2026-07-28). When set, a present `iss` that differs
|
|
42
|
+
* rejects the response before any other parameter is acted on.
|
|
43
|
+
*/
|
|
44
|
+
expectedIssuer?: string;
|
|
45
|
+
/**
|
|
46
|
+
* `authorization_response_iss_parameter_supported` from the same metadata.
|
|
47
|
+
* When true, a response WITHOUT `iss` is rejected.
|
|
48
|
+
*/
|
|
49
|
+
issuerResponseIssSupported?: boolean;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Abstract base class for OAuth flows with local callback servers.
|
|
54
|
+
*/
|
|
55
|
+
export abstract class OAuthCallbackFlow {
|
|
56
|
+
ctrl: OAuthController;
|
|
57
|
+
preferredPort: number;
|
|
58
|
+
callbackPath: string;
|
|
59
|
+
callbackHostname: string;
|
|
60
|
+
callbackBindHostname: string;
|
|
61
|
+
redirectUri?: string;
|
|
62
|
+
expectedIssuer?: string;
|
|
63
|
+
issuerResponseIssSupported?: boolean;
|
|
64
|
+
readonly #skipCallbackServer: boolean;
|
|
65
|
+
#callbackResolve?: (result: CallbackResult) => void;
|
|
66
|
+
#callbackReject?: (error: string) => void;
|
|
67
|
+
|
|
68
|
+
constructor(
|
|
69
|
+
ctrl: OAuthController,
|
|
70
|
+
preferredPortOrOptions: number | OAuthCallbackFlowOptions,
|
|
71
|
+
callbackPath: string = CALLBACK_PATH,
|
|
72
|
+
) {
|
|
73
|
+
this.ctrl = ctrl;
|
|
74
|
+
if (typeof preferredPortOrOptions === "number") {
|
|
75
|
+
this.preferredPort = preferredPortOrOptions;
|
|
76
|
+
this.callbackPath = callbackPath;
|
|
77
|
+
this.callbackHostname = DEFAULT_HOSTNAME;
|
|
78
|
+
this.callbackBindHostname = DEFAULT_HOSTNAME;
|
|
79
|
+
this.#skipCallbackServer = false;
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
this.preferredPort = preferredPortOrOptions.preferredPort;
|
|
84
|
+
this.callbackPath = preferredPortOrOptions.callbackPath ?? CALLBACK_PATH;
|
|
85
|
+
this.callbackHostname = preferredPortOrOptions.callbackHostname ?? DEFAULT_HOSTNAME;
|
|
86
|
+
this.callbackBindHostname = preferredPortOrOptions.callbackBindHostname ?? this.callbackHostname;
|
|
87
|
+
this.redirectUri = preferredPortOrOptions.redirectUri;
|
|
88
|
+
this.expectedIssuer = preferredPortOrOptions.expectedIssuer;
|
|
89
|
+
this.issuerResponseIssSupported = preferredPortOrOptions.issuerResponseIssSupported;
|
|
90
|
+
this.#skipCallbackServer = preferredPortOrOptions.skipCallbackServer === true;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Generate provider-specific authorization URL.
|
|
95
|
+
* @param state - CSRF state token
|
|
96
|
+
* @param redirectUri - The actual redirect URI to use (may differ from expected if port fallback occurred)
|
|
97
|
+
* @returns Authorization URL and optional instructions
|
|
98
|
+
*/
|
|
99
|
+
abstract generateAuthUrl(state: string, redirectUri: string): Promise<{ url: string; instructions?: string }>;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Exchange authorization code for OAuth tokens.
|
|
103
|
+
* @param code - Authorization code from callback
|
|
104
|
+
* @param state - CSRF state token
|
|
105
|
+
* @param redirectUri - The actual redirect URI used (must match authorization request)
|
|
106
|
+
* @returns OAuth credentials
|
|
107
|
+
*/
|
|
108
|
+
abstract exchangeToken(code: string, state: string, redirectUri: string): Promise<OAuthCredentials>;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Generate CSRF state token. Override if provider needs custom state generation.
|
|
112
|
+
*/
|
|
113
|
+
generateState(): string {
|
|
114
|
+
const bytes = new Uint8Array(16);
|
|
115
|
+
crypto.getRandomValues(bytes);
|
|
116
|
+
return Array.from(bytes)
|
|
117
|
+
.map(value => value.toString(16).padStart(2, "0"))
|
|
118
|
+
.join("");
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Execute the OAuth login flow.
|
|
123
|
+
*/
|
|
124
|
+
async login(): Promise<OAuthCredentials> {
|
|
125
|
+
if (this.#skipCallbackServer && !this.ctrl.onManualCodeInput) {
|
|
126
|
+
// Fail before a browser is opened: without a listener and without a paste
|
|
127
|
+
// handler the flow can only sit until the 5-minute timeout.
|
|
128
|
+
throw new Error(
|
|
129
|
+
"OAuth flow is configured without a local callback server, but no manual authorization-code handler was provided",
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
const state = this.generateState();
|
|
133
|
+
|
|
134
|
+
// Start callback server first to get actual redirect URI
|
|
135
|
+
const { server, redirectUri } = await this.#startCallbackServer(state);
|
|
136
|
+
|
|
137
|
+
try {
|
|
138
|
+
// Generate auth URL with the ACTUAL redirect URI (may differ from expected if port was busy)
|
|
139
|
+
const { url: authUrl, instructions } = await this.generateAuthUrl(state, redirectUri);
|
|
140
|
+
|
|
141
|
+
// Notify controller that auth is ready
|
|
142
|
+
this.ctrl.onAuth?.({ url: authUrl, instructions });
|
|
143
|
+
this.ctrl.onProgress?.(
|
|
144
|
+
this.#skipCallbackServer
|
|
145
|
+
? "Waiting for the authorization code..."
|
|
146
|
+
: "Waiting for browser authentication...",
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
// Wait for callback or manual input
|
|
150
|
+
const { code } = await this.#waitForCallback(state);
|
|
151
|
+
|
|
152
|
+
this.ctrl.onProgress?.("Exchanging authorization code for tokens...");
|
|
153
|
+
|
|
154
|
+
return await this.exchangeToken(code, state, redirectUri);
|
|
155
|
+
} finally {
|
|
156
|
+
server?.stop();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Start callback server, trying preferred port first, falling back to random.
|
|
162
|
+
* Returns no server when the flow opted out of the local listener.
|
|
163
|
+
*/
|
|
164
|
+
async #startCallbackServer(
|
|
165
|
+
expectedState: string,
|
|
166
|
+
): Promise<{ server: Bun.Server<unknown> | undefined; redirectUri: string }> {
|
|
167
|
+
if (this.#skipCallbackServer) {
|
|
168
|
+
if (!this.redirectUri) {
|
|
169
|
+
throw new Error("OAuth flow skips the local callback server but no redirect URI was configured");
|
|
170
|
+
}
|
|
171
|
+
return { server: undefined, redirectUri: this.redirectUri };
|
|
172
|
+
}
|
|
173
|
+
try {
|
|
174
|
+
const server = this.#createServer(this.preferredPort, expectedState);
|
|
175
|
+
if (this.redirectUri) {
|
|
176
|
+
return { server, redirectUri: this.redirectUri };
|
|
177
|
+
}
|
|
178
|
+
const redirectUri = `http://${this.callbackHostname}:${this.preferredPort}${this.callbackPath}`;
|
|
179
|
+
return { server, redirectUri };
|
|
180
|
+
} catch {
|
|
181
|
+
if (this.redirectUri) {
|
|
182
|
+
throw new Error(
|
|
183
|
+
`OAuth callback port ${this.preferredPort} unavailable; cannot fall back to a random port when oauth.redirectUri is set`,
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
const server = this.#createServer(0, expectedState);
|
|
187
|
+
const actualPort = server.port;
|
|
188
|
+
const redirectUri = `http://${this.callbackHostname}:${actualPort}${this.callbackPath}`;
|
|
189
|
+
this.ctrl.onProgress?.(`Preferred port ${this.preferredPort} unavailable, using port ${actualPort}`);
|
|
190
|
+
return { server, redirectUri };
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Create HTTP server for OAuth callback.
|
|
196
|
+
*/
|
|
197
|
+
#createServer(port: number, expectedState: string): Bun.Server<unknown> {
|
|
198
|
+
return Bun.serve({
|
|
199
|
+
hostname: this.callbackBindHostname,
|
|
200
|
+
port,
|
|
201
|
+
reusePort: false,
|
|
202
|
+
fetch: req => this.#handleCallback(req, expectedState),
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Handle OAuth callback HTTP request.
|
|
208
|
+
*/
|
|
209
|
+
#handleCallback(req: Request, expectedState: string): Response {
|
|
210
|
+
const url = new URL(req.url);
|
|
211
|
+
|
|
212
|
+
if (url.pathname !== this.callbackPath) {
|
|
213
|
+
return new Response("Not Found", { status: 404 });
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const code = url.searchParams.get("code");
|
|
217
|
+
const state = url.searchParams.get("state") || "";
|
|
218
|
+
const error = url.searchParams.get("error") || "";
|
|
219
|
+
const errorDescription = url.searchParams.get("error_description") || error;
|
|
220
|
+
const iss = url.searchParams.get("iss");
|
|
221
|
+
|
|
222
|
+
type OkState = { ok: true; code: string; state: string };
|
|
223
|
+
type ErrorState = { ok?: false; error?: string };
|
|
224
|
+
let resultState: OkState | ErrorState;
|
|
225
|
+
|
|
226
|
+
// RFC 9207 §2.4 (MCP 2026-07-28): validate the response issuer before acting
|
|
227
|
+
// on any other parameter; on mismatch, server-supplied error details must not
|
|
228
|
+
// be acted on or displayed, so the failure message is generic by design.
|
|
229
|
+
let issuerFailure: string | null = null;
|
|
230
|
+
if (this.expectedIssuer) {
|
|
231
|
+
if (iss !== null && iss !== this.expectedIssuer) {
|
|
232
|
+
issuerFailure = "Authorization response issuer mismatch";
|
|
233
|
+
} else if (iss === null && this.issuerResponseIssSupported === true) {
|
|
234
|
+
issuerFailure = "Authorization response missing required issuer (iss)";
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (issuerFailure) {
|
|
239
|
+
resultState = { ok: false, error: issuerFailure };
|
|
240
|
+
} else if (error) {
|
|
241
|
+
resultState = { ok: false, error: `Authorization failed: ${errorDescription}` };
|
|
242
|
+
} else if (!code) {
|
|
243
|
+
resultState = { ok: false, error: "Missing authorization code" };
|
|
244
|
+
} else if (expectedState && state !== expectedState) {
|
|
245
|
+
resultState = { ok: false, error: "State mismatch - possible CSRF attack" };
|
|
246
|
+
} else {
|
|
247
|
+
resultState = { ok: true, code, state };
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Signal to waitForCallback - capture refs before they could be cleared
|
|
251
|
+
const resolve = this.#callbackResolve;
|
|
252
|
+
const reject = this.#callbackReject;
|
|
253
|
+
queueMicrotask(() => {
|
|
254
|
+
if (resultState.ok) {
|
|
255
|
+
resolve?.({ code: resultState.code, state: resultState.state });
|
|
256
|
+
} else {
|
|
257
|
+
reject?.(resultState.error ?? "Unknown error");
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
return new Response(
|
|
262
|
+
(templateHtml as unknown as string).replaceAll("__OAUTH_STATE__", JSON.stringify(resultState)),
|
|
263
|
+
{
|
|
264
|
+
status: resultState.ok ? 200 : 500,
|
|
265
|
+
headers: { "Content-Type": "text/html" },
|
|
266
|
+
},
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Wait for OAuth callback or manual input (whichever comes first).
|
|
272
|
+
*/
|
|
273
|
+
#waitForCallback(expectedState: string): Promise<CallbackResult> {
|
|
274
|
+
const timeoutSignal = AbortSignal.timeout(DEFAULT_TIMEOUT);
|
|
275
|
+
const signal = this.ctrl.signal ? AbortSignal.any([this.ctrl.signal, timeoutSignal]) : timeoutSignal;
|
|
276
|
+
|
|
277
|
+
const callbackPromise = new Promise<CallbackResult>((resolve, reject) => {
|
|
278
|
+
this.#callbackResolve = resolve;
|
|
279
|
+
this.#callbackReject = reject;
|
|
280
|
+
|
|
281
|
+
const cancel = () => {
|
|
282
|
+
this.#callbackResolve = undefined;
|
|
283
|
+
this.#callbackReject = undefined;
|
|
284
|
+
reject(new Error(`OAuth callback cancelled: ${signal.reason}`));
|
|
285
|
+
};
|
|
286
|
+
// A signal that aborted before the listener was attached never fires the
|
|
287
|
+
// event. Without a local listener to fall back on there would be nothing
|
|
288
|
+
// left to settle this promise, so check the current state too.
|
|
289
|
+
if (signal.aborted) {
|
|
290
|
+
cancel();
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
signal.addEventListener("abort", cancel);
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
const parseManualInput = (input: string): CallbackResult | null => {
|
|
297
|
+
const parsed = parseCallbackInput(input);
|
|
298
|
+
if (!parsed.code) return null;
|
|
299
|
+
if (expectedState && parsed.state && parsed.state !== expectedState) return null;
|
|
300
|
+
return { code: parsed.code, state: parsed.state ?? "" };
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
// Manual input race (if supported)
|
|
304
|
+
if (this.ctrl.onManualCodeInput) {
|
|
305
|
+
const requestManualInput = this.ctrl.onManualCodeInput;
|
|
306
|
+
const manualPromise = (async (): Promise<CallbackResult> => {
|
|
307
|
+
while (true) {
|
|
308
|
+
const attempt = requestManualInput().then(parseManualInput);
|
|
309
|
+
// The losing branch of the race can still reject long after the login
|
|
310
|
+
// settled (the pending prompt is cleared on teardown); keep that from
|
|
311
|
+
// surfacing as an unhandled rejection.
|
|
312
|
+
attempt.catch(() => undefined);
|
|
313
|
+
// A rejection that arrives first is a cancellation — the prompt was
|
|
314
|
+
// cleared or superseded — not a bad value. Re-prompting would spin
|
|
315
|
+
// forever, and with no local listener nothing else can settle this.
|
|
316
|
+
const result = await Promise.race([callbackPromise, attempt]);
|
|
317
|
+
if (result) return result;
|
|
318
|
+
// Yield to the macrotask queue so a handler that immediately resolves
|
|
319
|
+
// unusable values cannot starve the abort/timeout timer.
|
|
320
|
+
await Bun.sleep(0);
|
|
321
|
+
}
|
|
322
|
+
})();
|
|
323
|
+
|
|
324
|
+
return Promise.race([callbackPromise, manualPromise]);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
return callbackPromise;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Parse a redirect URL or code string to extract code and state.
|
|
333
|
+
*/
|
|
334
|
+
export function parseCallbackInput(input: string): { code?: string; state?: string } {
|
|
335
|
+
const value = input.trim();
|
|
336
|
+
if (!value) return {};
|
|
337
|
+
|
|
338
|
+
try {
|
|
339
|
+
const url = new URL(value);
|
|
340
|
+
return {
|
|
341
|
+
code: url.searchParams.get("code") ?? undefined,
|
|
342
|
+
state: url.searchParams.get("state") ?? undefined,
|
|
343
|
+
};
|
|
344
|
+
} catch {
|
|
345
|
+
// Not a URL - check for query string format
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
if (value.includes("code=")) {
|
|
349
|
+
const params = new URLSearchParams(value.replace(/^[?#]/, ""));
|
|
350
|
+
return {
|
|
351
|
+
code: params.get("code") ?? undefined,
|
|
352
|
+
state: params.get("state") ?? undefined,
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Assume raw code, possibly with state after #
|
|
357
|
+
const [code, state] = value.split("#", 2);
|
|
358
|
+
return { code, state };
|
|
359
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Cerebras login flow (API key paste against https://api.cerebras.ai/v1). */
|
|
2
|
+
import { createApiKeyLogin } from "./api-key-login";
|
|
3
|
+
|
|
4
|
+
export const loginCerebras = createApiKeyLogin({
|
|
5
|
+
providerLabel: "Cerebras",
|
|
6
|
+
authUrl: "https://cloud.cerebras.ai/platform/",
|
|
7
|
+
instructions: "Copy your API key from the Cerebras dashboard",
|
|
8
|
+
promptMessage: "Paste your Cerebras API key",
|
|
9
|
+
placeholder: "csk-...",
|
|
10
|
+
validation: {
|
|
11
|
+
kind: "chat-completions",
|
|
12
|
+
provider: "Cerebras",
|
|
13
|
+
baseUrl: "https://api.cerebras.ai/v1",
|
|
14
|
+
model: "gpt-oss-120b",
|
|
15
|
+
},
|
|
16
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloudflare AI Gateway login flow.
|
|
3
|
+
*
|
|
4
|
+
* Cloudflare AI Gateway proxies upstream model providers.
|
|
5
|
+
*
|
|
6
|
+
* This is not OAuth - it's a simple API key flow:
|
|
7
|
+
* 1. Open Cloudflare AI Gateway docs/dashboard
|
|
8
|
+
* 2. User copies their Cloudflare AI Gateway token/API key
|
|
9
|
+
* 3. User pastes the API key into the CLI
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { OAuthController } from "./types";
|
|
13
|
+
|
|
14
|
+
const AUTH_URL = "https://developers.cloudflare.com/ai-gateway/configuration/authentication/";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Login to Cloudflare AI Gateway.
|
|
18
|
+
*
|
|
19
|
+
* Opens browser to Cloudflare AI Gateway authentication docs and prompts for a gateway token/API key.
|
|
20
|
+
* Returns the API key directly (not OAuthCredentials - this isn't OAuth).
|
|
21
|
+
*/
|
|
22
|
+
export async function loginCloudflareAiGateway(options: OAuthController): Promise<string> {
|
|
23
|
+
if (!options.onPrompt) {
|
|
24
|
+
throw new Error("Cloudflare AI Gateway login requires onPrompt callback");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
options.onAuth?.({
|
|
28
|
+
url: AUTH_URL,
|
|
29
|
+
instructions:
|
|
30
|
+
"Copy your Cloudflare AI Gateway token/API key. Configure account/gateway base URL in models config.",
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const apiKey = await options.onPrompt({
|
|
34
|
+
message: "Paste your Cloudflare AI Gateway token/API key",
|
|
35
|
+
placeholder: "cf-aig-...",
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
if (options.signal?.aborted) {
|
|
39
|
+
throw new Error("Login cancelled");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const trimmed = apiKey.trim();
|
|
43
|
+
if (!trimmed) {
|
|
44
|
+
throw new Error("API key is required");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return trimmed;
|
|
48
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createApiKeyLogin } from "./api-key-login";
|
|
2
|
+
|
|
3
|
+
export const loginCommandCode = createApiKeyLogin({
|
|
4
|
+
providerLabel: "Command Code GOAT",
|
|
5
|
+
authUrl: "https://commandcode.ai/studio/#api-keys",
|
|
6
|
+
instructions: "Create or copy your Command Code API key",
|
|
7
|
+
promptMessage: "Paste your Command Code API key",
|
|
8
|
+
placeholder: "cmd-...",
|
|
9
|
+
validationProgressMessage: "Verifying Command Code inference entitlement...",
|
|
10
|
+
validation: {
|
|
11
|
+
kind: "chat-completions",
|
|
12
|
+
provider: "Command Code GOAT",
|
|
13
|
+
baseUrl: "https://api.commandcode.ai/provider/v1",
|
|
14
|
+
model: "zai-org/GLM-5.3",
|
|
15
|
+
requireInferenceResponse: true,
|
|
16
|
+
},
|
|
17
|
+
});
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { generatePKCE } from "./pkce";
|
|
2
|
+
import type { OAuthCredentials } from "./types";
|
|
3
|
+
|
|
4
|
+
const CURSOR_LOGIN_URL = "https://cursor.com/loginDeepControl";
|
|
5
|
+
const CURSOR_POLL_URL = "https://api2.cursor.sh/auth/poll";
|
|
6
|
+
const CURSOR_REFRESH_URL = "https://api2.cursor.sh/auth/exchange_user_api_key";
|
|
7
|
+
|
|
8
|
+
const POLL_MAX_ATTEMPTS = 150;
|
|
9
|
+
const POLL_BASE_DELAY = 1000;
|
|
10
|
+
const POLL_MAX_DELAY = 10000;
|
|
11
|
+
const POLL_BACKOFF_MULTIPLIER = 1.2;
|
|
12
|
+
|
|
13
|
+
export interface CursorAuthParams {
|
|
14
|
+
verifier: string;
|
|
15
|
+
challenge: string;
|
|
16
|
+
uuid: string;
|
|
17
|
+
loginUrl: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function generateCursorAuthParams(): Promise<CursorAuthParams> {
|
|
21
|
+
const { verifier, challenge } = await generatePKCE();
|
|
22
|
+
const uuid = crypto.randomUUID();
|
|
23
|
+
|
|
24
|
+
const params = new URLSearchParams({
|
|
25
|
+
challenge,
|
|
26
|
+
uuid,
|
|
27
|
+
mode: "login",
|
|
28
|
+
redirectTarget: "cli",
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const loginUrl = `${CURSOR_LOGIN_URL}?${params.toString()}`;
|
|
32
|
+
|
|
33
|
+
return { verifier, challenge, uuid, loginUrl };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function pollCursorAuth(
|
|
37
|
+
uuid: string,
|
|
38
|
+
verifier: string,
|
|
39
|
+
): Promise<{ accessToken: string; refreshToken: string }> {
|
|
40
|
+
let delay = POLL_BASE_DELAY;
|
|
41
|
+
let consecutiveErrors = 0;
|
|
42
|
+
|
|
43
|
+
for (let attempt = 0; attempt < POLL_MAX_ATTEMPTS; attempt++) {
|
|
44
|
+
await Bun.sleep(delay);
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
const response = await fetch(`${CURSOR_POLL_URL}?uuid=${uuid}&verifier=${verifier}`);
|
|
48
|
+
|
|
49
|
+
if (response.status === 404) {
|
|
50
|
+
consecutiveErrors = 0;
|
|
51
|
+
delay = Math.min(delay * POLL_BACKOFF_MULTIPLIER, POLL_MAX_DELAY);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (response.ok) {
|
|
56
|
+
const data = (await response.json()) as {
|
|
57
|
+
accessToken: string;
|
|
58
|
+
refreshToken: string;
|
|
59
|
+
};
|
|
60
|
+
return {
|
|
61
|
+
accessToken: data.accessToken,
|
|
62
|
+
refreshToken: data.refreshToken,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
throw new Error(`Poll failed: ${response.status}`);
|
|
67
|
+
} catch {
|
|
68
|
+
consecutiveErrors++;
|
|
69
|
+
if (consecutiveErrors >= 3) {
|
|
70
|
+
throw new Error("Too many consecutive errors during Cursor auth polling");
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
throw new Error("Cursor authentication polling timeout");
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export async function loginCursor(
|
|
79
|
+
onAuthUrl: (url: string) => void,
|
|
80
|
+
onPollStart?: () => void,
|
|
81
|
+
): Promise<OAuthCredentials> {
|
|
82
|
+
const { verifier, uuid, loginUrl } = await generateCursorAuthParams();
|
|
83
|
+
|
|
84
|
+
onAuthUrl(loginUrl);
|
|
85
|
+
onPollStart?.();
|
|
86
|
+
|
|
87
|
+
const { accessToken, refreshToken } = await pollCursorAuth(uuid, verifier);
|
|
88
|
+
|
|
89
|
+
const expiresAt = getTokenExpiry(accessToken);
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
access: accessToken,
|
|
93
|
+
refresh: refreshToken,
|
|
94
|
+
expires: expiresAt,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export async function refreshCursorToken(apiKeyOrRefreshToken: string): Promise<OAuthCredentials> {
|
|
99
|
+
const response = await fetch(CURSOR_REFRESH_URL, {
|
|
100
|
+
method: "POST",
|
|
101
|
+
headers: {
|
|
102
|
+
Authorization: `Bearer ${apiKeyOrRefreshToken}`,
|
|
103
|
+
"Content-Type": "application/json",
|
|
104
|
+
},
|
|
105
|
+
body: "{}",
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
if (!response.ok) {
|
|
109
|
+
const error = await response.text();
|
|
110
|
+
throw new Error(`Cursor token refresh failed: ${error}`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const data = (await response.json()) as {
|
|
114
|
+
accessToken: string;
|
|
115
|
+
refreshToken: string;
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const expiresAt = getTokenExpiry(data.accessToken);
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
access: data.accessToken,
|
|
122
|
+
refresh: data.refreshToken || apiKeyOrRefreshToken,
|
|
123
|
+
expires: expiresAt,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function getTokenExpiry(token: string): number {
|
|
128
|
+
try {
|
|
129
|
+
const parts = token.split(".");
|
|
130
|
+
if (parts.length !== 3) {
|
|
131
|
+
return Date.now() + 3600 * 1000;
|
|
132
|
+
}
|
|
133
|
+
const payload = parts[1];
|
|
134
|
+
if (!payload) {
|
|
135
|
+
return Date.now() + 3600 * 1000;
|
|
136
|
+
}
|
|
137
|
+
const decoded = JSON.parse(atob(payload.replace(/-/g, "+").replace(/_/g, "/")));
|
|
138
|
+
if (decoded && typeof decoded === "object" && typeof decoded.exp === "number") {
|
|
139
|
+
return decoded.exp * 1000 - 5 * 60 * 1000;
|
|
140
|
+
}
|
|
141
|
+
} catch {
|
|
142
|
+
// Ignore parsing errors
|
|
143
|
+
}
|
|
144
|
+
return Date.now() + 3600 * 1000;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function isCursorTokenExpiringSoon(token: string, thresholdSeconds = 300): boolean {
|
|
148
|
+
try {
|
|
149
|
+
const [, payload] = token.split(".");
|
|
150
|
+
if (!payload) return true;
|
|
151
|
+
const decoded = JSON.parse(atob(payload.replace(/-/g, "+").replace(/_/g, "/")));
|
|
152
|
+
const currentTime = Math.floor(Date.now() / 1000);
|
|
153
|
+
return decoded.exp - currentTime < thresholdSeconds;
|
|
154
|
+
} catch {
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** DeepInfra login flow (API key paste against https://api.deepinfra.com/v1/openai). */
|
|
2
|
+
import { createApiKeyLogin } from "./api-key-login";
|
|
3
|
+
|
|
4
|
+
export const loginDeepInfra = createApiKeyLogin({
|
|
5
|
+
providerLabel: "DeepInfra",
|
|
6
|
+
authUrl: "https://deepinfra.com/dash/api_keys",
|
|
7
|
+
instructions: "Create or copy your DeepInfra API key from the DeepInfra dashboard",
|
|
8
|
+
promptMessage: "Paste your DeepInfra API key",
|
|
9
|
+
placeholder: "sk-...",
|
|
10
|
+
validation: {
|
|
11
|
+
kind: "models-endpoint",
|
|
12
|
+
provider: "DeepInfra",
|
|
13
|
+
modelsUrl: "https://api.deepinfra.com/v1/openai/models",
|
|
14
|
+
},
|
|
15
|
+
});
|