neuro-cli 4.3.0 → 5.0.1
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/dist/agents/base.d.ts +21 -2
- package/dist/agents/base.js +174 -31
- package/dist/agents/orchestrator.d.ts +3 -1
- package/dist/agents/orchestrator.js +32 -16
- package/dist/api/openrouter.d.ts +7 -1
- package/dist/api/openrouter.js +152 -37
- package/dist/commands/commands.js +11 -0
- package/dist/config/config.js +17 -17
- package/dist/core/engine.d.ts +8 -3
- package/dist/core/engine.js +79 -57
- package/dist/core/fallback.d.ts +7 -1
- package/dist/core/fallback.js +68 -3
- package/dist/core/model-router.d.ts +6 -0
- package/dist/core/model-router.js +43 -4
- package/dist/core/rate-limiter.d.ts +162 -0
- package/dist/core/rate-limiter.js +589 -0
- package/dist/index.js +2 -2
- package/dist/ui/renderer.d.ts +1 -1
- package/dist/ui/renderer.js +3 -2
- package/package.json +1 -1
package/dist/api/openrouter.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// ============================================================
|
|
2
2
|
// NeuroCLI - OpenRouter API Client
|
|
3
3
|
// Streaming + Tool Use + Multi-model support
|
|
4
|
+
// Now with RateLimitManager integration
|
|
4
5
|
// ============================================================
|
|
5
6
|
// @ts-ignore
|
|
6
7
|
import { createParser } from 'eventsource-parser';
|
|
@@ -9,6 +10,7 @@ export class OpenRouterClient {
|
|
|
9
10
|
apiKey;
|
|
10
11
|
baseUrl;
|
|
11
12
|
totalUsage = { inputTokens: 0, outputTokens: 0, cost: 0 };
|
|
13
|
+
rateLimiter = null;
|
|
12
14
|
constructor(apiKey, baseUrl = 'https://openrouter.ai/api/v1') {
|
|
13
15
|
this.apiKey = apiKey;
|
|
14
16
|
this.baseUrl = baseUrl;
|
|
@@ -20,15 +22,42 @@ export class OpenRouterClient {
|
|
|
20
22
|
this.totalUsage = { inputTokens: 0, outputTokens: 0, cost: 0 };
|
|
21
23
|
}
|
|
22
24
|
/**
|
|
23
|
-
*
|
|
25
|
+
* Set the rate limiter instance for this client
|
|
26
|
+
*/
|
|
27
|
+
setRateLimiter(rateLimiter) {
|
|
28
|
+
this.rateLimiter = rateLimiter;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Main chat completion with streaming + rate limit awareness
|
|
24
32
|
*/
|
|
25
33
|
async chat(request, callbacks) {
|
|
26
34
|
const model = MODELS[request.model];
|
|
27
35
|
if (!model) {
|
|
28
36
|
throw new Error(`Unknown model: ${request.model}`);
|
|
29
37
|
}
|
|
38
|
+
// --- Rate limit pre-check ---
|
|
39
|
+
let activeModel = request.model;
|
|
40
|
+
if (this.rateLimiter) {
|
|
41
|
+
const check = await this.rateLimiter.acquire(request.model);
|
|
42
|
+
if (check.suggestedModel) {
|
|
43
|
+
// Switch to the suggested alternative model
|
|
44
|
+
activeModel = check.suggestedModel;
|
|
45
|
+
callbacks?.onThinking?.(`🔄 Rate limiter rotated to ${MODELS[activeModel]?.name || activeModel}`);
|
|
46
|
+
}
|
|
47
|
+
else if (!check.allowed) {
|
|
48
|
+
// Not allowed and no alternative - wait
|
|
49
|
+
if (check.waitMs > 0) {
|
|
50
|
+
callbacks?.onThinking?.(`⏳ Rate limited, waiting ${Math.ceil(check.waitMs / 1000)}s...`);
|
|
51
|
+
await new Promise(resolve => setTimeout(resolve, check.waitMs));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const activeModelConfig = MODELS[activeModel];
|
|
56
|
+
if (!activeModelConfig) {
|
|
57
|
+
throw new Error(`Unknown model after rate limit rotation: ${activeModel}`);
|
|
58
|
+
}
|
|
30
59
|
const body = {
|
|
31
|
-
model:
|
|
60
|
+
model: activeModel,
|
|
32
61
|
messages: request.messages.map(m => ({
|
|
33
62
|
role: m.role,
|
|
34
63
|
content: m.content,
|
|
@@ -38,9 +67,9 @@ export class OpenRouterClient {
|
|
|
38
67
|
})),
|
|
39
68
|
stream: request.stream ?? true,
|
|
40
69
|
temperature: request.temperature ?? 0.7,
|
|
41
|
-
max_tokens: request.maxTokens ??
|
|
70
|
+
max_tokens: request.maxTokens ?? activeModelConfig.maxOutput,
|
|
42
71
|
};
|
|
43
|
-
if (request.tools && request.tools.length > 0 &&
|
|
72
|
+
if (request.tools && request.tools.length > 0 && activeModelConfig.supportsTools) {
|
|
44
73
|
body.tools = request.tools.map(t => ({
|
|
45
74
|
type: 'function',
|
|
46
75
|
function: {
|
|
@@ -54,47 +83,133 @@ export class OpenRouterClient {
|
|
|
54
83
|
let lastError = null;
|
|
55
84
|
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
56
85
|
if (attempt > 0) {
|
|
57
|
-
//
|
|
58
|
-
|
|
59
|
-
|
|
86
|
+
// Smart backoff: use rate limiter cooldown if available, otherwise exponential
|
|
87
|
+
let waitTime;
|
|
88
|
+
if (this.rateLimiter) {
|
|
89
|
+
const state = this.rateLimiter.getStatus().find(s => s.model === activeModel);
|
|
90
|
+
waitTime = state && state.cooldown > 0 ? state.cooldown * 1000 : Math.min(5000 * Math.pow(2, attempt - 1), 30000);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
waitTime = Math.min(5000 * Math.pow(3, attempt - 1), 30000);
|
|
94
|
+
}
|
|
95
|
+
callbacks?.onThinking?.(`⏳ Retrying in ${Math.ceil(waitTime / 1000)}s (attempt ${attempt + 1}/${maxRetries + 1})...`);
|
|
60
96
|
await new Promise(resolve => setTimeout(resolve, waitTime));
|
|
61
97
|
}
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
'
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if (response.
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
98
|
+
const startTime = Date.now();
|
|
99
|
+
try {
|
|
100
|
+
const response = await fetch(`${this.baseUrl}/chat/completions`, {
|
|
101
|
+
method: 'POST',
|
|
102
|
+
headers: {
|
|
103
|
+
'Authorization': `Bearer ${this.apiKey}`,
|
|
104
|
+
'Content-Type': 'application/json',
|
|
105
|
+
'HTTP-Referer': 'https://neurocli.dev',
|
|
106
|
+
'X-Title': 'NeuroCLI',
|
|
107
|
+
},
|
|
108
|
+
body: JSON.stringify(body),
|
|
109
|
+
});
|
|
110
|
+
const responseTimeMs = Date.now() - startTime;
|
|
111
|
+
if (!response.ok) {
|
|
112
|
+
const errorBody = await response.text();
|
|
113
|
+
// Parse retry_after from 429 errors
|
|
114
|
+
if (response.status === 429) {
|
|
115
|
+
let retryAfterSeconds;
|
|
116
|
+
try {
|
|
117
|
+
const errorData = JSON.parse(errorBody);
|
|
118
|
+
retryAfterSeconds = errorData?.error?.metadata?.retry_after_seconds;
|
|
119
|
+
}
|
|
120
|
+
catch { }
|
|
121
|
+
// Record rate limit in manager
|
|
122
|
+
if (this.rateLimiter) {
|
|
123
|
+
this.rateLimiter.recordRateLimit(activeModel, retryAfterSeconds);
|
|
124
|
+
}
|
|
125
|
+
// Try model rotation before retrying
|
|
126
|
+
if (this.rateLimiter && attempt < maxRetries) {
|
|
127
|
+
const nextModel = this.rateLimiter.getNextRotationModel(activeModel);
|
|
128
|
+
if (nextModel && nextModel !== activeModel) {
|
|
129
|
+
const nextModelConfig = MODELS[nextModel];
|
|
130
|
+
if (nextModelConfig) {
|
|
131
|
+
callbacks?.onThinking?.(`🔄 Rotating ${MODELS[activeModel]?.name || activeModel} → ${nextModelConfig.name} due to rate limit`);
|
|
132
|
+
activeModel = nextModel;
|
|
133
|
+
body.model = nextModel;
|
|
134
|
+
body.max_tokens = request.maxTokens ?? nextModelConfig.maxOutput;
|
|
135
|
+
if (request.tools && request.tools.length > 0 && nextModelConfig.supportsTools) {
|
|
136
|
+
// tools already set
|
|
137
|
+
}
|
|
138
|
+
else if (request.tools && !nextModelConfig.supportsTools) {
|
|
139
|
+
delete body.tools;
|
|
140
|
+
}
|
|
141
|
+
// Don't count this as a retry attempt for the new model
|
|
142
|
+
attempt--;
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (retryAfterSeconds && attempt < maxRetries) {
|
|
148
|
+
lastError = new Error(`Rate limited, retry after ${retryAfterSeconds}s`);
|
|
81
149
|
continue; // Retry
|
|
82
150
|
}
|
|
151
|
+
if (attempt < maxRetries) {
|
|
152
|
+
lastError = new Error(`Rate limited (429): ${errorBody}`);
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
83
155
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
156
|
+
// Server errors (5xx) - record and potentially rotate
|
|
157
|
+
if (response.status >= 500) {
|
|
158
|
+
if (this.rateLimiter) {
|
|
159
|
+
this.rateLimiter.recordServerError(activeModel);
|
|
160
|
+
}
|
|
161
|
+
if (attempt < maxRetries) {
|
|
162
|
+
lastError = new Error(`Server error (${response.status}): ${errorBody}`);
|
|
163
|
+
// Try model rotation for server errors too
|
|
164
|
+
if (this.rateLimiter) {
|
|
165
|
+
const nextModel = this.rateLimiter.getNextRotationModel(activeModel);
|
|
166
|
+
if (nextModel && nextModel !== activeModel) {
|
|
167
|
+
const nextModelConfig = MODELS[nextModel];
|
|
168
|
+
if (nextModelConfig) {
|
|
169
|
+
callbacks?.onThinking?.(`🔄 Rotating away from ${MODELS[activeModel]?.name || activeModel} due to server error`);
|
|
170
|
+
activeModel = nextModel;
|
|
171
|
+
body.model = nextModel;
|
|
172
|
+
body.max_tokens = request.maxTokens ?? nextModelConfig.maxOutput;
|
|
173
|
+
if (request.tools && request.tools.length > 0 && nextModelConfig.supportsTools) {
|
|
174
|
+
// tools already set
|
|
175
|
+
}
|
|
176
|
+
else if (request.tools && !nextModelConfig.supportsTools) {
|
|
177
|
+
delete body.tools;
|
|
178
|
+
}
|
|
179
|
+
attempt--;
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
89
186
|
}
|
|
187
|
+
throw new Error(`OpenRouter API error (${response.status}): ${errorBody}`);
|
|
188
|
+
}
|
|
189
|
+
// Success!
|
|
190
|
+
if (this.rateLimiter) {
|
|
191
|
+
this.rateLimiter.recordSuccess(activeModel, responseTimeMs);
|
|
192
|
+
}
|
|
193
|
+
if (request.stream && callbacks) {
|
|
194
|
+
const result = await this.handleStreamingResponse(response, activeModel, callbacks);
|
|
195
|
+
return result;
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
const result = await this.handleNonStreamingResponse(response, activeModel);
|
|
199
|
+
return result;
|
|
90
200
|
}
|
|
91
|
-
throw new Error(`OpenRouter API error (${response.status}): ${errorBody}`);
|
|
92
|
-
}
|
|
93
|
-
if (request.stream && callbacks) {
|
|
94
|
-
return this.handleStreamingResponse(response, request.model, callbacks);
|
|
95
201
|
}
|
|
96
|
-
|
|
97
|
-
|
|
202
|
+
catch (error) {
|
|
203
|
+
// Network-level errors (fetch failed)
|
|
204
|
+
if (error instanceof TypeError && error.message.includes('fetch')) {
|
|
205
|
+
if (this.rateLimiter) {
|
|
206
|
+
this.rateLimiter.recordServerError(activeModel);
|
|
207
|
+
}
|
|
208
|
+
lastError = error;
|
|
209
|
+
if (attempt < maxRetries)
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
throw error;
|
|
98
213
|
}
|
|
99
214
|
}
|
|
100
215
|
throw lastError || new Error('Max retries exceeded');
|
|
@@ -297,6 +297,17 @@ export class CommandSystem {
|
|
|
297
297
|
description: 'Browser automation (navigate/screenshot/click)',
|
|
298
298
|
prompt: 'Use the browser to navigate, take screenshots, click elements, or extract content from web pages. {args}',
|
|
299
299
|
},
|
|
300
|
+
// --- Rate Limit Commands ---
|
|
301
|
+
{
|
|
302
|
+
name: 'ratelimit',
|
|
303
|
+
description: 'Show rate limiter status for all models',
|
|
304
|
+
prompt: 'Show the current rate limiter status. Display health scores, cooldowns, 429 counts, and queue status for all tracked models. {args}',
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
name: 'ratelimit-reset',
|
|
308
|
+
description: 'Reset rate limiter state',
|
|
309
|
+
prompt: 'Reset all rate limiter cooldowns and health scores. Use this if models are stuck in cooldown. {args}',
|
|
310
|
+
},
|
|
300
311
|
];
|
|
301
312
|
for (const cmd of bundled) {
|
|
302
313
|
if (!this.commands.has(cmd.name)) {
|
package/dist/config/config.js
CHANGED
|
@@ -14,82 +14,82 @@ export const DEFAULT_CONFIG = {
|
|
|
14
14
|
planner: {
|
|
15
15
|
name: 'Planner',
|
|
16
16
|
description: 'Task decomposition and planning specialist',
|
|
17
|
-
systemPrompt: `You are an expert software architect and planner. Your job is to break down complex tasks into clear, actionable steps. For each step, specify which agent should handle it and what tools they should use. Be thorough but concise.`,
|
|
17
|
+
systemPrompt: `You are an expert software architect and planner. Your job is to break down complex tasks into clear, actionable steps. For each step, specify which agent should handle it and what tools they should use. Be thorough but concise. Keep working until you have a COMPLETE plan covering every aspect of the task.`,
|
|
18
18
|
model: 'qwen/qwen3-coder:free',
|
|
19
19
|
temperature: 0.7,
|
|
20
20
|
maxTokens: 4096,
|
|
21
21
|
tools: ['read_file', 'search_files', 'list_directory'],
|
|
22
|
-
maxIterations:
|
|
22
|
+
maxIterations: 0, // 0 = no limit, run until done
|
|
23
23
|
},
|
|
24
24
|
coder: {
|
|
25
25
|
name: 'Coder',
|
|
26
26
|
description: 'Code generation and modification specialist',
|
|
27
|
-
systemPrompt: `You are an expert software developer. You write clean, efficient, well-documented code. You understand design patterns, best practices, and can work with any programming language or framework. When modifying existing code, you make minimal, targeted changes. Always consider edge cases and error handling.`,
|
|
27
|
+
systemPrompt: `You are an expert software developer. You write clean, efficient, well-documented code. You understand design patterns, best practices, and can work with any programming language or framework. When modifying existing code, you make minimal, targeted changes. Always consider edge cases and error handling. IMPORTANT: You MUST keep working until the entire task is COMPLETE — do not stop after creating only some files. Create ALL necessary files, update ALL imports, and verify your work.`,
|
|
28
28
|
model: 'qwen/qwen3-coder:free',
|
|
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:
|
|
32
|
+
maxIterations: 0, // 0 = no limit, run until done
|
|
33
33
|
},
|
|
34
34
|
reviewer: {
|
|
35
35
|
name: 'Reviewer',
|
|
36
36
|
description: 'Code review and quality assurance specialist',
|
|
37
|
-
systemPrompt: `You are an expert code reviewer. You analyze code for bugs, security vulnerabilities, performance issues, and adherence to best practices. You provide specific, actionable feedback with line references. You categorize issues by severity (critical, warning, suggestion). You also check for test coverage and documentation.`,
|
|
37
|
+
systemPrompt: `You are an expert code reviewer. You analyze code for bugs, security vulnerabilities, performance issues, and adherence to best practices. You provide specific, actionable feedback with line references. You categorize issues by severity (critical, warning, suggestion). You also check for test coverage and documentation. Keep reviewing until you have checked ALL relevant files.`,
|
|
38
38
|
model: 'nvidia/nemotron-3-super-120b-a12b:free',
|
|
39
39
|
temperature: 0.3,
|
|
40
40
|
maxTokens: 8192,
|
|
41
41
|
tools: ['read_file', 'search_files', 'list_directory'],
|
|
42
|
-
maxIterations:
|
|
42
|
+
maxIterations: 0,
|
|
43
43
|
},
|
|
44
44
|
researcher: {
|
|
45
45
|
name: 'Researcher',
|
|
46
46
|
description: 'Information gathering and analysis specialist',
|
|
47
|
-
systemPrompt: `You are an expert researcher and analyst. You gather information from files, web resources, and codebases. You synthesize findings into clear, structured reports. You can explain complex technical concepts and find relevant examples or documentation.`,
|
|
47
|
+
systemPrompt: `You are an expert researcher and analyst. You gather information from files, web resources, and codebases. You synthesize findings into clear, structured reports. You can explain complex technical concepts and find relevant examples or documentation. Keep researching until you have a COMPLETE picture.`,
|
|
48
48
|
model: 'google/gemma-4-31b-it:free',
|
|
49
49
|
temperature: 0.5,
|
|
50
50
|
maxTokens: 8192,
|
|
51
51
|
tools: ['read_file', 'search_files', 'list_directory', 'web_search', 'web_fetch'],
|
|
52
|
-
maxIterations:
|
|
52
|
+
maxIterations: 0,
|
|
53
53
|
},
|
|
54
54
|
tester: {
|
|
55
55
|
name: 'Tester',
|
|
56
56
|
description: 'Test generation and execution specialist',
|
|
57
|
-
systemPrompt: `You are an expert QA engineer. You write comprehensive test suites covering unit tests, integration tests, and edge cases. You run tests and analyze failures to identify root causes. You ensure code meets quality standards before it's considered complete.`,
|
|
57
|
+
systemPrompt: `You are an expert QA engineer. You write comprehensive test suites covering unit tests, integration tests, and edge cases. You run tests and analyze failures to identify root causes. You ensure code meets quality standards before it's considered complete. Keep testing until ALL tests pass.`,
|
|
58
58
|
model: 'qwen/qwen3-coder:free',
|
|
59
59
|
temperature: 0.3,
|
|
60
60
|
maxTokens: 8192,
|
|
61
61
|
tools: ['read_file', 'write_file', 'search_files', 'run_command', 'list_directory'],
|
|
62
|
-
maxIterations:
|
|
62
|
+
maxIterations: 0,
|
|
63
63
|
},
|
|
64
64
|
debugger: {
|
|
65
65
|
name: 'Debugger',
|
|
66
66
|
description: 'Bug investigation and fixing specialist',
|
|
67
|
-
systemPrompt: `You are an expert debugger. You systematically investigate bugs by reading code, running diagnostic commands, analyzing error messages and stack traces. You identify root causes and implement targeted fixes. You verify fixes work before reporting completion.`,
|
|
67
|
+
systemPrompt: `You are an expert debugger. You systematically investigate bugs by reading code, running diagnostic commands, analyzing error messages and stack traces. You identify root causes and implement targeted fixes. You verify fixes work before reporting completion. Keep debugging until the bug is COMPLETELY fixed and verified.`,
|
|
68
68
|
model: 'qwen/qwen3-coder:free',
|
|
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:
|
|
72
|
+
maxIterations: 0,
|
|
73
73
|
},
|
|
74
74
|
architect: {
|
|
75
75
|
name: 'Architect',
|
|
76
76
|
description: 'System design and architecture specialist',
|
|
77
|
-
systemPrompt: `You are an expert software architect. You design scalable, maintainable system architectures. You make technology stack decisions, define component boundaries, and establish coding standards. You create detailed technical specifications that other agents can implement.`,
|
|
77
|
+
systemPrompt: `You are an expert software architect. You design scalable, maintainable system architectures. You make technology stack decisions, define component boundaries, and establish coding standards. You create detailed technical specifications that other agents can implement. Keep designing until the architecture is COMPLETE and all components are specified.`,
|
|
78
78
|
model: 'nvidia/nemotron-3-ultra-550b-a55b:free',
|
|
79
79
|
temperature: 0.7,
|
|
80
80
|
maxTokens: 8192,
|
|
81
81
|
tools: ['read_file', 'search_files', 'list_directory'],
|
|
82
|
-
maxIterations:
|
|
82
|
+
maxIterations: 0,
|
|
83
83
|
},
|
|
84
84
|
devops: {
|
|
85
85
|
name: 'DevOps',
|
|
86
86
|
description: 'Deployment and infrastructure specialist',
|
|
87
|
-
systemPrompt: `You are an expert DevOps engineer. You handle CI/CD pipelines, Docker configurations, cloud deployments, and infrastructure as code. You optimize build processes and ensure reliable deployments.`,
|
|
87
|
+
systemPrompt: `You are an expert DevOps engineer. You handle CI/CD pipelines, Docker configurations, cloud deployments, and infrastructure as code. You optimize build processes and ensure reliable deployments. Keep working until the deployment is FULLY configured and verified.`,
|
|
88
88
|
model: 'cohere/north-mini-code:free',
|
|
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:
|
|
92
|
+
maxIterations: 0,
|
|
93
93
|
},
|
|
94
94
|
},
|
|
95
95
|
tools: {
|
|
@@ -208,7 +208,7 @@ export const DEFAULT_CONFIG = {
|
|
|
208
208
|
autoMode: {
|
|
209
209
|
enabled: false,
|
|
210
210
|
safetyLevel: 'conservative',
|
|
211
|
-
maxIterations:
|
|
211
|
+
maxIterations: 0, // 0 = no limit, run until done (Claude Code style)
|
|
212
212
|
maxCost: 0,
|
|
213
213
|
maxTimeMs: 0,
|
|
214
214
|
blockedCommands: ['rm -rf /', 'mkfs', 'dd if=/dev/zero'],
|
package/dist/core/engine.d.ts
CHANGED
|
@@ -57,6 +57,7 @@ import { TerminalUX } from './terminal-ux.js';
|
|
|
57
57
|
import { MultiSessionManager } from './multi-session.js';
|
|
58
58
|
import { GitWorktreeManager } from './git-worktree.js';
|
|
59
59
|
import { AutoUpdater } from './updater.js';
|
|
60
|
+
import { RateLimitManager } from './rate-limiter.js';
|
|
60
61
|
export declare class NeuroEngine {
|
|
61
62
|
config: NeuroConfig;
|
|
62
63
|
client: OpenRouterClient;
|
|
@@ -117,6 +118,7 @@ export declare class NeuroEngine {
|
|
|
117
118
|
multiSession: MultiSessionManager;
|
|
118
119
|
gitWorktree: GitWorktreeManager;
|
|
119
120
|
updater: AutoUpdater;
|
|
121
|
+
rateLimiter: RateLimitManager;
|
|
120
122
|
private autoApproveSet;
|
|
121
123
|
private requireApprovalSet;
|
|
122
124
|
constructor(config: NeuroConfig);
|
|
@@ -137,7 +139,9 @@ export declare class NeuroEngine {
|
|
|
137
139
|
*/
|
|
138
140
|
private initializeAgents;
|
|
139
141
|
/**
|
|
140
|
-
* Process a user message
|
|
142
|
+
* Process a user message — Claude Code style
|
|
143
|
+
* Every task is sent to the best agent which runs until completion.
|
|
144
|
+
* No arbitrary early termination — the agent keeps working until done.
|
|
141
145
|
*/
|
|
142
146
|
processMessage(message: string, mode?: 'auto' | 'agent' | 'direct', targetAgent?: string): Promise<{
|
|
143
147
|
content: string;
|
|
@@ -153,8 +157,9 @@ export declare class NeuroEngine {
|
|
|
153
157
|
*/
|
|
154
158
|
private handleApproval;
|
|
155
159
|
/**
|
|
156
|
-
* Assess task complexity
|
|
157
|
-
*
|
|
160
|
+
* Assess task complexity — delegates to ModelRouter
|
|
161
|
+
* Note: complexity no longer determines execution mode (all tasks run until complete)
|
|
162
|
+
* but is still used for model selection
|
|
158
163
|
*/
|
|
159
164
|
private assessComplexity;
|
|
160
165
|
/**
|