@vib-rato/ai 0.16.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 (525) hide show
  1. package/CHANGELOG.md +3354 -0
  2. package/README.md +1194 -0
  3. package/dist/types/adapter-internals/provider-safety-stop.d.ts +45 -0
  4. package/dist/types/api-registry.d.ts +30 -0
  5. package/dist/types/auth-broker/client.d.ts +80 -0
  6. package/dist/types/auth-broker/index.d.ts +5 -0
  7. package/dist/types/auth-broker/redact.d.ts +7 -0
  8. package/dist/types/auth-broker/refresher.d.ts +25 -0
  9. package/dist/types/auth-broker/remote-store.d.ts +153 -0
  10. package/dist/types/auth-broker/server.d.ts +32 -0
  11. package/dist/types/auth-broker/types.d.ts +132 -0
  12. package/dist/types/auth-broker/wire-schemas.d.ts +555 -0
  13. package/dist/types/auth-gateway/http.d.ts +40 -0
  14. package/dist/types/auth-gateway/index.d.ts +3 -0
  15. package/dist/types/auth-gateway/server.d.ts +70 -0
  16. package/dist/types/auth-gateway/types.d.ts +129 -0
  17. package/dist/types/auth-storage.d.ts +1074 -0
  18. package/dist/types/cli.d.ts +2 -0
  19. package/dist/types/codex-tools.d.ts +4 -0
  20. package/dist/types/context-cap-policy.d.ts +68 -0
  21. package/dist/types/core.d.ts +35 -0
  22. package/dist/types/index.d.ts +55 -0
  23. package/dist/types/model-cache.d.ts +24 -0
  24. package/dist/types/model-manager.d.ts +77 -0
  25. package/dist/types/model-pricing.d.ts +3 -0
  26. package/dist/types/model-retirements.d.ts +6 -0
  27. package/dist/types/model-thinking.d.ts +100 -0
  28. package/dist/types/models.d.ts +21 -0
  29. package/dist/types/openai-completions-compat.d.ts +34 -0
  30. package/dist/types/provider-details.d.ts +24 -0
  31. package/dist/types/provider-models/bundled-references.d.ts +4 -0
  32. package/dist/types/provider-models/descriptors.d.ts +48 -0
  33. package/dist/types/provider-models/google.d.ts +20 -0
  34. package/dist/types/provider-models/index.d.ts +5 -0
  35. package/dist/types/provider-models/ollama.d.ts +7 -0
  36. package/dist/types/provider-models/openai-compat.d.ts +293 -0
  37. package/dist/types/provider-models/special.d.ts +29 -0
  38. package/dist/types/providers/amazon-bedrock.d.ts +60 -0
  39. package/dist/types/providers/anthropic-messages-server-schema.d.ts +450 -0
  40. package/dist/types/providers/anthropic-messages-server.d.ts +17 -0
  41. package/dist/types/providers/anthropic.d.ts +280 -0
  42. package/dist/types/providers/aws-credential-config.d.ts +19 -0
  43. package/dist/types/providers/aws-credentials.d.ts +43 -0
  44. package/dist/types/providers/aws-eventstream.d.ts +38 -0
  45. package/dist/types/providers/aws-sigv4.d.ts +55 -0
  46. package/dist/types/providers/azure-openai-responses.d.ts +22 -0
  47. package/dist/types/providers/composer-discipline.d.ts +32 -0
  48. package/dist/types/providers/cursor/client-version.d.ts +10 -0
  49. package/dist/types/providers/cursor/exec-modern.d.ts +98 -0
  50. package/dist/types/providers/cursor/gen/agent_pb.d.ts +16769 -0
  51. package/dist/types/providers/cursor-pi-args.d.ts +119 -0
  52. package/dist/types/providers/cursor.d.ts +72 -0
  53. package/dist/types/providers/dashscope-token-plan-headers.d.ts +57 -0
  54. package/dist/types/providers/error-message.d.ts +27 -0
  55. package/dist/types/providers/github-copilot-headers.d.ts +40 -0
  56. package/dist/types/providers/gitlab-duo.d.ts +27 -0
  57. package/dist/types/providers/google-auth.d.ts +26 -0
  58. package/dist/types/providers/google-gemini-cli.d.ts +75 -0
  59. package/dist/types/providers/google-gemini-headers.d.ts +43 -0
  60. package/dist/types/providers/google-shared.d.ts +183 -0
  61. package/dist/types/providers/google-types.d.ts +138 -0
  62. package/dist/types/providers/google-vertex.d.ts +11 -0
  63. package/dist/types/providers/google.d.ts +4 -0
  64. package/dist/types/providers/grammar.d.ts +1 -0
  65. package/dist/types/providers/kimi.d.ts +27 -0
  66. package/dist/types/providers/kiro-api-key.d.ts +50 -0
  67. package/dist/types/providers/kiro-codewhisperer.d.ts +11 -0
  68. package/dist/types/providers/mock.d.ts +189 -0
  69. package/dist/types/providers/ollama.d.ts +41 -0
  70. package/dist/types/providers/openai-anthropic-shim.d.ts +31 -0
  71. package/dist/types/providers/openai-bounded-rate-limits.d.ts +3 -0
  72. package/dist/types/providers/openai-chat-server-schema.d.ts +1733 -0
  73. package/dist/types/providers/openai-chat-server.d.ts +16 -0
  74. package/dist/types/providers/openai-codex/constants.d.ts +26 -0
  75. package/dist/types/providers/openai-codex/request-transformer.d.ts +50 -0
  76. package/dist/types/providers/openai-codex/response-handler.d.ts +18 -0
  77. package/dist/types/providers/openai-codex-responses.d.ts +71 -0
  78. package/dist/types/providers/openai-completions-compat.d.ts +6 -0
  79. package/dist/types/providers/openai-completions.d.ts +35 -0
  80. package/dist/types/providers/openai-opencodex-responses.d.ts +10 -0
  81. package/dist/types/providers/openai-request-transform.d.ts +4 -0
  82. package/dist/types/providers/openai-responses-server-schema.d.ts +392 -0
  83. package/dist/types/providers/openai-responses-server.d.ts +17 -0
  84. package/dist/types/providers/openai-responses-shared.d.ts +106 -0
  85. package/dist/types/providers/openai-responses.d.ts +37 -0
  86. package/dist/types/providers/pi-native-client.d.ts +29 -0
  87. package/dist/types/providers/pi-native-server.d.ts +60 -0
  88. package/dist/types/providers/register-builtins.d.ts +59 -0
  89. package/dist/types/providers/synthetic.d.ts +26 -0
  90. package/dist/types/providers/transform-messages.d.ts +33 -0
  91. package/dist/types/providers/vision-guard.d.ts +8 -0
  92. package/dist/types/rate-limit-utils.d.ts +19 -0
  93. package/dist/types/stream.d.ts +45 -0
  94. package/dist/types/types.d.ts +1073 -0
  95. package/dist/types/usage/claude.d.ts +3 -0
  96. package/dist/types/usage/gemini.d.ts +2 -0
  97. package/dist/types/usage/github-copilot.d.ts +7 -0
  98. package/dist/types/usage/google-antigravity.d.ts +2 -0
  99. package/dist/types/usage/grok-cli.d.ts +17 -0
  100. package/dist/types/usage/kimi.d.ts +4 -0
  101. package/dist/types/usage/minimax-code.d.ts +2 -0
  102. package/dist/types/usage/openai-codex.d.ts +3 -0
  103. package/dist/types/usage/shared.d.ts +1 -0
  104. package/dist/types/usage/zai.d.ts +2 -0
  105. package/dist/types/usage.d.ts +264 -0
  106. package/dist/types/utils/abort.d.ts +19 -0
  107. package/dist/types/utils/anthropic-auth.d.ts +39 -0
  108. package/dist/types/utils/block-symbols.d.ts +6 -0
  109. package/dist/types/utils/discovery/antigravity.d.ts +67 -0
  110. package/dist/types/utils/discovery/codex.d.ts +38 -0
  111. package/dist/types/utils/discovery/cursor.d.ts +49 -0
  112. package/dist/types/utils/discovery/gemini.d.ts +25 -0
  113. package/dist/types/utils/discovery/index.d.ts +4 -0
  114. package/dist/types/utils/discovery/openai-compatible.d.ts +81 -0
  115. package/dist/types/utils/event-stream.d.ts +41 -0
  116. package/dist/types/utils/fallback-transport.d.ts +110 -0
  117. package/dist/types/utils/fireworks-model-id.d.ts +10 -0
  118. package/dist/types/utils/foundry.d.ts +11 -0
  119. package/dist/types/utils/h2-fetch.d.ts +22 -0
  120. package/dist/types/utils/http-inspector.d.ts +59 -0
  121. package/dist/types/utils/idle-iterator.d.ts +122 -0
  122. package/dist/types/utils/json-parse.d.ts +98 -0
  123. package/dist/types/utils/oauth/alibaba-token-plan.d.ts +19 -0
  124. package/dist/types/utils/oauth/anthropic.d.ts +41 -0
  125. package/dist/types/utils/oauth/api-key-login.d.ts +38 -0
  126. package/dist/types/utils/oauth/api-key-validation.d.ts +39 -0
  127. package/dist/types/utils/oauth/bizrouter.d.ts +1 -0
  128. package/dist/types/utils/oauth/callback-server.d.ts +80 -0
  129. package/dist/types/utils/oauth/cerebras.d.ts +1 -0
  130. package/dist/types/utils/oauth/cloudflare-ai-gateway.d.ts +18 -0
  131. package/dist/types/utils/oauth/commandcode.d.ts +1 -0
  132. package/dist/types/utils/oauth/cursor.d.ts +15 -0
  133. package/dist/types/utils/oauth/deepinfra.d.ts +1 -0
  134. package/dist/types/utils/oauth/deepseek.d.ts +10 -0
  135. package/dist/types/utils/oauth/firepass.d.ts +1 -0
  136. package/dist/types/utils/oauth/fireworks.d.ts +1 -0
  137. package/dist/types/utils/oauth/fugu.d.ts +1 -0
  138. package/dist/types/utils/oauth/github-copilot.d.ts +38 -0
  139. package/dist/types/utils/oauth/gitlab-duo.d.ts +3 -0
  140. package/dist/types/utils/oauth/glm-zcode.d.ts +71 -0
  141. package/dist/types/utils/oauth/google-antigravity.d.ts +11 -0
  142. package/dist/types/utils/oauth/google-gemini-cli.d.ts +10 -0
  143. package/dist/types/utils/oauth/google-oauth-shared.d.ts +28 -0
  144. package/dist/types/utils/oauth/huggingface.d.ts +19 -0
  145. package/dist/types/utils/oauth/index.d.ts +39 -0
  146. package/dist/types/utils/oauth/kagi.d.ts +17 -0
  147. package/dist/types/utils/oauth/kilo.d.ts +5 -0
  148. package/dist/types/utils/oauth/kimi.d.ts +17 -0
  149. package/dist/types/utils/oauth/kiro.d.ts +71 -0
  150. package/dist/types/utils/oauth/litellm.d.ts +18 -0
  151. package/dist/types/utils/oauth/lm-studio.d.ts +17 -0
  152. package/dist/types/utils/oauth/mara.d.ts +1 -0
  153. package/dist/types/utils/oauth/minimax-code.d.ts +28 -0
  154. package/dist/types/utils/oauth/moonshot.d.ts +1 -0
  155. package/dist/types/utils/oauth/nanogpt.d.ts +1 -0
  156. package/dist/types/utils/oauth/nvidia.d.ts +18 -0
  157. package/dist/types/utils/oauth/ollama-cloud.d.ts +2 -0
  158. package/dist/types/utils/oauth/ollama.d.ts +18 -0
  159. package/dist/types/utils/oauth/openai-codex.d.ts +21 -0
  160. package/dist/types/utils/oauth/opencode.d.ts +18 -0
  161. package/dist/types/utils/oauth/opengateway.d.ts +1 -0
  162. package/dist/types/utils/oauth/openrouter.d.ts +1 -0
  163. package/dist/types/utils/oauth/parallel.d.ts +17 -0
  164. package/dist/types/utils/oauth/perplexity.d.ts +4 -0
  165. package/dist/types/utils/oauth/pkce.d.ts +8 -0
  166. package/dist/types/utils/oauth/qianfan.d.ts +17 -0
  167. package/dist/types/utils/oauth/qwen-portal.d.ts +19 -0
  168. package/dist/types/utils/oauth/sglang.d.ts +16 -0
  169. package/dist/types/utils/oauth/synthetic.d.ts +1 -0
  170. package/dist/types/utils/oauth/tavily.d.ts +17 -0
  171. package/dist/types/utils/oauth/together.d.ts +1 -0
  172. package/dist/types/utils/oauth/types.d.ts +56 -0
  173. package/dist/types/utils/oauth/venice.d.ts +18 -0
  174. package/dist/types/utils/oauth/vercel-ai-gateway.d.ts +18 -0
  175. package/dist/types/utils/oauth/vllm.d.ts +16 -0
  176. package/dist/types/utils/oauth/xai.d.ts +30 -0
  177. package/dist/types/utils/oauth/xiaomi.d.ts +25 -0
  178. package/dist/types/utils/oauth/zai.d.ts +18 -0
  179. package/dist/types/utils/oauth/zenmux.d.ts +1 -0
  180. package/dist/types/utils/overflow.d.ts +14 -0
  181. package/dist/types/utils/parse-bind.d.ts +26 -0
  182. package/dist/types/utils/provider-response.d.ts +6 -0
  183. package/dist/types/utils/provider-safety-stop.d.ts +8 -0
  184. package/dist/types/utils/proxy.d.ts +7 -0
  185. package/dist/types/utils/retry-after.d.ts +3 -0
  186. package/dist/types/utils/retry-budget.d.ts +1 -0
  187. package/dist/types/utils/retry.d.ts +29 -0
  188. package/dist/types/utils/schema/adapt.d.ts +24 -0
  189. package/dist/types/utils/schema/compatibility.d.ts +30 -0
  190. package/dist/types/utils/schema/dereference.d.ts +11 -0
  191. package/dist/types/utils/schema/draft.d.ts +10 -0
  192. package/dist/types/utils/schema/equality.d.ts +4 -0
  193. package/dist/types/utils/schema/fields.d.ts +49 -0
  194. package/dist/types/utils/schema/index.d.ts +14 -0
  195. package/dist/types/utils/schema/json-schema-validator.d.ts +12 -0
  196. package/dist/types/utils/schema/meta-validator.d.ts +2 -0
  197. package/dist/types/utils/schema/normalize.d.ts +93 -0
  198. package/dist/types/utils/schema/root-combinator.d.ts +12 -0
  199. package/dist/types/utils/schema/spill.d.ts +8 -0
  200. package/dist/types/utils/schema/stamps.d.ts +25 -0
  201. package/dist/types/utils/schema/types.d.ts +4 -0
  202. package/dist/types/utils/schema/wire.d.ts +54 -0
  203. package/dist/types/utils/schema/zod-decontaminate.d.ts +31 -0
  204. package/dist/types/utils/sse-debug.d.ts +10 -0
  205. package/dist/types/utils/tool-call-healing.d.ts +80 -0
  206. package/dist/types/utils/tool-choice-capability.d.ts +57 -0
  207. package/dist/types/utils/tool-choice.d.ts +50 -0
  208. package/dist/types/utils/validation.d.ts +17 -0
  209. package/dist/types/utils.d.ts +117 -0
  210. package/package.json +152 -0
  211. package/src/adapter-internals/provider-safety-stop.d.ts +45 -0
  212. package/src/adapter-internals/provider-safety-stop.ts +156 -0
  213. package/src/api-registry.d.ts +30 -0
  214. package/src/api-registry.ts +96 -0
  215. package/src/auth-broker/client.ts +444 -0
  216. package/src/auth-broker/index.ts +5 -0
  217. package/src/auth-broker/redact.ts +39 -0
  218. package/src/auth-broker/refresher.ts +130 -0
  219. package/src/auth-broker/remote-store.ts +1576 -0
  220. package/src/auth-broker/server.ts +764 -0
  221. package/src/auth-broker/types.ts +164 -0
  222. package/src/auth-broker/wire-schemas.ts +261 -0
  223. package/src/auth-gateway/http.ts +198 -0
  224. package/src/auth-gateway/index.ts +3 -0
  225. package/src/auth-gateway/server.ts +1315 -0
  226. package/src/auth-gateway/types.ts +160 -0
  227. package/src/auth-storage.ts +7312 -0
  228. package/src/cli.ts +269 -0
  229. package/src/codex-tools.d.ts +4 -0
  230. package/src/codex-tools.ts +24 -0
  231. package/src/context-cap-policy.d.ts +68 -0
  232. package/src/context-cap-policy.ts +123 -0
  233. package/src/core.ts +44 -0
  234. package/src/index.ts +61 -0
  235. package/src/model-cache.ts +236 -0
  236. package/src/model-manager.ts +744 -0
  237. package/src/model-pricing.d.ts +3 -0
  238. package/src/model-pricing.ts +68 -0
  239. package/src/model-retirements.d.ts +6 -0
  240. package/src/model-retirements.ts +19 -0
  241. package/src/model-thinking.d.ts +100 -0
  242. package/src/model-thinking.ts +1054 -0
  243. package/src/models.d.ts +21 -0
  244. package/src/models.json +94672 -0
  245. package/src/models.json.d.ts +9 -0
  246. package/src/models.ts +126 -0
  247. package/src/openai-completions-compat.d.ts +34 -0
  248. package/src/openai-completions-compat.ts +383 -0
  249. package/src/prompts/composer-bash-policy-recovery.md +1 -0
  250. package/src/prompts/cursor-composer-bash-policy-recovery.md +1 -0
  251. package/src/prompts/cursor-composer-edit-discipline.md +7 -0
  252. package/src/prompts/turn-aborted-guidance.md +4 -0
  253. package/src/provider-details.ts +90 -0
  254. package/src/provider-models/bundled-references.ts +38 -0
  255. package/src/provider-models/descriptors.ts +392 -0
  256. package/src/provider-models/google.ts +92 -0
  257. package/src/provider-models/index.ts +5 -0
  258. package/src/provider-models/ollama.ts +159 -0
  259. package/src/provider-models/openai-compat.ts +2920 -0
  260. package/src/provider-models/special.ts +185 -0
  261. package/src/providers/amazon-bedrock.d.ts +60 -0
  262. package/src/providers/amazon-bedrock.ts +939 -0
  263. package/src/providers/anthropic-messages-server-schema.ts +229 -0
  264. package/src/providers/anthropic-messages-server.ts +839 -0
  265. package/src/providers/anthropic.d.ts +280 -0
  266. package/src/providers/anthropic.ts +4421 -0
  267. package/src/providers/aws-credential-config.d.ts +19 -0
  268. package/src/providers/aws-credential-config.ts +179 -0
  269. package/src/providers/aws-credentials.d.ts +43 -0
  270. package/src/providers/aws-credentials.ts +457 -0
  271. package/src/providers/aws-eventstream.d.ts +38 -0
  272. package/src/providers/aws-eventstream.ts +185 -0
  273. package/src/providers/aws-sigv4.d.ts +55 -0
  274. package/src/providers/aws-sigv4.ts +218 -0
  275. package/src/providers/azure-openai-responses.d.ts +22 -0
  276. package/src/providers/azure-openai-responses.ts +447 -0
  277. package/src/providers/composer-discipline.d.ts +32 -0
  278. package/src/providers/composer-discipline.ts +95 -0
  279. package/src/providers/cursor/client-version.d.ts +10 -0
  280. package/src/providers/cursor/client-version.ts +10 -0
  281. package/src/providers/cursor/exec-modern.d.ts +98 -0
  282. package/src/providers/cursor/exec-modern.ts +497 -0
  283. package/src/providers/cursor/gen/agent_pb.d.ts +16769 -0
  284. package/src/providers/cursor/gen/agent_pb.ts +19780 -0
  285. package/src/providers/cursor/proto/agent.proto +4533 -0
  286. package/src/providers/cursor/proto/buf.gen.yaml +6 -0
  287. package/src/providers/cursor/proto/buf.yaml +17 -0
  288. package/src/providers/cursor-pi-args.d.ts +119 -0
  289. package/src/providers/cursor-pi-args.ts +187 -0
  290. package/src/providers/cursor.d.ts +72 -0
  291. package/src/providers/cursor.ts +3396 -0
  292. package/src/providers/dashscope-token-plan-headers.d.ts +57 -0
  293. package/src/providers/dashscope-token-plan-headers.ts +84 -0
  294. package/src/providers/error-message.d.ts +27 -0
  295. package/src/providers/error-message.ts +21 -0
  296. package/src/providers/github-copilot-headers.d.ts +40 -0
  297. package/src/providers/github-copilot-headers.ts +140 -0
  298. package/src/providers/gitlab-duo.d.ts +27 -0
  299. package/src/providers/gitlab-duo.ts +393 -0
  300. package/src/providers/google-auth.d.ts +26 -0
  301. package/src/providers/google-auth.ts +262 -0
  302. package/src/providers/google-gemini-cli.d.ts +75 -0
  303. package/src/providers/google-gemini-cli.ts +969 -0
  304. package/src/providers/google-gemini-headers.d.ts +43 -0
  305. package/src/providers/google-gemini-headers.ts +100 -0
  306. package/src/providers/google-shared.d.ts +183 -0
  307. package/src/providers/google-shared.ts +1105 -0
  308. package/src/providers/google-types.d.ts +138 -0
  309. package/src/providers/google-types.ts +167 -0
  310. package/src/providers/google-vertex.d.ts +11 -0
  311. package/src/providers/google-vertex.ts +124 -0
  312. package/src/providers/google.d.ts +4 -0
  313. package/src/providers/google.ts +41 -0
  314. package/src/providers/grammar.d.ts +1 -0
  315. package/src/providers/grammar.ts +70 -0
  316. package/src/providers/kimi.d.ts +27 -0
  317. package/src/providers/kimi.ts +52 -0
  318. package/src/providers/kiro-api-key.d.ts +50 -0
  319. package/src/providers/kiro-api-key.ts +786 -0
  320. package/src/providers/kiro-codewhisperer.d.ts +11 -0
  321. package/src/providers/kiro-codewhisperer.ts +600 -0
  322. package/src/providers/mock.ts +526 -0
  323. package/src/providers/ollama.d.ts +41 -0
  324. package/src/providers/ollama.ts +645 -0
  325. package/src/providers/openai-anthropic-shim.d.ts +31 -0
  326. package/src/providers/openai-anthropic-shim.ts +156 -0
  327. package/src/providers/openai-bounded-rate-limits.d.ts +3 -0
  328. package/src/providers/openai-bounded-rate-limits.ts +57 -0
  329. package/src/providers/openai-chat-server-schema.ts +254 -0
  330. package/src/providers/openai-chat-server.ts +724 -0
  331. package/src/providers/openai-codex/constants.d.ts +26 -0
  332. package/src/providers/openai-codex/constants.ts +43 -0
  333. package/src/providers/openai-codex/request-transformer.d.ts +50 -0
  334. package/src/providers/openai-codex/request-transformer.ts +219 -0
  335. package/src/providers/openai-codex/response-handler.d.ts +18 -0
  336. package/src/providers/openai-codex/response-handler.ts +111 -0
  337. package/src/providers/openai-codex-responses.d.ts +71 -0
  338. package/src/providers/openai-codex-responses.ts +3288 -0
  339. package/src/providers/openai-completions-compat.d.ts +6 -0
  340. package/src/providers/openai-completions-compat.ts +6 -0
  341. package/src/providers/openai-completions.d.ts +35 -0
  342. package/src/providers/openai-completions.ts +2294 -0
  343. package/src/providers/openai-opencodex-responses.ts +174 -0
  344. package/src/providers/openai-request-transform.d.ts +4 -0
  345. package/src/providers/openai-request-transform.ts +136 -0
  346. package/src/providers/openai-responses-server-schema.ts +290 -0
  347. package/src/providers/openai-responses-server.ts +1268 -0
  348. package/src/providers/openai-responses-shared.d.ts +106 -0
  349. package/src/providers/openai-responses-shared.ts +1253 -0
  350. package/src/providers/openai-responses.d.ts +37 -0
  351. package/src/providers/openai-responses.ts +989 -0
  352. package/src/providers/pi-native-client.d.ts +29 -0
  353. package/src/providers/pi-native-client.ts +243 -0
  354. package/src/providers/pi-native-server.ts +488 -0
  355. package/src/providers/register-builtins.d.ts +59 -0
  356. package/src/providers/register-builtins.ts +544 -0
  357. package/src/providers/synthetic.d.ts +26 -0
  358. package/src/providers/synthetic.ts +50 -0
  359. package/src/providers/transform-messages.d.ts +33 -0
  360. package/src/providers/transform-messages.ts +408 -0
  361. package/src/providers/vision-guard.d.ts +8 -0
  362. package/src/providers/vision-guard.ts +31 -0
  363. package/src/rate-limit-utils.d.ts +19 -0
  364. package/src/rate-limit-utils.ts +102 -0
  365. package/src/stream.d.ts +45 -0
  366. package/src/stream.ts +1306 -0
  367. package/src/types.d.ts +1073 -0
  368. package/src/types.ts +1305 -0
  369. package/src/usage/claude.ts +449 -0
  370. package/src/usage/gemini.ts +250 -0
  371. package/src/usage/github-copilot.ts +421 -0
  372. package/src/usage/google-antigravity.ts +201 -0
  373. package/src/usage/grok-cli.ts +259 -0
  374. package/src/usage/kimi.ts +285 -0
  375. package/src/usage/minimax-code.ts +31 -0
  376. package/src/usage/openai-codex.ts +503 -0
  377. package/src/usage/shared.ts +10 -0
  378. package/src/usage/zai.ts +247 -0
  379. package/src/usage.ts +190 -0
  380. package/src/utils/abort.d.ts +19 -0
  381. package/src/utils/abort.ts +51 -0
  382. package/src/utils/anthropic-auth.ts +95 -0
  383. package/src/utils/block-symbols.d.ts +6 -0
  384. package/src/utils/block-symbols.ts +11 -0
  385. package/src/utils/discovery/antigravity.ts +275 -0
  386. package/src/utils/discovery/codex.ts +362 -0
  387. package/src/utils/discovery/cursor.ts +388 -0
  388. package/src/utils/discovery/gemini.ts +248 -0
  389. package/src/utils/discovery/index.ts +4 -0
  390. package/src/utils/discovery/openai-compatible.ts +379 -0
  391. package/src/utils/event-stream.d.ts +41 -0
  392. package/src/utils/event-stream.ts +269 -0
  393. package/src/utils/fallback-transport.d.ts +110 -0
  394. package/src/utils/fallback-transport.ts +411 -0
  395. package/src/utils/fireworks-model-id.d.ts +10 -0
  396. package/src/utils/fireworks-model-id.ts +30 -0
  397. package/src/utils/foundry.d.ts +11 -0
  398. package/src/utils/foundry.ts +18 -0
  399. package/src/utils/h2-fetch.ts +60 -0
  400. package/src/utils/http-inspector.d.ts +59 -0
  401. package/src/utils/http-inspector.ts +380 -0
  402. package/src/utils/idle-iterator.d.ts +122 -0
  403. package/src/utils/idle-iterator.ts +410 -0
  404. package/src/utils/json-parse.d.ts +98 -0
  405. package/src/utils/json-parse.ts +607 -0
  406. package/src/utils/oauth/alibaba-token-plan.ts +60 -0
  407. package/src/utils/oauth/anthropic.ts +233 -0
  408. package/src/utils/oauth/api-key-login.ts +98 -0
  409. package/src/utils/oauth/api-key-validation.ts +344 -0
  410. package/src/utils/oauth/bizrouter.ts +15 -0
  411. package/src/utils/oauth/callback-server.d.ts +80 -0
  412. package/src/utils/oauth/callback-server.ts +359 -0
  413. package/src/utils/oauth/cerebras.ts +16 -0
  414. package/src/utils/oauth/cloudflare-ai-gateway.ts +48 -0
  415. package/src/utils/oauth/commandcode.ts +17 -0
  416. package/src/utils/oauth/cursor.ts +157 -0
  417. package/src/utils/oauth/deepinfra.ts +15 -0
  418. package/src/utils/oauth/deepseek.ts +53 -0
  419. package/src/utils/oauth/firepass.ts +24 -0
  420. package/src/utils/oauth/fireworks.ts +15 -0
  421. package/src/utils/oauth/fugu.ts +15 -0
  422. package/src/utils/oauth/github-copilot.d.ts +38 -0
  423. package/src/utils/oauth/github-copilot.ts +362 -0
  424. package/src/utils/oauth/gitlab-duo.ts +123 -0
  425. package/src/utils/oauth/glm-zcode.d.ts +71 -0
  426. package/src/utils/oauth/glm-zcode.ts +433 -0
  427. package/src/utils/oauth/google-antigravity.ts +200 -0
  428. package/src/utils/oauth/google-gemini-cli.ts +256 -0
  429. package/src/utils/oauth/google-oauth-shared.ts +110 -0
  430. package/src/utils/oauth/huggingface.ts +62 -0
  431. package/src/utils/oauth/index.ts +558 -0
  432. package/src/utils/oauth/kagi.ts +47 -0
  433. package/src/utils/oauth/kilo.ts +87 -0
  434. package/src/utils/oauth/kimi.d.ts +17 -0
  435. package/src/utils/oauth/kimi.ts +275 -0
  436. package/src/utils/oauth/kiro.ts +448 -0
  437. package/src/utils/oauth/litellm.ts +47 -0
  438. package/src/utils/oauth/lm-studio.ts +38 -0
  439. package/src/utils/oauth/mara.ts +16 -0
  440. package/src/utils/oauth/minimax-code.ts +78 -0
  441. package/src/utils/oauth/moonshot.ts +16 -0
  442. package/src/utils/oauth/nanogpt.ts +15 -0
  443. package/src/utils/oauth/nvidia.ts +70 -0
  444. package/src/utils/oauth/oauth.html +199 -0
  445. package/src/utils/oauth/ollama-cloud.ts +28 -0
  446. package/src/utils/oauth/ollama.ts +47 -0
  447. package/src/utils/oauth/openai-codex.ts +299 -0
  448. package/src/utils/oauth/opencode.ts +49 -0
  449. package/src/utils/oauth/opengateway.ts +15 -0
  450. package/src/utils/oauth/openrouter.ts +16 -0
  451. package/src/utils/oauth/parallel.ts +46 -0
  452. package/src/utils/oauth/perplexity.ts +225 -0
  453. package/src/utils/oauth/pkce.ts +18 -0
  454. package/src/utils/oauth/qianfan.ts +58 -0
  455. package/src/utils/oauth/qwen-portal.ts +60 -0
  456. package/src/utils/oauth/sglang.ts +42 -0
  457. package/src/utils/oauth/synthetic.ts +15 -0
  458. package/src/utils/oauth/tavily.ts +46 -0
  459. package/src/utils/oauth/together.ts +16 -0
  460. package/src/utils/oauth/types.d.ts +56 -0
  461. package/src/utils/oauth/types.ts +122 -0
  462. package/src/utils/oauth/venice.ts +59 -0
  463. package/src/utils/oauth/vercel-ai-gateway.ts +47 -0
  464. package/src/utils/oauth/vllm.ts +42 -0
  465. package/src/utils/oauth/xai.ts +246 -0
  466. package/src/utils/oauth/xiaomi.ts +199 -0
  467. package/src/utils/oauth/zai.ts +60 -0
  468. package/src/utils/oauth/zenmux.ts +15 -0
  469. package/src/utils/overflow.ts +275 -0
  470. package/src/utils/parse-bind.ts +81 -0
  471. package/src/utils/provider-response.d.ts +6 -0
  472. package/src/utils/provider-response.ts +30 -0
  473. package/src/utils/provider-safety-stop.ts +8 -0
  474. package/src/utils/proxy.d.ts +7 -0
  475. package/src/utils/proxy.ts +652 -0
  476. package/src/utils/retry-after.d.ts +3 -0
  477. package/src/utils/retry-after.ts +110 -0
  478. package/src/utils/retry-budget.d.ts +1 -0
  479. package/src/utils/retry-budget.ts +4 -0
  480. package/src/utils/retry.d.ts +29 -0
  481. package/src/utils/retry.ts +67 -0
  482. package/src/utils/schema/CONSTRAINTS.md +164 -0
  483. package/src/utils/schema/adapt.d.ts +24 -0
  484. package/src/utils/schema/adapt.ts +36 -0
  485. package/src/utils/schema/compatibility.d.ts +30 -0
  486. package/src/utils/schema/compatibility.ts +435 -0
  487. package/src/utils/schema/dereference.d.ts +11 -0
  488. package/src/utils/schema/dereference.ts +98 -0
  489. package/src/utils/schema/draft.d.ts +10 -0
  490. package/src/utils/schema/draft.ts +341 -0
  491. package/src/utils/schema/equality.d.ts +4 -0
  492. package/src/utils/schema/equality.ts +97 -0
  493. package/src/utils/schema/fields.d.ts +49 -0
  494. package/src/utils/schema/fields.ts +190 -0
  495. package/src/utils/schema/index.d.ts +14 -0
  496. package/src/utils/schema/index.ts +14 -0
  497. package/src/utils/schema/json-schema-validator.d.ts +12 -0
  498. package/src/utils/schema/json-schema-validator.ts +577 -0
  499. package/src/utils/schema/meta-validator.d.ts +2 -0
  500. package/src/utils/schema/meta-validator.ts +167 -0
  501. package/src/utils/schema/normalize.d.ts +93 -0
  502. package/src/utils/schema/normalize.ts +1588 -0
  503. package/src/utils/schema/root-combinator.d.ts +12 -0
  504. package/src/utils/schema/root-combinator.ts +143 -0
  505. package/src/utils/schema/spill.d.ts +8 -0
  506. package/src/utils/schema/spill.ts +43 -0
  507. package/src/utils/schema/stamps.d.ts +25 -0
  508. package/src/utils/schema/stamps.ts +97 -0
  509. package/src/utils/schema/types.d.ts +4 -0
  510. package/src/utils/schema/types.ts +11 -0
  511. package/src/utils/schema/wire.d.ts +54 -0
  512. package/src/utils/schema/wire.ts +213 -0
  513. package/src/utils/schema/zod-decontaminate.d.ts +31 -0
  514. package/src/utils/schema/zod-decontaminate.ts +331 -0
  515. package/src/utils/sse-debug.d.ts +10 -0
  516. package/src/utils/sse-debug.ts +289 -0
  517. package/src/utils/tool-call-healing.d.ts +80 -0
  518. package/src/utils/tool-call-healing.ts +298 -0
  519. package/src/utils/tool-choice-capability.d.ts +57 -0
  520. package/src/utils/tool-choice-capability.ts +633 -0
  521. package/src/utils/tool-choice.d.ts +50 -0
  522. package/src/utils/tool-choice.ts +99 -0
  523. package/src/utils/validation.ts +1080 -0
  524. package/src/utils.d.ts +117 -0
  525. package/src/utils.ts +523 -0
