@zodic/shared 0.0.293 → 0.0.295

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.
@@ -1,5 +1,8 @@
1
+ import { eq } from 'drizzle-orm';
1
2
  import { inject, injectable } from 'inversify';
2
- import { KVArchetype } from '../../types/scopes/legacy';
3
+ import { ChatMessages, schema } from '../..';
4
+ import { KVArchetype, ZodiacSignSlug } from '../../types/scopes/legacy';
5
+ import { generateArchetypePrompt } from '../../utils/archetypeNamesMessages';
3
6
  import { buildCosmicMirrorArchetypeKVKey } from '../../utils/KVKeysBuilders';
4
7
  import { AppContext } from '../base';
5
8
 
@@ -281,4 +284,240 @@ export class ArchetypeService {
281
284
  })
282
285
  );
283
286
  }
287
+
288
+ async generateArchetypeNames(
289
+ combination: string,
290
+ gender: 'male' | 'female' | 'non-binary',
291
+ overrideExisting: boolean = false
292
+ ) {
293
+ const [sun, ascendant, moon] = combination.split('-') as ZodiacSignSlug[];
294
+
295
+ const prompt = generateArchetypePrompt([{ sun, ascendant, moon }]);
296
+ const messages: ChatMessages = [
297
+ {
298
+ role: 'user',
299
+ content: prompt,
300
+ },
301
+ ];
302
+ const response = await this.context.api().callTogether.single(messages, {});
303
+
304
+ if (!response) {
305
+ throw new Error(
306
+ `No response when generating archetype names for ${combination}`
307
+ );
308
+ }
309
+
310
+ const blocks = response
311
+ .split('-EN')[1]
312
+ .split('-PT')[0]
313
+ .trim()
314
+ .split(/\n\d\.\s*\n?/)
315
+ .filter(Boolean);
316
+ const ptBlocks = response
317
+ .split('-PT')[1]
318
+ .trim()
319
+ .split(/\n\d\.\s*\n?/)
320
+ .filter(Boolean);
321
+
322
+ const englishNames = blocks.map((block) => {
323
+ const nameMatch = block.match(/• Name:\s*(.+)/);
324
+ const essenceMatch = block.match(/• Essence:\s*(.+)/);
325
+ return {
326
+ name: nameMatch?.[1]?.trim() || '',
327
+ essenceLine: essenceMatch?.[1]?.trim() || '',
328
+ };
329
+ });
330
+
331
+ const portugueseVariants = ptBlocks.map((block) => {
332
+ const masc = block.match(/• Masculino:\s*(.+)/)?.[1]?.trim() || '';
333
+ const fem = block.match(/• Feminino:\s*(.+)/)?.[1]?.trim() || '';
334
+ const essence = block.match(/• Essência:\s*(.+)/)?.[1]?.trim() || '';
335
+ return { masc, fem, essenceLine: essence };
336
+ });
337
+
338
+ const db = this.context.drizzle();
339
+
340
+ await Promise.all(
341
+ englishNames.map(async (entry, i) => {
342
+ const index = (i + 1).toString();
343
+ const existingEntry = await db
344
+ .select({ id: schema.archetypesData.id })
345
+ .from(schema.archetypesData)
346
+ .where(
347
+ eq(schema.archetypesData.id, `${combination}:${gender}:${index}`)
348
+ )
349
+ .execute();
350
+
351
+ if (overrideExisting || existingEntry.length === 0) {
352
+ await db
353
+ .insert(schema.archetypesData)
354
+ .values({
355
+ id: `${combination}:${gender}:${index}`,
356
+ combination,
357
+ gender,
358
+ archetypeIndex: index,
359
+ language: 'en-us',
360
+ name: entry.name,
361
+ essenceLine: entry.essenceLine,
362
+ status: 'idle',
363
+ })
364
+ .onConflictDoUpdate({
365
+ target: [schema.archetypesData.id],
366
+ set: {
367
+ name: entry.name,
368
+ essenceLine: entry.essenceLine,
369
+ updatedAt: new Date().getTime(),
370
+ },
371
+ });
372
+ }
373
+
374
+ const existingEntryPt = await db
375
+ .select({ id: schema.archetypesData.id })
376
+ .from(schema.archetypesData)
377
+ .where(
378
+ eq(schema.archetypesData.id, `${combination}:${gender}:${index}:pt`)
379
+ )
380
+ .execute();
381
+
382
+ if (overrideExisting || existingEntryPt.length === 0) {
383
+ await db
384
+ .insert(schema.archetypesData)
385
+ .values({
386
+ id: `${combination}:${gender}:${index}:pt`,
387
+ combination,
388
+ gender,
389
+ archetypeIndex: index,
390
+ language: 'pt-br',
391
+ name: portugueseVariants[i].masc,
392
+ essenceLine: portugueseVariants[i].essenceLine,
393
+ status: 'idle',
394
+ })
395
+ .onConflictDoUpdate({
396
+ target: [schema.archetypesData.id],
397
+ set: {
398
+ name: portugueseVariants[i].masc,
399
+ essenceLine: portugueseVariants[i].essenceLine,
400
+ updatedAt: new Date().getTime(),
401
+ },
402
+ });
403
+ }
404
+ })
405
+ );
406
+ }
407
+
408
+ async generateArchetypeNamesBatch(
409
+ entries: Array<{
410
+ combination: string;
411
+ gender: 'male' | 'female' | 'non-binary';
412
+ }>,
413
+ overrideExisting: boolean = false
414
+ ) {
415
+ const prompts = entries.map(({ combination }) => {
416
+ const [sun, ascendant, moon] = combination.split('-') as ZodiacSignSlug[];
417
+ return { sun, ascendant, moon };
418
+ });
419
+
420
+ const prompt = generateArchetypePrompt(prompts);
421
+ const messages: ChatMessages = [{ role: 'user', content: prompt }];
422
+ const response = await this.context.api().callTogether.single(messages, {});
423
+
424
+ if (!response)
425
+ throw new Error('No response when generating batch archetype names');
426
+
427
+ const db = this.context.drizzle();
428
+
429
+ const blocks = response
430
+ .split(/Composition \d+/)
431
+ .slice(1)
432
+ .map((b) => b.trim());
433
+
434
+ for (let i = 0; i < entries.length; i++) {
435
+ const { combination, gender } = entries[i];
436
+ const block = blocks[i];
437
+ const en = block.split('-EN')[1].split('-PT')[0].trim();
438
+ const pt = block.split('-PT')[1].trim();
439
+
440
+ const english = en
441
+ .split(/\n\d\.\s*\n?/)
442
+ .filter(Boolean)
443
+ .map((line) => ({
444
+ name: line.match(/• Name:\s*(.+)/)?.[1]?.trim() || '',
445
+ essenceLine: line.match(/• Essence:\s*(.+)/)?.[1]?.trim() || '',
446
+ }));
447
+
448
+ const portuguese = pt
449
+ .split(/\n\d\.\s*\n?/)
450
+ .filter(Boolean)
451
+ .map((line) => ({
452
+ masc: line.match(/• Masculino:\s*(.+)/)?.[1]?.trim() || '',
453
+ essenceLine: line.match(/• Essência:\s*(.+)/)?.[1]?.trim() || '',
454
+ }));
455
+
456
+ for (let j = 0; j < 3; j++) {
457
+ const index = (j + 1).toString();
458
+
459
+ const existingEntry = await db
460
+ .select({ id: schema.archetypesData.id })
461
+ .from(schema.archetypesData)
462
+ .where(
463
+ eq(schema.archetypesData.id, `${combination}:${gender}:${index}`)
464
+ )
465
+ .execute();
466
+
467
+ if (overrideExisting || existingEntry.length === 0) {
468
+ await db
469
+ .insert(schema.archetypesData)
470
+ .values({
471
+ id: `${combination}:${gender}:${index}`,
472
+ combination,
473
+ gender,
474
+ archetypeIndex: index,
475
+ language: 'en-us',
476
+ name: english[j].name,
477
+ essenceLine: english[j].essenceLine,
478
+ status: 'idle',
479
+ })
480
+ .onConflictDoUpdate({
481
+ target: [schema.archetypesData.id],
482
+ set: {
483
+ name: english[j].name,
484
+ essenceLine: english[j].essenceLine,
485
+ updatedAt: new Date().getTime(),
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
+ });
519
+ }
520
+ }
521
+ }
522
+ }
284
523
  }
