@yemi33/minions 0.1.958 → 0.1.960

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # Changelog
2
2
 
3
- ## 0.1.958 (2026-04-14)
3
+ ## 0.1.960 (2026-04-14)
4
4
 
5
5
  ### Features
6
6
  - surface in-flight tool calls in lastAction (#1064)
@@ -25,6 +25,7 @@
25
25
  - add missing branch_name to central dispatch vars (#967)
26
26
 
27
27
  ### Fixes
28
+ - fix CC queued message 'already processing' and thinking UX stacking
28
29
  - enforce --timeout 1 on all azureauth calls to prevent agent orphans (#1063)
29
30
  - cancel steering kill watcher on resume spawn (#1052) (#1062)
30
31
  - suppress warn for optional template variables (#1061)
@@ -44,9 +45,9 @@
44
45
  - show doc-chat badges on Notes and KB items (#1016)
45
46
  - steering kill on no-session re-queues dispatch instead of erroring (#1015)
46
47
  - inject cached ADO token into spawned agents (#998) (#1012)
47
- - qaAbort race + skip kill on completed doc-chat
48
48
 
49
49
  ### Other
50
+ - refactor(dashboard): extract _releaseCCTab helper and CC_LOCK_WAIT_MS constant
50
51
  - test(engine): add regression tests for autoFixConflicts flag and DEFAULTS alias
51
52
  - refactor(ado): simplify ado-status and extract build/review status helpers
52
53
  - refactor(ado): extract stripRefsHeads helper, deduplicate refs/heads/ stripping
@@ -547,8 +547,9 @@ async function _ccDoSend(message, skipUserMsg, forceTabId) {
547
547
  // 429 = server still releasing previous request (abort race) — retry silently up to 3 times
548
548
  if (res.status === 429 && (!activeTab._429retries || activeTab._429retries < 3)) {
549
549
  activeTab._429retries = (activeTab._429retries || 0) + 1;
550
+ _cleanupStreamDiv(); // remove current thinking div — prevents stacking on each retry
550
551
  await new Promise(function(r) { setTimeout(r, 1500); });
551
- return await _ccDoSend(message, true); // retry with skipUserMsg=true (already displayed)
552
+ return await _ccDoSend(message, true, forceTabId || activeTabId); // retry pass tabId so timer closures don't fight
552
553
  }
553
554
  activeTab._429retries = 0;
554
555
  _cleanupStreamDiv();
package/dashboard.js CHANGED
@@ -471,7 +471,10 @@ setInterval(() => {
471
471
  const CC_SESSION_MAX_TURNS = Infinity;
472
472
  let ccSession = { sessionId: null, createdAt: null, lastActiveAt: null, turnCount: 0 };
473
473
  const ccInFlightTabs = new Set(); // per-tab in-flight tracking for parallel CC requests
474
+ const ccInFlightAborts = new Map(); // tabId → abortFn — lets a new request kill the stale LLM
474
475
  const CC_INFLIGHT_TIMEOUT_MS = 2 * 60 * 1000; // 2 minutes — auto-release if request hangs
476
+ const CC_LOCK_WAIT_MS = 200; // grace period for previous handler's finally to release lock
477
+ function _releaseCCTab(tabId) { ccInFlightTabs.delete(tabId); ccInFlightAborts.delete(tabId); }
475
478
 
476
479
  // _ccPromptHash computed after CC_STATIC_SYSTEM_PROMPT is defined (see below)
477
480
 
@@ -3400,7 +3403,10 @@ What would you like to discuss or change? When you're happy, say "approve" and I
3400
3403
  // Per-tab concurrency guard
3401
3404
  const tabId = body.tabId || 'default';
3402
3405
  if (ccInFlightTabs.has(tabId)) {
3403
- return jsonReply(res, 429, { error: 'This tab is already processing — wait or open a new tab.' });
3406
+ await new Promise(r => setTimeout(r, CC_LOCK_WAIT_MS));
3407
+ if (ccInFlightTabs.has(tabId)) {
3408
+ return jsonReply(res, 429, { error: 'This tab is already processing — wait or open a new tab.' });
3409
+ }
3404
3410
  }
3405
3411
  ccInFlightTabs.add(tabId);
3406
3412
 
@@ -3447,9 +3453,9 @@ What would you like to discuss or change? When you're happy, say "approve" and I
3447
3453
  if (sessionReset) reply.sessionReset = true;
3448
3454
  return jsonReply(res, 200, reply);
3449
3455
  } finally {
3450
- ccInFlightTabs.delete(tabId);
3456
+ _releaseCCTab(tabId);
3451
3457
  }
3452
- } catch (e) { ccInFlightTabs.delete(tabId); return jsonReply(res, 500, { error: e.message }); }
3458
+ } catch (e) { _releaseCCTab(tabId); return jsonReply(res, 500, { error: e.message }); }
3453
3459
  }
3454
3460
 
3455
3461
  /** Build a lightweight input object for SSE tool events — keeps only the fields formatToolSummary needs, with truncated string values. */
@@ -3471,7 +3477,13 @@ What would you like to discuss or change? When you're happy, say "approve" and I
3471
3477
  if (!body.message) { res.statusCode = 400; res.end('message required'); return; }
3472
3478
  const tabId = body.tabId || 'default';
3473
3479
  if (ccInFlightTabs.has(tabId)) {
3474
- res.statusCode = 429; res.end('This tab is already processing'); return;
3480
+ // Previous request still in-flight — abort its LLM (handles keep-alive abort where close event didn't fire)
3481
+ const prevAbort = ccInFlightAborts.get(tabId);
3482
+ if (prevAbort) { prevAbort(); }
3483
+ await new Promise(r => setTimeout(r, CC_LOCK_WAIT_MS)); // let previous finally run and release the lock
3484
+ if (ccInFlightTabs.has(tabId)) {
3485
+ res.statusCode = 429; res.end('This tab is already processing'); return;
3486
+ }
3475
3487
  }
3476
3488
  ccInFlightTabs.add(tabId);
3477
3489
 
@@ -3480,7 +3492,7 @@ What would you like to discuss or change? When you're happy, say "approve" and I
3480
3492
  let _ccStreamEnded = false;
3481
3493
  // Kill LLM process immediately if client disconnects mid-stream
3482
3494
  req.on('close', () => {
3483
- ccInFlightTabs.delete(tabId);
3495
+ _releaseCCTab(tabId);
3484
3496
  if (!_ccStreamEnded && _ccStreamAbort) {
3485
3497
  console.log(`[CC-stream] Client disconnected for tab ${tabId} — aborting LLM`);
3486
3498
  _ccStreamAbort();
@@ -3523,6 +3535,7 @@ What would you like to discuss or change? When you're happy, say "approve" and I
3523
3535
  }
3524
3536
  });
3525
3537
  _ccStreamAbort = llmPromise.abort;
3538
+ ccInFlightAborts.set(tabId, _ccStreamAbort);
3526
3539
  const result = await llmPromise;
3527
3540
  trackUsage('command-center', result.usage);
3528
3541
 
@@ -3604,10 +3617,10 @@ What would you like to discuss or change? When you're happy, say "approve" and I
3604
3617
 
3605
3618
  _ccStreamEnded = true; res.end();
3606
3619
  } finally {
3607
- ccInFlightTabs.delete(tabId);
3620
+ _releaseCCTab(tabId);
3608
3621
  }
3609
3622
  } catch (e) {
3610
- ccInFlightTabs.delete(tabId);
3623
+ _releaseCCTab(tabId);
3611
3624
  try { res.write('data: ' + JSON.stringify({ type: 'error', error: e.message }) + '\n\n'); } catch {}
3612
3625
  _ccStreamEnded = true; try { res.end(); } catch {}
3613
3626
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.958",
3
+ "version": "0.1.960",
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"