@nodaro/prompts 1.38.0 → 1.40.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.
Files changed (130) hide show
  1. package/dist/chunk-2EW5B7ZV.cjs +86 -0
  2. package/dist/chunk-2EW5B7ZV.cjs.map +1 -0
  3. package/dist/chunk-2P26SZX5.cjs +414 -0
  4. package/dist/chunk-2P26SZX5.cjs.map +1 -0
  5. package/dist/{chunk-7XKHDXCL.cjs → chunk-3U7X6JZN.cjs} +13 -12
  6. package/dist/chunk-3U7X6JZN.cjs.map +1 -0
  7. package/dist/chunk-4GKTOVFM.cjs +8 -0
  8. package/dist/chunk-4GKTOVFM.cjs.map +1 -0
  9. package/dist/{chunk-HRBBNODV.js → chunk-6GVFJLDL.js} +4 -3
  10. package/dist/chunk-6GVFJLDL.js.map +1 -0
  11. package/dist/{chunk-LVSH7K7R.cjs → chunk-C3NHNECH.cjs} +165 -88
  12. package/dist/chunk-C3NHNECH.cjs.map +1 -0
  13. package/dist/{chunk-CEPVQQVO.js → chunk-C46256GZ.js} +43 -5
  14. package/dist/chunk-C46256GZ.js.map +1 -0
  15. package/dist/{chunk-JKCR6WRZ.cjs → chunk-DQFQJECU.cjs} +43 -5
  16. package/dist/chunk-DQFQJECU.cjs.map +1 -0
  17. package/dist/{chunk-QDEWBBUR.js → chunk-DUXX6CBX.js} +12 -143
  18. package/dist/chunk-DUXX6CBX.js.map +1 -0
  19. package/dist/chunk-EAYEZXWT.js +388 -0
  20. package/dist/chunk-EAYEZXWT.js.map +1 -0
  21. package/dist/chunk-GILUVQQJ.js +6 -0
  22. package/dist/chunk-GILUVQQJ.js.map +1 -0
  23. package/dist/{chunk-KIYNOOPJ.js → chunk-GTDKDD7Y.js} +12 -6
  24. package/dist/chunk-GTDKDD7Y.js.map +1 -0
  25. package/dist/{chunk-QBEZMR2F.js → chunk-HQTHDTHN.js} +137 -62
  26. package/dist/chunk-HQTHDTHN.js.map +1 -0
  27. package/dist/{chunk-TLVX5PXD.cjs → chunk-IUCNJAHW.cjs} +13 -7
  28. package/dist/chunk-IUCNJAHW.cjs.map +1 -0
  29. package/dist/{chunk-ZFIXQRBZ.cjs → chunk-LXPKTI2K.cjs} +12 -83
  30. package/dist/chunk-LXPKTI2K.cjs.map +1 -0
  31. package/dist/{chunk-CVPB2N3Z.cjs → chunk-LZ53F5BN.cjs} +103 -5
  32. package/dist/chunk-LZ53F5BN.cjs.map +1 -0
  33. package/dist/{chunk-4FDNVNJE.js → chunk-N6VMPG5S.js} +12 -79
  34. package/dist/chunk-N6VMPG5S.js.map +1 -0
  35. package/dist/{chunk-LK2CZK5U.cjs → chunk-PWWM7Q3T.cjs} +7 -7
  36. package/dist/{chunk-LK2CZK5U.cjs.map → chunk-PWWM7Q3T.cjs.map} +1 -1
  37. package/dist/{chunk-N7TOWXDJ.js → chunk-QDUTMOF4.js} +3 -3
  38. package/dist/{chunk-N7TOWXDJ.js.map → chunk-QDUTMOF4.js.map} +1 -1
  39. package/dist/{chunk-NO6XHX4R.js → chunk-RB2F5JQF.js} +100 -7
  40. package/dist/chunk-RB2F5JQF.js.map +1 -0
  41. package/dist/{chunk-MENBHEAY.cjs → chunk-WRM52ZBN.cjs} +19 -161
  42. package/dist/chunk-WRM52ZBN.cjs.map +1 -0
  43. package/dist/chunk-YS6HOWMW.js +80 -0
  44. package/dist/chunk-YS6HOWMW.js.map +1 -0
  45. package/dist/entries/assembly.cjs +34 -25
  46. package/dist/entries/assembly.d.cts +121 -37
  47. package/dist/entries/assembly.d.ts +121 -37
  48. package/dist/entries/assembly.js +5 -4
  49. package/dist/entries/doctrine.cjs +46 -46
  50. package/dist/entries/doctrine.d.cts +3 -3
  51. package/dist/entries/doctrine.d.ts +3 -3
  52. package/dist/entries/doctrine.js +1 -1
  53. package/dist/entries/picker-catalogs.cjs +42 -42
  54. package/dist/entries/picker-catalogs.js +3 -3
  55. package/dist/entries/presets.cjs +49 -26
  56. package/dist/entries/presets.d.cts +53 -1
  57. package/dist/entries/presets.d.ts +53 -1
  58. package/dist/entries/presets.js +4 -1
  59. package/dist/entries/prompt-builder.cjs +135 -98
  60. package/dist/entries/prompt-builder.d.cts +22 -11
  61. package/dist/entries/prompt-builder.d.ts +22 -11
  62. package/dist/entries/prompt-builder.js +4 -3
  63. package/dist/entries/prompt-fields.cjs +41 -40
  64. package/dist/entries/prompt-fields.d.cts +2 -1
  65. package/dist/entries/prompt-fields.d.ts +2 -1
  66. package/dist/entries/prompt-fields.js +2 -1
  67. package/dist/index.cjs +339 -273
  68. package/dist/index.d.cts +4 -4
  69. package/dist/index.d.ts +4 -4
  70. package/dist/index.js +11 -9
  71. package/dist/{subject-registry-BUswuEVD.d.cts → subject-registry-CQi_CZfJ.d.cts} +78 -9
  72. package/dist/{subject-registry-D7V8PEG-.d.ts → subject-registry-DFiGx49v.d.ts} +78 -9
  73. package/package.json +2 -2
  74. package/src/__tests__/assemble-image-input-style-references.test.ts +173 -0
  75. package/src/__tests__/catalog-id-guard.test.ts +30 -0
  76. package/src/__tests__/factory-preset-previews.test.ts +123 -0
  77. package/src/__tests__/factory-preset-references.test.ts +222 -0
  78. package/src/__tests__/factory-presets-prototype-keys.test.ts +43 -0
  79. package/src/__tests__/frame-reference-slots.test.ts +43 -0
  80. package/src/__tests__/gemini-omni-inputs.test.ts +12 -10
  81. package/src/__tests__/provider-prompt-doctrine.test.ts +14 -0
  82. package/src/__tests__/user-direction-refs.test.ts +180 -0
  83. package/src/__tests__/veo-i2v-inputs.test.ts +16 -11
  84. package/src/assemble-image-input.ts +114 -13
  85. package/src/catalog-id-guard.ts +18 -2
  86. package/src/color-names.ts +192 -0
  87. package/src/direction-registry.ts +66 -5
  88. package/src/entries/assembly.ts +1 -0
  89. package/src/entries/prompt-builder.ts +2 -0
  90. package/src/factory-presets/generate-image.ts +29 -0
  91. package/src/factory-presets/index.ts +6 -1
  92. package/src/factory-presets/preview-files.generated.ts +4 -0
  93. package/src/factory-presets/previews.ts +40 -0
  94. package/src/factory-presets/references.ts +81 -0
  95. package/src/factory-presets/shared-image.ts +4 -0
  96. package/src/factory-presets/types.ts +8 -0
  97. package/src/frame-reference-slots.ts +92 -0
  98. package/src/gemini-omni-inputs.ts +23 -22
  99. package/src/image-reference-doctrine.ts +3 -3
  100. package/src/image-token-pattern.ts +13 -0
  101. package/src/node-prompt-fields.ts +5 -3
  102. package/src/own-entry.ts +11 -0
  103. package/src/prompt-builder.ts +4 -5
  104. package/src/prompt-style-section.ts +3 -3
  105. package/src/prompt-wizard-categories.ts +2 -0
  106. package/src/provider-prompt-doctrine.ts +45 -3
  107. package/src/ref-binding.ts +28 -3
  108. package/src/resolve-prompt.ts +2 -1
  109. package/src/seedance-2-inputs.ts +15 -40
  110. package/src/user-direction-refs.ts +110 -0
  111. package/src/veo-i2v-inputs.ts +24 -17
  112. package/src/video-reference-resolver.ts +1 -1
  113. package/dist/chunk-4FDNVNJE.js.map +0 -1
  114. package/dist/chunk-7XKHDXCL.cjs.map +0 -1
  115. package/dist/chunk-CEPVQQVO.js.map +0 -1
  116. package/dist/chunk-CVPB2N3Z.cjs.map +0 -1
  117. package/dist/chunk-HRBBNODV.js.map +0 -1
  118. package/dist/chunk-JKCR6WRZ.cjs.map +0 -1
  119. package/dist/chunk-KIYNOOPJ.js.map +0 -1
  120. package/dist/chunk-LVSH7K7R.cjs.map +0 -1
  121. package/dist/chunk-MENBHEAY.cjs.map +0 -1
  122. package/dist/chunk-NO6XHX4R.js.map +0 -1
  123. package/dist/chunk-QBEZMR2F.js.map +0 -1
  124. package/dist/chunk-QDEWBBUR.js.map +0 -1
  125. package/dist/chunk-TLVX5PXD.cjs.map +0 -1
  126. package/dist/chunk-UJKFHPZ7.js +0 -37
  127. package/dist/chunk-UJKFHPZ7.js.map +0 -1
  128. package/dist/chunk-W5SCZIOB.cjs +0 -43
  129. package/dist/chunk-W5SCZIOB.cjs.map +0 -1
  130. package/dist/chunk-ZFIXQRBZ.cjs.map +0 -1
