@kolbo/mcp 1.81.2 → 1.81.5
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/README.md +5 -2
- package/package.json +1 -1
- package/skill/GENERATED.md +1 -1
- package/skill/SKILL.md +68 -89
- package/skill/VERSION +1 -1
- package/skill/references/models/creative-director.md +2 -8
- package/skill/references/models/music.md +1 -1
- package/skill/references/models/prompt-copilot.md +1 -1
- package/skill/references/models/seedance.md +5 -21
- package/skill/references/models/seedance25.md +1 -1
- package/skill/references/models/veo.md +1 -1
- package/skill/references/workflows/color-dna.md +12 -0
- package/skill/references/workflows/cost-and-validation.md +6 -26
- package/skill/references/workflows/dtc-ads.md +1 -1
- package/skill/references/workflows/filmmaking.md +1 -25
- package/skill/references/workflows/marketing-studio.md +14 -14
- package/skill/references/workflows/media-library.md +11 -1
- package/skill/references/workflows/product-photoshoot.md +1 -1
- package/skill/references/workflows/production-log.md +2 -14
- package/skill/references/workflows/production-planning.md +6 -5
- package/skill/references/workflows/review-collections.md +98 -0
- package/skill/references/workflows/troubleshooting.md +2 -8
- package/skill/references/workflows/visual-dna.md +5 -34
- package/src/apps/bridge.js +4 -0
- package/src/apps/html.js +2 -1
- package/src/apps/index.js +1 -0
- package/src/apps/theme.js +2 -1
- package/src/apps/widgets/catalog.js +1 -1
- package/src/apps/widgets/generation.js +67 -17
- package/src/apps/widgets/list.js +6 -6
- package/src/apps/widgets/mediaGrid.js +3 -6
- package/src/tools/_shared.js +55 -9
- package/src/tools/generate.js +21 -9
- package/src/tools/projects.js +41 -9
|
@@ -52,30 +52,6 @@ Compile only what the current generation needs. A video model cannot resolve “
|
|
|
52
52
|
|
|
53
53
|
Kolbo Visual DNA is semantic project truth, not merely reference imagery. Read and preserve the saved DNA type and analyzed context: character DNAs own identity/state/performance/voice; environment and scene DNAs own location/geography/light; product DNAs own prop/product identity, scale, material, and state; style DNAs own the visual register. Keep exact tags and never reinterpret one DNA type as another.
|
|
54
54
|
|
|
55
|
-
## Choose control density
|
|
56
|
-
|
|
57
|
-
Never equate sophistication with maximum length.
|
|
58
|
-
|
|
59
|
-
- **Strict** — lock exact blocking, count, timing, dialogue, hand/prop state, axis, scale, or failure-prone physics. Use for continuity-heavy dialogue, expensive hero shots, repeated failures, and exact music synchronization.
|
|
60
|
-
- **Anchored** — dictate non-negotiable story/continuity/physics anchors and allow camera or performance variation inside them. Use for complex spectacle where controlled discovery is valuable.
|
|
61
|
-
- **Exploratory** — protect identity, world, safety, and essential beats while inviting coverage variations. Use for montage, inserts, music-video coverage, and ideation.
|
|
62
|
-
|
|
63
|
-
If the user supplied an exact prompt, preserve its chosen density unless the failure diagnosis proves density itself is the problem.
|
|
64
|
-
|
|
65
|
-
## Select craft packs
|
|
66
|
-
|
|
67
|
-
Load only what the shot needs:
|
|
68
|
-
|
|
69
|
-
- Story causality and scene reversals: [scene-engine.md](references/filmmaking/scene-engine.md)
|
|
70
|
-
- Asset building, versions, and stress tests: [asset-preproduction.md](references/filmmaking/asset-preproduction.md)
|
|
71
|
-
- Character performance, listening, and voice identity: [acting-direction.md](references/filmmaking/acting-direction.md)
|
|
72
|
-
- Geography, axes, eyelines, diagrams, and state continuity: [blocking-continuity.md](references/filmmaking/blocking-continuity.md)
|
|
73
|
-
- Shot size, optics, operator behavior, and visual grammar: [cinematography.md](references/filmmaking/cinematography.md)
|
|
74
|
-
- Action feasibility, mass, materials, transformations, and impossible shots: [physics-action.md](references/filmmaking/physics-action.md)
|
|
75
|
-
- Dialogue, ambience, native audio, source-song performance, and post music: [audio-dialogue-music.md](references/filmmaking/audio-dialogue-music.md)
|
|
76
|
-
|
|
77
|
-
Do not paste every craft pack into every prompt. Translate the selected pack into the shortest observable instructions that preserve the intended result.
|
|
78
|
-
|
|
79
55
|
## Compile a shot
|
|
80
56
|
|
|
81
57
|
Read [prompt-contracts.md](references/filmmaking/prompt-contracts.md) for exact structures.
|
|
@@ -92,7 +68,7 @@ Before writing, establish:
|
|
|
92
68
|
8. Audio ownership, exact words/lyrics, and whether music is native, source-driven, or reserved for post.
|
|
93
69
|
9. Model capability limits and target generation mode.
|
|
94
70
|
|
|
95
|
-
Prompt-length limits apply to the entire compiled generation prompt as one string, including whitespace, headers, timecodes, dialogue, audio, and locks. Count after compilation
|
|
71
|
+
Prompt-length limits apply to the entire compiled generation prompt as one string, including whitespace, headers, timecodes, dialogue, audio, and locks. Count after compilation; read the cap from `max_prompt_length` via `list_models` (see `models/seedance25.md`).
|
|
96
72
|
|
|
97
73
|
**Seedance 2 / Seedance 2.5 / `generate_elements` — Locked Intro is the only compile shape.** Read `references/models/seedance.md` (and `seedance25.md` for 2.5 caps). Do not emit the SCENE CONTEXT / OPTICS / ACTION department pack below as the generation prompt. Every Visual DNA in play must be `@ExactName` in CAST and in each shot — never "the left man" or a possessive.
|
|
98
74
|
|
|
@@ -44,15 +44,17 @@ If the user mentions a product / brand but no mode word, default to `ugc`. If th
|
|
|
44
44
|
|
|
45
45
|
The mode determines which Kolbo MCP tool to call, what defaults to set, and what's forbidden.
|
|
46
46
|
|
|
47
|
-
| Mode | Primary tool |
|
|
48
|
-
|
|
49
|
-
| `ugc`, `ugc_how_to`, `ugc_unboxing`, `ugc_virtual_try_on`, `product_review` | `generate_video_from_image` (frame-first) OR `generate_elements` (Visual DNA → video) |
|
|
50
|
-
| `product_showcase` | `generate_creative_director` with `workflow_type: "video"` (for multi-shot) OR `generate_video` (single) |
|
|
51
|
-
| `tv_spot` | `generate_creative_director` with `workflow_type: "video"` (3–6 shots for a beat structure) |
|
|
52
|
-
| `virtual_try_on` | `generate_elements` with character Visual DNA + product as `reference_images` |
|
|
53
|
-
| `wild_card` | User's chosen model with broader prompt latitude (no mode-specific defaults) |
|
|
47
|
+
| Mode | Primary tool |
|
|
48
|
+
|---|---|
|
|
49
|
+
| `ugc`, `ugc_how_to`, `ugc_unboxing`, `ugc_virtual_try_on`, `product_review` | `generate_video_from_image` (frame-first) OR `generate_elements` (Visual DNA → video) |
|
|
50
|
+
| `product_showcase` | `generate_creative_director` with `workflow_type: "video"` (for multi-shot) OR `generate_video` (single) |
|
|
51
|
+
| `tv_spot` | `generate_creative_director` with `workflow_type: "video"` (3–6 shots for a beat structure) |
|
|
52
|
+
| `virtual_try_on` | `generate_elements` with character Visual DNA + product as `reference_images` |
|
|
53
|
+
| `wild_card` | User's chosen model with broader prompt latitude (no mode-specific defaults) |
|
|
54
|
+
|
|
55
|
+
Aspect / duration / sound / captions defaults for the `ugc*` family live in "UGC Family Defaults" below.
|
|
54
56
|
|
|
55
|
-
**Pick the actual model** with `list_models({ type: "..." })` and validate caps before firing — see
|
|
57
|
+
**Pick the actual model** with `list_models({ type: "..." })` and validate caps before firing — see `references/workflows/cost-and-validation.md`.
|
|
56
58
|
|
|
57
59
|
## The Look Itself — read `workflows/ugc-smartphone.md`
|
|
58
60
|
|
|
@@ -149,8 +151,7 @@ Scale to 2–6 slots. Keep `hook → demo → payoff` as the minimum arc; add `t
|
|
|
149
151
|
### 2. Rendering rules (hard invariants — apply to EVERY slot)
|
|
150
152
|
|
|
151
153
|
- One aspect ratio across all slots (UGC = `9:16`). Never mix.
|
|
152
|
-
- **
|
|
153
|
-
- **Identity lock**: same presenter, same wardrobe, same lighting environment across all slots — open the prompt with `same character throughout all shots`.
|
|
154
|
+
- **Identity lock**: same presenter, same wardrobe, same lighting environment across all slots — bind identity by tagging `@<dna-name>` in every slot description (identity binds via the DNA; the phrase "same character throughout all shots" is FORBIDDEN — see `models/seedance.md`).
|
|
154
155
|
- Hands and product must read cleanly — no deformed hands, no floating / clipping product, product logo legible when held.
|
|
155
156
|
- Phone-shot aesthetic (handheld sway, window/screen key) unless the mode is polished (`tv_spot`, `product_showcase`).
|
|
156
157
|
|
|
@@ -183,7 +184,7 @@ Track these so each slot's call is reproducible and the arc stays coherent:
|
|
|
183
184
|
Brief: *"15s UGC review of a skincare serum, tech-savvy woman creator."*
|
|
184
185
|
|
|
185
186
|
1. Ensure/create presenter Visual DNA (tech-savvy woman) → `visual_dna_id`.
|
|
186
|
-
2. Board: `generate_image` a 3-panel `16:9` sheet — (a) chest-up hook holding the serum, (b) hands applying it, (c) thumbs-up reaction —
|
|
187
|
+
2. Board: `generate_image` a 3-panel `16:9` sheet — (a) chest-up hook holding the serum, (b) hands applying it, (c) thumbs-up reaction — `@<dna-name>` tagged in every panel description, locked to the DNA. → `board_media_id`.
|
|
187
188
|
3. Slots (each `9:16`, ~5s, sound OFF, animate from the matching board panel + product `@image2`):
|
|
188
189
|
- Slot 1 (hook): "Before this serum my routine was five products…" holding it to camera.
|
|
189
190
|
- Slot 2 (demo): hands applying, product in active use.
|
|
@@ -194,9 +195,8 @@ Brief: *"15s UGC review of a skincare serum, tech-savvy woman creator."*
|
|
|
194
195
|
|
|
195
196
|
1. **Always pick a mode explicitly.** Don't auto-pick from one ambiguous word. If the user said "make me an ad" with no other signal, offer labeled options: `[UGC / TV Spot / Product Showcase / Surprise me]`.
|
|
196
197
|
2. **Always confirm aspect ratio + duration + sound** before firing — these materially change output and cost. One question, labeled options.
|
|
197
|
-
3. **
|
|
198
|
-
4. **
|
|
199
|
-
5. **Show results without dumping URLs** — see SKILL.md "Generated URLs in chat".
|
|
198
|
+
3. **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 prompt or product.
|
|
199
|
+
4. **Show results without dumping URLs** — see SKILL.md "Generated URLs in chat".
|
|
200
200
|
|
|
201
201
|
## Prompt Template Seed for UGC
|
|
202
202
|
|
|
@@ -70,7 +70,7 @@ fails to open (exit 26).
|
|
|
70
70
|
|
|
71
71
|
| User says | Call |
|
|
72
72
|
|---|---|
|
|
73
|
-
| "Upload this file" / "host this" / "give me a public URL for this" | `upload_media` — but see "Local files"
|
|
73
|
+
| "Upload this file" / "host this" / "give me a public URL for this" | `upload_media` — but see "Local files" above if it's a path on the user's disk |
|
|
74
74
|
| "Show my media" / "list my images/videos" / "what do I have?" | `list_media` (pass `type` / `category` / `project_id` / `folder_id` / `search`) |
|
|
75
75
|
| "Show my favorites" / "list starred items" | `list_media` with `category=favorites` |
|
|
76
76
|
| "List everything in project X" | `list_media` with `project_id=X` |
|
|
@@ -110,3 +110,13 @@ fails to open (exit 26).
|
|
|
110
110
|
8. **Bulk caps:** 1000 ids for `bulk_delete_media` / `bulk_restore_media` / `bulk_permanently_delete_media` / `bulk_move_media`; 500 ids for `add_media_to_folder` / `remove_media_from_folder`. Split larger jobs into successive calls.
|
|
111
111
|
9. **Folder share resolution:** `share_media_folder` takes emails; users not found come back in `not_found`. Report those to the user — don't assume the share succeeded silently. Members can list/add/remove items but cannot delete the folder or reshare it.
|
|
112
112
|
10. **`get_media` accepts a generation_id as a fallback** for the `media_id` arg, so you can chase down items the user references by their original generation rather than by library id.
|
|
113
|
+
|
|
114
|
+
## SYNCI licensed music — operational detail
|
|
115
|
+
|
|
116
|
+
The `*_music_library` tools (`search_music_library` / `browse_music_library` / `get_music_library_facets` / `get_music_track_audio` / `get_music_track_lyrics` / `get_music_track_related` / `analyze_script_for_music` / `acquire_clean_music_track` / `import_music_track_to_library`) front **SYNCI**, a commercially licensed catalog — not free stock.
|
|
117
|
+
|
|
118
|
+
- Discovery and previews are free but **watermarked** — there is no unwatermarked URL until you pay.
|
|
119
|
+
- `acquire_clean_music_track` **CHARGES CREDITS** for the clean master. Confirm with the user first, and pass a stable `requestId` so a retry doesn't buy the track twice.
|
|
120
|
+
- `import_music_track_to_library` charges the same way AND also copies the clean track into the media library.
|
|
121
|
+
- `analyze_script_for_music` turns a script into search terms for `search_music_library`.
|
|
122
|
+
- Use this family when the user needs music cleared for commercial use. When free stock will do, use `search_stock_media` with `mediaType: "music"` instead.
|
|
@@ -61,7 +61,7 @@ The mode determines which Kolbo MCP tool to call and what defaults to use.
|
|
|
61
61
|
|
|
62
62
|
**For multi-output modes** (`social_carousel`, `ad_creative_pack`), always use `generate_creative_director` — never fire ≥2 `generate_image` calls in a loop. See `models/creative-director.md`.
|
|
63
63
|
|
|
64
|
-
**Always validate** `aspect_ratio` and `resolution` against the chosen model's `supported_aspect_ratios` / `supported_resolutions` via `list_models` — see
|
|
64
|
+
**Always validate** `aspect_ratio` and `resolution` against the chosen model's `supported_aspect_ratios` / `supported_resolutions` via `list_models` — see `references/workflows/cost-and-validation.md`.
|
|
65
65
|
|
|
66
66
|
## Pre-Generation Interview (CRITICAL)
|
|
67
67
|
|
|
@@ -38,20 +38,8 @@ The log records **what the user approved** — not everything you produced. Gett
|
|
|
38
38
|
|
|
39
39
|
**Never write an artifact into the log as approved without the user's approval.**
|
|
40
40
|
|
|
41
|
-
If they
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
```
|
|
45
|
-
GATE — <bucket name>
|
|
46
|
-
Presented: <what is in play>
|
|
47
|
-
Lock + next: "lock <bucket>" / "yes" / "next" / "now <next bucket>"
|
|
48
|
-
Stay: "redo @name" / "another take of …"
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
Confirmation the agent may treat as a lock: `yes`, `ok`, `lock`, `approved`,
|
|
52
|
-
`that's the one`, `use take 2`, `next`, `go`, `continue`, or they name the next
|
|
53
|
-
planned bucket while treating this set as done. Silence / "maybe" / a new
|
|
54
|
-
question is **not** a lock — repeat the GATE once, do not invent a yes.
|
|
41
|
+
If they didn't volunteer a yes, end the turn with the GATE block from
|
|
42
|
+
`production-planning.md` §3.
|
|
55
43
|
|
|
56
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.
|
|
57
45
|
|
|
@@ -143,11 +143,12 @@ the next planned bucket in **its** session.
|
|
|
143
143
|
Only now compile shots. Defaults:
|
|
144
144
|
|
|
145
145
|
- **`generate_elements` with Seedance 2.5** (`seedance-2-5`) for the film itself —
|
|
146
|
-
up to 30s and 30 shots in ONE generation,
|
|
147
|
-
|
|
148
|
-
the primary reference-driven route.
|
|
149
|
-
- **Seedance 2.0** (`seedance-2`, cheaper, 4–15s,
|
|
150
|
-
|
|
146
|
+
up to 30s and 30 shots in ONE generation, dialogue and SFX baked in. DNA cap:
|
|
147
|
+
read `max_visual_dna` from `list_models`. `generate_video` also accepts
|
|
148
|
+
`visual_dna_ids` now; Elements remains the primary reference-driven route.
|
|
149
|
+
- **Seedance 2.0** (`seedance-2`, cheaper, 4–15s, smaller DNA cap per
|
|
150
|
+
`list_models`) when the piece is short and the cast is small.
|
|
151
|
+
`seedance-2-fast` / `seedance-2-mini` for cheap blocking.
|
|
151
152
|
- Every DNA in `visual_dna_ids` must also appear as `@ExactName` in the prompt.
|
|
152
153
|
- Dialogue in quotes inside its shot beat — English only, never TTS or lipsync.
|
|
153
154
|
See `models/seedance25.md`.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Kolbo Review — client review & approval collections
|
|
2
|
+
|
|
3
|
+
Load this file when the user wants **feedback on finished media**: send a cut to a client,
|
|
4
|
+
collect timestamped comments, run an approve / request-changes loop, ship a v2 against the
|
|
5
|
+
same feedback thread, or share work with someone who has no Kolbo account. This is a
|
|
6
|
+
Frame.io-style layer over the media library — assets, versions, comments, statuses, and
|
|
7
|
+
guest share links — all project-scoped like everything else in Kolbo.
|
|
8
|
+
|
|
9
|
+
Not for: publishing a page (`publish_html_artifact`), sharing a whole media folder
|
|
10
|
+
(`share_media_folder`), or internal doc collaboration (`share_doc`).
|
|
11
|
+
|
|
12
|
+
## Tool inventory
|
|
13
|
+
|
|
14
|
+
| Tool | What it does |
|
|
15
|
+
|---|---|
|
|
16
|
+
| `create_review_asset` | New review asset with v1 media attached (`name`, `media_id`, optional `collection_id`, `version_note`). |
|
|
17
|
+
| `list_review_assets` / `get_review_asset` | Browse a project's review assets (filter by `collection_id` / `status`); fetch one with all versions + URLs. |
|
|
18
|
+
| `update_review_asset` | Rename, move to a collection (`collection_id: null` = uncollected), or switch `current_version_index`. |
|
|
19
|
+
| `add_review_version` | Append a new version to an existing asset from a `media_id`. |
|
|
20
|
+
| `set_review_status` | Workflow status: `in_progress` / `needs_review` / `approved` / `changes_requested`. |
|
|
21
|
+
| `delete_review_asset` | Soft-delete an asset AND its underlying review media. |
|
|
22
|
+
| `create_review_collection` / `list_review_collections` / `update_review_collection` / `delete_review_collection` | Folder layer. Deleting a collection is soft — its assets become uncollected, not deleted. |
|
|
23
|
+
| `create_review_comment` / `list_review_comments` / `reply_review_comment` / `edit_review_comment` / `delete_review_comment` | Text comments, optional video timecodes (`time_start` / `time_end`, seconds). One level of reply threading. |
|
|
24
|
+
| `resolve_review_comment` / `unresolve_review_comment` | Close / reopen a comment thread. |
|
|
25
|
+
| `create_review_share_link` / `list_review_share_links` / `revoke_review_share_link` | Guest links (no Kolbo account) for one asset or a whole collection. |
|
|
26
|
+
| `get_review_storage_usage` | `usedBytes` vs the 5GB review cap for the API-key owner. |
|
|
27
|
+
|
|
28
|
+
## The core flow
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
upload_media (or reuse a generation's media_id from list_media)
|
|
32
|
+
→ create_review_collection (only if grouping multiple assets)
|
|
33
|
+
→ create_review_asset ← media becomes v1
|
|
34
|
+
→ set_review_status "needs_review"
|
|
35
|
+
→ create_review_share_link ← hand the client the share_url
|
|
36
|
+
→ list_review_comments ← read what came back
|
|
37
|
+
→ fix → add_review_version ← v2 on the SAME asset
|
|
38
|
+
→ resolve_review_comment on each addressed note
|
|
39
|
+
→ set_review_status "approved" (usually the client does this via the link)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Media must already exist in the library — every attach point takes a `media_id` from
|
|
43
|
+
`upload_media` / `create_upload_ticket` / `media_upload_widget` / `list_media`, never a raw
|
|
44
|
+
URL or local path.
|
|
45
|
+
|
|
46
|
+
## Version semantics
|
|
47
|
+
|
|
48
|
+
- Versions **append**; labels are auto-set `v1`, `v2`, … — you can't choose or reorder them.
|
|
49
|
+
- `add_review_version` automatically makes the new version current. Use
|
|
50
|
+
`update_review_asset({ current_version_index })` only to point BACK at an older cut.
|
|
51
|
+
- **Comments attach to a version's media**, not the asset. `list_review_comments` defaults
|
|
52
|
+
to the current version — after adding v2, pass `version_media_id` to re-read v1 feedback.
|
|
53
|
+
Comments do not carry forward; the v2 thread starts clean.
|
|
54
|
+
- Never delete+recreate an asset to "update" it — that orphans the comment history and
|
|
55
|
+
every share link already sent to the client. New cut = `add_review_version`. Rename /
|
|
56
|
+
re-file = `update_review_asset`. Delete is for abandoning the review entirely.
|
|
57
|
+
|
|
58
|
+
## Share links — permissions and defaults
|
|
59
|
+
|
|
60
|
+
`create_review_share_link` targets an `asset` or a `collection` (collection links cover
|
|
61
|
+
every asset inside, including ones added later). Guest defaults if you pass nothing:
|
|
62
|
+
|
|
63
|
+
| Permission | Default |
|
|
64
|
+
|---|---|
|
|
65
|
+
| `canComment`, `canViewOtherComments`, `canSwitchVersions` | **true** |
|
|
66
|
+
| `canDownload`, `canResolveOwn`, `canSetStatus` | **false** |
|
|
67
|
+
| `require_email` | **true** — guests identify by email before viewing |
|
|
68
|
+
| `role_label` | `"Client"` (max 40 chars) |
|
|
69
|
+
|
|
70
|
+
- Want the client to approve directly? Pass `permissions: { canSetStatus: true }` —
|
|
71
|
+
otherwise they can only comment and you relay the verdict via `set_review_status`.
|
|
72
|
+
- Lockdown options: `password` (a NEW guest password — never an account credential),
|
|
73
|
+
`allowed_emails`, `expires_at` (ISO8601).
|
|
74
|
+
- Links are revoked by id (`revoke_review_share_link`), not edited — to change permissions,
|
|
75
|
+
create a new link and revoke the old one. This is the one place recreate IS the mechanism.
|
|
76
|
+
- When someone other than the owner sets a status, the owner gets a notification — don't
|
|
77
|
+
also announce it manually.
|
|
78
|
+
|
|
79
|
+
## Storage — the 5GB cap
|
|
80
|
+
|
|
81
|
+
Review media is **copied into dedicated review storage** and counts against a flat 5GB cap
|
|
82
|
+
per account — separate from library storage. The cap is enforced on `create_review_asset`
|
|
83
|
+
AND `add_review_version`; hitting it returns `REVIEW_STORAGE_LIMIT` (413). That error is a
|
|
84
|
+
real limit, not a transient failure — don't retry. Check `get_review_storage_usage`
|
|
85
|
+
(`usedBytes` / `capBytes`) before bulk-adding large videos, and free space by deleting
|
|
86
|
+
finished review assets (the library originals are untouched).
|
|
87
|
+
|
|
88
|
+
## Practical notes
|
|
89
|
+
|
|
90
|
+
- All of this is instant CRUD — no credits, no polling, no `get_generation_status`.
|
|
91
|
+
- Project contract applies: pass the same `project_id` you resolved via `list_projects` on
|
|
92
|
+
`create_review_asset` / `create_review_collection` / the list calls.
|
|
93
|
+
- `status` filter on `list_review_assets` takes exactly the four enum values — "pending" /
|
|
94
|
+
"done" are not statuses.
|
|
95
|
+
- Comment ids are `note_id` in the reply/edit/delete/resolve tools; version notes cap at
|
|
96
|
+
1000 chars.
|
|
97
|
+
- Guests can only resolve their own comments, and only if you granted `canResolveOwn` — the
|
|
98
|
+
resolve loop on client feedback is normally yours to run after fixing.
|
|
@@ -26,9 +26,9 @@ If Kolbo tools timeout or aren't listed, the MCP server may not be wired. Tell t
|
|
|
26
26
|
```
|
|
27
27
|
This re-wires the MCP configuration automatically. Then restart the session.
|
|
28
28
|
|
|
29
|
-
##
|
|
29
|
+
## Generation status, waiting, black cards
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
Status semantics, `wait=true` batching, black-card-is-normal and the credit guard live in SKILL.md "⚠️ Generation lifecycle — source of truth, waiting, failures".
|
|
32
32
|
|
|
33
33
|
## "Rate limited" (429 errors)
|
|
34
34
|
|
|
@@ -47,12 +47,6 @@ Call `list_color_palettes` and look for `is_active: true`. Then either
|
|
|
47
47
|
grade by writing colours into the prompt — the palette is applied after, and the
|
|
48
48
|
prompt loses.
|
|
49
49
|
|
|
50
|
-
## Checking generation status without spinning
|
|
51
|
-
|
|
52
|
-
`get_generation_status` supports `wait=true` (blocks server-side until the generation reaches a final state, up to ~3 min) and `generation_ids` (many ids in one call → returns `all_done`, `still_processing`, and per-generation results). **Never call it repeatedly in a loop** — one `wait=true` call replaces the loop. If some generations are still running after the wait window, call it ONCE more with `wait=true` and only the `still_processing` ids.
|
|
53
|
-
|
|
54
|
-
**Credit guard:** after a generate tool returns `submitted` / `_timed_out`, do not keep thinking or editing files while the card spins — that burns coding credits. End the turn, or make **one** `wait=true` status call if you need the URLs next.
|
|
55
|
-
|
|
56
50
|
## Failure envelope from `get_generation_status`
|
|
57
51
|
|
|
58
52
|
When a generation fails, `get_generation_status` returns a structured `failure` field alongside `error`:
|
|
@@ -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. **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 **that share the same identity and vibe**; never pass 5+). Optionally video and audio. See **Purity**
|
|
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 **that share the same identity and vibe**; never pass 5+). Optionally video and audio. See **Purity** below before you generate those stills.
|
|
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`.
|
|
@@ -22,7 +22,7 @@ Visual DNA profiles capture the visual "identity" of a character, style, product
|
|
|
22
22
|
Kolbo no longer sends only the first still or the character sheet. For every attached DNA:
|
|
23
23
|
|
|
24
24
|
1. **User-uploaded refs take image slots first.**
|
|
25
|
-
2. **Remaining slots:** one main still per DNA, then leftover stills from each DNA **round-robin** until the model's image-slot cap (`
|
|
25
|
+
2. **Remaining slots:** one main still per DNA, then leftover stills from each DNA **round-robin** until the model's image-slot cap (`elements_max_images` / equivalent) is full.
|
|
26
26
|
3. **If every still fits the cap, every still is sent** as its own reference. A 4-image character DNA on a 9-slot model is four slots, not one.
|
|
27
27
|
4. **If a DNA only gets one leftover slot**, has **no distinct character sheet**, and still has unused stills, those leftovers are composited into a **white grid / collage** (up to 9 cells) so the model still sees them. A real character sheet is never overwritten by a collage.
|
|
28
28
|
5. **Native Kling Elements** stays one element per DNA (sheet / frontal). Other providers use the slot pack above.
|
|
@@ -104,16 +104,7 @@ Fields to read for the image source (use the first one present on the item): `th
|
|
|
104
104
|
|
|
105
105
|
## ⚠️ @name Syntax — ALWAYS use it when passing visual_dna_ids (MANDATORY)
|
|
106
106
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
**Use the actual stored name, programmatically.** When you call `list_visual_dnas` (or `create_visual_dna`), read the `name` field off the response and use that exact string after the `@`. Do NOT:
|
|
110
|
-
|
|
111
|
-
- Translate the name into another language ("אסתר" / "esther" / "אסתי" — pick whichever string is in `name` and use ONLY that one).
|
|
112
|
-
- Invent a friendlier alias ("the model", "המודל", "her", "Zohar's", "the left man", "the man on the LEFT").
|
|
113
|
-
- Write a "Visual DNA anchors:" prose block that describes position/wardrobe but never writes `@ExactName`.
|
|
114
|
-
- Write the character's name in plain text without the `@` prefix.
|
|
115
|
-
- 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.
|
|
116
|
-
- **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.
|
|
107
|
+
SKILL.md's `@Name` hard rule applies; here is why it binds that way:
|
|
117
108
|
|
|
118
109
|
**Wrong** (DNA `name` is `esther_model`, user wrote prompt in Hebrew):
|
|
119
110
|
```
|
|
@@ -228,31 +219,11 @@ You can combine all three reference types in a single call — they're additive,
|
|
|
228
219
|
|
|
229
220
|
## Visual DNA Limits
|
|
230
221
|
|
|
231
|
-
Read `max_visual_dna` from `list_models` for the
|
|
222
|
+
Read `max_visual_dna` (and `elements_max_images` for image-slot packing) from `list_models` for the chosen model, AND `supports_visual_dna` for the on/off boolean. A model can support DNA without an explicit cap, or have a non-null cap but silently ignore DNA on certain paths (e.g. `generate_video`). Typical ranges: image models (non-Kling) up to **8**, Kling image models **3**, Elements video models **3–5**, everything else up to **3**.
|
|
232
223
|
|
|
233
224
|
## ⚠️ Visual DNA Creation — Always Generate Reference Images First (MANDATORY)
|
|
234
225
|
|
|
235
|
-
**Before calling `create_visual_dna` for a character**,
|
|
236
|
-
|
|
237
|
-
**Step 1 — Generate both images in parallel (one `generate_image` call each, fire simultaneously):**
|
|
238
|
-
|
|
239
|
-
1. **4-angle character sheet** — prompt: `"[character description], character reference sheet showing front view, back view, left side view, right side view, four panels arranged in a 2x2 grid, neutral solid background, full body, photorealistic"`, aspect ratio `16:9` (or `3:2` — always landscape, see the aspect-ratio rule below)
|
|
240
|
-
2. **Close-up portrait** — prompt: `"[character description], close-up portrait, face and shoulders, neutral solid background, soft studio lighting, photorealistic"`, aspect ratio `1:1`
|
|
241
|
-
|
|
242
|
-
**Step 2 — Call `create_visual_dna`** with:
|
|
243
|
-
- `images`: the 4-angle sheet URL first, then the close-up URL — **plus** the user's reference photo(s) only if they provided one (i.e. a real person or existing character they want to match). If they gave no reference image, the 2 generated images alone are sufficient.
|
|
244
|
-
- `type`: `"character"`
|
|
245
|
-
- `name`: single-token lowercase descriptive name (see naming rule above)
|
|
246
|
-
|
|
247
|
-
**Why:** A single reference photo only shows one angle. The close-up gives the engine facial detail; the 4-angle sheet gives it body geometry and pose range. Together they produce far more consistent generations. Both stills (and any user photos you add) must be the **same person, same vibe** — they will all be packed into the next generation.
|
|
248
|
-
|
|
249
|
-
**Skip this only if** the user explicitly says "just use my image as-is" or provides 3+ reference images already covering multiple angles.
|
|
250
|
-
|
|
251
|
-
### Environments, products, style — same precision
|
|
252
|
-
|
|
253
|
-
- **Environment / location:** generate empty (or crowd-only) plates. Prompt out heroes and readable faces. A location DNA that contains `@maya` in the frame will put Maya in every later shot of that place.
|
|
254
|
-
- **Product:** isolated angles, consistent lighting, readable label. No extra hero unless the product is worn and the body is generic.
|
|
255
|
-
- **Style:** one look, applied cleanly. Do not mix neon-cyber and dusty-western stills on the same style DNA.
|
|
226
|
+
**Before calling `create_visual_dna` for a character**, generate the reference stills first — a multi-angle sheet plus a close-up gives the engine far better coverage than a single photo. Route the stills through the **preset contract** (`list_presets` search → `preset_id` on `generate_image`), never a raw hand-written sheet prompt — see "Character sheet — default for production assets" below for the full flow, preset search terms, and aspect-ratio rules. Include the user's reference photo(s) alongside only if they provided one. **Skip this only if** the user explicitly says "just use my image as-is" or provides 3+ reference images already covering multiple angles.
|
|
256
227
|
|
|
257
228
|
## When to Use
|
|
258
229
|
|
package/src/apps/bridge.js
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
* .onThemeChange(fn) — fn(hostContext) on host-context-changed
|
|
23
23
|
* .callTool(name, args) — Promise<CallToolResult>
|
|
24
24
|
* .sendMessage(text) — append a user chat message (returns Promise)
|
|
25
|
+
* .insertText(text) — paste into the host composer, do not send
|
|
25
26
|
* .openLink(url) — open external URL
|
|
26
27
|
* .copyText(text) — copy via the host clipboard (ui/copy-text)
|
|
27
28
|
* .notifySize() — report content size to host
|
|
@@ -183,6 +184,9 @@ const BRIDGE_JS = `
|
|
|
183
184
|
sendMessage: function (text) {
|
|
184
185
|
return request('ui/message', { role: 'user', content: [{ type: 'text', text: text }] });
|
|
185
186
|
},
|
|
187
|
+
insertText: function (text) {
|
|
188
|
+
return request('ui/insert-text', { text: text });
|
|
189
|
+
},
|
|
186
190
|
openLink: function (url) { return request('ui/open-link', { url: url }); },
|
|
187
191
|
copyText: function (text) { return request('ui/copy-text', { text: text }); },
|
|
188
192
|
// Hand a piece of this widget's media to the host's composer. Dragging it
|
package/src/apps/html.js
CHANGED
|
@@ -136,7 +136,8 @@ function modelChipHTML(name, iconUrl) {
|
|
|
136
136
|
return '<span class="k-chip brand">' + inner + esc(name) + '</span>';
|
|
137
137
|
}
|
|
138
138
|
function monogram(name) {
|
|
139
|
-
|
|
139
|
+
var ch = String(name || '').replace(/^[@#]+/, '').trim().charAt(0) || '?';
|
|
140
|
+
return '<span class="k-mono-icon">' + esc(ch.toUpperCase()) + '</span>';
|
|
140
141
|
}
|
|
141
142
|
// In-widget preview overlay — every card (generation chips, media grid, list
|
|
142
143
|
// rows) uses this so a DNA / reference / library thumb opens a popup in Kolbo
|
package/src/apps/index.js
CHANGED
package/src/apps/theme.js
CHANGED
|
@@ -340,7 +340,8 @@ html.k-fullscreen .k-actions { flex: none; padding-top: 8px; }
|
|
|
340
340
|
background: var(--brand-soft); }
|
|
341
341
|
.k-audio-meta { flex: 1; min-width: 0; }
|
|
342
342
|
.k-audio-title { font-size: 12.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
343
|
-
.k-audio-sub { font-size: 11px; color: var(--text-faint);
|
|
343
|
+
.k-audio-sub { font-size: 11px; color: var(--text-faint);
|
|
344
|
+
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
|
|
344
345
|
.k-generated-audio {
|
|
345
346
|
display: grid; grid-template-columns: 40px minmax(0, 1fr) auto;
|
|
346
347
|
align-items: center; gap: 7px 10px;
|
|
@@ -67,7 +67,7 @@ function boot(sc) {
|
|
|
67
67
|
Array.prototype.forEach.call(document.querySelectorAll('[data-g]'), function (row) {
|
|
68
68
|
row.onclick = function () {
|
|
69
69
|
var m = state.groups[+row.getAttribute('data-g')].models[+row.getAttribute('data-m')];
|
|
70
|
-
window.kolbo.
|
|
70
|
+
window.kolbo.insertText(m.identifier || m.name || '');
|
|
71
71
|
};
|
|
72
72
|
});
|
|
73
73
|
window.kolbo.notifySize();
|
|
@@ -75,6 +75,34 @@ var TOOL_TITLES = {
|
|
|
75
75
|
generate_creative_director: 'Creative Director', edit_image: 'Image Edit', edit_video: 'Video Edit',
|
|
76
76
|
get_generation_status: 'Generations'
|
|
77
77
|
};
|
|
78
|
+
var OPEN_ROUTES = {
|
|
79
|
+
generate_image: { path: '/image-tools', tool: 'text-to-image' },
|
|
80
|
+
generate_image_edit: { path: '/image-tools', tool: 'image-editing' },
|
|
81
|
+
edit_image: { path: '/image-tools', tool: 'image-editing' },
|
|
82
|
+
generate_video: { path: '/video-tools', tool: 'text-to-video' },
|
|
83
|
+
generate_video_from_image: { path: '/video-tools', tool: 'image-to-video' },
|
|
84
|
+
generate_elements: { path: '/video-tools', tool: 'image-to-video', mode: 'elements' },
|
|
85
|
+
generate_first_last_frame: { path: '/video-tools', tool: 'image-to-video', mode: 'first-last' },
|
|
86
|
+
generate_video_from_video: { path: '/video-tools', tool: 'video-to-video' },
|
|
87
|
+
generate_lipsync: { path: '/video-tools', tool: 'lipsync' },
|
|
88
|
+
generate_music: { path: '/audio-tools', tool: 'music-generator' },
|
|
89
|
+
generate_speech: { path: '/audio-tools', tool: 'text-to-speech' },
|
|
90
|
+
generate_sound: { path: '/audio-tools', tool: 'text-to-sound' },
|
|
91
|
+
transcribe_audio: { path: '/audio-tools', tool: 'speech-to-text' },
|
|
92
|
+
generate_creative_director: { path: '/creative-director' }
|
|
93
|
+
};
|
|
94
|
+
function kolboUrl(sc) {
|
|
95
|
+
if (sc && typeof sc.open_url === 'string' && sc.open_url) return sc.open_url;
|
|
96
|
+
var sid = sc && (sc.session_id || sc.sessionId);
|
|
97
|
+
var route = OPEN_ROUTES[(sc && sc.tool) || originTool];
|
|
98
|
+
if (!route || !sid) return 'https://app.kolbo.ai';
|
|
99
|
+
var url = 'https://app.kolbo.ai' + route.path + '?session=' + encodeURIComponent(sid);
|
|
100
|
+
if (route.tool) url += '&tool=' + route.tool;
|
|
101
|
+
if (route.mode) url += '&mode=' + route.mode;
|
|
102
|
+
var pid = sc && (sc.project_id || sc.projectId);
|
|
103
|
+
if (pid) url += '&project=' + encodeURIComponent(pid);
|
|
104
|
+
return url;
|
|
105
|
+
}
|
|
78
106
|
|
|
79
107
|
// Long text is clamped by CSS (.k-prompt 2 lines / .k-caption 1 line). Expand
|
|
80
108
|
// lives on a separate button so the text itself stays selectable.
|
|
@@ -488,20 +516,20 @@ function stopNow(sc, spec) {
|
|
|
488
516
|
var refund = 0;
|
|
489
517
|
sts.forEach(function (s) { if (s.credits_refunded) refund += s.credits_refunded; });
|
|
490
518
|
return {
|
|
491
|
-
cancelled: sts.some(function (s) { return s.cancelled
|
|
519
|
+
cancelled: sts.some(function (s) { return s.cancelled === true; }),
|
|
492
520
|
credits_refunded: refund || undefined
|
|
493
521
|
};
|
|
494
522
|
})
|
|
495
523
|
: window.kolbo.callTool(spec.tool, spec.args).then(function (r) { return structured(r) || {}; });
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
524
|
+
call.then(function (st) {
|
|
525
|
+
if (!st || st.cancelled !== true) {
|
|
526
|
+
// Empty host ack used to land here as {} and the card painted
|
|
527
|
+
// cancelled while the job kept running. Only an explicit cancel counts.
|
|
528
|
+
cancelRequested = false;
|
|
529
|
+
renderStopButton(sc);
|
|
530
|
+
return schedulePoll(sc);
|
|
531
|
+
}
|
|
532
|
+
renderCancelled(st.credits_refunded);
|
|
505
533
|
}).catch(function () {
|
|
506
534
|
cancelRequested = false;
|
|
507
535
|
renderStopButton(sc);
|
|
@@ -608,7 +636,12 @@ function poll(sc) {
|
|
|
608
636
|
var done = Object.assign({}, sc, r, {
|
|
609
637
|
phase: 'completed',
|
|
610
638
|
urls: r.urls || st.urls || [],
|
|
611
|
-
credits_used: st.credits_used != null ? st.credits_used : sc.credits_used
|
|
639
|
+
credits_used: st.credits_used != null ? st.credits_used : sc.credits_used,
|
|
640
|
+
// Status structuredContent used to set open_url:undefined and wipe the
|
|
641
|
+
// session deep-link the generating card already had.
|
|
642
|
+
open_url: (sc && sc.open_url) || r.open_url,
|
|
643
|
+
session_id: (sc && (sc.session_id || sc.sessionId)) || r.session_id || st.session_id,
|
|
644
|
+
project_id: (sc && (sc.project_id || sc.projectId)) || r.project_id || st.project_id
|
|
612
645
|
});
|
|
613
646
|
state = done;
|
|
614
647
|
el('credits').textContent = done.credits_used != null ? fmtCredits(done.credits_used) : '';
|
|
@@ -652,6 +685,11 @@ function handleBatchStatus(sc, st) {
|
|
|
652
685
|
if (!st.all_done) return schedulePoll(sc);
|
|
653
686
|
|
|
654
687
|
var scenes = [], failedCount = 0, credits = 0, haveCredits = false, allUrls = [];
|
|
688
|
+
// get_generation_status resolves model_name/model_icon into EACH result
|
|
689
|
+
// (addDisplayNames in generate.js) — sc is only the submit-time guess
|
|
690
|
+
// (usually "Smart Select"). Every id in one batch ran the same model, so the
|
|
691
|
+
// first resolved one is enough to replace the guess on the finished card.
|
|
692
|
+
var resolved = {};
|
|
655
693
|
gens.forEach(function (g, i) {
|
|
656
694
|
var r = g.result || g;
|
|
657
695
|
var urls = (r && r.urls) || [];
|
|
@@ -659,6 +697,11 @@ function handleBatchStatus(sc, st) {
|
|
|
659
697
|
allUrls = allUrls.concat(urls);
|
|
660
698
|
var c = g.credits_used != null ? g.credits_used : (r.credits_used != null ? r.credits_used : null);
|
|
661
699
|
if (c != null) { credits += c; haveCredits = true; }
|
|
700
|
+
if (!resolved.model_name && r.model_name) {
|
|
701
|
+
resolved.model = r.model;
|
|
702
|
+
resolved.model_name = r.model_name;
|
|
703
|
+
resolved.model_icon = r.model_icon;
|
|
704
|
+
}
|
|
662
705
|
scenes.push({
|
|
663
706
|
scene_number: i + 1,
|
|
664
707
|
title: (sc.prompts && sc.prompts[i]) || '',
|
|
@@ -668,7 +711,7 @@ function handleBatchStatus(sc, st) {
|
|
|
668
711
|
});
|
|
669
712
|
if (!scenes.length) return renderError('All ' + gens.length + ' generations failed');
|
|
670
713
|
|
|
671
|
-
var done = Object.assign({}, sc, {
|
|
714
|
+
var done = Object.assign({}, sc, resolved, {
|
|
672
715
|
phase: 'completed', kind: 'scenes', batch: true, scenes: scenes, urls: [],
|
|
673
716
|
credits_used: haveCredits ? credits : sc.credits_used
|
|
674
717
|
});
|
|
@@ -902,10 +945,14 @@ function renderBatchGrid(sc) {
|
|
|
902
945
|
dlBtnHTML(it.url) + '</div>';
|
|
903
946
|
}).join('') + '</div>';
|
|
904
947
|
wireDlButtons(el('stage'));
|
|
948
|
+
// In-widget popup, not the host round-trip focusMedia() uses — a batch grid
|
|
949
|
+
// tile has no visible full-size image otherwise, so a host that never resolves
|
|
950
|
+
// requestDisplayMode() (or drops window.open after the async round trip eats
|
|
951
|
+
// the click's user-activation window) leaves the click doing nothing at all.
|
|
905
952
|
Array.prototype.forEach.call(el('stage').querySelectorAll('[data-focus]'), function (cell) {
|
|
906
953
|
var it = items[+cell.getAttribute('data-focus')];
|
|
907
954
|
if (it.type !== 'image') return; // <video controls> owns its own clicks
|
|
908
|
-
cell.onclick = function () {
|
|
955
|
+
cell.onclick = function () { openPeek(it.url, 'image', it.label); };
|
|
909
956
|
});
|
|
910
957
|
renderActions(sc);
|
|
911
958
|
window.kolbo.notifySize();
|
|
@@ -949,7 +996,7 @@ function renderStatusGrid(sc) {
|
|
|
949
996
|
Array.prototype.forEach.call(el('stage').querySelectorAll('[data-focus]'), function (cell) {
|
|
950
997
|
var it = items[+cell.getAttribute('data-focus')];
|
|
951
998
|
if (it.kind !== 'image') return; // <video controls> owns its own clicks
|
|
952
|
-
cell.onclick = function () {
|
|
999
|
+
cell.onclick = function () { openPeek(it.url, 'image', it.title); };
|
|
953
1000
|
});
|
|
954
1001
|
renderActions(sc);
|
|
955
1002
|
window.kolbo.notifySize();
|
|
@@ -1030,7 +1077,7 @@ function renderTrackingIssue(msg) {
|
|
|
1030
1077
|
(state && state.generation_id ? '\\nGeneration ID: ' + state.generation_id : ''));
|
|
1031
1078
|
};
|
|
1032
1079
|
el('tracking-open').onclick = function () {
|
|
1033
|
-
window.kolbo.openLink((state
|
|
1080
|
+
window.kolbo.openLink(kolboUrl(state));
|
|
1034
1081
|
};
|
|
1035
1082
|
window.kolbo.notifySize();
|
|
1036
1083
|
}
|
|
@@ -1100,7 +1147,7 @@ function renderActions(sc) {
|
|
|
1100
1147
|
el('actions').innerHTML = a.join('');
|
|
1101
1148
|
|
|
1102
1149
|
bind('btn-download', function () { window.kolbo.openLink(downloadUrl(currentUrl())); });
|
|
1103
|
-
bind('btn-open', function () { window.kolbo.openLink(state
|
|
1150
|
+
bind('btn-open', function () { window.kolbo.openLink(kolboUrl(state)); });
|
|
1104
1151
|
bind('btn-recreate', function () {
|
|
1105
1152
|
window.kolbo.sendMessage('Recreate this with the same settings' +
|
|
1106
1153
|
(state.model ? '\\nModel: ' + state.model : '') +
|
|
@@ -1195,7 +1242,10 @@ function completedFromPlain(sc) {
|
|
|
1195
1242
|
aspect_ratio: originArgs.aspect_ratio,
|
|
1196
1243
|
quality: originArgs.quality
|
|
1197
1244
|
},
|
|
1198
|
-
urls: sc.urls || []
|
|
1245
|
+
urls: sc.urls || [],
|
|
1246
|
+
session_id: sc.session_id || originArgs.session_id,
|
|
1247
|
+
project_id: sc.project_id || originArgs.project_id,
|
|
1248
|
+
open_url: sc.open_url
|
|
1199
1249
|
});
|
|
1200
1250
|
}
|
|
1201
1251
|
|