@llumiverse/drivers 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (409) hide show
  1. package/lib/{types/adobe → adobe}/firefly.d.ts +2 -1
  2. package/lib/adobe/firefly.d.ts.map +1 -0
  3. package/lib/adobe/firefly.js +120 -0
  4. package/lib/adobe/firefly.js.map +1 -0
  5. package/lib/{types/anthropic → anthropic}/index.d.ts +4 -2
  6. package/lib/anthropic/index.d.ts.map +1 -0
  7. package/lib/{esm/anthropic → anthropic}/index.js +19 -8
  8. package/lib/anthropic/index.js.map +1 -0
  9. package/lib/{types/azure → azure}/azure_foundry.d.ts +9 -7
  10. package/lib/azure/azure_foundry.d.ts.map +1 -0
  11. package/lib/{esm/azure → azure}/azure_foundry.js +138 -124
  12. package/lib/azure/azure_foundry.js.map +1 -0
  13. package/lib/{types/bedrock → bedrock}/converse.d.ts +2 -2
  14. package/lib/bedrock/converse.d.ts.map +1 -0
  15. package/lib/{esm/bedrock → bedrock}/converse.js +86 -79
  16. package/lib/bedrock/converse.js.map +1 -0
  17. package/lib/bedrock/embeddings.d.ts +4 -0
  18. package/lib/bedrock/embeddings.d.ts.map +1 -0
  19. package/lib/bedrock/embeddings.js +359 -0
  20. package/lib/bedrock/embeddings.js.map +1 -0
  21. package/lib/{types/bedrock → bedrock}/index.d.ts +33 -9
  22. package/lib/bedrock/index.d.ts.map +1 -0
  23. package/lib/{esm/bedrock → bedrock}/index.js +599 -324
  24. package/lib/bedrock/index.js.map +1 -0
  25. package/lib/{types/bedrock → bedrock}/nova-image-payload.d.ts +5 -5
  26. package/lib/bedrock/nova-image-payload.d.ts.map +1 -0
  27. package/lib/{esm/bedrock → bedrock}/nova-image-payload.js +31 -36
  28. package/lib/bedrock/nova-image-payload.js.map +1 -0
  29. package/lib/{types/bedrock → bedrock}/payloads.d.ts +1 -1
  30. package/lib/bedrock/payloads.d.ts.map +1 -0
  31. package/lib/{cjs/bedrock → bedrock}/payloads.js.map +1 -1
  32. package/lib/{types/bedrock → bedrock}/s3.d.ts +3 -2
  33. package/lib/bedrock/s3.d.ts.map +1 -0
  34. package/lib/{esm/bedrock → bedrock}/s3.js +27 -23
  35. package/lib/bedrock/s3.js.map +1 -0
  36. package/lib/{types/bedrock → bedrock}/twelvelabs.d.ts +8 -9
  37. package/lib/bedrock/twelvelabs.d.ts.map +1 -0
  38. package/lib/{esm/bedrock → bedrock}/twelvelabs.js +17 -21
  39. package/lib/bedrock/twelvelabs.js.map +1 -0
  40. package/lib/{types/groq → groq}/index.d.ts +6 -4
  41. package/lib/groq/index.d.ts.map +1 -0
  42. package/lib/{esm/groq → groq}/index.js +72 -39
  43. package/lib/groq/index.js.map +1 -0
  44. package/lib/{types/huggingface_ie.d.ts → huggingface_ie.d.ts} +4 -3
  45. package/lib/huggingface_ie.d.ts.map +1 -0
  46. package/lib/{esm/huggingface_ie.js → huggingface_ie.js} +32 -31
  47. package/lib/huggingface_ie.js.map +1 -0
  48. package/lib/index.d.ts +16 -0
  49. package/lib/index.d.ts.map +1 -0
  50. package/lib/index.js +16 -0
  51. package/lib/index.js.map +1 -0
  52. package/lib/{types/mistral → mistral}/index.d.ts +6 -5
  53. package/lib/mistral/index.d.ts.map +1 -0
  54. package/lib/{esm/mistral → mistral}/index.js +66 -38
  55. package/lib/mistral/index.js.map +1 -0
  56. package/lib/{types/mistral → mistral}/types.d.ts +1 -0
  57. package/lib/mistral/types.d.ts.map +1 -0
  58. package/lib/mistral/types.js.map +1 -0
  59. package/lib/{types/openai → openai}/azure_openai.d.ts +5 -4
  60. package/lib/openai/azure_openai.d.ts.map +1 -0
  61. package/lib/{esm/openai → openai}/azure_openai.js +17 -14
  62. package/lib/openai/azure_openai.js.map +1 -0
  63. package/lib/openai/drivers.d.ts +4 -0
  64. package/lib/openai/drivers.d.ts.map +1 -0
  65. package/lib/openai/drivers.js +9 -0
  66. package/lib/openai/drivers.js.map +1 -0
  67. package/lib/{types/openai → openai}/index.d.ts +16 -5
  68. package/lib/openai/index.d.ts.map +1 -0
  69. package/lib/{esm/openai → openai}/index.js +242 -141
  70. package/lib/openai/index.js.map +1 -0
  71. package/lib/{types/openai → openai}/openai.d.ts +3 -3
  72. package/lib/openai/openai.d.ts.map +1 -0
  73. package/lib/openai/openai.js +15 -0
  74. package/lib/openai/openai.js.map +1 -0
  75. package/lib/{types/openai → openai}/openai_compatible.d.ts +3 -3
  76. package/lib/openai/openai_compatible.d.ts.map +1 -0
  77. package/lib/{esm/openai → openai}/openai_compatible.js +14 -11
  78. package/lib/openai/openai_compatible.js.map +1 -0
  79. package/lib/{types/openai → openai}/openai_format.d.ts +3 -2
  80. package/lib/openai/openai_format.d.ts.map +1 -0
  81. package/lib/{esm/openai → openai}/openai_format.js +66 -24
  82. package/lib/openai/openai_format.js.map +1 -0
  83. package/lib/{types/replicate.d.ts → replicate.d.ts} +3 -2
  84. package/lib/replicate.d.ts.map +1 -0
  85. package/lib/{esm/replicate.js → replicate.js} +59 -49
  86. package/lib/replicate.js.map +1 -0
  87. package/lib/{types/shared → shared}/claude-messages.d.ts +25 -1
  88. package/lib/shared/claude-messages.d.ts.map +1 -0
  89. package/lib/{esm/shared → shared}/claude-messages.js +212 -59
  90. package/lib/shared/claude-messages.js.map +1 -0
  91. package/lib/{types/shared → shared}/claude-thinking.d.ts +1 -1
  92. package/lib/shared/claude-thinking.d.ts.map +1 -0
  93. package/lib/{esm/shared → shared}/claude-thinking.js +5 -7
  94. package/lib/shared/claude-thinking.js.map +1 -0
  95. package/lib/shared/debug-prompt.d.ts +5 -0
  96. package/lib/shared/debug-prompt.d.ts.map +1 -0
  97. package/lib/shared/debug-prompt.js +25 -0
  98. package/lib/shared/debug-prompt.js.map +1 -0
  99. package/lib/{types/test-driver → test-driver}/TestErrorCompletionStream.d.ts +1 -1
  100. package/lib/test-driver/TestErrorCompletionStream.d.ts.map +1 -0
  101. package/lib/test-driver/TestErrorCompletionStream.js +16 -0
  102. package/lib/test-driver/TestErrorCompletionStream.js.map +1 -0
  103. package/lib/{types/test-driver → test-driver}/TestValidationErrorCompletionStream.d.ts +1 -1
  104. package/lib/test-driver/TestValidationErrorCompletionStream.d.ts.map +1 -0
  105. package/lib/{esm/test-driver → test-driver}/TestValidationErrorCompletionStream.js +4 -4
  106. package/lib/test-driver/TestValidationErrorCompletionStream.js.map +1 -0
  107. package/lib/{types/test-driver → test-driver}/index.d.ts +3 -3
  108. package/lib/test-driver/index.d.ts.map +1 -0
  109. package/lib/{esm/test-driver → test-driver}/index.js +20 -20
  110. package/lib/test-driver/index.js.map +1 -0
  111. package/lib/{types/test-driver → test-driver}/utils.d.ts +1 -1
  112. package/lib/test-driver/utils.d.ts.map +1 -0
  113. package/lib/{esm/test-driver → test-driver}/utils.js +4 -4
  114. package/lib/test-driver/utils.js.map +1 -0
  115. package/lib/togetherai/index.d.ts +15 -0
  116. package/lib/togetherai/index.d.ts.map +1 -0
  117. package/lib/togetherai/index.js +54 -0
  118. package/lib/togetherai/index.js.map +1 -0
  119. package/lib/{types/togetherai → togetherai}/interfaces.d.ts +1 -1
  120. package/lib/togetherai/interfaces.d.ts.map +1 -0
  121. package/lib/{cjs/watsonx → togetherai}/interfaces.js.map +1 -1
  122. package/lib/vertexai/debug.d.ts +2 -0
  123. package/lib/vertexai/debug.d.ts.map +1 -0
  124. package/lib/{esm/vertexai → vertexai}/debug.js +1 -1
  125. package/lib/vertexai/debug.js.map +1 -0
  126. package/lib/vertexai/embeddings/embed-legacy-multimodal.d.ts +9 -0
  127. package/lib/vertexai/embeddings/embed-legacy-multimodal.d.ts.map +1 -0
  128. package/lib/vertexai/embeddings/embed-legacy-multimodal.js +141 -0
  129. package/lib/vertexai/embeddings/embed-legacy-multimodal.js.map +1 -0
  130. package/lib/vertexai/embeddings/embed.d.ts +13 -0
  131. package/lib/vertexai/embeddings/embed.d.ts.map +1 -0
  132. package/lib/vertexai/embeddings/embed.js +162 -0
  133. package/lib/vertexai/embeddings/embed.js.map +1 -0
  134. package/lib/vertexai/embeddings/source-utils.d.ts +9 -0
  135. package/lib/vertexai/embeddings/source-utils.d.ts.map +1 -0
  136. package/lib/vertexai/embeddings/source-utils.js +18 -0
  137. package/lib/vertexai/embeddings/source-utils.js.map +1 -0
  138. package/lib/{types/vertexai → vertexai}/index.d.ts +31 -19
  139. package/lib/vertexai/index.d.ts.map +1 -0
  140. package/lib/{esm/vertexai → vertexai}/index.js +221 -159
  141. package/lib/vertexai/index.js.map +1 -0
  142. package/lib/{types/vertexai → vertexai}/models/claude.d.ts +4 -4
  143. package/lib/vertexai/models/claude.d.ts.map +1 -0
  144. package/lib/{esm/vertexai → vertexai}/models/claude.js +17 -20
  145. package/lib/vertexai/models/claude.js.map +1 -0
  146. package/lib/{types/vertexai → vertexai}/models/gemini.d.ts +28 -4
  147. package/lib/vertexai/models/gemini.d.ts.map +1 -0
  148. package/lib/{esm/vertexai → vertexai}/models/gemini.js +238 -116
  149. package/lib/vertexai/models/gemini.js.map +1 -0
  150. package/lib/{types/vertexai → vertexai}/models/imagen.d.ts +12 -11
  151. package/lib/vertexai/models/imagen.d.ts.map +1 -0
  152. package/lib/{esm/vertexai → vertexai}/models/imagen.js +74 -47
  153. package/lib/vertexai/models/imagen.js.map +1 -0
  154. package/lib/{types/vertexai → vertexai}/models/llama.d.ts +4 -4
  155. package/lib/vertexai/models/llama.d.ts.map +1 -0
  156. package/lib/{esm/vertexai → vertexai}/models/llama.js +37 -33
  157. package/lib/vertexai/models/llama.js.map +1 -0
  158. package/lib/vertexai/models.d.ts +21 -0
  159. package/lib/vertexai/models.d.ts.map +1 -0
  160. package/lib/{esm/vertexai → vertexai}/models.js +12 -9
  161. package/lib/vertexai/models.js.map +1 -0
  162. package/lib/{types/watsonx → watsonx}/index.d.ts +4 -3
  163. package/lib/watsonx/index.d.ts.map +1 -0
  164. package/lib/{esm/watsonx → watsonx}/index.js +69 -41
  165. package/lib/watsonx/index.js.map +1 -0
  166. package/lib/watsonx/interfaces.d.ts.map +1 -0
  167. package/lib/{esm/watsonx → watsonx}/interfaces.js.map +1 -1
  168. package/lib/{types/xai → xai}/index.d.ts +4 -4
  169. package/lib/xai/index.d.ts.map +1 -0
  170. package/lib/{esm/xai → xai}/index.js +22 -18
  171. package/lib/xai/index.js.map +1 -0
  172. package/package.json +87 -36
  173. package/src/adobe/firefly.ts +60 -43
  174. package/src/anthropic/index.ts +37 -20
  175. package/src/azure/azure_foundry.ts +210 -165
  176. package/src/bedrock/converse.ts +124 -101
  177. package/src/bedrock/embeddings.test.ts +508 -0
  178. package/src/bedrock/embeddings.ts +517 -0
  179. package/src/bedrock/error-handling.test.ts +62 -14
  180. package/src/bedrock/index.ts +832 -466
  181. package/src/bedrock/nova-image-payload.ts +98 -91
  182. package/src/bedrock/payloads.ts +9 -9
  183. package/src/bedrock/s3.test.ts +39 -0
  184. package/src/bedrock/s3.ts +57 -38
  185. package/src/bedrock/streaming-tool-use.test.ts +86 -69
  186. package/src/bedrock/twelvelabs.ts +35 -32
  187. package/src/groq/index.ts +143 -60
  188. package/src/http-timeout-wiring.test.ts +263 -0
  189. package/src/huggingface_ie.ts +45 -61
  190. package/src/index.ts +15 -16
  191. package/src/mistral/index.ts +97 -48
  192. package/src/mistral/types.ts +13 -12
  193. package/src/openai/azure_openai.ts +35 -27
  194. package/src/openai/drivers.ts +9 -0
  195. package/src/openai/error-handling.test.ts +308 -113
  196. package/src/openai/index.ts +378 -248
  197. package/src/openai/openai.ts +6 -13
  198. package/src/openai/openai_compatible.ts +35 -25
  199. package/src/openai/openai_format.ts +90 -40
  200. package/src/replicate.ts +108 -86
  201. package/src/shared/claude-messages.test.ts +37 -0
  202. package/src/shared/claude-messages.ts +303 -97
  203. package/src/shared/claude-thinking.ts +6 -12
  204. package/src/shared/debug-prompt.ts +28 -0
  205. package/src/test-driver/TestErrorCompletionStream.ts +9 -10
  206. package/src/test-driver/TestValidationErrorCompletionStream.ts +9 -10
  207. package/src/test-driver/index.ts +43 -27
  208. package/src/test-driver/utils.ts +8 -8
  209. package/src/togetherai/index.test.ts +32 -0
  210. package/src/togetherai/index.ts +64 -128
  211. package/src/togetherai/interfaces.ts +5 -5
  212. package/src/vertexai/debug.ts +3 -3
  213. package/src/vertexai/embeddings/embed-legacy-multimodal.ts +211 -0
  214. package/src/vertexai/embeddings/embed.ts +206 -0
  215. package/src/vertexai/embeddings/embeddings.test.ts +497 -0
  216. package/src/vertexai/embeddings/source-utils.test.ts +54 -0
  217. package/src/vertexai/embeddings/source-utils.ts +29 -0
  218. package/src/vertexai/index.ts +331 -244
  219. package/src/vertexai/models/claude-error-handling.test.ts +83 -36
  220. package/src/vertexai/models/claude-streaming-spacing.test.ts +82 -75
  221. package/src/vertexai/models/claude.ts +55 -40
  222. package/src/vertexai/models/gemini-conversation-mutation.test.ts +65 -23
  223. package/src/vertexai/models/gemini-error-handling.test.ts +126 -10
  224. package/src/vertexai/models/gemini-orphaned-tool-result.test.ts +118 -0
  225. package/src/vertexai/models/gemini.ts +349 -172
  226. package/src/vertexai/models/imagen.ts +164 -100
  227. package/src/vertexai/models/llama.ts +70 -48
  228. package/src/vertexai/models.ts +36 -16
  229. package/src/watsonx/index.ts +101 -65
  230. package/src/watsonx/interfaces.ts +10 -15
  231. package/src/xai/index.ts +30 -30
  232. package/lib/cjs/adobe/firefly.js +0 -120
  233. package/lib/cjs/adobe/firefly.js.map +0 -1
  234. package/lib/cjs/anthropic/index.js +0 -64
  235. package/lib/cjs/anthropic/index.js.map +0 -1
  236. package/lib/cjs/azure/azure_foundry.js +0 -432
  237. package/lib/cjs/azure/azure_foundry.js.map +0 -1
  238. package/lib/cjs/bedrock/converse.js +0 -359
  239. package/lib/cjs/bedrock/converse.js.map +0 -1
  240. package/lib/cjs/bedrock/index.js +0 -1508
  241. package/lib/cjs/bedrock/index.js.map +0 -1
  242. package/lib/cjs/bedrock/nova-image-payload.js +0 -207
  243. package/lib/cjs/bedrock/nova-image-payload.js.map +0 -1
  244. package/lib/cjs/bedrock/payloads.js +0 -3
  245. package/lib/cjs/bedrock/s3.js +0 -107
  246. package/lib/cjs/bedrock/s3.js.map +0 -1
  247. package/lib/cjs/bedrock/twelvelabs.js +0 -87
  248. package/lib/cjs/bedrock/twelvelabs.js.map +0 -1
  249. package/lib/cjs/groq/index.js +0 -328
  250. package/lib/cjs/groq/index.js.map +0 -1
  251. package/lib/cjs/huggingface_ie.js +0 -201
  252. package/lib/cjs/huggingface_ie.js.map +0 -1
  253. package/lib/cjs/index.js +0 -32
  254. package/lib/cjs/index.js.map +0 -1
  255. package/lib/cjs/mistral/index.js +0 -176
  256. package/lib/cjs/mistral/index.js.map +0 -1
  257. package/lib/cjs/mistral/types.js +0 -83
  258. package/lib/cjs/mistral/types.js.map +0 -1
  259. package/lib/cjs/openai/azure_openai.js +0 -72
  260. package/lib/cjs/openai/azure_openai.js.map +0 -1
  261. package/lib/cjs/openai/index.js +0 -1135
  262. package/lib/cjs/openai/index.js.map +0 -1
  263. package/lib/cjs/openai/openai.js +0 -21
  264. package/lib/cjs/openai/openai.js.map +0 -1
  265. package/lib/cjs/openai/openai_compatible.js +0 -63
  266. package/lib/cjs/openai/openai_compatible.js.map +0 -1
  267. package/lib/cjs/openai/openai_format.js +0 -131
  268. package/lib/cjs/openai/openai_format.js.map +0 -1
  269. package/lib/cjs/package.json +0 -3
  270. package/lib/cjs/replicate.js +0 -275
  271. package/lib/cjs/replicate.js.map +0 -1
  272. package/lib/cjs/shared/claude-messages.js +0 -737
  273. package/lib/cjs/shared/claude-messages.js.map +0 -1
  274. package/lib/cjs/shared/claude-thinking.js +0 -60
  275. package/lib/cjs/shared/claude-thinking.js.map +0 -1
  276. package/lib/cjs/test-driver/TestErrorCompletionStream.js +0 -20
  277. package/lib/cjs/test-driver/TestErrorCompletionStream.js.map +0 -1
  278. package/lib/cjs/test-driver/TestValidationErrorCompletionStream.js +0 -24
  279. package/lib/cjs/test-driver/TestValidationErrorCompletionStream.js.map +0 -1
  280. package/lib/cjs/test-driver/index.js +0 -109
  281. package/lib/cjs/test-driver/index.js.map +0 -1
  282. package/lib/cjs/test-driver/utils.js +0 -30
  283. package/lib/cjs/test-driver/utils.js.map +0 -1
  284. package/lib/cjs/togetherai/index.js +0 -126
  285. package/lib/cjs/togetherai/index.js.map +0 -1
  286. package/lib/cjs/togetherai/interfaces.js +0 -3
  287. package/lib/cjs/togetherai/interfaces.js.map +0 -1
  288. package/lib/cjs/vertexai/debug.js +0 -12
  289. package/lib/cjs/vertexai/debug.js.map +0 -1
  290. package/lib/cjs/vertexai/embeddings/embeddings-image.js +0 -27
  291. package/lib/cjs/vertexai/embeddings/embeddings-image.js.map +0 -1
  292. package/lib/cjs/vertexai/embeddings/embeddings-text.js +0 -23
  293. package/lib/cjs/vertexai/embeddings/embeddings-text.js.map +0 -1
  294. package/lib/cjs/vertexai/index.js +0 -644
  295. package/lib/cjs/vertexai/index.js.map +0 -1
  296. package/lib/cjs/vertexai/models/claude.js +0 -72
  297. package/lib/cjs/vertexai/models/claude.js.map +0 -1
  298. package/lib/cjs/vertexai/models/gemini.js +0 -864
  299. package/lib/cjs/vertexai/models/gemini.js.map +0 -1
  300. package/lib/cjs/vertexai/models/imagen.js +0 -303
  301. package/lib/cjs/vertexai/models/imagen.js.map +0 -1
  302. package/lib/cjs/vertexai/models/llama.js +0 -183
  303. package/lib/cjs/vertexai/models/llama.js.map +0 -1
  304. package/lib/cjs/vertexai/models.js +0 -35
  305. package/lib/cjs/vertexai/models.js.map +0 -1
  306. package/lib/cjs/watsonx/index.js +0 -161
  307. package/lib/cjs/watsonx/index.js.map +0 -1
  308. package/lib/cjs/watsonx/interfaces.js +0 -3
  309. package/lib/cjs/xai/index.js +0 -65
  310. package/lib/cjs/xai/index.js.map +0 -1
  311. package/lib/esm/adobe/firefly.js +0 -116
  312. package/lib/esm/adobe/firefly.js.map +0 -1
  313. package/lib/esm/anthropic/index.js.map +0 -1
  314. package/lib/esm/azure/azure_foundry.js.map +0 -1
  315. package/lib/esm/bedrock/converse.js.map +0 -1
  316. package/lib/esm/bedrock/index.js.map +0 -1
  317. package/lib/esm/bedrock/nova-image-payload.js.map +0 -1
  318. package/lib/esm/bedrock/payloads.js.map +0 -1
  319. package/lib/esm/bedrock/s3.js.map +0 -1
  320. package/lib/esm/bedrock/twelvelabs.js.map +0 -1
  321. package/lib/esm/groq/index.js.map +0 -1
  322. package/lib/esm/huggingface_ie.js.map +0 -1
  323. package/lib/esm/index.js +0 -16
  324. package/lib/esm/index.js.map +0 -1
  325. package/lib/esm/mistral/index.js.map +0 -1
  326. package/lib/esm/mistral/types.js.map +0 -1
  327. package/lib/esm/openai/azure_openai.js.map +0 -1
  328. package/lib/esm/openai/index.js.map +0 -1
  329. package/lib/esm/openai/openai.js +0 -14
  330. package/lib/esm/openai/openai.js.map +0 -1
  331. package/lib/esm/openai/openai_compatible.js.map +0 -1
  332. package/lib/esm/openai/openai_format.js.map +0 -1
  333. package/lib/esm/replicate.js.map +0 -1
  334. package/lib/esm/shared/claude-messages.js.map +0 -1
  335. package/lib/esm/shared/claude-thinking.js.map +0 -1
  336. package/lib/esm/test-driver/TestErrorCompletionStream.js +0 -16
  337. package/lib/esm/test-driver/TestErrorCompletionStream.js.map +0 -1
  338. package/lib/esm/test-driver/TestValidationErrorCompletionStream.js.map +0 -1
  339. package/lib/esm/test-driver/index.js.map +0 -1
  340. package/lib/esm/test-driver/utils.js.map +0 -1
  341. package/lib/esm/togetherai/index.js +0 -122
  342. package/lib/esm/togetherai/index.js.map +0 -1
  343. package/lib/esm/togetherai/interfaces.js.map +0 -1
  344. package/lib/esm/vertexai/debug.js.map +0 -1
  345. package/lib/esm/vertexai/embeddings/embeddings-image.js +0 -24
  346. package/lib/esm/vertexai/embeddings/embeddings-image.js.map +0 -1
  347. package/lib/esm/vertexai/embeddings/embeddings-text.js +0 -20
  348. package/lib/esm/vertexai/embeddings/embeddings-text.js.map +0 -1
  349. package/lib/esm/vertexai/index.js.map +0 -1
  350. package/lib/esm/vertexai/models/claude.js.map +0 -1
  351. package/lib/esm/vertexai/models/gemini.js.map +0 -1
  352. package/lib/esm/vertexai/models/imagen.js.map +0 -1
  353. package/lib/esm/vertexai/models/llama.js.map +0 -1
  354. package/lib/esm/vertexai/models.js.map +0 -1
  355. package/lib/esm/watsonx/index.js.map +0 -1
  356. package/lib/esm/xai/index.js.map +0 -1
  357. package/lib/types/adobe/firefly.d.ts.map +0 -1
  358. package/lib/types/anthropic/index.d.ts.map +0 -1
  359. package/lib/types/azure/azure_foundry.d.ts.map +0 -1
  360. package/lib/types/bedrock/converse.d.ts.map +0 -1
  361. package/lib/types/bedrock/index.d.ts.map +0 -1
  362. package/lib/types/bedrock/nova-image-payload.d.ts.map +0 -1
  363. package/lib/types/bedrock/payloads.d.ts.map +0 -1
  364. package/lib/types/bedrock/s3.d.ts.map +0 -1
  365. package/lib/types/bedrock/twelvelabs.d.ts.map +0 -1
  366. package/lib/types/groq/index.d.ts.map +0 -1
  367. package/lib/types/huggingface_ie.d.ts.map +0 -1
  368. package/lib/types/index.d.ts +0 -16
  369. package/lib/types/index.d.ts.map +0 -1
  370. package/lib/types/mistral/index.d.ts.map +0 -1
  371. package/lib/types/mistral/types.d.ts.map +0 -1
  372. package/lib/types/openai/azure_openai.d.ts.map +0 -1
  373. package/lib/types/openai/index.d.ts.map +0 -1
  374. package/lib/types/openai/openai.d.ts.map +0 -1
  375. package/lib/types/openai/openai_compatible.d.ts.map +0 -1
  376. package/lib/types/openai/openai_format.d.ts.map +0 -1
  377. package/lib/types/replicate.d.ts.map +0 -1
  378. package/lib/types/shared/claude-messages.d.ts.map +0 -1
  379. package/lib/types/shared/claude-thinking.d.ts.map +0 -1
  380. package/lib/types/test-driver/TestErrorCompletionStream.d.ts.map +0 -1
  381. package/lib/types/test-driver/TestValidationErrorCompletionStream.d.ts.map +0 -1
  382. package/lib/types/test-driver/index.d.ts.map +0 -1
  383. package/lib/types/test-driver/utils.d.ts.map +0 -1
  384. package/lib/types/togetherai/index.d.ts +0 -23
  385. package/lib/types/togetherai/index.d.ts.map +0 -1
  386. package/lib/types/togetherai/interfaces.d.ts.map +0 -1
  387. package/lib/types/vertexai/debug.d.ts +0 -2
  388. package/lib/types/vertexai/debug.d.ts.map +0 -1
  389. package/lib/types/vertexai/embeddings/embeddings-image.d.ts +0 -11
  390. package/lib/types/vertexai/embeddings/embeddings-image.d.ts.map +0 -1
  391. package/lib/types/vertexai/embeddings/embeddings-text.d.ts +0 -10
  392. package/lib/types/vertexai/embeddings/embeddings-text.d.ts.map +0 -1
  393. package/lib/types/vertexai/index.d.ts.map +0 -1
  394. package/lib/types/vertexai/models/claude.d.ts.map +0 -1
  395. package/lib/types/vertexai/models/gemini.d.ts.map +0 -1
  396. package/lib/types/vertexai/models/imagen.d.ts.map +0 -1
  397. package/lib/types/vertexai/models/llama.d.ts.map +0 -1
  398. package/lib/types/vertexai/models.d.ts +0 -20
  399. package/lib/types/vertexai/models.d.ts.map +0 -1
  400. package/lib/types/watsonx/index.d.ts.map +0 -1
  401. package/lib/types/watsonx/interfaces.d.ts.map +0 -1
  402. package/lib/types/xai/index.d.ts.map +0 -1
  403. package/src/vertexai/embeddings/embeddings-image.ts +0 -52
  404. package/src/vertexai/embeddings/embeddings-text.ts +0 -54
  405. /package/lib/{esm/bedrock → bedrock}/payloads.js +0 -0
  406. /package/lib/{esm/mistral → mistral}/types.js +0 -0
  407. /package/lib/{esm/togetherai → togetherai}/interfaces.js +0 -0
  408. /package/lib/{types/watsonx → watsonx}/interfaces.d.ts +0 -0
  409. /package/lib/{esm/watsonx → watsonx}/interfaces.js +0 -0
