@warlock.js/ai-bedrock 5.29.0 → 5.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/cjs/index.cjs +350 -57
- package/cjs/index.cjs.map +1 -1
- package/esm/config.type.d.mts +31 -6
- package/esm/config.type.d.mts.map +1 -1
- package/esm/embedder.mjs +1 -1
- package/esm/embedder.mjs.map +1 -1
- package/esm/index.d.mts +3 -1
- package/esm/index.mjs +2 -1
- package/esm/known-capabilities.mjs +42 -4
- package/esm/known-capabilities.mjs.map +1 -1
- package/esm/known-pricing.d.mts +48 -0
- package/esm/known-pricing.d.mts.map +1 -0
- package/esm/known-pricing.mjs +99 -0
- package/esm/known-pricing.mjs.map +1 -0
- package/esm/known-vision-models.mjs +1 -1
- package/esm/known-vision-models.mjs.map +1 -1
- package/esm/model.mjs +122 -46
- package/esm/model.mjs.map +1 -1
- package/esm/provider-options.d.mts +8 -0
- package/esm/provider-options.d.mts.map +1 -0
- package/esm/provider-options.mjs +36 -0
- package/esm/provider-options.mjs.map +1 -0
- package/esm/sdk.d.mts +5 -1
- package/esm/sdk.d.mts.map +1 -1
- package/esm/sdk.mjs +35 -4
- package/esm/sdk.mjs.map +1 -1
- package/esm/utils/map-stop-reason.mjs +1 -1
- package/esm/utils/map-stop-reason.mjs.map +1 -1
- package/esm/utils/reasoning-blocks.mjs +1 -1
- package/esm/utils/reasoning-blocks.mjs.map +1 -1
- package/esm/utils/to-bedrock-messages.mjs +15 -2
- package/esm/utils/to-bedrock-messages.mjs.map +1 -1
- package/esm/utils/to-bedrock-tools.mjs +1 -1
- package/esm/utils/to-bedrock-tools.mjs.map +1 -1
- package/esm/utils/wrap-bedrock-error.mjs +6 -2
- package/esm/utils/wrap-bedrock-error.mjs.map +1 -1
- package/llms-full.txt +152 -38
- package/llms.txt +1 -1
- package/package.json +5 -4
- package/skills/setup-bedrock/SKILL.md +152 -38
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"known-capabilities.mjs","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"known-capabilities.mjs","names":[],"sources":["../../../../../../../packages/ai-bedrock/src/known-capabilities.ts"],"sourcesContent":["/**\n * Cost-truth capability inference for Bedrock Converse model ids.\n *\n * Bedrock model ids are provider-prefixed and version-suffixed\n * (`anthropic.claude-3-7-sonnet-20250219-v1:0`, `us.amazon.nova-pro-v1:0`),\n * so — exactly like `known-vision-models.ts` — a lowercase substring scan\n * is the only robust check across cross-region inference-profile prefixes\n * (`us.`, `eu.`, `apac.`) and date/version tags.\n *\n * Each predicate answers a single `ModelCapabilities` flag the agent reads\n * to decide whether to forward a cost-truth option (`reasoning`,\n * `cacheControl`) or up-front-reject an attachment (`pdf`). Unknown ids\n * default to `false` so an unsupported request fails fast with a clear\n * capability error instead of an opaque Bedrock `ValidationException`.\n * Every inference is overridable per-model via `bedrock.model({ name, … })`.\n */\n\n/**\n * Families that expose Anthropic-style extended thinking on Bedrock\n * Converse via `additionalModelRequestFields.thinking`. Only Claude 3.7\n * and the Claude 4 line (Sonnet / Opus / Haiku) support a configurable\n * thinking budget; earlier Claude, Nova, Llama, Mistral and Cohere do\n * not, so they are intentionally absent.\n */\nconst REASONING_CAPABLE_SUBSTRINGS = [\n \"claude-3-7\",\n \"claude-sonnet-4\",\n \"claude-opus-4\",\n \"claude-haiku-4\",\n];\n\n/**\n * Families that honor Converse `cachePoint` prompt-cache breakpoints.\n * Anthropic Claude 3.5+ / 3.7 / 4 / 5 and the Amazon Nova line support\n * cache points; text-only legacy families do not. Per the \"Supported\n * models\" table of https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-caching.html\n * (checked 2026-10-17).\n */\nconst PROMPT_CACHING_CAPABLE_SUBSTRINGS = [\n \"claude-3-5\",\n \"claude-3-7\",\n \"claude-sonnet-4\",\n \"claude-opus-4\",\n \"claude-haiku-4\",\n \"claude-sonnet-5\",\n \"claude-opus-5\",\n \"claude-haiku-5\",\n \"claude-fable-5\",\n \"claude-mythos-5\",\n \"nova-2-lite\",\n \"nova-lite\",\n \"nova-pro\",\n \"nova-premier\",\n \"nova-micro\",\n];\n\n/**\n * Families that accept Converse `document` content blocks (PDF / docx /\n * txt input). The multimodal Claude 3+ and Nova families support\n * document blocks; the substring set mirrors the vision-capable list\n * minus the image-only Llama entries (Llama on Bedrock takes images but\n * not document blocks via Converse).\n */\nconst PDF_CAPABLE_SUBSTRINGS = [\n \"claude-3\",\n \"claude-sonnet-4\",\n \"claude-opus-4\",\n \"claude-haiku-4\",\n \"nova-lite\",\n \"nova-pro\",\n \"nova-premier\",\n];\n\nfunction matchesAny(modelId: string, fragments: string[]): boolean {\n const normalized = modelId.toLowerCase();\n\n return fragments.some((fragment) => normalized.includes(fragment));\n}\n\n/**\n * Infer whether a Bedrock model id exposes extended-thinking / reasoning\n * (Claude 3.7 + Claude 4). When true the adapter forwards\n * `ModelCallOptions.reasoning` as Converse\n * `additionalModelRequestFields.thinking`.\n *\n * @example\n * inferReasoningCapability(\"anthropic.claude-3-7-sonnet-20250219-v1:0\"); // → true\n * inferReasoningCapability(\"us.amazon.nova-pro-v1:0\"); // → false\n */\nexport function inferReasoningCapability(modelId: string): boolean {\n return matchesAny(modelId, REASONING_CAPABLE_SUBSTRINGS);\n}\n\n/**\n * Infer whether a Bedrock model id honors Converse `cachePoint`\n * breakpoints (Claude 3.5+ / Nova). When true the adapter both maps\n * `ModelCallOptions.cacheControl` write breakpoints to cache points and\n * reports `Usage.cachedTokens` / `Usage.cacheWriteTokens`.\n *\n * @example\n * inferPromptCachingCapability(\"us.amazon.nova-pro-v1:0\"); // → true\n * inferPromptCachingCapability(\"meta.llama3-1-8b-instruct-v1:0\"); // → false\n */\nexport function inferPromptCachingCapability(modelId: string): boolean {\n return matchesAny(modelId, PROMPT_CACHING_CAPABLE_SUBSTRINGS);\n}\n\n/**\n * Infer whether a Bedrock model id accepts Converse `document` content\n * blocks (PDF / document input — Claude 3+ / Nova). When false the agent\n * rejects a PDF attachment up front instead of dropping it at the wire.\n *\n * @example\n * inferPdfCapability(\"anthropic.claude-3-5-sonnet-20240620-v1:0\"); // → true\n * inferPdfCapability(\"meta.llama3-2-90b-instruct-v1:0\"); // → false\n */\nexport function inferPdfCapability(modelId: string): boolean {\n return matchesAny(modelId, PDF_CAPABLE_SUBSTRINGS);\n}\n\n/**\n * Claude on Bedrock accepts a `cachePoint` in `system`, `messages` and\n * `tools`; Amazon Nova accepts one only in `system` and `messages`\n * (https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-caching.html,\n * \"Fields that accept prompt cache checkpoints\", checked 2026-10-17).\n * Unknown families get no tool cache point.\n *\n * @example\n * supportsToolCachePoint(\"global.anthropic.claude-sonnet-4-6\"); // true\n * supportsToolCachePoint(\"amazon.nova-pro-v1:0\"); // false\n */\nexport function supportsToolCachePoint(modelId: string): boolean {\n return modelId.toLowerCase().includes(\"anthropic.claude\");\n}\n\n/** Claude families whose cache points accept the 1-hour TTL. */\nconst ONE_HOUR_TTL_PATTERN =\n /anthropic\\.claude-(?:(?:opus|sonnet|haiku|fable|mythos)-5|opus-4-[5-9]|sonnet-4-[5-9]|haiku-4-5)/;\n\n/**\n * Claude models whose Converse `cachePoint` accepts `ttl: \"1h\"`: Claude\n * Haiku 4.5, the 4.5+ Sonnet / Opus line and every Claude 5 family. Any\n * other model gets no `ttl` field (the 5-minute default), since AWS\n * warns that sending it to a 5-minute-only model \"can result in a\n * ValidationException\" (same page, checked 2026-10-17).\n *\n * @example\n * supportsOneHourCacheTtl(\"anthropic.claude-haiku-4-5-20251001-v1:0\"); // true\n * supportsOneHourCacheTtl(\"anthropic.claude-3-7-sonnet-20250219-v1:0\"); // false\n */\nexport function supportsOneHourCacheTtl(modelId: string): boolean {\n return ONE_HOUR_TTL_PATTERN.test(modelId.toLowerCase());\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAwBA,MAAM,+BAA+B;CACnC;CACA;CACA;CACA;AACF;;;;;;;;AASA,MAAM,oCAAoC;CACxC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;;;;;;;AASA,MAAM,yBAAyB;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,SAAS,WAAW,SAAiB,WAA8B;CACjE,MAAM,aAAa,QAAQ,YAAY;CAEvC,OAAO,UAAU,MAAM,aAAa,WAAW,SAAS,QAAQ,CAAC;AACnE;;;;;;;;;;;AAYA,SAAgB,yBAAyB,SAA0B;CACjE,OAAO,WAAW,SAAS,4BAA4B;AACzD;;;;;;;;;;;AAYA,SAAgB,6BAA6B,SAA0B;CACrE,OAAO,WAAW,SAAS,iCAAiC;AAC9D;;;;;;;;;;AAWA,SAAgB,mBAAmB,SAA0B;CAC3D,OAAO,WAAW,SAAS,sBAAsB;AACnD;;;;;;;;;;;;AAaA,SAAgB,uBAAuB,SAA0B;CAC/D,OAAO,QAAQ,YAAY,CAAC,CAAC,SAAS,kBAAkB;AAC1D;;AAGA,MAAM,uBACJ;;;;;;;;;;;;AAaF,SAAgB,wBAAwB,SAA0B;CAChE,OAAO,qBAAqB,KAAK,QAAQ,YAAY,CAAC;AACxD"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { ModelPricing } from "@warlock.js/ai";
|
|
2
|
+
|
|
3
|
+
//#region ../../packages/ai-bedrock/src/known-pricing.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Bedrock on-demand list prices for Anthropic Claude, USD per 1,000,000
|
|
6
|
+
* tokens, keyed by Bedrock model id (without an inference-profile
|
|
7
|
+
* prefix). `cacheWrite` is the 5-minute write rate, `cacheWrite1h` the
|
|
8
|
+
* 1-hour write rate, `cachedInput` the cache-read rate.
|
|
9
|
+
*
|
|
10
|
+
* Source: https://aws.amazon.com/bedrock/pricing/ — the page's own price
|
|
11
|
+
* feed for "US East (N. Virginia)", fetched 2026-10-17 (Sonnet 5.5 cache
|
|
12
|
+
* reads already at the rate effective 2026-10-07). Model ids from
|
|
13
|
+
* https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-caching.html.
|
|
14
|
+
*
|
|
15
|
+
* Two tables, because AWS prices them differently:
|
|
16
|
+
* - {@link BEDROCK_GLOBAL_PRICING} — `global.` cross-Region inference
|
|
17
|
+
* profiles.
|
|
18
|
+
* - {@link BEDROCK_US_PRICING} — `us.` geographic profiles (the
|
|
19
|
+
* "Geo / In-region" rates, 10% above global for these models).
|
|
20
|
+
*
|
|
21
|
+
* In-Region ids without a profile prefix, other geographies (`eu.`,
|
|
22
|
+
* `apac.`, …), Claude Haiku 5.5 and non-Claude models stay unpriced —
|
|
23
|
+
* their rates vary by Region or were not verified — so pass `pricing`
|
|
24
|
+
* yourself for them.
|
|
25
|
+
*/
|
|
26
|
+
declare const BEDROCK_GLOBAL_PRICING: Readonly<Record<string, ModelPricing>>;
|
|
27
|
+
/** `us.` geographic-profile prices — see {@link BEDROCK_GLOBAL_PRICING}. */
|
|
28
|
+
declare const BEDROCK_US_PRICING: Readonly<Record<string, ModelPricing>>;
|
|
29
|
+
/**
|
|
30
|
+
* Look up the built-in price for a Bedrock model id or inference-profile
|
|
31
|
+
* id: `global.<model>` reads {@link BEDROCK_GLOBAL_PRICING}, `us.<model>`
|
|
32
|
+
* reads {@link BEDROCK_US_PRICING}; anything else is `undefined`.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* bedrockPricingFor("global.anthropic.claude-sonnet-4-6"); // { input: 3, output: 15, … }
|
|
36
|
+
* bedrockPricingFor("anthropic.claude-sonnet-4-6"); // undefined — in-Region rates vary
|
|
37
|
+
*/
|
|
38
|
+
declare function bedrockPricingFor(modelId: string): ModelPricing | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* Fill the Claude cache-write rates (5-minute 1.25x, 1-hour 2x the input
|
|
41
|
+
* rate — the ratio of every Claude row in the tables above) into a
|
|
42
|
+
* caller-supplied entry for a Claude model that omits them. Non-Claude
|
|
43
|
+
* models are returned unchanged.
|
|
44
|
+
*/
|
|
45
|
+
declare function withClaudeCacheWriteRates(modelId: string, pricing: ModelPricing | undefined): ModelPricing | undefined;
|
|
46
|
+
//#endregion
|
|
47
|
+
export { BEDROCK_GLOBAL_PRICING, BEDROCK_US_PRICING, bedrockPricingFor, withClaudeCacheWriteRates };
|
|
48
|
+
//# sourceMappingURL=known-pricing.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"known-pricing.d.mts","names":[],"sources":["../../../../../../../packages/ai-bedrock/src/known-pricing.ts"],"mappings":";;;;;AAwBA;;;;;;;;;;;;AAAyE;AAiBzE;;;;;;;cAjBa,sBAAA,EAAwB,QAAA,CAAS,MAAA,SAAe,YAAA;;cAiBhD,kBAAA,EAAoB,QAAA,CAAS,MAAA,SAAe,YAAA;;;AAAY;AAyBrE;;;;AAAgE;AAkBhE;iBAlBgB,iBAAA,CAAkB,OAAA,WAAkB,YAAY;;;;;;;iBAkBhD,yBAAA,CACd,OAAA,UACA,OAAA,EAAS,YAAA,eACR,YAAY"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
//#region ../../packages/ai-bedrock/src/known-pricing.ts
|
|
2
|
+
/**
|
|
3
|
+
* Bedrock on-demand list prices for Anthropic Claude, USD per 1,000,000
|
|
4
|
+
* tokens, keyed by Bedrock model id (without an inference-profile
|
|
5
|
+
* prefix). `cacheWrite` is the 5-minute write rate, `cacheWrite1h` the
|
|
6
|
+
* 1-hour write rate, `cachedInput` the cache-read rate.
|
|
7
|
+
*
|
|
8
|
+
* Source: https://aws.amazon.com/bedrock/pricing/ — the page's own price
|
|
9
|
+
* feed for "US East (N. Virginia)", fetched 2026-10-17 (Sonnet 5.5 cache
|
|
10
|
+
* reads already at the rate effective 2026-10-07). Model ids from
|
|
11
|
+
* https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-caching.html.
|
|
12
|
+
*
|
|
13
|
+
* Two tables, because AWS prices them differently:
|
|
14
|
+
* - {@link BEDROCK_GLOBAL_PRICING} — `global.` cross-Region inference
|
|
15
|
+
* profiles.
|
|
16
|
+
* - {@link BEDROCK_US_PRICING} — `us.` geographic profiles (the
|
|
17
|
+
* "Geo / In-region" rates, 10% above global for these models).
|
|
18
|
+
*
|
|
19
|
+
* In-Region ids without a profile prefix, other geographies (`eu.`,
|
|
20
|
+
* `apac.`, …), Claude Haiku 5.5 and non-Claude models stay unpriced —
|
|
21
|
+
* their rates vary by Region or were not verified — so pass `pricing`
|
|
22
|
+
* yourself for them.
|
|
23
|
+
*/
|
|
24
|
+
const BEDROCK_GLOBAL_PRICING = {
|
|
25
|
+
"anthropic.claude-sonnet-5-5": claude(2, 10, .1),
|
|
26
|
+
"anthropic.claude-opus-5-5": claude(4, 20, .2),
|
|
27
|
+
"anthropic.claude-fable-5-1": claude(10, 50, .25),
|
|
28
|
+
"anthropic.claude-opus-5": claude(5, 25, .5),
|
|
29
|
+
"anthropic.claude-sonnet-5": claude(2, 10, .2),
|
|
30
|
+
"anthropic.claude-fable-5": claude(10, 50, 1),
|
|
31
|
+
"anthropic.claude-opus-4-8": claude(5, 25, .5),
|
|
32
|
+
"anthropic.claude-opus-4-7": claude(5, 25, .5),
|
|
33
|
+
"anthropic.claude-opus-4-6-v1": claude(5, 25, .5),
|
|
34
|
+
"anthropic.claude-sonnet-4-6": claude(3, 15, .3),
|
|
35
|
+
"anthropic.claude-opus-4-5-20251101-v1:0": claude(5, 25, .5),
|
|
36
|
+
"anthropic.claude-sonnet-4-5-20250929-v1:0": claude(3, 15, .3),
|
|
37
|
+
"anthropic.claude-haiku-4-5-20251001-v1:0": claude(1, 5, .1)
|
|
38
|
+
};
|
|
39
|
+
/** `us.` geographic-profile prices — see {@link BEDROCK_GLOBAL_PRICING}. */
|
|
40
|
+
const BEDROCK_US_PRICING = {
|
|
41
|
+
"anthropic.claude-sonnet-5-5": claude(2.2, 11, .11),
|
|
42
|
+
"anthropic.claude-opus-5-5": claude(4.4, 22, .22),
|
|
43
|
+
"anthropic.claude-fable-5-1": claude(11, 55, .275),
|
|
44
|
+
"anthropic.claude-opus-5": claude(5.5, 27.5, .55),
|
|
45
|
+
"anthropic.claude-sonnet-5": claude(2.2, 11, .22),
|
|
46
|
+
"anthropic.claude-fable-5": claude(11, 55, 1.1),
|
|
47
|
+
"anthropic.claude-opus-4-8": claude(5.5, 27.5, .55),
|
|
48
|
+
"anthropic.claude-opus-4-7": claude(5.5, 27.5, .55),
|
|
49
|
+
"anthropic.claude-opus-4-6-v1": claude(5.5, 27.5, .55),
|
|
50
|
+
"anthropic.claude-sonnet-4-6": claude(3.3, 16.5, .33),
|
|
51
|
+
"anthropic.claude-opus-4-5-20251101-v1:0": claude(5.5, 27.5, .55),
|
|
52
|
+
"anthropic.claude-sonnet-4-5-20250929-v1:0": claude(3.3, 16.5, .33),
|
|
53
|
+
"anthropic.claude-haiku-4-5-20251001-v1:0": claude(1.1, 5.5, .11)
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Look up the built-in price for a Bedrock model id or inference-profile
|
|
57
|
+
* id: `global.<model>` reads {@link BEDROCK_GLOBAL_PRICING}, `us.<model>`
|
|
58
|
+
* reads {@link BEDROCK_US_PRICING}; anything else is `undefined`.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* bedrockPricingFor("global.anthropic.claude-sonnet-4-6"); // { input: 3, output: 15, … }
|
|
62
|
+
* bedrockPricingFor("anthropic.claude-sonnet-4-6"); // undefined — in-Region rates vary
|
|
63
|
+
*/
|
|
64
|
+
function bedrockPricingFor(modelId) {
|
|
65
|
+
if (modelId.startsWith("global.")) return BEDROCK_GLOBAL_PRICING[modelId.slice(7)];
|
|
66
|
+
if (modelId.startsWith("us.")) return BEDROCK_US_PRICING[modelId.slice(3)];
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Fill the Claude cache-write rates (5-minute 1.25x, 1-hour 2x the input
|
|
70
|
+
* rate — the ratio of every Claude row in the tables above) into a
|
|
71
|
+
* caller-supplied entry for a Claude model that omits them. Non-Claude
|
|
72
|
+
* models are returned unchanged.
|
|
73
|
+
*/
|
|
74
|
+
function withClaudeCacheWriteRates(modelId, pricing) {
|
|
75
|
+
if (!pricing || !modelId.toLowerCase().includes("anthropic.claude")) return pricing;
|
|
76
|
+
if (pricing.cacheWrite !== void 0 && pricing.cacheWrite1h !== void 0) return pricing;
|
|
77
|
+
return {
|
|
78
|
+
...pricing,
|
|
79
|
+
cacheWrite: pricing.cacheWrite ?? pricing.cachedOutput ?? round(pricing.input * 1.25),
|
|
80
|
+
cacheWrite1h: pricing.cacheWrite1h ?? round(pricing.input * 2)
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function claude(input, output, cachedInput) {
|
|
84
|
+
return {
|
|
85
|
+
input,
|
|
86
|
+
output,
|
|
87
|
+
cachedInput,
|
|
88
|
+
cacheWrite: round(input * 1.25),
|
|
89
|
+
cacheWrite1h: round(input * 2)
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/** Trim binary floating-point noise (2.2 * 1.25 = 2.7500000000000004). */
|
|
93
|
+
function round(value) {
|
|
94
|
+
return Math.round(value * 1e9) / 1e9;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
//#endregion
|
|
98
|
+
export { BEDROCK_GLOBAL_PRICING, BEDROCK_US_PRICING, bedrockPricingFor, withClaudeCacheWriteRates };
|
|
99
|
+
//# sourceMappingURL=known-pricing.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"known-pricing.mjs","names":[],"sources":["../../../../../../../packages/ai-bedrock/src/known-pricing.ts"],"sourcesContent":["import type { ModelPricing } from \"@warlock.js/ai\";\n\n/**\n * Bedrock on-demand list prices for Anthropic Claude, USD per 1,000,000\n * tokens, keyed by Bedrock model id (without an inference-profile\n * prefix). `cacheWrite` is the 5-minute write rate, `cacheWrite1h` the\n * 1-hour write rate, `cachedInput` the cache-read rate.\n *\n * Source: https://aws.amazon.com/bedrock/pricing/ — the page's own price\n * feed for \"US East (N. Virginia)\", fetched 2026-10-17 (Sonnet 5.5 cache\n * reads already at the rate effective 2026-10-07). Model ids from\n * https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-caching.html.\n *\n * Two tables, because AWS prices them differently:\n * - {@link BEDROCK_GLOBAL_PRICING} — `global.` cross-Region inference\n * profiles.\n * - {@link BEDROCK_US_PRICING} — `us.` geographic profiles (the\n * \"Geo / In-region\" rates, 10% above global for these models).\n *\n * In-Region ids without a profile prefix, other geographies (`eu.`,\n * `apac.`, …), Claude Haiku 5.5 and non-Claude models stay unpriced —\n * their rates vary by Region or were not verified — so pass `pricing`\n * yourself for them.\n */\nexport const BEDROCK_GLOBAL_PRICING: Readonly<Record<string, ModelPricing>> = {\n \"anthropic.claude-sonnet-5-5\": claude(2, 10, 0.1),\n \"anthropic.claude-opus-5-5\": claude(4, 20, 0.2),\n \"anthropic.claude-fable-5-1\": claude(10, 50, 0.25),\n \"anthropic.claude-opus-5\": claude(5, 25, 0.5),\n \"anthropic.claude-sonnet-5\": claude(2, 10, 0.2),\n \"anthropic.claude-fable-5\": claude(10, 50, 1),\n \"anthropic.claude-opus-4-8\": claude(5, 25, 0.5),\n \"anthropic.claude-opus-4-7\": claude(5, 25, 0.5),\n \"anthropic.claude-opus-4-6-v1\": claude(5, 25, 0.5),\n \"anthropic.claude-sonnet-4-6\": claude(3, 15, 0.3),\n \"anthropic.claude-opus-4-5-20251101-v1:0\": claude(5, 25, 0.5),\n \"anthropic.claude-sonnet-4-5-20250929-v1:0\": claude(3, 15, 0.3),\n \"anthropic.claude-haiku-4-5-20251001-v1:0\": claude(1, 5, 0.1),\n};\n\n/** `us.` geographic-profile prices — see {@link BEDROCK_GLOBAL_PRICING}. */\nexport const BEDROCK_US_PRICING: Readonly<Record<string, ModelPricing>> = {\n \"anthropic.claude-sonnet-5-5\": claude(2.2, 11, 0.11),\n \"anthropic.claude-opus-5-5\": claude(4.4, 22, 0.22),\n \"anthropic.claude-fable-5-1\": claude(11, 55, 0.275),\n \"anthropic.claude-opus-5\": claude(5.5, 27.5, 0.55),\n \"anthropic.claude-sonnet-5\": claude(2.2, 11, 0.22),\n \"anthropic.claude-fable-5\": claude(11, 55, 1.1),\n \"anthropic.claude-opus-4-8\": claude(5.5, 27.5, 0.55),\n \"anthropic.claude-opus-4-7\": claude(5.5, 27.5, 0.55),\n \"anthropic.claude-opus-4-6-v1\": claude(5.5, 27.5, 0.55),\n \"anthropic.claude-sonnet-4-6\": claude(3.3, 16.5, 0.33),\n \"anthropic.claude-opus-4-5-20251101-v1:0\": claude(5.5, 27.5, 0.55),\n \"anthropic.claude-sonnet-4-5-20250929-v1:0\": claude(3.3, 16.5, 0.33),\n \"anthropic.claude-haiku-4-5-20251001-v1:0\": claude(1.1, 5.5, 0.11),\n};\n\n/**\n * Look up the built-in price for a Bedrock model id or inference-profile\n * id: `global.<model>` reads {@link BEDROCK_GLOBAL_PRICING}, `us.<model>`\n * reads {@link BEDROCK_US_PRICING}; anything else is `undefined`.\n *\n * @example\n * bedrockPricingFor(\"global.anthropic.claude-sonnet-4-6\"); // { input: 3, output: 15, … }\n * bedrockPricingFor(\"anthropic.claude-sonnet-4-6\"); // undefined — in-Region rates vary\n */\nexport function bedrockPricingFor(modelId: string): ModelPricing | undefined {\n if (modelId.startsWith(\"global.\")) {\n return BEDROCK_GLOBAL_PRICING[modelId.slice(\"global.\".length)];\n }\n\n if (modelId.startsWith(\"us.\")) {\n return BEDROCK_US_PRICING[modelId.slice(\"us.\".length)];\n }\n\n return undefined;\n}\n\n/**\n * Fill the Claude cache-write rates (5-minute 1.25x, 1-hour 2x the input\n * rate — the ratio of every Claude row in the tables above) into a\n * caller-supplied entry for a Claude model that omits them. Non-Claude\n * models are returned unchanged.\n */\nexport function withClaudeCacheWriteRates(\n modelId: string,\n pricing: ModelPricing | undefined,\n): ModelPricing | undefined {\n if (!pricing || !modelId.toLowerCase().includes(\"anthropic.claude\")) {\n return pricing;\n }\n\n if (pricing.cacheWrite !== undefined && pricing.cacheWrite1h !== undefined) {\n return pricing;\n }\n\n return {\n ...pricing,\n cacheWrite: pricing.cacheWrite ?? pricing.cachedOutput ?? round(pricing.input * 1.25),\n cacheWrite1h: pricing.cacheWrite1h ?? round(pricing.input * 2),\n };\n}\n\nfunction claude(input: number, output: number, cachedInput: number): ModelPricing {\n return {\n input,\n output,\n cachedInput,\n cacheWrite: round(input * 1.25),\n cacheWrite1h: round(input * 2),\n };\n}\n\n/** Trim binary floating-point noise (2.2 * 1.25 = 2.7500000000000004). */\nfunction round(value: number): number {\n return Math.round(value * 1e9) / 1e9;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAwBA,MAAa,yBAAiE;CAC5E,+BAA+B,OAAO,GAAG,IAAI,EAAG;CAChD,6BAA6B,OAAO,GAAG,IAAI,EAAG;CAC9C,8BAA8B,OAAO,IAAI,IAAI,GAAI;CACjD,2BAA2B,OAAO,GAAG,IAAI,EAAG;CAC5C,6BAA6B,OAAO,GAAG,IAAI,EAAG;CAC9C,4BAA4B,OAAO,IAAI,IAAI,CAAC;CAC5C,6BAA6B,OAAO,GAAG,IAAI,EAAG;CAC9C,6BAA6B,OAAO,GAAG,IAAI,EAAG;CAC9C,gCAAgC,OAAO,GAAG,IAAI,EAAG;CACjD,+BAA+B,OAAO,GAAG,IAAI,EAAG;CAChD,2CAA2C,OAAO,GAAG,IAAI,EAAG;CAC5D,6CAA6C,OAAO,GAAG,IAAI,EAAG;CAC9D,4CAA4C,OAAO,GAAG,GAAG,EAAG;AAC9D;;AAGA,MAAa,qBAA6D;CACxE,+BAA+B,OAAO,KAAK,IAAI,GAAI;CACnD,6BAA6B,OAAO,KAAK,IAAI,GAAI;CACjD,8BAA8B,OAAO,IAAI,IAAI,IAAK;CAClD,2BAA2B,OAAO,KAAK,MAAM,GAAI;CACjD,6BAA6B,OAAO,KAAK,IAAI,GAAI;CACjD,4BAA4B,OAAO,IAAI,IAAI,GAAG;CAC9C,6BAA6B,OAAO,KAAK,MAAM,GAAI;CACnD,6BAA6B,OAAO,KAAK,MAAM,GAAI;CACnD,gCAAgC,OAAO,KAAK,MAAM,GAAI;CACtD,+BAA+B,OAAO,KAAK,MAAM,GAAI;CACrD,2CAA2C,OAAO,KAAK,MAAM,GAAI;CACjE,6CAA6C,OAAO,KAAK,MAAM,GAAI;CACnE,4CAA4C,OAAO,KAAK,KAAK,GAAI;AACnE;;;;;;;;;;AAWA,SAAgB,kBAAkB,SAA2C;CAC3E,IAAI,QAAQ,WAAW,SAAS,GAC9B,OAAO,uBAAuB,QAAQ,MAAM,CAAgB;CAG9D,IAAI,QAAQ,WAAW,KAAK,GAC1B,OAAO,mBAAmB,QAAQ,MAAM,CAAY;AAIxD;;;;;;;AAQA,SAAgB,0BACd,SACA,SAC0B;CAC1B,IAAI,CAAC,WAAW,CAAC,QAAQ,YAAY,CAAC,CAAC,SAAS,kBAAkB,GAChE,OAAO;CAGT,IAAI,QAAQ,eAAe,UAAa,QAAQ,iBAAiB,QAC/D,OAAO;CAGT,OAAO;EACL,GAAG;EACH,YAAY,QAAQ,cAAc,QAAQ,gBAAgB,MAAM,QAAQ,QAAQ,IAAI;EACpF,cAAc,QAAQ,gBAAgB,MAAM,QAAQ,QAAQ,CAAC;CAC/D;AACF;AAEA,SAAS,OAAO,OAAe,QAAgB,aAAmC;CAChF,OAAO;EACL;EACA;EACA;EACA,YAAY,MAAM,QAAQ,IAAI;EAC9B,cAAc,MAAM,QAAQ,CAAC;CAC/B;AACF;;AAGA,SAAS,MAAM,OAAuB;CACpC,OAAO,KAAK,MAAM,QAAQ,GAAG,IAAI;AACnC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"known-vision-models.mjs","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"known-vision-models.mjs","names":[],"sources":["../../../../../../../packages/ai-bedrock/src/known-vision-models.ts"],"sourcesContent":["/**\n * Substrings that identify Bedrock model ids whose family accepts image\n * input on the Converse API.\n *\n * Bedrock model ids are provider-prefixed and version-suffixed\n * (`anthropic.claude-3-5-sonnet-20240620-v1:0`, `us.amazon.nova-pro-v1:0`,\n * `meta.llama3-2-90b-instruct-v1:0`), so a substring match is the only\n * robust check across the cross-region inference-profile prefixes\n * (`us.`, `eu.`, `apac.`) and date/version tags.\n *\n * Multimodal families covered: Anthropic Claude 3 / 3.5 / 3.7 / 4,\n * Amazon Nova Lite/Pro/Premier, Meta Llama 3.2 (11B/90B) and Llama 4.\n * Text-only families (Llama 3/3.1, Titan Text, Mistral 7B, Cohere\n * Command) are intentionally absent. Override per-model via\n * `bedrock.model({ name, vision: true | false })`.\n */\nconst VISION_CAPABLE_SUBSTRINGS = [\n \"claude-3\",\n \"claude-sonnet-4\",\n \"claude-opus-4\",\n \"claude-haiku-4\",\n \"nova-lite\",\n \"nova-pro\",\n \"nova-premier\",\n \"llama3-2-11b\",\n \"llama3-2-90b\",\n \"llama4\",\n];\n\n/**\n * Infer whether a Bedrock model id supports vision based on the known\n * multimodal-family substrings. Unknown ids default to `false` so that\n * passing an image attachment to an unsupported model surfaces a clear,\n * agent-side capability error instead of an opaque Bedrock validation\n * fault.\n *\n * @example\n * inferVisionCapability(\"anthropic.claude-3-5-sonnet-20240620-v1:0\"); // → true\n * inferVisionCapability(\"us.amazon.nova-pro-v1:0\"); // → true\n * inferVisionCapability(\"meta.llama3-1-8b-instruct-v1:0\"); // → false\n * inferVisionCapability(\"amazon.titan-text-express-v1\"); // → false\n */\nexport function inferVisionCapability(modelId: string): boolean {\n const normalized = modelId.toLowerCase();\n\n return VISION_CAPABLE_SUBSTRINGS.some((fragment) => normalized.includes(fragment));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAgBA,MAAM,4BAA4B;CAChC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;;;;;;;;;;;;;AAeA,SAAgB,sBAAsB,SAA0B;CAC9D,MAAM,aAAa,QAAQ,YAAY;CAEvC,OAAO,0BAA0B,MAAM,aAAa,WAAW,SAAS,QAAQ,CAAC;AACnF"}
|
package/esm/model.mjs
CHANGED
|
@@ -4,14 +4,20 @@ import { toBedrockMessages } from "./utils/to-bedrock-messages.mjs";
|
|
|
4
4
|
import { toBedrockToolConfig } from "./utils/to-bedrock-tools.mjs";
|
|
5
5
|
import { wrapBedrockError } from "./utils/wrap-bedrock-error.mjs";
|
|
6
6
|
import "./utils/index.mjs";
|
|
7
|
-
import {
|
|
7
|
+
import { mergeProviderBody } from "./provider-options.mjs";
|
|
8
|
+
import { inferPdfCapability, inferPromptCachingCapability, inferReasoningCapability, supportsOneHourCacheTtl, supportsToolCachePoint } from "./known-capabilities.mjs";
|
|
9
|
+
import { bedrockPricingFor, withClaudeCacheWriteRates } from "./known-pricing.mjs";
|
|
8
10
|
import { inferVisionCapability } from "./known-vision-models.mjs";
|
|
9
|
-
import { ConverseCommand, ConverseStreamCommand } from "@aws-sdk/client-bedrock-runtime";
|
|
10
|
-
import { safeJsonParse } from "@warlock.js/ai";
|
|
11
|
+
import { ConverseCommand, ConverseStreamCommand, CountTokensCommand } from "@aws-sdk/client-bedrock-runtime";
|
|
12
|
+
import { InvalidRequestError, attachCost, resolveStreamChunks, safeJsonParse, selectProviderTools } from "@warlock.js/ai";
|
|
11
13
|
import { log } from "@warlock.js/logger";
|
|
12
14
|
|
|
13
|
-
//#region
|
|
15
|
+
//#region ../../packages/ai-bedrock/src/model.ts
|
|
14
16
|
const LOG_MODULE = "ai.bedrock";
|
|
17
|
+
/** `provider` value of `ai.providerTool()` entries this adapter sends verbatim. */
|
|
18
|
+
const BEDROCK_WIRE_FORMAT = "bedrock";
|
|
19
|
+
/** Converse `ToolUseBlock.type` of a tool use run by Bedrock itself (SDK `ToolUseType`). */
|
|
20
|
+
const SERVER_TOOL_USE = "server_tool_use";
|
|
15
21
|
/** Default output allowance added to a thinking budget when maxTokens is unset. */
|
|
16
22
|
const DEFAULT_MAX_TOKENS = 4096;
|
|
17
23
|
const MIN_THINKING_BUDGET = 1024;
|
|
@@ -72,7 +78,7 @@ var BedrockModel = class {
|
|
|
72
78
|
this.config = config;
|
|
73
79
|
this.name = config.name;
|
|
74
80
|
this.provider = provider;
|
|
75
|
-
this.pricing = config.pricing;
|
|
81
|
+
this.pricing = withClaudeCacheWriteRates(config.name, config.pricing ?? bedrockPricingFor(config.name));
|
|
76
82
|
this.capabilities = {
|
|
77
83
|
structuredOutput: config.structuredOutput ?? true,
|
|
78
84
|
vision: config.vision ?? inferVisionCapability(config.name),
|
|
@@ -103,7 +109,7 @@ var BedrockModel = class {
|
|
|
103
109
|
}
|
|
104
110
|
const blocks = response.output?.message?.content ?? [];
|
|
105
111
|
const finishReason = mapStopReason(response.stopReason);
|
|
106
|
-
const usage = this.extractUsage(response.usage);
|
|
112
|
+
const usage = attachCost(this.extractUsage(response.usage), this.pricing);
|
|
107
113
|
const toolCalls = this.extractToolCalls(blocks);
|
|
108
114
|
this.logger.debug(LOG_MODULE, "response", "Converse call succeeded", {
|
|
109
115
|
finishReason,
|
|
@@ -116,11 +122,36 @@ var BedrockModel = class {
|
|
|
116
122
|
toolCalls
|
|
117
123
|
};
|
|
118
124
|
}
|
|
125
|
+
/** Count native input tokens from the same Converse conversation and tool configuration. */
|
|
126
|
+
async countTokens(messages, options) {
|
|
127
|
+
const request = this.buildRequest(messages, options);
|
|
128
|
+
try {
|
|
129
|
+
const response = await this.client.send(new CountTokensCommand({
|
|
130
|
+
modelId: request.modelId,
|
|
131
|
+
input: { converse: {
|
|
132
|
+
messages: request.messages,
|
|
133
|
+
system: request.system,
|
|
134
|
+
toolConfig: request.toolConfig,
|
|
135
|
+
additionalModelRequestFields: request.additionalModelRequestFields
|
|
136
|
+
} }
|
|
137
|
+
}), options?.signal ? { abortSignal: options.signal } : void 0);
|
|
138
|
+
if (response.inputTokens === void 0) throw new InvalidRequestError("Bedrock countTokens returned no inputTokens.");
|
|
139
|
+
return response.inputTokens;
|
|
140
|
+
} catch (thrown) {
|
|
141
|
+
throw this.logAndWrap(thrown);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
119
144
|
/**
|
|
120
145
|
* Incremental streaming completion via ConverseStream. Yields neutral
|
|
121
146
|
* `ModelStreamChunk`s — `delta` for text, `tool-call` once a
|
|
122
147
|
* `toolUse` block's accumulated input JSON is complete, and a
|
|
123
148
|
* terminal `done` with the final finish reason + usage totals.
|
|
149
|
+
*
|
|
150
|
+
* With `options.streamChunks` it also yields `reasoning` for each
|
|
151
|
+
* `reasoningContent.text` delta and `tool-args` for each client
|
|
152
|
+
* `toolUse.input` delta. Usage arrives once, in the final `metadata`
|
|
153
|
+
* event, so no `usage` chunk is emitted. A system tool's
|
|
154
|
+
* `server_tool_use` block never becomes a `tool-call`.
|
|
124
155
|
*/
|
|
125
156
|
async *stream(messages, options) {
|
|
126
157
|
this.logger.debug(LOG_MODULE, "request", "Starting ConverseStream call", {
|
|
@@ -136,11 +167,12 @@ var BedrockModel = class {
|
|
|
136
167
|
throw this.logAndWrap(thrown);
|
|
137
168
|
}
|
|
138
169
|
let rawStopReason;
|
|
139
|
-
|
|
170
|
+
let usage = {
|
|
140
171
|
input: 0,
|
|
141
172
|
output: 0,
|
|
142
173
|
total: 0
|
|
143
174
|
};
|
|
175
|
+
const want = resolveStreamChunks(options);
|
|
144
176
|
const toolBlocks = /* @__PURE__ */ new Map();
|
|
145
177
|
const reasoningBlocks = /* @__PURE__ */ new Map();
|
|
146
178
|
const completedReasoningBlocks = [];
|
|
@@ -148,6 +180,7 @@ var BedrockModel = class {
|
|
|
148
180
|
for await (const event of response.stream ?? []) {
|
|
149
181
|
if (event.contentBlockStart?.start?.toolUse) {
|
|
150
182
|
const start = event.contentBlockStart.start.toolUse;
|
|
183
|
+
if (start.type === SERVER_TOOL_USE) continue;
|
|
151
184
|
toolBlocks.set(event.contentBlockStart.contentBlockIndex ?? 0, {
|
|
152
185
|
id: start.toolUseId ?? "",
|
|
153
186
|
name: start.name ?? "",
|
|
@@ -163,11 +196,25 @@ var BedrockModel = class {
|
|
|
163
196
|
};
|
|
164
197
|
else if (delta.toolUse) {
|
|
165
198
|
const accumulator = toolBlocks.get(event.contentBlockDelta.contentBlockIndex ?? 0);
|
|
166
|
-
if (accumulator)
|
|
199
|
+
if (accumulator) {
|
|
200
|
+
accumulator.json += delta.toolUse.input ?? "";
|
|
201
|
+
if (want.toolArgs && delta.toolUse.input) yield {
|
|
202
|
+
type: "tool-args",
|
|
203
|
+
callId: accumulator.id,
|
|
204
|
+
name: accumulator.name,
|
|
205
|
+
delta: delta.toolUse.input
|
|
206
|
+
};
|
|
207
|
+
}
|
|
167
208
|
} else if (delta.reasoningContent) {
|
|
168
209
|
const index = event.contentBlockDelta.contentBlockIndex ?? 0;
|
|
169
210
|
const accumulator = reasoningBlocks.get(index) ?? {};
|
|
170
|
-
if (delta.reasoningContent.text !== void 0)
|
|
211
|
+
if (delta.reasoningContent.text !== void 0) {
|
|
212
|
+
accumulator.text = (accumulator.text ?? "") + delta.reasoningContent.text;
|
|
213
|
+
if (want.reasoning && delta.reasoningContent.text !== "") yield {
|
|
214
|
+
type: "reasoning",
|
|
215
|
+
delta: delta.reasoningContent.text
|
|
216
|
+
};
|
|
217
|
+
}
|
|
171
218
|
if (delta.reasoningContent.signature !== void 0) accumulator.signature = delta.reasoningContent.signature;
|
|
172
219
|
if (delta.reasoningContent.redactedContent !== void 0) accumulator.redactedContent = delta.reasoningContent.redactedContent;
|
|
173
220
|
reasoningBlocks.set(index, accumulator);
|
|
@@ -196,19 +243,13 @@ var BedrockModel = class {
|
|
|
196
243
|
continue;
|
|
197
244
|
}
|
|
198
245
|
if (event.messageStop) rawStopReason = event.messageStop.stopReason;
|
|
199
|
-
if (event.metadata?.usage)
|
|
200
|
-
const raw = event.metadata.usage;
|
|
201
|
-
usage.input = raw.inputTokens ?? 0;
|
|
202
|
-
usage.output = raw.outputTokens ?? 0;
|
|
203
|
-
usage.total = raw.totalTokens ?? usage.input + usage.output;
|
|
204
|
-
if (raw.cacheReadInputTokens && raw.cacheReadInputTokens > 0) usage.cachedTokens = raw.cacheReadInputTokens;
|
|
205
|
-
if (raw.cacheWriteInputTokens && raw.cacheWriteInputTokens > 0) usage.cacheWriteTokens = raw.cacheWriteInputTokens;
|
|
206
|
-
}
|
|
246
|
+
if (event.metadata?.usage) usage = this.extractUsage(event.metadata.usage);
|
|
207
247
|
}
|
|
208
248
|
} catch (thrown) {
|
|
209
249
|
throw this.logAndWrap(thrown);
|
|
210
250
|
}
|
|
211
251
|
const finishReason = mapStopReason(rawStopReason);
|
|
252
|
+
attachCost(usage, this.pricing);
|
|
212
253
|
this.logger.debug(LOG_MODULE, "response", "ConverseStream call succeeded", {
|
|
213
254
|
finishReason,
|
|
214
255
|
usage
|
|
@@ -231,44 +272,58 @@ var BedrockModel = class {
|
|
|
231
272
|
const configuredMaxTokens = options?.maxTokens ?? this.config.maxTokens;
|
|
232
273
|
const maxTokens = this.resolveMaxTokens(configuredMaxTokens, thinkingBudget);
|
|
233
274
|
const temperature = options?.temperature ?? this.config.temperature;
|
|
234
|
-
const
|
|
235
|
-
|
|
275
|
+
const cachePoint = this.resolveCachePoint(options?.cacheControl);
|
|
276
|
+
const cachedMessages = this.applyCacheBreakpoints(bedrockMessages, cachePoint);
|
|
277
|
+
const cachedSystem = system && cachePoint ? [...system, { cachePoint }] : system;
|
|
278
|
+
return mergeProviderBody({
|
|
236
279
|
modelId: this.name,
|
|
237
280
|
messages: cachedMessages,
|
|
238
|
-
...
|
|
281
|
+
...cachedSystem ? { system: cachedSystem } : {},
|
|
239
282
|
inferenceConfig: {
|
|
240
283
|
...maxTokens !== void 0 ? { maxTokens } : {},
|
|
241
284
|
...temperature !== void 0 ? { temperature } : {}
|
|
242
285
|
},
|
|
243
|
-
...this.buildToolConfig(options
|
|
286
|
+
...this.buildToolConfig(options, cachePoint),
|
|
244
287
|
...this.buildOutputConfig(options?.responseSchema),
|
|
245
288
|
...this.buildReasoningConfig(thinkingBudget)
|
|
246
|
-
};
|
|
289
|
+
}, options);
|
|
247
290
|
}
|
|
248
291
|
/**
|
|
249
|
-
*
|
|
250
|
-
*
|
|
251
|
-
* `promptCaching`-capable
|
|
252
|
-
*
|
|
253
|
-
*
|
|
254
|
-
* (surfaced as `Usage.cachedTokens`). No-ops gracefully when caching
|
|
255
|
-
* is unsupported, no breakpoint was requested, or there are no
|
|
256
|
-
* messages to mark — Bedrock then prices the call normally.
|
|
292
|
+
* Resolve the Converse `cachePoint` to place for this call, or
|
|
293
|
+
* `undefined` when no cache point applies (the model is not
|
|
294
|
+
* `promptCaching`-capable or no `cacheControl` breakpoint was asked
|
|
295
|
+
* for). Bedrock only honors `type: "default"`; the neutral
|
|
296
|
+
* `breakpoints` count is a presence hint.
|
|
257
297
|
*
|
|
258
|
-
*
|
|
259
|
-
* `
|
|
260
|
-
*
|
|
261
|
-
*
|
|
298
|
+
* The lifetime is the per-call `cacheControl.ttl`, else the model's
|
|
299
|
+
* `promptCacheTtl`. `ttl: "1h"` is sent only to models that accept it
|
|
300
|
+
* ({@link supportsOneHourCacheTtl}); any other model gets the 5-minute
|
|
301
|
+
* default, because AWS rejects the field there.
|
|
262
302
|
*/
|
|
263
|
-
|
|
303
|
+
resolveCachePoint(cacheControl) {
|
|
264
304
|
const breakpoints = cacheControl?.breakpoints ?? 0;
|
|
265
|
-
if (!this.capabilities.promptCaching || breakpoints <= 0
|
|
305
|
+
if (!this.capabilities.promptCaching || breakpoints <= 0) return;
|
|
306
|
+
return (cacheControl?.ttl ?? this.config.promptCacheTtl) === "1h" && supportsOneHourCacheTtl(this.name) ? {
|
|
307
|
+
type: "default",
|
|
308
|
+
ttl: "1h"
|
|
309
|
+
} : { type: "default" };
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Append the call's `cachePoint` to the LAST message. Together with the
|
|
313
|
+
* `system` and `tools` cache points (see `buildRequest` /
|
|
314
|
+
* `buildToolConfig`) this caches every stable segment of the prefix —
|
|
315
|
+
* Bedrock processes them in `tools` → `system` → `messages` order, at
|
|
316
|
+
* most three of the four checkpoints it allows — so later calls reusing
|
|
317
|
+
* the prefix bill it at the cache-read rate (`Usage.cachedTokens`).
|
|
318
|
+
*/
|
|
319
|
+
applyCacheBreakpoints(messages, cachePoint) {
|
|
320
|
+
if (!cachePoint || !messages || messages.length === 0) return messages;
|
|
266
321
|
const last = messages.length - 1;
|
|
267
322
|
const lastMessage = messages[last];
|
|
268
323
|
if (!lastMessage) return messages;
|
|
269
324
|
return [...messages.slice(0, last), {
|
|
270
325
|
...lastMessage,
|
|
271
|
-
content: [...lastMessage.content ?? [], { cachePoint
|
|
326
|
+
content: [...lastMessage.content ?? [], { cachePoint }]
|
|
272
327
|
}];
|
|
273
328
|
}
|
|
274
329
|
/**
|
|
@@ -304,11 +359,26 @@ var BedrockModel = class {
|
|
|
304
359
|
}
|
|
305
360
|
/**
|
|
306
361
|
* Spread-friendly tool fragment. Returns an empty object when no
|
|
307
|
-
* tools were supplied (Bedrock rejects an empty `tools` array).
|
|
362
|
+
* tools were supplied (Bedrock rejects an empty `tools` array). With a
|
|
363
|
+
* cache point, a trailing `{ cachePoint }` caches every tool definition
|
|
364
|
+
* — Claude only, since Nova accepts no cache point in `tools`.
|
|
308
365
|
*/
|
|
309
|
-
buildToolConfig(
|
|
366
|
+
buildToolConfig(options, cachePoint) {
|
|
367
|
+
const { tools, definitions } = selectProviderTools(options, {
|
|
368
|
+
accepts: [BEDROCK_WIRE_FORMAT, this.provider],
|
|
369
|
+
module: LOG_MODULE,
|
|
370
|
+
model: this.name,
|
|
371
|
+
logger: this.logger
|
|
372
|
+
});
|
|
310
373
|
const toolConfig = toBedrockToolConfig(tools);
|
|
311
|
-
|
|
374
|
+
const providerDefined = definitions;
|
|
375
|
+
const allTools = [...toolConfig?.tools ?? [], ...providerDefined];
|
|
376
|
+
if (allTools.length === 0) return toolConfig ? { toolConfig } : {};
|
|
377
|
+
const withCachePoint = cachePoint && supportsToolCachePoint(this.name) ? [...allTools, { cachePoint }] : allTools;
|
|
378
|
+
return { toolConfig: {
|
|
379
|
+
...toolConfig,
|
|
380
|
+
tools: withCachePoint
|
|
381
|
+
} };
|
|
312
382
|
}
|
|
313
383
|
/**
|
|
314
384
|
* Translate the neutral `responseSchema` into Converse's native
|
|
@@ -346,7 +416,7 @@ var BedrockModel = class {
|
|
|
346
416
|
extractToolCalls(blocks) {
|
|
347
417
|
const toolCalls = [];
|
|
348
418
|
const reasoningBlocks = blocks.map(toReasoningMetadata).filter((block) => block !== void 0);
|
|
349
|
-
for (const block of blocks) if ("toolUse" in block && block.toolUse) toolCalls.push({
|
|
419
|
+
for (const block of blocks) if ("toolUse" in block && block.toolUse && block.toolUse.type !== SERVER_TOOL_USE) toolCalls.push({
|
|
350
420
|
id: block.toolUse.toolUseId ?? "",
|
|
351
421
|
name: block.toolUse.name ?? "",
|
|
352
422
|
input: block.toolUse.input ?? {},
|
|
@@ -366,10 +436,13 @@ var BedrockModel = class {
|
|
|
366
436
|
* Normalize Converse's `TokenUsage` into the neutral `Usage` shape.
|
|
367
437
|
* Bedrock supplies a pre-summed `totalTokens`; cache-read and
|
|
368
438
|
* cache-write tokens are surfaced as `cachedTokens` /
|
|
369
|
-
* `cacheWriteTokens` only when non-zero
|
|
370
|
-
*
|
|
371
|
-
*
|
|
372
|
-
*
|
|
439
|
+
* `cacheWriteTokens` only when non-zero, and the 1-hour share of the
|
|
440
|
+
* writes (`cacheDetails` entries with `ttl: "1h"`) as
|
|
441
|
+
* `cacheWrite1hTokens`. With caching, `inputTokens` "represents only
|
|
442
|
+
* the non-cached input tokens" (AWS prompt-caching guide), so the usage
|
|
443
|
+
* is marked `inputIncludesCache: false`. Bedrock's Converse `TokenUsage`
|
|
444
|
+
* carries no reasoning-token channel, so `Usage.reasoningTokens` is
|
|
445
|
+
* intentionally left unset here.
|
|
373
446
|
*/
|
|
374
447
|
extractUsage(raw) {
|
|
375
448
|
if (!raw) return {
|
|
@@ -381,12 +454,15 @@ var BedrockModel = class {
|
|
|
381
454
|
const output = raw.outputTokens ?? 0;
|
|
382
455
|
const cached = raw.cacheReadInputTokens;
|
|
383
456
|
const cacheWrite = raw.cacheWriteInputTokens;
|
|
457
|
+
const cacheWrite1h = (raw.cacheDetails ?? []).filter((detail) => detail.ttl === "1h").reduce((sum, detail) => sum + (detail.inputTokens ?? 0), 0);
|
|
384
458
|
return {
|
|
385
459
|
input,
|
|
386
460
|
output,
|
|
387
461
|
total: raw.totalTokens ?? input + output,
|
|
462
|
+
inputIncludesCache: false,
|
|
388
463
|
...cached && cached > 0 ? { cachedTokens: cached } : {},
|
|
389
|
-
...cacheWrite && cacheWrite > 0 ? { cacheWriteTokens: cacheWrite } : {}
|
|
464
|
+
...cacheWrite && cacheWrite > 0 ? { cacheWriteTokens: cacheWrite } : {},
|
|
465
|
+
...cacheWrite && cacheWrite > 0 && cacheWrite1h > 0 ? { cacheWrite1hTokens: Math.min(cacheWrite1h, cacheWrite) } : {}
|
|
390
466
|
};
|
|
391
467
|
}
|
|
392
468
|
/**
|