multi-agents-cli 1.0.30 → 1.0.32
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/init.js +132 -29
- package/package.json +1 -1
package/init.js
CHANGED
|
@@ -89,7 +89,8 @@ if (isReInit) {
|
|
|
89
89
|
// Re-init from inside project or worktree - self-relocate to repo root
|
|
90
90
|
try {
|
|
91
91
|
const { execSync } = require('child_process');
|
|
92
|
-
const
|
|
92
|
+
const gitCommonDir = execSync('git rev-parse --git-common-dir', { encoding: 'utf8' }).trim();
|
|
93
|
+
const repoRoot = require('path').resolve(gitCommonDir, '..');
|
|
93
94
|
process.chdir(repoRoot);
|
|
94
95
|
} catch { /* stay in current directory */ }
|
|
95
96
|
}
|
|
@@ -657,38 +658,140 @@ const main = async () => {
|
|
|
657
658
|
|
|
658
659
|
if (fs.existsSync(LOCK_FILE)) {
|
|
659
660
|
const ts = fs.readFileSync(LOCK_FILE, 'utf8').trim();
|
|
660
|
-
const
|
|
661
|
-
const
|
|
661
|
+
const trackingPath = path.join(RUNTIME_DIR, '.tracking.json');
|
|
662
|
+
const tracking = fs.existsSync(trackingPath) ? JSON.parse(fs.readFileSync(trackingPath, 'utf8')) : {};
|
|
663
|
+
|
|
664
|
+
// Dependency map — primary agents whose restart cascades to dependents
|
|
665
|
+
const DEPENDENCIES = {
|
|
666
|
+
client: { UI: ['LOGIC', 'FORMS', 'ROUTING', 'TESTING', 'ACCESSIBILITY'] },
|
|
667
|
+
backend: { DB: ['API', 'AUTH', 'LOGIC', 'EVENTS', 'JOBS', 'TESTING'] },
|
|
668
|
+
shared: {},
|
|
669
|
+
};
|
|
662
670
|
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
console.log(` ${dim('3.')} Exit\n`);
|
|
671
|
+
const getActiveAgents = (scope) => {
|
|
672
|
+
const agents = tracking[scope] || {};
|
|
673
|
+
return Object.entries(agents).filter(([, v]) => v && v.branch);
|
|
674
|
+
};
|
|
668
675
|
|
|
669
|
-
const
|
|
676
|
+
const showRestartProcess = async () => {
|
|
677
|
+
// Build list of active processes across all scopes
|
|
678
|
+
const active = [];
|
|
679
|
+
for (const scope of ['client', 'backend', 'shared']) {
|
|
680
|
+
for (const [agent, data] of getActiveAgents(scope)) {
|
|
681
|
+
active.push({ scope, agent, data });
|
|
682
|
+
}
|
|
683
|
+
}
|
|
670
684
|
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
685
|
+
if (active.length === 0) {
|
|
686
|
+
console.log(yellow('\n No active processes found.\n'));
|
|
687
|
+
return false;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
separator();
|
|
691
|
+
console.log(`\n${bold(' Which process do you want to restart?')}\n`);
|
|
692
|
+
active.forEach(({ scope, agent, data }, i) => {
|
|
693
|
+
const status = data.status || 'ACTIVE';
|
|
694
|
+
console.log(` ${dim(`${i + 1}.`)} ${bold(agent)} ${dim(`(${scope})`)} - ${dim(status)}`);
|
|
677
695
|
});
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
696
|
+
console.log(` ${dim(`${active.length + 1}.`)} ${dim('Back')}\n`);
|
|
697
|
+
|
|
698
|
+
const rl3 = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
699
|
+
const ask3 = (q) => new Promise((resolve) => rl3.question(q, (a) => { rl3.close(); resolve(a.trim()); }));
|
|
700
|
+
const pick = await ask3(` ${bold('Select')} ${dim(`(1-${active.length + 1})`)}: `);
|
|
701
|
+
|
|
702
|
+
const idx = parseInt(pick) - 1;
|
|
703
|
+
if (idx === active.length) return false; // Back
|
|
704
|
+
if (idx < 0 || idx >= active.length) return false;
|
|
705
|
+
|
|
706
|
+
const { scope, agent, data } = active[idx];
|
|
707
|
+
const deps = (DEPENDENCIES[scope] || {})[agent] || [];
|
|
708
|
+
const affectedAgents = [{ scope, agent, data }];
|
|
709
|
+
|
|
710
|
+
// Find dependent agents that are also active
|
|
711
|
+
for (const dep of deps) {
|
|
712
|
+
const depData = (tracking[scope] || {})[dep];
|
|
713
|
+
if (depData && depData.branch) {
|
|
714
|
+
affectedAgents.push({ scope, agent: dep, data: depData });
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
// Show warning with exact names
|
|
719
|
+
separator();
|
|
720
|
+
console.log(`\n${yellow(` ⚠ Restarting ${agent} will delete:`)}`);
|
|
721
|
+
for (const { agent: a, data: d } of affectedAgents) {
|
|
722
|
+
console.log(`\n ${bold(a)}`);
|
|
723
|
+
console.log(` - Branch (${d.branch})`);
|
|
724
|
+
console.log(` - Remote branch (origin/${d.branch})`);
|
|
725
|
+
if (d.worktreePath) {
|
|
726
|
+
const wtName = path.relative(ROOT, d.worktreePath);
|
|
727
|
+
console.log(` - Worktree (${wtName})`);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
if (deps.length > 0) {
|
|
732
|
+
console.log(`\n ${yellow('Dependent processes will also be wiped.')}`);
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
console.log(`\n ${red('This cannot be undone.')}\n`);
|
|
736
|
+
|
|
737
|
+
const rl4 = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
738
|
+
const ask4 = (q) => new Promise((resolve) => rl4.question(q, (a) => { rl4.close(); resolve(a.trim()); }));
|
|
739
|
+
const confirm = await ask4(` Continue? (y/N): `);
|
|
740
|
+
|
|
741
|
+
if (confirm.toLowerCase() !== 'y') {
|
|
742
|
+
console.log(dim('\n Cancelled.\n'));
|
|
743
|
+
return false;
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
// Perform wipe
|
|
747
|
+
for (const { agent: a, data: d, scope: s } of affectedAgents) {
|
|
748
|
+
try { execSync(`git worktree remove "${d.worktreePath}" --force`, { cwd: ROOT, stdio: 'pipe' }); } catch {}
|
|
749
|
+
try { execSync(`git branch -D ${d.branch}`, { cwd: ROOT, stdio: 'pipe' }); } catch {}
|
|
750
|
+
try { execSync(`git push origin --delete ${d.branch}`, { cwd: ROOT, stdio: 'pipe' }); } catch {}
|
|
751
|
+
// Clear tracking
|
|
752
|
+
if (tracking[s] && tracking[s][a]) {
|
|
753
|
+
tracking[s][a] = { branch: null, timestamp: null, launchedAt: null, status: null, missingCount: 0, worktreePath: null };
|
|
754
|
+
}
|
|
755
|
+
console.log(` ${green('✓')} ${a} wiped`);
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
fs.writeFileSync(trackingPath, JSON.stringify(tracking, null, 2), 'utf8');
|
|
759
|
+
console.log(`\n ${green('✓')} Restart complete.\n`);
|
|
760
|
+
return true;
|
|
761
|
+
};
|
|
762
|
+
|
|
763
|
+
if (prompts && process.stdin.isTTY) {
|
|
764
|
+
let lockLoop = true;
|
|
765
|
+
while (lockLoop) {
|
|
766
|
+
separator();
|
|
767
|
+
console.log(`\n${yellow(' This project has already been initialized.')}`);
|
|
768
|
+
console.log(dim(` Initialized on: ${ts}\n`));
|
|
769
|
+
|
|
770
|
+
const res = await prompts({
|
|
771
|
+
type: 'select',
|
|
772
|
+
name: 'value',
|
|
773
|
+
message: 'What would you like to do?',
|
|
774
|
+
choices: [
|
|
775
|
+
{ title: 'Resume', description: 'Pick up where you left off', value: '1' },
|
|
776
|
+
{ title: 'Restart process', description: 'Wipe and restart a specific process', value: '2' },
|
|
777
|
+
{ title: 'Cancel', value: '3' },
|
|
778
|
+
],
|
|
779
|
+
}, { onCancel: () => process.exit(0) });
|
|
780
|
+
|
|
781
|
+
if (res.value === '1') {
|
|
782
|
+
const child = spawn('node', [path.join(ROOT, '.workflow', 'agent.js')], { stdio: 'inherit', cwd: ROOT });
|
|
783
|
+
child.on('exit', (code) => process.exit(code));
|
|
784
|
+
return;
|
|
785
|
+
} else if (res.value === '2') {
|
|
786
|
+
const didRestart = await showRestartProcess();
|
|
787
|
+
if (!didRestart) continue; // Back — show menu again
|
|
788
|
+
lockLoop = false;
|
|
789
|
+
return;
|
|
790
|
+
} else {
|
|
791
|
+
console.log(dim('\n Cancelled.\n'));
|
|
792
|
+
process.exit(0);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
692
795
|
}
|
|
693
796
|
}
|
|
694
797
|
|
package/package.json
CHANGED