@llumiverse/drivers 1.3.0 → 1.4.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 (409) hide show
  1. package/lib/{types/adobe → adobe}/firefly.d.ts +2 -1
  2. package/lib/adobe/firefly.d.ts.map +1 -0
  3. package/lib/adobe/firefly.js +120 -0
  4. package/lib/adobe/firefly.js.map +1 -0
  5. package/lib/{types/anthropic → anthropic}/index.d.ts +4 -2
  6. package/lib/anthropic/index.d.ts.map +1 -0
  7. package/lib/{esm/anthropic → anthropic}/index.js +19 -8
  8. package/lib/anthropic/index.js.map +1 -0
  9. package/lib/{types/azure → azure}/azure_foundry.d.ts +9 -7
  10. package/lib/azure/azure_foundry.d.ts.map +1 -0
  11. package/lib/{esm/azure → azure}/azure_foundry.js +138 -124
  12. package/lib/azure/azure_foundry.js.map +1 -0
  13. package/lib/{types/bedrock → bedrock}/converse.d.ts +2 -2
  14. package/lib/bedrock/converse.d.ts.map +1 -0
  15. package/lib/{esm/bedrock → bedrock}/converse.js +86 -79
  16. package/lib/bedrock/converse.js.map +1 -0
  17. package/lib/bedrock/embeddings.d.ts +4 -0
  18. package/lib/bedrock/embeddings.d.ts.map +1 -0
  19. package/lib/bedrock/embeddings.js +359 -0
  20. package/lib/bedrock/embeddings.js.map +1 -0
  21. package/lib/{types/bedrock → bedrock}/index.d.ts +33 -9
  22. package/lib/bedrock/index.d.ts.map +1 -0
  23. package/lib/{esm/bedrock → bedrock}/index.js +599 -324
  24. package/lib/bedrock/index.js.map +1 -0
  25. package/lib/{types/bedrock → bedrock}/nova-image-payload.d.ts +5 -5
  26. package/lib/bedrock/nova-image-payload.d.ts.map +1 -0
  27. package/lib/{esm/bedrock → bedrock}/nova-image-payload.js +31 -36
  28. package/lib/bedrock/nova-image-payload.js.map +1 -0
  29. package/lib/{types/bedrock → bedrock}/payloads.d.ts +1 -1
  30. package/lib/bedrock/payloads.d.ts.map +1 -0
  31. package/lib/{cjs/bedrock → bedrock}/payloads.js.map +1 -1
  32. package/lib/{types/bedrock → bedrock}/s3.d.ts +3 -2
  33. package/lib/bedrock/s3.d.ts.map +1 -0
  34. package/lib/{esm/bedrock → bedrock}/s3.js +27 -23
  35. package/lib/bedrock/s3.js.map +1 -0
  36. package/lib/{types/bedrock → bedrock}/twelvelabs.d.ts +8 -9
  37. package/lib/bedrock/twelvelabs.d.ts.map +1 -0
  38. package/lib/{esm/bedrock → bedrock}/twelvelabs.js +17 -21
  39. package/lib/bedrock/twelvelabs.js.map +1 -0
  40. package/lib/{types/groq → groq}/index.d.ts +6 -4
  41. package/lib/groq/index.d.ts.map +1 -0
  42. package/lib/{esm/groq → groq}/index.js +72 -39
  43. package/lib/groq/index.js.map +1 -0
  44. package/lib/{types/huggingface_ie.d.ts → huggingface_ie.d.ts} +4 -3
  45. package/lib/huggingface_ie.d.ts.map +1 -0
  46. package/lib/{esm/huggingface_ie.js → huggingface_ie.js} +32 -31
  47. package/lib/huggingface_ie.js.map +1 -0
  48. package/lib/index.d.ts +16 -0
  49. package/lib/index.d.ts.map +1 -0
  50. package/lib/index.js +16 -0
  51. package/lib/index.js.map +1 -0
  52. package/lib/{types/mistral → mistral}/index.d.ts +6 -5
  53. package/lib/mistral/index.d.ts.map +1 -0
  54. package/lib/{esm/mistral → mistral}/index.js +66 -38
  55. package/lib/mistral/index.js.map +1 -0
  56. package/lib/{types/mistral → mistral}/types.d.ts +1 -0
  57. package/lib/mistral/types.d.ts.map +1 -0
  58. package/lib/mistral/types.js.map +1 -0
  59. package/lib/{types/openai → openai}/azure_openai.d.ts +5 -4
  60. package/lib/openai/azure_openai.d.ts.map +1 -0
  61. package/lib/{esm/openai → openai}/azure_openai.js +17 -14
  62. package/lib/openai/azure_openai.js.map +1 -0
  63. package/lib/openai/drivers.d.ts +4 -0
  64. package/lib/openai/drivers.d.ts.map +1 -0
  65. package/lib/openai/drivers.js +9 -0
  66. package/lib/openai/drivers.js.map +1 -0
  67. package/lib/{types/openai → openai}/index.d.ts +16 -5
  68. package/lib/openai/index.d.ts.map +1 -0
  69. package/lib/{esm/openai → openai}/index.js +242 -141
  70. package/lib/openai/index.js.map +1 -0
  71. package/lib/{types/openai → openai}/openai.d.ts +3 -3
  72. package/lib/openai/openai.d.ts.map +1 -0
  73. package/lib/openai/openai.js +15 -0
  74. package/lib/openai/openai.js.map +1 -0
  75. package/lib/{types/openai → openai}/openai_compatible.d.ts +3 -3
  76. package/lib/openai/openai_compatible.d.ts.map +1 -0
  77. package/lib/{esm/openai → openai}/openai_compatible.js +14 -11
  78. package/lib/openai/openai_compatible.js.map +1 -0
  79. package/lib/{types/openai → openai}/openai_format.d.ts +3 -2
  80. package/lib/openai/openai_format.d.ts.map +1 -0
  81. package/lib/{esm/openai → openai}/openai_format.js +66 -24
  82. package/lib/openai/openai_format.js.map +1 -0
  83. package/lib/{types/replicate.d.ts → replicate.d.ts} +3 -2
  84. package/lib/replicate.d.ts.map +1 -0
  85. package/lib/{esm/replicate.js → replicate.js} +59 -49
  86. package/lib/replicate.js.map +1 -0
  87. package/lib/{types/shared → shared}/claude-messages.d.ts +25 -1
  88. package/lib/shared/claude-messages.d.ts.map +1 -0
  89. package/lib/{esm/shared → shared}/claude-messages.js +212 -59
  90. package/lib/shared/claude-messages.js.map +1 -0
  91. package/lib/{types/shared → shared}/claude-thinking.d.ts +1 -1
  92. package/lib/shared/claude-thinking.d.ts.map +1 -0
  93. package/lib/{esm/shared → shared}/claude-thinking.js +5 -7
  94. package/lib/shared/claude-thinking.js.map +1 -0
  95. package/lib/shared/debug-prompt.d.ts +5 -0
  96. package/lib/shared/debug-prompt.d.ts.map +1 -0
  97. package/lib/shared/debug-prompt.js +25 -0
  98. package/lib/shared/debug-prompt.js.map +1 -0
  99. package/lib/{types/test-driver → test-driver}/TestErrorCompletionStream.d.ts +1 -1
  100. package/lib/test-driver/TestErrorCompletionStream.d.ts.map +1 -0
  101. package/lib/test-driver/TestErrorCompletionStream.js +16 -0
  102. package/lib/test-driver/TestErrorCompletionStream.js.map +1 -0
  103. package/lib/{types/test-driver → test-driver}/TestValidationErrorCompletionStream.d.ts +1 -1
  104. package/lib/test-driver/TestValidationErrorCompletionStream.d.ts.map +1 -0
  105. package/lib/{esm/test-driver → test-driver}/TestValidationErrorCompletionStream.js +4 -4
  106. package/lib/test-driver/TestValidationErrorCompletionStream.js.map +1 -0
  107. package/lib/{types/test-driver → test-driver}/index.d.ts +3 -3
  108. package/lib/test-driver/index.d.ts.map +1 -0
  109. package/lib/{esm/test-driver → test-driver}/index.js +20 -20
  110. package/lib/test-driver/index.js.map +1 -0
  111. package/lib/{types/test-driver → test-driver}/utils.d.ts +1 -1
  112. package/lib/test-driver/utils.d.ts.map +1 -0
  113. package/lib/{esm/test-driver → test-driver}/utils.js +4 -4
  114. package/lib/test-driver/utils.js.map +1 -0
  115. package/lib/togetherai/index.d.ts +15 -0
  116. package/lib/togetherai/index.d.ts.map +1 -0
  117. package/lib/togetherai/index.js +54 -0
  118. package/lib/togetherai/index.js.map +1 -0
  119. package/lib/{types/togetherai → togetherai}/interfaces.d.ts +1 -1
  120. package/lib/togetherai/interfaces.d.ts.map +1 -0
  121. package/lib/{cjs/watsonx → togetherai}/interfaces.js.map +1 -1
  122. package/lib/vertexai/debug.d.ts +2 -0
  123. package/lib/vertexai/debug.d.ts.map +1 -0
  124. package/lib/{esm/vertexai → vertexai}/debug.js +1 -1
  125. package/lib/vertexai/debug.js.map +1 -0
  126. package/lib/vertexai/embeddings/embed-legacy-multimodal.d.ts +9 -0
  127. package/lib/vertexai/embeddings/embed-legacy-multimodal.d.ts.map +1 -0
  128. package/lib/vertexai/embeddings/embed-legacy-multimodal.js +141 -0
  129. package/lib/vertexai/embeddings/embed-legacy-multimodal.js.map +1 -0
  130. package/lib/vertexai/embeddings/embed.d.ts +13 -0
  131. package/lib/vertexai/embeddings/embed.d.ts.map +1 -0
  132. package/lib/vertexai/embeddings/embed.js +162 -0
  133. package/lib/vertexai/embeddings/embed.js.map +1 -0
  134. package/lib/vertexai/embeddings/source-utils.d.ts +9 -0
  135. package/lib/vertexai/embeddings/source-utils.d.ts.map +1 -0
  136. package/lib/vertexai/embeddings/source-utils.js +18 -0
  137. package/lib/vertexai/embeddings/source-utils.js.map +1 -0
  138. package/lib/{types/vertexai → vertexai}/index.d.ts +31 -19
  139. package/lib/vertexai/index.d.ts.map +1 -0
  140. package/lib/{esm/vertexai → vertexai}/index.js +221 -159
  141. package/lib/vertexai/index.js.map +1 -0
  142. package/lib/{types/vertexai → vertexai}/models/claude.d.ts +4 -4
  143. package/lib/vertexai/models/claude.d.ts.map +1 -0
  144. package/lib/{esm/vertexai → vertexai}/models/claude.js +17 -20
  145. package/lib/vertexai/models/claude.js.map +1 -0
  146. package/lib/{types/vertexai → vertexai}/models/gemini.d.ts +28 -4
  147. package/lib/vertexai/models/gemini.d.ts.map +1 -0
  148. package/lib/{esm/vertexai → vertexai}/models/gemini.js +238 -116
  149. package/lib/vertexai/models/gemini.js.map +1 -0
  150. package/lib/{types/vertexai → vertexai}/models/imagen.d.ts +12 -11
  151. package/lib/vertexai/models/imagen.d.ts.map +1 -0
  152. package/lib/{esm/vertexai → vertexai}/models/imagen.js +74 -47
  153. package/lib/vertexai/models/imagen.js.map +1 -0
  154. package/lib/{types/vertexai → vertexai}/models/llama.d.ts +4 -4
  155. package/lib/vertexai/models/llama.d.ts.map +1 -0
  156. package/lib/{esm/vertexai → vertexai}/models/llama.js +37 -33
  157. package/lib/vertexai/models/llama.js.map +1 -0
  158. package/lib/vertexai/models.d.ts +21 -0
  159. package/lib/vertexai/models.d.ts.map +1 -0
  160. package/lib/{esm/vertexai → vertexai}/models.js +12 -9
  161. package/lib/vertexai/models.js.map +1 -0
  162. package/lib/{types/watsonx → watsonx}/index.d.ts +4 -3
  163. package/lib/watsonx/index.d.ts.map +1 -0
  164. package/lib/{esm/watsonx → watsonx}/index.js +69 -41
  165. package/lib/watsonx/index.js.map +1 -0
  166. package/lib/watsonx/interfaces.d.ts.map +1 -0
  167. package/lib/{esm/watsonx → watsonx}/interfaces.js.map +1 -1
  168. package/lib/{types/xai → xai}/index.d.ts +4 -4
  169. package/lib/xai/index.d.ts.map +1 -0
  170. package/lib/{esm/xai → xai}/index.js +22 -18
  171. package/lib/xai/index.js.map +1 -0
  172. package/package.json +87 -36
  173. package/src/adobe/firefly.ts +60 -43
  174. package/src/anthropic/index.ts +37 -20
  175. package/src/azure/azure_foundry.ts +210 -165
  176. package/src/bedrock/converse.ts +124 -101
  177. package/src/bedrock/embeddings.test.ts +508 -0
  178. package/src/bedrock/embeddings.ts +517 -0
  179. package/src/bedrock/error-handling.test.ts +62 -14
  180. package/src/bedrock/index.ts +832 -466
  181. package/src/bedrock/nova-image-payload.ts +98 -91
  182. package/src/bedrock/payloads.ts +9 -9
  183. package/src/bedrock/s3.test.ts +39 -0
  184. package/src/bedrock/s3.ts +57 -38
  185. package/src/bedrock/streaming-tool-use.test.ts +86 -69
  186. package/src/bedrock/twelvelabs.ts +35 -32
  187. package/src/groq/index.ts +143 -60
  188. package/src/http-timeout-wiring.test.ts +263 -0
  189. package/src/huggingface_ie.ts +45 -61
  190. package/src/index.ts +15 -16
  191. package/src/mistral/index.ts +97 -48
  192. package/src/mistral/types.ts +13 -12
  193. package/src/openai/azure_openai.ts +35 -27
  194. package/src/openai/drivers.ts +9 -0
  195. package/src/openai/error-handling.test.ts +308 -113
  196. package/src/openai/index.ts +378 -248
  197. package/src/openai/openai.ts +6 -13
  198. package/src/openai/openai_compatible.ts +35 -25
  199. package/src/openai/openai_format.ts +90 -40
  200. package/src/replicate.ts +108 -86
  201. package/src/shared/claude-messages.test.ts +37 -0
  202. package/src/shared/claude-messages.ts +303 -97
  203. package/src/shared/claude-thinking.ts +6 -12
  204. package/src/shared/debug-prompt.ts +28 -0
  205. package/src/test-driver/TestErrorCompletionStream.ts +9 -10
  206. package/src/test-driver/TestValidationErrorCompletionStream.ts +9 -10
  207. package/src/test-driver/index.ts +43 -27
  208. package/src/test-driver/utils.ts +8 -8
  209. package/src/togetherai/index.test.ts +32 -0
  210. package/src/togetherai/index.ts +64 -128
  211. package/src/togetherai/interfaces.ts +5 -5
  212. package/src/vertexai/debug.ts +3 -3
  213. package/src/vertexai/embeddings/embed-legacy-multimodal.ts +211 -0
  214. package/src/vertexai/embeddings/embed.ts +206 -0
  215. package/src/vertexai/embeddings/embeddings.test.ts +497 -0
  216. package/src/vertexai/embeddings/source-utils.test.ts +54 -0
  217. package/src/vertexai/embeddings/source-utils.ts +29 -0
  218. package/src/vertexai/index.ts +331 -244
  219. package/src/vertexai/models/claude-error-handling.test.ts +83 -36
  220. package/src/vertexai/models/claude-streaming-spacing.test.ts +82 -75
  221. package/src/vertexai/models/claude.ts +55 -40
  222. package/src/vertexai/models/gemini-conversation-mutation.test.ts +65 -23
  223. package/src/vertexai/models/gemini-error-handling.test.ts +126 -10
  224. package/src/vertexai/models/gemini-orphaned-tool-result.test.ts +118 -0
  225. package/src/vertexai/models/gemini.ts +349 -172
  226. package/src/vertexai/models/imagen.ts +164 -100
  227. package/src/vertexai/models/llama.ts +70 -48
  228. package/src/vertexai/models.ts +36 -16
  229. package/src/watsonx/index.ts +101 -65
  230. package/src/watsonx/interfaces.ts +10 -15
  231. package/src/xai/index.ts +30 -30
  232. package/lib/cjs/adobe/firefly.js +0 -120
  233. package/lib/cjs/adobe/firefly.js.map +0 -1
  234. package/lib/cjs/anthropic/index.js +0 -64
  235. package/lib/cjs/anthropic/index.js.map +0 -1
  236. package/lib/cjs/azure/azure_foundry.js +0 -432
  237. package/lib/cjs/azure/azure_foundry.js.map +0 -1
  238. package/lib/cjs/bedrock/converse.js +0 -359
  239. package/lib/cjs/bedrock/converse.js.map +0 -1
  240. package/lib/cjs/bedrock/index.js +0 -1508
  241. package/lib/cjs/bedrock/index.js.map +0 -1
  242. package/lib/cjs/bedrock/nova-image-payload.js +0 -207
  243. package/lib/cjs/bedrock/nova-image-payload.js.map +0 -1
  244. package/lib/cjs/bedrock/payloads.js +0 -3
  245. package/lib/cjs/bedrock/s3.js +0 -107
  246. package/lib/cjs/bedrock/s3.js.map +0 -1
  247. package/lib/cjs/bedrock/twelvelabs.js +0 -87
  248. package/lib/cjs/bedrock/twelvelabs.js.map +0 -1
  249. package/lib/cjs/groq/index.js +0 -328
  250. package/lib/cjs/groq/index.js.map +0 -1
  251. package/lib/cjs/huggingface_ie.js +0 -201
  252. package/lib/cjs/huggingface_ie.js.map +0 -1
  253. package/lib/cjs/index.js +0 -32
  254. package/lib/cjs/index.js.map +0 -1
  255. package/lib/cjs/mistral/index.js +0 -176
  256. package/lib/cjs/mistral/index.js.map +0 -1
  257. package/lib/cjs/mistral/types.js +0 -83
  258. package/lib/cjs/mistral/types.js.map +0 -1
  259. package/lib/cjs/openai/azure_openai.js +0 -72
  260. package/lib/cjs/openai/azure_openai.js.map +0 -1
  261. package/lib/cjs/openai/index.js +0 -1135
  262. package/lib/cjs/openai/index.js.map +0 -1
  263. package/lib/cjs/openai/openai.js +0 -21
  264. package/lib/cjs/openai/openai.js.map +0 -1
  265. package/lib/cjs/openai/openai_compatible.js +0 -63
  266. package/lib/cjs/openai/openai_compatible.js.map +0 -1
  267. package/lib/cjs/openai/openai_format.js +0 -131
  268. package/lib/cjs/openai/openai_format.js.map +0 -1
  269. package/lib/cjs/package.json +0 -3
  270. package/lib/cjs/replicate.js +0 -275
  271. package/lib/cjs/replicate.js.map +0 -1
  272. package/lib/cjs/shared/claude-messages.js +0 -737
  273. package/lib/cjs/shared/claude-messages.js.map +0 -1
  274. package/lib/cjs/shared/claude-thinking.js +0 -60
  275. package/lib/cjs/shared/claude-thinking.js.map +0 -1
  276. package/lib/cjs/test-driver/TestErrorCompletionStream.js +0 -20
  277. package/lib/cjs/test-driver/TestErrorCompletionStream.js.map +0 -1
  278. package/lib/cjs/test-driver/TestValidationErrorCompletionStream.js +0 -24
  279. package/lib/cjs/test-driver/TestValidationErrorCompletionStream.js.map +0 -1
  280. package/lib/cjs/test-driver/index.js +0 -109
  281. package/lib/cjs/test-driver/index.js.map +0 -1
  282. package/lib/cjs/test-driver/utils.js +0 -30
  283. package/lib/cjs/test-driver/utils.js.map +0 -1
  284. package/lib/cjs/togetherai/index.js +0 -126
  285. package/lib/cjs/togetherai/index.js.map +0 -1
  286. package/lib/cjs/togetherai/interfaces.js +0 -3
  287. package/lib/cjs/togetherai/interfaces.js.map +0 -1
  288. package/lib/cjs/vertexai/debug.js +0 -12
  289. package/lib/cjs/vertexai/debug.js.map +0 -1
  290. package/lib/cjs/vertexai/embeddings/embeddings-image.js +0 -27
  291. package/lib/cjs/vertexai/embeddings/embeddings-image.js.map +0 -1
  292. package/lib/cjs/vertexai/embeddings/embeddings-text.js +0 -23
  293. package/lib/cjs/vertexai/embeddings/embeddings-text.js.map +0 -1
  294. package/lib/cjs/vertexai/index.js +0 -644
  295. package/lib/cjs/vertexai/index.js.map +0 -1
  296. package/lib/cjs/vertexai/models/claude.js +0 -72
  297. package/lib/cjs/vertexai/models/claude.js.map +0 -1
  298. package/lib/cjs/vertexai/models/gemini.js +0 -864
  299. package/lib/cjs/vertexai/models/gemini.js.map +0 -1
  300. package/lib/cjs/vertexai/models/imagen.js +0 -303
  301. package/lib/cjs/vertexai/models/imagen.js.map +0 -1
  302. package/lib/cjs/vertexai/models/llama.js +0 -183
  303. package/lib/cjs/vertexai/models/llama.js.map +0 -1
  304. package/lib/cjs/vertexai/models.js +0 -35
  305. package/lib/cjs/vertexai/models.js.map +0 -1
  306. package/lib/cjs/watsonx/index.js +0 -161
  307. package/lib/cjs/watsonx/index.js.map +0 -1
  308. package/lib/cjs/watsonx/interfaces.js +0 -3
  309. package/lib/cjs/xai/index.js +0 -65
  310. package/lib/cjs/xai/index.js.map +0 -1
  311. package/lib/esm/adobe/firefly.js +0 -116
  312. package/lib/esm/adobe/firefly.js.map +0 -1
  313. package/lib/esm/anthropic/index.js.map +0 -1
  314. package/lib/esm/azure/azure_foundry.js.map +0 -1
  315. package/lib/esm/bedrock/converse.js.map +0 -1
  316. package/lib/esm/bedrock/index.js.map +0 -1
  317. package/lib/esm/bedrock/nova-image-payload.js.map +0 -1
  318. package/lib/esm/bedrock/payloads.js.map +0 -1
  319. package/lib/esm/bedrock/s3.js.map +0 -1
  320. package/lib/esm/bedrock/twelvelabs.js.map +0 -1
  321. package/lib/esm/groq/index.js.map +0 -1
  322. package/lib/esm/huggingface_ie.js.map +0 -1
  323. package/lib/esm/index.js +0 -16
  324. package/lib/esm/index.js.map +0 -1
  325. package/lib/esm/mistral/index.js.map +0 -1
  326. package/lib/esm/mistral/types.js.map +0 -1
  327. package/lib/esm/openai/azure_openai.js.map +0 -1
  328. package/lib/esm/openai/index.js.map +0 -1
  329. package/lib/esm/openai/openai.js +0 -14
  330. package/lib/esm/openai/openai.js.map +0 -1
  331. package/lib/esm/openai/openai_compatible.js.map +0 -1
  332. package/lib/esm/openai/openai_format.js.map +0 -1
  333. package/lib/esm/replicate.js.map +0 -1
  334. package/lib/esm/shared/claude-messages.js.map +0 -1
  335. package/lib/esm/shared/claude-thinking.js.map +0 -1
  336. package/lib/esm/test-driver/TestErrorCompletionStream.js +0 -16
  337. package/lib/esm/test-driver/TestErrorCompletionStream.js.map +0 -1
  338. package/lib/esm/test-driver/TestValidationErrorCompletionStream.js.map +0 -1
  339. package/lib/esm/test-driver/index.js.map +0 -1
  340. package/lib/esm/test-driver/utils.js.map +0 -1
  341. package/lib/esm/togetherai/index.js +0 -122
  342. package/lib/esm/togetherai/index.js.map +0 -1
  343. package/lib/esm/togetherai/interfaces.js.map +0 -1
  344. package/lib/esm/vertexai/debug.js.map +0 -1
  345. package/lib/esm/vertexai/embeddings/embeddings-image.js +0 -24
  346. package/lib/esm/vertexai/embeddings/embeddings-image.js.map +0 -1
  347. package/lib/esm/vertexai/embeddings/embeddings-text.js +0 -20
  348. package/lib/esm/vertexai/embeddings/embeddings-text.js.map +0 -1
  349. package/lib/esm/vertexai/index.js.map +0 -1
  350. package/lib/esm/vertexai/models/claude.js.map +0 -1
  351. package/lib/esm/vertexai/models/gemini.js.map +0 -1
  352. package/lib/esm/vertexai/models/imagen.js.map +0 -1
  353. package/lib/esm/vertexai/models/llama.js.map +0 -1
  354. package/lib/esm/vertexai/models.js.map +0 -1
  355. package/lib/esm/watsonx/index.js.map +0 -1
  356. package/lib/esm/xai/index.js.map +0 -1
  357. package/lib/types/adobe/firefly.d.ts.map +0 -1
  358. package/lib/types/anthropic/index.d.ts.map +0 -1
  359. package/lib/types/azure/azure_foundry.d.ts.map +0 -1
  360. package/lib/types/bedrock/converse.d.ts.map +0 -1
  361. package/lib/types/bedrock/index.d.ts.map +0 -1
  362. package/lib/types/bedrock/nova-image-payload.d.ts.map +0 -1
  363. package/lib/types/bedrock/payloads.d.ts.map +0 -1
  364. package/lib/types/bedrock/s3.d.ts.map +0 -1
  365. package/lib/types/bedrock/twelvelabs.d.ts.map +0 -1
  366. package/lib/types/groq/index.d.ts.map +0 -1
  367. package/lib/types/huggingface_ie.d.ts.map +0 -1
  368. package/lib/types/index.d.ts +0 -16
  369. package/lib/types/index.d.ts.map +0 -1
  370. package/lib/types/mistral/index.d.ts.map +0 -1
  371. package/lib/types/mistral/types.d.ts.map +0 -1
  372. package/lib/types/openai/azure_openai.d.ts.map +0 -1
  373. package/lib/types/openai/index.d.ts.map +0 -1
  374. package/lib/types/openai/openai.d.ts.map +0 -1
  375. package/lib/types/openai/openai_compatible.d.ts.map +0 -1
  376. package/lib/types/openai/openai_format.d.ts.map +0 -1
  377. package/lib/types/replicate.d.ts.map +0 -1
  378. package/lib/types/shared/claude-messages.d.ts.map +0 -1
  379. package/lib/types/shared/claude-thinking.d.ts.map +0 -1
  380. package/lib/types/test-driver/TestErrorCompletionStream.d.ts.map +0 -1
  381. package/lib/types/test-driver/TestValidationErrorCompletionStream.d.ts.map +0 -1
  382. package/lib/types/test-driver/index.d.ts.map +0 -1
  383. package/lib/types/test-driver/utils.d.ts.map +0 -1
  384. package/lib/types/togetherai/index.d.ts +0 -23
  385. package/lib/types/togetherai/index.d.ts.map +0 -1
  386. package/lib/types/togetherai/interfaces.d.ts.map +0 -1
  387. package/lib/types/vertexai/debug.d.ts +0 -2
  388. package/lib/types/vertexai/debug.d.ts.map +0 -1
  389. package/lib/types/vertexai/embeddings/embeddings-image.d.ts +0 -11
  390. package/lib/types/vertexai/embeddings/embeddings-image.d.ts.map +0 -1
  391. package/lib/types/vertexai/embeddings/embeddings-text.d.ts +0 -10
  392. package/lib/types/vertexai/embeddings/embeddings-text.d.ts.map +0 -1
  393. package/lib/types/vertexai/index.d.ts.map +0 -1
  394. package/lib/types/vertexai/models/claude.d.ts.map +0 -1
  395. package/lib/types/vertexai/models/gemini.d.ts.map +0 -1
  396. package/lib/types/vertexai/models/imagen.d.ts.map +0 -1
  397. package/lib/types/vertexai/models/llama.d.ts.map +0 -1
  398. package/lib/types/vertexai/models.d.ts +0 -20
  399. package/lib/types/vertexai/models.d.ts.map +0 -1
  400. package/lib/types/watsonx/index.d.ts.map +0 -1
  401. package/lib/types/watsonx/interfaces.d.ts.map +0 -1
  402. package/lib/types/xai/index.d.ts.map +0 -1
  403. package/src/vertexai/embeddings/embeddings-image.ts +0 -52
  404. package/src/vertexai/embeddings/embeddings-text.ts +0 -54
  405. /package/lib/{esm/bedrock → bedrock}/payloads.js +0 -0
  406. /package/lib/{esm/mistral → mistral}/types.js +0 -0
  407. /package/lib/{esm/togetherai → togetherai}/interfaces.js +0 -0
  408. /package/lib/{types/watsonx → watsonx}/interfaces.d.ts +0 -0
  409. /package/lib/{esm/watsonx → watsonx}/interfaces.js +0 -0
