@xiaoso/dsh-tool-plus 0.1.16 → 0.1.17-beta.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.
Files changed (109) hide show
  1. package/lib/{abort-DZ54CaKU.mjs → abort-BTblp0Rt.mjs} +2 -2
  2. package/lib/{alibaba-coding-plan-DODpkcqi.mjs → alibaba-coding-plan-t3R4YKCB.mjs} +3 -3
  3. package/lib/{alibaba-token-plan-C6lpKCda.mjs → alibaba-token-plan-CO4djG1y.mjs} +4 -4
  4. package/lib/{alibaba-token-plan-CHGyWOfX.mjs → alibaba-token-plan-CUjYJX0-.mjs} +1 -1
  5. package/lib/{anthropic-Dv_GGX6g.mjs → anthropic-nf7w6so1.mjs} +48 -21
  6. package/lib/{api-key-validation-MnMf_ihX.mjs → api-key-validation-C_tZ7Y9a.mjs} +2 -2
  7. package/lib/behavior-BwvTUtag.mjs +111 -0
  8. package/lib/{browser-render-BZXt548F.mjs → browser-render-BQaEVK_n.mjs} +4 -4
  9. package/lib/{reference-CtvM4zLU.mjs → bundled-references-CrQ4dQcT.mjs} +57 -4
  10. package/lib/cascade-BWjRTD1q.mjs +30265 -0
  11. package/lib/{cline-pass-BT9CBEOj.mjs → cline-pass-Bjm-O8GG.mjs} +2 -2
  12. package/lib/cloudflare-CKXRJ0l9.mjs +37 -0
  13. package/lib/{cloudflare-ai-gateway-DReN6ohJ.mjs → cloudflare-ai-gateway-BpnBSjwV.mjs} +8 -4
  14. package/lib/cloudflare-workers-ai-odj9XswL.mjs +32 -0
  15. package/lib/collapse-_nkb2dn7.mjs +1945 -0
  16. package/lib/{coreweave-C82HrLpb.mjs → coreweave-CGDZOD8-.mjs} +1 -1
  17. package/lib/{coreweave-C68UgRQO.mjs → coreweave-DwffcgW5.mjs} +4 -4
  18. package/lib/cursor-BgOuV7Qf.mjs +794 -0
  19. package/lib/{cursor-_gHHq-Dq.mjs → cursor-CF1iHHbv.mjs} +68 -19
  20. package/lib/{cursor-proto-Cr_WEMuv.mjs → cursor-proto-BuNTjX3L.mjs} +823 -23
  21. package/lib/{devin-QpfTSl9H.mjs → devin-7OEeEb80.mjs} +112 -31
  22. package/lib/{devin-proto-DYhp4Ty6.mjs → devin-proto-C-QreeAv.mjs} +71 -5
  23. package/lib/{dom-DG3sPESc.mjs → dom-BmbZv4v9.mjs} +598 -182
  24. package/lib/{error-O63pC8zg.mjs → error-8LVo7tug.mjs} +725 -104
  25. package/lib/factory-droid-ChhmsGWb.mjs +71 -0
  26. package/lib/{fs-promises-shim-B2YFWkcd.mjs → fs-promises-shim-CANAxFWh.mjs} +10 -1
  27. package/lib/{github-copilot-BMEcw8N1.mjs → github-copilot-QwevdT30.mjs} +4 -4
  28. package/lib/{github-copilot-headers-DnjGEbko.mjs → github-copilot-headers-CAUZ0rUD.mjs} +138 -26
  29. package/lib/{gitlab-duo-DnHqJjFY.mjs → gitlab-duo-DigV7k_o.mjs} +2 -2
  30. package/lib/{google-antigravity-B1mSckrK.mjs → google-antigravity-D-oe0r8A.mjs} +6 -7
  31. package/lib/{google-gemini-cli-DJwThCCn.mjs → google-gemini-cli-CQBHgGJT.mjs} +5 -6
  32. package/lib/{google-oauth-shared-BctLpVUN.mjs → google-oauth-shared-CvgVIUwJ.mjs} +2 -2
  33. package/lib/google-validation-CdvRj4ec.mjs +126 -0
  34. package/lib/id-EJwVLDHE.mjs +2548 -0
  35. package/lib/index.mjs +248 -258
  36. package/lib/{kilo-BEgEwMJQ.mjs → kilo-5r6OffCa.mjs} +2 -2
  37. package/lib/{kimi-T9NldEIJ.mjs → kimi-DOOtbXmm.mjs} +9 -10
  38. package/lib/{launch-BIWNyrBB.mjs → launch-DkAjib7h.mjs} +1 -1
  39. package/lib/{markit-Dvp2JPdT.mjs → markit-CCcyeAds.mjs} +359 -140
  40. package/lib/{models-DnXMYGcJ.mjs → models-DCpDT_im.mjs} +199203 -112275
  41. package/lib/{muse-code-CNvqqAp6.mjs → muse-code-CYf8zj_B.mjs} +5 -5
  42. package/lib/{openai-codex-D5-CyTxa.mjs → openai-codex-Cj-TvSFh.mjs} +13 -10
  43. package/lib/{perplexity-A2PEoGaC.mjs → perplexity-Dh_Qgsmx.mjs} +68 -25
  44. package/lib/{pkce-BYjmugmw.mjs → pkce-DO-jBJLV.mjs} +1 -1
  45. package/lib/pricing-DusBEhwm.mjs +593 -0
  46. package/lib/{readability-uGhqb4GC.mjs → readability-XHK0o3bv.mjs} +287 -27
  47. package/lib/{scrapers-C1ujjV8k.mjs → scrapers-B6PADOVm.mjs} +13 -13
  48. package/lib/slugify-ynYWBIA5.mjs +11 -0
  49. package/lib/snowflake-B_jap6lz.mjs +666 -0
  50. package/lib/snowflake-Cu1ZyOp6.mjs +151 -0
  51. package/lib/{src-AELUUb5U.mjs → src-BhinCSpi.mjs} +1172 -458
  52. package/lib/{stream-AVOoe5Hj.mjs → stream-D2ivg3GH.mjs} +3740 -5311
  53. package/lib/{turndown-D6fof1OX.mjs → turndown-Vya8SavL.mjs} +82 -30
  54. package/lib/types/tools/hashline/native/index.d.ts +2 -2
  55. package/lib/types/tools/hashline/native/policy.d.ts +19 -21
  56. package/lib/types/tools/omp/session/agent-storage.d.ts +3 -3
  57. package/lib/types/tools/shared/bun-named-shim.d.ts +5 -0
  58. package/lib/{types-BLrLohwK.mjs → types-tH1v9uRm.mjs} +2 -2
  59. package/lib/{utils-cZX3f_Ls.mjs → utils-C_Ncya1r.mjs} +1737 -509
  60. package/lib/utils-D2tK38xq.mjs +34006 -0
  61. package/lib/{utils-I4I8azHN.mjs → utils-DrDwmNtu.mjs} +8 -3
  62. package/lib/{xai-oauth-CbeldUSV.mjs → xai-oauth-DLLzX6my.mjs} +4 -4
  63. package/lib/{xiaomi-Dl3VSs04.mjs → xiaomi-CqK-KivK.mjs} +2 -2
  64. package/lib/{zai-FyjGSypr.mjs → zai-DoJ2xPIH.mjs} +2 -2
  65. package/lib/{zip-DRrycScC.mjs → zip-DG1mUV6X.mjs} +1 -1
  66. package/package.json +8 -8
  67. package/lib/amazon-bedrock-Dx0rr9dY.mjs +0 -996
  68. package/lib/anthropic-ClCw0PV_.mjs +0 -3624
  69. package/lib/anthropic-wire-lbGAFzYb.mjs +0 -927
  70. package/lib/azure-openai-responses-WE_bgFWp.mjs +0 -285
  71. package/lib/bundled-references-DY3EJxZV.mjs +0 -56
  72. package/lib/cloudflare-ai-gateway-CrMa97Ap.mjs +0 -44
  73. package/lib/collapse-CkMNRNr7.mjs +0 -2304
  74. package/lib/cursor-C6jaIJDg.mjs +0 -283
  75. package/lib/cursor-D-XZYDf_.mjs +0 -4544
  76. package/lib/deterministic-id-CUEIMSqR.mjs +0 -17
  77. package/lib/devin-ExGIghmx.mjs +0 -69
  78. package/lib/devin-u0ljw5P6.mjs +0 -628
  79. package/lib/effort-BdtQMN-_.mjs +0 -23
  80. package/lib/event-stream-BKEtb45Y.mjs +0 -167
  81. package/lib/gemini-headers-Co9cVvex.mjs +0 -54
  82. package/lib/google-auth-qAN-6DMW.mjs +0 -232
  83. package/lib/google-gemini-cli-B2Aw1S5w.mjs +0 -844
  84. package/lib/google-lTxuq28n.mjs +0 -38
  85. package/lib/google-shared-Y01j9xOr.mjs +0 -856
  86. package/lib/google-validation-BEkNs-Bx.mjs +0 -18
  87. package/lib/google-vertex-DcM-FRC5.mjs +0 -99
  88. package/lib/hosts-00rjRzUD.mjs +0 -203
  89. package/lib/id-AL5obQzR.mjs +0 -71
  90. package/lib/idle-iterator-D0ZXEcUq.mjs +0 -366
  91. package/lib/ollama-6R0oXZks.mjs +0 -574
  92. package/lib/openai-codex-responses-C8bnBWOe.mjs +0 -3232
  93. package/lib/openai-completions-DNr3mUsn.mjs +0 -1430
  94. package/lib/openai-configuration-update-xMYUjaK_.mjs +0 -150
  95. package/lib/openai-reasoning-fallback-Ju-5pSR8.mjs +0 -380
  96. package/lib/openai-responses-CjpafAEr.mjs +0 -861
  97. package/lib/protobuf-BMgDYu_U.mjs +0 -717
  98. package/lib/provider-response-SqKSkkUc.mjs +0 -22
  99. package/lib/proxy-DxvCQOCA.mjs +0 -230
  100. package/lib/request-debug-BwPOqN_j.mjs +0 -183
  101. package/lib/sanitize-text-BCf5KmCf.mjs +0 -33
  102. package/lib/sse-debug-B-tkLCPW.mjs +0 -11
  103. package/lib/stream-markup-healing-CN3RsqG9.mjs +0 -267
  104. package/lib/strict-tool-validation-CBTz1dAA.mjs +0 -105
  105. package/lib/taxonomy-DSIM99rS.mjs +0 -15392
  106. package/lib/thinking-ngMwf_1Y.mjs +0 -336
  107. package/lib/type-guards-CttAANEx.mjs +0 -11
  108. package/lib/utils-CE3DSebh.mjs +0 -11763
  109. package/lib/vision-guard-BCpXWUj3.mjs +0 -77
