@juspay/neurolink 2.1.0 → 3.0.1

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 +36 -9
  2. package/README.md +17 -39
  3. package/dist/cli/index.js +40 -18
  4. package/dist/lib/mcp/plugins/filesystem-mcp.d.ts +1 -1
  5. package/dist/lib/neurolink.d.ts +2 -0
  6. package/dist/lib/neurolink.js +5 -3
  7. package/dist/lib/providers/agent-enhanced-provider.js +61 -53
  8. package/dist/lib/providers/amazonBedrock.js +11 -7
  9. package/dist/lib/providers/anthropic.js +13 -11
  10. package/dist/lib/providers/azureOpenAI.js +10 -10
  11. package/dist/lib/providers/googleAIStudio.js +14 -7
  12. package/dist/lib/providers/googleVertexAI.js +14 -7
  13. package/dist/lib/providers/huggingFace.js +11 -7
  14. package/dist/lib/providers/mistralAI.js +11 -7
  15. package/dist/lib/providers/ollama.js +12 -4
  16. package/dist/lib/providers/openAI.js +11 -7
  17. package/dist/lib/providers/timeout-wrapper.d.ts +2 -2
  18. package/dist/lib/providers/timeout-wrapper.js +3 -3
  19. package/dist/lib/proxy/proxy-fetch.d.ts +18 -0
  20. package/dist/lib/proxy/proxy-fetch.js +64 -0
  21. package/dist/lib/utils/timeout.d.ts +4 -4
  22. package/dist/lib/utils/timeout.js +42 -34
  23. package/dist/mcp/plugins/filesystem-mcp.d.ts +1 -1
  24. package/dist/mcp/plugins/filesystem-mcp.js +1 -1
  25. package/dist/neurolink.d.ts +2 -0
  26. package/dist/neurolink.js +5 -3
  27. package/dist/providers/agent-enhanced-provider.js +61 -53
  28. package/dist/providers/amazonBedrock.js +11 -7
  29. package/dist/providers/anthropic.js +13 -11
  30. package/dist/providers/azureOpenAI.js +10 -10
  31. package/dist/providers/googleAIStudio.js +14 -7
  32. package/dist/providers/googleVertexAI.js +14 -7
  33. package/dist/providers/huggingFace.js +11 -7
  34. package/dist/providers/mistralAI.js +11 -7
  35. package/dist/providers/ollama.js +12 -4
  36. package/dist/providers/openAI.js +11 -7
  37. package/dist/providers/timeout-wrapper.d.ts +2 -2
  38. package/dist/providers/timeout-wrapper.js +3 -3
  39. package/dist/proxy/proxy-fetch.d.ts +18 -0
  40. package/dist/proxy/proxy-fetch.js +64 -0
  41. package/dist/utils/timeout.d.ts +4 -4
  42. package/dist/utils/timeout.js +42 -34
  43. package/package.json +2 -1
@@ -66,14 +66,15 @@ export class AgentEnhancedProvider {
66
66
  try {
67
67
  mcpLogger.info("[AgentEnhancedProvider] Initializing MCP integration...");
68
68
  this.mcpSystem = new UnifiedMCPSystem({
69
- configPath: this.config.mcpDiscoveryOptions?.configFiles?.[0] || ".mcp-config.json",
69
+ configPath: this.config.mcpDiscoveryOptions?.configFiles?.[0] ||
70
+ ".mcp-config.json",
70
71
  enableExternalServers: true,
71
72
  enableInternalServers: true,
72
- autoInitialize: false
73
+ autoInitialize: false,
73
74
  });
74
75
  // ADD TIMEOUT to prevent hanging forever
75
76
  const initPromise = this.mcpSystem.initialize();
76
- const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error('MCP initialization timeout after 15 seconds')), this.config.mcpInitTimeoutMs || 15000));
77
+ const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error("MCP initialization timeout after 15 seconds")), this.config.mcpInitTimeoutMs || 15000));
77
78
  await Promise.race([initPromise, timeoutPromise]);
78
79
  this.mcpInitialized = true;
79
80
  mcpLogger.info("[AgentEnhancedProvider] MCP integration initialized successfully");
@@ -101,10 +102,13 @@ export class AgentEnhancedProvider {
101
102
  return directTools;
102
103
  }
103
104
  // Get MCP tools if available
