@yemi33/minions 0.1.613 → 0.1.615
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 +3 -1
- package/engine/cleanup.js +49 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.1.
|
|
3
|
+
## 0.1.615 (2026-04-08)
|
|
4
4
|
|
|
5
5
|
### Features
|
|
6
6
|
- clickable pinned notes and skills with full content + doc-chat
|
|
7
7
|
|
|
8
8
|
### Fixes
|
|
9
|
+
- only kill orphaned processes before worktree removal, not active ones
|
|
10
|
+
- kill process holding worktree lock before removal attempt
|
|
9
11
|
- dedup worktree removal attempts, add Windows rd fallback
|
|
10
12
|
- accurate LLM call timing and agent metrics on engine page
|
|
11
13
|
- worktree count now checks for .git file instead of any directory
|
package/engine/cleanup.js
CHANGED
|
@@ -39,6 +39,53 @@ function worktreeDirMatchesBranch(dirLower, branch) {
|
|
|
39
39
|
return dirLower === branchSlug || dirLower.includes(branchSlug + '-') || dirLower.endsWith('-' + branchSlug);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Kill orphaned processes whose dispatch ID appears in the worktree dir name.
|
|
44
|
+
* Only kills processes NOT in the active dispatch queue — never kills live agents.
|
|
45
|
+
*/
|
|
46
|
+
function _killProcessInWorktree(dir, activeProcesses) {
|
|
47
|
+
const dirLower = dir.toLowerCase();
|
|
48
|
+
const dispatch = getDispatch();
|
|
49
|
+
const activeIds = new Set((dispatch.active || []).map(d => d.id));
|
|
50
|
+
|
|
51
|
+
// Check tracked in-memory processes — only kill if dispatch is no longer active
|
|
52
|
+
for (const [id, info] of activeProcesses.entries()) {
|
|
53
|
+
if (!dirLower.includes(id.toLowerCase().slice(-8))) continue;
|
|
54
|
+
if (activeIds.has(id)) continue; // still active — do not kill
|
|
55
|
+
try { shared.killImmediate(info.proc); } catch {}
|
|
56
|
+
activeProcesses.delete(id);
|
|
57
|
+
log('info', `Killed orphaned process for dispatch ${id} before worktree removal`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Check PID files in engine/tmp/ — only kill if no active dispatch matches
|
|
61
|
+
try {
|
|
62
|
+
const tmpDir = path.join(ENGINE_DIR, 'tmp');
|
|
63
|
+
for (const f of fs.readdirSync(tmpDir)) {
|
|
64
|
+
if (!f.startsWith('pid-') || !f.endsWith('.pid')) continue;
|
|
65
|
+
const pidFileName = f.replace(/^pid-/, '').replace(/\.pid$/, '');
|
|
66
|
+
if (!dirLower.includes(pidFileName.slice(-8))) continue;
|
|
67
|
+
// Verify this PID file's dispatch is not active
|
|
68
|
+
const isActive = [...activeIds].some(id => pidFileName.includes(id.slice(-8)));
|
|
69
|
+
if (isActive) continue; // still active — do not kill
|
|
70
|
+
const pid = parseInt(fs.readFileSync(path.join(tmpDir, f), 'utf8').trim(), 10);
|
|
71
|
+
if (pid > 0) {
|
|
72
|
+
// Verify the process is actually a node/claude process before killing
|
|
73
|
+
try {
|
|
74
|
+
if (process.platform === 'win32') {
|
|
75
|
+
const taskInfo = exec(`tasklist /FI "PID eq ${pid}" /NH`, { encoding: 'utf8', timeout: 3000, windowsHide: true });
|
|
76
|
+
if (!taskInfo.toLowerCase().includes('node')) continue; // not a node process — skip
|
|
77
|
+
exec(`taskkill /F /PID ${pid}`, { stdio: 'pipe', timeout: 5000, windowsHide: true });
|
|
78
|
+
} else {
|
|
79
|
+
process.kill(pid, 'SIGKILL');
|
|
80
|
+
}
|
|
81
|
+
log('info', `Killed orphaned PID ${pid} (${f}) before worktree removal`);
|
|
82
|
+
} catch {} // process may already be dead
|
|
83
|
+
}
|
|
84
|
+
try { fs.unlinkSync(path.join(tmpDir, f)); } catch {}
|
|
85
|
+
}
|
|
86
|
+
} catch {} // tmp dir may not exist
|
|
87
|
+
}
|
|
88
|
+
|
|
42
89
|
// ─── Cleanup Orchestrator ────────────────────────────────────────────────────
|
|
43
90
|
|
|
44
91
|
function runCleanup(config, verbose = false) {
|
|
@@ -264,6 +311,8 @@ function runCleanup(config, verbose = false) {
|
|
|
264
311
|
|
|
265
312
|
if (_attemptedWorktreePaths.has(entry.wtPath)) continue;
|
|
266
313
|
_attemptedWorktreePaths.add(entry.wtPath);
|
|
314
|
+
// Kill any process still running in this worktree before removal
|
|
315
|
+
_killProcessInWorktree(entry.dir, activeProcesses);
|
|
267
316
|
if (shared.removeWorktree(entry.wtPath, root, worktreeRoot)) {
|
|
268
317
|
cleaned.worktrees++;
|
|
269
318
|
if (verbose) console.log(` Removed worktree: ${entry.wtPath}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.615",
|
|
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"
|