@zodic/shared 0.0.298 → 0.0.300
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 +333 -133
- package/db/schema.ts +1 -1
- package/package.json +1 -1
- package/utils/archetypeNamesMessages.ts +28 -29
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import { and, eq } from 'drizzle-orm';
|
|
1
|
+
import { and, eq, sql } from 'drizzle-orm';
|
|
2
2
|
import { inject, injectable } from 'inversify';
|
|
3
3
|
import { ChatMessages, schema } from '../..';
|
|
4
4
|
import { KVArchetype, ZodiacSignSlug } from '../../types/scopes/legacy';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
Composition,
|
|
7
|
+
generateArchetypePrompt,
|
|
8
|
+
} from '../../utils/archetypeNamesMessages';
|
|
6
9
|
import { buildCosmicMirrorArchetypeKVKey } from '../../utils/KVKeysBuilders';
|
|
7
10
|
import { AppContext } from '../base';
|
|
8
11
|
|
|
@@ -287,19 +290,29 @@ export class ArchetypeService {
|
|
|
287
290
|
|
|
288
291
|
async generateArchetypeNames(
|
|
289
292
|
combination: string,
|
|
290
|
-
overrideExisting: boolean = false
|
|
293
|
+
overrideExisting: boolean = false,
|
|
294
|
+
indexesToGenerate?: number[]
|
|
291
295
|
) {
|
|
292
296
|
const db = this.context.drizzle();
|
|
293
|
-
|
|
297
|
+
console.log(
|
|
298
|
+
`🚀 [Single] Starting generation for combination: ${combination} | Override: ${overrideExisting}`
|
|
299
|
+
);
|
|
294
300
|
|
|
295
|
-
const
|
|
301
|
+
const [sun, ascendant, moon] = combination.split('-') as ZodiacSignSlug[];
|
|
302
|
+
const prompt = generateArchetypePrompt([
|
|
303
|
+
{
|
|
304
|
+
sun,
|
|
305
|
+
ascendant,
|
|
306
|
+
moon,
|
|
307
|
+
indexesToGenerate: indexesToGenerate ?? [1, 2, 3],
|
|
308
|
+
},
|
|
309
|
+
]);
|
|
296
310
|
const messages: ChatMessages = [{ role: 'user', content: prompt }];
|
|
297
311
|
const response = await this.context.api().callTogether.single(messages, {});
|
|
298
312
|
|
|
299
313
|
if (!response) {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
);
|
|
314
|
+
console.error(`❌ [Single] No response for: ${combination}`);
|
|
315
|
+
return;
|
|
303
316
|
}
|
|
304
317
|
|
|
305
318
|
let blocks: string[] = [];
|
|
@@ -319,7 +332,7 @@ export class ArchetypeService {
|
|
|
319
332
|
.split(/\n\d\.\s*\n?/)
|
|
320
333
|
.filter(Boolean);
|
|
321
334
|
} catch (err) {
|
|
322
|
-
console.error(
|
|
335
|
+
console.error(`❌ [Single] Parsing failed for ${combination}`, err);
|
|
323
336
|
await db.insert(schema.archetypeNameDumps).values({
|
|
324
337
|
id: combination,
|
|
325
338
|
combination,
|
|
@@ -330,23 +343,17 @@ export class ArchetypeService {
|
|
|
330
343
|
return;
|
|
331
344
|
}
|
|
332
345
|
|
|
333
|
-
const englishNames = blocks.map((block) => {
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
name: nameMatch?.[1]?.trim() || '',
|
|
338
|
-
essenceLine: essenceMatch?.[1]?.trim() || '',
|
|
339
|
-
};
|
|
340
|
-
});
|
|
346
|
+
const englishNames = blocks.map((block) => ({
|
|
347
|
+
name: block.match(/• Name:\s*(.+)/)?.[1]?.trim() || '',
|
|
348
|
+
essenceLine: block.match(/• Essence:\s*(.+)/)?.[1]?.trim() || '',
|
|
349
|
+
}));
|
|
341
350
|
|
|
342
|
-
const portugueseVariants = ptBlocks.map((block) => {
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
});
|
|
351
|
+
const portugueseVariants = ptBlocks.map((block) => ({
|
|
352
|
+
masc: block.match(/• Masculino:\s*(.+)/)?.[1]?.trim() || '',
|
|
353
|
+
fem: block.match(/• Feminino:\s*(.+)/)?.[1]?.trim() || '',
|
|
354
|
+
essenceLine: block.match(/• Essência:\s*(.+)/)?.[1]?.trim() || '',
|
|
355
|
+
}));
|
|
348
356
|
|
|
349
|
-
// Duplicate helper
|
|
350
357
|
async function isEnglishNameDuplicate(name: string): Promise<boolean> {
|
|
351
358
|
const result = await db
|
|
352
359
|
.select({ name: schema.archetypesData.name })
|
|
@@ -369,7 +376,7 @@ export class ArchetypeService {
|
|
|
369
376
|
const ptVariant = portugueseVariants[i];
|
|
370
377
|
|
|
371
378
|
if (await isEnglishNameDuplicate(entry.name)) {
|
|
372
|
-
console.warn(
|
|
379
|
+
console.warn(`⚠️ [Single] Duplicate name skipped: ${entry.name}`);
|
|
373
380
|
return;
|
|
374
381
|
}
|
|
375
382
|
|
|
@@ -378,66 +385,56 @@ export class ArchetypeService {
|
|
|
378
385
|
const ptId = `${combination}:${gender}:${index}:pt`;
|
|
379
386
|
const ptName = gender === 'female' ? ptVariant.fem : ptVariant.masc;
|
|
380
387
|
|
|
381
|
-
|
|
382
|
-
.
|
|
383
|
-
.
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
.
|
|
390
|
-
.
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
388
|
+
await db
|
|
389
|
+
.insert(schema.archetypesData)
|
|
390
|
+
.values({
|
|
391
|
+
id: enId,
|
|
392
|
+
combination,
|
|
393
|
+
gender,
|
|
394
|
+
archetypeIndex: index,
|
|
395
|
+
language: 'en-us',
|
|
396
|
+
name: entry.name,
|
|
397
|
+
essenceLine: entry.essenceLine,
|
|
398
|
+
status: 'idle',
|
|
399
|
+
})
|
|
400
|
+
.onConflictDoUpdate({
|
|
401
|
+
target: [schema.archetypesData.id],
|
|
402
|
+
set: {
|
|
396
403
|
name: entry.name,
|
|
397
404
|
essenceLine: entry.essenceLine,
|
|
398
|
-
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
.
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
await db
|
|
418
|
-
.insert(schema.archetypesData)
|
|
419
|
-
.values({
|
|
420
|
-
id: ptId,
|
|
421
|
-
combination,
|
|
422
|
-
gender,
|
|
423
|
-
archetypeIndex: index,
|
|
424
|
-
language: 'pt-br',
|
|
405
|
+
updatedAt: new Date().getTime(),
|
|
406
|
+
},
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
await db
|
|
410
|
+
.insert(schema.archetypesData)
|
|
411
|
+
.values({
|
|
412
|
+
id: ptId,
|
|
413
|
+
combination,
|
|
414
|
+
gender,
|
|
415
|
+
archetypeIndex: index,
|
|
416
|
+
language: 'pt-br',
|
|
417
|
+
name: ptName,
|
|
418
|
+
essenceLine: ptVariant.essenceLine,
|
|
419
|
+
status: 'idle',
|
|
420
|
+
})
|
|
421
|
+
.onConflictDoUpdate({
|
|
422
|
+
target: [schema.archetypesData.id],
|
|
423
|
+
set: {
|
|
425
424
|
name: ptName,
|
|
426
425
|
essenceLine: ptVariant.essenceLine,
|
|
427
|
-
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
updatedAt: new Date().getTime(),
|
|
435
|
-
},
|
|
436
|
-
});
|
|
437
|
-
}
|
|
426
|
+
updatedAt: new Date().getTime(),
|
|
427
|
+
},
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
console.log(
|
|
431
|
+
`✅ [Single] Saved archetype ${index} (${gender}) for ${combination}`
|
|
432
|
+
);
|
|
438
433
|
}
|
|
439
434
|
})
|
|
440
435
|
);
|
|
436
|
+
|
|
437
|
+
console.log(`🏁 [Single] Done generating names for ${combination}`);
|
|
441
438
|
}
|
|
442
439
|
|
|
443
440
|
async generateArchetypeNamesBatch(
|
|
@@ -445,6 +442,9 @@ export class ArchetypeService {
|
|
|
445
442
|
overrideExisting: boolean = false
|
|
446
443
|
) {
|
|
447
444
|
const db = this.context.drizzle();
|
|
445
|
+
console.log(
|
|
446
|
+
`🚀 [Batch] Starting generation for ${entries.length} combinations | Override: ${overrideExisting}`
|
|
447
|
+
);
|
|
448
448
|
|
|
449
449
|
const prompts = entries.map(({ combination }) => {
|
|
450
450
|
const [sun, ascendant, moon] = combination.split('-') as ZodiacSignSlug[];
|
|
@@ -456,7 +456,8 @@ export class ArchetypeService {
|
|
|
456
456
|
const response = await this.context.api().callTogether.single(messages, {});
|
|
457
457
|
|
|
458
458
|
if (!response) {
|
|
459
|
-
|
|
459
|
+
console.error(`❌ [Batch] No response from model`);
|
|
460
|
+
return;
|
|
460
461
|
}
|
|
461
462
|
|
|
462
463
|
const blocks = response
|
|
@@ -483,6 +484,7 @@ export class ArchetypeService {
|
|
|
483
484
|
for (let i = 0; i < entries.length; i++) {
|
|
484
485
|
const { combination } = entries[i];
|
|
485
486
|
const block = blocks[i];
|
|
487
|
+
console.log(`📦 [Batch] Processing: ${combination}`);
|
|
486
488
|
|
|
487
489
|
let en = '';
|
|
488
490
|
let pt = '';
|
|
@@ -490,7 +492,7 @@ export class ArchetypeService {
|
|
|
490
492
|
en = block.split('-EN')[1].split('-PT')[0].trim();
|
|
491
493
|
pt = block.split('-PT')[1].trim();
|
|
492
494
|
} catch (err) {
|
|
493
|
-
console.error(
|
|
495
|
+
console.error(`❌ [Batch] Parsing failed for: ${combination}`, err);
|
|
494
496
|
await db.insert(schema.archetypeNameDumps).values({
|
|
495
497
|
id: combination,
|
|
496
498
|
combination,
|
|
@@ -525,7 +527,7 @@ export class ArchetypeService {
|
|
|
525
527
|
|
|
526
528
|
if (await isEnglishNameDuplicate(englishEntry.name)) {
|
|
527
529
|
console.warn(
|
|
528
|
-
|
|
530
|
+
`⚠️ [Batch] Duplicate name skipped: ${englishEntry.name}`
|
|
529
531
|
);
|
|
530
532
|
continue;
|
|
531
533
|
}
|
|
@@ -535,65 +537,263 @@ export class ArchetypeService {
|
|
|
535
537
|
const ptId = `${combination}:${gender}:${index}:pt`;
|
|
536
538
|
const ptName = gender === 'female' ? ptEntry.fem : ptEntry.masc;
|
|
537
539
|
|
|
538
|
-
|
|
539
|
-
.
|
|
540
|
-
.
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
.
|
|
547
|
-
.
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
540
|
+
await db
|
|
541
|
+
.insert(schema.archetypesData)
|
|
542
|
+
.values({
|
|
543
|
+
id: enId,
|
|
544
|
+
combination,
|
|
545
|
+
gender,
|
|
546
|
+
archetypeIndex: index,
|
|
547
|
+
language: 'en-us',
|
|
548
|
+
name: englishEntry.name,
|
|
549
|
+
essenceLine: englishEntry.essenceLine,
|
|
550
|
+
status: 'idle',
|
|
551
|
+
})
|
|
552
|
+
.onConflictDoUpdate({
|
|
553
|
+
target: [schema.archetypesData.id],
|
|
554
|
+
set: {
|
|
553
555
|
name: englishEntry.name,
|
|
554
556
|
essenceLine: englishEntry.essenceLine,
|
|
555
|
-
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
557
|
+
updatedAt: new Date().getTime(),
|
|
558
|
+
},
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
await db
|
|
562
|
+
.insert(schema.archetypesData)
|
|
563
|
+
.values({
|
|
564
|
+
id: ptId,
|
|
565
|
+
combination,
|
|
566
|
+
gender,
|
|
567
|
+
archetypeIndex: index,
|
|
568
|
+
language: 'pt-br',
|
|
569
|
+
name: ptName,
|
|
570
|
+
essenceLine: ptEntry.essenceLine,
|
|
571
|
+
status: 'idle',
|
|
572
|
+
})
|
|
573
|
+
.onConflictDoUpdate({
|
|
574
|
+
target: [schema.archetypesData.id],
|
|
575
|
+
set: {
|
|
576
|
+
name: ptName,
|
|
577
|
+
essenceLine: ptEntry.essenceLine,
|
|
578
|
+
updatedAt: new Date().getTime(),
|
|
579
|
+
},
|
|
580
|
+
});
|
|
581
|
+
|
|
582
|
+
console.log(
|
|
583
|
+
`✅ [Batch] Saved archetype ${index} (${gender}) for ${combination}`
|
|
584
|
+
);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
console.log(`🏁 [Batch] Finished combination: ${combination}`);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
console.log(
|
|
592
|
+
`🎉 [Batch] Completed processing for all ${entries.length} combinations`
|
|
593
|
+
);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
async findIncompleteCombinations(): Promise<
|
|
597
|
+
Array<{ combination: string; count: number }>
|
|
598
|
+
> {
|
|
599
|
+
const db = this.context.drizzle();
|
|
600
|
+
|
|
601
|
+
const result = await db
|
|
602
|
+
.select({
|
|
603
|
+
combination: schema.archetypesData.combination,
|
|
604
|
+
count: sql<number>`count(*)`.as('count'),
|
|
605
|
+
})
|
|
606
|
+
.from(schema.archetypesData)
|
|
607
|
+
.groupBy(schema.archetypesData.combination)
|
|
608
|
+
.having(sql`count(*) < 12`)
|
|
609
|
+
.execute();
|
|
610
|
+
|
|
611
|
+
const typedResult = result.map((row) => ({
|
|
612
|
+
combination: row.combination,
|
|
613
|
+
count: Number(row.count),
|
|
614
|
+
}));
|
|
615
|
+
|
|
616
|
+
console.log(`🔍 Found ${typedResult.length} incomplete combinations`);
|
|
617
|
+
return typedResult;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
async regenerateMissingArchetypeNames(overrideExisting: boolean = false) {
|
|
621
|
+
const incomplete = await this.findIncompleteCombinations();
|
|
622
|
+
console.log(
|
|
623
|
+
`🔁 Starting regeneration for ${incomplete.length} combinations`
|
|
624
|
+
);
|
|
625
|
+
|
|
626
|
+
for (const { combination, count } of incomplete) {
|
|
627
|
+
const indexesToGenerate: number[] = [];
|
|
628
|
+
|
|
629
|
+
const db = this.context.drizzle();
|
|
630
|
+
const existing = await db
|
|
631
|
+
.select({
|
|
632
|
+
archetypeIndex: schema.archetypesData.archetypeIndex,
|
|
633
|
+
language: schema.archetypesData.language,
|
|
634
|
+
gender: schema.archetypesData.gender,
|
|
635
|
+
})
|
|
636
|
+
.from(schema.archetypesData)
|
|
637
|
+
.where(eq(schema.archetypesData.combination, combination))
|
|
638
|
+
.execute();
|
|
639
|
+
|
|
640
|
+
for (let i = 1; i <= 3; i++) {
|
|
641
|
+
const hasAll =
|
|
642
|
+
existing.filter((e) => e.archetypeIndex === i.toString()).length ===
|
|
643
|
+
4;
|
|
644
|
+
if (!hasAll) indexesToGenerate.push(i);
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
if (indexesToGenerate.length > 0) {
|
|
648
|
+
console.log(
|
|
649
|
+
`🧩 Regenerating indexes ${indexesToGenerate.join(
|
|
650
|
+
','
|
|
651
|
+
)} for ${combination}`
|
|
652
|
+
);
|
|
653
|
+
await this.generateArchetypeNames(
|
|
654
|
+
combination,
|
|
655
|
+
overrideExisting,
|
|
656
|
+
indexesToGenerate
|
|
657
|
+
);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
console.log(`✅ Done regenerating missing archetype names`);
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
async regenerateMissingArchetypeNamesBatch(compositions: Composition[]) {
|
|
665
|
+
if (compositions.length === 0) {
|
|
666
|
+
console.log('✅ [Batch] No combinations provided for regeneration');
|
|
667
|
+
return;
|
|
668
|
+
}
|
|
566
669
|
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
670
|
+
console.log(
|
|
671
|
+
`🔁 [Batch] Starting regeneration for ${compositions.length} combinations`
|
|
672
|
+
);
|
|
673
|
+
|
|
674
|
+
const prompt = generateArchetypePrompt(compositions);
|
|
675
|
+
const messages: ChatMessages = [{ role: 'user', content: prompt }];
|
|
676
|
+
const response = await this.context.api().callTogether.single(messages, {});
|
|
677
|
+
|
|
678
|
+
if (!response) {
|
|
679
|
+
console.error(`❌ [Batch] No response from model during regeneration`);
|
|
680
|
+
return;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
const blocks = response
|
|
684
|
+
.split(/Composition \d+/)
|
|
685
|
+
.slice(1)
|
|
686
|
+
.map((b) => b.trim());
|
|
687
|
+
|
|
688
|
+
for (let i = 0; i < compositions.length; i++) {
|
|
689
|
+
const comp = compositions[i];
|
|
690
|
+
const combination = [comp.sun, comp.ascendant, comp.moon].join('-');
|
|
691
|
+
const block = blocks[i];
|
|
692
|
+
const indexes = comp.indexesToGenerate ?? [1, 2, 3];
|
|
693
|
+
|
|
694
|
+
console.log(`🔄 [Batch] Processing: ${combination}`);
|
|
695
|
+
|
|
696
|
+
let en = '';
|
|
697
|
+
let pt = '';
|
|
698
|
+
try {
|
|
699
|
+
en = block.split('-EN')[1].split('-PT')[0].trim();
|
|
700
|
+
pt = block.split('-PT')[1].trim();
|
|
701
|
+
} catch (err) {
|
|
702
|
+
console.error(`❌ [Batch] Parsing failed for: ${combination}`, err);
|
|
703
|
+
await this.context
|
|
704
|
+
.drizzle()
|
|
705
|
+
.insert(schema.archetypeNameDumps)
|
|
706
|
+
.values({
|
|
707
|
+
id: `${combination}:${Date.now()}`,
|
|
708
|
+
combination,
|
|
709
|
+
rawText: block,
|
|
710
|
+
parsedSuccessfully: 0,
|
|
711
|
+
createdAt: Date.now(),
|
|
712
|
+
});
|
|
713
|
+
continue;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
const english = en
|
|
717
|
+
.split(/\n\d\.\s*\n?/)
|
|
718
|
+
.filter(Boolean)
|
|
719
|
+
.map((line) => ({
|
|
720
|
+
name: line.match(/• Name:\s*(.+)/)?.[1]?.trim() || '',
|
|
721
|
+
essenceLine: line.match(/• Essence:\s*(.+)/)?.[1]?.trim() || '',
|
|
722
|
+
}));
|
|
723
|
+
|
|
724
|
+
const portuguese = pt
|
|
725
|
+
.split(/\n\d\.\s*\n?/)
|
|
726
|
+
.filter(Boolean)
|
|
727
|
+
.map((line) => ({
|
|
728
|
+
masc: line.match(/• Masculino:\s*(.+)/)?.[1]?.trim() || '',
|
|
729
|
+
fem: line.match(/• Feminino:\s*(.+)/)?.[1]?.trim() || '',
|
|
730
|
+
essenceLine: line.match(/• Essência:\s*(.+)/)?.[1]?.trim() || '',
|
|
731
|
+
}));
|
|
732
|
+
|
|
733
|
+
for (const index of indexes) {
|
|
734
|
+
const englishEntry = english[index - 1];
|
|
735
|
+
const ptEntry = portuguese[index - 1];
|
|
736
|
+
|
|
737
|
+
for (const gender of ['male', 'female']) {
|
|
738
|
+
const enId = `${combination}:${gender}:${index}`;
|
|
739
|
+
const ptId = `${combination}:${gender}:${index}:pt`;
|
|
740
|
+
const ptName = gender === 'female' ? ptEntry.fem : ptEntry.masc;
|
|
741
|
+
|
|
742
|
+
await this.context
|
|
743
|
+
.drizzle()
|
|
744
|
+
.insert(schema.archetypesData)
|
|
745
|
+
.values({
|
|
746
|
+
id: enId,
|
|
747
|
+
combination,
|
|
748
|
+
gender,
|
|
749
|
+
archetypeIndex: index.toString(),
|
|
750
|
+
language: 'en-us',
|
|
751
|
+
name: englishEntry.name,
|
|
752
|
+
essenceLine: englishEntry.essenceLine,
|
|
753
|
+
status: 'idle',
|
|
754
|
+
})
|
|
755
|
+
.onConflictDoUpdate({
|
|
756
|
+
target: [schema.archetypesData.id],
|
|
757
|
+
set: {
|
|
758
|
+
name: englishEntry.name,
|
|
759
|
+
essenceLine: englishEntry.essenceLine,
|
|
760
|
+
updatedAt: new Date().getTime(),
|
|
761
|
+
},
|
|
762
|
+
});
|
|
763
|
+
|
|
764
|
+
await this.context
|
|
765
|
+
.drizzle()
|
|
766
|
+
.insert(schema.archetypesData)
|
|
767
|
+
.values({
|
|
768
|
+
id: ptId,
|
|
769
|
+
combination,
|
|
770
|
+
gender,
|
|
771
|
+
archetypeIndex: index.toString(),
|
|
772
|
+
language: 'pt-br',
|
|
773
|
+
name: ptName,
|
|
774
|
+
essenceLine: ptEntry.essenceLine,
|
|
775
|
+
status: 'idle',
|
|
776
|
+
})
|
|
777
|
+
.onConflictDoUpdate({
|
|
778
|
+
target: [schema.archetypesData.id],
|
|
779
|
+
set: {
|
|
582
780
|
name: ptName,
|
|
583
781
|
essenceLine: ptEntry.essenceLine,
|
|
584
|
-
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
updatedAt: new Date().getTime(),
|
|
592
|
-
},
|
|
593
|
-
});
|
|
594
|
-
}
|
|
782
|
+
updatedAt: new Date().getTime(),
|
|
783
|
+
},
|
|
784
|
+
});
|
|
785
|
+
|
|
786
|
+
console.log(
|
|
787
|
+
`✅ [Batch] Saved archetype ${index} (${gender}) for ${combination}`
|
|
788
|
+
);
|
|
595
789
|
}
|
|
596
790
|
}
|
|
791
|
+
|
|
792
|
+
console.log(`🏁 [Batch] Finished combination: ${combination}`);
|
|
597
793
|
}
|
|
794
|
+
|
|
795
|
+
console.log(
|
|
796
|
+
`🎉 [Batch] Completed regenerating ${compositions.length} combinations`
|
|
797
|
+
);
|
|
598
798
|
}
|
|
599
799
|
}
|
package/db/schema.ts
CHANGED
|
@@ -425,7 +425,7 @@ export const archetypesData = sqliteTable(
|
|
|
425
425
|
content: text('content').default('[]').notNull(), // JSON stringified structured content
|
|
426
426
|
virtues: text('virtues').default('[]').notNull(), // JSON stringified array
|
|
427
427
|
leonardoPrompt: text('leonardo_prompt'), // Leonardo prompt
|
|
428
|
-
status: text('status').default('idle'), //
|
|
428
|
+
status: text('status').default('idle'), // Status: 'idle', 'generated', 'duplicate', 'error'
|
|
429
429
|
createdAt: integer('created_at').default(sql`CURRENT_TIMESTAMP`),
|
|
430
430
|
// JSON array of objects: { leonardoId: string; url: string; height: number; width: number; }
|
|
431
431
|
images: text('images').default('[]').notNull(),
|
package/package.json
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
// --- 1. Influence Table ---
|
|
2
|
-
|
|
3
1
|
import { ZodiacSignSlug } from '../types/scopes/legacy';
|
|
4
2
|
|
|
5
3
|
export type Planet = 'sun' | 'ascendant' | 'moon';
|
|
@@ -198,12 +196,11 @@ export const influenceMap: Record<Planet, Record<ZodiacSignSlug, Trait>> = {
|
|
|
198
196
|
},
|
|
199
197
|
};
|
|
200
198
|
|
|
201
|
-
// --- 2. Prompt Generator ---
|
|
202
|
-
|
|
203
199
|
export interface Composition {
|
|
204
200
|
sun: ZodiacSignSlug;
|
|
205
201
|
ascendant: ZodiacSignSlug;
|
|
206
202
|
moon: ZodiacSignSlug;
|
|
203
|
+
indexesToGenerate?: number[];
|
|
207
204
|
}
|
|
208
205
|
|
|
209
206
|
export function generateArchetypePrompt(compositions: Composition[]): string {
|
|
@@ -226,40 +223,42 @@ Do not include any commentary or explanations outside the defined output structu
|
|
|
226
223
|
const sun = influenceMap.sun[comp.sun];
|
|
227
224
|
const asc = influenceMap.ascendant[comp.ascendant];
|
|
228
225
|
const moon = influenceMap.moon[comp.moon];
|
|
226
|
+
const indexes = comp.indexesToGenerate ?? [1, 2, 3];
|
|
229
227
|
|
|
230
|
-
|
|
228
|
+
const influences = `\n\n### Composition ${i + 1}
|
|
231
229
|
|
|
232
230
|
• First Influence – ${sun.label}: ${sun.description}
|
|
233
231
|
• Second Influence – ${asc.label}: ${asc.description}
|
|
234
232
|
• Third Influence – ${moon.label}: ${moon.description}`;
|
|
235
|
-
});
|
|
236
233
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
• Name: [Name that emphasizes the
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
•
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
• Name: [Name that emphasizes the third influence, while blending the first and second]
|
|
247
|
-
• Essence: [Short poetic description line in English]
|
|
234
|
+
const enLines = indexes
|
|
235
|
+
.map(
|
|
236
|
+
(idx) => `${idx}.
|
|
237
|
+
• Name: [Name that emphasizes the ${
|
|
238
|
+
['first', 'second', 'third'][idx - 1]
|
|
239
|
+
} influence, while blending the other two]
|
|
240
|
+
• Essence: [Short poetic description line in English]`
|
|
241
|
+
)
|
|
242
|
+
.join('\n');
|
|
248
243
|
|
|
249
|
-
|
|
250
|
-
|
|
244
|
+
const ptLines = indexes
|
|
245
|
+
.map(
|
|
246
|
+
(idx) => `${idx}.
|
|
251
247
|
• Masculino: [Portuguese name (masc)]
|
|
252
248
|
• Feminino: [Portuguese name (fem)]
|
|
253
|
-
• Essência: [Short poetic description line in Portuguese]
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
249
|
+
• Essência: [Short poetic description line in Portuguese]`
|
|
250
|
+
)
|
|
251
|
+
.join('\n');
|
|
252
|
+
|
|
253
|
+
return `${influences}
|
|
254
|
+
|
|
255
|
+
\`\n-EN
|
|
256
|
+
${enLines}
|
|
257
|
+
|
|
258
|
+
-PT
|
|
259
|
+
${ptLines}
|
|
262
260
|
\``;
|
|
261
|
+
});
|
|
263
262
|
|
|
264
|
-
return `${promptHeader}\n${compositionBlocks.join('\n')}
|
|
263
|
+
return `${promptHeader}\n${compositionBlocks.join('\n')}`;
|
|
265
264
|
}
|