@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 state
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
- // ✅ **Batch storage writes** instead of multiple separate `put()` calls
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
- `https://internal/names`
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(`!-- Error fetching names from DO for ${conceptSlug}`);
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
- // 🔥 If names already exist in KV but not in DO, add them
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
- const recentNamesEN = allNamesEN.slice(-144);
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
- `❌ Attempt ${attempts} failed at phase: ${phase}`,
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));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zodic/shared",
3
- "version": "0.0.180",
3
+ "version": "0.0.182",
4
4
  "module": "index.ts",
5
5
  "type": "module",
6
6
  "publishConfig": {