@zodic/shared 0.0.299 → 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 +342 -103
- 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,24 +290,34 @@ 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
|
-
console.log(
|
|
294
|
-
|
|
297
|
+
console.log(
|
|
298
|
+
`🚀 [Single] Starting generation for combination: ${combination} | Override: ${overrideExisting}`
|
|
299
|
+
);
|
|
300
|
+
|
|
295
301
|
const [sun, ascendant, moon] = combination.split('-') as ZodiacSignSlug[];
|
|
296
|
-
const prompt = generateArchetypePrompt([
|
|
302
|
+
const prompt = generateArchetypePrompt([
|
|
303
|
+
{
|
|
304
|
+
sun,
|
|
305
|
+
ascendant,
|
|
306
|
+
moon,
|
|
307
|
+
indexesToGenerate: indexesToGenerate ?? [1, 2, 3],
|
|
308
|
+
},
|
|
309
|
+
]);
|
|
297
310
|
const messages: ChatMessages = [{ role: 'user', content: prompt }];
|
|
298
311
|
const response = await this.context.api().callTogether.single(messages, {});
|
|
299
|
-
|
|
312
|
+
|
|
300
313
|
if (!response) {
|
|
301
314
|
console.error(`❌ [Single] No response for: ${combination}`);
|
|
302
315
|
return;
|
|
303
316
|
}
|
|
304
|
-
|
|
317
|
+
|
|
305
318
|
let blocks: string[] = [];
|
|
306
319
|
let ptBlocks: string[] = [];
|
|
307
|
-
|
|
320
|
+
|
|
308
321
|
try {
|
|
309
322
|
blocks = response
|
|
310
323
|
.split('-EN')[1]
|
|
@@ -312,7 +325,7 @@ export class ArchetypeService {
|
|
|
312
325
|
.trim()
|
|
313
326
|
.split(/\n\d\.\s*\n?/)
|
|
314
327
|
.filter(Boolean);
|
|
315
|
-
|
|
328
|
+
|
|
316
329
|
ptBlocks = response
|
|
317
330
|
.split('-PT')[1]
|
|
318
331
|
.trim()
|
|
@@ -329,18 +342,18 @@ export class ArchetypeService {
|
|
|
329
342
|
});
|
|
330
343
|
return;
|
|
331
344
|
}
|
|
332
|
-
|
|
345
|
+
|
|
333
346
|
const englishNames = blocks.map((block) => ({
|
|
334
347
|
name: block.match(/• Name:\s*(.+)/)?.[1]?.trim() || '',
|
|
335
348
|
essenceLine: block.match(/• Essence:\s*(.+)/)?.[1]?.trim() || '',
|
|
336
349
|
}));
|
|
337
|
-
|
|
350
|
+
|
|
338
351
|
const portugueseVariants = ptBlocks.map((block) => ({
|
|
339
352
|
masc: block.match(/• Masculino:\s*(.+)/)?.[1]?.trim() || '',
|
|
340
353
|
fem: block.match(/• Feminino:\s*(.+)/)?.[1]?.trim() || '',
|
|
341
354
|
essenceLine: block.match(/• Essência:\s*(.+)/)?.[1]?.trim() || '',
|
|
342
355
|
}));
|
|
343
|
-
|
|
356
|
+
|
|
344
357
|
async function isEnglishNameDuplicate(name: string): Promise<boolean> {
|
|
345
358
|
const result = await db
|
|
346
359
|
.select({ name: schema.archetypesData.name })
|
|
@@ -353,66 +366,74 @@ export class ArchetypeService {
|
|
|
353
366
|
)
|
|
354
367
|
.limit(1)
|
|
355
368
|
.execute();
|
|
356
|
-
|
|
369
|
+
|
|
357
370
|
return result.length > 0;
|
|
358
371
|
}
|
|
359
|
-
|
|
372
|
+
|
|
360
373
|
await Promise.all(
|
|
361
374
|
englishNames.map(async (entry, i) => {
|
|
362
375
|
const index = (i + 1).toString();
|
|
363
376
|
const ptVariant = portugueseVariants[i];
|
|
364
|
-
|
|
377
|
+
|
|
365
378
|
if (await isEnglishNameDuplicate(entry.name)) {
|
|
366
379
|
console.warn(`⚠️ [Single] Duplicate name skipped: ${entry.name}`);
|
|
367
380
|
return;
|
|
368
381
|
}
|
|
369
|
-
|
|
382
|
+
|
|
370
383
|
for (const gender of ['male', 'female']) {
|
|
371
384
|
const enId = `${combination}:${gender}:${index}`;
|
|
372
385
|
const ptId = `${combination}:${gender}:${index}:pt`;
|
|
373
386
|
const ptName = gender === 'female' ? ptVariant.fem : ptVariant.masc;
|
|
374
|
-
|
|
375
|
-
await db
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
status: 'idle',
|
|
384
|
-
}).onConflictDoUpdate({
|
|
385
|
-
target: [schema.archetypesData.id],
|
|
386
|
-
set: {
|
|
387
|
+
|
|
388
|
+
await db
|
|
389
|
+
.insert(schema.archetypesData)
|
|
390
|
+
.values({
|
|
391
|
+
id: enId,
|
|
392
|
+
combination,
|
|
393
|
+
gender,
|
|
394
|
+
archetypeIndex: index,
|
|
395
|
+
language: 'en-us',
|
|
387
396
|
name: entry.name,
|
|
388
397
|
essenceLine: entry.essenceLine,
|
|
389
|
-
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
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
|
+
|
|
409
|
+
await db
|
|
410
|
+
.insert(schema.archetypesData)
|
|
411
|
+
.values({
|
|
412
|
+
id: ptId,
|
|
413
|
+
combination,
|
|
414
|
+
gender,
|
|
415
|
+
archetypeIndex: index,
|
|
416
|
+
language: 'pt-br',
|
|
405
417
|
name: ptName,
|
|
406
418
|
essenceLine: ptVariant.essenceLine,
|
|
407
|
-
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
419
|
+
status: 'idle',
|
|
420
|
+
})
|
|
421
|
+
.onConflictDoUpdate({
|
|
422
|
+
target: [schema.archetypesData.id],
|
|
423
|
+
set: {
|
|
424
|
+
name: ptName,
|
|
425
|
+
essenceLine: ptVariant.essenceLine,
|
|
426
|
+
updatedAt: new Date().getTime(),
|
|
427
|
+
},
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
console.log(
|
|
431
|
+
`✅ [Single] Saved archetype ${index} (${gender}) for ${combination}`
|
|
432
|
+
);
|
|
412
433
|
}
|
|
413
434
|
})
|
|
414
435
|
);
|
|
415
|
-
|
|
436
|
+
|
|
416
437
|
console.log(`🏁 [Single] Done generating names for ${combination}`);
|
|
417
438
|
}
|
|
418
439
|
|
|
@@ -421,27 +442,29 @@ export class ArchetypeService {
|
|
|
421
442
|
overrideExisting: boolean = false
|
|
422
443
|
) {
|
|
423
444
|
const db = this.context.drizzle();
|
|
424
|
-
console.log(
|
|
425
|
-
|
|
445
|
+
console.log(
|
|
446
|
+
`🚀 [Batch] Starting generation for ${entries.length} combinations | Override: ${overrideExisting}`
|
|
447
|
+
);
|
|
448
|
+
|
|
426
449
|
const prompts = entries.map(({ combination }) => {
|
|
427
450
|
const [sun, ascendant, moon] = combination.split('-') as ZodiacSignSlug[];
|
|
428
451
|
return { sun, ascendant, moon };
|
|
429
452
|
});
|
|
430
|
-
|
|
453
|
+
|
|
431
454
|
const prompt = generateArchetypePrompt(prompts);
|
|
432
455
|
const messages: ChatMessages = [{ role: 'user', content: prompt }];
|
|
433
456
|
const response = await this.context.api().callTogether.single(messages, {});
|
|
434
|
-
|
|
457
|
+
|
|
435
458
|
if (!response) {
|
|
436
459
|
console.error(`❌ [Batch] No response from model`);
|
|
437
460
|
return;
|
|
438
461
|
}
|
|
439
|
-
|
|
462
|
+
|
|
440
463
|
const blocks = response
|
|
441
464
|
.split(/Composition \d+/)
|
|
442
465
|
.slice(1)
|
|
443
466
|
.map((b) => b.trim());
|
|
444
|
-
|
|
467
|
+
|
|
445
468
|
async function isEnglishNameDuplicate(name: string): Promise<boolean> {
|
|
446
469
|
const result = await db
|
|
447
470
|
.select({ name: schema.archetypesData.name })
|
|
@@ -454,15 +477,15 @@ export class ArchetypeService {
|
|
|
454
477
|
)
|
|
455
478
|
.limit(1)
|
|
456
479
|
.execute();
|
|
457
|
-
|
|
480
|
+
|
|
458
481
|
return result.length > 0;
|
|
459
482
|
}
|
|
460
|
-
|
|
483
|
+
|
|
461
484
|
for (let i = 0; i < entries.length; i++) {
|
|
462
485
|
const { combination } = entries[i];
|
|
463
486
|
const block = blocks[i];
|
|
464
487
|
console.log(`📦 [Batch] Processing: ${combination}`);
|
|
465
|
-
|
|
488
|
+
|
|
466
489
|
let en = '';
|
|
467
490
|
let pt = '';
|
|
468
491
|
try {
|
|
@@ -479,7 +502,7 @@ export class ArchetypeService {
|
|
|
479
502
|
});
|
|
480
503
|
continue;
|
|
481
504
|
}
|
|
482
|
-
|
|
505
|
+
|
|
483
506
|
const english = en
|
|
484
507
|
.split(/\n\d\.\s*\n?/)
|
|
485
508
|
.filter(Boolean)
|
|
@@ -487,7 +510,7 @@ export class ArchetypeService {
|
|
|
487
510
|
name: line.match(/• Name:\s*(.+)/)?.[1]?.trim() || '',
|
|
488
511
|
essenceLine: line.match(/• Essence:\s*(.+)/)?.[1]?.trim() || '',
|
|
489
512
|
}));
|
|
490
|
-
|
|
513
|
+
|
|
491
514
|
const portuguese = pt
|
|
492
515
|
.split(/\n\d\.\s*\n?/)
|
|
493
516
|
.filter(Boolean)
|
|
@@ -496,65 +519,281 @@ export class ArchetypeService {
|
|
|
496
519
|
fem: line.match(/• Feminino:\s*(.+)/)?.[1]?.trim() || '',
|
|
497
520
|
essenceLine: line.match(/• Essência:\s*(.+)/)?.[1]?.trim() || '',
|
|
498
521
|
}));
|
|
499
|
-
|
|
522
|
+
|
|
500
523
|
for (let j = 0; j < 3; j++) {
|
|
501
524
|
const index = (j + 1).toString();
|
|
502
525
|
const englishEntry = english[j];
|
|
503
526
|
const ptEntry = portuguese[j];
|
|
504
|
-
|
|
527
|
+
|
|
505
528
|
if (await isEnglishNameDuplicate(englishEntry.name)) {
|
|
506
|
-
console.warn(
|
|
529
|
+
console.warn(
|
|
530
|
+
`⚠️ [Batch] Duplicate name skipped: ${englishEntry.name}`
|
|
531
|
+
);
|
|
507
532
|
continue;
|
|
508
533
|
}
|
|
509
|
-
|
|
534
|
+
|
|
510
535
|
for (const gender of ['male', 'female']) {
|
|
511
536
|
const enId = `${combination}:${gender}:${index}`;
|
|
512
537
|
const ptId = `${combination}:${gender}:${index}:pt`;
|
|
513
538
|
const ptName = gender === 'female' ? ptEntry.fem : ptEntry.masc;
|
|
514
|
-
|
|
515
|
-
await db
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
status: 'idle',
|
|
524
|
-
}).onConflictDoUpdate({
|
|
525
|
-
target: [schema.archetypesData.id],
|
|
526
|
-
set: {
|
|
539
|
+
|
|
540
|
+
await db
|
|
541
|
+
.insert(schema.archetypesData)
|
|
542
|
+
.values({
|
|
543
|
+
id: enId,
|
|
544
|
+
combination,
|
|
545
|
+
gender,
|
|
546
|
+
archetypeIndex: index,
|
|
547
|
+
language: 'en-us',
|
|
527
548
|
name: englishEntry.name,
|
|
528
549
|
essenceLine: englishEntry.essenceLine,
|
|
529
|
-
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
550
|
+
status: 'idle',
|
|
551
|
+
})
|
|
552
|
+
.onConflictDoUpdate({
|
|
553
|
+
target: [schema.archetypesData.id],
|
|
554
|
+
set: {
|
|
555
|
+
name: englishEntry.name,
|
|
556
|
+
essenceLine: englishEntry.essenceLine,
|
|
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',
|
|
545
569
|
name: ptName,
|
|
546
570
|
essenceLine: ptEntry.essenceLine,
|
|
547
|
-
|
|
548
|
-
}
|
|
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
|
+
}
|
|
669
|
+
|
|
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(),
|
|
549
712
|
});
|
|
550
|
-
|
|
551
|
-
|
|
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: {
|
|
780
|
+
name: ptName,
|
|
781
|
+
essenceLine: ptEntry.essenceLine,
|
|
782
|
+
updatedAt: new Date().getTime(),
|
|
783
|
+
},
|
|
784
|
+
});
|
|
785
|
+
|
|
786
|
+
console.log(
|
|
787
|
+
`✅ [Batch] Saved archetype ${index} (${gender}) for ${combination}`
|
|
788
|
+
);
|
|
552
789
|
}
|
|
553
790
|
}
|
|
554
|
-
|
|
791
|
+
|
|
555
792
|
console.log(`🏁 [Batch] Finished combination: ${combination}`);
|
|
556
793
|
}
|
|
557
|
-
|
|
558
|
-
console.log(
|
|
794
|
+
|
|
795
|
+
console.log(
|
|
796
|
+
`🎉 [Batch] Completed regenerating ${compositions.length} combinations`
|
|
797
|
+
);
|
|
559
798
|
}
|
|
560
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
|
}
|