@kolbo/mcp 1.83.0 → 1.83.2

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.83.0",
3
+ "version": "1.83.2",
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@c3b231a, the single source of truth.
3
+ This tree is mirrored from kolbo-code@06cf199, 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
@@ -20,7 +20,7 @@ allowed-tools: Bash, Read, Write, Edit
20
20
 
21
21
  You have direct access to the Kolbo AI creative platform via MCP tools (auto-configured by `kolbo auth login`). Use them to generate and deliver real content — do NOT just describe what you would create.
22
22
 
23
- > 🚫 **Don't dump generated URLs as bare text or markdown links in chat** — the UI already shows results in **Library** (right panel) and on the generation card. Refer by description ("the rainy scene"), store URLs in `.kolbo/production.md`. INLINE `![](url)` images ARE allowed for catalog-style replies (per-item thumbs in numbered lists).
23
+ > 🚫 **Don't dump generated URLs as bare text or markdown links in chat** — the UI already shows results in **Library** (right panel) and on the generation card. Refer by description ("the rainy scene"). Store only user-approved results in `.kolbo/production.md`; pending takes stay out. INLINE `![](url)` images ARE allowed for catalog-style replies (per-item thumbs in numbered lists).
24
24
 
25
25
  This file is the **always-loaded core**: tool inventory + universal hard rules + routing index — for model-specific prompt rules, workflows, cost validation, etc., Read the matching `references/` file from the index below; loading is mandatory, not optional flavor (users never invoke the bundled skills themselves — skipping them yields a lazy one-line prompt).
26
26
 
@@ -55,7 +55,7 @@ Then generate **only** with the confirmed parameters. If the user changes an opt
55
55
 
56
56
  - **Video/lipsync `credit` is per-SECOND, not per-clip**: `total = credit × duration`. This is the universal rule for video/firstlast/elements/motion_graphic/cast types, not a per-model exception — `list_models` states it inline now. The one carve-out is a model with `flat_credit_by_resolution` set.
57
57
  - **Batch totalling 100+ credits**: run `check_credits` first.
58
- - **Quote real cost**: after firing, log `credits_used` (from the tool result) to `.kolbo/production.md` — never `base × count`.
58
+ - **Quote real cost**: when the user approves the result, log its actual `credits_used` (from the tool result) to `.kolbo/production.md` — never `base × count`.
59
59
  - **Never state "credits remaining" from arithmetic** (opening balance − generation costs). Coding/chat usage deducts credits too, so the math is always wrong. Report cost only; if the user asks for their balance, call `check_credits` fresh at that moment.
60
60
  - **Out of credits → `show_plans`.** A generation refused for credits already returns the upgrade card automatically — do NOT retry it, and do not re-run the tool "to be sure". Call `show_plans` yourself when the user asks about pricing, plans, upgrading, or how to get more credits. Prices are live and promo-adjusted; never quote them from memory. The user completes any purchase themselves on app.kolbo.ai/pricing — you cannot buy for them.
61
61
 
@@ -105,12 +105,10 @@ Each `references/models/*.md` mirrors the matching skill prompt in `kolbo-api/sr
105
105
  |------|-------------|
106
106
  | `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`. |
107
107
  | `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" })`. |
108
- | `edit_image` | Operation-routed image tools such as upscale, reframe, outpaint, background work, inpaint and enhance. Before choosing `model`, call `list_models` with the operation family (`image_upscale`, `image_reframe`, `image_zoom_out`, `background_remove`, `graphics_enhance`, etc.) and pass a concrete returned identifier. `multi_shot` and `split` use pinned processing, so omit `model` for those. |
109
108
  | `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. |
110
109
  | `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. |
111
110
  | `generate_video_from_image` | Animate a still. Prompt describes motion, not subject. |
112
111
  | `generate_video_from_video` | Restyle/transform an existing video. Keeps original motion. |
113
- | `edit_video` | Operation-routed video tools such as upscale, reframe, audio generation, watermark/background removal, face swap, extend, inpaint and retake. Discover the real engines through the operation family (`video_upscale`, `video_reframe`, `video_to_sound`, `video_extend`, etc.), compare caps/cost/`params`, and pass a concrete identifier — never a `kolbo_gateway_*` navigation row. |
114
112
  | `generate_elements` | Reference-driven video. **Primary route for DNA → video.** Prompt = Seedance Locked Intro (`Total` + `[GLOBAL LOOK]` / `[CAST]` / `[LOCATION]` + `SHOT N`). Every DNA in `visual_dna_ids` must also be `@Name` in that prompt. |
115
113
  | `generate_first_last_frame` | Keyframe interpolation between two frames. |
116
114
  | `generate_lipsync` | Lipsync an existing waveform onto a face. **Not the route for dialogue in a film you are generating** — write the line in the Seedance prompt instead. |
@@ -209,7 +207,9 @@ Scene dialogue is **never** `generate_speech` or `generate_lipsync`. Seedance 2
209
207
 
210
208
  ## ⚠️ Load the matching skill BEFORE generating (HARD RULE)
211
209
 
212
- 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.
210
+ This `kolbo` skill is the mandatory first layer for every Kolbo media task. Do **not** call `generate_*` / `generate_elements` / `generate_image_edit`, or write the billable prompt for them, until you have loaded every matching dependency **in this turn** (the `skill` tool for bundled skills and Read of the required Kolbo references). "I already know this," memory, or a prior-turn load does not count. Users will never invoke these skills themselves.
211
+
212
+ Dependencies accumulate: narrative Elements work requires **Kolbo + filmmaking + elements-prompting**, not whichever one was loaded first. Before the first paid call, silently check the stack and load anything missing.
213
213
 
214
214
  | About to call / user intent | `skill` tool | Also Read |
215
215
  |---|---|---|
@@ -295,7 +295,7 @@ Four surfaces show the same job. Use this map — never invent a fifth:
295
295
  | **Library** (right panel — "This session" / "All media") | User-facing gallery of **completed** media | "Is the user's output there?" Point humans here — never to chat history. Finished clips/images land automatically — do **not** call `list_media` / `get_media` / `list_session_generations` to "check if it worked" after a generate you already submitted (burns credits/context, can pollute the session). A K/logo spinner tile **is** the in-progress placeholder for the same job, not a missing one. |
296
296
  | **Chat generation card** | Progress chrome while a job is in flight | Status badge only (`Generating` / done). A **black / empty preview while Generating is NORMAL** — the iframe has nothing to paint yet. It is **not** failure, not "lost", not a reason to re-fire. |
297
297
  | **`get_generation_status`** (MCP) | Agent API for job state | Whether the server job is `completed` / `failed` / still running, and the final `urls`. This is your SoT for in-flight work — **not** the card pixels. |
298
- | **`.kolbo/production.md`** | Your private log across turns | Ids + URLs after success. Compaction-safe memory — not the user gallery. |
298
+ | **`.kolbo/production.md`** | Your private log across turns | User-approved ids + URLs only. Compaction-safe memory — not the user gallery or a candidate scratchpad. |
299
299
 
