@zodic/shared 0.0.295 → 0.0.297
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 +180 -142
- package/app/workflow/ArchetypeWorkflow.ts +4 -5
- package/db/migrations/0013_lean_frightful_four.sql +7 -0
- package/db/migrations/meta/0013_snapshot.json +2649 -0
- package/db/migrations/meta/_journal.json +7 -0
- package/db/schema.ts +16 -2
- package/package.json +1 -1
- package/utils/isEnglishNameDuplicate.ts +22 -0
|
@@ -287,18 +287,13 @@ export class ArchetypeService {
|
|
|
287
287
|
|
|
288
288
|
async generateArchetypeNames(
|
|
289
289
|
combination: string,
|
|
290
|
-
gender: 'male' | 'female' | 'non-binary',
|
|
291
290
|
overrideExisting: boolean = false
|
|
292
291
|
) {
|
|
292
|
+
const db = this.context.drizzle();
|
|
293
293
|
const [sun, ascendant, moon] = combination.split('-') as ZodiacSignSlug[];
|
|
294
294
|
|
|
295
295
|
const prompt = generateArchetypePrompt([{ sun, ascendant, moon }]);
|
|
296
|
-
const messages: ChatMessages = [
|
|
297
|
-
{
|
|
298
|
-
role: 'user',
|
|
299
|
-
content: prompt,
|
|
300
|
-
},
|
|
301
|
-
];
|
|
296
|
+
const messages: ChatMessages = [{ role: 'user', content: prompt }];
|
|
302
297
|
const response = await this.context.api().callTogether.single(messages, {});
|
|
303
298
|
|
|
304
299
|
if (!response) {
|
|
@@ -307,17 +302,33 @@ export class ArchetypeService {
|
|
|
307
302
|
);
|
|
308
303
|
}
|
|
309
304
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
305
|
+
let blocks: string[] = [];
|
|
306
|
+
let ptBlocks: string[] = [];
|
|
307
|
+
|
|
308
|
+
try {
|
|
309
|
+
blocks = response
|
|
310
|
+
.split('-EN')[1]
|
|
311
|
+
.split('-PT')[0]
|
|
312
|
+
.trim()
|
|
313
|
+
.split(/\n\d\.\s*\n?/)
|
|
314
|
+
.filter(Boolean);
|
|
315
|
+
|
|
316
|
+
ptBlocks = response
|
|
317
|
+
.split('-PT')[1]
|
|
318
|
+
.trim()
|
|
319
|
+
.split(/\n\d\.\s*\n?/)
|
|
320
|
+
.filter(Boolean);
|
|
321
|
+
} catch (err) {
|
|
322
|
+
console.error(`Parsing failed for combination: ${combination}`, err);
|
|
323
|
+
await db.insert(schema.archetypeNameDumps).values({
|
|
324
|
+
id: combination,
|
|
325
|
+
combination,
|
|
326
|
+
rawText: response,
|
|
327
|
+
parsedSuccessfully: 0,
|
|
328
|
+
createdAt: Date.now(),
|
|
329
|
+
});
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
321
332
|
|
|
322
333
|
const englishNames = blocks.map((block) => {
|
|
323
334
|
const nameMatch = block.match(/• Name:\s*(.+)/);
|
|
@@ -335,81 +346,102 @@ export class ArchetypeService {
|
|
|
335
346
|
return { masc, fem, essenceLine: essence };
|
|
336
347
|
});
|
|
337
348
|
|
|
338
|
-
|
|
349
|
+
// Duplicate helper
|
|
350
|
+
async function isEnglishNameDuplicate(name: string): Promise<boolean> {
|
|
351
|
+
const result = await db
|
|
352
|
+
.select({ name: schema.archetypesData.name })
|
|
353
|
+
.from(schema.archetypesData)
|
|
354
|
+
.where(
|
|
355
|
+
and(
|
|
356
|
+
eq(schema.archetypesData.language, 'en-us'),
|
|
357
|
+
eq(schema.archetypesData.name, name)
|
|
358
|
+
)
|
|
359
|
+
)
|
|
360
|
+
.limit(1)
|
|
361
|
+
.execute();
|
|
362
|
+
|
|
363
|
+
return result.length > 0;
|
|
364
|
+
}
|
|
339
365
|
|
|
340
366
|
await Promise.all(
|
|
341
367
|
englishNames.map(async (entry, i) => {
|
|
342
368
|
const index = (i + 1).toString();
|
|
343
|
-
const
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
.
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
369
|
+
const ptVariant = portugueseVariants[i];
|
|
370
|
+
|
|
371
|
+
if (await isEnglishNameDuplicate(entry.name)) {
|
|
372
|
+
console.warn(`Duplicate name detected: "${entry.name}" — skipping.`);
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
for (const gender of ['male', 'female']) {
|
|
377
|
+
const enId = `${combination}:${gender}:${index}`;
|
|
378
|
+
const ptId = `${combination}:${gender}:${index}:pt`;
|
|
379
|
+
const ptName = gender === 'female' ? ptVariant.fem : ptVariant.masc;
|
|
380
|
+
|
|
381
|
+
const existingEn = await db
|
|
382
|
+
.select({ id: schema.archetypesData.id })
|
|
383
|
+
.from(schema.archetypesData)
|
|
384
|
+
.where(eq(schema.archetypesData.id, enId))
|
|
385
|
+
.execute();
|
|
386
|
+
|
|
387
|
+
if (overrideExisting || existingEn.length === 0) {
|
|
388
|
+
await db
|
|
389
|
+
.insert(schema.archetypesData)
|
|
390
|
+
.values({
|
|
391
|
+
id: enId,
|
|
392
|
+
combination,
|
|
393
|
+
gender,
|
|
394
|
+
archetypeIndex: index,
|
|
395
|
+
language: 'en-us',
|
|
367
396
|
name: entry.name,
|
|
368
397
|
essenceLine: entry.essenceLine,
|
|
369
|
-
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
|
|
398
|
+
status: 'idle',
|
|
399
|
+
})
|
|
400
|
+
.onConflictDoUpdate({
|
|
401
|
+
target: [schema.archetypesData.id],
|
|
402
|
+
set: {
|
|
403
|
+
name: entry.name,
|
|
404
|
+
essenceLine: entry.essenceLine,
|
|
405
|
+
updatedAt: new Date().getTime(),
|
|
406
|
+
},
|
|
407
|
+
});
|
|
408
|
+
}
|
|
373
409
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
.
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
});
|
|
410
|
+
const existingPt = await db
|
|
411
|
+
.select({ id: schema.archetypesData.id })
|
|
412
|
+
.from(schema.archetypesData)
|
|
413
|
+
.where(eq(schema.archetypesData.id, ptId))
|
|
414
|
+
.execute();
|
|
415
|
+
|
|
416
|
+
if (overrideExisting || existingPt.length === 0) {
|
|
417
|
+
await db
|
|
418
|
+
.insert(schema.archetypesData)
|
|
419
|
+
.values({
|
|
420
|
+
id: ptId,
|
|
421
|
+
combination,
|
|
422
|
+
gender,
|
|
423
|
+
archetypeIndex: index,
|
|
424
|
+
language: 'pt-br',
|
|
425
|
+
name: ptName,
|
|
426
|
+
essenceLine: ptVariant.essenceLine,
|
|
427
|
+
status: 'idle',
|
|
428
|
+
})
|
|
429
|
+
.onConflictDoUpdate({
|
|
430
|
+
target: [schema.archetypesData.id],
|
|
431
|
+
set: {
|
|
432
|
+
name: ptName,
|
|
433
|
+
essenceLine: ptVariant.essenceLine,
|
|
434
|
+
updatedAt: new Date().getTime(),
|
|
435
|
+
},
|
|
436
|
+
});
|
|
437
|
+
}
|
|
403
438
|
}
|
|
404
439
|
})
|
|
405
440
|
);
|
|
406
441
|
}
|
|
407
442
|
|
|
408
443
|
async generateArchetypeNamesBatch(
|
|
409
|
-
entries: Array<{
|
|
410
|
-
combination: string;
|
|
411
|
-
gender: 'male' | 'female' | 'non-binary';
|
|
412
|
-
}>,
|
|
444
|
+
entries: Array<{ combination: string }>,
|
|
413
445
|
overrideExisting: boolean = false
|
|
414
446
|
) {
|
|
415
447
|
const prompts = entries.map(({ combination }) => {
|
|
@@ -421,8 +453,9 @@ export class ArchetypeService {
|
|
|
421
453
|
const messages: ChatMessages = [{ role: 'user', content: prompt }];
|
|
422
454
|
const response = await this.context.api().callTogether.single(messages, {});
|
|
423
455
|
|
|
424
|
-
if (!response)
|
|
456
|
+
if (!response) {
|
|
425
457
|
throw new Error('No response when generating batch archetype names');
|
|
458
|
+
}
|
|
426
459
|
|
|
427
460
|
const db = this.context.drizzle();
|
|
428
461
|
|
|
@@ -432,7 +465,7 @@ export class ArchetypeService {
|
|
|
432
465
|
.map((b) => b.trim());
|
|
433
466
|
|
|
434
467
|
for (let i = 0; i < entries.length; i++) {
|
|
435
|
-
const { combination
|
|
468
|
+
const { combination } = entries[i];
|
|
436
469
|
const block = blocks[i];
|
|
437
470
|
const en = block.split('-EN')[1].split('-PT')[0].trim();
|
|
438
471
|
const pt = block.split('-PT')[1].trim();
|
|
@@ -450,72 +483,77 @@ export class ArchetypeService {
|
|
|
450
483
|
.filter(Boolean)
|
|
451
484
|
.map((line) => ({
|
|
452
485
|
masc: line.match(/• Masculino:\s*(.+)/)?.[1]?.trim() || '',
|
|
486
|
+
fem: line.match(/• Feminino:\s*(.+)/)?.[1]?.trim() || '',
|
|
453
487
|
essenceLine: line.match(/• Essência:\s*(.+)/)?.[1]?.trim() || '',
|
|
454
488
|
}));
|
|
455
489
|
|
|
456
490
|
for (let j = 0; j < 3; j++) {
|
|
457
491
|
const index = (j + 1).toString();
|
|
492
|
+
const englishEntry = english[j];
|
|
493
|
+
const ptEntry = portuguese[j];
|
|
494
|
+
|
|
495
|
+
for (const gender of ['male', 'female']) {
|
|
496
|
+
const enId = `${combination}:${gender}:${index}`;
|
|
497
|
+
const ptId = `${combination}:${gender}:${index}:pt`;
|
|
498
|
+
const ptName = gender === 'female' ? ptEntry.fem : ptEntry.masc;
|
|
499
|
+
|
|
500
|
+
const existingEn = await db
|
|
501
|
+
.select({ id: schema.archetypesData.id })
|
|
502
|
+
.from(schema.archetypesData)
|
|
503
|
+
.where(eq(schema.archetypesData.id, enId))
|
|
504
|
+
.execute();
|
|
505
|
+
|
|
506
|
+
if (overrideExisting || existingEn.length === 0) {
|
|
507
|
+
await db
|
|
508
|
+
.insert(schema.archetypesData)
|
|
509
|
+
.values({
|
|
510
|
+
id: enId,
|
|
511
|
+
combination,
|
|
512
|
+
gender,
|
|
513
|
+
archetypeIndex: index,
|
|
514
|
+
language: 'en-us',
|
|
515
|
+
name: englishEntry.name,
|
|
516
|
+
essenceLine: englishEntry.essenceLine,
|
|
517
|
+
status: 'idle',
|
|
518
|
+
})
|
|
519
|
+
.onConflictDoUpdate({
|
|
520
|
+
target: [schema.archetypesData.id],
|
|
521
|
+
set: {
|
|
522
|
+
name: englishEntry.name,
|
|
523
|
+
essenceLine: englishEntry.essenceLine,
|
|
524
|
+
updatedAt: new Date().getTime(),
|
|
525
|
+
},
|
|
526
|
+
});
|
|
527
|
+
}
|
|
458
528
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
.
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
});
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
const existingEntryPt = await db
|
|
491
|
-
.select({ id: schema.archetypesData.id })
|
|
492
|
-
.from(schema.archetypesData)
|
|
493
|
-
.where(
|
|
494
|
-
eq(schema.archetypesData.id, `${combination}:${gender}:${index}:pt`)
|
|
495
|
-
)
|
|
496
|
-
.execute();
|
|
497
|
-
|
|
498
|
-
if (overrideExisting || existingEntryPt.length === 0) {
|
|
499
|
-
await db
|
|
500
|
-
.insert(schema.archetypesData)
|
|
501
|
-
.values({
|
|
502
|
-
id: `${combination}:${gender}:${index}:pt`,
|
|
503
|
-
combination,
|
|
504
|
-
gender,
|
|
505
|
-
archetypeIndex: index,
|
|
506
|
-
language: 'pt-br',
|
|
507
|
-
name: portuguese[j].masc,
|
|
508
|
-
essenceLine: portuguese[j].essenceLine,
|
|
509
|
-
status: 'idle',
|
|
510
|
-
})
|
|
511
|
-
.onConflictDoUpdate({
|
|
512
|
-
target: [schema.archetypesData.id],
|
|
513
|
-
set: {
|
|
514
|
-
name: portuguese[j].masc,
|
|
515
|
-
essenceLine: portuguese[j].essenceLine,
|
|
516
|
-
updatedAt: new Date().getTime(),
|
|
517
|
-
},
|
|
518
|
-
});
|
|
529
|
+
const existingPt = await db
|
|
530
|
+
.select({ id: schema.archetypesData.id })
|
|
531
|
+
.from(schema.archetypesData)
|
|
532
|
+
.where(eq(schema.archetypesData.id, ptId))
|
|
533
|
+
.execute();
|
|
534
|
+
|
|
535
|
+
if (overrideExisting || existingPt.length === 0) {
|
|
536
|
+
await db
|
|
537
|
+
.insert(schema.archetypesData)
|
|
538
|
+
.values({
|
|
539
|
+
id: ptId,
|
|
540
|
+
combination,
|
|
541
|
+
gender,
|
|
542
|
+
archetypeIndex: index,
|
|
543
|
+
language: 'pt-br',
|
|
544
|
+
name: ptName,
|
|
545
|
+
essenceLine: ptEntry.essenceLine,
|
|
546
|
+
status: 'idle',
|
|
547
|
+
})
|
|
548
|
+
.onConflictDoUpdate({
|
|
549
|
+
target: [schema.archetypesData.id],
|
|
550
|
+
set: {
|
|
551
|
+
name: ptName,
|
|
552
|
+
essenceLine: ptEntry.essenceLine,
|
|
553
|
+
updatedAt: new Date().getTime(),
|
|
554
|
+
},
|
|
555
|
+
});
|
|
556
|
+
}
|
|
519
557
|
}
|
|
520
558
|
}
|
|
521
559
|
}
|
|
@@ -89,11 +89,9 @@ export class ArchetypeWorkflow {
|
|
|
89
89
|
|
|
90
90
|
async generateNames({
|
|
91
91
|
combinations,
|
|
92
|
-
gender,
|
|
93
92
|
overrideExisting,
|
|
94
93
|
}: {
|
|
95
94
|
combinations: string[];
|
|
96
|
-
gender: Gender;
|
|
97
95
|
overrideExisting?: boolean;
|
|
98
96
|
}): Promise<void> {
|
|
99
97
|
if (combinations.length === 0) return;
|
|
@@ -101,16 +99,17 @@ export class ArchetypeWorkflow {
|
|
|
101
99
|
if (combinations.length === 1) {
|
|
102
100
|
await this.archetypeService.generateArchetypeNames(
|
|
103
101
|
combinations[0],
|
|
104
|
-
gender,
|
|
105
102
|
overrideExisting
|
|
106
103
|
);
|
|
107
104
|
} else {
|
|
108
105
|
const entries = combinations.map((combination) => ({
|
|
109
106
|
combination,
|
|
110
|
-
gender,
|
|
111
107
|
}));
|
|
112
108
|
|
|
113
|
-
await this.archetypeService.generateArchetypeNamesBatch(
|
|
109
|
+
await this.archetypeService.generateArchetypeNamesBatch(
|
|
110
|
+
entries,
|
|
111
|
+
overrideExisting
|
|
112
|
+
);
|
|
114
113
|
}
|
|
115
114
|
}
|
|
116
115
|
|