@kolbo/mcp 1.77.0 → 1.77.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.77.0",
3
+ "version": "1.77.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/theme.js CHANGED
@@ -144,20 +144,31 @@ body {
144
144
  .k-skel.portrait { aspect-ratio: 3 / 4; }
145
145
  .k-skel::after {
146
146
  content: ''; position: absolute; inset: 0;
147
+ /* The shimmer covers the WHOLE cell and outlives the skeleton — .k-skel.done
148
+ only clears its paint, not its box. A pseudo-element hit-tests as its
149
+ originating element, so every click on a finished cell landed on the cell
150
+ instead of the media inside it: image cells still worked (their handler is
151
+ ON the cell), but a <video>'s native controls never saw a single event —
152
+ play, scrub, volume and fullscreen were all dead. It is decoration; it must
153
+ never take a click. */
154
+ pointer-events: none;
147
155
  background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.06) 40%, rgba(255,255,255,0.10) 50%, rgba(255,255,255,0.06) 60%, transparent 100%);
148
156
  background-size: 200% 100%;
149
157
  animation: k-sweep 1.6s ease-in-out infinite;
150
158
  }
151
159
  @keyframes k-sweep { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
152
160
  /* Batch grid: per-cell prompt caption + a cell that already finished */
153
- .k-skel-cap { position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
161
+ /* bottom: 0 puts this exactly where a <video> draws its control bar, so it has
162
+ to be click-through too — the caption is a label, not a target. The full text
163
+ stays reachable: the title tooltip moved onto the cell. */
164
+ .k-skel-cap { position: absolute; left: 0; right: 0; bottom: 0; z-index: 2; pointer-events: none;
154
165
  padding: 12px 8px 6px; font-size: 10.5px; color: #fff;
155
166
  background: linear-gradient(transparent, rgba(0, 0, 0, 0.65));
156
167
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
157
168
  .k-skel.done::after { animation: none; background: none; }
158
169
  .k-cell-fill { width: 100%; height: 100%; object-fit: contain; display: block; background: #000; }
159
170
  .k-gen-badge {
160
- position: absolute; top: 10px; left: 10px; z-index: 2;
171
+ position: absolute; top: 10px; left: 10px; z-index: 2; pointer-events: none;
161
172
  display: inline-flex; align-items: center; gap: 6px;
162
173
  padding: 4px 10px; border-radius: 999px;
163
174
  background: rgba(0, 0, 0, 0.65); /* no backdrop-filter: nested blur over the
@@ -586,8 +586,12 @@ function fillBatchCell(sc, i, g) {
586
586
  cell.classList.add('done');
587
587
  var cap = (sc.prompts && sc.prompts[i])
588
588
  ? '<span class="k-skel-cap" title="' + esc(sc.prompts[i]) + '">' + esc(sc.prompts[i]) + '</span>' : '';
589
+ if (sc.prompts && sc.prompts[i]) cell.title = sc.prompts[i];
590
+ // The controls attribute is not optional here: this cell is a FINISHED result
591
+ // the user is meant to watch, and without it the tile was a muted poster with
592
+ // no way to play, seek or unmute until the whole batch finished and repainted.
589
593
  cell.innerHTML = (sc.kind === 'video'
590
- ? '<video class="k-cell-fill" src="' + esc(u) + '"' + (r.thumbnail_url ? ' poster="' + esc(r.thumbnail_url) + '"' : '') + ' muted playsinline preload="metadata"></video>'
594
+ ? '<video class="k-cell-fill" src="' + esc(u) + '"' + (r.thumbnail_url ? ' poster="' + esc(r.thumbnail_url) + '"' : '') + ' controls playsinline preload="metadata"></video>'
591
595
  : '<img class="k-cell-fill" src="' + esc(u) + '" alt="">') + cap;
592
596
  window.kolbo.notifySize();
593
597
  }
@@ -767,7 +771,8 @@ function renderBatchGrid(sc) {
767
771
  var shape = items[0].type === 'video' ? 'video' : 'square';
768
772
  el('stage').innerHTML = '<div class="k-gen-grid n' + Math.min(items.length, 4) + '">' +
769
773
  items.map(function (it, i) {
770
- return '<div class="k-skel done ' + shape + '" data-focus="' + i + '">' +
774
+ return '<div class="k-skel done ' + shape + '" data-focus="' + i + '"' +
775
+ (it.label ? ' title="' + esc(it.label) + '"' : '') + '>' +
771
776
  (it.type === 'video'
772
777
  ? '<video class="k-cell-fill" src="' + esc(it.url) + '" controls playsinline preload="metadata"></video>'
773
778
  : '<img class="k-cell-fill" src="' + esc(it.url) + '" alt="" loading="lazy" style="cursor:zoom-in">') +
@@ -803,7 +808,8 @@ function renderStatusGrid(sc) {
803
808
  // file — the tool only knows a url came back, not what kind it is.
804
809
  it.kind = refKind(it.url, 'image');
805
810
  var shape = it.kind === 'video' ? 'video' : 'square';
806
- return '<div class="k-skel done ' + shape + '" data-focus="' + i + '">' +
811
+ return '<div class="k-skel done ' + shape + '" data-focus="' + i + '"' +
812
+ (it.title ? ' title="' + esc(it.title) + '"' : '') + '>' +
807
813
  (it.kind === 'video'
808
814
  ? '<video class="k-cell-fill" src="' + esc(it.url) + '" controls playsinline preload="metadata"></video>'
809
815
  : it.kind === 'audio'