@llumiverse/common 1.0.0-dev.20260224.234313Z → 1.0.0-dev.20260331.080752Z

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 (41) hide show
  1. package/lib/cjs/capability/openai.js +4 -1
  2. package/lib/cjs/capability/openai.js.map +1 -1
  3. package/lib/cjs/capability.js +28 -1
  4. package/lib/cjs/capability.js.map +1 -1
  5. package/lib/cjs/options/context-windows.js +2 -1
  6. package/lib/cjs/options/context-windows.js.map +1 -1
  7. package/lib/cjs/options/openai.js +101 -0
  8. package/lib/cjs/options/openai.js.map +1 -1
  9. package/lib/cjs/options/vertexai.js +219 -65
  10. package/lib/cjs/options/vertexai.js.map +1 -1
  11. package/lib/cjs/types.js +104 -1
  12. package/lib/cjs/types.js.map +1 -1
  13. package/lib/esm/capability/openai.js +4 -1
  14. package/lib/esm/capability/openai.js.map +1 -1
  15. package/lib/esm/capability.js +28 -1
  16. package/lib/esm/capability.js.map +1 -1
  17. package/lib/esm/options/context-windows.js +2 -1
  18. package/lib/esm/options/context-windows.js.map +1 -1
  19. package/lib/esm/options/openai.js +101 -0
  20. package/lib/esm/options/openai.js.map +1 -1
  21. package/lib/esm/options/vertexai.js +217 -65
  22. package/lib/esm/options/vertexai.js.map +1 -1
  23. package/lib/esm/types.js +102 -0
  24. package/lib/esm/types.js.map +1 -1
  25. package/lib/types/capability/openai.d.ts.map +1 -1
  26. package/lib/types/capability.d.ts.map +1 -1
  27. package/lib/types/options/context-windows.d.ts.map +1 -1
  28. package/lib/types/options/openai.d.ts +17 -2
  29. package/lib/types/options/openai.d.ts.map +1 -1
  30. package/lib/types/options/vertexai.d.ts +17 -1
  31. package/lib/types/options/vertexai.d.ts.map +1 -1
  32. package/lib/types/types.d.ts +95 -0
  33. package/lib/types/types.d.ts.map +1 -1
  34. package/package.json +1 -1
  35. package/src/LlumiverseError.test.ts +265 -0
  36. package/src/capability/openai.ts +21 -18
  37. package/src/capability.ts +30 -1
  38. package/src/options/context-windows.ts +2 -1
  39. package/src/options/openai.ts +126 -3
  40. package/src/options/vertexai.ts +262 -77
  41. package/src/types.ts +139 -0
@@ -1,8 +1,8 @@
1
- import { ModelOptionsInfo, ModelOptionInfoItem, ModelOptions, OptionType, SharedOptions } from "../types.js";
1
+ import { ModelOptionInfoItem, ModelOptions, ModelOptionsInfo, OptionType, SharedOptions } from "../types.js";
2
2
  import { textOptionsFallback } from "./fallback.js";
3
3
 
4
- // Union type of all Bedrock options
5
- export type OpenAiOptions = OpenAiThinkingOptions | OpenAiTextOptions;
4
+ // Union type of all OpenAI options
5
+ export type OpenAiOptions = OpenAiThinkingOptions | OpenAiTextOptions | OpenAiDalleOptions | OpenAiGptImageOptions;
6
6
 
