@juspay/neurolink 7.1.0 → 7.3.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 (92) hide show
  1. package/CHANGELOG.md +15 -2
  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 +14 -0
  11. package/dist/cli/factories/commandFactory.js +346 -47
  12. package/dist/cli/index.js +25 -10
  13. package/dist/cli/utils/completeSetup.js +9 -8
  14. package/dist/cli/utils/envManager.js +7 -6
  15. package/dist/cli/utils/interactiveSetup.js +20 -19
  16. package/dist/core/analytics.js +25 -38
  17. package/dist/core/baseProvider.d.ts +8 -0
  18. package/dist/core/baseProvider.js +177 -68
  19. package/dist/core/constants.d.ts +11 -0
  20. package/dist/core/constants.js +17 -0
  21. package/dist/core/evaluation.js +25 -14
  22. package/dist/core/factory.js +19 -18
  23. package/dist/core/streamAnalytics.d.ts +65 -0
  24. package/dist/core/streamAnalytics.js +125 -0
  25. package/dist/lib/core/analytics.js +25 -38
  26. package/dist/lib/core/baseProvider.d.ts +8 -0
  27. package/dist/lib/core/baseProvider.js +177 -68
  28. package/dist/lib/core/constants.d.ts +11 -0
  29. package/dist/lib/core/constants.js +17 -0
  30. package/dist/lib/core/evaluation.js +25 -14
  31. package/dist/lib/core/factory.js +19 -18
  32. package/dist/lib/core/streamAnalytics.d.ts +65 -0
  33. package/dist/lib/core/streamAnalytics.js +125 -0
  34. package/dist/lib/models/modelRegistry.d.ts +132 -0
  35. package/dist/lib/models/modelRegistry.js +483 -0
  36. package/dist/lib/models/modelResolver.d.ts +115 -0
  37. package/dist/lib/models/modelResolver.js +467 -0
  38. package/dist/lib/neurolink.d.ts +4 -1
  39. package/dist/lib/neurolink.js +101 -67
  40. package/dist/lib/providers/anthropic.js +3 -0
  41. package/dist/lib/providers/googleAiStudio.js +13 -0
  42. package/dist/lib/providers/huggingFace.js +15 -3
  43. package/dist/lib/providers/mistral.js +19 -7
  44. package/dist/lib/providers/ollama.js +31 -7
  45. package/dist/lib/providers/openAI.js +12 -0
  46. package/dist/lib/sdk/toolRegistration.js +2 -2
  47. package/dist/lib/types/cli.d.ts +56 -1
  48. package/dist/lib/types/contextTypes.d.ts +110 -0
  49. package/dist/lib/types/contextTypes.js +176 -0
  50. package/dist/lib/types/index.d.ts +4 -1
  51. package/dist/lib/types/mcpTypes.d.ts +118 -7
  52. package/dist/lib/types/providers.d.ts +81 -0
  53. package/dist/lib/types/streamTypes.d.ts +44 -7
  54. package/dist/lib/types/tools.d.ts +9 -0
  55. package/dist/lib/types/universalProviderOptions.d.ts +3 -1
  56. package/dist/lib/types/universalProviderOptions.js +2 -1
  57. package/dist/lib/utils/logger.d.ts +7 -0
  58. package/dist/lib/utils/logger.js +11 -0
  59. package/dist/lib/utils/performance.d.ts +105 -0
  60. package/dist/lib/utils/performance.js +210 -0
  61. package/dist/lib/utils/retryHandler.d.ts +89 -0
  62. package/dist/lib/utils/retryHandler.js +269 -0
  63. package/dist/models/modelRegistry.d.ts +132 -0
  64. package/dist/models/modelRegistry.js +483 -0
  65. package/dist/models/modelResolver.d.ts +115 -0
  66. package/dist/models/modelResolver.js +468 -0
  67. package/dist/neurolink.d.ts +4 -1
  68. package/dist/neurolink.js +101 -67
  69. package/dist/providers/anthropic.js +3 -0
  70. package/dist/providers/googleAiStudio.js +13 -0
  71. package/dist/providers/huggingFace.js +15 -3
  72. package/dist/providers/mistral.js +19 -7
  73. package/dist/providers/ollama.js +31 -7
  74. package/dist/providers/openAI.js +12 -0
  75. package/dist/sdk/toolRegistration.js +2 -2
  76. package/dist/types/cli.d.ts +56 -1
  77. package/dist/types/contextTypes.d.ts +110 -0
  78. package/dist/types/contextTypes.js +177 -0
  79. package/dist/types/index.d.ts +4 -1
  80. package/dist/types/mcpTypes.d.ts +118 -7
  81. package/dist/types/providers.d.ts +81 -0
  82. package/dist/types/streamTypes.d.ts +44 -7
  83. package/dist/types/tools.d.ts +9 -0
  84. package/dist/types/universalProviderOptions.d.ts +3 -1
  85. package/dist/types/universalProviderOptions.js +3 -1
  86. package/dist/utils/logger.d.ts +7 -0
  87. package/dist/utils/logger.js +11 -0
  88. package/dist/utils/performance.d.ts +105 -0
  89. package/dist/utils/performance.js +210 -0
  90. package/dist/utils/retryHandler.d.ts +89 -0
  91. package/dist/utils/retryHandler.js +269 -0
  92. package/package.json +2 -1
