@zodic/shared 0.0.312 → 0.0.314

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.
@@ -3,6 +3,7 @@ import { inject, injectable } from 'inversify';
3
3
  import { ChatMessages, Composition, schema } from '../..';
4
4
  import { KVArchetype, ZodiacSignSlug } from '../../types/scopes/legacy';
5
5
  import { generateArchetypePrompt } from '../../utils/archetypeNamesMessages';
6
+ import { duplicatedArchetypeNamePrompt } from '../../utils/duplicatedArchetypeNamePrompt';
6
7
  import { buildCosmicMirrorArchetypeKVKey } from '../../utils/KVKeysBuilders';
7
8
  import { AppContext } from '../base';
8
9
 
@@ -449,18 +450,36 @@ export class ArchetypeService {
449
450
 
450
451
  const { english, portuguese } = this.parseArchetypeNameBlocks(block);
451
452
 
453
+ // Check if parsing produced the expected number of entries
454
+ if (english.length !== 3 || portuguese.length !== 3) {
455
+ console.error(
456
+ `[Batch] Parsing failed for ${combination}. Expected 3 entries, got English: ${english.length}, Portuguese: ${portuguese.length}`
457
+ );
458
+ continue; // Skip this combination if parsing failed
459
+ }
460
+
452
461
  for (let j = 0; j < 3; j++) {
453
462
  const index = (j + 1).toString();
454
463
  const englishEntry = english[j];
455
464
  const ptEntry = portuguese[j];
456
465
 
457
- if (await isEnglishNameDuplicate(englishEntry.name)) {
466
+ // Skip if either entry is missing (shouldn't happen with the above check, but added for safety)
467
+ if (!englishEntry || !ptEntry) {
458
468
  console.warn(
459
- `⚠️ [Batch] Duplicate name skipped: ${englishEntry.name}`
469
+ `[Batch] Skipping index ${index} for ${combination} due to missing parsed data. English: ${JSON.stringify(
470
+ englishEntry
471
+ )}, Portuguese: ${JSON.stringify(ptEntry)}`
460
472
  );
461
473
  continue;
462
474
  }
463
475
 
476
+ // if (await isEnglishNameDuplicate(englishEntry.name)) {
477
+ // console.warn(
478
+ // `⚠️ [Batch] Duplicate name skipped: ${englishEntry.name}`
479
+ // );
480
+ // continue;
481
+ // }
482
+
464
483
  for (const gender of ['male', 'female']) {
465
484
  const enId = `${combination}:${gender}:${index}`;
466
485
  const ptId = `${combination}:${gender}:${index}:pt`;
@@ -733,26 +752,221 @@ export class ArchetypeService {
733
752
  );
734
753
  }
735
754
 
736
- async recycleArchetypeNameDumpsBatch(compositions: Composition[]): Promise<void> {
755
+ async regenerateDuplicateArchetypeNamesBatch(
756
+ entriesByCombination: Record<string, any[]>
757
+ ) {
758
+ const db = this.context.drizzle();
759
+ console.log(
760
+ `[RegenerateDuplicatesBatch] Processing batch with ${
761
+ Object.keys(entriesByCombination).length
762
+ } combinations`
763
+ );
764
+
765
+ // Process each combination in the batch
766
+ for (const [combination, entries] of Object.entries(entriesByCombination)) {
767
+ console.log(
768
+ `[RegenerateDuplicatesBatch] Processing combination: ${combination}`
769
+ );
770
+
771
+ // Fetch all existing English names for this combination (across all archetypeIndex, gender, language)
772
+ const existingNamesResult = await db
773
+ .selectDistinct({ name: schema.archetypesData.name })
774
+ .from(schema.archetypesData)
775
+ .where(
776
+ and(
777
+ eq(schema.archetypesData.combination, combination),
778
+ eq(schema.archetypesData.language, 'en-us')
779
+ )
780
+ )
781
+ .execute();
782
+
783
+ let existingNames = existingNamesResult.map((r) => r.name);
784
+ console.log(
785
+ `[RegenerateDuplicatesBatch] Existing names for ${combination}: ${existingNames.join(
786
+ ', '
787
+ )}`
788
+ );
789
+
790
+ // Process each entry with the duplicate name in this combination
791
+ for (const entry of entries) {
792
+ const { archetypeIndex, essenceLine } = entry;
793
+ console.log(
794
+ `[RegenerateDuplicatesBatch] Regenerating name for ${combination} (archetypeIndex: ${archetypeIndex})`
795
+ );
796
+
797
+ let newName: {
798
+ name_en: string;
799
+ name_pt_male: string;
800
+ name_pt_female: string;
801
+ } | null = null;
802
+ let attempts = 0;
803
+ const maxAttempts = 5;
804
+
805
+ // Generate a new name until a unique one is found
806
+ while (attempts < maxAttempts) {
807
+ attempts++;
808
+ console.log(
809
+ `[RegenerateDuplicatesBatch] Attempt ${attempts} to generate a new name for ${combination} (archetypeIndex: ${archetypeIndex})`
810
+ );
811
+
812
+ // Build the prompt
813
+ const prompt = duplicatedArchetypeNamePrompt({
814
+ combination,
815
+ essenceLine: essenceLine || 'A unique and meaningful archetype', // Fallback for null essenceLine
816
+ existingNames,
817
+ });
818
+
819
+ // Send the request to the AI
820
+ const messages: ChatMessages = [{ role: 'user', content: prompt }];
821
+ const response = await this.context
822
+ .api()
823
+ .callTogether.single(messages, {});
824
+
825
+ if (!response) {
826
+ console.error(
827
+ `[RegenerateDuplicatesBatch] No response from model for ${combination} (archetypeIndex: ${archetypeIndex})`
828
+ );
829
+ continue;
830
+ }
831
+
832
+ // Parse the response
833
+ try {
834
+ newName = JSON.parse(response);
835
+ console.log(
836
+ `[RegenerateDuplicatesBatch] Generated new name: ${JSON.stringify(
837
+ newName,
838
+ null,
839
+ 2
840
+ )}`
841
+ );
842
+
843
+ // Validate the response format
844
+ if (
845
+ !newName ||
846
+ !newName.name_en ||
847
+ !newName.name_pt_male ||
848
+ !newName.name_pt_female
849
+ ) {
850
+ console.error(
851
+ `[RegenerateDuplicatesBatch] Invalid response format for ${combination} (archetypeIndex: ${archetypeIndex}): ${response}`
852
+ );
853
+ newName = null;
854
+ continue;
855
+ }
856
+ } catch (error) {
857
+ console.error(
858
+ `[RegenerateDuplicatesBatch] Failed to parse AI response for ${combination} (archetypeIndex: ${archetypeIndex}): ${response}`,
859
+ error
860
+ );
861
+ continue;
862
+ }
863
+
864
+ // Check if the new name is unique (globally across all combinations)
865
+ const isDuplicate = await db
866
+ .select({ name: schema.archetypesData.name })
867
+ .from(schema.archetypesData)
868
+ .where(
869
+ and(
870
+ eq(schema.archetypesData.language, 'en-us'),
871
+ eq(schema.archetypesData.name, newName.name_en)
872
+ )
873
+ )
874
+ .limit(1)
875
+ .execute();
876
+
877
+ if (isDuplicate.length > 0) {
878
+ console.warn(
879
+ `[RegenerateDuplicatesBatch] Generated name "${newName.name_en}" is already used. Adding to existing names and retrying.`
880
+ );
881
+ existingNames.push(newName.name_en);
882
+ newName = null;
883
+ continue;
884
+ }
885
+
886
+ // If we reach here, the name is unique
887
+ break;
888
+ }
889
+
890
+ if (!newName) {
891
+ console.error(
892
+ `[RegenerateDuplicatesBatch] Failed to generate a unique name for ${combination} (archetypeIndex: ${archetypeIndex}) after ${maxAttempts} attempts`
893
+ );
894
+ continue;
895
+ }
896
+
897
+ // Update the database with the new names
898
+ for (const gender of ['male', 'female']) {
899
+ const enId = `${combination}:${gender}:${archetypeIndex}`;
900
+ const ptId = `${combination}:${gender}:${archetypeIndex}:pt`;
901
+
902
+ // Update English entry
903
+ await db
904
+ .update(schema.archetypesData)
905
+ .set({
906
+ name: newName.name_en,
907
+ updatedAt: new Date().getTime(),
908
+ })
909
+ .where(
910
+ and(
911
+ eq(schema.archetypesData.id, enId),
912
+ eq(schema.archetypesData.language, 'en-us')
913
+ )
914
+ )
915
+ .execute();
916
+
917
+ // Update Portuguese entry
918
+ const ptName =
919
+ gender === 'female' ? newName.name_pt_female : newName.name_pt_male;
920
+ await db
921
+ .update(schema.archetypesData)
922
+ .set({
923
+ name: ptName,
924
+ updatedAt: new Date().getTime(),
925
+ })
926
+ .where(
927
+ and(
928
+ eq(schema.archetypesData.id, ptId),
929
+ eq(schema.archetypesData.language, 'pt-br')
930
+ )
931
+ )
932
+ .execute();
933
+
934
+ console.log(
935
+ `[RegenerateDuplicatesBatch] Updated ${combination} (archetypeIndex: ${archetypeIndex}, gender: ${gender}) with new name - English: ${newName.name_en}, Portuguese: ${ptName}`
936
+ );
937
+ }
938
+ }
939
+ }
940
+
941
+ console.log(`✅ [RegenerateDuplicatesBatch] Finished processing batch`);
942
+ }
943
+
944
+ async recycleArchetypeNameDumpsBatch(
945
+ compositions: Composition[]
946
+ ): Promise<void> {
737
947
  console.log('🔁 [Recycle] Starting recycling of archetype name dumps');
738
-
948
+
739
949
  if (compositions.length === 0) {
740
950
  console.log('✅ [Recycle] No compositions provided for recycling');
741
951
  return;
742
952
  }
743
-
953
+
744
954
  console.log(
745
955
  `📦 [Recycle] Total compositions to recycle: ${compositions.length}`
746
956
  );
747
-
957
+
748
958
  // Step 1: Process each composition
749
959
  const db = this.context.drizzle();
750
960
  for (const comp of compositions) {
751
961
  const combination = [comp.sun, comp.ascendant, comp.moon].join('-');
752
962
  const indexes = comp.indexesToGenerate ?? [1, 2, 3];
753
-
754
- console.log(`🔄 [Recycle] Processing combination: ${combination} with indexes: [${indexes.join(', ')}]`);
755
-
963
+
964
+ console.log(
965
+ `🔄 [Recycle] Processing combination: ${combination} with indexes: [${indexes.join(
966
+ ', '
967
+ )}]`
968
+ );
969
+
756
970
  // Fetch all dump entries for this combination
757
971
  const dumpEntries = await db
758
972
  .select({
@@ -762,22 +976,28 @@ export class ArchetypeService {
762
976
  .from(schema.archetypeNameDumps)
763
977
  .where(eq(schema.archetypeNameDumps.combination, combination))
764
978
  .execute();
765
-
979
+
766
980
  console.log(
767
- `[Recycle] Retrieved ${dumpEntries.length} dump entries for ${combination}: ${JSON.stringify(dumpEntries, null, 2)}`
981
+ `[Recycle] Retrieved ${
982
+ dumpEntries.length
983
+ } dump entries for ${combination}: ${JSON.stringify(
984
+ dumpEntries,
985
+ null,
986
+ 2
987
+ )}`
768
988
  );
769
-
989
+
770
990
  if (dumpEntries.length === 0) {
771
991
  console.log(
772
992
  `⚠️ [Recycle] No dump entries found for combination: ${combination}`
773
993
  );
774
994
  continue;
775
995
  }
776
-
996
+
777
997
  // Step 2: Process each missing index
778
998
  for (const index of indexes) {
779
999
  console.log(`[Recycle] Processing index ${index} for ${combination}`);
780
-
1000
+
781
1001
  // Find a dump entry that contains the specific index
782
1002
  let rawText: string | null = null;
783
1003
  let selectedEntryId: string | null = null;
@@ -791,21 +1011,25 @@ export class ArchetypeService {
791
1011
  break;
792
1012
  }
793
1013
  }
794
-
1014
+
795
1015
  if (!rawText) {
796
1016
  console.log(
797
1017
  `⚠️ [Recycle] No dump entry contains index ${index} for combination: ${combination}`
798
1018
  );
799
1019
  continue;
800
1020
  }
801
-
1021
+
802
1022
  // Clean up the raw text
803
- console.log(`[Recycle] Cleaning rawText for index ${index}: ${rawText}`);
1023
+ console.log(
1024
+ `[Recycle] Cleaning rawText for index ${index}: ${rawText}`
1025
+ );
804
1026
  const cleanedText = rawText
805
1027
  .replace(/###|---\s*###|-\s*###/g, '')
806
1028
  .trim();
807
- console.log(`[Recycle] Cleaned text for index ${index}: ${cleanedText}`);
808
-
1029
+ console.log(
1030
+ `[Recycle] Cleaned text for index ${index}: ${cleanedText}`
1031
+ );
1032
+
809
1033
  // Extract the specific index sections
810
1034
  const enSectionMatch = cleanedText.match(
811
1035
  new RegExp(`-EN ${index}\\.\\s*[^-]*(?=-EN|-PT|$)`, 's')
@@ -813,28 +1037,43 @@ export class ArchetypeService {
813
1037
  const ptSectionMatch = cleanedText.match(
814
1038
  new RegExp(`-PT ${index}\\.\\s*[^-]*(?=-EN|-PT|$)`, 's')
815
1039
  );
816
-
1040
+
817
1041
  console.log(
818
- `[Recycle] Extracted sections for index ${index} - enSectionMatch: ${JSON.stringify(enSectionMatch)}, ptSectionMatch: ${JSON.stringify(ptSectionMatch)}`
1042
+ `[Recycle] Extracted sections for index ${index} - enSectionMatch: ${JSON.stringify(
1043
+ enSectionMatch
1044
+ )}, ptSectionMatch: ${JSON.stringify(ptSectionMatch)}`
819
1045
  );
820
-
821
- if (!enSectionMatch || !ptSectionMatch || !enSectionMatch[0] || !ptSectionMatch[0]) {
1046
+
1047
+ if (
1048
+ !enSectionMatch ||
1049
+ !ptSectionMatch ||
1050
+ !enSectionMatch[0] ||
1051
+ !ptSectionMatch[0]
1052
+ ) {
822
1053
  console.log(
823
- `⚠️ [Recycle] Could not extract index ${index} sections for combination: ${combination}. enSectionMatch: ${JSON.stringify(enSectionMatch)}, ptSectionMatch: ${JSON.stringify(ptSectionMatch)}`
1054
+ `⚠️ [Recycle] Could not extract index ${index} sections for combination: ${combination}. enSectionMatch: ${JSON.stringify(
1055
+ enSectionMatch
1056
+ )}, ptSectionMatch: ${JSON.stringify(ptSectionMatch)}`
824
1057
  );
825
1058
  continue;
826
1059
  }
827
-
1060
+
828
1061
  // Combine the extracted sections into a block for parsing
829
- const block = `-EN\n${enSectionMatch[0].replace(/-EN\s*/, '').trim()}\n\n-PT\n${ptSectionMatch[0].replace(/-PT\s*/, '').trim()}`;
1062
+ const block = `-EN\n${enSectionMatch[0]
1063
+ .replace(/-EN\s*/, '')
1064
+ .trim()}\n\n-PT\n${ptSectionMatch[0].replace(/-PT\s*/, '').trim()}`;
830
1065
  console.log(`[Recycle] Constructed block for index ${index}: ${block}`);
831
-
1066
+
832
1067
  // Step 3: Parse the block
833
1068
  const { english, portuguese } = this.parseArchetypeNameBlocks(block);
834
1069
  console.log(
835
- `[Recycle] Parsed results for index ${index} - English: ${JSON.stringify(english, null, 2)}, Portuguese: ${JSON.stringify(portuguese, null, 2)}`
1070
+ `[Recycle] Parsed results for index ${index} - English: ${JSON.stringify(
1071
+ english,
1072
+ null,
1073
+ 2
1074
+ )}, Portuguese: ${JSON.stringify(portuguese, null, 2)}`
836
1075
  );
837
-
1076
+
838
1077
  if (english.length === 0 || portuguese.length === 0) {
839
1078
  console.error(
840
1079
  `❌ [Recycle] Parsing failed for index ${index} of combination: ${combination}. Block: ${block}`
@@ -860,27 +1099,33 @@ export class ArchetypeService {
860
1099
  }
861
1100
  continue;
862
1101
  }
863
-
1102
+
864
1103
  const englishEntry = english[0];
865
1104
  const ptEntry = portuguese[0];
866
-
1105
+
867
1106
  console.log(
868
- `[Recycle] Extracted entries for index ${index} - englishEntry: ${JSON.stringify(englishEntry, null, 2)}, ptEntry: ${JSON.stringify(ptEntry, null, 2)}`
1107
+ `[Recycle] Extracted entries for index ${index} - englishEntry: ${JSON.stringify(
1108
+ englishEntry,
1109
+ null,
1110
+ 2
1111
+ )}, ptEntry: ${JSON.stringify(ptEntry, null, 2)}`
869
1112
  );
870
-
1113
+
871
1114
  if (!englishEntry || !ptEntry) {
872
1115
  console.warn(
873
- `⚠️ [Recycle] Skipping index ${index} for ${combination} due to missing parsed data. englishEntry: ${JSON.stringify(englishEntry)}, ptEntry: ${JSON.stringify(ptEntry)}`
1116
+ `⚠️ [Recycle] Skipping index ${index} for ${combination} due to missing parsed data. englishEntry: ${JSON.stringify(
1117
+ englishEntry
1118
+ )}, ptEntry: ${JSON.stringify(ptEntry)}`
874
1119
  );
875
1120
  continue;
876
1121
  }
877
-
1122
+
878
1123
  // Step 4: Insert the parsed data into archetypes_data
879
1124
  for (const gender of ['male', 'female']) {
880
1125
  const enId = `${combination}:${gender}:${index}`;
881
1126
  const ptId = `${combination}:${gender}:${index}:pt`;
882
1127
  const ptName = gender === 'female' ? ptEntry.fem : ptEntry.masc;
883
-
1128
+
884
1129
  console.log(
885
1130
  `[Recycle] Inserting English entry for ${combination}, index ${index}, gender ${gender}: id=${enId}, name=${englishEntry.name}, essenceLine=${englishEntry.essenceLine}`
886
1131
  );
@@ -905,7 +1150,7 @@ export class ArchetypeService {
905
1150
  updatedAt: new Date().getTime(),
906
1151
  },
907
1152
  });
908
-
1153
+
909
1154
  console.log(
910
1155
  `[Recycle] Inserting Portuguese entry for ${combination}, index ${index}, gender ${gender}: id=${ptId}, name=${ptName}, essenceLine=${ptEntry.essenceLine}`
911
1156
  );
@@ -930,7 +1175,7 @@ export class ArchetypeService {
930
1175
  updatedAt: new Date().getTime(),
931
1176
  },
932
1177
  });
933
-
1178
+
934
1179
  // Delete the processed dump entry
935
1180
  if (selectedEntryId) {
936
1181
  console.log(
@@ -947,16 +1192,16 @@ export class ArchetypeService {
947
1192
  `[Recycle] Could not delete dump entry for ${combination}, index ${index}: selectedEntryId is null`
948
1193
  );
949
1194
  }
950
-
1195
+
951
1196
  console.log(
952
1197
  `✅ [Recycle] Saved archetype ${index} (${gender}) for ${combination}`
953
1198
  );
954
1199
  }
955
1200
  }
956
-
1201
+
957
1202
  console.log(`🏁 [Recycle] Finished combination: ${combination}`);
958
1203
  }
959
-
1204
+
960
1205
  console.log(
961
1206
  `🎉 [Recycle] Completed recycling for ${compositions.length} combinations`
962
1207
  );
@@ -1022,95 +1267,139 @@ export class ArchetypeService {
1022
1267
  portuguese: any[];
1023
1268
  } {
1024
1269
  console.log(`[Parse] Starting parsing of block: ${block}`);
1025
-
1270
+
1271
+ // Split the block into sections based on -EN and -PT markers
1026
1272
  const sections = block.split(/^-EN|^-PT/m).filter((s) => s.trim());
1027
1273
  console.log(
1028
- `[Parse] Split block into ${sections.length} sections: ${JSON.stringify(sections, null, 2)}`
1274
+ `[Parse] Split block into ${sections.length} sections: ${JSON.stringify(
1275
+ sections,
1276
+ null,
1277
+ 2
1278
+ )}`
1029
1279
  );
1030
-
1280
+
1031
1281
  const english: any[] = [];
1032
1282
  const portuguese: any[] = [];
1033
-
1034
- for (const section of sections) {
1283
+
1284
+ // Track whether we're in an EN or PT section
1285
+ let currentLang: 'EN' | 'PT' | null = null;
1286
+
1287
+ for (let i = 0; i < block.length; i++) {
1288
+ if (block.startsWith('-EN', i)) {
1289
+ currentLang = 'EN';
1290
+ i += 3; // Skip past "-EN"
1291
+ } else if (block.startsWith('-PT', i)) {
1292
+ currentLang = 'PT';
1293
+ i += 3; // Skip past "-PT"
1294
+ }
1295
+ }
1296
+
1297
+ // Process each section
1298
+ for (let i = 0; i < sections.length; i++) {
1299
+ const section = sections[i].trim();
1035
1300
  console.log(`[Parse] Processing section: ${section}`);
1036
-
1037
- if (section.startsWith('EN')) {
1038
- const lines = section.split('\n').filter((l) => l.trim());
1039
- console.log(
1040
- `[Parse] Extracted ${lines.length} lines from English section: ${JSON.stringify(lines, null, 2)}`
1041
- );
1042
-
1043
- const nameMatch = lines
1044
- .find((l) => l.includes('• Name:'))
1045
- ?.split('• Name:')[1]
1046
- ?.trim();
1047
- console.log(`[Parse] English nameMatch: ${nameMatch}`);
1048
-
1049
- const essenceMatch = lines
1050
- .find((l) => l.includes('• Essence:'))
1051
- ?.split('• Essence:')[1]
1052
- ?.trim();
1053
- console.log(`[Parse] English essenceMatch: ${essenceMatch}`);
1054
-
1055
- if (nameMatch && essenceMatch) {
1056
- const entry = { name: nameMatch, essenceLine: essenceMatch };
1057
- english.push(entry);
1058
- console.log(
1059
- `[Parse] Added English entry: ${JSON.stringify(entry, null, 2)}`
1060
- );
1061
- } else {
1062
- console.warn(
1063
- `[Parse] Skipping English section due to missing fields. nameMatch: ${nameMatch}, essenceMatch: ${essenceMatch}`
1064
- );
1065
- }
1066
- } else if (section.startsWith('PT')) {
1067
- const lines = section.split('\n').filter((l) => l.trim());
1301
+
1302
+ // Determine the language based on the section's position relative to -EN and -PT markers
1303
+ const lang = i === 0 ? 'EN' : 'PT'; // First section after -EN, second after -PT
1304
+
1305
+ // Split the section into individual entries based on numbered markers (1., 2., 3.)
1306
+ const entries = section.split(/\n(?=\d+\.\s*)/).filter((e) => e.trim());
1307
+ console.log(
1308
+ `[Parse] Split section into ${entries.length} entries: ${JSON.stringify(
1309
+ entries,
1310
+ null,
1311
+ 2
1312
+ )}`
1313
+ );
1314
+
1315
+ for (const entry of entries) {
1316
+ const lines = entry.split('\n').filter((l) => l.trim());
1068
1317
  console.log(
1069
- `[Parse] Extracted ${lines.length} lines from Portuguese section: ${JSON.stringify(lines, null, 2)}`
1318
+ `[Parse] Extracted ${lines.length} lines from entry: ${JSON.stringify(
1319
+ lines,
1320
+ null,
1321
+ 2
1322
+ )}`
1070
1323
  );
1071
-
1072
- const mascMatch = lines
1073
- .find((l) => l.includes('• Masculino:'))
1074
- ?.split('• Masculino:')[1]
1075
- ?.trim();
1076
- console.log(`[Parse] Portuguese mascMatch: ${mascMatch}`);
1077
-
1078
- const femMatch = lines
1079
- .find((l) => l.includes('• Feminino:'))
1080
- ?.split('• Feminino:')[1]
1081
- ?.trim();
1082
- console.log(`[Parse] Portuguese femMatch: ${femMatch}`);
1083
-
1084
- const essenceMatch = lines
1085
- .find((l) => l.includes('• Essência:'))
1086
- ?.split('• Essência:')[1]
1087
- ?.trim();
1088
- console.log(`[Parse] Portuguese essenceMatch: ${essenceMatch}`);
1089
-
1090
- if (mascMatch && femMatch && essenceMatch) {
1091
- const entry = {
1092
- masc: mascMatch,
1093
- fem: femMatch,
1094
- essenceLine: essenceMatch,
1095
- };
1096
- portuguese.push(entry);
1097
- console.log(
1098
- `[Parse] Added Portuguese entry: ${JSON.stringify(entry, null, 2)}`
1099
- );
1100
- } else {
1101
- console.warn(
1102
- `[Parse] Skipping Portuguese section due to missing fields. mascMatch: ${mascMatch}, femMatch: ${femMatch}, essenceMatch: ${essenceMatch}`
1103
- );
1324
+
1325
+ if (lang === 'EN') {
1326
+ const nameMatch = lines
1327
+ .find((l) => l.includes('• Name:'))
1328
+ ?.split('• Name:')[1]
1329
+ ?.trim();
1330
+ console.log(`[Parse] English nameMatch: ${nameMatch}`);
1331
+
1332
+ const essenceMatch = lines
1333
+ .find((l) => l.includes('• Essence:'))
1334
+ ?.split('• Essence:')[1]
1335
+ ?.trim();
1336
+ console.log(`[Parse] English essenceMatch: ${essenceMatch}`);
1337
+
1338
+ if (nameMatch && essenceMatch) {
1339
+ const englishEntry = { name: nameMatch, essenceLine: essenceMatch };
1340
+ english.push(englishEntry);
1341
+ console.log(
1342
+ `[Parse] Added English entry: ${JSON.stringify(
1343
+ englishEntry,
1344
+ null,
1345
+ 2
1346
+ )}`
1347
+ );
1348
+ } else {
1349
+ console.warn(
1350
+ `[Parse] Skipping English entry due to missing fields. nameMatch: ${nameMatch}, essenceMatch: ${essenceMatch}`
1351
+ );
1352
+ }
1353
+ } else if (lang === 'PT') {
1354
+ const mascMatch = lines
1355
+ .find((l) => l.includes('• Masculino:'))
1356
+ ?.split('• Masculino:')[1]
1357
+ ?.trim();
1358
+ console.log(`[Parse] Portuguese mascMatch: ${mascMatch}`);
1359
+
1360
+ const femMatch = lines
1361
+ .find((l) => l.includes('• Feminino:'))
1362
+ ?.split('• Feminino:')[1]
1363
+ ?.trim();
1364
+ console.log(`[Parse] Portuguese femMatch: ${femMatch}`);
1365
+
1366
+ const essenceMatch = lines
1367
+ .find((l) => l.includes('• Essência:'))
1368
+ ?.split('• Essência:')[1]
1369
+ ?.trim();
1370
+ console.log(`[Parse] Portuguese essenceMatch: ${essenceMatch}`);
1371
+
1372
+ if (mascMatch && femMatch && essenceMatch) {
1373
+ const ptEntry = {
1374
+ masc: mascMatch,
1375
+ fem: femMatch,
1376
+ essenceLine: essenceMatch,
1377
+ };
1378
+ portuguese.push(ptEntry);
1379
+ console.log(
1380
+ `[Parse] Added Portuguese entry: ${JSON.stringify(
1381
+ ptEntry,
1382
+ null,
1383
+ 2
1384
+ )}`
1385
+ );
1386
+ } else {
1387
+ console.warn(
1388
+ `[Parse] Skipping Portuguese entry due to missing fields. mascMatch: ${mascMatch}, femMatch: ${femMatch}, essenceMatch: ${essenceMatch}`
1389
+ );
1390
+ }
1104
1391
  }
1105
- } else {
1106
- console.warn(`[Parse] Unrecognized section: ${section}`);
1107
1392
  }
1108
1393
  }
1109
-
1394
+
1110
1395
  console.log(
1111
- `[Parse] Final parsed results - English: ${JSON.stringify(english, null, 2)}, Portuguese: ${JSON.stringify(portuguese, null, 2)}`
1396
+ `[Parse] Final parsed results - English: ${JSON.stringify(
1397
+ english,
1398
+ null,
1399
+ 2
1400
+ )}, Portuguese: ${JSON.stringify(portuguese, null, 2)}`
1112
1401
  );
1113
-
1402
+
1114
1403
  return { english, portuguese };
1115
1404
  }
1116
1405
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zodic/shared",
3
- "version": "0.0.312",
3
+ "version": "0.0.314",
4
4
  "module": "index.ts",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -0,0 +1,47 @@
1
+ type ArchetypePromptInputs = {
2
+ combination: string;
3
+ essenceLine: string;
4
+ existingNames: string[];
5
+ };
6
+
7
+ export function duplicatedArchetypeNamePrompt({
8
+ combination,
9
+ essenceLine,
10
+ existingNames,
11
+ }: ArchetypePromptInputs): string {
12
+ return `
13
+ You are a creative naming assistant for a symbolic astrology project. Each archetype is defined by a unique combination of three zodiac signs (Sun, Moon, Ascendant), and has an associated *essence line* that captures its spiritual and psychological meaning. Your task is to generate a new, poetic and meaningful name for the archetype, ensuring it is unique among previously used names.
14
+
15
+ ---
16
+
17
+ Input:
18
+
19
+ - Combination: \`${combination}\`
20
+ - Essence Line: \`${essenceLine}\`
21
+ - Existing Names: \`${JSON.stringify(existingNames)}\`
22
+
23
+ ---
24
+
25
+ Important Instructions:
26
+
27
+ 1. Create a new archetype name that poetically reflects the given essence line.
28
+ 2. The name should follow the same style as existing archetypes (e.g., \`The Wandering Alchemist\`, \`The Radiant Mask\`, \`The Harmonious Builder\`).
29
+ 3. The name must not appear in the list of existing names.
30
+ 4. Also generate Portuguese translations of the name:
31
+ - One in masculine form.
32
+ - One in feminine form.
33
+ 5. Ensure all outputs are semantically coherent and well-written.
34
+ 6. Use the following output format precisely.
35
+
36
+ ---
37
+
38
+ Output Format (exactly like this, do not change it):
39
+
40
+ {
41
+ "name_en": <Name in English>,
42
+ "name_pt_male": <Name in Portuguese Male>,
43
+ "name_pt_female": <Name in Portuguese Female>,
44
+ }
45
+
46
+ `;
47
+ }