@yemi33/minions 0.1.202 → 0.1.203
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 +5 -0
- package/minions.js +41 -18
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/minions.js
CHANGED
|
@@ -129,17 +129,20 @@ function buildPrUrlBase({ repoHost, org, project, repoName }) {
|
|
|
129
129
|
if (repoHost === 'github') {
|
|
130
130
|
return org && repoName ? `https://github.com/${org}/${repoName}/pull/` : '';
|
|
131
131
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
132
|
+
if (repoHost === 'ado' && org && project && repoName) {
|
|
133
|
+
return `https://dev.azure.com/${org}/${project}/_git/${repoName}/pullrequest/`;
|
|
134
|
+
}
|
|
135
|
+
return '';
|
|
135
136
|
}
|
|
136
137
|
|
|
137
138
|
function buildProjectEntry({ name, description, localPath, repoHost, repositoryId, org, project, repoName, mainBranch }) {
|
|
139
|
+
// Sanitize name for use as directory name in projects/<name>/
|
|
140
|
+
const safeName = (name || 'project').replace(/[^a-zA-Z0-9._-]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '').slice(0, 60) || 'project';
|
|
138
141
|
return {
|
|
139
|
-
name,
|
|
142
|
+
name: safeName,
|
|
140
143
|
description: description || '',
|
|
141
144
|
localPath: (localPath || '').replace(/\\/g, '/'),
|
|
142
|
-
repoHost: repoHost || '
|
|
145
|
+
repoHost: repoHost || 'github',
|
|
143
146
|
repositoryId: repositoryId || '',
|
|
144
147
|
adoOrg: org || '',
|
|
145
148
|
adoProject: project || '',
|
|
@@ -149,10 +152,6 @@ function buildProjectEntry({ name, description, localPath, repoHost, repositoryI
|
|
|
149
152
|
};
|
|
150
153
|
}
|
|
151
154
|
|
|
152
|
-
function ensureProjectStateFiles() {
|
|
153
|
-
// Project state is stored centrally at ~/.minions/projects/<name>/
|
|
154
|
-
// No files created inside user repos.
|
|
155
|
-
}
|
|
156
155
|
|
|
157
156
|
// ─── Commands ────────────────────────────────────────────────────────────────
|
|
158
157
|
|
|
@@ -187,7 +186,7 @@ async function addProject(targetDir) {
|
|
|
187
186
|
|
|
188
187
|
const name = await ask('Project name', detected.name || path.basename(target));
|
|
189
188
|
const description = await ask('Description (what this repo contains/does)', detected.description || '');
|
|
190
|
-
const repoHost = await ask('Repo host (ado
|
|
189
|
+
const repoHost = await ask('Repo host (github/ado)', detected.repoHost || 'github');
|
|
191
190
|
const org = await ask('Organization', detected.org || '');
|
|
192
191
|
const project = await ask('Project', detected.project || '');
|
|
193
192
|
const repoName = await ask('Repo name', detected.repoName || name);
|
|
@@ -198,7 +197,6 @@ async function addProject(targetDir) {
|
|
|
198
197
|
|
|
199
198
|
config.projects.push(buildProjectEntry({ name, description, localPath: target, repoHost, repositoryId, org, project, repoName, mainBranch }));
|
|
200
199
|
saveConfig(config);
|
|
201
|
-
ensureProjectStateFiles(target);
|
|
202
200
|
|
|
203
201
|
console.log(`\n Linked "${name}" (${target})`);
|
|
204
202
|
console.log(` Total projects: ${config.projects.length}`);
|
|
@@ -259,7 +257,9 @@ function findGitRepos(rootDir, maxDepth = 3) {
|
|
|
259
257
|
// Skip common non-project dirs
|
|
260
258
|
const base = path.basename(dir);
|
|
261
259
|
if (['node_modules', '.git', '.hg', 'AppData', '$Recycle.Bin', 'Windows', 'Program Files',
|
|
262
|
-
'Program Files (x86)', '.cache', '.npm', '.yarn', '.nuget', 'worktrees'].includes(base)) return;
|
|
260
|
+
'Program Files (x86)', '.cache', '.npm', '.yarn', '.nuget', 'worktrees', '.minions'].includes(base)) return;
|
|
261
|
+
// Skip minions home directory itself
|
|
262
|
+
if (path.resolve(dir) === path.resolve(MINIONS_HOME)) return;
|
|
263
263
|
|
|
264
264
|
const gitDir = path.join(dir, '.git');
|
|
265
265
|
if (fs.existsSync(gitDir)) {
|
|
@@ -377,14 +377,22 @@ async function scanAndAdd({ root, depth } = {}) {
|
|
|
377
377
|
|
|
378
378
|
console.log(`\n Adding ${toAdd.length} project(s)...\n`);
|
|
379
379
|
|
|
380
|
+
const existingNames = new Set((config.projects || []).map(p => p.name));
|
|
380
381
|
for (const repo of toAdd) {
|
|
382
|
+
// Deduplicate names — append -2, -3 etc. if name already taken
|
|
383
|
+
let name = repo.name;
|
|
384
|
+
if (existingNames.has(name)) {
|
|
385
|
+
let i = 2;
|
|
386
|
+
while (existingNames.has(name + '-' + i)) i++;
|
|
387
|
+
name = name + '-' + i;
|
|
388
|
+
}
|
|
389
|
+
existingNames.add(name);
|
|
381
390
|
config.projects.push(buildProjectEntry({
|
|
382
|
-
name
|
|
391
|
+
name, description: repo.description, localPath: repo.path,
|
|
383
392
|
repoHost: repo.host, org: repo.org, project: repo.project,
|
|
384
393
|
repoName: repo.repoName, mainBranch: repo.mainBranch,
|
|
385
394
|
}));
|
|
386
|
-
|
|
387
|
-
console.log(` + ${repo.name} (${repo.path})`);
|
|
395
|
+
console.log(` + ${name} (${repo.path})`);
|
|
388
396
|
}
|
|
389
397
|
|
|
390
398
|
saveConfig(config);
|
|
@@ -416,19 +424,34 @@ async function initMinions({ skipScan = false, scanRoot, scanDepth } = {}) {
|
|
|
416
424
|
saveConfig(config);
|
|
417
425
|
console.log(`\n Minions initialized at ${MINIONS_HOME}`);
|
|
418
426
|
console.log(` Config, agents, and engine defaults created.\n`);
|
|
427
|
+
|
|
428
|
+
// Preflight checks
|
|
429
|
+
let preflightOk = true;
|
|
430
|
+
try { execSync('git --version', { encoding: 'utf8', timeout: 5000, stdio: 'pipe' }); console.log(' ✓ Git found'); }
|
|
431
|
+
catch { console.log(' ✗ Git not found — agents need git for worktrees and PRs'); preflightOk = false; }
|
|
432
|
+
try {
|
|
433
|
+
const isWin = process.platform === 'win32';
|
|
434
|
+
const cmd = isWin ? 'where claude 2>NUL' : 'which claude 2>/dev/null';
|
|
435
|
+
execSync(cmd, { encoding: 'utf8', timeout: 5000, stdio: 'pipe' });
|
|
436
|
+
console.log(' ✓ Claude Code CLI found');
|
|
437
|
+
} catch { console.log(' ✗ Claude Code CLI not found — install: npm i -g @anthropic-ai/claude-code (or native installer)'); preflightOk = false; }
|
|
438
|
+
const nodeVer = parseInt(process.versions.node);
|
|
439
|
+
if (nodeVer >= 18) { console.log(' ✓ Node.js ' + process.versions.node); }
|
|
440
|
+
else { console.log(' ✗ Node.js ' + process.versions.node + ' — version 18+ required'); preflightOk = false; }
|
|
441
|
+
if (!preflightOk) console.log('\n Some prerequisites missing — agents may fail until resolved.\n');
|
|
442
|
+
else console.log('');
|
|
419
443
|
if (removedPlaceholders > 0) {
|
|
420
444
|
console.log(` Removed ${removedPlaceholders} placeholder project entr${removedPlaceholders === 1 ? 'y' : 'ies'} from config.\n`);
|
|
421
445
|
}
|
|
422
446
|
|
|
423
447
|
if (skipScan) {
|
|
424
448
|
console.log(' Skipping repo scan (--skip-scan). Run "node minions.js scan" later to link projects.\n');
|
|
449
|
+
rl.close();
|
|
425
450
|
} else {
|
|
426
|
-
// Auto-chain into scan
|
|
451
|
+
// Auto-chain into scan (scanAndAdd closes rl)
|
|
427
452
|
console.log(' Now let\'s find your repos...\n');
|
|
428
453
|
await scanAndAdd({ root: scanRoot, depth: scanDepth });
|
|
429
454
|
}
|
|
430
|
-
|
|
431
|
-
rl.close();
|
|
432
455
|
}
|
|
433
456
|
|
|
434
457
|
function nukeMinions() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.203",
|
|
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"
|