@aryee337/aery-ai 0.2.27 → 0.2.29
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 +2914 -0
- package/README.md +614 -813
- package/package.json +140 -105
- package/src/api-registry.ts +96 -0
- package/src/auth-broker/client.ts +358 -0
- package/src/auth-broker/index.ts +5 -0
- package/src/auth-broker/refresher.ts +117 -0
- package/src/auth-broker/remote-store.ts +623 -0
- package/src/auth-broker/server.ts +644 -0
- package/src/auth-broker/types.ts +127 -0
- package/src/auth-broker/wire-schemas.ts +200 -0
- package/src/auth-gateway/http.ts +194 -0
- package/src/auth-gateway/index.ts +3 -0
- package/src/auth-gateway/server.ts +818 -0
- package/src/auth-gateway/types.ts +143 -0
- package/src/auth-storage.ts +4422 -0
- package/src/index.ts +54 -0
- package/src/model-cache.ts +129 -0
- package/src/model-manager.ts +469 -0
- package/src/model-thinking.ts +782 -0
- package/src/models.json +83530 -0
- package/src/models.json.d.ts +9 -0
- package/src/models.ts +56 -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 +355 -0
- package/src/provider-models/google.ts +88 -0
- package/src/provider-models/index.ts +5 -0
- package/src/provider-models/ollama.ts +153 -0
- package/src/provider-models/openai-compat.ts +2817 -0
- package/src/provider-models/special.ts +67 -0
- package/src/providers/aery-native-client.ts +228 -0
- package/src/providers/aery-native-server.ts +212 -0
- package/src/providers/amazon-bedrock.ts +873 -0
- package/src/providers/anthropic-client.ts +318 -0
- package/src/providers/anthropic-messages-server-schema.ts +243 -0
- package/src/providers/anthropic-messages-server.ts +683 -0
- package/src/providers/anthropic-wire.ts +268 -0
- package/src/providers/anthropic.ts +3094 -0
- package/src/providers/aws-credentials.ts +501 -0
- package/src/providers/aws-eventstream.ts +185 -0
- package/src/providers/aws-sigv4.ts +218 -0
- package/src/providers/azure-openai-responses.ts +361 -0
- package/src/providers/cursor/gen/agent_pb.ts +15274 -0
- package/src/providers/cursor/proto/agent.proto +3526 -0
- package/src/providers/cursor/proto/buf.gen.yaml +6 -0
- package/src/providers/cursor/proto/buf.yaml +17 -0
- package/src/providers/cursor.ts +2621 -0
- package/src/providers/error-message.ts +21 -0
- package/src/providers/github-copilot-headers.ts +140 -0
- package/src/providers/gitlab-duo.ts +372 -0
- package/src/providers/google-auth.ts +252 -0
- package/src/providers/google-gemini-cli.ts +809 -0
- package/src/providers/google-gemini-headers.ts +41 -0
- package/src/providers/google-shared.ts +917 -0
- package/src/providers/google-types.ts +167 -0
- package/src/providers/google-vertex.ts +91 -0
- package/src/providers/google.ts +41 -0
- package/src/providers/grammar.ts +70 -0
- package/src/providers/kimi.ts +52 -0
- package/src/providers/mock.ts +496 -0
- package/src/providers/ollama.ts +644 -0
- package/src/providers/openai-anthropic-shim.ts +138 -0
- package/src/providers/openai-chat-server-schema.ts +252 -0
- package/src/providers/openai-chat-server.ts +647 -0
- package/src/providers/openai-codex/constants.ts +43 -0
- package/src/providers/openai-codex/request-transformer.ts +161 -0
- package/src/providers/openai-codex/response-handler.ts +81 -0
- package/src/providers/openai-codex-responses.ts +3018 -0
- package/src/providers/openai-completions-compat.ts +300 -0
- package/src/providers/openai-completions.ts +1979 -0
- package/src/providers/openai-responses-server-schema.ts +290 -0
- package/src/providers/openai-responses-server.ts +1183 -0
- package/src/providers/openai-responses-shared.ts +873 -0
- package/src/providers/openai-responses.ts +679 -0
- package/src/providers/register-builtins.ts +436 -0
- package/src/providers/synthetic.ts +50 -0
- package/src/providers/transform-messages.ts +382 -0
- package/src/providers/vision-guard.ts +31 -0
- package/src/providers/xai-responses.ts +82 -0
- package/src/rate-limit-utils.ts +84 -0
- package/src/stream.ts +1065 -0
- package/src/types.ts +944 -0
- package/src/usage/claude.ts +482 -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/kimi.ts +271 -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 +185 -0
- package/src/utils/abort.ts +51 -0
- package/src/utils/abortable-iterator.ts +69 -0
- package/src/utils/anthropic-auth.ts +93 -0
- package/src/utils/discovery/antigravity.ts +261 -0
- package/src/utils/discovery/codex.ts +371 -0
- package/src/utils/discovery/cursor.ts +306 -0
- package/src/utils/discovery/gemini.ts +248 -0
- package/src/utils/discovery/index.ts +4 -0
- package/src/utils/discovery/openai-compatible.ts +224 -0
- package/src/utils/event-stream.ts +142 -0
- package/src/utils/fireworks-model-id.ts +30 -0
- package/src/utils/foundry.ts +8 -0
- package/src/utils/http-inspector.ts +176 -0
- package/src/utils/idle-iterator.ts +267 -0
- package/src/utils/json-parse.ts +182 -0
- package/src/utils/oauth/__tests__/xai-oauth.test.ts +107 -0
- package/src/utils/oauth/alibaba-coding-plan.ts +59 -0
- package/src/utils/oauth/anthropic.ts +273 -0
- package/src/utils/oauth/api-key-login.ts +87 -0
- package/src/utils/oauth/api-key-validation.ts +92 -0
- package/src/utils/oauth/callback-server.ts +276 -0
- package/src/utils/oauth/cerebras.ts +16 -0
- package/src/utils/oauth/cloudflare-ai-gateway.ts +48 -0
- package/src/utils/oauth/cursor.ts +157 -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/github-copilot.ts +362 -0
- package/src/utils/oauth/gitlab-duo.ts +123 -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 +484 -0
- package/src/utils/oauth/kagi.ts +47 -0
- package/src/utils/oauth/kilo.ts +87 -0
- package/src/utils/oauth/kimi.ts +254 -0
- package/src/utils/oauth/litellm.ts +47 -0
- package/src/utils/oauth/lm-studio.ts +38 -0
- package/src/utils/oauth/minimax-code.ts +78 -0
- package/src/utils/oauth/moonshot.ts +23 -0
- package/src/utils/oauth/nanogpt.ts +15 -0
- package/src/utils/oauth/nvidia.ts +70 -0
- package/src/utils/oauth/oauth.html +203 -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/openrouter.ts +20 -0
- package/src/utils/oauth/parallel.ts +46 -0
- package/src/utils/oauth/perplexity.ts +206 -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/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.ts +99 -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 +40 -0
- package/src/utils/oauth/wafer.ts +50 -0
- package/src/utils/oauth/xai-oauth.ts +342 -0
- package/src/utils/oauth/xiaomi.ts +139 -0
- package/src/utils/oauth/zai.ts +60 -0
- package/src/utils/oauth/zenmux.ts +15 -0
- package/src/utils/oauth/zhipu.ts +60 -0
- package/src/utils/overflow.ts +137 -0
- package/src/utils/parse-bind.ts +54 -0
- package/src/utils/provider-response.ts +30 -0
- package/src/utils/request-debug.ts +336 -0
- package/src/utils/retry-after.ts +110 -0
- package/src/utils/retry.ts +54 -0
- package/src/utils/schema/CONSTRAINTS.md +164 -0
- package/src/utils/schema/adapt.ts +36 -0
- package/src/utils/schema/compatibility.ts +435 -0
- package/src/utils/schema/dereference.ts +98 -0
- package/src/utils/schema/draft.ts +341 -0
- package/src/utils/schema/equality.ts +97 -0
- package/src/utils/schema/fields.ts +191 -0
- package/src/utils/schema/index.ts +13 -0
- package/src/utils/schema/json-schema-validator.ts +577 -0
- package/src/utils/schema/meta-validator.ts +167 -0
- package/src/utils/schema/normalize.ts +1588 -0
- package/src/utils/schema/spill.ts +43 -0
- package/src/utils/schema/stamps.ts +97 -0
- package/src/utils/schema/types.ts +10 -0
- package/src/utils/schema/wire.ts +293 -0
- package/src/utils/schema/zod-decontaminate.ts +331 -0
- package/src/utils/sdk-stream-timeout.ts +43 -0
- package/src/utils/sse-debug.ts +289 -0
- package/src/utils/stream-markup-healing.ts +612 -0
- package/src/utils/tool-choice.ts +99 -0
- package/src/utils/validation.ts +1024 -0
- package/src/utils.ts +166 -0
- package/dist/api-registry.d.ts +0 -20
- package/dist/api-registry.d.ts.map +0 -1
- package/dist/api-registry.js +0 -44
- package/dist/api-registry.js.map +0 -1
- package/dist/bedrock-provider.d.ts +0 -5
- package/dist/bedrock-provider.d.ts.map +0 -1
- package/dist/bedrock-provider.js +0 -6
- package/dist/bedrock-provider.js.map +0 -1
- package/dist/cli.d.ts +0 -3
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -130
- package/dist/cli.js.map +0 -1
- package/dist/env-api-keys.d.ts +0 -18
- package/dist/env-api-keys.d.ts.map +0 -1
- package/dist/env-api-keys.js +0 -178
- package/dist/env-api-keys.js.map +0 -1
- package/dist/image-models.d.ts +0 -10
- package/dist/image-models.d.ts.map +0 -1
- package/dist/image-models.generated.d.ts +0 -440
- package/dist/image-models.generated.d.ts.map +0 -1
- package/dist/image-models.generated.js +0 -442
- package/dist/image-models.generated.js.map +0 -1
- package/dist/image-models.js +0 -23
- package/dist/image-models.js.map +0 -1
- package/dist/images-api-registry.d.ts +0 -14
- package/dist/images-api-registry.d.ts.map +0 -1
- package/dist/images-api-registry.js +0 -22
- package/dist/images-api-registry.js.map +0 -1
- package/dist/images.d.ts +0 -4
- package/dist/images.d.ts.map +0 -1
- package/dist/images.js +0 -14
- package/dist/images.js.map +0 -1
- package/dist/index.d.ts +0 -32
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -20
- package/dist/index.js.map +0 -1
- package/dist/models.d.ts +0 -18
- package/dist/models.d.ts.map +0 -1
- package/dist/models.generated.d.ts +0 -17707
- package/dist/models.generated.d.ts.map +0 -1
- package/dist/models.generated.js +0 -16561
- package/dist/models.generated.js.map +0 -1
- package/dist/models.js +0 -71
- package/dist/models.js.map +0 -1
- package/dist/oauth.d.ts +0 -2
- package/dist/oauth.d.ts.map +0 -1
- package/dist/oauth.js +0 -2
- package/dist/oauth.js.map +0 -1
- package/dist/providers/aery-error-formatting.d.ts +0 -13
- package/dist/providers/aery-error-formatting.d.ts.map +0 -1
- package/dist/providers/aery-error-formatting.js +0 -112
- package/dist/providers/aery-error-formatting.js.map +0 -1
- package/dist/providers/amazon-bedrock.d.ts +0 -38
- package/dist/providers/amazon-bedrock.d.ts.map +0 -1
- package/dist/providers/amazon-bedrock.js +0 -763
- package/dist/providers/amazon-bedrock.js.map +0 -1
- package/dist/providers/anthropic.d.ts +0 -71
- package/dist/providers/anthropic.d.ts.map +0 -1
- package/dist/providers/anthropic.js +0 -949
- package/dist/providers/anthropic.js.map +0 -1
- package/dist/providers/azure-openai-responses.d.ts +0 -15
- package/dist/providers/azure-openai-responses.d.ts.map +0 -1
- package/dist/providers/azure-openai-responses.js +0 -225
- package/dist/providers/azure-openai-responses.js.map +0 -1
- package/dist/providers/cloudflare.d.ts +0 -13
- package/dist/providers/cloudflare.d.ts.map +0 -1
- package/dist/providers/cloudflare.js +0 -26
- package/dist/providers/cloudflare.js.map +0 -1
- package/dist/providers/faux.d.ts +0 -56
- package/dist/providers/faux.d.ts.map +0 -1
- package/dist/providers/faux.js +0 -368
- package/dist/providers/faux.js.map +0 -1
- package/dist/providers/github-copilot-headers.d.ts +0 -8
- package/dist/providers/github-copilot-headers.d.ts.map +0 -1
- package/dist/providers/github-copilot-headers.js +0 -29
- package/dist/providers/github-copilot-headers.js.map +0 -1
- package/dist/providers/google-gemini-cli.d.ts +0 -74
- package/dist/providers/google-gemini-cli.d.ts.map +0 -1
- package/dist/providers/google-gemini-cli.js +0 -779
- package/dist/providers/google-gemini-cli.js.map +0 -1
- package/dist/providers/google-shared.d.ts +0 -70
- package/dist/providers/google-shared.d.ts.map +0 -1
- package/dist/providers/google-shared.js +0 -329
- package/dist/providers/google-shared.js.map +0 -1
- package/dist/providers/google-vertex.d.ts +0 -15
- package/dist/providers/google-vertex.d.ts.map +0 -1
- package/dist/providers/google-vertex.js +0 -442
- package/dist/providers/google-vertex.js.map +0 -1
- package/dist/providers/google.d.ts +0 -13
- package/dist/providers/google.d.ts.map +0 -1
- package/dist/providers/google.js +0 -400
- package/dist/providers/google.js.map +0 -1
- package/dist/providers/images/openrouter.d.ts +0 -3
- package/dist/providers/images/openrouter.d.ts.map +0 -1
- package/dist/providers/images/openrouter.js +0 -129
- package/dist/providers/images/openrouter.js.map +0 -1
- package/dist/providers/images/register-builtins.d.ts +0 -4
- package/dist/providers/images/register-builtins.d.ts.map +0 -1
- package/dist/providers/images/register-builtins.js +0 -34
- package/dist/providers/images/register-builtins.js.map +0 -1
- package/dist/providers/mistral.d.ts +0 -25
- package/dist/providers/mistral.d.ts.map +0 -1
- package/dist/providers/mistral.js +0 -535
- package/dist/providers/mistral.js.map +0 -1
- package/dist/providers/openai-codex-responses.d.ts +0 -30
- package/dist/providers/openai-codex-responses.d.ts.map +0 -1
- package/dist/providers/openai-codex-responses.js +0 -1090
- package/dist/providers/openai-codex-responses.js.map +0 -1
- package/dist/providers/openai-completions.d.ts +0 -19
- package/dist/providers/openai-completions.d.ts.map +0 -1
- package/dist/providers/openai-completions.js +0 -950
- package/dist/providers/openai-completions.js.map +0 -1
- package/dist/providers/openai-prompt-cache.d.ts +0 -3
- package/dist/providers/openai-prompt-cache.d.ts.map +0 -1
- package/dist/providers/openai-prompt-cache.js +0 -10
- package/dist/providers/openai-prompt-cache.js.map +0 -1
- package/dist/providers/openai-responses-shared.d.ts +0 -18
- package/dist/providers/openai-responses-shared.d.ts.map +0 -1
- package/dist/providers/openai-responses-shared.js +0 -492
- package/dist/providers/openai-responses-shared.js.map +0 -1
- package/dist/providers/openai-responses.d.ts +0 -13
- package/dist/providers/openai-responses.d.ts.map +0 -1
- package/dist/providers/openai-responses.js +0 -237
- package/dist/providers/openai-responses.js.map +0 -1
- package/dist/providers/register-builtins.d.ts +0 -38
- package/dist/providers/register-builtins.d.ts.map +0 -1
- package/dist/providers/register-builtins.js +0 -278
- package/dist/providers/register-builtins.js.map +0 -1
- package/dist/providers/simple-options.d.ts +0 -8
- package/dist/providers/simple-options.d.ts.map +0 -1
- package/dist/providers/simple-options.js +0 -41
- package/dist/providers/simple-options.js.map +0 -1
- package/dist/providers/transform-messages.d.ts +0 -8
- package/dist/providers/transform-messages.d.ts.map +0 -1
- package/dist/providers/transform-messages.js +0 -184
- package/dist/providers/transform-messages.js.map +0 -1
- package/dist/session-resources.d.ts +0 -4
- package/dist/session-resources.d.ts.map +0 -1
- package/dist/session-resources.js +0 -22
- package/dist/session-resources.js.map +0 -1
- package/dist/stream.d.ts +0 -8
- package/dist/stream.d.ts.map +0 -1
- package/dist/stream.js +0 -27
- package/dist/stream.js.map +0 -1
- package/dist/types.d.ts +0 -498
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
- package/dist/utils/diagnostics.d.ts +0 -19
- package/dist/utils/diagnostics.d.ts.map +0 -1
- package/dist/utils/diagnostics.js +0 -25
- package/dist/utils/diagnostics.js.map +0 -1
- package/dist/utils/event-stream.d.ts +0 -21
- package/dist/utils/event-stream.d.ts.map +0 -1
- package/dist/utils/event-stream.js +0 -81
- package/dist/utils/event-stream.js.map +0 -1
- package/dist/utils/hash.d.ts +0 -3
- package/dist/utils/hash.d.ts.map +0 -1
- package/dist/utils/hash.js +0 -14
- package/dist/utils/hash.js.map +0 -1
- package/dist/utils/headers.d.ts +0 -2
- package/dist/utils/headers.d.ts.map +0 -1
- package/dist/utils/headers.js +0 -8
- package/dist/utils/headers.js.map +0 -1
- package/dist/utils/json-parse.d.ts +0 -16
- package/dist/utils/json-parse.d.ts.map +0 -1
- package/dist/utils/json-parse.js +0 -113
- package/dist/utils/json-parse.js.map +0 -1
- package/dist/utils/node-http-proxy.d.ts +0 -10
- package/dist/utils/node-http-proxy.d.ts.map +0 -1
- package/dist/utils/node-http-proxy.js +0 -97
- package/dist/utils/node-http-proxy.js.map +0 -1
- package/dist/utils/oauth/anthropic.d.ts +0 -25
- package/dist/utils/oauth/anthropic.d.ts.map +0 -1
- package/dist/utils/oauth/anthropic.js +0 -335
- package/dist/utils/oauth/anthropic.js.map +0 -1
- package/dist/utils/oauth/device-code.d.ts +0 -19
- package/dist/utils/oauth/device-code.d.ts.map +0 -1
- package/dist/utils/oauth/device-code.js +0 -55
- package/dist/utils/oauth/device-code.js.map +0 -1
- package/dist/utils/oauth/github-copilot.d.ts +0 -30
- package/dist/utils/oauth/github-copilot.d.ts.map +0 -1
- package/dist/utils/oauth/github-copilot.js +0 -268
- package/dist/utils/oauth/github-copilot.js.map +0 -1
- package/dist/utils/oauth/google-antigravity.d.ts +0 -26
- package/dist/utils/oauth/google-antigravity.d.ts.map +0 -1
- package/dist/utils/oauth/google-antigravity.js +0 -377
- package/dist/utils/oauth/google-antigravity.js.map +0 -1
- package/dist/utils/oauth/google-gemini-cli.d.ts +0 -26
- package/dist/utils/oauth/google-gemini-cli.d.ts.map +0 -1
- package/dist/utils/oauth/google-gemini-cli.js +0 -482
- package/dist/utils/oauth/google-gemini-cli.js.map +0 -1
- package/dist/utils/oauth/index.d.ts +0 -63
- package/dist/utils/oauth/index.d.ts.map +0 -1
- package/dist/utils/oauth/index.js +0 -131
- package/dist/utils/oauth/index.js.map +0 -1
- package/dist/utils/oauth/oauth-page.d.ts +0 -3
- package/dist/utils/oauth/oauth-page.d.ts.map +0 -1
- package/dist/utils/oauth/oauth-page.js +0 -105
- package/dist/utils/oauth/oauth-page.js.map +0 -1
- package/dist/utils/oauth/openai-codex.d.ts +0 -34
- package/dist/utils/oauth/openai-codex.d.ts.map +0 -1
- package/dist/utils/oauth/openai-codex.js +0 -385
- package/dist/utils/oauth/openai-codex.js.map +0 -1
- package/dist/utils/oauth/pkce.d.ts +0 -13
- package/dist/utils/oauth/pkce.d.ts.map +0 -1
- package/dist/utils/oauth/pkce.js +0 -31
- package/dist/utils/oauth/pkce.js.map +0 -1
- package/dist/utils/oauth/types.d.ts +0 -64
- package/dist/utils/oauth/types.d.ts.map +0 -1
- package/dist/utils/oauth/types.js +0 -2
- package/dist/utils/oauth/types.js.map +0 -1
- package/dist/utils/overflow.d.ts +0 -56
- package/dist/utils/overflow.d.ts.map +0 -1
- package/dist/utils/overflow.js +0 -151
- package/dist/utils/overflow.js.map +0 -1
- package/dist/utils/sanitize-unicode.d.ts +0 -22
- package/dist/utils/sanitize-unicode.d.ts.map +0 -1
- package/dist/utils/sanitize-unicode.js +0 -26
- package/dist/utils/sanitize-unicode.js.map +0 -1
- package/dist/utils/typebox-helpers.d.ts +0 -17
- package/dist/utils/typebox-helpers.d.ts.map +0 -1
- package/dist/utils/typebox-helpers.js +0 -21
- package/dist/utils/typebox-helpers.js.map +0 -1
- package/dist/utils/validation.d.ts +0 -18
- package/dist/utils/validation.d.ts.map +0 -1
- package/dist/utils/validation.js +0 -281
- package/dist/utils/validation.js.map +0 -1
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal HTTP client for the Anthropic Messages API.
|
|
3
|
+
*
|
|
4
|
+
* aery-ai builds every request header itself (`buildAnthropicHeaders`), serializes
|
|
5
|
+
* the body itself (`buildParams`), and parses SSE frames itself
|
|
6
|
+
* (`iterateAnthropicEvents`), so the only `@anthropic-ai/sdk` surface this
|
|
7
|
+
* package ever exercised was URL assembly, auth-header injection, bounded
|
|
8
|
+
* retries, the pre-response timeout, and HTTP-error-to-status mapping. This
|
|
9
|
+
* module implements exactly that surface and nothing else.
|
|
10
|
+
*
|
|
11
|
+
* Behavioral contract (kept compatible with the SDK so downstream error
|
|
12
|
+
* classification keeps working):
|
|
13
|
+
* - Non-2xx responses throw {@link AnthropicApiError} whose `status` property
|
|
14
|
+
* carries the HTTP status and whose message is `"<status> <body>"`.
|
|
15
|
+
* - Pre-response timeouts throw {@link AnthropicConnectionTimeoutError}
|
|
16
|
+
* ("Request timed out.").
|
|
17
|
+
* - Caller aborts throw an `Error` with message "Request was aborted.".
|
|
18
|
+
* - Retries: connection errors and 408/409/429/5xx (or `x-should-retry: true`)
|
|
19
|
+
* are retried up to `maxRetries` times, honoring `retry-after-ms` /
|
|
20
|
+
* `retry-after`, otherwise exponential backoff (0.5s * 2^n, capped at 8s,
|
|
21
|
+
* with up to 25% jitter).
|
|
22
|
+
*/
|
|
23
|
+
import { scheduler } from "node:timers/promises";
|
|
24
|
+
import type { FetchImpl } from "../types";
|
|
25
|
+
import type { MessageCreateParamsStreaming } from "./anthropic-wire";
|
|
26
|
+
|
|
27
|
+
/** Default pre-response timeout, matching the SDK's 10-minute default. */
|
|
28
|
+
const DEFAULT_TIMEOUT_MS = 600_000;
|
|
29
|
+
/** Default retry budget, matching the SDK's default. */
|
|
30
|
+
const DEFAULT_MAX_RETRIES = 2;
|
|
31
|
+
const INITIAL_RETRY_DELAY_S = 0.5;
|
|
32
|
+
const MAX_RETRY_DELAY_S = 8;
|
|
33
|
+
|
|
34
|
+
/** Per-request options accepted by {@link AnthropicMessages.create}. */
|
|
35
|
+
export interface AnthropicRequestOptions {
|
|
36
|
+
signal?: AbortSignal;
|
|
37
|
+
/** Pre-response timeout in milliseconds. */
|
|
38
|
+
timeout?: number;
|
|
39
|
+
/** Per-request retry budget override. */
|
|
40
|
+
maxRetries?: number;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Extra `RequestInit` fields merged into every fetch call. Bun extends
|
|
45
|
+
* `RequestInit` with a `tls` option used for the Claude Code TLS profile and
|
|
46
|
+
* Foundry mTLS.
|
|
47
|
+
*/
|
|
48
|
+
export type AnthropicFetchOptions = RequestInit & {
|
|
49
|
+
tls?: {
|
|
50
|
+
rejectUnauthorized?: boolean;
|
|
51
|
+
serverName?: string;
|
|
52
|
+
ciphers?: string;
|
|
53
|
+
ca?: string | string[];
|
|
54
|
+
cert?: string;
|
|
55
|
+
key?: string;
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export interface AnthropicClientOptions {
|
|
60
|
+
/** Sent as `X-Api-Key` unless the header is already present in `defaultHeaders`. */
|
|
61
|
+
apiKey?: string | null;
|
|
62
|
+
/** Sent as `Authorization: Bearer <token>` unless the header is already present in `defaultHeaders`. */
|
|
63
|
+
authToken?: string | null;
|
|
64
|
+
baseURL?: string | null;
|
|
65
|
+
maxRetries?: number;
|
|
66
|
+
/** Pre-response timeout in milliseconds. Defaults to 10 minutes. */
|
|
67
|
+
timeout?: number;
|
|
68
|
+
defaultHeaders?: Record<string, string>;
|
|
69
|
+
fetch?: FetchImpl;
|
|
70
|
+
fetchOptions?: AnthropicFetchOptions;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Non-2xx response from the Anthropic API. */
|
|
74
|
+
export class AnthropicApiError extends Error {
|
|
75
|
+
readonly status: number;
|
|
76
|
+
readonly headers: Headers;
|
|
77
|
+
readonly requestId: string | null;
|
|
78
|
+
|
|
79
|
+
constructor(status: number, message: string, headers: Headers) {
|
|
80
|
+
super(message);
|
|
81
|
+
this.name = "AnthropicApiError";
|
|
82
|
+
this.status = status;
|
|
83
|
+
this.headers = headers;
|
|
84
|
+
this.requestId = headers.get("request-id");
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
static async fromResponse(response: Response): Promise<AnthropicApiError> {
|
|
88
|
+
const body = await response.text().catch(() => "");
|
|
89
|
+
const detail = body.trim() || "status code (no body)";
|
|
90
|
+
return new AnthropicApiError(response.status, `${response.status} ${detail}`, response.headers);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Network-level failure (DNS, TLS, socket reset) after retries were exhausted. */
|
|
95
|
+
export class AnthropicConnectionError extends Error {
|
|
96
|
+
constructor(cause: unknown) {
|
|
97
|
+
super("Connection error.", { cause });
|
|
98
|
+
this.name = "AnthropicConnectionError";
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** No response headers arrived within the configured request timeout. */
|
|
103
|
+
export class AnthropicConnectionTimeoutError extends Error {
|
|
104
|
+
constructor() {
|
|
105
|
+
super("Request timed out.");
|
|
106
|
+
this.name = "AnthropicConnectionTimeoutError";
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function createAbortError(): Error {
|
|
111
|
+
return new Error("Request was aborted.");
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** `x-should-retry` override, then 408/409/429/5xx. */
|
|
115
|
+
function shouldRetryResponse(response: Response): boolean {
|
|
116
|
+
const shouldRetryHeader = response.headers.get("x-should-retry");
|
|
117
|
+
if (shouldRetryHeader === "true") return true;
|
|
118
|
+
if (shouldRetryHeader === "false") return false;
|
|
119
|
+
const status = response.status;
|
|
120
|
+
return status === 408 || status === 409 || status === 429 || status >= 500;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Server-suggested delay (`retry-after-ms`, then `retry-after` seconds or HTTP date). */
|
|
124
|
+
function retryDelayFromHeaders(headers: Headers | undefined): number | undefined {
|
|
125
|
+
if (!headers) return undefined;
|
|
126
|
+
const retryAfterMs = headers.get("retry-after-ms");
|
|
127
|
+
if (retryAfterMs) {
|
|
128
|
+
const ms = Number.parseFloat(retryAfterMs);
|
|
129
|
+
if (Number.isFinite(ms) && ms >= 0) return ms;
|
|
130
|
+
}
|
|
131
|
+
const retryAfter = headers.get("retry-after");
|
|
132
|
+
if (retryAfter) {
|
|
133
|
+
const seconds = Number.parseFloat(retryAfter);
|
|
134
|
+
if (Number.isFinite(seconds) && seconds >= 0) return seconds * 1000;
|
|
135
|
+
const dateMs = Date.parse(retryAfter) - Date.now();
|
|
136
|
+
if (Number.isFinite(dateMs) && dateMs >= 0) return dateMs;
|
|
137
|
+
}
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function defaultRetryDelayMs(attempt: number): number {
|
|
142
|
+
const sleepSeconds = Math.min(INITIAL_RETRY_DELAY_S * 2 ** attempt, MAX_RETRY_DELAY_S);
|
|
143
|
+
const jitter = 1 - Math.random() * 0.25;
|
|
144
|
+
return sleepSeconds * jitter * 1000;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function hasHeaderCaseInsensitive(headers: Record<string, string>, lowerName: string): boolean {
|
|
148
|
+
for (const key in headers) {
|
|
149
|
+
if (key.toLowerCase() === lowerName) return true;
|
|
150
|
+
}
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Lazy in-flight request handle. The HTTP request starts on the first
|
|
156
|
+
* `asResponse()` call; subsequent calls return the same promise.
|
|
157
|
+
*
|
|
158
|
+
* Shape-compatible with the SDK's `APIPromise.asResponse()` so
|
|
159
|
+
* `getAnthropicStreamResponse` treats internal and injected clients uniformly.
|
|
160
|
+
*/
|
|
161
|
+
export class AnthropicApiRequest {
|
|
162
|
+
#start: () => Promise<Response>;
|
|
163
|
+
#response: Promise<Response> | undefined;
|
|
164
|
+
|
|
165
|
+
constructor(start: () => Promise<Response>) {
|
|
166
|
+
this.#start = start;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
asResponse(): Promise<Response> {
|
|
170
|
+
this.#response ??= this.#start();
|
|
171
|
+
return this.#response;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* `messages` resource. `create` lives on the prototype so tests can intercept
|
|
177
|
+
* every outgoing request with `vi.spyOn(AnthropicMessages.prototype, "create")`.
|
|
178
|
+
*/
|
|
179
|
+
export class AnthropicMessages {
|
|
180
|
+
#client: AnthropicMessagesClient;
|
|
181
|
+
#path: string;
|
|
182
|
+
|
|
183
|
+
constructor(client: AnthropicMessagesClient, path: string) {
|
|
184
|
+
this.#client = client;
|
|
185
|
+
this.#path = path;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
create(params: MessageCreateParamsStreaming, options?: AnthropicRequestOptions): AnthropicApiRequest {
|
|
189
|
+
return this.#client.request(this.#path, params, options);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Structural interface satisfied by both {@link AnthropicMessagesClient} and
|
|
195
|
+
* SDK-style clients (e.g. `AnthropicVertex`), so callers can inject an
|
|
196
|
+
* alternative Messages-API client via `AnthropicOptions.client`.
|
|
197
|
+
*/
|
|
198
|
+
export interface AnthropicMessagesClientLike {
|
|
199
|
+
messages: { create(params: MessageCreateParamsStreaming, options?: AnthropicRequestOptions): unknown };
|
|
200
|
+
beta?: { messages: { create(params: MessageCreateParamsStreaming, options?: AnthropicRequestOptions): unknown } };
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export class AnthropicMessagesClient implements AnthropicMessagesClientLike {
|
|
204
|
+
readonly messages: AnthropicMessages;
|
|
205
|
+
readonly beta: { readonly messages: AnthropicMessages };
|
|
206
|
+
#options: AnthropicClientOptions;
|
|
207
|
+
|
|
208
|
+
constructor(options: AnthropicClientOptions) {
|
|
209
|
+
this.#options = options;
|
|
210
|
+
this.messages = new AnthropicMessages(this, "/v1/messages");
|
|
211
|
+
this.beta = { messages: new AnthropicMessages(this, "/v1/messages?beta=true") };
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
request(path: string, params: MessageCreateParamsStreaming, options?: AnthropicRequestOptions): AnthropicApiRequest {
|
|
215
|
+
return new AnthropicApiRequest(() => this.#send(path, params, options));
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
#buildHeaders(): Record<string, string> {
|
|
219
|
+
const opts = this.#options;
|
|
220
|
+
const defaults = opts.defaultHeaders ?? {};
|
|
221
|
+
const headers: Record<string, string> = {};
|
|
222
|
+
if (opts.apiKey != null && !hasHeaderCaseInsensitive(defaults, "x-api-key")) {
|
|
223
|
+
headers["X-Api-Key"] = opts.apiKey;
|
|
224
|
+
}
|
|
225
|
+
if (opts.authToken != null && !hasHeaderCaseInsensitive(defaults, "authorization")) {
|
|
226
|
+
headers.Authorization = `Bearer ${opts.authToken}`;
|
|
227
|
+
}
|
|
228
|
+
Object.assign(headers, defaults);
|
|
229
|
+
return headers;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
async #send(
|
|
233
|
+
path: string,
|
|
234
|
+
params: MessageCreateParamsStreaming,
|
|
235
|
+
options?: AnthropicRequestOptions,
|
|
236
|
+
): Promise<Response> {
|
|
237
|
+
const opts = this.#options;
|
|
238
|
+
const fetchFn: FetchImpl = opts.fetch ?? fetch;
|
|
239
|
+
const callerSignal = options?.signal;
|
|
240
|
+
const timeoutMs = options?.timeout ?? opts.timeout ?? DEFAULT_TIMEOUT_MS;
|
|
241
|
+
const maxRetries = Math.max(0, options?.maxRetries ?? opts.maxRetries ?? DEFAULT_MAX_RETRIES);
|
|
242
|
+
const url = `${opts.baseURL ?? "https://api.anthropic.com"}${path}`;
|
|
243
|
+
const headers = this.#buildHeaders();
|
|
244
|
+
const body = JSON.stringify(params);
|
|
245
|
+
|
|
246
|
+
for (let attempt = 0; ; attempt++) {
|
|
247
|
+
if (callerSignal?.aborted) throw createAbortError();
|
|
248
|
+
|
|
249
|
+
let response: Response;
|
|
250
|
+
try {
|
|
251
|
+
response = await this.#fetchOnce(fetchFn, url, headers, body, timeoutMs, callerSignal);
|
|
252
|
+
} catch (error) {
|
|
253
|
+
if (callerSignal?.aborted) throw createAbortError();
|
|
254
|
+
if (attempt < maxRetries) {
|
|
255
|
+
await this.#backoff(attempt, undefined, callerSignal);
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
if (error instanceof AnthropicConnectionTimeoutError) throw error;
|
|
259
|
+
throw new AnthropicConnectionError(error);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (response.ok) return response;
|
|
263
|
+
|
|
264
|
+
if (attempt < maxRetries && shouldRetryResponse(response)) {
|
|
265
|
+
await response.body?.cancel().catch(() => {});
|
|
266
|
+
await this.#backoff(attempt, response.headers, callerSignal);
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
throw await AnthropicApiError.fromResponse(response);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
async #fetchOnce(
|
|
274
|
+
fetchFn: FetchImpl,
|
|
275
|
+
url: string,
|
|
276
|
+
headers: Record<string, string>,
|
|
277
|
+
body: string,
|
|
278
|
+
timeoutMs: number,
|
|
279
|
+
callerSignal: AbortSignal | undefined,
|
|
280
|
+
): Promise<Response> {
|
|
281
|
+
const controller = new AbortController();
|
|
282
|
+
let timedOut = false;
|
|
283
|
+
const timer = setTimeout(() => {
|
|
284
|
+
timedOut = true;
|
|
285
|
+
controller.abort();
|
|
286
|
+
}, timeoutMs);
|
|
287
|
+
const onAbort = () => controller.abort();
|
|
288
|
+
callerSignal?.addEventListener("abort", onAbort, { once: true });
|
|
289
|
+
try {
|
|
290
|
+
return await fetchFn(url, {
|
|
291
|
+
method: "POST",
|
|
292
|
+
headers,
|
|
293
|
+
body,
|
|
294
|
+
signal: controller.signal,
|
|
295
|
+
...(this.#options.fetchOptions ?? {}),
|
|
296
|
+
});
|
|
297
|
+
} catch (error) {
|
|
298
|
+
if (timedOut && !callerSignal?.aborted) throw new AnthropicConnectionTimeoutError();
|
|
299
|
+
throw error;
|
|
300
|
+
} finally {
|
|
301
|
+
clearTimeout(timer);
|
|
302
|
+
callerSignal?.removeEventListener("abort", onAbort);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
async #backoff(
|
|
307
|
+
attempt: number,
|
|
308
|
+
responseHeaders: Headers | undefined,
|
|
309
|
+
signal: AbortSignal | undefined,
|
|
310
|
+
): Promise<void> {
|
|
311
|
+
const delayMs = retryDelayFromHeaders(responseHeaders) ?? defaultRetryDelayMs(attempt);
|
|
312
|
+
try {
|
|
313
|
+
await scheduler.wait(delayMs, { signal });
|
|
314
|
+
} catch {
|
|
315
|
+
throw createAbortError();
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zod schemas for the Anthropic Messages API request shape we accept on the
|
|
3
|
+
* gateway. Mirrors https://docs.anthropic.com/en/api/messages — only the
|
|
4
|
+
* shapes the gateway actually understands; unsupported fields are caught with
|
|
5
|
+
* `.refine(...)` so the error mentions them explicitly.
|
|
6
|
+
*
|
|
7
|
+
* Used by `anthropic-messages.ts:parseRequest` to validate the inbound JSON
|
|
8
|
+
* before walking it into aery-ai's canonical `Context`.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import * as z from "zod/v4";
|
|
12
|
+
import type {
|
|
13
|
+
ContentBlockParam,
|
|
14
|
+
ImageBlockParam,
|
|
15
|
+
MessageCreateParams,
|
|
16
|
+
MessageParam,
|
|
17
|
+
TextBlockParam,
|
|
18
|
+
Tool,
|
|
19
|
+
ToolChoice,
|
|
20
|
+
} from "./anthropic-wire";
|
|
21
|
+
|
|
22
|
+
// `cache_control` is accepted and translated to aery-ai's per-request
|
|
23
|
+
// `cacheRetention` (any `ttl: "1h"` marker upgrades the request to "long";
|
|
24
|
+
// any other ephemeral marker maps to "short"). The walker doesn't try to
|
|
25
|
+
// preserve per-block breakpoints — aery-ai's anthropic provider re-applies them
|
|
26
|
+
// against the rebuilt outbound request anyway.
|
|
27
|
+
export const cacheControlSchema = z
|
|
28
|
+
.object({
|
|
29
|
+
type: z.literal("ephemeral"),
|
|
30
|
+
ttl: z.union([z.literal("1h"), z.literal("5m")]).optional(),
|
|
31
|
+
})
|
|
32
|
+
.loose();
|
|
33
|
+
|
|
34
|
+
// ─── Sources / inner shapes ─────────────────────────────────────────────────
|
|
35
|
+
|
|
36
|
+
export const base64ImageSourceSchema = z.object({
|
|
37
|
+
type: z.literal("base64"),
|
|
38
|
+
data: z.string().min(1),
|
|
39
|
+
media_type: z.string().min(1),
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
export const urlImageSourceSchema = z.object({
|
|
43
|
+
type: z.literal("url"),
|
|
44
|
+
url: z.url(),
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
export const fileImageSourceSchema = z.object({
|
|
48
|
+
type: z.literal("file"),
|
|
49
|
+
file_id: z.string().min(1),
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
export const imageSourceSchema = z.discriminatedUnion("type", [
|
|
53
|
+
base64ImageSourceSchema,
|
|
54
|
+
urlImageSourceSchema,
|
|
55
|
+
fileImageSourceSchema,
|
|
56
|
+
]);
|
|
57
|
+
|
|
58
|
+
const textBlockSchema = z.object({
|
|
59
|
+
type: z.literal("text"),
|
|
60
|
+
text: z.string(),
|
|
61
|
+
cache_control: cacheControlSchema.optional(),
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const imageBlockSchema = z.object({
|
|
65
|
+
type: z.literal("image"),
|
|
66
|
+
source: imageSourceSchema,
|
|
67
|
+
cache_control: cacheControlSchema.optional(),
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const thinkingBlockSchema = z.object({
|
|
71
|
+
type: z.literal("thinking"),
|
|
72
|
+
thinking: z.string(),
|
|
73
|
+
signature: z.string().optional(),
|
|
74
|
+
cache_control: cacheControlSchema.optional(),
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const redactedThinkingBlockSchema = z.object({
|
|
78
|
+
type: z.literal("redacted_thinking"),
|
|
79
|
+
data: z.string(),
|
|
80
|
+
cache_control: cacheControlSchema.optional(),
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const toolUseBlockSchema = z.object({
|
|
84
|
+
type: z.literal("tool_use"),
|
|
85
|
+
id: z.string().min(1),
|
|
86
|
+
name: z.string().min(1),
|
|
87
|
+
input: z.record(z.string(), z.unknown()).optional(),
|
|
88
|
+
cache_control: cacheControlSchema.optional(),
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const toolResultContentBlockSchema = z.discriminatedUnion("type", [textBlockSchema, imageBlockSchema]);
|
|
92
|
+
|
|
93
|
+
const toolResultBlockSchema = z.object({
|
|
94
|
+
type: z.literal("tool_result"),
|
|
95
|
+
tool_use_id: z.string().min(1),
|
|
96
|
+
content: z.union([z.string(), z.array(toolResultContentBlockSchema)]).optional(),
|
|
97
|
+
is_error: z.boolean().optional(),
|
|
98
|
+
cache_control: cacheControlSchema.optional(),
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// Catch-all for content block variants Anthropic ships that the gateway doesn't
|
|
102
|
+
// natively understand (server_tool_use, web_search_tool_result, mcp_*,
|
|
103
|
+
// container_upload, code_execution_*, document, …). The walker flattens these
|
|
104
|
+
// to a text placeholder so legitimate Anthropic clients don't get rejected.
|
|
105
|
+
const unknownContentBlockSchema = z.object({ type: z.string() }).loose();
|
|
106
|
+
|
|
107
|
+
// ─── System ────────────────────────────────────────────────────────────────
|
|
108
|
+
|
|
109
|
+
const systemBlockSchema = z.object({
|
|
110
|
+
type: z.literal("text"),
|
|
111
|
+
text: z.string(),
|
|
112
|
+
cache_control: cacheControlSchema.optional(),
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
export const systemSchema = z.union([z.string(), z.array(systemBlockSchema)]).optional();
|
|
116
|
+
|
|
117
|
+
// ─── Messages ──────────────────────────────────────────────────────────────
|
|
118
|
+
|
|
119
|
+
const userContentBlockSchema = z.union([
|
|
120
|
+
z.discriminatedUnion("type", [textBlockSchema, imageBlockSchema, toolResultBlockSchema]),
|
|
121
|
+
unknownContentBlockSchema,
|
|
122
|
+
]);
|
|
123
|
+
|
|
124
|
+
const assistantContentBlockSchema = z.union([
|
|
125
|
+
z.discriminatedUnion("type", [
|
|
126
|
+
textBlockSchema,
|
|
127
|
+
thinkingBlockSchema,
|
|
128
|
+
redactedThinkingBlockSchema,
|
|
129
|
+
toolUseBlockSchema,
|
|
130
|
+
]),
|
|
131
|
+
unknownContentBlockSchema,
|
|
132
|
+
]);
|
|
133
|
+
|
|
134
|
+
export const userMessageSchema = z.object({
|
|
135
|
+
role: z.literal("user"),
|
|
136
|
+
content: z.union([z.string(), z.array(userContentBlockSchema)]),
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
export const assistantMessageSchema = z.object({
|
|
140
|
+
role: z.literal("assistant"),
|
|
141
|
+
content: z.union([z.string(), z.array(assistantContentBlockSchema)]),
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
export const messageSchema = z.discriminatedUnion("role", [userMessageSchema, assistantMessageSchema]);
|
|
145
|
+
|
|
146
|
+
// ─── Tools ─────────────────────────────────────────────────────────────────
|
|
147
|
+
|
|
148
|
+
export const toolSchema = z.object({
|
|
149
|
+
name: z.string().min(1),
|
|
150
|
+
description: z.string().optional(),
|
|
151
|
+
input_schema: z.record(z.string(), z.unknown()),
|
|
152
|
+
cache_control: cacheControlSchema.optional(),
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// ─── Tool choice ───────────────────────────────────────────────────────────
|
|
156
|
+
|
|
157
|
+
// `disable_parallel_tool_use` is accepted on every variant; the walker maps it
|
|
158
|
+
// onto `options.parallelToolCalls = !disable_parallel_tool_use`.
|
|
159
|
+
export const toolChoiceSchema = z.discriminatedUnion("type", [
|
|
160
|
+
z.object({ type: z.literal("auto"), disable_parallel_tool_use: z.boolean().optional() }),
|
|
161
|
+
z.object({ type: z.literal("any"), disable_parallel_tool_use: z.boolean().optional() }),
|
|
162
|
+
z.object({ type: z.literal("none"), disable_parallel_tool_use: z.boolean().optional() }),
|
|
163
|
+
z.object({
|
|
164
|
+
type: z.literal("tool"),
|
|
165
|
+
name: z.string().min(1),
|
|
166
|
+
disable_parallel_tool_use: z.boolean().optional(),
|
|
167
|
+
}),
|
|
168
|
+
]);
|
|
169
|
+
|
|
170
|
+
// ─── Thinking ──────────────────────────────────────────────────────────────
|
|
171
|
+
|
|
172
|
+
// Anthropic's three thinking shapes. `enabled` requires a budget; `disabled`
|
|
173
|
+
// suppresses reasoning even on models that default it on; `adaptive` lets the
|
|
174
|
+
// provider pick the budget on the fly. Extra hints (`display: "omitted"`, …)
|
|
175
|
+
// are accepted but ignored on the translate path.
|
|
176
|
+
export const thinkingConfigSchema = z.discriminatedUnion("type", [
|
|
177
|
+
z.object({
|
|
178
|
+
type: z.literal("enabled"),
|
|
179
|
+
budget_tokens: z.number(),
|
|
180
|
+
display: z.unknown().optional(),
|
|
181
|
+
}),
|
|
182
|
+
z.object({
|
|
183
|
+
type: z.literal("disabled"),
|
|
184
|
+
display: z.unknown().optional(),
|
|
185
|
+
}),
|
|
186
|
+
z.object({
|
|
187
|
+
type: z.literal("adaptive"),
|
|
188
|
+
budget_tokens: z.number().optional(),
|
|
189
|
+
display: z.unknown().optional(),
|
|
190
|
+
}),
|
|
191
|
+
]);
|
|
192
|
+
|
|
193
|
+
const taskBudgetSchema = z.object({
|
|
194
|
+
type: z.literal("tokens"),
|
|
195
|
+
total: z.number(),
|
|
196
|
+
remaining: z.number().optional(),
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
const outputConfigSchema = z.object({
|
|
200
|
+
effort: z.enum(["low", "medium", "high", "xhigh", "max"]).optional(),
|
|
201
|
+
task_budget: taskBudgetSchema.optional(),
|
|
202
|
+
format: z.unknown().optional(),
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
// ─── Top-level request ─────────────────────────────────────────────────────
|
|
206
|
+
|
|
207
|
+
export const anthropicMessagesRequestSchema = z.object({
|
|
208
|
+
model: z.string().min(1),
|
|
209
|
+
messages: z.array(messageSchema),
|
|
210
|
+
max_tokens: z.number(),
|
|
211
|
+
system: systemSchema,
|
|
212
|
+
tools: z.array(toolSchema).optional(),
|
|
213
|
+
tool_choice: toolChoiceSchema.optional(),
|
|
214
|
+
temperature: z.number().optional(),
|
|
215
|
+
top_p: z.number().optional(),
|
|
216
|
+
top_k: z.number().optional(),
|
|
217
|
+
stop_sequences: z.array(z.string()).optional(),
|
|
218
|
+
stream: z.boolean().optional(),
|
|
219
|
+
thinking: thinkingConfigSchema.optional(),
|
|
220
|
+
output_config: outputConfigSchema.optional(),
|
|
221
|
+
// Anthropic clients commonly send `metadata: { user_id }`; the walker
|
|
222
|
+
// surfaces it on `options.metadata` for downstream provider forwarding.
|
|
223
|
+
metadata: z.record(z.string(), z.unknown()).optional(),
|
|
224
|
+
// Spec fields that the gateway tolerates but doesn't translate yet.
|
|
225
|
+
container: z.unknown().optional(),
|
|
226
|
+
context_management: z.unknown().optional(),
|
|
227
|
+
mcp_servers: z.unknown().optional(),
|
|
228
|
+
service_tier: z.unknown().optional(),
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Public types are sourced from the upstream Anthropic SDK so the gateway
|
|
233
|
+
* stays in lock-step with the canonical API surface; the schemas above are
|
|
234
|
+
* runtime validators for the subset we actually accept.
|
|
235
|
+
*/
|
|
236
|
+
export type AnthropicMessagesRequest = MessageCreateParams;
|
|
237
|
+
export type AnthropicSystem = MessageCreateParams["system"];
|
|
238
|
+
export type AnthropicMessage = MessageParam;
|
|
239
|
+
export type AnthropicUserContentBlock = ContentBlockParam;
|
|
240
|
+
export type AnthropicAssistantContentBlock = ContentBlockParam;
|
|
241
|
+
export type AnthropicTool = Tool;
|
|
242
|
+
export type AnthropicToolChoice = ToolChoice;
|
|
243
|
+
export type AnthropicToolResultContent = TextBlockParam | ImageBlockParam;
|