300
300
  **🛑 NEVER re-fire a generation you already called.** Aborted / timed-out / `submitted` calls still process server-side. Finish with `get_generation_status` (`wait=true`) — never a second `generate_*`.
301
301
 
@@ -305,14 +305,14 @@ Four surfaces show the same job. Use this map — never invent a fifth:
305
305
 
306
306
  **Detecting failure — a generation can fail three ways. Treat ALL as failure:**
307
307
 
308
- 1. **Tool returns `error`** — explicit. Surface, suggest retry, log `generation_id`.
308
+ 1. **Tool returns `error`** — explicit. Surface it and suggest a retry. Keep the `generation_id` in the active run for recovery; never put failures in production.md.
309
309
  2. **Tool returns `completed` but `urls` is empty** — silent failure (NSFW filter, model OOM, upstream 5xx). Tell user "completed without an output — retrying" and re-fire ONCE. Do NOT claim it worked.
310
310
  3. **Tool hangs / never returns** — MCP poll timed out. Call `get_generation_status(generation_id, wait=true)` IMMEDIATELY. The server might be done.
311
311
 
312
312
  **Reporting:**
313
313
  - Don't celebrate before reading the result. Verify `urls` is non-empty.
314
314
  - Don't auto-retry without surfacing the failure. Partial batches: list failed items + reasons + successful count, and surface the user's count — "6 of 8 ready", not "videos ready". Never "✅ all done!" on partials.
315
- - Log only successes to `.kolbo/production.md` — never failed items.
315
+ - Log only successful results the user explicitly approves to `.kolbo/production.md` — never pending, rejected, or failed items.
316
316
  - When done: say the result is in **Library → This session**. "Where is it?" → Library (This session). "Is it done?" with no urls yet → `get_generation_status` once.
317
317
 
318
318
  `failure` envelope structure + retry rules: `references/workflows/troubleshooting.md`.
@@ -345,13 +345,13 @@ How to thread:
345
345
  3. New scene or new concept → new session. Same scene / same cast pass → never a new session.
346
346
  4. Image tools and video tools cannot share an id (server kinds differ). Cast/Locations stay image; scene clips stay video.
347
347
 
348
- 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`.
348
+ After the user approves a bucket, write its `session_id` + plan name into `.kolbo/production.md` `### Sessions`. Do not create or update the file for a pending bucket. Full rules: `references/workflows/production-planning.md` + `production-log.md`.
349
349
 
350
350
  ## Rate Limiting & Batch Generation
351
351
 
352
352
  - `generate_image`: 30/min. All other generation tools: 10/min per type. 300/min global. `upload_media`: 300/min, no credit cost.
353
353
  - **Batch ≤10 items**: output ALL tool calls in one response — they run concurrently.
354
- - **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`.
354
+ - **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. Keep pending ids in the current run; persist only the user-approved winners in `.kolbo/production.md`.
355
355
 
356
356
  ## ⚠️ Multi-output? Default to `generate_creative_director` (CRITICAL)
357
357
 
@@ -406,7 +406,7 @@ Avoid bare URL dumps and HTML `<table>` grids — Library already provides a gal
406
406
 
407
407
  **After `generate_creative_director` completes** — share results as individual URLs, one per scene. Do NOT create an HTML grid artifact.
408
408
 
409
- **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`.
409
+ **Never update `.kolbo/production.md` merely because a generation succeeded.** Keep the result provisional in the generation card / Library, ask the user to choose, and write only the explicitly approved winner in the same turn as approval. Brief approval before generation is not output approval; silence, a topic change, or requesting the next task is not approval. See `references/workflows/production-log.md`.
410
410
 
411
411
  ## Limitations & Safety
412
412
 
@@ -115,6 +115,6 @@ Cost formula: `final_cost = credit × resolution_multipliers[resolution] × (sou
115
115
  - **Video**: `720p` (or the cheapest), with `default_duration` (or shortest in `supported_durations`).
116
116
  - **Sound**: respect `sound_enabled_by_default`; if false, leave off.
117
117
 
118
- ## Always Log the Resolution / Duration / Sound Choices
118
+ ## Log Approved Resolution / Duration / Sound Choices
119
119
 
120
- Log `credits_used`, resolution, duration and sound state per entry format in `production-log.md`.
120
+ After the user approves the actual result, log its `credits_used`, resolution, duration, and sound state. Pending and rejected outputs stay out; use the format in `production-log.md`.
@@ -70,12 +70,12 @@ For ads featuring a specific product:
70
70
 
71
71
  | User provides | Do |
72
72
  |---|---|
73
- | **Product photo** (local file or URL) | `upload_media({ source })` → tag as `@image1` in prompt → log to `.kolbo/production.md` under `### Products` |
73
+ | **User-approved product photo** (local file or URL) | `upload_media({ source })` → tag as `@image1` in prompt → log to `.kolbo/production.md` under `### Products` |
74
74
  | **Product URL only** (no photo) | Run `workflows/research-first.md` first to scrape hero images + brand palette; re-host via `upload_media` → use Kolbo CDN URL |
75
75
  | **Multiple angles** | Upload all in parallel (one `upload_media` call each) → pass all in `reference_images` → tag `@image1`, `@image2`, … per `workflows/visual-dna.md` reference-tagging rules |
76
76
  | **Nothing — text only** | Ask once: "Do you have a product photo? It dramatically improves fidelity." If they say no, proceed text-only but warn quality may be lower |
77
77
 
78
- **Always log products in `.kolbo/production.md`** so subsequent ads in the same workspace reuse the same CDN URL without re-uploading.
78
+ **Log user-approved products in `.kolbo/production.md`** so subsequent ads reuse the same CDN URL. Generated variants stay out until approved.
79
79
 
80
80
  ## Reference Media Cap
81
81
 
@@ -121,6 +121,6 @@ Default-to-cheapest when the user hasn't expressed a quality intent and the diff
121
121
  1. **Always pick an ad format explicitly** with the user — never auto-pick.
122
122
  2. **Always confirm aspect ratio + resolution + quantity** before firing.
123
123
  3. **Always check for a brand kit** before scraping fresh — `Read .kolbo/brand-kits/<slug>.md` first.
124
- 4. **Always log products + brand kits in `.kolbo/production.md`** so future ads reuse instead of re-uploading / re-scraping.
124
+ 4. **Log approved products + brand kits in `.kolbo/production.md`** so future ads reuse them. Do not log generated variants before output approval.
125
125
  5. **Retries:** one retry only when `failure.retryable === true` or the generation completed with empty URLs (SKILL.md "⚠️ Generation lifecycle"); otherwise surface the reason and let the user adjust.
126
126
  6. **Strict NO uninvited additions** in every ad prompt: "NO captions, NO subtitles, NO watermarks, NO extra text beyond what's specified."
@@ -1,5 +1,7 @@
1
1
  # Filmmaking Router
2
2
 
