@umituz/react-native-ai-generation-content 1.17.112 → 1.17.114

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-generation-content",
3
- "version": "1.17.112",
3
+ "version": "1.17.114",
4
4
  "description": "Provider-agnostic AI generation orchestration for React Native",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -16,6 +16,40 @@ export interface AIProviderConfig {
16
16
  textToImageModel?: string;
17
17
  /** Image editing model ID */
18
18
  imageEditModel?: string;
19
+ /** Video generation model ID */
20
+ videoGenerationModel?: string;
21
+ }
22
+
23
+ /**
24
+ * Provider-level progress info for run/subscribe operations
25
+ */
26
+ export interface ProviderProgressInfo {
27
+ /** Progress percentage (0-100) */
28
+ progress: number;
29
+ /** Current job status */
30
+ status?: AIJobStatusType;
31
+ /** Human-readable message */
32
+ message?: string;
33
+ /** Estimated time remaining in ms */
34
+ estimatedTimeRemaining?: number;
35
+ }
36
+
37
+ /**
38
+ * Provider capabilities and metadata
39
+ */
40
+ export interface ProviderCapabilities {
41
+ /** Supported image features */
42
+ imageFeatures: readonly ImageFeatureType[];
43
+ /** Supported video features */
44
+ videoFeatures: readonly VideoFeatureType[];
45
+ /** Supports text-to-image generation */
46
+ textToImage: boolean;
47
+ /** Supports text-to-video generation */
48
+ textToVideo: boolean;
49
+ /** Supports image-to-video generation */
50
+ imageToVideo: boolean;
51
+ /** Supports text-to-voice generation */
52
+ textToVoice: boolean;
19
53
  }
20
54
 
