@juspay/neurolink 2.0.0 → 3.0.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 (50) hide show
  1. package/CHANGELOG.md +34 -7
  2. package/README.md +38 -34
  3. package/dist/cli/commands/config.d.ts +6 -6
  4. package/dist/cli/index.js +46 -35
  5. package/dist/core/types.d.ts +2 -0
  6. package/dist/lib/core/types.d.ts +2 -0
  7. package/dist/lib/mcp/plugins/filesystem-mcp.d.ts +1 -1
  8. package/dist/lib/neurolink.d.ts +2 -0
  9. package/dist/lib/neurolink.js +23 -2
  10. package/dist/lib/providers/agent-enhanced-provider.d.ts +1 -0
  11. package/dist/lib/providers/agent-enhanced-provider.js +115 -51
  12. package/dist/lib/providers/amazonBedrock.js +74 -24
  13. package/dist/lib/providers/anthropic.js +80 -16
  14. package/dist/lib/providers/azureOpenAI.js +77 -15
  15. package/dist/lib/providers/googleAIStudio.js +77 -26
  16. package/dist/lib/providers/googleVertexAI.js +77 -24
  17. package/dist/lib/providers/huggingFace.js +74 -26
  18. package/dist/lib/providers/mistralAI.js +74 -26
  19. package/dist/lib/providers/ollama.d.ts +1 -1
  20. package/dist/lib/providers/ollama.js +32 -10
  21. package/dist/lib/providers/openAI.js +71 -23
  22. package/dist/lib/providers/timeout-wrapper.d.ts +40 -0
  23. package/dist/lib/providers/timeout-wrapper.js +100 -0
  24. package/dist/lib/proxy/proxy-fetch.d.ts +18 -0
  25. package/dist/lib/proxy/proxy-fetch.js +64 -0
  26. package/dist/lib/utils/timeout.d.ts +69 -0
  27. package/dist/lib/utils/timeout.js +138 -0
  28. package/dist/mcp/plugins/filesystem-mcp.d.ts +1 -1
  29. package/dist/mcp/plugins/filesystem-mcp.js +1 -1
  30. package/dist/neurolink.d.ts +2 -0
  31. package/dist/neurolink.js +23 -2
  32. package/dist/providers/agent-enhanced-provider.d.ts +1 -0
  33. package/dist/providers/agent-enhanced-provider.js +115 -51
  34. package/dist/providers/amazonBedrock.js +74 -24
  35. package/dist/providers/anthropic.js +80 -16
  36. package/dist/providers/azureOpenAI.js +77 -15
  37. package/dist/providers/googleAIStudio.js +77 -26
  38. package/dist/providers/googleVertexAI.js +77 -24
  39. package/dist/providers/huggingFace.js +74 -26
  40. package/dist/providers/mistralAI.js +74 -26
  41. package/dist/providers/ollama.d.ts +1 -1
  42. package/dist/providers/ollama.js +32 -10
  43. package/dist/providers/openAI.js +71 -23
  44. package/dist/providers/timeout-wrapper.d.ts +40 -0
  45. package/dist/providers/timeout-wrapper.js +100 -0
  46. package/dist/proxy/proxy-fetch.d.ts +18 -0
  47. package/dist/proxy/proxy-fetch.js +64 -0
  48. package/dist/utils/timeout.d.ts +69 -0
  49. package/dist/utils/timeout.js +138 -0
  50. package/package.json +2 -1
@@ -1,6 +1,7 @@
1
1
  import { openai } from "@ai-sdk/openai";
2
2
  import { streamText, generateText, Output, } from "ai";
3
3
  import { logger } from "../utils/logger.js";
4
+ import { createTimeoutController, getDefaultTimeout, TimeoutError, } from "../utils/timeout.js";
4
5
  // Default system context
