@llumiverse/drivers 0.20.0 → 0.22.0-dev.1

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 (293) hide show
  1. package/lib/cjs/adobe/firefly.js +6 -5
  2. package/lib/cjs/adobe/firefly.js.map +1 -1
  3. package/lib/cjs/azure/azure_foundry.js +388 -0
  4. package/lib/cjs/azure/azure_foundry.js.map +1 -0
  5. package/lib/cjs/bedrock/index.js +62 -39
  6. package/lib/cjs/bedrock/index.js.map +1 -1
  7. package/lib/cjs/groq/index.js +178 -22
  8. package/lib/cjs/groq/index.js.map +1 -1
  9. package/lib/cjs/huggingface_ie.js +5 -4
  10. package/lib/cjs/huggingface_ie.js.map +1 -1
  11. package/lib/cjs/index.js +3 -2
  12. package/lib/cjs/index.js.map +1 -1
  13. package/lib/cjs/mistral/index.js +5 -3
  14. package/lib/cjs/mistral/index.js.map +1 -1
  15. package/lib/cjs/openai/azure_openai.js +72 -0
  16. package/lib/cjs/openai/azure_openai.js.map +1 -0
  17. package/lib/cjs/openai/index.js +13 -16
  18. package/lib/cjs/openai/index.js.map +1 -1
  19. package/lib/cjs/openai/openai.js +2 -2
  20. package/lib/cjs/openai/openai.js.map +1 -1
  21. package/lib/cjs/openai/openai_format.js +138 -0
  22. package/lib/cjs/openai/openai_format.js.map +1 -0
  23. package/lib/cjs/replicate.js +3 -3
  24. package/lib/cjs/replicate.js.map +1 -1
  25. package/lib/cjs/test/utils.js +1 -1
  26. package/lib/cjs/test/utils.js.map +1 -1
  27. package/lib/cjs/test-driver/TestErrorCompletionStream.js +20 -0
  28. package/lib/cjs/test-driver/TestErrorCompletionStream.js.map +1 -0
  29. package/lib/cjs/test-driver/TestValidationErrorCompletionStream.js +24 -0
  30. package/lib/cjs/test-driver/TestValidationErrorCompletionStream.js.map +1 -0
  31. package/lib/cjs/test-driver/index.js +109 -0
  32. package/lib/cjs/test-driver/index.js.map +1 -0
  33. package/lib/cjs/test-driver/utils.js +30 -0
  34. package/lib/cjs/test-driver/utils.js.map +1 -0
  35. package/lib/cjs/togetherai/index.js +2 -2
  36. package/lib/cjs/togetherai/index.js.map +1 -1
  37. package/lib/cjs/vertexai/embeddings/embeddings-text.js +1 -1
  38. package/lib/cjs/vertexai/embeddings/embeddings-text.js.map +1 -1
  39. package/lib/cjs/vertexai/index.js +90 -28
  40. package/lib/cjs/vertexai/index.js.map +1 -1
  41. package/lib/cjs/vertexai/models/claude.js +14 -12
  42. package/lib/cjs/vertexai/models/claude.js.map +1 -1
  43. package/lib/cjs/vertexai/models/gemini.js +158 -52
  44. package/lib/cjs/vertexai/models/gemini.js.map +1 -1
  45. package/lib/cjs/vertexai/models/imagen.js +11 -22
  46. package/lib/cjs/vertexai/models/imagen.js.map +1 -1
  47. package/lib/cjs/vertexai/models/llama.js +4 -3
  48. package/lib/cjs/vertexai/models/llama.js.map +1 -1
  49. package/lib/cjs/watsonx/index.js +3 -3
  50. package/lib/cjs/watsonx/index.js.map +1 -1
  51. package/lib/cjs/xai/index.js +4 -4
  52. package/lib/cjs/xai/index.js.map +1 -1
  53. package/lib/esm/adobe/firefly.js +6 -5
  54. package/lib/esm/adobe/firefly.js.map +1 -1
  55. package/lib/esm/azure/azure_foundry.js +382 -0
  56. package/lib/esm/azure/azure_foundry.js.map +1 -0
  57. package/lib/esm/bedrock/index.js +62 -39
  58. package/lib/esm/bedrock/index.js.map +1 -1
  59. package/lib/esm/groq/index.js +178 -22
  60. package/lib/esm/groq/index.js.map +1 -1
  61. package/lib/esm/huggingface_ie.js +6 -5
  62. package/lib/esm/huggingface_ie.js.map +1 -1
  63. package/lib/esm/index.js +3 -2
  64. package/lib/esm/index.js.map +1 -1
  65. package/lib/esm/mistral/index.js +5 -3
  66. package/lib/esm/mistral/index.js.map +1 -1
  67. package/lib/esm/openai/azure_openai.js +68 -0
  68. package/lib/esm/openai/azure_openai.js.map +1 -0
  69. package/lib/esm/openai/index.js +12 -15
  70. package/lib/esm/openai/index.js.map +1 -1
  71. package/lib/esm/openai/openai.js +2 -2
  72. package/lib/esm/openai/openai.js.map +1 -1
  73. package/lib/esm/openai/openai_format.js +134 -0
  74. package/lib/esm/openai/openai_format.js.map +1 -0
  75. package/lib/esm/replicate.js +3 -3
  76. package/lib/esm/replicate.js.map +1 -1
  77. package/lib/esm/src/adobe/firefly.js +116 -0
  78. package/lib/esm/src/adobe/firefly.js.map +1 -0
  79. package/lib/esm/src/azure/azure_foundry.js +382 -0
  80. package/lib/esm/src/azure/azure_foundry.js.map +1 -0
  81. package/lib/esm/src/bedrock/converse.js +278 -0
  82. package/lib/esm/src/bedrock/converse.js.map +1 -0
  83. package/lib/esm/src/bedrock/index.js +819 -0
  84. package/lib/esm/src/bedrock/index.js.map +1 -0
  85. package/lib/esm/src/bedrock/nova-image-payload.js +203 -0
  86. package/lib/esm/src/bedrock/nova-image-payload.js.map +1 -0
  87. package/lib/esm/src/bedrock/payloads.js +2 -0
  88. package/lib/esm/src/bedrock/payloads.js.map +1 -0
  89. package/lib/esm/src/bedrock/s3.js +99 -0
  90. package/lib/esm/src/bedrock/s3.js.map +1 -0
  91. package/lib/esm/src/groq/index.js +286 -0
  92. package/lib/esm/src/groq/index.js.map +1 -0
  93. package/lib/esm/src/huggingface_ie.js +196 -0
  94. package/lib/esm/src/huggingface_ie.js.map +1 -0
  95. package/lib/esm/src/index.js +14 -0
  96. package/lib/esm/src/index.js.map +1 -0
  97. package/lib/esm/src/mistral/index.js +169 -0
  98. package/lib/esm/src/mistral/index.js.map +1 -0
  99. package/lib/esm/src/mistral/types.js +80 -0
  100. package/lib/esm/src/mistral/types.js.map +1 -0
  101. package/lib/esm/src/openai/azure_openai.js +68 -0
  102. package/lib/esm/src/openai/azure_openai.js.map +1 -0
  103. package/lib/esm/src/openai/index.js +460 -0
  104. package/lib/esm/src/openai/index.js.map +1 -0
  105. package/lib/esm/src/openai/openai.js +14 -0
  106. package/lib/esm/src/openai/openai.js.map +1 -0
  107. package/lib/esm/src/openai/openai_format.js +134 -0
  108. package/lib/esm/src/openai/openai_format.js.map +1 -0
  109. package/lib/esm/src/replicate.js +268 -0
  110. package/lib/esm/src/replicate.js.map +1 -0
  111. package/lib/esm/src/test/TestErrorCompletionStream.js +16 -0
  112. package/lib/esm/src/test/TestErrorCompletionStream.js.map +1 -0
  113. package/lib/esm/src/test/TestValidationErrorCompletionStream.js +20 -0
  114. package/lib/esm/src/test/TestValidationErrorCompletionStream.js.map +1 -0
  115. package/lib/esm/src/test/index.js +91 -0
  116. package/lib/esm/src/test/index.js.map +1 -0
  117. package/lib/esm/src/test/utils.js +25 -0
  118. package/lib/esm/src/test/utils.js.map +1 -0
  119. package/lib/esm/src/togetherai/index.js +122 -0
  120. package/lib/esm/src/togetherai/index.js.map +1 -0
  121. package/lib/esm/src/togetherai/interfaces.js +2 -0
  122. package/lib/esm/src/togetherai/interfaces.js.map +1 -0
  123. package/lib/esm/src/vertexai/debug.js +6 -0
  124. package/lib/esm/src/vertexai/debug.js.map +1 -0
  125. package/lib/esm/src/vertexai/embeddings/embeddings-image.js +24 -0
  126. package/lib/esm/src/vertexai/embeddings/embeddings-image.js.map +1 -0
  127. package/lib/esm/src/vertexai/embeddings/embeddings-text.js +20 -0
  128. package/lib/esm/src/vertexai/embeddings/embeddings-text.js.map +1 -0
  129. package/lib/esm/src/vertexai/index.js +332 -0
  130. package/lib/esm/src/vertexai/index.js.map +1 -0
  131. package/lib/esm/src/vertexai/models/claude.js +372 -0
  132. package/lib/esm/src/vertexai/models/claude.js.map +1 -0
  133. package/lib/esm/src/vertexai/models/gemini.js +806 -0
  134. package/lib/esm/src/vertexai/models/gemini.js.map +1 -0
  135. package/lib/esm/src/vertexai/models/imagen.js +302 -0
  136. package/lib/esm/src/vertexai/models/imagen.js.map +1 -0
  137. package/lib/esm/src/vertexai/models/llama.js +179 -0
  138. package/lib/esm/src/vertexai/models/llama.js.map +1 -0
  139. package/lib/esm/src/vertexai/models.js +21 -0
  140. package/lib/esm/src/vertexai/models.js.map +1 -0
  141. package/lib/esm/src/watsonx/index.js +157 -0
  142. package/lib/esm/src/watsonx/index.js.map +1 -0
  143. package/lib/esm/src/watsonx/interfaces.js +2 -0
  144. package/lib/esm/src/watsonx/interfaces.js.map +1 -0
  145. package/lib/esm/src/xai/index.js +64 -0
  146. package/lib/esm/src/xai/index.js.map +1 -0
  147. package/lib/esm/test/utils.js +1 -1
  148. package/lib/esm/test/utils.js.map +1 -1
  149. package/lib/esm/test-driver/TestErrorCompletionStream.js +16 -0
  150. package/lib/esm/test-driver/TestErrorCompletionStream.js.map +1 -0
  151. package/lib/esm/test-driver/TestValidationErrorCompletionStream.js +20 -0
  152. package/lib/esm/test-driver/TestValidationErrorCompletionStream.js.map +1 -0
  153. package/lib/esm/test-driver/index.js +91 -0
  154. package/lib/esm/test-driver/index.js.map +1 -0
  155. package/lib/esm/test-driver/utils.js +25 -0
  156. package/lib/esm/test-driver/utils.js.map +1 -0
  157. package/lib/esm/togetherai/index.js +2 -2
  158. package/lib/esm/togetherai/index.js.map +1 -1
  159. package/lib/esm/tsconfig.tsbuildinfo +1 -0
  160. package/lib/esm/vertexai/embeddings/embeddings-text.js +1 -1
  161. package/lib/esm/vertexai/embeddings/embeddings-text.js.map +1 -1
  162. package/lib/esm/vertexai/index.js +91 -29
  163. package/lib/esm/vertexai/index.js.map +1 -1
  164. package/lib/esm/vertexai/models/claude.js +14 -12
  165. package/lib/esm/vertexai/models/claude.js.map +1 -1
  166. package/lib/esm/vertexai/models/gemini.js +159 -53
  167. package/lib/esm/vertexai/models/gemini.js.map +1 -1
  168. package/lib/esm/vertexai/models/imagen.js +8 -16
  169. package/lib/esm/vertexai/models/imagen.js.map +1 -1
  170. package/lib/esm/vertexai/models/llama.js +4 -3
  171. package/lib/esm/vertexai/models/llama.js.map +1 -1
  172. package/lib/esm/vertexai/models.js.map +1 -1
  173. package/lib/esm/watsonx/index.js +3 -3
  174. package/lib/esm/watsonx/index.js.map +1 -1
  175. package/lib/esm/xai/index.js +3 -3
  176. package/lib/esm/xai/index.js.map +1 -1
  177. package/lib/types/adobe/firefly.d.ts +3 -3
  178. package/lib/types/adobe/firefly.d.ts.map +1 -1
  179. package/lib/types/azure/azure_foundry.d.ts +50 -0
  180. package/lib/types/azure/azure_foundry.d.ts.map +1 -0
  181. package/lib/types/bedrock/index.d.ts +4 -4
  182. package/lib/types/bedrock/index.d.ts.map +1 -1
  183. package/lib/types/groq/index.d.ts +8 -5
  184. package/lib/types/groq/index.d.ts.map +1 -1
  185. package/lib/types/huggingface_ie.d.ts +8 -5
  186. package/lib/types/huggingface_ie.d.ts.map +1 -1
  187. package/lib/types/index.d.ts +3 -2
  188. package/lib/types/index.d.ts.map +1 -1
  189. package/lib/types/mistral/index.d.ts +4 -4
  190. package/lib/types/mistral/index.d.ts.map +1 -1
  191. package/lib/types/openai/azure_openai.d.ts +25 -0
  192. package/lib/types/openai/azure_openai.d.ts.map +1 -0
  193. package/lib/types/openai/index.d.ts +6 -7
  194. package/lib/types/openai/index.d.ts.map +1 -1
  195. package/lib/types/openai/openai.d.ts +2 -2
  196. package/lib/types/openai/openai.d.ts.map +1 -1
  197. package/lib/types/openai/openai_format.d.ts +19 -0
  198. package/lib/types/openai/openai_format.d.ts.map +1 -0
  199. package/lib/types/replicate.d.ts +6 -3
  200. package/lib/types/replicate.d.ts.map +1 -1
  201. package/lib/types/src/adobe/firefly.d.ts +29 -0
  202. package/lib/types/src/azure/azure_foundry.d.ts +49 -0
  203. package/lib/types/src/bedrock/converse.d.ts +8 -0
  204. package/lib/types/src/bedrock/index.d.ts +57 -0
  205. package/lib/types/src/bedrock/nova-image-payload.d.ts +73 -0
  206. package/lib/types/src/bedrock/payloads.d.ts +11 -0
  207. package/lib/types/src/bedrock/s3.d.ts +22 -0
  208. package/lib/types/src/groq/index.d.ts +26 -0
  209. package/lib/types/src/huggingface_ie.d.ts +34 -0
  210. package/lib/types/src/index.d.ts +13 -0
  211. package/lib/types/src/mistral/index.d.ts +24 -0
  212. package/lib/types/src/mistral/types.d.ts +131 -0
  213. package/lib/types/src/openai/azure_openai.d.ts +24 -0
  214. package/lib/types/src/openai/index.d.ts +24 -0
  215. package/lib/types/src/openai/openai.d.ts +14 -0
  216. package/lib/types/src/openai/openai_format.d.ts +18 -0
  217. package/lib/types/src/replicate.d.ts +47 -0
  218. package/lib/types/src/test/TestErrorCompletionStream.d.ts +8 -0
  219. package/lib/types/src/test/TestValidationErrorCompletionStream.d.ts +8 -0
  220. package/lib/types/src/test/index.d.ts +23 -0
  221. package/lib/types/src/test/utils.d.ts +4 -0
  222. package/lib/types/src/togetherai/index.d.ts +22 -0
  223. package/lib/types/src/togetherai/interfaces.d.ts +95 -0
  224. package/lib/types/src/vertexai/debug.d.ts +1 -0
  225. package/lib/types/src/vertexai/embeddings/embeddings-image.d.ts +10 -0
  226. package/lib/types/src/vertexai/embeddings/embeddings-text.d.ts +9 -0
  227. package/lib/types/src/vertexai/index.d.ts +52 -0
  228. package/lib/types/src/vertexai/models/claude.d.ts +17 -0
  229. package/lib/types/src/vertexai/models/gemini.d.ts +17 -0
  230. package/lib/types/src/vertexai/models/imagen.d.ts +74 -0
  231. package/lib/types/src/vertexai/models/llama.d.ts +19 -0
  232. package/lib/types/src/vertexai/models.d.ts +14 -0
  233. package/lib/types/src/watsonx/index.d.ts +26 -0
  234. package/lib/types/src/watsonx/interfaces.d.ts +64 -0
  235. package/lib/types/src/xai/index.d.ts +18 -0
  236. package/lib/types/test-driver/TestErrorCompletionStream.d.ts +9 -0
  237. package/lib/types/test-driver/TestErrorCompletionStream.d.ts.map +1 -0
  238. package/lib/types/test-driver/TestValidationErrorCompletionStream.d.ts +9 -0
  239. package/lib/types/test-driver/TestValidationErrorCompletionStream.d.ts.map +1 -0
  240. package/lib/types/test-driver/index.d.ts +24 -0
  241. package/lib/types/test-driver/index.d.ts.map +1 -0
  242. package/lib/types/test-driver/utils.d.ts +5 -0
  243. package/lib/types/test-driver/utils.d.ts.map +1 -0
  244. package/lib/types/togetherai/index.d.ts +3 -3
  245. package/lib/types/togetherai/index.d.ts.map +1 -1
  246. package/lib/types/vertexai/index.d.ts +10 -7
  247. package/lib/types/vertexai/index.d.ts.map +1 -1
  248. package/lib/types/vertexai/models/claude.d.ts.map +1 -1
  249. package/lib/types/vertexai/models/gemini.d.ts +3 -2
  250. package/lib/types/vertexai/models/gemini.d.ts.map +1 -1
  251. package/lib/types/vertexai/models/imagen.d.ts +2 -2
  252. package/lib/types/vertexai/models/imagen.d.ts.map +1 -1
  253. package/lib/types/vertexai/models/llama.d.ts +2 -2
  254. package/lib/types/vertexai/models/llama.d.ts.map +1 -1
  255. package/lib/types/vertexai/models.d.ts +2 -2
  256. package/lib/types/vertexai/models.d.ts.map +1 -1
  257. package/lib/types/watsonx/index.d.ts +3 -3
  258. package/lib/types/watsonx/index.d.ts.map +1 -1
  259. package/lib/types/xai/index.d.ts.map +1 -1
  260. package/package.json +29 -25
  261. package/src/adobe/firefly.ts +12 -20
  262. package/src/azure/azure_foundry.ts +458 -0
  263. package/src/bedrock/index.ts +65 -43
  264. package/src/groq/index.ts +219 -32
  265. package/src/huggingface_ie.ts +13 -14
  266. package/src/index.ts +3 -2
  267. package/src/mistral/index.ts +11 -9
  268. package/src/openai/azure_openai.ts +92 -0
  269. package/src/openai/index.ts +27 -28
  270. package/src/openai/openai.ts +2 -5
  271. package/src/openai/openai_format.ts +165 -0
  272. package/src/replicate.ts +12 -12
  273. package/src/{test → test-driver}/utils.ts +1 -1
  274. package/src/togetherai/index.ts +7 -7
  275. package/src/vertexai/embeddings/embeddings-text.ts +2 -2
  276. package/src/vertexai/index.ts +104 -38
  277. package/src/vertexai/models/claude.ts +18 -16
  278. package/src/vertexai/models/gemini.ts +195 -67
  279. package/src/vertexai/models/imagen.ts +15 -26
  280. package/src/vertexai/models/llama.ts +6 -5
  281. package/src/vertexai/models.ts +4 -4
  282. package/src/watsonx/index.ts +10 -10
  283. package/src/xai/index.ts +13 -15
  284. package/lib/cjs/openai/azure.js +0 -31
  285. package/lib/cjs/openai/azure.js.map +0 -1
  286. package/lib/esm/openai/azure.js +0 -27
  287. package/lib/esm/openai/azure.js.map +0 -1
  288. package/lib/types/openai/azure.d.ts +0 -20
  289. package/lib/types/openai/azure.d.ts.map +0 -1
  290. package/src/openai/azure.ts +0 -54
  291. /package/src/{test → test-driver}/TestErrorCompletionStream.ts +0 -0
  292. /package/src/{test → test-driver}/TestValidationErrorCompletionStream.ts +0 -0
  293. /package/src/{test → test-driver}/index.ts +0 -0
