@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.
Files changed (101) hide show
  1. package/CHANGELOG.md +15 -4
  2. package/README.md +16 -11
  3. package/dist/cli/commands/config.d.ts +2 -2
  4. package/dist/cli/commands/config.js +22 -21
  5. package/dist/cli/commands/mcp.d.ts +79 -0
  6. package/dist/cli/commands/mcp.js +916 -0
  7. package/dist/cli/commands/models.d.ts +63 -0
  8. package/dist/cli/commands/models.js +653 -0
  9. package/dist/cli/commands/ollama.js +56 -55
  10. package/dist/cli/factories/commandFactory.d.ts +67 -2
  11. package/dist/cli/factories/commandFactory.js +840 -92
  12. package/dist/cli/index.d.ts +6 -0
  13. package/dist/cli/index.js +42 -999
  14. package/dist/cli/utils/completeSetup.js +9 -8
  15. package/dist/cli/utils/envManager.js +7 -6
  16. package/dist/cli/utils/interactiveSetup.js +20 -19
  17. package/dist/core/analytics.js +25 -38
  18. package/dist/core/baseProvider.d.ts +8 -0
  19. package/dist/core/baseProvider.js +177 -68
  20. package/dist/core/constants.d.ts +11 -0
  21. package/dist/core/constants.js +17 -0
  22. package/dist/core/evaluation.js +25 -14
  23. package/dist/core/factory.js +21 -18
  24. package/dist/core/streamAnalytics.d.ts +65 -0
  25. package/dist/core/streamAnalytics.js +125 -0
  26. package/dist/factories/providerRegistry.js +3 -1
  27. package/dist/lib/core/analytics.js +25 -38
  28. package/dist/lib/core/baseProvider.d.ts +8 -0
  29. package/dist/lib/core/baseProvider.js +177 -68
  30. package/dist/lib/core/constants.d.ts +11 -0
  31. package/dist/lib/core/constants.js +17 -0
  32. package/dist/lib/core/evaluation.js +25 -14
  33. package/dist/lib/core/factory.js +22 -18
  34. package/dist/lib/core/streamAnalytics.d.ts +65 -0
  35. package/dist/lib/core/streamAnalytics.js +125 -0
  36. package/dist/lib/factories/providerRegistry.js +3 -1
  37. package/dist/lib/mcp/toolRegistry.d.ts +5 -0
  38. package/dist/lib/mcp/toolRegistry.js +60 -0
  39. package/dist/lib/models/modelRegistry.d.ts +132 -0
  40. package/dist/lib/models/modelRegistry.js +483 -0
  41. package/dist/lib/models/modelResolver.d.ts +115 -0
  42. package/dist/lib/models/modelResolver.js +467 -0
  43. package/dist/lib/neurolink.d.ts +4 -1
  44. package/dist/lib/neurolink.js +108 -69
  45. package/dist/lib/providers/anthropic.js +3 -0
  46. package/dist/lib/providers/googleAiStudio.js +13 -0
  47. package/dist/lib/providers/huggingFace.js +15 -3
  48. package/dist/lib/providers/mistral.js +19 -7
  49. package/dist/lib/providers/ollama.js +31 -7
  50. package/dist/lib/providers/openAI.js +12 -0
  51. package/dist/lib/sdk/toolRegistration.js +17 -0
  52. package/dist/lib/types/cli.d.ts +56 -1
  53. package/dist/lib/types/contextTypes.d.ts +110 -0
  54. package/dist/lib/types/contextTypes.js +176 -0
  55. package/dist/lib/types/index.d.ts +4 -1
  56. package/dist/lib/types/mcpTypes.d.ts +118 -7
  57. package/dist/lib/types/providers.d.ts +81 -0
  58. package/dist/lib/types/streamTypes.d.ts +44 -7
  59. package/dist/lib/types/tools.d.ts +9 -0
  60. package/dist/lib/types/universalProviderOptions.d.ts +3 -1
  61. package/dist/lib/types/universalProviderOptions.js +2 -1
  62. package/dist/lib/utils/logger.d.ts +7 -0
  63. package/dist/lib/utils/logger.js +16 -6
  64. package/dist/lib/utils/performance.d.ts +105 -0
  65. package/dist/lib/utils/performance.js +210 -0
  66. package/dist/lib/utils/providerUtils.js +9 -2
  67. package/dist/lib/utils/retryHandler.d.ts +89 -0
  68. package/dist/lib/utils/retryHandler.js +269 -0
  69. package/dist/mcp/toolRegistry.d.ts +5 -0
  70. package/dist/mcp/toolRegistry.js +60 -0
  71. package/dist/models/modelRegistry.d.ts +132 -0
  72. package/dist/models/modelRegistry.js +483 -0
  73. package/dist/models/modelResolver.d.ts +115 -0
  74. package/dist/models/modelResolver.js +468 -0
  75. package/dist/neurolink.d.ts +4 -1
  76. package/dist/neurolink.js +108 -69
  77. package/dist/providers/anthropic.js +3 -0
  78. package/dist/providers/googleAiStudio.js +13 -0
  79. package/dist/providers/huggingFace.js +15 -3
  80. package/dist/providers/mistral.js +19 -7
  81. package/dist/providers/ollama.js +31 -7
  82. package/dist/providers/openAI.js +12 -0
  83. package/dist/sdk/toolRegistration.js +17 -0
  84. package/dist/types/cli.d.ts +56 -1
  85. package/dist/types/contextTypes.d.ts +110 -0
  86. package/dist/types/contextTypes.js +177 -0
  87. package/dist/types/index.d.ts +4 -1
  88. package/dist/types/mcpTypes.d.ts +118 -7
  89. package/dist/types/providers.d.ts +81 -0
  90. package/dist/types/streamTypes.d.ts +44 -7
  91. package/dist/types/tools.d.ts +9 -0
  92. package/dist/types/universalProviderOptions.d.ts +3 -1
  93. package/dist/types/universalProviderOptions.js +3 -1
  94. package/dist/utils/logger.d.ts +7 -0
  95. package/dist/utils/logger.js +16 -6
  96. package/dist/utils/performance.d.ts +105 -0
  97. package/dist/utils/performance.js +210 -0
  98. package/dist/utils/providerUtils.js +9 -2
  99. package/dist/utils/retryHandler.d.ts +89 -0
  100. package/dist/utils/retryHandler.js +269 -0
  101. 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
