@kolbo/mcp 1.84.1 → 1.84.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kolbo/mcp",
3
- "version": "1.84.1",
3
+ "version": "1.84.3",
4
4
  "description": "Kolbo AI MCP Server - Generate images, videos, music, speech, and sound effects from Claude Code",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  # AUTO-GENERATED — do not edit
2
2
 
3
- This tree is mirrored from kolbo-code@24a7092, the single source of truth.
3
+ This tree is mirrored from kolbo-code@261fab2, the single source of truth.
4
4
  Canonical source: packages/opencode/skills/kolbo/
5
5
  Distribution: .github/workflows/sync-skill-to-plugin.yml
6
6
 
package/skill/SKILL.md CHANGED
@@ -9,7 +9,8 @@ description: |
9
9
  filmmaking as well as individual media:
10
10
  scripts, production bibles, recurring characters and locations, acting,
11
11
  dialogue, music performance, blocking, physics, multi-shot continuity,
12
- connected scenes, prompt audits, and feature-length production planning.
12
+ connected scenes, prompt audits, feature-length production planning, and
13
+ direct Blender scene building through the connected Kolbo Blender plugin.
13
14
 
14
15
  NOT for: video editing / FFmpeg (use video-production), motion graphics
15
16
  (use remotion-best-practices), code editing, or general chat.