@@ -121,6 +121,14 @@ class NeuroLinkLogger {
121
121
  always(...args) {
122
122
  console.log(...args);
123
123
  }
124
+ /**
125
+ * Displays tabular data unconditionally using `console.table`.
126
+ *
127
+ * @param data - The data to display in table format
128
+ */
129
+ table(data) {
130
+ console.table(data);
131
+ }
124
132
  }
125
133
  // Export singleton instance
126
134
  const neuroLinkLogger = new NeuroLinkLogger();
@@ -166,6 +174,9 @@ export const logger = {
166
174
  always: (...args) => {
167
175
  neuroLinkLogger.always(...args);
168
176
  },
177
+ table: (data) => {
178
+ neuroLinkLogger.table(data);
179
+ },
169
180
  // Expose structured logging methods
170
181
  setLogLevel: (level) => neuroLinkLogger.setLogLevel(level),
171
182
  getLogs: (level) => neuroLinkLogger.getLogs(level),
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Performance measurement and memory management utilities
3
+ * Part of Sub-phase 3.3.1-3.3.2 optimization efforts
4
+ */
5
+ export interface PerformanceMetrics {
6
+ startTime: number;
7
+ endTime?: number;
8
+ duration?: number;
9
+ memoryStart: NodeJS.MemoryUsage;
10
+ memoryEnd?: NodeJS.MemoryUsage;
11
+ memoryDelta?: {
12
+ rss: number;
13
+ heapTotal: number;
14
+ heapUsed: number;
15
+ external: number;
16
+ };
17
+ }
18
+ /**
19
+ * Performance measurement utility for tracking operations
20
+ */
21
+ export declare class PerformanceTracker {
22
+ private metrics;
23
+ /**
24
+ * Start tracking performance for an operation
25
+ */
26
+ start(operationName: string): void;
27
+ /**
28
+ * End tracking and calculate metrics
29
+ */
30
+ end(operationName: string): PerformanceMetrics | null;
31
+ /**
32
+ * Get metrics for an operation
33
+ */
34
+ getMetrics(operationName: string): PerformanceMetrics | null;
35
+ /**
36
+ * Clear all metrics
37
+ */
38
+ clear(): void;
39
+ /**
40
+ * Format metrics for display
41
+ */
42
+ formatMetrics(operationName: string): string;
43
+ }
44
+ /**
45
+ * Global performance tracker instance
46
+ */
47
+ export declare const globalTracker: PerformanceTracker;
48
+ /**
49
+ * Memory management utilities
50
+ */
51
+ export declare class MemoryManager {
52
+ /**
53
+ * Force garbage collection if available
54
+ */
55
+ static forceGC(): boolean;
56
+ /**
57
+ * Get current memory usage in MB
58
+ */
59
+ static getMemoryUsageMB(): {
60
+ rss: number;
61
+ heapTotal: number;
62
+ heapUsed: number;
63
+ external: number;
64
+ };
65
+ /**
66
+ * Monitor memory usage and warn if it exceeds threshold
67
+ */
68
+ static monitorMemory(threshold?: number): boolean;
69
+ /**
70
+ * Clean up and optimize memory usage.
71
+ * Attempts to force garbage collection if available.
72
+ *
73
+ * @returns {object|null} Memory usage statistics if cleanup was performed, or null if not possible.
74
+ * - If manual garbage collection is not available (i.e., Node.js not run with --expose-gc),
75
+ * no cleanup is performed and null is returned.
76
+ * - Clearing the require cache is not attempted due to potential side effects.
77
+ */
78
+ static cleanup(): {
79
+ beforeMB: number;
80
+ afterMB: number;
81
+ freedMB: number;
82
+ } | null;
83
+ }
84
+ /**
85
+ * Decorator for tracking performance of async functions
86
+ */
87
+ export declare function trackPerformance(operationName: string): <T extends (...args: unknown[]) => Promise<unknown>>(target: unknown, propertyName: string, descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T>;
88
+ /**
89
+ * Performance monitoring for CLI operations
90
+ */
91
+ export declare class CLIPerformanceMonitor {
92
+ private static instance;
93
+ private enabled;
94
+ static getInstance(): CLIPerformanceMonitor;
95
+ enable(): void;
96
+ disable(): void;
97
+ /**
98
+ * Monitor a CLI operation
99
+ */
100
+ monitorOperation<T>(operationName: string, operation: () => Promise<T>): Promise<T>;
101
+ }
102
+ /**
103
+ * Export singleton monitor for easy access
104
+ */
105
+ export declare const cliMonitor: CLIPerformanceMonitor;
@@ -0,0 +1,210 @@
1
+ /**
2
+ * Performance measurement and memory management utilities
3
+ * Part of Sub-phase 3.3.1-3.3.2 optimization efforts
4
+ */
5
+ import { logger } from "./logger.js";
6
+ /**
7
+ * Performance measurement utility for tracking operations
8
+ */
9
+ export class PerformanceTracker {
10
+ metrics = new Map();
11
+ /**
12
+ * Start tracking performance for an operation
13
+ */
14
+ start(operationName) {
15
+ this.metrics.set(operationName, {
16
+ startTime: Date.now(),
17
+ memoryStart: process.memoryUsage(),
18
+ });
19
+ }
20
+ /**
21
+ * End tracking and calculate metrics
22
+ */
23
+ end(operationName) {
24
+ const metric = this.metrics.get(operationName);
25
+ if (!metric) {
26
+ return null;
27
+ }
28
+ const endTime = Date.now();
29
+ const memoryEnd = process.memoryUsage();
30
+ const completedMetric = {
31
+ ...metric,
32
+ endTime,
33
+ duration: endTime - metric.startTime,
34
+ memoryEnd,
35
+ memoryDelta: {
36
+ rss: memoryEnd.rss - metric.memoryStart.rss,
37
+ heapTotal: memoryEnd.heapTotal - metric.memoryStart.heapTotal,
38
+ heapUsed: memoryEnd.heapUsed - metric.memoryStart.heapUsed,
39
+ external: memoryEnd.external - metric.memoryStart.external,
40
+ },
41
+ };
42
+ this.metrics.set(operationName, completedMetric);
43
+ return completedMetric;
44
+ }
45
+ /**
46
+ * Get metrics for an operation
47
+ */
48
+ getMetrics(operationName) {
49
+ return this.metrics.get(operationName) || null;
50
+ }
51
+ /**
52
+ * Clear all metrics
53
+ */
54
+ clear() {
55
+ this.metrics.clear();
56
+ }
57
+ /**
58
+ * Format metrics for display
59
+ */
60
+ formatMetrics(operationName) {
61
+ const metric = this.metrics.get(operationName);
62
+ if (!metric || !metric.duration) {
63
+ return `${operationName}: No metrics available`;
64
+ }
65
+ const memoryMB = (bytes) => (bytes / 1024 / 1024).toFixed(1);
66
+ return [
67
+ `${operationName}:`,
68
+ ` Duration: ${metric.duration}ms`,
69
+ ` Memory Delta: +${memoryMB(metric.memoryDelta.heapUsed)}MB heap`,
70
+ ` RSS Delta: +${memoryMB(metric.memoryDelta.rss)}MB`,
71
+ ].join("\n");
72
+ }
73
+ }
74
+ /**
75
+ * Global performance tracker instance
76
+ */
77
+ export const globalTracker = new PerformanceTracker();
78
+ /**
79
+ * Memory management utilities
80
+ */
81
+ export class MemoryManager {
82
+ /**
83
+ * Force garbage collection if available
84
+ */
85
+ static forceGC() {
86
+ if (typeof global !== "undefined" && global.gc) {
87
+ global.gc();
88
+ return true;
89
+ }
90
+ return false;
91
+ }
92
+ /**
93
+ * Get current memory usage in MB
94
+ */
95
+ static getMemoryUsageMB() {
96
+ const usage = process.memoryUsage();
97
+ return {
98
+ rss: Math.round(usage.rss / 1024 / 1024),
99
+ heapTotal: Math.round(usage.heapTotal / 1024 / 1024),
100
+ heapUsed: Math.round(usage.heapUsed / 1024 / 1024),
101
+ external: Math.round(usage.external / 1024 / 1024),
102
+ };
103
+ }
104
+ /**
105
+ * Monitor memory usage and warn if it exceeds threshold
106
+ */
107
+ static monitorMemory(threshold = 100) {
108
+ const usage = this.getMemoryUsageMB();
109
+ if (usage.heapUsed > threshold) {
110
+ logger.warn(`⚠️ High memory usage: ${usage.heapUsed}MB heap (threshold: ${threshold}MB)`);
111
+ return true;
112
+ }
113
+ return false;
114
+ }
115
+ /**
116
+ * Clean up and optimize memory usage.
117
+ * Attempts to force garbage collection if available.
118
+ *
119
+ * @returns {object|null} Memory usage statistics if cleanup was performed, or null if not possible.
120
+ * - If manual garbage collection is not available (i.e., Node.js not run with --expose-gc),
121
+ * no cleanup is performed and null is returned.
122
+ * - Clearing the require cache is not attempted due to potential side effects.
123
+ */
124
+ static cleanup() {
125
+ const before = this.getMemoryUsageMB();
126
+ const gcForced = this.forceGC();
127
+ if (!gcForced) {
128
+ // Manual garbage collection not available.
129
+ // No cleanup performed. Clearing require cache is dangerous and not attempted.
130
+ // Memory cleanup relies on Node.js natural garbage collection.
131
+ return null;
132
+ }
133
+ const after = this.getMemoryUsageMB();
134
+ return {
135
+ beforeMB: before.heapUsed,
136
+ afterMB: after.heapUsed,
137
+ freedMB: before.heapUsed - after.heapUsed,
138
+ };
139
+ }
140
+ }
141
+ /**
142
+ * Decorator for tracking performance of async functions
143
+ */
144
+ export function trackPerformance(operationName) {
145
+ return function (target, propertyName, descriptor) {
146
+ const method = descriptor.value;
147
+ descriptor.value = async function (...args) {
148
+ globalTracker.start(operationName);
149
+ try {
150
+ const result = await method.apply(this, args);
151
+ globalTracker.end(operationName);
152
+ return result;
153
+ }
154
+ catch (error) {
155
+ globalTracker.end(operationName);
156
+ throw error;
157
+ }
158
+ };
159
+ return descriptor;
160
+ };
161
+ }
162
+ /**
163
+ * Performance monitoring for CLI operations
164
+ */
165
+ export class CLIPerformanceMonitor {
166
+ static instance;
167
+ enabled = false;
168
+ static getInstance() {
169
+ if (!CLIPerformanceMonitor.instance) {
170
+ CLIPerformanceMonitor.instance = new CLIPerformanceMonitor();
171
+ }
172
+ return CLIPerformanceMonitor.instance;
173
+ }
174
+ enable() {
175
+ this.enabled = true;
176
+ }
177
+ disable() {
178
+ this.enabled = false;
179
+ }
180
+ /**
181
+ * Monitor a CLI operation
182
+ */
183
+ async monitorOperation(operationName, operation) {
184
+ if (!this.enabled) {
185
+ return operation();
186
+ }
187
+ globalTracker.start(operationName);
188
+ const startMemory = MemoryManager.getMemoryUsageMB();
189
+ try {
190
+ const result = await operation();
191
+ const metrics = globalTracker.end(operationName);
192
+ const endMemory = MemoryManager.getMemoryUsageMB();
193
+ if (metrics) {
194
+ logger.debug(`\n🔍 Performance: ${operationName}`);
195
+ logger.debug(` Duration: ${metrics.duration}ms`);
196
+ logger.debug(` Memory: ${startMemory.heapUsed}MB → ${endMemory.heapUsed}MB`);
197
+ logger.debug(` Delta: +${endMemory.heapUsed - startMemory.heapUsed}MB`);
198
+ }
199
+ return result;
200
+ }
201
+ catch (error) {
202
+ globalTracker.end(operationName);
203
+ throw error;
204
+ }
205
+ }
206
+ }
207
+ /**
208
+ * Export singleton monitor for easy access
209
+ */
210
+ export const cliMonitor = CLIPerformanceMonitor.getInstance();
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Retry and resilience utilities for NeuroLink
3
+ * Part of Sub-phase 3.3.3 - Edge Case Handling
4
+ */
5
+ /**
6
+ * Calculate exponential backoff delay with jitter
7
+ * @param attempt - Current attempt number (1-based)
8
+ * @param initialDelay - Initial delay in milliseconds
9
+ * @param multiplier - Backoff multiplier for exponential growth
10
+ * @param maxDelay - Maximum delay cap in milliseconds
11
+ * @param addJitter - Whether to add random jitter to prevent thundering herd
12
+ * @returns Calculated delay in milliseconds
13
+ */
14
+ export declare function calculateBackoffDelay(attempt: number, initialDelay?: number, multiplier?: number, maxDelay?: number, addJitter?: boolean): number;
15
+ export interface RetryOptions {
16
+ maxAttempts?: number;
17
+ initialDelay?: number;
18
+ maxDelay?: number;
19
+ backoffMultiplier?: number;
20
+ retryCondition?: (error: unknown) => boolean;
21
+ onRetry?: (attempt: number, error: unknown) => void;
22
+ }
23
+ /**
24
+ * Error types that are typically retryable
25
+ */
26
+ export declare class NetworkError extends Error {
27
+ readonly cause?: Error | undefined;
28
+ constructor(message: string, cause?: Error | undefined);
29
+ }
30
+ export declare class TemporaryError extends Error {
31
+ readonly cause?: Error | undefined;
32
+ constructor(message: string, cause?: Error | undefined);
33
+ }
34
+ /**
35
+ * Default retry configuration
36
+ */
37
+ export declare const DEFAULT_RETRY_CONFIG: Required<RetryOptions>;
38
+ /**
39
+ * Execute an operation with retry logic
40
+ */
41
+ export declare function withRetry<T>(operation: () => Promise<T>, options?: RetryOptions): Promise<T>;
42
+ /**
43
+ * Enhanced timeout with retry for network operations
44
+ */
45
+ export declare function withTimeoutAndRetry<T>(operation: () => Promise<T>, timeoutMs: number, retryOptions?: RetryOptions): Promise<T>;
46
+ /**
47
+ * Circuit breaker pattern for preventing cascading failures
48
+ */
49
+ export declare class CircuitBreaker {
50
+ private threshold;
51
+ private timeout;
52
+ private monitorWindow;
53
+ private failures;
54
+ private lastFailureTime;
55
+ private state;
56
+ constructor(threshold?: number, timeout?: number, // 1 minute
57
+ monitorWindow?: number);
58
+ execute<T>(operation: () => Promise<T>): Promise<T>;
59
+ private onSuccess;
60
+ private onFailure;
61
+ getState(): string;
62
+ reset(): void;
63
+ }
64
+ /**
65
+ * Rate limiter to prevent overwhelming APIs
66
+ */
67
+ export declare class RateLimiter {
68
+ private maxRequests;
69
+ private windowMs;
70
+ private requests;
71
+ constructor(maxRequests: number, windowMs: number);
72
+ acquire(): Promise<void>;
73
+ }
74
+ /**
75
+ * Utility for graceful shutdown handling
76
+ */
77
+ export declare class GracefulShutdown {
78
+ private operations;
79
+ private shutdownPromise;
80
+ track<T>(operation: Promise<T>): Promise<T>;
81
+ shutdown(timeoutMs?: number): Promise<void>;
82
+ private performShutdown;
83
+ }
84
+ /**
85
+ * Global instances for convenience
86
+ */
87
+ export declare const globalShutdown: GracefulShutdown;
88
+ export declare const providerCircuitBreaker: CircuitBreaker;
89
+ export declare const apiRateLimiter: RateLimiter;
@@ -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