@warlock.js/ai-bedrock 5.30.0 → 5.32.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/llms-full.txt CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  ---
10
10
  name: setup-bedrock
11
- description: 'Wire @warlock.js/ai-bedrock — new BedrockSDK({region, credentials?, provider?}) for AWS Bedrock Converse API + Titan embeddings. AWS credential chain (no apiKey). .model({name, vision?, reasoning?, promptCaching?, pdf?, audio?}) with cost-truth capabilities inferred per family, extended thinking via options.reasoning → Converse thinking budget_tokens, prompt caching via options.cacheControl → cachePoint, usage cachedTokens/cacheWriteTokens. Triggers: `BedrockSDK`, `bedrock.model`, `bedrock.embedder`, `bedrock.count`, `BedrockRuntimeClient`, `reasoning`, `thinking`, `budget_tokens`, `cachePoint`, `cacheControl`, `promptCaching`, `cachedTokens`, `cacheWriteTokens`; "how do I use AWS Bedrock", "wire Claude/Nova/Llama on Bedrock", "Titan embeddings", "Bedrock Converse API", "Claude 3.7/4 extended thinking on Bedrock", "Bedrock prompt caching cost"; typical import `import { BedrockSDK } from "@warlock.js/ai-bedrock"`. Skip: agent wiring — the `run-ai-agent` topic of the `warlock-js-ai` skill; provider choice — the `pick-ai-provider` topic of the `warlock-js-ai` skill; embeddings concepts — the `embed-text` topic of the `warlock-js-ai` skill; competing libs `@aws-sdk/client-bedrock-runtime`, `@ai-sdk/amazon-bedrock`; sibling adapters `@warlock.js/ai-openai`, `@warlock.js/ai-anthropic`, `@warlock.js/ai-google`, `@warlock.js/ai-ollama`.'
11
+ description: 'Wire @warlock.js/ai-bedrock — new BedrockSDK({region, apiKey?, credentials?, provider?}) for AWS Bedrock Converse API + Titan embeddings. AWS credential chain or an Amazon Bedrock API key (bearer). .model({name, vision?, reasoning?, promptCaching?, pdf?, audio?}) with cost-truth capabilities inferred per family, extended thinking via options.reasoning → Converse thinking budget_tokens, prompt caching via options.cacheControl → cachePoint on tools (Claude), system and the last message, 1h TTL via promptCacheTtl, usage inputIncludesCache: false + cachedTokens/cacheWriteTokens/cacheWrite1hTokens, built-in Claude prices for global./us. profiles (BEDROCK_GLOBAL_PRICING, BEDROCK_US_PRICING, bedrockPricingFor), ServiceUnavailableException → ProviderOverloadedError. Triggers: `apiKey`, `AWS_BEARER_TOKEN_BEDROCK`, `providerOptions`, `BedrockCallOptions`, `countTokens`, `BedrockSDK`, `bedrock.model`, `bedrock.embedder`, `bedrock.count`, `BedrockRuntimeClient`, `reasoning`, `thinking`, `budget_tokens`, `cachePoint`, `cacheControl`, `ai.providerTool`, `systemTool`, `nova_grounding`, `server_tool_use`, `streamChunks`, `promptCaching`, `cachedTokens`, `cacheWriteTokens`; "how do I use AWS Bedrock", "wire Claude/Nova/Llama on Bedrock", "Titan embeddings", "Bedrock Converse API", "Claude 3.7/4 extended thinking on Bedrock", "Bedrock prompt caching cost"; typical import `import { BedrockSDK } from "@warlock.js/ai-bedrock"`. Skip: agent wiring — the `run-ai-agent` topic of the `warlock-js-ai` skill; provider choice — the `pick-ai-provider` topic of the `warlock-js-ai` skill; embeddings concepts — the `embed-text` topic of the `warlock-js-ai` skill; competing libs `@aws-sdk/client-bedrock-runtime`, `@ai-sdk/amazon-bedrock`; sibling adapters `@warlock.js/ai-openai`, `@warlock.js/ai-anthropic`, `@warlock.js/ai-google`, `@warlock.js/ai-ollama`.'
12
12
  ---