3
+ **Prerequisite:** the `kolbo` skill must already be loaded in this turn. This router extends Kolbo; it does not replace Kolbo's tool, model, cost, approval, and logging rules. For any Elements/reference-driven/Visual-DNA video, also load the `elements-prompting` skill before compiling or generating. If a dependency is missing, stop and load it first.
4
+
3
5
  Operate as a filmmaking system, not merely a prompt writer. Preserve project truth across generations while compiling every generation into a self-contained instruction the selected model can execute.
4
6
 
5
7
  ## Start here
@@ -126,7 +126,7 @@ For ads that feature a specific product:
126
126
  1. **Upload product photo** via `upload_media` → Kolbo CDN URL.
127
127
  2. **Pass as `reference_images`** to `generate_creative_director` / `generate_elements` / `generate_video_from_image`.
128
128
  3. **Tag with `@image1`** in the prompt.
129
- 4. **Log in `.kolbo/production.md`** under a `### Products` subsection so future ads in the same workspace reuse the same CDN URL (don't re-upload).
129
+ 4. **After the user approves the product asset, log it in `.kolbo/production.md`** under `### Products` so future ads reuse the same CDN URL. Pending variants stay out.
130
130
 
131
131
  If the user gives a **product URL** instead of a photo, see `workflows/research-first.md` — scrape, extract images, re-host via `upload_media`, persist as a brand kit at `.kolbo/brand-kits/<slug>.md`.
132
132
 
@@ -125,7 +125,7 @@ Skip questions whose answer is obvious from the request.
125
125
  ...
126
126
  ```
127
127
  Do NOT wrap them in an HTML grid artifact — the canvas already shows the gallery.
128
- - Log all URLs to `.kolbo/production.md` under `## Production: <product name>` → `### Marketplace Cards` subsection.
128
+ - After the user approves specific cards, log only those URLs to `.kolbo/production.md` under `## Production: <product name>` → `### Marketplace Cards`.
129
129
  - If a `main_image` came back with text / props (compliance failure), surface the issue and re-fire with stronger prompt prohibitions — don't ship a non-compliant main image.
130
130
 
131
131
  ## Existing Main-Image Reuse
@@ -143,4 +143,4 @@ If the user already has an approved `main_image` from a prior session and wants
143
143
  3. **Always reuse brand kit** — Read `.kolbo/brand-kits/<slug>.md` first; pass palette + fonts to every A+ module.
144
144
  4. **Recommend GPT Image 2 + 2K/4K for dense-text A+ modules** — Nano Banana renders text well but GPT Image 2 wins at multi-line technical layouts.
145
145
  5. **For bundles, always use `generate_creative_director`** — never fire 13 parallel `generate_image` calls.
146
- 6. **Log everything to `.kolbo/production.md`** — marketplace listings get updated quarterly; reuse beats regenerate.
146
+ 6. **After approval, log the approved cards to `.kolbo/production.md`** — pending and rejected variants stay out; approved listings can then be reused.
@@ -143,7 +143,7 @@ For `social_carousel` / `ad_creative_pack` (multi-output by design):
143
143
  - Call the chosen MCP tool — single command, no preamble.
144
144
  - For multi-output: `generate_creative_director` returns N URLs; share them as individual lines (do NOT build an HTML grid artifact — the canvas already shows the gallery).
145
145
  - For single-output: one image URL.
146
- - Log every URL + model + resolution + mode into `.kolbo/production.md` under `### <Mode>` subsection.
146
+ - After the user approves a result, log only that URL + model + resolution + mode into `.kolbo/production.md` under `### <Mode>`.
147
147
 
148
148
  ## UX Rules
149
149
 
@@ -1,116 +1,104 @@
1
1
  # Production Log — `.kolbo/production.md`
2
2
 
3
- Load this file when starting a multi-step production, or before any continuation of prior media work ("edit", "redo", "the same character", `@name` references, "scene N").
3
+ Load this file when starting a multi-step production, or before continuing prior
4
+ media work ("edit", "redo", "the same character", `@name`, "scene N").
4
5
 
5
- ## Why It Exists
6
+ ## Purpose and boundary
6
7
 
7
- Every URL, id, and brief produced by a Kolbo MCP tool MUST be recorded in `.kolbo/production.md` in the user's workspace. This file is **your** (agent) source of truth for prior artifacts across turns — not chat history (unreliable / compacted) and not a substitute for the user's **Library** gallery. URLs scattered across `tool_result` blobs are unreliable to re-scan and disappear entirely on context compaction. If the user named a model, write that name into `## 🎯 Now` and keep using that family on every follow-up — compaction is not permission to cheapest-swap.
8
+ `.kolbo/production.md` is the agent's durable registry of **user-approved**
9
+ artifacts across turns. It is not the user's gallery and it is not a scratchpad
10
+ for generations that are still being judged.
8
11
 
9
- **User vs agent SoT:** finished media for the human → **Library → This session**. Job state while in flight → `get_generation_status`. Your memory → this file. Chat cards are progress UI only.
12
+ The boundary is absolute:
10
13
 
11
- ## When to READ it
14
+ - Do not create, edit, or append to the file when a generation succeeds.
15
+ - Do not log pending candidates, rejected takes, failures, unapproved session
16
+ ids, planned buckets, or estimated costs.
17
+ - Write only after the user explicitly approves the actual generated result.
18
+ - Approval of the brief before generation does not approve the output.
19
+ - Silence, a topic change, asking for another take, or merely continuing the
20
+ workflow is not approval.
12
21
 
13
- Read `.kolbo/production.md` **before** acting on any of these signals:
14
- - "edit", "animate", "combine", "redo", "polish", "fix", "regenerate"
15
- - "the same character / scene / image / video / sound", "that X", "scene N", "the rainy one", etc.
16
- - `@name` references for Visual DNA
17
- - Any continuation of prior media work ("now make scene 3")
18
-
19
- If the file is missing and the user is referencing prior media, ask the user — do not guess from chat.
20
-
21
- ## ⚠️ Approval gates — the user is usually still iterating (READ THIS FIRST)
22
-
23
- Most media work is an **approval loop**, not a single shot. The user generates, looks, asks for another take, and keeps going until satisfied. This is the normal case for **images, image sets, Visual DNAs, moodboards, and videos** alike.
24
-
25
- The log records **what the user approved** — not everything you produced. Getting this wrong is expensive in both directions: log too eagerly and take 3 of 7 is enshrined as "the character"; log too late and the approved URL is gone after compaction.
26
-
27
- **The loop:**
28
-
29
- 1. **Generate** candidates.
30
- 2. **Present them so the user can actually judge.** Never ask "approve?" over bare URLs or ids — the user cannot see those. Use the widget-carrying tools:
31
- - Visual DNAs → `list_visual_dnas` (renders a thumbnail media grid; `create_visual_dna` returns text only, so follow it with this)
32
- - Moodboards → `list_moodboards`
33
- - Images / videos / audio → show the returned URLs as markdown images/links
34
- Say plainly which ones are in play, e.g. "created `@maya` and `@maya_alt` — here they are".
35
- 3. **Ask for a decision** and name the options ("keep the first, redo the second, or both?").
36
- 4. **Repeat** until the user is satisfied. Log nothing as approved during this stage.
37
- 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.
38
-
39
- **Never write an artifact into the log as approved without the user's approval.**
40
-
41
- If they didn't volunteer a yes, end the turn with the GATE block from
42
- `production-planning.md` §3.
43
-
44
- **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.
22
+ Library This session is the human-facing source for completed and provisional
23
+ media. `get_generation_status` is the source for in-flight jobs. The production
24
+ log is the source only for what has been locked.
45
25
 
46
- **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)`:
26
+ ## Read before continuation
47
27
 
48
- ```md
49
- 2. **Rainy street walk** — neon reflections, slow dolly
50
- #### Candidates (pending approval)
51
- - take 1: https://...02-rain-a.png (flux-2-pro, 2026-08-17)
52
- - take 2: https://...02-rain-b.png (flux-2-pro, 2026-08-17)
53
- ```
28
+ Read `.kolbo/production.md` before acting on:
54
29
 
55
- after the user picks take 2:
30
+ - "edit", "animate", "combine", "redo", "polish", "fix", "regenerate"
31
+ - "the same character / scene / image / video / sound", "that one", "scene N"
32
+ - `@name` references for Visual DNA
33
+ - any continuation of previously approved media work
56
34
 
57
- ```md
58
- 2. **Rainy street walk** neon reflections, slow dolly
59
- - still: https://...02-rain-b.png (flux-2-pro · 1K, approved 2026-08-17)
60
- - take 1: https://...02-rain-a.png (rejected 2026-08-17)
61
- ```
35
+ If the file is missing and the user references prior work, resolve it from the
36
+ current conversation or Library/session tools. Do not guess and do not create a
37
+ placeholder entry.
62
38
 
63
- **Re-confirm state after a long loop.** When a session has churned through many takes, restate the approved set before moving on — "so we're locked on: @maya, moodboard #noir, scenes 1-3" — and make the log match. An approval loop that ends without a written-down approved state is how the wrong asset ships.
39
+ ## Approval loop
64
40
 
65
- ## When to WRITE to it
41
+ 1. Generate the requested result.
42
+ 2. Present it through the generation card / Library so the user can judge it.
43
+ 3. Ask for a concrete decision: which result to lock, redo, or discard.
44
+ 4. Keep all iterations provisional and leave `.kolbo/production.md` untouched.
45
+ 5. When the user explicitly approves a visible result, update the log in that
46
+ same turn and record only the approved winner.
47
+ 6. Only after that write may the production advance to the next gated bucket.
66
48
 
67
- Two writes, different jobs:
49
+ Clear approvals include `approve`, `lock`, `that's the one`, `use take 2`, or an
50
+ equally unambiguous choice naming the actual result. If the user delegates a
51
+ choice **after seeing the takes** ("you choose between these"), choose one,
52
+ state which one, and log it as `(user-delegated choice)`. A pre-generation "you
53
+ pick" still requires approval of the resulting media before writing.
68
54
 
