@kolbo/mcp 1.106.0 → 1.106.2
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/index.js +64 -48
- package/src/apps/theme.js +0 -2
- package/src/apps/widgets/generation.js +4 -12
package/package.json
CHANGED
package/src/apps/index.js
CHANGED
|
@@ -20,25 +20,25 @@ const { generationWidgetHtml } = require('./widgets/generation');
|
|
|
20
20
|
const { mediaGridWidgetHtml } = require('./widgets/mediaGrid');
|
|
21
21
|
const { catalogWidgetHtml } = require('./widgets/catalog');
|
|
22
22
|
const { transcriptWidgetHtml } = require('./widgets/transcript');
|
|
23
|
-
const { uploadWidgetHtml } = require('./widgets/upload');
|
|
24
|
-
const { fontUploadWidgetHtml } = require('./widgets/fontUpload');
|
|
23
|
+
const { uploadWidgetHtml } = require('./widgets/upload');
|
|
24
|
+
const { fontUploadWidgetHtml } = require('./widgets/fontUpload');
|
|
25
25
|
const { listWidgetHtml } = require('./widgets/list');
|
|
26
26
|
const { HOST_MAP } = require('../cdn');
|
|
27
|
-
const { plansWidgetHtml } = require('./widgets/plans');
|
|
28
|
-
const { creditsWidgetHtml } = require('./widgets/credits');
|
|
29
|
-
const { ResourceTemplate } = require('@modelcontextprotocol/sdk/server/mcp.js');
|
|
30
|
-
const { McpError, ErrorCode } = require('@modelcontextprotocol/sdk/types.js');
|
|
27
|
+
const { plansWidgetHtml } = require('./widgets/plans');
|
|
28
|
+
const { creditsWidgetHtml } = require('./widgets/credits');
|
|
29
|
+
const { ResourceTemplate } = require('@modelcontextprotocol/sdk/server/mcp.js');
|
|
30
|
+
const { McpError, ErrorCode } = require('@modelcontextprotocol/sdk/types.js');
|
|
31
31
|
|
|
32
32
|
const UI = {
|
|
33
33
|
generation: 'ui://kolbo/generation.html',
|
|
34
34
|
mediaGrid: 'ui://kolbo/media-grid.html',
|
|
35
35
|
catalog: 'ui://kolbo/catalog.html',
|
|
36
36
|
transcript: 'ui://kolbo/transcript.html',
|
|
37
|
-
upload: 'ui://kolbo/upload.html',
|
|
38
|
-
fontUpload: 'ui://kolbo/font-upload.html',
|
|
37
|
+
upload: 'ui://kolbo/upload.html',
|
|
38
|
+
fontUpload: 'ui://kolbo/font-upload.html',
|
|
39
39
|
list: 'ui://kolbo/list.html',
|
|
40
|
-
plans: 'ui://kolbo/plans.html',
|
|
41
|
-
credits: 'ui://kolbo/credits.html',
|
|
40
|
+
plans: 'ui://kolbo/plans.html',
|
|
41
|
+
credits: 'ui://kolbo/credits.html',
|
|
42
42
|
};
|
|
43
43
|
|
|
44
44
|
const WIDGET_BUILDERS = {
|
|
@@ -46,11 +46,11 @@ const WIDGET_BUILDERS = {
|
|
|
46
46
|
[UI.mediaGrid]: mediaGridWidgetHtml,
|
|
47
47
|
[UI.catalog]: catalogWidgetHtml,
|
|
48
48
|
[UI.transcript]: transcriptWidgetHtml,
|
|
49
|
-
[UI.upload]: uploadWidgetHtml,
|
|
50
|
-
[UI.fontUpload]: fontUploadWidgetHtml,
|
|
49
|
+
[UI.upload]: uploadWidgetHtml,
|
|
50
|
+
[UI.fontUpload]: fontUploadWidgetHtml,
|
|
51
51
|
[UI.list]: listWidgetHtml,
|
|
52
|
-
[UI.plans]: plansWidgetHtml,
|
|
53
|
-
[UI.credits]: creditsWidgetHtml,
|
|
52
|
+
[UI.plans]: plansWidgetHtml,
|
|
53
|
+
[UI.credits]: creditsWidgetHtml,
|
|
54
54
|
};
|
|
55
55
|
|
|
56
56
|
// Widgets are pure functions of source — build once per process.
|
|
@@ -169,11 +169,11 @@ function registerApps(server) {
|
|
|
169
169
|
[UI.mediaGrid, 'Kolbo Library Widget'],
|
|
170
170
|
[UI.catalog, 'Kolbo Model Catalog Widget'],
|
|
171
171
|
[UI.transcript, 'Kolbo Transcription Widget'],
|
|
172
|
-
[UI.upload, 'Kolbo Upload Widget'],
|
|
173
|
-
[UI.fontUpload, 'Kolbo Font Upload Widget'],
|
|
172
|
+
[UI.upload, 'Kolbo Upload Widget'],
|
|
173
|
+
[UI.fontUpload, 'Kolbo Font Upload Widget'],
|
|
174
174
|
[UI.list, 'Kolbo List Widget'],
|
|
175
|
-
[UI.plans, 'Kolbo Plans Widget'],
|
|
176
|
-
[UI.credits, 'Kolbo Credit Balance Widget'],
|
|
175
|
+
[UI.plans, 'Kolbo Plans Widget'],
|
|
176
|
+
[UI.credits, 'Kolbo Credit Balance Widget'],
|
|
177
177
|
]) {
|
|
178
178
|
for (const u of [versionedUri(uri), uri]) {
|
|
179
179
|
registerAppResource(
|
|
@@ -185,30 +185,30 @@ function registerApps(server) {
|
|
|
185
185
|
_meta: { csp: WIDGET_CSP, ui: { csp: WIDGET_CSP } },
|
|
186
186
|
}],
|
|
187
187
|
})
|
|
188
|
-
);
|
|
189
|
-
}
|
|
190
|
-
// Published tool definitions and old conversations can retain any previous
|
|
191
|
-
// content hash. Keep those addresses readable after deploying new HTML.
|
|
192
|
-
// Match only this registered widget and the version format we publish.
|
|
193
|
-
registerAppResource(
|
|
194
|
-
server, name + ' (previous versions)',
|
|
195
|
-
new ResourceTemplate(uri + '{?v}', { list: undefined }),
|
|
196
|
-
{ mimeType: RESOURCE_MIME_TYPE, _meta: { csp: WIDGET_CSP, ui: { csp: WIDGET_CSP } } },
|
|
197
|
-
async (requestedUri) => {
|
|
198
|
-
const requested = requestedUri.href;
|
|
199
|
-
if (!new RegExp('^' + uri.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '\\?v=[a-f0-9]{10}$').test(requested)) {
|
|
200
|
-
throw new McpError(ErrorCode.InvalidParams, 'Unknown widget version URI');
|
|
201
|
-
}
|
|
202
|
-
return {
|
|
203
|
-
contents: [{
|
|
204
|
-
uri: requested, mimeType: RESOURCE_MIME_TYPE, text: widgetHtml(uri),
|
|
205
|
-
_meta: { csp: WIDGET_CSP, ui: { csp: WIDGET_CSP } },
|
|
206
|
-
}],
|
|
207
|
-
};
|
|
208
|
-
}
|
|
209
|
-
);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
// Published tool definitions and old conversations can retain any previous
|
|
191
|
+
// content hash. Keep those addresses readable after deploying new HTML.
|
|
192
|
+
// Match only this registered widget and the version format we publish.
|
|
193
|
+
registerAppResource(
|
|
194
|
+
server, name + ' (previous versions)',
|
|
195
|
+
new ResourceTemplate(uri + '{?v}', { list: undefined }),
|
|
196
|
+
{ mimeType: RESOURCE_MIME_TYPE, _meta: { csp: WIDGET_CSP, ui: { csp: WIDGET_CSP } } },
|
|
197
|
+
async (requestedUri) => {
|
|
198
|
+
const requested = requestedUri.href;
|
|
199
|
+
if (!new RegExp('^' + uri.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '\\?v=[a-f0-9]{10}$').test(requested)) {
|
|
200
|
+
throw new McpError(ErrorCode.InvalidParams, 'Unknown widget version URI');
|
|
201
|
+
}
|
|
202
|
+
return {
|
|
203
|
+
contents: [{
|
|
204
|
+
uri: requested, mimeType: RESOURCE_MIME_TYPE, text: widgetHtml(uri),
|
|
205
|
+
_meta: { csp: WIDGET_CSP, ui: { csp: WIDGET_CSP } },
|
|
206
|
+
}],
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
212
|
|
|
213
213
|
/** `_meta` for a tool RESULT (and optionally for tool registration). */
|
|
214
214
|
function uiMeta(uri) {
|
|
@@ -371,9 +371,25 @@ async function modelInfo(client, modelName) {
|
|
|
371
371
|
const rows = catalog.all || [];
|
|
372
372
|
return rows.find((row) => normId(row.id) === want || normId(row.name) === want)
|
|
373
373
|
|| rows.find((row) => normId(row.id).startsWith(want) || normId(row.name).startsWith(want))
|
|
374
|
+
|| variantBase(rows, modelName)
|
|
374
375
|
|| { icon: null, eta: null, name: null };
|
|
375
376
|
}
|
|
376
377
|
|
|
378
|
+
// A finished generation can report an internal variant of a catalog model —
|
|
379
|
+
// "seedance-2-5-draft-enhance" (draft tier + prompt enhance) is not itself in
|
|
380
|
+
// /v1/models, so the chip showed a letter monogram and the raw id. Resolve it
|
|
381
|
+
// to the LONGEST catalog identifier it extends at a "-" boundary
|
|
382
|
+
// ("seedance-2-5", not "seedance-2").
|
|
383
|
+
function variantBase(rows, modelName) {
|
|
384
|
+
const raw = String(modelName).toLowerCase();
|
|
385
|
+
let best = null;
|
|
386
|
+
for (const row of rows) {
|
|
387
|
+
const id = row.id && String(row.id).toLowerCase();
|
|
388
|
+
if (id && raw.startsWith(id + '-') && (!best || id.length > best.id.length)) best = row;
|
|
389
|
+
}
|
|
390
|
+
return best;
|
|
391
|
+
}
|
|
392
|
+
|
|
377
393
|
/**
|
|
378
394
|
* Snap a requested aspect ratio onto the catalog enum for that model.
|
|
379
395
|
* Every image/video generate_* tool must call this after canonicalModelId —
|
|
@@ -621,8 +637,8 @@ async function canonicalModelId(client, input, type) {
|
|
|
621
637
|
if (!input || typeof input !== 'string') return input;
|
|
622
638
|
const key = input.toLowerCase().trim();
|
|
623
639
|
const want = normId(key);
|
|
624
|
-
if (!want || AUTO_ALIASES.has(want)) return input;
|
|
625
|
-
// Exact native-workflow ids pass through: the near-miss check below would reject an
|
|
640
|
+
if (!want || AUTO_ALIASES.has(want)) return input;
|
|
641
|
+
// Exact native-workflow ids pass through: the near-miss check below would reject an
|
|
626
642
|
// unpublished or cached-out 'kolbo-*' id as unknown.
|
|
627
643
|
if (NATIVE_WORKFLOW_MODEL_IDS.has(key)) return input;
|
|
628
644
|
|
|
@@ -769,8 +785,8 @@ const TOOL_WIDGETS = {
|
|
|
769
785
|
// never saw it as widget-carrying. Result-level _meta alone isn't enough.
|
|
770
786
|
list_color_palettes: UI.mediaGrid,
|
|
771
787
|
// upload widget
|
|
772
|
-
media_upload_widget: UI.upload,
|
|
773
|
-
font_upload_widget: UI.fontUpload,
|
|
788
|
+
media_upload_widget: UI.upload,
|
|
789
|
+
font_upload_widget: UI.fontUpload,
|
|
774
790
|
// generic list widget — flat record lists with no natural thumbnail
|
|
775
791
|
list_projects: UI.list,
|
|
776
792
|
// Must stay list.html — mapping this to generation.html mounts "Kolbo Generation /
|
|
@@ -782,8 +798,8 @@ const TOOL_WIDGETS = {
|
|
|
782
798
|
list_docs: UI.list,
|
|
783
799
|
list_media_folders: UI.list,
|
|
784
800
|
list_visual_dna_folders: UI.list,
|
|
785
|
-
show_plans: UI.plans,
|
|
786
|
-
check_credits: UI.credits,
|
|
801
|
+
show_plans: UI.plans,
|
|
802
|
+
check_credits: UI.credits,
|
|
787
803
|
list_project_assets: UI.list,
|
|
788
804
|
};
|
|
789
805
|
|
package/src/apps/theme.js
CHANGED
|
@@ -335,8 +335,6 @@ video::-webkit-media-controls-fullscreen-button { display: none !important; }
|
|
|
335
335
|
hover-only Download / Attach buttons were simply invisible. */
|
|
336
336
|
@media (hover: none) { .k-dl { opacity: 1; } }
|
|
337
337
|
.k-dl:hover { background: var(--brand); border-color: var(--brand); }
|
|
338
|
-
/* Attach-to-prompt sits immediately left of Download (30px button + 8px gap). */
|
|
339
|
-
.k-attach { right: 46px; }
|
|
340
338
|
.k-viewer { position: relative; }
|
|
341
339
|
|
|
342
340
|
/* Keep the whole completed card under the host's iframe height cap (~800px):
|
|
@@ -1040,12 +1040,10 @@ function renderLinks(urls) {
|
|
|
1040
1040
|
// Small hover download button attached to a media cell (per-item downloads —
|
|
1041
1041
|
// batch grids and CD scenes have no single "current" url for the action row).
|
|
1042
1042
|
function dlBtnHTML(u) {
|
|
1043
|
-
//
|
|
1044
|
-
//
|
|
1045
|
-
// media
|
|
1046
|
-
return '<button class="k-dl
|
|
1047
|
-
+ ICONS.upload + '</button>'
|
|
1048
|
-
+ '<button class="k-dl" data-dl="' + esc(u) + '" title="Download" aria-label="Download">' + ICONS.download + '</button>';
|
|
1043
|
+
// Download only. The "attach to prompt" button that sat beside it was
|
|
1044
|
+
// removed: no host (claude.ai, ChatGPT, Claude Code, Kolbo Code) reliably
|
|
1045
|
+
// put the media into the composer, so it read as a dead upload button.
|
|
1046
|
+
return '<button class="k-dl" data-dl="' + esc(u) + '" title="Download" aria-label="Download">' + ICONS.download + '</button>';
|
|
1049
1047
|
}
|
|
1050
1048
|
function wireDlButtons(root) {
|
|
1051
1049
|
Array.prototype.forEach.call((root || document).querySelectorAll('.k-dl[data-dl]'), function (b) {
|
|
@@ -1054,12 +1052,6 @@ function wireDlButtons(root) {
|
|
|
1054
1052
|
window.kolbo.openLink(downloadUrl(b.getAttribute('data-dl')));
|
|
1055
1053
|
};
|
|
1056
1054
|
});
|
|
1057
|
-
Array.prototype.forEach.call((root || document).querySelectorAll('.k-attach[data-attach]'), function (b) {
|
|
1058
|
-
b.onclick = function (e) {
|
|
1059
|
-
e.stopPropagation();
|
|
1060
|
-
window.kolbo.attachMedia(b.getAttribute('data-attach'));
|
|
1061
|
-
};
|
|
1062
|
-
});
|
|
1063
1055
|
}
|
|
1064
1056
|
|
|
1065
1057
|
// CD scenes render as the SAME viewer+thumbnail carousel as image batches —
|