@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
@@ -0,0 +1,517 @@
1
+ import { BEDROCK_DEFAULT_EMBEDDING_MODEL } from '@llumiverse/common';
2
+ import {
3
+ Base64DataSource,
4
+ buildEmbeddingsResult,
5
+ type DataSource,
6
+ dataSourceToBase64,
7
+ type EmbeddingInput,
8
+ type EmbeddingOutput,
9
+ type EmbeddingResultItem,
10
+ type EmbeddingsOptions,
11
+ type EmbeddingsResult,
12
+ type EmbeddingTaskType,
13
+ type ImageEmbeddingInput,
14
+ LlumiverseError,
15
+ normalizeEmbeddingsOptions,
16
+ type TextEmbeddingInput,
17
+ } from '@llumiverse/core';
18
+ import type { BedrockDriver } from './index.js';
19
+ import type { TwelvelabsMarengoRequest, TwelvelabsMarengoResponse } from './twelvelabs.js';
20
+
21
+ interface BedrockMediaSource {
22
+ base64String?: string;
23
+ s3Location?: {
24
+ uri: string;
25
+ bucketOwner?: string;
26
+ };
27
+ }
28
+
29
+ /** Matches s3[.region].amazonaws.com or bucket.s3[.region].amazonaws.com — anchored to prevent subdomain spoofing. */
30
+ const S3_HOSTNAME_RE = /^(?:[^.]+\.)?s3(?:\.[a-z0-9-]+)?\.amazonaws\.com$/;
31
+
32
+ function isS3Url(url: string): boolean {
33
+ if (url.startsWith('s3://')) return true;
34
+ try {
35
+ const parsed = new URL(url);
36
+ return S3_HOSTNAME_RE.test(parsed.hostname);
37
+ } catch {
38
+ return false;
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Converts an S3 HTTPS URL to s3:// URI form. Handles both addressing styles:
44
+ * virtual-hosted: https://bucket.s3[.region].amazonaws.com/key
45
+ * path-style: https://s3[.region].amazonaws.com/bucket/key
46
+ */
47
+ function toS3Uri(url: string): string {
48
+ if (url.startsWith('s3://')) return url;
49
+ const parsed = new URL(url);
50
+ // Virtual-hosted style: bucket.s3[.region].amazonaws.com
51
+ const virtualHostedMatch = parsed.hostname.match(/^([^.]+)\.s3(?:\.[a-z0-9-]+)?\.amazonaws\.com$/);
52
+ if (virtualHostedMatch) {
53
+ const bucket = virtualHostedMatch[1];
54
+ const key = parsed.pathname.replace(/^\/+/, '');
55
+ return `s3://${bucket}/${key}`;
56
+ }
57
+ // Path-style: s3[.region].amazonaws.com/bucket/key
58
+ const pathParts = parsed.pathname.replace(/^\/+/, '').split('/');
59
+ const bucket = pathParts[0];
60
+ const key = pathParts.slice(1).join('/');
61
+ return `s3://${bucket}/${key}`;
62
+ }
63
+
64
+ async function dataSourceToBedrockMediaSource(ds: DataSource): Promise<BedrockMediaSource> {
65
+ const url = await ds.getURL().catch(() => undefined);
66
+ if (url && isS3Url(url)) {
67
+ return { s3Location: { uri: toS3Uri(url) } };
68
+ }
69
+ if (ds instanceof Base64DataSource) {
70
+ return { base64String: ds.getBase64() };
71
+ }
72
+ return { base64String: await dataSourceToBase64(ds) };
73
+ }
74
+
75
+ async function invokeJson<R>(driver: BedrockDriver, modelId: string, body: unknown): Promise<R> {
76
+ const executor = driver.getExecutor();
77
+ const res = await executor.invokeModel({
78
+ modelId,
79
+ contentType: 'application/json',
80
+ accept: 'application/json',
81
+ body: JSON.stringify(body),
82
+ });
83
+ if (!res.body) throw new Error(`InvokeModel returned empty response body for model: ${modelId}`);
84
+ return JSON.parse(new TextDecoder().decode(res.body)) as R;
85
+ }
86
+
87
+ // ── Shared format lookup maps ───────────────────────────────────────────────
88
+
89
+ const MIME_TO_IMAGE_FORMAT: Record<string, string> = {
90
+ 'image/jpeg': 'jpeg',
91
+ 'image/jpg': 'jpeg',
92
+ 'image/png': 'png',
93
+ 'image/gif': 'gif',
94
+ 'image/webp': 'webp',
95
+ };
96
+
97
+ const MIME_TO_AUDIO_FORMAT: Record<string, string> = {
98
+ 'audio/mpeg': 'mp3',
99
+ 'audio/mp3': 'mp3',
100
+ 'audio/wav': 'wav',
101
+ 'audio/wave': 'wav',
102
+ 'audio/x-wav': 'wav',
103
+ 'audio/ogg': 'ogg',
104
+ };
105
+
106
+ const MIME_TO_VIDEO_FORMAT: Record<string, string> = {
107
+ 'video/mp4': 'mp4',
108
+ 'video/quicktime': 'mov',
109
+ 'video/x-matroska': 'mkv',
110
+ 'video/webm': 'webm',
111
+ 'video/x-flv': 'flv',
112
+ 'video/mpeg': 'mpeg',
113
+ 'video/mpg': 'mpg',
114
+ 'video/x-ms-wmv': 'wmv',
115
+ 'video/3gpp': '3gp',
116
+ };
117
+
118
+ function requireFormat(map: Record<string, string>, mime: string, label: string): string {
119
+ const fmt = map[mime.toLowerCase()];
120
+ if (!fmt) throw new Error(`Unsupported ${label} MIME type for Bedrock: '${mime}'`);
121
+ return fmt;
122
+ }
123
+
124
+ // =================== Nova multimodal ===================
125
+
126
+ /**
127
+ * Synchronous InvokeModel request body for amazon.nova-2-multimodal-embeddings-v1:0.
128
+ * Schema: https://docs.aws.amazon.com/nova/latest/userguide/embeddings-schema.html
129
+ *
130
+ * Sync limits (InvokeModel): text 8K tokens, image 50 MB S3 / 25 MB inline,
131
+ * audio/video 30 s / 100 MB S3 / 25 MB inline base64.
132
+ *
133
+ * For inputs exceeding these limits, the Bedrock Runtime exposes StartAsyncInvoke:
134
+ * the caller submits a job and receives an invocationArn, then polls GetAsyncInvoke
135
+ * until the job completes and reads segmented embeddings from the S3 output bucket.
136
+ * This is incompatible with a simple await-style interface and is not implemented here.
137
+ */
138
+
139
+ type NovaEmbeddingPurpose =
140
+ | 'GENERIC_INDEX'
141
+ | 'GENERIC_RETRIEVAL'
142
+ | 'TEXT_RETRIEVAL'
143
+ | 'IMAGE_RETRIEVAL'
144
+ | 'VIDEO_RETRIEVAL'
145
+ | 'DOCUMENT_RETRIEVAL'
146
+ | 'AUDIO_RETRIEVAL'
147
+ | 'CLASSIFICATION'
148
+ | 'CLUSTERING';
149
+
150
+ type NovaSource = { bytes: string } | { s3Location: { uri: string } };
151
+
152
+ interface NovaSingleEmbeddingParams {
153
+ embeddingPurpose: NovaEmbeddingPurpose;
154
+ embeddingDimension?: number;
155
+ text?: { truncationMode: 'START' | 'END' | 'NONE'; value: string };
156
+ image?: { format: string; source: NovaSource; detailLevel?: 'STANDARD_IMAGE' | 'DOCUMENT_IMAGE' };
157
+ audio?: { format: string; source: NovaSource };
158
+ video?: { format: string; source: NovaSource; embeddingMode: 'AUDIO_VIDEO_COMBINED' | 'AUDIO_VIDEO_SEPARATE' };
159
+ }
160
+
161
+ interface NovaEmbeddingRequest {
162
+ taskType: 'SINGLE_EMBEDDING';
163
+ singleEmbeddingParams: NovaSingleEmbeddingParams;
164
+ }
165
+
166
+ interface NovaEmbeddingResponse {
167
+ embeddings: Array<{
168
+ embeddingType: 'TEXT' | 'IMAGE' | 'VIDEO' | 'AUDIO' | 'AUDIO_VIDEO_COMBINED';
169
+ embedding: number[];
170
+ }>;
171
+ }
172
+
173
+ function toNovaEmbeddingPurpose(taskType: EmbeddingTaskType | undefined): NovaEmbeddingPurpose {
174
+ return taskType === 'query' ? 'GENERIC_RETRIEVAL' : 'GENERIC_INDEX';
175
+ }
176
+
177
+ async function toNovaSource(ds: DataSource): Promise<NovaSource> {
178
+ const url = await ds.getURL().catch(() => undefined);
179
+ if (url && isS3Url(url)) return { s3Location: { uri: toS3Uri(url) } };
180
+ const bytes = ds instanceof Base64DataSource ? ds.getBase64() : await dataSourceToBase64(ds);
181
+ return { bytes };
182
+ }
183
+
184
+ async function buildNovaParams(
185
+ input: EmbeddingInput,
186
+ ): Promise<Omit<NovaSingleEmbeddingParams, 'embeddingPurpose' | 'embeddingDimension'>> {
187
+ switch (input.type) {
188
+ case 'text':
189
+ return { text: { truncationMode: 'END', value: input.text } };
190
+ case 'image': {
191
+ const source = await toNovaSource(input.source);
192
+ return { image: { format: requireFormat(MIME_TO_IMAGE_FORMAT, input.source.mime_type, 'image'), source } };
193
+ }
194
+ case 'audio': {
195
+ const source = await toNovaSource(input.source);
196
+ return { audio: { format: requireFormat(MIME_TO_AUDIO_FORMAT, input.source.mime_type, 'audio'), source } };
197
+ }
198
+ case 'video': {
199
+ // Sync path supports video up to 30 s / 100 MB via S3 (or 25 MB inline base64).
200
+ // Longer video requires StartAsyncInvoke with segmentationConfig — not implemented.
201
+ const source = await toNovaSource(input.source);
202
+ return {
203
+ video: {
204
+ format: requireFormat(MIME_TO_VIDEO_FORMAT, input.source.mime_type, 'video'),
205
+ source,
206
+ embeddingMode: 'AUDIO_VIDEO_COMBINED',
207
+ },
208
+ };
209
+ }
210
+ }
211
+ }
212
+
213
+ async function generateNovaEmbeddings(
214
+ driver: BedrockDriver,
215
+ options: EmbeddingsOptions,
216
+ modelId: string,
217
+ ): Promise<EmbeddingsResult> {
218
+ const items: EmbeddingResultItem[] = [];
219
+
220
+ for (const input of options.inputs) {
221
+ const inputTaskType = input.type === 'text' ? input.task_type : undefined;
222
+ const purpose = toNovaEmbeddingPurpose(inputTaskType ?? options.task_type);
223
+ const modalParams = await buildNovaParams(input);
224
+ const request: NovaEmbeddingRequest = {
225
+ taskType: 'SINGLE_EMBEDDING',
226
+ singleEmbeddingParams: {
227
+ embeddingPurpose: purpose,
228
+ ...(options.dimensions ? { embeddingDimension: options.dimensions } : {}),
229
+ ...modalParams,
230
+ },
231
+ };
232
+ const response = await invokeJson<NovaEmbeddingResponse>(driver, modelId, request);
233
+ const item = response.embeddings?.[0];
234
+ if (!item?.embedding) {
235
+ throw new Error(
236
+ `Nova embeddings response missing 'embeddings[0].embedding' for input type '${input.type}'`,
237
+ );
238
+ }
239
+ items.push({ outputs: [{ values: item.embedding, modality: input.type }] });
240
+ }
241
+
242
+ return buildEmbeddingsResult(modelId, items);
243
+ }
244
+
245
+ // =================== Titan ===================
246
+
247
+ interface TitanTextRequest {
248
+ inputText: string;
249
+ dimensions?: number;
250
+ normalize?: boolean;
251
+ }
252
+ interface TitanTextResponse {
253
+ embedding: number[];
254
+ inputTextTokenCount?: number;
255
+ }
256
+ interface TitanImageRequest {
257
+ inputText?: string;
258
+ inputImage?: string;
259
+ embeddingConfig?: { outputEmbeddingLength?: number };
260
+ }
261
+ interface TitanImageResponse {
262
+ embedding?: number[];
263
+ inputTextTokenCount?: number;
264
+ message?: string;
265
+ }
266
+
267
+ async function generateTitanEmbeddings(
268
+ driver: BedrockDriver,
269
+ options: EmbeddingsOptions,
270
+ modelId: string,
271
+ ): Promise<EmbeddingsResult> {
272
+ const isImageModel = modelId.includes('titan-embed-image');
273
+ const items: EmbeddingResultItem[] = [];
274
+ let totalTokens: number | undefined;
275
+
276
+ for (const input of options.inputs) {
277
+ if (input.type === 'video' || input.type === 'audio') {
278
+ throw new Error(`Titan embeddings do not support '${input.type}' input`);
279
+ }
280
+
281
+ if (isImageModel) {
282
+ const body: TitanImageRequest = {};
283
+ if (input.type === 'text') body.inputText = input.text;
284
+ if (input.type === 'image') body.inputImage = await dataSourceToBase64(input.source);
285
+ if (options.dimensions) body.embeddingConfig = { outputEmbeddingLength: options.dimensions };
286
+ const res = await invokeJson<TitanImageResponse>(driver, modelId, body);
287
+ if (res.message) throw new Error(`Titan image embedding error: ${res.message}`);
288
+ if (!res.embedding) throw new Error(`Titan image embedding response missing 'embedding'`);
289
+ items.push({
290
+ outputs: [{ values: res.embedding, modality: input.type }],
291
+ input_tokens: res.inputTextTokenCount,
292
+ });
293
+ if (typeof res.inputTextTokenCount === 'number') totalTokens = (totalTokens ?? 0) + res.inputTextTokenCount;
294
+ } else {
295
+ if (input.type !== 'text') {
296
+ throw new Error(`Titan text embeddings model '${modelId}' only supports text input`);
297
+ }
298
+ const body: TitanTextRequest = { inputText: input.text };
299
+ if (options.dimensions) body.dimensions = options.dimensions;
300
+ const res = await invokeJson<TitanTextResponse>(driver, modelId, body);
301
+ if (!res.embedding) throw new Error(`Titan text embedding response missing 'embedding' (model ${modelId})`);
302
+ items.push({
303
+ outputs: [{ values: res.embedding, modality: 'text' }],
304
+ input_tokens: res.inputTextTokenCount,
305
+ });
306
+ if (typeof res.inputTextTokenCount === 'number') totalTokens = (totalTokens ?? 0) + res.inputTextTokenCount;
307
+ }
308
+ }
309
+
310
+ const usage = totalTokens !== undefined ? { input_tokens: totalTokens } : undefined;
311
+ return buildEmbeddingsResult(modelId, items, usage);
312
+ }
313
+
314
+ // =================== Cohere ===================
315
+
316
+ type CohereInputType = 'search_query' | 'search_document' | 'image';
317
+
318
+ interface CohereEmbeddingRequest {
319
+ texts?: string[];
320
+ images?: string[];
321
+ input_type?: CohereInputType;
322
+ }
323
+
324
+ interface CohereEmbeddingResponse {
325
+ embeddings: number[][];
326
+ texts?: string[];
327
+ response_type?: string;
328
+ }
329
+
330
+ function cohereInputType(taskType: EmbeddingTaskType | undefined): CohereInputType | undefined {
331
+ switch (taskType) {
332
+ case 'query':
333
+ return 'search_query';
334
+ case 'document':
335
+ return 'search_document';
336
+ default:
337
+ return undefined;
338
+ }
339
+ }
340
+
341
+ async function generateCohereEmbeddings(
342
+ driver: BedrockDriver,
343
+ options: EmbeddingsOptions,
344
+ modelId: string,
345
+ ): Promise<EmbeddingsResult> {
346
+ const textInputs: { index: number; input: TextEmbeddingInput }[] = [];
347
+ const imageInputs: { index: number; input: ImageEmbeddingInput }[] = [];
348
+ options.inputs.forEach((input, index) => {
349
+ if (input.type === 'text') textInputs.push({ index, input });
350
+ else if (input.type === 'image') imageInputs.push({ index, input });
351
+ else throw new Error(`Cohere embeddings do not support '${input.type}' input`);
352
+ });
353
+
354
+ const items = new Array<EmbeddingResultItem>(options.inputs.length);
355
+
356
+ // Group texts by their effective input_type so per-input task_type overrides are respected.
357
+ const textGroups = new Map<CohereInputType | undefined, { index: number; input: TextEmbeddingInput }[]>();
358
+ for (const entry of textInputs) {
359
+ const key = cohereInputType(entry.input.task_type ?? options.task_type);
360
+ if (!textGroups.has(key)) textGroups.set(key, []);
361
+ textGroups.get(key)?.push(entry);
362
+ }
363
+ for (const [groupInputType, group] of textGroups) {
364
+ const body: CohereEmbeddingRequest = {
365
+ texts: group.map((t) => t.input.text),
366
+ input_type: groupInputType,
367
+ };
368
+ const res = await invokeJson<CohereEmbeddingResponse>(driver, modelId, body);
369
+ if (res.embeddings.length !== group.length) {
370
+ driver.logger.warn(
371
+ `[Bedrock/Cohere] Embedding count mismatch: expected ${group.length}, got ${res.embeddings.length} (model ${modelId})`,
372
+ );
373
+ throw new Error(
374
+ `Cohere returned ${res.embeddings.length} embeddings for ${group.length} texts (model ${modelId})`,
375
+ );
376
+ }
377
+ group.forEach((entry, i) => {
378
+ items[entry.index] = { outputs: [{ values: res.embeddings[i], modality: 'text' }] };
379
+ });
380
+ }
381
+
382
+ // Cohere accepts exactly one image per call; images must be data URIs.
383
+ for (const entry of imageInputs) {
384
+ const base64 = await dataSourceToBase64(entry.input.source);
385
+ const dataUri = `data:${entry.input.source.mime_type};base64,${base64}`;
386
+ const body: CohereEmbeddingRequest = { images: [dataUri], input_type: 'image' };
387
+ const res = await invokeJson<CohereEmbeddingResponse>(driver, modelId, body);
388
+ if (!res.embeddings[0]) {
389
+ throw new Error(`Cohere returned no embedding for image input (model ${modelId})`);
390
+ }
391
+ items[entry.index] = { outputs: [{ values: res.embeddings[0], modality: 'image' }] };
392
+ }
393
+
394
+ return buildEmbeddingsResult(modelId, items);
395
+ }
396
+
397
+ // =================== TwelveLabs Marengo ===================
398
+
399
+ /** Marengo returns either a bare segment object or an envelope { embeddings: [...] }. */
400
+ type MarengoApiResponse = TwelvelabsMarengoResponse | { embeddings: TwelvelabsMarengoResponse[] };
401
+ function isMarengoEnvelope(r: MarengoApiResponse): r is { embeddings: TwelvelabsMarengoResponse[] } {
402
+ return Array.isArray((r as { embeddings?: unknown }).embeddings);
403
+ }
404
+
405
+ async function generateMarengoEmbeddings(
406
+ driver: BedrockDriver,
407
+ options: EmbeddingsOptions,
408
+ modelId: string,
409
+ ): Promise<EmbeddingsResult> {
410
+ const items: EmbeddingResultItem[] = [];
411
+
412
+ for (const input of options.inputs) {
413
+ const request = await buildMarengoRequest(input);
414
+ const response = await invokeJson<MarengoApiResponse>(driver, modelId, request);
415
+ const segments = isMarengoEnvelope(response) ? response.embeddings : [response];
416
+
417
+ const outputs: EmbeddingOutput[] = segments
418
+ .filter((seg) => Array.isArray(seg.embedding))
419
+ .map(
420
+ (seg) =>
421
+ ({
422
+ values: seg.embedding,
423
+ modality: input.type === 'text' ? 'text' : input.type,
424
+ start_sec: seg.startSec,
425
+ end_sec: seg.endSec,
426
+ embedding_option: seg.embeddingOption,
427
+ }) satisfies EmbeddingOutput,
428
+ );
429
+
430
+ if (outputs.length === 0) {
431
+ throw new Error(`Marengo response did not contain embedding values for input type '${input.type}'`);
432
+ }
433
+ items.push({ outputs });
434
+ }
435
+
436
+ return buildEmbeddingsResult(modelId, items);
437
+ }
438
+
439
+ async function buildMarengoRequest(input: EmbeddingInput): Promise<TwelvelabsMarengoRequest> {
440
+ switch (input.type) {
441
+ case 'text':
442
+ return { inputType: 'text', inputText: input.text };
443
+ case 'image': {
444
+ const media = await dataSourceToBedrockMediaSource(input.source);
445
+ return { inputType: 'image', mediaSource: media };
446
+ }
447
+ case 'video': {
448
+ const media = await dataSourceToBedrockMediaSource(input.source);
449
+ const request: TwelvelabsMarengoRequest = { inputType: 'video', mediaSource: media };
450
+ if (input.start_sec !== undefined) request.startSec = input.start_sec;
451
+ if (input.length_sec !== undefined) request.lengthSec = input.length_sec;
452
+ if (input.use_fixed_length_sec !== undefined) request.useFixedLengthSec = input.use_fixed_length_sec;
453
+ if (input.min_clip_sec !== undefined) request.minClipSec = input.min_clip_sec;
454
+ // Marengo accepts at most one embedding_option per request.
455
+ // For multiple views (e.g. visual-text + audio), submit separate inputs — one per option.
456
+ if (input.embedding_option) {
457
+ if (input.embedding_option.length > 1) {
458
+ throw new Error(
459
+ `Marengo accepts only one embedding_option per request; ` +
460
+ `received [${input.embedding_option.join(', ')}]. ` +
461
+ `Submit separate inputs, one per option.`,
462
+ );
463
+ }
464
+ if (input.embedding_option.length === 1) {
465
+ request.embeddingOption = input.embedding_option[0];
466
+ }
467
+ }
468
+ return request;
469
+ }
470
+ case 'audio': {
471
+ const media = await dataSourceToBedrockMediaSource(input.source);
472
+ const request: TwelvelabsMarengoRequest = { inputType: 'audio', mediaSource: media };
473
+ if (input.start_sec !== undefined) request.startSec = input.start_sec;
474
+ if (input.length_sec !== undefined) request.lengthSec = input.length_sec;
475
+ return request;
476
+ }
477
+ }
478
+ }
479
+
480
+ // =================== Routing ===================
481
+
482
+ export async function generateBedrockEmbeddings(
483
+ driver: BedrockDriver,
484
+ options: EmbeddingsOptions,
485
+ ): Promise<EmbeddingsResult> {
486
+ const normalized = normalizeEmbeddingsOptions(options);
487
+ const modelId = normalized.model ?? BEDROCK_DEFAULT_EMBEDDING_MODEL;
488
+ driver.logger.info(
489
+ `[Bedrock] Generating embeddings with model ${modelId} for ${normalized.inputs.length} input(s)`,
490
+ );
491
+ try {
492
+ if (modelId.includes('twelvelabs.marengo')) {
493
+ return await generateMarengoEmbeddings(driver, normalized, modelId);
494
+ }
495
+ if (modelId.startsWith('cohere.embed')) {
496
+ return await generateCohereEmbeddings(driver, normalized, modelId);
497
+ }
498
+ if (modelId.includes('titan-embed')) {
499
+ return await generateTitanEmbeddings(driver, normalized, modelId);
500
+ }
501
+ return await generateNovaEmbeddings(driver, normalized, modelId);
502
+ } catch (error) {
503
+ if (LlumiverseError.isLlumiverseError(error)) throw error;
504
+ // Re-throw plain validation errors (thrown before any HTTP call) as-is.
505
+ if (
506
+ error instanceof Error &&
507
+ typeof (error as { $metadata?: unknown }).$metadata === 'undefined' &&
508
+ typeof (error as { status?: unknown }).status !== 'number'
509
+ )
510
+ throw error;
511
+ throw driver.formatLlumiverseError(error, {
512
+ provider: 'bedrock',
513
+ model: modelId,
514
+ operation: 'execute',
515
+ });
516
+ }
517
+ }
@@ -1,7 +1,18 @@
1
1
  import { LlumiverseError } from '@llumiverse/core';
2
2
  import { beforeEach, describe, expect, it } from 'vitest';
3
+ import { exposePrivate } from '../../test/__helpers__/test-utils.js';
3
4
  import { BedrockDriver } from './index.js';
4
5
 
6
+ type BedrockDriverInternals = {
7
+ isBedrockErrorRetryable: (
8
+ errorName: string,
9
+ httpStatusCode: number | undefined,
10
+ fault: string | undefined,
11
+ ) => boolean | undefined;
12
+ };
13
+
14
+ type AwsErrorMetadata = { $metadata: { requestId?: string; httpStatusCode?: number } };
15
+
5
16
  describe('BedrockDriver Error Handling', () => {
6
17
  let driver: BedrockDriver;
7
18
 
@@ -13,7 +24,8 @@ describe('BedrockDriver Error Handling', () => {
13
24
  it('should handle ValidationException with status code in message', () => {
14
25
  const awsError = {
15
26
  name: 'ValidationException',
16
- message: "1 validation error detected: Value '32424.0' at 'inferenceConfig.temperature' failed to satisfy constraint: Member must have value less than or equal to 1",
27
+ message:
28
+ "1 validation error detected: Value '32424.0' at 'inferenceConfig.temperature' failed to satisfy constraint: Member must have value less than or equal to 1",
17
29
  $fault: 'client',
18
30
  $metadata: {
19
31
  httpStatusCode: 400,
@@ -298,7 +310,7 @@ describe('BedrockDriver Error Handling', () => {
298
310
  });
299
311
 
300
312
  expect(error.originalError).toBe(awsError);
301
- expect((error.originalError as any).$metadata.requestId).toBe('test-123');
313
+ expect((error.originalError as AwsErrorMetadata).$metadata.requestId).toBe('test-123');
302
314
  });
303
315
  });
304
316
 
@@ -312,7 +324,11 @@ describe('BedrockDriver Error Handling', () => {
312
324
  ];
313
325
 
314
326
  retryableErrors.forEach((errorName) => {
315
- const result = (driver as any).isBedrockErrorRetryable(errorName, undefined, undefined);
327
+ const result = exposePrivate<BedrockDriverInternals>(driver).isBedrockErrorRetryable(
328
+ errorName,
329
+ undefined,
330
+ undefined,
331
+ );
316
332
  expect(result, `${errorName} should be retryable`).toBe(true);
317
333
  });
318
334
  });
@@ -328,25 +344,57 @@ describe('BedrockDriver Error Handling', () => {
328
344
  ];
329
345
 
330
346
  nonRetryableErrors.forEach((errorName) => {
331
- const result = (driver as any).isBedrockErrorRetryable(errorName, undefined, undefined);
347
+ const result = exposePrivate<BedrockDriverInternals>(driver).isBedrockErrorRetryable(
348
+ errorName,
349
+ undefined,
350
+ undefined,
351
+ );
332
352
  expect(result, `${errorName} should not be retryable`).toBe(false);
333
353
  });
334
354
  });
335
355
 
336
356
  it('should use HTTP status codes when available', () => {
337
- expect((driver as any).isBedrockErrorRetryable('UnknownError', 429, undefined)).toBe(true);
338
- expect((driver as any).isBedrockErrorRetryable('UnknownError', 408, undefined)).toBe(true);
339
- expect((driver as any).isBedrockErrorRetryable('UnknownError', 529, undefined)).toBe(true);
340
- expect((driver as any).isBedrockErrorRetryable('UnknownError', 500, undefined)).toBe(true);
341
- expect((driver as any).isBedrockErrorRetryable('UnknownError', 503, undefined)).toBe(true);
342
- expect((driver as any).isBedrockErrorRetryable('UnknownError', 400, undefined)).toBe(false);
343
- expect((driver as any).isBedrockErrorRetryable('UnknownError', 403, undefined)).toBe(false);
344
- expect((driver as any).isBedrockErrorRetryable('UnknownError', 404, undefined)).toBe(false);
357
+ expect(
358
+ exposePrivate<BedrockDriverInternals>(driver).isBedrockErrorRetryable('UnknownError', 429, undefined),
359
+ ).toBe(true);
360
+ expect(
361
+ exposePrivate<BedrockDriverInternals>(driver).isBedrockErrorRetryable('UnknownError', 408, undefined),
362
+ ).toBe(true);
363
+ expect(
364
+ exposePrivate<BedrockDriverInternals>(driver).isBedrockErrorRetryable('UnknownError', 529, undefined),
365
+ ).toBe(true);
366
+ expect(
367
+ exposePrivate<BedrockDriverInternals>(driver).isBedrockErrorRetryable('UnknownError', 500, undefined),
368
+ ).toBe(true);
369
+ expect(
370
+ exposePrivate<BedrockDriverInternals>(driver).isBedrockErrorRetryable('UnknownError', 503, undefined),
371
+ ).toBe(true);
372
+ expect(
373
+ exposePrivate<BedrockDriverInternals>(driver).isBedrockErrorRetryable('UnknownError', 400, undefined),
374
+ ).toBe(false);
375
+ expect(
376
+ exposePrivate<BedrockDriverInternals>(driver).isBedrockErrorRetryable('UnknownError', 403, undefined),
377
+ ).toBe(false);
378
+ expect(
379
+ exposePrivate<BedrockDriverInternals>(driver).isBedrockErrorRetryable('UnknownError', 404, undefined),
380
+ ).toBe(false);
345
381
  });
346
382
 
347
383
  it('should use fault type as fallback', () => {
348
- expect((driver as any).isBedrockErrorRetryable('UnknownError', undefined, 'server')).toBe(true);
349
- expect((driver as any).isBedrockErrorRetryable('UnknownError', undefined, 'client')).toBe(false);
384
+ expect(
385
+ exposePrivate<BedrockDriverInternals>(driver).isBedrockErrorRetryable(
386
+ 'UnknownError',
387
+ undefined,
388
+ 'server',
389
+ ),
390
+ ).toBe(true);
391
+ expect(
392
+ exposePrivate<BedrockDriverInternals>(driver).isBedrockErrorRetryable(
393
+ 'UnknownError',
394
+ undefined,
395
+ 'client',
396
+ ),
397
+ ).toBe(false);
350
398
  });
351
399
  });
352
400
  });