5
6
  const DEFAULT_SYSTEM_CONTEXT = {
6
7
  systemPrompt: "You are a helpful AI assistant.",
@@ -59,7 +60,7 @@ export class OpenAI {
59
60
  const options = typeof optionsOrPrompt === "string"
60
61
  ? { prompt: optionsOrPrompt }
61
62
  : optionsOrPrompt;
62
- const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt = DEFAULT_SYSTEM_CONTEXT.systemPrompt, schema, } = options;
63
+ const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt = DEFAULT_SYSTEM_CONTEXT.systemPrompt, schema, timeout = getDefaultTimeout(provider, "stream"), } = options;
63
64
  // Use schema from options or fallback parameter
64
65
  const finalSchema = schema || analysisSchema;
65
66
  logger.debug(`[${functionTag}] Stream text started`, {
@@ -68,13 +69,20 @@ export class OpenAI {
68
69
  promptLength: prompt.length,
69
70
  temperature,
70
71
  maxTokens,
72
+ timeout,
71
73
  });
74
+ // Create timeout controller if timeout is specified
75
+ const timeoutController = createTimeoutController(timeout, provider, "stream");
72
76
  const streamOptions = {
73
77
  model: this.model,
74
78
  prompt: prompt,
75
79
  system: systemPrompt,
76
80
  temperature,
77
81
  maxTokens,
82
+ // Add abort signal if available
83
+ ...(timeoutController && {
84
+ abortSignal: timeoutController.controller.signal,
85
+ }),
78
86
  onError: (event) => {
79
87
  const error = event.error;
80
88
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -116,15 +124,28 @@ export class OpenAI {
116
124
  });
117
125
  }
118
126
  const result = streamText(streamOptions);
127
+ // For streaming, we can't clean up immediately, but the timeout will auto-clean
128
+ // The user should handle the stream and any timeout errors
119
129
  return result;
120
130
  }
121
131
  catch (err) {
122
- logger.debug(`[${functionTag}] Exception`, {
123
- provider,
124
- modelName: this.modelName,
125
- message: "Error in streaming text",
126
- err: String(err),
127
- });
132
+ // Log timeout errors specifically
133
+ if (err instanceof TimeoutError) {
134
+ logger.debug(`[${functionTag}] Timeout error`, {
135
+ provider,
136
+ modelName: this.modelName,
137
+ timeout: err.timeout,
138
+ message: err.message,
139
+ });
140
+ }
141
+ else {
142
+ logger.debug(`[${functionTag}] Exception`, {
143
+ provider,
144
+ modelName: this.modelName,
145
+ message: "Error in streaming text",
146
+ err: String(err),
147
+ });
148
+ }
128
149
  throw err; // Re-throw error to trigger fallback
129
150
  }
130
151
  }
@@ -136,7 +157,7 @@ export class OpenAI {
136
157
  const options = typeof optionsOrPrompt === "string"
137
158
  ? { prompt: optionsOrPrompt }
138
159
  : optionsOrPrompt;
139
- const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt = DEFAULT_SYSTEM_CONTEXT.systemPrompt, schema, } = options;
160
+ const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt = DEFAULT_SYSTEM_CONTEXT.systemPrompt, schema, timeout = getDefaultTimeout(provider, "generate"), } = options;
140
161
  // Use schema from options or fallback parameter
141
162
  const finalSchema = schema || analysisSchema;
142
163
  logger.debug(`[${functionTag}] Generate text started`, {
@@ -145,36 +166,63 @@ export class OpenAI {
145
166
  promptLength: prompt.length,
146
167
  temperature,
147
168
  maxTokens,
169
+ timeout,
148
170
  });
171
+ // Create timeout controller if timeout is specified
172
+ const timeoutController = createTimeoutController(timeout, provider, "generate");
149
173
  const generateOptions = {
150
174
  model: this.model,
151
175
  prompt: prompt,
152
176
  system: systemPrompt,
153
177
  temperature,
154
178
  maxTokens,
179
+ // Add abort signal if available
180
+ ...(timeoutController && {
181
+ abortSignal: timeoutController.controller.signal,
182
+ }),
155
183
  };
156
184
  if (finalSchema) {
157
185
  generateOptions.experimental_output = Output.object({
158
186
  schema: finalSchema,
159
187
  });
160
188
  }
161
- const result = await generateText(generateOptions);
162
- logger.debug(`[${functionTag}] Generate text completed`, {
163
- provider,
164
- modelName: this.modelName,
165
- usage: result.usage,
166
- finishReason: result.finishReason,
167
- responseLength: result.text?.length || 0,
168
- });
169
- return result;
189
+ try {
190
+ const result = await generateText(generateOptions);
191
+ // Clean up timeout if successful
192
+ timeoutController?.cleanup();
193
+ logger.debug(`[${functionTag}] Generate text completed`, {
194
+ provider,
195
+ modelName: this.modelName,
196
+ usage: result.usage,
197
+ finishReason: result.finishReason,
198
+ responseLength: result.text?.length || 0,
199
+ timeout,
200
+ });
201
+ return result;
202
+ }
203
+ finally {
204
+ // Always cleanup timeout
205
+ timeoutController?.cleanup();
206
+ }
170
207
  }
