@zodic/shared 0.0.313 → 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
|
|
|
@@ -751,6 +752,195 @@ export class ArchetypeService {
|
|
|
751
752
|
);
|
|
752
753
|
}
|
|
753
754
|
|
|
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
|
+
|
|
754
944
|
async recycleArchetypeNameDumpsBatch(
|
|
755
945
|
compositions: Composition[]
|
|
756
946
|
): Promise<void> {
|
package/package.json
CHANGED
|
@@ -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
|
+
}
|