@nodetool-ai/agents 0.8.4-a24.3 → 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.
- package/dist/.nodetool-build-stamp +1 -1
- package/dist/_skills/LICENSE-iart-motion-design-skills +21 -0
- package/dist/_skills/README.md +211 -0
- package/dist/_skills/api-agents/SKILL.md +58 -0
- package/dist/_skills/api-apps/SKILL.md +54 -0
- package/dist/_skills/api-assets/SKILL.md +66 -0
- package/dist/_skills/api-collections/SKILL.md +33 -0
- package/dist/_skills/api-games/SKILL.md +81 -0
- package/dist/_skills/api-media/SKILL.md +131 -0
- package/dist/_skills/api-memory/SKILL.md +72 -0
- package/dist/_skills/api-models/SKILL.md +78 -0
- package/dist/_skills/api-scripts/SKILL.md +79 -0
- package/dist/_skills/api-settings/SKILL.md +49 -0
- package/dist/_skills/api-sketches/SKILL.md +61 -0
- package/dist/_skills/api-storyboards/SKILL.md +94 -0
- package/dist/_skills/api-timelines/SKILL.md +151 -0
- package/dist/_skills/api-web/SKILL.md +57 -0
- package/dist/_skills/api-workflows/SKILL.md +123 -0
- package/dist/_skills/beat-sync-editing/SKILL.md +208 -0
- package/dist/_skills/caption-titles/SKILL.md +94 -0
- package/dist/_skills/color-motion/SKILL.md +185 -0
- package/dist/_skills/commercial-beat-sheet/SKILL.md +338 -0
- package/dist/_skills/elevenlabs-audio-prompting/SKILL.md +163 -0
- package/dist/_skills/explainer-storyboard/SKILL.md +63 -0
- package/dist/_skills/flux-2-klein-prompting/SKILL.md +107 -0
- package/dist/_skills/frame-composition/SKILL.md +291 -0
- package/dist/_skills/game-direction/SKILL.md +99 -0
- package/dist/_skills/gpt-image-2-prompting/SKILL.md +161 -0
- package/dist/_skills/hailuo-prompting/SKILL.md +107 -0
- package/dist/_skills/kling-video-prompting/SKILL.md +188 -0
- package/dist/_skills/launch-commercial/SKILL.md +267 -0
- package/dist/_skills/launch-kit/SKILL.md +120 -0
- package/dist/_skills/logo-reveal/SKILL.md +225 -0
- package/dist/_skills/manimgx/SKILL.md +123 -0
- package/dist/_skills/minimax-h3-prompting/SKILL.md +134 -0
- package/dist/_skills/motion-ad/SKILL.md +281 -0
- package/dist/_skills/motion-background/SKILL.md +145 -0
- package/dist/_skills/motion-curves/SKILL.md +302 -0
- package/dist/_skills/motion-direction/SKILL.md +259 -0
- package/dist/_skills/motion-graphics/SKILL.md +217 -0
- package/dist/_skills/motion-principles/SKILL.md +255 -0
- package/dist/_skills/music-video-treatment/SKILL.md +40 -0
- package/dist/_skills/nano-banana-pro-prompting/SKILL.md +133 -0
- package/dist/_skills/native-game/SKILL.md +310 -0
- package/dist/_skills/native-game-reference/SKILL.md +879 -0
- package/dist/_skills/nodetool-3d-scene/SKILL.md +110 -0
- package/dist/_skills/nodetool-api-reference/SKILL.md +338 -0
- package/dist/_skills/nodetool-app-builder/SKILL.md +291 -0
- package/dist/_skills/nodetool-browser-agent/SKILL.md +119 -0
- package/dist/_skills/nodetool-chat-cli/SKILL.md +184 -0
- package/dist/_skills/nodetool-custom-node-developer/SKILL.md +294 -0
- package/dist/_skills/nodetool-deployment/SKILL.md +195 -0
- package/dist/_skills/nodetool-js-scripting/SKILL.md +223 -0
- package/dist/_skills/nodetool-model-provider-config/SKILL.md +348 -0
- package/dist/_skills/nodetool-rag-indexing/SKILL.md +153 -0
- package/dist/_skills/nodetool-sketch/SKILL.md +138 -0
- package/dist/_skills/nodetool-skill-author/SKILL.md +125 -0
- package/dist/_skills/nodetool-troubleshooter/SKILL.md +370 -0
- package/dist/_skills/nodetool-video-post/SKILL.md +149 -0
- package/dist/_skills/nodetool-workflow-builder/SKILL.md +295 -0
- package/dist/_skills/product-commercial/SKILL.md +132 -0
- package/dist/_skills/qwen-image-prompting/SKILL.md +122 -0
- package/dist/_skills/script-video/SKILL.md +106 -0
- package/dist/_skills/seedance-2-prompting/SKILL.md +194 -0
- package/dist/_skills/seedream-prompting/SKILL.md +117 -0
- package/dist/_skills/short-film/SKILL.md +123 -0
- package/dist/_skills/stable-audio-prompting/SKILL.md +130 -0
- package/dist/_skills/storyboard-core/SKILL.md +716 -0
- package/dist/_skills/timeline-edit-ops/SKILL.md +736 -0
- package/dist/_skills/trailer-template/SKILL.md +291 -0
- package/dist/_skills/ugc-video/SKILL.md +186 -0
- package/dist/_skills/veo-3-prompting/SKILL.md +140 -0
- package/dist/_skills/video-audio-continuity/SKILL.md +90 -0
- package/dist/_skills/video-clone/SKILL.md +96 -0
- package/dist/_skills/video-workflow/SKILL.md +119 -0
- package/dist/_skills/wan-2-6-prompting/SKILL.md +107 -0
- package/dist/app-build/bridge.d.ts.map +1 -1
- package/dist/app-build/bridge.js +44 -17
- package/dist/app-build/bridge.js.map +1 -1
- package/dist/capabilities/apps.d.ts.map +1 -1
- package/dist/capabilities/apps.js +55 -13
- package/dist/capabilities/apps.js.map +1 -1
- package/dist/capabilities/apps.specs.d.ts.map +1 -1
- package/dist/capabilities/apps.specs.js +5 -3
- package/dist/capabilities/apps.specs.js.map +1 -1
- package/dist/capabilities/game-asset-browser.d.ts.map +1 -1
- package/dist/capabilities/game-asset-browser.js +6 -1
- package/dist/capabilities/game-asset-browser.js.map +1 -1
- package/dist/capabilities/game.d.ts +1 -1
- package/dist/capabilities/game.d.ts.map +1 -1
- package/dist/capabilities/game.js +71 -56
- package/dist/capabilities/game.js.map +1 -1
- package/dist/capabilities/game.specs.js +1 -1
- package/dist/capabilities/game.specs.js.map +1 -1
- package/dist/capabilities/game3d.d.ts.map +1 -1
- package/dist/capabilities/game3d.js +14 -19
- package/dist/capabilities/game3d.js.map +1 -1
- package/dist/capabilities/gameAssertions.d.ts +52 -0
- package/dist/capabilities/gameAssertions.d.ts.map +1 -0
- package/dist/capabilities/gameAssertions.js +32 -0
- package/dist/capabilities/gameAssertions.js.map +1 -0
- package/dist/capabilities/models.d.ts.map +1 -1
- package/dist/capabilities/models.js +9 -0
- package/dist/capabilities/models.js.map +1 -1
- package/dist/capabilities/storyboards.d.ts.map +1 -1
- package/dist/capabilities/storyboards.js +36 -11
- package/dist/capabilities/storyboards.js.map +1 -1
- package/dist/capabilities/storyboards.specs.d.ts.map +1 -1
- package/dist/capabilities/storyboards.specs.js +11 -1
- package/dist/capabilities/storyboards.specs.js.map +1 -1
- package/dist/capabilities/workflows.d.ts.map +1 -1
- package/dist/capabilities/workflows.js +1 -0
- package/dist/capabilities/workflows.js.map +1 -1
- package/dist/capabilities/workflows.specs.d.ts.map +1 -1
- package/dist/capabilities/workflows.specs.js +4 -3
- package/dist/capabilities/workflows.specs.js.map +1 -1
- package/dist/evals/surfaces/game.d.ts.map +1 -1
- package/dist/evals/surfaces/game.js +29 -1
- package/dist/evals/surfaces/game.js.map +1 -1
- package/dist/game-authoring.d.ts +120 -0
- package/dist/game-authoring.d.ts.map +1 -1
- package/dist/game-build-integrity.d.ts +12 -0
- package/dist/game-build-integrity.d.ts.map +1 -0
- package/dist/game-build-integrity.js +78 -0
- package/dist/game-build-integrity.js.map +1 -0
- package/dist/game-examples.d.ts +44 -3
- package/dist/game-examples.d.ts.map +1 -1
- package/dist/game-examples.js +60 -10
- package/dist/game-examples.js.map +1 -1
- package/dist/system-skills.d.ts +1 -1
- package/dist/system-skills.js +1 -1
- package/dist/tools/builtin-tools.d.ts.map +1 -1
- package/dist/tools/builtin-tools.js +2 -0
- package/dist/tools/builtin-tools.js.map +1 -1
- package/package.json +19 -19
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nodetool-workflow-builder
|
|
3
|
+
description: "Create or edit NodeTool workflow graphs, connections, and properties using UI, headless tools, or requested workflow files."
|
|
4
|
+
featured: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Build NodeTool workflows
|
|
8
|
+
|
|
9
|
+
Create or edit a workflow that produces the requested outputs from the specified
|
|
10
|
+
inputs. Preserve existing nodes and connections outside the requested change.
|
|
11
|
+
|
|
12
|
+
## A graph is one surface among several
|
|
13
|
+
|
|
14
|
+
NodeTool holds several document kinds, and most of them are not graphs. Build a
|
|
15
|
+
graph when the user asked for one, when the job has to re-run on new inputs, or
|
|
16
|
+
when the result must be callable over the API. Otherwise route the request.
|
|
17
|
+
|
|
18
|
+
| The deliverable | Skill |
|
|
19
|
+
|---|---|
|
|
20
|
+
| A finished video, still set or campaign | `storyboard-core`, which picks the job skill |
|
|
21
|
+
| A screen someone clicks | `nodetool-app-builder` |
|
|
22
|
+
| A repair on footage already cut: cutout, upscale, lip sync, generated sound | `nodetool-video-post` |
|
|
23
|
+
| A cut, titles, transitions or animation on a timeline | the `motion-graphics` system skill, via `load_skill` |
|
|
24
|
+
| Logic in JavaScript rather than nodes | `nodetool-js-scripting` |
|
|
25
|
+
| A layered image, mask or overlay | `nodetool-sketch` |
|
|
26
|
+
| A 3D model or scene | `nodetool-3d-scene` |
|
|
27
|
+
| A playable 2D or 3D game | `native-game` |
|
|
28
|
+
| A math or explainer animation in Python | `manimgx` |
|
|
29
|
+
| Document indexing, vector search, RAG | `nodetool-rag-indexing` |
|
|
30
|
+
| Navigating, reading or filling in web pages | `nodetool-browser-agent` |
|
|
31
|
+
| A reusable video template for batches | `video-workflow` |
|
|
32
|
+
| A new node type | `nodetool-custom-node-developer` |
|
|
33
|
+
|
|
34
|
+
A workflow can still be the right answer alongside one of these: a mini app runs
|
|
35
|
+
workflows, and a timeline clip can be produced by one.
|
|
36
|
+
|
|
37
|
+
Use the authoring surface the user requested: the graph tools for a saved or
|
|
38
|
+
open workflow, and JSON or the TypeScript DSL when a workflow file is
|
|
39
|
+
requested. Do not claim a missing tool is callable. Use the live schemas and
|
|
40
|
+
registry as the source of identifiers.
|
|
41
|
+
|
|
42
|
+
## Build and verify
|
|
43
|
+
|
|
44
|
+
1. Inspect the existing graph for edits (`ui_get_graph` or `get_workflow`).
|
|
45
|
+
Identify required inputs, outputs, and behavior from the request.
|
|
46
|
+
2. Find node types. On the canvas, `ui_search_nodes` with
|
|
47
|
+
`include_properties: true` and `include_outputs: true` returns property and
|
|
48
|
+
output names. Headlessly, `search_nodes {query: [...]}` finds the type and
|
|
49
|
+
`get_node_info {node_type}` returns its inputs, outputs, types and defaults.
|
|
50
|
+
Pick models with `find_model` (headless) or `ui_search_models` (canvas). Do
|
|
51
|
+
not invent node types, properties, handles, or model identifiers.
|
|
52
|
+
3. Add or update nodes, set required properties, and connect compatible handles.
|
|
53
|
+
Keep existing layout and identifiers when editing.
|
|
54
|
+
4. Validate with `ui_get_graph` (its `validation` field) or `validate_workflow`.
|
|
55
|
+
Fix errors and required-input warnings. Read back the saved graph before
|
|
56
|
+
claiming it was created or changed. Report any remaining limitation.
|
|
57
|
+
5. Execute only when the request includes a run. A run of generation nodes
|
|
58
|
+
spends provider money, so confirm scope with the user first. Report the
|
|
59
|
+
workflow id, inputs, validation result, and actual run outcome.
|
|
60
|
+
|
|
61
|
+
If a node is unavailable, broaden the search and inspect supported alternatives.
|
|
62
|
+
Proceed with an equivalent composition when it preserves the requested behavior.
|
|
63
|
+
Otherwise explain the missing capability and ask only for the decision needed to
|
|
64
|
+
choose an alternative. Continue independent work on the rest of the graph.
|
|
65
|
+
|
|
66
|
+
## Graph tools
|
|
67
|
+
|
|
68
|
+
These edit one workflow. With the workflow open in the editor they act on the
|
|
69
|
+
live canvas. With no editor open, the eight graph tools (`ui_get_graph`,
|
|
70
|
+
`ui_add_node`, `ui_connect_nodes`, `ui_update_node_data`, `ui_delete_node`,
|
|
71
|
+
`ui_delete_edge`, `ui_move_node`, `ui_set_node_title`) read and write the saved
|
|
72
|
+
workflow named by `workflow_id`. Each mutation also accepts
|
|
73
|
+
`based_on_revision` (from `ui_get_graph`), which refuses the edit if the graph
|
|
74
|
+
changed.
|
|
75
|
+
|
|
76
|
+
| Tool | Purpose | Key params |
|
|
77
|
+
|------|---------|-----------|
|
|
78
|
+
| `ui_search_nodes` | Find node types | `query`, `input_type`, `output_type`, `include_properties`, `include_outputs`, `limit` |
|
|
79
|
+
| `ui_search_models` | Models for a generic AI node | `kind` (`text_to_image`, `image_to_image`, `text_to_video`, `image_to_video`, `reference_to_video`, `text_to_speech`, `text_to_music`, `audio_to_audio`, `speech_to_text`, `text_generation`, `embedding`), `limit` |
|
|
80
|
+
| `ui_add_node` | Add one node | `id`, `type`, `position {x, y}`, `properties` |
|
|
81
|
+
| `ui_connect_nodes` | Connect two nodes | `source_node_id`, `source_handle`, `target_node_id`, `target_handle` |
|
|
82
|
+
| `ui_update_node_data` | Merge into a node's `data` | `node_id`, `data` (e.g. `{properties: {…}}`, `{dynamic_outputs: {…}}`, `{title}`) |
|
|
83
|
+
| `ui_get_graph` | Read graph, revision and validation | `workflow_id` |
|
|
84
|
+
| `ui_delete_node` / `ui_delete_edge` | Remove | `node_id` / `edge_id` |
|
|
85
|
+
| `ui_move_node` | Reposition | `node_id`, `position {x, y}` |
|
|
86
|
+
| `ui_set_node_title` | Rename a node | `node_id`, `title` |
|
|
87
|
+
| `ui_open_workflow` | Open a workflow tab | `workflow_id` |
|
|
88
|
+
| `ui_run_workflow` | Execute | `workflow_id`, `params` |
|
|
89
|
+
|
|
90
|
+
`ui_add_node` takes `properties` only. Anything else on the node's `data`, such
|
|
91
|
+
as `dynamic_outputs`, is set afterwards with `ui_update_node_data`.
|
|
92
|
+
|
|
93
|
+
## Workflow tools
|
|
94
|
+
|
|
95
|
+
These need no editor.
|
|
96
|
+
|
|
97
|
+
| Tool | Purpose |
|
|
98
|
+
|---|---|
|
|
99
|
+
| `list_workflows`, `get_workflow` | Find and read a workflow |
|
|
100
|
+
| `search_nodes`, `get_node_info`, `list_nodes` | Node discovery. `search_nodes` hides provider nodes (`openai.*`, `kie.*`, …) unless `include_provider_nodes: true`, which is for a provider the user named |
|
|
101
|
+
| `find_model` | A `{provider, model}` ref for a generic AI node's `model` property |
|
|
102
|
+
| `create_workflow {name, graph}` | Save a new graph. Nodes are `{id, type, properties}`. Edges are `{source, sourceHandle, target, targetHandle}` |
|
|
103
|
+
| `validate_workflow {workflow_id \| graph}` | Static check: unknown types, missing properties, unselected models, bad edges |
|
|
104
|
+
| `run_workflow`, `start_background_job`, `debug_workflow` | Execute, execute without waiting, or execute with a full debug report |
|
|
105
|
+
| `run_node {node_type, inputs}` | Run one node to probe what it does (chat only) |
|
|
106
|
+
|
|
107
|
+
For a brief rather than a graph, the planner builds one: `plan_workflow
|
|
108
|
+
{workflow_id}` stores a plan whose steps map to registry node types,
|
|
109
|
+
`update_workflow_plan_step` fixes a step the registry lacks, and
|
|
110
|
+
`build_workflow_from_plan {workflow_id}` places and validates the nodes. On the
|
|
111
|
+
canvas the same flow is `ui_workflow_plan`, `ui_workflow_update_plan_step` and
|
|
112
|
+
`ui_workflow_build_from_plan`.
|
|
113
|
+
|
|
114
|
+
## Node catalog
|
|
115
|
+
|
|
116
|
+
Catalog entries are search leads. Confirm each type with `get_node_info` or
|
|
117
|
+
`ui_search_nodes` before using it. From the CLI, inspect installed types with
|
|
118
|
+
`nodetool node list` and `nodetool node info <type>`.
|
|
119
|
+
|
|
120
|
+
`nodetool.output.Output` is supplied by the audio pack. If it is needed but
|
|
121
|
+
not installed, run `nodetool packs add audio --yes`. CLI workflow runs also
|
|
122
|
+
return terminal transform outputs: a core-only deterministic text graph can
|
|
123
|
+
end at `nodetool.text.Template` without a dedicated sink. For example,
|
|
124
|
+
`StringInput` → `Template` returns the template's values under `outputs.Template`.
|
|
125
|
+
|
|
126
|
+
| Namespace | Common nodes |
|
|
127
|
+
|---|---|
|
|
128
|
+
| `nodetool.input` | `StringInput`, `IntegerInput`, `FloatInput`, `BooleanInput`, `ImageInput`, `AudioInput`, `VideoInput`, `DocumentInput`, `MessageInput`, `LanguageModelInput` |
|
|
129
|
+
| `nodetool.output` | `Output`. `nodetool.workflows.base_node.Preview` shows an intermediate value |
|
|
130
|
+
| `nodetool.constant` | `String`, `Integer`, `Float`, `Bool`, `List`, `Dict`, `Image`, `Audio`, `Video`, `JSON` |
|
|
131
|
+
| `nodetool.agents` | `Agent`, `Summarizer`, `Extractor`, `Classifier`, `Decision`, `EnhancePrompt`, `CreateThread` |
|
|
132
|
+
| `nodetool.generators` | `ListGenerator`, `DataGenerator`, `StructuredOutputGenerator`, `ChartGenerator`, `SVGGenerator` |
|
|
133
|
+
| `nodetool.text` | `Template`, `Concat`, `Prompt`, `FilterString`, `FilterRegexString`, `Embedding`, `AutomaticSpeechRecognition`, `SaveText` |
|
|
134
|
+
| `nodetool.code` | `Code`: a JavaScript body. See `nodetool-js-scripting` |
|
|
135
|
+
| `nodetool.control` | `If`, `Switch`, `ForEach`, `Collect`, `Loop`, `Chunk`, `Take`, `Zip`, `RepeatCount`, `RepeatValue`, `TryCatch` |
|
|
136
|
+
| `nodetool.data` | `ForEachRow`, `LoadCSVAssets` |
|
|
137
|
+
| `nodetool.document` | `LoadDocumentFile`, `SaveDocumentFile`, `ListDocuments` |
|
|
138
|
+
| `nodetool.image` | `TextToImage`, `ImageToImage`, `LoadImageFile`, `SaveImage`, `Resize`, `Crop`, `RotateAndFlip`, `Compositor`, `Upscale`, `RemoveBackground` |
|
|
139
|
+
| `nodetool.audio` | `TextToSpeech`, `TextToMusic`, `LoadAudioFile`, `SaveAudio`, `AudioMixer`, `Concat`, `Trim`, `Normalize` |
|
|
140
|
+
| `nodetool.video` | `TextToVideo`, `ImageToVideo`, `ReferenceToVideo`, `LoadVideoFile`, `SaveVideo`, `Concat`, `Trim`, `ExtractFrame`, `ExtractAudio`, `AddAudio`, `GetVideoInfo` |
|
|
141
|
+
| `vector` | `Collection`, `IndexTextChunk`, `QueryText`, `HybridSearch`. See `nodetool-rag-indexing` |
|
|
142
|
+
| `lib.*` | `lib.pdf` (text, tables, page images), `lib.image.*` (filters, color, draw), `lib.audio.*` (effects), `lib.svg`, `lib.charts.ChartRenderer`, `lib.browser.Screenshot`, `lib.sqlite.GetDatabasePath` |
|
|
143
|
+
|
|
144
|
+
`lib.http`, `lib.os`, `lib.datetime`, `lib.json`, `lib.math`, `lib.uuid`,
|
|
145
|
+
`nodetool.boolean`, `nodetool.dictionary`, `nodetool.list`, `nodetool.numbers`,
|
|
146
|
+
the old `nodetool.text` helpers such as `Slugify` and `Chunk`, and all `skills.*`
|
|
147
|
+
nodes have been removed. Use the Code node (`nodetool.code.Code`) and its
|
|
148
|
+
snippet library instead. Its body is plain JavaScript with `fetch`,
|
|
149
|
+
`workspace.*` and the other globals `nodetool-js-scripting` lists. Libraries
|
|
150
|
+
such as `@nodetool-ai/sandbox-dates` are imported sandbox packages, not globals.
|
|
151
|
+
|
|
152
|
+
### Generation nodes
|
|
153
|
+
|
|
154
|
+
Use the generic nodes with a `model` property: `nodetool.image.TextToImage`,
|
|
155
|
+
`ImageToImage`, `nodetool.video.TextToVideo`, `ImageToVideo`,
|
|
156
|
+
`ReferenceToVideo`, `nodetool.audio.TextToSpeech`, `TextToMusic`. Set `model`
|
|
157
|
+
from `find_model` or `ui_search_models`. A provider's own node (`kie.video.*`,
|
|
158
|
+
`openai.*`, `gemini.*`, …) exposes that model's extra settings. Search for one
|
|
159
|
+
only when the user named the provider or needs a setting the generic node does
|
|
160
|
+
not carry, with `include_provider_nodes: true` on `search_nodes`.
|
|
161
|
+
|
|
162
|
+
### Data types
|
|
163
|
+
|
|
164
|
+
- **Primitives**: `str`, `int`, `float`, `bool`, `list`, `dict`, `any`
|
|
165
|
+
- **Assets**: `{type: "image|audio|video|document", uri: "..."}`
|
|
166
|
+
- **Models**: `language_model`, `image_model`, `video_model`, `embedding_model`, `tts_model`
|
|
167
|
+
|
|
168
|
+
Edges enforce type compatibility. Use `any` for flexible connections. Search
|
|
169
|
+
with `input_type` / `output_type` (`"str"`, `"image"`, `"list"`, …) to find a
|
|
170
|
+
node that fits a handle.
|
|
171
|
+
|
|
172
|
+
## Workflow patterns
|
|
173
|
+
|
|
174
|
+
- **Pipeline.** Input → transforms → Output. For example `ImageInput` →
|
|
175
|
+
`lib.image.enhance.AutoContrast` → `SaveImage` → `Output`.
|
|
176
|
+
- **Agent generation.** Input → `Agent` or `Summarizer` → post-process →
|
|
177
|
+
Output. `ListGenerator` streams one item per line for fan-out.
|
|
178
|
+
- **Previews.** Put `Preview` nodes after intermediate stages of a multi-stage
|
|
179
|
+
generation so progress is visible.
|
|
180
|
+
- **RAG.** Index: Code node (`workspace.list`) → `LoadDocumentFile` → Code node
|
|
181
|
+
("Chunk Text" snippet) → `vector.IndexTextChunk`. Query: `StringInput` →
|
|
182
|
+
`vector.HybridSearch` → `Template` → `Agent` → `Output`. See
|
|
183
|
+
`nodetool-rag-indexing`.
|
|
184
|
+
- **Realtime.** `RealtimeAudioInput` → `openai.agents.RealtimeAgent` or
|
|
185
|
+
`openai.agents.LiveAgent` → `Preview`. `LiveAgent` runs full-duplex speech;
|
|
186
|
+
feed it 24 kHz PCM16 microphone chunks.
|
|
187
|
+
- **Multi-modal.** Chain modalities: `AutomaticSpeechRecognition` → `Agent` →
|
|
188
|
+
`TextToImage`, or `ExtractAudio` → `AutomaticSpeechRecognition` →
|
|
189
|
+
`Summarizer`.
|
|
190
|
+
- **Generated media.** `StringInput` (prompt) → `TextToVideo` → `Output`, or
|
|
191
|
+
`ImageInput` + `StringInput` → `ImageToVideo` → `Output`. For lip sync,
|
|
192
|
+
upscaling or avatar work, search `"lip sync"`, `"upscale"` or `"avatar"`.
|
|
193
|
+
|
|
194
|
+
### Agent outputs and tools
|
|
195
|
+
|
|
196
|
+
- `dynamic_outputs` on an `Agent` (`{"title": {"type": "str"}}`) declares
|
|
197
|
+
structured result fields. The model fills them through a submit tool, and each
|
|
198
|
+
becomes an output handle.
|
|
199
|
+
- To let an Agent call another node as a tool, connect it with a control edge
|
|
200
|
+
(`edge_type: "control"`, both handles `__control__`). The Agent's regular
|
|
201
|
+
outputs (`text`, `chunk`) still route to `Preview` or `Output`.
|
|
202
|
+
|
|
203
|
+
### Streaming and control flow
|
|
204
|
+
|
|
205
|
+
- Everything is a stream. A single value is a one-item stream.
|
|
206
|
+
- `nodetool.control.Collect` gathers a stream into a list.
|
|
207
|
+
`nodetool.control.ForEach` emits each item of a list.
|
|
208
|
+
- `nodetool.control.Loop` repeats part of the graph: wire `initial` into the
|
|
209
|
+
body, the body's result back into `next`, and a bool into `condition` (loop
|
|
210
|
+
again while true). `max_iterations` bounds it and `done` carries the final
|
|
211
|
+
value. It is the only way to close a cycle. The DSL cannot express the back
|
|
212
|
+
edge, so build loops with the graph tools or workflow JSON.
|
|
213
|
+
- `nodetool.agents.Decision` lets a model make the call: `prompt` is a yes/no
|
|
214
|
+
question, `value` is what it judges (images are shown to the model),
|
|
215
|
+
`decision` is the bool and `if_true`/`if_false` route `value` like `If`. Wire
|
|
216
|
+
`decision` into `Loop.condition` to loop until a model is satisfied, and phrase
|
|
217
|
+
the question so yes means "loop again".
|
|
218
|
+
|
|
219
|
+
## Debugging and validation
|
|
220
|
+
|
|
221
|
+
`ui_get_graph` returns a `validation` field:
|
|
222
|
+
|
|
223
|
+
- `errors`: blocking issues, such as invalid node types or a Code body that does
|
|
224
|
+
not parse.
|
|
225
|
+
- `warnings`: disconnected required inputs and empty required properties.
|
|
226
|
+
- `suggestions`: orphaned nodes.
|
|
227
|
+
|
|
228
|
+
`validate_workflow` is the headless equivalent and also catches unselected
|
|
229
|
+
models and model ids a provider does not offer. Fix blocking errors and the
|
|
230
|
+
warnings that prevent the requested behavior. Explain any remaining warning
|
|
231
|
+
without expanding the task.
|
|
232
|
+
|
|
233
|
+
- **"Required property 'X' is not set"**: set it with `ui_update_node_data` or in
|
|
234
|
+
the graph's `properties`. Common ones are `model` and `prompt`.
|
|
235
|
+
- **"Required input 'X' not connected"**: add an edge or set a value.
|
|
236
|
+
- **Wrong handle name**: re-read the type with `get_node_info` or
|
|
237
|
+
`ui_search_nodes {include_outputs: true}`.
|
|
238
|
+
- **Type mismatch**: compare the source output type with the target input type.
|
|
239
|
+
- **Node not found**: broaden the query or search by namespace prefix
|
|
240
|
+
(`"nodetool.text"`).
|
|
241
|
+
|
|
242
|
+
Do not retry a failing call unchanged. Agent and generator nodes need `model`,
|
|
243
|
+
generation nodes need `prompt`, and `ForEach` needs a list input. Set them or ask
|
|
244
|
+
the user which value to use.
|
|
245
|
+
|
|
246
|
+
## Running workflows from a shell
|
|
247
|
+
|
|
248
|
+
This section is for a person or agent with a shell. The in-product agent uses
|
|
249
|
+
`run_workflow` instead.
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
nodetool workflows run ./workflow.json --params '{"input": "hello"}' --json
|
|
253
|
+
nodetool workflows run ./workflow.ts --json # a DSL file, built then run
|
|
254
|
+
nodetool workflows run <workflow_id>
|
|
255
|
+
nodetool workflows list
|
|
256
|
+
nodetool workflows get <id>
|
|
257
|
+
nodetool jobs list
|
|
258
|
+
nodetool serve --port 7777
|
|
259
|
+
|
|
260
|
+
# From a NodeTool checkout
|
|
261
|
+
npm run workflow -- ./workflow.json --input text='hello' --show-messages
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## TypeScript DSL
|
|
265
|
+
|
|
266
|
+
Write workflows as TypeScript with `@nodetool-ai/dsl`. Namespaces mirror node
|
|
267
|
+
namespaces: `nodetool.text` is `text`, `nodetool.control` is `control`,
|
|
268
|
+
`lib.pdf` is `libPdf`, `vector` is `vector`.
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
import { workflow, input, text, agents, output } from "@nodetool-ai/dsl";
|
|
272
|
+
|
|
273
|
+
const topic = input.stringInput({ name: "topic", value: "tides" });
|
|
274
|
+
const brief = text.template({
|
|
275
|
+
string: "Explain {{ topic }} to a ten-year-old.",
|
|
276
|
+
topic: topic.output()
|
|
277
|
+
});
|
|
278
|
+
const answer = agents.summarizer({ text: brief.output() });
|
|
279
|
+
const result = output.output({ name: "answer", value: answer.output("text") });
|
|
280
|
+
|
|
281
|
+
const wf = workflow(result);
|
|
282
|
+
console.log(JSON.stringify(wf));
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
- **`node.output()`** is a function. It returns the default output handle and
|
|
286
|
+
only works on a node with one. Name the slot on a multi-output node:
|
|
287
|
+
`answer.output("text")`, `branch.output("if_true")`.
|
|
288
|
+
- **Connectable**: every input accepts a literal value or an output handle.
|
|
289
|
+
- **`workflow(...terminals)`** traces from the terminal nodes and returns
|
|
290
|
+
serializable `{nodes, edges}`. A node shared by two branches appears once.
|
|
291
|
+
- **`run(wf, opts?)`** executes in-process. **`runGraph(...terminals)`** is
|
|
292
|
+
`run(workflow(...terminals))`.
|
|
293
|
+
- Dynamic inputs are extra keys, as `topic` on `text.template` above.
|
|
294
|
+
- There is no `libMath`, `libHttp` or `list` namespace. Use `code.code` for
|
|
295
|
+
arithmetic, JSON, list and HTTP logic.
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: product-commercial
|
|
3
|
+
description: "Direct the look of a polished product film or brand commercial in NodeTool. For the ad's beat structure pair with commercial-beat-sheet, for a finished spot from a product page use launch-commercial, and for phone-shot creator ads use ugc-video."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
**Load `/storyboard-core` first.** It carries the loop, the tool contract,
|
|
7
|
+
the entity rules and the gating this skill assumes. Everything below is what is
|
|
8
|
+
different about a camera-grade product film. This skill sets the look; an ad's
|
|
9
|
+
hook, beats and timecodes come from `/commercial-beat-sheet`, which composes with
|
|
10
|
+
it on the same board.
|
|
11
|
+
|
|
12
|
+
## What makes this job type its own
|
|
13
|
+
|
|
14
|
+
There is no face to hold steady, so the thing that drifts is the **pack**: label
|
|
15
|
+
geometry, cap, proportions, colour. That is what the product entity is for, and it is
|
|
16
|
+
why the reference image matters more here than the descriptor.
|
|
17
|
+
|
|
18
|
+
The other difference is that a product film's shots are mostly about **light**, and
|
|
19
|
+
light lives in the board style, not in the shot.
|
|
20
|
+
|
|
21
|
+
## Casting the pack
|
|
22
|
+
|
|
23
|
+
The user's pack shot is the entity. Save the attached image as an asset, then
|
|
24
|
+
`create_entity {asset_id, kind: "prop", name, descriptor}`. Write the descriptor as
|
|
25
|
+
geometry and finish — `squat 200ml amber glass cylinder, brushed gold screw cap,
|
|
26
|
+
single centred cream label, serif wordmark` — not as marketing copy.
|
|
27
|
+
|
|
28
|
+
Never invent a logo, a tagline or a label layout. If the label has to be readable, say
|
|
29
|
+
so in the shot's `action` and give that shot a macro framing. Inspect the still
|
|
30
|
+
before rendering its clip. If the label remains unreadable, retry only within the
|
|
31
|
+
user's retry and spending limits. With no retries authorized, report the defect
|
|
32
|
+
and follow the remaining requested stages without claiming the label is readable.
|
|
33
|
+
|
|
34
|
+
Given several angles (front, three-quarter, back, top), tag the best single hero angle
|
|
35
|
+
as the entity and keep the rest as plain assets. An entity is one image asset, so it
|
|
36
|
+
carries one reference into the prompt.
|
|
37
|
+
|
|
38
|
+
## The look goes in the board style, once
|
|
39
|
+
|
|
40
|
+
| Register | `style` |
|
|
41
|
+
|---|---|
|
|
42
|
+
| Luxury studio | `black cyclorama, one warm key, gold rim, volumetric mist, 85-100mm, 24fps, no grain` |
|
|
43
|
+
| Clean e-comm | `white sweep, soft top light, even fill, 50mm, no shadow detail loss` |
|
|
44
|
+
| Location / lifestyle | `90s print / 35mm commercial, hard noon sun, mild bloom, no other brand marks` |
|
|
45
|
+
| Dark technical | `graphite surface, hard side key, specular edges, controlled falloff` |
|
|
46
|
+
|
|
47
|
+
Add `no on-screen type` to the style. Video models letter badly, and titles belong on
|
|
48
|
+
the timeline as text clips (`edit_timeline` → `add_text_clip`), where they stay
|
|
49
|
+
editable.
|
|
50
|
+
|
|
51
|
+
## Shot pattern
|
|
52
|
+
|
|
53
|
+
Use the requested shot count. When the brief leaves it open, five to seven shots
|
|
54
|
+
are a starting pattern. Give each cut a distinct purpose. A product film reads as expensive
|
|
55
|
+
when the **light** moves and the pack does not — write that literally:
|
|
56
|
+
`the light streak crosses the glass, the bottle stays still`.
|
|
57
|
+
|
|
58
|
+
- Put the move in `motion` with a distance or a degree: `slow 8cm push-in`,
|
|
59
|
+
`low 30-degree orbit`, `rack focus from cap to liquid`.
|
|
60
|
+
- Give the last shot a **hold**: `last 1.2s dead hold` — models drift on the tail, and
|
|
61
|
+
a hold is what makes an end card usable.
|
|
62
|
+
- Count the physical events: `two condensation beads run`, `one ripple, then still`.
|
|
63
|
+
- On a location spot with talent, cast the person as a character entity per
|
|
64
|
+
`/ugc-video`'s casting pass, but keep the pack's shots free of them with an
|
|
65
|
+
explicit `entity_ids`.
|
|
66
|
+
|
|
67
|
+
## Where a still is the wrong unit
|
|
68
|
+
|
|
69
|
+
Macro glass, mist and specular highlights are where `keyframe` mode pays — the still
|
|
70
|
+
is cheap and you can judge the light before spending on motion. Keep the default.
|
|
71
|
+
|
|
72
|
+
Switch a shot to `render_mode: "direct"` only for heavy motion the first frame would
|
|
73
|
+
stiffen: a fast orbit, liquid pouring, an explosive reveal. The direct clip prompt
|
|
74
|
+
carries the camera fields, the scene lighting and the board style itself.
|
|
75
|
+
|
|
76
|
+
## Briefs
|
|
77
|
+
|
|
78
|
+
Adapt these examples to the user's brief. Example deliverables, style choices,
|
|
79
|
+
and approval checkpoints apply only when the user adopts them.
|
|
80
|
+
|
|
81
|
+
**Briefs** below has two: a 10s luxury pack shot with no talent, and a 30s
|
|
82
|
+
street CPG walk with a character. Replace the bracketed placeholders and hand one over
|
|
83
|
+
after the standing orders.
|
|
84
|
+
|
|
85
|
+
## Briefs — product film
|
|
86
|
+
|
|
87
|
+
One per message, after the standing orders from `/storyboard-core`. Replace
|
|
88
|
+
`[PRODUCT]` and `[CITY]`. `Nova` stands for the character entity's **plain name**.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
### Luxury pack shot, 10s 16:9
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
Direct a 10s 16:9 luxury commercial. [PRODUCT] only, no talent, no type.
|
|
96
|
+
|
|
97
|
+
Cast the pack from the attached shot: save it as an asset, then tag it as a prop
|
|
98
|
+
entity. Descriptor is geometry and finish, not copy.
|
|
99
|
+
|
|
100
|
+
Board style: black cyclorama, one warm key, gold rim, volumetric mist, 85-100mm,
|
|
101
|
+
24fps, no grain, no on-screen type.
|
|
102
|
+
|
|
103
|
+
1a 0-2 macro. A light streak crosses the glass, two condensation beads run.
|
|
104
|
+
The light moves, the pack does not.
|
|
105
|
+
2a 2-4 the bottle rises onto black acrylic, key holds.
|
|
106
|
+
3a 4-6 low 30-degree orbit, label readable at the midpoint.
|
|
107
|
+
4a 6-8 rack focus from cap to liquid, one ripple, then still.
|
|
108
|
+
5a 8-10 pull back to a centred hero, key lifts ten percent, last 1.2s dead hold.
|
|
109
|
+
|
|
110
|
+
Stop after the board. Stills before clips.
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Street CPG walk, 30s 16:9
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
Direct a 30s 16:9 street commercial in [CITY] for [PRODUCT] with Nova.
|
|
117
|
+
|
|
118
|
+
Cast both: the pack from the attached shot as a prop entity, Nova as a character
|
|
119
|
+
entity from a generated reference you show me first.
|
|
120
|
+
|
|
121
|
+
Board style: 90s print / 35mm commercial, hard noon sun, mild bloom, no other
|
|
122
|
+
brand marks, no on-screen type.
|
|
123
|
+
|
|
124
|
+
1a 0-4 fisheye on a boom, Nova walking cobbles, [PRODUCT] in hand, long shadow
|
|
125
|
+
2a 4-8 shoulder track, one bite or sip
|
|
126
|
+
3a 8-12 POV from inside the cup or wrapper, a building cornice behind
|
|
127
|
+
4a 12-16 low wide at a crosswalk, one unbranded taxi crosses
|
|
128
|
+
5a 16-22 she stops and turns once, the pack reads
|
|
129
|
+
6a 22-27 she leans to the lens, a small late smile. One line, this shot only.
|
|
130
|
+
7a 27-30 the pack alone on a cafe table, street bokeh, one-second push, dead
|
|
131
|
+
hold on the tail. entity_ids: the product only.
|
|
132
|
+
```
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: qwen-image-prompting
|
|
3
|
+
description: Prompt Alibaba's Qwen-Image line for the typography work it is built for — quoting exact copy so the model stops inventing it, switching prompt expansion off before it rewrites your strings, describing layout in relative position and weight rather than point sizes, writing non-Latin scripts as characters, and addressing edit references as image 1/2/3. Use whenever the model id names Qwen-Image (alibaba/qwen-image-3/text-to-image, alibaba/qwen-image-3/edit, fal-ai/qwen-image-2/pro/text-to-image, fal-ai/qwen-image-edit-2511, fal-ai/qwen-image-2512, fal-ai/qwen-image-layered, qwen-image-3.0-pro/edit, qwen/qwen-image-edit-plus) on generate_image, edit_image or a TextToImage node.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Qwen-Image → the model you reach for when the image has words in it
|
|
7
|
+
|
|
8
|
+
Qwen-Image renders text other image models garble. Runware's guide claims
|
|
9
|
+
twelve scripts natively, legible down to roughly 10 px, and long layout
|
|
10
|
+
instructions honoured. That is the
|
|
11
|
+
reason to pick it, and the prompt should spend its length on the copy and the
|
|
12
|
+
layout rather than on adjectives.
|
|
13
|
+
|
|
14
|
+
Reach it with `find_model` for `text_to_image` or `image_to_image`, then
|
|
15
|
+
`generate_image` / `edit_image`. `generate_image` forwards only the prompt, a
|
|
16
|
+
negative prompt, the size and a quality string, and `edit_image` only the
|
|
17
|
+
images, the prompt, a negative prompt, a target size and a strength. The
|
|
18
|
+
expansion flag, guidance and step count exist only on the route's own node:
|
|
19
|
+
find it with `search_nodes`, read its fields with `get_node_info`, and run it
|
|
20
|
+
with `run_node`.
|
|
21
|
+
|
|
22
|
+
On Qwen-Image-3 (`alibaba/qwen-image-3/*`) prompts run to 5000 characters; the
|
|
23
|
+
negative prompt caps at 500. `fal-ai/qwen-image-2/edit` and the
|
|
24
|
+
`qwen-image-max` routes cap the prompt at 800.
|
|
25
|
+
|
|
26
|
+
## Quote the copy
|
|
27
|
+
|
|
28
|
+
Anything in quotation marks is treated as literal copy. Anything you describe
|
|
29
|
+
instead, the model writes for you — usually plausibly and never what you meant.
|
|
30
|
+
|
|
31
|
+
> A vertical science poster. Title "轨道力学" in large bold characters across the
|
|
32
|
+
> upper third, subtitle "Orbital Mechanics" in small widely-spaced capitals
|
|
33
|
+
> directly beneath. Three labelled diagram panels down the centre, captions
|
|
34
|
+
> "近地点", "远地点", "转移轨道" under each. A thin rule separates the diagram block
|
|
35
|
+
> from a footer reading "第三版 · 2026". Flat editorial illustration, two-colour
|
|
36
|
+
> palette. No other text.
|
|
37
|
+
|
|
38
|
+
Three habits that make it land:
|
|
39
|
+
|
|
40
|
+
- **Write the characters, never describe them.** Paste the Chinese, Japanese,
|
|
41
|
+
Korean or Spanish string itself, with its diacritics. "The Chinese word for
|
|
42
|
+
orbit" produces something that is not that word.
|
|
43
|
+
- **State the relationship between scripts** in a bilingual layout — "on the
|
|
44
|
+
same line", "stacked directly beneath" — and match their size and weight, or
|
|
45
|
+
one language reads as an afterthought.
|
|
46
|
+
- **Close with "no other text".** Left to itself, the model fills empty margins
|
|
47
|
+
with invented lettering.
|
|
48
|
+
|
|
49
|
+
This is the model for copy that is part of the image — a poster, a label, a
|
|
50
|
+
sign in the scene. A title or a super on a still headed for a timeline is not:
|
|
51
|
+
that goes on as a text clip afterwards (`caption-titles`), where it can be
|
|
52
|
+
corrected and re-timed.
|
|
53
|
+
|
|
54
|
+
## Turn prompt expansion off for typography
|
|
55
|
+
|
|
56
|
+
On the hosted tiers — Qwen-Image-2, Max and 3 — `enable_prompt_expansion`
|
|
57
|
+
defaults to true and runs an LLM over your prompt first. AtlasCloud's
|
|
58
|
+
`qwen-image-3.0` and `qwen-image-3.0-pro` routes spell it `prompt_extend`, also
|
|
59
|
+
true by default. It helps a three-word
|
|
60
|
+
prompt and ruins a typographic one: it edits the strings you quoted and adds
|
|
61
|
+
signage you did not ask for. Set it false whenever exact copy matters.
|
|
62
|
+
|
|
63
|
+
The open-weight checkpoints (`fal-ai/qwen-image`, the `qwen-image-edit-*`
|
|
64
|
+
releases) have no such flag and take your prompt as written. On fal they expose
|
|
65
|
+
`guidance_scale` and `num_inference_steps` instead, and LoRA variants — raise
|
|
66
|
+
guidance when the layout is being loosely interpreted, and leave the step
|
|
67
|
+
count alone until the prompt is settled. Replicate's `qwen/qwen-image` and
|
|
68
|
+
`qwen/qwen-image-2512` call the dial `guidance`, and `qwen/qwen-image` adds an
|
|
69
|
+
`enhance_prompt` rewrite that is off by default. Several Replicate edit routes
|
|
70
|
+
(`qwen/qwen-image-edit`, `qwen/qwen-image-edit-plus`,
|
|
71
|
+
`qwen/qwen-image-edit-2511`) expose neither dial.
|
|
72
|
+
|
|
73
|
+
## Layout is relative, not metric
|
|
74
|
+
|
|
75
|
+
Point sizes and pixel coordinates mean nothing here. Vertical order, relative
|
|
76
|
+
size and relative weight mean everything. "Large bold capitals across the top,
|
|
77
|
+
small widely-spaced capitals directly beneath, body copy in two columns below
|
|
78
|
+
the rule" is a layout the model can execute. "24pt heading at x=120" is not.
|
|
79
|
+
|
|
80
|
+
For dense label sets, add structural marks — rules, borders, panels. Without
|
|
81
|
+
them a block of labels renders as a list.
|
|
82
|
+
|
|
83
|
+
## Size
|
|
84
|
+
|
|
85
|
+
On Qwen-Image-3, text-to-image runs 512×512 to 2048×2048 total pixels and
|
|
86
|
+
editing runs 512×512 to 1440×1440; the other checkpoints have their own
|
|
87
|
+
ceilings, so read the endpoint. Small type needs the pixels: draft the
|
|
88
|
+
composition small, then render the deliverable near the ceiling, and choose a
|
|
89
|
+
taller canvas when the fine print has to survive.
|
|
90
|
+
|
|
91
|
+
## Editing
|
|
92
|
+
|
|
93
|
+
Qwen-Image-3 Edit takes one to three reference images and **order matters** —
|
|
94
|
+
the prompt addresses them as "image 1", "image 2", "image 3". References run
|
|
95
|
+
384–2048 px per side, 10 MB each, JPEG/PNG without alpha or WEBP. The earlier
|
|
96
|
+
edit checkpoints take a list too, and the same "image N" convention applies.
|
|
97
|
+
|
|
98
|
+
> Place the bottle from image 1 on the marble surface from image 2, keeping the
|
|
99
|
+
> bottle's label, proportions and cap exactly as they are. Match the lighting
|
|
100
|
+
> direction of image 2. Replace the label copy with "SERIES 04" in white
|
|
101
|
+
> sans-serif capitals.
|
|
102
|
+
|
|
103
|
+
Name what stays as explicitly as what changes. Recolouring a packshot, carrying
|
|
104
|
+
a product into a new scene, and staging two products together are all the same
|
|
105
|
+
instruction shape: what comes from which image, what must not move.
|
|
106
|
+
|
|
107
|
+
## Symptoms
|
|
108
|
+
|
|
109
|
+
| What went wrong | What to change |
|
|
110
|
+
| :--- | :--- |
|
|
111
|
+
| The text is close to yours but not yours | Quote it, and set `enable_prompt_expansion` (or `prompt_extend`) false |
|
|
112
|
+
| Invented words in the margins | Add "no other text" |
|
|
113
|
+
| Non-Latin script renders as garbage | Paste the characters instead of describing them |
|
|
114
|
+
| Small type is illegible | Render nearer the pixel ceiling, or use a taller canvas |
|
|
115
|
+
| The wrong reference supplied the subject | Say "image 1" / "image 2" explicitly and check the order you sent |
|
|
116
|
+
| Hierarchy is flat | Give each line a relative size and weight, not a size in points |
|
|
117
|
+
|
|
118
|
+
Grade the result with `critique_image` and `score_image_adherence`, which will
|
|
119
|
+
tell you whether the copy rendered as written before you look at the picture.
|
|
120
|
+
|
|
121
|
+
Adapted from Runware's Qwen-Image-3.0 text and typography guide:
|
|
122
|
+
https://runware.ai/docs/models/alibaba-qwen-image-3-0/guides/text-and-typography
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: script-video
|
|
3
|
+
description: "Direct a NodeTool video whose timing follows written voiceover, such as a narrated explainer or narrated b-roll: script, voice, and shots timed to the takes. For an explainer's beat structure, pair with explainer-storyboard. For on-camera creators, use ugc-video."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
**Load `/storyboard-core` first.** It carries the loop, the tool contract and
|
|
7
|
+
the gating this skill assumes. This job type inverts the order of that loop, so read
|
|
8
|
+
the sequence below before creating a board. For a product explainer, load
|
|
9
|
+
`/explainer-storyboard` as well: it sets the teaching arc and the beats, and this
|
|
10
|
+
skill turns their voiceover into a script that times the shots.
|
|
11
|
+
|
|
12
|
+
## What makes this job type its own
|
|
13
|
+
|
|
14
|
+
Everywhere else the picture comes first and the words ride along. Here the words are
|
|
15
|
+
the spine: they set the running time, and each shot has to be exactly as long as the
|
|
16
|
+
line it covers. That is a different tool path — a **script resource** the storyboard
|
|
17
|
+
links to — not a storyboard with narration typed into it.
|
|
18
|
+
|
|
19
|
+
The payoff is that `assemble_storyboard_timeline` on a linked board cuts words and
|
|
20
|
+
picture together: each shot runs as long as the takes it covers, and every voiced line
|
|
21
|
+
becomes its own voiceover clip.
|
|
22
|
+
|
|
23
|
+
## The sequence
|
|
24
|
+
|
|
25
|
+
1. **Research and write the voiceover.** 150–165 words is about 60 seconds. Write it
|
|
26
|
+
before anything visual exists.
|
|
27
|
+
2. `create_script {name}`.
|
|
28
|
+
3. `edit_script {script_id, ops}` — `{"op": "add_speaker", "name": "Narrator"}`, then
|
|
29
|
+
one `{"op": "add_line", "speaker": "Narrator", "text": "..."}` per sentence. A line
|
|
30
|
+
with no `speaker` has no voice to inherit and reads `no_voice` however the cast is
|
|
31
|
+
set. One sentence per line: a line is the unit that gets a take and times a shot,
|
|
32
|
+
so a paragraph in one line gives you a shot you cannot cut.
|
|
33
|
+
4. **Give the narrator a voice:** `find_model` (`text_to_speech`) →
|
|
34
|
+
`{"op": "set_speaker_voice", "target": "Narrator", "provider", "model", "voice"}`.
|
|
35
|
+
Without it every line reads `no_voice`. `voice` is the provider's own voice name
|
|
36
|
+
(`Aoede`, `alloy`), not a model id.
|
|
37
|
+
5. `derive_storyboard_from_script {script_id, provider, model}` — one shot per line, in
|
|
38
|
+
reading order, each carrying the line ids it covers. Pass a language provider and
|
|
39
|
+
model for a director pass that writes each shot's visuals over that scaffold; omit
|
|
40
|
+
**both** for the bare scaffold.
|
|
41
|
+
6. **Rewrite the visuals.** The derived shots are a starting point. Go through with
|
|
42
|
+
`edit_storyboard` `update_shot`, giving each an `action` that is concrete b-roll and
|
|
43
|
+
a `motion` with a count. Set the board `style` and `entity_ids` with `set_board`.
|
|
44
|
+
Confirm the shot count and the models with the user before the first render.
|
|
45
|
+
7. **Stills on every shot**, reviewed, before any clip.
|
|
46
|
+
8. `voice_script_lines {script_id}` — defaults to every draft or stale line. Word
|
|
47
|
+
timings come from a transcription pass (`transcribe: true` by default) and ride into
|
|
48
|
+
the clips as captions.
|
|
49
|
+
9. Clips, then `assemble_storyboard_timeline`, then `validate_timeline`.
|
|
50
|
+
10. **Duck the pictures' own sound.** Assembly gives every shot clip an audio twin on a
|
|
51
|
+
"Shot Audio" track. `edit_timeline` → `get_state`, then `set_clip_params` with
|
|
52
|
+
`muted: true` on those clips so the voiceover carries.
|
|
53
|
+
|
|
54
|
+
## Timing
|
|
55
|
+
|
|
56
|
+
A shot on a linked board takes its length from its lines' takes — that is
|
|
57
|
+
`duration_source: "audio"`, the default once linked. Leave it alone. Pin a shot with
|
|
58
|
+
`duration_source: "manual"` plus `duration_seconds` only when it must hold past its
|
|
59
|
+
narration, such as a final card.
|
|
60
|
+
|
|
61
|
+
Voice **before** you cut. A line with no take leaves its shot on its own duration, and
|
|
62
|
+
the assembly lists it as skipped.
|
|
63
|
+
|
|
64
|
+
## Style registers
|
|
65
|
+
|
|
66
|
+
Put one in the board `style`, and say `no on-screen type` — titles belong on the
|
|
67
|
+
timeline as text clips, where they stay editable.
|
|
68
|
+
|
|
69
|
+
| Register | `style` |
|
|
70
|
+
|---|---|
|
|
71
|
+
| Flat 2D | `flat vector illustration, three-colour palette, thick uniform strokes, white ground` |
|
|
72
|
+
| Documentary macro | `macro photography, shallow depth, natural light, matte film grade` |
|
|
73
|
+
| Dark UI | `dark interface on a black ground, single accent colour, crisp type-free panels` |
|
|
74
|
+
| Paper-craft | `cut-paper layers, soft drop shadows, warm raking light` |
|
|
75
|
+
|
|
76
|
+
## Music
|
|
77
|
+
|
|
78
|
+
`edit_storyboard` → `{op: "set_board", music_prompt: "..."}` sets the score direction,
|
|
79
|
+
headless, and assembly turns it into a draft music clip under the voiceover. For a bed
|
|
80
|
+
you generate yourself instead: `generate_music`, then `edit_timeline` → `add_track` +
|
|
81
|
+
`add_media_clip`, with its `volumeDb` low enough to sit under the voiceover.
|
|
82
|
+
|
|
83
|
+
## Brief
|
|
84
|
+
|
|
85
|
+
Adapt these examples to the user's brief. Example deliverables, style choices,
|
|
86
|
+
and approval checkpoints apply only when the user adopts them.
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
Research [TOPIC], then direct a faceless 16:9 explainer. No on-camera talent.
|
|
90
|
+
|
|
91
|
+
Write the voiceover first, 150-165 words, one sentence per line, as a script:
|
|
92
|
+
create_script, then edit_script to add a Narrator speaker and the lines, each
|
|
93
|
+
line with speaker Narrator. Give the narrator a voice with set_speaker_voice
|
|
94
|
+
before anything else.
|
|
95
|
+
|
|
96
|
+
Then derive_storyboard_from_script with a director pass, and rewrite each of the
|
|
97
|
+
eight shots' action and motion as concrete b-roll to that voiceover.
|
|
98
|
+
Board style: [flat 2D / documentary macro / dark UI / paper-craft], no on-screen
|
|
99
|
+
type.
|
|
100
|
+
|
|
101
|
+
Stills on every shot before any clip. Then voice_script_lines so the shots take
|
|
102
|
+
their length from the takes, then clips, then assemble_storyboard_timeline and
|
|
103
|
+
validate_timeline. Finish by muting the Shot Audio clips under the voiceover.
|
|
104
|
+
|
|
105
|
+
Stop after the script and the board. Show me the words before you spend.
|
|
106
|
+
```
|