@juspay/neurolink 7.14.2 → 7.14.3

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 (99) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/cli/commands/config.d.ts +66 -66
  3. package/dist/core/baseProvider.d.ts +12 -7
  4. package/dist/core/baseProvider.js +118 -125
  5. package/dist/core/constants.d.ts +5 -0
  6. package/dist/core/constants.js +6 -0
  7. package/dist/core/dynamicModels.d.ts +4 -4
  8. package/dist/core/factory.d.ts +2 -4
  9. package/dist/core/types.d.ts +8 -22
  10. package/dist/index.d.ts +1 -4
  11. package/dist/lib/core/baseProvider.d.ts +12 -7
  12. package/dist/lib/core/baseProvider.js +118 -125
  13. package/dist/lib/core/constants.d.ts +5 -0
  14. package/dist/lib/core/constants.js +6 -0
  15. package/dist/lib/core/dynamicModels.d.ts +8 -8
  16. package/dist/lib/core/factory.d.ts +2 -4
  17. package/dist/lib/core/types.d.ts +8 -22
  18. package/dist/lib/index.d.ts +1 -4
  19. package/dist/lib/mcp/contracts/mcpContract.d.ts +6 -19
  20. package/dist/lib/mcp/externalServerManager.d.ts +2 -4
  21. package/dist/lib/mcp/externalServerManager.js +7 -8
  22. package/dist/lib/mcp/factory.d.ts +61 -7
  23. package/dist/lib/mcp/factory.js +36 -23
  24. package/dist/lib/mcp/mcpClientFactory.d.ts +2 -1
  25. package/dist/lib/mcp/mcpClientFactory.js +73 -26
  26. package/dist/lib/mcp/registry.d.ts +1 -1
  27. package/dist/lib/mcp/toolDiscoveryService.d.ts +1 -1
  28. package/dist/lib/mcp/toolDiscoveryService.js +50 -19
  29. package/dist/lib/mcp/toolRegistry.d.ts +23 -1
  30. package/dist/lib/mcp/toolRegistry.js +108 -17
  31. package/dist/lib/models/modelResolver.js +2 -1
  32. package/dist/lib/neurolink.d.ts +12 -8
  33. package/dist/lib/neurolink.js +130 -134
  34. package/dist/lib/providers/amazonBedrock.d.ts +2 -2
  35. package/dist/lib/providers/anthropic.d.ts +3 -3
  36. package/dist/lib/providers/googleAiStudio.d.ts +2 -2
  37. package/dist/lib/providers/mistral.d.ts +3 -3
  38. package/dist/lib/providers/ollama.d.ts +2 -2
  39. package/dist/lib/providers/openAI.d.ts +3 -3
  40. package/dist/lib/providers/openaiCompatible.d.ts +2 -2
  41. package/dist/lib/providers/sagemaker/client.d.ts +2 -5
  42. package/dist/lib/providers/sagemaker/language-model.d.ts +4 -6
  43. package/dist/lib/providers/sagemaker/parsers.js +5 -4
  44. package/dist/lib/sdk/toolRegistration.d.ts +6 -6
  45. package/dist/lib/sdk/toolRegistration.js +17 -56
  46. package/dist/lib/types/generateTypes.d.ts +9 -9
  47. package/dist/lib/types/streamTypes.d.ts +4 -4
  48. package/dist/lib/types/tools.d.ts +15 -7
  49. package/dist/lib/types/typeAliases.d.ts +412 -0
  50. package/dist/lib/types/typeAliases.js +48 -0
  51. package/dist/lib/utils/factoryProcessing.d.ts +2 -1
  52. package/dist/lib/utils/factoryProcessing.js +4 -3
  53. package/dist/lib/utils/parameterValidation.d.ts +97 -0
  54. package/dist/lib/utils/parameterValidation.js +452 -0
  55. package/dist/lib/utils/transformationUtils.d.ts +204 -0
  56. package/dist/lib/utils/transformationUtils.js +334 -0
  57. package/dist/lib/utils/typeUtils.d.ts +77 -0
  58. package/dist/lib/utils/typeUtils.js +97 -0
  59. package/dist/mcp/contracts/mcpContract.d.ts +6 -19
  60. package/dist/mcp/externalServerManager.d.ts +2 -4
  61. package/dist/mcp/externalServerManager.js +7 -8
  62. package/dist/mcp/factory.d.ts +61 -7
  63. package/dist/mcp/factory.js +36 -23
  64. package/dist/mcp/mcpClientFactory.d.ts +2 -1
  65. package/dist/mcp/mcpClientFactory.js +73 -26
  66. package/dist/mcp/registry.d.ts +1 -1
  67. package/dist/mcp/toolDiscoveryService.d.ts +1 -1
  68. package/dist/mcp/toolDiscoveryService.js +50 -19
  69. package/dist/mcp/toolRegistry.d.ts +23 -1
  70. package/dist/mcp/toolRegistry.js +108 -17
  71. package/dist/models/modelResolver.js +2 -1
  72. package/dist/neurolink.d.ts +12 -8
  73. package/dist/neurolink.js +130 -134
  74. package/dist/providers/amazonBedrock.d.ts +2 -2
  75. package/dist/providers/anthropic.d.ts +3 -3
  76. package/dist/providers/googleAiStudio.d.ts +2 -2
  77. package/dist/providers/mistral.d.ts +3 -3
  78. package/dist/providers/ollama.d.ts +2 -2
  79. package/dist/providers/openAI.d.ts +3 -3
  80. package/dist/providers/openaiCompatible.d.ts +2 -2
  81. package/dist/providers/sagemaker/client.d.ts +2 -5
  82. package/dist/providers/sagemaker/language-model.d.ts +4 -6
  83. package/dist/providers/sagemaker/parsers.js +5 -4
  84. package/dist/sdk/toolRegistration.d.ts +6 -6
  85. package/dist/sdk/toolRegistration.js +17 -56
  86. package/dist/types/generateTypes.d.ts +9 -9
  87. package/dist/types/streamTypes.d.ts +4 -4
  88. package/dist/types/tools.d.ts +15 -7
  89. package/dist/types/typeAliases.d.ts +412 -0
  90. package/dist/types/typeAliases.js +48 -0
  91. package/dist/utils/factoryProcessing.d.ts +2 -1
  92. package/dist/utils/factoryProcessing.js +4 -3
  93. package/dist/utils/parameterValidation.d.ts +97 -0
  94. package/dist/utils/parameterValidation.js +452 -0
  95. package/dist/utils/transformationUtils.d.ts +204 -0
  96. package/dist/utils/transformationUtils.js +334 -0
  97. package/dist/utils/typeUtils.d.ts +77 -0
  98. package/dist/utils/typeUtils.js +97 -0
  99. package/package.json +1 -1
