@juspay/neurolink 2.0.0 → 2.1.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 (43) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +31 -5
  3. package/dist/cli/commands/config.d.ts +6 -6
  4. package/dist/cli/index.js +29 -30
  5. package/dist/core/types.d.ts +2 -0
  6. package/dist/lib/core/types.d.ts +2 -0
  7. package/dist/lib/neurolink.d.ts +2 -0
  8. package/dist/lib/neurolink.js +23 -2
  9. package/dist/lib/providers/agent-enhanced-provider.d.ts +1 -0
  10. package/dist/lib/providers/agent-enhanced-provider.js +59 -3
  11. package/dist/lib/providers/amazonBedrock.js +70 -24
  12. package/dist/lib/providers/anthropic.js +77 -15
  13. package/dist/lib/providers/azureOpenAI.js +77 -15
  14. package/dist/lib/providers/googleAIStudio.js +70 -26
  15. package/dist/lib/providers/googleVertexAI.js +70 -24
  16. package/dist/lib/providers/huggingFace.js +70 -26
  17. package/dist/lib/providers/mistralAI.js +70 -26
  18. package/dist/lib/providers/ollama.d.ts +1 -1
  19. package/dist/lib/providers/ollama.js +24 -10
  20. package/dist/lib/providers/openAI.js +67 -23
  21. package/dist/lib/providers/timeout-wrapper.d.ts +40 -0
  22. package/dist/lib/providers/timeout-wrapper.js +100 -0
  23. package/dist/lib/utils/timeout.d.ts +69 -0
  24. package/dist/lib/utils/timeout.js +130 -0
  25. package/dist/neurolink.d.ts +2 -0
  26. package/dist/neurolink.js +23 -2
  27. package/dist/providers/agent-enhanced-provider.d.ts +1 -0
  28. package/dist/providers/agent-enhanced-provider.js +59 -3
  29. package/dist/providers/amazonBedrock.js +70 -24
  30. package/dist/providers/anthropic.js +77 -15
  31. package/dist/providers/azureOpenAI.js +77 -15
  32. package/dist/providers/googleAIStudio.js +70 -26
  33. package/dist/providers/googleVertexAI.js +70 -24
  34. package/dist/providers/huggingFace.js +70 -26
  35. package/dist/providers/mistralAI.js +70 -26
  36. package/dist/providers/ollama.d.ts +1 -1
  37. package/dist/providers/ollama.js +24 -10
  38. package/dist/providers/openAI.js +67 -23
  39. package/dist/providers/timeout-wrapper.d.ts +40 -0
  40. package/dist/providers/timeout-wrapper.js +100 -0
  41. package/dist/utils/timeout.d.ts +69 -0
  42. package/dist/utils/timeout.js +130 -0
  43. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ # [2.1.0](https://github.com/juspay/neurolink/compare/v2.0.0...v2.1.0) (2025-06-29)
