@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.
Files changed (171) hide show
  1. package/package.json +3 -3
  2. package/src/domain/interfaces/app-services-auth.interface.ts +27 -0
  3. package/src/domain/interfaces/app-services-composite.interface.ts +29 -0
  4. package/src/domain/interfaces/app-services-optional.interface.ts +42 -0
  5. package/src/domain/interfaces/app-services.interface.ts +0 -79
  6. package/src/domain/interfaces/index.ts +3 -0
  7. package/src/domains/background/infrastructure/services/job-poller-index.ts +7 -0
  8. package/src/domains/background/infrastructure/services/job-poller-utils.ts +127 -0
  9. package/src/domains/background/infrastructure/services/job-poller.service.ts +85 -140
  10. package/src/domains/background/infrastructure/utils/polling-interval.util.ts +1 -1
  11. package/src/domains/background/presentation/hooks/use-background-generation.ts +1 -1
  12. package/src/domains/content-moderation/index.ts +7 -13
  13. package/src/domains/content-moderation/infrastructure/services/content-moderation.service.ts +1 -1
  14. package/src/domains/content-moderation/infrastructure/services/moderators/image.moderator.ts +34 -8
  15. package/src/domains/content-moderation/infrastructure/services/moderators/text.moderator.ts +15 -4
  16. package/src/domains/content-moderation/infrastructure/services/moderators/video.moderator.ts +34 -8
  17. package/src/domains/content-moderation/infrastructure/services/moderators/voice.moderator.ts +19 -8
  18. package/src/domains/content-moderation/infrastructure/services/pattern-matcher.service.ts +1 -2
  19. package/src/domains/creations/domain/types/creation-categories.constants.ts +57 -0
  20. package/src/domains/creations/domain/types/creation-categories.helpers.ts +67 -0
  21. package/src/domains/creations/domain/types/creation-categories.ts +7 -114
  22. package/src/domains/creations/domain/utils/creation-display.util.ts +1 -1
  23. package/src/domains/creations/domain/utils/status-helpers.ts +1 -1
  24. package/src/domains/creations/presentation/hooks/creation-validators.ts +31 -29
  25. package/src/domains/creations/presentation/hooks/job-poller-index.ts +10 -0
  26. package/src/domains/creations/presentation/hooks/job-poller-utils.filters.ts +34 -0
  27. package/src/domains/creations/presentation/hooks/job-poller-utils.logger.ts +76 -0
  28. package/src/domains/creations/presentation/hooks/job-poller-utils.stale-handlers.ts +52 -0
  29. package/src/domains/creations/presentation/hooks/job-poller-utils.ts +8 -0
  30. package/src/domains/creations/presentation/hooks/useCreations.ts +1 -1
  31. package/src/domains/creations/presentation/hooks/useProcessingJobsPoller.ts +18 -235
  32. package/src/domains/creations/presentation/screens/CreationsGalleryScreen.tsx +1 -2
  33. package/src/domains/creations/presentation-exports.ts +2 -2
  34. package/src/domains/face-detection/domain/entities/FaceDetection.ts +4 -3
  35. package/src/domains/face-detection/presentation/hooks/useFaceDetection.ts +24 -21
  36. package/src/domains/generation/infrastructure/appearance-analysis/index.ts +5 -0
  37. package/src/domains/generation/infrastructure/couple-generation-builder/builder-couple-preparation.ts +58 -0
  38. package/src/domains/generation/infrastructure/couple-generation-builder/builder-couple-prompt.ts +69 -0
  39. package/src/domains/generation/infrastructure/couple-generation-builder/builder-couple-resolution.ts +77 -0
  40. package/src/domains/generation/infrastructure/couple-generation-builder/builder-couple.ts +54 -0
  41. package/src/domains/generation/infrastructure/couple-generation-builder/builder-index.ts +8 -0
  42. package/src/domains/generation/infrastructure/couple-generation-builder/builder-scenario.ts +112 -0
  43. package/src/domains/generation/infrastructure/couple-generation-builder/builder.ts +7 -0
  44. package/src/domains/generation/infrastructure/couple-generation-builder/index.ts +20 -0
  45. package/src/domains/generation/infrastructure/couple-generation-builder/types.ts +44 -0
  46. package/src/domains/generation/infrastructure/couple-generation-builder/utils/builder-end-logger.ts +18 -0
  47. package/src/domains/generation/infrastructure/couple-generation-builder/utils/builder-start-logger.ts +57 -0
  48. package/src/domains/generation/infrastructure/couple-generation-builder/utils/builder-step-logger.ts +106 -0
  49. package/src/domains/generation/infrastructure/couple-generation-builder/utils/index.ts +8 -0
  50. package/src/domains/generation/infrastructure/couple-generation-builder/utils/types.ts +49 -0
  51. package/src/domains/generation/infrastructure/couple-generation-builder/utils.ts +8 -0
  52. package/src/domains/generation/infrastructure/flow/flow-store-actions.ts +105 -0
  53. package/src/domains/generation/infrastructure/flow/flow-store-initial-state.ts +26 -0
  54. package/src/domains/generation/infrastructure/flow/useFlowStore.ts +4 -116
  55. package/src/domains/generation/presentation/useAIGeneration.hook.ts +1 -1
  56. package/src/domains/generation/wizard/infrastructure/strategies/image-generation-strategy-index.ts +7 -0
  57. package/src/domains/generation/wizard/infrastructure/strategies/image-generation.executor.ts +2 -12
  58. package/src/domains/generation/wizard/infrastructure/strategies/image-generation.executor.types.ts +11 -0
  59. package/src/domains/generation/wizard/infrastructure/strategies/image-generation.executor.utils.ts +12 -0
  60. package/src/domains/generation/wizard/infrastructure/strategies/image-generation.strategy.ts +1 -220
  61. package/src/domains/generation/wizard/infrastructure/strategies/image-input-builder.ts +66 -0
  62. package/src/domains/generation/wizard/infrastructure/strategies/image-input-extraction.ts +88 -0
  63. package/src/domains/generation/wizard/infrastructure/strategies/image-input-prompt-builder.ts +74 -0
  64. package/src/domains/generation/wizard/infrastructure/strategies/image-input-style-enhancements.ts +35 -0
  65. package/src/domains/generation/wizard/infrastructure/strategies/image-strategy-factory.ts +41 -0
  66. package/src/domains/generation/wizard/infrastructure/strategies/video-generation-executor-index.ts +10 -0
  67. package/src/domains/generation/wizard/infrastructure/strategies/video-generation-executor.ts +76 -0
  68. package/src/domains/generation/wizard/infrastructure/strategies/video-generation-input-builder.ts +46 -0
  69. package/src/domains/generation/wizard/infrastructure/strategies/video-generation-result-types.ts +17 -0
  70. package/src/domains/generation/wizard/infrastructure/strategies/video-generation-submission.ts +61 -0
  71. package/src/domains/generation/wizard/infrastructure/strategies/video-generation.audio-extractor.ts +27 -0
  72. package/src/domains/generation/wizard/infrastructure/strategies/video-generation.executor.ts +2 -176
  73. package/src/domains/generation/wizard/infrastructure/strategies/video-generation.input-builder.ts +90 -0
  74. package/src/domains/generation/wizard/infrastructure/strategies/video-generation.strategy.ts +3 -108
  75. package/src/domains/generation/wizard/infrastructure/strategies/video-generation.types.ts +0 -130
  76. package/src/domains/generation/wizard/infrastructure/strategies/video-generation.validation.ts +136 -0
  77. package/src/domains/generation/wizard/presentation/hooks/photo-upload/index.ts +40 -0
  78. package/src/domains/generation/wizard/presentation/hooks/photo-upload/types.ts +37 -0
  79. package/src/domains/generation/wizard/presentation/hooks/photo-upload/usePhotoUploadStateLogic.ts +142 -0
  80. package/src/domains/generation/wizard/presentation/hooks/use-video-queue-utils.ts +102 -0
  81. package/src/domains/generation/wizard/presentation/hooks/usePhotoBlockingGeneration.handlers.ts +97 -0
  82. package/src/domains/generation/wizard/presentation/hooks/usePhotoBlockingGeneration.saver.ts +54 -0
  83. package/src/domains/generation/wizard/presentation/hooks/usePhotoBlockingGeneration.ts +22 -87
  84. package/src/domains/generation/wizard/presentation/hooks/usePhotoUploadState.ts +8 -177
  85. package/src/domains/generation/wizard/presentation/hooks/useVideoQueueGeneration.ts +1 -295
  86. package/src/domains/generation/wizard/presentation/hooks/useWizardGeneration.ts +1 -1
  87. package/src/domains/generation/wizard/presentation/hooks/video-queue/index.ts +77 -0
  88. package/src/domains/generation/wizard/presentation/hooks/video-queue/use-video-queue-utils.ts +123 -0
  89. package/src/domains/generation/wizard/presentation/hooks/video-queue/useVideoQueueGenerationCallbacks.ts +119 -0
  90. package/src/domains/generation/wizard/presentation/hooks/video-queue/useVideoQueueGenerationPolling.ts +75 -0
  91. package/src/domains/generation/wizard/presentation/hooks/video-queue/useVideoQueueGenerationRefs.ts +65 -0
  92. package/src/domains/generation/wizard/presentation/hooks/video-queue/useVideoQueueGenerationStart.ts +123 -0
  93. package/src/domains/generation/wizard/presentation/hooks/video-queue-index.ts +9 -0
  94. package/src/domains/image-to-video/domain/types/image-to-video-state.types.ts +11 -4
  95. package/src/domains/text-to-image/domain/constants/index.ts +5 -6
  96. package/src/domains/text-to-image/domain/types/text-to-image.types.ts +43 -22
  97. package/src/domains/text-to-video/domain/types/request.types.ts +32 -9
  98. package/src/domains/text-to-video/domain/types/state.types.ts +22 -22
  99. package/src/domains/text-to-video/presentation/hooks/useTextToVideoForm.handlers.ts +44 -0
  100. package/src/domains/text-to-video/presentation/hooks/useTextToVideoForm.ts +5 -51
  101. package/src/domains/text-to-video/presentation/hooks/useTextToVideoForm.types.ts +33 -0
  102. package/src/exports/features.ts +1 -1
  103. package/src/infrastructure/services/generation-orchestrator.service.ts +2 -2
  104. package/src/infrastructure/utils/couple-input-context.ts +13 -0
  105. package/src/infrastructure/utils/couple-input-index.ts +9 -0
  106. package/src/infrastructure/utils/couple-input-photorealistic.ts +40 -0
  107. package/src/infrastructure/utils/couple-input-refiner.ts +101 -0
  108. package/src/infrastructure/utils/couple-input-resolver.ts +71 -0
  109. package/src/infrastructure/utils/couple-input-types.ts +11 -0
  110. package/src/infrastructure/utils/couple-input.util.ts +3 -176
  111. package/src/infrastructure/utils/photo-generation/photo-preparation.util.ts +1 -1
  112. package/src/infrastructure/validation/base-validator.ts +3 -26
  113. package/src/infrastructure/validation/base-validator.types.ts +32 -0
  114. package/src/presentation/hooks/generation/index.ts +1 -1
  115. package/src/presentation/hooks/generation/orchestrator-abort-logs.ts +48 -0
  116. package/src/presentation/hooks/generation/orchestrator-execution-logs.ts +67 -0
  117. package/src/presentation/hooks/generation/orchestrator-index.ts +14 -0
  118. package/src/presentation/hooks/generation/orchestrator-start-logs.ts +65 -0
  119. package/src/presentation/hooks/generation/orchestrator-state-utils.ts +17 -0
  120. package/src/presentation/hooks/generation/orchestrator-types.ts +55 -0
  121. package/src/presentation/hooks/generation/orchestrator-utils-index.ts +29 -0
  122. package/src/presentation/hooks/generation/orchestrator-utils.ts +25 -0
  123. package/src/presentation/hooks/generation/useDualImageGeneration.ts +1 -1
  124. package/src/presentation/hooks/generation/useImageGeneration.ts +1 -1
  125. package/src/presentation/hooks/generation/useVideoGeneration.ts +1 -1
  126. package/src/shared/hooks/factories/generation-hook-index.ts +12 -0
  127. package/src/shared/hooks/factories/generation-hook-types.ts +47 -0
  128. package/src/shared/hooks/factories/generation-hook-utils.ts +94 -0
  129. package/src/shared/hooks/factories/index.ts +1 -1
  130. package/src/shared/index.ts +1 -1
  131. package/src/shared/utils/calculations/aspect-ratio-calculations.ts +30 -0
  132. package/src/shared/utils/calculations/base64-calculations.ts +26 -0
  133. package/src/shared/utils/calculations/confidence-calculations.ts +21 -0
  134. package/src/shared/utils/calculations/cost-calculations-index.ts +43 -0
  135. package/src/shared/utils/calculations/cost-calculations.ts +25 -0
  136. package/src/shared/utils/calculations/credit-calculations.ts +37 -0
  137. package/src/shared/utils/calculations/index.ts +46 -0
  138. package/src/shared/utils/calculations/math-utilities.ts +32 -0
  139. package/src/shared/utils/calculations/memory-calculations.ts +33 -0
  140. package/src/shared/utils/calculations/pagination-calculations.ts +38 -0
  141. package/src/shared/utils/calculations/percentage-calculations.ts +33 -0
  142. package/src/shared/utils/calculations/time-calculations.ts +99 -0
  143. package/src/shared/utils/credit.ts +1 -1
  144. package/src/shared-kernel/application/hooks/index.ts +8 -0
  145. package/src/shared-kernel/application/hooks/use-feature-state.ts +106 -0
  146. package/src/shared-kernel/application/hooks/use-generation-handler.ts +110 -0
  147. package/src/shared-kernel/base-types/base-callbacks.types.ts +73 -0
  148. package/src/shared-kernel/base-types/base-feature-state.types.ts +77 -0
  149. package/src/shared-kernel/base-types/base-generation.types.ts +69 -0
  150. package/src/shared-kernel/base-types/index.ts +30 -0
  151. package/src/shared-kernel/domain/base-generation-strategy.ts +146 -0
  152. package/src/shared-kernel/domain/index.ts +7 -0
  153. package/src/shared-kernel/index.ts +17 -0
  154. package/src/shared-kernel/infrastructure/validation/common-validators.ts +126 -0
  155. package/src/shared-kernel/infrastructure/validation/common-validators.types.ts +33 -0
  156. package/src/shared-kernel/infrastructure/validation/error-handler.ts +52 -0
  157. package/src/shared-kernel/infrastructure/validation/error-handler.types.ts +38 -0
  158. package/src/shared-kernel/infrastructure/validation/error-handler.utils.ts +79 -0
  159. package/src/shared-kernel/infrastructure/validation/index.ts +70 -0
  160. package/src/domains/content-moderation/infrastructure/services/index.ts +0 -8
  161. package/src/domains/creations/domain/constants/index.ts +0 -12
  162. package/src/domains/creations/domain/utils/index.ts +0 -12
  163. package/src/domains/generation/infrastructure/couple-generation-builder.ts +0 -374
  164. package/src/domains/image-to-video/domain/index.ts +0 -2
  165. package/src/domains/image-to-video/infrastructure/index.ts +0 -1
  166. package/src/domains/image-to-video/presentation/index.ts +0 -5
  167. package/src/domains/text-to-video/domain/index.ts +0 -1
  168. package/src/domains/text-to-video/presentation/index.ts +0 -7
  169. package/src/presentation/hooks/generation/orchestrator.ts +0 -276
  170. package/src/shared/hooks/factories/createGenerationHook.ts +0 -253
  171. package/src/shared/utils/calculations.util.ts +0 -366
