@juspay/neurolink 9.14.0 → 9.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +15 -15
- package/dist/adapters/video/videoAnalyzer.d.ts +1 -1
- package/dist/adapters/video/videoAnalyzer.js +10 -8
- package/dist/auth/anthropicOAuth.d.ts +377 -0
- package/dist/auth/anthropicOAuth.js +914 -0
- package/dist/auth/index.d.ts +20 -0
- package/dist/auth/index.js +29 -0
- package/dist/auth/tokenStore.d.ts +225 -0
- package/dist/auth/tokenStore.js +521 -0
- package/dist/cli/commands/auth.d.ts +50 -0
- package/dist/cli/commands/auth.js +1115 -0
- package/dist/cli/commands/setup-anthropic.js +1 -14
- package/dist/cli/commands/setup-azure.js +1 -12
- package/dist/cli/commands/setup-bedrock.js +1 -9
- package/dist/cli/commands/setup-google-ai.js +1 -12
- package/dist/cli/commands/setup-openai.js +1 -14
- package/dist/cli/commands/workflow.d.ts +27 -0
- package/dist/cli/commands/workflow.js +216 -0
- package/dist/cli/factories/authCommandFactory.d.ts +52 -0
- package/dist/cli/factories/authCommandFactory.js +146 -0
- package/dist/cli/factories/commandFactory.d.ts +6 -0
- package/dist/cli/factories/commandFactory.js +171 -22
- package/dist/cli/index.js +0 -1
- package/dist/cli/parser.js +14 -2
- package/dist/cli/utils/maskCredential.d.ts +11 -0
- package/dist/cli/utils/maskCredential.js +23 -0
- package/dist/constants/contextWindows.js +107 -16
- package/dist/constants/enums.d.ts +119 -15
- package/dist/constants/enums.js +182 -22
- package/dist/constants/index.d.ts +3 -1
- package/dist/constants/index.js +11 -1
- package/dist/context/budgetChecker.js +1 -1
- package/dist/context/contextCompactor.js +31 -4
- package/dist/context/emergencyTruncation.d.ts +21 -0
- package/dist/context/emergencyTruncation.js +88 -0
- package/dist/context/errorDetection.d.ts +16 -0
- package/dist/context/errorDetection.js +48 -1
- package/dist/context/errors.d.ts +19 -0
- package/dist/context/errors.js +21 -0
- package/dist/context/stages/slidingWindowTruncator.d.ts +6 -0
- package/dist/context/stages/slidingWindowTruncator.js +159 -24
- package/dist/core/baseProvider.js +306 -200
- package/dist/core/conversationMemoryManager.js +104 -61
- package/dist/core/evaluationProviders.js +16 -33
- package/dist/core/factory.js +237 -164
- package/dist/core/modules/GenerationHandler.js +175 -116
- package/dist/core/modules/MessageBuilder.js +222 -170
- package/dist/core/modules/StreamHandler.d.ts +1 -0
- package/dist/core/modules/StreamHandler.js +95 -27
- package/dist/core/modules/TelemetryHandler.d.ts +10 -1
- package/dist/core/modules/TelemetryHandler.js +25 -7
- package/dist/core/modules/ToolsManager.js +115 -191
- package/dist/core/redisConversationMemoryManager.js +418 -282
- package/dist/factories/providerRegistry.d.ts +5 -0
- package/dist/factories/providerRegistry.js +20 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.js +4 -2
- package/dist/lib/adapters/video/videoAnalyzer.d.ts +1 -1
- package/dist/lib/adapters/video/videoAnalyzer.js +10 -8
- package/dist/lib/auth/anthropicOAuth.d.ts +377 -0
- package/dist/lib/auth/anthropicOAuth.js +915 -0
- package/dist/lib/auth/index.d.ts +20 -0
- package/dist/lib/auth/index.js +30 -0
- package/dist/lib/auth/tokenStore.d.ts +225 -0
- package/dist/lib/auth/tokenStore.js +522 -0
- package/dist/lib/constants/contextWindows.js +107 -16
- package/dist/lib/constants/enums.d.ts +119 -15
- package/dist/lib/constants/enums.js +182 -22
- package/dist/lib/constants/index.d.ts +3 -1
- package/dist/lib/constants/index.js +11 -1
- package/dist/lib/context/budgetChecker.js +1 -1
- package/dist/lib/context/contextCompactor.js +31 -4
- package/dist/lib/context/emergencyTruncation.d.ts +21 -0
- package/dist/lib/context/emergencyTruncation.js +89 -0
- package/dist/lib/context/errorDetection.d.ts +16 -0
- package/dist/lib/context/errorDetection.js +48 -1
- package/dist/lib/context/errors.d.ts +19 -0
- package/dist/lib/context/errors.js +22 -0
- package/dist/lib/context/stages/slidingWindowTruncator.d.ts +6 -0
- package/dist/lib/context/stages/slidingWindowTruncator.js +159 -24
- package/dist/lib/core/baseProvider.js +306 -200
- package/dist/lib/core/conversationMemoryManager.js +104 -61
- package/dist/lib/core/evaluationProviders.js +16 -33
- package/dist/lib/core/factory.js +237 -164
- package/dist/lib/core/modules/GenerationHandler.js +175 -116
- package/dist/lib/core/modules/MessageBuilder.js +222 -170
- package/dist/lib/core/modules/StreamHandler.d.ts +1 -0
- package/dist/lib/core/modules/StreamHandler.js +95 -27
- package/dist/lib/core/modules/TelemetryHandler.d.ts +10 -1
- package/dist/lib/core/modules/TelemetryHandler.js +25 -7
- package/dist/lib/core/modules/ToolsManager.js +115 -191
- package/dist/lib/core/redisConversationMemoryManager.js +418 -282
- package/dist/lib/factories/providerRegistry.d.ts +5 -0
- package/dist/lib/factories/providerRegistry.js +20 -2
- package/dist/lib/index.d.ts +3 -3
- package/dist/lib/index.js +4 -2
- package/dist/lib/mcp/externalServerManager.js +66 -0
- package/dist/lib/mcp/mcpCircuitBreaker.js +24 -0
- package/dist/lib/mcp/mcpClientFactory.js +16 -0
- package/dist/lib/mcp/toolDiscoveryService.js +32 -6
- package/dist/lib/mcp/toolRegistry.js +193 -123
- package/dist/lib/models/anthropicModels.d.ts +267 -0
- package/dist/lib/models/anthropicModels.js +528 -0
- package/dist/lib/neurolink.d.ts +6 -0
- package/dist/lib/neurolink.js +1162 -646
- package/dist/lib/providers/amazonBedrock.d.ts +1 -1
- package/dist/lib/providers/amazonBedrock.js +521 -319
- package/dist/lib/providers/anthropic.d.ts +123 -2
- package/dist/lib/providers/anthropic.js +873 -27
- package/dist/lib/providers/anthropicBaseProvider.js +77 -17
- package/dist/lib/providers/googleAiStudio.d.ts +1 -1
- package/dist/lib/providers/googleAiStudio.js +292 -227
- package/dist/lib/providers/googleVertex.d.ts +36 -1
- package/dist/lib/providers/googleVertex.js +553 -260
- package/dist/lib/providers/ollama.js +329 -278
- package/dist/lib/providers/openAI.js +77 -19
- package/dist/lib/providers/sagemaker/parsers.js +3 -3
- package/dist/lib/providers/sagemaker/streaming.js +3 -3
- package/dist/lib/proxy/proxyFetch.js +81 -48
- package/dist/lib/rag/ChunkerFactory.js +1 -1
- package/dist/lib/rag/chunkers/MarkdownChunker.d.ts +22 -0
- package/dist/lib/rag/chunkers/MarkdownChunker.js +213 -9
- package/dist/lib/rag/chunking/markdownChunker.d.ts +16 -0
- package/dist/lib/rag/chunking/markdownChunker.js +174 -2
- package/dist/lib/rag/pipeline/contextAssembly.js +2 -1
- package/dist/lib/rag/ragIntegration.d.ts +18 -1
- package/dist/lib/rag/ragIntegration.js +94 -14
- package/dist/lib/rag/retrieval/vectorQueryTool.js +21 -4
- package/dist/lib/server/abstract/baseServerAdapter.js +4 -1
- package/dist/lib/server/adapters/fastifyAdapter.js +35 -30
- package/dist/lib/services/server/ai/observability/instrumentation.d.ts +32 -0
- package/dist/lib/services/server/ai/observability/instrumentation.js +39 -0
- package/dist/lib/telemetry/attributes.d.ts +52 -0
- package/dist/lib/telemetry/attributes.js +61 -0
- package/dist/lib/telemetry/index.d.ts +3 -0
- package/dist/lib/telemetry/index.js +3 -0
- package/dist/lib/telemetry/telemetryService.d.ts +6 -0
- package/dist/lib/telemetry/telemetryService.js +6 -0
- package/dist/lib/telemetry/tracers.d.ts +15 -0
- package/dist/lib/telemetry/tracers.js +17 -0
- package/dist/lib/telemetry/withSpan.d.ts +9 -0
- package/dist/lib/telemetry/withSpan.js +35 -0
- package/dist/lib/types/contextTypes.d.ts +10 -0
- package/dist/lib/types/errors.d.ts +62 -0
- package/dist/lib/types/errors.js +107 -0
- package/dist/lib/types/index.d.ts +2 -1
- package/dist/lib/types/index.js +2 -0
- package/dist/lib/types/providers.d.ts +107 -0
- package/dist/lib/types/providers.js +69 -0
- package/dist/lib/types/streamTypes.d.ts +14 -0
- package/dist/lib/types/subscriptionTypes.d.ts +893 -0
- package/dist/lib/types/subscriptionTypes.js +8 -0
- package/dist/lib/utils/conversationMemory.js +121 -82
- package/dist/lib/utils/logger.d.ts +5 -0
- package/dist/lib/utils/logger.js +50 -2
- package/dist/lib/utils/messageBuilder.js +22 -42
- package/dist/lib/utils/modelDetection.js +3 -3
- package/dist/lib/utils/providerConfig.d.ts +167 -0
- package/dist/lib/utils/providerConfig.js +619 -9
- package/dist/lib/utils/providerRetry.d.ts +41 -0
- package/dist/lib/utils/providerRetry.js +114 -0
- package/dist/lib/utils/retryability.d.ts +14 -0
- package/dist/lib/utils/retryability.js +23 -0
- package/dist/lib/utils/sanitizers/svg.js +4 -5
- package/dist/lib/utils/tokenEstimation.d.ts +11 -1
- package/dist/lib/utils/tokenEstimation.js +19 -4
- package/dist/lib/utils/videoAnalysisProcessor.js +7 -3
- package/dist/mcp/externalServerManager.js +66 -0
- package/dist/mcp/mcpCircuitBreaker.js +24 -0
- package/dist/mcp/mcpClientFactory.js +16 -0
- package/dist/mcp/toolDiscoveryService.js +32 -6
- package/dist/mcp/toolRegistry.js +193 -123
- package/dist/models/anthropicModels.d.ts +267 -0
- package/dist/models/anthropicModels.js +527 -0
- package/dist/neurolink.d.ts +6 -0
- package/dist/neurolink.js +1162 -646
- package/dist/providers/amazonBedrock.d.ts +1 -1
- package/dist/providers/amazonBedrock.js +521 -319
- package/dist/providers/anthropic.d.ts +123 -2
- package/dist/providers/anthropic.js +873 -27
- package/dist/providers/anthropicBaseProvider.js +77 -17
- package/dist/providers/googleAiStudio.d.ts +1 -1
- package/dist/providers/googleAiStudio.js +292 -227
- package/dist/providers/googleVertex.d.ts +36 -1
- package/dist/providers/googleVertex.js +553 -260
- package/dist/providers/ollama.js +329 -278
- package/dist/providers/openAI.js +77 -19
- package/dist/providers/sagemaker/parsers.js +3 -3
- package/dist/providers/sagemaker/streaming.js +3 -3
- package/dist/proxy/proxyFetch.js +81 -48
- package/dist/rag/ChunkerFactory.js +1 -1
- package/dist/rag/chunkers/MarkdownChunker.d.ts +22 -0
- package/dist/rag/chunkers/MarkdownChunker.js +213 -9
- package/dist/rag/chunking/markdownChunker.d.ts +16 -0
- package/dist/rag/chunking/markdownChunker.js +174 -2
- package/dist/rag/pipeline/contextAssembly.js +2 -1
- package/dist/rag/ragIntegration.d.ts +18 -1
- package/dist/rag/ragIntegration.js +94 -14
- package/dist/rag/retrieval/vectorQueryTool.js +21 -4
- package/dist/server/abstract/baseServerAdapter.js +4 -1
- package/dist/server/adapters/fastifyAdapter.js +35 -30
- package/dist/services/server/ai/observability/instrumentation.d.ts +32 -0
- package/dist/services/server/ai/observability/instrumentation.js +39 -0
- package/dist/telemetry/attributes.d.ts +52 -0
- package/dist/telemetry/attributes.js +60 -0
- package/dist/telemetry/index.d.ts +3 -0
- package/dist/telemetry/index.js +3 -0
- package/dist/telemetry/telemetryService.d.ts +6 -0
- package/dist/telemetry/telemetryService.js +6 -0
- package/dist/telemetry/tracers.d.ts +15 -0
- package/dist/telemetry/tracers.js +16 -0
- package/dist/telemetry/withSpan.d.ts +9 -0
- package/dist/telemetry/withSpan.js +34 -0
- package/dist/types/contextTypes.d.ts +10 -0
- package/dist/types/errors.d.ts +62 -0
- package/dist/types/errors.js +107 -0
- package/dist/types/index.d.ts +2 -1
- package/dist/types/index.js +2 -0
- package/dist/types/providers.d.ts +107 -0
- package/dist/types/providers.js +69 -0
- package/dist/types/streamTypes.d.ts +14 -0
- package/dist/types/subscriptionTypes.d.ts +893 -0
- package/dist/types/subscriptionTypes.js +7 -0
- package/dist/utils/conversationMemory.js +121 -82
- package/dist/utils/logger.d.ts +5 -0
- package/dist/utils/logger.js +50 -2
- package/dist/utils/messageBuilder.js +22 -42
- package/dist/utils/modelDetection.js +3 -3
- package/dist/utils/providerConfig.d.ts +167 -0
- package/dist/utils/providerConfig.js +619 -9
- package/dist/utils/providerRetry.d.ts +41 -0
- package/dist/utils/providerRetry.js +113 -0
- package/dist/utils/retryability.d.ts +14 -0
- package/dist/utils/retryability.js +22 -0
- package/dist/utils/sanitizers/svg.js +4 -5
- package/dist/utils/tokenEstimation.d.ts +11 -1
- package/dist/utils/tokenEstimation.js +19 -4
- package/dist/utils/videoAnalysisProcessor.js +7 -3
- package/dist/workflow/config.d.ts +26 -26
- package/package.json +2 -1
|
@@ -15,9 +15,10 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { nanoid } from "nanoid";
|
|
17
17
|
import { logger } from "../../utils/logger.js";
|
|
18
|
-
import {
|
|
18
|
+
import { recordProviderPerformanceFromMetrics } from "../evaluationProviders.js";
|
|
19
19
|
import { modelConfig } from "../modelConfiguration.js";
|
|
20
20
|
import { TelemetryService } from "../../telemetry/telemetryService.js";
|
|
21
|
+
import { calculateCost, hasPricing } from "../../utils/pricing.js";
|
|
21
22
|
/**
|
|
22
23
|
* TelemetryHandler class - Handles analytics and telemetry for AI providers
|
|
23
24
|
*/
|
|
@@ -82,12 +83,10 @@ export class TelemetryHandler {
|
|
|
82
83
|
});
|
|
83
84
|
// Wire TelemetryService metrics so OTEL counters/histograms are populated
|
|
84
85
|
TelemetryService.getInstance().recordAIRequest(this.providerName, this.modelName, usage?.totalTokens || 0, responseTime, actualCost > 0 ? actualCost : undefined);
|
|
85
|
-
|
|
86
|
-
logger.debug(`🚀 Performance recorded for ${this.providerName}:`, {
|
|
86
|
+
logger.debug(`Performance recorded for ${this.providerName}`, {
|
|
87
87
|
responseTime: `${responseTime}ms`,
|
|
88
88
|
tokens: usage?.totalTokens || 0,
|
|
89
89
|
estimatedCost: `$${actualCost.toFixed(6)}`,
|
|
90
|
-
recommendedSpeedProvider: optimizedProvider?.provider || "none",
|
|
91
90
|
});
|
|
92
91
|
}
|
|
93
92
|
catch (perfError) {
|
|
@@ -95,16 +94,35 @@ export class TelemetryHandler {
|
|
|
95
94
|
}
|
|
96
95
|
}
|
|
97
96
|
/**
|
|
98
|
-
* Calculate actual cost based on token usage and provider configuration
|
|
97
|
+
* Calculate actual cost based on token usage and provider configuration.
|
|
98
|
+
*
|
|
99
|
+
* Uses the per-model pricing table first (which has accurate rates for
|
|
100
|
+
* specific models like Claude on Vertex AI), then falls back to the
|
|
101
|
+
* provider-level default cost from modelConfiguration.
|
|
102
|
+
*
|
|
103
|
+
* Previously this only used modelConfig.getCostInfo() which returns
|
|
104
|
+
* provider-level defaults (e.g. Gemini rates for the "vertex" provider),
|
|
105
|
+
* causing a ~1,780x under-estimate when the actual model was Claude Sonnet
|
|
106
|
+
* on Vertex AI ($0.000060 vs $0.106895 for the same request).
|
|
99
107
|
*/
|
|
100
108
|
async calculateActualCost(usage) {
|
|
101
109
|
try {
|
|
110
|
+
const promptTokens = usage?.promptTokens || 0;
|
|
111
|
+
const completionTokens = usage?.completionTokens || 0;
|
|
112
|
+
// Try the per-model pricing table first (includes correct rates for
|
|
113
|
+
// Claude on Vertex, cache token rates, etc.)
|
|
114
|
+
if (hasPricing(this.providerName, this.modelName)) {
|
|
115
|
+
return calculateCost(this.providerName, this.modelName, {
|
|
116
|
+
input: promptTokens,
|
|
117
|
+
output: completionTokens,
|
|
118
|
+
total: promptTokens + completionTokens,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
// Fall back to provider-level default cost from configuration system
|
|
102
122
|
const costInfo = modelConfig.getCostInfo(this.providerName, this.modelName);
|
|
103
123
|
if (!costInfo) {
|
|
104
124
|
return 0; // No cost info available
|
|
105
125
|
}
|
|
106
|
-
const promptTokens = usage?.promptTokens || 0;
|
|
107
|
-
const completionTokens = usage?.completionTokens || 0;
|
|
108
126
|
// Calculate cost per 1K tokens
|
|
109
127
|
const inputCost = (promptTokens / 1000) * costInfo.input;
|
|
110
128
|
const outputCost = (completionTokens / 1000) * costInfo.output;
|
|
@@ -16,8 +16,10 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import { tool as createAISDKTool, jsonSchema } from "ai";
|
|
18
18
|
import { z } from "zod";
|
|
19
|
+
import { tracers, ATTR, withSpan } from "../../telemetry/index.js";
|
|
20
|
+
import { SpanStatusCode } from "@opentelemetry/api";
|
|
19
21
|
import { logger } from "../../utils/logger.js";
|
|
20
|
-
import {
|
|
22
|
+
import { getKeyCount } from "../../utils/transformationUtils.js";
|
|
21
23
|
import { convertJsonSchemaToZod } from "../../utils/schemaConversion.js";
|
|
22
24
|
/**
|
|
23
25
|
* ToolsManager class - Handles all tool management operations
|
|
@@ -54,39 +56,88 @@ export class ToolsManager {
|
|
|
54
56
|
* @param functionTag - Function name for logging
|
|
55
57
|
*/
|
|
56
58
|
setupToolExecutor(sdk, functionTag) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
availableCustomTools: sdk.customTools.size,
|
|
63
|
-
customToolsStored: !!this.customTools,
|
|
64
|
-
toolExecutorStored: !!this.toolExecutor,
|
|
59
|
+
const span = tracers.sdk.startSpan("neurolink.tools.register", {
|
|
60
|
+
attributes: {
|
|
61
|
+
[ATTR.NL_PROVIDER]: this.providerName,
|
|
62
|
+
"tools.custom_count": sdk.customTools.size,
|
|
63
|
+
},
|
|
65
64
|
});
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
try {
|
|
66
|
+
// Store custom tools for use in getAllTools()
|
|
67
|
+
this.customTools = sdk.customTools;
|
|
68
|
+
this.toolExecutor = sdk.executeTool;
|
|
69
|
+
logger.debug(`[${functionTag}] Setting up tool executor for provider`, {
|
|
70
|
+
providerName: this.providerName,
|
|
71
|
+
availableCustomTools: sdk.customTools.size,
|
|
72
|
+
customToolsStored: !!this.customTools,
|
|
73
|
+
toolExecutorStored: !!this.toolExecutor,
|
|
74
|
+
});
|
|
75
|
+
// Note: Tool execution will be handled through getAllTools() -> AI SDK tools
|
|
76
|
+
// The custom tools are converted to AI SDK format in getAllTools() method
|
|
77
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
span.setStatus({
|
|
81
|
+
code: SpanStatusCode.ERROR,
|
|
82
|
+
message: error instanceof Error ? error.message : String(error),
|
|
83
|
+
});
|
|
84
|
+
if (error instanceof Error) {
|
|
85
|
+
span.recordException(error);
|
|
86
|
+
}
|
|
87
|
+
throw error;
|
|
88
|
+
}
|
|
89
|
+
finally {
|
|
90
|
+
span.end();
|
|
91
|
+
}
|
|
68
92
|
}
|
|
69
93
|
/**
|
|
70
94
|
* Get all available tools - direct tools are ALWAYS available
|
|
71
95
|
* MCP tools are added when available (without blocking)
|
|
72
96
|
*/
|
|
73
97
|
async getAllTools() {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
98
|
+
return withSpan({
|
|
99
|
+
name: "neurolink.tools.getAll",
|
|
100
|
+
tracer: tracers.sdk,
|
|
101
|
+
attributes: {
|
|
102
|
+
[ATTR.NL_PROVIDER]: this.providerName,
|
|
103
|
+
},
|
|
104
|
+
}, async (span) => {
|
|
105
|
+
// Start with wrapped direct tools that emit events
|
|
106
|
+
const tools = {};
|
|
107
|
+
// Wrap direct tools with event emission
|
|
108
|
+
await this.processDirectTools(tools);
|
|
109
|
+
const directCount = Object.keys(tools).length;
|
|
110
|
+
span.setAttribute("tools.direct_count", directCount);
|
|
111
|
+
logger.debug(`[ToolsManager] getAllTools called for ${this.providerName}`, {
|
|
112
|
+
directToolsCount: getKeyCount(this.directTools),
|
|
113
|
+
});
|
|
114
|
+
// Process all tool types using dedicated helper methods
|
|
115
|
+
await this.processCustomTools(tools);
|
|
116
|
+
const customCount = Object.keys(tools).length - directCount;
|
|
117
|
+
span.setAttribute("tools.custom_count", customCount);
|
|
118
|
+
await this.processExternalMCPTools(tools);
|
|
119
|
+
const externalCount = Object.keys(tools).length - directCount - customCount;
|
|
120
|
+
span.setAttribute("tools.external_mcp_count", externalCount);
|
|
121
|
+
await this.processMCPTools(tools);
|
|
122
|
+
const totalCount = Object.keys(tools).length;
|
|
123
|
+
span.setAttribute(ATTR.NL_TOOL_COUNT, totalCount);
|
|
124
|
+
// Record tool names for debugging (truncated)
|
|
125
|
+
const toolNames = Object.keys(tools);
|
|
126
|
+
span.setAttribute("tools.names", toolNames.slice(0, 20).join(",") +
|
|
127
|
+
(toolNames.length > 20 ? `...+${toolNames.length - 20}` : ""));
|
|
128
|
+
// Log a compact summary instead of full tool list
|
|
129
|
+
logger.debug(`[ToolsManager] getAllTools complete: ${toolNames.length} tools available`, {
|
|
130
|
+
provider: this.providerName,
|
|
131
|
+
toolCount: toolNames.length,
|
|
132
|
+
toolNames: toolNames.length <= 10
|
|
133
|
+
? toolNames
|
|
134
|
+
: [
|
|
135
|
+
...toolNames.slice(0, 10),
|
|
136
|
+
`... and ${toolNames.length - 10} more`,
|
|
137
|
+
],
|
|
138
|
+
});
|
|
139
|
+
return tools;
|
|
82
140
|
});
|
|
83
|
-
logger.debug(`[ToolsManager] Direct tools: ${getKeysAsString(this.directTools)}`);
|
|
84
|
-
// Process all tool types using dedicated helper methods
|
|
85
|
-
await this.processCustomTools(tools);
|
|
86
|
-
await this.processExternalMCPTools(tools);
|
|
87
|
-
await this.processMCPTools(tools);
|
|
88
|
-
logger.debug(`[ToolsManager] getAllTools returning tools: ${getKeysAsString(tools)}`);
|
|
89
|
-
return tools;
|
|
90
141
|
}
|
|
91
142
|
/**
|
|
92
143
|
* Get direct tools (built-in agent tools)
|
|
@@ -113,17 +164,8 @@ export class ToolsManager {
|
|
|
113
164
|
if (!this.directTools || Object.keys(this.directTools).length === 0) {
|
|
114
165
|
return;
|
|
115
166
|
}
|
|
116
|
-
logger.debug(`Loading ${Object.keys(this.directTools).length} direct tools
|
|
167
|
+
logger.debug(`[ToolsManager] Loading ${Object.keys(this.directTools).length} direct tools`);
|
|
117
168
|
for (const [toolName, directTool] of Object.entries(this.directTools)) {
|
|
118
|
-
logger.debug(`Processing direct tool: ${toolName}`, {
|
|
119
|
-
toolName,
|
|
120
|
-
hasExecute: directTool &&
|
|
121
|
-
typeof directTool === "object" &&
|
|
122
|
-
"execute" in directTool,
|
|
123
|
-
hasDescription: directTool &&
|
|
124
|
-
typeof directTool === "object" &&
|
|
125
|
-
"description" in directTool,
|
|
126
|
-
});
|
|
127
169
|
// Wrap the direct tool's execute function with event emission
|
|
128
170
|
if (directTool &&
|
|
129
171
|
typeof directTool === "object" &&
|
|
@@ -137,11 +179,6 @@ export class ToolsManager {
|
|
|
137
179
|
if (this.neurolink?.getEventEmitter) {
|
|
138
180
|
const emitter = this.neurolink.getEventEmitter();
|
|
139
181
|
emitter.emit("tool:start", { tool: toolName, input: params });
|
|
140
|
-
logger.debug(`Direct tool:start event emitted for ${toolName}`, {
|
|
141
|
-
toolName,
|
|
142
|
-
input: params,
|
|
143
|
-
hasEmitter: !!emitter,
|
|
144
|
-
});
|
|
145
182
|
}
|
|
146
183
|
try {
|
|
147
184
|
const result = await originalExecute(params);
|
|
@@ -149,13 +186,6 @@ export class ToolsManager {
|
|
|
149
186
|
if (this.neurolink?.getEventEmitter) {
|
|
150
187
|
const emitter = this.neurolink.getEventEmitter();
|
|
151
188
|
emitter.emit("tool:end", { tool: toolName, result });
|
|
152
|
-
logger.debug(`Direct tool:end event emitted for ${toolName}`, {
|
|
153
|
-
toolName,
|
|
154
|
-
result: typeof result === "string"
|
|
155
|
-
? result.substring(0, 100)
|
|
156
|
-
: JSON.stringify(result).substring(0, 100),
|
|
157
|
-
hasEmitter: !!emitter,
|
|
158
|
-
});
|
|
159
189
|
}
|
|
160
190
|
return result;
|
|
161
191
|
}
|
|
@@ -165,11 +195,6 @@ export class ToolsManager {
|
|
|
165
195
|
const emitter = this.neurolink.getEventEmitter();
|
|
166
196
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
167
197
|
emitter.emit("tool:end", { tool: toolName, error: errorMsg });
|
|
168
|
-
logger.debug(`Direct tool:end error event emitted for ${toolName}`, {
|
|
169
|
-
toolName,
|
|
170
|
-
error: errorMsg,
|
|
171
|
-
hasEmitter: !!emitter,
|
|
172
|
-
});
|
|
173
198
|
}
|
|
174
199
|
throw error;
|
|
175
200
|
}
|
|
@@ -181,9 +206,7 @@ export class ToolsManager {
|
|
|
181
206
|
tools[toolName] = directTool;
|
|
182
207
|
}
|
|
183
208
|
}
|
|
184
|
-
|
|
185
|
-
directToolsProcessed: Object.keys(this.directTools).length,
|
|
186
|
-
});
|
|
209
|
+
// Direct tools processing complete — count already logged at start
|
|
187
210
|
}
|
|
188
211
|
/**
|
|
189
212
|
* Process custom tools from setupToolExecutor
|
|
@@ -194,11 +217,6 @@ export class ToolsManager {
|
|
|
194
217
|
}
|
|
195
218
|
logger.debug(`[ToolsManager] Loading ${this.customTools.size} custom tools from setupToolExecutor`);
|
|
196
219
|
for (const [toolName, toolDef] of this.customTools.entries()) {
|
|
197
|
-
logger.debug(`Processing custom tool: ${toolName}`, {
|
|
198
|
-
toolDef: typeof toolDef,
|
|
199
|
-
hasExecute: toolDef && typeof toolDef === "object" && "execute" in toolDef,
|
|
200
|
-
hasName: toolDef && typeof toolDef === "object" && "name" in toolDef,
|
|
201
|
-
});
|
|
202
220
|
// Validate tool definition has required execute function
|
|
203
221
|
const toolInfo = toolDef ||
|
|
204
222
|
{};
|
|
@@ -209,9 +227,7 @@ export class ToolsManager {
|
|
|
209
227
|
}
|
|
210
228
|
}
|
|
211
229
|
}
|
|
212
|
-
|
|
213
|
-
customToolsProcessed: this.customTools.size,
|
|
214
|
-
});
|
|
230
|
+
// Custom tools processing complete — count already logged at start
|
|
215
231
|
}
|
|
216
232
|
/**
|
|
217
233
|
* Process MCP tools integration
|
|
@@ -238,26 +254,21 @@ export class ToolsManager {
|
|
|
238
254
|
async processExternalMCPTools(tools) {
|
|
239
255
|
if (!this.neurolink ||
|
|
240
256
|
typeof this.neurolink.getExternalMCPTools !== "function") {
|
|
241
|
-
logger.debug(`[ToolsManager] No external MCP tool interface available`, {
|
|
242
|
-
hasNeuroLink: !!this.neurolink,
|
|
243
|
-
hasGetExternalMCPTools: this.neurolink &&
|
|
244
|
-
typeof this.neurolink.getExternalMCPTools === "function",
|
|
245
|
-
});
|
|
246
257
|
return;
|
|
247
258
|
}
|
|
248
259
|
try {
|
|
249
|
-
logger.debug(`[ToolsManager] Loading external MCP tools for ${this.providerName}`);
|
|
250
260
|
const externalTools = await this.neurolink.getExternalMCPTools();
|
|
251
|
-
|
|
261
|
+
let addedCount = 0;
|
|
252
262
|
for (const tool of externalTools) {
|
|
253
263
|
const mcpTool = await this.createExternalMCPTool(tool);
|
|
254
264
|
if (mcpTool && !tools[tool.name]) {
|
|
255
265
|
tools[tool.name] = mcpTool;
|
|
256
|
-
|
|
266
|
+
addedCount++;
|
|
257
267
|
}
|
|
258
268
|
}
|
|
259
|
-
logger.debug(`[ToolsManager] External MCP tools
|
|
260
|
-
|
|
269
|
+
logger.debug(`[ToolsManager] External MCP tools loaded`, {
|
|
270
|
+
found: externalTools.length,
|
|
271
|
+
added: addedCount,
|
|
261
272
|
});
|
|
262
273
|
}
|
|
263
274
|
catch (error) {
|
|
@@ -270,7 +281,6 @@ export class ToolsManager {
|
|
|
270
281
|
*/
|
|
271
282
|
async createCustomToolFromDefinition(toolName, toolInfo) {
|
|
272
283
|
try {
|
|
273
|
-
logger.debug(`[ToolsManager] Converting custom tool: ${toolName}`);
|
|
274
284
|
let finalSchema;
|
|
275
285
|
let originalInputSchema;
|
|
276
286
|
// Prioritize parameters (Zod), then inputSchema (Zod or JSON Schema)
|
|
@@ -299,55 +309,19 @@ export class ToolsManager {
|
|
|
299
309
|
description: toolInfo.description || `Tool ${toolName}`,
|
|
300
310
|
parameters: finalSchema,
|
|
301
311
|
execute: async (params) => {
|
|
312
|
+
const customToolSpan = tracers.sdk.startSpan("neurolink.tools.execute_custom", {
|
|
313
|
+
attributes: {
|
|
314
|
+
"tool.name": toolName,
|
|
315
|
+
"tool.type": "custom",
|
|
316
|
+
},
|
|
317
|
+
});
|
|
302
318
|
const startTime = Date.now();
|
|
303
319
|
let executionId;
|
|
304
|
-
if (this.neurolink?.emitToolStart) {
|
|
305
|
-
executionId = this.neurolink.emitToolStart(toolName, params, startTime);
|
|
306
|
-
logger.debug(`Custom tool:start emitted via NeuroLink for ${toolName}`, {
|
|
307
|
-
toolName,
|
|
308
|
-
executionId,
|
|
309
|
-
input: params,
|
|
310
|
-
hasNativeEmission: true,
|
|
311
|
-
});
|
|
312
|
-
}
|
|
313
320
|
try {
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
paramsBeforeExecution: {
|
|
318
|
-
type: typeof params,
|
|
319
|
-
isNull: params === null,
|
|
320
|
-
isUndefined: params === undefined,
|
|
321
|
-
isEmpty: params &&
|
|
322
|
-
typeof params === "object" &&
|
|
323
|
-
Object.keys(params).length === 0,
|
|
324
|
-
keys: params && typeof params === "object"
|
|
325
|
-
? Object.keys(params)
|
|
326
|
-
: "NOT_OBJECT",
|
|
327
|
-
keysLength: params && typeof params === "object"
|
|
328
|
-
? Object.keys(params).length
|
|
329
|
-
: 0,
|
|
330
|
-
},
|
|
331
|
-
executorInfo: {
|
|
332
|
-
hasExecutor: typeof toolInfo.execute === "function",
|
|
333
|
-
executorType: typeof toolInfo.execute,
|
|
334
|
-
},
|
|
335
|
-
timestamp: Date.now(),
|
|
336
|
-
phase: "BEFORE_NEUROLINK_EXECUTE",
|
|
337
|
-
});
|
|
321
|
+
if (this.neurolink?.emitToolStart) {
|
|
322
|
+
executionId = this.neurolink.emitToolStart(toolName, params, startTime);
|
|
323
|
+
}
|
|
338
324
|
const result = await toolInfo.execute(params);
|
|
339
|
-
// 🔧 PARAMETER FLOW TRACING - After NeuroLink executeTool call
|
|
340
|
-
logger.debug(`NeuroLink executeTool completed for ${toolName}`, {
|
|
341
|
-
toolName,
|
|
342
|
-
resultInfo: {
|
|
343
|
-
type: typeof result,
|
|
344
|
-
isNull: result === null,
|
|
345
|
-
isUndefined: result === undefined,
|
|
346
|
-
hasError: result && typeof result === "object" && "error" in result,
|
|
347
|
-
},
|
|
348
|
-
timestamp: Date.now(),
|
|
349
|
-
phase: "AFTER_NEUROLINK_EXECUTE",
|
|
350
|
-
});
|
|
351
325
|
const convertedResult = this.utilities?.convertToolResult
|
|
352
326
|
? await this.utilities.convertToolResult(result)
|
|
353
327
|
: result;
|
|
@@ -364,36 +338,36 @@ export class ToolsManager {
|
|
|
364
338
|
logger.error(`Failed to serialize error result for ${toolName}`, error);
|
|
365
339
|
}
|
|
366
340
|
}
|
|
367
|
-
//
|
|
341
|
+
// Emit tool end event (success or handled error)
|
|
368
342
|
if (this.neurolink?.emitToolEnd) {
|
|
369
343
|
this.neurolink.emitToolEnd(toolName, convertedResult, errorResult, startTime, endTime, executionId);
|
|
370
|
-
logger.debug(`Custom tool:end emitted via NeuroLink for ${toolName}`, {
|
|
371
|
-
toolName,
|
|
372
|
-
executionId,
|
|
373
|
-
duration: endTime - startTime,
|
|
374
|
-
hasResult: convertedResult !== undefined,
|
|
375
|
-
hasNativeEmission: true,
|
|
376
|
-
});
|
|
377
344
|
}
|
|
345
|
+
customToolSpan.setAttribute("tool.duration_ms", endTime - startTime);
|
|
346
|
+
customToolSpan.setAttribute("tool.result.status", errorResult ? "error" : "success");
|
|
347
|
+
customToolSpan.setStatus({ code: SpanStatusCode.OK });
|
|
378
348
|
return convertedResult;
|
|
379
349
|
}
|
|
380
350
|
catch (error) {
|
|
381
351
|
const endTime = Date.now();
|
|
382
352
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
383
|
-
//
|
|
353
|
+
// Emit tool end event (error)
|
|
384
354
|
if (this.neurolink?.emitToolEnd) {
|
|
385
355
|
this.neurolink.emitToolEnd(toolName, undefined, // no result
|
|
386
356
|
errorMsg, startTime, endTime, executionId);
|
|
387
|
-
logger.
|
|
388
|
-
toolName,
|
|
389
|
-
executionId,
|
|
390
|
-
duration: endTime - startTime,
|
|
391
|
-
error: errorMsg,
|
|
392
|
-
hasNativeEmission: true,
|
|
393
|
-
});
|
|
357
|
+
logger.debug(`Custom tool error: ${toolName} (${endTime - startTime}ms)`, { error: errorMsg });
|
|
394
358
|
}
|
|
359
|
+
customToolSpan.setAttribute("tool.duration_ms", endTime - startTime);
|
|
360
|
+
customToolSpan.setAttribute("tool.result.status", "error");
|
|
361
|
+
customToolSpan.recordException(error instanceof Error ? error : new Error(errorMsg));
|
|
362
|
+
customToolSpan.setStatus({
|
|
363
|
+
code: SpanStatusCode.ERROR,
|
|
364
|
+
message: errorMsg,
|
|
365
|
+
});
|
|
395
366
|
throw error;
|
|
396
367
|
}
|
|
368
|
+
finally {
|
|
369
|
+
customToolSpan.end();
|
|
370
|
+
}
|
|
397
371
|
},
|
|
398
372
|
});
|
|
399
373
|
}
|
|
@@ -407,7 +381,6 @@ export class ToolsManager {
|
|
|
407
381
|
*/
|
|
408
382
|
async createExternalMCPTool(tool) {
|
|
409
383
|
try {
|
|
410
|
-
logger.debug(`[ToolsManager] Converting external MCP tool: ${tool.name}`);
|
|
411
384
|
// Use original JSON Schema from MCP tool if available, otherwise use permissive schema
|
|
412
385
|
let finalSchema;
|
|
413
386
|
if (tool.inputSchema && typeof tool.inputSchema === "object") {
|
|
@@ -427,98 +400,49 @@ export class ToolsManager {
|
|
|
427
400
|
description: tool.description || `External MCP tool ${tool.name}`,
|
|
428
401
|
parameters: finalSchema,
|
|
429
402
|
execute: async (params) => {
|
|
430
|
-
|
|
431
|
-
toolName: tool.name,
|
|
432
|
-
serverId: tool.serverId,
|
|
433
|
-
params: JSON.stringify(params),
|
|
434
|
-
paramsType: typeof params,
|
|
435
|
-
hasNeurolink: !!this.neurolink,
|
|
436
|
-
hasExecuteFunction: this.neurolink &&
|
|
437
|
-
typeof this.neurolink.executeExternalMCPTool === "function",
|
|
438
|
-
timestamp: Date.now(),
|
|
439
|
-
});
|
|
440
|
-
// 🔧 EMIT TOOL START EVENT - Bedrock-compatible format
|
|
403
|
+
// Emit tool start event
|
|
441
404
|
if (this.neurolink?.getEventEmitter) {
|
|
442
405
|
const emitter = this.neurolink.getEventEmitter();
|
|
443
406
|
emitter.emit("tool:start", { tool: tool.name, input: params });
|
|
444
|
-
logger.debug(`tool:start event emitted for ${tool.name}`, {
|
|
445
|
-
toolName: tool.name,
|
|
446
|
-
input: params,
|
|
447
|
-
hasEmitter: !!emitter,
|
|
448
|
-
});
|
|
449
407
|
}
|
|
450
408
|
// Execute via NeuroLink's direct tool execution
|
|
451
409
|
if (this.neurolink &&
|
|
452
410
|
typeof this.neurolink.executeExternalMCPTool === "function") {
|
|
453
411
|
try {
|
|
454
412
|
const result = await this.neurolink.executeExternalMCPTool(tool.serverId || "unknown", tool.name, params);
|
|
455
|
-
//
|
|
413
|
+
// Emit tool end event (success)
|
|
456
414
|
if (this.neurolink?.getEventEmitter) {
|
|
457
415
|
const emitter = this.neurolink.getEventEmitter();
|
|
458
416
|
emitter.emit("tool:end", { tool: tool.name, result });
|
|
459
|
-
logger.debug(`tool:end event emitted for ${tool.name}`, {
|
|
460
|
-
toolName: tool.name,
|
|
461
|
-
result: typeof result === "string"
|
|
462
|
-
? result.substring(0, 100)
|
|
463
|
-
: JSON.stringify(result).substring(0, 100),
|
|
464
|
-
hasEmitter: !!emitter,
|
|
465
|
-
});
|
|
466
417
|
}
|
|
467
|
-
logger.debug(`External MCP tool executed: ${tool.name}`, {
|
|
468
|
-
toolName: tool.name,
|
|
469
|
-
result: typeof result === "string"
|
|
470
|
-
? result.substring(0, 200)
|
|
471
|
-
: JSON.stringify(result).substring(0, 200),
|
|
472
|
-
resultType: typeof result,
|
|
473
|
-
timestamp: Date.now(),
|
|
474
|
-
});
|
|
475
418
|
return result;
|
|
476
419
|
}
|
|
477
420
|
catch (mcpError) {
|
|
478
|
-
//
|
|
421
|
+
// Emit tool end event (error)
|
|
479
422
|
if (this.neurolink?.getEventEmitter) {
|
|
480
423
|
const emitter = this.neurolink.getEventEmitter();
|
|
481
424
|
const errorMsg = mcpError instanceof Error
|
|
482
425
|
? mcpError.message
|
|
483
426
|
: String(mcpError);
|
|
484
427
|
emitter.emit("tool:end", { tool: tool.name, error: errorMsg });
|
|
485
|
-
logger.debug(`tool:end error event emitted for ${tool.name}`, {
|
|
486
|
-
toolName: tool.name,
|
|
487
|
-
error: errorMsg,
|
|
488
|
-
hasEmitter: !!emitter,
|
|
489
|
-
});
|
|
490
428
|
}
|
|
491
429
|
logger.error(`External MCP tool failed: ${tool.name}`, {
|
|
492
|
-
toolName: tool.name,
|
|
493
430
|
serverId: tool.serverId,
|
|
494
431
|
error: mcpError instanceof Error
|
|
495
432
|
? mcpError.message
|
|
496
433
|
: String(mcpError),
|
|
497
|
-
errorStack: mcpError instanceof Error ? mcpError.stack : undefined,
|
|
498
|
-
params: JSON.stringify(params),
|
|
499
|
-
timestamp: Date.now(),
|
|
500
434
|
});
|
|
501
435
|
throw mcpError;
|
|
502
436
|
}
|
|
503
437
|
}
|
|
504
438
|
else {
|
|
505
439
|
const error = `Cannot execute external MCP tool: NeuroLink executeExternalMCPTool not available`;
|
|
506
|
-
//
|
|
440
|
+
// Emit tool end event (error - no executor)
|
|
507
441
|
if (this.neurolink?.getEventEmitter) {
|
|
508
442
|
const emitter = this.neurolink.getEventEmitter();
|
|
509
443
|
emitter.emit("tool:end", { tool: tool.name, error });
|
|
510
|
-
logger.debug(`tool:end error event emitted for ${tool.name}`, {
|
|
511
|
-
toolName: tool.name,
|
|
512
|
-
error,
|
|
513
|
-
hasEmitter: !!emitter,
|
|
514
|
-
});
|
|
515
444
|
}
|
|
516
|
-
logger.error(
|
|
517
|
-
toolName: tool.name,
|
|
518
|
-
hasNeurolink: !!this.neurolink,
|
|
519
|
-
neurolinkType: typeof this.neurolink,
|
|
520
|
-
timestamp: Date.now(),
|
|
521
|
-
});
|
|
445
|
+
logger.error(error);
|
|
522
446
|
throw new Error(error);
|
|
523
447
|
}
|
|
524
448
|
},
|