@umituz/react-native-ai-fal-provider 1.0.13 → 1.0.15
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.15",
|
|
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",
|
|
@@ -93,7 +93,9 @@ class FalClientService {
|
|
|
93
93
|
const result = await Promise.race([
|
|
94
94
|
fal.subscribe(modelEndpoint, {
|
|
95
95
|
input,
|
|
96
|
-
|
|
96
|
+
logs: true,
|
|
97
|
+
pollInterval: 1000,
|
|
98
|
+
onQueueUpdate: (update: { status: string; logs?: unknown[] }) => {
|
|
97
99
|
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
98
100
|
// eslint-disable-next-line no-console
|
|
99
101
|
console.log("[FAL] Queue update:", { status: update.status });
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FAL Feature Builder Service
|
|
3
|
+
* Handles building input data for different AI features
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type {
|
|
7
|
+
ImageFeatureType,
|
|
8
|
+
VideoFeatureType,
|
|
9
|
+
ImageFeatureInputData,
|
|
10
|
+
VideoFeatureInputData,
|
|
11
|
+
} from "@umituz/react-native-ai-generation-content";
|
|
12
|
+
import {
|
|
13
|
+
FAL_IMAGE_FEATURE_MODELS,
|
|
14
|
+
FAL_VIDEO_FEATURE_MODELS,
|
|
15
|
+
} from "../../domain/constants/feature-models.constants";
|
|
16
|
+
import {
|
|
17
|
+
buildUpscaleInput,
|
|
18
|
+
buildPhotoRestoreInput,
|
|
19
|
+
buildVideoFromImageInput,
|
|
20
|
+
buildFaceSwapInput,
|
|
21
|
+
buildAnimeSelfieInput,
|
|
22
|
+
buildRemoveBackgroundInput,
|
|
23
|
+
buildRemoveObjectInput,
|
|
24
|
+
buildReplaceBackgroundInput,
|
|
25
|
+
buildHDTouchUpInput,
|
|
26
|
+
} from "../utils/input-builders.util";
|
|
27
|
+
|
|
28
|
+
export function getImageFeatureModel(feature: ImageFeatureType): string {
|
|
29
|
+
return FAL_IMAGE_FEATURE_MODELS[feature];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function getVideoFeatureModel(feature: VideoFeatureType): string {
|
|
33
|
+
return FAL_VIDEO_FEATURE_MODELS[feature];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function buildImageFeatureInput(
|
|
37
|
+
feature: ImageFeatureType,
|
|
38
|
+
data: ImageFeatureInputData,
|
|
39
|
+
): Record<string, unknown> {
|
|
40
|
+
const { imageBase64, targetImageBase64, prompt, options } = data;
|
|
41
|
+
|
|
42
|
+
switch (feature) {
|
|
43
|
+
case "upscale":
|
|
44
|
+
return buildUpscaleInput(imageBase64, options);
|
|
45
|
+
case "photo-restore":
|
|
46
|
+
return buildPhotoRestoreInput(imageBase64, options);
|
|
47
|
+
case "face-swap":
|
|
48
|
+
if (!targetImageBase64) {
|
|
49
|
+
throw new Error("Face swap requires target image");
|
|
50
|
+
}
|
|
51
|
+
return buildFaceSwapInput(imageBase64, targetImageBase64, options);
|
|
52
|
+
case "anime-selfie":
|
|
53
|
+
return buildAnimeSelfieInput(imageBase64, options);
|
|
54
|
+
case "remove-background":
|
|
55
|
+
return buildRemoveBackgroundInput(imageBase64, options);
|
|
56
|
+
case "remove-object":
|
|
57
|
+
return buildRemoveObjectInput(imageBase64, { prompt, ...options });
|
|
58
|
+
case "hd-touch-up":
|
|
59
|
+
return buildHDTouchUpInput(imageBase64, options);
|
|
60
|
+
case "replace-background":
|
|
61
|
+
if (!prompt) {
|
|
62
|
+
throw new Error("Replace background requires prompt");
|
|
63
|
+
}
|
|
64
|
+
return buildReplaceBackgroundInput(imageBase64, { prompt });
|
|
65
|
+
default:
|
|
66
|
+
throw new Error(`Unknown image feature: ${String(feature)}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function buildVideoFeatureInput(
|
|
71
|
+
feature: VideoFeatureType,
|
|
72
|
+
data: VideoFeatureInputData,
|
|
73
|
+
): Record<string, unknown> {
|
|
74
|
+
const { sourceImageBase64, targetImageBase64, prompt, options } = data;
|
|
75
|
+
|
|
76
|
+
switch (feature) {
|
|
77
|
+
case "ai-hug":
|
|
78
|
+
case "ai-kiss":
|
|
79
|
+
return buildVideoFromImageInput(sourceImageBase64, {
|
|
80
|
+
target_image: targetImageBase64,
|
|
81
|
+
motion_prompt: prompt,
|
|
82
|
+
...options,
|
|
83
|
+
});
|
|
84
|
+
default:
|
|
85
|
+
throw new Error(`Unknown video feature: ${String(feature)}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -18,25 +18,13 @@ import type {
|
|
|
18
18
|
VideoFeatureInputData,
|
|
19
19
|
ProviderCapabilities,
|
|
20
20
|
} from "@umituz/react-native-ai-generation-content";
|
|
21
|
-
import type {
|
|
22
|
-
FalQueueStatus,
|
|
23
|
-
FalLogEntry,
|
|
24
|
-
} from "../../domain/entities/fal.types";
|
|
25
|
-
import {
|
|
26
|
-
FAL_IMAGE_FEATURE_MODELS,
|
|
27
|
-
FAL_VIDEO_FEATURE_MODELS,
|
|
28
|
-
} from "../../domain/constants/feature-models.constants";
|
|
21
|
+
import type { FalQueueStatus, FalLogEntry } from "../../domain/entities/fal.types";
|
|
29
22
|
import {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
buildRemoveBackgroundInput,
|
|
36
|
-
buildRemoveObjectInput,
|
|
37
|
-
buildReplaceBackgroundInput,
|
|
38
|
-
buildHDTouchUpInput,
|
|
39
|
-
} from "../utils/input-builders.util";
|
|
23
|
+
getImageFeatureModel,
|
|
24
|
+
getVideoFeatureModel,
|
|
25
|
+
buildImageFeatureInput,
|
|
26
|
+
buildVideoFeatureInput,
|
|
27
|
+
} from "./fal-feature-builder.service";
|
|
40
28
|
|
|
41
29
|
declare const __DEV__: boolean;
|
|
42
30
|
|
|
@@ -45,11 +33,9 @@ const DEFAULT_CONFIG = {
|
|
|
45
33
|
baseDelay: 1000,
|
|
46
34
|
maxDelay: 10000,
|
|
47
35
|
defaultTimeoutMs: 300000,
|
|
36
|
+
pollInterval: 1000,
|
|
48
37
|
};
|
|
49
38
|
|
|
50
|
-
/**
|
|
51
|
-
* FAL provider capabilities
|
|
52
|
-
*/
|
|
53
39
|
const FAL_CAPABILITIES: ProviderCapabilities = {
|
|
54
40
|
imageFeatures: [
|
|
55
41
|
"upscale",
|
|
@@ -112,7 +98,6 @@ export class FalProvider implements IAIProvider {
|
|
|
112
98
|
this.initialized = true;
|
|
113
99
|
|
|
114
100
|
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
115
|
-
// eslint-disable-next-line no-console
|
|
116
101
|
console.log("[FalProvider] Initialized");
|
|
117
102
|
}
|
|
118
103
|
}
|
|
@@ -139,14 +124,9 @@ export class FalProvider implements IAIProvider {
|
|
|
139
124
|
}
|
|
140
125
|
}
|
|
141
126
|
|
|
142
|
-
async submitJob(
|
|
143
|
-
model: string,
|
|
144
|
-
input: Record<string, unknown>,
|
|
145
|
-
): Promise<JobSubmission> {
|
|
127
|
+
async submitJob(model: string, input: Record<string, unknown>): Promise<JobSubmission> {
|
|
146
128
|
this.validateInitialization();
|
|
147
|
-
|
|
148
129
|
const result = await fal.queue.submit(model, { input });
|
|
149
|
-
|
|
150
130
|
return {
|
|
151
131
|
requestId: result.request_id,
|
|
152
132
|
statusUrl: result.status_url,
|
|
@@ -156,20 +136,13 @@ export class FalProvider implements IAIProvider {
|
|
|
156
136
|
|
|
157
137
|
async getJobStatus(model: string, requestId: string): Promise<JobStatus> {
|
|
158
138
|
this.validateInitialization();
|
|
159
|
-
|
|
160
139
|
const status = await fal.queue.status(model, { requestId, logs: true });
|
|
161
|
-
|
|
162
140
|
return mapFalStatusToJobStatus(status as unknown as FalQueueStatus);
|
|
163
141
|
}
|
|
164
142
|
|
|
165
|
-
async getJobResult<T = unknown>(
|
|
166
|
-
model: string,
|
|
167
|
-
requestId: string,
|
|
168
|
-
): Promise<T> {
|
|
143
|
+
async getJobResult<T = unknown>(model: string, requestId: string): Promise<T> {
|
|
169
144
|
this.validateInitialization();
|
|
170
|
-
|
|
171
145
|
const result = await fal.queue.result(model, { requestId });
|
|
172
|
-
|
|
173
146
|
return result.data as T;
|
|
174
147
|
}
|
|
175
148
|
|
|
@@ -180,14 +153,10 @@ export class FalProvider implements IAIProvider {
|
|
|
180
153
|
): Promise<T> {
|
|
181
154
|
this.validateInitialization();
|
|
182
155
|
|
|
183
|
-
const timeoutMs =
|
|
184
|
-
options?.timeoutMs ??
|
|
185
|
-
this.config?.defaultTimeoutMs ??
|
|
186
|
-
DEFAULT_CONFIG.defaultTimeoutMs;
|
|
156
|
+
const timeoutMs = options?.timeoutMs ?? this.config?.defaultTimeoutMs ?? DEFAULT_CONFIG.defaultTimeoutMs;
|
|
187
157
|
let timeoutId: ReturnType<typeof setTimeout> | null = null;
|
|
188
158
|
|
|
189
159
|
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
190
|
-
// eslint-disable-next-line no-console
|
|
191
160
|
console.log("[FalProvider] Subscribe started:", { model, timeoutMs });
|
|
192
161
|
}
|
|
193
162
|
|
|
@@ -195,59 +164,47 @@ export class FalProvider implements IAIProvider {
|
|
|
195
164
|
const result = await Promise.race([
|
|
196
165
|
fal.subscribe(model, {
|
|
197
166
|
input,
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
)
|
|
167
|
+
logs: true,
|
|
168
|
+
pollInterval: DEFAULT_CONFIG.pollInterval,
|
|
169
|
+
onQueueUpdate: (update: { status: string; logs?: unknown[] }) => {
|
|
170
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
171
|
+
console.log("[FalProvider] Queue update:", JSON.stringify(update));
|
|
172
|
+
}
|
|
173
|
+
const jobStatus = mapFalStatusToJobStatus(update as unknown as FalQueueStatus);
|
|
202
174
|
options?.onQueueUpdate?.(jobStatus);
|
|
203
175
|
},
|
|
204
176
|
}),
|
|
205
177
|
new Promise<never>((_, reject) => {
|
|
206
|
-
timeoutId = setTimeout(
|
|
207
|
-
() => reject(new Error("FAL subscription timeout")),
|
|
208
|
-
timeoutMs,
|
|
209
|
-
);
|
|
178
|
+
timeoutId = setTimeout(() => reject(new Error("FAL subscription timeout")), timeoutMs);
|
|
210
179
|
}),
|
|
211
180
|
]);
|
|
212
181
|
|
|
213
182
|
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
214
|
-
// eslint-disable-next-line no-console
|
|
215
183
|
console.log("[FalProvider] Subscribe completed:", { model });
|
|
216
184
|
}
|
|
217
185
|
|
|
218
186
|
options?.onResult?.(result as T);
|
|
219
|
-
|
|
220
187
|
return result as T;
|
|
221
188
|
} finally {
|
|
222
|
-
if (timeoutId)
|
|
223
|
-
clearTimeout(timeoutId);
|
|
224
|
-
}
|
|
189
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
225
190
|
}
|
|
226
191
|
}
|
|
227
192
|
|
|
228
|
-
async run<T = unknown>(
|
|
229
|
-
model: string,
|
|
230
|
-
input: Record<string, unknown>,
|
|
231
|
-
options?: RunOptions,
|
|
232
|
-
): Promise<T> {
|
|
193
|
+
async run<T = unknown>(model: string, input: Record<string, unknown>, options?: RunOptions): Promise<T> {
|
|
233
194
|
this.validateInitialization();
|
|
234
|
-
|
|
235
195
|
options?.onProgress?.({ progress: 10, status: "IN_PROGRESS" });
|
|
236
196
|
|
|
237
197
|
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
238
|
-
// eslint-disable-next-line no-console
|
|
239
198
|
console.log("[FalProvider] run() model:", model, "inputKeys:", Object.keys(input));
|
|
240
199
|
}
|
|
241
200
|
|
|
242
201
|
const result = await fal.run(model, { input });
|
|
243
202
|
|
|
244
203
|
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
245
|
-
// eslint-disable-next-line no-console
|
|
246
204
|
console.log("[FalProvider] run() completed, hasResult:", !!result);
|
|
247
205
|
}
|
|
248
206
|
|
|
249
207
|
options?.onProgress?.({ progress: 100, status: "COMPLETED" });
|
|
250
|
-
|
|
251
208
|
return result as T;
|
|
252
209
|
}
|
|
253
210
|
|
|
@@ -257,77 +214,20 @@ export class FalProvider implements IAIProvider {
|
|
|
257
214
|
this.initialized = false;
|
|
258
215
|
}
|
|
259
216
|
|
|
260
|
-
/**
|
|
261
|
-
* Get model ID for an IMAGE feature
|
|
262
|
-
*/
|
|
263
217
|
getImageFeatureModel(feature: ImageFeatureType): string {
|
|
264
|
-
return
|
|
218
|
+
return getImageFeatureModel(feature);
|
|
265
219
|
}
|
|
266
220
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
*/
|
|
270
|
-
buildImageFeatureInput(
|
|
271
|
-
feature: ImageFeatureType,
|
|
272
|
-
data: ImageFeatureInputData,
|
|
273
|
-
): Record<string, unknown> {
|
|
274
|
-
const { imageBase64, targetImageBase64, prompt, options } = data;
|
|
275
|
-
|
|
276
|
-
switch (feature) {
|
|
277
|
-
case "upscale":
|
|
278
|
-
return buildUpscaleInput(imageBase64, options);
|
|
279
|
-
case "photo-restore":
|
|
280
|
-
return buildPhotoRestoreInput(imageBase64, options);
|
|
281
|
-
case "face-swap":
|
|
282
|
-
if (!targetImageBase64) {
|
|
283
|
-
throw new Error("Face swap requires target image");
|
|
284
|
-
}
|
|
285
|
-
return buildFaceSwapInput(imageBase64, targetImageBase64, options);
|
|
286
|
-
case "anime-selfie":
|
|
287
|
-
return buildAnimeSelfieInput(imageBase64, options);
|
|
288
|
-
case "remove-background":
|
|
289
|
-
return buildRemoveBackgroundInput(imageBase64, options);
|
|
290
|
-
case "remove-object":
|
|
291
|
-
return buildRemoveObjectInput(imageBase64, { prompt, ...options });
|
|
292
|
-
case "hd-touch-up":
|
|
293
|
-
return buildHDTouchUpInput(imageBase64, options);
|
|
294
|
-
case "replace-background":
|
|
295
|
-
if (!prompt) {
|
|
296
|
-
throw new Error("Replace background requires prompt");
|
|
297
|
-
}
|
|
298
|
-
return buildReplaceBackgroundInput(imageBase64, { prompt });
|
|
299
|
-
default:
|
|
300
|
-
throw new Error(`Unknown image feature: ${String(feature)}`);
|
|
301
|
-
}
|
|
221
|
+
buildImageFeatureInput(feature: ImageFeatureType, data: ImageFeatureInputData): Record<string, unknown> {
|
|
222
|
+
return buildImageFeatureInput(feature, data);
|
|
302
223
|
}
|
|
303
224
|
|
|
304
|
-
/**
|
|
305
|
-
* Get model ID for a VIDEO feature
|
|
306
|
-
*/
|
|
307
225
|
getVideoFeatureModel(feature: VideoFeatureType): string {
|
|
308
|
-
return
|
|
226
|
+
return getVideoFeatureModel(feature);
|
|
309
227
|
}
|
|
310
228
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
*/
|
|
314
|
-
buildVideoFeatureInput(
|
|
315
|
-
feature: VideoFeatureType,
|
|
316
|
-
data: VideoFeatureInputData,
|
|
317
|
-
): Record<string, unknown> {
|
|
318
|
-
const { sourceImageBase64, targetImageBase64, prompt, options } = data;
|
|
319
|
-
|
|
320
|
-
switch (feature) {
|
|
321
|
-
case "ai-hug":
|
|
322
|
-
case "ai-kiss":
|
|
323
|
-
return buildVideoFromImageInput(sourceImageBase64, {
|
|
324
|
-
target_image: targetImageBase64,
|
|
325
|
-
motion_prompt: prompt,
|
|
326
|
-
...options,
|
|
327
|
-
});
|
|
328
|
-
default:
|
|
329
|
-
throw new Error(`Unknown video feature: ${String(feature)}`);
|
|
330
|
-
}
|
|
229
|
+
buildVideoFeatureInput(feature: VideoFeatureType, data: VideoFeatureInputData): Record<string, unknown> {
|
|
230
|
+
return buildVideoFeatureInput(feature, data);
|
|
331
231
|
}
|
|
332
232
|
}
|
|
333
233
|
|
|
@@ -6,3 +6,9 @@
|
|
|
6
6
|
export { falClientService } from "./fal-client.service";
|
|
7
7
|
export { FalProvider, falProvider } from "./fal-provider";
|
|
8
8
|
export { falModelsService, type FalModelConfig, type ModelFetcher } from "./fal-models.service";
|
|
9
|
+
export {
|
|
10
|
+
getImageFeatureModel,
|
|
11
|
+
getVideoFeatureModel,
|
|
12
|
+
buildImageFeatureInput,
|
|
13
|
+
buildVideoFeatureInput,
|
|
14
|
+
} from "./fal-feature-builder.service";
|