@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,110 @@
|
|
|
1
|
+
export type FallbackTriggerClass = "rate_limit" | "quota" | "auth" | "server" | "unknown" | "other";
|
|
2
|
+
/**
|
|
3
|
+
* Refinement of an `auth` trigger.
|
|
4
|
+
*
|
|
5
|
+
* The transport deliberately collapses HTTP 401 and 403 into a single `auth`
|
|
6
|
+
* class, but the two demand opposite handling: a credential problem may be
|
|
7
|
+
* recoverable by trying a different stored credential, whereas a plain
|
|
8
|
+
* `forbidden` is an authorization or configuration defect that rotation would
|
|
9
|
+
* only hide — it would cycle and block every otherwise-healthy credential.
|
|
10
|
+
*
|
|
11
|
+
* This is a refinement rather than a new {@link FallbackTriggerClass} member so
|
|
12
|
+
* every existing `trigger.class === "auth"` consumer keeps compiling and keeps
|
|
13
|
+
* its current behavior until it explicitly opts into the distinction.
|
|
14
|
+
*/
|
|
15
|
+
export type AuthDisposition = "credential" | "forbidden";
|
|
16
|
+
export interface FallbackTrigger {
|
|
17
|
+
class: FallbackTriggerClass;
|
|
18
|
+
retryAfterMs?: number;
|
|
19
|
+
/** Present only when `class === "auth"`. */
|
|
20
|
+
authDisposition?: AuthDisposition;
|
|
21
|
+
}
|
|
22
|
+
/** Stable code for streams that time out before producing semantic progress. */
|
|
23
|
+
export declare const STREAM_FIRST_EVENT_TIMEOUT_PROVIDER_CODE = "stream_first_event_timeout";
|
|
24
|
+
/** Stable code for a nominally successful response with no content or token usage. */
|
|
25
|
+
export declare const EMPTY_RESPONSE_PROVIDER_CODE = "empty_response";
|
|
26
|
+
/**
|
|
27
|
+
* OpenAI's typed capacity-overload code. It arrives without an HTTP status —
|
|
28
|
+
* inside an HTTP 200 terminal Responses envelope or a Codex error event — so the
|
|
29
|
+
* code itself is the only structured evidence of the failure and must survive
|
|
30
|
+
* the existence gate below. It is always compared case-sensitively.
|
|
31
|
+
*/
|
|
32
|
+
export declare const SERVER_OVERLOADED_PROVIDER_CODE = "server_is_overloaded";
|
|
33
|
+
export type TransportHeaders = Headers | Record<string, string | undefined>;
|
|
34
|
+
/**
|
|
35
|
+
* Structured facts from an upstream HTTP or transport failure. Retry decisions
|
|
36
|
+
* must use these facts rather than provider- or application-owned error text.
|
|
37
|
+
*
|
|
38
|
+
* `headers` is always a plain record limited to the retained retry-signal
|
|
39
|
+
* entries: facts travel on persisted `AssistantMessage`s and through
|
|
40
|
+
* `structuredClone` snapshots (managed fallback attempt staging), so they must
|
|
41
|
+
* never carry a live `Headers` instance — cloning one throws `DataCloneError`
|
|
42
|
+
* ("The object can not be cloned.") and masks the real provider failure.
|
|
43
|
+
*/
|
|
44
|
+
export interface TransportFailureFacts {
|
|
45
|
+
kind: "transport";
|
|
46
|
+
status?: number;
|
|
47
|
+
/** Canonical provider error code used for fallback classification. */
|
|
48
|
+
providerCode?: string;
|
|
49
|
+
/** Anthropic's typed `error.type`, preserved separately at the transport boundary. */
|
|
50
|
+
anthropicErrorType?: string;
|
|
51
|
+
/** OpenAI's typed `error.code`, preserved separately at the transport boundary. */
|
|
52
|
+
openaiErrorCode?: string;
|
|
53
|
+
headers?: Record<string, string>;
|
|
54
|
+
/** Safe request-size observation for retry amplification policy. Never contains body content. */
|
|
55
|
+
requestBytes?: number;
|
|
56
|
+
/** Time spent waiting for the first semantic stream event on the failed request. */
|
|
57
|
+
firstEventElapsedMs?: number;
|
|
58
|
+
/** Configured first-event window before any bounded endpoint grace. */
|
|
59
|
+
firstEventTimeoutMs?: number;
|
|
60
|
+
/** Coarse endpoint class; deliberately excludes host, path, credentials, and query parameters. */
|
|
61
|
+
endpointClass?: "canonical" | "custom";
|
|
62
|
+
/** Provider-supplied ceiling for total attempts, including the initial request. */
|
|
63
|
+
retryMaxAttempts?: number;
|
|
64
|
+
}
|
|
65
|
+
/** Opaque per-invocation marker required by managed fallback transport calls. */
|
|
66
|
+
export interface FallbackAttemptToken {
|
|
67
|
+
readonly modelKey: string;
|
|
68
|
+
readonly attemptId: string | number;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Marks a single outer fallback invocation. Accounting belongs to the caller;
|
|
72
|
+
* this token prevents managed transport calls from silently bypassing it.
|
|
73
|
+
*/
|
|
74
|
+
export declare function beginAttempt(modelKey: string, attemptId: string | number): FallbackAttemptToken;
|
|
75
|
+
export declare function assertManagedAttempt(options: {
|
|
76
|
+
fallbackManaged?: boolean;
|
|
77
|
+
fallbackAttempt?: FallbackAttemptToken;
|
|
78
|
+
} | undefined): void;
|
|
79
|
+
/**
|
|
80
|
+
* Compatibility input for callers that have not yet wrapped their HTTP facts
|
|
81
|
+
* in the discriminated form. Only its structured fields are inspected.
|
|
82
|
+
*/
|
|
83
|
+
export interface FallbackTriggerInput {
|
|
84
|
+
status?: number;
|
|
85
|
+
providerCode?: string;
|
|
86
|
+
code?: string;
|
|
87
|
+
headers?: TransportHeaders;
|
|
88
|
+
response?: {
|
|
89
|
+
status?: number;
|
|
90
|
+
headers?: TransportHeaders;
|
|
91
|
+
};
|
|
92
|
+
error?: {
|
|
93
|
+
code?: string;
|
|
94
|
+
type?: string;
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/** Extracts only explicit HTTP/transport metadata; it never parses error text. */
|
|
98
|
+
export declare function transportFailureFacts(error: unknown, capturedResponse?: {
|
|
99
|
+
status?: number;
|
|
100
|
+
headers?: TransportHeaders;
|
|
101
|
+
}): TransportFailureFacts | undefined;
|
|
102
|
+
/** Classifies only typed upstream transport facts without consuming response bodies. */
|
|
103
|
+
export declare function classifyFallbackTrigger(errorOrFacts: TransportFailureFacts | FallbackTriggerInput | unknown): FallbackTrigger;
|
|
104
|
+
/**
|
|
105
|
+
* True when a failure is an `auth` failure that must NOT rotate credentials.
|
|
106
|
+
*
|
|
107
|
+
* Callers that mutate credential state on auth failures should consult this
|
|
108
|
+
* first so a plain `forbidden` cannot block otherwise-healthy credentials.
|
|
109
|
+
*/
|
|
110
|
+
export declare function isForbiddenAuthFailure(errorOrFacts: TransportFailureFacts | FallbackTriggerInput | unknown): boolean;
|
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
export type FallbackTriggerClass = "rate_limit" | "quota" | "auth" | "server" | "unknown" | "other";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Refinement of an `auth` trigger.
|
|
5
|
+
*
|
|
6
|
+
* The transport deliberately collapses HTTP 401 and 403 into a single `auth`
|
|
7
|
+
* class, but the two demand opposite handling: a credential problem may be
|
|
8
|
+
* recoverable by trying a different stored credential, whereas a plain
|
|
9
|
+
* `forbidden` is an authorization or configuration defect that rotation would
|
|
10
|
+
* only hide — it would cycle and block every otherwise-healthy credential.
|
|
11
|
+
*
|
|
12
|
+
* This is a refinement rather than a new {@link FallbackTriggerClass} member so
|
|
13
|
+
* every existing `trigger.class === "auth"` consumer keeps compiling and keeps
|
|
14
|
+
* its current behavior until it explicitly opts into the distinction.
|
|
15
|
+
*/
|
|
16
|
+
export type AuthDisposition = "credential" | "forbidden";
|
|
17
|
+
|
|
18
|
+
export interface FallbackTrigger {
|
|
19
|
+
class: FallbackTriggerClass;
|
|
20
|
+
retryAfterMs?: number;
|
|
21
|
+
/** Present only when `class === "auth"`. */
|
|
22
|
+
authDisposition?: AuthDisposition;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Stable code for streams that time out before producing semantic progress. */
|
|
26
|
+
export const STREAM_FIRST_EVENT_TIMEOUT_PROVIDER_CODE = "stream_first_event_timeout";
|
|
27
|
+
/** Stable code for a nominally successful response with no content or token usage. */
|
|
28
|
+
export const EMPTY_RESPONSE_PROVIDER_CODE = "empty_response";
|
|
29
|
+
/**
|
|
30
|
+
* OpenAI's typed capacity-overload code. It arrives without an HTTP status —
|
|
31
|
+
* inside an HTTP 200 terminal Responses envelope or a Codex error event — so the
|
|
32
|
+
* code itself is the only structured evidence of the failure and must survive
|
|
33
|
+
* the existence gate below. It is always compared case-sensitively.
|
|
34
|
+
*/
|
|
35
|
+
export const SERVER_OVERLOADED_PROVIDER_CODE = "server_is_overloaded";
|
|
36
|
+
|
|
37
|
+
export type TransportHeaders = Headers | Record<string, string | undefined>;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Structured facts from an upstream HTTP or transport failure. Retry decisions
|
|
41
|
+
* must use these facts rather than provider- or application-owned error text.
|
|
42
|
+
*
|
|
43
|
+
* `headers` is always a plain record limited to the retained retry-signal
|
|
44
|
+
* entries: facts travel on persisted `AssistantMessage`s and through
|
|
45
|
+
* `structuredClone` snapshots (managed fallback attempt staging), so they must
|
|
46
|
+
* never carry a live `Headers` instance — cloning one throws `DataCloneError`
|
|
47
|
+
* ("The object can not be cloned.") and masks the real provider failure.
|
|
48
|
+
*/
|
|
49
|
+
export interface TransportFailureFacts {
|
|
50
|
+
kind: "transport";
|
|
51
|
+
status?: number;
|
|
52
|
+
/** Canonical provider error code used for fallback classification. */
|
|
53
|
+
providerCode?: string;
|
|
54
|
+
/** Anthropic's typed `error.type`, preserved separately at the transport boundary. */
|
|
55
|
+
anthropicErrorType?: string;
|
|
56
|
+
/** OpenAI's typed `error.code`, preserved separately at the transport boundary. */
|
|
57
|
+
openaiErrorCode?: string;
|
|
58
|
+
headers?: Record<string, string>;
|
|
59
|
+
/** Safe request-size observation for retry amplification policy. Never contains body content. */
|
|
60
|
+
requestBytes?: number;
|
|
61
|
+
/** Time spent waiting for the first semantic stream event on the failed request. */
|
|
62
|
+
firstEventElapsedMs?: number;
|
|
63
|
+
/** Configured first-event window before any bounded endpoint grace. */
|
|
64
|
+
firstEventTimeoutMs?: number;
|
|
65
|
+
/** Coarse endpoint class; deliberately excludes host, path, credentials, and query parameters. */
|
|
66
|
+
endpointClass?: "canonical" | "custom";
|
|
67
|
+
/** Provider-supplied ceiling for total attempts, including the initial request. */
|
|
68
|
+
retryMaxAttempts?: number;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Opaque per-invocation marker required by managed fallback transport calls. */
|
|
72
|
+
export interface FallbackAttemptToken {
|
|
73
|
+
readonly modelKey: string;
|
|
74
|
+
readonly attemptId: string | number;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const issuedAttemptTokens = new WeakSet<object>();
|
|
78
|
+
const consumedAttemptTokens = new WeakSet<object>();
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Marks a single outer fallback invocation. Accounting belongs to the caller;
|
|
82
|
+
* this token prevents managed transport calls from silently bypassing it.
|
|
83
|
+
*/
|
|
84
|
+
export function beginAttempt(modelKey: string, attemptId: string | number): FallbackAttemptToken {
|
|
85
|
+
const token = Object.freeze({ modelKey, attemptId });
|
|
86
|
+
issuedAttemptTokens.add(token);
|
|
87
|
+
return token;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function assertManagedAttempt(
|
|
91
|
+
options: { fallbackManaged?: boolean; fallbackAttempt?: FallbackAttemptToken } | undefined,
|
|
92
|
+
): void {
|
|
93
|
+
if (!options?.fallbackManaged) return;
|
|
94
|
+
const token = options.fallbackAttempt;
|
|
95
|
+
if (!token || !issuedAttemptTokens.has(token)) {
|
|
96
|
+
throw new Error("fallbackManaged transport invocation requires a token returned by beginAttempt()");
|
|
97
|
+
}
|
|
98
|
+
if (consumedAttemptTokens.has(token)) {
|
|
99
|
+
throw new Error("fallbackManaged transport invocation cannot reuse a beginAttempt() token");
|
|
100
|
+
}
|
|
101
|
+
consumedAttemptTokens.add(token);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Compatibility input for callers that have not yet wrapped their HTTP facts
|
|
106
|
+
* in the discriminated form. Only its structured fields are inspected.
|
|
107
|
+
*/
|
|
108
|
+
export interface FallbackTriggerInput {
|
|
109
|
+
status?: number;
|
|
110
|
+
providerCode?: string;
|
|
111
|
+
code?: string;
|
|
112
|
+
headers?: TransportHeaders;
|
|
113
|
+
response?: { status?: number; headers?: TransportHeaders };
|
|
114
|
+
error?: { code?: string; type?: string };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function isTransportHeaders(value: unknown): value is TransportHeaders {
|
|
118
|
+
try {
|
|
119
|
+
return value instanceof Headers || (!!value && typeof value === "object");
|
|
120
|
+
} catch {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function propertyOf(value: unknown, name: string): unknown {
|
|
126
|
+
if (!value || typeof value !== "object") return undefined;
|
|
127
|
+
try {
|
|
128
|
+
return Reflect.get(value, name);
|
|
129
|
+
} catch {
|
|
130
|
+
return undefined;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function finiteStatus(value: unknown): number | undefined {
|
|
135
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function finiteNonNegativeInteger(value: unknown): number | undefined {
|
|
139
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 0 ? value : undefined;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function finitePositiveInteger(value: unknown): number | undefined {
|
|
143
|
+
return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : undefined;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function stringValue(value: unknown): string | undefined {
|
|
147
|
+
return typeof value === "string" ? value : undefined;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** Retry-signal headers retained on transport facts; everything else is dropped. */
|
|
151
|
+
const RETAINED_TRANSPORT_HEADERS = ["retry-after", "retry-after-ms"] as const;
|
|
152
|
+
|
|
153
|
+
const RETAINED_TRANSPORT_HEADER_SET: ReadonlySet<string> = new Set(RETAINED_TRANSPORT_HEADERS);
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Reduce transport headers to the retained retry-signal entries in a plain
|
|
157
|
+
* record, so facts stay structured-cloneable and JSON-serializable and never
|
|
158
|
+
* persist arbitrary response headers into session files.
|
|
159
|
+
*
|
|
160
|
+
* Exception-safe by contract: inspection uses only `Headers.get()` results
|
|
161
|
+
* that are primitive strings or own data-descriptor record entries. Any
|
|
162
|
+
* failure omits headers instead of throwing — status/providerCode facts
|
|
163
|
+
* extracted by the caller must survive a hostile headers object.
|
|
164
|
+
*/
|
|
165
|
+
function retainedHeaderRecord(headers: TransportHeaders | undefined): Record<string, string> | undefined {
|
|
166
|
+
if (headers === undefined) return undefined;
|
|
167
|
+
let record: Record<string, string> | undefined;
|
|
168
|
+
try {
|
|
169
|
+
if (headers instanceof Headers) {
|
|
170
|
+
for (const name of RETAINED_TRANSPORT_HEADERS) {
|
|
171
|
+
const value = headers.get(name);
|
|
172
|
+
if (typeof value !== "string") continue;
|
|
173
|
+
record ??= {};
|
|
174
|
+
record[name] = value;
|
|
175
|
+
}
|
|
176
|
+
return record;
|
|
177
|
+
}
|
|
178
|
+
for (const key of Object.keys(headers)) {
|
|
179
|
+
const descriptor = Object.getOwnPropertyDescriptor(headers, key);
|
|
180
|
+
if (!descriptor || !("value" in descriptor) || typeof descriptor.value !== "string") continue;
|
|
181
|
+
const name = key.toLowerCase();
|
|
182
|
+
if (!RETAINED_TRANSPORT_HEADER_SET.has(name)) continue;
|
|
183
|
+
record ??= {};
|
|
184
|
+
record[name] = descriptor.value;
|
|
185
|
+
}
|
|
186
|
+
return record;
|
|
187
|
+
} catch {
|
|
188
|
+
return undefined;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** Extracts only explicit HTTP/transport metadata; it never parses error text. */
|
|
193
|
+
export function transportFailureFacts(
|
|
194
|
+
error: unknown,
|
|
195
|
+
capturedResponse?: { status?: number; headers?: TransportHeaders },
|
|
196
|
+
): TransportFailureFacts | undefined {
|
|
197
|
+
if (!error || typeof error !== "object") return undefined;
|
|
198
|
+
const value = error as FallbackTriggerInput & { kind?: unknown; type?: unknown };
|
|
199
|
+
const response = propertyOf(value, "response");
|
|
200
|
+
const nestedError = propertyOf(value, "error");
|
|
201
|
+
const status =
|
|
202
|
+
finiteStatus(propertyOf(value, "status")) ??
|
|
203
|
+
finiteStatus(propertyOf(response, "status")) ??
|
|
204
|
+
finiteStatus(propertyOf(capturedResponse, "status"));
|
|
205
|
+
// `anthropicErrorType` is also read from its own key so re-normalizing an
|
|
206
|
+
// already-built facts object (which consumers do deliberately) preserves it
|
|
207
|
+
// instead of silently dropping the Anthropic code on the second pass.
|
|
208
|
+
const anthropicErrorType =
|
|
209
|
+
stringValue(propertyOf(nestedError, "type")) ??
|
|
210
|
+
stringValue(propertyOf(value, "anthropicErrorType")) ??
|
|
211
|
+
stringValue(propertyOf(value, "type"));
|
|
212
|
+
const openaiErrorCode =
|
|
213
|
+
stringValue(propertyOf(value, "openaiErrorCode")) ?? stringValue(propertyOf(nestedError, "code"));
|
|
214
|
+
const providerCode =
|
|
215
|
+
stringValue(propertyOf(value, "providerCode")) ??
|
|
216
|
+
openaiErrorCode ??
|
|
217
|
+
stringValue(propertyOf(value, "code")) ??
|
|
218
|
+
anthropicErrorType;
|
|
219
|
+
const errorHeaders = propertyOf(value, "headers");
|
|
220
|
+
const responseHeaders = propertyOf(response, "headers");
|
|
221
|
+
const capturedHeaders = propertyOf(capturedResponse, "headers");
|
|
222
|
+
const rawHeaders = isTransportHeaders(errorHeaders)
|
|
223
|
+
? errorHeaders
|
|
224
|
+
: isTransportHeaders(responseHeaders)
|
|
225
|
+
? responseHeaders
|
|
226
|
+
: isTransportHeaders(capturedHeaders)
|
|
227
|
+
? capturedHeaders
|
|
228
|
+
: undefined;
|
|
229
|
+
// Normalize BEFORE the existence gate so normalization is idempotent:
|
|
230
|
+
// facts built from an error whose headers carry no retained retry signal
|
|
231
|
+
// must not exist on the first pass and then vanish when re-normalized
|
|
232
|
+
// (consumers deliberately re-run transportFailureFacts on embedded facts).
|
|
233
|
+
const headers = retainedHeaderRecord(rawHeaders);
|
|
234
|
+
const normalizedCode = providerCode?.toLowerCase();
|
|
235
|
+
const requestBytes = finiteNonNegativeInteger(propertyOf(value, "requestBytes"));
|
|
236
|
+
const firstEventElapsedMs = finiteNonNegativeInteger(propertyOf(value, "firstEventElapsedMs"));
|
|
237
|
+
const firstEventTimeoutMs = finiteNonNegativeInteger(propertyOf(value, "firstEventTimeoutMs"));
|
|
238
|
+
const retryMaxAttempts = finitePositiveInteger(propertyOf(value, "retryMaxAttempts"));
|
|
239
|
+
const endpointClassValue = propertyOf(value, "endpointClass");
|
|
240
|
+
const endpointClass =
|
|
241
|
+
endpointClassValue === "canonical" || endpointClassValue === "custom" ? endpointClassValue : undefined;
|
|
242
|
+
if (
|
|
243
|
+
status === undefined &&
|
|
244
|
+
headers === undefined &&
|
|
245
|
+
!isQuotaCode(normalizedCode) &&
|
|
246
|
+
!isAuthCode(normalizedCode) &&
|
|
247
|
+
!isRateLimitCode(normalizedCode) &&
|
|
248
|
+
!isContextOverflowCode(normalizedCode) &&
|
|
249
|
+
normalizedCode !== STREAM_FIRST_EVENT_TIMEOUT_PROVIDER_CODE &&
|
|
250
|
+
normalizedCode !== EMPTY_RESPONSE_PROVIDER_CODE &&
|
|
251
|
+
// Matched case-sensitively against the raw code: this is the one gate a
|
|
252
|
+
// provider-owned code can open on its own, so a cased or padded variant
|
|
253
|
+
// must not materialize facts that would disqualify an unrelated
|
|
254
|
+
// bare-default retry.
|
|
255
|
+
providerCode !== SERVER_OVERLOADED_PROVIDER_CODE &&
|
|
256
|
+
requestBytes === undefined &&
|
|
257
|
+
firstEventElapsedMs === undefined &&
|
|
258
|
+
firstEventTimeoutMs === undefined &&
|
|
259
|
+
endpointClass === undefined &&
|
|
260
|
+
retryMaxAttempts === undefined
|
|
261
|
+
) {
|
|
262
|
+
return undefined;
|
|
263
|
+
}
|
|
264
|
+
return {
|
|
265
|
+
kind: "transport",
|
|
266
|
+
status,
|
|
267
|
+
providerCode,
|
|
268
|
+
anthropicErrorType,
|
|
269
|
+
openaiErrorCode,
|
|
270
|
+
headers,
|
|
271
|
+
...(requestBytes === undefined ? {} : { requestBytes }),
|
|
272
|
+
...(firstEventElapsedMs === undefined ? {} : { firstEventElapsedMs }),
|
|
273
|
+
...(firstEventTimeoutMs === undefined ? {} : { firstEventTimeoutMs }),
|
|
274
|
+
...(endpointClass === undefined ? {} : { endpointClass }),
|
|
275
|
+
...(retryMaxAttempts === undefined ? {} : { retryMaxAttempts }),
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function headersOf(headers: TransportHeaders | undefined): Headers | undefined {
|
|
280
|
+
if (headers instanceof Headers) return headers;
|
|
281
|
+
return headers ? new Headers(headers as Record<string, string>) : undefined;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function parseRetryAfterSeconds(value: string | null, now = Date.now()): number | undefined {
|
|
285
|
+
if (!value) return undefined;
|
|
286
|
+
const seconds = Number(value);
|
|
287
|
+
if (Number.isFinite(seconds) && seconds >= 0) return Math.round(seconds * 1000);
|
|
288
|
+
const date = Date.parse(value);
|
|
289
|
+
return Number.isFinite(date) ? Math.max(0, date - now) : undefined;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function parseRetryAfterMilliseconds(value: string | null): number | undefined {
|
|
293
|
+
if (!value) return undefined;
|
|
294
|
+
const milliseconds = Number(value);
|
|
295
|
+
return Number.isFinite(milliseconds) && milliseconds >= 0 ? Math.round(milliseconds) : undefined;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function isContextOverflowCode(code: string | undefined): boolean {
|
|
299
|
+
return code === "context_length_exceeded";
|
|
300
|
+
}
|
|
301
|
+
function isQuotaCode(code: string | undefined): boolean {
|
|
302
|
+
return (
|
|
303
|
+
code === "insufficient_quota" ||
|
|
304
|
+
code === "quota_exceeded" ||
|
|
305
|
+
code === "quota_exhausted" ||
|
|
306
|
+
code === "usage_limit_reached" ||
|
|
307
|
+
code === "usage_not_included" ||
|
|
308
|
+
code === "out_of_credits"
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
const FORBIDDEN_AUTH_CODE = "forbidden";
|
|
313
|
+
|
|
314
|
+
/** Auth codes that name a credential problem rather than an authorization one. */
|
|
315
|
+
function isCredentialAuthCode(code: string | undefined): boolean {
|
|
316
|
+
return (
|
|
317
|
+
code === "authentication_error" ||
|
|
318
|
+
code === "invalid_api_key" ||
|
|
319
|
+
code === "invalid_token" ||
|
|
320
|
+
code === "token_expired" ||
|
|
321
|
+
code === "unauthorized"
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function isAuthCode(code: string | undefined): boolean {
|
|
326
|
+
return isCredentialAuthCode(code) || code === FORBIDDEN_AUTH_CODE;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Resolves the {@link AuthDisposition} for an `auth` trigger.
|
|
331
|
+
*
|
|
332
|
+
* Precedence is explicit and ordered by specificity rather than by field,
|
|
333
|
+
* because transport facts can carry a first-party typed code and a
|
|
334
|
+
* `providerCode` that disagree:
|
|
335
|
+
*
|
|
336
|
+
* 1. A code naming a concrete credential fault (`invalid_api_key`,
|
|
337
|
+
* `authentication_error`, …) wins, from whichever field it arrives in: it is
|
|
338
|
+
* a specific diagnosis, while `forbidden` is the generic bucket this
|
|
339
|
+
* refinement exists to distrust.
|
|
340
|
+
* 2. Otherwise a `forbidden` code in any field is terminal, so
|
|
341
|
+
* `{status: 401, providerCode: "forbidden"}` does not mutate credentials.
|
|
342
|
+
* 3. Otherwise the HTTP status decides, and an unknown-status `auth` defaults to
|
|
343
|
+
* `credential` because that is the classification the pre-refinement code
|
|
344
|
+
* already produced.
|
|
345
|
+
*
|
|
346
|
+
* Trigger-class selection deliberately keeps its single-code precedence
|
|
347
|
+
* (`openaiErrorCode ?? anthropicErrorType ?? providerCode`); only this auth
|
|
348
|
+
* refinement reads every code field.
|
|
349
|
+
*/
|
|
350
|
+
function resolveAuthDisposition(codes: readonly (string | undefined)[], status: number | undefined): AuthDisposition {
|
|
351
|
+
if (codes.some(code => isCredentialAuthCode(code))) return "credential";
|
|
352
|
+
if (codes.some(code => code === FORBIDDEN_AUTH_CODE)) return "forbidden";
|
|
353
|
+
return status === 403 ? "forbidden" : "credential";
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function isRateLimitCode(code: string | undefined): boolean {
|
|
357
|
+
return (
|
|
358
|
+
code === "rate_limit" ||
|
|
359
|
+
code === "rate_limit_error" ||
|
|
360
|
+
code === "rate_limit_exceeded" ||
|
|
361
|
+
code === "too_many_requests"
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/** Classifies only typed upstream transport facts without consuming response bodies. */
|
|
366
|
+
export function classifyFallbackTrigger(
|
|
367
|
+
errorOrFacts: TransportFailureFacts | FallbackTriggerInput | unknown,
|
|
368
|
+
): FallbackTrigger {
|
|
369
|
+
const facts = transportFailureFacts(errorOrFacts);
|
|
370
|
+
if (!facts) return { class: "other" };
|
|
371
|
+
const headers = headersOf(facts.headers);
|
|
372
|
+
const retryAfterMs =
|
|
373
|
+
parseRetryAfterMilliseconds(headers?.get("retry-after-ms") ?? null) ??
|
|
374
|
+
parseRetryAfterSeconds(headers?.get("retry-after") ?? null);
|
|
375
|
+
const rawCodes = [facts.openaiErrorCode, facts.anthropicErrorType, facts.providerCode];
|
|
376
|
+
const codes = rawCodes.map(value => value?.toLowerCase());
|
|
377
|
+
const code = codes[0] ?? codes[1] ?? codes[2];
|
|
378
|
+
// The capacity-overload code is provider-owned and is the only code that can
|
|
379
|
+
// classify without a status, so it is matched case-sensitively — the same
|
|
380
|
+
// exactness the parser and the session admission use.
|
|
381
|
+
const rawCode = rawCodes[0] ?? rawCodes[1] ?? rawCodes[2];
|
|
382
|
+
const triggerClass: FallbackTriggerClass =
|
|
383
|
+
code === STREAM_FIRST_EVENT_TIMEOUT_PROVIDER_CODE ||
|
|
384
|
+
code === EMPTY_RESPONSE_PROVIDER_CODE ||
|
|
385
|
+
(facts.status === undefined && rawCode === SERVER_OVERLOADED_PROVIDER_CODE)
|
|
386
|
+
? "server"
|
|
387
|
+
: isQuotaCode(code)
|
|
388
|
+
? "quota"
|
|
389
|
+
: facts.status === 401 || facts.status === 403 || isAuthCode(code)
|
|
390
|
+
? "auth"
|
|
391
|
+
: facts.status === 429 || isRateLimitCode(code)
|
|
392
|
+
? "rate_limit"
|
|
393
|
+
: facts.status !== undefined && facts.status >= 500 && facts.status <= 599
|
|
394
|
+
? "server"
|
|
395
|
+
: "other";
|
|
396
|
+
const trigger: FallbackTrigger = { class: triggerClass };
|
|
397
|
+
if (retryAfterMs !== undefined) trigger.retryAfterMs = retryAfterMs;
|
|
398
|
+
if (triggerClass === "auth") trigger.authDisposition = resolveAuthDisposition(codes, facts.status);
|
|
399
|
+
return trigger;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* True when a failure is an `auth` failure that must NOT rotate credentials.
|
|
404
|
+
*
|
|
405
|
+
* Callers that mutate credential state on auth failures should consult this
|
|
406
|
+
* first so a plain `forbidden` cannot block otherwise-healthy credentials.
|
|
407
|
+
*/
|
|
408
|
+
export function isForbiddenAuthFailure(errorOrFacts: TransportFailureFacts | FallbackTriggerInput | unknown): boolean {
|
|
409
|
+
const trigger = classifyFallbackTrigger(errorOrFacts);
|
|
410
|
+
return trigger.class === "auth" && trigger.authDisposition === "forbidden";
|
|
411
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare function toFireworksPublicModelId(modelId: string): string;
|
|
2
|
+
export declare function toFireworksWireModelId(modelId: string): string;
|
|
3
|
+
/**
|
|
4
|
+
* Fire Pass exposes its Kimi K2.6 Turbo subscription through a dedicated router
|
|
5
|
+
* endpoint at `accounts/fireworks/routers/<id>` rather than the `models/` namespace.
|
|
6
|
+
* We keep a friendly public id (e.g. `kimi-k2.6-turbo`) in the catalog and translate
|
|
7
|
+
* to the wire form (`accounts/fireworks/routers/kimi-k2p6-turbo`) at request time.
|
|
8
|
+
*/
|
|
9
|
+
export declare function toFirepassPublicModelId(modelId: string): string;
|
|
10
|
+
export declare function toFirepassWireModelId(modelId: string): string;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const FIREWORKS_WIRE_PREFIX = "accounts/fireworks/models/";
|
|
2
|
+
const FIREPASS_WIRE_PREFIX = "accounts/fireworks/routers/";
|
|
3
|
+
const VERSION_SEPARATOR_PATTERN = /(?<=\d)p(?=\d)/g;
|
|
4
|
+
const VERSION_DOT_PATTERN = /(?<=\d)\.(?=\d)/g;
|
|
5
|
+
|
|
6
|
+
export function toFireworksPublicModelId(modelId: string): string {
|
|
7
|
+
const stripped = modelId.startsWith(FIREWORKS_WIRE_PREFIX) ? modelId.slice(FIREWORKS_WIRE_PREFIX.length) : modelId;
|
|
8
|
+
return stripped.replace(VERSION_SEPARATOR_PATTERN, ".");
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function toFireworksWireModelId(modelId: string): string {
|
|
12
|
+
const stripped = modelId.startsWith(FIREWORKS_WIRE_PREFIX) ? modelId.slice(FIREWORKS_WIRE_PREFIX.length) : modelId;
|
|
13
|
+
return `${FIREWORKS_WIRE_PREFIX}${stripped.replace(VERSION_DOT_PATTERN, "p")}`;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Fire Pass exposes its Kimi K2.6 Turbo subscription through a dedicated router
|
|
18
|
+
* endpoint at `accounts/fireworks/routers/<id>` rather than the `models/` namespace.
|
|
19
|
+
* We keep a friendly public id (e.g. `kimi-k2.6-turbo`) in the catalog and translate
|
|
20
|
+
* to the wire form (`accounts/fireworks/routers/kimi-k2p6-turbo`) at request time.
|
|
21
|
+
*/
|
|
22
|
+
export function toFirepassPublicModelId(modelId: string): string {
|
|
23
|
+
const stripped = modelId.startsWith(FIREPASS_WIRE_PREFIX) ? modelId.slice(FIREPASS_WIRE_PREFIX.length) : modelId;
|
|
24
|
+
return stripped.replace(VERSION_SEPARATOR_PATTERN, ".");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function toFirepassWireModelId(modelId: string): string {
|
|
28
|
+
const stripped = modelId.startsWith(FIREPASS_WIRE_PREFIX) ? modelId.slice(FIREPASS_WIRE_PREFIX.length) : modelId;
|
|
29
|
+
return `${FIREPASS_WIRE_PREFIX}${stripped.replace(VERSION_DOT_PATTERN, "p")}`;
|
|
30
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether Anthropic requests run in Foundry gateway mode.
|
|
3
|
+
*
|
|
4
|
+
* Resolved from trusted environment sources only. Enabling Foundry switches the
|
|
5
|
+
* request base URL and injects TLS client material, so whatever can set this
|
|
6
|
+
* redirects authenticated traffic. `$env` merges the caller's `cwd/.env`, so
|
|
7
|
+
* reading it there would let repository content flip the mode; resolve it the
|
|
8
|
+
* same way the credentials themselves are (launching shell plus Vibrato/user-owned
|
|
9
|
+
* `.env` files, never the project `.env`).
|
|
10
|
+
*/
|
|
11
|
+
export declare function isFoundryEnabled(): boolean;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { $credentialEnv } from "@vib-rato/utils";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Whether Anthropic requests run in Foundry gateway mode.
|
|
5
|
+
*
|
|
6
|
+
* Resolved from trusted environment sources only. Enabling Foundry switches the
|
|
7
|
+
* request base URL and injects TLS client material, so whatever can set this
|
|
8
|
+
* redirects authenticated traffic. `$env` merges the caller's `cwd/.env`, so
|
|
9
|
+
* reading it there would let repository content flip the mode; resolve it the
|
|
10
|
+
* same way the credentials themselves are (launching shell plus Vibrato/user-owned
|
|
11
|
+
* `.env` files, never the project `.env`).
|
|
12
|
+
*/
|
|
13
|
+
export function isFoundryEnabled(): boolean {
|
|
14
|
+
const value = $credentialEnv("CLAUDE_CODE_USE_FOUNDRY");
|
|
15
|
+
if (!value) return false;
|
|
16
|
+
const normalized = value.trim().toLowerCase();
|
|
17
|
+
return normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on";
|
|
18
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Patch `globalThis.fetch` to advertise HTTP/2 in TLS ALPN, with transparent
|
|
3
|
+
* HTTP/1.1 fallback when the server doesn't negotiate `h2`.
|
|
4
|
+
*
|
|
5
|
+
* Bun's HTTP/2 client is gated on `BUN_FEATURE_FLAG_EXPERIMENTAL_HTTP2_CLIENT`,
|
|
6
|
+
* read by the native runtime before any JS executes; assigning to
|
|
7
|
+
* `process.env` from inside JS is a no-op. Per-request `protocol: "http2"`
|
|
8
|
+
* activates h2 over TLS ALPN and rejects with `error.code === "HTTP2Unsupported"`
|
|
9
|
+
* if the server picks anything else, so we catch and retry without the hint.
|
|
10
|
+
*
|
|
11
|
+
* Some HTTPS endpoints (e.g. corporate API gateways behind reverse proxies)
|
|
12
|
+
* advertise h2 via ALPN but then refuse or reset the connection at the HTTP/2
|
|
13
|
+
* framing layer. Bun surfaces these as `ConnectionRefused`, `ConnectionReset`,
|
|
14
|
+
* or `ConnectionClosed` rather than `HTTP2Unsupported`, so we treat those
|
|
15
|
+
* codes as h2-fallback triggers as well.
|
|
16
|
+
*
|
|
17
|
+
* Bun negotiates h2 via ALPN over TLS only (no h2c), so plain `http://` URLs
|
|
18
|
+
* skip the attempt entirely — avoids the throw/retry round-trip for localhost.
|
|
19
|
+
*
|
|
20
|
+
* Idempotent.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
const installed: unique symbol = Symbol.for("vib-rato.h2fetch.installed");
|
|
24
|
+
|
|
25
|
+
interface PatchedFetch {
|
|
26
|
+
[installed]?: true;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function installH2Fetch(): void {
|
|
30
|
+
const original = globalThis.fetch as typeof fetch & PatchedFetch;
|
|
31
|
+
if (original[installed]) return;
|
|
32
|
+
|
|
33
|
+
/** Error codes that indicate h2 negotiation/transport failure (not an application error). */
|
|
34
|
+
const h2FallbackCodes: ReadonlySet<string> = new Set([
|
|
35
|
+
"HTTP2Unsupported", // Server selected h1 in ALPN
|
|
36
|
+
"ConnectionRefused", // Server refused the h2 connection
|
|
37
|
+
"ConnectionReset", // Server reset during h2 handshake
|
|
38
|
+
"ConnectionClosed", // Server closed before h2 response
|
|
39
|
+
]);
|
|
40
|
+
const wrapper = async function h2fetch(input: string | URL | Request, init?: RequestInit): Promise<Response> {
|
|
41
|
+
if (!isHttps(input)) return original(input, init);
|
|
42
|
+
try {
|
|
43
|
+
return await original(input, { ...init, protocol: "http2" });
|
|
44
|
+
} catch (err) {
|
|
45
|
+
if (!h2FallbackCodes.has((err as { code?: string }).code ?? "")) throw err;
|
|
46
|
+
return original(input, init);
|
|
47
|
+
}
|
|
48
|
+
} as typeof fetch & PatchedFetch;
|
|
49
|
+
|
|
50
|
+
// Preserve `fetch.preconnect` and any other statics SDK code might poke at.
|
|
51
|
+
Object.assign(wrapper, original);
|
|
52
|
+
wrapper[installed] = true;
|
|
53
|
+
globalThis.fetch = wrapper;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function isHttps(input: string | URL | Request): boolean {
|
|
57
|
+
if (typeof input === "string") return input.startsWith("https:");
|
|
58
|
+
if (input instanceof URL) return input.protocol === "https:";
|
|
59
|
+
return input.url.startsWith("https:");
|
|
60
|
+
}
|