@umituz/react-native-ai-generation-content 1.19.6 → 1.19.8

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.19.6",
3
+ "version": "1.19.8",
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",
@@ -18,23 +18,51 @@ export async function executeCoupleFuture(
18
18
  input: CoupleFutureInput,
19
19
  config?: CoupleFutureConfig,
20
20
  ): Promise<CoupleFutureResult> {
21
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
22
+ console.log("[Executor] ========== COUPLE FUTURE START ==========");
23
+ console.log("[Executor] Input received:", {
24
+ hasPartnerA: !!input.partnerABase64,
25
+ partnerALength: input.partnerABase64?.length || 0,
26
+ hasPartnerB: !!input.partnerBBase64,
27
+ partnerBLength: input.partnerBBase64?.length || 0,
28
+ promptLength: input.prompt?.length || 0,
29
+ prompt: input.prompt?.slice(0, 300),
30
+ });
31
+ console.log("[Executor] Config:", {
32
+ hasOnProgress: !!config?.onProgress,
33
+ timeoutMs: config?.timeoutMs,
34
+ aspectRatio: config?.aspectRatio,
35
+ outputFormat: config?.outputFormat,
36
+ });
37
+ }
38
+
21
39
  const provider = providerRegistry.getActiveProvider();
22
40
 
23
41
  if (!provider) {
42
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
43
+ console.log("[Executor] ❌ No AI provider configured");
44
+ }
24
45
  return { success: false, error: "No AI provider configured" };
25
46
  }
26
47
 
48
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
49
+ console.log("[Executor] ✅ Provider found:", provider.constructor.name);
50
+ }
51
+
27
52
  if (!provider.isInitialized()) {
53
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
54
+ console.log("[Executor] ❌ AI provider not initialized");
55
+ }
28
56
  return { success: false, error: "AI provider not initialized" };
29
57
  }
30
58
 
31
- const { onProgress, timeoutMs, aspectRatio, outputFormat } = config ?? {};
32
- let lastStatus = "";
33
-
34
59
  if (typeof __DEV__ !== "undefined" && __DEV__) {
35
- console.log("[CoupleFuture] Starting Nano Banana generation");
60
+ console.log("[Executor] Provider initialized");
36
61
  }
37
62
 
63
+ const { onProgress, timeoutMs, aspectRatio, outputFormat } = config ?? {};
64
+ let lastStatus = "";
65
+
38
66
  try {
39
67
  onProgress?.(5);
40
68
 
@@ -42,7 +70,18 @@ export async function executeCoupleFuture(
42
70
  .filter(Boolean)
43
71
  .map(formatBase64);
44
72
 
73
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
74
+ console.log("[Executor] 🖼️ Image URLs prepared:", {
75
+ count: imageUrls.length,
76
+ url1Length: imageUrls[0]?.length || 0,
77
+ url2Length: imageUrls[1]?.length || 0,
78
+ });
79
+ }
80
+
45
81
  if (imageUrls.length < 2) {
82
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
83
+ console.log("[Executor] ❌ Two reference images required, got:", imageUrls.length);
84
+ }
46
85
  return { success: false, error: "Two reference images required" };
47
86
  }
48
87
 
@@ -59,7 +98,16 @@ export async function executeCoupleFuture(
59
98
  };
60
99
 
61
100
  if (typeof __DEV__ !== "undefined" && __DEV__) {
62
- console.log("[CoupleFuture] Prompt:", enhancedPrompt);
101
+ console.log("[Executor] 📤 FAL AI Request:");
102
+ console.log("[Executor] Model:", COUPLE_FUTURE_DEFAULTS.model);
103
+ console.log("[Executor] Prompt:", enhancedPrompt.slice(0, 400));
104
+ console.log("[Executor] Aspect ratio:", modelInput.aspect_ratio);
105
+ console.log("[Executor] Output format:", modelInput.output_format);
106
+ console.log("[Executor] Timeout:", timeoutMs ?? COUPLE_FUTURE_DEFAULTS.timeoutMs);
107
+ }
108
+
109
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
110
+ console.log("[Executor] 📡 Calling provider.subscribe()...");
63
111
  }
64
112
 
