@umituz/react-native-ai-generation-content 1.90.2 → 1.90.3
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/domain/interfaces/app-services-auth.interface.ts +27 -0
- package/src/domain/interfaces/app-services-composite.interface.ts +29 -0
- package/src/domain/interfaces/app-services-optional.interface.ts +42 -0
- package/src/domain/interfaces/app-services.interface.ts +0 -79
- package/src/domains/background/infrastructure/services/job-poller-index.ts +7 -0
- package/src/domains/background/infrastructure/services/job-poller-utils.ts +130 -0
- package/src/domains/background/infrastructure/utils/polling-interval.util.ts +1 -1
- package/src/domains/background/presentation/hooks/use-background-generation.ts +1 -1
- package/src/domains/content-moderation/infrastructure/services/content-moderation.service.ts +1 -1
- package/src/domains/content-moderation/infrastructure/services/moderators/image.moderator.ts +34 -8
- package/src/domains/content-moderation/infrastructure/services/moderators/text.moderator.ts +15 -4
- package/src/domains/content-moderation/infrastructure/services/moderators/video.moderator.ts +34 -8
- package/src/domains/content-moderation/infrastructure/services/moderators/voice.moderator.ts +19 -8
- package/src/domains/creations/domain/types/creation-categories.constants.ts +57 -0
- package/src/domains/creations/domain/types/creation-categories.helpers.ts +67 -0
- package/src/domains/creations/domain/types/creation-categories.ts +5 -111
- package/src/domains/creations/presentation/hooks/creation-validators.ts +31 -29
- package/src/domains/creations/presentation/hooks/job-poller-index.ts +10 -0
- package/src/domains/creations/presentation/hooks/job-poller-utils.filters.ts +34 -0
- package/src/domains/creations/presentation/hooks/job-poller-utils.logger.ts +76 -0
- package/src/domains/creations/presentation/hooks/job-poller-utils.stale-handlers.ts +52 -0
- package/src/domains/creations/presentation/hooks/job-poller-utils.ts +8 -0
- package/src/domains/creations/presentation/screens/CreationsGalleryScreen.tsx +1 -1
- package/src/domains/creations/presentation-exports.ts +2 -2
- package/src/domains/face-detection/domain/entities/FaceDetection.ts +4 -3
- package/src/domains/face-detection/presentation/hooks/useFaceDetection.ts +24 -21
- package/src/domains/generation/infrastructure/couple-generation-builder/builder-couple-preparation.ts +58 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/builder-couple-prompt.ts +69 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/builder-couple-resolution.ts +77 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/builder-couple.ts +54 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/builder-index.ts +8 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/builder-scenario.ts +113 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/builder.ts +7 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/index.ts +20 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/types.ts +44 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/utils/builder-end-logger.ts +18 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/utils/builder-start-logger.ts +57 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/utils/builder-step-logger.ts +106 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/utils/index.ts +8 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/utils/types.ts +49 -0
- package/src/domains/generation/infrastructure/couple-generation-builder/utils.ts +8 -0
- package/src/domains/generation/infrastructure/flow/flow-store-actions.ts +105 -0
- package/src/domains/generation/infrastructure/flow/flow-store-initial-state.ts +26 -0
- package/src/domains/generation/infrastructure/flow/useFlowStore.ts +4 -116
- package/src/domains/generation/presentation/useAIGeneration.hook.ts +1 -1
- package/src/domains/generation/wizard/infrastructure/strategies/image-generation-strategy-index.ts +7 -0
- package/src/domains/generation/wizard/infrastructure/strategies/image-generation.executor.ts +2 -12
- package/src/domains/generation/wizard/infrastructure/strategies/image-generation.executor.types.ts +11 -0
- package/src/domains/generation/wizard/infrastructure/strategies/image-generation.executor.utils.ts +12 -0
- package/src/domains/generation/wizard/infrastructure/strategies/image-generation.strategy.ts +1 -220
- package/src/domains/generation/wizard/infrastructure/strategies/image-input-builder.ts +66 -0
- package/src/domains/generation/wizard/infrastructure/strategies/image-input-extraction.ts +88 -0
- package/src/domains/generation/wizard/infrastructure/strategies/image-input-prompt-builder.ts +75 -0
- package/src/domains/generation/wizard/infrastructure/strategies/image-input-style-enhancements.ts +35 -0
- package/src/domains/generation/wizard/infrastructure/strategies/image-strategy-factory.ts +42 -0
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation-executor-index.ts +11 -0
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation-executor.ts +76 -0
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation-input-builder.ts +46 -0
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation-result-types.ts +17 -0
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation-submission.ts +62 -0
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation.audio-extractor.ts +27 -0
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation.executor.ts +2 -175
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation.input-builder.ts +90 -0
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation.strategy.ts +3 -108
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation.types.ts +0 -129
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation.validation.ts +136 -0
- package/src/domains/generation/wizard/presentation/hooks/photo-upload/index.ts +39 -0
- package/src/domains/generation/wizard/presentation/hooks/photo-upload/types.ts +37 -0
- package/src/domains/generation/wizard/presentation/hooks/photo-upload/usePhotoUploadStateLogic.ts +142 -0
- package/src/domains/generation/wizard/presentation/hooks/use-video-queue-utils.ts +103 -0
- package/src/domains/generation/wizard/presentation/hooks/usePhotoBlockingGeneration.handlers.ts +97 -0
- package/src/domains/generation/wizard/presentation/hooks/usePhotoBlockingGeneration.saver.ts +54 -0
- package/src/domains/generation/wizard/presentation/hooks/usePhotoBlockingGeneration.ts +22 -87
- package/src/domains/generation/wizard/presentation/hooks/usePhotoUploadState.ts +8 -177
- package/src/domains/generation/wizard/presentation/hooks/useVideoQueueGeneration.ts +1 -295
- package/src/domains/generation/wizard/presentation/hooks/useWizardGeneration.ts +1 -1
- package/src/domains/generation/wizard/presentation/hooks/video-queue/index.ts +82 -0
- package/src/domains/generation/wizard/presentation/hooks/video-queue/useVideoQueueGenerationCallbacks.ts +120 -0
- package/src/domains/generation/wizard/presentation/hooks/video-queue/useVideoQueueGenerationPolling.ts +76 -0
- package/src/domains/generation/wizard/presentation/hooks/video-queue/useVideoQueueGenerationRefs.ts +65 -0
- package/src/domains/generation/wizard/presentation/hooks/video-queue/useVideoQueueGenerationStart.ts +123 -0
- package/src/domains/generation/wizard/presentation/hooks/video-queue-index.ts +9 -0
- package/src/domains/image-to-video/domain/types/image-to-video-state.types.ts +11 -4
- package/src/domains/text-to-image/domain/types/text-to-image.types.ts +44 -22
- package/src/domains/text-to-video/domain/types/request.types.ts +33 -9
- package/src/domains/text-to-video/domain/types/state.types.ts +29 -9
- package/src/domains/text-to-video/presentation/hooks/useTextToVideoForm.handlers.ts +44 -0
- package/src/domains/text-to-video/presentation/hooks/useTextToVideoForm.ts +5 -51
- package/src/domains/text-to-video/presentation/hooks/useTextToVideoForm.types.ts +33 -0
- package/src/infrastructure/services/generation-orchestrator.service.ts +2 -2
- package/src/infrastructure/utils/couple-input-context.ts +13 -0
- package/src/infrastructure/utils/couple-input-index.ts +8 -0
- package/src/infrastructure/utils/couple-input-refiner.ts +101 -0
- package/src/infrastructure/utils/couple-input-resolver.ts +71 -0
- package/src/infrastructure/utils/couple-input-types.ts +14 -0
- package/src/infrastructure/utils/couple-input.util.ts +3 -176
- package/src/infrastructure/utils/photo-generation/photo-preparation.util.ts +1 -1
- package/src/infrastructure/validation/base-validator.ts +1 -27
- package/src/infrastructure/validation/base-validator.types.ts +32 -0
- package/src/presentation/hooks/generation/index.ts +1 -1
- package/src/presentation/hooks/generation/orchestrator-abort-logs.ts +48 -0
- package/src/presentation/hooks/generation/orchestrator-execution-logs.ts +67 -0
- package/src/presentation/hooks/generation/orchestrator-index.ts +14 -0
- package/src/presentation/hooks/generation/orchestrator-start-logs.ts +65 -0
- package/src/presentation/hooks/generation/orchestrator-state-utils.ts +17 -0
- package/src/presentation/hooks/generation/orchestrator-types.ts +55 -0
- package/src/presentation/hooks/generation/orchestrator-utils-index.ts +29 -0
- package/src/presentation/hooks/generation/orchestrator-utils.ts +25 -0
- package/src/presentation/hooks/generation/useDualImageGeneration.ts +1 -1
- package/src/presentation/hooks/generation/useImageGeneration.ts +1 -1
- package/src/presentation/hooks/generation/useVideoGeneration.ts +1 -1
- package/src/shared/hooks/factories/generation-hook-index.ts +12 -0
- package/src/shared/hooks/factories/generation-hook-types.ts +47 -0
- package/src/shared/hooks/factories/generation-hook-utils.ts +94 -0
- package/src/shared/hooks/factories/index.ts +1 -1
- package/src/shared/index.ts +1 -1
- package/src/shared/utils/calculations/aspect-ratio-calculations.ts +30 -0
- package/src/shared/utils/calculations/base64-calculations.ts +26 -0
- package/src/shared/utils/calculations/confidence-calculations.ts +21 -0
- package/src/shared/utils/calculations/cost-calculations-index.ts +43 -0
- package/src/shared/utils/calculations/cost-calculations.ts +25 -0
- package/src/shared/utils/calculations/credit-calculations.ts +37 -0
- package/src/shared/utils/calculations/index.ts +46 -0
- package/src/shared/utils/calculations/math-utilities.ts +32 -0
- package/src/shared/utils/calculations/memory-calculations.ts +33 -0
- package/src/shared/utils/calculations/pagination-calculations.ts +38 -0
- package/src/shared/utils/calculations/percentage-calculations.ts +33 -0
- package/src/shared/utils/calculations/time-calculations.ts +99 -0
- package/src/shared/utils/credit.ts +1 -1
- package/src/shared-kernel/application/hooks/index.ts +8 -0
- package/src/shared-kernel/application/hooks/use-feature-state.ts +107 -0
- package/src/shared-kernel/application/hooks/use-generation-handler.ts +110 -0
- package/src/shared-kernel/base-types/base-callbacks.types.ts +73 -0
- package/src/shared-kernel/base-types/base-feature-state.types.ts +77 -0
- package/src/shared-kernel/base-types/base-generation.types.ts +69 -0
- package/src/shared-kernel/base-types/index.ts +30 -0
- package/src/shared-kernel/domain/base-generation-strategy.ts +146 -0
- package/src/shared-kernel/domain/index.ts +7 -0
- package/src/shared-kernel/index.ts +17 -0
- package/src/shared-kernel/infrastructure/validation/common-validators.ts +126 -0
- package/src/shared-kernel/infrastructure/validation/common-validators.types.ts +33 -0
- package/src/shared-kernel/infrastructure/validation/error-handler.ts +52 -0
- package/src/shared-kernel/infrastructure/validation/error-handler.types.ts +38 -0
- package/src/shared-kernel/infrastructure/validation/error-handler.utils.ts +79 -0
- package/src/shared-kernel/infrastructure/validation/index.ts +28 -0
- package/src/domains/background/infrastructure/services/job-poller.service.ts +0 -234
- package/src/domains/creations/presentation/hooks/useProcessingJobsPoller.ts +0 -256
- package/src/domains/generation/infrastructure/couple-generation-builder.ts +0 -374
- package/src/presentation/hooks/generation/orchestrator.ts +0 -276
- package/src/shared/hooks/factories/createGenerationHook.ts +0 -253
- package/src/shared/utils/calculations.util.ts +0 -366
|
@@ -1,374 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Couple Image Generation Builder
|
|
3
|
-
*
|
|
4
|
-
* Wardrobe'da kusursuz çalışan mantığı tüm couple generation için paylaştırır.
|
|
5
|
-
* Bu utility'yi tüm çift görüntü oluşturma işlemleri kullanır.
|
|
6
|
-
*
|
|
7
|
-
* Kullanım alanları:
|
|
8
|
-
* - Senaryo generation (Home couple images)
|
|
9
|
-
* - Wardrobe generation
|
|
10
|
-
* - Background generation
|
|
11
|
-
* - Art style generation
|
|
12
|
-
* - Mood filter generation
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import {
|
|
16
|
-
resolveCoupleInput,
|
|
17
|
-
prependContext,
|
|
18
|
-
refinePromptForCouple,
|
|
19
|
-
} from "../../../infrastructure/utils/couple-input.util";
|
|
20
|
-
import type { GenerationTargetLike } from "../../../infrastructure/utils/couple-input.util";
|
|
21
|
-
import { createPhotorealisticPrompt } from "../../prompts";
|
|
22
|
-
import { getAppearanceContext } from "./appearance-analysis";
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Couple generation input parameters
|
|
26
|
-
*/
|
|
27
|
-
export interface CoupleGenerationInputParams {
|
|
28
|
-
// Required params
|
|
29
|
-
partner1PhotoUri: string;
|
|
30
|
-
partner2PhotoUri: string | null;
|
|
31
|
-
isCoupleMode: boolean;
|
|
32
|
-
basePrompt: string; // Scenario prompt, wardrobe prompt, background prompt, etc.
|
|
33
|
-
|
|
34
|
-
// Optional params
|
|
35
|
-
customInstructions?: string;
|
|
36
|
-
aspectRatio?: string; // Default: "3:4"
|
|
37
|
-
strength?: number; // Optional strength for some operations
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Couple generation result
|
|
42
|
-
*/
|
|
43
|
-
export interface CoupleGenerationInput {
|
|
44
|
-
target: GenerationTargetLike;
|
|
45
|
-
prompt: string;
|
|
46
|
-
params: Record<string, unknown>;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Scenario generation input parameters
|
|
51
|
-
*/
|
|
52
|
-
export interface ScenarioGenerationInputParams {
|
|
53
|
-
partner1PhotoUri: string;
|
|
54
|
-
partner2PhotoUri: string | null;
|
|
55
|
-
isCoupleMode: boolean;
|
|
56
|
-
scenarioPrompt: string; // Senaryo prompt'u (aiPrompt)
|
|
57
|
-
customInstructions?: string;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Merkezi couple generation input builder
|
|
62
|
-
*
|
|
63
|
-
* Wardrobe mantığını tüm couple generation için paylaştırır:
|
|
64
|
-
* 1. Appearance analysis (fotoğrafları analiz et)
|
|
65
|
-
* 2. Couple refinement (çift modu için iyileştir)
|
|
66
|
-
* 3. Context prepending (context'i prompt'a ekle)
|
|
67
|
-
* 4. Photorealistic prompt creation
|
|
68
|
-
* 5. Couple input resolution (doğru target ve image'lar)
|
|
69
|
-
*
|
|
70
|
-
* @param params - Generation parameters
|
|
71
|
-
* @returns Generation input with target, prompt, and params
|
|
72
|
-
*/
|
|
73
|
-
export async function buildCoupleGenerationInput(
|
|
74
|
-
params: CoupleGenerationInputParams,
|
|
75
|
-
): Promise<CoupleGenerationInput> {
|
|
76
|
-
const DEV = typeof __DEV__ !== "undefined" && __DEV__;
|
|
77
|
-
|
|
78
|
-
const {
|
|
79
|
-
partner1PhotoUri,
|
|
80
|
-
partner2PhotoUri,
|
|
81
|
-
isCoupleMode,
|
|
82
|
-
basePrompt,
|
|
83
|
-
customInstructions,
|
|
84
|
-
aspectRatio = "3:4", // Standard portrait ratio like Wardrobe
|
|
85
|
-
strength,
|
|
86
|
-
} = params;
|
|
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
|
-
|
|
109
|
-
// 1. GET PHOTO URIs - Couple mode kontrolü
|
|
110
|
-
const photoUris =
|
|
111
|
-
isCoupleMode && partner2PhotoUri
|
|
112
|
-
? [partner1PhotoUri, partner2PhotoUri]
|
|
113
|
-
: [partner1PhotoUri];
|
|
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
|
-
|
|
124
|
-
// 2. ANALYZE APPEARANCE - Wardrobe'daki gibi
|
|
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
|
-
|
|
134
|
-
const appearanceContext = await getAppearanceContext(
|
|
135
|
-
photoUris,
|
|
136
|
-
isCoupleMode,
|
|
137
|
-
);
|
|
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
|
-
|
|
148
|
-
// 3. REFINE FOR COUPLE + PREPEND CONTEXT - Wardrobe mantığı
|
|
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
|
-
|
|
158
|
-
const refinedPrompt = prependContext(
|
|
159
|
-
refinePromptForCouple(basePrompt, isCoupleMode),
|
|
160
|
-
appearanceContext,
|
|
161
|
-
);
|
|
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
|
-
|
|
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
|
-
|
|
178
|
-
const prompt = createPhotorealisticPrompt(refinedPrompt, {
|
|
179
|
-
isCouple: isCoupleMode,
|
|
180
|
-
customInstructions,
|
|
181
|
-
});
|
|
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
|
-
|
|
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
|
-
|
|
204
|
-
const { target, imageUrls } = resolveCoupleInput(
|
|
205
|
-
partner1PhotoUri,
|
|
206
|
-
partner2PhotoUri,
|
|
207
|
-
isCoupleMode,
|
|
208
|
-
{ model: "p-image-edit", providerId: "pruna" }, // Single target
|
|
209
|
-
{ model: "p-image-edit", providerId: "pruna" }, // Couple target
|
|
210
|
-
);
|
|
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
|
-
|
|
223
|
-
// 6. BUILD PARAMS - Wardrobe formatında
|
|
224
|
-
if (DEV) {
|
|
225
|
-
console.log("[CoupleBuilder] ===== STEP 6: BUILD PARAMS =====");
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
const genParams: Record<string, unknown> = {
|
|
229
|
-
prompt,
|
|
230
|
-
image_urls: imageUrls,
|
|
231
|
-
aspect_ratio: aspectRatio,
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
// Optional strength parameter
|
|
235
|
-
if (strength !== undefined) {
|
|
236
|
-
genParams.strength = strength;
|
|
237
|
-
}
|
|
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
|
-
|
|
252
|
-
return {
|
|
253
|
-
target,
|
|
254
|
-
prompt,
|
|
255
|
-
params: genParams,
|
|
256
|
-
};
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
* Scenario generation için özel wrapper
|
|
261
|
-
*
|
|
262
|
-
* Senaryo aiPrompt'larını (zaten createPhotorealisticPrompt ile oluşturulmuş)
|
|
263
|
-
* Wardrobe mantığı ile birleştirir.
|
|
264
|
-
*/
|
|
265
|
-
export async function buildScenarioGenerationInput(
|
|
266
|
-
params: ScenarioGenerationInputParams,
|
|
267
|
-
): Promise<CoupleGenerationInput> {
|
|
268
|
-
const DEV = typeof __DEV__ !== "undefined" && __DEV__;
|
|
269
|
-
|
|
270
|
-
const {
|
|
271
|
-
partner1PhotoUri,
|
|
272
|
-
partner2PhotoUri,
|
|
273
|
-
isCoupleMode,
|
|
274
|
-
scenarioPrompt,
|
|
275
|
-
} = params;
|
|
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
|
-
|
|
291
|
-
// 1. GET PHOTO URIs
|
|
292
|
-
const photoUris =
|
|
293
|
-
isCoupleMode && partner2PhotoUri
|
|
294
|
-
? [partner1PhotoUri, partner2PhotoUri]
|
|
295
|
-
: [partner1PhotoUri];
|
|
296
|
-
|
|
297
|
-
if (DEV) {
|
|
298
|
-
console.log("[ScenarioBuilder] ===== STEP 1: PHOTO URIs =====");
|
|
299
|
-
console.log("[ScenarioBuilder] Photo URIs count:", photoUris.length);
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
// 2. ANALYZE APPEARANCE
|
|
303
|
-
if (DEV) {
|
|
304
|
-
console.log("[ScenarioBuilder] ===== STEP 2: APPEARANCE ANALYSIS =====");
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
const appearanceContext = await getAppearanceContext(
|
|
308
|
-
photoUris,
|
|
309
|
-
isCoupleMode,
|
|
310
|
-
);
|
|
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
|
-
|
|
321
|
-
// 3. REFINE FOR COUPLE + PREPEND CONTEXT
|
|
322
|
-
// Senaryo prompt'unu (zaten photorealistic) dynamic context ile birleştir
|
|
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
|
-
}
|
|
336
|
-
|
|
337
|
-
// 4. RESOLVE COUPLE INPUT
|
|
338
|
-
if (DEV) {
|
|
339
|
-
console.log("[ScenarioBuilder] ===== STEP 4: RESOLVE COUPLE INPUT =====");
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
const { target, imageUrls } = resolveCoupleInput(
|
|
343
|
-
partner1PhotoUri,
|
|
344
|
-
partner2PhotoUri,
|
|
345
|
-
isCoupleMode,
|
|
346
|
-
{ model: "p-image-edit", providerId: "pruna" }, // Single target
|
|
347
|
-
{ model: "p-image-edit", providerId: "pruna" }, // Couple target
|
|
348
|
-
);
|
|
349
|
-
|
|
350
|
-
if (DEV) {
|
|
351
|
-
console.log("[ScenarioBuilder] Target:", target.model, "/", target.providerId);
|
|
352
|
-
console.log("[ScenarioBuilder] Image URLs count:", imageUrls.length);
|
|
353
|
-
}
|
|
354
|
-
|
|
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
|
-
|
|
365
|
-
return {
|
|
366
|
-
target,
|
|
367
|
-
prompt: finalPrompt,
|
|
368
|
-
params: {
|
|
369
|
-
prompt: finalPrompt,
|
|
370
|
-
image_urls: imageUrls,
|
|
371
|
-
aspect_ratio: "3:4",
|
|
372
|
-
},
|
|
373
|
-
};
|
|
374
|
-
}
|
|
@@ -1,276 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generation Orchestrator
|
|
3
|
-
* Handles AI generation execution with network check, moderation, credit deduction, and error handling
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { useState, useCallback, useRef, useEffect } from "react";
|
|
7
|
-
import { useAlert } from "@umituz/react-native-design-system/molecules";
|
|
8
|
-
import { useOfflineStore } from "@umituz/react-native-design-system/offline";
|
|
9
|
-
import { createGenerationError, getAlertMessage, parseError } from "./errors";
|
|
10
|
-
import { handleModeration } from "./moderation-handler";
|
|
11
|
-
import type {
|
|
12
|
-
GenerationStrategy,
|
|
13
|
-
GenerationConfig,
|
|
14
|
-
GenerationState,
|
|
15
|
-
GenerationError,
|
|
16
|
-
UseGenerationOrchestratorReturn,
|
|
17
|
-
} from "./types";
|
|
18
|
-
|
|
19
|
-
const getInitialState = <T>(): GenerationState<T> => ({
|
|
20
|
-
status: "idle",
|
|
21
|
-
isGenerating: false,
|
|
22
|
-
result: null,
|
|
23
|
-
error: null,
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
export const useGenerationOrchestrator = <TInput, TResult>(
|
|
27
|
-
strategy: GenerationStrategy<TInput, TResult>,
|
|
28
|
-
config: GenerationConfig,
|
|
29
|
-
): UseGenerationOrchestratorReturn<TInput, TResult> => {
|
|
30
|
-
const { userId, alertMessages, onSuccess, onError, moderation, lifecycle } = config;
|
|
31
|
-
|
|
32
|
-
const [state, setState] = useState<GenerationState<TResult>>(getInitialState<TResult>());
|
|
33
|
-
const isGeneratingRef = useRef(false);
|
|
34
|
-
const isMountedRef = useRef(true);
|
|
35
|
-
const abortControllerRef = useRef<AbortController | null>(null);
|
|
36
|
-
const cleanupTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
37
|
-
|
|
38
|
-
// Stable refs for callbacks — prevents useCallback deps from thrashing when
|
|
39
|
-
// callers pass inline functions (which create new references every render).
|
|
40
|
-
const onSuccessRef = useRef(onSuccess);
|
|
41
|
-
const onErrorRef = useRef(onError);
|
|
42
|
-
// Update refs in render body (not useEffect) so they're always in sync — no 1-frame delay
|
|
43
|
-
onSuccessRef.current = onSuccess;
|
|
44
|
-
onErrorRef.current = onError;
|
|
45
|
-
|
|
46
|
-
const offlineStore = useOfflineStore();
|
|
47
|
-
const { showError, showSuccess } = useAlert();
|
|
48
|
-
|
|
49
|
-
useEffect(() => {
|
|
50
|
-
isMountedRef.current = true;
|
|
51
|
-
return () => {
|
|
52
|
-
isMountedRef.current = false;
|
|
53
|
-
abortControllerRef.current?.abort();
|
|
54
|
-
// Clear any pending lifecycle complete timeout
|
|
55
|
-
if (cleanupTimeoutRef.current) {
|
|
56
|
-
clearTimeout(cleanupTimeoutRef.current);
|
|
57
|
-
cleanupTimeoutRef.current = null;
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
}, []);
|
|
61
|
-
|
|
62
|
-
const handleLifecycleComplete = useCallback(
|
|
63
|
-
(status: "success" | "error", result?: TResult, error?: GenerationError) => {
|
|
64
|
-
if (!lifecycle?.onComplete) return;
|
|
65
|
-
|
|
66
|
-
// Clear any existing timeout first
|
|
67
|
-
if (cleanupTimeoutRef.current) {
|
|
68
|
-
clearTimeout(cleanupTimeoutRef.current);
|
|
69
|
-
cleanupTimeoutRef.current = null;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const delay = lifecycle.completeDelay ?? 500;
|
|
73
|
-
cleanupTimeoutRef.current = setTimeout(() => {
|
|
74
|
-
if (isMountedRef.current) {
|
|
75
|
-
lifecycle.onComplete?.(status, result, error);
|
|
76
|
-
}
|
|
77
|
-
cleanupTimeoutRef.current = null;
|
|
78
|
-
}, delay);
|
|
79
|
-
},
|
|
80
|
-
[lifecycle],
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
const executeGeneration = useCallback(
|
|
84
|
-
async (input: TInput) => {
|
|
85
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
86
|
-
console.log("[Orchestrator] ----------------------------------------");
|
|
87
|
-
console.log("[Orchestrator] executeGeneration() called");
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Check abort signal before starting
|
|
91
|
-
if (abortControllerRef.current?.signal.aborted) {
|
|
92
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
93
|
-
console.log("[Orchestrator] Aborted before generation started");
|
|
94
|
-
}
|
|
95
|
-
throw new Error("Generation aborted");
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
setState((prev) => ({ ...prev, status: "generating" }));
|
|
99
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
100
|
-
console.log("[Orchestrator] State: generating - calling strategy.execute()");
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const result = await strategy.execute(input);
|
|
104
|
-
|
|
105
|
-
// Check abort signal after execution
|
|
106
|
-
if (abortControllerRef.current?.signal.aborted) {
|
|
107
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
108
|
-
console.log("[Orchestrator] Aborted after generation completed");
|
|
109
|
-
}
|
|
110
|
-
throw new Error("Generation aborted");
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
114
|
-
console.log("[Orchestrator] strategy.execute() completed");
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (strategy.save && userId) {
|
|
118
|
-
// Check abort signal before save
|
|
119
|
-
if (abortControllerRef.current?.signal.aborted) {
|
|
120
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
121
|
-
console.log("[Orchestrator] Aborted before save");
|
|
122
|
-
}
|
|
123
|
-
throw new Error("Generation aborted");
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (isMountedRef.current) setState((prev) => ({ ...prev, status: "saving" }));
|
|
127
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
128
|
-
console.log("[Orchestrator] Saving result to Firestore");
|
|
129
|
-
}
|
|
130
|
-
try {
|
|
131
|
-
await strategy.save(result, userId);
|
|
132
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
133
|
-
console.log("[Orchestrator] Result saved successfully");
|
|
134
|
-
}
|
|
135
|
-
} catch (saveErr) {
|
|
136
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
137
|
-
console.log("[Orchestrator] ERROR: Save failed:", saveErr);
|
|
138
|
-
}
|
|
139
|
-
// Update state to error on save failure
|
|
140
|
-
if (isMountedRef.current) {
|
|
141
|
-
setState((prev) => ({ ...prev, status: "error", isGenerating: false }));
|
|
142
|
-
}
|
|
143
|
-
throw createGenerationError("save", alertMessages.saveFailed, saveErr instanceof Error ? saveErr : undefined);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Final abort check before success
|
|
148
|
-
if (abortControllerRef.current?.signal.aborted) {
|
|
149
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
150
|
-
console.log("[Orchestrator] Aborted before success callback");
|
|
151
|
-
}
|
|
152
|
-
throw new Error("Generation aborted");
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (isMountedRef.current) setState({ status: "success", isGenerating: false, result, error: null });
|
|
156
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
157
|
-
console.log("[Orchestrator] ✅ Generation SUCCESS");
|
|
158
|
-
console.log("[Orchestrator] ========================================");
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
if (alertMessages.success) showSuccess("Success", alertMessages.success);
|
|
162
|
-
await onSuccessRef.current?.(result);
|
|
163
|
-
handleLifecycleComplete("success", result);
|
|
164
|
-
return result;
|
|
165
|
-
},
|
|
166
|
-
[strategy, userId, alertMessages, showSuccess, handleLifecycleComplete],
|
|
167
|
-
);
|
|
168
|
-
|
|
169
|
-
const generate = useCallback(
|
|
170
|
-
async (input: TInput): Promise<TResult | void> => {
|
|
171
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
172
|
-
console.log("[Orchestrator] ========================================");
|
|
173
|
-
console.log("[Orchestrator] generate() called with input:", JSON.stringify(input).substring(0, 200));
|
|
174
|
-
console.log("[Orchestrator] isGenerating:", isGeneratingRef.current);
|
|
175
|
-
console.log("[Orchestrator] userId:", userId);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
if (isGeneratingRef.current) {
|
|
179
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
180
|
-
console.log("[Orchestrator] BLOCKED: Already generating");
|
|
181
|
-
}
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// Create new AbortController for this generation
|
|
186
|
-
abortControllerRef.current = new AbortController();
|
|
187
|
-
isGeneratingRef.current = true;
|
|
188
|
-
let moderationPending = false;
|
|
189
|
-
setState({ ...getInitialState<TResult>(), status: "checking", isGenerating: true });
|
|
190
|
-
|
|
191
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
192
|
-
console.log("[Orchestrator] State set to 'checking', isGenerating: true");
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
try {
|
|
196
|
-
// Check online status inside the try block to avoid dependency on offlineStore.isOnline
|
|
197
|
-
if (!offlineStore.isOnline) {
|
|
198
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
199
|
-
console.log("[Orchestrator] ERROR: User is offline");
|
|
200
|
-
}
|
|
201
|
-
throw createGenerationError("network", alertMessages.networkError);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
205
|
-
console.log("[Orchestrator] Online check passed");
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// Check if aborted before moderation
|
|
209
|
-
if (abortControllerRef.current.signal.aborted) {
|
|
210
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
211
|
-
console.log("[Orchestrator] ERROR: Generation aborted (2)");
|
|
212
|
-
}
|
|
213
|
-
throw new Error("Generation aborted");
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
217
|
-
console.log("[Orchestrator] Starting moderation check");
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
const result = await handleModeration({
|
|
221
|
-
input,
|
|
222
|
-
moderation,
|
|
223
|
-
alertMessages,
|
|
224
|
-
isMountedRef,
|
|
225
|
-
isGeneratingRef,
|
|
226
|
-
setState: (s) => setState(s as GenerationState<TResult>),
|
|
227
|
-
resetState: () => setState(getInitialState<TResult>()),
|
|
228
|
-
executeGeneration,
|
|
229
|
-
showError,
|
|
230
|
-
onError,
|
|
231
|
-
handleLifecycleComplete,
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
// If handleModeration returned undefined, the warning dialog was shown.
|
|
235
|
-
// The dialog's proceed/cancel callbacks now own isGeneratingRef — don't reset in finally.
|
|
236
|
-
if (result === undefined && moderation) {
|
|
237
|
-
moderationPending = true;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
return result;
|
|
241
|
-
} catch (err) {
|
|
242
|
-
// Don't show error if aborted
|
|
243
|
-
if (abortControllerRef.current?.signal.aborted) {
|
|
244
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
245
|
-
console.log("[Orchestrator] Generation aborted");
|
|
246
|
-
}
|
|
247
|
-
return;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
const error = parseError(err);
|
|
251
|
-
if (typeof __DEV__ !== "undefined" && __DEV__) console.log("[Orchestrator] Error:", error);
|
|
252
|
-
if (isMountedRef.current) setState({ status: "error", isGenerating: false, result: null, error });
|
|
253
|
-
showError("Error", getAlertMessage(error, alertMessages));
|
|
254
|
-
await onErrorRef.current?.(error);
|
|
255
|
-
handleLifecycleComplete("error", undefined, error);
|
|
256
|
-
throw error;
|
|
257
|
-
} finally {
|
|
258
|
-
// Only reset if moderation dialog did not take ownership
|
|
259
|
-
if (!moderationPending) {
|
|
260
|
-
isGeneratingRef.current = false;
|
|
261
|
-
}
|
|
262
|
-
abortControllerRef.current = null;
|
|
263
|
-
}
|
|
264
|
-
},
|
|
265
|
-
[offlineStore, moderation, alertMessages, strategy, executeGeneration, showError, handleLifecycleComplete],
|
|
266
|
-
);
|
|
267
|
-
|
|
268
|
-
const reset = useCallback(() => {
|
|
269
|
-
abortControllerRef.current?.abort();
|
|
270
|
-
abortControllerRef.current = null;
|
|
271
|
-
setState(getInitialState<TResult>());
|
|
272
|
-
isGeneratingRef.current = false;
|
|
273
|
-
}, []);
|
|
274
|
-
|
|
275
|
-
return { generate, reset, status: state.status, isGenerating: state.isGenerating, result: state.result, error: state.error };
|
|
276
|
-
};
|