neuro-cli 4.1.1 → 4.1.2

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.
@@ -1,3 +1,4 @@
1
+ import { Interface as ReadLineInterface } from 'readline';
1
2
  export type PermissionMode = 'manual' | 'auto' | 'plan' | 'yolo';
2
3
  export interface ApprovalResult {
3
4
  approved: boolean;
@@ -39,6 +40,7 @@ export declare class ApprovalSystem {
39
40
  private persistDecisions;
40
41
  private consecutiveAutoApproves;
41
42
  private rl;
43
+ private mainRl;
42
44
  private stats;
43
45
  private pendingBatch;
44
46
  private batchTimer;
@@ -65,6 +67,11 @@ export declare class ApprovalSystem {
65
67
  private isWhitelisted;
66
68
  private getPattern;
67
69
  private getAlwaysKey;
70
+ /**
71
+ * Set the main readline interface from index.ts
72
+ * This prevents creating a second readline on the same stdin
73
+ */
74
+ setMainReadline(rl: ReadLineInterface): void;
68
75
  private readline;
69
76
  close(): void;
70
77
  addAutoApprove(toolName: string): void;
@@ -23,6 +23,7 @@ export class ApprovalSystem {
23
23
  persistDecisions = true;
24
24
  consecutiveAutoApproves = 0;
25
25
  rl = null;
26
+ mainRl = null;
26
27
  stats = new Map();
27
28
  pendingBatch = [];
28
29
  batchTimer = null;
@@ -333,10 +334,38 @@ export class ApprovalSystem {
333
334
  getAlwaysKey(toolName, args) {
334
335
  return `${toolName}:${this.getPattern(args)}`;
335
336
  }
337
+ /**
338
+ * Set the main readline interface from index.ts
339
+ * This prevents creating a second readline on the same stdin
340
+ */
341
+ setMainReadline(rl) {
342
+ this.mainRl = rl;
343
+ }
336
344
  readline(prompt) {
337
- if (!this.rl)
338
- this.rl = createInterface({ input: process.stdin, output: process.stdout });
339
- return new Promise((resolve) => { this.rl.question(prompt, (answer) => resolve(answer)); });
345
+ // Pause the main readline to prevent it from also reading stdin input
346
+ // This is the root cause of double character input (YY instead of Y)
347
+ const mainInputStream = this.mainRl?.input;
348
+ const wasMainPaused = mainInputStream?.isPaused?.();
349
+ if (this.mainRl && mainInputStream && mainInputStream.isPaused()) {
350
+ // Already paused, skip
351
+ }
352
+ else if (this.mainRl) {
353
+ this.mainRl.pause();
354
+ }
355
+ return new Promise((resolve) => {
356
+ // Reuse the main readline if available, otherwise create a temporary one
357
+ const rl = this.mainRl || this.rl || createInterface({ input: process.stdin, output: process.stdout });
358
+ if (!this.rl && !this.mainRl)
359
+ this.rl = rl;
360
+ rl.question(prompt, (answer) => {
361
+ // Resume the main readline after getting the answer
362
+ if (this.mainRl) {
363
+ this.mainRl.resume();
364
+ this.mainRl.prompt();
365
+ }
366
+ resolve(answer);
367
+ });
368
+ });
340
369
  }
341
370
  close() {
342
371
  if (this.rl) {
@@ -3,6 +3,7 @@
3
3
  // Shows file changes before applying them
4
4
  // ============================================================
5
5
  import { readFileSync, existsSync } from 'fs';
6
+ import { createInterface } from 'readline';
6
7
  import chalk from 'chalk';
7
8
  export class DiffPreview {
8
9
  /**
@@ -128,7 +129,7 @@ export class DiffPreview {
128
129
  */
129
130
  static async confirmDiff(diff) {
130
131
  DiffPreview.renderDiff(diff);
131
- const rl = require('readline').createInterface({ input: process.stdin, output: process.stdout });
132
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
132
133
  return new Promise((resolve) => {
133
134
  rl.question(chalk.cyan(' Apply these changes? [y/n]: '), (answer) => {
134
135
  rl.close();
@@ -1,5 +1,5 @@
1
1
  // ============================================================
2
- // NeuroCLI - NeuroEngine v4.1.1
2
+ // NeuroCLI - NeuroEngine v4.1.2
3
3
  // The main engine that ties everything together
4
4
  // Now with: Sandbox, Plugin SDK, Enhanced MCP, Enhanced Approval,
5
5
  // Model Router, Prompt Cache, Undo/Redo, Output Styles,
@@ -483,7 +483,7 @@ export class NeuroEngine {
483
483
  this.gitWorktree = new GitWorktreeManager(process.cwd());
484
484
  // Auto-Updater
485
485
  this.updater = new AutoUpdater({
486
- currentVersion: '4.1.1',
486
+ currentVersion: '4.1.2',
487
487
  autoCheck: true,
488
488
  autoUpdate: false,
489
489
  });
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  // ============================================================
3
3
  // NeuroCLI - Advanced AI Terminal Coding Assistant
4
- // Main Entry Point - v4.1.1 with cross-platform path fix
4
+ // Main Entry Point - v4.1.2 with cross-platform path fix
5
5
  // ============================================================
6
6
  import { Command } from 'commander';
7
7
  import { createInterface } from 'readline';
@@ -16,7 +16,7 @@ import { HeadlessMode } from './core/headless.js';
16
16
  import { ShellCompletionGenerator } from './core/shell-completion.js';
17
17
  import chalk from 'chalk';
18
18
  import { AutoUpdater } from './core/updater.js';
19
- const VERSION = '4.1.1';
19
+ const VERSION = '4.1.2';
20
20
  // ---- CLI Setup ----
21
21
  const program = new Command();
22
22
  program
@@ -430,14 +430,22 @@ async function startInteractive(options) {
430
430
  completer: completionEngine.complete,
431
431
  });
432
432
  rl.prompt();
433
+ // Wire the main readline to the approval system to prevent dual-readline bug
434
+ // (double character input when approval prompt and main rl both read stdin)
435
+ engine.approval.setMainReadline(rl);
433
436
  let currentMode = 'auto';
434
437
  let currentAgent;
438
+ let isProcessing = false;
435
439
  rl.on('line', async (line) => {
436
440
  const input = line.trim();
437
441
  if (!input) {
438
442
  rl.prompt();
439
443
  return;
440
444
  }
445
+ // Prevent input while processing (approval prompt may be active)
446
+ if (isProcessing) {
447
+ return;
448
+ }
441
449
  // Add to history
442
450
  completionEngine.addHistory(input);
443
451
  // Handle slash commands
@@ -909,7 +917,7 @@ async function startInteractive(options) {
909
917
  }
910
918
  break;
911
919
  case 'doctor':
912
- console.log(chalk.bold('\nNeuroCLI v4.1.1 Health Check:\n'));
920
+ console.log(chalk.bold('\nNeuroCLI v4.1.2 Health Check:\n'));
913
921
  console.log(` API Key: ${config.apiKey ? chalk.green('configured') : chalk.red('MISSING')}`);
914
922
  console.log(` Default Model: ${chalk.cyan(config.defaultModel)} ${MODELS[config.defaultModel] ? chalk.green('valid') : chalk.red('INVALID')}`);
915
923
  console.log(` MCP Servers: ${chalk.cyan(String(engine.mcpClient.listServers().length))}`);
@@ -1112,11 +1120,15 @@ async function startInteractive(options) {
1112
1120
  }
1113
1121
  // Process message with the engine
1114
1122
  try {
1123
+ isProcessing = true;
1115
1124
  await engine.processMessage(input, currentMode, currentAgent);
1116
1125
  }
1117
1126
  catch (error) {
1118
1127
  engine.ui.error(error instanceof Error ? error.message : String(error));
1119
1128
  }
1129
+ finally {
1130
+ isProcessing = false;
1131
+ }
1120
1132
  rl.prompt();
1121
1133
  });
1122
1134
  rl.on('close', () => {
@@ -1128,7 +1140,7 @@ async function startInteractive(options) {
1128
1140
  }
1129
1141
  function printHelp(engine) {
1130
1142
  const t = engine.ui.theme;
1131
- console.log(`\n ${t.bold('NeuroCLI v4.1.1 Commands:')}\n`);
1143
+ console.log(`\n ${t.bold('NeuroCLI v4.1.2 Commands:')}\n`);
1132
1144
  console.log(` ${t.tool('/help')} Show this help message`);
1133
1145
  console.log(` ${t.tool('/model [id]')} Switch or list models`);
1134
1146
  console.log(` ${t.tool('/agent [name]')} Switch or list agents`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neuro-cli",
3
- "version": "4.1.1",
3
+ "version": "4.1.2",
4
4
  "description": "Advanced AI-powered terminal coding assistant with multi-agent orchestration, sub-agent spawning, ACP protocol, OS-level sandboxing, spec-driven development, smart monitoring, multi-model routing, MCP Apps, auto-updater, and 23+ free models",
5
5
  "main": "dist/index.js",
6
6
  "bin": {