65
113
  const result = await provider.subscribe(COUPLE_FUTURE_DEFAULTS.model, modelInput, {
@@ -69,7 +117,10 @@ export async function executeCoupleFuture(
69
117
  lastStatus = status.status;
70
118
 
71
119
  if (typeof __DEV__ !== "undefined" && __DEV__) {
72
- console.log("[CoupleFuture] Status:", status.status);
120
+ console.log("[Executor] 📊 Queue status update:", {
121
+ status: status.status,
122
+ logs: status.logs?.slice(-3),
123
+ });
73
124
  }
74
125
 
75
126
  if (status.status === "IN_QUEUE") onProgress?.(20);
@@ -80,8 +131,10 @@ export async function executeCoupleFuture(
80
131
  onProgress?.(90);
81
132
 
82
133
  if (typeof __DEV__ !== "undefined" && __DEV__) {
83
- console.log("[CoupleFuture] Raw result:", JSON.stringify(result, null, 2));
84
- console.log("[CoupleFuture] Result keys:", result ? Object.keys(result as object) : "null");
134
+ console.log("[Executor] 📥 FAL AI Response received");
135
+ console.log("[Executor] Raw result type:", typeof result);
136
+ console.log("[Executor] Raw result keys:", result ? Object.keys(result as object) : "null");
137
+ console.log("[Executor] Raw result:", JSON.stringify(result, null, 2).slice(0, 1000));
85
138
  }
86
139
 
87
140
  const rawResult = result as Record<string, unknown>;
@@ -89,21 +142,38 @@ export async function executeCoupleFuture(
89
142
  const imageUrl = data?.images?.[0]?.url;
90
143
 
91
144
  if (typeof __DEV__ !== "undefined" && __DEV__) {
92
- console.log("[CoupleFuture] Parsed data:", JSON.stringify(data, null, 2));
93
- console.log("[CoupleFuture] Image URL:", imageUrl);
145
+ console.log("[Executor] 🔍 Parsed response:");
146
+ console.log("[Executor] Has data:", !!data);
147
+ console.log("[Executor] Images array length:", data?.images?.length || 0);
148
+ console.log("[Executor] First image URL:", imageUrl?.slice(0, 100));
94
149
  }
95
150
 
96
151
  onProgress?.(100);
97
152
 
98
153
  if (!imageUrl) {
154
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
155
+ console.log("[Executor] ❌ No image URL in response");
156
+ console.log("[Executor] ========== COUPLE FUTURE END (FAILED) ==========");
157
+ }
99
158
  return { success: false, error: "No image generated" };
100
159
  }
101
160
 
161
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
162
+ console.log("[Executor] ✅ Generation successful!");
163
+ console.log("[Executor] Image URL:", imageUrl.slice(0, 100));
164
+ console.log("[Executor] ========== COUPLE FUTURE END (SUCCESS) ==========");
165
+ }
166
+
102
167
  return { success: true, imageUrl };
103
168
  } catch (error) {
104
169
  const message = error instanceof Error ? error.message : "Generation failed";
105
170
  if (typeof __DEV__ !== "undefined" && __DEV__) {
106
- console.error("[CoupleFuture] Error:", message);
171
+ console.error("[Executor] ❌ Exception caught:", {
172
+ message,
173
+ name: error instanceof Error ? error.name : "Unknown",
174
+ stack: error instanceof Error ? error.stack?.slice(0, 500) : undefined,
175
+ });
176
+ console.log("[Executor] ========== COUPLE FUTURE END (ERROR) ==========");
107
177
  }
108
178
  return { success: false, error: message };
109
179
  }
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Couple Future Flow Types
3
+ * Type definitions for couple future wizard flow
4
+ */
5
+
6
+ export interface CoupleFutureFlowConfig<TStep, TScenarioId> {
7
+ steps: {
8
+ SCENARIO: TStep;
9
+ SCENARIO_PREVIEW: TStep;
10
+ COUPLE_FEATURE_SELECTOR: TStep;
11
+ TEXT_INPUT: TStep;
12
+ PARTNER_A: TStep;
13
+ PARTNER_B: TStep;
14
+ GENERATING: TStep;
15
+ };
16
+ customScenarioId: TScenarioId;
17
+ }
18
+
19
+ export interface CoupleFutureFlowState<TStep, TScenarioId> {
20
+ step: TStep;
21
+ selectedScenarioId: TScenarioId | null;
22
+ selectedFeature: string | null;
23
+ partnerA: unknown;
24
+ partnerB: unknown;
25
+ partnerAName: string;
26
+ partnerBName: string;
27
+ customPrompt: string | null;
28
+ visualStyle: string | null;
29
+ selection: unknown;
30
+ isProcessing: boolean;
31
+ scenarioConfig: unknown;
32
+ selectedScenarioData: { requiresPhoto?: boolean } | null;
33
+ }
34
+
35
+ export interface CoupleFutureFlowActions<TStep, TScenarioId, TResult> {
36
+ setStep: (step: TStep) => void;
37
+ selectScenario: (id: TScenarioId) => void;
38
+ setPartnerA: (image: unknown) => void;
39
+ setPartnerAName: (name: string) => void;
40
+ setPartnerB: (image: unknown) => void;
41
+ setPartnerBName: (name: string) => void;
42
+ setCustomPrompt: (prompt: string) => void;
43
+ setVisualStyle: (style: string) => void;
44
+ startGeneration: () => void;
45
+ generationSuccess: (result: TResult) => void;
46
+ generationError: (error: string) => void;
47
+ requireFeature: (callback: () => void) => void;
48
+ onNavigateToHistory: () => void;
49
+ }
50
+
51
+ export interface CoupleFutureFlowProps<TStep, TScenarioId, TResult> {
52
+ userId?: string;
53
+ config: CoupleFutureFlowConfig<TStep, TScenarioId>;
54
+ state: CoupleFutureFlowState<TStep, TScenarioId>;
55
+ actions: CoupleFutureFlowActions<TStep, TScenarioId, TResult>;
56
+ generationConfig: {
57
+ visualStyleModifiers: Record<string, string>;
58
+ defaultPartnerAName: string;
59
+ defaultPartnerBName: string;
60
+ };
61
+ alertMessages: {
62
+ networkError: string;
63
+ policyViolation: string;
64
+ saveFailed: string;
65
+ creditFailed: string;
66
+ unknown: string;
67
+ };
68
+ processResult: (imageUrl: string, input: unknown) => TResult;
69
+ buildCreation: (result: TResult, input: unknown) => unknown;
70
+ onCreditsExhausted: () => void;
71
+ }
@@ -8,73 +8,21 @@ import { InteractionManager } from "react-native";
8
8
  import { useCoupleFutureGeneration } from "./useCoupleFutureGeneration";
9
9
  import { buildGenerationInputFromConfig } from "../../infrastructure/generationUtils";
10
10
  import type { UploadedImage } from "../../../partner-upload/domain/types";
11
-
12
- export interface CoupleFutureFlowConfig<TStep, TScenarioId> {
13
- steps: {
14
- SCENARIO: TStep;
15
- SCENARIO_PREVIEW: TStep;
16
- COUPLE_FEATURE_SELECTOR: TStep;
17
- TEXT_INPUT: TStep;
18
- PARTNER_A: TStep;
19
- PARTNER_B: TStep;
20
- GENERATING: TStep;
21
- };
22
- customScenarioId: TScenarioId;
23
- }
24
-
25
- export interface CoupleFutureFlowState<TStep, TScenarioId> {
26
- step: TStep;
27
- selectedScenarioId: TScenarioId | null;
28
- selectedFeature: string | null;
29
- partnerA: unknown;
30
- partnerB: unknown;
31
- partnerAName: string;
32
- partnerBName: string;
33
- customPrompt: string | null;
34
- visualStyle: string | null;
35
- selection: unknown;
36
- isProcessing: boolean;
37
- scenarioConfig: unknown;
38
- selectedScenarioData: { requiresPhoto?: boolean } | null;
39
- }
40
-
41
- export interface CoupleFutureFlowActions<TStep, TScenarioId, TResult> {
42
- setStep: (step: TStep) => void;
43
- selectScenario: (id: TScenarioId) => void;
44
- setPartnerA: (image: unknown) => void;
45
- setPartnerAName: (name: string) => void;
46
- setPartnerB: (image: unknown) => void;
47
- setPartnerBName: (name: string) => void;
48
- setCustomPrompt: (prompt: string) => void;
49
- setVisualStyle: (style: string) => void;
50
- startGeneration: () => void;
51
- generationSuccess: (result: TResult) => void;
52
- generationError: (error: string) => void;
53
- requireFeature: (callback: () => void) => void;
54
- onNavigateToHistory: () => void;
55
- }
56
-
57
- export interface CoupleFutureFlowProps<TStep, TScenarioId, TResult> {
58
- userId?: string;
59
- config: CoupleFutureFlowConfig<TStep, TScenarioId>;
60
- state: CoupleFutureFlowState<TStep, TScenarioId>;
61
- actions: CoupleFutureFlowActions<TStep, TScenarioId, TResult>;
62
- generationConfig: {
63
- visualStyleModifiers: Record<string, string>;
64
- defaultPartnerAName: string;
65
- defaultPartnerBName: string;
66
- };
67
- alertMessages: {
68
- networkError: string;
69
- policyViolation: string;
70
- saveFailed: string;
71
- creditFailed: string;
72
- unknown: string;
73
- };
74
- processResult: (imageUrl: string, input: unknown) => TResult;
75
- buildCreation: (result: TResult, input: unknown) => unknown;
76
- onCreditsExhausted: () => void;
77
- }
11
+ import type {
12
+ CoupleFutureFlowConfig,
13
+ CoupleFutureFlowState,
14
+ CoupleFutureFlowActions,
15
+ CoupleFutureFlowProps,
16
+ } from "./coupleFutureFlow.types";
17
+
18
+ declare const __DEV__: boolean;
19
+
20
+ export type {
21
+ CoupleFutureFlowConfig,
22
+ CoupleFutureFlowState,
23
+ CoupleFutureFlowActions,
24
+ CoupleFutureFlowProps,
25
+ };
78
26
 
79
27
  export const useCoupleFutureFlow = <TStep, TScenarioId, TResult>(
80
28
  props: CoupleFutureFlowProps<TStep, TScenarioId, TResult>,
@@ -83,82 +31,110 @@ export const useCoupleFutureFlow = <TStep, TScenarioId, TResult>(
83
31
  const { processResult, buildCreation, onCreditsExhausted, userId } = props;
84
32
  const hasStarted = useRef(false);
85
33
 
86
- const { generate, isGenerating, progress } =
87
- useCoupleFutureGeneration<TResult>({
88
- userId,
89
- onCreditsExhausted,
90
- onSuccess: (result) => {
91
- actions.generationSuccess(result);
92
- InteractionManager.runAfterInteractions(() => {
93
- setTimeout(() => actions.onNavigateToHistory(), 300);
94
- });
95
- },
96
- onError: actions.generationError,
97
- processResult: processResult as never,
98
- buildCreation: buildCreation as never,
99
- alertMessages,
100
- });
34
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
35
+ console.log("[CoupleFutureFlow] Hook initialized:", { userId, step: state.step });
36
+ }
101
37
 
102
- const {
103
- step,
104
- isProcessing,
105
- partnerA,
106
- partnerB,
107
- partnerAName,
108
- partnerBName,
109
- scenarioConfig,
110
- customPrompt,
111
- visualStyle,
112
- selection,
113
- selectedFeature,
114
- selectedScenarioId,
115
- selectedScenarioData,
116
- } = state;
38
+ const { generate, isGenerating, progress } = useCoupleFutureGeneration<TResult>({
39
+ userId,
40
+ onCreditsExhausted,
41
+ onSuccess: (result) => {
42
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
43
+ console.log("[CoupleFutureFlow] 🎉 onSuccess callback triggered");
44
+ }
45
+ actions.generationSuccess(result);
46
+ InteractionManager.runAfterInteractions(() => {
47
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
48
+ console.log("[CoupleFutureFlow] 🔄 Navigating to History in 300ms...");
49
+ }
50
+ setTimeout(() => actions.onNavigateToHistory(), 300);
51
+ });
52
+ },
53
+ onError: (error) => {
54
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
55
+ console.log("[CoupleFutureFlow] ❌ onError callback:", error);
56
+ }
57
+ actions.generationError(error);
58
+ },
59
+ processResult: processResult as never,
60
+ buildCreation: buildCreation as never,
61
+ alertMessages,
62
+ });
63
+
64
+ const { step, isProcessing, selectedFeature, selectedScenarioId, selectedScenarioData } = state;
117
65
 
