@nodaro/prompts 1.35.0 → 1.37.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.cjs CHANGED
@@ -23099,9 +23099,9 @@ function renderDescribedReferenceLines(refs) {
23099
23099
  }
23100
23100
  function renderReferenceCaptionLines(videoCaptions, audioCaptions, counts) {
23101
23101
  const lines = [];
23102
- const render = (captions, kind, cap) => {
23102
+ const render = (captions, kind, cap2) => {
23103
23103
  if (!captions) return;
23104
- for (let i = 0; i < captions.length && i < cap; i++) {
23104
+ for (let i = 0; i < captions.length && i < cap2; i++) {
23105
23105
  const text = captions[i]?.trim();
23106
23106
  if (!text) continue;
23107
23107
  lines.push(`@${kind}_${i + 1}: ${text}.`);
@@ -25669,17 +25669,17 @@ function composeVideoPromptText(userPrompt, direction, structured, opts) {
25669
25669
  ].filter((c) => c.text.length > 0);
25670
25670
  const structuredFragment = structured ? renderStructuredFields(structured) : "";
25671
25671
  const composeWith = (kept2) => composeSectionedPrompt(userPrompt, hintClauses.slice(0, kept2), structuredFragment);
25672
- const cap = opts?.cap;
25673
- if (cap === void 0) return composeWith(hintClauses.length);
25672
+ const cap2 = opts?.cap;
25673
+ if (cap2 === void 0) return composeWith(hintClauses.length);
25674
25674
  const frame = opts?.frame ?? ((body2) => body2);
25675
25675
  let kept = hintClauses.length;
25676
25676
  let body = composeWith(kept);
25677
25677
  let framedLength = frame(body)?.length ?? 0;
25678
- if (framedLength <= cap) return body;
25678
+ if (framedLength <= cap2) return body;
25679
25679
  const costs = sectionedClauseCosts(userPrompt, hintClauses, structuredFragment);
25680
25680
  const texts = hintClauses.map((c) => c.text);
25681
- while (framedLength > cap && kept > 0) {
25682
- kept = keepableDirectionHints(texts, kept, framedLength - cap, costs);
25681
+ while (framedLength > cap2 && kept > 0) {
25682
+ kept = keepableDirectionHints(texts, kept, framedLength - cap2, costs);
25683
25683
  body = composeWith(kept);
25684
25684
  framedLength = frame(body)?.length ?? 0;
25685
25685
  }
@@ -40860,8 +40860,8 @@ ${buildPickerLegend(spec)}`);
40860
40860
  function buildPickerLegend(spec) {
40861
40861
  const lines = [];
40862
40862
  for (const d of spec.dimensions) {
40863
- const cap = d.limit > 1 ? `up to ${d.limit}` : "one";
40864
- lines.push(`## ${d.label} (key: "${d.dimension}", choose ${cap})`);
40863
+ const cap2 = d.limit > 1 ? `up to ${d.limit}` : "one";
40864
+ lines.push(`## ${d.label} (key: "${d.dimension}", choose ${cap2})`);
40865
40865
  for (const e of d.legend) {
40866
40866
  lines.push(`- ${e.id}: ${e.label}${e.description ? ` \u2014 ${e.description}` : ""}`);
40867
40867
  }
@@ -41181,7 +41181,7 @@ var KLING_AUDIO_DOCTRINE = {
41181
41181
  };
41182
41182
  var MINIMAX_H3_DOCTRINE = {
41183
41183
  providers: ["minimax-h3"],
41184
- heading: "MiniMax Hailuo 3 (minimax-h3)",
41184
+ heading: "MiniMax H3 (minimax-h3)",
41185
41185
  tips: [
41186
41186
  "Natural-language prompts up to 7000 chars. Front-load what matters: subject \u2192 action \u2192 scene/environment \u2192 lighting \u2192 camera move \u2192 style. One camera movement per shot.",
41187
41187
  "Output 2K (default) or 768P (cheaper tier). Aspect: pure text-to-video needs a concrete ratio (21:9/16:9/4:3/1:1/3:4/9:16); reference runs default to adaptive (match the input).",
@@ -41572,11 +41572,11 @@ function buildScene3DUnreferencedFiguresWarning(check2) {
41572
41572
  const figureWord = figures === 1 ? "figure" : "figures";
41573
41573
  const refWord = refs === 1 ? "character reference is" : "character references are";
41574
41574
  let message = `The layout reference shows ${figures} ${figureWord} but ${refs} ${refWord} attached. A figure without its own character reference takes the clay look of the layout reference. Attach one character reference per figure (${missing} more)`;
41575
- const cap = check2.imageReferenceCap;
41576
- if (typeof cap === "number" && Number.isFinite(cap) && cap > 0) {
41575
+ const cap2 = check2.imageReferenceCap;
41576
+ if (typeof cap2 === "number" && Number.isFinite(cap2) && cap2 > 0) {
41577
41577
  const seats = Math.max(0, Math.floor(check2.layoutReferenceImageSeats ?? 0));
41578
- const spare = cap - seats - figures;
41579
- message += spare >= SCENE3D_FREE_PLATE_SLOTS ? `; this model takes ${cap} image references, which leaves ${spare} for a location or style plate.` : `; this model takes ${cap} image references, so one per figure plus ${SCENE3D_FREE_PLATE_SLOTS} free slots for a location or style plate does not fit \u2014 reference the figures that matter most first.`;
41578
+ const spare = cap2 - seats - figures;
41579
+ message += spare >= SCENE3D_FREE_PLATE_SLOTS ? `; this model takes ${cap2} image references, which leaves ${spare} for a location or style plate.` : `; this model takes ${cap2} image references, so one per figure plus ${SCENE3D_FREE_PLATE_SLOTS} free slots for a location or style plate does not fit \u2014 reference the figures that matter most first.`;
41580
41580
  } else {
41581
41581
  message += ".";
41582
41582
  }
@@ -41767,7 +41767,7 @@ var PROVIDER_CAPABILITIES = {
41767
41767
  "seedance-2-fast": "Seedance 2.0 Fast \u2014 same multimodal + audio capabilities, cheaper and quicker",
41768
41768
  "seedance-2-mini": "Seedance 2.0 Mini \u2014 same multimodal + audio capabilities, budget tier, 480p/720p, 4-15s",
41769
41769
  "seedance-2-5": "Seedance 2.5 \u2014 up to 30s in ONE shot (no stitching), wider multimodal refs (30 images / 10 videos / 10 audio), native audio, 480p/720p/1080p",
41770
- "minimax-h3": "MiniMax Hailuo 3 \u2014 premium multimodal refs (9 images / 3 videos / 3 audio), always-on audio, 2K or 768P, 4-15s per-second pricing",
41770
+ "minimax-h3": "MiniMax H3 \u2014 premium multimodal refs (9 images / 3 videos / 3 audio), always-on audio, 2K or 768P, 4-15s per-second pricing",
41771
41771
  "wan": "Versatile, good for animations and transformations",
41772
41772
  "wan-turbo": "Faster Wan generation",
41773
41773
  "hailuo-standard": "Standard quality, cost-effective",
@@ -41798,7 +41798,7 @@ var PROVIDER_CAPABILITIES = {
41798
41798
  "seedance-2-fast": "Seedance 2.0 Fast \u2014 same capabilities, cheaper and quicker",
41799
41799
  "seedance-2-mini": "Seedance 2.0 Mini \u2014 same capabilities, budget tier, 480p/720p",
41800
41800
  "seedance-2-5": "Seedance 2.5 \u2014 start/end frame + wide multimodal refs, native audio, up to 30s, 480p/720p/1080p",
41801
- "minimax-h3": "MiniMax Hailuo 3 \u2014 first/last frame + multimodal refs, always-on audio, 2K or 768P, 4-15s",
41801
+ "minimax-h3": "MiniMax H3 \u2014 first/last frame + multimodal refs, always-on audio, 2K or 768P, 4-15s",
41802
41802
  "hailuo-2.3-pro": "Premium Hailuo animation",
41803
41803
  "hailuo-2.3": "Standard Hailuo animation",
41804
41804
  "hailuo-standard": "Cost-effective animation",
@@ -42010,6 +42010,8 @@ var NODE_PROMPT_FIELDS = {
42010
42010
  "cinematic-avatar": { prompt: "prompt", media: "video", inline: true },
42011
42011
  "video-sfx": { prompt: "prompt", negative: "negativePrompt", promptLabel: "Sound prompt", media: "audio", inline: true },
42012
42012
  "video-retake": { prompt: "prompt", promptLabel: "Retake prompt", media: "video", inline: true },
42013
+ // Video Mask (SAM 3) — the subject to track, like Generate Mask's "what to mask".
42014
+ "video-mask": { prompt: "prompt", promptLabel: "What to mask", media: "video", inline: true },
42013
42015
  // ── Audio / music ──
42014
42016
  "generate-music": { prompt: "prompt", media: "audio", inline: true },
42015
42017
  "suno-generate": { prompt: "prompt", media: "audio", inline: true },
@@ -42085,6 +42087,19 @@ var PROMPT_AFFIX_NODE_TYPES = new Set(
42085
42087
  Object.entries(NODE_PROMPT_FIELDS).filter(([, s]) => s.affixes !== false).map(([t]) => t)
42086
42088
  );
42087
42089
 
42090
+ // src/realism-wording.ts
42091
+ var NEUTRAL_PERSON = { subject: "the person", possessive: "their" };
42092
+ var cap = (s) => s.length === 0 ? s : `${s[0].toUpperCase()}${s.slice(1)}`;
42093
+ var REALISM_SKIN = "Skin shows its real structure: visible pores that vary in size across the nose and cheeks, fine vellus hair catching the light, faint uneven pigmentation, a little redness around the nostrils, natural oil on the forehead.";
42094
+ var REALISM_FINISH = "The plain look of an everyday small-sensor snapshot: colour left as it was recorded, deep focus from the nearest shoulder to the background, a fine grain in the darker areas, bright areas that fade rather than clip.";
42095
+ var REALISM_PASS_INSTRUCTION = "Make this photo look like an unretouched everyday snapshot: skin that shows its pores, its fine hairs and the small changes in tone real skin has, colour left as it was recorded, everything sharp from the shoulders to the background, a little grain in the shadows. Take out anything that makes it look rendered \u2014 smoothed, waxy or airbrushed skin, a glow, over-sharpened edges \u2014 and add no text or icons. Otherwise it stays the same person in the same frame: the face and its proportions, hair, clothing, pose and background as they are.";
42096
+ function realismViewpoint(p) {
42097
+ return `${cap(p.subject)} is looking straight at the viewer from eye level, mid-sentence: ${p.possessive} face and shoulders close up, the framing loose and a little crooked, both arms relaxed and down out of the frame. The whole image is the photograph itself, edge to edge, with no text or icons anywhere.`;
42098
+ }
42099
+ function realismEmptyHands(p) {
42100
+ return `${cap(p.possessive)} hands are empty; ${p.subject} is holding nothing.`;
42101
+ }
42102
+
42088
42103
  // src/factory-presets/shared-image.ts
42089
42104
  var STYLIZED_SUBJECT = [
42090
42105
  {
@@ -42217,6 +42232,47 @@ var IMAGE_EDITS = [
42217
42232
  promptPrefix: "Decorate the reference photo with expressive hand-drawn doodles layered on top, keeping the underlying photograph itself completely unchanged. Free, confident hand-drawn marker linework \u2014 wobbly outlines, sparkles, squiggles, little flames or hearts where they fit the mood, and a short handwritten phrase that responds cleverly to the content of the photo (never a generic clich\xE9). Mix of white and one or two bright accent colors. Outline style only, no filled shapes. Compose the doodles around the subject \u2014 never on top of faces or the focal point \u2014 using empty areas and edges. Loose, playful, zine-like energy: it should feel like a bored genius doodled on a printed photo. Keep the original image pixels intact beneath the doodle layer.",
42218
42233
  negativePrompt: "altered photo, restyled or recolored scene, covered faces, filled color blocks, sticker or clipart look, clich\xE9 phrases, garbled or misspelled handwriting, cluttered composition, watermark, blurry"
42219
42234
  }
42235
+ },
42236
+ {
42237
+ slug: "add-skin-realism",
42238
+ name: "Add Skin Realism",
42239
+ description: "Brings back visible skin texture \u2014 same person, same photo.",
42240
+ data: { provider: "nano-banana-2-1", aspectRatio: "auto", resolution: "2K", promptPrefix: REALISM_PASS_INSTRUCTION }
42241
+ },
42242
+ {
42243
+ slug: "natural-photo-finish",
42244
+ name: "Natural Photo Finish",
42245
+ description: "Takes out a rendered-looking finish, keeps the photo.",
42246
+ data: {
42247
+ provider: "nano-banana-2-1",
42248
+ aspectRatio: "auto",
42249
+ resolution: "2K",
42250
+ promptPrefix: `Keep this photo as it is and take out only what makes it look rendered: smoothed, waxy or airbrushed skin, a glow, over-sharpened edges, hair too perfect to be real. ${REALISM_FINISH} Otherwise the same people, framing, pose and background.`
42251
+ }
42252
+ },
42253
+ {
42254
+ slug: "phone-camera-look",
42255
+ name: "Phone Camera Look",
42256
+ description: "Re-finishes a photo as an everyday snapshot.",
42257
+ data: {
42258
+ provider: "nano-banana-2-1",
42259
+ aspectRatio: "auto",
42260
+ resolution: "2K",
42261
+ promptPrefix: `Re-finish this photo, changing nothing in it: ${REALISM_FINISH} Same people, framing, pose and background.`
42262
+ }
42263
+ },
42264
+ {
42265
+ slug: "undo-beauty-filter",
42266
+ name: "Undo Beauty Filter",
42267
+ description: "Reverses smoothing and reshaping on a real photo.",
42268
+ data: {
42269
+ provider: "seedream-5-pro",
42270
+ // "auto" keeps the photo's shape: this model lists no native "auto", so on either node the
42271
+ // run takes its listed ratio nearest the connected photo.
42272
+ aspectRatio: "auto",
42273
+ quality: "high",
42274
+ promptPrefix: "Undo the beauty filter on this photo: bring back the person's real skin texture, the natural shape of the face, jaw, nose and eyes, and the real colour of skin and lips. Change nothing else: the same person, expression, hair, clothing, framing and background."
42275
+ }
42220
42276
  }
42221
42277
  ];
42222
42278
  function editsFor(nodeType) {
@@ -42230,6 +42286,9 @@ function editsFor(nodeType) {
42230
42286
  }
42231
42287
 
42232
42288
  // src/factory-presets/generate-image.ts
42289
+ var sentences = (...parts) => parts.join(" ");
42290
+ var REALISM_MODEL = { provider: "gpt-image-2", resolution: "2K" };
42291
+ var SKIN_STUDY_MODEL = { provider: "seedream-5-pro", quality: "high" };
42233
42292
  var GENERATE_IMAGE_PRESETS = [
42234
42293
  // ── Reference Sheet ──────────────────────────────────────────────────────
42235
42294
  {
@@ -42386,6 +42445,22 @@ var GENERATE_IMAGE_PRESETS = [
42386
42445
  negativePrompt: "illustration, cartoon, 3d render, garbled text, misspelled labels, watermark, deformed anatomy, inconsistent markings between panels, wrong breed, blurry, low resolution"
42387
42446
  }
42388
42447
  },
42448
+ {
42449
+ id: "generate-image/skin-detail-sheet",
42450
+ name: "Skin Detail Sheet",
42451
+ description: "Connect a sharp face photo \u2192 a six-panel skin reference.",
42452
+ group: "Reference Sheet",
42453
+ data: {
42454
+ ...SKIN_STUDY_MODEL,
42455
+ aspectRatio: "3:2",
42456
+ promptPrefix: sentences(
42457
+ 'Create a single skin detail reference sheet titled "SKIN DETAIL SHEET" from the attached photo of the person, the single source of truth for identity, skin tone and features. The same person, the same light and the same unretouched skin in every panel. Six panels \u2014 render ALL six panel headings exactly as written, never merging or omitting a panel: PANEL 01 \u2014 FULL FACE (front, eye level) \xB7 PANEL 02 \u2014 LEFT CHEEK & NOSE \xB7 PANEL 03 \u2014 RIGHT CHEEK & JAW \xB7 PANEL 04 \u2014 FOREHEAD & HAIRLINE \xB7 PANEL 05 \u2014 EYES & BROWS \xB7 PANEL 06 \u2014 LIPS & CHIN. In every panel:',
42458
+ REALISM_SKIN,
42459
+ "Flat, even daylight, neutral colour, everything sharp."
42460
+ ),
42461
+ promptSuffix: "Plain neutral grey background, thin white panel labels in English. Use this sheet as a visual reference for consistent skin detail of this person across generations."
42462
+ }
42463
+ },
42389
42464
  // ── Cast & Consistency (clean grids per the multi-character workflow:
42390
42465
  // sterile neutral-background reference grids built to be FED BACK as identity
42391
42466
  // anchors — unlike the editorial boards above, decoration here is noise.
@@ -43742,10 +43817,106 @@ var GENERATE_IMAGE_PRESETS = [
43742
43817
  // (GPT Image 2.5 Flare edits it while preserving untouched regions). The
43743
43818
  // instruction lives in the prompt, not `style`.
43744
43819
  ...stylizedSubjectFor("generate-image"),
43745
- ...editsFor("generate-image")
43820
+ ...editsFor("generate-image"),
43821
+ // ── Realism & Authentic ──────────────────────────────────────────────────
43822
+ {
43823
+ id: "generate-image/unretouched-portrait",
43824
+ name: "Unretouched Portrait",
43825
+ description: "Straight-on head-and-shoulders portrait, real skin, everyday finish.",
43826
+ group: "Realism & Authentic",
43827
+ data: {
43828
+ ...REALISM_MODEL,
43829
+ aspectRatio: "3:4",
43830
+ prompt: sentences("{subject || An adult woman in her thirties with dark shoulder-length hair}, a straight-on head-and-shoulders portrait at eye level against a plain pale wall, soft daylight from one side.", REALISM_SKIN, REALISM_FINISH)
43831
+ }
43832
+ },
43833
+ {
43834
+ id: "generate-image/phone-selfie",
43835
+ name: "Phone Selfie",
43836
+ description: "Eye-level, arm's-length self-portrait look.",
43837
+ group: "Realism & Authentic",
43838
+ data: {
43839
+ ...REALISM_MODEL,
43840
+ aspectRatio: "3:4",
43841
+ prompt: sentences("{subject || An adult woman in her late twenties with her hair tied back}, {setting || on a couch at home, a cushion and a lamp behind}.", realismViewpoint(NEUTRAL_PERSON), realismEmptyHands(NEUTRAL_PERSON), REALISM_SKIN, REALISM_FINISH)
43842
+ }
43843
+ },
43844
+ {
43845
+ id: "generate-image/candid-snapshot",
43846
+ name: "Candid Phone Snapshot",
43847
+ description: "Caught mid-moment, an everyday snapshot.",
43848
+ group: "Realism & Authentic",
43849
+ data: {
43850
+ ...REALISM_MODEL,
43851
+ aspectRatio: "3:4",
43852
+ prompt: sentences("{subject || An adult man in his thirties} caught mid-moment, not posing, glancing away, the framing a little crooked, part of the scene cut by the edge, {setting || at a kitchen table at home}.", REALISM_SKIN, REALISM_FINISH)
43853
+ }
43854
+ },
43855
+ {
43856
+ id: "generate-image/mirror-selfie",
43857
+ name: "Mirror Selfie",
43858
+ description: "Mirror self-portrait, phone in hand.",
43859
+ group: "Realism & Authentic",
43860
+ data: {
43861
+ ...REALISM_MODEL,
43862
+ aspectRatio: "9:16",
43863
+ prompt: sentences("{subject || An adult woman in her twenties} photographs their reflection in a full-length mirror {setting || in a hallway at home}, a phone held at chest height with its back toward the mirror.", REALISM_SKIN, REALISM_FINISH)
43864
+ }
43865
+ },
43866
+ {
43867
+ id: "generate-image/creator-at-home",
43868
+ name: "Creator at Home \xB7 Waist-Up",
43869
+ description: "A waist-up reference of the same person \u2014 wire a face photo into the references.",
43870
+ group: "Realism & Authentic",
43871
+ data: {
43872
+ ...REALISM_MODEL,
43873
+ aspectRatio: "9:16",
43874
+ prompt: sentences("Waist-up photo of {image:1:person}, an adult, standing at home in front of a plain wall, arms relaxed, empty hands.", REALISM_SKIN, REALISM_FINISH)
43875
+ }
43876
+ },
43877
+ {
43878
+ id: "generate-image/video-call-frame",
43879
+ name: "Webcam / Video-Call Frame",
43880
+ description: "Chest-up video-call framing.",
43881
+ group: "Realism & Authentic",
43882
+ data: {
43883
+ ...REALISM_MODEL,
43884
+ aspectRatio: "16:9",
43885
+ prompt: sentences("{subject || An adult man in his forties}, chest-up, a little off-centre, slightly wide, seen from a fixed point just above eye level about an arm's length away, a softly lit room behind, flat even light from the front.", REALISM_FINISH)
43886
+ }
43887
+ },
43888
+ {
43889
+ id: "generate-image/macro-skin-study",
43890
+ name: "Macro Skin Study",
43891
+ description: "A close study of one area of skin.",
43892
+ group: "Realism & Authentic",
43893
+ data: {
43894
+ ...SKIN_STUDY_MODEL,
43895
+ aspectRatio: "1:1",
43896
+ prompt: sentences("{feature || the left cheek and the side of the nose} of {subject || an adult woman in her thirties}, filling the frame, everything sharp front to back, flat cool daylight, neutral colour, a plain study of the skin, not a glamour shot.", REALISM_SKIN)
43897
+ }
43898
+ },
43899
+ {
43900
+ id: "generate-image/product-in-hand",
43901
+ name: "Product in Hand \u2014 phone photo",
43902
+ description: "Wire a photo of the product into the references.",
43903
+ group: "Realism & Authentic",
43904
+ data: {
43905
+ ...REALISM_MODEL,
43906
+ aspectRatio: "3:4",
43907
+ prompt: sentences("{subject || An adult woman in her thirties} holds {image:1:product} at chest height toward the viewer, label facing out, {setting || in a bright room at home}.", REALISM_FINISH)
43908
+ }
43909
+ }
43746
43910
  ];
43747
43911
 
43748
43912
  // src/factory-presets/generate-video.ts
43913
+ var UGC_TAIL = "Keep it subtitle-free, do not generate a watermark.";
43914
+ var UGC_PAUSE = "A short natural pause before the first word and after the last.";
43915
+ var ugcSpeech = (line) => `The person says, in a natural American accent, lively and conversational, quicker on connecting words and slower on numbers: "{line || ${line}}"`;
43916
+ var UGC_VIDEO = { provider: "seedance-2-5", aspectRatio: "9:16", duration: 8, resolution: "720p", generateAudio: true };
43917
+ var UGC_SHORT_VIDEO = { ...UGC_VIDEO, duration: 5 };
43918
+ var ugcPrompt = (...parts) => [...parts, UGC_TAIL].join(" ");
43919
+ var TALKING_AT_HOME = "{image:1:person} talks straight to the viewer at eye level at home, face and shoulders close, the framing a little crooked, deep focus, plain colour, a faint natural sway;";
43749
43920
  var GENERATE_VIDEO_PRESETS = [
43750
43921
  // ── Camera Moves (composable cinematography fragments) ───────────────────
43751
43922
  {
@@ -44844,6 +45015,63 @@ var GENERATE_VIDEO_PRESETS = [
44844
45015
  promptPrefix: "edit {video:1} as follows:\n",
44845
45016
  promptSuffix: "Keep everything else in the clip unchanged: the same people, motion, framing and timing. Keep it subtitle-free, do not generate a watermark."
44846
45017
  }
45018
+ },
45019
+ // ── UGC & Creator (everyday talking-to-camera clips) ──────────────────────
45020
+ {
45021
+ id: "generate-video/ugc-talking-head",
45022
+ name: "UGC Talking Head",
45023
+ description: "Talks to the viewer at home \u2014 type the line to be spoken; write numbers as words.",
45024
+ group: "UGC & Creator",
45025
+ data: { ...UGC_VIDEO, prompt: ugcPrompt(`${TALKING_AT_HOME} hands move naturally while talking and hold nothing.`, ugcSpeech("I cut my weekly reporting from three hours to twenty minutes."), UGC_PAUSE) }
45026
+ },
45027
+ {
45028
+ id: "generate-video/ugc-product-closer",
45029
+ name: "UGC Product Closer",
45030
+ description: "Holds your product up while talking \u2014 wire a face photo and a product photo; type the line, numbers as words.",
45031
+ group: "UGC & Creator",
45032
+ data: { ...UGC_VIDEO, prompt: ugcPrompt(`${TALKING_AT_HOME} hands move naturally while talking and hold nothing until the first word.`, "As they say the first word, one hand lifts {image:2:product} into view and holds it up beside their face, its front turned to the viewer, while they talk; the other hand keeps moving naturally.", ugcSpeech("Honestly, this is the one I keep coming back to."), UGC_PAUSE, "After the last word, they lower the product with a small smile.") }
45033
+ },
45034
+ {
45035
+ id: "generate-video/handheld-unboxing",
45036
+ name: "Handheld Unboxing",
45037
+ description: "Opens a box with their own hands and reveals your product \u2014 wire a face photo and a product photo.",
45038
+ group: "UGC & Creator",
45039
+ data: { ...UGC_VIDEO, prompt: ugcPrompt(
45040
+ "Close on a table at home, seen the whole time through the eyes of {image:1:person} as they look down at it.",
45041
+ "From the first moment their own two hands are on the lid of a plain box, both forearms coming up from the bottom of the frame.",
45042
+ "One adult's left and right hand, no one else's; only their hands and forearms are seen.",
45043
+ "They open the box at once and lift out {image:2:product} with both hands, clear of the box by the middle of the clip.",
45044
+ "Until the end they hold it up in front of them, the whole of it in frame, tilting it slowly in the light with the same side toward them.",
45045
+ "Daylight, deep focus from their hands to the background, plain colour, the framing a little crooked, a faint natural sway."
45046
+ ) }
45047
+ },
45048
+ {
45049
+ id: "generate-video/get-ready-with-me",
45050
+ name: "Get Ready With Me",
45051
+ description: "Gets ready at a mirror while chatting \u2014 type the line, numbers as words.",
45052
+ group: "UGC & Creator",
45053
+ data: { ...UGC_VIDEO, prompt: ugcPrompt("{image:1:person} at a bathroom mirror applies a little makeup while chatting to the viewer, everyday light, deep focus, plain colour.", ugcSpeech("Two minutes and I'm ready to go."), UGC_PAUSE) }
45054
+ },
45055
+ {
45056
+ id: "generate-video/street-qa",
45057
+ name: "Street-Style Q&A",
45058
+ description: "A staged street-interview look \u2014 cast it yourself; type a short answer, numbers as words.",
45059
+ group: "UGC & Creator",
45060
+ data: { ...UGC_SHORT_VIDEO, prompt: ugcPrompt("A staged street-interview look: {image:1:person} stands on a sidewalk answering an interviewer who stays out of frame, beside the viewer; only the interviewer's hand is seen, holding a plain microphone out toward them from a lower corner of the frame, passers-by soft in the background.", "Their eyes stay on the interviewer the whole time, off to the side the microphone comes from.", "The answer starts at once, with no wait before the first word.", ugcSpeech("I'd say about twenty minutes a day, tops."), "After the last word, a small laugh and a shrug, eyes still on the interviewer.") }
45061
+ },
45062
+ {
45063
+ id: "generate-video/reaction-shot",
45064
+ name: "Reaction Shot",
45065
+ description: "A quick reaction to something out of frame.",
45066
+ group: "UGC & Creator",
45067
+ data: { ...UGC_SHORT_VIDEO, prompt: ugcPrompt("{image:1:person} sits on a couch at home, a cushion and a lamp behind them, looking off to one side at something just out of frame; at eye level, the framing a little crooked, deep focus, plain colour, a faint natural sway.", "Almost at once, what they see catches them by surprise: their eyes go wide, a hand flies to their mouth and they break into a laugh, their shoulders shaking.", "Still laughing, they glance briefly at the viewer, then look back off to the side, shaking their head.", "A short exclamation at most.") }
45068
+ },
45069
+ {
45070
+ id: "generate-video/acts-on-phone",
45071
+ name: "Acts on Phone, Screen Hidden",
45072
+ description: "Taps a phone whose screen faces away \u2014 type the line, numbers as words.",
45073
+ group: "UGC & Creator",
45074
+ data: { ...UGC_VIDEO, prompt: ugcPrompt(`${TALKING_AT_HOME} hands move naturally while talking and hold nothing until the last seconds.`, ugcSpeech("That's the whole setup, and it took me five minutes."), UGC_PAUSE, "In the last seconds the person picks up a phone and looks down into its screen while typing on it for a moment, then looks back up at the viewer; the screen faces away from the camera.") }
44847
45075
  }
44848
45076
  ];
44849
45077
 
@@ -45996,6 +46224,34 @@ var LLM_CHAT_PRESETS = [
45996
46224
  temperature: 0.9
45997
46225
  }
45998
46226
  },
46227
+ {
46228
+ id: "llm-chat/ugc-monologue-writer",
46229
+ name: "UGC Monologue Writer",
46230
+ description: "A talking-to-camera script as JSON: hook, beats, closer.",
46231
+ group: "Writing & Marketing",
46232
+ data: {
46233
+ systemPrompt: `You write the script of a short vertical video in which one person talks straight to the camera about a product, a site or an idea. Return it as JSON with three parts.
46234
+
46235
+ hook \u2014 the first line: one short spoken clause of at most 8 words. It leads with the payload the viewer can check (a number, a price, a time saved, a before and after, a named result) and opens on the claim itself \u2014 no greeting, no filler, no introduction first.
46236
+
46237
+ beats \u2014 one beat per point the video makes, in order. When the user lists screenshots, write one beat per screenshot, in the same order. The first beat names the product. Every beat is one short spoken sentence a person says in one easy breath; nothing is crammed in.
46238
+
46239
+ closer \u2014 the last line. It ends on one simple physical action the speaker can do on camera.
46240
+
46241
+ Leave room for a short pause at the start and the end of each clip. Sound said, not written: contractions, one connecting word, sentences of mixed length, and one live, imperfect moment such as a small self-correction or an aside. Carry emphasis with word choice and repetition, never with capitals or stage directions. Write only what is spoken: no speaker names, brackets, emoji or sound effects.
46242
+
46243
+ Spell the brand exactly as the user gives it, every time. Write numbers as digits, except inside the brand's own name. Use only figures the user supplies. Write in the language the user writes in.
46244
+
46245
+ When the script is in Hebrew: write spoken Israeli Hebrew, the way a person talks to their phone, not ad copy. Every first-person verb and adjective agrees with the speaker's gender, and never switches. Speak to the viewer in the plural ("\u05EA\u05E0\u05E1\u05D5"), so the viewer is not given a gender. Keep sentences short. Write numbers and prices as digits ("3", "\u20AA49", "20%"). Keep the brand exactly as given, usually in Latin letters; when a Hebrew prefix joins it, use a hyphen ("\u05D1-Planwell"). Leave out vowel points. The hook is at most 8 words, as in English, a word with a joined prefix counting as one word, and opens on the result, the number or the contrast \u2014 never on a greeting or a filler word.
46246
+
46247
+ Return only this JSON, no code fences, no commentary:
46248
+ {"hook": "\u2026", "beats": ["\u2026", "\u2026"], "closer": "\u2026"}`,
46249
+ llmModel: "claude-opus-5.5",
46250
+ reasoningEffort: "high",
46251
+ temperature: 0.8,
46252
+ maxTokens: 2048
46253
+ }
46254
+ },
45999
46255
  // ── Utility ──────────────────────────────────────────────────────────────
46000
46256
  {
46001
46257
  id: "llm-chat/prompt-enhancer",
@@ -46106,7 +46362,9 @@ var GENERATE_SCRIPT_PRESETS = [
46106
46362
  sceneCount: 4,
46107
46363
  targetLength: 30,
46108
46364
  structure: "freeform",
46109
- styleGuide: "Selfie-style UGC testimonial for {product}. Structure: Hook (stop the scroll) \u2192 Show (the product in real use) \u2192 Proof (a concrete result or detail) \u2192 Opinion (a genuine personal take). A real person sharing a real opinion \u2014 first-person, natural, unpolished. Short spoken sentences for clean lip-sync; no salesy voiceover."
46365
+ llmModel: "claude-opus-5.5",
46366
+ reasoningEffort: "high",
46367
+ styleGuide: "Selfie-style UGC testimonial for {product}. Open on the payload: the first spoken line is a short claim the viewer can check \u2014 a number, a price, a time saved, a before and after \u2014 never a greeting or an introduction. Then Show (the product in real use) \u2192 Proof (a concrete result or detail) \u2192 Opinion (a genuine personal take). Sound said, not written: contractions, sentences of mixed length, one small aside; carry emphasis with word choice, never capitals or stage directions. Spell the brand exactly as given and write numbers as digits. Use only figures the user supplies, in what is said and what is shown, and take the Proof from the topic. Short spoken sentences for clean lip-sync; no salesy voiceover."
46110
46368
  }
46111
46369
  },
46112
46370
  // ── Long-Form & Narrative ────────────────────────────────────────────────
@@ -46201,6 +46459,16 @@ var IMAGE_TO_TEXT_PRESETS = [
46201
46459
  description: "Image \u2192 text-to-image prompt.",
46202
46460
  group: "Creative",
46203
46461
  data: { detailLevel: "detailed", customPrompt: "Describe this image as a detailed text-to-image generation prompt: subject, style, lighting, composition and lens. Return only the prompt." }
46462
+ },
46463
+ {
46464
+ id: "image-to-text/realism-audit",
46465
+ name: "Realism Audit",
46466
+ description: "Lists the signs an image was generated, with a count.",
46467
+ group: "Creative",
46468
+ data: {
46469
+ detailLevel: "structured",
46470
+ customPrompt: 'Check this image for signs that it was generated rather than photographed. Answer each question yes or no, with a few words why. 1. Is the skin smooth, waxy or airbrushed, with no visible pores? 2. Is the face unusually symmetrical, or are the teeth unnaturally even and white? 3. Are any hands or fingers malformed, merged or the wrong count? 4. Is any text, logo or sign garbled? 5. Is the background blurred far more than an everyday snapshot would be? 6. Are the catchlights in the eyes perfect rings, or identical in both eyes? 7. Is the hair uniformly perfect, with no flyaways? 8. Do edges look over-sharpened or haloed? 9. Is there a glow or bloom on the skin? 10. Do shadows or reflections disagree with the light? Finish with one line: "Tells found: N of 10".'
46471
+ }
46204
46472
  }
46205
46473
  ];
46206
46474
 
@@ -46247,6 +46515,21 @@ var VIDEO_TO_VIDEO_PRESETS = [
46247
46515
  description: "Flowing washes on paper.",
46248
46516
  group: "Restyle Looks",
46249
46517
  data: { provider: "wan", promptPrefix: "Restyle as a flowing watercolor animation with soft washes, bleeding edges, and visible paper texture. Keep the original motion and composition.", negativePrompt: "photorealistic, harsh edges, blurry, flickering" }
46518
+ },
46519
+ {
46520
+ id: "video-to-video/phone-footage-look",
46521
+ name: "Phone Footage Look",
46522
+ description: "Everyday handheld look for b-roll \u2014 it re-renders faces, so not for talking clips.",
46523
+ group: "Restyle Looks",
46524
+ data: {
46525
+ provider: "wan-videoedit",
46526
+ v2vResolution: "720p",
46527
+ videoEditDuration: "0",
46528
+ audioSetting: "origin",
46529
+ promptExtend: false,
46530
+ promptPrefix: `Keep everything in this clip as it is \u2014 the same people, objects, colours and light \u2014 and only make it look like everyday handheld digital video, left unedited. ${REALISM_FINISH} The edges of the frame keep the light they have in the clip, and each moment keeps the brightness it has in the clip, from the first frame to the last. Preserve the original motion, composition and timing.`,
46531
+ negativePrompt: "cinematic grade, shallow depth of field, glow, skin smoothing, flickering, light leaks, flare, coloured bands at the edges of the frame, colour cast, shifted colours, oversaturated colours, vintage film look, overexposure, pulsing brightness, heavy grain"
46532
+ }
46250
46533
  }
46251
46534
  ];
46252
46535
  var ADD_CAPTIONS_PRESETS = [
@@ -46846,12 +47129,17 @@ function groupFactoryPresets(presets) {
46846
47129
  }
46847
47130
 
46848
47131
  // src/factory-presets/index.ts
47132
+ function forModifyImage(p) {
47133
+ const provider = p.data.provider;
47134
+ const imageToImage = typeof provider === "string" ? shared.T2I_TO_I2I_VARIANT[provider] : void 0;
47135
+ return imageToImage ? { ...p, data: { ...p.data, provider: imageToImage } } : p;
47136
+ }
46849
47137
  var FACTORY_PRESETS = {
46850
47138
  "generate-image": GENERATE_IMAGE_PRESETS,
46851
47139
  // modify-image shares the Stylized Subject + Edits catalogs with generate-image
46852
47140
  // (single source of truth in STYLIZED_SUBJECT / IMAGE_EDITS). modify-image is
46853
47141
  // slated for deprecation in favor of generate-image — when removed, drop this key.
46854
- "modify-image": [...stylizedSubjectFor("modify-image"), ...editsFor("modify-image")],
47142
+ "modify-image": [...stylizedSubjectFor("modify-image"), ...editsFor("modify-image")].map(forModifyImage),
46855
47143
  "generate-video": GENERATE_VIDEO_PRESETS,
46856
47144
  "text-to-speech": TEXT_TO_SPEECH_PRESETS,
46857
47145
  "text-to-audio": TEXT_TO_AUDIO_PRESETS,
@@ -47501,23 +47789,23 @@ function planFrameDelivery(args) {
47501
47789
  ...requested === "reference" && !args.supportsReferenceImages ? { refusedReason: "no-reference-support" } : {}
47502
47790
  };
47503
47791
  }
47504
- const cap = shared.VIDEO_REF_LIMITS_BY_PROVIDER[args.provider ?? ""]?.images;
47505
- if (cap !== void 0 && userRefs.length + frames.length > cap) {
47792
+ const cap2 = shared.VIDEO_REF_LIMITS_BY_PROVIDER[args.provider ?? ""]?.images;
47793
+ if (cap2 !== void 0 && userRefs.length + frames.length > cap2) {
47506
47794
  return { delivery: "frame", referenceImageUrls: userRefs, promptSuffix: "", refusedReason: "image-cap" };
47507
47795
  }
47508
47796
  const referenceImageUrls = [...userRefs];
47509
- const sentences = [];
47797
+ const sentences2 = [];
47510
47798
  if (args.startFrameUrl) {
47511
47799
  referenceImageUrls.push(args.startFrameUrl);
47512
47800
  if (!promptBindsFirstFrame(args.prompt)) {
47513
- sentences.push(REF_BINDING.frame(referenceImageUrls.length, "opening"));
47801
+ sentences2.push(REF_BINDING.frame(referenceImageUrls.length, "opening"));
47514
47802
  }
47515
47803
  }
47516
47804
  if (args.endFrameUrl) {
47517
47805
  referenceImageUrls.push(args.endFrameUrl);
47518
- sentences.push(REF_BINDING.frame(referenceImageUrls.length, "closing"));
47806
+ sentences2.push(REF_BINDING.frame(referenceImageUrls.length, "closing"));
47519
47807
  }
47520
- return { delivery: "reference", referenceImageUrls, promptSuffix: sentences.join(" ") };
47808
+ return { delivery: "reference", referenceImageUrls, promptSuffix: sentences2.join(" ") };
47521
47809
  }
47522
47810
 
47523
47811
  // src/character-motion-diagnostics.ts
@@ -47801,6 +48089,7 @@ exports.MUSIC_GENRE_DEFAULT_DATA = MUSIC_GENRE_DEFAULT_DATA;
47801
48089
  exports.MUSIC_MOOD_DEFAULT_DATA = MUSIC_MOOD_DEFAULT_DATA;
47802
48090
  exports.MUSIC_VIBES = MUSIC_VIBES;
47803
48091
  exports.MUSIC_WIZARD_CATEGORIES = MUSIC_WIZARD_CATEGORIES;
48092
+ exports.NEUTRAL_PERSON = NEUTRAL_PERSON;
47804
48093
  exports.NODE_PROMPT_CANDIDATE_FIELDS = NODE_PROMPT_CANDIDATE_FIELDS;
47805
48094
  exports.NODE_PROMPT_FIELDS = NODE_PROMPT_FIELDS;
47806
48095
  exports.OBJECT_ANGLE_PRESETS = OBJECT_ANGLE_PRESETS;
@@ -47844,6 +48133,9 @@ exports.PROMPT_AFFIX_NODE_TYPES = PROMPT_AFFIX_NODE_TYPES;
47844
48133
  exports.PROMPT_HINT_SEPARATOR = PROMPT_HINT_SEPARATOR;
47845
48134
  exports.PROVIDER_CAPABILITIES = PROVIDER_CAPABILITIES;
47846
48135
  exports.PROVIDER_PROMPT_DOCTRINES = PROVIDER_PROMPT_DOCTRINES;
48136
+ exports.REALISM_FINISH = REALISM_FINISH;
48137
+ exports.REALISM_PASS_INSTRUCTION = REALISM_PASS_INSTRUCTION;
48138
+ exports.REALISM_SKIN = REALISM_SKIN;
47847
48139
  exports.REFERENCE_IMAGE_ROLES = REFERENCE_IMAGE_ROLES;
47848
48140
  exports.REFERENCE_RULES = REFERENCE_RULES;
47849
48141
  exports.REFERENCE_RULES_MULTI_PERSON = REFERENCE_RULES_MULTI_PERSON;
@@ -48296,6 +48588,8 @@ exports.readDirectionFields = readDirectionFields;
48296
48588
  exports.readStructuredFields = readStructuredFields;
48297
48589
  exports.readSubjectFields = readSubjectFields;
48298
48590
  exports.readTransitionOptionValues = readTransitionOptionValues;
48591
+ exports.realismEmptyHands = realismEmptyHands;
48592
+ exports.realismViewpoint = realismViewpoint;
48299
48593
  exports.referenceDescriptionLine = referenceDescriptionLine;
48300
48594
  exports.referenceRulesBlock = referenceRulesBlock;
48301
48595
  exports.registerCatalogPack = registerCatalogPack;