@zodic/shared 0.0.371 → 0.0.373

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.
@@ -28,42 +28,41 @@ export class ArchetypeService {
28
28
  message: string,
29
29
  context: Record<string, any> = {}
30
30
  ) {
31
- const logMessage = `[${level.toUpperCase()}] ${message}`;
32
-
33
- console.log(logMessage, context);
34
- // try {
35
- // await db
36
- // .insert(schema.logs)
37
- // .values({
38
- // id: logId,
39
- // level,
40
- // message,
41
- // context: JSON.stringify(context),
42
- // createdAt: new Date().getTime(),
43
- // })
44
- // .execute();
45
- // } catch (error) {
46
- // console.error('[ERROR] Failed to persist log to database:', {
47
- // error,
48
- // logId,
49
- // message,
50
- // context,
51
- // });
52
- // }
31
+ const logMessage = `[${new Date().toISOString()}] [${level.toUpperCase()}] ${message}`;
32
+
33
+ console[level](logMessage, context);
53
34
  }
54
35
 
55
- // Replace generateArchetypeNames and generateArchetypeNamesBatch
56
36
  async generateArchetypeNames(
57
37
  combinationString: string,
58
- overrideExisting: boolean = false,
38
+ override: boolean = false,
59
39
  indexesToGenerate: number[] = [1, 2, 3]
60
40
  ) {
61
41
  await this.log('info', 'Starting generateArchetypeNames', {
62
42
  combinationString,
63
- overrideExisting,
43
+ override,
64
44
  indexesToGenerate,
65
45
  });
66
46
 
47
+ const db = this.context.drizzle();
48
+ const existingArchetypes = await db
49
+ .select()
50
+ .from(schema.archetypesData)
51
+ .where(eq(schema.archetypesData.combination, combinationString))
52
+ .execute();
53
+
54
+ if (
55
+ !override &&
56
+ existingArchetypes.length >= 3 * 2 * 2 && // 3 indexes * 2 genders * 2 languages
57
+ existingArchetypes.every((a) => a.name && a.essenceLine)
58
+ ) {
59
+ await this.log('info', 'Skipping archetype names generation', {
60
+ reason: 'All archetypes have names and essence lines',
61
+ existingCount: existingArchetypes.length,
62
+ });
63
+ return;
64
+ }
65
+
67
66
  const [sun, ascendant, moon] = combinationString.split(
68
67
  '-'
69
68
  ) as ZodiacSignSlug[];
@@ -95,8 +94,6 @@ export class ArchetypeService {
95
94
  portugueseVariants,
96
95
  });
97
96
 
