@umituz/react-native-ai-gemini-provider 1.10.1 → 1.10.4

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,12 +1,13 @@
1
1
  {
2
2
  "name": "@umituz/react-native-ai-gemini-provider",
3
- "version": "1.10.1",
3
+ "version": "1.10.4",
4
4
  "description": "Google Gemini AI provider for React Native applications",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
7
7
  "scripts": {
8
- "typecheck": "echo 'TypeScript validation passed'",
9
- "lint": "echo 'Lint passed'",
8
+ "typecheck": "tsc --noEmit",
9
+ "lint": "eslint src --ext .ts,.tsx --max-warnings 0",
10
+ "lint:fix": "eslint src --ext .ts,.tsx --fix",
10
11
  "version:patch": "npm version patch -m 'chore: release v%s'",
11
12
  "version:minor": "npm version minor -m 'chore: release v%s'",
12
13
  "version:major": "npm version major -m 'chore: release v%s'"
@@ -33,10 +34,13 @@
33
34
  },
34
35
  "devDependencies": {
35
36
  "@google/generative-ai": "^0.21.0",
37
+ "@typescript-eslint/eslint-plugin": "^7.0.0",
38
+ "@typescript-eslint/parser": "^7.0.0",
39
+ "eslint": "^8.57.0",
36
40
  "@types/react": "~19.1.10",
37
41
  "react": "19.1.0",
38
42
  "react-native": "0.81.5",
39
- "typescript": "~5.9.2"
43
+ "typescript": "^5.3.0"
40
44
  },
41
45
  "publishConfig": {
42
46
  "access": "public"
@@ -4,31 +4,17 @@
4
4
  */
5
5
 
6
6
  import type {
7
- GeminiConfig,
8
7
  GeminiImageInput,
9
8
  GeminiImageGenerationResult,
10
9
  } from "../../domain/entities";
11
- import { geminiClientCoreService } from "./gemini-client-core.service";
12
- import { geminiTextGenerationService } from "./gemini-text-generation.service";
13
10
  import { geminiImageGenerationService } from "./gemini-image-generation.service";
14
11
  import { geminiImageEditService } from "./gemini-image-edit.service";
15
- import { JobManager } from "../job/JobManager";
16
- import { ContentBuilder } from "../content/ContentBuilder";
17
- import { ResponseFormatter } from "../response/ResponseFormatter";
12
+ import { providerInitializer, type AIProviderConfig } from "./provider-initializer";
13
+ import { jobProcessor } from "./job-processor";
14
+ import { generationExecutor } from "./generation-executor";
18
15
  import type { JobSubmission, JobStatus } from "../job/JobManager";
19
16
 
20
- declare const __DEV__: boolean;
21
-
22
- export interface AIProviderConfig {
23
- apiKey: string;
24
- maxRetries?: number;
25
- baseDelay?: number;
26
- maxDelay?: number;
27
- defaultTimeoutMs?: number;
28
- textModel?: string;
29
- textToImageModel?: string;
30
- imageEditModel?: string;
31
- }
17
+ export type { AIProviderConfig, JobSubmission, JobStatus };
32
18
 
33
19
  export interface SubscribeOptions<T = unknown> {
34
20
  timeoutMs?: number;
@@ -41,59 +27,24 @@ export class GeminiProvider {
41
27
  readonly providerId = "gemini";
42
28
  readonly providerName = "Google Gemini";
43
29
 
44
- private jobManager = new JobManager();
45
- private contentBuilder = new ContentBuilder();
46
- private responseFormatter = new ResponseFormatter();
47
-
48
30
  initialize(config: AIProviderConfig): void {
49
- if (typeof __DEV__ !== "undefined" && __DEV__) {
50
- // eslint-disable-next-line no-console
51
- console.log("[GeminiProvider] Initializing...");
52
- }
53
-
54
- const geminiConfig: GeminiConfig = {
55
- apiKey: config.apiKey,
56
- maxRetries: config.maxRetries,
57
- baseDelay: config.baseDelay,
58
- maxDelay: config.maxDelay,
59
- defaultTimeoutMs: config.defaultTimeoutMs,
60
- textModel: config.textModel,
61
- textToImageModel: config.textToImageModel,
62
- imageEditModel: config.imageEditModel,
63
- };
64
-
65
- geminiClientCoreService.initialize(geminiConfig);
31
+ providerInitializer.initialize(config);
66
32
  }
67
33
 
68
34
  isInitialized(): boolean {
69
- return geminiClientCoreService.isInitialized();
35
+ return providerInitializer.isInitialized();
70
36
  }
71
37
 
72
38
  submitJob(model: string, input: Record<string, unknown>): Promise<JobSubmission> {
73
- const submission = this.jobManager.submitJob(model, input);
74
-
75
- this.processJobAsync(submission.requestId).catch((error) => {
76
- if (typeof __DEV__ !== "undefined" && __DEV__) {
77
- // eslint-disable-next-line no-console
78
- console.error("[GeminiProvider] Job failed:", error);
79
- }
80
- });
81
-
82
- return Promise.resolve(submission);
39
+ return jobProcessor.submitJob(model, input);
83
40
  }
84
41
 
85
42
  getJobStatus(_model: string, requestId: string): Promise<JobStatus> {
86
- const status = this.jobManager.getJobStatus(requestId);
87
- return Promise.resolve(status);
43
+ return jobProcessor.getJobStatus(_model, requestId);
88
44
  }
89
45
 
90
46
  getJobResult<T = unknown>(_model: string, requestId: string): Promise<T> {
91
- try {
92
- const result = this.jobManager.getJobResult<T>(requestId);
93
- return Promise.resolve(result);
94
- } catch (error) {
95
- return Promise.reject(error);
96
- }
47
+ return jobProcessor.getJobResult<T>(_model, requestId);
97
48
  }
98
49
 
99
50
  async subscribe<T = unknown>(
@@ -104,7 +55,7 @@ export class GeminiProvider {
104
55
  options?.onQueueUpdate?.({ status: "IN_QUEUE" });
105
56
  options?.onProgress?.(10);
106
57
 
107
- const result = await this.executeGeneration<T>(model, input);
58
+ const result = await generationExecutor.executeGeneration<T>(model, input);
108
59
 
109
60
  options?.onProgress?.(100);
110
61
  options?.onQueueUpdate?.({ status: "COMPLETED" });
@@ -117,7 +68,7 @@ export class GeminiProvider {
117
68
  model: string,
118
69
  input: Record<string, unknown>,
119
70
  ): Promise<T> {
120
- return this.executeGeneration<T>(model, input);
71
+ return generationExecutor.executeGeneration<T>(model, input);
121
72
  }
122
73
 
123
74
  async generateImage(prompt: string): Promise<GeminiImageGenerationResult> {
@@ -136,61 +87,12 @@ export class GeminiProvider {
136
87
  prompt: string,
137
88
  images: GeminiImageInput[],
138
89
  ): Promise<{ text: string; response: unknown }> {
139
- const response = await geminiTextGenerationService.generateWithImages(
140
- model,
141
- prompt,
142
- images,
143
- );
144
-
145
- const text = response.candidates?.[0]?.content.parts
146
- .filter((p): p is { text: string } => "text" in p)
147
- .map((p) => p.text)
148
- .join("") || "";
149
-
150
- return { text, response };
90
+ return generationExecutor.generateWithImages(model, prompt, images);
151
91
  }
152
92
 
153
93
  reset(): void {
154
- geminiClientCoreService.reset();
155
- this.jobManager.clear();
156
- }
157
-
158
- private async processJobAsync(requestId: string): Promise<void> {
159
- const job = this.jobManager.getJob(requestId);
160
- if (!job) return;
161
-
162
- this.jobManager.updateJobStatus(requestId, "IN_PROGRESS");
163
-
164
- try {
165
- const result = await this.executeGeneration(job.model, job.input);
166
- this.jobManager.setJobResult(requestId, result);
167
- } catch (error) {
168
- const errorMessage = error instanceof Error ? error.message : String(error);
169
- this.jobManager.setJobError(requestId, errorMessage);
170
- }
171
- }
172
-
173
- private async executeGeneration<T>(
174
- model: string,
175
- input: Record<string, unknown>,
176
- ): Promise<T> {
177
- const isImageGeneration = input.generateImage === true || input.type === "image";
178
-
179
- if (isImageGeneration) {
180
- const prompt = String(input.prompt || "");
181
- const images = input.images as GeminiImageInput[] | undefined;
182
- const result = await geminiImageGenerationService.generateImage(prompt, images);
183
- return result as T;
184
- }
185
-
186
- const contents = this.contentBuilder.buildContents(input);
187
- const response = await geminiTextGenerationService.generateContent(
188
- model,
189
- contents,
190
- input.generationConfig as undefined,
191
- );
192
-
193
- return this.responseFormatter.formatResponse<T>(response, input);
94
+ providerInitializer.reset();
95
+ jobProcessor.clear();
194
96
  }
195
97
  }
196
98
 
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Generation Executor
3
+ * Handles execution of different generation types
4
+ */
5
+
6
+ import type {
7
+ GeminiImageInput,
8
+ } from "../../domain/entities";
9
+ import { geminiTextGenerationService } from "./gemini-text-generation.service";
10
+ import { geminiImageGenerationService } from "./gemini-image-generation.service";
11
+ import { ContentBuilder } from "../content/ContentBuilder";
12
+ import { ResponseFormatter } from "../response/ResponseFormatter";
13
+
14
+ export class GenerationExecutor {
15
+ private contentBuilder = new ContentBuilder();
16
+ private responseFormatter = new ResponseFormatter();
17
+
18
+ async executeGeneration<T>(
19
+ model: string,
20
+ input: Record<string, unknown>,
21
+ ): Promise<T> {
22
+ const isImageGeneration = input.generateImage === true || input.type === "image";
23
+
24
+ if (isImageGeneration) {
25
+ const prompt = String(input.prompt || "");
26
+ const images = input.images as GeminiImageInput[] | undefined;
27
+ const result = await geminiImageGenerationService.generateImage(prompt, images);
28
+ return result as T;
29
+ }
30
+
31
+ const contents = this.contentBuilder.buildContents(input);
32
+ const response = await geminiTextGenerationService.generateContent(
33
+ model,
34
+ contents,
35
+ input.generationConfig as undefined,
36
+ );
37
+
38
+ return this.responseFormatter.formatResponse<T>(response, input);
39
+ }
40
+
41
+ async generateWithImages(
42
+ model: string,
43
+ prompt: string,
44
+ images: GeminiImageInput[],
45
+ ): Promise<{ text: string; response: unknown }> {
46
+ const response = await geminiTextGenerationService.generateWithImages(
47
+ model,
48
+ prompt,
49
+ images,
50
+ );
51
+
52
+ const text = response.candidates?.[0]?.content.parts
53
+ .filter((p): p is { text: string } => "text" in p)
54
+ .map((p) => p.text)
55
+ .join("") || "";
56
+
57
+ return { text, response };
58
+ }
59
+ }
60
+
61
+ export const generationExecutor = new GenerationExecutor();
@@ -10,6 +10,11 @@ export { geminiImageGenerationService } from "./gemini-image-generation.service"
10
10
  export { geminiImageEditService } from "./gemini-image-edit.service";
11
11
  export { geminiStreamingService } from "./gemini-streaming.service";
12
12
 
13
+ // Modular services
14
+ export { providerInitializer } from "./provider-initializer";
15
+ export { jobProcessor } from "./job-processor";
16
+ export { generationExecutor } from "./generation-executor";
17
+
13
18
  // Public provider API
14
19
  export {
15
20
  geminiProviderService,
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Job Processor
3
+ * Handles async job processing
4
+ */
5
+
6
+ import { JobManager } from "../job/JobManager";
7
+ import type { JobSubmission, JobStatus } from "../job/JobManager";
8
+ import { generationExecutor } from "./generation-executor";
9
+
10
+ declare const __DEV__: boolean;
11
+
12
+ export class JobProcessor {
13
+ private jobManager = new JobManager();
14
+
15
+ submitJob(model: string, input: Record<string, unknown>): Promise<JobSubmission> {
16
+ const submission = this.jobManager.submitJob(model, input);
17
+
18
+ this.processJobAsync(submission.requestId).catch((error) => {
19
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
20
+ // eslint-disable-next-line no-console
21
+ console.error("[GeminiProvider] Job failed:", error);
22
+ }
23
+ });
24
+
25
+ return Promise.resolve(submission);
26
+ }
27
+
28
+ getJobStatus(_model: string, requestId: string): Promise<JobStatus> {
29
+ const status = this.jobManager.getJobStatus(requestId);
30
+ return Promise.resolve(status);
31
+ }
32
+
33
+ getJobResult<T = unknown>(_model: string, requestId: string): Promise<T> {
34
+ try {
35
+ const result = this.jobManager.getJobResult<T>(requestId);
36
+ return Promise.resolve(result);
37
+ } catch (error) {
38
+ return Promise.reject(error);
39
+ }
40
+ }
41
+
42
+ clear(): void {
43
+ this.jobManager.clear();
44
+ }
45
+
46
+ private async processJobAsync(requestId: string): Promise<void> {
47
+ const job = this.jobManager.getJob(requestId);
48
+ if (!job) return;
49
+
50
+ this.jobManager.updateJobStatus(requestId, "IN_PROGRESS");
51
+
52
+ try {
53
+ const result = await generationExecutor.executeGeneration(job.model, job.input);
54
+ this.jobManager.setJobResult(requestId, result);
55
+ } catch (error) {
56
+ const errorMessage = error instanceof Error ? error.message : String(error);
57
+ this.jobManager.setJobError(requestId, errorMessage);
58
+ }
59
+ }
60
+ }
61
+
62
+ export const jobProcessor = new JobProcessor();
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Provider Initializer
3
+ * Handles initialization logic for Gemini Provider
4
+ */
5
+
6
+ import type { GeminiConfig } from "../../domain/entities";
7
+ import { geminiClientCoreService } from "./gemini-client-core.service";
8
+
9
+ declare const __DEV__: boolean;
10
+
11
+ export interface AIProviderConfig {
12
+ apiKey: string;
13
+ maxRetries?: number;
14
+ baseDelay?: number;
15
+ maxDelay?: number;
16
+ defaultTimeoutMs?: number;
17
+ textModel?: string;
18
+ textToImageModel?: string;
19
+ imageEditModel?: string;
20
+ }
21
+
22
+ export class ProviderInitializer {
23
+ initialize(config: AIProviderConfig): void {
24
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
25
+ // eslint-disable-next-line no-console
26
+ console.log("[GeminiProvider] Initializing...");
27
+ }
28
+
29
+ const geminiConfig: GeminiConfig = {
30
+ apiKey: config.apiKey,
31
+ maxRetries: config.maxRetries,
32
+ baseDelay: config.baseDelay,
33
+ maxDelay: config.maxDelay,
34
+ defaultTimeoutMs: config.defaultTimeoutMs,
35
+ textModel: config.textModel,
36
+ textToImageModel: config.textToImageModel,
37
+ imageEditModel: config.imageEditModel,
38
+ };
39
+
40
+ geminiClientCoreService.initialize(geminiConfig);
41
+ }
42
+
43
+ isInitialized(): boolean {
44
+ return geminiClientCoreService.isInitialized();
45
+ }
46
+
47
+ reset(): void {
48
+ geminiClientCoreService.reset();
49
+ }
50
+ }
51
+
52
+ export const providerInitializer = new ProviderInitializer();
@@ -15,7 +15,6 @@ import {
15
15
  getQualityOptimizedConfig,
16
16
  } from "./ProviderConfig";
17
17
 
18
- declare const __DEV__: boolean;
19
18
 
20
19
  export type OptimizationStrategy = "cost" | "quality" | "balanced";
21
20
 
@@ -49,15 +48,7 @@ class ProviderFactory {
49
48
 
50
49
  this.currentConfig = config;
51
50
 
52
- if (typeof __DEV__ !== "undefined" && __DEV__) {
53
- console.log("[ProviderFactory] Initializing with config:", {
54
- tier: config.subscriptionTier,
55
- strategy: options.strategy || "balanced",
56
- textModel: config.textModel,
57
- imageEditModel: config.imageEditModel,
58
- maxRetries: config.maxRetries,
59
- });
60
- }
51
+ this.currentConfig = config;
61
52
 
62
53
  // Initialize Gemini client with resolved config
63
54
  const geminiConfig: GeminiConfig = {
@@ -72,9 +63,7 @@ class ProviderFactory {
72
63
 
73
64
  geminiClientCoreService.initialize(geminiConfig);
74
65
 
75
- if (typeof __DEV__ !== "undefined" && __DEV__) {
76
- console.log("[ProviderFactory] Provider initialized successfully");
77
- }
66
+ geminiClientCoreService.initialize(geminiConfig);
78
67
  }
79
68
 
80
69
  /**