@yemi33/minions 0.1.61 → 0.1.63

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 CHANGED
@@ -1,5 +1,38 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.63 (2026-03-31)
4
+
5
+ ### Engine
6
+ - engine/scheduler.js
7
+
8
+ ## 0.1.62 (2026-03-30)
9
+
10
+ ### Dashboard
11
+ - dashboard/js/command-center.js
12
+ - dashboard/js/command-history.js
13
+ - dashboard/js/command-input.js
14
+ - dashboard/js/command-parser.js
15
+ - dashboard/js/detail-panel.js
16
+ - dashboard/js/live-stream.js
17
+ - dashboard/js/modal-qa.js
18
+ - dashboard/js/modal.js
19
+ - dashboard/js/refresh.js
20
+ - dashboard/js/render-agents.js
21
+ - dashboard/js/render-dispatch.js
22
+ - dashboard/js/render-inbox.js
23
+ - dashboard/js/render-kb.js
24
+ - dashboard/js/render-other.js
25
+ - dashboard/js/render-pinned.js
26
+ - dashboard/js/render-plans.js
27
+ - dashboard/js/render-prd.js
28
+ - dashboard/js/render-prs.js
29
+ - dashboard/js/render-schedules.js
30
+ - dashboard/js/render-skills.js
31
+ - dashboard/js/render-work-items.js
32
+ - dashboard/js/settings.js
33
+ - dashboard/js/state.js
34
+ - dashboard/js/utils.js
35
+
3
36
  ## 0.1.61 (2026-03-30)
4
37
 
5
38
  ### Engine
@@ -378,3 +378,5 @@ async function ccExecuteAction(action) {
378
378
  msgs.scrollTop = msgs.scrollHeight;
379
379
  refresh();
380
380
  }
381
+
382
+ window.MinionsCC = { toggleCommandCenter, ccNewSession, ccRestoreMessages, ccSaveState, ccUpdateSessionIndicator, ccAddMessage, ccSend, ccExecuteAction };
@@ -68,3 +68,5 @@ function timeSinceStr(date) {
68
68
  if (s < 86400) return Math.floor(s / 3600) + 'h ago';
69
69
  return Math.floor(s / 86400) + 'd ago';
70
70
  }
71
+
72
+ window.MinionsCmdHistory = { cmdGetHistory, cmdSaveHistory, cmdShowHistory, cmdResubmit, timeSinceStr };
@@ -266,3 +266,5 @@ function cmdInsertPopupItem(id) {
266
266
  cmdHidePopup();
267
267
  cmdRenderMeta();
268
268
  }
269
+
270
+ window.MinionsCmdInput = { cmdAutoResize, cmdUpdateHighlight, syncHighlightScroll, cmdInputChanged, cmdKeyDown, cmdSubmit, cmdRenderMeta, cmdShowMentions, cmdShowProjects, cmdHidePopup, cmdInsertPopupItem };
@@ -127,3 +127,5 @@ function cmdParseInput(raw) {
127
127
 
128
128
  return result;
129
129
  }
130
+
131
+ window.MinionsCmdParser = { cmdUpdateAgentList, cmdUpdateProjectList, showToast, detectWorkItemType, cmdParseInput };
@@ -105,3 +105,5 @@ function renderDetailContent(detail, tab) {
105
105
  el.innerHTML = '<div class="section">' + escHtml(detail.outputLog || 'No output log. The coordinator will save agent output here when tasks complete.') + '</div>';
106
106
  }
107
107
  }
108
+
109
+ window.MinionsDetail = { closeDetail, renderDetailTabs, switchTab, renderDetailContent };
@@ -157,3 +157,5 @@ async function sendSteering() {
157
157
  }
158
158
  } catch (e) { alert('Error: ' + e.message); }
159
159
  }
160
+
161
+ window.MinionsLive = { renderLiveChatMessage, startLiveStream, stopLiveStream, startLivePolling, stopLivePolling, refreshLiveOutput, sendSteering };
@@ -307,3 +307,5 @@ async function qaReplacePrd(planFile) {
307
307
  const btn = document.getElementById('qa-generate-prd-btn');
308
308
  if (btn) btn.innerHTML = '<span style="color:var(--orange);font-size:12px">Replacing PRD — old items paused, agent regenerating from revised plan.</span>';
309
309
  }
