@nodetool-ai/agents 0.8.4-a24.2 → 0.8.4

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 (135) hide show
  1. package/dist/.nodetool-build-stamp +1 -1
  2. package/dist/_skills/LICENSE-iart-motion-design-skills +21 -0
  3. package/dist/_skills/README.md +211 -0
  4. package/dist/_skills/api-agents/SKILL.md +58 -0
  5. package/dist/_skills/api-apps/SKILL.md +54 -0
  6. package/dist/_skills/api-assets/SKILL.md +66 -0
  7. package/dist/_skills/api-collections/SKILL.md +33 -0
  8. package/dist/_skills/api-games/SKILL.md +81 -0
  9. package/dist/_skills/api-media/SKILL.md +131 -0
  10. package/dist/_skills/api-memory/SKILL.md +72 -0
  11. package/dist/_skills/api-models/SKILL.md +78 -0
  12. package/dist/_skills/api-scripts/SKILL.md +79 -0
  13. package/dist/_skills/api-settings/SKILL.md +49 -0
  14. package/dist/_skills/api-sketches/SKILL.md +61 -0
  15. package/dist/_skills/api-storyboards/SKILL.md +94 -0
  16. package/dist/_skills/api-timelines/SKILL.md +151 -0
  17. package/dist/_skills/api-web/SKILL.md +57 -0
  18. package/dist/_skills/api-workflows/SKILL.md +123 -0
  19. package/dist/_skills/beat-sync-editing/SKILL.md +208 -0
  20. package/dist/_skills/caption-titles/SKILL.md +94 -0
  21. package/dist/_skills/color-motion/SKILL.md +185 -0
  22. package/dist/_skills/commercial-beat-sheet/SKILL.md +338 -0
  23. package/dist/_skills/elevenlabs-audio-prompting/SKILL.md +163 -0
  24. package/dist/_skills/explainer-storyboard/SKILL.md +63 -0
  25. package/dist/_skills/flux-2-klein-prompting/SKILL.md +107 -0
  26. package/dist/_skills/frame-composition/SKILL.md +291 -0
  27. package/dist/_skills/game-direction/SKILL.md +99 -0
  28. package/dist/_skills/gpt-image-2-prompting/SKILL.md +161 -0
  29. package/dist/_skills/hailuo-prompting/SKILL.md +107 -0
  30. package/dist/_skills/kling-video-prompting/SKILL.md +188 -0
  31. package/dist/_skills/launch-commercial/SKILL.md +267 -0
  32. package/dist/_skills/launch-kit/SKILL.md +120 -0
  33. package/dist/_skills/logo-reveal/SKILL.md +225 -0
  34. package/dist/_skills/manimgx/SKILL.md +123 -0
  35. package/dist/_skills/minimax-h3-prompting/SKILL.md +134 -0
  36. package/dist/_skills/motion-ad/SKILL.md +281 -0
  37. package/dist/_skills/motion-background/SKILL.md +145 -0
  38. package/dist/_skills/motion-curves/SKILL.md +302 -0
  39. package/dist/_skills/motion-direction/SKILL.md +259 -0
  40. package/dist/_skills/motion-graphics/SKILL.md +217 -0
  41. package/dist/_skills/motion-principles/SKILL.md +255 -0
  42. package/dist/_skills/music-video-treatment/SKILL.md +40 -0
  43. package/dist/_skills/nano-banana-pro-prompting/SKILL.md +133 -0
  44. package/dist/_skills/native-game/SKILL.md +310 -0
  45. package/dist/_skills/native-game-reference/SKILL.md +879 -0
  46. package/dist/_skills/nodetool-3d-scene/SKILL.md +110 -0
  47. package/dist/_skills/nodetool-api-reference/SKILL.md +338 -0
  48. package/dist/_skills/nodetool-app-builder/SKILL.md +291 -0
  49. package/dist/_skills/nodetool-browser-agent/SKILL.md +119 -0
  50. package/dist/_skills/nodetool-chat-cli/SKILL.md +184 -0
  51. package/dist/_skills/nodetool-custom-node-developer/SKILL.md +294 -0
  52. package/dist/_skills/nodetool-deployment/SKILL.md +195 -0
  53. package/dist/_skills/nodetool-js-scripting/SKILL.md +223 -0
  54. package/dist/_skills/nodetool-model-provider-config/SKILL.md +348 -0
  55. package/dist/_skills/nodetool-rag-indexing/SKILL.md +153 -0
  56. package/dist/_skills/nodetool-sketch/SKILL.md +138 -0
  57. package/dist/_skills/nodetool-skill-author/SKILL.md +125 -0
  58. package/dist/_skills/nodetool-troubleshooter/SKILL.md +370 -0
  59. package/dist/_skills/nodetool-video-post/SKILL.md +149 -0
  60. package/dist/_skills/nodetool-workflow-builder/SKILL.md +295 -0
  61. package/dist/_skills/product-commercial/SKILL.md +132 -0
  62. package/dist/_skills/qwen-image-prompting/SKILL.md +122 -0
  63. package/dist/_skills/script-video/SKILL.md +106 -0
  64. package/dist/_skills/seedance-2-prompting/SKILL.md +194 -0
  65. package/dist/_skills/seedream-prompting/SKILL.md +117 -0
  66. package/dist/_skills/short-film/SKILL.md +123 -0
  67. package/dist/_skills/stable-audio-prompting/SKILL.md +130 -0
  68. package/dist/_skills/storyboard-core/SKILL.md +716 -0
  69. package/dist/_skills/timeline-edit-ops/SKILL.md +736 -0
  70. package/dist/_skills/trailer-template/SKILL.md +291 -0
  71. package/dist/_skills/ugc-video/SKILL.md +186 -0
  72. package/dist/_skills/veo-3-prompting/SKILL.md +140 -0
  73. package/dist/_skills/video-audio-continuity/SKILL.md +90 -0
  74. package/dist/_skills/video-clone/SKILL.md +96 -0
  75. package/dist/_skills/video-workflow/SKILL.md +119 -0
  76. package/dist/_skills/wan-2-6-prompting/SKILL.md +107 -0
  77. package/dist/app-build/bridge.d.ts.map +1 -1
  78. package/dist/app-build/bridge.js +44 -17
  79. package/dist/app-build/bridge.js.map +1 -1
  80. package/dist/capabilities/apps.d.ts.map +1 -1
  81. package/dist/capabilities/apps.js +55 -13
  82. package/dist/capabilities/apps.js.map +1 -1
  83. package/dist/capabilities/apps.specs.d.ts.map +1 -1
  84. package/dist/capabilities/apps.specs.js +5 -3
  85. package/dist/capabilities/apps.specs.js.map +1 -1
  86. package/dist/capabilities/game-asset-browser.d.ts.map +1 -1
  87. package/dist/capabilities/game-asset-browser.js +6 -1
  88. package/dist/capabilities/game-asset-browser.js.map +1 -1
  89. package/dist/capabilities/game.d.ts +1 -1
  90. package/dist/capabilities/game.d.ts.map +1 -1
  91. package/dist/capabilities/game.js +71 -56
  92. package/dist/capabilities/game.js.map +1 -1
  93. package/dist/capabilities/game.specs.js +1 -1
  94. package/dist/capabilities/game.specs.js.map +1 -1
  95. package/dist/capabilities/game3d.d.ts.map +1 -1
  96. package/dist/capabilities/game3d.js +14 -19
  97. package/dist/capabilities/game3d.js.map +1 -1
  98. package/dist/capabilities/gameAssertions.d.ts +52 -0
  99. package/dist/capabilities/gameAssertions.d.ts.map +1 -0
  100. package/dist/capabilities/gameAssertions.js +32 -0
  101. package/dist/capabilities/gameAssertions.js.map +1 -0
  102. package/dist/capabilities/models.d.ts.map +1 -1
  103. package/dist/capabilities/models.js +9 -0
  104. package/dist/capabilities/models.js.map +1 -1
  105. package/dist/capabilities/storyboards.d.ts.map +1 -1
  106. package/dist/capabilities/storyboards.js +36 -11
  107. package/dist/capabilities/storyboards.js.map +1 -1
  108. package/dist/capabilities/storyboards.specs.d.ts.map +1 -1
  109. package/dist/capabilities/storyboards.specs.js +11 -1
  110. package/dist/capabilities/storyboards.specs.js.map +1 -1
  111. package/dist/capabilities/workflows.d.ts.map +1 -1
  112. package/dist/capabilities/workflows.js +1 -0
  113. package/dist/capabilities/workflows.js.map +1 -1
  114. package/dist/capabilities/workflows.specs.d.ts.map +1 -1
  115. package/dist/capabilities/workflows.specs.js +4 -3
  116. package/dist/capabilities/workflows.specs.js.map +1 -1
  117. package/dist/evals/surfaces/game.d.ts.map +1 -1
  118. package/dist/evals/surfaces/game.js +29 -1
  119. package/dist/evals/surfaces/game.js.map +1 -1
  120. package/dist/game-authoring.d.ts +120 -0
  121. package/dist/game-authoring.d.ts.map +1 -1
  122. package/dist/game-build-integrity.d.ts +12 -0
  123. package/dist/game-build-integrity.d.ts.map +1 -0
  124. package/dist/game-build-integrity.js +78 -0
  125. package/dist/game-build-integrity.js.map +1 -0
  126. package/dist/game-examples.d.ts +44 -3
  127. package/dist/game-examples.d.ts.map +1 -1
  128. package/dist/game-examples.js +60 -10
  129. package/dist/game-examples.js.map +1 -1
  130. package/dist/system-skills.d.ts +1 -1
  131. package/dist/system-skills.js +1 -1
  132. package/dist/tools/builtin-tools.d.ts.map +1 -1
  133. package/dist/tools/builtin-tools.js +2 -0
  134. package/dist/tools/builtin-tools.js.map +1 -1
  135. package/package.json +19 -19
