@yemi33/minions 0.1.754 → 0.1.756
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 +22 -4
- package/engine.js +18 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.1.
|
|
3
|
+
## 0.1.756 (2026-04-09)
|
|
4
4
|
|
|
5
5
|
### Features
|
|
6
6
|
- show branch strategy badge on PRD group header
|
|
7
7
|
|
|
8
8
|
### Fixes
|
|
9
|
+
- skip merged dependency branches instead of failing worktree setup
|
|
10
|
+
- restore same thinking UX when switching back to processing tab
|
|
9
11
|
- show thinking indicator when switching back to a processing tab
|
|
10
12
|
- CC messages go to originating tab, not whichever tab is visible
|
|
11
13
|
- tab title no longer covers close button
|
|
@@ -135,14 +135,31 @@ function ccSwitchTab(id) {
|
|
|
135
135
|
for (var i = 0; i < tab.messages.length; i++) {
|
|
136
136
|
ccAddMessage(tab.messages[i].role, tab.messages[i].html, true);
|
|
137
137
|
}
|
|
138
|
-
// If this tab is still processing, show
|
|
138
|
+
// If this tab is still processing, show the same thinking UX as during send
|
|
139
139
|
if (tab._sending) {
|
|
140
|
+
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>';
|
|
141
|
+
var elapsed = tab._sendStartedAt ? Math.floor((Date.now() - tab._sendStartedAt) / 1000) : 0;
|
|
142
|
+
var phases = [[0,'Thinking...'],[3000,'Reading minions context...'],[8000,'Analyzing...'],[15000,'Using tools to dig deeper...'],[30000,'Still working (multi-turn)...'],[60000,'Deep research in progress...']];
|
|
143
|
+
var elapsedMs = elapsed * 1000;
|
|
144
|
+
var phaseText = 'Thinking...';
|
|
145
|
+
for (var pi = phases.length - 1; pi >= 0; pi--) { if (elapsedMs >= phases[pi][0]) { phaseText = phases[pi][1]; break; } }
|
|
140
146
|
var thinking = document.createElement('div');
|
|
141
|
-
thinking.
|
|
142
|
-
thinking.
|
|
143
|
-
|
|
147
|
+
thinking.id = 'cc-restore-thinking';
|
|
148
|
+
thinking.style.cssText = 'padding:8px 12px;border-radius:8px;font-size:11px;color:var(--muted);align-self:flex-start;background:var(--surface2);border:1px solid var(--border);position:relative;max-width:95%';
|
|
149
|
+
thinking.innerHTML = '<div>' + dotPulse + ' <span id="cc-restore-phase">' + phaseText + '</span> <span id="cc-restore-time" style="font-size:10px;color:var(--border)">' + elapsed + 's</span>' +
|
|
150
|
+
' <button onclick="ccAbort()" style="font-size:9px;padding:2px 8px;background:var(--surface2);border:1px solid var(--border);border-radius:4px;color:var(--red);cursor:pointer;margin-left:6px">Stop</button></div>';
|
|
144
151
|
el.appendChild(thinking);
|
|
145
152
|
el.scrollTop = el.scrollHeight;
|
|
153
|
+
// Live update timer and phase
|
|
154
|
+
var restoreStart = tab._sendStartedAt || Date.now();
|
|
155
|
+
var restoreInterval = setInterval(function() {
|
|
156
|
+
var phaseEl = document.getElementById('cc-restore-phase');
|
|
157
|
+
var timeEl = document.getElementById('cc-restore-time');
|
|
158
|
+
if (!phaseEl || !timeEl || !tab._sending) { clearInterval(restoreInterval); var re = document.getElementById('cc-restore-thinking'); if (re) re.remove(); return; }
|
|
159
|
+
var ms = Date.now() - restoreStart;
|
|
160
|
+
timeEl.textContent = Math.floor(ms / 1000) + 's';
|
|
161
|
+
for (var p = phases.length - 1; p >= 0; p--) { if (ms >= phases[p][0]) { phaseEl.textContent = phases[p][1]; break; } }
|
|
162
|
+
}, 1000);
|
|
146
163
|
}
|
|
147
164
|
ccRenderTabBar();
|
|
148
165
|
ccUpdateSessionIndicator();
|
|
@@ -405,6 +422,7 @@ async function _ccDoSend(message, skipUserMsg) {
|
|
|
405
422
|
var activeTabId = _ccActiveTabId;
|
|
406
423
|
if (!activeTab) return;
|
|
407
424
|
activeTab._sending = true;
|
|
425
|
+
activeTab._sendStartedAt = Date.now();
|
|
408
426
|
activeTab._abortController = new AbortController();
|
|
409
427
|
_ccSending = true; // UI indicator
|
|
410
428
|
var _wasAborted = false;
|
package/engine.js
CHANGED
|
@@ -454,7 +454,13 @@ async function spawnAgent(dispatchItem, config) {
|
|
|
454
454
|
// Fetch all dependency branches in parallel (git fetches are independent)
|
|
455
455
|
const fetchable = depBranches.filter(d => !_failedRefCache.has(d.branch));
|
|
456
456
|
const unfetchable = depBranches.filter(d => _failedRefCache.has(d.branch));
|
|
457
|
-
|
|
457
|
+
const allPrsForDeps = unfetchable.length > 0 ? shared.getProjects(config).reduce((acc, p) => acc.concat(safeJson(shared.projectPrPath(p)) || []), []) : [];
|
|
458
|
+
for (const { branch: depBranch, prId } of unfetchable) {
|
|
459
|
+
const pr = allPrsForDeps.find(p => p.id === prId);
|
|
460
|
+
if (pr && (pr.status === 'merged' || pr.status === 'closed')) {
|
|
461
|
+
log('info', `Dependency ${depBranch} (${prId}) already merged — skipping, changes already in main`);
|
|
462
|
+
continue;
|
|
463
|
+
}
|
|
458
464
|
log('warn', `Skipping dependency ${depBranch} — already failed to fetch this tick`);
|
|
459
465
|
depMergeFailed = true;
|
|
460
466
|
}
|
|
@@ -463,17 +469,26 @@ async function spawnAgent(dispatchItem, config) {
|
|
|
463
469
|
execAsync(`git fetch origin "${depBranch}"`, { ..._gitOpts, cwd: rootDir }).then(() => depBranch)
|
|
464
470
|
)
|
|
465
471
|
);
|
|
472
|
+
const hasFetchFailures = fetchResults.some(r => r.status === 'rejected');
|
|
473
|
+
const allPrsForFetch = hasFetchFailures ? shared.getProjects(config).reduce((acc, p) => acc.concat(safeJson(shared.projectPrPath(p)) || []), []) : [];
|
|
466
474
|
for (let i = 0; i < fetchResults.length; i++) {
|
|
467
475
|
if (fetchResults[i].status === 'rejected') {
|
|
468
476
|
const failedBranch = fetchable[i].branch;
|
|
477
|
+
const failedPrId = fetchable[i].prId;
|
|
478
|
+
const pr = allPrsForFetch.find(p => p.id === failedPrId);
|
|
479
|
+
if (pr && (pr.status === 'merged' || pr.status === 'closed')) {
|
|
480
|
+
log('info', `Dependency ${failedBranch} (${failedPrId}) already merged — skipping, changes already in main`);
|
|
481
|
+
continue;
|
|
482
|
+
}
|
|
469
483
|
_failedRefCache.add(failedBranch);
|
|
470
484
|
log('warn', `Failed to fetch dependency ${failedBranch}: ${fetchResults[i].reason?.message}`);
|
|
471
485
|
depMergeFailed = true;
|
|
472
486
|
}
|
|
473
487
|
}
|
|
474
|
-
// Merge fetched branches sequentially (merges modify the worktree)
|
|
488
|
+
// Merge successfully-fetched branches sequentially (merges modify the worktree)
|
|
489
|
+
const fetched = fetchable.filter((_, i) => fetchResults[i].status === 'fulfilled');
|
|
475
490
|
if (!depMergeFailed) {
|
|
476
|
-
for (const { branch: depBranch, prId } of
|
|
491
|
+
for (const { branch: depBranch, prId } of fetched) {
|
|
477
492
|
try {
|
|
478
493
|
await execAsync(`git merge "origin/${depBranch}" --no-edit`, { ..._gitOpts, cwd: worktreePath });
|
|
479
494
|
log('info', `Merged dependency branch ${depBranch} (${prId}) into worktree ${branchName}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.756",
|
|
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"
|