69
- 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.
70
- 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.
55
+ Legacy logs may contain `Candidates` sections. Treat them as unapproved. Do not
56
+ add new candidates. Promote only the item the user explicitly chooses; leave
57
+ unselected legacy lines untouched rather than adding new rejected entries.
71
58
 
72
- 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.
59
+ ## Write after approval
73
60
 
74
- Tools that REQUIRE logging:
75
- - `generate_image`, `generate_image_edit`, `edit_image`
76
- - `generate_video`, `generate_video_from_image`, `generate_video_from_video`, `edit_video`
77
- - `generate_elements`, `generate_first_last_frame`, `generate_lipsync`
78
- - `generate_music`, `generate_sound`, `generate_speech`
79
- - `generate_3d`, `generate_creative_director`
80
- - `create_visual_dna`, `upload_media`
61
+ For an approved result, record:
81
62
 
82
- Tools that do NOT log: `list_*`, `get_*`, `check_credits`, `chat_*`, `transcribe_audio` (read-only / discovery).
63
+ - a plain-English label the user would use
64
+ - output URL
65
+ - model, resolution/quality, and video duration/sound state when applicable
66
+ - ISO approval date
67
+ - actual `credits_used` from the tool result—not a catalog estimate
68
+ - `session_id` and `generation_id` when returned
69
+ - Visual DNA / moodboard bindings such as `@maya → vdna_id`
83
70
 
84
- ## File creation pick the right tool to avoid the "must Read first" error
71
+ If the approved result replaces an older approved asset, mark the old entry
72
+ `(superseded YYYY-MM-DD)` and add the new entry beneath it. Do not delete history.
85
73
 
86
- `Edit` refuses to overwrite a file unless you've `Read` it first in the same session. Pick by file state:
74
+ ### Tool choice
87
75
 
88
76
  | State | Tool |
89
77
  |---|---|
90
- | File **does not exist** (typical first turn) | `Write` with the full stub below |
91
- | File **exists** | `Read` first, then `Edit` |
92
- | Not sure | `Read` first; on ENOENT, fall back to `Write` |
78
+ | File does not exist at approval time | `Write` with the stub below |
79
+ | File exists | `Read`, then `Edit` |
80
+ | Not sure | `Read`; on ENOENT, use `Write` |
93
81
 
94
- Stub for first creation:
82
+ ## Canonical stub
95
83
 
96
84
  ```md
97
- <!-- .kolbo/production.md — agent-managed media artifact registry.
85
+ <!-- .kolbo/production.md — agent-managed registry of user-approved media.
86
+ Pending and rejected generations stay in Library, not in this file.
98
87
  User may hand-edit; agent must Read-before-Edit to reconcile. -->
99
88
 
100
89
  # Production Log
101
90
 
102
91
  ## 🎯 Now
103
92
 
104
- **Brief:** <paraphrase of user's overall goal in 1-3 sentences>
105
- **Now working on:** <the immediate next step>
106
- **Approved:** <locked assets — DNAs, moodboards, scenes; "nothing yet" if still iterating>
107
- **Awaiting approval:** <what you've presented and are waiting on; omit when nothing is pending>
108
- **Sessions:** <plan names + ids — Cast / Locations / Scene 01 — …; "none yet" until first generate>
93
+ **Brief:** <paraphrase of the approved production goal in 1-3 sentences>
94
+ **Now working on:** <the next approved production step>
95
+ **Approved:** <locked assets>
96
+ **Sessions:** <approved plan names + ids>
109
97
  **Last updated:** <ISO date>
110
98
 
111
99
  ---
112
100
 
113
- ## Production: <name from user's request, slugified human label>
101
+ ## Production: <name from user's request>
114
102
 
115
103
  ### Sessions
116
104
  ### Cast
@@ -120,101 +108,44 @@ Stub for first creation:
120
108
  ### Final
121
109
  ```
