@yemi33/minions 0.1.121 → 0.1.123
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 +20 -0
- package/dashboard/js/detail-panel.js +53 -3
- package/dashboard/js/modal-qa.js +1 -1
- package/dashboard/js/render-inbox.js +1 -1
- package/dashboard/js/render-kb.js +1 -3
- package/dashboard/js/render-plans.js +3 -9
- package/dashboard/js/utils.js +1 -1
- package/dashboard/styles.css +8 -0
- package/dashboard.js +6 -6
- package/engine/ado-mcp-wrapper.js +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.123 (2026-04-01)
|
|
4
|
+
|
|
5
|
+
### Engine
|
|
6
|
+
- engine/ado-mcp-wrapper.js
|
|
7
|
+
|
|
8
|
+
### Dashboard
|
|
9
|
+
- dashboard.js
|
|
10
|
+
- dashboard/js/detail-panel.js
|
|
11
|
+
- dashboard/js/modal-qa.js
|
|
12
|
+
- dashboard/js/render-inbox.js
|
|
13
|
+
- dashboard/js/render-kb.js
|
|
14
|
+
- dashboard/js/render-plans.js
|
|
15
|
+
- dashboard/js/utils.js
|
|
16
|
+
- dashboard/styles.css
|
|
17
|
+
|
|
18
|
+
## 0.1.122 (2026-04-01)
|
|
19
|
+
|
|
20
|
+
### Other
|
|
21
|
+
- test/unit.test.js
|
|
22
|
+
|
|
3
23
|
## 0.1.121 (2026-04-01)
|
|
4
24
|
|
|
5
25
|
### Dashboard
|
|
@@ -79,7 +79,16 @@ function renderDetailContent(detail, tab) {
|
|
|
79
79
|
'</div>';
|
|
80
80
|
startLiveStream(currentAgentId);
|
|
81
81
|
} else if (tab === 'charter') {
|
|
82
|
-
|
|
82
|
+
const charterContent = detail.charter || '';
|
|
83
|
+
el.innerHTML =
|
|
84
|
+
'<div style="display:flex;gap:6px;margin-bottom:8px">' +
|
|
85
|
+
'<button class="pr-pager-btn" id="charter-edit-btn" style="font-size:10px;padding:2px 10px" onclick="_toggleCharterEdit()">Edit</button>' +
|
|
86
|
+
'<button class="pr-pager-btn" id="charter-save-btn" style="font-size:10px;padding:2px 10px;color:var(--green);border-color:var(--green);display:none" onclick="_saveCharter()">Save</button>' +
|
|
87
|
+
'<button class="pr-pager-btn" id="charter-cancel-btn" style="font-size:10px;padding:2px 10px;display:none" onclick="_cancelCharterEdit()">Cancel</button>' +
|
|
88
|
+
'</div>' +
|
|
89
|
+
'<div id="charter-view" class="section">' + renderMd(charterContent || 'No charter found. Click Edit to create one.') + '</div>' +
|
|
90
|
+
'<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
|
+
el._charterRaw = charterContent;
|
|
83
92
|
} else if (tab === 'history') {
|
|
84
93
|
let html = '';
|
|
85
94
|
// Recent dispatch results
|
|
@@ -99,11 +108,52 @@ function renderDetailContent(detail, tab) {
|
|
|
99
108
|
html += '</tbody></table>';
|
|
100
109
|
}
|
|
101
110
|
// Raw history.md
|
|
102
|
-
html += '<h4>Task History</h4><div class="section">' +
|
|
111
|
+
html += '<h4>Task History</h4><div class="section">' + renderMd(detail.history || 'No history yet.') + '</div>';
|
|
103
112
|
el.innerHTML = html;
|
|
104
113
|
} else if (tab === 'output') {
|
|
105
|
-
el.innerHTML = '<div class="section">' +
|
|
114
|
+
el.innerHTML = '<div class="section">' + renderMd(detail.outputLog || 'No output log. The coordinator will save agent output here when tasks complete.') + '</div>';
|
|
106
115
|
}
|
|
107
116
|
}
|
|
108
117
|
|
|
118
|
+
function _toggleCharterEdit() {
|
|
119
|
+
document.getElementById('charter-view').style.display = 'none';
|
|
120
|
+
document.getElementById('charter-editor').style.display = '';
|
|
121
|
+
document.getElementById('charter-edit-btn').style.display = 'none';
|
|
122
|
+
document.getElementById('charter-save-btn').style.display = '';
|
|
123
|
+
document.getElementById('charter-cancel-btn').style.display = '';
|
|
124
|
+
document.getElementById('charter-editor').focus();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function _cancelCharterEdit() {
|
|
128
|
+
const el = document.getElementById('detail-content');
|
|
129
|
+
document.getElementById('charter-editor').value = el._charterRaw || '';
|
|
130
|
+
document.getElementById('charter-view').style.display = '';
|
|
131
|
+
document.getElementById('charter-editor').style.display = 'none';
|
|
132
|
+
document.getElementById('charter-edit-btn').style.display = '';
|
|
133
|
+
document.getElementById('charter-save-btn').style.display = 'none';
|
|
134
|
+
document.getElementById('charter-cancel-btn').style.display = 'none';
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
async function _saveCharter() {
|
|
138
|
+
const content = document.getElementById('charter-editor').value;
|
|
139
|
+
const btn = document.getElementById('charter-save-btn');
|
|
140
|
+
btn.textContent = 'Saving...'; btn.style.pointerEvents = 'none';
|
|
141
|
+
try {
|
|
142
|
+
const res = await fetch('/api/agents/charter', {
|
|
143
|
+
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
144
|
+
body: JSON.stringify({ agent: currentAgentId, content })
|
|
145
|
+
});
|
|
146
|
+
if (res.ok) {
|
|
147
|
+
document.getElementById('charter-view').innerHTML = renderMd(content);
|
|
148
|
+
document.getElementById('detail-content')._charterRaw = content;
|
|
149
|
+
_cancelCharterEdit();
|
|
150
|
+
showToast('cmd-toast', 'Charter saved', true);
|
|
151
|
+
} else {
|
|
152
|
+
const d = await res.json().catch(() => ({}));
|
|
153
|
+
alert('Save failed: ' + (d.error || 'unknown'));
|
|
154
|
+
}
|
|
155
|
+
} catch (e) { alert('Save failed: ' + e.message); }
|
|
156
|
+
btn.textContent = 'Save'; btn.style.pointerEvents = '';
|
|
157
|
+
}
|
|
158
|
+
|
|
109
159
|
window.MinionsDetail = { closeDetail, renderDetailTabs, switchTab, renderDetailContent };
|
package/dashboard/js/modal-qa.js
CHANGED
|
@@ -220,7 +220,7 @@ async function _processQaMessage(message, selection) {
|
|
|
220
220
|
if (isJson) {
|
|
221
221
|
body.textContent = display;
|
|
222
222
|
} else {
|
|
223
|
-
body.innerHTML =
|
|
223
|
+
body.innerHTML = renderMd(display);
|
|
224
224
|
body.style.fontFamily = "'Segoe UI', system-ui, sans-serif";
|
|
225
225
|
body.style.whiteSpace = 'normal';
|
|
226
226
|
}
|
|
@@ -65,7 +65,7 @@ function openNotesModal() {
|
|
|
65
65
|
if (!preview) return;
|
|
66
66
|
const content = preview._rawContent || preview.textContent;
|
|
67
67
|
document.getElementById('modal-title').textContent = 'Team Notes';
|
|
68
|
-
document.getElementById('modal-body').innerHTML =
|
|
68
|
+
document.getElementById('modal-body').innerHTML = renderMd(content);
|
|
69
69
|
document.getElementById('modal-body').style.fontFamily = "'Segoe UI', system-ui, sans-serif";
|
|
70
70
|
document.getElementById('modal-body').style.whiteSpace = 'normal';
|
|
71
71
|
_modalDocContext = { title: 'Team Notes', content, selection: '' };
|
|
@@ -164,9 +164,7 @@ async function kbOpenItem(category, file) {
|
|
|
164
164
|
const display = content.replace(/^---[\s\S]*?---\n*/m, '');
|
|
165
165
|
document.getElementById('modal-title').textContent = file;
|
|
166
166
|
const modalBody = document.getElementById('modal-body');
|
|
167
|
-
modalBody.innerHTML =
|
|
168
|
-
modalBody.style.fontFamily = "'Segoe UI', system-ui, sans-serif";
|
|
169
|
-
modalBody.style.whiteSpace = 'normal';
|
|
167
|
+
modalBody.innerHTML = renderMd(display);
|
|
170
168
|
_modalDocContext = { title: file, content: display, selection: '' };
|
|
171
169
|
_modalFilePath = 'knowledge/' + category + '/' + file; showModalQa();
|
|
172
170
|
// Clear notification badge when opening this document
|
|
@@ -488,9 +488,7 @@ async function planView(file) {
|
|
|
488
488
|
modalBody.style.fontFamily = 'Consolas, monospace';
|
|
489
489
|
modalBody.style.whiteSpace = 'pre-wrap';
|
|
490
490
|
} else {
|
|
491
|
-
modalBody.innerHTML =
|
|
492
|
-
modalBody.style.fontFamily = "'Segoe UI', system-ui, sans-serif";
|
|
493
|
-
modalBody.style.whiteSpace = 'normal';
|
|
491
|
+
modalBody.innerHTML = renderMd(text);
|
|
494
492
|
}
|
|
495
493
|
_modalDocContext = { title, content: text, selection: '' };
|
|
496
494
|
_modalFilePath = resolvedPath || ((normalizedFile.endsWith('.json') ? 'prd/' : 'plans/') + normalizedFile); showModalQa();
|
|
@@ -634,9 +632,7 @@ async function planOpenInDocChat(file) {
|
|
|
634
632
|
document.getElementById('modal-body').style.fontFamily = 'Consolas, monospace';
|
|
635
633
|
document.getElementById('modal-body').style.whiteSpace = 'pre-wrap';
|
|
636
634
|
} else {
|
|
637
|
-
document.getElementById('modal-body').innerHTML =
|
|
638
|
-
document.getElementById('modal-body').style.fontFamily = "'Segoe UI', system-ui, sans-serif";
|
|
639
|
-
document.getElementById('modal-body').style.whiteSpace = 'normal';
|
|
635
|
+
document.getElementById('modal-body').innerHTML = renderMd(text);
|
|
640
636
|
}
|
|
641
637
|
_modalDocContext = { title: title, content: text, selection: '' };
|
|
642
638
|
_modalFilePath = resolvedPath || ((normalizedFile.endsWith('.json') ? 'prd/' : 'plans/') + normalizedFile); showModalQa();
|
|
@@ -669,9 +665,7 @@ async function openVerifyGuide(file) {
|
|
|
669
665
|
const content = await fetch('/api/plans/' + encodeURIComponent(normalizedFile)).then(r => r.text());
|
|
670
666
|
document.getElementById('modal-title').innerHTML = 'Manual Testing Guide' +
|
|
671
667
|
' <button class="pr-pager-btn" style="font-size:9px;padding:2px 8px;margin-left:8px;vertical-align:middle" onclick="openArchivedPrdModal()">Back</button>';
|
|
672
|
-
document.getElementById('modal-body').innerHTML =
|
|
673
|
-
document.getElementById('modal-body').style.fontFamily = "'Segoe UI', system-ui, sans-serif";
|
|
674
|
-
document.getElementById('modal-body').style.whiteSpace = 'normal';
|
|
668
|
+
document.getElementById('modal-body').innerHTML = renderMd(content);
|
|
675
669
|
_modalDocContext = { title: 'Manual Testing Guide', content, selection: '' };
|
|
676
670
|
_modalFilePath = 'prd/' + normalizedFile; showModalQa();
|
|
677
671
|
const card = findCardForFile(_modalFilePath);
|
package/dashboard/js/utils.js
CHANGED
|
@@ -187,7 +187,7 @@ function renderMd(s) {
|
|
|
187
187
|
// 4. Restore code placeholders
|
|
188
188
|
html = html.replace(/\x00CB(\d+)\x00/g, function(_, idx) { return codeSlots[idx]; });
|
|
189
189
|
|
|
190
|
-
return html;
|
|
190
|
+
return '<div class="md-content">' + html + '</div>';
|
|
191
191
|
}
|
|
192
192
|
|
|
193
193
|
window.MinionsUtils = { wakeEngine, escHtml, renderMd, normalizePlanFile, timeAgo, statusColor, llmCopyBtn, copyLlmText };
|
package/dashboard/styles.css
CHANGED
|
@@ -541,6 +541,14 @@
|
|
|
541
541
|
}
|
|
542
542
|
.detail-content h4 { color: var(--text); font-size: var(--text-lg); margin: var(--space-6) 0 var(--space-3) 0; font-family: 'Segoe UI', sans-serif; }
|
|
543
543
|
.detail-content .section { margin-bottom: var(--space-7); padding: var(--space-6); background: var(--surface2); border: 1px solid var(--border); border-radius: var(--radius-md); }
|
|
544
|
+
|
|
545
|
+
/* Markdown content — consistent styling everywhere renderMd() is used */
|
|
546
|
+
.md-content { font-family: 'Segoe UI', system-ui, sans-serif; font-size: 12px; line-height: 1.6; white-space: normal; word-break: break-word; }
|
|
547
|
+
.md-content pre { font-family: Consolas, 'Courier New', monospace; white-space: pre-wrap; }
|
|
548
|
+
.md-content code { font-family: Consolas, 'Courier New', monospace; }
|
|
549
|
+
.md-content table { border-collapse: collapse; width: 100%; margin: 6px 0; }
|
|
550
|
+
.md-content th, .md-content td { padding: 4px 8px; border: 1px solid var(--border); text-align: left; font-size: 11px; }
|
|
551
|
+
.md-content th { background: var(--surface); font-weight: 600; }
|
|
544
552
|
.status-line { display: flex; align-items: center; gap: var(--space-5); padding: var(--space-5) var(--space-7); background: var(--bg); border-bottom: 1px solid var(--border); font-size: var(--text-md); }
|
|
545
553
|
|
|
546
554
|
/* Modal for inbox detail */
|
package/dashboard.js
CHANGED
|
@@ -747,7 +747,7 @@ function spawnEngine() {
|
|
|
747
747
|
if (key === 'CLAUDECODE' || key.startsWith('CLAUDE_CODE') || key.startsWith('CLAUDECODE_')) delete childEnv[key];
|
|
748
748
|
}
|
|
749
749
|
const engineProc = cpSpawn(process.execPath, [path.join(MINIONS_DIR, 'engine.js'), 'start'], {
|
|
750
|
-
cwd: MINIONS_DIR, stdio: 'ignore', detached: true, env: childEnv,
|
|
750
|
+
cwd: MINIONS_DIR, stdio: 'ignore', detached: true, env: childEnv, windowsHide: true,
|
|
751
751
|
});
|
|
752
752
|
engineProc.unref();
|
|
753
753
|
return engineProc.pid;
|
|
@@ -758,7 +758,7 @@ function killEnginePid(pid) {
|
|
|
758
758
|
try {
|
|
759
759
|
const safePid = shared.validatePid(pid);
|
|
760
760
|
if (process.platform === 'win32') {
|
|
761
|
-
execFileSync('taskkill', ['/PID', String(safePid), '/F', '/T'], { stdio: 'pipe', timeout: 5000 });
|
|
761
|
+
execFileSync('taskkill', ['/PID', String(safePid), '/F', '/T'], { stdio: 'pipe', timeout: 5000, windowsHide: true });
|
|
762
762
|
} else {
|
|
763
763
|
process.kill(safePid, 'SIGKILL');
|
|
764
764
|
}
|
|
@@ -1271,7 +1271,7 @@ const server = http.createServer(async (req, res) => {
|
|
|
1271
1271
|
try {
|
|
1272
1272
|
const safePid = shared.validatePid(status.pid);
|
|
1273
1273
|
if (process.platform === 'win32') {
|
|
1274
|
-
require('child_process').execFileSync('taskkill', ['/PID', String(safePid), '/F', '/T'], { stdio: 'pipe', timeout: 5000 });
|
|
1274
|
+
require('child_process').execFileSync('taskkill', ['/PID', String(safePid), '/F', '/T'], { stdio: 'pipe', timeout: 5000, windowsHide: true });
|
|
1275
1275
|
} else {
|
|
1276
1276
|
process.kill(safePid, 'SIGTERM');
|
|
1277
1277
|
}
|
|
@@ -1866,7 +1866,7 @@ If nothing to do: { "duplicates": [], "reclassify": [], "remove": [] }`;
|
|
|
1866
1866
|
try {
|
|
1867
1867
|
const safePid = shared.validatePid(agentStatus.pid);
|
|
1868
1868
|
if (process.platform === 'win32') {
|
|
1869
|
-
require('child_process').execFileSync('taskkill', ['/PID', String(safePid), '/F', '/T'], { stdio: 'pipe', timeout: 5000 });
|
|
1869
|
+
require('child_process').execFileSync('taskkill', ['/PID', String(safePid), '/F', '/T'], { stdio: 'pipe', timeout: 5000, windowsHide: true });
|
|
1870
1870
|
} else {
|
|
1871
1871
|
process.kill(safePid, 'SIGTERM');
|
|
1872
1872
|
}
|
|
@@ -2567,7 +2567,7 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
2567
2567
|
try {
|
|
2568
2568
|
const safePid = shared.validatePid(agentStatus.pid);
|
|
2569
2569
|
if (process.platform === 'win32') {
|
|
2570
|
-
require('child_process').execFileSync('taskkill', ['/PID', String(safePid), '/F', '/T'], { stdio: 'pipe', timeout: 5000 });
|
|
2570
|
+
require('child_process').execFileSync('taskkill', ['/PID', String(safePid), '/F', '/T'], { stdio: 'pipe', timeout: 5000, windowsHide: true });
|
|
2571
2571
|
} else {
|
|
2572
2572
|
process.kill(safePid, 'SIGTERM');
|
|
2573
2573
|
}
|
|
@@ -3602,7 +3602,7 @@ server.listen(PORT, '127.0.0.1', () => {
|
|
|
3602
3602
|
let alive = false;
|
|
3603
3603
|
try {
|
|
3604
3604
|
if (process.platform === 'win32') {
|
|
3605
|
-
const out = execSync(`tasklist /FI "PID eq ${control.pid}" /NH`, { encoding: 'utf8', timeout: 3000 });
|
|
3605
|
+
const out = execSync(`tasklist /FI "PID eq ${control.pid}" /NH`, { encoding: 'utf8', timeout: 3000, windowsHide: true });
|
|
3606
3606
|
alive = out.includes(String(control.pid));
|
|
3607
3607
|
} else {
|
|
3608
3608
|
process.kill(control.pid, 0); // signal 0 = check existence
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.123",
|
|
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"
|