2
+
3
+
4
+ ### Features
5
+
6
+ * **timeout:** add comprehensive timeout support for all AI providers ([8610f4a](https://github.com/juspay/neurolink/commit/8610f4ade418345b0395ab72af6e675f6eec6f93))
7
+
1
8
  # [2.0.0](https://github.com/juspay/neurolink/compare/v1.11.3...v2.0.0) (2025-06-28)
2
9
 
3
10
 
package/README.md CHANGED
@@ -61,6 +61,7 @@ import { createBestAIProvider } from "@juspay/neurolink";
61
61
  const provider = createBestAIProvider();
62
62
  const result = await provider.generateText({
63
63
  prompt: "Write a haiku about programming",
64
+ timeout: '30s' // Optional: Set custom timeout (default: 30s)
64
65
  });
65
66
 
66
67
  console.log(result.text);
@@ -182,36 +183,61 @@ npx @juspay/neurolink gen "What time is it?"
182
183
  # Disable tools for training-data-only responses
183
184
  npx @juspay/neurolink generate "What time is it?" --disable-tools
184
185
 
186
+ # With custom timeout for complex prompts
187
+ npx @juspay/neurolink generate "Explain quantum computing in detail" --timeout 1m
188
+
185
189
  # Real-time streaming with agent support (default)
186
190
  npx @juspay/neurolink stream "What time is it?"
187
191
 
188
192
  # Streaming without tools (traditional mode)
189
193
  npx @juspay/neurolink stream "Tell me a story" --disable-tools
190
194
 
195
+ # Streaming with extended timeout
196
+ npx @juspay/neurolink stream "Write a long story" --timeout 5m
197
+
191
198
  # Provider diagnostics
192
199
  npx @juspay/neurolink status --verbose
193
200
 
194
201
  # Batch processing
195
202
  echo -e "Write a haiku\nExplain gravity" > prompts.txt
196
203
  npx @juspay/neurolink batch prompts.txt --output results.json
204
+
205
+ # Batch with custom timeout per request
206
+ npx @juspay/neurolink batch prompts.txt --timeout 45s --output results.json
197
207
  ```
198
208
 
199
209
  ### SDK Integration
200
210
 
201
211
  ```typescript
202
- // SvelteKit API route
212
+ // SvelteKit API route with timeout handling
203
213
  export const POST: RequestHandler = async ({ request }) => {
204
214
  const { message } = await request.json();
205
215
  const provider = createBestAIProvider();
206
- const result = await provider.streamText({ prompt: message });
207
- return new Response(result.toReadableStream());
216
+
217
+ try {
218
+ const result = await provider.streamText({
219
+ prompt: message,
220
+ timeout: '2m' // 2 minutes for streaming
221
+ });
222
+ return new Response(result.toReadableStream());
223
+ } catch (error) {
224
+ if (error.name === 'TimeoutError') {
225
+ return new Response('Request timed out', { status: 408 });
226
+ }
227
+ throw error;
228
+ }
208
229
  };
209
230
 
210
- // Next.js API route
231
+ // Next.js API route with timeout
211
232
  export async function POST(request: NextRequest) {
212
233
  const { prompt } = await request.json();
213
234
  const provider = createBestAIProvider();
214
- const result = await provider.generateText({ prompt });
235
+
236
+ const result = await provider.generateText({
237
+ prompt,
238
+ timeout: process.env.AI_TIMEOUT || '30s' // Configurable timeout
239
+ });
240
+
215
241
  return NextResponse.json({ text: result.text });
216
242
  }
217
243
  ```
@@ -117,12 +117,12 @@ declare const ConfigSchema: z.ZodObject<{
117
117
  model: z.ZodDefault<z.ZodString>;
118
118
  timeout: z.ZodDefault<z.ZodNumber>;
119
119
  }, "strip", z.ZodTypeAny, {
120
- model: string;
121
120
  timeout: number;
121
+ model: string;
122
122
  baseUrl: string;
123
123
  }, {
124
- model?: string | undefined;
125
124
  timeout?: number | undefined;
125
+ model?: string | undefined;
126
126
  baseUrl?: string | undefined;
127
127
  }>>;
128
128
  mistral: z.ZodOptional<z.ZodObject<{
@@ -176,8 +176,8 @@ declare const ConfigSchema: z.ZodObject<{
176
176
  apiKey?: string | undefined;
177
177
  } | undefined;
178
178
  ollama?: {
179
- model: string;
180
179
  timeout: number;
180
+ model: string;
181
181
  baseUrl: string;
182
182
  } | undefined;
183
183
  mistral?: {
@@ -225,8 +225,8 @@ declare const ConfigSchema: z.ZodObject<{
225
225
  apiKey?: string | undefined;
226
226
  } | undefined;
227
227
  ollama?: {
228
- model?: string | undefined;
229
228
  timeout?: number | undefined;
229
+ model?: string | undefined;
230
230
  baseUrl?: string | undefined;
231
231
  } | undefined;
232
232
  mistral?: {
@@ -299,8 +299,8 @@ declare const ConfigSchema: z.ZodObject<{
299
299
  apiKey?: string | undefined;
300
300
  } | undefined;
301
301
  ollama?: {
302
- model: string;
303
302
  timeout: number;
303
+ model: string;
304
304
  baseUrl: string;
305
305
  } | undefined;
306
306
  mistral?: {
@@ -360,8 +360,8 @@ declare const ConfigSchema: z.ZodObject<{
360
360
  apiKey?: string | undefined;
361
361
  } | undefined;
362
362
  ollama?: {
363
- model?: string | undefined;
364
363
  timeout?: number | undefined;
364
+ model?: string | undefined;
365
365
  baseUrl?: string | undefined;
366
366
  } | undefined;
367
367
  mistral?: {
package/dist/cli/index.js CHANGED
@@ -253,9 +253,9 @@ const cli = yargs(args)
253
253
  description: "Enable debug mode with verbose output",
254
254
  }) // Kept for potential specific debug logic
255
255
  .option("timeout", {
256
- type: "number",
257
- default: 30000,
258
- description: "Timeout for the request in milliseconds",
256
+ type: "string",
257
+ default: "30s",
258
+ description: "Timeout for the request (e.g., 30s, 2m, 1h, 5000)",
259
259
  })
260
260
  .option("disable-tools", {
261
261
  type: "boolean",
@@ -285,9 +285,8 @@ const cli = yargs(args)
285
285
  ? null
286
286
  : ora("🤖 Generating text...").start();
287
287
  try {
288
- const timeoutPromise = new Promise((_, reject) => {
289
- setTimeout(() => reject(new Error(`Request timeout (${argv.timeout}ms)`)), argv.timeout);
290
- });
288
+ // The SDK will handle the timeout internally, so we don't need this wrapper anymore
289
+ // Just pass the timeout to the SDK
291
290
  // Use AgentEnhancedProvider when tools are enabled, otherwise use standard SDK
292
291
  let generatePromise;
293
292
  if (argv.disableTools === true) {
@@ -300,6 +299,7 @@ const cli = yargs(args)
300
299
  temperature: argv.temperature,
301
300
  maxTokens: argv.maxTokens,
302
301
  systemPrompt: argv.system,
302
+ timeout: argv.timeout,
303
303
  });
304
304
  }
305
305
  else {
@@ -323,10 +323,7 @@ const cli = yargs(args)
323
323
  });
324
324
  generatePromise = agentProvider.generateText(argv.prompt);
325
325
  }
326
- const result = (await Promise.race([
327
- generatePromise,
328
- timeoutPromise,
329
- ]));
326
+ const result = await generatePromise;
330
327
  if (argv.format === "json" && originalConsole.log) {
331
328
  Object.assign(console, originalConsole);
332
329
  }
@@ -334,20 +331,20 @@ const cli = yargs(args)
334
331
  spinner.succeed(chalk.green("✅ Text generated successfully!"));
335
332
  }
336
333
  // Handle both AgentEnhancedProvider (AI SDK) and standard NeuroLink SDK responses
337
- const responseText = result.text || result.content || "";
338
- const responseUsage = result.usage || {
334
+ const responseText = result ? (result.text || result.content || "") : "";
335
+ const responseUsage = result ? (result.usage || {
339
336
  promptTokens: 0,
340
337
  completionTokens: 0,
341
338
  totalTokens: 0,
342
- };
339
+ }) : { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
343
340
  if (argv.format === "json") {
344
341
  const jsonOutput = {
345
342
  content: responseText,
346
- provider: result.provider || argv.provider,
343
+ provider: result ? (result.provider || argv.provider) : argv.provider,
347
344
  usage: responseUsage,
348
- responseTime: result.responseTime || 0,
349
- toolCalls: result.toolCalls || [],
350
- toolResults: result.toolResults || [],
345
+ responseTime: result ? (result.responseTime || 0) : 0,
346
+ toolCalls: result ? (result.toolCalls || []) : [],
347
+ toolResults: result ? (result.toolResults || []) : [],
351
348
  };
352
349
  process.stdout.write(JSON.stringify(jsonOutput, null, 2) + "\n");
353
350
  }
@@ -357,7 +354,7 @@ const cli = yargs(args)
357
354
  console.log("\n" + responseText + "\n");
358
355
  }
359
356
  // Show tool calls if any
360
- if (result.toolCalls && result.toolCalls.length > 0) {
357
+ if (result && result.toolCalls && result.toolCalls.length > 0) {
361
358
  console.log(chalk.blue("🔧 Tools Called:"));
362
359
  for (const toolCall of result.toolCalls) {
363
360
  console.log(`- ${toolCall.toolName}`);
@@ -366,7 +363,7 @@ const cli = yargs(args)
366
363
  console.log();
367
364
  }
368
365
  // Show tool results if any
369
- if (result.toolResults && result.toolResults.length > 0) {
366
+ if (result && result.toolResults && result.toolResults.length > 0) {
370
367
  console.log(chalk.blue("📋 Tool Results:"));
371
368
  for (const toolResult of result.toolResults) {
372
369
  console.log(`- ${toolResult.toolCallId}`);
@@ -375,9 +372,9 @@ const cli = yargs(args)
375
372
  console.log();
376
373
  }
377
374
  console.log(JSON.stringify({
378
- provider: result.provider || argv.provider,
375
+ provider: result ? (result.provider || argv.provider) : argv.provider,
379
376
  usage: responseUsage,
380
- responseTime: result.responseTime || 0,
377
+ responseTime: result ? (result.responseTime || 0) : 0,
381
378
  }, null, 2));
382
379
  if (responseUsage.totalTokens) {
383
380
  console.log(chalk.blue(`ℹ️ ${responseUsage.totalTokens} tokens used`));
@@ -436,6 +433,11 @@ const cli = yargs(args)
436
433
  type: "number",
437
434
  default: 0.7,
438
435
  description: "Creativity level",
436
+ })
437
+ .option("timeout", {
438
+ type: "string",
439
+ default: "2m",
440
+ description: "Timeout for streaming (e.g., 30s, 2m, 1h)",
439
441
  })
440
442
  .option("debug", {
441
443
  type: "boolean",
@@ -468,6 +470,7 @@ const cli = yargs(args)
468
470
  ? undefined
469
471
  : argv.provider,
470
472
  temperature: argv.temperature,
473
+ timeout: argv.timeout,
471
474
  });
472
475
  }
473
476
  else {
@@ -552,9 +555,9 @@ const cli = yargs(args)
552
555
  description: "AI provider to use",
553
556
  })
554
557
  .option("timeout", {
555
- type: "number",
556
- default: 30000,
557
- description: "Timeout for each request in milliseconds",
558
+ type: "string",
559
+ default: "30s",
560
+ description: "Timeout for each request (e.g., 30s, 2m, 1h)",
558
561
  })
559
562
  .option("temperature", {
560
563
  type: "number",
@@ -607,8 +610,7 @@ const cli = yargs(args)
607
610
  spinner.text = `Processing ${i + 1}/${prompts.length}: ${prompts[i].substring(0, 30)}...`;
608
611
  }
609
612
  try {
610
- const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error("Request timeout")), argv.timeout));
611
- const generatePromise = sdk.generateText({
613
+ const result = await sdk.generateText({
612
614
  prompt: prompts[i],
613
615
  provider: argv.provider === "auto"
614
616
  ? undefined
@@ -616,11 +618,8 @@ const cli = yargs(args)
616
618
  temperature: argv.temperature,
617
619
  maxTokens: argv.maxTokens,
618
620
  systemPrompt: argv.system,
621
+ timeout: argv.timeout,
619
622
  });
620
- const result = (await Promise.race([
621
- generatePromise,
622
- timeoutPromise,
623
- ]));
624
623
  results.push({ prompt: prompts[i], response: result.content });
625
624
  if (spinner) {
626
625
  spinner.render();
@@ -80,6 +80,7 @@ export interface TextGenerationOptions {
80
80
  systemPrompt?: string;
81
81
  schema?: ZodType<unknown, ZodTypeDef, unknown> | Schema<unknown>;
82
82
  tools?: Record<string, Tool>;
83
+ timeout?: number | string;
83
84
  }
84
85
  /**
85
86
  * Stream text options interface
@@ -92,6 +93,7 @@ export interface StreamTextOptions {
92
93
  systemPrompt?: string;
93
94
  schema?: ZodType<unknown, ZodTypeDef, unknown> | Schema<unknown>;
94
95
  tools?: Record<string, Tool>;
96
+ timeout?: number | string;
95
97
  }
96
98
  /**
97
99
  * AI Provider interface with flexible parameter support
@@ -80,6 +80,7 @@ export interface TextGenerationOptions {
80
80
  systemPrompt?: string;
81
81
  schema?: ZodType<unknown, ZodTypeDef, unknown> | Schema<unknown>;
82
82
  tools?: Record<string, Tool>;
83
+ timeout?: number | string;
83
84
  }
84
85
  /**
85
86
  * Stream text options interface
@@ -92,6 +93,7 @@ export interface StreamTextOptions {
92
93
  systemPrompt?: string;
93
94
  schema?: ZodType<unknown, ZodTypeDef, unknown> | Schema<unknown>;
94
95
  tools?: Record<string, Tool>;
96
+ timeout?: number | string;
95
97
  }
96
98
  /**
97
99
  * AI Provider interface with flexible parameter support
@@ -12,6 +12,7 @@ export interface TextGenerationOptions {
12
12
  maxTokens?: number;
13
13
  systemPrompt?: string;
14
14
  schema?: any;
15
+ timeout?: number | string;
15
16
  disableTools?: boolean;
16
17
  }
17
18
  export interface StreamTextOptions {
@@ -20,6 +21,7 @@ export interface StreamTextOptions {
20
21
  temperature?: number;
21
22
  maxTokens?: number;
22
23
  systemPrompt?: string;
24
+ timeout?: number | string;
23
25
  }
24
26
  export interface TextGenerationResult {
25
27
  content: string;
@@ -11,6 +11,7 @@ import { toolRegistry } from "./mcp/tool-registry.js";
11
11
  import { unifiedRegistry } from "./mcp/unified-registry.js";
12
12
  import { logger } from "./utils/logger.js";
13
13
  import { getBestProvider } from "./utils/providerUtils-fixed.js";
14
+ import { TimeoutError } from "./utils/timeout.js";
14
15
  export class NeuroLink {
15
16
  mcpInitialized = false;
16
17
  contextManager;
@@ -32,10 +33,9 @@ export class NeuroLink {
32
33
  const mcpInitPromise = Promise.race([
33
34
  this.doIsolatedMCPInitialization(),
34
35
  new Promise((_, reject) => {
35
- const timer = setTimeout(() => {
36
+ setTimeout(() => {
36
37
  reject(new Error("MCP initialization timeout after 3s"));
37
38
  }, initTimeout);
38
- timer.unref(); // Don't keep process alive
39
39
  }),
40
40
  ]);
41
41
  await mcpInitPromise;
@@ -134,6 +134,7 @@ export class NeuroLink {
134
134
  temperature: options.temperature,
135
135
  maxTokens: options.maxTokens,
136
136
  systemPrompt: enhancedSystemPrompt,
137
+ timeout: options.timeout,
137
138
  }, options.schema);
138
139
  if (!result) {
139
140
  throw new Error("No response received from AI provider");
@@ -222,6 +223,7 @@ export class NeuroLink {
222
223
  temperature: options.temperature,
223
224
  maxTokens: options.maxTokens,
224
225
  systemPrompt: options.systemPrompt,
226
+ timeout: options.timeout,
225
227
  }, options.schema);
226
228
  if (!result) {
227
229
  throw new Error("No response received from AI provider");
@@ -252,9 +254,18 @@ export class NeuroLink {
252
254
  catch (error) {
253
255
  const errorMessage = error instanceof Error ? error.message : String(error);
254
256
  lastError = error instanceof Error ? error : new Error(errorMessage);
257
+ // Special handling for timeout errors
258
+ if (error instanceof TimeoutError) {
259
+ logger.warn(`[${functionTag}] Provider timed out`, {
260
+ provider: providerName,
261
+ timeout: error.timeout,
262
+ operation: error.operation,
263
+ });
264
+ }
255
265
  logger.debug(`[${functionTag}] Provider failed, trying next`, {
256
266
  provider: providerName,
257
267
  error: errorMessage,
268
+ isTimeout: error instanceof TimeoutError,
258
269
  remainingProviders: tryProviders.slice(tryProviders.indexOf(providerName) + 1),
259
270
  });
260
271
  // Continue to next provider
@@ -338,6 +349,7 @@ Note: Tool integration is currently in development. Please provide helpful respo
338
349
  temperature: options.temperature,
339
350
  maxTokens: options.maxTokens,
340
351
  systemPrompt: options.systemPrompt,
352
+ timeout: options.timeout,
341
353
  });
342
354
  if (!result) {
343
355
  throw new Error("No stream response received from AI provider");
@@ -358,9 +370,18 @@ Note: Tool integration is currently in development. Please provide helpful respo
358
370
  catch (error) {
359
371
  const errorMessage = error instanceof Error ? error.message : String(error);
360
372
  lastError = error instanceof Error ? error : new Error(errorMessage);
373
+ // Special handling for timeout errors
374
+ if (error instanceof TimeoutError) {
375
+ logger.warn(`[${functionTag}] Provider timed out`, {
376
+ provider: providerName,
377
+ timeout: error.timeout,
378
+ operation: error.operation,
379
+ });
380
+ }
361
381
  logger.debug(`[${functionTag}] Provider failed, trying next`, {
362
382
  provider: providerName,
363
383
  error: errorMessage,
384
+ isTimeout: error instanceof TimeoutError,
364
385
  remainingProviders: tryProviders.slice(tryProviders.indexOf(providerName) + 1),
365
386
  });
366
387
  // Continue to next provider
@@ -15,6 +15,7 @@ interface AgentConfig {
15
15
  enableTools?: boolean;
16
16
  enableMCP?: boolean;
17
17
  mcpInitTimeoutMs?: number;
18
+ toolExecutionTimeout?: number | string;
18
19
  mcpDiscoveryOptions?: {
19
20
  searchPaths?: string[];
20
21
  configFiles?: string[];
@@ -9,6 +9,7 @@ import { anthropic } from "@ai-sdk/anthropic";
9
9
  import { getToolsForCategory, } from "../agent/direct-tools.js";
10
10
  import { UnifiedMCPSystem } from "../mcp/unified-mcp.js";
11
11
  import { mcpLogger } from "../mcp/logging.js";
12
+ import { parseTimeout } from "../utils/timeout.js";
12
13
  /**
13
14
  * Agent-Enhanced Provider Class
14
15
  * Provides AI generation with tool calling capabilities
@@ -114,7 +115,21 @@ export class AgentEnhancedProvider {
114
115
  description: toolInfo.description || `MCP tool: ${toolInfo.name}`,
115
116
  parameters: toolInfo.inputSchema || {},
116
117
  execute: async (args) => {
118
+ let timeoutId;
117
119
  try {
120
+ // Create timeout controller for tool execution if configured
121
+ const toolTimeout = this.config.toolExecutionTimeout;
122
+ const toolAbortController = toolTimeout
123
+ ? new AbortController()
124
+ : undefined;
125
+ if (toolAbortController && toolTimeout) {
126
+ const timeoutMs = typeof toolTimeout === 'string'
127
+ ? parseTimeout(toolTimeout)
128
+ : toolTimeout;
129
+ timeoutId = setTimeout(() => {
130
+ toolAbortController.abort();
131
+ }, timeoutMs);
132
+ }
118
133
  const context = {
119
134
  sessionId: 'cli-session',
120
135
  userId: 'cli-user',
@@ -185,10 +200,33 @@ export class AgentEnhancedProvider {
185
200
  }
186
201
  }
187
202
  };
188
- const result = await this.mcpSystem.executeTool(toolInfo.name, args, context);
203
+ const toolPromise = this.mcpSystem.executeTool(toolInfo.name, args, context);
204
+ let result;
205
+ if (toolAbortController) {
206
+ // Race between tool execution and timeout
207
+ result = await Promise.race([
208
+ toolPromise,
209
+ new Promise((_, reject) => {
210
+ toolAbortController.signal.addEventListener('abort', () => {
211
+ reject(new Error(`Tool ${toolInfo.name} timed out after ${this.config.toolExecutionTimeout}`));
212
+ });
213
+ })
214
+ ]);
215
+ }
216
+ else {
217
+ result = await toolPromise;
218
+ }
219
+ // Clear timeout if successful
220
+ if (timeoutId) {
221
+ clearTimeout(timeoutId);
222
+ }
189
223
  return result.data || result;
190
224
  }
191
225
  catch (error) {
226
+ // Clear timeout on error
227
+ if (timeoutId) {
228
+ clearTimeout(timeoutId);
229
+ }
192
230
  mcpLogger.error(`MCP tool ${toolInfo.name} execution failed:`, error);
193
231
  throw error;
194
232
  }
@@ -206,7 +244,7 @@ export class AgentEnhancedProvider {
206
244
  const options = typeof optionsOrPrompt === "string"
207
245
  ? { prompt: optionsOrPrompt }
208
246
  : optionsOrPrompt;
209
- const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt, schema, } = options;
247
+ const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt, schema, timeout, } = options;
210
248
  // Get combined tools (direct + MCP) if enabled
211
249
  const tools = this.config.enableTools
212
250
  ? await this.getCombinedTools()
@@ -220,6 +258,14 @@ export class AgentEnhancedProvider {
220
258
  maxSteps: this.config.maxSteps
221
259
  });
222
260
  try {
261
+ // Parse timeout if provided
262
+ let abortSignal;
263
+ if (timeout) {
264
+ const timeoutMs = typeof timeout === 'string' ? parseTimeout(timeout) : timeout;
265
+ if (timeoutMs !== undefined) {
266
+ abortSignal = AbortSignal.timeout(timeoutMs);
267
+ }
268
+ }
223
269
  // The AI SDK with maxSteps automatically handles tool calling and result integration
224
270
  const result = await generateText({
225
271
  model: this.model,
@@ -231,6 +277,7 @@ export class AgentEnhancedProvider {
231
277
  temperature,
232
278
  maxTokens,
233
279
  toolChoice: this.shouldForceToolUsage(prompt) ? "required" : "auto",
280
+ abortSignal, // Pass abort signal for timeout support
234
281
  });
235
282
  log('Generation completed', {
236
283
  text: result.text?.substring(0, 200),
@@ -307,12 +354,20 @@ export class AgentEnhancedProvider {
307
354
  const options = typeof optionsOrPrompt === "string"
308
355
  ? { prompt: optionsOrPrompt }
309
356
  : optionsOrPrompt;
310
- const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt, } = options;
357
+ const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt, timeout, } = options;
311
358
  // Get combined tools (direct + MCP) if enabled
312
359
  const tools = this.config.enableTools
313
360
  ? await this.getCombinedTools()
314
361
  : {};
315
362
  try {
363
+ // Parse timeout if provided
364
+ let abortSignal;
365
+ if (timeout) {
366
+ const timeoutMs = typeof timeout === 'string' ? parseTimeout(timeout) : timeout;
367
+ if (timeoutMs !== undefined) {
368
+ abortSignal = AbortSignal.timeout(timeoutMs);
369
+ }
370
+ }
316
371
  const result = await streamText({
317
372
  model: this.model,
318
373
  prompt: systemPrompt
@@ -323,6 +378,7 @@ export class AgentEnhancedProvider {
323
378
  temperature,
324
379
  maxTokens,
325
380
  toolChoice: this.shouldForceToolUsage(prompt) ? "required" : "auto",
381
+ abortSignal, // Pass abort signal for timeout support
326
382
  });
327
383
  return result;
328
384
  }