@llumiverse/drivers 1.2.0 → 1.4.0-dev.20260629.090753Z

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 (403) 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/anthropic/index.d.ts +23 -0
  6. package/lib/anthropic/index.d.ts.map +1 -0
  7. package/lib/anthropic/index.js +68 -0
  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 +17 -5
  68. package/lib/openai/index.d.ts.map +1 -0
  69. package/lib/{esm/openai → openai}/index.js +254 -148
  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/shared/claude-messages.d.ts +99 -0
  88. package/lib/shared/claude-messages.d.ts.map +1 -0
  89. package/lib/shared/claude-messages.js +869 -0
  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/vertexai/models/claude.d.ts +16 -0
  143. package/lib/vertexai/models/claude.d.ts.map +1 -0
  144. package/lib/vertexai/models/claude.js +65 -0
  145. package/lib/vertexai/models/claude.js.map +1 -0
  146. package/lib/{types/vertexai → vertexai}/models/gemini.d.ts +29 -5
  147. package/lib/vertexai/models/gemini.d.ts.map +1 -0
  148. package/lib/{esm/vertexai → vertexai}/models/gemini.js +255 -127
  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 +88 -36
  173. package/src/adobe/firefly.ts +60 -43
  174. package/src/anthropic/index.ts +121 -0
  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 -15
  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 +389 -254
  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 +1085 -0
  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 +339 -253
  219. package/src/vertexai/models/claude-error-handling.test.ts +86 -39
  220. package/src/vertexai/models/claude-streaming-spacing.test.ts +82 -75
  221. package/src/vertexai/models/claude.ts +84 -1041
  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 +372 -182
  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/azure/azure_foundry.js +0 -432
  235. package/lib/cjs/azure/azure_foundry.js.map +0 -1
  236. package/lib/cjs/bedrock/converse.js +0 -359
  237. package/lib/cjs/bedrock/converse.js.map +0 -1
  238. package/lib/cjs/bedrock/index.js +0 -1508
  239. package/lib/cjs/bedrock/index.js.map +0 -1
  240. package/lib/cjs/bedrock/nova-image-payload.js +0 -207
  241. package/lib/cjs/bedrock/nova-image-payload.js.map +0 -1
  242. package/lib/cjs/bedrock/payloads.js +0 -3
  243. package/lib/cjs/bedrock/s3.js +0 -107
  244. package/lib/cjs/bedrock/s3.js.map +0 -1
  245. package/lib/cjs/bedrock/twelvelabs.js +0 -87
  246. package/lib/cjs/bedrock/twelvelabs.js.map +0 -1
  247. package/lib/cjs/groq/index.js +0 -328
  248. package/lib/cjs/groq/index.js.map +0 -1
  249. package/lib/cjs/huggingface_ie.js +0 -201
  250. package/lib/cjs/huggingface_ie.js.map +0 -1
  251. package/lib/cjs/index.js +0 -31
  252. package/lib/cjs/index.js.map +0 -1
  253. package/lib/cjs/mistral/index.js +0 -176
  254. package/lib/cjs/mistral/index.js.map +0 -1
  255. package/lib/cjs/mistral/types.js +0 -83
  256. package/lib/cjs/mistral/types.js.map +0 -1
  257. package/lib/cjs/openai/azure_openai.js +0 -72
  258. package/lib/cjs/openai/azure_openai.js.map +0 -1
  259. package/lib/cjs/openai/index.js +0 -1129
  260. package/lib/cjs/openai/index.js.map +0 -1
  261. package/lib/cjs/openai/openai.js +0 -21
  262. package/lib/cjs/openai/openai.js.map +0 -1
  263. package/lib/cjs/openai/openai_compatible.js +0 -63
  264. package/lib/cjs/openai/openai_compatible.js.map +0 -1
  265. package/lib/cjs/openai/openai_format.js +0 -131
  266. package/lib/cjs/openai/openai_format.js.map +0 -1
  267. package/lib/cjs/package.json +0 -3
  268. package/lib/cjs/replicate.js +0 -275
  269. package/lib/cjs/replicate.js.map +0 -1
  270. package/lib/cjs/shared/claude-thinking.js +0 -60
  271. package/lib/cjs/shared/claude-thinking.js.map +0 -1
  272. package/lib/cjs/test-driver/TestErrorCompletionStream.js +0 -20
  273. package/lib/cjs/test-driver/TestErrorCompletionStream.js.map +0 -1
  274. package/lib/cjs/test-driver/TestValidationErrorCompletionStream.js +0 -24
  275. package/lib/cjs/test-driver/TestValidationErrorCompletionStream.js.map +0 -1
  276. package/lib/cjs/test-driver/index.js +0 -109
  277. package/lib/cjs/test-driver/index.js.map +0 -1
  278. package/lib/cjs/test-driver/utils.js +0 -30
  279. package/lib/cjs/test-driver/utils.js.map +0 -1
  280. package/lib/cjs/togetherai/index.js +0 -126
  281. package/lib/cjs/togetherai/index.js.map +0 -1
  282. package/lib/cjs/togetherai/interfaces.js +0 -3
  283. package/lib/cjs/togetherai/interfaces.js.map +0 -1
  284. package/lib/cjs/vertexai/debug.js +0 -12
  285. package/lib/cjs/vertexai/debug.js.map +0 -1
  286. package/lib/cjs/vertexai/embeddings/embeddings-image.js +0 -27
  287. package/lib/cjs/vertexai/embeddings/embeddings-image.js.map +0 -1
  288. package/lib/cjs/vertexai/embeddings/embeddings-text.js +0 -23
  289. package/lib/cjs/vertexai/embeddings/embeddings-text.js.map +0 -1
  290. package/lib/cjs/vertexai/index.js +0 -644
  291. package/lib/cjs/vertexai/index.js.map +0 -1
  292. package/lib/cjs/vertexai/models/claude.js +0 -917
  293. package/lib/cjs/vertexai/models/claude.js.map +0 -1
  294. package/lib/cjs/vertexai/models/gemini.js +0 -858
  295. package/lib/cjs/vertexai/models/gemini.js.map +0 -1
  296. package/lib/cjs/vertexai/models/imagen.js +0 -303
  297. package/lib/cjs/vertexai/models/imagen.js.map +0 -1
  298. package/lib/cjs/vertexai/models/llama.js +0 -183
  299. package/lib/cjs/vertexai/models/llama.js.map +0 -1
  300. package/lib/cjs/vertexai/models.js +0 -35
  301. package/lib/cjs/vertexai/models.js.map +0 -1
  302. package/lib/cjs/watsonx/index.js +0 -161
  303. package/lib/cjs/watsonx/index.js.map +0 -1
  304. package/lib/cjs/watsonx/interfaces.js +0 -3
  305. package/lib/cjs/xai/index.js +0 -65
  306. package/lib/cjs/xai/index.js.map +0 -1
  307. package/lib/esm/adobe/firefly.js +0 -116
  308. package/lib/esm/adobe/firefly.js.map +0 -1
  309. package/lib/esm/azure/azure_foundry.js.map +0 -1
  310. package/lib/esm/bedrock/converse.js.map +0 -1
  311. package/lib/esm/bedrock/index.js.map +0 -1
  312. package/lib/esm/bedrock/nova-image-payload.js.map +0 -1
  313. package/lib/esm/bedrock/payloads.js.map +0 -1
  314. package/lib/esm/bedrock/s3.js.map +0 -1
  315. package/lib/esm/bedrock/twelvelabs.js.map +0 -1
  316. package/lib/esm/groq/index.js.map +0 -1
  317. package/lib/esm/huggingface_ie.js.map +0 -1
  318. package/lib/esm/index.js +0 -15
  319. package/lib/esm/index.js.map +0 -1
  320. package/lib/esm/mistral/index.js.map +0 -1
  321. package/lib/esm/mistral/types.js.map +0 -1
  322. package/lib/esm/openai/azure_openai.js.map +0 -1
  323. package/lib/esm/openai/index.js.map +0 -1
  324. package/lib/esm/openai/openai.js +0 -14
  325. package/lib/esm/openai/openai.js.map +0 -1
  326. package/lib/esm/openai/openai_compatible.js.map +0 -1
  327. package/lib/esm/openai/openai_format.js.map +0 -1
  328. package/lib/esm/replicate.js.map +0 -1
  329. package/lib/esm/shared/claude-thinking.js.map +0 -1
  330. package/lib/esm/test-driver/TestErrorCompletionStream.js +0 -16
  331. package/lib/esm/test-driver/TestErrorCompletionStream.js.map +0 -1
  332. package/lib/esm/test-driver/TestValidationErrorCompletionStream.js.map +0 -1
  333. package/lib/esm/test-driver/index.js.map +0 -1
  334. package/lib/esm/test-driver/utils.js.map +0 -1
  335. package/lib/esm/togetherai/index.js +0 -122
  336. package/lib/esm/togetherai/index.js.map +0 -1
  337. package/lib/esm/togetherai/interfaces.js.map +0 -1
  338. package/lib/esm/vertexai/debug.js.map +0 -1
  339. package/lib/esm/vertexai/embeddings/embeddings-image.js +0 -24
  340. package/lib/esm/vertexai/embeddings/embeddings-image.js.map +0 -1
  341. package/lib/esm/vertexai/embeddings/embeddings-text.js +0 -20
  342. package/lib/esm/vertexai/embeddings/embeddings-text.js.map +0 -1
  343. package/lib/esm/vertexai/index.js.map +0 -1
  344. package/lib/esm/vertexai/models/claude.js +0 -906
  345. package/lib/esm/vertexai/models/claude.js.map +0 -1
  346. package/lib/esm/vertexai/models/gemini.js.map +0 -1
  347. package/lib/esm/vertexai/models/imagen.js.map +0 -1
  348. package/lib/esm/vertexai/models/llama.js.map +0 -1
  349. package/lib/esm/vertexai/models.js.map +0 -1
  350. package/lib/esm/watsonx/index.js.map +0 -1
  351. package/lib/esm/xai/index.js.map +0 -1
  352. package/lib/types/adobe/firefly.d.ts.map +0 -1
  353. package/lib/types/azure/azure_foundry.d.ts.map +0 -1
  354. package/lib/types/bedrock/converse.d.ts.map +0 -1
  355. package/lib/types/bedrock/index.d.ts.map +0 -1
  356. package/lib/types/bedrock/nova-image-payload.d.ts.map +0 -1
  357. package/lib/types/bedrock/payloads.d.ts.map +0 -1
  358. package/lib/types/bedrock/s3.d.ts.map +0 -1
  359. package/lib/types/bedrock/twelvelabs.d.ts.map +0 -1
  360. package/lib/types/groq/index.d.ts.map +0 -1
  361. package/lib/types/huggingface_ie.d.ts.map +0 -1
  362. package/lib/types/index.d.ts +0 -15
  363. package/lib/types/index.d.ts.map +0 -1
  364. package/lib/types/mistral/index.d.ts.map +0 -1
  365. package/lib/types/mistral/types.d.ts.map +0 -1
  366. package/lib/types/openai/azure_openai.d.ts.map +0 -1
  367. package/lib/types/openai/index.d.ts.map +0 -1
  368. package/lib/types/openai/openai.d.ts.map +0 -1
  369. package/lib/types/openai/openai_compatible.d.ts.map +0 -1
  370. package/lib/types/openai/openai_format.d.ts.map +0 -1
  371. package/lib/types/replicate.d.ts.map +0 -1
  372. package/lib/types/shared/claude-thinking.d.ts.map +0 -1
  373. package/lib/types/test-driver/TestErrorCompletionStream.d.ts.map +0 -1
  374. package/lib/types/test-driver/TestValidationErrorCompletionStream.d.ts.map +0 -1
  375. package/lib/types/test-driver/index.d.ts.map +0 -1
  376. package/lib/types/test-driver/utils.d.ts.map +0 -1
  377. package/lib/types/togetherai/index.d.ts +0 -23
  378. package/lib/types/togetherai/index.d.ts.map +0 -1
  379. package/lib/types/togetherai/interfaces.d.ts.map +0 -1
  380. package/lib/types/vertexai/debug.d.ts +0 -2
  381. package/lib/types/vertexai/debug.d.ts.map +0 -1
  382. package/lib/types/vertexai/embeddings/embeddings-image.d.ts +0 -11
  383. package/lib/types/vertexai/embeddings/embeddings-image.d.ts.map +0 -1
  384. package/lib/types/vertexai/embeddings/embeddings-text.d.ts +0 -10
  385. package/lib/types/vertexai/embeddings/embeddings-text.d.ts.map +0 -1
  386. package/lib/types/vertexai/index.d.ts.map +0 -1
  387. package/lib/types/vertexai/models/claude.d.ts +0 -119
  388. package/lib/types/vertexai/models/claude.d.ts.map +0 -1
  389. package/lib/types/vertexai/models/gemini.d.ts.map +0 -1
  390. package/lib/types/vertexai/models/imagen.d.ts.map +0 -1
  391. package/lib/types/vertexai/models/llama.d.ts.map +0 -1
  392. package/lib/types/vertexai/models.d.ts +0 -20
  393. package/lib/types/vertexai/models.d.ts.map +0 -1
  394. package/lib/types/watsonx/index.d.ts.map +0 -1
  395. package/lib/types/watsonx/interfaces.d.ts.map +0 -1
  396. package/lib/types/xai/index.d.ts.map +0 -1
  397. package/src/vertexai/embeddings/embeddings-image.ts +0 -52
  398. package/src/vertexai/embeddings/embeddings-text.ts +0 -54
  399. /package/lib/{esm/bedrock → bedrock}/payloads.js +0 -0
  400. /package/lib/{esm/mistral → mistral}/types.js +0 -0
  401. /package/lib/{esm/togetherai → togetherai}/interfaces.js +0 -0
  402. /package/lib/{types/watsonx → watsonx}/interfaces.d.ts +0 -0
  403. /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,29 +760,33 @@ 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
  }