@@ -1,15 +1,19 @@
1
- import { Bedrock, CreateModelCustomizationJobCommand, GetModelCustomizationJobCommand, ModelCustomizationJobStatus, ModelModality, StopModelCustomizationJobCommand } from "@aws-sdk/client-bedrock";
2
- import { BedrockRuntime } from "@aws-sdk/client-bedrock-runtime";
3
- import { S3Client } from "@aws-sdk/client-s3";
4
- import { AbstractDriver, deserializeBinaryFromStorage, getConversationMeta, getMaxTokensLimitBedrock, getModelCapabilities, incrementConversationTurn, isClaudeVersionGTE, LlumiverseError, modelModalitiesToArray, stripBinaryFromConversation, stripHeartbeatsFromConversation, TrainingJobStatus, truncateLargeTextInConversation } from "@llumiverse/core";
5
- import { transformAsyncIterator } from "@llumiverse/core/async";
6
- import { formatNovaPrompt } from "@llumiverse/core/formatters";
7
- import { LRUCache } from "mnemonist";
8
- import { resolveClaudeThinking } from "../shared/claude-thinking.js";
9
- import { converseConcatMessages, converseJSONprefill, converseSystemToMessages, formatConversePrompt } from "./converse.js";
10
- import { formatNovaImageGenerationPayload, NovaImageGenerationTaskType } from "./nova-image-payload.js";
11
- import { forceUploadFile } from "./s3.js";
12
- import { formatTwelvelabsPegasusPrompt } from "./twelvelabs.js";
1
+ import { Bedrock, CreateModelCustomizationJobCommand, GetModelCustomizationJobCommand, ModelCustomizationJobStatus, ModelModality, StopModelCustomizationJobCommand, } from '@aws-sdk/client-bedrock';
2
+ import { BedrockRuntime, } from '@aws-sdk/client-bedrock-runtime';
3
+ import { S3Client } from '@aws-sdk/client-s3';
4
+ import { deserializeBinaryFromStorage, getConversationMeta, getMaxTokensLimitBedrock, getModelCapabilities, incrementConversationTurn, isClaudeVersionGTE, LlumiverseError, modelModalitiesToArray, stripBinaryFromConversation, stripHeartbeatsFromConversation, TrainingJobStatus, truncateLargeTextInConversation, } from '@llumiverse/core';
5
+ import { transformAsyncIterator } from '@llumiverse/core/async';
6
+ import { AbstractDriver } from '@llumiverse/core/driver';
7
+ import { formatNovaPrompt } from '@llumiverse/core/formatters';
8
+ import { mergeDriverHttpTimeoutOptions, resolveDriverHttpTimeouts } from '@llumiverse/core/http-agent';
9
+ import { LRUCache } from 'mnemonist';
10
+ import { resolveClaudeThinking } from '../shared/claude-thinking.js';
11
+ import { truncateBinaryForDebug, uint8ArrayToBase64ForDebug } from '../shared/debug-prompt.js';
12
+ import { converseConcatMessages, converseJSONprefill, converseSystemToMessages, formatConversePrompt, } from './converse.js';
13
+ import { generateBedrockEmbeddings } from './embeddings.js';
14
+ import { formatNovaImageGenerationPayload, NovaImageGenerationTaskType } from './nova-image-payload.js';
15
+ import { forceUploadFile } from './s3.js';
16
+ import { formatTwelvelabsPegasusPrompt } from './twelvelabs.js';
13
17
  const supportStreamingCache = new LRUCache(4096);