7
7
  export interface OpenAiThinkingOptions {
8
8
  _option_id: "openai-thinking",
@@ -22,6 +22,22 @@ export interface OpenAiTextOptions {
22
22
  stop_sequence?: string[],
23
23
  image_detail?: "low" | "high" | "auto",
24
24
  }
25
+ export interface OpenAiDalleOptions {
26
+ _option_id: "openai-dalle",
27
+ size?: "256x256" | "512x512" | "1024x1024" | "1792x1024" | "1024x1792",
28
+ image_quality?: "standard" | "hd",
29
+ style?: "vivid" | "natural",
30
+ response_format?: "url" | "b64_json",
31
+ n?: number,
32
+ }
33
+
34
+ export interface OpenAiGptImageOptions {
35
+ _option_id: "openai-gpt-image",
36
+ size?: "1024x1024" | "1024x1536" | "1536x1024" | "auto",
37
+ image_quality?: "low" | "medium" | "high" | "auto",
38
+ background?: "transparent" | "opaque" | "auto",
39
+ output_format?: "png" | "webp" | "jpeg",
40
+ }
25
41
 
26
42
  export function getOpenAiOptions(model: string, _option?: ModelOptions): ModelOptionsInfo {
27
43
  const visionOptions: ModelOptionInfoItem[] = isVisionModel(model) ? [
@@ -31,6 +47,109 @@ export function getOpenAiOptions(model: string, _option?: ModelOptions): ModelOp
31
47
  },
32
48
  ] : [];
33
49
 
50
+ // Image generation models
51
+ if (isImageModel(model)) {
52
+ const isGPTImage = model.includes("gpt-image") || model.includes("chatgpt-image");
53
+ const isDallE2 = model.includes("dall-e-2");
54
+ const isDallE3 = model.includes("dall-e-3");
55
+
56
+ const sizeOptions: Record<string, string> = {};
57
+ if (isGPTImage) {
58
+ sizeOptions["1024x1024"] = "1024x1024";
59
+ sizeOptions["1024x1536"] = "1024x1536";
60
+ sizeOptions["1536x1024"] = "1536x1024";
61
+ sizeOptions["Auto"] = "auto";
62
+ } else if (isDallE2) {
63
+ sizeOptions["256x256"] = "256x256";
64
+ sizeOptions["512x512"] = "512x512";
65
+ sizeOptions["1024x1024"] = "1024x1024";
66
+ } else if (isDallE3) {
67
+ sizeOptions["1024x1024"] = "1024x1024";
68
+ sizeOptions["1792x1024"] = "1792x1024";
69
+ sizeOptions["1024x1792"] = "1024x1792";
70
+ }
71
+
72
+ const baseImageOptions: ModelOptionInfoItem[] = [
73
+ {
74
+ name: "size",
75
+ type: OptionType.enum,
76
+ enum: sizeOptions,
77
+ default: "1024x1024",
78
+ description: "The size of the generated image"
79
+ }
80
+ ];
81
+
82
+ const gptImageOptions: ModelOptionInfoItem[] = isGPTImage ? [
83
+ {
84
+ name: "image_quality",
85
+ type: OptionType.enum,
86
+ enum: { "Low": "low", "Medium": "medium", "High": "high", "Auto": "auto" },
87
+ default: "auto",
88
+ description: "The quality of the generated image"
89
+ },
90
+ {
91
+ name: "background",
92
+ type: OptionType.enum,
93
+ enum: { "Transparent": "transparent", "Opaque": "opaque", "Auto": "auto" },
94
+ default: "auto",
95
+ description: "The background setting for the image"
96
+ },
97
+ {
98
+ name: "output_format",
99
+ type: OptionType.enum,
100
+ enum: { "PNG": "png", "WebP": "webp", "JPEG": "jpeg" },
101
+ default: "png",
102
+ description: "The output format for the image"
103
+ }
104
+ ] : [];
105
+
106
+ const dalleOptions: ModelOptionInfoItem[] = (isDallE2 || isDallE3) ? [
107
+ {
108
+ name: "image_quality",
109
+ type: OptionType.enum,
110
+ enum: isDallE3 ? { "Standard": "standard", "HD": "hd" } : { "Standard": "standard" },
111
+ default: "standard",
112
+ description: "The quality of the generated image"
113
+ },
114
+ {
115
+ name: "style",
116
+ type: OptionType.enum,
117
+ enum: { "Vivid": "vivid", "Natural": "natural" },
118
+ default: "vivid",
119
+ description: "The style of the generated image (DALL-E 3 only)"
120
+ },
121
+ {
122
+ name: "response_format",
123
+ type: OptionType.enum,
124
+ enum: { "URL": "url", "Base64 JSON": "b64_json" },
125
+ default: "b64_json",
126
+ description: "The format of the response"
127
+ }
128
+ ] : [];
129
+
130
+ const nImagesOption: ModelOptionInfoItem[] = isDallE2 ? [
131
+ {
132
+ name: "n",
133
+ type: OptionType.numeric,
134
+ min: 1,
135
+ max: 10,
136
+ default: 1,
137
+ integer: true,
138
+ description: "Number of images to generate (DALL-E 2 only)"
139
+ }
140
+ ] : [];
141
+
142
+ return {
143
+ _option_id: isGPTImage ? "openai-gpt-image" : "openai-dalle",
144
+ options: [
145
+ ...baseImageOptions,
146
+ ...gptImageOptions,
147
+ ...dalleOptions,
148
+ ...nImagesOption,
149
+ ]
150
+ };
151
+ }
152
+
34
153
  if (model.includes("o1") || model.includes("o3")) {
35
154
  //Is thinking text model
36
155
  let max_tokens_limit = 4096;
@@ -148,4 +267,8 @@ function isO1Full(model: string): boolean {
148
267
 
149
268
  function isVisionModel(model: string): boolean {
150
269
  return model.includes("gpt-4o") || isO1Full(model) || model.includes("gpt-4-turbo");
270
+ }
271
+
272
+ function isImageModel(model: string): boolean {
273
+ return model.includes("dall-e") || model.includes("gpt-image") || model.includes("chatgpt-image");
151
274
  }
@@ -1,4 +1,4 @@
1
- import { ModelOptionsInfo, ModelOptionInfoItem, OptionType, SharedOptions, ModelOptions } from "../types.js";
1
+ import { ModelOptionInfoItem, ModelOptions, ModelOptionsInfo, OptionType, SharedOptions } from "../types.js";
2
2
  import { getMaxOutputTokens } from "./context-windows.js";
3
3
  import { textOptionsFallback } from "./fallback.js";
4
4
 
@@ -26,7 +26,9 @@ export enum ImagenMaskMode {
26
26
 
27
27
  export enum ThinkingLevel {
28
28
  HIGH = "HIGH",
29
+ MEDIUM = "MEDIUM",
29
30
  LOW = "LOW",
31
+ MINIMAL = "MINIMAL",
30
32
  THINKING_LEVEL_UNSPECIFIED = "THINKING_LEVEL_UNSPECIFIED"
31
33
  }
32
34
 
@@ -83,7 +85,13 @@ export interface VertexAIGeminiOptions {
83
85
  include_thoughts?: boolean;
84
86
  thinking_budget_tokens?: number;
85
87
  thinking_level?: ThinkingLevel;
88
+ // ImageConfig properties
86
89
  image_aspect_ratio?: "1:1" | "2:3" | "3:2" | "3:4" | "4:3" | "9:16" | "16:9" | "21:9";
90
+ image_size?: "1K" | "2K" | "4K";
91
+ person_generation?: "ALLOW_ALL" | "ALLOW_ADULT" | "ALLOW_NONE";
92
+ prominent_people?: "PROMINENT_PEOPLE_UNSPECIFIED" | "ALLOW_PROMINENT_PEOPLE" | "BLOCK_PROMINENT_PEOPLE";
93
+ output_mime_type?: "image/png" | "image/jpeg";
94
+ output_compression_quality?: number;
87
95
  }
88
96
 
89
97
  export function getVertexAiOptions(model: string, option?: ModelOptions): ModelOptionsInfo {
@@ -99,6 +107,142 @@ export function getVertexAiOptions(model: string, option?: ModelOptions): ModelO
99
107
  return textOptionsFallback;
100
108
  }
101
109
 
110
+ /**
111
+ * Extract Gemini version from a model ID.
112
+ *
113
+ * Examples:
114
+ * - locations/global/publishers/google/models/gemini-2.5-flash -> 2.5
115
+ * - publishers/google/models/gemini-3-pro-image-preview -> 3
116
+ */
117
+ export function getGeminiModelVersion(modelId: string): string | undefined {
118
+ const modelName = modelId.split('/').pop() ?? modelId;
119
+ const match = modelName.match(/^gemini-(\d+(?:\.\d+)?)/i);
120
+ return match?.[1];
121
+ }
122
+
123
+ function parseVersion(version: string): { major: number; minor: number } | undefined {
124
+ const match = version.match(/^(\d+)(?:\.(\d+))?$/);
125
+ if (!match) {
126
+ return undefined;
127
+ }
128
+
129
+ return {
130
+ major: Number(match[1]),
131
+ minor: Number(match[2] ?? '0'),
132
+ };
133
+ }
134
+
135
+ export function isGeminiModelVersionGte(modelId: string, minVersion: string): boolean {
136
+ const modelVersion = getGeminiModelVersion(modelId);
137
+ if (!modelVersion) {
138
+ return false;
139
+ }
140
+
141
+ const current = parseVersion(modelVersion);
142
+ const target = parseVersion(minVersion);
143
+ if (!current || !target) {
144
+ return false;
145
+ }
146
+
147
+ if (current.major > target.major) {
148
+ return true;
149
+ }
150
+ if (current.major < target.major) {
151
+ return false;
152
+ }
153
+
154
+ return current.minor >= target.minor;
155
+ }
156
+
157
+ function getGeminiThinkingLevels(model: string): {
158
+ levels: Record<string, ThinkingLevel>;
159
+ defaultLevel: ThinkingLevel;
160
+ } {
161
+ const normalized = model.toLowerCase();
162
+ const isGemini3OrLater = isGeminiModelVersionGte(model, "3.0");
163
+ const isGemini31OrLater = isGeminiModelVersionGte(model, "3.1");
164
+ const isFlashLite = normalized.includes("flash-lite");
165
+ const isFlash = normalized.includes("flash") && !isFlashLite;
166
+ const isPro = normalized.includes("pro");
167
+
168
+ // Gemini 3 / 3.1 thinking_level support summary:
169
+ // - MINIMAL: Gemini 3 Flash and Gemini 3.1 Flash-Lite only.
170
+ // Gemini 3.1 Flash-Lite defaults to MINIMAL.
171
+ // - LOW: Supported by Gemini 3+ models.
172
+ // - MEDIUM: Gemini 3 Flash, Gemini 3.1 Pro, Gemini 3.1 Flash-Lite.
173
+ // - HIGH: Supported by Gemini 3+ models.
174
+ // - Thinking cannot be turned off for Gemini 3 Pro and Gemini 3.1 Pro.
175
+ if (isFlashLite && isGemini31OrLater) {
176
+ return {
177
+ levels: {
178
+ "Minimal": ThinkingLevel.MINIMAL,
179
+ "Low": ThinkingLevel.LOW,
180
+ "Medium": ThinkingLevel.MEDIUM,
181
+ "High": ThinkingLevel.HIGH,
182
+ },
183
+ defaultLevel: ThinkingLevel.MINIMAL,
184
+ };
185
+ }
186
+
187
+ // Gemini 3+ Flash supports MINIMAL and MEDIUM in addition to LOW/HIGH.
188
+ if (isFlash) {
189
+ return {
190
+ levels: {
191
+ "Minimal": ThinkingLevel.MINIMAL,
192
+ "Low": ThinkingLevel.LOW,
193
+ "Medium": ThinkingLevel.MEDIUM,
194
+ "High": ThinkingLevel.HIGH,
195
+ },
196
+ defaultLevel: ThinkingLevel.MINIMAL,
197
+ };
198
+ }
199
+
200
+ // Gemini 3.1 Pro adds MEDIUM, but does not support turning thinking off.
201
+ if (isPro && isGemini31OrLater) {
202
+ return {
203
+ levels: {
204
+ "Low": ThinkingLevel.LOW,
205
+ "Medium": ThinkingLevel.MEDIUM,
206
+ "High": ThinkingLevel.HIGH,
207
+ },
208
+ defaultLevel: ThinkingLevel.LOW,
209
+ };
210
+ }
211
+
212
+ // Gemini 3 Pro supports LOW/HIGH. Thinking cannot be turned off.
213
+ if (isPro) {
214
+ return {
215
+ levels: {
216
+ "Low": ThinkingLevel.LOW,
217
+ "High": ThinkingLevel.HIGH,
218
+ },
219
+ defaultLevel: ThinkingLevel.LOW,
220
+ };
221
+ }
222
+
223
+ // Fallback for unknown Gemini 3+/4+ families:
224
+ // prefer future-safe propagation by enabling the guaranteed baseline levels.
225
+ if (isGemini3OrLater) {
226
+ return {
227
+ levels: {
228
+ "Low": ThinkingLevel.LOW,
229
+ "Medium": ThinkingLevel.MEDIUM,
230
+ "High": ThinkingLevel.HIGH,
231
+ },
232
+ defaultLevel: ThinkingLevel.LOW,
233
+ };
234
+ }
235
+
236
+ // Non-3.x models should not reach this helper in normal flow.
237
+ return {
238
+ levels: {
239
+ "Low": ThinkingLevel.LOW,
240
+ "High": ThinkingLevel.HIGH,
241
+ },
242
+ defaultLevel: ThinkingLevel.LOW,
243
+ };
244
+ }
245
+
102
246
  function getImagenOptions(model: string, option?: ModelOptions): ModelOptionsInfo {
103
247
  const commonOptions: ModelOptionInfoItem[] = [
104
248
  {
@@ -253,58 +397,36 @@ function getImagenOptions(model: string, option?: ModelOptions): ModelOptionsInf
253
397
  return textOptionsFallback;
254
398
  }
255
399
 
256
- function getGeminiOptions(model: string, _option?: ModelOptions): ModelOptionsInfo {
257
- // Special handling for gemini-2.5-flash-image
258
- if (model.includes("gemini-2.5-flash-image")) {
259
- const options: ModelOptionInfoItem[] = [
260
- {
261
- name: SharedOptions.temperature,
262
- type: OptionType.numeric,
263
- min: 0.0,
264
- max: 2.0,
265
- default: 0.7,
266
- step: 0.01,
267
- description: "Sampling temperature"
268
- },
269
- {
270
- name: SharedOptions.top_p,
271
- type: OptionType.numeric,
272
- min: 0.0,
273
- max: 1.0,
274
- step: 0.01,
275
- description: "Nucleus sampling probability"
276
- },
277
- {
278
- name: "candidate_count",
279
- type: OptionType.numeric,
280
- min: 1,
281
- max: 8,
282
- default: 1,
283
- integer: true,
284
- description: "Number of candidates to generate"
285
- },
286
- {
287
- name: SharedOptions.max_tokens,
288
- type: OptionType.numeric,
289
- min: 1,
290
- max: 32768,
291
- integer: true,
292
- step: 200,
293
- description: "Maximum output tokens"
294
- }
295
- ];
296
- return {
297
- _option_id: "vertexai-gemini",
298
- options
299
- };
300
- }
301
- // Special handling for gemini-2.5-flash-image and gemini-3-pro-image
302
- if (model.includes("gemini-2.5-flash-image") || model.includes("gemini-3-pro-image")) {
303
- const max_tokens_limit = 32768;
400
+ function getGeminiThinkingOptionItems(model: string): ModelOptionInfoItem[] {
401
+ const thinkingLevelConfig = getGeminiThinkingLevels(model);
402
+ return [
403
+ {
404
+ name: "include_thoughts",
405
+ type: OptionType.boolean,
406
+ default: false,
407
+ description: "Include the model's reasoning process in the response"
408
+ },
409
+ {
410
+ name: "thinking_level",
411
+ type: OptionType.enum,
412
+ enum: thinkingLevelConfig.levels,
413
+ default: thinkingLevelConfig.defaultLevel,
414
+ description: "Higher thinking levels may improve quality, but increase response times and token costs"
415
+ }
416
+ ];
417
+ }
418
+
419
+ function getGeminiOptions(model: string, option?: ModelOptions): ModelOptionsInfo {
420
+ // Special handling for gemini image / nano banana models
421
+ if (model.includes("image")) {
422
+ const isGemini25OrLater = isGeminiModelVersionGte(model, "2.5");
423
+ const isGemini3OrLater = isGeminiModelVersionGte(model, "3.0");
424
+
425
+ const max_tokens_limit = getGeminiMaxTokensLimit(model);
304
426
  const excludeOptions = ["max_tokens", "presence_penalty", "frequency_penalty", "seed", "top_k"];
305
427
  let commonOptions = textOptionsFallback.options.filter((option) => !excludeOptions.includes(option.name));
306
428
 
307
- // Set max temperature to 2.0 for gemini-2.5-flash-image
429
+ // Set max temperature to 2.0
308
430
  commonOptions = commonOptions.map((option) => {
309
431
  if (
310
432
  option.name === SharedOptions.temperature &&
@@ -328,28 +450,100 @@ function getGeminiOptions(model: string, _option?: ModelOptions): ModelOptionsIn
328
450
  description: "Maximum output tokens"
329
451
  }];
330
452
 
331
- const imageAspectRatio: ModelOptionInfoItem[] = [{
332
- name: "image_aspect_ratio",
453
+ const imageOptions: ModelOptionInfoItem[] = [];
454
+
455
+ // Aspect ratio, person generation, prominent people: 2.5+
456
+ if (isGemini25OrLater) {
457
+ imageOptions.push(
458
+ {
459
+ name: "image_aspect_ratio",
460
+ type: OptionType.enum,
461
+ enum: {
462
+ "1:1": "1:1",
463
+ "2:3": "2:3",
464
+ "3:2": "3:2",
465
+ "3:4": "3:4",
466
+ "4:3": "4:3",
467
+ "9:16": "9:16",
468
+ "16:9": "16:9",
469
+ "21:9": "21:9"
470
+ },
471
+ default: "1:1",
472
+ description: "Aspect ratio of the generated images"
473
+ },
474
+ {
475
+ name: "person_generation",
476
+ type: OptionType.enum,
477
+ enum: {
478
+ "Allow all people": "ALLOW_ALL",
479
+ "Allow adults only": "ALLOW_ADULT",
480
+ "Do not generate people": "ALLOW_NONE"
481
+ },
482
+ default: "ALLOW_ALL",
483
+ description: "Controls the generation of people in images"
484
+ },
485
+ {
486
+ name: "prominent_people",
487
+ type: OptionType.enum,
488
+ enum: {
489
+ "Allow prominent people": "ALLOW_PROMINENT_PEOPLE",
490
+ "Block prominent people": "BLOCK_PROMINENT_PEOPLE"
491
+ },
492
+ description: "Controls whether prominent people (celebrities) can be generated"
493
+ },
494
+ );
495
+ }
496
+
497
+ // Resolution settings: 3.0+
498
+ if (isGemini3OrLater) {
499
+ imageOptions.push({
500
+ name: "image_size",
501
+ type: OptionType.enum,
502
+ enum: {
503
+ "1K": "1K",
504
+ "2K": "2K",
505
+ "4K": "4K"
506
+ },
507
+ default: "1K",
508
+ description: "Size of generated images"
509
+ });
510
+ }
511
+
512
+ // Output format: all image models
513
+ imageOptions.push({
514
+ name: "output_mime_type",
333
515
  type: OptionType.enum,
334
516
  enum: {
335
- "1:1": "1:1",
336
- "2:3": "2:3",
337
- "3:2": "3:2",
338
- "3:4": "3:4",
339
- "4:3": "4:3",
340
- "9:16": "9:16",
341
- "16:9": "16:9",
342
- "21:9": "21:9"
517
+ "PNG": "image/png",
518
+ "JPEG": "image/jpeg",
343
519
  },
344
- description: "Aspect ratio of the generated images"
345
- }];
520
+ default: "image/png",
521
+ description: "MIME type of the generated image",
522
+ refresh: true,
523
+ });
524
+
525
+ if ((option as VertexAIGeminiOptions)?.output_mime_type === "image/jpeg") {
526
+ imageOptions.push({
527
+ name: "output_compression_quality",
528
+ type: OptionType.numeric,
529
+ min: 0,
530
+ max: 100,
531
+ default: 90,
532
+ integer: true,
533
+ description: "Compression quality for JPEG images (0-100)"
534
+ });
535
+ }
536
+
537
+ // Thinking options: 3.0+ (same as non-image counterparts)
538
+ const thinkingOptions = isGemini3OrLater ? getGeminiThinkingOptionItems(model) : [];
346
539
 
347
540
  return {
348
541
  _option_id: "vertexai-gemini",
349
542
  options: [
350
543
  ...max_tokens,
351
544
  ...commonOptions,
352
- ...imageAspectRatio,
545
+ ...imageOptions,
546
+ ...thinkingOptions,
353
547
  ]
354
548
  };
355
549
  }
@@ -366,23 +560,14 @@ function getGeminiOptions(model: string, _option?: ModelOptions): ModelOptionsIn
366
560
  name: SharedOptions.seed, type: OptionType.numeric, integer: true, description: "The seed for the generation, useful for reproducibility"
367
561
  };
368
562
 
369
- if (model.includes("-3-")) {
370
- const geminiThinkingOptions: ModelOptionInfoItem[] = [
371
- {
372
- name: "include_thoughts",
373
- type: OptionType.boolean,
374
- default: false,
375
- description: "Include the model's reasoning process in the response"
376
- }
377
- ];
378
-
563
+ if (isGeminiModelVersionGte(model, "3.0")) {
379
564
  return {
380
565
  _option_id: "vertexai-gemini",
381
566
  options: [
382
567
  ...max_tokens,
383
568
  ...commonOptions,
384
569
  seedOption,
385
- ...geminiThinkingOptions,
570
+ ...getGeminiThinkingOptionItems(model),
386
571
  ]
387
572
  };
388
573
  }
@@ -545,10 +730,10 @@ function getLlamaOptions(model: string): ModelOptionsInfo {
545
730
  }
546
731
 
547
732
  function getGeminiMaxTokensLimit(model: string): number {
548
- if (model.includes("gemini-2.5-flash-image") || model.includes("gemini-3-pro-image")) {
549
- return 32768;
733
+ if (model.includes("image")) {
734
+ return isGeminiModelVersionGte(model, "2.5") ? 32768 : 8192;
550
735
  }
551
- if (model.includes("thinking") || model.includes("-2.5-") || model.includes("-3-")) {
736
+ if (model.includes("thinking") || isGeminiModelVersionGte(model, "2.5")) {
552
737
  return 65535; // API upper bound is exclusive
553
738
  }
554
739
  if (model.includes("ultra") || model.includes("vision")) {