@kolbo/mcp 1.112.2 → 1.112.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/package.json +1 -1
- package/skill/GENERATED.md +1 -1
- package/skill/SKILL.md +2 -2
- package/skill/VERSION +1 -1
- package/skill/references/workflows/presets.md +6 -0
- package/skill/references/workflows/visual-dna.md +12 -0
- package/src/apps/theme.js +10 -1
- package/src/apps/widgets/generation.js +24 -10
- package/src/tools/generate.js +25 -14
package/package.json
CHANGED
package/skill/GENERATED.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# AUTO-GENERATED — do not edit
|
|
2
2
|
|
|
3
|
-
This tree is mirrored from kolbo-code@
|
|
3
|
+
This tree is mirrored from kolbo-code@49cd478, 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
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
version: 0.9.
|
|
2
|
+
version: 0.9.23
|
|
3
3
|
name: kolbo
|
|
4
4
|
description: |
|
|
5
5
|
Generate, edit, analyze, and direct creative media through Kolbo AI: images,
|
|
@@ -155,7 +155,7 @@ Font tools (when exposed by the installed MCP): `list_fonts`, `get_font`, `uploa
|
|
|
155
155
|
| `list_models` / `list_voices` / `check_credits` / `show_plans` / `get_generation_status` / `cancel_generation` / `get_session_usage` | Discovery + status. `list_models` with no args returns the recommended shortlist out of ~428 — pass `type` for a full category with per-model caps. `cancel_generation` stops an in-flight job and refunds what it can: use it when the user changes their mind mid-generation instead of letting it run. `show_plans` renders the balance + upgrade card for pricing/plan/upgrade questions. |
|
|
156
156
|
| `download_media_from_url` / `get_download_status` / `cancel_download` | Download a public social/video page URL to Kolbo storage. Async job; use download status, not generation status. See `workflows/media-library.md`. |
|
|
157
157
|
| `upload_media` / `create_upload_ticket` / `list_media` / `get_media` / `get_media_stats` / `favorite_media` / `unfavorite_media` / `delete_media` / `restore_media` / `permanently_delete_media` / `move_media` / `bulk_*_media` / `*_media_folder` | Media library — see `workflows/media-library.md`. Getting a LOCAL file in depends on where the server runs: `upload_media` with a path only works on a local (stdio) install; over a remote connector use `create_upload_ticket` and POST the file yourself. |
|
|
158
|
-
| `create_visual_dna` / `update_visual_dna` / `generate_character_sheet` / `list_visual_dnas` / `get_visual_dna` / `delete_visual_dna` / `*_visual_dna_folder` (5 folder tools) | Visual DNA (+ character sheet
|
|
158
|
+
| `create_visual_dna` / `update_visual_dna` / `generate_character_sheet` / `list_visual_dnas` / `get_visual_dna` / `delete_visual_dna` / `*_visual_dna_folder` (5 folder tools) | Visual DNA (+ character sheet and character folders) — see `workflows/visual-dna.md`. Edit with `update_visual_dna`; never delete+recreate. Account transfers use the Kolbo UI until the MCP tools ship. |
|
|
159
159
|
| `list_moodboards` / `get_moodboard` / `list_presets` / `list_cinematic_presets` | Style overlays + presets. `list_presets` spans FOUR distinct catalogs (`image`, `image_edit`, `video`, `music`; `text_to_video` is an alias for `video`, `shorts` is empty) — the `video` one holds 200+ Seedance shot recipes. `list_cinematic_presets` is a separate tool feeding the `cinematic` arg, never `preset_id`. Full doctrine + intent→catalog map: `references/workflows/presets.md`. Never omit `preset_id` after claiming a preset was used. |
|
|
160
160
|
| `list_color_palettes` / `analyze_color_palette` / `create_color_palette` / `update_color_palette` / `delete_color_palette` / `activate_color_palette` / `deactivate_color_palette` | **Color DNA — sticky + account-wide; at most one palette active at a time**, and while active it strict-grades **every** image and video generation automatically. Per-generation opt-out: `skip_color_palette: true`. Details: `workflows/color-dna.md`. |
|
|
161
161
|
| `list_agents` / `create_agent` / `update_agent` / `delete_agent` (same tools as `list_skills` / `create_skill` / `update_skill` / `delete_skill`) | Custom chat agents — reusable named personas for `chat_send_message`. The agent's `description` IS the system instruction. Resolve a name the user mentions ("use my SEO agent") to an id with `list_agents` (paged: `page` / `limit`, follow `pagination.has_more`), then pass `agent_id`. Global/preset agents are read-only; only the user's own can be updated or deleted. |
|
package/skill/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.9.
|
|
1
|
+
0.9.23
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Presets — Kolbo's stored instruction blocks
|
|
2
2
|
|
|
3
|
+
Generation widgets show the selected template name and thumbnail in a dedicated
|
|
4
|
+
Template section, plus every supplied reference in References. Local image sources
|
|
5
|
+
preview through their uploaded CDN URLs. Both sections persist through completion,
|
|
6
|
+
including image batches and standalone status checks. Keep passing the exact
|
|
7
|
+
`preset_id`; the thumbnail is a preview, not an extra conditioning image.
|
|
8
|
+
|
|
3
9
|
A preset is a long, hand-tuned instruction block stored in Kolbo's catalog. Passing
|
|
4
10
|
`preset_id` prepends it to the user's prompt at generation time. **The craft lives on
|
|
5
11
|
the preset** — a three-panel character sheet, a Seedance shot-sequence structure, a
|
|
@@ -254,6 +254,18 @@ Tools: `list_visual_dna_folders`, `create_visual_dna_folder` (`name`, optional h
|
|
|
254
254
|
- **Creating many characters for one production?** Create the folder FIRST, then `move_visual_dna_to_folder` each DNA right after `create_visual_dna` — don't leave a big cast unsorted at root.
|
|
255
255
|
- To list a folder's contents: `list_visual_dnas` and filter by each profile's `folder_id` (there is no server-side folder filter).
|
|
256
256
|
|
|
257
|
+
## Transfer through Kolbo UI — send DNAs to another account
|
|
258
|
+
|
|
259
|
+
Use the authenticated Kolbo UI for account transfers. Dedicated MCP transfer tools
|
|
260
|
+
are not in the current published tool surface; do not invent or call them.
|
|
261
|
+
|
|
262
|
+
- Recipient must already have a Kolbo account; nothing changes until they accept (7-day expiry).
|
|
263
|
+
- On accept the recipient gets their OWN copy — **new ids**, returned in `copies`. Use those ids and names for the recipient's generations, never the sender's ids. A name clash becomes "Name (1)".
|
|
264
|
+
- `keep_sender_copy: false` is a move: the sender's originals go to trash on accept. Default keeps them.
|
|
265
|
+
- Only the sender's personal, ready DNAs — not global, organization, or still-generating ones. Custom cloned/designed voices stay owned by the sender.
|
|
266
|
+
- GATE: confirm recipient email, the DNA list and keep/move with the user before sending through the UI; confirm before accepting.
|
|
267
|
+
- Whole project instead (cast comes along as copies)? Use `transfer_project`.
|
|
268
|
+
|
|
257
269
|
## Character sheet — default for production assets (not a catalog preset)
|
|
258
270
|
|
|
259
271
|
Custom instructions live on the **image preset**. Resolve it silently, then generate:
|
package/src/apps/theme.js
CHANGED
|
@@ -152,7 +152,16 @@ body {
|
|
|
152
152
|
align-items: center; justify-content: center; font-family: inherit;
|
|
153
153
|
}
|
|
154
154
|
.k-chip img.k-voice-thumb { width: 18px; height: 18px; border-radius: 999px; margin-left: -3px; }
|
|
155
|
-
.k-ref-thumb { width: 26px; height: 26px; border-radius: 6px; object-fit: cover; border: 1px solid var(--border-strong); }
|
|
155
|
+
.k-ref-thumb { width: 26px; height: 26px; border-radius: 6px; object-fit: cover; border: 1px solid var(--border-strong); }
|
|
156
|
+
.k-input-section { flex-basis: 100%; min-width: 0; margin-top: 6px; }
|
|
157
|
+
.k-input-label { display: block; color: var(--muted); font-size: 11px; margin-bottom: 6px; }
|
|
158
|
+
.k-input-media { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
|
|
159
|
+
.k-input-media .k-ref-thumb { width: 40px; height: 40px; object-fit: contain; background: var(--panel); }
|
|
160
|
+
.k-ref-audio { display: flex; flex-direction: column; gap: 6px; max-width: 100%; font-size: 11px; }
|
|
161
|
+
.k-ref-audio audio { width: 240px; max-width: 100%; height: 32px; }
|
|
162
|
+
.k-template { display: flex; align-items: center; gap: 12px; font-size: 12px; }
|
|
163
|
+
.k-template-thumb, .k-template-placeholder { width: 104px; height: 80px; border-radius: 8px; object-fit: contain; background: var(--panel); border: 1px solid var(--border-strong); }
|
|
164
|
+
.k-template-placeholder { display: flex; align-items: center; justify-content: center; color: var(--muted); }
|
|
156
165
|
.k-peek-hit { cursor: zoom-in; }
|
|
157
166
|
.k-peek {
|
|
158
167
|
position: absolute; inset: 0; z-index: 20;
|
|
@@ -385,7 +385,7 @@ function renderChips(sc) {
|
|
|
385
385
|
if (s.mode) h += chip(esc(editLabel(s.mode)));
|
|
386
386
|
if (Array.isArray(s.details)) s.details.forEach(function (d) { if (d) h += chip(esc(String(d))); });
|
|
387
387
|
if (many && !kind) h += chip(sc.count + ' items');
|
|
388
|
-
h += referenceHTML(sc);
|
|
388
|
+
h += templateHTML(sc) + referenceHTML(sc);
|
|
389
389
|
el('chips').innerHTML = h;
|
|
390
390
|
}
|
|
391
391
|
|
|
@@ -429,7 +429,7 @@ function referenceHTML(sc) {
|
|
|
429
429
|
h += '<video class="k-ref-thumb k-peek-hit" src="' + url + '#t=0.1" muted playsinline preload="metadata" title="'
|
|
430
430
|
+ title + '"' + peek + ' onerror="this.style.display=\\'none\\'"></video>';
|
|
431
431
|
} else if (refs[i].kind === 'audio') {
|
|
432
|
-
h += '<span class="k-
|
|
432
|
+
h += '<span class="k-ref-audio" title="' + title + '">' + ICONS.sound + ' audio ref<audio controls preload="none" src="' + url + '"></audio></span>';
|
|
433
433
|
} else {
|
|
434
434
|
h += '<img class="k-ref-thumb k-peek-hit" src="' + url + '" alt="" loading="lazy" title="' + title + '"'
|
|
435
435
|
+ peek + ' onerror="this.style.display=\\'none\\'">';
|
|
@@ -438,12 +438,23 @@ function referenceHTML(sc) {
|
|
|
438
438
|
// Local files the caller passed by path: the iframe cannot load them and they
|
|
439
439
|
// are only uploaded during the run, so name them instead of showing nothing.
|
|
440
440
|
// The finished card carries the uploaded thumbnails and drops these.
|
|
441
|
-
if (sc.phase !== 'completed' && Array.isArray(sc.local_references)) {
|
|
442
|
-
sc.local_references.
|
|
441
|
+
if (sc.phase !== 'completed' && Array.isArray(sc.local_references) && !refs.length) {
|
|
442
|
+
sc.local_references.forEach(function (name) {
|
|
443
443
|
h += '<span class="k-chip" title="' + esc(name) + '">' + ICONS.image + ' ' + esc(String(name).slice(0, 24)) + '</span>';
|
|
444
444
|
});
|
|
445
445
|
}
|
|
446
|
-
return h;
|
|
446
|
+
return h ? '<div class="k-input-section"><span class="k-input-label">References</span><div class="k-input-media">' + h + '</div></div>' : '';
|
|
447
|
+
}
|
|
448
|
+
function templateHTML(sc) {
|
|
449
|
+
var s = sc.settings || {};
|
|
450
|
+
if (!s.preset_id && !s.preset_name && !s.preset_thumbnail) return '';
|
|
451
|
+
var name = s.preset_name || 'Selected template';
|
|
452
|
+
var url = s.preset_thumbnail;
|
|
453
|
+
var media = url ? '<img class="k-template-thumb k-peek-hit" src="' + esc(url) + '" alt="' + esc(name)
|
|
454
|
+
+ '" loading="lazy" data-peek="' + esc(url) + '" data-peek-kind="image" data-peek-cap="' + esc(name) + '">'
|
|
455
|
+
: '<span class="k-template-placeholder">' + ICONS.image + '</span>';
|
|
456
|
+
return '<div class="k-input-section"><span class="k-input-label">Template</span><div class="k-template">'
|
|
457
|
+
+ media + '<span>' + esc(name) + '</span></div></div>';
|
|
447
458
|
}
|
|
448
459
|
// Which characters/looks are locked into this generation — by face and name,
|
|
449
460
|
// resolved from visual_dna_ids server-side. "1 Visual DNA" told the user nothing
|
|
@@ -830,6 +841,7 @@ function poll(sc) {
|
|
|
830
841
|
|
|
831
842
|
var done = Object.assign({}, sc, r, {
|
|
832
843
|
phase: 'completed',
|
|
844
|
+
settings: Object.assign({}, sc.settings || {}, r.settings || {}),
|
|
833
845
|
urls: r.urls || st.urls || [],
|
|
834
846
|
credits_used: st.credits_used != null ? st.credits_used : sc.credits_used,
|
|
835
847
|
// Status structuredContent used to set open_url:undefined and wipe the
|
|
@@ -1462,7 +1474,7 @@ function kindFromTool(tool, sc) {
|
|
|
1462
1474
|
function liveFromTimedOut(sc) {
|
|
1463
1475
|
if (!sc || !sc.generation_id || isTerminal(sc.state) || Array.isArray(sc.urls)) return null;
|
|
1464
1476
|
var ids = Array.isArray(sc.generation_ids) && sc.generation_ids.length > 1 ? sc.generation_ids : null;
|
|
1465
|
-
var live = {
|
|
1477
|
+
var live = Object.assign({}, preRefSc(originTool, originArgs), {
|
|
1466
1478
|
widget: 'generation',
|
|
1467
1479
|
phase: 'generating',
|
|
1468
1480
|
tool: originTool,
|
|
@@ -1477,7 +1489,8 @@ function liveFromTimedOut(sc) {
|
|
|
1477
1489
|
quality: originArgs.quality,
|
|
1478
1490
|
mode: originArgs.operation,
|
|
1479
1491
|
visual_dna_ids: originArgs.visual_dna_ids,
|
|
1480
|
-
moodboard_id: originArgs.moodboard_id
|
|
1492
|
+
moodboard_id: originArgs.moodboard_id,
|
|
1493
|
+
preset_id: originArgs.preset_id
|
|
1481
1494
|
}, originArgs),
|
|
1482
1495
|
count: ids ? ids.length : (originArgs.num_images || 1),
|
|
1483
1496
|
generation_id: sc.generation_id,
|
|
@@ -1485,14 +1498,14 @@ function liveFromTimedOut(sc) {
|
|
|
1485
1498
|
status_args: ids ? { generation_ids: ids, wait: true } : { generation_id: sc.generation_id, wait: true },
|
|
1486
1499
|
session_id: sc.session_id || originArgs.session_id,
|
|
1487
1500
|
project_id: sc.project_id || originArgs.project_id
|
|
1488
|
-
};
|
|
1501
|
+
});
|
|
1489
1502
|
if (ids) { live.generation_ids = ids; live.prompts = originArgs.prompts || []; }
|
|
1490
1503
|
return live;
|
|
1491
1504
|
}
|
|
1492
1505
|
|
|
1493
1506
|
function completedFromPlain(sc) {
|
|
1494
1507
|
if (!sc || (!Array.isArray(sc.urls) && !Array.isArray(sc.scenes))) return null;
|
|
1495
|
-
return Object.assign({}, sc, {
|
|
1508
|
+
return Object.assign({}, preRefSc(originTool, originArgs), sc, {
|
|
1496
1509
|
widget: 'generation',
|
|
1497
1510
|
phase: 'completed',
|
|
1498
1511
|
tool: originTool,
|
|
@@ -1505,7 +1518,8 @@ function completedFromPlain(sc) {
|
|
|
1505
1518
|
resolution: originArgs.draft === true ? '480p-draft' : originArgs.draft === false ? String(originArgs.resolution || '').replace(/-draft$/i, '') : originArgs.resolution,
|
|
1506
1519
|
aspect_ratio: originArgs.aspect_ratio,
|
|
1507
1520
|
quality: originArgs.quality,
|
|
1508
|
-
mode: originArgs.operation
|
|
1521
|
+
mode: originArgs.operation,
|
|
1522
|
+
preset_id: originArgs.preset_id
|
|
1509
1523
|
}, originArgs),
|
|
1510
1524
|
urls: sc.urls || [],
|
|
1511
1525
|
session_id: sc.session_id || originArgs.session_id,
|
package/src/tools/generate.js
CHANGED
|
@@ -110,7 +110,7 @@ async function submitBatch(rawItems, submitOne) {
|
|
|
110
110
|
// multi-id branch, same fix: always ship structuredContent via the shared
|
|
111
111
|
// kind:'status' grid, which already renders any mix of completed/processing
|
|
112
112
|
// items correctly.
|
|
113
|
-
async function pollBatch(client, batch, { interval, timeout }, toolName, submittedModel) {
|
|
113
|
+
async function pollBatch(client, batch, { interval, timeout }, toolName, submittedModel, inputs = {}) {
|
|
114
114
|
const polls = await Promise.all(batch.ids.map((id) => pollOrTimedOut(client, id, { interval, timeout })));
|
|
115
115
|
const generations = polls.map((p, i) => p.timedOut
|
|
116
116
|
? { prompt: batch.ok[i].prompt, generation_id: batch.ids[i], status: 'processing', note: 'Still running — call get_generation_status with wait=true to collect it.' }
|
|
@@ -126,8 +126,9 @@ async function pollBatch(client, batch, { interval, timeout }, toolName, submitt
|
|
|
126
126
|
return uiCompleted({
|
|
127
127
|
tool: toolName, kind: 'status', client,
|
|
128
128
|
model: modelsRan.length === 1 ? modelsRan[0] : (submittedModel || 'Generations'),
|
|
129
|
-
gen: { generation_id: batch.ids[0], session_id: batch.ok[0].gen.session_id },
|
|
130
|
-
settings: {},
|
|
129
|
+
gen: { generation_id: batch.ids[0], session_id: batch.ok[0].gen.session_id },
|
|
130
|
+
settings: {},
|
|
131
|
+
...inputs,
|
|
131
132
|
items: generations.map(g => ({
|
|
132
133
|
id: g.generation_id,
|
|
133
134
|
state: g.status,
|
|
@@ -338,10 +339,11 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
338
339
|
if (!prompt && !(prompts && prompts.length)) throw new Error('Provide prompt or prompts');
|
|
339
340
|
model = await canonicalModelId(client, model, 'text_to_img'); // lenient id resolution ("z-image" → "z-image/turbo")
|
|
340
341
|
aspect_ratio = await resolveCatalogAspectRatio(client, model, aspect_ratio, 'text_to_img');
|
|
341
|
-
const shared = {
|
|
342
|
-
model, aspect_ratio, enhance_prompt, font_ids,
|
|
343
|
-
reference_images, visual_dna_ids, moodboard_id, enable_web_search, resolution, quality, background, output_format, output_compression, moderation, mask_image_url, preset_id, cinematic, skip_color_palette, project_id, session_id
|
|
344
|
-
};
|
|
342
|
+
const shared = await rehostLocalPaths(client, {
|
|
343
|
+
model, aspect_ratio, enhance_prompt, font_ids,
|
|
344
|
+
reference_images, visual_dna_ids, moodboard_id, enable_web_search, resolution, quality, background, output_format, output_compression, moderation, mask_image_url, preset_id, cinematic, skip_color_palette, project_id, session_id
|
|
345
|
+
}, { allowLocalFiles: !options.remote });
|
|
346
|
+
reference_images = [...(shared.reference_images || []), shared.mask_image_url].filter(Boolean);
|
|
345
347
|
|
|
346
348
|
// Batch mode: N different prompts, one widget owning all generation ids.
|
|
347
349
|
if (prompts && prompts.length) {
|
|
@@ -354,7 +356,7 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
354
356
|
status_args: { generation_ids: batch.ids, wait: true },
|
|
355
357
|
reference_images
|
|
356
358
|
});
|
|
357
|
-
return pollBatch(client, batch, { interval: (batch.ok[0].gen.poll_interval_hint || 3) * 1000, timeout: 150000 }, 'generate_image', model);
|
|
359
|
+
return pollBatch(client, batch, { interval: (batch.ok[0].gen.poll_interval_hint || 3) * 1000, timeout: 150000 }, 'generate_image', model, { settings: imageSettings(shared), reference_images });
|
|
358
360
|
}
|
|
359
361
|
|
|
360
362
|
const gen = await client.post('/v1/generate/image', { ...shared, prompt, num_images });
|
|
@@ -429,10 +431,12 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
429
431
|
if (!prompt && !(prompts && prompts.length)) throw new Error('Provide prompt or prompts');
|
|
430
432
|
model = await canonicalModelId(client, model, 'image_editing'); // lenient id resolution ("z-image" → "z-image/turbo")
|
|
431
433
|
aspect_ratio = await resolveCatalogAspectRatio(client, model, aspect_ratio, 'image_editing');
|
|
432
|
-
const shared = {
|
|
433
|
-
model, source_images, reference_images, aspect_ratio, enhance_prompt, font_ids,
|
|
434
|
-
visual_dna_ids, moodboard_id, enable_web_search, resolution, quality, background, output_format, output_compression, moderation, mask_image_url, preset_id, cinematic, skip_color_palette, project_id, session_id
|
|
435
|
-
};
|
|
434
|
+
const shared = await rehostLocalPaths(client, {
|
|
435
|
+
model, source_images, reference_images, aspect_ratio, enhance_prompt, font_ids,
|
|
436
|
+
visual_dna_ids, moodboard_id, enable_web_search, resolution, quality, background, output_format, output_compression, moderation, mask_image_url, preset_id, cinematic, skip_color_palette, project_id, session_id
|
|
437
|
+
}, { allowLocalFiles: !options.remote });
|
|
438
|
+
source_images = shared.source_images;
|
|
439
|
+
reference_images = [...(shared.reference_images || []), shared.mask_image_url].filter(Boolean);
|
|
436
440
|
const settings = imageSettings(shared);
|
|
437
441
|
|
|
438
442
|
// Batch mode: N different edit instructions against the SAME source
|
|
@@ -449,7 +453,7 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
449
453
|
status_args: { generation_ids: batch.ids, wait: true },
|
|
450
454
|
reference_images: [...(source_images || []), ...(reference_images || [])]
|
|
451
455
|
});
|
|
452
|
-
return pollBatch(client, batch, { interval: (batch.ok[0].gen.poll_interval_hint || 3) * 1000, timeout: 150000 }, 'generate_image_edit', model);
|
|
456
|
+
return pollBatch(client, batch, { interval: (batch.ok[0].gen.poll_interval_hint || 3) * 1000, timeout: 150000 }, 'generate_image_edit', model, { settings, reference_images: [...(source_images || []), ...reference_images] });
|
|
453
457
|
}
|
|
454
458
|
|
|
455
459
|
const gen = await client.post('/v1/generate/image-edit', { ...shared, prompt, num_images });
|
|
@@ -1441,7 +1445,14 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
1441
1445
|
// the live card merges this payload over its submit-time state, so
|
|
1442
1446
|
// the finished card shows every reference, including server-side
|
|
1443
1447
|
// additions (DNA stills, merged sources) the tool call never named.
|
|
1444
|
-
reference_images: res.reference_images,
|
|
1448
|
+
reference_images: res.reference_images,
|
|
1449
|
+
reference_videos: res.reference_videos,
|
|
1450
|
+
reference_audio: res.reference_audio,
|
|
1451
|
+
...(res.preset ? { settings: {
|
|
1452
|
+
preset_id: res.preset.id,
|
|
1453
|
+
preset_name: res.preset.name,
|
|
1454
|
+
preset_thumbnail: res.preset.thumbnail_url,
|
|
1455
|
+
} } : {}),
|
|
1445
1456
|
// Transcription results ride the same status tool as media
|
|
1446
1457
|
// generations; without these the transcript widget merges a payload
|
|
1447
1458
|
// with no transcript in it.
|