@yemi33/minions 0.1.278 → 0.1.280
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/command-center.js +18 -5
- package/dashboard/js/modal-qa.js +20 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -215,6 +215,15 @@ async function _ccDoSend(message, skipUserMsg) {
|
|
|
215
215
|
let streamedText = '';
|
|
216
216
|
let toolsUsed = [];
|
|
217
217
|
const 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>';
|
|
218
|
+
function _getThinkingPhase() {
|
|
219
|
+
var elapsed = Date.now() - ccStartTime;
|
|
220
|
+
var label = 'Thinking...';
|
|
221
|
+
for (var pi = phases.length - 1; pi >= 0; pi--) {
|
|
222
|
+
if (elapsed >= phases[pi][0]) { label = phases[pi][1]; break; }
|
|
223
|
+
}
|
|
224
|
+
var secs = Math.floor(elapsed / 1000);
|
|
225
|
+
return label + ' <span style="font-size:9px;color:var(--border)">' + secs + 's</span>';
|
|
226
|
+
}
|
|
218
227
|
function updateStreamDiv() {
|
|
219
228
|
var html = '';
|
|
220
229
|
if (toolsUsed.length > 0) {
|
|
@@ -227,13 +236,16 @@ async function _ccDoSend(message, skipUserMsg) {
|
|
|
227
236
|
if (streamedText) {
|
|
228
237
|
html += renderMd(streamedText);
|
|
229
238
|
}
|
|
230
|
-
html += '<div style="margin-top:' + (streamedText ? '6px' : '0') + '"><span style="color:var(--muted);font-size:11px">
|
|
239
|
+
html += '<div style="margin-top:' + (streamedText ? '6px' : '0') + '"><span style="color:var(--muted);font-size:11px">' + _getThinkingPhase() + dotPulse + '</span></div>';
|
|
231
240
|
streamDiv.innerHTML = html;
|
|
232
241
|
// Re-append queue indicators so they stay below the streaming content
|
|
233
242
|
if (_ccQueue.length > 0) _renderQueueIndicator();
|
|
234
243
|
if (msgs.scrollHeight - msgs.scrollTop - msgs.clientHeight < 150) msgs.scrollTop = msgs.scrollHeight;
|
|
235
244
|
}
|
|
236
245
|
|
|
246
|
+
// Periodically update thinking phase text + timer
|
|
247
|
+
const phaseTimer = setInterval(updateStreamDiv, 1000);
|
|
248
|
+
|
|
237
249
|
const reader = res.body.getReader();
|
|
238
250
|
const decoder = new TextDecoder();
|
|
239
251
|
let buf = '';
|
|
@@ -257,7 +269,7 @@ async function _ccDoSend(message, skipUserMsg) {
|
|
|
257
269
|
if (msgs.scrollHeight - msgs.scrollTop - msgs.clientHeight < 150) msgs.scrollTop = msgs.scrollHeight;
|
|
258
270
|
} else if (evt.type === 'done') {
|
|
259
271
|
// Replace streaming div with a proper ccAddMessage
|
|
260
|
-
streamDiv.remove();
|
|
272
|
+
clearInterval(phaseTimer); streamDiv.remove();
|
|
261
273
|
// placeholder was added with skipSave=true — nothing to pop
|
|
262
274
|
const ccElapsed = Math.round((Date.now() - ccStartTime) / 1000);
|
|
263
275
|
const rendered = renderMd(evt.text || streamedText || '');
|
|
@@ -267,7 +279,7 @@ async function _ccDoSend(message, skipUserMsg) {
|
|
|
267
279
|
for (const action of evt.actions) { await ccExecuteAction(action); }
|
|
268
280
|
}
|
|
269
281
|
} else if (evt.type === 'error') {
|
|
270
|
-
streamDiv.remove();
|
|
282
|
+
clearInterval(phaseTimer); streamDiv.remove();
|
|
271
283
|
// placeholder was skipSave — no pop needed
|
|
272
284
|
ccAddMessage('assistant', '<span style="color:var(--red)">' + escHtml(evt.error) + '</span>');
|
|
273
285
|
}
|
|
@@ -281,7 +293,7 @@ async function _ccDoSend(message, skipUserMsg) {
|
|
|
281
293
|
try {
|
|
282
294
|
const evt = JSON.parse(line.slice(6));
|
|
283
295
|
if (evt.type === 'done') {
|
|
284
|
-
streamDiv.remove();
|
|
296
|
+
clearInterval(phaseTimer); streamDiv.remove();
|
|
285
297
|
// placeholder was skipSave — no pop needed
|
|
286
298
|
const ccElapsed = Math.round((Date.now() - ccStartTime) / 1000);
|
|
287
299
|
const rendered = renderMd(evt.text || streamedText || '');
|
|
@@ -299,7 +311,7 @@ async function _ccDoSend(message, skipUserMsg) {
|
|
|
299
311
|
}
|
|
300
312
|
// If stream ended without a 'done' event, finalize with whatever we have
|
|
301
313
|
if (streamDiv.parentNode) {
|
|
302
|
-
streamDiv.remove();
|
|
314
|
+
clearInterval(phaseTimer); streamDiv.remove();
|
|
303
315
|
if (streamedText) {
|
|
304
316
|
const ccElapsed = Math.round((Date.now() - ccStartTime) / 1000);
|
|
305
317
|
ccAddMessage('assistant', renderMd(streamedText) + '<div style="font-size:9px;color:var(--muted);margin-top:6px;display:flex;justify-content:flex-end;padding-right:30px">' + ccElapsed + 's</div>');
|
|
@@ -314,6 +326,7 @@ async function _ccDoSend(message, skipUserMsg) {
|
|
|
314
326
|
} finally {
|
|
315
327
|
_ccSending = false;
|
|
316
328
|
_ccAbortController = null;
|
|
329
|
+
try { clearInterval(phaseTimer); } catch { /* may not be defined if error before reader */ }
|
|
317
330
|
try { localStorage.removeItem('cc-sending'); } catch {}
|
|
318
331
|
// Show notification badge on CC button if drawer is closed
|
|
319
332
|
if (!_ccOpen) showNotifBadge(document.getElementById('cc-toggle-btn'));
|
package/dashboard/js/modal-qa.js
CHANGED
|
@@ -6,8 +6,22 @@ let _modalFilePath = null; // file path for steering (null = read-only Q&A only)
|
|
|
6
6
|
function showModalQa() {
|
|
7
7
|
document.getElementById('modal-qa').style.display = '';
|
|
8
8
|
}
|
|
9
|
+
|
|
10
|
+
function _qaNotifySidebar(filePath) {
|
|
11
|
+
if (!filePath) return;
|
|
12
|
+
let page = '';
|
|
13
|
+
if (/^plans\//.test(filePath) || /^prd\//.test(filePath)) page = 'plans';
|
|
14
|
+
else if (/^knowledge\//.test(filePath) || /^notes/.test(filePath) || /^pinned/.test(filePath)) page = 'inbox';
|
|
15
|
+
else if (/^meetings\//.test(filePath)) page = 'inbox';
|
|
16
|
+
else return;
|
|
17
|
+
// Don't badge if user is already on that page
|
|
18
|
+
const currentPage = document.querySelector('.sidebar-link.active')?.getAttribute('data-page');
|
|
19
|
+
if (currentPage === page) return;
|
|
20
|
+
const link = document.querySelector('.sidebar-link[data-page="' + page + '"]');
|
|
21
|
+
if (link && !link.querySelector('.notif-badge')) showNotifBadge(link);
|
|
22
|
+
}
|
|
9
23
|
let _qaHistory = []; // multi-turn conversation history [{role:'user',text:''},{role:'assistant',text:''}]
|
|
10
|
-
let _qaProcessing = false; // true while waiting for
|
|
24
|
+
let _qaProcessing = false; // true while waiting for response
|
|
11
25
|
let _qaQueue = []; // queued messages while processing
|
|
12
26
|
let _qaSessionKey = ''; // key for current conversation (title or filePath)
|
|
13
27
|
const _qaSessions = new Map(); // persist conversations across modal open/close {key → {history, threadHtml}}
|
|
@@ -199,13 +213,16 @@ async function _processQaMessage(message, selection) {
|
|
|
199
213
|
const borderColor = data.edited ? 'var(--green)' : 'var(--blue)';
|
|
200
214
|
const suffix = data.edited ? '\n\n\u2713 Document saved.' : '';
|
|
201
215
|
const qaElapsed = Math.round((Date.now() - qaStartTime) / 1000);
|
|
202
|
-
const qaTimeLabel = '<div style="font-size:9px;color:var(--muted);margin-top:4px;text-align:right">' + qaElapsed + 's</div>';
|
|
216
|
+
const qaTimeLabel = '<div style="font-size:9px;color:var(--muted);margin-top:4px;text-align:right;padding-right:24px">' + qaElapsed + 's</div>';
|
|
203
217
|
thread.innerHTML += '<div class="modal-qa-a" style="border-left-color:' + borderColor + '">' + llmCopyBtn() + renderMd(data.answer + suffix) + qaTimeLabel + '</div>';
|
|
204
218
|
|
|
205
219
|
// Track conversation history
|
|
206
220
|
_qaHistory.push({ role: 'user', text: message });
|
|
207
221
|
_qaHistory.push({ role: 'assistant', text: data.answer });
|
|
208
222
|
|
|
223
|
+
// Notify sidebar page link
|
|
224
|
+
_qaNotifySidebar(capturedFilePath);
|
|
225
|
+
|
|
209
226
|
// Execute any CC actions (dispatch, note, etc.)
|
|
210
227
|
if (data.actions && data.actions.length > 0) {
|
|
211
228
|
for (const action of data.actions) { await ccExecuteAction(action); }
|
|
@@ -267,7 +284,7 @@ async function _processQaMessage(message, selection) {
|
|
|
267
284
|
filePath: sessionFilePath,
|
|
268
285
|
});
|
|
269
286
|
_saveQaSessions();
|
|
270
|
-
//
|
|
287
|
+
// Show notification badge on source card when modal was closed during processing
|
|
271
288
|
if (!modalIsOpen) {
|
|
272
289
|
const card = findCardForFile(sessionFilePath);
|
|
273
290
|
if (card) showNotifBadge(card);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.280",
|
|
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"
|