@umituz/react-native-ai-generation-content 1.1.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-ai-generation-content",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "Provider-agnostic AI generation orchestration for React Native",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -7,3 +7,4 @@ export * from "./error.types";
7
7
  export * from "./generation.types";
8
8
  export * from "./polling.types";
9
9
  export * from "./progress.types";
10
+ export * from "./middleware.types";
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Middleware Types
3
+ * Generic middleware pattern for generation workflow
4
+ */
5
+
6
+ import type { GenerationRequest, GenerationResult } from "./generation.types";
7
+
8
+ /**
9
+ * Context passed to middleware hooks
10
+ */
11
+ export interface MiddlewareContext {
12
+ request: GenerationRequest;
13
+ userId?: string;
14
+ metadata?: Record<string, unknown>;
15
+ }
16
+
17
+ /**
18
+ * Result context passed to afterGenerate hook
19
+ */
20
+ export interface MiddlewareResultContext<T> extends MiddlewareContext {
21
+ result: GenerationResult<T>;
22
+ }
23
+
24
+ /**
25
+ * Middleware hook executed before generation
26
+ * Can throw error to prevent generation
27
+ */
28
+ export type BeforeGenerateHook = (
29
+ context: MiddlewareContext,
30
+ ) => Promise<void> | void;
31
+
32
+ /**
33
+ * Middleware hook executed after generation (success or failure)
34
+ * Cannot modify result, used for logging/tracking
35
+ */
36
+ export type AfterGenerateHook<T = unknown> = (
37
+ context: MiddlewareResultContext<T>,
38
+ ) => Promise<void> | void;
39
+
40
+ /**
41
+ * Complete middleware configuration
42
+ */
43
+ export interface GenerationMiddleware {
44
+ /** Hook executed before generation starts */
45
+ beforeGenerate?: BeforeGenerateHook;
46
+ /** Hook executed after generation completes (success or failure) */
47
+ afterGenerate?: AfterGenerateHook;
48
+ }
49
+
50
+ /**
51
+ * Middleware chain configuration
52
+ */
53
+ export interface MiddlewareChain {
54
+ /** Array of middleware to execute in order */
55
+ middleware: GenerationMiddleware[];
56
+ }
package/src/index.ts CHANGED
@@ -42,6 +42,12 @@ export type {
42
42
  PollingOptions,
43
43
  ProgressStageConfig,
44
44
  ProgressConfig,
45
+ MiddlewareContext,
46
+ MiddlewareResultContext,
47
+ BeforeGenerateHook,
48
+ AfterGenerateHook,
49
+ GenerationMiddleware,
50
+ MiddlewareChain,
45
51
  } from "./domain/entities";
46
52
 
47
53
  export { DEFAULT_POLLING_CONFIG, DEFAULT_PROGRESS_STAGES } from "./domain/entities";
@@ -55,12 +61,15 @@ export {
55
61
  generationOrchestrator,
56
62
  pollJob,
57
63
  createJobPoller,
64
+ generationWrapper,
65
+ createGenerationWrapper,
58
66
  } from "./infrastructure/services";
59
67
 
60
68
  export type {
61
69
  OrchestratorConfig,
62
70
  PollJobOptions,
63
71
  PollJobResult,
72
+ WrapperConfig,
64
73
  } from "./infrastructure/services";
65
74
 
66
75
  // =============================================================================
@@ -30,6 +30,13 @@ class GenerationOrchestratorService {
30
30
  private config: OrchestratorConfig = {};
31
31
 
32
32
  configure(config: OrchestratorConfig): void {
33
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
34
+ // eslint-disable-next-line no-console
35
+ console.log("[Orchestrator] configure() called", {
36
+ hasPollingConfig: !!config.polling,
37
+ hasStatusUpdate: !!config.onStatusUpdate,
38
+ });
39
+ }
33
40
  this.config = { ...this.config, ...config };
34
41
  }
35
42
 