@@ -1,276 +0,0 @@
1
- /**
2
- * Generation Orchestrator
3
- * Handles AI generation execution with network check, moderation, credit deduction, and error handling
4
- */
5
-
6
- import { useState, useCallback, useRef, useEffect } from "react";
7
- import { useAlert } from "@umituz/react-native-design-system/molecules";
8
- import { useOfflineStore } from "@umituz/react-native-design-system/offline";
9
- import { createGenerationError, getAlertMessage, parseError } from "./errors";
10
- import { handleModeration } from "./moderation-handler";
11
- import type {
12
- GenerationStrategy,
13
- GenerationConfig,
14
- GenerationState,
15
- GenerationError,
16
- UseGenerationOrchestratorReturn,
17
- } from "./types";
18
-
19
- const getInitialState = <T>(): GenerationState<T> => ({
20
- status: "idle",
21
- isGenerating: false,
22
- result: null,
23
- error: null,
24
- });
25
-
26
- export const useGenerationOrchestrator = <TInput, TResult>(
27
- strategy: GenerationStrategy<TInput, TResult>,
28
- config: GenerationConfig,
29
- ): UseGenerationOrchestratorReturn<TInput, TResult> => {
30
- const { userId, alertMessages, onSuccess, onError, moderation, lifecycle } = config;
31
-
32
- const [state, setState] = useState<GenerationState<TResult>>(getInitialState<TResult>());
33
- const isGeneratingRef = useRef(false);
34
- const isMountedRef = useRef(true);
35
- const abortControllerRef = useRef<AbortController | null>(null);
36
- const cleanupTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
37
-
38
- // Stable refs for callbacks — prevents useCallback deps from thrashing when
39
- // callers pass inline functions (which create new references every render).
40
- const onSuccessRef = useRef(onSuccess);
41
- const onErrorRef = useRef(onError);
42
- // Update refs in render body (not useEffect) so they're always in sync — no 1-frame delay
43
- onSuccessRef.current = onSuccess;
44
- onErrorRef.current = onError;
45
-
46
- const offlineStore = useOfflineStore();
47
- const { showError, showSuccess } = useAlert();
48
-
49
- useEffect(() => {
50
- isMountedRef.current = true;
51
- return () => {
52
- isMountedRef.current = false;
53
- abortControllerRef.current?.abort();
54
- // Clear any pending lifecycle complete timeout
55
- if (cleanupTimeoutRef.current) {
56
- clearTimeout(cleanupTimeoutRef.current);
57
- cleanupTimeoutRef.current = null;
58
- }
59
- };
60
- }, []);
61
-
62
- const handleLifecycleComplete = useCallback(
63
- (status: "success" | "error", result?: TResult, error?: GenerationError) => {
64
- if (!lifecycle?.onComplete) return;
65
-
66
- // Clear any existing timeout first
67
- if (cleanupTimeoutRef.current) {
68
- clearTimeout(cleanupTimeoutRef.current);
69
- cleanupTimeoutRef.current = null;
70
- }
71
-
72
- const delay = lifecycle.completeDelay ?? 500;
73
- cleanupTimeoutRef.current = setTimeout(() => {
74
- if (isMountedRef.current) {
75
- lifecycle.onComplete?.(status, result, error);
76
- }
77
- cleanupTimeoutRef.current = null;
78
- }, delay);
79
- },
80
- [lifecycle],
81
- );
82
-
83
- const executeGeneration = useCallback(
84
- async (input: TInput) => {
85
- if (typeof __DEV__ !== "undefined" && __DEV__) {
86
- console.log("[Orchestrator] ----------------------------------------");
87
- console.log("[Orchestrator] executeGeneration() called");
88
- }
89
-
90
- // Check abort signal before starting
91
- if (abortControllerRef.current?.signal.aborted) {
92
- if (typeof __DEV__ !== "undefined" && __DEV__) {
93
- console.log("[Orchestrator] Aborted before generation started");
94
- }
95
- throw new Error("Generation aborted");
96
- }
97
-
98
- setState((prev) => ({ ...prev, status: "generating" }));
99
- if (typeof __DEV__ !== "undefined" && __DEV__) {
100
- console.log("[Orchestrator] State: generating - calling strategy.execute()");
101
- }
102
-
103
- const result = await strategy.execute(input);
104
-
105
- // Check abort signal after execution
106
- if (abortControllerRef.current?.signal.aborted) {
107
- if (typeof __DEV__ !== "undefined" && __DEV__) {
108
- console.log("[Orchestrator] Aborted after generation completed");
109
- }
110
- throw new Error("Generation aborted");
111
- }
112
-
113
- if (typeof __DEV__ !== "undefined" && __DEV__) {
114
- console.log("[Orchestrator] strategy.execute() completed");
115
- }
116
-
117
- if (strategy.save && userId) {
118
- // Check abort signal before save
119
- if (abortControllerRef.current?.signal.aborted) {
120
- if (typeof __DEV__ !== "undefined" && __DEV__) {
121
- console.log("[Orchestrator] Aborted before save");
122
- }
123
- throw new Error("Generation aborted");
124
- }
125
-
126
- if (isMountedRef.current) setState((prev) => ({ ...prev, status: "saving" }));
127
- if (typeof __DEV__ !== "undefined" && __DEV__) {
128
- console.log("[Orchestrator] Saving result to Firestore");
129
- }
130
- try {
131
- await strategy.save(result, userId);
132
- if (typeof __DEV__ !== "undefined" && __DEV__) {
133
- console.log("[Orchestrator] Result saved successfully");
134
- }
135
- } catch (saveErr) {
136
- if (typeof __DEV__ !== "undefined" && __DEV__) {
137
- console.log("[Orchestrator] ERROR: Save failed:", saveErr);
138
- }
139
- // Update state to error on save failure
140
- if (isMountedRef.current) {
141
- setState((prev) => ({ ...prev, status: "error", isGenerating: false }));
142
- }
143
- throw createGenerationError("save", alertMessages.saveFailed, saveErr instanceof Error ? saveErr : undefined);
144
- }
145
- }
146
-
147
- // Final abort check before success
148
- if (abortControllerRef.current?.signal.aborted) {
149
- if (typeof __DEV__ !== "undefined" && __DEV__) {
150
- console.log("[Orchestrator] Aborted before success callback");
151
- }
152
- throw new Error("Generation aborted");
153
- }
154
-
155
- if (isMountedRef.current) setState({ status: "success", isGenerating: false, result, error: null });
156
- if (typeof __DEV__ !== "undefined" && __DEV__) {
157
- console.log("[Orchestrator] ✅ Generation SUCCESS");
158
- console.log("[Orchestrator] ========================================");
159
- }
160
-
161
- if (alertMessages.success) showSuccess("Success", alertMessages.success);
162
- await onSuccessRef.current?.(result);
163
- handleLifecycleComplete("success", result);
164
- return result;
165
- },
166
- [strategy, userId, alertMessages, showSuccess, handleLifecycleComplete],
167
- );
168
-
169
- const generate = useCallback(
170
- async (input: TInput): Promise<TResult | void> => {
171
- if (typeof __DEV__ !== "undefined" && __DEV__) {
172
- console.log("[Orchestrator] ========================================");
173
- console.log("[Orchestrator] generate() called with input:", JSON.stringify(input).substring(0, 200));
174
- console.log("[Orchestrator] isGenerating:", isGeneratingRef.current);
175
- console.log("[Orchestrator] userId:", userId);
176
- }
177
-
178
- if (isGeneratingRef.current) {
179
- if (typeof __DEV__ !== "undefined" && __DEV__) {
180
- console.log("[Orchestrator] BLOCKED: Already generating");
181
- }
182
- return;
183
- }
184
-
185
- // Create new AbortController for this generation
186
- abortControllerRef.current = new AbortController();
187
- isGeneratingRef.current = true;
188
- let moderationPending = false;
189
- setState({ ...getInitialState<TResult>(), status: "checking", isGenerating: true });
190
-
191
- if (typeof __DEV__ !== "undefined" && __DEV__) {
192
- console.log("[Orchestrator] State set to 'checking', isGenerating: true");
193
- }
194
-
195
- try {
196
- // Check online status inside the try block to avoid dependency on offlineStore.isOnline
197
- if (!offlineStore.isOnline) {
198
- if (typeof __DEV__ !== "undefined" && __DEV__) {
199
- console.log("[Orchestrator] ERROR: User is offline");
200
- }
201
- throw createGenerationError("network", alertMessages.networkError);
202
- }
203
-
204
- if (typeof __DEV__ !== "undefined" && __DEV__) {
205
- console.log("[Orchestrator] Online check passed");
206
- }
207
-
208
- // Check if aborted before moderation
209
- if (abortControllerRef.current.signal.aborted) {
210
- if (typeof __DEV__ !== "undefined" && __DEV__) {
211
- console.log("[Orchestrator] ERROR: Generation aborted (2)");
212
- }
213
- throw new Error("Generation aborted");
214
- }
215
-
216
- if (typeof __DEV__ !== "undefined" && __DEV__) {
217
- console.log("[Orchestrator] Starting moderation check");
218
- }
219
-
220
- const result = await handleModeration({
221
- input,
222
- moderation,
223
- alertMessages,
224
- isMountedRef,
225
- isGeneratingRef,
226
- setState: (s) => setState(s as GenerationState<TResult>),
227
- resetState: () => setState(getInitialState<TResult>()),
228
- executeGeneration,
229
- showError,
230
- onError,
231
- handleLifecycleComplete,
232
- });
233
-
234
- // If handleModeration returned undefined, the warning dialog was shown.
235
- // The dialog's proceed/cancel callbacks now own isGeneratingRef — don't reset in finally.
236
- if (result === undefined && moderation) {
237
- moderationPending = true;
238
- }
239
-
240
- return result;
241
- } catch (err) {
242
- // Don't show error if aborted
243
- if (abortControllerRef.current?.signal.aborted) {
244
- if (typeof __DEV__ !== "undefined" && __DEV__) {
245
- console.log("[Orchestrator] Generation aborted");
246
- }
247
- return;
248
- }
249
-
250
- const error = parseError(err);
251
- if (typeof __DEV__ !== "undefined" && __DEV__) console.log("[Orchestrator] Error:", error);
252
- if (isMountedRef.current) setState({ status: "error", isGenerating: false, result: null, error });
253
- showError("Error", getAlertMessage(error, alertMessages));
254
- await onErrorRef.current?.(error);
255
- handleLifecycleComplete("error", undefined, error);
256
- throw error;
257
- } finally {
258
- // Only reset if moderation dialog did not take ownership
259
- if (!moderationPending) {
260
- isGeneratingRef.current = false;
261
- }
262
- abortControllerRef.current = null;
263
- }
264
- },
265
- [offlineStore, moderation, alertMessages, strategy, executeGeneration, showError, handleLifecycleComplete],
266
- );
267
-
268
- const reset = useCallback(() => {
269
- abortControllerRef.current?.abort();
270
- abortControllerRef.current = null;
271
- setState(getInitialState<TResult>());
272
- isGeneratingRef.current = false;
273
- }, []);
274
-
275
- return { generate, reset, status: state.status, isGenerating: state.isGenerating, result: state.result, error: state.error };
276
- };
@@ -1,253 +0,0 @@
1
- /**
2
- * Generic Generation Hook Factory
3
- * Creates type-safe generation hooks with error handling, progress tracking, and abort support
4
- */
5
-
6
- import { useState, useCallback, useRef, useEffect } from "react";
7
-
8
- /**
9
- * Generation state
10
- */
11
- export interface GenerationState {
12
- isGenerating: boolean;
13
- progress: number;
14
- error: string | null;
15
- }
16
-
17
- /**
18
- * Generation callbacks
19
- */
20
- export interface GenerationCallbacks<TResult> {
21
- /** Called when generation succeeds */
22
- onSuccess?: (result: TResult) => void;
23
- /** Called when generation fails */
24
- onError?: (error: string) => void;
25
- /** Called on progress update */
26
- onProgress?: (progress: number) => void;
27
- }
28
-
29
- /**
30
- * Generation hook configuration
31
- */
32
- export interface GenerationHookConfig<TRequest, TResult> {
33
- /** Execute the generation request */
34
- execute: (request: TRequest, signal?: AbortSignal) => Promise<TResult>;
35
- /** Optional validation before execution */
36
- validate?: (request: TRequest) => string | null;
37
- /** Optional transform for errors */
38
- transformError?: (error: unknown) => string;
39
- }
40
-
41
- /**
42
- * Generation hook return type
43
- */
44
- export interface GenerationHookReturn<TRequest, TResult> {
45
- generationState: GenerationState;
46
- handleGenerate: (request: TRequest) => Promise<TResult | null>;
47
- setProgress: (progress: number) => void;
48
- setError: (error: string | null) => void;
49
- abort: () => void;
50
- }
51
-
52
- const INITIAL_STATE: GenerationState = {
53
- isGenerating: false,
54
- progress: 0,
55
- error: null,
56
- };
57
-
58
- /**
59
- * Creates a type-safe generation hook
60
- * @param config - Generation hook configuration
61
- * @param callbacks - Generation callbacks
62
- * @returns Generation hook
63
- *
64
- * @example
65
- * ```ts
66
- * const useMyGeneration = createGenerationHook({
67
- * execute: async (request) => {
68
- * return await api.generate(request);
69
- * },
70
- * validate: (request) => {
71
- * if (!request.prompt) return "Prompt is required";
72
- * return null;
73
- * },
74
- * });
75
- *
76
- * // Usage
77
- * const { generationState, handleGenerate } = useMyGeneration({
78
- * onSuccess: (result) => console.log("Success!", result),
79
- * onError: (error) => console.error("Error:", error),
80
- * });
81
- * ```
82
- */
83
- export function createGenerationHook<TRequest, TResult>(
84
- config: GenerationHookConfig<TRequest, TResult>
85
- ) {
86
- return function useGeneration(
87
- callbacks: GenerationCallbacks<TResult> = {}
88
- ): GenerationHookReturn<TRequest, TResult> {
89
- const [generationState, setGenerationState] = useState<GenerationState>(INITIAL_STATE);
90
-
91
- const abortControllerRef = useRef<AbortController | null>(null);
92
- const isMountedRef = useRef(true);
93
-
94
- // Stabilize callbacks
95
- const onSuccessRef = useRef(callbacks.onSuccess);
96
- const onErrorRef = useRef(callbacks.onError);
97
- const onProgressRef = useRef(callbacks.onProgress);
98
-
99
- useEffect(() => {
100
- onSuccessRef.current = callbacks.onSuccess;
101
- onErrorRef.current = callbacks.onError;
102
- onProgressRef.current = callbacks.onProgress;
103
- }, [callbacks.onSuccess, callbacks.onError, callbacks.onProgress]);
104
-
105
- // Cleanup on unmount
106
- useEffect(() => {
107
- isMountedRef.current = true;
108
- return () => {
109
- isMountedRef.current = false;
110
- abortControllerRef.current?.abort();
111
- };
112
- }, []);
113
-
114
- const setProgress = useCallback((progress: number) => {
115
- if (!isMountedRef.current) return;
116
- setGenerationState((prev) => ({ ...prev, progress }));
117
- onProgressRef.current?.(progress);
118
- }, []);
119
-
120
- const setError = useCallback((error: string | null) => {
121
- if (!isMountedRef.current) return;
122
- setGenerationState((prev) => ({ ...prev, error, isGenerating: false }));
123
- if (error) {
124
- onErrorRef.current?.(error);
125
- }
126
- }, []);
127
-
128
- const abort = useCallback(() => {
129
- abortControllerRef.current?.abort();
130
- if (isMountedRef.current) {
131
- setGenerationState((prev) => ({
132
- ...prev,
133
- isGenerating: false,
134
- error: "Generation aborted",
135
- }));
136
- }
137
- }, []);
138
-
139
- const handleGenerate = useCallback(
140
- async (request: TRequest): Promise<TResult | null> => {
141
- // Validate request
142
- if (config.validate) {
143
- const validationError = config.validate(request);
144
- if (validationError) {
145
- setError(validationError);
146
- return null;
147
- }
148
- }
149
-
150
- // Create new AbortController
151
- abortControllerRef.current = new AbortController();
152
-
153
- setGenerationState({
154
- isGenerating: true,
155
- progress: 0,
156
- error: null,
157
- });
158
-
159
- try {
160
- const result = await config.execute(
161
- request,
162
- abortControllerRef.current.signal
163
- );
164
-
165
- if (!isMountedRef.current || abortControllerRef.current.signal.aborted) {
166
- return null;
167
- }
168
-
169
- setGenerationState((prev) => ({
170
- ...prev,
171
- isGenerating: false,
172
- progress: 100
173
- }));
174
-
175
- onSuccessRef.current?.(result);
176
- return result;
177
- } catch (error) {
178
- if (!isMountedRef.current || abortControllerRef.current.signal.aborted) {
179
- return null;
180
- }
181
-
182
- const errorMessage = config.transformError
183
- ? config.transformError(error)
184
- : error instanceof Error
185
- ? error.message
186
- : String(error);
187
-
188
- setError(errorMessage);
189
- return null;
190
- } finally {
191
- abortControllerRef.current = null;
192
- }
193
- },
194
- [config, setError]
195
- );
196
-
197
- return {
198
- generationState,
199
- handleGenerate,
200
- setProgress,
201
- setError,
202
- abort,
203
- };
204
- };
205
- }
206
-
207
- /**
208
- * Creates a generation hook with progress updates
209
- * Useful when the generation API supports progress callbacks
210
- */
211
- export function createGenerationHookWithProgress<TRequest, TResult>(
212
- config: GenerationHookConfig<TRequest, TResult> & {
213
- /** Get progress stream or polling function */
214
- subscribeToProgress?: (
215
- request: TRequest,
216
- onProgress: (progress: number) => void
217
- ) => () => void;
218
- }
219
- ) {
220
- const baseHook = createGenerationHook(config);
221
-
222
- return function useGenerationWithProgress(
223
- callbacks: GenerationCallbacks<TResult> = {}
224
- ): GenerationHookReturn<TRequest, TResult> {
225
- const hookResult = baseHook(callbacks);
226
- const unsubscribeRef = useRef<(() => void) | null>(null);
227
-
228
- const handleGenerateWithProgress = useCallback(
229
- async (request: TRequest): Promise<TResult | null> => {
230
- // Subscribe to progress if available
231
- if (config.subscribeToProgress) {
232
- unsubscribeRef.current = config.subscribeToProgress(
233
- request,
234
- hookResult.setProgress
235
- );
236
- }
237
-
238
- try {
239
- return await hookResult.handleGenerate(request);
240
- } finally {
241
- unsubscribeRef.current?.();
242
- unsubscribeRef.current = null;
243
- }
244
- },
245
- [hookResult, config.subscribeToProgress]
246
- );
247
-
248
- return {
249
- ...hookResult,
250
- handleGenerate: handleGenerateWithProgress,
251
- };
252
- };
253
- }