@zodic/shared 0.0.138 → 0.0.139
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.
|
@@ -16,64 +16,83 @@ export class ConceptService {
|
|
|
16
16
|
/**
|
|
17
17
|
* Generate basic info for a concept: name, description, and poem.
|
|
18
18
|
*/
|
|
19
|
-
async generateBasicInfo(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
): Promise<void> {
|
|
24
|
-
const kvKey = buildConceptKVKey(language, conceptSlug, combinationString);
|
|
25
|
-
console.log(
|
|
26
|
-
`Generating basic info for concept: ${conceptSlug}, combination: ${combinationString}, language: ${language}`
|
|
27
|
-
);
|
|
28
|
-
|
|
19
|
+
async generateBasicInfo(conceptSlug: Concept, combinationString: string): Promise<void> {
|
|
20
|
+
console.log(`🚀 Generating basic info for concept: ${conceptSlug}, combination: ${combinationString}`);
|
|
21
|
+
|
|
22
|
+
// ✅ Build the messages to request content
|
|
29
23
|
const messages = this.context.buildLLMMessages().generateConceptBasicInfo({
|
|
30
24
|
combination: combinationString,
|
|
31
25
|
conceptSlug,
|
|
32
26
|
});
|
|
33
|
-
|
|
27
|
+
|
|
28
|
+
// ✅ Call ChatGPT API
|
|
34
29
|
const response = await this.context.api().callChatGPT.single(messages, {});
|
|
35
30
|
if (!response) {
|
|
36
|
-
throw new Error(
|
|
37
|
-
`Failed to generate basic info for concept: ${conceptSlug}`
|
|
38
|
-
);
|
|
31
|
+
throw new Error(`❌ Failed to generate basic info for concept: ${conceptSlug}`);
|
|
39
32
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
);
|
|
33
|
+
|
|
34
|
+
// ✅ Parse response for both languages
|
|
35
|
+
const { nameEN, descriptionEN, poemEN, namePT, descriptionPT, poemPT } = this.parseBasicInfoResponse(response);
|
|
36
|
+
|
|
37
|
+
// ✅ Store in KV for both languages
|
|
38
|
+
const kvStore = this.context.kvConceptsStore();
|
|
39
|
+
|
|
40
|
+
// 🌍 English version
|
|
41
|
+
const kvKeyEN = buildConceptKVKey("en-us", conceptSlug, combinationString);
|
|
42
|
+
const conceptEN = await this.getKVConcept(kvKeyEN);
|
|
43
|
+
Object.assign(conceptEN, { name: nameEN, description: descriptionEN, poem: poemEN, status: "idle" });
|
|
44
|
+
await kvStore.put(kvKeyEN, JSON.stringify(conceptEN));
|
|
45
|
+
|
|
46
|
+
// 🇧🇷 Portuguese version
|
|
47
|
+
const kvKeyPT = buildConceptKVKey("pt-br", conceptSlug, combinationString);
|
|
48
|
+
const conceptPT = await this.getKVConcept(kvKeyPT);
|
|
49
|
+
Object.assign(conceptPT, { name: namePT, description: descriptionPT, poem: poemPT, status: "idle" });
|
|
50
|
+
await kvStore.put(kvKeyPT, JSON.stringify(conceptPT));
|
|
51
|
+
|
|
52
|
+
console.log(`✅ Basic info stored for ${conceptSlug}, combination: ${combinationString}, in both languages.`);
|
|
50
53
|
}
|
|
51
54
|
|
|
52
55
|
private parseBasicInfoResponse(response: string): {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
+
nameEN: string;
|
|
57
|
+
descriptionEN: string;
|
|
58
|
+
poemEN: string;
|
|
59
|
+
namePT: string;
|
|
60
|
+
descriptionPT: string;
|
|
61
|
+
poemPT: string;
|
|
56
62
|
} {
|
|
57
|
-
console.log(
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
63
|
+
console.log("📌 Parsing basic info response from ChatGPT:", response);
|
|
64
|
+
|
|
65
|
+
const nameENMatch = response.match(/EN:\s*•\s*Name:\s*(.+)/);
|
|
66
|
+
const descriptionENMatch = response.match(/EN:\s*•\s*Description:\s*([\s\S]+?)\s*•\s*Poetic Passage:/);
|
|
67
|
+
const poemENMatch = response.match(/EN:\s*•\s*Poetic Passage:\s*([\s\S]+?)\s*PT:/);
|
|
68
|
+
|
|
69
|
+
const namePTMatch = response.match(/PT:\s*•\s*Nome:\s*(.+)/);
|
|
70
|
+
const descriptionPTMatch = response.match(/PT:\s*•\s*Descrição:\s*([\s\S]+?)\s*•\s*Passagem Poética:/);
|
|
71
|
+
const poemPTMatch = response.match(/PT:\s*•\s*Passagem Poética:\s*([\s\S]+)/);
|
|
72
|
+
|
|
73
|
+
if (!nameENMatch || !descriptionENMatch || !poemENMatch || !namePTMatch || !descriptionPTMatch || !poemPTMatch) {
|
|
74
|
+
console.error("❌ Invalid basic info response format:", response);
|
|
75
|
+
throw new Error("Invalid basic info response format");
|
|
68
76
|
}
|
|
69
|
-
|
|
70
|
-
const
|
|
71
|
-
const
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
+
|
|
78
|
+
const nameEN = nameENMatch[1].trim();
|
|
79
|
+
const descriptionEN = descriptionENMatch[1].trim();
|
|
80
|
+
const poemEN = poemENMatch[1].trim();
|
|
81
|
+
|
|
82
|
+
const namePT = namePTMatch[1].trim();
|
|
83
|
+
const descriptionPT = descriptionPTMatch[1].trim();
|
|
84
|
+
const poemPT = poemPTMatch[1].trim();
|
|
85
|
+
|
|
86
|
+
console.log("✅ Parsed basic info:", {
|
|
87
|
+
nameEN,
|
|
88
|
+
descriptionEN,
|
|
89
|
+
poemEN,
|
|
90
|
+
namePT,
|
|
91
|
+
descriptionPT,
|
|
92
|
+
poemPT,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
return { nameEN, descriptionEN, poemEN, namePT, descriptionPT, poemPT };
|
|
77
96
|
}
|
|
78
97
|
|
|
79
98
|
/**
|
package/package.json
CHANGED
package/utils/buildMessages.ts
CHANGED
|
@@ -99,7 +99,7 @@ export const buildLLMMessages = (env: BackendBindings) => ({
|
|
|
99
99
|
conceptSlug,
|
|
100
100
|
}: {
|
|
101
101
|
combination: string;
|
|
102
|
-
conceptSlug:
|
|
102
|
+
conceptSlug: Concept;
|
|
103
103
|
}): ChatMessages => {
|
|
104
104
|
const zodiacCombination = mapConceptToPlanets(conceptSlug, combination);
|
|
105
105
|
|
|
@@ -111,8 +111,7 @@ export const buildLLMMessages = (env: BackendBindings) => ({
|
|
|
111
111
|
{
|
|
112
112
|
role: 'user',
|
|
113
113
|
content: `
|
|
114
|
-
Combination:
|
|
115
|
-
${zodiacCombination}
|
|
114
|
+
Combination: ${zodiacCombination}
|
|
116
115
|
`,
|
|
117
116
|
},
|
|
118
117
|
];
|
|
@@ -122,7 +121,7 @@ export const buildLLMMessages = (env: BackendBindings) => ({
|
|
|
122
121
|
conceptSlug,
|
|
123
122
|
}: {
|
|
124
123
|
combination: string;
|
|
125
|
-
conceptSlug:
|
|
124
|
+
conceptSlug: Concept;
|
|
126
125
|
}): ChatMessages => [
|
|
127
126
|
{
|
|
128
127
|
role: 'system',
|
|
@@ -145,24 +144,28 @@ export const buildLLMMessages = (env: BackendBindings) => ({
|
|
|
145
144
|
name: string;
|
|
146
145
|
description: string;
|
|
147
146
|
poem: string;
|
|
148
|
-
conceptSlug:
|
|
147
|
+
conceptSlug: Concept;
|
|
149
148
|
combination: string;
|
|
150
|
-
}): ChatMessages =>
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
149
|
+
}): ChatMessages => {
|
|
150
|
+
const zodiacCombination = mapConceptToPlanets(conceptSlug, combination);
|
|
151
|
+
|
|
152
|
+
return [
|
|
153
|
+
{
|
|
154
|
+
role: 'system',
|
|
155
|
+
content: conceptPrompts(env)['content'][conceptSlug],
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
role: 'user',
|
|
159
|
+
content: `
|
|
158
160
|
Concept Details:
|
|
159
|
-
- Combination: ${
|
|
161
|
+
- Combination: ${zodiacCombination}
|
|
160
162
|
- Name: ${name}
|
|
161
163
|
- Description: ${description}
|
|
162
164
|
- Poem: ${poem}
|
|
163
165
|
|
|
164
166
|
Generate additional content to elaborate on this concept for frontend display.
|
|
165
167
|
`,
|
|
166
|
-
|
|
167
|
-
|
|
168
|
+
},
|
|
169
|
+
];
|
|
170
|
+
},
|
|
168
171
|
});
|
package/utils/conceptPrompts.ts
CHANGED
|
@@ -52,14 +52,36 @@ export const conceptPrompts: (
|
|
|
52
52
|
// }
|
|
53
53
|
|
|
54
54
|
export const PROMPT_GENERATE_CROWN = `
|
|
55
|
-
You are a skilled creative writer specializing in astrology and symbolic storytelling. Your task is to craft a name, description, and poetic
|
|
56
|
-
|
|
57
|
-
For the given combination:
|
|
58
|
-
1. Name: Keep it sober and descriptive, focusing on the Crown’s symbolic purpose. Avoid ornate or fantastical phrasing. It should start with
|
|
59
|
-
2. Description: Write a concise, grounded narrative that links the Crown’s qualities to the traits of the zodiac combination. Emphasize balance, identity, and inner power without exaggeration.
|
|
60
|
-
3.
|
|
61
|
-
|
|
62
|
-
|
|
55
|
+
You are a skilled creative writer specializing in astrology and symbolic storytelling. Your task is to craft a name, description, and poetic passage for the Crown concept in both English and Brazilian Portuguese simultaneously. The Crown reflects core identity, representing self-awareness, inner strength, and personal truth, as influenced by a given zodiac sign combination.
|
|
56
|
+
|
|
57
|
+
For the given combination, generate the following in both languages, ensuring the content remains identical in meaning and tone except for the poem, which should be independently written in each language:
|
|
58
|
+
1. Name (Nome): Keep it sober and descriptive, focusing on the Crown’s symbolic purpose. Avoid ornate or fantastical phrasing. It should start with “The Crown of…” in English and “A Coroa de…” in Portuguese.
|
|
59
|
+
2. Description (Descrição): Write a concise, grounded narrative that links the Crown’s qualities to the traits of the zodiac combination. Emphasize balance, identity, and inner power without exaggeration. Keep the Portuguese version faithful in tone and depth to the English version.
|
|
60
|
+
3. Poetic Passage (Passagem Poética): Create two separate and independent poetic passages—one in English, one in Portuguese. Each should reflect the same essence but be uniquely crafted to best suit the flow and artistic qualities of its respective language. The passage should be long and evocative, 4 poetic lines, ensuring it deeply resonates and immerses the reader in a sense of destiny, wisdom, and transformation.
|
|
61
|
+
• Do not translate the poem directly—let each version flourish naturally in its own language.
|
|
62
|
+
• Ensure the passage flows rhythmically, evoking emotion and imagery.
|
|
63
|
+
• Avoid mentioning the Crown itself or using the word “crown.”
|
|
64
|
+
|
|
65
|
+
Rules & Formatting:
|
|
66
|
+
• Do not mention zodiac signs or planets explicitly.
|
|
67
|
+
• Ensure both descriptions are structurally and emotionally equivalent.
|
|
68
|
+
• Write the poem freely in each language to maximize impact, avoiding direct translation.
|
|
69
|
+
• Use rich, symbolic language while keeping it accessible and inspiring.
|
|
70
|
+
• Use around 120-140 words to create the description
|
|
71
|
+
|
|
72
|
+
Response Format:
|
|
73
|
+
|
|
74
|
+
EN:
|
|
75
|
+
• Name: The Crown of [Symbolic Concept]
|
|
76
|
+
• Description: [Concise and grounded explanation - around 120-140 words]
|
|
77
|
+
• Poetic Passage:
|
|
78
|
+
[4 poetic lines uniquely written in English]
|
|
79
|
+
|
|
80
|
+
PT:
|
|
81
|
+
• Nome: A Coroa de [Conceito Simbólico]
|
|
82
|
+
• Descrição: [Explicação concisa e bem fundamentada - em torno de 120-140 palavras]
|
|
83
|
+
• Passagem Poética:
|
|
84
|
+
[4 poetic lines uniquely written in Portuguese]
|
|
63
85
|
`;
|
|
64
86
|
|
|
65
87
|
export const PROMPT_GENERATE_SCEPTER = `
|
|
@@ -27,5 +27,8 @@ export const mapConceptToPlanets = (
|
|
|
27
27
|
);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
// ✅ Format planets and signs properly
|
|
31
|
+
return signs
|
|
32
|
+
.map((sign, index) => `${planets[index]} in ${sign}`)
|
|
33
|
+
.join(', ');
|
|
31
34
|
};
|