@@ -0,0 +1,163 @@
1
+ ---
2
+ name: elevenlabs-audio-prompting
3
+ description: Direct ElevenLabs speech, dialogue, sound effects and music — v3 audio tags and the voice that decides whether they land, stability as the delivery dial, punctuation for pacing, the per-line dialogue list, source-action-space sound-effect briefs, and the music composition plan. Use whenever the model id names an ElevenLabs generation endpoint (fal-ai/elevenlabs/tts/eleven-v3, fal-ai/elevenlabs/tts/multilingual-v2, fal-ai/elevenlabs/text-to-dialogue/eleven-v3, fal-ai/elevenlabs/sound-effects/v2, fal-ai/elevenlabs/music, elevenlabs/text-to-speech-multilingual-v2, elevenlabs/text-to-dialogue-v3, elevenlabs/v2-multilingual, elevenlabs/turbo-v2.5, direct eleven_v3, eleven_multilingual_v2, eleven_turbo_v2_5 and eleven_flash_v2_5) on generate_speech, generate_music, run_node or a TextToSpeech node. Not for Eleven v4, ElevenLabs Music v2 or v2.5, or the transcription, dubbing and isolation endpoints.
4
+ ---
5
+
6
+ # ElevenLabs → direct the read, don't just submit the text
7
+
8
+ The text is the smallest part of an ElevenLabs request. What decides whether it
9
+ sounds directed is the voice you picked, the stability you set, and the tags
10
+ and punctuation carrying the performance.
11
+
12
+ Reach speech with `find_model` for `text_to_speech`, then `generate_speech`;
13
+ music with `find_model` for `text_to_music`, then `generate_music`.
14
+ `generate_speech` forwards only the text, the voice and the speed, and
15
+ `generate_music` only the prompt, lyrics and a duration. Stability,
16
+ `language_code`, the dialogue list, `composition_plan`, `force_instrumental` and
17
+ every sound-effect field below exist only on the route's own node:
18
+ `elevenlabs.TextToSpeech` for the direct `eleven_*` models, the fal, kie or
19
+ Replicate node for the others. Find it with `search_nodes`, read its fields with
20
+ `get_node_info`, and run it with `run_node`. Each run is a paid generation, so
21
+ confirm the scope with the user before running several.
22
+
23
+ ## Voice first, then tags
24
+
25
+ A tag only does what the voice can already do. `[shouts]` on a voice trained on
26
+ soft narration produces a slightly louder narration. Pick a voice whose range
27
+ covers the delivery you want, then direct within it.
28
+
29
+ - **Emotionally varied** voices take direction across a scene.
30
+ - **Narrow, consistent** voices are right when every line is the same register.
31
+ - **Neutral** voices are the most stable across languages and styles.
32
+
33
+ ## Stability is the delivery dial
34
+
35
+ The single most consequential setting. ElevenLabs names three points on it.
36
+ The speech routes take any value from 0 to 1 (default 0.5). The dialogue routes
37
+ take only the three named points, and fal's rounds anything else to the
38
+ nearest of them.
39
+
40
+ | Value | Behaviour | Use for |
41
+ | :--- | :--- | :--- |
42
+ | 0.0 — creative | Most expressive, most responsive to tags, occasional hallucination | Character work, dialogue, anything with `[whispers]` or `[laughs]` |
43
+ | 0.5 — natural | Balanced, closest to the reference recording | Narration, most production reads |
44
+ | 1.0 — robust | Very consistent, largely ignores directional tags | Long documents, repeated renders that must match |
45
+
46
+ At 1.0 your tags stop working. If a tag is being ignored, check stability
47
+ before rewriting the tag.
48
+
49
+ ## Audio tags
50
+
51
+ Bracketed, inline, and they act from that point in the line. They are a v3
52
+ feature: on multilingual-v2, turbo and flash there is nothing to act on them,
53
+ and punctuation plus sentence structure are the only direction you have.
54
+
55
+ - **Delivery**: `[whispers]`, `[shouts]`, `[sarcastic]`, `[curious]`,
56
+ `[excited]`, `[mischievously]`
57
+ - **Reactions**: `[laughs]`, `[sighs]`, `[crying]`, `[clears throat]`,
58
+ `[snorts]`
59
+ - **Environment**: `[applause]`, `[clapping]`, `[gunshot]`, `[explosion]`
60
+ - **Experimental**: `[sings]`, `[strong French accent]`
61
+
62
+ Punctuation carries the rest, and v3 does not support SSML break tags. Ellipses
63
+ are pauses and hesitation, capitals are emphasis, ordinary commas and full
64
+ stops set the rhythm:
65
+
66
+ > [sighs] It was a VERY long day … nobody listens any more. [quietly] Maybe
67
+ > that's the point.
68
+
69
+ Give the model a few sentences rather than a fragment. Short isolated lines
70
+ deliver inconsistently because there is no context to read the register from.
71
+ `language_code` forces a language when the text alone is ambiguous.
72
+
73
+ ## Several speakers
74
+
75
+ The dialogue endpoint takes a list of lines, each with its own text and
76
+ voice, rather than one block of text with names in it. fal calls the list
77
+ `inputs` and kie calls it `dialogue`. The speaker is the entry's voice, never a
78
+ name in the text, because anything bracketed in the text is read as an audio
79
+ tag. Tag each line for its own delivery, and write interruptions as they
80
+ happen:
81
+
82
+ ```json
83
+ [
84
+ {"text": "[flat] You said you'd call.", "voice": "<Ana's voice id>"},
85
+ {"text": "[defensive] I did — twice —", "voice": "<Ruben's voice id>"},
86
+ {"text": "[cutting in] Once. And you hung up.", "voice": "<Ana's voice id>"}
87
+ ]
88
+ ```
89
+
90
+ Distinct voices per speaker is what makes it a conversation; the same voice
91
+ twice reads as one person talking to themselves.
92
+
93
+ ## Sound effects
94
+
95
+ Brief them as source, action and space: what makes the sound, what happens to
96
+ it, and the room it happens in.
97
+
98
+ > A heavy oak door swinging shut and latching in a stone corridor, long natural
99
+ > reverb tail, close mic on the latch.
100
+
101
+ - `duration_seconds` runs 0.5–22; leave it unset and the model infers a length
102
+ from the prompt. Impacts want 1–3 s, beds want 10–20 s.
103
+ - `prompt_influence` defaults to 0.3. Raise it toward 1 to follow the brief
104
+ closely and lose variation; lower it when you want takes to choose from.
105
+ - `loop` makes the tail blend into the head — the setting for ambience and game
106
+ audio, and pointless for a one-shot.
107
+
108
+ ## Music
109
+
110
+ A prompt gets you a track: genre, instrumentation with character, tempo in bpm,
111
+ emotional arc, and what it is for.
112
+
113
+ > Fast-paced electronic chase cue for a game trailer, driving synth arpeggios,
114
+ > punchy drums, distorted bass, rising tension with abrupt transitions,
115
+ > 130–150 bpm.
116
+
117
+ When the structure matters more than the vibe, send a `composition_plan`
118
+ instead: an ordered list of sections, each with its own `durationMs`,
119
+ `positiveStyles` and `negativeStyles`. That is what makes an intro stay sparse
120
+ and a drop actually land where you wanted it. `respect_sections_durations`
121
+ enforces those lengths; `music_length_ms` applies only to the prompt path.
122
+ `force_instrumental` asks for no vocal. It defaults to false on fal, so a
123
+ prompt that does not mention vocals may still come back sung, and to true on
124
+ Replicate's `elevenlabs/music`.
125
+
126
+ The vendor's guide says a prompt naming an artist, a band or copyrighted
127
+ lyrics is rejected, with a rephrasing suggestion in the error. Describe the
128
+ sound instead of the reference.
129
+
130
+ ## Symptoms
131
+
132
+ | What went wrong | What to change |
133
+ | :--- | :--- |
134
+ | Tags do nothing | Lower stability to 0.5 or 0.0, and check the voice can do that delivery |
135
+ | The read is flat | Add punctuation and a delivery tag; stop relying on the words alone |
136
+ | Pauses are ignored | Use ellipses and line structure — SSML breaks are not supported |
137
+ | Two speakers sound the same | Assign a different voice per dialogue entry |
138
+ | The effect is too variable | Raise `prompt_influence`, and set an explicit duration |
139
+ | A loop clicks | Set `loop` true and regenerate rather than trimming |
140
+ | A song ignores its structure | Move from a prompt to a `composition_plan` |
141
+ | The prompt was refused | Remove artist and band names; describe the sound |
142
+
143
+ Check the result with `analyze_audio` and `detect_audio_events` rather than
144
+ listening through it, and `transcribe_audio` when you need to prove the words
145
+ landed as written.
146
+
147
+ ## Where it lands
148
+
149
+ A voice or a bed from here is the "track of your own" build in
150
+ `video-audio-continuity`: it goes on its own audio track and the generated
151
+ clips are muted under it, which is what lets a multi-scene piece keep one
152
+ continuous mix. For a storyboard's script, `voice_script_lines` voices every
153
+ line in one call, each with its own voice, instead of one `generate_speech`
154
+ per line. A bed built from a `composition_plan` has sections of known length,
155
+ which is the grid `beat-sync-editing` cuts to; a sound-effect hit is what
156
+ `logo-reveal` times a sting against. `motion-graphics` carries the timeline ops
157
+ that lay the clip down.
158
+
159
+ Adapted from the ElevenLabs prompting documentation for Eleven v3, sound
160
+ effects and music:
161
+ https://elevenlabs.io/docs/best-practices/prompting/eleven-v3
162
+ https://elevenlabs.io/docs/overview/capabilities/sound-effects
163
+ https://elevenlabs.io/docs/eleven-api/guides/cookbooks/music.md
@@ -0,0 +1,63 @@
1
+ ---
2
+ name: explainer-storyboard
3
+ description: Turn a confirmed product or feature brief into a shootable 30–120 second explainer storyboard with a consistent entity roster. Use for the beat structure of an explanatory product video, not workflows, pipelines, or finished renders. A narrated explainer whose shots are timed to the voiceover also loads script-video for the script, voice and timing.
4
+ ---
5
+
6
+ # Explainer Storyboard → Storyboard Agent
7
+
8
+ Create a complete, shootable explainer beat sheet as a NodeTool storyboard. Work directly through the storyboard and entity capability modules. Do not build a workflow or run a pipeline. Do not render stills, clips, or assemble a timeline unless the user asks.
9
+
10
+ This skill is the explainer's structure. When the voiceover should time the shots, load `script-video` as well: write the VO from this beat sheet into a script, voice it, and let the linked board take each shot's length from its takes.
11
+
12
+ ## Truthful brief
13
+
14
+ Collect these facts before creating a board: product or feature, brand and traits, category, audience, core problem, shift, 2–4 concrete mechanism steps, proof assets, CTA, runtime (30, 60, 90, or 120 seconds), platform, tone, mandatory content, and forbidden claims. The core problem, shift, and mechanism are required. Never invent a capability, integration, metric, screen, or customer. Write `[CLIENT INPUT NEEDED]` wherever proof is not confirmed.
15
+
16
+ ## Resolve entities before beats
17
+
18
+ Every recurring person, location, product UI, device, metaphor object, brand mark, and visual style is an entity. Start with `list_entities`; reuse user-provided references and existing entities before generating anything. A real product screenshot is a `prop` reference and must never be regenerated.
19
+
20
+ Resolve a style entity first. Generate only missing references, applying that style before generating each other entity. A typical 60-second explainer has 4–7 entities: style, persona, optional location, product UI prop, and metaphor prop. Label generated UI as a mock.
21
+
22
+ Use `create_entity` with a dense visual descriptor. The descriptor specifies the exact recurring appearance: character features and wardrobe; location materials and lighting; UI layout, palette, typography, and content boundaries; metaphor geometry and material; or style medium, palette, lighting, and lens. An entity id is the asset id supplied to `create_entity`.
23
+
24
+ ## Teaching arc
25
+
26
+ Compute timecodes from the selected runtime, rounded to 0.5 seconds. Use this arc:
27
+
28
+ | Beat | Runtime share |
29
+ | --- | --- |
30
+ | Problem | 0–15% |
31
+ | Stakes | 15–25% |
32
+ | Shift | 25–40% |
33
+ | Mechanism 1 | 40–55% |
34
+ | Mechanism 2 | 55–68% |
35
+ | Outcome / proof | 68–82% |
36
+ | CTA | 82–93% |
37
+ | Sign-off | 93–100% |
38
+
39
+ For 30 seconds, combine problem and stakes and use one mechanism beat. For 90–120 seconds, use at most three mechanism beats. Use one concept and one literal metaphor. Put the visual aha at the shift-to-mechanism boundary and leave a deliberate half-beat of silence after it. Voice-over must be at most `runtime × 2.2` words.
40
+
41
+ ## Deliverables
42
+
43
+ Produce, in order: three concept directions with a recommendation, the full beat sheet, and an entity roster with id, kind, descriptor summary, and referenced beats. Each direction states its entry problem, metaphor, aha, fit, risk, and referenced entities.
44
+
45
+ For every beat include timecode, teaching job, framing, visual, action, visible entities, verbatim VO, on-screen text of five words or fewer, exact UI/demo input and output or `NONE`, sound, music, transition, and why it teaches. Mechanism beats must show the real UI or a labelled mock. Brand marks wait until the shift. Use verbs in VO and nouns on screen. The sign-off echoes the opening problem.
46
+
47
+ ## Persist the board
48
+
49
+ Create the storyboard with `create_storyboard({ name, brief, style, aspect_ratio })`. Use `board.storyboard_id`. Put the complete brief, chosen direction, and entity roster into `brief` so the project can be reconstructed later. The exact call shapes and return fields — entity id equals the asset id you passed in, the fifteen `edit_storyboard` ops, what `set_board` accepts, what each prompt receives — are in `storyboard-core` § Tool contract; every board skill builds against that one section.
50
+
51
+ Attach roster ids with `edit_storyboard({ storyboard_id, ops: [{ op: "set_board", entity_ids }] })` (`set_entities` is only an alias for `set_board`). Resolve the render models in the same op: `find_model` for `text_to_image` and `image_to_video`, each result's `.ref` on `image_model` / `video_model`, and each result's `prompting_skill` loaded before the shot text is written — the still model reads the shot `action` with the camera framing, angle and lens, the scene lighting and the board style appended.
52
+
53
+ Add one shot per beat with `edit_storyboard` and an `add_shot` op. The dense `action` field names the teaching job, visible entity names in brackets, on-screen text, and UI demonstration. The render attaches a persona or prop entity to a shot only when its name appears in that shot's text (style and location always apply), so every visible entity must be named in `action` or `motion`, or listed on the shot's own `entity_ids`. On-screen text in `action` is a note for the cut: it goes on as a text clip after assembly (`caption-titles`), not into the render prompt.
54
+
55
+ Stop after the planned board unless the user explicitly requests rendering or a cut. Report the directions, chosen board, and entity roster.
56
+
57
+ ## Render (only on request)
58
+
59
+ Stills first with `render_storyboard_stills` — they cost less than clips, and you look at every one with `view_image` asking what is wrong, then `score_image_adherence` against the shot text. A persona or UI mock that drifts is fixed at the entity (descriptor or reference), then every shot using it re-renders; a shot that fails on composition is fixed in its `action`. Clips with `render_storyboard_clips`; a clip wrong where its still was right is one `revise_storyboard_clip`. Then `assemble_storyboard_timeline`.
60
+
61
+ ## When the board becomes motion
62
+
63
+ When a cut is asked for, `timeline-edit-ops` carries the timeline op contract and `motion-graphics` the build loop, which routes to the craft skill for the job: `video-audio-continuity` for whether the beats render as one clip or under a narration track, `caption-titles` for the on-screen text and callouts this beat sheet already specifies, `frame-composition` for where a UI mock sits and whether it survives 9:16, `motion-direction` to hold one motion language across the mechanism beats, and `beat-sync-editing` when the cut has to sit on a music bed. The half-beat of silence after the aha is a hold, not a gap — keep it in the cut.
@@ -0,0 +1,107 @@
1
+ ---
2
+ name: flux-2-klein-prompting
3
+ description: Prompt Black Forest Labs' FLUX.2 [klein] — the subject/environment/style/technical hierarchy it processes in order, guidance-scale and step choices, negative prompts aimed at real failure modes, and the seed-locked one-variable-at-a-time loop its distilled checkpoints make fast enough to run. Which dials exist depends on base versus distilled. Use whenever the model id contains flux-2/klein or flux-2-klein (fal-ai/flux-2/klein/4b, fal-ai/flux-2/klein/9b, their /base, /edit and /lora variants, fal-ai/flux-2/klein/realtime, black-forest-labs/flux-2-klein-4b, black-forest-labs/flux-2-klein-9b) on generate_image, edit_image or a TextToImage node. Not for FLUX.2 pro, flex, max or dev.
4
+ ---
5
+
6
+ # FLUX.2 [klein] → structure first, then iterate fast
7
+
8
+ klein is the small, fast member of the FLUX.2 family, at 4B or 9B. It ships
9
+ two kinds of checkpoint. The distilled ones (every route without `/base`) run
10
+ in 4 to 8 steps, which fal's guide puts under a second. The `/base` ones run
11
+ 28 steps by default and carry the guidance, negative-prompt and acceleration
12
+ dials. The speed is the point of the distilled routes. When a generation takes
13
+ 30 seconds, prompt refinement stalls; here you can change one clause and look
14
+ again, so the working method below is worth more than any single prompt.
15
+
16
+ Reach it with `find_model` for `text_to_image` or `image_to_image`, then
17
+ `generate_image` / `edit_image`. `generate_image` forwards only the prompt, a
18
+ negative prompt, the size and a quality string, and `edit_image` only the
19
+ images, the prompt, a negative prompt, a target size and a strength. Every other
20
+ field below exists only on the route's own node: find it with `search_nodes`,
21
+ read its fields with `get_node_info`, and run it with `run_node`. Each run is a
22
+ paid generation, so confirm the scope with the user before a long loop.
23
+
24
+ ## Prompt hierarchy
25
+
26
+ klein reads a prompt in this order, and content words (nouns) move the output
27
+ more than modifiers do. Write it in the same order:
28
+
29
+ 1. **Subject** — concrete beats abstract. "A woman in her mid-30s with
30
+ shoulder-length auburn hair" over "a person".
31
+ 2. **Environment** — lighting, atmosphere, spatial relationships. "First light
32
+ filtering through morning mist" gives rendering cues that "morning scene"
33
+ does not.
34
+ 3. **Style and mood** — direction that guides without overwhelming:
35
+ "documentary photography", "studio lighting", "cinematic".
36
+ 4. **Technical** — composition ("rule of thirds"), depth of field ("shallow
37
+ focus on the foreground"), palette ("warm earth tones").
38
+
39
+ > Professional headshot of a male architect in his 40s, salt-and-pepper beard,
40
+ > black-rimmed glasses, charcoal blazer. Modern office background with
41
+ > architectural models visible but softly blurred. Natural window light from
42
+ > the left creating gentle shadows. Corporate photography style, sharp focus on
43
+ > the eyes, neutral grey backdrop.
44
+
45
+ ## Parameters
46
+
47
+ | Parameter | Where it exists | What it trades | Where to sit |
48
+ | :--- | :--- | :--- | :--- |
49
+ | `guidance_scale` | fal `/base` routes (default 5); Replicate `-base` calls it `guidance` (default 4) | Prompt adherence against creative freedom | 2–4 for artistic interpretation, 5–8 for product photography and technical illustration |
50
+ | `num_inference_steps` | fal only: 4–50 on `/base` (default 28), 4–8 on distilled (default 4), 1–8 on `realtime` | Quality against time | Low while developing a prompt, high for print-ready output |
51
+ | `acceleration` | fal `/base` routes | Detail against throughput | `regular` for production, `high` for maximum speed |
52
+ | `negative_prompt` | fal `/base` routes | See below | Failure modes only |
53
+ | `seed` | every route | Nothing — it removes noise from the comparison | Pin it while testing prompt variations |
54
+
55
+ On a distilled route the prompt and the seed are the whole instrument, and a
56
+ negative prompt sent through `generate_image` is dropped.
57
+
58
+ Aspect ratio follows the deployment: landscape for presentations and web,
59
+ portrait for social and mobile, square for profiles and balanced compositions.
60
+
61
+ ## Technique
62
+
63
+ - **Emphasis is natural language, not weights.** fal's guide says there is no
64
+ weight syntax. "Prominently featuring", "with particular attention to" and
65
+ "especially detailed" are how you raise an element's priority.
66
+ - **Negative prompts target failure modes, not quality** (`/base` only). For
67
+ portraits: "distorted features, unnatural proportions, extra limbs". For
68
+ landscapes:
69
+ "oversaturated colours, artificial lighting, lens distortion". A generic
70
+ quality list buys nothing.
71
+ - **Text renders well when specified.** Give the copy, the font class, the
72
+ colour, the placement and the capitalisation: "a white coffee mug with the
73
+ text 'GOOD MORNING' in bold sans-serif black letters, centred on the mug".
74
+ Copy that belongs to the design, in other words — a title or a super on a
75
+ still headed for a timeline goes on as a text clip afterwards
76
+ (`caption-titles`), not into the render.
77
+ - **Multi-reference conditioning is the family's edge.** "The subject from the
78
+ first image wearing the jacket from the second image, photographed in the
79
+ environment from the third image."
80
+
81
+ ## The five mistakes
82
+
83
+ - **Overloaded prompts.** fal's guide says that past roughly 100 words the
84
+ model starts dropping clauses. Every word should be doing something.
85
+ - **Vague style references.** "Make it look good" is not a direction. "Shot on
86
+ Hasselblad medium format" or "impressionist painting technique" is.
87
+ - **Missing composition.** Prompts describe the subject thoroughly and never
88
+ say where it sits. Add "centred composition", "rule of thirds with the
89
+ subject on the left vertical", or "bird's eye view".
90
+ - **Conflicting instructions.** "Photorealistic portrait" and "watercolour
91
+ painting style" in one prompt commits to neither.
92
+ - **Neglected lighting.** Lighting is what makes an image dimensional. Always
93
+ name it: golden hour, studio softbox, rim lighting creating a silhouette.
94
+
95
+ ## The loop klein is for
96
+
97
+ Start with subject, environment and style. Generate. Pin the seed. Change one
98
+ element — add lighting detail, refine the subject, move the composition — and
99
+ generate again. One variable at a time is what tells you which clause drove
100
+ which change; a distilled route's turnaround is what makes that affordable.
101
+
102
+ Keep the prompts that worked. A library of formulas per use case, with the
103
+ guidance and step values that suited each, is the output of this loop as much
104
+ as the images are.
105
+
106
+ Adapted from fal's FLUX.2 [klein] prompt guide:
107
+ https://fal.ai/learn/devs/flux-2-klein-prompt-guide
@@ -0,0 +1,291 @@
1
+ ---
2
+ name: frame-composition
3
+ description: Stage the frame on a NodeTool timeline — grids, focal placement, safe areas per aspect ratio, depth layers and parallax, camera moves, and where elements enter and leave. Use when placing titles, lower thirds, shapes or overlays, when a layout must survive 16:9 and 9:16, when adding a push or a parallax move, or when a frame reads flat or cramped. Not for what a clip says or when it cuts.
4
+ ---
5
+
6
+ # Frame Composition → staging on the timeline
7
+
8
+ Where things sit, how deep the frame is, and how the camera moves through it.
9
+ `motion-graphics` is the build loop; `timeline-edit-ops` carries the op
10
+ contract. This decides the coordinates you pass either.
11
+
12
+ ## Coordinate spaces, and mixing them is the usual bug
13
+
14
+ | What | Space | Read as |
15
+ |---|---|---|
16
+ | `shapeStyle.x/y/width/height`, `x2/y2`, `d` | 0..1 of the **frame** | 0.5 is the frame's middle |
17
+ | `set_mask` `x/y/width/height`, `d` | 0..1 of the **layer** | 0.5 is the clip's own middle, not the frame's |
18
+ | `positionX` / `positionY` curves | canvas px | Absolute, and folds as `replace` |
19
+ | `offsetX` / `offsetY` curves | canvas px, added | Composes with everything else |
20
+ | `slide` `distance`, `kenBurns` `driftX/driftY` | fraction of frame width or height | 0.3 travels 30% of the frame |
21
+ | `anchorX` / `anchorY` | 0..1 | The point a scale or a rotation pivots on |
22
+ | `textStyle.fontSizePx` | sequence px | Against `height` from `get_timeline`, not the preview width |
23
+ | `transform.depthPx`, `camera2d.position/depthPx/focalLengthPx` | sequence px | Perspective; clip depth also orders clips within one track |
24
+ | `layout.gap`, `layout.padding` | sequence px | Flex container spacing, measured against its children's rendered boxes |
25
+
26
+ Read `width`, `height` and `fps` off `get_timeline` before you compute anything.
27
+ A layout authored against 1920×1080 and saved onto a 1080×1920 sequence is off
28
+ by more than a crop.
29
+
30
+ ## Text is placed by containers
31
+
32
+ Building with `@nodetool-ai/sandbox-timeline` (see `motion-graphics` for when
33
+ code is the right surface)? **A container decides where its children sit —
34
+ you almost never write `x`/`y` for text.** `s.stack(children, o)` and
35
+ `s.row(children, o)` build a real Yoga flex container and reparent
36
+ `children` onto it as its real children — nest freely, a `row` of `stack`s
37
+ or a `stack` holding a nested `row` both resolve correctly. A text child
38
+ reflows to whatever width Yoga offers it, not a guessed line length.
39
+
40
+ The container's own placement in the frame is `o.at` (`{x, y}`, default the
41
+ frame centre) plus `o.anchor` (default `"center"`): `anchor` names the point
42
+ of the container's own *computed* box that lands at `at` — the name
43
+ `"left"` puts that box's left edge at `at.x`, no measuring a sibling's width
44
+ required. Named anchors: `"top-left"`, `"top"`, `"top-right"`, `"left"`,
45
+ `"center"`, `"right"`, `"bottom-left"`, `"bottom"`, `"bottom-right"`, or pass
46
+ `{x, y}` fractions directly. `o.align` (cross axis, default `"start"`) and
47
+ `o.justify` (main axis, unset) are the Yoga `alignItems`/`justifyContent`.
48
+ A child's own flex sizing is `o.flexItem` on that child's own call (`grow`,
49
+ `width`, `alignSelf`, …); `absolute: true` on a `rect`/`ellipse` (or any
50
+ clip) takes it out of flow and resizes it to fill its flex parent's box
51
+ exactly — how a plate sits behind a card's text with no pixel math.
52
+
53
+ Reach for explicit `x`/`y` only for decoration (a stray mark, a background
54
+ shape) or a deliberate free placement that has nothing to do with reading
55
+ order. Anything a viewer reads — a title, a kicker, a caption, a row of
56
+ stats — goes in a container.
57
+
58
+ **Title block** — kicker, title, sub, stacked with a shared rhythm:
59
+
60
+ ```js
61
+ // fragment
62
+ const kicker = s.kicker("LAUNCHING TODAY");
63
+ const title = s.text("Round-ups", { size: 120, weight: 700 });
64
+ const sub = s.text("on every card", { size: 40 });
65
+ s.stack([kicker, title, sub], { gap: 20 });
66
+ ```
67
+
68
+ **Lockup** — a mark beside its wordmark, one row:
69
+
70
+ ```js
71
+ // fragment
72
+ const mark = s.image(logoAssetId);
73
+ const wordmark = s.text("Northwind", { size: 64, weight: 700 });
74
+ s.row([mark, wordmark], { gap: 16, align: "center" });
75
+ ```
76
+
77
+ **Card** — a padded column over an absolute plate:
78
+
79
+ ```js
80
+ // fragment
81
+ const plate = s.rect(1, 1, "#0c2a21", { r: 24, absolute: true });
82
+ const heading = s.text("Plan Pro", { size: 48, weight: 700 });
83
+ const price = s.text("$12/mo", { size: 32 });
84
+ s.stack([plate, heading, price], { gap: 8, padding: 24 });
85
+ ```
86
+
87
+ **List / grid** — a row that wraps into a grid when it runs out of width:
88
+
89
+ ```js
90
+ // fragment
91
+ const chips = ["Round-ups", "Instant transfers", "No fees"].map((t) => s.pill(t));
92
+ s.row(chips, { gap: 12, wrap: true });
93
+ ```
94
+
95
+ ## Grid
96
+
97
+ Twelve columns for landscape, six for vertical. For a 1920-wide frame with a
98
+ 100px outer margin and a 24px gutter:
99
+
100
+ ```
101
+ content = 1920 − 2×100 = 1720
102
+ column = (1720 − 11×24) / 12 = 121.3px
103
+ ```
104
+
105
+ Space everything in multiples of 8. `fontSizePx` for body copy sits near 2.5–4%
106
+ of frame height; below 2.5% `validate_timeline` reports `text_illegible`.
107
+ Choose the family, weights, and title scale from `motion-direction` § Typography
108
+ before placing text on this grid.
109
+
110
+ ## One focal point
111
+
112
+ Place the subject on a thirds power point, not dead centre, unless the piece
113
+ uses symmetry deliberately. The intersections:
114
+
115
+ | Sequence | Power points (px) |
116
+ |---|---|
117
+ | 1920×1080 | x 640 / 1280, y 360 / 720 |
118
+ | 1080×1920 | x 360 / 720, y 640 / 1280 |
119
+ | 1080×1080 | x 360 / 720, y 360 / 720 |
120
+
121
+ Rank the eye's path by **size, then contrast, then colour, then position**. One
122
+ primary per frame; everything else supports. Leave negative space around it —
123
+ a frame filled edge to edge reads as cheap and gives the motion nowhere to go.
124
+
125
+ ## Depth: planes and track order
126
+
127
+ Split the picture into background, midground and foreground. Track index
128
+ controls order **between** tracks: lowest index draws on top. Within one
129
+ track, clips sort by `transform.depthPx`: farther values draw first and
130
+ nearer, positive values draw later, in front. The same depth controls
131
+ perspective under the sequence's `camera2d`. Moving a clip to another track
132
+ changes its overlap order but not its camera distance.
133
+
134
+ | Plane | Suggested track index | Clip depth | Motion and look |
135
+ |---|---|---|---|
136
+ | Foreground | lowest | Nearer, positive | The move the eye follows; sharp unless focus shifts |
137
+ | Midground | middle | Around zero | The subject and contrast peak |
138
+ | Background | highest | Farther, negative | Small drift and lower contrast |
139
+
140
+ For flat parallax, run three speeds over one window. One `kenBurns` per layer
141
+ with `zoom: 0` and a different drift is a `fullClip` preset, so all three
142
+ cover the same span. Put the three on clips of the same length: the drift is
143
+ spread over the clip, so its speed scales with clip length:
144
+
145
+ ```json
146
+ {"role": "loop", "preset": "kenBurns",
147
+ "params": {"zoom": 0, "driftX": -0.02, "driftY": 0}}
148
+ ```
149
+
150
+ Background −0.02, midground −0.06, foreground −0.12. One layer at one speed is
151
+ not parallax, it is the template moving.
152
+
153
+ For a shared 2.5D move, give the layers distinct `transform.depthPx` values and
154
+ keyframe the sequence's `camera2d`. Its absolute `timeMs` keyframes interpolate
155
+ camera position and depth linearly. `focusDepthPx` and `aperturePx` control depth of
156
+ field. Use one camera move to connect the planes, then inspect a middle frame
157
+ for unwanted scale or blur. Set track indexes for overlap between tracks and
158
+ clip depth for order within a track.
159
+
160
+ For a tilted card wall, parent the cards to a group with the wall's 2D
161
+ `rotation`, `rotationX`, and `perspective`. Give each card its own `depthPx`
162
+ and scroll curve, then use `camera2d` for the shared push and depth blur.
163
+ This is a flat card projection: preview the wall at several frames to check
164
+ that spacing, overlap, and blur read as one assembly.
165
+
166
+ For a move with a shape of its own, write a `custom` curve instead and mind the
167
+ role: an `in` window holds its `t=0` values before it and contributes nothing
168
+ after, an `out` window holds its `t=1` values after it, and a `loop` repeats its
169
+ cycle — so a one-way travel that must stay where it landed is an `out`, and a
170
+ `loop` curve has to return to the value it started on or it jumps every cycle.
171
+
172
+ Parent the assembly to a group when the layers must hold their relationship
173
+ through a move: `add_group`, then animate the group. Children keep their own
174
+ tracks, so grouping never changes what covers what.
175
+ For a transition on the assembled picture, set `transitionIn` on the group. The
176
+ children stay parented on their own tracks while the transition acts once on
177
+ their precomposed surface.
178
+
179
+ Shape geometry is rasterized inside a frame-sized source surface before the
180
+ clip is placed. Keep normalized `shapeStyle` geometry inside that surface,
181
+ then move the clip or parent group with `transform.position` or custom
182
+ `offsetX`/`offsetY` curves for scrolling walls and flying cards. Geometry
183
+ authored outside the source surface clips before placement.
184
+
185
+ ## Camera moves
186
+
187
+ Choose between a sequence camera move and a local clip move. `camera2d`
188
+ keyframes move the view across all depth planes. A layer animation moves one
189
+ clip, and its `anchor` decides where scale or rotation pivots.
190
+
191
+ | Move | How | Timing |
192
+ |---|---|---|
193
+ | Push / pull | `kenBurns` with `zoom` 0.08–0.2 and `direction` in or out | 1500–4000ms, `easeInOut` |
194
+ | Drift | `kenBurns` `driftX` / `driftY`, ±0.02–0.08 | Same window as the zoom |
195
+ | Pan | `custom` curve on `offsetX` across the clip | 800–2000ms, `easeInOut` |
196
+ | Whip | `offsetX` over 150–250ms with a `blur` effect at 12–24px | On a cut, never mid-shot |
197
+ | Follow | `offsetX` and `offsetY` tracking the subject, subject held off-centre and leading | Whatever the action takes |
198
+
199
+ `camera2d` is a document field. `set_clip_params` changes a clip's `transform`
200
+ but refuses `camera2d`, `layout`, `repeater`, `motionBlur`, and other new document
201
+ fields. Read the full document with `get_timeline`, change the relevant fields,
202
+ then write the full document with `set_timeline_document`. Keep its tracks,
203
+ clips, markers, tempo, setup, media tracks, template identity, and other fields
204
+ in the write. `timeline-edit-ops` carries the
205
+ op contract.
206
+
207
+ `kenBurns` is `fullClip`: it ignores `durationMs` and `delayMs` and runs across
208
+ the whole clip. To time a push to something shorter, write it as a `custom`
209
+ `scale` curve instead.
210
+
211
+ One move per beat. A push plus a pan plus a rotate reads as chaos, and the three
212
+ fold together into a direction nobody chose.
213
+
214
+ ## Enter and exit
215
+
216
+ Motion that follows reading direction feels natural; reversing it reads as going
217
+ back. Match `slide`'s `direction` to intent — it names the edge the element
218
+ arrives **from**:
219
+
220
+ - New content: from the right, or from below.
221
+ - Dismissing or undoing: reverse the entrance.
222
+ - Drilling in: `pop`, or a scale curve rather than a travel.
223
+
224
+ Enter and leave through the nearest edge. Keep `distance` at or below 0.35 or
225
+ the travel reads as a slide of the whole template — pair a longer move with a
226
+ scale or opacity change on the same window. Same vocabulary on the cut:
227
+ `set_transition` `direction` on `wipe`, `push` and `slide` also names the edge
228
+ the incoming clip arrives from.
229
+
230
+ ## Safe areas
231
+
232
+ Keep titles, logos, faces and calls to action inside the margin. The numbers are
233
+ fractions of the frame, so convert against `width` and `height`.
234
+
235
+ | Aspect | Top | Bottom | Sides |
236
+ |---|---|---|---|
237
+ | 16:9 | 5% | 5% | 5% |
238
+ | 9:16 | 12–14% | 18–20% | 6% |
239
+ | 1:1 | 7% | 7% | 7% |
240
+ | 4:5 | 8% | 8% | 6% |
241
+
242
+ On 1080×1920 that leaves the usable band roughly y 250 to y 1570. A caption clip
243
+ already sits at `bottomMarginFrac` 0.12 by default, which is inside the phone UI
244
+ zone on some platforms — raise it rather than assuming.
245
+
246
+ ## One layout, several aspects
247
+
248
+ Master in the widest target with the focal point inside the centre band, then
249
+ **restack** for vertical: move the headline above the subject, pull the subject
250
+ up out of the bottom UI zone, and raise `fontSizePx` by about 20%. Cropping a
251
+ 16:9 layout to 9:16 clips whatever sat in the outer columns, which is usually the
252
+ logo and the call to action.
253
+
254
+ Building in code, restacking is usually one option change on the container
255
+ above — flip `s.row` to `s.stack` (or its `align`/`justify`), or move it to a
256
+ new `at`/`anchor` — not a rebuild of every child's `x`/`y`.
257
+
258
+ On the ops path, `layout: {display: "flex", flexDirection: "row" | "column",
259
+ gap}` on a group clip keeps its real children (their `parentId` names the
260
+ group) laid out with ordinary CSS flexbox — `justifyContent`/`alignItems`
261
+ position them, `padding` insets the container. For a shape behind text, give
262
+ the shape `flexItem: {position: "absolute", inset: 0}` inside a padded flex
263
+ column holding the text: the shape's box resizes to the text's padded box,
264
+ including an animated font size, with no manual pixel math. These relations
265
+ avoid redoing pixel math for each text change. A 16:9 document still needs a
266
+ separate placement pass for 9:16, with safe areas checked at that size.
267
+
268
+ ## Check the frame, not the document
269
+
270
+ `preview_timeline_frame` composites the real picture — every track in order,
271
+ transforms and opacity applied, animations mid-flight. Read the layer list it
272
+ returns beside each frame: it names the stack top first with each layer's
273
+ `z_index`, `opacity` and wipe progress, which answers most staging questions
274
+ without looking at a pixel.
275
+
276
+ Preview at the midpoint of every move, not at its ends. What frames catch and a
277
+ validator cannot: a title that slid outside the frame, a scrim covering the face
278
+ it was meant to sit beside, a lower third under the wrong element because two
279
+ track indexes are the wrong way round, a layer that never draws because it is on
280
+ an audio track.
281
+
282
+ ## Before you finish
283
+
284
+ - One focal point, on a power point or deliberately centred.
285
+ - Every element assigned a track for overlap order and a depth plane when the camera moves.
286
+ - One camera move or eased layer move, 800–4000ms.
287
+ - Entrances through the nearest edge, `distance` ≤ 0.35 or paired with a second
288
+ channel.
289
+ - Critical content inside the safe margin for every target aspect, vertical
290
+ restacked rather than cropped.
291
+ - Previewed at the midpoints, and the layer stack read.