122
110
 
123
- Subsections (`### Cast` etc.) are **suggested defaults**, not required. Adapt: a logo set has `### Logos`, an album has `### Tracks`, a 3D render has `### Models`. Leave empty subsections out of the file when you create entries.
124
-
125
- ## Entry shape
111
+ Subsection headings are suggestions. Adapt them to the production and omit empty
112
+ ones.
126
113
 
127
- 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.
114
+ ## Entry example
128
115
 
129
116
  ```md
130
117
  ### Sessions
131
- - **Cast**sess_abc (image)@maya @doron
132
- - **Locations** — sess_def (image) — @night_market
133
- - **Scene 01 — coffee shop** — sess_ghi (video) — shots 1–4
134
- - **Scene 02 — rooftop chase** — (pending)
135
-
136
- ### Cast
137
- - **Maya** — female, 30, urban photographer, leather jacket
138
- - portrait: https://...characters/maya.png (nano-banana-2, 2026-05-13)
139
- - visual DNA: vdna_8f2c (@maya)
140
- - session: sess_abc
118
+ - `Scene 02 rainy street` `ses_abc123` (video; approved 2026-08-28)
141
119
 
142
120
  ### Scenes
143
- 1. **Coffee shop morning** — Maya at counter, soft light, wide shot
144
- - still: https://...scenes/01-coffee.png (flux-2-pro, 2026-05-13)
145
- - video: (pending)
146
121
  2. **Rainy street walk** — neon reflections, slow dolly
147
- - still: https://...scenes/02-rain.png (flux-2-pro, 2026-05-13)
148
- - video: https://...videos/02-rain.mp4 (kling-2, 2026-05-13)
149
- ```
150
-
151
- ## Header rewrite rule (Manus pattern — IMPORTANT)
152
-
153
- The `## 🎯 Now` block at the top of the file is **rewritten every turn** to keep the brief + current step near the model's recency window. Body sections (everything below the first `---`) are **append-only**.
154
-
155
- When a user request supersedes a previous artifact (e.g., "redo scene 2 with more rain"), do not delete the old entry. Mark it `(superseded YYYY-MM-DD)` and place the new entry beneath:
156
-
157
- ```md
158
- 2. **Rainy street walk** — neon reflections, slow dolly
159
- - still: https://...scenes/02-rain.png (superseded 2026-05-13)
160
- - still: https://...scenes/02-rain-v2.png (flux-2-pro, 2026-05-13)
161
- - video: https://...videos/02-rain-v2.mp4 (kling-2, 2026-05-13)
122
+ - video: https://.../02-rain-b.mp4
123
+ - model: kling-2 · 1080p · 5s · sound-on
124
+ - generation_id: gen_8a2c…
125
+ - session_id: ses_abc123
126
+ - credits_used: 24
127
+ - approved: 2026-08-28
162
128
  ```
163
129
 
164
130
  ## Rules
165
131
 
166
- 1. **First touch `Write`, subsequent touches `Read` `Edit`** (see "File creation" above). If `Edit` fails on exact-match, `Read` again — the user may have hand-edited.
167
- 2. **Plain English labels** write what the user would call it.
168
- 3. **Append-only body.** Only the `## 🎯 Now` header is rewritten. Never delete artifact entries; mark them `(superseded)` instead.
169
- 4. **Do not log failures.** Only successful generations.
170
- 5. **Resolve user references via the log, not chat history.** If the user says "scene 3," use the URL the log says is scene 3, even if a later tool_result mentioned a different URL.
171
- 6. **One file per workspace.** Multiple concurrent productions go under separate `## Production: <name>` headings inside the same file.
172
- 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.
173
- 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.
174
- 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.
175
-
176
- ## Bulk Generation Entry Shape
177
-
178
- For batch runs (50-item UGC sets, etc.), persist every `generation_id` (even for failures) — required for `get_generation_status` recovery and cross-session dedupe.
179
-
180
- ```md
181
- 12. ✅ Asian F 24, bedroom, hype POV
182
- - generation_id: gen_8a2c…
183
- - url: https://…
184
- - model: seedance-2 · 720p · 10s · sound-on
185
- - generated: 2026-05-14T07:42Z
186
- 13. ❌ Latino M 31, gym
187
- - generation_id: gen_ff19…
188
- - error: 429 Too many generation requests
189
- - retry_after: 2026-05-14T07:43Z
190
- ```
191
-
192
- ## Always log the resolution / duration / sound choices
193
-
194
- Production-log entries should include the resolution and (for video) duration + sound state alongside the URL, so the user can see what they paid for:
195
-
196
- ```md
197
- - still: https://...01-coffee.png (flux-2-pro · 1K, 2026-05-14)
198
- - video: https://...02-rain.mp4 (kling-2 · 1080p · 5s · sound-off, 2026-05-14)
199
- ```
132
+ 1. Approved artifacts only; generation success is never approval.
133
+ 2. First touch uses `Write`; later touches use `Read` then `Edit`.
134
+ 3. Body history is append-only. Mark replacements superseded; never delete.
135
+ 4. Never log failures, rejected takes, or pending candidates.
136
+ 5. Keep one file per workspace; separate productions use separate headings.
137
+ 6. Resolve references from approved entries, not from an arbitrary later take.
138
+ 7. Add a session row only when its associated result/bucket is approved. Reuse
139
+ the active `session_id` for provisional retakes without logging it.
140
+ 8. Preserve prompt tags and their URL / DNA-id bindings in approved entries.
200
141
 
201
- ## Production Log vs TodoWrite
142
+ ## Production Log vs task planning
202
143
 
203
- Use both different jobs:
204
-
205
- | | `.kolbo/production.md` | `TodoWrite` |
144
+ | | `.kolbo/production.md` | Task plan |
206
145
  |---|---|---|
207
- | Purpose | Durable artifact registry | Ephemeral step plan |
208
- | Lifetime | Persists across sessions / compaction | Per turn / per request |
209
- | Content | URLs, ids, briefs | "Do X, then Y, then Z" |
210
- | Example | `still: https://...01-coffee.png` | `Generate visual DNA for Maya` |
211
-
212
- ## Real Cost Quoting
213
-
214
- Every generation now returns `credits_used` (multiplier-adjusted total) and `credits_breakdown` (per-model attribution). **Log `credits_used` to `.kolbo/production.md`, not `base × count`.**
215
-
216
- ```json
217
- { "credits_used": 12, "credits_breakdown": [{ "model": "nano-banana-2", "base": 8, "final": 12, ... }], "urls": [...] }
218
- ```
146
+ | Purpose | Durable approved artifact registry | Current provisional work |
147
+ | Content | Locked URLs, ids, sessions, actual cost | Generate, review, redo, choose |
148
+ | Write time | After explicit output approval | Before and during iteration |
219
149
 
