@prometheus-ai/ai 0.5.4 → 0.5.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/types/auth-broker/remote-store.d.ts +2 -1
- package/dist/types/auth-broker/wire-schemas.d.ts +4 -1
- package/dist/types/auth-gateway/server.d.ts +19 -0
- package/dist/types/auth-gateway/types.d.ts +9 -3
- package/dist/types/auth-retry.d.ts +119 -0
- package/dist/types/auth-storage.d.ts +217 -8
- package/dist/types/errors.d.ts +24 -0
- package/dist/types/index.d.ts +5 -9
- package/dist/types/provider-details.d.ts +1 -1
- package/dist/types/providers/amazon-bedrock.d.ts +12 -6
- package/dist/types/providers/anthropic-client.d.ts +10 -3
- package/dist/types/providers/anthropic-messages-server-schema.d.ts +2 -2
- package/dist/types/providers/anthropic-messages-server.d.ts +3 -3
- package/dist/types/providers/anthropic-wire.d.ts +3 -3
- package/dist/types/providers/anthropic.d.ts +41 -34
- package/dist/types/providers/aws-credentials.d.ts +8 -0
- package/dist/types/providers/azure-openai-responses.d.ts +1 -0
- package/dist/types/providers/google-gemini-cli.d.ts +22 -1
- package/dist/types/providers/google-shared.d.ts +22 -0
- package/dist/types/providers/google-types.d.ts +13 -1
- package/dist/types/providers/mock.d.ts +8 -3
- package/dist/types/providers/ollama.d.ts +6 -0
- package/dist/types/providers/openai-chat-server-schema.d.ts +6 -3
- package/dist/types/providers/openai-chat-server.d.ts +3 -3
- package/dist/types/providers/openai-chat-wire.d.ts +644 -0
- package/dist/types/providers/openai-codex/request-transformer.d.ts +8 -0
- package/dist/types/providers/openai-codex/response-handler.d.ts +9 -0
- package/dist/types/providers/openai-codex-responses.d.ts +31 -2
- package/dist/types/providers/openai-completions-compat.d.ts +2 -25
- package/dist/types/providers/openai-completions.d.ts +2 -10
- package/dist/types/providers/openai-responses-server-schema.d.ts +4 -4
- package/dist/types/providers/openai-responses-server.d.ts +2 -2
- package/dist/types/providers/openai-responses-shared.d.ts +49 -9
- package/dist/types/providers/openai-responses-wire.d.ts +6065 -0
- package/dist/types/providers/openai-responses.d.ts +13 -4
- package/dist/types/providers/prometheus-native-client.d.ts +9 -0
- package/dist/types/providers/prometheus-native-server.d.ts +4 -3
- package/dist/types/providers/transform-messages.d.ts +1 -2
- package/dist/types/rate-limit-utils.d.ts +3 -2
- package/dist/types/registry/aimlapi.d.ts +4 -0
- package/dist/types/registry/alibaba-coding-plan.d.ts +7 -0
- package/dist/types/registry/amazon-bedrock.d.ts +5 -0
- package/dist/types/registry/anthropic.d.ts +10 -0
- package/dist/types/{utils/oauth → registry}/api-key-login.d.ts +8 -2
- package/dist/types/{utils/oauth → registry}/api-key-validation.d.ts +15 -0
- package/dist/types/registry/cerebras.d.ts +7 -0
- package/dist/types/registry/cloudflare-ai-gateway.d.ts +13 -0
- package/dist/types/registry/cursor.d.ts +7 -0
- package/dist/types/registry/deepseek.d.ts +8 -0
- package/dist/types/registry/derived.d.ts +5 -0
- package/dist/types/registry/firepass.d.ts +16 -0
- package/dist/types/registry/fireworks.d.ts +7 -0
- package/dist/types/registry/github-copilot.d.ts +7 -0
- package/dist/types/registry/gitlab-duo.d.ts +9 -0
- package/dist/types/registry/google-antigravity.d.ts +9 -0
- package/dist/types/registry/google-gemini-cli.d.ts +9 -0
- package/dist/types/registry/google-vertex.d.ts +5 -0
- package/dist/types/registry/google.d.ts +4 -0
- package/dist/types/registry/groq.d.ts +4 -0
- package/dist/types/registry/huggingface.d.ts +7 -0
- package/dist/types/registry/index.d.ts +4 -0
- package/dist/types/registry/kagi.d.ts +14 -0
- package/dist/types/registry/kilo.d.ts +7 -0
- package/dist/types/registry/kimi-code.d.ts +7 -0
- package/dist/types/registry/litellm.d.ts +13 -0
- package/dist/types/registry/lm-studio.d.ts +8 -0
- package/dist/types/registry/minimax-code-cn.d.ts +6 -0
- package/dist/types/registry/minimax-code.d.ts +6 -0
- package/dist/types/registry/minimax.d.ts +4 -0
- package/dist/types/registry/mistral.d.ts +4 -0
- package/dist/types/registry/moonshot.d.ts +7 -0
- package/dist/types/registry/nanogpt.d.ts +7 -0
- package/dist/types/registry/nvidia.d.ts +7 -0
- package/dist/types/registry/oauth/__tests__/xai-oauth.test.d.ts +1 -0
- package/dist/types/{utils → registry}/oauth/anthropic.d.ts +2 -1
- package/dist/types/{utils → registry}/oauth/github-copilot.d.ts +15 -23
- package/dist/types/{utils → registry}/oauth/index.d.ts +1 -0
- package/dist/types/{utils → registry}/oauth/minimax-code.d.ts +5 -5
- package/dist/types/{utils → registry}/oauth/types.d.ts +6 -1
- package/dist/types/{utils → registry}/oauth/xai-oauth.d.ts +2 -1
- package/dist/types/registry/ollama-cloud.d.ts +7 -0
- package/dist/types/registry/ollama.d.ts +12 -0
- package/dist/types/registry/openai-codex-device.d.ts +8 -0
- package/dist/types/registry/openai-codex.d.ts +9 -0
- package/dist/types/registry/openai.d.ts +4 -0
- package/dist/types/registry/opencode-go.d.ts +6 -0
- package/dist/types/registry/opencode-zen.d.ts +6 -0
- package/dist/types/registry/openrouter.d.ts +13 -0
- package/dist/types/registry/parallel.d.ts +14 -0
- package/dist/types/registry/perplexity.d.ts +7 -0
- package/dist/types/registry/qianfan.d.ts +7 -0
- package/dist/types/registry/qwen-portal.d.ts +7 -0
- package/dist/types/registry/registry.d.ts +272 -0
- package/dist/types/registry/synthetic.d.ts +6 -0
- package/dist/types/registry/tavily.d.ts +14 -0
- package/dist/types/registry/together.d.ts +6 -0
- package/dist/types/registry/types.d.ts +51 -0
- package/dist/types/registry/venice.d.ts +13 -0
- package/dist/types/registry/vercel-ai-gateway.d.ts +7 -0
- package/dist/types/registry/vllm.d.ts +7 -0
- package/dist/types/registry/wafer-pass.d.ts +6 -0
- package/dist/types/registry/wafer-serverless.d.ts +6 -0
- package/dist/types/registry/xai-oauth.d.ts +7 -0
- package/dist/types/registry/xai.d.ts +4 -0
- package/dist/types/registry/xiaomi-token-plan-ams.d.ts +6 -0
- package/dist/types/registry/xiaomi-token-plan-cn.d.ts +6 -0
- package/dist/types/registry/xiaomi-token-plan-sgp.d.ts +6 -0
- package/dist/types/registry/xiaomi.d.ts +6 -0
- package/dist/types/registry/zai.d.ts +7 -0
- package/dist/types/registry/zenmux.d.ts +7 -0
- package/dist/types/registry/zhipu-coding-plan.d.ts +7 -0
- package/dist/types/stream.d.ts +9 -1
- package/dist/types/types.d.ts +56 -295
- package/dist/types/usage/google-antigravity.d.ts +15 -1
- package/dist/types/usage/openai-codex-reset.d.ts +79 -0
- package/dist/types/usage/openai-codex.d.ts +1 -0
- package/dist/types/usage.d.ts +77 -4
- package/dist/types/utils/abort.d.ts +6 -0
- package/dist/types/utils/event-stream.d.ts +2 -0
- package/dist/types/utils/http-inspector.d.ts +0 -1
- package/dist/types/utils/idle-iterator.d.ts +35 -0
- package/dist/types/utils/openai-http.d.ts +58 -0
- package/dist/types/utils/request-debug.d.ts +3 -0
- package/dist/types/utils/retry-after.d.ts +1 -0
- package/dist/types/utils/schema/fields.d.ts +5 -0
- package/dist/types/utils/schema/json-schema-validator.d.ts +8 -0
- package/dist/types/utils/schema/stamps.d.ts +7 -15
- package/dist/types/utils/sse-debug.d.ts +0 -5
- package/dist/types/utils/stream-markup-healing.d.ts +2 -0
- package/dist/types/utils.d.ts +1 -5
- package/package.json +17 -29
- package/src/auth-broker/remote-store.ts +10 -1
- package/src/auth-broker/snapshot-cache.ts +1 -1
- package/src/auth-broker/wire-schemas.ts +1 -1
- package/src/auth-gateway/http.ts +1 -1
- package/src/auth-gateway/server.ts +95 -30
- package/src/auth-gateway/types.ts +10 -2
- package/src/auth-retry.ts +238 -0
- package/src/auth-storage.ts +935 -430
- package/src/errors.ts +32 -0
- package/src/index.ts +9 -14
- package/src/provider-details.ts +1 -1
- package/src/providers/__tests__/google-auth.test.ts +144 -0
- package/src/providers/amazon-bedrock.ts +70 -40
- package/src/providers/anthropic-client.ts +15 -13
- package/src/providers/anthropic-messages-server-schema.ts +17 -7
- package/src/providers/anthropic-messages-server.ts +88 -20
- package/src/providers/anthropic-wire.ts +4 -3
- package/src/providers/anthropic.ts +1234 -621
- package/src/providers/aws-credentials.ts +47 -5
- package/src/providers/aws-eventstream.ts +5 -0
- package/src/providers/azure-openai-responses.ts +117 -67
- package/src/providers/cursor.ts +30 -30
- package/src/providers/github-copilot-headers.ts +1 -1
- package/src/providers/gitlab-duo.ts +36 -29
- package/src/providers/google-auth.ts +71 -8
- package/src/providers/google-gemini-cli.ts +118 -22
- package/src/providers/google-shared.ts +163 -43
- package/src/providers/google-types.ts +10 -1
- package/src/providers/kimi.ts +1 -1
- package/src/providers/mock.ts +11 -3
- package/src/providers/ollama.ts +64 -7
- package/src/providers/openai-anthropic-shim.ts +17 -8
- package/src/providers/openai-chat-server-schema.ts +9 -3
- package/src/providers/openai-chat-server.ts +82 -16
- package/src/providers/openai-chat-wire.ts +847 -0
- package/src/providers/openai-codex/request-transformer.ts +129 -34
- package/src/providers/openai-codex/response-handler.ts +22 -1
- package/src/providers/openai-codex-responses.ts +699 -247
- package/src/providers/openai-completions-compat.ts +8 -308
- package/src/providers/openai-completions.ts +416 -267
- package/src/providers/openai-responses-server-schema.ts +15 -9
- package/src/providers/openai-responses-server.ts +162 -114
- package/src/providers/openai-responses-shared.ts +320 -82
- package/src/providers/openai-responses-wire.ts +6391 -0
- package/src/providers/openai-responses.ts +382 -176
- package/src/providers/prometheus-native-client.ts +27 -11
- package/src/providers/prometheus-native-server.ts +44 -17
- package/src/providers/transform-messages.ts +311 -120
- package/src/providers/vision-guard.ts +5 -3
- package/src/rate-limit-utils.ts +13 -3
- package/src/registry/aimlapi.ts +6 -0
- package/src/{utils/oauth → registry}/alibaba-coding-plan.ts +8 -18
- package/src/registry/amazon-bedrock.ts +22 -0
- package/src/registry/anthropic.ts +26 -0
- package/src/{utils/oauth → registry}/api-key-login.ts +25 -3
- package/src/{utils/oauth → registry}/api-key-validation.ts +62 -2
- package/src/{utils/oauth → registry}/cerebras.ts +8 -1
- package/src/{utils/oauth → registry}/cloudflare-ai-gateway.ts +8 -12
- package/src/registry/cursor.ts +20 -0
- package/src/{utils/oauth → registry}/deepseek.ts +9 -17
- package/src/registry/derived.ts +9 -0
- package/src/{utils/oauth → registry}/firepass.ts +10 -2
- package/src/{utils/oauth → registry}/fireworks.ts +8 -1
- package/src/registry/github-copilot.ts +22 -0
- package/src/registry/gitlab-duo.ts +19 -0
- package/src/registry/google-antigravity.ts +21 -0
- package/src/registry/google-gemini-cli.ts +21 -0
- package/src/registry/google-vertex.ts +38 -0
- package/src/registry/google.ts +6 -0
- package/src/registry/groq.ts +6 -0
- package/src/{utils/oauth → registry}/huggingface.ts +8 -19
- package/src/registry/index.ts +4 -0
- package/src/{utils/oauth → registry}/kagi.ts +9 -11
- package/src/{utils/oauth → registry}/kilo.ts +11 -6
- package/src/registry/kimi-code.ts +17 -0
- package/src/{utils/oauth → registry}/litellm.ts +8 -12
- package/src/{utils/oauth → registry}/lm-studio.ts +9 -17
- package/src/registry/minimax-code-cn.ts +12 -0
- package/src/registry/minimax-code.ts +12 -0
- package/src/registry/minimax.ts +6 -0
- package/src/registry/mistral.ts +6 -0
- package/src/{utils/oauth → registry}/moonshot.ts +8 -9
- package/src/{utils/oauth → registry}/nanogpt.ts +8 -1
- package/src/{utils/oauth → registry}/nvidia.ts +8 -18
- package/src/{utils → registry}/oauth/__tests__/xai-oauth.test.ts +4 -7
- package/src/{utils → registry}/oauth/anthropic.ts +38 -17
- package/src/{utils → registry}/oauth/github-copilot.ts +79 -115
- package/src/registry/oauth/gitlab-duo.ts +198 -0
- package/src/{utils → registry}/oauth/google-antigravity.ts +1 -4
- package/src/{utils → registry}/oauth/google-gemini-cli.ts +1 -4
- package/src/registry/oauth/index.ts +164 -0
- package/src/{utils → registry}/oauth/minimax-code.ts +16 -14
- package/src/{utils → registry}/oauth/types.ts +7 -51
- package/src/{utils → registry}/oauth/wafer.ts +1 -1
- package/src/{utils → registry}/oauth/xai-oauth.ts +16 -8
- package/src/{utils → registry}/oauth/xiaomi.ts +9 -4
- package/src/{utils/oauth → registry}/ollama-cloud.ts +8 -1
- package/src/{utils/oauth → registry}/ollama.ts +8 -13
- package/src/registry/openai-codex-device.ts +18 -0
- package/src/registry/openai-codex.ts +19 -0
- package/src/registry/openai.ts +6 -0
- package/src/registry/opencode-go.ts +12 -0
- package/src/registry/opencode-zen.ts +12 -0
- package/src/{utils/oauth → registry}/openrouter.ts +10 -2
- package/src/{utils/oauth → registry}/parallel.ts +9 -11
- package/src/registry/perplexity.ts +13 -0
- package/src/{utils/oauth → registry}/qianfan.ts +8 -17
- package/src/{utils/oauth → registry}/qwen-portal.ts +8 -19
- package/src/registry/registry.ts +149 -0
- package/src/{utils/oauth → registry}/synthetic.ts +7 -1
- package/src/{utils/oauth → registry}/tavily.ts +10 -12
- package/src/{utils/oauth → registry}/together.ts +7 -1
- package/src/registry/types.ts +56 -0
- package/src/{utils/oauth → registry}/venice.ts +8 -12
- package/src/{utils/oauth → registry}/vercel-ai-gateway.ts +8 -18
- package/src/{utils/oauth → registry}/vllm.ts +9 -16
- package/src/registry/wafer-pass.ts +12 -0
- package/src/registry/wafer-serverless.ts +12 -0
- package/src/registry/xai-oauth.ts +17 -0
- package/src/registry/xai.ts +6 -0
- package/src/registry/xiaomi-token-plan-ams.ts +12 -0
- package/src/registry/xiaomi-token-plan-cn.ts +12 -0
- package/src/registry/xiaomi-token-plan-sgp.ts +12 -0
- package/src/registry/xiaomi.ts +12 -0
- package/src/{utils/oauth → registry}/zai.ts +10 -22
- package/src/{utils/oauth → registry}/zenmux.ts +8 -1
- package/src/{utils/oauth/zhipu.ts → registry/zhipu-coding-plan.ts} +9 -21
- package/src/stream.ts +229 -199
- package/src/types.ts +63 -384
- package/src/usage/claude.ts +4 -2
- package/src/usage/github-copilot.ts +4 -2
- package/src/usage/google-antigravity.ts +196 -28
- package/src/usage/kimi.ts +1 -1
- package/src/usage/minimax-code.ts +5 -6
- package/src/usage/openai-codex-reset.ts +174 -0
- package/src/usage/openai-codex.ts +19 -2
- package/src/usage/zai.ts +2 -1
- package/src/usage.ts +93 -4
- package/src/utils/abort.ts +14 -0
- package/src/utils/event-stream.ts +17 -0
- package/src/utils/http-inspector.ts +4 -12
- package/src/utils/idle-iterator.ts +250 -79
- package/src/utils/openai-http.ts +157 -0
- package/src/utils/request-debug.ts +67 -19
- package/src/utils/retry-after.ts +1 -1
- package/src/utils/retry.ts +23 -2
- package/src/utils/schema/CONSTRAINTS.md +4 -2
- package/src/utils/schema/fields.ts +16 -0
- package/src/utils/schema/json-schema-validator.ts +19 -1
- package/src/utils/schema/normalize.ts +80 -8
- package/src/utils/schema/stamps.ts +22 -10
- package/src/utils/schema/wire.ts +2 -2
- package/src/utils/sse-debug.ts +0 -271
- package/src/utils/stream-markup-healing.ts +50 -8
- package/src/utils/validation.ts +49 -13
- package/src/utils.ts +2 -26
- package/dist/types/model-cache.d.ts +0 -17
- package/dist/types/model-manager.d.ts +0 -64
- package/dist/types/model-thinking.d.ts +0 -100
- package/dist/types/models.d.ts +0 -12
- package/dist/types/provider-models/bundled-references.d.ts +0 -4
- package/dist/types/provider-models/descriptors.d.ts +0 -50
- package/dist/types/provider-models/google.d.ts +0 -24
- package/dist/types/provider-models/index.d.ts +0 -5
- package/dist/types/provider-models/ollama.d.ts +0 -7
- package/dist/types/provider-models/openai-compat.d.ts +0 -323
- package/dist/types/provider-models/special.d.ts +0 -16
- package/dist/types/utils/discovery/antigravity.d.ts +0 -61
- package/dist/types/utils/discovery/codex.d.ts +0 -38
- package/dist/types/utils/discovery/cursor.d.ts +0 -23
- package/dist/types/utils/discovery/gemini.d.ts +0 -25
- package/dist/types/utils/discovery/index.d.ts +0 -4
- package/dist/types/utils/discovery/openai-compatible.d.ts +0 -72
- package/dist/types/utils/oauth/alibaba-coding-plan.d.ts +0 -18
- package/dist/types/utils/oauth/cerebras.d.ts +0 -1
- package/dist/types/utils/oauth/cloudflare-ai-gateway.d.ts +0 -18
- package/dist/types/utils/oauth/deepseek.d.ts +0 -10
- package/dist/types/utils/oauth/firepass.d.ts +0 -1
- package/dist/types/utils/oauth/fireworks.d.ts +0 -1
- package/dist/types/utils/oauth/huggingface.d.ts +0 -19
- package/dist/types/utils/oauth/kagi.d.ts +0 -17
- package/dist/types/utils/oauth/kilo.d.ts +0 -5
- package/dist/types/utils/oauth/litellm.d.ts +0 -18
- package/dist/types/utils/oauth/lm-studio.d.ts +0 -17
- package/dist/types/utils/oauth/moonshot.d.ts +0 -1
- package/dist/types/utils/oauth/nanogpt.d.ts +0 -1
- package/dist/types/utils/oauth/nvidia.d.ts +0 -18
- package/dist/types/utils/oauth/ollama-cloud.d.ts +0 -2
- package/dist/types/utils/oauth/ollama.d.ts +0 -18
- package/dist/types/utils/oauth/openrouter.d.ts +0 -1
- package/dist/types/utils/oauth/parallel.d.ts +0 -17
- package/dist/types/utils/oauth/qianfan.d.ts +0 -17
- package/dist/types/utils/oauth/qwen-portal.d.ts +0 -19
- package/dist/types/utils/oauth/synthetic.d.ts +0 -1
- package/dist/types/utils/oauth/tavily.d.ts +0 -17
- package/dist/types/utils/oauth/together.d.ts +0 -1
- package/dist/types/utils/oauth/venice.d.ts +0 -18
- package/dist/types/utils/oauth/vercel-ai-gateway.d.ts +0 -18
- package/dist/types/utils/oauth/vllm.d.ts +0 -16
- package/dist/types/utils/oauth/zai.d.ts +0 -18
- package/dist/types/utils/oauth/zenmux.d.ts +0 -1
- package/dist/types/utils/oauth/zhipu.d.ts +0 -18
- package/src/model-cache.ts +0 -129
- package/src/model-manager.ts +0 -469
- package/src/model-thinking.ts +0 -756
- package/src/models.json +0 -60287
- package/src/models.json.d.ts +0 -9
- package/src/models.ts +0 -56
- package/src/provider-models/bundled-references.ts +0 -38
- package/src/provider-models/descriptors.ts +0 -364
- package/src/provider-models/google.ts +0 -88
- package/src/provider-models/index.ts +0 -5
- package/src/provider-models/ollama.ts +0 -153
- package/src/provider-models/openai-compat.ts +0 -2904
- package/src/provider-models/special.ts +0 -67
- package/src/utils/discovery/antigravity.ts +0 -261
- package/src/utils/discovery/codex.ts +0 -371
- package/src/utils/discovery/cursor.ts +0 -306
- package/src/utils/discovery/gemini.ts +0 -248
- package/src/utils/discovery/index.ts +0 -4
- package/src/utils/discovery/openai-compatible.ts +0 -224
- package/src/utils/oauth/gitlab-duo.ts +0 -123
- package/src/utils/oauth/index.ts +0 -502
- /package/dist/types/{utils/oauth/__tests__/xai-oauth.test.d.ts → providers/__tests__/google-auth.test.d.ts} +0 -0
- /package/dist/types/{utils → registry}/oauth/callback-server.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/cursor.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/gitlab-duo.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/google-antigravity.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/google-gemini-cli.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/google-oauth-shared.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/kimi.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/openai-codex.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/opencode.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/perplexity.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/pkce.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/wafer.d.ts +0 -0
- /package/dist/types/{utils → registry}/oauth/xiaomi.d.ts +0 -0
- /package/src/{utils → registry}/oauth/callback-server.ts +0 -0
- /package/src/{utils → registry}/oauth/cursor.ts +0 -0
- /package/src/{utils → registry}/oauth/google-oauth-shared.ts +0 -0
- /package/src/{utils → registry}/oauth/kimi.ts +0 -0
- /package/src/{utils → registry}/oauth/oauth.html +0 -0
- /package/src/{utils → registry}/oauth/openai-codex.ts +0 -0
- /package/src/{utils → registry}/oauth/opencode.ts +0 -0
- /package/src/{utils → registry}/oauth/perplexity.ts +0 -0
- /package/src/{utils → registry}/oauth/pkce.ts +0 -0
package/src/errors.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured HTTP errors thrown by provider clients.
|
|
3
|
+
*
|
|
4
|
+
* Downstream classification reads these fields structurally rather than via
|
|
5
|
+
* `instanceof`: `extractHttpStatusFromError` (@prometheus-ai/utils) reads `status`,
|
|
6
|
+
* `getHeadersFromError` (retry-after extraction) reads `headers`, and retry
|
|
7
|
+
* policies such as `isCopilotTransientModelError` read `code`. Per-provider
|
|
8
|
+
* subclasses exist so call sites can narrow with `instanceof` and logs carry
|
|
9
|
+
* a meaningful `error.name`.
|
|
10
|
+
*/
|
|
11
|
+
export interface ProviderHttpErrorOptions {
|
|
12
|
+
/** Response headers; enables `retry-after`/rate-limit extraction downstream. */
|
|
13
|
+
headers?: Headers;
|
|
14
|
+
/** Machine-readable error code from the response body (`error.code` / `error.type`). */
|
|
15
|
+
code?: string;
|
|
16
|
+
cause?: unknown;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Non-2xx HTTP response from a provider endpoint. */
|
|
20
|
+
export class ProviderHttpError extends Error {
|
|
21
|
+
readonly status: number;
|
|
22
|
+
readonly headers: Headers | undefined;
|
|
23
|
+
readonly code: string | undefined;
|
|
24
|
+
|
|
25
|
+
constructor(message: string, status: number, options?: ProviderHttpErrorOptions) {
|
|
26
|
+
super(message, options?.cause === undefined ? undefined : { cause: options.cause });
|
|
27
|
+
this.name = "ProviderHttpError";
|
|
28
|
+
this.status = status;
|
|
29
|
+
this.headers = options?.headers;
|
|
30
|
+
this.code = options?.code;
|
|
31
|
+
}
|
|
32
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
+
export {
|
|
2
|
+
ANTIGRAVITY_SYSTEM_INSTRUCTION,
|
|
3
|
+
getAntigravityUserAgent,
|
|
4
|
+
getGeminiCliHeaders,
|
|
5
|
+
} from "@prometheus-ai/catalog/wire/gemini-headers";
|
|
1
6
|
export { type ZodType, z } from "zod/v4";
|
|
2
7
|
export * from "./api-registry";
|
|
3
8
|
export * from "./auth-broker";
|
|
4
9
|
export { type AuthGatewayBootOptions, type ModelResolver, startAuthGateway } from "./auth-gateway/server";
|
|
5
10
|
export * from "./auth-gateway/types";
|
|
11
|
+
export * from "./auth-retry";
|
|
6
12
|
export * from "./auth-storage";
|
|
7
|
-
export * from "./
|
|
8
|
-
export * from "./model-manager";
|
|
9
|
-
export * from "./model-thinking";
|
|
10
|
-
export * from "./models";
|
|
13
|
+
export * from "./errors";
|
|
11
14
|
export * from "./provider-details";
|
|
12
|
-
export * from "./provider-models";
|
|
13
15
|
export * from "./providers/anthropic";
|
|
14
16
|
export * from "./providers/anthropic-client";
|
|
15
17
|
export * from "./providers/azure-openai-responses";
|
|
@@ -17,7 +19,6 @@ export type * from "./providers/cursor";
|
|
|
17
19
|
export * from "./providers/gitlab-duo";
|
|
18
20
|
export type * from "./providers/google";
|
|
19
21
|
export type * from "./providers/google-gemini-cli";
|
|
20
|
-
export * from "./providers/google-gemini-headers";
|
|
21
22
|
export type * from "./providers/google-vertex";
|
|
22
23
|
export * from "./providers/kimi";
|
|
23
24
|
export * from "./providers/mock";
|
|
@@ -27,6 +28,7 @@ export * from "./providers/openai-completions";
|
|
|
27
28
|
export * from "./providers/openai-responses";
|
|
28
29
|
export * from "./providers/synthetic";
|
|
29
30
|
export * from "./rate-limit-utils";
|
|
31
|
+
export * from "./registry";
|
|
30
32
|
export * from "./stream";
|
|
31
33
|
export * from "./types";
|
|
32
34
|
export * from "./usage";
|
|
@@ -37,17 +39,10 @@ export * from "./usage/google-antigravity";
|
|
|
37
39
|
export * from "./usage/kimi";
|
|
38
40
|
export * from "./usage/minimax-code";
|
|
39
41
|
export * from "./usage/openai-codex";
|
|
42
|
+
export * from "./usage/openai-codex-reset";
|
|
40
43
|
export * from "./usage/zai";
|
|
41
44
|
export * from "./utils/anthropic-auth";
|
|
42
|
-
export * from "./utils/discovery";
|
|
43
45
|
export * from "./utils/event-stream";
|
|
44
|
-
export * from "./utils/oauth";
|
|
45
|
-
export type {
|
|
46
|
-
OAuthCredentials,
|
|
47
|
-
OAuthProvider,
|
|
48
|
-
OAuthProviderId,
|
|
49
|
-
OAuthProviderInfo,
|
|
50
|
-
} from "./utils/oauth/types";
|
|
51
46
|
export * from "./utils/overflow";
|
|
52
47
|
export * from "./utils/retry";
|
|
53
48
|
export * from "./utils/schema";
|
package/src/provider-details.ts
CHANGED
|
@@ -18,7 +18,7 @@ export interface ProviderDetailsContext {
|
|
|
18
18
|
authMode?: string;
|
|
19
19
|
/**
|
|
20
20
|
* Human-readable description of the active credential, e.g.
|
|
21
|
-
* `"broker http://
|
|
21
|
+
* `"broker http://auth-broker.internal:8765 - oauth #5 (foo@bar.com)"`.
|
|
22
22
|
* Rendered as a `Source` field; omitted when undefined.
|
|
23
23
|
*/
|
|
24
24
|
credentialSource?: string;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it } from "bun:test";
|
|
2
|
+
import { Buffer } from "node:buffer";
|
|
3
|
+
import * as fs from "node:fs/promises";
|
|
4
|
+
import * as os from "node:os";
|
|
5
|
+
import * as path from "node:path";
|
|
6
|
+
import type { FetchImpl } from "../../types";
|
|
7
|
+
import { __resetVertexTokenCache, getVertexAccessToken } from "../google-auth";
|
|
8
|
+
|
|
9
|
+
const CLOUD_PLATFORM_SCOPE = "https://www.googleapis.com/auth/cloud-platform";
|
|
10
|
+
const JWT_BEARER_GRANT = "urn:ietf:params:oauth:grant-type:jwt-bearer";
|
|
11
|
+
|
|
12
|
+
/** Generate a real RS256 private key so signJwtRs256 / pemToPkcs8 run for real. */
|
|
13
|
+
async function generateServiceAccountPem(): Promise<string> {
|
|
14
|
+
const keyPair = (await globalThis.crypto.subtle.generateKey(
|
|
15
|
+
{ name: "RSASSA-PKCS1-v1_5", modulusLength: 2048, publicExponent: new Uint8Array([1, 0, 1]), hash: "SHA-256" },
|
|
16
|
+
true,
|
|
17
|
+
["sign", "verify"],
|
|
18
|
+
)) as CryptoKeyPair;
|
|
19
|
+
const pkcs8 = new Uint8Array(await globalThis.crypto.subtle.exportKey("pkcs8", keyPair.privateKey));
|
|
20
|
+
const body = (
|
|
21
|
+
Buffer.from(pkcs8)
|
|
22
|
+
.toString("base64")
|
|
23
|
+
.match(/.{1,64}/g) ?? []
|
|
24
|
+
).join("\n");
|
|
25
|
+
return `-----BEGIN PRIVATE KEY-----\n${body}\n-----END PRIVATE KEY-----\n`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function urlOf(input: string | URL | Request): string {
|
|
29
|
+
if (typeof input === "string") return input;
|
|
30
|
+
if (input instanceof URL) return input.toString();
|
|
31
|
+
return input.url;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
describe("getVertexAccessToken impersonated_service_account ADC", () => {
|
|
35
|
+
let tmpDir: string;
|
|
36
|
+
let originalGac: string | undefined;
|
|
37
|
+
|
|
38
|
+
beforeEach(async () => {
|
|
39
|
+
__resetVertexTokenCache();
|
|
40
|
+
originalGac = Bun.env.GOOGLE_APPLICATION_CREDENTIALS;
|
|
41
|
+
tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "prometheus-vertex-adc-"));
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
afterEach(async () => {
|
|
45
|
+
__resetVertexTokenCache();
|
|
46
|
+
if (originalGac === undefined) delete Bun.env.GOOGLE_APPLICATION_CREDENTIALS;
|
|
47
|
+
else Bun.env.GOOGLE_APPLICATION_CREDENTIALS = originalGac;
|
|
48
|
+
await fs.rm(tmpDir, { recursive: true, force: true });
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("rejects a malformed service_account_impersonation_url before any network call", async () => {
|
|
52
|
+
const adcPath = path.join(tmpDir, "impersonated-bad-url.json");
|
|
53
|
+
await Bun.write(
|
|
54
|
+
adcPath,
|
|
55
|
+
JSON.stringify({
|
|
56
|
+
type: "impersonated_service_account",
|
|
57
|
+
// Missing the trailing ":generateAccessToken" the principal parser requires.
|
|
58
|
+
service_account_impersonation_url:
|
|
59
|
+
"https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/target@project.iam.gserviceaccount.com",
|
|
60
|
+
source_credentials: {
|
|
61
|
+
type: "authorized_user",
|
|
62
|
+
client_id: "client-id",
|
|
63
|
+
client_secret: "client-secret",
|
|
64
|
+
refresh_token: "refresh-token",
|
|
65
|
+
},
|
|
66
|
+
}),
|
|
67
|
+
);
|
|
68
|
+
Bun.env.GOOGLE_APPLICATION_CREDENTIALS = adcPath;
|
|
69
|
+
|
|
70
|
+
const calls: string[] = [];
|
|
71
|
+
const fetchImpl: FetchImpl = async input => {
|
|
72
|
+
calls.push(urlOf(input));
|
|
73
|
+
return new Response("{}");
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// The principal is parsed before the source exchange, so a bad URL must fail
|
|
77
|
+
// up front rather than after burning a source-token round trip.
|
|
78
|
+
await expect(getVertexAccessToken({ fetch: fetchImpl })).rejects.toBeInstanceOf(RangeError);
|
|
79
|
+
expect(calls).toEqual([]);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("signs an RS256 JWT for a service_account source and reconstructs the IAM URL", async () => {
|
|
83
|
+
const pem = await generateServiceAccountPem();
|
|
84
|
+
const adcPath = path.join(tmpDir, "impersonated-sa.json");
|
|
85
|
+
await Bun.write(
|
|
86
|
+
adcPath,
|
|
87
|
+
JSON.stringify({
|
|
88
|
+
type: "impersonated_service_account",
|
|
89
|
+
// Non-canonical project segment proves the request URL is rebuilt, not echoed.
|
|
90
|
+
service_account_impersonation_url:
|
|
91
|
+
"https://iamcredentials.googleapis.com/v1/projects/explicit-proj/serviceAccounts/target@project.iam.gserviceaccount.com:generateAccessToken",
|
|
92
|
+
source_credentials: {
|
|
93
|
+
type: "service_account",
|
|
94
|
+
client_email: "source@project.iam.gserviceaccount.com",
|
|
95
|
+
private_key: pem,
|
|
96
|
+
private_key_id: "key-1",
|
|
97
|
+
},
|
|
98
|
+
// delegates intentionally omitted — the IAM body must default to [].
|
|
99
|
+
}),
|
|
100
|
+
);
|
|
101
|
+
Bun.env.GOOGLE_APPLICATION_CREDENTIALS = adcPath;
|
|
102
|
+
|
|
103
|
+
const calls: { url: string; init?: RequestInit }[] = [];
|
|
104
|
+
const fetchImpl: FetchImpl = async (input, init) => {
|
|
105
|
+
const url = urlOf(input);
|
|
106
|
+
calls.push({ url, init });
|
|
107
|
+
if (url === "https://oauth2.googleapis.com/token") {
|
|
108
|
+
return new Response(JSON.stringify({ access_token: "sa-source-token", expires_in: 3600 }));
|
|
109
|
+
}
|
|
110
|
+
if (url.startsWith("https://iamcredentials.googleapis.com/")) {
|
|
111
|
+
return new Response(
|
|
112
|
+
JSON.stringify({
|
|
113
|
+
accessToken: "impersonated-token",
|
|
114
|
+
expireTime: new Date(Date.now() + 3_600_000).toISOString(),
|
|
115
|
+
}),
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
return new Response("unexpected", { status: 404 });
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const token = await getVertexAccessToken({ fetch: fetchImpl });
|
|
122
|
+
expect(token).toBe("impersonated-token");
|
|
123
|
+
|
|
124
|
+
// Source JWT exchange happens first, then the impersonation exchange.
|
|
125
|
+
expect(calls.map(c => c.url)).toEqual([
|
|
126
|
+
"https://oauth2.googleapis.com/token",
|
|
127
|
+
"https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/target@project.iam.gserviceaccount.com:generateAccessToken",
|
|
128
|
+
]);
|
|
129
|
+
|
|
130
|
+
// Source credential is exchanged via a signed JWT bearer assertion, not a refresh grant.
|
|
131
|
+
const sourceBody = new URLSearchParams(String(calls[0].init?.body));
|
|
132
|
+
expect(sourceBody.get("grant_type")).toBe(JWT_BEARER_GRANT);
|
|
133
|
+
expect((sourceBody.get("assertion") ?? "").split(".")).toHaveLength(3);
|
|
134
|
+
|
|
135
|
+
// The IAM call carries the source-derived bearer token and defaults delegates to [].
|
|
136
|
+
const iamHeaders = calls[1].init?.headers as Record<string, string>;
|
|
137
|
+
expect(iamHeaders.Authorization).toBe("Bearer sa-source-token");
|
|
138
|
+
expect(JSON.parse(String(calls[1].init?.body))).toEqual({
|
|
139
|
+
delegates: [],
|
|
140
|
+
scope: [CLOUD_PLATFORM_SCOPE],
|
|
141
|
+
lifetime: "3600s",
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
});
|
|
@@ -7,10 +7,11 @@
|
|
|
7
7
|
* Bun's native `HTTPS_PROXY` support.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
import type { Effort } from "@prometheus-ai/catalog/effort";
|
|
11
|
+
import { mapEffortToAnthropicAdaptiveEffort, requireSupportedEffort } from "@prometheus-ai/catalog/model-thinking";
|
|
12
|
+
import { calculateCost } from "@prometheus-ai/catalog/models";
|
|
10
13
|
import { $env, $flag, extractHttpStatusFromError, fetchWithRetry } from "@prometheus-ai/utils";
|
|
11
|
-
import
|
|
12
|
-
import { mapEffortToAnthropicAdaptiveEffort, requireSupportedEffort } from "../model-thinking";
|
|
13
|
-
import { calculateCost } from "../models";
|
|
14
|
+
import { ProviderHttpError } from "../errors";
|
|
14
15
|
import type {
|
|
15
16
|
Api,
|
|
16
17
|
AssistantMessage,
|
|
@@ -29,14 +30,20 @@ import type {
|
|
|
29
30
|
} from "../types";
|
|
30
31
|
import { normalizeToolCallId, resolveCacheRetention } from "../utils";
|
|
31
32
|
import { AssistantMessageEventStream } from "../utils/event-stream";
|
|
32
|
-
import { appendRawHttpRequestDumpFor400, type RawHttpRequestDump
|
|
33
|
+
import { appendRawHttpRequestDumpFor400, type RawHttpRequestDump } from "../utils/http-inspector";
|
|
34
|
+
import { getStreamFirstEventTimeoutMs } from "../utils/idle-iterator";
|
|
33
35
|
import { parseStreamingJson, parseStreamingJsonThrottled } from "../utils/json-parse";
|
|
34
36
|
import { toolWireSchema } from "../utils/schema/wire";
|
|
35
|
-
import { resolveAwsCredentials } from "./aws-credentials";
|
|
37
|
+
import { invalidateAwsCredentialCache, resolveAwsCredentials } from "./aws-credentials";
|
|
36
38
|
import { decodeEventStream } from "./aws-eventstream";
|
|
37
39
|
import { signRequest } from "./aws-sigv4";
|
|
38
40
|
import { transformMessages } from "./transform-messages";
|
|
39
41
|
|
|
42
|
+
/** Non-2xx response (or in-stream exception event) from the Bedrock runtime API. */
|
|
43
|
+
export class BedrockApiError extends ProviderHttpError {
|
|
44
|
+
override readonly name = "BedrockApiError";
|
|
45
|
+
}
|
|
46
|
+
|
|
40
47
|
export type BedrockThinkingDisplay = "summarized" | "omitted";
|
|
41
48
|
|
|
42
49
|
export interface BedrockOptions extends StreamOptions {
|
|
@@ -57,11 +64,12 @@ export interface BedrockOptions extends StreamOptions {
|
|
|
57
64
|
* - `"omitted"`: thinking content is suppressed; the encrypted signature still
|
|
58
65
|
* travels back for multi-turn continuity.
|
|
59
66
|
*
|
|
60
|
-
* Starting with Claude Opus 4.7
|
|
61
|
-
* leaves callers waiting on a silent stream during
|
|
62
|
-
* #1373). We default to `"summarized"` so adaptive-
|
|
63
|
-
* the field keep producing visible thinking deltas.
|
|
64
|
-
* models (Opus 4.6, Sonnet 4.6+) reject the field, so
|
|
67
|
+
* Starting with Claude Opus 4.7 and Claude Fable/Mythos 5 the Anthropic API
|
|
68
|
+
* default is `"omitted"`, which leaves callers waiting on a silent stream during
|
|
69
|
+
* long reasoning runs (issue #1373). We default to `"summarized"` so adaptive-
|
|
70
|
+
* thinking models that accept the field keep producing visible thinking deltas.
|
|
71
|
+
* Older adaptive-thinking models (Opus 4.6, Sonnet 4.6+) reject the field, so
|
|
72
|
+
* we omit it for them.
|
|
65
73
|
*/
|
|
66
74
|
thinkingDisplay?: BedrockThinkingDisplay;
|
|
67
75
|
}
|
|
@@ -202,7 +210,10 @@ export const streamBedrock: StreamFunction<"bedrock-converse-stream"> = (
|
|
|
202
210
|
|
|
203
211
|
try {
|
|
204
212
|
const cacheRetention = resolveCacheRetention(options.cacheRetention);
|
|
205
|
-
const
|
|
213
|
+
const historyHasToolBlocks = context.messages.some(
|
|
214
|
+
m => m.role === "toolResult" || (m.role === "assistant" && m.content.some(b => b.type === "toolCall")),
|
|
215
|
+
);
|
|
216
|
+
const toolConfig = convertToolConfig(context.tools, options.toolChoice, historyHasToolBlocks);
|
|
206
217
|
let additionalModelRequestFields = buildAdditionalModelRequestFields(model, options);
|
|
207
218
|
|
|
208
219
|
// Bedrock rejects thinking + forced tool_choice ("any" or specific tool).
|
|
@@ -272,20 +283,41 @@ export const streamBedrock: StreamFunction<"bedrock-converse-stream"> = (
|
|
|
272
283
|
requestHeaders = { ...baseHeaders, ...signed };
|
|
273
284
|
}
|
|
274
285
|
|
|
286
|
+
// Bun's native fetch ceiling is disabled below (`timeout: false`) so
|
|
287
|
+
// configurable watchdogs govern slow-prefill streams (issue #2422).
|
|
288
|
+
// Direct callers that bypass `register-builtins` (which installs the
|
|
289
|
+
// iterator-level first-event watchdog) still need a pre-response
|
|
290
|
+
// timer, otherwise a Bedrock/proxy that accepts the POST and never
|
|
291
|
+
// sends headers would hang forever.
|
|
292
|
+
const firstEventTimeoutMs = options.streamFirstEventTimeoutMs ?? getStreamFirstEventTimeoutMs();
|
|
293
|
+
const preResponseWatchdog =
|
|
294
|
+
firstEventTimeoutMs !== undefined && firstEventTimeoutMs > 0
|
|
295
|
+
? AbortSignal.timeout(firstEventTimeoutMs)
|
|
296
|
+
: undefined;
|
|
297
|
+
const fetchSignal = preResponseWatchdog
|
|
298
|
+
? options.signal
|
|
299
|
+
? AbortSignal.any([options.signal, preResponseWatchdog])
|
|
300
|
+
: preResponseWatchdog
|
|
301
|
+
: options.signal;
|
|
275
302
|
const response = await fetchWithRetry(url, {
|
|
276
303
|
method: "POST",
|
|
277
304
|
headers: requestHeaders,
|
|
278
305
|
body,
|
|
279
|
-
signal:
|
|
306
|
+
signal: fetchSignal,
|
|
280
307
|
fetch: options.fetch,
|
|
308
|
+
timeout: false,
|
|
281
309
|
});
|
|
282
310
|
|
|
283
311
|
if (!response.ok) {
|
|
312
|
+
if (!bearerToken && (response.status === 401 || response.status === 403)) {
|
|
313
|
+
// Stale cached credentials (e.g. rotated session keys in ~/.aws/credentials) —
|
|
314
|
+
// drop the cache entry so the next attempt re-resolves from scratch.
|
|
315
|
+
invalidateAwsCredentialCache({ profile: options.profile, region });
|
|
316
|
+
}
|
|
284
317
|
const errBody = await response.text().catch(() => "");
|
|
285
|
-
throw
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
);
|
|
318
|
+
throw new BedrockApiError(`Bedrock HTTP ${response.status}: ${errBody.slice(0, 1000)}`, response.status, {
|
|
319
|
+
headers: response.headers,
|
|
320
|
+
});
|
|
289
321
|
}
|
|
290
322
|
if (!response.body) throw new Error("Bedrock response has no body");
|
|
291
323
|
|
|
@@ -298,9 +330,10 @@ export const streamBedrock: StreamFunction<"bedrock-converse-stream"> = (
|
|
|
298
330
|
const exceptionType = message.headers[":exception-type"] || "Exception";
|
|
299
331
|
const payload = safeParsePayload(message.payload) as { message?: string } | undefined;
|
|
300
332
|
const errorMessage = payload?.message || new TextDecoder().decode(message.payload);
|
|
301
|
-
const
|
|
302
|
-
|
|
303
|
-
|
|
333
|
+
const text = `${exceptionType}: ${errorMessage}`;
|
|
334
|
+
throw exceptionType === "validationException"
|
|
335
|
+
? new BedrockApiError(text, 400, { code: exceptionType })
|
|
336
|
+
: new Error(text);
|
|
304
337
|
}
|
|
305
338
|
if (messageType === "error") {
|
|
306
339
|
const code = message.headers[":error-code"] || "UnknownError";
|
|
@@ -339,6 +372,9 @@ export const streamBedrock: StreamFunction<"bedrock-converse-stream"> = (
|
|
|
339
372
|
case "messageStop": {
|
|
340
373
|
const ev = payload as MessageStopEvent;
|
|
341
374
|
output.stopReason = mapStopReason(ev.stopReason);
|
|
375
|
+
if (output.stopReason === "error") {
|
|
376
|
+
output.errorMessage = `Generation failed with stop reason: ${ev.stopReason ?? "unknown"}`;
|
|
377
|
+
}
|
|
342
378
|
break;
|
|
343
379
|
}
|
|
344
380
|
case "metadata": {
|
|
@@ -739,8 +775,9 @@ function convertMessages(
|
|
|
739
775
|
function convertToolConfig(
|
|
740
776
|
tools: Tool[] | undefined,
|
|
741
777
|
toolChoice: BedrockOptions["toolChoice"],
|
|
778
|
+
historyHasToolBlocks: boolean,
|
|
742
779
|
): WireToolConfig | undefined {
|
|
743
|
-
if (!tools?.length
|
|
780
|
+
if (!tools?.length) return undefined;
|
|
744
781
|
|
|
745
782
|
const bedrockTools: WireToolSpec[] = tools.map(tool => ({
|
|
746
783
|
toolSpec: {
|
|
@@ -750,6 +787,13 @@ function convertToolConfig(
|
|
|
750
787
|
},
|
|
751
788
|
}));
|
|
752
789
|
|
|
790
|
+
// Bedrock rejects requests whose history contains toolUse/toolResult blocks without a
|
|
791
|
+
// toolConfig. With prior tool use we must keep the tool specs and merely omit the choice
|
|
792
|
+
// (there is no "none" choice on Converse); dropping toolConfig entirely would 400.
|
|
793
|
+
if (toolChoice === "none") {
|
|
794
|
+
return historyHasToolBlocks ? { tools: bedrockTools } : undefined;
|
|
795
|
+
}
|
|
796
|
+
|
|
753
797
|
let bedrockToolChoice: WireToolChoice | undefined;
|
|
754
798
|
switch (toolChoice) {
|
|
755
799
|
case "auto":
|
|
@@ -792,12 +836,13 @@ function buildAdditionalModelRequestFields(
|
|
|
792
836
|
const mode = model.thinking?.mode;
|
|
793
837
|
if (mode === "anthropic-adaptive") {
|
|
794
838
|
const effort = mapEffortToAnthropicAdaptiveEffort(model, reasoning);
|
|
795
|
-
// Starting with Claude Opus 4.7, Anthropic switched
|
|
796
|
-
// default to "omitted", which silently suppresses
|
|
797
|
-
// can read as a stalled stream during long reasoning
|
|
798
|
-
// Opt back into "summarized" by default on models that
|
|
839
|
+
// Starting with Claude Opus 4.7 and Claude Fable/Mythos 5, Anthropic switched
|
|
840
|
+
// the adaptive-thinking default to "omitted", which silently suppresses
|
|
841
|
+
// streamed reasoning and can read as a stalled stream during long reasoning
|
|
842
|
+
// runs (issue #1373). Opt back into "summarized" by default on models that
|
|
843
|
+
// accept the field.
|
|
799
844
|
const adaptive: { type: "adaptive"; display?: BedrockThinkingDisplay } = { type: "adaptive" };
|
|
800
|
-
if (
|
|
845
|
+
if (model.thinking?.supportsDisplay) {
|
|
801
846
|
adaptive.display = options.thinkingDisplay ?? "summarized";
|
|
802
847
|
}
|
|
803
848
|
return {
|
|
@@ -831,21 +876,6 @@ function buildAdditionalModelRequestFields(
|
|
|
831
876
|
return result;
|
|
832
877
|
}
|
|
833
878
|
|
|
834
|
-
/**
|
|
835
|
-
* Adaptive thinking `display` is supported starting with Claude Opus 4.7.
|
|
836
|
-
* Older adaptive-thinking models (Opus 4.6, Sonnet 4.6+) reject the field.
|
|
837
|
-
* Bedrock model ids are prefixed with region/inference-profile slugs (e.g.
|
|
838
|
-
* `eu.anthropic.claude-opus-4-7-...`); the regex matches the `claude-opus-X-Y`
|
|
839
|
-
* fragment regardless of prefix.
|
|
840
|
-
*/
|
|
841
|
-
function supportsAdaptiveThinkingDisplay(modelId: string): boolean {
|
|
842
|
-
const match = /claude-opus-(\d+)-(\d+)/.exec(modelId);
|
|
843
|
-
if (!match) return false;
|
|
844
|
-
const major = Number(match[1]);
|
|
845
|
-
const minor = Number(match[2]);
|
|
846
|
-
return major > 4 || (major === 4 && minor >= 7);
|
|
847
|
-
}
|
|
848
|
-
|
|
849
879
|
/**
|
|
850
880
|
* Bedrock's wire format expects the image as `{ source: { bytes: <base64-string> }, format }`.
|
|
851
881
|
* The caller already passes base64-encoded data, so no decode/re-encode round-trip is needed.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Minimal HTTP client for the Anthropic Messages API.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* the body itself (`buildParams`), and parses SSE frames itself
|
|
4
|
+
* This package builds every request header itself (`buildAnthropicHeaders`),
|
|
5
|
+
* serializes the body itself (`buildParams`), and parses SSE frames itself
|
|
6
6
|
* (`iterateAnthropicEvents`), so the only `@anthropic-ai/sdk` surface this
|
|
7
7
|
* package ever exercised was URL assembly, auth-header injection, bounded
|
|
8
8
|
* retries, the pre-response timeout, and HTTP-error-to-status mapping. This
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
* with up to 25% jitter).
|
|
22
22
|
*/
|
|
23
23
|
import { scheduler } from "node:timers/promises";
|
|
24
|
+
import { ProviderHttpError } from "../errors";
|
|
24
25
|
import type { FetchImpl } from "../types";
|
|
25
26
|
import type { MessageCreateParamsStreaming } from "./anthropic-wire";
|
|
26
27
|
|
|
@@ -43,7 +44,9 @@ export interface AnthropicRequestOptions {
|
|
|
43
44
|
/**
|
|
44
45
|
* Extra `RequestInit` fields merged into every fetch call. Bun extends
|
|
45
46
|
* `RequestInit` with a `tls` option used for the Claude Code TLS profile and
|
|
46
|
-
* Foundry mTLS.
|
|
47
|
+
* Foundry mTLS. Core request fields (`method`, `headers`, `body`, `signal`)
|
|
48
|
+
* are owned by the client and cannot be overridden from here — the timeout
|
|
49
|
+
* controller's signal in particular must always win.
|
|
47
50
|
*/
|
|
48
51
|
export type AnthropicFetchOptions = RequestInit & {
|
|
49
52
|
tls?: {
|
|
@@ -54,6 +57,8 @@ export type AnthropicFetchOptions = RequestInit & {
|
|
|
54
57
|
cert?: string;
|
|
55
58
|
key?: string;
|
|
56
59
|
};
|
|
60
|
+
/** Bun extension: see {@link FetchWithRetryOptions.timeout} — `false` disables Bun's native fetch TTFT timeout (issue #2422). */
|
|
61
|
+
timeout?: number | false;
|
|
57
62
|
};
|
|
58
63
|
|
|
59
64
|
export interface AnthropicClientOptions {
|
|
@@ -71,16 +76,13 @@ export interface AnthropicClientOptions {
|
|
|
71
76
|
}
|
|
72
77
|
|
|
73
78
|
/** Non-2xx response from the Anthropic API. */
|
|
74
|
-
export class AnthropicApiError extends
|
|
75
|
-
readonly
|
|
76
|
-
readonly headers: Headers;
|
|
79
|
+
export class AnthropicApiError extends ProviderHttpError {
|
|
80
|
+
declare readonly headers: Headers;
|
|
77
81
|
readonly requestId: string | null;
|
|
78
82
|
|
|
79
83
|
constructor(status: number, message: string, headers: Headers) {
|
|
80
|
-
super(message);
|
|
84
|
+
super(message, status, { headers });
|
|
81
85
|
this.name = "AnthropicApiError";
|
|
82
|
-
this.status = status;
|
|
83
|
-
this.headers = headers;
|
|
84
86
|
this.requestId = headers.get("request-id");
|
|
85
87
|
}
|
|
86
88
|
|
|
@@ -121,7 +123,7 @@ function shouldRetryResponse(response: Response): boolean {
|
|
|
121
123
|
}
|
|
122
124
|
|
|
123
125
|
/** Server-suggested delay (`retry-after-ms`, then `retry-after` seconds or HTTP date). */
|
|
124
|
-
function retryDelayFromHeaders(headers: Headers | undefined): number | undefined {
|
|
126
|
+
export function retryDelayFromHeaders(headers: Headers | undefined): number | undefined {
|
|
125
127
|
if (!headers) return undefined;
|
|
126
128
|
const retryAfterMs = headers.get("retry-after-ms");
|
|
127
129
|
if (retryAfterMs) {
|
|
@@ -138,7 +140,7 @@ function retryDelayFromHeaders(headers: Headers | undefined): number | undefined
|
|
|
138
140
|
return undefined;
|
|
139
141
|
}
|
|
140
142
|
|
|
141
|
-
function
|
|
143
|
+
export function calculateAnthropicRetryDelayMs(attempt: number): number {
|
|
142
144
|
const sleepSeconds = Math.min(INITIAL_RETRY_DELAY_S * 2 ** attempt, MAX_RETRY_DELAY_S);
|
|
143
145
|
const jitter = 1 - Math.random() * 0.25;
|
|
144
146
|
return sleepSeconds * jitter * 1000;
|
|
@@ -288,11 +290,11 @@ export class AnthropicMessagesClient implements AnthropicMessagesClientLike {
|
|
|
288
290
|
callerSignal?.addEventListener("abort", onAbort, { once: true });
|
|
289
291
|
try {
|
|
290
292
|
return await fetchFn(url, {
|
|
293
|
+
...(this.#options.fetchOptions ?? {}),
|
|
291
294
|
method: "POST",
|
|
292
295
|
headers,
|
|
293
296
|
body,
|
|
294
297
|
signal: controller.signal,
|
|
295
|
-
...(this.#options.fetchOptions ?? {}),
|
|
296
298
|
});
|
|
297
299
|
} catch (error) {
|
|
298
300
|
if (timedOut && !callerSignal?.aborted) throw new AnthropicConnectionTimeoutError();
|
|
@@ -308,7 +310,7 @@ export class AnthropicMessagesClient implements AnthropicMessagesClientLike {
|
|
|
308
310
|
responseHeaders: Headers | undefined,
|
|
309
311
|
signal: AbortSignal | undefined,
|
|
310
312
|
): Promise<void> {
|
|
311
|
-
const delayMs = retryDelayFromHeaders(responseHeaders) ??
|
|
313
|
+
const delayMs = retryDelayFromHeaders(responseHeaders) ?? calculateAnthropicRetryDelayMs(attempt);
|
|
312
314
|
try {
|
|
313
315
|
await scheduler.wait(delayMs, { signal });
|
|
314
316
|
} catch {
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
* `.refine(...)` so the error mentions them explicitly.
|
|
6
6
|
*
|
|
7
7
|
* Used by `anthropic-messages.ts:parseRequest` to validate the inbound JSON
|
|
8
|
-
* before walking it into
|
|
8
|
+
* before walking it into Prometheus AI's canonical `Context`.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import
|
|
11
|
+
import { z } from "zod/v4";
|
|
12
12
|
import type {
|
|
13
13
|
ContentBlockParam,
|
|
14
14
|
ImageBlockParam,
|
|
@@ -19,10 +19,10 @@ import type {
|
|
|
19
19
|
ToolChoice,
|
|
20
20
|
} from "./anthropic-wire";
|
|
21
21
|
|
|
22
|
-
// `cache_control` is accepted and translated to
|
|
22
|
+
// `cache_control` is accepted and translated to Prometheus AI's per-request
|
|
23
23
|
// `cacheRetention` (any `ttl: "1h"` marker upgrades the request to "long";
|
|
24
24
|
// any other ephemeral marker maps to "short"). The walker doesn't try to
|
|
25
|
-
// preserve per-block breakpoints —
|
|
25
|
+
// preserve per-block breakpoints — Prometheus AI's anthropic provider re-applies them
|
|
26
26
|
// against the rebuilt outbound request anyway.
|
|
27
27
|
export const cacheControlSchema = z
|
|
28
28
|
.object({
|
|
@@ -102,7 +102,17 @@ const toolResultBlockSchema = z.object({
|
|
|
102
102
|
// natively understand (server_tool_use, web_search_tool_result, mcp_*,
|
|
103
103
|
// container_upload, code_execution_*, document, …). The walker flattens these
|
|
104
104
|
// to a text placeholder so legitimate Anthropic clients don't get rejected.
|
|
105
|
-
|
|
105
|
+
// Known `type` values are excluded so a malformed known block (e.g.
|
|
106
|
+
// `{type:"text", text: 123}`) fails validation with a clean 400 instead of
|
|
107
|
+
// slipping past the discriminated union and throwing a TypeError downstream.
|
|
108
|
+
function unknownContentBlockSchema(knownTypes: readonly string[]) {
|
|
109
|
+
const known = new Set(knownTypes);
|
|
110
|
+
return z
|
|
111
|
+
.object({
|
|
112
|
+
type: z.string().refine(t => !known.has(t), { message: "malformed known content block" }),
|
|
113
|
+
})
|
|
114
|
+
.loose();
|
|
115
|
+
}
|
|
106
116
|
|
|
107
117
|
// ─── System ────────────────────────────────────────────────────────────────
|
|
108
118
|
|
|
@@ -118,7 +128,7 @@ export const systemSchema = z.union([z.string(), z.array(systemBlockSchema)]).op
|
|
|
118
128
|
|
|
119
129
|
const userContentBlockSchema = z.union([
|
|
120
130
|
z.discriminatedUnion("type", [textBlockSchema, imageBlockSchema, toolResultBlockSchema]),
|
|
121
|
-
unknownContentBlockSchema,
|
|
131
|
+
unknownContentBlockSchema(["text", "image", "tool_result"]),
|
|
122
132
|
]);
|
|
123
133
|
|
|
124
134
|
const assistantContentBlockSchema = z.union([
|
|
@@ -128,7 +138,7 @@ const assistantContentBlockSchema = z.union([
|
|
|
128
138
|
redactedThinkingBlockSchema,
|
|
129
139
|
toolUseBlockSchema,
|
|
130
140
|
]),
|
|
131
|
-
unknownContentBlockSchema,
|
|
141
|
+
unknownContentBlockSchema(["text", "thinking", "redacted_thinking", "tool_use"]),
|
|
132
142
|
]);
|
|
133
143
|
|
|
134
144
|
export const userMessageSchema = z.object({
|