@@ -1,11 +1,13 @@
1
1
  import {
2
- Content, FinishReason, FunctionCallingConfigMode, FunctionDeclaration, GenerateContentParameters,
2
+ Content, FinishReason, FunctionCallingConfigMode, FunctionDeclaration, GenerateContentConfig, GenerateContentParameters,
3
+ GenerateContentResponseUsageMetadata,
3
4
  HarmBlockThreshold, HarmCategory, Part, SafetySetting, Schema, Tool, Type
4
5
  } from "@google/genai";
5
6
  import {
6
- AIModel, Completion, CompletionChunkObject, ExecutionOptions,
7
- ExecutionTokenUsage, JSONObject, JSONSchema, ModelType, PromptOptions, PromptRole,
8
- PromptSegment, readStreamAsBase64, ToolDefinition, ToolUse
7
+ AIModel, Completion, CompletionChunkObject, CompletionResult, ExecutionOptions,
8
+ ExecutionTokenUsage, getMaxTokensLimitVertexAi, JSONObject, JSONSchema, ModelType, PromptOptions, PromptRole,
9
+ PromptSegment, readStreamAsBase64, StatelessExecutionOptions, ToolDefinition, ToolUse,
10
+ VertexAIGeminiOptions
9
11
  } from "@llumiverse/core";