118
66
  useEffect(() => {
67
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
68
+ console.log("[CoupleFutureFlow] useEffect triggered:", {
69
+ step,
70
+ isProcessing,
71
+ hasStarted: hasStarted.current,
72
+ targetStep: config.steps.GENERATING,
73
+ });
74
+ }
75
+
119
76
  if (step !== config.steps.GENERATING) {
120
77
  hasStarted.current = false;
121
78
  return;
122
79
  }
123
- if (!isProcessing || hasStarted.current) return;
80
+ if (!isProcessing || hasStarted.current) {
81
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
82
+ console.log("[CoupleFutureFlow] ⚠️ Skipping generation:", {
83
+ reason: !isProcessing ? "isProcessing=false" : "already started",
84
+ });
85
+ }
86
+ return;
87
+ }
124
88
  hasStarted.current = true;
125
89
 
90
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
91
+ console.log("[CoupleFutureFlow] 🚀 Building generation input...");
92
+ console.log("[CoupleFutureFlow] State:", {
93
+ hasPartnerA: !!state.partnerA,
94
+ hasPartnerB: !!state.partnerB,
95
+ partnerAName: state.partnerAName,
96
+ partnerBName: state.partnerBName,
97
+ hasScenarioConfig: !!state.scenarioConfig,
98
+ customPrompt: state.customPrompt?.slice(0, 100),
99
+ visualStyle: state.visualStyle,
100
+ });
101
+ }
102
+
126
103
  const input = buildGenerationInputFromConfig({
127
- partnerA: partnerA as never,
128
- partnerB: partnerB as never,
129
- partnerAName,
130
- partnerBName,
131
- scenario: scenarioConfig as never,
132
- customPrompt: customPrompt || undefined,
133
- visualStyle: visualStyle || "",
104
+ partnerA: state.partnerA as never,
105
+ partnerB: state.partnerB as never,
106
+ partnerAName: state.partnerAName,
107
+ partnerBName: state.partnerBName,
108
+ scenario: state.scenarioConfig as never,
109
+ customPrompt: state.customPrompt || undefined,
110
+ visualStyle: state.visualStyle || "",
134
111
  defaultPartnerAName: generationConfig.defaultPartnerAName,
135
112
  defaultPartnerBName: generationConfig.defaultPartnerBName,
136
- coupleFeatureSelection: selection as never,
113
+ coupleFeatureSelection: state.selection as never,
137
114
  visualStyles: generationConfig.visualStyleModifiers,
138
115
  customScenarioId: config.customScenarioId as string,
139
116
  });
