@juspay/neurolink 7.0.0 → 7.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.
- package/CHANGELOG.md +15 -4
- package/README.md +16 -11
- package/dist/cli/commands/config.d.ts +2 -2
- package/dist/cli/commands/config.js +22 -21
- package/dist/cli/commands/mcp.d.ts +79 -0
- package/dist/cli/commands/mcp.js +916 -0
- package/dist/cli/commands/models.d.ts +63 -0
- package/dist/cli/commands/models.js +653 -0
- package/dist/cli/commands/ollama.js +56 -55
- package/dist/cli/factories/commandFactory.d.ts +67 -2
- package/dist/cli/factories/commandFactory.js +840 -92
- package/dist/cli/index.d.ts +6 -0
- package/dist/cli/index.js +42 -999
- package/dist/cli/utils/completeSetup.js +9 -8
- package/dist/cli/utils/envManager.js +7 -6
- package/dist/cli/utils/interactiveSetup.js +20 -19
- package/dist/core/analytics.js +25 -38
- package/dist/core/baseProvider.d.ts +8 -0
- package/dist/core/baseProvider.js +177 -68
- package/dist/core/constants.d.ts +11 -0
- package/dist/core/constants.js +17 -0
- package/dist/core/evaluation.js +25 -14
- package/dist/core/factory.js +21 -18
- package/dist/core/streamAnalytics.d.ts +65 -0
- package/dist/core/streamAnalytics.js +125 -0
- package/dist/factories/providerRegistry.js +3 -1
- package/dist/lib/core/analytics.js +25 -38
- package/dist/lib/core/baseProvider.d.ts +8 -0
- package/dist/lib/core/baseProvider.js +177 -68
- package/dist/lib/core/constants.d.ts +11 -0
- package/dist/lib/core/constants.js +17 -0
- package/dist/lib/core/evaluation.js +25 -14
- package/dist/lib/core/factory.js +22 -18
- package/dist/lib/core/streamAnalytics.d.ts +65 -0
- package/dist/lib/core/streamAnalytics.js +125 -0
- package/dist/lib/factories/providerRegistry.js +3 -1
- package/dist/lib/mcp/toolRegistry.d.ts +5 -0
- package/dist/lib/mcp/toolRegistry.js +60 -0
- package/dist/lib/models/modelRegistry.d.ts +132 -0
- package/dist/lib/models/modelRegistry.js +483 -0
- package/dist/lib/models/modelResolver.d.ts +115 -0
- package/dist/lib/models/modelResolver.js +467 -0
- package/dist/lib/neurolink.d.ts +4 -1
- package/dist/lib/neurolink.js +108 -69
- package/dist/lib/providers/anthropic.js +3 -0
- package/dist/lib/providers/googleAiStudio.js +13 -0
- package/dist/lib/providers/huggingFace.js +15 -3
- package/dist/lib/providers/mistral.js +19 -7
- package/dist/lib/providers/ollama.js +31 -7
- package/dist/lib/providers/openAI.js +12 -0
- package/dist/lib/sdk/toolRegistration.js +17 -0
- package/dist/lib/types/cli.d.ts +56 -1
- package/dist/lib/types/contextTypes.d.ts +110 -0
- package/dist/lib/types/contextTypes.js +176 -0
- package/dist/lib/types/index.d.ts +4 -1
- package/dist/lib/types/mcpTypes.d.ts +118 -7
- package/dist/lib/types/providers.d.ts +81 -0
- package/dist/lib/types/streamTypes.d.ts +44 -7
- package/dist/lib/types/tools.d.ts +9 -0
- package/dist/lib/types/universalProviderOptions.d.ts +3 -1
- package/dist/lib/types/universalProviderOptions.js +2 -1
- package/dist/lib/utils/logger.d.ts +7 -0
- package/dist/lib/utils/logger.js +16 -6
- package/dist/lib/utils/performance.d.ts +105 -0
- package/dist/lib/utils/performance.js +210 -0
- package/dist/lib/utils/providerUtils.js +9 -2
- package/dist/lib/utils/retryHandler.d.ts +89 -0
- package/dist/lib/utils/retryHandler.js +269 -0
- package/dist/mcp/toolRegistry.d.ts +5 -0
- package/dist/mcp/toolRegistry.js +60 -0
- package/dist/models/modelRegistry.d.ts +132 -0
- package/dist/models/modelRegistry.js +483 -0
- package/dist/models/modelResolver.d.ts +115 -0
- package/dist/models/modelResolver.js +468 -0
- package/dist/neurolink.d.ts +4 -1
- package/dist/neurolink.js +108 -69
- package/dist/providers/anthropic.js +3 -0
- package/dist/providers/googleAiStudio.js +13 -0
- package/dist/providers/huggingFace.js +15 -3
- package/dist/providers/mistral.js +19 -7
- package/dist/providers/ollama.js +31 -7
- package/dist/providers/openAI.js +12 -0
- package/dist/sdk/toolRegistration.js +17 -0
- package/dist/types/cli.d.ts +56 -1
- package/dist/types/contextTypes.d.ts +110 -0
- package/dist/types/contextTypes.js +177 -0
- package/dist/types/index.d.ts +4 -1
- package/dist/types/mcpTypes.d.ts +118 -7
- package/dist/types/providers.d.ts +81 -0
- package/dist/types/streamTypes.d.ts +44 -7
- package/dist/types/tools.d.ts +9 -0
- package/dist/types/universalProviderOptions.d.ts +3 -1
- package/dist/types/universalProviderOptions.js +3 -1
- package/dist/utils/logger.d.ts +7 -0
- package/dist/utils/logger.js +16 -6
- package/dist/utils/performance.d.ts +105 -0
- package/dist/utils/performance.js +210 -0
- package/dist/utils/providerUtils.js +9 -2
- package/dist/utils/retryHandler.d.ts +89 -0
- package/dist/utils/retryHandler.js +269 -0
- package/package.json +2 -1
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retry and resilience utilities for NeuroLink
|
|
3
|
+
* Part of Sub-phase 3.3.3 - Edge Case Handling
|
|
4
|
+
*/
|
|
5
|
+
import { logger } from "./logger.js";
|
|
6
|
+
import { SYSTEM_LIMITS } from "../core/constants.js";
|
|
7
|
+
/**
|
|
8
|
+
* Calculate exponential backoff delay with jitter
|
|
9
|
+
* @param attempt - Current attempt number (1-based)
|
|
10
|
+
* @param initialDelay - Initial delay in milliseconds
|
|
11
|
+
* @param multiplier - Backoff multiplier for exponential growth
|
|
12
|
+
* @param maxDelay - Maximum delay cap in milliseconds
|
|
13
|
+
* @param addJitter - Whether to add random jitter to prevent thundering herd
|
|
14
|
+
* @returns Calculated delay in milliseconds
|
|
15
|
+
*/
|
|
16
|
+
export function calculateBackoffDelay(attempt, initialDelay = SYSTEM_LIMITS.DEFAULT_INITIAL_DELAY, multiplier = SYSTEM_LIMITS.DEFAULT_BACKOFF_MULTIPLIER, maxDelay = SYSTEM_LIMITS.DEFAULT_MAX_DELAY, addJitter = true) {
|
|
17
|
+
// Calculate exponential backoff
|
|
18
|
+
const exponentialDelay = initialDelay * Math.pow(multiplier, attempt - 1);
|
|
19
|
+
// Apply maximum delay cap
|
|
20
|
+
const cappedDelay = Math.min(exponentialDelay, maxDelay);
|
|
21
|
+
// Add jitter to avoid thundering herd (up to 10% of delay, max 1 second)
|
|
22
|
+
const jitter = addJitter
|
|
23
|
+
? Math.random() * Math.min(cappedDelay * 0.1, 1000)
|
|
24
|
+
: 0;
|
|
25
|
+
return cappedDelay + jitter;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Error types that are typically retryable
|
|
29
|
+
*/
|
|
30
|
+
export class NetworkError extends Error {
|
|
31
|
+
cause;
|
|
32
|
+
constructor(message, cause) {
|
|
33
|
+
super(message);
|
|
34
|
+
this.cause = cause;
|
|
35
|
+
this.name = "NetworkError";
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export class TemporaryError extends Error {
|
|
39
|
+
cause;
|
|
40
|
+
constructor(message, cause) {
|
|
41
|
+
super(message);
|
|
42
|
+
this.cause = cause;
|
|
43
|
+
this.name = "TemporaryError";
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Default retry configuration
|
|
48
|
+
*/
|
|
49
|
+
export const DEFAULT_RETRY_CONFIG = {
|
|
50
|
+
maxAttempts: SYSTEM_LIMITS.DEFAULT_RETRY_ATTEMPTS,
|
|
51
|
+
initialDelay: SYSTEM_LIMITS.DEFAULT_INITIAL_DELAY,
|
|
52
|
+
maxDelay: SYSTEM_LIMITS.DEFAULT_MAX_DELAY,
|
|
53
|
+
backoffMultiplier: SYSTEM_LIMITS.DEFAULT_BACKOFF_MULTIPLIER,
|
|
54
|
+
retryCondition: (error) => {
|
|
55
|
+
// Retry on network errors, timeouts, and specific HTTP errors
|
|
56
|
+
if (error instanceof NetworkError || error instanceof TemporaryError) {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
// Retry on timeout errors
|
|
60
|
+
if (error &&
|
|
61
|
+
typeof error === "object" &&
|
|
62
|
+
(error.name === "TimeoutError" ||
|
|
63
|
+
error.code === "TIMEOUT")) {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
// Retry on network-related errors
|
|
67
|
+
if (error &&
|
|
68
|
+
typeof error === "object" &&
|
|
69
|
+
(error.code === "ECONNRESET" ||
|
|
70
|
+
error.code === "ENOTFOUND" ||
|
|
71
|
+
error.code === "ECONNREFUSED" ||
|
|
72
|
+
error.code === "ETIMEDOUT")) {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
// Retry on HTTP 5xx errors and some 4xx errors
|
|
76
|
+
if (error &&
|
|
77
|
+
typeof error === "object" &&
|
|
78
|
+
error.status) {
|
|
79
|
+
const status = Number(error.status);
|
|
80
|
+
return status >= 500 || status === 429 || status === 408;
|
|
81
|
+
}
|
|
82
|
+
// Don't retry by default
|
|
83
|
+
return false;
|
|
84
|
+
},
|
|
85
|
+
onRetry: (attempt, error) => {
|
|
86
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
87
|
+
logger.warn(`⚠️ Retry attempt ${attempt}: ${message}`);
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Sleep utility for retry delays
|
|
92
|
+
*/
|
|
93
|
+
function sleep(ms) {
|
|
94
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Execute an operation with retry logic
|
|
98
|
+
*/
|
|
99
|
+
export async function withRetry(operation, options = {}) {
|
|
100
|
+
const config = { ...DEFAULT_RETRY_CONFIG, ...options };
|
|
101
|
+
let lastError;
|
|
102
|
+
for (let attempt = 1; attempt <= config.maxAttempts; attempt++) {
|
|
103
|
+
try {
|
|
104
|
+
return await operation();
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
lastError = error;
|
|
108
|
+
// Don't retry if it's the last attempt
|
|
109
|
+
if (attempt === config.maxAttempts) {
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
// Check if we should retry this error
|
|
113
|
+
if (!config.retryCondition(error)) {
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
// Call retry callback
|
|
117
|
+
config.onRetry(attempt, error);
|
|
118
|
+
// Calculate delay with exponential backoff and jitter
|
|
119
|
+
const jitteredDelay = calculateBackoffDelay(attempt, config.initialDelay, config.backoffMultiplier, config.maxDelay, true);
|
|
120
|
+
await sleep(jitteredDelay);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
throw lastError;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Enhanced timeout with retry for network operations
|
|
127
|
+
*/
|
|
128
|
+
export async function withTimeoutAndRetry(operation, timeoutMs, retryOptions = {}) {
|
|
129
|
+
return withRetry(async () => {
|
|
130
|
+
return new Promise((resolve, reject) => {
|
|
131
|
+
const timeout = setTimeout(() => {
|
|
132
|
+
reject(new NetworkError(`Operation timed out after ${timeoutMs}ms`));
|
|
133
|
+
}, timeoutMs);
|
|
134
|
+
operation()
|
|
135
|
+
.then((result) => {
|
|
136
|
+
clearTimeout(timeout);
|
|
137
|
+
resolve(result);
|
|
138
|
+
})
|
|
139
|
+
.catch((error) => {
|
|
140
|
+
clearTimeout(timeout);
|
|
141
|
+
reject(error);
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
}, retryOptions);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Circuit breaker pattern for preventing cascading failures
|
|
148
|
+
*/
|
|
149
|
+
export class CircuitBreaker {
|
|
150
|
+
threshold;
|
|
151
|
+
timeout;
|
|
152
|
+
monitorWindow;
|
|
153
|
+
failures = 0;
|
|
154
|
+
lastFailureTime = 0;
|
|
155
|
+
state = "closed";
|
|
156
|
+
constructor(threshold = 5, timeout = 60000, // 1 minute
|
|
157
|
+
monitorWindow = 600000) {
|
|
158
|
+
this.threshold = threshold;
|
|
159
|
+
this.timeout = timeout;
|
|
160
|
+
this.monitorWindow = monitorWindow;
|
|
161
|
+
}
|
|
162
|
+
async execute(operation) {
|
|
163
|
+
if (this.state === "open") {
|
|
164
|
+
if (Date.now() - this.lastFailureTime > this.timeout) {
|
|
165
|
+
this.state = "half-open";
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
throw new Error("Circuit breaker is open - operation rejected");
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
try {
|
|
172
|
+
const result = await operation();
|
|
173
|
+
this.onSuccess();
|
|
174
|
+
return result;
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
this.onFailure();
|
|
178
|
+
throw error;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
onSuccess() {
|
|
182
|
+
this.failures = 0;
|
|
183
|
+
this.state = "closed";
|
|
184
|
+
}
|
|
185
|
+
onFailure() {
|
|
186
|
+
this.failures++;
|
|
187
|
+
this.lastFailureTime = Date.now();
|
|
188
|
+
if (this.failures >= this.threshold) {
|
|
189
|
+
this.state = "open";
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
getState() {
|
|
193
|
+
return this.state;
|
|
194
|
+
}
|
|
195
|
+
reset() {
|
|
196
|
+
this.failures = 0;
|
|
197
|
+
this.lastFailureTime = 0;
|
|
198
|
+
this.state = "closed";
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Rate limiter to prevent overwhelming APIs
|
|
203
|
+
*/
|
|
204
|
+
export class RateLimiter {
|
|
205
|
+
maxRequests;
|
|
206
|
+
windowMs;
|
|
207
|
+
requests = [];
|
|
208
|
+
constructor(maxRequests, windowMs) {
|
|
209
|
+
this.maxRequests = maxRequests;
|
|
210
|
+
this.windowMs = windowMs;
|
|
211
|
+
}
|
|
212
|
+
async acquire() {
|
|
213
|
+
const now = Date.now();
|
|
214
|
+
// Remove old requests outside the window
|
|
215
|
+
this.requests = this.requests.filter((time) => now - time < this.windowMs);
|
|
216
|
+
if (this.requests.length >= this.maxRequests) {
|
|
217
|
+
// Calculate delay until next available slot
|
|
218
|
+
const oldestRequest = Math.min(...this.requests);
|
|
219
|
+
const delay = this.windowMs - (now - oldestRequest);
|
|
220
|
+
if (delay > 0) {
|
|
221
|
+
await sleep(delay);
|
|
222
|
+
return this.acquire(); // Try again after delay
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
this.requests.push(now);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Utility for graceful shutdown handling
|
|
230
|
+
*/
|
|
231
|
+
export class GracefulShutdown {
|
|
232
|
+
operations = new Set();
|
|
233
|
+
shutdownPromise = null;
|
|
234
|
+
track(operation) {
|
|
235
|
+
this.operations.add(operation);
|
|
236
|
+
operation.finally(() => {
|
|
237
|
+
this.operations.delete(operation);
|
|
238
|
+
});
|
|
239
|
+
return operation;
|
|
240
|
+
}
|
|
241
|
+
async shutdown(timeoutMs = 30000) {
|
|
242
|
+
if (this.shutdownPromise) {
|
|
243
|
+
return this.shutdownPromise;
|
|
244
|
+
}
|
|
245
|
+
this.shutdownPromise = this.performShutdown(timeoutMs);
|
|
246
|
+
return this.shutdownPromise;
|
|
247
|
+
}
|
|
248
|
+
async performShutdown(timeoutMs) {
|
|
249
|
+
logger.debug(`🔄 Graceful shutdown: waiting for ${this.operations.size} operations...`);
|
|
250
|
+
try {
|
|
251
|
+
await Promise.race([
|
|
252
|
+
Promise.all(this.operations),
|
|
253
|
+
sleep(timeoutMs).then(() => {
|
|
254
|
+
throw new Error(`Shutdown timeout: ${this.operations.size} operations still running`);
|
|
255
|
+
}),
|
|
256
|
+
]);
|
|
257
|
+
logger.debug("✅ Graceful shutdown completed");
|
|
258
|
+
}
|
|
259
|
+
catch (error) {
|
|
260
|
+
logger.warn(`⚠️ Shutdown warning: ${error instanceof Error ? error.message : String(error)}`);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Global instances for convenience
|
|
266
|
+
*/
|
|
267
|
+
export const globalShutdown = new GracefulShutdown();
|
|
268
|
+
export const providerCircuitBreaker = new CircuitBreaker(3, 30000); // 3 failures, 30s timeout
|
|
269
|
+
export const apiRateLimiter = new RateLimiter(100, 60000); // 100 requests per minute
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.2.0",
|
|
4
4
|
"description": "Universal AI Development Platform with working MCP integration, multi-provider support, and professional CLI. Built-in tools operational, 58+ external MCP servers discoverable. Connect to filesystem, GitHub, database operations, and more. Build, test, and deploy AI applications with 9 major providers: OpenAI, Anthropic, Google AI, AWS Bedrock, Azure, Hugging Face, Ollama, and Mistral AI.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Juspay Technologies",
|
|
@@ -155,6 +155,7 @@
|
|
|
155
155
|
"mathjs": "^14.5.3",
|
|
156
156
|
"ollama-ai-provider": "^1.2.0",
|
|
157
157
|
"ora": "^7.0.1",
|
|
158
|
+
"p-limit": "^6.2.0",
|
|
158
159
|
"reconnecting-eventsource": "^1.6.4",
|
|
159
160
|
"undici": "^6.6.2",
|
|
160
161
|
"uuid": "^11.1.0",
|