@yemi33/minions 0.1.367 → 0.1.369
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 +10 -0
- package/dashboard/js/command-center.js +25 -77
- package/dashboard/js/detail-panel.js +5 -3
- package/dashboard/js/modal.js +3 -1
- package/dashboard/js/render-kb.js +1 -1
- package/dashboard/js/render-plans.js +5 -1
- package/dashboard/js/render-prd.js +8 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.369 (2026-04-06)
|
|
4
|
+
|
|
5
|
+
### Fixes
|
|
6
|
+
- copy button preserves markdown formatting
|
|
7
|
+
|
|
8
|
+
## 0.1.368 (2026-04-06)
|
|
9
|
+
|
|
10
|
+
### Fixes
|
|
11
|
+
- dashboard audit pass 2 — CC error handling, charter edits, archived PRDs (#214)
|
|
12
|
+
|
|
3
13
|
## 0.1.367 (2026-04-06)
|
|
4
14
|
|
|
5
15
|
### Fixes
|
|
@@ -348,6 +348,12 @@ function ccRetryLast() {
|
|
|
348
348
|
_ccDoSend(text.trim());
|
|
349
349
|
}
|
|
350
350
|
|
|
351
|
+
async function _ccFetch(url, body) {
|
|
352
|
+
const res = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) });
|
|
353
|
+
if (!res.ok) { const d = await res.json().catch(() => ({})); throw new Error(d.error || 'Request failed (' + res.status + ')'); }
|
|
354
|
+
return res;
|
|
355
|
+
}
|
|
356
|
+
|
|
351
357
|
async function ccExecuteAction(action) {
|
|
352
358
|
const msgs = document.getElementById('cc-messages');
|
|
353
359
|
const status = document.createElement('div');
|
|
@@ -356,13 +362,10 @@ async function ccExecuteAction(action) {
|
|
|
356
362
|
try {
|
|
357
363
|
switch (action.type) {
|
|
358
364
|
case 'dispatch': {
|
|
359
|
-
const res = await
|
|
360
|
-
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
361
|
-
body: JSON.stringify({
|
|
365
|
+
const res = await _ccFetch('/api/work-items', {
|
|
362
366
|
title: action.title, type: action.workType || 'implement',
|
|
363
367
|
priority: action.priority || 'medium', description: action.description || '',
|
|
364
368
|
project: action.project || '', agents: action.agents || [],
|
|
365
|
-
})
|
|
366
369
|
});
|
|
367
370
|
const d = await res.json();
|
|
368
371
|
status.innerHTML = '✓ Dispatched: <strong>' + escHtml(d.id || action.title) + '</strong>';
|
|
@@ -371,49 +374,33 @@ async function ccExecuteAction(action) {
|
|
|
371
374
|
break;
|
|
372
375
|
}
|
|
373
376
|
case 'note': {
|
|
374
|
-
|
|
375
|
-
await fetch('/api/notes', {
|
|
376
|
-
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
377
|
-
body: JSON.stringify({ title: action.title, what: action.content || action.description, author: 'command-center' })
|
|
378
|
-
});
|
|
377
|
+
await _ccFetch('/api/notes', { title: action.title, what: action.content || action.description, author: 'command-center' });
|
|
379
378
|
status.innerHTML = '✓ Note saved: <strong>' + escHtml(action.title) + '</strong>';
|
|
380
379
|
status.style.color = 'var(--green)';
|
|
381
380
|
break;
|
|
382
381
|
}
|
|
383
382
|
case 'pin': {
|
|
384
|
-
await
|
|
385
|
-
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
386
|
-
body: JSON.stringify({ title: action.title, content: action.content || action.description, level: action.level || '' })
|
|
387
|
-
});
|
|
383
|
+
await _ccFetch('/api/pinned', { title: action.title, content: action.content || action.description, level: action.level || '' });
|
|
388
384
|
status.innerHTML = '📌 Pinned: <strong>' + escHtml(action.title) + '</strong> — visible to all agents';
|
|
389
385
|
status.style.color = 'var(--green)';
|
|
390
386
|
refresh();
|
|
391
387
|
break;
|
|
392
388
|
}
|
|
393
389
|
case 'plan': {
|
|
394
|
-
await
|
|
395
|
-
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
396
|
-
body: JSON.stringify({ title: action.title, description: action.description, project: action.project, branchStrategy: action.branchStrategy || 'parallel' })
|
|
397
|
-
});
|
|
390
|
+
await _ccFetch('/api/plan', { title: action.title, description: action.description, project: action.project, branchStrategy: action.branchStrategy || 'parallel' });
|
|
398
391
|
status.innerHTML = '✓ Plan queued: <strong>' + escHtml(action.title) + '</strong>';
|
|
399
392
|
status.style.color = 'var(--green)';
|
|
400
393
|
break;
|
|
401
394
|
}
|
|
402
395
|
case 'cancel': {
|
|
403
|
-
await
|
|
404
|
-
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
405
|
-
body: JSON.stringify({ agentId: action.agent, reason: action.reason || 'Cancelled via command center' })
|
|
406
|
-
});
|
|
396
|
+
await _ccFetch('/api/agents/cancel', { agentId: action.agent, reason: action.reason || 'Cancelled via command center' });
|
|
407
397
|
status.innerHTML = '✓ Cancelled agent: <strong>' + escHtml(action.agent) + '</strong>';
|
|
408
398
|
status.style.color = 'var(--orange)';
|
|
409
399
|
break;
|
|
410
400
|
}
|
|
411
401
|
case 'retry': {
|
|
412
402
|
for (const id of (action.ids || [])) {
|
|
413
|
-
await
|
|
414
|
-
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
415
|
-
body: JSON.stringify({ id, source: '' })
|
|
416
|
-
});
|
|
403
|
+
await _ccFetch('/api/work-items/retry', { id, source: '' });
|
|
417
404
|
}
|
|
418
405
|
status.innerHTML = '✓ Retried: <strong>' + escHtml((action.ids || []).join(', ')) + '</strong>';
|
|
419
406
|
status.style.color = 'var(--green)';
|
|
@@ -421,46 +408,31 @@ async function ccExecuteAction(action) {
|
|
|
421
408
|
break;
|
|
422
409
|
}
|
|
423
410
|
case 'pause-plan': {
|
|
424
|
-
await
|
|
425
|
-
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
426
|
-
body: JSON.stringify({ file: action.file })
|
|
427
|
-
});
|
|
411
|
+
await _ccFetch('/api/plans/pause', { file: action.file });
|
|
428
412
|
status.innerHTML = '✓ Paused plan: <strong>' + escHtml(action.file) + '</strong>';
|
|
429
413
|
status.style.color = 'var(--orange)';
|
|
430
414
|
break;
|
|
431
415
|
}
|
|
432
416
|
case 'approve-plan': {
|
|
433
|
-
await
|
|
434
|
-
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
435
|
-
body: JSON.stringify({ file: action.file })
|
|
436
|
-
});
|
|
417
|
+
await _ccFetch('/api/plans/approve', { file: action.file });
|
|
437
418
|
status.innerHTML = '✓ Approved plan: <strong>' + escHtml(action.file) + '</strong>';
|
|
438
419
|
status.style.color = 'var(--green)';
|
|
439
420
|
break;
|
|
440
421
|
}
|
|
441
422
|
case 'edit-prd-item': {
|
|
442
|
-
await
|
|
443
|
-
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
444
|
-
body: JSON.stringify({ source: action.source, itemId: action.itemId, name: action.name, description: action.description, priority: action.priority, estimated_complexity: action.complexity })
|
|
445
|
-
});
|
|
423
|
+
await _ccFetch('/api/prd-items/update', { source: action.source, itemId: action.itemId, name: action.name, description: action.description, priority: action.priority, estimated_complexity: action.complexity });
|
|
446
424
|
status.innerHTML = '✓ Updated PRD item: <strong>' + escHtml(action.itemId) + '</strong>';
|
|
447
425
|
status.style.color = 'var(--green)';
|
|
448
426
|
break;
|
|
449
427
|
}
|
|
450
428
|
case 'remove-prd-item': {
|
|
451
|
-
await
|
|
452
|
-
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
453
|
-
body: JSON.stringify({ source: action.source, itemId: action.itemId })
|
|
454
|
-
});
|
|
429
|
+
await _ccFetch('/api/prd-items/remove', { source: action.source, itemId: action.itemId });
|
|
455
430
|
status.innerHTML = '✓ Removed PRD item: <strong>' + escHtml(action.itemId) + '</strong>';
|
|
456
431
|
status.style.color = 'var(--orange)';
|
|
457
432
|
break;
|
|
458
433
|
}
|
|
459
434
|
case 'delete-work-item': {
|
|
460
|
-
await
|
|
461
|
-
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
462
|
-
body: JSON.stringify({ id: action.id, source: action.source || '' })
|
|
463
|
-
});
|
|
435
|
+
await _ccFetch('/api/work-items/delete', { id: action.id, source: action.source || '' });
|
|
464
436
|
status.innerHTML = '✓ Deleted work item: <strong>' + escHtml(action.id) + '</strong>';
|
|
465
437
|
status.style.color = 'var(--orange)';
|
|
466
438
|
break;
|
|
@@ -585,48 +557,33 @@ async function ccExecuteAction(action) {
|
|
|
585
557
|
break;
|
|
586
558
|
}
|
|
587
559
|
case 'unpin': {
|
|
588
|
-
await
|
|
589
|
-
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
590
|
-
body: JSON.stringify({ title: action.title })
|
|
591
|
-
});
|
|
560
|
+
await _ccFetch('/api/pinned/remove', { title: action.title });
|
|
592
561
|
status.innerHTML = '✓ Unpinned: <strong>' + escHtml(action.title) + '</strong>';
|
|
593
562
|
status.style.color = 'var(--green)';
|
|
594
563
|
refresh();
|
|
595
564
|
break;
|
|
596
565
|
}
|
|
597
566
|
case 'archive-plan': {
|
|
598
|
-
await
|
|
599
|
-
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
600
|
-
body: JSON.stringify({ file: action.file })
|
|
601
|
-
});
|
|
567
|
+
await _ccFetch('/api/plans/archive', { file: action.file });
|
|
602
568
|
status.innerHTML = '✓ Archived plan: <strong>' + escHtml(action.file) + '</strong>';
|
|
603
569
|
status.style.color = 'var(--green)';
|
|
604
570
|
refresh();
|
|
605
571
|
break;
|
|
606
572
|
}
|
|
607
573
|
case 'reject-plan': {
|
|
608
|
-
await
|
|
609
|
-
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
610
|
-
body: JSON.stringify({ file: action.file, reason: action.reason || '' })
|
|
611
|
-
});
|
|
574
|
+
await _ccFetch('/api/plans/reject', { file: action.file, reason: action.reason || '' });
|
|
612
575
|
status.innerHTML = '✓ Rejected plan: <strong>' + escHtml(action.file) + '</strong>';
|
|
613
576
|
status.style.color = 'var(--orange)';
|
|
614
577
|
break;
|
|
615
578
|
}
|
|
616
579
|
case 'steer-agent': {
|
|
617
|
-
await
|
|
618
|
-
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
619
|
-
body: JSON.stringify({ agent: action.agent, message: action.message || action.content })
|
|
620
|
-
});
|
|
580
|
+
await _ccFetch('/api/agents/steer', { agent: action.agent, message: action.message || action.content });
|
|
621
581
|
status.innerHTML = '✓ Steering message sent to <strong>' + escHtml(action.agent) + '</strong>';
|
|
622
582
|
status.style.color = 'var(--green)';
|
|
623
583
|
break;
|
|
624
584
|
}
|
|
625
585
|
case 'add-meeting-note': {
|
|
626
|
-
await
|
|
627
|
-
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
628
|
-
body: JSON.stringify({ id: action.id, note: action.note || action.content })
|
|
629
|
-
});
|
|
586
|
+
await _ccFetch('/api/meetings/note', { id: action.id, note: action.note || action.content });
|
|
630
587
|
status.innerHTML = '✓ Note added to meeting <strong>' + escHtml(action.id) + '</strong>';
|
|
631
588
|
status.style.color = 'var(--green)';
|
|
632
589
|
break;
|
|
@@ -643,30 +600,21 @@ async function ccExecuteAction(action) {
|
|
|
643
600
|
break;
|
|
644
601
|
}
|
|
645
602
|
case 'link-pr': {
|
|
646
|
-
await
|
|
647
|
-
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
648
|
-
body: JSON.stringify({ url: action.url, title: action.title || '', project: action.project || '', autoObserve: action.autoObserve !== false })
|
|
649
|
-
});
|
|
603
|
+
await _ccFetch('/api/pull-requests/link', { url: action.url, title: action.title || '', project: action.project || '', autoObserve: action.autoObserve !== false });
|
|
650
604
|
status.innerHTML = '✓ PR linked: <strong>' + escHtml(action.url) + '</strong>';
|
|
651
605
|
status.style.color = 'var(--green)';
|
|
652
606
|
refresh();
|
|
653
607
|
break;
|
|
654
608
|
}
|
|
655
609
|
case 'archive-meeting': {
|
|
656
|
-
await
|
|
657
|
-
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
658
|
-
body: JSON.stringify({ id: action.id })
|
|
659
|
-
});
|
|
610
|
+
await _ccFetch('/api/meetings/archive', { id: action.id });
|
|
660
611
|
status.innerHTML = '✓ Meeting archived: <strong>' + escHtml(action.id) + '</strong>';
|
|
661
612
|
status.style.color = 'var(--green)';
|
|
662
613
|
refresh();
|
|
663
614
|
break;
|
|
664
615
|
}
|
|
665
616
|
case 'update-routing': {
|
|
666
|
-
await
|
|
667
|
-
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
668
|
-
body: JSON.stringify({ content: action.content })
|
|
669
|
-
});
|
|
617
|
+
await _ccFetch('/api/settings/routing', { content: action.content });
|
|
670
618
|
status.innerHTML = '✓ Routing updated';
|
|
671
619
|
status.style.color = 'var(--green)';
|
|
672
620
|
break;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// dashboard/js/detail-panel.js — Agent detail panel extracted from dashboard.html
|
|
2
2
|
|
|
3
|
+
let _charterRawCache = ''; // stored outside DOM to survive innerHTML rewrites on tab switch
|
|
4
|
+
|
|
3
5
|
function closeDetail() {
|
|
4
6
|
document.getElementById('detail-overlay').classList.remove('open');
|
|
5
7
|
document.getElementById('detail-panel').classList.remove('open');
|
|
@@ -88,7 +90,7 @@ function renderDetailContent(detail, tab) {
|
|
|
88
90
|
'</div>' +
|
|
89
91
|
'<div id="charter-view" class="section">' + renderMd(charterContent || 'No charter found. Click Edit to create one.') + '</div>' +
|
|
90
92
|
'<textarea id="charter-editor" style="display:none;width:100%;min-height:300px;padding:8px;background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--text);font-family:Consolas,monospace;font-size:12px;resize:vertical">' + escHtml(charterContent) + '</textarea>';
|
|
91
|
-
|
|
93
|
+
_charterRawCache = charterContent;
|
|
92
94
|
} else if (tab === 'history') {
|
|
93
95
|
let html = '';
|
|
94
96
|
// Recent dispatch results
|
|
@@ -126,7 +128,7 @@ function _toggleCharterEdit() {
|
|
|
126
128
|
|
|
127
129
|
function _cancelCharterEdit() {
|
|
128
130
|
const el = document.getElementById('detail-content');
|
|
129
|
-
document.getElementById('charter-editor').value =
|
|
131
|
+
document.getElementById('charter-editor').value = _charterRawCache || '';
|
|
130
132
|
document.getElementById('charter-view').style.display = '';
|
|
131
133
|
document.getElementById('charter-editor').style.display = 'none';
|
|
132
134
|
document.getElementById('charter-edit-btn').style.display = '';
|
|
@@ -146,7 +148,7 @@ async function _saveCharter() {
|
|
|
146
148
|
});
|
|
147
149
|
if (res.ok) {
|
|
148
150
|
document.getElementById('charter-view').innerHTML = renderMd(content);
|
|
149
|
-
|
|
151
|
+
_charterRawCache = content;
|
|
150
152
|
_cancelCharterEdit();
|
|
151
153
|
showToast('cmd-toast', 'Charter saved', true);
|
|
152
154
|
} else {
|
package/dashboard/js/modal.js
CHANGED
|
@@ -49,7 +49,9 @@ function closeModal() {
|
|
|
49
49
|
function copyModalContent() {
|
|
50
50
|
const body = document.getElementById('modal-body');
|
|
51
51
|
const btn = document.getElementById('modal-copy-btn');
|
|
52
|
-
|
|
52
|
+
// Prefer raw markdown source if available, fall back to rendered text
|
|
53
|
+
const text = (typeof _modalDocContext !== 'undefined' && _modalDocContext.content) ? _modalDocContext.content : body.textContent;
|
|
54
|
+
navigator.clipboard.writeText(text).then(() => {
|
|
53
55
|
btn.classList.add('copied');
|
|
54
56
|
btn.innerHTML = '<svg width="12" height="12" viewBox="0 0 16 16" fill="currentColor"><path d="M13.78 4.22a.75.75 0 010 1.06l-7.25 7.25a.75.75 0 01-1.06 0L2.22 9.28a.75.75 0 011.06-1.06L6 10.94l6.72-6.72a.75.75 0 011.06 0z"/></svg> Copied';
|
|
55
57
|
setTimeout(() => {
|
|
@@ -62,7 +62,7 @@ function renderKnowledgeBase() {
|
|
|
62
62
|
if (!Array.isArray(catItems)) continue;
|
|
63
63
|
for (const item of catItems) items.push({ ...item, category: cat });
|
|
64
64
|
}
|
|
65
|
-
items.sort((a, b) => b.date.localeCompare(a.date));
|
|
65
|
+
items.sort((a, b) => (b.date || '').localeCompare(a.date || ''));
|
|
66
66
|
} else {
|
|
67
67
|
items = (_kbData[_kbActiveTab] || []).map(i => ({ ...i, category: _kbActiveTab }));
|
|
68
68
|
}
|
|
@@ -400,7 +400,11 @@ function _renderPlanModal(normalizedFile, raw, lastMod) {
|
|
|
400
400
|
let text = '';
|
|
401
401
|
|
|
402
402
|
if (normalizedFile.endsWith('.json')) {
|
|
403
|
-
|
|
403
|
+
let plan;
|
|
404
|
+
try { plan = JSON.parse(raw); } catch (e) {
|
|
405
|
+
document.getElementById('modal-body').innerHTML = '<p style="color:var(--red)">Failed to parse plan JSON: ' + escHtml(e.message) + '</p><pre style="font-size:10px;max-height:200px;overflow:auto">' + escHtml((raw || '').slice(0, 500)) + '</pre>';
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
404
408
|
title = plan.plan_summary || normalizedFile;
|
|
405
409
|
const items = (plan.missing_features || []).map((f, i) =>
|
|
406
410
|
(i + 1) + '. [' + f.id + '] ' + f.name + ' (' + (f.estimated_complexity || '?') + ', ' + (f.priority || '?') + ')' +
|
|
@@ -550,7 +550,14 @@ function showArchivedPrdDetail(idxOrFile) {
|
|
|
550
550
|
}
|
|
551
551
|
|
|
552
552
|
async function prdItemEdit(source, itemId) {
|
|
553
|
-
|
|
553
|
+
let item = _prdItems.find(i => i.source === source && i.id === itemId);
|
|
554
|
+
// Also search archived groups if not found in active items
|
|
555
|
+
if (!item && window._archivedPrdGroups) {
|
|
556
|
+
for (const g of window._archivedPrdGroups) {
|
|
557
|
+
item = (g.items || []).find(i => i.source === source && i.id === itemId);
|
|
558
|
+
if (item) break;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
554
561
|
if (!item) return;
|
|
555
562
|
|
|
556
563
|
// Look up work item and dispatch completion info
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.369",
|
|
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"
|