@umituz/react-native-ai-generation-content 1.26.68 → 1.26.70

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.26.68",
3
+ "version": "1.26.70",
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",
@@ -1,15 +1,6 @@
1
1
  /**
2
2
  * Generic Wizard Flow Component
3
- * ONE wizard to rule them all!
4
- *
5
- * Works for:
6
- * - Couple features (romantic-kiss, ai-hug, etc.)
7
- * - Face swap
8
- * - Image-to-video
9
- * - Text-to-video
10
- * - ANY future feature!
11
- *
12
- * NO feature-specific code here - everything driven by configuration!
3
+ * Config-driven wizard for AI generation features
13
4
  */
14
5
 
15
6
  import React, { useMemo, useCallback, useEffect, useRef, useState } from "react";
@@ -28,6 +19,8 @@ import { validateScenario } from "../utilities/validateScenario";
28
19
  import { WizardStepRenderer } from "./WizardStepRenderer";
29
20
  import { StarRatingPicker } from "../../../../result-preview/presentation/components/StarRatingPicker";
30
21
 
22
+ declare const __DEV__: boolean;
23
+
31
24
  export interface GenericWizardFlowProps {
32
25
  readonly featureConfig: WizardFeatureConfig;
33
26
  readonly scenario?: WizardScenarioData;
@@ -38,9 +31,6 @@ export interface GenericWizardFlowProps {
38
31
  readonly onGenerationComplete?: (result: unknown) => void;
39
32
  readonly onGenerationError?: (error: string) => void;
40
33
  readonly onCreditsExhausted?: () => void;
41
- /** Auth check - orchestrator will check auth BEFORE credits */
42
- readonly isAuthenticated?: () => boolean;
43
- readonly onAuthRequired?: () => void;
44
34
  readonly onRate?: (creationId: string, rating: number, description: string) => Promise<boolean>;
45
35
  readonly onBack?: () => void;
46
36
  readonly onTryAgain?: () => void;
@@ -61,8 +51,6 @@ export const GenericWizardFlow: React.FC<GenericWizardFlowProps> = ({
61
51
  onGenerationComplete,
62
52
  onGenerationError,
63
53
  onCreditsExhausted,
64
- isAuthenticated,
65
- onAuthRequired,
66
54
  onRate,
67
55
  onBack,
68
56
  onTryAgain,
@@ -130,8 +118,6 @@ export const GenericWizardFlow: React.FC<GenericWizardFlowProps> = ({
130
118
  onError: onGenerationError,
131
119
  onProgressChange: handleProgressChange,
132
120
  onCreditsExhausted,
133
- isAuthenticated,
134
- onAuthRequired,
135
121
  });
136
122
 
137
123
  useEffect(() => {
@@ -174,9 +160,7 @@ export const GenericWizardFlow: React.FC<GenericWizardFlowProps> = ({
174
160
  const handleSubmitRating = useCallback(async (rating: number, description: string) => {
175
161
  if (!currentCreation?.id || !onRate) return;
176
162
  const success = await onRate(currentCreation.id, rating, description);
177
- if (success) {
178
- setHasRated(true);
179
- }
163
+ if (success) setHasRated(true);
180
164
  setShowRatingPicker(false);
181
165
  }, [currentCreation, onRate]);
182
166
 
@@ -10,17 +10,13 @@ import { createWizardStrategy, buildWizardInput } from "../../infrastructure/str
10
10
 
11
11
  declare const __DEV__: boolean;
12
12
 
13
- // ============================================================================
14
- // Types
15
- // ============================================================================
16
-
17
13
  export type WizardOutputType = "image" | "video";
18
14
 
19
15
  export interface WizardScenarioData {
20
16
  readonly id: string;
21
17
  readonly aiPrompt: string;
22
18
  readonly outputType?: WizardOutputType;
23
- readonly model?: string; // AI model from app config
19
+ readonly model?: string;
24
20
  readonly title?: string;
25
21
  readonly description?: string;
26
22
  [key: string]: unknown;
@@ -36,9 +32,6 @@ export interface UseWizardGenerationProps {
36
32
  readonly onError?: (error: string) => void;
37
33
  readonly onProgressChange?: (progress: number) => void;
38
34
  readonly onCreditsExhausted?: () => void;
39
- /** Auth check - if user not authenticated, onAuthRequired will be called */
40
- readonly isAuthenticated?: () => boolean;
41
- readonly onAuthRequired?: () => void;
42
35
  }
43
36
 
44
37
  export interface UseWizardGenerationReturn {
@@ -46,10 +39,6 @@ export interface UseWizardGenerationReturn {
46
39
  readonly progress: number;
47
40
  }
48
41
 
49
- // ============================================================================
50
- // Hook
51
- // ============================================================================
52
-
53
42
  export const useWizardGeneration = (
54
43
  props: UseWizardGenerationProps,
55
44
  ): UseWizardGenerationReturn => {
@@ -63,24 +52,19 @@ export const useWizardGeneration = (
63
52
  onError,
64
53
  onProgressChange,
65
54
  onCreditsExhausted,
66
- isAuthenticated,
67
- onAuthRequired,
68
55
  } = props;
69
56
 
70
57
  const hasStarted = useRef(false);
71
58
 
72
- // Log output type on mount
73
59
  useEffect(() => {
74
60
  if (typeof __DEV__ !== "undefined" && __DEV__) {
75
61
  console.log("[useWizardGeneration] Initialized", {
76
62
  scenarioId: scenario.id,
77
63
  outputType: scenario.outputType || "video",
78
- hasOutputType: !!scenario.outputType,
79
64
  });
80
65
  }
81
66
  }, [scenario.id, scenario.outputType]);
82
67
 
83
- // Create strategy using factory
84
68
  const strategy = useMemo(() => {
85
69
  return createWizardStrategy({
86
70
  scenario,
@@ -89,7 +73,6 @@ export const useWizardGeneration = (
89
73
  });
90
74
  }, [scenario, wizardData]);
91
75
 
92
- // Use orchestrator with strategy
93
76
  const { generate, isGenerating, progress } = useGenerationOrchestrator(
94
77
  strategy,
95
78
  {
@@ -102,10 +85,6 @@ export const useWizardGeneration = (
102
85
  unknown: "An error occurred",
103
86
  },
104
87
  onCreditsExhausted,
105
- // Auth config - check auth BEFORE credits
106
- auth: isAuthenticated && onAuthRequired
107
- ? { isAuthenticated, onAuthRequired }
108
- : undefined,
109
88
  onSuccess: (result) => {
110
89
  if (typeof __DEV__ !== "undefined" && __DEV__) {
111
90
  console.log("[useWizardGeneration] Success");
@@ -121,14 +100,10 @@ export const useWizardGeneration = (
121
100
  },
122
101
  );
123
102
 
124
- // Sync progress to parent
125
103
  useEffect(() => {
126
- if (onProgressChange) {
127
- onProgressChange(progress);
128
- }
104
+ if (onProgressChange) onProgressChange(progress);
129
105
  }, [progress, onProgressChange]);
130
106
 
131
- // Auto-start generation when entering generating step
132
107
  useEffect(() => {
133
108
  if (isGeneratingStep && !hasStarted.current && !isGenerating) {
134
109
  if (typeof __DEV__ !== "undefined" && __DEV__) {
@@ -138,37 +113,30 @@ export const useWizardGeneration = (
138
113
  });
139
114
  }
140
115
 
141
- // Build input and start generation
116
+ hasStarted.current = true;
117
+
142
118
  buildWizardInput(wizardData, scenario)
143
119
  .then((input) => {
144
120
  if (!input) {
145
- const error = "Failed to build generation input";
146
- if (typeof __DEV__ !== "undefined" && __DEV__) {
147
- console.error("[useWizardGeneration]", error);
148
- }
149
- onError?.(error);
121
+ hasStarted.current = false;
122
+ onError?.("Failed to build generation input");
150
123
  return;
151
124
  }
152
-
153
125
  generate(input);
154
- hasStarted.current = true;
155
126
  })
156
127
  .catch((error) => {
157
128
  if (typeof __DEV__ !== "undefined" && __DEV__) {
158
129
  console.error("[useWizardGeneration] Input build error:", error);
159
130
  }
131
+ hasStarted.current = false;
160
132
  onError?.(error.message || "Failed to prepare generation");
161
133
  });
162
134
  }
163
135
 
164
- // Reset hasStarted when leaving generating step
165
136
  if (!isGeneratingStep && hasStarted.current) {
166
137
  hasStarted.current = false;
167
138
  }
168
139
  }, [isGeneratingStep, scenario, wizardData, isGenerating, generate, onError]);
169
140
 
170
- return {
171
- isGenerating,
172
- progress,
173
- };
141
+ return { isGenerating, progress };
174
142
  };
@@ -1,13 +1,14 @@
1
1
  /**
2
2
  * Generation Orchestrator
3
- * Feature-agnostic hook for AI generation with centralized:
4
- * - Auth checking (optional)
3
+ * Feature-agnostic hook for AI generation with:
4
+ * - Network check (via design system's useOfflineStore)
5
5
  * - Content moderation (optional)
6
- * - Credit management
7
- * - Error handling
8
- * - Alert display
6
+ * - Credit management (via subscription package)
7
+ * - Error handling & alerts
9
8
  * - Progress tracking
10
- * - Lifecycle management (navigation, cleanup)
9
+ * - Lifecycle management
10
+ *
11
+ * NOTE: Auth is handled by useFeatureGate before generation starts
11
12
  */
12
13
 
13
14
  import { useState, useCallback, useRef, useEffect } from "react";
@@ -45,7 +46,6 @@ export const useGenerationOrchestrator = <TInput, TResult>(
45
46
  onCreditsExhausted,
46
47
  onSuccess,
47
48
  onError,
48
- auth,
49
49
  moderation,
50
50
  credits,
51
51
  lifecycle,
@@ -54,7 +54,6 @@ export const useGenerationOrchestrator = <TInput, TResult>(
54
54
  if (typeof __DEV__ !== "undefined" && __DEV__) {
55
55
  console.log("[Orchestrator] 🎬 Hook initialized:", {
56
56
  userId,
57
- hasAuth: !!auth,
58
57
  hasModeration: !!moderation,
59
58
  hasCreditsCallbacks: !!credits,
60
59
  hasLifecycle: !!lifecycle,
@@ -72,84 +71,48 @@ export const useGenerationOrchestrator = <TInput, TResult>(
72
71
  const { showError, showSuccess } = useAlert();
73
72
  const creditHook = useDeductCredit({ userId, onCreditsExhausted });
74
73
 
75
- // Wrap credit hook to match expected interface
76
74
  const defaultCredits = {
77
75
  checkCredits: creditHook.checkCredits,
78
76
  deductCredit: async (amount: number): Promise<boolean> => {
79
77
  return creditHook.deductCredit(amount);
80
- }
78
+ },
81
79
  };
82
80
 
83
- // Use provided credit callbacks or default to useDeductCredit hook
84
81
  const checkCredits = credits?.checkCredits ?? defaultCredits.checkCredits;
85
82
  const deductCredit = credits?.deductCredits ?? defaultCredits.deductCredit;
86
83
  const handleCreditsExhausted = credits?.onCreditsExhausted ?? onCreditsExhausted;
87
84
 
88
- // Cleanup on unmount
89
85
  useEffect(() => {
90
86
  isMountedRef.current = true;
91
87
  return () => {
92
88
  isMountedRef.current = false;
93
- if (completeTimeoutRef.current) {
94
- clearTimeout(completeTimeoutRef.current);
95
- completeTimeoutRef.current = null;
96
- }
97
- if (resetTimeoutRef.current) {
98
- clearTimeout(resetTimeoutRef.current);
99
- resetTimeoutRef.current = null;
100
- }
89
+ if (completeTimeoutRef.current) clearTimeout(completeTimeoutRef.current);
90
+ if (resetTimeoutRef.current) clearTimeout(resetTimeoutRef.current);
101
91
  if (typeof __DEV__ !== "undefined" && __DEV__) {
102
- console.log("[Orchestrator] 🧹 Cleanup: cleared all timeouts");
92
+ console.log("[Orchestrator] 🧹 Cleanup");
103
93
  }
104
94
  };
105
95
  }, []);
106
96
 
107
- // Handle lifecycle completion
108
97
  const handleLifecycleComplete = useCallback(
109
98
  (status: "success" | "error", result?: TResult, error?: GenerationError) => {
110
99
  if (!lifecycle?.onComplete) return;
111
100
 
112
101
  const delay = lifecycle.completeDelay ?? DEFAULT_COMPLETE_DELAY;
113
102
 
114
- if (typeof __DEV__ !== "undefined" && __DEV__) {
115
- console.log("[Orchestrator] ⏱️ Scheduling lifecycle.onComplete:", { status, delay });
116
- }
117
-
118
- // Clear any existing timeout
119
- if (completeTimeoutRef.current) {
120
- clearTimeout(completeTimeoutRef.current);
121
- }
103
+ if (completeTimeoutRef.current) clearTimeout(completeTimeoutRef.current);
122
104
 
123
105
  completeTimeoutRef.current = setTimeout(() => {
124
- if (!isMountedRef.current) {
125
- if (typeof __DEV__ !== "undefined" && __DEV__) {
126
- console.log("[Orchestrator] ⚠️ Component unmounted, skipping onComplete");
127
- }
128
- return;
129
- }
130
-
131
- if (typeof __DEV__ !== "undefined" && __DEV__) {
132
- console.log("[Orchestrator] 📍 Calling lifecycle.onComplete:", status);
133
- }
106
+ if (!isMountedRef.current) return;
134
107
 
135
108
  lifecycle.onComplete?.(status, result, error);
136
109
 
137
- // Auto-reset if configured
138
110
  if (lifecycle.autoReset) {
139
111
  const resetDelay = lifecycle.resetDelay ?? DEFAULT_RESET_DELAY;
140
- if (typeof __DEV__ !== "undefined" && __DEV__) {
141
- console.log("[Orchestrator] 🔄 Scheduling auto-reset in:", resetDelay);
142
- }
143
-
144
- if (resetTimeoutRef.current) {
145
- clearTimeout(resetTimeoutRef.current);
146
- }
112
+ if (resetTimeoutRef.current) clearTimeout(resetTimeoutRef.current);
147
113
 
148
114
  resetTimeoutRef.current = setTimeout(() => {
149
115
  if (isMountedRef.current) {
150
- if (typeof __DEV__ !== "undefined" && __DEV__) {
151
- console.log("[Orchestrator] 🔄 Auto-reset triggered");
152
- }
153
116
  setState(INITIAL_STATE);
154
117
  isGeneratingRef.current = false;
155
118
  }
@@ -160,74 +123,41 @@ export const useGenerationOrchestrator = <TInput, TResult>(
160
123
  [lifecycle],
161
124
  );
162
125
 
163
- // Core execution logic (after all checks pass)
164
126
  const executeGeneration = useCallback(
165
127
  async (input: TInput) => {
166
128
  const creditCost = strategy.getCreditCost();
167
129
 
168
130
  setState((prev) => ({ ...prev, status: "generating", progress: 10 }));
169
131
  if (typeof __DEV__ !== "undefined" && __DEV__) {
170
- console.log("[Orchestrator] 🎨 Starting strategy.execute()");
132
+ console.log("[Orchestrator] 🎨 Starting generation");
171
133
  }
172
134
 
173
135
  const result = await strategy.execute(input, (progress) => {
174
- if (typeof __DEV__ !== "undefined" && __DEV__) {
175
- console.log("[Orchestrator] 📊 Progress update:", progress);
176
- }
177
- if (isMountedRef.current) {
178
- setState((prev) => ({ ...prev, progress }));
179
- }
136
+ if (isMountedRef.current) setState((prev) => ({ ...prev, progress }));
180
137
  });
181
138
 
182
- if (typeof __DEV__ !== "undefined" && __DEV__) {
183
- console.log("[Orchestrator] ✅ strategy.execute() completed");
184
- }
139
+ if (isMountedRef.current) setState((prev) => ({ ...prev, progress: 70 }));
185
140
 
186
- if (isMountedRef.current) {
187
- setState((prev) => ({ ...prev, progress: 70 }));
188
- }
189
-
190
- // Save result
191
141
  if (strategy.save && userId) {
192
- if (isMountedRef.current) {
193
- setState((prev) => ({ ...prev, status: "saving" }));
194
- }
195
- if (typeof __DEV__ !== "undefined" && __DEV__) {
196
- console.log("[Orchestrator] 💾 Saving result...");
197
- }
142
+ if (isMountedRef.current) setState((prev) => ({ ...prev, status: "saving" }));
198
143
  try {
199
144
  await strategy.save(result, userId);
200
- if (typeof __DEV__ !== "undefined" && __DEV__) {
201
- console.log("[Orchestrator] ✅ Save completed");
202
- }
203
145
  } catch (saveErr) {
204
- if (typeof __DEV__ !== "undefined" && __DEV__) {
205
- console.log("[Orchestrator] ❌ Save failed:", saveErr);
206
- }
207
- throw createGenerationError("save", "Failed to save", saveErr instanceof Error ? saveErr : undefined);
146
+ throw createGenerationError(
147
+ "save",
148
+ "Failed to save",
149
+ saveErr instanceof Error ? saveErr : undefined,
150
+ );
208
151
  }
209
152
  }
210
153
 
211
- if (isMountedRef.current) {
212
- setState((prev) => ({ ...prev, progress: 90 }));
213
- }
154
+ if (isMountedRef.current) setState((prev) => ({ ...prev, progress: 90 }));
214
155
 
215
- // Deduct credit
216
- if (typeof __DEV__ !== "undefined" && __DEV__) {
217
- console.log("[Orchestrator] 💳 Deducting credit:", creditCost);
218
- }
219
156
  const creditDeducted = await deductCredit(creditCost);
220
157
  if (!creditDeducted) {
221
- if (typeof __DEV__ !== "undefined" && __DEV__) {
222
- console.log("[Orchestrator] ❌ Credit deduction failed");
223
- }
224
158
  throw createGenerationError("credits", "Failed to deduct credits");
225
159
  }
226
- if (typeof __DEV__ !== "undefined" && __DEV__) {
227
- console.log("[Orchestrator] ✅ Credit deducted successfully");
228
- }
229
160
 
230
- // Success
231
161
  if (isMountedRef.current) {
232
162
  setState({ status: "success", isGenerating: false, progress: 100, result, error: null });
233
163
  }
@@ -236,14 +166,8 @@ export const useGenerationOrchestrator = <TInput, TResult>(
236
166
  console.log("[Orchestrator] 🎉 Generation SUCCESS");
237
167
  }
238
168
 
239
- if (alertMessages.success) {
240
- void showSuccess("Success", alertMessages.success);
241
- }
242
-
243
- // Call onSuccess callback
169
+ if (alertMessages.success) void showSuccess("Success", alertMessages.success);
244
170
  onSuccess?.(result);
245
-
246
- // Handle lifecycle completion
247
171
  handleLifecycleComplete("success", result);
248
172
 
249
173
  return result;
@@ -255,105 +179,41 @@ export const useGenerationOrchestrator = <TInput, TResult>(
255
179
  async (input: TInput) => {
256
180
  if (typeof __DEV__ !== "undefined" && __DEV__) {
257
181
  console.log("[Orchestrator] 🚀 generate() called");
258
- console.log("[Orchestrator] Input:", JSON.stringify(input, null, 2).slice(0, 500));
259
182
  }
260
183
 
261
- if (isGeneratingRef.current) {
262
- if (typeof __DEV__ !== "undefined" && __DEV__) {
263
- console.log("[Orchestrator] ⚠️ Already generating, skipping");
264
- }
265
- return;
266
- }
184
+ if (isGeneratingRef.current) return;
267
185
 
268
186
  isGeneratingRef.current = true;
269
187
  pendingInputRef.current = input;
270
188
  setState({ ...INITIAL_STATE, status: "checking", isGenerating: true });
271
189
 
272
190
  try {
273
- // 1. Auth check (optional)
274
- if (auth) {
275
- setState((prev) => ({ ...prev, status: "authenticating" }));
276
- if (typeof __DEV__ !== "undefined" && __DEV__) {
277
- console.log("[Orchestrator] 🔐 Checking authentication...");
278
- }
279
-
280
- if (!auth.isAuthenticated()) {
281
- if (typeof __DEV__ !== "undefined" && __DEV__) {
282
- console.log("[Orchestrator] ❌ Not authenticated");
283
- }
284
- isGeneratingRef.current = false;
285
- setState(INITIAL_STATE);
286
- auth.onAuthRequired?.();
287
- return;
288
- }
289
- if (typeof __DEV__ !== "undefined" && __DEV__) {
290
- console.log("[Orchestrator] ✅ Authentication passed");
291
- }
292
- }
293
-
294
- // 2. Network check
295
191
  if (!offlineStore.isOnline) {
296
- if (typeof __DEV__ !== "undefined" && __DEV__) {
297
- console.log("[Orchestrator] ❌ Network check failed - offline");
298
- }
299
192
  throw createGenerationError("network", "No internet connection");
300
193
  }
301
- if (typeof __DEV__ !== "undefined" && __DEV__) {
302
- console.log("[Orchestrator] ✅ Network check passed");
303
- }
304
194
 
305
- // 3. Credit check
306
195
  const creditCost = strategy.getCreditCost();
307
- if (typeof __DEV__ !== "undefined" && __DEV__) {
308
- console.log("[Orchestrator] 💳 Credit cost:", creditCost);
309
- }
310
-
311
196
  const hasCredits = await checkCredits(creditCost);
312
197
  if (!hasCredits) {
313
- if (typeof __DEV__ !== "undefined" && __DEV__) {
314
- console.log("[Orchestrator] ❌ No credits, opening paywall");
315
- }
316
198
  isGeneratingRef.current = false;
317
199
  setState(INITIAL_STATE);
318
200
  handleCreditsExhausted?.();
319
201
  return;
320
202
  }
321
- if (typeof __DEV__ !== "undefined" && __DEV__) {
322
- console.log("[Orchestrator] ✅ Credit check passed");
323
- }
324
203
 
325
- // 4. Content moderation (optional)
326
204
  if (moderation) {
327
205
  setState((prev) => ({ ...prev, status: "moderating" }));
328
- if (typeof __DEV__ !== "undefined" && __DEV__) {
329
- console.log("[Orchestrator] 🛡️ Checking content moderation...");
330
- }
331
-
332
206
  const moderationResult = await moderation.checkContent(input);
333
- if (!moderationResult.allowed && moderationResult.warnings.length > 0) {
334
- if (typeof __DEV__ !== "undefined" && __DEV__) {
335
- console.log("[Orchestrator] ⚠️ Moderation warnings:", moderationResult.warnings);
336
- }
337
207
 
208
+ if (!moderationResult.allowed && moderationResult.warnings.length > 0) {
338
209
  if (moderation.onShowWarning) {
339
- // Show warning and let user decide
340
210
  moderation.onShowWarning(
341
211
  moderationResult.warnings,
342
212
  () => {
343
- // User cancelled
344
- if (typeof __DEV__ !== "undefined" && __DEV__) {
345
- console.log("[Orchestrator] User cancelled after moderation warning");
346
- }
347
213
  isGeneratingRef.current = false;
348
- if (isMountedRef.current) {
349
- setState(INITIAL_STATE);
350
- }
214
+ if (isMountedRef.current) setState(INITIAL_STATE);
351
215
  },
352
216
  async () => {
353
- // User continued - execute generation
354
- if (typeof __DEV__ !== "undefined" && __DEV__) {
355
- console.log("[Orchestrator] User continued after moderation warning");
356
- }
357
217
  try {
358
218
  await executeGeneration(input);
359
219
  } catch (err) {
@@ -369,41 +229,30 @@ export const useGenerationOrchestrator = <TInput, TResult>(
369
229
  }
370
230
  },
371
231
  );
372
- return; // Exit here - callback will handle the rest
232
+ return;
373
233
  }
374
- // No warning handler - block the request
375
234
  throw createGenerationError("policy", "Content policy violation");
376
235
  }
377
- if (typeof __DEV__ !== "undefined" && __DEV__) {
378
- console.log("[Orchestrator] ✅ Moderation passed");
379
- }
380
236
  }
381
237
 
382
- // 5. Execute generation
383
238
  return await executeGeneration(input);
384
239
  } catch (err) {
385
240
  const error = parseError(err);
386
241
  if (typeof __DEV__ !== "undefined" && __DEV__) {
387
- console.log("[Orchestrator] ❌ Generation ERROR:", error);
242
+ console.log("[Orchestrator] ❌ Error:", error);
388
243
  }
389
244
  if (isMountedRef.current) {
390
245
  setState({ status: "error", isGenerating: false, progress: 0, result: null, error });
391
246
  }
392
247
  void showError("Error", getAlertMessage(error, alertMessages));
393
248
  onError?.(error);
394
-
395
- // Handle lifecycle completion for errors
396
249
  handleLifecycleComplete("error", undefined, error);
397
- throw error; // Re-throw so caller knows it failed
250
+ throw error;
398
251
  } finally {
399
252
  isGeneratingRef.current = false;
400
- if (typeof __DEV__ !== "undefined" && __DEV__) {
401
- console.log("[Orchestrator] 🏁 generate() finished");
402
- }
403
253
  }
404
254
  },
405
255
  [
406
- auth,
407
256
  moderation,
408
257
  strategy,
409
258
  alertMessages,
@@ -418,9 +267,6 @@ export const useGenerationOrchestrator = <TInput, TResult>(
418
267
  );
419
268
 
420
269
  const reset = useCallback(() => {
421
- if (typeof __DEV__ !== "undefined" && __DEV__) {
422
- console.log("[Orchestrator] 🔄 reset() called");
423
- }
424
270
  setState(INITIAL_STATE);
425
271
  isGeneratingRef.current = false;
426
272
  }, []);
@@ -6,7 +6,6 @@
6
6
  export type OrchestratorStatus =
7
7
  | "idle"
8
8
  | "checking"
9
- | "authenticating"
10
9
  | "moderating"
11
10
  | "generating"
12
11
  | "saving"
@@ -14,14 +13,8 @@ export type OrchestratorStatus =
14
13
  | "error";
15
14
 
16
15
  export interface GenerationStrategy<TInput, TResult> {
17
- /** Execute the generation */
18
- execute: (
19
- input: TInput,
20
- onProgress?: (progress: number) => void,
21
- ) => Promise<TResult>;
22
- /** Credit cost for this generation */
16
+ execute: (input: TInput, onProgress?: (progress: number) => void) => Promise<TResult>;
23
17
  getCreditCost: () => number;
24
- /** Optional: Save result to storage */
25
18
  save?: (result: TResult, userId: string) => Promise<void>;
26
19
  }
27
20
 
@@ -32,61 +25,28 @@ export interface AlertMessages {
32
25
  creditFailed: string;
33
26
  unknown: string;
34
27
  success?: string;
35
- authRequired?: string;
36
28
  }
37
29
 
38
- /** Content moderation result */
39
30
  export interface ModerationResult {
40
31
  allowed: boolean;
41
32
  warnings: string[];
42
33
  }
43
34
 
44
- /** Auth callbacks for features that need authentication */
45
- export interface AuthCallbacks {
46
- /** Check if user is authenticated */
47
- isAuthenticated: () => boolean;
48
- /** Called when auth is required */
49
- onAuthRequired?: () => void;
50
- }
51
-
52
- /** Moderation callbacks for content filtering */
53
35
  export interface ModerationCallbacks {
54
- /** Check content for policy violations */
55
36
  checkContent: (input: unknown) => Promise<ModerationResult>;
56
- /** Show moderation warning with continue/cancel options */
57
- onShowWarning?: (
58
- warnings: string[],
59
- onCancel: () => void,
60
- onContinue: () => void,
61
- ) => void;
37
+ onShowWarning?: (warnings: string[], onCancel: () => void, onContinue: () => void) => void;
62
38
  }
63
39
 
64
- /** Credit callbacks for features that manage credits via callbacks */
65
40
  export interface CreditCallbacks {
66
- /** Check if user can afford the cost */
67
41
  checkCredits: (cost: number) => Promise<boolean>;
68
- /** Deduct credits after successful generation - returns true if successful */
69
42
  deductCredits: (cost: number) => Promise<boolean>;
70
- /** Called when credits are exhausted */
71
43
  onCreditsExhausted?: () => void;
72
44
  }
73
45
 
74
- /**
75
- * Lifecycle configuration for generation flow
76
- * Centralizes post-generation behavior (navigation, cleanup, etc.)
77
- */
78
46
  export interface LifecycleConfig {
79
- /** Callback after generation completes (success or error) - for navigation, state updates */
80
- onComplete?: (
81
- status: "success" | "error",
82
- result?: unknown,
83
- error?: GenerationError,
84
- ) => void;
85
- /** Delay before calling onComplete (ms) - allows UI to show success state */
47
+ onComplete?: (status: "success" | "error", result?: unknown, error?: GenerationError) => void;
86
48
  completeDelay?: number;
87
- /** Auto-reset state after completion */
88
49
  autoReset?: boolean;
89
- /** Delay before auto-reset (ms) */
90
50
  resetDelay?: number;
91
51
  }
92
52
 
@@ -96,13 +56,8 @@ export interface GenerationConfig {
96
56
  onCreditsExhausted?: () => void;
97
57
  onSuccess?: (result: unknown) => void;
98
58
  onError?: (error: GenerationError) => void;
99
- /** Optional auth callbacks - if not provided, auth is skipped */
100
- auth?: AuthCallbacks;
101
- /** Optional moderation callbacks - if not provided, moderation is skipped */
102
59
  moderation?: ModerationCallbacks;
103
- /** Optional credit callbacks - if provided, overrides default useDeductCredit */
104
60
  credits?: CreditCallbacks;
105
- /** Lifecycle configuration for post-generation behavior */
106
61
  lifecycle?: LifecycleConfig;
107
62
  }
108
63
 
@@ -120,12 +75,7 @@ export interface GenerationError {
120
75
  originalError?: Error;
121
76
  }
122
77
 
123
- export type GenerationErrorType =
124
- | "network"
125
- | "credits"
126
- | "policy"
127
- | "save"
128
- | "unknown";
78
+ export type GenerationErrorType = "network" | "credits" | "policy" | "save" | "unknown";
129
79
 
130
80
  export interface UseGenerationOrchestratorReturn<TInput, TResult> {
131
81
  generate: (input: TInput) => Promise<TResult | void>;
@@ -137,22 +87,15 @@ export interface UseGenerationOrchestratorReturn<TInput, TResult> {
137
87
  error: GenerationError | null;
138
88
  }
139
89
 
140
- /**
141
- * Generation error UI configuration
142
- */
143
90
  export interface GenerationErrorConfig {
144
91
  readonly showCreditInfo?: boolean;
145
92
  readonly iconName?: string;
146
93
  readonly iconSize?: number;
147
94
  }
148
95
 
149
- /**
150
- * Generation error UI translations
151
- */
152
96
  export interface GenerationErrorTranslations {
153
97
  readonly title: string;
154
98
  readonly tryAgain: string;
155
99
  readonly chooseAnother: string;
156
100
  readonly noCreditCharged: string;
157
101
  }
158
-