@yemi33/minions 0.1.758 → 0.1.760
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 +1 -1
- package/dashboard.js +27 -35
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.1.
|
|
3
|
+
## 0.1.760 (2026-04-10)
|
|
4
4
|
|
|
5
5
|
### Features
|
|
6
6
|
- show branch strategy badge on PRD group header
|
|
7
7
|
|
|
8
8
|
### Fixes
|
|
9
|
+
- prevent completed SSE stream from aborting other tab's LLM process
|
|
10
|
+
- eliminate global ccSession corruption, clean up streaming state
|
|
9
11
|
- restore full streaming state (tools + partial text) on tab switch
|
|
10
12
|
- restored thinking UX matches original exactly (same bubble, layout)
|
|
11
13
|
- skip merged dependency branches instead of failing worktree setup
|
|
@@ -625,7 +625,7 @@ async function _ccDoSend(message, skipUserMsg) {
|
|
|
625
625
|
' <button onclick="ccNewTab()" style="margin-top:6px;padding:4px 12px;background:var(--surface2);border:1px solid var(--border);border-radius:4px;color:var(--muted);cursor:pointer;font-size:11px">New Session</button>');
|
|
626
626
|
}
|
|
627
627
|
} finally {
|
|
628
|
-
if (activeTab) { activeTab._sending = false; activeTab._abortController = null; }
|
|
628
|
+
if (activeTab) { activeTab._sending = false; activeTab._abortController = null; delete activeTab._streamedText; delete activeTab._toolsUsed; delete activeTab._sendStartedAt; }
|
|
629
629
|
_ccSending = (_ccTabs.some(function(t) { return t._sending; }));
|
|
630
630
|
try { clearInterval(phaseTimer); } catch { /* may not be defined if error before reader */ }
|
|
631
631
|
try { localStorage.removeItem('cc-sending'); } catch {}
|
package/dashboard.js
CHANGED
|
@@ -3325,20 +3325,21 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
3325
3325
|
|
|
3326
3326
|
res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive' });
|
|
3327
3327
|
let _ccStreamAbort = null;
|
|
3328
|
+
let _ccStreamEnded = false;
|
|
3328
3329
|
// Kill LLM process immediately if client disconnects mid-stream
|
|
3329
|
-
req.on('close', () => {
|
|
3330
|
+
req.on('close', () => {
|
|
3331
|
+
ccInFlightTabs.delete(tabId);
|
|
3332
|
+
if (!_ccStreamEnded && _ccStreamAbort) {
|
|
3333
|
+
console.log(`[CC-stream] Client disconnected for tab ${tabId} — aborting LLM`);
|
|
3334
|
+
_ccStreamAbort();
|
|
3335
|
+
}
|
|
3336
|
+
});
|
|
3330
3337
|
|
|
3331
3338
|
try {
|
|
3332
|
-
// Session management — per-tab: use sessionId from request
|
|
3339
|
+
// Session management — per-tab: use sessionId from request, don't mutate global ccSession
|
|
3333
3340
|
const tabSessionId = body.sessionId || null;
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
ccSession = { sessionId: tabSessionId, createdAt: ccSession.createdAt, lastActiveAt: Date.now(), turnCount: ccSession.turnCount || 0, _promptHash: _ccPromptHash };
|
|
3337
|
-
} else if (!ccSessionValid()) {
|
|
3338
|
-
ccSession = { sessionId: null, createdAt: null, lastActiveAt: null, turnCount: 0 };
|
|
3339
|
-
}
|
|
3340
|
-
const wasResume = !!tabSessionId || !!(ccSessionValid() && ccSession.sessionId);
|
|
3341
|
-
const sessionId = tabSessionId || (wasResume ? ccSession.sessionId : null);
|
|
3341
|
+
const wasResume = !!tabSessionId;
|
|
3342
|
+
const sessionId = tabSessionId || null;
|
|
3342
3343
|
const preamble = wasResume ? '' : buildCCStatePreamble();
|
|
3343
3344
|
const prompt = (preamble ? preamble + '\n\n---\n\n' : '') + body.message;
|
|
3344
3345
|
|
|
@@ -3367,42 +3368,33 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
3367
3368
|
const stderrTail = (result.stderr || '').trim().split('\n').filter(Boolean).slice(-3).join(' | ');
|
|
3368
3369
|
console.error(`[CC-stream] Failed: code=${result.code}, stderr=${(result.stderr || '').slice(0, 500)}, stdout_tail=${(result.raw || '').slice(-500)}`);
|
|
3369
3370
|
// If resuming a session failed, auto-reset so next attempt starts fresh
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
}
|
|
3376
|
-
|
|
3377
|
-
? 'Your session is still active — just send your message again to retry.'
|
|
3378
|
-
: 'Try clicking **New Session** and sending your message again.';
|
|
3379
|
-
}
|
|
3380
|
-
res.write('data: ' + JSON.stringify({ type: 'done', text: `I had trouble processing that ${debugInfo}. ${stderrTail ? 'Detail: ' + stderrTail : ''}\n\n${retryHint}`, actions: [], sessionId: ccSession.sessionId }) + '\n\n');
|
|
3381
|
-
res.end();
|
|
3371
|
+
const retryHint = wasResume && result.code !== 0
|
|
3372
|
+
? 'Session was reset — send your message again to start fresh.'
|
|
3373
|
+
: 'Send your message again to retry.';
|
|
3374
|
+
// Return null sessionId on resume failure so client clears the stale session
|
|
3375
|
+
const errorSessionId = (wasResume && result.code !== 0) ? null : tabSessionId;
|
|
3376
|
+
res.write('data: ' + JSON.stringify({ type: 'done', text: `I had trouble processing that ${debugInfo}. ${stderrTail ? 'Detail: ' + stderrTail : ''}\n\n${retryHint}`, actions: [], sessionId: errorSessionId }) + '\n\n');
|
|
3377
|
+
_ccStreamEnded = true; res.end();
|
|
3382
3378
|
return;
|
|
3383
3379
|
}
|
|
3384
3380
|
|
|
3385
3381
|
// Update session
|
|
3382
|
+
// Persist tab→session mapping (no global ccSession mutation)
|
|
3386
3383
|
const now = Date.now();
|
|
3387
|
-
|
|
3388
|
-
ccSession = { sessionId: result.sessionId, createdAt: ccSession.createdAt || now, lastActiveAt: now, turnCount: (ccSession.turnCount || 0) + 1, _promptHash: _ccPromptHash };
|
|
3389
|
-
safeWrite(path.join(ENGINE_DIR, 'cc-session.json'), ccSession);
|
|
3390
|
-
}
|
|
3391
|
-
|
|
3392
|
-
// Persist tab→session mapping if tabId provided
|
|
3384
|
+
const responseSessionId = result.sessionId || tabSessionId;
|
|
3393
3385
|
const tabId = body.tabId;
|
|
3394
|
-
if (tabId &&
|
|
3386
|
+
if (tabId && responseSessionId) {
|
|
3395
3387
|
try {
|
|
3396
3388
|
const sessions = shared.safeJsonArr(CC_SESSIONS_PATH);
|
|
3397
3389
|
const existing = sessions.find(s => s.id === tabId);
|
|
3398
3390
|
const preview = (body.message || '').slice(0, 80);
|
|
3399
3391
|
if (existing) {
|
|
3400
|
-
existing.sessionId =
|
|
3392
|
+
existing.sessionId = responseSessionId;
|
|
3401
3393
|
existing.lastActiveAt = new Date(now).toISOString();
|
|
3402
|
-
existing.turnCount =
|
|
3394
|
+
existing.turnCount = (existing.turnCount || 0) + 1;
|
|
3403
3395
|
existing.preview = preview;
|
|
3404
3396
|
} else {
|
|
3405
|
-
sessions.push({ id: tabId, title: (body.message || 'New chat').slice(0, 40), sessionId:
|
|
3397
|
+
sessions.push({ id: tabId, title: (body.message || 'New chat').slice(0, 40), sessionId: responseSessionId, createdAt: new Date(now).toISOString(), lastActiveAt: new Date(now).toISOString(), turnCount: 1, preview });
|
|
3406
3398
|
}
|
|
3407
3399
|
safeWrite(CC_SESSIONS_PATH, sessions);
|
|
3408
3400
|
} catch { /* non-critical */ }
|
|
@@ -3410,15 +3402,15 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
3410
3402
|
|
|
3411
3403
|
// Send final result with actions
|
|
3412
3404
|
const { text: displayText, actions } = parseCCActions(result.text);
|
|
3413
|
-
res.write('data: ' + JSON.stringify({ type: 'done', text: displayText, actions, sessionId:
|
|
3414
|
-
res.end();
|
|
3405
|
+
res.write('data: ' + JSON.stringify({ type: 'done', text: displayText, actions, sessionId: responseSessionId, newSession: !wasResume }) + '\n\n');
|
|
3406
|
+
_ccStreamEnded = true; res.end();
|
|
3415
3407
|
} finally {
|
|
3416
3408
|
ccInFlightTabs.delete(tabId);
|
|
3417
3409
|
}
|
|
3418
3410
|
} catch (e) {
|
|
3419
3411
|
ccInFlightTabs.delete(tabId);
|
|
3420
3412
|
try { res.write('data: ' + JSON.stringify({ type: 'error', error: e.message }) + '\n\n'); } catch {}
|
|
3421
|
-
try { res.end(); } catch {}
|
|
3413
|
+
_ccStreamEnded = true; try { res.end(); } catch {}
|
|
3422
3414
|
}
|
|
3423
3415
|
}
|
|
3424
3416
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.760",
|
|
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"
|