@@ -0,0 +1,939 @@
1
+ /**
2
+ * Amazon Bedrock Converse Stream provider.
3
+ *
4
+ * Talks directly to `bedrock-runtime.{region}.amazonaws.com` over HTTPS with
5
+ * SigV4 signing and decodes the `application/vnd.amazon.eventstream` response.
6
+ * No `@aws-sdk/*`, no `@smithy/*`, no `proxy-agent`. Proxies are honored via
7
+ * Bun's native `HTTPS_PROXY` support.
8
+ */
9
+
10
+ import { $credentialEnv, $env, $flag, extractHttpStatusFromError, fetchWithRetry } from "@vib-rato/utils";
11
+ import type { Effort } from "../model-thinking";
12
+ import {
13
+ mapEffortToAnthropicAdaptiveEffort,
14
+ requireSupportedEffort,
15
+ supportsAnthropicAdaptiveThinkingDisplay as supportsAdaptiveThinkingDisplay,
16
+ } from "../model-thinking";
17
+ import { calculateCost } from "../models";
18
+ import type {
19
+ Api,
20
+ AssistantMessage,
21
+ CacheRetention,
22
+ Context,
23
+ Model,
24
+ StopReason,
25
+ StreamFunction,
26
+ StreamOptions,
27
+ TextContent,
28
+ ThinkingBudgets,
29
+ ThinkingContent,
30
+ Tool,
31
+ ToolCall,
32
+ ToolChoice,
33
+ ToolResultMessage,
34
+ } from "../types";
35
+ import { normalizeToolCallId, resolveCacheRetention, sanitizeJsonStrings } from "../utils";
36
+ import { AssistantMessageEventStream } from "../utils/event-stream";
37
+ import { transportFailureFacts } from "../utils/fallback-transport";
38
+ import { appendRawHttpRequestDumpFor400, type RawHttpRequestDump, withHttpStatus } from "../utils/http-inspector";
39
+ import { captureUnicodeEscapeEvidence, parseStreamingJson } from "../utils/json-parse";
40
+ import { resolveRetryBudget } from "../utils/retry-budget";
41
+ import { flattenToolRootCombinators, toolWireSchema } from "../utils/schema";
42
+ import {
43
+ isForcedToolChoiceUnsupportedError,
44
+ markToolChoiceIncapability,
45
+ resolveToolChoice,
46
+ } from "../utils/tool-choice-capability";
47
+ import { isValidBedrockBearerToken } from "./aws-credential-config";
48
+ import { resolveAwsCredentials } from "./aws-credentials";
49
+ import { decodeEventStream } from "./aws-eventstream";
50
+ import type { AwsCredentials } from "./aws-sigv4";
51
+ import { signRequest } from "./aws-sigv4";
52
+ import { transformMessages } from "./transform-messages";
53
+
54
+ export type BedrockThinkingDisplay = "summarized" | "omitted";
55
+
56
+ export interface BedrockOptions extends StreamOptions {
57
+ region?: string;
58
+ profile?: string;
59
+ toolChoice?: ToolChoice;
60
+ /* See https://docs.aws.amazon.com/bedrock/latest/userguide/inference-reasoning.html for supported models. */
61
+ reasoning?: Effort;
62
+ /* Custom token budgets per thinking level. Overrides default budgets. */
63
+ thinkingBudgets?: ThinkingBudgets;
64
+ /* Only supported by Anthropic model 4.x models, see https://docs.aws.amazon.com/bedrock/latest/userguide/Anthropic model-messages-extended-thinking.html#Anthropic model-messages-extended-thinking-tool-use-interleaved */
65
+ interleavedThinking?: boolean;
66
+ /**
67
+ * Controls how Anthropic model returns thinking content in Bedrock responses.
68
+ * - `"summarized"`: thinking blocks include human-readable summaries (default here).
69
+ * - `"omitted"`: thinking content is suppressed; the encrypted signature still
70
+ * travels back for multi-turn continuity.
71
+ *
72
+ * Starting with Anthropic model Opus 4.7 the Anthropic API default is `"omitted"`, which
73
+ * leaves callers waiting on a silent stream during long reasoning runs (issue
74
+ * #1373). We default to `"summarized"` so adaptive-thinking models that accept
75
+ * the field keep producing visible thinking deltas. Older adaptive-thinking
76
+ * models (Opus 4.6, Sonnet 4.6+) reject the field, so we omit it for them.
77
+ */
78
+ thinkingDisplay?: BedrockThinkingDisplay;
79
+ }
80
+
81
+ type Block = (TextContent | ThinkingContent | ToolCall) & { index?: number; partialJson?: string };
82
+
83
+ // ---------- Bedrock wire-format types ----------
84
+ // Mirrors only what we actually consume from `ConverseStreamRequest` /
85
+ // `ConverseStreamOutput`. Keeps us decoupled from `@aws-sdk/client-bedrock-runtime`.
86
+
87
+ interface CachePoint {
88
+ cachePoint: { type: "default"; ttl?: "5m" | "1h" };
89
+ }
90
+ interface TextBlockWire {
91
+ text: string;
92
+ }
93
+ interface ImageBlockWire {
94
+ image: { format: "jpeg" | "png" | "gif" | "webp"; source: { bytes: string } };
95
+ }
96
+ interface ToolUseBlockWire {
97
+ toolUse: { toolUseId: string; name: string; input: unknown };
98
+ }
99
+ interface ToolResultBlockWire {
100
+ toolResult: {
101
+ toolUseId: string;
102
+ content: Array<TextBlockWire | ImageBlockWire>;
103
+ status: "success" | "error";
104
+ };
105
+ }
106
+ interface ReasoningBlockWire {
107
+ reasoningContent: { reasoningText: { text: string; signature?: string } };
108
+ }
109
+
110
+ type UserContent = TextBlockWire | ImageBlockWire | ToolResultBlockWire | CachePoint;
111
+ type AssistantContent = TextBlockWire | ToolUseBlockWire | ReasoningBlockWire;
112
+ type SystemContent = TextBlockWire | CachePoint;
113
+
114
+ interface WireMessage {
115
+ role: "user" | "assistant";
116
+ content: Array<UserContent | AssistantContent>;
117
+ }
118
+
119
+ interface WireToolSpec {
120
+ toolSpec: { name: string; description: string; inputSchema: { json: unknown } };
121
+ }
122
+ interface WireToolChoice {
123
+ auto?: Record<string, never>;
124
+ any?: Record<string, never>;
125
+ tool?: { name: string };
126
+ }
127
+ interface WireToolConfig {
128
+ tools: WireToolSpec[];
129
+ toolChoice?: WireToolChoice;
130
+ }
131
+
132
+ interface ConverseStreamRequest {
133
+ messages: WireMessage[];
134
+ system?: SystemContent[];
135
+ inferenceConfig?: { maxTokens?: number; temperature?: number; topP?: number };
136
+ toolConfig?: WireToolConfig;
137
+ additionalModelRequestFields?: Record<string, unknown>;
138
+ }
139
+
140
+ // Streaming events (snake_case matches the JSON envelope key, but Bedrock uses camelCase).
141
+ interface MessageStartEvent {
142
+ role: "user" | "assistant";
143
+ }
144
+ interface ContentBlockStartEvent {
145
+ contentBlockIndex: number;
146
+ start?: { toolUse?: { toolUseId?: string; name?: string } };
147
+ }
148
+ interface ContentBlockDeltaEvent {
149
+ contentBlockIndex: number;
150
+ delta?: {
151
+ text?: string;
152
+ toolUse?: { input?: string };
153
+ reasoningContent?: { text?: string; signature?: string };
154
+ };
155
+ }
156
+ interface ContentBlockStopEvent {
157
+ contentBlockIndex: number;
158
+ }
159
+ interface MessageStopEvent {
160
+ stopReason?: string;
161
+ }
162
+ interface MetadataEvent {
163
+ usage?: {
164
+ inputTokens?: number;
165
+ outputTokens?: number;
166
+ cacheReadInputTokens?: number;
167
+ cacheWriteInputTokens?: number;
168
+ totalTokens?: number;
169
+ };
170
+ }
171
+
172
+ type BedrockAuthMode = { kind: "bearer"; token: string } | { kind: "sigv4"; credentials: AwsCredentials };
173
+
174
+ export const streamBedrock: StreamFunction<"bedrock-converse-stream"> = (
175
+ model: Model<"bedrock-converse-stream">,
176
+ context: Context,
177
+ options: BedrockOptions,
178
+ ): AssistantMessageEventStream => {
179
+ const stream = new AssistantMessageEventStream();
180
+
181
+ (async () => {
182
+ const startTime = Date.now();
183
+ let firstTokenTime: number | undefined;
184
+
185
+ const output: AssistantMessage = {
186
+ role: "assistant",
187
+ content: [],
188
+ api: "bedrock-converse-stream" as Api,
189
+ provider: model.provider,
190
+ model: model.id,
191
+ usage: {
192
+ input: 0,
193
+ output: 0,
194
+ cacheRead: 0,
195
+ cacheWrite: 0,
196
+ totalTokens: 0,
197
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
198
+ },
199
+ stopReason: "stop",
200
+ timestamp: Date.now(),
201
+ };
202
+
203
+ const blocks = output.content as Block[];
204
+ let rawRequestDump: RawHttpRequestDump | undefined;
205
+ const region = options.region || $env.AWS_REGION || $env.AWS_DEFAULT_REGION || "us-east-1";
206
+
207
+ try {
208
+ const cacheRetention = resolveCacheRetention(options.cacheRetention);
209
+ const resolvedToolChoice = resolveToolChoice(model, options.toolChoice);
210
+ const toolConfig = convertToolConfig(context.tools, resolvedToolChoice.resolvedChoice);
211
+ let additionalModelRequestFields = buildAdditionalModelRequestFields(model, options);
212
+
213
+ // Bedrock rejects thinking + forced tool_choice ("any" or specific tool).
214
+ // When the resolved tool_choice forces tool use, disable thinking to avoid API errors.
215
+ if (toolConfig?.toolChoice && additionalModelRequestFields) {
216
+ const tc = toolConfig.toolChoice;
217
+ if (tc.any || tc.tool) additionalModelRequestFields = undefined;
218
+ }
219
+
220
+ const commandInput: ConverseStreamRequest = {
221
+ messages: convertMessages(context, model, cacheRetention),
222
+ system: buildSystemPrompt(context.systemPrompt, model, cacheRetention),
223
+ inferenceConfig: {
224
+ maxTokens: options.maxTokens,
225
+ temperature: options.temperature,
226
+ topP: options.topP,
227
+ },
228
+ toolConfig,
229
+ additionalModelRequestFields,
230
+ };
231
+ options?.onPayload?.(commandInput, model, options?.attemptScope);
232
+
233
+ const host = `bedrock-runtime.${region}.amazonaws.com`;
234
+ const url = `https://${host}/model/${encodeURIComponent(model.id)}/converse-stream`;
235
+ const urlPath = `/model/${encodeURIComponent(model.id)}/converse-stream`;
236
+ rawRequestDump = {
237
+ provider: model.provider,
238
+ api: output.api,
239
+ model: model.id,
240
+ method: "POST",
241
+ url,
242
+ body: commandInput,
243
+ };
244
+
245
+ const bearerToken = $credentialEnv("AWS_BEARER_TOKEN_BEDROCK");
246
+ if (bearerToken && !isValidBedrockBearerToken(bearerToken)) {
247
+ throw new Error("AWS_BEARER_TOKEN_BEDROCK contains unsafe control characters.");
248
+ }
249
+ const authMode: BedrockAuthMode = bearerToken
250
+ ? { kind: "bearer", token: bearerToken }
251
+ : {
252
+ kind: "sigv4",
253
+ credentials: $flag("AWS_BEDROCK_SKIP_AUTH")
254
+ ? { accessKeyId: "dummy-access-key", secretAccessKey: "dummy-secret-key" }
255
+ : await resolveAwsCredentials({ profile: options.profile, region, signal: options.signal }),
256
+ };
257
+ const bodyText = JSON.stringify(commandInput);
258
+ const body = new TextEncoder().encode(bodyText);
259
+ const baseHeaders: Record<string, string> = {
260
+ "content-type": "application/json",
261
+ accept: "application/vnd.amazon.eventstream",
262
+ };
263
+ const buildRequestHeaders = async (requestBody: Uint8Array): Promise<Record<string, string>> => {
264
+ const headers = new Headers(baseHeaders);
265
+ if (authMode.kind === "bearer") {
266
+ headers.set("authorization", `Bearer ${authMode.token}`);
267
+ return Object.fromEntries(headers);
268
+ }
269
+ const signed = await signRequest({
270
+ method: "POST",
271
+ host,
272
+ path: urlPath,
273
+ body: requestBody,
274
+ region,
275
+ service: "bedrock",
276
+ credentials: authMode.credentials,
277
+ headers: baseHeaders,
278
+ });
279
+ for (const [name, value] of Object.entries(signed)) headers.set(name, value);
280
+ return Object.fromEntries(headers);
281
+ };
282
+ const requestHeaders = await buildRequestHeaders(body);
283
+ const sentForcedToolChoice = Boolean(toolConfig?.toolChoice?.any || toolConfig?.toolChoice?.tool);
284
+ let fallbackRan = false;
285
+ const retryWithoutForcedToolChoice = async (reason: string) => {
286
+ fallbackRan = true;
287
+ markToolChoiceIncapability(model, "auto", reason);
288
+ stream.push({
289
+ type: "toolChoiceIncapability",
290
+ api: output.api,
291
+ provider: model.provider,
292
+ model: model.id,
293
+ requestedLevel: resolvedToolChoice.requestedLevel,
294
+ resolvedLevel: "auto",
295
+ reason,
296
+ registryKey: resolvedToolChoice.registryKey,
297
+ });
298
+ stripBedrockForcedToolChoiceForRetry(commandInput);
299
+ const retryBodyText = JSON.stringify(commandInput);
300
+ const retryBody = new TextEncoder().encode(retryBodyText);
301
+ if (rawRequestDump) rawRequestDump.body = commandInput;
302
+ return fetchWithRetry(url, {
303
+ method: "POST",
304
+ headers: await buildRequestHeaders(retryBody),
305
+ body: retryBody,
306
+ signal: options.signal,
307
+ maxAttempts: 1,
308
+ });
309
+ };
310
+
311
+ let response = await fetchWithRetry(url, {
312
+ method: "POST",
313
+ headers: requestHeaders,
314
+ body,
315
+ signal: options.signal,
316
+ maxAttempts: resolveRetryBudget(options.requestMaxRetries, 4) + 1,
317
+ });
318
+
319
+ if (!response.ok && sentForcedToolChoice) {
320
+ const errBody = await response.text().catch(() => "");
321
+ const error = withHttpStatus(
322
+ new Error(`Bedrock HTTP ${response.status}: ${errBody.slice(0, 1000)}`),
323
+ response.status,
324
+ );
325
+ if (
326
+ firstTokenTime === undefined &&
327
+ !fallbackRan &&
328
+ !options.fallbackManaged &&
329
+ isForcedToolChoiceUnsupportedError(error, true)
330
+ ) {
331
+ response = await retryWithoutForcedToolChoice(error.message);
332
+ } else {
333
+ throw error;
334
+ }
335
+ }
336
+ if (!response.ok) {
337
+ const errBody = await response.text().catch(() => "");
338
+ throw withHttpStatus(
339
+ new Error(`Bedrock HTTP ${response.status}: ${errBody.slice(0, 1000)}`),
340
+ response.status,
341
+ );
342
+ }
343
+ if (!response.body) throw new Error("Bedrock response has no body");
344
+
345
+ // Track first event for the abort/diagnostic path (currently informational).
346
+ streamLoop: while (true) {
347
+ for await (const message of decodeEventStream(response.body)) {
348
+ const messageType = message.headers[":message-type"];
349
+ const eventType = message.headers[":event-type"];
350
+
351
+ if (messageType === "exception") {
352
+ const exceptionType = message.headers[":exception-type"] || "Exception";
353
+ const payload = safeParsePayload(message.payload) as { message?: string } | undefined;
354
+ const errorMessage = payload?.message || new TextDecoder().decode(message.payload);
355
+ const status = exceptionType === "validationException" ? 400 : 0;
356
+ const err = new Error(`${exceptionType}: ${errorMessage}`);
357
+ const error = status ? withHttpStatus(err, status) : err;
358
+ if (
359
+ firstTokenTime === undefined &&
360
+ sentForcedToolChoice &&
361
+ !fallbackRan &&
362
+ !options.fallbackManaged &&
363
+ isForcedToolChoiceUnsupportedError(error, true)
364
+ ) {
365
+ response = await retryWithoutForcedToolChoice(error.message);
366
+ if (!response.ok) {
367
+ const errBody = await response.text().catch(() => "");
368
+ throw withHttpStatus(
369
+ new Error(`Bedrock HTTP ${response.status}: ${errBody.slice(0, 1000)}`),
370
+ response.status,
371
+ );
372
+ }
373
+ if (!response.body) throw new Error("Bedrock response has no body");
374
+ continue streamLoop;
375
+ }
376
+ throw error;
377
+ }
378
+ if (messageType === "error") {
379
+ const code = message.headers[":error-code"] || "UnknownError";
380
+ const errorMessage = message.headers[":error-message"] || new TextDecoder().decode(message.payload);
381
+ throw new Error(`${code}: ${errorMessage}`);
382
+ }
383
+ if (messageType !== "event") continue;
384
+
385
+ const payload = safeParsePayload(message.payload);
386
+ if (!payload) continue;
387
+
388
+ switch (eventType) {
389
+ case "messageStart": {
390
+ // no-op: first event marker is implicit by stream entry.
391
+ const ev = payload as MessageStartEvent;
392
+ if (ev.role !== "assistant") {
393
+ throw new Error("Unexpected assistant message start but got user message start instead");
394
+ }
395
+ stream.push({ type: "start", partial: output });
396
+ break;
397
+ }
398
+ case "contentBlockStart": {
399
+ if (!firstTokenTime) firstTokenTime = Date.now();
400
+ handleContentBlockStart(payload as ContentBlockStartEvent, blocks, output, stream);
401
+ break;
402
+ }
403
+ case "contentBlockDelta": {
404
+ if (!firstTokenTime) firstTokenTime = Date.now();
405
+ handleContentBlockDelta(payload as ContentBlockDeltaEvent, blocks, output, stream);
406
+ break;
407
+ }
408
+ case "contentBlockStop": {
409
+ handleContentBlockStop(payload as ContentBlockStopEvent, blocks, output, stream);
410
+ break;
411
+ }
412
+ case "messageStop": {
413
+ const ev = payload as MessageStopEvent;
414
+ output.stopReason = mapStopReason(ev.stopReason);
415
+ break;
416
+ }
417
+ case "metadata": {
418
+ handleMetadata(payload as MetadataEvent, model, output);
419
+ break;
420
+ }
421
+ default:
422
+ // Unknown event types (Bedrock may add new ones) — ignore.
423
+ break;
424
+ }
425
+ }
426
+ break;
427
+ }
428
+
429
+ if (options.signal?.aborted) throw new Error("Request was aborted");
430
+
431
+ if (output.stopReason === "error" || output.stopReason === "aborted") {
432
+ throw new Error(output.errorMessage ?? "An unknown error occurred");
433
+ }
434
+
435
+ output.duration = Date.now() - startTime;
436
+ if (firstTokenTime) output.ttft = firstTokenTime - startTime;
437
+ stream.push({ type: "done", reason: output.stopReason, message: output });
438
+ stream.end();
439
+ } catch (error) {
440
+ for (const block of output.content) {
441
+ delete (block as Block).index;
442
+ delete (block as Block).partialJson;
443
+ }
444
+ output.stopReason = options.signal?.aborted ? "aborted" : "error";
445
+ output.errorStatus = extractHttpStatusFromError(error);
446
+ output.transportFailure = transportFailureFacts(error);
447
+ const baseMessage = error instanceof Error ? error.message : JSON.stringify(error);
448
+ // Enrich error with thinking block diagnostics for signature-related failures
449
+ let diagnostics = "";
450
+ if (baseMessage.includes("signature") || baseMessage.includes("thinking")) {
451
+ const thinkingBlocks = context.messages
452
+ .filter((m): m is AssistantMessage => m.role === "assistant")
453
+ .flatMap((m, mi) =>
454
+ m.content
455
+ .filter(b => b.type === "thinking")
456
+ .map((b, bi) => ({
457
+ msg: mi,
458
+ block: bi,
459
+ stop: m.stopReason,
460
+ sigLen: b.thinkingSignature?.length ?? -1,
461
+ thinkLen: b.thinking.length,
462
+ })),
463
+ );
464
+ if (thinkingBlocks.length > 0) {
465
+ diagnostics = `\n[thinking-diag] ${JSON.stringify(thinkingBlocks)}`;
466
+ }
467
+ }
468
+ output.errorMessage = await appendRawHttpRequestDumpFor400(baseMessage + diagnostics, error, rawRequestDump);
469
+ output.duration = Date.now() - startTime;
470
+ if (firstTokenTime) output.ttft = firstTokenTime - startTime;
471
+ stream.push({ type: "error", reason: output.stopReason, error: output });
472
+ stream.end();
473
+ }
474
+ })();
475
+
476
+ return stream;
477
+ };
478
+
479
+ function safeParsePayload(payload: Uint8Array): unknown {
480
+ if (payload.length === 0) return {};
481
+ try {
482
+ return JSON.parse(new TextDecoder().decode(payload));
483
+ } catch {
484
+ return undefined;
485
+ }
486
+ }
487
+
488
+ function handleContentBlockStart(
489
+ event: ContentBlockStartEvent,
490
+ blocks: Block[],
491
+ output: AssistantMessage,
492
+ stream: AssistantMessageEventStream,
493
+ ): void {
494
+ const index = event.contentBlockIndex;
495
+ const start = event.start;
496
+
497
+ if (start?.toolUse) {
498
+ const block: Block = {
499
+ type: "toolCall",
500
+ id: normalizeToolCallId(start.toolUse.toolUseId || ""),
501
+ name: start.toolUse.name || "",
502
+ arguments: {},
503
+ partialJson: "",
504
+ index,
505
+ };
506
+ output.content.push(block);
507
+ stream.push({ type: "toolcall_start", contentIndex: blocks.length - 1, partial: output });
508
+ }
509
+ }
510
+
511
+ function handleContentBlockDelta(
512
+ event: ContentBlockDeltaEvent,
513
+ blocks: Block[],
514
+ output: AssistantMessage,
515
+ stream: AssistantMessageEventStream,
516
+ ): void {
517
+ const contentBlockIndex = event.contentBlockIndex;
518
+ const delta = event.delta;
519
+ let index = blocks.findIndex(b => b.index === contentBlockIndex);
520
+ let block = blocks[index];
521
+
522
+ if (delta?.text !== undefined) {
523
+ // If no text block exists yet, create one — `handleContentBlockStart` is not sent for text blocks
524
+ if (!block) {
525
+ const newBlock: Block = { type: "text", text: "", index: contentBlockIndex };
526
+ output.content.push(newBlock);
527
+ index = blocks.length - 1;
528
+ block = blocks[index];
529
+ stream.push({ type: "text_start", contentIndex: index, partial: output });
530
+ }
531
+ if (block.type === "text") {
532
+ block.text += delta.text;
533
+ stream.push({ type: "text_delta", contentIndex: index, delta: delta.text, partial: output });
534
+ }
535
+ } else if (delta?.toolUse && block?.type === "toolCall") {
536
+ block.partialJson = (block.partialJson || "") + (delta.toolUse.input || "");
537
+ block.arguments = parseStreamingJson(block.partialJson);
538
+ stream.push({ type: "toolcall_delta", contentIndex: index, delta: delta.toolUse.input || "", partial: output });
539
+ } else if (delta?.reasoningContent) {
540
+ let thinkingBlock = block;
541
+ let thinkingIndex = index;
542
+
543
+ if (!thinkingBlock) {
544
+ const newBlock: Block = { type: "thinking", thinking: "", thinkingSignature: "", index: contentBlockIndex };
545
+ output.content.push(newBlock);
546
+ thinkingIndex = blocks.length - 1;
547
+ thinkingBlock = blocks[thinkingIndex];
548
+ stream.push({ type: "thinking_start", contentIndex: thinkingIndex, partial: output });
549
+ }
550
+
551
+ if (thinkingBlock?.type === "thinking") {
552
+ if (delta.reasoningContent.text) {
553
+ thinkingBlock.thinking += delta.reasoningContent.text;
554
+ stream.push({
555
+ type: "thinking_delta",
556
+ contentIndex: thinkingIndex,
557
+ delta: delta.reasoningContent.text,
558
+ partial: output,
559
+ });
560
+ }
561
+ if (delta.reasoningContent.signature) {
562
+ thinkingBlock.thinkingSignature =
563
+ (thinkingBlock.thinkingSignature || "") + delta.reasoningContent.signature;
564
+ }
565
+ }
566
+ }
567
+ }
568
+
569
+ function handleMetadata(event: MetadataEvent, model: Model<"bedrock-converse-stream">, output: AssistantMessage): void {
570
+ if (event.usage) {
571
+ output.usage.input = event.usage.inputTokens || 0;
572
+ output.usage.output = event.usage.outputTokens || 0;
573
+ output.usage.cacheRead = event.usage.cacheReadInputTokens || 0;
574
+ output.usage.cacheWrite = event.usage.cacheWriteInputTokens || 0;
575
+ output.usage.totalTokens = event.usage.totalTokens || output.usage.input + output.usage.output;
576
+ calculateCost(model, output.usage);
577
+ }
578
+ }
579
+
580
+ function handleContentBlockStop(
581
+ event: ContentBlockStopEvent,
582
+ blocks: Block[],
583
+ output: AssistantMessage,
584
+ stream: AssistantMessageEventStream,
585
+ ): void {
586
+ const index = blocks.findIndex(b => b.index === event.contentBlockIndex);
587
+ const block = blocks[index];
588
+ if (!block) return;
589
+ delete (block as Block).index;
590
+
591
+ switch (block.type) {
592
+ case "text":
593
+ stream.push({ type: "text_end", contentIndex: index, content: block.text, partial: output });
594
+ break;
595
+ case "thinking":
596
+ stream.push({ type: "thinking_end", contentIndex: index, content: block.thinking, partial: output });
597
+ break;
598
+ case "toolCall":
599
+ block.arguments = parseStreamingJson(block.partialJson);
600
+ captureUnicodeEscapeEvidence(block, block.partialJson ?? "");
601
+ delete (block as Block).partialJson;
602
+ stream.push({ type: "toolcall_end", contentIndex: index, toolCall: block, partial: output });
603
+ break;
604
+ }
605
+ }
606
+
607
+ /**
608
+ * Check if the model supports prompt caching.
609
+ * Supported: Anthropic model 3.5 Haiku, Anthropic model 3.7 Sonnet, Anthropic model 4.x+ models, Haiku 4.5+
610
+ *
611
+ * For base models and system-defined inference profiles the model ID / ARN
612
+ * contains the model name, so we can decide locally.
613
+ *
614
+ * For application inference profiles (whose ARNs don't contain the model name),
615
+ * set AWS_BEDROCK_FORCE_CACHE=1 to enable cache points. Amazon Nova models
616
+ * have automatic caching and don't need explicit cache points.
617
+ */
618
+ function supportsPromptCaching(model: Model<"bedrock-converse-stream">): boolean {
619
+ if (model.cost.cacheRead || model.cost.cacheWrite) return true;
620
+ const id = model.id.toLowerCase();
621
+ // Anthropic model 4.x models (opus-4, sonnet-4, haiku-4)
622
+ if (id.includes("claude") && (id.includes("-4-") || id.includes("-4."))) return true;
623
+ // Anthropic model 3.5 Haiku, Anthropic model 3.7 Sonnet (legacy naming)
624
+ if (id.includes("claude-3-7-sonnet") || id.includes("claude-3-5-haiku")) return true;
625
+ // Anthropic model Haiku 4.5+ (new naming)
626
+ if (id.includes("claude-haiku")) return true;
627
+ // Application inference profiles don't contain the model name in the ARN.
628
+ // Allow users to force cache points via environment variable.
629
+ if (typeof process !== "undefined" && $flag("AWS_BEDROCK_FORCE_CACHE")) return true;
630
+ return false;
631
+ }
632
+
633
+ /**
634
+ * Check if the model supports thinking signatures in reasoningContent.
635
+ * Only Anthropic Anthropic model models support the signature field.
636
+ * Other models (Nova, Titan, Mistral, Llama, etc.) reject it with:
637
+ * "This model doesn't support the reasoningContent.reasoningText.signature field"
638
+ */
639
+ function supportsThinkingSignature(model: Model<"bedrock-converse-stream">): boolean {
640
+ const id = model.id.toLowerCase();
641
+ return id.includes("anthropic.claude") || id.includes("anthropic/claude");
642
+ }
643
+
644
+ function buildSystemPrompt(
645
+ systemPrompt: readonly string[] | undefined,
646
+ model: Model<"bedrock-converse-stream">,
647
+ cacheRetention: CacheRetention,
648
+ ): SystemContent[] | undefined {
649
+ const prompts = systemPrompt?.map(prompt => prompt.toWellFormed()).filter(prompt => prompt.length > 0) ?? [];
650
+ if (prompts.length === 0) return undefined;
651
+
652
+ const blocks: SystemContent[] = prompts.map(prompt => ({ text: prompt }));
653
+
654
+ // Add cache point for supported Anthropic model models
655
+ if (cacheRetention !== "none" && supportsPromptCaching(model)) {
656
+ blocks.push({
657
+ cachePoint: { type: "default", ...(cacheRetention === "long" ? { ttl: "1h" } : {}) },
658
+ });
659
+ }
660
+
661
+ return blocks;
662
+ }
663
+
664
+ function convertMessages(
665
+ context: Context,
666
+ model: Model<"bedrock-converse-stream">,
667
+ cacheRetention: CacheRetention,
668
+ ): WireMessage[] {
669
+ const result: WireMessage[] = [];
670
+ const transformedMessages = transformMessages(context.messages, model, normalizeToolCallId);
671
+
672
+ for (let i = 0; i < transformedMessages.length; i++) {
673
+ const m = transformedMessages[i];
674
+
675
+ switch (m.role) {
676
+ case "developer":
677
+ case "user":
678
+ if (typeof m.content === "string") {
679
+ // Skip empty user messages
680
+ if (!m.content || m.content.trim() === "") continue;
681
+ result.push({ role: "user", content: [{ text: m.content.toWellFormed() }] });
682
+ } else {
683
+ const contentBlocks: UserContent[] = [];
684
+ for (const c of m.content) {
685
+ switch (c.type) {
686
+ case "text": {
687
+ const text = c.text.toWellFormed();
688
+ if (text.trim().length === 0) continue;
689
+ contentBlocks.push({ text });
690
+ break;
691
+ }
692
+ case "image":
693
+ contentBlocks.push({ image: createImageBlock(c.mimeType, c.data) });
694
+ break;
695
+ default:
696
+ throw new Error("Unknown user content type");
697
+ }
698
+ }
699
+ // Skip message if all blocks filtered out
700
+ if (contentBlocks.length === 0) continue;
701
+ result.push({ role: "user", content: contentBlocks });
702
+ }
703
+ break;
704
+ case "assistant": {
705
+ // Skip assistant messages with empty content (e.g., from aborted requests)
706
+ // Bedrock rejects messages with empty content arrays
707
+ if (m.content.length === 0) continue;
708
+ const contentBlocks: AssistantContent[] = [];
709
+ for (const c of m.content) {
710
+ switch (c.type) {
711
+ case "text":
712
+ // Skip empty text blocks
713
+ if (c.text.trim().length === 0) continue;
714
+ contentBlocks.push({ text: c.text.toWellFormed() });
715
+ break;
716
+ case "toolCall":
717
+ contentBlocks.push({
718
+ toolUse: {
719
+ toolUseId: normalizeToolCallId(c.id),
720
+ name: c.name,
721
+ input: sanitizeJsonStrings(c.arguments),
722
+ },
723
+ });
724
+ break;
725
+ case "thinking":
726
+ // Skip empty thinking blocks
727
+ if (c.thinking.trim().length === 0) continue;
728
+ // Thinking blocks require a valid signature when sent as reasoningContent.
729
+ // If the signature is missing (e.g., from an aborted stream), or the model
730
+ // doesn't support signatures, convert to plain text instead.
731
+ if (supportsThinkingSignature(model) && c.thinkingSignature) {
732
+ contentBlocks.push({
733
+ reasoningContent: {
734
+ reasoningText: { text: c.thinking.toWellFormed(), signature: c.thinkingSignature },
735
+ },
736
+ });
737
+ } else if (!supportsThinkingSignature(model)) {
738
+ // Model doesn't support signatures at all — send as unsigned reasoning
739
+ contentBlocks.push({
740
+ reasoningContent: { reasoningText: { text: c.thinking.toWellFormed() } },
741
+ });
742
+ } else {
743
+ // Model requires signature but we don't have one — demote to text
744
+ contentBlocks.push({ text: `[Thinking]: ${c.thinking.toWellFormed()}` });
745
+ }
746
+ break;
747
+ default:
748
+ throw new Error("Unknown assistant content type");
749
+ }
750
+ }
751
+ // Skip if all content blocks were filtered out
752
+ if (contentBlocks.length === 0) continue;
753
+ result.push({ role: "assistant", content: contentBlocks });
754
+ break;
755
+ }
756
+ case "toolResult": {
757
+ // Collect all consecutive toolResult messages into a single user message —
758
+ // Bedrock requires all tool results to be in one message.
759
+ const toolResults: ToolResultBlockWire[] = [];
760
+ toolResults.push({
761
+ toolResult: {
762
+ toolUseId: normalizeToolCallId(m.toolCallId),
763
+ content: m.content.map(c =>
764
+ c.type === "image"
765
+ ? { image: createImageBlock(c.mimeType, c.data) }
766
+ : { text: c.text.toWellFormed() },
767
+ ),
768
+ status: m.isError ? "error" : "success",
769
+ },
770
+ });
771
+
772
+ let j = i + 1;
773
+ while (j < transformedMessages.length && transformedMessages[j].role === "toolResult") {
774
+ const nextMsg = transformedMessages[j] as ToolResultMessage;
775
+ toolResults.push({
776
+ toolResult: {
777
+ toolUseId: normalizeToolCallId(nextMsg.toolCallId),
778
+ content: nextMsg.content.map(c =>
779
+ c.type === "image"
780
+ ? { image: createImageBlock(c.mimeType, c.data) }
781
+ : { text: c.text.toWellFormed() },
782
+ ),
783
+ status: nextMsg.isError ? "error" : "success",
784
+ },
785
+ });
786
+ j++;
787
+ }
788
+ i = j - 1;
789
+
790
+ result.push({ role: "user", content: toolResults });
791
+ break;
792
+ }
793
+ default:
794
+ throw new Error("Unknown message role");
795
+ }
796
+ }
797
+
798
+ // Add cache point to the last user message for supported Anthropic model models
799
+ if (cacheRetention !== "none" && supportsPromptCaching(model) && result.length > 0) {
800
+ const lastMessage = result[result.length - 1];
801
+ if (lastMessage.role === "user" && lastMessage.content) {
802
+ (lastMessage.content as UserContent[]).push({
803
+ cachePoint: { type: "default", ...(cacheRetention === "long" ? { ttl: "1h" } : {}) },
804
+ });
805
+ }
806
+ }
807
+
808
+ return result;
809
+ }
810
+
811
+ export function stripBedrockForcedToolChoiceForRetry<T extends { toolConfig?: { toolChoice?: unknown } }>(body: T): T {
812
+ if (body.toolConfig) {
813
+ body.toolConfig = { ...body.toolConfig, toolChoice: undefined };
814
+ }
815
+ return body;
816
+ }
817
+
818
+ export function convertToolConfig(
819
+ tools: Tool[] | undefined,
820
+ toolChoice: BedrockOptions["toolChoice"],
821
+ ): WireToolConfig | undefined {
822
+ if (!tools?.length || toolChoice === "none") return undefined;
823
+
824
+ const bedrockTools: WireToolSpec[] = tools.map(tool => ({
825
+ toolSpec: {
826
+ name: tool.name,
827
+ description: tool.description || "",
828
+ inputSchema: { json: flattenToolRootCombinators(toolWireSchema(tool)) },
829
+ },
830
+ }));
831
+
832
+ let bedrockToolChoice: WireToolChoice | undefined;
833
+ switch (toolChoice) {
834
+ case "auto":
835
+ bedrockToolChoice = { auto: {} };
836
+ break;
837
+ case "any":
838
+ case "required":
839
+ bedrockToolChoice = { any: {} };
840
+ break;
841
+ default:
842
+ if (toolChoice?.type === "tool") {
843
+ bedrockToolChoice = { tool: { name: toolChoice.name } };
844
+ }
845
+ }
846
+
847
+ return bedrockToolChoice ? { tools: bedrockTools, toolChoice: bedrockToolChoice } : { tools: bedrockTools };
848
+ }
849
+
850
+ function mapStopReason(reason: string | undefined): StopReason {
851
+ switch (reason) {
852
+ case "end_turn":
853
+ case "stop_sequence":
854
+ return "stop";
855
+ case "max_tokens":
856
+ case "model_context_window_exceeded":
857
+ return "length";
858
+ case "tool_use":
859
+ return "toolUse";
860
+ default:
861
+ return "error";
862
+ }
863
+ }
864
+
865
+ function buildAdditionalModelRequestFields(
866
+ model: Model<"bedrock-converse-stream">,
867
+ options: BedrockOptions,
868
+ ): Record<string, unknown> | undefined {
869
+ const reasoning = options.reasoning;
870
+ if (!reasoning || !model.reasoning) return undefined;
871
+
872
+ const mode = model.thinking?.mode;
873
+ if (mode === "anthropic-adaptive") {
874
+ const effort = mapEffortToAnthropicAdaptiveEffort(model, reasoning);
875
+ // Starting with Anthropic model Opus 4.7, Anthropic switched the adaptive-thinking
876
+ // default to "omitted", which silently suppresses streamed reasoning and
877
+ // can read as a stalled stream during long reasoning runs (issue #1373).
878
+ // Opt back into "summarized" by default on models that accept the field.
879
+ const adaptive: { type: "adaptive"; display?: BedrockThinkingDisplay } = { type: "adaptive" };
880
+ if (supportsAdaptiveThinkingDisplay(model.id)) {
881
+ adaptive.display = options.thinkingDisplay ?? "summarized";
882
+ }
883
+ return {
884
+ thinking: adaptive,
885
+ output_config: { effort },
886
+ };
887
+ }
888
+
889
+ const level = requireSupportedEffort(model, reasoning);
890
+ const defaultBudgets: Record<Effort, number> = {
891
+ minimal: 1024,
892
+ low: 2048,
893
+ medium: 8192,
894
+ high: 16384,
895
+ xhigh: 32768,
896
+ max: 32768,
897
+ };
898
+ const budget = options.thinkingBudgets?.[level] ?? defaultBudgets[level];
899
+
900
+ const result: Record<string, unknown> = {
901
+ thinking: {
902
+ type: "enabled",
903
+ budget_tokens: budget,
904
+ display: options.thinkingDisplay ?? "summarized",
905
+ },
906
+ };
907
+
908
+ if (options.interleavedThinking) {
909
+ result.anthropic_beta = ["interleaved-thinking-2025-05-14"];
910
+ }
911
+
912
+ return result;
913
+ }
914
+
915
+ /**
916
+ * Bedrock's wire format expects the image as `{ source: { bytes: <base64-string> }, format }`.
917
+ * The caller already passes base64-encoded data, so no decode/re-encode round-trip is needed.
918
+ */
919
+ function createImageBlock(mimeType: string, data: string): ImageBlockWire["image"] {
920
+ let format: "jpeg" | "png" | "gif" | "webp";
921
+ switch (mimeType) {
922
+ case "image/jpeg":
923
+ case "image/jpg":
924
+ format = "jpeg";
925
+ break;
926
+ case "image/png":
927
+ format = "png";
928
+ break;
929
+ case "image/gif":
930
+ format = "gif";
931
+ break;
932
+ case "image/webp":
933
+ format = "webp";
934
+ break;
935
+ default:
936
+ throw new Error(`Unknown image type: ${mimeType}`);
937
+ }
938
+ return { source: { bytes: data }, format };
939
+ }