@kolbo/mcp 1.79.4 → 1.79.7
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 +1 -1
- package/skill/GENERATED.md +1 -1
- package/skill/SKILL.md +74 -16
- package/skill/references/models/prompt-copilot.md +2 -0
- package/skill/references/models/seedance.md +1 -0
- package/skill/references/models/seedance25.md +1 -1
- package/skill/references/workflows/media-library.md +6 -0
- package/skill/references/workflows/production-log.md +32 -2
- package/skill/references/workflows/production-planning.md +65 -17
- package/skill/references/workflows/prompt-structure.md +131 -0
- package/skill/references/workflows/research-first.md +1 -1
- package/skill/references/workflows/visual-dna.md +17 -6
- package/src/index.js +1 -1
- package/src/tools/media.js +16 -2
- package/src/tools/owned-url.js +13 -0
package/package.json
CHANGED
package/skill/GENERATED.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# AUTO-GENERATED — do not edit
|
|
2
2
|
|
|
3
|
-
This tree is mirrored from kolbo-code@
|
|
3
|
+
This tree is mirrored from kolbo-code@fccda44, 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
|
@@ -24,6 +24,8 @@ You have direct access to the Kolbo AI creative platform via MCP tools (auto-con
|
|
|
24
24
|
|
|
25
25
|
This file is the **always-loaded core**: tool inventory + universal hard rules + routing index. For any model-specific prompt rules, Visual DNA workflow, production log format, marketing workflow, cost validation, etc., **Read the matching `references/` file from the index below**. Don't try to remember the rules — load the file when you need them.
|
|
26
26
|
|
|
27
|
+
Users never see the bundled prompting skills. If you skip them, they get a lazy one-line prompt. **Loading is mandatory, not optional flavor.**
|
|
28
|
+
|
|
27
29
|
## Step 0 — Bootstrap
|
|
28
30
|
|
|
29
31
|
Once per conversation, before any other Kolbo tool call:
|
|
@@ -59,8 +61,8 @@ For multi-scene / batch work this pairs with `generate_creative_director` (see b
|
|
|
59
61
|
|---|---|
|
|
60
62
|
| 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` |
|
|
61
63
|
| Direct, develop, audit, or continue a **film / episode / connected scene / complex performance** with continuity, acting, dialogue, music, blocking, or physics | `references/workflows/filmmaking.md` |
|
|
62
|
-
| Generate a **Seedance 2.5** video | `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 |
|
|
63
|
-
| Generate a **Seedance 2 /
|
|
64
|
+
| 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 |
|
|
65
|
+
| 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 |
|
|
64
66
|
| Generate a **GPT Image 2** image | `references/models/gpt-image.md` |
|
|
65
67
|
| Generate a **Nano Banana / Gemini** image | `references/models/nano-banana.md` |
|
|
66
68
|
| Generate a **Veo 3 / 3.1** video | `references/models/veo.md` |
|
|
@@ -93,7 +95,7 @@ Each `references/models/*.md` mirrors the matching skill prompt in `kolbo-api/sr
|
|
|
93
95
|
### Generation
|
|
94
96
|
| Tool | Description |
|
|
95
97
|
|------|-------------|
|
|
96
|
-
| `generate_image` | Single image from a text prompt. Supports Visual DNA, moodboards, image presets, reference images, web-search grounding.
|
|
98
|
+
| `generate_image` | Single image from a text prompt. Supports Visual DNA, moodboards, image presets (custom instructions live here), reference images, web-search grounding. Named sheets/styles: `list_presets({ type: "image", search: "headless" })` then `preset_id`. |
|
|
97
99
|
| `generate_image_edit` | Edit/transform an existing image. Pass `source_images` + edit prompt. Image-editing presets are supported through `preset_id` from `list_presets({ type: "image_edit" })`. |
|
|
98
100
|
| `generate_creative_director` | **2–8 related images or videos as one coherent set.** Use INSTEAD of multiple `generate_image` calls for any related multi-output. |
|
|
99
101
|
| `generate_video` | Text-to-video. Accepts `visual_dna_ids` and `sound_enabled`; `generate_elements` is still the primary reference-driven route for a DNA-anchored film. |
|
|
@@ -116,7 +118,7 @@ Each `references/models/*.md` mirrors the matching skill prompt in `kolbo-api/sr
|
|
|
116
118
|
| `list_models` / `list_voices` / `check_credits` / `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. |
|
|
117
119
|
| `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. |
|
|
118
120
|
| `create_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` |
|
|
119
|
-
| `list_moodboards` / `get_moodboard` / `list_presets` | Style overlays.
|
|
121
|
+
| `list_moodboards` / `get_moodboard` / `list_presets` | Style overlays + sheet presets. Always pass `search` when you know the name — that is a silent id lookup, not a catalog to show. Never omit `preset_id` after claiming a preset was used. |
|
|
120
122
|
| `list_color_palettes` / `analyze_color_palette` / `create_color_palette` / `update_color_palette` / `delete_color_palette` / `activate_color_palette` / `deactivate_color_palette` | **Color DNA — sticky and account-wide.** At most one palette is active at a time; while it is, it strict-grades **every** image and video generation automatically, with no per-call argument. `analyze_color_palette` pulls colors out of 1-5 image URLs for free and does NOT save. `create_color_palette` defaults `is_active: true`, which activates it and deactivates any other. Per-generation opt-out: `skip_color_palette: true` on `generate_image` / `generate_image_edit` / `generate_video` / `generate_video_from_image`. |
|
|
121
123
|
| `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. |
|
|
122
124
|
| `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. |
|
|
@@ -141,6 +143,10 @@ Passing `visual_dna_ids` is **not enough**. For every DNA in that array you MUST
|
|
|
141
143
|
- Never invent a role label or possessive as a substitute for `@Name`
|
|
142
144
|
- Same rule for moodboards: `#ExactBoardName`
|
|
143
145
|
|
|
146
|
+
**Rewrite / compile never drops a tag.** If the user, a prior prompt, or `list_visual_dnas` already has `@gal_suit` / `@yonatan` / `#Board`, the Locked Intro you write MUST still contain those exact tokens in CAST **and** in every shot they appear in. Do not "clean" them into first names, `@Image 1 (Lee)`, "the singer", or a SCENE CONTEXT / ACTIVE REFERENCES block with no `@`. A compile that loses a tag is a failed turn — put the tags back before calling `generate_*`.
|
|
147
|
+
|
|
148
|
+
Before `generate_elements` / any DNA video: for each id in `visual_dna_ids`, confirm the prompt string includes `@` + that DNA's stored `name`. Missing even one → fix the prompt, do not fire.
|
|
149
|
+
|
|
144
150
|
Resolve names with `list_visual_dnas` first. Full binding rules: `references/workflows/visual-dna.md`.
|
|
145
151
|
|
|
146
152
|
## ⚠️ `enhance_prompt` — leave it OFF (HARD RULE)
|
|
@@ -156,21 +162,47 @@ first, so the model renders *different words than the ones the user wrote*.
|
|
|
156
162
|
user never asked for, and their own wording never reached the model.
|
|
157
163
|
- The default is `false` in every generation tool. Leave the argument out.
|
|
158
164
|
|
|
165
|
+
## ⚠️ Never re-upload a Kolbo URL (HARD RULE)
|
|
166
|
+
|
|
167
|
+
A URL from `generate_*`, `list_media`, `get_media`, or a prior `upload_media` is **already on Kolbo CDN**. Pass that exact URL to the next tool (`reference_images` / `source_images` / `image_url` / `files`). Do **not** call `upload_media`, `create_upload_ticket`, or `media_upload_widget` on it — that copies the file a second time and wastes storage.
|
|
168
|
+
|
|
169
|
+
- Hosts that are already hosted: `media.kolbo.ai`, any `*.kolbo.ai`, Kolbo DigitalOcean Spaces.
|
|
170
|
+
- `upload_media` is only for a **local disk path** or an **external** (non-Kolbo) URL that the tools would 400 on.
|
|
171
|
+
- Same rule after compaction: pull the URL from `.kolbo/production.md` and reuse it. Never download-then-reupload.
|
|
172
|
+
|
|
159
173
|
## ⚠️ Assets Before Shots (HARD RULE)
|
|
160
174
|
|
|
161
|
-
For any film / ad / scene / episode / campaign the order is **Map → Create → Confirm → Shoot
|
|
175
|
+
For any film / ad / scene / episode / campaign the order is **Map → Create → Confirm → Shoot** (the directing guide — load `references/workflows/production-planning.md` + `filmmaking.md` before creating anything). Crack the concept first. Then every character, location, and prop becomes a Visual DNA **from a sheet** (`list_presets` search → `generate_image` with that `preset_id` → `create_visual_dna`). Do **not** register a DNA from a single portrait and skip the sheet. Publish the session plan (`Cast` / `Locations` / `Scene NN — slug`). Get a GATE lock on the asset set. **Only then** video. A shot against an unapproved cast is waste.
|
|
162
176
|
|
|
163
177
|
Scene dialogue is **never** `generate_speech` or `generate_lipsync`. Seedance 2 / 2.5 performs quoted lines written into the shot beat itself — English only. Full flow: `references/workflows/production-planning.md`.
|
|
164
178
|
|
|
179
|
+
## ⚠️ Load the matching skill BEFORE generating (HARD RULE)
|
|
180
|
+
|
|
181
|
+
Do **not** call `generate_*` / `generate_elements` / `generate_image_edit` until you have loaded the matching skill **in this turn** (the `skill` tool for bundled skills, and/or Read of the `references/` file). "I already know this" is not a load. Users will never invoke these skills themselves.
|
|
182
|
+
|
|
183
|
+
| About to call / user intent | `skill` tool | Also Read |
|
|
184
|
+
|---|---|---|
|
|
185
|
+
| `generate_elements` **or** any video with Visual DNA **or** Seedance 2 / 2.5 / WAN / MiniMax H3 / Gemini video | `elements-prompting` | `references/models/seedance.md` (+ `seedance25.md` if 2.5) and `references/workflows/visual-dna.md` when DNA is in play |
|
|
186
|
+
| `generate_image` / `generate_image_edit` | `image-prompting-guide` | `references/models/gpt-image.md` / `nano-banana.md` / `prompt-copilot.md` as the model requires. Complex stills / identity lock: `references/workflows/prompt-structure.md` |
|
|
187
|
+
| `generate_video*` that is **not** Elements/DNA (Kling, Veo, Sora, Grok, Hailuo, generic t2v/i2v) | `video-prompting-guide` | matching `references/models/*.md` |
|
|
188
|
+
| `generate_music` | `music-prompting` | `references/models/music.md` |
|
|
189
|
+
| UGC / phone-shot / selfie / "authentic" / must-not-look-like-an-ad | — | `references/workflows/ugc-smartphone.md` |
|
|
190
|
+
| Marketing / TV spot / branded video / unboxing / product review | — | `references/workflows/marketing-studio.md` |
|
|
191
|
+
| DTC ad image | — | `references/workflows/dtc-ads.md` |
|
|
192
|
+
| Product photoshoot / hero / lifestyle / try-on | — | `references/workflows/product-photoshoot.md` |
|
|
193
|
+
| Thumbnail / cover | — | `references/workflows/thumbnails.md` |
|
|
194
|
+
| Marketplace listing cards | — | `references/workflows/marketplace-cards.md` |
|
|
195
|
+
| Film / episode / connected scene | — | `references/workflows/filmmaking.md` + `production-planning.md` |
|
|
196
|
+
|
|
165
197
|
## ⚠️ Seedance / Elements prompt contract (HARD RULE)
|
|
166
198
|
|
|
167
|
-
`generate_elements`, Seedance 2
|
|
199
|
+
`generate_elements`, Seedance 2 / 2.5, WAN, MiniMax H3, Gemini, and any Visual DNA video share **one** compile shape — the Locked Intro in `references/models/seedance.md`. Load `elements-prompting` first (craft, `@Image N` mapping, eight elements), then compile:
|
|
168
200
|
|
|
169
201
|
`Total: Xs / N shots / AR` → `[GLOBAL LOOK – LOCKED, APPLIES TO EVERY SHOT]` → `[CAST – IDENTICAL IN EVERY SHOT]` (each person is `@DNAName`) → `[LOCATION]` → `SHOT N — 0:00–0:02 — …`
|
|
170
202
|
|
|
171
203
|
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.
|
|
172
204
|
|
|
173
|
-
Do **not** default Elements to `SCENE CONTEXT` / `OPTICS` / `ACTION` / `ACTIVE REFERENCES` department packs (those live in filmmaking audit/contracts for other models).
|
|
205
|
+
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.
|
|
174
206
|
|
|
175
207
|
## ⚠️ If the User Names a Tool, USE THAT TOOL (HARD RULE)
|
|
176
208
|
|
|
@@ -201,19 +233,24 @@ A user-named tool — in any language — overrides every other rule. Recognized
|
|
|
201
233
|
|
|
202
234
|
## Core Workflow
|
|
203
235
|
|
|
204
|
-
**Preset contract:**
|
|
236
|
+
**Preset contract:**
|
|
237
|
+
- Custom instructions live on the **preset**. Prefer `generate_image` + `preset_id` (not `generate_character_sheet`) for Character Sheet / Headless / Bible / location / product sheets.
|
|
238
|
+
- 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.
|
|
239
|
+
- Browse (no search) only when the user asked to see presets.
|
|
240
|
+
- Pass the exact returned `id` as `preset_id`. Never invent an id.
|
|
205
241
|
|
|
206
242
|
1. **Check credits** ONCE per conversation (Step 0). Skip if already checked.
|
|
207
|
-
2. **
|
|
208
|
-
3. **
|
|
243
|
+
2. **Load the matching skill** (HARD RULE above) — `skill` tool + Read the `references/` file. Do this before the first paid call in the turn.
|
|
244
|
+
3. **Discover models** with `list_models` using a `type` filter — but **skip when the user names a specific model** (this turn **or** earlier in the conversation / compaction `## Locked choices`).
|
|
245
|
+
4. **Pick the model**:
|
|
209
246
|
- User named one → that name is a **family lock**, not a single catalog row. Use it. Identifiers resolve leniently — `"z-image"` / `"nano banana 2"` / `"grok imagine"` auto-resolve, including to the sibling for the tool you are calling (`grok-imagine-text-to-video` on `generate_video_from_image` becomes `grok-imagine-image-to-video`). `list_models` is still authoritative for constraints, caps, and pricing — not for swapping brands.
|
|
210
247
|
- **Never cheapest-swap a named family.** After compaction, "animate those images" is still Grok if the user said Grok. Seedance / Kling / Veo are not a "best balance" substitute. If the named family has no variant for this modality, ASK — do not silently switch.
|
|
211
248
|
- Auto-select → **only when no model was named on this task**. Then pick from "Auto-selectable" (models with a `summary`). Cheapest fit. Prefer `[RECOMMENDED]` when cost is similar.
|
|
212
249
|
- Never auto-select from "Named-only" section.
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
250
|
+
5. **Validate inputs** against model caps — see `references/workflows/cost-and-validation.md`.
|
|
251
|
+
6. **How calls work**: each tool blocks until generation is fully complete. Images: seconds. Video: minutes. Multiple tool calls in one response run concurrently. On hosts with live widgets the tool instead returns `submitted` instantly — the card updates on its own; you only need `get_generation_status` when a follow-up step needs the output URLs.
|
|
252
|
+
7. **Checking status — NEVER poll in a loop**: `get_generation_status` takes `wait=true` (blocks server-side until done, ~3 min) and `generation_ids` (check MANY generations in ONE call — returns `all_done` + which are still running). One `wait=true` call replaces any polling loop. If it comes back with some still processing, call it ONCE more with `wait=true` and the remaining ids.
|
|
253
|
+
8. **Share the URL** after success. Never fabricate URLs.
|
|
217
254
|
|
|
218
255
|
Model types for `list_models`: `text_to_img`, `image_editing`, `text_to_video`, `img_to_video`, `draw_to_video`, `video_to_video`, `elements`, `firstlastgenerations`, `lipsync-image`, `lipsync-video`, `music_gen`, `text_to_speech`, `text_to_sound`, `stt`, `text`, `3d_text_to_model`, `3d_image_to_model`, `3d_multi_image_to_model`, `3d_world`.
|
|
219
256
|
|
|
@@ -225,6 +262,27 @@ Everything in Kolbo — sessions, generations, media, docs — lives inside a PR
|
|
|
225
262
|
2. **No project mentioned** → omit `project_id`; the default bucket is correct. Don't ask unless intent is ambiguous. If `list_sessions` already returned a `project_id` for the work you are continuing, keep passing that id.
|
|
226
263
|
3. **Work landed in the wrong project? MOVE it, never regenerate**: `move_session` relocates a whole session + all its media (works for any session type — the `session_id` from generation responses, chats, transcriptions); `move_media` / `bulk_move_media` / `move_folder_contents` relocate individual media items. Empty leftover sessions after a move: `delete_session` (soft-delete; `restore_session` undoes it). `rename_session` only changes the sidebar title.
|
|
227
264
|
|
|
265
|
+
## ⚠️ One session per plan bucket (HARD RULE)
|
|
266
|
+
|
|
267
|
+
Omitting `session_id` on a generate call creates a **new** Kolbo sidebar session. Do that only when the **plan** starts a new bucket — not per take, not per shot, not because you just called a tool.
|
|
268
|
+
|
|
269
|
+
Name buckets from the plan you already showed the user, then `rename_session` on first create:
|
|
270
|
+
|
|
271
|
+
| Bucket | What lives in it | Kind |
|
|
272
|
+
|---|---|---|
|
|
273
|
+
| `Cast` | every character sheet / character DNA | image |
|
|
274
|
+
| `Locations` | every environment | image |
|
|
275
|
+
| `Props` | hero products / vehicles (if any) | image |
|
|
276
|
+
| `Scene NN — <slug>` | that scene's video shots **and** retakes | video |
|
|
277
|
+
|
|
278
|
+
How to thread:
|
|
279
|
+
|
|
280
|
+
1. First generate of a bucket → omit `session_id`, read it from the result, immediately `rename_session` to the plan name (`Cast`, `Locations`, `Scene 03 — rooftop chase`).
|
|
281
|
+
2. Every later generate in that bucket (more characters, another environment, shot 2, "make it darker", redo take 3) → pass that **same** `session_id`.
|
|
282
|
+
3. New scene or new concept → new session. Same scene / same cast pass → never a new session.
|
|
283
|
+
4. Image tools and video tools cannot share an id (server kinds differ). Cast/Locations stay image; scene clips stay video.
|
|
284
|
+
|
|
285
|
+
Write each session's `session_id` + plan name into `.kolbo/production.md` `### Sessions`. Do **not** mark the phase Approved or jump to the next bucket until the user confirms (or you asked a labeled GATE and they answered). Full rules: `references/workflows/production-planning.md` + `production-log.md`.
|
|
228
286
|
|
|
229
287
|
## Cost Awareness — Quick Rules
|
|
230
288
|
|
|
@@ -244,7 +302,7 @@ Full tables + formulas in `references/workflows/cost-and-validation.md`. Quick r
|
|
|
244
302
|
- **Tracking a batch**: check ALL in-flight ids in ONE `get_generation_status` call with `generation_ids` + `wait=true`. Read `all_done` / `still_processing` from the response — do not check ids one by one, and never re-call without `wait`.
|
|
245
303
|
- **Batch ≤10 items**: output ALL tool calls in one response — they run concurrently.
|
|
246
304
|
- **Bulk >10 items**: real-world ceilings — `generate_image` 8–10 in-flight, image-edit 5–8, video tools 3–5, `generate_video_from_video` 3, music/speech/sound 5–8. Fire one batch → wait → fire next. Persist every `generation_id` in `.kolbo/production.md`.
|
|
247
|
-
- **`upload_media` external URLs
|
|
305
|
+
- **`upload_media` external (non-Kolbo) URLs only.** `files`/`source_images`/`image_url` reject unknown hosts with `400`. A `media.kolbo.ai` / generate_* URL is already hosted — pass it through. Never `upload_media` a Kolbo URL.
|
|
248
306
|
|
|
249
307
|
## ⚠️ Multi-output? Default to `generate_creative_director` (CRITICAL)
|
|
250
308
|
|
|
@@ -315,7 +373,7 @@ Avoid bare URL dumps and HTML `<table>` grids — canvas already provides a gall
|
|
|
315
373
|
|
|
316
374
|
**After `generate_creative_director` completes** — share results as individual URLs, one per scene. Do NOT create an HTML grid artifact.
|
|
317
375
|
|
|
318
|
-
**Always**
|
|
376
|
+
**Always** park every successful URL + `session_id` in `.kolbo/production.md` as a **candidate**. Promote to Approved and advance the plan only after the user confirms — see `references/workflows/production-log.md`.
|
|
319
377
|
|
|
320
378
|
## Limitations & Safety
|
|
321
379
|
|
|
@@ -40,6 +40,8 @@ Always call `list_models({ type: "<tool-type>" })` first when the user hasn't na
|
|
|
40
40
|
|
|
41
41
|
## Universal Rules
|
|
42
42
|
|
|
43
|
+
- **Keep every `@DNA` / `#Moodboard` / `@ImageN` token.** Same contract as the Kolbo help widget: tag EVERY referenced asset in the prompt text (exact `@DNA_name`, `@ImageN`, `#Name` — an untagged reference is silently dropped). The tag stays the canonical subject name in every shot. Never replace it with a nickname, role label, or pronoun. Rewriting a user prompt and losing `@yonatan` is a failed turn.
|
|
44
|
+
- When the output is **one video** and the user has Visual DNA / several refs / "keep him consistent", write an **Elements** prompt (not a still, not Creative Director). Elements is video-only.
|
|
43
45
|
- **Clean prompts only.** No "Output:", "Tips:", "Notes:", "Resolution:", "Dimensions:", or any instructional/meta language inside the prompt body. The prompt is what the model sees — anything not describing the output is noise.
|
|
44
46
|
- **Resolution / aspect ratio / duration are MCP-tool params**, not prompt text. Pass them as separate fields on the tool call.
|
|
45
47
|
- **Match prompt length to complexity**: focused 2–3 sentences beats a bloated paragraph for simple cases; only go longer when the concept genuinely needs it. Aim for **under ~200 tokens** — long prompts distort.
|
|
@@ -14,6 +14,7 @@ Load this file when the user wants a **Seedance 2 / Seedance 2.0** (ByteDance) v
|
|
|
14
14
|
## Universal Rules (apply to EVERY Seedance / Elements prompt)
|
|
15
15
|
|
|
16
16
|
- **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
|
+
- **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.
|
|
17
18
|
- **First line ALWAYS declares shot structure**: total duration, shot count, aspect ratio. Example: `Total: 15s / 6 shots / 16:9`. Put it at the BOTTOM of the prompt too. For connected narrative sequences the proven phrasing is `N connected cinematic shots, 15 seconds total, 16:9, Multishot ON` — use it and keep `Multishot ON` for any multi-shot story.
|
|
18
19
|
- **Then the Locked Intro** — `[GLOBAL LOOK]` / `[CAST]` / `[LOCATION]` — before any shot. A one-liner `same character throughout` is not a character lock.
|
|
19
20
|
- **Order inside each shot**: Subject → Action → Camera → Constraints → (Audio/SFX if relevant). Do NOT restack GLOBAL LOOK style inside the shot.
|
|
@@ -20,7 +20,7 @@ Load this file when the user wants a **Seedance 2.5** video (they said "2.5" / "
|
|
|
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
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.
|
|
23
|
-
- **Up to 50 reference medias / Visual DNA mentions** (`@Name`, `@ImageN`, `#Moodboard`). Every referenced asset must be tagged in the prompt text.
|
|
23
|
+
- **Up to 50 reference medias / Visual DNA mentions** (`@Name`, `@ImageN`, `#Moodboard`). 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
25
|
|
|
26
26
|
## Locked Intro (DEFAULT — same shape as Seedance 2)
|
|
@@ -4,6 +4,12 @@ Load this file when the user wants to browse, list, organize, delete, restore, m
|
|
|
4
4
|
|
|
5
5
|
The library covers both **uploaded files** and **AI-generated outputs the user has saved**. Tools fall into five groups: ingest, browse, lifecycle (delete/restore/move), folders, and favorites.
|
|
6
6
|
|
|
7
|
+
## ⚠️ Already-hosted URLs — never re-upload
|
|
8
|
+
|
|
9
|
+
`generate_*` / `list_media` / `get_media` / a prior `upload_media` already return a Kolbo CDN URL (`media.kolbo.ai`, `*.kolbo.ai`, Spaces). Pass that exact URL into the next generation tool. Calling `upload_media` on it duplicates the file.
|
|
10
|
+
|
|
11
|
+
`upload_media` is only for a local path or an external (non-Kolbo) URL. If you already have a Kolbo URL, skip ingest.
|
|
12
|
+
|
|
7
13
|
## ⚠️ Present locally-produced media to the user
|
|
8
14
|
|
|
9
15
|
When you produce a media file LOCALLY — `ffmpeg` via the `video-production` skill, Remotion render, manual `Bash` mux of audio + video, `edit_image` outputs saved to disk, any save-to-file flow — make sure the user can actually find and open it. Local files are invisible in the chat / canvas UI by default; only the path string makes it through.
|
|
@@ -32,10 +32,25 @@ The log records **what the user approved** — not everything you produced. Gett
|
|
|
32
32
|
Say plainly which ones are in play, e.g. "created `@maya` and `@maya_alt` — here they are".
|
|
33
33
|
3. **Ask for a decision** and name the options ("keep the first, redo the second, or both?").
|
|
34
34
|
4. **Repeat** until the user is satisfied. Log nothing as approved during this stage.
|
|
35
|
-
5. **On approval →
|
|
35
|
+
5. **On approval → promote in `.kolbo/production.md` immediately**, in the same turn: move the winner out of Candidates, update `**Approved:**`, then you may start the next plan bucket. Do not advance `**Now working on:**` to the next phase before this.
|
|
36
36
|
|
|
37
37
|
**Never write an artifact into the log as approved without the user's approval.**
|
|
38
38
|
|
|
39
|
+
If they did not volunteer a yes, end the turn with a **GATE** the next message can
|
|
40
|
+
parse (same contract as `production-planning.md`):
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
GATE — <bucket name>
|
|
44
|
+
Presented: <what is in play>
|
|
45
|
+
Lock + next: "lock <bucket>" / "yes" / "next" / "now <next bucket>"
|
|
46
|
+
Stay: "redo @name" / "another take of …"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Confirmation the agent may treat as a lock: `yes`, `ok`, `lock`, `approved`,
|
|
50
|
+
`that's the one`, `use take 2`, `next`, `go`, `continue`, or they name the next
|
|
51
|
+
planned bucket while treating this set as done. Silence / "maybe" / a new
|
|
52
|
+
question is **not** a lock — repeat the GATE once, do not invent a yes.
|
|
53
|
+
|
|
39
54
|
**If the user genuinely doesn't care** — "whatever you think", "you pick", "don't care", or they hand you the whole job — then **you decide**. Choose, say in one line which you picked and why, and log it as usual with `(agent-selected)`. Do not stall a production waiting for an approval the user has already delegated to you.
|
|
40
55
|
|
|
41
56
|
**Don't lose candidate URLs while iterating.** Recording a candidate is not the same as claiming approval, and compaction will eat unlogged URLs. Park in-flight takes under a `#### Candidates (pending approval)` bullet, and on approval promote the winner to a normal entry and mark the rest `(rejected)`:
|
|
@@ -59,7 +74,12 @@ after the user picks take 2:
|
|
|
59
74
|
|
|
60
75
|
## When to WRITE to it
|
|
61
76
|
|
|
62
|
-
|
|
77
|
+
Two writes, different jobs:
|
|
78
|
+
|
|
79
|
+
1. **Right after a successful generate** — park the URL, `generation_id`, `credits_used`, and `session_id` under `#### Candidates (pending approval)` and under `### Sessions` if this is the first shot of a new bucket. Rewrite `## 🎯 Now` only for `**Awaiting approval:**` / the current bucket. This is what the runtime reminder is asking for. It is **not** approval.
|
|
80
|
+
2. **After the user locks the bucket** — promote the winner, mark rejects, update `**Approved:**`, then you may change `**Now working on:**` to the next planned bucket.
|
|
81
|
+
|
|
82
|
+
Where there is no production (user asked for one throwaway image and got it, or said "you pick") — approval is implicit and you log the finished entry right away. A film / ad / scene plan is never that case.
|
|
63
83
|
|
|
64
84
|
Tools that REQUIRE logging:
|
|
65
85
|
- `generate_image`, `generate_image_edit`, `edit_image`
|
|
@@ -95,12 +115,14 @@ Stub for first creation:
|
|
|
95
115
|
**Now working on:** <the immediate next step>
|
|
96
116
|
**Approved:** <locked assets — DNAs, moodboards, scenes; "nothing yet" if still iterating>
|
|
97
117
|
**Awaiting approval:** <what you've presented and are waiting on; omit when nothing is pending>
|
|
118
|
+
**Sessions:** <plan names + ids — Cast / Locations / Scene 01 — …; "none yet" until first generate>
|
|
98
119
|
**Last updated:** <ISO date>
|
|
99
120
|
|
|
100
121
|
---
|
|
101
122
|
|
|
102
123
|
## Production: <name from user's request, slugified human label>
|
|
103
124
|
|
|
125
|
+
### Sessions
|
|
104
126
|
### Cast
|
|
105
127
|
### Visual DNA
|
|
106
128
|
### Scenes
|
|
@@ -115,10 +137,17 @@ Subsections (`### Cast` etc.) are **suggested defaults**, not required. Adapt: a
|
|
|
115
137
|
One bullet per artifact. Write the label **the way the user would reference it next time** ("the rainy one"), not the model's raw output.
|
|
116
138
|
|
|
117
139
|
```md
|
|
140
|
+
### Sessions
|
|
141
|
+
- **Cast** — sess_abc (image) — @maya @doron
|
|
142
|
+
- **Locations** — sess_def (image) — @night_market
|
|
143
|
+
- **Scene 01 — coffee shop** — sess_ghi (video) — shots 1–4
|
|
144
|
+
- **Scene 02 — rooftop chase** — (pending)
|
|
145
|
+
|
|
118
146
|
### Cast
|
|
119
147
|
- **Maya** — female, 30, urban photographer, leather jacket
|
|
120
148
|
- portrait: https://...characters/maya.png (nano-banana-2, 2026-05-13)
|
|
121
149
|
- visual DNA: vdna_8f2c (@maya)
|
|
150
|
+
- session: sess_abc
|
|
122
151
|
|
|
123
152
|
### Scenes
|
|
124
153
|
1. **Coffee shop morning** — Maya at counter, soft light, wide shot
|
|
@@ -152,6 +181,7 @@ When a user request supersedes a previous artifact (e.g., "redo scene 2 with mor
|
|
|
152
181
|
6. **One file per workspace.** Multiple concurrent productions go under separate `## Production: <name>` headings inside the same file.
|
|
153
182
|
7. **Approved state is user-granted, never assumed.** A generation succeeding is not approval. Only the user's "yes" — or their explicit delegation of the choice to you — promotes a candidate to an approved entry. Silence is not approval; neither is the user moving on to another topic.
|
|
154
183
|
8. **The `## 🎯 Now` block names what is locked.** Keep an `**Approved:**` line there listing the currently-approved cast, DNAs, moodboards, and scenes, so the approved state survives compaction and is the first thing you read next session.
|
|
184
|
+
9. **Sessions are part of the log.** Every bucket from the plan gets a `### Sessions` row (name from the plan, `session_id`, kind, which `@tags` / scene it holds). After the first generate of a bucket, `rename_session` to that plan name and write the id. Reuse that id — do not spawn untitled sessions for retakes.
|
|
155
185
|
|
|
156
186
|
## Bulk Generation Entry Shape
|
|
157
187
|
|
|
@@ -14,10 +14,10 @@ that has to match anything else.
|
|
|
14
14
|
|
|
15
15
|
## The order is not negotiable
|
|
16
16
|
|
|
17
|
-
1. **Map** every element the script needs.
|
|
18
|
-
2. **Create** each one as an
|
|
19
|
-
3. **Confirm**
|
|
20
|
-
4. **Only then** compile shots and generate video.
|
|
17
|
+
1. **Map** every element the script needs — including the **session plan** (names).
|
|
18
|
+
2. **Create** each one as an asset (Visual DNA), grouped into the planned sessions.
|
|
19
|
+
3. **Confirm** that bucket with the user. Do not start the next bucket until they lock this one.
|
|
20
|
+
4. **Only then** compile shots and generate video (one session per scene).
|
|
21
21
|
|
|
22
22
|
Generating video before step 3 is how a production ends up with a different face
|
|
23
23
|
in every shot and a re-shoot bill. A shot generated against an unapproved cast is
|
|
@@ -39,6 +39,30 @@ State the inventory back to the user as a list with counts and cost before
|
|
|
39
39
|
creating anything. A 4-character, 2-location, 1-prop film is 7 assets, not "some
|
|
40
40
|
characters".
|
|
41
41
|
|
|
42
|
+
Also publish the **session plan** in that same MAP reply — exact sidebar titles
|
|
43
|
+
you will `rename_session` to. Default buckets:
|
|
44
|
+
|
|
45
|
+
| Session name | Kind | Contents |
|
|
46
|
+
|---|---|---|
|
|
47
|
+
| `Cast` | image | all character sheets / character DNAs |
|
|
48
|
+
| `Locations` | image | all environments |
|
|
49
|
+
| `Props` | image | hero products / vehicles (omit if none) |
|
|
50
|
+
| `Scene 01 — <slug>` | video | every shot and retake of that scene |
|
|
51
|
+
| `Scene 02 — <slug>` | video | next scene |
|
|
52
|
+
|
|
53
|
+
Slugs come from the plan (`Scene 01 — coffee shop`, `Scene 03 — rooftop chase`),
|
|
54
|
+
not generic "API Generations" or "Untitled". One video session **per scene**;
|
|
55
|
+
shots live inside it. A new session is a new scene or a new concept — never a
|
|
56
|
+
new take.
|
|
57
|
+
|
|
58
|
+
Omitting `session_id` on generate creates a new session. First call of a bucket
|
|
59
|
+
omits it, then `rename_session` immediately; every later call in that bucket
|
|
60
|
+
passes the same id. Image and video kinds cannot share an id.
|
|
61
|
+
|
|
62
|
+
Write those planned names into `.kolbo/production.md` `### Sessions` as
|
|
63
|
+
`(pending)` during MAP. Fill in the real `session_id` when the first generate
|
|
64
|
+
returns. See `production-log.md`.
|
|
65
|
+
|
|
42
66
|
Separate **states** from **identities**: clean vs bloodied, day vs night, intact
|
|
43
67
|
vs broken are their own assets. Do not expect one DNA to carry both.
|
|
44
68
|
|
|
@@ -58,26 +82,50 @@ Read the matching prompt reference before writing an asset prompt:
|
|
|
58
82
|
for GPT Image 2. There is no Mirage reference file — prompt it as a plain cinematic
|
|
59
83
|
still.
|
|
60
84
|
|
|
61
|
-
|
|
62
|
-
|
|
85
|
+
Resolve the sheet **preset** (custom instructions live there):
|
|
86
|
+
`list_presets({ type: "image", search: "bible" | "headless" | "character sheet" })`
|
|
87
|
+
then `generate_image` with that `preset_id`. Do not dump the catalog — always
|
|
88
|
+
pass `search`.
|
|
63
89
|
|
|
64
|
-
- `
|
|
65
|
-
- `
|
|
66
|
-
- `
|
|
67
|
-
- `
|
|
68
|
-
- `product` — angles plus material and construction close-ups
|
|
69
|
-
- `style` — one look applied across six varied subjects
|
|
90
|
+
- `bible` — lead or anyone with a lot of detail (default when in doubt)
|
|
91
|
+
- `headless` — body / wardrobe / instrument; face already locked
|
|
92
|
+
- `character sheet` — simple supporting role
|
|
93
|
+
- `location` / `product` — matching DNA type
|
|
70
94
|
|
|
71
|
-
|
|
72
|
-
|
|
95
|
+
Sheets are **2K or 4K** (never 1K). Default 2K; 4K for bible / high-detail / when
|
|
96
|
+
the user names 4K or GPT Image 2.
|
|
97
|
+
|
|
98
|
+
Do not skip the sheet and `create_visual_dna` from a portrait. The sheet is the
|
|
99
|
+
asset; the DNA stores it.
|
|
73
100
|
|
|
74
101
|
Then `create_visual_dna` with the sheet as the reference and the matching
|
|
75
102
|
`dna_type`. Name each DNA in the exact form it will be tagged with later.
|
|
76
103
|
|
|
77
|
-
## 3. Confirm
|
|
104
|
+
## 3. Confirm — a labeled GATE, then wait
|
|
105
|
+
|
|
106
|
+
Show the user what this bucket produced and **stop**. Do not start Locations
|
|
107
|
+
while Cast is still iterating. Do not shoot while assets are unapproved.
|
|
108
|
+
Do not rewrite `## 🎯 Now` to the next phase until the gate is answered.
|
|
109
|
+
|
|
110
|
+
If they do not volunteer a yes, end the turn with a GATE the next message can
|
|
111
|
+
parse — not a vague "looks good?":
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
GATE — Cast
|
|
115
|
+
Presented: @maya, @doron (candidates in the log)
|
|
116
|
+
Lock + next: "lock cast" / "yes" / "next" / "now locations"
|
|
117
|
+
Stay: "redo @maya" / "another take of the leather jacket"
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Treat as confirmation: `yes`, `ok`, `lock`, `approved`, `that's the one`,
|
|
121
|
+
`use take 2`, `next`, `go`, `continue`, or they name the **next** bucket
|
|
122
|
+
("now do environments", "shoot scene 1") while treating the current set as done.
|
|
123
|
+
|
|
124
|
+
Not confirmation: silence, "maybe", a question about something else, another
|
|
125
|
+
take request. Ask the GATE again once; do not invent a yes.
|
|
78
126
|
|
|
79
|
-
|
|
80
|
-
the
|
|
127
|
+
On lock: promote candidates → Approved in `.kolbo/production.md`, then start
|
|
128
|
+
the next planned bucket in **its** session.
|
|
81
129
|
|
|
82
130
|
## 4. Shoot
|
|
83
131
|
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
<!-- Schema and preserve-vocabulary distilled from patterns observed across a
|
|
2
|
+
22,000-prompt open corpus (YouMind-OpenLab/ai-image-prompts-skill, MIT).
|
|
3
|
+
Patterns and field frequencies only — no prompt text or assets were copied. -->
|
|
4
|
+
|
|
5
|
+
# Prompt Structure — Structured Blocks, Reference Contracts, Reusable Templates
|
|
6
|
+
|
|
7
|
+
Load this file when a still-image request is **complex** (many elements that must all
|
|
8
|
+
land), an **edit that must not drift**, or a **template the user will run more than once**.
|
|
9
|
+
|
|
10
|
+
Simple asks do not need any of this. "A watercolor cat on a windowsill" is a finished
|
|
11
|
+
prompt — structure added to a simple request just gives the model more surface to
|
|
12
|
+
misread. Reach for these three tools only when the picture has parts that fight.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 1. Structured blocks — for complex scenes
|
|
17
|
+
|
|
18
|
+
When a single paragraph has to carry a subject, a wardrobe, a pose, an environment, a
|
|
19
|
+
light setup and a camera, prose starts losing elements. Break it into labelled blocks so
|
|
20
|
+
each one is independently checkable. This is the schema that recurs across thousands of
|
|
21
|
+
working prompts, in frequency order — use the blocks the picture needs, skip the rest:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
output_goal: one sentence — what the finished image IS
|
|
25
|
+
subject: identity, expression, pose, wardrobe, accessories
|
|
26
|
+
environment: location, background, props, atmosphere
|
|
27
|
+
lighting: type, direction, quality, mood
|
|
28
|
+
camera: shot size, lens, angle, focus, depth of field
|
|
29
|
+
composition: framing, subject placement, negative space
|
|
30
|
+
style: medium, rendering, colour palette, reference era
|
|
31
|
+
negative: what must NOT appear
|
|
32
|
+
aspect_ratio: the target canvas
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Rules that make it work rather than just look organised:
|
|
36
|
+
|
|
37
|
+
- **`output_goal` first, one sentence.** It is the model's summary of intent, and it
|
|
38
|
+
catches briefs that contradict themselves before you write 400 words.
|
|
39
|
+
- **One fact per field.** `"lighting": "hard noon sun from camera-left, deep short
|
|
40
|
+
shadows"` — not a paragraph.
|
|
41
|
+
- **Nest only where it earns it.** `subject.hair`, `subject.expression`, `subject.pose`
|
|
42
|
+
are worth splitting when they matter; otherwise keep `subject` flat.
|
|
43
|
+
- **`negative` is a real field, not a mood.** Name objects and treatments to exclude
|
|
44
|
+
("no text, no watermark, no extra fingers, no lens flare"), not qualities to avoid.
|
|
45
|
+
- **Never restate a block's content inside another block.** Style written into every
|
|
46
|
+
field is how a picture ends up over-styled and identical in every region.
|
|
47
|
+
- JSON-ish, YAML-ish or plain labelled lines all work. Pick one and stay in it.
|
|
48
|
+
|
|
49
|
+
## 2. The reference contract — how an edit stops drifting
|
|
50
|
+
|
|
51
|
+
This is the highest-value pattern in the file. "Keep everything else the same" is too
|
|
52
|
+
vague to hold, and it is why a chain of edits quietly turns a person into someone else.
|
|
53
|
+
An edit prompt opens with an explicit contract:
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
reference_image:
|
|
57
|
+
use_uploaded_image: true
|
|
58
|
+
identity_lock: face_only | full_subject | product | scene | none
|
|
59
|
+
preserve: [ <the exact properties that must survive> ]
|
|
60
|
+
edit_scope: <the ONE thing that changes>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**`identity_lock` says how much is frozen:**
|
|
64
|
+
|
|
65
|
+
| Mode | What travels | Typical use |
|
|
66
|
+
|---|---|---|
|
|
67
|
+
| `face_only` | the face, nothing else | put this person in a new scene, outfit or style |
|
|
68
|
+
| `full_subject` | face, body, wardrobe | same person, same clothes, new environment |
|
|
69
|
+
| `product` | the object's design | the product in a new setting or lighting |
|
|
70
|
+
| `scene` | the environment | same room, different subject |
|
|
71
|
+
| `none` | nothing — a style reference only | borrow a look, not a thing |
|
|
72
|
+
|
|
73
|
+
**`preserve` is a list of properties, never an adjective.** Name what actually drifts,
|
|
74
|
+
in the order it drifts:
|
|
75
|
+
|
|
76
|
+
- **People** — facial bone structure, nose shape, eye spacing, jawline, hairline and
|
|
77
|
+
hairstyle, skin tone and texture, expression, body proportions.
|
|
78
|
+
- **Products** — label artwork, typography, logo placement, colours, proportions,
|
|
79
|
+
closure or cap, material finish.
|
|
80
|
+
- **Scenes** — camera angle, layout, background objects, lighting direction.
|
|
81
|
+
|
|
82
|
+
**The edit-scope field names ONE change.** "Change only the background to a night street." A
|
|
83
|
+
prompt that re-describes the whole picture is a re-generation, and the model will
|
|
84
|
+
re-imagine exactly the parts you wanted frozen.
|
|
85
|
+
|
|
86
|
+
**Restate the whole contract on every iteration.** Drift is cumulative — the third edit
|
|
87
|
+
in a chain is where the face goes. Never write "same as before".
|
|
88
|
+
|
|
89
|
+
Two more invariants worth stating outright: natural anatomy must stay accurate, and a
|
|
90
|
+
preserved object keeps its true scale relative to hands and surfaces.
|
|
91
|
+
|
|
92
|
+
If the user has not uploaded anything, there is no reference contract to write — that is
|
|
93
|
+
a from-scratch generation, and `text_to_image` is the tool.
|
|
94
|
+
|
|
95
|
+
## 3. Reusable templates — named slots
|
|
96
|
+
|
|
97
|
+
When the user wants a recipe rather than one picture ("for every product", "every
|
|
98
|
+
episode cover", "swap the character"), write the prompt once and mark the variable parts
|
|
99
|
+
as named slots carrying a working default:
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
{argument name="product name" default="the serum bottle"}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
- Slot only what changes per run — subject, product name, on-image text, brand colour,
|
|
106
|
+
setting. Everything else stays literal, which is what makes the look reproducible.
|
|
107
|
+
- **Every slot needs a default that actually renders**, so the template works unfilled.
|
|
108
|
+
- Name slots for what they are — `"hero headline"`, `"character identity"` — never
|
|
109
|
+
`var1`.
|
|
110
|
+
- **Reuse one slot name everywhere that value appears.** A nine-frame storyboard that
|
|
111
|
+
names the product in four frames uses one slot four times, not four slots.
|
|
112
|
+
- A variation set is one template plus a single stated variation axis (angle, mood,
|
|
113
|
+
palette). Vary that axis only — a set whose look drifts between frames is not a set.
|
|
114
|
+
- Deliver the filled version and say which slots to swap next time.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Which tool for which ask
|
|
119
|
+
|
|
120
|
+
| The ask | Reach for |
|
|
121
|
+
|---|---|
|
|
122
|
+
| One simple picture | none of this — write good prose |
|
|
123
|
+
| Many elements that must all land | structured blocks |
|
|
124
|
+
| Editing an upload; identity must survive | reference contract (+ blocks if complex) |
|
|
125
|
+
| "I'll run this again for each X" | named slots |
|
|
126
|
+
| A set of variations | one template + one variation axis |
|
|
127
|
+
|
|
128
|
+
Related: `workflows/ugc-smartphone.md` for the phone-shot look (its product rules are the
|
|
129
|
+
reference contract applied to packaging), `workflows/visual-dna.md` for locking identity
|
|
130
|
+
across many generations rather than one edit, and `models/gpt-image.md` /
|
|
131
|
+
`models/nano-banana.md` for per-model phrasing.
|
|
@@ -45,7 +45,7 @@ Extract from this page, in compact bullets:
|
|
|
45
45
|
|
|
46
46
|
## Re-host every external image via `upload_media`
|
|
47
47
|
|
|
48
|
-
The bulk-API rule applies: external URLs in `reference_images` / `source_images` / `image_url` cause **400 Bad Request**.
|
|
48
|
+
The bulk-API rule applies: **external** (non-Kolbo) URLs in `reference_images` / `source_images` / `image_url` cause **400 Bad Request**. Skip this pipeline if the URL is already `media.kolbo.ai` / `*.kolbo.ai` / a generate_* result — pass that URL through. For a third-party host:
|
|
49
49
|
|
|
50
50
|
1. `Bash: curl -fsSL "<external-url>" -o /tmp/<name>.<ext>` (or use WebFetch where it returns the binary)
|
|
51
51
|
2. `mcp__kolbo__upload_media` with the local file → returns Kolbo CDN URL
|
|
@@ -8,7 +8,7 @@ Visual DNA profiles capture the visual "identity" of a character, style, product
|
|
|
8
8
|
|
|
9
9
|
## Workflow
|
|
10
10
|
|
|
11
|
-
1. **
|
|
11
|
+
1. **Sheet first, then DNA.** For any production asset (character / location / prop), resolve the sheet **preset** (`list_presets` with `search`) and `generate_image` with that `preset_id` — custom instructions live on the preset. Then `create_visual_dna` with the sheet as `character_sheet_url` (max 4 extra images — if the user gives more, pick the 4 most representative; never pass 5+). Optionally video and audio.
|
|
12
12
|
2. **Types**: `character` (default), `style`, `product`, `scene`, `environment`.
|
|
13
13
|
3. **Use** the profile by passing its `id` in `visual_dna_ids` in: `generate_image`, `generate_creative_director`, `generate_elements`, `generate_video_from_image`, `generate_video_from_video`, `generate_first_last_frame`.
|
|
14
14
|
4. **List/inspect** profiles with `list_visual_dnas` / `get_visual_dna`.
|
|
@@ -85,6 +85,7 @@ Whenever a generation call passes `visual_dna_ids` (even just one), the prompt M
|
|
|
85
85
|
- Write a "Visual DNA anchors:" prose block that describes position/wardrobe but never writes `@ExactName`.
|
|
86
86
|
- Write the character's name in plain text without the `@` prefix.
|
|
87
87
|
- Drop the `@name` when only one DNA is passed — the engine still needs the binding so it knows the DNA is the *subject* and not a passive style.
|
|
88
|
+
- **Drop or "clean" tags while rewriting a prompt** (help-widget parity). Compiling SCENE CONTEXT / Locked Intro / a "better" English prompt is not permission to delete `@gal_suit` or rewrite `@yonatan` as `Yonatan`. Copy every existing `@` / `#` token into the new prompt, then add craft around them.
|
|
88
89
|
|
|
89
90
|
**Wrong** (DNA `name` is `esther_model`, user wrote prompt in Hebrew):
|
|
90
91
|
```
|
|
@@ -244,12 +245,22 @@ Tools: `list_visual_dna_folders`, `create_visual_dna_folder` (`name`, optional h
|
|
|
244
245
|
- **Creating many characters for one production?** Create the folder FIRST, then `move_visual_dna_to_folder` each DNA right after `create_visual_dna` — don't leave a big cast unsorted at root.
|
|
245
246
|
- To list a folder's contents: `list_visual_dnas` and filter by each profile's `folder_id` (there is no server-side folder filter).
|
|
246
247
|
|
|
247
|
-
## Character sheet —
|
|
248
|
+
## Character sheet — default for production assets (not a catalog preset)
|
|
248
249
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
250
|
+
Custom instructions live on the **image preset**. Resolve it silently, then generate:
|
|
251
|
+
|
|
252
|
+
1. `list_presets({ type: "image", search: "headless" | "bible" | "character sheet" | "location" | "product" })`
|
|
253
|
+
2. Pass the exact `id` as `preset_id` on `generate_image` (2K or 4K, never 1K; 4K for bible / high-detail / when named)
|
|
254
|
+
3. Show the sheet → GATE → `create_visual_dna { name, images, character_sheet_url }`
|
|
255
|
+
|
|
256
|
+
| Search | When |
|
|
257
|
+
|---|---|
|
|
258
|
+
| `bible` | Lead or anyone with a lot of detail (wardrobe, hair, accessories, instrument) |
|
|
259
|
+
| `headless` | Face already locked, or clothing / instrument / body must stay independent of the face |
|
|
260
|
+
| `character sheet` | Simple supporting person |
|
|
261
|
+
| `location` / `product` | Matching DNA type |
|
|
262
|
+
|
|
263
|
+
Do **not** omit `search` (that dumps the catalog). Do not show the preset picker. `generate_character_sheet` is fallback only if no preset matches.
|
|
253
264
|
|
|
254
265
|
### ⚠️ Aspect ratio — character sheets and bibles are LANDSCAPE
|
|
255
266
|
|
package/src/index.js
CHANGED
|
@@ -126,7 +126,7 @@ function createServer(opts = {}) {
|
|
|
126
126
|
'5. Written deliverables (plans, briefs, scripts, research summaries) can live in Kolbo too: author them as AI Docs with `create_doc` (project-scoped, editable in the app, shareable via `share_doc`).',
|
|
127
127
|
'6. TIMEOUT HANDLING (applies to EVERY generate_* / edit_* / chat_send_message / transcribe_audio tool): each tool blocks and polls internally, then gives up after its own window if the job is not yet terminal. A timeout is NOT a failure — it returns `_timed_out:true` with the `generation_id` (not an error), because the job is almost always STILL RUNNING on the server (or already finished). Call `get_generation_status` with that `generation_id` and `wait=true` to keep checking until state="completed". NEVER conclude the generation failed and re-run the same tool from scratch after a `_timed_out:true` result — that wastes the user\'s credits by paying twice. DIRECTOR / BATCH JOBS follow the same convention through a dedicated tool: generate_creative_director runs its scenes (image OR video) in parallel and only reports state="completed" once EVERY scene is terminal; on `_timed_out:true` call `get_creative_director_status` (not get_generation_status) with the returned generation_id and keep checking. If scenes already carry image_urls/video_urls, they are done; do not regenerate.',
|
|
128
128
|
'7. SESSION CONTINUITY — one task, one session, always: every generation tool returns a `session_id`. For ANY follow-up, refinement, retry, or next step on the SAME task, pass that session_id back — never start fresh. BATCH RULE (critical): when a single user request produces multiple parallel generations (e.g. "animate these 5 images", "generate 3 variants"), do NOT launch them all at once without a session_id. Instead: (1) run the FIRST generation without session_id to create the session, (2) capture the session_id from its response, (3) pass that session_id to ALL remaining generations in the batch. This keeps the entire batch in one session. Exception: only omit session_id and start fresh when the user explicitly starts an unrelated new task.',
|
|
129
|
-
'8. LOCAL FILES / REFERENCE MEDIA — HOW TO HANDLE EVERY CASE. (A) User has a LOCAL file (audio, video, image, document) on their machine. What matters is WHERE THIS SERVER RUNS, not what your client can do — your own filesystem access is irrelevant if the server is somewhere else. On a LOCAL stdio install (server and client share a machine) → call `upload_media` with the absolute path, or pass the path straight to tools like `transcribe_audio` that accept local paths. Over a REMOTE connector the server cannot see that path no matter how capable you are, so a local path will always fail: if you can run shell commands or issue HTTP requests → call `create_upload_ticket` and POST the file to the returned upload_url yourself (fastest, no user interaction); if you cannot → call `media_upload_widget` IMMEDIATELY, the user uploads, and a `media.kolbo.ai` CDN URL comes back for any follow-up call. (B) You already have a public URL
|
|
129
|
+
'8. LOCAL FILES / REFERENCE MEDIA — HOW TO HANDLE EVERY CASE. (A) User has a LOCAL file (audio, video, image, document) on their machine. What matters is WHERE THIS SERVER RUNS, not what your client can do — your own filesystem access is irrelevant if the server is somewhere else. On a LOCAL stdio install (server and client share a machine) → call `upload_media` with the absolute path, or pass the path straight to tools like `transcribe_audio` that accept local paths. Over a REMOTE connector the server cannot see that path no matter how capable you are, so a local path will always fail: if you can run shell commands or issue HTTP requests → call `create_upload_ticket` and POST the file to the returned upload_url yourself (fastest, no user interaction); if you cannot → call `media_upload_widget` IMMEDIATELY, the user uploads, and a `media.kolbo.ai` CDN URL comes back for any follow-up call. (B) You already have a public URL → pass it directly. A URL from generate_* / list_media / upload_media / media.kolbo.ai / any *.kolbo.ai host is ALREADY hosted — NEVER call upload_media on it (that duplicates the file). External (non-Kolbo) URLs may need one upload_media re-host; Kolbo URLs never do. NEVER search for DO Spaces keys, DigitalOcean credentials, or server-side upload credentials. NEVER ask the user to put the file on Google Drive, Dropbox, or Loom. NEVER invent or guess a URL. NEVER base64 anything but a tiny file — it costs context in proportion to file size; use the ticket or the widget instead.',
|
|
130
130
|
'9. MODEL SELECTION — NAMED MODEL WINS, THEN STRENGTHS SUMMARY: ALWAYS pass a specific `model` on every generation tool — do NOT omit it (omitting falls back to "Smart Select" auto-routing, which hides the choice from the user; use it ONLY if the user explicitly asks you to auto-pick). If the user named a model this turn OR earlier in the conversation (including a compaction "Locked choices" / summary), that name is a FAMILY LOCK: pass it (or its display name) on every follow-up, including when the tool changes (text-to-video → image-to-video). Identifier resolution remaps a t2v id to the family\'s i2v sibling automatically. NEVER substitute a different brand because it is cheaper, faster, or "best balance" (Grok Imagine named → do not fire Seedance). If the named family has no variant for this modality, ASK — do not silently switch. Cheapest-summary routing applies ONLY when no model was named on this task: call `list_models` with the matching `type` and read each model\'s STRENGTHS SUMMARY — the "— …" clause printed after the credit cost — then pick the CHEAPEST model whose summary covers the task. `[NEW]` and `[RECOMMENDED]` badges, a high credit number, and "flagship"/"most intelligent" wording are NOT selection signals — never pick a model because it is newest, biggest or most expensive. Escalate to a premium/frontier model only when the user explicitly asks for maximum quality, or when no cheaper summary covers the requirement. Models printed under "Named-only" (no summary) are opt-in: use them only when the user names them. TEXT/CHAT: `chat_send_message` bills PER TOKEN, so the listed credit number is not the cost — a frontier text model (Claude Fable 5, GPT-5.6 Sol, Pro-class) costs 5-30x a mid-tier one per reply. Default ordinary chat (writing, brainstorming, Q&A, summarising) to a balanced mid-tier model and reserve the frontier tier for hard reasoning or long-form code the user asked for.',
|
|
131
131
|
'10. IMAGE EDITING: for ANY prompt-driven / content edit of an existing image — "make it night", changing scene/lighting/colors, adding/removing/replacing objects, restyling — use `generate_image_edit`. Auto-pick only Nano Banana 2 (`nano-banana-2` / `nano-banana-2-image-editing`) or GPT Image 2 (`gpt-image-2` / `gpt-image-2/edit`) for photoreal photo edits, object removal, keep-subject/remove-others, or crowd cleanup. Do NOT auto-pick Flux 2 / flux-2/edit / Flux Klein — those are generate-from-scratch / style, named-only for editing. Do NOT use `edit_image` for content edits — `edit_image` is ONLY for mechanical enhancements (upscale, expand/outpaint, remove-background, skin retouch). Its `magic_edit` operation is deprecated in favor of `generate_image_edit`. EXPANDING AN IMAGE: to widen/extend/uncrop an image or fit it into a wider frame while KEEPING the existing artwork, use `edit_image` with operation="zoom_out" (outpainting — original pixels preserved; size it with `zoom_out_percentage` or the `expand_left/right/top/bottom` pixel args). The "reframe" operation is NOT this: it re-generates the whole picture at a new aspect ratio and the subject comes back re-imagined. Only pick "reframe" when the user wants the shot re-taken, never when they want their image extended.',
|
|
132
132
|
'11. PRESET CONTRACT: if the user asks for a preset, names a preset, or says to use one of their/Kolbo presets, you MUST call `list_presets` with the matching type before generation, resolve the named or closest matching preset, and pass its exact returned `id` as `preset_id`. Use type="image" for generate_image and type="image_edit" for generate_image_edit. Never silently ignore a preset request, never invent an id, and never claim a preset was applied unless `preset_id` was present in the generation call.'
|
package/src/tools/media.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
const { z } = require('zod');
|
|
7
7
|
const FormData = require('form-data');
|
|
8
8
|
const { resolveToBuffer, DEFAULT_MAX_FILE_MB, compactList } = require('./_shared');
|
|
9
|
+
const { ownedUrl } = require('./owned-url');
|
|
9
10
|
const { UI, uiResult, listResult } = require('../apps');
|
|
10
11
|
|
|
11
12
|
// How many tiles the media grid renders. A rendering limit only — the text
|
|
@@ -160,9 +161,9 @@ function registerMediaTools(server, client, options = {}) {
|
|
|
160
161
|
// ─── upload_media ──────────────────────────────────────────
|
|
161
162
|
server.tool(
|
|
162
163
|
'upload_media',
|
|
163
|
-
'Upload a
|
|
164
|
+
'Upload a LOCAL file (or a NON-Kolbo remote URL) to the user\'s Kolbo media library and get back a stable Kolbo CDN URL. NEVER call this on a URL that is already Kolbo-hosted: generate_* / list_media / prior upload_media results, media.kolbo.ai, *.kolbo.ai, or DigitalOcean Spaces. Those URLs are already usable — pass them as-is to generate_* as reference_images / source_images / image_url. Use this only for a path on disk or an external (non-Kolbo) URL that needs re-hosting. Auto-detects media type from the file extension.',
|
|
164
165
|
{
|
|
165
|
-
source: z.string().optional().describe('
|
|
166
|
+
source: z.string().optional().describe('Absolute local path, or a NON-Kolbo URL to re-host. Do not pass a media.kolbo.ai / generate_* / list_media URL — those are already hosted and this tool will refuse to duplicate them. Provide this OR source_base64.'),
|
|
166
167
|
source_base64: z.string().optional().describe('Raw file content as base64 (no data: prefix) — fallback for hosts with no filesystem or public URL (e.g. small images on claude.ai when the upload widget is unavailable). Requires `filename`. Keep under ~10MB; for larger files use media_upload_widget.'),
|
|
167
168
|
filename: z.string().optional().describe('Original filename WITH extension (e.g. photo.png) — required with source_base64; the extension determines the media type.'),
|
|
168
169
|
description: z.string().optional().describe('Optional description / caption for the uploaded media'),
|
|
@@ -171,6 +172,19 @@ function registerMediaTools(server, client, options = {}) {
|
|
|
171
172
|
async ({ source, source_base64, filename, description, project_id }) => {
|
|
172
173
|
if (!source && !source_base64) throw new Error('Provide source (URL or absolute local path) OR source_base64 (+ filename)');
|
|
173
174
|
|
|
175
|
+
if (source && ownedUrl(source)) {
|
|
176
|
+
return {
|
|
177
|
+
content: [{
|
|
178
|
+
type: 'text',
|
|
179
|
+
text: JSON.stringify({
|
|
180
|
+
reused: true,
|
|
181
|
+
url: source,
|
|
182
|
+
hint: 'This URL is already on Kolbo CDN. Pass it as-is to generate_* (reference_images / source_images / image_url / files). Do not upload again.',
|
|
183
|
+
}, null, 2),
|
|
184
|
+
}],
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
174
188
|
if (source_base64) {
|
|
175
189
|
if (!filename || !/\.[a-z0-9]{2,5}$/i.test(filename)) {
|
|
176
190
|
throw new Error('source_base64 requires a `filename` with an extension (e.g. photo.png)');
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Generation + library URLs already live on Kolbo CDN (media.kolbo.ai, Spaces).
|
|
2
|
+
// Re-uploading them wastes storage and time — pass the URL through as-is.
|
|
3
|
+
function ownedUrl(url) {
|
|
4
|
+
if (typeof url !== 'string' || !/^https?:\/\//i.test(url)) return false;
|
|
5
|
+
try {
|
|
6
|
+
const host = new URL(url).hostname;
|
|
7
|
+
return /(?:^|\.)kolbo\.ai$/.test(host) || /digitaloceanspaces\.com$/.test(host);
|
|
8
|
+
} catch {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
module.exports = { ownedUrl };
|