310
+
311
+ window.MinionsQA = { showModalQa, modalAskAboutSelection, clearQaSelection, clearQaConversation, modalSend, qaNewPrd, qaReplacePrd };
@@ -129,3 +129,5 @@ function renderArchiveButtons(archives) {
129
129
  '<button class="archive-btn" onclick="openArchive(' + i + ')">Archived: ' + escHtml(a.version) + ' (' + a.total + ' items)</button>'
130
130
  ).join(' ');
131
131
  }
132
+
133
+ window.MinionsModal = { closeModal, copyModalContent, showNotifBadge, clearNotifBadge, restoreNotifBadges, findCardForFile, renderArchiveButtons };
@@ -83,3 +83,5 @@ try {
83
83
  const _hotReload = new EventSource('/api/hot-reload');
84
84
  _hotReload.onmessage = (e) => { if (e.data === 'reload') location.reload(); };
85
85
  } catch { /* expected */ }
86
+
87
+ window.MinionsRefresh = { refresh };
@@ -42,3 +42,5 @@ async function openAgentDetail(id) {
42
42
  document.getElementById('detail-overlay').classList.add('open');
43
43
  document.getElementById('detail-panel').classList.add('open');
44
44
  }
45
+
46
+ window.MinionsAgents = { renderAgents, openAgentDetail };
@@ -169,3 +169,5 @@ async function showErrorDetails(agentId, reason, task) {
169
169
  document.getElementById('modal-body').textContent = 'Reason: ' + reason + '\n\n(Could not load agent output)';
170
170
  }
171
171
  }
172
+
173
+ window.MinionsDispatch = { renderEngineStatus, renderEngineAlert, renderDispatch, renderEngineLog, shortTime, showErrorDetails };
@@ -198,3 +198,5 @@ async function doPromoteToKB(name, category) {
198
198
  }
199
199
  } catch (e) { alert('Error: ' + e.message); }
200
200
  }
201
+
202
+ window.MinionsInbox = { renderInbox, promoteToKB, renderNotes, openNotesModal, modalToggleEdit, modalSaveEdit, modalCancelEdit, deleteInboxItem, openInboxInExplorer, openQuickNoteModal, submitQuickNote, doPromoteToKB };
@@ -162,3 +162,5 @@ async function kbOpenItem(category, file) {
162
162
  console.error('Failed to load KB item:', e);
163
163
  }
164
164
  }
165
+
166
+ window.MinionsKb = { refreshKnowledgeBase, renderKnowledgeBase, kbSetTab, kbSweep, openCreateKbModal, submitKbEntry, kbOpenItem };
@@ -180,3 +180,5 @@ function renderTokenUsage(metrics) {
180
180
 
181
181
  el.innerHTML = html;
182
182
  }
183
+
184
+ window.MinionsOther = { renderProjects, renderMcpServers, renderMetrics, renderTokenUsage };
@@ -51,3 +51,5 @@ async function removePinnedNote(title) {
51
51
  refresh();
52
52
  } catch (e) { alert('Error: ' + e.message); }
53
53
  }
54
+
55
+ window.MinionsPinned = { renderPinned, openPinNoteModal, submitPinnedNote, removePinnedNote };
@@ -629,3 +629,5 @@ async function triggerVerify(file) {
629
629
  }
630
630
  } catch (e) { alert('Error: ' + e.message); }
631
631
  }
632
+
633
+ window.MinionsPlans = { openCreatePlanModal, refreshPlans, derivePlanStatus, renderPlans, openArchivedPlansModal, qaDisablePrdButtons, showPlanVersionActions, qaJustSave, planExecute, planSubmitRevise, planShowRevise, planHideRevise, planView, planApprove, planDelete, planPause, planReject, planDiscuss, planOpenInDocChat, planRegeneratePRD, openVerifyGuide, triggerVerify };
@@ -716,3 +716,5 @@ function openArchive(i) {
716
716
  document.getElementById('modal-body').style.whiteSpace = 'normal';
717
717
  document.getElementById('modal').classList.add('open');
718
718
  }
