@umituz/react-native-ai-generation-content 1.89.40 → 1.89.48

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.89.40",
3
+ "version": "1.89.48",
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",
@@ -7,7 +7,6 @@ import React, { useMemo } from "react";
7
7
  import { View, TouchableOpacity, StyleSheet } from "react-native";
8
8
  import { AtomicIcon, AtomicText } from "@umituz/react-native-design-system/atoms";
9
9
  import { useAppDesignTokens, type DesignTokens } from "@umituz/react-native-design-system/theme";
10
- import { useSafeAreaInsets } from "react-native-safe-area-context";
11
10
 
12
11
  interface GalleryScreenHeaderProps {
13
12
  readonly title: string;
@@ -16,7 +15,6 @@ interface GalleryScreenHeaderProps {
16
15
 
17
16
  export const GalleryScreenHeader: React.FC<GalleryScreenHeaderProps> = ({ title, onBack }) => {
18
17
  const tokens = useAppDesignTokens();
19
- const insets = useSafeAreaInsets();
20
18
  const styles = useMemo(() => createStyles(tokens), [tokens]);
21
19
 
22
20
  return (
@@ -1,6 +1,5 @@
1
1
  import React, { useMemo, useCallback, useState } from "react";
2
2
  import { View, FlatList } from "react-native";
3
- import { useSafeAreaInsets } from "react-native-safe-area-context";
4
3
  import { ScreenLayout } from "@umituz/react-native-design-system/layouts";
5
4
  import { FilterSheet, useAppFocusEffect } from "@umituz/react-native-design-system/molecules";
6
5
  import { useAppDesignTokens } from "@umituz/react-native-design-system/theme";
@@ -38,7 +37,6 @@ export function CreationsGalleryScreen({
38
37
  onShareToFeed,
39
38
  }: CreationsGalleryScreenProps) {
40
39
  const tokens = useAppDesignTokens();
41
- const insets = useSafeAreaInsets();
42
40
  const [viewMode, setViewMode] = useState<"list" | "grid">("list");
43
41
 
44
42
  const { data: creations, isLoading, refetch } = useCreations({ userId, repository });
@@ -19,6 +19,17 @@ export async function getAppearanceContext(
19
19
  photoUris: string[],
20
20
  isCoupleMode: boolean,
21
21
  ): Promise<string> {
22
+ const DEV = typeof __DEV__ !== "undefined" && __DEV__;
23
+
24
+ if (DEV) {
25
+ console.log("[AppearanceAnalysis] ===== ANALYSIS START =====");
26
+ console.log("[AppearanceAnalysis] Photo URIs:", photoUris.length);
27
+ console.log("[AppearanceAnalysis] Is couple mode:", isCoupleMode);
28
+ console.log("[AppearanceAnalysis] URIs:", photoUris.map((uri, i) => ` ${i + 1}. ${uri.substring(0, 60)}...`));
29
+ console.log("[AppearanceAnalysis] Vision analysis: DISABLED (returning empty context)");
30
+ console.log("[AppearanceAnalysis] ===== ANALYSIS END =====");
31
+ }
32
+
22
33
  // Vision analysis temporarily disabled due to API limitations
23
34
  // Future: Implement vision analysis to extract appearance features
24
35
  return "";
@@ -39,15 +50,50 @@ export async function enhancePromptWithAnalysis(
39
50
  photoUris: string[],
40
51
  isCoupleMode: boolean,
41
52
  ): Promise<string> {
53
+ const DEV = typeof __DEV__ !== "undefined" && __DEV__;
54
+
55
+ if (DEV) {
56
+ console.log("[AppearanceAnalysis] ===== ENHANCE START =====");
57
+ console.log("[AppearanceAnalysis] Original prompt length:", originalPrompt.length);
58
+ console.log("[AppearanceAnalysis] Photo URIs:", photoUris.length);
59
+ console.log("[AppearanceAnalysis] Is couple mode:", isCoupleMode);
60
+ console.log("[AppearanceAnalysis] Original preview:", originalPrompt.substring(0, 200) + "...");
61
+ }
62
+
42
63
  // Always apply basic couple refinement first
43
64
  let finalPrompt = refinePromptForCouple(originalPrompt, isCoupleMode);
44
65
 
45
- if (photoUris.length === 0) return finalPrompt;
66
+ if (DEV) {
67
+ console.log("[AppearanceAnalysis] After refinePromptForCouple length:", finalPrompt.length);
68
+ console.log("[AppearanceAnalysis] After refine preview:", finalPrompt.substring(0, 250) + "...");
69
+ }
70
+
71
+ if (photoUris.length === 0) {
72
+ if (DEV) {
73
+ console.log("[AppearanceAnalysis] No photos - returning refined prompt");
74
+ console.log("[AppearanceAnalysis] ===== ENHANCE END =====");
75
+ }
76
+ return finalPrompt;
77
+ }
46
78
 
47
79
  const appearanceContext = await getAppearanceContext(photoUris, isCoupleMode);
48
80
 
49
81
  if (appearanceContext) {
50
82
  finalPrompt = `${appearanceContext}\n\n${finalPrompt}`;
83
+ if (DEV) {
84
+ console.log("[AppearanceAnalysis] ✅ Appearance context prepended");
85
+ console.log("[AppearanceAnalysis] Context length:", appearanceContext.length);
86
+ }
87
+ } else {
88
+ if (DEV) {
89
+ console.log("[AppearanceAnalysis] ℹ️ No appearance context (vision disabled)");
90
+ }
91
+ }
92
+
93
+ if (DEV) {
94
+ console.log("[AppearanceAnalysis] Final prompt length:", finalPrompt.length);
95
+ console.log("[AppearanceAnalysis] Final preview:", finalPrompt.substring(0, 300) + "...");
96
+ console.log("[AppearanceAnalysis] ===== ENHANCE END =====");
51
97
  }
52
98
 
53
99
  return finalPrompt;
@@ -12,7 +12,6 @@
12
12
  * - Mood filter generation
13
13
  */
14
14
 
15
- import type { GenerationTarget } from "../../../exports/presentation";
16
15
  import {
17
16
  resolveCoupleInput,
18
17
  prependContext,
@@ -74,6 +73,8 @@ export interface ScenarioGenerationInputParams {
74
73
  export async function buildCoupleGenerationInput(
75
74
  params: CoupleGenerationInputParams,
76
75
  ): Promise<CoupleGenerationInput> {
76
+ const DEV = typeof __DEV__ !== "undefined" && __DEV__;
77
+
77
78
  const {
78
79
  partner1PhotoUri,
79
80
  partner2PhotoUri,
@@ -84,33 +85,122 @@ export async function buildCoupleGenerationInput(
84
85
  strength,
85
86
  } = params;
86
87
 
88
+ if (DEV) {
89
+ console.log("[CoupleBuilder] ========================================");
90
+ console.log("[CoupleBuilder] ===== BUILD COUPLE GENERATION START =====");
91
+ console.log("[CoupleBuilder] ========================================");
92
+ console.log("[CoupleBuilder] ===== INPUT PARAMS =====");
93
+ console.log("[CoupleBuilder] Is couple mode:", isCoupleMode);
94
+ console.log("[CoupleBuilder] Base prompt length:", basePrompt.length);
95
+ console.log("[CoupleBuilder] Base prompt preview:", basePrompt.substring(0, 200) + "...");
96
+ console.log("[CoupleBuilder] Aspect ratio:", aspectRatio);
97
+ console.log("[CoupleBuilder] Has partner 2:", !!partner2PhotoUri);
98
+ console.log("[CoupleBuilder] Has custom instructions:", !!customInstructions);
99
+ console.log("[CoupleBuilder] Has strength:", strength !== undefined);
100
+ if (strength !== undefined) {
101
+ console.log("[CoupleBuilder] Strength value:", strength);
102
+ }
103
+ console.log("[CoupleBuilder] Partner 1 URI:", partner1PhotoUri.substring(0, 80) + "...");
104
+ if (partner2PhotoUri) {
105
+ console.log("[CoupleBuilder] Partner 2 URI:", partner2PhotoUri.substring(0, 80) + "...");
106
+ }
107
+ }
108
+
87
109
  // 1. GET PHOTO URIs - Couple mode kontrolü
88
110
  const photoUris =
89
111
  isCoupleMode && partner2PhotoUri
90
112
  ? [partner1PhotoUri, partner2PhotoUri]
91
113
  : [partner1PhotoUri];
92
114
 
115
+ if (DEV) {
116
+ console.log("[CoupleBuilder] ===== STEP 1: PHOTO URIs =====");
117
+ console.log("[CoupleBuilder] Photo URIs count:", photoUris.length);
118
+ console.log("[CoupleBuilder] Photo 1:", photoUris[0].substring(0, 60) + "...");
119
+ if (photoUris.length > 1) {
120
+ console.log("[CoupleBuilder] Photo 2:", photoUris[1].substring(0, 60) + "...");
121
+ }
122
+ }
123
+
93
124
  // 2. ANALYZE APPEARANCE - Wardrobe'daki gibi
94
125
  // Fotoğrafları analiz et ve context çıkar
126
+ if (DEV) {
127
+ console.log("[CoupleBuilder] ===== STEP 2: APPEARANCE ANALYSIS =====");
128
+ console.log("[CoupleBuilder] Calling getAppearanceContext with:", {
129
+ photoCount: photoUris.length,
130
+ isCoupleMode
131
+ });
132
+ }
133
+
95
134
  const appearanceContext = await getAppearanceContext(
96
135
  photoUris,
97
136
  isCoupleMode,
98
137
  );
99
138
 
139
+ if (DEV) {
140
+ console.log("[CoupleBuilder] Appearance context length:", appearanceContext.length);
141
+ if (appearanceContext.length > 0) {
142
+ console.log("[CoupleBuilder] Appearance context preview:", appearanceContext.substring(0, 150) + "...");
143
+ } else {
144
+ console.log("[CoupleBuilder] ℹ️ No appearance context returned (vision disabled)");
145
+ }
146
+ }
147
+
100
148
  // 3. REFINE FOR COUPLE + PREPEND CONTEXT - Wardrobe mantığı
101
149
  // Coupler modu için prompt'u iyileştir ve context'i ekle
150
+ if (DEV) {
151
+ console.log("[CoupleBuilder] ===== STEP 3: REFINE & PREPEND CONTEXT =====");
152
+ console.log("[CoupleBuilder] Calling refinePromptForCouple with:", {
153
+ basePromptLength: basePrompt.length,
154
+ isCoupleMode
155
+ });
156
+ }
157
+
102
158
  const refinedPrompt = prependContext(
103
159
  refinePromptForCouple(basePrompt, isCoupleMode),
104
160
  appearanceContext,
105
161
  );
106
162
 
163
+ if (DEV) {
164
+ console.log("[CoupleBuilder] After refinePromptForCouple + prependContext:");
165
+ console.log("[CoupleBuilder] Refined prompt length:", refinedPrompt.length);
166
+ console.log("[CoupleBuilder] Refined prompt preview:", refinedPrompt.substring(0, 300) + "...");
167
+ }
168
+
107
169
  // 4. CREATE FINAL PROMPT - Photorealistic
170
+ if (DEV) {
171
+ console.log("[CoupleBuilder] ===== STEP 4: CREATE PHOTOREALISTIC PROMPT =====");
172
+ console.log("[CoupleBuilder] Calling createPhotorealisticPrompt with:", {
173
+ isCouple: isCoupleMode,
174
+ hasCustomInstructions: !!customInstructions
175
+ });
176
+ }
177
+
108
178
  const prompt = createPhotorealisticPrompt(refinedPrompt, {
109
179
  isCouple: isCoupleMode,
110
180
  customInstructions,
111
181
  });
112
182
 
183
+ if (DEV) {
184
+ console.log("[CoupleBuilder] Final prompt length:", prompt.length);
185
+ console.log("[CoupleBuilder] Final prompt preview:", prompt.substring(0, 500) + "...");
186
+ console.log("[CoupleBuilder] Has custom instructions:", !!customInstructions);
187
+ if (customInstructions) {
188
+ console.log("[CoupleBuilder] Custom instructions:", customInstructions);
189
+ }
190
+ }
191
+
113
192
  // 5. RESOLVE COUPLE INPUT - Doğru target ve image'lar
193
+ if (DEV) {
194
+ console.log("[CoupleBuilder] ===== STEP 5: RESOLVE COUPLE INPUT =====");
195
+ console.log("[CoupleBuilder] Calling resolveCoupleInput with:", {
196
+ partner1PhotoUri: partner1PhotoUri.substring(0, 50) + "...",
197
+ partner2PhotoUri: partner2PhotoUri ? partner2PhotoUri.substring(0, 50) + "..." : null,
198
+ isCoupleMode,
199
+ singleTarget: "p-image-edit/pruna",
200
+ coupleTarget: "p-image-edit/pruna"
201
+ });
202
+ }
203
+
114
204
  const { target, imageUrls } = resolveCoupleInput(
115
205
  partner1PhotoUri,
116
206
  partner2PhotoUri,
@@ -119,7 +209,22 @@ export async function buildCoupleGenerationInput(
119
209
  { model: "p-image-edit", providerId: "pruna" }, // Couple target
120
210
  );
121
211
 
212
+ if (DEV) {
213
+ console.log("[CoupleBuilder] Target resolution result:");
214
+ console.log("[CoupleBuilder] Target model:", target.model);
215
+ console.log("[CoupleBuilder] Target provider:", target.providerId);
216
+ console.log("[CoupleBuilder] Image URLs count:", imageUrls.length);
217
+ console.log("[CoupleBuilder] Image 1:", imageUrls[0]?.substring(0, 80) + "...");
218
+ if (imageUrls.length > 1) {
219
+ console.log("[CoupleBuilder] Image 2:", imageUrls[1]?.substring(0, 80) + "...");
220
+ }
221
+ }
222
+
122
223
  // 6. BUILD PARAMS - Wardrobe formatında
224
+ if (DEV) {
225
+ console.log("[CoupleBuilder] ===== STEP 6: BUILD PARAMS =====");
226
+ }
227
+
123
228
  const genParams: Record<string, unknown> = {
124
229
  prompt,
125
230
  image_urls: imageUrls,
@@ -131,6 +236,19 @@ export async function buildCoupleGenerationInput(
131
236
  genParams.strength = strength;
132
237
  }
133
238
 
239
+ if (DEV) {
240
+ console.log("[CoupleBuilder] Final params structure:");
241
+ console.log("[CoupleBuilder] Keys:", Object.keys(genParams).join(", "));
242
+ console.log("[CoupleBuilder] 'image_urls' count:", Array.isArray(genParams.image_urls) ? genParams.image_urls.length : "N/A");
243
+ console.log("[CoupleBuilder] 'aspect_ratio':", genParams.aspect_ratio);
244
+ console.log("[CoupleBuilder] 'strength':", genParams.strength ?? "not set");
245
+ console.log("[CoupleBuilder] ========================================");
246
+ console.log("[CoupleBuilder] ===== BUILD COUPLE GENERATION END =====");
247
+ console.log("[CoupleBuilder] ========================================");
248
+ console.log("[CoupleBuilder] Returning: { target, prompt, params }");
249
+ console.log("");
250
+ }
251
+
134
252
  return {
135
253
  target,
136
254
  prompt,
@@ -147,34 +265,80 @@ export async function buildCoupleGenerationInput(
147
265
  export async function buildScenarioGenerationInput(
148
266
  params: ScenarioGenerationInputParams,
149
267
  ): Promise<CoupleGenerationInput> {
268
+ const DEV = typeof __DEV__ !== "undefined" && __DEV__;
269
+
150
270
  const {
151
271
  partner1PhotoUri,
152
272
  partner2PhotoUri,
153
273
  isCoupleMode,
154
274
  scenarioPrompt,
155
- customInstructions,
156
275
  } = params;
157
276
 
277
+ if (DEV) {
278
+ console.log("[ScenarioBuilder] ========================================");
279
+ console.log("[ScenarioBuilder] ===== BUILD SCENARIO GENERATION START =====");
280
+ console.log("[ScenarioBuilder] ========================================");
281
+ console.log("[ScenarioBuilder] ===== INPUT PARAMS =====");
282
+ console.log("[ScenarioBuilder] Is couple mode:", isCoupleMode);
283
+ console.log("[ScenarioBuilder] Scenario prompt length:", scenarioPrompt.length);
284
+ console.log("[ScenarioBuilder] Scenario prompt preview:", scenarioPrompt.substring(0, 200) + "...");
285
+ console.log("[ScenarioBuilder] Partner 1 URI:", partner1PhotoUri.substring(0, 80) + "...");
286
+ if (partner2PhotoUri) {
287
+ console.log("[ScenarioBuilder] Partner 2 URI:", partner2PhotoUri.substring(0, 80) + "...");
288
+ }
289
+ }
290
+
158
291
  // 1. GET PHOTO URIs
159
292
  const photoUris =
160
293
  isCoupleMode && partner2PhotoUri
161
294
  ? [partner1PhotoUri, partner2PhotoUri]
162
295
  : [partner1PhotoUri];
163
296
 
297
+ if (DEV) {
298
+ console.log("[ScenarioBuilder] ===== STEP 1: PHOTO URIs =====");
299
+ console.log("[ScenarioBuilder] Photo URIs count:", photoUris.length);
300
+ }
301
+
164
302
  // 2. ANALYZE APPEARANCE
303
+ if (DEV) {
304
+ console.log("[ScenarioBuilder] ===== STEP 2: APPEARANCE ANALYSIS =====");
305
+ }
306
+
165
307
  const appearanceContext = await getAppearanceContext(
166
308
  photoUris,
167
309
  isCoupleMode,
168
310
  );
169
311
 
312
+ if (DEV) {
313
+ console.log("[ScenarioBuilder] Appearance context length:", appearanceContext.length);
314
+ if (appearanceContext.length > 0) {
315
+ console.log("[ScenarioBuilder] Appearance context preview:", appearanceContext.substring(0, 150) + "...");
316
+ } else {
317
+ console.log("[ScenarioBuilder] ℹ️ No appearance context (vision disabled)");
318
+ }
319
+ }
320
+
170
321
  // 3. REFINE FOR COUPLE + PREPEND CONTEXT
171
322
  // Senaryo prompt'unu (zaten photorealistic) dynamic context ile birleştir
172
- const finalPrompt = prependContext(
173
- refinePromptForCouple(scenarioPrompt, isCoupleMode),
174
- appearanceContext,
175
- );
323
+ if (DEV) {
324
+ console.log("[ScenarioBuilder] ===== STEP 3: REFINE & PREPEND CONTEXT =====");
325
+ console.log("[ScenarioBuilder] Calling refinePromptForCouple...");
326
+ }
327
+
328
+ const refinedPrompt = refinePromptForCouple(scenarioPrompt, isCoupleMode);
329
+ const finalPrompt = prependContext(refinedPrompt, appearanceContext);
330
+
331
+ if (DEV) {
332
+ console.log("[ScenarioBuilder] After refinePromptForCouple length:", refinedPrompt.length);
333
+ console.log("[ScenarioBuilder] After prependContext length:", finalPrompt.length);
334
+ console.log("[ScenarioBuilder] Final prompt preview:", finalPrompt.substring(0, 300) + "...");
335
+ }
176
336
 
177
337
  // 4. RESOLVE COUPLE INPUT
338
+ if (DEV) {
339
+ console.log("[ScenarioBuilder] ===== STEP 4: RESOLVE COUPLE INPUT =====");
340
+ }
341
+
178
342
  const { target, imageUrls } = resolveCoupleInput(
179
343
  partner1PhotoUri,
180
344
  partner2PhotoUri,
@@ -183,7 +347,21 @@ export async function buildScenarioGenerationInput(
183
347
  { model: "p-image-edit", providerId: "pruna" }, // Couple target
184
348
  );
185
349
 
350
+ if (DEV) {
351
+ console.log("[ScenarioBuilder] Target:", target.model, "/", target.providerId);
352
+ console.log("[ScenarioBuilder] Image URLs count:", imageUrls.length);
353
+ }
354
+
186
355
  // 5. BUILD PARAMS - Scenario formatında
356
+ if (DEV) {
357
+ console.log("[ScenarioBuilder] ===== STEP 5: BUILD PARAMS =====");
358
+ console.log("[ScenarioBuilder] Aspect ratio: 3:4");
359
+ console.log("[ScenarioBuilder] ========================================");
360
+ console.log("[ScenarioBuilder] ===== BUILD SCENARIO GENERATION END =====");
361
+ console.log("[ScenarioBuilder] ========================================");
362
+ console.log("");
363
+ }
364
+
187
365
  return {
188
366
  target,
189
367
  prompt: finalPrompt,
@@ -58,6 +58,28 @@ export async function executeImageGeneration(
58
58
  const mode = imageUrls.length > 0 ? "Photo-based" : "Text-to-image";
59
59
  const totalImageSize = imageUrls.reduce((sum, url) => sum + url.length, 0);
60
60
 
61
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
62
+ console.log("[ImageExecutor] ===== EXECUTION START =====");
63
+ console.log("[ImageExecutor] Mode:", mode);
64
+ console.log("[ImageExecutor] Model:", model);
65
+ console.log("[ImageExecutor] Provider ID:", providerId);
66
+ console.log("[ImageExecutor] ===== INPUT DATA =====");
67
+ console.log("[ImageExecutor] Photo count:", imageUrls.length);
68
+ console.log("[ImageExecutor] Total image size:", Math.round(totalImageSize / 1024), "KB");
69
+ console.log("[ImageExecutor] Image sizes:", imageUrls.map((url, i) => ` Photo ${i + 1}: ${(url.length / 1024).toFixed(2)}KB`));
70
+ console.log("[ImageExecutor] Aspect ratio:", input.aspectRatio || MODEL_INPUT_DEFAULTS.aspectRatio);
71
+ console.log("[ImageExecutor] ===== PROMPT =====");
72
+ console.log("[ImageExecutor] Prompt length:", finalPrompt.length);
73
+ console.log("[ImageExecutor] Prompt preview:");
74
+ console.log(finalPrompt.substring(0, 400) + "...");
75
+ console.log("[ImageExecutor] ===== MODEL INPUT =====");
76
+ console.log("[ImageExecutor] Model:", model);
77
+ console.log("[ImageExecutor] Input keys:", Object.keys(MODEL_INPUT_DEFAULTS));
78
+ console.log("[ImageExecutor] Output format:", MODEL_INPUT_DEFAULTS.outputFormat);
79
+ console.log("[ImageExecutor] Num images:", MODEL_INPUT_DEFAULTS.numImages);
80
+ console.log("[ImageExecutor] Safety checker:", MODEL_INPUT_DEFAULTS.enableSafetyChecker);
81
+ }
82
+
61
83
  addGenerationLog(sid, TAG, `${mode} generation starting`, 'info', {
62
84
  model,
63
85
  photoCount: imageUrls.length,
@@ -70,16 +92,24 @@ export async function executeImageGeneration(
70
92
  const modelInput: Record<string, unknown> = {
71
93
  prompt: finalPrompt,
72
94
  aspect_ratio: input.aspectRatio || MODEL_INPUT_DEFAULTS.aspectRatio,
73
- output_format: MODEL_INPUT_DEFAULTS.outputFormat,
74
- num_images: MODEL_INPUT_DEFAULTS.numImages,
75
- enable_safety_checker: MODEL_INPUT_DEFAULTS.enableSafetyChecker,
76
95
  };
77
96
 
78
- // p-image-edit (and typical multi-ref models) usually expect 'images' key
79
- // supporting both 'images' and 'image_urls' for maximum compatibility
80
97
  if (imageUrls.length > 0) {
81
- modelInput.images = imageUrls;
82
98
  modelInput.image_urls = imageUrls;
99
+ modelInput.images = imageUrls;
100
+ }
101
+
102
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
103
+ console.log("[ImageExecutor] ===== MODEL INPUT CONSTRUCTED =====");
104
+ console.log("[ImageExecutor] Input keys:", Object.keys(modelInput));
105
+ console.log("[ImageExecutor] Has 'images':", "images" in modelInput, "(count:", Array.isArray(modelInput.images) ? modelInput.images.length : "N/A", ")");
106
+ console.log("[ImageExecutor] Has 'image_urls':", "image_urls" in modelInput, "(count:", Array.isArray(modelInput.image_urls) ? modelInput.image_urls.length : "N/A", ")");
107
+ console.log("[ImageExecutor] Images array length:", imageUrls.length);
108
+ if (imageUrls.length > 0) {
109
+ console.log("[ImageExecutor] First image preview:", imageUrls[0].substring(0, 80) + "...");
110
+ console.log("[ImageExecutor] Last image preview:", imageUrls[imageUrls.length - 1].substring(0, 80) + "...");
111
+ }
112
+ console.log("[ImageExecutor] ===== CALLING PROVIDER =====");
83
113
  }
84
114
 
85
115
  addGenerationLog(sid, TAG, 'Calling provider.subscribe()...');
@@ -11,6 +11,7 @@ import { extractPhotosAsBase64, extractPhotoUris } from "./shared/photo-extracti
11
11
  import { executeImageGeneration } from "./image-generation.executor";
12
12
  import type { WizardImageInput, CreateImageStrategyOptions } from "./image-generation.types";
13
13
  import { enhancePromptWithAnalysis } from "../../../infrastructure/appearance-analysis";
14
+ import { createPhotorealisticPrompt } from "../../../../prompts/domain/base/creators";
14
15
 
15
16
 
16
17
  // ============================================================================
@@ -21,17 +22,65 @@ export async function buildImageInput(
21
22
  wizardData: Record<string, unknown>,
22
23
  scenario: WizardScenarioData,
23
24
  ): Promise<WizardImageInput | null> {
25
+ const DEV = typeof __DEV__ !== "undefined" && __DEV__;
26
+
27
+ if (DEV) {
28
+ console.log("[ImageStrategy] ===== BUILD IMAGE INPUT START =====");
29
+ console.log("[ImageStrategy] Scenario ID:", scenario.id);
30
+ console.log("[ImageStrategy] Scenario model:", scenario.model);
31
+ console.log("[ImageStrategy] Scenario provider:", scenario.providerId);
32
+ console.log("[ImageStrategy] ===== WIZARD DATA KEYS =====");
33
+ const wizardKeys = Object.keys(wizardData);
34
+ console.log("[ImageStrategy] Total keys:", wizardKeys.length);
35
+ console.log("[ImageStrategy] Keys:", wizardKeys.slice(0, 20).join(", ") + (wizardKeys.length > 20 ? "..." : ""));
36
+
37
+ // Log photo-related keys
38
+ const photoKeys = wizardKeys.filter(k => k.includes("photo"));
39
+ if (photoKeys.length > 0) {
40
+ console.log("[ImageStrategy] Photo-related keys:", photoKeys.join(", "));
41
+ }
42
+
43
+ // Log selection/style keys
44
+ const selectionKeys = wizardKeys.filter(k => k.includes("selection") || k.includes("style"));
45
+ if (selectionKeys.length > 0) {
46
+ console.log("[ImageStrategy] Selection/style keys:", selectionKeys.join(", "));
47
+ }
48
+ }
49
+
24
50
  // Extract photo URIs first (for couple refinement)
25
51
  const photoUris = extractPhotoUris(wizardData);
26
- const photos = await extractPhotosAsBase64(wizardData);
52
+ const photos = await extractPhotosAsBase64(wizardData, DEV);
53
+
54
+ if (DEV) {
55
+ console.log("[ImageStrategy] ===== EXTRACTION COMPLETE =====");
56
+ console.log("[ImageStrategy] Photo URIs count:", photoUris.length);
57
+ console.log("[ImageStrategy] Base64 photos count:", photos.length);
58
+ }
27
59
 
28
60
  // Extract prompt with fallback to default
29
61
  let prompt = extractPrompt(wizardData, scenario.aiPrompt);
30
62
 
63
+ if (DEV) {
64
+ console.log("[ImageStrategy] ===== PROMPT EXTRACTION =====");
65
+ console.log("[ImageStrategy] Scenario aiPrompt type:", typeof scenario.aiPrompt);
66
+ console.log("[ImageStrategy] Scenario aiPrompt length:", typeof scenario.aiPrompt === "string" ? scenario.aiPrompt.length : "N/A");
67
+ if (typeof scenario.aiPrompt === "string") {
68
+ console.log("[ImageStrategy] Scenario aiPrompt preview:", scenario.aiPrompt.substring(0, 200) + "...");
69
+ }
70
+ console.log("[ImageStrategy] Extracted prompt type:", typeof prompt);
71
+ console.log("[ImageStrategy] Extracted prompt length:", prompt?.length ?? 0);
72
+ if (prompt) {
73
+ console.log("[ImageStrategy] Extracted prompt preview:", prompt.substring(0, 200) + "...");
74
+ }
75
+ }
76
+
31
77
  if (!prompt) {
32
78
  const defaultPrompt = IMAGE_PROCESSING_PROMPTS[scenario.id];
33
79
  if (defaultPrompt) {
34
80
  prompt = defaultPrompt;
81
+ if (DEV) {
82
+ console.log("[ImageStrategy] Using default prompt for scenario:", scenario.id);
83
+ }
35
84
  } else {
36
85
  throw new Error("Prompt is required for image generation");
37
86
  }
@@ -40,20 +89,49 @@ export async function buildImageInput(
40
89
  // Apply style enhancements for photo-based generation
41
90
  let finalPrompt = prompt;
42
91
  if (photos.length > 0) {
43
- finalPrompt = applyStyleEnhancements(prompt, wizardData);
44
-
45
- // ✅ Apply couple refinement (same logic as Wardrobe)
46
- // This ensures consistency across all couple generation scenarios
47
92
  const isCoupleMode = photos.length >= 2;
48
- finalPrompt = await enhancePromptWithAnalysis(finalPrompt, photoUris, isCoupleMode);
93
+ const styleEnhanced = applyStyleEnhancements(prompt, wizardData);
94
+
95
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
96
+ console.log("[ImageStrategy] ===== STRATEGY START =====");
97
+ console.log("[ImageStrategy] Scenario:", scenario.id);
98
+ console.log("[ImageStrategy] Model:", scenario.model);
99
+ console.log("[ImageStrategy] Provider:", scenario.providerId);
100
+ console.log("[ImageStrategy] ===== PROMPT FLOW =====");
101
+ console.log("[ImageStrategy] [1/5] Original scenario prompt:");
102
+ console.log("[ImageStrategy] Length:", prompt.length);
103
+ console.log("[ImageStrategy] Preview:", prompt.substring(0, 150) + "...");
104
+ console.log("[ImageStrategy] [2/5] Style enhancements applied:", styleEnhanced !== prompt);
105
+ if (styleEnhanced !== prompt) {
106
+ console.log("[ImageStrategy] Enhanced preview:", styleEnhanced.substring(0, 150) + "...");
107
+ }
108
+ console.log("[ImageStrategy] [3/5] Couple mode:", isCoupleMode);
109
+ console.log("[ImageStrategy] Photo count:", photos.length);
110
+ console.log("[ImageStrategy] [4/5] Calling enhancePromptWithAnalysis...");
111
+ }
112
+
113
+ const refinedPrompt = await enhancePromptWithAnalysis(styleEnhanced, photoUris, isCoupleMode);
114
+
115
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
116
+ console.log("[ImageStrategy] After enhancePromptWithAnalysis:");
117
+ console.log("[ImageStrategy] Length:", refinedPrompt.length);
118
+ console.log("[ImageStrategy] Preview:", refinedPrompt.substring(0, 200) + "...");
119
+ console.log("[ImageStrategy] [5/5] Calling createPhotorealisticPrompt (Wardrobe style)...");
120
+ }
121
+
122
+ finalPrompt = createPhotorealisticPrompt(refinedPrompt, {
123
+ isCouple: isCoupleMode,
124
+ customInstructions: undefined,
125
+ });
49
126
 
50
127
  if (typeof __DEV__ !== "undefined" && __DEV__) {
51
- console.log("[ImageStrategy] Prompt enhanced with couple refinement", {
52
- photoCount: photos.length,
53
- isCoupleMode,
54
- originalPromptLength: prompt.length,
55
- finalPromptLength: finalPrompt.length,
56
- });
128
+ console.log("[ImageStrategy] ===== STRATEGY END =====");
129
+ console.log("[ImageStrategy] Final prompt length:", finalPrompt.length);
130
+ console.log("[ImageStrategy] Final prompt preview:");
131
+ console.log(finalPrompt.substring(0, 600) + "...");
132
+ console.log("[ImageStrategy] ===== OUTPUT =====");
133
+ console.log("[ImageStrategy] Photo count:", photos.length);
134
+ console.log("[ImageStrategy] Photo sizes:", photos.map((p, i) => `Photo ${i + 1}: ${(p.length / 1024).toFixed(2)}KB`));
57
135
  }
58
136
  }
59
137
 
@@ -61,8 +139,29 @@ export async function buildImageInput(
61
139
  const styleValue = extractSelection(wizardData.style);
62
140
  const style = typeof styleValue === "string" ? styleValue : undefined;
63
141
 
64
- // Extract aspect ratio from wizard data
65
- const aspectRatio = typeof wizardData.aspect_ratio === "string" ? wizardData.aspect_ratio : undefined;
142
+ let aspectRatio = typeof wizardData.aspect_ratio === "string" ? wizardData.aspect_ratio : undefined;
143
+
144
+ if (!aspectRatio && photos.length > 0) {
145
+ aspectRatio = "3:4"; // Wardrobe default
146
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
147
+ console.log("[ImageStrategy] No aspect_ratio in wizardData, using Wardrobe default: 3:4");
148
+ }
149
+ }
150
+
151
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
152
+ console.log("[ImageStrategy] ===== STYLE & ASPECT RATIO =====");
153
+ console.log("[ImageStrategy] wizardData.style:", wizardData.style);
154
+ console.log("[ImageStrategy] Extracted styleValue:", styleValue);
155
+ console.log("[ImageStrategy] Final style:", style || "none");
156
+ console.log("[ImageStrategy] wizardData.aspect_ratio:", wizardData.aspect_ratio);
157
+ console.log("[ImageStrategy] Final aspectRatio:", aspectRatio || "default");
158
+ console.log("[ImageStrategy] ===== FINAL OUTPUT =====");
159
+ console.log("[ImageStrategy] Photos count:", photos.length);
160
+ console.log("[ImageStrategy] Prompt length:", finalPrompt.length);
161
+ console.log("[ImageStrategy] Aspect ratio:", aspectRatio || "default");
162
+ console.log("[ImageStrategy] Returning WizardImageInput");
163
+ console.log("[ImageStrategy] ===== STRATEGY COMPLETE =====");
164
+ }
66
165
 
67
166
  return { photos, prompt: finalPrompt, style, aspectRatio };
68
167
  }
@@ -227,6 +227,13 @@ export const WizardFlowContent: React.FC<WizardFlowContentProps> = (props) => {
227
227
  [customData, featureConfig.steps, calculateCredits, creditCost, validatedScenario.outputType, validatedScenario.inputType],
228
228
  );
229
229
 
230
+ // Reset local state when scenario changes
231
+ useEffect(() => {
232
+ setCurrentCreation(null);
233
+ setShowRatingPicker(false);
234
+ setHasRated(false);
235
+ }, [scenario?.id]);
236
+
230
237
  useEffect(() => {
231
238
  if (currentStep && onStepChange && prevStepIdRef.current !== currentStep.id) {
232
239
  prevStepIdRef.current = currentStep.id;
@@ -3,7 +3,7 @@
3
3
  * Generic selection step for wizard flows (duration, style, etc.)
4
4
  */
5
5
 
6
- import React, { useState, useCallback, useMemo } from "react";
6
+ import React, { useState, useCallback, useMemo, useEffect } from "react";
7
7
  import { View, TouchableOpacity, StyleSheet } from "react-native";
8
8
  import { AtomicText, AtomicIcon } from "@umituz/react-native-design-system/atoms";
9
9
  import { NavigationHeader } from "@umituz/react-native-design-system/molecules";
@@ -42,6 +42,19 @@ export const SelectionScreen: React.FC<SelectionScreenProps> = ({
42
42
  });
43
43
 
44
44
  const isMultiSelect = config?.multiSelect ?? false;
45
+
46
+ // Reset selection when initialValue, options, or config changes (e.g., when scenario changes)
47
+ useEffect(() => {
48
+ const optionIds = options.map((opt) => opt.id);
49
+
50
+ if (isMultiSelect) {
51
+ const initialArr = initialValue && Array.isArray(initialValue) ? initialValue : [];
52
+ setSelected(initialArr.filter((id) => optionIds.includes(id)));
53
+ } else {
54
+ const initialStr = typeof initialValue === "string" ? initialValue : "";
55
+ setSelected(optionIds.includes(initialStr) ? initialStr : "");
56
+ }
57
+ }, [initialValue, options, isMultiSelect]);
45
58
  const isRequired = config?.required ?? true;
46
59
  const canContinue = isRequired
47
60
  ? isMultiSelect ? (selected as string[]).length > 0 : selected !== ""
@@ -4,7 +4,7 @@
4
4
  * Uses design system: NavigationHeader + ScreenLayout
5
5
  */
6
6
 
7
- import React, { useState, useCallback, useMemo } from "react";
7
+ import React, { useState, useCallback, useMemo, useEffect } from "react";
8
8
  import { View, TextInput, StyleSheet } from "react-native";
9
9
  import { AtomicText, AtomicButton } from "@umituz/react-native-design-system/atoms";
10
10
  import { ScreenLayout } from "@umituz/react-native-design-system/layouts";
@@ -36,6 +36,11 @@ export const TextInputScreen: React.FC<TextInputScreenProps> = ({
36
36
  const alert = useAlert();
37
37
  const [text, setText] = useState(initialValue);
38
38
 
39
+ // Reset text when initialValue changes (e.g., when scenario changes)
40
+ useEffect(() => {
41
+ setText(initialValue);
42
+ }, [initialValue]);
43
+
39
44
  // Validate config - REQUIRED, NO DEFAULTS
40
45
  if (!config) {
41
46
  throw new Error("[TextInputScreen] Config is required but was not provided.");
@@ -20,16 +20,54 @@ export function resolveCoupleInput(
20
20
  singleTarget: GenerationTargetLike,
21
21
  coupleTarget: GenerationTargetLike,
22
22
  ): CoupleInputResult {
23
+ const DEV = typeof __DEV__ !== "undefined" && __DEV__;
24
+
25
+ if (DEV) {
26
+ console.log("[CoupleUtil] ===== RESOLVE COUPLE INPUT =====");
27
+ console.log("[CoupleUtil] Is couple mode:", isCoupleMode);
28
+ console.log("[CoupleUtil] Has partner 2:", !!partner2PhotoUri);
29
+ console.log("[CoupleUtil] Partner 1 URI:", partner1PhotoUri.substring(0, 60) + "...");
30
+ if (partner2PhotoUri) {
31
+ console.log("[CoupleUtil] Partner 2 URI:", partner2PhotoUri.substring(0, 60) + "...");
32
+ }
33
+ console.log("[CoupleUtil] Single target:", `${singleTarget.model}/${singleTarget.providerId}`);
34
+ console.log("[CoupleUtil] Couple target:", `${coupleTarget.model}/${coupleTarget.providerId}`);
35
+ }
36
+
23
37
  if (isCoupleMode && partner2PhotoUri) {
24
- return {
38
+ const result = {
25
39
  target: coupleTarget,
26
40
  imageUrls: [partner1PhotoUri, partner2PhotoUri],
27
41
  };
42
+
43
+ if (DEV) {
44
+ console.log("[CoupleUtil] ===== COUPLE MODE SELECTED =====");
45
+ console.log("[CoupleUtil] Target model:", result.target.model);
46
+ console.log("[CoupleUtil] Target provider:", result.target.providerId);
47
+ console.log("[CoupleUtil] Image URLs:", result.imageUrls.length);
48
+ console.log("[CoupleUtil] Image 1:", result.imageUrls[0].substring(0, 60) + "...");
49
+ console.log("[CoupleUtil] Image 2:", result.imageUrls[1].substring(0, 60) + "...");
50
+ console.log("[CoupleUtil] ===== RESOLVE COMPLETE =====");
51
+ }
52
+
53
+ return result;
28
54
  }
29
- return {
55
+
56
+ const result = {
30
57
  target: singleTarget,
31
58
  imageUrls: [partner1PhotoUri],
32
59
  };
60
+
61
+ if (DEV) {
62
+ console.log("[CoupleUtil] ===== SINGLE MODE SELECTED =====");
63
+ console.log("[CoupleUtil] Target model:", result.target.model);
64
+ console.log("[CoupleUtil] Target provider:", result.target.providerId);
65
+ console.log("[CoupleUtil] Image URLs:", result.imageUrls.length);
66
+ console.log("[CoupleUtil] Image 1:", result.imageUrls[0].substring(0, 60) + "...");
67
+ console.log("[CoupleUtil] ===== RESOLVE COMPLETE =====");
68
+ }
69
+
70
+ return result;
33
71
  }
34
72
 
35
73
  /**
@@ -47,6 +85,13 @@ export function prependContext(
47
85
  * Primarily used to fix "baked" prompts that were generated with a specific mode in mind.
48
86
  */
49
87
  export function refinePromptForCouple(prompt: string, isCouple: boolean): string {
88
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
89
+ console.log("[CoupleUtil] ===== REFINE PROMPT START =====");
90
+ console.log("[CoupleUtil] Is couple mode:", isCouple);
91
+ console.log("[CoupleUtil] Original prompt length:", prompt.length);
92
+ console.log("[CoupleUtil] Original prompt preview:", prompt.substring(0, 200) + "...");
93
+ }
94
+
50
95
  if (isCouple) {
51
96
  // Ensure couple context is present
52
97
  let refined = prompt
@@ -64,22 +109,36 @@ export function refinePromptForCouple(prompt: string, isCouple: boolean): string
64
109
  refined = refined
65
110
  .replace(/\b(dress|gown)\b/gi, "$1 (worn by Person 1)")
66
111
  .replace(/\b(suit|tuxedo|linen trousers)\b/gi, "$1 (worn by Person 2)");
67
-
112
+
68
113
  // Also add explicit mapping to the top if not already there
69
114
  if (!refined.includes("DIRECTIVE: MAP PHOTO 1 TO PERSON 1")) {
70
115
  refined = `DIRECTIVE: MAP PHOTO 1 TO PERSON 1, MAP PHOTO 2 TO PERSON 2\n\n${refined}`;
71
116
  }
117
+
118
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
119
+ console.log("[CoupleUtil] ✅ Clothing mapping applied!");
120
+ console.log("[CoupleUtil] ✅ Directive added for photo mapping");
121
+ }
72
122
  }
73
123
 
74
124
  // If it doesn't already have couple-hints, add them at the start
75
125
  if (!/\b(couple|both|matching|dual|two people)\b/i.test(refined) && !refined.includes("DIRECTIVE:")) {
76
126
  refined = `A photo of a couple, ${refined}`;
127
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
128
+ console.log("[CoupleUtil] ✅ Added 'A photo of a couple' prefix");
129
+ }
130
+ }
131
+
132
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
133
+ console.log("[CoupleUtil] Refined prompt length:", refined.length);
134
+ console.log("[CoupleUtil] Refined prompt preview:", refined.substring(0, 300) + "...");
135
+ console.log("[CoupleUtil] ===== REFINE PROMPT END =====");
77
136
  }
78
137
  return refined;
79
138
  } else {
80
139
  // Solo mode: AGGRESSIVELY remove plural references to prevent "ghost" people
81
- return prompt
82
- // Instead of removing the clothing descriptions, just remove the gender labels
140
+ const soloRefined = prompt
141
+ // Instead of removing the clothing descriptions, just remove the gender labels
83
142
  // so the AI can apply the relevant clothing to the single person it sees.
84
143
  .replace(/\sfor women\b/gi, "")
85
144
  .replace(/\sfor men\b/gi, "")
@@ -90,7 +149,7 @@ export function refinePromptForCouple(prompt: string, isCouple: boolean): string
90
149
  .replace(/\bcoordinating\b/gi, "")
91
150
  .replace(/\bcouple\b/gi, "person")
92
151
  .replace(/\bduo\b/gi, "person")
93
- .replace(/\bpair\b/gi, "person")
152
+ .replace(/\bpair\b/gi, "person")
94
153
  .replace(/\bdoubles\b/gi, "")
95
154
  .replace(/\bboth\b/gi, "the person")
96
155
  .replace(/\bthey are\b/gi, "the person is")
@@ -109,6 +168,13 @@ export function refinePromptForCouple(prompt: string, isCouple: boolean): string
109
168
  .replace(/\bhats\b/gi, "hat")
110
169
  .replace(/\baccessories\b/gi, "accessory")
111
170
  .replace(/\s+/g, ' ').trim();
171
+
172
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
173
+ console.log("[CoupleUtil] ✅ Solo mode - removed all plural references");
174
+ console.log("[CoupleUtil] Solo refined prompt length:", soloRefined.length);
175
+ console.log("[CoupleUtil] ===== REFINE PROMPT END =====");
176
+ }
177
+ return soloRefined;
112
178
  }
113
179
  }
114
180