@@ -1,16 +1,20 @@
1
- import { AbstractDriver, getConversationMeta, getModelCapabilities, incrementConversationTurn, LlumiverseError, modelModalitiesToArray, ModelType, stripBase64ImagesFromConversation, stripHeartbeatsFromConversation, supportsToolUse, TrainingJobStatus, truncateLargeTextInConversation, unwrapConversationArray, } from "@llumiverse/core";
1
+ import { getConversationMeta, getModelCapabilities, incrementConversationTurn, LlumiverseError, ModelType, modelModalitiesToArray, normalizeEmbeddingsOptions, OPENAI_DEFAULT_EMBEDDING_MODEL, stripBase64ImagesFromConversation, stripHeartbeatsFromConversation, supportsToolUse, TrainingJobStatus, truncateLargeTextInConversation, unwrapConversationArray, } from '@llumiverse/core';
2
+ import { AbstractDriver } from '@llumiverse/core/driver';
2
3
  import { APIConnectionError, APIConnectionTimeoutError, APIError, AuthenticationError, BadRequestError, ConflictError, ContentFilterFinishReasonError, InternalServerError, LengthFinishReasonError, NotFoundError, OpenAIError, PermissionDeniedError, RateLimitError, UnprocessableEntityError, } from 'openai/error';