712
767
  }
713
768
  return result;
714
769
  }
715
- function mapResponseStream(stream) {
770
+ 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}`;
722
- const actualId = event.item.id ?? event.item.call_id;
723
- if (actualId) {
724
- toolCallMetadata.set(actualId, { syntheticId, name: event.item.name });
779
+ const callId = event.item.call_id ?? event.item.id;
780
+ const metadata = { syntheticId, callId, name: event.item.name };
781
+ if (event.item.id) {
782
+ toolCallMetadata.set(event.item.id, metadata);
783
+ }
784
+ if (event.item.call_id) {
785
+ toolCallMetadata.set(event.item.call_id, metadata);
725
786
  }
726
787
  const toolUse = {
727
788
  id: syntheticId,
728
- _actual_id: actualId,
789
+ _actual_id: callId,
729
790
  tool_name: event.item.name,
730
791
  tool_input: '',
731
792
  };
@@ -737,9 +798,10 @@ function mapResponseStream(stream) {
737
798
  else if (event.type === 'response.function_call_arguments.delta') {
738
799
  const metadata = toolCallMetadata.get(event.item_id);
739
800
  const syntheticId = metadata?.syntheticId ?? `tool_${event.output_index}`;
801
+ const callId = metadata?.callId ?? event.item_id;
740
802
  const toolUse = {
741
803
  id: syntheticId,
742
- _actual_id: event.item_id,
804
+ _actual_id: callId,
743
805
  tool_name: metadata?.name ?? '',
744
806
  tool_input: event.delta,
745
807
  };
@@ -757,17 +819,38 @@ function mapResponseStream(stream) {
757
819
  const syntheticId = metadata?.syntheticId ?? `tool_${event.output_index}`;
758
820
  const tool_name = metadata?.name ?? event.name ?? '';
759
821
  if (event.item_id) {
760
- toolCallMetadata.set(event.item_id, { syntheticId, name: tool_name });
822
+ toolCallMetadata.set(event.item_id, { syntheticId, callId: metadata?.callId, name: tool_name });
761
823
  }
762
824
  }
763
825
  else if (event.type === 'response.output_text.delta') {
826
+ hasTextDeltas = true;
764
827
  yield {
765
828
  result: textToCompletionResult(event.delta),
766
829
  };
767
830
  }
768
- // Note: We don't emit response.output_text.done because the text was already
769
- // streamed via delta events. Emitting it again would duplicate the content.
770
- 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') {
771
854
  const finalTools = collectTools(event.response.output);
772
855
  yield {
773
856
  result: [],
@@ -776,11 +859,11 @@ function mapResponseStream(stream) {
776
859
  };
777
860
  }
778
861
  }
779
- }
862
+ },
780
863
  };
781
864
  }
782
865
  function insert_image_detail(items, detail_level) {
783
- if (detail_level === "auto" || detail_level === "low" || detail_level === "high") {
866
+ if (detail_level === 'auto' || detail_level === 'low' || detail_level === 'high') {
784
867
  for (const item of items) {
785
868
  // Check if it's an EasyInputMessage or Message with content array
786
869
  if ('role' in item && 'content' in item && item.role !== 'assistant') {
@@ -799,8 +882,8 @@ function insert_image_detail(items, detail_level) {
799
882
  }
800
883
  function convertRoles(items, model) {
801
884
  //New openai models use developer role instead of system
802
- if (model.includes("o1") || model.includes("o3")) {
803
- 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')) {
804
887
  //o1-mini and o1-preview support neither system nor developer
805
888
  for (const item of items) {
806
889
  if ('role' in item && item.role === 'system') {
@@ -821,12 +904,12 @@ function convertRoles(items, model) {
821
904
  }
822
905
  //Structured output support is typically aligned with tool use support
823
906
  //Not true for realtime models, which do not support structured output, but do support tool use.
824
- function supportsSchema(model) {
825
- const realtimeModel = model.includes("realtime");
907
+ function supportsSchema(model, provider) {
908
+ const realtimeModel = model.includes('realtime');
826
909
  if (realtimeModel) {
827
910
  return false;
828
911
  }
829
- return supportsToolUse(model, "openai");
912
+ return supportsToolUse(model, provider);
830
913
  }
831
914
  /**
832
915
  * Converts function_call and function_call_output items to text messages in OpenAI conversation.
@@ -834,17 +917,17 @@ function supportsSchema(model) {
834
917
  * tools to be defined in the API request.
835
918
  */
836
919
  export function convertOpenAIFunctionItemsToText(items) {
837
- const hasFunctionItems = items.some(item => {
920
+ const hasFunctionItems = items.some((item) => {
838
921
  const type = item.type;
839
922
  return type === 'function_call' || type === 'function_call_output';
840
923
  });
841
924
  if (!hasFunctionItems)
842
925
  return items;
843
- return items.map(item => {
926
+ return items.map((item) => {
844
927
  const typed = item;
845
928
  if (typed.type === 'function_call') {
846
929
  const argsStr = typed.arguments || '';
847
- const truncated = argsStr.length > 500 ? argsStr.substring(0, 500) + '...' : argsStr;
930
+ const truncated = argsStr.length > 500 ? `${argsStr.substring(0, 500)}...` : argsStr;
848
931
  return {
849
932
  role: 'assistant',
850
933
  content: `[Tool call: ${typed.name}(${truncated})]`,
@@ -852,7 +935,7 @@ export function convertOpenAIFunctionItemsToText(items) {
852
935
  }
853
936
  if (typed.type === 'function_call_output') {
854
937
  const output = typed.output || 'No output';
855
- const truncated = output.length > 500 ? output.substring(0, 500) + '...' : output;
938
+ const truncated = output.length > 500 ? `${output.substring(0, 500)}...` : output;
856
939
  return {
857
940
  role: 'user',
858
941
  content: `[Tool result: ${truncated}]`,
@@ -865,7 +948,7 @@ function getToolDefinitions(tools) {
865
948
  return tools ? tools.map(getToolDefinition) : undefined;
866
949
  }
867
950
  function getToolDefinition(toolDef) {
868
- let parsedSchema = undefined;
951
+ let parsedSchema;
869
952
  let strictMode = false;
870
953
  if (toolDef.input_schema) {
871
954
  try {
@@ -873,14 +956,14 @@ function getToolDefinition(toolDef) {
873
956
  parsedSchema = openAISchemaFormat(toolDef.input_schema);
874
957
  strictMode = true;
875
958
  }
876
- catch (e) {
959
+ catch {
877
960
  //TODO: type assertion here is not safe, does not work with satisfies
878
961
  parsedSchema = limitedSchemaFormat(toolDef.input_schema);
879
962
  strictMode = false;
880
963
  }
881
964
  }
882
965
  return {
883
- type: "function",
966
+ type: 'function',
884
967
  name: toolDef.name,
885
968
  description: toolDef.description,
886
969
  parameters: parsedSchema ?? null,
@@ -936,8 +1019,8 @@ function extractCompletionResults(output) {
936
1019
  for (const part of item.content) {
937
1020
  if (part.type === 'output_text' && part.text) {
938
1021
  results.push({
939
- type: "text",
940
- value: part.text
1022
+ type: 'text',
1023
+ value: part.text,
941
1024
  });
942
1025
  }
943
1026
  }
@@ -946,12 +1029,10 @@ function extractCompletionResults(output) {
946
1029
  // GPT-image models return base64 encoded images in result field
947
1030
  const base64Data = item.result;
948
1031
  // Format as data URL for consistency with other image outputs
949
- const imageUrl = base64Data.startsWith('data:')
950
- ? base64Data
951
- : `data:image/png;base64,${base64Data}`;
1032
+ const imageUrl = base64Data.startsWith('data:') ? base64Data : `data:image/png;base64,${base64Data}`;
952
1033
  results.push({
953
- type: "image",
954
- value: imageUrl
1034
+ type: 'image',
1035
+ value: imageUrl,
955
1036
  });
956
1037
  }
957
1038
  }
@@ -994,13 +1075,13 @@ function limitedSchemaFormat(schema) {
994
1075
  //For strict mode true
995
1076
  function openAISchemaFormat(schema, nesting = 0) {
996
1077
  if (nesting > 5) {
997
- throw new Error("OpenAI schema nesting too deep");
1078
+ throw new Error('OpenAI schema nesting too deep');
998
1079
  }
999
1080
  const formattedSchema = { ...schema };
1000
1081
  // Defaults not supported
1001
1082
  delete formattedSchema.default;
1002
1083
  // Additional properties not supported, required to be set.
1003
- if (formattedSchema?.type === "object") {
1084
+ if (formattedSchema?.type === 'object') {
1004
1085
  formattedSchema.additionalProperties = false;
1005
1086
  }
1006
1087
  if (formattedSchema?.properties) {
@@ -1024,16 +1105,17 @@ function openAISchemaFormat(schema, nesting = 0) {
1024
1105
  }
1025
1106
  }
1026
1107
  }
1027
- 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)) {
1028
1110
  //If no properties are defined, then additionalProperties: true was set or the object would be empty.
1029
1111
  //OpenAI does not support this on structured output/ strict mode.
1030
- 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');
1031
1113
  }
1032
1114
  return formattedSchema;
1033
1115
  }
1034
1116
  function responseFinishReason(response, tools) {
1035
1117
  if (tools && tools.length > 0) {
1036
- return "tool_use";
1118
+ return 'tool_use';
1037
1119
  }
1038
1120
  if (response.status === 'incomplete') {
1039
1121
  if (response.incomplete_details?.reason === 'max_output_tokens') {
@@ -1108,6 +1190,30 @@ export function fixOrphanedToolUse(items) {
1108
1190
  }
1109
1191
  return result;
1110
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
+ }
1111
1217
  function safeJsonParse(value) {
1112
1218
  if (typeof value !== 'string') {
1113
1219
  return value;