@yemi33/minions 0.1.1582 → 0.1.1584

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,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.1584 (2026-04-28)
4
+
5
+ ### Fixes
6
+ - stack chain-of-thought above progress block (was side-by-side)
7
+
8
+ ### Other
9
+ - Keep doc chat collapsed while streaming
10
+
3
11
  ## 0.1.1582 (2026-04-28)
4
12
 
5
13
  ### Fixes
@@ -27,6 +27,7 @@ let _qaProcessing = false; // true while waiting for response
27
27
  let _qaAbortController = null;
28
28
  let _qaQueue = []; // queued messages while processing
29
29
  const QA_QUEUE_CAP = 10; // max queued messages
30
+ const QA_STREAM_STALL_MS = 90000; // abort doc-chat if heartbeats continue but no chunk/tool progress arrives
30
31
  let _qaSessionKey = ''; // key for current conversation (title or filePath)
31
32
 
32
33
  function _renderQaUserMessage(thread, message, selection) {
@@ -198,28 +199,29 @@ function _qaBuildAssistantHtml(text, opts) {
198
199
 
199
200
  function _qaBuildLiveProgressHtml(loadingId, label, elapsedSeconds, streamedText, toolsUsed, queueCount) {
200
201
  const qaQueueBadge = queueCount > 0 ? ' <span style="font-size:9px;color:var(--muted);background:var(--surface);padding:1px 5px;border-radius:8px;border:1px solid var(--border)">+' + queueCount + ' queued</span>' : '';
201
- let html = '';
202
+ // Wrap in a column-flex container so chain-of-thought (tool calls) stack
203
+ // vertically on top and the progress block sits at the bottom. Overrides the
204
+ // parent .modal-qa-loading row-flex (which is right for the simple
205
+ // "Thinking..." initial state but wrong once tools/streamed text appear).
206
+ let html = '<div style="display:flex;flex-direction:column;align-items:stretch;gap:6px;width:100%">';
202
207
  if (toolsUsed && toolsUsed.length > 0) {
203
- html += '<div style="margin-bottom:6px">';
208
+ html += '<div style="display:flex;flex-direction:column;gap:2px">';
204
209
  toolsUsed.forEach(function(t) {
205
210
  const name = typeof t === 'string' ? t : t.name;
206
211
  const input = typeof t === 'string' ? {} : (t.input || {});
207
- html += '<div style="color:var(--muted);font-size:10px;font-family:monospace"><span style="flex-shrink:0">&#9679;</span> ' + formatToolSummary(name, input) + '</div>';
212
+ html += '<div style="color:var(--muted);font-size:10px;font-family:monospace;display:flex;align-items:flex-start;gap:6px"><span style="flex-shrink:0">&#9679;</span><span style="word-break:break-all">' + formatToolSummary(name, input) + '</span></div>';
208
213
  });
209
214
  html += '</div>';
210
215
  }
211
- if (streamedText) html += '<div style="margin-bottom:6px">' + renderMd(streamedText) + '</div>';
212
- html += '<div style="display:flex;flex-direction:column;align-items:flex-start;gap:6px">' +
213
- '<div style="display:flex;align-items:center;gap:6px;flex-wrap:wrap">' +
214
- '<span class="dot-pulse"><span></span><span></span><span></span></span> ' +
215
- '<span id="' + loadingId + '-text">' + escHtml(label) + '</span>' +
216
- '</div>' +
217
- '<div style="display:flex;align-items:center;gap:6px;flex-wrap:wrap">' +
218
- '<span id="' + loadingId + '-time" style="font-size:10px;color:var(--muted)">' + elapsedSeconds + 's</span>' +
219
- '<button onclick="qaAbort()" style="font-size:9px;padding:2px 8px;background:var(--surface2);border:1px solid var(--border);border-radius:4px;color:var(--red);cursor:pointer">Stop</button>' +
220
- qaQueueBadge +
221
- '</div>' +
222
- '</div>';
216
+ if (streamedText) html += '<div>' + renderMd(streamedText) + '</div>';
217
+ html += '<div style="display:flex;align-items:center;gap:8px;flex-wrap:wrap">' +
218
+ '<span class="dot-pulse"><span></span><span></span><span></span></span>' +
219
+ '<span id="' + loadingId + '-text">' + escHtml(label) + '</span>' +
220
+ '<span id="' + loadingId + '-time" style="font-size:10px;color:var(--muted)">' + elapsedSeconds + 's</span>' +
221
+ '<button onclick="qaAbort()" style="font-size:9px;padding:2px 8px;background:var(--surface2);border:1px solid var(--border);border-radius:4px;color:var(--red);cursor:pointer">Stop</button>' +
222
+ qaQueueBadge +
223
+ '</div>';
224
+ html += '</div>';
223
225
  return html;
224
226
  }
225
227
 
@@ -430,6 +432,21 @@ async function _processQaMessage(message, selection, opts) {
430
432
  : [[0,'Thinking...'],[3000,'Reading document...'],[8000,'Analyzing...'],[20000,'Still working...'],[60000,'Taking a while...']];
431
433
  let streamedText = '';
432
434
  let toolsUsed = [];
435
+ let _qaStreamStalled = false;
436
+ let _qaStallTimer = null;
437
+ function _clearQaStreamWatchdog() {
438
+ if (_qaStallTimer) {
439
+ clearTimeout(_qaStallTimer);
440
+ _qaStallTimer = null;
441
+ }
442
+ }
443
+ function _resetQaStreamWatchdog() {
444
+ _clearQaStreamWatchdog();
445
+ _qaStallTimer = setTimeout(() => {
446
+ _qaStreamStalled = true;
447
+ try { abortController.abort(); } catch {}
448
+ }, QA_STREAM_STALL_MS);
449
+ }
433
450
  function _qaProgressLabel(elapsed) {
434
451
  let label = qaPhases[0][1];
435
452
  for (let i = qaPhases.length - 1; i >= 0; i--) {
@@ -468,6 +485,7 @@ async function _processQaMessage(message, selection, opts) {
468
485
  _qaRenderProgress(false);
469
486
  }, 500);
470
487
  _qaRenderProgress(false);
488
+ _resetQaStreamWatchdog();
471
489
 
472
490
  try {
473
491
  const res = await fetch('/api/doc-chat/stream', {
@@ -504,11 +522,13 @@ async function _processQaMessage(message, selection, opts) {
504
522
  if (!evt || !evt.type) return;
505
523
  if (evt.type === 'heartbeat') return;
506
524
  if (evt.type === 'chunk') {
525
+ _resetQaStreamWatchdog();
507
526
  streamedText = evt.text || '';
508
527
  _qaRenderProgress(true);
509
528
  return;
510
529
  }
511
530
  if (evt.type === 'tool') {
531
+ _resetQaStreamWatchdog();
512
532
  toolsUsed.push({ name: evt.name, input: evt.input || {} });
513
533
  _qaRenderProgress(true);
514
534
  return;
@@ -516,6 +536,7 @@ async function _processQaMessage(message, selection, opts) {
516
536
  if (evt.type === 'done') {
517
537
  terminalEventSeen = true;
518
538
  clearInterval(qaTimer);
539
+ _clearQaStreamWatchdog();
519
540
  const qaElapsed = Math.round((Date.now() - qaStartTime) / 1000);
520
541
  const borderColor = evt.edited ? 'var(--green)' : 'var(--blue)';
521
542
  const suffix = evt.edited ? '\n\n\u2713 Document saved.' : '';
@@ -562,7 +583,10 @@ async function _processQaMessage(message, selection, opts) {
562
583
  });
563
584
  return;
564
585
  }
565
- if (evt.type === 'error') throw new Error(evt.error || 'Failed');
586
+ if (evt.type === 'error') {
587
+ _clearQaStreamWatchdog();
588
+ throw new Error(evt.error || 'Failed');
589
+ }
566
590
  }
567
591
 
568
592
  while (true) {
@@ -588,8 +612,14 @@ async function _processQaMessage(message, selection, opts) {
588
612
  if (!terminalEventSeen) throw new Error('The response stream ended before completion.');
589
613
  } catch (e) {
590
614
  clearInterval(qaTimer);
615
+ _clearQaStreamWatchdog();
591
616
  const qaElapsedExc = Math.round((Date.now() - qaStartTime) / 1000);
592
- const messageHtml = e.name === 'AbortError'
617
+ const stallMessage = 'Doc chat stalled with no tool or text progress for 90s.';
618
+ const messageHtml = _qaStreamStalled
619
+ ? (streamedText
620
+ ? _qaBuildAssistantHtml(streamedText + '\n\nError: ' + stallMessage, { borderColor: 'var(--red)', elapsed: qaElapsedExc })
621
+ : _qaBuildAssistantHtml('Error: ' + stallMessage, { color: 'var(--red)', isError: true, elapsed: qaElapsedExc }))
622
+ : e.name === 'AbortError'
593
623
  ? (streamedText
594
624
  ? _qaBuildAssistantHtml(streamedText + '\n\n_Stopped._', { borderColor: 'var(--muted)', elapsed: qaElapsedExc })
595
625
  : _qaBuildAssistantHtml('Stopped', { color: 'var(--muted)', isError: true, elapsed: qaElapsedExc }))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.1582",
3
+ "version": "0.1.1584",
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"