3
- import { formatOpenAILikeMultimodalPrompt } from "./openai_format.js";
4
+ import { formatOpenAILikeMultimodalPrompt } from './openai_format.js';
4
5
  // Helper function to convert string to CompletionResult[]
5
6
  function textToCompletionResult(text) {
6
- return text ? [{ type: "text", value: text }] : [];
7
+ return text ? [{ type: 'text', value: text }] : [];
8
+ }
9
+ function hasNumericStatus(error) {
10
+ return error instanceof Error && typeof error.status === 'number';
7
11
  }
8
12
  function isOpenAIReasoningModel(model) {
9
13
  const normalized = model.toLowerCase();
10
- return normalized.includes("o1")
11
- || normalized.includes("o3")
12
- || normalized.includes("o4")
13
- || normalized.includes("gpt-5");
14
+ return (normalized.includes('o1') ||
15
+ normalized.includes('o3') ||
16
+ normalized.includes('o4') ||
17
+ normalized.includes('gpt-5'));
14
18
  }
15
19
  function isGpt5ProModel(model) {
16
20
  const modelName = model.toLowerCase().split('/').pop() ?? model.toLowerCase();
@@ -21,17 +25,17 @@ function openAIReasoningEffort(model, effort) {
21
25
  return undefined;
22
26
  }
23
27
  if (isGpt5ProModel(model)) {
24
- return "high";
28
+ return 'high';
25
29
  }
26
- return effort === "low" || effort === "medium" || effort === "high" ? effort : undefined;
30
+ return effort === 'low' || effort === 'medium' || effort === 'high' ? effort : undefined;
27
31
  }
