@yemi33/minions 0.1.28 → 0.1.30

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,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.30 (2026-03-28)
4
+
5
+ ### Dashboard
6
+ - dashboard/js/render-work-items.js
7
+
8
+ ## 0.1.29 (2026-03-28)
9
+
10
+ ### Dashboard
11
+ - dashboard.js
12
+
3
13
  ## 0.1.28 (2026-03-28)
4
14
 
5
15
  ### Engine
@@ -226,20 +226,42 @@ async function retryWorkItem(id, source) {
226
226
  function wiPrev() { if (wiPage > 0) { wiPage--; renderWorkItems(allWorkItems); } }
227
227
  function wiNext() { const tp = Math.ceil(allWorkItems.length / WI_PER_PAGE); if (wiPage < tp-1) { wiPage++; renderWorkItems(allWorkItems); } }
228
228
 
229
+ let _feedbackRating = null;
229
230
  function feedbackWorkItem(id, source) {
231
+ _feedbackRating = null;
230
232
  document.getElementById('modal-title').textContent = 'Feedback on ' + id;
231
233
  document.getElementById('modal-body').innerHTML =
232
- '<div style="display:flex;flex-direction:column;gap:16px;align-items:center">' +
233
- '<div style="display:flex;gap:24px">' +
234
- '<button onclick="submitFeedback(\'' + escHtml(id) + '\',\'' + escHtml(source) + '\',\'up\')" style="font-size:40px;background:none;border:2px solid var(--border);border-radius:12px;padding:16px 24px;cursor:pointer;transition:all 0.2s" onmouseover="this.style.borderColor=\'var(--green)\'" onmouseout="this.style.borderColor=\'var(--border)\'">&#x1F44D;</button>' +
235
- '<button onclick="submitFeedback(\'' + escHtml(id) + '\',\'' + escHtml(source) + '\',\'down\')" style="font-size:40px;background:none;border:2px solid var(--border);border-radius:12px;padding:16px 24px;cursor:pointer;transition:all 0.2s" onmouseover="this.style.borderColor=\'var(--red)\'" onmouseout="this.style.borderColor=\'var(--border)\'">&#x1F44E;</button>' +
234
+ '<div style="display:flex;flex-direction:column;gap:16px">' +
235
+ '<div style="display:flex;gap:16px;justify-content:center">' +
236
+ '<button id="fb-up" onclick="_selectRating(\'up\')" style="font-size:36px;background:none;border:2px solid var(--border);border-radius:12px;padding:12px 20px;cursor:pointer;transition:all 0.2s">&#x1F44D;</button>' +
237
+ '<button id="fb-down" onclick="_selectRating(\'down\')" style="font-size:36px;background:none;border:2px solid var(--border);border-radius:12px;padding:12px 20px;cursor:pointer;transition:all 0.2s">&#x1F44E;</button>' +
238
+ '</div>' +
239
+ '<textarea id="feedback-comment" rows="3" style="width:100%;padding:8px;background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--text);font-family:inherit;resize:vertical" placeholder="What was good or needs improvement?"></textarea>' +
240
+ '<div style="display:flex;justify-content:flex-end;gap:8px">' +
241
+ '<button onclick="closeModal()" class="pr-pager-btn">Cancel</button>' +
242
+ '<button id="fb-send" onclick="submitFeedback(\'' + escHtml(id) + '\',\'' + escHtml(source) + '\')" style="padding:6px 16px;background:var(--surface2);color:var(--muted);border:1px solid var(--border);border-radius:var(--radius-sm);cursor:not-allowed" disabled>Select rating first</button>' +
236
243
  '</div>' +
237
- '<textarea id="feedback-comment" rows="3" style="width:100%;padding:8px;background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--text);font-family:inherit;resize:vertical" placeholder="Optional: what was good or needs improvement?"></textarea>' +
238
244
  '</div>';
239
245
  document.getElementById('modal').classList.add('open');
240
246
  }
247
+ function _selectRating(r) {
248
+ _feedbackRating = r;
249
+ document.getElementById('fb-up').style.borderColor = r === 'up' ? 'var(--green)' : 'var(--border)';
250
+ document.getElementById('fb-up').style.background = r === 'up' ? 'rgba(63,185,80,0.1)' : 'none';
251
+ document.getElementById('fb-down').style.borderColor = r === 'down' ? 'var(--red)' : 'var(--border)';
252
+ document.getElementById('fb-down').style.background = r === 'down' ? 'rgba(248,81,73,0.1)' : 'none';
253
+ const btn = document.getElementById('fb-send');
254
+ btn.disabled = false;
255
+ btn.style.background = 'var(--blue)';
256
+ btn.style.color = '#fff';
257
+ btn.style.cursor = 'pointer';
258
+ btn.style.borderColor = 'var(--blue)';
259
+ btn.textContent = 'Send Feedback';
260
+ }
241
261
 
242
- async function submitFeedback(id, source, rating) {
262
+ async function submitFeedback(id, source) {
263
+ const rating = _feedbackRating;
264
+ if (!rating) { alert('Please select a rating first'); return; }
243
265
  const comment = document.getElementById('feedback-comment')?.value || '';
244
266
  try {
245
267
  const res = await fetch('/api/work-items/feedback', {
package/dashboard.js CHANGED
@@ -596,6 +596,7 @@ function jsonReply(res, code, data, req) {
596
596
  */
597
597
  function cleanDispatchEntries(matchFn) {
598
598
  const dispatchPath = path.join(MINIONS_DIR, 'engine', 'dispatch.json');
599
+ const engineDir = path.join(MINIONS_DIR, 'engine');
599
600
  try {
600
601
  let removed = 0;
601
602
  mutateJsonFileLocked(dispatchPath, (dispatch) => {
@@ -606,16 +607,18 @@ function cleanDispatchEntries(matchFn) {
606
607
  const before = dispatch[queue].length;
607
608
  if (queue === 'active') {
608
609
  for (const d of dispatch[queue]) {
609
- if (matchFn(d) && d.agent) {
610
- const statusPath = path.join(MINIONS_DIR, 'agents', d.agent, 'status.json');
611
- try {
612
- const status = JSON.parse(safeRead(statusPath) || '{}');
613
- if (status.pid) try { process.kill(status.pid, 'SIGTERM'); } catch {}
614
- status.status = 'idle';
615
- delete status.currentTask;
616
- safeWrite(statusPath, status);
617
- } catch {}
618
- }
610
+ if (!matchFn(d)) continue;
611
+ // Kill the running agent process via PID file
612
+ const pidFile = path.join(engineDir, `pid-${d.id}.pid`);
613
+ try {
614
+ const pid = parseInt(fs.readFileSync(pidFile, 'utf8').trim());
615
+ if (pid) process.kill(pid, 'SIGTERM');
616
+ } catch {}
617
+ try { fs.unlinkSync(pidFile); } catch {}
618
+ // Clean up temp prompt files
619
+ try { fs.unlinkSync(path.join(engineDir, 'tmp', `prompt-${d.id}.md`)); } catch {}
620
+ try { fs.unlinkSync(path.join(engineDir, 'tmp', `sysprompt-${d.id}.md`)); } catch {}
621
+ try { fs.unlinkSync(path.join(engineDir, 'tmp', `sysprompt-${d.id}.md.tmp`)); } catch {}
619
622
  }
620
623
  }
621
624
  dispatch[queue] = dispatch[queue].filter(d => !matchFn(d));
@@ -814,15 +817,24 @@ const server = http.createServer(async (req, res) => {
814
817
  safeWrite(wiPath, items);
815
818
 
816
819
  // Clean dispatch entries + kill running agent
817
- const sourcePrefix = (!source || source === 'central') ? 'central-work-' : `work-${source}-`;
818
- const dispatchKey = sourcePrefix + id;
819
- cleanDispatchEntries(d =>
820
- d.meta?.dispatchKey === dispatchKey ||
821
- (d.meta?.parentKey && d.meta.parentKey === dispatchKey) ||
822
- d.meta?.item?.id === id
820
+ const dispatchRemoved = cleanDispatchEntries(d =>
821
+ d.meta?.item?.id === id ||
822
+ d.meta?.dispatchKey?.endsWith(id)
823
823
  );
824
824
 
825
- return jsonReply(res, 200, { ok: true, id });
825
+ // Clean cooldown entries so item can be re-created immediately
826
+ try {
827
+ const cooldownPath = path.join(MINIONS_DIR, 'engine', 'cooldowns.json');
828
+ const cooldowns = JSON.parse(safeRead(cooldownPath) || '{}');
829
+ let cleaned = false;
830
+ for (const key of Object.keys(cooldowns)) {
831
+ if (key.includes(id)) { delete cooldowns[key]; cleaned = true; }
832
+ }
833
+ if (cleaned) safeWrite(cooldownPath, cooldowns);
834
+ } catch {}
835
+
836
+ invalidateStatusCache();
837
+ return jsonReply(res, 200, { ok: true, id, dispatchRemoved });
826
838
  } catch (e) { return jsonReply(res, 400, { error: e.message }); }
827
839
  }
828
840
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.28",
3
+ "version": "0.1.30",
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"