21
55
  export interface JobSubmission {
@@ -46,12 +80,12 @@ export interface AILogEntry {
46
80
  export interface SubscribeOptions<T = unknown> {
47
81
  timeoutMs?: number;
48
82
  onQueueUpdate?: (status: JobStatus) => void;
49
- onProgress?: (progress: number) => void;
83
+ onProgress?: (progress: ProviderProgressInfo) => void;
50
84
  onResult?: (result: T) => void;
51
85
  }
52
86
 
53
87
  export interface RunOptions {
54
- onProgress?: (progress: number) => void;
88
+ onProgress?: (progress: ProviderProgressInfo) => void;
55
89
  }
56
90
 
57
91
  /**
@@ -105,6 +139,16 @@ export interface IAIProvider {
105
139
  initialize(config: AIProviderConfig): void;
106
140
  isInitialized(): boolean;
107
141
 
142
+ /**
143
+ * Get provider capabilities
144
+ */
145
+ getCapabilities(): ProviderCapabilities;
146
+
147
+ /**
148
+ * Check if a specific feature is supported
149
+ */
150
+ isFeatureSupported(feature: ImageFeatureType | VideoFeatureType): boolean;
151
+
108
152
  submitJob(
109
153
  model: string,
110
154
  input: Record<string, unknown>,
@@ -130,11 +174,13 @@ export interface IAIProvider {
130
174
 
131
175
  /**
132
176
  * Get model ID for an image feature
177
+ * @throws Error if feature is not supported
133
178
  */
134
179
  getImageFeatureModel(feature: ImageFeatureType): string;
135
180
 
136
181
  /**
137
182
  * Build provider-specific input for an image feature
183
+ * @throws Error if feature is not supported
138
184
  */
139
185
  buildImageFeatureInput(
140
186
  feature: ImageFeatureType,
@@ -143,11 +189,13 @@ export interface IAIProvider {
143
189
 
144
190
  /**
145
191
  * Get model ID for a video feature
192
+ * @throws Error if feature is not supported
146
193
  */
147
194
  getVideoFeatureModel(feature: VideoFeatureType): string;
148
195
 
149
196
  /**
150
197
  * Build provider-specific input for a video feature
198
+ * @throws Error if feature is not supported
151
199
  */
152
200
  buildVideoFeatureInput(
153
201
  feature: VideoFeatureType,
@@ -12,6 +12,11 @@ export class CreationsWriter {
12
12
  constructor(private readonly pathResolver: FirestorePathResolver) { }
13
13
 
14
14
  async create(userId: string, creation: Creation): Promise<void> {
15
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
16
+ // eslint-disable-next-line no-console
17
+ console.log("[CreationsWriter] create() start", { userId, creationId: creation.id });
18
+ }
19
+
15
20
  const docRef = this.pathResolver.getDocRef(userId, creation.id);
16
21
  if (!docRef) throw new Error("Firestore not initialized");
17
22
 
@@ -27,7 +32,19 @@ export class CreationsWriter {
27
32
  output: creation.output,
28
33
  };
29
34
 
30
- await setDoc(docRef, data);
35
+ try {
36
+ await setDoc(docRef, data);
37
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
38
+ // eslint-disable-next-line no-console
39
+ console.log("[CreationsWriter] create() success", { creationId: creation.id });
40
+ }
41
+ } catch (error) {
42
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
43
+ // eslint-disable-next-line no-console
44
+ console.error("[CreationsWriter] create() error", error);
45
+ }
46
+ throw error;
47
+ }
31
48
  }
32
49
 
33
50
  async update(
@@ -40,7 +40,7 @@ function isVideoUrl(url?: string | null): boolean {
40
40
 
41
41
  export function CreationVideoPreview({
42
42
  thumbnailUrl,
43
- videoUrl,
43
+ videoUrl: _videoUrl,
44
44
  status = "completed",
45
45
  aspectRatio = 16 / 9,
46
46
  height,
@@ -66,7 +66,7 @@ export async function executeImageToVideo(
66
66
 
67
67
  const { model, buildInput, extractResult, onProgress } = options;
68
68
 
69
- if (__DEV__) {
69
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
70
70
  // eslint-disable-next-line no-console
71
71
  console.log(`[ImageToVideo] Provider: ${provider.providerId}, Model: ${model}`);
72
72
  }
@@ -98,7 +98,7 @@ export async function executeImageToVideo(
98
98
  };
99
99
  } catch (error) {
100
100
  const message = error instanceof Error ? error.message : String(error);
101
- if (__DEV__) {
101
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
102
102
  // eslint-disable-next-line no-console
103
103
  console.error("[ImageToVideo] Error:", message);
104
104
  }
@@ -84,7 +84,7 @@ export async function executeTextToImage(
84
84
 
85
85
  const { model, buildInput, extractResult, onProgress } = options;
86
86
 
87
- if (__DEV__) {
87
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
88
88
  // eslint-disable-next-line no-console
89
89
  console.log(`[TextToImage] Provider: ${provider.providerId}, Model: ${model}`);
90
90
  }
@@ -113,7 +113,7 @@ export async function executeTextToImage(
113
113
  };
114
114
  } catch (error) {
115
115
  const message = error instanceof Error ? error.message : String(error);
116
- if (__DEV__) {
116
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
117
117
  // eslint-disable-next-line no-console
118
118
  console.error("[TextToImage] Error:", message);
119
119
  }
@@ -49,13 +49,26 @@ export async function executeTextToVideo(
49
49
  request: TextToVideoRequest,
50
50
  options: ExecuteTextToVideoOptions,
51
51
  ): Promise<TextToVideoResult> {
52
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
53
+ // eslint-disable-next-line no-console
54
+ console.log("[TextToVideoExecutor] executeTextToVideo() called");
55
+ }
56
+
52
57
  const provider = providerRegistry.getActiveProvider();
53
58
 
54
59
  if (!provider) {
60
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
61
+ // eslint-disable-next-line no-console
62
+ console.error("[TextToVideoExecutor] No AI provider configured");
63
+ }
55
64
  return { success: false, error: "No AI provider configured" };
56
65
  }
57
66
 
58
67
  if (!provider.isInitialized()) {
68
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
69
+ // eslint-disable-next-line no-console
70
+ console.error("[TextToVideoExecutor] AI provider not initialized");
71
+ }
59
72
  return { success: false, error: "AI provider not initialized" };
60
73
  }
61
74
 
@@ -65,27 +78,45 @@ export async function executeTextToVideo(
65
78
 
66
79
  const { model, buildInput, extractResult, onProgress } = options;
67
80
 
68
- if (__DEV__) {
81
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
69
82
  // eslint-disable-next-line no-console
70
- console.log(`[TextToVideo] Provider: ${provider.providerId}, Model: ${model}`);
83
+ console.log(`[TextToVideoExecutor] Provider: ${provider.providerId}, Model: ${model}`);
71
84
  }
72
85
 
73
86
  try {
74
87
  onProgress?.(5);
88
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
89
+ // eslint-disable-next-line no-console
90
+ console.log("[TextToVideoExecutor] Starting provider.run()...");
91
+ }
75
92
 
76
93
  const input = buildInput(request.prompt, request.options);
77
94
 
78
95
  const result = await provider.run(model, input, {
79
- onProgress: (progress) => {
80
- onProgress?.(progress);
96
+ onProgress: (progressInfo) => {
97
+ const progressValue = progressInfo.progress;
98
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
99
+ // eslint-disable-next-line no-console
100
+ console.log("[TextToVideoExecutor] Progress:", progressValue);
101
+ }
102
+ onProgress?.(progressValue);
81
103
  },
82
104
  });
83
105
 
106
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
107
+ // eslint-disable-next-line no-console
108
+ console.log("[TextToVideoExecutor] provider.run() completed", result);
109
+ }
110
+
84
111
  const extractor = extractResult || defaultExtractResult;
85
112
  const extracted = extractor(result);
86
113
  onProgress?.(100);
87
114
 
88
115
  if (!extracted?.videoUrl) {
116
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
117
+ // eslint-disable-next-line no-console
118
+ console.error("[TextToVideoExecutor] No video URL in response");
119
+ }
89
120
  return { success: false, error: "No video in response" };
90
121
  }
91
122
 
@@ -96,9 +127,9 @@ export async function executeTextToVideo(
96
127
  };
97
128
  } catch (error) {
98
129
  const message = error instanceof Error ? error.message : String(error);
99
- if (__DEV__) {
130
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
100
131
  // eslint-disable-next-line no-console
101
- console.error("[TextToVideo] Error:", message);
132
+ console.error("[TextToVideoExecutor] Error:", message);
102
133
  }
103
134
  return { success: false, error: message };
104
135
  }
@@ -139,67 +139,92 @@ export function useTextToVideoFeature(
139
139
  console.log("[TextToVideoFeature] Starting generation with prompt:", prompt, "creationId:", creationId);
140
140
  }
141
141
 
142
- // Create "processing" creation at start
142
+ // Create "processing" creation at start (fire-and-forget to not block generation)
143
143
  if (callbacks.onGenerationStart) {
144
- await callbacks.onGenerationStart({
144
+ callbacks.onGenerationStart({
145
145
  creationId,
146
146
  type: "text-to-video",
147
147
  prompt,
148
148
  metadata: options as Record<string, unknown> | undefined,
149
+ }).catch((err) => {
150
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
151
+ // eslint-disable-next-line no-console
152
+ console.warn("[TextToVideoFeature] onGenerationStart failed:", err);
153
+ }
149
154
  });
150
155
  }
151
156
 
152
- const result = await executeTextToVideo(
153
- { prompt, userId, options },
154
- {
155
- model: config.model,
156
- buildInput,
157
- extractResult,
158
- onProgress: (progress) => {
159
- setState((prev) => ({ ...prev, progress }));
160
- callbacks.onProgress?.(progress);
161
- },
162
- },
163
- );
164
-
165
- if (result.success && result.videoUrl) {
166
- setState((prev) => ({
167
- ...prev,
168
- videoUrl: result.videoUrl ?? null,
169
- thumbnailUrl: result.thumbnailUrl ?? null,
170
- isProcessing: false,
171
- progress: 100,
172
- }));
157
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
158
+ // eslint-disable-next-line no-console
159
+ console.log("[TextToVideoFeature] Starting executeTextToVideo...");
160
+ }
173
161
 
174
- // Deduct credits after successful generation
175
- if (callbacks.onCreditDeduct) {
176
- await callbacks.onCreditDeduct(config.creditCost);
162
+ try {
163
+ const result = await executeTextToVideo(
164
+ { prompt, userId, options },
165
+ {
166
+ model: config.model,
167
+ buildInput,
168
+ extractResult,
169
+ onProgress: (progress) => {
170
+ setState((prev) => ({ ...prev, progress }));
171
+ callbacks.onProgress?.(progress);
172
+ },
173
+ },
174
+ );
175
+
176
+ if (result.success && result.videoUrl) {
177
+ setState((prev) => ({
178
+ ...prev,
179
+ videoUrl: result.videoUrl ?? null,
180
+ thumbnailUrl: result.thumbnailUrl ?? null,
181
+ isProcessing: false,
182
+ progress: 100,
183
+ }));
184
+
185
+ // Deduct credits after successful generation
186
+ if (callbacks.onCreditDeduct) {
187
+ await callbacks.onCreditDeduct(config.creditCost);
188
+ }
189
+
190
+ // Update creation to completed after successful generation
191
+ if (callbacks.onCreationSave) {
192
+ await callbacks.onCreationSave({
193
+ creationId,
194
+ type: "text-to-video",
195
+ videoUrl: result.videoUrl,
196
+ thumbnailUrl: result.thumbnailUrl,
197
+ prompt,
198
+ metadata: options as Record<string, unknown> | undefined,
199
+ });
200
+ }
201
+
202
+ callbacks.onGenerate?.(result);
203
+ } else {
204
+ const error = result.error || "Generation failed";
205
+ setState((prev) => ({
206
+ ...prev,
207
+ isProcessing: false,
208
+ error,
209
+ }));
210
+ callbacks.onError?.(error);
177
211
  }
178
212
 
179
- // Update creation to completed after successful generation
180
- if (callbacks.onCreationSave) {
181
- await callbacks.onCreationSave({
182
- creationId,
183
- type: "text-to-video",
184
- videoUrl: result.videoUrl,
185
- thumbnailUrl: result.thumbnailUrl,
186
- prompt,
187
- metadata: options as Record<string, unknown> | undefined,
188
- });
213
+ return result;
214
+ } catch (err) {
215
+ const errorMessage = err instanceof Error ? err.message : String(err);
216
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
217
+ // eslint-disable-next-line no-console
218
+ console.error("[TextToVideoFeature] Generation error:", errorMessage);
189
219
  }
190
-
191
- callbacks.onGenerate?.(result);
192
- } else {
193
- const error = result.error || "Generation failed";
194
220
  setState((prev) => ({
195
221
  ...prev,
196
222
  isProcessing: false,
197
- error,
223
+ error: errorMessage,
198
224
  }));
199
- callbacks.onError?.(error);
225
+ callbacks.onError?.(errorMessage);
226
+ return { success: false, error: errorMessage };
200
227
  }
201
-
202
- return result;
203
228
  },
204
229
  [userId, config.model, buildInput, extractResult, callbacks],
205
230
  );
package/src/index.ts CHANGED
@@ -30,6 +30,8 @@ export type {
30
30
  VideoFeatureType,
31
31
  ImageFeatureInputData,
32
32
  VideoFeatureInputData,
33
+ ProviderCapabilities,
34
+ ProviderProgressInfo,
33
35
  // App Services Interfaces
34
36
  INetworkService,
35
37
  ICreditService,