@@ -39,6 +39,11 @@ export declare class MCPToolRegistry extends MCPRegistry {
39
39
  private tools;
40
40
  private toolImpls;
41
41
  private toolExecutionStats;
42
+ constructor();
43
+ /**
44
+ * Register all direct tools from directAgentTools
45
+ */
46
+ private registerDirectTools;
42
47
  /**
43
48
  * Register a server with its tools (updated signature)
44
49
  */
@@ -5,10 +5,70 @@
5
5
  import { MCPRegistry } from "./registry.js";
6
6
  import { registryLogger } from "../utils/logger.js";
7
7
  import { randomUUID } from "crypto";
8
+ import { directAgentTools } from "../agent/directTools.js";
8
9
  export class MCPToolRegistry extends MCPRegistry {
9
10
  tools = new Map();
10
11
  toolImpls = new Map(); // Store actual tool implementations
11
12
  toolExecutionStats = new Map();
13
+ constructor() {
14
+ super();
15
+ // Auto-register direct tools on initialization
16
+ this.registerDirectTools();
17
+ }
18
+ /**
19
+ * Register all direct tools from directAgentTools
20
+ */
21
+ registerDirectTools() {
22
+ registryLogger.info("Auto-registering direct tools...");
23
+ for (const [toolName, toolDef] of Object.entries(directAgentTools)) {
24
+ const toolId = `direct.${toolName}`;
25
+ const toolInfo = {
26
+ name: toolName,
27
+ description: toolDef.description || `Direct tool: ${toolName}`,
28
+ inputSchema: {},
29
+ serverId: "direct",
30
+ category: "built-in",
31
+ };
32
+ this.tools.set(toolId, toolInfo);
33
+ this.toolImpls.set(toolId, {
34
+ execute: async (params, context) => {
35
+ try {
36
+ // Direct tools from AI SDK expect their specific parameter structure
37
+ // Each tool validates its own parameters, so we safely pass them through
38
+ const result = await toolDef.execute(params, {
39
+ toolCallId: context?.sessionId || "unknown",
40
+ messages: [],
41
+ });
42
+ // Return the result wrapped in our standard format
43
+ return {
44
+ success: true,
45
+ data: result,
46
+ metadata: {
47
+ toolName,
48
+ serverId: "direct",
49
+ executionTime: 0,
50
+ },
51
+ };
52
+ }
53
+ catch (error) {
54
+ return {
55
+ success: false,
56
+ error: error instanceof Error ? error.message : String(error),
57
+ metadata: {
58
+ toolName,
59
+ serverId: "direct",
60
+ executionTime: 0,
61
+ },
62
+ };
63
+ }
64
+ },
65
+ description: toolDef.description,
66
+ inputSchema: {},
67
+ });
68
+ registryLogger.debug(`Registered direct tool: ${toolName} as ${toolId}`);
69
+ }
70
+ registryLogger.info(`Auto-registered ${Object.keys(directAgentTools).length} direct tools`);
71
+ }
12
72
  /**
13
73
  * Register a server with its tools (updated signature)
14
74
  */
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Model Registry for NeuroLink CLI Commands
3
+ * Provides centralized model data for models command system
4
+ * Part of Phase 4.1 - Models Command System
5
+ */
6
+ import { AIProviderName } from "../core/types.js";
7
+ import type { JsonValue } from "../types/common.js";
8
+ /**
9
+ * Model capabilities interface
10
+ */
11
+ export interface ModelCapabilities {
12
+ vision: boolean;
13
+ functionCalling: boolean;
14
+ codeGeneration: boolean;
15
+ reasoning: boolean;
16
+ multimodal: boolean;
17
+ streaming: boolean;
18
+ jsonMode: boolean;
19
+ }
20
+ /**
21
+ * Model pricing information
22
+ */
23
+ export interface ModelPricing {
24
+ inputCostPer1K: number;
25
+ outputCostPer1K: number;
26
+ currency: string;
27
+ }
28
+ /**
29
+ * Model performance characteristics
30
+ */
31
+ export interface ModelPerformance {
32
+ speed: "fast" | "medium" | "slow";
33
+ quality: "high" | "medium" | "low";
34
+ accuracy: "high" | "medium" | "low";
35
+ }
36
+ /**
37
+ * Model limitations and constraints
38
+ */
39
+ export interface ModelLimits {
40
+ maxContextTokens: number;
41
+ maxOutputTokens: number;
42
+ maxRequestsPerMinute?: number;
43
+ maxRequestsPerDay?: number;
44
+ }
45
+ /**
46
+ * Use case suitability scores (1-10 scale)
47
+ */
48
+ export interface UseCaseSuitability {
49
+ coding: number;
50
+ creative: number;
51
+ analysis: number;
52
+ conversation: number;
53
+ reasoning: number;
54
+ translation: number;
55
+ summarization: number;
56
+ }
57
+ /**
58
+ * Complete model information
59
+ */
60
+ export interface ModelInfo {
61
+ id: string;
62
+ name: string;
63
+ provider: AIProviderName;
64
+ description: string;
65
+ capabilities: ModelCapabilities;
66
+ pricing: ModelPricing;
67
+ performance: ModelPerformance;
68
+ limits: ModelLimits;
69
+ useCases: UseCaseSuitability;
70
+ aliases: string[];
71
+ deprecated: boolean;
72
+ isLocal: boolean;
73
+ releaseDate?: string;
74
+ category: "general" | "coding" | "creative" | "vision" | "reasoning";
75
+ }
76
+ /**
77
+ * Model search filters
78
+ */
79
+ export interface ModelSearchFilters {
80
+ provider?: AIProviderName | AIProviderName[];
81
+ capability?: keyof ModelCapabilities | (keyof ModelCapabilities)[];
82
+ useCase?: keyof UseCaseSuitability;
83
+ maxCost?: number;
84
+ minContextSize?: number;
85
+ maxContextSize?: number;
86
+ performance?: ModelPerformance["speed"] | ModelPerformance["quality"];
87
+ category?: ModelInfo["category"] | ModelInfo["category"][];
88
+ }
89
+ /**
90
+ * Model search result with ranking
91
+ */
92
+ export interface ModelSearchResult {
93
+ model: ModelInfo;
94
+ score: number;
95
+ matchReasons: string[];
96
+ }
97
+ /**
98
+ * Comprehensive model registry
99
+ */
100
+ export declare const MODEL_REGISTRY: Record<string, ModelInfo>;
101
+ /**
102
+ * Model aliases registry for quick resolution
103
+ */
104
+ export declare const MODEL_ALIASES: Record<string, string>;
105
+ /**
106
+ * Use case to model mappings
107
+ */
108
+ export declare const USE_CASE_RECOMMENDATIONS: Record<string, string[]>;
109
+ /**
110
+ * Get all models
111
+ */
112
+ export declare function getAllModels(): ModelInfo[];
113
+ /**
114
+ * Get model by ID
115
+ */
116
+ export declare function getModelById(id: string): ModelInfo | undefined;
117
+ /**
118
+ * Get models by provider
119
+ */
120
+ export declare function getModelsByProvider(provider: AIProviderName): ModelInfo[];
121
+ /**
122
+ * Get available providers
123
+ */
124
+ export declare function getAvailableProviders(): AIProviderName[];
125
+ /**
126
+ * Calculate estimated cost for a request
127
+ */
128
+ export declare function calculateCost(model: ModelInfo, inputTokens: number, outputTokens: number): number;
129
+ /**
130
+ * Format model for display
131
+ */
132
+ export declare function formatModelForDisplay(model: ModelInfo): JsonValue;