@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,497 @@
1
+ /**
2
+ * VertexAI embedding driver tests.
3
+ *
4
+ * Default (USE_REAL_API = false): all Google API calls are mocked — no
5
+ * credentials or network access required.
6
+ * Live mode (USE_REAL_API = true): a real VertexAIDriver is used for the live
7
+ * describe block. Requires Application Default Credentials (ADC) in the
8
+ * environment (e.g. `gcloud auth application-default login`) and the models
9
+ * enabled in your Vertex AI project.
10
+ */
11
+ import { helpers } from '@google-cloud/aiplatform';
12
+ import { Base64DataSource, URLDataSource } from '@llumiverse/core';
13
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
14
+ import { VertexAIDriver } from '../index.js';
15
+ import { generateVertexAiEmbeddings } from './embed.js';
16
+ import { generateLegacyMultimodalEmbeddings } from './embed-legacy-multimodal.js';
17
+
18
+ // ── Live-mode toggle ──────────────────────────────────────────────────────────
19
+ /** Set to true to run tests against the real Vertex AI API instead of mocks. */
20
+ const USE_REAL_API = false;
21
+ /** GCP project used for live tests. */
22
+ const LIVE_PROJECT = process.env.GOOGLE_CLOUD_PROJECT ?? 'your-gcp-project';
23
+ /** GCP region used for live tests. */
24
+ const LIVE_REGION = process.env.GOOGLE_CLOUD_REGION ?? 'us-central1';
25
+
26
+ /**
27
+ * Minimal 8×8 white PNG (base64) used as inline image fixture in live tests.
28
+ */
29
+ const TINY_PNG_B64 =
30
+ 'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAADklEQVQI12P4' + 'z8BQDwADhQGAWjR9awAAAABJRU5ErkJggg==';
31
+
32
+ // ── Mock helpers ──────────────────────────────────────────────────────────────
33
+
34
+ const FAKE_VECTOR = [0.1, 0.2, 0.3];
35
+
36
+ /** Build a VertexAIDriver with getGoogleGenAIClient mocked to return fake embedContent results. */
37
+ function makeEmbedContentDriver(embeddingsList: Array<{ values: number[]; statistics?: { tokenCount: number } }>) {
38
+ const driver = new VertexAIDriver({ project: 'test-project', region: 'us-central1' });
39
+
40
+ const mockEmbedContent = vi.fn().mockResolvedValue({ embeddings: embeddingsList });
41
+ const mockModels = { embedContent: mockEmbedContent };
42
+ vi.spyOn(driver, 'getGoogleGenAIClient').mockReturnValue({ models: mockModels } as never);
43
+
44
+ return { driver, mockEmbedContent };
45
+ }
46
+
47
+ /**
48
+ * Build a VertexAIDriver with getPredictionServiceClient mocked for the
49
+ * legacy multimodalembedding@001 predict path.
50
+ */
51
+ function makeLegacyDriver(predictions: Array<Record<string, unknown>>) {
52
+ const driver = new VertexAIDriver({ project: 'test-project', region: 'us-central1' });
53
+
54
+ // Encode predictions as Protobuf Struct values via @google-cloud/aiplatform helpers
55
+ const encoded = predictions.map((p) => helpers.toValue(p));
56
+
57
+ const mockPredict = vi.fn().mockResolvedValue([{ predictions: encoded }]);
58
+ const mockClient = { predict: mockPredict };
59
+ vi.spyOn(driver, 'getPredictionServiceClient').mockResolvedValue(mockClient as never);
60
+
61
+ return { driver, mockPredict };
62
+ }
63
+
64
+ // =================== embedContent (embed.ts) ===================
65
+
66
+ describe('generateVertexAiEmbeddings — text embedding (text-embedding-005)', () => {
67
+ beforeEach(() => {
68
+ vi.restoreAllMocks();
69
+ });
70
+
71
+ it('embeds a single text and maps result', async () => {
72
+ const { driver, mockEmbedContent } = makeEmbedContentDriver([
73
+ { values: FAKE_VECTOR, statistics: { tokenCount: 5 } },
74
+ ]);
75
+ const result = await generateVertexAiEmbeddings(driver, {
76
+ inputs: [{ type: 'text', text: 'hello world' }],
77
+ model: 'text-embedding-005',
78
+ });
79
+
80
+ expect(mockEmbedContent).toHaveBeenCalledTimes(1);
81
+ const call = mockEmbedContent.mock.calls[0][0];
82
+ expect(call.model).toBe('text-embedding-005');
83
+ expect(call.contents[0].parts[0].text).toBe('hello world');
84
+
85
+ expect(result.results).toHaveLength(1);
86
+ expect(result.results[0].outputs[0].values).toEqual(FAKE_VECTOR);
87
+ expect(result.results[0].outputs[0].modality).toBe('text');
88
+ expect(result.usage?.input_tokens).toBe(5);
89
+ });
90
+
91
+ it("sets taskType RETRIEVAL_QUERY for task_type 'query'", async () => {
92
+ const { driver, mockEmbedContent } = makeEmbedContentDriver([{ values: FAKE_VECTOR }]);
93
+ // task_type at the options level is now propagated to inputs internally
94
+ await generateVertexAiEmbeddings(driver, {
95
+ inputs: [{ type: 'text', text: 'search query' }],
96
+ model: 'text-embedding-005',
97
+ task_type: 'query',
98
+ });
99
+
100
+ const call = mockEmbedContent.mock.calls[0][0];
101
+ expect(call.config?.taskType).toBe('RETRIEVAL_QUERY');
102
+ });
103
+
104
+ it("sets taskType RETRIEVAL_DOCUMENT for task_type 'document'", async () => {
105
+ const { driver, mockEmbedContent } = makeEmbedContentDriver([{ values: FAKE_VECTOR }]);
106
+ await generateVertexAiEmbeddings(driver, {
107
+ inputs: [{ type: 'text', text: 'a document', task_type: 'document' }],
108
+ model: 'text-embedding-005',
109
+ });
110
+
111
+ const call = mockEmbedContent.mock.calls[0][0];
112
+ expect(call.config?.taskType).toBe('RETRIEVAL_DOCUMENT');
113
+ });
114
+
115
+ it('passes outputDimensionality when dimensions is set', async () => {
116
+ const { driver, mockEmbedContent } = makeEmbedContentDriver([{ values: FAKE_VECTOR }]);
117
+ await generateVertexAiEmbeddings(driver, {
118
+ inputs: [{ type: 'text', text: 'x' }],
119
+ model: 'text-embedding-005',
120
+ dimensions: 128,
121
+ });
122
+
123
+ const call = mockEmbedContent.mock.calls[0][0];
124
+ expect(call.config?.outputDimensionality).toBe(128);
125
+ });
126
+
127
+ it('batches inputs with the same config in a single call', async () => {
128
+ const { driver, mockEmbedContent } = makeEmbedContentDriver([{ values: FAKE_VECTOR }, { values: [0.4, 0.5] }]);
129
+ const result = await generateVertexAiEmbeddings(driver, {
130
+ inputs: [
131
+ { type: 'text', text: 'first' },
132
+ { type: 'text', text: 'second' },
133
+ ],
134
+ model: 'text-embedding-005',
135
+ task_type: 'document',
136
+ });
137
+
138
+ expect(mockEmbedContent).toHaveBeenCalledTimes(1);
139
+ const call = mockEmbedContent.mock.calls[0][0];
140
+ expect(call.config?.taskType).toBe('RETRIEVAL_DOCUMENT');
141
+ expect(result.results).toHaveLength(2);
142
+ expect(result.results[0].outputs[0].values).toEqual(FAKE_VECTOR);
143
+ expect(result.results[1].outputs[0].values).toEqual([0.4, 0.5]);
144
+ });
145
+
146
+ it('issues separate calls for inputs with different config signatures', async () => {
147
+ const { driver, mockEmbedContent } = makeEmbedContentDriver([{ values: FAKE_VECTOR }]);
148
+ await generateVertexAiEmbeddings(driver, {
149
+ inputs: [
150
+ { type: 'text', text: 'query text', task_type: 'query' },
151
+ { type: 'text', text: 'doc text', task_type: 'document' },
152
+ ],
153
+ model: 'text-embedding-005',
154
+ });
155
+
156
+ // Different taskType → different config signature → 2 API calls
157
+ expect(mockEmbedContent).toHaveBeenCalledTimes(2);
158
+ });
159
+
160
+ it('per-input task_type overrides the global default', async () => {
161
+ const { driver, mockEmbedContent } = makeEmbedContentDriver([{ values: FAKE_VECTOR }]);
162
+ await generateVertexAiEmbeddings(driver, {
163
+ inputs: [{ type: 'text', text: 'override', task_type: 'query' }],
164
+ model: 'text-embedding-005',
165
+ task_type: 'document',
166
+ });
167
+
168
+ const call = mockEmbedContent.mock.calls[0][0];
169
+ expect(call.config?.taskType).toBe('RETRIEVAL_QUERY');
170
+ });
171
+
172
+ it('preserves result order when groups are batched out-of-order', async () => {
173
+ // Two query texts + one document text → 2 calls; order in result must match input order
174
+ const { driver, mockEmbedContent } = makeEmbedContentDriver([{ values: [1, 2] }]);
175
+ // Second call returns different vector
176
+ mockEmbedContent.mockResolvedValueOnce({ embeddings: [{ values: [1, 2] }, { values: [3, 4] }] });
177
+ mockEmbedContent.mockResolvedValueOnce({ embeddings: [{ values: [5, 6] }] });
178
+
179
+ const result = await generateVertexAiEmbeddings(driver, {
180
+ inputs: [
181
+ { type: 'text', text: 'q1', task_type: 'query' },
182
+ { type: 'text', text: 'q2', task_type: 'query' },
183
+ { type: 'text', text: 'd1', task_type: 'document' },
184
+ ],
185
+ model: 'text-embedding-005',
186
+ });
187
+
188
+ expect(result.results).toHaveLength(3);
189
+ // first batch (query): inputs 0 and 1
190
+ expect(result.results[0].outputs[0].values).toEqual([1, 2]);
191
+ expect(result.results[1].outputs[0].values).toEqual([3, 4]);
192
+ // second batch (document): input 2
193
+ expect(result.results[2].outputs[0].values).toEqual([5, 6]);
194
+ });
195
+ });
196
+
197
+ describe('generateVertexAiEmbeddings — image embedding (text-embedding-005)', () => {
198
+ beforeEach(() => {
199
+ vi.restoreAllMocks();
200
+ });
201
+
202
+ it('embeds inline base64 image', async () => {
203
+ const { driver, mockEmbedContent } = makeEmbedContentDriver([{ values: FAKE_VECTOR }]);
204
+ const b64 = Buffer.from('img-bytes').toString('base64');
205
+ const ds = new Base64DataSource('img.jpg', 'image/jpeg', b64);
206
+
207
+ const result = await generateVertexAiEmbeddings(driver, {
208
+ inputs: [{ type: 'image', source: ds }],
209
+ model: 'text-embedding-005',
210
+ });
211
+
212
+ const call = mockEmbedContent.mock.calls[0][0];
213
+ expect(call.contents[0].parts[0].inlineData?.mimeType).toBe('image/jpeg');
214
+ expect(call.contents[0].parts[0].inlineData?.data).toBe(b64);
215
+ expect(result.results[0].outputs[0].modality).toBe('image');
216
+ });
217
+
218
+ it('uses fileData for GCS image URLs', async () => {
219
+ const { driver, mockEmbedContent } = makeEmbedContentDriver([{ values: FAKE_VECTOR }]);
220
+ const ds = new URLDataSource('img.jpg', 'image/jpeg', 'gs://my-bucket/img.jpg');
221
+
222
+ await generateVertexAiEmbeddings(driver, {
223
+ inputs: [{ type: 'image', source: ds }],
224
+ model: 'text-embedding-005',
225
+ });
226
+
227
+ const part = mockEmbedContent.mock.calls[0][0].contents[0].parts[0];
228
+ expect(part.fileData?.fileUri).toBe('gs://my-bucket/img.jpg');
229
+ expect(part.inlineData).toBeUndefined();
230
+ });
231
+ });
232
+
233
+ describe('generateVertexAiEmbeddings — gemini-embedding-2 prefix model', () => {
234
+ beforeEach(() => {
235
+ vi.restoreAllMocks();
236
+ });
237
+
238
+ it('prepends task prefix instead of sending taskType config', async () => {
239
+ const { driver, mockEmbedContent } = makeEmbedContentDriver([{ values: FAKE_VECTOR }]);
240
+ await generateVertexAiEmbeddings(driver, {
241
+ inputs: [{ type: 'text', text: 'find something', task_type: 'query' }],
242
+ model: 'gemini-embedding-2',
243
+ });
244
+
245
+ const call = mockEmbedContent.mock.calls[0][0];
246
+ // Config must NOT contain taskType (prefix-only model)
247
+ expect(call.config?.taskType).toBeUndefined();
248
+ // Text must be prefixed (query → "task: search result | query: {text}")
249
+ const text: string = call.contents[0].parts[0].text;
250
+ expect(text).toBe('task: search result | query: find something');
251
+ });
252
+
253
+ it('builds document prefix with title when title is set', async () => {
254
+ const { driver, mockEmbedContent } = makeEmbedContentDriver([{ values: FAKE_VECTOR }]);
255
+ await generateVertexAiEmbeddings(driver, {
256
+ inputs: [{ type: 'text', text: 'content', task_type: 'document', title: 'My Doc' }],
257
+ model: 'gemini-embedding-2',
258
+ });
259
+
260
+ const text: string = mockEmbedContent.mock.calls[0][0].contents[0].parts[0].text;
261
+ expect(text).toBe('title: My Doc | text: content');
262
+ });
263
+
264
+ it("uses 'title: none' when title is absent for document prefix", async () => {
265
+ const { driver, mockEmbedContent } = makeEmbedContentDriver([{ values: FAKE_VECTOR }]);
266
+ await generateVertexAiEmbeddings(driver, {
267
+ inputs: [{ type: 'text', text: 'content', task_type: 'document' }],
268
+ model: 'gemini-embedding-2',
269
+ });
270
+
271
+ const text: string = mockEmbedContent.mock.calls[0][0].contents[0].parts[0].text;
272
+ expect(text).toBe('title: none | text: content');
273
+ });
274
+
275
+ it("uses 'global' region client for gemini-embedding-2", async () => {
276
+ const driver = new VertexAIDriver({ project: 'test-project', region: 'us-central1' });
277
+ const mockEmbedContent = vi.fn().mockResolvedValue({ embeddings: [{ values: FAKE_VECTOR }] });
278
+ const getClientSpy = vi
279
+ .spyOn(driver, 'getGoogleGenAIClient')
280
+ .mockReturnValue({ models: { embedContent: mockEmbedContent } } as never);
281
+
282
+ await generateVertexAiEmbeddings(driver, {
283
+ inputs: [{ type: 'text', text: 'x' }],
284
+ model: 'gemini-embedding-2',
285
+ });
286
+
287
+ expect(getClientSpy).toHaveBeenCalledWith('global');
288
+ });
289
+ });
290
+
291
+ // =================== Legacy multimodal (embed-legacy-multimodal.ts) ===================
292
+
293
+ describe('generateLegacyMultimodalEmbeddings — multimodalembedding@001', () => {
294
+ beforeEach(() => {
295
+ vi.restoreAllMocks();
296
+ });
297
+
298
+ it('embeds a text input', async () => {
299
+ const { driver, mockPredict } = makeLegacyDriver([{ textEmbedding: FAKE_VECTOR }]);
300
+ const result = await generateLegacyMultimodalEmbeddings(driver, {
301
+ inputs: [{ type: 'text', text: 'hello' }],
302
+ });
303
+
304
+ expect(mockPredict).toHaveBeenCalledTimes(1);
305
+ expect(result.results).toHaveLength(1);
306
+ expect(result.results[0].outputs[0].values).toEqual(FAKE_VECTOR);
307
+ expect(result.results[0].outputs[0].modality).toBe('text');
308
+ });
309
+
310
+ it('embeds an inline base64 image', async () => {
311
+ const { driver, mockPredict } = makeLegacyDriver([{ imageEmbedding: FAKE_VECTOR }]);
312
+ const b64 = Buffer.from('img').toString('base64');
313
+ const ds = new Base64DataSource('img.jpg', 'image/jpeg', b64);
314
+
315
+ const result = await generateLegacyMultimodalEmbeddings(driver, {
316
+ inputs: [{ type: 'image', source: ds }],
317
+ });
318
+
319
+ expect(mockPredict).toHaveBeenCalledTimes(1);
320
+ expect(result.results[0].outputs[0].values).toEqual(FAKE_VECTOR);
321
+ expect(result.results[0].outputs[0].modality).toBe('image');
322
+ });
323
+
324
+ it('embeds a video and returns segmented outputs', async () => {
325
+ const { driver } = makeLegacyDriver([
326
+ {
327
+ videoEmbeddings: [
328
+ { embedding: [0.1, 0.2], startOffsetSec: 0, endOffsetSec: 5 },
329
+ { embedding: [0.3, 0.4], startOffsetSec: 5, endOffsetSec: 10 },
330
+ ],
331
+ },
332
+ ]);
333
+ const ds = new URLDataSource('v.mp4', 'video/mp4', 'gs://my-bucket/v.mp4');
334
+
335
+ const result = await generateLegacyMultimodalEmbeddings(driver, {
336
+ inputs: [{ type: 'video', source: ds }],
337
+ });
338
+
339
+ expect(result.results[0].outputs).toHaveLength(2);
340
+ expect(result.results[0].outputs[0].start_sec).toBe(0);
341
+ expect(result.results[0].outputs[1].start_sec).toBe(5);
342
+ });
343
+
344
+ it('routes audio through the video path', async () => {
345
+ const { driver, mockPredict } = makeLegacyDriver([{ videoEmbeddings: [{ embedding: FAKE_VECTOR }] }]);
346
+ const ds = new URLDataSource('a.mp3', 'audio/mpeg', 'gs://my-bucket/a.mp3');
347
+
348
+ const result = await generateLegacyMultimodalEmbeddings(driver, {
349
+ inputs: [{ type: 'audio', source: ds }],
350
+ });
351
+
352
+ expect(mockPredict).toHaveBeenCalledTimes(1);
353
+ expect(result.results[0].outputs[0].modality).toBe('audio');
354
+ });
355
+
356
+ it('passes dimension parameter to predict', async () => {
357
+ const { driver, mockPredict } = makeLegacyDriver([{ textEmbedding: FAKE_VECTOR }]);
358
+ await generateLegacyMultimodalEmbeddings(driver, {
359
+ inputs: [{ type: 'text', text: 'x' }],
360
+ dimensions: 256,
361
+ });
362
+
363
+ const call = mockPredict.mock.calls[0][0];
364
+ // parameters should be a Protobuf Value encoding { dimension: 256 }
365
+ expect(call.parameters).toBeDefined();
366
+ });
367
+
368
+ it('throws when prediction count mismatches input count', async () => {
369
+ // Return 2 predictions for 1 input
370
+ const { driver } = makeLegacyDriver([{ textEmbedding: FAKE_VECTOR }, { textEmbedding: [0.9, 0.8] }]);
371
+ // Only send 1 input so the count check fires
372
+ await expect(
373
+ generateLegacyMultimodalEmbeddings(driver, {
374
+ inputs: [{ type: 'text', text: 'one' }],
375
+ }),
376
+ ).rejects.toThrow(/predictions for .* instances/);
377
+ });
378
+ });
379
+
380
+ // =================== Routing from generateVertexAiEmbeddings ===================
381
+
382
+ describe('generateVertexAiEmbeddings — legacy multimodal routing', () => {
383
+ beforeEach(() => {
384
+ vi.restoreAllMocks();
385
+ });
386
+
387
+ it('routes to legacy predict path when model is multimodalembedding@001', async () => {
388
+ const { driver, mockPredict } = makeLegacyDriver([{ textEmbedding: FAKE_VECTOR }]);
389
+ const result = await generateVertexAiEmbeddings(driver, {
390
+ inputs: [{ type: 'text', text: 'hello' }],
391
+ model: 'multimodalembedding@001',
392
+ });
393
+
394
+ expect(mockPredict).toHaveBeenCalledTimes(1);
395
+ expect(result.results).toHaveLength(1);
396
+ expect(result.results[0].outputs[0].values).toEqual(FAKE_VECTOR);
397
+ expect(result.results[0].outputs[0].modality).toBe('text');
398
+ });
399
+ });
400
+
401
+ // =================== Live API tests ===================
402
+ // Skipped unless USE_REAL_API = true.
403
+ // Each test has a 30 s timeout to accommodate network latency.
404
+
405
+ function makeLiveDriver() {
406
+ return new VertexAIDriver({ project: LIVE_PROJECT, region: LIVE_REGION });
407
+ }
408
+
409
+ function assertVector(values: number[]) {
410
+ expect(Array.isArray(values)).toBe(true);
411
+ expect(values.length).toBeGreaterThan(0);
412
+ expect(values.every((v) => typeof v === 'number' && Number.isFinite(v))).toBe(true);
413
+ }
414
+
415
+ describe.skipIf(!USE_REAL_API)('generateVertexAiEmbeddings — live API', () => {
416
+ it('text-embedding-005: text embedding (RETRIEVAL_DOCUMENT)', async () => {
417
+ const result = await generateVertexAiEmbeddings(makeLiveDriver(), {
418
+ inputs: [{ type: 'text', text: 'The quick brown fox jumps over the lazy dog' }],
419
+ model: 'text-embedding-005',
420
+ task_type: 'document',
421
+ });
422
+ expect(result.results).toHaveLength(1);
423
+ assertVector(result.results[0].outputs[0].values);
424
+ expect(result.results[0].outputs[0].modality).toBe('text');
425
+ }, 30_000);
426
+
427
+ it('text-embedding-005: text embedding (RETRIEVAL_QUERY)', async () => {
428
+ const result = await generateVertexAiEmbeddings(makeLiveDriver(), {
429
+ inputs: [{ type: 'text', text: 'what is the capital of France?' }],
430
+ model: 'text-embedding-005',
431
+ task_type: 'query',
432
+ });
433
+ assertVector(result.results[0].outputs[0].values);
434
+ }, 30_000);
435
+
436
+ it('text-embedding-005: dimensions param respected', async () => {
437
+ const result = await generateVertexAiEmbeddings(makeLiveDriver(), {
438
+ inputs: [{ type: 'text', text: 'dimension test' }],
439
+ model: 'text-embedding-005',
440
+ dimensions: 128,
441
+ });
442
+ assertVector(result.results[0].outputs[0].values);
443
+ expect(result.results[0].outputs[0].values.length).toBe(128);
444
+ }, 30_000);
445
+
446
+ it('text-embedding-005: batch — two texts in one call', async () => {
447
+ const result = await generateVertexAiEmbeddings(makeLiveDriver(), {
448
+ inputs: [
449
+ { type: 'text', text: 'first document' },
450
+ { type: 'text', text: 'second document' },
451
+ ],
452
+ model: 'text-embedding-005',
453
+ task_type: 'document',
454
+ });
455
+ expect(result.results).toHaveLength(2);
456
+ assertVector(result.results[0].outputs[0].values);
457
+ assertVector(result.results[1].outputs[0].values);
458
+ }, 30_000);
459
+
460
+ it('text-embedding-005: inline image embedding', async () => {
461
+ const ds = new Base64DataSource('pixel.png', 'image/png', TINY_PNG_B64);
462
+ const result = await generateVertexAiEmbeddings(makeLiveDriver(), {
463
+ inputs: [{ type: 'image', source: ds }],
464
+ model: 'text-embedding-005',
465
+ });
466
+ expect(result.results).toHaveLength(1);
467
+ assertVector(result.results[0].outputs[0].values);
468
+ }, 30_000);
469
+
470
+ it('gemini-embedding-2: text embedding with task prefix', async () => {
471
+ const result = await generateVertexAiEmbeddings(makeLiveDriver(), {
472
+ inputs: [{ type: 'text', text: 'find something relevant' }],
473
+ model: 'gemini-embedding-2',
474
+ task_type: 'query',
475
+ });
476
+ assertVector(result.results[0].outputs[0].values);
477
+ }, 30_000);
478
+ });
479
+
480
+ describe.skipIf(!USE_REAL_API)('generateLegacyMultimodalEmbeddings — live API', () => {
481
+ it('multimodalembedding@001: text embedding', async () => {
482
+ const result = await generateLegacyMultimodalEmbeddings(makeLiveDriver(), {
483
+ inputs: [{ type: 'text', text: 'The quick brown fox' }],
484
+ });
485
+ expect(result.results).toHaveLength(1);
486
+ assertVector(result.results[0].outputs[0].values);
487
+ }, 30_000);
488
+
489
+ it('multimodalembedding@001: image embedding (inline base64)', async () => {
490
+ const ds = new Base64DataSource('pixel.png', 'image/png', TINY_PNG_B64);
491
+ const result = await generateLegacyMultimodalEmbeddings(makeLiveDriver(), {
492
+ inputs: [{ type: 'image', source: ds }],
493
+ });
494
+ expect(result.results).toHaveLength(1);
495
+ assertVector(result.results[0].outputs[0].values);
496
+ }, 30_000);
497
+ });
@@ -0,0 +1,54 @@
1
+ import { Base64DataSource } from '@llumiverse/core';
2
+ import { describe, expect, test } from 'vitest';
3
+ import { dataSourceToVertexSourceData, isGcsUrl } from './source-utils.js';
4
+
5
+ describe('isGcsUrl', () => {
6
+ test('recognises gs:// scheme', () => {
7
+ expect(isGcsUrl('gs://my-bucket/file.jpg')).toBe(true);
8
+ });
9
+
10
+ test('recognises storage.googleapis.com URL', () => {
11
+ expect(isGcsUrl('https://storage.googleapis.com/my-bucket/file.jpg')).toBe(true);
12
+ });
13
+
14
+ test('recognises storage.cloud.google.com URL', () => {
15
+ expect(isGcsUrl('https://storage.cloud.google.com/bucket/obj')).toBe(true);
16
+ });
17
+
18
+ test('rejects arbitrary https URL', () => {
19
+ expect(isGcsUrl('https://example.com/file.jpg')).toBe(false);
20
+ });
21
+
22
+ test('rejects S3 URL', () => {
23
+ expect(isGcsUrl('s3://my-bucket/file.mp4')).toBe(false);
24
+ });
25
+ });
26
+
27
+ describe('dataSourceToVertexSourceData', () => {
28
+ test('returns gcsUri for gs:// URL', async () => {
29
+ const ds = new Base64DataSource('file.mp4', 'video/mp4', 'abc');
30
+ // Simulate a GCS URL by overriding getURL
31
+ ds.getURL = async () => 'gs://my-bucket/video.mp4';
32
+ const result = await dataSourceToVertexSourceData(ds);
33
+ expect(result.gcsUri).toBe('gs://my-bucket/video.mp4');
34
+ expect(result.bytesBase64Encoded).toBeUndefined();
35
+ });
36
+
37
+ test('returns base64 bytes for Base64DataSource with non-GCS URL', async () => {
38
+ const b64 = Buffer.from('hello').toString('base64');
39
+ const ds = new Base64DataSource('img.jpg', 'image/jpeg', b64);
40
+ const result = await dataSourceToVertexSourceData(ds);
41
+ expect(result.bytesBase64Encoded).toBe(b64);
42
+ expect(result.gcsUri).toBeUndefined();
43
+ });
44
+
45
+ test('falls back to base64 when getURL rejects', async () => {
46
+ const b64 = Buffer.from('world').toString('base64');
47
+ const ds = new Base64DataSource('img.jpg', 'image/jpeg', b64);
48
+ ds.getURL = async () => {
49
+ throw new Error('no url');
50
+ };
51
+ const result = await dataSourceToVertexSourceData(ds);
52
+ expect(result.bytesBase64Encoded).toBe(b64);
53
+ });
54
+ });
@@ -0,0 +1,29 @@
1
+ import { Base64DataSource, type DataSource, dataSourceToBase64 } from '@llumiverse/core';
2
+
3
+ interface VertexSourceData {
4
+ gcsUri?: string;
5
+ bytesBase64Encoded?: string;
6
+ }
7
+
8
+ export function isGcsUrl(url: string): boolean {
9
+ return (
10
+ url.startsWith('gs://') ||
11
+ url.startsWith('https://storage.googleapis.com/') ||
12
+ url.startsWith('https://storage.cloud.google.com/')
13
+ );
14
+ }
15
+
16
+ export async function dataSourceToVertexSourceData(ds: DataSource): Promise<VertexSourceData> {
17
+ const url = await ds.getURL().catch(() => undefined);
18
+ if (url && isGcsUrl(url)) {
19
+ return { gcsUri: url };
20
+ }
21
+
22
+ const bytesBase64Encoded = ds instanceof Base64DataSource ? ds.getBase64() : await dataSourceToBase64(ds);
23
+ if (!bytesBase64Encoded) {
24
+ throw new Error(
25
+ `Data source conversion produced empty result — name=${ds.name}, mime=${ds.mime_type ?? 'unknown'}`,
26
+ );
27
+ }
28
+ return { bytesBase64Encoded };
29
+ }