@umituz/react-native-ai-gemini-provider 1.16.0 → 2.0.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.
Files changed (30) hide show
  1. package/package.json +4 -9
  2. package/src/domain/constants/index.ts +1 -11
  3. package/src/domain/entities/index.ts +0 -1
  4. package/src/index.ts +2 -54
  5. package/src/infrastructure/job/JobManager.ts +11 -8
  6. package/src/infrastructure/services/gemini-provider.ts +31 -152
  7. package/src/infrastructure/services/generation-executor.ts +80 -141
  8. package/src/infrastructure/services/index.ts +1 -14
  9. package/src/infrastructure/services/job-processor.ts +42 -42
  10. package/src/infrastructure/services/provider-initializer.ts +19 -33
  11. package/src/infrastructure/utils/index.ts +1 -37
  12. package/src/infrastructure/utils/model-validation.util.ts +3 -29
  13. package/src/domain/constants/feature-models.constants.ts +0 -70
  14. package/src/domain/entities/video.types.ts +0 -149
  15. package/src/infrastructure/services/feature-input-builder.ts +0 -89
  16. package/src/infrastructure/services/feature-model-selector.ts +0 -77
  17. package/src/infrastructure/services/gemini-image-edit.service.ts +0 -134
  18. package/src/infrastructure/services/gemini-image-generation.service.ts +0 -137
  19. package/src/infrastructure/services/gemini-video-downloader.ts +0 -77
  20. package/src/infrastructure/services/gemini-video-error.ts +0 -21
  21. package/src/infrastructure/services/gemini-video-generation.service.ts +0 -103
  22. package/src/infrastructure/services/gemini-video-url-extractor.ts +0 -45
  23. package/src/infrastructure/services/veo-http-client.service.ts +0 -70
  24. package/src/infrastructure/services/veo-polling.service.ts +0 -119
  25. package/src/infrastructure/utils/base-input-builders.util.ts +0 -49
  26. package/src/infrastructure/utils/image-feature-builders.util.ts +0 -123
  27. package/src/infrastructure/utils/image-preparer.util.ts +0 -74
  28. package/src/infrastructure/utils/input-builder.types.ts +0 -44
  29. package/src/infrastructure/utils/input-builders.util.ts +0 -38
  30. package/src/infrastructure/utils/video-feature-builders.util.ts +0 -43
@@ -1,5 +1,6 @@
1
1
  /**
2
2
  * Infrastructure Services
3
+ * Text-only Gemini services
3
4
  */
4
5
 
5
6
  // Core services (low-level SDK wrappers)
@@ -8,16 +9,12 @@ export { geminiRetryService } from "./gemini-retry.service";
8
9
  export { geminiTextGenerationService } from "./gemini-text-generation.service";
9
10
  export { geminiTextService } from "./gemini-text-generation.service";
10
11
  export { geminiStructuredTextService } from "./gemini-structured-text.service";
11
- export { geminiImageGenerationService } from "./gemini-image-generation.service";
12
- export { geminiImageEditService } from "./gemini-image-edit.service";
13
12
  export { geminiStreamingService } from "./gemini-streaming.service";
14
- export { geminiVideoGenerationService } from "./gemini-video-generation.service";
15
13
 
16
14
  // Modular services
17
15
  export { providerInitializer } from "./provider-initializer";
18
16
  export { jobProcessor } from "./job-processor";
19
17
  export { generationExecutor } from "./generation-executor";
20
- export { featureModelSelector } from "./feature-model-selector";
21
18
 
22
19
  // Public provider API
