@yemi33/minions 0.1.138 → 0.1.140
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 +12 -0
- package/dashboard/js/command-center.js +14 -0
- package/dashboard/js/render-pipelines.js +147 -5
- package/dashboard.js +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.140 (2026-04-01)
|
|
4
|
+
|
|
5
|
+
### Dashboard
|
|
6
|
+
- dashboard.js
|
|
7
|
+
- dashboard/js/command-center.js
|
|
8
|
+
- dashboard/js/render-pipelines.js
|
|
9
|
+
|
|
10
|
+
## 0.1.139 (2026-04-01)
|
|
11
|
+
|
|
12
|
+
### Dashboard
|
|
13
|
+
- dashboard/js/render-pipelines.js
|
|
14
|
+
|
|
3
15
|
## 0.1.138 (2026-04-01)
|
|
4
16
|
|
|
5
17
|
### Dashboard
|
|
@@ -434,6 +434,20 @@ async function ccExecuteAction(action) {
|
|
|
434
434
|
status.style.color = 'var(--green)';
|
|
435
435
|
break;
|
|
436
436
|
}
|
|
437
|
+
case 'edit-pipeline': {
|
|
438
|
+
const body = { id: action.id };
|
|
439
|
+
if (action.title) body.title = action.title;
|
|
440
|
+
if (action.stages) body.stages = action.stages;
|
|
441
|
+
if (action.trigger !== undefined) body.trigger = action.trigger;
|
|
442
|
+
const res = await fetch('/api/pipelines/update', {
|
|
443
|
+
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
444
|
+
body: JSON.stringify(body)
|
|
445
|
+
});
|
|
446
|
+
if (!res.ok) { const d = await res.json().catch(() => ({})); throw new Error(d.error || 'Pipeline update failed'); }
|
|
447
|
+
status.innerHTML = '✓ Updated pipeline: <strong>' + escHtml(action.id) + '</strong>';
|
|
448
|
+
status.style.color = 'var(--green)';
|
|
449
|
+
break;
|
|
450
|
+
}
|
|
437
451
|
default:
|
|
438
452
|
status.innerHTML = '? Unknown action: ' + escHtml(action.type);
|
|
439
453
|
status.style.color = 'var(--muted)';
|
|
@@ -19,7 +19,7 @@ function renderPipelines(pipelines) {
|
|
|
19
19
|
const lastRun = (p.runs || []).slice(-1)[0];
|
|
20
20
|
const statusColor = activeRun ? 'var(--blue)' : lastRun?.status === 'completed' ? 'var(--green)' : lastRun?.status === 'failed' ? 'var(--red)' : 'var(--muted)';
|
|
21
21
|
const statusLabel = activeRun ? 'Running' : lastRun ? (lastRun.status === 'completed' ? 'Completed' : lastRun.status === 'failed' ? 'Failed' : lastRun.status) : 'Never run';
|
|
22
|
-
const trigger = p.trigger?.cron ?
|
|
22
|
+
const trigger = p.trigger?.cron ? _cronToHuman(p.trigger.cron) : 'Manual';
|
|
23
23
|
|
|
24
24
|
// Stage flow visualization
|
|
25
25
|
var stageFlow = (p.stages || []).map(function(s) {
|
|
@@ -52,9 +52,10 @@ function openPipelineDetail(id) {
|
|
|
52
52
|
// Status + actions
|
|
53
53
|
var activeRun = (p.runs || []).find(function(r) { return r.status === 'running'; });
|
|
54
54
|
html += '<div style="display:flex;justify-content:space-between;align-items:center">' +
|
|
55
|
-
'<span style="font-size:10px;color:var(--muted)">' + (p.trigger?.cron ? '
|
|
55
|
+
'<span style="font-size:10px;color:var(--muted)">' + (p.trigger?.cron ? escHtml(_cronToHuman(p.trigger.cron)) + ' <span style="opacity:0.6">(' + escHtml(p.trigger.cron) + ', ' + escHtml(Intl.DateTimeFormat().resolvedOptions().timeZone) + ')</span>' : 'Manual trigger') + '</span>' +
|
|
56
56
|
'<div style="display:flex;gap:6px">' +
|
|
57
57
|
(activeRun ? '' : '<button class="pr-pager-btn" style="font-size:9px;padding:2px 8px;color:var(--green);border-color:var(--green)" onclick="_triggerPipeline(\'' + escHtml(id) + '\',this)">Run Now</button>') +
|
|
58
|
+
'<button class="pr-pager-btn" style="font-size:9px;padding:2px 8px;color:var(--blue);border-color:var(--blue)" onclick="openEditPipelineModal(\'' + escHtml(id) + '\')">Edit</button>' +
|
|
58
59
|
'<button class="pr-pager-btn" style="font-size:9px;padding:2px 8px" onclick="_togglePipelineEnabled(\'' + escHtml(id) + '\',' + !p.enabled + ',this)">' + (p.enabled !== false ? 'Disable' : 'Enable') + '</button>' +
|
|
59
60
|
'<button class="pr-pager-btn" style="font-size:9px;padding:2px 8px;color:var(--red);border-color:var(--red)" onclick="_deletePipelineConfirm(\'' + escHtml(id) + '\')">Delete</button>' +
|
|
60
61
|
'</div>' +
|
|
@@ -142,13 +143,52 @@ async function _deletePipelineConfirm(id) {
|
|
|
142
143
|
|
|
143
144
|
function openCreatePipelineModal() {
|
|
144
145
|
var inputStyle = 'display:block;width:100%;margin-top:4px;padding:6px 8px;background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--text);font-size:var(--text-md);font-family:inherit';
|
|
146
|
+
var pillStyle = 'display:inline-block;padding:4px 10px;margin:2px;border:1px solid var(--border);border-radius:12px;cursor:pointer;font-size:11px;color:var(--text);background:var(--bg);user-select:none;transition:all 0.15s';
|
|
147
|
+
var linkStyle = 'font-size:10px;color:var(--blue);cursor:pointer;text-decoration:underline;margin-right:8px';
|
|
148
|
+
var tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
149
|
+
|
|
150
|
+
// Hour options (0-23)
|
|
151
|
+
var hourOpts = '';
|
|
152
|
+
for (var h = 0; h < 24; h++) hourOpts += '<option value="' + h + '"' + (h === 9 ? ' selected' : '') + '>' + String(h).padStart(2, '0') + '</option>';
|
|
153
|
+
// Minute options (0, 5, 10, ..., 55)
|
|
154
|
+
var minOpts = '';
|
|
155
|
+
for (var m = 0; m <= 55; m += 5) minOpts += '<option value="' + m + '"' + (m === 0 ? ' selected' : '') + '>' + String(m).padStart(2, '0') + '</option>';
|
|
156
|
+
|
|
157
|
+
var dayOrder = [0, 1, 2, 3, 4, 5, 6];
|
|
158
|
+
var dayLabels = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
|
159
|
+
var dayPills = dayOrder.map(function(d) {
|
|
160
|
+
var active = d >= 1 && d <= 5; // default weekdays
|
|
161
|
+
return '<span class="sched-day-pill' + (active ? ' active' : '') + '" data-day="' + d + '" ' +
|
|
162
|
+
'style="' + pillStyle + (active ? ';background:var(--blue);color:#fff;border-color:var(--blue)' : '') + '" ' +
|
|
163
|
+
'onclick="_toggleDayPill(this);_updatePlCronPreview()">' + dayLabels[d] + '</span>';
|
|
164
|
+
}).join('');
|
|
145
165
|
|
|
146
166
|
document.getElementById('modal-title').textContent = 'New Pipeline';
|
|
147
167
|
document.getElementById('modal-body').innerHTML =
|
|
148
168
|
'<div style="display:flex;flex-direction:column;gap:10px">' +
|
|
149
169
|
'<label style="color:var(--text);font-size:var(--text-md)">ID<input id="pl-id" style="' + inputStyle + '" placeholder="e.g. daily-audit-cycle"></label>' +
|
|
150
170
|
'<label style="color:var(--text);font-size:var(--text-md)">Title<input id="pl-title" style="' + inputStyle + '" placeholder="e.g. Daily audit and improvement cycle"></label>' +
|
|
151
|
-
'<
|
|
171
|
+
'<div>' +
|
|
172
|
+
'<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px">' +
|
|
173
|
+
'<label style="color:var(--text);font-size:var(--text-md);margin:0">Schedule</label>' +
|
|
174
|
+
'<label style="font-size:11px;color:var(--muted);cursor:pointer"><input type="checkbox" id="pl-use-cron" checked onchange="_updatePlCronPreview()" style="accent-color:var(--blue)"> Enable automatic trigger</label>' +
|
|
175
|
+
'</div>' +
|
|
176
|
+
'<div id="pl-cron-picker">' +
|
|
177
|
+
'<div style="display:flex;gap:8px;align-items:center">' +
|
|
178
|
+
'<select id="pl-pick-hour" style="' + inputStyle + ';width:auto;display:inline-block" onchange="_updatePlCronPreview()">' + hourOpts + '</select>' +
|
|
179
|
+
'<span style="color:var(--muted)">:</span>' +
|
|
180
|
+
'<select id="pl-pick-minute" style="' + inputStyle + ';width:auto;display:inline-block" onchange="_updatePlCronPreview()">' + minOpts + '</select>' +
|
|
181
|
+
'<span style="font-size:10px;color:var(--muted)">' + escHtml(tz) + '</span>' +
|
|
182
|
+
'</div>' +
|
|
183
|
+
'<div style="margin-top:8px">' + dayPills + '</div>' +
|
|
184
|
+
'<div style="margin-top:6px">' +
|
|
185
|
+
'<span style="' + linkStyle + '" onclick="_quickSelectDays(\'all\');_updatePlCronPreview()">Every day</span>' +
|
|
186
|
+
'<span style="' + linkStyle + '" onclick="_quickSelectDays(\'weekdays\');_updatePlCronPreview()">Weekdays</span>' +
|
|
187
|
+
'<span style="' + linkStyle + '" onclick="_quickSelectDays(\'weekends\');_updatePlCronPreview()">Weekends</span>' +
|
|
188
|
+
'</div>' +
|
|
189
|
+
'<div id="pl-cron-preview" style="margin-top:4px;font-size:11px;color:var(--blue)"></div>' +
|
|
190
|
+
'</div>' +
|
|
191
|
+
'</div>' +
|
|
152
192
|
'<label style="color:var(--text);font-size:var(--text-md)">Stages (JSON array)<textarea id="pl-stages" rows="10" style="' + inputStyle + ';resize:vertical;font-family:Consolas,monospace" placeholder=\'[{"id":"audit","type":"task","title":"Audit codebase","taskType":"explore"},{"id":"discuss","type":"meeting","title":"Discuss findings","dependsOn":["audit"],"participants":["all"]}]\'></textarea></label>' +
|
|
153
193
|
'<div style="display:flex;justify-content:flex-end;gap:8px;margin-top:4px">' +
|
|
154
194
|
'<button onclick="closeModal()" class="pr-pager-btn">Cancel</button>' +
|
|
@@ -156,12 +196,30 @@ function openCreatePipelineModal() {
|
|
|
156
196
|
'</div>' +
|
|
157
197
|
'</div>';
|
|
158
198
|
document.getElementById('modal').classList.add('open');
|
|
199
|
+
_updatePlCronPreview();
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function _updatePlCronPreview() {
|
|
203
|
+
var useCron = document.getElementById('pl-use-cron')?.checked;
|
|
204
|
+
var pickerEl = document.getElementById('pl-cron-picker');
|
|
205
|
+
if (pickerEl) pickerEl.style.opacity = useCron ? '1' : '0.4';
|
|
206
|
+
if (pickerEl) pickerEl.style.pointerEvents = useCron ? '' : 'none';
|
|
207
|
+
if (!useCron) { window._plComputedCron = ''; var prev = document.getElementById('pl-cron-preview'); if (prev) prev.textContent = 'Manual trigger only'; return; }
|
|
208
|
+
var hour = parseInt(document.getElementById('pl-pick-hour')?.value || '9', 10);
|
|
209
|
+
var minute = parseInt(document.getElementById('pl-pick-minute')?.value || '0', 10);
|
|
210
|
+
var days = [];
|
|
211
|
+
document.querySelectorAll('.sched-day-pill').forEach(function(btn) { if (btn.classList.contains('active')) days.push(parseInt(btn.dataset.day, 10)); });
|
|
212
|
+
var cron = _pickerToCron(hour, minute, days);
|
|
213
|
+
window._plComputedCron = cron;
|
|
214
|
+
var prev = document.getElementById('pl-cron-preview');
|
|
215
|
+
if (prev) prev.textContent = cron ? '\u2192 ' + _cronToHuman(cron) : '(select at least one day)';
|
|
159
216
|
}
|
|
160
217
|
|
|
161
218
|
async function _submitCreatePipeline() {
|
|
162
219
|
var id = document.getElementById('pl-id')?.value?.trim();
|
|
163
220
|
var title = document.getElementById('pl-title')?.value?.trim();
|
|
164
|
-
var
|
|
221
|
+
var useCron = document.getElementById('pl-use-cron')?.checked;
|
|
222
|
+
var cron = useCron ? (window._plComputedCron || '') : '';
|
|
165
223
|
var stagesRaw = document.getElementById('pl-stages')?.value?.trim();
|
|
166
224
|
if (!id || !title) { alert('ID and title required'); return; }
|
|
167
225
|
var stages;
|
|
@@ -179,4 +237,88 @@ async function _submitCreatePipeline() {
|
|
|
179
237
|
} catch (e) { alert('Error: ' + e.message); openCreatePipelineModal(); }
|
|
180
238
|
}
|
|
181
239
|
|
|
182
|
-
|
|
240
|
+
function openEditPipelineModal(id) {
|
|
241
|
+
var p = _pipelinesData.find(function(x) { return x.id === id; });
|
|
242
|
+
if (!p) return;
|
|
243
|
+
var inputStyle = 'display:block;width:100%;margin-top:4px;padding:6px 8px;background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--text);font-size:var(--text-md);font-family:inherit';
|
|
244
|
+
var pillStyle = 'display:inline-block;padding:4px 10px;margin:2px;border:1px solid var(--border);border-radius:12px;cursor:pointer;font-size:11px;color:var(--text);background:var(--bg);user-select:none;transition:all 0.15s';
|
|
245
|
+
var linkStyle = 'font-size:10px;color:var(--blue);cursor:pointer;text-decoration:underline;margin-right:8px';
|
|
246
|
+
var tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
247
|
+
var hasCron = !!p.trigger?.cron;
|
|
248
|
+
var picker = hasCron ? _parseCronToPicker(p.trigger.cron) : { hour: 9, minute: 0, days: [1,2,3,4,5] };
|
|
249
|
+
|
|
250
|
+
var hourOpts = '';
|
|
251
|
+
for (var h = 0; h < 24; h++) hourOpts += '<option value="' + h + '"' + (h === picker.hour ? ' selected' : '') + '>' + String(h).padStart(2, '0') + '</option>';
|
|
252
|
+
var minOpts = '';
|
|
253
|
+
for (var m = 0; m <= 55; m += 5) minOpts += '<option value="' + m + '"' + (m === picker.minute ? ' selected' : '') + '>' + String(m).padStart(2, '0') + '</option>';
|
|
254
|
+
|
|
255
|
+
var dayOrder = [0, 1, 2, 3, 4, 5, 6];
|
|
256
|
+
var dayLabels = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
|
257
|
+
var dayPills = dayOrder.map(function(d) {
|
|
258
|
+
var active = picker.days.includes(d);
|
|
259
|
+
return '<span class="sched-day-pill' + (active ? ' active' : '') + '" data-day="' + d + '" ' +
|
|
260
|
+
'style="' + pillStyle + (active ? ';background:var(--blue);color:#fff;border-color:var(--blue)' : '') + '" ' +
|
|
261
|
+
'onclick="_toggleDayPill(this);_updatePlCronPreview()">' + dayLabels[d] + '</span>';
|
|
262
|
+
}).join('');
|
|
263
|
+
|
|
264
|
+
window._editPipelineId = id;
|
|
265
|
+
|
|
266
|
+
document.getElementById('modal-title').textContent = 'Edit Pipeline: ' + p.title;
|
|
267
|
+
document.getElementById('modal-body').innerHTML =
|
|
268
|
+
'<div style="display:flex;flex-direction:column;gap:10px">' +
|
|
269
|
+
'<div style="color:var(--muted);font-size:11px">ID: <strong style="color:var(--text)">' + escHtml(id) + '</strong></div>' +
|
|
270
|
+
'<label style="color:var(--text);font-size:var(--text-md)">Title<input id="pl-title" value="' + escHtml(p.title || '') + '" style="' + inputStyle + '"></label>' +
|
|
271
|
+
'<div>' +
|
|
272
|
+
'<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px">' +
|
|
273
|
+
'<label style="color:var(--text);font-size:var(--text-md);margin:0">Schedule</label>' +
|
|
274
|
+
'<label style="font-size:11px;color:var(--muted);cursor:pointer"><input type="checkbox" id="pl-use-cron"' + (hasCron ? ' checked' : '') + ' onchange="_updatePlCronPreview()" style="accent-color:var(--blue)"> Enable automatic trigger</label>' +
|
|
275
|
+
'</div>' +
|
|
276
|
+
'<div id="pl-cron-picker">' +
|
|
277
|
+
'<div style="display:flex;gap:8px;align-items:center">' +
|
|
278
|
+
'<select id="pl-pick-hour" style="' + inputStyle + ';width:auto;display:inline-block" onchange="_updatePlCronPreview()">' + hourOpts + '</select>' +
|
|
279
|
+
'<span style="color:var(--muted)">:</span>' +
|
|
280
|
+
'<select id="pl-pick-minute" style="' + inputStyle + ';width:auto;display:inline-block" onchange="_updatePlCronPreview()">' + minOpts + '</select>' +
|
|
281
|
+
'<span style="font-size:10px;color:var(--muted)">' + escHtml(tz) + '</span>' +
|
|
282
|
+
'</div>' +
|
|
283
|
+
'<div style="margin-top:8px">' + dayPills + '</div>' +
|
|
284
|
+
'<div style="margin-top:6px">' +
|
|
285
|
+
'<span style="' + linkStyle + '" onclick="_quickSelectDays(\'all\');_updatePlCronPreview()">Every day</span>' +
|
|
286
|
+
'<span style="' + linkStyle + '" onclick="_quickSelectDays(\'weekdays\');_updatePlCronPreview()">Weekdays</span>' +
|
|
287
|
+
'<span style="' + linkStyle + '" onclick="_quickSelectDays(\'weekends\');_updatePlCronPreview()">Weekends</span>' +
|
|
288
|
+
'</div>' +
|
|
289
|
+
'<div id="pl-cron-preview" style="margin-top:4px;font-size:11px;color:var(--blue)"></div>' +
|
|
290
|
+
'</div>' +
|
|
291
|
+
'</div>' +
|
|
292
|
+
'<label style="color:var(--text);font-size:var(--text-md)">Stages (JSON array)<textarea id="pl-stages" rows="10" style="' + inputStyle + ';resize:vertical;font-family:Consolas,monospace">' + escHtml(JSON.stringify(p.stages || [], null, 2)) + '</textarea></label>' +
|
|
293
|
+
'<div style="display:flex;justify-content:flex-end;gap:8px;margin-top:4px">' +
|
|
294
|
+
'<button onclick="closeModal()" class="pr-pager-btn">Cancel</button>' +
|
|
295
|
+
'<button onclick="_submitEditPipeline()" style="padding:6px 16px;background:var(--blue);color:#fff;border:none;border-radius:var(--radius-sm);cursor:pointer">Save</button>' +
|
|
296
|
+
'</div>' +
|
|
297
|
+
'</div>';
|
|
298
|
+
document.getElementById('modal-body').style.whiteSpace = 'normal';
|
|
299
|
+
document.getElementById('modal-body').style.fontFamily = '';
|
|
300
|
+
document.getElementById('modal').classList.add('open');
|
|
301
|
+
_updatePlCronPreview();
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
async function _submitEditPipeline() {
|
|
305
|
+
var id = window._editPipelineId;
|
|
306
|
+
if (!id) return;
|
|
307
|
+
var title = document.getElementById('pl-title')?.value?.trim();
|
|
308
|
+
var useCron = document.getElementById('pl-use-cron')?.checked;
|
|
309
|
+
var cron = useCron ? (window._plComputedCron || '') : '';
|
|
310
|
+
var stagesRaw = document.getElementById('pl-stages')?.value?.trim();
|
|
311
|
+
if (!title) { alert('Title required'); return; }
|
|
312
|
+
var stages;
|
|
313
|
+
try { stages = JSON.parse(stagesRaw); } catch (e) { alert('Invalid JSON in stages: ' + e.message); return; }
|
|
314
|
+
if (!Array.isArray(stages) || stages.length === 0) { alert('Stages must be a non-empty array'); return; }
|
|
315
|
+
|
|
316
|
+
var body = { id: id, title: title, stages: stages, trigger: cron ? { cron: cron } : null };
|
|
317
|
+
try {
|
|
318
|
+
var res = await fetch('/api/pipelines/update', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) });
|
|
319
|
+
if (res.ok) { closeModal(); showToast('cmd-toast', 'Pipeline updated', true); refresh(); }
|
|
320
|
+
else { var d = await res.json().catch(function() { return {}; }); alert('Failed: ' + (d.error || 'unknown')); }
|
|
321
|
+
} catch (e) { alert('Error: ' + e.message); }
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
window.MinionsPipelines = { renderPipelines, openPipelineDetail, openCreatePipelineModal, openEditPipelineModal };
|
package/dashboard.js
CHANGED
|
@@ -387,6 +387,7 @@ Available action types:
|
|
|
387
387
|
- **delete-schedule**: Delete a scheduled task. Fields: id.
|
|
388
388
|
- **create-meeting**: Start a team meeting. Fields: title (short meeting name), agenda (detailed text — what agents should investigate/debate, numbered items work best), agents (array of agent IDs), rounds (optional, default 3), project (optional).
|
|
389
389
|
- **set-config**: Update engine settings. Fields: setting (setting name), value (new value). Valid settings: autoApprovePlans (bool), autoDecompose (bool), allowTempAgents (bool), maxConcurrent (number), maxTurns (number). Example: { "type": "set-config", "setting": "autoApprovePlans", "value": true }
|
|
390
|
+
- **edit-pipeline**: Update an existing pipeline. Fields: id (pipeline ID), title (optional), stages (optional, JSON array), trigger (optional, { cron: "minute hour dow" } or null for manual).
|
|
390
391
|
|
|
391
392
|
## Rules
|
|
392
393
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.140",
|
|
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"
|