10
12
  import { asyncMap } from "@llumiverse/core/async";
11
13
  import { VertexAIDriver, GenerateContentPrompt } from "../index.js";
@@ -44,42 +46,52 @@ const geminiSafetySettings: SafetySetting[] = [
44
46
  ];
45
47
 
46
48
  function getGeminiPayload(options: ExecutionOptions, prompt: GenerateContentPrompt): GenerateContentParameters {
47
- const model_options = options.model_options as any;
49
+ const model_options = options.model_options as VertexAIGeminiOptions | undefined;
48
50
  const tools = getToolDefinitions(options.tools);
49
51
 
50
52
  const useStructuredOutput = supportsStructuredOutput(options) && !tools;
51
53
 
54
+ const thinkingConfigNeeded = model_options?.include_thoughts
55
+ || model_options?.thinking_budget_tokens
56
+ || options.model.includes("gemini-2.5");
57
+
58
+ const configNanoBanana: GenerateContentConfig = {
59
+ responseModalities: ["TEXT", "IMAGE"]
60
+ }
61
+
62
+ const config: GenerateContentConfig = {
63
+ systemInstruction: prompt.system,
64
+ safetySettings: geminiSafetySettings,
65
+ tools: tools ? [tools] : undefined,
66
+ toolConfig: tools ? {
67
+ functionCallingConfig: {
68
+ mode: FunctionCallingConfigMode.AUTO,
69
+ }
70
+ } : undefined,
71
+ candidateCount: 1,
72
+ //JSON/Structured output
73
+ responseMimeType: useStructuredOutput ? "application/json" : undefined,
74
+ responseSchema: useStructuredOutput ? parseJSONtoSchema(options.result_schema, true) : undefined,
75
+ //Model options
76
+ temperature: model_options?.temperature,
77
+ topP: model_options?.top_p,
78
+ topK: model_options?.top_k,
79
+ maxOutputTokens: geminiMaxTokens(options),
80
+ stopSequences: model_options?.stop_sequence,
81
+ presencePenalty: model_options?.presence_penalty,
82
+ frequencyPenalty: model_options?.frequency_penalty,
83
+ seed: model_options?.seed,
84
+ thinkingConfig: thinkingConfigNeeded ?
85
+ {
86
+ includeThoughts: model_options?.include_thoughts ?? false,
87
+ thinkingBudget: geminiThinkingBudget(options),
88
+ } : undefined,
89
+ }
90
+
52
91
  return {
53
92
  model: options.model,
54
93
  contents: prompt.contents,
55
- config: {
56
- systemInstruction: prompt.system,
57
- safetySettings: geminiSafetySettings,
58
- tools: tools ? [tools] : undefined,
59
- toolConfig: tools ? {
60
- functionCallingConfig: {
61
- mode: FunctionCallingConfigMode.AUTO,
62
- }
63
- } : undefined,
64
- candidateCount: 1,
65
- //JSON/Structured output
66
- responseMimeType: useStructuredOutput ? "application/json" : undefined,
67
- responseSchema: useStructuredOutput ? parseJSONtoSchema(options.result_schema, true) : undefined,
68
- //Model options
69
- temperature: model_options?.temperature,
70
- topP: model_options?.top_p,
71
- topK: model_options?.top_k,
72
- maxOutputTokens: model_options?.max_tokens,
73
- stopSequences: model_options?.stop_sequence,
74
- presencePenalty: model_options?.presence_penalty,
75
- frequencyPenalty: model_options?.frequency_penalty,
76
- seed: model_options?.seed,
77
- thinkingConfig: model_options?.include_thoughts || model_options?.thinking_budget_tokens ?
78
- {
79
- includeThoughts: model_options?.include_thoughts,
80
- thinkingBudget: model_options?.thinking_budget_tokens,
81
- } : undefined,
82
- }
94
+ config: options.model.toLowerCase().includes("image") ? configNanoBanana : config,
83
95
  };
84
96
  }
