@nodaro/prompts 1.15.0 → 1.17.0

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/dist/index.js CHANGED
@@ -2717,9 +2717,9 @@ var PEOPLE = [
2717
2717
  { id: "bust-small", label: "Small", dimension: "bust", description: "Small bust", promptHint: "small bust", term: "small bust", adultOnly: true },
2718
2718
  { id: "bust-average", label: "Average", dimension: "bust", description: "Average bust", promptHint: "" },
2719
2719
  { id: "bust-full", label: "Full", dimension: "bust", description: "Full bust", promptHint: "full bust", term: "full bust", adultOnly: true },
2720
- { id: "bust-very-full", label: "Very Full", dimension: "bust", description: "Very full bust", promptHint: "very full bust", term: "very full bust", adultOnly: true },
2720
+ { id: "bust-very-full", label: "Very Full", dimension: "bust", description: "Very full bust", promptHint: "a fuller bust", term: "fuller bust", adultOnly: true },
2721
2721
  // ----- Waist -----
2722
- { id: "waist-defined", label: "Defined", dimension: "waist", description: "Defined, cinched waist", promptHint: "defined waist", term: "defined waist", adultOnly: true },
2722
+ { id: "waist-defined", label: "Defined", dimension: "waist", description: "Defined, cinched waist", promptHint: "a defined waistline", term: "defined waistline", adultOnly: true },
2723
2723
  { id: "waist-average", label: "Average", dimension: "waist", description: "Average waist", promptHint: "" },
2724
2724
  { id: "waist-straight", label: "Straight", dimension: "waist", description: "Straight, undefined waist", promptHint: "straight waistline", term: "straight waistline", adultOnly: true },
2725
2725
  // ----- Hips -----
@@ -2727,7 +2727,7 @@ var PEOPLE = [
2727
2727
  { id: "hips-balanced", label: "Balanced", dimension: "hips", description: "Balanced hips", promptHint: "" },
2728
2728
  { id: "hips-wide", label: "Wide", dimension: "hips", description: "Wide hips", promptHint: "wide hips", term: "wide hips", adultOnly: true },
2729
2729
  // ----- Silhouette (overall body shape; optional, no neutral) -----
2730
- { id: "silhouette-hourglass", label: "Hourglass", dimension: "silhouette", description: "Balanced bust + hips, defined waist", promptHint: "hourglass silhouette", term: "hourglass silhouette", adultOnly: true },
2730
+ { id: "silhouette-hourglass", label: "Hourglass", dimension: "silhouette", description: "Balanced bust + hips, defined waist", promptHint: "an hourglass figure", term: "hourglass figure", adultOnly: true },
2731
2731
  { id: "silhouette-rectangular", label: "Rectangular", dimension: "silhouette", description: "Straight up-and-down silhouette", promptHint: "rectangular silhouette", term: "rectangular silhouette" },
2732
2732
  { id: "silhouette-pear", label: "Pear", dimension: "silhouette", description: "Hips wider than shoulders", promptHint: "pear-shaped silhouette", term: "pear-shaped silhouette", adultOnly: true },
2733
2733
  { id: "silhouette-inverted", label: "Inverted Triangle", dimension: "silhouette", description: "Broad shoulders, narrow hips", promptHint: "inverted-triangle silhouette", term: "inverted-triangle silhouette" },
@@ -2816,11 +2816,11 @@ var PEOPLE = [
2816
2816
  { id: "lips-small", label: "Small", dimension: "lip-shape", description: "Petite mouth", promptHint: "a small petite mouth", term: "small petite mouth" },
2817
2817
  // -------------------- Lip State (what the lips are doing / wearing) --------------------
2818
2818
  { id: "lip-state-chapped", label: "Chapped", dimension: "lip-state", description: "Cracked, dry, weather-worn lips", promptHint: "with chapped, cracked, weather-worn dry lips", term: "chapped dry lips" },
2819
- { id: "lip-state-glossy", label: "Glossy", dimension: "lip-state", description: "High-shine, wet-look lips", promptHint: "with high-shine glossy wet-look lips", term: "glossy wet-look lips", adultOnly: true },
2819
+ { id: "lip-state-glossy", label: "Glossy", dimension: "lip-state", description: "High-shine, wet-look lips", promptHint: "with a glossy lip finish", term: "glossy lips", adultOnly: true },
2820
2820
  { id: "lip-state-bare", label: "Bare", dimension: "lip-state", description: "Natural, untreated, no makeup", promptHint: "with bare, natural, untreated lips", term: "bare natural lips" },
2821
2821
  { id: "lip-state-bold-red", label: "Bold Red", dimension: "lip-state", description: "Saturated red lipstick statement", promptHint: "with a bold, saturated red lipstick statement", term: "bold red lipstick" },
2822
- { id: "lip-state-bitten", label: "Bitten", dimension: "lip-state", description: "Slight playful lip-bite, lower lip caught", promptHint: "playfully biting the lower lip", term: "biting the lower lip", adultOnly: true },
2823
- { id: "lip-state-parted", label: "Parted", dimension: "lip-state", description: "Lips slightly parted, breath of air", promptHint: "with lips slightly parted, taking a soft breath", term: "lips slightly parted", adultOnly: true },
2822
+ { id: "lip-state-bitten", label: "Bitten", dimension: "lip-state", description: "Slight playful lip-bite, lower lip caught", promptHint: "lightly biting the lower lip", term: "biting lower lip", adultOnly: true },
2823
+ { id: "lip-state-parted", label: "Parted", dimension: "lip-state", description: "Lips slightly parted, breath of air", promptHint: "with lips relaxed and slightly open, as if mid-sentence", term: "lips slightly open", adultOnly: true },
2824
2824
  { id: "lip-state-pursed", label: "Pursed", dimension: "lip-state", description: "Lips pressed and pushed forward", promptHint: "with lips pursed, pressed and pushed forward", term: "pursed lips" },
2825
2825
  { id: "lip-state-bold-black", label: "Bold Black", dimension: "lip-state", description: "Saturated black lipstick statement (goth / avant-garde)", promptHint: "with a bold, saturated black lipstick statement, goth / avant-garde", term: "bold black lipstick" },
2826
2826
  { id: "lip-state-burgundy", label: "Burgundy", dimension: "lip-state", description: "Deep wine-red lipstick", promptHint: "with deep wine-red burgundy lipstick", term: "burgundy lipstick" },
@@ -2933,9 +2933,9 @@ var PEOPLE = [
2933
2933
  { id: "eyes-black", label: "Black", dimension: "eye-color", description: "Truly black iris (deeper than brown)", promptHint: "jet-black eyes with a truly black iris, deeper than brown", term: "jet-black eyes" },
2934
2934
  // -------------------- Eye State (what the eyes are doing / where they look) --------------------
2935
2935
  { id: "eye-state-closed", label: "Closed", dimension: "eye-state", description: "Eyes fully closed, peaceful", promptHint: "with eyes fully closed in a peaceful expression", term: "eyes fully closed" },
2936
- { id: "eye-state-half-lidded", label: "Half-lidded", dimension: "eye-state", description: "Heavy-lidded sleepy gaze", promptHint: "with heavy half-lidded sleepy eyes", term: "half-lidded sleepy eyes", adultOnly: true },
2936
+ { id: "eye-state-half-lidded", label: "Half-lidded", dimension: "eye-state", description: "Heavy-lidded sleepy gaze", promptHint: "with drowsy, partly closed eyes, the lids sitting low over the iris", term: "drowsy, partly closed eyes", adultOnly: true },
2937
2937
  { id: "eye-state-wide-eyed", label: "Wide-eyed", dimension: "eye-state", description: "Eyes wide open, alert / surprised", promptHint: "with eyes wide open, alert and surprised" },
2938
- { id: "eye-state-staring-camera", label: "Staring at Camera", dimension: "eye-state", description: "Direct unbroken eye contact with the lens", promptHint: "staring directly at the camera with unbroken eye contact" },
2938
+ { id: "eye-state-staring-camera", label: "Staring at Camera", dimension: "eye-state", description: "Direct unbroken eye contact with the lens", promptHint: "looking directly into the camera", term: "direct gaze to camera" },
2939
2939
  { id: "eye-state-gazing-away", label: "Gazing Away", dimension: "eye-state", description: "Looking off-camera, contemplative", promptHint: "gazing off-camera with a contemplative expression", term: "gazing off-camera" },
2940
2940
  { id: "eye-state-gazing-up", label: "Gazing Up", dimension: "eye-state", description: "Eyes raised toward something above", promptHint: "with eyes gazing upward toward something above" },
2941
2941
  { id: "eye-state-gazing-down", label: "Gazing Down", dimension: "eye-state", description: "Eyes downcast", promptHint: "with eyes downcast, gazing softly downward" },
@@ -2952,8 +2952,8 @@ var PEOPLE = [
2952
2952
  { id: "texture-smooth", label: "Smooth", dimension: "skin-texture", description: "Flawless, silky smooth skin", promptHint: "with flawless, silky smooth skin", term: "flawless smooth skin" },
2953
2953
  { id: "texture-wrinkled", label: "Wrinkled", dimension: "skin-texture", description: "Aged, deeply lined skin", promptHint: "with deep wrinkles and aged skin texture", term: "deeply wrinkled aged skin" },
2954
2954
  { id: "texture-goosebumps", label: "Goosebumps", dimension: "skin-texture", description: "Raised goosebumps on skin", promptHint: "with goosebumps raised on the skin" },
2955
- { id: "texture-dewy", label: "Dewy", dimension: "skin-texture", description: "Glowing, dewy fresh skin", promptHint: "with dewy, glowing skin and a fresh sheen", term: "dewy glowing skin" },
2956
- { id: "texture-glistening", label: "Glistening", dimension: "skin-texture", description: "Sweat or oil sheen", promptHint: "with glistening skin, sweat or oil catching the light", term: "glistening skin", adultOnly: true },
2955
+ { id: "texture-dewy", label: "Dewy", dimension: "skin-texture", description: "Glowing, dewy fresh skin", promptHint: "with dewy, luminous skin", term: "dewy skin" },
2956
+ { id: "texture-glistening", label: "Glistening", dimension: "skin-texture", description: "Sweat or oil sheen", promptHint: "with a light glistening sheen on the skin", term: "glistening sheen", adultOnly: true },
2957
2957
  { id: "texture-weathered", label: "Weathered", dimension: "skin-texture", description: "Sun-aged rough skin", promptHint: "with weathered, sun-worn rough skin", term: "weathered sun-worn skin" },
2958
2958
  { id: "texture-porcelain", label: "Porcelain", dimension: "skin-texture", description: "Flawless near-translucent porcelain", promptHint: "with flawless, near-translucent porcelain skin", term: "porcelain skin" },
2959
2959
  { id: "texture-sun-kissed", label: "Sun-kissed", dimension: "skin-texture", description: "Warm tan with healthy glow", promptHint: "with sun-kissed skin, warmly tanned with a healthy glow", term: "sun-kissed skin" },
@@ -2965,8 +2965,8 @@ var PEOPLE = [
2965
2965
  { id: "texture-oily", label: "Oily / Shiny", dimension: "skin-texture", description: "Slight oil sheen on T-zone", promptHint: "with a slight oily sheen across the T-zone", term: "oily shiny skin", adultOnly: true },
2966
2966
  { id: "texture-matte", label: "Matte", dimension: "skin-texture", description: "Poreless matte finish", promptHint: "with a poreless, matte skin finish", term: "matte skin finish" },
2967
2967
  { id: "texture-blemished", label: "Blemished", dimension: "skin-texture", description: "Visible blemishes, real-skin imperfections", promptHint: "with visible blemishes and natural real-skin imperfections", term: "blemished skin" },
2968
- { id: "texture-baby-soft", label: "Baby-soft", dimension: "skin-texture", description: "Smooth, fine-pored youthful skin", promptHint: "with baby-soft, fine-pored, youthful smooth skin", term: "baby-soft skin" },
2969
- { id: "texture-shower-fresh-wet", label: "Shower-Fresh Wet", dimension: "skin-texture", description: "Just-out-of-shower wet skin with water beads", promptHint: "with just-out-of-the-shower wet skin, water beading on the surface and rolling in slow droplets down the curves of the body", term: "shower-fresh wet skin", adultOnly: true },
2968
+ { id: "texture-baby-soft", label: "Baby-soft", dimension: "skin-texture", description: "Smooth, fine-pored youthful skin", promptHint: "with soft, fine-pored skin", term: "soft fine-pored skin" },
2969
+ { id: "texture-shower-fresh-wet", label: "Shower-Fresh Wet", dimension: "skin-texture", description: "Just-out-of-shower wet skin with water beads", promptHint: "with fresh, water-dappled skin as if just out of the shower", term: "water-dappled skin", adultOnly: true },
2970
2970
  { id: "texture-acne-scarred", label: "Acne-scarred", dimension: "skin-texture", description: "Visible acne scarring (distinct from blemished \u2014 healed scar pattern)", promptHint: "with visible acne scarring, healed pitted-skin texture and uneven surface from past breakouts", term: "acne-scarred skin" },
2971
2971
  // -------------------- Distinctive Features --------------------
2972
2972
  { id: "feature-glasses", label: "Glasses", dimension: "distinctive-features", description: "Wears glasses", promptHint: "wearing glasses", term: "wearing glasses" },
@@ -2995,9 +2995,9 @@ var PEOPLE = [
2995
2995
  { id: "feature-ear-piercings", label: "Ear Piercings", dimension: "distinctive-features", description: "Multiple stacked ear piercings (cartilage, helix, conch)", promptHint: "with multiple stacked ear piercings \u2014 cartilage, helix, and conch", term: "multiple stacked ear piercings" },
2996
2996
  { id: "feature-lip-piercing", label: "Lip Piercing", dimension: "distinctive-features", description: "Lip ring / labret stud", promptHint: "with a lip piercing, a small ring or labret stud at the lip" },
2997
2997
  { id: "feature-nostril-piercing", label: "Nostril Piercing", dimension: "distinctive-features", description: "Single nostril stud or ring", promptHint: "with a single nostril piercing, a small stud or ring at the nostril" },
2998
- { id: "feature-bare-shoulders", label: "Bare Shoulders", dimension: "distinctive-features", description: "Bare shoulders exposed", promptHint: "with bare shoulders exposed, the line of the collarbone and shoulder muscles uncovered", adultOnly: true },
2999
- { id: "feature-collarbone-visible", label: "Collarbone Visible", dimension: "distinctive-features", description: "Prominent collarbone catching light", promptHint: "with a prominent collarbone clearly defined and catching the light", term: "visible collarbone", adultOnly: true },
3000
- { id: "feature-midriff-visible", label: "Midriff Visible", dimension: "distinctive-features", description: "Exposed midriff between top and bottom", promptHint: "wearing a cropped style with the midriff visible", term: "visible midriff", adultOnly: true },
2998
+ { id: "feature-bare-shoulders", label: "Bare Shoulders", dimension: "distinctive-features", description: "Bare shoulders exposed", promptHint: "with the shoulders uncovered", term: "shoulders uncovered", adultOnly: true },
2999
+ { id: "feature-collarbone-visible", label: "Collarbone Visible", dimension: "distinctive-features", description: "Prominent collarbone catching light", promptHint: "with an open neckline that leaves the collarbones uncovered", term: "open neckline, collarbones uncovered", adultOnly: true },
3000
+ { id: "feature-midriff-visible", label: "Midriff Visible", dimension: "distinctive-features", description: "Exposed midriff between top and bottom", promptHint: "with a cropped hemline", term: "cropped hemline", adultOnly: true },
3001
3001
  { id: "feature-navel-visible", label: "Navel Visible", dimension: "distinctive-features", description: "Visible navel on bare stomach", promptHint: "with the navel visible", term: "visible navel", adultOnly: true },
3002
3002
  { id: "feature-elongated-neck", label: "Elongated Neck", dimension: "distinctive-features", description: "Long swan-like neck", promptHint: "with an elongated, swan-like neck, long and gracefully extended", term: "elongated swan-like neck" },
3003
3003
  { id: "feature-under-eye-circles", label: "Under-Eye Circles", dimension: "distinctive-features", description: "Subtle dark circles under the eyes (distinct from puffy eye-bags)", promptHint: "with subtle dark circles under the eyes", term: "dark under-eye circles" },
@@ -3324,7 +3324,7 @@ function emitIndependentFragments(value, fragmentFor) {
3324
3324
  const navel = ids.includes("feature-navel-visible");
3325
3325
  for (const id of ids) {
3326
3326
  if (midriff && navel && (id === "feature-midriff-visible" || id === "feature-navel-visible")) {
3327
- if (id === "feature-midriff-visible" && fragmentFor(id) !== "") out.push("wearing a cropped style, midriff and navel visible");
3327
+ if (id === "feature-midriff-visible" && fragmentFor(id) !== "") out.push("with a cropped hemline and the navel showing");
3328
3328
  continue;
3329
3329
  }
3330
3330
  const fragment = fragmentFor(id);
@@ -3589,7 +3589,7 @@ var POSES = [
3589
3589
  { id: "throwing", label: "Throwing", category: "action", description: "Mid-throw motion", promptHint: "caught mid-throw, body coiled and releasing", term: "caught mid-throw" },
3590
3590
  { id: "leaping", label: "Leaping", category: "action", description: "Leaping forward dynamically", promptHint: "leaping forward dynamically with body extended" },
3591
3591
  { id: "dramatic-action", label: "Dramatic Action", category: "action", description: "Exaggerated action pose", promptHint: "in a dramatic, exaggerated action pose full of motion", term: "dramatic exaggerated action pose" },
3592
- { id: "biting-lip", label: "Biting Lip", category: "action", description: "Slight playful lip-bite", promptHint: "biting the lower lip with a subtle playful expression", term: "biting the lower lip", adultOnly: true },
3592
+ { id: "biting-lip", label: "Biting Lip", category: "action", description: "Slight playful lip-bite", promptHint: "lightly biting the lower lip, a subtle playful expression", term: "biting lower lip", adultOnly: true },
3593
3593
  { id: "mid-laugh", label: "Mid-Laugh", category: "action", description: "Caught mid-laugh, head back", promptHint: "caught mid-laugh with head tipped back, eyes crinkled" },
3594
3594
  { id: "pointing-at-camera", label: "Pointing at Camera", category: "action", description: "Pointing directly at camera", promptHint: "pointing one finger directly at the camera, arm extended", term: "pointing directly at the camera" },
3595
3595
  { id: "tongue-out", label: "Sticking Tongue Out", category: "action", description: "Playful tongue-out expression", promptHint: "sticking the tongue out playfully" },
@@ -4017,10 +4017,10 @@ var STYLINGS = [
4017
4017
  { id: "footwear-espadrilles", label: "Espadrilles", dimension: "footwear", description: "Woven jute-sole canvas summer shoe", promptHint: "in woven jute-sole espadrilles with a canvas upper, a casual summer shoe" },
4018
4018
  // -------------------- Wardrobe State (modifier — composes with any garment) --------------------
4019
4019
  { id: "state-oversized", label: "Oversized", dimension: "wardrobe-state", description: "Loose, oversized fit", promptHint: "the clothing loose and oversized, draping freely well past the body", term: "oversized fit" },
4020
- { id: "state-fitted", label: "Fitted", dimension: "wardrobe-state", description: "Form-fitting silhouette", promptHint: "the clothing fitted and form-conscious, hugging the contours of the body", term: "form-fitting clothing", adultOnly: true },
4020
+ { id: "state-fitted", label: "Fitted", dimension: "wardrobe-state", description: "Form-fitting silhouette", promptHint: "tailored, close-fitting clothing", term: "close-fitting clothing", adultOnly: true },
4021
4021
  { id: "state-cropped", label: "Cropped", dimension: "wardrobe-state", description: "Top cropped at midriff", promptHint: "the top cropped above the midriff with the stomach visible", term: "cropped top", adultOnly: true },
4022
4022
  { id: "state-sheer", label: "Sheer", dimension: "wardrobe-state", description: "Translucent fabric", promptHint: "the fabric translucent and sheer, hinting at the silhouette underneath", term: "sheer clothing", adultOnly: true },
4023
- { id: "state-wet", label: "Wet", dimension: "wardrobe-state", description: "Soaked, water-clinging", promptHint: "the clothing soaked and wet, the fabric clinging to the body and dripping water", term: "wet clothing", adultOnly: true },
4023
+ { id: "state-wet", label: "Wet", dimension: "wardrobe-state", description: "Soaked, water-clinging", promptHint: "the clothing soaked through and dripping", term: "soaked clothing", adultOnly: true },
4024
4024
  { id: "state-ripped", label: "Ripped", dimension: "wardrobe-state", description: "Torn and frayed", promptHint: "the fabric torn and ripped at the seams, with frayed edges", term: "ripped clothing" },
4025
4025
  { id: "state-distressed", label: "Distressed", dimension: "wardrobe-state", description: "Worn, faded, weathered", promptHint: "the clothing distressed and weathered, with faded color and worn-down edges", term: "distressed clothing" },
4026
4026
  { id: "state-vintage", label: "Vintage", dimension: "wardrobe-state", description: "Worn, retro character", promptHint: "the clothing carrying vintage character \u2014 softened color, broken-in fit, retro silhouette", term: "vintage clothing" },
@@ -4130,16 +4130,23 @@ function collectStylingFragments(data, fragmentFor) {
4130
4130
  const boldRedAlready = Array.isArray(lipStateRaw) ? lipStateRaw.includes("lip-state-bold-red") : lipStateRaw === "lip-state-bold-red";
4131
4131
  const floored = isMinorAge(data);
4132
4132
  const emit = floored ? (id) => getStyling(id)?.adultOnly === true ? "" : fragmentFor(id) : fragmentFor;
4133
+ const featureRaw = data.distinctiveFeature;
4134
+ const midriffPicked = Array.isArray(featureRaw) ? featureRaw.includes("feature-midriff-visible") : featureRaw === "feature-midriff-visible";
4135
+ const midriffAlready = midriffPicked && !floored;
4136
+ const cropTopPicked = data.top === "top-crop-top";
4137
+ const croppedSuppressed = (id) => id === "top-crop-top" && midriffAlready || id === "state-cropped" && (midriffAlready || cropTopPicked);
4133
4138
  for (const dimension of STYLING_DIMENSION_ORDER) {
4134
4139
  const field = STYLING_FIELD_BY_DIMENSION[dimension];
4135
4140
  const raw = data[field];
4136
4141
  if (dimension === "makeup" && boldRedAlready && raw === "makeup-bold-lips") continue;
4137
4142
  if (typeof raw === "string" && raw.length > 0) {
4143
+ if (croppedSuppressed(raw)) continue;
4138
4144
  const fragment = emit(raw);
4139
4145
  if (fragment) out.push(fragment);
4140
4146
  } else if (Array.isArray(raw)) {
4141
4147
  for (const item of raw) {
4142
4148
  if (typeof item !== "string" || item.length === 0) continue;
4149
+ if (croppedSuppressed(item)) continue;
4143
4150
  const fragment = emit(item);
4144
4151
  if (fragment) out.push(fragment);
4145
4152
  }
@@ -10335,32 +10342,6 @@ function resolveBrandInput(brand) {
10335
10342
  return brand;
10336
10343
  }
10337
10344
 
10338
- // src/prompt-templates.ts
10339
- var DEFAULT_TEMPLATES = {
10340
- "character-description": "Include character '{name}': {description}.",
10341
- "object-description": "Include object '{name}': {description}.",
10342
- "location-description": "Include location '{name}': {description}.",
10343
- "face-description": "Include the exact face and facial features of '{name}' from the reference image. Maintain perfect likeness and facial identity.",
10344
- // `-generation` templates drive standalone entity generation routes
10345
- // (`/v1/generate-character`, `/v1/generate-face`, etc.). Duplicated between
10346
- // frontend and backend historically; consolidated here so the backend DAG
10347
- // orchestrator produces the same prompt as a single-node HTTP call.
10348
- "character-generation": "Create a full-body character portrait: {description}. Style: {style}. Gender: {gender}. High quality, detailed, consistent lighting, neutral background.",
10349
- "object-generation": "Create a product photo of: {description}. Category: {category}. Clean background, professional studio lighting, high detail.",
10350
- "location-generation": "Create a cinematic scene of: {description}. Category: {category}. Atmospheric lighting, high detail, wide angle.",
10351
- "face-generation": "Create a professional close-up face portrait headshot: {description}. Style: {style}. Looking directly at camera, sharp focus on facial features, clean background, studio lighting, high resolution. Maintain exact facial identity and features from the reference image.",
10352
- "generate-image-wrapper": "{userPrompt}\n{assetDescriptions}"
10353
- };
10354
- function resolveTemplate(key, userTemplates, flowTemplates) {
10355
- return flowTemplates?.[key] ?? userTemplates?.[key] ?? DEFAULT_TEMPLATES[key] ?? "";
10356
- }
10357
- function applyTemplate(template, vars) {
10358
- return Object.entries(vars).reduce(
10359
- (result, [key, value]) => result.replaceAll(`{${key}}`, value || ""),
10360
- template
10361
- );
10362
- }
10363
-
10364
10345
  // src/prompt-hint-join.ts
10365
10346
  var PROMPT_HINT_SEPARATOR = ". ";
10366
10347
  function joinPromptHints(userPrompt, hints) {
@@ -10572,6 +10553,87 @@ function sectionedClauseCosts(userPrompt, clauses, structuredFragment) {
10572
10553
  }
10573
10554
  return costs;
10574
10555
  }
10556
+
10557
+ // src/described-references.ts
10558
+ var CHARACTER_BLOCK_HEADER = "Use these characters:";
10559
+ function referenceDescriptionLine(subject, description) {
10560
+ const s = subject.trim();
10561
+ const d = description?.trim();
10562
+ if (!s || !d) return "";
10563
+ return `${s} \u2014 ${d}.`;
10564
+ }
10565
+ function renderDescribedReferenceLines(refs) {
10566
+ if (!refs || refs.length === 0) return [];
10567
+ const lines = [];
10568
+ const seen = /* @__PURE__ */ new Set();
10569
+ for (const r of refs) {
10570
+ const key = r.name?.trim().toLowerCase();
10571
+ if (!key || seen.has(key)) continue;
10572
+ const line = referenceDescriptionLine(r.name, r.description);
10573
+ if (!line) continue;
10574
+ seen.add(key);
10575
+ lines.push(line);
10576
+ }
10577
+ return lines;
10578
+ }
10579
+ function renderReferenceCaptionLines(videoCaptions, audioCaptions, counts) {
10580
+ const lines = [];
10581
+ const render = (captions, kind, cap) => {
10582
+ if (!captions) return;
10583
+ for (let i = 0; i < captions.length && i < cap; i++) {
10584
+ const text = captions[i]?.trim();
10585
+ if (!text) continue;
10586
+ lines.push(`@${kind}_${i + 1}: ${text}.`);
10587
+ }
10588
+ };
10589
+ render(videoCaptions, "video", counts.video);
10590
+ render(audioCaptions, "audio", counts.audio);
10591
+ return lines;
10592
+ }
10593
+ function appendReferenceLines(prompt, lines, format) {
10594
+ if (lines.length === 0) return prompt;
10595
+ if (format === "hybrid") return insertBeforeStyleSection(prompt, lines);
10596
+ const bullets = lines.map((l) => `- ${l}`).join("\n");
10597
+ if (prompt.startsWith(`${CHARACTER_BLOCK_HEADER}
10598
+ `)) {
10599
+ const splitIdx = prompt.indexOf("\n\n");
10600
+ if (splitIdx === -1) return `${prompt}
10601
+ ${bullets}`;
10602
+ return `${prompt.slice(0, splitIdx)}
10603
+ ${bullets}${prompt.slice(splitIdx)}`;
10604
+ }
10605
+ const block = `${CHARACTER_BLOCK_HEADER}
10606
+ ${bullets}`;
10607
+ return prompt ? `${block}
10608
+
10609
+ ${prompt}` : block;
10610
+ }
10611
+
10612
+ // src/prompt-templates.ts
10613
+ var DEFAULT_TEMPLATES = {
10614
+ "character-description": "Include character '{name}': {description}.",
10615
+ "object-description": "Include object '{name}': {description}.",
10616
+ "location-description": "Include location '{name}': {description}.",
10617
+ "face-description": "Include the exact face and facial features of '{name}' from the reference image. Maintain perfect likeness and facial identity.",
10618
+ // `-generation` templates drive standalone entity generation routes
10619
+ // (`/v1/generate-character`, `/v1/generate-face`, etc.). Duplicated between
10620
+ // frontend and backend historically; consolidated here so the backend DAG
10621
+ // orchestrator produces the same prompt as a single-node HTTP call.
10622
+ "character-generation": "Create a full-body character portrait: {description}. Style: {style}. Gender: {gender}. High quality, detailed, consistent lighting, neutral background.",
10623
+ "object-generation": "Create a product photo of: {description}. Category: {category}. Clean background, professional studio lighting, high detail.",
10624
+ "location-generation": "Create a cinematic scene of: {description}. Category: {category}. Atmospheric lighting, high detail, wide angle.",
10625
+ "face-generation": "Create a professional close-up face portrait headshot: {description}. Style: {style}. Looking directly at camera, sharp focus on facial features, clean background, studio lighting, high resolution. Maintain exact facial identity and features from the reference image.",
10626
+ "generate-image-wrapper": "{userPrompt}\n{assetDescriptions}"
10627
+ };
10628
+ function resolveTemplate(key, userTemplates, flowTemplates) {
10629
+ return flowTemplates?.[key] ?? userTemplates?.[key] ?? DEFAULT_TEMPLATES[key] ?? "";
10630
+ }
10631
+ function applyTemplate(template, vars) {
10632
+ return Object.entries(vars).reduce(
10633
+ (result, [key, value]) => result.replaceAll(`{${key}}`, value || ""),
10634
+ template
10635
+ );
10636
+ }
10575
10637
  function composeIdentityDescPart(subject, canonicalDesc, elementInjection) {
10576
10638
  const parts = [];
10577
10639
  const c = canonicalDesc?.trim();
@@ -10580,6 +10642,10 @@ function composeIdentityDescPart(subject, canonicalDesc, elementInjection) {
10580
10642
  if (e) parts.push(e);
10581
10643
  return parts.length > 0 ? `${subject} \u2014 ${parts.join(". ")}` : subject;
10582
10644
  }
10645
+ function pushOverrideDirective(out, ref, binding) {
10646
+ const line = referenceDescriptionLine(binding, ref.descriptionOverride);
10647
+ if (line) out.push(line);
10648
+ }
10583
10649
  function resolveCharacterMentions(prompt, tokens, refs) {
10584
10650
  const bySlug = /* @__PURE__ */ new Map();
10585
10651
  const byVariant = /* @__PURE__ */ new Map();
@@ -10620,7 +10686,7 @@ function resolveCharacterMentions(prompt, tokens, refs) {
10620
10686
  const includeCanonicalDesc = effectiveMode === "identical" || effectiveMode === "face-pose";
10621
10687
  const descPart = composeIdentityDescPart(
10622
10688
  subject,
10623
- includeCanonicalDesc ? match.characterCanonicalDescription : void 0,
10689
+ match.descriptionOverride?.trim() || (includeCanonicalDesc ? match.characterCanonicalDescription : void 0),
10624
10690
  match.elementInjection
10625
10691
  );
10626
10692
  directiveLines.push(`- ${descPart}.${directive ? ` ${directive}` : ""}`);
@@ -10698,6 +10764,7 @@ function resolveCharacterMentionsHybrid(prompt, tokens, refs, existingUrls) {
10698
10764
  const binding = bindingFor(m.url);
10699
10765
  const lock = buildIdentityLockLine(withForcedIdentityLock(ref, lockOverrideByUrl.get(m.url)), binding);
10700
10766
  if (lock) lockLines.push(lock);
10767
+ pushOverrideDirective(elementDirectives, ref, binding);
10701
10768
  const inject = ref.elementInjection?.trim();
10702
10769
  if (inject) elementDirectives.push(inject);
10703
10770
  }
@@ -10771,7 +10838,8 @@ function resolveLocationMentions(prompt, tokens, refs) {
10771
10838
  const subject = `Image ${t.imageIndex} (${displayName})`;
10772
10839
  const includeCanonicalDesc = effectiveMode === "identical";
10773
10840
  const canonicalDesc = match.locationCanonicalDescription?.trim();
10774
- const descPart = includeCanonicalDesc && canonicalDesc ? `${subject} \u2014 ${canonicalDesc}` : subject;
10841
+ const shownDesc = match.descriptionOverride?.trim() || (includeCanonicalDesc ? canonicalDesc : void 0);
10842
+ const descPart = shownDesc ? `${subject} \u2014 ${shownDesc}` : subject;
10775
10843
  directiveLines.push(`- ${descPart}.${directive ? ` ${directive}` : ""}`);
10776
10844
  if (t.bucket && t.variant && match.locationVariantDisplayName && match.locationVariantDisplayName !== "canonical") {
10777
10845
  directiveLines.push(` (in this image: ${match.locationVariantDisplayName})`);
@@ -10839,6 +10907,7 @@ function resolveLocationMentionsHybrid(prompt, tokens, refs, existingUrls) {
10839
10907
  const binding = bindingFor(m.url);
10840
10908
  const lock = buildIdentityLockLine(withForcedIdentityLock(ref, lockOverrideByUrl.get(m.url)), binding);
10841
10909
  if (lock) lockLines.push(lock);
10910
+ pushOverrideDirective(elementDirectives, ref, binding);
10842
10911
  const inject = ref.elementInjection?.trim();
10843
10912
  if (inject) elementDirectives.push(inject);
10844
10913
  }
@@ -10888,10 +10957,11 @@ function resolveImageMentionsHybrid(prompt, tokens, refs, existingUrls) {
10888
10957
  const binding = bindingFor(m.url);
10889
10958
  const lock = buildIdentityLockLine(withForcedIdentityLock(ref, lockOverrideByUrl.get(m.url)), binding);
10890
10959
  if (lock) lockLines.push(lock);
10960
+ pushOverrideDirective(elementDirectives, ref, binding);
10891
10961
  const inject = ref.elementInjection?.trim();
10892
10962
  if (inject) elementDirectives.push(inject);
10893
10963
  }
10894
- return { prompt: resolvedPrompt, additionalUrls, lockLines, elementDirectives };
10964
+ return { prompt: resolvedPrompt, additionalUrls, mentionedUrls: seenUrls, lockLines, elementDirectives };
10895
10965
  }
10896
10966
  function resolveEntityMentionsHybrid(prompt, tokens, refs, existingUrls) {
10897
10967
  const bySlug = /* @__PURE__ */ new Map();
@@ -10942,6 +11012,7 @@ function resolveEntityMentionsHybrid(prompt, tokens, refs, existingUrls) {
10942
11012
  const binding = bindingFor(m.url);
10943
11013
  const lock = buildIdentityLockLine(withForcedIdentityLock(ref, lockOverrideByUrl.get(m.url)), binding);
10944
11014
  if (lock) lockLines.push(lock);
11015
+ pushOverrideDirective(elementDirectives, ref, binding);
10945
11016
  const inject = ref.elementInjection?.trim();
10946
11017
  if (inject) elementDirectives.push(inject);
10947
11018
  }
@@ -10977,7 +11048,7 @@ function buildCanonicalFallback(refs, mentionedSlugs, startIndex) {
10977
11048
  const subject = `Image ${cursor} (${displayName})`;
10978
11049
  const descPart = composeIdentityDescPart(
10979
11050
  subject,
10980
- includeCanonicalDesc ? r.characterCanonicalDescription : void 0,
11051
+ r.descriptionOverride?.trim() || (includeCanonicalDesc ? r.characterCanonicalDescription : void 0),
10981
11052
  r.elementInjection
10982
11053
  );
10983
11054
  directiveLines.push(`- ${descPart}.${directive ? ` ${directive}` : ""}`);
@@ -10993,7 +11064,7 @@ function buildExtraRefDirectives(refs, emittedCharacterPositions, startIndex) {
10993
11064
  for (const r of refs) {
10994
11065
  if (!r.isExtraRef) continue;
10995
11066
  if (!r.url) continue;
10996
- const description = (r.description ?? r.variantDescription ?? "").trim();
11067
+ const description = (r.descriptionOverride ?? "").trim() || (r.description ?? r.variantDescription ?? "").trim();
10997
11068
  if (r.source === "wired-character" && r.characterSlug) {
10998
11069
  const effectiveMode = r.defaultUsageMode ?? DEFAULT_USAGE_MODE;
10999
11070
  const earlierPos = positionsByChar.get(r.characterSlug);
@@ -11057,6 +11128,7 @@ function renderCanonicalFallbackHybrid(refs, letterForUrl) {
11057
11128
  phrases.push(roleToPhrase(resolveDefaultRole(r.defaultRole, r.defaultUsageMode, r.source), binding));
11058
11129
  const lock = buildIdentityLockLine(r, binding);
11059
11130
  if (lock) lockLines.push(lock);
11131
+ pushOverrideDirective(elementDirectives, r, binding);
11060
11132
  const inject = r.elementInjection?.trim();
11061
11133
  if (inject) elementDirectives.push(inject);
11062
11134
  }
@@ -11071,7 +11143,7 @@ function renderExtraRefsHybrid(extraRefs, letterForUrl, seedLetterByChar) {
11071
11143
  if (!r.url) continue;
11072
11144
  const letter = letterForUrl(r.url);
11073
11145
  const binding = `reference image ${letter}`;
11074
- const description = (r.description ?? r.variantDescription ?? "").trim();
11146
+ const description = (r.descriptionOverride ?? "").trim() || (r.description ?? r.variantDescription ?? "").trim();
11075
11147
  if (r.source === "wired-character" && r.characterSlug) {
11076
11148
  const earlier = firstLetterByChar.get(r.characterSlug);
11077
11149
  if (earlier !== void 0 && earlier !== letter) {
@@ -11108,10 +11180,11 @@ function renderLocationCanonicalHybrid(nonCharacterRefs, finalIndexByUrl, covere
11108
11180
  phrases.push(roleToPhrase(resolveLocationRole(null, null, r), binding));
11109
11181
  const lock = buildIdentityLockLine(r, binding);
11110
11182
  if (lock) lockLines.push(lock);
11183
+ pushOverrideDirective(elementDirectives, r, binding);
11111
11184
  const inject = r.elementInjection?.trim();
11112
11185
  if (inject) elementDirectives.push(inject);
11113
11186
  }
11114
- return { phrases, lockLines, elementDirectives };
11187
+ return { phrases, lockLines, elementDirectives, renderedUrls: seenUrls };
11115
11188
  }
11116
11189
  function renderObjectCreatureCanonicalHybrid(nonCharacterRefs, finalIndexByUrl, coveredUrls) {
11117
11190
  const phrases = [];
@@ -11128,10 +11201,24 @@ function renderObjectCreatureCanonicalHybrid(nonCharacterRefs, finalIndexByUrl,
11128
11201
  phrases.push(roleToPhrase(defaultRoleForSource(r.source), binding));
11129
11202
  const lock = buildIdentityLockLine(r, binding);
11130
11203
  if (lock) lockLines.push(lock);
11204
+ pushOverrideDirective(elementDirectives, r, binding);
11131
11205
  const inject = r.elementInjection?.trim();
11132
11206
  if (inject) elementDirectives.push(inject);
11133
11207
  }
11134
- return { phrases, lockLines, elementDirectives };
11208
+ return { phrases, lockLines, elementDirectives, renderedUrls: seenUrls };
11209
+ }
11210
+ function renderUntoldOverridesHybrid(nonCharacterRefs, finalIndexByUrl, toldUrls) {
11211
+ const lines = [];
11212
+ const sweptUrls = /* @__PURE__ */ new Set();
11213
+ for (const r of nonCharacterRefs) {
11214
+ if (!r.url || toldUrls.has(r.url) || sweptUrls.has(r.url)) continue;
11215
+ const slot = finalIndexByUrl.get(r.url);
11216
+ if (!slot) continue;
11217
+ const before = lines.length;
11218
+ pushOverrideDirective(lines, r, `reference image ${slotToLetter(slot)}`);
11219
+ if (lines.length > before) sweptUrls.add(r.url);
11220
+ }
11221
+ return lines;
11135
11222
  }
11136
11223
  function buildTileIdForUrl(urls, refs, prompt, sourceNodeIdById) {
11137
11224
  const knownSlugs = Array.from(
@@ -11304,8 +11391,10 @@ function buildImagePromptInternal(config2, marks) {
11304
11391
  );
11305
11392
  const suppressedCanonicalLocationIds = config2.suppressedCanonicalLocationIds ?? [];
11306
11393
  const isHybrid = config2.referenceFormat === "hybrid";
11394
+ const describedLines = renderDescribedReferenceLines(config2.describedReferences);
11307
11395
  let hybridBodyConverged = false;
11308
11396
  const mentionedEntityUrls = /* @__PURE__ */ new Set();
11397
+ const mentionedImageUrls = /* @__PURE__ */ new Set();
11309
11398
  if (config2.skipCharacterMentions) {
11310
11399
  config2 = {
11311
11400
  ...config2,
@@ -11423,6 +11512,7 @@ function buildImagePromptInternal(config2, marks) {
11423
11512
  resolved.additionalUrls = [...resolved.additionalUrls, ...hi.additionalUrls];
11424
11513
  hybridImageLockLines = hi.lockLines;
11425
11514
  hybridImageElementDirectives = hi.elementDirectives;
11515
+ for (const u of hi.mentionedUrls) mentionedImageUrls.add(u);
11426
11516
  if (hi.additionalUrls.length > 0) hybridBodyConverged = true;
11427
11517
  }
11428
11518
  }
@@ -11553,9 +11643,13 @@ ${promptForNext}`;
11553
11643
  referenceImageUrls = config2.referenceImageUrls || [];
11554
11644
  }
11555
11645
  }
11556
- if (connectedReferences) {
11646
+ if (connectedReferences || describedLines.length > 0) {
11647
+ const structuredRefs = connectedReferences ?? [];
11557
11648
  let prompt2 = config2.prompt;
11558
- const nonCharacterRefs = connectedReferences.filter(
11649
+ if (!isHybrid && describedLines.length > 0) {
11650
+ prompt2 = appendReferenceLines(prompt2, describedLines, "legacy");
11651
+ }
11652
+ const nonCharacterRefs = structuredRefs.filter(
11559
11653
  (r) => r.source !== "wired-character" && r.isExtraRef !== true
11560
11654
  );
11561
11655
  const nonCharacterUrls = nonCharacterRefs.map((r) => r.url).filter((u) => Boolean(u));
@@ -11585,11 +11679,23 @@ ${promptForNext}`;
11585
11679
  const canonLockBlock = canonLockLines.length > 0 ? `${canonLockLines.join("\n")}
11586
11680
 
11587
11681
  ` : "";
11682
+ const toldOverrideUrls = /* @__PURE__ */ new Set([
11683
+ ...locCanon.renderedUrls,
11684
+ ...objCanon.renderedUrls,
11685
+ ...mentionedEntityUrls,
11686
+ ...mentionedImageUrls
11687
+ ]);
11688
+ const untoldOverrides = renderUntoldOverridesHybrid(
11689
+ nonCharacterRefs,
11690
+ finalIndexByUrl,
11691
+ toldOverrideUrls
11692
+ );
11588
11693
  const canonTrailingLines = [
11589
11694
  ...locCanon.phrases,
11590
11695
  ...objCanon.phrases,
11591
11696
  ...locCanon.elementDirectives,
11592
- ...objCanon.elementDirectives
11697
+ ...objCanon.elementDirectives,
11698
+ ...untoldOverrides
11593
11699
  ];
11594
11700
  const composedScene = `${canonLockBlock}${insertBeforeStyleSection(scene, canonTrailingLines)}`;
11595
11701
  prompt2 = config2.referenceLockSnippet ? `${config2.referenceLockSnippet}
@@ -11616,6 +11722,9 @@ ${directives}`;
11616
11722
  }
11617
11723
  }
11618
11724
  }
11725
+ if (isHybrid && describedLines.length > 0) {
11726
+ prompt2 = appendReferenceLines(prompt2, describedLines, "hybrid");
11727
+ }
11619
11728
  const styleText2 = style?.trim();
11620
11729
  const styleLine2 = styleText2 && !isDeniedStyleId(styleText2) ? `Style: ${getStylePromptHint(styleText2) || styleText2}` : "";
11621
11730
  const negPrompt2 = negativePrompt?.trim();
@@ -11656,7 +11765,7 @@ ${directives}`;
11656
11765
  const reordered = applyReferenceOrder(
11657
11766
  assembledUrls,
11658
11767
  prompt2,
11659
- connectedReferences,
11768
+ structuredRefs,
11660
11769
  referenceOrder,
11661
11770
  sourceNodeIdById
11662
11771
  );
@@ -11781,7 +11890,10 @@ function collectIdentities(prompt, refs, meta3) {
11781
11890
  label,
11782
11891
  fidelity: m?.fidelity ?? defaultFidelityForSource(ref?.source),
11783
11892
  customText: m?.customText?.trim() || void 0,
11784
- description: ref?.description,
11893
+ // Per-use override ahead of the ref's own description; the directive
11894
+ // builder's location-canonical fallback only fires when BOTH are absent,
11895
+ // so an override outranks the stored location wording too.
11896
+ description: ref?.descriptionOverride?.trim() || ref?.description,
11785
11897
  source: ref?.source,
11786
11898
  locationCanonicalDescription: ref?.locationCanonicalDescription,
11787
11899
  locationSlug: ref?.locationSlug,
@@ -11889,7 +12001,7 @@ function buildNonCharacterDirectives(prompt, nonCharacterRefs, identityMeta, fin
11889
12001
  // wired-object falls through to the strict "match exactly" verb.
11890
12002
  label: ref.source === "wired-location" ? "location" : ref.source === "wired-creature" ? "creature" : "object",
11891
12003
  fidelity: defaultFidelityForSource(ref.source),
11892
- description: ref.description?.trim() || void 0,
12004
+ description: ref.descriptionOverride?.trim() || ref.description?.trim() || void 0,
11893
12005
  source: ref.source,
11894
12006
  locationCanonicalDescription: ref.locationCanonicalDescription,
11895
12007
  locationSlug: ref.locationSlug,
@@ -12416,6 +12528,8 @@ function resolveVideoCharacterMentionsHybrid(prompt, tokens, refs, offset) {
12416
12528
  const binding = bindingFor(m.url);
12417
12529
  const lock = buildIdentityLockLine(withForcedIdentityLock(ref, lockOverrideByUrl.get(m.url)), binding);
12418
12530
  if (lock) lockLines.push(lock);
12531
+ const overrideLine = referenceDescriptionLine(binding, ref.descriptionOverride);
12532
+ if (overrideLine) elementDirectives.push(overrideLine);
12419
12533
  const inject = ref.elementInjection?.trim();
12420
12534
  if (inject) elementDirectives.push(inject);
12421
12535
  }
@@ -12441,6 +12555,13 @@ function resolveVideoReferenceCore(args) {
12441
12555
  video: args.videoRefCount ?? 0,
12442
12556
  audio: args.audioRefCount ?? 0
12443
12557
  });
12558
+ const describedAndCaptionLines = [
12559
+ ...renderDescribedReferenceLines(args.describedReferences),
12560
+ ...renderReferenceCaptionLines(args.videoCaptions, args.audioCaptions, {
12561
+ video: args.videoRefCount ?? 0,
12562
+ audio: args.audioRefCount ?? 0
12563
+ })
12564
+ ];
12444
12565
  let wiredCharRefs = [...args.wiredCharRefs];
12445
12566
  const suppressedSlugs = new Set(args.suppressedCanonicalCharacterIds ?? []);
12446
12567
  if (suppressedSlugs.size > 0) {
@@ -12465,14 +12586,15 @@ function resolveVideoReferenceCore(args) {
12465
12586
  const slotByRefId = /* @__PURE__ */ new Map();
12466
12587
  if (wiredCharRefs.length === 0 && !hasExtras) {
12467
12588
  const counts = tokenCounts(leadingRefUrls.length);
12589
+ const resolved2 = resolveReferenceTokens(
12590
+ resolveRefIdTokens(args.prompt, { slotById: slotByRefId, nameById: nameByRefId, imageCount: counts.image }),
12591
+ counts
12592
+ );
12468
12593
  return {
12469
- // tokenCounts(leadingRefUrls.length) → image count == offset (no assets here):
12470
- // leadingRefUrls mode counts the leading refs; ordinalOffset mode counts the
12471
- // caller-owned leading refs the offset stands in for.
12472
- prompt: resolveReferenceTokens(
12473
- resolveRefIdTokens(args.prompt, { slotById: slotByRefId, nameById: nameByRefId, imageCount: counts.image }),
12474
- counts
12475
- ),
12594
+ // Described references and rail captions are the ONE thing this branch can
12595
+ // still contribute: they need no seat, so a request that carries only them
12596
+ // (a story landing before any entity exists) reaches the model here.
12597
+ prompt: describedAndCaptionLines.length > 0 ? appendReferenceLines(resolved2 ?? "", describedAndCaptionLines, args.hybridRoles === true ? "hybrid" : "legacy") : resolved2,
12476
12598
  additionalUrls: [...leadingRefUrls]
12477
12599
  };
12478
12600
  }
@@ -12530,6 +12652,8 @@ function resolveVideoReferenceCore(args) {
12530
12652
  canonicalPhrases.push(roleToPhrase(resolveDefaultRole(r.defaultRole, r.defaultUsageMode, r.source), binding));
12531
12653
  const lock = buildIdentityLockLine(r, binding);
12532
12654
  if (lock) canonicalLockLines.push(lock);
12655
+ const overrideLine = referenceDescriptionLine(binding, r.descriptionOverride);
12656
+ if (overrideLine) canonicalElementDirectives.push(overrideLine);
12533
12657
  const inject = r.elementInjection?.trim();
12534
12658
  if (inject) canonicalElementDirectives.push(inject);
12535
12659
  continue;
@@ -12546,7 +12670,10 @@ function resolveVideoReferenceCore(args) {
12546
12670
  const directive = usageModeDirective(effectiveMode);
12547
12671
  const includeCanonicalDesc = effectiveMode === "identical" || effectiveMode === "face-pose";
12548
12672
  const descBodyParts = [];
12549
- if (includeCanonicalDesc && r.characterCanonicalDescription?.trim()) {
12673
+ const canonicalOverride = r.descriptionOverride?.trim();
12674
+ if (canonicalOverride) {
12675
+ descBodyParts.push(canonicalOverride);
12676
+ } else if (includeCanonicalDesc && r.characterCanonicalDescription?.trim()) {
12550
12677
  descBodyParts.push(r.characterCanonicalDescription.trim());
12551
12678
  }
12552
12679
  if (r.elementInjection?.trim()) descBodyParts.push(r.elementInjection.trim());
@@ -12563,7 +12690,7 @@ function resolveVideoReferenceCore(args) {
12563
12690
  if (!ex.url) continue;
12564
12691
  position += 1;
12565
12692
  if (ex.id && !slotByRefId.has(ex.id)) slotByRefId.set(ex.id, position);
12566
- const desc = (ex.description ?? "").trim();
12693
+ const desc = (ex.descriptionOverride ?? "").trim() || (ex.description ?? "").trim();
12567
12694
  if (ex.characterSlug) {
12568
12695
  const meta3 = args.lookupCharacterBySlug?.(ex.characterSlug);
12569
12696
  const charDefaultMode = meta3?.defaultUsageMode;
@@ -12707,6 +12834,11 @@ ${finalPrompt}` : block;
12707
12834
  merged.push(u);
12708
12835
  }
12709
12836
  }
12837
+ finalPrompt = appendReferenceLines(
12838
+ finalPrompt,
12839
+ describedAndCaptionLines,
12840
+ hybrid ? "hybrid" : "legacy"
12841
+ );
12710
12842
  finalPrompt = resolveRefIdTokens(finalPrompt, {
12711
12843
  slotById: slotByRefId,
12712
12844
  nameById: nameByRefId,
@@ -12921,6 +13053,7 @@ function assembleImageInput(input) {
12921
13053
  prompt: composePromptText(input.userPrompt, pieces, keptHintClauses),
12922
13054
  provider: input.provider,
12923
13055
  ...input.connectedReferences !== void 0 ? { connectedReferences: input.connectedReferences } : {},
13056
+ ...input.describedReferences !== void 0 ? { describedReferences: input.describedReferences } : {},
12924
13057
  // Manual uploads / direct refs ride the builder's reference-URL channel so
12925
13058
  // the per-provider reference gate filters them alongside bound entities.
12926
13059
  // Omit the field entirely when absent so the builder's default ([]) kicks
@@ -13353,8 +13486,44 @@ function getAdultOnlyEntries() {
13353
13486
  function getAdultOnlyIds() {
13354
13487
  return new Set(getAdultOnlyEntries().map((e) => e.id));
13355
13488
  }
13489
+ var RETIRED_ADULT_ONLY_HINT_STRINGS = [
13490
+ // bust-very-full
13491
+ "very full bust",
13492
+ // silhouette-hourglass
13493
+ "hourglass silhouette",
13494
+ // waist-defined
13495
+ "defined waist",
13496
+ // lip-state-glossy
13497
+ "with high-shine glossy wet-look lips",
13498
+ // lip-state-parted
13499
+ "with lips slightly parted, taking a soft breath",
13500
+ // lip-state-bitten
13501
+ "playfully biting the lower lip",
13502
+ // eye-state-half-lidded
13503
+ "with heavy half-lidded sleepy eyes",
13504
+ // texture-glistening
13505
+ "with glistening skin, sweat or oil catching the light",
13506
+ // texture-shower-fresh-wet
13507
+ "with just-out-of-the-shower wet skin, water beading on the surface and rolling in slow droplets down the curves of the body",
13508
+ // feature-bare-shoulders
13509
+ "with bare shoulders exposed, the line of the collarbone and shoulder muscles uncovered",
13510
+ // feature-collarbone-visible
13511
+ "with a prominent collarbone clearly defined and catching the light",
13512
+ // feature-midriff-visible
13513
+ "wearing a cropped style with the midriff visible",
13514
+ // state-fitted — the 2026-07-30 incident clause
13515
+ "the clothing fitted and form-conscious, hugging the contours of the body",
13516
+ // state-wet
13517
+ "the clothing soaked and wet, the fabric clinging to the body and dripping water",
13518
+ // pose `biting-lip` (the lip-state-bitten twin)
13519
+ "biting the lower lip with a subtle playful expression",
13520
+ // the hard-coded midriff+navel fold in emitIndependentFragments — not any
13521
+ // entry's hint, so retiring it ADDS a needle for a clause that really is
13522
+ // emitted verbatim.
13523
+ "wearing a cropped style, midriff and navel visible"
13524
+ ];
13356
13525
  function getAdultOnlyHintStrings() {
13357
- const out = /* @__PURE__ */ new Set();
13526
+ const out = new Set(RETIRED_ADULT_ONLY_HINT_STRINGS);
13358
13527
  for (const e of getAdultOnlyEntries()) {
13359
13528
  if (e.promptHint) out.add(e.promptHint.toLowerCase());
13360
13529
  }
@@ -34593,6 +34762,6 @@ function buildSurroundFillPrompt(direction, userPrompt) {
34593
34762
  return `${scene}This is a partial frame: the ${carried} portion contains real, finished pixels and the ${painted} portion is flat gray that MUST be painted in. Paint ONLY the ${painted} gray region as a natural, seamless continuation of the ${carried} portion \u2014 same scene, same perspective, continuing the horizon, geometry, and content across the boundary with no break. Keep the ${carried} portion completely unchanged. CRITICAL: do NOT change the lighting, exposure, white balance, or time of day. Match the ${carried} portion's EXACT light, color temperature, and contrast across the whole frame \u2014 if it is flat overcast daylight, keep flat overcast daylight. No golden hour, no sunset, no warm relight, no cinematic regrade. The seam between the ${carried} and ${painted} portions must be invisible. No people, no text, no labels, no watermarks.`;
34594
34763
  }
34595
34764
 
34596
- export { ACTION_FX, ACTION_FX_CATEGORY_LABELS, ACTION_FX_CATEGORY_ORDER, ACTION_FX_IDS, ADULT_AGE_IDS, ADULT_ONLY_FLAG, ADULT_SWEPT_CATALOG_IDS, AESTHETICS, AESTHETIC_CATEGORY_LABELS, AESTHETIC_CATEGORY_ORDER, AESTHETIC_IDS, ALL_PICKER_WIRING, ANALYZABLE_PICKER_TYPES, ANGLE_LABELS, ASPECT_RATIO_LABELS, ATMOSPHERES, ATMOSPHERE_IDS, AUDIO_WIZARD_CATEGORIES, BACKDROPS, BACKDROP_CATEGORY_LABELS, BACKDROP_CATEGORY_ORDER, BACKDROP_IDS, BRAND_PRESETS, BRAND_PRESET_IDS, BRAND_PRESET_META, CAMERA_FORMATS, CAMERA_FORMAT_IDS, CAMERA_MOTIONS, CAMERA_MOTION_CATEGORY_LABELS, CAMERA_MOTION_CATEGORY_ORDER, CAMERA_MOTION_IDS, CHARACTER_FX, CHARACTER_FX_CATEGORY_LABELS, CHARACTER_FX_CATEGORY_ORDER, CHARACTER_FX_DURATIONS, CHARACTER_FX_IDS, CHARACTER_FX_INTENSITIES, CHARACTER_FX_POSITIONS, CINEMATIC_LOOK_TAIL, COLOR_LOOKS, COLOR_LOOK_CATEGORY_LABELS, COLOR_LOOK_CATEGORY_ORDER, COLOR_LOOK_IDS, COMPOSITION_EFFECTS, COMPOSITION_EFFECT_IDS, DEFAULT_IDENTITY_LOCK, DEFAULT_TEMPLATES, DIRECTION_ARRAY_CEILING, DIRECTION_FIELDS, DIRECTION_ID_MAX_CHARS, DIRECTION_KEYS, ERAS, ERA_CATEGORY_LABELS, ERA_CATEGORY_ORDER, ERA_IDS, EXPOSURE_CATEGORY_LABELS, EXPOSURE_CATEGORY_ORDER, EXPOSURE_FIELD_BY_CATEGORY, EXPOSURE_IDS, EXPOSURE_SETTINGS, FACTORY_PRESETS, FACTORY_SNIPPETS, FILM_STILL_PREFIX, FILM_STYLE_KEYS, FLOORED_PICKER_KEYS, FRAMINGS, FRAMING_CATEGORY_LABELS, FRAMING_CATEGORY_ORDER, FRAMING_FIELD_BY_CATEGORY, FRAMING_IDS, GAPS_SCHEMA, HELD_PROPS, HELD_PROP_CATEGORY_LABELS, HELD_PROP_CATEGORY_ORDER, HELD_PROP_IDS, IMAGE_HINT_MODE_DEFAULT, IMAGE_REFERENCE_PROMPT_DOCTRINE, IMAGE_WIZARD_CATEGORIES, INSTRUMENTATION_DEFAULT_DATA, INSTRUMENTS, INSTRUMENT_CATEGORY_LABELS, INSTRUMENT_CATEGORY_ORDER, LENSES, LENS_IDS, LIGHTINGS, LIGHTING_CATEGORY_LABELS, LIGHTING_CATEGORY_ORDER, LIGHTING_FIELD_BY_CATEGORY, LIGHTING_IDS, LLM_CHAT_WIZARD_CATEGORIES, LOOP_SUBJECTS, LOOP_SUBJECT_CATEGORY_LABELS, LOOP_SUBJECT_CATEGORY_ORDER, MATERIALS, MATERIAL_CATEGORY_LABELS, MATERIAL_CATEGORY_ORDER, MATERIAL_IDS, MAX_SELECTED_BY_DIMENSION, MAX_SELECTED_BY_FRAMING_CATEGORY, MAX_SELECTED_BY_STYLING_DIMENSION, MAX_SUBJECT_KEYS, MINOR_IMPLYING_TYPE_IDS, MOODS, MOOD_CATEGORY_LABELS, MOOD_CATEGORY_ORDER, MOOD_IDS, MOVEMENT_LABELS, MULTI_PICKER_WIRING, MUSIC_EMOTIONS, MUSIC_ENERGIES, MUSIC_ERAS, MUSIC_GENRES, MUSIC_GENRE_CATEGORY_LABELS, MUSIC_GENRE_CATEGORY_ORDER, MUSIC_GENRE_DEFAULT_DATA, MUSIC_MOOD_DEFAULT_DATA, MUSIC_VIBES, MUSIC_WIZARD_CATEGORIES, NODE_PROMPT_CANDIDATE_FIELDS, NODE_PROMPT_FIELDS, OBJECT_ANGLE_PRESETS, OBJECT_ANGLE_PROMPTS, OBJECT_ASSET_PRESETS, OBJECT_ASSET_PROMPTS, OBJECT_MATERIAL_PRESETS, OBJECT_MATERIAL_PROMPTS, OBJECT_VARIATION_PRESETS, OBJECT_VARIATION_PROMPTS, PEOPLE, PERSON_DIMENSION_LABELS, PERSON_DIMENSION_ORDER, PERSON_DIMENSION_SECTIONS, PERSON_FIELD_BY_DIMENSION, PERSON_IDS, PHOTOGRAPHERS, PHOTOGRAPHER_CATEGORY_LABELS, PHOTOGRAPHER_CATEGORY_ORDER, PHOTOGRAPHER_IDS, PHOTO_GENRES, PHOTO_GENRE_CATEGORY_LABELS, PHOTO_GENRE_CATEGORY_ORDER, PHOTO_GENRE_IDS, PICKER_ANALYZER_FAMILIES, PICKER_ANALYZER_REGISTRY, PICKER_CATALOGS, PICKER_TYPES, POSES, POSE_CATEGORY_LABELS, POSE_CATEGORY_ORDER, POSE_IDS, POST_PROCESS_EFFECTS, POST_PROCESS_EFFECT_IDS, PRODUCTION_STYLES, PROMPT_AFFIX_CORE_FIELD_OVERRIDES, PROMPT_AFFIX_NODE_TYPES, PROMPT_HINT_SEPARATOR, PROVIDER_CAPABILITIES, PROVIDER_PROMPT_DOCTRINES, REFERENCE_IMAGE_ROLES, REFERENCE_RULES, REFERENCE_RULES_MULTI_PERSON, REF_BINDING, RENDER_QUALITIES, RENDER_QUALITY_IDS, SCENE_FRAME_RULE, SCENE_PROMPT_MAX_LENGTH, SETTINGS, SETTING_CATEGORY_LABELS, SETTING_IDS, SHOT_LABELS, SINGING_STYLES, SINGLE_PICKER_WIRING, SNIPPET_MEDIA_VALUES, STYLES, STYLE_IDS, STYLE_PRESETS, STYLE_SECTION_GAP, STYLE_SECTION_HEADER, STYLINGS, STYLING_DIMENSION_LABELS, STYLING_DIMENSION_ORDER, STYLING_FIELD_BY_DIMENSION, STYLING_IDS, SUBJECT_ARRAY_CEILING, SUBJECT_CUSTOM_AGE_KEY, SUBJECT_FIELDS, SUBJECT_FOLD_KEYS, SUBJECT_ID_MAX_CHARS, SUBJECT_IMAGE_HINT_MODE_DEFAULT, SUBJECT_KEYS, SUBJECT_KEY_MAX_CHARS, SUBJECT_VIDEO_HINT_MODE_DEFAULT, TEMPORALS, TEMPORAL_CATEGORY_LABELS, TEMPORAL_CATEGORY_ORDER, TEMPORAL_FIELD_BY_CATEGORY, TEMPORAL_IDS, TERM_MAX_CHARS, TEXT_WIZARD_CATEGORIES, TRANSITIONS, TRANSITION_CATEGORY_LABELS, TRANSITION_CATEGORY_ORDER, TRANSITION_DURATIONS, TRANSITION_IDS, TRANSITION_INTENSITIES, TRANSITION_POSITIONS, VIDEO_HINT_MODE_DEFAULT, VIDEO_WIZARD_CATEGORIES, VOCAL_PRESENCE, VOCAL_PRESENCE_INSTRUMENTAL_ID, VOICE_ACCENTS, VOICE_AGES, VOICE_ARCHETYPES, VOICE_CHARACTER_DEFAULT_DATA, VOICE_DELIVERY_DEFAULT_DATA, VOICE_EMOTIONS, VOICE_GENDERS, VOICE_LANGUAGES, VOICE_PACES, VOICE_TIMBRES, WARDROBE, WARDROBE_CATEGORY_LABELS, WARDROBE_DIMENSION_ORDER, WARDROBE_FIELD_BY_DIMENSION, __resetCatalogIdGuardForTests, appendField, appendMusicMeta, applyMinorAgeFloorToPickerValues, applyPickerJson, applyPromptAffixes, applyReferenceOrderToVideo, applyTemplate, asBodyClauses, assembleImageInput, assembleSunoInput, buildActionFxHints, buildActionFxTerms, buildAestheticHints, buildAestheticTerms, buildAgeHint, buildAtmosphereHints, buildAtmosphereTerms, buildCharacterPrompt, buildCreaturePrompt, buildExposureHints, buildExposureTerms, buildFaceTemplateInputs, buildFramingHints, buildFramingTerms, buildHeldPropHints, buildHeldPropTerms, buildIdentityDirectives, buildIdentityLockLine, buildImagePrompt, buildImagePromptSegments, buildImagePromptWithOverflow, buildInstrumentationHints, buildInstrumentationTerms, buildLightingHints, buildLightingTerms, buildLocationMotionPrompt, buildLocationPrompt, buildLocationRefinePrompt, buildMaterialHints, buildMaterialTerms, buildMoodHints, buildMoodTerms, buildMotionPrompt, buildMultiPickerAnalyzerSpec, buildMusicGenreHints, buildMusicGenreTerms, buildMusicMoodHints, buildMusicMoodTerms, buildNeedleAlternationSource, buildObjectMotionPrompt, buildObjectPrompt, buildPersonHints, buildPersonTerms, buildPhotographerHints, buildPhotographerTerms, buildPickerAnalyzerSpec, buildPickerLegend, buildPickerZodSchema, buildPoseHints, buildPoseTerms, buildPostProcessHints, buildPostProcessTerms, buildReferenceBlocks, buildScenePrompt, buildStylingHints, buildStylingTerms, buildSurroundFillPrompt, buildTemporalHints, buildTemporalTerms, buildVoiceCharacterHints, buildVoiceCharacterTerms, buildVoiceDeliveryHints, buildVoiceDeliveryTerms, buildWardrobeHints, catalogGuardActive, catalogPacksVersion, characterLockToRefLock, collectIdentityLockClause, composeCameraMotionHintFromConnections, composeCameraMotionTermFromConnections, composeCharacterFxHintFromConnections, composeNegative, composePickerCatalogs, composeSectionedPrompt, composeSoundHintFromConnections, composeTransitionHintFromConnections, composeVideoPromptText, composedHas, composedOption, composedOptionIndex, computeLlmChatFields, computeNodePrompt, computePackSidecarCoverage, containsMinorAgeHint, curateEntries, curatedAnimalPromptHint, curatedAnimalTerm, curatedFurnitureText, curatedVehicleText, curatedWeaponText, deriveTerm, directionFieldsForSurface, endsInsideStyleSection, expandImagePositionRefs, expandImageRefTokens, filmStillPrefix, findForeignCatalogIds, findForeignCatalogIdsInBody, foreignCatalogIdMessage, getActionFx, getActionFxLabel, getActionFxPromptHint, getActionFxTerm, getAdultOnlyEntries, getAdultOnlyHintStrings, getAdultOnlyIds, getAesthetic, getAestheticLabel, getAestheticPromptHint, getAestheticTerm, getAtmosphere, getAtmosphereLabel, getAtmospherePromptHint, getAtmosphereTerm, getBackdrop, getBackdropLabel, getBackdropPromptHint, getBackdropTerm, getCameraFormat, getCameraFormatLabel, getCameraFormatPromptHint, getCameraFormatTerm, getCameraMotion, getCameraMotionLabel, getCameraMotionPromptHint, getCameraMotionTerm, getCategoriesForNodeType, getCharacterFx, getCharacterFxLabel, getCharacterFxPromptHint, getCharacterFxTerm, getColorLook, getColorLookLabel, getColorLookPromptHint, getColorLookTerm, getCompositionEffect, getCompositionEffectLabel, getCompositionEffectPromptHint, getCompositionEffectTerm, getEffectiveSunoCustomMode, getEra, getEraLabel, getEraPromptHint, getEraTerm, getExposure, getExposureLabel, getExposurePromptHint, getExposureTerm, getFactoryPresets, getFactorySnippets, getFraming, getFramingCategoryLimit, getFramingLabel, getFramingPromptHint, getFramingTerm, getHeldProp, getHeldPropLabel, getHeldPropPromptHint, getHeldPropTerm, getIdentityLockClause, getInstrument, getInstrumentTerm, getLens, getLensLabel, getLensPromptHint, getLensTerm, getLighting, getLightingLabel, getLightingPromptHint, getLightingTerm, getLoopSubject, getLoopSubjectLabel, getLoopSubjectPromptHint, getLoopSubjectTerm, getMaterial, getMaterialLabel, getMaterialPromptHint, getMaterialTerm, getMinorAgeHintStrings, getMood, getMoodLabel, getMoodPromptHint, getMoodTerm, getMusicEmotion, getMusicEmotionTerm, getMusicEnergy, getMusicEnergyTerm, getMusicEra, getMusicEraTerm, getMusicGenre, getMusicGenreLabel, getMusicGenreTerm, getMusicSubgenre, getMusicSubgenreTerm, getMusicVibe, getMusicVibeTerm, getParameterPromptHint, getPerson, getPersonDimensionLimit, getPersonLabel, getPersonPromptHint, getPersonTerm, getPhotoGenre, getPhotoGenreLabel, getPhotoGenrePromptHint, getPhotoGenreTerm, getPhotographer, getPhotographerLabel, getPhotographerPromptHint, getPhotographerTerm, getPickerAnalyzer, getPickerCatalog, getPickerWiring, getPose, getPoseLabel, getPosePromptHint, getPoseTerm, getPostProcessEffect, getPostProcessEffectLabel, getPostProcessEffectPromptHint, getPostProcessEffectTerm, getProductionStyle, getProductionStyleTerm, getPromptDoctrine, getPromptFields, getPromptTips, getRegisteredCatalogPacks, getRegisteredPeople, getRegisteredPersonDimensionLabels, getRegisteredPersonDimensionOrder, getRegisteredPersonFieldByDimension, getRegisteredPickerCatalogs, getRegisteredSubjectKeys, getRenderQuality, getRenderQualityLabel, getRenderQualityPromptHint, getRenderQualityTerm, getSetting, getSettingLabel, getSettingPromptHint, getSettingTerm, getSingingStyle, getSingingStyleTerm, getSnippetMedia, getStyle, getStyleLabel, getStylePreset, getStylePromptHint, getStyleTerm, getStyling, getStylingDimensionLimit, getStylingLabel, getStylingPromptHint, getStylingTerm, getTemporal, getTemporalLabel, getTemporalPromptHint, getTemporalTerm, getTransition, getTransitionLabel, getTransitionPromptHint, getTransitionTerm, getVocalPresence, getVocalPresenceTerm, getVoiceAccent, getVoiceAccentTerm, getVoiceAge, getVoiceAgeTerm, getVoiceArchetype, getVoiceArchetypeTerm, getVoiceEmotion, getVoiceEmotionTerm, getVoiceGender, getVoiceGenderTerm, getVoiceLanguage, getVoiceLanguageTerm, getVoicePace, getVoicePaceTerm, getVoiceTimbre, getVoiceTimbreTerm, getWardrobeEntriesByDimension, getWardrobeEntry, getWardrobePromptHint, groupFactoryPresets, hasCatalogPacksFor, hasUpstreamCharacter, identityRefsSentence, insertBeforeStyleSection, isAnalyzablePicker, isDeniedStyleId, isInstrumentalVocal, isMinorAge, isSuspiciousDerivedTerm, isVantageFraming, isWizardSupported, joinPromptHints, joinPromptParts, keepableDirectionHints, listPickerCatalogs, migratePersonValue, modeForFamily, nodeHasInlinePrompt, nodeHasPromptField, nodeSupportsPromptAffixes, normalizeSubjectFields, overlayEntry, partitionStyleClauses, personPacksVersion, pickerFanoutTargets, projectAllCatalogs, projectPickerCatalog, promptAffixCoreField, promptBindsFirstFrame, promptFieldCarriesAffixes, promptPartSeparator, readDirectionFields, readStructuredFields, readSubjectFields, referenceRulesBlock, registerCatalogPack, registerPersonPack, renderDirectionHintClauses, renderDirectionHints, renderStructuredFields, renderStyleSection, renderSubjectHints, resetCatalogPacks, resetPersonPacks, resolveBrandInput, resolveCharacterMentions, resolveGeminiOmniI2vInputs, resolveLocationMentions, resolvePrompt, resolveRefIdTokens, resolveReferenceTokens, resolveSeedance2Inputs, resolveTemplate, resolveTerm, resolveVeoI2vInputs, resolveVideoReferenceCore, sectionedClauseCosts, setComposedCatalogResolver, splitStyleSection, styleSectionFromClauses, styleSlotFor, subjectFieldsForSurface, subscribeCatalogPacks, summarizePickerCatalogs, toIdentityLockMode, truncateForField, truncateText, withForcedIdentityLock };
34765
+ export { ACTION_FX, ACTION_FX_CATEGORY_LABELS, ACTION_FX_CATEGORY_ORDER, ACTION_FX_IDS, ADULT_AGE_IDS, ADULT_ONLY_FLAG, ADULT_SWEPT_CATALOG_IDS, AESTHETICS, AESTHETIC_CATEGORY_LABELS, AESTHETIC_CATEGORY_ORDER, AESTHETIC_IDS, ALL_PICKER_WIRING, ANALYZABLE_PICKER_TYPES, ANGLE_LABELS, ASPECT_RATIO_LABELS, ATMOSPHERES, ATMOSPHERE_IDS, AUDIO_WIZARD_CATEGORIES, BACKDROPS, BACKDROP_CATEGORY_LABELS, BACKDROP_CATEGORY_ORDER, BACKDROP_IDS, BRAND_PRESETS, BRAND_PRESET_IDS, BRAND_PRESET_META, CAMERA_FORMATS, CAMERA_FORMAT_IDS, CAMERA_MOTIONS, CAMERA_MOTION_CATEGORY_LABELS, CAMERA_MOTION_CATEGORY_ORDER, CAMERA_MOTION_IDS, CHARACTER_FX, CHARACTER_FX_CATEGORY_LABELS, CHARACTER_FX_CATEGORY_ORDER, CHARACTER_FX_DURATIONS, CHARACTER_FX_IDS, CHARACTER_FX_INTENSITIES, CHARACTER_FX_POSITIONS, CINEMATIC_LOOK_TAIL, COLOR_LOOKS, COLOR_LOOK_CATEGORY_LABELS, COLOR_LOOK_CATEGORY_ORDER, COLOR_LOOK_IDS, COMPOSITION_EFFECTS, COMPOSITION_EFFECT_IDS, DEFAULT_IDENTITY_LOCK, DEFAULT_TEMPLATES, DIRECTION_ARRAY_CEILING, DIRECTION_FIELDS, DIRECTION_ID_MAX_CHARS, DIRECTION_KEYS, ERAS, ERA_CATEGORY_LABELS, ERA_CATEGORY_ORDER, ERA_IDS, EXPOSURE_CATEGORY_LABELS, EXPOSURE_CATEGORY_ORDER, EXPOSURE_FIELD_BY_CATEGORY, EXPOSURE_IDS, EXPOSURE_SETTINGS, FACTORY_PRESETS, FACTORY_SNIPPETS, FILM_STILL_PREFIX, FILM_STYLE_KEYS, FLOORED_PICKER_KEYS, FRAMINGS, FRAMING_CATEGORY_LABELS, FRAMING_CATEGORY_ORDER, FRAMING_FIELD_BY_CATEGORY, FRAMING_IDS, GAPS_SCHEMA, HELD_PROPS, HELD_PROP_CATEGORY_LABELS, HELD_PROP_CATEGORY_ORDER, HELD_PROP_IDS, IMAGE_HINT_MODE_DEFAULT, IMAGE_REFERENCE_PROMPT_DOCTRINE, IMAGE_WIZARD_CATEGORIES, INSTRUMENTATION_DEFAULT_DATA, INSTRUMENTS, INSTRUMENT_CATEGORY_LABELS, INSTRUMENT_CATEGORY_ORDER, LENSES, LENS_IDS, LIGHTINGS, LIGHTING_CATEGORY_LABELS, LIGHTING_CATEGORY_ORDER, LIGHTING_FIELD_BY_CATEGORY, LIGHTING_IDS, LLM_CHAT_WIZARD_CATEGORIES, LOOP_SUBJECTS, LOOP_SUBJECT_CATEGORY_LABELS, LOOP_SUBJECT_CATEGORY_ORDER, MATERIALS, MATERIAL_CATEGORY_LABELS, MATERIAL_CATEGORY_ORDER, MATERIAL_IDS, MAX_SELECTED_BY_DIMENSION, MAX_SELECTED_BY_FRAMING_CATEGORY, MAX_SELECTED_BY_STYLING_DIMENSION, MAX_SUBJECT_KEYS, MINOR_IMPLYING_TYPE_IDS, MOODS, MOOD_CATEGORY_LABELS, MOOD_CATEGORY_ORDER, MOOD_IDS, MOVEMENT_LABELS, MULTI_PICKER_WIRING, MUSIC_EMOTIONS, MUSIC_ENERGIES, MUSIC_ERAS, MUSIC_GENRES, MUSIC_GENRE_CATEGORY_LABELS, MUSIC_GENRE_CATEGORY_ORDER, MUSIC_GENRE_DEFAULT_DATA, MUSIC_MOOD_DEFAULT_DATA, MUSIC_VIBES, MUSIC_WIZARD_CATEGORIES, NODE_PROMPT_CANDIDATE_FIELDS, NODE_PROMPT_FIELDS, OBJECT_ANGLE_PRESETS, OBJECT_ANGLE_PROMPTS, OBJECT_ASSET_PRESETS, OBJECT_ASSET_PROMPTS, OBJECT_MATERIAL_PRESETS, OBJECT_MATERIAL_PROMPTS, OBJECT_VARIATION_PRESETS, OBJECT_VARIATION_PROMPTS, PEOPLE, PERSON_DIMENSION_LABELS, PERSON_DIMENSION_ORDER, PERSON_DIMENSION_SECTIONS, PERSON_FIELD_BY_DIMENSION, PERSON_IDS, PHOTOGRAPHERS, PHOTOGRAPHER_CATEGORY_LABELS, PHOTOGRAPHER_CATEGORY_ORDER, PHOTOGRAPHER_IDS, PHOTO_GENRES, PHOTO_GENRE_CATEGORY_LABELS, PHOTO_GENRE_CATEGORY_ORDER, PHOTO_GENRE_IDS, PICKER_ANALYZER_FAMILIES, PICKER_ANALYZER_REGISTRY, PICKER_CATALOGS, PICKER_TYPES, POSES, POSE_CATEGORY_LABELS, POSE_CATEGORY_ORDER, POSE_IDS, POST_PROCESS_EFFECTS, POST_PROCESS_EFFECT_IDS, PRODUCTION_STYLES, PROMPT_AFFIX_CORE_FIELD_OVERRIDES, PROMPT_AFFIX_NODE_TYPES, PROMPT_HINT_SEPARATOR, PROVIDER_CAPABILITIES, PROVIDER_PROMPT_DOCTRINES, REFERENCE_IMAGE_ROLES, REFERENCE_RULES, REFERENCE_RULES_MULTI_PERSON, REF_BINDING, RENDER_QUALITIES, RENDER_QUALITY_IDS, RETIRED_ADULT_ONLY_HINT_STRINGS, SCENE_FRAME_RULE, SCENE_PROMPT_MAX_LENGTH, SETTINGS, SETTING_CATEGORY_LABELS, SETTING_IDS, SHOT_LABELS, SINGING_STYLES, SINGLE_PICKER_WIRING, SNIPPET_MEDIA_VALUES, STYLES, STYLE_IDS, STYLE_PRESETS, STYLE_SECTION_GAP, STYLE_SECTION_HEADER, STYLINGS, STYLING_DIMENSION_LABELS, STYLING_DIMENSION_ORDER, STYLING_FIELD_BY_DIMENSION, STYLING_IDS, SUBJECT_ARRAY_CEILING, SUBJECT_CUSTOM_AGE_KEY, SUBJECT_FIELDS, SUBJECT_FOLD_KEYS, SUBJECT_ID_MAX_CHARS, SUBJECT_IMAGE_HINT_MODE_DEFAULT, SUBJECT_KEYS, SUBJECT_KEY_MAX_CHARS, SUBJECT_VIDEO_HINT_MODE_DEFAULT, TEMPORALS, TEMPORAL_CATEGORY_LABELS, TEMPORAL_CATEGORY_ORDER, TEMPORAL_FIELD_BY_CATEGORY, TEMPORAL_IDS, TERM_MAX_CHARS, TEXT_WIZARD_CATEGORIES, TRANSITIONS, TRANSITION_CATEGORY_LABELS, TRANSITION_CATEGORY_ORDER, TRANSITION_DURATIONS, TRANSITION_IDS, TRANSITION_INTENSITIES, TRANSITION_POSITIONS, VIDEO_HINT_MODE_DEFAULT, VIDEO_WIZARD_CATEGORIES, VOCAL_PRESENCE, VOCAL_PRESENCE_INSTRUMENTAL_ID, VOICE_ACCENTS, VOICE_AGES, VOICE_ARCHETYPES, VOICE_CHARACTER_DEFAULT_DATA, VOICE_DELIVERY_DEFAULT_DATA, VOICE_EMOTIONS, VOICE_GENDERS, VOICE_LANGUAGES, VOICE_PACES, VOICE_TIMBRES, WARDROBE, WARDROBE_CATEGORY_LABELS, WARDROBE_DIMENSION_ORDER, WARDROBE_FIELD_BY_DIMENSION, __resetCatalogIdGuardForTests, appendField, appendMusicMeta, appendReferenceLines, applyMinorAgeFloorToPickerValues, applyPickerJson, applyPromptAffixes, applyReferenceOrderToVideo, applyTemplate, asBodyClauses, assembleImageInput, assembleSunoInput, buildActionFxHints, buildActionFxTerms, buildAestheticHints, buildAestheticTerms, buildAgeHint, buildAtmosphereHints, buildAtmosphereTerms, buildCharacterPrompt, buildCreaturePrompt, buildExposureHints, buildExposureTerms, buildFaceTemplateInputs, buildFramingHints, buildFramingTerms, buildHeldPropHints, buildHeldPropTerms, buildIdentityDirectives, buildIdentityLockLine, buildImagePrompt, buildImagePromptSegments, buildImagePromptWithOverflow, buildInstrumentationHints, buildInstrumentationTerms, buildLightingHints, buildLightingTerms, buildLocationMotionPrompt, buildLocationPrompt, buildLocationRefinePrompt, buildMaterialHints, buildMaterialTerms, buildMoodHints, buildMoodTerms, buildMotionPrompt, buildMultiPickerAnalyzerSpec, buildMusicGenreHints, buildMusicGenreTerms, buildMusicMoodHints, buildMusicMoodTerms, buildNeedleAlternationSource, buildObjectMotionPrompt, buildObjectPrompt, buildPersonHints, buildPersonTerms, buildPhotographerHints, buildPhotographerTerms, buildPickerAnalyzerSpec, buildPickerLegend, buildPickerZodSchema, buildPoseHints, buildPoseTerms, buildPostProcessHints, buildPostProcessTerms, buildReferenceBlocks, buildScenePrompt, buildStylingHints, buildStylingTerms, buildSurroundFillPrompt, buildTemporalHints, buildTemporalTerms, buildVoiceCharacterHints, buildVoiceCharacterTerms, buildVoiceDeliveryHints, buildVoiceDeliveryTerms, buildWardrobeHints, catalogGuardActive, catalogPacksVersion, characterLockToRefLock, collectIdentityLockClause, composeCameraMotionHintFromConnections, composeCameraMotionTermFromConnections, composeCharacterFxHintFromConnections, composeNegative, composePickerCatalogs, composeSectionedPrompt, composeSoundHintFromConnections, composeTransitionHintFromConnections, composeVideoPromptText, composedHas, composedOption, composedOptionIndex, computeLlmChatFields, computeNodePrompt, computePackSidecarCoverage, containsMinorAgeHint, curateEntries, curatedAnimalPromptHint, curatedAnimalTerm, curatedFurnitureText, curatedVehicleText, curatedWeaponText, deriveTerm, directionFieldsForSurface, endsInsideStyleSection, expandImagePositionRefs, expandImageRefTokens, filmStillPrefix, findForeignCatalogIds, findForeignCatalogIdsInBody, foreignCatalogIdMessage, getActionFx, getActionFxLabel, getActionFxPromptHint, getActionFxTerm, getAdultOnlyEntries, getAdultOnlyHintStrings, getAdultOnlyIds, getAesthetic, getAestheticLabel, getAestheticPromptHint, getAestheticTerm, getAtmosphere, getAtmosphereLabel, getAtmospherePromptHint, getAtmosphereTerm, getBackdrop, getBackdropLabel, getBackdropPromptHint, getBackdropTerm, getCameraFormat, getCameraFormatLabel, getCameraFormatPromptHint, getCameraFormatTerm, getCameraMotion, getCameraMotionLabel, getCameraMotionPromptHint, getCameraMotionTerm, getCategoriesForNodeType, getCharacterFx, getCharacterFxLabel, getCharacterFxPromptHint, getCharacterFxTerm, getColorLook, getColorLookLabel, getColorLookPromptHint, getColorLookTerm, getCompositionEffect, getCompositionEffectLabel, getCompositionEffectPromptHint, getCompositionEffectTerm, getEffectiveSunoCustomMode, getEra, getEraLabel, getEraPromptHint, getEraTerm, getExposure, getExposureLabel, getExposurePromptHint, getExposureTerm, getFactoryPresets, getFactorySnippets, getFraming, getFramingCategoryLimit, getFramingLabel, getFramingPromptHint, getFramingTerm, getHeldProp, getHeldPropLabel, getHeldPropPromptHint, getHeldPropTerm, getIdentityLockClause, getInstrument, getInstrumentTerm, getLens, getLensLabel, getLensPromptHint, getLensTerm, getLighting, getLightingLabel, getLightingPromptHint, getLightingTerm, getLoopSubject, getLoopSubjectLabel, getLoopSubjectPromptHint, getLoopSubjectTerm, getMaterial, getMaterialLabel, getMaterialPromptHint, getMaterialTerm, getMinorAgeHintStrings, getMood, getMoodLabel, getMoodPromptHint, getMoodTerm, getMusicEmotion, getMusicEmotionTerm, getMusicEnergy, getMusicEnergyTerm, getMusicEra, getMusicEraTerm, getMusicGenre, getMusicGenreLabel, getMusicGenreTerm, getMusicSubgenre, getMusicSubgenreTerm, getMusicVibe, getMusicVibeTerm, getParameterPromptHint, getPerson, getPersonDimensionLimit, getPersonLabel, getPersonPromptHint, getPersonTerm, getPhotoGenre, getPhotoGenreLabel, getPhotoGenrePromptHint, getPhotoGenreTerm, getPhotographer, getPhotographerLabel, getPhotographerPromptHint, getPhotographerTerm, getPickerAnalyzer, getPickerCatalog, getPickerWiring, getPose, getPoseLabel, getPosePromptHint, getPoseTerm, getPostProcessEffect, getPostProcessEffectLabel, getPostProcessEffectPromptHint, getPostProcessEffectTerm, getProductionStyle, getProductionStyleTerm, getPromptDoctrine, getPromptFields, getPromptTips, getRegisteredCatalogPacks, getRegisteredPeople, getRegisteredPersonDimensionLabels, getRegisteredPersonDimensionOrder, getRegisteredPersonFieldByDimension, getRegisteredPickerCatalogs, getRegisteredSubjectKeys, getRenderQuality, getRenderQualityLabel, getRenderQualityPromptHint, getRenderQualityTerm, getSetting, getSettingLabel, getSettingPromptHint, getSettingTerm, getSingingStyle, getSingingStyleTerm, getSnippetMedia, getStyle, getStyleLabel, getStylePreset, getStylePromptHint, getStyleTerm, getStyling, getStylingDimensionLimit, getStylingLabel, getStylingPromptHint, getStylingTerm, getTemporal, getTemporalLabel, getTemporalPromptHint, getTemporalTerm, getTransition, getTransitionLabel, getTransitionPromptHint, getTransitionTerm, getVocalPresence, getVocalPresenceTerm, getVoiceAccent, getVoiceAccentTerm, getVoiceAge, getVoiceAgeTerm, getVoiceArchetype, getVoiceArchetypeTerm, getVoiceEmotion, getVoiceEmotionTerm, getVoiceGender, getVoiceGenderTerm, getVoiceLanguage, getVoiceLanguageTerm, getVoicePace, getVoicePaceTerm, getVoiceTimbre, getVoiceTimbreTerm, getWardrobeEntriesByDimension, getWardrobeEntry, getWardrobePromptHint, groupFactoryPresets, hasCatalogPacksFor, hasUpstreamCharacter, identityRefsSentence, insertBeforeStyleSection, isAnalyzablePicker, isDeniedStyleId, isInstrumentalVocal, isMinorAge, isSuspiciousDerivedTerm, isVantageFraming, isWizardSupported, joinPromptHints, joinPromptParts, keepableDirectionHints, listPickerCatalogs, migratePersonValue, modeForFamily, nodeHasInlinePrompt, nodeHasPromptField, nodeSupportsPromptAffixes, normalizeSubjectFields, overlayEntry, partitionStyleClauses, personPacksVersion, pickerFanoutTargets, projectAllCatalogs, projectPickerCatalog, promptAffixCoreField, promptBindsFirstFrame, promptFieldCarriesAffixes, promptPartSeparator, readDirectionFields, readStructuredFields, readSubjectFields, referenceDescriptionLine, referenceRulesBlock, registerCatalogPack, registerPersonPack, renderDescribedReferenceLines, renderDirectionHintClauses, renderDirectionHints, renderReferenceCaptionLines, renderStructuredFields, renderStyleSection, renderSubjectHints, resetCatalogPacks, resetPersonPacks, resolveBrandInput, resolveCharacterMentions, resolveGeminiOmniI2vInputs, resolveLocationMentions, resolvePrompt, resolveRefIdTokens, resolveReferenceTokens, resolveSeedance2Inputs, resolveTemplate, resolveTerm, resolveVeoI2vInputs, resolveVideoReferenceCore, sectionedClauseCosts, setComposedCatalogResolver, splitStyleSection, styleSectionFromClauses, styleSlotFor, subjectFieldsForSurface, subscribeCatalogPacks, summarizePickerCatalogs, toIdentityLockMode, truncateForField, truncateText, withForcedIdentityLock };
34597
34766
  //# sourceMappingURL=index.js.map
34598
34767
  //# sourceMappingURL=index.js.map