@loonylabs/tti-middleware 1.1.1 → 1.2.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/README.md +609 -602
- package/dist/middleware/services/tti/providers/base-tti-provider.d.ts +17 -5
- package/dist/middleware/services/tti/providers/base-tti-provider.js +82 -21
- package/dist/middleware/services/tti/providers/google-cloud-provider.js +2 -2
- package/dist/middleware/types/index.d.ts +28 -8
- package/dist/middleware/types/index.js +6 -3
- package/package.json +90 -90
|
@@ -84,24 +84,36 @@ export declare abstract class BaseTTIProvider implements ITTIProvider {
|
|
|
84
84
|
* Validate that the request is valid
|
|
85
85
|
*/
|
|
86
86
|
protected validateRequest(request: TTIRequest): void;
|
|
87
|
+
/** Resolved retry config type (without deprecated fields) */
|
|
88
|
+
protected static readonly RESOLVED_RETRY_DEFAULTS: Required<Omit<RetryOptions, "incrementalBackoff">>;
|
|
87
89
|
/**
|
|
88
90
|
* Resolve retry configuration from request
|
|
89
91
|
*/
|
|
90
|
-
protected resolveRetryConfig(request: TTIRequest): Required<RetryOptions
|
|
92
|
+
protected resolveRetryConfig(request: TTIRequest): Required<Omit<RetryOptions, 'incrementalBackoff'>> | null;
|
|
91
93
|
/**
|
|
92
|
-
* Calculate delay for a specific retry attempt
|
|
94
|
+
* Calculate delay for a specific retry attempt using exponential backoff.
|
|
95
|
+
* Formula: min(delayMs * backoffMultiplier^(attempt-1), maxDelayMs)
|
|
96
|
+
* With optional jitter: random value between 0 and computed delay.
|
|
93
97
|
*/
|
|
94
|
-
protected calculateRetryDelay(attempt: number, config: Required<RetryOptions
|
|
98
|
+
protected calculateRetryDelay(attempt: number, config: Required<Omit<RetryOptions, 'incrementalBackoff'>>): number;
|
|
95
99
|
/**
|
|
96
100
|
* Sleep for a specified duration
|
|
97
101
|
*/
|
|
98
102
|
protected sleep(ms: number): Promise<void>;
|
|
99
103
|
/**
|
|
100
|
-
* Execute a generation function with retry logic for
|
|
104
|
+
* Execute a generation function with retry logic for transient errors.
|
|
105
|
+
* Retries on: 429, 408, 5xx, network timeouts, TCP disconnects.
|
|
106
|
+
* Does NOT retry on: 400, 401, 403, and other client errors.
|
|
101
107
|
*/
|
|
102
108
|
protected executeWithRetry<T>(request: TTIRequest, operation: () => Promise<T>, operationName: string): Promise<T>;
|
|
103
109
|
/**
|
|
104
|
-
* Check if an error is
|
|
110
|
+
* Check if an error is retryable (transient).
|
|
111
|
+
* Retryable: 429, 408, 500, 502, 503, 504, network errors, timeouts.
|
|
112
|
+
* Not retryable: 400, 401, 403, and other client errors.
|
|
113
|
+
*/
|
|
114
|
+
protected isRetryableError(error: Error): boolean;
|
|
115
|
+
/**
|
|
116
|
+
* @deprecated Use isRetryableError() instead
|
|
105
117
|
*/
|
|
106
118
|
protected isRateLimitError(error: Error): boolean;
|
|
107
119
|
/**
|
|
@@ -220,9 +220,6 @@ class BaseTTIProvider {
|
|
|
220
220
|
}
|
|
221
221
|
}
|
|
222
222
|
}
|
|
223
|
-
// ============================================================
|
|
224
|
-
// RETRY LOGIC
|
|
225
|
-
// ============================================================
|
|
226
223
|
/**
|
|
227
224
|
* Resolve retry configuration from request
|
|
228
225
|
*/
|
|
@@ -236,23 +233,36 @@ class BaseTTIProvider {
|
|
|
236
233
|
if (retryOption === undefined || retryOption === true) {
|
|
237
234
|
return { ...types_1.DEFAULT_RETRY_OPTIONS };
|
|
238
235
|
}
|
|
236
|
+
// Handle deprecated incrementalBackoff
|
|
237
|
+
let backoffMultiplier = retryOption.backoffMultiplier ?? types_1.DEFAULT_RETRY_OPTIONS.backoffMultiplier;
|
|
238
|
+
if (retryOption.incrementalBackoff !== undefined && retryOption.backoffMultiplier === undefined) {
|
|
239
|
+
// Legacy: incrementalBackoff=true mapped to linear scaling (multiplier 1.0)
|
|
240
|
+
backoffMultiplier = retryOption.incrementalBackoff ? 1.0 : 1.0;
|
|
241
|
+
}
|
|
239
242
|
// Custom configuration: merge with defaults
|
|
240
243
|
return {
|
|
241
244
|
maxRetries: retryOption.maxRetries ?? types_1.DEFAULT_RETRY_OPTIONS.maxRetries,
|
|
242
245
|
delayMs: retryOption.delayMs ?? types_1.DEFAULT_RETRY_OPTIONS.delayMs,
|
|
243
|
-
|
|
246
|
+
backoffMultiplier,
|
|
247
|
+
maxDelayMs: retryOption.maxDelayMs ?? types_1.DEFAULT_RETRY_OPTIONS.maxDelayMs,
|
|
248
|
+
jitter: retryOption.jitter ?? types_1.DEFAULT_RETRY_OPTIONS.jitter,
|
|
244
249
|
};
|
|
245
250
|
}
|
|
246
251
|
/**
|
|
247
|
-
* Calculate delay for a specific retry attempt
|
|
252
|
+
* Calculate delay for a specific retry attempt using exponential backoff.
|
|
253
|
+
* Formula: min(delayMs * backoffMultiplier^(attempt-1), maxDelayMs)
|
|
254
|
+
* With optional jitter: random value between 0 and computed delay.
|
|
248
255
|
*/
|
|
249
256
|
calculateRetryDelay(attempt, config) {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
257
|
+
// Exponential backoff: delayMs * multiplier^(attempt-1)
|
|
258
|
+
const exponentialDelay = config.delayMs * Math.pow(config.backoffMultiplier, attempt - 1);
|
|
259
|
+
// Cap at maxDelayMs
|
|
260
|
+
const cappedDelay = Math.min(exponentialDelay, config.maxDelayMs);
|
|
261
|
+
// Apply jitter: random value between 0 and cappedDelay
|
|
262
|
+
if (config.jitter) {
|
|
263
|
+
return Math.round(Math.random() * cappedDelay);
|
|
253
264
|
}
|
|
254
|
-
|
|
255
|
-
return config.delayMs;
|
|
265
|
+
return Math.round(cappedDelay);
|
|
256
266
|
}
|
|
257
267
|
/**
|
|
258
268
|
* Sleep for a specified duration
|
|
@@ -261,7 +271,9 @@ class BaseTTIProvider {
|
|
|
261
271
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
262
272
|
}
|
|
263
273
|
/**
|
|
264
|
-
* Execute a generation function with retry logic for
|
|
274
|
+
* Execute a generation function with retry logic for transient errors.
|
|
275
|
+
* Retries on: 429, 408, 5xx, network timeouts, TCP disconnects.
|
|
276
|
+
* Does NOT retry on: 400, 401, 403, and other client errors.
|
|
265
277
|
*/
|
|
266
278
|
async executeWithRetry(request, operation, operationName) {
|
|
267
279
|
const retryConfig = this.resolveRetryConfig(request);
|
|
@@ -277,33 +289,77 @@ class BaseTTIProvider {
|
|
|
277
289
|
}
|
|
278
290
|
catch (error) {
|
|
279
291
|
lastError = error;
|
|
280
|
-
//
|
|
281
|
-
|
|
282
|
-
// Only retry on rate limit errors
|
|
283
|
-
if (!isRateLimitError) {
|
|
292
|
+
// Only retry on retryable errors
|
|
293
|
+
if (!this.isRetryableError(error)) {
|
|
284
294
|
throw error;
|
|
285
295
|
}
|
|
286
296
|
// Check if we have retries left
|
|
287
297
|
if (attempt < maxAttempts) {
|
|
288
298
|
const delay = this.calculateRetryDelay(attempt, retryConfig);
|
|
289
|
-
this.log('warn', `
|
|
299
|
+
this.log('warn', `Transient error during ${operationName}. Retry ${attempt}/${retryConfig.maxRetries} in ${delay}ms...`, { attempt, maxRetries: retryConfig.maxRetries, delayMs: delay, error: error.message });
|
|
290
300
|
await this.sleep(delay);
|
|
291
301
|
}
|
|
292
302
|
}
|
|
293
303
|
}
|
|
294
304
|
// All retries exhausted
|
|
305
|
+
this.log('error', `All ${retryConfig.maxRetries} retries exhausted for ${operationName}`, {
|
|
306
|
+
lastError: lastError?.message,
|
|
307
|
+
});
|
|
295
308
|
throw lastError;
|
|
296
309
|
}
|
|
297
310
|
/**
|
|
298
|
-
* Check if an error is
|
|
311
|
+
* Check if an error is retryable (transient).
|
|
312
|
+
* Retryable: 429, 408, 500, 502, 503, 504, network errors, timeouts.
|
|
313
|
+
* Not retryable: 400, 401, 403, and other client errors.
|
|
299
314
|
*/
|
|
300
|
-
|
|
315
|
+
isRetryableError(error) {
|
|
301
316
|
const message = error.message.toLowerCase();
|
|
302
|
-
|
|
303
|
-
|
|
317
|
+
// Non-retryable client errors (check first to avoid false positives)
|
|
318
|
+
if (message.includes('401') ||
|
|
319
|
+
message.includes('403') ||
|
|
320
|
+
message.includes('400') ||
|
|
321
|
+
message.includes('authentication') ||
|
|
322
|
+
message.includes('unauthorized') ||
|
|
323
|
+
message.includes('forbidden')) {
|
|
324
|
+
return false;
|
|
325
|
+
}
|
|
326
|
+
// Retryable HTTP status codes
|
|
327
|
+
if (message.includes('429') ||
|
|
328
|
+
message.includes('408') ||
|
|
329
|
+
message.includes('500') ||
|
|
330
|
+
message.includes('502') ||
|
|
331
|
+
message.includes('503') ||
|
|
332
|
+
message.includes('504')) {
|
|
333
|
+
return true;
|
|
334
|
+
}
|
|
335
|
+
// Retryable by error description
|
|
336
|
+
if (message.includes('rate limit') ||
|
|
304
337
|
message.includes('quota exceeded') ||
|
|
305
338
|
message.includes('too many requests') ||
|
|
306
|
-
message.includes('resource exhausted'))
|
|
339
|
+
message.includes('resource exhausted')) {
|
|
340
|
+
return true;
|
|
341
|
+
}
|
|
342
|
+
// Network / timeout errors
|
|
343
|
+
if (message.includes('timeout') ||
|
|
344
|
+
message.includes('etimedout') ||
|
|
345
|
+
message.includes('esockettimedout') ||
|
|
346
|
+
message.includes('econnreset') ||
|
|
347
|
+
message.includes('econnrefused') ||
|
|
348
|
+
message.includes('enotfound') ||
|
|
349
|
+
message.includes('econnaborted') ||
|
|
350
|
+
message.includes('epipe') ||
|
|
351
|
+
message.includes('ehostunreach') ||
|
|
352
|
+
message.includes('enetunreach') ||
|
|
353
|
+
message.includes('socket hang up')) {
|
|
354
|
+
return true;
|
|
355
|
+
}
|
|
356
|
+
return false;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* @deprecated Use isRetryableError() instead
|
|
360
|
+
*/
|
|
361
|
+
isRateLimitError(error) {
|
|
362
|
+
return this.isRetryableError(error);
|
|
307
363
|
}
|
|
308
364
|
/**
|
|
309
365
|
* Convert errors to TTIError instances with proper classification
|
|
@@ -354,6 +410,11 @@ class BaseTTIProvider {
|
|
|
354
410
|
}
|
|
355
411
|
exports.BaseTTIProvider = BaseTTIProvider;
|
|
356
412
|
// ============================================================
|
|
413
|
+
// RETRY LOGIC
|
|
414
|
+
// ============================================================
|
|
415
|
+
/** Resolved retry config type (without deprecated fields) */
|
|
416
|
+
BaseTTIProvider.RESOLVED_RETRY_DEFAULTS = types_1.DEFAULT_RETRY_OPTIONS;
|
|
417
|
+
// ============================================================
|
|
357
418
|
// HELPER FUNCTIONS
|
|
358
419
|
// ============================================================
|
|
359
420
|
/**
|
|
@@ -449,8 +449,8 @@ class GoogleCloudTTIProvider extends base_tti_provider_1.BaseTTIProvider {
|
|
|
449
449
|
}
|
|
450
450
|
buildCharacterConsistencyPrompt(userPrompt, subjectDescription, referenceCount) {
|
|
451
451
|
const referenceText = referenceCount === 1 ? 'the reference image' : `the ${referenceCount} reference images`;
|
|
452
|
-
return `Using ${referenceText} as a reference for the subject "${subjectDescription}", generate a new image where: ${userPrompt}
|
|
453
|
-
|
|
452
|
+
return `Using ${referenceText} as a reference for the subject "${subjectDescription}", generate a new image where: ${userPrompt}
|
|
453
|
+
|
|
454
454
|
IMPORTANT: Maintain exact visual consistency with the subject in the reference - same style, colors, proportions, and distinctive features. The subject should be immediately recognizable as the same one from the reference.`;
|
|
455
455
|
}
|
|
456
456
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -165,11 +165,16 @@ export interface TTIResponse {
|
|
|
165
165
|
}
|
|
166
166
|
export type TTIErrorCode = 'INVALID_CONFIG' | 'QUOTA_EXCEEDED' | 'PROVIDER_UNAVAILABLE' | 'GENERATION_FAILED' | 'NETWORK_ERROR' | 'UNAUTHORIZED' | 'CAPABILITY_NOT_SUPPORTED';
|
|
167
167
|
/**
|
|
168
|
-
* Configuration for retry behavior on
|
|
168
|
+
* Configuration for retry behavior on transient errors.
|
|
169
|
+
*
|
|
170
|
+
* Retryable errors: 429 (rate limit), 408 (timeout), 5xx (server errors),
|
|
171
|
+
* network timeouts, and TCP disconnects.
|
|
172
|
+
*
|
|
173
|
+
* Non-retryable errors: 400, 401, 403, and other client errors.
|
|
169
174
|
*/
|
|
170
175
|
export interface RetryOptions {
|
|
171
176
|
/**
|
|
172
|
-
* Maximum number of retry attempts (default:
|
|
177
|
+
* Maximum number of retry attempts (default: 3)
|
|
173
178
|
* Total attempts = 1 (initial) + maxRetries
|
|
174
179
|
*/
|
|
175
180
|
maxRetries?: number;
|
|
@@ -178,17 +183,32 @@ export interface RetryOptions {
|
|
|
178
183
|
*/
|
|
179
184
|
delayMs?: number;
|
|
180
185
|
/**
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
|
|
186
|
+
* Backoff multiplier for exponential backoff (default: 2.0)
|
|
187
|
+
* Delay formula: delayMs * (backoffMultiplier ^ (attempt - 1))
|
|
188
|
+
* Set to 1.0 for constant delay.
|
|
189
|
+
*/
|
|
190
|
+
backoffMultiplier?: number;
|
|
191
|
+
/**
|
|
192
|
+
* Maximum delay in milliseconds (default: 30000)
|
|
193
|
+
* Caps the computed delay to prevent excessively long waits.
|
|
194
|
+
*/
|
|
195
|
+
maxDelayMs?: number;
|
|
196
|
+
/**
|
|
197
|
+
* Enable jitter to randomize delay and prevent thundering herd (default: true)
|
|
198
|
+
* When enabled, actual delay is randomized between 0 and the computed delay.
|
|
199
|
+
*/
|
|
200
|
+
jitter?: boolean;
|
|
201
|
+
/**
|
|
202
|
+
* @deprecated Use `backoffMultiplier` instead. Will be removed in v2.0.
|
|
203
|
+
* When true, equivalent to backoffMultiplier of 1.0 with linear scaling (delayMs * attempt).
|
|
185
204
|
*/
|
|
186
205
|
incrementalBackoff?: boolean;
|
|
187
206
|
}
|
|
188
207
|
/**
|
|
189
|
-
* Default retry configuration
|
|
208
|
+
* Default retry configuration following Google Cloud best practices.
|
|
209
|
+
* @see https://cloud.google.com/storage/docs/retry-strategy
|
|
190
210
|
*/
|
|
191
|
-
export declare const DEFAULT_RETRY_OPTIONS: Required<RetryOptions
|
|
211
|
+
export declare const DEFAULT_RETRY_OPTIONS: Required<Omit<RetryOptions, 'incrementalBackoff'>>;
|
|
192
212
|
/**
|
|
193
213
|
* Interface that all TTI providers must implement
|
|
194
214
|
*/
|
|
@@ -28,10 +28,13 @@ exports.LOG_LEVEL_PRIORITY = {
|
|
|
28
28
|
silent: 4,
|
|
29
29
|
};
|
|
30
30
|
/**
|
|
31
|
-
* Default retry configuration
|
|
31
|
+
* Default retry configuration following Google Cloud best practices.
|
|
32
|
+
* @see https://cloud.google.com/storage/docs/retry-strategy
|
|
32
33
|
*/
|
|
33
34
|
exports.DEFAULT_RETRY_OPTIONS = {
|
|
34
|
-
maxRetries:
|
|
35
|
+
maxRetries: 3,
|
|
35
36
|
delayMs: 1000,
|
|
36
|
-
|
|
37
|
+
backoffMultiplier: 2.0,
|
|
38
|
+
maxDelayMs: 30000,
|
|
39
|
+
jitter: true,
|
|
37
40
|
};
|
package/package.json
CHANGED
|
@@ -1,90 +1,90 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@loonylabs/tti-middleware",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Provider-agnostic Text-to-Image middleware with GDPR compliance. Supports Google Cloud (Imagen, Gemini), Eden AI, and IONOS.",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
7
|
-
"files": [
|
|
8
|
-
"dist",
|
|
9
|
-
"LICENSE",
|
|
10
|
-
"README.md",
|
|
11
|
-
".env.example"
|
|
12
|
-
],
|
|
13
|
-
"scripts": {
|
|
14
|
-
"build": "tsc",
|
|
15
|
-
"test": "npm run test:unit",
|
|
16
|
-
"test:unit": "jest --testPathPattern=tests/unit",
|
|
17
|
-
"test:unit:watch": "jest --testPathPattern=tests/unit --watch",
|
|
18
|
-
"test:unit:coverage": "jest --testPathPattern=tests/unit --coverage",
|
|
19
|
-
"test:integration": "cross-env TTI_INTEGRATION_TESTS=true jest --testPathPattern=tests/integration",
|
|
20
|
-
"test:ci": "jest --runInBand --ci --coverage --testPathPattern=tests/unit",
|
|
21
|
-
"test:live": "TTI_INTEGRATION_TESTS=true jest tests/integration/*.integration.test.ts --testTimeout=120000",
|
|
22
|
-
"test:manual": "ts-node scripts/manual-test-edenai.ts",
|
|
23
|
-
"test:manual:google-cloud": "ts-node scripts/manual-test-google-cloud.ts",
|
|
24
|
-
"lint": "eslint src/**/*.ts",
|
|
25
|
-
"format": "prettier --write \"src/**/*.ts\"",
|
|
26
|
-
"clean": "node -e \"const fs=require('fs');if(fs.existsSync('dist'))fs.rmSync('dist',{recursive:true})\"",
|
|
27
|
-
"prepare": "npm run build",
|
|
28
|
-
"prepublishOnly": "npm run clean && npm run build && npm run test"
|
|
29
|
-
},
|
|
30
|
-
"keywords": [
|
|
31
|
-
"tti",
|
|
32
|
-
"text-to-image",
|
|
33
|
-
"image-generation",
|
|
34
|
-
"ai",
|
|
35
|
-
"vertex-ai",
|
|
36
|
-
"google-cloud",
|
|
37
|
-
"gemini",
|
|
38
|
-
"imagen",
|
|
39
|
-
"middleware",
|
|
40
|
-
"provider-agnostic",
|
|
41
|
-
"typescript",
|
|
42
|
-
"gdpr",
|
|
43
|
-
"dsgvo",
|
|
44
|
-
"character-consistency"
|
|
45
|
-
],
|
|
46
|
-
"author": "loonylabs-dev",
|
|
47
|
-
"license": "MIT",
|
|
48
|
-
"repository": {
|
|
49
|
-
"type": "git",
|
|
50
|
-
"url": "https://github.com/loonylabs-dev/tti-middleware.git"
|
|
51
|
-
},
|
|
52
|
-
"bugs": {
|
|
53
|
-
"url": "https://github.com/loonylabs-dev/tti-middleware/issues"
|
|
54
|
-
},
|
|
55
|
-
"homepage": "https://github.com/loonylabs-dev/tti-middleware#readme",
|
|
56
|
-
"peerDependencies": {
|
|
57
|
-
"@google-cloud/aiplatform": ">=3.0.0",
|
|
58
|
-
"@google/genai": ">=0.14.0"
|
|
59
|
-
},
|
|
60
|
-
"peerDependenciesMeta": {
|
|
61
|
-
"@google-cloud/aiplatform": {
|
|
62
|
-
"optional": true
|
|
63
|
-
},
|
|
64
|
-
"@google/genai": {
|
|
65
|
-
"optional": true
|
|
66
|
-
}
|
|
67
|
-
},
|
|
68
|
-
"devDependencies": {
|
|
69
|
-
"@google-cloud/aiplatform": "^3.29.0",
|
|
70
|
-
"@google/genai": "^0.14.0",
|
|
71
|
-
"@types/jest": "^29.5.8",
|
|
72
|
-
"@types/node": "^20.10.0",
|
|
73
|
-
"@typescript-eslint/eslint-plugin": "^6.13.0",
|
|
74
|
-
"@typescript-eslint/parser": "^6.13.0",
|
|
75
|
-
"cross-env": "^10.1.0",
|
|
76
|
-
"dotenv": "^17.2.3",
|
|
77
|
-
"eslint": "^8.54.0",
|
|
78
|
-
"jest": "^29.7.0",
|
|
79
|
-
"prettier": "^3.1.0",
|
|
80
|
-
"ts-jest": "^29.1.1",
|
|
81
|
-
"ts-node": "^10.9.2",
|
|
82
|
-
"typescript": "^5.3.2"
|
|
83
|
-
},
|
|
84
|
-
"engines": {
|
|
85
|
-
"node": ">=18.0.0"
|
|
86
|
-
},
|
|
87
|
-
"publishConfig": {
|
|
88
|
-
"access": "public"
|
|
89
|
-
}
|
|
90
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@loonylabs/tti-middleware",
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "Provider-agnostic Text-to-Image middleware with GDPR compliance. Supports Google Cloud (Imagen, Gemini), Eden AI, and IONOS.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist",
|
|
9
|
+
"LICENSE",
|
|
10
|
+
"README.md",
|
|
11
|
+
".env.example"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc",
|
|
15
|
+
"test": "npm run test:unit",
|
|
16
|
+
"test:unit": "jest --testPathPattern=tests/unit",
|
|
17
|
+
"test:unit:watch": "jest --testPathPattern=tests/unit --watch",
|
|
18
|
+
"test:unit:coverage": "jest --testPathPattern=tests/unit --coverage",
|
|
19
|
+
"test:integration": "cross-env TTI_INTEGRATION_TESTS=true jest --testPathPattern=tests/integration",
|
|
20
|
+
"test:ci": "jest --runInBand --ci --coverage --testPathPattern=tests/unit",
|
|
21
|
+
"test:live": "TTI_INTEGRATION_TESTS=true jest tests/integration/*.integration.test.ts --testTimeout=120000",
|
|
22
|
+
"test:manual": "ts-node scripts/manual-test-edenai.ts",
|
|
23
|
+
"test:manual:google-cloud": "ts-node scripts/manual-test-google-cloud.ts",
|
|
24
|
+
"lint": "eslint src/**/*.ts",
|
|
25
|
+
"format": "prettier --write \"src/**/*.ts\"",
|
|
26
|
+
"clean": "node -e \"const fs=require('fs');if(fs.existsSync('dist'))fs.rmSync('dist',{recursive:true})\"",
|
|
27
|
+
"prepare": "npm run build",
|
|
28
|
+
"prepublishOnly": "npm run clean && npm run build && npm run test"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"tti",
|
|
32
|
+
"text-to-image",
|
|
33
|
+
"image-generation",
|
|
34
|
+
"ai",
|
|
35
|
+
"vertex-ai",
|
|
36
|
+
"google-cloud",
|
|
37
|
+
"gemini",
|
|
38
|
+
"imagen",
|
|
39
|
+
"middleware",
|
|
40
|
+
"provider-agnostic",
|
|
41
|
+
"typescript",
|
|
42
|
+
"gdpr",
|
|
43
|
+
"dsgvo",
|
|
44
|
+
"character-consistency"
|
|
45
|
+
],
|
|
46
|
+
"author": "loonylabs-dev",
|
|
47
|
+
"license": "MIT",
|
|
48
|
+
"repository": {
|
|
49
|
+
"type": "git",
|
|
50
|
+
"url": "https://github.com/loonylabs-dev/tti-middleware.git"
|
|
51
|
+
},
|
|
52
|
+
"bugs": {
|
|
53
|
+
"url": "https://github.com/loonylabs-dev/tti-middleware/issues"
|
|
54
|
+
},
|
|
55
|
+
"homepage": "https://github.com/loonylabs-dev/tti-middleware#readme",
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"@google-cloud/aiplatform": ">=3.0.0",
|
|
58
|
+
"@google/genai": ">=0.14.0"
|
|
59
|
+
},
|
|
60
|
+
"peerDependenciesMeta": {
|
|
61
|
+
"@google-cloud/aiplatform": {
|
|
62
|
+
"optional": true
|
|
63
|
+
},
|
|
64
|
+
"@google/genai": {
|
|
65
|
+
"optional": true
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"devDependencies": {
|
|
69
|
+
"@google-cloud/aiplatform": "^3.29.0",
|
|
70
|
+
"@google/genai": "^0.14.0",
|
|
71
|
+
"@types/jest": "^29.5.8",
|
|
72
|
+
"@types/node": "^20.10.0",
|
|
73
|
+
"@typescript-eslint/eslint-plugin": "^6.13.0",
|
|
74
|
+
"@typescript-eslint/parser": "^6.13.0",
|
|
75
|
+
"cross-env": "^10.1.0",
|
|
76
|
+
"dotenv": "^17.2.3",
|
|
77
|
+
"eslint": "^8.54.0",
|
|
78
|
+
"jest": "^29.7.0",
|
|
79
|
+
"prettier": "^3.1.0",
|
|
80
|
+
"ts-jest": "^29.1.1",
|
|
81
|
+
"ts-node": "^10.9.2",
|
|
82
|
+
"typescript": "^5.3.2"
|
|
83
|
+
},
|
|
84
|
+
"engines": {
|
|
85
|
+
"node": ">=18.0.0"
|
|
86
|
+
},
|
|
87
|
+
"publishConfig": {
|
|
88
|
+
"access": "public"
|
|
89
|
+
}
|
|
90
|
+
}
|