@zodic/shared 0.0.313 → 0.0.315
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/ArchetypeService.ts +190 -0
- package/app/workflow/ArchetypeWorkflow.ts +676 -124
- package/db/migrations/0014_green_marvel_apes.sql +10 -0
- package/db/migrations/meta/0014_snapshot.json +2723 -0
- package/db/migrations/meta/_journal.json +7 -0
- package/db/schema.ts +17 -0
- package/package.json +1 -1
- package/utils/buildMessages.ts +273 -59
- package/utils/duplicatedArchetypeNamePrompt.ts +47 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { and, eq } from 'drizzle-orm';
|
|
1
2
|
import { inject, injectable } from 'inversify';
|
|
3
|
+
import { schema } from '../..';
|
|
2
4
|
import { Gender } from '../../types';
|
|
3
|
-
import { KVArchetype } from '../../types/scopes/legacy';
|
|
4
|
-
import { buildCosmicMirrorArchetypeKVKey } from '../../utils/KVKeysBuilders';
|
|
5
5
|
import { AppContext } from '../base/AppContext';
|
|
6
6
|
import { ArchetypeService } from '../services/ArchetypeService';
|
|
7
7
|
import { LeonardoService } from '../services/LeonardoService';
|
|
@@ -14,176 +14,728 @@ export class ArchetypeWorkflow {
|
|
|
14
14
|
@inject(LeonardoService) private leonardoService: LeonardoService
|
|
15
15
|
) {}
|
|
16
16
|
|
|
17
|
-
async
|
|
18
|
-
|
|
17
|
+
private async log(
|
|
18
|
+
level: 'info' | 'debug' | 'warn' | 'error',
|
|
19
|
+
message: string,
|
|
20
|
+
context: Record<string, any> = {}
|
|
21
|
+
) {
|
|
22
|
+
const logId = `archetype-workflow:${Date.now()}`;
|
|
23
|
+
const logMessage = `[${level.toUpperCase()}] ${message}`;
|
|
24
|
+
|
|
25
|
+
console[level](logMessage, context);
|
|
26
|
+
|
|
27
|
+
const db = this.context.drizzle();
|
|
28
|
+
try {
|
|
29
|
+
await db
|
|
30
|
+
.insert(schema.logs)
|
|
31
|
+
.values({
|
|
32
|
+
id: logId,
|
|
33
|
+
level,
|
|
34
|
+
message,
|
|
35
|
+
context: JSON.stringify(context),
|
|
36
|
+
createdAt: new Date().getTime(),
|
|
37
|
+
})
|
|
38
|
+
.execute();
|
|
39
|
+
} catch (error) {
|
|
40
|
+
console.error('[ERROR] Failed to persist log to database:', {
|
|
41
|
+
error,
|
|
42
|
+
logId,
|
|
43
|
+
message,
|
|
44
|
+
context,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async execute(
|
|
50
|
+
combinationString: string,
|
|
51
|
+
gender: Gender,
|
|
52
|
+
language: string = 'en-us'
|
|
53
|
+
) {
|
|
54
|
+
await this.log('info', 'Starting ArchetypeWorkflow', {
|
|
19
55
|
combinationString,
|
|
20
56
|
gender,
|
|
57
|
+
language,
|
|
21
58
|
});
|
|
22
59
|
|
|
23
|
-
|
|
60
|
+
// Fetch archetypes from archetypes_data
|
|
61
|
+
await this.log('debug', 'Fetching archetypes from database', {
|
|
62
|
+
combinationString,
|
|
63
|
+
gender,
|
|
64
|
+
language,
|
|
65
|
+
});
|
|
66
|
+
const archetypes = await this.fetchArchetypesFromDB(
|
|
24
67
|
combinationString,
|
|
25
|
-
gender
|
|
68
|
+
gender,
|
|
69
|
+
language
|
|
26
70
|
);
|
|
71
|
+
await this.log('info', 'Fetched archetypes', {
|
|
72
|
+
archetypesCount: archetypes.length,
|
|
73
|
+
archetypeIds: archetypes.map((a) => a.id),
|
|
74
|
+
});
|
|
27
75
|
|
|
28
|
-
if
|
|
29
|
-
|
|
30
|
-
|
|
76
|
+
// Check if any archetypes are already being processed (images are generating)
|
|
77
|
+
const db = this.context.drizzle();
|
|
78
|
+
await this.log('debug', 'Checking for in-progress image generations', {
|
|
79
|
+
combinationString,
|
|
80
|
+
gender,
|
|
81
|
+
});
|
|
82
|
+
const inProgressGenerations = await db
|
|
83
|
+
.select()
|
|
84
|
+
.from(schema.generations)
|
|
85
|
+
.where(
|
|
86
|
+
and(
|
|
87
|
+
eq(schema.generations.status, 'pending'),
|
|
88
|
+
eq(schema.generations.gender, gender),
|
|
89
|
+
eq(schema.generations.conceptCombinationId, combinationString)
|
|
90
|
+
)
|
|
91
|
+
)
|
|
92
|
+
.execute();
|
|
93
|
+
|
|
94
|
+
if (inProgressGenerations.length > 0) {
|
|
95
|
+
await this.log(
|
|
96
|
+
'warn',
|
|
97
|
+
`Images are already being processed for ${combinationString}, gender: ${gender}`,
|
|
98
|
+
{
|
|
99
|
+
inProgressGenerationsCount: inProgressGenerations.length,
|
|
100
|
+
generationIds: inProgressGenerations.map((g) => g.id),
|
|
101
|
+
}
|
|
31
102
|
);
|
|
32
103
|
return { message: 'Images are being processed, please try again later.' };
|
|
33
104
|
}
|
|
105
|
+
await this.log('info', 'No in-progress image generations found', {
|
|
106
|
+
combinationString,
|
|
107
|
+
gender,
|
|
108
|
+
});
|
|
34
109
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
110
|
+
// Step 1: Generate missing textual content (description, virtues, content, leonardoPrompt)
|
|
111
|
+
const archetypesNeedingText = archetypes.filter(
|
|
112
|
+
(arc) =>
|
|
113
|
+
!arc.description ||
|
|
114
|
+
arc.virtues === '[]' ||
|
|
115
|
+
arc.content === '[]' ||
|
|
116
|
+
!arc.leonardoPrompt
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
if (archetypesNeedingText.length > 0) {
|
|
120
|
+
await this.log('info', 'Generating missing textual content', {
|
|
121
|
+
combinationString,
|
|
122
|
+
gender,
|
|
123
|
+
language,
|
|
124
|
+
archetypesNeedingTextCount: archetypesNeedingText.length,
|
|
125
|
+
archetypeIds: archetypesNeedingText.map((a) => a.id),
|
|
126
|
+
});
|
|
127
|
+
await this.generateTextualContent(combinationString, gender, language);
|
|
128
|
+
} else {
|
|
129
|
+
await this.log('info', 'No textual content generation needed', {
|
|
130
|
+
combinationString,
|
|
131
|
+
gender,
|
|
132
|
+
language,
|
|
133
|
+
});
|
|
40
134
|
}
|
|
41
135
|
|
|
42
|
-
|
|
136
|
+
// Refetch archetypes after generating textual content
|
|
137
|
+
await this.log(
|
|
138
|
+
'debug',
|
|
139
|
+
'Refetching archetypes after textual content generation',
|
|
140
|
+
{ combinationString, gender, language }
|
|
141
|
+
);
|
|
142
|
+
const updatedArchetypes = await this.fetchArchetypesFromDB(
|
|
43
143
|
combinationString,
|
|
44
|
-
gender
|
|
144
|
+
gender,
|
|
145
|
+
language
|
|
45
146
|
);
|
|
147
|
+
await this.log('info', 'Refetched archetypes', {
|
|
148
|
+
updatedArchetypesCount: updatedArchetypes.length,
|
|
149
|
+
archetypeIds: updatedArchetypes.map((a) => a.id),
|
|
150
|
+
});
|
|
46
151
|
|
|
47
|
-
|
|
48
|
-
console.log('Generating missing Leonardo prompts...');
|
|
49
|
-
await this.leonardoService.processArchetypesPrompts(combinationString);
|
|
50
|
-
}
|
|
51
|
-
|
|
152
|
+
// Step 2: Queue image generation if needed
|
|
52
153
|
const archetypesNeedingImages = updatedArchetypes.filter(
|
|
53
|
-
(arc) => arc.images.length < 3
|
|
154
|
+
(arc) => JSON.parse(arc.images).length < 3
|
|
54
155
|
);
|
|
55
156
|
|
|
56
157
|
if (archetypesNeedingImages.length > 0) {
|
|
57
|
-
|
|
58
|
-
|
|
158
|
+
await this.log(
|
|
159
|
+
'info',
|
|
160
|
+
'Queuing image generation for missing archetypes',
|
|
161
|
+
{
|
|
162
|
+
archetypesNeedingImagesCount: archetypesNeedingImages.length,
|
|
163
|
+
archetypeIds: archetypesNeedingImages.map((a) => a.id),
|
|
164
|
+
}
|
|
165
|
+
);
|
|
59
166
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
167
|
+
// Queue image generation for all archetypes needing images
|
|
168
|
+
const batch = archetypesNeedingImages.map((arc) => ({
|
|
169
|
+
body: {
|
|
170
|
+
archetypeDataId: arc.id,
|
|
171
|
+
combination: combinationString,
|
|
172
|
+
gender,
|
|
173
|
+
language,
|
|
174
|
+
archetypeIndex: arc.archetypeIndex,
|
|
175
|
+
},
|
|
176
|
+
}));
|
|
177
|
+
await this.log('debug', 'Sending batch to ARCHETYPE_POPULATION_QUEUE', {
|
|
178
|
+
batchCount: batch.length,
|
|
179
|
+
batch,
|
|
180
|
+
});
|
|
181
|
+
await this.context.env.ARCHETYPE_POPULATION_QUEUE.sendBatch(batch);
|
|
182
|
+
await this.log('info', 'Successfully queued image generation', {
|
|
183
|
+
batchCount: batch.length,
|
|
184
|
+
});
|
|
70
185
|
|
|
71
186
|
return { message: 'Images are being processed, please try again later.' };
|
|
72
187
|
}
|
|
73
188
|
|
|
74
|
-
await this.
|
|
75
|
-
|
|
76
|
-
|
|
189
|
+
await this.log('info', 'Archetypes fully processed and ready', {
|
|
190
|
+
updatedArchetypes,
|
|
191
|
+
});
|
|
77
192
|
return {
|
|
78
193
|
archetypes: updatedArchetypes.map(
|
|
79
|
-
({ name,
|
|
194
|
+
({ name, essenceLine, description, virtues, images }) => ({
|
|
80
195
|
name,
|
|
81
|
-
|
|
196
|
+
essenceLine,
|
|
82
197
|
description,
|
|
83
|
-
virtues,
|
|
84
|
-
images,
|
|
198
|
+
virtues: JSON.parse(virtues),
|
|
199
|
+
images: JSON.parse(images),
|
|
85
200
|
})
|
|
86
201
|
),
|
|
87
202
|
};
|
|
88
203
|
}
|
|
89
204
|
|
|
90
|
-
async
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
205
|
+
private async fetchArchetypesFromDB(
|
|
206
|
+
combinationString: string,
|
|
207
|
+
gender: Gender,
|
|
208
|
+
language: string
|
|
209
|
+
) {
|
|
210
|
+
await this.log('debug', 'Executing fetchArchetypesFromDB', {
|
|
211
|
+
combinationString,
|
|
212
|
+
gender,
|
|
213
|
+
language,
|
|
214
|
+
});
|
|
215
|
+
const db = this.context.drizzle();
|
|
216
|
+
const result = await db
|
|
217
|
+
.select()
|
|
218
|
+
.from(schema.archetypesData)
|
|
219
|
+
.where(
|
|
220
|
+
and(
|
|
221
|
+
eq(schema.archetypesData.combination, combinationString),
|
|
222
|
+
eq(schema.archetypesData.gender, gender),
|
|
223
|
+
eq(schema.archetypesData.language, language)
|
|
224
|
+
)
|
|
225
|
+
)
|
|
226
|
+
.execute();
|
|
227
|
+
await this.log('debug', 'fetchArchetypesFromDB result', {
|
|
228
|
+
resultCount: result.length,
|
|
229
|
+
result,
|
|
230
|
+
});
|
|
231
|
+
return result;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
private async generateTextualContent(
|
|
235
|
+
combinationString: string,
|
|
236
|
+
gender: Gender,
|
|
237
|
+
language: string
|
|
238
|
+
) {
|
|
239
|
+
await this.log('info', 'Starting generateTextualContent', {
|
|
240
|
+
combinationString,
|
|
241
|
+
gender,
|
|
242
|
+
language,
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
const db = this.context.drizzle();
|
|
246
|
+
|
|
247
|
+
// Fetch English archetypes to get names and essence lines
|
|
248
|
+
await this.log(
|
|
249
|
+
'debug',
|
|
250
|
+
'Fetching English archetypes for names and essence lines',
|
|
251
|
+
{ combinationString, gender }
|
|
252
|
+
);
|
|
253
|
+
const archetypes = await db
|
|
254
|
+
.select()
|
|
255
|
+
.from(schema.archetypesData)
|
|
256
|
+
.where(
|
|
257
|
+
and(
|
|
258
|
+
eq(schema.archetypesData.combination, combinationString),
|
|
259
|
+
eq(schema.archetypesData.gender, gender),
|
|
260
|
+
eq(schema.archetypesData.language, 'en-us')
|
|
261
|
+
)
|
|
262
|
+
)
|
|
263
|
+
.execute();
|
|
264
|
+
await this.log('info', 'Fetched English archetypes', {
|
|
265
|
+
archetypesCount: archetypes.length,
|
|
266
|
+
names: archetypes.map((a) => a.name),
|
|
267
|
+
essenceLines: archetypes.map((a) => a.essenceLine),
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// Step 1: Generate description and virtues
|
|
271
|
+
await this.log('debug', 'Generating description and virtues', {
|
|
272
|
+
combinationString,
|
|
273
|
+
});
|
|
274
|
+
const descVirtueMessages = this.context
|
|
275
|
+
.buildLLMMessages()
|
|
276
|
+
.generateCosmicMirrorDescriptionAndVirtues({
|
|
277
|
+
combination: combinationString,
|
|
278
|
+
names: [archetypes[0].name, archetypes[1].name, archetypes[2].name],
|
|
279
|
+
essenceLines: [
|
|
280
|
+
archetypes[0].essenceLine,
|
|
281
|
+
archetypes[1].essenceLine,
|
|
282
|
+
archetypes[2].essenceLine,
|
|
283
|
+
],
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
await this.log('debug', 'Calling API for description and virtues', {
|
|
287
|
+
messages: descVirtueMessages,
|
|
288
|
+
});
|
|
289
|
+
const descVirtueResponse = await this.context
|
|
290
|
+
.api()
|
|
291
|
+
.callTogether.single(descVirtueMessages, {});
|
|
292
|
+
await this.log('info', 'Received description and virtues response', {
|
|
293
|
+
responseLength: descVirtueResponse.length,
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
await this.log('debug', 'Parsing description and virtues response');
|
|
297
|
+
const parsedDescVirtues =
|
|
298
|
+
this.parseDescriptionAndVirtuesResponse(descVirtueResponse);
|
|
299
|
+
await this.log('info', 'Parsed description and virtues', {
|
|
300
|
+
parsedDescVirtues,
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
// Step 2: Generate content for each archetype
|
|
304
|
+
const contentResults = [];
|
|
305
|
+
for (let i = 0; i < 3; i++) {
|
|
306
|
+
await this.log('debug', `Generating content for archetype ${i + 1}`, {
|
|
307
|
+
name: archetypes[i].name,
|
|
308
|
+
});
|
|
309
|
+
const contentMessages = this.context
|
|
310
|
+
.buildLLMMessages()
|
|
311
|
+
.generateCosmicMirrorArchetypeContent({
|
|
312
|
+
combination: combinationString,
|
|
313
|
+
name: archetypes[i].name,
|
|
314
|
+
description: parsedDescVirtues[i].descriptionEN,
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
await this.log('debug', `Calling API for content of archetype ${i + 1}`, {
|
|
318
|
+
messages: contentMessages,
|
|
319
|
+
});
|
|
320
|
+
const contentResponse = await this.context
|
|
321
|
+
.api()
|
|
322
|
+
.callTogether.single(contentMessages, {});
|
|
323
|
+
await this.log(
|
|
324
|
+
'info',
|
|
325
|
+
`Received content response for archetype ${i + 1}`,
|
|
326
|
+
{ responseLength: contentResponse.length }
|
|
103
327
|
);
|
|
104
|
-
} else {
|
|
105
|
-
const entries = combinations.map((combination) => ({
|
|
106
|
-
combination,
|
|
107
|
-
}));
|
|
108
328
|
|
|
109
|
-
await this.
|
|
110
|
-
|
|
111
|
-
|
|
329
|
+
await this.log(
|
|
330
|
+
'debug',
|
|
331
|
+
`Parsing content response for archetype ${i + 1}`
|
|
112
332
|
);
|
|
333
|
+
const parsedContent = this.parseContentResponse(contentResponse);
|
|
334
|
+
contentResults.push(parsedContent);
|
|
335
|
+
await this.log('info', `Parsed content for archetype ${i + 1}`, {
|
|
336
|
+
parsedContent,
|
|
337
|
+
});
|
|
113
338
|
}
|
|
114
|
-
}
|
|
115
339
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
340
|
+
// Step 3: Generate Leonardo prompts for all archetypes
|
|
341
|
+
await this.log('debug', 'Generating Leonardo prompts for all archetypes');
|
|
342
|
+
const promptMessages = this.context
|
|
343
|
+
.buildLLMMessages()
|
|
344
|
+
.generateCosmicMirrorArchetypeLeonardoPrompts(
|
|
345
|
+
archetypes.map((arc, idx) => ({
|
|
346
|
+
name: arc.name,
|
|
347
|
+
description: parsedDescVirtues[idx].descriptionEN,
|
|
348
|
+
}))
|
|
349
|
+
);
|
|
350
|
+
|
|
351
|
+
await this.log('debug', 'Calling API for Leonardo prompts', {
|
|
352
|
+
messages: promptMessages,
|
|
353
|
+
});
|
|
354
|
+
const promptResponse = await this.context
|
|
355
|
+
.api()
|
|
356
|
+
.callTogether.single(promptMessages, {});
|
|
357
|
+
await this.log('info', 'Received Leonardo prompts response', {
|
|
358
|
+
responseLength: promptResponse.length,
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
await this.log('debug', 'Parsing Leonardo prompts response');
|
|
362
|
+
const parsedPrompts = this.parseLeonardoPromptResponse(promptResponse);
|
|
363
|
+
await this.log('info', 'Parsed Leonardo prompts', { parsedPrompts });
|
|
364
|
+
|
|
365
|
+
// Update archetypes_data with the generated content
|
|
366
|
+
for (let i = 0; i < 3; i++) {
|
|
367
|
+
const archetype = archetypes[i];
|
|
368
|
+
const index = (i + 1).toString();
|
|
369
|
+
|
|
370
|
+
for (const lang of ['en-us', 'pt-br']) {
|
|
371
|
+
const descriptionField =
|
|
372
|
+
lang === 'en-us'
|
|
373
|
+
? parsedDescVirtues[i].descriptionEN
|
|
374
|
+
: gender === 'male'
|
|
375
|
+
? parsedDescVirtues[i].descriptionPTM
|
|
376
|
+
: parsedDescVirtues[i].descriptionPTF;
|
|
377
|
+
|
|
378
|
+
const contentLangIndex =
|
|
379
|
+
lang === 'en-us' ? 0 : gender === 'male' ? 1 : 2;
|
|
380
|
+
const content = [
|
|
381
|
+
{
|
|
382
|
+
section: 'voiceOfTheSoul',
|
|
383
|
+
text: contentResults[i][contentLangIndex].voiceOfTheSoul,
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
section: 'giftsYouBear',
|
|
387
|
+
text: contentResults[i][contentLangIndex].giftsYouBear,
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
section: 'shadowsYouFace',
|
|
391
|
+
text: contentResults[i][contentLangIndex].shadowsYouFace,
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
section: 'rhythmOfYourDays',
|
|
395
|
+
text: contentResults[i][contentLangIndex].rhythmOfYourDays,
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
section: 'tiesThatBind',
|
|
399
|
+
text: contentResults[i][contentLangIndex].tiesThatBind,
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
section: 'lightWithin',
|
|
403
|
+
text: contentResults[i][contentLangIndex].lightWithin,
|
|
404
|
+
},
|
|
405
|
+
];
|
|
406
|
+
|
|
407
|
+
const leonardoPrompt =
|
|
408
|
+
gender === 'male'
|
|
409
|
+
? parsedPrompts[i].malePrompt
|
|
410
|
+
: parsedPrompts[i].femalePrompt;
|
|
411
|
+
|
|
412
|
+
await this.log(
|
|
413
|
+
'debug',
|
|
414
|
+
`Updating archetypes_data for archetype ${index}, language: ${lang}`,
|
|
415
|
+
{
|
|
416
|
+
descriptionField,
|
|
417
|
+
content,
|
|
418
|
+
leonardoPrompt,
|
|
419
|
+
}
|
|
130
420
|
);
|
|
131
|
-
console.log(`Fetching archetype from KV: ${kvKey}`);
|
|
132
421
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
422
|
+
await db
|
|
423
|
+
.update(schema.archetypesData)
|
|
424
|
+
.set({
|
|
425
|
+
description: descriptionField,
|
|
426
|
+
virtues: JSON.stringify(parsedDescVirtues[i].virtues),
|
|
427
|
+
content: JSON.stringify(content),
|
|
428
|
+
leonardoPrompt,
|
|
429
|
+
updatedAt: new Date().getTime(),
|
|
430
|
+
})
|
|
431
|
+
.where(
|
|
432
|
+
and(
|
|
433
|
+
eq(schema.archetypesData.combination, combinationString),
|
|
434
|
+
eq(schema.archetypesData.gender, gender),
|
|
435
|
+
eq(schema.archetypesData.language, lang),
|
|
436
|
+
eq(schema.archetypesData.archetypeIndex, index)
|
|
437
|
+
)
|
|
438
|
+
)
|
|
439
|
+
.execute();
|
|
440
|
+
|
|
441
|
+
await this.log(
|
|
442
|
+
'info',
|
|
443
|
+
`Updated archetypes_data for archetype ${index}, language: ${lang}`
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
await this.log('info', 'Completed generateTextualContent', {
|
|
449
|
+
combinationString,
|
|
450
|
+
gender,
|
|
451
|
+
language,
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
private parseDescriptionAndVirtuesResponse(response: string) {
|
|
456
|
+
this.log('debug', 'Starting parseDescriptionAndVirtuesResponse', {
|
|
457
|
+
responseLength: response.length,
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
const entries = response
|
|
461
|
+
.split(/---/)
|
|
462
|
+
.map((block) => block.trim())
|
|
463
|
+
.filter((block) => block.length > 0);
|
|
464
|
+
|
|
465
|
+
this.log('debug', 'Split response into entries', {
|
|
466
|
+
entriesCount: entries.length,
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
const result = entries.map((entry, entryIndex) => {
|
|
470
|
+
this.log('debug', `Processing entry ${entryIndex + 1}`, { entry });
|
|
471
|
+
|
|
472
|
+
const lines = entry.split('\n').filter((line) => line.trim());
|
|
473
|
+
this.log('debug', `Split entry ${entryIndex + 1} into lines`, {
|
|
474
|
+
linesCount: lines.length,
|
|
475
|
+
lines,
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
let descriptionEN = '';
|
|
479
|
+
let descriptionPTM = '';
|
|
480
|
+
let descriptionPTF = '';
|
|
481
|
+
let virtues: string[] = [];
|
|
482
|
+
let currentField = '';
|
|
483
|
+
|
|
484
|
+
for (const line of lines) {
|
|
485
|
+
if (line.startsWith('• Description EN:')) {
|
|
486
|
+
currentField = 'descriptionEN';
|
|
487
|
+
descriptionEN = line.split('• Description EN:')[1]?.trim() || '';
|
|
488
|
+
this.log(
|
|
489
|
+
'debug',
|
|
490
|
+
`Extracted descriptionEN for entry ${entryIndex + 1}`,
|
|
491
|
+
{ descriptionEN }
|
|
138
492
|
);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
493
|
+
} else if (line.startsWith('• Description PT-M:')) {
|
|
494
|
+
currentField = 'descriptionPTM';
|
|
495
|
+
descriptionPTM = line.split('• Description PT-M:')[1]?.trim() || '';
|
|
496
|
+
this.log(
|
|
497
|
+
'debug',
|
|
498
|
+
`Extracted descriptionPTM for entry ${entryIndex + 1}`,
|
|
499
|
+
{ descriptionPTM }
|
|
143
500
|
);
|
|
144
|
-
|
|
501
|
+
} else if (line.startsWith('• Description PT-F:')) {
|
|
502
|
+
currentField = 'descriptionPTF';
|
|
503
|
+
descriptionPTF = line.split('• Description PT-F:')[1]?.trim() || '';
|
|
504
|
+
this.log(
|
|
505
|
+
'debug',
|
|
506
|
+
`Extracted descriptionPTF for entry ${entryIndex + 1}`,
|
|
507
|
+
{ descriptionPTF }
|
|
508
|
+
);
|
|
509
|
+
} else if (line.startsWith('• Virtues:')) {
|
|
510
|
+
currentField = 'virtues';
|
|
511
|
+
virtues =
|
|
512
|
+
line
|
|
513
|
+
.split('• Virtues:')[1]
|
|
514
|
+
?.split(',')
|
|
515
|
+
.map((v) => v.trim())
|
|
516
|
+
.filter((v) => v) || [];
|
|
517
|
+
this.log('debug', `Extracted virtues for entry ${entryIndex + 1}`, {
|
|
518
|
+
virtues,
|
|
519
|
+
});
|
|
520
|
+
} else if (currentField && currentField !== 'virtues') {
|
|
521
|
+
if (currentField === 'descriptionEN') {
|
|
522
|
+
descriptionEN += ' ' + line.trim();
|
|
523
|
+
this.log(
|
|
524
|
+
'debug',
|
|
525
|
+
`Appended to descriptionEN for entry ${entryIndex + 1}`,
|
|
526
|
+
{ descriptionEN }
|
|
527
|
+
);
|
|
528
|
+
}
|
|
529
|
+
if (currentField === 'descriptionPTM') {
|
|
530
|
+
descriptionPTM += ' ' + line.trim();
|
|
531
|
+
this.log(
|
|
532
|
+
'debug',
|
|
533
|
+
`Appended to descriptionPTM for entry ${entryIndex + 1}`,
|
|
534
|
+
{ descriptionPTM }
|
|
535
|
+
);
|
|
536
|
+
}
|
|
537
|
+
if (currentField === 'descriptionPTF') {
|
|
538
|
+
descriptionPTF += ' ' + line.trim();
|
|
539
|
+
this.log(
|
|
540
|
+
'debug',
|
|
541
|
+
`Appended to descriptionPTF for entry ${entryIndex + 1}`,
|
|
542
|
+
{ descriptionPTF }
|
|
543
|
+
);
|
|
544
|
+
}
|
|
145
545
|
}
|
|
146
|
-
}
|
|
147
|
-
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
if (
|
|
549
|
+
!descriptionEN ||
|
|
550
|
+
!descriptionPTM ||
|
|
551
|
+
!descriptionPTF ||
|
|
552
|
+
virtues.length !== 3
|
|
553
|
+
) {
|
|
554
|
+
this.log(
|
|
555
|
+
'warn',
|
|
556
|
+
`Malformed description and virtues response for entry ${
|
|
557
|
+
entryIndex + 1
|
|
558
|
+
}`,
|
|
559
|
+
{
|
|
560
|
+
descriptionEN,
|
|
561
|
+
descriptionPTM,
|
|
562
|
+
descriptionPTF,
|
|
563
|
+
virtues,
|
|
564
|
+
response: entry,
|
|
565
|
+
}
|
|
566
|
+
);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
return { descriptionEN, descriptionPTM, descriptionPTF, virtues };
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
this.log('info', 'Completed parseDescriptionAndVirtuesResponse', {
|
|
573
|
+
result,
|
|
574
|
+
});
|
|
575
|
+
return result;
|
|
148
576
|
}
|
|
149
577
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
578
|
+
private parseContentResponse(response: string) {
|
|
579
|
+
this.log('debug', 'Starting parseContentResponse', {
|
|
580
|
+
responseLength: response.length,
|
|
581
|
+
});
|
|
582
|
+
|
|
583
|
+
const sections = response
|
|
584
|
+
.split(/---/)
|
|
585
|
+
.map((block) => block.trim())
|
|
586
|
+
.filter((block) => block.length > 0);
|
|
587
|
+
this.log('debug', 'Split response into sections', {
|
|
588
|
+
sectionsCount: sections.length,
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
const result = sections.map((section, sectionIndex) => {
|
|
592
|
+
this.log('debug', `Processing section ${sectionIndex + 1}`, { section });
|
|
593
|
+
|
|
594
|
+
const lines = section.split('\n').filter((line) => line.trim());
|
|
595
|
+
this.log('debug', `Split section ${sectionIndex + 1} into lines`, {
|
|
596
|
+
linesCount: lines.length,
|
|
597
|
+
lines,
|
|
598
|
+
});
|
|
599
|
+
|
|
600
|
+
const content: Record<string, string> = {};
|
|
601
|
+
let currentSection = '';
|
|
602
|
+
let currentText: string[] = [];
|
|
603
|
+
|
|
604
|
+
for (const line of lines) {
|
|
605
|
+
if (
|
|
606
|
+
line.startsWith('EN:') ||
|
|
607
|
+
line.startsWith('PT-M:') ||
|
|
608
|
+
line.startsWith('PT-F:')
|
|
609
|
+
) {
|
|
610
|
+
this.log(
|
|
611
|
+
'debug',
|
|
612
|
+
`Skipping language header in section ${sectionIndex + 1}`,
|
|
613
|
+
{ line }
|
|
614
|
+
);
|
|
615
|
+
continue;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
if (line.startsWith('#')) {
|
|
619
|
+
if (currentSection && currentText.length > 0) {
|
|
620
|
+
const key = currentSection
|
|
621
|
+
.toLowerCase()
|
|
622
|
+
.replace(/\s+/g, '')
|
|
623
|
+
.replace(/([A-Z])/g, (match) => match.toLowerCase());
|
|
624
|
+
content[key] = currentText.join(' ').trim();
|
|
625
|
+
this.log(
|
|
626
|
+
'debug',
|
|
627
|
+
`Extracted section ${currentSection} in section ${
|
|
628
|
+
sectionIndex + 1
|
|
629
|
+
}`,
|
|
630
|
+
{ key, text: content[key] }
|
|
631
|
+
);
|
|
632
|
+
}
|
|
633
|
+
currentSection = line.replace('# ', '');
|
|
634
|
+
currentText = [];
|
|
635
|
+
this.log(
|
|
636
|
+
'debug',
|
|
637
|
+
`Starting new section ${currentSection} in section ${
|
|
638
|
+
sectionIndex + 1
|
|
639
|
+
}`
|
|
640
|
+
);
|
|
641
|
+
} else {
|
|
642
|
+
currentText.push(line);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
if (currentSection && currentText.length > 0) {
|
|
647
|
+
const key = currentSection
|
|
648
|
+
.toLowerCase()
|
|
649
|
+
.replace(/\s+/g, '')
|
|
650
|
+
.replace(/([A-Z])/g, (match) => match.toLowerCase());
|
|
651
|
+
content[key] = currentText.join(' ').trim();
|
|
652
|
+
this.log(
|
|
653
|
+
'debug',
|
|
654
|
+
`Extracted final section ${currentSection} in section ${
|
|
655
|
+
sectionIndex + 1
|
|
656
|
+
}`,
|
|
657
|
+
{ key, text: content[key] }
|
|
165
658
|
);
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
const parsedContent = {
|
|
662
|
+
voiceOfTheSoul:
|
|
663
|
+
content['thevoiceofthesoul'] || content['avozdaalma'] || '',
|
|
664
|
+
giftsYouBear:
|
|
665
|
+
content['thegiftsyoubear'] || content['osdonsquevocêcarrega'] || '',
|
|
666
|
+
shadowsYouFace:
|
|
667
|
+
content['theshadowsyouface'] || content['assombrasqueenfrenta'] || '',
|
|
668
|
+
rhythmOfYourDays:
|
|
669
|
+
content['therhythmofyourdays'] || content['oritmodosseusdias'] || '',
|
|
670
|
+
tiesThatBind:
|
|
671
|
+
content['thetiesthatbind'] || content['oslaçosqueteconectam'] || '',
|
|
672
|
+
lightWithin: content['thelightwithin'] || content['aluzinterior'] || '',
|
|
673
|
+
};
|
|
674
|
+
|
|
675
|
+
if (Object.values(parsedContent).some((value) => !value)) {
|
|
676
|
+
this.log(
|
|
677
|
+
'warn',
|
|
678
|
+
`Malformed content response for section ${sectionIndex + 1}`,
|
|
679
|
+
{
|
|
680
|
+
parsedContent,
|
|
681
|
+
response: section,
|
|
682
|
+
}
|
|
683
|
+
);
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
return parsedContent;
|
|
687
|
+
});
|
|
688
|
+
|
|
689
|
+
this.log('info', 'Completed parseContentResponse', { result });
|
|
690
|
+
return result;
|
|
172
691
|
}
|
|
173
692
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
693
|
+
private parseLeonardoPromptResponse(response: string) {
|
|
694
|
+
this.log('debug', 'Starting parseLeonardoPromptResponse', {
|
|
695
|
+
responseLength: response.length,
|
|
696
|
+
});
|
|
697
|
+
|
|
698
|
+
const lines = response.split('\n').filter((line) => line.trim());
|
|
699
|
+
this.log('debug', 'Split response into lines', {
|
|
700
|
+
linesCount: lines.length,
|
|
701
|
+
lines,
|
|
702
|
+
});
|
|
703
|
+
|
|
704
|
+
const prompts: Array<{ malePrompt: string; femalePrompt: string }> = [];
|
|
705
|
+
|
|
706
|
+
for (let i = 0; i < lines.length; i += 2) {
|
|
707
|
+
const maleLine = lines[i];
|
|
708
|
+
const femaleLine = lines[i + 1];
|
|
709
|
+
|
|
710
|
+
const malePrompt = maleLine.startsWith(`${Math.floor(i / 2) + 1}.m`)
|
|
711
|
+
? maleLine.split(`${Math.floor(i / 2) + 1}.m`)[1]?.trim()
|
|
712
|
+
: '';
|
|
713
|
+
const femalePrompt = femaleLine.startsWith(`${Math.floor(i / 2) + 1}.f`)
|
|
714
|
+
? femaleLine.split(`${Math.floor(i / 2) + 1}.f`)[1]?.trim()
|
|
715
|
+
: '';
|
|
716
|
+
|
|
717
|
+
prompts.push({ malePrompt, femalePrompt });
|
|
718
|
+
this.log(
|
|
719
|
+
'debug',
|
|
720
|
+
`Parsed prompts for archetype ${Math.floor(i / 2) + 1}`,
|
|
721
|
+
{ malePrompt, femalePrompt }
|
|
722
|
+
);
|
|
723
|
+
|
|
724
|
+
if (!malePrompt || !femalePrompt) {
|
|
725
|
+
this.log(
|
|
726
|
+
'warn',
|
|
727
|
+
`Malformed Leonardo prompt for archetype ${Math.floor(i / 2) + 1}`,
|
|
728
|
+
{
|
|
729
|
+
malePrompt,
|
|
730
|
+
femalePrompt,
|
|
731
|
+
maleLine,
|
|
732
|
+
femaleLine,
|
|
733
|
+
}
|
|
734
|
+
);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
this.log('info', 'Completed parseLeonardoPromptResponse', { prompts });
|
|
739
|
+
return prompts;
|
|
188
740
|
}
|
|
189
741
|
}
|