@umituz/react-native-ai-fal-provider 1.0.46 → 1.0.48

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-fal-provider",
3
- "version": "1.0.46",
3
+ "version": "1.0.48",
4
4
  "description": "FAL AI provider for React Native - implements IAIProvider interface for unified AI generation",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
package/src/index.ts CHANGED
@@ -25,7 +25,7 @@ export type { FeatureModelConfig } from "./domain/constants/feature-models.const
25
25
 
26
26
  export {
27
27
  FalProvider, falProvider, falModelsService,
28
- getImageFeatureModel, getVideoFeatureModel,
28
+ getImageFeatureModel, getVideoFeatureModel, NSFWContentError,
29
29
  } from "./infrastructure/services";
30
30
  export type { ModelFetcher } from "./infrastructure/services";
31
31
 
@@ -20,6 +20,7 @@ import type {
20
20
  import type { FalQueueStatus } from "../../domain/entities/fal.types";
21
21
  import { DEFAULT_FAL_CONFIG, FAL_CAPABILITIES } from "./fal-provider.constants";
22
22
  import { mapFalStatusToJobStatus } from "./fal-status-mapper";
23
+ import { NSFWContentError } from "./nsfw-content-error";
23
24
  import { FAL_IMAGE_FEATURE_MODELS, FAL_VIDEO_FEATURE_MODELS } from "../../domain/constants/feature-models.constants";
24
25
  import {
25
26
  buildSingleImageInput,
@@ -119,17 +120,22 @@ export class FalProvider implements IAIProvider {
119
120
  console.log("[FalProvider] Subscribe started:", { model, timeoutMs });
120
121
  }
121
122
 
123
+ let lastStatus = "";
124
+
122
125
  try {
123
126
  const result = await Promise.race([
124
127
  fal.subscribe(model, {
125
128
  input,
126
- logs: true,
129
+ logs: false,
127
130
  pollInterval: DEFAULT_FAL_CONFIG.pollInterval,
128
131
  onQueueUpdate: (update: { status: string; logs?: unknown[] }) => {
129
- if (typeof __DEV__ !== "undefined" && __DEV__) {
130
- console.log("[FalProvider] Queue update:", JSON.stringify(update));
131
- }
132
132
  const jobStatus = mapFalStatusToJobStatus(update as unknown as FalQueueStatus);
133
+ if (jobStatus.status !== lastStatus) {
134
+ lastStatus = jobStatus.status;
135
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
136
+ console.log("[FalProvider] Status:", jobStatus.status);
137
+ }
138
+ }
133
139
  options?.onQueueUpdate?.(jobStatus);
134
140
  },
135
141
  }),
@@ -142,6 +148,8 @@ export class FalProvider implements IAIProvider {
142
148
  console.log("[FalProvider] Subscribe completed:", { model });
143
149
  }
144
150
 
151
+ this.checkForNSFWContent(result as Record<string, unknown>);
152
+
145
153
  options?.onResult?.(result as T);
146
154
  return result as T;
147
155
  } finally {
@@ -163,19 +171,29 @@ export class FalProvider implements IAIProvider {
163
171
  console.log("[FalProvider] run() raw result:", JSON.stringify(result, null, 2));
164
172
  console.log("[FalProvider] run() result type:", typeof result);
165
173
  console.log("[FalProvider] run() result keys:", result ? Object.keys(result as object) : "null");
166
- const r = result as Record<string, unknown>;
167
- if (r?.data) {
168
- console.log("[FalProvider] run() has data property, data keys:", Object.keys(r.data as object));
169
- }
170
- if (r?.images) {
171
- console.log("[FalProvider] run() has images property, images:", JSON.stringify(r.images));
172
- }
173
174
  }
174
175
 
176
+ this.checkForNSFWContent(result as Record<string, unknown>);
177
+
175
178
  options?.onProgress?.({ progress: 100, status: "COMPLETED" });
176
179
  return result as T;
177
180
  }
178
181
 
182
+ private checkForNSFWContent(result: Record<string, unknown>): void {
183
+ const nsfwConcepts = result?.has_nsfw_concepts as boolean[] | undefined;
184
+
185
+ if (nsfwConcepts && Array.isArray(nsfwConcepts)) {
186
+ const hasNSFW = nsfwConcepts.some((value) => value === true);
187
+
188
+ if (hasNSFW) {
189
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
190
+ console.log("[FalProvider] NSFW content detected, rejecting result");
191
+ }
192
+ throw new NSFWContentError();
193
+ }
194
+ }
195
+ }
196
+
179
197
  reset(): void {
180
198
  this.apiKey = null;
181
199
  this.config = null;
@@ -7,6 +7,7 @@ import type { ImageFeatureType, VideoFeatureType } from "@umituz/react-native-ai
7
7
 
8
8
  export { FalProvider, falProvider } from "./fal-provider";
9
9
  export { falModelsService, type FalModelConfig, type ModelFetcher } from "./fal-models.service";
10
+ export { NSFWContentError } from "./nsfw-content-error";
10
11
 
11
12
  export function getImageFeatureModel(feature: ImageFeatureType): string {
12
13
  return FAL_IMAGE_FEATURE_MODELS[feature];
@@ -0,0 +1,24 @@
1
+ /**
2
+ * NSFW Content Error
3
+ * Thrown when AI provider detects NSFW content in generated output
4
+ */
5
+
6
+ import { FalErrorType } from "../../domain/entities/error.types";
7
+
8
+ export class NSFWContentError extends Error {
9
+ public readonly type = FalErrorType.CONTENT_POLICY;
10
+ public readonly retryable = false;
11
+ public readonly messageKey = "error.nsfw_content_detected";
12
+
13
+ constructor(message?: string) {
14
+ super(
15
+ message ||
16
+ "The generated content was flagged as inappropriate. Please try a different prompt."
17
+ );
18
+ this.name = "NSFWContentError";
19
+ }
20
+
21
+ getUserMessage(): string {
22
+ return this.message;
23
+ }
24
+ }