multi-agents-cli 1.0.6 → 1.0.8
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 +79 -55
- package/package.json +4 -1
package/init.js
CHANGED
|
@@ -11,6 +11,45 @@
|
|
|
11
11
|
const readline = require('readline');
|
|
12
12
|
const fs = require('fs');
|
|
13
13
|
const path = require('path');
|
|
14
|
+
|
|
15
|
+
// ── Prompts (arrow-key navigation) ───────────────────────────────────────────
|
|
16
|
+
|
|
17
|
+
let prompts;
|
|
18
|
+
try { prompts = require('prompts'); } catch { prompts = null; }
|
|
19
|
+
|
|
20
|
+
const arrowSelect = async (message, choices, rl) => {
|
|
21
|
+
if (prompts && process.stdin.isTTY) {
|
|
22
|
+
const res = await prompts({
|
|
23
|
+
type: 'select',
|
|
24
|
+
name: 'value',
|
|
25
|
+
message,
|
|
26
|
+
choices: choices.map((c, i) => ({ title: typeof c === 'string' ? c : c.label, value: i })),
|
|
27
|
+
}, { onCancel: () => process.exit(0) });
|
|
28
|
+
return res.value ?? 0;
|
|
29
|
+
}
|
|
30
|
+
choices.forEach((c, i) => console.log(` ${dim(`${i + 1}.`)} ${typeof c === 'string' ? c : c.label}`));
|
|
31
|
+
return new Promise(resolve => {
|
|
32
|
+
rl.question(`\n Select (1-${choices.length}): `, ans => {
|
|
33
|
+
const n = parseInt(ans) - 1;
|
|
34
|
+
resolve(!isNaN(n) && n >= 0 && n < choices.length ? n : 0);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const arrowConfirm = async (message, rl) => {
|
|
40
|
+
if (prompts && process.stdin.isTTY) {
|
|
41
|
+
const res = await prompts({
|
|
42
|
+
type: 'confirm',
|
|
43
|
+
name: 'value',
|
|
44
|
+
message,
|
|
45
|
+
initial: true,
|
|
46
|
+
}, { onCancel: () => process.exit(0) });
|
|
47
|
+
return res.value ?? true;
|
|
48
|
+
}
|
|
49
|
+
return new Promise(resolve => {
|
|
50
|
+
rl.question(`${message} (y/n): `, ans => resolve(ans.toLowerCase() !== 'n'));
|
|
51
|
+
});
|
|
52
|
+
};
|
|
14
53
|
const os = require('os');
|
|
15
54
|
const { execSync, spawn } = require('child_process');
|
|
16
55
|
|
|
@@ -436,29 +475,19 @@ const showList = (items, showSkip = false) => {
|
|
|
436
475
|
};
|
|
437
476
|
|
|
438
477
|
const selectRequired = async (prompt, items) => {
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
showList(items);
|
|
442
|
-
const input = await ask(`\n ${bold('Select')} ${dim(`(1-${items.length})`)}: `);
|
|
443
|
-
const index = parseInt(input) - 1;
|
|
444
|
-
if (!isNaN(index) && index >= 0 && index < items.length) return items[index];
|
|
445
|
-
console.log(yellow(` Please enter a number between 1 and ${items.length}.`));
|
|
446
|
-
}
|
|
478
|
+
const idx = await arrowSelect(prompt, items.map(i => ({ label: typeof i === 'string' ? i : i.label })), rl);
|
|
479
|
+
return items[idx];
|
|
447
480
|
};
|
|
448
481
|
|
|
449
482
|
const selectOptional = async (prompt, items) => {
|
|
450
483
|
if (!items || items.length === 0) return null;
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
return typeof items[index] === 'string' ? items[index] : items[index].value;
|
|
459
|
-
}
|
|
460
|
-
console.log(yellow(` Invalid selection. Please enter a number between 0 and ${items.length}.`));
|
|
461
|
-
}
|
|
484
|
+
const choices = [
|
|
485
|
+
...items.map(i => ({ label: typeof i === 'string' ? i : i.label })),
|
|
486
|
+
{ label: dim('Skip (agent will propose when needed)') },
|
|
487
|
+
];
|
|
488
|
+
const idx = await arrowSelect(prompt, choices, rl);
|
|
489
|
+
if (idx === items.length) return null;
|
|
490
|
+
return typeof items[idx] === 'string' ? items[idx] : items[idx].value;
|
|
462
491
|
};
|
|
463
492
|
|
|
464
493
|
const separator = () => console.log(`\n${dim('─'.repeat(60))}`);
|
|
@@ -564,7 +593,7 @@ const main = async () => {
|
|
|
564
593
|
separator();
|
|
565
594
|
|
|
566
595
|
console.log(`\n${bold('Let\'s configure your project.')}`);
|
|
567
|
-
console.log(dim('
|
|
596
|
+
console.log(dim(' Use arrow keys to select. Optional fields can be skipped.\n'));
|
|
568
597
|
console.log(dim(' Skipped fields will be resolved by the agent when first needed.\n'));
|
|
569
598
|
|
|
570
599
|
// ── Project name ────────────────────────────────────────────────────────────
|
|
@@ -600,11 +629,11 @@ const main = async () => {
|
|
|
600
629
|
let backendOrm = null;
|
|
601
630
|
let backendAuth = null;
|
|
602
631
|
let backendType = null;
|
|
632
|
+
let backendFwObj = null;
|
|
603
633
|
|
|
604
634
|
if (clientFw.integratedBackend) {
|
|
605
635
|
console.log(dim(` ${clientFw.value} supports server-side rendering and API routes.\n`));
|
|
606
|
-
|
|
607
|
-
useIntegratedBackend = integratedAnswer.toLowerCase() === 'y';
|
|
636
|
+
useIntegratedBackend = await arrowConfirm(`Use integrated backend (${clientFw.value} API routes/SSR) instead of a separate backend?`, rl);
|
|
608
637
|
|
|
609
638
|
if (useIntegratedBackend) {
|
|
610
639
|
backendType = 'integrated';
|
|
@@ -615,22 +644,12 @@ const main = async () => {
|
|
|
615
644
|
if (!useIntegratedBackend) {
|
|
616
645
|
console.log(dim(' You can skip the backend framework and decide later.\n'));
|
|
617
646
|
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
backendFwObj = null;
|
|
625
|
-
} else {
|
|
626
|
-
const index = parseInt(input) - 1;
|
|
627
|
-
if (isNaN(index) || index < 0 || index >= BACKEND_FRAMEWORKS.length) {
|
|
628
|
-
console.log(yellow(` Please enter a number between 0 and ${BACKEND_FRAMEWORKS.length}.`));
|
|
629
|
-
} else {
|
|
630
|
-
backendFwObj = BACKEND_FRAMEWORKS[index];
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
}
|
|
647
|
+
const backendChoices = [
|
|
648
|
+
...BACKEND_FRAMEWORKS.map(f => ({ label: f.label || f.value })),
|
|
649
|
+
{ label: dim('Skip (decide later)') },
|
|
650
|
+
];
|
|
651
|
+
const backendIdx = await arrowSelect('Backend framework:', backendChoices, rl);
|
|
652
|
+
backendFwObj = backendIdx === BACKEND_FRAMEWORKS.length ? null : BACKEND_FRAMEWORKS[backendIdx];
|
|
634
653
|
|
|
635
654
|
backendFw = backendFwObj ? backendFwObj.value : null;
|
|
636
655
|
backendLang = backendFwObj ? backendFwObj.language : null;
|
|
@@ -675,8 +694,7 @@ const main = async () => {
|
|
|
675
694
|
if (ideChoice.cmd && !ideChoice.detected) {
|
|
676
695
|
console.log(yellow(` ⚠ ${ideChoice.name} was not detected on PATH. It may not open automatically.`));
|
|
677
696
|
}
|
|
678
|
-
|
|
679
|
-
if (confirmIde.toLowerCase() !== 'y') {
|
|
697
|
+
if (!await arrowConfirm('Confirm this selection?', rl)) {
|
|
680
698
|
console.log(dim(' Re-selecting...\n'));
|
|
681
699
|
continue;
|
|
682
700
|
}
|
|
@@ -698,8 +716,7 @@ const main = async () => {
|
|
|
698
716
|
}
|
|
699
717
|
|
|
700
718
|
console.log(` ${yellow('!')} Could not verify ${ideChoice.name}. The CLI may not be installed or accessible.`);
|
|
701
|
-
|
|
702
|
-
if (proceedAnyway.toLowerCase() === 'y') break;
|
|
719
|
+
if (await arrowConfirm('Continue with this IDE anyway?', rl)) break;
|
|
703
720
|
console.log(dim(' Re-selecting...\n'));
|
|
704
721
|
}
|
|
705
722
|
|
|
@@ -724,9 +741,13 @@ const main = async () => {
|
|
|
724
741
|
|
|
725
742
|
console.log('');
|
|
726
743
|
console.log(dim(' y = confirm | n = abort | e = edit (start over)\n'));
|
|
727
|
-
const
|
|
744
|
+
const confirmIdx = await arrowSelect('Confirm and write to config files?', [
|
|
745
|
+
{ label: `${green('✓')} Confirm — write config and set up project` },
|
|
746
|
+
{ label: `${yellow('↺')} Restart — redo configuration` },
|
|
747
|
+
{ label: `${red('✗')} Abort` },
|
|
748
|
+
], rl);
|
|
728
749
|
|
|
729
|
-
if (
|
|
750
|
+
if (confirmIdx === 1) {
|
|
730
751
|
console.log(yellow('\n Restarting configuration...\n'));
|
|
731
752
|
rl.close();
|
|
732
753
|
const { spawn } = require('child_process');
|
|
@@ -735,7 +756,7 @@ const main = async () => {
|
|
|
735
756
|
return;
|
|
736
757
|
}
|
|
737
758
|
|
|
738
|
-
if (
|
|
759
|
+
if (confirmIdx === 2) {
|
|
739
760
|
console.log(yellow('\n Aborted. No files were changed.\n'));
|
|
740
761
|
rl.close();
|
|
741
762
|
return;
|
|
@@ -1125,11 +1146,11 @@ fi
|
|
|
1125
1146
|
// Wrap in loop to support back navigation
|
|
1126
1147
|
let trajectory = null;
|
|
1127
1148
|
trajectoryLoop: while (true) {
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1149
|
+
const trajIdx = await arrowSelect('How do you want to build?', [
|
|
1150
|
+
{ label: bold('Multi-Agent Driven Orchestration') },
|
|
1151
|
+
{ label: bold('Shared Orchestration') },
|
|
1152
|
+
], rl);
|
|
1153
|
+
trajectory = String(trajIdx + 1);
|
|
1133
1154
|
|
|
1134
1155
|
const selected = TRAJECTORY_DETAILS[trajectory];
|
|
1135
1156
|
separator();
|
|
@@ -1137,9 +1158,12 @@ fi
|
|
|
1137
1158
|
renderTrajectoryLines(selected.full);
|
|
1138
1159
|
console.log('');
|
|
1139
1160
|
|
|
1140
|
-
const
|
|
1141
|
-
|
|
1142
|
-
|
|
1161
|
+
const confirmIdx = await arrowSelect('Confirm?', [
|
|
1162
|
+
{ label: `${green('✓')} Confirm` },
|
|
1163
|
+
{ label: `${yellow('←')} Back — pick differently` },
|
|
1164
|
+
], rl);
|
|
1165
|
+
if (confirmIdx === 0) break trajectoryLoop;
|
|
1166
|
+
trajectory = null;
|
|
1143
1167
|
separator();
|
|
1144
1168
|
console.log(`\n ${bold('How do you want to build?')}\n`);
|
|
1145
1169
|
console.log(` ${dim('1.')} ${bold('Multi-Agent Driven Orchestration')}`);
|
|
@@ -1168,8 +1192,8 @@ fi
|
|
|
1168
1192
|
} catch { /* best-effort */ }
|
|
1169
1193
|
|
|
1170
1194
|
if (selected.next === 'launch') {
|
|
1171
|
-
const
|
|
1172
|
-
if (
|
|
1195
|
+
const launchConfirm = await arrowConfirm('Ready to launch your first task?', rl);
|
|
1196
|
+
if (launchConfirm) {
|
|
1173
1197
|
rl.close();
|
|
1174
1198
|
console.log('');
|
|
1175
1199
|
const child = spawn('node', [path.join(ROOT, '.workflow', 'launch.js')], {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "multi-agents-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"description": "Multi-agent workflow orchestration for Claude Code — isolated git worktrees, structured state tracking, autonomous task chaining",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude-code",
|
|
@@ -16,6 +16,9 @@
|
|
|
16
16
|
"bin": {
|
|
17
17
|
"multi-agents": "init.js"
|
|
18
18
|
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"prompts": "^2.4.2"
|
|
21
|
+
},
|
|
19
22
|
"files": [
|
|
20
23
|
"init.js",
|
|
21
24
|
"README.md",
|