@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,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Xiaomi MiMo login flow.
|
|
3
|
+
*
|
|
4
|
+
* Xiaomi MiMo provides OpenAI-compatible models via
|
|
5
|
+
* https://api.xiaomimimo.com/v1.
|
|
6
|
+
*
|
|
7
|
+
* Standard Xiaomi login opens the pay-as-you-go API key console. Token Plan
|
|
8
|
+
* login opens plan management so users copy the regional `tp-...` key.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { FetchImpl } from "../../types";
|
|
12
|
+
import type { OAuthController } from "./types";
|
|
13
|
+
|
|
14
|
+
const PROVIDER_ID = "xiaomi";
|
|
15
|
+
const PROVIDER_NAME = "Xiaomi MiMo";
|
|
16
|
+
const STANDARD_AUTH_URL = "https://platform.xiaomimimo.com/#/console/api-keys";
|
|
17
|
+
const TOKEN_PLAN_AUTH_URL = "https://platform.xiaomimimo.com/console/plan-manage";
|
|
18
|
+
const STANDARD_API_BASE_URL = "https://api.xiaomimimo.com/v1";
|
|
19
|
+
const TOKEN_PLAN_KEY_PREFIX = "tp-";
|
|
20
|
+
const STANDARD_VALIDATION_MODEL = "mimo-v2-flash";
|
|
21
|
+
const TOKEN_PLAN_VALIDATION_MODEL = "mimo-v2.5";
|
|
22
|
+
const TOKEN_PLAN_SGP_API_BASE_URL = "https://token-plan-sgp.xiaomimimo.com/v1";
|
|
23
|
+
const TOKEN_PLAN_AMS_API_BASE_URL = "https://token-plan-ams.xiaomimimo.com/v1";
|
|
24
|
+
const TOKEN_PLAN_CN_API_BASE_URL = "https://token-plan-cn.xiaomimimo.com/v1";
|
|
25
|
+
|
|
26
|
+
/** Region codes accepted by the Xiaomi Token Plan login flow. */
|
|
27
|
+
export type XiaomiTokenPlanRegion = "sgp" | "ams" | "cn";
|
|
28
|
+
|
|
29
|
+
type XiaomiValidationEndpoint = {
|
|
30
|
+
baseUrl: string;
|
|
31
|
+
model: string;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const TOKEN_PLAN_VALIDATION_ENDPOINTS: Record<XiaomiTokenPlanRegion, XiaomiValidationEndpoint> = {
|
|
35
|
+
sgp: { baseUrl: TOKEN_PLAN_SGP_API_BASE_URL, model: TOKEN_PLAN_VALIDATION_MODEL },
|
|
36
|
+
ams: { baseUrl: TOKEN_PLAN_AMS_API_BASE_URL, model: TOKEN_PLAN_VALIDATION_MODEL },
|
|
37
|
+
cn: { baseUrl: TOKEN_PLAN_CN_API_BASE_URL, model: TOKEN_PLAN_VALIDATION_MODEL },
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const TOKEN_PLAN_REGION_NAMES: Record<XiaomiTokenPlanRegion, string> = {
|
|
41
|
+
sgp: "Singapore",
|
|
42
|
+
ams: "Europe",
|
|
43
|
+
cn: "China",
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
function isTokenPlanKey(apiKey: string): boolean {
|
|
47
|
+
return apiKey.startsWith(TOKEN_PLAN_KEY_PREFIX);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const VALIDATION_TIMEOUT_MS = 15_000;
|
|
51
|
+
|
|
52
|
+
async function validateXiaomiApiKey(
|
|
53
|
+
apiKey: string,
|
|
54
|
+
tokenPlanRegion: XiaomiTokenPlanRegion | undefined,
|
|
55
|
+
signal?: AbortSignal,
|
|
56
|
+
fetchOverride?: FetchImpl,
|
|
57
|
+
): Promise<void> {
|
|
58
|
+
const fetchImpl = fetchOverride ?? fetch;
|
|
59
|
+
// Region-specific Token Plan logins must validate against the selected
|
|
60
|
+
// cluster. Generic Xiaomi login keeps the historical SGP → AMS → CN fallback.
|
|
61
|
+
const endpoints = tokenPlanRegion
|
|
62
|
+
? [TOKEN_PLAN_VALIDATION_ENDPOINTS[tokenPlanRegion]]
|
|
63
|
+
: isTokenPlanKey(apiKey)
|
|
64
|
+
? [
|
|
65
|
+
TOKEN_PLAN_VALIDATION_ENDPOINTS.sgp,
|
|
66
|
+
TOKEN_PLAN_VALIDATION_ENDPOINTS.ams,
|
|
67
|
+
TOKEN_PLAN_VALIDATION_ENDPOINTS.cn,
|
|
68
|
+
]
|
|
69
|
+
: [{ baseUrl: STANDARD_API_BASE_URL, model: STANDARD_VALIDATION_MODEL }];
|
|
70
|
+
|
|
71
|
+
let lastError: Error | null = null;
|
|
72
|
+
|
|
73
|
+
for (const ep of endpoints) {
|
|
74
|
+
// Fresh timeout per endpoint so SGP→AMS fallback works after a regional
|
|
75
|
+
// timeout: a shared AbortSignal.timeout would stay aborted and instantly
|
|
76
|
+
// abort the AMS fetch.
|
|
77
|
+
const timeoutSignal = AbortSignal.timeout(VALIDATION_TIMEOUT_MS);
|
|
78
|
+
const requestSignal = signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal;
|
|
79
|
+
try {
|
|
80
|
+
const response = await fetchImpl(`${ep.baseUrl}/chat/completions`, {
|
|
81
|
+
method: "POST",
|
|
82
|
+
headers: {
|
|
83
|
+
"Content-Type": "application/json",
|
|
84
|
+
Authorization: `Bearer ${apiKey}`,
|
|
85
|
+
},
|
|
86
|
+
body: JSON.stringify({
|
|
87
|
+
model: ep.model,
|
|
88
|
+
max_tokens: 1,
|
|
89
|
+
messages: [{ role: "user", content: "ping" }],
|
|
90
|
+
}),
|
|
91
|
+
signal: requestSignal,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
if (response.ok) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// 401 means this endpoint didn't accept the key; try the next one
|
|
99
|
+
if (response.status === 401) {
|
|
100
|
+
let details = "";
|
|
101
|
+
try {
|
|
102
|
+
details = (await response.text()).trim();
|
|
103
|
+
} catch {
|
|
104
|
+
// ignore body parse errors, status is enough
|
|
105
|
+
}
|
|
106
|
+
lastError = new Error(
|
|
107
|
+
details
|
|
108
|
+
? `${PROVIDER_NAME} API key validation failed (${response.status}): ${details}`
|
|
109
|
+
: `${PROVIDER_NAME} API key validation failed (${response.status})`,
|
|
110
|
+
);
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Non-auth errors are real failures
|
|
115
|
+
let details = "";
|
|
116
|
+
try {
|
|
117
|
+
details = (await response.text()).trim();
|
|
118
|
+
} catch {
|
|
119
|
+
// ignore body parse errors, status is enough
|
|
120
|
+
}
|
|
121
|
+
const message = details
|
|
122
|
+
? `${PROVIDER_NAME} API key validation failed (${response.status}): ${details}`
|
|
123
|
+
: `${PROVIDER_NAME} API key validation failed (${response.status})`;
|
|
124
|
+
throw new Error(message);
|
|
125
|
+
} catch (e) {
|
|
126
|
+
// Only re-throw AbortError when the caller explicitly cancelled.
|
|
127
|
+
// Timeout aborts (from AbortSignal.timeout) should fall through to
|
|
128
|
+
// the next endpoint so SGP→AMS fallback works during regional outages.
|
|
129
|
+
if (e instanceof DOMException && e.name === "AbortError" && signal?.aborted) {
|
|
130
|
+
throw e;
|
|
131
|
+
}
|
|
132
|
+
lastError = e instanceof Error ? e : new Error(String(e));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
throw lastError ?? new Error(`${PROVIDER_NAME} API key validation failed`);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Login to Xiaomi MiMo.
|
|
140
|
+
*
|
|
141
|
+
* Opens browser to API keys page, prompts user to paste their API key.
|
|
142
|
+
* Returns the API key directly (not OAuthCredentials - this isn't OAuth).
|
|
143
|
+
*/
|
|
144
|
+
export async function loginXiaomi(options: OAuthController): Promise<string> {
|
|
145
|
+
const fetchImpl = options.fetch ?? fetch;
|
|
146
|
+
if (!options.onPrompt) {
|
|
147
|
+
throw new Error(`${PROVIDER_NAME} login requires onPrompt callback`);
|
|
148
|
+
}
|
|
149
|
+
options.onAuth?.({
|
|
150
|
+
url: STANDARD_AUTH_URL,
|
|
151
|
+
instructions: "Copy your API key from the Xiaomi MiMo console",
|
|
152
|
+
});
|
|
153
|
+
const apiKey = await options.onPrompt({
|
|
154
|
+
message: "Paste your Xiaomi API key (sk-... or token-plan tp-...)",
|
|
155
|
+
placeholder: "sk-... or tp-...",
|
|
156
|
+
});
|
|
157
|
+
if (options.signal?.aborted) {
|
|
158
|
+
throw new Error("Login cancelled");
|
|
159
|
+
}
|
|
160
|
+
const trimmed = apiKey.trim();
|
|
161
|
+
if (!trimmed) {
|
|
162
|
+
throw new Error("API key is required");
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
options.onProgress?.(`Validating ${PROVIDER_ID} API key...`);
|
|
166
|
+
await validateXiaomiApiKey(trimmed, undefined, options.signal, fetchImpl);
|
|
167
|
+
return trimmed;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Login to a regional Xiaomi Token Plan endpoint.
|
|
172
|
+
*
|
|
173
|
+
* Prompts for a token-plan API key and validates it against the selected region.
|
|
174
|
+
*/
|
|
175
|
+
export async function loginXiaomiTokenPlan(options: OAuthController, region: XiaomiTokenPlanRegion): Promise<string> {
|
|
176
|
+
const fetchImpl = options.fetch ?? fetch;
|
|
177
|
+
if (!options.onPrompt) {
|
|
178
|
+
throw new Error(`Xiaomi Token Plan (${TOKEN_PLAN_REGION_NAMES[region]}) login requires onPrompt callback`);
|
|
179
|
+
}
|
|
180
|
+
options.onAuth?.({
|
|
181
|
+
url: TOKEN_PLAN_AUTH_URL,
|
|
182
|
+
instructions: `Copy your token-plan API key for the ${TOKEN_PLAN_REGION_NAMES[region]} region`,
|
|
183
|
+
});
|
|
184
|
+
const apiKey = await options.onPrompt({
|
|
185
|
+
message: `Paste your Xiaomi Token Plan ${TOKEN_PLAN_REGION_NAMES[region]} API key (tp-...)`,
|
|
186
|
+
placeholder: "tp-...",
|
|
187
|
+
});
|
|
188
|
+
if (options.signal?.aborted) {
|
|
189
|
+
throw new Error("Login cancelled");
|
|
190
|
+
}
|
|
191
|
+
const trimmed = apiKey.trim();
|
|
192
|
+
if (!trimmed) {
|
|
193
|
+
throw new Error("API key is required");
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
options.onProgress?.(`Validating Xiaomi Token Plan (${TOKEN_PLAN_REGION_NAMES[region]}) API key...`);
|
|
197
|
+
await validateXiaomiApiKey(trimmed, region, options.signal, fetchImpl);
|
|
198
|
+
return trimmed;
|
|
199
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Z.AI login flow.
|
|
3
|
+
*
|
|
4
|
+
* Z.AI is a platform that provides access to GLM models through an OpenAI-compatible API.
|
|
5
|
+
* API docs: https://docs.z.ai/guides/overview/quick-start
|
|
6
|
+
*
|
|
7
|
+
* This is not OAuth - it's a simple API key flow:
|
|
8
|
+
* 1. User gets their API key from https://z.ai/settings/api-keys
|
|
9
|
+
* 2. User pastes the API key into the CLI
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { validateOpenAICompatibleApiKey } from "./api-key-validation";
|
|
13
|
+
import type { OAuthController } from "./types";
|
|
14
|
+
|
|
15
|
+
const AUTH_URL = "https://z.ai/manage-apikey/apikey-list";
|
|
16
|
+
const API_BASE_URL = "https://api.z.ai/api/coding/paas/v4";
|
|
17
|
+
const VALIDATION_MODEL = "glm-4.7";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Login to Z.AI.
|
|
21
|
+
*
|
|
22
|
+
* Opens browser to API keys page, prompts user to paste their API key.
|
|
23
|
+
* Returns the API key directly (not OAuthCredentials - this isn't OAuth).
|
|
24
|
+
*/
|
|
25
|
+
export async function loginZai(options: OAuthController): Promise<string> {
|
|
26
|
+
if (!options.onPrompt) {
|
|
27
|
+
throw new Error("Z.AI login requires onPrompt callback");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Open browser to API keys page
|
|
31
|
+
options.onAuth?.({
|
|
32
|
+
url: AUTH_URL,
|
|
33
|
+
instructions: "Copy your API key from the dashboard",
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Prompt user to paste their API key
|
|
37
|
+
const apiKey = await options.onPrompt({
|
|
38
|
+
message: "Paste your Z.AI API key",
|
|
39
|
+
placeholder: "sk-...",
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
if (options.signal?.aborted) {
|
|
43
|
+
throw new Error("Login cancelled");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const trimmed = apiKey.trim();
|
|
47
|
+
if (!trimmed) {
|
|
48
|
+
throw new Error("API key is required");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
options.onProgress?.("Validating API key...");
|
|
52
|
+
await validateOpenAICompatibleApiKey({
|
|
53
|
+
provider: "Z.AI",
|
|
54
|
+
apiKey: trimmed,
|
|
55
|
+
baseUrl: API_BASE_URL,
|
|
56
|
+
model: VALIDATION_MODEL,
|
|
57
|
+
signal: options.signal,
|
|
58
|
+
});
|
|
59
|
+
return trimmed;
|
|
60
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** ZenMux login flow (API key paste, validated via /models). */
|
|
2
|
+
import { createApiKeyLogin } from "./api-key-login";
|
|
3
|
+
|
|
4
|
+
export const loginZenMux = createApiKeyLogin({
|
|
5
|
+
providerLabel: "ZenMux",
|
|
6
|
+
authUrl: "https://zenmux.ai/settings/keys",
|
|
7
|
+
instructions: "Create or copy your ZenMux API key",
|
|
8
|
+
promptMessage: "Paste your ZenMux API key",
|
|
9
|
+
placeholder: "sk-...",
|
|
10
|
+
validation: {
|
|
11
|
+
kind: "models-endpoint",
|
|
12
|
+
provider: "ZenMux",
|
|
13
|
+
modelsUrl: "https://zenmux.ai/api/v1/models",
|
|
14
|
+
},
|
|
15
|
+
});
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import type { AssistantMessage } from "../types";
|
|
2
|
+
import type { TransportFailureFacts } from "./fallback-transport";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Regex patterns to detect context overflow errors from different providers.
|
|
6
|
+
*
|
|
7
|
+
* These patterns match error messages returned when the input exceeds
|
|
8
|
+
* the model's context window.
|
|
9
|
+
*
|
|
10
|
+
* Provider-specific patterns (with example error messages):
|
|
11
|
+
*
|
|
12
|
+
* - Anthropic: "prompt is too long: 213462 tokens > 200000 maximum"
|
|
13
|
+
* - OpenAI: "Your input exceeds the context window of this model"
|
|
14
|
+
* - Google: "The input token count (1196265) exceeds the maximum number of tokens allowed (1048575)"
|
|
15
|
+
* - xAI: "This model's maximum prompt length is 131072 but the request contains 537812 tokens"
|
|
16
|
+
* - Groq: "Please reduce the length of the messages or completion"
|
|
17
|
+
* - OpenRouter: "This endpoint's maximum context length is X tokens. However, you requested about Y tokens"
|
|
18
|
+
* - llama.cpp: "the request exceeds the available context size, try increasing it"
|
|
19
|
+
* - LM Studio: "tokens to keep from the initial prompt is greater than the context length"
|
|
20
|
+
* - GitHub Copilot: "prompt token count of X exceeds the limit of Y"
|
|
21
|
+
* - MiniMax: "invalid params, context window exceeds limit"
|
|
22
|
+
* - Kimi For Coding: "Your request exceeded model token limit: X (requested: Y)"
|
|
23
|
+
* - Anthropic 413: "request_too_large" / "Request exceeds the maximum size" (payload too large)
|
|
24
|
+
* - HTTP 413 variants: "Payload Too Large" / "Request Entity Too Large"
|
|
25
|
+
* - z.ai / GLM: Returns finish_reason: "model_context_window_exceeded" mapped to error message
|
|
26
|
+
* - z.ai: Does NOT error, accepts overflow silently - handled via usage.input > contextWindow
|
|
27
|
+
* - Ollama: Silently truncates input - not detectable via error message
|
|
28
|
+
*/
|
|
29
|
+
const OVERFLOW_PATTERNS = [
|
|
30
|
+
/prompt is too long/i, // Anthropic
|
|
31
|
+
/input is too long for requested model/i, // Amazon Bedrock
|
|
32
|
+
/exceeds the context window/i, // OpenAI (Completions & Responses API)
|
|
33
|
+
/input token count.*exceeds the maximum/i, // Google (Gemini)
|
|
34
|
+
/maximum prompt length is \d+/i, // xAI (Grok)
|
|
35
|
+
/reduce the length of the messages/i, // Groq
|
|
36
|
+
/maximum context length is \d+ tokens/i, // OpenRouter (all backends)
|
|
37
|
+
/exceeds the limit of \d+/i, // GitHub Copilot
|
|
38
|
+
/exceeds the available context size/i, // llama.cpp server
|
|
39
|
+
/requested tokens?.*exceed.*context (window|length|size)/i, // llama.cpp / OpenAI-compatible local servers
|
|
40
|
+
/context (window|length|size).*(exceeded|overflow|too small)/i, // Generic local server variants
|
|
41
|
+
/(prompt|input).*(too long|too large).*(context|n_ctx)/i, // llama.cpp phrasing variants
|
|
42
|
+
/requested tokens?.*(exceeds?|greater than).*(n_ctx|context)/i, // llama.cpp n_ctx variants
|
|
43
|
+
/greater than the context length/i, // LM Studio
|
|
44
|
+
/context window exceeds limit/i, // MiniMax
|
|
45
|
+
/exceeded model token limit/i, // Kimi For Coding
|
|
46
|
+
/context[_ ]length[_ ]exceeded/i, // Generic fallback
|
|
47
|
+
/too many tokens/i, // Generic fallback
|
|
48
|
+
/token limit exceeded/i, // Generic fallback
|
|
49
|
+
/request_too_large/i, // Anthropic 413 (request body too large)
|
|
50
|
+
/request exceeds the maximum size/i, // Anthropic 413 variant
|
|
51
|
+
/payload too large/i, // Generic HTTP 413 variant
|
|
52
|
+
/entity too large/i, // Generic HTTP 413 variant
|
|
53
|
+
/\b413\b.*\b(request|payload|entity)\b.*\btoo large\b/i, // "413 Request Entity Too Large" variants
|
|
54
|
+
/model_context_window_exceeded/i, // z.ai non-standard finish_reason surfaced as error text
|
|
55
|
+
];
|
|
56
|
+
/**
|
|
57
|
+
* Threshold below which a "successful" (stopReason "stop") response with empty
|
|
58
|
+
* content is considered anomalous. Some proxies (notably LiteLLM) return an
|
|
59
|
+
* empty `choices[0].message.content` with a near-zero `usage` (e.g. input: 1,
|
|
60
|
+
* output: 1) when the upstream model context window is exceeded, instead of
|
|
61
|
+
* surfacing a proper error. The total token count for such a response is well
|
|
62
|
+
* below any realistic turn, so we treat it as a proxy-level overflow signal.
|
|
63
|
+
*/
|
|
64
|
+
const EMPTY_RESPONSE_USAGE_THRESHOLD = 5;
|
|
65
|
+
/**
|
|
66
|
+
* Check if an assistant message represents a context overflow error.
|
|
67
|
+
*
|
|
68
|
+
* This handles three cases:
|
|
69
|
+
* 1. Error-based overflow: Most providers return stopReason "error" with a
|
|
70
|
+
* specific error message pattern.
|
|
71
|
+
* 2. Silent overflow: Some providers accept overflow requests and return
|
|
72
|
+
* successfully. For these, we check if usage.input exceeds the context window.
|
|
73
|
+
* 3. Proxy-level overflow: Some proxies (e.g. LiteLLM) return a "successful"
|
|
74
|
+
* response with empty content and a fabricated near-zero usage when the
|
|
75
|
+
* upstream model's context window is exceeded.
|
|
76
|
+
*
|
|
77
|
+
* ## Reliability by Provider
|
|
78
|
+
*
|
|
79
|
+
* **Reliable detection (returns error with detectable message):**
|
|
80
|
+
* - Anthropic: "prompt is too long: X tokens > Y maximum"
|
|
81
|
+
* - OpenAI (Completions & Responses): "exceeds the context window"
|
|
82
|
+
* - Google Gemini: "input token count exceeds the maximum"
|
|
83
|
+
* - xAI (Grok): "maximum prompt length is X but request contains Y"
|
|
84
|
+
* - Groq: "reduce the length of the messages"
|
|
85
|
+
* - Cerebras: 400/413 status code (no body)
|
|
86
|
+
* - Mistral: 400/413 status code (no body)
|
|
87
|
+
* - HTTP 413 payload/entity-too-large variants
|
|
88
|
+
* - OpenRouter (all backends): "maximum context length is X tokens"
|
|
89
|
+
* - llama.cpp: "exceeds the available context size"
|
|
90
|
+
* - LM Studio: "greater than the context length"
|
|
91
|
+
* - Kimi For Coding: "exceeded model token limit: X (requested: Y)"
|
|
92
|
+
* - Anthropic 413: "request_too_large" (request body exceeds size limit)
|
|
93
|
+
* - HTTP 413: "Payload Too Large" / "Request Entity Too Large"
|
|
94
|
+
*
|
|
95
|
+
* **Unreliable detection:**
|
|
96
|
+
* - z.ai: Sometimes accepts overflow silently (detectable via usage.input > contextWindow),
|
|
97
|
+
* sometimes returns rate limit errors. Pass contextWindow param to detect silent overflow.
|
|
98
|
+
* - Ollama: Silently truncates input without error. Cannot be detected via this function.
|
|
99
|
+
* - LiteLLM proxy: Returns a "successful" response with empty content and a
|
|
100
|
+
* fabricated near-zero usage (e.g. input: 1, output: 1) when the upstream
|
|
101
|
+
* model's context window is exceeded. Detected via Case 3 (empty content +
|
|
102
|
+
* anomalously low usage). Note: the LiteLLM proxy's context limit may differ
|
|
103
|
+
* from the underlying model's advertised contextWindow (e.g. configured via
|
|
104
|
+
* `model_info.max_tokens` in LiteLLM's config.yaml), so Case 2 (which compares
|
|
105
|
+
* usage.input against contextWindow) may not catch it.
|
|
106
|
+
* The response will have usage.input < expected, but we don't know the expected value.
|
|
107
|
+
*
|
|
108
|
+
* ## Custom Providers
|
|
109
|
+
*
|
|
110
|
+
* If you've added custom models via settings.json, this function may not detect
|
|
111
|
+
* overflow errors from those providers. To add support:
|
|
112
|
+
*
|
|
113
|
+
* 1. Send a request that exceeds the model's context window
|
|
114
|
+
* 2. Check the errorMessage in the response
|
|
115
|
+
* 3. Create a regex pattern that matches the error
|
|
116
|
+
* 4. The pattern should be added to OVERFLOW_PATTERNS in this file, or
|
|
117
|
+
* check the errorMessage yourself before calling this function
|
|
118
|
+
*
|
|
119
|
+
* @param message - The assistant message to check
|
|
120
|
+
* @param contextWindow - Optional context window size for detecting silent overflow (z.ai)
|
|
121
|
+
* @returns true if the message indicates a context overflow
|
|
122
|
+
*/
|
|
123
|
+
/**
|
|
124
|
+
* Authoritatively classify a context overflow from the assistant result and
|
|
125
|
+
* normalized transport facts. Typed facts take precedence over provider prose:
|
|
126
|
+
* an explicit non-overflow transport failure cannot be upgraded by hostile or
|
|
127
|
+
* misleading error text.
|
|
128
|
+
*/
|
|
129
|
+
const OVERFLOW_PROVIDER_CODES = new Set(["context_length_exceeded", "request_too_large"]);
|
|
130
|
+
/**
|
|
131
|
+
* Codes that name a specific non-overflow *cause*. These are authoritative and
|
|
132
|
+
* can never be upgraded by error prose. Generic HTTP envelope types belong in
|
|
133
|
+
* {@link GENERIC_ENVELOPE_PROVIDER_CODES} instead.
|
|
134
|
+
*/
|
|
135
|
+
const NON_OVERFLOW_PROVIDER_CODES = new Set([
|
|
136
|
+
"authentication_error",
|
|
137
|
+
"invalid_api_key",
|
|
138
|
+
"invalid_token",
|
|
139
|
+
"token_expired",
|
|
140
|
+
"unauthorized",
|
|
141
|
+
"forbidden",
|
|
142
|
+
"insufficient_quota",
|
|
143
|
+
"quota_exceeded",
|
|
144
|
+
"quota_exhausted",
|
|
145
|
+
"usage_limit_reached",
|
|
146
|
+
"usage_not_included",
|
|
147
|
+
"out_of_credits",
|
|
148
|
+
"rate_limit",
|
|
149
|
+
"rate_limit_error",
|
|
150
|
+
"rate_limit_exceeded",
|
|
151
|
+
"too_many_requests",
|
|
152
|
+
"empty_response",
|
|
153
|
+
]);
|
|
154
|
+
|
|
155
|
+
function transportCodes(transportFailure: TransportFailureFacts | undefined): string[] {
|
|
156
|
+
return [transportFailure?.openaiErrorCode, transportFailure?.anthropicErrorType, transportFailure?.providerCode]
|
|
157
|
+
.filter((code): code is string => typeof code === "string")
|
|
158
|
+
.map(code => code.toLowerCase());
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function hasTypedNonOverflowCode(transportFailure: TransportFailureFacts | undefined): boolean {
|
|
162
|
+
return transportCodes(transportFailure).some(code => NON_OVERFLOW_PROVIDER_CODES.has(code));
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Generic envelope codes that name the HTTP error *category*, not its cause.
|
|
167
|
+
*
|
|
168
|
+
* Anthropic reports context overflow through this envelope:
|
|
169
|
+
*
|
|
170
|
+
* {"type":"error","error":{"type":"invalid_request_error",
|
|
171
|
+
* "message":"prompt is too long: 1158066 tokens > 1000000 maximum"}}
|
|
172
|
+
*
|
|
173
|
+
* Treating the envelope as an authoritative non-overflow cause vetoed the
|
|
174
|
+
* overflow classification, so auto-compaction never ran and the session died on
|
|
175
|
+
* the very overflow it was supposed to absorb.
|
|
176
|
+
*
|
|
177
|
+
* Unlike {@link NON_OVERFLOW_PROVIDER_CODES} (auth, quota, rate limit), this
|
|
178
|
+
* envelope names no cause, so it must not veto an overflow the provider stated
|
|
179
|
+
* quantitatively. It still vetoes free-form prose: only the self-verifying
|
|
180
|
+
* measured form below can override it.
|
|
181
|
+
*/
|
|
182
|
+
const GENERIC_ENVELOPE_PROVIDER_CODES = new Set(["invalid_request_error"]);
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Anthropic's measured overflow report: `<used> tokens > <limit> maximum`.
|
|
186
|
+
*
|
|
187
|
+
* Deliberately far narrower than {@link OVERFLOW_PATTERNS}. Those patterns
|
|
188
|
+
* include loose prose (`too many tokens`, `token limit exceeded`) that a tool
|
|
189
|
+
* result or a model-authored string can trivially contain, so they must never
|
|
190
|
+
* be able to flip a typed transport classification. This form carries its own
|
|
191
|
+
* arithmetic proof and is verified below, so injected text cannot satisfy it
|
|
192
|
+
* without also asserting a real overage.
|
|
193
|
+
*/
|
|
194
|
+
const ANTHROPIC_MEASURED_OVERFLOW_PATTERN = /prompt is too long:\s*(\d+)\s*tokens?\s*>\s*(\d+)\s*maximum/i;
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* True only for a provider-measured overflow that verifies against itself:
|
|
198
|
+
* the reported usage must actually exceed the reported maximum.
|
|
199
|
+
*/
|
|
200
|
+
function hasSelfVerifyingOverflowMeasurement(message: AssistantMessage): boolean {
|
|
201
|
+
if (message.stopReason !== "error") return false;
|
|
202
|
+
const errorMessage = message.errorMessage;
|
|
203
|
+
if (!errorMessage) return false;
|
|
204
|
+
const match = ANTHROPIC_MEASURED_OVERFLOW_PATTERN.exec(errorMessage);
|
|
205
|
+
if (!match) return false;
|
|
206
|
+
const used = Number(match[1]);
|
|
207
|
+
const maximum = Number(match[2]);
|
|
208
|
+
if (!Number.isFinite(used) || !Number.isFinite(maximum) || maximum <= 0) return false;
|
|
209
|
+
return used > maximum;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function isTypedNoBodyOverflow(
|
|
213
|
+
message: AssistantMessage,
|
|
214
|
+
transportFailure: TransportFailureFacts | undefined,
|
|
215
|
+
): boolean {
|
|
216
|
+
if (transportFailure?.status !== 400 && transportFailure?.status !== 413) return false;
|
|
217
|
+
return !message.errorMessage || /\b4(00|13)\s*(status code)?\s*\(no body\)/i.test(message.errorMessage);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export function classifyContextOverflow(
|
|
221
|
+
message: AssistantMessage,
|
|
222
|
+
transportFailure?: TransportFailureFacts,
|
|
223
|
+
contextWindow?: number,
|
|
224
|
+
): boolean {
|
|
225
|
+
if (transportFailure?.status === 429) return false;
|
|
226
|
+
const typedCodes = transportCodes(transportFailure);
|
|
227
|
+
if (typedCodes.some(code => OVERFLOW_PROVIDER_CODES.has(code))) return true;
|
|
228
|
+
// A specific non-overflow cause (auth, quota, rate limit) is authoritative
|
|
229
|
+
// and can never be upgraded by error prose.
|
|
230
|
+
if (hasTypedNonOverflowCode(transportFailure)) return false;
|
|
231
|
+
// A generic envelope (`invalid_request_error`) names no cause. It still
|
|
232
|
+
// vetoes free-form overflow prose, but must not veto a provider-measured,
|
|
233
|
+
// self-verifying overflow report — that is how Anthropic reports overflow.
|
|
234
|
+
if (
|
|
235
|
+
typedCodes.some(code => GENERIC_ENVELOPE_PROVIDER_CODES.has(code)) &&
|
|
236
|
+
!hasSelfVerifyingOverflowMeasurement(message)
|
|
237
|
+
) {
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
if (isTypedNoBodyOverflow(message, transportFailure)) return true;
|
|
241
|
+
|
|
242
|
+
const errorMessage = message.errorMessage;
|
|
243
|
+
if (message.stopReason === "error" && errorMessage) {
|
|
244
|
+
if (OVERFLOW_PATTERNS.some(pattern => pattern.test(errorMessage))) return true;
|
|
245
|
+
if (/\b4(00|13)\s*(status code)?\s*\(no body\)/i.test(errorMessage)) return true;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (contextWindow) {
|
|
249
|
+
const inputTokens = message.usage.input + message.usage.cacheRead + message.usage.cacheWrite;
|
|
250
|
+
if (inputTokens > contextWindow) return true;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return (
|
|
254
|
+
message.stopReason === "stop" &&
|
|
255
|
+
message.content.length === 0 &&
|
|
256
|
+
message.usage.input + message.usage.output <= EMPTY_RESPONSE_USAGE_THRESHOLD
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Check if an assistant message represents a context overflow error.
|
|
262
|
+
*
|
|
263
|
+
* Callers with normalized transport facts should use {@link classifyContextOverflow}
|
|
264
|
+
* so typed provider codes take precedence over error prose.
|
|
265
|
+
*/
|
|
266
|
+
export function isContextOverflow(message: AssistantMessage, contextWindow?: number): boolean {
|
|
267
|
+
return classifyContextOverflow(message, undefined, contextWindow);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Get the overflow patterns for testing purposes.
|
|
272
|
+
*/
|
|
273
|
+
export function getOverflowPatterns(): RegExp[] {
|
|
274
|
+
return [...OVERFLOW_PATTERNS];
|
|
275
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared `host:port` parser used by the auth-broker and auth-gateway boot
|
|
3
|
+
* paths. Centralized so the two servers can't drift on what they accept (the
|
|
4
|
+
* gateway used to silently allow empty hostnames; this fixes it).
|
|
5
|
+
*/
|
|
6
|
+
import { isIP } from "node:net";
|
|
7
|
+
|
|
8
|
+
export interface ParsedBind {
|
|
9
|
+
hostname: string;
|
|
10
|
+
port: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function parsePort(raw: string, bind: string): number {
|
|
14
|
+
if (!/^\d+$/.test(raw)) {
|
|
15
|
+
throw new Error(`Invalid bind '${bind}'; port must be an integer.`);
|
|
16
|
+
}
|
|
17
|
+
const port = Number.parseInt(raw, 10);
|
|
18
|
+
if (!Number.isFinite(port) || port < 0 || port > 65535) {
|
|
19
|
+
throw new Error(`Invalid bind '${bind}'; port out of range.`);
|
|
20
|
+
}
|
|
21
|
+
return port;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Parse a `host:port` (or bare `port`, which assumes loopback) string.
|
|
26
|
+
*
|
|
27
|
+
* Accepts:
|
|
28
|
+
* - `"4000"` → `127.0.0.1:4000`
|
|
29
|
+
* - `"0.0.0.0:4000"` → as written
|
|
30
|
+
* - `"[::1]:4000"` → as written (brackets retained, Bun handles them)
|
|
31
|
+
*
|
|
32
|
+
* Rejects:
|
|
33
|
+
* - empty input
|
|
34
|
+
* - empty hostname (`":4000"`)
|
|
35
|
+
* - non-integer / out-of-range port
|
|
36
|
+
*/
|
|
37
|
+
export function parseBind(raw: string): ParsedBind {
|
|
38
|
+
const trimmed = raw.trim();
|
|
39
|
+
if (trimmed.length === 0) {
|
|
40
|
+
throw new Error("Invalid bind; expected 'host:port' or 'port'.");
|
|
41
|
+
}
|
|
42
|
+
if (/^\d+$/.test(trimmed)) {
|
|
43
|
+
return { hostname: "127.0.0.1", port: parsePort(trimmed, raw) };
|
|
44
|
+
}
|
|
45
|
+
const lastColon = trimmed.lastIndexOf(":");
|
|
46
|
+
if (lastColon < 0) {
|
|
47
|
+
throw new Error(`Invalid bind '${raw}'; expected 'host:port' or 'port'.`);
|
|
48
|
+
}
|
|
49
|
+
const hostPart = trimmed.slice(0, lastColon);
|
|
50
|
+
const portPart = trimmed.slice(lastColon + 1);
|
|
51
|
+
if (hostPart.length === 0) {
|
|
52
|
+
throw new Error(`Invalid bind '${raw}'; host must not be empty.`);
|
|
53
|
+
}
|
|
54
|
+
return { hostname: hostPart, port: parsePort(portPart, raw) };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** True for loopback-only hostnames the auth servers may bind without credentials. */
|
|
58
|
+
export function isLoopbackHostname(hostname: string): boolean {
|
|
59
|
+
const normalized = hostname
|
|
60
|
+
.trim()
|
|
61
|
+
.toLowerCase()
|
|
62
|
+
.replace(/^\[|\]$/g, "");
|
|
63
|
+
if (normalized === "localhost" || normalized === "::1") return true;
|
|
64
|
+
// Strict numeric IPv4 loopback literals only: a bare prefix match would
|
|
65
|
+
// accept attacker-controlled names like `127.evil.example`, and short/hex
|
|
66
|
+
// IPv4 forms (`127.1`, `0x7f.1`) are rejected by the parser anyway.
|
|
67
|
+
return isIP(normalized) === 4 && normalized.split(".")[0] === "127";
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Fail closed when an unauthenticated auth server (empty bearer token set)
|
|
72
|
+
* would bind a non-loopback address: that exposes credential operations to the
|
|
73
|
+
* network with no proof of possession.
|
|
74
|
+
*/
|
|
75
|
+
export function assertAuthenticatedOrLoopback(bind: ParsedBind, bearerTokenCount: number, serverName: string): void {
|
|
76
|
+
if (bearerTokenCount > 0) return;
|
|
77
|
+
if (isLoopbackHostname(bind.hostname)) return;
|
|
78
|
+
throw new Error(
|
|
79
|
+
`${serverName} refuses to bind ${bind.hostname}:${bind.port} without bearer tokens; unauthenticated mode is loopback-only.`,
|
|
80
|
+
);
|
|
81
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Api, AttemptScopeRef, Model, ProviderResponseMetadata, StreamOptions } from "../types";
|
|
2
|
+
export declare function normalizeProviderResponse(response: Response, requestId?: string | null, metadata?: Record<string, unknown>): ProviderResponseMetadata;
|
|
3
|
+
export declare function notifyProviderResponse(options: {
|
|
4
|
+
onResponse?: StreamOptions["onResponse"];
|
|
5
|
+
attemptScope?: AttemptScopeRef;
|
|
6
|
+
} | undefined, response: Response, model?: Model<Api>, requestId?: string | null, metadata?: Record<string, unknown>): Promise<void>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Api, AttemptScopeRef, Model, ProviderResponseMetadata, StreamOptions } from "../types";
|
|
2
|
+
|
|
3
|
+
export function normalizeProviderResponse(
|
|
4
|
+
response: Response,
|
|
5
|
+
requestId?: string | null,
|
|
6
|
+
metadata?: Record<string, unknown>,
|
|
7
|
+
): ProviderResponseMetadata {
|
|
8
|
+
const headers: Record<string, string> = {};
|
|
9
|
+
response.headers.forEach((value, key) => {
|
|
10
|
+
headers[key.toLowerCase()] = value;
|
|
11
|
+
});
|
|
12
|
+
const providerResponse: ProviderResponseMetadata = {
|
|
13
|
+
status: response.status,
|
|
14
|
+
headers,
|
|
15
|
+
};
|
|
16
|
+
if (requestId !== undefined) providerResponse.requestId = requestId;
|
|
17
|
+
if (metadata !== undefined) providerResponse.metadata = metadata;
|
|
18
|
+
return providerResponse;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export async function notifyProviderResponse(
|
|
22
|
+
options: { onResponse?: StreamOptions["onResponse"]; attemptScope?: AttemptScopeRef } | undefined,
|
|
23
|
+
response: Response,
|
|
24
|
+
model?: Model<Api>,
|
|
25
|
+
requestId?: string | null,
|
|
26
|
+
metadata?: Record<string, unknown>,
|
|
27
|
+
): Promise<void> {
|
|
28
|
+
if (!options?.onResponse) return;
|
|
29
|
+
await options.onResponse(normalizeProviderResponse(response, requestId, metadata), model, options.attemptScope);
|
|
30
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public provider safety-stop surface (issue #4777 review follow-up).
|
|
3
|
+
*
|
|
4
|
+
* First-party adapters mint terminal authority through the package-private
|
|
5
|
+
* adapter-internals module. Public consumers may only verify existing
|
|
6
|
+
* authority; message fields and structured refusal text never mint authority.
|
|
7
|
+
*/
|
|
8
|
+
export { isProviderSafetyStopAuthenticated } from "../adapter-internals/provider-safety-stop";
|