171
208
  catch (err) {
172
- logger.debug(`[${functionTag}] Exception`, {
173
- provider,
174
- modelName: this.modelName,
175
- message: "Error in generating text",
176
- err: String(err),
177
- });
209
+ // Log timeout errors specifically
210
+ if (err instanceof TimeoutError) {
211
+ logger.debug(`[${functionTag}] Timeout error`, {
212
+ provider,
213
+ modelName: this.modelName,
214
+ timeout: err.timeout,
215
+ message: err.message,
216
+ });
217
+ }
218
+ else {
219
+ logger.debug(`[${functionTag}] Exception`, {
220
+ provider,
221
+ modelName: this.modelName,
222
+ message: "Error in generating text",
223
+ err: String(err),
224
+ });
225
+ }
178
226
  throw err; // Re-throw error to trigger fallback
179
227
  }
180
228
  }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Timeout wrapper for AI provider operations
3
+ *
4
+ * Provides a consistent way to add timeout functionality to any async operation.
5
+ */
6
+ /**
7
+ * Wrap an async operation with a timeout
8
+ * @param promise - The promise to wrap
9
+ * @param timeout - Timeout duration (number in ms or string with unit)
10
+ * @param provider - Provider name for error messages
11
+ * @param operation - Operation type (generate or stream)
12
+ * @returns The result of the promise or throws TimeoutError
13
+ */
14
+ export declare function withTimeout<T>(promise: Promise<T>, timeout: number | string | undefined, provider: string, operation: "generate" | "stream"): Promise<T>;
15
+ /**
16
+ * Wrap a streaming async generator with timeout
17
+ * @param generator - The async generator to wrap
18
+ * @param timeout - Timeout duration for the entire stream
19
+ * @param provider - Provider name for error messages
20
+ * @returns Wrapped async generator that respects timeout
21
+ */
22
+ export declare function withStreamingTimeout<T>(generator: AsyncGenerator<T>, timeout: number | string | undefined, provider: string): AsyncGenerator<T>;
23
+ /**
24
+ * Create an abort controller with timeout
25
+ * @param timeout - Timeout duration
26
+ * @param provider - Provider name for error messages
27
+ * @param operation - Operation type
28
+ * @returns AbortController and cleanup function
29
+ */
30
+ export declare function createTimeoutController(timeout: number | string | undefined, provider: string, operation: "generate" | "stream"): {
31
+ controller: AbortController;
32
+ cleanup: () => void;
33
+ timeoutMs: number;
34
+ } | null;
35
+ /**
36
+ * Merge abort signals (for combining user abort with timeout)
37
+ * @param signals - Array of abort signals to merge
38
+ * @returns Combined abort controller
39
+ */
40
+ export declare function mergeAbortSignals(signals: (AbortSignal | undefined)[]): AbortController;
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Timeout wrapper for AI provider operations
3
+ *
4
+ * Provides a consistent way to add timeout functionality to any async operation.
5
+ */
6
+ import { parseTimeout, TimeoutError, createTimeoutPromise, } from "../utils/timeout.js";
7
+ /**
8
+ * Wrap an async operation with a timeout
9
+ * @param promise - The promise to wrap
10
+ * @param timeout - Timeout duration (number in ms or string with unit)
11
+ * @param provider - Provider name for error messages
12
+ * @param operation - Operation type (generate or stream)
13
+ * @returns The result of the promise or throws TimeoutError
14
+ */
15
+ export async function withTimeout(promise, timeout, provider, operation) {
16
+ const timeoutPromise = createTimeoutPromise(timeout, provider, operation);
17
+ if (!timeoutPromise) {
18
+ // No timeout specified, return original promise
19
+ return promise;
20
+ }
21
+ // Race between the actual operation and timeout
22
+ return Promise.race([promise, timeoutPromise]);
23
+ }
24
+ /**
25
+ * Wrap a streaming async generator with timeout
26
+ * @param generator - The async generator to wrap
27
+ * @param timeout - Timeout duration for the entire stream
28
+ * @param provider - Provider name for error messages
29
+ * @returns Wrapped async generator that respects timeout
30
+ */
31
+ export async function* withStreamingTimeout(generator, timeout, provider) {
32
+ const timeoutMs = parseTimeout(timeout);
33
+ if (!timeoutMs) {
34
+ // No timeout, pass through original generator
35
+ yield* generator;
36
+ return;
37
+ }
38
+ const startTime = Date.now();
39
+ try {
40
+ for await (const chunk of generator) {
41
+ // Check if we've exceeded the timeout
42
+ if (Date.now() - startTime > timeoutMs) {
43
+ throw new TimeoutError(`${provider} streaming operation timed out after ${timeout}`, timeoutMs, provider, "stream");
44
+ }
45
+ yield chunk;
46
+ }
47
+ }
48
+ finally {
49
+ // Ensure generator is properly closed
50
+ if (generator.return) {
51
+ await generator.return(undefined);
52
+ }
53
+ }
54
+ }
55
+ /**
56
+ * Create an abort controller with timeout
57
+ * @param timeout - Timeout duration
58
+ * @param provider - Provider name for error messages
59
+ * @param operation - Operation type
60
+ * @returns AbortController and cleanup function
61
+ */
62
+ export function createTimeoutController(timeout, provider, operation) {
63
+ const timeoutMs = parseTimeout(timeout);
64
+ if (!timeoutMs) {
65
+ return null;
66
+ }
67
+ const controller = new AbortController();
68
+ const timer = setTimeout(() => {
69
+ controller.abort(new TimeoutError(`${provider} ${operation} operation timed out after ${timeout}`, timeoutMs, provider, operation));
70
+ }, timeoutMs);
71
+ // Cleanup function to clear the timer
72
+ const cleanup = () => {
73
+ clearTimeout(timer);
74
+ };
75
+ return { controller, cleanup, timeoutMs };
76
+ }
77
+ /**
78
+ * Merge abort signals (for combining user abort with timeout)
79
+ * @param signals - Array of abort signals to merge
80
+ * @returns Combined abort controller
81
+ */
82
+ export function mergeAbortSignals(signals) {
83
+ const controller = new AbortController();
84
+ // Listen to all signals and abort when any fires
85
+ for (const signal of signals) {
86
+ if (signal && !signal.aborted) {
87
+ signal.addEventListener("abort", () => {
88
+ if (!controller.signal.aborted) {
89
+ controller.abort(signal.reason);
90
+ }
91
+ });
92
+ }
93
+ // If any signal is already aborted, abort immediately
94
+ if (signal?.aborted) {
95
+ controller.abort(signal.reason);
96
+ break;
97
+ }
98
+ }
99
+ return controller;
100
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Proxy-aware fetch implementation for AI SDK providers
3
+ * Implements the proven Vercel AI SDK proxy pattern using undici
4
+ */
5
+ /**
6
+ * Create a proxy-aware fetch function
7
+ * This implements the community-validated approach for Vercel AI SDK
8
+ */
9
+ export declare function createProxyFetch(): typeof fetch;
10
+ /**
11
+ * Get proxy status information
12
+ */
13
+ export declare function getProxyStatus(): {
14
+ enabled: boolean;
15
+ httpProxy: string | null;
16
+ httpsProxy: string | null;
17
+ method: string;
18
+ };
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Proxy-aware fetch implementation for AI SDK providers
3
+ * Implements the proven Vercel AI SDK proxy pattern using undici
4
+ */
5
+ /**
6
+ * Create a proxy-aware fetch function
7
+ * This implements the community-validated approach for Vercel AI SDK
8
+ */
9
+ export function createProxyFetch() {
10
+ const httpsProxy = process.env.HTTPS_PROXY || process.env.https_proxy;
11
+ const httpProxy = process.env.HTTP_PROXY || process.env.http_proxy;
12
+ // If no proxy configured, return standard fetch
13
+ if (!httpsProxy && !httpProxy) {
14
+ console.log("[Proxy Fetch] No proxy environment variables found - using standard fetch");
15
+ return fetch;
16
+ }
17
+ console.log(`[Proxy Fetch] Configuring proxy with undici ProxyAgent:`);
18
+ console.log(`[Proxy Fetch] HTTP_PROXY: ${httpProxy || "not set"}`);
19
+ console.log(`[Proxy Fetch] HTTPS_PROXY: ${httpsProxy || "not set"}`);
20
+ // Return proxy-aware fetch function
21
+ return async (input, init) => {
22
+ try {
23
+ // Dynamic import undici to avoid build issues
24
+ const undici = await import("undici");
25
+ const { ProxyAgent } = undici;
26
+ const url = typeof input === "string"
27
+ ? new URL(input)
28
+ : input instanceof URL
29
+ ? input
30
+ : new URL(input.url);
31
+ const proxyUrl = url.protocol === "https:" ? httpsProxy : httpProxy;
32
+ if (proxyUrl) {
33
+ console.log(`[Proxy Fetch] Creating ProxyAgent for ${url.hostname} via ${proxyUrl}`);
34
+ // Create ProxyAgent
35
+ const dispatcher = new ProxyAgent(proxyUrl);
36
+ // Use undici fetch with dispatcher
37
+ const response = await undici.fetch(input, {
38
+ ...init,
39
+ dispatcher: dispatcher,
40
+ });
41
+ console.log(`[Proxy Fetch] ✅ Request proxied successfully to ${url.hostname}`);
42
+ return response; // Type assertion to avoid complex type issues
43
+ }
44
+ }
45
+ catch (error) {
46
+ console.warn(`[Proxy Fetch] Proxy failed (${error.message}), falling back to direct connection`);
47
+ }
48
+ // Fallback to standard fetch
49
+ return fetch(input, init);
50
+ };
51
+ }
52
+ /**
53
+ * Get proxy status information
54
+ */
55
+ export function getProxyStatus() {
56
+ const httpsProxy = process.env.HTTPS_PROXY || process.env.https_proxy;
57
+ const httpProxy = process.env.HTTP_PROXY || process.env.http_proxy;
58
+ return {
59
+ enabled: !!(httpsProxy || httpProxy),
60
+ httpProxy: httpProxy || null,
61
+ httpsProxy: httpsProxy || null,
62
+ method: "undici-proxy-agent",
63
+ };
64
+ }
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Timeout utilities for NeuroLink
3
+ *
4
+ * Provides flexible timeout parsing and error handling for AI operations.
5
+ * Supports multiple time formats: milliseconds, seconds, minutes, hours.
6
+ */
7
+ /**
8
+ * Custom error class for timeout operations
9
+ */
10
+ export declare class TimeoutError extends Error {
11
+ readonly timeout: number;
12
+ readonly provider?: string | undefined;
13
+ readonly operation?: "generate" | "stream" | undefined;
14
+ constructor(message: string, timeout: number, provider?: string | undefined, operation?: "generate" | "stream" | undefined);
15
+ }
16
+ /**
17
+ * Parse timeout value from various formats
18
+ * @param timeout - Can be number (ms), string with unit, or undefined
19
+ * @returns Parsed timeout in milliseconds or undefined
20
+ * @throws Error if format is invalid
21
+ *
22
+ * Examples:
23
+ * - parseTimeout(5000) => 5000
24
+ * - parseTimeout('30s') => 30000
25
+ * - parseTimeout('2m') => 120000
26
+ * - parseTimeout('1.5h') => 5400000
27
+ * - parseTimeout(undefined) => undefined
28
+ */
29
+ export declare function parseTimeout(timeout: number | string | undefined): number | undefined;
30
+ /**
31
+ * Default timeout configurations for different providers and operations
32
+ */
33
+ export declare const DEFAULT_TIMEOUTS: {
34
+ global: string;
35
+ streaming: string;
36
+ providers: {
37
+ openai: string;
38
+ bedrock: string;
39
+ vertex: string;
40
+ anthropic: string;
41
+ azure: string;
42
+ "google-ai": string;
43
+ huggingface: string;
44
+ ollama: string;
45
+ mistral: string;
46
+ };
47
+ tools: {
48
+ default: string;
49
+ filesystem: string;
50
+ network: string;
51
+ computation: string;
52
+ };
53
+ };
54
+ /**
55
+ * Get default timeout for a specific provider
56
+ * @param provider - Provider name
57
+ * @param operation - Operation type (generate or stream)
58
+ * @returns Default timeout string
59
+ */
60
+ export declare function getDefaultTimeout(provider: string, operation?: "generate" | "stream"): string;
61
+ /**
62
+ * Create a timeout promise that rejects after specified duration
63
+ * @param timeout - Timeout duration
64
+ * @param provider - Provider name for error message
65
+ * @param operation - Operation type for error message
66
+ * @returns Promise that rejects with TimeoutError
67
+ */
68
+ export declare function createTimeoutPromise(timeout: number | string | undefined, provider: string, operation: "generate" | "stream"): Promise<never> | null;
69
+ export { createTimeoutController } from "../providers/timeout-wrapper.js";
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Timeout utilities for NeuroLink
3
+ *
4
+ * Provides flexible timeout parsing and error handling for AI operations.
5
+ * Supports multiple time formats: milliseconds, seconds, minutes, hours.
6
+ */
7
+ /**
8
+ * Custom error class for timeout operations
9
+ */
10
+ export class TimeoutError extends Error {
11
+ timeout;
12
+ provider;
13
+ operation;
14
+ constructor(message, timeout, provider, operation) {
15
+ super(message);
16
+ this.timeout = timeout;
17
+ this.provider = provider;
18
+ this.operation = operation;
19
+ this.name = "TimeoutError";
20
+ // Maintains proper stack trace for where error was thrown
21
+ if (typeof Error.captureStackTrace === "function") {
22
+ Error.captureStackTrace(this, TimeoutError);
23
+ }
24
+ }
25
+ }
26
+ /**
27
+ * Parse timeout value from various formats
28
+ * @param timeout - Can be number (ms), string with unit, or undefined
29
+ * @returns Parsed timeout in milliseconds or undefined
30
+ * @throws Error if format is invalid
31
+ *
32
+ * Examples:
33
+ * - parseTimeout(5000) => 5000
34
+ * - parseTimeout('30s') => 30000
35
+ * - parseTimeout('2m') => 120000
36
+ * - parseTimeout('1.5h') => 5400000
37
+ * - parseTimeout(undefined) => undefined
38
+ */
39
+ export function parseTimeout(timeout) {
40
+ if (timeout === undefined) {
41
+ return undefined;
42
+ }
43
+ if (typeof timeout === "number") {
44
+ if (timeout <= 0) {
45
+ throw new Error(`Timeout must be positive, got: ${timeout}`);
46
+ }
47
+ return timeout; // Assume milliseconds
48
+ }
49
+ if (typeof timeout === "string") {
50
+ // Match number (including decimals) followed by optional unit
51
+ const match = timeout.match(/^(\d+(?:\.\d+)?)(ms|s|m|h)?$/);
52
+ if (!match) {
53
+ throw new Error(`Invalid timeout format: ${timeout}. Use formats like '30s', '2m', '500ms', or '1.5h'`);
54
+ }
55
+ const value = parseFloat(match[1]);
56
+ if (value <= 0) {
57
+ throw new Error(`Timeout must be positive, got: ${value}`);
58
+ }
59
+ const unit = match[2] || "ms";
60
+ switch (unit) {
61
+ case "ms":
62
+ return value;
63
+ case "s":
64
+ return value * 1000;
65
+ case "m":
66
+ return value * 60 * 1000;
67
+ case "h":
68
+ return value * 60 * 60 * 1000;
69
+ default:
70
+ return value; // Should never reach here due to regex
71
+ }
72
+ }
73
+ throw new Error(`Invalid timeout type: ${typeof timeout}`);
74
+ }
75
+ /**
76
+ * Default timeout configurations for different providers and operations
77
+ */
78
+ export const DEFAULT_TIMEOUTS = {
79
+ global: "30s", // Default for all providers
80
+ streaming: "2m", // Longer timeout for streaming operations
81
+ providers: {
82
+ openai: "30s", // OpenAI typically responds quickly
83
+ bedrock: "45s", // AWS can be slower, especially for cold starts
84
+ vertex: "60s", // Google Cloud can be slower
85
+ anthropic: "30s", // Direct Anthropic API is fast
86
+ azure: "30s", // Azure OpenAI similar to OpenAI
87
+ "google-ai": "30s", // Google AI Studio is fast
88
+ huggingface: "2m", // Open source models vary significantly
89
+ ollama: "5m", // Local models need more time, especially large ones
90
+ mistral: "45s", // Mistral AI moderate speed
91
+ },
92
+ tools: {
93
+ default: "10s", // Default timeout for MCP tool execution
94
+ filesystem: "5s", // File operations should be quick
95
+ network: "30s", // Network requests might take longer
96
+ computation: "2m", // Heavy computation tools need more time
97
+ },
98
+ };
99
+ /**
100
+ * Get default timeout for a specific provider
101
+ * @param provider - Provider name
102
+ * @param operation - Operation type (generate or stream)
103
+ * @returns Default timeout string
104
+ */
105
+ export function getDefaultTimeout(provider, operation = "generate") {
106
+ if (operation === "stream") {
107
+ return DEFAULT_TIMEOUTS.streaming;
108
+ }
109
+ const providerKey = provider.toLowerCase().replace("_", "-");
110
+ return (DEFAULT_TIMEOUTS.providers[providerKey] || DEFAULT_TIMEOUTS.global);
111
+ }
112
+ /**
113
+ * Create a timeout promise that rejects after specified duration
114
+ * @param timeout - Timeout duration
115
+ * @param provider - Provider name for error message
116
+ * @param operation - Operation type for error message
117
+ * @returns Promise that rejects with TimeoutError
118
+ */
119
+ export function createTimeoutPromise(timeout, provider, operation) {
120
+ const timeoutMs = parseTimeout(timeout);
121
+ if (!timeoutMs) {
122
+ return null; // No timeout
123
+ }
124
+ return new Promise((_, reject) => {
125
+ const timer = setTimeout(() => {
126
+ reject(new TimeoutError(`${provider} ${operation} operation timed out after ${timeout}`, timeoutMs, provider, operation));
127
+ }, timeoutMs);
128
+ // Unref the timer so it doesn't keep the process alive (Node.js only)
129
+ if (typeof timer === "object" &&
130
+ timer &&
131
+ "unref" in timer &&
132
+ typeof timer.unref === "function") {
133
+ timer.unref();
134
+ }
135
+ });
136
+ }
137
+ // Re-export createTimeoutController from timeout-wrapper for convenience
138
+ export { createTimeoutController } from "../providers/timeout-wrapper.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "2.0.0",
3
+ "version": "3.0.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",
@@ -138,6 +138,7 @@
138
138
  "dotenv": "^16.5.0",
139
139
  "express": "^5.1.0",
140
140
  "inquirer": "^9.2.15",
141
+ "undici": "^6.6.2",
141
142
  "ora": "^7.0.1",
142
143
  "playwright": "^1.52.0",
143
144
  "uuid": "^11.1.0",