@yemi33/minions 0.1.199 → 0.1.200

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,13 +1,15 @@
1
1
  # Changelog
2
2
 
3
- ## 0.1.199 (2026-04-02)
3
+ ## 0.1.200 (2026-04-02)
4
4
 
5
5
  ### Engine
6
6
  - engine/ado.js
7
7
  - engine/github.js
8
8
  - engine/lifecycle.js
9
+ - engine/preflight.js
9
10
  - engine/queries.js
10
11
  - engine/shared.js
12
+ - engine/spawn-agent.js
11
13
 
12
14
  ### Dashboard
13
15
  - dashboard.js
@@ -14,26 +14,50 @@ const { execSync } = require('child_process');
14
14
  */
15
15
  function findClaudeBinary() {
16
16
  const searchPaths = [
17
- path.join(process.env.npm_config_prefix || '', 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js'),
18
- path.join(process.env.APPDATA || '', 'npm', 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js'),
17
+ // npm global (npm_config_prefix)
18
+ process.env.npm_config_prefix ? path.join(process.env.npm_config_prefix, 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js') : '',
19
+ // Windows: %APPDATA%\npm
20
+ process.env.APPDATA ? path.join(process.env.APPDATA, 'npm', 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js') : '',
21
+ // Unix global
19
22
  '/usr/local/lib/node_modules/@anthropic-ai/claude-code/cli.js',
20
23
  '/usr/lib/node_modules/@anthropic-ai/claude-code/cli.js',
21
- ];
24
+ // Homebrew (macOS)
25
+ '/opt/homebrew/lib/node_modules/@anthropic-ai/claude-code/cli.js',
26
+ // nvm (current node version)
27
+ path.join(path.dirname(process.execPath), '..', 'lib', 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js'),
28
+ // fnm / volta — sibling to the node binary
29
+ path.join(path.dirname(process.execPath), 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js'),
30
+ ].filter(Boolean);
22
31
  for (const p of searchPaths) {
23
- if (p && fs.existsSync(p)) return p;
32
+ try { if (fs.existsSync(p)) return p; } catch {}
24
33
  }
25
- // Fallback: parse the shell wrapper
34
+ // Fallback: which/where resolve wrapper to cli.js
26
35
  try {
27
- const which = execSync('bash -c "which claude"', { encoding: 'utf8', windowsHide: true, timeout: 5000 }).trim();
28
- const whichNative = which.replace(/^\/([a-zA-Z])\//, (_, d) => d.toUpperCase() + ':/').replace(/\//g, path.sep);
29
- const wrapper = fs.readFileSync(whichNative, 'utf8');
30
- const m = wrapper.match(/node_modules\/@anthropic-ai\/claude-code\/cli\.js/);
31
- if (m) {
32
- const basedir = path.dirname(whichNative);
33
- const resolved = path.join(basedir, 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js');
34
- if (fs.existsSync(resolved)) return resolved;
36
+ const isWin = process.platform === 'win32';
37
+ const cmd = isWin ? 'where claude 2>NUL' : 'which claude 2>/dev/null';
38
+ const which = execSync(cmd, { encoding: 'utf8', windowsHide: true, timeout: 5000 }).trim().split('\n')[0].trim();
39
+ if (which) {
40
+ const whichNative = isWin ? which : which.replace(/^\/([a-zA-Z])\//, (_, d) => d.toUpperCase() + ':/').replace(/\//g, path.sep);
41
+ try {
42
+ const resolved = fs.realpathSync(whichNative);
43
+ if (resolved.endsWith('cli.js') && fs.existsSync(resolved)) return resolved;
44
+ } catch {}
45
+ try {
46
+ const wrapper = fs.readFileSync(whichNative, 'utf8');
47
+ const m = wrapper.match(/node_modules[\\/]@anthropic-ai[\\/]claude-code[\\/]cli\.js/);
48
+ if (m) {
49
+ const candidate = path.join(path.dirname(whichNative), 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js');
50
+ if (fs.existsSync(candidate)) return candidate;
51
+ }
52
+ } catch {}
35
53
  }
36
54
  } catch { /* optional */ }
55
+ // Last resort: npm root -g
56
+ try {
57
+ const globalRoot = execSync('npm root -g', { encoding: 'utf8', windowsHide: true, timeout: 5000 }).trim();
58
+ const candidate = path.join(globalRoot, '@anthropic-ai', 'claude-code', 'cli.js');
59
+ if (fs.existsSync(candidate)) return candidate;
60
+ } catch { /* optional */ }
37
61
  return null;
38
62
  }
39
63
 
@@ -24,31 +24,70 @@ const env = cleanChildEnv();
24
24
 
25
25
  // Resolve claude binary — find the actual JS entry point
26
26
  let claudeBin;
27
+
28
+ // Strategy 1: Known global install locations
29
+ const homeDir = process.env.USERPROFILE || process.env.HOME || '';
27
30
  const searchPaths = [
28
- // npm global install locations (platform-adaptive)
29
- path.join(process.env.npm_config_prefix || '', 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js'),
30
- path.join(process.env.APPDATA || '', 'npm', 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js'),
31
- // Unix global locations
31
+ // npm global (npm_config_prefix)
32
+ process.env.npm_config_prefix ? path.join(process.env.npm_config_prefix, 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js') : '',
33
+ // Windows: %APPDATA%\npm
34
+ process.env.APPDATA ? path.join(process.env.APPDATA, 'npm', 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js') : '',
35
+ // Unix global
32
36
  '/usr/local/lib/node_modules/@anthropic-ai/claude-code/cli.js',
33
37
  '/usr/lib/node_modules/@anthropic-ai/claude-code/cli.js',
34
- ];
38
+ // Homebrew (macOS)
39
+ '/opt/homebrew/lib/node_modules/@anthropic-ai/claude-code/cli.js',
40
+ // nvm (current node version)
41
+ path.join(path.dirname(process.execPath), '..', 'lib', 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js'),
42
+ // fnm / volta — sibling to the node binary
43
+ path.join(path.dirname(process.execPath), 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js'),
44
+ // Local node_modules (if minions is in a project)
45
+ path.join(__dirname, '..', 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js'),
46
+ ].filter(Boolean);
35
47
  for (const p of searchPaths) {
36
- if (p && fs.existsSync(p)) { claudeBin = p; break; }
48
+ try { if (fs.existsSync(p)) { claudeBin = p; break; } } catch {}
37
49
  }
38
- // Fallback: parse the shell wrapper
50
+
51
+ // Strategy 2: Use `which` (Unix) or `where` (Windows) to find the claude wrapper, then resolve cli.js
39
52
  if (!claudeBin) {
40
53
  try {
41
- const which = exec('bash -c "which claude"', { encoding: 'utf8', env, timeout: 10000 }).trim();
42
- const whichNative = which.replace(/^\/([a-zA-Z])\//, (_, d) => d.toUpperCase() + ':/').replace(/\//g, path.sep);
43
- const wrapper = fs.readFileSync(whichNative, 'utf8');
44
- const m = wrapper.match(/node_modules\/@anthropic-ai\/claude-code\/cli\.js/);
45
- if (m) {
46
- const basedir = path.dirname(whichNative);
47
- claudeBin = path.join(basedir, 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js');
54
+ const isWin = process.platform === 'win32';
55
+ const cmd = isWin ? 'where claude 2>NUL' : 'which claude 2>/dev/null';
56
+ const which = exec(cmd, { encoding: 'utf8', env, timeout: 10000 }).trim().split('\n')[0].trim();
57
+ if (which) {
58
+ const whichNative = isWin ? which : which.replace(/^\/([a-zA-Z])\//, (_, d) => d.toUpperCase() + ':/').replace(/\//g, path.sep);
59
+ // The wrapper script or symlink — resolve to cli.js
60
+ try {
61
+ const resolved = fs.realpathSync(whichNative);
62
+ if (resolved.endsWith('cli.js')) {
63
+ claudeBin = resolved;
64
+ } else {
65
+ // Read wrapper script to extract cli.js path
66
+ const wrapper = fs.readFileSync(resolved, 'utf8');
67
+ const m = wrapper.match(/node_modules[\\/]@anthropic-ai[\\/]claude-code[\\/]cli\.js/);
68
+ if (m) claudeBin = path.join(path.dirname(resolved), 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js');
69
+ }
70
+ } catch {
71
+ // Try reading the wrapper directly (may be a batch file on Windows)
72
+ try {
73
+ const wrapper = fs.readFileSync(whichNative, 'utf8');
74
+ const m = wrapper.match(/node_modules[\\/]@anthropic-ai[\\/]claude-code[\\/]cli\.js/);
75
+ if (m) claudeBin = path.join(path.dirname(whichNative), 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js');
76
+ } catch {}
77
+ }
48
78
  }
49
79
  } catch { /* optional */ }
50
80
  }
51
81
 
82
+ // Strategy 3: npm root -g to find global node_modules
83
+ if (!claudeBin) {
84
+ try {
85
+ const globalRoot = exec('npm root -g', { encoding: 'utf8', env, timeout: 10000 }).trim();
86
+ const candidate = path.join(globalRoot, '@anthropic-ai', 'claude-code', 'cli.js');
87
+ if (fs.existsSync(candidate)) claudeBin = candidate;
88
+ } catch { /* optional */ }
89
+ }
90
+
52
91
  // Debug log
53
92
  const tmpDir = path.join(__dirname, 'tmp');
54
93
  if (!fs.existsSync(tmpDir)) fs.mkdirSync(tmpDir, { recursive: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.199",
3
+ "version": "0.1.200",
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"