13
13
 
14
14
  # `@warlock.js/ai-bedrock`
@@ -29,32 +29,38 @@ const bedrock2 = new BedrockSDK({
29
29
  credentials: { accessKeyId: "AKIA...", secretAccessKey: "..." },
30
30
  provider: "bedrock-eu",
31
31
  });
32
+
33
+ // Amazon Bedrock API key (bearer auth, no AWS credentials):
34
+ const bedrock3 = new BedrockSDK({
35
+ apiKey: process.env.BEDROCK_API_KEY!,
36
+ region: "us-east-1",
37
+ });
32
38
  ```
33
39
 
34
- Bedrock authenticates via the **AWS credential chain, not an API key** — there is no `apiKey`. `region` is required; `credentials` is optional (omit to use the standard provider chain). The whole config object is forwarded to `BedrockRuntimeClient`, so any AWS client option (`endpoint`, `requestHandler`, retry config) is accepted. `provider` defaults to `"bedrock"`.
40
+ Bedrock authenticates via the **AWS credential chain** or an **Amazon Bedrock API key**. `apiKey` sends `Authorization: Bearer <key>` instead of a SigV4 signature (the adapter sets the AWS SDK's `token` + `authSchemePreference: ["httpBearerAuth"]`); combining it with `credentials` or `token`, or passing an empty key, throws `InvalidRequestError`. Without `apiKey`, the AWS SDK still reads a key from `AWS_BEARER_TOKEN_BEDROCK` on its own. `region` is required; `credentials` is optional (omit to use the standard provider chain). The whole config object is forwarded to `BedrockRuntimeClient`, so any AWS client option (`endpoint`, `requestHandler`, retry config) is accepted. `provider` defaults to `"bedrock"`.
35
41
 
36
42
  ## Producing a model
37
43
 
38
44
  `name` is the Bedrock **model id or inference-profile id**:
39
45
 
40
46
  ```ts