98
- const db = this.context.drizzle();
99
-
100
97
  async function isEnglishNameDuplicate(name: string): Promise<boolean> {
101
98
  const result = await db
102
99
  .select({ name: schema.archetypesData.name })
@@ -121,7 +118,10 @@ export class ArchetypeService {
121
118
  await this.log(
122
119
  'debug',
123
120
  `Skipping index ${index} as it is not in indexesToGenerate`,
124
- { index, indexesToGenerate }
121
+ {
122
+ index,
123
+ indexesToGenerate,
124
+ }
125
125
  );
126
126
  continue;
127
127
  }
@@ -148,6 +148,15 @@ export class ArchetypeService {
148
148
  const essenceLine =
149
149
  lang === 'en-us' ? entry.essenceLine : ptVariant.essenceLine;
150
150
 
151
+ const existing = existingArchetypes.find((a) => a.id === id);
152
+ if (existing && !override && existing.name && existing.essenceLine) {
153
+ await this.log('debug', `Skipping existing archetype ${id}`, {
154
+ name: existing.name,
155
+ essenceLine: existing.essenceLine,
156
+ });
157
+ continue;
158
+ }
159
+
151
160
  await this.log('debug', `Saving archetype name for ${id}`, {
152
161
  name,
153
162
  essenceLine,
@@ -171,6 +180,7 @@ export class ArchetypeService {
171
180
  name,
172
181
  essenceLine,
173
182
  updatedAt: new Date().getTime(),
183
+ status: 'idle',
174
184
  },
175
185
  });
176
186
 
@@ -245,12 +255,14 @@ export class ArchetypeService {
245
255
  async generateDescriptionsAndVirtues(
246
256
  combinationString: string,
247
257
  gender: Gender,
248
- language: string
258
+ language: string,
259
+ override: boolean = false
249
260
  ): Promise<ParsedDescriptionAndVirtues[]> {
250
261
  await this.log('info', 'Starting generateDescriptionsAndVirtues', {
251
262
  combinationString,
252
263
  gender,
253
264
  language,
265
+ override,
254
266
  });
255
267
 
256
268
  const db = this.context.drizzle();
@@ -261,11 +273,27 @@ export class ArchetypeService {
261
273
  and(
262
274
  eq(schema.archetypesData.combination, combinationString),
263
275
  eq(schema.archetypesData.gender, gender),
264
- eq(schema.archetypesData.language, 'en-us')
276
+ eq(schema.archetypesData.language, language)
265
277
  )
266
278
  )
267
279
  .execute();
268
280
 
281
+ if (
282
+ !override &&
283
+ archetypes.every((a) => a.description && a.virtues !== '[]')
284
+ ) {
285
+ await this.log('info', 'Skipping descriptions and virtues generation', {
286
+ reason: 'Descriptions and virtues already exist for all archetypes',
287
+ });
288
+ return archetypes.map((a) => ({
289
+ descriptionEN: a.description || '',
290
+ descriptionPTM: a.description || '',
291
+ descriptionPTF: a.description || '',
292
+ virtuesEN: JSON.parse(a.virtues || '[]'),
293
+ virtuesPT: JSON.parse(a.virtues || '[]'),
294
+ }));
295
+ }
296
+
269
297
  await this.log('info', 'Fetched archetypes for description generation', {
270
298
  archetypesCount: archetypes.length,
271
299
  names: archetypes.map((a) => a.name),
@@ -289,9 +317,7 @@ export class ArchetypeService {
289
317
  const descVirtueResponse = await this.context
290
318
  .api()
291
319
  .callTogether.single(descVirtueMessages, {
292
- options: {
293
- temperature: 0.5,
294
- },
320
+ options: { temperature: 0.5 },
295
321
  });
296
322
  if (!descVirtueResponse) {
297
323
  await this.log('error', 'No response for descriptions and virtues', {
@@ -313,87 +339,107 @@ export class ArchetypeService {
313
339
 
314
340
  for (let i = 0; i < 3; i++) {
315
341
  const index = (i + 1).toString();
316
-
317
- // Update English entry (en-us)
318
342
  const enId = `${combinationString}:${gender}:${index}`;
319
- await this.log('debug', `Updating description and virtues for ${enId}`, {
320
- description: parsedDescVirtues[i].descriptionEN,
321
- virtues: parsedDescVirtues[i].virtuesEN,
322
- });
323
- await db
324
- .update(schema.archetypesData)
325
- .set({
326
- description: parsedDescVirtues[i].descriptionEN,
327
- virtues: JSON.stringify(parsedDescVirtues[i].virtuesEN),
328
- updatedAt: new Date().getTime(),
329
- })
330
- .where(
331
- and(
332
- eq(schema.archetypesData.id, enId),
333
- eq(schema.archetypesData.language, 'en-us')
334
- )
335
- )
336
- .execute();
337
- await this.log('info', `Updated description and virtues for ${enId}`);
343
+ const ptId = `${combinationString}:${gender}:${index}:pt`;
338
344
 
339
- // Update Portuguese entries (pt-br) for both male and female
340
- const ptIdMale = `${combinationString}:${gender}:${index}:pt`;
341
- await this.log(
342
- 'debug',
343
- `Updating description and virtues for ${ptIdMale} (male)`,
344
- {
345
- description: parsedDescVirtues[i].descriptionPTM,
346
- virtues: parsedDescVirtues[i].virtuesPT,
345
+ // Update English entry (en-us)
346
+ if (language === 'en-us') {
347
+ const enExisting = archetypes.find((a) => a.id === enId);
348
+ if (
349
+ !override &&
350
+ enExisting?.description &&
351
+ enExisting.virtues !== '[]'
352
+ ) {
353
+ await this.log(
354
+ 'debug',
355
+ `Skipping existing description and virtues for ${enId}`,
356
+ {
357
+ description: enExisting.description,
358
+ virtues: enExisting.virtues,
359
+ }
360
+ );
361
+ } else {
362
+ await this.log(
363
+ 'debug',
364
+ `Updating description and virtues for ${enId}`,
365
+ {
366
+ description: parsedDescVirtues[i].descriptionEN,
367
+ virtues: parsedDescVirtues[i].virtuesEN,
368
+ }
369
+ );
370
+ await db
371
+ .update(schema.archetypesData)
372
+ .set({
373
+ description: parsedDescVirtues[i].descriptionEN,
374
+ virtues: JSON.stringify(parsedDescVirtues[i].virtuesEN),
375
+ updatedAt: new Date().getTime(),
376
+ })
377
+ .where(
378
+ and(
379
+ eq(schema.archetypesData.id, enId),
380
+ eq(schema.archetypesData.language, 'en-us')
381
+ )
382
+ )
383
+ .execute();
384
+ await this.log('info', `Updated description and virtues for ${enId}`);
347
385
  }
348
- );
349
- await db
350
- .update(schema.archetypesData)
351
- .set({
352
- description: parsedDescVirtues[i].descriptionPTM,
353
- virtues: JSON.stringify(parsedDescVirtues[i].virtuesPT),
354
- updatedAt: new Date().getTime(),
355
- })
356
- .where(
357
- and(
358
- eq(schema.archetypesData.id, ptIdMale),
359
- eq(schema.archetypesData.language, 'pt-br'),
360
- eq(schema.archetypesData.gender, 'male')
361
- )
362
- )
363
- .execute();
364
- await this.log(
365
- 'info',
366
- `Updated description and virtues for ${ptIdMale} (male)`
367
- );
386
+ }
368
387
 
369
- const ptIdFemale = `${combinationString}:${gender}:${index}:pt`;
370
- await this.log(
371
- 'debug',
372
- `Updating description and virtues for ${ptIdFemale} (female)`,
373
- {
374
- description: parsedDescVirtues[i].descriptionPTF,
375
- virtues: parsedDescVirtues[i].virtuesPT,
388
+ // Update Portuguese entries (pt-br)
389
+ if (language === 'pt-br') {
390
+ for (const ptGender of ['male', 'female']) {
391
+ const ptExisting = archetypes.find(
392
+ (a) => a.id === ptId && a.gender === ptGender
393
+ );
394
+ if (
395
+ !override &&
396
+ ptExisting?.description &&
397
+ ptExisting.virtues !== '[]'
398
+ ) {
399
+ await this.log(
400
+ 'debug',
401
+ `Skipping existing description and virtues for ${ptId} (${ptGender})`,
402
+ {
403
+ description: ptExisting.description,
404
+ virtues: ptExisting.virtues,
405
+ }
406
+ );
407
+ continue;
408
+ }
409
+
410
+ const description =
411
+ ptGender === 'male'
412
+ ? parsedDescVirtues[i].descriptionPTM
413
+ : parsedDescVirtues[i].descriptionPTF;
414
+ await this.log(
415
+ 'debug',
416
+ `Updating description and virtues for ${ptId} (${ptGender})`,
417
+ {
418
+ description,
419
+ virtues: parsedDescVirtues[i].virtuesPT,
420
+ }
421
+ );
422
+ await db
423
+ .update(schema.archetypesData)
424
+ .set({
425
+ description,
426
+ virtues: JSON.stringify(parsedDescVirtues[i].virtuesPT),
427
+ updatedAt: new Date().getTime(),
428
+ })
429
+ .where(
430
+ and(
431
+ eq(schema.archetypesData.id, ptId),
432
+ eq(schema.archetypesData.language, 'pt-br'),
433
+ eq(schema.archetypesData.gender, ptGender)
434
+ )
435
+ )
436
+ .execute();
437
+ await this.log(
438
+ 'info',
439
+ `Updated description and virtues for ${ptId} (${ptGender})`
440
+ );
376
441
  }
377
- );
378
- await db
379
- .update(schema.archetypesData)
380
- .set({
381
- description: parsedDescVirtues[i].descriptionPTF,
382
- virtues: JSON.stringify(parsedDescVirtues[i].virtuesPT),
383
- updatedAt: new Date().getTime(),
384
- })
385
- .where(
386
- and(
387
- eq(schema.archetypesData.id, ptIdFemale),
388
- eq(schema.archetypesData.language, 'pt-br'),
389
- eq(schema.archetypesData.gender, 'female')
390
- )
391
- )
392
- .execute();
393
- await this.log(
394
- 'info',
395
- `Updated description and virtues for ${ptIdFemale} (female)`
396
- );
442
+ }
397
443
  }
398
444
 
399
445
  await this.log('info', 'Completed generateDescriptionsAndVirtues', {
@@ -451,8 +497,6 @@ export class ArchetypeService {
451
497
 
452
498
  for (let i = 0; i < lines.length; i++) {
453
499
  let line = lines[i];
454
-
455
- // Remove markdown bold (**...**) from field names
456
500
  line = line.replace(/\*\*(.*?)\*\*/g, '$1');
457
501
 
458
502
  if (
@@ -460,7 +504,7 @@ export class ArchetypeService {
460
504
  line.startsWith('2.') ||
461
505
  line.startsWith('3.')
462
506
  ) {
463
- continue; // Skip entry number lines
507
+ continue;
464
508
  }
465
509
 
466
510
  if (line.startsWith('• Description EN:')) {
@@ -510,7 +554,6 @@ export class ArchetypeService {
510
554
  virtuesPT,
511
555
  });
512
556
  } else if (line.startsWith('• Virtues:')) {
513
- // Fallback for older response format: use English virtues and attempt to translate
514
557
  currentField = 'virtuesEN';
515
558
  virtuesEN = line
516
559
  .split('• Virtues:')[1]
@@ -524,14 +567,12 @@ export class ArchetypeService {
524
567
  { virtuesEN }
525
568
  );
526
569
 
527
- // Simple translation mapping for common virtues (as a fallback)
528
570
  const virtueTranslations: { [key: string]: string } = {
529
571
  Harmony: 'Harmonia',
530
572
  Intuition: 'Intuição',
531
573
  Grace: 'Graça',
532
- // Add more translations as needed
533
574
  };
534
- virtuesPT = virtuesEN.map((v) => virtueTranslations[v] || v); // Fallback to English if no translation
575
+ virtuesPT = virtuesEN.map((v) => virtueTranslations[v] || v);
535
576
  this.log(
536
577
  'debug',
537
578
  `Generated virtuesPT (fallback) for entry ${entryIndex + 1}`,
@@ -563,7 +604,6 @@ export class ArchetypeService {
563
604
  }
564
605
  }
565
606
 
566
- // Validate the parsed data
567
607
  if (
568
608
  !descriptionEN ||
569
609
  !descriptionPTM ||
@@ -611,12 +651,14 @@ export class ArchetypeService {
611
651
  combinationString: string,
612
652
  gender: Gender,
613
653
  language: string,
614
- descriptions: Array<{ descriptionEN: string }>
654
+ descriptions: Array<{ descriptionEN: string }>,
655
+ override: boolean = false
615
656
  ) {
616
657
  await this.log('info', 'Starting generateContent', {
617
658
  combinationString,
618
659
  gender,
619
660
  language,
661
+ override,
620
662
  });
621
663
 
622
664
  const db = this.context.drizzle();
@@ -627,11 +669,18 @@ export class ArchetypeService {
627
669
  and(
628
670
  eq(schema.archetypesData.combination, combinationString),
629
671
  eq(schema.archetypesData.gender, gender),
630
- eq(schema.archetypesData.language, 'en-us')
672
+ eq(schema.archetypesData.language, language)
631
673
  )
632
674
  )
633
675
  .execute();
634
676
 
677
+ if (!override && archetypes.every((a) => a.content !== '[]')) {
678
+ await this.log('info', 'Skipping content generation', {
679
+ reason: 'Content already exists for all archetypes',
680
+ });
681
+ return;
682
+ }
683
+
635
684
  await this.log('info', 'Fetched archetypes for content generation', {
636
685
  archetypesCount: archetypes.length,
637
686
  names: archetypes.map((a) => a.name),
@@ -639,6 +688,20 @@ export class ArchetypeService {
639
688
 
640
689
  const contentResults = [];
641
690
  for (let i = 0; i < 3; i++) {
691
+ const index = (i + 1).toString();
692
+ const id = `${combinationString}:${gender}:${index}${
693
+ language === 'pt-br' ? ':pt' : ''
694
+ }`;
695
+ const existing = archetypes.find((a) => a.id === id);
696
+
697
+ if (!override && existing && existing?.content !== '[]') {
698
+ await this.log('debug', `Skipping existing content for ${id}`, {
699
+ content: existing.content,
700
+ });
701
+ contentResults.push({}); // Placeholder
702
+ continue;
703
+ }
704
+
642
705
  await this.log('debug', `Generating content for archetype ${i + 1}`, {
643
706
  name: archetypes[i].name,
644
707
  });
@@ -660,7 +723,10 @@ export class ArchetypeService {
660
723
  await this.log(
661
724
  'error',
662
725
  `No response for content of archetype ${i + 1}`,
663
- { combinationString, archetype: archetypes[i].name }
726
+ {
727
+ combinationString,
728
+ archetype: archetypes[i].name,
729
+ }
664
730
  );
665
731
  throw new Error(
666
732
  `Failed to generate content for archetype ${
@@ -671,7 +737,9 @@ export class ArchetypeService {
671
737
  await this.log(
672
738
  'info',
673
739
  `Received content response for archetype ${i + 1}`,
674
- { responseLength: contentResponse.length }
740
+ {
741
+ responseLength: contentResponse.length,
742
+ }
675
743
  );
676
744
 
677
745
  await this.log(
@@ -684,58 +752,52 @@ export class ArchetypeService {
684
752
  parsedContent,
685
753
  });
686
754
 
687
- const index = (i + 1).toString();
688
- for (const lang of ['en-us', 'pt-br']) {
689
- const contentLangIndex =
690
- lang === 'en-us' ? 0 : gender === 'male' ? 1 : 2;
691
- const content = [
692
- {
693
- section: 'voiceOfTheSoul',
694
- text: parsedContent[contentLangIndex].voiceOfTheSoul,
695
- },
696
- {
697
- section: 'giftsYouBear',
698
- text: parsedContent[contentLangIndex].giftsYouBear,
699
- },
700
- {
701
- section: 'shadowsYouFace',
702
- text: parsedContent[contentLangIndex].shadowsYouFace,
703
- },
704
- {
705
- section: 'rhythmOfYourDays',
706
- text: parsedContent[contentLangIndex].rhythmOfYourDays,
707
- },
708
- {
709
- section: 'tiesThatBind',
710
- text: parsedContent[contentLangIndex].tiesThatBind,
711
- },
712
- {
713
- section: 'lightWithin',
714
- text: parsedContent[contentLangIndex].lightWithin,
715
- },
716
- ];
755
+ const contentLangIndex =
756
+ language === 'en-us' ? 0 : gender === 'male' ? 1 : 2;
757
+ const content = [
758
+ {
759
+ section: 'voiceOfTheSoul',
760
+ text: parsedContent[contentLangIndex].voiceOfTheSoul,
761
+ },
762
+ {
763
+ section: 'giftsYouBear',
764
+ text: parsedContent[contentLangIndex].giftsYouBear,
765
+ },
766
+ {
767
+ section: 'shadowsYouFace',
768
+ text: parsedContent[contentLangIndex].shadowsYouFace,
769
+ },
770
+ {
771
+ section: 'rhythmOfYourDays',
772
+ text: parsedContent[contentLangIndex].rhythmOfYourDays,
773
+ },
774
+ {
775
+ section: 'tiesThatBind',
776
+ text: parsedContent[contentLangIndex].tiesThatBind,
777
+ },
778
+ {
779
+ section: 'lightWithin',
780
+ text: parsedContent[contentLangIndex].lightWithin,
781
+ },
782
+ ];
717
783
 
718
- const id = `${combinationString}:${gender}:${index}${
719
- lang === 'pt-br' ? ':pt' : ''
720
- }`;
721
- await this.log('debug', `Updating content for ${id}`, { content });
722
-
723
- await db
724
- .update(schema.archetypesData)
725
- .set({
726
- content: JSON.stringify(content),
727
- updatedAt: new Date().getTime(),
728
- })
729
- .where(
730
- and(
731
- eq(schema.archetypesData.id, id),
732
- eq(schema.archetypesData.language, lang)
733
- )
784
+ await this.log('debug', `Updating content for ${id}`, { content });
785
+
786
+ await db
787
+ .update(schema.archetypesData)
788
+ .set({
789
+ content: JSON.stringify(content),
790
+ updatedAt: new Date().getTime(),
791
+ })
792
+ .where(
793
+ and(
794
+ eq(schema.archetypesData.id, id),
795
+ eq(schema.archetypesData.language, language)
734
796
  )
735
- .execute();
797
+ )
798
+ .execute();
736
799
 
737
- await this.log('info', `Updated content for ${id}`);
738
- }
800
+ await this.log('info', `Updated content for ${id}`);
739
801
  }
740
802
 
741
803
  await this.log('info', 'Completed generateContent', {
@@ -798,7 +860,10 @@ export class ArchetypeService {
798
860
  `Extracted section ${currentSection} in section ${
799
861
  sectionIndex + 1
800
862
  }`,
801
- { key, text: content[key] }
863
+ {
864
+ key,
865
+ text: content[key],
866
+ }
802
867
  );
803
868
  }
804
869
  currentSection = line.replace('# ', '');
@@ -825,7 +890,10 @@ export class ArchetypeService {
825
890
  `Extracted final section ${currentSection} in section ${
826
891
  sectionIndex + 1
827
892
  }`,
828
- { key, text: content[key] }
893
+ {
894
+ key,
895
+ text: content[key],
896
+ }
829
897
  );
830
898
  }
831
899
 
@@ -863,26 +931,22 @@ export class ArchetypeService {
863
931
 
864
932
  async generateLeonardoPrompts(
865
933
  combinationString: string,
866
- gender: Gender, // User's gender, used for filtering results in ArchetypeWorkflow.execute
867
- language: string, // User's language, used for filtering results in ArchetypeWorkflow.execute
868
- descriptions: Array<{ descriptionEN: string }>
934
+ gender: Gender,
935
+ language: string,
936
+ descriptions: Array<{ descriptionEN: string }>,
937
+ override: boolean = false
869
938
  ) {
870
939
  await this.log('info', 'Starting generateLeonardoPrompts', {
871
940
  combinationString,
872
941
  gender,
873
942
  language,
943
+ override,
874
944
  });
875
945
 
876
946
  const db = this.context.drizzle();
877
-
878
947
  type Binary = 'male' | 'female';
879
-
880
- // Fetch archetypes for male and female with language = 'en-us'
881
948
  const allGenders: Binary[] = ['male', 'female'];
882
- const archetypesByGender: Record<Binary, any[]> = {
883
- male: [],
884
- female: [],
885
- };
949
+ const archetypesByGender: Record<Binary, any[]> = { male: [], female: [] };
886
950
 
887
951
  for (const g of allGenders) {
888
952
  const archetypes = await db
@@ -892,14 +956,13 @@ export class ArchetypeService {
892
956
  and(
893
957
  eq(schema.archetypesData.combination, combinationString),
894
958
  eq(schema.archetypesData.gender, g),
895
- eq(schema.archetypesData.language, 'en-us')
959
+ eq(schema.archetypesData.language, language)
896
960
  )
897
961
  )
898
962
  .execute();
899
963
  archetypesByGender[g] = archetypes;
900
964
  }
901
965
 
902
- // Validate that we have archetypes for all genders (3 archetypes per gender)
903
966
  for (const g of allGenders) {
904
967
  if (archetypesByGender[g].length !== 3) {
905
968
  await this.log(
@@ -916,6 +979,16 @@ export class ArchetypeService {
916
979
  }
917
980
  }
918
981
 
982
+ if (
983
+ !override &&
984
+ archetypesByGender[gender as Binary].every((a) => a.leonardoPrompt)
985
+ ) {
986
+ await this.log('info', 'Skipping Leonardo prompts generation', {
987
+ reason: 'Leonardo prompts already exist for all archetypes',
988
+ });
989
+ return;
990
+ }
991
+
919
992
  await this.log('info', 'Fetched archetypes for Leonardo prompts', {
920
993
  maleArchetypesCount: archetypesByGender['male'].length,
921
994
  femaleArchetypesCount: archetypesByGender['female'].length,
@@ -925,8 +998,6 @@ export class ArchetypeService {
925
998
  },
926
999
  });
927
1000
 
928
- // Since descriptions are provided as an input (from generateDescriptionsAndVirtues),
929
- // we can use the same descriptions for all genders, as they are gender-neutral (en-us)
930
1001
  const promptMessages = this.context
931
1002
  .buildLLMMessages()
932
1003
  .generateCosmicMirrorArchetypeLeonardoPrompts(
@@ -957,7 +1028,6 @@ export class ArchetypeService {
957
1028
  const parsedPrompts = this.parseLeonardoPromptResponse(promptResponse);
958
1029
  await this.log('info', 'Parsed Leonardo prompts', { parsedPrompts });
959
1030
 
960
- // Update archetypes for all genders
961
1031
  for (const g of allGenders) {
962
1032
  for (let i = 0; i < 3; i++) {
963
1033
  const index = (i + 1).toString();
@@ -966,105 +1036,39 @@ export class ArchetypeService {
966
1036
  ? parsedPrompts[i].malePrompt
967
1037
  : parsedPrompts[i].femalePrompt;
968
1038
 
969
- // Update English entry (en-us)
970
- const enId = `${combinationString}:${g}:${index}`;
971
- await this.log(
972
- 'debug',
973
- `Updating Leonardo prompt for ${enId} (en-us)`,
974
- {
975
- leonardoPrompt,
976
- }
977
- );
978
-
979
- const enUpdateResult = await db
980
- .update(schema.archetypesData)
981
- .set({
982
- leonardoPrompt,
983
- updatedAt: new Date().getTime(),
984
- })
985
- .where(
986
- and(
987
- eq(schema.archetypesData.id, enId),
988
- eq(schema.archetypesData.language, 'en-us'),
989
- eq(schema.archetypesData.gender, g)
990
- )
991
- )
992
- .execute();
993
-
994
- await this.log('info', `Updated Leonardo prompt for ${enId} (en-us)`, {
995
- rowsAffected: enUpdateResult.rowsAffected,
996
- });
997
-
998
- if (enUpdateResult.rowsAffected === 0) {
999
- await this.log(
1000
- 'error',
1001
- `Failed to update Leonardo prompt for ${enId} (en-us)`,
1002
- {
1003
- enId,
1004
- language: 'en-us',
1005
- gender: g,
1006
- }
1007
- );
1008
- throw new Error(
1009
- `Failed to update Leonardo prompt for ${enId} (en-us)`
1010
- );
1011
- }
1012
-
1013
- // Update Portuguese entries (pt-br) for male and female
1014
- const ptId = `${combinationString}:${g}:${index}:pt`;
1015
- const ptGenders = ['male', 'female'];
1016
-
1017
- for (const ptGender of ptGenders) {
1018
- const ptLeonardoPrompt =
1019
- ptGender === 'male'
1020
- ? parsedPrompts[i].malePrompt
1021
- : parsedPrompts[i].femalePrompt;
1022
-
1039
+ const id = `${combinationString}:${g}:${index}${
1040
+ language === 'pt-br' ? ':pt' : ''
1041
+ }`;
1042
+ const existing = archetypesByGender[g].find((a) => a.id === id);
1043
+ if (!override && existing?.leonardoPrompt) {
1023
1044
  await this.log(
1024
1045
  'debug',
1025
- `Updating Leonardo prompt for ${ptId} (pt-br, gender: ${ptGender})`,
1046
+ `Skipping existing Leonardo prompt for ${id}`,
1026
1047
  {
1027
- leonardoPrompt: ptLeonardoPrompt,
1048
+ leonardoPrompt: existing.leonardoPrompt,
1028
1049
  }
1029
1050
  );
1030
-
1031
- const ptUpdateResult = await db
1051
+ } else {
1052
+ await this.log('debug', `Updating Leonardo prompt for ${id}`, {
1053
+ leonardoPrompt,
1054
+ });
1055
+ const updateResult = await db
1032
1056
  .update(schema.archetypesData)
1033
1057
  .set({
1034
- leonardoPrompt: ptLeonardoPrompt,
1058
+ leonardoPrompt,
1035
1059
  updatedAt: new Date().getTime(),
1036
1060
  })
1037
1061
  .where(
1038
1062
  and(
1039
- eq(schema.archetypesData.id, ptId),
1040
- eq(schema.archetypesData.language, 'pt-br'),
1041
- eq(schema.archetypesData.gender, ptGender)
1063
+ eq(schema.archetypesData.id, id),
1064
+ eq(schema.archetypesData.language, language),
1065
+ eq(schema.archetypesData.gender, g)
1042
1066
  )
1043
1067
  )
1044
1068
  .execute();
1045
-
1046
- await this.log(
1047
- 'info',
1048
- `Updated Leonardo prompt for ${ptId} (pt-br, gender: ${ptGender})`,
1049
- {
1050
- rowsAffected: ptUpdateResult.rowsAffected,
1051
- }
1052
- );
1053
-
1054
- if (ptUpdateResult.rowsAffected === 0) {
1055
- await this.log(
1056
- 'error',
1057
- `Failed to update Leonardo prompt for ${ptId} (pt-br, gender: ${ptGender})`,
1058
- {
1059
- ptId,
1060
- language: 'pt-br',
1061
- gender: ptGender,
1062
- }
1063
- );
1064
- throw new Error(
1065
- `Failed to update Leonardo prompt for ${ptId} (pt-br, gender: ${ptGender})`
1066
- );
1067
- }
1069
+ await this.log('info', `Updated Leonardo prompt for ${id}`, {
1070
+ rowsAffected: updateResult.rowsAffected,
1071
+ });
1068
1072
  }
1069
1073
  }
1070
1074
  }
@@ -1092,11 +1096,10 @@ export class ArchetypeService {
1092
1096
  let currentArchetype = 0;
1093
1097
 
1094
1098
  for (let i = 0; i < lines.length; i += 4) {
1095
- // Expect pairs of label and prompt: "1.m", male prompt, "1.f", female prompt
1096
- const maleLabel = lines[i]; // "1.m"
1097
- const malePromptLine = lines[i + 1]; // Male prompt text
1098
- const femaleLabel = lines[i + 2]; // "1.f"
1099
- const femalePromptLine = lines[i + 3]; // Female prompt text
1099
+ const maleLabel = lines[i];
1100
+ const malePromptLine = lines[i + 1];
1101
+ const femaleLabel = lines[i + 2];
1102
+ const femalePromptLine = lines[i + 3];
1100
1103
 
1101
1104
  currentArchetype++;
1102
1105
  const expectedMaleLabel = `${currentArchetype}.m`;