140
- if (input) generate(input);
141
- }, [
142
- step,
143
- isProcessing,
144
- partnerA,
145
- partnerB,
146
- partnerAName,
147
- partnerBName,
148
- scenarioConfig,
149
- customPrompt,
150
- visualStyle,
151
- selection,
152
- config.steps.GENERATING,
153
- config.customScenarioId,
154
- generationConfig.defaultPartnerAName,
155
- generationConfig.defaultPartnerBName,
156
- generationConfig.visualStyleModifiers,
157
- generate,
158
- ]);
117
+
118
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
119
+ console.log("[CoupleFutureFlow] 📦 Generation input built:", {
120
+ hasInput: !!input,
121
+ prompt: input?.prompt?.slice(0, 200),
122
+ });
123
+ }
124
+
125
+ if (input) {
126
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
127
+ console.log("[CoupleFutureFlow] 🚀 Calling generate()...");
128
+ }
129
+ generate(input);
130
+ }
131
+ }, [step, isProcessing, state, config, generationConfig, generate]);
159
132
 
160
133
  const handleScenarioSelect = useCallback(
161
134
  (id: string) => {
135
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
136
+ console.log("[CoupleFutureFlow] handleScenarioSelect:", id);
137
+ }
162
138
  actions.selectScenario(id as TScenarioId);
163
139
  actions.setStep(config.steps.SCENARIO_PREVIEW);
164
140
  },
