@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 +1 -1
- package/src/domain/entities/index.ts +1 -0
- package/src/domain/entities/middleware.types.ts +56 -0
- package/src/index.ts +9 -0
- package/src/infrastructure/services/generation-orchestrator.service.ts +52 -0
- package/src/infrastructure/services/generation-wrapper.service.ts +148 -0
- package/src/infrastructure/services/index.ts +5 -0
- package/src/infrastructure/services/provider-registry.service.ts +24 -1
package/package.json
CHANGED
|
@@ -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
|
-
|
|
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 {
|