@kolbo/mcp 1.75.3 → 1.75.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/src/tools/generate.js +74 -24
package/package.json
CHANGED
package/src/tools/generate.js
CHANGED
|
@@ -77,22 +77,35 @@ async function submitBatch(rawItems, submitOne) {
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
// Blocking path for text-only hosts: wait for every batch member, aggregate.
|
|
80
|
-
|
|
80
|
+
// This is the exact path Kolbo Code takes for a `prompts`-array batch call
|
|
81
|
+
// (ui() is false there, so the uiGenerating branch above never runs) — it was
|
|
82
|
+
// text-only, no structuredContent, so a batch of N prompts rendered as a bare
|
|
83
|
+
// JSON dump instead of N cards. Same class of bug as get_generation_status's
|
|
84
|
+
// multi-id branch, same fix: always ship structuredContent via the shared
|
|
85
|
+
// kind:'status' grid, which already renders any mix of completed/processing
|
|
86
|
+
// items correctly.
|
|
87
|
+
async function pollBatch(client, batch, { interval, timeout }, toolName) {
|
|
81
88
|
const polls = await Promise.all(batch.ids.map((id) => pollOrTimedOut(client, id, { interval, timeout })));
|
|
82
89
|
const generations = polls.map((p, i) => p.timedOut
|
|
83
90
|
? { 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.' }
|
|
84
91
|
: { prompt: batch.ok[i].prompt, generation_id: batch.ids[i], status: 'completed', ...creditFields(polls[i].result), urls: p.result.result.urls });
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
|
|
92
|
+
const text = JSON.stringify({
|
|
93
|
+
batch: true,
|
|
94
|
+
session_id: batch.ok[0].gen.session_id,
|
|
95
|
+
generations,
|
|
96
|
+
failed_submissions: batch.failed.length ? batch.failed : undefined
|
|
97
|
+
}, null, 2);
|
|
98
|
+
return uiCompleted({
|
|
99
|
+
tool: toolName, kind: 'status', client,
|
|
100
|
+
model: 'Generations', gen: { generation_id: batch.ids[0], session_id: batch.ok[0].gen.session_id },
|
|
101
|
+
settings: {},
|
|
102
|
+
items: generations.map(g => ({
|
|
103
|
+
id: g.generation_id,
|
|
104
|
+
state: g.status,
|
|
105
|
+
title: g.prompt,
|
|
106
|
+
url: Array.isArray(g.urls) ? g.urls[0] : undefined,
|
|
107
|
+
})),
|
|
108
|
+
}, text);
|
|
96
109
|
}
|
|
97
110
|
|
|
98
111
|
// ─── Widget settings block ──────────────────────────────────────────────────
|
|
@@ -205,7 +218,7 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
205
218
|
status_args: { generation_ids: batch.ids, wait: true },
|
|
206
219
|
reference_images
|
|
207
220
|
});
|
|
208
|
-
return pollBatch(client, batch, { interval: (batch.ok[0].gen.poll_interval_hint || 3) * 1000, timeout: 240000 });
|
|
221
|
+
return pollBatch(client, batch, { interval: (batch.ok[0].gen.poll_interval_hint || 3) * 1000, timeout: 240000 }, 'generate_image');
|
|
209
222
|
}
|
|
210
223
|
|
|
211
224
|
const gen = await client.post('/v1/generate/image', { ...shared, prompt, num_images });
|
|
@@ -288,7 +301,7 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
288
301
|
status_args: { generation_ids: batch.ids, wait: true },
|
|
289
302
|
reference_images: source_images
|
|
290
303
|
});
|
|
291
|
-
return pollBatch(client, batch, { interval: (batch.ok[0].gen.poll_interval_hint || 3) * 1000, timeout: 240000 });
|
|
304
|
+
return pollBatch(client, batch, { interval: (batch.ok[0].gen.poll_interval_hint || 3) * 1000, timeout: 240000 }, 'generate_image_edit');
|
|
292
305
|
}
|
|
293
306
|
|
|
294
307
|
const gen = await client.post('/v1/generate/image-edit', { ...shared, prompt, num_images });
|
|
@@ -463,7 +476,7 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
463
476
|
video_urls: s.video_urls || null
|
|
464
477
|
}));
|
|
465
478
|
const completed = scenes.filter(s => s.status === 'completed').length;
|
|
466
|
-
|
|
479
|
+
const text = JSON.stringify({
|
|
467
480
|
...creditFields(status),
|
|
468
481
|
state: status.state,
|
|
469
482
|
generation_id,
|
|
@@ -474,7 +487,23 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
474
487
|
_hint: status.state === 'completed'
|
|
475
488
|
? 'All scenes terminal. Every completed scene\'s image_urls/video_urls are final.'
|
|
476
489
|
: `Still running — not a failure. Each wait=true call blocks for at most ~${WAIT_WINDOW_S}s, and a video batch routinely outlasts several windows, so call get_creative_director_status again with wait=true and keep going until state is terminal. Scenes that already carry image_urls/video_urls are done; never re-run generate_creative_director.`
|
|
477
|
-
}, null, 2)
|
|
490
|
+
}, null, 2);
|
|
491
|
+
// Same text-only gap as get_generation_status/pollBatch, called out in
|
|
492
|
+
// this tool's own comment above ("especially parallel VIDEO scenes that
|
|
493
|
+
// exceed the blocking poll window") — a CD batch checked here after
|
|
494
|
+
// outliving one wait window rendered as a bare JSON dump, no scene
|
|
495
|
+
// thumbnails. Always ship the same kind:'status' grid, one item per scene.
|
|
496
|
+
return uiCompleted({
|
|
497
|
+
tool: 'get_creative_director_status', kind: 'status', client,
|
|
498
|
+
model: 'Generations', gen: { generation_id },
|
|
499
|
+
settings: {},
|
|
500
|
+
items: scenes.map(s => ({
|
|
501
|
+
id: generation_id + '-' + s.scene_number,
|
|
502
|
+
state: s.status,
|
|
503
|
+
title: s.title || ('Scene ' + s.scene_number),
|
|
504
|
+
url: (Array.isArray(s.image_urls) && s.image_urls[0]) || (Array.isArray(s.video_urls) && s.video_urls[0]) || undefined,
|
|
505
|
+
})),
|
|
506
|
+
}, text);
|
|
478
507
|
}
|
|
479
508
|
);
|
|
480
509
|
|
|
@@ -519,7 +548,7 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
519
548
|
status_args: { generation_ids: batch.ids, wait: true },
|
|
520
549
|
reference_images
|
|
521
550
|
});
|
|
522
|
-
return pollBatch(client, batch, { interval: (batch.ok[0].gen.poll_interval_hint || 8) * 1000, timeout: 900000 });
|
|
551
|
+
return pollBatch(client, batch, { interval: (batch.ok[0].gen.poll_interval_hint || 8) * 1000, timeout: 900000 }, 'generate_video');
|
|
523
552
|
}
|
|
524
553
|
|
|
525
554
|
const gen = await client.post('/v1/generate/video', { ...shared, prompt });
|
|
@@ -606,7 +635,7 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
606
635
|
status_args: { generation_ids: batch.ids, wait: true },
|
|
607
636
|
reference_images: items.map((item) => item.image_url)
|
|
608
637
|
});
|
|
609
|
-
return pollBatch(client, batch, { interval: (batch.ok[0].gen.poll_interval_hint || 8) * 1000, timeout: 900000 });
|
|
638
|
+
return pollBatch(client, batch, { interval: (batch.ok[0].gen.poll_interval_hint || 8) * 1000, timeout: 900000 }, 'generate_video_from_image');
|
|
610
639
|
}
|
|
611
640
|
|
|
612
641
|
const gen = await client.post('/v1/generate/video/from-image', { ...shared, image_url, prompt });
|
|
@@ -965,17 +994,38 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
965
994
|
: '';
|
|
966
995
|
const pendingHint = stillRunningHint(idsPhrase);
|
|
967
996
|
|
|
968
|
-
// Single-id calls keep the original flat shape —
|
|
969
|
-
//
|
|
970
|
-
// state/result at the
|
|
997
|
+
// Single-id calls keep the original flat TEXT shape — a live uiGenerating
|
|
998
|
+
// widget (ui()==true, still open from the original generate_* call) polls
|
|
999
|
+
// this tool directly from its own iframe JS and reads state/result at the
|
|
1000
|
+
// top level, so `text` must stay exactly what it always was.
|
|
1001
|
+
//
|
|
1002
|
+
// But a single id checked here often has NO live widget behind it at all:
|
|
1003
|
+
// Kolbo Code never opens one (ui() is false there), and even on hosts that
|
|
1004
|
+
// do, the original call can have returned poll.timedOut before uiGenerating
|
|
1005
|
+
// ever ran (see pollOrTimedOut) — a parallel batch is exactly when that
|
|
1006
|
+
// happens, since every concurrent generation competes for the same
|
|
1007
|
+
// per-call poll window. Either way this is then a FRESH, standalone tool
|
|
1008
|
+
// response that needs its own renderable card, same reasoning as the
|
|
1009
|
+
// multi-id fix just above. Reuse the same kind:'status' single-item grid
|
|
1010
|
+
// rather than inventing per-media-type rendering here.
|
|
971
1011
|
if (!generation_ids || generation_ids.length === 0) {
|
|
972
1012
|
const single = results[0];
|
|
973
1013
|
single._hint = pending.length === 0
|
|
974
1014
|
? 'This generation is in a FINAL state — do not poll it again.'
|
|
975
1015
|
: pendingHint;
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
1016
|
+
const singleText = JSON.stringify(single, null, 2);
|
|
1017
|
+
const res = single.result || {};
|
|
1018
|
+
return uiCompleted({
|
|
1019
|
+
tool: 'get_generation_status', kind: 'status', client,
|
|
1020
|
+
model: 'Generations', gen: { generation_id: single.generation_id },
|
|
1021
|
+
settings: {},
|
|
1022
|
+
items: [{
|
|
1023
|
+
id: single.generation_id,
|
|
1024
|
+
state: single.state,
|
|
1025
|
+
title: res.prompt_used || res.prompt || undefined,
|
|
1026
|
+
url: Array.isArray(res.urls) ? res.urls[0] : undefined,
|
|
1027
|
+
}],
|
|
1028
|
+
}, singleText);
|
|
979
1029
|
}
|
|
980
1030
|
|
|
981
1031
|
const text = JSON.stringify({
|