@linxiraos/pi-ai 1.0.1 → 1.0.2
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 +118 -30
- package/package.json +135 -136
- package/src/auth/sqlite-credential-store.ts +0 -56
- package/src/auth-retry.ts +5 -4
- package/src/auth-storage.ts +121 -111
- package/src/dialect/owned-stream.ts +3 -0
- package/src/error/auth-classify.ts +7 -6
- package/src/error/aws.ts +5 -1
- package/src/error/flags.ts +25 -1
- package/src/error/provider.ts +6 -5
- package/src/error/rate-limit.ts +71 -1
- package/src/providers/amazon-bedrock.ts +38 -0
- package/src/providers/anthropic-client.ts +6 -10
- package/src/providers/anthropic.ts +107 -259
- package/src/providers/aws-credentials.ts +222 -29
- package/src/providers/azure-openai-responses.ts +1 -0
- package/src/providers/cursor/exec-modern.ts +1 -0
- package/src/providers/cursor-pi-args.ts +22 -0
- package/src/providers/cursor.ts +81 -1
- package/src/providers/devin.ts +3 -3
- package/src/providers/google-antigravity-forced-tool.md +1 -0
- package/src/providers/google-gemini-cli.ts +83 -40
- package/src/providers/google-shared.ts +22 -8
- package/src/providers/ollama.ts +15 -3
- package/src/providers/openai-codex/request-transformer.ts +47 -21
- package/src/providers/openai-codex-responses.ts +3 -3
- package/src/providers/openai-reasoning-fallback.ts +21 -8
- package/src/providers/openai-responses.ts +77 -12
- package/src/providers/openai-shared.ts +114 -15
- package/src/providers/pi-native-server.ts +1 -0
- package/src/providers/register-builtins.ts +18 -14
- package/src/providers/vision-guard.ts +15 -3
- package/src/registry/amazon-bedrock.ts +9 -14
- package/src/registry/api-key-login.ts +26 -12
- package/src/registry/aws.ts +16 -8
- package/src/registry/cloudflare-ai-gateway.ts +10 -29
- package/src/registry/kagi.ts +11 -29
- package/src/registry/litellm.ts +11 -29
- package/src/registry/llama-cpp.ts +11 -21
- package/src/registry/lm-studio.ts +9 -20
- package/src/registry/oauth/callback-server.ts +93 -5
- package/src/registry/oauth/google-antigravity.ts +99 -44
- package/src/registry/oauth/perplexity.ts +32 -4
- package/src/registry/parallel.ts +10 -28
- package/src/registry/tavily.ts +9 -27
- package/src/registry/together.ts +7 -3
- package/src/registry/vercel-ai-gateway.ts +10 -28
- package/src/registry/vllm.ts +11 -21
- package/src/stream.ts +459 -53
- package/src/types.ts +23 -0
- package/src/usage/alibaba-token-plan.ts +8 -15
- package/src/usage/claude.ts +12 -19
- package/src/usage/cursor.ts +179 -59
- package/src/usage/gemini.ts +4 -3
- package/src/usage/github-copilot.ts +3 -2
- package/src/usage/google-antigravity.ts +10 -17
- package/src/usage/kimi.ts +35 -17
- package/src/usage/minimax-code.ts +7 -27
- package/src/usage/openai-codex-reset.ts +3 -2
- package/src/usage/openai-codex.ts +5 -5
- package/src/usage/opencode-go.ts +170 -60
- package/src/usage/shared.ts +33 -10
- package/src/usage/synthetic.ts +4 -11
- package/src/usage/umans.ts +2 -2
- package/src/usage/xai-oauth.ts +62 -34
- package/src/usage/zai.ts +4 -6
- package/src/usage.ts +0 -20
- package/src/utils/aws-profile.ts +39 -1
- package/src/utils/block-symbols.ts +18 -0
- package/src/utils/empty-completion-retry.ts +4 -1
- package/src/utils/leaked-thinking-stream.ts +3 -0
- package/src/utils/openrouter-headers.ts +4 -4
- package/src/utils/thinking-loop.ts +17 -38
- package/dist/types/api-registry.d.ts +0 -30
- package/dist/types/auth/sqlite-credential-store.d.ts +0 -117
- package/dist/types/auth-broker/client.d.ts +0 -93
- package/dist/types/auth-broker/discover.d.ts +0 -39
- package/dist/types/auth-broker/index.d.ts +0 -7
- package/dist/types/auth-broker/refresher.d.ts +0 -25
- package/dist/types/auth-broker/remote-store.d.ts +0 -136
- package/dist/types/auth-broker/server.d.ts +0 -48
- package/dist/types/auth-broker/snapshot-cache.d.ts +0 -17
- package/dist/types/auth-broker/types.d.ts +0 -152
- package/dist/types/auth-broker/wire-schema-resource.d.ts +0 -53
- package/dist/types/auth-broker/wire-schemas.d.ts +0 -5
- package/dist/types/auth-gateway/http.d.ts +0 -56
- package/dist/types/auth-gateway/index.d.ts +0 -3
- package/dist/types/auth-gateway/server.d.ts +0 -36
- package/dist/types/auth-gateway/types.d.ts +0 -127
- package/dist/types/auth-retry.d.ts +0 -150
- package/dist/types/auth-storage.d.ts +0 -1258
- package/dist/types/dialect/anthropic.d.ts +0 -15
- package/dist/types/dialect/catalog.d.ts +0 -3
- package/dist/types/dialect/coercion.d.ts +0 -23
- package/dist/types/dialect/deepseek.d.ts +0 -14
- package/dist/types/dialect/demotion.d.ts +0 -30
- package/dist/types/dialect/examples.d.ts +0 -18
- package/dist/types/dialect/factory.d.ts +0 -3
- package/dist/types/dialect/fenced-thinking.d.ts +0 -53
- package/dist/types/dialect/gemini.d.ts +0 -17
- package/dist/types/dialect/gemma.d.ts +0 -15
- package/dist/types/dialect/glm.d.ts +0 -9
- package/dist/types/dialect/harmony.d.ts +0 -8
- package/dist/types/dialect/hermes.d.ts +0 -9
- package/dist/types/dialect/history.d.ts +0 -3
- package/dist/types/dialect/index.d.ts +0 -11
- package/dist/types/dialect/inventory.d.ts +0 -9
- package/dist/types/dialect/kimi.d.ts +0 -14
- package/dist/types/dialect/minimax.d.ts +0 -3
- package/dist/types/dialect/owned-stream.d.ts +0 -4
- package/dist/types/dialect/qwen3.d.ts +0 -9
- package/dist/types/dialect/rendering.d.ts +0 -54
- package/dist/types/dialect/thinking.d.ts +0 -6
- package/dist/types/dialect/types.d.ts +0 -68
- package/dist/types/dialect/xml.d.ts +0 -9
- package/dist/types/error/abort.d.ts +0 -14
- package/dist/types/error/auth-classify.d.ts +0 -20
- package/dist/types/error/auth.d.ts +0 -27
- package/dist/types/error/aws.d.ts +0 -27
- package/dist/types/error/classes.d.ts +0 -106
- package/dist/types/error/finalize.d.ts +0 -39
- package/dist/types/error/flags.d.ts +0 -94
- package/dist/types/error/format.d.ts +0 -20
- package/dist/types/error/gateway.d.ts +0 -20
- package/dist/types/error/index.d.ts +0 -14
- package/dist/types/error/oauth.d.ts +0 -43
- package/dist/types/error/provider.d.ts +0 -42
- package/dist/types/error/rate-limit.d.ts +0 -80
- package/dist/types/error/retryable.d.ts +0 -27
- package/dist/types/error/validation.d.ts +0 -32
- package/dist/types/index.d.ts +0 -51
- package/dist/types/provider-details.d.ts +0 -24
- package/dist/types/providers/amazon-bedrock.d.ts +0 -39
- package/dist/types/providers/anthropic-client.d.ts +0 -106
- package/dist/types/providers/anthropic-messages-server-schema.d.ts +0 -937
- package/dist/types/providers/anthropic-messages-server.d.ts +0 -17
- package/dist/types/providers/anthropic-wire.d.ts +0 -345
- package/dist/types/providers/anthropic.d.ts +0 -261
- package/dist/types/providers/aws-credentials.d.ts +0 -48
- package/dist/types/providers/aws-eventstream.d.ts +0 -39
- package/dist/types/providers/aws-sigv4.d.ts +0 -55
- package/dist/types/providers/azure-openai-responses.d.ts +0 -16
- package/dist/types/providers/bedrock-mantle.d.ts +0 -13
- package/dist/types/providers/claude-code-fingerprint.d.ts +0 -19
- package/dist/types/providers/cowork-fetch.d.ts +0 -3
- package/dist/types/providers/cursor/exec-modern.d.ts +0 -98
- package/dist/types/providers/cursor-pi-args.d.ts +0 -105
- package/dist/types/providers/cursor.d.ts +0 -221
- package/dist/types/providers/devin.d.ts +0 -12
- package/dist/types/providers/error-message.d.ts +0 -25
- package/dist/types/providers/github-copilot-headers.d.ts +0 -40
- package/dist/types/providers/gitlab-duo-workflow.d.ts +0 -254
- package/dist/types/providers/gitlab-duo.d.ts +0 -27
- package/dist/types/providers/google-auth.d.ts +0 -24
- package/dist/types/providers/google-gemini-cli.d.ts +0 -120
- package/dist/types/providers/google-shared.d.ts +0 -203
- package/dist/types/providers/google-types.d.ts +0 -155
- package/dist/types/providers/google-vertex.d.ts +0 -7
- package/dist/types/providers/google.d.ts +0 -4
- package/dist/types/providers/grammar.d.ts +0 -1
- package/dist/types/providers/kimi.d.ts +0 -27
- package/dist/types/providers/mock.d.ts +0 -179
- package/dist/types/providers/ollama.d.ts +0 -8
- package/dist/types/providers/openai-anthropic-shim.d.ts +0 -35
- package/dist/types/providers/openai-chat-server-schema.d.ts +0 -1311
- package/dist/types/providers/openai-chat-server.d.ts +0 -16
- package/dist/types/providers/openai-chat-wire.d.ts +0 -669
- package/dist/types/providers/openai-codex/request-transformer.d.ts +0 -109
- package/dist/types/providers/openai-codex/response-handler.d.ts +0 -26
- package/dist/types/providers/openai-codex-responses.d.ts +0 -238
- package/dist/types/providers/openai-completions.d.ts +0 -48
- package/dist/types/providers/openai-reasoning-fallback.d.ts +0 -25
- package/dist/types/providers/openai-responses-server-schema.d.ts +0 -1314
- package/dist/types/providers/openai-responses-server.d.ts +0 -17
- package/dist/types/providers/openai-responses-wire.d.ts +0 -6099
- package/dist/types/providers/openai-responses.d.ts +0 -131
- package/dist/types/providers/openai-shared.d.ts +0 -624
- package/dist/types/providers/pi-native-client.d.ts +0 -13
- package/dist/types/providers/pi-native-server.d.ts +0 -69
- package/dist/types/providers/register-builtins.d.ts +0 -37
- package/dist/types/providers/synthetic.d.ts +0 -26
- package/dist/types/providers/transform-messages.d.ts +0 -32
- package/dist/types/providers/vision-guard.d.ts +0 -20
- package/dist/types/registry/aiand.d.ts +0 -7
- package/dist/types/registry/aimlapi.d.ts +0 -4
- package/dist/types/registry/alibaba-coding-plan.d.ts +0 -8
- package/dist/types/registry/alibaba-token-plan.d.ts +0 -18
- package/dist/types/registry/amazon-bedrock.d.ts +0 -5
- package/dist/types/registry/anthropic.d.ts +0 -10
- package/dist/types/registry/api-key-login.d.ts +0 -42
- package/dist/types/registry/api-key-validation.d.ts +0 -43
- package/dist/types/registry/aws.d.ts +0 -13
- package/dist/types/registry/azure.d.ts +0 -4
- package/dist/types/registry/baseten.d.ts +0 -7
- package/dist/types/registry/bedrock-mantle.d.ts +0 -22
- package/dist/types/registry/cerebras.d.ts +0 -7
- package/dist/types/registry/cloudflare-ai-gateway.d.ts +0 -13
- package/dist/types/registry/coreweave.d.ts +0 -7
- package/dist/types/registry/cursor.d.ts +0 -7
- package/dist/types/registry/deepseek.d.ts +0 -8
- package/dist/types/registry/derived.d.ts +0 -5
- package/dist/types/registry/devin.d.ts +0 -8
- package/dist/types/registry/exa.d.ts +0 -8
- package/dist/types/registry/firepass.d.ts +0 -16
- package/dist/types/registry/fireworks.d.ts +0 -7
- package/dist/types/registry/github-copilot.d.ts +0 -7
- package/dist/types/registry/gitlab-duo-workflow.d.ts +0 -10
- package/dist/types/registry/gitlab-duo.d.ts +0 -9
- package/dist/types/registry/gmi-cloud.d.ts +0 -7
- package/dist/types/registry/google-antigravity.d.ts +0 -9
- package/dist/types/registry/google-gemini-cli.d.ts +0 -9
- package/dist/types/registry/google-vertex.d.ts +0 -5
- package/dist/types/registry/google.d.ts +0 -4
- package/dist/types/registry/groq.d.ts +0 -4
- package/dist/types/registry/huggingface.d.ts +0 -7
- package/dist/types/registry/index.d.ts +0 -4
- package/dist/types/registry/kagi.d.ts +0 -14
- package/dist/types/registry/kilo.d.ts +0 -7
- package/dist/types/registry/kimi-code.d.ts +0 -7
- package/dist/types/registry/litellm.d.ts +0 -13
- package/dist/types/registry/llama-cpp.d.ts +0 -8
- package/dist/types/registry/lm-studio.d.ts +0 -8
- package/dist/types/registry/meta.d.ts +0 -7
- package/dist/types/registry/minimax-code-cn.d.ts +0 -6
- package/dist/types/registry/minimax-code.d.ts +0 -6
- package/dist/types/registry/minimax.d.ts +0 -4
- package/dist/types/registry/mistral.d.ts +0 -4
- package/dist/types/registry/moonshot.d.ts +0 -7
- package/dist/types/registry/nanogpt.d.ts +0 -7
- package/dist/types/registry/novita.d.ts +0 -6
- package/dist/types/registry/nvidia.d.ts +0 -7
- package/dist/types/registry/oauth/anthropic-constants.d.ts +0 -12
- package/dist/types/registry/oauth/anthropic.d.ts +0 -24
- package/dist/types/registry/oauth/callback-server.d.ts +0 -74
- package/dist/types/registry/oauth/cursor.d.ts +0 -16
- package/dist/types/registry/oauth/device-code.d.ts +0 -25
- package/dist/types/registry/oauth/devin.d.ts +0 -5
- package/dist/types/registry/oauth/github-copilot.d.ts +0 -30
- package/dist/types/registry/oauth/gitlab-duo-workflow.d.ts +0 -6
- package/dist/types/registry/oauth/gitlab-duo.d.ts +0 -3
- package/dist/types/registry/oauth/google-antigravity.d.ts +0 -11
- package/dist/types/registry/oauth/google-gemini-cli.d.ts +0 -22
- package/dist/types/registry/oauth/google-oauth-shared.d.ts +0 -56
- package/dist/types/registry/oauth/index.d.ts +0 -45
- package/dist/types/registry/oauth/kimi.d.ts +0 -21
- package/dist/types/registry/oauth/minimax-code.d.ts +0 -27
- package/dist/types/registry/oauth/openai-codex.d.ts +0 -33
- package/dist/types/registry/oauth/opencode.d.ts +0 -18
- package/dist/types/registry/oauth/perplexity.d.ts +0 -9
- package/dist/types/registry/oauth/pkce.d.ts +0 -8
- package/dist/types/registry/oauth/types.d.ts +0 -87
- package/dist/types/registry/oauth/wafer.d.ts +0 -1
- package/dist/types/registry/oauth/xai-oauth.d.ts +0 -46
- package/dist/types/registry/oauth/xiaomi.d.ts +0 -25
- package/dist/types/registry/oauth/zai.d.ts +0 -25
- package/dist/types/registry/ollama-cloud.d.ts +0 -7
- package/dist/types/registry/ollama.d.ts +0 -12
- package/dist/types/registry/openai-codex-device.d.ts +0 -8
- package/dist/types/registry/openai-codex.d.ts +0 -9
- package/dist/types/registry/openai.d.ts +0 -4
- package/dist/types/registry/opencode-go.d.ts +0 -6
- package/dist/types/registry/opencode-zen.d.ts +0 -6
- package/dist/types/registry/openrouter.d.ts +0 -13
- package/dist/types/registry/parallel.d.ts +0 -14
- package/dist/types/registry/perplexity.d.ts +0 -7
- package/dist/types/registry/qianfan.d.ts +0 -7
- package/dist/types/registry/qwen-portal.d.ts +0 -7
- package/dist/types/registry/registry.d.ts +0 -367
- package/dist/types/registry/sakana.d.ts +0 -7
- package/dist/types/registry/siliconflow-cn.d.ts +0 -7
- package/dist/types/registry/siliconflow.d.ts +0 -7
- package/dist/types/registry/synthetic.d.ts +0 -6
- package/dist/types/registry/tavily.d.ts +0 -14
- package/dist/types/registry/together.d.ts +0 -6
- package/dist/types/registry/types.d.ts +0 -75
- package/dist/types/registry/umans.d.ts +0 -7
- package/dist/types/registry/venice.d.ts +0 -13
- package/dist/types/registry/vercel-ai-gateway.d.ts +0 -7
- package/dist/types/registry/vllm.d.ts +0 -7
- package/dist/types/registry/wafer-serverless.d.ts +0 -6
- package/dist/types/registry/xai-oauth.d.ts +0 -7
- package/dist/types/registry/xai.d.ts +0 -7
- package/dist/types/registry/xiaomi-token-plan-ams.d.ts +0 -6
- package/dist/types/registry/xiaomi-token-plan-cn.d.ts +0 -6
- package/dist/types/registry/xiaomi-token-plan-sgp.d.ts +0 -6
- package/dist/types/registry/xiaomi.d.ts +0 -6
- package/dist/types/registry/zai.d.ts +0 -15
- package/dist/types/registry/zenmux.d.ts +0 -7
- package/dist/types/registry/zhipu-coding-plan.d.ts +0 -7
- package/dist/types/stream.d.ts +0 -46
- package/dist/types/types.d.ts +0 -1064
- package/dist/types/usage/alibaba-token-plan.d.ts +0 -3
- package/dist/types/usage/claude.d.ts +0 -4
- package/dist/types/usage/cursor.d.ts +0 -4
- package/dist/types/usage/gemini.d.ts +0 -2
- package/dist/types/usage/github-copilot.d.ts +0 -7
- package/dist/types/usage/google-antigravity.d.ts +0 -15
- package/dist/types/usage/kimi.d.ts +0 -2
- package/dist/types/usage/minimax-code.d.ts +0 -3
- package/dist/types/usage/ollama.d.ts +0 -5
- package/dist/types/usage/openai-codex-base-url.d.ts +0 -18
- package/dist/types/usage/openai-codex-reset.d.ts +0 -88
- package/dist/types/usage/openai-codex.d.ts +0 -10
- package/dist/types/usage/opencode-go.d.ts +0 -2
- package/dist/types/usage/shared.d.ts +0 -1
- package/dist/types/usage/synthetic.d.ts +0 -2
- package/dist/types/usage/umans.d.ts +0 -2
- package/dist/types/usage/xai-oauth.d.ts +0 -12
- package/dist/types/usage/zai.d.ts +0 -3
- package/dist/types/usage.d.ts +0 -527
- package/dist/types/utils/abort.d.ts +0 -25
- package/dist/types/utils/anthropic-auth.d.ts +0 -35
- package/dist/types/utils/aws-profile.d.ts +0 -17
- package/dist/types/utils/block-symbols.d.ts +0 -62
- package/dist/types/utils/deterministic-id.d.ts +0 -16
- package/dist/types/utils/empty-completion-retry.d.ts +0 -21
- package/dist/types/utils/event-stream.d.ts +0 -39
- package/dist/types/utils/foundry.d.ts +0 -1
- package/dist/types/utils/google-validation.d.ts +0 -2
- package/dist/types/utils/harmony-leak.d.ts +0 -135
- package/dist/types/utils/http-inspector.d.ts +0 -49
- package/dist/types/utils/idle-iterator.d.ts +0 -149
- package/dist/types/utils/leaked-thinking-stream.d.ts +0 -33
- package/dist/types/utils/openai-http.d.ts +0 -48
- package/dist/types/utils/openrouter-headers.d.ts +0 -1
- package/dist/types/utils/parse-bind.d.ts +0 -23
- package/dist/types/utils/provider-response.d.ts +0 -3
- package/dist/types/utils/proxy.d.ts +0 -39
- package/dist/types/utils/request-debug.d.ts +0 -29
- package/dist/types/utils/retry-after.d.ts +0 -4
- package/dist/types/utils/retry.d.ts +0 -14
- package/dist/types/utils/schema/adapt.d.ts +0 -24
- package/dist/types/utils/schema/compatibility.d.ts +0 -30
- package/dist/types/utils/schema/dereference.d.ts +0 -11
- package/dist/types/utils/schema/draft.d.ts +0 -10
- package/dist/types/utils/schema/equality.d.ts +0 -4
- package/dist/types/utils/schema/fields.d.ts +0 -54
- package/dist/types/utils/schema/index.d.ts +0 -14
- package/dist/types/utils/schema/json-schema-validator.d.ts +0 -20
- package/dist/types/utils/schema/meta-validator.d.ts +0 -2
- package/dist/types/utils/schema/normalize.d.ts +0 -153
- package/dist/types/utils/schema/spill.d.ts +0 -8
- package/dist/types/utils/schema/stamps.d.ts +0 -17
- package/dist/types/utils/schema/strict-tool-validation.d.ts +0 -16
- package/dist/types/utils/schema/types.d.ts +0 -4
- package/dist/types/utils/schema/typescript.d.ts +0 -24
- package/dist/types/utils/schema/wire.d.ts +0 -52
- package/dist/types/utils/sdk-stream-timeout.d.ts +0 -33
- package/dist/types/utils/sse-debug.d.ts +0 -5
- package/dist/types/utils/stream-markup-healing.d.ts +0 -87
- package/dist/types/utils/thinking-loop.d.ts +0 -102
- package/dist/types/utils/tool-call-loop-guard.d.ts +0 -26
- package/dist/types/utils/tool-choice.d.ts +0 -52
- package/dist/types/utils/validation.d.ts +0 -28
- package/dist/types/utils.d.ts +0 -57
|
@@ -45,6 +45,19 @@ import { decodeEventStream } from "./aws-eventstream";
|
|
|
45
45
|
import { signRequest } from "./aws-sigv4";
|
|
46
46
|
import { transformMessages } from "./transform-messages";
|
|
47
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Headers SigV4 generates for itself. A caller cannot be allowed to supply these:
|
|
50
|
+
* `signRequest` would sign the caller's value but return its own, so the signature
|
|
51
|
+
* would not match what goes on the wire.
|
|
52
|
+
*/
|
|
53
|
+
const SIGNER_OWNED_HEADERS = new Set(["host", "x-amz-date", "x-amz-content-sha256", "x-amz-security-token"]);
|
|
54
|
+
|
|
55
|
+
/** Headers the Bedrock request sets itself; a caller copy in any casing duplicates them. */
|
|
56
|
+
// `content-length` included: the fetch layer recomputes it from the serialized
|
|
57
|
+
// body, so a caller value would be signed but not sent, and AWS rejects the
|
|
58
|
+
// mismatch.
|
|
59
|
+
const BEDROCK_RESERVED_HEADERS = new Set(["content-type", "accept", "authorization", "content-length"]);
|
|
60
|
+
|
|
48
61
|
export type BedrockThinkingDisplay = "summarized" | "omitted";
|
|
49
62
|
|
|
50
63
|
export interface BedrockOptions extends StreamOptions {
|
|
@@ -356,7 +369,32 @@ export const streamBedrock: StreamFunction<"bedrock-converse-stream"> = (
|
|
|
356
369
|
|
|
357
370
|
const bodyText = JSON.stringify(commandInput);
|
|
358
371
|
const body = new TextEncoder().encode(bodyText);
|
|
372
|
+
// Caller headers are merged BEFORE signing, so SigV4 covers them and they
|
|
373
|
+
// reach the wire. Bedrock built its header map from scratch and ignored
|
|
374
|
+
// `options.headers` entirely, so tracing/attribution headers set by a
|
|
375
|
+
// caller (or by a `before_provider_headers` extension) were silently
|
|
376
|
+
// dropped here while working on every other provider. Content-type and
|
|
377
|
+
// accept stay last: the eventstream framing is not the caller's to change.
|
|
378
|
+
//
|
|
379
|
+
// The signer's OWN headers are dropped first, and that is load-bearing:
|
|
380
|
+
// `signRequest` lets a caller value overwrite `host`/`x-amz-*` in the map
|
|
381
|
+
// it signs, but always RETURNS the generated ones, which `requestHeaders`
|
|
382
|
+
// below then puts on the wire. A caller supplying any of them would sign
|
|
383
|
+
// one set of values and send another, and Bedrock would reject every
|
|
384
|
+
// request with a signature mismatch.
|
|
385
|
+
// Lower-cased, and names the request sets itself are dropped. Keeping a
|
|
386
|
+
// caller `Content-Type` beside the fixed `content-type` leaves TWO object
|
|
387
|
+
// keys: SigV4 signs one value while fetch canonicalizes both into a single
|
|
388
|
+
// comma-joined wire header, so AWS validates different bytes than were
|
|
389
|
+
// signed and rejects the request.
|
|
390
|
+
const callerHeaders: Record<string, string> = {};
|
|
391
|
+
for (const [name, value] of Object.entries(options?.headers ?? {})) {
|
|
392
|
+
const field = name.toLowerCase();
|
|
393
|
+
if (SIGNER_OWNED_HEADERS.has(field) || BEDROCK_RESERVED_HEADERS.has(field)) continue;
|
|
394
|
+
callerHeaders[field] = value;
|
|
395
|
+
}
|
|
359
396
|
const baseHeaders: Record<string, string> = {
|
|
397
|
+
...callerHeaders,
|
|
360
398
|
"content-type": "application/json",
|
|
361
399
|
accept: "application/vnd.amazon.eventstream",
|
|
362
400
|
};
|
|
@@ -27,7 +27,7 @@ import { AnthropicApiError, AnthropicConnectionError, AnthropicConnectionTimeout
|
|
|
27
27
|
export { AnthropicApiError, AnthropicConnectionError, AnthropicConnectionTimeoutError };
|
|
28
28
|
|
|
29
29
|
import type { FetchImpl } from "../types";
|
|
30
|
-
import type {
|
|
30
|
+
import type { MessageCreateParams } from "./anthropic-wire";
|
|
31
31
|
|
|
32
32
|
/** Default pre-response timeout, matching the SDK's 10-minute default. */
|
|
33
33
|
const DEFAULT_TIMEOUT_MS = 600_000;
|
|
@@ -173,7 +173,7 @@ export class AnthropicMessages {
|
|
|
173
173
|
this.#path = path;
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
create(params:
|
|
176
|
+
create(params: MessageCreateParams, options?: AnthropicRequestOptions): AnthropicApiRequest {
|
|
177
177
|
return this.#client.request(this.#path, params, options);
|
|
178
178
|
}
|
|
179
179
|
}
|
|
@@ -184,8 +184,8 @@ export class AnthropicMessages {
|
|
|
184
184
|
* alternative Messages-API client via `AnthropicOptions.client`.
|
|
185
185
|
*/
|
|
186
186
|
export interface AnthropicMessagesClientLike {
|
|
187
|
-
messages: { create(params:
|
|
188
|
-
beta?: { messages: { create(params:
|
|
187
|
+
messages: { create(params: MessageCreateParams, options?: AnthropicRequestOptions): unknown };
|
|
188
|
+
beta?: { messages: { create(params: MessageCreateParams, options?: AnthropicRequestOptions): unknown } };
|
|
189
189
|
}
|
|
190
190
|
|
|
191
191
|
export class AnthropicMessagesClient implements AnthropicMessagesClientLike {
|
|
@@ -199,7 +199,7 @@ export class AnthropicMessagesClient implements AnthropicMessagesClientLike {
|
|
|
199
199
|
this.beta = { messages: new AnthropicMessages(this, "/v1/messages?beta=true") };
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
-
request(path: string, params:
|
|
202
|
+
request(path: string, params: MessageCreateParams, options?: AnthropicRequestOptions): AnthropicApiRequest {
|
|
203
203
|
return new AnthropicApiRequest(() => this.#send(path, params, options));
|
|
204
204
|
}
|
|
205
205
|
|
|
@@ -218,11 +218,7 @@ export class AnthropicMessagesClient implements AnthropicMessagesClientLike {
|
|
|
218
218
|
return headers;
|
|
219
219
|
}
|
|
220
220
|
|
|
221
|
-
async #send(
|
|
222
|
-
path: string,
|
|
223
|
-
params: MessageCreateParamsStreaming,
|
|
224
|
-
options?: AnthropicRequestOptions,
|
|
225
|
-
): Promise<Response> {
|
|
221
|
+
async #send(path: string, params: MessageCreateParams, options?: AnthropicRequestOptions): Promise<Response> {
|
|
226
222
|
const opts = this.#options;
|
|
227
223
|
const fetchFn: FetchImpl = opts.fetch ?? fetch;
|
|
228
224
|
const callerSignal = options?.signal;
|
|
@@ -80,6 +80,7 @@ import {
|
|
|
80
80
|
type ContentBlockParam,
|
|
81
81
|
type FallbackParam,
|
|
82
82
|
isAnthropicWebSearchHistoryBlock,
|
|
83
|
+
type MessageCreateParams,
|
|
83
84
|
type MessageCreateParamsStreaming,
|
|
84
85
|
type MessageParam,
|
|
85
86
|
type RawMessageStreamEvent,
|
|
@@ -482,17 +483,11 @@ function dropAnthropicStrictTools(params: MessageCreateParamsStreaming): void {
|
|
|
482
483
|
function getCacheControl(
|
|
483
484
|
model: Model<"anthropic-messages">,
|
|
484
485
|
cacheRetention: CacheRetention | undefined,
|
|
485
|
-
isOAuthToken: boolean,
|
|
486
486
|
): { retention: CacheRetention; cacheControl?: AnthropicCacheControl } {
|
|
487
|
-
//
|
|
488
|
-
//
|
|
489
|
-
//
|
|
490
|
-
|
|
491
|
-
// breakpoint cold-misses the entire prefix on resume. PI_CACHE_RETENTION
|
|
492
|
-
// still overrides the API-key default in either direction.
|
|
493
|
-
const retention = isOAuthToken
|
|
494
|
-
? (cacheRetention ?? "long")
|
|
495
|
-
: resolveCacheRetention(cacheRetention, model.compat.supportsLongCacheRetention ? "long" : "short");
|
|
487
|
+
// Five-minute writes are the cheapest cache population strategy. Longer
|
|
488
|
+
// retention remains an explicit PI_CACHE_RETENTION/request override; idle
|
|
489
|
+
// sessions keep the short entry warm with bounded read-only refreshes.
|
|
490
|
+
const retention = resolveCacheRetention(cacheRetention, "short");
|
|
496
491
|
if (retention === "none") {
|
|
497
492
|
return { retention };
|
|
498
493
|
}
|
|
@@ -1653,6 +1648,31 @@ export function applyAnthropicUsageExtras(usage: Usage, source: AnthropicUsageLi
|
|
|
1653
1648
|
}
|
|
1654
1649
|
}
|
|
1655
1650
|
|
|
1651
|
+
function parseAnthropicWireUsage(value: unknown): AnthropicWireUsage | undefined {
|
|
1652
|
+
if (!isRecord(value)) return undefined;
|
|
1653
|
+
const cacheCreation = isRecord(value.cache_creation)
|
|
1654
|
+
? {
|
|
1655
|
+
...(typeof value.cache_creation.ephemeral_5m_input_tokens === "number"
|
|
1656
|
+
? { ephemeral_5m_input_tokens: value.cache_creation.ephemeral_5m_input_tokens }
|
|
1657
|
+
: {}),
|
|
1658
|
+
...(typeof value.cache_creation.ephemeral_1h_input_tokens === "number"
|
|
1659
|
+
? { ephemeral_1h_input_tokens: value.cache_creation.ephemeral_1h_input_tokens }
|
|
1660
|
+
: {}),
|
|
1661
|
+
}
|
|
1662
|
+
: undefined;
|
|
1663
|
+
return {
|
|
1664
|
+
...(typeof value.input_tokens === "number" ? { input_tokens: value.input_tokens } : {}),
|
|
1665
|
+
...(typeof value.output_tokens === "number" ? { output_tokens: value.output_tokens } : {}),
|
|
1666
|
+
...(typeof value.cache_read_input_tokens === "number"
|
|
1667
|
+
? { cache_read_input_tokens: value.cache_read_input_tokens }
|
|
1668
|
+
: {}),
|
|
1669
|
+
...(typeof value.cache_creation_input_tokens === "number"
|
|
1670
|
+
? { cache_creation_input_tokens: value.cache_creation_input_tokens }
|
|
1671
|
+
: {}),
|
|
1672
|
+
...(cacheCreation === undefined ? {} : { cache_creation: cacheCreation }),
|
|
1673
|
+
};
|
|
1674
|
+
}
|
|
1675
|
+
|
|
1656
1676
|
function parseAnthropicFallbackWireBlock(value: unknown): AnthropicFallbackContent | undefined {
|
|
1657
1677
|
if (!isRecord(value) || value.type !== "fallback") return undefined;
|
|
1658
1678
|
const from = isRecord(value.from) && typeof value.from.model === "string" ? value.from.model : undefined;
|
|
@@ -1857,6 +1877,7 @@ const streamAnthropicOnce = (
|
|
|
1857
1877
|
});
|
|
1858
1878
|
}
|
|
1859
1879
|
|
|
1880
|
+
const zeroOutputCacheRefresh = options?.anthropicCacheRefreshRequest === true;
|
|
1860
1881
|
let client: AnthropicMessagesClientLike;
|
|
1861
1882
|
let isOAuthToken: boolean;
|
|
1862
1883
|
|
|
@@ -1927,7 +1948,7 @@ const streamAnthropicOnce = (
|
|
|
1927
1948
|
// requests must not deviate from CC's header fingerprint.
|
|
1928
1949
|
if (
|
|
1929
1950
|
!(options?.isOAuth ?? isAnthropicOAuthToken(apiKey)) &&
|
|
1930
|
-
getCacheControl(model, options?.cacheRetention
|
|
1951
|
+
getCacheControl(model, options?.cacheRetention).cacheControl?.ttl === "1h" &&
|
|
1931
1952
|
!extraBetas.includes(extendedCacheTtlBeta)
|
|
1932
1953
|
) {
|
|
1933
1954
|
extraBetas.push(extendedCacheTtlBeta);
|
|
@@ -1958,7 +1979,7 @@ const streamAnthropicOnce = (
|
|
|
1958
1979
|
model,
|
|
1959
1980
|
apiKey,
|
|
1960
1981
|
extraBetas,
|
|
1961
|
-
stream:
|
|
1982
|
+
stream: !zeroOutputCacheRefresh,
|
|
1962
1983
|
interleavedThinking: options?.interleavedThinking ?? true,
|
|
1963
1984
|
headers: options?.headers,
|
|
1964
1985
|
dynamicHeaders: copilotDynamicHeaders?.headers,
|
|
@@ -2005,6 +2026,60 @@ const streamAnthropicOnce = (
|
|
|
2005
2026
|
return nextParams;
|
|
2006
2027
|
};
|
|
2007
2028
|
let params = await prepareParams();
|
|
2029
|
+
const idleTimeoutMs = options?.streamIdleTimeoutMs ?? getStreamIdleTimeoutMs(model.compat.streamIdleTimeoutMs);
|
|
2030
|
+
const firstEventTimeoutMs = options?.streamFirstEventTimeoutMs ?? getStreamFirstEventTimeoutMs(idleTimeoutMs);
|
|
2031
|
+
const requestTimeoutMs =
|
|
2032
|
+
firstEventTimeoutMs !== undefined && firstEventTimeoutMs > 0 ? firstEventTimeoutMs : undefined;
|
|
2033
|
+
|
|
2034
|
+
if (zeroOutputCacheRefresh) {
|
|
2035
|
+
const refreshParams: MessageCreateParams = { ...params, max_tokens: 0, stream: false };
|
|
2036
|
+
rawRequestDump = {
|
|
2037
|
+
provider: model.provider,
|
|
2038
|
+
api: output.api,
|
|
2039
|
+
model: model.id,
|
|
2040
|
+
method: "POST",
|
|
2041
|
+
url: `${baseUrl}/v1/messages${isOAuthToken ? "?beta=true" : ""}`,
|
|
2042
|
+
body: refreshParams,
|
|
2043
|
+
};
|
|
2044
|
+
const { requestSignal } = activeAbortTracker;
|
|
2045
|
+
const requestOptions = {
|
|
2046
|
+
...createSdkStreamRequestOptions(requestSignal, requestTimeoutMs),
|
|
2047
|
+
maxRetries: 0,
|
|
2048
|
+
};
|
|
2049
|
+
const request: unknown =
|
|
2050
|
+
isOAuthToken && client.beta
|
|
2051
|
+
? client.beta.messages.create(refreshParams, requestOptions)
|
|
2052
|
+
: client.messages.create(refreshParams, requestOptions);
|
|
2053
|
+
if (!hasAnthropicRawResponseRequest(request)) {
|
|
2054
|
+
throw new AIError.AnthropicStreamEnvelopeError(
|
|
2055
|
+
"Anthropic cache refresh request did not expose a raw response",
|
|
2056
|
+
);
|
|
2057
|
+
}
|
|
2058
|
+
const response = await request.asResponse();
|
|
2059
|
+
await notifyProviderResponse(options, response, model, response.headers.get("request-id"));
|
|
2060
|
+
const body: unknown = await response.json();
|
|
2061
|
+
if (!isRecord(body)) {
|
|
2062
|
+
throw new AIError.AnthropicStreamEnvelopeError("Anthropic cache refresh returned a malformed response");
|
|
2063
|
+
}
|
|
2064
|
+
const wireUsage = parseAnthropicWireUsage(body.usage);
|
|
2065
|
+
if (!wireUsage) {
|
|
2066
|
+
throw new AIError.AnthropicStreamEnvelopeError("Anthropic cache refresh response omitted usage");
|
|
2067
|
+
}
|
|
2068
|
+
if (typeof body.id === "string") output.responseId = body.id;
|
|
2069
|
+
output.usage.input = wireUsage.input_tokens ?? 0;
|
|
2070
|
+
output.usage.output = wireUsage.output_tokens ?? 0;
|
|
2071
|
+
output.usage.cacheRead = wireUsage.cache_read_input_tokens ?? 0;
|
|
2072
|
+
output.usage.cacheWrite = wireUsage.cache_creation_input_tokens ?? 0;
|
|
2073
|
+
applyAnthropicUsageExtras(output.usage, wireUsage);
|
|
2074
|
+
output.usage.totalTokens =
|
|
2075
|
+
output.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;
|
|
2076
|
+
calculateCost(model, output.usage);
|
|
2077
|
+
output.duration = performance.now() - startTime;
|
|
2078
|
+
stream.push({ type: "start", partial: output });
|
|
2079
|
+
stream.push({ type: "done", reason: "stop", message: output });
|
|
2080
|
+
stream.end();
|
|
2081
|
+
return;
|
|
2082
|
+
}
|
|
2008
2083
|
|
|
2009
2084
|
// Opt-in flag: the response parser only honors `fallback` content
|
|
2010
2085
|
// blocks and `usage.iterations` when the current request opted into
|
|
@@ -2019,10 +2094,6 @@ const streamAnthropicOnce = (
|
|
|
2019
2094
|
| (AnthropicServerToolContent & { [kStreamingPartialJson]?: string })
|
|
2020
2095
|
| (ToolCall & { [kStreamingPartialJson]: string; [kStreamingLastParseLen]?: number })
|
|
2021
2096
|
) & { [kStreamingBlockIndex]: number };
|
|
2022
|
-
const idleTimeoutMs = options?.streamIdleTimeoutMs ?? getStreamIdleTimeoutMs(model.compat.streamIdleTimeoutMs);
|
|
2023
|
-
const firstEventTimeoutMs = options?.streamFirstEventTimeoutMs ?? getStreamFirstEventTimeoutMs(idleTimeoutMs);
|
|
2024
|
-
const requestTimeoutMs =
|
|
2025
|
-
firstEventTimeoutMs !== undefined && firstEventTimeoutMs > 0 ? firstEventTimeoutMs : undefined;
|
|
2026
2097
|
const blocks = output.content as Block[];
|
|
2027
2098
|
const finalizeStreamBlock = (block: Block, contentIndex: number): void => {
|
|
2028
2099
|
if (block.type === "text") {
|
|
@@ -2807,65 +2878,19 @@ export const streamAnthropic: StreamFunction<"anthropic-messages"> = (model, con
|
|
|
2807
2878
|
export type AnthropicSystemBlock = {
|
|
2808
2879
|
type: "text";
|
|
2809
2880
|
text: string;
|
|
2810
|
-
cache_control?: AnthropicCacheControl;
|
|
2811
2881
|
};
|
|
2812
2882
|
type SystemBlockOptions = {
|
|
2813
2883
|
includeClaudeCodeInstruction?: boolean;
|
|
2814
2884
|
extraInstructions?: string[];
|
|
2815
2885
|
/** Text of the first user message — used as fingerprint seed for the billing header. */
|
|
2816
2886
|
firstUserMessageText?: string;
|
|
2817
|
-
cacheControl?: AnthropicCacheControl;
|
|
2818
2887
|
};
|
|
2819
2888
|
|
|
2820
|
-
/**
|
|
2821
|
-
* Place system-block cache breakpoints that survive volatile project context.
|
|
2822
|
-
*
|
|
2823
|
-
* omp normally appends its project footer (cwd, date, workspace tree) after the
|
|
2824
|
-
* stable system prefix. When cwd is outside a single direct child repository,
|
|
2825
|
-
* an active-repo context block follows that footer. Caching up to the last three
|
|
2826
|
-
* eligible blocks therefore covers both layouts:
|
|
2827
|
-
*
|
|
2828
|
-
* - stable prefix, project footer
|
|
2829
|
-
* - stable prefix, project footer, active-repo context
|
|
2830
|
-
*
|
|
2831
|
-
* A footer change can then fall back to the stable-prefix entry instead of
|
|
2832
|
-
* re-writing the entire system cache (issue #7324).
|
|
2833
|
-
*
|
|
2834
|
-
* @returns breakpoints placed, capped by `maxBreakpoints`.
|
|
2835
|
-
*/
|
|
2836
|
-
function cacheSystemPrefixBreakpoints(
|
|
2837
|
-
blocks: AnthropicSystemBlock[],
|
|
2838
|
-
cacheControl: AnthropicCacheControl | undefined,
|
|
2839
|
-
maxBreakpoints: number,
|
|
2840
|
-
firstCacheableIndex: number,
|
|
2841
|
-
): number {
|
|
2842
|
-
if (!cacheControl || maxBreakpoints <= 0) return 0;
|
|
2843
|
-
let placed = 0;
|
|
2844
|
-
for (let index = blocks.length - 1; index >= firstCacheableIndex && placed < maxBreakpoints; index--) {
|
|
2845
|
-
if (blocks[index].cache_control != null) continue;
|
|
2846
|
-
blocks[index] = { ...blocks[index], cache_control: cloneAnthropicCacheControl(cacheControl) };
|
|
2847
|
-
placed++;
|
|
2848
|
-
}
|
|
2849
|
-
return placed;
|
|
2850
|
-
}
|
|
2851
|
-
|
|
2852
|
-
/**
|
|
2853
|
-
* First system-block index that may carry a cache breakpoint. Skips the OAuth
|
|
2854
|
-
* cloak blocks that must stay uncached: the CC billing header (block 0, a
|
|
2855
|
-
* per-request fingerprint) and the Claude Code identity instruction (block 1).
|
|
2856
|
-
*/
|
|
2857
|
-
function firstCacheableSystemIndex(blocks: readonly AnthropicSystemBlock[]): number {
|
|
2858
|
-
let index = 0;
|
|
2859
|
-
if (blocks[index]?.text?.startsWith(CLAUDE_BILLING_HEADER_PREFIX)) index++;
|
|
2860
|
-
if (blocks[index]?.text === claudeCodeSystemInstruction) index++;
|
|
2861
|
-
return index;
|
|
2862
|
-
}
|
|
2863
|
-
|
|
2864
2889
|
export function buildAnthropicSystemBlocks(
|
|
2865
2890
|
systemPrompt: readonly string[] | undefined,
|
|
2866
2891
|
options: SystemBlockOptions = {},
|
|
2867
2892
|
): AnthropicSystemBlock[] | undefined {
|
|
2868
|
-
const { includeClaudeCodeInstruction = false, extraInstructions = [], firstUserMessageText
|
|
2893
|
+
const { includeClaudeCodeInstruction = false, extraInstructions = [], firstUserMessageText } = options;
|
|
2869
2894
|
const sanitizedPrompts = normalizeSystemPrompts(systemPrompt);
|
|
2870
2895
|
const trimmedInstructions = extraInstructions.map(instruction => instruction.trim()).filter(Boolean);
|
|
2871
2896
|
const hasBillingHeader = sanitizedPrompts.some(prompt => prompt.startsWith(CLAUDE_BILLING_HEADER_PREFIX));
|
|
@@ -2882,7 +2907,6 @@ export function buildAnthropicSystemBlocks(
|
|
|
2882
2907
|
for (const prompt of sanitizedPrompts) {
|
|
2883
2908
|
blocks.push({ type: "text", text: prompt });
|
|
2884
2909
|
}
|
|
2885
|
-
cacheSystemPrefixBreakpoints(blocks, cacheControl, 3, firstCacheableSystemIndex(blocks));
|
|
2886
2910
|
|
|
2887
2911
|
return blocks;
|
|
2888
2912
|
}
|
|
@@ -2894,10 +2918,6 @@ export function buildAnthropicSystemBlocks(
|
|
|
2894
2918
|
for (const prompt of sanitizedPrompts) {
|
|
2895
2919
|
blocks.push({ type: "text", text: prompt });
|
|
2896
2920
|
}
|
|
2897
|
-
const lastIndex = blocks.length - 1;
|
|
2898
|
-
if (cacheControl && lastIndex >= 0 && blocks[lastIndex].cache_control == null) {
|
|
2899
|
-
blocks[lastIndex] = { ...blocks[lastIndex], cache_control: cloneAnthropicCacheControl(cacheControl) };
|
|
2900
|
-
}
|
|
2901
2921
|
return blocks.length > 0 ? blocks : undefined;
|
|
2902
2922
|
}
|
|
2903
2923
|
|
|
@@ -3149,29 +3169,17 @@ function ensureMaxTokensForThinking(params: MessageCreateParamsStreaming, maxAll
|
|
|
3149
3169
|
thinking.budget_tokens = clampedBudget;
|
|
3150
3170
|
}
|
|
3151
3171
|
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
if (blocks.length === 0) return false;
|
|
3161
|
-
for (let i = blocks.length - 1; i >= 0; i--) {
|
|
3162
|
-
if (blocks[i].type === "text") {
|
|
3163
|
-
if (blocks[i].cache_control != null) return false;
|
|
3164
|
-
blocks[i] = { ...blocks[i], cache_control: cloneAnthropicCacheControl(cacheControl) };
|
|
3165
|
-
return true;
|
|
3172
|
+
function applyCacheControlToLastBlock(blocks: ContentBlockParam[], cacheControl: AnthropicCacheControl): boolean {
|
|
3173
|
+
for (let index = blocks.length - 1; index >= 0; index--) {
|
|
3174
|
+
const block = blocks[index];
|
|
3175
|
+
// Anthropic rejects cache_control on generated reasoning and fallback
|
|
3176
|
+
// boundary blocks. Preserve the requested trailing boundary on every
|
|
3177
|
+
// ordinary content block, including tool use and tool results.
|
|
3178
|
+
if (block.type === "thinking" || block.type === "redacted_thinking" || block.type === "fallback") {
|
|
3179
|
+
continue;
|
|
3166
3180
|
}
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
// thinking/redacted_thinking blocks reject the field with a 400.
|
|
3170
|
-
for (let i = blocks.length - 1; i >= 0; i--) {
|
|
3171
|
-
const type = blocks[i].type;
|
|
3172
|
-
if (type === "thinking" || type === "redacted_thinking") continue;
|
|
3173
|
-
if (blocks[i].cache_control != null) return false;
|
|
3174
|
-
blocks[i] = { ...blocks[i], cache_control: cloneAnthropicCacheControl(cacheControl) };
|
|
3181
|
+
if ("cache_control" in block && block.cache_control != null) return false;
|
|
3182
|
+
blocks[index] = { ...block, cache_control: cloneAnthropicCacheControl(cacheControl) };
|
|
3175
3183
|
return true;
|
|
3176
3184
|
}
|
|
3177
3185
|
return false;
|
|
@@ -3180,28 +3188,10 @@ function applyCacheControlToLastTextBlock(
|
|
|
3180
3188
|
function applyPromptCaching(params: MessageCreateParamsStreaming, cacheControl?: AnthropicCacheControl): void {
|
|
3181
3189
|
if (!cacheControl) return;
|
|
3182
3190
|
|
|
3183
|
-
const MAX_CACHE_BREAKPOINTS = 4;
|
|
3184
|
-
let cacheBreakpointsUsed = countCacheControlBreakpoints(params);
|
|
3185
|
-
if (cacheBreakpointsUsed >= MAX_CACHE_BREAKPOINTS) return;
|
|
3186
|
-
let isCCLayout = false;
|
|
3187
|
-
|
|
3188
|
-
if (params.system && Array.isArray(params.system) && params.system.length > 0) {
|
|
3189
|
-
isCCLayout = params.system[0]?.text?.startsWith(CLAUDE_BILLING_HEADER_PREFIX) === true;
|
|
3190
|
-
const maxSystemBreakpoints = Math.min(3, MAX_CACHE_BREAKPOINTS - cacheBreakpointsUsed);
|
|
3191
|
-
cacheBreakpointsUsed += cacheSystemPrefixBreakpoints(
|
|
3192
|
-
params.system as AnthropicSystemBlock[],
|
|
3193
|
-
cacheControl,
|
|
3194
|
-
maxSystemBreakpoints,
|
|
3195
|
-
isCCLayout ? firstCacheableSystemIndex(params.system as AnthropicSystemBlock[]) : 0,
|
|
3196
|
-
);
|
|
3197
|
-
}
|
|
3198
|
-
|
|
3199
|
-
if (cacheBreakpointsUsed >= MAX_CACHE_BREAKPOINTS) return;
|
|
3200
|
-
|
|
3201
3191
|
// `convertAnthropicMessages` appends this neutral pad after a trailing
|
|
3202
3192
|
// assistant because Anthropic rejects assistant-prefill endings. It is absent
|
|
3203
|
-
// from the next normal turn, so
|
|
3204
|
-
//
|
|
3193
|
+
// from the next normal turn, so anchor the rolling window on the preceding
|
|
3194
|
+
// real assistant instead.
|
|
3205
3195
|
const trailingIndex = params.messages.length - 1;
|
|
3206
3196
|
const trailingMessage = params.messages[trailingIndex];
|
|
3207
3197
|
const hasTrailingAssistantPad =
|
|
@@ -3209,160 +3199,20 @@ function applyPromptCaching(params: MessageCreateParamsStreaming, cacheControl?:
|
|
|
3209
3199
|
trailingMessage.content === "Continue." &&
|
|
3210
3200
|
params.messages[trailingIndex - 1]?.role === "assistant";
|
|
3211
3201
|
const messageEnd = hasTrailingAssistantPad ? trailingIndex - 1 : trailingIndex;
|
|
3212
|
-
const
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
if (cacheBreakpointsUsed >= MAX_CACHE_BREAKPOINTS) break;
|
|
3216
|
-
const message = params.messages[i];
|
|
3202
|
+
const start = Math.max(0, messageEnd - 1);
|
|
3203
|
+
for (let index = messageEnd; index >= start; index--) {
|
|
3204
|
+
const message = params.messages[index];
|
|
3217
3205
|
if (!message) continue;
|
|
3218
3206
|
if (typeof message.content === "string") {
|
|
3219
3207
|
message.content = [
|
|
3220
3208
|
{ type: "text", text: message.content, cache_control: cloneAnthropicCacheControl(cacheControl) },
|
|
3221
3209
|
];
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
if (
|
|
3225
|
-
applyCacheControlToLastTextBlock(
|
|
3226
|
-
message.content as Array<ContentBlockParam & CacheControlBlock>,
|
|
3227
|
-
cacheControl,
|
|
3228
|
-
)
|
|
3229
|
-
) {
|
|
3230
|
-
cacheBreakpointsUsed++;
|
|
3231
|
-
}
|
|
3232
|
-
}
|
|
3233
|
-
}
|
|
3234
|
-
}
|
|
3235
|
-
|
|
3236
|
-
function normalizeCacheControlBlockTtl(block: CacheControlBlock, seenFiveMinute: { value: boolean }): void {
|
|
3237
|
-
const cacheControl = block.cache_control;
|
|
3238
|
-
if (!cacheControl) return;
|
|
3239
|
-
if (cacheControl.ttl !== "1h") {
|
|
3240
|
-
seenFiveMinute.value = true;
|
|
3241
|
-
return;
|
|
3242
|
-
}
|
|
3243
|
-
if (seenFiveMinute.value) {
|
|
3244
|
-
const normalized = cloneAnthropicCacheControl(cacheControl);
|
|
3245
|
-
delete normalized.ttl;
|
|
3246
|
-
block.cache_control = normalized;
|
|
3247
|
-
}
|
|
3248
|
-
}
|
|
3249
|
-
|
|
3250
|
-
function normalizeCacheControlTtlOrdering(params: MessageCreateParamsStreaming): void {
|
|
3251
|
-
const seenFiveMinute = { value: false };
|
|
3252
|
-
if (params.tools) {
|
|
3253
|
-
for (const tool of params.tools as Array<AnthropicWireTool & CacheControlBlock>) {
|
|
3254
|
-
normalizeCacheControlBlockTtl(tool, seenFiveMinute);
|
|
3255
|
-
}
|
|
3256
|
-
}
|
|
3257
|
-
if (params.system && Array.isArray(params.system)) {
|
|
3258
|
-
for (const block of params.system as Array<AnthropicSystemBlock & CacheControlBlock>) {
|
|
3259
|
-
normalizeCacheControlBlockTtl(block, seenFiveMinute);
|
|
3260
|
-
}
|
|
3261
|
-
}
|
|
3262
|
-
for (const message of params.messages) {
|
|
3263
|
-
if (!Array.isArray(message.content)) continue;
|
|
3264
|
-
for (const block of message.content as Array<ContentBlockParam & CacheControlBlock>) {
|
|
3265
|
-
normalizeCacheControlBlockTtl(block, seenFiveMinute);
|
|
3266
|
-
}
|
|
3267
|
-
}
|
|
3268
|
-
}
|
|
3269
|
-
|
|
3270
|
-
function findLastCacheControlIndex<T extends CacheControlBlock>(blocks: T[]): number {
|
|
3271
|
-
for (let index = blocks.length - 1; index >= 0; index--) {
|
|
3272
|
-
if (blocks[index]?.cache_control != null) return index;
|
|
3273
|
-
}
|
|
3274
|
-
return -1;
|
|
3275
|
-
}
|
|
3276
|
-
|
|
3277
|
-
function stripCacheControlExceptIndex<T extends CacheControlBlock>(
|
|
3278
|
-
blocks: T[],
|
|
3279
|
-
preserveIndex: number,
|
|
3280
|
-
excessCounter: { value: number },
|
|
3281
|
-
): void {
|
|
3282
|
-
for (let index = 0; index < blocks.length && excessCounter.value > 0; index++) {
|
|
3283
|
-
if (index === preserveIndex) continue;
|
|
3284
|
-
if (!blocks[index]?.cache_control) continue;
|
|
3285
|
-
delete blocks[index].cache_control;
|
|
3286
|
-
excessCounter.value--;
|
|
3287
|
-
}
|
|
3288
|
-
}
|
|
3289
|
-
|
|
3290
|
-
function stripAllCacheControl<T extends CacheControlBlock>(blocks: T[], excessCounter: { value: number }): void {
|
|
3291
|
-
for (const block of blocks) {
|
|
3292
|
-
if (excessCounter.value <= 0) return;
|
|
3293
|
-
if (!block.cache_control) continue;
|
|
3294
|
-
delete block.cache_control;
|
|
3295
|
-
excessCounter.value--;
|
|
3296
|
-
}
|
|
3297
|
-
}
|
|
3298
|
-
|
|
3299
|
-
function stripMessageCacheControl(
|
|
3300
|
-
messages: MessageCreateParamsStreaming["messages"],
|
|
3301
|
-
excessCounter: { value: number },
|
|
3302
|
-
): void {
|
|
3303
|
-
for (const message of messages) {
|
|
3304
|
-
if (excessCounter.value <= 0) return;
|
|
3305
|
-
if (!Array.isArray(message.content)) continue;
|
|
3306
|
-
for (const block of message.content as Array<ContentBlockParam & CacheControlBlock>) {
|
|
3307
|
-
if (excessCounter.value <= 0) return;
|
|
3308
|
-
if (!block.cache_control) continue;
|
|
3309
|
-
delete block.cache_control;
|
|
3310
|
-
excessCounter.value--;
|
|
3210
|
+
} else if (Array.isArray(message.content)) {
|
|
3211
|
+
applyCacheControlToLastBlock(message.content, cacheControl);
|
|
3311
3212
|
}
|
|
3312
3213
|
}
|
|
3313
3214
|
}
|
|
3314
3215
|
|
|
3315
|
-
function countCacheControlBreakpoints(params: MessageCreateParamsStreaming): number {
|
|
3316
|
-
let total = 0;
|
|
3317
|
-
if (params.tools) {
|
|
3318
|
-
for (const tool of params.tools as Array<AnthropicWireTool & CacheControlBlock>) {
|
|
3319
|
-
if (tool.cache_control) total++;
|
|
3320
|
-
}
|
|
3321
|
-
}
|
|
3322
|
-
if (params.system && Array.isArray(params.system)) {
|
|
3323
|
-
for (const block of params.system as Array<AnthropicSystemBlock & CacheControlBlock>) {
|
|
3324
|
-
if (block.cache_control) total++;
|
|
3325
|
-
}
|
|
3326
|
-
}
|
|
3327
|
-
for (const message of params.messages) {
|
|
3328
|
-
if (!Array.isArray(message.content)) continue;
|
|
3329
|
-
for (const block of message.content as Array<ContentBlockParam & CacheControlBlock>) {
|
|
3330
|
-
if (block.cache_control) total++;
|
|
3331
|
-
}
|
|
3332
|
-
}
|
|
3333
|
-
return total;
|
|
3334
|
-
}
|
|
3335
|
-
|
|
3336
|
-
function enforceCacheControlLimit(params: MessageCreateParamsStreaming, maxBreakpoints: number): void {
|
|
3337
|
-
const total = countCacheControlBreakpoints(params);
|
|
3338
|
-
if (total <= maxBreakpoints) return;
|
|
3339
|
-
const excessCounter = { value: total - maxBreakpoints };
|
|
3340
|
-
const systemBlocks =
|
|
3341
|
-
params.system && Array.isArray(params.system)
|
|
3342
|
-
? (params.system as Array<AnthropicSystemBlock & CacheControlBlock>)
|
|
3343
|
-
: [];
|
|
3344
|
-
const toolBlocks = (params.tools ?? []) as Array<AnthropicWireTool & CacheControlBlock>;
|
|
3345
|
-
const lastSystemIndex = findLastCacheControlIndex(systemBlocks);
|
|
3346
|
-
const lastToolIndex = findLastCacheControlIndex(toolBlocks);
|
|
3347
|
-
if (systemBlocks.length > 0) {
|
|
3348
|
-
stripCacheControlExceptIndex(systemBlocks, lastSystemIndex, excessCounter);
|
|
3349
|
-
}
|
|
3350
|
-
if (excessCounter.value <= 0) return;
|
|
3351
|
-
if (toolBlocks.length > 0) {
|
|
3352
|
-
stripCacheControlExceptIndex(toolBlocks, lastToolIndex, excessCounter);
|
|
3353
|
-
}
|
|
3354
|
-
if (excessCounter.value <= 0) return;
|
|
3355
|
-
stripMessageCacheControl(params.messages, excessCounter);
|
|
3356
|
-
if (excessCounter.value <= 0) return;
|
|
3357
|
-
if (systemBlocks.length > 0) {
|
|
3358
|
-
stripAllCacheControl(systemBlocks, excessCounter);
|
|
3359
|
-
}
|
|
3360
|
-
if (excessCounter.value <= 0) return;
|
|
3361
|
-
if (toolBlocks.length > 0) {
|
|
3362
|
-
stripAllCacheControl(toolBlocks, excessCounter);
|
|
3363
|
-
}
|
|
3364
|
-
}
|
|
3365
|
-
|
|
3366
3216
|
function usesAdaptiveThinkingTagOnly(model: Model<"anthropic-messages">): boolean {
|
|
3367
3217
|
const thinking = model.thinking;
|
|
3368
3218
|
if (thinking?.mode !== "anthropic-adaptive") return false;
|
|
@@ -3445,7 +3295,7 @@ function buildParams(
|
|
|
3445
3295
|
forceDemoteUnsignedThinking && model.compat.replayUnsignedThinking
|
|
3446
3296
|
? { ...model, compat: { ...model.compat, replayUnsignedThinking: false } }
|
|
3447
3297
|
: model;
|
|
3448
|
-
const { cacheControl } = getCacheControl(model, options?.cacheRetention
|
|
3298
|
+
const { cacheControl } = getCacheControl(model, options?.cacheRetention);
|
|
3449
3299
|
|
|
3450
3300
|
// Pre-compute system blocks so they occupy the right slot in the serialized body.
|
|
3451
3301
|
const shouldInjectClaudeCodeInstruction = isOAuthToken && !model.id.startsWith("claude-3-5-haiku");
|
|
@@ -3582,7 +3432,7 @@ function buildParams(
|
|
|
3582
3432
|
...(systemBlocks && { system: systemBlocks }),
|
|
3583
3433
|
...(tools !== undefined && { tools }),
|
|
3584
3434
|
...(metadata && { metadata }),
|
|
3585
|
-
max_tokens: Math.min(maxOutputTokens, options?.maxTokens
|
|
3435
|
+
max_tokens: Math.min(maxOutputTokens, options?.maxTokens ?? modelMaxTokens),
|
|
3586
3436
|
...(thinking && { thinking }),
|
|
3587
3437
|
...(contextManagement && { context_management: contextManagement }),
|
|
3588
3438
|
...(outputConfig && { output_config: outputConfig }),
|
|
@@ -3647,8 +3497,6 @@ function buildParams(
|
|
|
3647
3497
|
disableThinkingIfToolChoiceForced(params, model);
|
|
3648
3498
|
ensureMaxTokensForThinking(params, maxOutputTokens);
|
|
3649
3499
|
applyPromptCaching(params, cacheControl);
|
|
3650
|
-
enforceCacheControlLimit(params, 4);
|
|
3651
|
-
normalizeCacheControlTtlOrdering(params);
|
|
3652
3500
|
|
|
3653
3501
|
return params;
|
|
3654
3502
|
}
|