@@ -139,6 +146,15 @@ class GenerationOrchestratorService {
139
146
  requestId: string,
140
147
  onProgress?: (progress: GenerationProgress) => void,
141
148
  ): Promise<T> {
149
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
150
+ // eslint-disable-next-line no-console
151
+ console.log("[Orchestrator] pollForResult() started", {
152
+ provider: provider.providerId,
153
+ model,
154
+ requestId,
155
+ });
156
+ }
157
+
142
158
  const config = {
143
159
  ...DEFAULT_POLLING_CONFIG,
144
160
  ...this.config.polling,
@@ -149,6 +165,14 @@ class GenerationOrchestratorService {
149
165
  for (let attempt = 0; attempt < config.maxAttempts; attempt++) {
150
166
  await createPollingDelay(attempt, config);
151
167
 
168
+ if (typeof __DEV__ !== "undefined" && __DEV__ && attempt % 5 === 0) {
169
+ // eslint-disable-next-line no-console
170
+ console.log("[Orchestrator] pollForResult() attempt", {
171
+ attempt,
172
+ maxAttempts: config.maxAttempts,
173
+ });
174
+ }
175
+
152
176
  try {
153
177
  const status = await provider.getJobStatus(model, requestId);
154
178
 
@@ -157,6 +181,13 @@ class GenerationOrchestratorService {
157
181
  this.updateProgressFromStatus(status, attempt, config, onProgress);
158
182
 
159
183
  if (status.status === "COMPLETED") {
184
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
185
+ // eslint-disable-next-line no-console
186
+ console.log("[Orchestrator] pollForResult() job COMPLETED", {
187
+ requestId,
188
+ attempt,
189
+ });
190
+ }
160
191
  return provider.getJobResult<T>(model, requestId);
161
192
  }
162
193
 
@@ -214,20 +245,41 @@ class GenerationOrchestratorService {
214
245
  }
215
246
 
216
247
  private getProvider(): IAIProvider {
248
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
249
+ // eslint-disable-next-line no-console
250
+ console.log("[Orchestrator] getProvider() called");
251
+ }
252
+
217
253
  const provider = providerRegistry.getActiveProvider();
218
254
 
219
255
  if (!provider) {
256
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
257
+ // eslint-disable-next-line no-console
258
+ console.error("[Orchestrator] No active provider found!");
259
+ }
220
260
  throw new Error(
221
261
  "No active AI provider. Register and set a provider first.",
222
262
  );
223
263
  }
224
264
 
225
265
  if (!provider.isInitialized()) {
266
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
267
+ // eslint-disable-next-line no-console
268
+ console.error("[Orchestrator] Provider not initialized:", provider.providerId);
269
+ }
226
270
  throw new Error(
227
271
  `Provider ${provider.providerId} is not initialized.`,
228
272
  );
229
273
  }
230
274
 
275
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
276
+ // eslint-disable-next-line no-console
277
+ console.log("[Orchestrator] getProvider() returning:", {
278
+ providerId: provider.providerId,
279
+ isInitialized: provider.isInitialized(),
280
+ });
281
+ }
282
+
231
283
  return provider;
232
284
  }
