@kolbo/mcp 1.30.5 → 1.30.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/apps/bridge.js +21 -3
- package/src/apps/index.js +39 -3
- package/src/tools/generate.js +16 -1
package/package.json
CHANGED
package/src/apps/bridge.js
CHANGED
|
@@ -102,10 +102,28 @@ const BRIDGE_JS = `
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
var sizeTimer = null;
|
|
105
|
-
|
|
105
|
+
function queueSize(delay) {
|
|
106
106
|
clearTimeout(sizeTimer);
|
|
107
|
-
sizeTimer = setTimeout(notifySize, 120);
|
|
108
|
-
}
|
|
107
|
+
sizeTimer = setTimeout(notifySize, delay || 120);
|
|
108
|
+
}
|
|
109
|
+
new MutationObserver(function () { queueSize(120); })
|
|
110
|
+
.observe(document.documentElement, { childList: true, subtree: true, attributes: true });
|
|
111
|
+
// DOM mutations don't fire when an <img>/<video> finishes loading and reflows
|
|
112
|
+
// the card — without this the host keeps the pre-image height and the card
|
|
113
|
+
// gets an inner scrollbar. ResizeObserver catches every layout change.
|
|
114
|
+
if (window.ResizeObserver) {
|
|
115
|
+
var ro = new ResizeObserver(function () { queueSize(60); });
|
|
116
|
+
ro.observe(document.documentElement);
|
|
117
|
+
ro.observe(document.body);
|
|
118
|
+
var card = document.querySelector('.k-card');
|
|
119
|
+
if (card) ro.observe(card);
|
|
120
|
+
}
|
|
121
|
+
// Belt and suspenders: media load events bubble as capture-phase 'load'.
|
|
122
|
+
document.addEventListener('load', function (e) {
|
|
123
|
+
var t = e.target && e.target.tagName;
|
|
124
|
+
if (t === 'IMG' || t === 'VIDEO') queueSize(60);
|
|
125
|
+
}, true);
|
|
126
|
+
document.addEventListener('loadedmetadata', function () { queueSize(60); }, true);
|
|
109
127
|
|
|
110
128
|
window.kolbo = {
|
|
111
129
|
ready: function (f) { if (initialized) f(hostContext); else readyFns.push(f); },
|
package/src/apps/index.js
CHANGED
|
@@ -169,14 +169,24 @@ async function modelInfoMap(client) {
|
|
|
169
169
|
// Real p75 wall-clock estimate mined from production creditUsages —
|
|
170
170
|
// the same source the in-app countdowns use. No estimate → no ETA shown.
|
|
171
171
|
const eta = Number(m.estimatedDurationSeconds || m.estimated_duration_seconds) || null;
|
|
172
|
-
const info = { icon, eta };
|
|
173
|
-
|
|
172
|
+
const info = { icon, eta, id: m.identifier || null };
|
|
173
|
+
// Display names collide across variants ("Nano Banana 2" names both the
|
|
174
|
+
// t2i model and its editing sibling) — on collision keep the model with
|
|
175
|
+
// the SHORTEST identifier (the base model), deterministically.
|
|
176
|
+
const setName = (k) => {
|
|
177
|
+
const prev = byKey.get(k);
|
|
178
|
+
if (!prev || !prev.id || (info.id && info.id.length < prev.id.length)) byKey.set(k, info);
|
|
179
|
+
};
|
|
180
|
+
if (m.name) setName(String(m.name).toLowerCase());
|
|
174
181
|
if (m.identifier) byKey.set(String(m.identifier).toLowerCase(), info);
|
|
175
182
|
}
|
|
176
183
|
} catch (_) {
|
|
177
184
|
/* fail open — widgets fall back to monogram chips, no ETA */
|
|
178
185
|
}
|
|
179
|
-
|
|
186
|
+
// Never cache an empty map: the first request in a fresh worker (typical
|
|
187
|
+
// right after a deploy restart) can fail transiently, and caching that
|
|
188
|
+
// failure blanks every model icon for the TTL window.
|
|
189
|
+
if (byKey.size > 0) infoCache.set(cacheKey, { at: Date.now(), byKey });
|
|
180
190
|
return byKey;
|
|
181
191
|
}
|
|
182
192
|
|
|
@@ -192,6 +202,31 @@ async function modelIcon(client, modelName) {
|
|
|
192
202
|
return (await modelInfo(client, modelName)).icon;
|
|
193
203
|
}
|
|
194
204
|
|
|
205
|
+
/**
|
|
206
|
+
* Lenient model-identifier resolution for LLM-supplied model args.
|
|
207
|
+
* Users say "z-image"; the real identifier is "z-image/turbo" — the backend
|
|
208
|
+
* has no fuzzy matching on generation routes and fails deep in credit
|
|
209
|
+
* reservation. Resolve here: exact name/identifier hit → its identifier;
|
|
210
|
+
* else a UNIQUE identifier prefix match ("z-image" → "z-image/turbo");
|
|
211
|
+
* ambiguous or unknown → pass through unchanged (API stays source of truth).
|
|
212
|
+
*/
|
|
213
|
+
async function canonicalModelId(client, input) {
|
|
214
|
+
if (!input || typeof input !== 'string') return input;
|
|
215
|
+
try {
|
|
216
|
+
const map = await modelInfoMap(client);
|
|
217
|
+
const key = input.toLowerCase().trim();
|
|
218
|
+
const hit = map.get(key) || map.get(key.replace(/\s+/g, '-'));
|
|
219
|
+
if (hit && hit.id) return hit.id;
|
|
220
|
+
const ids = new Set();
|
|
221
|
+
for (const info of map.values()) {
|
|
222
|
+
const id = (info.id || '').toLowerCase();
|
|
223
|
+
if (id && (id.startsWith(key + '/') || id.startsWith(key + '-'))) ids.add(info.id);
|
|
224
|
+
}
|
|
225
|
+
if (ids.size === 1) return [...ids][0];
|
|
226
|
+
} catch (_) { /* fail open */ }
|
|
227
|
+
return input;
|
|
228
|
+
}
|
|
229
|
+
|
|
195
230
|
/* ------------------------------------------------------------------ */
|
|
196
231
|
/* Declaration-level widget metadata */
|
|
197
232
|
/* ------------------------------------------------------------------ */
|
|
@@ -256,6 +291,7 @@ module.exports = {
|
|
|
256
291
|
modelIcon,
|
|
257
292
|
modelInfo,
|
|
258
293
|
modelInfoMap,
|
|
294
|
+
canonicalModelId,
|
|
259
295
|
resolveAvatarUrl,
|
|
260
296
|
widgetHtml, // exported for smoke tests
|
|
261
297
|
};
|
package/src/tools/generate.js
CHANGED
|
@@ -7,7 +7,7 @@ const { z } = require('zod');
|
|
|
7
7
|
const FormData = require('form-data');
|
|
8
8
|
const { pollUntilDone } = require('../polling');
|
|
9
9
|
const { resolveToBuffer, creditFields, projectIdField, inlineImageBlocks, uiGenerating, uiCompleted, appsEnabled } = require('./_shared');
|
|
10
|
-
const { UI, uiResult } = require('../apps');
|
|
10
|
+
const { UI, uiResult, canonicalModelId } = require('../apps');
|
|
11
11
|
|
|
12
12
|
function registerGenerateTools(server, client, options = {}) {
|
|
13
13
|
// Only enabled by hosts that explicitly opt in (the remote HTTP connector).
|
|
@@ -37,6 +37,7 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
37
37
|
project_id: projectIdField
|
|
38
38
|
},
|
|
39
39
|
async ({ prompt, model, aspect_ratio, enhance_prompt, num_images, reference_images, visual_dna_ids, moodboard_id, enable_web_search, resolution, preset_id, project_id }) => {
|
|
40
|
+
model = await canonicalModelId(client, model); // lenient id resolution ("z-image" → "z-image/turbo")
|
|
40
41
|
const gen = await client.post('/v1/generate/image', {
|
|
41
42
|
prompt, model, aspect_ratio, enhance_prompt, num_images,
|
|
42
43
|
reference_images, visual_dna_ids, moodboard_id, enable_web_search, resolution, preset_id, project_id
|
|
@@ -87,6 +88,7 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
87
88
|
project_id: projectIdField
|
|
88
89
|
},
|
|
89
90
|
async ({ prompt, model, source_images, aspect_ratio, enhance_prompt, num_images, visual_dna_ids, moodboard_id, enable_web_search, resolution, project_id }) => {
|
|
91
|
+
model = await canonicalModelId(client, model); // lenient id resolution ("z-image" → "z-image/turbo")
|
|
90
92
|
const gen = await client.post('/v1/generate/image-edit', {
|
|
91
93
|
prompt, model, source_images, aspect_ratio, enhance_prompt, num_images,
|
|
92
94
|
visual_dna_ids, moodboard_id, enable_web_search, resolution, project_id
|
|
@@ -143,6 +145,7 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
143
145
|
project_id: projectIdField
|
|
144
146
|
},
|
|
145
147
|
async ({ prompt, scene_count, model, aspect_ratio, workflow_type, duration, enhance_prompt, reference_images, visual_dna_ids, moodboard_id, moodboard_ids, resolution, project_id }) => {
|
|
148
|
+
model = await canonicalModelId(client, model); // lenient id resolution ("z-image" → "z-image/turbo")
|
|
146
149
|
const gen = await client.post('/v1/generate/creative-director', {
|
|
147
150
|
prompt, scene_count, model, aspect_ratio, workflow_type, duration,
|
|
148
151
|
enhance_prompt, reference_images, visual_dna_ids, moodboard_id, moodboard_ids, resolution, project_id
|
|
@@ -204,6 +207,7 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
204
207
|
project_id: projectIdField
|
|
205
208
|
},
|
|
206
209
|
async ({ prompt, model, aspect_ratio, duration, enhance_prompt, reference_images, resolution, preset_id, project_id }) => {
|
|
210
|
+
model = await canonicalModelId(client, model); // lenient id resolution ("z-image" → "z-image/turbo")
|
|
207
211
|
const gen = await client.post('/v1/generate/video', {
|
|
208
212
|
prompt, model, aspect_ratio, duration, enhance_prompt, reference_images, resolution, preset_id, project_id
|
|
209
213
|
});
|
|
@@ -252,6 +256,7 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
252
256
|
project_id: projectIdField
|
|
253
257
|
},
|
|
254
258
|
async ({ image_url, prompt, model, aspect_ratio, duration, enhance_prompt, visual_dna_ids, resolution, project_id }) => {
|
|
259
|
+
model = await canonicalModelId(client, model); // lenient id resolution ("z-image" → "z-image/turbo")
|
|
255
260
|
const gen = await client.post('/v1/generate/video/from-image', {
|
|
256
261
|
image_url, prompt, model, aspect_ratio, duration, enhance_prompt, visual_dna_ids, resolution, project_id
|
|
257
262
|
});
|
|
@@ -299,6 +304,7 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
299
304
|
project_id: projectIdField
|
|
300
305
|
},
|
|
301
306
|
async ({ prompt, model, style, instrumental, lyrics, vocal_gender, enhance_prompt, preset_id, project_id }) => {
|
|
307
|
+
model = await canonicalModelId(client, model); // lenient id resolution ("z-image" → "z-image/turbo")
|
|
302
308
|
const gen = await client.post('/v1/generate/music', {
|
|
303
309
|
prompt, model, style, instrumental, lyrics, vocal_gender, enhance_prompt, preset_id, project_id
|
|
304
310
|
});
|
|
@@ -340,6 +346,7 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
340
346
|
project_id: projectIdField
|
|
341
347
|
},
|
|
342
348
|
async ({ text, voice, model, language, project_id }) => {
|
|
349
|
+
model = await canonicalModelId(client, model); // lenient id resolution ("z-image" → "z-image/turbo")
|
|
343
350
|
const gen = await client.post('/v1/generate/speech', {
|
|
344
351
|
text, voice, model, language, project_id
|
|
345
352
|
});
|
|
@@ -380,6 +387,7 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
380
387
|
project_id: projectIdField
|
|
381
388
|
},
|
|
382
389
|
async ({ prompt, model, duration, prompt_influence, project_id }) => {
|
|
390
|
+
model = await canonicalModelId(client, model); // lenient id resolution ("z-image" → "z-image/turbo")
|
|
383
391
|
const gen = await client.post('/v1/generate/sound', {
|
|
384
392
|
prompt, model, duration, prompt_influence, project_id
|
|
385
393
|
});
|
|
@@ -451,6 +459,7 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
451
459
|
project_id: projectIdField
|
|
452
460
|
},
|
|
453
461
|
async ({ prompt, model, reference_images, reference_videos, audio_url, files, duration, aspect_ratio, motion, preset_id, enhance_prompt, visual_dna_ids, resolution, project_id }) => {
|
|
462
|
+
model = await canonicalModelId(client, model); // lenient id resolution ("z-image" → "z-image/turbo")
|
|
454
463
|
if (!prompt) throw new Error('prompt is required');
|
|
455
464
|
|
|
456
465
|
let startResponse;
|
|
@@ -527,6 +536,7 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
527
536
|
project_id: projectIdField
|
|
528
537
|
},
|
|
529
538
|
async ({ first_frame_url, last_frame_url, first_frame, last_frame, prompt, model, duration, aspect_ratio, enhance_prompt, visual_dna_ids, resolution, project_id }) => {
|
|
539
|
+
model = await canonicalModelId(client, model); // lenient id resolution ("z-image" → "z-image/turbo")
|
|
530
540
|
const urlMode = first_frame_url && last_frame_url;
|
|
531
541
|
const fileMode = first_frame && last_frame;
|
|
532
542
|
if (!urlMode && !fileMode) {
|
|
@@ -614,6 +624,7 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
614
624
|
project_id: projectIdField
|
|
615
625
|
},
|
|
616
626
|
async ({ source, audio, text_prompt, model, bounding_box_target, sync_mode, model_mode, emotion, temperature, occlusion_detection_enabled, active_speaker_detection, project_id }) => {
|
|
627
|
+
model = await canonicalModelId(client, model); // lenient id resolution ("z-image" → "z-image/turbo")
|
|
617
628
|
if (!source) throw new Error('source is required (URL or absolute local path to image/video)');
|
|
618
629
|
if (!audio) throw new Error('audio is required (URL or absolute local path to audio file)');
|
|
619
630
|
|
|
@@ -732,6 +743,7 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
732
743
|
project_id: projectIdField
|
|
733
744
|
},
|
|
734
745
|
async ({ source_video, prompt, model, aspect_ratio, duration, enhance_prompt, visual_dna_ids, resolution, reference_images, reference_videos, elements, preset, source_language, translation_language, srt_content, srt_file_url, vocabulary, customization, project_id }) => {
|
|
746
|
+
model = await canonicalModelId(client, model); // lenient id resolution ("z-image" → "z-image/turbo")
|
|
735
747
|
if (!source_video) throw new Error('source_video is required');
|
|
736
748
|
|
|
737
749
|
const isUrl = /^https?:\/\//i.test(source_video);
|
|
@@ -868,6 +880,7 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
868
880
|
project_id: projectIdField
|
|
869
881
|
},
|
|
870
882
|
async ({ prompt, reference_images, mode, texture_prompt, model, topology, target_polycount, enable_tpose, enable_pbr, project_id }) => {
|
|
883
|
+
model = await canonicalModelId(client, model); // lenient id resolution ("z-image" → "z-image/turbo")
|
|
871
884
|
if (!prompt && !(reference_images && reference_images.length > 0)) {
|
|
872
885
|
throw new Error('Provide prompt (text mode) or reference_images (single/multi mode)');
|
|
873
886
|
}
|
|
@@ -927,6 +940,7 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
927
940
|
project_id: projectIdField
|
|
928
941
|
},
|
|
929
942
|
async ({ image_url, operation, model, scale, aspect_ratio, skin_strength, prompt, project_id }) => {
|
|
943
|
+
model = await canonicalModelId(client, model); // lenient id resolution ("z-image" → "z-image/turbo")
|
|
930
944
|
if (operation === 'magic_edit' && !prompt) throw new Error('prompt is required for magic_edit operation');
|
|
931
945
|
if (operation === 'reframe' && !aspect_ratio) throw new Error('aspect_ratio is required for reframe operation');
|
|
932
946
|
|
|
@@ -979,6 +993,7 @@ function registerGenerateTools(server, client, options = {}) {
|
|
|
979
993
|
project_id: projectIdField
|
|
980
994
|
},
|
|
981
995
|
async ({ video_url, operation, model, aspect_ratio, scale, prompt, image_url, audio_url, duration, mode, project_id }) => {
|
|
996
|
+
model = await canonicalModelId(client, model); // lenient id resolution ("z-image" → "z-image/turbo")
|
|
982
997
|
if (operation === 'magic_edit' && !prompt) throw new Error('prompt is required for magic_edit');
|
|
983
998
|
if (operation === 'generate_audio' && !prompt) throw new Error('prompt is required for generate_audio');
|
|
984
999
|
if (operation === 'reframe' && !aspect_ratio) throw new Error('aspect_ratio is required for reframe');
|