@zodic/shared 0.0.370 → 0.0.372

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.
@@ -340,14 +340,14 @@ export class ConceptService {
340
340
  override: boolean = false
341
341
  ): Promise<{ generatedPrompt: string }> {
342
342
  console.log(
343
- `🚀 Generating Leonardo prompt for concept: ${conceptSlug}, combination: ${combinationString}, override: ${override}`
343
+ `[${new Date().toISOString()}] 🚀 Generating Leonardo prompt for concept: ${conceptSlug}, combination: ${combinationString}, override: ${override}`
344
344
  );
345
345
 
346
346
  const db = drizzle(this.context.env.DB); // ✅ Initialize Drizzle with Cloudflare D1
347
347
 
348
348
  // ✅ Fetch concept data from D1 for both languages
349
349
  console.log(
350
- `📡 Fetching concept data for ${conceptSlug}:${combinationString}`
350
+ `[${new Date().toISOString()}] 📡 Fetching concept data for ${conceptSlug}:${combinationString}`
351
351
  );
352
352
 
353
353
  const conceptEntries = await db
@@ -382,12 +382,18 @@ export class ConceptService {
382
382
  throw new Error(`❌ Could not find both EN and PT versions.`);
383
383
  }
384
384
 
385
+ const leonardoPromptExistsEN =
386
+ conceptEN.leonardoPrompt && conceptEN.leonardoPrompt.length > 4;
387
+
388
+ const leonardoPromptExistsPT =
389
+ conceptPT.leonardoPrompt && conceptPT.leonardoPrompt.length > 4;
390
+
385
391
  // ✅ Check if prompt already exists and skip if override is false
386
- if (!override && conceptEN.leonardoPrompt && conceptPT.leonardoPrompt) {
392
+ if (!override && leonardoPromptExistsEN && leonardoPromptExistsPT) {
387
393
  console.log(
388
- `⚡ Leonardo prompt already exists for ${conceptSlug}, skipping.`
394
+ `[${new Date().toISOString()}] ⚡ Leonardo prompt already exists for ${conceptSlug}, skipping.`
389
395
  );
390
- return { generatedPrompt: conceptEN.leonardoPrompt };
396
+ return { generatedPrompt: conceptEN.leonardoPrompt! };
391
397
  }
392
398
 
393
399
  // ✅ Ensure basic info is present
@@ -420,11 +426,30 @@ export class ConceptService {
420
426
  );
421
427
  }
422
428
 
423
- const generatedPrompt = response.trim();
429
+ // Clean the response to remove unwanted elements
430
+ let generatedPrompt = response.trim();
431
+
432
+ // Step 1: Remove **Prompt:** or Prompt: from the start
433
+ generatedPrompt = generatedPrompt.replace(
434
+ /^(?:\*\*Prompt:\*\*|Prompt:)\s*/,
435
+ ''
436
+ );
437
+
438
+ // Step 2: Remove character count suffix (e.g., *(Character count: 749)* or *(1498 characters)*)
439
+ generatedPrompt = generatedPrompt.replace(/\s*\*\([^()]*\)*\s*$/, '');
440
+
441
+ // Step 3: Remove surrounding quotes if they wrap the entire prompt
442
+ if (generatedPrompt.startsWith('"') && generatedPrompt.endsWith('"')) {
443
+ generatedPrompt = generatedPrompt.slice(1, -1).trim();
444
+ }
445
+
446
+ console.log(
447
+ `[${new Date().toISOString()}] ✨ Cleaned generated prompt: "${generatedPrompt}"`
448
+ );
424
449
 
425
450
  // ✅ Store the generated prompt in D1 for both languages
426
451
  console.log(
427
- `💾 Storing Leonardo prompt for ${conceptSlug}:${combinationString} in D1...`
452
+ `[${new Date().toISOString()}] 💾 Storing Leonardo prompt for ${conceptSlug}:${combinationString} in D1...`
428
453
  );
429
454
  await db.batch([
430
455
  db
@@ -448,7 +473,7 @@ export class ConceptService {
448
473
  ]);
449
474
 
450
475
  console.log(
451
- `✅ Leonardo prompt stored for concept: ${conceptSlug}, combination: ${combinationString}, in both languages.`
476
+ `[${new Date().toISOString()}] ✅ Leonardo prompt stored for concept: ${conceptSlug}, combination: ${combinationString}, in both languages.`
452
477
  );
453
478
 
454
479
  return { generatedPrompt };
@@ -1801,41 +1826,44 @@ export class ConceptService {
1801
1826
  .limit(1)
1802
1827
  .execute();
1803
1828
 
1804
- return !!conceptData?.leonardoPrompt && conceptData.leonardoPrompt.length > 10;
1829
+ return (
1830
+ !!conceptData?.leonardoPrompt && conceptData.leonardoPrompt.length > 10
1831
+ );
1805
1832
  }
1806
1833
 
1807
- // src/services/ConceptService.ts
1808
- async checkConceptCompletion(
1809
- conceptSlug: Concept,
1810
- combinationString: string,
1811
- lang: string = 'en-us'
1812
- ): Promise<boolean> {
1813
- const db = this.context.drizzle();
1814
- const [conceptData] = await db
1815
- .select({
1816
- leonardoPrompt: schema.conceptsData.leonardoPrompt,
1817
- postImages: schema.conceptsData.postImages,
1818
- reelImages: schema.conceptsData.reelImages,
1819
- })
1820
- .from(schema.conceptsData)
1821
- .where(
1822
- and(
1823
- eq(schema.conceptsData.conceptSlug, conceptSlug),
1824
- eq(schema.conceptsData.combination, combinationString),
1825
- eq(schema.conceptsData.language, lang)
1834
+ // src/services/ConceptService.ts
1835
+ async checkConceptCompletion(
1836
+ conceptSlug: Concept,
1837
+ combinationString: string,
1838
+ lang: string = 'en-us'
1839
+ ): Promise<boolean> {
1840
+ const db = this.context.drizzle();
1841
+ const [conceptData] = await db
1842
+ .select({
1843
+ leonardoPrompt: schema.conceptsData.leonardoPrompt,
1844
+ postImages: schema.conceptsData.postImages,
1845
+ reelImages: schema.conceptsData.reelImages,
1846
+ })
1847
+ .from(schema.conceptsData)
1848
+ .where(
1849
+ and(
1850
+ eq(schema.conceptsData.conceptSlug, conceptSlug),
1851
+ eq(schema.conceptsData.combination, combinationString),
1852
+ eq(schema.conceptsData.language, lang)
1853
+ )
1826
1854
  )
1827
- )
1828
- .limit(1)
1829
- .execute();
1830
-
1831
- if (!conceptData) return false; // No concept data found
1855
+ .limit(1)
1856
+ .execute();
1832
1857
 
1833
- // Check if postImages and reelImages are valid non-empty JSON arrays
1834
- const hasPostImages =
1835
- conceptData.postImages &&
1836
- conceptData.postImages.trim().length > 4 && // Ensures length > 4 to exclude "[]"
1837
- JSON.parse(conceptData.postImages).length > 2;
1858
+ if (!conceptData) return false; // No concept data found
1859
+ const hasPrompt =
1860
+ !!conceptData?.leonardoPrompt && conceptData.leonardoPrompt.length > 10;
1861
+ // Check if postImages and reelImages are valid non-empty JSON arrays
1862
+ const hasPostImages =
1863
+ conceptData.postImages &&
1864
+ conceptData.postImages.trim().length > 4 && // Ensures length > 4 to exclude "[]"
1865
+ JSON.parse(conceptData.postImages).length > 2;
1838
1866
 
1839
- return !!conceptData.leonardoPrompt && !!hasPostImages;
1840
- }
1867
+ return hasPrompt && !!hasPostImages;
1868
+ }
1841
1869
  }
@@ -1,7 +1,9 @@
1
1
  import { inject, injectable } from 'inversify';
2
+ import { schema } from '../..';
2
3
  import { Concept } from '../../types';
3
4
  import { AppContext } from '../base';
4
5
  import { ConceptService } from '../services';
6
+ import { and, eq } from 'drizzle-orm';
5
7
 
6
8
  @injectable()
7
9
  export class ConceptWorkflow {
@@ -14,6 +16,7 @@ export class ConceptWorkflow {
14
16
  userId: string,
15
17
  conceptSlug: Concept,
16
18
  combinationString: string,
19
+ conceptCombinationId: string,
17
20
  lang: string = 'en-us'
18
21
  ) {
19
22
  console.log(
@@ -21,6 +24,26 @@ export class ConceptWorkflow {
21
24
  { userId, lang }
22
25
  );
23
26
 
27
+ const pendingGeneration = await this.context
28
+ .drizzle()
29
+ .select({ id: schema.generations.id })
30
+ .from(schema.generations)
31
+ .where(
32
+ and(
33
+ eq(schema.generations.conceptCombinationId, conceptCombinationId),
34
+ eq(schema.generations.status, 'pending')
35
+ )
36
+ )
37
+ .limit(1)
38
+ .execute();
39
+
40
+ if (pendingGeneration.length) {
41
+ console.log(
42
+ `[${new Date().toISOString()}] ⏳ Found pending generation for combination ${conceptCombinationId}`
43
+ );
44
+ return;
45
+ }
46
+
24
47
  try {
25
48
  // Step 1: Generate Leonardo prompt if missing
26
49
  const hasPrompt = await this.conceptService.checkHasPrompt(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zodic/shared",
3
- "version": "0.0.370",
3
+ "version": "0.0.372",
4
4
  "module": "index.ts",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -559,19 +559,15 @@ PT:
559
559
  `;
560
560
 
561
561
  export const PROMPT_GENERATE_CROWN_LEONARDO = `
562
- You are an expert creative writer specializing in crafting intricate and vivid prompts for AI image generation. Your task is to create a detailed, high-quality prompt for a majestic crown that symbolizes core identity, inner power, and essence. The design of the crown must reflect the symbolic traits of a given zodiac sign combination, but without directly mentioning zodiac signs or incorporating any animal-based descriptions.
563
- Describe the crown in exquisite detail, focusing on its materials, structure, symbolic engravings, and intricate patterns. Avoid references to animal figures, replacing them with celestial, geometric, alchemical, or elemental motifs that embody nobility and profound self-awareness. Highlight the type of light the crown reflects or emits, the way it rests atop its pedestal or bearer, and the aura of authority and grace it projects. Ensure the design elements convey dignity, individuality, and inner strength while maintaining an artistic and mystical tone.
564
- Include rendering details such as ‘ultra-realistic,’ ‘8K resolution,’ and ‘HDR’ to guide the AI model. Keep the description concise, under 1500 characters, ensuring it is structured for direct use in Leonardo.ai. Respond with a single descriptive paragraph based on the given zodiac sign combination.
562
+ You are an expert creative writer specializing in crafting intricate and vivid prompts for AI image generation. Your task is to create a detailed, high-quality prompt for a majestic crown that symbolizes core identity, inner power, and essence. The design must reflect the symbolic traits of a specific zodiac sign combination, without directly referencing zodiac signs or using animal-based imagery. Describe only the crown—avoid any depiction of heads, people, or additional objects. The background should be minimal yet evocative, enhancing the crown’s mystical presence without introducing unrelated elements. Focus on the crown’s materials, structure, symbolic engravings, and intricate patterns. Replace animal motifs with celestial, geometric, alchemical, or elemental symbols that evoke nobility and profound self-awareness. Describe the type of light the crown reflects or emits, and the aura of grace, power, and individuality it projects. Maintain a mystical and refined tone throughout. Include rendering cues such as “ultra-realistic,” “8K resolution,” and “HDR.” Ensure the final description is a single, elegant paragraph under 1500 characters, formatted with no labels or metadata—just the descriptive text for image generation.
565
563
  `;
566
564
 
567
565
  export const PROMPT_GENERATE_SCEPTER_LEONARDO = `
568
- You are an expert creative writer specializing in crafting intricate and vivid prompts for AI image generation. Your task is to create a detailed, high-quality prompt for a symbolic scepter that embodies external influence, action, and empowerment. The design of the scepter must reflect the symbolic traits of a given zodiac sign combination, but without directly mentioning zodiac signs or incorporating any animal-based descriptions.
569
- Describe the scepter in exquisite detail, focusing on its materials, structure, symbolic engravings, and artistic patterns. Avoid references to animal figures, replacing them with celestial, geometric, alchemical, or elemental motifs that convey its regal and commanding presence. Highlight how the scepter is held or displayed, the energy it radiates, and how its presence shapes the surrounding ambiance. Ensure the design elements reflect strength, authority, and purpose while maintaining an artistic and mystical tone.
570
- Include rendering details such as ‘ultra-realistic,’ ‘8K resolution,’ and ‘HDR’ to guide the AI model. Keep the description concise, under 1500 characters, ensuring it is structured for direct use in Leonardo.ai. Respond with a single descriptive paragraph based on the given zodiac sign combination.
566
+ You are an expert creative writer specializing in crafting intricate and vivid prompts for AI image generation. Your task is to create a detailed, high-quality prompt for a symbolic scepter that embodies external influence, action, and empowerment. The design must reflect the symbolic traits of a specific zodiac sign combination, without directly referencing zodiac signs or using animal-based imagery. Describe only the scepter—exclude hands, figures, or unrelated objects. The background should be visually appealing and thematically aligned with the scepter’s symbolism, incorporating mystical, celestial, or elemental elements that enhance its presence without overshadowing it. Focus on the scepter’s materials, structure, symbolic engravings, and artistic patterns. Replace animal motifs with celestial, geometric, alchemical, or elemental designs that convey strength, authority, and purpose. Highlight the energy it radiates and how it subtly shapes the surrounding ambiance. Maintain an artistic, regal, and mystical tone throughout. Include rendering cues like “ultra-realistic,” “8K resolution,” and “HDR.” Ensure the final output is a single descriptive paragraph under 1500 characters, with no titles, labels, or metadata—just the prompt for image generation.
571
567
  `;
572
568
 
573
569
  export const PROMPT_GENERATE_RING_LEONARDO = `
574
- You are an expert creative writer specializing in crafting intricate and vivid prompts for AI image generation. Your task is to create a detailed, high-quality prompt for a symbolic ring that embodies love and bonds. The design of the ring must reflect the mystical and fated nature of deep relationships, shaped by a given zodiac sign combination. Describe the ring in detail, including its materials, structure, engravings, and artistic patterns. Focus on capturing the essence of attraction, karmic ties, and emotional depth through meaningful motifs and elegant, symbolic elements, avoiding direct references to zodiac signs. Highlight the aura or glow the ring emanates, the emotions it evokes, and the way it would be worn as a symbol of fate and devotion. Ensure the design conveys a sense of destined connection, passion, and spiritual intimacy, while maintaining an artistic and mystical tone. Include artistic rendering details such as “ultra-realistic,” “8K resolution,” “HDR lighting,” and “intricate details” to guide the AI model. Keep the description concise, under 1500 characters, and ensure it can be used directly with Leonardo.ai for image generation. Respond with a single descriptive paragraph based on the given zodiac sign combination.
570
+ You are an expert creative writer specializing in crafting intricate and vivid prompts for AI image generation. Your task is to create a detailed, high-quality prompt for a symbolic ring that embodies love and bonds. The design of the ring must reflect the mystical and fated nature of deep relationships, shaped by a given zodiac sign combination. Describe the ring in detail, including its materials, structure, engravings, and artistic patterns. Focus on capturing the essence of attraction, karmic ties, and emotional depth through meaningful motifs and elegant, symbolic elements, avoiding direct references to zodiac signs. Highlight the aura or glow the ring emanates, the emotions it evokes, and the way it would be worn as a symbol of fate and devotion. Ensure the design conveys a sense of destined connection, passion, and spiritual intimacy, while maintaining an artistic and mystical tone. Include artistic rendering details such as “ultra-realistic,” “8K resolution,” “HDR lighting,” and “intricate details” to guide the AI model. Keep the description concise, under 1500 characters, and ensure it can be used directly with Leonardo.ai for image generation. Respond with a single descriptive paragraph based on the given zodiac sign combination. Ensure the final output is a single descriptive paragraph under 1500 characters, with no titles, labels, or metadata, just the prompt for image generation.
575
571
  `;
576
572
 
577
573
  export const PROMPT_GENERATE_AMULET_LEONARDO = `
@@ -589,5 +585,5 @@ Include rendering details such as ‘ultra-realistic,’ ‘8K resolution,’ an
589
585
  export const PROMPT_GENERATE_ORB_LEONARDO = `
590
586
  You are an expert creative writer specializing in crafting intricate and vivid prompts for AI image generation. Your task is to create a detailed, high-quality prompt for a mystical Orb that symbolizes destiny, purpose, and higher vision. The design of the Orb must reflect the symbolic traits of a given zodiac sign combination, but without directly mentioning zodiac signs or incorporating any animal-based descriptions.
591
587
  Describe the Orb in exquisite detail, focusing on its materials, structure, symbolic engravings, and artistic patterns. Avoid references to animal figures, replacing them with celestial, geometric, alchemical, or elemental motifs that evoke wisdom and transcendence. Highlight the Orb’s radiant energy, the depth of its swirling patterns, and how it is displayed—whether floating, resting on an ornate pedestal, or encased in a symbolic frame.
592
- Ensure the design elements convey mystery, enlightenment, and cosmic significance while maintaining an artistic and mystical tone. Include rendering details such as ‘ultra-realistic,’ ‘8K resolution,’ and ‘HDR’ to guide the AI model. Keep the description concise, under 1500 characters, ensuring it is structured for direct use in Leonardo.ai. Respond with a single descriptive paragraph based on the given zodiac sign combination.
588
+ Ensure the design elements convey mystery, enlightenment, and cosmic significance while maintaining an artistic and mystical tone. Include rendering details such as ‘ultra-realistic,’ ‘8K resolution,’ and ‘HDR’ to guide the AI model. Keep the description concise, under 1500 characters, ensuring it is structured for direct use in Leonardo.ai. Respond with a single descriptive paragraph based on the given zodiac sign combination. Ensure the final output is a single descriptive paragraph under 1500 characters, with no titles, labels, or metadata, just the prompt for image generation.
593
589
  `;
@@ -3,16 +3,16 @@ import { Concept } from '../types';
3
3
  export const leonardoInitImages: LeonardoInitImages = {
4
4
  concepts: {
5
5
  crown: {
6
- imageId: '450076a1-c6bb-4877-8a0b-c0d3ba72fca7',
6
+ imageId: '65081af2-eaf5-47b4-8f3f-d0255db28f58',
7
7
  imageUrl:
8
- 'https://cdn.leonardo.ai/users/b117a933-e5c9-45b2-96aa-4b619c2d74ba/initImages/450076a1-c6bb-4877-8a0b-c0d3ba72fca7.jpg',
8
+ 'https://cdn.leonardo.ai/users/b117a933-e5c9-45b2-96aa-4b619c2d74ba/initImages/65081af2-eaf5-47b4-8f3f-d0255db28f58.jpg',
9
9
  preprocessorId: 100,
10
10
  strengthType: 'Low',
11
11
  },
12
12
  scepter: {
13
- imageId: '744169ef-3db4-416d-86dd-9bd814e33432',
13
+ imageId: '7a448a58-5bec-44ce-8bc8-eca125d46794',
14
14
  imageUrl:
15
- 'https://cdn.leonardo.ai/users/b117a933-e5c9-45b2-96aa-4b619c2d74ba/initImages/744169ef-3db4-416d-86dd-9bd814e33432.jpg',
15
+ 'https://cdn.leonardo.ai/users/b117a933-e5c9-45b2-96aa-4b619c2d74ba/initImages/7a448a58-5bec-44ce-8bc8-eca125d46794.jpg',
16
16
  preprocessorId: 100,
17
17
  strengthType: 'Low',
18
18
  },
@@ -28,8 +28,8 @@ export const leonardoInitImages: LeonardoInitImages = {
28
28
  imageId: 'c489e496-00c4-4958-8bcd-4460a43a43bf',
29
29
  imageUrl:
30
30
  'https://cdn.leonardo.ai/users/b117a933-e5c9-45b2-96aa-4b619c2d74ba/initImages/c489e496-00c4-4958-8bcd-4460a43a43bf.jpg',
31
- preprocessorId: 19,
32
- weight: 0.3,
31
+ preprocessorId: 100,
32
+ strengthType: 'Low',
33
33
  },
34
34
  ring: {
35
35
  imageId: null,