@umituz/react-native-ai-fal-provider 1.0.45 → 1.0.47
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.
|
|
3
|
+
"version": "1.0.47",
|
|
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,
|
|
@@ -142,6 +143,8 @@ export class FalProvider implements IAIProvider {
|
|
|
142
143
|
console.log("[FalProvider] Subscribe completed:", { model });
|
|
143
144
|
}
|
|
144
145
|
|
|
146
|
+
this.checkForNSFWContent(result as Record<string, unknown>);
|
|
147
|
+
|
|
145
148
|
options?.onResult?.(result as T);
|
|
146
149
|
return result as T;
|
|
147
150
|
} finally {
|
|
@@ -163,19 +166,29 @@ export class FalProvider implements IAIProvider {
|
|
|
163
166
|
console.log("[FalProvider] run() raw result:", JSON.stringify(result, null, 2));
|
|
164
167
|
console.log("[FalProvider] run() result type:", typeof result);
|
|
165
168
|
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
169
|
}
|
|
174
170
|
|
|
171
|
+
this.checkForNSFWContent(result as Record<string, unknown>);
|
|
172
|
+
|
|
175
173
|
options?.onProgress?.({ progress: 100, status: "COMPLETED" });
|
|
176
174
|
return result as T;
|
|
177
175
|
}
|
|
178
176
|
|
|
177
|
+
private checkForNSFWContent(result: Record<string, unknown>): void {
|
|
178
|
+
const nsfwConcepts = result?.has_nsfw_concepts as boolean[] | undefined;
|
|
179
|
+
|
|
180
|
+
if (nsfwConcepts && Array.isArray(nsfwConcepts)) {
|
|
181
|
+
const hasNSFW = nsfwConcepts.some((value) => value === true);
|
|
182
|
+
|
|
183
|
+
if (hasNSFW) {
|
|
184
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
185
|
+
console.log("[FalProvider] NSFW content detected, rejecting result");
|
|
186
|
+
}
|
|
187
|
+
throw new NSFWContentError();
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
179
192
|
reset(): void {
|
|
180
193
|
this.apiKey = null;
|
|
181
194
|
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
|
+
}
|
|
@@ -104,13 +104,20 @@ export function buildVideoFromImageInput(
|
|
|
104
104
|
|
|
105
105
|
/**
|
|
106
106
|
* Build face swap input for FAL face-swap
|
|
107
|
+
* FAL API requires: base_image_url (target face) and swap_image_url (face to swap in)
|
|
107
108
|
*/
|
|
108
109
|
export function buildFaceSwapInput(
|
|
109
110
|
sourceBase64: string,
|
|
110
111
|
targetBase64: string,
|
|
111
112
|
_options?: FaceSwapOptions,
|
|
112
113
|
): Record<string, unknown> {
|
|
113
|
-
|
|
114
|
+
const formatImage = (b64: string) =>
|
|
115
|
+
b64.startsWith("data:") ? b64 : `data:image/jpeg;base64,${b64}`;
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
base_image_url: formatImage(sourceBase64),
|
|
119
|
+
swap_image_url: formatImage(targetBase64),
|
|
120
|
+
};
|
|
114
121
|
}
|
|
115
122
|
|
|
116
123
|
/**
|