220
- When the user asks "how much did I spend?" call `get_session_usage` for the real, multiplier-adjusted session total + per-tool + per-model breakdowns (same numbers as the desktop bottom-bar counter).
150
+ When the user asks how much a session spent, call `get_session_usage`; do not
151
+ derive a remaining balance from production-log entries.
@@ -59,9 +59,10 @@ Omitting `session_id` on generate creates a new session. First call of a bucket
59
59
  omits it, then `rename_session` immediately; every later call in that bucket
60
60
  passes the same id. Image and video kinds cannot share an id.
61
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`.
62
+ Keep planned names in the working plan during MAP. Do not create or update
63
+ `.kolbo/production.md` for pending buckets. After the user approves a bucket,
64
+ write its plan name and real `session_id` under `### Sessions`. See
65
+ `production-log.md`.
65
66
 
66
67
  Separate **states** from **identities**: clean vs bloodied, day vs night, intact
67
68
  vs broken are their own assets. Do not expect one DNA to carry both.
@@ -123,7 +124,7 @@ parse — not a vague "looks good?":
123
124
 
124
125
  ```
125
126
  GATE — Cast
126
- Presented: @maya, @doron (candidates in the log)
127
+ Presented: @maya, @doron (provisional; not yet in the production log)
127
128
  Lock + next: "lock cast" / "yes" / "next" / "now locations"
128
129
  Stay: "redo @maya" / "another take of the leather jacket"
129
130
  ```
@@ -135,8 +136,9 @@ Treat as confirmation: `yes`, `ok`, `lock`, `approved`, `that's the one`,
135
136
  Not confirmation: silence, "maybe", a question about something else, another
136
137
  take request. Ask the GATE again once; do not invent a yes.
137
138
 
138
- On lock: promote candidates Approved in `.kolbo/production.md`, then start
139
- the next planned bucket in **its** session.
139
+ On lock: write the approved result into `.kolbo/production.md`, then start the
140
+ next planned bucket in **its** session. Rejected and pending takes never enter
141
+ the log.
140
142
 
141
143
  ## 4. Shoot
142
144
 
@@ -50,7 +50,7 @@ The bulk-API rule applies: **external** (non-Kolbo) URLs in `reference_images` /
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
52
52
  3. Use the returned CDN URL in any subsequent generation call
53
- 4. Log both URLs in the production log (so the user can trace provenance)
53
+ 4. After the user approves the researched direction, log its two source URLs in the production log for provenance
54
54
 
55
55
  ## Synthesizing the research
56
56
 
@@ -154,7 +154,7 @@ The other workflow files consume the brand kit:
154
154
  - `workflows/marketplace-cards.md` — palette + fonts critical for A+ module consistency
155
155
  - `workflows/marketing-studio.md` — voice/tone shapes UGC presenter dialogue; palette shapes any branded overlays
156
156
 
157
- Always cite the brand-kit slug in the production log so reviewers can trace which kit drove a given generation.
157
+ When an approved generation is logged, cite the brand-kit slug so reviewers can trace which kit drove it. Do not update the log for pending results.
158
158
 
159
159
  ## Building prompts informed by the research
160
160
 
@@ -149,7 +149,7 @@ visual_dna_ids: ["vdna_8f2c"] // maya
149
149
 
150
150
  The point is **not** to dump an essay into the prompt — it's to make sure every concrete detail the next model needs to preserve (or change) is named, so the chain doesn't lose continuity across steps.
151
151
 
152
- **Production-log tie-in:** when you analyze a generated still/clip, write a one-line description into `.kolbo/production.md` next to the URL that way the next chained step can read the log instead of re-analyzing.
152
+ **Production-log tie-in:** only if the still/clip is already user-approved and present in `.kolbo/production.md`, add a one-line analysis beside its URL. Never create an entry for an unapproved asset merely because it was analyzed.
153
153
 
154
154
  ## Image Analysis Detail (when the user uploads images)
155
155
 
@@ -68,7 +68,7 @@ When a generation fails, `get_generation_status` returns a structured `failure`
68
68
 
69
69
  Branch on `failure.category` / `failure.retryable`:
70
70
 
71
- - `category === "content_policy"` (or `code === "CONTENT_FLAGGED_SENSITIVE"`) → **do not retry the same prompt**. Tell the user the model refused, suggest a less explicit phrasing or a Visual DNA fallback. Log to `.kolbo/production.md` Failures section with the exact reason.
71
+ - `category === "content_policy"` (or `code === "CONTENT_FLAGGED_SENSITIVE"`) → **do not retry the same prompt**. Tell the user the model refused and suggest a less explicit phrasing or a Visual DNA fallback. Keep the failure out of `.kolbo/production.md`.
72
72
  - `category === "auth"` or `code === "[KOLBO_AUTH_EXPIRED]"` → surface the reconnect flow, don't auto-retry.
73
73
  - `retryable === true` (transient: network, rate limit, provider 5xx) → retry once with the same payload after a short pause. If it fails again, surface to user.
74
74
  - `retryable === false` and unknown category → surface the raw `message` to the user, don't retry.
@@ -63,7 +63,7 @@ When the user says "use the model אסתר" but you've only created a DNA for "
63
63
 
64
64
  ## ⚠️ Don't re-fetch / re-list your own outputs (CRITICAL)
65
65
 
66
- After a generation tool returns its URLs, those URLs are **already** in **Library** (right panel — This session) and in `.kolbo/production.md`. Do **NOT** call `list_media`, `get_media`, `get_media_stats`, `list_visual_dnas`, or `chat_send_message` with `media_urls` on those URLs just to "verify" or "fetch thumbnails of the results":
66
+ After a generation tool returns its URLs, those URLs are already in **Library** (right panel — This session). They enter `.kolbo/production.md` only after the user approves the actual result. Do **NOT** call `list_media`, `get_media`, `get_media_stats`, `list_visual_dnas`, or `chat_send_message` with `media_urls` just to "verify" or "fetch thumbnails":
67
67
 
68
68
  - It burns credits and time for zero new information.
69
69
  - Every such tool call streams partial output into the session, which forces Library to re-evaluate (visible flicker on the gallery tiles).
@@ -75,7 +75,7 @@ After a generation tool returns its URLs, those URLs are **already** in **Librar
75
75
  - You need details about something generated in an **earlier session** that you don't have a record of.
76
76
  - You're chasing a specific user reference like "the rainy clip from yesterday" that isn't in the current chat's `.kolbo/production.md`.
77
77
 
78
- For media you generated this session, you already know the prompt, model, and result URL — write that into `.kolbo/production.md` and reference it from context.
78
+ For media generated this session, use the current tool result while approval is pending. After explicit output approval, write the winner's prompt, model, and URL into `.kolbo/production.md`.
79
79
 
80
80
  ## ⚠️ Presenting list results — show thumbnails (MANDATORY)
81
81
 
@@ -179,7 +179,7 @@ Lipsync @video1's speaker to the dialogue track @Audio1, keeping the original am
179
179
  2. **For edits, the source is `@image1` (or `@video1`).** In `generate_image_edit`, the first entry of `source_images` is the canonical base.