@@ -181,19 +157,13 @@ export const useCoupleFutureFlow = <TStep, TScenarioId, TResult>(
181
157
  } else {
182
158
  actions.setStep(config.steps.PARTNER_A);
183
159
  }
184
- }, [
185
- actions,
186
- config.steps.COUPLE_FEATURE_SELECTOR,
187
- config.steps.TEXT_INPUT,
188
- config.steps.PARTNER_A,
189
- config.customScenarioId,
190
- selectedFeature,
191
- selectedScenarioId,
192
- selectedScenarioData,
193
- ]);
160
+ }, [actions, config, selectedFeature, selectedScenarioId, selectedScenarioData]);
194
161
 
195
162
  const handlePartnerAContinue = useCallback(
196
163
  (image: UploadedImage, name: string) => {
164
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
165
+ console.log("[CoupleFutureFlow] handlePartnerAContinue:", { hasImage: !!image, name });
166
+ }
197
167
  actions.setPartnerA(image);
198
168
  actions.setPartnerAName(name);
199
169
  actions.setStep(config.steps.PARTNER_B);
@@ -202,22 +172,23 @@ export const useCoupleFutureFlow = <TStep, TScenarioId, TResult>(
202
172
  );
203
173
 
204
174
  const handlePartnerABack = useCallback(() => {
205
- actions.setStep(
175
+ const targetStep =
206
176
  selectedScenarioId === config.customScenarioId
207
177
  ? config.steps.TEXT_INPUT
208
- : config.steps.SCENARIO_PREVIEW,
209
- );
210
- }, [
211
- actions,
212
- config.customScenarioId,
213
- config.steps.TEXT_INPUT,
214
- config.steps.SCENARIO_PREVIEW,
215
- selectedScenarioId,
216
- ]);
178
+ : config.steps.SCENARIO_PREVIEW;
179
+ actions.setStep(targetStep);
180
+ }, [actions, config, selectedScenarioId]);
217
181
 