14
18
  var BedrockModelType;
15
19
  (function (BedrockModelType) {
@@ -18,22 +22,36 @@ var BedrockModelType;
18
22
  BedrockModelType["CustomModel"] = "custom-model";
19
23
  BedrockModelType["Unknown"] = "unknown";
20
24
  })(BedrockModelType || (BedrockModelType = {}));
21
- ;
22
25
  function converseFinishReason(reason) {
23
26
  //Possible values:
24
27
  //end_turn | tool_use | max_tokens | stop_sequence | guardrail_intervened | content_filtered
25
28
  if (!reason)
26
29
  return undefined;
27
30
  switch (reason) {
28
- case 'end_turn': return "stop";
29
- case 'max_tokens': return "length";
30
- default: return reason;
31
+ case 'end_turn':
32
+ return 'stop';
33
+ case 'max_tokens':
34
+ return 'length';
35
+ default:
36
+ return reason;
31
37
  }
32
38
  }
39
+ function withBedrockRuntimeScope(iterable, scope) {
40
+ return {
41
+ async *[Symbol.asyncIterator]() {
42
+ try {
43
+ yield* iterable;
44
+ }
45
+ finally {
46
+ scope.close();
47
+ }
48
+ },
49
+ };
50
+ }
33
51
  //Used to get a max_token value when not specified in the model options. Claude requires it to be set.
