@yemi33/minions 0.1.750 → 0.1.752
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/CHANGELOG.md +3 -1
- package/dashboard/js/command-center.js +30 -22
- package/dashboard/styles.css +3 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.1.
|
|
3
|
+
## 0.1.752 (2026-04-09)
|
|
4
4
|
|
|
5
5
|
### Fixes
|
|
6
|
+
- CC messages go to originating tab, not whichever tab is visible
|
|
7
|
+
- tab title no longer covers close button
|
|
6
8
|
- replace stale _ccQueue/_ccAbortController references with per-tab state
|
|
7
9
|
|
|
8
10
|
## 0.1.749 (2026-04-09)
|
|
@@ -210,7 +210,7 @@ function ccRenderTabBar() {
|
|
|
210
210
|
var t = _ccTabs[i];
|
|
211
211
|
var isActive = t.id === _ccActiveTabId;
|
|
212
212
|
html += '<div class="cc-tab' + (isActive ? ' active' : '') + '" onclick="ccSwitchTab(\'' + t.id + '\')" title="' + escHtml(t.title) + '">';
|
|
213
|
-
html += escHtml(t.title);
|
|
213
|
+
html += '<span class="cc-tab-text">' + escHtml(t.title) + '</span>';
|
|
214
214
|
html += '<span class="cc-tab-close" onclick="event.stopPropagation();ccCloseTab(\'' + t.id + '\')">×</span>';
|
|
215
215
|
html += '</div>';
|
|
216
216
|
}
|
|
@@ -287,20 +287,25 @@ function ccUpdateSessionIndicator() {
|
|
|
287
287
|
}
|
|
288
288
|
}
|
|
289
289
|
|
|
290
|
-
function ccAddMessage(role, html, skipSave) {
|
|
291
|
-
var el = document.getElementById('cc-messages');
|
|
290
|
+
function ccAddMessage(role, html, skipSave, targetTabId) {
|
|
292
291
|
var isUser = role === 'user';
|
|
293
|
-
var div = document.createElement('div');
|
|
294
292
|
var isAssistant = !isUser;
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
293
|
+
var targetTab = targetTabId ? _ccTabs.find(function(t) { return t.id === targetTabId; }) : _ccActiveTab();
|
|
294
|
+
// Only render to DOM if this message is for the currently visible tab
|
|
295
|
+
var isVisible = !targetTabId || targetTabId === _ccActiveTabId;
|
|
296
|
+
if (isVisible) {
|
|
297
|
+
var el = document.getElementById('cc-messages');
|
|
298
|
+
var div = document.createElement('div');
|
|
299
|
+
div.className = isAssistant ? 'cc-msg-assistant' : '';
|
|
300
|
+
div.style.cssText = 'padding:8px 12px;border-radius:8px;font-size:12px;line-height:1.6;max-width:95%;' +
|
|
301
|
+
(isUser ? 'background:var(--blue);color:#fff;align-self:flex-end' : 'background:var(--surface2);color:var(--text);align-self:flex-start;border:1px solid var(--border);position:relative');
|
|
302
|
+
div.innerHTML = (isAssistant && !html.includes('color:var(--red)') && !html.includes('cc-queued-pill') ? llmCopyBtn() : '') + html;
|
|
303
|
+
var wasNearBottom = el.scrollHeight - el.scrollTop - el.clientHeight < 150;
|
|
304
|
+
el.appendChild(div);
|
|
305
|
+
if (wasNearBottom || isUser) requestAnimationFrame(function() { el.scrollTop = el.scrollHeight; });
|
|
306
|
+
}
|
|
302
307
|
if (!skipSave) {
|
|
303
|
-
var tab =
|
|
308
|
+
var tab = targetTab;
|
|
304
309
|
if (tab) {
|
|
305
310
|
tab.messages.push({ role: role, html: html });
|
|
306
311
|
// Auto-title from first user message
|
|
@@ -396,7 +401,10 @@ async function _ccDoSend(message, skipUserMsg) {
|
|
|
396
401
|
var _wasAborted = false;
|
|
397
402
|
try { localStorage.setItem('cc-sending', JSON.stringify({ sending: true, startedAt: Date.now() })); } catch {}
|
|
398
403
|
|
|
399
|
-
|
|
404
|
+
// Scoped helper — always targets the originating tab, even if user switches tabs
|
|
405
|
+
function addMsg(role, html, skipSave) { ccAddMessage(role, html, skipSave, activeTabId); }
|
|
406
|
+
|
|
407
|
+
if (!skipUserMsg) addMsg('user', escHtml(message));
|
|
400
408
|
|
|
401
409
|
// Remove queue indicator before processing (it'll be re-added if more queued)
|
|
402
410
|
var existingQueueEl = document.getElementById('cc-queue-indicator');
|
|
@@ -424,7 +432,7 @@ async function _ccDoSend(message, skipUserMsg) {
|
|
|
424
432
|
var activeTabId = _ccActiveTabId;
|
|
425
433
|
|
|
426
434
|
// Show thinking immediately — before fetch starts
|
|
427
|
-
|
|
435
|
+
addMsg('assistant', '<span style="color:var(--muted);font-size:11px">Thinking...</span>', true);
|
|
428
436
|
var msgs = document.getElementById('cc-messages');
|
|
429
437
|
var streamDiv = msgs.lastElementChild;
|
|
430
438
|
var dotPulse = '<span style="display:inline-flex;gap:3px;margin-left:6px;vertical-align:middle"><span style="width:4px;height:4px;background:var(--blue);border-radius:50%;animation:dotPulse 1.2s infinite"></span><span style="width:4px;height:4px;background:var(--blue);border-radius:50%;animation:dotPulse 1.2s infinite;animation-delay:0.2s"></span><span style="width:4px;height:4px;background:var(--blue);border-radius:50%;animation:dotPulse 1.2s infinite;animation-delay:0.4s"></span></span>';
|
|
@@ -471,7 +479,7 @@ async function _ccDoSend(message, skipUserMsg) {
|
|
|
471
479
|
if (!res.ok) {
|
|
472
480
|
clearInterval(phaseTimer); streamDiv.remove();
|
|
473
481
|
var errText = await res.text();
|
|
474
|
-
|
|
482
|
+
addMsg('assistant', '<span style="color:var(--red)">' + escHtml(errText || 'CC error') + '</span>' +
|
|
475
483
|
(errText.includes('busy') ? ' <button onclick="ccNewTab()" style="margin-top:4px;padding:3px 10px;background:var(--surface2);border:1px solid var(--border);border-radius:4px;color:var(--blue);cursor:pointer;font-size:10px">Reset CC</button>' : ''));
|
|
476
484
|
return;
|
|
477
485
|
}
|
|
@@ -504,7 +512,7 @@ async function _ccDoSend(message, skipUserMsg) {
|
|
|
504
512
|
// placeholder was added with skipSave=true — nothing to pop
|
|
505
513
|
var ccElapsed = Math.round((Date.now() - ccStartTime) / 1000);
|
|
506
514
|
var rendered = renderMd(evt.text || streamedText || '');
|
|
507
|
-
|
|
515
|
+
addMsg('assistant', rendered + '<div style="font-size:9px;color:var(--muted);margin-top:6px;display:flex;justify-content:flex-end;padding-right:30px">' + ccElapsed + 's</div>');
|
|
508
516
|
if (evt.sessionId !== undefined) {
|
|
509
517
|
var currentTab = _ccActiveTab();
|
|
510
518
|
if (currentTab) { currentTab.sessionId = evt.sessionId || null; }
|
|
@@ -516,7 +524,7 @@ async function _ccDoSend(message, skipUserMsg) {
|
|
|
516
524
|
} else if (evt.type === 'error') {
|
|
517
525
|
clearInterval(phaseTimer); streamDiv.remove();
|
|
518
526
|
// placeholder was skipSave — no pop needed
|
|
519
|
-
|
|
527
|
+
addMsg('assistant', '<span style="color:var(--red)">' + escHtml(evt.error) + '</span>');
|
|
520
528
|
}
|
|
521
529
|
} catch { /* incomplete JSON */ }
|
|
522
530
|
}
|
|
@@ -534,7 +542,7 @@ async function _ccDoSend(message, skipUserMsg) {
|
|
|
534
542
|
// placeholder was skipSave — no pop needed
|
|
535
543
|
var ccElapsed2 = Math.round((Date.now() - ccStartTime) / 1000);
|
|
536
544
|
var rendered2 = renderMd(revt.text || streamedText || '');
|
|
537
|
-
|
|
545
|
+
addMsg('assistant', rendered2 + '<div style="font-size:9px;color:var(--muted);margin-top:6px;display:flex;justify-content:flex-end;padding-right:30px">' + ccElapsed2 + 's</div>');
|
|
538
546
|
if (revt.sessionId !== undefined) {
|
|
539
547
|
var currentTab2 = _ccActiveTab();
|
|
540
548
|
if (currentTab2) { currentTab2.sessionId = revt.sessionId || null; }
|
|
@@ -555,7 +563,7 @@ async function _ccDoSend(message, skipUserMsg) {
|
|
|
555
563
|
clearInterval(phaseTimer); streamDiv.remove();
|
|
556
564
|
if (streamedText) {
|
|
557
565
|
var ccElapsed3 = Math.round((Date.now() - ccStartTime) / 1000);
|
|
558
|
-
|
|
566
|
+
addMsg('assistant', renderMd(streamedText) + '<div style="font-size:9px;color:var(--muted);margin-top:6px;display:flex;justify-content:flex-end;padding-right:30px">' + ccElapsed3 + 's</div>');
|
|
559
567
|
}
|
|
560
568
|
}
|
|
561
569
|
} catch (e) {
|
|
@@ -564,14 +572,14 @@ async function _ccDoSend(message, skipUserMsg) {
|
|
|
564
572
|
_wasAborted = true;
|
|
565
573
|
if (streamedText) {
|
|
566
574
|
var ccElapsed4 = Math.round((Date.now() - ccStartTime) / 1000);
|
|
567
|
-
|
|
575
|
+
addMsg('assistant', renderMd(streamedText) + '<div style="font-size:9px;color:var(--muted);margin-top:6px;display:flex;justify-content:flex-end;padding-right:30px">Stopped after ' + ccElapsed4 + 's</div>');
|
|
568
576
|
} else {
|
|
569
|
-
|
|
577
|
+
addMsg('assistant', '<span style="color:var(--red);font-size:11px">Stopped</span>');
|
|
570
578
|
}
|
|
571
579
|
} else {
|
|
572
580
|
var retryId = 'cc-retry-' + Date.now();
|
|
573
581
|
var isNetworkError = e.message === 'Failed to fetch' || e.message.includes('NetworkError');
|
|
574
|
-
|
|
582
|
+
addMsg('assistant', '<span style="color:var(--red)">Error: ' + escHtml(e.message) + '</span>' +
|
|
575
583
|
(isNetworkError ? '<div style="font-size:10px;color:var(--muted);margin-top:4px">Dashboard connection lost. Reload the page to reconnect.</div>' : '') +
|
|
576
584
|
'<button id="' + retryId + '" onclick="ccRetryLast()" style="margin-top:6px;padding:4px 12px;background:var(--surface2);border:1px solid var(--border);border-radius:4px;color:var(--blue);cursor:pointer;font-size:11px">Retry</button>' +
|
|
577
585
|
(isNetworkError ? ' <button onclick="location.reload()" style="margin-top:6px;padding:4px 12px;background:var(--orange);color:#fff;border:none;border-radius:4px;cursor:pointer;font-size:11px">Reload Page</button>' : '') +
|
package/dashboard/styles.css
CHANGED
|
@@ -621,9 +621,10 @@
|
|
|
621
621
|
@keyframes notifPulse { 0%,100% { opacity: 1; } 50% { opacity: 0.5; } }
|
|
622
622
|
|
|
623
623
|
/* Command Center tab bar */
|
|
624
|
-
.cc-tab { padding: 4px 10px; font-size: 10px; border: 1px solid var(--border); border-bottom: none; border-radius: 6px 6px 0 0; background: var(--surface2); color: var(--muted); cursor: pointer; white-space: nowrap; max-width: 140px;
|
|
624
|
+
.cc-tab { padding: 4px 10px; font-size: 10px; border: 1px solid var(--border); border-bottom: none; border-radius: 6px 6px 0 0; background: var(--surface2); color: var(--muted); cursor: pointer; white-space: nowrap; max-width: 140px; display: inline-flex; align-items: center; gap: 2px; flex-shrink: 0; margin-bottom: -1px; position: relative; }
|
|
625
|
+
.cc-tab-text { overflow: hidden; text-overflow: ellipsis; flex: 1; min-width: 0; }
|
|
625
626
|
.cc-tab.active { color: var(--text); background: var(--bg); border-color: var(--border); z-index: 1; font-weight: 600; }
|
|
626
|
-
.cc-tab-close { margin-left: 4px; opacity: 0; cursor: pointer; font-size: 12px; line-height: 1; }
|
|
627
|
+
.cc-tab-close { flex-shrink: 0; margin-left: 4px; opacity: 0; cursor: pointer; font-size: 12px; line-height: 1; }
|
|
627
628
|
.cc-tab:hover .cc-tab-close { opacity: 0.5; }
|
|
628
629
|
.cc-tab-close:hover { opacity: 1; color: var(--red); }
|
|
629
630
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.752",
|
|
4
4
|
"description": "Multi-agent AI dev team that runs from ~/.minions/ — five autonomous agents share a single engine, dashboard, and knowledge base",
|
|
5
5
|
"bin": {
|
|
6
6
|
"minions": "bin/minions.js"
|