218
182
  const handlePartnerBContinue = useCallback(
219
183
  (image: UploadedImage, name: string) => {
184
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
185
+ console.log("[CoupleFutureFlow] handlePartnerBContinue:", { hasImage: !!image, name });
186
+ console.log("[CoupleFutureFlow] Calling requireFeature()...");
187
+ }
220
188
  actions.requireFeature(() => {
189
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
190
+ console.log("[CoupleFutureFlow] 🔓 Feature gate passed, starting generation");
191
+ }
221
192
  actions.setPartnerB(image);
222
193
  actions.setPartnerBName(name);
223
194
  actions.startGeneration();
@@ -233,6 +204,12 @@ export const useCoupleFutureFlow = <TStep, TScenarioId, TResult>(
233
204
 
234
205
  const handleMagicPromptContinue = useCallback(
235
206
  (prompt: string, style: string) => {
207
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
208
+ console.log("[CoupleFutureFlow] handleMagicPromptContinue:", {
209
+ promptLength: prompt.length,
210
+ style,
211
+ });
212
+ }
236
213
  actions.setCustomPrompt(prompt);
237
214
  actions.setVisualStyle(style);
238
215
  if (selectedScenarioId === config.customScenarioId) {
@@ -241,7 +218,7 @@ export const useCoupleFutureFlow = <TStep, TScenarioId, TResult>(
241
218
  actions.startGeneration();
242
219
  }
243
220
  },
244
- [actions, config.customScenarioId, config.steps.PARTNER_A, selectedScenarioId],
221
+ [actions, config, selectedScenarioId],
245
222
  );
246
223
 
247
224
  const handleMagicPromptBack = useCallback(
@@ -14,6 +14,8 @@ import type { CoupleFutureInput } from "../../domain/types";
14
14
  import { createCreationsRepository } from "../../../../domains/creations/infrastructure/adapters";
15
15
  import type { Creation } from "../../../../domains/creations/domain/entities/Creation";
16
16
 
17
+ declare const __DEV__: boolean;
18
+
17
19
  export interface CoupleFutureConfig<TResult> {
18
20
  userId: string | undefined;
19
21
  processResult: (imageUrl: string, input: CoupleFutureInput) => TResult;
@@ -24,33 +26,36 @@ export interface CoupleFutureConfig<TResult> {
24
26
  alertMessages: AlertMessages;
25
27
  }
26
28
 
27
- export const useCoupleFutureGeneration = <TResult>(
28
- config: CoupleFutureConfig<TResult>,
29
- ) => {
30
- const {
31
- userId,
32
- processResult,
33
- buildCreation,
34
- onCreditsExhausted,
35
- onSuccess,
36
- onError,
37
- alertMessages,
38
- } = config;
29
+ export const useCoupleFutureGeneration = <TResult>(config: CoupleFutureConfig<TResult>) => {
30
+ const { userId, processResult, buildCreation, onCreditsExhausted, onSuccess, onError, alertMessages } = config;
39
31
 
40
- const repository = useMemo(
41
- () => createCreationsRepository("creations"),
42
- [],
43
- );
32
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
33
+ console.log("[CoupleFutureGeneration] Hook initialized:", {
34
+ userId,
35
+ hasBuildCreation: !!buildCreation,
36
+ hasOnSuccess: !!onSuccess,
37
+ });
38
+ }
44
39
 
45
- // Store input for use in save callback
40
+ const repository = useMemo(() => createCreationsRepository("creations"), []);
46
41
  const lastInputRef = useRef<CoupleFutureInput | null>(null);
47
42
 
48
43
  const strategy: GenerationStrategy<CoupleFutureInput, TResult> = useMemo(
49
44
  () => ({
50
45
  execute: async (input, onProgress) => {
51
- // Store input for save callback
46
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
47
+ console.log("[CoupleFutureGeneration] 🎯 strategy.execute() START");
48
+ console.log("[CoupleFutureGeneration] Input prompt:", input.prompt?.slice(0, 200));
49
+ console.log("[CoupleFutureGeneration] Has partnerA:", !!input.partnerABase64);
50
+ console.log("[CoupleFutureGeneration] Has partnerB:", !!input.partnerBBase64);
51
+ }
52
+
52
53
  lastInputRef.current = input;
53
54
 
55
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
56
+ console.log("[CoupleFutureGeneration] 📡 Calling executeCoupleFuture()...");
57
+ }
58
+
54
59
  const result = await executeCoupleFuture(
55
60
  {
56
61
  partnerABase64: input.partnerABase64,
@@ -60,20 +65,44 @@ export const useCoupleFutureGeneration = <TResult>(
60
65
  { onProgress },
61
66
  );
62
67
 
68
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
69
+ console.log("[CoupleFutureGeneration] 📡 executeCoupleFuture() returned:", {
70
+ success: result.success,
71
+ hasImageUrl: !!result.imageUrl,
72
+ error: result.error,
73
+ });
74
+ }
75
+
63
76
  if (!result.success || !result.imageUrl) {
77
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
78
+ console.log("[CoupleFutureGeneration] ❌ Generation failed:", result.error);
79
+ }
64
80
  throw new Error(result.error || "Generation failed");
65
81
  }
66
82
 
83
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
84
+ console.log("[CoupleFutureGeneration] ✅ Processing result with processResult()");
85
+ }
86
+
67
87
  return processResult(result.imageUrl, input);
68
88
  },
69
89
  getCreditCost: () => 1,
70
90
  save: buildCreation
71
91
  ? async (result, uid) => {
92
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
93
+ console.log("[CoupleFutureGeneration] 💾 strategy.save() START");
94
+ }
72
95
  const input = lastInputRef.current;
73
96
  if (input) {
74
97
  const creation = buildCreation(result, input);
75
98
  if (creation) {
99
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
100
+ console.log("[CoupleFutureGeneration] 💾 Saving creation to repository...");
101
+ }
76
102
  await repository.create(uid, creation);
103
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
104
+ console.log("[CoupleFutureGeneration] ✅ Creation saved");
105
+ }
77
106
  }
78
107
  }
79
108
  }
@@ -84,16 +113,29 @@ export const useCoupleFutureGeneration = <TResult>(
84
113
 
85
114
  const handleError = useCallback(
86
115
  (error: { message: string }) => {
116
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
117
+ console.log("[CoupleFutureGeneration] ❌ handleError:", error.message);
118
+ }
87
119
  onError?.(error.message);
88
120
  },
89
121
  [onError],
90
122
  );
91
123
 
124
+ const handleSuccess = useCallback(
125
+ (result: unknown) => {
126
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
127
+ console.log("[CoupleFutureGeneration] 🎉 handleSuccess called");
128
+ }
129
+ onSuccess?.(result as TResult);
130
+ },
131
+ [onSuccess],
132
+ );
133
+
92
134
  return useGenerationOrchestrator(strategy, {
93
135
  userId,
94
136
  alertMessages,
95
137
  onCreditsExhausted,
96
- onSuccess: onSuccess as (result: unknown) => void,
138
+ onSuccess: handleSuccess,
97
139
  onError: handleError,
98
140
  });
99
141
  };
@@ -18,6 +18,8 @@ import type {
18
18
  UseGenerationOrchestratorReturn,
19
19
  } from "./types";
20
20
 
21
+ declare const __DEV__: boolean;
22
+
21
23
  const INITIAL_STATE = {
22
24
  status: "idle" as const,
23
25
  isGenerating: false,
@@ -30,53 +32,109 @@ export const useGenerationOrchestrator = <TInput, TResult>(
30
32
  strategy: GenerationStrategy<TInput, TResult>,
31
33
  config: GenerationConfig,
32
34
  ): UseGenerationOrchestratorReturn<TInput, TResult> => {
33
- const { userId, alertMessages, onCreditsExhausted, onSuccess, onError } =
34
- config;
35
+ const { userId, alertMessages, onCreditsExhausted, onSuccess, onError } = config;
36
+
37
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
38
+ console.log("[Orchestrator] Hook initialized:", { userId, hasAlertMessages: !!alertMessages });
39
+ }
35
40
 
36
41
  const [state, setState] = useState<GenerationState<TResult>>(INITIAL_STATE);
37
42
  const isGeneratingRef = useRef(false);
38
43
  const offlineStore = useOfflineStore();
39
44
  const { showError, showSuccess } = useAlert();
40
- const { checkCredits, deductCredit } = useDeductCredit({
41
- userId,
42
- onCreditsExhausted,
43
- });
45
+ const { checkCredits, deductCredit } = useDeductCredit({ userId, onCreditsExhausted });
44
46
 
45
47
  const generate = useCallback(
46
48
  async (input: TInput) => {
47
- if (isGeneratingRef.current) return;
49
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
50
+ console.log("[Orchestrator] 🚀 generate() called");
51
+ console.log("[Orchestrator] Input:", JSON.stringify(input, null, 2).slice(0, 500));
52
+ console.log("[Orchestrator] isGeneratingRef:", isGeneratingRef.current);
53
+ }
54
+
55
+ if (isGeneratingRef.current) {
56
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
57
+ console.log("[Orchestrator] ⚠️ Already generating, skipping");
58
+ }
59
+ return;
60
+ }
48
61
 
49
62
  isGeneratingRef.current = true;
50
63
  setState({ ...INITIAL_STATE, status: "checking", isGenerating: true });
51
64
 
65
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
66
+ console.log("[Orchestrator] State set to: checking, isGenerating: true");
67
+ }
68
+
52
69
  try {
70
+ // Network check
53
71
  if (!offlineStore.isOnline) {
72
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
73
+ console.log("[Orchestrator] ❌ Network check failed - offline");
74
+ }
54
75
  throw createGenerationError("network", "No internet connection");
55
76
  }
56
77
 
78
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
79
+ console.log("[Orchestrator] ✅ Network check passed");
80
+ }
81
+
82
+ // Credit check
57
83
  const creditCost = strategy.getCreditCost();