719
+
720
+ window.MinionsPrd = { renderPrd, renderPrdProgress, openArchivedPrdModal, showArchivedPrdDetail, prdItemEdit, prdItemSave, prdItemRemove, prdItemRequeue, prdRegenerate, openArchive };
@@ -143,3 +143,5 @@ async function _submitLinkPr() {
143
143
  }
144
144
  } catch (e) { alert('Error: ' + e.message); }
145
145
  }
146
+
147
+ window.MinionsPrs = { prRow, prTableHtml, renderPrs, prPrev, prNext, openAllPrs, openModal, openAddPrModal };
@@ -156,3 +156,5 @@ async function deleteSchedule(id) {
156
156
  }
157
157
  } catch (e) { alert('Delete error: ' + e.message); }
158
158
  }
159
+
160
+ window.MinionsSchedules = { renderSchedules, openCreateScheduleModal, openEditScheduleModal, submitSchedule, toggleScheduleEnabled, deleteSchedule };
@@ -87,3 +87,5 @@ function openSkill(file, source, dir) {
87
87
  })
88
88
  .catch(() => {});
89
89
  }
90
+
91
+ window.MinionsSkills = { renderSkills, openSkill };
@@ -396,3 +396,5 @@ function openAllWorkItems() {
396
396
  document.getElementById('modal-body').style.whiteSpace = 'normal';
397
397
  document.getElementById('modal').classList.add('open');
398
398
  }
399
+
400
+ window.MinionsWork = { wiRow, renderWorkItems, editWorkItem, submitWorkItemEdit, deleteWorkItem, archiveWorkItem, toggleWorkItemArchive, retryWorkItem, wiPrev, wiNext, feedbackWorkItem, submitFeedback, openCreateWorkItemModal, openWorkItemDetail, openAllWorkItems };
@@ -151,3 +151,5 @@ async function addProject() {
151
151
  refresh();
152
152
  } catch (e) { alert('Error: ' + e.message); }
153
153
  }
154
+
155
+ window.MinionsSettings = { openSettings, saveSettings, addProject };
@@ -82,3 +82,5 @@ function rerenderPrdFromCache() {
82
82
  if (!window._lastStatus || !window._lastStatus.prdProgress) return;
83
83
  renderPrd(window._lastStatus.prd, window._lastStatus.prdProgress);
84
84
  }
85
+
86
+ window.MinionsState = { getPageFromUrl, switchPage, getPrdRequeueState, setPrdRequeueState, clearPrdRequeueState, prunePrdRequeueState, rerenderPrdFromCache };
@@ -40,3 +40,5 @@ function copyLlmText(btn) {
40
40
  btn.innerHTML = '&#10003;';
41
41
  setTimeout(() => { btn.innerHTML = '&#x2398;'; }, 1500);
42
42
  }
43
+
44
+ window.MinionsUtils = { wakeEngine, escHtml, normalizePlanFile, timeAgo, statusColor, llmCopyBtn, copyLlmText };
@@ -1,24 +1,24 @@
1
1
  /**
2
- * engine/scheduler.js Cron-style scheduled task discovery.
3
- * Zero dependencies uses only Node.js built-ins.
2
+ * engine/scheduler.js -- Cron-style scheduled task discovery.
3
+ * Zero dependencies -- uses only Node.js built-ins.
4
4
  *
5
5
  * Config schema:
6
6
  * config.schedules: Array<{
7
- * id: string, unique schedule ID
8
- * cron: string, simplified cron: "minute hour dayOfWeek" (0=Sun..6=Sat)
9
- * type: string, work item type (implement, test, explore, ask, etc.)
10
- * title: string, work item title
7
+ * id: string, -- unique schedule ID
8
+ * cron: string, -- simplified cron: "minute hour dayOfWeek" (0=Sun..6=Sat)
9
+ * type: string, -- work item type (implement, test, explore, ask, etc.)
10
+ * title: string, -- work item title
11
11
  * description?: string,
12
- * project?: string, target project name
13
- * agent?: string, preferred agent ID
14
- * enabled?: boolean default true
12
+ * project?: string, -- target project name
13
+ * agent?: string, -- preferred agent ID
14
+ * enabled?: boolean -- default true
15
15
  * }>
16
16
  *
17
17
  * Cron field syntax:
18
- * * every value
19
- * N exact value (e.g., "0" = minute 0, "2" = 2am, "1" = Monday)
20
- * N,M multiple values (e.g., "1,3,5" = Mon/Wed/Fri)
21
- * * /N every Nth value (e.g., "* /15" = every 15 minutes) [no space formatting only]
18
+ * * -- every value
19
+ * N -- exact value (e.g., "0" = minute 0, "2" = 2am, "1" = Monday)
20
+ * N,M -- multiple values (e.g., "1,3,5" = Mon/Wed/Fri)
21
+ * * /N -- every Nth value (e.g., "* /15" = every 15 minutes) [no space -- formatting only]
22
22
  */