@@ -87,6 +87,33 @@ export class ArchetypeWorkflow {
87
87
  };
88
88
  }
89
89
 
90
+ async generateNames({
91
+ combinations,
92
+ gender,
93
+ overrideExisting,
94
+ }: {
95
+ combinations: string[];
96
+ gender: Gender;
97
+ overrideExisting?: boolean;
98
+ }): Promise<void> {
99
+ if (combinations.length === 0) return;
100
+
101
+ if (combinations.length === 1) {
102
+ await this.archetypeService.generateArchetypeNames(
103
+ combinations[0],
104
+ gender,
105
+ overrideExisting
106
+ );
107
+ } else {
108
+ const entries = combinations.map((combination) => ({
109
+ combination,
110
+ gender,
111
+ }));
112
+
113
+ await this.archetypeService.generateArchetypeNamesBatch(entries, overrideExisting);
114
+ }
115
+ }
116
+
90
117
  /**
91
118
  * Fetch all three archetypes from KV for a given combination and gender.
92
119
  */
@@ -0,0 +1,27 @@
1
+ PRAGMA foreign_keys=OFF;--> statement-breakpoint
2
+ CREATE TABLE `__new_archetypes_data` (
3
+ `id` text PRIMARY KEY NOT NULL,
4
+ `language` text NOT NULL,
5
+ `gender` text,
6
+ `combination` text NOT NULL,
7
+ `archetype_index` text NOT NULL,
8
+ `name` text NOT NULL,
9
+ `essence_line` text NOT NULL,
10
+ `description` text,
11
+ `content` text DEFAULT '[]' NOT NULL,
12
+ `virtues` text DEFAULT '[]' NOT NULL,
13
+ `leonardo_prompt` text,
14
+ `status` text DEFAULT 'idle',
15
+ `created_at` integer DEFAULT CURRENT_TIMESTAMP,
16
+ `images` text DEFAULT '[]' NOT NULL,
17
+ `updated_at` integer DEFAULT CURRENT_TIMESTAMP
18
+ );
19
+ --> statement-breakpoint
20
+ INSERT INTO `__new_archetypes_data`("id", "language", "gender", "combination", "archetype_index", "name", "essence_line", "description", "content", "virtues", "leonardo_prompt", "status", "created_at", "images", "updated_at") SELECT "id", "language", "gender", "combination", "archetype_index", "name", "essence_line", "description", "content", "virtues", "leonardo_prompt", "status", "created_at", "images", "updated_at" FROM `archetypes_data`;--> statement-breakpoint
21
+ DROP TABLE `archetypes_data`;--> statement-breakpoint
22
+ ALTER TABLE `__new_archetypes_data` RENAME TO `archetypes_data`;--> statement-breakpoint
23
+ PRAGMA foreign_keys=ON;--> statement-breakpoint
24
+ CREATE INDEX `archetypes_data_language_idx` ON `archetypes_data` (`language`);--> statement-breakpoint
25
+ CREATE INDEX `archetypes_data_combination_idx` ON `archetypes_data` (`combination`);--> statement-breakpoint
26
+ CREATE INDEX `archetypes_data_archetype_index_idx` ON `archetypes_data` (`archetype_index`);--> statement-breakpoint
27
+ CREATE INDEX `archetypes_data_gender_idx` ON `archetypes_data` (`gender`);