84
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
85
+ console.log("[Orchestrator] 💳 Credit cost:", creditCost);
86
+ }
87
+
58
88
  const hasCredits = await checkCredits(creditCost);
89
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
90
+ console.log("[Orchestrator] 💳 Has credits:", hasCredits);
91
+ }
92
+
59
93
  if (!hasCredits) {
60
- // Open paywall instead of showing error
94
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
95
+ console.log("[Orchestrator] ❌ No credits, opening paywall");
96
+ }
61
97
  isGeneratingRef.current = false;
62
98
  setState(INITIAL_STATE);
63
99
  onCreditsExhausted?.();
64
100
  return;
65
101
  }
66
102
 
103
+ // Start generation
67
104
  setState((prev) => ({ ...prev, status: "generating", progress: 10 }));
105
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
106
+ console.log("[Orchestrator] 🎨 Starting strategy.execute()");
107
+ }
68
108
 
69
109
  const result = await strategy.execute(input, (progress) => {
110
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
111
+ console.log("[Orchestrator] 📊 Progress update:", progress);
112
+ }
70
113
  setState((prev) => ({ ...prev, progress }));
71
114
  });
72
115
 
116
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
117
+ console.log("[Orchestrator] ✅ strategy.execute() completed");
118
+ console.log("[Orchestrator] Result type:", typeof result);
119
+ }
120
+
73
121
  setState((prev) => ({ ...prev, progress: 70 }));
