@umituz/react-native-ai-generation-content 1.89.42 → 1.89.49

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,16 +1,19 @@
1
1
  {
2
2
  "name": "@umituz/react-native-ai-generation-content",
3
- "version": "1.89.42",
3
+ "version": "1.89.49",
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
  "sideEffects": false,
8
8
  "exports": {
9
9
  ".": "./src/index.ts",
10
+ "./src": "./src/index.ts",
11
+ "./src/*": "./src/*.ts",
10
12
  "./core": "./src/core/index.ts",
11
13
  "./prompts": "./src/domains/prompts/index.ts",
12
14
  "./content-moderation": "./src/domains/content-moderation/index.ts",
13
15
  "./creations": "./src/domains/creations/index.ts",
16
+ "./src/creations": "./src/domains/creations/index.ts",
14
17
  "./face-detection": "./src/domains/face-detection/index.ts",
15
18
  "./generation": "./src/domains/generation/index.ts",
16
19
  "./package.json": "./package.json"
@@ -16,9 +16,20 @@ import { refinePromptForCouple } from "../../../infrastructure/utils/couple-inpu
16
16
  * @returns Appearance context string (şu an boş)
17
17
  */
18
18
  export async function getAppearanceContext(
19
- _photoUris: string[],
20
- _isCoupleMode: boolean,
19
+ photoUris: string[],
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;
@@ -73,6 +73,8 @@ export interface ScenarioGenerationInputParams {
73
73
  export async function buildCoupleGenerationInput(
74
74
  params: CoupleGenerationInputParams,
75
75
  ): Promise<CoupleGenerationInput> {
76
+ const DEV = typeof __DEV__ !== "undefined" && __DEV__;
77
+
76
78
  const {
77
79
  partner1PhotoUri,
78
80
  partner2PhotoUri,
@@ -83,33 +85,122 @@ export async function buildCoupleGenerationInput(
83
85
  strength,
84
86
  } = params;
85
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
+
86
109
  // 1. GET PHOTO URIs - Couple mode kontrolü
87
110
  const photoUris =
88
111
  isCoupleMode && partner2PhotoUri
89
112
  ? [partner1PhotoUri, partner2PhotoUri]
90
113
  : [partner1PhotoUri];
91
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
+
92
124
  // 2. ANALYZE APPEARANCE - Wardrobe'daki gibi
93
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
+
94
134
  const appearanceContext = await getAppearanceContext(
95
135
  photoUris,
96
136
  isCoupleMode,
97
137
  );
98
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
+
99
148
  // 3. REFINE FOR COUPLE + PREPEND CONTEXT - Wardrobe mantığı
100
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
+
101
158
  const refinedPrompt = prependContext(
102
159
  refinePromptForCouple(basePrompt, isCoupleMode),
103
160
  appearanceContext,
104
161
  );
105
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
+
106
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
+
107
178
  const prompt = createPhotorealisticPrompt(refinedPrompt, {
108
179
  isCouple: isCoupleMode,
109
180
  customInstructions,
110
181
  });
111
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
+
112
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
+
113
204
  const { target, imageUrls } = resolveCoupleInput(
114
205
  partner1PhotoUri,
115
206
  partner2PhotoUri,
@@ -118,7 +209,22 @@ export async function buildCoupleGenerationInput(
118
209
  { model: "p-image-edit", providerId: "pruna" }, // Couple target
119
210
  );
120
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
+
121
223
  // 6. BUILD PARAMS - Wardrobe formatında
224
+ if (DEV) {
225
+ console.log("[CoupleBuilder] ===== STEP 6: BUILD PARAMS =====");
226
+ }
227
+
122
228
  const genParams: Record<string, unknown> = {
123
229
  prompt,
124
230
  image_urls: imageUrls,
@@ -130,6 +236,19 @@ export async function buildCoupleGenerationInput(
130
236
  genParams.strength = strength;
131
237
  }
132
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
+
133
252
  return {
134
253
  target,
135
254
  prompt,
@@ -146,6 +265,8 @@ export async function buildCoupleGenerationInput(
146
265
  export async function buildScenarioGenerationInput(
147
266
  params: ScenarioGenerationInputParams,
148
267
  ): Promise<CoupleGenerationInput> {
268
+ const DEV = typeof __DEV__ !== "undefined" && __DEV__;
269
+
149
270
  const {
150
271
  partner1PhotoUri,
151
272
  partner2PhotoUri,
@@ -153,26 +274,71 @@ export async function buildScenarioGenerationInput(
153
274
  scenarioPrompt,
154
275
  } = params;
155
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
+
156
291
  // 1. GET PHOTO URIs
157
292
  const photoUris =
158
293
  isCoupleMode && partner2PhotoUri
159
294
  ? [partner1PhotoUri, partner2PhotoUri]
160
295
  : [partner1PhotoUri];
161
296
 
297
+ if (DEV) {
298
+ console.log("[ScenarioBuilder] ===== STEP 1: PHOTO URIs =====");
299
+ console.log("[ScenarioBuilder] Photo URIs count:", photoUris.length);
300
+ }
301
+
162
302
  // 2. ANALYZE APPEARANCE
303
+ if (DEV) {
304
+ console.log("[ScenarioBuilder] ===== STEP 2: APPEARANCE ANALYSIS =====");
305
+ }
306
+
163
307
  const appearanceContext = await getAppearanceContext(
164
308
  photoUris,
165
309
  isCoupleMode,
166
310
  );
167
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
+
168
321
  // 3. REFINE FOR COUPLE + PREPEND CONTEXT
169
322
  // Senaryo prompt'unu (zaten photorealistic) dynamic context ile birleştir
170
- const finalPrompt = prependContext(
171
- refinePromptForCouple(scenarioPrompt, isCoupleMode),
172
- appearanceContext,
173
- );
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
+ }
174
336
 
175
337
  // 4. RESOLVE COUPLE INPUT
338
+ if (DEV) {
339
+ console.log("[ScenarioBuilder] ===== STEP 4: RESOLVE COUPLE INPUT =====");
340
+ }
341
+
176
342
  const { target, imageUrls } = resolveCoupleInput(
177
343
  partner1PhotoUri,
178
344
  partner2PhotoUri,
@@ -181,7 +347,21 @@ export async function buildScenarioGenerationInput(
181
347
  { model: "p-image-edit", providerId: "pruna" }, // Couple target
182
348
  );
183
349
 
350
+ if (DEV) {
351
+ console.log("[ScenarioBuilder] Target:", target.model, "/", target.providerId);
352
+ console.log("[ScenarioBuilder] Image URLs count:", imageUrls.length);
353
+ }
354
+
184
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
+
185
365
  return {
186
366
  target,
187
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,21 +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
- // Note: Scenario prompts are already wrapped with createPhotorealisticPrompt
47
- // in the data files, so we only apply couple refinement here
48
92
  const isCoupleMode = photos.length >= 2;
49
- 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
+ });
50
126
 
51
127
  if (typeof __DEV__ !== "undefined" && __DEV__) {
52
- console.log("[ImageStrategy] Prompt enhanced with couple refinement", {
53
- photoCount: photos.length,
54
- isCoupleMode,
55
- originalPromptLength: prompt.length,
56
- finalPromptLength: finalPrompt.length,
57
- });
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`));
58
135
  }
59
136
  }
60
137
 
@@ -62,8 +139,29 @@ export async function buildImageInput(
62
139
  const styleValue = extractSelection(wizardData.style);
63
140
  const style = typeof styleValue === "string" ? styleValue : undefined;
64
141
 
65
- // Extract aspect ratio from wizard data
66
- 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
+ }
67
165
 
68
166
  return { photos, prompt: finalPrompt, style, aspectRatio };
69
167
  }
@@ -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