@umituz/react-native-ai-generation-content 1.78.0 → 1.79.0
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/index.ts +3 -0
- package/src/domain/interfaces/video-model-config.types.ts +52 -0
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation.executor.ts +39 -67
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation.strategy.ts +3 -5
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation.types.ts +3 -0
- package/src/domains/generation/wizard/infrastructure/strategies/wizard-strategy.factory.ts +5 -2
- package/src/domains/generation/wizard/presentation/components/GenericWizardFlow.tsx +5 -0
- package/src/domains/generation/wizard/presentation/components/WizardFlowContent.tsx +5 -0
- package/src/domains/generation/wizard/presentation/hooks/useWizardGeneration.ts +2 -1
- package/src/domains/generation/wizard/presentation/hooks/wizard-generation.types.ts +3 -0
- package/src/domains/generation/wizard/utilities/build-wizard-config.ts +76 -0
- package/src/index.ts +6 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-ai-generation-content",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.79.0",
|
|
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",
|
|
@@ -13,3 +13,6 @@ export type { IAIProviderJobManager } from "../../domains/background/domain/inte
|
|
|
13
13
|
export type { IAIProviderExecutor } from "./provider-executor.interface";
|
|
14
14
|
export type { IAIProviderImageFeatures } from "./provider-image-features.interface";
|
|
15
15
|
export type { IAIProviderVideoFeatures } from "./provider-video-features.interface";
|
|
16
|
+
|
|
17
|
+
// Video Model Configuration
|
|
18
|
+
export type { VideoModelConfig, ModelCapabilityOption } from "./video-model-config.types";
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VideoModelConfig - Model-Agnostic Configuration Interface
|
|
3
|
+
* Encapsulates ALL model-specific behavior in a single config object.
|
|
4
|
+
* Adding a new model = creating one config file. No other changes needed.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export interface ModelCapabilityOption {
|
|
8
|
+
readonly id: string;
|
|
9
|
+
readonly label: string;
|
|
10
|
+
readonly value: string | number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface VideoModelConfig {
|
|
14
|
+
/** Fal.ai model endpoint (e.g., "fal-ai/minimax/hailuo-02/standard/image-to-video") */
|
|
15
|
+
readonly modelId: string;
|
|
16
|
+
|
|
17
|
+
/** Human-readable display name */
|
|
18
|
+
readonly displayName: string;
|
|
19
|
+
|
|
20
|
+
/** What this model supports (drives wizard UI) */
|
|
21
|
+
readonly capabilities: {
|
|
22
|
+
readonly resolutions: ReadonlyArray<ModelCapabilityOption>;
|
|
23
|
+
readonly durations: ReadonlyArray<ModelCapabilityOption>;
|
|
24
|
+
readonly aspectRatios?: ReadonlyArray<ModelCapabilityOption>;
|
|
25
|
+
readonly defaults: {
|
|
26
|
+
readonly resolution: string;
|
|
27
|
+
readonly duration: number;
|
|
28
|
+
readonly aspectRatio?: string;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Maps generic WizardVideoInput to model-specific API parameters.
|
|
34
|
+
* This is the core adapter function - eliminates all model-specific if/else checks.
|
|
35
|
+
*/
|
|
36
|
+
readonly buildInput: (input: {
|
|
37
|
+
readonly prompt: string;
|
|
38
|
+
readonly sourceImageBase64?: string;
|
|
39
|
+
readonly targetImageBase64?: string;
|
|
40
|
+
readonly duration?: number;
|
|
41
|
+
readonly aspectRatio?: string;
|
|
42
|
+
readonly resolution?: string;
|
|
43
|
+
}) => Record<string, unknown>;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Pricing data for credit calculation.
|
|
47
|
+
* Keys are resolution IDs matching capabilities.resolutions[].id
|
|
48
|
+
*/
|
|
49
|
+
readonly pricing: {
|
|
50
|
+
readonly costPerSecond: Record<string, number>;
|
|
51
|
+
};
|
|
52
|
+
}
|
package/src/domains/generation/wizard/infrastructure/strategies/video-generation.executor.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Video Generation Executor
|
|
3
|
-
* Handles the actual video generation execution
|
|
4
|
-
*
|
|
3
|
+
* Handles the actual video generation execution.
|
|
4
|
+
* Model-agnostic: uses VideoModelConfig.buildInput() for model-specific parameters.
|
|
5
|
+
* Fallback: generic input builder when no modelConfig is provided.
|
|
5
6
|
*/
|
|
6
7
|
|
|
7
8
|
import type { WizardVideoInput } from "./video-generation.types";
|
|
9
|
+
import type { VideoModelConfig } from "../../../../../domain/interfaces/video-model-config.types";
|
|
8
10
|
import { GENERATION_TIMEOUT_MS, BASE64_IMAGE_PREFIX } from "./wizard-strategy.constants";
|
|
9
11
|
import { createGenerationError, GenerationErrorType } from "../../../../../infrastructure/utils/error-factory";
|
|
10
12
|
|
|
@@ -29,14 +31,38 @@ function formatBase64(base64: string | undefined): string | undefined {
|
|
|
29
31
|
return base64.startsWith("data:") ? base64 : `${BASE64_IMAGE_PREFIX}${base64}`;
|
|
30
32
|
}
|
|
31
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Generic input builder - used when no modelConfig is provided.
|
|
36
|
+
* Sends standard parameters without model-specific logic.
|
|
37
|
+
*/
|
|
38
|
+
function buildGenericInput(input: WizardVideoInput): Record<string, unknown> {
|
|
39
|
+
const modelInput: Record<string, unknown> = { prompt: input.prompt };
|
|
40
|
+
const sourceImage = formatBase64(input.sourceImageBase64);
|
|
41
|
+
|
|
42
|
+
if (sourceImage && sourceImage.length > 0) {
|
|
43
|
+
modelInput.image_url = sourceImage;
|
|
44
|
+
}
|
|
45
|
+
if (input.duration) {
|
|
46
|
+
modelInput.duration = input.duration;
|
|
47
|
+
}
|
|
48
|
+
if (input.aspectRatio) {
|
|
49
|
+
modelInput.aspect_ratio = input.aspectRatio;
|
|
50
|
+
}
|
|
51
|
+
if (input.resolution) {
|
|
52
|
+
modelInput.resolution = input.resolution;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return modelInput;
|
|
56
|
+
}
|
|
57
|
+
|
|
32
58
|
/**
|
|
33
59
|
* Execute video generation using direct provider call
|
|
34
|
-
* For text-to-video and image-to-video generation models (NOT features)
|
|
35
60
|
*/
|
|
36
61
|
export async function executeVideoGeneration(
|
|
37
62
|
input: WizardVideoInput,
|
|
38
63
|
model: string,
|
|
39
64
|
onProgress?: (status: string) => void,
|
|
65
|
+
modelConfig?: VideoModelConfig,
|
|
40
66
|
): Promise<ExecutionResult> {
|
|
41
67
|
const { providerRegistry } = await import("../../../../../infrastructure/services/provider-registry.service");
|
|
42
68
|
|
|
@@ -50,47 +76,19 @@ export async function executeVideoGeneration(
|
|
|
50
76
|
}
|
|
51
77
|
|
|
52
78
|
try {
|
|
53
|
-
const sourceImage = formatBase64(input.sourceImageBase64);
|
|
54
|
-
|
|
55
79
|
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
56
80
|
console.log("[VideoExecutor] Generation starting", {
|
|
57
81
|
model,
|
|
82
|
+
hasModelConfig: !!modelConfig,
|
|
58
83
|
duration: input.duration,
|
|
59
|
-
aspectRatio: input.aspectRatio,
|
|
60
84
|
resolution: input.resolution,
|
|
61
85
|
});
|
|
62
86
|
}
|
|
63
87
|
|
|
64
|
-
//
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
prompt: input.prompt,
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
if (sourceImage && sourceImage.length > 0) {
|
|
72
|
-
modelInput.image_url = sourceImage;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (isSubjectReference) {
|
|
76
|
-
modelInput.prompt_optimizer = true;
|
|
77
|
-
if (input.duration) {
|
|
78
|
-
modelInput.duration = String(input.duration);
|
|
79
|
-
}
|
|
80
|
-
if (input.resolution) {
|
|
81
|
-
modelInput.resolution = input.resolution;
|
|
82
|
-
}
|
|
83
|
-
} else {
|
|
84
|
-
if (input.duration) {
|
|
85
|
-
modelInput.duration = input.duration;
|
|
86
|
-
}
|
|
87
|
-
if (input.aspectRatio) {
|
|
88
|
-
modelInput.aspect_ratio = input.aspectRatio;
|
|
89
|
-
}
|
|
90
|
-
if (input.resolution) {
|
|
91
|
-
modelInput.resolution = input.resolution;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
88
|
+
// Use modelConfig.buildInput() if available, otherwise generic fallback
|
|
89
|
+
const modelInput = modelConfig
|
|
90
|
+
? modelConfig.buildInput(input)
|
|
91
|
+
: buildGenericInput(input);
|
|
94
92
|
|
|
95
93
|
let lastStatus = "";
|
|
96
94
|
const result = await provider.subscribe(model, modelInput, {
|
|
@@ -126,6 +124,7 @@ export async function executeVideoGeneration(
|
|
|
126
124
|
export async function submitVideoGenerationToQueue(
|
|
127
125
|
input: WizardVideoInput,
|
|
128
126
|
model: string,
|
|
127
|
+
modelConfig?: VideoModelConfig,
|
|
129
128
|
): Promise<SubmissionResult> {
|
|
130
129
|
const { providerRegistry } = await import("../../../../../infrastructure/services/provider-registry.service");
|
|
131
130
|
|
|
@@ -139,37 +138,10 @@ export async function submitVideoGenerationToQueue(
|
|
|
139
138
|
}
|
|
140
139
|
|
|
141
140
|
try {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const modelInput: Record<string, unknown> = {
|
|
147
|
-
prompt: input.prompt,
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
if (sourceImage && sourceImage.length > 0) {
|
|
151
|
-
modelInput.image_url = sourceImage;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
if (isSubjectReference) {
|
|
155
|
-
modelInput.prompt_optimizer = true;
|
|
156
|
-
if (input.duration) {
|
|
157
|
-
modelInput.duration = String(input.duration);
|
|
158
|
-
}
|
|
159
|
-
if (input.resolution) {
|
|
160
|
-
modelInput.resolution = input.resolution;
|
|
161
|
-
}
|
|
162
|
-
} else {
|
|
163
|
-
if (input.duration) {
|
|
164
|
-
modelInput.duration = input.duration;
|
|
165
|
-
}
|
|
166
|
-
if (input.aspectRatio) {
|
|
167
|
-
modelInput.aspect_ratio = input.aspectRatio;
|
|
168
|
-
}
|
|
169
|
-
if (input.resolution) {
|
|
170
|
-
modelInput.resolution = input.resolution;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
141
|
+
// Use modelConfig.buildInput() if available, otherwise generic fallback
|
|
142
|
+
const modelInput = modelConfig
|
|
143
|
+
? modelConfig.buildInput(input)
|
|
144
|
+
: buildGenericInput(input);
|
|
173
145
|
|
|
174
146
|
const submission = await provider.submitJob(model, modelInput);
|
|
175
147
|
|
package/src/domains/generation/wizard/infrastructure/strategies/video-generation.strategy.ts
CHANGED
|
@@ -67,7 +67,7 @@ export async function buildVideoInput(
|
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
export function createVideoStrategy(options: CreateVideoStrategyOptions): WizardStrategy {
|
|
70
|
-
const { scenario, creditCost } = options;
|
|
70
|
+
const { scenario, modelConfig, creditCost } = options;
|
|
71
71
|
|
|
72
72
|
// Validate model early - fail fast
|
|
73
73
|
if (!scenario.model) {
|
|
@@ -78,10 +78,9 @@ export function createVideoStrategy(options: CreateVideoStrategyOptions): Wizard
|
|
|
78
78
|
|
|
79
79
|
return {
|
|
80
80
|
execute: async (input: unknown) => {
|
|
81
|
-
// Runtime validation with descriptive errors
|
|
82
81
|
const videoInput = validateWizardVideoInput(input);
|
|
83
82
|
|
|
84
|
-
const result = await executeVideoGeneration(videoInput, model);
|
|
83
|
+
const result = await executeVideoGeneration(videoInput, model, undefined, modelConfig);
|
|
85
84
|
|
|
86
85
|
if (!result.success || !result.videoUrl) {
|
|
87
86
|
throw new Error(result.error || "Video generation failed");
|
|
@@ -91,10 +90,9 @@ export function createVideoStrategy(options: CreateVideoStrategyOptions): Wizard
|
|
|
91
90
|
},
|
|
92
91
|
|
|
93
92
|
submitToQueue: async (input: unknown) => {
|
|
94
|
-
// Runtime validation with descriptive errors
|
|
95
93
|
const videoInput = validateWizardVideoInput(input);
|
|
96
94
|
|
|
97
|
-
const result = await submitVideoGenerationToQueue(videoInput, model);
|
|
95
|
+
const result = await submitVideoGenerationToQueue(videoInput, model, modelConfig);
|
|
98
96
|
|
|
99
97
|
return {
|
|
100
98
|
success: result.success,
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import type { WizardScenarioData } from "../../presentation/hooks/useWizardGeneration";
|
|
7
7
|
import type { ScenarioInputType } from "../../../../scenarios/domain/Scenario";
|
|
8
|
+
import type { VideoModelConfig } from "../../../../../domain/interfaces/video-model-config.types";
|
|
8
9
|
|
|
9
10
|
export interface WizardVideoInput {
|
|
10
11
|
/** Source image (optional for text-to-video) */
|
|
@@ -26,6 +27,8 @@ export interface WizardVideoResult {
|
|
|
26
27
|
|
|
27
28
|
export interface CreateVideoStrategyOptions {
|
|
28
29
|
readonly scenario: WizardScenarioData;
|
|
30
|
+
/** Model configuration - encapsulates all model-specific behavior */
|
|
31
|
+
readonly modelConfig?: VideoModelConfig;
|
|
29
32
|
readonly collectionName?: string;
|
|
30
33
|
/** Credit cost for this generation - REQUIRED, determined by the app */
|
|
31
34
|
readonly creditCost: number;
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import type { WizardScenarioData } from "../../presentation/hooks/useWizardGeneration";
|
|
8
8
|
import type { WizardStrategy } from "./wizard-strategy.types";
|
|
9
|
+
import type { VideoModelConfig } from "../../../../../domain/interfaces/video-model-config.types";
|
|
9
10
|
import { createImageStrategy, buildImageInput } from "./image-generation.strategy";
|
|
10
11
|
import { createVideoStrategy, buildVideoInput } from "./video-generation.strategy";
|
|
11
12
|
|
|
@@ -17,6 +18,8 @@ export type { WizardStrategy } from "./wizard-strategy.types";
|
|
|
17
18
|
|
|
18
19
|
export interface CreateWizardStrategyOptions {
|
|
19
20
|
readonly scenario: WizardScenarioData;
|
|
21
|
+
/** Model configuration - encapsulates all model-specific behavior */
|
|
22
|
+
readonly modelConfig?: VideoModelConfig;
|
|
20
23
|
readonly collectionName?: string;
|
|
21
24
|
/** Credit cost for this generation - REQUIRED, determined by the app */
|
|
22
25
|
readonly creditCost: number;
|
|
@@ -27,14 +30,14 @@ export interface CreateWizardStrategyOptions {
|
|
|
27
30
|
// ============================================================================
|
|
28
31
|
|
|
29
32
|
export function createWizardStrategy(options: CreateWizardStrategyOptions): WizardStrategy {
|
|
30
|
-
const { scenario, collectionName, creditCost } = options;
|
|
33
|
+
const { scenario, modelConfig, collectionName, creditCost } = options;
|
|
31
34
|
|
|
32
35
|
if (scenario.outputType === "image") {
|
|
33
36
|
return createImageStrategy({ scenario, collectionName, creditCost });
|
|
34
37
|
}
|
|
35
38
|
|
|
36
39
|
// Default to video strategy for video outputType or undefined
|
|
37
|
-
return createVideoStrategy({ scenario, collectionName, creditCost });
|
|
40
|
+
return createVideoStrategy({ scenario, modelConfig, collectionName, creditCost });
|
|
38
41
|
}
|
|
39
42
|
|
|
40
43
|
// ============================================================================
|
|
@@ -11,6 +11,7 @@ import type { WizardScenarioData } from "../hooks/useWizardGeneration";
|
|
|
11
11
|
import type { AlertMessages } from "../../../../../presentation/hooks/generation/types";
|
|
12
12
|
import type { GenerationErrorInfo } from "./WizardFlow.types";
|
|
13
13
|
import type { CreditCalculatorFn } from "../../domain/types/credit-calculation.types";
|
|
14
|
+
import type { VideoModelConfig } from "../../../../../domain/interfaces/video-model-config.types";
|
|
14
15
|
import { validateScenario } from "../utilities/validateScenario";
|
|
15
16
|
import { WizardFlowContent } from "./WizardFlowContent";
|
|
16
17
|
import {
|
|
@@ -24,6 +25,8 @@ export interface GenericWizardFlowProps {
|
|
|
24
25
|
readonly featureConfig: WizardFeatureConfig;
|
|
25
26
|
readonly scenario?: WizardScenarioData;
|
|
26
27
|
readonly scenarioId?: string;
|
|
28
|
+
/** Model configuration - encapsulates all model-specific behavior */
|
|
29
|
+
readonly modelConfig?: VideoModelConfig;
|
|
27
30
|
readonly userId?: string;
|
|
28
31
|
readonly alertMessages: AlertMessages;
|
|
29
32
|
/** Credit cost for this generation - REQUIRED, determined by the app */
|
|
@@ -54,6 +57,7 @@ export const GenericWizardFlow: React.FC<GenericWizardFlowProps> = (props) => {
|
|
|
54
57
|
featureConfig,
|
|
55
58
|
scenario: scenarioProp,
|
|
56
59
|
scenarioId,
|
|
60
|
+
modelConfig,
|
|
57
61
|
userId,
|
|
58
62
|
alertMessages,
|
|
59
63
|
creditCost,
|
|
@@ -111,6 +115,7 @@ export const GenericWizardFlow: React.FC<GenericWizardFlowProps> = (props) => {
|
|
|
111
115
|
featureConfig={featureConfig}
|
|
112
116
|
scenario={scenario}
|
|
113
117
|
validatedScenario={validatedScenario}
|
|
118
|
+
modelConfig={modelConfig}
|
|
114
119
|
userId={userId}
|
|
115
120
|
alertMessages={alertMessages}
|
|
116
121
|
creditCost={creditCost}
|
|
@@ -20,11 +20,14 @@ import { extractDuration, extractResolution } from "../../infrastructure/utils/c
|
|
|
20
20
|
import { WizardStepRenderer } from "./WizardStepRenderer";
|
|
21
21
|
import { StarRatingPicker } from "../../../../result-preview/presentation/components/StarRatingPicker";
|
|
22
22
|
import type { CreditCalculatorFn } from "../../domain/types/credit-calculation.types";
|
|
23
|
+
import type { VideoModelConfig } from "../../../../../domain/interfaces/video-model-config.types";
|
|
23
24
|
|
|
24
25
|
export interface WizardFlowContentProps {
|
|
25
26
|
readonly featureConfig: WizardFeatureConfig;
|
|
26
27
|
readonly scenario?: WizardScenarioData;
|
|
27
28
|
readonly validatedScenario: WizardScenarioData;
|
|
29
|
+
/** Model configuration - encapsulates all model-specific behavior */
|
|
30
|
+
readonly modelConfig?: VideoModelConfig;
|
|
28
31
|
readonly userId?: string;
|
|
29
32
|
readonly alertMessages: AlertMessages;
|
|
30
33
|
/** Credit cost for this generation - REQUIRED, determined by the app */
|
|
@@ -54,6 +57,7 @@ export const WizardFlowContent: React.FC<WizardFlowContentProps> = (props) => {
|
|
|
54
57
|
featureConfig,
|
|
55
58
|
scenario,
|
|
56
59
|
validatedScenario,
|
|
60
|
+
modelConfig,
|
|
57
61
|
userId,
|
|
58
62
|
alertMessages,
|
|
59
63
|
creditCost, // Still needed for initial feature gate in parent
|
|
@@ -174,6 +178,7 @@ export const WizardFlowContent: React.FC<WizardFlowContentProps> = (props) => {
|
|
|
174
178
|
|
|
175
179
|
useWizardGeneration({
|
|
176
180
|
scenario: validatedScenario,
|
|
181
|
+
modelConfig,
|
|
177
182
|
wizardData: customData,
|
|
178
183
|
userId,
|
|
179
184
|
isGeneratingStep: currentStep?.type === StepType.GENERATING,
|
|
@@ -22,6 +22,7 @@ export type {
|
|
|
22
22
|
export const useWizardGeneration = (props: UseWizardGenerationProps): UseWizardGenerationReturn => {
|
|
23
23
|
const {
|
|
24
24
|
scenario,
|
|
25
|
+
modelConfig,
|
|
25
26
|
wizardData,
|
|
26
27
|
userId,
|
|
27
28
|
isGeneratingStep,
|
|
@@ -43,7 +44,7 @@ export const useWizardGeneration = (props: UseWizardGenerationProps): UseWizardG
|
|
|
43
44
|
}, []);
|
|
44
45
|
|
|
45
46
|
const persistence = useMemo(() => createCreationPersistence(), []);
|
|
46
|
-
const strategy = useMemo(() => createWizardStrategy({ scenario, creditCost }), [scenario, creditCost]);
|
|
47
|
+
const strategy = useMemo(() => createWizardStrategy({ scenario, modelConfig, creditCost }), [scenario, modelConfig, creditCost]);
|
|
47
48
|
const isVideoMode = scenario.outputType === "video" && !!strategy.submitToQueue;
|
|
48
49
|
|
|
49
50
|
const videoGeneration = useVideoQueueGeneration({
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import type { AlertMessages } from "../../../../../presentation/hooks/generation/types";
|
|
7
7
|
import type { ScenarioInputType, ScenarioPromptType } from "../../../../scenarios/domain/Scenario";
|
|
8
|
+
import type { VideoModelConfig } from "../../../../../domain/interfaces/video-model-config.types";
|
|
8
9
|
|
|
9
10
|
export type WizardOutputType = "image" | "video";
|
|
10
11
|
|
|
@@ -26,6 +27,8 @@ export interface WizardScenarioData {
|
|
|
26
27
|
|
|
27
28
|
export interface UseWizardGenerationProps {
|
|
28
29
|
readonly scenario: WizardScenarioData;
|
|
30
|
+
/** Model configuration - encapsulates all model-specific behavior */
|
|
31
|
+
readonly modelConfig?: VideoModelConfig;
|
|
29
32
|
readonly wizardData: Record<string, unknown>;
|
|
30
33
|
readonly userId?: string;
|
|
31
34
|
readonly isGeneratingStep: boolean;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build Wizard Config from VideoModelConfig
|
|
3
|
+
* Generates wizard step configuration from model capabilities.
|
|
4
|
+
* No hardcoded model-specific values - everything comes from config.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { VideoModelConfig } from "../../../../domain/interfaces/video-model-config.types";
|
|
8
|
+
import type { WizardFeatureConfig } from "../domain/entities/wizard-feature-config.types";
|
|
9
|
+
import type { WizardStepConfig } from "../domain/entities/wizard-step.types";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Builds a WizardFeatureConfig from a VideoModelConfig + input steps.
|
|
13
|
+
* Input steps (photo upload, text input) come from the caller.
|
|
14
|
+
* Resolution/duration/aspectRatio steps are auto-generated from model capabilities.
|
|
15
|
+
*/
|
|
16
|
+
export function buildWizardConfigFromModelConfig(
|
|
17
|
+
modelConfig: VideoModelConfig,
|
|
18
|
+
inputSteps: readonly WizardStepConfig[],
|
|
19
|
+
): WizardFeatureConfig {
|
|
20
|
+
const steps: WizardStepConfig[] = [...inputSteps];
|
|
21
|
+
|
|
22
|
+
if (modelConfig.capabilities.resolutions.length > 0) {
|
|
23
|
+
steps.push({
|
|
24
|
+
id: "resolution",
|
|
25
|
+
type: "selection" as const,
|
|
26
|
+
titleKey: "generation.resolution.title",
|
|
27
|
+
selectionType: "resolution" as const,
|
|
28
|
+
options: modelConfig.capabilities.resolutions.map((r) => ({
|
|
29
|
+
id: r.id,
|
|
30
|
+
label: r.label,
|
|
31
|
+
value: r.value,
|
|
32
|
+
})),
|
|
33
|
+
required: true,
|
|
34
|
+
defaultValue: modelConfig.capabilities.defaults.resolution,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (modelConfig.capabilities.aspectRatios && modelConfig.capabilities.aspectRatios.length > 0) {
|
|
39
|
+
steps.push({
|
|
40
|
+
id: "aspect_ratio",
|
|
41
|
+
type: "selection" as const,
|
|
42
|
+
titleKey: "generation.aspectRatio.title",
|
|
43
|
+
selectionType: "aspect_ratio" as const,
|
|
44
|
+
options: modelConfig.capabilities.aspectRatios.map((a) => ({
|
|
45
|
+
id: a.id,
|
|
46
|
+
label: a.label,
|
|
47
|
+
value: a.value,
|
|
48
|
+
})),
|
|
49
|
+
required: true,
|
|
50
|
+
defaultValue: modelConfig.capabilities.defaults.aspectRatio,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (modelConfig.capabilities.durations.length > 0) {
|
|
55
|
+
steps.push({
|
|
56
|
+
id: "duration",
|
|
57
|
+
type: "selection" as const,
|
|
58
|
+
titleKey: "generation.duration.title",
|
|
59
|
+
selectionType: "duration" as const,
|
|
60
|
+
layout: "list" as const,
|
|
61
|
+
options: modelConfig.capabilities.durations.map((d) => ({
|
|
62
|
+
id: d.id,
|
|
63
|
+
label: d.label,
|
|
64
|
+
value: d.value,
|
|
65
|
+
})),
|
|
66
|
+
required: true,
|
|
67
|
+
defaultValue: modelConfig.capabilities.defaults.duration,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
id: modelConfig.modelId,
|
|
73
|
+
name: modelConfig.displayName,
|
|
74
|
+
steps,
|
|
75
|
+
};
|
|
76
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -40,3 +40,9 @@ export {
|
|
|
40
40
|
getCreditConfig,
|
|
41
41
|
} from "./domains/generation/wizard";
|
|
42
42
|
export type { ValidationResult, CreditCalculatorFn } from "./domains/generation/wizard";
|
|
43
|
+
|
|
44
|
+
// Video Model Config (for app-side model definitions)
|
|
45
|
+
export type { VideoModelConfig, ModelCapabilityOption } from "./domain/interfaces";
|
|
46
|
+
|
|
47
|
+
// Wizard Config Builder (generates wizard steps from VideoModelConfig)
|
|
48
|
+
export { buildWizardConfigFromModelConfig } from "./domains/generation/wizard/utilities/build-wizard-config";
|