85
97
 
@@ -335,7 +347,7 @@ function cleanEmptyFieldsContent(content: Content, result_schema?: JSONSchema):
335
347
  const jsonText = JSON.parse(part.text);
336
348
  // Skip cleaning if not an object
337
349
  if (typeof jsonText === 'object' && jsonText !== null && !Array.isArray(jsonText)) {
338
- const cleanedJson = removeEmptyFields(jsonText, result_schema);
350
+ const cleanedJson = removeEmptyFields(jsonText, result_schema);
339
351
  newPart.text = JSON.stringify(cleanedJson);
340
352
  } else {
341
353
  // Keep original if not an object (string, number, array, etc.)
@@ -370,14 +382,14 @@ function removeEmptyFields(object: JSONObject | any[], schema: JSONSchema): JSON
370
382
  if (typeof object == 'object' || object === null) {
371
383
  return removeEmptyJSONObject(object, schema);
372
384
  }
373
-
385
+
374
386
  return object;
375
387
  }
376
388
 
377
389
  function removeEmptyJSONObject(object: JSONObject, schema: JSONSchema): JSONObject {
378
390
  // Get the original required properties from schema
379
391
  const requiredProps = schema.required || [];
380
- const cleanedResult: JSONObject = {...object};
392
+ const cleanedResult: JSONObject = { ...object };
381
393
 
382
394
  // Process each property
383
395
  for (const [key, value] of Object.entries(object)) {
@@ -401,24 +413,46 @@ function removeEmptyJSONObject(object: JSONObject, schema: JSONSchema): JSONObje
401
413
 
402
414
  function removeEmptyJSONArray(array: any[], schema: JSONSchema): any[] {
403
415
  const cleanedArray = array.map(item => {
404
- return removeEmptyFields(item, schema);
416
+ return removeEmptyFields(item, schema);
405
417
  });
406
418
 
407
419
  // Filter out empty objects from the array
408
420
  return cleanedArray.filter(item => !isEmpty(item));
409
421
  }
410
422
 
411
- function collectTextParts(content: Content) {
412
- const out = [];
423
+ function collectTextParts(content: Content): CompletionResult[] {
424
+ const results: CompletionResult[] = [];
413
425
  const parts = content.parts;
414
426
  if (parts) {
415
427
  for (const part of parts) {
416
428
  if (part.text) {
417
- out.push(part.text);
429
+ results.push({
430
+ type: "text",
431
+ value: part.text
432
+ });
418
433
  }
419
434
  }
420
435
  }
421
- return out.join('\n');
436
+ return results;
437
+ }
438
+
439
+ function collectInlineDataParts(content: Content): CompletionResult[] {
440
+ const results: CompletionResult[] = [];
441
+ const parts = content.parts;
442
+ if (parts) {
443
+ for (const part of parts) {
444
+ if (part.inlineData) {
445
+ const base64ImageBytes: string = part.inlineData.data ?? "";
446
+ const mimeType = part.inlineData.mimeType ?? "image/png";
447
+ const imageUrl = `data:${mimeType};base64,${base64ImageBytes}`;
448
+ results.push({
449
+ type: "image",
450
+ value: imageUrl
451
+ });
452
+ }
453
+ }
454
+ }
455
+ return results;
422
456
  }
423
457
 
424
458
  function collectToolUseParts(content: Content): ToolUse[] | undefined {
@@ -439,7 +473,7 @@ function collectToolUseParts(content: Content): ToolUse[] | undefined {
439
473
  export function mergeConsecutiveRole(contents: Content[] | undefined): Content[] {
440
474
  if (!contents || contents.length === 0) return [];
441
475
 
442
- const needsMerging = contents.some((content, i) =>
476
+ const needsMerging = contents.some((content, i) =>
443
477
  i < contents.length - 1 && content.role === contents[i + 1].role
444
478
  );
445
479
  // If no merging needed, return original array
@@ -465,6 +499,41 @@ export function mergeConsecutiveRole(contents: Content[] | undefined): Content[]
465
499
  return result;
466
500
  }
467
501
 
502
+ const supportedFinishReasons: FinishReason[] = [
503
+ FinishReason.MAX_TOKENS,
504
+ FinishReason.STOP,
505
+ FinishReason.FINISH_REASON_UNSPECIFIED
506
+ ]
507
+
508
+ function geminiMaxTokens(option: StatelessExecutionOptions) {
509
+ const model_options = option.model_options as VertexAIGeminiOptions | undefined;
510
+ if (model_options?.max_tokens) {
511
+ return model_options.max_tokens;
512
+ }
513
+ if (option.model.includes("gemini-2.5")) {
514
+ const maxSupportedTokens = getMaxTokensLimitVertexAi(option.model);
515
+ const thinkingBudget = geminiThinkingBudget(option) ?? 0;
516
+ return Math.min(maxSupportedTokens, 16000 + thinkingBudget);
517
+ }
518
+ return undefined;
519
+ }
520
+
521
+ function geminiThinkingBudget(option: StatelessExecutionOptions) {
522
+ const model_options = option.model_options as VertexAIGeminiOptions | undefined;
523
+ if (model_options?.thinking_budget_tokens) {
524
+ return model_options.thinking_budget_tokens;
525
+ }
526
+ // Set minimum thinking level by default.
527
+ // Docs: https://ai.google.dev/gemini-api/docs/thinking#set-budget
528
+ if (option.model.includes("gemini-2.5")) {
529
+ if (option.model.includes("pro")) {
530
+ return 128;
531
+ }
532
+ return 0;
533
+ }
534
+ return undefined;
535
+ }
536
+
468
537
  export class GeminiModelDefinition implements ModelDefinition<GenerateContentPrompt> {
469
538
 
470
539
  model: AIModel
@@ -485,8 +554,16 @@ export class GeminiModelDefinition implements ModelDefinition<GenerateContentPro
485
554
  return { result, options };
486
555
  }
487
556
  try {
488
- const jsonResult = JSON.parse(result.result);
489
- result.result = JSON.stringify(removeEmptyFields(jsonResult, options.result_schema));
557
+ // Extract text content for JSON processing - only process first text result
558
+ const textResult = result.result.find(r => r.type === 'text')?.value;
559
+ if (textResult) {
560
+ const jsonResult = JSON.parse(textResult);
561
+ const cleanedJson = JSON.stringify(removeEmptyFields(jsonResult, options.result_schema));
562
+ // Replace the text result with cleaned version
563
+ result.result = result.result.map(r =>
564
+ r.type === 'text' ? { ...r, value: cleanedJson } : r
565
+ );
566
+ }
490
567
  return { result, options };
491
568
  } catch (error) {
492
569
  // Log error during processing but don't fail the completion
@@ -504,7 +581,7 @@ export class GeminiModelDefinition implements ModelDefinition<GenerateContentPro
504
581
  const schema = options.result_schema;
505
582
  let contents: Content[] = [];
506
583
  let system: Content | undefined = { role: "user", parts: [] }; // Single content block for system messages
507
-
584
+
508
585
  const safety: Content[] = [];
509
586
 
510
587
  for (const msg of segments) {
@@ -517,7 +594,7 @@ export class GeminiModelDefinition implements ModelDefinition<GenerateContentPro
517
594
 
518
595
  if (msg.content) {
519
596
  system.parts?.push({
520
- text: msg.content
597
+ text: msg.content
521
598
  });
522
599
  }
523
600
  } else if (msg.role === PromptRole.tool) {
@@ -591,7 +668,7 @@ export class GeminiModelDefinition implements ModelDefinition<GenerateContentPro
591
668
  }
592
669
  }
593
670
  }
594
-
671
+
595
672
  // If no system messages, set system to undefined.
596
673
  if (!system.parts || system.parts.length === 0) {
597
674
  system = undefined;
@@ -604,29 +681,58 @@ export class GeminiModelDefinition implements ModelDefinition<GenerateContentPro
604
681
 
605
682
  // Merge consecutive messages with the same role. Note: this may not be necessary, works without it, keeping to match previous behavior.
606
683
  contents = mergeConsecutiveRole(contents);
607
-
684
+
608
685
  return { contents, system };
609
686
  }
610
687
 
688
+ usageMetadataToTokenUsage(usageMetadata: GenerateContentResponseUsageMetadata | undefined): ExecutionTokenUsage {
689
+ if (!usageMetadata || !usageMetadata.totalTokenCount) {
690
+ return {};
691
+ }
692
+ const tokenUsage: ExecutionTokenUsage = { total: usageMetadata.totalTokenCount, prompt: usageMetadata.promptTokenCount };
693
+
694
+ //Output/Response side
695
+ tokenUsage.result = (usageMetadata.candidatesTokenCount ?? 0)
696
+ + (usageMetadata.thoughtsTokenCount ?? 0)
697
+ + (usageMetadata.toolUsePromptTokenCount ?? 0);
698
+
699
+ if ((tokenUsage.total ?? 0) != (tokenUsage.prompt ?? 0) + tokenUsage.result) {
700
+ console.warn("[VertexAI] Gemini token usage mismatch: total does not equal prompt + result", {
701
+ total: tokenUsage.total,
702
+ prompt: tokenUsage.prompt,
703
+ result: tokenUsage.result
704
+ });
705
+ }
706
+
707
+ if (!tokenUsage.result) {
708
+ tokenUsage.result = undefined; // If no result, mark as undefined
709
+ }
710
+
711
+ return tokenUsage;
712
+ }
713
+
611
714
  async requestTextCompletion(driver: VertexAIDriver, prompt: GenerateContentPrompt, options: ExecutionOptions): Promise<Completion> {
612
715
  const splits = options.model.split("/");
716
+ let region: string | undefined = undefined;
717
+ if (splits[0] === "locations" && splits.length >= 2) {
718
+ region = splits[1];
719
+ }
613
720
  const modelName = splits[splits.length - 1];
614
721
  options = { ...options, model: modelName };
615
722
 
616
723
  let conversation = updateConversation(options.conversation as Content[], prompt.contents);
617
724
  prompt.contents = conversation;
618
725
 
619
- const client = driver.getGoogleGenAIClient();
726
+ if (options.model.includes("gemini-2.5-flash-image")) {
727
+ region = "global"; // Gemini Flash Image only available in global region, this is for nano-banana model
728
+ }
729
+
730
+ const client = driver.getGoogleGenAIClient(region);
620
731
 
621
732
  const payload = getGeminiPayload(options, prompt);
622
733
  const response = await client.models.generateContent(payload);
623
734
 
624
- const usage = response.usageMetadata;
625
- const token_usage: ExecutionTokenUsage = {
626
- prompt: usage?.promptTokenCount,
627
- result: usage?.candidatesTokenCount,
628
- total: usage?.totalTokenCount,
629
- }
735
+ const token_usage: ExecutionTokenUsage = this.usageMetadataToTokenUsage(response.usageMetadata);
630
736
 
631
737
  let tool_use: ToolUse[] | undefined;
632
738
  let finish_reason: string | undefined, result: any;
@@ -638,22 +744,33 @@ export class GeminiModelDefinition implements ModelDefinition<GenerateContentPro
638
744
  default: finish_reason = candidate.finishReason;
639
745
  }
640
746
  const content = candidate.content;
747
+
748
+ if (candidate.finishReason && !supportedFinishReasons.includes(candidate.finishReason)) {
749
+ throw new Error(`Unsupported finish reason: ${candidate.finishReason}, `
750
+ + `finish message: ${candidate.finishMessage}, `
751
+ + `content: ${JSON.stringify(content, null, 2)}, safety: ${JSON.stringify(candidate.safetyRatings, null, 2)}`);
752
+ }
753
+
641
754
  if (content) {
642
755
  tool_use = collectToolUseParts(content);
643
756
 
644
757
  // We clean the content before validation, so we can update the conversation.
645
758
  const cleanedContent = cleanEmptyFieldsContent(content, options.result_schema);
646
- result = collectTextParts(cleanedContent);
759
+ const textResults = collectTextParts(cleanedContent);
760
+ const imageResults = collectInlineDataParts(cleanedContent);
761
+ result = [...textResults, ...imageResults];
647
762
  conversation = updateConversation(conversation, [cleanedContent]);
648
763
  }
649
764
  }
650
765
 
766
+
767
+
651
768
  if (tool_use) {
652
769
  finish_reason = "tool_use";
653
770
  }
654
771
 
655
772
  return {
656
- result: result ?? '',
773
+ result: result && result.length > 0 ? result : [{ type: "text" as const, value: '' }],
657
774
  token_usage: token_usage,
658
775
  finish_reason: finish_reason,
659
776
  original_response: options.include_original_response ? response : undefined,
@@ -664,21 +781,24 @@ export class GeminiModelDefinition implements ModelDefinition<GenerateContentPro
664
781
 
665
782
  async requestTextCompletionStream(driver: VertexAIDriver, prompt: GenerateContentPrompt, options: ExecutionOptions): Promise<AsyncIterable<CompletionChunkObject>> {
666
783
  const splits = options.model.split("/");
784
+ let region: string | undefined = undefined;
785
+ if (splits[0] === "locations" && splits.length >= 2) {
786
+ region = splits[1];
787
+ }
667
788
  const modelName = splits[splits.length - 1];
668
789
  options = { ...options, model: modelName };
669
790
 
670
- const client = driver.getGoogleGenAIClient();
791
+ if (options.model.includes("gemini-2.5-flash-image")) {
792
+ region = "global"; // Gemini Flash Image only available in global region, this is for nano-banana model
793
+ }
794
+
795
+ const client = driver.getGoogleGenAIClient(region);
671
796
 
672
797
  const payload = getGeminiPayload(options, prompt);
673
798
  const response = await client.models.generateContentStream(payload);
674
799
 
675
800
  const stream = asyncMap(response, async (item) => {
676
- const usage = item.usageMetadata;
677
- const token_usage: ExecutionTokenUsage = {
678
- prompt: usage?.promptTokenCount,
679
- result: usage?.candidatesTokenCount,
680
- total: usage?.totalTokenCount,
681
- }
801
+ const token_usage: ExecutionTokenUsage = this.usageMetadataToTokenUsage(item.usageMetadata);
682
802
  if (item.candidates && item.candidates.length > 0) {
683
803
  for (const candidate of item.candidates) {
684
804
  let tool_use: ToolUse[] | undefined;
@@ -688,14 +808,21 @@ export class GeminiModelDefinition implements ModelDefinition<GenerateContentPro
688
808
  case FinishReason.STOP: finish_reason = "stop"; break;
689
809
  default: finish_reason = candidate.finishReason;
690
810
  }
811
+ if (candidate.finishReason && !supportedFinishReasons.includes(candidate.finishReason)) {
812
+ throw new Error(`Unsupported finish reason: ${candidate.finishReason}, `
813
+ + `finish message: ${candidate.finishMessage}, `
814
+ + `content: ${JSON.stringify(candidate.content, null, 2)}, safety: ${JSON.stringify(candidate.safetyRatings, null, 2)}`);
815
+ }
691
816
  if (candidate.content?.role === 'model') {
692
- const text = collectTextParts(candidate.content);
817
+ const textResults = collectTextParts(candidate.content);
818
+ const imageResults = collectInlineDataParts(candidate.content);
819
+ const combinedResults = [...textResults, ...imageResults];
693
820
  tool_use = collectToolUseParts(candidate.content);
694
821
  if (tool_use) {
695
822
  finish_reason = "tool_use";
696
823
  }
697
824
  return {
698
- result: text,
825
+ result: combinedResults.length > 0 ? combinedResults : [],
699
826
  token_usage: token_usage,
700
827
  finish_reason: finish_reason,
701
828
  tool_use,
@@ -705,8 +832,9 @@ export class GeminiModelDefinition implements ModelDefinition<GenerateContentPro
705
832
  }
706
833
  //No normal output, returning block reason if it exists.
707
834
  return {
708
- result: item.promptFeedback?.blockReasonMessage ?? "",
835
+ result: item.promptFeedback?.blockReasonMessage ? [{ type: "text" as const, value: item.promptFeedback.blockReasonMessage }] : [],
709
836
  finish_reason: item.promptFeedback?.blockReason ?? "",
837
+ token_usage: token_usage,
710
838
  };
711
839
  });
712
840
 
@@ -1,19 +1,12 @@
1
1
  import {
2
- AIModel, Completion, ExecutionOptions, ImageGeneration, Modalities,
2
+ AIModel, Completion, ExecutionOptions, Modalities,
3
3
  ModelType, PromptRole, PromptSegment, readStreamAsBase64, ImagenOptions
4
4
  } from "@llumiverse/core";
5
5
  import { VertexAIDriver } from "../index.js";
6
6
 
7
- const projectId = process.env.GOOGLE_PROJECT_ID;
8
- const location = 'us-central1';
9
-
10
- import aiplatform, { protos } from '@google-cloud/aiplatform';
11
-
12
- // Imports the Google Cloud Prediction Service Client library
13
- const { PredictionServiceClient } = aiplatform.v1;
14
-
15
7
  // Import the helper module for converting arbitrary protobuf.Value objects
16
- import { helpers } from '@google-cloud/aiplatform';
8
+ import { protos, helpers } from '@google-cloud/aiplatform';
9
+
17
10
  interface ImagenBaseReference {
18
11
  referenceType: "REFERENCE_TYPE_RAW" | "REFERENCE_TYPE_MASK" | "REFERENCE_TYPE_SUBJECT" |
19
12
  "REFERENCE_TYPE_CONTROL" | "REFERENCE_TYPE_STYLE";
@@ -90,14 +83,6 @@ export interface ImagenPrompt {
90
83
  negativePrompt?: string; //Used for negative prompts
91
84
  }
92
85
 
93
- // Specifies the location of the api endpoint
94
- const clientOptions = {
95
- apiEndpoint: `${location}-aiplatform.googleapis.com`,
96
- };
97
-
98
- // Instantiates a client
99
- const predictionServiceClient = new PredictionServiceClient(clientOptions);
100
-
101
86
  function getImagenParameters(taskType: string, options: ImagenOptions) {
102
87
  const commonParameters = {
103
88
  sampleCount: options?.number_of_images,
@@ -337,9 +322,9 @@ export class ImagenModelDefinition {
337
322
  return prompt
338
323
  }
339
324
 
340
- async requestImageGeneration(driver: VertexAIDriver, prompt: ImagenPrompt, options: ExecutionOptions): Promise<Completion<ImageGeneration>> {
325
+ async requestImageGeneration(driver: VertexAIDriver, prompt: ImagenPrompt, options: ExecutionOptions): Promise<Completion> {
341
326
  if (options.model_options?._option_id !== "vertexai-imagen") {
342
- driver.logger.warn("Invalid model options", {options: options.model_options });
327
+ driver.logger.warn("Invalid model options", { options: options.model_options });
343
328
  }
344
329
  options.model_options = options.model_options as ImagenOptions | undefined;
345
330
 
@@ -351,10 +336,11 @@ export class ImagenModelDefinition {
351
336
 
352
337
  driver.logger.info("Task type: " + taskType);
353
338
 
354
- const modelName = options.model.split("/").pop() ?? '';
339
+ const modelName = options.model.split("/").pop() ?? '';
355
340
 
356
341
  // Configure the parent resource
357
- const endpoint = `projects/${projectId}/locations/${location}/publishers/google/models/${modelName}`;
342
+ // TODO: make location configurable, fixed to us-central1 for now
343
+ const endpoint = `projects/${driver.options.project}/locations/us-central1/publishers/google/models/${modelName}`;
358
344
 
359
345
  const instanceValue = helpers.toValue(prompt);
360
346
  if (!instanceValue) {
@@ -380,8 +366,10 @@ export class ImagenModelDefinition {
380
366
  parameters,
381
367
  };
382
368
 
369
+ const client = driver.getImagenClient();
370
+
383
371
  // Predict request
384
- const [response] = await predictionServiceClient.predict(request, { timeout: 120000 * numberOfImages }); //Extended timeout for image generation
372
+ const [response] = await client.predict(request, { timeout: 120000 * numberOfImages }); //Extended timeout for image generation
385
373
  const predictions = response.predictions;
386
374
 
387
375
  if (!predictions) {
@@ -394,9 +382,10 @@ export class ImagenModelDefinition {
394
382
  );
395
383
 
396
384
  return {
397
- result: {
398
- images
399
- },
385
+ result: images.map(image => ({
386
+ type: "image" as const,
387
+ value: image
388
+ })),
400
389
  };
401
390
  }
402
391
  }
@@ -1,5 +1,5 @@
1
1
  import {
2
- AIModel, Completion, CompletionChunk, CompletionChunkObject, ExecutionOptions, ModelType,
2
+ AIModel, Completion, CompletionChunkObject, ExecutionOptions, ModelType,
3
3
  PromptOptions, PromptRole, PromptSegment,
4
4
  TextFallbackOptions
5
5
  } from "@llumiverse/core";
@@ -195,7 +195,7 @@ export class LLamaModelDefinition implements ModelDefinition<LLamaPrompt> {
195
195
  });
196
196
 
197
197
  return {
198
- result: text,
198
+ result: [{ type: "text", value: text }],
199
199
  token_usage: {
200
200
  prompt: result.usage.prompt_tokens,
201
201
  result: result.usage.completion_tokens,
@@ -206,11 +206,11 @@ export class LLamaModelDefinition implements ModelDefinition<LLamaPrompt> {
206
206
  };
207
207
  }
208
208
 
209
- async requestTextCompletionStream(driver: VertexAIDriver, prompt: LLamaPrompt, options: ExecutionOptions): Promise<AsyncIterable<CompletionChunk>> {
209
+ async requestTextCompletionStream(driver: VertexAIDriver, prompt: LLamaPrompt, options: ExecutionOptions): Promise<AsyncIterable<CompletionChunkObject>> {
210
210
  const splits = options.model.split("/");
211
211
  const modelName = splits[splits.length - 1];
212
212
 
213
- let conversation = updateConversation(options.conversation as LLamaPrompt, prompt);
213
+ const conversation = updateConversation(options.conversation as LLamaPrompt, prompt);
214
214
 
215
215
  const modelOptions = options.model_options as TextFallbackOptions;
216
216
 
@@ -247,8 +247,9 @@ export class LLamaModelDefinition implements ModelDefinition<LLamaPrompt> {
247
247
  return transformSSEStream(stream, (data: string): CompletionChunkObject => {
248
248
  const json = JSON.parse(data) as LLamaStreamResponse;
249
249
  const choice = json.choices?.[0];
250
+ const content = choice?.delta?.content ?? '';
250
251
  return {
251
- result: choice?.delta?.content ?? '',
252
+ result: content ? [{ type: "text", value: content }] : [],
252
253
  finish_reason: choice?.finish_reason,
253
254
  token_usage: json.usage ? {
254
255
  prompt: json.usage.prompt_tokens,
@@ -1,5 +1,5 @@
1
- import { AIModel, Completion, PromptSegment, ExecutionOptions, CompletionChunk } from "@llumiverse/core";
2
- import { VertexAIDriver , trimModelName} from "./index.js";
1
+ import { AIModel, Completion, PromptSegment, ExecutionOptions, CompletionChunkObject } from "@llumiverse/core";
2
+ import { VertexAIDriver, trimModelName } from "./index.js";
3
3
  import { GeminiModelDefinition } from "./models/gemini.js";
4
4
  import { ClaudeModelDefinition } from "./models/claude.js";
5
5
  import { LLamaModelDefinition } from "./models/llama.js";
@@ -9,7 +9,7 @@ export interface ModelDefinition<PromptT = any> {
9
9
  versions?: string[]; // the versions of the model that are available. ex: ['001', '002']
10
10
  createPrompt: (driver: VertexAIDriver, segments: PromptSegment[], options: ExecutionOptions) => Promise<PromptT>;
11
11
  requestTextCompletion: (driver: VertexAIDriver, prompt: PromptT, options: ExecutionOptions) => Promise<Completion>;
12
- requestTextCompletionStream: (driver: VertexAIDriver, prompt: PromptT, options: ExecutionOptions) => Promise<AsyncIterable<CompletionChunk>>;
12
+ requestTextCompletionStream: (driver: VertexAIDriver, prompt: PromptT, options: ExecutionOptions) => Promise<AsyncIterable<CompletionChunkObject>>;
13
13
  preValidationProcessing?(result: Completion, options: ExecutionOptions): { result: Completion, options: ExecutionOptions };
14
14
  }
15
15
 
@@ -17,7 +17,7 @@ export function getModelDefinition(model: string): ModelDefinition {
17
17
  const splits = model.split("/");
18
18
  const publisher = splits[1];
19
19
  const modelName = trimModelName(splits[splits.length - 1]);
20
-
20
+
21
21
  if (publisher?.includes("anthropic")) {
22
22
  return new ClaudeModelDefinition(modelName);
23
23
  } else if (publisher?.includes("google")) {
@@ -1,4 +1,4 @@
1
- import { AIModel, AbstractDriver, Completion, CompletionChunk, DriverOptions, EmbeddingsOptions, EmbeddingsResult, ExecutionOptions, TextFallbackOptions } from "@llumiverse/core";
1
+ import { AIModel, AbstractDriver, Completion, CompletionChunkObject, DriverOptions, EmbeddingsOptions, EmbeddingsResult, ExecutionOptions, TextFallbackOptions } from "@llumiverse/core";
2
2
  import { transformSSEStream } from "@llumiverse/core/async";
3
3
  import { FetchClient } from "@vertesia/api-fetch-client";
4
4
  import { GenerateEmbeddingPayload, GenerateEmbeddingResponse, WatsonAuthToken, WatsonxListModelResponse, WatsonxModelSpec, WatsonxTextGenerationPayload, WatsonxTextGenerationResponse } from "./interfaces.js";
@@ -29,12 +29,12 @@ export class WatsonxDriver extends AbstractDriver<WatsonxDriverOptions, string>
29
29
  this.fetchClient = new FetchClient(this.endpoint_url).withAuthCallback(async () => this.getAuthToken().then(token => `Bearer ${token}`));
30
30
  }
31
31
 
32
- async requestTextCompletion(prompt: string, options: ExecutionOptions): Promise<Completion<any>> {
32
+ async requestTextCompletion(prompt: string, options: ExecutionOptions): Promise<Completion> {
33
33
  if (options.model_options?._option_id !== "text-fallback") {
34
- this.logger.warn("Invalid model options", {options: options.model_options });
34
+ this.logger.warn("Invalid model options", { options: options.model_options });
35
35
  }
36
36
  options.model_options = options.model_options as TextFallbackOptions | undefined;
37
-
37
+
38
38
  const payload: WatsonxTextGenerationPayload = {
39
39
  model_id: options.model,
40
40
  input: prompt + "\n",
@@ -53,7 +53,7 @@ export class WatsonxDriver extends AbstractDriver<WatsonxDriverOptions, string>
53
53
  const result = res.results[0];
54
54
 
55
55
  return {
56
- result: result.generated_text,
56
+ result: [{ type: "text", value: result.generated_text }],
57
57
  token_usage: {
58
58
  prompt: result.input_token_count,
59
59
  result: result.generated_token_count,
@@ -64,9 +64,9 @@ export class WatsonxDriver extends AbstractDriver<WatsonxDriverOptions, string>
64
64
  }
65
65
  }
66
66
 
67
- async requestTextCompletionStream(prompt: string, options: ExecutionOptions): Promise<AsyncIterable<CompletionChunk>> {
67
+ async requestTextCompletionStream(prompt: string, options: ExecutionOptions): Promise<AsyncIterable<CompletionChunkObject>> {
68
68
  if (options.model_options?._option_id !== "text-fallback") {
69
- this.logger.warn("Invalid model options", {options: options.model_options });
69
+ this.logger.warn("Invalid model options", { options: options.model_options });
70
70
  }
71
71
  options.model_options = options.model_options as TextFallbackOptions | undefined;
72
72
  const payload: WatsonxTextGenerationPayload = {
@@ -90,7 +90,7 @@ export class WatsonxDriver extends AbstractDriver<WatsonxDriverOptions, string>
90
90
  return transformSSEStream(stream, (data: string) => {
91
91
  const json = JSON.parse(data) as WatsonxTextGenerationResponse;
92
92
  return {
93
- result: json.results[0]?.generated_text ?? '',
93
+ result: json.results[0]?.generated_text ? [{ type: "text", value: json.results[0].generated_text }] : [],
94
94
  finish_reason: watsonFinishReason(json.results[0]?.stop_reason),
95
95
  token_usage: {
96
96
  prompt: json.results[0].input_token_count,
@@ -132,7 +132,7 @@ export class WatsonxDriver extends AbstractDriver<WatsonxDriverOptions, string>
132
132
  if (now < this.authToken.expiration) {
133
133
  return this.authToken.access_token;
134
134
  } else {
135
- this.logger.debug("Token expired, refetching", this.authToken, now)
135
+ this.logger.debug("Token expired, refetching")
136
136
  }
137
137
  }
138
138
  const authToken = await fetch('https://iam.cloud.ibm.com/identity/token', {
@@ -163,7 +163,7 @@ export class WatsonxDriver extends AbstractDriver<WatsonxDriverOptions, string>
163
163
  }
164
164
 
165
165
  if (!options.text) {
166
- throw new Error ("No text provided");
166
+ throw new Error("No text provided");
167
167
  }
168
168
 
169
169
  const payload: GenerateEmbeddingPayload = {