@@ -0,0 +1,388 @@
1
+ import { renderTransitionBases, buildMoodHints, getFramingTerm, getFramingPromptHint, getLightingTerm, getLightingPromptHint, getExposureTerm, getExposurePromptHint, getTemporalTerm, getTemporalPromptHint, getCameraMotionTerm, getCameraMotionPromptHint, getPoseTerm, getPosePromptHint, getCompositionEffectTerm, getCompositionEffectPromptHint, getCameraFormatTerm, getCameraFormatPromptHint, getLensTerm, getLensPromptHint, getColorLookTerm, getColorLookPromptHint, buildAtmosphereHints, buildPostProcessHints, getStyleTerm, getStylePromptHint, buildAestheticHints, getPhotoGenreTerm, getPhotoGenrePromptHint, buildPhotographerHints, getRenderQualityTerm, getRenderQualityPromptHint, getSettingTerm, getSettingPromptHint, getEraTerm, getEraPromptHint, getBackdropTerm, getBackdropPromptHint, buildActionFxHints, getLoopSubjectTerm, getLoopSubjectPromptHint, composedHas, composedOption } from './chunk-SXXW4LCR.js';
2
+ import { deriveTerm } from './chunk-XAMHEW76.js';
3
+ import { getAnimalPromptHint, getAnimalTerm, getVehicle, getWeapon, getFurniture } from '@nodaro/shared/catalogs';
4
+
5
+ // src/color-names.ts
6
+ var NAMED = [
7
+ // Neutrals
8
+ ["black", "#000000"],
9
+ ["charcoal", "#36454F"],
10
+ ["dark gray", "#555555"],
11
+ ["slate gray", "#708090"],
12
+ ["gray", "#808080"],
13
+ ["warm gray", "#9A9088"],
14
+ ["silver", "#C0C0C0"],
15
+ ["light gray", "#D3D3D3"],
16
+ ["off-white", "#F2F0EB"],
17
+ ["white", "#FFFFFF"],
18
+ ["ivory", "#FFFFF0"],
19
+ ["cream", "#FFFDD0"],
20
+ ["eggshell", "#F0EAD6"],
21
+ ["linen", "#FAF0E6"],
22
+ ["champagne", "#F7E7CE"],
23
+ ["wheat", "#F5DEB3"],
24
+ // Earth tones and browns
25
+ ["sand", "#C2B280"],
26
+ ["tan", "#D2B48C"],
27
+ ["khaki", "#C3B091"],
28
+ ["taupe", "#8B8589"],
29
+ ["camel", "#C19A6B"],
30
+ ["caramel", "#C68E17"],
31
+ ["brown", "#964B00"],
32
+ ["chocolate", "#7B3F00"],
33
+ ["coffee", "#6F4E37"],
34
+ ["espresso", "#4E312D"],
35
+ ["walnut", "#773F1A"],
36
+ ["chestnut", "#954535"],
37
+ ["mahogany", "#C04000"],
38
+ ["rust", "#B7410E"],
39
+ ["terracotta", "#E2725B"],
40
+ ["copper", "#B87333"],
41
+ ["bronze", "#CD7F32"],
42
+ ["ochre", "#CC7722"],
43
+ // Oranges
44
+ ["burnt orange", "#CC5500"],
45
+ ["orange", "#FFA500"],
46
+ ["tangerine", "#F28500"],
47
+ ["apricot", "#FBCEB1"],
48
+ ["peach", "#FFCBA4"],
49
+ ["coral", "#FF7F50"],
50
+ ["salmon", "#FA8072"],
51
+ // Reds
52
+ ["red", "#FF0000"],
53
+ ["scarlet", "#FF2400"],
54
+ ["crimson", "#DC143C"],
55
+ ["cherry red", "#D2042D"],
56
+ ["brick red", "#CB4154"],
57
+ ["burgundy", "#800020"],
58
+ ["maroon", "#800000"],
59
+ ["wine red", "#722F37"],
60
+ ["oxblood", "#4A0000"],
61
+ // Pinks
62
+ ["raspberry", "#E30B5C"],
63
+ ["rose", "#FF007F"],
64
+ ["hot pink", "#FF69B4"],
65
+ ["pink", "#FFC0CB"],
66
+ ["blush pink", "#E8B4B8"],
67
+ ["dusty rose", "#C08081"],
68
+ ["mauve", "#B784A7"],
69
+ // Purples
70
+ ["magenta", "#FF00FF"],
71
+ ["orchid", "#DA70D6"],
72
+ ["plum", "#8E4585"],
73
+ ["eggplant", "#614051"],
74
+ ["dusty purple", "#6E5A7E"],
75
+ ["lilac", "#C8A2C8"],
76
+ ["lavender", "#B57EDC"],
77
+ ["pale lavender", "#E6E6FA"],
78
+ ["amethyst", "#9966CC"],
79
+ ["violet", "#8F00FF"],
80
+ ["purple", "#800080"],
81
+ ["indigo", "#4B0082"],
82
+ // Blues
83
+ ["navy blue", "#000080"],
84
+ ["midnight blue", "#191970"],
85
+ ["prussian blue", "#003153"],
86
+ ["dusky blue", "#4B5E7D"],
87
+ ["royal blue", "#4169E1"],
88
+ ["cobalt blue", "#0047AB"],
89
+ ["blue", "#0000FF"],
90
+ ["cornflower blue", "#6495ED"],
91
+ ["denim blue", "#1560BD"],
92
+ ["steel blue", "#4682B4"],
93
+ ["slate blue", "#6A5ACD"],
94
+ ["periwinkle", "#CCCCFF"],
95
+ ["sky blue", "#87CEEB"],
96
+ ["baby blue", "#89CFF0"],
97
+ ["powder blue", "#B0E0E6"],
98
+ ["ice blue", "#D6ECEF"],
99
+ ["azure", "#007FFF"],
100
+ ["cerulean", "#007BA7"],
101
+ ["petrol blue", "#005F6A"],
102
+ // Cyans and teals
103
+ ["cyan", "#00FFFF"],
104
+ ["turquoise", "#40E0D0"],
105
+ ["aquamarine", "#7FFFD4"],
106
+ ["teal", "#008080"],
107
+ ["dark teal", "#014D4E"],
108
+ ["dark slate gray", "#2F4F4F"],
109
+ // Greens
110
+ ["sea green", "#2E8B57"],
111
+ ["emerald green", "#50C878"],
112
+ ["jade green", "#00A86B"],
113
+ ["mint green", "#98FF98"],
114
+ ["seafoam green", "#93E9BE"],
115
+ ["sage green", "#9CAF88"],
116
+ ["olive green", "#708238"],
117
+ ["olive", "#808000"],
118
+ ["moss green", "#8A9A5B"],
119
+ ["forest green", "#228B22"],
120
+ ["hunter green", "#355E3B"],
121
+ ["bottle green", "#006A4E"],
122
+ ["dark green", "#013220"],
123
+ ["green", "#008000"],
124
+ ["kelly green", "#4CBB17"],
125
+ ["lime green", "#32CD32"],
126
+ ["chartreuse", "#7FFF00"],
127
+ ["pistachio", "#93C572"],
128
+ // Yellows and golds
129
+ ["yellow", "#FFFF00"],
130
+ ["lemon yellow", "#FFF44F"],
131
+ ["pale yellow", "#FDFD96"],
132
+ ["canary yellow", "#FFEF00"],
133
+ ["mustard yellow", "#E1AD01"],
134
+ ["gold", "#FFD700"],
135
+ ["amber", "#FFBF00"],
136
+ ["honey", "#F0A830"],
137
+ ["saffron", "#F4C430"]
138
+ ];
139
+ var HEX_RE = /^#[0-9a-f]{6}$/i;
140
+ function channel(v) {
141
+ const c = v / 255;
142
+ return c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
143
+ }
144
+ function labPivot(t) {
145
+ return t > 216 / 24389 ? Math.cbrt(t) : (24389 / 27 * t + 16) / 116;
146
+ }
147
+ function toLab(hex) {
148
+ const r = channel(parseInt(hex.slice(1, 3), 16));
149
+ const g = channel(parseInt(hex.slice(3, 5), 16));
150
+ const b = channel(parseInt(hex.slice(5, 7), 16));
151
+ const x = labPivot((0.4124564 * r + 0.3575761 * g + 0.1804375 * b) / 0.95047);
152
+ const y = labPivot(0.2126729 * r + 0.7151522 * g + 0.072175 * b);
153
+ const z = labPivot((0.0193339 * r + 0.119192 * g + 0.9503041 * b) / 1.08883);
154
+ return [116 * y - 16, 500 * (x - y), 200 * (y - z)];
155
+ }
156
+ var namedLab = null;
157
+ function nearestColorName(hex) {
158
+ if (!HEX_RE.test(hex)) return "";
159
+ namedLab ??= NAMED.map(([name, value]) => [name, toLab(value)]);
160
+ const [l, a, b] = toLab(hex);
161
+ let best = "";
162
+ let bestDistance = Infinity;
163
+ for (const [name, [nl, na, nb]] of namedLab) {
164
+ const d = (l - nl) ** 2 + (a - na) ** 2 + (b - nb) ** 2;
165
+ if (d < bestDistance) {
166
+ bestDistance = d;
167
+ best = name;
168
+ }
169
+ }
170
+ return best;
171
+ }
172
+
173
+ // src/user-direction-refs.ts
174
+ var USER_DIRECTION_REF_KINDS = ["palette", "moodboard"];
175
+ var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
176
+ function parseUserDirectionRef(value) {
177
+ if (typeof value !== "string") return null;
178
+ for (const kind of USER_DIRECTION_REF_KINDS) {
179
+ const prefix = `${kind}:`;
180
+ if (value.startsWith(prefix)) {
181
+ const id = value.slice(prefix.length);
182
+ return { kind, id, wellFormed: UUID_RE.test(id) };
183
+ }
184
+ }
185
+ return null;
186
+ }
187
+ function userDirectionRefValue(kind, id) {
188
+ return `${kind}:${id}`;
189
+ }
190
+ function oneLine(text) {
191
+ return (text ?? "").replace(/\s+/g, " ").trim();
192
+ }
193
+ var HEX_RE2 = /^#[0-9a-f]{6}$/i;
194
+ function renderPaletteClause(colors) {
195
+ const named = colors.filter((c) => HEX_RE2.test(c)).map((c) => `${nearestColorName(c)} ${c.toUpperCase()}`);
196
+ return named.length > 0 ? `color palette: ${named.join(", ")}` : "";
197
+ }
198
+ function renderMoodboardClause(description) {
199
+ return oneLine(description);
200
+ }
201
+ function styleReferenceDescription(index, caption) {
202
+ const cap = oneLine(caption);
203
+ const tail = cap ? ` (${cap})` : "";
204
+ return index === 0 ? `match the colors, light, texture and mood of this style reference${tail}, not its subject or layout` : `another style reference${tail}`;
205
+ }
206
+
207
+ // src/direction-registry.ts
208
+ var perId = (full, compact) => (ids, mode) => {
209
+ const out = [];
210
+ for (const id of ids) {
211
+ const frag = mode === "compact" ? compact(id) : full(id);
212
+ if (frag.length > 0) out.push(frag);
213
+ }
214
+ return out;
215
+ };
216
+ var viaListBuilder = (build) => (ids, mode) => build(ids.length === 1 ? ids[0] : [...ids], mode).filter((s) => s.length > 0);
217
+ var viaStringBuilder = (build) => (ids, mode) => {
218
+ const s = build(ids.length === 1 ? ids[0] : [...ids], mode);
219
+ return s.length > 0 ? [s] : [];
220
+ };
221
+ var viaMood = (ids, mode) => buildMoodHints({ mood: ids.length === 1 ? ids[0] : [...ids] }, mode).filter(
222
+ (s) => s.length > 0
223
+ );
224
+ var framing = perId(getFramingPromptHint, getFramingTerm);
225
+ var lighting = perId(getLightingPromptHint, getLightingTerm);
226
+ var exposure = perId(getExposurePromptHint, getExposureTerm);
227
+ var temporal = perId(getTemporalPromptHint, getTemporalTerm);
228
+ var DIRECTION_FIELDS = [
229
+ { key: "cameraMotion", surface: "video", family: "motion", maxPicks: 1, render: perId(getCameraMotionPromptHint, getCameraMotionTerm) },
230
+ // Composition (the Framing catalog, one row per category).
231
+ { key: "shotSize", surface: "both", family: "look", maxPicks: 1, render: framing },
232
+ { key: "angle", surface: "both", family: "look", maxPicks: 1, render: framing },
233
+ { key: "coverage", surface: "both", family: "look", maxPicks: 1, render: framing },
234
+ { key: "composition", surface: "both", family: "look", maxPicks: 2, render: framing },
235
+ { key: "vantage", surface: "both", family: "look", maxPicks: 1, render: framing },
236
+ { key: "pose", surface: "both", family: "look", maxPicks: 1, render: perId(getPosePromptHint, getPoseTerm) },
237
+ { key: "compositionEffect", surface: "both", family: "look", maxPicks: 1, render: perId(getCompositionEffectPromptHint, getCompositionEffectTerm) },
238
+ // Camera.
239
+ { key: "cameraFormat", surface: "both", family: "look", styleGroup: "film", maxPicks: 1, render: perId(getCameraFormatPromptHint, getCameraFormatTerm) },
240
+ { key: "lens", surface: "both", family: "look", maxPicks: 1, render: perId(getLensPromptHint, getLensTerm) },
241
+ // Exposure (stills only — a video's exposure rides its own temporal levers).
242
+ { key: "aperture", surface: "image", family: "look", maxPicks: 1, render: exposure },
243
+ { key: "shutterSpeed", surface: "image", family: "look", maxPicks: 1, render: exposure },
244
+ { key: "isoValue", surface: "image", family: "look", maxPicks: 1, render: exposure },
245
+ // Light (the Lighting catalog, one row per category).
246
+ { key: "timeOfDay", surface: "both", family: "look", maxPicks: 1, render: lighting },
247
+ { key: "lightingStyle", surface: "both", family: "look", maxPicks: 2, render: lighting },
248
+ { key: "lightingDirection", surface: "both", family: "look", maxPicks: 1, render: lighting },
249
+ { key: "lightingRatio", surface: "both", family: "look", maxPicks: 1, render: lighting },
250
+ { key: "colorTemperature", surface: "both", family: "look", maxPicks: 1, render: lighting },
251
+ { key: "colorLook", surface: "both", family: "look", styleGroup: "film", maxPicks: 1, userRef: "palette", render: perId(getColorLookPromptHint, getColorLookTerm) },
252
+ { key: "atmosphere", surface: "both", family: "look", maxPicks: 2, render: viaListBuilder(buildAtmosphereHints) },
253
+ { key: "postProcess", surface: "image", family: "look", maxPicks: 2, render: viaListBuilder(buildPostProcessHints) },
254
+ // Style.
255
+ { key: "style", surface: "both", family: "look", styleGroup: "film", maxPicks: 1, userRef: "moodboard", render: perId(getStylePromptHint, getStyleTerm) },
256
+ { key: "mood", surface: "both", family: "look", maxPicks: 2, render: viaMood },
257
+ { key: "aesthetic", surface: "both", family: "look", maxPicks: 2, render: viaStringBuilder(buildAestheticHints) },
258
+ { key: "photoGenre", surface: "image", family: "look", maxPicks: 1, render: perId(getPhotoGenrePromptHint, getPhotoGenreTerm) },
259
+ { key: "photographer", surface: "image", family: "look", maxPicks: 2, render: viaStringBuilder(buildPhotographerHints) },
260
+ { key: "renderQuality", surface: "image", family: "look", maxPicks: 1, render: perId(getRenderQualityPromptHint, getRenderQualityTerm) },
261
+ // Scene.
262
+ { key: "setting", surface: "both", family: "look", maxPicks: 1, render: perId(getSettingPromptHint, getSettingTerm) },
263
+ { key: "era", surface: "both", family: "look", styleGroup: "film", maxPicks: 1, render: perId(getEraPromptHint, getEraTerm) },
264
+ { key: "backdrop", surface: "both", family: "look", maxPicks: 1, render: perId(getBackdropPromptHint, getBackdropTerm) },
265
+ // Motion & time.
266
+ { key: "actionFx", surface: "video", family: "motion", maxPicks: 2, render: viaListBuilder(buildActionFxHints) },
267
+ { key: "temporalSpeed", surface: "video", family: "motion", maxPicks: 1, render: temporal },
268
+ { key: "temporalFreeze", surface: "video", family: "motion", maxPicks: 1, render: temporal },
269
+ { key: "temporalDirection", surface: "video", family: "motion", maxPicks: 1, render: temporal },
270
+ { key: "temporalShutter", surface: "video", family: "motion", maxPicks: 1, render: temporal },
271
+ { key: "transition", surface: "video", family: "motion", maxPicks: 2, render: renderTransitionBases },
272
+ { key: "loopSubject", surface: "video", family: "motion", maxPicks: 1, render: perId(getLoopSubjectPromptHint, getLoopSubjectTerm) },
273
+ // ── LEGACY BLOCK — see the table doc above. Placed LAST, in today's exact
274
+ // `composePromptText` order, so every pre-registry caller is byte-identical.
275
+ { key: "framingId", surface: "both", family: "look", maxPicks: 1, render: framing },
276
+ { key: "framingAngleId", surface: "both", family: "look", maxPicks: 1, render: framing },
277
+ { key: "lightingId", surface: "both", family: "look", maxPicks: 1, render: lighting },
278
+ { key: "lensId", surface: "both", family: "look", maxPicks: 1, render: perId(getLensPromptHint, getLensTerm) },
279
+ { key: "cameraFormatId", surface: "both", family: "look", styleGroup: "film", maxPicks: 1, render: perId(getCameraFormatPromptHint, getCameraFormatTerm) }
280
+ ];
281
+ var DIRECTION_SPECS = DIRECTION_FIELDS;
282
+ var DIRECTION_KEYS = DIRECTION_FIELDS.map((f) => f.key);
283
+ var FILM_STYLE_KEYS = DIRECTION_SPECS.filter(
284
+ (f) => f.styleGroup === "film"
285
+ ).map((f) => f.key);
286
+ function directionKeyForUserRef(kind) {
287
+ const row = DIRECTION_SPECS.find((f) => f.userRef === kind);
288
+ if (!row) throw new Error(`no direction row takes a ${kind} reference`);
289
+ return row.key;
290
+ }
291
+ function userRefKindOfDirectionKey(key) {
292
+ return DIRECTION_SPECS.find((f) => f.key === key)?.userRef;
293
+ }
294
+ var IMAGE_HINT_MODE_DEFAULT = "full";
295
+ var VIDEO_HINT_MODE_DEFAULT = { look: "full", motion: "compact" };
296
+ function modeForFamily(mode, family) {
297
+ return typeof mode === "string" ? mode : family === "motion" ? mode.motion : mode.look;
298
+ }
299
+ var DIRECTION_ARRAY_CEILING = 8;
300
+ var DIRECTION_ID_MAX_CHARS = 100;
301
+ function normalizeDirectionIds(value, maxPicks) {
302
+ const ids = [];
303
+ if (typeof value === "string") {
304
+ if (value) ids.push(value);
305
+ } else if (Array.isArray(value)) {
306
+ for (const v of value) {
307
+ if (ids.length >= maxPicks) break;
308
+ if (typeof v === "string" && v && !ids.includes(v)) ids.push(v);
309
+ }
310
+ }
311
+ return ids.slice(0, maxPicks);
312
+ }
313
+ function renderRow(spec, ids, mode, refs) {
314
+ if (spec.userRef === void 0 || !ids.some((id) => parseUserDirectionRef(id) !== null)) {
315
+ return spec.render(ids, mode);
316
+ }
317
+ return ids.flatMap((id) => {
318
+ const ref = parseUserDirectionRef(id);
319
+ if (ref === null) return spec.render([id], mode);
320
+ const clause = ref.kind === spec.userRef ? refs?.get(id) : void 0;
321
+ return clause ? [clause] : [];
322
+ });
323
+ }
324
+ function directionFieldsForSurface(surface) {
325
+ return DIRECTION_SPECS.filter((f) => f.surface === "both" || f.surface === surface);
326
+ }
327
+ function renderDirectionHintClauses(direction, opts) {
328
+ if (!direction) return [];
329
+ const mode = opts.mode ?? "full";
330
+ const out = [];
331
+ const seen = /* @__PURE__ */ new Set();
332
+ for (const spec of DIRECTION_SPECS) {
333
+ if (spec.surface !== "both" && spec.surface !== opts.surface) continue;
334
+ const ids = normalizeDirectionIds(
335
+ direction[spec.key],
336
+ spec.maxPicks
337
+ );
338
+ if (ids.length === 0) continue;
339
+ for (const hint of renderRow(spec, ids, modeForFamily(mode, spec.family), opts.refs)) {
340
+ if (hint.length > 0 && !seen.has(hint)) {
341
+ seen.add(hint);
342
+ out.push({
343
+ key: spec.key,
344
+ family: spec.family,
345
+ ...spec.styleGroup !== void 0 ? { styleGroup: spec.styleGroup } : {},
346
+ text: hint
347
+ });
348
+ }
349
+ }
350
+ }
351
+ return out;
352
+ }
353
+ function renderDirectionHints(direction, opts) {
354
+ return renderDirectionHintClauses(direction, opts).map((c) => c.text);
355
+ }
356
+ function curatedAnimalPromptHint(id) {
357
+ if (!id) return "";
358
+ if (!composedHas("animals", id)) return "";
359
+ return composedOption("animals", id)?.promptHint ?? getAnimalPromptHint(id);
360
+ }
361
+ function curatedAnimalTerm(id) {
362
+ if (!id) return "";
363
+ if (!composedHas("animals", id)) return "";
364
+ return composedOption("animals", id)?.term ?? getAnimalTerm(id);
365
+ }
366
+ function objectEntityText(catalogId, id, stock, stockHint, stockTerm) {
367
+ if (!id || !composedHas(catalogId, id)) return { hint: "", term: "" };
368
+ const composed = composedOption(catalogId, id);
369
+ if (composed) return { hint: composed.promptHint, term: composed.term };
370
+ if (!stock) return { hint: "", term: "" };
371
+ return { hint: stockHint(stock), term: stockTerm(stock) };
372
+ }
373
+ function objectEntityTerm(entry) {
374
+ return entry.term ?? deriveTerm(entry.label);
375
+ }
376
+ function curatedVehicleText(id) {
377
+ return objectEntityText("vehicles", id, getVehicle(id), (e) => `featuring a ${e.label.toLowerCase()}, ${e.description}`, objectEntityTerm);
378
+ }
379
+ function curatedWeaponText(id) {
380
+ return objectEntityText("weapons", id, getWeapon(id), (e) => `with a ${e.label.toLowerCase()}, ${e.description}`, objectEntityTerm);
381
+ }
382
+ function curatedFurnitureText(id) {
383
+ return objectEntityText("furniture", id, getFurniture(id), (e) => `including a ${e.label.toLowerCase()}, ${e.description}`, objectEntityTerm);
384
+ }
385
+
386
+ export { DIRECTION_ARRAY_CEILING, DIRECTION_FIELDS, DIRECTION_ID_MAX_CHARS, DIRECTION_KEYS, FILM_STYLE_KEYS, IMAGE_HINT_MODE_DEFAULT, USER_DIRECTION_REF_KINDS, VIDEO_HINT_MODE_DEFAULT, curatedAnimalPromptHint, curatedAnimalTerm, curatedFurnitureText, curatedVehicleText, curatedWeaponText, directionFieldsForSurface, directionKeyForUserRef, modeForFamily, nearestColorName, parseUserDirectionRef, renderDirectionHintClauses, renderDirectionHints, renderMoodboardClause, renderPaletteClause, styleReferenceDescription, userDirectionRefValue, userRefKindOfDirectionKey };
387
+ //# sourceMappingURL=chunk-EAYEZXWT.js.map
388
+ //# sourceMappingURL=chunk-EAYEZXWT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/color-names.ts","../src/user-direction-refs.ts","../src/direction-registry.ts","../src/shared-catalog-overlay.ts"],"names":["HEX_RE"],"mappings":"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","file":"chunk-EAYEZXWT.js","sourcesContent":["/**\n * Plain colour names for a hex value — what a saved colour palette reads as\n * in a prompt (\"deep teal #0F4C5C\"). A model follows a named colour more\n * reliably than a bare hex code, and the hex keeps the exact value.\n *\n * NEAREST NAME, NOT A CLASSIFIER: a fixed table of everyday colour names, each\n * with a representative value, and the one closest to the input in CIE Lab\n * (ΔE 1976 — Euclidean distance in Lab, which tracks perceived difference far\n * better than RGB). Deterministic, dependency-free, and a name is always one a\n * person would say. Ties go to the earlier row.\n */\n\n/** Everyday colour names and a representative sRGB value for each. */\nconst NAMED: ReadonlyArray<readonly [name: string, hex: string]> = [\n // Neutrals\n [\"black\", \"#000000\"],\n [\"charcoal\", \"#36454F\"],\n [\"dark gray\", \"#555555\"],\n [\"slate gray\", \"#708090\"],\n [\"gray\", \"#808080\"],\n [\"warm gray\", \"#9A9088\"],\n [\"silver\", \"#C0C0C0\"],\n [\"light gray\", \"#D3D3D3\"],\n [\"off-white\", \"#F2F0EB\"],\n [\"white\", \"#FFFFFF\"],\n [\"ivory\", \"#FFFFF0\"],\n [\"cream\", \"#FFFDD0\"],\n [\"eggshell\", \"#F0EAD6\"],\n [\"linen\", \"#FAF0E6\"],\n [\"champagne\", \"#F7E7CE\"],\n [\"wheat\", \"#F5DEB3\"],\n // Earth tones and browns\n [\"sand\", \"#C2B280\"],\n [\"tan\", \"#D2B48C\"],\n [\"khaki\", \"#C3B091\"],\n [\"taupe\", \"#8B8589\"],\n [\"camel\", \"#C19A6B\"],\n [\"caramel\", \"#C68E17\"],\n [\"brown\", \"#964B00\"],\n [\"chocolate\", \"#7B3F00\"],\n [\"coffee\", \"#6F4E37\"],\n [\"espresso\", \"#4E312D\"],\n [\"walnut\", \"#773F1A\"],\n [\"chestnut\", \"#954535\"],\n [\"mahogany\", \"#C04000\"],\n [\"rust\", \"#B7410E\"],\n [\"terracotta\", \"#E2725B\"],\n [\"copper\", \"#B87333\"],\n [\"bronze\", \"#CD7F32\"],\n [\"ochre\", \"#CC7722\"],\n // Oranges\n [\"burnt orange\", \"#CC5500\"],\n [\"orange\", \"#FFA500\"],\n [\"tangerine\", \"#F28500\"],\n [\"apricot\", \"#FBCEB1\"],\n [\"peach\", \"#FFCBA4\"],\n [\"coral\", \"#FF7F50\"],\n [\"salmon\", \"#FA8072\"],\n // Reds\n [\"red\", \"#FF0000\"],\n [\"scarlet\", \"#FF2400\"],\n [\"crimson\", \"#DC143C\"],\n [\"cherry red\", \"#D2042D\"],\n [\"brick red\", \"#CB4154\"],\n [\"burgundy\", \"#800020\"],\n [\"maroon\", \"#800000\"],\n [\"wine red\", \"#722F37\"],\n [\"oxblood\", \"#4A0000\"],\n // Pinks\n [\"raspberry\", \"#E30B5C\"],\n [\"rose\", \"#FF007F\"],\n [\"hot pink\", \"#FF69B4\"],\n [\"pink\", \"#FFC0CB\"],\n [\"blush pink\", \"#E8B4B8\"],\n [\"dusty rose\", \"#C08081\"],\n [\"mauve\", \"#B784A7\"],\n // Purples\n [\"magenta\", \"#FF00FF\"],\n [\"orchid\", \"#DA70D6\"],\n [\"plum\", \"#8E4585\"],\n [\"eggplant\", \"#614051\"],\n [\"dusty purple\", \"#6E5A7E\"],\n [\"lilac\", \"#C8A2C8\"],\n [\"lavender\", \"#B57EDC\"],\n [\"pale lavender\", \"#E6E6FA\"],\n [\"amethyst\", \"#9966CC\"],\n [\"violet\", \"#8F00FF\"],\n [\"purple\", \"#800080\"],\n [\"indigo\", \"#4B0082\"],\n // Blues\n [\"navy blue\", \"#000080\"],\n [\"midnight blue\", \"#191970\"],\n [\"prussian blue\", \"#003153\"],\n [\"dusky blue\", \"#4B5E7D\"],\n [\"royal blue\", \"#4169E1\"],\n [\"cobalt blue\", \"#0047AB\"],\n [\"blue\", \"#0000FF\"],\n [\"cornflower blue\", \"#6495ED\"],\n [\"denim blue\", \"#1560BD\"],\n [\"steel blue\", \"#4682B4\"],\n [\"slate blue\", \"#6A5ACD\"],\n [\"periwinkle\", \"#CCCCFF\"],\n [\"sky blue\", \"#87CEEB\"],\n [\"baby blue\", \"#89CFF0\"],\n [\"powder blue\", \"#B0E0E6\"],\n [\"ice blue\", \"#D6ECEF\"],\n [\"azure\", \"#007FFF\"],\n [\"cerulean\", \"#007BA7\"],\n [\"petrol blue\", \"#005F6A\"],\n // Cyans and teals\n [\"cyan\", \"#00FFFF\"],\n [\"turquoise\", \"#40E0D0\"],\n [\"aquamarine\", \"#7FFFD4\"],\n [\"teal\", \"#008080\"],\n [\"dark teal\", \"#014D4E\"],\n [\"dark slate gray\", \"#2F4F4F\"],\n // Greens\n [\"sea green\", \"#2E8B57\"],\n [\"emerald green\", \"#50C878\"],\n [\"jade green\", \"#00A86B\"],\n [\"mint green\", \"#98FF98\"],\n [\"seafoam green\", \"#93E9BE\"],\n [\"sage green\", \"#9CAF88\"],\n [\"olive green\", \"#708238\"],\n [\"olive\", \"#808000\"],\n [\"moss green\", \"#8A9A5B\"],\n [\"forest green\", \"#228B22\"],\n [\"hunter green\", \"#355E3B\"],\n [\"bottle green\", \"#006A4E\"],\n [\"dark green\", \"#013220\"],\n [\"green\", \"#008000\"],\n [\"kelly green\", \"#4CBB17\"],\n [\"lime green\", \"#32CD32\"],\n [\"chartreuse\", \"#7FFF00\"],\n [\"pistachio\", \"#93C572\"],\n // Yellows and golds\n [\"yellow\", \"#FFFF00\"],\n [\"lemon yellow\", \"#FFF44F\"],\n [\"pale yellow\", \"#FDFD96\"],\n [\"canary yellow\", \"#FFEF00\"],\n [\"mustard yellow\", \"#E1AD01\"],\n [\"gold\", \"#FFD700\"],\n [\"amber\", \"#FFBF00\"],\n [\"honey\", \"#F0A830\"],\n [\"saffron\", \"#F4C430\"],\n]\n\nconst HEX_RE = /^#[0-9a-f]{6}$/i\n\ntype Lab = readonly [l: number, a: number, b: number]\n\nfunction channel(v: number): number {\n const c = v / 255\n return c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4\n}\n\nfunction labPivot(t: number): number {\n return t > 216 / 24389 ? Math.cbrt(t) : (24389 / 27 * t + 16) / 116\n}\n\n/** sRGB hex → CIE Lab (D65). Only called with a value that passed `HEX_RE`. */\nfunction toLab(hex: string): Lab {\n const r = channel(parseInt(hex.slice(1, 3), 16))\n const g = channel(parseInt(hex.slice(3, 5), 16))\n const b = channel(parseInt(hex.slice(5, 7), 16))\n const x = labPivot((0.4124564 * r + 0.3575761 * g + 0.1804375 * b) / 0.95047)\n const y = labPivot(0.2126729 * r + 0.7151522 * g + 0.072175 * b)\n const z = labPivot((0.0193339 * r + 0.119192 * g + 0.9503041 * b) / 1.08883)\n return [116 * y - 16, 500 * (x - y), 200 * (y - z)]\n}\n\nlet namedLab: ReadonlyArray<readonly [string, Lab]> | null = null\n\n/**\n * The everyday name nearest to `hex` (`#RRGGBB`, any case), or `\"\"` when the\n * value is not a `#RRGGBB` colour.\n */\nexport function nearestColorName(hex: string): string {\n if (!HEX_RE.test(hex)) return \"\"\n namedLab ??= NAMED.map(([name, value]) => [name, toLab(value)] as const)\n const [l, a, b] = toLab(hex)\n let best = \"\"\n let bestDistance = Infinity\n for (const [name, [nl, na, nb]] of namedLab) {\n const d = (l - nl) ** 2 + (a - na) ** 2 + (b - nb) ** 2\n if (d < bestDistance) {\n bestDistance = d\n best = name\n }\n }\n return best\n}\n","/**\n * USER-OWNED DIRECTION REFERENCES — a `direction` value that names one of the\n * caller's own saved resources instead of a catalog id.\n *\n * Two rows of the direction registry take one (their `userRef` column):\n * - `colorLook: \"palette:<uuid>\"` — a saved colour palette;\n * - `style: \"moodboard:<uuid>\"` — a saved moodboard.\n * The prefix namespaces them, so they never collide with a catalog id\n * (catalog ids are slugs; none carries a colon).\n *\n * The wire carries the id, never the resolved text, so a re-run resolves it\n * again and an edited palette reaches the next run. RESOLVING is a database\n * read, so it happens in the platform before the (pure, synchronous) fold:\n * the caller hands the fold a map of value → rendered clause\n * (`renderDirectionHintClauses`' `refs`, `assembleImageInput`'s\n * `directionRefs`), and a moodboard's images as fill-only style references\n * (`assembleImageInput`'s `styleReferences`). This module holds what is pure:\n * the grammar and the WORDING of those clauses and reference lines.\n */\nimport { nearestColorName } from \"./color-names.js\"\n\n/** The kinds of saved resource a direction value can name. */\nexport type UserDirectionRefKind = \"palette\" | \"moodboard\"\n\nexport const USER_DIRECTION_REF_KINDS: ReadonlyArray<UserDirectionRefKind> = [\"palette\", \"moodboard\"]\n\n/** A parsed user-owned reference. `wellFormed` = its id is a uuid. */\nexport interface UserDirectionRef {\n readonly kind: UserDirectionRefKind\n readonly id: string\n readonly wellFormed: boolean\n}\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i\n\n/**\n * Read one direction value. `null` when it is not a user-owned reference at\n * all (a catalog id, an empty string, anything that is not a string). A value\n * with a known prefix is ALWAYS a reference — `wellFormed: false` when what\n * follows is not a uuid, so a caller can refuse it rather than treat it as an\n * unknown catalog id and skip it in silence.\n */\nexport function parseUserDirectionRef(value: unknown): UserDirectionRef | null {\n if (typeof value !== \"string\") return null\n for (const kind of USER_DIRECTION_REF_KINDS) {\n const prefix = `${kind}:`\n if (value.startsWith(prefix)) {\n const id = value.slice(prefix.length)\n return { kind, id, wellFormed: UUID_RE.test(id) }\n }\n }\n return null\n}\n\n/** The wire value for a saved resource: `palette:<id>` / `moodboard:<id>`. */\nexport function userDirectionRefValue(kind: UserDirectionRefKind, id: string): string {\n return `${kind}:${id}`\n}\n\n/** Collapse all whitespace (newlines included) to single spaces and trim. User\n * text never opens a line of its own inside the assembled prompt — a newline\n * there could start a fake `[style]:` section. */\nfunction oneLine(text: string | null | undefined): string {\n return (text ?? \"\").replace(/\\s+/g, \" \").trim()\n}\n\nconst HEX_RE = /^#[0-9a-f]{6}$/i\n\n/**\n * A saved palette as a look clause: every colour by its everyday name and its\n * exact hex, in the palette's order — `color palette: dark teal #0F4C5C,\n * saffron #E3B23C`. An entry that is not a `#RRGGBB` colour is skipped; no\n * valid colour renders nothing.\n */\nexport function renderPaletteClause(colors: ReadonlyArray<string>): string {\n const named = colors\n .filter((c) => HEX_RE.test(c))\n .map((c) => `${nearestColorName(c)} ${c.toUpperCase()}`)\n return named.length > 0 ? `color palette: ${named.join(\", \")}` : \"\"\n}\n\n/**\n * A saved moodboard's written description as its look clause: the user's own\n * words, on one line. No description renders nothing (the moodboard's images\n * still go along as style references).\n */\nexport function renderMoodboardClause(description: string | null | undefined): string {\n return oneLine(description)\n}\n\n/** One style reference image (a moodboard's image) handed to the assembler. */\nexport interface StyleReferenceInput {\n readonly url: string\n /** What the image is for — rides its reference line. */\n readonly caption?: string\n}\n\n/**\n * The line a style reference carries in the assembled prompt (its\n * `description` as a reference). The first one says what to take from a style\n * reference and what not to; the rest stay short, so a full moodboard does not\n * bury the prompt. A caption rides along on one line.\n */\nexport function styleReferenceDescription(index: number, caption?: string): string {\n const cap = oneLine(caption)\n const tail = cap ? ` (${cap})` : \"\"\n return index === 0\n ? `match the colors, light, texture and mood of this style reference${tail}, not its subject or layout`\n : `another style reference${tail}`\n}\n","/**\n * THE DIRECTION REGISTRY — the single, ordered table of every cinematic\n * dimension the flat `direction` channel carries, plus the one renderer that\n * folds it into prompt text.\n *\n * WHY IT EXISTS: before this module, five of the ~35 cinematic dimensions rode\n * the `direction` wire channel and every other dimension was folded into prompt\n * TEXT by the client. A production copied between clients therefore froze stale\n * catalog wording, and each client re-implemented the fold. The table below is\n * the platform-owned replacement: the wire carries ids, the platform renders\n * the clauses, and the fold ORDER is exported so a client preview cannot drift\n * from what the server actually emits.\n *\n * WIRE VOCABULARY: the keys are the platform's OWN node-data field names — the\n * ones `SINGLE_PICKER_WIRING[].valueField` and the four `*_FIELD_BY_CATEGORY`\n * maps already use (`shotSize`, `lightingStyle`, `isoValue`, `style`, `mood`,\n * `cameraMotion`, …). A Studio-emitted graph and a hand-built canvas node\n * therefore speak ONE vocabulary for one catalog, and every `build*Hints`\n * already consumes these names.\n *\n * IMPORT RULE (hard): this module imports only `get*PromptHint` / `get*Term` /\n * `build*Hints` FUNCTIONS — never a raw UPPERCASE catalog array.\n * `catalog-funnel-ratchet.test.ts` derives its watch set from\n * `picker-catalogs.ts`'s uppercase value imports and can only SHRINK, so a raw\n * array import here would be a new offender. Nothing here reads an environment\n * variable either (`content-free-contract.test.ts`) — verbosity and surface are\n * threaded parameters, never deployment state.\n *\n * DELIBERATELY EXCLUDED, so neither is filed as a gap:\n * - `characterFx` — a per-shot composer with catalog timing levers\n * (`composeCharacterFxHintFromConnections`) positioned at an in-prose effect\n * token, not a bare id. A single-id channel cannot carry it.\n * - Subject / Styling / prop dimensions (`animal`, `heldProp`, `material`,\n * Person, Styling) — a separate `subject` channel, deliberately out of scope\n * here. It now exists: `subject-registry.ts`, same table-driven shape, its\n * key set DISJOINT from this one (pinned by a test) so nothing folds twice.\n *\n * PACK BLINDNESS (parity, not a regression): `get*PromptHint` reads the frozen\n * base arrays, so ids added by a deployment-registered catalog pack resolve to\n * `\"\"` and contribute no clause. This is identical to the behavior of the five\n * keys that shipped before this table; routing through `getPickerCatalog` is a\n * deliberate non-goal.\n */\nimport type { PickerHintMode } from \"./term.js\"\nimport { getFramingPromptHint, getFramingTerm } from \"./framing.js\"\nimport { getLightingPromptHint, getLightingTerm } from \"./lighting.js\"\nimport { getLensPromptHint, getLensTerm } from \"./lens.js\"\nimport { getCameraFormatPromptHint, getCameraFormatTerm } from \"./camera-format.js\"\nimport { getCameraMotionPromptHint, getCameraMotionTerm } from \"./camera-motions.js\"\nimport { getPosePromptHint, getPoseTerm } from \"./pose.js\"\nimport {\n getCompositionEffectPromptHint,\n getCompositionEffectTerm,\n} from \"./composition-effects.js\"\nimport { getExposurePromptHint, getExposureTerm } from \"./exposure-settings.js\"\nimport { getColorLookPromptHint, getColorLookTerm } from \"./color-look.js\"\nimport { buildAtmosphereHints } from \"./atmosphere.js\"\nimport { buildPostProcessHints } from \"./post-process-effects.js\"\nimport { getStylePromptHint, getStyleTerm } from \"./style.js\"\nimport { buildMoodHints } from \"./mood.js\"\nimport { buildAestheticHints } from \"./aesthetic.js\"\nimport { getPhotoGenrePromptHint, getPhotoGenreTerm } from \"./photo-genre.js\"\nimport { buildPhotographerHints } from \"./photographer.js\"\nimport { getRenderQualityPromptHint, getRenderQualityTerm } from \"./render-quality.js\"\nimport { getSettingPromptHint, getSettingTerm } from \"./setting.js\"\nimport { getEraPromptHint, getEraTerm } from \"./era.js\"\nimport { getBackdropPromptHint, getBackdropTerm } from \"./backdrop.js\"\nimport { buildActionFxHints } from \"./action-fx.js\"\nimport { getTemporalPromptHint, getTemporalTerm } from \"./temporal.js\"\nimport { renderTransitionBases } from \"./transitions.js\"\nimport { getLoopSubjectPromptHint, getLoopSubjectTerm } from \"./loop-subject.js\"\nimport { parseUserDirectionRef, type UserDirectionRefKind } from \"./user-direction-refs.js\"\n\n/** Which generation stages fold a dimension. */\nexport type DirectionSurface = \"image\" | \"video\" | \"both\"\n/**\n * Verbosity family — the video policy folds `motion` compact, `look` full.\n *\n * It is ALSO the body/section split (`prompt-style-section.ts`): `motion` stays\n * in the prompt body as shot prose, `look` moves to the `[style]` section. The\n * two meanings are deliberately the same column: camera motion is part of the\n * shot, not part of the look, on both axes, and a second column would let the\n * verbosity policy and the section boundary drift apart one row at a time.\n */\nexport type DirectionFamily = \"look\" | \"motion\"\n/**\n * Which `[style]` line a LOOK row renders on. `\"film\"` = the four dimensions\n * that describe the CAPTURE (stock, grade, style, era) plus the legacy camera\n * format key; every other look row falls to the scene line. Absent on `motion`\n * rows, which never reach the section at all.\n */\nexport type DirectionStyleGroup = \"film\"\n\nexport interface DirectionFieldSpec {\n /**\n * Wire key — also the `DirectionFields` property name and the canvas\n * node-data field name for the same catalog.\n */\n readonly key: string\n /**\n * Which generation stages fold this dimension. Filtering happens in the\n * RENDERER, never in the wire schema: an image-only key sent to\n * `/v1/generate-video` is accepted and simply contributes no hint.\n */\n readonly surface: DirectionSurface\n /** Verbosity family. The video policy folds `motion` compact, `look` full. */\n readonly family: DirectionFamily\n /**\n * `[style]`-section line for a `look` row. Omitted = the scene line. Meaningless\n * on a `motion` row (those stay in the body), which is why it is optional\n * rather than a required column with a null member.\n */\n readonly styleGroup?: DirectionStyleGroup\n /** Ids honored per dimension. Extras are SLICED at render, never a 400. */\n readonly maxPicks: number\n /**\n * The kind of the caller's OWN saved resource this row also takes, as\n * `<kind>:<uuid>` (`user-direction-refs.ts`) — a palette on `colorLook`, a\n * moodboard on `style`. Only single-pick rows carry one, so a pick budget can\n * never slice a reference away. The platform resolves the reference before\n * the fold and hands the rendered clause in as `refs`.\n */\n readonly userRef?: UserDirectionRefKind\n /**\n * Render selected ids in this catalog's own doctrine: per-id for independent\n * catalogs, ONE blended clause for Mood / Aesthetic / Photographer, the\n * catalog's own multi builder where it has one. `[]` when nothing resolves.\n */\n readonly render: (ids: readonly string[], mode: PickerHintMode) => string[]\n}\n\n// ── Render adapters (module-private) ────────────────────────────────────────\n\n/**\n * Independent per-id emission — the default doctrine.\n *\n * Only ever passes NON-EMPTY strings (the normalizer drops empties), which is\n * what makes `getLoopSubjectPromptHint(id: string)`'s required-string signature\n * safe here alongside the `string | undefined | null` getters.\n */\nconst perId =\n (full: (id: string) => string, compact: (id: string) => string) =>\n (ids: readonly string[], mode: PickerHintMode): string[] => {\n const out: string[] = []\n for (const id of ids) {\n const frag = mode === \"compact\" ? compact(id) : full(id)\n if (frag.length > 0) out.push(frag)\n }\n return out\n }\n\n/** Catalogs whose own builder returns a LIST (atmosphere, post-process, action FX). */\nconst viaListBuilder =\n (build: (v: unknown, mode: PickerHintMode) => string[]) =>\n (ids: readonly string[], mode: PickerHintMode): string[] =>\n build(ids.length === 1 ? ids[0] : [...ids], mode).filter((s) => s.length > 0)\n\n/** Catalogs whose own builder returns ONE blended clause (aesthetic, photographer). */\nconst viaStringBuilder =\n (build: (v: unknown, mode: PickerHintMode) => string) =>\n (ids: readonly string[], mode: PickerHintMode): string[] => {\n const s = build(ids.length === 1 ? ids[0] : [...ids], mode)\n return s.length > 0 ? [s] : []\n }\n\n/** Mood's builder takes a RECORD and returns a list — and blends multi picks. */\nconst viaMood = (ids: readonly string[], mode: PickerHintMode): string[] =>\n buildMoodHints({ mood: ids.length === 1 ? ids[0] : [...ids] }, mode).filter(\n (s) => s.length > 0,\n )\n\nconst framing = perId(getFramingPromptHint, getFramingTerm)\nconst lighting = perId(getLightingPromptHint, getLightingTerm)\nconst exposure = perId(getExposurePromptHint, getExposureTerm)\nconst temporal = perId(getTemporalPromptHint, getTemporalTerm)\n\n/**\n * THE TABLE. Declaration order IS fold order (`DIRECTION_KEYS`), pinned by\n * `__tests__/direction-registry.test.ts`.\n *\n * Group order: camera motion leads (matching the video hint order the canvas\n * and Studio both emit today), then composition → camera → exposure → light →\n * style → scene → motion, then the LEGACY BLOCK last.\n *\n * THE LEGACY BLOCK (the last five rows) is the pre-registry published\n * `DirectionFields`, placed LAST in today's exact `composePromptText` order so\n * every existing caller's fold is byte-identical. They are WHOLE-CATALOG keys —\n * `framingId` accepts ANY `FRAMINGS` id and `lightingId` ANY `LIGHTINGS` id —\n * so they are NOT aliases of `shotSize` / `lightingStyle`, and an alias table\n * would wrongly suppress a legal second selection. Overlap is handled instead\n * by the exact-string dedupe in `renderDirectionHints`.\n *\n * SECOND MEANING OF POSITION — SURVIVAL, NOT STRING POSITION: BOTH cap-aware\n * assemblers — `assembleImageInput` (stills) and `composeVideoPromptText`\n * (video) — shed hint clauses from the TAIL of this order when a provider's\n * prompt cap overflows, through the one shared arithmetic in\n * `hint-shedding.ts`. So a row's position is its survival order under the cap on\n * EVERY surface: reordering rows for one surface silently changes what the other\n * drops first, and the row a video-surface reorder would most likely touch\n * (`cameraMotion`) leads the fold. What position is NOT any more is the clause's\n * place in the assembled STRING: every `look` row is lifted out of the body into\n * the trailing `[style]` section (`prompt-style-section.ts`), so a look clause\n * reads after every motion clause however early it folds. That is a consequence\n * of reusing the fold order, not a ranking — this table stays a compatibility\n * order; anything that needs a real importance ranking should add an explicit\n * priority column rather than reorder these rows.\n *\n * WHERE THIS TABLE SITS IN THE COMBINED ORDER: both assemblers fold the SUBJECT\n * channel (`subject-registry.ts`) BEFORE this one and shed the combined list\n * tail-first, so every direction row here is dropped before any subject clause.\n * Deliberate — see `hint-shedding.ts` for the argument.\n */\nexport const DIRECTION_FIELDS = [\n { key: \"cameraMotion\", surface: \"video\", family: \"motion\", maxPicks: 1, render: perId(getCameraMotionPromptHint, getCameraMotionTerm) },\n\n // Composition (the Framing catalog, one row per category).\n { key: \"shotSize\", surface: \"both\", family: \"look\", maxPicks: 1, render: framing },\n { key: \"angle\", surface: \"both\", family: \"look\", maxPicks: 1, render: framing },\n { key: \"coverage\", surface: \"both\", family: \"look\", maxPicks: 1, render: framing },\n { key: \"composition\", surface: \"both\", family: \"look\", maxPicks: 2, render: framing },\n { key: \"vantage\", surface: \"both\", family: \"look\", maxPicks: 1, render: framing },\n { key: \"pose\", surface: \"both\", family: \"look\", maxPicks: 1, render: perId(getPosePromptHint, getPoseTerm) },\n { key: \"compositionEffect\", surface: \"both\", family: \"look\", maxPicks: 1, render: perId(getCompositionEffectPromptHint, getCompositionEffectTerm) },\n\n // Camera.\n { key: \"cameraFormat\", surface: \"both\", family: \"look\", styleGroup: \"film\", maxPicks: 1, render: perId(getCameraFormatPromptHint, getCameraFormatTerm) },\n { key: \"lens\", surface: \"both\", family: \"look\", maxPicks: 1, render: perId(getLensPromptHint, getLensTerm) },\n\n // Exposure (stills only — a video's exposure rides its own temporal levers).\n { key: \"aperture\", surface: \"image\", family: \"look\", maxPicks: 1, render: exposure },\n { key: \"shutterSpeed\", surface: \"image\", family: \"look\", maxPicks: 1, render: exposure },\n { key: \"isoValue\", surface: \"image\", family: \"look\", maxPicks: 1, render: exposure },\n\n // Light (the Lighting catalog, one row per category).\n { key: \"timeOfDay\", surface: \"both\", family: \"look\", maxPicks: 1, render: lighting },\n { key: \"lightingStyle\", surface: \"both\", family: \"look\", maxPicks: 2, render: lighting },\n { key: \"lightingDirection\", surface: \"both\", family: \"look\", maxPicks: 1, render: lighting },\n { key: \"lightingRatio\", surface: \"both\", family: \"look\", maxPicks: 1, render: lighting },\n { key: \"colorTemperature\", surface: \"both\", family: \"look\", maxPicks: 1, render: lighting },\n { key: \"colorLook\", surface: \"both\", family: \"look\", styleGroup: \"film\", maxPicks: 1, userRef: \"palette\", render: perId(getColorLookPromptHint, getColorLookTerm) },\n { key: \"atmosphere\", surface: \"both\", family: \"look\", maxPicks: 2, render: viaListBuilder(buildAtmosphereHints) },\n { key: \"postProcess\", surface: \"image\", family: \"look\", maxPicks: 2, render: viaListBuilder(buildPostProcessHints) },\n\n // Style.\n { key: \"style\", surface: \"both\", family: \"look\", styleGroup: \"film\", maxPicks: 1, userRef: \"moodboard\", render: perId(getStylePromptHint, getStyleTerm) },\n { key: \"mood\", surface: \"both\", family: \"look\", maxPicks: 2, render: viaMood },\n { key: \"aesthetic\", surface: \"both\", family: \"look\", maxPicks: 2, render: viaStringBuilder(buildAestheticHints) },\n { key: \"photoGenre\", surface: \"image\", family: \"look\", maxPicks: 1, render: perId(getPhotoGenrePromptHint, getPhotoGenreTerm) },\n { key: \"photographer\", surface: \"image\", family: \"look\", maxPicks: 2, render: viaStringBuilder(buildPhotographerHints) },\n { key: \"renderQuality\", surface: \"image\", family: \"look\", maxPicks: 1, render: perId(getRenderQualityPromptHint, getRenderQualityTerm) },\n\n // Scene.\n { key: \"setting\", surface: \"both\", family: \"look\", maxPicks: 1, render: perId(getSettingPromptHint, getSettingTerm) },\n { key: \"era\", surface: \"both\", family: \"look\", styleGroup: \"film\", maxPicks: 1, render: perId(getEraPromptHint, getEraTerm) },\n { key: \"backdrop\", surface: \"both\", family: \"look\", maxPicks: 1, render: perId(getBackdropPromptHint, getBackdropTerm) },\n\n // Motion & time.\n { key: \"actionFx\", surface: \"video\", family: \"motion\", maxPicks: 2, render: viaListBuilder(buildActionFxHints) },\n { key: \"temporalSpeed\", surface: \"video\", family: \"motion\", maxPicks: 1, render: temporal },\n { key: \"temporalFreeze\", surface: \"video\", family: \"motion\", maxPicks: 1, render: temporal },\n { key: \"temporalDirection\", surface: \"video\", family: \"motion\", maxPicks: 1, render: temporal },\n { key: \"temporalShutter\", surface: \"video\", family: \"motion\", maxPicks: 1, render: temporal },\n { key: \"transition\", surface: \"video\", family: \"motion\", maxPicks: 2, render: renderTransitionBases },\n { key: \"loopSubject\", surface: \"video\", family: \"motion\", maxPicks: 1, render: perId(getLoopSubjectPromptHint, getLoopSubjectTerm) },\n\n // ── LEGACY BLOCK — see the table doc above. Placed LAST, in today's exact\n // `composePromptText` order, so every pre-registry caller is byte-identical.\n { key: \"framingId\", surface: \"both\", family: \"look\", maxPicks: 1, render: framing },\n { key: \"framingAngleId\", surface: \"both\", family: \"look\", maxPicks: 1, render: framing },\n { key: \"lightingId\", surface: \"both\", family: \"look\", maxPicks: 1, render: lighting },\n { key: \"lensId\", surface: \"both\", family: \"look\", maxPicks: 1, render: perId(getLensPromptHint, getLensTerm) },\n { key: \"cameraFormatId\", surface: \"both\", family: \"look\", styleGroup: \"film\", maxPicks: 1, render: perId(getCameraFormatPromptHint, getCameraFormatTerm) },\n] as const satisfies ReadonlyArray<DirectionFieldSpec>\n\n/**\n * The table read at its DECLARED type. `styleGroup` is optional, so on the\n * `as const` tuple only the rows that carry it have the property at all — a\n * member-wise read would not compile. Every walk over the table goes through\n * this binding.\n */\nconst DIRECTION_SPECS: ReadonlyArray<DirectionFieldSpec> = DIRECTION_FIELDS\n\nexport type DirectionFieldRow = (typeof DIRECTION_FIELDS)[number]\nexport type DirectionKey = DirectionFieldRow[\"key\"]\nexport type ImageDirectionKey = Extract<DirectionFieldRow, { surface: \"image\" | \"both\" }>[\"key\"]\nexport type VideoDirectionKey = Extract<DirectionFieldRow, { surface: \"video\" | \"both\" }>[\"key\"]\n\n/**\n * Flat cinematic-direction ids (Studio / MCP / canvas node data).\n *\n * Every key accepts a single id OR an array: multi-pick dimensions always carry\n * an array, and a single-pick key may legitimately carry one (a client's\n * partition writer preserving legacy out-of-catalog ids). Absent ≠ empty — a\n * missing key means \"no hint\", never a default.\n */\nexport type DirectionFields = { readonly [K in DirectionKey]?: string | readonly string[] }\n\n/**\n * Table order — THE canonical fold order. Exported so a client's \"will inject\n * into prompt\" preview folds in the exact order the server does instead of\n * re-deriving one.\n */\nexport const DIRECTION_KEYS: ReadonlyArray<DirectionKey> = DIRECTION_FIELDS.map((f) => f.key)\n\n/**\n * The rows that render on the `[style]` section's FILM line, in table order —\n * derived from the table's `styleGroup` column so the grouping has exactly one\n * definition. Exported for clients that render the section themselves; the\n * platform's own renderer reads the column, not this list.\n */\nexport const FILM_STYLE_KEYS: ReadonlyArray<DirectionKey> = DIRECTION_SPECS.filter(\n (f) => f.styleGroup === \"film\",\n).map((f) => f.key as DirectionKey)\n\n/**\n * The direction key that takes a reference of this kind — `colorLook` for a\n * palette, `style` for a moodboard. Derived from the table's `userRef` column.\n */\nexport function directionKeyForUserRef(kind: UserDirectionRefKind): DirectionKey {\n const row = DIRECTION_SPECS.find((f) => f.userRef === kind)\n if (!row) throw new Error(`no direction row takes a ${kind} reference`)\n return row.key as DirectionKey\n}\n\n/** The kind of saved resource a direction key takes, or undefined (most keys). */\nexport function userRefKindOfDirectionKey(key: string): UserDirectionRefKind | undefined {\n return DIRECTION_SPECS.find((f) => f.key === key)?.userRef\n}\n\n/** Verbosity for a whole fold, or split per family. */\nexport type DirectionHintMode =\n | PickerHintMode\n | { readonly look: PickerHintMode; readonly motion: PickerHintMode }\n\n/** How a direction bag is folded. */\nexport interface DirectionRenderOptions {\n readonly surface: \"image\" | \"video\"\n readonly mode?: DirectionHintMode\n /**\n * Rendered clauses for the caller's OWN saved resources, keyed by the\n * direction value (`palette:<id>` → `color palette: …`), resolved by the\n * platform before the fold. A reference absent from the map renders nothing,\n * exactly like an unknown catalog id. Absent = no reference resolves.\n */\n readonly refs?: ReadonlyMap<string, string>\n}\n\n/** Image policy: full clause for every dimension (today's behavior). */\nexport const IMAGE_HINT_MODE_DEFAULT: DirectionHintMode = \"full\"\n\n/** Video policy: full look clauses, compact motion terms. */\nexport const VIDEO_HINT_MODE_DEFAULT: DirectionHintMode = { look: \"full\", motion: \"compact\" }\n\nexport function modeForFamily(mode: DirectionHintMode, family: DirectionFamily): PickerHintMode {\n return typeof mode === \"string\" ? mode : family === \"motion\" ? mode.motion : mode.look\n}\n\n/**\n * Wire tolerance ceiling for an array-valued direction key. The SEMANTIC cap is\n * the per-row render-time slice (`maxPicks`) — this is only the point past\n * which a body is malformed rather than merely over-generous.\n */\nexport const DIRECTION_ARRAY_CEILING = 8\n\n/**\n * Tolerance ceiling for the LENGTH of a single direction id. Catalog ids are\n * short slugs (<= ~40 chars); 100 is generous and closes an otherwise unbounded\n * string channel that lands verbatim in `jobs.input_data`.\n *\n * ONE literal for BOTH doors into the fold — the route's `directionSchema`\n * (`backend/src/lib/direction-schema.ts`) and the persisted-node reader\n * (`read-node-direction.ts`) — so the wire and the canvas cannot start\n * disagreeing about which strings are ids at all.\n */\nexport const DIRECTION_ID_MAX_CHARS = 100\n\n/**\n * `string | string[]` → deduped, non-empty, capped id list.\n *\n * The `ids.length >= maxPicks` bail is load-bearing, not an optimization: the\n * dedupe is an `includes` scan, so without it the cost is quadratic in the\n * CALLER's array length — and one caller (`readDirectionFields`) reads\n * untrusted persisted JSONB. Bailing is semantics-preserving: once `maxPicks`\n * unique ids exist, no later entry can change the sliced result (and\n * `maxPicks = 0` still yields `[]`).\n */\nfunction normalizeDirectionIds(value: unknown, maxPicks: number): string[] {\n const ids: string[] = []\n if (typeof value === \"string\") {\n if (value) ids.push(value)\n } else if (Array.isArray(value)) {\n for (const v of value) {\n if (ids.length >= maxPicks) break\n if (typeof v === \"string\" && v && !ids.includes(v)) ids.push(v)\n }\n }\n return ids.slice(0, maxPicks)\n}\n\n/**\n * One row's clauses. A row with no user-owned reference among its ids renders\n * through its catalog doctrine exactly as before (byte parity). On a row that\n * takes a reference (`userRef`), each id renders on its own, in order: a\n * reference of the row's kind becomes its resolved clause from `refs` (nothing\n * when unresolved), any other value goes through the catalog.\n */\nfunction renderRow(\n spec: DirectionFieldSpec,\n ids: readonly string[],\n mode: PickerHintMode,\n refs: ReadonlyMap<string, string> | undefined,\n): string[] {\n if (spec.userRef === undefined || !ids.some((id) => parseUserDirectionRef(id) !== null)) {\n return spec.render(ids, mode)\n }\n return ids.flatMap((id) => {\n const ref = parseUserDirectionRef(id)\n if (ref === null) return spec.render([id], mode)\n const clause = ref.kind === spec.userRef ? refs?.get(id) : undefined\n return clause ? [clause] : []\n })\n}\n\n/** The rows a given generation stage folds, in table order. */\nexport function directionFieldsForSurface(\n surface: \"image\" | \"video\",\n): ReadonlyArray<DirectionFieldSpec> {\n return DIRECTION_SPECS.filter((f) => f.surface === \"both\" || f.surface === surface)\n}\n\n/** One rendered clause, still carrying the table attributes it came from. */\nexport interface DirectionHintClause {\n readonly key: DirectionKey\n readonly family: DirectionFamily\n readonly styleGroup?: DirectionStyleGroup\n readonly text: string\n}\n\n/**\n * `renderDirectionHints` with the row each clause came from still attached —\n * what the `[style]` section needs to decide which line a clause belongs on\n * without a second table. Same order, same surface filter, same dedupe; the\n * plain renderer is this one's `.text` projection, so the two cannot drift.\n */\nexport function renderDirectionHintClauses(\n direction: DirectionFields | undefined,\n opts: DirectionRenderOptions,\n): DirectionHintClause[] {\n if (!direction) return []\n const mode = opts.mode ?? \"full\"\n const out: DirectionHintClause[] = []\n const seen = new Set<string>()\n for (const spec of DIRECTION_SPECS) {\n if (spec.surface !== \"both\" && spec.surface !== opts.surface) continue\n const ids = normalizeDirectionIds(\n (direction as Record<string, unknown>)[spec.key],\n spec.maxPicks,\n )\n if (ids.length === 0) continue\n for (const hint of renderRow(spec, ids, modeForFamily(mode, spec.family), opts.refs)) {\n if (hint.length > 0 && !seen.has(hint)) {\n seen.add(hint)\n out.push({\n key: spec.key as DirectionKey,\n family: spec.family,\n ...(spec.styleGroup !== undefined ? { styleGroup: spec.styleGroup } : {}),\n text: hint,\n })\n }\n }\n }\n return out\n}\n\n/**\n * Every clause the `direction` channel injects, in canonical table order.\n *\n * Iterates the TABLE (never the caller's object), so unknown wire keys are\n * ignored, the order is platform-owned, and off-surface dimensions are inert.\n * Unknown IDS are silently skipped too — every `get*PromptHint` returns `\"\"` on\n * a miss, so a retired or pack-only id contributes no clause rather than a 400.\n *\n * DEDUPE: the result is de-duplicated by exact clause string, FIRST OCCURRENCE\n * WINS (order-preserving). This is what lets the five legacy whole-catalog keys\n * (`framingId`, `lightingId`, …) coexist with their canonical counterparts\n * without an alias table: a caller sending `framingId` and `shotSize` with the\n * SAME id emits the clause once, while `lightingId: \"golden-hour\"` alongside\n * `lightingStyle: \"rembrandt\"` correctly emits BOTH (they are different ids in\n * the same catalog — an alias table would have wrongly suppressed one).\n * A caller sending two DIFFERENT ids for the same dimension gets both clauses,\n * exactly as two wired picker nodes of one family behave today.\n *\n * Exported so a client's \"will inject into prompt\" preview renders the exact\n * clauses the server does instead of re-implementing the fold. A preview of the\n * assembled STRING needs `prompt-style-section.ts` on top: the look clauses in\n * this list do not read in this position any more.\n */\nexport function renderDirectionHints(\n direction: DirectionFields | undefined,\n opts: DirectionRenderOptions,\n): string[] {\n return renderDirectionHintClauses(direction, opts).map((c) => c.text)\n}\n","import { getAnimalPromptHint, getAnimalTerm, getVehicle, getWeapon, getFurniture } from \"@nodaro/shared/catalogs\"\nimport { composedHas, composedOption } from \"./catalog-overlay.js\"\nimport { deriveTerm } from \"./term.js\"\n\n/**\n * The four object-entity catalogs — animals, vehicles, weapons, furniture —\n * are OWNED by `@nodaro/shared`, which cannot depend on this package, so\n * their getters cannot carry the `overlayEntry` the other 34 catalogs do.\n * These wrappers are the overlay for them, and EVERY prompt-text read of\n * those catalogs goes through here: the parameter-node dispatcher and the\n * subject fold both. Two call sites resolving the same id to different text\n * — one curated, one stock — is exactly what a second, un-overlaid path\n * produced during review.\n *\n * Precedence per id, same four outcomes as catalog-overlay.ts:\n * - no pack on the catalog → the stock getter, untouched\n * - denied / not in the pack → \"\" (nothing reaches the prompt)\n * - composed option present → ITS promptHint / term. A pack author\n * who rewrote an entry wrote the hint they want injected; rebuilding it\n * from label + description would discard that\n * - pack-added id (no stock row) → the composed option (covered by the\n * branch above — the stock getter is never consulted when a pack exists)\n */\n\nexport function curatedAnimalPromptHint(id: string): string {\n if (!id) return \"\"\n if (!composedHas(\"animals\", id)) return \"\"\n return composedOption(\"animals\", id)?.promptHint ?? getAnimalPromptHint(id)\n}\nexport function curatedAnimalTerm(id: string): string {\n if (!id) return \"\"\n if (!composedHas(\"animals\", id)) return \"\"\n return composedOption(\"animals\", id)?.term ?? getAnimalTerm(id)\n}\n\ntype ObjectEntity = { readonly label: string; readonly description: string }\n\nfunction objectEntityText(\n catalogId: string,\n id: string,\n stock: ObjectEntity | undefined,\n stockHint: (e: ObjectEntity) => string,\n stockTerm: (e: ObjectEntity) => string,\n): { readonly hint: string; readonly term: string } {\n if (!id || !composedHas(catalogId, id)) return { hint: \"\", term: \"\" }\n const composed = composedOption(catalogId, id)\n if (composed) return { hint: composed.promptHint, term: composed.term }\n if (!stock) return { hint: \"\", term: \"\" }\n return { hint: stockHint(stock), term: stockTerm(stock) }\n}\n\n/**\n * The compact fragment for an OBJECT-entity entry (animal / vehicle / weapon /\n * furniture). Those catalogs carry no `promptHint` of their own — the full\n * fragment is synthesized as \"featuring a {label}, {description}\" — so the\n * compact form is the authored `term` when there is one and the derived label\n * otherwise (a concrete object's label IS its trade term). The framing verb\n * (\"featuring a\", \"with a\") belongs to the HINT; a term drops bare into\n * whatever sentence the consumer is building, and \"the object is in the scene\"\n * is precisely what these four nodes mean.\n *\n * The fallback MUST be `deriveTerm` and not a bare `toLowerCase()`: it is the\n * same fallback `objectOptions` uses to build the `/v1/catalogs` projection,\n * so a parenthetical label (\"Rifle (bolt-action)\") must strip identically here\n * or the injected fragment and the projected term would disagree.\n *\n * `term` is read structurally because it is being added to the shared entity\n * interfaces separately; this stays correct before and after that lands.\n */\n\nfunction objectEntityTerm(entry: { readonly label: string }): string {\n return (entry as { term?: string }).term ?? deriveTerm(entry.label)\n}\n\nexport function curatedVehicleText(id: string) {\n return objectEntityText(\"vehicles\", id, getVehicle(id), (e) => `featuring a ${e.label.toLowerCase()}, ${e.description}`, objectEntityTerm)\n}\nexport function curatedWeaponText(id: string) {\n return objectEntityText(\"weapons\", id, getWeapon(id), (e) => `with a ${e.label.toLowerCase()}, ${e.description}`, objectEntityTerm)\n}\nexport function curatedFurnitureText(id: string) {\n return objectEntityText(\"furniture\", id, getFurniture(id), (e) => `including a ${e.label.toLowerCase()}, ${e.description}`, objectEntityTerm)\n}\n"]}
@@ -0,0 +1,6 @@
1
+ // src/image-token-pattern.ts
2
+ var IMAGE_TOKEN_PATTERN = /\{image:(\d+)(?::([^}\n]+))?\}/gi;
3
+
4
+ export { IMAGE_TOKEN_PATTERN };
5
+ //# sourceMappingURL=chunk-GILUVQQJ.js.map
6
+ //# sourceMappingURL=chunk-GILUVQQJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/image-token-pattern.ts"],"names":[],"mappings":";AAYO,IAAM,mBAAA,GAAsB","file":"chunk-GILUVQQJ.js","sourcesContent":["/**\n * The `{image:N}` / `{image:N:label}` reference-token grammar — one pattern for\n * the image prompt assembly (`prompt-builder.ts`) and for the preset metadata\n * that reads which references a template names (`factory-presets/references.ts`).\n *\n * Group 1 = position (1-based), group 2 = optional label. The label allows\n * spaces (multi-word labels like \"clothes and shoes\") but never a newline or\n * `}`, so a match can't run away across lines or token boundaries.\n *\n * Global on purpose (callers use `.replace` / `.matchAll`, which never leave a\n * `lastIndex` behind); never call `.test` / `.exec` on it.\n */\nexport const IMAGE_TOKEN_PATTERN = /\\{image:(\\d+)(?::([^}\\n]+))?\\}/gi\n"]}
@@ -1,4 +1,5 @@
1
- import { getAdultOnlyIds } from './chunk-N7TOWXDJ.js';
1
+ import { getAdultOnlyIds } from './chunk-QDUTMOF4.js';
2
+ import { parseUserDirectionRef, userRefKindOfDirectionKey } from './chunk-EAYEZXWT.js';
2
3
  import { MUSIC_GENRES, SETTING_CATEGORY_LABELS, COLOR_LOOK_CATEGORY_LABELS, COLOR_LOOK_CATEGORY_ORDER, MOOD_CATEGORY_LABELS, MOOD_CATEGORY_ORDER, PHOTOGRAPHER_CATEGORY_LABELS, PHOTOGRAPHER_CATEGORY_ORDER, AESTHETIC_CATEGORY_LABELS, AESTHETIC_CATEGORY_ORDER, ERA_CATEGORY_LABELS, ERA_CATEGORY_ORDER, PHOTO_GENRE_CATEGORY_LABELS, PHOTO_GENRE_CATEGORY_ORDER, BACKDROP_CATEGORY_LABELS, BACKDROP_CATEGORY_ORDER, ACTION_FX_CATEGORY_LABELS, ACTION_FX_CATEGORY_ORDER, LOOP_SUBJECT_CATEGORY_LABELS, LOOP_SUBJECT_CATEGORY_ORDER, CAMERA_MOTION_CATEGORY_LABELS, CAMERA_MOTION_CATEGORY_ORDER, TRANSITION_CATEGORY_LABELS, TRANSITION_CATEGORY_ORDER, CHARACTER_FX_CATEGORY_LABELS, CHARACTER_FX_CATEGORY_ORDER, CHARACTER_MOTION_CATEGORY_LABELS, CHARACTER_MOTION_CATEGORY_ORDER, POSE_CATEGORY_LABELS, POSE_CATEGORY_ORDER, MATERIAL_CATEGORY_LABELS, MATERIAL_CATEGORY_ORDER, HELD_PROP_CATEGORY_LABELS, HELD_PROP_CATEGORY_ORDER, STYLING_DIMENSION_ORDER, STYLING_FIELD_BY_DIMENSION, LIGHTING_CATEGORY_ORDER, LIGHTING_FIELD_BY_CATEGORY, EXPOSURE_SETTINGS, TEMPORALS, LIGHTINGS, LIGHTING_CATEGORY_LABELS, CAMERA_MOTIONS, HELD_PROPS, MATERIALS, POSES, CHARACTER_MOTIONS, CHARACTER_FX, TRANSITIONS, LOOP_SUBJECTS, ACTION_FX, POST_PROCESS_EFFECTS, COMPOSITION_EFFECTS, RENDER_QUALITIES, BACKDROPS, PHOTO_GENRES, ERAS, AESTHETICS, PHOTOGRAPHERS, COLOR_LOOKS, MOODS, STYLES, ATMOSPHERES, SETTINGS, CAMERA_FORMATS, LENSES, FRAMINGS, FRAMING_CATEGORY_LABELS, FRAMING_FIELD_BY_CATEGORY, FRAMING_CATEGORY_ORDER, STYLINGS, STYLING_DIMENSION_LABELS, MUSIC_ERAS, MUSIC_VIBES, MUSIC_EMOTIONS, MUSIC_ENERGIES, SINGING_STYLES, VOCAL_PRESENCE, PRODUCTION_STYLES, INSTRUMENTS, VOICE_TIMBRES, VOICE_ACCENTS, VOICE_LANGUAGES, VOICE_GENDERS, VOICE_AGES, VOICE_ARCHETYPES, VOICE_EMOTIONS, VOICE_PACES, getFramingCategoryLimit, getStylingDimensionLimit, PICKER_CATALOGS, getPickerCatalog } from './chunk-SXXW4LCR.js';
