@umituz/react-native-ai-gemini-provider 1.8.2 → 1.8.3

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-ai-gemini-provider",
3
- "version": "1.8.2",
3
+ "version": "1.8.3",
4
4
  "description": "Google Gemini AI provider for React Native applications",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -14,11 +14,16 @@ export const GEMINI_MODELS = {
14
14
  PRO: "gemini-1.5-pro",
15
15
  },
16
16
 
17
- // Image generation models (Imagen 4.0)
18
- IMAGE: {
17
+ // Text-to-Image models (Imagen 4.0) - generates images from text only
18
+ TEXT_TO_IMAGE: {
19
19
  DEFAULT: "imagen-4.0-generate-001",
20
20
  },
21
21
 
22
+ // Image editing models (Gemini) - transforms/edits images with input image + prompt
23
+ IMAGE_EDIT: {
24
+ DEFAULT: "gemini-2.0-flash-exp-image-generation",
25
+ },
26
+
22
27
  // Video understanding models
23
28
  VIDEO: {
24
29
  FLASH: "gemini-2.0-flash",
@@ -30,7 +35,8 @@ export const GEMINI_MODELS = {
30
35
  */
31
36
  export const DEFAULT_MODELS = {
32
37
  TEXT: GEMINI_MODELS.TEXT.FLASH,
33
- IMAGE: GEMINI_MODELS.IMAGE.DEFAULT,
38
+ TEXT_TO_IMAGE: GEMINI_MODELS.TEXT_TO_IMAGE.DEFAULT,
39
+ IMAGE_EDIT: GEMINI_MODELS.IMAGE_EDIT.DEFAULT,
34
40
  VIDEO: GEMINI_MODELS.VIDEO.FLASH,
35
41
  } as const;
36
42
 
@@ -23,7 +23,7 @@ const DEFAULT_CONFIG: Partial<GeminiConfig> = {
23
23
  maxDelay: 10000,
24
24
  defaultTimeoutMs: 60000,
25
25
  defaultModel: DEFAULT_MODELS.TEXT,
26
- imageModel: DEFAULT_MODELS.IMAGE,
26
+ imageModel: DEFAULT_MODELS.TEXT_TO_IMAGE,
27
27
  };
28
28
 
29
29
  const RETRYABLE_ERROR_PATTERNS = [
@@ -264,7 +264,7 @@ class GeminiClientService {
264
264
  ): Promise<GeminiImageGenerationResult> {
265
265
  this.validateInitialization();
266
266
 
267
- const imageModel = this.config?.imageModel || DEFAULT_MODELS.IMAGE;
267
+ const imageModel = this.config?.imageModel || DEFAULT_MODELS.TEXT_TO_IMAGE;
268
268
  const apiKey = this.config?.apiKey;
269
269
 
270
270
  if (typeof __DEV__ !== "undefined" && __DEV__) {
@@ -339,6 +339,109 @@ class GeminiClientService {
339
339
  return result;
340
340
  }
341
341
 
342
+ /**
343
+ * Edit/transform image using Gemini generateContent API
344
+ * Takes input image + prompt and generates new image
345
+ */
346
+ async editImage(
347
+ prompt: string,
348
+ images: Array<{ base64: string; mimeType: string }>,
349
+ ): Promise<GeminiImageGenerationResult> {
350
+ this.validateInitialization();
351
+
352
+ const editModel = DEFAULT_MODELS.IMAGE_EDIT;
353
+ const apiKey = this.config?.apiKey;
354
+
355
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
356
+ // eslint-disable-next-line no-console
357
+ console.log("[GeminiClient] editImage() called", {
358
+ model: editModel,
359
+ promptLength: prompt.length,
360
+ imagesCount: images.length,
361
+ });
362
+ }
363
+
364
+ const url = `https://generativelanguage.googleapis.com/v1beta/models/${editModel}:generateContent`;
365
+
366
+ const parts: Array<Record<string, unknown>> = [];
367
+
368
+ for (const image of images) {
369
+ parts.push({
370
+ inlineData: {
371
+ mimeType: image.mimeType,
372
+ data: extractBase64Data(image.base64),
373
+ },
374
+ });
375
+ }
376
+
377
+ parts.push({ text: prompt });
378
+
379
+ const requestBody = {
380
+ contents: [{ parts }],
381
+ generationConfig: {
382
+ responseModalities: ["TEXT", "IMAGE"],
383
+ },
384
+ };
385
+
386
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
387
+ // eslint-disable-next-line no-console
388
+ console.log("[GeminiClient] editImage() request", {
389
+ url,
390
+ partsCount: parts.length,
391
+ });
392
+ }
393
+
394
+ const response = await this.executeWithRetry(async () => {
395
+ const res = await fetch(url, {
396
+ method: "POST",
397
+ headers: {
398
+ "Content-Type": "application/json",
399
+ "x-goog-api-key": apiKey!,
400
+ },
401
+ body: JSON.stringify(requestBody),
402
+ });
403
+
404
+ if (!res.ok) {
405
+ const errorText = await res.text();
406
+ throw new Error(`Image edit API error (${res.status}): ${errorText}`);
407
+ }
408
+
409
+ return res.json();
410
+ });
411
+
412
+ const result: GeminiImageGenerationResult = {
413
+ text: undefined,
414
+ imageUrl: undefined,
415
+ imageBase64: undefined,
416
+ mimeType: "image/png",
417
+ };
418
+
419
+ const candidate = response.candidates?.[0];
420
+ const responseParts = candidate?.content?.parts || [];
421
+
422
+ for (const part of responseParts) {
423
+ if (part.text) {
424
+ result.text = part.text;
425
+ }
426
+ if (part.inlineData) {
427
+ result.imageBase64 = part.inlineData.data;
428
+ result.mimeType = part.inlineData.mimeType || "image/png";
429
+ result.imageUrl = `data:${result.mimeType};base64,${result.imageBase64}`;
430
+ }
431
+ }
432
+
433
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
434
+ // eslint-disable-next-line no-console
435
+ console.log("[GeminiClient] editImage() completed", {
436
+ hasImage: !!result.imageBase64,
437
+ hasText: !!result.text,
438
+ imageDataLength: result.imageBase64?.length ?? 0,
439
+ });
440
+ }
441
+
442
+ return result;
443
+ }
444
+
342
445
  /**
343
446
  * Stream content generation
344
447
  */
@@ -201,14 +201,24 @@ class GeminiProviderService {
201
201
  }
202
202
 
203
203
  /**
204
- * Generate image with optional input images
205
- * Convenience method for image generation
204
+ * Generate image from text only (Imagen API)
205
+ * Use for text-to-image generation without input images
206
206
  */
207
207
  async generateImage(
208
208
  prompt: string,
209
- images?: GeminiImageInput[],
210
209
  ): Promise<GeminiImageGenerationResult> {
211
- return geminiClientService.generateImage(prompt, images);
210
+ return geminiClientService.generateImage(prompt);
211
+ }
212
+
213
+ /**
214
+ * Edit/transform image using input image + prompt (Gemini API)
215
+ * Use for image editing, transformation, style transfer
216
+ */
217
+ async editImage(
218
+ prompt: string,
219
+ images: GeminiImageInput[],
220
+ ): Promise<GeminiImageGenerationResult> {
221
+ return geminiClientService.editImage(prompt, images);
212
222
  }
213
223
 
214
224
  /**