34
52
  function maxTokenFallbackClaude(option) {
35
53
  const modelOptions = option.model_options;
36
- if (modelOptions && typeof modelOptions.max_tokens === "number") {
54
+ if (modelOptions && typeof modelOptions.max_tokens === 'number') {
37
55
  return modelOptions.max_tokens;
38
56
  }
39
57
  else {
@@ -45,8 +63,166 @@ function maxTokenFallbackClaude(option) {
45
63
  return maxSupportedTokens;
46
64
  }
47
65
  }
66
+ function formatBedrockBytes(bytes) {
67
+ if (bytes instanceof Uint8Array) {
68
+ return truncateBinaryForDebug(uint8ArrayToBase64ForDebug(bytes));
69
+ }
70
+ if (typeof bytes === 'string') {
71
+ return truncateBinaryForDebug(bytes);
72
+ }
73
+ return bytes;
74
+ }
75
+ function formatBedrockBytesForDebug(bytes) {
76
+ // AWS SDK prompt types require Uint8Array here, but the debug prompt returned to
77
+ // Studio must be JSON-safe. Keep the mismatch contained to this conversion.
78
+ return formatBedrockBytes(bytes);
79
+ }
80
+ function formatBedrockContentBlockForDebug(block) {
81
+ if (block.image?.source?.bytes) {
82
+ return {
83
+ ...block,
84
+ image: {
85
+ ...block.image,
86
+ source: {
87
+ ...block.image.source,
88
+ bytes: formatBedrockBytesForDebug(block.image.source.bytes),
89
+ },
90
+ },
91
+ };
92
+ }
93
+ if (block.document?.source?.bytes) {
94
+ return {
95
+ ...block,
96
+ document: {
97
+ ...block.document,
98
+ source: {
99
+ ...block.document.source,
100
+ bytes: formatBedrockBytesForDebug(block.document.source.bytes),
101
+ },
102
+ },
103
+ };
104
+ }
105
+ if (block.video?.source?.bytes) {
106
+ return {
107
+ ...block,
108
+ video: {
109
+ ...block.video,
110
+ source: {
111
+ ...block.video.source,
112
+ bytes: formatBedrockBytesForDebug(block.video.source.bytes),
113
+ },
114
+ },
115
+ };
116
+ }
117
+ if (block.toolResult?.content) {
118
+ return {
119
+ ...block,
120
+ toolResult: {
121
+ ...block.toolResult,
122
+ content: block.toolResult.content.map(formatBedrockToolResultContentBlockForDebug),
123
+ },
124
+ };
125
+ }
126
+ return block;
127
+ }
128
+ function formatBedrockToolResultContentBlockForDebug(block) {
129
+ if (block.image?.source?.bytes) {
130
+ return {
131
+ ...block,
132
+ image: {
133
+ ...block.image,
134
+ source: {
135
+ ...block.image.source,
136
+ bytes: formatBedrockBytesForDebug(block.image.source.bytes),
137
+ },
138
+ },
139
+ };
140
+ }
141
+ if (block.document?.source?.bytes) {
142
+ return {
143
+ ...block,
144
+ document: {
145
+ ...block.document,
146
+ source: {
147
+ ...block.document.source,
148
+ bytes: formatBedrockBytesForDebug(block.document.source.bytes),
149
+ },
150
+ },
151
+ };
152
+ }
153
+ if (block.video?.source?.bytes) {
154
+ return {
155
+ ...block,
156
+ video: {
157
+ ...block.video,
158
+ source: {
159
+ ...block.video.source,
160
+ bytes: formatBedrockBytesForDebug(block.video.source.bytes),
161
+ },
162
+ },
163
+ };
164
+ }
165
+ return block;
166
+ }
167
+ function formatConversePromptForDebug(prompt) {
168
+ return {
169
+ ...prompt,
170
+ messages: prompt.messages?.map((message) => ({
171
+ ...message,
172
+ content: message.content?.map(formatBedrockContentBlockForDebug),
173
+ })),
174
+ };
175
+ }
176
+ function formatNovaPromptForDebug(prompt) {
177
+ return {
178
+ ...prompt,
179
+ messages: prompt.messages.map((message) => ({
180
+ ...message,
181
+ content: message.content.map((part) => {
182
+ if (!part.image?.source.bytes && !part.video?.source.bytes) {
183
+ return part;
184
+ }
185
+ return {
186
+ ...part,
187
+ image: part.image
188
+ ? {
189
+ ...part.image,
190
+ source: {
191
+ ...part.image.source,
192
+ bytes: truncateBinaryForDebug(part.image.source.bytes),
193
+ },
194
+ }
195
+ : undefined,
196
+ video: part.video
197
+ ? {
198
+ ...part.video,
199
+ source: {
200
+ ...part.video.source,
201
+ bytes: part.video.source.bytes
202
+ ? truncateBinaryForDebug(part.video.source.bytes)
203
+ : undefined,
204
+ },
205
+ }
206
+ : undefined,
207
+ };
208
+ }),
209
+ })),
210
+ };
211
+ }
212
+ function formatTwelvelabsPromptForDebug(prompt) {
213
+ if (!prompt.mediaSource.base64String) {
214
+ return prompt;
215
+ }
216
+ return {
217
+ ...prompt,
218
+ mediaSource: {
219
+ ...prompt.mediaSource,
220
+ base64String: truncateBinaryForDebug(prompt.mediaSource.base64String),
221
+ },
222
+ };
223
+ }
48
224
  export class BedrockDriver extends AbstractDriver {
49
- static PROVIDER = "bedrock";
225
+ static PROVIDER = 'bedrock';
50
226
  provider = BedrockDriver.PROVIDER;
51
227
  _executor;
52
228
  _service;
@@ -57,34 +233,79 @@ export class BedrockDriver extends AbstractDriver {
57
233
  throw new Error("No region found. Set the region in the environment's endpoint URL.");
58
234
  }
59
235
  }
60
- getExecutor() {
236
+ /**
237
+ * Build a Smithy `requestHandler` config from the driver's
238
+ * `httpTimeout` so AWS SDK calls fail fast on hung upstream Bedrock
239
+ * endpoints instead of using the AWS default (no request timeout).
240
+ * Returns a partial config the SDK merges into its default handler.
241
+ */
242
+ getBedrockRequestHandlerConfig(httpTimeout) {
243
+ const timeouts = resolveDriverHttpTimeouts(mergeDriverHttpTimeoutOptions(this.options.httpTimeout, httpTimeout));
244
+ return {
245
+ requestTimeout: timeouts.headersTimeout,
246
+ throwOnRequestTimeout: true,
247
+ connectionTimeout: timeouts.connectTimeout,
248
+ socketTimeout: timeouts.bodyTimeout,
249
+ };
250
+ }
251
+ createExecutor(httpTimeout) {
252
+ return new BedrockRuntime({
253
+ region: this.options.region,
254
+ credentials: this.options.credentials,
255
+ requestHandler: this.getBedrockRequestHandlerConfig(httpTimeout),
256
+ });
257
+ }
258
+ getExecutor(httpTimeout) {
259
+ if (httpTimeout) {
260
+ return this.createExecutor(httpTimeout);
261
+ }
61
262
  if (!this._executor) {
62
- this._executor = new BedrockRuntime({
63
- region: this.options.region,
64
- credentials: this.options.credentials,
65
- });
263
+ this._executor = this.createExecutor();
66
264
  }
67
265
  return this._executor;
68
266
  }
267
+ getScopedExecutor(options) {
268
+ if (!options.httpTimeout) {
269
+ return {
270
+ executor: this.getExecutor(),
271
+ close: () => undefined,
272
+ };
273
+ }
274
+ const executor = this.getExecutor(options.httpTimeout);
275
+ return {
276
+ executor,
277
+ close: () => executor.destroy(),
278
+ };
279
+ }
69
280
  getService(region = this.options.region) {
70
281
  if (!this._service || this._service_region !== region) {
71
282
  this._service = new Bedrock({
72
283
  region: region,
73
284
  credentials: this.options.credentials,
285
+ requestHandler: this.getBedrockRequestHandlerConfig(),
74
286
  });
75
287
  this._service_region = region;
76
288
  }
77
289
  return this._service;
78
290
  }
79
291
  async formatPrompt(segments, opts) {
80
- if (opts.model.includes("canvas")) {
292
+ if (opts.model.includes('canvas')) {
81
293
  return await formatNovaPrompt(segments, opts.result_schema);
82
294
  }
83
- if (opts.model.includes("twelvelabs.pegasus")) {
295
+ if (opts.model.includes('twelvelabs.pegasus')) {
84
296
  return await formatTwelvelabsPegasusPrompt(segments, opts);
85
297
  }
86
298
  return await formatConversePrompt(segments, opts);
87
299
  }
300
+ formatDebugPrompt(prompt) {
301
+ if ('mediaSource' in prompt) {
302
+ return formatTwelvelabsPromptForDebug(prompt);
303
+ }
304
+ if ('modelId' in prompt) {
305
+ return formatConversePromptForDebug(prompt);
306
+ }
307
+ return formatNovaPromptForDebug(prompt);
308
+ }
88
309
  /**
89
310
  * Format AWS Bedrock errors into LlumiverseError with proper status codes and retryability.
90
311
  *
@@ -139,8 +360,7 @@ export class BedrockDriver extends AbstractDriver {
139
360
  // Determine retryability based on AWS error types
140
361
  const retryable = this.isBedrockErrorRetryable(errorName, httpStatusCode, fault);
141
362
  return new LlumiverseError(`[${this.provider}] ${userMessage}`, retryable, context, error, httpStatusCode, // Only set code if we have numeric status code
142
- errorName // Preserve AWS error name
143
- );
363
+ errorName);
144
364
  }
145
365
  /**
146
366
  * Determine if a Bedrock error is retryable based on error type and status.
@@ -204,8 +424,8 @@ export class BedrockDriver extends AbstractDriver {
204
424
  return undefined;
205
425
  }
206
426
  getExtractedExecution(result, _prompt, options) {
207
- let resultText = "";
208
- let reasoning = "";
427
+ let resultText = '';
428
+ let reasoning = '';
209
429
  if (result.output?.message?.content) {
210
430
  for (const content of result.output.message.content) {
211
431
  // Get text output
@@ -228,13 +448,13 @@ export class BedrockDriver extends AbstractDriver {
228
448
  }
229
449
  }
230
450
  else {
231
- this.logger.info("[Bedrock] Not outputting reasoning content as include_thoughts is false");
451
+ this.logger.info('[Bedrock] Not outputting reasoning content as include_thoughts is false');
232
452
  }
233
453
  }
234
454
  else {
235
455
  // Get content block type
236
- const type = Object.keys(content).find(key => key !== '$unknown' && content[key] !== undefined);
237
- this.logger.info({ type }, "[Bedrock] Unsupported content response type:");
456
+ const type = Object.keys(content).find((key) => key !== '$unknown' && content[key] !== undefined);
457
+ this.logger.info({ type }, '[Bedrock] Unsupported content response type:');
238
458
  }
239
459
  }
240
460
  // Add spacing if we have reasoning content
@@ -243,14 +463,18 @@ export class BedrockDriver extends AbstractDriver {
243
463
  }
244
464
  }
245
465
  const completionResult = {
246
- result: reasoning + resultText ? [{ type: "text", value: reasoning + resultText }] : [],
466
+ result: reasoning + resultText ? [{ type: 'text', value: reasoning + resultText }] : [],
247
467
  token_usage: {
248
468
  // Bedrock's inputTokens already excludes cache-read tokens,
249
469
  // so prompt_new is inputTokens directly (no subtraction needed).
250
470
  // prompt is the total including cached + cache_write for consistency
251
471
  // with the Vertex Claude driver.
252
472
  prompt_new: result.usage?.inputTokens,
253
- prompt: result.usage ? (result.usage.inputTokens ?? 0) + (result.usage.cacheReadInputTokens ?? 0) + (result.usage.cacheWriteInputTokens ?? 0) : undefined,
473
+ prompt: result.usage
474
+ ? (result.usage.inputTokens ?? 0) +
475
+ (result.usage.cacheReadInputTokens ?? 0) +
476
+ (result.usage.cacheWriteInputTokens ?? 0)
477
+ : undefined,
254
478
  result: result.usage?.outputTokens,
255
479
  total: result.usage?.totalTokens,
256
480
  prompt_cached: result.usage?.cacheReadInputTokens ?? undefined,
@@ -260,11 +484,10 @@ export class BedrockDriver extends AbstractDriver {
260
484
  };
261
485
  return completionResult;
262
486
  }
263
- ;
264
487
  getExtractedStream(result, _prompt, options, streamingToolBlocks) {
265
- let output = "";
266
- let reasoning = "";
267
- let stop_reason = "";
488
+ let output = '';
489
+ let reasoning = '';
490
+ let stop_reason = '';
268
491
  let token_usage;
269
492
  let tool_use;
270
493
  // Check if we should include thoughts (always true for reasoning-only models like DeepSeek R1)
@@ -272,7 +495,9 @@ export class BedrockDriver extends AbstractDriver {
272
495
  const shouldIncludeThoughts = isReasoningModel || (options && options.model_options?.include_thoughts);
273
496
  // Handle content block start events (for reasoning blocks and tool use)
274
497
  if (result.contentBlockStart) {
275
- if (result.contentBlockStart.start && 'toolUse' in result.contentBlockStart.start && result.contentBlockStart.start.toolUse) {
498
+ if (result.contentBlockStart.start &&
499
+ 'toolUse' in result.contentBlockStart.start &&
500
+ result.contentBlockStart.start.toolUse) {
276
501
  // Register new tool call block and emit an initial chunk so the accumulator can track it by id
277
502
  const toolUseStart = result.contentBlockStart.start.toolUse;
278
503
  const blockIndex = result.contentBlockStart.contentBlockIndex ?? -1;
@@ -281,7 +506,9 @@ export class BedrockDriver extends AbstractDriver {
281
506
  streamingToolBlocks?.set(blockIndex, { id, name });
282
507
  tool_use = [{ id, tool_name: name, tool_input: '' }];
283
508
  }
284
- else if (result.contentBlockStart.start && 'reasoningContent' in result.contentBlockStart.start && shouldIncludeThoughts) {
509
+ else if (result.contentBlockStart.start &&
510
+ 'reasoningContent' in result.contentBlockStart.start &&
511
+ shouldIncludeThoughts) {
285
512
  // Handle redacted content at block start
286
513
  const reasoningStart = result.contentBlockStart.start;
287
514
  if (reasoningStart.reasoningContent?.redactedContent) {
@@ -314,15 +541,15 @@ export class BedrockDriver extends AbstractDriver {
314
541
  }
315
542
  else if (delta.reasoningContent.signature) {
316
543
  // Handle signature updates for reasoning content - end of thinking
317
- reasoning = "\n\n";
544
+ reasoning = '\n\n';
318
545
  // Putting logging here so it only triggers once.
319
- this.logger.info("[Bedrock] Not outputting reasoning content as include_thoughts is false");
546
+ this.logger.info('[Bedrock] Not outputting reasoning content as include_thoughts is false');
320
547
  }
321
548
  }
322
549
  else if (delta) {
323
550
  // Get content block type
324
- const type = Object.keys(delta).find(key => key !== '$unknown' && delta[key] !== undefined);
325
- this.logger.info({ type }, "[Bedrock] Unsupported content response type:");
551
+ const type = Object.keys(delta).find((key) => key !== '$unknown' && delta[key] !== undefined);
552
+ this.logger.info({ type }, '[Bedrock] Unsupported content response type:');
326
553
  }
327
554
  }
328
555
  // Handle content block stop events
@@ -336,12 +563,16 @@ export class BedrockDriver extends AbstractDriver {
336
563
  }
337
564
  }
338
565
  if (result.messageStop) {
339
- stop_reason = result.messageStop.stopReason ?? "";
566
+ stop_reason = result.messageStop.stopReason ?? '';
340
567
  }
341
568
  if (result.metadata) {
342
569
  token_usage = {
343
570
  prompt_new: result.metadata.usage?.inputTokens,
344
- prompt: result.metadata.usage ? (result.metadata.usage.inputTokens ?? 0) + (result.metadata.usage.cacheReadInputTokens ?? 0) + (result.metadata.usage.cacheWriteInputTokens ?? 0) : undefined,
571
+ prompt: result.metadata.usage
572
+ ? (result.metadata.usage.inputTokens ?? 0) +
573
+ (result.metadata.usage.cacheReadInputTokens ?? 0) +
574
+ (result.metadata.usage.cacheWriteInputTokens ?? 0)
575
+ : undefined,
345
576
  result: result.metadata.usage?.outputTokens,
346
577
  total: result.metadata.usage?.totalTokens,
347
578
  prompt_cached: result.metadata.usage?.cacheReadInputTokens ?? undefined,
@@ -349,14 +580,13 @@ export class BedrockDriver extends AbstractDriver {
349
580
  };
350
581
  }
351
582
  const completionResult = {
352
- result: reasoning + output ? [{ type: "text", value: reasoning + output }] : [],
583
+ result: reasoning + output ? [{ type: 'text', value: reasoning + output }] : [],
353
584
  token_usage: token_usage,
354
585
  finish_reason: converseFinishReason(stop_reason),
355
586
  tool_use,
356
587
  };
357
588
  return completionResult;
358
589
  }
359
- ;
360
590
  extractRegion(modelString, defaultRegion) {
361
591
  // Match region in full ARN pattern
362
592
  const arnMatch = modelString.match(/arn:aws[^:]*:bedrock:([^:]+):/);
@@ -377,7 +607,7 @@ export class BedrockDriver extends AbstractDriver {
377
607
  if (type === BedrockModelType.FoundationModel || type === BedrockModelType.Unknown) {
378
608
  try {
379
609
  const response = await this.getService(region).getFoundationModel({
380
- modelIdentifier: model
610
+ modelIdentifier: model,
381
611
  });
382
612
  canStream = response.modelDetails?.responseStreamingSupported ?? false;
383
613
  return canStream;
@@ -389,9 +619,9 @@ export class BedrockDriver extends AbstractDriver {
389
619
  if (type === BedrockModelType.InferenceProfile || type === BedrockModelType.Unknown) {
390
620
  try {
391
621
  const response = await this.getService(region).getInferenceProfile({
392
- inferenceProfileIdentifier: model
622
+ inferenceProfileIdentifier: model,
393
623
  });
394
- canStream = await this.getCanStream(response.models?.[0].modelArn ?? "", BedrockModelType.FoundationModel);
624
+ canStream = await this.getCanStream(response.models?.[0].modelArn ?? '', BedrockModelType.FoundationModel);
395
625
  return canStream;
396
626
  }
397
627
  catch (e) {
@@ -401,9 +631,9 @@ export class BedrockDriver extends AbstractDriver {
401
631
  if (type === BedrockModelType.CustomModel || type === BedrockModelType.Unknown) {
402
632
  try {
403
633
  const response = await this.getService(region).getCustomModel({
404
- modelIdentifier: model
634
+ modelIdentifier: model,
405
635
  });
406
- canStream = await this.getCanStream(response.baseModelArn ?? "", BedrockModelType.FoundationModel);
636
+ canStream = await this.getCanStream(response.baseModelArn ?? '', BedrockModelType.FoundationModel);
407
637
  return canStream;
408
638
  }
409
639
  catch (e) {
@@ -411,7 +641,7 @@ export class BedrockDriver extends AbstractDriver {
411
641
  }
412
642
  }
413
643
  if (error) {
414
- console.warn("Error on canStream check for model: " + model + " region detected: " + region, error);
644
+ console.warn(`Error on canStream check for model: ${model} region detected: ${region}`, error);
415
645
  }
416
646
  return canStream;
417
647
  }
@@ -423,13 +653,13 @@ export class BedrockDriver extends AbstractDriver {
423
653
  let canStream = supportStreamingCache.get(options.model);
424
654
  if (canStream == null) {
425
655
  let type = BedrockModelType.Unknown;
426
- if (options.model.includes("foundation-model")) {
656
+ if (options.model.includes('foundation-model')) {
427
657
  type = BedrockModelType.FoundationModel;
428
658
  }
429
- else if (options.model.includes("inference-profile")) {
659
+ else if (options.model.includes('inference-profile')) {
430
660
  type = BedrockModelType.InferenceProfile;
431
661
  }
432
- else if (options.model.includes("custom-model")) {
662
+ else if (options.model.includes('custom-model')) {
433
663
  type = BedrockModelType.CustomModel;
434
664
  }
435
665
  canStream = await this.getCanStream(options.model, type);
@@ -443,14 +673,14 @@ export class BedrockDriver extends AbstractDriver {
443
673
  */
444
674
  buildStreamingConversation(prompt, result, toolUse, options) {
445
675
  // Only handle ConverseRequest prompts (not NovaMessagesPrompt or TwelvelabsPegasusRequest)
446
- if (options.model.includes("canvas") || options.model.includes("twelvelabs.pegasus")) {
676
+ if (options.model.includes('canvas') || options.model.includes('twelvelabs.pegasus')) {
447
677
  return undefined;
448
678
  }
449
679
  const conversePrompt = prompt;
450
680
  const completionResults = result;
451
681
  // Convert accumulated results to text content for assistant message
452
682
  const textContent = completionResults
453
- .map(r => {
683
+ .map((r) => {
454
684
  switch (r.type) {
455
685
  case 'text':
456
686
  return r.value;
@@ -459,8 +689,10 @@ export class BedrockDriver extends AbstractDriver {
459
689
  case 'image':
460
690
  // Skip images in conversation - they're in the result
461
691
  return '';
462
- default:
463
- return String(r.value || '');
692
+ default: {
693
+ const _exhaustive = r;
694
+ return String(_exhaustive);
695
+ }
464
696
  }
465
697
  })
466
698
  .join('');
@@ -481,16 +713,18 @@ export class BedrockDriver extends AbstractDriver {
481
713
  toolUseId: tool.id,
482
714
  name: tool.tool_name,
483
715
  input: tool.tool_input,
484
- }
716
+ },
485
717
  });
486
718
  }
487
719
  }
488
720
  // Add assistant message
489
721
  const assistantMessage = {
490
- messages: [{
722
+ messages: [
723
+ {
491
724
  content: messageContent.length > 0 ? messageContent : [{ text: '' }],
492
- role: "assistant"
493
- }],
725
+ role: 'assistant',
726
+ },
727
+ ],
494
728
  modelId: conversePrompt.modelId,
495
729
  };
496
730
  conversation = updateConversation(conversation, assistantMessage);
@@ -501,7 +735,7 @@ export class BedrockDriver extends AbstractDriver {
501
735
  const stripOptions = {
502
736
  keepForTurns: options.stripImagesAfterTurns ?? Infinity,
503
737
  currentTurn,
504
- textMaxTokens: options.stripTextMaxTokens
738
+ textMaxTokens: options.stripTextMaxTokens,
505
739
  };
506
740
  let processedConversation = stripBinaryFromConversation(conversation, stripOptions);
507
741
  processedConversation = truncateLargeTextInConversation(processedConversation, stripOptions);
@@ -513,7 +747,7 @@ export class BedrockDriver extends AbstractDriver {
513
747
  }
514
748
  async requestTextCompletion(prompt, options) {
515
749
  // Handle Twelvelabs Pegasus models
516
- if (options.model.includes("twelvelabs.pegasus")) {
750
+ if (options.model.includes('twelvelabs.pegasus')) {
517
751
  return this.requestTwelvelabsPegasusCompletion(prompt, options);
518
752
  }
519
753
  // Handle other Bedrock models that use Converse API
@@ -522,15 +756,21 @@ export class BedrockDriver extends AbstractDriver {
522
756
  const incomingConversation = deserializeBinaryFromStorage(options.conversation);
523
757
  let conversation = updateConversation(incomingConversation, conversePrompt);
524
758
  const payload = this.preparePayload(conversation, options);
525
- const executor = this.getExecutor();
526
- const res = await executor.converse({
527
- ...payload,
528
- });
759
+ const executorScope = this.getScopedExecutor(options);
760
+ let res;
761
+ try {
762
+ res = await executorScope.executor.converse({
763
+ ...payload,
764
+ });
765
+ }
766
+ finally {
767
+ executorScope.close();
768
+ }
529
769
  // Strip reasoningContent from assistant messages before storing in conversation
530
770
  // (DeepSeek R1 returns reasoning blocks but rejects them in subsequent user turns)
531
- const assistantMsg = res.output?.message ?? { content: [{ text: "" }], role: "assistant" };
771
+ const assistantMsg = res.output?.message ?? { content: [{ text: '' }], role: 'assistant' };
532
772
  if (assistantMsg.content) {
533
- assistantMsg.content = assistantMsg.content.filter((c) => !c.reasoningContent);
773
+ assistantMsg.content = assistantMsg.content.filter((c) => !('reasoningContent' in c));
534
774
  }
535
775
  conversation = updateConversation(conversation, {
536
776
  messages: [assistantMsg],
@@ -538,14 +778,14 @@ export class BedrockDriver extends AbstractDriver {
538
778
  });
539
779
  // Increment turn counter for deferred stripping
540
780
  conversation = incrementConversationTurn(conversation);
541
- let tool_use = undefined;
781
+ let tool_use;
542
782
  //Get tool requests, we check tool use regardless of finish reason, as you can hit length and still get a valid response.
543
783
  tool_use = res.output?.message?.content?.reduce((tools, c) => {
544
784
  if (c.toolUse) {
545
785
  tools.push({
546
- tool_name: c.toolUse.name ?? "",
786
+ tool_name: c.toolUse.name ?? '',
547
787
  tool_input: c.toolUse.input,
548
- id: c.toolUse.toolUseId ?? "",
788
+ id: c.toolUse.toolUseId ?? '',
549
789
  });
550
790
  }
551
791
  return tools;
@@ -559,7 +799,7 @@ export class BedrockDriver extends AbstractDriver {
559
799
  const stripOptions = {
560
800
  keepForTurns: options.stripImagesAfterTurns ?? Infinity,
561
801
  currentTurn,
562
- textMaxTokens: options.stripTextMaxTokens
802
+ textMaxTokens: options.stripTextMaxTokens,
563
803
  };
564
804
  let processedConversation = stripBinaryFromConversation(conversation, stripOptions);
565
805
  // Truncate large text content if configured
@@ -578,85 +818,100 @@ export class BedrockDriver extends AbstractDriver {
578
818
  return completion;
579
819
  }
580
820
  async requestTwelvelabsPegasusCompletion(prompt, options) {
581
- const executor = this.getExecutor();
582
- const res = await executor.invokeModel({
583
- modelId: options.model,
584
- contentType: "application/json",
585
- accept: "application/json",
586
- body: JSON.stringify(prompt),
587
- });
821
+ const executorScope = this.getScopedExecutor(options);
822
+ let res;
823
+ try {
824
+ res = await executorScope.executor.invokeModel({
825
+ modelId: options.model,
826
+ contentType: 'application/json',
827
+ accept: 'application/json',
828
+ body: JSON.stringify(prompt),
829
+ });
830
+ }
831
+ finally {
832
+ executorScope.close();
833
+ }
588
834
  const decoder = new TextDecoder();
589
835
  const body = decoder.decode(res.body);
590
836
  const result = JSON.parse(body);
591
837
  // Extract the response according to TwelveLabs Pegasus format
592
838
  let finishReason;
593
839
  switch (result.finishReason) {
594
- case "stop":
595
- finishReason = "stop";
840
+ case 'stop':
841
+ finishReason = 'stop';
596
842
  break;
597
- case "length":
598
- finishReason = "length";
843
+ case 'length':
844
+ finishReason = 'length';
599
845
  break;
600
846
  default:
601
847
  finishReason = result.finishReason;
602
848
  }
603
849
  return {
604
- result: result.message ? [{ type: "text", value: result.message }] : [],
850
+ result: result.message ? [{ type: 'text', value: result.message }] : [],
605
851
  finish_reason: finishReason,
606
852
  original_response: options.include_original_response ? result : undefined,
607
853
  };
608
854
  }
609
855
  async requestTwelvelabsPegasusCompletionStream(prompt, options) {
610
- const executor = this.getExecutor();
611
- const res = await executor.invokeModelWithResponseStream({
612
- modelId: options.model,
613
- contentType: "application/json",
614
- accept: "application/json",
615
- body: JSON.stringify(prompt),
616
- });
617
- if (!res.body) {
618
- throw new Error("[Bedrock] Stream not found in response");
619
- }
620
- return transformAsyncIterator(res.body, (chunk) => {
621
- if (chunk.chunk?.bytes) {
622
- const decoder = new TextDecoder();
623
- const body = decoder.decode(chunk.chunk.bytes);
624
- try {
625
- const result = JSON.parse(body);
626
- // Extract streaming response according to TwelveLabs Pegasus format
627
- let finishReason;
628
- if (result.finishReason) {
629
- switch (result.finishReason) {
630
- case "stop":
631
- finishReason = "stop";
632
- break;
633
- case "length":
634
- finishReason = "length";
635
- break;
636
- default:
637
- finishReason = result.finishReason;
856
+ const executorScope = this.getScopedExecutor(options);
857
+ try {
858
+ const res = await executorScope.executor.invokeModelWithResponseStream({
859
+ modelId: options.model,
860
+ contentType: 'application/json',
861
+ accept: 'application/json',
862
+ body: JSON.stringify(prompt),
863
+ });
864
+ if (!res.body) {
865
+ throw new Error('[Bedrock] Stream not found in response');
866
+ }
867
+ const stream = transformAsyncIterator(res.body, (chunk) => {
868
+ if (chunk.chunk?.bytes) {
869
+ const decoder = new TextDecoder();
870
+ const body = decoder.decode(chunk.chunk.bytes);
871
+ try {
872
+ const result = JSON.parse(body);
873
+ // Extract streaming response according to TwelveLabs Pegasus format
874
+ let finishReason;
875
+ if (result.finishReason) {
876
+ switch (result.finishReason) {
877
+ case 'stop':
878
+ finishReason = 'stop';
879
+ break;
880
+ case 'length':
881
+ finishReason = 'length';
882
+ break;
883
+ default:
884
+ finishReason = result.finishReason;
885
+ }
638
886
  }
887
+ return {
888
+ result: result.delta || result.message
889
+ ? [{ type: 'text', value: result.delta || result.message || '' }]
890
+ : [],
891
+ finish_reason: finishReason,
892
+ };
893
+ }
894
+ catch {
895
+ // If JSON parsing fails, return empty chunk
896
+ return {
897
+ result: [],
898
+ };
639
899
  }
640
- return {
641
- result: result.delta || result.message ? [{ type: "text", value: result.delta || result.message || "" }] : [],
642
- finish_reason: finishReason,
643
- };
644
- }
645
- catch (error) {
646
- // If JSON parsing fails, return empty chunk
647
- return {
648
- result: [],
649
- };
650
900
  }
651
- }
652
- return {
653
- result: [],
654
- };
655
- });
901
+ return {
902
+ result: [],
903
+ };
904
+ });
905
+ return withBedrockRuntimeScope(stream, executorScope);
906
+ }
907
+ catch (err) {
908
+ executorScope.close();
909
+ throw err;
910
+ }
656
911
  }
657
912
  async requestTextCompletionStream(prompt, options) {
658
913
  // Handle Twelvelabs Pegasus models
659
- if (options.model.includes("twelvelabs.pegasus")) {
914
+ if (options.model.includes('twelvelabs.pegasus')) {
660
915
  return this.requestTwelvelabsPegasusCompletionStream(prompt, options);
661
916
  }
662
917
  // Handle other Bedrock models that use Converse API
@@ -666,42 +921,49 @@ export class BedrockDriver extends AbstractDriver {
666
921
  const incomingConversation = deserializeBinaryFromStorage(options.conversation);
667
922
  const conversation = updateConversation(incomingConversation, conversePrompt);
668
923
  const payload = this.preparePayload(conversation, options);
669
- const executor = this.getExecutor();
670
- return executor.converseStream({
924
+ const executorScope = this.getScopedExecutor(options);
925
+ return executorScope.executor
926
+ .converseStream({
671
927
  ...payload,
672
- }).then((res) => {
928
+ })
929
+ .then((res) => {
673
930
  const stream = res.stream;
674
931
  if (!stream) {
675
- throw new Error("[Bedrock] Stream not found in response");
932
+ throw new Error('[Bedrock] Stream not found in response');
676
933
  }
677
934
  const streamingToolBlocks = new Map();
678
- return transformAsyncIterator(stream, (streamSegment) => {
935
+ const transformedStream = transformAsyncIterator(stream, (streamSegment) => {
679
936
  return this.getExtractedStream(streamSegment, conversePrompt, options, streamingToolBlocks);
680
937
  });
681
- }).catch((err) => {
682
- this.logger.error({ error: err }, "[Bedrock] Failed to stream");
938
+ return withBedrockRuntimeScope(transformedStream, executorScope);
939
+ })
940
+ .catch((err) => {
941
+ executorScope.close();
942
+ this.logger.error({ error: err }, '[Bedrock] Failed to stream');
683
943
  throw err;
684
944
  });
685
945
  }
686
946
  preparePayload(prompt, options) {
687
- const model_options = options.model_options ?? { _option_id: "text-fallback" };
947
+ const model_options = options.model_options ?? {
948
+ _option_id: 'text-fallback',
949
+ };
688
950
  let additionalField = {};
689
951
  let supportsJSONPrefill = false;
690
952
  // Resolve thinking, effort, and sampling restrictions using shared Claude helper
691
953
  const claudeThinking = resolveClaudeThinking(options.model, options.model_options);
692
954
  const hasSamplingRestriction = claudeThinking.hasSamplingRestriction;
693
- if (options.model.includes("amazon")) {
955
+ if (options.model.includes('amazon')) {
694
956
  supportsJSONPrefill = true;
695
957
  //Titan models also exists but does not support any additional options
696
- if (options.model.includes("nova")) {
958
+ if (options.model.includes('nova')) {
697
959
  additionalField = { inferenceConfig: { topK: model_options.top_k } };
698
960
  }
699
961
  }
700
- else if (options.model.includes("claude")) {
962
+ else if (options.model.includes('claude')) {
701
963
  const claude_options = model_options;
702
964
  // Thinking is active when extended (budget set) or adaptive (effort set) thinking is enabled.
703
965
  // JSON prefill is incompatible with active thinking.
704
- const thinkingActive = claudeThinking.thinking != null && claudeThinking.thinking.type !== "disabled";
966
+ const thinkingActive = claudeThinking.thinking != null && claudeThinking.thinking.type !== 'disabled';
705
967
  supportsJSONPrefill = !thinkingActive;
706
968
  // Claude 3.7+ supports thinking — use shared helper for reasoning_config
707
969
  if (claudeThinking.supportsThinking) {
@@ -712,12 +974,12 @@ export class BedrockDriver extends AbstractDriver {
712
974
  };
713
975
  }
714
976
  // For Claude 3.7 with extended thinking + high output, add beta header
715
- if (claudeThinking.thinking?.type === "enabled" &&
716
- options.model.includes("claude-3-7-sonnet") &&
977
+ if (claudeThinking.thinking?.type === 'enabled' &&
978
+ options.model.includes('claude-3-7-sonnet') &&
717
979
  ((claude_options.max_tokens ?? 0) > 64000 || (claude_options.thinking_budget_tokens ?? 0) > 64000)) {
718
980
  additionalField = {
719
981
  ...additionalField,
720
- anthropic_beta: ["output-128k-2025-02-19"]
982
+ anthropic_beta: ['output-128k-2025-02-19'],
721
983
  };
722
984
  }
723
985
  }
@@ -725,7 +987,7 @@ export class BedrockDriver extends AbstractDriver {
725
987
  if (claudeThinking.outputConfig) {
726
988
  additionalField = {
727
989
  ...additionalField,
728
- output_config: claudeThinking.outputConfig
990
+ output_config: claudeThinking.outputConfig,
729
991
  };
730
992
  }
731
993
  // Claude 4.6 and later versions don't support JSON prefill
@@ -741,12 +1003,12 @@ export class BedrockDriver extends AbstractDriver {
741
1003
  additionalField = { ...additionalField, top_k: model_options.top_k };
742
1004
  }
743
1005
  }
744
- else if (options.model.includes("meta")) {
1006
+ else if (options.model.includes('meta')) {
745
1007
  //LLaMA models support no additional options
746
1008
  }
747
- else if (options.model.includes("mistral")) {
1009
+ else if (options.model.includes('mistral')) {
748
1010
  //7B instruct and 8x7B instruct
749
- if (options.model.includes("7b")) {
1011
+ if (options.model.includes('7b')) {
750
1012
  additionalField = { top_k: model_options.top_k };
751
1013
  //Does not support system messages
752
1014
  if (prompt.system && prompt.system?.length !== 0) {
@@ -760,10 +1022,10 @@ export class BedrockDriver extends AbstractDriver {
760
1022
  //Support no additional fields.
761
1023
  }
762
1024
  }
763
- else if (options.model.includes("ai21")) {
1025
+ else if (options.model.includes('ai21')) {
764
1026
  //Jamba models support no additional options
765
1027
  //Jurassic 2 models do.
766
- if (options.model.includes("j2")) {
1028
+ if (options.model.includes('j2')) {
767
1029
  additionalField = {
768
1030
  presencePenalty: { scale: model_options.presence_penalty },
769
1031
  frequencyPenalty: { scale: model_options.frequency_penalty },
@@ -776,10 +1038,10 @@ export class BedrockDriver extends AbstractDriver {
776
1038
  }
777
1039
  }
778
1040
  }
779
- else if (options.model.includes("cohere.command")) {
1041
+ else if (options.model.includes('cohere.command')) {
780
1042
  // If last message is "```json", remove it.
781
1043
  //Command R and R plus
782
- if (options.model.includes("cohere.command-r")) {
1044
+ if (options.model.includes('cohere.command-r')) {
783
1045
  additionalField = {
784
1046
  k: model_options.top_k,
785
1047
  frequency_penalty: model_options.frequency_penalty,
@@ -797,7 +1059,7 @@ export class BedrockDriver extends AbstractDriver {
797
1059
  }
798
1060
  }
799
1061
  }
800
- else if (options.model.includes("palmyra")) {
1062
+ else if (options.model.includes('palmyra')) {
801
1063
  const palmyraOptions = model_options;
802
1064
  additionalField = {
803
1065
  seed: palmyraOptions?.seed,
@@ -806,12 +1068,12 @@ export class BedrockDriver extends AbstractDriver {
806
1068
  min_tokens: palmyraOptions?.min_tokens,
807
1069
  };
808
1070
  }
809
- else if (options.model.includes("deepseek")) {
1071
+ else if (options.model.includes('deepseek')) {
810
1072
  // DeepSeek models: no additional options, no stopSequences, only one of temperature/top_p
811
1073
  model_options.stop_sequence = undefined;
812
1074
  model_options.top_p = undefined;
813
1075
  }
814
- else if (options.model.includes("gpt-oss")) {
1076
+ else if (options.model.includes('gpt-oss')) {
815
1077
  const gptOssOptions = model_options;
816
1078
  additionalField = {
817
1079
  reasoning_effort: gptOssOptions?.reasoning_effort,
@@ -819,13 +1081,13 @@ export class BedrockDriver extends AbstractDriver {
819
1081
  }
820
1082
  //If last message is "```json", add corresponding ``` as a stop sequence.
821
1083
  if (prompt.messages && prompt.messages.length > 0) {
822
- if (prompt.messages[prompt.messages.length - 1].content?.[0].text === "```json") {
1084
+ if (prompt.messages[prompt.messages.length - 1].content?.[0].text === '```json') {
823
1085
  const stopSeq = model_options.stop_sequence;
824
1086
  if (!stopSeq) {
825
- model_options.stop_sequence = ["```"];
1087
+ model_options.stop_sequence = ['```'];
826
1088
  }
827
- else if (!stopSeq.includes("```")) {
828
- stopSeq.push("```");
1089
+ else if (!stopSeq.includes('```')) {
1090
+ stopSeq.push('```');
829
1091
  model_options.stop_sequence = stopSeq;
830
1092
  }
831
1093
  }
@@ -841,10 +1103,12 @@ export class BedrockDriver extends AbstractDriver {
841
1103
  // Models with sampling parameter restrictions don't support temperature/top_p - exclude them from inference config
842
1104
  const cleanedModelOptions = removeUndefinedValues({
843
1105
  maxTokens: model_options.max_tokens,
844
- ...(hasSamplingRestriction ? {} : {
845
- temperature: model_options.temperature,
846
- topP: model_options.temperature != null ? undefined : model_options.top_p,
847
- }),
1106
+ ...(hasSamplingRestriction
1107
+ ? {}
1108
+ : {
1109
+ temperature: model_options.temperature,
1110
+ topP: model_options.temperature != null ? undefined : model_options.top_p,
1111
+ }),
848
1112
  stopSequences: model_options.stop_sequence,
849
1113
  });
850
1114
  //Construct the final request payload
@@ -862,7 +1126,8 @@ export class BedrockDriver extends AbstractDriver {
862
1126
  request.inferenceConfig = cleanedModelOptions;
863
1127
  }
864
1128
  if (Object.keys(cleanedAdditionalFields).length > 0) {
865
- request.additionalModelRequestFields = cleanedAdditionalFields;
1129
+ request.additionalModelRequestFields =
1130
+ cleanedAdditionalFields;
866
1131
  }
867
1132
  if (tool_defs?.length) {
868
1133
  request.toolConfig = {
@@ -915,37 +1180,47 @@ export class BedrockDriver extends AbstractDriver {
915
1180
  return request;
916
1181
  }
917
1182
  isImageModel(model) {
918
- return model.includes("titan-image") || model.includes("stable-diffusion") || model.includes("nova-canvas");
1183
+ return model.includes('titan-image') || model.includes('stable-diffusion') || model.includes('nova-canvas');
919
1184
  }
920
1185
  async requestImageGeneration(prompt, options) {
921
- if (options.model_options?._option_id !== undefined && options.model_options?._option_id !== "bedrock-nova-canvas") {
922
- this.logger.debug({ options: options.model_options }, "Unexpected option id");
1186
+ if (options.model_options?._option_id !== undefined &&
1187
+ options.model_options?._option_id !== 'bedrock-nova-canvas') {
1188
+ this.logger.debug({ options: options.model_options }, 'Unexpected option id');
923
1189
  }
924
1190
  const model_options = options.model_options;
925
- const executor = this.getExecutor();
926
1191
  const taskType = model_options.taskType ?? NovaImageGenerationTaskType.TEXT_IMAGE;
927
- this.logger.info("Task type: " + taskType);
928
- if (typeof prompt === "string") {
929
- throw new Error("Bad prompt format");
1192
+ this.logger.info(`Task type: ${taskType}`);
1193
+ if (typeof prompt === 'string') {
1194
+ throw new Error('Bad prompt format');
930
1195
  }
931
1196
  const payload = await formatNovaImageGenerationPayload(taskType, prompt, options);
932
- const res = await executor.invokeModel({
933
- modelId: options.model,
934
- contentType: "application/json",
935
- accept: "application/json",
936
- body: JSON.stringify(payload),
937
- }, {
938
- requestTimeout: 60000 * 5
939
- });
1197
+ const executorScope = this.getScopedExecutor(options);
1198
+ let res;
1199
+ try {
1200
+ const requestTimeout = options.httpTimeout
1201
+ ? resolveDriverHttpTimeouts(mergeDriverHttpTimeoutOptions(this.options.httpTimeout, options.httpTimeout)).headersTimeout
1202
+ : (this.options.httpTimeout?.headersTimeout ?? 60_000 * 5);
1203
+ res = await executorScope.executor.invokeModel({
1204
+ modelId: options.model,
1205
+ contentType: 'application/json',
1206
+ accept: 'application/json',
1207
+ body: JSON.stringify(payload),
1208
+ }, {
1209
+ requestTimeout,
1210
+ });
1211
+ }
1212
+ finally {
1213
+ executorScope.close();
1214
+ }
940
1215
  const decoder = new TextDecoder();
941
1216
  const body = decoder.decode(res.body);
942
1217
  const bedrockResult = JSON.parse(body);
943
1218
  return {
944
1219
  error: bedrockResult.error,
945
1220
  result: bedrockResult.images.map((image) => ({
946
- type: "image",
947
- value: image
948
- }))
1221
+ type: 'image',
1222
+ value: image,
1223
+ })),
949
1224
  };
950
1225
  }
951
1226
  async startTraining(dataset, options) {
@@ -962,11 +1237,11 @@ export class BedrockDriver extends AbstractDriver {
962
1237
  const upload = await forceUploadFile(s3, stream, this.options.training_bucket, dataset.name);
963
1238
  const service = this.getService();
964
1239
  const response = await service.send(new CreateModelCustomizationJobCommand({
965
- jobName: options.name + "-job",
1240
+ jobName: `${options.name}-job`,
966
1241
  customModelName: options.name,
967
1242
  roleArn: this.options.training_role_arn || undefined,
968
1243
  baseModelIdentifier: options.model,
969
- clientRequestToken: "llumiverse-" + Date.now(),
1244
+ clientRequestToken: `llumiverse-${Date.now()}`,
970
1245
  trainingDataConfig: {
971
1246
  s3Uri: `s3://${upload.Bucket}/${upload.Key}`,
972
1247
  },
@@ -976,43 +1251,44 @@ export class BedrockDriver extends AbstractDriver {
976
1251
  //customizationType: "FINE_TUNING",
977
1252
  }));
978
1253
  const job = await service.send(new GetModelCustomizationJobCommand({
979
- jobIdentifier: response.jobArn
1254
+ jobIdentifier: response.jobArn,
980
1255
  }));
1256
+ // biome-ignore lint/style/noNonNullAssertion: intentional non-null assertion; TS can't prove narrowing here
981
1257
  return jobInfo(job, response.jobArn);
982
1258
  }
983
1259
  async cancelTraining(jobId) {
984
1260
  const service = this.getService();
985
1261
  await service.send(new StopModelCustomizationJobCommand({
986
- jobIdentifier: jobId
1262
+ jobIdentifier: jobId,
987
1263
  }));
988
1264
  const job = await service.send(new GetModelCustomizationJobCommand({
989
- jobIdentifier: jobId
1265
+ jobIdentifier: jobId,
990
1266
  }));
991
1267
  return jobInfo(job, jobId);
992
1268
  }
993
1269
  async getTrainingJob(jobId) {
994
1270
  const service = this.getService();
995
1271
  const job = await service.send(new GetModelCustomizationJobCommand({
996
- jobIdentifier: jobId
1272
+ jobIdentifier: jobId,
997
1273
  }));
998
1274
  return jobInfo(job, jobId);
999
1275
  }
1000
1276
  // ===================== management API ==================
1001
1277
  async validateConnection() {
1002
1278
  const service = this.getService();
1003
- this.logger.debug("[Bedrock] validating connection", service.config.credentials.name);
1279
+ this.logger.debug('[Bedrock] validating connection', service.config.credentials.name);
1004
1280
  //return true as if the client has been initialized, it means the connection is valid
1005
1281
  return true;
1006
1282
  }
1007
1283
  async listTrainableModels() {
1008
- this.logger.debug("[Bedrock] listing trainable models");
1009
- return this._listModels(m => m.customizationsSupported ? m.customizationsSupported.includes("FINE_TUNING") : false);
1284
+ this.logger.debug('[Bedrock] listing trainable models');
1285
+ return this._listModels((m) => m.customizationsSupported ? m.customizationsSupported.includes('FINE_TUNING') : false);
1010
1286
  }
1011
1287
  async listModels() {
1012
- this.logger.debug("[Bedrock] listing models");
1288
+ this.logger.debug('[Bedrock] listing models');
1013
1289
  // exclude trainable models since they are not executable
1014
1290
  // exclude embedding models, not to be used for typical completions.
1015
- const filter = (m) => (m.inferenceTypesSupported?.includes("ON_DEMAND") && !m.outputModalities?.includes("EMBEDDING")) ?? false;
1291
+ const filter = (m) => (m.inferenceTypesSupported?.includes('ON_DEMAND') && !m.outputModalities?.includes('EMBEDDING')) ?? false;
1016
1292
  return this._listModels(filter);
1017
1293
  }
1018
1294
  async _listModels(foundationFilter) {
@@ -1032,26 +1308,36 @@ export class BedrockDriver extends AbstractDriver {
1032
1308
  }),
1033
1309
  ]);
1034
1310
  if (!foundationModelsList?.modelSummaries) {
1035
- throw new Error("Foundation models not found");
1311
+ throw new Error('Foundation models not found');
1036
1312
  }
1037
1313
  let foundationModels = foundationModelsList.modelSummaries || [];
1038
1314
  if (foundationFilter) {
1039
1315
  foundationModels = foundationModels.filter(foundationFilter);
1040
1316
  }
1041
- const supportedPublishers = ["amazon", "anthropic", "cohere", "ai21",
1042
- "mistral", "meta", "deepseek", "writer",
1043
- "openai", "twelvelabs", "qwen"];
1317
+ const supportedPublishers = [
1318
+ 'amazon',
1319
+ 'anthropic',
1320
+ 'cohere',
1321
+ 'ai21',
1322
+ 'mistral',
1323
+ 'meta',
1324
+ 'deepseek',
1325
+ 'writer',
1326
+ 'openai',
1327
+ 'twelvelabs',
1328
+ 'qwen',
1329
+ ];
1044
1330
  const unsupportedModelsByPublisher = {
1045
- amazon: ["titan-image-generator", "nova-reel", "nova-sonic", "rerank"],
1331
+ amazon: ['titan-image-generator', 'nova-reel', 'nova-sonic', 'rerank'],
1046
1332
  anthropic: [],
1047
- cohere: ["rerank", "embed"],
1333
+ cohere: ['rerank', 'embed'],
1048
1334
  ai21: [],
1049
1335
  mistral: [],
1050
1336
  meta: [],
1051
1337
  deepseek: [],
1052
1338
  writer: [],
1053
1339
  openai: [],
1054
- twelvelabs: ["marengo"],
1340
+ twelvelabs: ['marengo'],
1055
1341
  qwen: [],
1056
1342
  };
1057
1343
  // Helper function to check if model should be filtered out
@@ -1060,22 +1346,22 @@ export class BedrockDriver extends AbstractDriver {
1060
1346
  return false;
1061
1347
  const normalizedProvider = providerName.toLowerCase();
1062
1348
  // Check if provider is supported
1063
- const isProviderSupported = supportedPublishers.some(provider => normalizedProvider.includes(provider));
1349
+ const isProviderSupported = supportedPublishers.some((provider) => normalizedProvider.includes(provider));
1064
1350
  if (!isProviderSupported)
1065
1351
  return false;
1066
1352
  // Check if model is in the unsupported list for its provider
1067
1353
  for (const provider of supportedPublishers) {
1068
1354
  if (normalizedProvider.includes(provider)) {
1069
1355
  const unsupportedModels = unsupportedModelsByPublisher[provider] || [];
1070
- return !unsupportedModels.some(unsupported => modelId.toLowerCase().includes(unsupported));
1356
+ return !unsupportedModels.some((unsupported) => modelId.toLowerCase().includes(unsupported));
1071
1357
  }
1072
1358
  }
1073
1359
  return true;
1074
1360
  };
1075
- foundationModels = foundationModels.filter(m => shouldIncludeModel(m.modelId, m.providerName));
1361
+ foundationModels = foundationModels.filter((m) => shouldIncludeModel(m.modelId, m.providerName));
1076
1362
  const aiModels = foundationModels.map((m) => {
1077
1363
  if (!m.modelId) {
1078
- throw new Error("modelId not found");
1364
+ throw new Error('modelId not found');
1079
1365
  }
1080
1366
  const modelCapability = getModelCapabilities(m.modelArn ?? m.modelId, this.provider);
1081
1367
  const model = {
@@ -1084,8 +1370,12 @@ export class BedrockDriver extends AbstractDriver {
1084
1370
  provider: this.provider,
1085
1371
  owner: m.providerName,
1086
1372
  can_stream: m.responseStreamingSupported ?? false,
1087
- input_modalities: m.inputModalities ? formatAmazonModalities(m.inputModalities) : modelModalitiesToArray(modelCapability.input),
1088
- output_modalities: m.outputModalities ? formatAmazonModalities(m.outputModalities) : modelModalitiesToArray(modelCapability.input),
1373
+ input_modalities: m.inputModalities
1374
+ ? formatAmazonModalities(m.inputModalities)
1375
+ : modelModalitiesToArray(modelCapability.input),
1376
+ output_modalities: m.outputModalities
1377
+ ? formatAmazonModalities(m.outputModalities)
1378
+ : modelModalitiesToArray(modelCapability.input),
1089
1379
  tool_support: modelCapability.tool_support,
1090
1380
  };
1091
1381
  return model;
@@ -1094,14 +1384,14 @@ export class BedrockDriver extends AbstractDriver {
1094
1384
  if (customModelsList?.modelSummaries) {
1095
1385
  customModelsList.modelSummaries.forEach((m) => {
1096
1386
  if (!m.modelArn) {
1097
- throw new Error("Model ID not found");
1387
+ throw new Error('Model ID not found');
1098
1388
  }
1099
1389
  const modelCapability = getModelCapabilities(m.modelArn, this.provider);
1100
1390
  const model = {
1101
1391
  id: m.modelArn,
1102
1392
  name: m.modelName ?? m.modelArn,
1103
1393
  provider: this.provider,
1104
- owner: "custom",
1394
+ owner: 'custom',
1105
1395
  description: `Custom model from ${m.baseModelName}`,
1106
1396
  is_custom: true,
1107
1397
  input_modalities: modelModalitiesToArray(modelCapability.input),
@@ -1109,20 +1399,19 @@ export class BedrockDriver extends AbstractDriver {
1109
1399
  tool_support: modelCapability.tool_support,
1110
1400
  };
1111
1401
  aiModels.push(model);
1112
- this.validateConnection;
1113
1402
  });
1114
1403
  }
1115
1404
  //add inference profiles
1116
1405
  if (inferenceProfilesList?.inferenceProfileSummaries) {
1117
1406
  inferenceProfilesList.inferenceProfileSummaries.forEach((p) => {
1118
1407
  if (!p.inferenceProfileArn) {
1119
- throw new Error("Profile ARN not found");
1408
+ throw new Error('Profile ARN not found');
1120
1409
  }
1121
1410
  // Apply the same filtering logic to inference profiles based on their name
1122
- const profileId = p.inferenceProfileId || "";
1123
- const profileName = p.inferenceProfileName || "";
1411
+ const profileId = p.inferenceProfileId || '';
1412
+ const profileName = p.inferenceProfileName || '';
1124
1413
  // Extract provider name from profile name or ID
1125
- let providerName = "";
1414
+ let providerName = '';
1126
1415
  for (const provider of supportedPublishers) {
1127
1416
  if (profileName.toLowerCase().includes(provider) || profileId.toLowerCase().includes(provider)) {
1128
1417
  providerName = provider;
@@ -1146,73 +1435,8 @@ export class BedrockDriver extends AbstractDriver {
1146
1435
  }
1147
1436
  return aiModels;
1148
1437
  }
1149
- async generateEmbeddings({ text, image, model }) {
1150
- this.logger.info("[Bedrock] Generating embeddings with model " + model);
1151
- // Handle TwelveLabs Marengo models
1152
- if (model?.includes("twelvelabs.marengo")) {
1153
- return this.generateTwelvelabsMarengoEmbeddings({ text, image, model });
1154
- }
1155
- // Handle other Bedrock embedding models
1156
- const defaultModel = image ? "amazon.titan-embed-image-v1" : "amazon.titan-embed-text-v2:0";
1157
- const modelID = model ?? defaultModel;
1158
- const invokeBody = {
1159
- inputText: text,
1160
- inputImage: image
1161
- };
1162
- const executor = this.getExecutor();
1163
- const res = await executor.invokeModel({
1164
- modelId: modelID,
1165
- contentType: "application/json",
1166
- body: JSON.stringify(invokeBody),
1167
- });
1168
- const decoder = new TextDecoder();
1169
- const body = decoder.decode(res.body);
1170
- const result = JSON.parse(body);
1171
- if (!result.embedding) {
1172
- throw new Error("Embeddings not found");
1173
- }
1174
- return {
1175
- values: result.embedding,
1176
- model: modelID,
1177
- token_count: result.inputTextTokenCount
1178
- };
1179
- }
1180
- async generateTwelvelabsMarengoEmbeddings({ text, image, model }) {
1181
- const executor = this.getExecutor();
1182
- // Prepare the request payload for TwelveLabs Marengo
1183
- const invokeBody = {
1184
- inputType: "text"
1185
- };
1186
- if (text) {
1187
- invokeBody.inputText = text;
1188
- invokeBody.inputType = "text";
1189
- }
1190
- if (image) {
1191
- // For the embeddings interface, image is expected to be base64
1192
- invokeBody.mediaSource = {
1193
- base64String: image
1194
- };
1195
- invokeBody.inputType = "image";
1196
- }
1197
- const res = await executor.invokeModel({
1198
- modelId: model,
1199
- contentType: "application/json",
1200
- accept: "application/json",
1201
- body: JSON.stringify(invokeBody),
1202
- });
1203
- const decoder = new TextDecoder();
1204
- const body = decoder.decode(res.body);
1205
- const result = JSON.parse(body);
1206
- // TwelveLabs Marengo returns embedding data
1207
- if (!result.embedding) {
1208
- throw new Error("Embeddings not found in TwelveLabs Marengo response");
1209
- }
1210
- return {
1211
- values: result.embedding,
1212
- model: model,
1213
- // TwelveLabs Marengo doesn't return token count in the same way
1214
- token_count: undefined
1215
- };
1438
+ async generateEmbeddings(options) {
1439
+ return generateBedrockEmbeddings(this, options);
1216
1440
  }
1217
1441
  /**
1218
1442
  * Cleanup AWS SDK clients when the driver is evicted from the cache.
@@ -1220,6 +1444,9 @@ export class BedrockDriver extends AbstractDriver {
1220
1444
  destroy() {
1221
1445
  this._executor?.destroy();
1222
1446
  this._service?.destroy();
1447
+ this._executor = undefined;
1448
+ this._service = undefined;
1449
+ super.destroy();
1223
1450
  }
1224
1451
  }
1225
1452
  function jobInfo(job, jobId) {
@@ -1231,7 +1458,7 @@ function jobInfo(job, jobId) {
1231
1458
  }
1232
1459
  else if (jobStatus === ModelCustomizationJobStatus.FAILED) {
1233
1460
  status = TrainingJobStatus.failed;
1234
- details = job.failureMessage || "error";
1461
+ details = job.failureMessage || 'error';
1235
1462
  }
1236
1463
  else if (jobStatus === ModelCustomizationJobStatus.STOPPED) {
1237
1464
  status = TrainingJobStatus.cancelled;
@@ -1240,12 +1467,11 @@ function jobInfo(job, jobId) {
1240
1467
  status = TrainingJobStatus.running;
1241
1468
  details = jobStatus;
1242
1469
  }
1243
- job.baseModelArn;
1244
1470
  return {
1245
1471
  id: jobId,
1246
1472
  model: job.outputModelArn,
1247
1473
  status,
1248
- details
1474
+ details,
1249
1475
  };
1250
1476
  }
1251
1477
  function getToolDefinitions(tools) {
@@ -1258,8 +1484,8 @@ function getToolDefinition(tool) {
1258
1484
  description: tool.description,
1259
1485
  inputSchema: {
1260
1486
  json: tool.input_schema,
1261
- }
1262
- }
1487
+ },
1488
+ },
1263
1489
  };
1264
1490
  }
1265
1491
  /**
@@ -1270,8 +1496,7 @@ export function messagesContainToolBlocks(messages) {
1270
1496
  if (!msg.content)
1271
1497
  continue;
1272
1498
  for (const block of msg.content) {
1273
- if (block.toolUse ||
1274
- block.toolResult) {
1499
+ if (block.toolUse || block.toolResult) {
1275
1500
  return true;
1276
1501
  }
1277
1502
  }
@@ -1287,13 +1512,12 @@ export function messagesContainToolBlocks(messages) {
1287
1512
  * conversation history contains tool interactions from prior turns.
1288
1513
  */
1289
1514
  export function convertToolBlocksToText(messages) {
1290
- return messages.map(msg => {
1515
+ return messages.map((msg) => {
1291
1516
  if (!msg.content)
1292
1517
  return msg;
1293
1518
  let hasToolBlocks = false;
1294
1519
  for (const block of msg.content) {
1295
- if (block.toolUse ||
1296
- block.toolResult) {
1520
+ if (block.toolUse || block.toolResult) {
1297
1521
  hasToolBlocks = true;
1298
1522
  break;
1299
1523
  }
@@ -1306,7 +1530,7 @@ export function convertToolBlocksToText(messages) {
1306
1530
  const toolResult = block.toolResult;
1307
1531
  if (toolUse) {
1308
1532
  const inputStr = toolUse.input ? JSON.stringify(toolUse.input) : '';
1309
- const truncatedInput = inputStr.length > 500 ? inputStr.substring(0, 500) + '...' : inputStr;
1533
+ const truncatedInput = inputStr.length > 500 ? `${inputStr.substring(0, 500)}...` : inputStr;
1310
1534
  newContent.push({
1311
1535
  text: `[Tool call: ${toolUse.name}(${truncatedInput})]`,
1312
1536
  });
@@ -1315,9 +1539,9 @@ export function convertToolBlocksToText(messages) {
1315
1539
  const resultTexts = [];
1316
1540
  if (toolResult.content) {
1317
1541
  for (const c of toolResult.content) {
1318
- if (c.text) {
1542
+ if ('text' in c && typeof c.text === 'string') {
1319
1543
  const text = c.text;
1320
- resultTexts.push(text.length > 500 ? text.substring(0, 500) + '...' : text);
1544
+ resultTexts.push(text.length > 500 ? `${text.substring(0, 500)}...` : text);
1321
1545
  }
1322
1546
  }
1323
1547
  }
@@ -1368,8 +1592,11 @@ function removeUndefinedValues(obj) {
1368
1592
  function updateConversation(conversation, prompt) {
1369
1593
  const combinedMessages = [...(conversation?.messages || []), ...(prompt.messages || [])];
1370
1594
  const combinedSystem = prompt.system || conversation?.system;
1371
- // Fix orphaned toolUse blocks before returning
1372
- const fixedMessages = fixOrphanedToolUse(combinedMessages);
1595
+ // Fix both orphan directions before returning: a toolUse with no result
1596
+ // (interrupted run) gets a synthetic result; a toolResult with no matching
1597
+ // toolUse in the previous message (e.g. compaction-trimmed) is dropped. Either
1598
+ // would otherwise trip the Converse API's toolUse/toolResult pairing check.
1599
+ const fixedMessages = fixOrphanedToolResults(fixOrphanedToolUse(combinedMessages));
1373
1600
  return {
1374
1601
  modelId: prompt?.modelId || conversation?.modelId,
1375
1602
  messages: fixedMessages.length > 0 ? fixedMessages : [],
@@ -1377,16 +1604,16 @@ function updateConversation(conversation, prompt) {
1377
1604
  };
1378
1605
  }
1379
1606
  function stripClaudeCachePoints(messages) {
1380
- return messages.map(message => ({
1607
+ return messages.map((message) => ({
1381
1608
  ...message,
1382
- content: message.content?.filter(block => !('cachePoint' in block)),
1609
+ content: message.content?.filter((block) => !('cachePoint' in block)),
1383
1610
  }));
1384
1611
  }
1385
1612
  function stripClaudeCachePointsFromSystem(system) {
1386
- return (system?.filter(block => !('cachePoint' in block)) ?? undefined);
1613
+ return (system?.filter((block) => !('cachePoint' in block)) ?? undefined);
1387
1614
  }
1388
1615
  function stripClaudeCachePointsFromTools(tools) {
1389
- return (tools?.filter(tool => !('cachePoint' in tool)) ?? undefined);
1616
+ return (tools?.filter((tool) => !('cachePoint' in tool)) ?? undefined);
1390
1617
  }
1391
1618
  /**
1392
1619
  * Fix orphaned toolUse blocks in the conversation.
@@ -1413,7 +1640,7 @@ export function fixOrphanedToolUse(messages) {
1413
1640
  if (block.toolUse?.toolUseId) {
1414
1641
  toolUseBlocks.push({
1415
1642
  toolUseId: block.toolUse.toolUseId,
1416
- name: block.toolUse.name ?? 'unknown'
1643
+ name: block.toolUse.name ?? 'unknown',
1417
1644
  });
1418
1645
  }
1419
1646
  }
@@ -1429,21 +1656,23 @@ export function fixOrphanedToolUse(messages) {
1429
1656
  }
1430
1657
  }
1431
1658
  // Find orphaned toolUse blocks (no matching toolResult)
1432
- const orphanedToolUse = toolUseBlocks.filter(tu => !toolResultIds.has(tu.toolUseId));
1659
+ const orphanedToolUse = toolUseBlocks.filter((tu) => !toolResultIds.has(tu.toolUseId));
1433
1660
  if (orphanedToolUse.length > 0) {
1434
1661
  // Inject synthetic toolResults for orphaned toolUse
1435
- const syntheticResults = orphanedToolUse.map(tu => ({
1662
+ const syntheticResults = orphanedToolUse.map((tu) => ({
1436
1663
  toolResult: {
1437
1664
  toolUseId: tu.toolUseId,
1438
- content: [{
1439
- text: `[Tool interrupted: The user stopped the operation before "${tu.name}" could execute.]`
1440
- }]
1441
- }
1665
+ content: [
1666
+ {
1667
+ text: `[Tool interrupted: The user stopped the operation before "${tu.name}" could execute.]`,
1668
+ },
1669
+ ],
1670
+ },
1442
1671
  }));
1443
1672
  // Prepend synthetic results to the next user message
1444
1673
  const updatedNextMessage = {
1445
1674
  ...nextMessage,
1446
- content: [...syntheticResults, ...nextMessage.content]
1675
+ content: [...syntheticResults, ...nextMessage.content],
1447
1676
  };
1448
1677
  // Replace the next message in our iteration
1449
1678
  messages[i + 1] = updatedNextMessage;
@@ -1452,17 +1681,19 @@ export function fixOrphanedToolUse(messages) {
1452
1681
  else if (nextMessage && nextMessage.role === 'user' && !nextMessage.content) {
1453
1682
  // Next message is a user message but has no content
1454
1683
  // We need to add toolResults
1455
- const syntheticResults = toolUseBlocks.map(tu => ({
1684
+ const syntheticResults = toolUseBlocks.map((tu) => ({
1456
1685
  toolResult: {
1457
1686
  toolUseId: tu.toolUseId,
1458
- content: [{
1459
- text: `[Tool interrupted: The user stopped the operation before "${tu.name}" could execute.]`
1460
- }]
1461
- }
1687
+ content: [
1688
+ {
1689
+ text: `[Tool interrupted: The user stopped the operation before "${tu.name}" could execute.]`,
1690
+ },
1691
+ ],
1692
+ },
1462
1693
  }));
1463
1694
  const updatedNextMessage = {
1464
1695
  role: 'user',
1465
- content: syntheticResults
1696
+ content: syntheticResults,
1466
1697
  };
1467
1698
  messages[i + 1] = updatedNextMessage;
1468
1699
  }
@@ -1473,23 +1704,67 @@ export function fixOrphanedToolUse(messages) {
1473
1704
  }
1474
1705
  return result;
1475
1706
  }
1707
+ /**
1708
+ * Drop toolResult blocks whose toolUseId has no matching toolUse in the
1709
+ * immediately-preceding assistant message. Mirror of {@link fixOrphanedToolUse}:
1710
+ * that function synthesizes results for an unanswered toolUse (e.g. a cancelled
1711
+ * run); this one removes results left dangling after their toolUse was dropped
1712
+ * (e.g. by conversation compaction/trimming).
1713
+ *
1714
+ * Without this, the AWS Converse API rejects the request because every
1715
+ * toolResult must correspond to a toolUse in the previous message. Bedrock
1716
+ * conversations are already role-alternating, so a compaction that drops an
1717
+ * assistant toolUse turn leaves an orphaned toolResult (and a user/user
1718
+ * adjacency); dropping the orphan — and the now-empty message — repairs both.
1719
+ */
1720
+ export function fixOrphanedToolResults(messages) {
1721
+ if (messages.length === 0)
1722
+ return messages;
1723
+ const result = [];
1724
+ for (let i = 0; i < messages.length; i++) {
1725
+ const message = messages[i];
1726
+ if (message.role !== 'user' || !message.content) {
1727
+ result.push(message);
1728
+ continue;
1729
+ }
1730
+ const hasToolResult = message.content.some((block) => block.toolResult);
1731
+ if (!hasToolResult) {
1732
+ result.push(message);
1733
+ continue;
1734
+ }
1735
+ const prev = messages[i - 1];
1736
+ const allowedIds = new Set();
1737
+ if (prev && prev.role === 'assistant' && prev.content) {
1738
+ for (const block of prev.content) {
1739
+ if (block.toolUse?.toolUseId)
1740
+ allowedIds.add(block.toolUse.toolUseId);
1741
+ }
1742
+ }
1743
+ const filtered = message.content.filter((block) => block.toolResult ? allowedIds.has(block.toolResult.toolUseId ?? '') : true);
1744
+ // Drop the message if every block was an orphaned toolResult.
1745
+ if (filtered.length === 0)
1746
+ continue;
1747
+ result.push(filtered.length === message.content.length ? message : { ...message, content: filtered });
1748
+ }
1749
+ return result;
1750
+ }
1476
1751
  function formatAmazonModalities(modalities) {
1477
1752
  const standardizedModalities = [];
1478
1753
  for (const modality of modalities) {
1479
1754
  if (modality === ModelModality.TEXT) {
1480
- standardizedModalities.push("text");
1755
+ standardizedModalities.push('text');
1481
1756
  }
1482
1757
  else if (modality === ModelModality.IMAGE) {
1483
- standardizedModalities.push("image");
1758
+ standardizedModalities.push('image');
1484
1759
  }
1485
1760
  else if (modality === ModelModality.EMBEDDING) {
1486
- standardizedModalities.push("embedding");
1761
+ standardizedModalities.push('embedding');
1487
1762
  }
1488
- else if (modality === "SPEECH") {
1489
- standardizedModalities.push("audio");
1763
+ else if (modality === 'SPEECH') {
1764
+ standardizedModalities.push('audio');
1490
1765
  }
1491
- else if (modality === "VIDEO") {
1492
- standardizedModalities.push("video");
1766
+ else if (modality === 'VIDEO') {
1767
+ standardizedModalities.push('video');
1493
1768
  }
1494
1769
  else {
1495
1770
  // Handle other modalities as needed