180
180
  3. **Visual DNA tags are name-based, not positional.** `@maya` always means the DNA you registered as `name: "maya"`, regardless of where its id sits in `visual_dna_ids`.
181
181
  4. **Tag every reference you actually pass.** If you pass a reference but never mention it in the prompt, the engine often treats it as decorative — either drop it or name it explicitly.
182
- 5. **Tags carry across the production log.** When you log a generation to `.kolbo/production.md`, write the prompt with the tags intact and record the `@name → URL` / `@name → vdna_id` binding alongside.
182
+ 5. **Tags carry across the production log.** When the user approves a generation and you log it, preserve the prompt tags and record the `@name → URL` / `@name → vdna_id` binding alongside.
183
183
  6. **Tag even single-reference calls when a DNA, video, or audio is involved.** Single plain image with no DNA can use prose ("this image"), but as soon as the call also carries a DNA, a video ref, or an audio ref, tag every asset so the engine knows the subject vs. the modifier role.
184
184
 
185
185
  **Failure modes the tags fix:**
@@ -1254,12 +1254,12 @@ function registerGenerateTools(server, client, options = {}) {
1254
1254
  // ─── generate_elements ─────────────────────────────────────
1255
1255
  server.tool(
1256
1256
  'generate_elements',
1257
- 'Generate a video from reference elements (images, videos, and/or audio) + a text prompt. Use when the user wants to animate specific uploaded/referenced assets — e.g. "animate this product", "put these 3 characters into a scene". PRIMARY ROUTE FOR A DNA-ANCHORED MULTI-SHOT FILM: one call can carry the whole sequence — seedance-2-5 takes 4-30s, up to 30 shots and 20 Visual DNAs in a SINGLE generation (seedance-2: 4-15s, 9 DNAs) — instead of a stack of separate clips. DIALOGUE IS PERFORMED NATIVELY: quoted dialogue in the prompt comes back as synced voices with lip movement, room tone and the SFX named in the AUDIO block — never route scene dialogue to generate_speech or generate_lipsync. Write dialogue in ENGLISH; other languages (Hebrew included) do not perform reliably. COST: resolution is a MULTIPLIER, not a flat fee (vs 720p: 480p x0.44, 1080p x2.25, 4k x4.95) run blocking/draft passes at 480p and re-run only the approved cut at delivery resolution. PROMPT CONTRACT (Seedance / Elements): Locked Intro only — Total line, then [GLOBAL LOOK] / [CAST] / [LOCATION] / SHOT N. Do NOT write SCENE CONTEXT / OPTICS / ACTION department packs. Every Visual DNA in visual_dna_ids MUST also appear in the prompt as @ExactDNAName (e.g. "@Zohar walks…") — never "Zohar\'s" or "the man on the left" as a substitute. IMPORTANT: different models accept different numbers of inputs — call list_models type="elements" and read elements_max_images / elements_max_videos / elements_max_audio on the chosen model before generating. For text-only → video use generate_video instead. For animating a single still image use generate_video_from_image. Returns the final video URL when complete.',
1257
+ 'Generate a video from reference elements (images, videos, and/or audio) + a text prompt. Use when the user wants to animate specific uploaded/referenced assets — e.g. "animate this product", "put these 3 characters into a scene". PRIMARY ROUTE FOR A DNA-ANCHORED MULTI-SHOT FILM: one call can carry the whole sequence — seedance-2-5 takes 4-30s, up to 30 shots and 20 Visual DNAs in a SINGLE generation (seedance-2: 4-15s, 9 DNAs) — instead of a stack of separate clips. DIALOGUE IS PERFORMED NATIVELY: quoted dialogue in the prompt comes back as synced voices with lip movement, room tone and the SFX named in the AUDIO block — never route scene dialogue to generate_speech or generate_lipsync. Write dialogue in ENGLISH; other languages (Hebrew included) do not perform reliably. COST: resolution is a multiplier. When list_models publishes `video_input_credit` and this call carries videos, charge that rate against `sum(ceil(each input video duration)) + output duration`; otherwise use the normal output-second rate. PROMPT CONTRACT (Seedance / Elements): Locked Intro only — Total line, then [GLOBAL LOOK] / [CAST] / [LOCATION] / SHOT N. Do NOT write SCENE CONTEXT / OPTICS / ACTION department packs. Every Visual DNA in visual_dna_ids MUST also appear in the prompt as @ExactDNAName (e.g. "@Zohar walks…") — never "Zohar\'s" or "the man on the left" as a substitute. IMPORTANT: different models accept different numbers and durations of inputs — call list_models type="elements" and read elements_max_images / elements_max_videos / elements_max_audio plus min_video_duration / max_video_duration before generating. For text-only → video use generate_video instead. For animating a single still image use generate_video_from_image. Returns the final video URL when complete.',
1258
1258
  {
1259
1259
  prompt: z.string().describe('Locked Intro prompt (Seedance/Elements): Total line, [GLOBAL LOOK], [CAST] with @ExactDNAName for every visual_dna_ids entry, [LOCATION], then SHOT N. Not SCENE CONTEXT/OPTICS/ACTION packs. Never substitute "the left man" or "Zohar\'s" for @Name.'),
1260
1260
  model: z.string().optional().describe('Model identifier. If the user already named a family (Grok / Kling / Veo / Seedance / …), pass THAT family — never default to Seedance because Elements often uses it. Use list_models type="elements" for exact ids and elements_max_* caps. Do NOT omit (omitting = Smart Select).'),
1261
1261
  reference_images: z.array(z.string()).optional().describe('Array of image references (product shots, character references, etc.). Accepts a public URL (forwarded as-is; if the API rejects an external URL as untrusted, it is auto-rehosted into the media library and retried once) OR an absolute local path, which is uploaded for you. **Cap: pass at most `elements_max_images` URLs from list_models for the chosen model — exceeding it is a deterministic 400.**'),
1262
- reference_videos: z.array(z.string()).optional().describe('Array of reference videos for models that accept video inputs. Accepts a public URL (forwarded as-is; if the API rejects an external URL as untrusted, it is auto-rehosted into the media library and retried once) OR an absolute local path, which is uploaded for you. **Cap: pass at most `elements_max_videos` URLs from list_models if the cap is 0 the model rejects videos.**'),
1262
+ reference_videos: z.array(z.string()).optional().describe('Array of reference videos for models that accept video inputs. Accepts a public URL (forwarded as-is; if the API rejects an external URL as untrusted, it is auto-rehosted into the media library and retried once) OR an absolute local path, which is uploaded for you. **Cap: pass at most `elements_max_videos` URLs and keep every clip within `min_video_duration`-`max_video_duration` from list_models.** If `video_input_credit` is present, every attached video contributes `ceil(its duration)` to combined-second billing, in addition to output duration.'),
1263
1263
  reference_audio_urls: z.array(z.string()).optional().describe('Array of reference audio tracks for models that accept audio inputs. Accepts a public URL (forwarded as-is; if the API rejects an external URL as untrusted, it is auto-rehosted into the media library and retried once) OR an absolute local path, which is uploaded for you. **Cap: pass at most `elements_max_audio` URLs from list_models.** `audio_url` remains supported as the legacy single-track form.'),
1264
1264
  audio_url: z.string().optional().describe('A single reference audio track — legacy form of reference_audio_urls. Accepts a public URL (forwarded as-is; if the API rejects an external URL as untrusted, it is auto-rehosted into the media library and retried once) OR an absolute local path, which is uploaded for you. **Audio constraints: `elements_max_audio` from list_models gates whether audio is accepted at all; audio duration must fall within `min_audio_duration`-`max_audio_duration`; format must be in `supported_audio_formats` (if specified).**'),
1265
1265
  files: z.array(z.string()).optional().describe('Untyped catch-all for mixed media — images, videos AND audio, each a URL or an absolute local path. The kind is detected from the file extension and the item is routed to the matching reference list, so a local .mp4 is sent as a video and a local .mp3 as audio. Prefer the typed lists (reference_images / reference_videos / reference_audio_urls) when you already know the kind; they accept local paths too. URLs given here are forwarded as URLs, never re-uploaded. **Caps still apply per kind: `elements_max_images` / `elements_max_videos` / `elements_max_audio` from list_models. Local uploads are capped at 200MB each.**'),
@@ -106,6 +106,7 @@ const identifierRow = (m) => ({
106
106
  name: m.name,
107
107
  types: m.types,
108
108
  credit: m.credit,
109
+ ...(m.video_input_credit != null ? { video_input_credit: m.video_input_credit } : {}),
109
110
  ...(m.recommended ? { recommended: true } : {}),
110
111
  ...(m.new_model ? { new_model: true } : {}),
111
112
  });
@@ -115,7 +116,7 @@ function registerModelTools(server, client, options = {}) {
115
116
  // ─── list_models ───────────────────────────────────────────
116
117
  server.tool(
117
118
  'list_models',
118
- 'List available AI models on Kolbo. Filter by `type` to narrow to a generation type, and pass `format: "json"` to enumerate the catalog with exact identifiers — `format: "json"` + `type` returns the full raw model documents (every constraint field, for programmatic comparison / cap validation before submitting a generation); `format: "json"` alone returns a compact index of EVERY model and its identifier. Default `format: "text"` returns the human-readable summary. NEVER guess a model identifier: call this tool. ⚠️ COST: for any model whose type is video / firstlast / elements / motion_graphic / cast, `credit` is a PER-SECOND rate, not a per-clip price multiply by the requested `duration` before quoting cost to the user (e.g. `credit: 9` at `duration: 8` is 72 credits, not 9). This is the universal rule, not a per-model exception. The one carve-out is a model with `flat_credit_by_resolution` set those charge the flat rate regardless of duration. Every other model type (image, audio, 3D, per-token text) already bills flat per generation as `credit` states.',
119
+ 'List available AI models on Kolbo. Filter by `type` to narrow to a generation type, and pass `format: "json"` to enumerate the catalog with exact identifiers — `format: "json"` + `type` returns the full raw model documents (every constraint field, for programmatic comparison / cap validation before submitting a generation); `format: "json"` alone returns a compact index of EVERY model and its identifier. Default `format: "text"` returns the human-readable summary. NEVER guess a model identifier: call this tool. ⚠️ COST: video / firstlast / elements / motion_graphic / cast rates are normally per output second. If a model publishes `video_input_credit` and the request includes one or more input videos, use that alternate rate and bill `sum(ceil(each input video duration)) + output duration`; each input rounds separately. A `flat_credit_by_resolution` model instead charges the flat tier regardless of duration. Every other model type (image, audio, 3D, per-token text) bills as its catalog fields state.',
119
120
  {
120
121
  type: z.string().optional().describe('Filter by DB type name. Generation: "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". Image-edit engines: "image_upscale", "image_reframe", "image_zoom_out", "inpaint", "erase", "face_swap", "background_remove", "background_replace", "skin_enhancer", "graphics_enhance". Video-edit engines: "video_upscale", "video_reframe", "video_background_removal", "video_to_sound", "video_face_swap", "video_watermark_removal", "video_extend", "video_inpaint", "video_retake". For edit_image/edit_video, query the operation-specific type and pass a CONCRETE returned identifier; never submit a kolbo_gateway_* row, because those are web-navigation aliases rather than AI engines. Legacy aliases also accepted: "image", "image_edit", "video", "video_from_image", "video_from_video", "music", "speech", "sound", "chat", "lipsync", "three_d", "first_last_frame", "transcription". Omit for all models.'),
121
122
  format: z.enum(['text', 'json']).optional().describe('Output format. "text" (default) returns a human-readable summary with the most-used caps. "json" is the source of truth for identifiers and caps: with `type` it returns the raw model documents from the API (identifier, credit, supported_durations, supported_resolutions, supported_aspect_ratios, max_reference_images, max_visual_dna, max_video_duration, …) for EVERY model of that type; without `type` it returns a compact index of every model in the catalog and its exact identifier. Use it whenever you need an identifier you have not seen listed, or must verify a cap before passing a value that might exceed a model-specific limit.'),
@@ -213,6 +214,14 @@ function registerModelTools(server, client, options = {}) {
213
214
  );
214
215
  }
215
216
 
217
+ if (m.video_input_credit != null) {
218
+ const vm = m.video_input_resolution_multipliers || {};
219
+ const tiers = Object.keys(vm).length
220
+ ? ' · ' + Object.entries(vm).map(([r, mult]) => `${r} (${mult}×)`).join(' · ')
221
+ : '';
222
+ parts.push(`video_input_price: ${m.video_input_credit} credits/combined-second${tiers} · bill sum(ceil(each input video)) + output`);
223
+ }
224
+
216
225
  // Output durations (video gen output, not source video)
217
226
  if (Array.isArray(m.supported_durations) && m.supported_durations.length) {
218
227
  const ds = m.supported_durations;
@@ -369,7 +378,7 @@ function registerModelTools(server, client, options = {}) {
369
378
  const cost = m => (m.output_token_rate != null
370
379
  ? `${m.input_token_rate ?? '?'}/${m.output_token_rate} credits per 1K tokens (in/out)`
371
380
  : isPerSecondVideo(m)
372
- ? `${m.credit} credits/second requested duration NOT a flat per-clip price)`
381
+ ? `${m.credit} credits/output-second${m.video_input_credit != null ? `; ${m.video_input_credit} credits/combined-second with video input` : ''}`
373
382
  : `${m.credit} credits`);
374
383
  const formatModel = m =>
375
384
  `${m.identifier} (${m.name}) - ${cost(m)}${m.recommended ? ' [RECOMMENDED]' : ''}${m.new_model ? ' [NEW]' : ''}${m.summary ? ` — ${detailed ? m.summary : brief(m.summary)}` : ''}${detailed ? formatSpecs(m) : ''}`;