@zodic/shared 0.0.139 β 0.0.141
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/base/AppContext.ts +5 -26
- package/app/services/ConceptService.ts +119 -51
- package/package.json +1 -1
- package/types/scopes/cloudflare.ts +3 -10
package/app/base/AppContext.ts
CHANGED
|
@@ -25,40 +25,19 @@ export class AppContext {
|
|
|
25
25
|
kvConceptsStore() {
|
|
26
26
|
if (!this.env.KV_CONCEPTS) {
|
|
27
27
|
throw new Error(
|
|
28
|
-
'
|
|
28
|
+
'KV_CONCEPTS is not defined in the environment.'
|
|
29
29
|
);
|
|
30
30
|
}
|
|
31
31
|
return this.env.KV_CONCEPTS;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
if (!this.env.
|
|
34
|
+
kvConceptFailuresStore() {
|
|
35
|
+
if (!this.env.KV_CONCEPT_FAILURES) {
|
|
36
36
|
throw new Error(
|
|
37
|
-
'
|
|
37
|
+
'KV_CONCEPT_FAILURES is not defined in the environment.'
|
|
38
38
|
);
|
|
39
39
|
}
|
|
40
|
-
return this.env.
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
kvUserGenerationStore() {
|
|
44
|
-
if (!this.env.KV_USER_GENERATIONS) {
|
|
45
|
-
throw new Error('KV_USER_GENERATIONS is not defined in the environment.');
|
|
46
|
-
}
|
|
47
|
-
return this.env.KV_GENERATION_MANAGEMENT;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
kvPromptsStore() {
|
|
51
|
-
if (!this.env.KV_LEONARDO_PROMPTS) {
|
|
52
|
-
throw new Error('KV_LEONARDO_PROMPTS is not defined in the environment.');
|
|
53
|
-
}
|
|
54
|
-
return this.env.KV_LEONARDO_PROMPTS;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
kvUserProductStatus() {
|
|
58
|
-
if (!this.env.KV_USER_PRODUCT_STATUS) {
|
|
59
|
-
throw new Error('KV_LEONARDO_PROMPTS is not defined in the environment.');
|
|
60
|
-
}
|
|
61
|
-
return this.env.KV_USER_PRODUCT_STATUS;
|
|
40
|
+
return this.env.KV_CONCEPT_FAILURES;
|
|
62
41
|
}
|
|
63
42
|
|
|
64
43
|
kvConceptsManagementStore() {
|
|
@@ -16,40 +16,109 @@ export class ConceptService {
|
|
|
16
16
|
/**
|
|
17
17
|
* Generate basic info for a concept: name, description, and poem.
|
|
18
18
|
*/
|
|
19
|
-
async generateBasicInfo(
|
|
20
|
-
|
|
19
|
+
async generateBasicInfo(
|
|
20
|
+
conceptSlug: Concept,
|
|
21
|
+
combinationString: string,
|
|
22
|
+
override: boolean = false // β
New optional override param
|
|
23
|
+
): Promise<void> {
|
|
24
|
+
console.log(
|
|
25
|
+
`π Generating basic info for concept: ${conceptSlug}, combination: ${combinationString}, override: ${override}`
|
|
26
|
+
);
|
|
21
27
|
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
28
|
+
const kvStore = this.context.kvConceptsStore();
|
|
29
|
+
const kvFailuresStore = this.context.kvConceptFailuresStore(); // π΄ Replace with actual KV store
|
|
30
|
+
const kvKeyEN = buildConceptKVKey("en-us", conceptSlug, combinationString);
|
|
31
|
+
const kvKeyPT = buildConceptKVKey("pt-br", conceptSlug, combinationString);
|
|
32
|
+
const failureKey = `failures:${conceptSlug}:${combinationString}`;
|
|
27
33
|
|
|
28
|
-
// β
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
34
|
+
// β
Check if data already exists
|
|
35
|
+
if (!override) {
|
|
36
|
+
const existingEN = await this.getKVConcept(kvKeyEN);
|
|
37
|
+
const existingPT = await this.getKVConcept(kvKeyPT);
|
|
38
|
+
|
|
39
|
+
if (
|
|
40
|
+
existingEN.name && existingEN.description && existingEN.poem &&
|
|
41
|
+
existingPT.name && existingPT.description && existingPT.poem
|
|
42
|
+
) {
|
|
43
|
+
console.log(`β‘ Basic info already exists for ${conceptSlug}, combination: ${combinationString}. Skipping.`);
|
|
44
|
+
return; // β
Skip regeneration
|
|
45
|
+
}
|
|
32
46
|
}
|
|
33
47
|
|
|
34
|
-
|
|
35
|
-
const
|
|
48
|
+
let attempts = 0;
|
|
49
|
+
const maxAttempts = 3;
|
|
36
50
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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));
|
|
51
|
+
while (attempts < maxAttempts) {
|
|
52
|
+
let phase = "generation"; // π Track the phase
|
|
53
|
+
try {
|
|
54
|
+
attempts++;
|
|
55
|
+
console.log(`π Attempt ${attempts} to generate basic info...`);
|
|
45
56
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
57
|
+
// β
Build the messages to request content
|
|
58
|
+
const messages = this.context.buildLLMMessages().generateConceptBasicInfo({
|
|
59
|
+
combination: combinationString,
|
|
60
|
+
conceptSlug,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// β
Call ChatGPT API
|
|
64
|
+
const response = await this.context.api().callChatGPT.single(messages, {});
|
|
65
|
+
if (!response) {
|
|
66
|
+
throw new Error(`β AI returned an empty response`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
phase = "parsing"; // β
Switch to parsing phase
|
|
70
|
+
|
|
71
|
+
// β
Parse response for both languages
|
|
72
|
+
const { nameEN, descriptionEN, poemEN, namePT, descriptionPT, poemPT } =
|
|
73
|
+
this.parseBasicInfoResponse(response);
|
|
74
|
+
|
|
75
|
+
// π English version
|
|
76
|
+
const conceptEN = await this.getKVConcept(kvKeyEN);
|
|
77
|
+
Object.assign(conceptEN, {
|
|
78
|
+
name: nameEN,
|
|
79
|
+
description: descriptionEN,
|
|
80
|
+
poem: poemEN,
|
|
81
|
+
status: "idle",
|
|
82
|
+
});
|
|
83
|
+
await kvStore.put(kvKeyEN, JSON.stringify(conceptEN));
|
|
84
|
+
|
|
85
|
+
// π§π· Portuguese version
|
|
86
|
+
const conceptPT = await this.getKVConcept(kvKeyPT);
|
|
87
|
+
Object.assign(conceptPT, {
|
|
88
|
+
name: namePT,
|
|
89
|
+
description: descriptionPT,
|
|
90
|
+
poem: poemPT,
|
|
91
|
+
status: "idle",
|
|
92
|
+
});
|
|
93
|
+
await kvStore.put(kvKeyPT, JSON.stringify(conceptPT));
|
|
51
94
|
|
|
52
|
-
|
|
95
|
+
console.log(
|
|
96
|
+
`β
Basic info stored for ${conceptSlug}, combination: ${combinationString}, in both languages.`
|
|
97
|
+
);
|
|
98
|
+
return; // β
Exit loop if successful
|
|
99
|
+
|
|
100
|
+
} catch (error) {
|
|
101
|
+
console.error(`β Attempt ${attempts} failed at phase: ${phase}`, (error as Error).message);
|
|
102
|
+
|
|
103
|
+
// β
Store failure details in KV for manual review
|
|
104
|
+
await kvFailuresStore.put(failureKey, JSON.stringify({
|
|
105
|
+
error: (error as Error).message,
|
|
106
|
+
attempt: attempts,
|
|
107
|
+
phase, // β
Identify if failure occurred in "generation" or "parsing"
|
|
108
|
+
conceptSlug,
|
|
109
|
+
combinationString,
|
|
110
|
+
timestamp: new Date().toISOString(),
|
|
111
|
+
}));
|
|
112
|
+
|
|
113
|
+
if (attempts >= maxAttempts) {
|
|
114
|
+
console.error(`π¨ All ${maxAttempts} attempts failed during ${phase}. Logged failure.`);
|
|
115
|
+
throw new Error(`Failed to generate basic info after ${maxAttempts} attempts`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
console.log("π Retrying...");
|
|
119
|
+
await new Promise((resolve) => setTimeout(resolve, 2000)); // β³ Small delay before retrying
|
|
120
|
+
}
|
|
121
|
+
}
|
|
53
122
|
}
|
|
54
123
|
|
|
55
124
|
private parseBasicInfoResponse(response: string): {
|
|
@@ -60,30 +129,29 @@ export class ConceptService {
|
|
|
60
129
|
descriptionPT: string;
|
|
61
130
|
poemPT: string;
|
|
62
131
|
} {
|
|
63
|
-
console.log(
|
|
64
|
-
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
throw new Error("Invalid basic info response format");
|
|
132
|
+
console.log('π Parsing basic info response from ChatGPT:', response);
|
|
133
|
+
|
|
134
|
+
const enMatch = response.match(
|
|
135
|
+
/EN:\s*β’\s*Name:\s*(.+?)\s*β’\s*Description:\s*([\s\S]+?)\s*β’\s*Poetic Passage:\s*([\s\S]+?)\s*(?=PT:|$)/
|
|
136
|
+
);
|
|
137
|
+
const ptMatch = response.match(
|
|
138
|
+
/PT:\s*β’\s*Nome:\s*(.+?)\s*β’\s*DescriΓ§Γ£o:\s*([\s\S]+?)\s*β’\s*Passagem PoΓ©tica:\s*([\s\S]+)/
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
if (!enMatch || !ptMatch) {
|
|
142
|
+
console.error('β Invalid basic info response format:', response);
|
|
143
|
+
throw new Error('Invalid basic info response format');
|
|
76
144
|
}
|
|
77
|
-
|
|
78
|
-
const nameEN =
|
|
79
|
-
const descriptionEN =
|
|
80
|
-
const poemEN =
|
|
81
|
-
|
|
82
|
-
const namePT =
|
|
83
|
-
const descriptionPT =
|
|
84
|
-
const poemPT =
|
|
85
|
-
|
|
86
|
-
console.log(
|
|
145
|
+
|
|
146
|
+
const nameEN = enMatch[1].trim();
|
|
147
|
+
const descriptionEN = enMatch[2].trim();
|
|
148
|
+
const poemEN = enMatch[3].trim();
|
|
149
|
+
|
|
150
|
+
const namePT = ptMatch[1].trim();
|
|
151
|
+
const descriptionPT = ptMatch[2].trim();
|
|
152
|
+
const poemPT = ptMatch[3].trim();
|
|
153
|
+
|
|
154
|
+
console.log('β
Successfully parsed basic info:', {
|
|
87
155
|
nameEN,
|
|
88
156
|
descriptionEN,
|
|
89
157
|
poemEN,
|
|
@@ -91,7 +159,7 @@ export class ConceptService {
|
|
|
91
159
|
descriptionPT,
|
|
92
160
|
poemPT,
|
|
93
161
|
});
|
|
94
|
-
|
|
162
|
+
|
|
95
163
|
return { nameEN, descriptionEN, poemEN, namePT, descriptionPT, poemPT };
|
|
96
164
|
}
|
|
97
165
|
|
package/package.json
CHANGED
|
@@ -17,15 +17,11 @@ export type CentralBindings = {
|
|
|
17
17
|
DESCRIBER_API_KEY: string;
|
|
18
18
|
DESCRIBER_APP_ID: string;
|
|
19
19
|
AKOOL_API_KEY: string;
|
|
20
|
-
KV_GENERATION_MANAGEMENT: KVNamespace;
|
|
21
|
-
KV_USER_GENERATIONS: KVNamespace;
|
|
22
20
|
KV_COSMIC_MIRROR_ARCHETYPES: KVNamespace;
|
|
23
21
|
KV_CONCEPTS: KVNamespace;
|
|
24
22
|
KV_CONCEPTS_MANAGEMENT: KVNamespace;
|
|
25
|
-
KV_LEONARDO_PROMPTS: KVNamespace;
|
|
26
23
|
KV_ASTRO: KVNamespace;
|
|
27
|
-
|
|
28
|
-
KV_USER_PRODUCT_STATUS: KVNamespace;
|
|
24
|
+
KV_CONCEPT_FAILURES: KVNamespace;
|
|
29
25
|
CONCEPT_GENERATION_QUEUE: Queue;
|
|
30
26
|
|
|
31
27
|
PROMPT_IMAGE_DESCRIBER: string;
|
|
@@ -86,12 +82,11 @@ export type BackendBindings = Env &
|
|
|
86
82
|
| 'DESCRIBER_API_KEY'
|
|
87
83
|
| 'DESCRIBER_APP_ID'
|
|
88
84
|
| 'AKOOL_API_KEY'
|
|
89
|
-
| 'KV_GENERATION_MANAGEMENT'
|
|
90
|
-
| 'KV_USER_GENERATIONS'
|
|
91
85
|
| 'KV_COSMIC_MIRROR_ARCHETYPES'
|
|
92
86
|
| 'KV_CONCEPTS'
|
|
93
|
-
| 'KV_LEONARDO_PROMPTS'
|
|
94
87
|
| 'KV_ASTRO'
|
|
88
|
+
| 'KV_CONCEPTS_MANAGEMENT'
|
|
89
|
+
| 'KV_CONCEPT_FAILURES'
|
|
95
90
|
| 'PROMPT_IMAGE_DESCRIBER'
|
|
96
91
|
| 'PROMPT_GENERATE_ARCHETYPE_CONTENT'
|
|
97
92
|
| 'PROMPT_GENERATE_ARCHETYPE_LEONARDO_PROMPTS'
|
|
@@ -109,10 +104,8 @@ export type BackendBindings = Env &
|
|
|
109
104
|
| 'ASTROLOGY_PDF_API_KEY'
|
|
110
105
|
| 'ASTROLOGY_PDF_USER_ID'
|
|
111
106
|
| 'AI'
|
|
112
|
-
| 'KV_USER_PRODUCT_STATUS'
|
|
113
107
|
| 'PIAPI_API_KEY'
|
|
114
108
|
| 'CONCEPT_GENERATION_QUEUE'
|
|
115
|
-
| 'KV_CONCEPTS_MANAGEMENT'
|
|
116
109
|
| 'DEEPSEEK_API_KEY'
|
|
117
110
|
| 'PROMPT_GENERATE_ARCHETYPE_BASIC_INFO'
|
|
118
111
|
>;
|