3
4
  import { PERSON_DIMENSION_ORDER, PERSON_FIELD_BY_DIMENSION, PEOPLE, PERSON_DIMENSION_LABELS, getPersonDimensionLimit, isMinorAge } from './chunk-TDZFXOTE.js';
4
5
  import { getRegisteredCatalogPacks, catalogPacksVersion } from './chunk-XAMHEW76.js';
@@ -62,12 +63,17 @@ function values(v) {
62
63
  function catalogGuardActive() {
63
64
  return getRegisteredCatalogPacks().length > 0;
64
65
  }
65
- function checkRecord(nodeType, nodeId, data, fields, out) {
66
+ function isOwnUserRef(field, id) {
67
+ const ref = parseUserDirectionRef(id);
68
+ return ref !== null && userRefKindOfDirectionKey(field) === ref.kind;
69
+ }
70
+ function checkRecord(nodeType, nodeId, data, fields, out, skip) {
66
71
  for (const [field, catalogId] of fields) {
67
72
  const raw = data[field];
68
73
  if (raw === void 0 || raw === null) continue;
69
74
  const offered = composedIds(catalogId);
70
75
  for (const id of values(raw)) {
76
+ if (skip?.(field, id)) continue;
71
77
  if (!offered.has(id)) out.push({ nodeId, nodeType, field, id, catalogId });
72
78
  }
73
79
  }
@@ -86,7 +92,7 @@ function findForeignCatalogIds(nodes) {
86
92
  for (const key of ["direction", "subject"]) {
87
93
  const rec = data[key];
88
94
  if (rec && typeof rec === "object" && !Array.isArray(rec)) {
89
- checkRecord(type, nodeId, rec, table.byField, out);
95
+ checkRecord(type, nodeId, rec, table.byField, out, key === "direction" ? isOwnUserRef : void 0);
90
96
  }
91
97
  }
92
98
  }
@@ -99,7 +105,7 @@ function findForeignCatalogIdsInBody(nodeType, body) {
99
105
  for (const key of ["direction", "subject"]) {
100
106
  const rec = body[key];
101
107
  if (rec && typeof rec === "object" && !Array.isArray(rec)) {
102
- checkRecord(nodeType, void 0, rec, table.byField, out);
108
+ checkRecord(nodeType, void 0, rec, table.byField, out, key === "direction" ? isOwnUserRef : void 0);
103
109
  }
104
110
  }
105
111
  return out;
@@ -15198,5 +15204,5 @@ function getPickerWiring(nodeType) {
15198
15204
  }
15199
15205
 
15200
15206
  export { ALL_PICKER_WIRING, ANALYZABLE_PICKER_TYPES, GAPS_SCHEMA, MULTI_PICKER_WIRING, PICKER_ANALYZER_FAMILIES, PICKER_ANALYZER_REGISTRY, PICKER_TYPES, SINGLE_PICKER_WIRING, __resetCatalogIdGuardForTests, applyPickerJson, buildMultiPickerAnalyzerSpec, buildPickerAnalyzerSpec, buildPickerLegend, buildPickerZodSchema, catalogGuardActive, findForeignCatalogIds, findForeignCatalogIdsInBody, foreignCatalogIdMessage, getPickerAnalyzer, getPickerWiring, isAnalyzablePicker, pickerFanoutTargets };
15201
- //# sourceMappingURL=chunk-KIYNOOPJ.js.map
15202
- //# sourceMappingURL=chunk-KIYNOOPJ.js.map
15207
+ //# sourceMappingURL=chunk-GTDKDD7Y.js.map
15208
+ //# sourceMappingURL=chunk-GTDKDD7Y.js.map