multi-agents-cli 1.1.10 → 1.1.11

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.
@@ -9,7 +9,7 @@
9
9
  * Run from the repo root after a task is complete.
10
10
  */
11
11
 
12
- const readline = require('readline');
12
+ let prompts; try { prompts = require('prompts'); } catch { prompts = null; }
13
13
  const fs = require('fs');
14
14
  const path = require('path');
15
15
  const { execSync, spawn } = require('child_process');
@@ -51,15 +51,23 @@ if (!fs.existsSync(LOCK_PATH)) {
51
51
 
52
52
  const config = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8'));
53
53
 
54
- // ── Readline ──────────────────────────────────────────────────────────────────
54
+ // ── Arrow confirm helper ──────────────────────────────────────────────────────
55
55
 
56
- const rl = readline.createInterface({
57
- input: process.stdin,
58
- output: process.stdout,
59
- });
56
+ const arrowConfirm = async (message, initial = true) => {
57
+ if (prompts && process.stdin.isTTY) {
58
+ const res = await prompts({ type: 'confirm', name: 'value', message, initial }, { onCancel: () => process.exit(0) });
59
+ return res.value ?? initial;
60
+ }
61
+ return initial;
62
+ };
60
63
 
61
- const ask = (question) =>
62
- new Promise((resolve) => rl.question(question, (a) => resolve(a.trim())));
64
+ const arrowSelect = async (message, choices) => {
65
+ if (prompts && process.stdin.isTTY) {
66
+ const res = await prompts({ type: 'select', name: 'value', message, choices: choices.map((c, i) => ({ title: c, value: i })) }, { onCancel: () => process.exit(0) });
67
+ return res.value ?? 0;
68
+ }
69
+ return 0;
70
+ };
63
71
 
64
72
  const separator = () => console.log(`\n${dim('─'.repeat(60))}`);
65
73
 
@@ -143,7 +151,6 @@ const main = async () => {
143
151
  if (worktrees.length === 0) {
144
152
  console.log(`\n${yellow(' No active task worktrees found.')}`);
145
153
  console.log(dim(' Run npm run agent to start a task.\n'));
146
- rl.close();
147
154
  return;
148
155
  }
149
156
 
@@ -163,15 +170,8 @@ const main = async () => {
163
170
  selectedWorktree = worktrees[0];
164
171
  console.log(dim(`\n Auto-selected: ${selectedWorktree.branch}\n`));
165
172
  } else {
166
- while (!selectedWorktree) {
167
- const input = await ask(`\n ${bold('Select task to complete')} ${dim(`(1-${worktrees.length})`)}: `);
168
- const index = parseInt(input) - 1;
169
- if (!isNaN(index) && index >= 0 && index < worktrees.length) {
170
- selectedWorktree = worktrees[index];
171
- } else {
172
- console.log(yellow(` Please enter a number between 1 and ${worktrees.length}.`));
173
- }
174
- }
173
+ const idx = await arrowSelect('Select task to complete:', worktrees.map(wt => wt.branch));
174
+ selectedWorktree = worktrees[idx];
175
175
  }
176
176
 
177
177
  const { path: worktreePath, branch: branchName } = selectedWorktree;
@@ -219,7 +219,6 @@ const main = async () => {
219
219
  console.log(dim(' The following files are outside the allowed scope for ' + scopeMeta.agent + ' (' + scopeMeta.scope + '):\n'));
220
220
  violations.forEach(f => console.log(' ' + red('✗') + ' ' + f));
221
221
  console.log('\n' + dim(' Fix the violations, then re-run npm run complete.\n'));
222
- rl.close();
223
222
  return;
224
223
  }
225
224
 
@@ -238,10 +237,9 @@ const main = async () => {
238
237
  if (!isCompleted && !isNonTTY) {
239
238
  console.log(`\n${yellow(' TASK.md is not marked as COMPLETED.')}`);
240
239
  console.log(dim(' The agent may still be working on this task.\n'));
241
- const proceed = await ask(` ${bold('Proceed with merge anyway?')} ${dim('(y/n)')}: `);
242
- if (proceed.toLowerCase() !== 'y') {
240
+ const proceed = await arrowConfirm('Proceed with merge anyway?', false);
241
+ if (!proceed) {
243
242
  console.log(yellow('\n Aborted. Complete the task first.\n'));
244
- rl.close();
245
243
  return;
246
244
  }
247
245
  } else if (!isCompleted && isNonTTY) {
@@ -258,10 +256,9 @@ const main = async () => {
258
256
  console.log(` ${dim('Into')} : ${green('main')}`);
259
257
  console.log(` ${dim('Worktree')} : ${dim(worktreePath)}\n`);
260
258
 
261
- const confirm = isNonTTY ? 'y' : await ask(`${bold('Confirm merge into main?')} ${dim('(y/n)')}: `);
262
- if (confirm.toLowerCase() !== 'y') {
259
+ const confirmMerge = isNonTTY ? true : await arrowConfirm('Confirm merge into main?');
260
+ if (!confirmMerge) {
263
261
  console.log(yellow('\n Aborted.\n'));
264
- rl.close();
265
262
  return;
266
263
  }
267
264
 
@@ -328,10 +325,9 @@ const main = async () => {
328
325
  } catch (err) {
329
326
  console.log(` ${yellow('!')} Could not pull latest main.`);
330
327
  if (!isNonTTY) {
331
- const proceedAnyway = await ask(` ${bold('Proceed with merge anyway?')} ${dim('(y/n)')}: `);
332
- if (proceedAnyway.toLowerCase() !== 'y') {
328
+ const proceedAnyway = await arrowConfirm('Proceed with merge anyway?');
329
+ if (!proceedAnyway) {
333
330
  console.log(yellow('\n Aborted.\n'));
334
- rl.close();
335
331
  return;
336
332
  }
337
333
  } else {
@@ -362,12 +358,10 @@ const main = async () => {
362
358
  } else {
363
359
  console.log(`\n${red(' ✗ Merge conflict in:')} ${conflicts.join(', ')}`);
364
360
  console.log(dim(' Resolve conflicts manually, then run: git commit\n'));
365
- rl.close();
366
361
  return;
367
362
  }
368
363
  } catch {
369
364
  console.log(`\n${red(' ✗ Merge failed.')} Resolve manually.\n`);
370
- rl.close();
371
365
  return;
372
366
  }
373
367
  }
@@ -560,22 +554,13 @@ const main = async () => {
560
554
  console.log(` client/LOGIC is merged. This is the ideal moment to launch backend/INIT.\n`);
561
555
 
562
556
  const { spawn: _spawn } = require('child_process');
563
- const launchIdx = await new Promise(resolve => {
564
- rl2 = readline.createInterface({ input: process.stdin, output: process.stdout });
565
- const choices = [
566
- '1. Launch backend/INIT now ← recommended',
567
- '2. Skip — I will handle it manually',
568
- ];
569
- choices.forEach(c => console.log(` ${c}`));
570
- rl2.question('\n Select (1-2): ', ans => {
571
- rl2.close();
572
- resolve(parseInt(ans));
573
- });
574
- });
557
+ const launchIdx = await arrowSelect('Launch backend/INIT?', [
558
+ 'Launch backend/INIT now ← recommended',
559
+ 'Skip I will handle it manually',
560
+ ]);
575
561
 
576
562
  if (launchIdx === 1) {
577
563
  console.log(`\n ${green('✓')} Launching backend/INIT...\n`);
578
- rl.close();
579
564
  _spawn('node', [path.join(ROOT, '.workflow', 'agent.js'), '--scope=backend', '--agent=INIT'], {
580
565
  cwd: ROOT, stdio: 'inherit',
581
566
  });
@@ -583,8 +568,6 @@ const main = async () => {
583
568
  }
584
569
  }
585
570
  } catch { /* best-effort */ }
586
-
587
- rl.close();
588
571
  };
589
572
 
590
573
  main().catch((err) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "multi-agents-cli",
3
- "version": "1.1.10",
3
+ "version": "1.1.11",
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",