@workglow/google-gemini 0.2.33 → 0.2.35

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 (46) hide show
  1. package/dist/ai/GoogleGeminiProvider.d.ts +15 -20
  2. package/dist/ai/GoogleGeminiProvider.d.ts.map +1 -1
  3. package/dist/ai/GoogleGeminiQueuedProvider.d.ts +16 -21
  4. package/dist/ai/GoogleGeminiQueuedProvider.d.ts.map +1 -1
  5. package/dist/ai/common/Gemini_Capabilities.d.ts +49 -0
  6. package/dist/ai/common/Gemini_Capabilities.d.ts.map +1 -0
  7. package/dist/ai/common/Gemini_CapabilitySets.d.ts +30 -0
  8. package/dist/ai/common/Gemini_CapabilitySets.d.ts.map +1 -0
  9. package/dist/ai/common/Gemini_CountTokens.d.ts +1 -1
  10. package/dist/ai/common/Gemini_CountTokens.d.ts.map +1 -1
  11. package/dist/ai/common/Gemini_ImageEdit.d.ts +5 -6
  12. package/dist/ai/common/Gemini_ImageEdit.d.ts.map +1 -1
  13. package/dist/ai/common/Gemini_ImageGenerate.d.ts +5 -7
  14. package/dist/ai/common/Gemini_ImageGenerate.d.ts.map +1 -1
  15. package/dist/ai/common/Gemini_JobRunFns.d.ts +10 -3
  16. package/dist/ai/common/Gemini_JobRunFns.d.ts.map +1 -1
  17. package/dist/ai/common/Gemini_ModelInfo.d.ts +1 -1
  18. package/dist/ai/common/Gemini_ModelInfo.d.ts.map +1 -1
  19. package/dist/ai/common/Gemini_ModelSchema.d.ts +3 -3
  20. package/dist/ai/common/Gemini_ModelSearch.d.ts +8 -1
  21. package/dist/ai/common/Gemini_ModelSearch.d.ts.map +1 -1
  22. package/dist/ai/common/Gemini_StructuredGeneration.d.ts +9 -3
  23. package/dist/ai/common/Gemini_StructuredGeneration.d.ts.map +1 -1
  24. package/dist/ai/common/Gemini_TextEmbedding.d.ts +1 -1
  25. package/dist/ai/common/Gemini_TextEmbedding.d.ts.map +1 -1
  26. package/dist/ai/common/Gemini_TextGeneration.d.ts +13 -3
  27. package/dist/ai/common/Gemini_TextGeneration.d.ts.map +1 -1
  28. package/dist/ai/common/Gemini_TextRewriter.d.ts +2 -3
  29. package/dist/ai/common/Gemini_TextRewriter.d.ts.map +1 -1
  30. package/dist/ai/common/Gemini_TextSummary.d.ts +2 -3
  31. package/dist/ai/common/Gemini_TextSummary.d.ts.map +1 -1
  32. package/dist/ai/common/Gemini_ToolCalling.d.ts +2 -3
  33. package/dist/ai/common/Gemini_ToolCalling.d.ts.map +1 -1
  34. package/dist/ai/index.d.ts +25 -0
  35. package/dist/ai/index.d.ts.map +1 -1
  36. package/dist/ai/registerGeminiWorker.d.ts.map +1 -1
  37. package/dist/ai/runtime.d.ts.map +1 -1
  38. package/dist/ai-runtime.d.ts.map +1 -1
  39. package/dist/ai-runtime.js +490 -542
  40. package/dist/ai-runtime.js.map +22 -21
  41. package/dist/ai.d.ts.map +1 -1
  42. package/dist/ai.js +671 -38
  43. package/dist/ai.js.map +21 -5
  44. package/package.json +12 -13
  45. package/dist/ai/common/Gemini_Chat.d.ts +0 -10
  46. package/dist/ai/common/Gemini_Chat.d.ts.map +0 -1
package/dist/ai.js CHANGED
@@ -8,7 +8,6 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
8
8
 
9
9
  // src/ai/common/Gemini_Constants.ts
10
10
  var GOOGLE_GEMINI = "GOOGLE_GEMINI";
11
-
12
11
  // src/ai/common/Gemini_ImageValidation.ts
13
12
  import { AiImageOutputTask, ProviderUnsupportedFeatureError } from "@workglow/ai";
14
13
  function registerGeminiImageValidator() {
@@ -20,7 +19,6 @@ function registerGeminiImageValidator() {
20
19
  }
21
20
  });
22
21
  }
23
-
24
22
  // src/ai/common/Gemini_ModelSchema.ts
25
23
  import { ModelConfigSchema, ModelRecordSchema } from "@workglow/ai/worker";