@@ -68,6 +69,7 @@ For multi-scene / batch work this pairs with `generate_creative_director` (see b
68
69
  |---|---|
69
70
  | Make a **film / ad / scene / episode / campaign / any video with multiple or recurring characters** — read BEFORE planning a single shot | `references/workflows/production-planning.md` |
70
71
  | Direct, develop, audit, or continue a **film / episode / connected scene / complex performance** with continuity, acting, dialogue, music, blocking, or physics | `references/workflows/filmmaking.md` |
72
+ | Build, inspect, animate, light, render, or edit a **Blender scene through Kolbo Blender MCP** | `references/workflows/blender-mcp.md` |
71
73
  | Generate a **Seedance 2.5** video | `skill` `elements-prompting` + `references/models/seedance25.md` + Locked Intro in `references/models/seedance.md`. For narrative/continuity also load `references/workflows/filmmaking.md` — but compile the prompt as Locked Intro, NOT the SCENE CONTEXT / OPTICS / ACTION pack |
72
74
  | Generate a **Seedance 2 / WAN / MiniMax H3 / Gemini / Elements** video (`generate_elements` or Visual DNA) | `skill` `elements-prompting` + `references/models/seedance.md` — same Locked Intro. Elements is NOT a different prompt language |
73
75
  | Generate a **GPT Image 2** image | `references/models/gpt-image.md` |
@@ -86,6 +88,7 @@ For multi-scene / batch work this pairs with `generate_creative_director` (see b
86
88
  | Compose a **DTC ad image** (brand kit + ad format + avatar + product + reference media) | `references/workflows/dtc-ads.md` |
87
89
  | Generate **brand product imagery** (studio shot, lifestyle, Pinterest pin, hero banner, carousel, ad pack, virtual try-on, conceptual, restyle) | `references/workflows/product-photoshoot.md` |
88
90
  | Generate **marketplace listing cards** (Amazon main + secondary + A+ content) | `references/workflows/marketplace-cards.md` |
91
+ | Apply a **preset** — a named look, sheet, thumbnail, grading, camera move, Seedance shot recipe, music style — or decide whether one fits what the user just asked for | `references/workflows/presets.md` |
89
92
  | Use **Visual DNA** / character consistency / `@name` syntax | `references/workflows/visual-dna.md` |
90
93
  | Use **Color DNA** / brand palette grading | `references/workflows/color-dna.md` |
91
94
  | Start or continue a **multi-step production** (storyboard → scenes → final cut) | `references/workflows/production-log.md` |
@@ -128,7 +131,7 @@ Each `references/models/*.md` mirrors the matching skill prompt in `kolbo-api/sr
128
131
  | `list_models` / `list_voices` / `check_credits` / `show_plans` / `get_generation_status` / `cancel_generation` / `get_session_usage` | Discovery + status. `list_models` with no args returns the recommended shortlist out of ~428 — pass `type` for a full category with per-model caps. `cancel_generation` stops an in-flight job and refunds what it can: use it when the user changes their mind mid-generation instead of letting it run. `show_plans` renders the balance + upgrade card for pricing/plan/upgrade questions. |
129
132
  | `upload_media` / `create_upload_ticket` / `list_media` / `get_media` / `get_media_stats` / `favorite_media` / `unfavorite_media` / `delete_media` / `restore_media` / `permanently_delete_media` / `move_media` / `bulk_*_media` / `*_media_folder` | Media library — see `workflows/media-library.md`. Getting a LOCAL file in depends on where the server runs: `upload_media` with a path only works on a local (stdio) install; over a remote connector use `create_upload_ticket` and POST the file yourself. |
130
133
  | `create_visual_dna` / `update_visual_dna` / `generate_character_sheet` / `list_visual_dnas` / `get_visual_dna` / `delete_visual_dna` / `*_visual_dna_folder` (5 folder tools) | Visual DNA (+ character sheet, character folders) — see `workflows/visual-dna.md`. Edit with `update_visual_dna`; never delete+recreate. |
131
- | `list_moodboards` / `get_moodboard` / `list_presets` | Style overlays + sheet presets — see **Preset contract** in Core Workflow. Never omit `preset_id` after claiming a preset was used. |
134
+ | `list_moodboards` / `get_moodboard` / `list_presets` / `list_cinematic_presets` | Style overlays + presets. `list_presets` spans FOUR distinct catalogs (`image`, `image_edit`, `video`, `music`; `text_to_video` is an alias for `video`, `shorts` is empty) the `video` one holds 200+ Seedance shot recipes. `list_cinematic_presets` is a separate tool feeding the `cinematic` arg, never `preset_id`. Full doctrine + intent→catalog map: `references/workflows/presets.md`. Never omit `preset_id` after claiming a preset was used. |
132
135
  | `list_color_palettes` / `analyze_color_palette` / `create_color_palette` / `update_color_palette` / `delete_color_palette` / `activate_color_palette` / `deactivate_color_palette` | **Color DNA — sticky + account-wide; at most one palette active at a time**, and while active it strict-grades **every** image and video generation automatically. Per-generation opt-out: `skip_color_palette: true`. Details: `workflows/color-dna.md`. |
133
136
  | `list_agents` / `create_agent` / `update_agent` / `delete_agent` | Custom chat agents — reusable named personas for `chat_send_message`. The agent's `description` IS the system instruction. Resolve a name the user mentions ("use my SEO agent") to an id with `list_agents`, then pass `agent_id`. Global/preset agents are read-only; only the user's own can be updated or deleted. |
134
137
  | `search_stock_media` / `get_stock_sources` / `get_stock_categories` / `get_stock_collections` / `get_stock_asset` / `analyze_script_for_stock` / `import_stock_asset` | Stock library (free, no credits) — EXISTING photos / videos / 3D / SFX / music. For stock **music** use `search_stock_media` with `mediaType: "music"` (semantic vibe query, e.g. "uplifting corporate background") → `get_stock_asset` for downloads. The older `*_music_library` tools are deprecated adapters over this — prefer the stock tools, except for the licensed-catalog tools in the next row. |
@@ -234,7 +237,7 @@ Dependencies accumulate: narrative Elements work requires **Kolbo + filmmaking +
234
237
 
235
238
  `N connected cinematic shots, Xs total, AR, Multishot ON` → `Total: Xs / N shots / AR` → `[GLOBAL LOOK – LOCKED, APPLIES TO EVERY SHOT]` → `[CAST – IDENTICAL IN EVERY SHOT]` (each person is `@DNAName`) → `[LOCATION]` → LOCATION MAP / CONTINUITY / PHYSICS → `SHOT N — 0:00–0:02 — …` (ranges sum to Xs) → closing `Total: Xs / N shots / AR`. Pass MCP `duration: X` matching that Total. Omitting Total / Multishot is a failed compile — same contract as the Kolbo help widget.
236
239
 
237
- Write the beats at FULL DEPTH. The cap is 15,000 characters on Seedance 2.5 (10,000 on 2.0) — a 30s / 8+ shot compile should land around 4k–9k, and every beat carries its own camera move, a performance task for the speaker AND the listeners, prop/hand state, and the sound in that beat. A one-line shot beat is under-written; the structure alone is not the craft. Read `references/models/seedance25.md` before compiling.
240
+ Write the beats at FULL DEPTH. The cap is 30,000 characters on Seedance 2.5 (10,000 on 2.0) — a 30s / 8+ shot compile should land around 4k–9k, and every beat carries its own camera move, a performance task for the speaker AND the listeners, prop/hand state, and the sound in that beat. A one-line shot beat is under-written; the structure alone is not the craft. Read `references/models/seedance25.md` before compiling.
238
241
 
239
242
  Do **not** default Elements to `SCENE CONTEXT` / `OPTICS` / `ACTION` / `ACTIVE REFERENCES` department packs (those live in filmmaking audit/contracts for other models). `elements-prompting` is the craft skill (formerly `seedance-2-prompting`); Locked Intro is the compile shape.
240
243
 
@@ -267,11 +270,14 @@ A user-named tool — in any language — overrides every other rule. Recognized
267
270
 
268
271
  ## Core Workflow
269
272
 
270
- **Preset contract:**
271
- - Custom instructions live on the **preset**. Prefer `generate_image` + `preset_id` (not `generate_character_sheet`) for Character Sheet / Headless / Bible / location / product sheets.
272
- - Always `list_presets({ type: "image", search: "<name>" })` `headless`, `bible`, `character sheet`. That is a silent id lookup. Do **not** omit `search` (that dumps the whole catalog). Reuse the id after the first hit.
273
+ **Preset contract** (full doctrine — catalogs, intent→search map, cinematic dimensions: `references/workflows/presets.md`):
274
+ - Custom instructions live on the **preset**, and it is almost always better than the paragraph you would improvise. Prefer `generate_image` + `preset_id` (not `generate_character_sheet`) for Character Sheet / Headless / Bible / location / product sheets.
275
+ - **Presets are not image-only.** `type: "video"` holds 200+ Seedance 2 shot recipes (chase, orbital, drift, showcase, VFX, storyboard) and feeds `generate_video` + `generate_elements`; `image_edit` and `music` have their own catalogs. `image` and `image_edit` ids are NOT interchangeable.
276
+ - **Search on the user's own noun when their request matches a catalog** — they rarely say "preset". `list_presets({ type, search: "<their word>" })` matches name + description + category together.
277
+ - Always pass `search`. That is a silent id lookup. Do **not** omit it (that dumps a 632k-char catalog). Reuse the id after the first hit.
273
278
  - Browse (no search) only when the user asked to see presets.
274
- - Pass the exact returned `id` as `preset_id`. Never invent an id.
279
+ - Pass the exact returned `id` as `preset_id`. Never invent an id. Never claim a preset was used without passing it.
280
+ - Cinematic presets are a DIFFERENT tool (`list_cinematic_presets` → the `cinematic` arg, one id per dimension, omit for Auto) — never `preset_id`.
275
281
 
276
282
  1. **Check credits** ONCE per conversation (Step 0). Skip if already checked.
277
283
  2. **Load the matching skill** (HARD RULE above) before the first paid call in the turn.
@@ -13,6 +13,8 @@ Load this file when the user wants a **Seedance 2 / Seedance 2.0** (ByteDance) v
13
13
 
14
14
  ## Universal Rules (apply to EVERY Seedance / Elements prompt)
15
15
 
16
+ - **NO MUSIC BY DEFAULT (HARD):** Unless the user explicitly asks for music, every final Seedance prompt—including every Elements/reference-driven prompt—must explicitly say `No music. No musical score.` Keep requested dialogue, synchronized production sound, ambience, and SFX; "no music" does not mean "no audio." If the user explicitly requests music, describe that music instead and omit the no-music lock. Never invent background music from cinematic tone alone.
17
+ - **NO FAMOUS NAMES OR IP IN PROMPTS (HARD):** Never put celebrity/public-figure names, real directors or artists, copyrighted character/franchise/IP names, famous campaign names or slogans, or famous studio/company names into a final Seedance or Elements prompt. Translate user-supplied references into concrete visual traits—medium, shape language, palette, lighting, texture, camera behavior, pacing, and mood—without repeating the famous name. Preserve exact user-owned Visual DNA and asset tags.
16
18
  - **Visual DNA names are immutable anchors:** when `visual_dna_ids` is passed, every DNA MUST appear in the prompt as the exact literal `@DNA_name` (CAST + every shot it is in). Never "Zohar's", "the left man", "the man on the LEFT", a nickname, or a Visual DNA anchors paragraph without `@tags`.
17
19
  - **Rewrites never thin out or rename anchors.** "`@X anchors Odysseus`" is NOT a reference line, and `Odysseus` must never replace `@X` later. Every referenced asset keeps its exact literal tag plus a full role line on every rewrite. Re-use the exact DNA tag in every shot it participates in. A compile that dropped `@gal_suit` / `@yonatan` / `#Board` is a failed turn.
18
20
  - **DURATION + SHOT STRUCTURE (HARD — same as help widget):** every text-to-video / Elements prompt MUST open AND close with total duration, shot count, and aspect. Omit only for video-edit tasks (source duration is locked). Required first lines:
@@ -97,7 +99,7 @@ FORBIDDEN: omitting Total / Multishot; "same character throughout" as the only l
97
99
  - Always supply: **clear location, clear power mismatch, defined escalation arc**.
98
100
  - Describe choreography beat by beat — Seedance executes what you write.
99
101
  - Single continuous shot 15s works for two-fighter scenes; describe camera moves between beats (`crests rooftop edge`, `full 360 orbit`, `pulls back to wide`, `descends with them`).
100
- - Use `Guy Ritchie speed-ramping with Snyder impact slow-motion` as the style anchor when comedic/stylized.
102
+ - Use `playful speed-ramping with heavy impact slow-motion` as the style anchor when comedic/stylized.
101
103
 
102
104
  ### 5. Animation (3D stylized)
103
105
  - Break the 15s into **timed segments** (`0–3s`, `3–6s`, `6–9s`, `9–12s`, `12–15s`) and describe each explicitly.
@@ -196,7 +198,7 @@ Use only the discrete steps. Not "23°" — use 18° or 29°.
196
198
  - **Emotion through muscle movement**, not labels. ❌ "she looks sad" → ✅ "her eyes drop to the table, jaw tightens, she swallows once before answering."
197
199
  - **WB in Kelvin.** 3200K / 4000K / 5600K / 8500K. Pick ONE for the scene's mood.
198
200
  - **Color as material + light + role**, never a flat list. ❌ "she wears red, he wears blue" → ✅ "crimson silk scarf catching the cold tungsten spill from the corridor".
199
- - **No equipment names**, no director references, no "shot on ARRI / Sigma 85mm / Roger Deakins".
201
+ - **No equipment names and no famous creative references**; describe the observable lens, lighting, movement, texture, and grade instead.
200
202
 
201
203
  ### Cuts and timing
202
204
 
@@ -270,4 +272,4 @@ Seedance 2 lives in the **Video** category. Route the prompt card by the INPUTS:
270
272
 
271
273
  ## Seedance + Visual DNA / References
272
274
 
273
- When a character must stay consistent, pair Seedance with Visual DNA via `generate_elements` (NOT `generate_video` — text-to-video silently drops `visual_dna_ids`). `@DNA_name` tagging rules: see `workflows/visual-dna.md`. For grid/storyboard inputs, the source frame is `@image1`.
275
+ When a character must stay consistent, pair Seedance with Visual DNA via `generate_elements` (NOT `generate_video` — text-to-video silently drops `visual_dna_ids`). `@DNA_name` tagging rules: see `workflows/visual-dna.md`. For grid/storyboard inputs, the source frame is `@image1`.
@@ -19,9 +19,11 @@ Load this file when the user wants a **Seedance 2.5** video (they said "2.5" / "
19
19
 
20
20
  - **Duration 4–30 seconds**, whole seconds. 30s IS supported.
21
21
  - **Up to 30 shots/cuts in ONE generation.** Deliver exactly N if N ≤ 30.
22
- - **Prompt cap 15,000 characters** for the entire prompt as one string (`max_prompt_length` in the catalog; Seedance 2.0 is 10,000). Verify with `list_models` rather than trusting this number — it was documented as 30,000 for months, which is double the real limit.
22
+ - **Prompt cap 30,000 characters** for the entire prompt as one string (`max_prompt_length` in the catalog; Seedance 2.0 is 10,000). Raised from 15,000 on 2026-08-30 after the whole provider chain was verified live to serve it. Verify with `list_models` rather than trusting this number — it has moved before.
23
23
  - **Large reference / Visual DNA capacity** (`@Name`, `@ImageN`, `#Moodboard`) — read the exact caps from `max_visual_dna` / `elements_max_images` in `list_models`. Every referenced asset must be tagged in the prompt text. A rewrite that drops or renames a tag ( `@doron_fauda_1` → `DORON` / `the hero` ) is a failed turn — put the exact tag back.
24
24
  - **Multimodal refs:** images + video clips + audio can all anchor one generation.
25
+ - **NO MUSIC BY DEFAULT (HARD):** Unless the user explicitly asks for music, every final Seedance 2.5 prompt—including every Elements/reference-driven prompt—must explicitly say `No music. No musical score.` Preserve requested dialogue, synchronized production sound, ambience, and SFX; no music does not mean "no audio." If music is explicitly requested, describe it and omit the no-music lock.
26
+ - **NO FAMOUS NAMES OR IP IN PROMPTS (HARD):** Never put celebrity/public-figure names, real directors or artists, copyrighted character/franchise/IP names, famous campaign names or slogans, or famous studio/company names into a final Seedance 2.5 or Elements prompt. Translate user-supplied references into concrete visual traits without repeating the famous name; preserve exact user-owned Visual DNA and asset tags.
25
27
 
26
28
  ## Universal Rules (HARD — same as help widget OUTPUT CONTRACT)
27
29
 
@@ -65,7 +67,7 @@ FORBIDDEN: "same character throughout" as the only lock; one fence per shot; cla
65
67
 
66
68
  ## Prompt length
67
69
 
68
- Simple ≤15s ~120–280 words. Locked-intro cinematic 15s typically 400–900 words. Full 30s / 15+ shots typically 700–1200 words / ~4k–9k chars. Hard cap 15,000 characters. Never split into part 1 / part 2.
70
+ Simple ≤15s ~120–280 words. Locked-intro cinematic 15s typically 400–900 words. Full 30s / 15+ shots typically 700–1200 words / ~4k–9k chars. Hard cap 30,000 characters. Never split into part 1 / part 2.
69
71
 
70
72
  A one-line shot beat is UNDER-WRITTEN. At 30s / 8+ shots you have ~15k characters to work with and a thin prompt wastes them: every beat carries its own camera move, performance task for BOTH the speaker and the listeners, prop/hand state, and the sound in that beat. If a 30s compile lands under ~4k characters, it is too thin — go back and direct it.
71
73
 
@@ -0,0 +1,127 @@
1
+ # Blender MCP Scene Craft
2
+
3
+ Read this reference whenever the user wants an agent to inspect, build, block,
4
+ animate, light, render, or modify a live Blender scene through the Kolbo Blender
5
+ plugin. This is Blender work, not AI video generation: do not ask for a model,
6
+ project, aspect ratio, or credit confirmation unless the request also includes a
7
+ paid Kolbo media generation.
8
+
9
+ ## Connection and execution boundary
10
+
11
+ - Discover the user's connected Blender sessions first. If there is more than
12
+ one, identify the intended file/session from the returned name and scene
13
+ summary rather than guessing.
14
+ - Read the scene before editing it. Start with a compact summary, then inspect
15
+ only the relevant objects, collections, cameras, materials, and timeline.
16
+ - Prefer validated structured scene operations. Use Blender Python only when the
17
+ requested result cannot be expressed structurally; Python has full machine
18
+ authority and requires explicit approval unless trusted mode is active.
19
+ - Ordinary reversible construction and animation can execute directly. Deletion,
20
+ file open/overwrite, arbitrary paths or URLs, add-on installation, and Python
21
+ remain approval-gated.
22
+ - Keep edits in one undoable batch where the tool supports it. Never save,
23
+ overwrite, open another file, or render an entire animation unless requested.
24
+
25
+ ## Scene construction rules
26
+
27
+ - Preserve existing work unless the user explicitly asks to replace it. Put a
28
+ new build in a clearly named collection and use stable descriptive names.
29
+ - Respect the scene unit system. Blender defaults commonly represent meters, but
30
+ inspect the actual unit settings before creating dimensioned objects.
31
+ - Build recognizable assembled objects, not symbolic blocks. A chair needs a
32
+ seat, back, and visible supports or legs; a table needs a top and believable
33
+ supports; doors, lamps, shelves, vehicles, and props need the parts that make
34
+ their silhouette and function readable.
35
+ - Objects and datablocks are separate. Check whether mesh or material data is
36
+ shared before editing it; make it single-user when only one instance should
37
+ change.
38
+ - Prefer non-destructive modifiers for adjustable geometry. Apply destructive
39
+ mesh edits only when the result needs to be final or the user asks for them.
40
+ - When raw Blender operators are required, set Object/Edit mode, active object,
41
+ and selection explicitly. Operators can silently fail or affect the wrong
42
+ object when context is inherited from the viewport.
43
+ - Capture object references immediately after creation. Blender may suffix names
44
+ on collision, so do not assume a requested name was accepted unchanged.
45
+
46
+ ## Shots, cuts, and camera motion
47
+
48
+ A request for multiple shots means a real timeline sequence, not several unused
49
+ cameras:
50
+
51
+ 1. Set a deliberate frame range from the scene FPS and requested duration.
52
+ 2. Create one camera per hard-cut shot unless the user explicitly wants one
53
+ continuous take.
54
+ 3. Bind each shot camera to a timeline camera marker on the exact first frame of
55
+ that shot.
56
+ 4. Make the opening camera active and verify every requested cut by scrubbing the
57
+ boundary frames.
58
+
59
+ Never interpolate one camera through a hard cut. A cut is the marker switching
60
+ from one camera to another; animation belongs inside each shot.
61
+
62
+ For camera movement inside a shot:
63
+
64
+ - Keyframe both location and rotation at the first and last movement frames.
65
+ - Use `LINEAR` interpolation by default for a constant-speed dolly, truck, crane,
66
+ orbit, push-in, or pull-out. Blender's automatic Bezier handles can ease or
67
+ overshoot unexpectedly and make continuous motion accelerate near keyframes.
68
+ - Use `BEZIER` only when the brief explicitly calls for easing, a soft settle, or
69
+ an authored speed ramp. Inspect the curve for overshoot.
70
+ - Use `CONSTANT` only for intentional holds or stepped animation, never to fake a
71
+ camera cut.
72
+ - Keep a lock-off truly static. Do not add redundant drifting keyframes.
73
+ - Keep the camera aimed at the intended subject throughout the move. Verify the
74
+ midpoint as well as the endpoints; two acceptable endpoints can still produce
75
+ a bad path through geometry.
76
+ - Respect the camera's rotation mode. Structured operations use Euler radians;
77
+ raw Python should inspect the existing mode before choosing Euler or quaternion
78
+ keyframes.
79
+ - For a dolly zoom, animate lens and camera distance together. Do not call a
80
+ location-only push-in a dolly zoom.
81
+
82
+ ## Blocking and animation quality
83
+
84
+ - Establish readable contact and weight: feet meet the floor, chairs meet the
85
+ ground, tableware sits on the tabletop, hands meet held props, and objects do
86
+ not visibly interpenetrate unless intentional.
87
+ - Keyframe after setting the transform for that frame. Keyframe every channel
88
+ needed to preserve the pose; missing rotation keys commonly cause unwanted
89
+ interpolation.
90
+ - Do not add animation merely because the scene has a timeline. Animate only the
91
+ requested subjects and cameras.
92
+ - For repeated motion, prefer a clean reusable cycle or duplication of verified
93
+ keys over noisy frame-by-frame keys.
94
+ - In armature work, confirm the target bones are not constraint-driven before
95
+ keyframing them. Constraints can override apparently valid animation.
96
+
97
+ ## Materials, lighting, and presentation
98
+
99
+ - Give hero surfaces deliberate materials with plausible roughness and metallic
100
+ values. Reuse shared materials for related parts instead of creating a material
101
+ per primitive.
102
+ - Light for form and subject separation. A practical starting rig is a motivated
103
+ key, softer fill, and optional rim or practical light; adapt it to the requested
104
+ mood rather than mechanically adding three lights.
105
+ - Check render visibility separately from viewport visibility when an object
106
+ appears missing.
107
+ - Set an appropriate camera lens and composition. Avoid placing a camera without
108
+ checking framing through a viewport capture.
109
+
110
+ ## Verify before reporting completion
111
+
112
+ After applying edits:
113
+
114
+ 1. Re-read the scene and confirm the expected object, collection, camera, marker,
115
+ frame-range, and animation counts.
116
+ 2. Capture the viewport or a low-cost preview from the active camera.
117
+ 3. For animation, inspect the first frame, every cut boundary, one midpoint per
118
+ moving shot, and the final frame. Confirm interpolation is the intended type.
119
+ 4. Correct concrete failures before reporting success. Do not say a scene is
120
+ animated merely because keyframes exist.
121
+ 5. Report what actually changed: named collection, object count, shot cameras,
122
+ cut frames, animated channels, and any approval still waiting.
123
+
124
+ For complex Python work, return concise structured results from Blender rather
125
+ than dumping console output. Update the dependency graph before reading computed
126
+ transforms or modifier results, and inspect progressively instead of returning an
127
+ entire large scene.
@@ -0,0 +1,137 @@
1
+ # Presets — Kolbo's stored instruction blocks
2
+
3
+ A preset is a long, hand-tuned instruction block stored in Kolbo's catalog. Passing
4
+ `preset_id` prepends it to the user's prompt at generation time. **The craft lives on
5
+ the preset** — a three-panel character sheet, a Seedance shot-sequence structure, a
6
+ grading recipe — and it is always better than the paragraph you would improvise.
7
+
8
+ Until now the skill only ever taught `type: "image"` for character sheets. That left the
9
+ largest catalog in the product — **263 video presets, over 200 of them Seedance 2 shot
10
+ recipes** — invisible to every agent. If the user's request looks like something in a
11
+ catalog below, search it before you write the prompt yourself.
12
+
13
+ ## The catalogs
14
+
15
+ `list_presets({ type, search })`. Sizes measured 2026-08-31; they drift, so **never
16
+ memorise ids or names — always resolve live.**
17
+
18
+ | `type` | Size | Categories (the search vocabulary) | Passed to |
19
+ |---|---|---|---|
20
+ | `image` | ~146 | thumbnails, text, style, layout, personas, grading, camera | `generate_image` |
21
+ | `image_edit` | ~103 | style, camera control, grading, layout, enhancement | `generate_image_edit` |
22
+ | `video` | ~263 | **seedance 2 (200+)**, camera, storyboard, character, vfx | `generate_video`, `generate_elements` |
23
+ | `music` | ~54 | *(flat — no categories; search name/description)* | `generate_music` |
24
+
25
+ Two more `type` values exist and are traps:
26
+
27
+ - **`text_to_video` is an alias for `video`** — the same collection since consolidation,
28
+ returned with a different `type` label. Use `video`. Asking for both double-counts.
29
+ - **`shorts` is empty** (0 rows in production). Shorts Creator is built but not in
30
+ service. Do not offer it.
31
+
32
+ **`image` and `image_edit` are separate collections and their ids are NOT
33
+ interchangeable.** An `image` id on `generate_image_edit` fails. Resolve against the
34
+ catalog for the tool you are about to call.
35
+
36
+ **No preset on `generate_video_from_image`.** Image-to-video takes `visual_dna_ids` but
37
+ not `preset_id`. If a user wants a video preset look, route through `generate_video` or
38
+ `generate_elements`.
39
+
40
+ ## Reading the user's intent
41
+
42
+ This is the part that matters. The user rarely says "use a preset" — they describe an
43
+ outcome that a preset already encodes. Search when the request matches a row here:
44
+
45
+ | The user asks for… | Catalog | Search terms that hit |
46
+ |---|---|---|
47
+ | A character/location/product reference sheet, turnaround, model sheet | `image` | `character sheet`, `headless`, `bible`, `location`, `product` |
48
+ | A YouTube / Shorts / Reels thumbnail, a video cover | `image` | `thumbnail` — and read `workflows/thumbnails.md` |
49
+ | Text *in* the image — a headline, poster copy, a title card | `image` | `text`, `title`, `poster` |
50
+ | A named look: anime, noir, claymation, 35mm, cyberpunk | `image` | `style`, or the look itself |
51
+ | A colour treatment: teal-orange, bleach bypass, film stock | `image` / `image_edit` | `grading` |
52
+ | A specific framing: overhead, macro, wide establishing | `image` / `image_edit` | `camera` |
53
+ | A person archetype: influencer, CEO, athlete, elderly | `image` | `personas` |
54
+ | A grid, split-screen, collage, comparison, panel layout | `image` | `layout` |
55
+ | Upscale / restore / clean up / sharpen an existing image | `image_edit` | `enhancement` |
56
+ | Any Seedance 2 / 2.5 shot — chase, duel, drift, reveal, showcase | `video` | describe the ACTION: `chase`, `orbital`, `drift`, `duel`, `showcase` |
57
+ | A camera move: dolly, crane, whip pan, bullet time | `video` | `camera` |
58
+ | A storyboard or multi-shot beat sheet | `video` | `storyboard` |
59
+ | VFX: explosions, particles, morphs, energy | `video` | `vfx` |
60
+ | A music genre, mood, or instrumentation | `music` | the genre or mood word |
61
+
62
+ Search on the **noun the user used**, not a category name — the tool matches against
63
+ name, description and category together, so `"drift"` finds *Impossible Continuous
64
+ Drift* without you knowing which category it lives in.
65
+
66
+ ## Discovery contract
67
+
68
+ - **Always pass `search`.** The full catalog measured 632,919 characters; dumping it
69
+ burns the context window and returns nothing you can act on. A named lookup returns a
70
+ handful of rows.
71
+ - Browse (`search` omitted) **only when the user asked to see what's available.** That
72
+ renders a picker widget — it is for the human, not for you.
73
+ - The response carries `total` (catalog size) and `omitted_from_this_page`. A large
74
+ `omitted` on a lookup means your search was too broad — narrow it, don't paginate.
75
+ - **Reuse the id.** Once resolved in a conversation, it stays valid; do not re-search
76
+ for every generation in a batch.
77
+ - **Never invent, guess, or reconstruct an id from memory.** Ids are opaque ObjectIds.
78
+ - Do not filter results yourself by `category` casing — the API lowercases what Mongo
79
+ stores capitalised (`Layout` → `layout`). Match on meaning, not string equality.
80
+
81
+ ## Applying one
82
+
83
+ - Pass the **exact returned `id`** as `preset_id`. One preset per generation — there is
84
+ no array.
85
+ - **Never claim a preset was used without passing `preset_id`.** Saying "I applied the
86
+ Headless Character Sheet preset" while omitting the field is a fabricated result.
87
+ - The preset is **prepended**, not substituted: still write a real prompt describing the
88
+ subject. The preset supplies the treatment, you supply the content. A preset with an
89
+ empty prompt produces the preset's stock example.
90
+ - **Prefer `generate_image` + `preset_id` over `generate_character_sheet`** for any
91
+ sheet. The custom instructions live on the preset; the dedicated tool has less craft
92
+ in it.
93
+ - Video preset descriptions reference `@image1`, `@image2` for their subjects — when a
94
+ preset says that, supply reference images in that order.
95
+
96
+ ## Preset vs Visual DNA vs moodboard vs Color DNA
97
+
98
+ They stack, and they answer different questions. Do not substitute one for another:
99
+
100
+ - **Preset** — *how it is rendered.* Treatment, structure, camera, layout.
101
+ - **Visual DNA** (`visual_dna_ids` + `@Name` in the prompt) — *who or what is in it.*
102
+ Identity lock. See `workflows/visual-dna.md`.
103
+ - **Moodboard** (`moodboard_id` + `#Name`) — *the reference vibe*, derived from images.
104
+ - **Color DNA** — *the grade*, account-wide and automatic while active. See
105
+ `workflows/color-dna.md`.
106
+
107
+ A preset carrying its own grading language can fight an active Color DNA. If the user
108
+ picked both and the output drifts, that is the collision — say so and offer
109
+ `skip_color_palette: true` rather than silently dropping the preset.
110
+
111
+ ## Cinematic presets are a different tool
112
+
113
+ `list_cinematic_presets` — ~136 presets across dimensions (today: camera, lens,
114
+ focal_length, aperture, angle, shot_type, color_palette, lighting; data-driven, always
115
+ fetch). These are **not** `list_presets` rows and do not go in `preset_id`.
116
+
117
+ - Pass chosen ids via the `cinematic` argument of `generate_image` /
118
+ `generate_image_edit`, **at most one id per dimension**.
119
+ - **"Auto" is the absence of a selection** — omit the dimension, or the whole
120
+ `cinematic` object. Do not hunt for an "auto" preset.
121
+ - Call with no args for a compact index, then pass `dimension` for full descriptions of
122
+ just the one you are choosing from.
123
+ - **Only call this when the user wants a deliberate photographic look.** For an ordinary
124
+ generation, don't. "Make it cinematic" as a vague adjective is a prompt-quality
125
+ request, not a request for this tool.
126
+
127
+ ## When NOT to reach for a preset
128
+
129
+ - The user gave a **specific, complete creative direction of their own.** A preset
130
+ prepends 200+ words that will compete with theirs. Their words win.
131
+ - They named a **preset explicitly** — resolve that one, do not substitute a "better" match.
132
+ - The request is a **plain edit** ("remove the background", "make it 4K"). Those are
133
+ `edit_image` mechanics, not presets.
134
+ - You are **mid-batch on an approved look.** Changing preset between shots in one
135
+ sequence breaks continuity — that is the whole point of a locked global look.
136
+ - You could not find a good match. **Say nothing and write a good prompt.** Announcing
137
+ that you searched for presets is noise; silently applying a poor match is worse.
@@ -184,6 +184,21 @@ by the centre-square-crop test below. State this explicitly in the prompt ("gene
184
184
  margin on both sides, nothing touches the left/right edge") rather than fixing it after
185
185
  generation.
186
186
 
187
+ **Multi-element layout recipe that shipped (Aug 2026, nano-banana-2):** when a comp
188
+ carries 4+ graphic elements (headline, badge, app tile, still cards, brand chip), three
189
+ prompt clauses turned a cluttered mess into an approved final:
190
+ - **Glassmorphism containers** — put every element in its own "frosted translucent
191
+ glass container, soft blur, subtle white border, delicate shadow". Unifies the pile
192
+ into one designed system; solid stickers read as clutter.
193
+ - **STRICT NON-OVERLAP RULE** stated as its own sentence — "clear margin between every
194
+ element; nothing touches the face or hair" — models honour it remarkably well.
195
+ - **LIKENESS PRIORITY preamble** — face fidelity *drifts as element count grows*. With
196
+ 4+ elements, open the prompt with "preserve his EXACT face, identical to the Visual
197
+ DNA identity, do not drift the facial features" or the subject becomes a stranger.
198
+ - **Pin each mark to its container** — with two logos in one comp the model WILL swap
199
+ them; write "the tile shows ONLY the [X] mark; NEVER put [Y] on this tile; [Y]
200
+ appears ONLY in the bottom chip". Verify every logo placement on delivery.
201
+
187
202
  ## Variation ladder
188
203
 
189
204
  Vary the **concept**, never the words: bold dynamic · clean minimal · vibrant saturated ·
package/src/apps/index.js CHANGED
@@ -88,6 +88,17 @@ const WIDGET_CSP = {
88
88
  'https://assets.sketchfab.com',
89
89
  'https://sketchfab-prod-media.s3.amazonaws.com',
90
90
 
91
+ // Voice PREVIEW audio hosts. list_voices ships every voice with a
92
+ // preview_url and the card renders a real <audio> for it, but 150 of the
93
+ // 864 production voices store that preview on a provider host rather than a
94
+ // Kolbo bucket: 138 google voices on storage.googleapis.com and 12 on
95
+ // api.us.elevenlabs.io. media-src blocked both, so every google voice — the
96
+ // entire Hebrew set — rendered a player stuck at 0:00 / 0:00 with no error
97
+ // anywhere. The Spaces-hosted previews come free via HOST_MAP above; these
98
+ // two do not, because they are not ours.
99
+ 'https://storage.googleapis.com',
100
+ 'https://api.us.elevenlabs.io',
101
+
91
102
  // Default SYNCI catalog project. Any production override must be reviewed
92
103
  // and added here as an exact hostname before deployment.
93
104
  'https://gfbpxdkripkbbrcvoyeh.supabase.co',
@@ -48,17 +48,17 @@ function boot(sc) {
48
48
  var audioItems = sc.items.filter(function (i) { return i.media_type === 'audio'; });
49
49
  var visualItems = sc.items.filter(function (i) { return i.media_type !== 'audio'; });
50
50
  var h = '';
51
+ // Render everything currently in state — each PAGE is already capped
52
+ // server-side (GRID_CAP), so this grows one page per Load more instead of
53
+ // being pinned forever. The old hard slices (24 visual / 12 audio) meant an
54
+ // appended page could never actually appear, and the count below tallied all
55
+ // items while only 36 were drawn, so the button also lied about the total.
51
56
  if (visualItems.length) {
52
- h += '<div class="k-grid">' + visualItems.slice(0, 24).map(cellHTML).join('') + '</div>';
57
+ h += '<div class="k-grid">' + visualItems.map(cellHTML).join('') + '</div>';
53
58
  }
54
59
  if (audioItems.length) {
55
- h += audioItems.slice(0, 12).map(audioRowHTML).join('');
60
+ h += audioItems.map(audioRowHTML).join('');
56
61
  }
57
- // Only a fixed page ever renders here (24 visual + 12 audio) — with a library
58
- // in the thousands there was no way to reach the rest short of asking in
59
- // chat. A visible "Load more" turns that into one click; it sends a message
60
- // rather than calling the tool directly, since the widget has no host API
61
- // to invoke a tool itself — same mechanism every other "Use" action here uses.
62
62
  var shown = visualItems.length + audioItems.length;
63
63
  if (sc.total != null && sc.total > shown) {
64
64
  h += '<button class="k-btn" id="load-more" style="width:100%;margin-top:10px">Load more (' +
@@ -145,13 +145,50 @@ function wire() {
145
145
  });
146
146
  var loadMore = el('load-more');
147
147
  if (loadMore) {
148
- loadMore.onclick = function () {
149
- window.kolbo.sendMessage('Show me the next page of this same media search (already saw ' +
150
- (state.items.length) + ' of ' + state.total + ' results).');
151
- };
148
+ loadMore.onclick = function () { fetchNextPage(loadMore); };
152
149
  }
153
150
  }
154
151
 
152
+ // Fetch the next page IN the widget and append it.
153
+ //
154
+ // This used to sendMessage() a request for "the next page of this same media
155
+ // search", on the stated belief that a widget has no way to invoke a tool. It
156
+ // does — window.kolbo.callTool, the same bridge call every generation card
157
+ // polls status with. And the message could not have worked anyway: the payload
158
+ // carried no page number and none of the filters, so the model had nothing to
159
+ // reconstruct the query from and would re-run page 1 or something else. The
160
+ // button appeared to do nothing.
161
+ function fetchNextPage(btn) {
162
+ if (!state || !state.page_tool || btn.disabled) return;
163
+ var next = (state.page || 1) + 1;
164
+ btn.disabled = true;
165
+ var label = btn.textContent;
166
+ btn.innerHTML = '<span class="k-spin"></span> Loading';
167
+ var args = {};
168
+ var q = state.query || {};
169
+ for (var k in q) { if (q[k] !== undefined && q[k] !== null && q[k] !== '') args[k] = q[k]; }
170
+ args.page = next;
171
+ if (state.page_size) args.page_size = state.page_size;
172
+
173
+ window.kolbo.callTool(state.page_tool, args).then(function (res) {
174
+ var sc = structured(res);
175
+ var more = (sc && sc.items) || [];
176
+ if (!more.length) {
177
+ // Nothing came back: say so rather than restoring a button that still
178
+ // looks like it has pages behind it.
179
+ btn.textContent = 'No more results';
180
+ return;
181
+ }
182
+ state.items = (state.items || []).concat(more);
183
+ state.page = (sc && sc.page) || next;
184
+ if (sc && sc.total != null) state.total = sc.total;
185
+ boot(state); // re-renders the grid + a fresh Load more button
186
+ }).catch(function () {
187
+ btn.disabled = false;
188
+ btn.textContent = label;
189
+ });
190
+ }
191
+
155
192
  function useItem(i) {
156
193
  var item = state.items[i];
157
194
  if (!item || !item.id) return;
@@ -851,6 +851,18 @@ async function uiCompleted(p, textPayload, extraContent) {
851
851
  // above which assume everything finished together. Only set when the
852
852
  // caller actually has this shape; every existing caller is unaffected.
853
853
  ...(Array.isArray(p.items) ? { items: p.items } : {}),
854
+ // Transcription payload. get_generation_status is the ONLY way the live
855
+ // transcript widget learns its result, and it reads text/srt_url/txt_url off
856
+ // this object — but uiCompleted is shaped for the generation card and
857
+ // dropped every one, so a finished transcription rendered "(empty
858
+ // transcript)" with no SRT/TXT buttons while the text sat in the status
859
+ // response. structuredContent SHADOWS the text block on widget hosts, so
860
+ // omitting a field here is the same as deleting it.
861
+ ...(typeof p.text === 'string' ? { text: p.text } : {}),
862
+ ...(p.srt_url ? { srt_url: p.srt_url } : {}),
863
+ ...(p.word_by_word_srt_url ? { word_by_word_srt_url: p.word_by_word_srt_url } : {}),
864
+ ...(p.txt_url ? { txt_url: p.txt_url } : {}),
865
+ ...(p.audio_url ? { audio_url: p.audio_url } : {}),
854
866
  // The voice, by name and portrait. uiGenerating has carried this since the
855
867
  // chips were introduced; uiCompleted never did, so it silently dropped a
856
868
  // resolved voice its caller had already looked up — every FINISHED speech
@@ -1118,6 +1118,14 @@ function registerGenerateTools(server, client, options = {}) {
1118
1118
  state: single.state,
1119
1119
  urls: done ? urls : undefined,
1120
1120
  thumbnail_url: res.thumbnail_url,
1121
+ // Transcription results ride the same status tool as media
1122
+ // generations; without these the transcript widget merges a payload
1123
+ // with no transcript in it and renders "(empty transcript)".
1124
+ text: typeof res.text === 'string' ? res.text : undefined,
1125
+ srt_url: res.srt_url || undefined,
1126
+ word_by_word_srt_url: res.word_by_word_srt_url || undefined,
1127
+ txt_url: res.txt_url || undefined,
1128
+ audio_url: res.audio_url || undefined,
1121
1129
  // The refs the server actually conditioned on (reference_details) —
1122
1130
  // the live card merges this payload over its submit-time state, so
1123
1131
  // the finished card shows every reference, including server-side
@@ -303,7 +303,17 @@ function registerMediaTools(server, client, options = {}) {
303
303
  title: 'Media Library',
304
304
  items,
305
305
  total: totalItems != null ? totalItems : media.length,
306
- shown: Math.min(media.length, GRID_CAP)
306
+ shown: Math.min(media.length, GRID_CAP),
307
+ // Everything "Load more" needs to fetch page N+1 ITSELF. The button used
308
+ // to send a chat message asking the model to run the next page, on the
309
+ // belief that a widget cannot invoke a tool — it can
310
+ // (window.kolbo.callTool, the same call every generation card polls
311
+ // with). Worse, the payload carried no page and no filters, so the model
312
+ // could not reconstruct the query either and typically re-ran page 1.
313
+ page_tool: 'list_media',
314
+ page: page || 1,
315
+ page_size: page_size || 50,
316
+ query: { project_id, folder_id, type, category, source_type, sort, search }
307
317
  });
308
318
  }
309
319
  );