@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.
- package/CHANGELOG.md +6 -0
- package/dist/cli/commands/config.d.ts +66 -66
- package/dist/core/baseProvider.d.ts +12 -7
- package/dist/core/baseProvider.js +118 -125
- package/dist/core/constants.d.ts +5 -0
- package/dist/core/constants.js +6 -0
- package/dist/core/dynamicModels.d.ts +4 -4
- package/dist/core/factory.d.ts +2 -4
- package/dist/core/types.d.ts +8 -22
- package/dist/index.d.ts +1 -4
- package/dist/lib/core/baseProvider.d.ts +12 -7
- package/dist/lib/core/baseProvider.js +118 -125
- package/dist/lib/core/constants.d.ts +5 -0
- package/dist/lib/core/constants.js +6 -0
- package/dist/lib/core/dynamicModels.d.ts +8 -8
- package/dist/lib/core/factory.d.ts +2 -4
- package/dist/lib/core/types.d.ts +8 -22
- package/dist/lib/index.d.ts +1 -4
- package/dist/lib/mcp/contracts/mcpContract.d.ts +6 -19
- package/dist/lib/mcp/externalServerManager.d.ts +2 -4
- package/dist/lib/mcp/externalServerManager.js +7 -8
- package/dist/lib/mcp/factory.d.ts +61 -7
- package/dist/lib/mcp/factory.js +36 -23
- package/dist/lib/mcp/mcpClientFactory.d.ts +2 -1
- package/dist/lib/mcp/mcpClientFactory.js +73 -26
- package/dist/lib/mcp/registry.d.ts +1 -1
- package/dist/lib/mcp/toolDiscoveryService.d.ts +1 -1
- package/dist/lib/mcp/toolDiscoveryService.js +50 -19
- package/dist/lib/mcp/toolRegistry.d.ts +23 -1
- package/dist/lib/mcp/toolRegistry.js +108 -17
- package/dist/lib/models/modelResolver.js +2 -1
- package/dist/lib/neurolink.d.ts +12 -8
- package/dist/lib/neurolink.js +130 -134
- package/dist/lib/providers/amazonBedrock.d.ts +2 -2
- package/dist/lib/providers/anthropic.d.ts +3 -3
- package/dist/lib/providers/googleAiStudio.d.ts +2 -2
- package/dist/lib/providers/mistral.d.ts +3 -3
- package/dist/lib/providers/ollama.d.ts +2 -2
- package/dist/lib/providers/openAI.d.ts +3 -3
- package/dist/lib/providers/openaiCompatible.d.ts +2 -2
- package/dist/lib/providers/sagemaker/client.d.ts +2 -5
- package/dist/lib/providers/sagemaker/language-model.d.ts +4 -6
- package/dist/lib/providers/sagemaker/parsers.js +5 -4
- package/dist/lib/sdk/toolRegistration.d.ts +6 -6
- package/dist/lib/sdk/toolRegistration.js +17 -56
- package/dist/lib/types/generateTypes.d.ts +9 -9
- package/dist/lib/types/streamTypes.d.ts +4 -4
- package/dist/lib/types/tools.d.ts +15 -7
- package/dist/lib/types/typeAliases.d.ts +412 -0
- package/dist/lib/types/typeAliases.js +48 -0
- package/dist/lib/utils/factoryProcessing.d.ts +2 -1
- package/dist/lib/utils/factoryProcessing.js +4 -3
- package/dist/lib/utils/parameterValidation.d.ts +97 -0
- package/dist/lib/utils/parameterValidation.js +452 -0
- package/dist/lib/utils/transformationUtils.d.ts +204 -0
- package/dist/lib/utils/transformationUtils.js +334 -0
- package/dist/lib/utils/typeUtils.d.ts +77 -0
- package/dist/lib/utils/typeUtils.js +97 -0
- package/dist/mcp/contracts/mcpContract.d.ts +6 -19
- package/dist/mcp/externalServerManager.d.ts +2 -4
- package/dist/mcp/externalServerManager.js +7 -8
- package/dist/mcp/factory.d.ts +61 -7
- package/dist/mcp/factory.js +36 -23
- package/dist/mcp/mcpClientFactory.d.ts +2 -1
- package/dist/mcp/mcpClientFactory.js +73 -26
- package/dist/mcp/registry.d.ts +1 -1
- package/dist/mcp/toolDiscoveryService.d.ts +1 -1
- package/dist/mcp/toolDiscoveryService.js +50 -19
- package/dist/mcp/toolRegistry.d.ts +23 -1
- package/dist/mcp/toolRegistry.js +108 -17
- package/dist/models/modelResolver.js +2 -1
- package/dist/neurolink.d.ts +12 -8
- package/dist/neurolink.js +130 -134
- package/dist/providers/amazonBedrock.d.ts +2 -2
- package/dist/providers/anthropic.d.ts +3 -3
- package/dist/providers/googleAiStudio.d.ts +2 -2
- package/dist/providers/mistral.d.ts +3 -3
- package/dist/providers/ollama.d.ts +2 -2
- package/dist/providers/openAI.d.ts +3 -3
- package/dist/providers/openaiCompatible.d.ts +2 -2
- package/dist/providers/sagemaker/client.d.ts +2 -5
- package/dist/providers/sagemaker/language-model.d.ts +4 -6
- package/dist/providers/sagemaker/parsers.js +5 -4
- package/dist/sdk/toolRegistration.d.ts +6 -6
- package/dist/sdk/toolRegistration.js +17 -56
- package/dist/types/generateTypes.d.ts +9 -9
- package/dist/types/streamTypes.d.ts +4 -4
- package/dist/types/tools.d.ts +15 -7
- package/dist/types/typeAliases.d.ts +412 -0
- package/dist/types/typeAliases.js +48 -0
- package/dist/utils/factoryProcessing.d.ts +2 -1
- package/dist/utils/factoryProcessing.js +4 -3
- package/dist/utils/parameterValidation.d.ts +97 -0
- package/dist/utils/parameterValidation.js +452 -0
- package/dist/utils/transformationUtils.d.ts +204 -0
- package/dist/utils/transformationUtils.js +334 -0
- package/dist/utils/typeUtils.d.ts +77 -0
- package/dist/utils/typeUtils.js +97 -0
- 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
|
-
//
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
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
|
-
...(
|
|
423
|
+
...(isNonNullObject(modelDisplay)
|
|
423
424
|
? modelDisplay
|
|
424
425
|
: {}),
|
|
425
426
|
relevanceScore: result.score,
|
package/dist/lib/neurolink.d.ts
CHANGED
|
@@ -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<
|
|
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:
|
|
446
|
+
executeExternalMCPTool(serverId: string, toolName: string, parameters: JsonObject, options?: {
|
|
439
447
|
timeout?: number;
|
|
440
|
-
}): Promise<
|
|
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
|
package/dist/lib/neurolink.js
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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 (
|
|
924
|
+
execute: async (params, context) => {
|
|
922
925
|
// Type guard to ensure context is compatible with ExecutionContext
|
|
923
|
-
const executionContext = context &&
|
|
926
|
+
const executionContext = context && isNonNullObject(context)
|
|
924
927
|
? context
|
|
925
928
|
: undefined;
|
|
926
|
-
return await toolRegistry.executeTool(tool.name,
|
|
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:
|
|
1011
|
-
?
|
|
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
|
|
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
|
-
//
|
|
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
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
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
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
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:
|
|
1282
|
-
customTools:
|
|
1283
|
-
inMemoryTools:
|
|
1284
|
-
externalMCPTools:
|
|
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
|
-
//
|
|
1287
|
+
// Optimized collection patterns should reduce memory usage significantly
|
|
1293
1288
|
if (uniqueTools.length > 100) {
|
|
1294
|
-
mcpLogger.debug("💡
|
|
1289
|
+
mcpLogger.debug("💡 Tool collection optimized for large sets. Memory usage reduced through efficient object reuse.");
|
|
1295
1290
|
}
|
|
1296
1291
|
}
|
|
1297
|
-
|
|
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 (
|
|
2028
|
+
execute: async (params) => {
|
|
2033
2029
|
try {
|
|
2034
|
-
mcpLogger.debug(`[NeuroLink] Executing external MCP tool via AI SDK: ${tool.name}`, {
|
|
2035
|
-
const result = await this.externalServerManager.executeTool(tool.serverId, tool.name,
|
|
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 {
|
|
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?:
|
|
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
|
|
2
|
-
import
|
|
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?:
|
|
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?:
|
|
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
|
|
2
|
-
import
|
|
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?:
|
|
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 {
|
|
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?:
|
|
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
|