@kolbo/mcp 1.110.0 → 1.110.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kolbo/mcp",
3
- "version": "1.110.0",
3
+ "version": "1.110.1",
4
4
  "description": "Kolbo AI MCP Server - Generate images, videos, music, speech, and sound effects from Claude Code",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/apps/html.js CHANGED
@@ -236,9 +236,13 @@ function showPeekItem(time) {
236
236
  var it = peekList[peekIndex];
237
237
  var img = el('peek-img');
238
238
  var vid = el('peek-video');
239
+ var oldNote = el('peek-stage') && el('peek-stage').querySelector('.k-vnote');
240
+ if (oldNote) oldNote.parentNode.removeChild(oldNote);
241
+ vid.removeAttribute('data-unplayable');
239
242
  if (it.kind === 'video') {
240
243
  img.removeAttribute('src');
241
244
  vid.setAttribute('src', it.url);
245
+ guardPlayback(vid);
242
246
  if (time) vid.addEventListener('loadedmetadata', function () { try { vid.currentTime = time; } catch (e) {} }, { once: true });
243
247
  var p = vid.play && vid.play();
244
248
  if (p && p.catch) p.catch(function () {});
@@ -363,6 +367,42 @@ function wireVideoExpand(root) {
363
367
  b.addEventListener('keydown', mark);
364
368
  v.addEventListener('dblclick', function (e) { e.preventDefault(); mark(); b.click(); });
365
369
  v.parentNode.insertBefore(b, v.nextSibling);
370
+ guardPlayback(v);
371
+ });
372
+ }
373
+ // Some outputs cannot be decoded by a browser: 10/12-bit HEVC (Bytedance
374
+ // Upscaler Pro, Seedance 1080p masters) either errors or plays sound over a
375
+ // black frame. Detect both and replace the dead player with a clear note and
376
+ // a Download button instead of leaving the user staring at nothing.
377
+ function guardPlayback(v) {
378
+ if (!v || v.getAttribute('data-guard')) return;
379
+ v.setAttribute('data-guard', '1');
380
+ function fail() {
381
+ if (v.getAttribute('data-unplayable') || !v.parentNode) return;
382
+ v.setAttribute('data-unplayable', '1');
383
+ try { v.pause(); } catch (e) {}
384
+ var url = v.currentSrc || v.getAttribute('src');
385
+ var note = document.createElement('div');
386
+ note.className = 'k-vnote';
387
+ note.innerHTML = '<div class="k-vnote-t"></div><div class="k-vnote-s"></div><button type="button" class="k-btn primary"></button>';
388
+ note.querySelector('.k-vnote-t').textContent = "This video can't play in the browser";
389
+ note.querySelector('.k-vnote-s').textContent = 'It uses a high-quality format (HEVC, 10/12-bit) most browsers do not decode. Download it and open it in a video player.';
390
+ var dl = note.querySelector('button');
391
+ dl.innerHTML = ICONS.download + ' Download video';
392
+ dl.onclick = function (e) { e.stopPropagation(); window.kolbo.openLink(downloadUrl(url)); };
393
+ v.parentNode.insertBefore(note, v.nextSibling);
394
+ if (window.kolbo && window.kolbo.notifySize) window.kolbo.notifySize();
395
+ }
396
+ v.addEventListener('error', function () {
397
+ var code = v.error && v.error.code;
398
+ // 3 = decode failure, 4 = format not supported. Network errors (2) are not a format problem.
399
+ if (code === 3 || code === 4) fail();
400
+ });
401
+ // Sound with no picture: time advances but no video frame was ever decoded.
402
+ v.addEventListener('timeupdate', function () {
403
+ if (v.currentTime < 1.2 || v.getAttribute('data-unplayable')) return;
404
+ var q = v.getVideoPlaybackQuality ? v.getVideoPlaybackQuality() : null;
405
+ if ((q && q.totalVideoFrames === 0) || (v.readyState >= 2 && v.videoWidth === 0)) fail();
366
406
  });
367
407
  }
368
408
  if (window.MutationObserver) {
package/src/apps/theme.js CHANGED
@@ -222,6 +222,17 @@ html.k-peek-fs .k-card { min-height: 0; backdrop-filter: none; -webkit-backdrop-
222
222
  display: inline-flex; align-items: center; justify-content: center;
223
223
  }
224
224
  .k-vexpand:hover { background: var(--brand); border-color: var(--brand); }
225
+ /* Undecodable video (10/12-bit HEVC): the dead player is replaced by a note. */
226
+ video[data-unplayable] { display: none !important; }
227
+ video[data-unplayable] ~ .k-vexpand { display: none; }
228
+ .k-vnote { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
229
+ width: 100%; min-height: 160px; padding: 18px 16px; border-radius: 10px; text-align: center;
230
+ background: rgba(255, 255, 255, 0.05); }
231
+ .k-vnote-t { font-size: 13px; font-weight: 600; color: var(--text); }
232
+ .k-vnote-s { font-size: 12px; color: var(--text-muted); max-width: 360px; margin-bottom: 4px; }
233
+ .k-peek-stage .k-vnote { max-width: 440px; color: #fff; }
234
+ .k-peek-stage .k-vnote-t { color: #fff; }
235
+ .k-peek-stage .k-vnote-s { color: rgba(255, 255, 255, 0.7); }
225
236
  /* Recent Chromium still draws the native button despite controlslist. */
226
237
  video::-webkit-media-controls-fullscreen-button { display: none !important; }
227
238
  /* ---- Plans / upgrade card ---- */