@yemi33/minions 0.1.1079 → 0.1.1081
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 +31 -0
- package/engine/llm.js +2 -0
- package/engine/shared.js +13 -6
- package/engine/spawn-agent.js +39 -35
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.1081 (2026-04-18)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
- seed realActivityMap at spawn time, stamp pid in live-output (#1200)
|
|
7
|
+
|
|
8
|
+
### Fixes
|
|
9
|
+
- avoid no-op work item writes
|
|
10
|
+
- resilient claude binary resolution + surface spawn errors
|
|
11
|
+
- resolve native claude.exe from npm wrapper on Windows
|
|
12
|
+
- cap temp-agent creation at maxConcurrent per tick (#1219)
|
|
13
|
+
- reassign pending items from unspawned temp agents to idle named agents (#1204) (#1212)
|
|
14
|
+
- guard undefined agent in pending dispatch loop (closes #1206) (#1210)
|
|
15
|
+
- improve fallback meeting conclusion
|
|
16
|
+
- remove command center chevron
|
|
17
|
+
- stamp live-output.log stub before spawn (#1198)
|
|
18
|
+
- harden settings save and migrate pr poll config
|
|
19
|
+
|
|
20
|
+
### Other
|
|
21
|
+
- Use PAT for publish merges
|
|
22
|
+
- test(queries): add unit tests for invalidateDispatchCache/getInbox/getAgentCharter (#1214)
|
|
23
|
+
- test(shared): add unit tests for truncateTextBytes/tailTextBytes/execSilent/trackReviewMetric/parseCanonicalPrId (#1215)
|
|
24
|
+
- Fix publish workflow merge
|
|
25
|
+
- chore: raise default meeting round timeout
|
|
26
|
+
- Harden prompt context handling
|
|
27
|
+
- Harden loop watch conversion
|
|
28
|
+
- Add watches sidebar activity badge
|
|
29
|
+
- test(cli): add unit tests for handleCommand, start, stop, kill, spawn (#1191)
|
|
30
|
+
- chore: untrack pipeline files — local config only
|
|
31
|
+
- restore: recover daily-arch-improvement and weekly-dead-code-cleanup pipelines
|
|
32
|
+
- Harden CC stream resilience
|
|
33
|
+
|
|
3
34
|
## 0.1.1079 (2026-04-18)
|
|
4
35
|
|
|
5
36
|
### Features
|
package/engine/llm.js
CHANGED
|
@@ -246,6 +246,7 @@ function callLLM(promptText, sysPromptText, { timeout = 120000, label = 'llm', m
|
|
|
246
246
|
proc.on('error', (err) => {
|
|
247
247
|
clearTimeout(timer);
|
|
248
248
|
for (const f of cleanupFiles) safeUnlink(f);
|
|
249
|
+
console.error(`[LLM] spawn error (${label}): ${err.message}`);
|
|
249
250
|
resolve({ text: '', usage: null, sessionId: null, code: 1, stderr: err.message, raw: '', toolUses: [] });
|
|
250
251
|
});
|
|
251
252
|
});
|
|
@@ -307,6 +308,7 @@ function callLLMStreaming(promptText, sysPromptText, { timeout = 120000, label =
|
|
|
307
308
|
proc.on('error', (err) => {
|
|
308
309
|
clearTimeout(timer);
|
|
309
310
|
for (const f of cleanupFiles) safeUnlink(f);
|
|
311
|
+
console.error(`[LLM-stream] spawn error (${label}): ${err.message}`);
|
|
310
312
|
resolve({ text: '', usage: null, sessionId: null, code: 1, stderr: err.message, raw: '', toolUses: [] });
|
|
311
313
|
});
|
|
312
314
|
});
|
package/engine/shared.js
CHANGED
|
@@ -347,23 +347,30 @@ function withFileLock(lockPath, fn, {
|
|
|
347
347
|
function mutateJsonFileLocked(filePath, mutateFn, {
|
|
348
348
|
defaultValue = {},
|
|
349
349
|
lockRetries,
|
|
350
|
-
lockRetryBackoffMs
|
|
350
|
+
lockRetryBackoffMs,
|
|
351
|
+
skipWriteIfUnchanged = false
|
|
351
352
|
} = {}) {
|
|
352
353
|
const lockPath = `${filePath}.lock`;
|
|
353
354
|
const retries = lockRetries ?? ENGINE_DEFAULTS.lockRetries;
|
|
354
355
|
const retryBackoffMs = lockRetryBackoffMs ?? ENGINE_DEFAULTS.lockRetryBackoffMs;
|
|
355
356
|
return withFileLock(lockPath, () => {
|
|
357
|
+
const fileExists = fs.existsSync(filePath);
|
|
356
358
|
let data = safeJson(filePath);
|
|
359
|
+
const parsedInvalid = fileExists && data === null;
|
|
357
360
|
if (data === null || typeof data !== 'object') data = Array.isArray(defaultValue) ? [...defaultValue] : { ...defaultValue };
|
|
358
|
-
|
|
359
|
-
const backupPath = filePath + '.backup';
|
|
360
|
-
try { if (fs.existsSync(filePath)) fs.copyFileSync(filePath, backupPath); } catch { /* backup is best-effort */ }
|
|
361
|
+
const beforeSerialized = skipWriteIfUnchanged ? JSON.stringify(data) : null;
|
|
361
362
|
if (path.basename(filePath) === 'pull-requests.json' && Array.isArray(data)) {
|
|
362
363
|
normalizePrRecords(data, resolveProjectForPrPath(filePath));
|
|
363
364
|
}
|
|
364
365
|
const next = mutateFn(data);
|
|
365
366
|
const finalData = next === undefined ? data : next;
|
|
366
|
-
|
|
367
|
+
const shouldWrite = !skipWriteIfUnchanged || parsedInvalid || JSON.stringify(finalData) !== beforeSerialized;
|
|
368
|
+
if (shouldWrite) {
|
|
369
|
+
// Back up last-known-good state before mutation (best-effort)
|
|
370
|
+
const backupPath = filePath + '.backup';
|
|
371
|
+
try { if (fileExists) fs.copyFileSync(filePath, backupPath); } catch { /* backup is best-effort */ }
|
|
372
|
+
safeWrite(filePath, finalData);
|
|
373
|
+
}
|
|
367
374
|
return finalData;
|
|
368
375
|
}, { retries, retryBackoffMs });
|
|
369
376
|
}
|
|
@@ -1351,7 +1358,7 @@ function mutateWorkItems(filePath, mutator) {
|
|
|
1351
1358
|
return mutateJsonFileLocked(filePath, (data) => {
|
|
1352
1359
|
if (!Array.isArray(data)) data = [];
|
|
1353
1360
|
return mutator(data) || data;
|
|
1354
|
-
}, { defaultValue: [] });
|
|
1361
|
+
}, { defaultValue: [], skipWriteIfUnchanged: true });
|
|
1355
1362
|
}
|
|
1356
1363
|
|
|
1357
1364
|
/**
|
package/engine/spawn-agent.js
CHANGED
|
@@ -36,55 +36,59 @@ if (caps?.claudeBin && fs.existsSync(caps.claudeBin)) {
|
|
|
36
36
|
_cacheHit = true;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
// Strategy 1:
|
|
39
|
+
// Strategy 1: Find `claude` on PATH, then resolve to the actual binary
|
|
40
|
+
// Don't parse wrapper scripts — probe known binary locations relative to the wrapper's directory.
|
|
40
41
|
if (!claudeBin) try {
|
|
41
42
|
const isWin = process.platform === 'win32';
|
|
42
43
|
const cmd = isWin ? 'where claude 2>NUL' : 'which claude 2>/dev/null';
|
|
43
44
|
const which = exec(cmd, { encoding: 'utf8', env, timeout: 10000 }).trim().split('\n')[0].trim();
|
|
44
45
|
if (which) {
|
|
45
46
|
const whichNative = isWin ? which : which.replace(/^\/([a-zA-Z])\//, (_, d) => d.toUpperCase() + ':/').replace(/\//g, path.sep);
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
// npm wrapper may reference native binary (claude.exe) instead of cli.js
|
|
56
|
-
if (!claudeBin) {
|
|
57
|
-
const exeMatch = content.match(/node_modules[\\/]@anthropic-ai[\\/]claude-code[\\/]bin[\\/]claude(?:\.exe)?/);
|
|
58
|
-
if (exeMatch) {
|
|
59
|
-
const candidate = path.join(path.dirname(whichNative), 'node_modules', '@anthropic-ai', 'claude-code', 'bin', isWin ? 'claude.exe' : 'claude');
|
|
60
|
-
if (fs.existsSync(candidate)) { claudeBin = candidate; claudeIsNative = true; }
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
} catch {
|
|
64
|
-
// Can't read as text — it's a compiled binary
|
|
65
|
-
}
|
|
66
|
-
if (!claudeBin) {
|
|
67
|
-
// Native binary or wrapper without cli.js reference — use directly
|
|
68
|
-
claudeBin = whichNative;
|
|
47
|
+
const baseDir = path.dirname(whichNative);
|
|
48
|
+
const ccPkg = path.join(baseDir, 'node_modules', '@anthropic-ai', 'claude-code');
|
|
49
|
+
|
|
50
|
+
// Probe in priority order: native binary > cli.js > wrapper itself
|
|
51
|
+
const nativeBin = path.join(ccPkg, 'bin', isWin ? 'claude.exe' : 'claude');
|
|
52
|
+
const cliJs = path.join(ccPkg, 'cli.js');
|
|
53
|
+
|
|
54
|
+
if (fs.existsSync(nativeBin)) {
|
|
55
|
+
claudeBin = nativeBin;
|
|
69
56
|
claudeIsNative = true;
|
|
57
|
+
} else if (fs.existsSync(cliJs)) {
|
|
58
|
+
claudeBin = cliJs;
|
|
59
|
+
} else {
|
|
60
|
+
// Not an npm wrapper — check if the path itself is a native binary
|
|
61
|
+
// On Windows, only trust .exe files; shell scripts can't be spawned directly
|
|
62
|
+
const ext = path.extname(whichNative).toLowerCase();
|
|
63
|
+
if (!isWin || ext === '.exe') {
|
|
64
|
+
claudeBin = whichNative;
|
|
65
|
+
claudeIsNative = true;
|
|
66
|
+
}
|
|
70
67
|
}
|
|
71
68
|
}
|
|
72
69
|
} catch { /* optional */ }
|
|
73
70
|
|
|
74
71
|
// Strategy 2: Known node_modules locations (npm global installs)
|
|
72
|
+
// Check for native binary first, then cli.js
|
|
75
73
|
if (!claudeBin) {
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
process.env.
|
|
79
|
-
'
|
|
80
|
-
'/usr/lib/node_modules/@anthropic-ai/claude-code
|
|
81
|
-
'/
|
|
82
|
-
|
|
83
|
-
path.join(path.dirname(process.execPath), 'node_modules', '@anthropic-ai', 'claude-code'
|
|
84
|
-
path.join(
|
|
74
|
+
const isWin = process.platform === 'win32';
|
|
75
|
+
const prefixes = [
|
|
76
|
+
process.env.npm_config_prefix ? path.join(process.env.npm_config_prefix, 'node_modules', '@anthropic-ai', 'claude-code') : '',
|
|
77
|
+
process.env.APPDATA ? path.join(process.env.APPDATA, 'npm', 'node_modules', '@anthropic-ai', 'claude-code') : '',
|
|
78
|
+
'/usr/local/lib/node_modules/@anthropic-ai/claude-code',
|
|
79
|
+
'/usr/lib/node_modules/@anthropic-ai/claude-code',
|
|
80
|
+
'/opt/homebrew/lib/node_modules/@anthropic-ai/claude-code',
|
|
81
|
+
path.join(path.dirname(process.execPath), '..', 'lib', 'node_modules', '@anthropic-ai', 'claude-code'),
|
|
82
|
+
path.join(path.dirname(process.execPath), 'node_modules', '@anthropic-ai', 'claude-code'),
|
|
83
|
+
path.join(__dirname, '..', 'node_modules', '@anthropic-ai', 'claude-code'),
|
|
85
84
|
].filter(Boolean);
|
|
86
|
-
for (const
|
|
87
|
-
try {
|
|
85
|
+
for (const pkg of prefixes) {
|
|
86
|
+
try {
|
|
87
|
+
const nativeBin = path.join(pkg, 'bin', isWin ? 'claude.exe' : 'claude');
|
|
88
|
+
if (fs.existsSync(nativeBin)) { claudeBin = nativeBin; claudeIsNative = true; break; }
|
|
89
|
+
const cliJs = path.join(pkg, 'cli.js');
|
|
90
|
+
if (fs.existsSync(cliJs)) { claudeBin = cliJs; break; }
|
|
91
|
+
} catch {}
|
|
88
92
|
}
|
|
89
93
|
}
|
|
90
94
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1081",
|
|
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"
|