@juspay/neurolink 7.29.1 → 7.29.2
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 +3 -3
- package/dist/cli/commands/mcp.js +25 -0
- package/dist/cli/factories/commandFactory.d.ts +1 -0
- package/dist/cli/factories/commandFactory.js +115 -21
- package/dist/cli/index.js +8 -0
- package/dist/core/factory.js +77 -4
- package/dist/factories/providerFactory.js +3 -0
- package/dist/factories/providerRegistry.js +2 -2
- package/dist/lib/core/factory.js +77 -4
- package/dist/lib/factories/providerFactory.js +3 -0
- package/dist/lib/factories/providerRegistry.js +2 -2
- package/dist/lib/mcp/externalServerManager.js +13 -14
- package/dist/lib/mcp/flexibleToolValidator.d.ts +50 -0
- package/dist/lib/mcp/flexibleToolValidator.js +161 -0
- package/dist/lib/mcp/toolRegistry.d.ts +2 -2
- package/dist/lib/mcp/toolRegistry.js +25 -50
- package/dist/lib/neurolink.d.ts +2 -0
- package/dist/lib/neurolink.js +137 -69
- package/dist/lib/providers/amazonBedrock.d.ts +47 -6
- package/dist/lib/providers/amazonBedrock.js +282 -23
- package/dist/lib/providers/aws/credentialProvider.d.ts +58 -0
- package/dist/lib/providers/aws/credentialProvider.js +267 -0
- package/dist/lib/providers/aws/credentialTester.d.ts +49 -0
- package/dist/lib/providers/aws/credentialTester.js +394 -0
- package/dist/lib/proxy/awsProxyIntegration.d.ts +23 -0
- package/dist/lib/proxy/awsProxyIntegration.js +285 -0
- package/dist/lib/proxy/proxyFetch.d.ts +9 -5
- package/dist/lib/proxy/proxyFetch.js +232 -98
- package/dist/lib/proxy/utils/noProxyUtils.d.ts +39 -0
- package/dist/lib/proxy/utils/noProxyUtils.js +149 -0
- package/dist/lib/types/providers.d.ts +43 -0
- package/dist/lib/utils/providerConfig.d.ts +1 -0
- package/dist/lib/utils/providerConfig.js +2 -1
- package/dist/lib/utils/providerHealth.js +123 -5
- package/dist/mcp/externalServerManager.js +13 -14
- package/dist/mcp/flexibleToolValidator.d.ts +50 -0
- package/dist/mcp/flexibleToolValidator.js +161 -0
- package/dist/mcp/toolRegistry.d.ts +2 -2
- package/dist/mcp/toolRegistry.js +25 -50
- package/dist/neurolink.d.ts +2 -0
- package/dist/neurolink.js +137 -69
- package/dist/providers/amazonBedrock.d.ts +47 -6
- package/dist/providers/amazonBedrock.js +282 -23
- package/dist/providers/aws/credentialProvider.d.ts +58 -0
- package/dist/providers/aws/credentialProvider.js +267 -0
- package/dist/providers/aws/credentialTester.d.ts +49 -0
- package/dist/providers/aws/credentialTester.js +394 -0
- package/dist/proxy/awsProxyIntegration.d.ts +23 -0
- package/dist/proxy/awsProxyIntegration.js +285 -0
- package/dist/proxy/proxyFetch.d.ts +9 -5
- package/dist/proxy/proxyFetch.js +232 -98
- package/dist/proxy/utils/noProxyUtils.d.ts +39 -0
- package/dist/proxy/utils/noProxyUtils.js +149 -0
- package/dist/types/providers.d.ts +43 -0
- package/dist/utils/providerConfig.d.ts +1 -0
- package/dist/utils/providerConfig.js +2 -1
- package/dist/utils/providerHealth.js +123 -5
- package/package.json +5 -1
package/dist/lib/neurolink.js
CHANGED
|
@@ -24,6 +24,7 @@ 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
|
+
// Tool detection and execution imports
|
|
27
28
|
// Transformation utilities
|
|
28
29
|
import { transformToolExecutions, transformToolExecutionsForMCP, transformAvailableTools, transformToolsForMCP, transformToolsToExpectedFormat, transformToolsToDescriptions, extractToolNames, transformParamsForLogging, optimizeToolForCollection, } from "./utils/transformationUtils.js";
|
|
29
30
|
// Enhanced error handling imports
|
|
@@ -54,14 +55,21 @@ export class NeuroLink {
|
|
|
54
55
|
* @param toolName - Name of the tool
|
|
55
56
|
* @param startTime - Timestamp when tool execution started
|
|
56
57
|
* @param success - Whether the tool execution was successful
|
|
58
|
+
* @param result - The result of the tool execution (optional)
|
|
59
|
+
* @param error - The error if execution failed (optional)
|
|
57
60
|
*/
|
|
58
|
-
emitToolEndEvent(toolName, startTime, success) {
|
|
61
|
+
emitToolEndEvent(toolName, startTime, success, result, error) {
|
|
62
|
+
// Emit tool end event (NeuroLink format - enhanced with result/error)
|
|
59
63
|
this.emitter.emit("tool:end", {
|
|
60
64
|
toolName,
|
|
61
65
|
responseTime: Date.now() - startTime,
|
|
62
66
|
success,
|
|
63
67
|
timestamp: Date.now(),
|
|
68
|
+
result: result, // Enhanced: include actual result
|
|
69
|
+
error: error, // Enhanced: include error if present
|
|
64
70
|
});
|
|
71
|
+
// ADD: Bedrock-compatible tool:end event (positional parameters)
|
|
72
|
+
this.emitter.emit("tool:end", toolName, success ? result : error);
|
|
65
73
|
}
|
|
66
74
|
// Conversation memory support
|
|
67
75
|
conversationMemory;
|
|
@@ -816,11 +824,15 @@ export class NeuroLink {
|
|
|
816
824
|
options.input.text = this.contextManager.getContextForPrompt("user", options.input.text);
|
|
817
825
|
}
|
|
818
826
|
const startTime = Date.now();
|
|
819
|
-
// Emit generation start event
|
|
827
|
+
// Emit generation start event (NeuroLink format - keep existing)
|
|
820
828
|
this.emitter.emit("generation:start", {
|
|
821
829
|
provider: options.provider || "auto",
|
|
822
830
|
timestamp: startTime,
|
|
823
831
|
});
|
|
832
|
+
// ADD: Bedrock-compatible response:start event
|
|
833
|
+
this.emitter.emit("response:start");
|
|
834
|
+
// ADD: Bedrock-compatible message event
|
|
835
|
+
this.emitter.emit("message", `Starting ${options.provider || "auto"} text generation...`);
|
|
824
836
|
// Process factory configuration
|
|
825
837
|
const factoryResult = processFactoryOptions(options);
|
|
826
838
|
// Validate factory configuration if present
|
|
@@ -863,13 +875,18 @@ export class NeuroLink {
|
|
|
863
875
|
}
|
|
864
876
|
// Use redesigned generation logic
|
|
865
877
|
const textResult = await this.generateTextInternal(textOptions);
|
|
866
|
-
// Emit generation completion event
|
|
878
|
+
// Emit generation completion event (NeuroLink format - enhanced with content)
|
|
867
879
|
this.emitter.emit("generation:end", {
|
|
868
880
|
provider: textResult.provider,
|
|
869
881
|
responseTime: Date.now() - startTime,
|
|
870
882
|
toolsUsed: textResult.toolsUsed,
|
|
871
883
|
timestamp: Date.now(),
|
|
884
|
+
result: textResult, // Enhanced: include full result
|
|
872
885
|
});
|
|
886
|
+
// ADD: Bedrock-compatible response:end event with content
|
|
887
|
+
this.emitter.emit("response:end", textResult.content || "");
|
|
888
|
+
// ADD: Bedrock-compatible message event
|
|
889
|
+
this.emitter.emit("message", `Generation completed in ${Date.now() - startTime}ms`);
|
|
873
890
|
// Convert back to GenerateResult
|
|
874
891
|
const generateResult = {
|
|
875
892
|
content: textResult.content,
|
|
@@ -1002,6 +1019,10 @@ export class NeuroLink {
|
|
|
1002
1019
|
promptLength: options.prompt?.length || 0,
|
|
1003
1020
|
hasConversationMemory: !!this.conversationMemory,
|
|
1004
1021
|
});
|
|
1022
|
+
// ADD: Bedrock-compatible response:start event for generateTextInternal
|
|
1023
|
+
this.emitter.emit("response:start");
|
|
1024
|
+
// ADD: Bedrock-compatible message event for generateTextInternal
|
|
1025
|
+
this.emitter.emit("message", `Starting ${options.provider || "auto"} text generation (internal)...`);
|
|
1005
1026
|
try {
|
|
1006
1027
|
// 🚀 EXHAUSTIVE LOGGING POINT G002: CONVERSATION MEMORY INITIALIZATION
|
|
1007
1028
|
const conversationMemoryStartTime = process.hrtime.bigint();
|
|
@@ -1148,6 +1169,8 @@ export class NeuroLink {
|
|
|
1148
1169
|
});
|
|
1149
1170
|
// Store conversation turn
|
|
1150
1171
|
await storeConversationTurn(this.conversationMemory, options, mcpResult);
|
|
1172
|
+
// ADD: Bedrock-compatible response:end event for MCP success path
|
|
1173
|
+
this.emitter.emit("response:end", mcpResult.content || "");
|
|
1151
1174
|
return mcpResult;
|
|
1152
1175
|
}
|
|
1153
1176
|
else {
|
|
@@ -1164,6 +1187,8 @@ export class NeuroLink {
|
|
|
1164
1187
|
logger.debug(`[${functionTag}] Found tool executions but no content, continuing with result`);
|
|
1165
1188
|
// Store conversation turn even with empty content if tools executed
|
|
1166
1189
|
await storeConversationTurn(this.conversationMemory, options, mcpResult);
|
|
1190
|
+
// ADD: Bedrock-compatible response:end event for MCP tool execution success path
|
|
1191
|
+
this.emitter.emit("response:end", mcpResult.content || "");
|
|
1167
1192
|
return mcpResult;
|
|
1168
1193
|
}
|
|
1169
1194
|
}
|
|
@@ -1188,12 +1213,20 @@ export class NeuroLink {
|
|
|
1188
1213
|
logger.debug(`[${functionTag}] Direct generation successful`);
|
|
1189
1214
|
// Store conversation turn
|
|
1190
1215
|
await storeConversationTurn(this.conversationMemory, options, directResult);
|
|
1216
|
+
// ADD: Bedrock-compatible response:end event for generateTextInternal
|
|
1217
|
+
this.emitter.emit("response:end", directResult.content || "");
|
|
1218
|
+
// ADD: Bedrock-compatible message event for generateTextInternal completion
|
|
1219
|
+
this.emitter.emit("message", `Text generation completed successfully`);
|
|
1191
1220
|
return directResult;
|
|
1192
1221
|
}
|
|
1193
1222
|
catch (error) {
|
|
1194
1223
|
logger.error(`[${functionTag}] All generation methods failed`, {
|
|
1195
1224
|
error: error instanceof Error ? error.message : String(error),
|
|
1196
1225
|
});
|
|
1226
|
+
// ADD: Bedrock-compatible response:end event for error path (empty content)
|
|
1227
|
+
this.emitter.emit("response:end", "");
|
|
1228
|
+
// ADD: Centralized error event emission
|
|
1229
|
+
this.emitter.emit("error", error instanceof Error ? error : new Error(String(error)));
|
|
1197
1230
|
throw error;
|
|
1198
1231
|
}
|
|
1199
1232
|
}
|
|
@@ -1299,6 +1332,9 @@ export class NeuroLink {
|
|
|
1299
1332
|
// Create provider and generate
|
|
1300
1333
|
const provider = await AIProviderFactory.createProvider(providerName, options.model, !options.disableTools, // Pass disableTools as inverse of enableMCP
|
|
1301
1334
|
this);
|
|
1335
|
+
// ADD: Emit connection events for all providers (Bedrock-compatible)
|
|
1336
|
+
this.emitter.emit("connected");
|
|
1337
|
+
this.emitter.emit("message", `${providerName} provider initialized successfully`);
|
|
1302
1338
|
// Enable tool execution for the provider using BaseProvider method
|
|
1303
1339
|
provider.setupToolExecutor({
|
|
1304
1340
|
customTools: this.getCustomTools(),
|
|
@@ -1393,6 +1429,9 @@ export class NeuroLink {
|
|
|
1393
1429
|
const conversationMessages = await getConversationMessages(this.conversationMemory, options);
|
|
1394
1430
|
const provider = await AIProviderFactory.createProvider(providerName, options.model, !options.disableTools, // Pass disableTools as inverse of enableMCP
|
|
1395
1431
|
this);
|
|
1432
|
+
// ADD: Emit connection events for successful provider creation (Bedrock-compatible)
|
|
1433
|
+
this.emitter.emit("connected");
|
|
1434
|
+
this.emitter.emit("message", `${providerName} provider initialized successfully`);
|
|
1396
1435
|
// Enable tool execution for direct provider generation using BaseProvider method
|
|
1397
1436
|
provider.setupToolExecutor({
|
|
1398
1437
|
customTools: this.getCustomTools(),
|
|
@@ -1454,7 +1493,7 @@ export class NeuroLink {
|
|
|
1454
1493
|
* Execute tools if available through centralized registry
|
|
1455
1494
|
* Simplified approach without domain detection - relies on tool registry
|
|
1456
1495
|
*/
|
|
1457
|
-
async detectAndExecuteTools(prompt,
|
|
1496
|
+
async detectAndExecuteTools(prompt, _domainType) {
|
|
1458
1497
|
const functionTag = "NeuroLink.detectAndExecuteTools";
|
|
1459
1498
|
try {
|
|
1460
1499
|
// Simplified: Just return original prompt without complex detection
|
|
@@ -1669,7 +1708,7 @@ export class NeuroLink {
|
|
|
1669
1708
|
global.gc();
|
|
1670
1709
|
return process.memoryUsage();
|
|
1671
1710
|
}
|
|
1672
|
-
catch (
|
|
1711
|
+
catch (_e) {
|
|
1673
1712
|
return null;
|
|
1674
1713
|
}
|
|
1675
1714
|
})()
|
|
@@ -1807,11 +1846,15 @@ export class NeuroLink {
|
|
|
1807
1846
|
cpuAfterValidation: process.cpuUsage(),
|
|
1808
1847
|
message: "EXHAUSTIVE validation success - proceeding with stream processing",
|
|
1809
1848
|
});
|
|
1810
|
-
// Emit stream start event
|
|
1849
|
+
// Emit stream start event (NeuroLink format - keep existing)
|
|
1811
1850
|
this.emitter.emit("stream:start", {
|
|
1812
1851
|
provider: options.provider || "auto",
|
|
1813
1852
|
timestamp: startTime,
|
|
1814
1853
|
});
|
|
1854
|
+
// ADD: Bedrock-compatible response:start event
|
|
1855
|
+
this.emitter.emit("response:start");
|
|
1856
|
+
// ADD: Bedrock-compatible message event
|
|
1857
|
+
this.emitter.emit("message", `Starting ${options.provider || "auto"} stream generation...`);
|
|
1815
1858
|
// Process factory configuration for streaming
|
|
1816
1859
|
const factoryResult = processFactoryOptions(options);
|
|
1817
1860
|
const streamingResult = processStreamingFactoryOptions(options);
|
|
@@ -1903,6 +1946,8 @@ export class NeuroLink {
|
|
|
1903
1946
|
// Ensure chunk has content property and it's a string
|
|
1904
1947
|
if (typeof chunk.content === "string") {
|
|
1905
1948
|
accumulatedContent += chunk.content;
|
|
1949
|
+
// ADD: Bedrock-compatible response:chunk event
|
|
1950
|
+
self.emitter.emit("response:chunk", chunk.content);
|
|
1906
1951
|
}
|
|
1907
1952
|
else if (chunk.content === undefined ||
|
|
1908
1953
|
chunk.content === null) {
|
|
@@ -1914,6 +1959,8 @@ export class NeuroLink {
|
|
|
1914
1959
|
const stringContent = String(chunk.content || "");
|
|
1915
1960
|
processedChunk = { ...chunk, content: stringContent };
|
|
1916
1961
|
accumulatedContent += stringContent;
|
|
1962
|
+
// ADD: Bedrock-compatible response:chunk event
|
|
1963
|
+
self.emitter.emit("response:chunk", stringContent);
|
|
1917
1964
|
}
|
|
1918
1965
|
}
|
|
1919
1966
|
else if (chunk === null || chunk === undefined) {
|
|
@@ -1950,11 +1997,16 @@ export class NeuroLink {
|
|
|
1950
1997
|
responseTime,
|
|
1951
1998
|
provider: providerName,
|
|
1952
1999
|
});
|
|
1953
|
-
// Emit stream completion event
|
|
2000
|
+
// Emit stream completion event (NeuroLink format - enhanced with content)
|
|
1954
2001
|
this.emitter.emit("stream:end", {
|
|
1955
2002
|
provider: providerName,
|
|
1956
2003
|
responseTime,
|
|
2004
|
+
result: { content: accumulatedContent }, // Enhanced: include accumulated content
|
|
1957
2005
|
});
|
|
2006
|
+
// ADD: Bedrock-compatible response:end event with full response
|
|
2007
|
+
this.emitter.emit("response:end", accumulatedContent);
|
|
2008
|
+
// ADD: Bedrock-compatible message event
|
|
2009
|
+
this.emitter.emit("message", `Stream completed in ${responseTime}ms (${accumulatedContent.length} chars)`);
|
|
1958
2010
|
// Convert to StreamResult format - Include analytics and evaluation from provider
|
|
1959
2011
|
return {
|
|
1960
2012
|
stream: processedStream,
|
|
@@ -1983,6 +2035,8 @@ export class NeuroLink {
|
|
|
1983
2035
|
};
|
|
1984
2036
|
}
|
|
1985
2037
|
catch (error) {
|
|
2038
|
+
// ADD: Error event emission for MCP streaming failure
|
|
2039
|
+
this.emitter.emit("error", error instanceof Error ? error : new Error(String(error)));
|
|
1986
2040
|
// Fall back to regular streaming if MCP fails
|
|
1987
2041
|
mcpLogger.warn(`[${functionTag}] MCP streaming failed, falling back to regular`, {
|
|
1988
2042
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -2018,6 +2072,8 @@ export class NeuroLink {
|
|
|
2018
2072
|
for await (const chunk of streamResult.stream) {
|
|
2019
2073
|
if (chunk && typeof chunk.content === "string") {
|
|
2020
2074
|
fallbackAccumulatedContent += chunk.content;
|
|
2075
|
+
// ADD: Bedrock-compatible response:chunk event for fallback
|
|
2076
|
+
self.emitter.emit("response:chunk", chunk.content);
|
|
2021
2077
|
}
|
|
2022
2078
|
yield chunk; // Preserve original streaming behavior
|
|
2023
2079
|
}
|
|
@@ -2045,12 +2101,17 @@ export class NeuroLink {
|
|
|
2045
2101
|
}
|
|
2046
2102
|
})(this);
|
|
2047
2103
|
const responseTime = Date.now() - startTime;
|
|
2048
|
-
// Emit stream completion event for fallback
|
|
2104
|
+
// Emit stream completion event for fallback (NeuroLink format - enhanced with content)
|
|
2049
2105
|
this.emitter.emit("stream:end", {
|
|
2050
2106
|
provider: providerName,
|
|
2051
2107
|
responseTime,
|
|
2052
2108
|
fallback: true,
|
|
2109
|
+
result: { content: fallbackAccumulatedContent }, // Enhanced: include accumulated content
|
|
2053
2110
|
});
|
|
2111
|
+
// ADD: Bedrock-compatible response:end event with full response
|
|
2112
|
+
this.emitter.emit("response:end", fallbackAccumulatedContent);
|
|
2113
|
+
// ADD: Bedrock-compatible message event
|
|
2114
|
+
this.emitter.emit("message", `Fallback stream completed in ${responseTime}ms (${fallbackAccumulatedContent.length} chars)`);
|
|
2054
2115
|
return {
|
|
2055
2116
|
stream: fallbackProcessedStream,
|
|
2056
2117
|
provider: providerName,
|
|
@@ -2271,7 +2332,7 @@ export class NeuroLink {
|
|
|
2271
2332
|
timestamp: Date.now(),
|
|
2272
2333
|
});
|
|
2273
2334
|
try {
|
|
2274
|
-
// --- Start:
|
|
2335
|
+
// --- Start: Enhanced Validation Logic with FlexibleToolValidator ---
|
|
2275
2336
|
if (!name || typeof name !== "string") {
|
|
2276
2337
|
throw new Error("Invalid tool name");
|
|
2277
2338
|
}
|
|
@@ -2281,55 +2342,36 @@ export class NeuroLink {
|
|
|
2281
2342
|
if (typeof tool.execute !== "function") {
|
|
2282
2343
|
throw new Error(`Tool '${name}' must have an execute method.`);
|
|
2283
2344
|
}
|
|
2284
|
-
//
|
|
2285
|
-
// Import validation functions synchronously - they are pure functions
|
|
2286
|
-
let validateTool;
|
|
2287
|
-
let isToolNameAvailable;
|
|
2288
|
-
let suggestToolNames;
|
|
2345
|
+
// Use FlexibleToolValidator for consistent validation across SDK and toolRegistry
|
|
2289
2346
|
try {
|
|
2290
|
-
|
|
2291
|
-
const
|
|
2292
|
-
|
|
2293
|
-
|
|
2347
|
+
const flexibleValidatorModule = require("./mcp/flexibleToolValidator.js");
|
|
2348
|
+
const FlexibleToolValidator = flexibleValidatorModule.FlexibleToolValidator;
|
|
2349
|
+
// Use the same validation logic as toolRegistry (static method)
|
|
2350
|
+
const validationResult = FlexibleToolValidator.validateToolName(name);
|
|
2351
|
+
if (!validationResult.isValid) {
|
|
2352
|
+
throw new Error(`Tool validation failed: ${validationResult.error}`);
|
|
2353
|
+
}
|
|
2294
2354
|
}
|
|
2295
2355
|
catch (error) {
|
|
2296
|
-
//
|
|
2297
|
-
logger.warn("
|
|
2356
|
+
// If FlexibleToolValidator import fails, use basic safety checks
|
|
2357
|
+
logger.warn("FlexibleToolValidator not available, using basic validation", {
|
|
2298
2358
|
error: error instanceof Error ? error.message : String(error),
|
|
2299
2359
|
});
|
|
2300
|
-
//
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
// Create a simplified tool object for validation
|
|
2312
|
-
const toolForValidation = {
|
|
2313
|
-
description: tool.description || "",
|
|
2314
|
-
execute: async (params) => {
|
|
2315
|
-
if (tool.execute) {
|
|
2316
|
-
const result = await tool.execute(params);
|
|
2317
|
-
return result;
|
|
2318
|
-
}
|
|
2319
|
-
return "";
|
|
2320
|
-
},
|
|
2321
|
-
parameters: tool.inputSchema,
|
|
2322
|
-
metadata: {
|
|
2323
|
-
category: "custom",
|
|
2324
|
-
},
|
|
2325
|
-
};
|
|
2326
|
-
// Use comprehensive validation logic
|
|
2327
|
-
try {
|
|
2328
|
-
validateTool(name, toolForValidation);
|
|
2329
|
-
}
|
|
2330
|
-
catch (error) {
|
|
2331
|
-
throw new Error(`Tool registration failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
2360
|
+
// Basic safety checks to prevent obvious issues
|
|
2361
|
+
if (name.trim() === "") {
|
|
2362
|
+
throw new Error("Tool name cannot be empty");
|
|
2363
|
+
}
|
|
2364
|
+
if (name.length > 100) {
|
|
2365
|
+
throw new Error("Tool name is too long (maximum 100 characters)");
|
|
2366
|
+
}
|
|
2367
|
+
// eslint-disable-next-line no-control-regex
|
|
2368
|
+
if (/[\x00-\x1F\x7F]/.test(name)) {
|
|
2369
|
+
throw new Error("Tool name contains invalid control characters");
|
|
2370
|
+
}
|
|
2332
2371
|
}
|
|
2372
|
+
// --- End: Enhanced Validation Logic ---
|
|
2373
|
+
// Tool object validation is now handled by FlexibleToolValidator above
|
|
2374
|
+
// Proceed with tool registration since validation passed
|
|
2333
2375
|
// SMART DEFAULTS: Use utility to eliminate boilerplate creation
|
|
2334
2376
|
const mcpServerInfo = createCustomToolServerInfo(name, tool);
|
|
2335
2377
|
// Register with toolRegistry using MCPServerInfo directly
|
|
@@ -2489,11 +2531,14 @@ export class NeuroLink {
|
|
|
2489
2531
|
: params,
|
|
2490
2532
|
hasExternalManager: !!this.externalServerManager,
|
|
2491
2533
|
});
|
|
2492
|
-
// Emit tool start event
|
|
2534
|
+
// Emit tool start event (NeuroLink format - keep existing)
|
|
2493
2535
|
this.emitter.emit("tool:start", {
|
|
2494
2536
|
toolName,
|
|
2495
2537
|
timestamp: executionStartTime,
|
|
2538
|
+
input: params, // Enhanced: add input parameters
|
|
2496
2539
|
});
|
|
2540
|
+
// ADD: Bedrock-compatible tool:start event (positional parameters)
|
|
2541
|
+
this.emitter.emit("tool:start", toolName, params);
|
|
2497
2542
|
// Set default options
|
|
2498
2543
|
const finalOptions = {
|
|
2499
2544
|
timeout: options?.timeout || 30000, // 30 second default timeout
|
|
@@ -2519,13 +2564,15 @@ export class NeuroLink {
|
|
|
2519
2564
|
});
|
|
2520
2565
|
}
|
|
2521
2566
|
const metrics = this.toolExecutionMetrics.get(toolName);
|
|
2522
|
-
metrics
|
|
2567
|
+
if (metrics) {
|
|
2568
|
+
metrics.totalExecutions++;
|
|
2569
|
+
}
|
|
2523
2570
|
try {
|
|
2524
2571
|
mcpLogger.debug(`[${functionTag}] Executing tool: ${toolName}`, {
|
|
2525
2572
|
toolName,
|
|
2526
2573
|
params,
|
|
2527
2574
|
options: finalOptions,
|
|
2528
|
-
circuitBreakerState: circuitBreaker
|
|
2575
|
+
circuitBreakerState: circuitBreaker?.getState(),
|
|
2529
2576
|
});
|
|
2530
2577
|
// Execute with circuit breaker, timeout, and retry logic
|
|
2531
2578
|
const result = await circuitBreaker.execute(async () => {
|
|
@@ -2546,12 +2593,14 @@ export class NeuroLink {
|
|
|
2546
2593
|
});
|
|
2547
2594
|
// Update success metrics
|
|
2548
2595
|
const executionTime = Date.now() - executionStartTime;
|
|
2549
|
-
metrics
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2596
|
+
if (metrics) {
|
|
2597
|
+
metrics.successfulExecutions++;
|
|
2598
|
+
metrics.lastExecutionTime = executionTime;
|
|
2599
|
+
metrics.averageExecutionTime =
|
|
2600
|
+
(metrics.averageExecutionTime * (metrics.successfulExecutions - 1) +
|
|
2601
|
+
executionTime) /
|
|
2602
|
+
metrics.successfulExecutions;
|
|
2603
|
+
}
|
|
2555
2604
|
// Track memory usage
|
|
2556
2605
|
const endMemory = MemoryManager.getMemoryUsageMB();
|
|
2557
2606
|
const memoryDelta = endMemory.heapUsed - startMemory.heapUsed;
|
|
@@ -2566,15 +2615,17 @@ export class NeuroLink {
|
|
|
2566
2615
|
toolName,
|
|
2567
2616
|
executionTime,
|
|
2568
2617
|
memoryDelta,
|
|
2569
|
-
circuitBreakerState: circuitBreaker
|
|
2618
|
+
circuitBreakerState: circuitBreaker?.getState(),
|
|
2570
2619
|
});
|
|
2571
2620
|
// Emit tool end event using the helper method
|
|
2572
|
-
this.emitToolEndEvent(toolName, executionStartTime, true);
|
|
2621
|
+
this.emitToolEndEvent(toolName, executionStartTime, true, result);
|
|
2573
2622
|
return result;
|
|
2574
2623
|
}
|
|
2575
2624
|
catch (error) {
|
|
2576
2625
|
// Update failure metrics
|
|
2577
|
-
metrics
|
|
2626
|
+
if (metrics) {
|
|
2627
|
+
metrics.failedExecutions++;
|
|
2628
|
+
}
|
|
2578
2629
|
const executionTime = Date.now() - executionStartTime;
|
|
2579
2630
|
// Create structured error
|
|
2580
2631
|
let structuredError;
|
|
@@ -2605,8 +2656,10 @@ export class NeuroLink {
|
|
|
2605
2656
|
else {
|
|
2606
2657
|
structuredError = ErrorFactory.toolExecutionFailed(toolName, new Error(String(error)));
|
|
2607
2658
|
}
|
|
2659
|
+
// ADD: Centralized error event emission
|
|
2660
|
+
this.emitter.emit("error", structuredError);
|
|
2608
2661
|
// Emit tool end event using the helper method
|
|
2609
|
-
this.emitToolEndEvent(toolName, executionStartTime, false);
|
|
2662
|
+
this.emitToolEndEvent(toolName, executionStartTime, false, undefined, structuredError);
|
|
2610
2663
|
// Add execution context to structured error
|
|
2611
2664
|
structuredError = new NeuroLinkError({
|
|
2612
2665
|
...structuredError,
|
|
@@ -2615,8 +2668,8 @@ export class NeuroLink {
|
|
|
2615
2668
|
executionTime,
|
|
2616
2669
|
params,
|
|
2617
2670
|
options: finalOptions,
|
|
2618
|
-
circuitBreakerState: circuitBreaker
|
|
2619
|
-
circuitBreakerFailures: circuitBreaker
|
|
2671
|
+
circuitBreakerState: circuitBreaker?.getState(),
|
|
2672
|
+
circuitBreakerFailures: circuitBreaker?.getFailureCount(),
|
|
2620
2673
|
metrics: { ...metrics },
|
|
2621
2674
|
},
|
|
2622
2675
|
});
|
|
@@ -2667,9 +2720,21 @@ export class NeuroLink {
|
|
|
2667
2720
|
userId: "neurolink-user",
|
|
2668
2721
|
};
|
|
2669
2722
|
const result = (await toolRegistry.executeTool(toolName, params, context));
|
|
2723
|
+
// ADD: Check if result indicates a failure and emit error event
|
|
2724
|
+
if (result &&
|
|
2725
|
+
typeof result === "object" &&
|
|
2726
|
+
"success" in result &&
|
|
2727
|
+
result.success === false) {
|
|
2728
|
+
const errorMessage = result.error || "Tool execution failed";
|
|
2729
|
+
const errorToEmit = new Error(errorMessage);
|
|
2730
|
+
this.emitter.emit("error", errorToEmit);
|
|
2731
|
+
}
|
|
2670
2732
|
return result;
|
|
2671
2733
|
}
|
|
2672
2734
|
catch (error) {
|
|
2735
|
+
// ADD: Emergency error event emission (fallback)
|
|
2736
|
+
const errorToEmit = error instanceof Error ? error : new Error(String(error));
|
|
2737
|
+
this.emitter.emit("error", errorToEmit);
|
|
2673
2738
|
// Check if tool was not found
|
|
2674
2739
|
if (error instanceof Error && error.message.includes("not found")) {
|
|
2675
2740
|
const availableTools = await this.getAllAvailableTools();
|
|
@@ -2841,6 +2906,9 @@ export class NeuroLink {
|
|
|
2841
2906
|
}
|
|
2842
2907
|
const { AIProviderFactory } = await import("./core/factory.js");
|
|
2843
2908
|
const { hasProviderEnvVars } = await import("./utils/providerUtils.js");
|
|
2909
|
+
// Keep references to prevent unused variable warnings
|
|
2910
|
+
void AIProviderFactory;
|
|
2911
|
+
void hasProviderEnvVars;
|
|
2844
2912
|
const providers = [
|
|
2845
2913
|
"openai",
|
|
2846
2914
|
"bedrock",
|
|
@@ -3103,7 +3171,7 @@ export class NeuroLink {
|
|
|
3103
3171
|
const inMemoryServers = this.getInMemoryServers();
|
|
3104
3172
|
if (inMemoryServers.has(serverId)) {
|
|
3105
3173
|
const serverInfo = inMemoryServers.get(serverId);
|
|
3106
|
-
return !!(serverInfo
|
|
3174
|
+
return !!(serverInfo?.tools && serverInfo.tools.length > 0);
|
|
3107
3175
|
}
|
|
3108
3176
|
// Test external MCP servers
|
|
3109
3177
|
const externalServer = this.externalServerManager.getServer(serverId);
|
|
@@ -3610,7 +3678,7 @@ export class NeuroLink {
|
|
|
3610
3678
|
* Convert JSON Schema to AI SDK compatible format
|
|
3611
3679
|
* For now, we'll skip schema validation and let the AI SDK handle parameters dynamically
|
|
3612
3680
|
*/
|
|
3613
|
-
convertJSONSchemaToAISDKFormat(
|
|
3681
|
+
convertJSONSchemaToAISDKFormat(_inputSchema) {
|
|
3614
3682
|
// The simplest approach: don't provide parameters schema
|
|
3615
3683
|
// This lets the AI SDK handle the tool without schema validation
|
|
3616
3684
|
// Tools will still work, they just won't have strict parameter validation
|
|
@@ -3,29 +3,70 @@ import { type LanguageModelV1 } from "ai";
|
|
|
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";
|
|
6
|
+
import { AWSCredentialProvider } from "./aws/credentialProvider.js";
|
|
7
|
+
import { BedrockRuntimeClient } from "@aws-sdk/client-bedrock-runtime";
|
|
8
|
+
import type { AWSCredentialConfig } from "../types/providers.js";
|
|
9
|
+
import type { NeuroLink } from "../neurolink.js";
|
|
6
10
|
/**
|
|
7
|
-
* Amazon Bedrock Provider
|
|
11
|
+
* Amazon Bedrock Provider v3 - Enhanced Authentication Implementation
|
|
8
12
|
*
|
|
9
|
-
*
|
|
13
|
+
* BEDROCK-MCP-CONNECTOR COMPATIBILITY: Complete AWS SDK credential chain support
|
|
10
14
|
*
|
|
11
15
|
* Features:
|
|
12
16
|
* - Extends BaseProvider for shared functionality
|
|
13
|
-
* -
|
|
14
|
-
* -
|
|
15
|
-
* -
|
|
17
|
+
* - AWS SDK v3 defaultProvider credential chain (9 sources)
|
|
18
|
+
* - Dual access: AI SDK + Direct AWS SDK BedrockRuntimeClient
|
|
19
|
+
* - Full backward compatibility with existing configurations
|
|
16
20
|
* - Enhanced error handling with setup guidance
|
|
21
|
+
* - Bedrock-MCP-Connector compatible authentication patterns
|
|
17
22
|
*/
|
|
18
23
|
export declare class AmazonBedrockProvider extends BaseProvider {
|
|
24
|
+
private awsCredentialProvider;
|
|
25
|
+
private bedrockClient;
|
|
19
26
|
private bedrock;
|
|
20
27
|
private model;
|
|
21
|
-
constructor(modelName?: string);
|
|
28
|
+
constructor(modelName?: string, credentialConfig?: AWSCredentialConfig, neurolink?: NeuroLink);
|
|
29
|
+
/**
|
|
30
|
+
* Legacy AWS configuration for backward compatibility
|
|
31
|
+
*/
|
|
32
|
+
private createLegacyAWSConfig;
|
|
22
33
|
protected getProviderName(): AIProviderName;
|
|
23
34
|
protected getDefaultModel(): string;
|
|
24
35
|
/**
|
|
25
36
|
* Returns the Vercel AI SDK model instance for AWS Bedrock
|
|
26
37
|
*/
|
|
27
38
|
protected getAISDKModel(): LanguageModelV1;
|
|
39
|
+
/**
|
|
40
|
+
* Get AWS SDK BedrockRuntimeClient for direct access (Bedrock-MCP-Connector compatibility)
|
|
41
|
+
* This provides the same direct AWS SDK access that Bedrock-MCP-Connector uses
|
|
42
|
+
*/
|
|
43
|
+
getBedrockClient(): BedrockRuntimeClient;
|
|
44
|
+
/**
|
|
45
|
+
* Get AWS SDK BedrockRuntimeClient with proxy support ensured
|
|
46
|
+
* Use this method when proxy support is critical for the operation
|
|
47
|
+
*/
|
|
48
|
+
getBedrockClientWithProxy(): Promise<BedrockRuntimeClient>;
|
|
49
|
+
/**
|
|
50
|
+
* Get AWS credential provider for advanced credential management
|
|
51
|
+
*/
|
|
52
|
+
getCredentialProvider(): AWSCredentialProvider;
|
|
53
|
+
/**
|
|
54
|
+
* Ensure proxy support is configured for AWS SDK client if needed
|
|
55
|
+
*/
|
|
56
|
+
private ensureProxySupport;
|
|
57
|
+
/**
|
|
58
|
+
* Test AWS credentials and Bedrock connectivity
|
|
59
|
+
* Useful for debugging authentication issues
|
|
60
|
+
*/
|
|
61
|
+
testConnectivity(): Promise<{
|
|
62
|
+
credentialsValid: boolean;
|
|
63
|
+
bedrockAccessible: boolean;
|
|
64
|
+
credentialSource: string;
|
|
65
|
+
error?: string;
|
|
66
|
+
responseTime?: number;
|
|
67
|
+
}>;
|
|
28
68
|
protected executeStream(options: StreamOptions, _analysisSchema?: ZodUnknownSchema): Promise<StreamResult>;
|
|
69
|
+
protected handleStreamError(error: unknown): Error;
|
|
29
70
|
protected handleProviderError(error: unknown): Error;
|
|
30
71
|
}
|
|
31
72
|
export default AmazonBedrockProvider;
|