@zodic/shared 0.0.315 → 0.0.317

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.
@@ -2,7 +2,7 @@ import { and, eq } from 'drizzle-orm';
2
2
  import { inject, injectable } from 'inversify';
3
3
  import { schema } from '../..';
4
4
  import { Gender } from '../../types';
5
- import { AppContext } from '../base/AppContext';
5
+ import { AppContext } from '../base';
6
6
  import { ArchetypeService } from '../services/ArchetypeService';
7
7
  import { LeonardoService } from '../services/LeonardoService';
8
8
 
@@ -23,7 +23,6 @@ export class ArchetypeWorkflow {
23
23
  const logMessage = `[${level.toUpperCase()}] ${message}`;
24
24
 
25
25
  console[level](logMessage, context);
26
-
27
26
  const db = this.context.drizzle();
28
27
  try {
29
28
  await db
@@ -57,23 +56,31 @@ export class ArchetypeWorkflow {
57
56
  language,
58
57
  });
59
58
 
60
- // Fetch archetypes from archetypes_data
61
- await this.log('debug', 'Fetching archetypes from database', {
62
- combinationString,
63
- gender,
64
- language,
65
- });
66
- const archetypes = await this.fetchArchetypesFromDB(
59
+ // Step 1: Check if archetypes exist, if not, generate names
60
+ let archetypes = await this.archetypeService.fetchArchetypesFromDB(
67
61
  combinationString,
68
62
  gender,
69
63
  language
70
64
  );
65
+ if (archetypes.length === 0) {
66
+ await this.log('info', 'No archetypes found, generating names', {
67
+ combinationString,
68
+ gender,
69
+ language,
70
+ });
71
+ await this.archetypeService.generateArchetypeNames(combinationString);
72
+ archetypes = await this.archetypeService.fetchArchetypesFromDB(
73
+ combinationString,
74
+ gender,
75
+ language
76
+ );
77
+ }
71
78
  await this.log('info', 'Fetched archetypes', {
72
79
  archetypesCount: archetypes.length,
73
80
  archetypeIds: archetypes.map((a) => a.id),
74
81
  });
75
82
 
76
- // Check if any archetypes are already being processed (images are generating)
83
+ // Step 2: Check if any archetypes are already being processed (images are generating)
77
84
  const db = this.context.drizzle();
78
85
  await this.log('debug', 'Checking for in-progress image generations', {
79
86
  combinationString,
@@ -86,7 +93,7 @@ export class ArchetypeWorkflow {
86
93
  and(
87
94
  eq(schema.generations.status, 'pending'),
88
95
  eq(schema.generations.gender, gender),
89
- eq(schema.generations.conceptCombinationId, combinationString)
96
+ eq(schema.generations.archetypeDataId, combinationString)
90
97
  )
91
98
  )
92
99
  .execute();
@@ -107,7 +114,7 @@ export class ArchetypeWorkflow {
107
114
  gender,
108
115
  });
109
116
 
110
- // Step 1: Generate missing textual content (description, virtues, content, leonardoPrompt)
117
+ // Step 3: Generate missing textual content (description, virtues, content, leonardoPrompt)
111
118
  const archetypesNeedingText = archetypes.filter(
112
119
  (arc) =>
113
120
  !arc.description ||
@@ -124,7 +131,25 @@ export class ArchetypeWorkflow {
124
131
  archetypesNeedingTextCount: archetypesNeedingText.length,
125
132
  archetypeIds: archetypesNeedingText.map((a) => a.id),
126
133
  });
127
- await this.generateTextualContent(combinationString, gender, language);
134
+
135
+ const descVirtues =
136
+ await this.archetypeService.generateDescriptionsAndVirtues(
137
+ combinationString,
138
+ gender,
139
+ language
140
+ );
141
+ await this.archetypeService.generateContent(
142
+ combinationString,
143
+ gender,
144
+ language,
145
+ descVirtues
146
+ );
147
+ await this.archetypeService.generateLeonardoPrompts(
148
+ combinationString,
149
+ gender,
150
+ language,
151
+ descVirtues
152
+ );
128
153
  } else {
129
154
  await this.log('info', 'No textual content generation needed', {
130
155
  combinationString,
@@ -134,12 +159,7 @@ export class ArchetypeWorkflow {
134
159
  }
135
160
 
136
161
  // Refetch archetypes after generating textual content
137
- await this.log(
138
- 'debug',
139
- 'Refetching archetypes after textual content generation',
140
- { combinationString, gender, language }
141
- );
142
- const updatedArchetypes = await this.fetchArchetypesFromDB(
162
+ const updatedArchetypes = await this.archetypeService.fetchArchetypesFromDB(
143
163
  combinationString,
144
164
  gender,
145
165
  language
@@ -149,7 +169,7 @@ export class ArchetypeWorkflow {
149
169
  archetypeIds: updatedArchetypes.map((a) => a.id),
150
170
  });
151
171
 
152
- // Step 2: Queue image generation if needed
172
+ // Step 4: Queue image generation if needed
153
173
  const archetypesNeedingImages = updatedArchetypes.filter(
154
174
  (arc) => JSON.parse(arc.images).length < 3
155
175
  );
@@ -164,7 +184,6 @@ export class ArchetypeWorkflow {
164
184
  }
165
185
  );
166
186
 
167
- // Queue image generation for all archetypes needing images
168
187
  const batch = archetypesNeedingImages.map((arc) => ({
169
188
  body: {
170
189
  archetypeDataId: arc.id,
@@ -201,541 +220,4 @@ export class ArchetypeWorkflow {
201
220
  ),
202
221
  };
203
222
  }
204
-
205
- private async fetchArchetypesFromDB(
206
- combinationString: string,
207
- gender: Gender,
208
- language: string
209
- ) {
210
- await this.log('debug', 'Executing fetchArchetypesFromDB', {
211
- combinationString,
212
- gender,
213
- language,
214
- });
215
- const db = this.context.drizzle();
216
- const result = await db
217
- .select()
218
- .from(schema.archetypesData)
219
- .where(
220
- and(
221
- eq(schema.archetypesData.combination, combinationString),
222
- eq(schema.archetypesData.gender, gender),
223
- eq(schema.archetypesData.language, language)
224
- )
225
- )
226
- .execute();
227
- await this.log('debug', 'fetchArchetypesFromDB result', {
228
- resultCount: result.length,
229
- result,
230
- });
231
- return result;
232
- }
233
-
234
- private async generateTextualContent(
235
- combinationString: string,
236
- gender: Gender,
237
- language: string
238
- ) {
239
- await this.log('info', 'Starting generateTextualContent', {
240
- combinationString,
241
- gender,
242
- language,
243
- });
244
-
245
- const db = this.context.drizzle();
246
-
247
- // Fetch English archetypes to get names and essence lines
248
- await this.log(
249
- 'debug',
250
- 'Fetching English archetypes for names and essence lines',
251
- { combinationString, gender }
252
- );
253
- const archetypes = await db
254
- .select()
255
- .from(schema.archetypesData)
256
- .where(
257
- and(
258
- eq(schema.archetypesData.combination, combinationString),
259
- eq(schema.archetypesData.gender, gender),
260
- eq(schema.archetypesData.language, 'en-us')
261
- )
262
- )
263
- .execute();
264
- await this.log('info', 'Fetched English archetypes', {
265
- archetypesCount: archetypes.length,
266
- names: archetypes.map((a) => a.name),
267
- essenceLines: archetypes.map((a) => a.essenceLine),
268
- });
269
-
270
- // Step 1: Generate description and virtues
271
- await this.log('debug', 'Generating description and virtues', {
272
- combinationString,
273
- });
274
- const descVirtueMessages = this.context
275
- .buildLLMMessages()
276
- .generateCosmicMirrorDescriptionAndVirtues({
277
- combination: combinationString,
278
- names: [archetypes[0].name, archetypes[1].name, archetypes[2].name],
279
- essenceLines: [
280
- archetypes[0].essenceLine,
281
- archetypes[1].essenceLine,
282
- archetypes[2].essenceLine,
283
- ],
284
- });
285
-
286
- await this.log('debug', 'Calling API for description and virtues', {
287
- messages: descVirtueMessages,
288
- });
289
- const descVirtueResponse = await this.context
290
- .api()
291
- .callTogether.single(descVirtueMessages, {});
292
- await this.log('info', 'Received description and virtues response', {
293
- responseLength: descVirtueResponse.length,
294
- });
295
-
296
- await this.log('debug', 'Parsing description and virtues response');
297
- const parsedDescVirtues =
298
- this.parseDescriptionAndVirtuesResponse(descVirtueResponse);
299
- await this.log('info', 'Parsed description and virtues', {
300
- parsedDescVirtues,
301
- });
302
-
303
- // Step 2: Generate content for each archetype
304
- const contentResults = [];
305
- for (let i = 0; i < 3; i++) {
306
- await this.log('debug', `Generating content for archetype ${i + 1}`, {
307
- name: archetypes[i].name,
308
- });
309
- const contentMessages = this.context
310
- .buildLLMMessages()
311
- .generateCosmicMirrorArchetypeContent({
312
- combination: combinationString,
313
- name: archetypes[i].name,
314
- description: parsedDescVirtues[i].descriptionEN,
315
- });
316
-
317
- await this.log('debug', `Calling API for content of archetype ${i + 1}`, {
318
- messages: contentMessages,
319
- });
320
- const contentResponse = await this.context
321
- .api()
322
- .callTogether.single(contentMessages, {});
323
- await this.log(
324
- 'info',
325
- `Received content response for archetype ${i + 1}`,
326
- { responseLength: contentResponse.length }
327
- );
328
-
329
- await this.log(
330
- 'debug',
331
- `Parsing content response for archetype ${i + 1}`
332
- );
333
- const parsedContent = this.parseContentResponse(contentResponse);
334
- contentResults.push(parsedContent);
335
- await this.log('info', `Parsed content for archetype ${i + 1}`, {
336
- parsedContent,
337
- });
338
- }
339
-
340
- // Step 3: Generate Leonardo prompts for all archetypes
341
- await this.log('debug', 'Generating Leonardo prompts for all archetypes');
342
- const promptMessages = this.context
343
- .buildLLMMessages()
344
- .generateCosmicMirrorArchetypeLeonardoPrompts(
345
- archetypes.map((arc, idx) => ({
346
- name: arc.name,
347
- description: parsedDescVirtues[idx].descriptionEN,
348
- }))
349
- );
350
-
351
- await this.log('debug', 'Calling API for Leonardo prompts', {
352
- messages: promptMessages,
353
- });
354
- const promptResponse = await this.context
355
- .api()
356
- .callTogether.single(promptMessages, {});
357
- await this.log('info', 'Received Leonardo prompts response', {
358
- responseLength: promptResponse.length,
359
- });
360
-
361
- await this.log('debug', 'Parsing Leonardo prompts response');
362
- const parsedPrompts = this.parseLeonardoPromptResponse(promptResponse);
363
- await this.log('info', 'Parsed Leonardo prompts', { parsedPrompts });
364
-
365
- // Update archetypes_data with the generated content
366
- for (let i = 0; i < 3; i++) {
367
- const archetype = archetypes[i];
368
- const index = (i + 1).toString();
369
-
370
- for (const lang of ['en-us', 'pt-br']) {
371
- const descriptionField =
372
- lang === 'en-us'
373
- ? parsedDescVirtues[i].descriptionEN
374
- : gender === 'male'
375
- ? parsedDescVirtues[i].descriptionPTM
376
- : parsedDescVirtues[i].descriptionPTF;
377
-
378
- const contentLangIndex =
379
- lang === 'en-us' ? 0 : gender === 'male' ? 1 : 2;
380
- const content = [
381
- {
382
- section: 'voiceOfTheSoul',
383
- text: contentResults[i][contentLangIndex].voiceOfTheSoul,
384
- },
385
- {
386
- section: 'giftsYouBear',
387
- text: contentResults[i][contentLangIndex].giftsYouBear,
388
- },
389
- {
390
- section: 'shadowsYouFace',
391
- text: contentResults[i][contentLangIndex].shadowsYouFace,
392
- },
393
- {
394
- section: 'rhythmOfYourDays',
395
- text: contentResults[i][contentLangIndex].rhythmOfYourDays,
396
- },
397
- {
398
- section: 'tiesThatBind',
399
- text: contentResults[i][contentLangIndex].tiesThatBind,
400
- },
401
- {
402
- section: 'lightWithin',
403
- text: contentResults[i][contentLangIndex].lightWithin,
404
- },
405
- ];
406
-
407
- const leonardoPrompt =
408
- gender === 'male'
409
- ? parsedPrompts[i].malePrompt
410
- : parsedPrompts[i].femalePrompt;
411
-
412
- await this.log(
413
- 'debug',
414
- `Updating archetypes_data for archetype ${index}, language: ${lang}`,
415
- {
416
- descriptionField,
417
- content,
418
- leonardoPrompt,
419
- }
420
- );
421
-
422
- await db
423
- .update(schema.archetypesData)
424
- .set({
425
- description: descriptionField,
426
- virtues: JSON.stringify(parsedDescVirtues[i].virtues),
427
- content: JSON.stringify(content),
428
- leonardoPrompt,
429
- updatedAt: new Date().getTime(),
430
- })
431
- .where(
432
- and(
433
- eq(schema.archetypesData.combination, combinationString),
434
- eq(schema.archetypesData.gender, gender),
435
- eq(schema.archetypesData.language, lang),
436
- eq(schema.archetypesData.archetypeIndex, index)
437
- )
438
- )
439
- .execute();
440
-
441
- await this.log(
442
- 'info',
443
- `Updated archetypes_data for archetype ${index}, language: ${lang}`
444
- );
445
- }
446
- }
447
-
448
- await this.log('info', 'Completed generateTextualContent', {
449
- combinationString,
450
- gender,
451
- language,
452
- });
453
- }
454
-
455
- private parseDescriptionAndVirtuesResponse(response: string) {
456
- this.log('debug', 'Starting parseDescriptionAndVirtuesResponse', {
457
- responseLength: response.length,
458
- });
459
-
460
- const entries = response
461
- .split(/---/)
462
- .map((block) => block.trim())
463
- .filter((block) => block.length > 0);
464
-
465
- this.log('debug', 'Split response into entries', {
466
- entriesCount: entries.length,
467
- });
468
-
469
- const result = entries.map((entry, entryIndex) => {
470
- this.log('debug', `Processing entry ${entryIndex + 1}`, { entry });
471
-
472
- const lines = entry.split('\n').filter((line) => line.trim());
473
- this.log('debug', `Split entry ${entryIndex + 1} into lines`, {
474
- linesCount: lines.length,
475
- lines,
476
- });
477
-
478
- let descriptionEN = '';
479
- let descriptionPTM = '';
480
- let descriptionPTF = '';
481
- let virtues: string[] = [];
482
- let currentField = '';
483
-
484
- for (const line of lines) {
485
- if (line.startsWith('• Description EN:')) {
486
- currentField = 'descriptionEN';
487
- descriptionEN = line.split('• Description EN:')[1]?.trim() || '';
488
- this.log(
489
- 'debug',
490
- `Extracted descriptionEN for entry ${entryIndex + 1}`,
491
- { descriptionEN }
492
- );
493
- } else if (line.startsWith('• Description PT-M:')) {
494
- currentField = 'descriptionPTM';
495
- descriptionPTM = line.split('• Description PT-M:')[1]?.trim() || '';
496
- this.log(
497
- 'debug',
498
- `Extracted descriptionPTM for entry ${entryIndex + 1}`,
499
- { descriptionPTM }
500
- );
501
- } else if (line.startsWith('• Description PT-F:')) {
502
- currentField = 'descriptionPTF';
503
- descriptionPTF = line.split('• Description PT-F:')[1]?.trim() || '';
504
- this.log(
505
- 'debug',
506
- `Extracted descriptionPTF for entry ${entryIndex + 1}`,
507
- { descriptionPTF }
508
- );
509
- } else if (line.startsWith('• Virtues:')) {
510
- currentField = 'virtues';
511
- virtues =
512
- line
513
- .split('• Virtues:')[1]
514
- ?.split(',')
515
- .map((v) => v.trim())
516
- .filter((v) => v) || [];
517
- this.log('debug', `Extracted virtues for entry ${entryIndex + 1}`, {
518
- virtues,
519
- });
520
- } else if (currentField && currentField !== 'virtues') {
521
- if (currentField === 'descriptionEN') {
522
- descriptionEN += ' ' + line.trim();
523
- this.log(
524
- 'debug',
525
- `Appended to descriptionEN for entry ${entryIndex + 1}`,
526
- { descriptionEN }
527
- );
528
- }
529
- if (currentField === 'descriptionPTM') {
530
- descriptionPTM += ' ' + line.trim();
531
- this.log(
532
- 'debug',
533
- `Appended to descriptionPTM for entry ${entryIndex + 1}`,
534
- { descriptionPTM }
535
- );
536
- }
537
- if (currentField === 'descriptionPTF') {
538
- descriptionPTF += ' ' + line.trim();
539
- this.log(
540
- 'debug',
541
- `Appended to descriptionPTF for entry ${entryIndex + 1}`,
542
- { descriptionPTF }
543
- );
544
- }
545
- }
546
- }
547
-
548
- if (
549
- !descriptionEN ||
550
- !descriptionPTM ||
551
- !descriptionPTF ||
552
- virtues.length !== 3
553
- ) {
554
- this.log(
555
- 'warn',
556
- `Malformed description and virtues response for entry ${
557
- entryIndex + 1
558
- }`,
559
- {
560
- descriptionEN,
561
- descriptionPTM,
562
- descriptionPTF,
563
- virtues,
564
- response: entry,
565
- }
566
- );
567
- }
568
-
569
- return { descriptionEN, descriptionPTM, descriptionPTF, virtues };
570
- });
571
-
572
- this.log('info', 'Completed parseDescriptionAndVirtuesResponse', {
573
- result,
574
- });
575
- return result;
576
- }
577
-
578
- private parseContentResponse(response: string) {
579
- this.log('debug', 'Starting parseContentResponse', {
580
- responseLength: response.length,
581
- });
582
-
583
- const sections = response
584
- .split(/---/)
585
- .map((block) => block.trim())
586
- .filter((block) => block.length > 0);
587
- this.log('debug', 'Split response into sections', {
588
- sectionsCount: sections.length,
589
- });
590
-
591
- const result = sections.map((section, sectionIndex) => {
592
- this.log('debug', `Processing section ${sectionIndex + 1}`, { section });
593
-
594
- const lines = section.split('\n').filter((line) => line.trim());
595
- this.log('debug', `Split section ${sectionIndex + 1} into lines`, {
596
- linesCount: lines.length,
597
- lines,
598
- });
599
-
600
- const content: Record<string, string> = {};
601
- let currentSection = '';
602
- let currentText: string[] = [];
603
-
604
- for (const line of lines) {
605
- if (
606
- line.startsWith('EN:') ||
607
- line.startsWith('PT-M:') ||
608
- line.startsWith('PT-F:')
609
- ) {
610
- this.log(
611
- 'debug',
612
- `Skipping language header in section ${sectionIndex + 1}`,
613
- { line }
614
- );
615
- continue;
616
- }
617
-
618
- if (line.startsWith('#')) {
619
- if (currentSection && currentText.length > 0) {
620
- const key = currentSection
621
- .toLowerCase()
622
- .replace(/\s+/g, '')
623
- .replace(/([A-Z])/g, (match) => match.toLowerCase());
624
- content[key] = currentText.join(' ').trim();
625
- this.log(
626
- 'debug',
627
- `Extracted section ${currentSection} in section ${
628
- sectionIndex + 1
629
- }`,
630
- { key, text: content[key] }
631
- );
632
- }
633
- currentSection = line.replace('# ', '');
634
- currentText = [];
635
- this.log(
636
- 'debug',
637
- `Starting new section ${currentSection} in section ${
638
- sectionIndex + 1
639
- }`
640
- );
641
- } else {
642
- currentText.push(line);
643
- }
644
- }
645
-
646
- if (currentSection && currentText.length > 0) {
647
- const key = currentSection
648
- .toLowerCase()
649
- .replace(/\s+/g, '')
650
- .replace(/([A-Z])/g, (match) => match.toLowerCase());
651
- content[key] = currentText.join(' ').trim();
652
- this.log(
653
- 'debug',
654
- `Extracted final section ${currentSection} in section ${
655
- sectionIndex + 1
656
- }`,
657
- { key, text: content[key] }
658
- );
659
- }
660
-
661
- const parsedContent = {
662
- voiceOfTheSoul:
663
- content['thevoiceofthesoul'] || content['avozdaalma'] || '',
664
- giftsYouBear:
665
- content['thegiftsyoubear'] || content['osdonsquevocêcarrega'] || '',
666
- shadowsYouFace:
667
- content['theshadowsyouface'] || content['assombrasqueenfrenta'] || '',
668
- rhythmOfYourDays:
669
- content['therhythmofyourdays'] || content['oritmodosseusdias'] || '',
670
- tiesThatBind:
671
- content['thetiesthatbind'] || content['oslaçosqueteconectam'] || '',
672
- lightWithin: content['thelightwithin'] || content['aluzinterior'] || '',
673
- };
674
-
675
- if (Object.values(parsedContent).some((value) => !value)) {
676
- this.log(
677
- 'warn',
678
- `Malformed content response for section ${sectionIndex + 1}`,
679
- {
680
- parsedContent,
681
- response: section,
682
- }
683
- );
684
- }
685
-
686
- return parsedContent;
687
- });
688
-
689
- this.log('info', 'Completed parseContentResponse', { result });
690
- return result;
691
- }
692
-
693
- private parseLeonardoPromptResponse(response: string) {
694
- this.log('debug', 'Starting parseLeonardoPromptResponse', {
695
- responseLength: response.length,
696
- });
697
-
698
- const lines = response.split('\n').filter((line) => line.trim());
699
- this.log('debug', 'Split response into lines', {
700
- linesCount: lines.length,
701
- lines,
702
- });
703
-
704
- const prompts: Array<{ malePrompt: string; femalePrompt: string }> = [];
705
-
706
- for (let i = 0; i < lines.length; i += 2) {
707
- const maleLine = lines[i];
708
- const femaleLine = lines[i + 1];
709
-
710
- const malePrompt = maleLine.startsWith(`${Math.floor(i / 2) + 1}.m`)
711
- ? maleLine.split(`${Math.floor(i / 2) + 1}.m`)[1]?.trim()
712
- : '';
713
- const femalePrompt = femaleLine.startsWith(`${Math.floor(i / 2) + 1}.f`)
714
- ? femaleLine.split(`${Math.floor(i / 2) + 1}.f`)[1]?.trim()
715
- : '';
716
-
717
- prompts.push({ malePrompt, femalePrompt });
718
- this.log(
719
- 'debug',
720
- `Parsed prompts for archetype ${Math.floor(i / 2) + 1}`,
721
- { malePrompt, femalePrompt }
722
- );
723
-
724
- if (!malePrompt || !femalePrompt) {
725
- this.log(
726
- 'warn',
727
- `Malformed Leonardo prompt for archetype ${Math.floor(i / 2) + 1}`,
728
- {
729
- malePrompt,
730
- femalePrompt,
731
- maleLine,
732
- femaleLine,
733
- }
734
- );
735
- }
736
- }
737
-
738
- this.log('info', 'Completed parseLeonardoPromptResponse', { prompts });
739
- return prompts;
740
- }
741
223
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zodic/shared",
3
- "version": "0.0.315",
3
+ "version": "0.0.317",
4
4
  "module": "index.ts",
5
5
  "type": "module",
6
6
  "publishConfig": {