26
24
  var GeminiModelSchema = {
@@ -87,10 +85,9 @@ var GeminiModelConfigSchema = {
87
85
  required: [...ModelConfigSchema.required, ...GeminiModelSchema.required],
88
86
  additionalProperties: false
89
87
  };
90
-
91
88
  // src/ai/common/Gemini_ModelSearch.ts
92
89
  import { normalizedModelSearchQuery } from "@workglow/ai/provider-utils";
93
- var GEMINI_MODELS = [
90
+ var GEMINI_FALLBACK_MODELS = [
94
91
  { label: "gemini-3.1-pro-preview", value: "gemini-3.1-pro-preview" },
95
92
  { label: "gemini-3-flash-preview", value: "gemini-3-flash-preview" },
96
93
  { label: "gemini-3.1-flash-lite-preview", value: "gemini-3.1-flash-lite-preview" },
@@ -99,36 +96,36 @@ var GEMINI_MODELS = [
99
96
  {
100
97
  label: "gemini-embedding-2",
101
98
  value: "gemini-embedding-2",
102
- tasks: ["TextEmbeddingTask"]
99
+ capabilities: ["text.embedding"]
103
100
  },
104
101
  {
105
102
  label: "gemini-embedding-001",
106
103
  value: "gemini-embedding-001",
107
- tasks: ["TextEmbeddingTask"]
104
+ capabilities: ["text.embedding"]
108
105
  },
109
106
  {
110
107
  label: "gemini-3.1-flash-image-preview",
111
108
  value: "gemini-3.1-flash-image-preview",
112
- tasks: ["ImageGenerateTask", "ImageEditTask"]
109
+ capabilities: ["image.generation", "image.editing"]
113
110
  },
114
111
  {
115
112
  label: "gemini-3-pro-image-preview",
116
113
  value: "gemini-3-pro-image-preview",
117
- tasks: ["ImageGenerateTask", "ImageEditTask"]
114
+ capabilities: ["image.generation", "image.editing"]
118
115
  },
119
116
  {
120
117
  label: "imagen-4.0-generate-001",
121
118
  value: "imagen-4.0-generate-001",
122
- tasks: ["ImageGenerateTask"]
119
+ capabilities: ["image.generation"]
123
120
  }
124
121
  ];
125
- function tasksForGeminiApiModel(model, id) {
126
- const staticEntry = GEMINI_MODELS.find((m) => m.value === id);
127
- if (staticEntry?.tasks)
128
- return [...staticEntry.tasks];
122
+ function capabilitiesForGeminiApiModel(model, id) {
123
+ const staticEntry = GEMINI_FALLBACK_MODELS.find((m) => m.value === id);
124
+ if (staticEntry?.capabilities)
125
+ return [...staticEntry.capabilities];
129
126
  const methods = model.supportedGenerationMethods ?? [];
130
127
  if (methods.some((method) => method.toLowerCase().includes("embed"))) {
131
- return ["TextEmbeddingTask"];
128
+ return ["text.embedding"];
132
129
  }
133
130
  return [];
134
131
  }
@@ -144,7 +141,7 @@ function mapGeminiModel(model) {
144
141
  provider: GOOGLE_GEMINI,
145
142
  title,
146
143
  description: model.description ?? "",
147
- tasks: tasksForGeminiApiModel(model, id),
144
+ capabilities: capabilitiesForGeminiApiModel(model, id),
148
145
  provider_config: { model_name: id },
149
146
  metadata: {}
150
147
  },
@@ -161,14 +158,15 @@ async function listGeminiModels(credentialKey, signal) {
161
158
  const body = await response.json();
162
159
  return (body.models ?? []).map(mapGeminiModel);
163
160
  }
164
- var Gemini_ModelSearch = async (input, _model, _onProgress, signal) => {
161
+ var Gemini_ModelSearch_Stream = async (input, _model, signal, emit) => {
165
162
  const q = normalizedModelSearchQuery(input.query);
166
163
  if (input.credential_key) {
167
164
  const models = await listGeminiModels(input.credential_key, signal);
168
165
  const results2 = q ? models.filter((m) => m.id.toLowerCase().includes(q) || m.label.toLowerCase().includes(q)) : models;
169
- return { results: results2 };
166
+ emit({ type: "finish", data: { results: results2 } });
167
+ return;
170
168
  }
171
- const filtered = q ? GEMINI_MODELS.filter((m) => m.value.toLowerCase().includes(q) || m.label.toLowerCase().includes(q)) : GEMINI_MODELS;
169
+ const filtered = q ? GEMINI_FALLBACK_MODELS.filter((m) => m.value.toLowerCase().includes(q) || m.label.toLowerCase().includes(q)) : GEMINI_FALLBACK_MODELS;
172
170
  const results = filtered.map((m) => ({
173
171
  id: m.value,
174
172
  label: m.label,
@@ -178,40 +176,127 @@ var Gemini_ModelSearch = async (input, _model, _onProgress, signal) => {
178
176
  provider: GOOGLE_GEMINI,
179
177
  title: m.value,
180
178
  description: "",
181
- tasks: m.tasks ? [...m.tasks] : [],
179
+ capabilities: m.capabilities ? [...m.capabilities] : [],
182
180
  provider_config: { model_name: m.value },
183
181
  metadata: {}
184
182
  },
185
183
  raw: m
186
184
  }));
187
- return { results };
185
+ emit({ type: "finish", data: { results } });
188
186
  };
189
-
190
187
  // src/ai/registerGemini.ts
191
188
  import { registerProviderWithWorker } from "@workglow/ai/provider-utils";
192
189
 
193
190
  // src/ai/GoogleGeminiQueuedProvider.ts
194
191
  import { AiProvider } from "@workglow/ai";
195
192
  import { createCloudProviderClass } from "@workglow/ai/provider-utils";
196
- var GEMINI_TASK_TYPES = [
197
- "CountTokensTask",
198
- "ModelInfoTask",
199
- "TextGenerationTask",
200
- "TextEmbeddingTask",
201
- "TextRewriterTask",
202
- "TextSummaryTask",
203
- "StructuredGenerationTask",
204
- "ToolCallingTask",
205
- "ModelSearchTask",
206
- "ImageGenerateTask",
207
- "ImageEditTask"
193
+
194
+ // src/ai/common/Gemini_CapabilitySets.ts
195
+ var GEMINI_TEXT_GENERATION = ["text.generation"];
196
+ var GEMINI_TOOL_USE = ["text.generation", "tool-use"];
197
+ var GEMINI_JSON_MODE = ["text.generation", "json-mode"];
198
+ var GEMINI_TEXT_REWRITER = ["text.rewriter"];
199
+ var GEMINI_TEXT_SUMMARY = ["text.summary"];
200
+ var GEMINI_TEXT_EMBEDDING = ["text.embedding"];
201
+ var GEMINI_IMAGE_GENERATION = ["image.generation"];
202
+ var GEMINI_IMAGE_EDITING = ["image.editing"];
203
+ var GEMINI_COUNT_TOKENS = ["model.count-tokens"];
204
+ var GEMINI_MODEL_SEARCH = ["model.search"];
205
+ var GEMINI_MODEL_INFO = ["model.info"];
206
+ var GEMINI_CAPABILITY_SETS = [
207
+ GEMINI_TEXT_GENERATION,
208
+ GEMINI_TOOL_USE,
209
+ GEMINI_JSON_MODE,
210
+ GEMINI_TEXT_REWRITER,
211
+ GEMINI_TEXT_SUMMARY,
212
+ GEMINI_TEXT_EMBEDDING,
213
+ GEMINI_IMAGE_GENERATION,
214
+ GEMINI_IMAGE_EDITING,
215
+ GEMINI_COUNT_TOKENS,
216
+ GEMINI_MODEL_SEARCH,
217
+ GEMINI_MODEL_INFO
208
218
  ];
209
219
 
220
+ // src/ai/common/Gemini_Capabilities.ts
221
+ var GEMINI_RUN_FN_SPECS = GEMINI_CAPABILITY_SETS.map((serves) => ({ serves }));
222
+ function geminiWorkerRunFnSpecs() {
223
+ return GEMINI_RUN_FN_SPECS;
224
+ }
225
+ function inferGeminiCapabilities(model) {
226
+ const id = String(model.model_id ?? model.provider_config?.model_name ?? "");
227
+ if (/^text-embedding/i.test(id) || /^embedding-\d/i.test(id) || /^gemini-embedding/i.test(id)) {
228
+ return ["text.embedding", "model.info", "model.search"];
229
+ }
230
+ if (/^imagen-/i.test(id)) {
231
+ return ["image.generation", "model.info", "model.search"];
232
+ }
233
+ if (/^gemini-.*-image-/i.test(id)) {
234
+ return ["image.generation", "image.editing", "model.info", "model.search"];
235
+ }
236
+ if (/^gemini-pro-vision$/i.test(id)) {
237
+ return [
238
+ "text.generation",
239
+ "text.rewriter",
240
+ "text.summary",
241
+ "tool-use",
242
+ "json-mode",
243
+ "vision-input",
244
+ "model.info",
245
+ "model.search"
246
+ ];
247
+ }
248
+ if (/^gemini-1\.0-pro($|-(?!vision))/i.test(id)) {
249
+ return [
250
+ "text.generation",
251
+ "text.rewriter",
252
+ "text.summary",
253
+ "tool-use",
254
+ "json-mode",
255
+ "model.info",
256
+ "model.search"
257
+ ];
258
+ }
259
+ if (/^gemini-pro$/i.test(id)) {
260
+ return [
261
+ "text.generation",
262
+ "text.rewriter",
263
+ "text.summary",
264
+ "tool-use",
265
+ "json-mode",
266
+ "model.info",
267
+ "model.search"
268
+ ];
269
+ }
270
+ if (/^gemini-(?:1\.5|2\.[05]|2\.5|3(?:\.\d+)?-)/i.test(id)) {
271
+ return [
272
+ "text.generation",
273
+ "text.rewriter",
274
+ "text.summary",
275
+ "tool-use",
276
+ "json-mode",
277
+ "vision-input",
278
+ "model.count-tokens",
279
+ "model.info",
280
+ "model.search"
281
+ ];
282
+ }
283
+ const declared = model.capabilities ?? [];
284
+ if (declared.length > 0)
285
+ return declared;
286
+ return ["model.search", "model.info"];
287
+ }
288
+
289
+ // src/ai/GoogleGeminiQueuedProvider.ts
210
290
  class GoogleGeminiQueuedProvider extends createCloudProviderClass(AiProvider, {
211
291
  name: GOOGLE_GEMINI,
212
- displayName: "Google Gemini",
213
- taskTypes: GEMINI_TASK_TYPES
292
+ displayName: "Google Gemini"
214
293
  }) {
294
+ inferCapabilities(model) {
295
+ return inferGeminiCapabilities(model);
296
+ }
297
+ workerRunFnSpecs() {
298
+ return geminiWorkerRunFnSpecs();
299
+ }
215
300
  }
216
301
 
217
302
  // src/ai/registerGemini.ts
@@ -219,14 +304,562 @@ async function registerGemini(options) {
219
304
  registerGeminiImageValidator();
220
305
  await registerProviderWithWorker(new GoogleGeminiQueuedProvider, "Google Gemini", options);
221
306
  }
307
+ // src/ai/common/Gemini_Client.ts
308
+ import { resolveApiKey } from "@workglow/ai/provider-utils";
309
+ var _loadPromise;
310
+ async function loadGeminiSDK() {
311
+ _loadPromise ??= import("@google/generative-ai").then((mod) => mod.GoogleGenerativeAI).catch(() => {
312
+ _loadPromise = undefined;
313
+ throw new Error("@google/generative-ai is required for Gemini tasks. Install it with: bun add @google/generative-ai");
314
+ });
315
+ return _loadPromise;
316
+ }
317
+ function getApiKey(model) {
318
+ const config = model?.provider_config;
319
+ return resolveApiKey({
320
+ config,
321
+ envVar: ["GOOGLE_API_KEY", "GEMINI_API_KEY"],
322
+ providerLabel: "Google"
323
+ });
324
+ }
325
+ function getModelName(model) {
326
+ const name = model?.provider_config?.model_name;
327
+ if (!name) {
328
+ throw new Error("Missing model name in provider_config.model_name.");
329
+ }
330
+ return name;
331
+ }
332
+
333
+ // src/ai/common/Gemini_Schema.ts
334
+ function sanitizeSchemaForGemini(schema) {
335
+ const result = {};
336
+ for (const [key, value] of Object.entries(schema)) {
337
+ if (key === "additionalProperties")
338
+ continue;
339
+ if (value && typeof value === "object" && !Array.isArray(value)) {
340
+ result[key] = sanitizeSchemaForGemini(value);
341
+ } else {
342
+ result[key] = value;
343
+ }
344
+ }
345
+ return result;
346
+ }
347
+
348
+ // src/ai/common/Gemini_CountTokens.ts
349
+ var Gemini_CountTokens_Stream = async (input, model, signal, emit) => {
350
+ const GoogleGenerativeAI = await loadGeminiSDK();
351
+ const genAI = new GoogleGenerativeAI(getApiKey(model));
352
+ const genModel = genAI.getGenerativeModel({ model: getModelName(model) });
353
+ const result = await genModel.countTokens(input.text);
354
+ emit({ type: "finish", data: { count: result.totalTokens } });
355
+ };
356
+ var Gemini_CountTokens_Preview = async (input, _model) => {
357
+ return { count: Math.ceil(input.text.length / 4) };
358
+ };
359
+
360
+ // src/ai/common/Gemini_ImageEdit.ts
361
+ import { ImageGenerationContentPolicyError, ImageGenerationProviderError } from "@workglow/ai";
362
+ import { getLogger } from "@workglow/util/worker";
363
+ import { dataUriToImageValue, imageValueToPngBytes } from "@workglow/ai/provider-utils";
364
+ function modelIdOf(model) {
365
+ return model?.model_id ?? model?.provider_config?.model_name ?? "gemini";
366
+ }
367
+ async function decodeInlineImage(mimeType, data) {
368
+ return dataUriToImageValue(`data:${mimeType};base64,${data}`);
369
+ }
370
+ async function gpuImageToInlinePart(image) {
371
+ if (typeof image === "string" && image.startsWith("data:")) {
372
+ const base642 = image.replace(/^data:[^;]+;base64,/, "");
373
+ return { inlineData: { mimeType: "image/png", data: base642 } };
374
+ }
375
+ const bytes = await imageValueToPngBytes(image);
376
+ let base64;
377
+ if (typeof Buffer !== "undefined") {
378
+ base64 = Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength).toString("base64");
379
+ } else {
380
+ let binary = "";
381
+ for (let i = 0;i < bytes.byteLength; i++) {
382
+ binary += String.fromCharCode(bytes[i]);
383
+ }
384
+ base64 = btoa(binary);
385
+ }
386
+ return { inlineData: { mimeType: "image/png", data: base64 } };
387
+ }
388
+ var Gemini_ImageEdit_Stream = async (input, model, signal, emit) => {
389
+ const logger = getLogger();
390
+ const timer = `gemini:ImageEdit:${modelIdOf(model)}`;
391
+ logger.time(timer, { model: modelIdOf(model) });
392
+ try {
393
+ const GoogleGenerativeAI = await loadGeminiSDK();
394
+ const genAI = new GoogleGenerativeAI(getApiKey(model));
395
+ const modelName = getModelName(model);
396
+ const genModel = genAI.getGenerativeModel({ model: modelName });
397
+ const primaryPart = await gpuImageToInlinePart(input.image);
398
+ const additionalParts = input.additionalImages && input.additionalImages.length > 0 ? await Promise.all(input.additionalImages.map((g) => gpuImageToInlinePart(g))) : [];
399
+ const parts = [{ text: input.prompt }, primaryPart, ...additionalParts];
400
+ try {
401
+ const result = await genModel.generateContent({ contents: [{ role: "user", parts }] }, {
402
+ signal
403
+ });
404
+ const response = result.response;
405
+ if (!response.candidates || response.candidates.length === 0 || response.promptFeedback?.blockReason) {
406
+ const reason = response.promptFeedback?.blockReason ?? "SAFETY";
407
+ throw new ImageGenerationContentPolicyError(modelIdOf(model), `Blocked: ${reason}`);
408
+ }
409
+ const candidateParts = response.candidates[0]?.content?.parts ?? [];
410
+ const imagePart = candidateParts.find((p) => p.inlineData && p.inlineData.mimeType && p.inlineData.data);
411
+ if (!imagePart) {
412
+ throw new ImageGenerationProviderError(modelIdOf(model), "No image part in response (Gemini did not return an inline image)");
413
+ }
414
+ const image = await decodeInlineImage(imagePart.inlineData.mimeType, imagePart.inlineData.data);
415
+ emit({ type: "snapshot", data: { image } });
416
+ emit({ type: "finish", data: {} });
417
+ } catch (err) {
418
+ if (err instanceof ImageGenerationProviderError || err instanceof ImageGenerationContentPolicyError) {
419
+ throw err;
420
+ }
421
+ const msg = err instanceof Error ? err.message : "unknown error";
422
+ if (/safety|policy|moderation|blocked|SAFETY|PROHIBITED/i.test(msg)) {
423
+ throw new ImageGenerationContentPolicyError(modelIdOf(model), msg);
424
+ }
425
+ throw new ImageGenerationProviderError(modelIdOf(model), msg, { cause: err });
426
+ }
427
+ } finally {
428
+ logger.timeEnd(timer, { model: modelIdOf(model) });
429
+ }
430
+ };
431
+
432
+ // src/ai/common/Gemini_ImageGenerate.ts
433
+ import { ImageGenerationContentPolicyError as ImageGenerationContentPolicyError2, ImageGenerationProviderError as ImageGenerationProviderError2 } from "@workglow/ai";
434
+ import { getLogger as getLogger2 } from "@workglow/util/worker";
435
+ import { dataUriToImageValue as dataUriToImageValue2 } from "@workglow/ai/provider-utils";
436
+ function modelIdOf2(model) {
437
+ return model?.model_id ?? model?.provider_config?.model_name ?? "gemini";
438
+ }
439
+ async function decodeInlineImage2(mimeType, data) {
440
+ return dataUriToImageValue2(`data:${mimeType};base64,${data}`);
441
+ }
442
+ var Gemini_ImageGenerate_Stream = async (input, model, signal, emit) => {
443
+ const logger = getLogger2();
444
+ const timer = `gemini:ImageGenerate:${modelIdOf2(model)}`;
445
+ logger.time(timer, { model: modelIdOf2(model) });
446
+ try {
447
+ const GoogleGenerativeAI = await loadGeminiSDK();
448
+ const genAI = new GoogleGenerativeAI(getApiKey(model));
449
+ const modelName = getModelName(model);
450
+ const genModel = genAI.getGenerativeModel({ model: modelName });
451
+ const parts = [{ text: input.prompt }];
452
+ try {
453
+ const result = await genModel.generateContent({ contents: [{ role: "user", parts }] }, {
454
+ signal
455
+ });
456
+ const response = result.response;
457
+ if (!response.candidates || response.candidates.length === 0 || response.promptFeedback?.blockReason) {
458
+ const reason = response.promptFeedback?.blockReason ?? "SAFETY";
459
+ throw new ImageGenerationContentPolicyError2(modelIdOf2(model), `Blocked: ${reason}`);
460
+ }
461
+ const candidateParts = response.candidates[0]?.content?.parts ?? [];
462
+ const imagePart = candidateParts.find((p) => p.inlineData && p.inlineData.mimeType && p.inlineData.data);
463
+ if (!imagePart) {
464
+ throw new ImageGenerationProviderError2(modelIdOf2(model), "No image part in response (Gemini did not return an inline image)");
465
+ }
466
+ const image = await decodeInlineImage2(imagePart.inlineData.mimeType, imagePart.inlineData.data);
467
+ emit({ type: "snapshot", data: { image } });
468
+ emit({ type: "finish", data: {} });
469
+ } catch (err) {
470
+ if (err instanceof ImageGenerationProviderError2 || err instanceof ImageGenerationContentPolicyError2) {
471
+ throw err;
472
+ }
473
+ const msg = err instanceof Error ? err.message : "unknown error";
474
+ if (/safety|policy|moderation|blocked|SAFETY|PROHIBITED/i.test(msg)) {
475
+ throw new ImageGenerationContentPolicyError2(modelIdOf2(model), msg);
476
+ }
477
+ throw new ImageGenerationProviderError2(modelIdOf2(model), msg, { cause: err });
478
+ }
479
+ } finally {
480
+ logger.timeEnd(timer, { model: modelIdOf2(model) });
481
+ }
482
+ };
483
+
484
+ // src/ai/common/Gemini_ModelInfo.ts
485
+ var GEMINI_EMBEDDING_DIMENSIONS = {
486
+ "text-embedding-004": { native_dimensions: 768, mrl: true },
487
+ "embedding-001": { native_dimensions: 768, mrl: false }
488
+ };
489
+ var Gemini_ModelInfo_Stream = async (input, model, _signal, emit) => {
490
+ if (input.detail === "dimensions") {
491
+ const pc = model?.provider_config;
492
+ let native_dimensions = typeof pc?.native_dimensions === "number" ? pc.native_dimensions : undefined;
493
+ let mrl = typeof pc?.mrl === "boolean" ? pc.mrl : undefined;
494
+ if (native_dimensions === undefined) {
495
+ const modelName = pc?.model_name ?? "";
496
+ const known = GEMINI_EMBEDDING_DIMENSIONS[modelName];
497
+ if (known) {
498
+ native_dimensions = known.native_dimensions;
499
+ mrl = mrl ?? known.mrl;
500
+ }
501
+ }
502
+ emit({
503
+ type: "finish",
504
+ data: {
505
+ model: input.model,
506
+ is_local: false,
507
+ is_remote: true,
508
+ supports_browser: true,
509
+ supports_node: true,
510
+ is_cached: false,
511
+ is_loaded: false,
512
+ file_sizes: null,
513
+ ...native_dimensions !== undefined ? { native_dimensions } : {},
514
+ ...mrl !== undefined ? { mrl } : {}
515
+ }
516
+ });
517
+ return;
518
+ }
519
+ emit({
520
+ type: "finish",
521
+ data: {
522
+ model: input.model,
523
+ is_local: false,
524
+ is_remote: true,
525
+ supports_browser: true,
526
+ supports_node: true,
527
+ is_cached: false,
528
+ is_loaded: false,
529
+ file_sizes: null
530
+ }
531
+ });
532
+ };
533
+
534
+ // src/ai/common/Gemini_StructuredGeneration.ts
535
+ import { parsePartialJson } from "@workglow/util/worker";
536
+ var Gemini_StructuredGeneration_Stream = async (input, model, signal, emit, outputSchema) => {
537
+ const GoogleGenerativeAI = await loadGeminiSDK();
538
+ const genAI = new GoogleGenerativeAI(getApiKey(model));
539
+ const schema = input.outputSchema ?? outputSchema;
540
+ const sanitizedSchema = sanitizeSchemaForGemini(schema);
541
+ const genModel = genAI.getGenerativeModel({
542
+ model: getModelName(model),
543
+ generationConfig: {
544
+ responseMimeType: "application/json",
545
+ responseSchema: sanitizedSchema,
546
+ maxOutputTokens: input.maxTokens,
547
+ temperature: input.temperature
548
+ }
549
+ });
550
+ const result = await genModel.generateContentStream({ contents: [{ role: "user", parts: [{ text: input.prompt }] }] }, { signal });
551
+ let accumulatedJson = "";
552
+ for await (const chunk of result.stream) {
553
+ const text = chunk.text();
554
+ if (text) {
555
+ accumulatedJson += text;
556
+ const partial = parsePartialJson(accumulatedJson);
557
+ if (partial !== undefined) {
558
+ emit({ type: "object-delta", port: "object", objectDelta: partial });
559
+ }
560
+ }
561
+ }
562
+ let finalObject;
563
+ try {
564
+ finalObject = JSON.parse(accumulatedJson);
565
+ } catch {
566
+ finalObject = parsePartialJson(accumulatedJson) ?? {};
567
+ }
568
+ emit({ type: "finish", data: { object: finalObject } });
569
+ };
570
+
571
+ // src/ai/common/Gemini_TextEmbedding.ts
572
+ import { getLogger as getLogger3 } from "@workglow/util/worker";
573
+ var Gemini_TextEmbedding_Stream = async (input, model, _signal, emit) => {
574
+ const logger = getLogger3();
575
+ const timerLabel = `gemini:TextEmbedding:${model?.provider_config?.model_name}`;
576
+ logger.time(timerLabel, { model: model?.provider_config?.model_name });
577
+ try {
578
+ const GoogleGenerativeAI = await loadGeminiSDK();
579
+ const genAI = new GoogleGenerativeAI(getApiKey(model));
580
+ const embeddingModel = genAI.getGenerativeModel({
581
+ model: getModelName(model)
582
+ });
583
+ const taskType = model?.provider_config?.embedding_task_type || "RETRIEVAL_DOCUMENT";
584
+ if (Array.isArray(input.text)) {
585
+ const result2 = await embeddingModel.batchEmbedContents({
586
+ requests: input.text.map((t) => ({
587
+ content: { role: "user", parts: [{ text: t }] },
588
+ taskType
589
+ }))
590
+ });
591
+ emit({
592
+ type: "finish",
593
+ data: {
594
+ vector: result2.embeddings.map((e) => new Float32Array(e.values))
595
+ }
596
+ });
597
+ return;
598
+ }
599
+ const result = await embeddingModel.embedContent({
600
+ content: { role: "user", parts: [{ text: input.text }] },
601
+ taskType
602
+ });
603
+ emit({
604
+ type: "finish",
605
+ data: { vector: new Float32Array(result.embedding.values) }
606
+ });
607
+ } finally {
608
+ logger.timeEnd(timerLabel, { model: model?.provider_config?.model_name });
609
+ }
610
+ };
611
+
612
+ // src/ai/common/Gemini_TextGeneration.ts
613
+ import { getLogger as getLogger4 } from "@workglow/util/worker";
614
+
615
+ // src/ai/common/Gemini_ToolCalling.ts
616
+ import { buildToolDescription, filterValidToolCalls } from "@workglow/ai/worker";
617
+ function buildGeminiContents(messages, prompt) {
618
+ if (!messages || messages.length === 0) {
619
+ return [{ role: "user", parts: [{ text: prompt }] }];
620
+ }
621
+ const toolUseNames = new Map;
622
+ for (const msg of messages) {
623
+ if (msg.role !== "assistant")
624
+ continue;
625
+ for (const block of msg.content) {
626
+ if (block.type === "tool_use") {
627
+ toolUseNames.set(block.id, block.name);
628
+ }
629
+ }
630
+ }
631
+ const contents = [];
632
+ for (const msg of messages) {
633
+ if (msg.role === "user") {
634
+ const parts = [];
635
+ for (const block of msg.content) {
636
+ if (block.type === "text") {
637
+ parts.push({ text: block.text });
638
+ } else if (block.type === "image") {
639
+ parts.push({ inlineData: { mimeType: block.mimeType, data: block.data } });
640
+ }
641
+ }
642
+ contents.push({ role: "user", parts });
643
+ } else if (msg.role === "assistant") {
644
+ const parts = [];
645
+ for (const block of msg.content) {
646
+ if (block.type === "text" && block.text) {
647
+ parts.push({ text: block.text });
648
+ } else if (block.type === "tool_use") {
649
+ parts.push({ functionCall: { name: block.name, args: block.input } });
650
+ }
651
+ }
652
+ if (parts.length > 0)
653
+ contents.push({ role: "model", parts });
654
+ } else if (msg.role === "tool") {
655
+ const parts = [];
656
+ for (const block of msg.content) {
657
+ if (block.type !== "tool_result")
658
+ continue;
659
+ const name = toolUseNames.get(block.tool_use_id) ?? "unknown";
660
+ const textContent = block.content.filter((b) => b.type === "text").map((b) => b.text).join("");
661
+ let response;
662
+ try {
663
+ response = JSON.parse(textContent);
664
+ } catch {
665
+ response = { result: textContent };
666
+ }
667
+ parts.push({ functionResponse: { name, response } });
668
+ }
669
+ if (parts.length > 0)
670
+ contents.push({ role: "user", parts });
671
+ }
672
+ }
673
+ return contents;
674
+ }
675
+ function mapGeminiToolConfig(toolChoice) {
676
+ if (!toolChoice || toolChoice === "auto") {
677
+ return { functionCallingConfig: { mode: "AUTO" } };
678
+ }
679
+ if (toolChoice === "none") {
680
+ return { functionCallingConfig: { mode: "NONE" } };
681
+ }
682
+ if (toolChoice === "required") {
683
+ return { functionCallingConfig: { mode: "ANY" } };
684
+ }
685
+ return {
686
+ functionCallingConfig: {
687
+ mode: "ANY",
688
+ allowedFunctionNames: [toolChoice]
689
+ }
690
+ };
691
+ }
692
+ var Gemini_ToolCalling_Stream = async (input, model, signal, emit) => {
693
+ const GoogleGenerativeAI = await loadGeminiSDK();
694
+ const genAI = new GoogleGenerativeAI(getApiKey(model));
695
+ const functionDeclarations = input.tools.map((t) => ({
696
+ name: t.name,
697
+ description: buildToolDescription(t),
698
+ parameters: sanitizeSchemaForGemini(t.inputSchema)
699
+ }));
700
+ const toolConfig = mapGeminiToolConfig(input.toolChoice);
701
+ const genModel = genAI.getGenerativeModel({
702
+ model: getModelName(model),
703
+ tools: [{ functionDeclarations }],
704
+ toolConfig,
705
+ systemInstruction: input.systemPrompt || undefined,
706
+ generationConfig: {
707
+ maxOutputTokens: input.maxTokens,
708
+ temperature: input.temperature
709
+ }
710
+ });
711
+ const contents = buildGeminiContents(input.messages, input.prompt);
712
+ const result = await genModel.generateContentStream({ contents }, { signal });
713
+ let callIndex = 0;
714
+ for await (const chunk of result.stream) {
715
+ const parts = chunk.candidates?.[0]?.content?.parts ?? [];
716
+ for (const part of parts) {
717
+ if ("text" in part && part.text) {
718
+ emit({ type: "text-delta", port: "text", textDelta: part.text });
719
+ }
720
+ if ("functionCall" in part && part.functionCall) {
721
+ const id = `call_${callIndex++}`;
722
+ const validated = filterValidToolCalls([
723
+ {
724
+ id,
725
+ name: part.functionCall.name,
726
+ input: part.functionCall.args ?? {}
727
+ }
728
+ ], input.tools);
729
+ if (validated.length > 0) {
730
+ emit({
731
+ type: "object-delta",
732
+ port: "toolCalls",
733
+ objectDelta: validated
734
+ });
735
+ }
736
+ }
737
+ }
738
+ }
739
+ emit({ type: "finish", data: { text: "", toolCalls: [] } });
740
+ };
741
+
742
+ // src/ai/common/Gemini_TextGeneration.ts
743
+ var Gemini_TextGeneration_Stream = async (input, model, signal, emit) => {
744
+ const logger = getLogger4();
745
+ const timerLabel = `gemini:TextGeneration:${getModelName(model)}`;
746
+ logger.time(timerLabel, { model: getModelName(model) });
747
+ try {
748
+ signal?.throwIfAborted?.();
749
+ const unified = input;
750
+ const hasMessages = Array.isArray(unified.messages) && unified.messages.length > 0;
751
+ const GoogleGenerativeAI = await loadGeminiSDK();
752
+ const genAI = new GoogleGenerativeAI(getApiKey(model));
753
+ if (hasMessages) {
754
+ const genModel = genAI.getGenerativeModel({
755
+ model: getModelName(model),
756
+ systemInstruction: unified.systemPrompt || undefined,
757
+ generationConfig: {
758
+ maxOutputTokens: input.maxTokens,
759
+ temperature: input.temperature
760
+ }
761
+ });
762
+ const contents = buildGeminiContents(unified.messages, unified.prompt ?? "");
763
+ const result = await genModel.generateContentStream({ contents }, { signal });
764
+ for await (const chunk of result.stream) {
765
+ const text = chunk.text();
766
+ if (text) {
767
+ emit({ type: "text-delta", port: "text", textDelta: text });
768
+ }
769
+ }
770
+ } else {
771
+ const genModel = genAI.getGenerativeModel({
772
+ model: getModelName(model),
773
+ generationConfig: {
774
+ maxOutputTokens: input.maxTokens,
775
+ temperature: input.temperature,
776
+ topP: input.topP
777
+ }
778
+ });
779
+ const result = await genModel.generateContentStream({ contents: [{ role: "user", parts: [{ text: input.prompt }] }] }, { signal });
780
+ for await (const chunk of result.stream) {
781
+ const text = chunk.text();
782
+ if (text) {
783
+ emit({ type: "text-delta", port: "text", textDelta: text });
784
+ }
785
+ }
786
+ }
787
+ emit({ type: "finish", data: {} });
788
+ } finally {
789
+ logger.timeEnd(timerLabel, { model: getModelName(model) });
790
+ }
791
+ };
792
+
793
+ // src/ai/common/Gemini_TextRewriter.ts
794
+ var Gemini_TextRewriter_Stream = async (input, model, signal, emit) => {
795
+ const GoogleGenerativeAI = await loadGeminiSDK();
796
+ const genAI = new GoogleGenerativeAI(getApiKey(model));
797
+ const genModel = genAI.getGenerativeModel({
798
+ model: getModelName(model),
799
+ systemInstruction: input.prompt
800
+ });
801
+ const result = await genModel.generateContentStream({ contents: [{ role: "user", parts: [{ text: input.text }] }] }, { signal });
802
+ for await (const chunk of result.stream) {
803
+ const text = chunk.text();
804
+ if (text) {
805
+ emit({ type: "text-delta", port: "text", textDelta: text });
806
+ }
807
+ }
808
+ emit({ type: "finish", data: {} });
809
+ };
810
+
811
+ // src/ai/common/Gemini_TextSummary.ts
812
+ var Gemini_TextSummary_Stream = async (input, model, signal, emit) => {
813
+ const GoogleGenerativeAI = await loadGeminiSDK();
814
+ const genAI = new GoogleGenerativeAI(getApiKey(model));
815
+ const genModel = genAI.getGenerativeModel({
816
+ model: getModelName(model),
817
+ systemInstruction: "Summarize the following text concisely."
818
+ });
819
+ const result = await genModel.generateContentStream({ contents: [{ role: "user", parts: [{ text: input.text }] }] }, { signal });
820
+ for await (const chunk of result.stream) {
821
+ const text = chunk.text();
822
+ if (text) {
823
+ emit({ type: "text-delta", port: "text", textDelta: text });
824
+ }
825
+ }
826
+ emit({ type: "finish", data: {} });
827
+ };
828
+
829
+ // src/ai/common/Gemini_JobRunFns.ts
830
+ var GEMINI_RUN_FNS = [
831
+ { serves: GEMINI_TEXT_GENERATION, runFn: Gemini_TextGeneration_Stream },
832
+ { serves: GEMINI_TOOL_USE, runFn: Gemini_ToolCalling_Stream },
833
+ { serves: GEMINI_JSON_MODE, runFn: Gemini_StructuredGeneration_Stream },
834
+ { serves: GEMINI_TEXT_REWRITER, runFn: Gemini_TextRewriter_Stream },
835
+ { serves: GEMINI_TEXT_SUMMARY, runFn: Gemini_TextSummary_Stream },
836
+ { serves: GEMINI_TEXT_EMBEDDING, runFn: Gemini_TextEmbedding_Stream },
837
+ { serves: GEMINI_IMAGE_GENERATION, runFn: Gemini_ImageGenerate_Stream },
838
+ { serves: GEMINI_IMAGE_EDITING, runFn: Gemini_ImageEdit_Stream },
839
+ { serves: GEMINI_COUNT_TOKENS, runFn: Gemini_CountTokens_Stream },
840
+ { serves: GEMINI_MODEL_SEARCH, runFn: Gemini_ModelSearch_Stream },
841
+ { serves: GEMINI_MODEL_INFO, runFn: Gemini_ModelInfo_Stream }
842
+ ];
843
+ var GEMINI_PREVIEW_TASKS = {
844
+ CountTokensTask: Gemini_CountTokens_Preview
845
+ };
846
+
847
+ // src/ai/index.ts
848
+ var _testOnly = {
849
+ GoogleGeminiQueuedProvider,
850
+ GEMINI_RUN_FN_SPECS,
851
+ GEMINI_RUN_FNS
852
+ };
222
853
  export {
223
854
  registerGeminiImageValidator,
224
855
  registerGemini,
225
- Gemini_ModelSearch,
856
+ _testOnly,
857
+ Gemini_ModelSearch_Stream,
226
858
  GeminiModelSchema,
227
859
  GeminiModelRecordSchema,
228
860
  GeminiModelConfigSchema,
229
- GOOGLE_GEMINI
861
+ GOOGLE_GEMINI,
862
+ GEMINI_FALLBACK_MODELS
230
863
  };
231
864
 
232
- //# debugId=84E9A60003FFA1DA64756E2164756E21
865
+ //# debugId=22A7AC7F93C851F664756E2164756E21