23
20
  export {
@@ -27,7 +24,6 @@ export {
27
24
  } from "./gemini-provider";
28
25
 
29
26
  export type { GeminiProviderConfig } from "./gemini-provider";
30
- export type { GeminiProviderConfig as AIProviderConfig } from "./provider-initializer";
31
27
 
32
28
  // Generation executor types
33
29
  export type {
@@ -38,12 +34,3 @@ export type {
38
34
 
39
35
  // Retry service types
40
36
  export type { RetryOptions } from "./gemini-retry.service";
41
-
42
- // Re-export types from generation-content/core for convenience
43
- export type {
44
- IAIProvider,
45
- JobSubmission,
46
- JobStatus,
47
- SubscribeOptions,
48
- AIJobStatusType,
49
- } from "@umituz/react-native-ai-generation-content/core";
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Job Processor
3
- * Handles async job processing
3
+ * Handles async job processing for text generation
4
4
  */
5
5
 
6
6
  import { JobManager } from "../job/JobManager";
@@ -10,53 +10,53 @@ import { generationExecutor } from "./generation-executor";
10
10
  declare const __DEV__: boolean;
11
11
 
12
12
  export class JobProcessor {
13
- private jobManager = new JobManager();
14
-
15
- submitJob(model: string, input: Record<string, unknown>): Promise<JobSubmission> {
16
- const submission = this.jobManager.submitJob(model, input);
17
-
18
- this.processJobAsync(submission.requestId).catch((error) => {
19
- if (typeof __DEV__ !== "undefined" && __DEV__) {
20
- // eslint-disable-next-line no-console
21
- console.error("[GeminiProvider] Job failed:", error);
22
- }
23
- });
24
-
25
- return Promise.resolve(submission);
26
- }
27
-
28
- getJobStatus(_model: string, requestId: string): Promise<JobStatus> {
29
- const status = this.jobManager.getJobStatus(requestId);
30
- return Promise.resolve(status);
31
- }
32
-
33
- getJobResult<T = unknown>(_model: string, requestId: string): Promise<T> {
34
- try {
35
- const result = this.jobManager.getJobResult<T>(requestId);
36
- return Promise.resolve(result);
37
- } catch (error) {
38
- return Promise.reject(error);
39
- }
13
+ private jobManager = new JobManager();
14
+
15
+ submitJob(model: string, input: Record<string, unknown>): Promise<JobSubmission> {
16
+ const submission = this.jobManager.submitJob(model, input);
17
+
18
+ this.processJobAsync(submission.requestId).catch((error) => {
19
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
20
+ console.error("[GeminiProvider] Job failed:", error);
21
+ }
22
+ });
23
+
24
+ return Promise.resolve(submission);
25
+ }
26
+
27
+ getJobStatus(_model: string, requestId: string): Promise<JobStatus> {
28
+ const status = this.jobManager.getJobStatus(requestId);
29
+ return Promise.resolve(status);
30
+ }
31
+
32
+ getJobResult<T = unknown>(_model: string, requestId: string): Promise<T> {
33
+ try {
34
+ const result = this.jobManager.getJobResult<T>(requestId);
35
+ return Promise.resolve(result);
36
+ } catch (error) {
37
+ return Promise.reject(error);
40
38
  }
39
+ }
41
40
 
42
- clear(): void {
43
- this.jobManager.clear();
44
- }
41
+ clear(): void {
42
+ this.jobManager.clear();
43
+ }
45
44
 
46
- private async processJobAsync(requestId: string): Promise<void> {
47
- const job = this.jobManager.getJob(requestId);
48
- if (!job) return;
45
+ private async processJobAsync(requestId: string): Promise<void> {
46
+ const job = this.jobManager.getJob(requestId);
47
+ if (!job) return;
49
48
 
50
- this.jobManager.updateJobStatus(requestId, "IN_PROGRESS");
49
+ this.jobManager.updateJobStatus(requestId, "IN_PROGRESS");
51
50
 
52
- try {
53
- const result = await generationExecutor.executeGeneration(job.model, job.input);
54
- this.jobManager.setJobResult(requestId, result);
55
- } catch (error) {
56
- const errorMessage = error instanceof Error ? error.message : String(error);
57
- this.jobManager.setJobError(requestId, errorMessage);
58
- }
51
+ try {
52
+ const prompt = String(job.input.prompt ?? "");
53
+ const result = await generationExecutor.executeTextGeneration(prompt, job.model);
54
+ this.jobManager.setJobResult(requestId, result);
55
+ } catch (error) {
56
+ const errorMessage = error instanceof Error ? error.message : String(error);
57
+ this.jobManager.setJobError(requestId, errorMessage);
59
58
  }
59
+ }
60
60
  }
61
61
 
62
62
  export const jobProcessor = new JobProcessor();
@@ -3,50 +3,36 @@
3
3
  * Handles initialization logic for Gemini Provider
4
4
  */
5
5
 
6
- import type { AIProviderConfig } from "@umituz/react-native-ai-generation-content/core";
7
6
  import type { GeminiConfig } from "../../domain/entities";
8
7
  import { geminiClientCoreService } from "./gemini-client-core.service";
9
8
 
10
9
  declare const __DEV__: boolean;
11
10
 
12
- export type GeminiProviderConfig = AIProviderConfig;
11
+ export type GeminiProviderConfig = GeminiConfig;
13
12
 
14
13
  export class ProviderInitializer {
15
- initialize(config: GeminiProviderConfig): void {
16
- if (geminiClientCoreService.isInitialized()) {
17
- if (typeof __DEV__ !== "undefined" && __DEV__) {
18
- // eslint-disable-next-line no-console
19
- console.log("[GeminiProvider] Already initialized, skipping");
20
- }
21
- return;
22
- }
23
-
24
- if (typeof __DEV__ !== "undefined" && __DEV__) {
25
- // eslint-disable-next-line no-console
26
- console.log("[GeminiProvider] Initializing...");
27
- }
28
-
29
- const geminiConfig: GeminiConfig = {
30
- apiKey: config.apiKey,
31
- maxRetries: config.maxRetries,
32
- baseDelay: config.baseDelay,
33
- maxDelay: config.maxDelay,
34
- defaultTimeoutMs: config.defaultTimeoutMs,
35
- textModel: config.textModel,
36
- textToImageModel: config.textToImageModel,
37
- imageEditModel: config.imageEditModel,
38
- };
39
-
40
- geminiClientCoreService.initialize(geminiConfig);
14
+ initialize(config: GeminiProviderConfig): void {
15
+ if (geminiClientCoreService.isInitialized()) {
16
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
17
+ console.log("[GeminiProvider] Already initialized, skipping");
18
+ }
19
+ return;
41
20
  }
42
21
 
43
- isInitialized(): boolean {
44
- return geminiClientCoreService.isInitialized();
22
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
23
+ console.log("[GeminiProvider] Initializing...");
45
24
  }
46
25
 
47
- reset(): void {
48
- geminiClientCoreService.reset();
49
- }
26
+ geminiClientCoreService.initialize(config);
27
+ }
28
+
29
+ isInitialized(): boolean {
30
+ return geminiClientCoreService.isInitialized();
31
+ }
32
+
33
+ reset(): void {
34
+ geminiClientCoreService.reset();
35
+ }
50
36
  }
51
37
 
52
38
  export const providerInitializer = new ProviderInitializer();
@@ -1,5 +1,6 @@
1
1
  /**
2
2
  * Infrastructure Utils
3
+ * Text-only utilities
3
4
  */
4
5
 
5
6
  export {
@@ -14,21 +15,11 @@ export {
14
15
  extractTextFromResponse,
15
16
  } from "./gemini-data-transformer.util";
16
17
 
17
- export {
18
- prepareImageFromUri,
19
- prepareImage,
20
- isValidBase64,
21
- } from "./image-preparer.util";
22
- export type { PreparedImage } from "./image-preparer.util";
23
-
24
18
  export {
25
19
  isValidModel,
26
20
  validateModel,
27
21
  getSafeModel,
28
22
  isTextModel,
29
- isImageModel,
30
- isImageEditModel,
31
- isVideoGenerationModel,
32
23
  getModelCategory,
33
24
  getAllValidModels,
34
25
  } from "./model-validation.util";
@@ -49,30 +40,3 @@ export {
49
40
  rateLimiter,
50
41
  } from "./rate-limiter.util";
51
42
  export type { RateLimiterOptions } from "./rate-limiter.util";
52
-
53
- // Input builders
54
- export {
55
- buildSingleImageInput,
56
- buildDualImageInput,
57
- buildUpscaleInput,
58
- buildPhotoRestoreInput,
59
- buildFaceSwapInput,
60
- buildAnimeSelfieInput,
61
- buildRemoveBackgroundInput,
62
- buildRemoveObjectInput,
63
- buildReplaceBackgroundInput,
64
- buildHDTouchUpInput,
65
- buildVideoFromDualImagesInput,
66
- } from "./input-builders.util";
67
-
68
- export type {
69
- UpscaleOptions,
70
- PhotoRestoreOptions,
71
- FaceSwapOptions,
72
- AnimeSelfieOptions,
73
- RemoveBackgroundOptions,
74
- RemoveObjectOptions,
75
- ReplaceBackgroundOptions,
76
- VideoFromImageOptions,
77
- VideoFromDualImageOptions,
78
- } from "./input-builders.util";
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Model Validation Utilities
3
- * Validates model IDs and configurations
3
+ * Validates model IDs for text generation
4
4
  */
5
5
 
6
6
  import { GEMINI_MODELS, DEFAULT_MODELS } from "../../domain/entities";
@@ -8,10 +8,10 @@ import { GEMINI_MODELS, DEFAULT_MODELS } from "../../domain/entities";
8
8
  declare const __DEV__: boolean;
9
9
 
10
10
  /**
11
- * Known valid model IDs
11
+ * Known valid model IDs (text models only)
12
12
  */
13
13
  const VALID_MODELS = new Set<string>(
14
- Object.values(GEMINI_MODELS).flatMap((category) => Object.values(category)),
14
+ Object.values(GEMINI_MODELS.TEXT),
15
15
  );
16
16
 
17
17
  /**
@@ -36,7 +36,6 @@ export function validateModel(model: string): void {
36
36
  }
37
37
 
38
38
  if (typeof __DEV__ !== "undefined" && __DEV__) {
39
- // eslint-disable-next-line no-console
40
39
  console.log("[ModelValidation] Model validated:", model);
41
40
  }
42
41
  }
@@ -51,7 +50,6 @@ export function getSafeModel(model: string | undefined, defaultType: keyof typeo
51
50
 
52
51
  if (!isValidModel(model)) {
53
52
  if (typeof __DEV__ !== "undefined" && __DEV__) {
54
- // eslint-disable-next-line no-console
55
53
  console.warn(`[ModelValidation] Invalid model "${model}", falling back to ${DEFAULT_MODELS[defaultType]}`);
56
54
  }
57
55
  return DEFAULT_MODELS[defaultType];
@@ -67,35 +65,11 @@ export function isTextModel(model: string): boolean {
67
65
  return Object.values(GEMINI_MODELS.TEXT).includes(model as (typeof GEMINI_MODELS.TEXT)[keyof typeof GEMINI_MODELS.TEXT]);
68
66
  }
69
67
 
70
- /**
71
- * Check if model is an image generation model
72
- */
73
- export function isImageModel(model: string): boolean {
74
- return Object.values(GEMINI_MODELS.TEXT_TO_IMAGE).includes(model as (typeof GEMINI_MODELS.TEXT_TO_IMAGE)[keyof typeof GEMINI_MODELS.TEXT_TO_IMAGE]);
75
- }
76
-
77
- /**
78
- * Check if model is an image editing model
79
- */
80
- export function isImageEditModel(model: string): boolean {
81
- return Object.values(GEMINI_MODELS.IMAGE_EDIT).includes(model as (typeof GEMINI_MODELS.IMAGE_EDIT)[keyof typeof GEMINI_MODELS.IMAGE_EDIT]);
82
- }
83
-
84
- /**
85
- * Check if model is a video generation model
86
- */
87
- export function isVideoGenerationModel(model: string): boolean {
88
- return Object.values(GEMINI_MODELS.VIDEO_GENERATION).includes(model as (typeof GEMINI_MODELS.VIDEO_GENERATION)[keyof typeof GEMINI_MODELS.VIDEO_GENERATION]);
89
- }
90
-
91
68
  /**
92
69
  * Get model category
93
70
  */
94
71
  export function getModelCategory(model: string): string | null {
95
72
  if (isTextModel(model)) return "text";
96
- if (isImageModel(model)) return "text-to-image";
97
- if (isImageEditModel(model)) return "image-edit";
98
- if (isVideoGenerationModel(model)) return "video-generation";
99
73
  return null;
100
74
  }
101
75
 
@@ -1,70 +0,0 @@
1
- /**
2
- * Gemini Feature Models Catalog
3
- * Provider-specific model IDs for image and video processing features
4
- */
5
-
6
- import type {
7
- ImageFeatureType,
8
- VideoFeatureType,
9
- } from "@umituz/react-native-ai-generation-content/core";
10
-
11
- export interface FeatureModelConfig {
12
- id: string;
13
- feature: ImageFeatureType | VideoFeatureType;
14
- description?: string;
15
- }
16
-
17
- /**
18
- * Gemini model IDs for IMAGE processing features
19
- * Using gemini-2.0-flash-exp for image editing capabilities
20
- */
21
- export const GEMINI_IMAGE_FEATURE_MODELS: Record<ImageFeatureType, string> = {
22
- "upscale": "gemini-2.0-flash-exp",
23
- "photo-restore": "gemini-2.0-flash-exp",
24
- "face-swap": "gemini-2.0-flash-exp",
25
- "anime-selfie": "gemini-2.0-flash-exp",
26
- "remove-background": "gemini-2.0-flash-exp",
27
- "remove-object": "gemini-2.0-flash-exp",
28
- "hd-touch-up": "gemini-2.0-flash-exp",
29
- "replace-background": "gemini-2.0-flash-exp",
30
- };
31
-
32
- /**
33
- * Gemini model IDs for VIDEO generation features
34
- * Using gemini-2.0-flash-exp for video generation capabilities
35
- */
36
- export const GEMINI_VIDEO_FEATURE_MODELS: Record<VideoFeatureType, string> = {
37
- "image-to-video": "gemini-2.0-flash-exp",
38
- "text-to-video": "gemini-2.0-flash-exp",
39
- };
40
-
41
- /**
42
- * Get Gemini model ID for an image feature
43
- */
44
- export function getGeminiImageFeatureModel(feature: ImageFeatureType): string {
45
- return GEMINI_IMAGE_FEATURE_MODELS[feature];
46
- }
47
-
48
- /**
49
- * Get Gemini model ID for a video feature
50
- */
51
- export function getGeminiVideoFeatureModel(feature: VideoFeatureType): string {
52
- return GEMINI_VIDEO_FEATURE_MODELS[feature];
53
- }
54
-
55
- /**
56
- * Get all feature model configs
57
- */
58
- export function getAllFeatureModels(): FeatureModelConfig[] {
59
- const imageModels = Object.entries(GEMINI_IMAGE_FEATURE_MODELS).map(([feature, id]) => ({
60
- id,
61
- feature: feature as ImageFeatureType,
62
- }));
63
-
64
- const videoModels = Object.entries(GEMINI_VIDEO_FEATURE_MODELS).map(([feature, id]) => ({
65
- id,
66
- feature: feature as VideoFeatureType,
67
- }));
68
-
69
- return [...imageModels, ...videoModels];
70
- }
@@ -1,149 +0,0 @@
1
- /**
2
- * Video Generation Types
3
- * Type definitions for Google Veo video generation
4
- */
5
-
6
- /**
7
- * Video aspect ratio options
8
- */
9
- export type VideoAspectRatio = "9:16" | "16:9" | "1:1";
10
-
11
- /**
12
- * Video resolution options
13
- */
14
- export type VideoResolution = "720p" | "1080p" | "4K";
15
-
16
- /**
17
- * Video generation operation status
18
- */
19
- export type VideoOperationStatus =
20
- | "queued"
21
- | "processing"
22
- | "completed"
23
- | "failed";
24
-
25
- /**
26
- * Video generation configuration options
27
- */
28
- export interface VideoGenerationOptions {
29
- numberOfVideos?: number;
30
- aspectRatio?: VideoAspectRatio;
31
- resolution?: VideoResolution;
32
- duration?: number;
33
- }
34
-
35
- /**
36
- * Input for text-to-video generation
37
- */
38
- export interface TextToVideoInput {
39
- prompt: string;
40
- negativePrompt?: string;
41
- options?: VideoGenerationOptions;
42
- }
43
-
44
- /**
45
- * Input for image-to-video generation
46
- */
47
- export interface ImageToVideoInput {
48
- prompt: string;
49
- image: string;
50
- negativePrompt?: string;
51
- options?: VideoGenerationOptions;
52
- }
53
-
54
- /**
55
- * Input for video generation (supports both text-to-video and image-to-video)
56
- */
57
- export interface VideoGenerationInput {
58
- prompt: string;
59
- image?: string;
60
- negativePrompt?: string;
61
- options?: VideoGenerationOptions;
62
- }
63
-
64
- /**
65
- * Progress information during video generation
66
- */
67
- export interface VideoGenerationProgress {
68
- status: VideoOperationStatus;
69
- progress: number;
70
- estimatedTimeRemaining?: number;
71
- message?: string;
72
- }
73
-
74
- /**
75
- * Video generation result metadata
76
- */
77
- export interface VideoGenerationMetadata {
78
- duration: number;
79
- resolution: string;
80
- aspectRatio: string;
81
- model: string;
82
- operationName: string;
83
- }
84
-
85
- /**
86
- * Video generation result
87
- */
88
- export interface VideoGenerationResult {
89
- videoUrl: string;
90
- metadata: VideoGenerationMetadata;
91
- }
92
-
93
- /**
94
- * Video generation error types
95
- */
96
- export type VideoGenerationErrorType =
97
- | "QUOTA_EXCEEDED"
98
- | "POLICY_VIOLATION"
99
- | "TIMEOUT"
100
- | "NETWORK"
101
- | "INVALID_INPUT"
102
- | "OPERATION_FAILED";
103
-
104
- /**
105
- * Video generation error
106
- */
107
- export interface VideoGenerationError extends Error {
108
- type: VideoGenerationErrorType;
109
- statusCode?: number;
110
- retryable: boolean;
111
- }
112
-
113
- /**
114
- * Generated video from Veo API
115
- */
116
- export interface VeoGeneratedVideo {
117
- video: {
118
- uri?: string;
119
- url?: string;
120
- };
121
- }
122
-
123
- /**
124
- * Operation response from Veo API
125
- */
126
- export interface VeoOperation {
127
- name: string;
128
- done: boolean;
129
- metadata?: Record<string, unknown>;
130
- response?: {
131
- generatedVideos?: VeoGeneratedVideo[];
132
- candidates?: Array<{
133
- uri?: string;
134
- [key: string]: unknown;
135
- }>;
136
- generateVideoResponse?: {
137
- generatedSamples?: Array<{
138
- video?: {
139
- uri?: string;
140
- };
141
- }>;
142
- };
143
- };
144
- error?: {
145
- code: number;
146
- message: string;
147
- status: string;
148
- };
149
- }
@@ -1,89 +0,0 @@
1
- /**
2
- * Feature Input Builder
3
- * Builds Gemini API inputs for image and video features
4
- */
5
-
6
- import type {
7
- ImageFeatureType,
8
- VideoFeatureType,
9
- ImageFeatureInputData,
10
- VideoFeatureInputData,
11
- } from "@umituz/react-native-ai-generation-content/core";
12
- import {
13
- buildUpscaleInput,
14
- buildPhotoRestoreInput,
15
- buildFaceSwapInput,
16
- buildAnimeSelfieInput,
17
- buildRemoveBackgroundInput,
18
- buildRemoveObjectInput,
19
- buildReplaceBackgroundInput,
20
- buildHDTouchUpInput,
21
- buildVideoFromDualImagesInput,
22
- } from "../utils/input-builders.util";
23
-
24
- class FeatureInputBuilder {
25
- /**
26
- * Build input for an IMAGE feature
27
- */
28
- buildImageFeatureInput(
29
- feature: ImageFeatureType,
30
- data: ImageFeatureInputData,
31
- ): Record<string, unknown> {
32
- const { imageBase64, targetImageBase64, prompt, options } = data;
33
-
34
- switch (feature) {
35
- case "upscale":
36
- return buildUpscaleInput(imageBase64, options);
37
- case "photo-restore":
38
- return buildPhotoRestoreInput(imageBase64, options);
39
- case "face-swap":
40
- if (!targetImageBase64) {
41
- throw new Error("Face swap requires target image");
42
- }
43
- return buildFaceSwapInput(imageBase64, targetImageBase64, options);
44
- case "anime-selfie":
45
- return buildAnimeSelfieInput(imageBase64, options);
46
- case "remove-background":
47
- return buildRemoveBackgroundInput(imageBase64, options);
48
- case "remove-object":
49
- return buildRemoveObjectInput(imageBase64, { prompt, ...options });
50
- case "hd-touch-up":
51
- return buildHDTouchUpInput(imageBase64, options);
52
- case "replace-background":
53
- if (!prompt) {
54
- throw new Error("Replace background requires prompt");
55
- }
56
- return buildReplaceBackgroundInput(imageBase64, { prompt });
57
- default:
58
- throw new Error(`Unknown image feature: ${String(feature)}`);
59
- }
60
- }
61
-
62
- /**
63
- * Build input for a VIDEO feature
64
- */
65
- buildVideoFeatureInput(
66
- feature: VideoFeatureType,
67
- data: VideoFeatureInputData,
68
- ): Record<string, unknown> {
69
- const { sourceImageBase64, targetImageBase64, prompt, options } = data;
70
-
71
- switch (feature) {
72
- case "image-to-video":
73
- return buildVideoFromDualImagesInput(sourceImageBase64, {
74
- target_image: targetImageBase64,
75
- motion_prompt: prompt,
76
- ...options,
77
- });
78
- case "text-to-video":
79
- return buildVideoFromDualImagesInput(sourceImageBase64 || "", {
80
- motion_prompt: prompt,
81
- ...options,
82
- });
83
- default:
84
- throw new Error(`Unknown video feature: ${String(feature)}`);
85
- }
86
- }
87
- }
88
-
89
- export const featureInputBuilder = new FeatureInputBuilder();