@umituz/react-native-ai-generation-content 1.90.2 → 1.90.4
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 +3 -3
- 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/domain/interfaces/index.ts +3 -0
- package/src/domains/background/infrastructure/services/job-poller-index.ts +7 -0
- package/src/domains/background/infrastructure/services/job-poller-utils.ts +127 -0
- package/src/domains/background/infrastructure/services/job-poller.service.ts +85 -140
- 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/index.ts +7 -13
- 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/content-moderation/infrastructure/services/pattern-matcher.service.ts +1 -2
- 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 +7 -114
- package/src/domains/creations/domain/utils/creation-display.util.ts +1 -1
- package/src/domains/creations/domain/utils/status-helpers.ts +1 -1
- 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/hooks/useCreations.ts +1 -1
- package/src/domains/creations/presentation/hooks/useProcessingJobsPoller.ts +18 -235
- package/src/domains/creations/presentation/screens/CreationsGalleryScreen.tsx +1 -2
- 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/appearance-analysis/index.ts +5 -0
- 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 +112 -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 +74 -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 +41 -0
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation-executor-index.ts +10 -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 +61 -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 -176
- 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 -130
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation.validation.ts +136 -0
- package/src/domains/generation/wizard/presentation/hooks/photo-upload/index.ts +40 -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 +102 -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 +77 -0
- package/src/domains/generation/wizard/presentation/hooks/video-queue/use-video-queue-utils.ts +123 -0
- package/src/domains/generation/wizard/presentation/hooks/video-queue/useVideoQueueGenerationCallbacks.ts +119 -0
- package/src/domains/generation/wizard/presentation/hooks/video-queue/useVideoQueueGenerationPolling.ts +75 -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/constants/index.ts +5 -6
- package/src/domains/text-to-image/domain/types/text-to-image.types.ts +43 -22
- package/src/domains/text-to-video/domain/types/request.types.ts +32 -9
- package/src/domains/text-to-video/domain/types/state.types.ts +22 -22
- 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/exports/features.ts +1 -1
- 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 +9 -0
- package/src/infrastructure/utils/couple-input-photorealistic.ts +40 -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 +11 -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 +3 -26
- 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 +106 -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 +70 -0
- package/src/domains/content-moderation/infrastructure/services/index.ts +0 -8
- package/src/domains/creations/domain/constants/index.ts +0 -12
- package/src/domains/creations/domain/utils/index.ts +0 -12
- package/src/domains/generation/infrastructure/couple-generation-builder.ts +0 -374
- package/src/domains/image-to-video/domain/index.ts +0 -2
- package/src/domains/image-to-video/infrastructure/index.ts +0 -1
- package/src/domains/image-to-video/presentation/index.ts +0 -5
- package/src/domains/text-to-video/domain/index.ts +0 -1
- package/src/domains/text-to-video/presentation/index.ts +0 -7
- 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
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useTextToVideoForm Hook - Handlers
|
|
3
|
+
* Frame manipulation handlers for text-to-video form
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { FrameData } from "../../domain/types";
|
|
7
|
+
|
|
8
|
+
export function createFrameChangeHandler(
|
|
9
|
+
setFrames: React.Dispatch<React.SetStateAction<FrameData[]>>,
|
|
10
|
+
framesLength: number,
|
|
11
|
+
) {
|
|
12
|
+
return (fromIndex: number, toIndex: number) => {
|
|
13
|
+
if (fromIndex < 0 || fromIndex >= framesLength || toIndex < 0 || toIndex >= framesLength) {
|
|
14
|
+
if (__DEV__) {
|
|
15
|
+
console.warn("[TextToVideoForm] Invalid frame indices:", { fromIndex, toIndex, length: framesLength });
|
|
16
|
+
}
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (fromIndex === toIndex) return;
|
|
21
|
+
|
|
22
|
+
setFrames((prevFrames) => {
|
|
23
|
+
const newFrames = [...prevFrames];
|
|
24
|
+
const [movedFrame] = newFrames.splice(fromIndex, 1);
|
|
25
|
+
newFrames.splice(toIndex, 0, movedFrame);
|
|
26
|
+
return newFrames;
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function createFrameDeleteHandler(
|
|
32
|
+
setFrames: React.Dispatch<React.SetStateAction<FrameData[]>>,
|
|
33
|
+
framesLength: number,
|
|
34
|
+
) {
|
|
35
|
+
return (index: number) => {
|
|
36
|
+
if (index < 0 || index >= framesLength) {
|
|
37
|
+
if (__DEV__) {
|
|
38
|
+
console.warn("[TextToVideoForm] Invalid frame index:", index);
|
|
39
|
+
}
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
setFrames((prevFrames) => prevFrames.filter((_, i) => i !== index));
|
|
43
|
+
};
|
|
44
|
+
}
|
|
@@ -9,31 +9,8 @@ import type {
|
|
|
9
9
|
FrameData,
|
|
10
10
|
} from "../../domain/types";
|
|
11
11
|
import { INITIAL_FORM_STATE } from "../../domain/types";
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
export interface UseTextToVideoFormProps {
|
|
15
|
-
initialValues?: Partial<TextToVideoFormState>;
|
|
16
|
-
onPromptChange?: (prompt: string) => void;
|
|
17
|
-
onStyleChange?: (style: string) => void;
|
|
18
|
-
onTabChange?: (tab: string) => void;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface UseTextToVideoFormReturn {
|
|
22
|
-
state: TextToVideoFormState;
|
|
23
|
-
frames: FrameData[];
|
|
24
|
-
setPrompt: (prompt: string) => void;
|
|
25
|
-
setStyle: (style: string) => void;
|
|
26
|
-
setAspectRatio: (ratio: string) => void;
|
|
27
|
-
setDuration: (duration: number) => void;
|
|
28
|
-
setActiveTab: (tab: string) => void;
|
|
29
|
-
setSoundEnabled: (enabled: boolean) => void;
|
|
30
|
-
setProfessionalMode: (enabled: boolean) => void;
|
|
31
|
-
setFrames: (frames: FrameData[]) => void;
|
|
32
|
-
handleFrameChange: (fromIndex: number, toIndex: number) => void;
|
|
33
|
-
handleFrameDelete: (index: number) => void;
|
|
34
|
-
selectExamplePrompt: (prompt: string) => void;
|
|
35
|
-
reset: () => void;
|
|
36
|
-
}
|
|
12
|
+
import type { UseTextToVideoFormProps, UseTextToVideoFormReturn } from "./useTextToVideoForm.types";
|
|
13
|
+
import { createFrameChangeHandler, createFrameDeleteHandler } from "./useTextToVideoForm.handlers";
|
|
37
14
|
|
|
38
15
|
export function useTextToVideoForm(
|
|
39
16
|
props: UseTextToVideoFormProps = {},
|
|
@@ -88,36 +65,12 @@ export function useTextToVideoForm(
|
|
|
88
65
|
}, []);
|
|
89
66
|
|
|
90
67
|
const handleFrameChange = useCallback(
|
|
91
|
-
(
|
|
92
|
-
if (fromIndex < 0 || fromIndex >= frames.length || toIndex < 0 || toIndex >= frames.length) {
|
|
93
|
-
if (__DEV__) {
|
|
94
|
-
console.warn("[TextToVideoForm] Invalid frame indices:", { fromIndex, toIndex, length: frames.length });
|
|
95
|
-
}
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (fromIndex === toIndex) return;
|
|
100
|
-
|
|
101
|
-
setFrames((prevFrames) => {
|
|
102
|
-
const newFrames = [...prevFrames];
|
|
103
|
-
const [movedFrame] = newFrames.splice(fromIndex, 1);
|
|
104
|
-
newFrames.splice(toIndex, 0, movedFrame);
|
|
105
|
-
return newFrames;
|
|
106
|
-
});
|
|
107
|
-
},
|
|
68
|
+
createFrameChangeHandler(setFrames, frames.length),
|
|
108
69
|
[frames.length],
|
|
109
70
|
);
|
|
110
71
|
|
|
111
72
|
const handleFrameDelete = useCallback(
|
|
112
|
-
(
|
|
113
|
-
if (index < 0 || index >= frames.length) {
|
|
114
|
-
if (__DEV__) {
|
|
115
|
-
console.warn("[TextToVideoForm] Invalid frame index:", index);
|
|
116
|
-
}
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
setFrames((prevFrames) => prevFrames.filter((_, i) => i !== index));
|
|
120
|
-
},
|
|
73
|
+
createFrameDeleteHandler(setFrames, frames.length),
|
|
121
74
|
[frames.length],
|
|
122
75
|
);
|
|
123
76
|
|
|
@@ -150,3 +103,4 @@ export function useTextToVideoForm(
|
|
|
150
103
|
reset,
|
|
151
104
|
};
|
|
152
105
|
}
|
|
106
|
+
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useTextToVideoForm Hook - Types
|
|
3
|
+
* Type definitions for text-to-video form
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type {
|
|
7
|
+
TextToVideoFormState,
|
|
8
|
+
FrameData,
|
|
9
|
+
} from "../../domain/types";
|
|
10
|
+
|
|
11
|
+
export interface UseTextToVideoFormProps {
|
|
12
|
+
initialValues?: Partial<TextToVideoFormState>;
|
|
13
|
+
onPromptChange?: (prompt: string) => void;
|
|
14
|
+
onStyleChange?: (style: string) => void;
|
|
15
|
+
onTabChange?: (tab: string) => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface UseTextToVideoFormReturn {
|
|
19
|
+
state: TextToVideoFormState;
|
|
20
|
+
frames: FrameData[];
|
|
21
|
+
setPrompt: (prompt: string) => void;
|
|
22
|
+
setStyle: (style: string) => void;
|
|
23
|
+
setAspectRatio: (ratio: string) => void;
|
|
24
|
+
setDuration: (duration: number) => void;
|
|
25
|
+
setActiveTab: (tab: string) => void;
|
|
26
|
+
setSoundEnabled: (enabled: boolean) => void;
|
|
27
|
+
setProfessionalMode: (enabled: boolean) => void;
|
|
28
|
+
setFrames: (frames: FrameData[]) => void;
|
|
29
|
+
handleFrameChange: (fromIndex: number, toIndex: number) => void;
|
|
30
|
+
handleFrameDelete: (index: number) => void;
|
|
31
|
+
selectExamplePrompt: (prompt: string) => void;
|
|
32
|
+
reset: () => void;
|
|
33
|
+
}
|
package/src/exports/features.ts
CHANGED
|
@@ -47,7 +47,7 @@ export type {
|
|
|
47
47
|
UseTextToVideoFormProps, UseTextToVideoFormReturn, ExecuteTextToVideoOptions,
|
|
48
48
|
} from "../domains/text-to-video";
|
|
49
49
|
export {
|
|
50
|
-
INITIAL_FORM_STATE,
|
|
50
|
+
INITIAL_FORM_STATE,
|
|
51
51
|
executeTextToVideo, hasTextToVideoSupport,
|
|
52
52
|
useTextToVideoFeature, useTextToVideoForm,
|
|
53
53
|
GenerationTabs, FrameSelector, OptionsPanel, HeroSection, HintCarousel,
|
|
@@ -10,9 +10,9 @@ import type {
|
|
|
10
10
|
PollingConfig,
|
|
11
11
|
} from "../../domain/entities";
|
|
12
12
|
import { classifyError } from "../utils/error-classification";
|
|
13
|
-
import { pollJob } from "../../domains/background/infrastructure/services/job-poller
|
|
13
|
+
import { pollJob } from "../../domains/background/infrastructure/services/job-poller-index";
|
|
14
14
|
import { ProviderValidator } from "./provider-validator";
|
|
15
|
-
import { calculateDurationMs } from "../../shared/utils/calculations
|
|
15
|
+
import { calculateDurationMs } from "../../shared/utils/calculations";
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
export interface OrchestratorConfig {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Couple Input Utilities - Context Management
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Prepends optional context (e.g. appearance analysis) to a base prompt.
|
|
7
|
+
*/
|
|
8
|
+
export function prependContext(
|
|
9
|
+
basePrompt: string,
|
|
10
|
+
context: string | undefined | null,
|
|
11
|
+
): string {
|
|
12
|
+
return context ? `${context}\n\n${basePrompt}` : basePrompt;
|
|
13
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Couple Input Utilities - Index
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export { resolveCoupleInput } from "./couple-input-resolver";
|
|
6
|
+
export { prependContext } from "./couple-input-context";
|
|
7
|
+
export { refinePromptForCouple } from "./couple-input-refiner";
|
|
8
|
+
export { createPhotorealisticPrompt } from "./couple-input-photorealistic";
|
|
9
|
+
export type { GenerationTargetLike } from "./couple-input-types";
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Couple Input Utilities - Photorealistic Prompt Enhancement
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface PhotorealisticPromptOptions {
|
|
6
|
+
readonly isCouple?: boolean;
|
|
7
|
+
readonly customInstructions?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Create a photorealistic prompt from refined input
|
|
12
|
+
* Adds photorealistic enhancements to the base prompt
|
|
13
|
+
*/
|
|
14
|
+
export function createPhotorealisticPrompt(
|
|
15
|
+
refinedPrompt: string,
|
|
16
|
+
options: PhotorealisticPromptOptions = {}
|
|
17
|
+
): string {
|
|
18
|
+
const { isCouple = false, customInstructions } = options;
|
|
19
|
+
|
|
20
|
+
// Photorealistic quality keywords
|
|
21
|
+
const photorealisticPrefix = "high quality, photorealistic, detailed, 8k, professional photography";
|
|
22
|
+
|
|
23
|
+
// Build the final prompt
|
|
24
|
+
let finalPrompt = refinedPrompt;
|
|
25
|
+
|
|
26
|
+
// Add custom instructions if provided
|
|
27
|
+
if (customInstructions) {
|
|
28
|
+
finalPrompt = `${customInstructions}. ${finalPrompt}`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Add photorealistic prefix
|
|
32
|
+
finalPrompt = `${photorealisticPrefix}, ${finalPrompt}`;
|
|
33
|
+
|
|
34
|
+
// Add couple-specific enhancements
|
|
35
|
+
if (isCouple) {
|
|
36
|
+
finalPrompt = `${finalPrompt}, romantic couple, natural lighting, candid moment`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return finalPrompt;
|
|
40
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Couple Input Utilities - Prompt Refinement
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Refines a prompt for couple or solo mode by adjusting plurals and keywords.
|
|
7
|
+
* Primarily used to fix "baked" prompts that were generated with a specific mode in mind.
|
|
8
|
+
*/
|
|
9
|
+
export function refinePromptForCouple(prompt: string, isCouple: boolean): string {
|
|
10
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
11
|
+
console.log("[CoupleUtil] ===== REFINE PROMPT START =====");
|
|
12
|
+
console.log("[CoupleUtil] Is couple mode:", isCouple);
|
|
13
|
+
console.log("[CoupleUtil] Original prompt length:", prompt.length);
|
|
14
|
+
console.log("[CoupleUtil] Original prompt preview:", prompt.substring(0, 200) + "...");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (isCouple) {
|
|
18
|
+
// Ensure couple context is present
|
|
19
|
+
let refined = prompt
|
|
20
|
+
.replace(/\bthe person must be\b/gi, "both people must be")
|
|
21
|
+
.replace(/\bthe person is\b/gi, "both people are")
|
|
22
|
+
.replace(/\bkeep every facial feature\b/gi, "keep every facial feature for both people")
|
|
23
|
+
.replace(/\bthe person\b/gi, "both people")
|
|
24
|
+
.replace(/\bfacial feature\b/gi, "facial features")
|
|
25
|
+
.replace(/\bidentical\b/gi, "identical for both individuals")
|
|
26
|
+
.replace(/\binstantly recognizable\b/gi, "instantly recognizable as themselves");
|
|
27
|
+
|
|
28
|
+
// Special mapping for common couple scenarios: map "dress/gown" to person 1 and "suit/tuxedo" to person 2
|
|
29
|
+
// this helps the AI map reference images correctly to the scene roles
|
|
30
|
+
if (/\b(dress|gown)\b/i.test(refined) && /\b(suit|tuxedo|linen trousers)\b/i.test(refined)) {
|
|
31
|
+
refined = refined
|
|
32
|
+
.replace(/\b(dress|gown)\b/gi, "$1 (worn by Person 1)")
|
|
33
|
+
.replace(/\b(suit|tuxedo|linen trousers)\b/gi, "$1 (worn by Person 2)");
|
|
34
|
+
|
|
35
|
+
// Also add explicit mapping to the top if not already there
|
|
36
|
+
if (!refined.includes("DIRECTIVE: MAP PHOTO 1 TO PERSON 1")) {
|
|
37
|
+
refined = `DIRECTIVE: MAP PHOTO 1 TO PERSON 1, MAP PHOTO 2 TO PERSON 2\n\n${refined}`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
41
|
+
console.log("[CoupleUtil] ✅ Clothing mapping applied!");
|
|
42
|
+
console.log("[CoupleUtil] ✅ Directive added for photo mapping");
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// If it doesn't already have couple-hints, add them at the start
|
|
47
|
+
if (!/\b(couple|both|matching|dual|two people)\b/i.test(refined) && !refined.includes("DIRECTIVE:")) {
|
|
48
|
+
refined = `A photo of a couple, ${refined}`;
|
|
49
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
50
|
+
console.log("[CoupleUtil] ✅ Added 'A photo of a couple' prefix");
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
55
|
+
console.log("[CoupleUtil] Refined prompt length:", refined.length);
|
|
56
|
+
console.log("[CoupleUtil] Refined prompt preview:", refined.substring(0, 300) + "...");
|
|
57
|
+
console.log("[CoupleUtil] ===== REFINE PROMPT END =====");
|
|
58
|
+
}
|
|
59
|
+
return refined;
|
|
60
|
+
} else {
|
|
61
|
+
// Solo mode: AGGRESSIVELY remove plural references to prevent "ghost" people
|
|
62
|
+
const soloRefined = prompt
|
|
63
|
+
// Instead of removing the clothing descriptions, just remove the gender labels
|
|
64
|
+
// so the AI can apply the relevant clothing to the single person it sees.
|
|
65
|
+
.replace(/\sfor women\b/gi, "")
|
|
66
|
+
.replace(/\sfor men\b/gi, "")
|
|
67
|
+
// Remove collective adjectives
|
|
68
|
+
.replace(/\bmatching\b/gi, "")
|
|
69
|
+
.replace(/\bcoordinated\b/gi, "")
|
|
70
|
+
.replace(/\bcomplementary\b/gi, "")
|
|
71
|
+
.replace(/\bcoordinating\b/gi, "")
|
|
72
|
+
.replace(/\bcouple\b/gi, "person")
|
|
73
|
+
.replace(/\bduo\b/gi, "person")
|
|
74
|
+
.replace(/\bpair\b/gi, "person")
|
|
75
|
+
.replace(/\bdoubles\b/gi, "")
|
|
76
|
+
.replace(/\bboth\b/gi, "the person")
|
|
77
|
+
.replace(/\bthey are\b/gi, "the person is")
|
|
78
|
+
.replace(/\btheir\b/gi, "the person's")
|
|
79
|
+
// Force singular clothing
|
|
80
|
+
.replace(/\bjackets\b/gi, "jacket")
|
|
81
|
+
.replace(/\boutfits\b/gi, "outfit")
|
|
82
|
+
.replace(/\bsuits\b/gi, "suit")
|
|
83
|
+
.replace(/\btuxedos\b/gi, "tuxedo")
|
|
84
|
+
.replace(/\bgowns\b/gi, "gown")
|
|
85
|
+
.replace(/\bdresses\b/gi, "dress")
|
|
86
|
+
.replace(/\bsweaters\b/gi, "sweater")
|
|
87
|
+
.replace(/\bhoodies\b/gi, "hoodie")
|
|
88
|
+
.replace(/\bcoats\b/gi, "coat")
|
|
89
|
+
.replace(/\bshirts\b/gi, "shirt")
|
|
90
|
+
.replace(/\bhats\b/gi, "hat")
|
|
91
|
+
.replace(/\baccessories\b/gi, "accessory")
|
|
92
|
+
.replace(/\s+/g, ' ').trim();
|
|
93
|
+
|
|
94
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
95
|
+
console.log("[CoupleUtil] ✅ Solo mode - removed all plural references");
|
|
96
|
+
console.log("[CoupleUtil] Solo refined prompt length:", soloRefined.length);
|
|
97
|
+
console.log("[CoupleUtil] ===== REFINE PROMPT END =====");
|
|
98
|
+
}
|
|
99
|
+
return soloRefined;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Couple Input Utilities - Input Resolution
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { GenerationTargetLike } from "./couple-input-types";
|
|
6
|
+
|
|
7
|
+
interface CoupleInputResult {
|
|
8
|
+
readonly target: GenerationTargetLike;
|
|
9
|
+
readonly imageUrls: string[];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Resolves generation target and image URLs based on couple/single mode.
|
|
14
|
+
* Eliminates non-null assertions by narrowing partner2PhotoUri internally.
|
|
15
|
+
*/
|
|
16
|
+
export function resolveCoupleInput(
|
|
17
|
+
partner1PhotoUri: string,
|
|
18
|
+
partner2PhotoUri: string | null,
|
|
19
|
+
isCoupleMode: boolean,
|
|
20
|
+
singleTarget: GenerationTargetLike,
|
|
21
|
+
coupleTarget: GenerationTargetLike,
|
|
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
|
+
|
|
37
|
+
if (isCoupleMode && partner2PhotoUri) {
|
|
38
|
+
const result = {
|
|
39
|
+
target: coupleTarget,
|
|
40
|
+
imageUrls: [partner1PhotoUri, partner2PhotoUri],
|
|
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;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const result = {
|
|
57
|
+
target: singleTarget,
|
|
58
|
+
imageUrls: [partner1PhotoUri],
|
|
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;
|
|
71
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Couple Input Utilities - Type Definitions
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/** Target for generation: which model on which provider */
|
|
6
|
+
export interface GenerationTargetLike {
|
|
7
|
+
readonly model: string;
|
|
8
|
+
readonly providerId: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// CoupleInputResult is now defined inline where needed
|
|
@@ -1,180 +1,7 @@
|
|
|
1
|
-
/** Target for generation: which model on which provider */
|
|
2
|
-
export interface GenerationTargetLike {
|
|
3
|
-
readonly model: string;
|
|
4
|
-
readonly providerId: string;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
interface CoupleInputResult {
|
|
8
|
-
readonly target: GenerationTargetLike;
|
|
9
|
-
readonly imageUrls: string[];
|
|
10
|
-
}
|
|
11
|
-
|
|
12
1
|
/**
|
|
13
|
-
*
|
|
14
|
-
* Eliminates non-null assertions by narrowing partner2PhotoUri internally.
|
|
2
|
+
* Couple Input Utilities
|
|
15
3
|
*/
|
|
16
|
-
export function resolveCoupleInput(
|
|
17
|
-
partner1PhotoUri: string,
|
|
18
|
-
partner2PhotoUri: string | null,
|
|
19
|
-
isCoupleMode: boolean,
|
|
20
|
-
singleTarget: GenerationTargetLike,
|
|
21
|
-
coupleTarget: GenerationTargetLike,
|
|
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
|
-
|
|
37
|
-
if (isCoupleMode && partner2PhotoUri) {
|
|
38
|
-
const result = {
|
|
39
|
-
target: coupleTarget,
|
|
40
|
-
imageUrls: [partner1PhotoUri, partner2PhotoUri],
|
|
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;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const result = {
|
|
57
|
-
target: singleTarget,
|
|
58
|
-
imageUrls: [partner1PhotoUri],
|
|
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;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Prepends optional context (e.g. appearance analysis) to a base prompt.
|
|
75
|
-
*/
|
|
76
|
-
export function prependContext(
|
|
77
|
-
basePrompt: string,
|
|
78
|
-
context: string | undefined | null,
|
|
79
|
-
): string {
|
|
80
|
-
return context ? `${context}\n\n${basePrompt}` : basePrompt;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Refines a prompt for couple or solo mode by adjusting plurals and keywords.
|
|
85
|
-
* Primarily used to fix "baked" prompts that were generated with a specific mode in mind.
|
|
86
|
-
*/
|
|
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
|
-
|
|
95
|
-
if (isCouple) {
|
|
96
|
-
// Ensure couple context is present
|
|
97
|
-
let refined = prompt
|
|
98
|
-
.replace(/\bthe person must be\b/gi, "both people must be")
|
|
99
|
-
.replace(/\bthe person is\b/gi, "both people are")
|
|
100
|
-
.replace(/\bkeep every facial feature\b/gi, "keep every facial feature for both people")
|
|
101
|
-
.replace(/\bthe person\b/gi, "both people")
|
|
102
|
-
.replace(/\bfacial feature\b/gi, "facial features")
|
|
103
|
-
.replace(/\bidentical\b/gi, "identical for both individuals")
|
|
104
|
-
.replace(/\binstantly recognizable\b/gi, "instantly recognizable as themselves");
|
|
105
|
-
|
|
106
|
-
// Special mapping for common couple scenarios: map "dress/gown" to person 1 and "suit/tuxedo" to person 2
|
|
107
|
-
// this helps the AI map reference images correctly to the scene roles
|
|
108
|
-
if (/\b(dress|gown)\b/i.test(refined) && /\b(suit|tuxedo|linen trousers)\b/i.test(refined)) {
|
|
109
|
-
refined = refined
|
|
110
|
-
.replace(/\b(dress|gown)\b/gi, "$1 (worn by Person 1)")
|
|
111
|
-
.replace(/\b(suit|tuxedo|linen trousers)\b/gi, "$1 (worn by Person 2)");
|
|
112
|
-
|
|
113
|
-
// Also add explicit mapping to the top if not already there
|
|
114
|
-
if (!refined.includes("DIRECTIVE: MAP PHOTO 1 TO PERSON 1")) {
|
|
115
|
-
refined = `DIRECTIVE: MAP PHOTO 1 TO PERSON 1, MAP PHOTO 2 TO PERSON 2\n\n${refined}`;
|
|
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
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// If it doesn't already have couple-hints, add them at the start
|
|
125
|
-
if (!/\b(couple|both|matching|dual|two people)\b/i.test(refined) && !refined.includes("DIRECTIVE:")) {
|
|
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 =====");
|
|
136
|
-
}
|
|
137
|
-
return refined;
|
|
138
|
-
} else {
|
|
139
|
-
// Solo mode: AGGRESSIVELY remove plural references to prevent "ghost" people
|
|
140
|
-
const soloRefined = prompt
|
|
141
|
-
// Instead of removing the clothing descriptions, just remove the gender labels
|
|
142
|
-
// so the AI can apply the relevant clothing to the single person it sees.
|
|
143
|
-
.replace(/\sfor women\b/gi, "")
|
|
144
|
-
.replace(/\sfor men\b/gi, "")
|
|
145
|
-
// Remove collective adjectives
|
|
146
|
-
.replace(/\bmatching\b/gi, "")
|
|
147
|
-
.replace(/\bcoordinated\b/gi, "")
|
|
148
|
-
.replace(/\bcomplementary\b/gi, "")
|
|
149
|
-
.replace(/\bcoordinating\b/gi, "")
|
|
150
|
-
.replace(/\bcouple\b/gi, "person")
|
|
151
|
-
.replace(/\bduo\b/gi, "person")
|
|
152
|
-
.replace(/\bpair\b/gi, "person")
|
|
153
|
-
.replace(/\bdoubles\b/gi, "")
|
|
154
|
-
.replace(/\bboth\b/gi, "the person")
|
|
155
|
-
.replace(/\bthey are\b/gi, "the person is")
|
|
156
|
-
.replace(/\btheir\b/gi, "the person's")
|
|
157
|
-
// Force singular clothing
|
|
158
|
-
.replace(/\bjackets\b/gi, "jacket")
|
|
159
|
-
.replace(/\boutfits\b/gi, "outfit")
|
|
160
|
-
.replace(/\bsuits\b/gi, "suit")
|
|
161
|
-
.replace(/\btuxedos\b/gi, "tuxedo")
|
|
162
|
-
.replace(/\bgowns\b/gi, "gown")
|
|
163
|
-
.replace(/\bdresses\b/gi, "dress")
|
|
164
|
-
.replace(/\bsweaters\b/gi, "sweater")
|
|
165
|
-
.replace(/\bhoodies\b/gi, "hoodie")
|
|
166
|
-
.replace(/\bcoats\b/gi, "coat")
|
|
167
|
-
.replace(/\bshirts\b/gi, "shirt")
|
|
168
|
-
.replace(/\bhats\b/gi, "hat")
|
|
169
|
-
.replace(/\baccessories\b/gi, "accessory")
|
|
170
|
-
.replace(/\s+/g, ' ').trim();
|
|
171
4
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
console.log("[CoupleUtil] Solo refined prompt length:", soloRefined.length);
|
|
175
|
-
console.log("[CoupleUtil] ===== REFINE PROMPT END =====");
|
|
176
|
-
}
|
|
177
|
-
return soloRefined;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
5
|
+
export { resolveCoupleInput, prependContext, refinePromptForCouple, createPhotorealisticPrompt } from "./couple-input-index";
|
|
6
|
+
export type { GenerationTargetLike } from "./couple-input-index";
|
|
180
7
|
|
|
@@ -3,33 +3,10 @@
|
|
|
3
3
|
* Core validation functions for strings, numbers, URLs, emails, and base64
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
* Validation result type
|
|
8
|
-
*/
|
|
9
|
-
export interface ValidationResult {
|
|
10
|
-
readonly isValid: boolean;
|
|
11
|
-
readonly errors: readonly string[];
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* String validation options
|
|
16
|
-
*/
|
|
17
|
-
export interface StringValidationOptions {
|
|
18
|
-
readonly minLength?: number;
|
|
19
|
-
readonly maxLength?: number;
|
|
20
|
-
readonly pattern?: RegExp;
|
|
21
|
-
readonly allowedCharacters?: RegExp;
|
|
22
|
-
readonly trim?: boolean;
|
|
23
|
-
}
|
|
6
|
+
import type { ValidationResult, StringValidationOptions, NumericValidationOptions } from "./base-validator.types";
|
|
24
7
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
*/
|
|
28
|
-
export interface NumericValidationOptions {
|
|
29
|
-
readonly min?: number;
|
|
30
|
-
readonly max?: number;
|
|
31
|
-
readonly integer?: boolean;
|
|
32
|
-
}
|
|
8
|
+
// Re-export types for convenience
|
|
9
|
+
export type { ValidationResult, StringValidationOptions, NumericValidationOptions };
|
|
33
10
|
|
|
34
11
|
/**
|
|
35
12
|
* Validates a string input against provided rules
|