233
285
  }
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Generation Wrapper Service
3
+ * Wraps orchestrator with middleware support
4
+ * Enables credit checking, moderation, history via middleware pattern
5
+ */
6
+
7
+ import type {
8
+ GenerationRequest,
9
+ GenerationResult,
10
+ GenerationMiddleware,
11
+ MiddlewareContext,
12
+ MiddlewareResultContext,
13
+ } from "../../domain/entities";
14
+ import { generationOrchestrator } from "./generation-orchestrator.service";
15
+ import type { OrchestratorConfig } from "./generation-orchestrator.service";
16
+
17
+ export interface WrapperConfig {
18
+ /** Middleware to execute before/after generation */
19
+ middleware?: GenerationMiddleware[];
20
+ /** Orchestrator configuration */
21
+ orchestratorConfig?: OrchestratorConfig;
22
+ }
23
+
24
+ class GenerationWrapperService {
25
+ private middleware: GenerationMiddleware[] = [];
26
+ private orchestratorConfig?: OrchestratorConfig;
27
+
28
+ /**
29
+ * Configure wrapper with middleware
30
+ */
31
+ configure(config: WrapperConfig): void {
32
+ this.middleware = config.middleware || [];
33
+ this.orchestratorConfig = config.orchestratorConfig;
34
+
35
+ if (this.orchestratorConfig) {
36
+ generationOrchestrator.configure(this.orchestratorConfig);
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Add middleware to chain
42
+ */
43
+ use(middleware: GenerationMiddleware): void {
44
+ this.middleware.push(middleware);
45
+ }
46
+
47
+ /**
48
+ * Clear all middleware
49
+ */
50
+ clearMiddleware(): void {
51
+ this.middleware = [];
52
+ }
53
+
54
+ /**
55
+ * Generate with middleware support
56
+ */
57
+ async generate<T = unknown>(
58
+ request: GenerationRequest,
59
+ userId?: string,
60
+ metadata?: Record<string, unknown>,
61
+ ): Promise<GenerationResult<T>> {
62
+ const startTime = Date.now();
63
+
64
+ const context: MiddlewareContext = {
65
+ request,
66
+ userId,
67
+ metadata,
68
+ };
69
+
70
+ try {
71
+ await this.executeBeforeHooks(context);
72
+
73
+ const result = await generationOrchestrator.generate<T>(request);
74
+
75
+ const resultContext: MiddlewareResultContext<T> = {
76
+ ...context,
77
+ result,
78
+ };
79
+
80
+ await this.executeAfterHooks(resultContext);
81
+
82
+ return result;
83
+ } catch (error) {
84
+ const errorResult: GenerationResult<T> = {
85
+ success: false,
86
+ error: error instanceof Error ? error.message : String(error),
87
+ metadata: {
88
+ model: request.model || "unknown",
89
+ startTime,
90
+ endTime: Date.now(),
91
+ duration: Date.now() - startTime,
92
+ },
93
+ };
94
+
95
+ const resultContext: MiddlewareResultContext<T> = {
96
+ ...context,
97
+ result: errorResult,
98
+ };
99
+
100
+ await this.executeAfterHooks(resultContext).catch(() => {
101
+ // Silent fail on afterHooks error
102
+ });
103
+
104
+ return errorResult;
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Execute all beforeGenerate hooks
110
+ */
111
+ private async executeBeforeHooks(
112
+ context: MiddlewareContext,
113
+ ): Promise<void> {
114
+ for (const mw of this.middleware) {
115
+ if (mw.beforeGenerate) {
116
+ await mw.beforeGenerate(context);
117
+ }
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Execute all afterGenerate hooks
123
+ */
124
+ private async executeAfterHooks<T>(
125
+ context: MiddlewareResultContext<T>,
126
+ ): Promise<void> {
127
+ for (const mw of this.middleware) {
128
+ if (mw.afterGenerate) {
129
+ await mw.afterGenerate(context);
130
+ }
131
+ }
132
+ }
133
+ }
134
+
135
+ export const generationWrapper = new GenerationWrapperService();
136
+
137
+ /**
138
+ * Create new wrapper instance
139
+ */
140
+ export function createGenerationWrapper(
141
+ config?: WrapperConfig,
142
+ ): GenerationWrapperService {
143
+ const wrapper = new GenerationWrapperService();
144
+ if (config) {
145
+ wrapper.configure(config);
146
+ }
147
+ return wrapper;
148
+ }
@@ -7,3 +7,8 @@ export { generationOrchestrator } from "./generation-orchestrator.service";
7
7
  export type { OrchestratorConfig } from "./generation-orchestrator.service";
8
8
  export { pollJob, createJobPoller } from "./job-poller.service";
9
9
  export type { PollJobOptions, PollJobResult } from "./job-poller.service";
10
+ export {
11
+ generationWrapper,
12
+ createGenerationWrapper,
13
+ } from "./generation-wrapper.service";
14
+ export type { WrapperConfig } from "./generation-wrapper.service";
@@ -52,10 +52,33 @@ class ProviderRegistry {
52
52
  }
53
53
 
54
54
  getActiveProvider(): IAIProvider | null {
55
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
56
+ // eslint-disable-next-line no-console
57
+ console.log("[ProviderRegistry] getActiveProvider() called", {
58
+ activeProviderId: this.activeProviderId,
59
+ registeredProviders: Array.from(this.providers.keys()),
60
+ });
61
+ }
62
+
55
63
  if (!this.activeProviderId) {
64
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
65
+ // eslint-disable-next-line no-console
66
+ console.warn("[ProviderRegistry] No active provider set!");
67
+ }
56
68
  return null;
57
69
  }
58
- return this.providers.get(this.activeProviderId) ?? null;
70
+
71
+ const provider = this.providers.get(this.activeProviderId) ?? null;
72
+
73
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
74
+ // eslint-disable-next-line no-console
75
+ console.log("[ProviderRegistry] getActiveProvider() returning", {
76
+ providerId: provider?.providerId,
77
+ isInitialized: provider?.isInitialized(),
78
+ });
79
+ }
80
+
81
+ return provider;
59
82
  }
60
83
 
61
84
  getProvider(providerId: string): IAIProvider | null {