@zodic/shared 0.0.155 → 0.0.156
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/ConceptService.ts +41 -27
- package/package.json +1 -1
|
@@ -28,22 +28,23 @@ export class ConceptService {
|
|
|
28
28
|
console.log(
|
|
29
29
|
`🚀 Generating basic info for concept: ${conceptSlug}, combination: ${combinationString}, override: ${override}`
|
|
30
30
|
);
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
const kvStore = this.context.kvConceptsStore();
|
|
33
33
|
const kvFailuresStore = this.context.kvConceptFailuresStore();
|
|
34
34
|
const kvNamesStore = this.context.kvConceptNamesStore(); // ✅ New KV for storing names
|
|
35
35
|
const kvKeyEN = buildConceptKVKey('en-us', conceptSlug, combinationString);
|
|
36
36
|
const kvKeyPT = buildConceptKVKey('pt-br', conceptSlug, combinationString);
|
|
37
37
|
const failureKey = `failures:basic-info:${conceptSlug}:${combinationString}`;
|
|
38
|
-
|
|
39
|
-
const namesKeyEN = `${conceptSlug}:en-us`;
|
|
40
|
-
const namesKeyPT = `${conceptSlug}:pt-br`;
|
|
41
|
-
|
|
38
|
+
|
|
39
|
+
const namesKeyEN = `${conceptSlug}:en-us`;
|
|
40
|
+
const namesKeyPT = `${conceptSlug}:pt-br`;
|
|
41
|
+
const reportKey = `report:${conceptSlug}`; // ✅ New tracking key
|
|
42
|
+
|
|
42
43
|
// ✅ Check if data already exists
|
|
43
44
|
if (!override) {
|
|
44
45
|
const existingEN = await this.getKVConcept(kvKeyEN);
|
|
45
46
|
const existingPT = await this.getKVConcept(kvKeyPT);
|
|
46
|
-
|
|
47
|
+
|
|
47
48
|
if (
|
|
48
49
|
existingEN.name &&
|
|
49
50
|
existingEN.description &&
|
|
@@ -60,16 +61,16 @@ export class ConceptService {
|
|
|
60
61
|
return;
|
|
61
62
|
}
|
|
62
63
|
}
|
|
63
|
-
|
|
64
|
+
|
|
64
65
|
let attempts = 0;
|
|
65
66
|
const maxAttempts = 3;
|
|
66
|
-
|
|
67
|
+
|
|
67
68
|
while (attempts < maxAttempts) {
|
|
68
69
|
let phase = 'generation';
|
|
69
70
|
try {
|
|
70
71
|
attempts++;
|
|
71
72
|
console.log(`🔄 Attempt ${attempts} to generate basic info...`);
|
|
72
|
-
|
|
73
|
+
|
|
73
74
|
// ✅ Fetch the full name lists
|
|
74
75
|
let allNamesEN = JSON.parse(
|
|
75
76
|
(await kvNamesStore.get(namesKeyEN)) || '[]'
|
|
@@ -77,11 +78,11 @@ export class ConceptService {
|
|
|
77
78
|
let allNamesPT = JSON.parse(
|
|
78
79
|
(await kvNamesStore.get(namesKeyPT)) || '[]'
|
|
79
80
|
) as string[];
|
|
80
|
-
|
|
81
|
+
|
|
81
82
|
// ✅ Get only the last 50 names for AI context
|
|
82
83
|
const recentNamesEN = allNamesEN.slice(-50);
|
|
83
84
|
const recentNamesPT = allNamesPT.slice(-50);
|
|
84
|
-
|
|
85
|
+
|
|
85
86
|
// ✅ Build the messages to request content, ensuring uniqueness
|
|
86
87
|
const messages = this.context
|
|
87
88
|
.buildLLMMessages()
|
|
@@ -90,22 +91,22 @@ export class ConceptService {
|
|
|
90
91
|
conceptSlug,
|
|
91
92
|
existingNames: recentNamesEN, // 🔥 Pass only recent names
|
|
92
93
|
});
|
|
93
|
-
|
|
94
|
+
|
|
94
95
|
// ✅ Call ChatGPT API
|
|
95
96
|
let response = await this.context.api().callTogether.single(messages, {});
|
|
96
97
|
if (!response) {
|
|
97
98
|
throw new Error(`❌ AI returned an empty response`);
|
|
98
99
|
}
|
|
99
|
-
|
|
100
|
+
|
|
100
101
|
phase = 'cleaning';
|
|
101
|
-
response = this.cleanAIResponse(response);
|
|
102
|
-
|
|
102
|
+
response = this.cleanAIResponse(response);
|
|
103
|
+
|
|
103
104
|
phase = 'parsing';
|
|
104
|
-
|
|
105
|
+
|
|
105
106
|
// ✅ Parse response for both languages
|
|
106
107
|
let { nameEN, descriptionEN, poemEN, namePT, descriptionPT, poemPT } =
|
|
107
108
|
this.parseBasicInfoResponse(response);
|
|
108
|
-
|
|
109
|
+
|
|
109
110
|
// 🔥 Check if generated English name is unique
|
|
110
111
|
if (allNamesEN.includes(nameEN)) {
|
|
111
112
|
console.warn(`⚠️ Duplicate Crown Name Detected: "${nameEN}"`);
|
|
@@ -117,7 +118,7 @@ export class ConceptService {
|
|
|
117
118
|
console.log('🔁 Retrying due to duplicate English name...');
|
|
118
119
|
continue;
|
|
119
120
|
}
|
|
120
|
-
|
|
121
|
+
|
|
121
122
|
// 🔥 Check if generated Portuguese name is unique
|
|
122
123
|
if (allNamesPT.includes(namePT)) {
|
|
123
124
|
console.warn(`⚠️ Duplicate Portuguese Name Detected: "${namePT}"`);
|
|
@@ -129,15 +130,15 @@ export class ConceptService {
|
|
|
129
130
|
console.log('🔁 Retrying due to duplicate Portuguese name...');
|
|
130
131
|
continue;
|
|
131
132
|
}
|
|
132
|
-
|
|
133
|
+
|
|
133
134
|
// ✅ Append new names to the full list
|
|
134
135
|
allNamesEN.push(nameEN);
|
|
135
136
|
allNamesPT.push(namePT);
|
|
136
|
-
|
|
137
|
+
|
|
137
138
|
// ✅ Store updated name lists in KV
|
|
138
139
|
await kvNamesStore.put(namesKeyEN, JSON.stringify(allNamesEN));
|
|
139
140
|
await kvNamesStore.put(namesKeyPT, JSON.stringify(allNamesPT));
|
|
140
|
-
|
|
141
|
+
|
|
141
142
|
// 🌍 English version
|
|
142
143
|
const conceptEN = await this.getKVConcept(kvKeyEN);
|
|
143
144
|
Object.assign(conceptEN, {
|
|
@@ -147,7 +148,7 @@ export class ConceptService {
|
|
|
147
148
|
status: 'idle',
|
|
148
149
|
});
|
|
149
150
|
await kvStore.put(kvKeyEN, JSON.stringify(conceptEN));
|
|
150
|
-
|
|
151
|
+
|
|
151
152
|
// 🇧🇷 Portuguese version
|
|
152
153
|
const conceptPT = await this.getKVConcept(kvKeyPT);
|
|
153
154
|
Object.assign(conceptPT, {
|
|
@@ -157,30 +158,43 @@ export class ConceptService {
|
|
|
157
158
|
status: 'idle',
|
|
158
159
|
});
|
|
159
160
|
await kvStore.put(kvKeyPT, JSON.stringify(conceptPT));
|
|
160
|
-
|
|
161
|
+
|
|
161
162
|
console.log(
|
|
162
163
|
`✅ Basic info stored for ${conceptSlug}, combination: ${combinationString}, in both languages.`
|
|
163
164
|
);
|
|
165
|
+
|
|
166
|
+
// ✅ Increment report tracking successful inserts
|
|
167
|
+
let currentCount = parseInt(
|
|
168
|
+
(await kvNamesStore.get(reportKey)) || '0',
|
|
169
|
+
10
|
|
170
|
+
);
|
|
171
|
+
currentCount += 1;
|
|
172
|
+
await kvNamesStore.put(reportKey, currentCount.toString());
|
|
173
|
+
|
|
174
|
+
console.log(
|
|
175
|
+
`📊 Updated progress for ${conceptSlug}: ${currentCount} successful inserts.`
|
|
176
|
+
);
|
|
177
|
+
|
|
164
178
|
return; // ✅ Exit loop if successful
|
|
165
179
|
} catch (error) {
|
|
166
180
|
console.error(
|
|
167
181
|
`❌ Attempt ${attempts} failed at phase: ${phase}`,
|
|
168
182
|
(error as Error).message
|
|
169
183
|
);
|
|
170
|
-
|
|
184
|
+
|
|
171
185
|
// ✅ Store failure details in KV for manual review
|
|
172
186
|
await kvFailuresStore.put(
|
|
173
187
|
failureKey,
|
|
174
188
|
JSON.stringify({
|
|
175
189
|
error: (error as Error).message,
|
|
176
190
|
attempt: attempts,
|
|
177
|
-
phase,
|
|
191
|
+
phase,
|
|
178
192
|
conceptSlug,
|
|
179
193
|
combinationString,
|
|
180
194
|
timestamp: new Date().toISOString(),
|
|
181
195
|
})
|
|
182
196
|
);
|
|
183
|
-
|
|
197
|
+
|
|
184
198
|
if (attempts >= maxAttempts) {
|
|
185
199
|
console.error(
|
|
186
200
|
`🚨 All ${maxAttempts} attempts failed during ${phase}. Logged failure.`
|
|
@@ -189,7 +203,7 @@ export class ConceptService {
|
|
|
189
203
|
`Failed to generate basic info after ${maxAttempts} attempts`
|
|
190
204
|
);
|
|
191
205
|
}
|
|
192
|
-
|
|
206
|
+
|
|
193
207
|
console.log('🔁 Retrying...');
|
|
194
208
|
await new Promise((resolve) => setTimeout(resolve, 500)); // ⏳ Small delay before retrying
|
|
195
209
|
}
|