41
- bedrock.model({ name: "anthropic.claude-sonnet-4-5-20250929-v1:0" })
42
- bedrock.model({ name: "us.amazon.nova-pro-v1:0", temperature: 0.2 })
43
- bedrock.model({ name: "meta.llama3-1-8b-instruct-v1:0", maxTokens: 1024 })
47
+ bedrock.model({ name: "anthropic.claude-sonnet-4-5-20250929-v1:0" });
48
+ bedrock.model({ name: "us.amazon.nova-pro-v1:0", temperature: 0.2 });
49
+ bedrock.model({ name: "meta.llama3-1-8b-instruct-v1:0", maxTokens: 1024 });
44
50
  ```
45
51
 
46
52
  Uses the model-agnostic **Converse / ConverseStream** API — one wire mapping covers every Bedrock family (Claude, Nova, Llama, Mistral, Cohere) instead of per-family `InvokeModel` body shapes.
47
53
 
48
54
  ## Capabilities — what's auto-set
49
55
 
50
- | Flag | Default |
51
- | --- | --- |
52
- | `structuredOutput` | `true` (via Converse `outputConfig.textFormat`) |
53
- | `vision` | Inferred from model id substring. `true` for Claude 3/3.5/3.7/4, Nova Lite/Pro/Premier, Llama 3.2-11B/90B, Llama 4. |
54
- | `reasoning` | Inferred from model id. `true` for Claude 3.7 + Claude 4 (Sonnet/Opus/Haiku) — they expose a configurable thinking budget on Converse. |
55
- | `promptCaching` | Inferred from model id. `true` for Claude 3.5+/3.7/4 and Nova Micro/Lite/Pro/Premier — the families that honor Converse `cachePoint`. |
56
- | `pdf` | Inferred from model id. `true` for Claude 3+ and Nova Lite/Pro/Premier (Converse `document` blocks). |
57
- | `audio` | `false` by default — Converse does not accept audio blocks for the families this adapter targets. Pass `audio: true` for a confirmed audio model. |
56
+ | Flag | Default |
57
+ | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
58
+ | `structuredOutput` | `true` (via Converse `outputConfig.textFormat`) |
59
+ | `vision` | Inferred from model id substring. `true` for Claude 3/3.5/3.7/4, Nova Lite/Pro/Premier, Llama 3.2-11B/90B, Llama 4. |
60
+ | `reasoning` | Inferred from model id. `true` for Claude 3.7 + Claude 4 (Sonnet/Opus/Haiku) — they expose a configurable thinking budget on Converse. |
61
+ | `promptCaching` | Inferred from model id. `true` for Claude 3.5+/3.7/4/5 and Nova 2 Lite / Micro / Lite / Pro / Premier — the families that honor Converse `cachePoint`. |
62
+ | `pdf` | Inferred from model id. `true` for Claude 3+ and Nova Lite/Pro/Premier (Converse `document` blocks). |
63
+ | `audio` | `false` by default — Converse does not accept audio blocks for the families this adapter targets. Pass `audio: true` for a confirmed audio model. |
58
64
 
59
65
  Explicit config always wins — every flag is overridable per model, e.g. `bedrock.model({ name, reasoning: false, promptCaching: true, pdf: false, audio: true })`.
60
66
 
@@ -76,13 +82,38 @@ A thinking budget below `1024` throws before the request. When thinking is enabl
76
82
 
77
83
  ## Prompt caching
78
84
 
79
- For a `promptCaching`-capable model, `ModelCallOptions.cacheControl.breakpoints` (any positive value) appends one Converse `cachePoint: { type: "default" }` block to the LAST message — Bedrock then caches the whole prefix up to that point:
85
+ For a `promptCaching`-capable model, `ModelCallOptions.cacheControl.breakpoints` (any positive value) places a Converse `cachePoint` on every stable segment of the prefix, in the order Bedrock processes them (`tools` → `system` → `messages`, three of the four checkpoints it allows):
86
+
87
+ | Segment | Where the `cachePoint` goes | Models |
88
+ | -------- | --------------------------------------- | ---------------------------------------------------- |
89
+ | tools | after the last `toolConfig.tools` entry | Claude only — Nova accepts no cache point in `tools` |
90
+ | system | after the system blocks | every caching-capable model |
91
+ | messages | appended to the LAST message | every caching-capable model |
92
+
93
+ The lifetime is the per-call `cacheControl.ttl`, else the model's `promptCacheTtl`. `ttl: "1h"` is sent only to models that accept it — Claude Haiku 4.5, Sonnet / Opus 4.5+ and every Claude 5 family; any other model gets the 5-minute default, because AWS warns that the field "can result in a ValidationException" on 5-minute-only models.
80
94
 
81
95
  ```ts
82
- await model.complete(messages, { cacheControl: { breakpoints: 1 } });
96
+ import { BedrockSDK } from "@warlock.js/ai-bedrock";
97
+
98
+ const bedrock = new BedrockSDK({ region: "us-east-1" });
99
+ const model = bedrock.model({ name: "global.anthropic.claude-sonnet-4-6", promptCacheTtl: "1h" });
100
+
101
+ // tools + system + last message are cached for an hour:
102
+ await model.complete(
103
+ [
104
+ { role: "system", content: "Long, stable instructions…" },
105
+ { role: "user", content: "First question" },
106
+ ],
107
+ { cacheControl: { breakpoints: 1 } },
108
+ );
109
+
110
+ // Per call, the TTL can be overridden:
111
+ await model.complete([{ role: "user", content: "hi" }], {
112
+ cacheControl: { breakpoints: 1, ttl: "5m" },
113
+ });
83
114
  ```
84
115
 
85
- Earlier turns are untouched; only the trailing message is marked. No-ops gracefully when the model is not caching-capable or no breakpoint was requested. Read-side accounting works without any breakpoint — see the usage section below.
116
+ Source for the placement rules and TTL support: https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-caching.html (checked 2026-10-17). No-ops gracefully when the model is not caching-capable or no breakpoint was requested. Read-side accounting works without any breakpoint — see the usage section below.
86
117
 
87
118
  ## System prompt
88
119
 
@@ -112,6 +143,17 @@ Object-root `responseSchema` + `structuredOutput`-capable → `outputConfig.text
112
143
  - `contentBlockDelta.delta.text` → `{ type: "delta", content }`