74
122
 
123
+ // Save result
75
124
  if (strategy.save && userId) {
76
125
  setState((prev) => ({ ...prev, status: "saving" }));
126
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
127
+ console.log("[Orchestrator] 💾 Saving result...");
128
+ }
77
129
  try {
78
130
  await strategy.save(result, userId);
131
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
132
+ console.log("[Orchestrator] ✅ Save completed");
133
+ }
79
134
  } catch (saveErr) {
135
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
136
+ console.log("[Orchestrator] ❌ Save failed:", saveErr);
137
+ }
80
138
  throw createGenerationError(
81
139
  "save",
82
140
  "Failed to save",
@@ -87,8 +145,13 @@ export const useGenerationOrchestrator = <TInput, TResult>(
87
145
 
88
146
  setState((prev) => ({ ...prev, progress: 90 }));
89
147
 
148
+ // Deduct credit
149
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
150
+ console.log("[Orchestrator] 💳 Deducting credit:", creditCost);
151
+ }
90
152
  await deductCredit(creditCost);
91
153
 
154
+ // Success
92
155
  setState({
93
156
  status: "success",
94
157
  isGenerating: false,
@@ -97,6 +160,10 @@ export const useGenerationOrchestrator = <TInput, TResult>(
97
160
  error: null,
98
161
  });
99
162
 
163
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
164
+ console.log("[Orchestrator] 🎉 Generation SUCCESS");
165
+ }
166
+
100
167
  if (alertMessages.success) {
101
168
  void showSuccess("Success", alertMessages.success);
102
169
  }
@@ -105,6 +172,10 @@ export const useGenerationOrchestrator = <TInput, TResult>(
105
172
  } catch (err) {
106
173
  const error = parseError(err);
107
174
 
175
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
176
+ console.log("[Orchestrator] ❌ Generation ERROR:", error);
177
+ }
178
+
108
179
  setState({
109
180
  status: "error",
110
181
  isGenerating: false,
@@ -117,6 +188,9 @@ export const useGenerationOrchestrator = <TInput, TResult>(
117
188
  onError?.(error);
118
189
  } finally {
119
190
  isGeneratingRef.current = false;
191
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
192
+ console.log("[Orchestrator] 🏁 generate() finished, isGeneratingRef reset to false");
193
+ }
120
194
  }
121
195
  },
122
196
  [
@@ -134,6 +208,9 @@ export const useGenerationOrchestrator = <TInput, TResult>(
134
208
  );
135
209
 
136
210
  const reset = useCallback(() => {
211
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
212
+ console.log("[Orchestrator] 🔄 reset() called");
213
+ }
137
214
  setState(INITIAL_STATE);
138
215
  isGeneratingRef.current = false;
139
216
  }, []);