@yemi33/minions 0.1.28 → 0.1.29

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,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.29 (2026-03-28)
4
+
5
+ ### Dashboard
6
+ - dashboard.js
7
+
3
8
  ## 0.1.28 (2026-03-28)
4
9
 
5
10
  ### Engine
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.29",
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"