@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.
Files changed (241) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +15 -15
  3. package/dist/adapters/video/videoAnalyzer.d.ts +1 -1
  4. package/dist/adapters/video/videoAnalyzer.js +10 -8
  5. package/dist/auth/anthropicOAuth.d.ts +377 -0
  6. package/dist/auth/anthropicOAuth.js +914 -0
  7. package/dist/auth/index.d.ts +20 -0
  8. package/dist/auth/index.js +29 -0
  9. package/dist/auth/tokenStore.d.ts +225 -0
  10. package/dist/auth/tokenStore.js +521 -0
  11. package/dist/cli/commands/auth.d.ts +50 -0
  12. package/dist/cli/commands/auth.js +1115 -0
  13. package/dist/cli/commands/setup-anthropic.js +1 -14
  14. package/dist/cli/commands/setup-azure.js +1 -12
  15. package/dist/cli/commands/setup-bedrock.js +1 -9
  16. package/dist/cli/commands/setup-google-ai.js +1 -12
  17. package/dist/cli/commands/setup-openai.js +1 -14
  18. package/dist/cli/commands/workflow.d.ts +27 -0
  19. package/dist/cli/commands/workflow.js +216 -0
  20. package/dist/cli/factories/authCommandFactory.d.ts +52 -0
  21. package/dist/cli/factories/authCommandFactory.js +146 -0
  22. package/dist/cli/factories/commandFactory.d.ts +6 -0
  23. package/dist/cli/factories/commandFactory.js +171 -22
  24. package/dist/cli/index.js +0 -1
  25. package/dist/cli/parser.js +14 -2
  26. package/dist/cli/utils/maskCredential.d.ts +11 -0
  27. package/dist/cli/utils/maskCredential.js +23 -0
  28. package/dist/constants/contextWindows.js +107 -16
  29. package/dist/constants/enums.d.ts +119 -15
  30. package/dist/constants/enums.js +182 -22
  31. package/dist/constants/index.d.ts +3 -1
  32. package/dist/constants/index.js +11 -1
  33. package/dist/context/budgetChecker.js +1 -1
  34. package/dist/context/contextCompactor.js +31 -4
  35. package/dist/context/emergencyTruncation.d.ts +21 -0
  36. package/dist/context/emergencyTruncation.js +88 -0
  37. package/dist/context/errorDetection.d.ts +16 -0
  38. package/dist/context/errorDetection.js +48 -1
  39. package/dist/context/errors.d.ts +19 -0
  40. package/dist/context/errors.js +21 -0
  41. package/dist/context/stages/slidingWindowTruncator.d.ts +6 -0
  42. package/dist/context/stages/slidingWindowTruncator.js +159 -24
  43. package/dist/core/baseProvider.js +306 -200
  44. package/dist/core/conversationMemoryManager.js +104 -61
  45. package/dist/core/evaluationProviders.js +16 -33
  46. package/dist/core/factory.js +237 -164
  47. package/dist/core/modules/GenerationHandler.js +175 -116
  48. package/dist/core/modules/MessageBuilder.js +222 -170
  49. package/dist/core/modules/StreamHandler.d.ts +1 -0
  50. package/dist/core/modules/StreamHandler.js +95 -27
  51. package/dist/core/modules/TelemetryHandler.d.ts +10 -1
  52. package/dist/core/modules/TelemetryHandler.js +25 -7
  53. package/dist/core/modules/ToolsManager.js +115 -191
  54. package/dist/core/redisConversationMemoryManager.js +418 -282
  55. package/dist/factories/providerRegistry.d.ts +5 -0
  56. package/dist/factories/providerRegistry.js +20 -2
  57. package/dist/index.d.ts +3 -3
  58. package/dist/index.js +4 -2
  59. package/dist/lib/adapters/video/videoAnalyzer.d.ts +1 -1
  60. package/dist/lib/adapters/video/videoAnalyzer.js +10 -8
  61. package/dist/lib/auth/anthropicOAuth.d.ts +377 -0
  62. package/dist/lib/auth/anthropicOAuth.js +915 -0
  63. package/dist/lib/auth/index.d.ts +20 -0
  64. package/dist/lib/auth/index.js +30 -0
  65. package/dist/lib/auth/tokenStore.d.ts +225 -0
  66. package/dist/lib/auth/tokenStore.js +522 -0
  67. package/dist/lib/constants/contextWindows.js +107 -16
  68. package/dist/lib/constants/enums.d.ts +119 -15
  69. package/dist/lib/constants/enums.js +182 -22
  70. package/dist/lib/constants/index.d.ts +3 -1
  71. package/dist/lib/constants/index.js +11 -1
  72. package/dist/lib/context/budgetChecker.js +1 -1
  73. package/dist/lib/context/contextCompactor.js +31 -4
  74. package/dist/lib/context/emergencyTruncation.d.ts +21 -0
  75. package/dist/lib/context/emergencyTruncation.js +89 -0
  76. package/dist/lib/context/errorDetection.d.ts +16 -0
  77. package/dist/lib/context/errorDetection.js +48 -1
  78. package/dist/lib/context/errors.d.ts +19 -0
  79. package/dist/lib/context/errors.js +22 -0
  80. package/dist/lib/context/stages/slidingWindowTruncator.d.ts +6 -0
  81. package/dist/lib/context/stages/slidingWindowTruncator.js +159 -24
  82. package/dist/lib/core/baseProvider.js +306 -200
  83. package/dist/lib/core/conversationMemoryManager.js +104 -61
  84. package/dist/lib/core/evaluationProviders.js +16 -33
  85. package/dist/lib/core/factory.js +237 -164
  86. package/dist/lib/core/modules/GenerationHandler.js +175 -116
  87. package/dist/lib/core/modules/MessageBuilder.js +222 -170
  88. package/dist/lib/core/modules/StreamHandler.d.ts +1 -0
  89. package/dist/lib/core/modules/StreamHandler.js +95 -27
  90. package/dist/lib/core/modules/TelemetryHandler.d.ts +10 -1
  91. package/dist/lib/core/modules/TelemetryHandler.js +25 -7
  92. package/dist/lib/core/modules/ToolsManager.js +115 -191
  93. package/dist/lib/core/redisConversationMemoryManager.js +418 -282
  94. package/dist/lib/factories/providerRegistry.d.ts +5 -0
  95. package/dist/lib/factories/providerRegistry.js +20 -2
  96. package/dist/lib/index.d.ts +3 -3
  97. package/dist/lib/index.js +4 -2
  98. package/dist/lib/mcp/externalServerManager.js +66 -0
  99. package/dist/lib/mcp/mcpCircuitBreaker.js +24 -0
  100. package/dist/lib/mcp/mcpClientFactory.js +16 -0
  101. package/dist/lib/mcp/toolDiscoveryService.js +32 -6
  102. package/dist/lib/mcp/toolRegistry.js +193 -123
  103. package/dist/lib/models/anthropicModels.d.ts +267 -0
  104. package/dist/lib/models/anthropicModels.js +528 -0
  105. package/dist/lib/neurolink.d.ts +6 -0
  106. package/dist/lib/neurolink.js +1162 -646
  107. package/dist/lib/providers/amazonBedrock.d.ts +1 -1
  108. package/dist/lib/providers/amazonBedrock.js +521 -319
  109. package/dist/lib/providers/anthropic.d.ts +123 -2
  110. package/dist/lib/providers/anthropic.js +873 -27
  111. package/dist/lib/providers/anthropicBaseProvider.js +77 -17
  112. package/dist/lib/providers/googleAiStudio.d.ts +1 -1
  113. package/dist/lib/providers/googleAiStudio.js +292 -227
  114. package/dist/lib/providers/googleVertex.d.ts +36 -1
  115. package/dist/lib/providers/googleVertex.js +553 -260
  116. package/dist/lib/providers/ollama.js +329 -278
  117. package/dist/lib/providers/openAI.js +77 -19
  118. package/dist/lib/providers/sagemaker/parsers.js +3 -3
  119. package/dist/lib/providers/sagemaker/streaming.js +3 -3
  120. package/dist/lib/proxy/proxyFetch.js +81 -48
  121. package/dist/lib/rag/ChunkerFactory.js +1 -1
  122. package/dist/lib/rag/chunkers/MarkdownChunker.d.ts +22 -0
  123. package/dist/lib/rag/chunkers/MarkdownChunker.js +213 -9
  124. package/dist/lib/rag/chunking/markdownChunker.d.ts +16 -0
  125. package/dist/lib/rag/chunking/markdownChunker.js +174 -2
  126. package/dist/lib/rag/pipeline/contextAssembly.js +2 -1
  127. package/dist/lib/rag/ragIntegration.d.ts +18 -1
  128. package/dist/lib/rag/ragIntegration.js +94 -14
  129. package/dist/lib/rag/retrieval/vectorQueryTool.js +21 -4
  130. package/dist/lib/server/abstract/baseServerAdapter.js +4 -1
  131. package/dist/lib/server/adapters/fastifyAdapter.js +35 -30
  132. package/dist/lib/services/server/ai/observability/instrumentation.d.ts +32 -0
  133. package/dist/lib/services/server/ai/observability/instrumentation.js +39 -0
  134. package/dist/lib/telemetry/attributes.d.ts +52 -0
  135. package/dist/lib/telemetry/attributes.js +61 -0
  136. package/dist/lib/telemetry/index.d.ts +3 -0
  137. package/dist/lib/telemetry/index.js +3 -0
  138. package/dist/lib/telemetry/telemetryService.d.ts +6 -0
  139. package/dist/lib/telemetry/telemetryService.js +6 -0
  140. package/dist/lib/telemetry/tracers.d.ts +15 -0
  141. package/dist/lib/telemetry/tracers.js +17 -0
  142. package/dist/lib/telemetry/withSpan.d.ts +9 -0
  143. package/dist/lib/telemetry/withSpan.js +35 -0
  144. package/dist/lib/types/contextTypes.d.ts +10 -0
  145. package/dist/lib/types/errors.d.ts +62 -0
  146. package/dist/lib/types/errors.js +107 -0
  147. package/dist/lib/types/index.d.ts +2 -1
  148. package/dist/lib/types/index.js +2 -0
  149. package/dist/lib/types/providers.d.ts +107 -0
  150. package/dist/lib/types/providers.js +69 -0
  151. package/dist/lib/types/streamTypes.d.ts +14 -0
  152. package/dist/lib/types/subscriptionTypes.d.ts +893 -0
  153. package/dist/lib/types/subscriptionTypes.js +8 -0
  154. package/dist/lib/utils/conversationMemory.js +121 -82
  155. package/dist/lib/utils/logger.d.ts +5 -0
  156. package/dist/lib/utils/logger.js +50 -2
  157. package/dist/lib/utils/messageBuilder.js +22 -42
  158. package/dist/lib/utils/modelDetection.js +3 -3
  159. package/dist/lib/utils/providerConfig.d.ts +167 -0
  160. package/dist/lib/utils/providerConfig.js +619 -9
  161. package/dist/lib/utils/providerRetry.d.ts +41 -0
  162. package/dist/lib/utils/providerRetry.js +114 -0
  163. package/dist/lib/utils/retryability.d.ts +14 -0
  164. package/dist/lib/utils/retryability.js +23 -0
  165. package/dist/lib/utils/sanitizers/svg.js +4 -5
  166. package/dist/lib/utils/tokenEstimation.d.ts +11 -1
  167. package/dist/lib/utils/tokenEstimation.js +19 -4
  168. package/dist/lib/utils/videoAnalysisProcessor.js +7 -3
  169. package/dist/mcp/externalServerManager.js +66 -0
  170. package/dist/mcp/mcpCircuitBreaker.js +24 -0
  171. package/dist/mcp/mcpClientFactory.js +16 -0
  172. package/dist/mcp/toolDiscoveryService.js +32 -6
  173. package/dist/mcp/toolRegistry.js +193 -123
  174. package/dist/models/anthropicModels.d.ts +267 -0
  175. package/dist/models/anthropicModels.js +527 -0
  176. package/dist/neurolink.d.ts +6 -0
  177. package/dist/neurolink.js +1162 -646
  178. package/dist/providers/amazonBedrock.d.ts +1 -1
  179. package/dist/providers/amazonBedrock.js +521 -319
  180. package/dist/providers/anthropic.d.ts +123 -2
  181. package/dist/providers/anthropic.js +873 -27
  182. package/dist/providers/anthropicBaseProvider.js +77 -17
  183. package/dist/providers/googleAiStudio.d.ts +1 -1
  184. package/dist/providers/googleAiStudio.js +292 -227
  185. package/dist/providers/googleVertex.d.ts +36 -1
  186. package/dist/providers/googleVertex.js +553 -260
  187. package/dist/providers/ollama.js +329 -278
  188. package/dist/providers/openAI.js +77 -19
  189. package/dist/providers/sagemaker/parsers.js +3 -3
  190. package/dist/providers/sagemaker/streaming.js +3 -3
  191. package/dist/proxy/proxyFetch.js +81 -48
  192. package/dist/rag/ChunkerFactory.js +1 -1
  193. package/dist/rag/chunkers/MarkdownChunker.d.ts +22 -0
  194. package/dist/rag/chunkers/MarkdownChunker.js +213 -9
  195. package/dist/rag/chunking/markdownChunker.d.ts +16 -0
  196. package/dist/rag/chunking/markdownChunker.js +174 -2
  197. package/dist/rag/pipeline/contextAssembly.js +2 -1
  198. package/dist/rag/ragIntegration.d.ts +18 -1
  199. package/dist/rag/ragIntegration.js +94 -14
  200. package/dist/rag/retrieval/vectorQueryTool.js +21 -4
  201. package/dist/server/abstract/baseServerAdapter.js +4 -1
  202. package/dist/server/adapters/fastifyAdapter.js +35 -30
  203. package/dist/services/server/ai/observability/instrumentation.d.ts +32 -0
  204. package/dist/services/server/ai/observability/instrumentation.js +39 -0
  205. package/dist/telemetry/attributes.d.ts +52 -0
  206. package/dist/telemetry/attributes.js +60 -0
  207. package/dist/telemetry/index.d.ts +3 -0
  208. package/dist/telemetry/index.js +3 -0
  209. package/dist/telemetry/telemetryService.d.ts +6 -0
  210. package/dist/telemetry/telemetryService.js +6 -0
  211. package/dist/telemetry/tracers.d.ts +15 -0
  212. package/dist/telemetry/tracers.js +16 -0
  213. package/dist/telemetry/withSpan.d.ts +9 -0
  214. package/dist/telemetry/withSpan.js +34 -0
  215. package/dist/types/contextTypes.d.ts +10 -0
  216. package/dist/types/errors.d.ts +62 -0
  217. package/dist/types/errors.js +107 -0
  218. package/dist/types/index.d.ts +2 -1
  219. package/dist/types/index.js +2 -0
  220. package/dist/types/providers.d.ts +107 -0
  221. package/dist/types/providers.js +69 -0
  222. package/dist/types/streamTypes.d.ts +14 -0
  223. package/dist/types/subscriptionTypes.d.ts +893 -0
  224. package/dist/types/subscriptionTypes.js +7 -0
  225. package/dist/utils/conversationMemory.js +121 -82
  226. package/dist/utils/logger.d.ts +5 -0
  227. package/dist/utils/logger.js +50 -2
  228. package/dist/utils/messageBuilder.js +22 -42
  229. package/dist/utils/modelDetection.js +3 -3
  230. package/dist/utils/providerConfig.d.ts +167 -0
  231. package/dist/utils/providerConfig.js +619 -9
  232. package/dist/utils/providerRetry.d.ts +41 -0
  233. package/dist/utils/providerRetry.js +113 -0
  234. package/dist/utils/retryability.d.ts +14 -0
  235. package/dist/utils/retryability.js +22 -0
  236. package/dist/utils/sanitizers/svg.js +4 -5
  237. package/dist/utils/tokenEstimation.d.ts +11 -1
  238. package/dist/utils/tokenEstimation.js +19 -4
  239. package/dist/utils/videoAnalysisProcessor.js +7 -3
  240. package/dist/workflow/config.d.ts +26 -26
  241. 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 { getPerformanceOptimizedProvider, recordProviderPerformanceFromMetrics, } from "../evaluationProviders.js";
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
- const optimizedProvider = getPerformanceOptimizedProvider("speed");
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 { getKeysAsString, getKeyCount, } from "../../utils/transformationUtils.js";
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
- // Store custom tools for use in getAllTools()
58
- this.customTools = sdk.customTools;
59
- this.toolExecutor = sdk.executeTool;
60
- logger.debug(`[${functionTag}] Setting up tool executor for provider`, {
61
- providerName: this.providerName,
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
- // Note: Tool execution will be handled through getAllTools() -> AI SDK tools
67
- // The custom tools are converted to AI SDK format in getAllTools() method
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
- // Start with wrapped direct tools that emit events
75
- const tools = {};
76
- // Wrap direct tools with event emission
77
- await this.processDirectTools(tools);
78
- logger.debug(`[ToolsManager] getAllTools called for ${this.providerName}`, {
79
- neurolinkAvailable: !!this.neurolink,
80
- neurolinkType: typeof this.neurolink,
81
- directToolsCount: getKeyCount(this.directTools),
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 with event emission`);
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
- logger.debug(`Direct tools processing complete`, {
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
- logger.debug(`[ToolsManager] Custom tools processing complete`, {
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
- logger.debug(`[ToolsManager] Found ${externalTools.length} external MCP tools`);
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
- logger.debug(`[ToolsManager] Successfully added external MCP tool: ${tool.name}`);
266
+ addedCount++;
257
267
  }
258
268
  }
259
- logger.debug(`[ToolsManager] External MCP tools loading complete`, {
260
- totalToolsAdded: externalTools.length,
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
- // 🔧 PARAMETER FLOW TRACING - Before NeuroLink executeTool call
315
- logger.debug(`About to call NeuroLink executeTool for ${toolName}`, {
316
- toolName,
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
- // 🔧 NATIVE NEUROLINK EVENT EMISSION - Tool End (Success or Handled Error)
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
- // 🔧 NATIVE NEUROLINK EVENT EMISSION - Tool End (Error)
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.info(`Custom tool:end error emitted via NeuroLink for ${toolName}`, {
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
- logger.debug(`Executing external MCP tool: ${tool.name}`, {
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
- // 🔧 EMIT TOOL END EVENT - Bedrock-compatible format
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
- // 🔧 EMIT TOOL END EVENT FOR ERROR - Bedrock-compatible format
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
- // 🔧 EMIT TOOL END EVENT FOR ERROR - Bedrock-compatible format
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(`${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
  },