@umituz/react-native-ai-generation-content 1.17.228 → 1.17.230
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/LICENSE +21 -0
- package/README.md +346 -0
- package/package.json +1 -3
- package/src/domain/README.md +503 -0
- package/src/domains/content-moderation/README.md +363 -0
- package/src/domains/creations/README.md +394 -0
- package/src/domains/face-detection/README.md +395 -0
- package/src/domains/prompts/README.md +387 -0
- package/src/features/ai-hug/README.md +276 -0
- package/src/features/ai-kiss/README.md +276 -0
- package/src/features/anime-selfie/README.md +325 -0
- package/src/features/audio-generation/README.md +370 -0
- package/src/features/colorization/README.md +289 -0
- package/src/features/couple-future/README.md +270 -0
- package/src/features/face-swap/README.md +234 -0
- package/src/features/future-prediction/README.md +281 -0
- package/src/features/hd-touch-up/README.md +309 -0
- package/src/features/image-captioning/README.md +361 -0
- package/src/features/image-to-image/README.md +418 -0
- package/src/features/image-to-video/README.md +369 -0
- package/src/features/inpainting/README.md +302 -0
- package/src/features/meme-generator/README.md +327 -0
- package/src/features/photo-restoration/README.md +286 -0
- package/src/features/remove-background/README.md +292 -0
- package/src/features/remove-object/README.md +352 -0
- package/src/features/replace-background/README.md +288 -0
- package/src/features/script-generator/README.md +362 -0
- package/src/features/shared/README.md +280 -0
- package/src/features/sketch-to-image/README.md +296 -0
- package/src/features/style-transfer/README.md +301 -0
- package/src/features/text-to-image/README.md +228 -0
- package/src/features/text-to-video/README.md +245 -0
- package/src/features/text-to-voice/README.md +335 -0
- package/src/features/upscaling/README.md +247 -0
- package/src/infrastructure/config/README.md +310 -0
- package/src/infrastructure/middleware/README.md +378 -0
- package/src/infrastructure/orchestration/README.md +362 -0
- package/src/infrastructure/services/README.md +382 -0
- package/src/infrastructure/utils/README.md +523 -0
- package/src/infrastructure/wrappers/README.md +336 -0
- package/src/presentation/components/README.md +535 -0
- package/src/presentation/hooks/README.md +380 -0
- package/src/presentation/hooks/base/use-dual-image-feature.ts +4 -4
- package/src/presentation/hooks/base/use-image-with-prompt-feature.ts +4 -4
- package/src/presentation/hooks/base/utils/feature-state.factory.ts +1 -1
- package/src/presentation/layouts/README.md +374 -0
- package/src/presentation/layouts/types/layout-props.ts +1 -1
- package/src/presentation/screens/README.md +430 -0
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
# Infrastructure Utils
|
|
2
|
+
|
|
3
|
+
Utility functions for AI generation operations.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The utils module provides helper functions for common operations such as error classification, image preparation, polling, validation, and more.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- Error classification and handling
|
|
12
|
+
- Image preparation and optimization
|
|
13
|
+
- Job polling utilities
|
|
14
|
+
- Progress tracking
|
|
15
|
+
- Validation functions
|
|
16
|
+
- Helper functions for common tasks
|
|
17
|
+
|
|
18
|
+
## Error Handling
|
|
19
|
+
|
|
20
|
+
### classifyError
|
|
21
|
+
|
|
22
|
+
Classify errors into types:
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
import { classifyError, AIErrorType } from '@umituz/react-native-ai-generation-content';
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
await generateImage({ prompt: 'A sunset' });
|
|
29
|
+
} catch (error) {
|
|
30
|
+
const errorType = classifyError(error);
|
|
31
|
+
|
|
32
|
+
switch (errorType) {
|
|
33
|
+
case AIErrorType.INSUFFICIENT_CREDITS:
|
|
34
|
+
// Handle insufficient credits
|
|
35
|
+
showPaywall();
|
|
36
|
+
break;
|
|
37
|
+
case AIErrorType.PROVIDER_ERROR:
|
|
38
|
+
// Handle provider error
|
|
39
|
+
showErrorMessage('Provider error occurred');
|
|
40
|
+
break;
|
|
41
|
+
case AIErrorType.NETWORK_ERROR:
|
|
42
|
+
// Handle network error
|
|
43
|
+
showRetryOption();
|
|
44
|
+
break;
|
|
45
|
+
default:
|
|
46
|
+
// Handle unknown error
|
|
47
|
+
showGenericError();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### isTransientError
|
|
53
|
+
|
|
54
|
+
Check if error is transient (retry-able):
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
import { isTransientError } from '@umituz/react-native-ai-generation-content';
|
|
58
|
+
|
|
59
|
+
if (isTransientError(error)) {
|
|
60
|
+
// Safe to retry
|
|
61
|
+
retry();
|
|
62
|
+
} else {
|
|
63
|
+
// Don't retry
|
|
64
|
+
showError();
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### isPermanentError
|
|
69
|
+
|
|
70
|
+
Check if error is permanent:
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
import { isPermanentError } from '@umituz/react-native-ai-generation-content';
|
|
74
|
+
|
|
75
|
+
if (isPermanentError(error)) {
|
|
76
|
+
// Don't retry
|
|
77
|
+
showError();
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### handleGenerationError
|
|
82
|
+
|
|
83
|
+
Handle generation errors with default behavior:
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
import { handleGenerationError } from '@umituz/react-native-ai-generation-content';
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
await generateImage({ prompt: 'A sunset' });
|
|
90
|
+
} catch (error) {
|
|
91
|
+
await handleGenerationError(error, {
|
|
92
|
+
onInsufficientCredits: () => showPaywall(),
|
|
93
|
+
onNetworkError: () => showRetryDialog(),
|
|
94
|
+
onProviderError: () => showSupportContact(),
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Polling Utilities
|
|
100
|
+
|
|
101
|
+
### pollJob
|
|
102
|
+
|
|
103
|
+
Poll a job for completion:
|
|
104
|
+
|
|
105
|
+
```tsx
|
|
106
|
+
import { pollJob } from '@umituz/react-native-ai-generation-content';
|
|
107
|
+
|
|
108
|
+
const result = await pollJob({
|
|
109
|
+
jobId: 'job-123',
|
|
110
|
+
provider: 'openai',
|
|
111
|
+
maxAttempts: 30,
|
|
112
|
+
interval: 2000,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
if (result.status === JobStatus.COMPLETED) {
|
|
116
|
+
console.log('Result:', result.result);
|
|
117
|
+
} else if (result.status === JobStatus.FAILED) {
|
|
118
|
+
console.error('Error:', result.error);
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### createJobPoller
|
|
123
|
+
|
|
124
|
+
Create a persistent job poller:
|
|
125
|
+
|
|
126
|
+
```tsx
|
|
127
|
+
import { createJobPoller } from '@umituz/react-native-ai-generation-content';
|
|
128
|
+
|
|
129
|
+
const poller = createJobPoller({
|
|
130
|
+
jobId: 'job-123',
|
|
131
|
+
provider: 'openai',
|
|
132
|
+
onProgress: (progress) => {
|
|
133
|
+
console.log('Progress:', progress);
|
|
134
|
+
},
|
|
135
|
+
onComplete: (result) => {
|
|
136
|
+
console.log('Complete:', result);
|
|
137
|
+
},
|
|
138
|
+
onError: (error) => {
|
|
139
|
+
console.error('Error:', error);
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// Start polling
|
|
144
|
+
poller.start();
|
|
145
|
+
|
|
146
|
+
// Stop polling
|
|
147
|
+
poller.stop();
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### calculatePollingInterval
|
|
151
|
+
|
|
152
|
+
Calculate optimal polling interval:
|
|
153
|
+
|
|
154
|
+
```tsx
|
|
155
|
+
import { calculatePollingInterval } from '@umituz/react-native-ai-generation-content';
|
|
156
|
+
|
|
157
|
+
const interval = calculatePollingInterval({
|
|
158
|
+
baseInterval: 2000,
|
|
159
|
+
attemptNumber: 3,
|
|
160
|
+
maxInterval: 10000,
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
console.log('Interval:', interval); // 2000, 4000, 6000, ...
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Progress Tracking
|
|
167
|
+
|
|
168
|
+
### createProgressTracker
|
|
169
|
+
|
|
170
|
+
Create a progress tracker:
|
|
171
|
+
|
|
172
|
+
```tsx
|
|
173
|
+
import { createProgressTracker } from '@umituz/react-native-ai-generation-content';
|
|
174
|
+
|
|
175
|
+
const tracker = createProgressTracker({
|
|
176
|
+
stages: [
|
|
177
|
+
{ name: 'initializing', weight: 10 },
|
|
178
|
+
{ name: 'processing', weight: 70 },
|
|
179
|
+
{ name: 'finalizing', weight: 20 },
|
|
180
|
+
],
|
|
181
|
+
onProgress: (progress) => {
|
|
182
|
+
console.log('Progress:', progress.percent, progress.stage);
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// Update stage
|
|
187
|
+
tracker.setStage('processing');
|
|
188
|
+
|
|
189
|
+
// Update progress within stage
|
|
190
|
+
tracker.setProgress(50); // 50% of current stage
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### getProgressForStatus
|
|
194
|
+
|
|
195
|
+
Get progress for job status:
|
|
196
|
+
|
|
197
|
+
```tsx
|
|
198
|
+
import { getProgressForStatus } from '@umituz/react-native-ai-generation-content';
|
|
199
|
+
|
|
200
|
+
const progress = getProgressForStatus(JobStatus.PROCESSING);
|
|
201
|
+
console.log('Progress:', progress); // 0-100
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Image Preparation
|
|
205
|
+
|
|
206
|
+
### preparePhoto
|
|
207
|
+
|
|
208
|
+
Prepare and optimize photo for upload:
|
|
209
|
+
|
|
210
|
+
```tsx
|
|
211
|
+
import { preparePhoto } from '@umituz/react-native-ai-generation-content';
|
|
212
|
+
|
|
213
|
+
const prepared = await preparePhoto({
|
|
214
|
+
imageBase64: rawImage,
|
|
215
|
+
maxSize: 1048576, // 1MB
|
|
216
|
+
maxWidth: 1920,
|
|
217
|
+
maxHeight: 1080,
|
|
218
|
+
quality: 0.9,
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
console.log('Prepared image:', prepared.imageBase64);
|
|
222
|
+
console.log('Original size:', prepared.originalSize);
|
|
223
|
+
console.log('Compressed size:', prepared.compressedSize);
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### preparePhotos
|
|
227
|
+
|
|
228
|
+
Prepare multiple photos:
|
|
229
|
+
|
|
230
|
+
```tsx
|
|
231
|
+
import { preparePhotos } from '@umituz/react-native-ai-generation-content';
|
|
232
|
+
|
|
233
|
+
const prepared = await preparePhotos({
|
|
234
|
+
images: [image1, image2, image3],
|
|
235
|
+
maxSize: 1048576,
|
|
236
|
+
maxWidth: 1920,
|
|
237
|
+
maxHeight: 1080,
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
console.log('Prepared images:', prepared.images);
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### cleanBase64
|
|
244
|
+
|
|
245
|
+
Clean base64 string:
|
|
246
|
+
|
|
247
|
+
```tsx
|
|
248
|
+
import { cleanBase64 } from '@umituz/react-native-ai-generation-content';
|
|
249
|
+
|
|
250
|
+
const clean = cleanBase64('data:image/jpeg;base64,/9j/4AAQ...');
|
|
251
|
+
console.log('Clean base64:', clean);
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### addBase64Prefix
|
|
255
|
+
|
|
256
|
+
Add base64 prefix:
|
|
257
|
+
|
|
258
|
+
```tsx
|
|
259
|
+
import { addBase64Prefix } from '@umituz/react-native-ai-generation-content';
|
|
260
|
+
|
|
261
|
+
const withPrefix = addBase64Prefix('/9j/4AAQ...', 'image/jpeg');
|
|
262
|
+
console.log('With prefix:', withPrefix);
|
|
263
|
+
// "data:image/jpeg;base64,/9j/4AAQ..."
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Validation
|
|
267
|
+
|
|
268
|
+
### isValidBase64
|
|
269
|
+
|
|
270
|
+
Validate base64 string:
|
|
271
|
+
|
|
272
|
+
```tsx
|
|
273
|
+
import { isValidBase64 } from '@umituz/react-native-ai-generation-content';
|
|
274
|
+
|
|
275
|
+
if (isValidBase64(imageString)) {
|
|
276
|
+
// Valid base64
|
|
277
|
+
} else {
|
|
278
|
+
// Invalid base64
|
|
279
|
+
showError('Invalid image format');
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### validateResult
|
|
284
|
+
|
|
285
|
+
Validate generation result:
|
|
286
|
+
|
|
287
|
+
```tsx
|
|
288
|
+
import { validateResult } from '@umituz/react-native-ai-generation-content';
|
|
289
|
+
|
|
290
|
+
const isValid = await validateResult({
|
|
291
|
+
result: generationResult,
|
|
292
|
+
featureType: 'text-to-image',
|
|
293
|
+
checkUrl: true,
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
if (!isValid) {
|
|
297
|
+
showError('Invalid generation result');
|
|
298
|
+
}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### checkStatusForErrors
|
|
302
|
+
|
|
303
|
+
Check job status for errors:
|
|
304
|
+
|
|
305
|
+
```tsx
|
|
306
|
+
import { checkStatusForErrors } from '@umituz/react-native-ai-generation-content';
|
|
307
|
+
|
|
308
|
+
const hasError = checkStatusForErrors(jobStatus);
|
|
309
|
+
|
|
310
|
+
if (hasError) {
|
|
311
|
+
// Handle error
|
|
312
|
+
}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
## Result Extraction
|
|
316
|
+
|
|
317
|
+
### extractOutputUrl
|
|
318
|
+
|
|
319
|
+
Extract output URL from response:
|
|
320
|
+
|
|
321
|
+
```tsx
|
|
322
|
+
import { extractOutputUrl } from '@umituz/react-native-ai-generation-content';
|
|
323
|
+
|
|
324
|
+
const url = extractOutputUrl(providerResponse);
|
|
325
|
+
console.log('Output URL:', url);
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### extractOutputUrls
|
|
329
|
+
|
|
330
|
+
Extract multiple output URLs:
|
|
331
|
+
|
|
332
|
+
```tsx
|
|
333
|
+
import { extractOutputUrls } from '@umituz/react-native-ai-generation-content';
|
|
334
|
+
|
|
335
|
+
const urls = extractOutputUrls(providerResponse);
|
|
336
|
+
console.log('Output URLs:', urls);
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### extractVideoUrl
|
|
340
|
+
|
|
341
|
+
Extract video URL:
|
|
342
|
+
|
|
343
|
+
```tsx
|
|
344
|
+
import { extractVideoUrl } from '@umituz/react-native-ai-generation-content';
|
|
345
|
+
|
|
346
|
+
const videoUrl = extractVideoUrl(providerResponse);
|
|
347
|
+
console.log('Video URL:', videoUrl);
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### extractThumbnailUrl
|
|
351
|
+
|
|
352
|
+
Extract thumbnail URL:
|
|
353
|
+
|
|
354
|
+
```tsx
|
|
355
|
+
import { extractThumbnailUrl } from '@umituz/react-native-ai-generation-content';
|
|
356
|
+
|
|
357
|
+
const thumbnailUrl = extractThumbnailUrl(providerResponse);
|
|
358
|
+
console.log('Thumbnail URL:', thumbnailUrl);
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### extractAudioUrl
|
|
362
|
+
|
|
363
|
+
Extract audio URL:
|
|
364
|
+
|
|
365
|
+
```tsx
|
|
366
|
+
import { extractAudioUrl } from '@umituz/react-native-ai-generation-content';
|
|
367
|
+
|
|
368
|
+
const audioUrl = extractAudioUrl(providerResponse);
|
|
369
|
+
console.log('Audio URL:', audioUrl);
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
### extractImageUrls
|
|
373
|
+
|
|
374
|
+
Extract image URLs:
|
|
375
|
+
|
|
376
|
+
```tsx
|
|
377
|
+
import { extractImageUrls } from '@umituz/react-native-ai-generation-content';
|
|
378
|
+
|
|
379
|
+
const imageUrls = extractImageUrls(providerResponse);
|
|
380
|
+
console.log('Image URLs:', imageUrls);
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
## Base64 Utilities
|
|
384
|
+
|
|
385
|
+
### getBase64Size
|
|
386
|
+
|
|
387
|
+
Get base64 size in bytes:
|
|
388
|
+
|
|
389
|
+
```tsx
|
|
390
|
+
import { getBase64Size } from '@umituz/react-native-ai-generation-content';
|
|
391
|
+
|
|
392
|
+
const size = getBase64Size(base64String);
|
|
393
|
+
console.log('Size:', size, 'bytes');
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### getBase64SizeMB
|
|
397
|
+
|
|
398
|
+
Get base64 size in MB:
|
|
399
|
+
|
|
400
|
+
```tsx
|
|
401
|
+
import { getBase64SizeMB } from '@umituz/react-native-ai-generation-content';
|
|
402
|
+
|
|
403
|
+
const sizeMB = getBase64SizeMB(base64String);
|
|
404
|
+
console.log('Size:', sizeMB, 'MB');
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
## UI Helpers
|
|
408
|
+
|
|
409
|
+
### createDevCallbacks
|
|
410
|
+
|
|
411
|
+
Create development callbacks:
|
|
412
|
+
|
|
413
|
+
```tsx
|
|
414
|
+
import { createDevCallbacks } from '@umituz/react-native-ai-generation-content';
|
|
415
|
+
|
|
416
|
+
if (__DEV__) {
|
|
417
|
+
const callbacks = createDevCallbacks();
|
|
418
|
+
// Logs all generation events in development
|
|
419
|
+
}
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
### createFeatureUtils
|
|
423
|
+
|
|
424
|
+
Create feature utilities:
|
|
425
|
+
|
|
426
|
+
```tsx
|
|
427
|
+
import { createFeatureUtils } from '@umituz/react-native-ai-generation-content';
|
|
428
|
+
|
|
429
|
+
const utils = createFeatureUtils({
|
|
430
|
+
showVideoGenerationSuccess: true,
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
await utils.showVideoGenerationSuccess(videoUrl);
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
### showVideoGenerationSuccess
|
|
437
|
+
|
|
438
|
+
Show video generation success alert:
|
|
439
|
+
|
|
440
|
+
```tsx
|
|
441
|
+
import { showVideoGenerationSuccess } from '@umituz/react-native-ai-generation-content';
|
|
442
|
+
|
|
443
|
+
await showVideoGenerationSuccess({
|
|
444
|
+
videoUrl: 'https://...',
|
|
445
|
+
onSave: async () => {
|
|
446
|
+
await saveToGallery(videoUrl);
|
|
447
|
+
},
|
|
448
|
+
});
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
### showContentModerationWarning
|
|
452
|
+
|
|
453
|
+
Show content moderation warning:
|
|
454
|
+
|
|
455
|
+
```tsx
|
|
456
|
+
import { showContentModerationWarning } from '@umituz/react-native-ai-generation-content';
|
|
457
|
+
|
|
458
|
+
await showContentModerationWarning({
|
|
459
|
+
violations: ['violence', 'adult-content'],
|
|
460
|
+
onConfirm: () => {
|
|
461
|
+
// User acknowledged and wants to proceed
|
|
462
|
+
},
|
|
463
|
+
onCancel: () => {
|
|
464
|
+
// User cancelled
|
|
465
|
+
},
|
|
466
|
+
});
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
## Job Status Helpers
|
|
470
|
+
|
|
471
|
+
### isJobComplete
|
|
472
|
+
|
|
473
|
+
Check if job is complete:
|
|
474
|
+
|
|
475
|
+
```tsx
|
|
476
|
+
import { isJobComplete } from '@umituz/react-native-ai-generation-content';
|
|
477
|
+
|
|
478
|
+
if (isJobComplete(jobStatus)) {
|
|
479
|
+
// Job is complete
|
|
480
|
+
}
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
### isJobProcessing
|
|
484
|
+
|
|
485
|
+
Check if job is processing:
|
|
486
|
+
|
|
487
|
+
```tsx
|
|
488
|
+
import { isJobProcessing } from '@umituz/react-native-ai-generation-content';
|
|
489
|
+
|
|
490
|
+
if (isJobProcessing(jobStatus)) {
|
|
491
|
+
// Job is still processing
|
|
492
|
+
}
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
### isJobFailed
|
|
496
|
+
|
|
497
|
+
Check if job failed:
|
|
498
|
+
|
|
499
|
+
```tsx
|
|
500
|
+
import { isJobFailed } from '@umituz/react-native-ai-generation-content';
|
|
501
|
+
|
|
502
|
+
if (isJobFailed(jobStatus)) {
|
|
503
|
+
// Job failed
|
|
504
|
+
}
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
## Best Practices
|
|
508
|
+
|
|
509
|
+
1. **Error Handling**: Always classify and handle errors appropriately
|
|
510
|
+
2. **Image Preparation**: Always prepare images before upload
|
|
511
|
+
3. **Validation**: Validate inputs and results
|
|
512
|
+
4. **Progress Tracking**: Show progress to users for long operations
|
|
513
|
+
5. **Base64 Cleaning**: Clean base64 strings before processing
|
|
514
|
+
|
|
515
|
+
## Related
|
|
516
|
+
|
|
517
|
+
- [Config](../config/) - Service configuration
|
|
518
|
+
- [Services](../services/) - AI generation services
|
|
519
|
+
- [Orchestration](../orchestration/) - Generation orchestration
|
|
520
|
+
|
|
521
|
+
## License
|
|
522
|
+
|
|
523
|
+
MIT
|