@umituz/react-native-ai-generation-content 1.60.0 → 1.61.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@umituz/react-native-ai-generation-content",
3
- "version": "1.60.0",
3
+ "version": "1.61.1",
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",
7
7
  "exports": {
8
8
  ".": "./src/index.ts",
9
+ "./core": "./src/core/index.ts",
9
10
  "./prompts": "./src/domains/prompts/index.ts",
10
11
  "./content-moderation": "./src/domains/content-moderation/index.ts",
11
12
  "./creations": "./src/domains/creations/index.ts",
@@ -0,0 +1,61 @@
1
+ /**
2
+ * @umituz/react-native-ai-generation-content/core
3
+ *
4
+ * Core types for AI generation providers.
5
+ * This module contains ONLY types and utilities - no implementation details.
6
+ *
7
+ * Use this subpath for provider implementations:
8
+ * ```typescript
9
+ * import type { IAIProvider, AIProviderConfig } from "@umituz/react-native-ai-generation-content/core";
10
+ * ```
11
+ *
12
+ * @module @umituz/react-native-ai-generation-content/core
13
+ */
14
+
15
+ // Result Pattern
16
+ export type { Result, Success, Failure } from "./types/result.types";
17
+ export {
18
+ success,
19
+ failure,
20
+ isSuccess,
21
+ isFailure,
22
+ mapResult,
23
+ andThen,
24
+ unwrap,
25
+ unwrapOr,
26
+ } from "./types/result.types";
27
+
28
+ // Error Types
29
+ export { AIErrorType } from "./types/error.types";
30
+ export type { AIErrorInfo, AIErrorMessages } from "./types/error.types";
31
+
32
+ // Provider Types
33
+ export type {
34
+ // Feature Types
35
+ ImageFeatureType,
36
+ VideoFeatureType,
37
+ // Config
38
+ AIProviderConfig,
39
+ // Status
40
+ AIJobStatusType,
41
+ AILogEntry,
42
+ JobSubmission,
43
+ JobStatus,
44
+ // Progress
45
+ ProviderProgressInfo,
46
+ SubscribeOptions,
47
+ RunOptions,
48
+ // Capabilities
49
+ ProviderCapabilities,
50
+ // Input Data
51
+ ImageFeatureInputData,
52
+ VideoFeatureInputData,
53
+ // Provider Interfaces
54
+ IAIProviderLifecycle,
55
+ IAIProviderCapabilities,
56
+ IAIProviderJobManager,
57
+ IAIProviderExecutor,
58
+ IAIProviderImageFeatures,
59
+ IAIProviderVideoFeatures,
60
+ IAIProvider,
61
+ } from "./types/provider.types";
@@ -0,0 +1,36 @@
1
+ /**
2
+ * AI Generation Error Types
3
+ * Provider-agnostic error classification
4
+ *
5
+ * @module @umituz/react-native-ai-generation-content/core
6
+ */
7
+
8
+ export enum AIErrorType {
9
+ NETWORK = "NETWORK",
10
+ RATE_LIMIT = "RATE_LIMIT",
11
+ AUTHENTICATION = "AUTHENTICATION",
12
+ VALIDATION = "VALIDATION",
13
+ CONTENT_POLICY = "CONTENT_POLICY",
14
+ SERVER = "SERVER",
15
+ TIMEOUT = "TIMEOUT",
16
+ UNKNOWN = "UNKNOWN",
17
+ }
18
+
19
+ export interface AIErrorInfo {
20
+ type: AIErrorType;
21
+ messageKey: string;
22
+ retryable: boolean;
23
+ originalError?: unknown;
24
+ statusCode?: number;
25
+ }
26
+
27
+ export interface AIErrorMessages {
28
+ [AIErrorType.NETWORK]: string;
29
+ [AIErrorType.RATE_LIMIT]: string;
30
+ [AIErrorType.AUTHENTICATION]: string;
31
+ [AIErrorType.VALIDATION]: string;
32
+ [AIErrorType.CONTENT_POLICY]: string;
33
+ [AIErrorType.SERVER]: string;
34
+ [AIErrorType.TIMEOUT]: string;
35
+ [AIErrorType.UNKNOWN]: string;
36
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Core Types Index
3
+ * @module @umituz/react-native-ai-generation-content/core
4
+ */
5
+
6
+ export * from "./result.types";
7
+ export * from "./error.types";
8
+ export * from "./provider.types";
@@ -0,0 +1,201 @@
1
+ /**
2
+ * AI Provider Types
3
+ * Core interfaces for AI generation providers
4
+ *
5
+ * @module @umituz/react-native-ai-generation-content/core
6
+ */
7
+
8
+ // =============================================================================
9
+ // Feature Types
10
+ // =============================================================================
11
+
12
+ /**
13
+ * Feature types for image processing (output: image)
14
+ */
15
+ export type ImageFeatureType =
16
+ | "upscale"
17
+ | "photo-restore"
18
+ | "face-swap"
19
+ | "anime-selfie"
20
+ | "remove-background"
21
+ | "remove-object"
22
+ | "hd-touch-up"
23
+ | "replace-background";
24
+
25
+ /**
26
+ * Feature types for video generation (output: video)
27
+ */
28
+ export type VideoFeatureType = "image-to-video" | "text-to-video";
29
+
30
+ // =============================================================================
31
+ // Provider Configuration
32
+ // =============================================================================
33
+
34
+ export interface AIProviderConfig {
35
+ apiKey: string;
36
+ maxRetries?: number;
37
+ baseDelay?: number;
38
+ maxDelay?: number;
39
+ defaultTimeoutMs?: number;
40
+ textModel?: string;
41
+ textToImageModel?: string;
42
+ imageEditModel?: string;
43
+ videoGenerationModel?: string;
44
+ videoFeatureModels?: Partial<Record<VideoFeatureType, string>>;
45
+ imageFeatureModels?: Partial<Record<ImageFeatureType, string>>;
46
+ }
47
+
48
+ // =============================================================================
49
+ // Status Types
50
+ // =============================================================================
51
+
52
+ export type AIJobStatusType =
53
+ | "IN_QUEUE"
54
+ | "IN_PROGRESS"
55
+ | "COMPLETED"
56
+ | "FAILED";
57
+
58
+ export interface AILogEntry {
59
+ message: string;
60
+ level: "info" | "warn" | "error";
61
+ timestamp?: string;
62
+ }
63
+
64
+ export interface JobSubmission {
65
+ requestId: string;
66
+ statusUrl?: string;
67
+ responseUrl?: string;
68
+ }
69
+
70
+ export interface JobStatus {
71
+ status: AIJobStatusType;
72
+ logs?: AILogEntry[];
73
+ queuePosition?: number;
74
+ eta?: number;
75
+ }
76
+
77
+ // =============================================================================
78
+ // Progress & Options
79
+ // =============================================================================
80
+
81
+ export interface ProviderProgressInfo {
82
+ progress: number;
83
+ status?: AIJobStatusType;
84
+ message?: string;
85
+ estimatedTimeRemaining?: number;
86
+ }
87
+
88
+ export interface SubscribeOptions<T = unknown> {
89
+ timeoutMs?: number;
90
+ onQueueUpdate?: (status: JobStatus) => void;
91
+ onProgress?: (progress: ProviderProgressInfo) => void;
92
+ onResult?: (result: T) => void;
93
+ }
94
+
95
+ export interface RunOptions {
96
+ onProgress?: (progress: ProviderProgressInfo) => void;
97
+ }
98
+
99
+ // =============================================================================
100
+ // Capabilities
101
+ // =============================================================================
102
+
103
+ export interface ProviderCapabilities {
104
+ imageFeatures: readonly ImageFeatureType[];
105
+ videoFeatures: readonly VideoFeatureType[];
106
+ textToImage: boolean;
107
+ textToVideo: boolean;
108
+ imageToVideo: boolean;
109
+ textToVoice: boolean;
110
+ textToText: boolean;
111
+ }
112
+
113
+ // =============================================================================
114
+ // Feature Input Data
115
+ // =============================================================================
116
+
117
+ export interface ImageFeatureInputData {
118
+ imageBase64: string;
119
+ targetImageBase64?: string;
120
+ prompt?: string;
121
+ options?: Record<string, unknown>;
122
+ }
123
+
124
+ export interface VideoFeatureInputData {
125
+ sourceImageBase64?: string;
126
+ targetImageBase64?: string;
127
+ prompt?: string;
128
+ options?: Record<string, unknown>;
129
+ }
130
+
131
+ // =============================================================================
132
+ // Provider Sub-Interfaces (Interface Segregation Principle)
133
+ // =============================================================================
134
+
135
+ export interface IAIProviderLifecycle {
136
+ initialize(config: AIProviderConfig): void;
137
+ isInitialized(): boolean;
138
+ reset(): void;
139
+ }
140
+
141
+ export interface IAIProviderCapabilities {
142
+ getCapabilities(): ProviderCapabilities;
143
+ isFeatureSupported(feature: ImageFeatureType | VideoFeatureType): boolean;
144
+ }
145
+
146
+ export interface IAIProviderJobManager {
147
+ submitJob(
148
+ model: string,
149
+ input: Record<string, unknown>,
150
+ ): Promise<JobSubmission>;
151
+ getJobStatus(model: string, requestId: string): Promise<JobStatus>;
152
+ getJobResult<T = unknown>(model: string, requestId: string): Promise<T>;
153
+ }
154
+
155
+ export interface IAIProviderExecutor {
156
+ subscribe<T = unknown>(
157
+ model: string,
158
+ input: Record<string, unknown>,
159
+ options?: SubscribeOptions<T>,
160
+ ): Promise<T>;
161
+ run<T = unknown>(
162
+ model: string,
163
+ input: Record<string, unknown>,
164
+ options?: RunOptions,
165
+ ): Promise<T>;
166
+ }
167
+
168
+ export interface IAIProviderImageFeatures {
169
+ getImageFeatureModel(feature: ImageFeatureType): string;
170
+ buildImageFeatureInput(
171
+ feature: ImageFeatureType,
172
+ data: ImageFeatureInputData,
173
+ ): Record<string, unknown>;
174
+ }
175
+
176
+ export interface IAIProviderVideoFeatures {
177
+ getVideoFeatureModel(feature: VideoFeatureType): string;
178
+ buildVideoFeatureInput(
179
+ feature: VideoFeatureType,
180
+ data: VideoFeatureInputData,
181
+ ): Record<string, unknown>;
182
+ }
183
+
184
+ // =============================================================================
185
+ // Main Provider Interface
186
+ // =============================================================================
187
+
188
+ /**
189
+ * Main AI Provider Interface
190
+ * Composition of segregated interfaces following SOLID principles
191
+ */
192
+ export interface IAIProvider
193
+ extends IAIProviderLifecycle,
194
+ IAIProviderCapabilities,
195
+ IAIProviderJobManager,
196
+ IAIProviderExecutor,
197
+ IAIProviderImageFeatures,
198
+ IAIProviderVideoFeatures {
199
+ readonly providerId: string;
200
+ readonly providerName: string;
201
+ }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Result Type Pattern for Functional Error Handling
3
+ * Inspired by Rust's Result<T, E> type
4
+ *
5
+ * @module @umituz/react-native-ai-generation-content/core
6
+ */
7
+
8
+ /**
9
+ * Success result containing a value of type T
10
+ */
11
+ export interface Success<T> {
12
+ success: true;
13
+ value: T;
14
+ }
15
+
16
+ /**
17
+ * Failure result containing an error of type E
18
+ */
19
+ export interface Failure<E> {
20
+ success: false;
21
+ error: E;
22
+ }
23
+
24
+ /**
25
+ * Result type that can be either Success or Failure
26
+ * Forces explicit error handling at compile time
27
+ */
28
+ export type Result<T, E = string> = Success<T> | Failure<E>;
29
+
30
+ /**
31
+ * Create a successful result
32
+ */
33
+ export function success<T>(value: T): Success<T> {
34
+ return { success: true, value };
35
+ }
36
+
37
+ /**
38
+ * Create a failed result
39
+ */
40
+ export function failure<E>(error: E): Failure<E> {
41
+ return { success: false, error };
42
+ }
43
+
44
+ /**
45
+ * Type guard to check if result is successful
46
+ */
47
+ export function isSuccess<T, E>(result: Result<T, E>): result is Success<T> {
48
+ return result.success === true;
49
+ }
50
+
51
+ /**
52
+ * Type guard to check if result is a failure
53
+ */
54
+ export function isFailure<T, E>(result: Result<T, E>): result is Failure<E> {
55
+ return result.success === false;
56
+ }
57
+
58
+ /**
59
+ * Map a successful result to a new value
60
+ */
61
+ export function mapResult<T, U, E>(
62
+ result: Result<T, E>,
63
+ fn: (value: T) => U,
64
+ ): Result<U, E> {
65
+ if (isSuccess(result)) {
66
+ return success(fn(result.value));
67
+ }
68
+ return result;
69
+ }
70
+
71
+ /**
72
+ * Chain async operations on Result types
73
+ */
74
+ export async function andThen<T, U, E>(
75
+ result: Result<T, E>,
76
+ fn: (value: T) => Promise<Result<U, E>>,
77
+ ): Promise<Result<U, E>> {
78
+ if (isSuccess(result)) {
79
+ return fn(result.value);
80
+ }
81
+ return result;
82
+ }
83
+
84
+ /**
85
+ * Unwrap a result, throwing if it's a failure
86
+ */
87
+ export function unwrap<T, E>(result: Result<T, E>): T {
88
+ if (isSuccess(result)) {
89
+ return result.value;
90
+ }
91
+ throw new Error(`Called unwrap on a failure: ${String(result.error)}`);
92
+ }
93
+
94
+ /**
95
+ * Unwrap a result or return a default value
96
+ */
97
+ export function unwrapOr<T, E>(result: Result<T, E>, defaultValue: T): T {
98
+ if (isSuccess(result)) {
99
+ return result.value;
100
+ }
101
+ return defaultValue;
102
+ }
@@ -4,137 +4,53 @@
4
4
  * Output: video URL
5
5
  */
6
6
 
7
- import { providerRegistry } from "./provider-registry.service";
8
- import { cleanBase64, extractErrorMessage, checkFalApiError } from "../utils";
7
+ import { extractErrorMessage, checkFalApiError, validateProvider, prepareVideoInputData } from "../utils";
9
8
  import { extractVideoResult } from "../utils/url-extractor";
10
9
  import { VIDEO_TIMEOUT_MS } from "../constants";
11
- import type { VideoFeatureType, VideoFeatureInputData } from "../../domain/interfaces";
12
- import type {
13
- ExecuteVideoFeatureOptions,
14
- VideoFeatureResult,
15
- VideoFeatureRequest,
16
- } from "./video-feature-executor.types";
10
+ import type { VideoFeatureType } from "../../domain/interfaces";
11
+ import type { ExecuteVideoFeatureOptions, VideoFeatureResult, VideoFeatureRequest } from "./video-feature-executor.types";
17
12
 
18
13
  declare const __DEV__: boolean;
19
14
 
20
15
  /**
21
16
  * Execute any video feature using the active provider
22
- * Uses subscribe for video features to handle long-running generation with progress updates
23
17
  */
24
18
  export async function executeVideoFeature(
25
19
  featureType: VideoFeatureType,
26
20
  request: VideoFeatureRequest,
27
21
  options?: ExecuteVideoFeatureOptions,
28
22
  ): Promise<VideoFeatureResult> {
29
- if (__DEV__) {
30
- console.log(`[VideoExecutor:${featureType}] START`, {
31
- hasSource: !!request.sourceImageBase64,
32
- hasTarget: !!request.targetImageBase64,
33
- promptLength: request.prompt?.length ?? 0,
34
- options: request.options,
35
- });
36
- }
37
-
38
- const provider = providerRegistry.getActiveProvider();
39
-
40
- if (!provider) {
41
- if (__DEV__) {
42
- console.log(`[VideoExecutor:${featureType}] ERROR: No provider`);
43
- }
44
- return { success: false, error: "No AI provider configured" };
45
- }
46
-
47
- if (!provider.isInitialized()) {
48
- if (__DEV__) {
49
- console.log(`[VideoExecutor:${featureType}] ERROR: Provider not initialized`);
50
- }
51
- return { success: false, error: "AI provider not initialized" };
23
+ const validation = validateProvider(`VideoExecutor:${featureType}`);
24
+ if (!validation.success) {
25
+ return { success: false, error: validation.error };
52
26
  }
53
27
 
28
+ const { provider } = validation;
54
29
  const { extractResult, onStatusChange } = options ?? {};
55
-
56
30
  const model = provider.getVideoFeatureModel(featureType);
57
31
 
58
- if (__DEV__) {
59
- console.log(`[VideoExecutor:${featureType}] Provider: ${provider.providerId}, Model: ${model}`);
60
- }
61
-
62
32
  try {
63
- const inputData: VideoFeatureInputData = {
64
- sourceImageBase64: cleanBase64(request.sourceImageBase64),
65
- targetImageBase64: cleanBase64(request.targetImageBase64),
66
- prompt: request.prompt,
67
- options: request.options,
68
- };
69
-
70
- if (__DEV__) {
71
- console.log(`[VideoExecutor:${featureType}] InputData prepared`, {
72
- sourceSize: inputData.sourceImageBase64 ? `${(inputData.sourceImageBase64.length / 1024).toFixed(1)}KB` : "N/A",
73
- targetSize: inputData.targetImageBase64 ? `${(inputData.targetImageBase64.length / 1024).toFixed(1)}KB` : "N/A",
74
- prompt: inputData.prompt?.substring(0, 50) + "...",
75
- });
76
- }
77
-
33
+ const inputData = prepareVideoInputData(
34
+ request.sourceImageBase64,
35
+ request.targetImageBase64,
36
+ request.prompt,
37
+ request.options,
38
+ );
78
39
  const input = provider.buildVideoFeatureInput(featureType, inputData);
79
40
 
80
- if (__DEV__) {
81
- console.log(`[VideoExecutor:${featureType}] Built input for API`, {
82
- inputKeys: Object.keys(input),
83
- hasImageUrl: !!(input as Record<string, unknown>).image_url,
84
- hasPrompt: !!(input as Record<string, unknown>).prompt,
85
- });
86
- }
87
-
88
- let statusCount = 0;
89
41
  const result = await provider.subscribe(model, input, {
90
42
  timeoutMs: VIDEO_TIMEOUT_MS,
91
- onQueueUpdate: (status) => {
92
- statusCount++;
93
- // Log every 10th status update to avoid spam
94
- if (__DEV__ && statusCount % 10 === 1) {
95
- console.log(`[VideoExecutor:${featureType}] Queue #${statusCount}:`, status.status);
96
- }
97
- onStatusChange?.(status.status);
98
- },
43
+ onQueueUpdate: (status) => onStatusChange?.(status.status),
99
44
  });
100
45
 
101
- if (__DEV__) {
102
- console.log(`[VideoExecutor:${featureType}] API Response received`, {
103
- totalStatusUpdates: statusCount,
104
- resultKeys: result ? Object.keys(result as object) : "null",
105
- resultType: typeof result,
106
- });
107
- }
108
-
109
- // Check for FAL API error in result (may return with COMPLETED status)
110
46
  checkFalApiError(result);
111
47
 
112
- const extractor = extractResult ?? extractVideoResult;
113
- const videoUrl = extractor(result);
114
-
115
- if (__DEV__) {
116
- console.log(`[VideoExecutor:${featureType}] Extracted video URL`, {
117
- hasVideoUrl: !!videoUrl,
118
- urlPreview: videoUrl ? videoUrl.substring(0, 80) + "..." : "N/A",
119
- });
120
- }
48
+ const videoUrl = (extractResult ?? extractVideoResult)(result);
121
49
 
122
50
  if (!videoUrl) {
123
- if (__DEV__) {
124
- console.log(`[VideoExecutor:${featureType}] FAILED: No video URL`, {
125
- result: JSON.stringify(result).substring(0, 500),
126
- });
127
- }
128
51
  return { success: false, error: "No video in response" };
129
52
  }
130
53
 
131
- if (__DEV__) {
132
- console.log(`[VideoExecutor:${featureType}] SUCCESS`, {
133
- videoUrl: videoUrl.substring(0, 80) + "...",
134
- requestId: (result as { requestId?: string })?.requestId,
135
- });
136
- }
137
-
138
54
  return {
139
55
  success: true,
140
56
  videoUrl,
@@ -142,12 +58,6 @@ export async function executeVideoFeature(
142
58
  };
143
59
  } catch (error) {
144
60
  const message = extractErrorMessage(error, "Processing failed", `Video:${featureType}`);
145
- if (__DEV__) {
146
- console.log(`[VideoExecutor:${featureType}] EXCEPTION`, {
147
- error: message,
148
- originalError: error instanceof Error ? error.message : String(error),
149
- });
150
- }
151
61
  return { success: false, error: message };
152
62
  }
153
63
  }
@@ -156,67 +66,38 @@ export async function executeVideoFeature(
156
66
  * Check if video features are supported
157
67
  */
158
68
  export function hasVideoFeatureSupport(): boolean {
159
- const provider = providerRegistry.getActiveProvider();
160
- return provider !== null && provider.isInitialized();
69
+ const validation = validateProvider("VideoFeatureSupport");
70
+ return validation.success;
161
71
  }
162
72
 
163
73
  /**
164
74
  * Submit a video feature to the queue for background processing
165
- * Returns immediately with requestId and model for later status polling
166
75
  */
167
76
  export async function submitVideoFeatureToQueue(
168
77
  featureType: VideoFeatureType,
169
78
  request: VideoFeatureRequest,
170
79
  ): Promise<{ success: boolean; requestId?: string; model?: string; error?: string }> {
171
- if (__DEV__) {
172
- console.log(`[VideoExecutor:${featureType}] QUEUE SUBMIT`, {
173
- hasSource: !!request.sourceImageBase64,
174
- hasTarget: !!request.targetImageBase64,
175
- promptLength: request.prompt?.length ?? 0,
176
- });
177
- }
178
-
179
- const provider = providerRegistry.getActiveProvider();
180
-
181
- if (!provider) {
182
- return { success: false, error: "No AI provider configured" };
183
- }
184
-
185
- if (!provider.isInitialized()) {
186
- return { success: false, error: "AI provider not initialized" };
80
+ const validation = validateProvider(`VideoExecutor:${featureType}`);
81
+ if (!validation.success) {
82
+ return { success: false, error: validation.error };
187
83
  }
188
84
 
85
+ const { provider } = validation;
189
86
  const model = provider.getVideoFeatureModel(featureType);
190
87
 
191
88
  try {
192
- const inputData: VideoFeatureInputData = {
193
- sourceImageBase64: cleanBase64(request.sourceImageBase64),
194
- targetImageBase64: cleanBase64(request.targetImageBase64),
195
- prompt: request.prompt,
196
- options: request.options,
197
- };
198
-
89
+ const inputData = prepareVideoInputData(
90
+ request.sourceImageBase64,
91
+ request.targetImageBase64,
92
+ request.prompt,
93
+ request.options,
94
+ );
199
95
  const input = provider.buildVideoFeatureInput(featureType, inputData);
200
-
201
96
  const submission = await provider.submitJob(model, input);
202
97
 
203
- if (__DEV__) {
204
- console.log(`[VideoExecutor:${featureType}] QUEUE SUBMITTED`, {
205
- requestId: submission.requestId,
206
- model,
207
- });
208
- }
209
-
210
- return {
211
- success: true,
212
- requestId: submission.requestId,
213
- model,
214
- };
98
+ return { success: true, requestId: submission.requestId, model };
215
99
  } catch (error) {
216
100
  const message = extractErrorMessage(error, "Queue submission failed", `Video:${featureType}`);
217
- if (__DEV__) {
218
- console.error(`[VideoExecutor:${featureType}] QUEUE EXCEPTION`, { error: message });
219
- }
220
101
  return { success: false, error: message };
221
102
  }
222
103
  }
@@ -13,3 +13,4 @@ export * from "./photo-generation";
13
13
  export * from "./feature-utils";
14
14
  export * from "./video-helpers";
15
15
  export * from "./media-actions.util";
16
+ export * from "./provider-validator.util";
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Provider Validator Utility
3
+ * Validates provider state and prepares feature inputs
4
+ */
5
+
6
+ import { providerRegistry } from "../services/provider-registry.service";
7
+ import { cleanBase64 } from "./index";
8
+ import type { IAIProvider, VideoFeatureInputData, ImageFeatureInputData } from "../../domain/interfaces";
9
+
10
+ declare const __DEV__: boolean;
11
+
12
+ export type ProviderValidationResult =
13
+ | { success: true; provider: IAIProvider }
14
+ | { success: false; error: string };
15
+
16
+ /**
17
+ * Validate provider is available and initialized
18
+ */
19
+ export function validateProvider(context: string): ProviderValidationResult {
20
+ const provider = providerRegistry.getActiveProvider();
21
+
22
+ if (!provider) {
23
+ if (__DEV__) {
24
+ console.log(`[${context}] ERROR: No provider`);
25
+ }
26
+ return { success: false, error: "No AI provider configured" };
27
+ }
28
+
29
+ if (!provider.isInitialized()) {
30
+ if (__DEV__) {
31
+ console.log(`[${context}] ERROR: Provider not initialized`);
32
+ }
33
+ return { success: false, error: "AI provider not initialized" };
34
+ }
35
+
36
+ return { success: true, provider };
37
+ }
38
+
39
+ /**
40
+ * Prepare video feature input data
41
+ */
42
+ export function prepareVideoInputData(
43
+ sourceImageBase64?: string,
44
+ targetImageBase64?: string,
45
+ prompt?: string,
46
+ options?: Record<string, unknown>,
47
+ ): VideoFeatureInputData {
48
+ return {
49
+ sourceImageBase64: cleanBase64(sourceImageBase64),
50
+ targetImageBase64: cleanBase64(targetImageBase64),
51
+ prompt,
52
+ options,
53
+ };
54
+ }
55
+
56
+ /**
57
+ * Prepare image feature input data
58
+ */
59
+ export function prepareImageInputData(
60
+ imageBase64: string,
61
+ targetImageBase64?: string,
62
+ prompt?: string,
63
+ options?: Record<string, unknown>,
64
+ ): ImageFeatureInputData {
65
+ return {
66
+ imageBase64: cleanBase64(imageBase64) ?? "",
67
+ targetImageBase64: cleanBase64(targetImageBase64),
68
+ prompt,
69
+ options,
70
+ };
71
+ }