@umituz/react-native-ai-generation-content 1.26.28 → 1.26.29
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 +1 -1
- package/src/infrastructure/constants/index.ts +11 -0
- package/src/infrastructure/constants/progress.constants.ts +36 -0
- package/src/infrastructure/services/image-feature-executor.service.ts +8 -26
- package/src/infrastructure/services/provider-validator.ts +17 -38
- package/src/infrastructure/services/video-feature-executor.service.ts +11 -36
- package/src/infrastructure/utils/error-message-extractor.util.ts +41 -0
- package/src/infrastructure/utils/index.ts +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-ai-generation-content",
|
|
3
|
-
"version": "1.26.
|
|
3
|
+
"version": "1.26.29",
|
|
4
4
|
"description": "Provider-agnostic AI generation orchestration for React Native with result preview components",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "src/index.ts",
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Progress Constants
|
|
3
|
+
* Standardized progress values for generation pipelines
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/** Image generation progress stages */
|
|
7
|
+
export const IMAGE_PROGRESS = {
|
|
8
|
+
START: 10,
|
|
9
|
+
INPUT_PREPARED: 30,
|
|
10
|
+
REQUEST_SENT: 40,
|
|
11
|
+
RESULT_RECEIVED: 90,
|
|
12
|
+
COMPLETE: 100,
|
|
13
|
+
} as const;
|
|
14
|
+
|
|
15
|
+
/** Video generation progress stages */
|
|
16
|
+
export const VIDEO_PROGRESS = {
|
|
17
|
+
START: 5,
|
|
18
|
+
INPUT_PREPARED: 10,
|
|
19
|
+
REQUEST_SENT: 15,
|
|
20
|
+
IN_QUEUE: 20,
|
|
21
|
+
IN_PROGRESS: 50,
|
|
22
|
+
RESULT_RECEIVED: 90,
|
|
23
|
+
COMPLETE: 100,
|
|
24
|
+
} as const;
|
|
25
|
+
|
|
26
|
+
/** Polling progress stages */
|
|
27
|
+
export const POLLING_PROGRESS = {
|
|
28
|
+
RESULT_RECEIVED: 90,
|
|
29
|
+
COMPLETE: 100,
|
|
30
|
+
} as const;
|
|
31
|
+
|
|
32
|
+
/** Video generation timeout in milliseconds (5 minutes) */
|
|
33
|
+
export const VIDEO_TIMEOUT_MS = 300000;
|
|
34
|
+
|
|
35
|
+
/** Maximum consecutive transient errors before failing */
|
|
36
|
+
export const MAX_TRANSIENT_ERRORS = 5;
|
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { providerRegistry } from "./provider-registry.service";
|
|
8
|
-
import { cleanBase64 } from "../utils";
|
|
8
|
+
import { cleanBase64, extractErrorMessage } from "../utils";
|
|
9
9
|
import { extractImageResult } from "../utils/url-extractor";
|
|
10
|
+
import { IMAGE_PROGRESS } from "../constants";
|
|
10
11
|
import type { ImageResultExtractor } from "../utils/url-extractor";
|
|
11
12
|
import type { ImageFeatureType, ImageFeatureInputData } from "../../domain/interfaces";
|
|
12
13
|
|
|
@@ -68,7 +69,7 @@ export async function executeImageFeature(
|
|
|
68
69
|
}
|
|
69
70
|
|
|
70
71
|
try {
|
|
71
|
-
onProgress?.(
|
|
72
|
+
onProgress?.(IMAGE_PROGRESS.START);
|
|
72
73
|
|
|
73
74
|
const inputData: ImageFeatureInputData = {
|
|
74
75
|
imageBase64: request.imageBase64 ? cleanBase64(request.imageBase64) : "",
|
|
@@ -79,20 +80,20 @@ export async function executeImageFeature(
|
|
|
79
80
|
options: request.options,
|
|
80
81
|
};
|
|
81
82
|
|
|
82
|
-
onProgress?.(
|
|
83
|
+
onProgress?.(IMAGE_PROGRESS.INPUT_PREPARED);
|
|
83
84
|
|
|
84
85
|
const input = provider.buildImageFeatureInput(featureType, inputData);
|
|
85
86
|
|
|
86
|
-
onProgress?.(
|
|
87
|
+
onProgress?.(IMAGE_PROGRESS.REQUEST_SENT);
|
|
87
88
|
|
|
88
89
|
const result = await provider.run(model, input);
|
|
89
90
|
|
|
90
|
-
onProgress?.(
|
|
91
|
+
onProgress?.(IMAGE_PROGRESS.RESULT_RECEIVED);
|
|
91
92
|
|
|
92
93
|
const extractor = extractResult ?? extractImageResult;
|
|
93
94
|
const imageUrl = extractor(result);
|
|
94
95
|
|
|
95
|
-
onProgress?.(
|
|
96
|
+
onProgress?.(IMAGE_PROGRESS.COMPLETE);
|
|
96
97
|
|
|
97
98
|
if (!imageUrl) {
|
|
98
99
|
return { success: false, error: "No image in response" };
|
|
@@ -104,26 +105,7 @@ export async function executeImageFeature(
|
|
|
104
105
|
requestId: (result as { requestId?: string })?.requestId,
|
|
105
106
|
};
|
|
106
107
|
} catch (error) {
|
|
107
|
-
|
|
108
|
-
let message = "Processing failed";
|
|
109
|
-
if (error instanceof Error) {
|
|
110
|
-
message = error.message;
|
|
111
|
-
} else if (typeof error === "object" && error !== null) {
|
|
112
|
-
const errObj = error as Record<string, unknown>;
|
|
113
|
-
// FAL API error format: {detail: [{msg, type, loc}]} or {message}
|
|
114
|
-
if (Array.isArray(errObj.detail) && errObj.detail[0]?.msg) {
|
|
115
|
-
message = String(errObj.detail[0].msg);
|
|
116
|
-
} else if (errObj.detail) {
|
|
117
|
-
message = JSON.stringify(errObj.detail);
|
|
118
|
-
} else if (errObj.message) {
|
|
119
|
-
message = String(errObj.message);
|
|
120
|
-
} else if (errObj.msg) {
|
|
121
|
-
message = String(errObj.msg);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
if (__DEV__) {
|
|
125
|
-
console.error(`[Image:${featureType}] Error:`, message, error);
|
|
126
|
-
}
|
|
108
|
+
const message = extractErrorMessage(error, "Processing failed", `Image:${featureType}`);
|
|
127
109
|
return { success: false, error: message };
|
|
128
110
|
}
|
|
129
111
|
}
|
|
@@ -9,44 +9,23 @@ import { providerRegistry } from "./provider-registry.service";
|
|
|
9
9
|
declare const __DEV__: boolean;
|
|
10
10
|
|
|
11
11
|
export class ProviderValidator {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
22
|
-
|
|
23
|
-
console.error("[ProviderValidator] No active provider found!");
|
|
24
|
-
}
|
|
25
|
-
throw new Error(
|
|
26
|
-
"No active AI provider. Register and set a provider first.",
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (!provider.isInitialized()) {
|
|
31
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
32
|
-
|
|
33
|
-
console.error("[ProviderValidator] Provider not initialized:", provider.providerId);
|
|
34
|
-
}
|
|
35
|
-
throw new Error(
|
|
36
|
-
`Provider ${provider.providerId} is not initialized.`,
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
41
|
-
|
|
42
|
-
console.log("[ProviderValidator] getProvider() returning:", {
|
|
43
|
-
providerId: provider.providerId,
|
|
44
|
-
isInitialized: provider.isInitialized(),
|
|
45
|
-
});
|
|
46
|
-
}
|
|
12
|
+
getProvider(): IAIProvider {
|
|
13
|
+
const provider = providerRegistry.getActiveProvider();
|
|
14
|
+
|
|
15
|
+
if (!provider) {
|
|
16
|
+
if (__DEV__) {
|
|
17
|
+
console.error("[ProviderValidator] No active provider found");
|
|
18
|
+
}
|
|
19
|
+
throw new Error("No active AI provider. Register and set a provider first.");
|
|
20
|
+
}
|
|
47
21
|
|
|
48
|
-
|
|
22
|
+
if (!provider.isInitialized()) {
|
|
23
|
+
if (__DEV__) {
|
|
24
|
+
console.error("[ProviderValidator] Provider not initialized:", provider.providerId);
|
|
25
|
+
}
|
|
26
|
+
throw new Error(`Provider ${provider.providerId} is not initialized.`);
|
|
49
27
|
}
|
|
50
|
-
}
|
|
51
28
|
|
|
52
|
-
|
|
29
|
+
return provider;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { providerRegistry } from "./provider-registry.service";
|
|
8
|
-
import { cleanBase64 } from "../utils";
|
|
8
|
+
import { cleanBase64, extractErrorMessage } from "../utils";
|
|
9
9
|
import { extractVideoResult } from "../utils/url-extractor";
|
|
10
|
+
import { VIDEO_PROGRESS, VIDEO_TIMEOUT_MS } from "../constants";
|
|
10
11
|
import type { VideoFeatureType, VideoFeatureInputData } from "../../domain/interfaces";
|
|
11
12
|
import type {
|
|
12
13
|
ExecuteVideoFeatureOptions,
|
|
@@ -44,7 +45,7 @@ export async function executeVideoFeature(
|
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
try {
|
|
47
|
-
onProgress?.(
|
|
48
|
+
onProgress?.(VIDEO_PROGRESS.START);
|
|
48
49
|
|
|
49
50
|
const inputData: VideoFeatureInputData = {
|
|
50
51
|
sourceImageBase64: cleanBase64(request.sourceImageBase64),
|
|
@@ -53,34 +54,32 @@ export async function executeVideoFeature(
|
|
|
53
54
|
options: request.options,
|
|
54
55
|
};
|
|
55
56
|
|
|
56
|
-
onProgress?.(
|
|
57
|
+
onProgress?.(VIDEO_PROGRESS.INPUT_PREPARED);
|
|
57
58
|
|
|
58
59
|
const input = provider.buildVideoFeatureInput(featureType, inputData);
|
|
59
60
|
|
|
60
|
-
onProgress?.(
|
|
61
|
+
onProgress?.(VIDEO_PROGRESS.REQUEST_SENT);
|
|
61
62
|
|
|
62
|
-
// Use subscribe for video features - provides queue updates and handles long-running tasks
|
|
63
63
|
const result = await provider.subscribe(model, input, {
|
|
64
|
-
timeoutMs:
|
|
64
|
+
timeoutMs: VIDEO_TIMEOUT_MS,
|
|
65
65
|
onQueueUpdate: (status) => {
|
|
66
66
|
if (__DEV__) {
|
|
67
67
|
console.log(`[Video:${featureType}] Queue update:`, status.status);
|
|
68
68
|
}
|
|
69
|
-
// Map queue status to progress percentage
|
|
70
69
|
if (status.status === "IN_QUEUE") {
|
|
71
|
-
onProgress?.(
|
|
70
|
+
onProgress?.(VIDEO_PROGRESS.IN_QUEUE);
|
|
72
71
|
} else if (status.status === "IN_PROGRESS") {
|
|
73
|
-
onProgress?.(
|
|
72
|
+
onProgress?.(VIDEO_PROGRESS.IN_PROGRESS);
|
|
74
73
|
}
|
|
75
74
|
},
|
|
76
75
|
});
|
|
77
76
|
|
|
78
|
-
onProgress?.(
|
|
77
|
+
onProgress?.(VIDEO_PROGRESS.RESULT_RECEIVED);
|
|
79
78
|
|
|
80
79
|
const extractor = extractResult ?? extractVideoResult;
|
|
81
80
|
const videoUrl = extractor(result);
|
|
82
81
|
|
|
83
|
-
onProgress?.(
|
|
82
|
+
onProgress?.(VIDEO_PROGRESS.COMPLETE);
|
|
84
83
|
|
|
85
84
|
if (!videoUrl) {
|
|
86
85
|
if (__DEV__) {
|
|
@@ -95,35 +94,11 @@ export async function executeVideoFeature(
|
|
|
95
94
|
requestId: (result as { requestId?: string })?.requestId,
|
|
96
95
|
};
|
|
97
96
|
} catch (error) {
|
|
98
|
-
const message = extractErrorMessage(error, featureType);
|
|
97
|
+
const message = extractErrorMessage(error, "Processing failed", `Video:${featureType}`);
|
|
99
98
|
return { success: false, error: message };
|
|
100
99
|
}
|
|
101
100
|
}
|
|
102
101
|
|
|
103
|
-
/**
|
|
104
|
-
* Extract error message from various error formats
|
|
105
|
-
*/
|
|
106
|
-
function extractErrorMessage(error: unknown, featureType: VideoFeatureType): string {
|
|
107
|
-
let message = "Processing failed";
|
|
108
|
-
|
|
109
|
-
if (error instanceof Error) {
|
|
110
|
-
message = error.message;
|
|
111
|
-
} else if (typeof error === "object" && error !== null) {
|
|
112
|
-
const errObj = error as Record<string, unknown>;
|
|
113
|
-
if (errObj.detail) {
|
|
114
|
-
message = JSON.stringify(errObj.detail);
|
|
115
|
-
} else if (errObj.message) {
|
|
116
|
-
message = String(errObj.message);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (__DEV__) {
|
|
121
|
-
console.error(`[Video:${featureType}] Error:`, message, error);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return message;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
102
|
/**
|
|
128
103
|
* Check if video features are supported
|
|
129
104
|
*/
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Message Extractor
|
|
3
|
+
* Extracts error messages from various API error formats
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
declare const __DEV__: boolean;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Extract error message from FAL API and other error formats
|
|
10
|
+
* Supports: Error instances, FAL API errors, generic objects
|
|
11
|
+
*/
|
|
12
|
+
export function extractErrorMessage(
|
|
13
|
+
error: unknown,
|
|
14
|
+
defaultMessage = "Processing failed",
|
|
15
|
+
debugPrefix?: string,
|
|
16
|
+
): string {
|
|
17
|
+
let message = defaultMessage;
|
|
18
|
+
|
|
19
|
+
if (error instanceof Error) {
|
|
20
|
+
message = error.message;
|
|
21
|
+
} else if (typeof error === "object" && error !== null) {
|
|
22
|
+
const errObj = error as Record<string, unknown>;
|
|
23
|
+
|
|
24
|
+
// FAL API error format: {detail: [{msg, type, loc}]}
|
|
25
|
+
if (Array.isArray(errObj.detail) && errObj.detail[0]?.msg) {
|
|
26
|
+
message = String(errObj.detail[0].msg);
|
|
27
|
+
} else if (errObj.detail) {
|
|
28
|
+
message = JSON.stringify(errObj.detail);
|
|
29
|
+
} else if (errObj.message) {
|
|
30
|
+
message = String(errObj.message);
|
|
31
|
+
} else if (errObj.msg) {
|
|
32
|
+
message = String(errObj.msg);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (__DEV__ && debugPrefix) {
|
|
37
|
+
console.error(`[${debugPrefix}] Error:`, message, error);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return message;
|
|
41
|
+
}
|