@zodic/shared 0.0.383 → 0.0.385
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/services/ArchetypeService.ts +431 -124
- package/package.json +1 -1
- package/utils/buildMessages.ts +2 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { and, eq } from 'drizzle-orm';
|
|
1
|
+
import { and, eq, inArray } from 'drizzle-orm';
|
|
2
2
|
import { inject, injectable } from 'inversify';
|
|
3
3
|
import { ChatMessages, schema } from '../..';
|
|
4
|
-
import {
|
|
4
|
+
import { astroPlanets } from '../../db/schema';
|
|
5
|
+
import { Gender, Languages, VALID_GENDERS } from '../../types';
|
|
5
6
|
import { ZodiacSignSlug } from '../../types/scopes/legacy';
|
|
6
7
|
import { generateArchetypePrompt } from '../../utils/archetypeNamesMessages';
|
|
7
8
|
import { AppContext } from '../base';
|
|
@@ -690,11 +691,11 @@ export class ArchetypeService {
|
|
|
690
691
|
language,
|
|
691
692
|
override,
|
|
692
693
|
});
|
|
693
|
-
|
|
694
|
+
|
|
694
695
|
const db = this.context.drizzle();
|
|
695
696
|
const allGenders: Gender[] = ['male', 'female'];
|
|
696
697
|
const archetypesByGender: Record<Gender, any[]> = { male: [], female: [] };
|
|
697
|
-
|
|
698
|
+
|
|
698
699
|
for (const g of allGenders) {
|
|
699
700
|
const archetypes = await db
|
|
700
701
|
.select()
|
|
@@ -710,20 +711,20 @@ export class ArchetypeService {
|
|
|
710
711
|
.execute();
|
|
711
712
|
archetypesByGender[g] = archetypes;
|
|
712
713
|
}
|
|
713
|
-
|
|
714
|
+
|
|
714
715
|
const needsGeneration = allGenders.some(
|
|
715
716
|
(g) =>
|
|
716
717
|
archetypesByGender[g].length !== 3 ||
|
|
717
718
|
archetypesByGender[g].some((a) => a.content === '[]')
|
|
718
719
|
);
|
|
719
|
-
|
|
720
|
+
|
|
720
721
|
if (!override && !needsGeneration) {
|
|
721
722
|
await this.log('info', 'Skipping content generation', {
|
|
722
723
|
reason: 'Content already exists for all archetypes',
|
|
723
724
|
});
|
|
724
725
|
return;
|
|
725
726
|
}
|
|
726
|
-
|
|
727
|
+
|
|
727
728
|
await this.log('info', 'Fetched archetypes for content generation', {
|
|
728
729
|
maleArchetypes: archetypesByGender['male'].map((a) => ({
|
|
729
730
|
id: a.id,
|
|
@@ -736,29 +737,41 @@ export class ArchetypeService {
|
|
|
736
737
|
index: a.archetypeIndex,
|
|
737
738
|
})),
|
|
738
739
|
});
|
|
739
|
-
|
|
740
|
+
|
|
740
741
|
const contentResults = [];
|
|
741
742
|
for (let i = 0; i < 3; i++) {
|
|
742
743
|
const index = (i + 1).toString();
|
|
743
744
|
const archetype = archetypesByGender['male'][i];
|
|
744
745
|
if (!archetype || archetype.archetypeIndex !== index) {
|
|
745
|
-
await this.log(
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
746
|
+
await this.log(
|
|
747
|
+
'error',
|
|
748
|
+
`Archetype index mismatch at position ${i + 1}`,
|
|
749
|
+
{
|
|
750
|
+
expectedIndex: index,
|
|
751
|
+
actualIndex: archetype?.archetypeIndex,
|
|
752
|
+
archetypeId: archetype?.id,
|
|
753
|
+
}
|
|
754
|
+
);
|
|
755
|
+
throw new Error(
|
|
756
|
+
`Archetype index mismatch: expected ${index}, got ${archetype?.archetypeIndex}`
|
|
757
|
+
);
|
|
751
758
|
}
|
|
752
|
-
|
|
759
|
+
|
|
753
760
|
// Generate EN content
|
|
754
|
-
const enId = `${combinationString}:male:${index}${
|
|
761
|
+
const enId = `${combinationString}:male:${index}${
|
|
762
|
+
language === 'en-us' ? '' : ':pt'
|
|
763
|
+
}`;
|
|
755
764
|
if (!override && archetypesByGender['male'][i].content !== '[]') {
|
|
756
765
|
await this.log('debug', `Skipping existing EN content for ${enId}`, {
|
|
757
766
|
content: archetypesByGender['male'][i].content,
|
|
758
767
|
archetypeIndex: index,
|
|
759
768
|
});
|
|
760
769
|
} else {
|
|
761
|
-
await this.log(
|
|
770
|
+
await this.log(
|
|
771
|
+
'debug',
|
|
772
|
+
`Generating EN content for archetype ${index}`,
|
|
773
|
+
{ name: archetype.name }
|
|
774
|
+
);
|
|
762
775
|
const enMessages = this.context
|
|
763
776
|
.buildLLMMessages()
|
|
764
777
|
.generateCosmicMirrorArchetypeContentEN({
|
|
@@ -766,27 +779,48 @@ export class ArchetypeService {
|
|
|
766
779
|
description: descriptions[i].descriptionEN,
|
|
767
780
|
combination: combinationString,
|
|
768
781
|
});
|
|
769
|
-
|
|
770
|
-
await this.log(
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
782
|
+
|
|
783
|
+
await this.log(
|
|
784
|
+
'debug',
|
|
785
|
+
`Calling API for EN content of archetype ${index}`,
|
|
786
|
+
{ messages: enMessages }
|
|
787
|
+
);
|
|
788
|
+
const enResponse = await this.context
|
|
789
|
+
.api()
|
|
790
|
+
.callTogether.single(enMessages, {
|
|
791
|
+
options: { max_tokens: 4096 },
|
|
778
792
|
});
|
|
779
|
-
|
|
793
|
+
if (!enResponse) {
|
|
794
|
+
await this.log(
|
|
795
|
+
'error',
|
|
796
|
+
`No response for EN content of archetype ${index}`,
|
|
797
|
+
{
|
|
798
|
+
combinationString,
|
|
799
|
+
archetype: archetype.name,
|
|
800
|
+
}
|
|
801
|
+
);
|
|
802
|
+
throw new Error(
|
|
803
|
+
`Failed to generate EN content for archetype ${index} of: ${combinationString}`
|
|
804
|
+
);
|
|
780
805
|
}
|
|
781
|
-
await this.log(
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
806
|
+
await this.log(
|
|
807
|
+
'info',
|
|
808
|
+
`Received EN content response for archetype ${index}`,
|
|
809
|
+
{
|
|
810
|
+
responseLength: enResponse.length,
|
|
811
|
+
rawResponse: enResponse,
|
|
812
|
+
}
|
|
813
|
+
);
|
|
814
|
+
|
|
815
|
+
await this.log(
|
|
816
|
+
'debug',
|
|
817
|
+
`Parsing EN content response for archetype ${index}`
|
|
818
|
+
);
|
|
787
819
|
const enContent = this.parseContentResponse(enResponse, 'EN');
|
|
788
|
-
await this.log('info', `Parsed EN content for archetype ${index}`, {
|
|
789
|
-
|
|
820
|
+
await this.log('info', `Parsed EN content for archetype ${index}`, {
|
|
821
|
+
enContent,
|
|
822
|
+
});
|
|
823
|
+
|
|
790
824
|
const content = [
|
|
791
825
|
{ section: 'voiceOfTheSoul', text: enContent.voiceOfTheSoul },
|
|
792
826
|
{ section: 'giftsYouBear', text: enContent.giftsYouBear },
|
|
@@ -795,12 +829,12 @@ export class ArchetypeService {
|
|
|
795
829
|
{ section: 'tiesThatBind', text: enContent.tiesThatBind },
|
|
796
830
|
{ section: 'lightWithin', text: enContent.lightWithin },
|
|
797
831
|
];
|
|
798
|
-
|
|
832
|
+
|
|
799
833
|
await this.log('debug', `Updating EN content for ${enId}`, {
|
|
800
834
|
content,
|
|
801
835
|
archetypeIndex: index,
|
|
802
836
|
});
|
|
803
|
-
|
|
837
|
+
|
|
804
838
|
await db
|
|
805
839
|
.update(schema.archetypesData)
|
|
806
840
|
.set({
|
|
@@ -816,24 +850,36 @@ export class ArchetypeService {
|
|
|
816
850
|
)
|
|
817
851
|
)
|
|
818
852
|
.execute();
|
|
819
|
-
|
|
853
|
+
|
|
820
854
|
await this.log('info', `Updated EN content for ${enId}`);
|
|
821
855
|
contentResults.push(enContent);
|
|
822
856
|
}
|
|
823
|
-
|
|
857
|
+
|
|
824
858
|
// Generate PT content (both male and female)
|
|
825
859
|
const ptIds = {
|
|
826
860
|
male: `${combinationString}:male:${index}:pt`,
|
|
827
861
|
female: `${combinationString}:female:${index}:pt`,
|
|
828
862
|
};
|
|
829
|
-
if (
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
863
|
+
if (
|
|
864
|
+
!override &&
|
|
865
|
+
archetypesByGender['male'][i].content !== '[]' &&
|
|
866
|
+
archetypesByGender['female'][i].content !== '[]'
|
|
867
|
+
) {
|
|
868
|
+
await this.log(
|
|
869
|
+
'debug',
|
|
870
|
+
`Skipping existing PT content for ${ptIds.male} and ${ptIds.female}`,
|
|
871
|
+
{
|
|
872
|
+
maleContent: archetypesByGender['male'][i].content,
|
|
873
|
+
femaleContent: archetypesByGender['female'][i].content,
|
|
874
|
+
archetypeIndex: index,
|
|
875
|
+
}
|
|
876
|
+
);
|
|
835
877
|
} else {
|
|
836
|
-
await this.log(
|
|
878
|
+
await this.log(
|
|
879
|
+
'debug',
|
|
880
|
+
`Generating PT content for archetype ${index}`,
|
|
881
|
+
{ name: archetype.name }
|
|
882
|
+
);
|
|
837
883
|
const ptMessages = this.context
|
|
838
884
|
.buildLLMMessages()
|
|
839
885
|
.generateCosmicMirrorArchetypeContentPT({
|
|
@@ -841,49 +887,103 @@ export class ArchetypeService {
|
|
|
841
887
|
description: descriptions[i].descriptionEN,
|
|
842
888
|
combination: combinationString,
|
|
843
889
|
});
|
|
844
|
-
|
|
845
|
-
await this.log(
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
890
|
+
|
|
891
|
+
await this.log(
|
|
892
|
+
'debug',
|
|
893
|
+
`Calling API for PT content of archetype ${index}`,
|
|
894
|
+
{ messages: ptMessages }
|
|
895
|
+
);
|
|
896
|
+
const ptResponse = await this.context
|
|
897
|
+
.api()
|
|
898
|
+
.callTogether.single(ptMessages, {
|
|
899
|
+
options: { max_tokens: 8192 },
|
|
853
900
|
});
|
|
854
|
-
|
|
901
|
+
if (!ptResponse) {
|
|
902
|
+
await this.log(
|
|
903
|
+
'error',
|
|
904
|
+
`No response for PT content of archetype ${index}`,
|
|
905
|
+
{
|
|
906
|
+
combinationString,
|
|
907
|
+
archetype: archetype.name,
|
|
908
|
+
}
|
|
909
|
+
);
|
|
910
|
+
throw new Error(
|
|
911
|
+
`Failed to generate PT content for archetype ${index} of: ${combinationString}`
|
|
912
|
+
);
|
|
855
913
|
}
|
|
856
|
-
await this.log(
|
|
857
|
-
|
|
858
|
-
|
|
914
|
+
await this.log(
|
|
915
|
+
'info',
|
|
916
|
+
`Received PT content response for archetype ${index}`,
|
|
917
|
+
{
|
|
918
|
+
responseLength: ptResponse.length,
|
|
919
|
+
rawResponse: ptResponse,
|
|
920
|
+
}
|
|
921
|
+
);
|
|
922
|
+
|
|
923
|
+
await this.log(
|
|
924
|
+
'debug',
|
|
925
|
+
`Parsing PT-M content response for archetype ${index}`
|
|
926
|
+
);
|
|
927
|
+
const ptMaleContentParsed = this.parseContentResponse(
|
|
928
|
+
ptResponse,
|
|
929
|
+
'PT',
|
|
930
|
+
'male'
|
|
931
|
+
);
|
|
932
|
+
await this.log('info', `Parsed PT-M content for archetype ${index}`, {
|
|
933
|
+
ptMaleContentParsed,
|
|
859
934
|
});
|
|
860
|
-
|
|
861
|
-
await this.log(
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
935
|
+
|
|
936
|
+
await this.log(
|
|
937
|
+
'debug',
|
|
938
|
+
`Parsing PT-F content response for archetype ${index}`
|
|
939
|
+
);
|
|
940
|
+
const ptFemaleContentParsed = this.parseContentResponse(
|
|
941
|
+
ptResponse,
|
|
942
|
+
'PT',
|
|
943
|
+
'female'
|
|
944
|
+
);
|
|
945
|
+
await this.log('info', `Parsed PT-F content for archetype ${index}`, {
|
|
946
|
+
ptFemaleContentParsed,
|
|
947
|
+
});
|
|
948
|
+
|
|
869
949
|
const ptMaleContent = [
|
|
870
|
-
{
|
|
950
|
+
{
|
|
951
|
+
section: 'voiceOfTheSoul',
|
|
952
|
+
text: ptMaleContentParsed.voiceOfTheSoul,
|
|
953
|
+
},
|
|
871
954
|
{ section: 'giftsYouBear', text: ptMaleContentParsed.giftsYouBear },
|
|
872
|
-
{
|
|
873
|
-
|
|
955
|
+
{
|
|
956
|
+
section: 'shadowsYouFace',
|
|
957
|
+
text: ptMaleContentParsed.shadowsYouFace,
|
|
958
|
+
},
|
|
959
|
+
{
|
|
960
|
+
section: 'rhythmOfYourDays',
|
|
961
|
+
text: ptMaleContentParsed.rhythmOfYourDays,
|
|
962
|
+
},
|
|
874
963
|
{ section: 'tiesThatBind', text: ptMaleContentParsed.tiesThatBind },
|
|
875
964
|
{ section: 'lightWithin', text: ptMaleContentParsed.lightWithin },
|
|
876
965
|
];
|
|
877
966
|
const ptFemaleContent = [
|
|
878
|
-
{
|
|
967
|
+
{
|
|
968
|
+
section: 'voiceOfTheSoul',
|
|
969
|
+
text: ptFemaleContentParsed.voiceOfTheSoul,
|
|
970
|
+
},
|
|
879
971
|
{ section: 'giftsYouBear', text: ptFemaleContentParsed.giftsYouBear },
|
|
880
|
-
{
|
|
881
|
-
|
|
972
|
+
{
|
|
973
|
+
section: 'shadowsYouFace',
|
|
974
|
+
text: ptFemaleContentParsed.shadowsYouFace,
|
|
975
|
+
},
|
|
976
|
+
{
|
|
977
|
+
section: 'rhythmOfYourDays',
|
|
978
|
+
text: ptFemaleContentParsed.rhythmOfYourDays,
|
|
979
|
+
},
|
|
882
980
|
{ section: 'tiesThatBind', text: ptFemaleContentParsed.tiesThatBind },
|
|
883
981
|
{ section: 'lightWithin', text: ptFemaleContentParsed.lightWithin },
|
|
884
982
|
];
|
|
885
|
-
|
|
886
|
-
await this.log('debug', `Updating PT-M content for ${ptIds.male}`, {
|
|
983
|
+
|
|
984
|
+
await this.log('debug', `Updating PT-M content for ${ptIds.male}`, {
|
|
985
|
+
content: ptMaleContent,
|
|
986
|
+
});
|
|
887
987
|
await db
|
|
888
988
|
.update(schema.archetypesData)
|
|
889
989
|
.set({
|
|
@@ -900,8 +1000,10 @@ export class ArchetypeService {
|
|
|
900
1000
|
)
|
|
901
1001
|
.execute();
|
|
902
1002
|
await this.log('info', `Updated PT-M content for ${ptIds.male}`);
|
|
903
|
-
|
|
904
|
-
await this.log('debug', `Updating PT-F content for ${ptIds.female}`, {
|
|
1003
|
+
|
|
1004
|
+
await this.log('debug', `Updating PT-F content for ${ptIds.female}`, {
|
|
1005
|
+
content: ptFemaleContent,
|
|
1006
|
+
});
|
|
905
1007
|
await db
|
|
906
1008
|
.update(schema.archetypesData)
|
|
907
1009
|
.set({
|
|
@@ -920,89 +1022,153 @@ export class ArchetypeService {
|
|
|
920
1022
|
await this.log('info', `Updated PT-F content for ${ptIds.female}`);
|
|
921
1023
|
}
|
|
922
1024
|
}
|
|
923
|
-
|
|
924
|
-
await this.log('info', 'Completed generateContent', {
|
|
1025
|
+
|
|
1026
|
+
await this.log('info', 'Completed generateContent', {
|
|
1027
|
+
combinationString,
|
|
1028
|
+
gender,
|
|
1029
|
+
language,
|
|
1030
|
+
});
|
|
925
1031
|
return contentResults;
|
|
926
1032
|
}
|
|
927
1033
|
|
|
928
|
-
private parseContentResponse(
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
1034
|
+
private parseContentResponse(
|
|
1035
|
+
response: string,
|
|
1036
|
+
section: string,
|
|
1037
|
+
gender: Gender | null = null
|
|
1038
|
+
) {
|
|
1039
|
+
this.log('debug', 'Starting parseContentResponse', {
|
|
1040
|
+
responseLength: response.length,
|
|
1041
|
+
section,
|
|
1042
|
+
gender,
|
|
1043
|
+
});
|
|
1044
|
+
|
|
1045
|
+
const lines = response.split('\n').map((line) => line.trim());
|
|
1046
|
+
this.log('debug', 'Split response into lines', {
|
|
1047
|
+
linesCount: lines.length,
|
|
1048
|
+
lines,
|
|
1049
|
+
});
|
|
1050
|
+
|
|
934
1051
|
// Skip initial --- and empty lines
|
|
935
1052
|
let startIndex = 0;
|
|
936
|
-
while (
|
|
1053
|
+
while (
|
|
1054
|
+
startIndex < lines.length &&
|
|
1055
|
+
(lines[startIndex] === '---' || lines[startIndex] === '')
|
|
1056
|
+
) {
|
|
937
1057
|
startIndex++;
|
|
938
1058
|
}
|
|
939
|
-
|
|
1059
|
+
|
|
940
1060
|
if (startIndex >= lines.length) {
|
|
941
|
-
this.log(
|
|
942
|
-
|
|
1061
|
+
this.log(
|
|
1062
|
+
'error',
|
|
1063
|
+
`No content found after skipping delimiters for ${section}`,
|
|
1064
|
+
{ response }
|
|
1065
|
+
);
|
|
1066
|
+
throw new Error(
|
|
1067
|
+
`No content found after skipping delimiters for ${section}`
|
|
1068
|
+
);
|
|
943
1069
|
}
|
|
944
|
-
|
|
945
|
-
const content: Record<string, Record<string, string>> = {
|
|
1070
|
+
|
|
1071
|
+
const content: Record<string, Record<string, string>> = {
|
|
1072
|
+
'PT-M:': {},
|
|
1073
|
+
'PT-F:': {},
|
|
1074
|
+
'EN:': {},
|
|
1075
|
+
};
|
|
946
1076
|
let currentSectionHeader = '';
|
|
947
1077
|
let currentSection = '';
|
|
948
1078
|
let currentText: string[] = [];
|
|
949
1079
|
let currentLang = '';
|
|
950
|
-
|
|
1080
|
+
|
|
951
1081
|
for (let i = startIndex; i < lines.length; i++) {
|
|
952
1082
|
const line = lines[i];
|
|
953
|
-
|
|
1083
|
+
|
|
954
1084
|
if (line === '---') {
|
|
955
1085
|
if (currentSection && currentText.length > 0) {
|
|
956
|
-
const key = currentSection
|
|
1086
|
+
const key = currentSection
|
|
1087
|
+
.toLowerCase()
|
|
1088
|
+
.replace(/\s+/g, '')
|
|
1089
|
+
.replace(/([A-Z])/g, (match) => match.toLowerCase());
|
|
957
1090
|
content[currentLang][key] = currentText.join(' ').trim();
|
|
958
|
-
this.log(
|
|
1091
|
+
this.log(
|
|
1092
|
+
'debug',
|
|
1093
|
+
`Extracted section ${currentSection} for ${currentLang}`,
|
|
1094
|
+
{ key, text: content[currentLang][key] }
|
|
1095
|
+
);
|
|
959
1096
|
}
|
|
960
1097
|
currentSection = '';
|
|
961
1098
|
currentText = [];
|
|
962
1099
|
// Look for the next header
|
|
963
|
-
while (
|
|
1100
|
+
while (
|
|
1101
|
+
i + 1 < lines.length &&
|
|
1102
|
+
(lines[i + 1] === '' || lines[i + 1] === '---')
|
|
1103
|
+
) {
|
|
964
1104
|
i++;
|
|
965
1105
|
}
|
|
966
|
-
if (
|
|
1106
|
+
if (
|
|
1107
|
+
i + 1 < lines.length &&
|
|
1108
|
+
(lines[i + 1] === 'PT-M:' ||
|
|
1109
|
+
lines[i + 1] === 'PT-F:' ||
|
|
1110
|
+
lines[i + 1] === 'EN:')
|
|
1111
|
+
) {
|
|
967
1112
|
i++;
|
|
968
1113
|
currentLang = lines[i];
|
|
969
1114
|
this.log('debug', `Found new language section: ${currentLang}`);
|
|
970
1115
|
}
|
|
971
1116
|
continue;
|
|
972
1117
|
}
|
|
973
|
-
|
|
1118
|
+
|
|
974
1119
|
if (line === 'PT-M:' || line === 'PT-F:' || line === 'EN:') {
|
|
975
1120
|
currentLang = line;
|
|
976
1121
|
this.log('debug', `Starting language section: ${currentLang}`);
|
|
977
1122
|
continue;
|
|
978
1123
|
}
|
|
979
|
-
|
|
1124
|
+
|
|
980
1125
|
if (line.startsWith('#')) {
|
|
981
1126
|
if (currentSection && currentText.length > 0) {
|
|
982
|
-
const key = currentSection
|
|
1127
|
+
const key = currentSection
|
|
1128
|
+
.toLowerCase()
|
|
1129
|
+
.replace(/\s+/g, '')
|
|
1130
|
+
.replace(/([A-Z])/g, (match) => match.toLowerCase());
|
|
983
1131
|
content[currentLang][key] = currentText.join(' ').trim();
|
|
984
|
-
this.log(
|
|
1132
|
+
this.log(
|
|
1133
|
+
'debug',
|
|
1134
|
+
`Extracted section ${currentSection} for ${currentLang}`,
|
|
1135
|
+
{ key, text: content[currentLang][key] }
|
|
1136
|
+
);
|
|
985
1137
|
}
|
|
986
1138
|
currentSection = line.replace('# ', '');
|
|
987
1139
|
currentSectionHeader = currentSection.toLowerCase();
|
|
988
1140
|
currentText = [];
|
|
989
|
-
this.log(
|
|
1141
|
+
this.log(
|
|
1142
|
+
'debug',
|
|
1143
|
+
`Starting new section ${currentSection} for ${currentLang}`
|
|
1144
|
+
);
|
|
990
1145
|
} else if (line) {
|
|
991
1146
|
currentText.push(line);
|
|
992
|
-
this.log(
|
|
1147
|
+
this.log(
|
|
1148
|
+
'debug',
|
|
1149
|
+
`Adding line to ${currentSection} for ${currentLang}`,
|
|
1150
|
+
{ line }
|
|
1151
|
+
);
|
|
993
1152
|
}
|
|
994
1153
|
}
|
|
995
|
-
|
|
1154
|
+
|
|
996
1155
|
// Handle the last section
|
|
997
1156
|
if (currentSection && currentText.length > 0) {
|
|
998
|
-
const key = currentSection
|
|
1157
|
+
const key = currentSection
|
|
1158
|
+
.toLowerCase()
|
|
1159
|
+
.replace(/\s+/g, '')
|
|
1160
|
+
.replace(/([A-Z])/g, (match) => match.toLowerCase());
|
|
999
1161
|
content[currentLang][key] = currentText.join(' ').trim();
|
|
1000
|
-
this.log(
|
|
1162
|
+
this.log(
|
|
1163
|
+
'debug',
|
|
1164
|
+
`Extracted final section ${currentSection} for ${currentLang}`,
|
|
1165
|
+
{ key, text: content[currentLang][key] }
|
|
1166
|
+
);
|
|
1001
1167
|
}
|
|
1002
|
-
|
|
1168
|
+
|
|
1003
1169
|
// Log the full content object for debugging
|
|
1004
1170
|
this.log('debug', `Full parsed content before selection`, { content });
|
|
1005
|
-
|
|
1171
|
+
|
|
1006
1172
|
// Determine which content to return based on section and gender
|
|
1007
1173
|
let targetLang = section;
|
|
1008
1174
|
if (section === 'PT') {
|
|
@@ -1010,31 +1176,58 @@ export class ArchetypeService {
|
|
|
1010
1176
|
} else {
|
|
1011
1177
|
targetLang = `${section}:`;
|
|
1012
1178
|
}
|
|
1013
|
-
|
|
1179
|
+
|
|
1014
1180
|
const targetContent = content[targetLang];
|
|
1015
1181
|
if (!targetContent) {
|
|
1016
|
-
this.log('error', `No content found for target ${targetLang}`, {
|
|
1182
|
+
this.log('error', `No content found for target ${targetLang}`, {
|
|
1183
|
+
response,
|
|
1184
|
+
section,
|
|
1185
|
+
gender,
|
|
1186
|
+
});
|
|
1017
1187
|
throw new Error(`No content found for target ${targetLang}`);
|
|
1018
1188
|
}
|
|
1019
|
-
|
|
1189
|
+
|
|
1020
1190
|
const parsedContent = {
|
|
1021
|
-
voiceOfTheSoul:
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1191
|
+
voiceOfTheSoul:
|
|
1192
|
+
targetContent['thevoiceofthesoul'] || targetContent['avozdaalma'] || '',
|
|
1193
|
+
giftsYouBear:
|
|
1194
|
+
targetContent['thegiftsyoubear'] ||
|
|
1195
|
+
targetContent['osdonsquevocêcarrega'] ||
|
|
1196
|
+
'',
|
|
1197
|
+
shadowsYouFace:
|
|
1198
|
+
targetContent['theshadowsyouface'] ||
|
|
1199
|
+
targetContent['assombrasqueenfrenta'] ||
|
|
1200
|
+
'',
|
|
1201
|
+
rhythmOfYourDays:
|
|
1202
|
+
targetContent['therhythmofyourdays'] ||
|
|
1203
|
+
targetContent['oritmodosseusdias'] ||
|
|
1204
|
+
'',
|
|
1205
|
+
tiesThatBind:
|
|
1206
|
+
targetContent['thetiesthatbind'] ||
|
|
1207
|
+
targetContent['oslaçosqueteconectam'] ||
|
|
1208
|
+
'',
|
|
1209
|
+
lightWithin:
|
|
1210
|
+
targetContent['thelightwithin'] || targetContent['aluzinterior'] || '',
|
|
1027
1211
|
};
|
|
1028
|
-
|
|
1212
|
+
|
|
1029
1213
|
// Log the parsed content before validation
|
|
1030
|
-
this.log('debug', `Parsed content before validation for ${targetLang}`, {
|
|
1031
|
-
|
|
1214
|
+
this.log('debug', `Parsed content before validation for ${targetLang}`, {
|
|
1215
|
+
parsedContent,
|
|
1216
|
+
});
|
|
1217
|
+
|
|
1032
1218
|
if (Object.values(parsedContent).some((value) => !value)) {
|
|
1033
|
-
this.log('error', `Malformed content response for ${targetLang}`, {
|
|
1219
|
+
this.log('error', `Malformed content response for ${targetLang}`, {
|
|
1220
|
+
parsedContent,
|
|
1221
|
+
response,
|
|
1222
|
+
});
|
|
1034
1223
|
throw new Error(`Malformed content response for ${targetLang}`);
|
|
1035
1224
|
}
|
|
1036
|
-
|
|
1037
|
-
this.log('info', 'Completed parseContentResponse', {
|
|
1225
|
+
|
|
1226
|
+
this.log('info', 'Completed parseContentResponse', {
|
|
1227
|
+
parsedContent,
|
|
1228
|
+
section,
|
|
1229
|
+
gender,
|
|
1230
|
+
});
|
|
1038
1231
|
return parsedContent;
|
|
1039
1232
|
}
|
|
1040
1233
|
|
|
@@ -1316,4 +1509,118 @@ export class ArchetypeService {
|
|
|
1316
1509
|
});
|
|
1317
1510
|
return result;
|
|
1318
1511
|
}
|
|
1512
|
+
|
|
1513
|
+
async queueArchetypeGeneration(userId: string) {
|
|
1514
|
+
const drizzle = this.context.drizzle();
|
|
1515
|
+
try {
|
|
1516
|
+
await this.log('info', 'Starting archetype generation queuing for user', {
|
|
1517
|
+
userId,
|
|
1518
|
+
});
|
|
1519
|
+
|
|
1520
|
+
// Query astro_planets for Sun, Ascendant, and Moon signs
|
|
1521
|
+
const planets = await drizzle
|
|
1522
|
+
.select()
|
|
1523
|
+
.from(astroPlanets)
|
|
1524
|
+
.where(
|
|
1525
|
+
and(
|
|
1526
|
+
eq(astroPlanets.userId, userId),
|
|
1527
|
+
inArray(
|
|
1528
|
+
astroPlanets.name,
|
|
1529
|
+
['sun', 'ascendant', 'moon'] // Assuming these are the exact names
|
|
1530
|
+
)
|
|
1531
|
+
)
|
|
1532
|
+
);
|
|
1533
|
+
|
|
1534
|
+
if (planets.length !== 3) {
|
|
1535
|
+
this.log('warn', 'Incomplete planetary data for archetype generation', {
|
|
1536
|
+
userId,
|
|
1537
|
+
found: planets.map((p) => p.name),
|
|
1538
|
+
});
|
|
1539
|
+
return;
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
const sun = planets.find((p) => p.name === 'sun')?.sign;
|
|
1543
|
+
const ascendant = planets.find((p) => p.name === 'ascendant')?.sign;
|
|
1544
|
+
const moon = planets.find((p) => p.name === 'moon')?.sign;
|
|
1545
|
+
|
|
1546
|
+
if (!sun || !ascendant || !moon) {
|
|
1547
|
+
await this.log('warn', 'Missing Sun, Ascendant, or Moon data', {
|
|
1548
|
+
sun,
|
|
1549
|
+
ascendant,
|
|
1550
|
+
moon,
|
|
1551
|
+
});
|
|
1552
|
+
return;
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
const combinationString = [sun, ascendant, moon].join('-');
|
|
1556
|
+
await this.log(
|
|
1557
|
+
'info',
|
|
1558
|
+
'Generated combination string from astro_planets',
|
|
1559
|
+
{ combinationString }
|
|
1560
|
+
);
|
|
1561
|
+
|
|
1562
|
+
// Fetch user details for gender and language
|
|
1563
|
+
const [user] = await drizzle
|
|
1564
|
+
.select({
|
|
1565
|
+
gender: schema.users.gender,
|
|
1566
|
+
lang: schema.users.language,
|
|
1567
|
+
})
|
|
1568
|
+
.from(schema.users)
|
|
1569
|
+
.where(eq(schema.users.id, userId))
|
|
1570
|
+
.limit(1);
|
|
1571
|
+
|
|
1572
|
+
if (!user || !VALID_GENDERS.has(user.gender as Gender)) {
|
|
1573
|
+
await this.log('error', 'Invalid or missing gender', {
|
|
1574
|
+
userId,
|
|
1575
|
+
gender: user?.gender || 'null',
|
|
1576
|
+
});
|
|
1577
|
+
return;
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
const gender = user.gender as Gender;
|
|
1581
|
+
const lang = user.lang as Languages;
|
|
1582
|
+
|
|
1583
|
+
// Check if archetypes already exist to avoid redundant queuing
|
|
1584
|
+
const existingArchetypes = await drizzle
|
|
1585
|
+
.select()
|
|
1586
|
+
.from(schema.archetypesData)
|
|
1587
|
+
.where(
|
|
1588
|
+
and(
|
|
1589
|
+
eq(schema.archetypesData.combination, combinationString),
|
|
1590
|
+
eq(schema.archetypesData.gender, gender),
|
|
1591
|
+
eq(schema.archetypesData.language, lang)
|
|
1592
|
+
)
|
|
1593
|
+
);
|
|
1594
|
+
|
|
1595
|
+
if (
|
|
1596
|
+
existingArchetypes.length > 0 &&
|
|
1597
|
+
existingArchetypes.every((a) => a.status === 'completed')
|
|
1598
|
+
) {
|
|
1599
|
+
await this.log('info', 'Archetypes already exist and completed', {
|
|
1600
|
+
count: existingArchetypes.length,
|
|
1601
|
+
});
|
|
1602
|
+
return;
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1605
|
+
// Queue the archetype generation
|
|
1606
|
+
const queuePayload = {
|
|
1607
|
+
combinationString,
|
|
1608
|
+
gender,
|
|
1609
|
+
language: lang,
|
|
1610
|
+
userId,
|
|
1611
|
+
override: false,
|
|
1612
|
+
};
|
|
1613
|
+
await this.log('info', 'Queuing archetype generation', { queuePayload });
|
|
1614
|
+
await this.context.env.ARCHETYPE_POPULATION_QUEUE.send(queuePayload);
|
|
1615
|
+
await this.log(
|
|
1616
|
+
'info',
|
|
1617
|
+
'Queued archetype generation successfully for user signup'
|
|
1618
|
+
);
|
|
1619
|
+
} catch (error) {
|
|
1620
|
+
await this.log('error', 'Error queuing archetype generation', {
|
|
1621
|
+
userId,
|
|
1622
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1623
|
+
});
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1319
1626
|
}
|
package/package.json
CHANGED
package/utils/buildMessages.ts
CHANGED
|
@@ -24,6 +24,8 @@ export const buildLLMMessages = (env: BackendBindings) => ({
|
|
|
24
24
|
role: 'system',
|
|
25
25
|
content: `
|
|
26
26
|
You are a gifted fantasy writer and astrologer. Your task is to write mystical **narrative descriptions** and **core virtues** for three archetypes, based on their names, essence lines, and astrological combination.
|
|
27
|
+
|
|
28
|
+
Your response must be insightful, symbolic, and restrained. Focus on personality traits, behaviors, and subtle symbolic elements inspired by the archetypal energies of the Sun, Ascendant, and Moon signs, conveyed through elegant metaphors and thoughtful storytelling. Avoid overly fantastical or magical imagery like glowing lights, ethereal realms, or supernatural abilities, and instead emphasize a grounded, sober tone while maintaining a mystical depth.
|
|
27
29
|
|
|
28
30
|
Each archetype is influenced by the zodiac combination (Sun, Ascendant, Moon), and each one emphasizes one of those signs respectively. The signs and the archetype name should not be mentioned in the description. Use only their abstract representation and symbolism.
|
|
29
31
|
|