neuro-cli 4.1.3 → 4.2.0

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.
@@ -192,7 +192,7 @@ export class BaseAgent {
192
192
  }
193
193
  if (iteration > maxIter && execution.status === 'running') {
194
194
  execution.status = 'completed';
195
- execution.result = 'Max iterations reached';
195
+ execution.result = `Max iterations reached (${maxIter}). The task may not be fully completed. Consider using a higher effort level or switching to /orchestrate mode for complex tasks.`;
196
196
  }
197
197
  execution.endTime = Date.now();
198
198
  execution.iterations = iteration;
@@ -19,7 +19,7 @@ export const DEFAULT_CONFIG = {
19
19
  temperature: 0.7,
20
20
  maxTokens: 4096,
21
21
  tools: ['read_file', 'search_files', 'list_directory'],
22
- maxIterations: 3,
22
+ maxIterations: 10,
23
23
  },
24
24
  coder: {
25
25
  name: 'Coder',
@@ -29,7 +29,7 @@ export const DEFAULT_CONFIG = {
29
29
  temperature: 0.4,
30
30
  maxTokens: 16384,
31
31
  tools: ['read_file', 'write_file', 'edit_file', 'search_files', 'list_directory', 'run_command', 'apply_diff'],
32
- maxIterations: 15,
32
+ maxIterations: 50,
33
33
  },
34
34
  reviewer: {
35
35
  name: 'Reviewer',
@@ -39,7 +39,7 @@ export const DEFAULT_CONFIG = {
39
39
  temperature: 0.3,
40
40
  maxTokens: 8192,
41
41
  tools: ['read_file', 'search_files', 'list_directory'],
42
- maxIterations: 5,
42
+ maxIterations: 15,
43
43
  },
44
44
  researcher: {
45
45
  name: 'Researcher',
@@ -49,7 +49,7 @@ export const DEFAULT_CONFIG = {
49
49
  temperature: 0.5,
50
50
  maxTokens: 8192,
51
51
  tools: ['read_file', 'search_files', 'list_directory', 'web_search', 'web_fetch'],
52
- maxIterations: 8,
52
+ maxIterations: 20,
53
53
  },
54
54
  tester: {
55
55
  name: 'Tester',
@@ -59,7 +59,7 @@ export const DEFAULT_CONFIG = {
59
59
  temperature: 0.3,
60
60
  maxTokens: 8192,
61
61
  tools: ['read_file', 'write_file', 'search_files', 'run_command', 'list_directory'],
62
- maxIterations: 10,
62
+ maxIterations: 25,
63
63
  },
64
64
  debugger: {
65
65
  name: 'Debugger',
@@ -69,7 +69,7 @@ export const DEFAULT_CONFIG = {
69
69
  temperature: 0.2,
70
70
  maxTokens: 8192,
71
71
  tools: ['read_file', 'edit_file', 'search_files', 'run_command', 'list_directory', 'apply_diff'],
72
- maxIterations: 12,
72
+ maxIterations: 20,
73
73
  },
74
74
  architect: {
75
75
  name: 'Architect',
@@ -79,7 +79,7 @@ export const DEFAULT_CONFIG = {
79
79
  temperature: 0.7,
80
80
  maxTokens: 8192,
81
81
  tools: ['read_file', 'search_files', 'list_directory'],
82
- maxIterations: 5,
82
+ maxIterations: 15,
83
83
  },
84
84
  devops: {
85
85
  name: 'DevOps',
@@ -89,7 +89,7 @@ export const DEFAULT_CONFIG = {
89
89
  temperature: 0.3,
90
90
  maxTokens: 8192,
91
91
  tools: ['read_file', 'write_file', 'edit_file', 'run_command', 'search_files', 'list_directory'],
92
- maxIterations: 10,
92
+ maxIterations: 25,
93
93
  },
94
94
  },
95
95
  tools: {
@@ -344,27 +344,36 @@ export class ApprovalSystem {
344
344
  readline(prompt) {
345
345
  // Pause the main readline to prevent it from also reading stdin input
346
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();
347
+ if (this.mainRl) {
348
+ const mainInputStream = this.mainRl?.input;
349
+ if (mainInputStream && !mainInputStream.isPaused()) {
350
+ this.mainRl.pause();
351
+ }
354
352
  }
355
353
  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
- });
354
+ // Use the main readline's question method directly - it handles pause/resume internally
355
+ if (this.mainRl) {
356
+ this.mainRl.question(prompt, (answer) => {
357
+ // Resume the main readline after getting the answer
358
+ if (this.mainRl) {
359
+ this.mainRl.resume();
360
+ this.mainRl.prompt();
361
+ }
362
+ resolve(answer);
363
+ });
364
+ }
365
+ else if (this.rl) {
366
+ this.rl.question(prompt, (answer) => {
367
+ resolve(answer);
368
+ });
369
+ }
370
+ else {
371
+ const tempRl = createInterface({ input: process.stdin, output: process.stdout });
372
+ this.rl = tempRl;
373
+ tempRl.question(prompt, (answer) => {
374
+ resolve(answer);
375
+ });
376
+ }
368
377
  });
369
378
  }
370
379
  close() {
@@ -157,6 +157,10 @@ export declare class NeuroEngine {
157
157
  * Now delegates to ModelRouter for more sophisticated analysis
158
158
  */
159
159
  private assessComplexity;
160
+ /**
161
+ * Select the best agent for a given task category
162
+ */
163
+ private selectAgentForCategory;
160
164
  /**
161
165
  * Switch the active model
162
166
  */
@@ -537,7 +537,7 @@ Always consider the strengths of each agent when delegating:
537
537
  temperature: 0.7,
538
538
  maxTokens: 4096,
539
539
  tools: [],
540
- maxIterations: 5,
540
+ maxIterations: 20,
541
541
  };
542
542
  this.orchestrator = new Orchestrator(orchestratorConfig, this.client, this.registry, process.cwd(), this.sessionManager.getCurrent()?.id || 'default');
543
543
  // Register all agents with orchestrator
@@ -622,7 +622,7 @@ Always consider the strengths of each agent when delegating:
622
622
  const cwd = process.cwd();
623
623
  // Built-in agents
624
624
  for (const [key, agentConfig] of Object.entries(this.config.agents)) {
625
- const overrideConfig = { ...agentConfig, model: this.config.defaultModel };
625
+ const overrideConfig = { ...agentConfig };
626
626
  const agent = new BaseAgent(overrideConfig, this.client, this.registry, cwd, sessionId);
627
627
  this.agents.set(agentConfig.name, agent);
628
628
  }
@@ -750,9 +750,13 @@ Always consider the strengths of each agent when delegating:
750
750
  }
751
751
  else {
752
752
  const complexity = routeDecision?.complexity || this.assessComplexity(message);
753
+ const category = routeDecision?.category || this.modelRouter.getCategory(message);
753
754
  if (complexity === 'simple') {
754
- const agent = this.agents.get('Coder');
755
+ // Route to the best agent based on task category
756
+ const targetAgentName = this.selectAgentForCategory(category);
757
+ const agent = this.agents.get(targetAgentName);
755
758
  if (agent) {
759
+ this.ui.info(`Using ${targetAgentName} agent (${category} task)`);
756
760
  this.ui.startStreaming();
757
761
  try {
758
762
  result = await agent.run(message, callbacks);
@@ -762,16 +766,28 @@ Always consider the strengths of each agent when delegating:
762
766
  }
763
767
  }
764
768
  else {
765
- // Fallback to orchestration instead of crashing
766
- this.ui.warning('Coder agent not initialized, using orchestration mode');
767
- const orchestrateResult = await this.orchestrator.orchestrate(message, callbacks);
768
- result = {
769
- content: orchestrateResult.content,
770
- toolCallsMade: 0,
771
- iterations: orchestrateResult.execution.iterations,
772
- usage: orchestrateResult.totalUsage,
773
- execution: orchestrateResult.execution,
774
- };
769
+ // Fallback to Coder
770
+ const coderAgent = this.agents.get('Coder');
771
+ if (coderAgent) {
772
+ this.ui.startStreaming();
773
+ try {
774
+ result = await coderAgent.run(message, callbacks);
775
+ }
776
+ finally {
777
+ this.ui.endStreaming();
778
+ }
779
+ }
780
+ else {
781
+ this.ui.warning('No agents initialized, using orchestration mode');
782
+ const orchestrateResult = await this.orchestrator.orchestrate(message, callbacks);
783
+ result = {
784
+ content: orchestrateResult.content,
785
+ toolCallsMade: 0,
786
+ iterations: orchestrateResult.execution.iterations,
787
+ usage: orchestrateResult.totalUsage,
788
+ execution: orchestrateResult.execution,
789
+ };
790
+ }
775
791
  }
776
792
  }
777
793
  else {
@@ -905,6 +921,22 @@ Always consider the strengths of each agent when delegating:
905
921
  const decision = this.modelRouter.route(message);
906
922
  return decision.complexity;
907
923
  }
924
+ /**
925
+ * Select the best agent for a given task category
926
+ */
927
+ selectAgentForCategory(category) {
928
+ const categoryAgentMap = {
929
+ code: 'Coder',
930
+ reasoning: 'Architect',
931
+ creative: 'Coder',
932
+ analysis: 'Researcher',
933
+ conversation: 'Coder',
934
+ debugging: 'Debugger',
935
+ review: 'Reviewer',
936
+ refactoring: 'Coder',
937
+ };
938
+ return categoryAgentMap[category] || 'Coder';
939
+ }
908
940
  /**
909
941
  * Switch the active model
910
942
  */
@@ -72,7 +72,7 @@ const COMPLEXITY_SIGNALS = {
72
72
  /\b(hello|hi|thanks|yes|no|ok|sure|done|correct|right|please)\b/i,
73
73
  ],
74
74
  lengthThreshold: 80,
75
- maxSteps: 1,
75
+ maxSteps: 5,
76
76
  },
77
77
  moderate: {
78
78
  patterns: [
@@ -83,7 +83,7 @@ const COMPLEXITY_SIGNALS = {
83
83
  /\b(refactor|clean|simplify|optimize|restructure)\b/i,
84
84
  ],
85
85
  lengthThreshold: 300,
86
- maxSteps: 3,
86
+ maxSteps: 15,
87
87
  },
88
88
  complex: {
89
89
  patterns: [
@@ -97,7 +97,7 @@ const COMPLEXITY_SIGNALS = {
97
97
  /\b(security\s+(audit|review|hardening)|performance\s+(optim|tuning|profiling)|scalab(ility|le))\b/i,
98
98
  ],
99
99
  lengthThreshold: 500,
100
- maxSteps: 6,
100
+ maxSteps: 30,
101
101
  },
102
102
  };
103
103
  // ---------------------------------------------------------------------------
package/dist/index.js CHANGED
@@ -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.3';
19
+ const VERSION = '4.2.0';
20
20
  // ---- Global Error Handlers (prevent crashes) ----
21
21
  process.on('unhandledRejection', (reason) => {
22
22
  console.error(chalk.red('\n⚠️ Unhandled promise rejection:'), reason);
@@ -462,10 +462,6 @@ async function startInteractive(options) {
462
462
  rl.prompt();
463
463
  return;
464
464
  }
465
- // Prevent input while processing (approval prompt may be active)
466
- if (isProcessing) {
467
- return;
468
- }
469
465
  // Add to history
470
466
  completionEngine.addHistory(input);
471
467
  // Handle slash commands
@@ -937,7 +933,7 @@ async function startInteractive(options) {
937
933
  }
938
934
  break;
939
935
  case 'doctor':
940
- console.log(chalk.bold('\nNeuroCLI v4.1.2 Health Check:\n'));
936
+ console.log(chalk.bold('\nNeuroCLI v' + VERSION + ' Health Check:\n'));
941
937
  console.log(` API Key: ${config.apiKey ? chalk.green('configured') : chalk.red('MISSING')}`);
942
938
  console.log(` Default Model: ${chalk.cyan(config.defaultModel)} ${MODELS[config.defaultModel] ? chalk.green('valid') : chalk.red('INVALID')}`);
943
939
  console.log(` MCP Servers: ${chalk.cyan(String(engine.mcpClient.listServers().length))}`);
@@ -1139,6 +1135,11 @@ async function startInteractive(options) {
1139
1135
  return;
1140
1136
  }
1141
1137
  // Process message with the engine
1138
+ if (isProcessing) {
1139
+ engine.ui.warning('Still processing previous request. Please wait...');
1140
+ rl.prompt();
1141
+ return;
1142
+ }
1142
1143
  try {
1143
1144
  isProcessing = true;
1144
1145
  await engine.processMessage(input, currentMode, currentAgent);
@@ -1177,7 +1178,7 @@ async function startInteractive(options) {
1177
1178
  }
1178
1179
  function printHelp(engine) {
1179
1180
  const t = engine.ui.theme;
1180
- console.log(`\n ${t.bold('NeuroCLI v4.1.2 Commands:')}\n`);
1181
+ console.log(`\n ${t.bold(`NeuroCLI v${VERSION} Commands:`)}\n`);
1181
1182
  console.log(` ${t.tool('/help')} Show this help message`);
1182
1183
  console.log(` ${t.tool('/model [id]')} Switch or list models`);
1183
1184
  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.3",
3
+ "version": "4.2.0",
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": {