@zodic/shared 0.0.180 → 0.0.182
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.
|
@@ -99,19 +99,34 @@ export class ConceptNameDO {
|
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
async addName(language: 'en-us' | 'pt-br', name: string): Promise<void> {
|
|
102
|
-
await this.getNames(); // Ensure latest
|
|
102
|
+
await this.getNames(); // Ensure latest name list is loaded
|
|
103
|
+
await this.loadCount(); // ✅ Load latest count before modifying
|
|
103
104
|
|
|
104
105
|
if (!this.names[language].includes(name)) {
|
|
105
106
|
this.names[language].push(name);
|
|
106
|
-
this.count
|
|
107
|
+
this.count += 1; // ✅ Increment count correctly
|
|
108
|
+
|
|
107
109
|
this.recordTimestamp();
|
|
108
110
|
|
|
109
|
-
// ✅ **
|
|
111
|
+
// ✅ **Store all updated values in a single put() call**
|
|
110
112
|
await this.state.storage.put({
|
|
111
113
|
names: this.names,
|
|
112
|
-
count: this.count,
|
|
114
|
+
count: this.count, // ✅ Store updated count properly
|
|
113
115
|
timestamps: this.timestamps,
|
|
114
116
|
});
|
|
117
|
+
|
|
118
|
+
console.log(
|
|
119
|
+
`✅ Added name "${name}" to ${language}, count is now ${this.count}`
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async loadCount(): Promise<void> {
|
|
125
|
+
const storedCount = await this.state.storage.get<number>('count');
|
|
126
|
+
if (typeof storedCount === 'number') {
|
|
127
|
+
this.count = storedCount; // ✅ Ensure we always load the latest count
|
|
128
|
+
} else {
|
|
129
|
+
this.count = 0; // ✅ Ensure count is initialized properly
|
|
115
130
|
}
|
|
116
131
|
}
|
|
117
132
|
|
|
@@ -28,51 +28,51 @@ 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 kvKeyEN = buildConceptKVKey('en-us', conceptSlug, combinationString);
|
|
35
35
|
const kvKeyPT = buildConceptKVKey('pt-br', conceptSlug, combinationString);
|
|
36
36
|
const failureKey = `failures:basic-info:${conceptSlug}:${combinationString}`;
|
|
37
|
-
|
|
37
|
+
|
|
38
38
|
// ✅ Use Durable Object stub
|
|
39
39
|
const id = this.context.env.CONCEPT_NAMES_DO.idFromName(conceptSlug);
|
|
40
40
|
const stub = this.context.env.CONCEPT_NAMES_DO.get(id);
|
|
41
|
-
|
|
41
|
+
|
|
42
42
|
let attempts = 0;
|
|
43
43
|
const maxAttempts = 3;
|
|
44
|
-
|
|
44
|
+
|
|
45
45
|
while (attempts < maxAttempts) {
|
|
46
46
|
let phase = 'generation';
|
|
47
47
|
try {
|
|
48
48
|
attempts++;
|
|
49
|
-
console.log(`🔄 Attempt ${attempts} to generate basic info...`);
|
|
50
|
-
|
|
49
|
+
console.log(`🔄 Attempt ${attempts} to generate basic info for ${conceptSlug}...`);
|
|
50
|
+
|
|
51
51
|
// ✅ Fetch the latest name list from Durable Object
|
|
52
|
+
console.log(`📡 Fetching names from Durable Object for ${conceptSlug}...`);
|
|
52
53
|
let allNamesEN: string[] = [];
|
|
53
54
|
let allNamesPT: string[] = [];
|
|
54
|
-
const response = await stub.fetch(
|
|
55
|
-
|
|
56
|
-
);
|
|
55
|
+
const response = await stub.fetch(`https://internal/names`);
|
|
56
|
+
|
|
57
57
|
if (response.ok) {
|
|
58
|
-
const data = (await response.json()) as {
|
|
59
|
-
'en-us': string[];
|
|
60
|
-
'pt-br': string[];
|
|
61
|
-
};
|
|
58
|
+
const data = (await response.json()) as { 'en-us': string[]; 'pt-br': string[] };
|
|
62
59
|
allNamesEN = data['en-us'] || [];
|
|
63
60
|
allNamesPT = data['pt-br'] || [];
|
|
61
|
+
console.log(`✅ Retrieved ${allNamesEN.length} EN names and ${allNamesPT.length} PT names.`);
|
|
64
62
|
} else {
|
|
65
|
-
console.log(
|
|
66
|
-
console.log('!-- Response:', await response.text());
|
|
63
|
+
console.log(`❌ Error fetching names from DO for ${conceptSlug}: ${await response.text()}`);
|
|
67
64
|
}
|
|
68
|
-
|
|
65
|
+
|
|
69
66
|
// ✅ Fetch existing KV data to backfill Durable Object if necessary
|
|
67
|
+
console.log(`📡 Fetching existing KV data for ${conceptSlug}...`);
|
|
70
68
|
const existingEN = await this.getKVConcept(kvKeyEN);
|
|
71
69
|
const existingPT = await this.getKVConcept(kvKeyPT);
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
|
|
71
|
+
console.log(`📝 Existing EN name: ${existingEN.name || 'None'}, PT name: ${existingPT.name || 'None'}`);
|
|
72
|
+
|
|
73
|
+
// 🔥 If names exist in KV but not in DO, add them
|
|
74
74
|
if (existingEN.name && !allNamesEN.includes(existingEN.name)) {
|
|
75
|
-
console.log(`⚡ Backfilling existing name to DO: ${existingEN.name}`);
|
|
75
|
+
console.log(`⚡ Backfilling existing EN name to DO: ${existingEN.name}`);
|
|
76
76
|
await stub.fetch(`https://internal/add-name`, {
|
|
77
77
|
method: 'POST',
|
|
78
78
|
body: JSON.stringify({ language: 'en-us', name: existingEN.name }),
|
|
@@ -80,23 +80,22 @@ export class ConceptService {
|
|
|
80
80
|
});
|
|
81
81
|
}
|
|
82
82
|
if (existingPT.name && !allNamesPT.includes(existingPT.name)) {
|
|
83
|
-
console.log(`⚡ Backfilling existing name to DO: ${existingPT.name}`);
|
|
83
|
+
console.log(`⚡ Backfilling existing PT name to DO: ${existingPT.name}`);
|
|
84
84
|
await stub.fetch(`https://internal/add-name`, {
|
|
85
85
|
method: 'POST',
|
|
86
86
|
body: JSON.stringify({ language: 'pt-br', name: existingPT.name }),
|
|
87
87
|
headers: { 'Content-Type': 'application/json' },
|
|
88
88
|
});
|
|
89
89
|
}
|
|
90
|
-
|
|
90
|
+
|
|
91
91
|
// ✅ Skip generation if basic info already exists and override is false
|
|
92
92
|
if (!override && existingEN.name && existingPT.name) {
|
|
93
|
-
console.log(
|
|
94
|
-
`⚡ Basic info already exists for ${conceptSlug}, skipping.`
|
|
95
|
-
);
|
|
93
|
+
console.log(`⚡ Basic info already exists for ${conceptSlug}, skipping.`);
|
|
96
94
|
return;
|
|
97
95
|
}
|
|
98
|
-
|
|
99
|
-
|
|
96
|
+
|
|
97
|
+
console.log(`✏️ Generating new name...`);
|
|
98
|
+
const recentNamesEN = allNamesEN.slice(-60);
|
|
100
99
|
const messages = this.context
|
|
101
100
|
.buildLLMMessages()
|
|
102
101
|
.generateConceptBasicInfo({
|
|
@@ -104,43 +103,44 @@ export class ConceptService {
|
|
|
104
103
|
conceptSlug,
|
|
105
104
|
existingNames: recentNamesEN,
|
|
106
105
|
});
|
|
107
|
-
|
|
108
|
-
let aiResponse = await this.context
|
|
109
|
-
.api()
|
|
110
|
-
.callTogether.single(messages, {});
|
|
106
|
+
|
|
107
|
+
let aiResponse = await this.context.api().callTogether.single(messages, {});
|
|
111
108
|
if (!aiResponse) throw new Error(`❌ AI returned an empty response`);
|
|
112
|
-
|
|
109
|
+
|
|
113
110
|
phase = 'cleaning';
|
|
111
|
+
console.log(`🧼 Cleaning AI response...`);
|
|
114
112
|
aiResponse = this.cleanAIResponse(aiResponse);
|
|
115
|
-
|
|
113
|
+
|
|
116
114
|
phase = 'parsing';
|
|
115
|
+
console.log(`📜 Parsing AI response...`);
|
|
117
116
|
let { nameEN, descriptionEN, poemEN, namePT, descriptionPT, poemPT } =
|
|
118
117
|
this.parseBasicInfoResponse(aiResponse, conceptSlug);
|
|
119
|
-
|
|
118
|
+
|
|
119
|
+
console.log(`🎭 Generated names: EN - "${nameEN}", PT - "${namePT}"`);
|
|
120
|
+
|
|
120
121
|
// ✅ Check uniqueness before storing
|
|
121
122
|
if (allNamesEN.includes(nameEN) || allNamesPT.includes(namePT)) {
|
|
122
|
-
console.warn(
|
|
123
|
-
`⚠️ Duplicate Name Detected: "${nameEN}" or "${namePT}"`
|
|
124
|
-
);
|
|
123
|
+
console.warn(`⚠️ Duplicate Name Detected: "${nameEN}" or "${namePT}"`);
|
|
125
124
|
if (attempts >= maxAttempts)
|
|
126
125
|
throw new Error(`🚨 Could not generate a unique name`);
|
|
127
126
|
console.log('🔁 Retrying due to duplicate name...');
|
|
128
127
|
continue;
|
|
129
128
|
}
|
|
130
|
-
|
|
129
|
+
|
|
130
|
+
console.log(`📝 Storing names in Durable Object...`);
|
|
131
131
|
// ✅ **Immediately update Durable Object with the new name**
|
|
132
132
|
await stub.fetch(`https://internal/add-name`, {
|
|
133
133
|
method: 'POST',
|
|
134
134
|
body: JSON.stringify({ language: 'en-us', name: nameEN }),
|
|
135
135
|
headers: { 'Content-Type': 'application/json' },
|
|
136
136
|
});
|
|
137
|
-
|
|
137
|
+
|
|
138
138
|
await stub.fetch(`https://internal/add-name`, {
|
|
139
139
|
method: 'POST',
|
|
140
140
|
body: JSON.stringify({ language: 'pt-br', name: namePT }),
|
|
141
141
|
headers: { 'Content-Type': 'application/json' },
|
|
142
142
|
});
|
|
143
|
-
|
|
143
|
+
|
|
144
144
|
// ✅ Store the generated basic info in KV
|
|
145
145
|
Object.assign(existingEN, {
|
|
146
146
|
name: nameEN,
|
|
@@ -149,7 +149,7 @@ export class ConceptService {
|
|
|
149
149
|
status: 'idle',
|
|
150
150
|
});
|
|
151
151
|
await kvStore.put(kvKeyEN, JSON.stringify(existingEN));
|
|
152
|
-
|
|
152
|
+
|
|
153
153
|
Object.assign(existingPT, {
|
|
154
154
|
name: namePT,
|
|
155
155
|
description: descriptionPT,
|
|
@@ -157,17 +157,12 @@ export class ConceptService {
|
|
|
157
157
|
status: 'idle',
|
|
158
158
|
});
|
|
159
159
|
await kvStore.put(kvKeyPT, JSON.stringify(existingPT));
|
|
160
|
-
|
|
161
|
-
console.log(
|
|
162
|
-
`✅ Stored basic info for ${conceptSlug}, combination: ${combinationString}.`
|
|
163
|
-
);
|
|
160
|
+
|
|
161
|
+
console.log(`✅ Stored basic info for ${conceptSlug}, combination: ${combinationString}.`);
|
|
164
162
|
return;
|
|
165
163
|
} catch (error) {
|
|
166
|
-
console.error(
|
|
167
|
-
|
|
168
|
-
(error as Error).message
|
|
169
|
-
);
|
|
170
|
-
|
|
164
|
+
console.error(`❌ Attempt ${attempts} failed at phase: ${phase}`, (error as Error).message);
|
|
165
|
+
|
|
171
166
|
// ✅ Store failure details in KV for debugging
|
|
172
167
|
await kvFailuresStore.put(
|
|
173
168
|
failureKey,
|
|
@@ -180,12 +175,10 @@ export class ConceptService {
|
|
|
180
175
|
timestamp: new Date().toISOString(),
|
|
181
176
|
})
|
|
182
177
|
);
|
|
183
|
-
|
|
178
|
+
|
|
184
179
|
if (attempts >= maxAttempts) {
|
|
185
180
|
console.error(`🚨 All ${maxAttempts} attempts failed.`);
|
|
186
|
-
throw new Error(
|
|
187
|
-
`Failed to generate basic info after ${maxAttempts} attempts.`
|
|
188
|
-
);
|
|
181
|
+
throw new Error(`Failed to generate basic info after ${maxAttempts} attempts.`);
|
|
189
182
|
}
|
|
190
183
|
console.log('🔁 Retrying...');
|
|
191
184
|
await new Promise((resolve) => setTimeout(resolve, 500));
|