@@ -1,996 +0,0 @@
1
- import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
- __installBunShim();
3
- import { B as USER_AGENT, C as warn, F as $flag, _ as parseStreamingJson, v as parseStreamingJsonThrottled } from "./src-AELUUb5U.mjs";
4
- import { G as fetchWithRetry, I as BedrockApiError, U as EventStreamFrameError, _ as AbortError, c as finalize, r as ValidationError } from "./error-O63pC8zg.mjs";
5
- import { A as toolWireSchema, C as kStreamingLastParseLen, T as renderDemotedThinking, b as kStreamingBlockIndex, c as resolveCacheRetention, g as clearStreamingPartialJson, h as transformMessages, o as normalizeSystemPrompts, s as normalizeToolCallId, w as kStreamingPartialJson } from "./utils-cZX3f_Ls.mjs";
6
- import { n as isRecord } from "./type-guards-CttAANEx.mjs";
7
- import { a as mapEffortToAnthropicAdaptiveEffort, c as invalidateAwsCredentialCache, d as resolveAwsBearerToken, l as resolveAwsCredentials, m as resolveAwsAmbientRegion, o as requireSupportedEffort, r as parseAnthropicInputTransformations, t as THINKING_BINDING_CONTROLS_BETA, u as signRequest } from "./anthropic-wire-lbGAFzYb.mjs";
8
- import { t as calculateCost } from "./models-DnXMYGcJ.mjs";
9
- import { t as AssistantMessageEventStream } from "./event-stream-BKEtb45Y.mjs";
10
- import { i as getStreamFirstEventTimeoutMs, t as armPreResponseTimeout } from "./idle-iterator-D0ZXEcUq.mjs";
11
- //#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/providers/aws-eventstream.ts
12
- /**
13
- * `application/vnd.amazon.eventstream` decoder.
14
- *
15
- * Wire format (all integers big-endian):
16
- *
17
- * [total length u32]
18
- * [headers length u32]
19
- * [prelude CRC32 u32] <- CRC over the first 8 bytes
20
- * [headers headers_length]
21
- * [payload total_length - headers_length - 16]
22
- * [message CRC32 u32] <- CRC over the entire message minus the trailing 4 bytes
23
- *
24
- * Headers: a sequence of `[name_len u8][name utf8][value_type u8][value …]`.
25
- * We only need the typed values Bedrock emits (boolean true/false, byte, short,
26
- * integer, long, byte-array, string, timestamp, uuid). All are surfaced as
27
- * strings for ease of consumption — Bedrock only sets string-valued headers in
28
- * practice (`:event-type`, `:message-type`, `:content-type`, `:exception-type`).
29
- */
30
- const PRELUDE_LEN = 8;
31
- const MESSAGE_CRC_LEN = 4;
32
- const HEADER_BLOCK_OFFSET = 12;
33
- const MIN_MESSAGE_LEN = 16;
34
- /** CRC32 (IEEE / zlib polynomial 0xEDB88320), matches `@aws-crypto/crc32`. */
35
- function crc32(bytes) {
36
- return Bun.hash.crc32(bytes) >>> 0;
37
- }
38
- /**
39
- * Decode a single, fully buffered eventstream message. Throws if the framing is
40
- * malformed or either CRC mismatches. Used by both `decodeEventStream` (the
41
- * streaming entry point) and the unit tests, which exercise it with hand-built
42
- * frames.
43
- */
44
- function decodeMessage(frame) {
45
- if (frame.length < MIN_MESSAGE_LEN) throw new EventStreamFrameError("frame too short");
46
- const view = new DataView(frame.buffer, frame.byteOffset, frame.byteLength);
47
- const total = view.getUint32(0, false);
48
- if (total !== frame.length) throw new EventStreamFrameError(`framed length ${total} != buffer ${frame.length}`);
49
- const headersLen = view.getUint32(4, false);
50
- const preludeCrc = view.getUint32(8, false);
51
- if (crc32(frame.subarray(0, PRELUDE_LEN)) !== preludeCrc) throw new EventStreamFrameError("prelude CRC mismatch");
52
- const msgCrc = view.getUint32(total - MESSAGE_CRC_LEN, false);
53
- if (crc32(frame.subarray(0, total - MESSAGE_CRC_LEN)) !== msgCrc) throw new EventStreamFrameError("message CRC mismatch");
54
- const headersBytes = frame.subarray(HEADER_BLOCK_OFFSET, HEADER_BLOCK_OFFSET + headersLen);
55
- const payload = frame.subarray(HEADER_BLOCK_OFFSET + headersLen, total - MESSAGE_CRC_LEN);
56
- return {
57
- headers: parseHeaders(headersBytes),
58
- payload
59
- };
60
- }
61
- function parseHeaders(buf) {
62
- const out = {};
63
- const view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
64
- const decoder = new TextDecoder();
65
- let p = 0;
66
- while (p < buf.length) {
67
- const nameLen = view.getUint8(p);
68
- p += 1;
69
- const name = decoder.decode(buf.subarray(p, p + nameLen));
70
- p += nameLen;
71
- const type = view.getUint8(p);
72
- p += 1;
73
- switch (type) {
74
- case 0:
75
- out[name] = "true";
76
- break;
77
- case 1:
78
- out[name] = "false";
79
- break;
80
- case 2:
81
- out[name] = String(view.getInt8(p));
82
- p += 1;
83
- break;
84
- case 3:
85
- out[name] = String(view.getInt16(p, false));
86
- p += 2;
87
- break;
88
- case 4:
89
- out[name] = String(view.getInt32(p, false));
90
- p += 4;
91
- break;
92
- case 5:
93
- out[name] = bigIntFromBytes(buf.subarray(p, p + 8)).toString();
94
- p += 8;
95
- break;
96
- case 6: {
97
- const len = view.getUint16(p, false);
98
- p += 2;
99
- out[name] = Buffer.from(buf.buffer, buf.byteOffset + p, len).toString("base64");
100
- p += len;
101
- break;
102
- }
103
- case 7: {
104
- const len = view.getUint16(p, false);
105
- p += 2;
106
- out[name] = decoder.decode(buf.subarray(p, p + len));
107
- p += len;
108
- break;
109
- }
110
- case 8:
111
- out[name] = new Date(Number(bigIntFromBytes(buf.subarray(p, p + 8)))).toISOString();
112
- p += 8;
113
- break;
114
- case 9: {
115
- const u = buf.subarray(p, p + 16);
116
- const hex = [];
117
- for (let i = 0; i < 16; i++) hex.push(u[i].toString(16).padStart(2, "0"));
118
- out[name] = `${hex.slice(0, 4).join("")}-${hex.slice(4, 6).join("")}-${hex.slice(6, 8).join("")}-${hex.slice(8, 10).join("")}-${hex.slice(10, 16).join("")}`;
119
- p += 16;
120
- break;
121
- }
122
- default: throw new EventStreamFrameError(`unknown header value type ${type}`);
123
- }
124
- }
125
- return out;
126
- }
127
- function bigIntFromBytes(b) {
128
- let v = 0n;
129
- for (let i = 0; i < b.length; i++) v = v << 8n | BigInt(b[i]);
130
- if (b.length === 8 && b[0] & 128) v -= 1n << 64n;
131
- return v;
132
- }
133
- /**
134
- * Async generator that consumes a `ReadableStream<Uint8Array>` (e.g. a fetch
135
- * response body) and yields fully-framed messages. Handles arbitrary chunk
136
- * boundaries: messages may span multiple chunks, and a single chunk may carry
137
- * many messages.
138
- */
139
- async function* decodeEventStream(source) {
140
- const reader = source.getReader();
141
- let buf = /* @__PURE__ */ new Uint8Array(0);
142
- let completed = false;
143
- try {
144
- while (true) {
145
- const { value, done } = await reader.read();
146
- if (value && value.length > 0) buf = buf.length === 0 ? value : Buffer.concat([buf, value]);
147
- let offset = 0;
148
- while (buf.length - offset >= 4) {
149
- const total = new DataView(buf.buffer, buf.byteOffset + offset, buf.length - offset).getUint32(0, false);
150
- if (total < MIN_MESSAGE_LEN) throw new EventStreamFrameError(`total length ${total} below minimum`);
151
- if (buf.length - offset < total) break;
152
- yield decodeMessage(buf.subarray(offset, offset + total));
153
- offset += total;
154
- }
155
- if (offset > 0) buf = buf.slice(offset);
156
- if (done) break;
157
- }
158
- if (buf.length > 0) throw new EventStreamFrameError("truncated message at end of stream");
159
- completed = true;
160
- } finally {
161
- if (!completed) await reader.cancel().catch(() => {});
162
- reader.releaseLock();
163
- }
164
- }
165
- //#endregion
166
- //#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/providers/amazon-bedrock.ts
167
- /**
168
- * Headers SigV4 generates for itself. A caller cannot be allowed to supply these:
169
- * `signRequest` would sign the caller's value but return its own, so the signature
170
- * would not match what goes on the wire.
171
- */
172
- const SIGNER_OWNED_HEADERS = /* @__PURE__ */ new Set([
173
- "host",
174
- "x-amz-date",
175
- "x-amz-content-sha256",
176
- "x-amz-security-token"
177
- ]);
178
- /** Headers the Bedrock request sets itself; a caller copy in any casing duplicates them. */
179
- const BEDROCK_RESERVED_HEADERS = /* @__PURE__ */ new Set([
180
- "content-type",
181
- "accept",
182
- "authorization",
183
- "content-length"
184
- ]);
185
- function resolveBearerToken(options) {
186
- return resolveAwsBearerToken(options.apiKey, options.bearerToken);
187
- }
188
- function inferRegionFromBedrockArn(modelId) {
189
- const parts = modelId.split(":", 6);
190
- if (parts[0] !== "arn" || parts[2] !== "bedrock") return void 0;
191
- return parts[3] || void 0;
192
- }
193
- /**
194
- * Default AWS region for each Bedrock cross-region inference-profile geo prefix.
195
- * A geo-prefixed profile (e.g. `eu.anthropic.claude-…`) is only servable from
196
- * regions in its own geo, so routing one to `us-east-1` yields HTTP 400 "The
197
- * provided model identifier is invalid." `global.` profiles are anchored in the
198
- * us regions and intentionally absent here (they resolve fine via `us-east-1`).
199
- */
200
- const INFERENCE_PROFILE_GEO_DEFAULT_REGION = {
201
- us: "us-east-1",
202
- "us-gov": "us-gov-west-1",
203
- eu: "eu-west-1",
204
- apac: "ap-southeast-1",
205
- au: "ap-southeast-2",
206
- jp: "ap-northeast-1"
207
- };
208
- /** Geo prefix of a cross-region inference-profile id, e.g. `eu.anthropic.…` → `eu`. */
209
- function inferenceProfileGeo(modelId) {
210
- const dot = modelId.indexOf(".");
211
- if (dot <= 0) return void 0;
212
- const prefix = modelId.slice(0, dot);
213
- return prefix in INFERENCE_PROFILE_GEO_DEFAULT_REGION ? prefix : void 0;
214
- }
215
- /**
216
- * Whether a concrete AWS region can serve a given inference-profile geo. The
217
- * `ap-` regions overlap across `apac`/`au`/`jp` profiles, so the Australia and
218
- * Japan geos pin their specific source regions rather than matching all `ap-*`.
219
- */
220
- function regionServesGeo(region, geo) {
221
- switch (geo) {
222
- case "us-gov": return region.startsWith("us-gov-");
223
- case "us": return region.startsWith("us-") && !region.startsWith("us-gov-");
224
- case "eu": return region.startsWith("eu-");
225
- case "apac": return region.startsWith("ap-");
226
- case "au": return region === "ap-southeast-2" || region === "ap-southeast-4";
227
- case "jp": return region === "ap-northeast-1" || region === "ap-northeast-3";
228
- default: return false;
229
- }
230
- }
231
- /**
232
- * Resolve the Bedrock runtime region for a request. An explicit per-request
233
- * region and an ARN-embedded model region win outright. Otherwise, for a
234
- * geo-prefixed cross-region inference profile (`us.`/`eu.`/`apac.`/`au.`/`jp.`/
235
- * `us-gov.`), an ambient region (`AWS_REGION` / `AWS_DEFAULT_REGION`) is
236
- * honored only when it can serve the profile's geo. If the ambient region is
237
- * absent or mismatched, a same-geo guardrail ARN region is used when available;
238
- * otherwise the geo default is used. `global.` profiles have no geo entry, so
239
- * the ambient region (or, when absent, a guardrail ARN's region or
240
- * `us-east-1`) is used unchanged.
241
- */
242
- function resolveBedrockRegion(modelId, options) {
243
- const explicit = options.region || inferRegionFromBedrockArn(modelId);
244
- if (explicit) return explicit;
245
- const ambient = resolveAwsAmbientRegion(options.profile);
246
- const guardrailRegion = inferRegionFromBedrockArn(options.guardrailIdentifier ?? "");
247
- const geo = inferenceProfileGeo(modelId);
248
- if (geo) {
249
- if (ambient && regionServesGeo(ambient, geo)) return ambient;
250
- if (guardrailRegion && regionServesGeo(guardrailRegion, geo)) return guardrailRegion;
251
- return INFERENCE_PROFILE_GEO_DEFAULT_REGION[geo];
252
- }
253
- return ambient || guardrailRegion || "us-east-1";
254
- }
255
- /**
256
- * Bedrock validates that requests carrying any `toolUse`/`toolResult` history
257
- * include a `toolConfig`. For no-tool ephemeral turns (`/btw`, IRC auto-replies)
258
- * we have nothing real to send, so we inject this placeholder. Its presence is
259
- * tracked by a per-request flag — never the wire name — so callers who happen
260
- * to register a real tool literally called `__no_tools__` are not affected.
261
- */
262
- const NO_TOOLS_SENTINEL_NAME = "__no_tools__";
263
- const NO_TOOLS_SENTINEL = { toolSpec: {
264
- name: NO_TOOLS_SENTINEL_NAME,
265
- description: "Placeholder required by Bedrock validation. Do not call; answer with text.",
266
- inputSchema: { json: {
267
- type: "object",
268
- properties: {}
269
- } }
270
- } };
271
- const REQUEST_METADATA_PATTERN = /^[a-zA-Z0-9\s:_@$#=/+,\-.]*$/;
272
- const REQUEST_METADATA_MAX_ENTRIES = 16;
273
- const REQUEST_METADATA_MAX_LENGTH = 256;
274
- /**
275
- * Bedrock rejects the whole invocation on a malformed `requestMetadata` entry.
276
- * Attribution tags must never cost a turn, so invalid and excess entries are
277
- * dropped with a warning instead of failing the request. Returns `undefined`
278
- * for an empty result so the field is omitted from the body entirely.
279
- */
280
- function sanitizeRequestMetadata(raw) {
281
- if (!isRecord(raw)) return void 0;
282
- const out = {};
283
- const dropped = [];
284
- let kept = 0;
285
- for (const [key, value] of Object.entries(raw)) {
286
- if (typeof value !== "string" || key.length < 1 || key.length > REQUEST_METADATA_MAX_LENGTH || !REQUEST_METADATA_PATTERN.test(key) || value.length > REQUEST_METADATA_MAX_LENGTH || !REQUEST_METADATA_PATTERN.test(value) || kept >= REQUEST_METADATA_MAX_ENTRIES) {
287
- dropped.push(key);
288
- continue;
289
- }
290
- out[key] = value;
291
- kept++;
292
- }
293
- if (dropped.length > 0) warn("Bedrock requestMetadata entries dropped", { keys: dropped });
294
- return kept > 0 ? out : void 0;
295
- }
296
- const streamBedrock = (model, context, options) => {
297
- const stream = new AssistantMessageEventStream();
298
- (async () => {
299
- const startTime = performance.now();
300
- let firstTokenTime;
301
- const output = {
302
- role: "assistant",
303
- content: [],
304
- api: "bedrock-converse-stream",
305
- provider: model.provider,
306
- model: model.id,
307
- usage: {
308
- input: 0,
309
- output: 0,
310
- cacheRead: 0,
311
- cacheWrite: 0,
312
- totalTokens: 0,
313
- cost: {
314
- input: 0,
315
- output: 0,
316
- cacheRead: 0,
317
- cacheWrite: 0,
318
- total: 0
319
- }
320
- },
321
- stopReason: "stop",
322
- timestamp: Date.now()
323
- };
324
- const blocks = output.content;
325
- let rawRequestDump;
326
- const region = resolveBedrockRegion(model.id, options);
327
- try {
328
- const promptCachePolicy = resolvePromptCachePolicy(model, resolveCacheRetention(options.cacheRetention));
329
- const convertedMessages = convertMessages(context, model, promptCachePolicy);
330
- const toolPlan = planToolConfig(context.tools, options.toolChoice, convertedMessages);
331
- let toolConfig = toolPlan.toolConfig;
332
- const sentinelInjected = toolPlan.sentinelInjected;
333
- let additionalModelRequestFields = buildAdditionalModelRequestFields(model, options);
334
- const prefixMismatchBehavior = model.thinking?.prefixBinding ? options.anthropicPrefixMismatchBehavior ?? "drop_block" : void 0;
335
- if (toolConfig?.toolChoice && additionalModelRequestFields) {
336
- const tc = toolConfig.toolChoice;
337
- if (tc.any || tc.tool) {
338
- if (prefixMismatchBehavior) toolConfig = {
339
- ...toolConfig,
340
- toolChoice: { auto: {} }
341
- };
342
- else additionalModelRequestFields = void 0;
343
- }
344
- }
345
- if (prefixMismatchBehavior) additionalModelRequestFields = applyBedrockThinkingBinding(additionalModelRequestFields, prefixMismatchBehavior);
346
- let commandInput = {
347
- messages: convertedMessages,
348
- system: buildSystemPrompt(context.systemPrompt, promptCachePolicy),
349
- inferenceConfig: {
350
- maxTokens: options.maxTokens,
351
- temperature: options.temperature,
352
- topP: options.topP
353
- },
354
- toolConfig,
355
- guardrailConfig: buildGuardrailConfig(options),
356
- additionalModelRequestFields,
357
- requestMetadata: model.requestMetadata || options.requestMetadata ? {
358
- ...model.requestMetadata,
359
- ...options.requestMetadata
360
- } : void 0,
361
- ...prefixMismatchBehavior ? { additionalModelResponseFieldPaths: ["/input_transformations"] } : {}
362
- };
363
- const replacementInput = await options?.onPayload?.(commandInput, model);
364
- if (replacementInput !== void 0) commandInput = replacementInput;
365
- commandInput = {
366
- ...commandInput,
367
- requestMetadata: sanitizeRequestMetadata(commandInput.requestMetadata)
368
- };
369
- const host = `bedrock-runtime.${region}.amazonaws.com`;
370
- const url = `https://${host}/model/${encodeURIComponent(model.id)}/converse-stream`;
371
- const urlPath = `/model/${encodeURIComponent(model.id)}/converse-stream`;
372
- rawRequestDump = {
373
- provider: model.provider,
374
- api: output.api,
375
- model: model.id,
376
- method: "POST",
377
- url,
378
- body: commandInput
379
- };
380
- const bodyText = JSON.stringify(commandInput);
381
- const body = new TextEncoder().encode(bodyText);
382
- const callerHeaders = {};
383
- for (const source of [model.headers, options?.headers]) for (const [name, value] of Object.entries(source ?? {})) {
384
- const field = name.toLowerCase();
385
- if (SIGNER_OWNED_HEADERS.has(field) || BEDROCK_RESERVED_HEADERS.has(field)) continue;
386
- callerHeaders[field] = value;
387
- }
388
- callerHeaders["user-agent"] ??= USER_AGENT;
389
- const baseHeaders = {
390
- ...callerHeaders,
391
- "content-type": "application/json",
392
- accept: "application/vnd.amazon.eventstream"
393
- };
394
- const bearerToken = resolveBearerToken(options);
395
- let requestHeaders;
396
- if (bearerToken) requestHeaders = {
397
- ...baseHeaders,
398
- Authorization: `Bearer ${bearerToken}`
399
- };
400
- else {
401
- let credentials;
402
- if ($flag("AWS_BEDROCK_SKIP_AUTH")) credentials = {
403
- accessKeyId: "dummy-access-key",
404
- secretAccessKey: "dummy-secret-key"
405
- };
406
- else credentials = await resolveAwsCredentials({
407
- profile: options.profile,
408
- region,
409
- signal: options.signal,
410
- fetch: options.fetch
411
- });
412
- const signed = await signRequest({
413
- method: "POST",
414
- host,
415
- path: urlPath,
416
- body,
417
- region,
418
- service: "bedrock",
419
- credentials,
420
- headers: baseHeaders
421
- });
422
- requestHeaders = {
423
- ...baseHeaders,
424
- ...signed
425
- };
426
- }
427
- const firstEventTimeoutMs = options.streamFirstEventTimeoutMs ?? getStreamFirstEventTimeoutMs();
428
- const watchdog = armPreResponseTimeout(options.signal, firstEventTimeoutMs);
429
- let response;
430
- try {
431
- response = await fetchWithRetry(url, {
432
- method: "POST",
433
- headers: requestHeaders,
434
- body,
435
- signal: watchdog.signal,
436
- fetch: options.fetch,
437
- timeout: false
438
- });
439
- } finally {
440
- watchdog.clear();
441
- }
442
- if (!response.ok) {
443
- if (!bearerToken && (response.status === 401 || response.status === 403)) invalidateAwsCredentialCache({
444
- profile: options.profile,
445
- region
446
- });
447
- const errBody = await response.text().catch(() => "");
448
- throw new BedrockApiError(`Bedrock HTTP ${response.status}: ${errBody.slice(0, 1e3)}`, response.status, { headers: response.headers });
449
- }
450
- if (!response.body) throw new BedrockApiError("Bedrock response has no body", response.status);
451
- for await (const message of decodeEventStream(response.body)) {
452
- const messageType = message.headers[":message-type"];
453
- const eventType = message.headers[":event-type"];
454
- if (messageType === "exception") {
455
- const exceptionType = message.headers[":exception-type"] || "Exception";
456
- const text = `${exceptionType}: ${safeParsePayload(message.payload)?.message || new TextDecoder().decode(message.payload)}`;
457
- throw new BedrockApiError(text, 400, { code: exceptionType });
458
- }
459
- if (messageType === "error") {
460
- const code = message.headers[":error-code"] || "UnknownError";
461
- const errorMessage = message.headers[":error-message"] || new TextDecoder().decode(message.payload);
462
- throw new BedrockApiError(`${code}: ${errorMessage}`, 400, { code });
463
- }
464
- if (messageType !== "event") continue;
465
- const payload = safeParsePayload(message.payload);
466
- if (!payload) continue;
467
- switch (eventType) {
468
- case "messageStart":
469
- if (payload.role !== "assistant") throw new BedrockApiError("Unexpected assistant message start but got user message start instead", 0);
470
- stream.push({
471
- type: "start",
472
- partial: output
473
- });
474
- break;
475
- case "contentBlockStart":
476
- if (!firstTokenTime) firstTokenTime = performance.now();
477
- handleContentBlockStart(payload, blocks, output, stream, sentinelInjected);
478
- break;
479
- case "contentBlockDelta":
480
- if (!firstTokenTime) firstTokenTime = performance.now();
481
- handleContentBlockDelta(payload, blocks, output, stream);
482
- break;
483
- case "contentBlockStop":
484
- handleContentBlockStop(payload, blocks, output, stream);
485
- break;
486
- case "messageStop": {
487
- const ev = payload;
488
- const responseFields = isRecord(ev.additionalModelResponseFields) ? ev.additionalModelResponseFields : void 0;
489
- const transformations = parseAnthropicInputTransformations(responseFields?.input_transformations);
490
- if (transformations.length > 0) {
491
- output.inputTransformations = transformations;
492
- for (const transformation of transformations) {
493
- if (transformation.reason !== "prefix_binding_mismatch") continue;
494
- warn("bedrock: dropped thinking block after conversation prefix changed", {
495
- model: model.id,
496
- path: transformation.path
497
- });
498
- }
499
- }
500
- output.stopReason = sentinelInjected && ev.stopReason === "tool_use" ? "stop" : mapStopReason(ev.stopReason);
501
- if (output.stopReason === "error") output.errorMessage = ev.stopReason === "guardrail_intervened" ? `Response blocked by Amazon Bedrock guardrail (stop reason: ${ev.stopReason}).` : ev.stopReason === "content_filtered" ? `Response filtered by Amazon Bedrock content filters (stop reason: ${ev.stopReason}).` : `Generation failed with stop reason: ${ev.stopReason ?? "unknown"}`;
502
- break;
503
- }
504
- case "metadata": handleMetadata(payload, model, output);
505
- }
506
- }
507
- if (options.signal?.aborted) throw new AbortError();
508
- if (output.stopReason === "error" || output.stopReason === "aborted") throw new BedrockApiError(output.errorMessage ?? "An unknown error occurred", 0);
509
- output.duration = performance.now() - startTime;
510
- if (firstTokenTime) output.ttft = firstTokenTime - startTime;
511
- stream.push({
512
- type: "done",
513
- reason: output.stopReason,
514
- message: output
515
- });
516
- stream.end();
517
- } catch (error) {
518
- for (const block of output.content) if (block.type === "toolCall") clearStreamingPartialJson(block);
519
- let baseMessage;
520
- try {
521
- baseMessage = error instanceof Error ? error.message : JSON.stringify(error) ?? String(error);
522
- } catch {
523
- baseMessage = String(error);
524
- }
525
- let diagnostics = "";
526
- if (baseMessage.includes("signature") || baseMessage.includes("thinking")) {
527
- const thinkingBlocks = context.messages.filter((m) => m.role === "assistant").flatMap((m, mi) => m.content.filter((b) => b.type === "thinking").map((b, bi) => ({
528
- msg: mi,
529
- block: bi,
530
- stop: m.stopReason,
531
- sigLen: b.thinkingSignature?.length ?? -1,
532
- thinkLen: b.thinking.length
533
- })));
534
- if (thinkingBlocks.length > 0) diagnostics = `\n[thinking-diag] ${JSON.stringify(thinkingBlocks)}`;
535
- }
536
- const result = await finalize(error, {
537
- api: model.api,
538
- signal: options.signal,
539
- rawRequestDump
540
- });
541
- output.stopReason = result.stopReason;
542
- output.errorStatus = result.status;
543
- output.errorId = result.id;
544
- output.errorMessage = result.message + diagnostics;
545
- output.duration = performance.now() - startTime;
546
- if (firstTokenTime) output.ttft = firstTokenTime - startTime;
547
- stream.push({
548
- type: "error",
549
- reason: output.stopReason,
550
- error: output
551
- });
552
- stream.end();
553
- }
554
- })();
555
- return stream;
556
- };
557
- function safeParsePayload(payload) {
558
- if (payload.length === 0) return {};
559
- try {
560
- return JSON.parse(new TextDecoder().decode(payload));
561
- } catch {
562
- return;
563
- }
564
- }
565
- function handleContentBlockStart(event, blocks, output, stream, sentinelInjected) {
566
- const index = event.contentBlockIndex;
567
- const start = event.start;
568
- if (sentinelInjected && start?.toolUse?.name === NO_TOOLS_SENTINEL_NAME) return;
569
- if (start?.toolUse) {
570
- const block = {
571
- type: "toolCall",
572
- id: normalizeToolCallId(start.toolUse.toolUseId || ""),
573
- name: start.toolUse.name || "",
574
- arguments: {},
575
- [kStreamingPartialJson]: "",
576
- [kStreamingBlockIndex]: index
577
- };
578
- output.content.push(block);
579
- stream.push({
580
- type: "toolcall_start",
581
- contentIndex: blocks.length - 1,
582
- partial: output
583
- });
584
- }
585
- }
586
- function handleContentBlockDelta(event, blocks, output, stream) {
587
- const contentBlockIndex = event.contentBlockIndex;
588
- const delta = event.delta;
589
- let index = blocks.findIndex((b) => b[kStreamingBlockIndex] === contentBlockIndex);
590
- let block = blocks[index];
591
- if (delta?.text !== void 0) {
592
- if (!block) {
593
- const newBlock = {
594
- type: "text",
595
- text: "",
596
- [kStreamingBlockIndex]: contentBlockIndex
597
- };
598
- output.content.push(newBlock);
599
- index = blocks.length - 1;
600
- block = blocks[index];
601
- stream.push({
602
- type: "text_start",
603
- contentIndex: index,
604
- partial: output
605
- });
606
- }
607
- if (block.type === "text") {
608
- block.text += delta.text;
609
- stream.push({
610
- type: "text_delta",
611
- contentIndex: index,
612
- delta: delta.text,
613
- partial: output
614
- });
615
- }
616
- } else if (delta?.toolUse && block?.type === "toolCall") {
617
- block[kStreamingPartialJson] = (block[kStreamingPartialJson] || "") + (delta.toolUse.input || "");
618
- const throttled = parseStreamingJsonThrottled(block[kStreamingPartialJson], block[kStreamingLastParseLen] ?? 0);
619
- if (throttled) {
620
- block.arguments = throttled.value;
621
- block[kStreamingLastParseLen] = throttled.parsedLen;
622
- }
623
- stream.push({
624
- type: "toolcall_delta",
625
- contentIndex: index,
626
- delta: delta.toolUse.input || "",
627
- partial: output
628
- });
629
- } else if (delta?.reasoningContent) {
630
- let thinkingBlock = block;
631
- let thinkingIndex = index;
632
- if (!thinkingBlock) {
633
- const newBlock = {
634
- type: "thinking",
635
- thinking: "",
636
- thinkingSignature: "",
637
- [kStreamingBlockIndex]: contentBlockIndex
638
- };
639
- output.content.push(newBlock);
640
- thinkingIndex = blocks.length - 1;
641
- thinkingBlock = blocks[thinkingIndex];
642
- stream.push({
643
- type: "thinking_start",
644
- contentIndex: thinkingIndex,
645
- partial: output
646
- });
647
- }
648
- if (thinkingBlock?.type === "thinking") {
649
- if (delta.reasoningContent.text) {
650
- thinkingBlock.thinking += delta.reasoningContent.text;
651
- stream.push({
652
- type: "thinking_delta",
653
- contentIndex: thinkingIndex,
654
- delta: delta.reasoningContent.text,
655
- partial: output
656
- });
657
- }
658
- if (delta.reasoningContent.signature) thinkingBlock.thinkingSignature = (thinkingBlock.thinkingSignature || "") + delta.reasoningContent.signature;
659
- }
660
- }
661
- }
662
- function handleMetadata(event, model, output) {
663
- if (event.usage) {
664
- output.usage.input = event.usage.inputTokens || 0;
665
- output.usage.output = event.usage.outputTokens || 0;
666
- output.usage.cacheRead = event.usage.cacheReadInputTokens || 0;
667
- output.usage.cacheWrite = event.usage.cacheWriteInputTokens || 0;
668
- output.usage.totalTokens = event.usage.totalTokens || output.usage.input + output.usage.output;
669
- calculateCost(model, output.usage, output.timestamp);
670
- }
671
- }
672
- function handleContentBlockStop(event, blocks, output, stream) {
673
- const index = blocks.findIndex((b) => b[kStreamingBlockIndex] === event.contentBlockIndex);
674
- const block = blocks[index];
675
- if (!block) return;
676
- switch (block.type) {
677
- case "text":
678
- stream.push({
679
- type: "text_end",
680
- contentIndex: index,
681
- content: block.text,
682
- partial: output
683
- });
684
- break;
685
- case "thinking":
686
- stream.push({
687
- type: "thinking_end",
688
- contentIndex: index,
689
- content: block.thinking,
690
- partial: output
691
- });
692
- break;
693
- case "toolCall":
694
- block.arguments = parseStreamingJson(block[kStreamingPartialJson]);
695
- clearStreamingPartialJson(block);
696
- stream.push({
697
- type: "toolcall_end",
698
- contentIndex: index,
699
- toolCall: block,
700
- partial: output
701
- });
702
- }
703
- }
704
- /**
705
- * Resolve Bedrock's explicit-cache request policy from the catalog's
706
- * materialized provider contract. Bedrock enforces each model's minimum
707
- * prefix-token requirement, so this boundary intentionally does not locally
708
- * count tokens. The emitter prioritizes the final user boundary, then the
709
- * system boundary, without exceeding the configured checkpoint maximum.
710
- *
711
- * `AWS_BEDROCK_FORCE_CACHE` remains an escape hatch for opaque application
712
- * inference profiles, defaulting those otherwise-unknown models to the
713
- * existing two-checkpoint layout without inventing 1h retention.
714
- */
715
- function resolvePromptCachePolicy(model, cacheRetention) {
716
- if (cacheRetention === "none" || model.compat.promptCacheMode === "automatic") return { remainingCheckpoints: 0 };
717
- const forced = $flag("AWS_BEDROCK_FORCE_CACHE");
718
- const explicit = model.compat.promptCacheMode === "explicit";
719
- if (!explicit && !forced) return { remainingCheckpoints: 0 };
720
- const configuredMaximum = explicit ? model.compat.promptCacheMaximumCheckpoints : 2;
721
- if (configuredMaximum <= 0) return { remainingCheckpoints: 0 };
722
- return {
723
- remainingCheckpoints: Math.min(configuredMaximum, 2),
724
- ...cacheRetention === "long" && model.compat.supportsLongPromptCacheRetention ? { ttl: "1h" } : {}
725
- };
726
- }
727
- function takeCachePoint(policy) {
728
- if (policy.remainingCheckpoints <= 0) return void 0;
729
- policy.remainingCheckpoints--;
730
- return { cachePoint: {
731
- type: "default",
732
- ...policy.ttl ? { ttl: policy.ttl } : {}
733
- } };
734
- }
735
- function buildSystemPrompt(systemPrompt, promptCachePolicy) {
736
- const prompts = normalizeSystemPrompts(systemPrompt);
737
- if (prompts.length === 0) return void 0;
738
- const blocks = prompts.map((prompt) => ({ text: prompt }));
739
- const cachePoint = takeCachePoint(promptCachePolicy);
740
- if (cachePoint) blocks.push(cachePoint);
741
- return blocks;
742
- }
743
- function convertMessages(context, model, promptCachePolicy) {
744
- const result = [];
745
- const transformedMessages = transformMessages(context.messages, model, normalizeToolCallId);
746
- for (let i = 0; i < transformedMessages.length; i++) {
747
- const m = transformedMessages[i];
748
- switch (m.role) {
749
- case "developer":
750
- case "user":
751
- if (typeof m.content === "string") {
752
- if (!m.content || m.content.trim() === "") continue;
753
- result.push({
754
- role: "user",
755
- content: [{ text: m.content.toWellFormed() }]
756
- });
757
- } else {
758
- const contentBlocks = [];
759
- for (const c of m.content) switch (c.type) {
760
- case "text": {
761
- const text = c.text.toWellFormed();
762
- if (text.trim().length === 0) continue;
763
- contentBlocks.push({ text });
764
- break;
765
- }
766
- case "image":
767
- contentBlocks.push({ image: createImageBlock(c.mimeType, c.data) });
768
- break;
769
- default: throw new ValidationError("Unknown user content type");
770
- }
771
- if (contentBlocks.length === 0) continue;
772
- result.push({
773
- role: "user",
774
- content: contentBlocks
775
- });
776
- }
777
- break;
778
- case "assistant": {
779
- if (m.content.length === 0) continue;
780
- const contentBlocks = [];
781
- for (const c of m.content) switch (c.type) {
782
- case "text":
783
- if (c.text.trim().length === 0) continue;
784
- contentBlocks.push({ text: c.text.toWellFormed() });
785
- break;
786
- case "toolCall":
787
- contentBlocks.push({ toolUse: {
788
- toolUseId: normalizeToolCallId(c.id),
789
- name: c.name,
790
- input: c.arguments
791
- } });
792
- break;
793
- case "thinking":
794
- if (c.thinking.trim().length === 0 && !c.thinkingSignature) continue;
795
- if (c.thinkingSignature) contentBlocks.push({ reasoningContent: { reasoningText: {
796
- text: c.thinking.toWellFormed(),
797
- signature: c.thinkingSignature
798
- } } });
799
- else contentBlocks.push({ text: renderDemotedThinking(model.id, c.thinking) });
800
- break;
801
- default: throw new ValidationError("Unknown assistant content type");
802
- }
803
- if (contentBlocks.length === 0) continue;
804
- result.push({
805
- role: "assistant",
806
- content: contentBlocks
807
- });
808
- break;
809
- }
810
- case "toolResult": {
811
- const toolResults = [];
812
- toolResults.push({ toolResult: {
813
- toolUseId: normalizeToolCallId(m.toolCallId),
814
- content: m.content.map((c) => c.type === "image" ? { image: createImageBlock(c.mimeType, c.data) } : { text: c.text.toWellFormed() }),
815
- status: m.isError ? "error" : "success"
816
- } });
817
- let j = i + 1;
818
- while (j < transformedMessages.length && transformedMessages[j].role === "toolResult") {
819
- const nextMsg = transformedMessages[j];
820
- toolResults.push({ toolResult: {
821
- toolUseId: normalizeToolCallId(nextMsg.toolCallId),
822
- content: nextMsg.content.map((c) => c.type === "image" ? { image: createImageBlock(c.mimeType, c.data) } : { text: c.text.toWellFormed() }),
823
- status: nextMsg.isError ? "error" : "success"
824
- } });
825
- j++;
826
- }
827
- i = j - 1;
828
- result.push({
829
- role: "user",
830
- content: toolResults
831
- });
832
- break;
833
- }
834
- default: throw new ValidationError("Unknown message role");
835
- }
836
- }
837
- if (result.length > 0) {
838
- const lastMessage = result[result.length - 1];
839
- if (lastMessage.role === "user" && lastMessage.content) {
840
- const cachePoint = takeCachePoint(promptCachePolicy);
841
- if (cachePoint) lastMessage.content.push(cachePoint);
842
- }
843
- }
844
- return result;
845
- }
846
- function messagesHaveToolBlocks(messages) {
847
- for (const message of messages) for (const block of message.content) if ("toolUse" in block || "toolResult" in block) return true;
848
- return false;
849
- }
850
- function convertToolSpec(tool) {
851
- return { toolSpec: {
852
- name: tool.name,
853
- description: tool.description || "",
854
- inputSchema: { json: toolWireSchema(tool) }
855
- } };
856
- }
857
- function planToolConfig(tools, toolChoice, messages) {
858
- const activeTools = tools ?? [];
859
- const hasTools = activeTools.length > 0;
860
- const historyHasToolBlocks = messagesHaveToolBlocks(messages);
861
- if (toolChoice === "none") {
862
- if (!historyHasToolBlocks) return {
863
- toolConfig: void 0,
864
- sentinelInjected: false
865
- };
866
- if (!hasTools) return {
867
- toolConfig: {
868
- tools: [NO_TOOLS_SENTINEL],
869
- toolChoice: { auto: {} }
870
- },
871
- sentinelInjected: true
872
- };
873
- return {
874
- toolConfig: { tools: activeTools.map(convertToolSpec) },
875
- sentinelInjected: false
876
- };
877
- }
878
- if (!hasTools) return {
879
- toolConfig: void 0,
880
- sentinelInjected: false
881
- };
882
- const bedrockTools = activeTools.map(convertToolSpec);
883
- let bedrockToolChoice;
884
- switch (toolChoice) {
885
- case "auto":
886
- bedrockToolChoice = { auto: {} };
887
- break;
888
- case "any":
889
- bedrockToolChoice = { any: {} };
890
- break;
891
- default: if (toolChoice?.type === "tool") bedrockToolChoice = { tool: { name: toolChoice.name } };
892
- }
893
- return {
894
- toolConfig: {
895
- tools: bedrockTools,
896
- toolChoice: bedrockToolChoice
897
- },
898
- sentinelInjected: false
899
- };
900
- }
901
- function mapStopReason(reason) {
902
- switch (reason) {
903
- case "end_turn":
904
- case "stop_sequence": return "stop";
905
- case "max_tokens":
906
- case "model_context_window_exceeded": return "length";
907
- case "tool_use": return "toolUse";
908
- default: return "error";
909
- }
910
- }
911
- /**
912
- * Build the Converse `guardrailConfig` block when a guardrail identifier is set.
913
- * The version defaults to `"DRAFT"` (Bedrock's editable working draft) and the
914
- * trace is passed through untouched — leaving it undefined keeps Bedrock's own
915
- * default rather than forcing a value.
916
- */
917
- function buildGuardrailConfig(options) {
918
- if (!options.guardrailIdentifier) return void 0;
919
- return {
920
- guardrailIdentifier: options.guardrailIdentifier,
921
- guardrailVersion: options.guardrailVersion ?? "DRAFT",
922
- ...options.guardrailTrace === void 0 ? {} : { trace: options.guardrailTrace }
923
- };
924
- }
925
- function applyBedrockThinkingBinding(fields, behavior) {
926
- const result = { ...fields };
927
- const thinking = isRecord(result.thinking) ? { ...result.thinking } : { type: "adaptive" };
928
- thinking.block_binding = { prefix_mismatch_behavior: behavior };
929
- result.thinking = thinking;
930
- const betas = Array.isArray(result.anthropic_beta) ? result.anthropic_beta.filter((beta) => typeof beta === "string") : [];
931
- if (!betas.includes("thinking-binding-controls-2026-08-01")) betas.push(THINKING_BINDING_CONTROLS_BETA);
932
- result.anthropic_beta = betas;
933
- return result;
934
- }
935
- function buildAdditionalModelRequestFields(model, options) {
936
- const reasoning = options.reasoning;
937
- if (!reasoning || !model.reasoning) return void 0;
938
- const mode = model.thinking?.mode;
939
- if (mode === "anthropic-adaptive") {
940
- const effort = mapEffortToAnthropicAdaptiveEffort(model, reasoning);
941
- const adaptive = { type: "adaptive" };
942
- if (model.thinking?.supportsDisplay) adaptive.display = options.thinkingDisplay ?? "summarized";
943
- return {
944
- thinking: adaptive,
945
- output_config: { effort }
946
- };
947
- }
948
- if (mode === "effort") {
949
- const level = requireSupportedEffort(model, reasoning);
950
- return { reasoning: { effort: model.thinking?.effortMap?.[level] ?? level } };
951
- }
952
- const level = requireSupportedEffort(model, reasoning);
953
- const result = { thinking: {
954
- type: "enabled",
955
- budget_tokens: options.thinkingBudgets?.[level] ?? {
956
- minimal: 1024,
957
- low: 2048,
958
- medium: 8192,
959
- high: 16384,
960
- xhigh: 32768,
961
- max: 32768
962
- }[level],
963
- display: options.thinkingDisplay ?? "summarized"
964
- } };
965
- if (options.interleavedThinking) result.anthropic_beta = ["interleaved-thinking-2025-05-14"];
966
- return result;
967
- }
968
- /**
969
- * Bedrock's wire format expects the image as `{ source: { bytes: <base64-string> }, format }`.
970
- * The caller already passes base64-encoded data, so no decode/re-encode round-trip is needed.
971
- */
972
- function createImageBlock(mimeType, data) {
973
- let format;
974
- switch (mimeType) {
975
- case "image/jpeg":
976
- case "image/jpg":
977
- format = "jpeg";
978
- break;
979
- case "image/png":
980
- format = "png";
981
- break;
982
- case "image/gif":
983
- format = "gif";
984
- break;
985
- case "image/webp":
986
- format = "webp";
987
- break;
988
- default: throw new ValidationError(`Unknown image type: ${mimeType}`);
989
- }
990
- return {
991
- source: { bytes: data },
992
- format
993
- };
994
- }
995
- //#endregion
996
- export { streamBedrock };