113
144
  - `toolUse`: `contentBlockStart` opens an accumulator, `contentBlockDelta.delta.toolUse.input` fragments append, `contentBlockStop` emits one consolidated `{ type: "tool-call", ... }`
114
145
  - terminal `{ type: "done", finishReason, usage }` — usage from `metadata.usage` (a `TokenUsage`), including `cachedTokens` / `cacheWriteTokens` when reported (see the usage table below)
146
+ - opt-in (`options.streamChunks`, set by `agent.stream()`): `{ type: "reasoning", delta }` per `reasoningContent.text` delta, `{ type: "tool-args", callId, name, delta }` per client `toolUse.input` delta; no `usage` chunk (usage arrives once at the end)
147
+
148
+ **System tools:** `ai.providerTool({ provider: "bedrock", definition: { systemTool: { name: "nova_grounding" } } })` is appended to `toolConfig.tools` verbatim. `toolUse` blocks with `type: "server_tool_use"` are never dispatched as tool calls.
149
+
150
+ ```ts
151
+ const grounding = ai.providerTool({
152
+ provider: "bedrock",
153
+ definition: { systemTool: { name: "nova_grounding" } },
154
+ });
155
+ ai.agent({ model: bedrock.model({ name: "us.amazon.nova-premier-v1:0" }), tools: [grounding] });
156
+ ```
115
157
 
116
158
  ## Finish-reason mapping
117
159
 
@@ -122,7 +164,7 @@ Object-root `responseSchema` + `structuredOutput`-capable → `outputConfig.text
122
164
  ```ts
123
165
  const embedder = bedrock.embedder({ name: "amazon.titan-embed-text-v2:0" });
124
166
  const { vector } = await embedder.embed("Hello world");
125
- const { vectors } = await embedder.embedMany(["a", "b"]); // N sequential calls
167
+ const { vectors } = await embedder.embedMany(["a", "b"]); // N sequential calls
126
168
  ```
127
169
 
128
170
  Targets the **Titan Text Embeddings** family via `InvokeModel`. **Titan has no batch endpoint** — `embedMany` issues one request per input sequentially and aggregates token usage. Cohere-on-Bedrock batch embeddings use an incompatible body shape and are out of scope — use the OpenAI adapter when batch throughput matters.
@@ -138,50 +180,118 @@ Raw AWS SDK exceptions are wrapped into the typed `@warlock.js/ai` `AIError` hie
138
180
  - `ServiceQuotaExceededException` → `QuotaExceededError`
139
181
  - `ValidationException` with "too long / context window" → `ContextLengthExceededError`, else `InvalidRequestError`
140
182
  - `ModelTimeoutException` / `ETIMEDOUT` → `ProviderTimeoutError`
141
- - 5xx / `ModelError` / `ServiceUnavailable` → `ProviderError`
183
+ - `ServiceUnavailableException` / 503 → `ProviderOverloadedError` (`code: "PROVIDER_OVERLOADED"`, `retryable: true`) — the service is temporarily unable to serve the request
184
+ - other 5xx / `ModelError` → `ProviderError`
185
+
186
+ Every wrapped error carries `status`, `retryable` and `billed` (`false` for 401 / 402 / 403, otherwise `"unknown"` — AWS publishes no rule for failed requests). `fallbackModel` fails over on `PROVIDER_OVERLOADED` by default.
142
187
 
143
188
  ## Token counting
144
189
 
145
190
  ```ts
146
- await bedrock.count("some text") // approximate heuristic, offline
191
+ await bedrock.count("some text"); // approximate heuristic, offline
147
192
  ```
148
193
 
149
194
  Per-model tokenizers differ across Bedrock families.
150
195
 
151
- ## Pricing — per-model registry
196
+ ## Pricing — built-in Claude prices and registry
152
197
 
153
- `pricing` is an optional **registry keyed by Bedrock model id** — one entry per model, all rates in **USD per 1,000,000 tokens** (`ModelPricing`: `input`, `output`, optional `cachedInput` / `cachedOutput`). Set it on the SDK so every model it produces inherits the rates:
198
+ All rates are **USD per 1,000,000 tokens** (`ModelPricing`: `input`, `output`, optional `cachedInput`, `cacheWrite`, `cacheWrite1h`). Resolution at `model()` time: per-model `pricing` (`bedrock.model({ name, pricing })`) > SDK registry (exact id) > built-in profile price > `undefined` (no cost computed).
154
199
 
155
200
  ```ts