@@ -183,7 +183,29 @@ export class MCPToolRegistry extends MCPRegistry {
183
183
  }
184
184
  }
185
185
  /**
186
- * Execute a tool with enhanced context
186
+ * Execute a tool with enhanced context and automatic result wrapping
187
+ *
188
+ * This method handles both raw return values and ToolResult objects:
189
+ * - Raw values (primitives, objects) are automatically wrapped in ToolResult format
190
+ * - Existing ToolResult objects are enhanced with execution metadata
191
+ * - All results include execution timing and context information
192
+ *
193
+ * @param toolName - Name of the tool to execute
194
+ * @param args - Parameters to pass to the tool execution function
195
+ * @param context - Execution context with session, user, and environment info
196
+ * @returns Promise resolving to ToolResult object with data, metadata, and usage info
197
+ * @throws Error if tool is not found or execution fails
198
+ *
199
+ * @example
200
+ * ```typescript
201
+ * // Tool that returns raw value
202
+ * const result = await toolRegistry.executeTool("calculator", { a: 5, b: 3, op: "add" });
203
+ * // result.data === 8, result.metadata contains execution info
204
+ *
205
+ * // Tool that returns ToolResult
206
+ * const result = await toolRegistry.executeTool("complexTool", { input: "test" });
207
+ * // result is enhanced ToolResult with additional metadata
208
+ * ```
187
209
  */
