@zodic/shared 0.0.115 → 0.0.117
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/app/api/index.ts +19 -115
- package/app/services/ConceptService.ts +19 -20
- package/package.json +1 -1
- package/types/scopes/generic.ts +20 -2
- package/types/scopes/legacy.ts +3 -13
- package/utils/initImages.ts +33 -6
package/app/api/index.ts
CHANGED
|
@@ -16,9 +16,7 @@ import {
|
|
|
16
16
|
HouseCuspsReport,
|
|
17
17
|
LeonardoGenerateImageParams,
|
|
18
18
|
LeonardoGenerateImageResponse,
|
|
19
|
-
LeonardoGeneratePresignedUrlParams,
|
|
20
19
|
LeonardoRequestBody,
|
|
21
|
-
LeonardoUploadImageParams,
|
|
22
20
|
NatalHouseCuspReport,
|
|
23
21
|
TimezoneResponse,
|
|
24
22
|
} from '../../types/scopes/legacy';
|
|
@@ -236,13 +234,24 @@ export const Api = (env: BackendBindings) => ({
|
|
|
236
234
|
num_images: quantity,
|
|
237
235
|
};
|
|
238
236
|
|
|
237
|
+
// ✅ Dynamically add `controlNets` based on available settings
|
|
239
238
|
if (controlNets.length > 0) {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
239
|
+
// @ts-expect-error
|
|
240
|
+
body['controlnets'] = controlNets.map((net) => {
|
|
241
|
+
const baseNet = {
|
|
242
|
+
initImageId: net.initImageId,
|
|
243
|
+
initImageType: net.initImageType,
|
|
244
|
+
preprocessorId: net.preprocessorId,
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
if (net.preprocessorId === 100) {
|
|
248
|
+
return { ...baseNet, strengthType: net.strengthType };
|
|
249
|
+
} else if (net.preprocessorId === 19) {
|
|
250
|
+
return { ...baseNet, weight: net.weight };
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return baseNet;
|
|
254
|
+
});
|
|
246
255
|
}
|
|
247
256
|
|
|
248
257
|
if (initImageId) {
|
|
@@ -259,123 +268,18 @@ export const Api = (env: BackendBindings) => ({
|
|
|
259
268
|
|
|
260
269
|
if (!response.ok) {
|
|
261
270
|
const error = await response.json();
|
|
262
|
-
console.error('Error from Leonardo API:', error);
|
|
271
|
+
console.error('❌ Error from Leonardo API:', error);
|
|
263
272
|
throw new Error(`Leonardo API Error: ${response.status}`);
|
|
264
273
|
}
|
|
265
274
|
|
|
266
275
|
const data = (await response.json()) as LeonardoGenerateImageResponse;
|
|
267
276
|
return data;
|
|
268
277
|
} catch (err: any) {
|
|
269
|
-
console.error('Error calling Leonardo API:', err.message);
|
|
278
|
+
console.error('❌ Error calling Leonardo API:', err.message);
|
|
270
279
|
throw err;
|
|
271
280
|
}
|
|
272
281
|
},
|
|
273
|
-
generatePresignedUrl: async ({
|
|
274
|
-
extension,
|
|
275
|
-
}: LeonardoGeneratePresignedUrlParams): Promise<{
|
|
276
|
-
url: string;
|
|
277
|
-
fields: string;
|
|
278
|
-
id: string;
|
|
279
|
-
key: string;
|
|
280
|
-
}> => {
|
|
281
|
-
console.log('Generating presigned URL with extension:', extension);
|
|
282
|
-
|
|
283
|
-
const endpoint = 'https://cloud.leonardo.ai/api/rest/v1/init-image';
|
|
284
|
-
const headers = {
|
|
285
|
-
Authorization: `Bearer ${env.LEONARDO_API_KEY}`,
|
|
286
|
-
'Content-Type': 'application/json',
|
|
287
|
-
};
|
|
288
|
-
|
|
289
|
-
if (!extension) {
|
|
290
|
-
throw new Error('Invalid MIME type');
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
const body = JSON.stringify({
|
|
294
|
-
extension,
|
|
295
|
-
});
|
|
296
|
-
|
|
297
|
-
try {
|
|
298
|
-
const response = await fetch(endpoint, {
|
|
299
|
-
method: 'POST',
|
|
300
|
-
headers,
|
|
301
|
-
body,
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
if (!response.ok) {
|
|
305
|
-
const error = await response.text();
|
|
306
|
-
console.error('Leonardo API error:', error);
|
|
307
|
-
throw new Error(
|
|
308
|
-
`Presigned URL generation failed: ${response.status}`
|
|
309
|
-
);
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
const rawResponse = (await response.json()) as any;
|
|
313
|
-
console.log('Presigned URL response:', rawResponse);
|
|
314
|
-
|
|
315
|
-
if (
|
|
316
|
-
!rawResponse.uploadInitImage ||
|
|
317
|
-
!rawResponse.uploadInitImage.url ||
|
|
318
|
-
!rawResponse.uploadInitImage.fields
|
|
319
|
-
) {
|
|
320
|
-
throw new Error('Invalid presigned URL response');
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
return rawResponse.uploadInitImage;
|
|
324
|
-
} catch (error: any) {
|
|
325
|
-
console.error('Error generating presigned URL:', error.message);
|
|
326
|
-
throw error;
|
|
327
|
-
}
|
|
328
|
-
},
|
|
329
|
-
uploadImage: async ({
|
|
330
|
-
presignedUrl,
|
|
331
|
-
fields,
|
|
332
|
-
file,
|
|
333
|
-
}: LeonardoUploadImageParams) => {
|
|
334
|
-
console.log('Starting image upload to:', presignedUrl);
|
|
335
|
-
|
|
336
|
-
if (!(file instanceof Blob)) {
|
|
337
|
-
throw new Error('Invalid file type for upload');
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
try {
|
|
341
|
-
console.log('Parsing fields...');
|
|
342
|
-
const parsedFields = JSON.parse(fields);
|
|
343
|
-
|
|
344
|
-
if (!parsedFields || typeof parsedFields !== 'object') {
|
|
345
|
-
throw new Error('Invalid fields format');
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
console.log('Parsed fields:', parsedFields);
|
|
349
|
-
|
|
350
|
-
const formData = new FormData();
|
|
351
|
-
|
|
352
|
-
Object.entries(parsedFields).forEach(([key, value]) => {
|
|
353
|
-
formData.append(key, value as string);
|
|
354
|
-
});
|
|
355
|
-
|
|
356
|
-
formData.append('file', file);
|
|
357
|
-
|
|
358
|
-
console.log('Uploading with FormData:', Array.from(formData.entries()));
|
|
359
|
-
|
|
360
|
-
const response = await fetch(presignedUrl, {
|
|
361
|
-
method: 'POST',
|
|
362
|
-
body: formData,
|
|
363
|
-
});
|
|
364
|
-
|
|
365
|
-
if (!response.ok) {
|
|
366
|
-
const errorDetails = await response.text();
|
|
367
|
-
console.error('Upload failed:', errorDetails);
|
|
368
|
-
throw new Error(`Image upload failed: ${response.status}`);
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
console.log('Image uploaded successfully');
|
|
372
|
-
} catch (error: any) {
|
|
373
|
-
console.error('Error during uploadImage:', error.message);
|
|
374
|
-
throw error;
|
|
375
|
-
}
|
|
376
|
-
},
|
|
377
282
|
},
|
|
378
|
-
|
|
379
283
|
callImageDescriber: async (imageUrl: string): Promise<string> => {
|
|
380
284
|
const mimeType = 'image/png';
|
|
381
285
|
const endpoint =
|
|
@@ -3,7 +3,7 @@ import { inject, injectable } from 'inversify';
|
|
|
3
3
|
import 'reflect-metadata';
|
|
4
4
|
import { v4 as uuidv4 } from 'uuid';
|
|
5
5
|
import { schema } from '../..';
|
|
6
|
-
import { Concept, Languages } from '../../types';
|
|
6
|
+
import { Concept, ControlNetConfig, Languages } from '../../types';
|
|
7
7
|
import { KVConcept, sizes } from '../../types/scopes/legacy';
|
|
8
8
|
import { leonardoInitImages } from '../../utils/initImages';
|
|
9
9
|
import { buildConceptKVKey } from '../../utils/KVKeysBuilders';
|
|
@@ -214,7 +214,6 @@ export class ConceptService {
|
|
|
214
214
|
`🔹 Extracted planet signs: ${planet1} -> ${planet1Sign}, ${planet2} -> ${planet2Sign}, ${planet3} -> ${planet3Sign}`
|
|
215
215
|
);
|
|
216
216
|
|
|
217
|
-
// 🔍 Ensure Concept Combination exists
|
|
218
217
|
let [conceptCombination] = await drizzle
|
|
219
218
|
.select({ id: conceptCombinations.id })
|
|
220
219
|
.from(conceptCombinations)
|
|
@@ -253,25 +252,25 @@ export class ConceptService {
|
|
|
253
252
|
|
|
254
253
|
console.log(`🎨 Requesting Leonardo AI image generation...`);
|
|
255
254
|
|
|
256
|
-
|
|
257
|
-
const
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
255
|
+
const initImage = leonardoInitImages.concepts[conceptSlug];
|
|
256
|
+
const controlNets: ControlNetConfig[] = initImage.imageId
|
|
257
|
+
? [
|
|
258
|
+
initImage.preprocessorId === 100
|
|
259
|
+
? {
|
|
260
|
+
initImageId: initImage.imageId,
|
|
261
|
+
initImageType: 'UPLOADED',
|
|
262
|
+
preprocessorId: 100,
|
|
263
|
+
strengthType: initImage.strengthType!,
|
|
264
|
+
}
|
|
265
|
+
: {
|
|
266
|
+
initImageId: initImage.imageId,
|
|
267
|
+
initImageType: 'UPLOADED',
|
|
268
|
+
preprocessorId: 19,
|
|
269
|
+
weight: initImage.weight!,
|
|
270
|
+
},
|
|
271
|
+
]
|
|
272
272
|
: [];
|
|
273
273
|
|
|
274
|
-
// 🎨 Call Leonardo with or without ControlNet
|
|
275
274
|
const leonardoResponse = await this.context
|
|
276
275
|
.api()
|
|
277
276
|
.callLeonardo.generateImage({
|
|
@@ -279,7 +278,7 @@ export class ConceptService {
|
|
|
279
278
|
width,
|
|
280
279
|
height,
|
|
281
280
|
...(controlNets.length > 0 ? { controlNets } : {}),
|
|
282
|
-
negPrompt: 'person, hands, face, body parts, people, animals, fingers'
|
|
281
|
+
negPrompt: 'person, hands, face, body parts, people, animals, fingers',
|
|
283
282
|
});
|
|
284
283
|
|
|
285
284
|
const generationId = leonardoResponse?.sdGenerationJob?.generationId;
|
package/package.json
CHANGED
package/types/scopes/generic.ts
CHANGED
|
@@ -148,7 +148,7 @@ export type Concept =
|
|
|
148
148
|
| 'lantern'
|
|
149
149
|
| 'orb'
|
|
150
150
|
| 'ring';
|
|
151
|
-
|
|
151
|
+
|
|
152
152
|
export type Concepts = ['crown', 'scepter', 'amulet', 'lantern', 'orb', 'ring'];
|
|
153
153
|
export type ConceptQueueMessage = {
|
|
154
154
|
conceptSlug: Concept;
|
|
@@ -296,4 +296,22 @@ export interface JWK {
|
|
|
296
296
|
|
|
297
297
|
export interface JWKS {
|
|
298
298
|
keys: JWK[];
|
|
299
|
-
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
export type ControlNetStrenghtType = 'Low' | 'Mid' | 'High';
|
|
302
|
+
|
|
303
|
+
export type ControlNetPreprocessorId = 100 | 19;
|
|
304
|
+
|
|
305
|
+
export type ControlNetConfig =
|
|
306
|
+
| {
|
|
307
|
+
initImageId: string;
|
|
308
|
+
initImageType: 'UPLOADED' | 'GENERATED';
|
|
309
|
+
preprocessorId: 100; // Content Reference
|
|
310
|
+
strengthType: ControlNetStrenghtType;
|
|
311
|
+
}
|
|
312
|
+
| {
|
|
313
|
+
initImageId: string;
|
|
314
|
+
initImageType: 'UPLOADED' | 'GENERATED';
|
|
315
|
+
preprocessorId: 19; // Edge to Image
|
|
316
|
+
weight: string;
|
|
317
|
+
};
|
package/types/scopes/legacy.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BackendBindings } from './cloudflare';
|
|
2
|
-
import { Gender } from './generic';
|
|
2
|
+
import { ControlNetConfig, Gender } from './generic';
|
|
3
3
|
|
|
4
4
|
export const zodiacSigns = [
|
|
5
5
|
'Aries',
|
|
@@ -25,12 +25,7 @@ export interface LeonardoGenerateImageParams {
|
|
|
25
25
|
prompt: string;
|
|
26
26
|
width: number;
|
|
27
27
|
height: number;
|
|
28
|
-
controlNets?: Array<
|
|
29
|
-
initImageId: string;
|
|
30
|
-
initImageType: 'UPLOADED' | 'GENERATED';
|
|
31
|
-
preprocessorId: number;
|
|
32
|
-
strengthType: 'Low' | 'Mid' | 'High';
|
|
33
|
-
}>;
|
|
28
|
+
controlNets?: Array<ControlNetConfig>;
|
|
34
29
|
quantity?: number;
|
|
35
30
|
negPrompt?: string | null;
|
|
36
31
|
}
|
|
@@ -162,12 +157,7 @@ export interface LeonardoRequestBody {
|
|
|
162
157
|
modelId: string;
|
|
163
158
|
presetStyle: string;
|
|
164
159
|
alchemy: boolean;
|
|
165
|
-
controlnets?: Array<
|
|
166
|
-
initImageId: string;
|
|
167
|
-
initImageType: string;
|
|
168
|
-
preprocessorId: number;
|
|
169
|
-
strengthType: string;
|
|
170
|
-
}>;
|
|
160
|
+
controlnets?: Array<ControlNetConfig>;
|
|
171
161
|
init_generation_image_id?: string;
|
|
172
162
|
init_strength?: number;
|
|
173
163
|
}
|
package/utils/initImages.ts
CHANGED
|
@@ -6,11 +6,15 @@ export const leonardoInitImages: LeonardoInitImages = {
|
|
|
6
6
|
imageId: '450076a1-c6bb-4877-8a0b-c0d3ba72fca7',
|
|
7
7
|
imageUrl:
|
|
8
8
|
'https://cdn.leonardo.ai/users/b117a933-e5c9-45b2-96aa-4b619c2d74ba/initImages/450076a1-c6bb-4877-8a0b-c0d3ba72fca7.jpg',
|
|
9
|
+
preprocessorId: 100,
|
|
10
|
+
strengthType: 'Low',
|
|
9
11
|
},
|
|
10
12
|
scepter: {
|
|
11
13
|
imageId: '744169ef-3db4-416d-86dd-9bd814e33432',
|
|
12
14
|
imageUrl:
|
|
13
15
|
'https://cdn.leonardo.ai/users/b117a933-e5c9-45b2-96aa-4b619c2d74ba/initImages/744169ef-3db4-416d-86dd-9bd814e33432.jpg',
|
|
16
|
+
preprocessorId: 100,
|
|
17
|
+
strengthType: 'Low',
|
|
14
18
|
},
|
|
15
19
|
amulet: {
|
|
16
20
|
imageId: null,
|
|
@@ -21,8 +25,11 @@ export const leonardoInitImages: LeonardoInitImages = {
|
|
|
21
25
|
imageUrl: null,
|
|
22
26
|
},
|
|
23
27
|
orb: {
|
|
24
|
-
imageId:
|
|
25
|
-
imageUrl:
|
|
28
|
+
imageId: 'c489e496-00c4-4958-8bcd-4460a43a43bf',
|
|
29
|
+
imageUrl:
|
|
30
|
+
'https://cdn.leonardo.ai/users/b117a933-e5c9-45b2-96aa-4b619c2d74ba/initImages/c489e496-00c4-4958-8bcd-4460a43a43bf.jpg',
|
|
31
|
+
preprocessorId: 19,
|
|
32
|
+
weight: '0.3',
|
|
26
33
|
},
|
|
27
34
|
ring: {
|
|
28
35
|
imageId: null,
|
|
@@ -31,10 +38,30 @@ export const leonardoInitImages: LeonardoInitImages = {
|
|
|
31
38
|
},
|
|
32
39
|
};
|
|
33
40
|
|
|
34
|
-
type ConceptsInitImages = Record<
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
41
|
+
type ConceptsInitImages = Record<Concept, ControlNetSettings>;
|
|
42
|
+
|
|
43
|
+
type ControlNetSettings =
|
|
44
|
+
| {
|
|
45
|
+
imageId: string;
|
|
46
|
+
imageUrl: string;
|
|
47
|
+
preprocessorId: 100;
|
|
48
|
+
strengthType: 'Low' | 'Mid' | 'High';
|
|
49
|
+
weight?: null;
|
|
50
|
+
}
|
|
51
|
+
| {
|
|
52
|
+
imageId: string;
|
|
53
|
+
imageUrl: string;
|
|
54
|
+
preprocessorId: 19;
|
|
55
|
+
weight: string;
|
|
56
|
+
strengthType?: null;
|
|
57
|
+
}
|
|
58
|
+
| {
|
|
59
|
+
imageId: null;
|
|
60
|
+
imageUrl: null;
|
|
61
|
+
preprocessorId?: undefined;
|
|
62
|
+
strengthType?: undefined;
|
|
63
|
+
weight?: undefined;
|
|
64
|
+
};
|
|
38
65
|
|
|
39
66
|
type LeonardoInitImages = {
|
|
40
67
|
concepts: ConceptsInitImages;
|