104
- let mcpTools = {};
105
+ const mcpTools = {};
105
106
  try {
106
107
  // Skip if MCP failed to initialize or is still initializing
107
- if (this.mcpInitFailed || this.mcpInitializing || !this.mcpInitialized || !this.mcpSystem) {
108
+ if (this.mcpInitFailed ||
109
+ this.mcpInitializing ||
110
+ !this.mcpInitialized ||
111
+ !this.mcpSystem) {
108
112
  return directTools;
109
113
  }
110
114
  const mcpToolInfos = await this.mcpSystem.listTools();
@@ -123,7 +127,7 @@ export class AgentEnhancedProvider {
123
127
  ? new AbortController()
124
128
  : undefined;
125
129
  if (toolAbortController && toolTimeout) {
126
- const timeoutMs = typeof toolTimeout === 'string'
130
+ const timeoutMs = typeof toolTimeout === "string"
127
131
  ? parseTimeout(toolTimeout)
128
132
  : toolTimeout;
129
133
  timeoutId = setTimeout(() => {
@@ -131,31 +135,35 @@ export class AgentEnhancedProvider {
131
135
  }, timeoutMs);
132
136
  }
133
137
  const context = {
134
- sessionId: 'cli-session',
135
- userId: 'cli-user',
138
+ sessionId: "cli-session",
139
+ userId: "cli-user",
136
140
  secureFS: {
137
141
  readFile: async (path, encoding) => {
138
- const fs = await import('fs/promises');
139
- return encoding ? fs.readFile(path, { encoding: encoding }) : fs.readFile(path);
142
+ const fs = await import("fs/promises");
143
+ return encoding
144
+ ? fs.readFile(path, {
145
+ encoding: encoding,
146
+ })
147
+ : fs.readFile(path);
140
148
  },
141
149
  writeFile: async (path, content) => {
142
- const fs = await import('fs/promises');
150
+ const fs = await import("fs/promises");
143
151
  await fs.writeFile(path, content);
144
152
  },
145
153
  readdir: async (path) => {
146
- const fs = await import('fs/promises');
154
+ const fs = await import("fs/promises");
147
155
  return fs.readdir(path);
148
156
  },
149
157
  stat: async (path) => {
150
- const fs = await import('fs/promises');
158
+ const fs = await import("fs/promises");
151
159
  return fs.stat(path);
152
160
  },
153
161
  mkdir: async (path, options) => {
154
- const fs = await import('fs/promises');
162
+ const fs = await import("fs/promises");
155
163
  await fs.mkdir(path, options);
156
164
  },
157
165
  exists: async (path) => {
158
- const fs = await import('fs/promises');
166
+ const fs = await import("fs/promises");
159
167
  try {
160
168
  await fs.access(path);
161
169
  return true;
@@ -163,34 +171,34 @@ export class AgentEnhancedProvider {
163
171
  catch {
164
172
  return false;
165
173
  }
166
- }
174
+ },
167
175
  },
168
176
  path: {
169
177
  join: (...paths) => {
170
- const path = require('path');
178
+ const path = require("path");
171
179
  return path.join(...paths);
172
180
  },
173
181
  resolve: (...paths) => {
174
- const path = require('path');
182
+ const path = require("path");
175
183
  return path.resolve(...paths);
176
184
  },
177
185
  relative: (from, to) => {
178
- const path = require('path');
186
+ const path = require("path");
179
187
  return path.relative(from, to);
180
188
  },
181
189
  dirname: (path) => {
182
- const pathLib = require('path');
190
+ const pathLib = require("path");
183
191
  return pathLib.dirname(path);
184
192
  },
185
193
  basename: (path, ext) => {
186
- const pathLib = require('path');
194
+ const pathLib = require("path");
187
195
  return pathLib.basename(path, ext);
188
- }
196
+ },
189
197
  },
190
- grantedPermissions: ['read', 'write', 'execute'],
198
+ grantedPermissions: ["read", "write", "execute"],
191
199
  log: (level, message, data) => {
192
200
  const logFn = mcpLogger[level];
193
- if (typeof logFn === 'function') {
201
+ if (typeof logFn === "function") {
194
202
  if (data) {
195
203
  logFn(`${message} ${JSON.stringify(data)}`);
196
204
  }
@@ -198,7 +206,7 @@ export class AgentEnhancedProvider {
198
206
  logFn(message);
199
207
  }
200
208
  }
201
- }
209
+ },
202
210
  };
203
211
  const toolPromise = this.mcpSystem.executeTool(toolInfo.name, args, context);
204
212
  let result;
@@ -207,10 +215,10 @@ export class AgentEnhancedProvider {
207
215
  result = await Promise.race([
208
216
  toolPromise,
209
217
  new Promise((_, reject) => {
210
- toolAbortController.signal.addEventListener('abort', () => {
218
+ toolAbortController.signal.addEventListener("abort", () => {
211
219
  reject(new Error(`Tool ${toolInfo.name} timed out after ${this.config.toolExecutionTimeout}`));
212
220
  });
213
- })
221
+ }),
214
222
  ]);
215
223
  }
216
224
  else {
@@ -230,7 +238,7 @@ export class AgentEnhancedProvider {
230
238
  mcpLogger.error(`MCP tool ${toolInfo.name} execution failed:`, error);
231
239
  throw error;
232
240
  }
233
- }
241
+ },
234
242
  };
235
243
  }
236
244
  mcpLogger.info(`[AgentEnhancedProvider] Loaded ${Object.keys(mcpTools).length} MCP tools`);
@@ -246,22 +254,20 @@ export class AgentEnhancedProvider {
246
254
  : optionsOrPrompt;
247
255
  const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt, schema, timeout, } = options;
248
256
  // Get combined tools (direct + MCP) if enabled
249
- const tools = this.config.enableTools
250
- ? await this.getCombinedTools()
251
- : {};
257
+ const tools = this.config.enableTools ? await this.getCombinedTools() : {};
252
258
  const log = (msg, data) => {
253
- mcpLogger.info(`[AgentEnhancedProvider] ${msg}`, data ? JSON.stringify(data, null, 2) : '');
259
+ mcpLogger.info(`[AgentEnhancedProvider] ${msg}`, data ? JSON.stringify(data, null, 2) : "");
254
260
  };
255
- log('Starting text generation', {
261
+ log("Starting text generation", {
256
262
  prompt: prompt.substring(0, 100),
257
263
  toolsCount: Object.keys(tools).length,
258
- maxSteps: this.config.maxSteps
264
+ maxSteps: this.config.maxSteps,
259
265
  });
260
266
  try {
261
267
  // Parse timeout if provided
262
268
  let abortSignal;
263
269
  if (timeout) {
264
- const timeoutMs = typeof timeout === 'string' ? parseTimeout(timeout) : timeout;
270
+ const timeoutMs = typeof timeout === "string" ? parseTimeout(timeout) : timeout;
265
271
  if (timeoutMs !== undefined) {
266
272
  abortSignal = AbortSignal.timeout(timeoutMs);
267
273
  }
@@ -279,24 +285,26 @@ export class AgentEnhancedProvider {
279
285
  toolChoice: this.shouldForceToolUsage(prompt) ? "required" : "auto",
280
286
  abortSignal, // Pass abort signal for timeout support
281
287
  });
282
- log('Generation completed', {
288
+ log("Generation completed", {
283
289
  text: result.text?.substring(0, 200),
284
290
  finishReason: result.finishReason,
285
291
  toolCallsCount: result.toolCalls?.length || 0,
286
292
  toolResultsCount: result.toolResults?.length || 0,
287
- stepsCount: result.steps?.length || 0
293
+ stepsCount: result.steps?.length || 0,
288
294
  });
289
295
  // Check if tools were called but no final text was generated
290
- if (result.finishReason === 'tool-calls' && !result.text && result.toolResults?.length > 0) {
291
- log('Tools called but no final text generated, creating summary response');
296
+ if (result.finishReason === "tool-calls" &&
297
+ !result.text &&
298
+ result.toolResults?.length > 0) {
299
+ log("Tools called but no final text generated, creating summary response");
292
300
  try {
293
301
  // Extract tool results and create a summary prompt
294
- let toolResultsSummary = '';
302
+ let toolResultsSummary = "";
295
303
  if (result.toolResults) {
296
304
  for (const toolResult of result.toolResults) {
297
305
  const resultData = toolResult.result || toolResult;
298
306
  // Try to extract meaningful data from the result
299
- if (typeof resultData === 'object' && resultData !== null) {
307
+ if (typeof resultData === "object" && resultData !== null) {
300
308
  if (resultData.success && resultData.items) {
301
309
  // This looks like a filesystem listing
302
310
  toolResultsSummary += `Directory listing for ${resultData.path}:\n`;
@@ -311,34 +319,36 @@ export class AgentEnhancedProvider {
311
319
  else {
312
320
  toolResultsSummary += String(resultData);
313
321
  }
314
- toolResultsSummary += '\n\n';
322
+ toolResultsSummary += "\n\n";
315
323
  }
316
324
  }
317
- log('Tool results extracted', {
325
+ log("Tool results extracted", {
318
326
  summaryLength: toolResultsSummary.length,
319
- preview: toolResultsSummary.substring(0, 200)
327
+ preview: toolResultsSummary.substring(0, 200),
320
328
  });
321
329
  // Create a simple, direct summary
322
330
  const finalText = `Based on the user request "${prompt}", here's what I found:\n\n${toolResultsSummary}`;
323
- log('Final text created', {
331
+ log("Final text created", {
324
332
  textLength: finalText.length,
325
- preview: finalText.substring(0, 200)
333
+ preview: finalText.substring(0, 200),
326
334
  });
327
335
  // Return result with the formatted text
328
336
  return {
329
337
  ...result,
330
338
  text: finalText,
331
- finishReason: 'stop'
339
+ finishReason: "stop",
332
340
  };
333
341
  }
334
342
  catch (error) {
335
- log('Error in summary generation', { error: error instanceof Error ? error.message : String(error) });
343
+ log("Error in summary generation", {
344
+ error: error instanceof Error ? error.message : String(error),
345
+ });
336
346
  // Fallback: return raw tool results
337
347
  const fallbackText = `Tool execution completed. Raw results: ${JSON.stringify(result.toolResults, null, 2)}`;
338
348
  return {
339
349
  ...result,
340
350
  text: fallbackText,
341
- finishReason: 'stop'
351
+ finishReason: "stop",
342
352
  };
343
353
  }
344
354
  }
@@ -356,14 +366,12 @@ export class AgentEnhancedProvider {
356
366
  : optionsOrPrompt;
357
367
  const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt, timeout, } = options;
358
368
  // Get combined tools (direct + MCP) if enabled
359
- const tools = this.config.enableTools
360
- ? await this.getCombinedTools()
361
- : {};
369
+ const tools = this.config.enableTools ? await this.getCombinedTools() : {};
362
370
  try {
363
371
  // Parse timeout if provided
364
372
  let abortSignal;
365
373
  if (timeout) {
366
- const timeoutMs = typeof timeout === 'string' ? parseTimeout(timeout) : timeout;
374
+ const timeoutMs = typeof timeout === "string" ? parseTimeout(timeout) : timeout;
367
375
  if (timeoutMs !== undefined) {
368
376
  abortSignal = AbortSignal.timeout(timeoutMs);
369
377
  }
@@ -1,7 +1,7 @@
1
1
  import { createAmazonBedrock } from "@ai-sdk/amazon-bedrock";
2
2
  import { streamText, generateText, Output, } from "ai";
3
3
  import { logger } from "../utils/logger.js";
4
- import { createTimeoutController, TimeoutError, getDefaultTimeout } from "../utils/timeout.js";
4
+ import { createTimeoutController, TimeoutError, getDefaultTimeout, } from "../utils/timeout.js";
5
5
  // Default system context
6
6
  const DEFAULT_SYSTEM_CONTEXT = {
7
7
  systemPrompt: "You are a helpful AI assistant.",
@@ -129,7 +129,7 @@ export class AmazonBedrock {
129
129
  const options = typeof optionsOrPrompt === "string"
130
130
  ? { prompt: optionsOrPrompt }
131
131
  : optionsOrPrompt;
132
- const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt = DEFAULT_SYSTEM_CONTEXT.systemPrompt, schema, timeout = getDefaultTimeout(provider, 'stream'), } = options;
132
+ const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt = DEFAULT_SYSTEM_CONTEXT.systemPrompt, schema, timeout = getDefaultTimeout(provider, "stream"), } = options;
133
133
  // Use schema from options or fallback parameter
134
134
  const finalSchema = schema || analysisSchema;
135
135
  logger.debug(`[${functionTag}] Stream request started`, {
@@ -141,7 +141,7 @@ export class AmazonBedrock {
141
141
  timeout,
142
142
  });
143
143
  // Create timeout controller if timeout is specified
144
- const timeoutController = createTimeoutController(timeout, provider, 'stream');
144
+ const timeoutController = createTimeoutController(timeout, provider, "stream");
145
145
  const streamOptions = {
146
146
  model: this.model,
147
147
  prompt: prompt,
@@ -149,7 +149,9 @@ export class AmazonBedrock {
149
149
  temperature,
150
150
  maxTokens,
151
151
  // Add abort signal if available
152
- ...(timeoutController && { abortSignal: timeoutController.controller.signal }),
152
+ ...(timeoutController && {
153
+ abortSignal: timeoutController.controller.signal,
154
+ }),
153
155
  onError: (event) => {
154
156
  const error = event.error;
155
157
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -234,7 +236,7 @@ export class AmazonBedrock {
234
236
  const options = typeof optionsOrPrompt === "string"
235
237
  ? { prompt: optionsOrPrompt }
236
238
  : optionsOrPrompt;
237
- const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt = DEFAULT_SYSTEM_CONTEXT.systemPrompt, schema, timeout = getDefaultTimeout(provider, 'generate'), } = options;
239
+ const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt = DEFAULT_SYSTEM_CONTEXT.systemPrompt, schema, timeout = getDefaultTimeout(provider, "generate"), } = options;
238
240
  // Use schema from options or fallback parameter
239
241
  const finalSchema = schema || analysisSchema;
240
242
  logger.debug(`[${functionTag}] Generate text started`, {
@@ -247,7 +249,7 @@ export class AmazonBedrock {
247
249
  timeout,
248
250
  });
249
251
  // Create timeout controller if timeout is specified
250
- const timeoutController = createTimeoutController(timeout, provider, 'generate');
252
+ const timeoutController = createTimeoutController(timeout, provider, "generate");
251
253
  const generateOptions = {
252
254
  model: this.model,
253
255
  prompt: prompt,
@@ -255,7 +257,9 @@ export class AmazonBedrock {
255
257
  temperature,
256
258
  maxTokens,
257
259
  // Add abort signal if available
258
- ...(timeoutController && { abortSignal: timeoutController.controller.signal }),
260
+ ...(timeoutController && {
261
+ abortSignal: timeoutController.controller.signal,
262
+ }),
259
263
  };
260
264
  if (finalSchema) {
261
265
  generateOptions.experimental_output = Output.object({
@@ -6,7 +6,8 @@
6
6
  */
7
7
  import { AIProviderName } from "../core/types.js";
8
8
  import { logger } from "../utils/logger.js";
9
- import { createTimeoutController, TimeoutError, getDefaultTimeout } from "../utils/timeout.js";
9
+ import { createTimeoutController, TimeoutError, getDefaultTimeout, } from "../utils/timeout.js";
10
+ import { createProxyFetch } from "../proxy/proxy-fetch.js";
10
11
  export class AnthropicProvider {
11
12
  name = AIProviderName.ANTHROPIC;
12
13
  apiKey;
@@ -40,7 +41,8 @@ export class AnthropicProvider {
40
41
  };
41
42
  logger.debug(`[AnthropicProvider.makeRequest] ${stream ? "Streaming" : "Non-streaming"} request to ${url}`);
42
43
  logger.debug(`[AnthropicProvider.makeRequest] Model: ${body.model}, Max tokens: ${body.max_tokens}`);
43
- const response = await fetch(url, {
44
+ const proxyFetch = createProxyFetch();
45
+ const response = await proxyFetch(url, {
44
46
  method: "POST",
45
47
  headers,
46
48
  body: JSON.stringify(body),
@@ -61,7 +63,7 @@ export class AnthropicProvider {
61
63
  const options = typeof optionsOrPrompt === "string"
62
64
  ? { prompt: optionsOrPrompt }
63
65
  : optionsOrPrompt;
64
- const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt = "You are Claude, an AI assistant created by Anthropic. You are helpful, harmless, and honest.", timeout = getDefaultTimeout(provider, 'generate'), } = options;
66
+ const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt = "You are Claude, an AI assistant created by Anthropic. You are helpful, harmless, and honest.", timeout = getDefaultTimeout(provider, "generate"), } = options;
65
67
  logger.debug(`[${functionTag}] Prompt: "${prompt.substring(0, 100)}...", Temperature: ${temperature}, Max tokens: ${maxTokens}, Timeout: ${timeout}`);
66
68
  const requestBody = {
67
69
  model: this.getModel(),
@@ -76,7 +78,7 @@ export class AnthropicProvider {
76
78
  system: systemPrompt,
77
79
  };
78
80
  // Create timeout controller if timeout is specified
79
- const timeoutController = createTimeoutController(timeout, provider, 'generate');
81
+ const timeoutController = createTimeoutController(timeout, provider, "generate");
80
82
  try {
81
83
  const response = await this.makeRequest("messages", requestBody, false, timeoutController?.controller.signal);
82
84
  const data = await response.json();
@@ -107,9 +109,9 @@ export class AnthropicProvider {
107
109
  message: error.message,
108
110
  });
109
111
  }
110
- else if (error?.name === 'AbortError') {
112
+ else if (error?.name === "AbortError") {
111
113
  // Convert AbortError to TimeoutError
112
- const timeoutError = new TimeoutError(`${provider} generate operation timed out after ${timeout}`, timeoutController?.timeoutMs || 0, provider, 'generate');
114
+ const timeoutError = new TimeoutError(`${provider} generate operation timed out after ${timeout}`, timeoutController?.timeoutMs || 0, provider, "generate");
113
115
  logger.error(`[${functionTag}] Timeout error`, {
114
116
  provider,
115
117
  timeout: timeoutController?.timeoutMs,
@@ -131,7 +133,7 @@ export class AnthropicProvider {
131
133
  const options = typeof optionsOrPrompt === "string"
132
134
  ? { prompt: optionsOrPrompt }
133
135
  : optionsOrPrompt;
134
- const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt = "You are Claude, an AI assistant created by Anthropic. You are helpful, harmless, and honest.", timeout = getDefaultTimeout(provider, 'stream'), } = options;
136
+ const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt = "You are Claude, an AI assistant created by Anthropic. You are helpful, harmless, and honest.", timeout = getDefaultTimeout(provider, "stream"), } = options;
135
137
  logger.debug(`[${functionTag}] Streaming prompt: "${prompt.substring(0, 100)}...", Timeout: ${timeout}`);
136
138
  const requestBody = {
137
139
  model: this.getModel(),
@@ -147,7 +149,7 @@ export class AnthropicProvider {
147
149
  stream: true,
148
150
  };
149
151
  // Create timeout controller if timeout is specified
150
- const timeoutController = createTimeoutController(timeout, provider, 'stream');
152
+ const timeoutController = createTimeoutController(timeout, provider, "stream");
151
153
  try {
152
154
  const response = await this.makeRequest("messages", requestBody, true, timeoutController?.controller.signal);
153
155
  if (!response.body) {
@@ -174,9 +176,9 @@ export class AnthropicProvider {
174
176
  message: error.message,
175
177
  });
176
178
  }
177
- else if (error?.name === 'AbortError') {
179
+ else if (error?.name === "AbortError") {
178
180
  // Convert AbortError to TimeoutError
179
- const timeoutError = new TimeoutError(`${provider} stream operation timed out after ${timeout}`, timeoutController?.timeoutMs || 0, provider, 'stream');
181
+ const timeoutError = new TimeoutError(`${provider} stream operation timed out after ${timeout}`, timeoutController?.timeoutMs || 0, provider, "stream");
180
182
  logger.error(`[${functionTag}] Timeout error`, {
181
183
  provider,
182
184
  timeout: timeoutController?.timeoutMs,
@@ -198,7 +200,7 @@ export class AnthropicProvider {
198
200
  while (true) {
199
201
  // Check if aborted
200
202
  if (signal?.aborted) {
201
- throw new Error('AbortError');
203
+ throw new Error("AbortError");
202
204
  }
203
205
  const { done, value } = await reader.read();
204
206
  if (done) {
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import { AIProviderName } from "../core/types.js";
8
8
  import { logger } from "../utils/logger.js";
9
- import { createTimeoutController, TimeoutError, getDefaultTimeout } from "../utils/timeout.js";
9
+ import { createTimeoutController, TimeoutError, getDefaultTimeout, } from "../utils/timeout.js";
10
10
  export class AzureOpenAIProvider {
11
11
  name = AIProviderName.AZURE;
12
12
  apiKey;
@@ -74,7 +74,7 @@ export class AzureOpenAIProvider {
74
74
  const options = typeof optionsOrPrompt === "string"
75
75
  ? { prompt: optionsOrPrompt }
76
76
  : optionsOrPrompt;
77
- const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt = "You are a helpful AI assistant.", timeout = getDefaultTimeout(provider, 'generate'), } = options;
77
+ const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt = "You are a helpful AI assistant.", timeout = getDefaultTimeout(provider, "generate"), } = options;
78
78
  logger.debug(`[${functionTag}] Prompt: "${prompt.substring(0, 100)}...", Temperature: ${temperature}, Max tokens: ${maxTokens}, Timeout: ${timeout}`);
79
79
  const messages = [];
80
80
  if (systemPrompt) {
@@ -93,7 +93,7 @@ export class AzureOpenAIProvider {
93
93
  max_tokens: maxTokens,
94
94
  };
95
95
  // Create timeout controller if timeout is specified
96
- const timeoutController = createTimeoutController(timeout, provider, 'generate');
96
+ const timeoutController = createTimeoutController(timeout, provider, "generate");
97
97
  try {
98
98
  const response = await this.makeRequest(requestBody, false, timeoutController?.controller.signal);
99
99
  const data = await response.json();
@@ -124,9 +124,9 @@ export class AzureOpenAIProvider {
124
124
  message: error.message,
125
125
  });
126
126
  }
127
- else if (error?.name === 'AbortError') {
127
+ else if (error?.name === "AbortError") {
128
128
  // Convert AbortError to TimeoutError
129
- const timeoutError = new TimeoutError(`${provider} generate operation timed out after ${timeout}`, timeoutController?.timeoutMs || 0, provider, 'generate');
129
+ const timeoutError = new TimeoutError(`${provider} generate operation timed out after ${timeout}`, timeoutController?.timeoutMs || 0, provider, "generate");
130
130
  logger.error(`[${functionTag}] Timeout error`, {
131
131
  provider,
132
132
  timeout: timeoutController?.timeoutMs,
@@ -148,7 +148,7 @@ export class AzureOpenAIProvider {
148
148
  const options = typeof optionsOrPrompt === "string"
149
149
  ? { prompt: optionsOrPrompt }
150
150
  : optionsOrPrompt;
151
- const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt = "You are a helpful AI assistant.", timeout = getDefaultTimeout(provider, 'stream'), } = options;
151
+ const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt = "You are a helpful AI assistant.", timeout = getDefaultTimeout(provider, "stream"), } = options;
152
152
  logger.debug(`[${functionTag}] Streaming prompt: "${prompt.substring(0, 100)}...", Timeout: ${timeout}`);
153
153
  const messages = [];
154
154
  if (systemPrompt) {
@@ -168,7 +168,7 @@ export class AzureOpenAIProvider {
168
168
  stream: true,
169
169
  };
170
170
  // Create timeout controller if timeout is specified
171
- const timeoutController = createTimeoutController(timeout, provider, 'stream');
171
+ const timeoutController = createTimeoutController(timeout, provider, "stream");
172
172
  try {
173
173
  const response = await this.makeRequest(requestBody, true, timeoutController?.controller.signal);
174
174
  if (!response.body) {
@@ -195,9 +195,9 @@ export class AzureOpenAIProvider {
195
195
  message: error.message,
196
196
  });
197
197
  }
198
- else if (error?.name === 'AbortError') {
198
+ else if (error?.name === "AbortError") {
199
199
  // Convert AbortError to TimeoutError
200
- const timeoutError = new TimeoutError(`${provider} stream operation timed out after ${timeout}`, timeoutController?.timeoutMs || 0, provider, 'stream');
200
+ const timeoutError = new TimeoutError(`${provider} stream operation timed out after ${timeout}`, timeoutController?.timeoutMs || 0, provider, "stream");
201
201
  logger.error(`[${functionTag}] Timeout error`, {
202
202
  provider,
203
203
  timeout: timeoutController?.timeoutMs,
@@ -219,7 +219,7 @@ export class AzureOpenAIProvider {
219
219
  while (true) {
220
220
  // Check if aborted
221
221
  if (signal?.aborted) {
222
- throw new Error('AbortError');
222
+ throw new Error("AbortError");
223
223
  }
224
224
  const { done, value } = await reader.read();
225
225
  if (done) {
@@ -1,7 +1,8 @@
1
1
  import { createGoogleGenerativeAI } from "@ai-sdk/google";
2
2
  import { streamText, generateText, Output, } from "ai";
3
3
  import { logger } from "../utils/logger.js";
4
- import { createTimeoutController, TimeoutError, getDefaultTimeout } from "../utils/timeout.js";
4
+ import { createTimeoutController, TimeoutError, getDefaultTimeout, } from "../utils/timeout.js";
5
+ import { createProxyFetch } from "../proxy/proxy-fetch.js";
5
6
  // CRITICAL: Setup environment variables early for AI SDK compatibility
6
7
  // The AI SDK specifically looks for GOOGLE_GENERATIVE_AI_API_KEY
7
8
  // We need to ensure this is set before any AI SDK operations
@@ -39,8 +40,10 @@ let _google = null;
39
40
  function getGoogleInstance() {
40
41
  if (!_google) {
41
42
  const apiKey = getGoogleAIApiKey();
43
+ const proxyFetch = createProxyFetch();
42
44
  _google = createGoogleGenerativeAI({
43
45
  apiKey: apiKey,
46
+ fetch: proxyFetch,
44
47
  headers: {
45
48
  "X-Powered-By": "NeuroLink",
46
49
  },
@@ -110,7 +113,7 @@ export class GoogleAIStudio {
110
113
  const options = typeof optionsOrPrompt === "string"
111
114
  ? { prompt: optionsOrPrompt }
112
115
  : optionsOrPrompt;
113
- const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt = DEFAULT_SYSTEM_CONTEXT.systemPrompt, schema, tools, timeout = getDefaultTimeout(provider, 'stream'), } = options;
116
+ const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt = DEFAULT_SYSTEM_CONTEXT.systemPrompt, schema, tools, timeout = getDefaultTimeout(provider, "stream"), } = options;
114
117
  // Use schema from options or fallback parameter
115
118
  const finalSchema = schema || analysisSchema;
116
119
  logger.debug(`[${functionTag}] Stream request started`, {
@@ -126,7 +129,7 @@ export class GoogleAIStudio {
126
129
  });
127
130
  const model = this.getModel();
128
131
  // Create timeout controller if timeout is specified
129
- const timeoutController = createTimeoutController(timeout, provider, 'stream');
132
+ const timeoutController = createTimeoutController(timeout, provider, "stream");
130
133
  const streamOptions = {
131
134
  model: model,
132
135
  prompt: prompt,
@@ -135,7 +138,9 @@ export class GoogleAIStudio {
135
138
  maxTokens,
136
139
  ...(tools && { tools }), // Add tools if provided
137
140
  // Add abort signal if available
138
- ...(timeoutController && { abortSignal: timeoutController.controller.signal }),
141
+ ...(timeoutController && {
142
+ abortSignal: timeoutController.controller.signal,
143
+ }),
139
144
  onError: (event) => {
140
145
  const error = event.error;
141
146
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -219,7 +224,7 @@ export class GoogleAIStudio {
219
224
  const options = typeof optionsOrPrompt === "string"
220
225
  ? { prompt: optionsOrPrompt }
221
226
  : optionsOrPrompt;
222
- const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt = DEFAULT_SYSTEM_CONTEXT.systemPrompt, schema, tools, timeout = getDefaultTimeout(provider, 'generate'), } = options;
227
+ const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt = DEFAULT_SYSTEM_CONTEXT.systemPrompt, schema, tools, timeout = getDefaultTimeout(provider, "generate"), } = options;
223
228
  // Use schema from options or fallback parameter
224
229
  const finalSchema = schema || analysisSchema;
225
230
  logger.debug(`[${functionTag}] Generate request started`, {
@@ -234,7 +239,7 @@ export class GoogleAIStudio {
234
239
  });
235
240
  const model = this.getModel();
236
241
  // Create timeout controller if timeout is specified
237
- const timeoutController = createTimeoutController(timeout, provider, 'generate');
242
+ const timeoutController = createTimeoutController(timeout, provider, "generate");
238
243
  const generateOptions = {
239
244
  model: model,
240
245
  prompt: prompt,
@@ -246,7 +251,9 @@ export class GoogleAIStudio {
246
251
  maxSteps: 5, // Allow multiple steps for tool execution and response generation
247
252
  }), // Add tools if provided
248
253
  // Add abort signal if available
249
- ...(timeoutController && { abortSignal: timeoutController.controller.signal }),
254
+ ...(timeoutController && {
255
+ abortSignal: timeoutController.controller.signal,
256
+ }),
250
257
  };
251
258
  if (finalSchema) {
252
259
  generateOptions.experimental_output = Output.object({