188
210
  async executeTool(toolName, args, context) {
189
211
  const startTime = Date.now();
@@ -221,22 +243,46 @@ export class MCPToolRegistry extends MCPRegistry {
221
243
  // Execute the actual tool
222
244
  registryLogger.debug(`Executing tool '${toolName}' with args:`, args);
223
245
  const toolResult = await toolImpl.execute(args, execContext);
224
- // Add metadata to the tool result (don't double-wrap)
225
- const toolResultObj = toolResult;
226
- const result = {
227
- ...toolResultObj,
228
- usage: {
229
- ...(toolResultObj.usage || {}),
230
- executionTime: Date.now() - startTime,
231
- },
232
- metadata: {
233
- ...(toolResultObj.metadata || {}),
234
- toolName,
235
- serverId: tool.serverId,
236
- sessionId: execContext.sessionId,
237
- executionTime: Date.now() - startTime,
238
- },
239
- };
246
+ // Properly wrap raw results in ToolResult format
247
+ let result;
248
+ // Check if result is already a ToolResult object
249
+ if (toolResult &&
250
+ typeof toolResult === "object" &&
251
+ "success" in toolResult &&
252
+ typeof toolResult.success === "boolean") {
253
+ // Result is already a ToolResult, enhance with metadata
254
+ const toolResultObj = toolResult;
255
+ result = {
256
+ ...toolResultObj,
257
+ usage: {
258
+ ...(toolResultObj.usage || {}),
259
+ executionTime: Date.now() - startTime,
260
+ },
261
+ metadata: {
262
+ ...(toolResultObj.metadata || {}),
263
+ toolName,
264
+ serverId: tool.serverId,
265
+ sessionId: execContext.sessionId,
266
+ executionTime: Date.now() - startTime,
267
+ },
268
+ };
269
+ }
270
+ else {
271
+ // Result is a raw value, wrap it in ToolResult format
272
+ result = {
273
+ success: true,
274
+ data: toolResult,
275
+ usage: {
276
+ executionTime: Date.now() - startTime,
277
+ },
278
+ metadata: {
279
+ toolName,
280
+ serverId: tool.serverId,
281
+ sessionId: execContext.sessionId,
282
+ executionTime: Date.now() - startTime,
283
+ },
284
+ };
285
+ }
240
286
  // Update statistics
241
287
  const duration = Date.now() - startTime;
242
288
  this.updateStats(toolName, duration);
@@ -406,6 +452,51 @@ export class MCPToolRegistry extends MCPRegistry {
406
452
  */
407
453
  registerTool(toolId, toolInfo, toolImpl) {
408
454
  registryLogger.debug(`Registering tool: ${toolId}`);
455
+ // Import validation functions synchronously - they are pure functions
456
+ let validateTool;
457
+ let isToolNameAvailable;
458
+ let suggestToolNames;
459
+ try {
460
+ // Try ES module import first
461
+ const toolRegistrationModule = require("../sdk/toolRegistration.js");
462
+ ({ validateTool, isToolNameAvailable, suggestToolNames } =
463
+ toolRegistrationModule);
464
+ }
465
+ catch (error) {
466
+ // Fallback: skip validation if import fails (graceful degradation)
467
+ registryLogger.warn("Tool validation module not available, skipping advanced validation", {
468
+ error: error instanceof Error ? error.message : String(error),
469
+ });
470
+ // Create minimal validation functions
471
+ validateTool = () => { }; // No-op
472
+ isToolNameAvailable = () => true; // Allow all names
473
+ suggestToolNames = () => ["alternative_tool"];
474
+ }
475
+ // Check if tool name is available (not reserved)
476
+ if (!isToolNameAvailable(toolId)) {
477
+ const suggestions = suggestToolNames(toolId);
478
+ registryLogger.error(`Tool registration failed for ${toolId}: Name not available`);
479
+ throw new Error(`Tool name '${toolId}' is not available (reserved or invalid format). ` +
480
+ `Suggested alternatives: ${suggestions.slice(0, 3).join(", ")}`);
481
+ }
482
+ // Create a simplified tool object for validation
483
+ const toolForValidation = {
484
+ description: toolInfo.description || "",
485
+ execute: async () => "",
486
+ parameters: undefined,
487
+ metadata: {
488
+ category: toolInfo.category,
489
+ serverId: toolInfo.serverId,
490
+ },
491
+ };
492
+ // Use comprehensive validation logic
493
+ try {
494
+ validateTool(toolId, toolForValidation);
495
+ }
496
+ catch (error) {
497
+ registryLogger.error(`Tool registration failed for ${toolId}:`, error instanceof Error ? error.message : String(error));
498
+ throw error;
499
+ }
409
500
  this.tools.set(toolId, toolInfo);
410
501
  this.toolImpls.set(toolId, toolImpl);
411
502
  registryLogger.debug(`Successfully registered tool: ${toolId}`);
@@ -4,6 +4,7 @@
4
4
  * Part of Phase 4.1 - Models Command System
5
5
  */
6
6
  import { MODEL_REGISTRY, MODEL_ALIASES, USE_CASE_RECOMMENDATIONS, getAllModels, getModelById, getModelsByProvider, getAvailableProviders, calculateCost, formatModelForDisplay, } from "./modelRegistry.js";
7
+ import { isNonNullObject } from "../utils/typeUtils.js";
7
8
  /**
8
9
  * Model resolver class with advanced search and recommendation functionality
9
10
  */
@@ -419,7 +420,7 @@ export function formatSearchResults(results) {
419
420
  return results.map((result) => {
420
421
  const modelDisplay = formatModelForDisplay(result.model);
421
422
  return {
422
- ...(typeof modelDisplay === "object" && modelDisplay !== null
423
+ ...(isNonNullObject(modelDisplay)
423
424
  ? modelDisplay
424
425
  : {}),
425
426
  relevanceScore: result.score,
@@ -9,6 +9,8 @@ import type { TextGenerationOptions, TextGenerationResult } from "./core/types.j
9
9
  import type { GenerateOptions, GenerateResult } from "./types/generateTypes.js";
10
10
  import type { StreamOptions, StreamResult } from "./types/streamTypes.js";
11
11
  import type { MCPServerInfo, MCPExecutableTool } from "./types/mcpTypes.js";
12
+ import type { JsonObject } from "./types/common.js";
13
+ import type { BatchOperationResult } from "./types/typeAliases.js";
12
14
  import { EventEmitter } from "events";
13
15
  import type { ConversationMemoryConfig } from "./types/conversationTypes.js";
14
16
  import type { ExternalMCPServerInstance, ExternalMCPOperationResult, ExternalMCPToolInfo } from "./types/externalMcp.js";
@@ -207,7 +209,13 @@ export declare class NeuroLink {
207
209
  * Get all available tools including custom and in-memory ones
208
210
  * @returns Array of available tools with metadata
209
211
  */
210
- getAllAvailableTools(): Promise<any[]>;
212
+ getAllAvailableTools(): Promise<{
213
+ name: string;
214
+ description: string;
215
+ server: string;
216
+ category?: string;
217
+ inputSchema?: import("./types/typeAliases.js").StandardRecord;
218
+ }[]>;
211
219
  /**
212
220
  * Get comprehensive status of all AI providers
213
221
  * Primary method for provider health checking and diagnostics
@@ -435,9 +443,9 @@ export declare class NeuroLink {
435
443
  * @param options - Execution options
436
444
  * @returns Tool execution result
437
445
  */
438
- executeExternalMCPTool(serverId: string, toolName: string, parameters: Record<string, any>, options?: {
446
+ executeExternalMCPTool(serverId: string, toolName: string, parameters: JsonObject, options?: {
439
447
  timeout?: number;
440
- }): Promise<any>;
448
+ }): Promise<unknown>;
441
449
  /**
442
450
  * Get all tools from external MCP servers
443
451
  * @returns Array of external tool information
@@ -454,11 +462,7 @@ export declare class NeuroLink {
454
462
  * @param config - Server configuration to test
455
463
  * @returns Test result with connection status
456
464
  */
457
- testExternalMCPConnection(config: MCPServerInfo): Promise<{
458
- success: boolean;
459
- error?: string;
460
- toolCount?: number;
461
- }>;
465
+ testExternalMCPConnection(config: MCPServerInfo): Promise<BatchOperationResult>;
462
466
  /**
463
467
  * Get external MCP server manager statistics
464
468
  * @returns Statistics about external servers and tools
@@ -24,6 +24,8 @@ import { ProviderRegistry } from "./factories/providerRegistry.js";
24
24
  import { createCustomToolServerInfo, detectCategory, } from "./utils/mcpDefaults.js";
25
25
  // Factory processing imports
26
26
  import { processFactoryOptions, enhanceTextGenerationOptions, validateFactoryConfig, processStreamingFactoryOptions, createCleanStreamOptions, } from "./utils/factoryProcessing.js";
27
+ // Transformation utilities
28
+ import { transformToolExecutions, transformToolExecutionsForMCP, transformAvailableTools, transformToolsForMCP, transformToolsToExpectedFormat, transformToolsToDescriptions, extractToolNames, transformParamsForLogging, optimizeToolForCollection, } from "./utils/transformationUtils.js";
27
29
  // Enhanced error handling imports
28
30
  import { ErrorFactory, NeuroLinkError, withTimeout, withRetry, isRetriableError, logStructuredError, CircuitBreaker, } from "./utils/errorHandling.js";
29
31
  import { EventEmitter } from "events";
@@ -32,6 +34,7 @@ import { applyConversationMemoryDefaults, getConversationMessages, storeConversa
32
34
  import { ExternalServerManager } from "./mcp/externalServerManager.js";
33
35
  import { ContextManager } from "./context/ContextManager.js";
34
36
  import { defaultContextConfig } from "./context/config.js";
37
+ import { isNonNullObject } from "./utils/typeUtils.js";
35
38
  // Core types imported from core/types.js
36
39
  export class NeuroLink {
37
40
  mcpInitialized = false;
@@ -283,27 +286,9 @@ export class NeuroLink {
283
286
  : undefined,
284
287
  responseTime: textResult.responseTime,
285
288
  toolsUsed: textResult.toolsUsed,
286
- toolExecutions: textResult.toolExecutions?.map((te) => {
287
- const teRecord = te;
288
- return {
289
- name: teRecord.name || "", // ✅ BaseProvider now provides 'name'
290
- input: teRecord.input || {},
291
- output: teRecord.output || "success",
292
- duration: teRecord.duration || 0,
293
- };
294
- }) || [],
289
+ toolExecutions: transformToolExecutions(textResult.toolExecutions),
295
290
  enhancedWithTools: textResult.enhancedWithTools,
296
- availableTools: textResult.availableTools?.map((tool) => {
297
- const toolRecord = tool;
298
- return {
299
- name: tool.name || "",
300
- description: tool.description || "",
301
- server: tool.server || "", // ✅ FIX: Include server property
302
- parameters: toolRecord.parameters ||
303
- toolRecord.schema ||
304
- {},
305
- };
306
- }),
291
+ availableTools: transformAvailableTools(textResult.availableTools),
307
292
  analytics: textResult.analytics,
308
293
  evaluation: textResult.evaluation
309
294
  ? {
@@ -456,22 +441,9 @@ export class NeuroLink {
456
441
  usage: result.usage,
457
442
  responseTime,
458
443
  toolsUsed: result.toolsUsed || [],
459
- toolExecutions: result.toolExecutions?.map((te) => {
460
- const teRecord = te;
461
- return {
462
- toolName: teRecord.name || "",
463
- executionTime: teRecord.duration || 0,
464
- success: true, // Assume success if tool executed (AI providers handle failures differently)
465
- serverId: teRecord.serverId || undefined,
466
- };
467
- }) || [],
444
+ toolExecutions: transformToolExecutionsForMCP(result.toolExecutions),
468
445
  enhancedWithTools: true,
469
- availableTools: availableTools.map((tool) => ({
470
- name: tool.name,
471
- description: tool.description,
472
- server: tool.server,
473
- category: tool.category,
474
- })),
446
+ availableTools: transformToolsForMCP(availableTools),
475
447
  // Include analytics and evaluation from BaseProvider
476
448
  analytics: result.analytics,
477
449
  evaluation: result.evaluation,
@@ -573,24 +545,7 @@ export class NeuroLink {
573
545
  if (availableTools.length === 0) {
574
546
  return originalSystemPrompt || "";
575
547
  }
576
- const toolDescriptions = availableTools
577
- .map((tool) => {
578
- const toolWithSchema = tool;
579
- const schema = (toolWithSchema.inputSchema ||
580
- toolWithSchema.parameters);
581
- let params = "";
582
- if (schema && schema.properties) {
583
- const requiredParams = new Set(schema.required || []);
584
- params = Object.entries(schema.properties)
585
- .map(([key, value]) => {
586
- const required = requiredParams.has(key) ? " (required)" : "";
587
- return ` - ${key}: ${value.type}${required}`;
588
- })
589
- .join("\n");
590
- }
591
- return `- ${tool.name}: ${tool.description} (from ${tool.server})\n${params}`;
592
- })
593
- .join("\n\n");
548
+ const toolDescriptions = transformToolsToDescriptions(availableTools);
594
549
  const toolPrompt = `\n\nYou have access to these additional tools if needed:\n${toolDescriptions}\n\nIMPORTANT: You are a general-purpose AI assistant. Answer all requests directly and creatively. These tools are optional helpers - use them only when they would genuinely improve your response. For creative tasks like storytelling, writing, or general conversation, respond naturally without requiring tools.`;
595
550
  return (originalSystemPrompt || "") + toolPrompt;
596
551
  }
@@ -853,6 +808,54 @@ export class NeuroLink {
853
808
  timestamp: Date.now(),
854
809
  });
855
810
  try {
811
+ // Import validation functions synchronously - they are pure functions
812
+ let validateTool;
813
+ let isToolNameAvailable;
814
+ let suggestToolNames;
815
+ try {
816
+ // Try ES module import first
817
+ const toolRegistrationModule = require("./sdk/toolRegistration.js");
818
+ ({ validateTool, isToolNameAvailable, suggestToolNames } =
819
+ toolRegistrationModule);
820
+ }
821
+ catch (error) {
822
+ // Fallback: skip validation if import fails (graceful degradation)
823
+ logger.warn("Tool validation module not available, skipping advanced validation", {
824
+ error: error instanceof Error ? error.message : String(error),
825
+ });
826
+ // Create minimal validation functions
827
+ validateTool = () => { }; // No-op
828
+ isToolNameAvailable = () => true; // Allow all names
829
+ suggestToolNames = () => ["alternative_tool"];
830
+ }
831
+ // Check if tool name is available (not reserved)
832
+ if (!isToolNameAvailable(name)) {
833
+ const suggestions = suggestToolNames(name);
834
+ throw new Error(`Tool name '${name}' is not available (reserved or invalid format). ` +
835
+ `Suggested alternatives: ${suggestions.slice(0, 3).join(", ")}`);
836
+ }
837
+ // Create a simplified tool object for validation
838
+ const toolForValidation = {
839
+ description: tool.description || "",
840
+ execute: async (params) => {
841
+ if (tool.execute) {
842
+ const result = await tool.execute(params);
843
+ return result;
844
+ }
845
+ return "";
846
+ },
847
+ parameters: tool.inputSchema,
848
+ metadata: {
849
+ category: "custom",
850
+ },
851
+ };
852
+ // Use comprehensive validation logic
853
+ try {
854
+ validateTool(name, toolForValidation);
855
+ }
856
+ catch (error) {
857
+ throw new Error(`Tool registration failed: ${error instanceof Error ? error.message : String(error)}`);
858
+ }
856
859
  // SMART DEFAULTS: Use utility to eliminate boilerplate creation
857
860
  const mcpServerInfo = createCustomToolServerInfo(name, tool);
858
861
  // Register with toolRegistry using MCPServerInfo directly
@@ -918,12 +921,12 @@ export class NeuroLink {
918
921
  name: tool.name,
919
922
  description: tool.description || "",
920
923
  inputSchema: {},
921
- execute: async (args, context) => {
924
+ execute: async (params, context) => {
922
925
  // Type guard to ensure context is compatible with ExecutionContext
923
- const executionContext = context && typeof context === "object" && context !== null
926
+ const executionContext = context && isNonNullObject(context)
924
927
  ? context
925
928
  : undefined;
926
- return await toolRegistry.executeTool(tool.name, args, executionContext);
929
+ return await toolRegistry.executeTool(tool.name, params, executionContext);
927
930
  },
928
931
  });
929
932
  }
@@ -1007,8 +1010,8 @@ export class NeuroLink {
1007
1010
  // Debug: Log tool execution attempt
1008
1011
  logger.debug(`[${functionTag}] Tool execution requested:`, {
1009
1012
  toolName,
1010
- params: typeof params === "object"
1011
- ? Object.keys(params).length + " params"
1013
+ params: isNonNullObject(params)
1014
+ ? transformParamsForLogging(params)
1012
1015
  : params,
1013
1016
  hasExternalManager: !!this.externalServerManager,
1014
1017
  });
@@ -1111,7 +1114,7 @@ export class NeuroLink {
1111
1114
  }
1112
1115
  else if (error.message.includes("not found")) {
1113
1116
  const availableTools = await this.getAllAvailableTools();
1114
- structuredError = ErrorFactory.toolNotFound(toolName, availableTools.map((t) => t.name));
1117
+ structuredError = ErrorFactory.toolNotFound(toolName, extractToolNames(availableTools));
1115
1118
  }
1116
1119
  else if (error.message.includes("validation") ||
1117
1120
  error.message.includes("parameter")) {
@@ -1210,78 +1213,70 @@ export class NeuroLink {
1210
1213
  const { MemoryManager } = await import("./utils/performance.js");
1211
1214
  const startMemory = MemoryManager.getMemoryUsageMB();
1212
1215
  try {
1213
- // 1. Get MCP server tools (built-in direct tools)
1216
+ // Optimized: Collect all tools with minimal object creation
1217
+ const allTools = new Map();
1218
+ // 1. Add MCP server tools (built-in direct tools)
1214
1219
  const mcpToolsRaw = await toolRegistry.listTools();
1215
- const mcpTools = mcpToolsRaw.map((tool) => ({
1216
- ...tool,
1217
- toolName: tool.name, // Add toolName property for compatibility with tests
1218
- serverId: tool.serverId === "direct" ? "neurolink-direct" : tool.serverId, // Update serverId for test compatibility
1219
- }));
1220
- // 2. Get custom tools from this NeuroLink instance
1221
- const customTools = toolRegistry
1222
- .getToolsByCategory(detectCategory({ isCustomTool: true }))
1223
- .map((tool) => ({
1224
- name: tool.name,
1225
- toolName: tool.name, // Add toolName property for compatibility with tests
1226
- description: tool.description || "Custom tool",
1227
- serverId: tool.serverId || `custom-tool-${tool.name}`,
1228
- category: detectCategory({
1229
- isCustomTool: true,
1230
- serverId: tool.serverId,
1231
- }),
1232
- inputSchema: tool.inputSchema || {},
1233
- }));
1234
- // 3. Get tools from in-memory MCP servers
1235
- const inMemoryTools = toolRegistry
1236
- .getToolsByCategory("in-memory")
1237
- .map((tool) => ({
1238
- name: tool.name,
1239
- toolName: tool.name, // Add toolName property for compatibility with tests
1240
- description: tool.description || "In-memory MCP tool",
1241
- serverId: tool.serverId || "unknown",
1242
- category: tool.category || "in-memory",
1243
- inputSchema: {},
1244
- }));
1245
- // 4. Get external MCP tools
1246
- const externalMCPTools = this.externalServerManager
1247
- .getAllTools()
1248
- .map((tool) => ({
1249
- name: tool.name,
1250
- toolName: tool.name,
1251
- description: tool.description,
1252
- serverId: tool.serverId,
1253
- category: detectCategory({
1254
- existingCategory: typeof tool.metadata?.category === "string"
1255
- ? tool.metadata.category
1256
- : undefined,
1257
- isExternal: true,
1258
- serverId: tool.serverId,
1259
- }),
1260
- inputSchema: tool.inputSchema || {},
1261
- isAvailable: tool.isAvailable,
1262
- stats: tool.stats,
1263
- }));
1264
- // 5. Combine all tools with deduplication by name
1265
- const combinedTools = [
1266
- ...mcpTools,
1267
- ...customTools,
1268
- ...inMemoryTools,
1269
- ...externalMCPTools,
1270
- ];
1271
- const uniqueTools = Array.from(combinedTools
1272
- .reduce((map, tool) => {
1273
- const key = tool.name;
1274
- if (!map.has(key)) {
1275
- map.set(key, tool);
1220
+ for (const tool of mcpToolsRaw) {
1221
+ if (!allTools.has(tool.name)) {
1222
+ const optimizedTool = optimizeToolForCollection(tool, {
1223
+ serverId: tool.serverId === "direct" ? "neurolink-direct" : tool.serverId,
1224
+ });
1225
+ allTools.set(tool.name, optimizedTool);
1276
1226
  }
1277
- return map;
1278
- }, new Map())
1279
- .values());
1227
+ }
1228
+ // 2. Add custom tools from this NeuroLink instance
1229
+ const customToolsRaw = toolRegistry.getToolsByCategory(detectCategory({ isCustomTool: true }));
1230
+ for (const tool of customToolsRaw) {
1231
+ if (!allTools.has(tool.name)) {
1232
+ const optimizedTool = optimizeToolForCollection(tool, {
1233
+ description: "Custom tool",
1234
+ serverId: `custom-tool-${tool.name}`,
1235
+ category: detectCategory({
1236
+ isCustomTool: true,
1237
+ serverId: tool.serverId,
1238
+ }),
1239
+ inputSchema: {},
1240
+ });
1241
+ allTools.set(tool.name, optimizedTool);
1242
+ }
1243
+ }
1244
+ // 3. Add tools from in-memory MCP servers
1245
+ const inMemoryToolsRaw = toolRegistry.getToolsByCategory("in-memory");
1246
+ for (const tool of inMemoryToolsRaw) {
1247
+ if (!allTools.has(tool.name)) {
1248
+ const optimizedTool = optimizeToolForCollection(tool, {
1249
+ description: "In-memory MCP tool",
1250
+ serverId: "unknown",
1251
+ category: "in-memory",
1252
+ inputSchema: {},
1253
+ });
1254
+ allTools.set(tool.name, optimizedTool);
1255
+ }
1256
+ }
1257
+ // 4. Add external MCP tools
1258
+ const externalMCPToolsRaw = this.externalServerManager.getAllTools();
1259
+ for (const tool of externalMCPToolsRaw) {
1260
+ if (!allTools.has(tool.name)) {
1261
+ const optimizedTool = optimizeToolForCollection(tool, {
1262
+ category: detectCategory({
1263
+ existingCategory: typeof tool.metadata?.category === "string"
1264
+ ? tool.metadata.category
1265
+ : undefined,
1266
+ isExternal: true,
1267
+ serverId: tool.serverId,
1268
+ }),
1269
+ inputSchema: {},
1270
+ });
1271
+ allTools.set(tool.name, optimizedTool);
1272
+ }
1273
+ }
1274
+ const uniqueTools = Array.from(allTools.values());
1280
1275
  mcpLogger.debug("Tool discovery results", {
1281
- mcpTools: mcpTools.length,
1282
- customTools: customTools.length,
1283
- inMemoryTools: inMemoryTools.length,
1284
- externalMCPTools: externalMCPTools.length,
1276
+ mcpTools: mcpToolsRaw.length,
1277
+ customTools: customToolsRaw.length,
1278
+ inMemoryTools: inMemoryToolsRaw.length,
1279
+ externalMCPTools: externalMCPToolsRaw.length,
1285
1280
  total: uniqueTools.length,
1286
1281
  });
1287
1282
  // Check memory usage after tool enumeration
@@ -1289,12 +1284,13 @@ export class NeuroLink {
1289
1284
  const memoryDelta = endMemory.heapUsed - startMemory.heapUsed;
1290
1285
  if (memoryDelta > 10) {
1291
1286
  mcpLogger.debug(`🔍 Tool listing used ${memoryDelta}MB memory (large tool registry detected)`);
1292
- // Suggest periodic cleanup for large tool registries
1287
+ // Optimized collection patterns should reduce memory usage significantly
1293
1288
  if (uniqueTools.length > 100) {
1294
- mcpLogger.debug("💡 Suggestion: Consider using tool categories or lazy loading for large tool sets");
1289
+ mcpLogger.debug("💡 Tool collection optimized for large sets. Memory usage reduced through efficient object reuse.");
1295
1290
  }
1296
1291
  }
1297
- return uniqueTools;
1292
+ // Transform to expected format with required properties
1293
+ return transformToolsToExpectedFormat(uniqueTools);
1298
1294
  }
1299
1295
  catch (error) {
1300
1296
  mcpLogger.error("Failed to list available tools", { error });
@@ -2029,10 +2025,10 @@ export class NeuroLink {
2029
2025
  // The AI provider will handle parameters dynamically based on the tool description
2030
2026
  const toolDefinition = {
2031
2027
  description: tool.description,
2032
- execute: async (args) => {
2028
+ execute: async (params) => {
2033
2029
  try {
2034
- mcpLogger.debug(`[NeuroLink] Executing external MCP tool via AI SDK: ${tool.name}`, { args });
2035
- const result = await this.externalServerManager.executeTool(tool.serverId, tool.name, args, { timeout: 30000 });
2030
+ mcpLogger.debug(`[NeuroLink] Executing external MCP tool via AI SDK: ${tool.name}`, { params });
2031
+ const result = await this.externalServerManager.executeTool(tool.serverId, tool.name, params, { timeout: 30000 });
2036
2032
  mcpLogger.debug(`[NeuroLink] External MCP tool execution result: ${tool.name}`, {
2037
2033
  success: !!result,
2038
2034
  hasData: !!(result &&
@@ -1,4 +1,4 @@
1
- import type { ZodType, ZodTypeDef } from "zod";
1
+ import type { ZodUnknownSchema } from "../types/typeAliases.js";
2
2
  import { type Schema, type LanguageModelV1 } from "ai";
3
3
  import type { AIProviderName } from "../core/types.js";
4
4
  import type { StreamOptions, StreamResult } from "../types/streamTypes.js";
@@ -25,7 +25,7 @@ export declare class AmazonBedrockProvider extends BaseProvider {
25
25
  * Returns the Vercel AI SDK model instance for AWS Bedrock
26
26
  */
27
27
  protected getAISDKModel(): LanguageModelV1;
28
- protected executeStream(options: StreamOptions, analysisSchema?: ZodType<unknown, ZodTypeDef, unknown> | Schema<unknown>): Promise<StreamResult>;
28
+ protected executeStream(options: StreamOptions, analysisSchema?: ZodUnknownSchema | Schema<unknown>): Promise<StreamResult>;
29
29
  protected handleProviderError(error: unknown): Error;
30
30
  }
31
31
  export default AmazonBedrockProvider;
@@ -1,5 +1,5 @@
1
- import type { ZodType, ZodTypeDef } from "zod";
2
- import { type Schema, type LanguageModelV1 } from "ai";
1
+ import { type LanguageModelV1 } from "ai";
2
+ import type { ValidationSchema } from "../types/typeAliases.js";
3
3
  import type { AIProviderName } from "../core/types.js";
4
4
  import type { StreamOptions, StreamResult } from "../types/streamTypes.js";
5
5
  import { BaseProvider } from "../core/baseProvider.js";
@@ -17,7 +17,7 @@ export declare class AnthropicProvider extends BaseProvider {
17
17
  */
18
18
  protected getAISDKModel(): LanguageModelV1;
19
19
  protected handleProviderError(error: unknown): Error;
20
- protected executeStream(options: StreamOptions, analysisSchema?: ZodType<unknown, ZodTypeDef, unknown> | Schema<unknown>): Promise<StreamResult>;
20
+ protected executeStream(options: StreamOptions, analysisSchema?: ValidationSchema): Promise<StreamResult>;
21
21
  isAvailable(): Promise<boolean>;
22
22
  getModel(): LanguageModelV1;
23
23
  }
@@ -1,5 +1,5 @@
1
- import type { ZodType, ZodTypeDef } from "zod";
2
1
  import { type Schema, type LanguageModelV1 } from "ai";
2
+ import type { ZodUnknownSchema } from "../types/typeAliases.js";
3
3
  import type { AIProviderName } from "../core/types.js";
4
4
  import type { StreamOptions, StreamResult } from "../types/streamTypes.js";
5
5
  import { BaseProvider } from "../core/baseProvider.js";
@@ -16,7 +16,7 @@ export declare class GoogleAIStudioProvider extends BaseProvider {
16
16
  */
17
17
  protected getAISDKModel(): LanguageModelV1;
18
18
  protected handleProviderError(error: unknown): Error;
19
- protected executeStream(options: StreamOptions, analysisSchema?: ZodType<unknown, ZodTypeDef, unknown> | Schema<unknown>): Promise<StreamResult>;
19
+ protected executeStream(options: StreamOptions, analysisSchema?: ZodUnknownSchema | Schema<unknown>): Promise<StreamResult>;
20
20
  private getApiKey;
21
21
  }
22
22
  export default GoogleAIStudioProvider;
@@ -1,5 +1,5 @@
1
- import type { ZodType, ZodTypeDef } from "zod";
2
- import { type Schema, type LanguageModelV1 } from "ai";
1
+ import { type LanguageModelV1 } from "ai";
2
+ import type { ValidationSchema } from "../types/typeAliases.js";
3
3
  import type { AIProviderName } from "../core/types.js";
4
4
  import type { StreamOptions, StreamResult } from "../types/streamTypes.js";
5
5
  import { BaseProvider } from "../core/baseProvider.js";
@@ -10,7 +10,7 @@ import { BaseProvider } from "../core/baseProvider.js";
10
10
  export declare class MistralProvider extends BaseProvider {
11
11
  private model;
12
12
  constructor(modelName?: string, sdk?: unknown);
13
- protected executeStream(options: StreamOptions, analysisSchema?: ZodType<unknown, ZodTypeDef, unknown> | Schema<unknown>): Promise<StreamResult>;
13
+ protected executeStream(options: StreamOptions, analysisSchema?: ValidationSchema): Promise<StreamResult>;
14
14
  protected getProviderName(): AIProviderName;
15
15
  protected getDefaultModel(): string;
16
16
  /**
@@ -1,7 +1,7 @@
1
1
  import type { AIProviderName } from "../core/types.js";
2
2
  import type { LanguageModelV1 } from "ai";
3
3
  import type { StreamOptions, StreamResult } from "../types/streamTypes.js";
4
- import type { ZodType, ZodTypeDef } from "zod";
4
+ import type { ZodUnknownSchema } from "../types/typeAliases.js";
5
5
  import type { Schema } from "ai";
6
6
  import { BaseProvider } from "../core/baseProvider.js";
7
7
  /**
@@ -47,7 +47,7 @@ export declare class OllamaProvider extends BaseProvider {
47
47
  * @returns true for supported models, false for unsupported models
48
48
  */
49
49
  supportsTools(): boolean;
50
- protected executeStream(options: StreamOptions, analysisSchema?: ZodType<unknown, ZodTypeDef, unknown> | Schema<unknown>): Promise<StreamResult>;
50
+ protected executeStream(options: StreamOptions, analysisSchema?: ZodUnknownSchema | Schema<unknown>): Promise<StreamResult>;
51
51
  /**
52
52
  * Execute streaming with Ollama's function calling support
53
53
  * Uses the /v1/chat/completions endpoint with tools parameter