23
23
 
24
24
  const fs = require('fs');
@@ -28,13 +28,9 @@ const { safeJson, safeWrite, mutateJsonFileLocked } = shared;
28
28
 
29
29
  const SCHEDULE_RUNS_PATH = path.join(__dirname, 'schedule-runs.json');
30
30
 
31
- /**
32
- * Parse a single cron field into a matcher function.
33
- * @param {string} field e.g., "*", "5", "1,3,5", "*/15"
34
- * @param {number} min — minimum valid value (0 for minute/dow, 0 for hour)
35
- * @param {number} max — maximum valid value (59 for minute, 23 for hour, 6 for dow)
36
- * @returns {function(number): boolean}
37
- */
31
+ // Parse a single cron field into a matcher function.
32
+ // field: e.g., "*", "5", "1,3,5", "*/15"
33
+ // min/max: valid range (0-59 for minute, 0-23 for hour, 0-6 for dow)
38
34
  function parseCronField(field, min, max) {
39
35
  field = field.trim();
40
36
  if (field === '*') return () => true;
@@ -59,11 +55,9 @@ function parseCronField(field, min, max) {
59
55
  return () => false;
60
56
  }
61
57
 
62
- /**
63
- * Parse a 3-field cron expression: "minute hour dayOfWeek"
64
- * @param {string} expr — e.g., "0 2 *" (2am daily), "0 9 1" (9am Monday), "*/30 * *" (every 30 min)
65
- * @returns {{ matches: function(Date): boolean }} or null if invalid
66
- */
58
+ // Parse a 3-field cron expression: "minute hour dayOfWeek"
59
+ // expr: e.g., "0 2 *" (2am daily), "0 9 1" (9am Monday), "*/30 * *" (every 30 min)
60
+ // Returns { matches(date) } or null if invalid
67
61
  function parseCronExpr(expr) {
68
62
  if (!expr || typeof expr !== 'string') return null;
69
63
  const parts = expr.trim().split(/\s+/);
@@ -86,7 +80,7 @@ function parseCronExpr(expr) {
86
80
  * Check if a schedule should fire now, given its last run time.
87
81
  * Prevents double-firing within the same minute window.
88
82
  * @param {{ cron: string }} schedule
89
- * @param {string|null} lastRunAt ISO timestamp of last run
83
+ * @param {string|null} lastRunAt -- ISO timestamp of last run
90
84
  * @returns {boolean}
91
85
  */
92
86
  function shouldRunNow(schedule, lastRunAt) {
@@ -108,8 +102,8 @@ function shouldRunNow(schedule, lastRunAt) {
108
102
 
109
103
  /**
110
104
  * Discover work items from configured schedules.
111
- * @param {object} config full config object
112
- * @returns {Array<object>} work items to create
105
+ * @param {object} config -- full config object
106
+ * @returns {Array<object>} -- work items to create
113
107
  */
114
108
  function discoverScheduledWork(config) {
115
109
  const schedules = config.schedules;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.61",
3
+ "version": "0.1.63",
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"