@kolbo/mcp 1.53.0 → 1.53.1
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/widgets/catalog.js +16 -5
- package/src/tools/models.js +12 -6
package/package.json
CHANGED
|
@@ -31,9 +31,20 @@ el('kolbo-link').onclick = function (e) { e.preventDefault(); window.kolbo.openL
|
|
|
31
31
|
var state = null;
|
|
32
32
|
|
|
33
33
|
function boot(sc) {
|
|
34
|
-
if (!sc || !sc.groups) return;
|
|
34
|
+
if (!sc || !sc.groups || !sc.groups.length) return false;
|
|
35
35
|
state = sc;
|
|
36
36
|
el('title').textContent = sc.title || 'AI Models';
|
|
37
|
+
// Internal lookup (Claude checking caps mid-task): a full catalog card would
|
|
38
|
+
// be chat spam, an empty card would look broken. One expandable row instead.
|
|
39
|
+
if (sc.compact) {
|
|
40
|
+
el('stage').innerHTML = '<div class="k-audio-row" id="expand" style="cursor:pointer;padding:8px">' +
|
|
41
|
+
'<div class="k-audio-meta"><div class="k-audio-title" style="font-size:12px">Kolbo AI models</div>' +
|
|
42
|
+
'<div class="k-audio-sub" style="font-size:10.5px">Tap to browse what you can generate</div></div>' +
|
|
43
|
+
'<span class="k-chip" style="flex:none;padding:2px 7px;font-size:10px">Browse</span></div>';
|
|
44
|
+
el('expand').onclick = function () { sc.compact = false; boot(sc); };
|
|
45
|
+
window.kolbo.notifySize();
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
37
48
|
var shown = sc.groups.reduce(function (n, g) { return n + g.models.length; }, 0);
|
|
38
49
|
el('count-chip').style.display = '';
|
|
39
50
|
el('count-chip').textContent = sc.total_available && sc.total_available > shown
|
|
@@ -60,13 +71,13 @@ function boot(sc) {
|
|
|
60
71
|
};
|
|
61
72
|
});
|
|
62
73
|
window.kolbo.notifySize();
|
|
74
|
+
return true;
|
|
63
75
|
}
|
|
64
76
|
|
|
65
77
|
window.kolbo.onToolResult(function (result) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
//
|
|
69
|
-
// was attached on purpose. Collapse instead of showing a dead card.
|
|
78
|
+
if (boot(result.structuredContent || structured(result))) return;
|
|
79
|
+
// No catalog data reached the iframe (host/version mismatch, or a filter
|
|
80
|
+
// that matched nothing) — collapse instead of showing a dead card.
|
|
70
81
|
var card = document.querySelector('.k-card');
|
|
71
82
|
if (card) card.style.display = 'none';
|
|
72
83
|
window.kolbo.notifySize();
|
package/src/tools/models.js
CHANGED
|
@@ -49,7 +49,7 @@ function modelChips(m) {
|
|
|
49
49
|
// deliberately EXCLUDED — we always want a specific model chosen (server
|
|
50
50
|
// instruction #9): auto-routing hides the model choice and the generation
|
|
51
51
|
// metadata used to read just "Auto".
|
|
52
|
-
function buildCatalogStructured(models, type) {
|
|
52
|
+
function buildCatalogStructured(models, type, compact) {
|
|
53
53
|
const groups = [];
|
|
54
54
|
const byName = new Map();
|
|
55
55
|
const isAuto = (m) => /^auto$|smart.select/i.test(String(m.name || '')) || /smart-select|k_auto/i.test(String(m.identifier || ''));
|
|
@@ -78,6 +78,7 @@ function buildCatalogStructured(models, type) {
|
|
|
78
78
|
widget: 'catalog',
|
|
79
79
|
title: 'Kolbo AI Models' + (type ? ' — ' + type : ''),
|
|
80
80
|
total_available: models.length,
|
|
81
|
+
compact: compact === true,
|
|
81
82
|
groups,
|
|
82
83
|
};
|
|
83
84
|
}
|
|
@@ -91,11 +92,16 @@ function registerModelTools(server, client, options = {}) {
|
|
|
91
92
|
{
|
|
92
93
|
type: z.string().optional().describe('Filter by DB type name: "text_to_img", "image_editing", "text_to_video", "img_to_video", "draw_to_video", "video_to_video", "elements", "firstlastgenerations", "lipsync-image", "lipsync-video", "music_gen", "text_to_speech", "text_to_sound", "stt", "text". Legacy aliases also accepted: "image", "image_edit", "video", "video_from_image", "video_from_video", "music", "speech", "sound", "chat", "lipsync" (both lipsync types), "three_d" (all 3D types), "first_last_frame", "transcription". Omit for all models.'),
|
|
93
94
|
format: z.enum(['text', 'json']).optional().describe('Output format. "text" (default) returns a human-readable summary with the most-used caps. "json" returns the raw model documents from the API — use this when you need to programmatically verify caps (max_reference_images, max_visual_dna, max_video_duration, supported_aspect_ratios, etc.) before passing an array/value that might exceed a model-specific limit. The JSON form is the source of truth; the text form is a convenience preview.'),
|
|
94
|
-
display_catalog: z.boolean().optional().describe('Set true
|
|
95
|
+
display_catalog: z.boolean().optional().describe('Set true when the USER explicitly asked to see/browse the available models — the visual catalog opens expanded. Leave unset for internal lookups (verifying a model name, checking caps before a generation): the catalog stays collapsed to a single row the user can tap to browse.')
|
|
95
96
|
},
|
|
96
97
|
async ({ type, format, display_catalog }) => {
|
|
97
|
-
//
|
|
98
|
-
//
|
|
98
|
+
// The tool DECLARATION always carries widget meta, so hosts that mount
|
|
99
|
+
// from tools/list (Claude Code desktop) prepare an iframe on EVERY call.
|
|
100
|
+
// Returning plain text for internal lookups left that iframe with no
|
|
101
|
+
// data — a dead, empty "Widget from Kolbo list_models" shell. Always
|
|
102
|
+
// ship structuredContent; `compact` tells the widget to render a single
|
|
103
|
+
// "Browse models" row (expandable) instead of the full catalog, which is
|
|
104
|
+
// what display_catalog was really asking for.
|
|
99
105
|
const showCatalog = display_catalog === true;
|
|
100
106
|
const path = type ? `/v1/models?type=${encodeURIComponent(type)}` : '/v1/models';
|
|
101
107
|
const result = await client.get(path);
|
|
@@ -106,7 +112,7 @@ function registerModelTools(server, client, options = {}) {
|
|
|
106
112
|
// resolution multipliers, supports_* flags, prompt-length limits, etc.).
|
|
107
113
|
if (format === 'json') {
|
|
108
114
|
const text = JSON.stringify({ count: result.count, models: result.models }, null, 2);
|
|
109
|
-
if (ui()
|
|
115
|
+
if (ui()) return uiResult(UI.catalog, text, buildCatalogStructured(result.models, type, !showCatalog));
|
|
110
116
|
return { content: [{ type: 'text', text }] };
|
|
111
117
|
}
|
|
112
118
|
|
|
@@ -277,7 +283,7 @@ function registerModelTools(server, client, options = {}) {
|
|
|
277
283
|
}
|
|
278
284
|
|
|
279
285
|
const text = `Available models (${result.count}):\n\n${sections.join('\n\n')}\n\nUse the "identifier" value as the "model" parameter in generate tools. For programmatic cap validation, re-call with format: "json".`;
|
|
280
|
-
if (ui()
|
|
286
|
+
if (ui()) return uiResult(UI.catalog, text, buildCatalogStructured(result.models, type, !showCatalog));
|
|
281
287
|
return { content: [{ type: 'text', text }] };
|
|
282
288
|
}
|
|
283
289
|
);
|