201
+ import { ai, totalCost } from "@warlock.js/ai";
202
+ import {
203
+ BEDROCK_GLOBAL_PRICING,
204
+ BedrockSDK,
205
+ bedrockPricingFor,
206
+ withClaudeCacheWriteRates,
207
+ } from "@warlock.js/ai-bedrock";
208
+
156
209
  const bedrock = new BedrockSDK({
157
- region: "us-east-1",
210
+ region: "eu-west-1",
158
211
  pricing: {
159
- // USD per 1M tokens. Key = exact Bedrock model id / inference-profile id.
160
- "anthropic.claude-sonnet-4-5-20250929-v1:0": { input: 3, output: 15 },
161
- "us.amazon.nova-pro-v1:0": { input: 0.8, output: 3.2 },
212
+ // In-Region and non-US geographic ids are not built in — price them yourself.
213
+ "eu.anthropic.claude-sonnet-4-6": { input: 3.3, output: 16.5, cachedInput: 0.33 },
214
+ "amazon.nova-pro-v1:0": { input: 0.8, output: 3.2 }, // your own rates for unlisted models
162
215
  },
163
216
  });
164
217
 
165
- const { usage } = await ai.agent({ model: bedrock.model({ name: "us.amazon.nova-pro-v1:0" }) }).execute("hi");
166
- usage.cost; // per-channel USD breakdown of THIS run, computed from tokens × pricing[model]
218
+ bedrock.model({ name: "global.anthropic.claude-sonnet-4-6" }).pricing; // built-in global rate
219
+ bedrock.model({ name: "eu.anthropic.claude-sonnet-4-6" }).pricing; // registry + Claude write rates filled (cacheWrite 4.125, cacheWrite1h 6.6)
220
+ bedrockPricingFor("us.anthropic.claude-haiku-4-5-20251001-v1:0"); // US geographic rate
221
+ withClaudeCacheWriteRates("anthropic.claude-opus-4-8", { input: 5, output: 25 }); // + cacheWrite 6.25, cacheWrite1h 10
222
+ Object.keys(BEDROCK_GLOBAL_PRICING); // the priced Claude model ids
223
+
224
+ const { usage } = await ai
225
+ .agent({ model: bedrock.model({ name: "global.anthropic.claude-sonnet-4-6" }) })
226
+ .execute("hi");
227
+ console.log(usage.cost, totalCost(usage.cost)); // per-channel USD breakdown of THIS run, and its sum
167
228
  ```
168
229
 
169
- Resolution at `model()` time: per-model `pricing` (`bedrock.model({ name, pricing })`) > SDK registry > `undefined` (no cost computed). When the same model id appears under a cross-region inference profile, list each id you actually invoke (`us.`, `eu.`, `apac.` prefixes are distinct keys). See the `pick-ai-provider` topic of the `warlock-js-ai` skill.
230
+ - **Source.** https://aws.amazon.com/bedrock/pricing/ — the page's own price feed for "US East (N. Virginia)", fetched 2026-10-17; model ids from the prompt-caching guide. `BEDROCK_GLOBAL_PRICING` holds the `global.` cross-Region profile rates, `BEDROCK_US_PRICING` the `us.` geographic rates (10% above global for these models). Both are keyed by the bare model id; `bedrockPricingFor(id)` strips the profile prefix.
231
+ - **Covered:** Claude Sonnet 5.5 / 5 / 4.6 / 4.5, Opus 5.5 / 5 / 4.8 / 4.7 / 4.6 / 4.5, Fable 5.1 / 5, Haiku 4.5 — with cache read, 5-minute write (1.25x input) and 1-hour write (2x input).
232
+ - **Deliberately unpriced:** in-Region ids with no profile prefix and other geographies (`eu.`, `apac.`, …) — their rates vary by Region; Claude Haiku 5.5 (not verified); and every non-Claude model (Nova, Llama, Titan, …). Pass `pricing` for them.
233
+ - **Claude write rates are filled.** Any Claude entry (your own included) without `cacheWrite` / `cacheWrite1h` gets 1.25x / 2x the input rate (`withClaudeCacheWriteRates`). Non-Claude entries are left as given; an unpriced cache write then bills at the input rate.
170
234
 
171
235
  ### Tokens & usage — cost truth
172
236
 
173
- Both `complete()` and `stream()` normalize Converse's `TokenUsage` into the neutral `Usage` shape:
237
+ Both `complete()` and `stream()` normalize Converse's `TokenUsage` into the neutral `Usage` shape. With caching, `inputTokens` "represents only the non-cached input tokens" — total input is `inputTokens + cacheReadInputTokens + cacheWriteInputTokens` (AWS prompt-caching guide) — so the adapter marks the usage `inputIncludesCache: false` and cost bills each channel once:
174
238
 
175
- | Converse `TokenUsage` field | Neutral `Usage` field | Notes |
176
- | --- | --- | --- |
177
- | `inputTokens` | `usage.input` | Includes cached read tokens. |
178
- | `outputTokens` | `usage.output` | |
179
- | `totalTokens` | `usage.total` | Falls back to `input + output` when absent. |
180
- | `cacheReadInputTokens` | `usage.cachedTokens` | Only when `> 0`. Cache-hit reads — price at `pricing.cachedInput`. |
181
- | `cacheWriteInputTokens` | `usage.cacheWriteTokens` | Only when `> 0`. One-time cache write — price at `pricing.cachedOutput`. |
182
- | — | `usage.reasoningTokens` | **Never set** — Converse exposes no reasoning-token count. |
239
+ | Converse `TokenUsage` field | Neutral `Usage` field | Notes |
240
+ | --------------------------- | -------------------------- | -------------------------------------------------------------------- |
241
+ | `inputTokens` | `usage.input` | **Excludes** cache reads and writes. Bills at `pricing.input`. |
242
+ | — | `usage.inputIncludesCache` | Always `false` on Bedrock. |
243
+ | `outputTokens` | `usage.output` | |
244
+ | `totalTokens` | `usage.total` | Falls back to `input + output` when absent. |
245
+ | `cacheReadInputTokens` | `usage.cachedTokens` | Only when `> 0`. Cache-hit reads — bills at `pricing.cachedInput`. |
246
+ | `cacheWriteInputTokens` | `usage.cacheWriteTokens` | Only when `> 0`. Cache writes — bills at `pricing.cacheWrite`. |
247
+ | `cacheDetails[ttl: "1h"]` | `usage.cacheWrite1hTokens` | The 1-hour share of the writes — bills at `pricing.cacheWrite1h`. |
248
+ | — | `usage.reasoningTokens` | **Never set** — Converse exposes no reasoning-token count. |
249
+ | — | `usage.cost` | Attached on `complete()` and the streaming `done` chunk when priced. |
183
250
 
184
- Set `cachedInput` / `cachedOutput` in `ModelPricing` to have cache reads/writes billed at their distinct rates. Read-side accounting (`cachedTokens` / `cacheWriteTokens`) is populated whenever Bedrock reports it, independent of whether you sent a `cacheControl` breakpoint.
251
+ Read-side accounting is populated whenever Bedrock reports it, independent of whether you sent a `cacheControl` breakpoint.
252
+
253
+ ## Provider body options and input-token counts
254
+
255
+ Native body fields merge after neutral options. When both values are plain
256
+ objects, their immediate keys merge and caller-provided keys win; untouched
257
+ neutral fields remain. Arrays, scalars and `null` replace the field. This merge
258
+ is one level deep: a nested object explicitly supplied by the caller replaces
259
+ that nested value.
260
+
261
+ `providerOptions.bedrock.body` adds native Converse request fields after the
262
+ neutral options, for completion and streaming:
263
+
264
+ ```ts
265
+ const options = {
266
+ reasoning: { effort: "high" as const }, // preserved alongside top_k
267
+ providerOptions: { bedrock: { body: { additionalModelRequestFields: { top_k: 4 } } } },
268
+ };
269
+ await model.complete(messages, options);
270
+ ```
271
+
272
+ The key stays `bedrock` for custom provider labels. Other provider keys are
273
+ ignored. `BedrockCallOptions` is exported. `modelId`, `messages`, `system` and
274
+ `toolConfig` are protected; attempting to replace them throws
275
+ `InvalidRequestError`. Provider fields are otherwise forwarded without validation.
276
+
277
+ `model.countTokens(messages, options?)` calls Bedrock `CountTokens` using the same
278
+ Converse messages, system blocks, tool configuration and
279
+ `additionalModelRequestFields` used for generation. Cancellation is forwarded.
280
+ Availability depends on the model and region; provider failures use the adapter's
281
+ normal typed errors. `sdk.count(text)` remains a separate offline estimate.
282
+
283
+ For budget preflight, `countInputTokens(model, messages, { tools })` from
284
+ `@warlock.js/ai` returns `{ tokens, source }`. It estimates only when native
285
+ counting is absent or explicitly throws `InvalidRequestError` with
286
+ `reason: "count-unsupported"`; this adapter preserves that signal. System and
287
+ tools are supported natively. Ordinary validation, auth, network and rate-limit
288
+ errors propagate. See the cost/budget guide for reserve mode.
289
+
290
+ ```ts
291
+ if (model.countTokens) {
292
+ const inputTokens = await model.countTokens(messages, options);
293
+ }
294
+ ```
185
295
 
186
296
  ## When NOT to use this skill
187
297
 
@@ -195,4 +305,25 @@ Set `cachedInput` / `cachedOutput` in `ModelPricing` to have cache reads/writes
195
305
  - The `pick-ai-provider` topic of the `warlock-js-ai` skill
196
306
  - The `embed-text` topic of the `warlock-js-ai` skill
197
307
 
308
+ ## Adjacent conversation turns
309
+
310
+ Converse messages combine adjacent turns of the same role, retaining every
311
+ content block in order. This keeps parallel tool results in one user turn and
312
+ allows an automatic compaction summary beside an assistant tool-call turn
313
+ without creating consecutive assistant turns. Agent compaction frames a summary
314
+ as user context when it replaces the first non-system turn.
315
+
316
+ Adjacent-turn normalization preserves empty histories and separate system prompts
317
+ without inserting synthetic conversation turns.
318
+
319
+ ## Hosted-search accounting limit
320
+
321
+ Bedrock Converse's [TokenUsage schema](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_TokenUsage.html)
322
+ and the installed SDK expose token/cache counts, with no hosted-tool request
323
+ counter (verified 2026-10-18). `usage.serverToolUse` therefore remains absent;
324
+ no count or search fee is inferred from `server_tool_use` system-tool blocks.
325
+ Hosted system tools continue to stay outside function dispatch. Direct
326
+ Anthropic counters are not assumed to exist on Converse. Supply fees only when
327
+ your own verified metering establishes the billing unit.
328
+
198
329
 
package/llms.txt CHANGED
@@ -6,4 +6,4 @@
6
6
 
7
7
  ## Skills
8
8
 
9
- - [setup-bedrock](@warlock.js/ai-bedrock/setup-bedrock/SKILL.md): Wire @warlock.js/ai-bedrock — new BedrockSDK({region, credentials?, provider?}) for AWS Bedrock Converse API + Titan embeddings. AWS credential chain (no apiKey). .model({name, vision?, reasoning?, promptCaching?, pdf?, audio?}) with cost-truth capabilities inferred per family, extended thinking via options.reasoning → Converse thinking budget_tokens, prompt caching via options.cacheControl → cachePoint, usage cachedTokens/cacheWriteTokens. Triggers: `BedrockSDK`, `bedrock.model`, `bedrock.embedder`, `bedrock.count`, `BedrockRuntimeClient`, `reasoning`, `thinking`, `budget_tokens`, `cachePoint`, `cacheControl`, `promptCaching`, `cachedTokens`, `cacheWriteTokens`; "how do I use AWS Bedrock", "wire Claude/Nova/Llama on Bedrock", "Titan embeddings", "Bedrock Converse API", "Claude 3.7/4 extended thinking on Bedrock", "Bedrock prompt caching cost"; typical import `import { BedrockSDK } from "@warlock.js/ai-bedrock"`. Skip: agent wiring — the `run-ai-agent` topic of the `warlock-js-ai` skill; provider choice — the `pick-ai-provider` topic of the `warlock-js-ai` skill; embeddings concepts — the `embed-text` topic of the `warlock-js-ai` skill; competing libs `@aws-sdk/client-bedrock-runtime`, `@ai-sdk/amazon-bedrock`; sibling adapters `@warlock.js/ai-openai`, `@warlock.js/ai-anthropic`, `@warlock.js/ai-google`, `@warlock.js/ai-ollama`.
9
+ - [setup-bedrock](@warlock.js/ai-bedrock/setup-bedrock/SKILL.md): Wire @warlock.js/ai-bedrock — new BedrockSDK({region, apiKey?, credentials?, provider?}) for AWS Bedrock Converse API + Titan embeddings. AWS credential chain or an Amazon Bedrock API key (bearer). .model({name, vision?, reasoning?, promptCaching?, pdf?, audio?}) with cost-truth capabilities inferred per family, extended thinking via options.reasoning → Converse thinking budget_tokens, prompt caching via options.cacheControl → cachePoint on tools (Claude), system and the last message, 1h TTL via promptCacheTtl, usage inputIncludesCache: false + cachedTokens/cacheWriteTokens/cacheWrite1hTokens, built-in Claude prices for global./us. profiles (BEDROCK_GLOBAL_PRICING, BEDROCK_US_PRICING, bedrockPricingFor), ServiceUnavailableException → ProviderOverloadedError. Triggers: `apiKey`, `AWS_BEARER_TOKEN_BEDROCK`, `providerOptions`, `BedrockCallOptions`, `countTokens`, `BedrockSDK`, `bedrock.model`, `bedrock.embedder`, `bedrock.count`, `BedrockRuntimeClient`, `reasoning`, `thinking`, `budget_tokens`, `cachePoint`, `cacheControl`, `ai.providerTool`, `systemTool`, `nova_grounding`, `server_tool_use`, `streamChunks`, `promptCaching`, `cachedTokens`, `cacheWriteTokens`; "how do I use AWS Bedrock", "wire Claude/Nova/Llama on Bedrock", "Titan embeddings", "Bedrock Converse API", "Claude 3.7/4 extended thinking on Bedrock", "Bedrock prompt caching cost"; typical import `import { BedrockSDK } from "@warlock.js/ai-bedrock"`. Skip: agent wiring — the `run-ai-agent` topic of the `warlock-js-ai` skill; provider choice — the `pick-ai-provider` topic of the `warlock-js-ai` skill; embeddings concepts — the `embed-text` topic of the `warlock-js-ai` skill; competing libs `@aws-sdk/client-bedrock-runtime`, `@ai-sdk/amazon-bedrock`; sibling adapters `@warlock.js/ai-openai`, `@warlock.js/ai-anthropic`, `@warlock.js/ai-google`, `@warlock.js/ai-ollama`.
package/package.json CHANGED
@@ -15,13 +15,13 @@
15
15
  "directory": "packages/ai-bedrock"
16
16
  },
17
17
  "peerDependencies": {
18
- "@warlock.js/ai": "5.30.0"
18
+ "@warlock.js/ai": "5.32.0"
19
19
  },
20
20
  "dependencies": {
21
21
  "@aws-sdk/client-bedrock-runtime": "^3.1048.0",
22
- "@warlock.js/logger": "5.30.0"
22
+ "@warlock.js/logger": "5.32.0"
23
23
  },
24
- "version": "5.30.0",
24
+ "version": "5.32.0",
25
25
  "main": "./cjs/index.cjs",
26
26
  "module": "./esm/index.mjs",
27
27
  "types": "./esm/index.d.mts",