@umituz/react-native-ai-gemini-provider 2.0.32 → 2.1.0

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": "2.0.32",
3
+ "version": "2.1.0",
4
4
  "description": "Google Gemini AI text generation provider for React Native applications",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -9,8 +9,44 @@ import type {
9
9
  GeminiFinishReason,
10
10
  GeminiSafetyRating,
11
11
  GeminiResponse,
12
+ GeminiHarmCategory,
12
13
  } from "../../domain/entities";
13
14
 
15
+ const VALID_FINISH_REASONS: readonly string[] = [
16
+ "FINISH_REASON_UNSPECIFIED",
17
+ "STOP",
18
+ "MAX_TOKENS",
19
+ "SAFETY",
20
+ "RECITATION",
21
+ "OTHER",
22
+ ] as const;
23
+
24
+ const VALID_HARM_CATEGORIES: readonly string[] = [
25
+ "HARM_CATEGORY_HARASSMENT",
26
+ "HARM_CATEGORY_HATE_SPEECH",
27
+ "HARM_CATEGORY_SEXUALLY_EXPLICIT",
28
+ "HARM_CATEGORY_DANGEROUS_CONTENT",
29
+ ] as const;
30
+
31
+ const VALID_PROBABILITIES: readonly string[] = [
32
+ "NEGLIGIBLE",
33
+ "LOW",
34
+ "MEDIUM",
35
+ "HIGH",
36
+ ] as const;
37
+
38
+ function isValidFinishReason(value: string): value is GeminiFinishReason {
39
+ return VALID_FINISH_REASONS.includes(value);
40
+ }
41
+
42
+ function isValidHarmCategory(value: string): value is GeminiHarmCategory {
43
+ return VALID_HARM_CATEGORIES.includes(value);
44
+ }
45
+
46
+ function isValidProbability(value: string): value is GeminiSafetyRating["probability"] {
47
+ return VALID_PROBABILITIES.includes(value);
48
+ }
49
+
14
50
  /**
15
51
  * Convert domain content to SDK format
16
52
  */
@@ -62,21 +98,28 @@ export function transformCandidate(
62
98
  }
63
99
  }
64
100
 
65
- const finishReason: GeminiFinishReason | undefined = candidate.finishReason
66
- ? (candidate.finishReason as GeminiFinishReason)
67
- : undefined;
101
+ const finishReason: GeminiFinishReason | undefined =
102
+ candidate.finishReason && isValidFinishReason(candidate.finishReason)
103
+ ? candidate.finishReason
104
+ : undefined;
68
105
 
69
106
  const safetyRatings: GeminiSafetyRating[] | undefined = candidate.safetyRatings
70
- ? candidate.safetyRatings.map((rating) => ({
71
- category: rating.category as GeminiSafetyRating["category"],
72
- probability: rating.probability as GeminiSafetyRating["probability"],
73
- }))
107
+ ? candidate.safetyRatings
108
+ .filter((rating) => isValidHarmCategory(rating.category) && isValidProbability(rating.probability))
109
+ .map((rating) => ({
110
+ category: rating.category as GeminiHarmCategory,
111
+ probability: rating.probability as GeminiSafetyRating["probability"],
112
+ }))
74
113
  : undefined;
75
114
 
115
+ const role = candidate.content.role === "user" || candidate.content.role === "model"
116
+ ? candidate.content.role
117
+ : "model";
118
+
76
119
  return {
77
120
  content: {
78
121
  parts: transformedParts,
79
- role: (candidate.content.role || "model") as "user" | "model",
122
+ role,
80
123
  },
81
124
  finishReason,
82
125
  safetyRatings,
@@ -71,12 +71,18 @@ export function measureSync<T>(
71
71
  }
72
72
  }
73
73
 
74
+ interface DebouncedFunction<T extends (...args: never[]) => unknown> {
75
+ (...args: Parameters<T>): void;
76
+ cancel: () => void;
77
+ }
78
+
74
79
  export function debounce<T extends (...args: never[]) => unknown>(
75
80
  func: T,
76
81
  wait: number,
77
- ): (...args: Parameters<T>) => void {
82
+ ): DebouncedFunction<T> {
78
83
  let timeout: ReturnType<typeof setTimeout> | undefined;
79
- return (...args: Parameters<T>) => {
84
+
85
+ const debounced = (...args: Parameters<T>) => {
80
86
  const later = () => {
81
87
  timeout = undefined;
82
88
  func(...args);
@@ -86,19 +92,48 @@ export function debounce<T extends (...args: never[]) => unknown>(
86
92
  }
87
93
  timeout = setTimeout(later, wait);
88
94
  };
95
+
96
+ debounced.cancel = () => {
97
+ if (timeout) {
98
+ clearTimeout(timeout);
99
+ timeout = undefined;
100
+ }
101
+ };
102
+
103
+ return debounced;
104
+ }
105
+
106
+ interface ThrottledFunction<T extends (...args: never[]) => unknown> {
107
+ (...args: Parameters<T>): void;
108
+ cancel: () => void;
89
109
  }
90
110
 
91
111
  export function throttle<T extends (...args: never[]) => unknown>(
92
112
  func: T,
93
113
  limit: number,
94
- ): (...args: Parameters<T>) => void {
95
- let inThrottle: boolean;
96
- return (...args: Parameters<T>) => {
114
+ ): ThrottledFunction<T> {
115
+ let inThrottle = false;
116
+ let timeout: ReturnType<typeof setTimeout> | undefined;
117
+
118
+ const throttled = (...args: Parameters<T>) => {
97
119
  if (!inThrottle) {
98
120
  func(...args);
99
121
  inThrottle = true;
100
- setTimeout(() => (inThrottle = false), limit);
122
+ timeout = setTimeout(() => {
123
+ inThrottle = false;
124
+ timeout = undefined;
125
+ }, limit);
126
+ }
127
+ };
128
+
129
+ throttled.cancel = () => {
130
+ if (timeout) {
131
+ clearTimeout(timeout);
132
+ timeout = undefined;
133
+ inThrottle = false;
101
134
  }
102
135
  };
136
+
137
+ return throttled;
103
138
  }
104
139