28
32
  //TODO: Do we need a list?, replace with if statements and modernize?
29
33
  const supportFineTunning = new Set([
30
- "gpt-3.5-turbo-1106",
31
- "gpt-3.5-turbo-0613",
32
- "babbage-002",
33
- "davinci-002",
34
- "gpt-4-0613"
34
+ 'gpt-3.5-turbo-1106',
35
+ 'gpt-3.5-turbo-0613',
36
+ 'babbage-002',
37
+ 'davinci-002',
38
+ 'gpt-4-0613',
35
39
  ]);
36
40
  export class BaseOpenAIDriver extends AbstractDriver {
37
41
  constructor(opts) {
@@ -44,8 +48,8 @@ export class BaseOpenAIDriver extends AbstractDriver {
44
48
  // Collect all parts in order (text and images)
45
49
  const allResults = extractCompletionResults(result.output);
46
50
  if (allResults.length === 0 && !tools) {
47
- this.logger.error({ result }, "[OpenAI] Response is not valid");
48
- throw new Error("Response is not valid: no data");
51
+ this.logger.error({ result }, '[OpenAI] Response is not valid');
52
+ throw new Error('Response is not valid: no data');
49
53
  }
50
54
  return {
51
55
  result: allResults,
@@ -56,14 +60,14 @@ export class BaseOpenAIDriver extends AbstractDriver {
56
60
  }
57
61
  async requestTextCompletionStream(prompt, options) {
58
62
  if (options.model_options?._option_id !== undefined &&
59
- options.model_options?._option_id !== "openai-text" &&
60
- options.model_options?._option_id !== "openai-thinking" &&
61
- options.model_options?._option_id !== "text-fallback") {
62
- this.logger.debug({ options: options.model_options }, "Unexpected option id");
63
+ options.model_options?._option_id !== 'openai-text' &&
64
+ options.model_options?._option_id !== 'openai-thinking' &&
65
+ options.model_options?._option_id !== 'text-fallback') {
66
+ this.logger.debug({ options: options.model_options }, 'Unexpected option id');
63
67
  }
64
68
  // Include conversation history (same as non-streaming)
65
69
  // Fix orphaned function_call items (can occur when agent is stopped mid-tool-execution)
66
- let conversation = fixOrphanedToolUse(updateConversation(options.conversation, prompt));
70
+ let conversation = fixOrphanedToolResults(fixOrphanedToolUse(updateConversation(options.conversation, prompt)));
67
71
  const toolDefs = getToolDefinitions(options.tools);
68
72
  const useTools = toolDefs ? supportsToolUse(options.model, this.provider, true) : false;
69
73
  // When no tools are provided but conversation contains function_call/function_call_output
@@ -73,15 +77,15 @@ export class BaseOpenAIDriver extends AbstractDriver {
73
77
  }
74
78
  convertRoles(prompt, options.model);
75
79
  const model_options = options.model_options;
76
- insert_image_detail(prompt, model_options?.image_detail ?? "auto");
77
- let parsedSchema = undefined;
80
+ insert_image_detail(prompt, model_options?.image_detail ?? 'auto');
81
+ let parsedSchema;
78
82
  let strictMode = false;
79
- if (options.result_schema && supportsSchema(options.model)) {
83
+ if (options.result_schema && supportsSchema(options.model, this.provider)) {
80
84
  try {
81
85
  parsedSchema = openAISchemaFormat(options.result_schema);
82
86
  strictMode = true;
83
87
  }
84
- catch (e) {
88
+ catch {
85
89
  parsedSchema = limitedSchemaFormat(options.result_schema);
86
90
  strictMode = false;
87
91
  }
@@ -98,43 +102,46 @@ export class BaseOpenAIDriver extends AbstractDriver {
98
102
  top_p: isReasoningModel ? undefined : model_options?.top_p,
99
103
  max_output_tokens: model_options?.max_tokens,
100
104
  tools: useTools ? toolDefs : undefined,
101
- text: parsedSchema ? {
102
- format: {
103
- type: "json_schema",
104
- name: "format_output",
105
- schema: parsedSchema,
106
- strict: strictMode,
105
+ text: parsedSchema
106
+ ? {
107
+ format: {
108
+ type: 'json_schema',
109
+ name: 'format_output',
110
+ schema: parsedSchema,
111
+ strict: strictMode,
112
+ },
107
113
  }
108
- } : undefined,
114
+ : undefined,
109
115
  });
110
116
  return mapResponseStream(stream);
111
117
  }
112
118
  async requestTextCompletion(prompt, options) {
113
119
  if (options.model_options?._option_id !== undefined &&
114
- options.model_options?._option_id !== "openai-text" &&
115
- options.model_options?._option_id !== "openai-thinking") {
116
- this.logger.debug({ options: options.model_options }, "Unexpected option id");
120
+ options.model_options?._option_id !== 'openai-text' &&
121
+ options.model_options?._option_id !== 'openai-thinking' &&
122
+ options.model_options?._option_id !== 'text-fallback') {
123
+ this.logger.debug({ options: options.model_options }, 'Unexpected option id');
117
124
  }
118
125
  convertRoles(prompt, options.model);
119
126
  const model_options = options.model_options;
120
- insert_image_detail(prompt, model_options?.image_detail ?? "auto");
127
+ insert_image_detail(prompt, model_options?.image_detail ?? 'auto');
121
128
  const toolDefs = getToolDefinitions(options.tools);
122
129
  const useTools = toolDefs ? supportsToolUse(options.model, this.provider) : false;
123
130
  // Fix orphaned function_call items (can occur when agent is stopped mid-tool-execution)
124
- let conversation = fixOrphanedToolUse(updateConversation(options.conversation, prompt));
131
+ let conversation = fixOrphanedToolResults(fixOrphanedToolUse(updateConversation(options.conversation, prompt)));
125
132
  // When no tools are provided but conversation contains function_call/function_call_output
126
133
  // items (e.g. checkpoint summary calls), convert them to text to avoid API errors
127
134
  if (!useTools) {
128
135
  conversation = convertOpenAIFunctionItemsToText(conversation);
129
136
  }
130
- let parsedSchema = undefined;
137
+ let parsedSchema;
131
138
  let strictMode = false;
132
- if (options.result_schema && supportsSchema(options.model)) {
139
+ if (options.result_schema && supportsSchema(options.model, this.provider)) {
133
140
  try {
134
141
  parsedSchema = openAISchemaFormat(options.result_schema);
135
142
  strictMode = true;
136
143
  }
137
- catch (e) {
144
+ catch {
138
145
  parsedSchema = limitedSchemaFormat(options.result_schema);
139
146
  strictMode = false;
140
147
  }
@@ -151,14 +158,16 @@ export class BaseOpenAIDriver extends AbstractDriver {
151
158
  top_p: isReasoningModel ? undefined : model_options?.top_p,
152
159
  max_output_tokens: model_options?.max_tokens, //TODO: use max_tokens for older models, currently relying on OpenAI to handle it
153
160
  tools: useTools ? toolDefs : undefined,
154
- text: parsedSchema ? {
155
- format: {
156
- type: "json_schema",
157
- name: "format_output",
158
- schema: parsedSchema,
159
- strict: strictMode,
161
+ text: parsedSchema
162
+ ? {
163
+ format: {
164
+ type: 'json_schema',
165
+ name: 'format_output',
166
+ schema: parsedSchema,
167
+ strict: strictMode,
168
+ },
160
169
  }
161
- } : undefined,
170
+ : undefined,
162
171
  });
163
172
  const completion = this.extractDataFromResponse(options, res);
164
173
  if (options.include_original_response) {
@@ -172,7 +181,7 @@ export class BaseOpenAIDriver extends AbstractDriver {
172
181
  const stripOptions = {
173
182
  keepForTurns: options.stripImagesAfterTurns ?? Infinity,
174
183
  currentTurn,
175
- textMaxTokens: options.stripTextMaxTokens
184
+ textMaxTokens: options.stripTextMaxTokens,
176
185
  };
177
186
  let processedConversation = stripBase64ImagesFromConversation(conversation, stripOptions);
178
187
  // Truncate large text content if configured
@@ -187,13 +196,12 @@ export class BaseOpenAIDriver extends AbstractDriver {
187
196
  }
188
197
  canStream(_options) {
189
198
  // Image generation models don't support streaming
190
- if (_options.model.includes("dall-e")
191
- || _options.model.includes("gpt-image")
192
- || _options.model.includes("chatgpt-image")) {
199
+ if (_options.model.includes('dall-e') ||
200
+ _options.model.includes('gpt-image') ||
201
+ _options.model.includes('chatgpt-image')) {
193
202
  return Promise.resolve(false);
194
203
  }
195
- if (_options.model.includes("o1")
196
- && !(_options.model.includes("mini") || _options.model.includes("preview"))) {
204
+ if (_options.model.includes('o1') && !(_options.model.includes('mini') || _options.model.includes('preview'))) {
197
205
  //o1 full does not support streaming
198
206
  //TODO: Update when OpenAI adds support for streaming, last check 16/02/2025
199
207
  return Promise.resolve(false);
@@ -213,6 +221,7 @@ export class BaseOpenAIDriver extends AbstractDriver {
213
221
  // Add assistant message as EasyInputMessage
214
222
  if (textContent) {
215
223
  const assistantMessage = {
224
+ type: 'message',
216
225
  role: 'assistant',
217
226
  content: textContent,
218
227
  };
@@ -220,7 +229,7 @@ export class BaseOpenAIDriver extends AbstractDriver {
220
229
  }
221
230
  // Add function calls as separate items (Response API format)
222
231
  if (toolUse && toolUse.length > 0) {
223
- const functionCalls = toolUse.map(t => ({
232
+ const functionCalls = toolUse.map((t) => ({
224
233
  type: 'function_call',
225
234
  call_id: t.id,
226
235
  name: t.tool_name,
@@ -235,7 +244,7 @@ export class BaseOpenAIDriver extends AbstractDriver {
235
244
  const stripOptions = {
236
245
  keepForTurns: options.stripImagesAfterTurns ?? Infinity,
237
246
  currentTurn,
238
- textMaxTokens: options.stripTextMaxTokens
247
+ textMaxTokens: options.stripTextMaxTokens,
239
248
  };
240
249
  let processedConversation = stripBase64ImagesFromConversation(conversation, stripOptions);
241
250
  processedConversation = truncateLargeTextInConversation(processedConversation, stripOptions);
@@ -246,24 +255,24 @@ export class BaseOpenAIDriver extends AbstractDriver {
246
255
  return processedConversation;
247
256
  }
248
257
  createTrainingPrompt(options) {
249
- if (options.model.includes("gpt")) {
258
+ if (options.model.includes('gpt')) {
250
259
  return super.createTrainingPrompt(options);
251
260
  }
252
261
  else {
253
262
  // babbage, davinci not yet implemented
254
- throw new Error("Unsupported model for training: " + options.model);
263
+ throw new Error(`Unsupported model for training: ${options.model}`);
255
264
  }
256
265
  }
257
266
  async startTraining(dataset, options) {
258
267
  const url = await dataset.getURL();
259
268
  const file = await this.service.files.create({
260
269
  file: await fetch(url),
261
- purpose: "fine-tune",
270
+ purpose: 'fine-tune',
262
271
  });
263
272
  const job = await this.service.fineTuning.jobs.create({
264
273
  training_file: file.id,
265
274
  model: options.model,
266
- hyperparameters: options.params
275
+ hyperparameters: options.params,
267
276
  });
268
277
  return jobInfo(job);
269
278
  }
@@ -281,7 +290,7 @@ export class BaseOpenAIDriver extends AbstractDriver {
281
290
  await this.service.models.list();
282
291
  return true;
283
292
  }
284
- catch (error) {
293
+ catch {
285
294
  return false;
286
295
  }
287
296
  }
@@ -295,22 +304,36 @@ export class BaseOpenAIDriver extends AbstractDriver {
295
304
  let result = (await this.service.models.list()).data;
296
305
  //Some of these use the completions API instead of the chat completions API.
297
306
  //Others are for non-text input modalities. Therefore common to both.
298
- const wordBlacklist = ["embed", "whisper", "transcribe", "audio", "moderation", "tts",
299
- "realtime", "babbage", "davinci", "codex", "o1-pro", "computer-use", "sora"];
307
+ const wordBlacklist = [
308
+ 'embed',
309
+ 'whisper',
310
+ 'transcribe',
311
+ 'audio',
312
+ 'moderation',
313
+ 'tts',
314
+ 'realtime',
315
+ 'babbage',
316
+ 'davinci',
317
+ 'codex',
318
+ 'o1-pro',
319
+ 'computer-use',
320
+ 'sora',
321
+ ];
300
322
  //OpenAI has very little information, filtering based on name.
301
323
  result = result.filter((m) => {
302
324
  return !wordBlacklist.some((word) => m.id.includes(word));
303
325
  });
304
326
  const models = filter ? result.filter(filter) : result;
305
- const aiModels = models.map((m) => {
306
- const modelCapability = getModelCapabilities(m.id, "openai");
327
+ const aiModels = models
328
+ .map((m) => {
329
+ const modelCapability = getModelCapabilities(m.id, this.provider);
307
330
  let owner = m.owned_by;
308
- if (owner == "system") {
309
- owner = "openai";
331
+ if (owner === 'system') {
332
+ owner = 'openai';
310
333
  }
311
334
  // Determine model type based on capabilities
312
335
  let modelType = ModelType.Text;
313
- if (m.id.includes("dall-e") || m.id.includes("gpt-image")) {
336
+ if (m.id.includes('dall-e') || m.id.includes('gpt-image')) {
314
337
  modelType = ModelType.Image;
315
338
  }
316
339
  return {
@@ -323,34 +346,60 @@ export class BaseOpenAIDriver extends AbstractDriver {
323
346
  output_modalities: modelModalitiesToArray(modelCapability.output),
324
347
  tool_support: modelCapability.tool_support,
325
348
  };
326
- }).sort((a, b) => a.id.localeCompare(b.id));
349
+ })
350
+ .sort((a, b) => a.id.localeCompare(b.id));
327
351
  return aiModels;
328
352
  }
329
- async generateEmbeddings({ text, image, model = "text-embedding-3-small" }) {
330
- if (image) {
331
- throw new Error("Image embeddings not supported by OpenAI");
332
- }
333
- if (!text) {
334
- throw new Error("No text provided");
335
- }
336
- const res = await this.service.embeddings.create({
337
- input: text,
338
- model: model,
353
+ async generateEmbeddings(options) {
354
+ const normalized = normalizeEmbeddingsOptions(options);
355
+ const model = normalized.model ?? OPENAI_DEFAULT_EMBEDDING_MODEL;
356
+ const texts = normalized.inputs.map((input) => {
357
+ if (input.type !== 'text') {
358
+ throw new Error(`Provider 'openai' does not support '${input.type}' embeddings; only 'text' is supported.`);
359
+ }
360
+ return input.text;
339
361
  });
340
- const embeddings = res.data[0].embedding;
341
- if (!embeddings || embeddings.length === 0) {
342
- throw new Error("No embedding found");
362
+ try {
363
+ const res = await this.service.embeddings.create({
364
+ input: texts,
365
+ model,
366
+ ...(normalized.dimensions ? { dimensions: normalized.dimensions } : {}),
367
+ encoding_format: 'float',
368
+ });
369
+ // OpenAI does not guarantee data is returned in the same order as the input,
370
+ // but does return a stable `index` per item. Sort by index to align with inputs.
371
+ const ordered = [...res.data].sort((a, b) => a.index - b.index);
372
+ const items = ordered.map((entry) => {
373
+ if (!entry.embedding || entry.embedding.length === 0) {
374
+ throw new Error(`OpenAI embedding empty for input index ${entry.index}`);
375
+ }
376
+ return { outputs: [{ values: entry.embedding, modality: 'text' }] };
377
+ });
378
+ const usage = res.usage
379
+ ? { input_tokens: res.usage.prompt_tokens, input_text_tokens: res.usage.prompt_tokens }
380
+ : undefined;
381
+ return { model, results: items, usage };
382
+ }
383
+ catch (error) {
384
+ if (LlumiverseError.isLlumiverseError(error))
385
+ throw error;
386
+ if (error instanceof Error && !hasNumericStatus(error))
387
+ throw error;
388
+ throw this.formatLlumiverseError(error, {
389
+ provider: this.provider,
390
+ model,
391
+ operation: 'execute',
392
+ });
343
393
  }
344
- return { values: embeddings, model };
345
394
  }
346
- imageModels = ["dall-e", "gpt-image", "chatgpt-image"];
395
+ imageModels = ['dall-e', 'gpt-image', 'chatgpt-image'];
347
396
  /**
348
397
  * Determine if a model is specifically an image generation model (not conversational image model)
349
398
  */
350
399
  isImageModel(model) {
351
400
  // DALL-E models are standalone image generation
352
401
  // gpt-image models can generate images in conversations, not standalone
353
- return this.imageModels.some(imageModel => model.includes(imageModel));
402
+ return this.imageModels.some((imageModel) => model.includes(imageModel));
354
403
  }
355
404
  /**
356
405
  * Request image generation from standalone Images API
@@ -360,16 +409,16 @@ export class BaseOpenAIDriver extends AbstractDriver {
360
409
  this.logger.debug(`[${this.provider}] Generating image with model ${options.model}`);
361
410
  const model_options = options.model_options;
362
411
  // Extract prompt text from ResponseInputItem[]
363
- let promptText = "";
412
+ let promptText = '';
364
413
  for (const item of prompt) {
365
414
  if ('content' in item && typeof item.content === 'string') {
366
- promptText += item.content + "\\n";
415
+ promptText += `${item.content}\\n`;
367
416
  }
368
417
  else if ('content' in item && Array.isArray(item.content)) {
369
418
  // Extract text from content array
370
419
  for (const part of item.content) {
371
420
  if ('type' in part && part.type === 'input_text' && 'text' in part) {
372
- promptText += part.text + "\\n";
421
+ promptText += `${part.text}\\n`;
373
422
  }
374
423
  }
375
424
  }
@@ -379,15 +428,15 @@ export class BaseOpenAIDriver extends AbstractDriver {
379
428
  const generateParams = {
380
429
  model: options.model,
381
430
  prompt: promptText,
382
- size: model_options?.size || "1024x1024",
431
+ size: model_options?.size || '1024x1024',
383
432
  };
384
433
  // Add DALL-E specific options
385
- if (options.model.includes("dall-e") || model_options?._option_id === "openai-dalle") {
434
+ if (options.model.includes('dall-e') || model_options?._option_id === 'openai-dalle') {
386
435
  const dalleOptions = model_options;
387
436
  generateParams.n = dalleOptions?.n || 1;
388
- generateParams.response_format = dalleOptions?.response_format || "b64_json";
389
- if (options.model.includes("dall-e-3")) {
390
- generateParams.quality = dalleOptions?.image_quality || "standard";
437
+ generateParams.response_format = dalleOptions?.response_format || 'b64_json';
438
+ if (options.model.includes('dall-e-3')) {
439
+ generateParams.quality = dalleOptions?.image_quality || 'standard';
391
440
  if (dalleOptions?.style) {
392
441
  generateParams.style = dalleOptions.style;
393
442
  }
@@ -415,23 +464,27 @@ export class BaseOpenAIDriver extends AbstractDriver {
415
464
  continue;
416
465
  }
417
466
  results.push({
418
- type: "image",
419
- value: imageValue
467
+ type: 'image',
468
+ value: imageValue,
420
469
  });
421
470
  }
422
471
  }
423
472
  return {
424
- result: results
473
+ result: results,
425
474
  };
426
475
  }
427
476
  catch (error) {
428
477
  this.logger.error({ error }, `[${this.provider}] Image generation failed`);
478
+ const generationError = error instanceof Error ? error : new Error(String(error));
479
+ const errorCode = error?.code === 'content_policy_violation'
480
+ ? 'content_policy_violation'
481
+ : 'validation_error';
429
482
  return {
430
483
  result: [],
431
484
  error: {
432
- message: error.message,
433
- code: error.code || 'GENERATION_FAILED'
434
- }
485
+ message: generationError.message,
486
+ code: errorCode,
487
+ },
435
488
  };
436
489
  }
437
490
  }
@@ -512,9 +565,7 @@ export class BaseOpenAIDriver extends AbstractDriver {
512
565
  * Type guard to check if error is an OpenAI API error or OpenAI-specific error.
513
566
  */
514
567
  isOpenAIApiError(error) {
515
- return (error !== null &&
516
- typeof error === 'object' &&
517
- (error instanceof APIError || error instanceof OpenAIError));
568
+ return (error !== null && typeof error === 'object' && (error instanceof APIError || error instanceof OpenAIError));
518
569
  }
519
570
  /**
520
571
  * Determine if an OpenAI API error is retryable.
@@ -591,7 +642,7 @@ export class BaseOpenAIDriver extends AbstractDriver {
591
642
  return false;
592
643
  if (errorCode === 'invalid_model')
593
644
  return false;
594
- if (errorCode.includes('invalid_'))
645
+ if (typeof errorCode === 'string' && errorCode.includes('invalid_'))
595
646
  return false;
596
647
  }
597
648
  // Check error type
@@ -637,7 +688,9 @@ function jobInfo(job) {
637
688
  }
638
689
  else if (jobStatus === 'failed') {
639
690
  status = TrainingJobStatus.failed;
640
- details = job.error ? `${job.error.code} - ${job.error.message} ${job.error.param ? " [" + job.error.param + "]" : ""}` : "error";
691
+ details = job.error
692
+ ? `${job.error.code} - ${job.error.message} ${job.error.param ? ` [${job.error.param}]` : ''}`
693
+ : 'error';
641
694
  }
642
695
  else if (jobStatus === 'cancelled') {
643
696
  status = TrainingJobStatus.cancelled;
@@ -650,19 +703,20 @@ function jobInfo(job) {
650
703
  id: job.id,
651
704
  model: job.fine_tuned_model || undefined,
652
705
  status,
653
- details
706
+ details,
654
707
  };
655
708
  }
656
709
  function mapUsage(usage) {
657
710
  if (!usage) {
658
711
  return undefined;
659
712
  }
713
+ const cachedTokens = usage.input_tokens_details?.cached_tokens ?? usage.prompt_tokens_details?.cached_tokens ?? usage.cached_tokens;
660
714
  return {
661
715
  prompt: usage.input_tokens,
662
716
  result: usage.output_tokens,
663
717
  total: usage.total_tokens,
664
- prompt_cached: usage.input_tokens_details?.cached_tokens ?? undefined,
665
- prompt_new: usage.input_tokens - (usage.input_tokens_details?.cached_tokens ?? 0),
718
+ prompt_cached: cachedTokens ?? undefined,
719
+ prompt_new: usage.input_tokens - (cachedTokens ?? 0),
666
720
  };
667
721
  }
668
722
  function completionResultsToText(completionResults) {
@@ -670,7 +724,7 @@ function completionResultsToText(completionResults) {
670
724
  return '';
671
725
  }
672
726
  return completionResults
673
- .map(r => {
727
+ .map((r) => {
674
728
  switch (r.type) {
675
729
  case 'text':
676
730
  return r.value;
@@ -679,8 +733,10 @@ function completionResultsToText(completionResults) {
679
733
  case 'image':
680
734
  // Skip images in conversation - they're in the result
681
735
  return '';
682
- default:
683
- return String(r.value || '');
736
+ default: {
737
+ const _exhaustive = r;
738
+ return String(_exhaustive);
739
+ }
684
740
  }
685
741
  })
686
742
  .join('');
@@ -691,6 +747,7 @@ function createAssistantMessageFromCompletion(completion) {
691
747
  // Add assistant text message if present
692
748
  if (textContent) {
693
749
  const assistantMessage = {
750
+ type: 'message',
694
751
  role: 'assistant',
695
752
  content: textContent,
696
753
  };
@@ -703,9 +760,7 @@ function createAssistantMessageFromCompletion(completion) {
703
760
  type: 'function_call',
704
761
  call_id: t.id,
705
762
  name: t.tool_name,
706
- arguments: typeof t.tool_input === 'string'
707
- ? t.tool_input
708
- : JSON.stringify(t.tool_input ?? {}),
763
+ arguments: typeof t.tool_input === 'string' ? t.tool_input : JSON.stringify(t.tool_input ?? {}),
709
764
  };
710
765
  result.push(functionCall);
711
766
  }
@@ -716,6 +771,8 @@ export function mapResponseStream(stream) {
716
771
  const toolCallMetadata = new Map();
717
772
  return {
718
773
  async *[Symbol.asyncIterator]() {
774
+ let hasTextDeltas = false;
775
+ let refusalText = '';
719
776
  for await (const event of stream) {
720
777
  if (event.type === 'response.output_item.added' && event.item.type === 'function_call') {
721
778
  const syntheticId = `tool_${event.output_index}`;
@@ -766,13 +823,34 @@ export function mapResponseStream(stream) {
766
823
  }
767
824
  }
768
825
  else if (event.type === 'response.output_text.delta') {
826
+ hasTextDeltas = true;
769
827
  yield {
770
828
  result: textToCompletionResult(event.delta),
771
829
  };
772
830
  }
773
- // Note: We don't emit response.output_text.done because the text was already
774
- // streamed via delta events. Emitting it again would duplicate the content.
775
- else if (event.type === 'response.completed' || event.type === 'response.incomplete' || event.type === 'response.failed') {
831
+ else if (event.type === 'response.output_text.done') {
832
+ // Fallback: some models (e.g. gpt-5 with json_schema structured output) buffer
833
+ // the entire output and never emit delta events only the done event with the
834
+ // full text. Emit it here only when no deltas arrived to avoid duplication.
835
+ if (!hasTextDeltas && event.text) {
836
+ yield {
837
+ result: textToCompletionResult(event.text),
838
+ };
839
+ }
840
+ }
841
+ else if (event.type === 'response.refusal.delta') {
842
+ refusalText += event.delta;
843
+ }
844
+ else if (event.type === 'response.refusal.done') {
845
+ throw new Error(`[OpenAI] Model refused: ${event.refusal || refusalText}`);
846
+ }
847
+ else if (event.type === 'response.error') {
848
+ const errEvent = event;
849
+ throw new Error(`[OpenAI Responses API] ${errEvent.message}${errEvent.code ? ` (${errEvent.code})` : ''}`);
850
+ }
851
+ else if (event.type === 'response.completed' ||
852
+ event.type === 'response.incomplete' ||
853
+ event.type === 'response.failed') {
776
854
  const finalTools = collectTools(event.response.output);
777
855
  yield {
778
856
  result: [],
@@ -781,11 +859,11 @@ export function mapResponseStream(stream) {
781
859
  };
782
860
  }
783
861
  }
784
- }
862
+ },
785
863
  };
786
864
  }
787
865
  function insert_image_detail(items, detail_level) {
788
- if (detail_level === "auto" || detail_level === "low" || detail_level === "high") {
866
+ if (detail_level === 'auto' || detail_level === 'low' || detail_level === 'high') {
789
867
  for (const item of items) {
790
868
  // Check if it's an EasyInputMessage or Message with content array
791
869
  if ('role' in item && 'content' in item && item.role !== 'assistant') {
@@ -804,8 +882,8 @@ function insert_image_detail(items, detail_level) {
804
882
  }
805
883
  function convertRoles(items, model) {
806
884
  //New openai models use developer role instead of system
807
- if (model.includes("o1") || model.includes("o3")) {
808
- if (model.includes("o1-mini") || model.includes("o1-preview")) {
885
+ if (model.includes('o1') || model.includes('o3')) {
886
+ if (model.includes('o1-mini') || model.includes('o1-preview')) {
809
887
  //o1-mini and o1-preview support neither system nor developer
810
888
  for (const item of items) {
811
889
  if ('role' in item && item.role === 'system') {
@@ -826,12 +904,12 @@ function convertRoles(items, model) {
826
904
  }
827
905
  //Structured output support is typically aligned with tool use support
828
906
  //Not true for realtime models, which do not support structured output, but do support tool use.
829
- function supportsSchema(model) {
830
- const realtimeModel = model.includes("realtime");
907
+ function supportsSchema(model, provider) {
908
+ const realtimeModel = model.includes('realtime');
831
909
  if (realtimeModel) {
832
910
  return false;
833
911
  }
834
- return supportsToolUse(model, "openai");
912
+ return supportsToolUse(model, provider);
835
913
  }
836
914
  /**
837
915
  * Converts function_call and function_call_output items to text messages in OpenAI conversation.
@@ -839,17 +917,17 @@ function supportsSchema(model) {
839
917
  * tools to be defined in the API request.
840
918
  */
841
919
  export function convertOpenAIFunctionItemsToText(items) {
842
- const hasFunctionItems = items.some(item => {
920
+ const hasFunctionItems = items.some((item) => {
843
921
  const type = item.type;
844
922
  return type === 'function_call' || type === 'function_call_output';
845
923
  });
846
924
  if (!hasFunctionItems)
847
925
  return items;
848
- return items.map(item => {
926
+ return items.map((item) => {
849
927
  const typed = item;
850
928
  if (typed.type === 'function_call') {
851
929
  const argsStr = typed.arguments || '';
852
- const truncated = argsStr.length > 500 ? argsStr.substring(0, 500) + '...' : argsStr;
930
+ const truncated = argsStr.length > 500 ? `${argsStr.substring(0, 500)}...` : argsStr;
853
931
  return {
854
932
  role: 'assistant',
855
933
  content: `[Tool call: ${typed.name}(${truncated})]`,
@@ -857,7 +935,7 @@ export function convertOpenAIFunctionItemsToText(items) {
857
935
  }
858
936
  if (typed.type === 'function_call_output') {
859
937
  const output = typed.output || 'No output';
860
- const truncated = output.length > 500 ? output.substring(0, 500) + '...' : output;
938
+ const truncated = output.length > 500 ? `${output.substring(0, 500)}...` : output;
861
939
  return {
862
940
  role: 'user',
863
941
  content: `[Tool result: ${truncated}]`,
@@ -870,7 +948,7 @@ function getToolDefinitions(tools) {
870
948
  return tools ? tools.map(getToolDefinition) : undefined;
871
949
  }
872
950
  function getToolDefinition(toolDef) {
873
- let parsedSchema = undefined;
951
+ let parsedSchema;
874
952
  let strictMode = false;
875
953
  if (toolDef.input_schema) {
876
954
  try {
@@ -878,14 +956,14 @@ function getToolDefinition(toolDef) {
878
956
  parsedSchema = openAISchemaFormat(toolDef.input_schema);
879
957
  strictMode = true;
880
958
  }
881
- catch (e) {
959
+ catch {
882
960
  //TODO: type assertion here is not safe, does not work with satisfies
883
961
  parsedSchema = limitedSchemaFormat(toolDef.input_schema);
884
962
  strictMode = false;
885
963
  }
886
964
  }
887
965
  return {
888
- type: "function",
966
+ type: 'function',
889
967
  name: toolDef.name,
890
968
  description: toolDef.description,
891
969
  parameters: parsedSchema ?? null,
@@ -941,8 +1019,8 @@ function extractCompletionResults(output) {
941
1019
  for (const part of item.content) {
942
1020
  if (part.type === 'output_text' && part.text) {
943
1021
  results.push({
944
- type: "text",
945
- value: part.text
1022
+ type: 'text',
1023
+ value: part.text,
946
1024
  });
947
1025
  }
948
1026
  }
@@ -951,12 +1029,10 @@ function extractCompletionResults(output) {
951
1029
  // GPT-image models return base64 encoded images in result field
952
1030
  const base64Data = item.result;
953
1031
  // Format as data URL for consistency with other image outputs
954
- const imageUrl = base64Data.startsWith('data:')
955
- ? base64Data
956
- : `data:image/png;base64,${base64Data}`;
1032
+ const imageUrl = base64Data.startsWith('data:') ? base64Data : `data:image/png;base64,${base64Data}`;
957
1033
  results.push({
958
- type: "image",
959
- value: imageUrl
1034
+ type: 'image',
1035
+ value: imageUrl,
960
1036
  });
961
1037
  }
962
1038
  }
@@ -999,13 +1075,13 @@ function limitedSchemaFormat(schema) {
999
1075
  //For strict mode true
1000
1076
  function openAISchemaFormat(schema, nesting = 0) {
1001
1077
  if (nesting > 5) {
1002
- throw new Error("OpenAI schema nesting too deep");
1078
+ throw new Error('OpenAI schema nesting too deep');
1003
1079
  }
1004
1080
  const formattedSchema = { ...schema };
1005
1081
  // Defaults not supported
1006
1082
  delete formattedSchema.default;
1007
1083
  // Additional properties not supported, required to be set.
1008
- if (formattedSchema?.type === "object") {
1084
+ if (formattedSchema?.type === 'object') {
1009
1085
  formattedSchema.additionalProperties = false;
1010
1086
  }
1011
1087
  if (formattedSchema?.properties) {
@@ -1029,16 +1105,17 @@ function openAISchemaFormat(schema, nesting = 0) {
1029
1105
  }
1030
1106
  }
1031
1107
  }
1032
- if (formattedSchema?.type === 'object' && (!formattedSchema?.properties || Object.keys(formattedSchema?.properties ?? {}).length == 0)) {
1108
+ if (formattedSchema?.type === 'object' &&
1109
+ (!formattedSchema?.properties || Object.keys(formattedSchema?.properties ?? {}).length === 0)) {
1033
1110
  //If no properties are defined, then additionalProperties: true was set or the object would be empty.
1034
1111
  //OpenAI does not support this on structured output/ strict mode.
1035
- throw new Error("OpenAI does not support empty objects or objects with additionalProperties set to true");
1112
+ throw new Error('OpenAI does not support empty objects or objects with additionalProperties set to true');
1036
1113
  }
1037
1114
  return formattedSchema;
1038
1115
  }
1039
1116
  function responseFinishReason(response, tools) {
1040
1117
  if (tools && tools.length > 0) {
1041
- return "tool_use";
1118
+ return 'tool_use';
1042
1119
  }
1043
1120
  if (response.status === 'incomplete') {
1044
1121
  if (response.incomplete_details?.reason === 'max_output_tokens') {
@@ -1113,6 +1190,30 @@ export function fixOrphanedToolUse(items) {
1113
1190
  }
1114
1191
  return result;
1115
1192
  }
1193
+ /**
1194
+ * Drop function_call_output items whose call_id has no matching function_call
1195
+ * item anywhere in the input. Mirror of {@link fixOrphanedToolUse}: that
1196
+ * synthesizes outputs for calls left unanswered (e.g. a cancelled run); this
1197
+ * removes outputs left dangling after their function_call was dropped (e.g. by
1198
+ * conversation compaction/trimming). The OpenAI Responses API requires every
1199
+ * function_call_output to reference a prior function_call's call_id.
1200
+ */
1201
+ export function fixOrphanedToolResults(items) {
1202
+ if (items.length === 0)
1203
+ return items;
1204
+ const callIds = new Set();
1205
+ for (const item of items) {
1206
+ if ('type' in item && item.type === 'function_call') {
1207
+ callIds.add(item.call_id);
1208
+ }
1209
+ }
1210
+ return items.filter((item) => {
1211
+ if ('type' in item && item.type === 'function_call_output') {
1212
+ return callIds.has(item.call_id);
1213
+ }
1214
+ return true;
1215
+ });
1216
+ }
1116
1217
  function safeJsonParse(value) {
1117
1218
  if (typeof value !== 'string') {
1118
1219
  return value;