@nodaro/prompts 1.0.1

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 (150) hide show
  1. package/LICENSE +105 -0
  2. package/README.md +27 -0
  3. package/dist/index.cjs +21240 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +3599 -0
  6. package/dist/index.d.ts +3599 -0
  7. package/dist/index.js +20854 -0
  8. package/dist/index.js.map +1 -0
  9. package/package.json +49 -0
  10. package/src/__tests__/__snapshots__/prompt-builder-segments.test.ts.snap +65 -0
  11. package/src/__tests__/action-fx.test.ts +155 -0
  12. package/src/__tests__/apply-picker-json.test.ts +50 -0
  13. package/src/__tests__/assemble-image-input.test.ts +248 -0
  14. package/src/__tests__/assemble-suno-input.test.ts +283 -0
  15. package/src/__tests__/brand-tokens.test.ts +81 -0
  16. package/src/__tests__/build-image-prompt-element-injection.test.ts +118 -0
  17. package/src/__tests__/build-image-prompt-hybrid-format.test.ts +131 -0
  18. package/src/__tests__/build-image-prompt-mentions.test.ts +809 -0
  19. package/src/__tests__/build-image-prompt-reference-cap.test.ts +57 -0
  20. package/src/__tests__/build-image-prompt-reference-numbering.test.ts +237 -0
  21. package/src/__tests__/build-image-prompt-reference-order.test.ts +313 -0
  22. package/src/__tests__/camera-motions-from-connections.test.ts +71 -0
  23. package/src/__tests__/catalog-gapfill.test.ts +53 -0
  24. package/src/__tests__/character-convergence-image.test.ts +217 -0
  25. package/src/__tests__/character-default-role-image.test.ts +167 -0
  26. package/src/__tests__/character-default-role-video.test.ts +168 -0
  27. package/src/__tests__/character-default-role.test.ts +70 -0
  28. package/src/__tests__/character-fx.test.ts +200 -0
  29. package/src/__tests__/entity-prompts-location.test.ts +97 -0
  30. package/src/__tests__/entity-prompts.test.ts +240 -0
  31. package/src/__tests__/expand-extra-refs-role.test.ts +50 -0
  32. package/src/__tests__/factory-presets.test.ts +1045 -0
  33. package/src/__tests__/factory-snippets.test.ts +68 -0
  34. package/src/__tests__/framing-multi.test.ts +71 -0
  35. package/src/__tests__/framing-vantage.test.ts +39 -0
  36. package/src/__tests__/i18n-entry-completeness.test.ts +269 -0
  37. package/src/__tests__/identity-lock.test.ts +46 -0
  38. package/src/__tests__/instrumentation.test.ts +68 -0
  39. package/src/__tests__/lighting-multi.test.ts +68 -0
  40. package/src/__tests__/location-convergence-image.test.ts +124 -0
  41. package/src/__tests__/mention-lock-flag.test.ts +499 -0
  42. package/src/__tests__/multi-picker-spec.test.ts +71 -0
  43. package/src/__tests__/music-genre.test.ts +103 -0
  44. package/src/__tests__/music-mood.test.ts +87 -0
  45. package/src/__tests__/object-creature-convergence-image.test.ts +105 -0
  46. package/src/__tests__/parameter-prompt-hint.test.ts +270 -0
  47. package/src/__tests__/parameter-registry-sync.test.ts +243 -0
  48. package/src/__tests__/person-age.test.ts +80 -0
  49. package/src/__tests__/person-analyzer-invariants.test.ts +47 -0
  50. package/src/__tests__/person-body-axes.test.ts +67 -0
  51. package/src/__tests__/person-facial-geometry.test.ts +156 -0
  52. package/src/__tests__/person-regional-aesthetic.test.ts +161 -0
  53. package/src/__tests__/person-sections.test.ts +18 -0
  54. package/src/__tests__/picker-analyzer-registry.test.ts +108 -0
  55. package/src/__tests__/picker-catalogs-project.test.ts +85 -0
  56. package/src/__tests__/picker-catalogs.test.ts +53 -0
  57. package/src/__tests__/picker-limits.test.ts +20 -0
  58. package/src/__tests__/prompt-builder-segments.test.ts +183 -0
  59. package/src/__tests__/prompt-builder-structured-fields.test.ts +40 -0
  60. package/src/__tests__/prompt-builder.test.ts +1773 -0
  61. package/src/__tests__/prompt-wizard-categories.test.ts +31 -0
  62. package/src/__tests__/provider-prompt-doctrine.test.ts +49 -0
  63. package/src/__tests__/resolve-prompt-append.test.ts +58 -0
  64. package/src/__tests__/resolve-prompt.test.ts +44 -0
  65. package/src/__tests__/role-picker-shared.test.ts +208 -0
  66. package/src/__tests__/seedance-2-inputs.test.ts +173 -0
  67. package/src/__tests__/seedance-extend.test.ts +44 -0
  68. package/src/__tests__/sound-aggregator.test.ts +350 -0
  69. package/src/__tests__/style-presets.test.ts +34 -0
  70. package/src/__tests__/temporal-multi.test.ts +74 -0
  71. package/src/__tests__/transitions.test.ts +213 -0
  72. package/src/__tests__/video-reference-features.test.ts +41 -0
  73. package/src/__tests__/video-reference-leading-refs.test.ts +90 -0
  74. package/src/__tests__/video-reference-resolver.test.ts +233 -0
  75. package/src/__tests__/video-reference-roles.test.ts +96 -0
  76. package/src/__tests__/voice-character.test.ts +48 -0
  77. package/src/__tests__/voice-delivery.test.ts +41 -0
  78. package/src/__tests__/wardrobe.test.ts +25 -0
  79. package/src/action-fx.ts +255 -0
  80. package/src/aesthetic.ts +435 -0
  81. package/src/assemble-image-input.ts +236 -0
  82. package/src/assemble-suno-input.ts +147 -0
  83. package/src/atmosphere.ts +104 -0
  84. package/src/backdrop.ts +131 -0
  85. package/src/brand-tokens.ts +154 -0
  86. package/src/camera-format.ts +76 -0
  87. package/src/camera-motions.ts +615 -0
  88. package/src/character-fx.ts +274 -0
  89. package/src/color-look.ts +103 -0
  90. package/src/composition-effects.ts +67 -0
  91. package/src/entity-prompts.ts +231 -0
  92. package/src/era.ts +292 -0
  93. package/src/exposure-settings.ts +142 -0
  94. package/src/factory-presets/generate-image.ts +1644 -0
  95. package/src/factory-presets/generate-video.ts +1116 -0
  96. package/src/factory-presets/index.ts +46 -0
  97. package/src/factory-presets/lottie-overlay.ts +166 -0
  98. package/src/factory-presets/motion-graphics.ts +350 -0
  99. package/src/factory-presets/music.ts +734 -0
  100. package/src/factory-presets/sfx.ts +136 -0
  101. package/src/factory-presets/shared-image.ts +207 -0
  102. package/src/factory-presets/switchx.ts +65 -0
  103. package/src/factory-presets/text.ts +292 -0
  104. package/src/factory-presets/types.ts +51 -0
  105. package/src/factory-presets/video-edit.ts +136 -0
  106. package/src/factory-presets/voice.ts +172 -0
  107. package/src/factory-presets.ts +2 -0
  108. package/src/factory-snippets/catalog.ts +105 -0
  109. package/src/factory-snippets/index.ts +16 -0
  110. package/src/factory-snippets/types.ts +33 -0
  111. package/src/framing.ts +634 -0
  112. package/src/held-prop.ts +187 -0
  113. package/src/identity-lock.ts +213 -0
  114. package/src/index.ts +66 -0
  115. package/src/instrumentation.ts +337 -0
  116. package/src/lens.ts +59 -0
  117. package/src/lighting.ts +229 -0
  118. package/src/loop-subject.ts +276 -0
  119. package/src/materials.ts +184 -0
  120. package/src/mood.ts +186 -0
  121. package/src/music-genre.ts +662 -0
  122. package/src/music-mood.ts +137 -0
  123. package/src/object-asset-presets.ts +81 -0
  124. package/src/parameter-prompt-hint.ts +281 -0
  125. package/src/person.ts +1368 -0
  126. package/src/photo-genre.ts +151 -0
  127. package/src/photographer.ts +612 -0
  128. package/src/picker-analyzer-registry.ts +374 -0
  129. package/src/picker-catalogs.ts +858 -0
  130. package/src/pose.ts +246 -0
  131. package/src/post-process-effects.ts +94 -0
  132. package/src/prompt-builder-structured-fields.ts +116 -0
  133. package/src/prompt-builder.ts +2964 -0
  134. package/src/prompt-templates.ts +50 -0
  135. package/src/prompt-wizard-categories.ts +334 -0
  136. package/src/provider-prompt-doctrine.ts +85 -0
  137. package/src/render-quality.ts +89 -0
  138. package/src/resolve-prompt.ts +120 -0
  139. package/src/seedance-2-inputs.ts +100 -0
  140. package/src/setting.ts +130 -0
  141. package/src/sound-aggregator.ts +241 -0
  142. package/src/style-presets.ts +162 -0
  143. package/src/style.ts +99 -0
  144. package/src/styling.ts +585 -0
  145. package/src/temporal.ts +151 -0
  146. package/src/transitions.ts +333 -0
  147. package/src/video-reference-resolver.ts +823 -0
  148. package/src/voice-character.ts +237 -0
  149. package/src/voice-delivery.ts +142 -0
  150. package/src/wardrobe.ts +179 -0
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Default prompt templates and template resolution/application functions.
3
+ * Shared between frontend and backend.
4
+ */
5
+
6
+ export const DEFAULT_TEMPLATES: Record<string, string> = {
7
+ "character-description": "Include character '{name}': {description}.",
8
+ "object-description": "Include object '{name}': {description}.",
9
+ "location-description": "Include location '{name}': {description}.",
10
+ "face-description":
11
+ "Include the exact face and facial features of '{name}' from the reference image. Maintain perfect likeness and facial identity.",
12
+ // `-generation` templates drive standalone entity generation routes
13
+ // (`/v1/generate-character`, `/v1/generate-face`, etc.). Duplicated between
14
+ // frontend and backend historically; consolidated here so the backend DAG
15
+ // orchestrator produces the same prompt as a single-node HTTP call.
16
+ "character-generation":
17
+ "Create a full-body character portrait: {description}. Style: {style}. Gender: {gender}. High quality, detailed, consistent lighting, neutral background.",
18
+ "object-generation":
19
+ "Create a product photo of: {description}. Category: {category}. Clean background, professional studio lighting, high detail.",
20
+ "location-generation":
21
+ "Create a cinematic scene of: {description}. Category: {category}. Atmospheric lighting, high detail, wide angle.",
22
+ "face-generation":
23
+ "Create a professional close-up face portrait headshot: {description}. Style: {style}. Looking directly at camera, sharp focus on facial features, clean background, studio lighting, high resolution. Maintain exact facial identity and features from the reference image.",
24
+ "generate-image-wrapper": "{userPrompt}\n{assetDescriptions}",
25
+ }
26
+
27
+ /**
28
+ * Resolve a template by key, checking flow-level overrides, then user overrides,
29
+ * then the system defaults.
30
+ */
31
+ export function resolveTemplate(
32
+ key: string,
33
+ userTemplates?: Record<string, string>,
34
+ flowTemplates?: Record<string, string>,
35
+ ): string {
36
+ return flowTemplates?.[key] ?? userTemplates?.[key] ?? DEFAULT_TEMPLATES[key] ?? ""
37
+ }
38
+
39
+ /**
40
+ * Replace `{varName}` placeholders in a template string with values from vars.
41
+ */
42
+ export function applyTemplate(
43
+ template: string,
44
+ vars: Record<string, string>,
45
+ ): string {
46
+ return Object.entries(vars).reduce(
47
+ (result, [key, value]) => result.replaceAll(`{${key}}`, value || ""),
48
+ template,
49
+ )
50
+ }
@@ -0,0 +1,334 @@
1
+ /**
2
+ * Prompt Wizard — shared types, category definitions, and provider capabilities.
3
+ *
4
+ * Used by the backend (system prompt building) and frontend (type-checking, UI).
5
+ */
6
+
7
+ // ── Types ──
8
+
9
+ export interface WizardCategory {
10
+ readonly key: string
11
+ readonly label: string
12
+ readonly optional?: boolean
13
+ }
14
+
15
+ export interface WizardQuestion {
16
+ category: string
17
+ label: string
18
+ options: WizardOption[]
19
+ selected: string | string[] | null
20
+ allowCustom: boolean
21
+ multi?: boolean
22
+ }
23
+
24
+ export interface WizardOption {
25
+ value: string
26
+ label: string
27
+ description?: string
28
+ }
29
+
30
+ export interface WizardSelection {
31
+ category: string
32
+ value: string
33
+ isCustom: boolean
34
+ }
35
+
36
+ export interface RecommendedModel {
37
+ provider: string
38
+ field: string
39
+ label: string
40
+ reason: string
41
+ }
42
+
43
+ export interface WizardNodeContext {
44
+ connectedInputTypes?: string[]
45
+ referenceImageCount?: number
46
+ referenceImageUrls?: string[]
47
+ hasSourceVideo?: boolean
48
+ }
49
+
50
+ export interface ModelChange {
51
+ field: string
52
+ value: string
53
+ }
54
+
55
+ // ── Category Definitions ──
56
+
57
+ // ── Image (generate-image, image-to-image) ──
58
+ export const IMAGE_WIZARD_CATEGORIES: readonly WizardCategory[] = [
59
+ { key: "subject", label: "Subject" },
60
+ { key: "environment", label: "Environment / Setting" },
61
+ { key: "lighting", label: "Lighting" },
62
+ { key: "camera-composition", label: "Camera & Composition" },
63
+ { key: "style-medium", label: "Style / Medium" },
64
+ { key: "mood-tone", label: "Mood & Tone" },
65
+ { key: "details-texture", label: "Details / Texture", optional: true },
66
+ { key: "what-to-avoid", label: "What to Avoid", optional: true },
67
+ ]
68
+
69
+ // ── Video (text-to-video, image-to-video, video-to-video, motion-transfer, extend-video, speech-to-video) ──
70
+ export const VIDEO_WIZARD_CATEGORIES: readonly WizardCategory[] = [
71
+ { key: "subject-action", label: "Subject & Action" },
72
+ { key: "environment", label: "Environment / Setting" },
73
+ { key: "camera-movement", label: "Camera Movement" },
74
+ { key: "pacing-speed", label: "Pacing / Speed" },
75
+ { key: "style-look", label: "Style / Look" },
76
+ { key: "mood-tone", label: "Mood & Tone" },
77
+ ]
78
+
79
+ // ── Music (generate-music, suno-generate) ──
80
+ export const MUSIC_WIZARD_CATEGORIES: readonly WizardCategory[] = [
81
+ { key: "genre-style", label: "Genre / Style" },
82
+ { key: "mood-energy", label: "Mood & Energy" },
83
+ { key: "instruments", label: "Instruments" },
84
+ { key: "tempo", label: "Tempo" },
85
+ { key: "vocals", label: "Vocals" },
86
+ { key: "production-style", label: "Production Style" },
87
+ ]
88
+
89
+ // ── Audio / SFX (text-to-audio) ──
90
+ export const AUDIO_WIZARD_CATEGORIES: readonly WizardCategory[] = [
91
+ { key: "sound-type", label: "Sound Type" },
92
+ { key: "environment", label: "Environment" },
93
+ { key: "intensity", label: "Intensity" },
94
+ { key: "texture-quality", label: "Texture / Quality" },
95
+ ]
96
+
97
+ // ── Text / General (text-prompt) ──
98
+ export const TEXT_WIZARD_CATEGORIES: readonly WizardCategory[] = [
99
+ { key: "purpose-intent", label: "Purpose / Intent" },
100
+ { key: "tone-voice", label: "Tone / Voice" },
101
+ { key: "audience", label: "Audience" },
102
+ { key: "length-format", label: "Length / Format" },
103
+ ]
104
+
105
+ // ── LLM Chat (llm-chat) ──
106
+ export const LLM_CHAT_WIZARD_CATEGORIES: readonly WizardCategory[] = [
107
+ { key: "task", label: "Task / Goal" },
108
+ { key: "tone", label: "Tone & Style" },
109
+ { key: "format", label: "Output Format" },
110
+ { key: "constraints", label: "Constraints" },
111
+ ]
112
+
113
+ // ── Node Type Mapping ──
114
+
115
+ const NODE_TYPE_TO_CATEGORIES: Record<string, readonly WizardCategory[]> = {
116
+ "llm-chat": LLM_CHAT_WIZARD_CATEGORIES,
117
+ "generate-image": IMAGE_WIZARD_CATEGORIES,
118
+ "image-to-image": IMAGE_WIZARD_CATEGORIES,
119
+ "modify-image": IMAGE_WIZARD_CATEGORIES,
120
+ "text-to-video": VIDEO_WIZARD_CATEGORIES,
121
+ "image-to-video": VIDEO_WIZARD_CATEGORIES,
122
+ "generate-video": VIDEO_WIZARD_CATEGORIES,
123
+ "video-to-video": VIDEO_WIZARD_CATEGORIES,
124
+ "motion-transfer": VIDEO_WIZARD_CATEGORIES,
125
+ "extend-video": VIDEO_WIZARD_CATEGORIES,
126
+ "speech-to-video": VIDEO_WIZARD_CATEGORIES,
127
+ // cinematic-avatar's `prompt` IS a generative prompt (unlike ai-avatar's
128
+ // verbatim `script`), so the wizard applies — see design spec Part B.
129
+ "cinematic-avatar": VIDEO_WIZARD_CATEGORIES,
130
+ "generate-music": MUSIC_WIZARD_CATEGORIES,
131
+ "suno-generate": MUSIC_WIZARD_CATEGORIES,
132
+ // Composite wizard targets: same music form as suno-generate, but the backend
133
+ // system-prompt builder reshapes the OUTPUT per field (not prose):
134
+ // :style → comma-separated Suno *style tags*
135
+ // :negativeStyle → comma-separated tags of styles/sounds to AVOID
136
+ // :lyrics → full sectioned song LYRICS ([Verse]/[Chorus]/…)
137
+ "suno-generate:style": MUSIC_WIZARD_CATEGORIES,
138
+ "suno-generate:negativeStyle": MUSIC_WIZARD_CATEGORIES,
139
+ "suno-generate:lyrics": MUSIC_WIZARD_CATEGORIES,
140
+ "text-to-audio": AUDIO_WIZARD_CATEGORIES,
141
+ "text-prompt": TEXT_WIZARD_CATEGORIES,
142
+ }
143
+
144
+ export function getCategoriesForNodeType(nodeType: string): readonly WizardCategory[] | undefined {
145
+ return NODE_TYPE_TO_CATEGORIES[nodeType]
146
+ }
147
+
148
+ /** Node types that support the wizard (excludes edit-image, text-to-speech, lip-sync) */
149
+ export function isWizardSupported(nodeType: string): boolean {
150
+ return nodeType in NODE_TYPE_TO_CATEGORIES
151
+ }
152
+
153
+ // ── Provider Capabilities (for model recommendation) ──
154
+ // Must be updated when providers are added (see Provider Enum Sync in CLAUDE.md)
155
+
156
+ export const PROVIDER_CAPABILITIES: Record<string, Record<string, string>> = {
157
+ "generate-image": {
158
+ "flux": "Photorealistic, highly detailed, best overall quality",
159
+ "flux-flex": "Fast Flux variant, good quality at lower cost",
160
+ "flux-kontext": "Character consistency, reference-image-aware generation",
161
+ "flux-kontext-max": "Premium character consistency with highest detail",
162
+ "nano-banana": "Fast generation, style flexibility, reference image support",
163
+ "nano-banana-pro": "Higher quality Nano Banana with better detail",
164
+ "nano-banana-2": "Latest Nano Banana with resolution options (1K/2K/4K)",
165
+ "gpt-image": "Creative concepts, illustration, variable quality tiers",
166
+ "gpt-image-2": "Latest GPT Image — sharp text, photorealism, 1K/2K/4K resolution",
167
+ "grok": "General purpose, good text understanding",
168
+ "imagen4": "Google's latest, strong photorealism and text rendering",
169
+ "imagen4-fast": "Faster Imagen 4 variant",
170
+ "imagen4-ultra": "Highest quality Imagen 4",
171
+ "ideogram-v3": "Best for typography, text-in-image, logos, reference images",
172
+ "qwen": "Versatile, good prompt adherence",
173
+ "seedream": "Artistic, painterly styles, creative interpretation",
174
+ "seedream-5-lite": "Lighter Seedream, faster artistic generation",
175
+ "z-image": "Experimental, novel generation approaches",
176
+ "wan-2.7": "Wan 2.7 T2I — 1K/2K/4K, up to 9 ref images",
177
+ "wan-2.7-pro": "Wan 2.7 Pro T2I — higher quality, 1K/2K/4K",
178
+ "flux-2-klein": "Open Flux 2 9B via Replicate — fast, no safety filter",
179
+ "flux-2-pro": "BFL Flux 2 Pro via Replicate — flagship quality, safety_tolerance=5 (max for Pro)",
180
+ "flux-2-max": "BFL Flux 2 Max via Replicate — even larger than Pro, safety_tolerance=5, up to 8 refs (variable pricing)",
181
+ },
182
+ "image-to-image": {
183
+ "nano-banana": "Fast style transfer and transformation",
184
+ "nano-banana-pro": "Higher quality transformations",
185
+ "grok-i2i": "General purpose image transformation",
186
+ "flux-i2i": "High quality image-to-image with strong prompt adherence",
187
+ "flux-pro-i2i": "Premium Flux transformation",
188
+ "gpt-image-i2i": "Creative reinterpretation of source images",
189
+ "gpt-image-2-i2i": "Latest GPT Image — pixel-level edits with original lighting/texture preservation, up to 4K",
190
+ "ideogram-edit": "Instruction-based editing with text preservation",
191
+ "ideogram-remix": "Style remixing while preserving structure",
192
+ "ideogram-reframe": "Aspect ratio changes with AI fill",
193
+ "qwen-i2i": "Versatile transformation",
194
+ "qwen-edit": "Instruction-based editing",
195
+ "seedream-edit": "Artistic style editing",
196
+ "seedream-5-lite-i2i": "Light artistic transformation",
197
+ "flux-kontext": "Character-consistent edits with reference awareness",
198
+ "flux-kontext-max": "Premium character-consistent editing",
199
+ "kontext-multi": "Multi-image Kontext via Replicate — up to 4 refs, no safety filter",
200
+ "flux-2-pro": "BFL Flux 2 Pro via Replicate — flagship quality with reference images, safety_tolerance=5",
201
+ "flux-2-max": "BFL Flux 2 Max via Replicate — even larger sibling, up to 8 refs, safety_tolerance=5 (variable pricing)",
202
+ },
203
+ "modify-image": {
204
+ "nano-banana": "Fast style transfer and transformation",
205
+ "nano-banana-pro": "Higher quality transformations",
206
+ "nano-banana-edit": "AI-powered image editing with instructions",
207
+ "grok-i2i": "General purpose image transformation",
208
+ "flux-i2i": "High quality image-to-image with strong prompt adherence",
209
+ "flux-pro-i2i": "Premium Flux transformation",
210
+ "gpt-image-i2i": "Creative reinterpretation of source images",
211
+ "gpt-image-2-i2i": "Latest GPT Image — pixel-level edits with original lighting/texture preservation, up to 4K",
212
+ "ideogram-edit": "Instruction-based editing with text preservation",
213
+ "ideogram-remix": "Style remixing while preserving structure",
214
+ "ideogram-reframe": "Aspect ratio changes with AI fill",
215
+ "qwen-i2i": "Versatile transformation",
216
+ "qwen-edit": "Instruction-based editing",
217
+ "seedream-edit": "Artistic style editing",
218
+ "seedream-5-lite-i2i": "Light artistic transformation",
219
+ "flux-kontext": "Character-consistent edits with reference awareness",
220
+ "flux-kontext-max": "Premium character-consistent editing",
221
+ "kontext-multi": "Multi-image Kontext via Replicate — up to 4 refs, no safety filter",
222
+ "flux-2-pro": "BFL Flux 2 Pro via Replicate — flagship quality with reference images, safety_tolerance=5",
223
+ "flux-2-max": "BFL Flux 2 Max via Replicate — even larger sibling, up to 8 refs, safety_tolerance=5 (variable pricing)",
224
+ },
225
+ "generate-mask": {
226
+ "grounded-sam": "Text-prompted segmentation — isolates the subject you describe in words (Grounding DINO + Segment Anything)",
227
+ },
228
+ "text-to-video": {
229
+ "minimax": "Versatile, good motion quality, reliable",
230
+ "veo3": "Google's latest, photorealistic, audio generation support",
231
+ "veo3.1": "Enhanced VEO with improved motion",
232
+ "veo3_lite": "Cheapest VEO tier, 4/6/8s output, ideal for high-volume/test runs",
233
+ "kling": "Cinematic, precise camera control, high motion quality",
234
+ "kling-turbo": "Faster Kling generation",
235
+ "kling-3.0": "Latest Kling with motion control and multi-shot",
236
+ "grok": "General purpose video generation",
237
+ "seedance": "Seedance 1.5 Pro — general-purpose cinematic model, end-frame support, 4/8/12s",
238
+ "seedance-2": "Seedance 2.0 — multimodal refs (9 images / 3 videos / 3 audio), native multi-track audio, multi-shot storytelling, 4-15s",
239
+ "seedance-2-fast": "Seedance 2.0 Fast — same multimodal + audio capabilities, cheaper and quicker",
240
+ "seedance-2-mini": "Seedance 2.0 Mini — same multimodal + audio capabilities, budget tier, 480p/720p, 4-15s",
241
+ "wan": "Versatile, good for animations and transformations",
242
+ "wan-turbo": "Faster Wan generation",
243
+ "hailuo-standard": "Standard quality, cost-effective",
244
+ "bytedance-lite": "Fast, lightweight generation",
245
+ "bytedance-pro": "Higher quality ByteDance",
246
+ "runway-kie": "Runway via KIE, strong cinematic quality",
247
+ "wan-2.7-t2v": "Wan 2.7 T2V — 2–15s, 720p/1080p",
248
+ "happyhorse": "HappyHorse T2V — 3–15s, 720p/1080p",
249
+ "ltx-2.3-pro": "Lightricks LTX 2.3 Pro — text/image/audio→video, 6–10s, up to 4K",
250
+ "ltx-2.3-fast": "Lightricks LTX 2.3 Fast — text/image→video, 6–20s, up to 4K",
251
+ "gemini-omni-video": "Google Gemini Omni — multimodal video with native audio, 4–10s, up to 4K.",
252
+ "grok-imagine-video-1.5": "Grok Imagine 1.5 — image-to-video only; requires an input image",
253
+ },
254
+ "image-to-video": {
255
+ "minimax": "Versatile animation from still images",
256
+ "veo3": "Photorealistic animation with audio",
257
+ "veo3.1": "Enhanced image animation",
258
+ "veo3_lite": "Cheapest VEO tier — half the cost of Fast, 4/6/8s + audio + first/last-frame",
259
+ "kling": "Precise motion from stills, camera control",
260
+ "kling-turbo": "Faster Kling animation",
261
+ "kling-3.0": "Latest Kling with advanced motion",
262
+ "kling-master": "Highest quality Kling",
263
+ "seedance": "Seedance 1.5 Pro — general i2v from a still, start/end frame, 4/8/12s",
264
+ "seedance-2": "Seedance 2.0 — start/end frame + multimodal refs, native audio, 4-15s",
265
+ "seedance-2-fast": "Seedance 2.0 Fast — same capabilities, cheaper and quicker",
266
+ "seedance-2-mini": "Seedance 2.0 Mini — same capabilities, budget tier, 480p/720p",
267
+ "hailuo-2.3-pro": "Premium Hailuo animation",
268
+ "hailuo-2.3": "Standard Hailuo animation",
269
+ "hailuo-standard": "Cost-effective animation",
270
+ "wan-i2v": "Versatile image-to-video",
271
+ "wan-turbo": "Fast image animation",
272
+ "bytedance-lite": "Fast, lightweight",
273
+ "bytedance-pro": "Higher quality ByteDance",
274
+ "bytedance-pro-fast": "Fast premium ByteDance",
275
+ "grok-i2v": "General purpose animation",
276
+ "runway-kie": "Cinematic image animation",
277
+ "wan-2.7-i2v": "Wan 2.7 I2V — 2–15s, 720p/1080p, start+end frame",
278
+ "happyhorse-i2v": "HappyHorse I2V — 3–15s, 720p/1080p",
279
+ "happyhorse-ref2v": "HappyHorse Ref2V — multi-ref image to video, 3–15s",
280
+ "ltx-2.3-pro": "Lightricks LTX 2.3 Pro — start/end frame i2v + audio→video, 6–10s, up to 4K",
281
+ "ltx-2.3-fast": "Lightricks LTX 2.3 Fast — start/end frame i2v, 6–20s, up to 4K",
282
+ "gemini-omni-video": "Google Gemini Omni — multimodal video with native audio, 4–10s, up to 4K.",
283
+ "grok-imagine-video-1.5": "Grok Imagine 1.5 — stylized animation, 1–15s, 480p/720p (image required)",
284
+ },
285
+ "video-to-video": {
286
+ "wan": "Style transfer and video transformation",
287
+ "luma-modify": "Video modification preserving structure",
288
+ "runway-aleph": "Advanced video transformation",
289
+ "happyhorse-edit": "HappyHorse video-to-video editing",
290
+ },
291
+ "motion-transfer": {
292
+ "kling": "Motion transfer with camera control",
293
+ "kling-3.0": "Advanced motion transfer",
294
+ "wan-animate-move": "Movement-based motion transfer",
295
+ "wan-animate-replace": "Subject replacement with motion preservation",
296
+ },
297
+ "extend-video": {
298
+ "veo-extend": "Extend VEO-generated videos",
299
+ "runway-extend": "Extend Runway-generated videos",
300
+ "seedance-2-extend": "Extend ANY video by URL — seamless trim-stitched continuation with audio (Seedance 2.0)",
301
+ },
302
+ "speech-to-video": {
303
+ "wan-speech": "Wan 2.2 speech-driven video generation",
304
+ },
305
+ "ai-avatar": {
306
+ "heygen": "HeyGen — industry-standard AI avatars; Avatar IV for established quality, Avatar V for premium fidelity",
307
+ },
308
+ "cinematic-avatar": {
309
+ "heygen": "HeyGen Cinematic Avatar — prompt-driven generative clip (Seedance pipeline) from 1-3 avatar looks",
310
+ },
311
+ "generate-music": {
312
+ "minimax": "General music generation, multiple genres",
313
+ },
314
+ "suno-generate": {
315
+ "V4": "Standard Suno generation",
316
+ "V4_5": "Improved quality and coherence",
317
+ "V4_5PLUS": "Enhanced V4.5 with better production",
318
+ "V4_5ALL": "Full-featured V4.5",
319
+ "V5": "Latest Suno with highest quality",
320
+ },
321
+ "text-to-audio": {
322
+ "elevenlabs-sfx": "High quality sound effects and ambient audio",
323
+ },
324
+ "text-prompt": {},
325
+ }
326
+
327
+ /** Reference image role options (for multi-select) */
328
+ export const REFERENCE_IMAGE_ROLES: readonly WizardOption[] = [
329
+ { value: "character", label: "Character reference", description: "Preserve identity, face, clothing exactly" },
330
+ { value: "style-mood", label: "Style / mood reference", description: "Apply lighting, color palette, atmosphere only" },
331
+ { value: "composition", label: "Composition reference", description: "Follow layout and framing" },
332
+ { value: "scene-background", label: "Scene / background reference", description: "Use as environment, ignore subjects" },
333
+ { value: "texture-material", label: "Texture / material reference", description: "Apply surface details and textures" },
334
+ ]
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Per-provider prompting doctrine — the single source of truth for "how to
3
+ * prompt model family X well". Consumed by:
4
+ * 1. backend/src/prompts/prompt-wizard-system.ts (enhance/generate system prompts)
5
+ * 2. backend/scripts/gen-skills (provider-prompting block in video node skills)
6
+ * 3. backend/src/lib/mcp/tools/models.ts (list_models promptTips)
7
+ * 4. compact recipes in MCP tool descriptions point here via get_node_skill
8
+ *
9
+ * Sources, in precedence order (conflicts resolve top-down):
10
+ * - Official BytePlus ModelArk "Dreamina Seedance 2.0 series prompt guide"
11
+ * https://docs.byteplus.com/en/docs/ModelArk/2222480
12
+ * - Official launch post https://seed.bytedance.com/en/blog/official-launch-of-seedance-2-0
13
+ * - KIE API docs https://docs.kie.ai/market/bytedance/seedance-2
14
+ */
15
+ export interface ProviderPromptDoctrine {
16
+ /** MODEL_CATALOG ids this doctrine covers. */
17
+ readonly providers: readonly string[]
18
+ /** Human heading for skill docs, e.g. "Seedance 2.0 (seedance-2, seedance-2-fast)". */
19
+ readonly heading: string
20
+ /** Short bullets for compact surfaces (list_models promptTips). ≤220 chars each. */
21
+ readonly tips: readonly string[]
22
+ /** Full markdown doctrine for system prompts and generated skill docs. */
23
+ readonly doctrine: string
24
+ }
25
+
26
+ const SEEDANCE_2_DOCTRINE: ProviderPromptDoctrine = {
27
+ providers: ["seedance-2", "seedance-2-fast", "seedance-2-mini"],
28
+ heading: "Seedance 2.0 (seedance-2, seedance-2-fast, seedance-2-mini)",
29
+ tips: [
30
+ "Storyboard complex videos as 'Shot 1: … Shot 2: …' WITHOUT timestamps — timed shots like '(0-3s)' are officially unstable and can break generation.",
31
+ "One camera movement per shot; describe actions per body part with degree ('slowly raises a hand'); express emotion as physical detail, never abstract words.",
32
+ "Native multi-track audio — cue it inline: (background music), <sound effects>, and quoted dialogue.",
33
+ "References go by ordinal (@Image 1, Video 2) in attachment order; earlier = higher priority. Identity = ONE headshot + ONE full-body (multi-view sheets cause ID drift). 4-5 assets total beats maxing the 9/3/3 caps.",
34
+ "No negative-prompt parameter — put constraints in the prompt: 'keep it subtitle-free, do not generate a watermark, do not generate a logo'.",
35
+ ],
36
+ doctrine: `Prompt structure (front-load what matters most):
37
+ precise subject → action details → scene/environment → lighting & color tone → camera movement → visual style → image quality → constraints.
38
+
39
+ **Shots & pacing**
40
+ - Storyboard complex videos as "Shot 1: … Shot 2: … Shot 3: …" in event order. Do NOT attach timestamps (e.g. "(0-3s)") — precise-timing support is officially unstable and forcing durations can break generation; let the model pace naturally.
41
+ - Per shot cover, in order: camera move or transition, subject action + expression, spatial/position change, audio for that shot.
42
+ - One camera movement type per shot — never ask for push + pan + orbit at once (image instability).
43
+ - Prefer slow, gentle, continuous movements over high-burst action (sprints, big jumps, violent rolls morph). Describe actions per body part with quantified degree: "slowly raises a hand", "pushes hard off the ground". Chain actions with inertia: "uses the momentum of the turn to naturally raise an arm".
44
+ - Express emotion as externalized physical detail, never abstract words: not "very sad" but "lowering the head, shoulders trembling slightly, eyes reddening, fingers clutching the corner of clothing".
45
+
46
+ **References (when reference media is attached)**
47
+ - Refer to assets by ordinal in attachment order: "@Image 1", "Video 2", "Audio 1". Asset ORDER is priority — put the most identity-critical asset first. (In the editor, the \`{image:N:label}\` / \`{video:N}\` / \`{audio:N}\` prompt tokens auto-emit this binding — \`{image:1:person}\` resolves to "the person from @image_1" — so a wired reference and its mention stay in sync.)
48
+ - Define each subject once, then reuse the label consistently: 'Define the woman in the red dress in Image 1 as the courier' … '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".
49
+ - Character identity: ONE close-up headshot + ONE full-body image is ideal. Do NOT attach multi-view/three-view character sheets — the model reads the views as separate people, causing identity drift and twin duplicates.
50
+ - 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.
51
+ - Editing/extension instructions name clips directly: "Extend Video 1 backward…", "Remove the chair from Video 1". Saying "reference Video 1" flips the model into reference mode and breaks the edit. Track completion: "Video 1 + [transition description] + followed by Video 2" (≤3 clips, ≤15s total).
52
+
53
+ **Audio (native multi-track: music + ambience + voice, stereo)**
54
+ - Cue the layers separately with the official symbols: full-width parentheses for music (slow jazz piano in the background), angle brackets for sound effects <rain tapping on glass>, and dialogue as quoted speech: the man says "It's not that bad". Seedance also accepts curly-brace dialogue, but on Nodaro curly braces are reserved for prompt variables — always use quotes for dialogue here.
55
+ - Mark the language for non-English/Chinese dialogue ("says in Japanese …").
56
+ - With a reference voice attached, also describe the timbre in words: "the low, warm, finely grainy middle-aged male voice of Audio 1".
57
+
58
+ **Quality & constraints**
59
+ - Quality tail: "HD, rich details, cinematic texture, natural colors, stable picture."
60
+ - Anti-junk constraints (these official templates ARE negative-form): "keep it subtitle-free", "avoid generating any text or subtitles", "do not generate a watermark", "do not generate a logo". Landscape output is markedly less subtitle-prone than portrait — generate 16:9 and crop when portrait text-safety matters.
61
+ - There is NO negative-prompt parameter on Seedance — all constraints belong in the prompt text itself.
62
+
63
+ **Known weaknesses → workarounds**
64
+ - Text rendering is weak: keep on-screen text to short common words; for exact text or logos, attach the artwork as a reference image and instruct "the logo from Image N stays in the corner unchanged".
65
+ - More than 4 referenced people gets unstable: group people into composite images of ≤4 first (image generation), then reference those composites.
66
+ - Repeated extension degrades quality: prefer high-definition reference assets and avoid stacking many continuations.`,
67
+ }
68
+
69
+ export const PROVIDER_PROMPT_DOCTRINES: readonly ProviderPromptDoctrine[] = [
70
+ SEEDANCE_2_DOCTRINE,
71
+ ]
72
+
73
+ const DOCTRINE_BY_PROVIDER: ReadonlyMap<string, ProviderPromptDoctrine> = new Map(
74
+ PROVIDER_PROMPT_DOCTRINES.flatMap((d) => d.providers.map((p) => [p, d] as const)),
75
+ )
76
+
77
+ /** Full doctrine for a provider id, or undefined when none exists. */
78
+ export function getPromptDoctrine(providerId: string): ProviderPromptDoctrine | undefined {
79
+ return DOCTRINE_BY_PROVIDER.get(providerId)
80
+ }
81
+
82
+ /** Compact tips for a provider id ([] when none) — used by list_models. */
83
+ export function getPromptTips(providerId: string): readonly string[] {
84
+ return DOCTRINE_BY_PROVIDER.get(providerId)?.tips ?? []
85
+ }
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Canonical catalog of Render Engine / Quality presets.
3
+ *
4
+ * "Render Quality" is the pure technical-stamp dimension — what tool the image
5
+ * appears to have been rendered through, or what quality stamp it carries.
6
+ * Distinct from Style (artistic medium), Lens (optics), and Camera Format
7
+ * (capture medium): a "raytracing" hint says nothing about whether the look
8
+ * is anime or photorealistic; it just promises ray-traced-grade reflections,
9
+ * shadows, and global illumination.
10
+ *
11
+ * Three loose families, each adding a different kind of authority signal:
12
+ * - Engines: name a real render package (Unreal 5, Octane, Cycles…). Useful
13
+ * for hyper-stylized 3D illustration or game-trailer aesthetics.
14
+ * - Render-quality keywords: the technical buzzwords that lock in modern
15
+ * physically-correct lighting (raytracing, PBR, GI, lumen).
16
+ * - Resolution / Detail: explicit "sharp + detailed" stamps (4K/8K/16K,
17
+ * "ultra-detailed").
18
+ * - Style stamps: portmanteau quality markers ("masterpiece", "raw photo",
19
+ * "award-winning") that providers strongly weight.
20
+ *
21
+ * Single-pick — only one render-quality stamp is applied per consumer. Shared
22
+ * between picker UI and prompt-hint injection in the frontend DAG executor
23
+ * and the backend orchestrator.
24
+ */
25
+
26
+ export interface RenderQuality {
27
+ readonly id: string
28
+ readonly label: string
29
+ readonly description: string
30
+ readonly promptHint: string
31
+ }
32
+
33
+ export const RENDER_QUALITIES: ReadonlyArray<RenderQuality> = [
34
+ // ---------------------------- Engines ----------------------------
35
+ { id: "unreal-engine-5", label: "Unreal Engine 5", description: "Real-time path-traced UE5 look", promptHint: "rendered in Unreal Engine 5, real-time path-traced lighting with Lumen reflections, Nanite-grade micro-detail and cinematic post-processing" },
36
+ { id: "blender-cycles", label: "Blender Cycles", description: "Cycles unbiased path tracing", promptHint: "rendered in Blender Cycles, unbiased path-traced lighting with physically accurate shadows, soft global illumination and clean denoise" },
37
+ { id: "octane-render", label: "Octane Render", description: "GPU spectral path tracing", promptHint: "rendered in Octane, GPU spectral path tracing with hyper-realistic materials, vivid color response and crisp specular highlights" },
38
+ { id: "redshift", label: "Redshift", description: "Production GPU biased renderer", promptHint: "rendered in Redshift, production-quality GPU rendering with rich material response, controlled GI and film-grade depth" },
39
+ { id: "houdini-mantra", label: "Houdini Mantra", description: "VFX-grade physical rendering", promptHint: "rendered in Houdini Mantra, VFX-grade physically-based rendering with subtle volumetric scatter and ultra-clean shading" },
40
+ { id: "arnold-render", label: "Arnold Render", description: "Industry-standard VFX path tracer", promptHint: "rendered in Solid Angle Arnold, industry-standard VFX path-traced lighting with physically accurate light transport, smooth noise-free shading, and the flagship Pixar / ILM / Sony feature-film polish" },
41
+ { id: "corona-renderer", label: "Corona Renderer", description: "Photorealistic archviz unbiased renderer", promptHint: "rendered in Chaos Corona, unbiased photorealistic rendering with crisp daylight global illumination, refined material response and the signature architectural-visualization clarity" },
42
+ { id: "vray", label: "V-Ray", description: "Industry-standard product / archviz / VFX renderer", promptHint: "rendered in Chaos V-Ray, industry-standard hybrid path-traced production rendering with razor-sharp detail, accurate reflections and the polished product-viz / archviz / VFX finish" },
43
+ { id: "aces", label: "ACES", description: "Cinema-grade ACES color management", promptHint: "graded through the ACES (Academy Color Encoding System) color management workflow, modern cinema-grade tonal response with consistent wide-gamut color rendering, filmic highlight rolloff and reference-quality color fidelity" },
44
+
45
+ // ---------------------------- Render-quality keywords ----------------------------
46
+ { id: "raytracing", label: "Ray Tracing", description: "Accurate reflections + shadows", promptHint: "ray-traced rendering, physically accurate reflections, refractions and contact shadows with realistic light bounce" },
47
+ { id: "physically-based-rendering", label: "PBR", description: "Physically-based materials", promptHint: "physically-based rendering with energy-conserving materials, accurate metallic/roughness response and realistic Fresnel falloff" },
48
+ { id: "global-illumination", label: "Global Illumination", description: "Realistic light bounce", promptHint: "global illumination, realistic indirect light bounce with soft color bleeding between surfaces and naturally lit shadow regions" },
49
+ { id: "lumen-reflections", label: "Lumen Reflections", description: "Real-time dynamic GI", promptHint: "Lumen-style real-time dynamic global illumination with crisp screen-space reflections, soft contact shadows and beautifully lit indirect bounces" },
50
+
51
+ // ---------------------------- Resolution / Detail ----------------------------
52
+ { id: "8k-uhd", label: "8K UHD", description: "Ultra-sharp 8K resolution", promptHint: "8K ultra-high-definition resolution, ultra-sharp detail with every micro-texture preserved and zero softness" },
53
+ { id: "4k-uhd", label: "4K UHD", description: "Crisp 4K resolution", promptHint: "4K UHD resolution, crisp detail with cinema-grade clarity and clean edge definition" },
54
+ { id: "16k-megapixel", label: "16K Megapixel", description: "Insanely high-resolution detail", promptHint: "16K megapixel-grade resolution, insanely high-resolution detail with surgically clean edges and microscopic surface fidelity" },
55
+ { id: "ultra-detailed", label: "Ultra Detailed", description: "Maximum micro-detail rendering", promptHint: "ultra-detailed rendering with intricate micro-surface detail, fine pore-level fidelity and meticulously preserved fine structures" },
56
+
57
+ // ---------------------------- Style stamps ----------------------------
58
+ { id: "raw-photo", label: "Raw Photo", description: "Unprocessed photographic feel", promptHint: "raw photograph aesthetic, unprocessed natural color science, authentic photographic detail and untouched documentary realism" },
59
+ { id: "masterpiece", label: "Masterpiece", description: "Hand-of-an-expert quality stamp", promptHint: "masterpiece-quality rendering, hand-of-an-expert level execution with refined composition, immaculate detail and curated finish" },
60
+ { id: "award-winning", label: "Award Winning", description: "Award-circuit caliber", promptHint: "award-winning quality, award-circuit caliber image with editorial-grade composition, magazine-cover finish and signature visual authority" },
61
+
62
+ // ---------------------------- Lighting / Image-quality passes ----------------------------
63
+ { id: "volumetric-lighting", label: "Volumetric Lighting", description: "God-ray volumetric light shafts cutting through atmosphere", promptHint: "volumetric lighting with god-ray light shafts cutting through atmospheric haze, beams of illuminated dust and particulate scattering through the scene" },
64
+ { id: "photon-mapping", label: "Photon Mapping", description: "Caustic-aware photon-mapped global illumination renderer", promptHint: "photon-mapped global illumination with caustic-aware light transport, accurate refractive light patterns through glass and water and physically correct indirect bounces" },
65
+ { id: "ai-upscaled", label: "AI Upscaled", description: "Neural-network upscaled detail enhancement, sharp super-resolution", promptHint: "neural-network AI-upscaled detail enhancement, sharp super-resolution clarity with reconstructed micro-detail and surgically clean edge definition" },
66
+ { id: "denoised", label: "Denoised", description: "Clean noise-removed pristine rendering, no grain or speckle", promptHint: "clean denoised rendering with noise removed entirely, pristine smooth surfaces and zero grain or speckle across shadows and midtones" },
67
+ ] as const
68
+
69
+ const renderQualityById = new Map<string, RenderQuality>(
70
+ RENDER_QUALITIES.map((r) => [r.id, r]),
71
+ )
72
+
73
+ export function getRenderQuality(id: string | undefined | null): RenderQuality | undefined {
74
+ if (!id) return undefined
75
+ return renderQualityById.get(id)
76
+ }
77
+
78
+ export function getRenderQualityLabel(id: string | undefined | null, fallback?: string): string {
79
+ const r = getRenderQuality(id)
80
+ if (r) return r.label
81
+ if (fallback !== undefined) return fallback
82
+ return (id ?? "").replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase())
83
+ }
84
+
85
+ export function getRenderQualityPromptHint(id: string | undefined | null): string {
86
+ return getRenderQuality(id)?.promptHint ?? ""
87
+ }
88
+
89
+ export const RENDER_QUALITY_IDS: ReadonlyArray<string> = RENDER_QUALITIES.map((r) => r.id)