@nodaro/prompts 1.9.0 → 1.11.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
@@ -5892,24 +5892,35 @@ function getCharacterFxTerm(id) {
5892
5892
  return resolveTerm(getCharacterFx(id));
5893
5893
  }
5894
5894
  var CHARACTER_FX_IDS = CHARACTER_FX.map((c) => c.id);
5895
- var POSITION_CLAUSES2 = {
5896
- start: "the effect occurs at the opening of the clip",
5897
- middle: "the effect occurs in the middle of the clip",
5898
- end: "the effect occurs at the end of the clip",
5899
- full: "the effect persists for the entire clip"
5900
- };
5901
- var DURATION_CLAUSES2 = {
5902
- instant: "manifesting instantaneously",
5903
- short: "manifesting over approximately 1 second",
5904
- medium: "manifesting over approximately 2 seconds",
5905
- long: "manifesting over approximately 3 seconds"
5906
- };
5907
- var INTENSITY_CLAUSES2 = {
5908
- subtle: "with subtle restrained energy and minimal flourish",
5909
- natural: "with natural unhurried timing",
5910
- dynamic: "with dynamic energy and assertive flourish",
5911
- crazy: "with extreme exaggerated energy, wild flourishes, and dramatic distortion"
5912
- };
5895
+ var CHARACTER_FX_POSITIONS = [
5896
+ { id: "auto", label: "Auto", description: "Let the model place the effect", promptHint: "", term: "" },
5897
+ { id: "start", label: "Start", description: "Occurs at the opening of the clip", promptHint: "the effect occurs at the opening of the clip", term: "at the opening of the clip" },
5898
+ { id: "middle", label: "Middle", description: "Occurs in the middle of the clip", promptHint: "the effect occurs in the middle of the clip", term: "mid-clip" },
5899
+ { id: "end", label: "End", description: "Occurs at the end of the clip", promptHint: "the effect occurs at the end of the clip", term: "at the end of the clip" },
5900
+ { id: "full", label: "Full", description: "Persists for the entire clip", promptHint: "the effect persists for the entire clip", term: "persisting for the whole clip" }
5901
+ ];
5902
+ var CHARACTER_FX_DURATIONS = [
5903
+ { id: "auto", label: "Auto", description: "Let the model time the effect", promptHint: "", term: "" },
5904
+ { id: "instant", label: "Instant", description: "Manifests instantaneously", promptHint: "manifesting instantaneously", term: "manifesting instantly" },
5905
+ { id: "short", label: "Short (~1s)", description: "Manifests over approximately 1 second", promptHint: "manifesting over approximately 1 second", term: "manifesting over about 1 second" },
5906
+ { id: "medium", label: "Medium (~2s)", description: "Manifests over approximately 2 seconds", promptHint: "manifesting over approximately 2 seconds", term: "manifesting over about 2 seconds" },
5907
+ { id: "long", label: "Long (~3s)", description: "Manifests over approximately 3 seconds", promptHint: "manifesting over approximately 3 seconds", term: "manifesting over about 3 seconds" }
5908
+ ];
5909
+ var CHARACTER_FX_INTENSITIES = [
5910
+ { id: "auto", label: "Auto", description: "Let the model judge the effect's energy", promptHint: "", term: "" },
5911
+ { id: "subtle", label: "Subtle", description: "Restrained, minimal flourish", promptHint: "with subtle restrained energy and minimal flourish", term: "subtly" },
5912
+ { id: "natural", label: "Natural", description: "Unhurried, unforced timing", promptHint: "with natural unhurried timing", term: "at a natural pace" },
5913
+ { id: "dynamic", label: "Dynamic", description: "Assertive, energetic", promptHint: "with dynamic energy and assertive flourish", term: "energetically" },
5914
+ { id: "crazy", label: "Crazy", description: "Extreme, wild, distorted", promptHint: "with extreme exaggerated energy, wild flourishes, and dramatic distortion", term: "wildly exaggerated" }
5915
+ ];
5916
+ function clausesOf2(options) {
5917
+ return Object.fromEntries(
5918
+ options.filter((o) => o.id !== "auto").map((o) => [o.id, o.promptHint])
5919
+ );
5920
+ }
5921
+ var POSITION_CLAUSES2 = clausesOf2(CHARACTER_FX_POSITIONS);
5922
+ var DURATION_CLAUSES2 = clausesOf2(CHARACTER_FX_DURATIONS);
5923
+ var INTENSITY_CLAUSES2 = clausesOf2(CHARACTER_FX_INTENSITIES);
5913
5924
  function composeCharacterFxHintFromConnections(effectId, targetHints, timing, mode = "full") {
5914
5925
  const ids = Array.isArray(effectId) ? Array.from(new Set(effectId)).slice(0, 2) : effectId ? [effectId] : [];
5915
5926
  const resolveBase = mode === "compact" ? getCharacterFxTerm : getCharacterFxPromptHint;
@@ -9518,7 +9529,17 @@ var SINGLE_CATALOGS = [
9518
9529
  defaultValue: "auto",
9519
9530
  categoryOrder: CHARACTER_FX_CATEGORY_ORDER,
9520
9531
  categoryLabels: CHARACTER_FX_CATEGORY_LABELS,
9521
- options: toOptions(CHARACTER_FX, "category")
9532
+ options: toOptions(CHARACTER_FX, "category"),
9533
+ // The node's three timing parameters, alongside the effect itself — the
9534
+ // same shape `transition` carries above, but the character-fx scales, not
9535
+ // the transition ones: the wording is deliberately different (an effect
9536
+ // manifests and persists; a transition occurs and spans), so an id-only
9537
+ // consumer must read these rows, never reuse the transition rows.
9538
+ dimensions: perFieldDims([
9539
+ ["position", CHARACTER_FX_POSITIONS],
9540
+ ["duration", CHARACTER_FX_DURATIONS],
9541
+ ["intensity", CHARACTER_FX_INTENSITIES]
9542
+ ])
9522
9543
  },
9523
9544
  // -------- "Subject / Object" family --------
9524
9545
  {
@@ -10456,6 +10477,55 @@ function resolveLocationMentionsHybrid(prompt, tokens, refs, existingUrls) {
10456
10477
  }
10457
10478
  return { prompt: resolvedPrompt, additionalUrls, mentionedLocationSlugs, lockLines, elementDirectives };
10458
10479
  }
10480
+ function resolveImageMentionsHybrid(prompt, tokens, refs, existingUrls) {
10481
+ const bySlug = /* @__PURE__ */ new Map();
10482
+ for (const r of refs) {
10483
+ const slug = shared.imageMentionSlugForRef(r);
10484
+ if (!slug) continue;
10485
+ if (!bySlug.has(slug)) bySlug.set(slug, r);
10486
+ }
10487
+ const additionalUrls = [];
10488
+ const refByUrl = /* @__PURE__ */ new Map();
10489
+ const lockOverrideByUrl = /* @__PURE__ */ new Map();
10490
+ const matched = [];
10491
+ for (const t of tokens) {
10492
+ const match = bySlug.get(t.imageSlug);
10493
+ if (!match || !match.url) continue;
10494
+ additionalUrls.push(match.url);
10495
+ refByUrl.set(match.url, match);
10496
+ if (t.lock !== void 0) lockOverrideByUrl.set(match.url, t.lock);
10497
+ const role = (t.role ?? "").trim() || shared.resolveDefaultRole(match.defaultRole, match.defaultUsageMode, match.source);
10498
+ matched.push({ token: t.token, offset: t.offset, url: match.url, role });
10499
+ }
10500
+ const slotByUrl = /* @__PURE__ */ new Map();
10501
+ for (const u of [...existingUrls, ...additionalUrls]) {
10502
+ if (!slotByUrl.has(u)) slotByUrl.set(u, slotByUrl.size + 1);
10503
+ }
10504
+ const bindingFor = (url2) => {
10505
+ const slot = slotByUrl.get(url2);
10506
+ return slot ? `reference image ${slotToLetter(slot)}` : "the reference image";
10507
+ };
10508
+ let resolvedPrompt = prompt;
10509
+ for (const m of [...matched].sort((a, b) => b.offset - a.offset)) {
10510
+ const phrase = shared.roleToPhrase(m.role, bindingFor(m.url));
10511
+ resolvedPrompt = resolvedPrompt.slice(0, m.offset) + phrase + resolvedPrompt.slice(m.offset + m.token.length);
10512
+ }
10513
+ const lockLines = [];
10514
+ const elementDirectives = [];
10515
+ const seenUrls = /* @__PURE__ */ new Set();
10516
+ for (const m of matched) {
10517
+ if (seenUrls.has(m.url)) continue;
10518
+ seenUrls.add(m.url);
10519
+ const ref = refByUrl.get(m.url);
10520
+ if (!ref) continue;
10521
+ const binding = bindingFor(m.url);
10522
+ const lock = buildIdentityLockLine(withForcedIdentityLock(ref, lockOverrideByUrl.get(m.url)), binding);
10523
+ if (lock) lockLines.push(lock);
10524
+ const inject = ref.elementInjection?.trim();
10525
+ if (inject) elementDirectives.push(inject);
10526
+ }
10527
+ return { prompt: resolvedPrompt, additionalUrls, lockLines, elementDirectives };
10528
+ }
10459
10529
  function buildCanonicalFallback(refs, mentionedSlugs, startIndex) {
10460
10530
  const directiveLines = [];
10461
10531
  const urls = [];
@@ -10838,7 +10908,9 @@ function buildImagePromptInternal(config2, marks) {
10838
10908
  connectedReferences.map((r) => r.locationSlug).filter((s) => typeof s === "string" && s.length > 0)
10839
10909
  )
10840
10910
  );
10841
- if (knownCharacterSlugs.length > 0 || hasExtraRefs || knownLocationSlugs.length > 0) {
10911
+ const knownImageSlugs = shared.knownImageSlugsFromRefs(connectedReferences);
10912
+ const hasImageMentionTokens = isHybrid && knownImageSlugs.length > 0 && shared.findImageMentionTokens(config2.prompt, knownImageSlugs).length > 0;
10913
+ if (knownCharacterSlugs.length > 0 || hasExtraRefs || knownLocationSlugs.length > 0 || hasImageMentionTokens) {
10842
10914
  const mentionTokens = knownCharacterSlugs.length > 0 ? shared.findCharacterMentionTokens(config2.prompt, knownCharacterSlugs) : [];
10843
10915
  let hybridLockLines = [];
10844
10916
  let hybridElementDirectives = [];
@@ -10892,6 +10964,24 @@ function buildImagePromptInternal(config2, marks) {
10892
10964
  if (r.locationVariantBucket) return false;
10893
10965
  return !mentionedLocationSlugs.has(r.locationSlug);
10894
10966
  });
10967
+ let hybridImageLockLines = [];
10968
+ let hybridImageElementDirectives = [];
10969
+ if (hasImageMentionTokens) {
10970
+ const imageTokens = shared.findImageMentionTokens(resolved.prompt, knownImageSlugs);
10971
+ if (imageTokens.length > 0) {
10972
+ const hi = resolveImageMentionsHybrid(
10973
+ resolved.prompt,
10974
+ imageTokens,
10975
+ connectedReferences,
10976
+ [...referenceImageUrls || [], ...resolved.additionalUrls]
10977
+ );
10978
+ resolved.prompt = hi.prompt;
10979
+ resolved.additionalUrls = [...resolved.additionalUrls, ...hi.additionalUrls];
10980
+ hybridImageLockLines = hi.lockLines;
10981
+ hybridImageElementDirectives = hi.elementDirectives;
10982
+ if (hi.additionalUrls.length > 0) hybridBodyConverged = true;
10983
+ }
10984
+ }
10895
10985
  const prefixDedupedLength = [
10896
10986
  ...referenceImageUrls || [],
10897
10987
  ...resolved.additionalUrls
@@ -10972,12 +11062,14 @@ ${promptForNext}`;
10972
11062
  const allLockLines = [.../* @__PURE__ */ new Set([
10973
11063
  ...hybridLockLines,
10974
11064
  ...hybridLocationLockLines,
11065
+ ...hybridImageLockLines,
10975
11066
  ...canonical.lockLines,
10976
11067
  ...extrasRendered.lockLines
10977
11068
  ])];
10978
11069
  const trailingLines = [
10979
11070
  ...hybridElementDirectives,
10980
11071
  ...hybridLocationElementDirectives,
11072
+ ...hybridImageElementDirectives,
10981
11073
  ...canonical.phrases,
10982
11074
  ...canonical.elementDirectives,
10983
11075
  ...extrasRendered.bodyLines,
@@ -11600,6 +11692,134 @@ function renderLens(l) {
11600
11692
  if (l.aperture) bits.push(`f/${l.aperture}`);
11601
11693
  return bits.length > 0 ? `Lens: ${bits.join(", ")}.` : "";
11602
11694
  }
11695
+
11696
+ // src/direction-registry.ts
11697
+ var perId = (full, compact) => (ids, mode) => {
11698
+ const out = [];
11699
+ for (const id of ids) {
11700
+ const frag = mode === "compact" ? compact(id) : full(id);
11701
+ if (frag.length > 0) out.push(frag);
11702
+ }
11703
+ return out;
11704
+ };
11705
+ var viaListBuilder = (build) => (ids, mode) => build(ids.length === 1 ? ids[0] : [...ids], mode).filter((s) => s.length > 0);
11706
+ var viaStringBuilder = (build) => (ids, mode) => {
11707
+ const s = build(ids.length === 1 ? ids[0] : [...ids], mode);
11708
+ return s.length > 0 ? [s] : [];
11709
+ };
11710
+ var viaMood = (ids, mode) => buildMoodHints({ mood: ids.length === 1 ? ids[0] : [...ids] }, mode).filter(
11711
+ (s) => s.length > 0
11712
+ );
11713
+ var framing = perId(getFramingPromptHint, getFramingTerm);
11714
+ var lighting = perId(getLightingPromptHint, getLightingTerm);
11715
+ var exposure = perId(getExposurePromptHint, getExposureTerm);
11716
+ var temporal = perId(getTemporalPromptHint, getTemporalTerm);
11717
+ var DIRECTION_FIELDS = [
11718
+ { key: "cameraMotion", surface: "video", family: "motion", maxPicks: 1, render: perId(getCameraMotionPromptHint, getCameraMotionTerm) },
11719
+ // Composition (the Framing catalog, one row per category).
11720
+ { key: "shotSize", surface: "both", family: "look", maxPicks: 1, render: framing },
11721
+ { key: "angle", surface: "both", family: "look", maxPicks: 1, render: framing },
11722
+ { key: "coverage", surface: "both", family: "look", maxPicks: 1, render: framing },
11723
+ { key: "composition", surface: "both", family: "look", maxPicks: 2, render: framing },
11724
+ { key: "vantage", surface: "both", family: "look", maxPicks: 1, render: framing },
11725
+ { key: "pose", surface: "both", family: "look", maxPicks: 1, render: perId(getPosePromptHint, getPoseTerm) },
11726
+ { key: "compositionEffect", surface: "both", family: "look", maxPicks: 1, render: perId(getCompositionEffectPromptHint, getCompositionEffectTerm) },
11727
+ // Camera.
11728
+ { key: "cameraFormat", surface: "both", family: "look", maxPicks: 1, render: perId(getCameraFormatPromptHint, getCameraFormatTerm) },
11729
+ { key: "lens", surface: "both", family: "look", maxPicks: 1, render: perId(getLensPromptHint, getLensTerm) },
11730
+ // Exposure (stills only — a video's exposure rides its own temporal levers).
11731
+ { key: "aperture", surface: "image", family: "look", maxPicks: 1, render: exposure },
11732
+ { key: "shutterSpeed", surface: "image", family: "look", maxPicks: 1, render: exposure },
11733
+ { key: "isoValue", surface: "image", family: "look", maxPicks: 1, render: exposure },
11734
+ // Light (the Lighting catalog, one row per category).
11735
+ { key: "timeOfDay", surface: "both", family: "look", maxPicks: 1, render: lighting },
11736
+ { key: "lightingStyle", surface: "both", family: "look", maxPicks: 2, render: lighting },
11737
+ { key: "lightingDirection", surface: "both", family: "look", maxPicks: 1, render: lighting },
11738
+ { key: "lightingRatio", surface: "both", family: "look", maxPicks: 1, render: lighting },
11739
+ { key: "colorTemperature", surface: "both", family: "look", maxPicks: 1, render: lighting },
11740
+ { key: "colorLook", surface: "both", family: "look", maxPicks: 1, render: perId(getColorLookPromptHint, getColorLookTerm) },
11741
+ { key: "atmosphere", surface: "both", family: "look", maxPicks: 2, render: viaListBuilder(buildAtmosphereHints) },
11742
+ { key: "postProcess", surface: "image", family: "look", maxPicks: 2, render: viaListBuilder(buildPostProcessHints) },
11743
+ // Style.
11744
+ { key: "style", surface: "both", family: "look", maxPicks: 1, render: perId(getStylePromptHint, getStyleTerm) },
11745
+ { key: "mood", surface: "both", family: "look", maxPicks: 2, render: viaMood },
11746
+ { key: "aesthetic", surface: "both", family: "look", maxPicks: 2, render: viaStringBuilder(buildAestheticHints) },
11747
+ { key: "photoGenre", surface: "image", family: "look", maxPicks: 1, render: perId(getPhotoGenrePromptHint, getPhotoGenreTerm) },
11748
+ { key: "photographer", surface: "image", family: "look", maxPicks: 2, render: viaStringBuilder(buildPhotographerHints) },
11749
+ { key: "renderQuality", surface: "image", family: "look", maxPicks: 1, render: perId(getRenderQualityPromptHint, getRenderQualityTerm) },
11750
+ // Scene.
11751
+ { key: "setting", surface: "both", family: "look", maxPicks: 1, render: perId(getSettingPromptHint, getSettingTerm) },
11752
+ { key: "era", surface: "both", family: "look", maxPicks: 1, render: perId(getEraPromptHint, getEraTerm) },
11753
+ { key: "backdrop", surface: "both", family: "look", maxPicks: 1, render: perId(getBackdropPromptHint, getBackdropTerm) },
11754
+ // Motion & time.
11755
+ { key: "actionFx", surface: "video", family: "motion", maxPicks: 2, render: viaListBuilder(buildActionFxHints) },
11756
+ { key: "temporalSpeed", surface: "video", family: "motion", maxPicks: 1, render: temporal },
11757
+ { key: "temporalFreeze", surface: "video", family: "motion", maxPicks: 1, render: temporal },
11758
+ { key: "temporalDirection", surface: "video", family: "motion", maxPicks: 1, render: temporal },
11759
+ { key: "temporalShutter", surface: "video", family: "motion", maxPicks: 1, render: temporal },
11760
+ { key: "transition", surface: "video", family: "motion", maxPicks: 2, render: perId(getTransitionPromptHint, getTransitionTerm) },
11761
+ { key: "loopSubject", surface: "video", family: "motion", maxPicks: 1, render: perId(getLoopSubjectPromptHint, getLoopSubjectTerm) },
11762
+ // ── LEGACY BLOCK — see the table doc above. Placed LAST, in today's exact
11763
+ // `composePromptText` order, so every pre-registry caller is byte-identical.
11764
+ { key: "framingId", surface: "both", family: "look", maxPicks: 1, render: framing },
11765
+ { key: "framingAngleId", surface: "both", family: "look", maxPicks: 1, render: framing },
11766
+ { key: "lightingId", surface: "both", family: "look", maxPicks: 1, render: lighting },
11767
+ { key: "lensId", surface: "both", family: "look", maxPicks: 1, render: perId(getLensPromptHint, getLensTerm) },
11768
+ { key: "cameraFormatId", surface: "both", family: "look", maxPicks: 1, render: perId(getCameraFormatPromptHint, getCameraFormatTerm) }
11769
+ ];
11770
+ var DIRECTION_KEYS = DIRECTION_FIELDS.map((f) => f.key);
11771
+ var IMAGE_HINT_MODE_DEFAULT = "full";
11772
+ var VIDEO_HINT_MODE_DEFAULT = { look: "full", motion: "compact" };
11773
+ function modeForFamily(mode, family) {
11774
+ return typeof mode === "string" ? mode : family === "motion" ? mode.motion : mode.look;
11775
+ }
11776
+ var DIRECTION_ARRAY_CEILING = 8;
11777
+ var DIRECTION_ID_MAX_CHARS = 100;
11778
+ function normalizeDirectionIds(value, maxPicks) {
11779
+ const ids = [];
11780
+ if (typeof value === "string") {
11781
+ if (value) ids.push(value);
11782
+ } else if (Array.isArray(value)) {
11783
+ for (const v of value) {
11784
+ if (ids.length >= maxPicks) break;
11785
+ if (typeof v === "string" && v && !ids.includes(v)) ids.push(v);
11786
+ }
11787
+ }
11788
+ return ids.slice(0, maxPicks);
11789
+ }
11790
+ function directionFieldsForSurface(surface) {
11791
+ return DIRECTION_FIELDS.filter((f) => f.surface === "both" || f.surface === surface);
11792
+ }
11793
+ function renderDirectionHints(direction, opts) {
11794
+ if (!direction) return [];
11795
+ const mode = opts.mode ?? "full";
11796
+ const out = [];
11797
+ const seen = /* @__PURE__ */ new Set();
11798
+ for (const spec of DIRECTION_FIELDS) {
11799
+ if (spec.surface !== "both" && spec.surface !== opts.surface) continue;
11800
+ const ids = normalizeDirectionIds(
11801
+ direction[spec.key],
11802
+ spec.maxPicks
11803
+ );
11804
+ if (ids.length === 0) continue;
11805
+ for (const hint of spec.render(ids, modeForFamily(mode, spec.family))) {
11806
+ if (hint.length > 0 && !seen.has(hint)) {
11807
+ seen.add(hint);
11808
+ out.push(hint);
11809
+ }
11810
+ }
11811
+ }
11812
+ return out;
11813
+ }
11814
+
11815
+ // src/prompt-hint-join.ts
11816
+ var PROMPT_HINT_SEPARATOR = ". ";
11817
+ function joinPromptHints(userPrompt, hints) {
11818
+ if (hints.length === 0) return userPrompt;
11819
+ return [userPrompt.trim(), ...hints].filter((p) => p.length > 0).join(PROMPT_HINT_SEPARATOR);
11820
+ }
11821
+
11822
+ // src/ref-binding.ts
11603
11823
  function identityRefsSentence(firstOrdinal, lastOrdinal) {
11604
11824
  return firstOrdinal === lastOrdinal ? `${REF_BINDING.ordinal(firstOrdinal)} is an identity reference for this shot's subjects \u2014 match its subject's exact appearance; it is not a frame.` : `${REF_BINDING.ordinal(firstOrdinal)} through ${REF_BINDING.ordinal(lastOrdinal)} are identity references for this shot's subjects \u2014 match each subject's exact appearance; they are not frames.`;
11605
11825
  }
@@ -11611,6 +11831,38 @@ var REF_BINDING = {
11611
11831
  ordinal: (n) => `@image_${n}`,
11612
11832
  frame: (n, role) => `Use @image_${n} as the ${role} (${role === "opening" ? "first" : "last"}) frame of the video.`
11613
11833
  };
11834
+
11835
+ // src/ref-id-tokens.ts
11836
+ var REF_TOKEN_LABEL_RE = /^[a-zA-Z0-9_ -]+$/;
11837
+ var HAS_REF_ID_TOKEN_RE = /\{ref:/i;
11838
+ var REF_ID_TOKEN_RE = /\{[rR][eE][fF]:([^{}]*)\}/g;
11839
+ var MALFORMED_REF_ID_TOKEN_RE = /\{[rR][eE][fF]:[^\s{}]*\}?/g;
11840
+ function splitLabel(content) {
11841
+ const at = content.lastIndexOf(":");
11842
+ if (at === -1) return { id: content };
11843
+ const tail = content.slice(at + 1);
11844
+ if (!REF_TOKEN_LABEL_RE.test(tail)) return { id: content };
11845
+ return { id: content.slice(0, at), label: tail };
11846
+ }
11847
+ function resolveRefIdTokens(prompt, ctx) {
11848
+ if (!prompt || !HAS_REF_ID_TOKEN_RE.test(prompt)) return prompt;
11849
+ const known = (id) => id.length > 0 && (ctx.slotById.has(id) || ctx.nameById.has(id));
11850
+ const bind = (id, label) => {
11851
+ const slot = ctx.slotById.get(id);
11852
+ if (slot !== void 0 && slot >= 1 && slot <= ctx.imageCount) {
11853
+ return label ? REF_BINDING.image(label, slot) : REF_BINDING.ordinal(slot);
11854
+ }
11855
+ return label ?? ctx.nameById.get(id) ?? "";
11856
+ };
11857
+ return prompt.replace(REF_ID_TOKEN_RE, (_match, content) => {
11858
+ if (known(content)) return bind(content, void 0);
11859
+ const { id, label } = splitLabel(content);
11860
+ if (known(id)) return bind(id, label);
11861
+ return label ?? "";
11862
+ }).replace(MALFORMED_REF_ID_TOKEN_RE, "");
11863
+ }
11864
+
11865
+ // src/video-reference-resolver.ts
11614
11866
  var REFERENCE_TOKEN_RE = /\{(image|video|audio):(\d+)(?::([a-zA-Z0-9_ -]+))?\}/gi;
11615
11867
  function resolveReferenceTokens(prompt, counts) {
11616
11868
  if (!prompt) return prompt;
@@ -11711,12 +11963,27 @@ function resolveVideoReferenceCore(args) {
11711
11963
  });
11712
11964
  }
11713
11965
  const hasExtras = (args.extraRefs?.length ?? 0) > 0;
11966
+ const nameByRefId = /* @__PURE__ */ new Map();
11967
+ for (const r of args.wiredCharRefs) {
11968
+ if (r.id && !nameByRefId.has(r.id)) nameByRefId.set(r.id, r.defaultName || r.characterSlug || "");
11969
+ }
11970
+ for (const ex of args.extraRefs ?? []) {
11971
+ if (ex.id && !nameByRefId.has(ex.id)) nameByRefId.set(ex.id, "");
11972
+ }
11973
+ for (const [id, name] of args.refNamesById ?? []) {
11974
+ if (id) nameByRefId.set(id, name);
11975
+ }
11976
+ const slotByRefId = /* @__PURE__ */ new Map();
11714
11977
  if (wiredCharRefs.length === 0 && !hasExtras) {
11978
+ const counts = tokenCounts(leadingRefUrls.length);
11715
11979
  return {
11716
11980
  // tokenCounts(leadingRefUrls.length) → image count == offset (no assets here):
11717
11981
  // leadingRefUrls mode counts the leading refs; ordinalOffset mode counts the
11718
11982
  // caller-owned leading refs the offset stands in for.
11719
- prompt: resolveReferenceTokens(args.prompt, tokenCounts(leadingRefUrls.length)),
11983
+ prompt: resolveReferenceTokens(
11984
+ resolveRefIdTokens(args.prompt, { slotById: slotByRefId, nameById: nameByRefId, imageCount: counts.image }),
11985
+ counts
11986
+ ),
11720
11987
  additionalUrls: [...leadingRefUrls]
11721
11988
  };
11722
11989
  }
@@ -11749,9 +12016,13 @@ function resolveVideoReferenceCore(args) {
11749
12016
  let position = offset;
11750
12017
  for (let i = 0; i < resolved.additionalUrls.length; i++) {
11751
12018
  position += 1;
11752
- const ref = wiredCharRefs.find((r) => r.url === resolved.additionalUrls[i]);
12019
+ const url2 = resolved.additionalUrls[i];
12020
+ const ref = wiredCharRefs.find((r) => r.url === url2);
11753
12021
  const slug = ref?.characterSlug;
11754
12022
  if (slug && !positionsByChar.has(slug)) positionsByChar.set(slug, position);
12023
+ for (const r of wiredCharRefs) {
12024
+ if (r.url === url2 && r.id && !slotByRefId.has(r.id)) slotByRefId.set(r.id, position);
12025
+ }
11755
12026
  }
11756
12027
  for (const r of wiredCharRefs) {
11757
12028
  if (r.source !== "wired-character") continue;
@@ -11764,6 +12035,7 @@ function resolveVideoReferenceCore(args) {
11764
12035
  fallbackUrls.push(r.url);
11765
12036
  position += 1;
11766
12037
  if (!positionsByChar.has(r.characterSlug)) positionsByChar.set(r.characterSlug, position);
12038
+ if (r.id && !slotByRefId.has(r.id)) slotByRefId.set(r.id, position);
11767
12039
  if (hybrid) {
11768
12040
  const binding = REF_BINDING.ordinal(position);
11769
12041
  canonicalPhrases.push(shared.roleToPhrase(shared.resolveDefaultRole(r.defaultRole, r.defaultUsageMode, r.source), binding));
@@ -11801,6 +12073,7 @@ function resolveVideoReferenceCore(args) {
11801
12073
  for (const ex of args.extraRefs) {
11802
12074
  if (!ex.url) continue;
11803
12075
  position += 1;
12076
+ if (ex.id && !slotByRefId.has(ex.id)) slotByRefId.set(ex.id, position);
11804
12077
  const desc = (ex.description ?? "").trim();
11805
12078
  if (ex.characterSlug) {
11806
12079
  const meta3 = args.lookupCharacterBySlug?.(ex.characterSlug);
@@ -11947,6 +12220,11 @@ ${finalPrompt}` : block;
11947
12220
  merged.push(u);
11948
12221
  }
11949
12222
  }
12223
+ finalPrompt = resolveRefIdTokens(finalPrompt, {
12224
+ slotById: slotByRefId,
12225
+ nameById: nameByRefId,
12226
+ imageCount: tokenCounts(merged.length).image
12227
+ }) ?? finalPrompt;
11950
12228
  const referenceOrder = args.referenceOrder;
11951
12229
  const assetUrls = merged.slice(leadingRefUrls.length);
11952
12230
  if (referenceOrder && referenceOrder.length > 0 && assetUrls.length > 1) {
@@ -12128,15 +12406,10 @@ function assembleSunoInput(input) {
12128
12406
  // src/assemble-image-input.ts
12129
12407
  function composePromptText(userPrompt, direction, structured) {
12130
12408
  const hints = [
12131
- getFramingPromptHint(direction?.framingId),
12132
- getFramingPromptHint(direction?.framingAngleId),
12133
- getLightingPromptHint(direction?.lightingId),
12134
- getLensPromptHint(direction?.lensId),
12135
- getCameraFormatPromptHint(direction?.cameraFormatId),
12409
+ ...renderDirectionHints(direction, { surface: "image", mode: IMAGE_HINT_MODE_DEFAULT }),
12136
12410
  structured ? renderStructuredFields(structured) : ""
12137
12411
  ].filter((p) => p.length > 0);
12138
- if (hints.length === 0) return userPrompt;
12139
- return [userPrompt.trim(), ...hints].filter((p) => p.length > 0).join(". ");
12412
+ return joinPromptHints(userPrompt, hints);
12140
12413
  }
12141
12414
  function assembleImageInput(input) {
12142
12415
  const prompt = composePromptText(input.userPrompt, input.direction, input.structured);
@@ -12171,6 +12444,106 @@ function assembleImageInput(input) {
12171
12444
  }
12172
12445
  return result;
12173
12446
  }
12447
+
12448
+ // src/assemble-video-input.ts
12449
+ function composeVideoPromptText(userPrompt, direction, structured, opts) {
12450
+ const hints = [
12451
+ ...renderDirectionHints(direction, {
12452
+ surface: "video",
12453
+ mode: opts?.hintMode ?? VIDEO_HINT_MODE_DEFAULT
12454
+ }),
12455
+ structured ? renderStructuredFields(structured) : ""
12456
+ ].filter((p) => p.length > 0);
12457
+ if (hints.length === 0) return userPrompt;
12458
+ return joinPromptHints(userPrompt ?? "", hints);
12459
+ }
12460
+
12461
+ // src/read-node-direction.ts
12462
+ function readDirectionFields(value) {
12463
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
12464
+ const src = value;
12465
+ const out = {};
12466
+ for (const spec of DIRECTION_FIELDS) {
12467
+ const v = src[spec.key];
12468
+ if (typeof v === "string") {
12469
+ if (v.length > 0 && v.length <= DIRECTION_ID_MAX_CHARS) out[spec.key] = v;
12470
+ } else if (Array.isArray(v)) {
12471
+ const kept = [];
12472
+ for (const x of v) {
12473
+ if (kept.length >= DIRECTION_ARRAY_CEILING) break;
12474
+ if (typeof x === "string" && x.length > 0 && x.length <= DIRECTION_ID_MAX_CHARS) {
12475
+ kept.push(x);
12476
+ }
12477
+ }
12478
+ if (kept.length > 0) out[spec.key] = kept;
12479
+ }
12480
+ }
12481
+ return Object.keys(out).length > 0 ? out : void 0;
12482
+ }
12483
+ var GENDERS = ["man", "woman", "child", "non-binary"];
12484
+ var MAX_STRUCTURED_VALUE_CHARS = 200;
12485
+ var PERSON_FIELDS2 = {
12486
+ age: "number",
12487
+ gender: "gender",
12488
+ hair: "string",
12489
+ eyes: "string",
12490
+ expression: "string",
12491
+ profession: "string",
12492
+ warriorType: "string"
12493
+ };
12494
+ var STYLING_FIELDS2 = {
12495
+ mood: "string",
12496
+ lighting: "string",
12497
+ aesthetic: "string",
12498
+ colorLook: "string"
12499
+ };
12500
+ var SETTING_FIELDS = {
12501
+ era: "string",
12502
+ atmosphere: "string",
12503
+ backdrop: "string"
12504
+ };
12505
+ var CAMERA_FIELDS = {
12506
+ framing: "string",
12507
+ motion: "string",
12508
+ format: "string"
12509
+ };
12510
+ var LENS_FIELDS = { focalLength: "string", aperture: "string" };
12511
+ var STRUCTURED_GROUPS = {
12512
+ person: PERSON_FIELDS2,
12513
+ styling: STYLING_FIELDS2,
12514
+ setting: SETTING_FIELDS,
12515
+ camera: CAMERA_FIELDS,
12516
+ lens: LENS_FIELDS
12517
+ };
12518
+ function readField(v, kind) {
12519
+ if (kind === "number") return typeof v === "number" && Number.isFinite(v) ? v : void 0;
12520
+ if (typeof v !== "string" || v.length === 0 || v.length > MAX_STRUCTURED_VALUE_CHARS) {
12521
+ return void 0;
12522
+ }
12523
+ if (kind === "gender") return GENDERS.includes(v) ? v : void 0;
12524
+ return v;
12525
+ }
12526
+ function readStructuredFields(value) {
12527
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
12528
+ const src = value;
12529
+ const out = {};
12530
+ for (const group of Object.keys(STRUCTURED_GROUPS)) {
12531
+ const raw = src[group];
12532
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) continue;
12533
+ const rawRec = raw;
12534
+ const kept = {};
12535
+ for (const [field, kind] of Object.entries(
12536
+ STRUCTURED_GROUPS[group]
12537
+ )) {
12538
+ const v = readField(rawRec[field], kind);
12539
+ if (v !== void 0) kept[field] = v;
12540
+ }
12541
+ if (Object.keys(kept).length > 0) out[group] = kept;
12542
+ }
12543
+ const mood = readField(src.mood, "string");
12544
+ if (mood !== void 0) out.mood = mood;
12545
+ return Object.keys(out).length > 0 ? out : void 0;
12546
+ }
12174
12547
  var clean = (u) => {
12175
12548
  const t = u?.trim();
12176
12549
  return t && t.length > 0 ? t : void 0;
@@ -27333,7 +27706,7 @@ precise subject \u2192 action details \u2192 scene/environment \u2192 lighting &
27333
27706
  - Transitions and camera terms on 2.5: state a transition's trigger point AND method in one sentence \u2014 "At the 5-second mark, the camera quickly transitions leftward using a left wipe combined with a natural dissolve." Basic shot and camera terms are written directly (push in / pull out / pan / track / orbit / dolly zoom / whip pan / hard cut / dissolve / one-shot / speed ramp); only niche terms need [term + descriptive explanation] \u2014 which is exactly what the pickers' compact hint mode emits versus their long hints.
27334
27707
 
27335
27708
  **References (when reference media is attached)**
27336
- - Refer to assets by ordinal in attachment order: "@Image 1", "Video 2", "Audio 1". Asset ORDER is priority \u2014 put the most identity-critical asset first. (In the editor, the \`{image:N:label}\` / \`{video:N}\` / \`{audio:N}\` prompt tokens auto-emit this binding \u2014 \`{image:1:person}\` resolves to "the person from @image_1" \u2014 so a wired reference and its mention stay in sync.)
27709
+ - Refer to assets by ordinal in attachment order: "@Image 1", "Video 2", "Audio 1". Asset ORDER is priority \u2014 put the most identity-critical asset first. (In the editor, the \`{image:N:label}\` / \`{video:N}\` / \`{audio:N}\` prompt tokens auto-emit this binding \u2014 \`{image:1:person}\` resolves to "the person from @image_1" \u2014 so a wired reference and its mention stay in sync. An API caller that passes \`connectedReferences\` can instead name a reference by its own id \u2014 \`{ref:<id>}\` / \`{ref:<id>:label}\` \u2014 and the platform substitutes the \`@image_N\` seat after it has numbered the references, so the client never computes N; a token whose reference was not attached drops to its label or name.)
27337
27710
  - Define each subject once, then reuse the label consistently: 'Define the woman in the red dress in Image 1 as the courier' \u2026 'the courier opens the door'. In multi-character scenes bind every character to its image ("the man from Image 1 hands the box to the woman from Image 2") and append: "do not generate duplicate copies of the same character".
27338
27711
  - Character identity: ONE close-up headshot + ONE full-body image is ideal. On the 2.0 SKUs do NOT attach multi-view/three-view character sheets \u2014 the model reads the views as separate people, causing identity drift and twin duplicates; 2.5 accepts multi-view images (see "Generation differences").
27339
27712
  - 4-5 assets total works best (1-2 character images + 1 scene image + 1 camera-movement video + 1 audio clip). Maxing out the 9-image/3-video/3-audio limits degrades feature priority and adherence.
@@ -27435,7 +27808,7 @@ precise subject \u2192 action details \u2192 scene/environment \u2192 lighting &
27435
27808
  - Nothing visual connected \u2192 text-to-video. A concrete aspect ratio is required (21:9 / 16:9 / 4:3 / 1:1 / 3:4 / 9:16 \u2014 no adaptive); Nodaro renders 16:9 unless one is picked.
27436
27809
 
27437
27810
  **References (when reference media is attached)**
27438
- - Refer to assets by ordinal in attachment order: "@Image 1", "Video 1", "Audio 1". Put the identity-critical asset first. (In the editor, the \`{image:N:label}\` / \`{video:N}\` / \`{audio:N}\` prompt tokens auto-emit this binding, so a wired reference and its mention stay in sync.)
27811
+ - Refer to assets by ordinal in attachment order: "@Image 1", "Video 1", "Audio 1". Put the identity-critical asset first. (In the editor, the \`{image:N:label}\` / \`{video:N}\` / \`{audio:N}\` prompt tokens auto-emit this binding, so a wired reference and its mention stay in sync. An API caller that passes \`connectedReferences\` can instead write \`{ref:<id>}\` / \`{ref:<id>:label}\` with the reference's own id \u2014 the platform substitutes the \`@image_N\` seat after numbering.)
27439
27812
  - Caps: 9 reference images; 3 reference videos, each 2-15s and \u226415s combined; 3 reference audio clips, \u226415s combined. Reference audio cannot be used alone \u2014 it must accompany an image or video reference.
27440
27813
  - Define each subject once, then reuse the label consistently ("the woman from @Image 1 \u2026 the woman opens the door"). A focused set of 4-5 assets beats maxing every cap.
27441
27814
  - Billing note: generated seconds AND reference-video input seconds bill at the same per-second rate; the first 5 input images are free and each extra image adds a small surcharge; audio input is free.
@@ -33187,8 +33560,8 @@ var SINGLE_PICKER_WIRING = [
33187
33560
  { kind: "single", nodeType: "furniture", label: "Furniture", valueField: "furniture", defaultValue: "sofa", catalogId: "furniture", entries: mapCat(shared.FURNITURE, "subcategory"), groupOrder: shared.FURNITURE_SUBCATEGORY_ORDER, groupLabels: shared.FURNITURE_SUBCATEGORY_LABELS },
33188
33561
  { kind: "single", nodeType: "held-prop", label: "Held Prop", valueField: "heldProp", defaultValue: "smartphone", catalogId: "held-prop", entries: mapCat(HELD_PROPS, "category"), groupOrder: HELD_PROP_CATEGORY_ORDER, groupLabels: HELD_PROP_CATEGORY_LABELS }
33189
33562
  ];
33190
- var STYLING_FIELDS2 = STYLING_DIMENSION_ORDER.map((d) => STYLING_FIELD_BY_DIMENSION[d]);
33191
- var PERSON_FIELDS2 = PERSON_DIMENSION_ORDER.map((d) => PERSON_FIELD_BY_DIMENSION[d]);
33563
+ var STYLING_FIELDS3 = STYLING_DIMENSION_ORDER.map((d) => STYLING_FIELD_BY_DIMENSION[d]);
33564
+ var PERSON_FIELDS3 = PERSON_DIMENSION_ORDER.map((d) => PERSON_FIELD_BY_DIMENSION[d]);
33192
33565
  var LIGHTING_FIELDS2 = LIGHTING_CATEGORY_ORDER.map((c) => LIGHTING_FIELD_BY_CATEGORY[c]);
33193
33566
  var TEMPORAL_FIELD_BY_CATEGORY2 = {
33194
33567
  speed: "temporalSpeed",
@@ -33224,7 +33597,7 @@ var MULTI_PICKER_WIRING = [
33224
33597
  kind: "multi",
33225
33598
  nodeType: "person",
33226
33599
  label: "Person",
33227
- fields: PERSON_FIELDS2,
33600
+ fields: PERSON_FIELDS3,
33228
33601
  catalogId: "person",
33229
33602
  catalogEntries: flatCat(PEOPLE),
33230
33603
  fieldOptions: optionsByDiscriminator(PEOPLE, (e) => e.dimension, PERSON_FIELD_BY_DIMENSION)
@@ -33233,7 +33606,7 @@ var MULTI_PICKER_WIRING = [
33233
33606
  kind: "multi",
33234
33607
  nodeType: "styling",
33235
33608
  label: "Styling",
33236
- fields: STYLING_FIELDS2,
33609
+ fields: STYLING_FIELDS3,
33237
33610
  catalogId: "styling",
33238
33611
  catalogEntries: flatCat(STYLINGS),
33239
33612
  fieldOptions: optionsByDiscriminator(STYLINGS, (e) => e.dimension, STYLING_FIELD_BY_DIMENSION)
@@ -33402,7 +33775,10 @@ exports.CAMERA_MOTION_IDS = CAMERA_MOTION_IDS;
33402
33775
  exports.CHARACTER_FX = CHARACTER_FX;
33403
33776
  exports.CHARACTER_FX_CATEGORY_LABELS = CHARACTER_FX_CATEGORY_LABELS;
33404
33777
  exports.CHARACTER_FX_CATEGORY_ORDER = CHARACTER_FX_CATEGORY_ORDER;
33778
+ exports.CHARACTER_FX_DURATIONS = CHARACTER_FX_DURATIONS;
33405
33779
  exports.CHARACTER_FX_IDS = CHARACTER_FX_IDS;
33780
+ exports.CHARACTER_FX_INTENSITIES = CHARACTER_FX_INTENSITIES;
33781
+ exports.CHARACTER_FX_POSITIONS = CHARACTER_FX_POSITIONS;
33406
33782
  exports.CINEMATIC_LOOK_TAIL = CINEMATIC_LOOK_TAIL;
33407
33783
  exports.COLOR_LOOKS = COLOR_LOOKS;
33408
33784
  exports.COLOR_LOOK_CATEGORY_LABELS = COLOR_LOOK_CATEGORY_LABELS;
@@ -33412,6 +33788,10 @@ exports.COMPOSITION_EFFECTS = COMPOSITION_EFFECTS;
33412
33788
  exports.COMPOSITION_EFFECT_IDS = COMPOSITION_EFFECT_IDS;
33413
33789
  exports.DEFAULT_IDENTITY_LOCK = DEFAULT_IDENTITY_LOCK;
33414
33790
  exports.DEFAULT_TEMPLATES = DEFAULT_TEMPLATES;
33791
+ exports.DIRECTION_ARRAY_CEILING = DIRECTION_ARRAY_CEILING;
33792
+ exports.DIRECTION_FIELDS = DIRECTION_FIELDS;
33793
+ exports.DIRECTION_ID_MAX_CHARS = DIRECTION_ID_MAX_CHARS;
33794
+ exports.DIRECTION_KEYS = DIRECTION_KEYS;
33415
33795
  exports.ERAS = ERAS;
33416
33796
  exports.ERA_CATEGORY_LABELS = ERA_CATEGORY_LABELS;
33417
33797
  exports.ERA_CATEGORY_ORDER = ERA_CATEGORY_ORDER;
@@ -33434,6 +33814,7 @@ exports.HELD_PROPS = HELD_PROPS;
33434
33814
  exports.HELD_PROP_CATEGORY_LABELS = HELD_PROP_CATEGORY_LABELS;
33435
33815
  exports.HELD_PROP_CATEGORY_ORDER = HELD_PROP_CATEGORY_ORDER;
33436
33816
  exports.HELD_PROP_IDS = HELD_PROP_IDS;
33817
+ exports.IMAGE_HINT_MODE_DEFAULT = IMAGE_HINT_MODE_DEFAULT;
33437
33818
  exports.IMAGE_REFERENCE_PROMPT_DOCTRINE = IMAGE_REFERENCE_PROMPT_DOCTRINE;
33438
33819
  exports.IMAGE_WIZARD_CATEGORIES = IMAGE_WIZARD_CATEGORIES;
33439
33820
  exports.INSTRUMENTATION_DEFAULT_DATA = INSTRUMENTATION_DEFAULT_DATA;
@@ -33511,6 +33892,7 @@ exports.POST_PROCESS_EFFECT_IDS = POST_PROCESS_EFFECT_IDS;
33511
33892
  exports.PRODUCTION_STYLES = PRODUCTION_STYLES;
33512
33893
  exports.PROMPT_AFFIX_CORE_FIELD_OVERRIDES = PROMPT_AFFIX_CORE_FIELD_OVERRIDES;
33513
33894
  exports.PROMPT_AFFIX_NODE_TYPES = PROMPT_AFFIX_NODE_TYPES;
33895
+ exports.PROMPT_HINT_SEPARATOR = PROMPT_HINT_SEPARATOR;
33514
33896
  exports.PROVIDER_CAPABILITIES = PROVIDER_CAPABILITIES;
33515
33897
  exports.PROVIDER_PROMPT_DOCTRINES = PROVIDER_PROMPT_DOCTRINES;
33516
33898
  exports.REFERENCE_IMAGE_ROLES = REFERENCE_IMAGE_ROLES;
@@ -33550,6 +33932,7 @@ exports.TRANSITION_DURATIONS = TRANSITION_DURATIONS;
33550
33932
  exports.TRANSITION_IDS = TRANSITION_IDS;
33551
33933
  exports.TRANSITION_INTENSITIES = TRANSITION_INTENSITIES;
33552
33934
  exports.TRANSITION_POSITIONS = TRANSITION_POSITIONS;
33935
+ exports.VIDEO_HINT_MODE_DEFAULT = VIDEO_HINT_MODE_DEFAULT;
33553
33936
  exports.VIDEO_WIZARD_CATEGORIES = VIDEO_WIZARD_CATEGORIES;
33554
33937
  exports.VOCAL_PRESENCE = VOCAL_PRESENCE;
33555
33938
  exports.VOCAL_PRESENCE_INSTRUMENTAL_ID = VOCAL_PRESENCE_INSTRUMENTAL_ID;
@@ -33647,10 +34030,12 @@ exports.composeNegative = composeNegative;
33647
34030
  exports.composePickerCatalogs = composePickerCatalogs;
33648
34031
  exports.composeSoundHintFromConnections = composeSoundHintFromConnections;
33649
34032
  exports.composeTransitionHintFromConnections = composeTransitionHintFromConnections;
34033
+ exports.composeVideoPromptText = composeVideoPromptText;
33650
34034
  exports.computeLlmChatFields = computeLlmChatFields;
33651
34035
  exports.computeNodePrompt = computeNodePrompt;
33652
34036
  exports.computePackSidecarCoverage = computePackSidecarCoverage;
33653
34037
  exports.deriveTerm = deriveTerm;
34038
+ exports.directionFieldsForSurface = directionFieldsForSurface;
33654
34039
  exports.expandImagePositionRefs = expandImagePositionRefs;
33655
34040
  exports.expandImageRefTokens = expandImageRefTokens;
33656
34041
  exports.filmStillPrefix = filmStillPrefix;
@@ -33841,9 +34226,11 @@ exports.isInstrumentalVocal = isInstrumentalVocal;
33841
34226
  exports.isSuspiciousDerivedTerm = isSuspiciousDerivedTerm;
33842
34227
  exports.isVantageFraming = isVantageFraming;
33843
34228
  exports.isWizardSupported = isWizardSupported;
34229
+ exports.joinPromptHints = joinPromptHints;
33844
34230
  exports.joinPromptParts = joinPromptParts;
33845
34231
  exports.listPickerCatalogs = listPickerCatalogs;
33846
34232
  exports.migratePersonValue = migratePersonValue;
34233
+ exports.modeForFamily = modeForFamily;
33847
34234
  exports.nodeHasInlinePrompt = nodeHasInlinePrompt;
33848
34235
  exports.nodeHasPromptField = nodeHasPromptField;
33849
34236
  exports.nodeSupportsPromptAffixes = nodeSupportsPromptAffixes;
@@ -33855,9 +34242,12 @@ exports.promptAffixCoreField = promptAffixCoreField;
33855
34242
  exports.promptBindsFirstFrame = promptBindsFirstFrame;
33856
34243
  exports.promptFieldCarriesAffixes = promptFieldCarriesAffixes;
33857
34244
  exports.promptPartSeparator = promptPartSeparator;
34245
+ exports.readDirectionFields = readDirectionFields;
34246
+ exports.readStructuredFields = readStructuredFields;
33858
34247
  exports.referenceRulesBlock = referenceRulesBlock;
33859
34248
  exports.registerCatalogPack = registerCatalogPack;
33860
34249
  exports.registerPersonPack = registerPersonPack;
34250
+ exports.renderDirectionHints = renderDirectionHints;
33861
34251
  exports.renderStructuredFields = renderStructuredFields;
33862
34252
  exports.resetCatalogPacks = resetCatalogPacks;
33863
34253
  exports.resetPersonPacks = resetPersonPacks;
@@ -33866,6 +34256,7 @@ exports.resolveCharacterMentions = resolveCharacterMentions;
33866
34256
  exports.resolveGeminiOmniI2vInputs = resolveGeminiOmniI2vInputs;
33867
34257
  exports.resolveLocationMentions = resolveLocationMentions;
33868
34258
  exports.resolvePrompt = resolvePrompt;
34259
+ exports.resolveRefIdTokens = resolveRefIdTokens;
33869
34260
  exports.resolveReferenceTokens = resolveReferenceTokens;
33870
34261
  exports.resolveSeedance2Inputs = resolveSeedance2Inputs;
33871
34262
  exports.resolveTemplate = resolveTemplate;