@umituz/react-native-ai-generation-content 1.19.7 → 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 +1 -1
- package/src/features/couple-future/infrastructure/executor.ts +81 -11
- package/src/features/couple-future/presentation/hooks/useCoupleFutureFlow.ts +94 -17
- package/src/features/couple-future/presentation/hooks/useCoupleFutureGeneration.ts +61 -19
- package/src/presentation/hooks/generation/orchestrator.ts +85 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-ai-generation-content",
|
|
3
|
-
"version": "1.19.
|
|
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("[
|
|
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("[
|
|
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("[
|
|
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("[
|
|
84
|
-
console.log("[
|
|
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("[
|
|
93
|
-
console.log("[
|
|
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("[
|
|
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
|
}
|
|
@@ -15,6 +15,8 @@ import type {
|
|
|
15
15
|
CoupleFutureFlowProps,
|
|
16
16
|
} from "./coupleFutureFlow.types";
|
|
17
17
|
|
|
18
|
+
declare const __DEV__: boolean;
|
|
19
|
+
|
|
18
20
|
export type {
|
|
19
21
|
CoupleFutureFlowConfig,
|
|
20
22
|
CoupleFutureFlowState,
|
|
@@ -29,32 +31,75 @@ export const useCoupleFutureFlow = <TStep, TScenarioId, TResult>(
|
|
|
29
31
|
const { processResult, buildCreation, onCreditsExhausted, userId } = props;
|
|
30
32
|
const hasStarted = useRef(false);
|
|
31
33
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
34
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
35
|
+
console.log("[CoupleFutureFlow] Hook initialized:", { userId, step: state.step });
|
|
36
|
+
}
|
|
37
|
+
|
|
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
|
+
});
|
|
47
63
|
|
|
48
64
|
const { step, isProcessing, selectedFeature, selectedScenarioId, selectedScenarioData } = state;
|
|
49
65
|
|
|
50
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
|
+
|
|
51
76
|
if (step !== config.steps.GENERATING) {
|
|
52
77
|
hasStarted.current = false;
|
|
53
78
|
return;
|
|
54
79
|
}
|
|
55
|
-
if (!isProcessing || hasStarted.current)
|
|
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
|
+
}
|
|
56
88
|
hasStarted.current = true;
|
|
57
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
|
+
|
|
58
103
|
const input = buildGenerationInputFromConfig({
|
|
59
104
|
partnerA: state.partnerA as never,
|
|
60
105
|
partnerB: state.partnerB as never,
|
|
@@ -69,11 +114,27 @@ export const useCoupleFutureFlow = <TStep, TScenarioId, TResult>(
|
|
|
69
114
|
visualStyles: generationConfig.visualStyleModifiers,
|
|
70
115
|
customScenarioId: config.customScenarioId as string,
|
|
71
116
|
});
|
|
72
|
-
|
|
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
|
+
}
|
|
73
131
|
}, [step, isProcessing, state, config, generationConfig, generate]);
|
|
74
132
|
|
|
75
133
|
const handleScenarioSelect = useCallback(
|
|
76
134
|
(id: string) => {
|
|
135
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
136
|
+
console.log("[CoupleFutureFlow] handleScenarioSelect:", id);
|
|
137
|
+
}
|
|
77
138
|
actions.selectScenario(id as TScenarioId);
|
|
78
139
|
actions.setStep(config.steps.SCENARIO_PREVIEW);
|
|
79
140
|
},
|
|
@@ -100,6 +161,9 @@ export const useCoupleFutureFlow = <TStep, TScenarioId, TResult>(
|
|
|
100
161
|
|
|
101
162
|
const handlePartnerAContinue = useCallback(
|
|
102
163
|
(image: UploadedImage, name: string) => {
|
|
164
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
165
|
+
console.log("[CoupleFutureFlow] handlePartnerAContinue:", { hasImage: !!image, name });
|
|
166
|
+
}
|
|
103
167
|
actions.setPartnerA(image);
|
|
104
168
|
actions.setPartnerAName(name);
|
|
105
169
|
actions.setStep(config.steps.PARTNER_B);
|
|
@@ -117,7 +181,14 @@ export const useCoupleFutureFlow = <TStep, TScenarioId, TResult>(
|
|
|
117
181
|
|
|
118
182
|
const handlePartnerBContinue = useCallback(
|
|
119
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
|
+
}
|
|
120
188
|
actions.requireFeature(() => {
|
|
189
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
190
|
+
console.log("[CoupleFutureFlow] 🔓 Feature gate passed, starting generation");
|
|
191
|
+
}
|
|
121
192
|
actions.setPartnerB(image);
|
|
122
193
|
actions.setPartnerBName(name);
|
|
123
194
|
actions.startGeneration();
|
|
@@ -133,6 +204,12 @@ export const useCoupleFutureFlow = <TStep, TScenarioId, TResult>(
|
|
|
133
204
|
|
|
134
205
|
const handleMagicPromptContinue = useCallback(
|
|
135
206
|
(prompt: string, style: string) => {
|
|
207
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
208
|
+
console.log("[CoupleFutureFlow] handleMagicPromptContinue:", {
|
|
209
|
+
promptLength: prompt.length,
|
|
210
|
+
style,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
136
213
|
actions.setCustomPrompt(prompt);
|
|
137
214
|
actions.setVisualStyle(style);
|
|
138
215
|
if (selectedScenarioId === config.customScenarioId) {
|
|
@@ -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
|
|
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
|
-
|
|
41
|
-
(
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
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
|
}, []);
|