@umituz/react-native-ai-generation-content 1.83.68 → 1.83.70

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-ai-generation-content",
3
- "version": "1.83.68",
3
+ "version": "1.83.70",
4
4
  "description": "Provider-agnostic AI generation orchestration for React Native with result preview components",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -65,6 +65,7 @@ export async function executeImageGeneration(
65
65
  if (typeof __DEV__ !== "undefined" && __DEV__) {
66
66
  const mode = imageUrls.length > 0 ? "Photo-based" : "Text-to-image";
67
67
  console.log(`[ImageExecutor] ${mode} generation`, { personCount: imageUrls.length });
68
+ console.log(`[ImageExecutor] Final prompt (${finalPrompt.length} chars):\n${finalPrompt.substring(0, 800)}${finalPrompt.length > 800 ? "\n...[truncated]" : ""}`);
68
69
  }
69
70
 
70
71
  const modelInput: Record<string, unknown> = {
@@ -1,11 +1,19 @@
1
1
  /**
2
2
  * Unified Prompt Builder
3
3
  * Single prompt building logic for ALL generation types (image & video)
4
- * Uses MultiPersonPromptStructure for photo-based scenarios
5
- * Uses createPhotorealisticPrompt for text-only scenarios
4
+ *
5
+ * For photo-based scenarios: the app's scenario already uses createPhotorealisticPrompt()
6
+ * to build a structured prompt. This builder only injects the MULTI-PERSON block
7
+ * into that existing structure — it does NOT re-wrap.
8
+ *
9
+ * For text-only scenarios: uses createPhotorealisticPrompt for wrapping.
6
10
  */
7
11
 
8
- import { createMultiPersonPrompt } from "../../../../../prompts/domain/entities/MultiPersonPromptStructure";
12
+ import { IDENTITY_PRESERVATION_CORE } from "../../../../../prompts/domain/base/constants";
13
+ import {
14
+ createMultiPersonBlock,
15
+ createMultiPersonPrompt,
16
+ } from "../../../../../prompts/domain/entities/MultiPersonPromptStructure";
9
17
  import { createPhotorealisticPrompt } from "../../../../../prompts/domain/base/creators";
10
18
 
11
19
  interface BuildPromptOptions {
@@ -21,7 +29,8 @@ interface BuildPromptOptions {
21
29
 
22
30
  /**
23
31
  * Build unified prompt for any generation type
24
- * - Photo-based: Uses createMultiPersonPrompt with @image1, @image2 references
32
+ * - Photo-based (already structured): Injects MULTI-PERSON block into existing prompt
33
+ * - Photo-based (raw text): Full wrapping with createMultiPersonPrompt
25
34
  * - Text-only: Uses createPhotorealisticPrompt
26
35
  * - Custom: Uses basePrompt directly when skipIdentityPreservation is true
27
36
  */
@@ -42,8 +51,21 @@ export function buildUnifiedPrompt(options: BuildPromptOptions): string {
42
51
  return basePrompt;
43
52
  }
44
53
 
45
- // Default: Photo-based generation with identity preservation
46
- let finalPrompt = createMultiPersonPrompt(basePrompt, photoCount);
54
+ // Photo-based: check if prompt is already structured by createPhotorealisticPrompt
55
+ const isAlreadyStructured = basePrompt.includes(IDENTITY_PRESERVATION_CORE);
56
+
57
+ let finalPrompt: string;
58
+
59
+ if (isAlreadyStructured) {
60
+ // Prompt already has IDENTITY + PHOTOREALISTIC + POSE from createPhotorealisticPrompt.
61
+ // Only inject the MULTI-PERSON block after IDENTITY_PRESERVATION_CORE.
62
+ const multiPersonBlock = createMultiPersonBlock(photoCount);
63
+ const insertPos = basePrompt.indexOf(IDENTITY_PRESERVATION_CORE) + IDENTITY_PRESERVATION_CORE.length;
64
+ finalPrompt = basePrompt.slice(0, insertPos) + "\n\n" + multiPersonBlock + basePrompt.slice(insertPos);
65
+ } else {
66
+ // Raw text prompt — apply full wrapping
67
+ finalPrompt = createMultiPersonPrompt(basePrompt, photoCount);
68
+ }
47
69
 
48
70
  // Add interaction style if specified by scenario (no defaults)
49
71
  if (interactionStyle) {
@@ -36,6 +36,8 @@ export interface GenericWizardFlowProps {
36
36
  readonly deductCredits?: (cost: number) => Promise<boolean>;
37
37
  readonly skipResultStep?: boolean;
38
38
  readonly onStepChange?: (stepId: string, stepType: StepType | string) => void;
39
+ /** When true, the GENERATING step is visible but generation waits (e.g. for prompt enhancement) */
40
+ readonly isPreparing?: boolean;
39
41
  readonly onGenerationStart?: (
40
42
  data: Record<string, unknown>,
41
43
  proceedToGenerating: () => void,
@@ -66,6 +68,7 @@ export const GenericWizardFlow: React.FC<GenericWizardFlowProps> = (props) => {
66
68
  deductCredits,
67
69
  skipResultStep = false,
68
70
  onStepChange,
71
+ isPreparing = false,
69
72
  onGenerationStart,
70
73
  onGenerationComplete,
71
74
  onGenerationError,
@@ -124,6 +127,7 @@ export const GenericWizardFlow: React.FC<GenericWizardFlowProps> = (props) => {
124
127
  calculateCredits={calculateCredits}
125
128
  deductCredits={deductCredits}
126
129
  skipResultStep={skipResultStep}
130
+ isPreparing={isPreparing}
127
131
  onStepChange={onStepChange}
128
132
  onGenerationStart={onGenerationStart}
129
133
  onGenerationComplete={onGenerationComplete}
@@ -37,6 +37,8 @@ interface WizardFlowContentProps {
37
37
  /** Called after successful generation to deduct credits — provided by the app */
38
38
  readonly deductCredits?: (cost: number) => Promise<boolean>;
39
39
  readonly skipResultStep?: boolean;
40
+ /** When true, the GENERATING step is visible but generation waits (e.g. for prompt enhancement) */
41
+ readonly isPreparing?: boolean;
40
42
  readonly onStepChange?: (stepId: string, stepType: StepType | string) => void;
41
43
  readonly onGenerationStart?: (
42
44
  data: Record<string, unknown>,
@@ -66,6 +68,7 @@ export const WizardFlowContent: React.FC<WizardFlowContentProps> = (props) => {
66
68
  calculateCredits,
67
69
  deductCredits,
68
70
  skipResultStep = false,
71
+ isPreparing = false,
69
72
  onStepChange,
70
73
  onGenerationStart,
71
74
  onGenerationComplete,
@@ -189,6 +192,7 @@ export const WizardFlowContent: React.FC<WizardFlowContentProps> = (props) => {
189
192
  wizardData: customData,
190
193
  userId,
191
194
  isGeneratingStep: currentStep?.type === StepType.GENERATING,
195
+ isPreparing,
192
196
  alertMessages,
193
197
  creditCost: calculatedCreditCost,
194
198
  deductCredits,
@@ -80,12 +80,10 @@ export const usePhotoUploadState = ({
80
80
  if (isLoading) {
81
81
  timeoutRef.current = setTimeout(() => {
82
82
  if (typeof __DEV__ !== "undefined" && __DEV__) {
83
- console.warn("[usePhotoUploadState] Image picker timeout - possible stuck state");
83
+ console.warn("[usePhotoUploadState] Image picker timeout - possible stuck state (DEV warning only)");
84
84
  }
85
- onErrorRef.current?.({
86
- title: translationsRef.current.error,
87
- message: "Image selection is taking too long. Please try again.",
88
- });
85
+ // NOTE: Do NOT call onError here — the picker may still complete successfully.
86
+ // Showing a modal alert while the picker is open blocks the UI.
89
87
  }, 30000);
90
88
  }
91
89
 
@@ -26,6 +26,7 @@ export const useWizardGeneration = (props: UseWizardGenerationProps): UseWizardG
26
26
  wizardData,
27
27
  userId,
28
28
  isGeneratingStep,
29
+ isPreparing = false,
29
30
  alertMessages,
30
31
  creditCost,
31
32
  deductCredits,
@@ -84,7 +85,7 @@ export const useWizardGeneration = (props: UseWizardGenerationProps): UseWizardG
84
85
  useEffect(() => {
85
86
  const isAlreadyGenerating = videoGeneration.isGenerating || photoGeneration.isGenerating;
86
87
 
87
- if (isGeneratingStep && state.status === "IDLE" && !isAlreadyGenerating) {
88
+ if (isGeneratingStep && state.status === "IDLE" && !isAlreadyGenerating && !isPreparing) {
88
89
  dispatch({ type: "START_PREPARATION" });
89
90
 
90
91
  // Execute generation and handle errors properly
@@ -112,6 +113,7 @@ export const useWizardGeneration = (props: UseWizardGenerationProps): UseWizardG
112
113
  }
113
114
  }, [
114
115
  isGeneratingStep,
116
+ isPreparing,
115
117
  state.status,
116
118
  scenario,
117
119
  wizardData,
@@ -32,6 +32,8 @@ export interface UseWizardGenerationProps {
32
32
  readonly wizardData: Record<string, unknown>;
33
33
  readonly userId?: string;
34
34
  readonly isGeneratingStep: boolean;
35
+ /** When true, generation waits even if on GENERATING step (e.g. prompt enhancement in progress) */
36
+ readonly isPreparing?: boolean;
35
37
  /** Required - alert messages for error states */
36
38
  readonly alertMessages: AlertMessages;
37
39
  /** Credit cost for this generation - REQUIRED, determined by the app */
@@ -23,23 +23,15 @@ export const MULTI_PERSON_PRESERVATION_RULES: MultiPersonPreservationRules = {
23
23
  };
24
24
 
25
25
  /**
26
- * Creates a multi-person prompt dynamically
27
- *
28
- * @param scenarioPrompt - The scenario description
29
- * @param personCount - Number of people (1, 2, 3, N)
30
- * @returns Complete prompt with identity preservation for all people
26
+ * Creates ONLY the multi-person identity block (no full wrapping).
27
+ * Used to inject into an already-structured prompt.
31
28
  */
32
- export const createMultiPersonPrompt = (
33
- scenarioPrompt: string,
34
- personCount: number,
35
- ): string => {
29
+ export const createMultiPersonBlock = (personCount: number): string => {
36
30
  const personRefs = Array.from({ length: personCount }, (_, i) =>
37
31
  `Person ${i + 1}: @image${i + 1} - preserve 100% facial identity`
38
32
  ).join("\n ");
39
33
 
40
- return `${IDENTITY_PRESERVATION_CORE}
41
-
42
- MULTI-PERSON IDENTITY PRESERVATION (${personCount} people):
34
+ return `MULTI-PERSON IDENTITY PRESERVATION (${personCount} people):
43
35
  {
44
36
  "requirement": "${MULTI_PERSON_PRESERVATION_RULES.requirement}",
45
37
  "references": [
@@ -47,7 +39,24 @@ MULTI-PERSON IDENTITY PRESERVATION (${personCount} people):
47
39
  ],
48
40
  "forbidden": ${JSON.stringify(MULTI_PERSON_PRESERVATION_RULES.forbidden)},
49
41
  "positioning": "${MULTI_PERSON_PRESERVATION_RULES.positioning}"
50
- }
42
+ }`;
43
+ };
44
+
45
+ /**
46
+ * Creates a multi-person prompt dynamically
47
+ * Used as fallback when basePrompt is raw text (not already structured).
48
+ *
49
+ * @param scenarioPrompt - The scenario description
50
+ * @param personCount - Number of people (1, 2, 3, N)
51
+ * @returns Complete prompt with identity preservation for all people
52
+ */
53
+ export const createMultiPersonPrompt = (
54
+ scenarioPrompt: string,
55
+ personCount: number,
56
+ ): string => {
57
+ return `${IDENTITY_PRESERVATION_CORE}
58
+
59
+ ${createMultiPersonBlock(personCount)}
51
60
 
52
61
  ${PHOTOREALISTIC_RENDERING}
53
62
 
@@ -54,6 +54,7 @@ export type { CreatePromptOptions } from './domain/base/types';
54
54
 
55
55
  export {
56
56
  MULTI_PERSON_PRESERVATION_RULES,
57
+ createMultiPersonBlock,
57
58
  createMultiPersonPrompt,
58
59
  } from './domain/entities/MultiPersonPromptStructure';
59
60
  export type { MultiPersonPreservationRules } from './domain/entities/MultiPersonPromptStructure';