@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 +8 -0
- package/dashboard/js/modal-qa.js +47 -17
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/dashboard/js/modal-qa.js
CHANGED
|
@@ -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
|
-
|
|
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="
|
|
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">●</span>
|
|
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">●</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
|
|
212
|
-
html += '<div style="display:flex;
|
|
213
|
-
'<
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
'</
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
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')
|
|
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
|
|
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.
|
|
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"
|