@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
@@ -10,6 +10,7 @@ import { directAgentTools } from "../agent/directTools.js";
10
10
  import { detectCategory, createMCPServerInfo } from "../utils/mcpDefaults.js";
11
11
  import { FlexibleToolValidator } from "./flexibleToolValidator.js";
12
12
  import { HITLUserRejectedError, HITLTimeoutError } from "../hitl/hitlErrors.js";
13
+ import { withSpan, tracers, ATTR } from "../telemetry/index.js";
13
14
  export class MCPToolRegistry extends MCPRegistry {
14
15
  tools = new Map();
15
16
  toolImplementations = new Map(); // Store actual tool implementations
@@ -227,149 +228,218 @@ export class MCPToolRegistry extends MCPRegistry {
227
228
  */
228
229
  async executeTool(toolName, args, context) {
229
230
  const startTime = Date.now();
230
- try {
231
- registryLogger.info(`🔧 [TOOL_EXECUTION] Starting execution: ${toolName}`, { args, context });
232
- // Try to find the tool by fully-qualified name first
233
- let tool = this.tools.get(toolName);
234
- registryLogger.info(`🔍 [TOOL_LOOKUP] Direct lookup result for '${toolName}':`, !!tool);
235
- // If not found, search for tool by name across all entries (for backward compatibility)
236
- let toolId = toolName;
237
- if (!tool) {
238
- for (const [candidateToolId, toolInfo] of this.tools.entries()) {
239
- if (toolInfo.name === toolName) {
231
+ // Resolve serverId eagerly for span attributes
232
+ let preResolvedServerId;
233
+ const toolEntry = this.tools.get(toolName);
234
+ if (toolEntry) {
235
+ preResolvedServerId = toolEntry.serverId;
236
+ }
237
+ else {
238
+ for (const toolInfo of this.tools.values()) {
239
+ if (toolInfo.name === toolName) {
240
+ preResolvedServerId = toolInfo.serverId;
241
+ break;
242
+ }
243
+ }
244
+ }
245
+ return withSpan({
246
+ name: "neurolink.tool.execute",
247
+ tracer: tracers.mcp,
248
+ attributes: {
249
+ [ATTR.GEN_AI_TOOL_NAME]: toolName,
250
+ [ATTR.MCP_SERVER_ID]: preResolvedServerId || "builtin",
251
+ },
252
+ }, async (span) => {
253
+ try {
254
+ registryLogger.info(`🔧 [TOOL_EXECUTION] Starting execution: ${toolName}`, {
255
+ hasArgs: args !== undefined,
256
+ hasContext: context !== undefined,
257
+ sessionId: context?.sessionId,
258
+ });
259
+ // Try to find the tool by fully-qualified name first
260
+ let tool = this.tools.get(toolName);
261
+ registryLogger.info(`🔍 [TOOL_LOOKUP] Direct lookup result for '${toolName}':`, !!tool);
262
+ // If not found, search for tool by name across all entries (for backward compatibility)
263
+ let toolId = toolName;
264
+ if (!tool) {
265
+ const matches = Array.from(this.tools.entries()).filter(([, toolInfo]) => toolInfo.name === toolName);
266
+ if (matches.length > 1) {
267
+ throw new Error(`Ambiguous tool name '${toolName}'. Use fully-qualified name 'serverId.${toolName}'.`);
268
+ }
269
+ if (matches.length === 1) {
270
+ const [candidateToolId, toolInfo] = matches[0];
240
271
  tool = toolInfo;
241
272
  toolId = candidateToolId;
242
- break;
243
273
  }
244
274
  }
245
- }
246
- if (!tool) {
247
- throw new Error(`Tool '${toolName}' not found in registry`);
248
- }
249
- // Create execution context if not provided
250
- const execContext = {
251
- sessionId: context?.sessionId || randomUUID(),
252
- userId: context?.userId,
253
- ...context,
254
- };
255
- // Get the tool implementation using the resolved toolId
256
- const toolImpl = this.toolImplementations.get(toolId);
257
- registryLogger.debug(`Looking for tool '${toolName}' (toolId: '${toolId}'), found: ${!!toolImpl}, type: ${typeof toolImpl?.execute}`);
258
- registryLogger.debug(`Available tools:`, Array.from(this.toolImplementations.keys()));
259
- if (!toolImpl || typeof toolImpl?.execute !== "function") {
260
- throw new Error(`Tool '${toolName}' implementation not found or not executable`);
261
- }
262
- // HITL Safety Check: Request confirmation if required
263
- let finalArgs = args;
264
- if (this.hitlManager && this.hitlManager.isEnabled()) {
265
- const requiresConfirmation = this.hitlManager.requiresConfirmation(toolName, args);
266
- if (requiresConfirmation) {
267
- registryLogger.info(`Tool '${toolName}' requires HITL confirmation`);
268
- try {
269
- const confirmationResult = await this.hitlManager.requestConfirmation(toolName, args, {
270
- serverId: tool.serverId,
271
- sessionId: execContext.sessionId,
272
- userId: execContext.userId,
273
- });
274
- if (!confirmationResult.approved) {
275
- // User rejected the tool execution
276
- throw new HITLUserRejectedError(`Tool execution rejected by user: ${confirmationResult.reason || "No reason provided"}`, toolName, confirmationResult.reason);
275
+ if (!tool) {
276
+ throw new Error(`Tool '${toolName}' not found in registry`);
277
+ }
278
+ // Classify tool type for observability
279
+ const serverId = tool.serverId || "unknown";
280
+ const toolType = serverId === "direct"
281
+ ? "builtin"
282
+ : serverId.startsWith("custom-tool-")
283
+ ? "custom"
284
+ : "mcp";
285
+ span.setAttribute("tool.type", toolType);
286
+ span.setAttribute(ATTR.MCP_SERVER_ID, serverId);
287
+ // Create execution context if not provided
288
+ const execContext = {
289
+ ...context,
290
+ sessionId: context?.sessionId ?? randomUUID(),
291
+ userId: context?.userId,
292
+ };
293
+ // Get the tool implementation using the resolved toolId
294
+ const toolImpl = this.toolImplementations.get(toolId);
295
+ registryLogger.debug(`Looking for tool '${toolName}' (toolId: '${toolId}'), found: ${!!toolImpl}, type: ${typeof toolImpl?.execute}`);
296
+ registryLogger.debug(`Available tools:`, Array.from(this.toolImplementations.keys()));
297
+ if (!toolImpl || typeof toolImpl?.execute !== "function") {
298
+ throw new Error(`Tool '${toolName}' implementation not found or not executable`);
299
+ }
300
+ // Capture argument metadata (avoid logging raw values which may contain secrets)
301
+ let argsStr;
302
+ try {
303
+ argsStr = JSON.stringify(args).slice(0, 4096);
304
+ }
305
+ catch {
306
+ argsStr = "[unserializable]";
307
+ }
308
+ span.setAttribute("tool.arguments_present", args !== undefined);
309
+ span.setAttribute("tool.arguments_size", argsStr.length);
310
+ // HITL Safety Check: Request confirmation if required
311
+ let finalArgs = args;
312
+ if (this.hitlManager && this.hitlManager.isEnabled()) {
313
+ const requiresConfirmation = this.hitlManager.requiresConfirmation(toolName, args);
314
+ if (requiresConfirmation) {
315
+ registryLogger.info(`Tool '${toolName}' requires HITL confirmation`);
316
+ span.addEvent("tool.hitl_requested");
317
+ try {
318
+ const confirmationResult = await this.hitlManager.requestConfirmation(toolName, args, {
319
+ serverId: tool.serverId,
320
+ sessionId: execContext.sessionId,
321
+ userId: execContext.userId,
322
+ });
323
+ if (!confirmationResult.approved) {
324
+ // User rejected the tool execution
325
+ span.addEvent("tool.hitl_rejected");
326
+ throw new HITLUserRejectedError(`Tool execution rejected by user: ${confirmationResult.reason || "No reason provided"}`, toolName, confirmationResult.reason);
327
+ }
328
+ span.addEvent("tool.hitl_approved");
329
+ // User approved - use modified arguments if provided
330
+ if (confirmationResult.modifiedArguments !== undefined) {
331
+ finalArgs = confirmationResult.modifiedArguments;
332
+ registryLogger.info(`Tool '${toolName}' arguments modified by user`);
333
+ }
334
+ registryLogger.info(`Tool '${toolName}' approved for execution (response time: ${confirmationResult.responseTime}ms)`);
277
335
  }
278
- // User approved - use modified arguments if provided
279
- if (confirmationResult.modifiedArguments !== undefined) {
280
- finalArgs = confirmationResult.modifiedArguments;
281
- registryLogger.info(`Tool '${toolName}' arguments modified by user`);
336
+ catch (error) {
337
+ if (error instanceof HITLTimeoutError) {
338
+ // Timeout occurred - user didn't respond in time
339
+ registryLogger.warn(`Tool '${toolName}' execution timed out waiting for user confirmation`);
340
+ throw error;
341
+ }
342
+ else if (error instanceof HITLUserRejectedError) {
343
+ // User explicitly rejected
344
+ registryLogger.info(`Tool '${toolName}' execution rejected by user`);
345
+ throw error;
346
+ }
347
+ else {
348
+ // Other HITL error (configuration, system error, etc.)
349
+ registryLogger.error(`HITL confirmation failed for tool '${toolName}':`, error);
350
+ throw new Error(`HITL confirmation failed: ${error instanceof Error ? error.message : String(error)}`);
351
+ }
282
352
  }
283
- registryLogger.info(`Tool '${toolName}' approved for execution (response time: ${confirmationResult.responseTime}ms)`);
284
353
  }
285
- catch (error) {
286
- if (error instanceof HITLTimeoutError) {
287
- // Timeout occurred - user didn't respond in time
288
- registryLogger.warn(`Tool '${toolName}' execution timed out waiting for user confirmation`);
289
- throw error;
290
- }
291
- else if (error instanceof HITLUserRejectedError) {
292
- // User explicitly rejected
293
- registryLogger.info(`Tool '${toolName}' execution rejected by user`);
294
- throw error;
295
- }
296
- else {
297
- // Other HITL error (configuration, system error, etc.)
298
- registryLogger.error(`HITL confirmation failed for tool '${toolName}':`, error);
299
- throw new Error(`HITL confirmation failed: ${error instanceof Error ? error.message : String(error)}`);
300
- }
354
+ else {
355
+ registryLogger.debug(`Tool '${toolName}' does not require HITL confirmation`);
301
356
  }
302
357
  }
358
+ // Execute the actual tool (with potentially modified arguments)
359
+ registryLogger.debug(`Executing tool '${toolName}' with args:`, finalArgs);
360
+ const toolResult = await toolImpl.execute(finalArgs, execContext);
361
+ // Properly wrap raw results in ToolResult format
362
+ let result;
363
+ // Check if result is already a ToolResult object
364
+ if (toolResult &&
365
+ typeof toolResult === "object" &&
366
+ "success" in toolResult &&
367
+ typeof toolResult.success === "boolean") {
368
+ // Result is already a ToolResult, enhance with metadata
369
+ const toolResultObj = toolResult;
370
+ result = {
371
+ ...toolResultObj,
372
+ usage: {
373
+ ...(toolResultObj.usage || {}),
374
+ executionTime: Date.now() - startTime,
375
+ },
376
+ metadata: {
377
+ ...(toolResultObj.metadata || {}),
378
+ toolName,
379
+ serverId: tool.serverId,
380
+ sessionId: execContext.sessionId,
381
+ executionTime: Date.now() - startTime,
382
+ },
383
+ };
384
+ }
303
385
  else {
304
- registryLogger.debug(`Tool '${toolName}' does not require HITL confirmation`);
386
+ // Result is a raw value, wrap it in ToolResult format
387
+ result = {
388
+ success: true,
389
+ data: toolResult,
390
+ usage: {
391
+ executionTime: Date.now() - startTime,
392
+ },
393
+ metadata: {
394
+ toolName,
395
+ serverId: tool.serverId,
396
+ sessionId: execContext.sessionId,
397
+ executionTime: Date.now() - startTime,
398
+ },
399
+ };
305
400
  }
401
+ // Update statistics
402
+ const duration = Date.now() - startTime;
403
+ this.updateStats(toolName, duration);
404
+ // Record success on span
405
+ let resultStr;
406
+ try {
407
+ resultStr = JSON.stringify(result.data);
408
+ }
409
+ catch {
410
+ resultStr = "[unserializable]";
411
+ }
412
+ span.setAttribute("tool.result_length", resultStr.length);
413
+ span.setAttribute("tool.success", true);
414
+ registryLogger.debug(`Tool '${toolName}' executed successfully in ${duration}ms`);
415
+ return result;
306
416
  }
307
- // Execute the actual tool (with potentially modified arguments)
308
- registryLogger.debug(`Executing tool '${toolName}' with args:`, finalArgs);
309
- const toolResult = await toolImpl.execute(finalArgs, execContext);
310
- // Properly wrap raw results in ToolResult format
311
- let result;
312
- // Check if result is already a ToolResult object
313
- if (toolResult &&
314
- typeof toolResult === "object" &&
315
- "success" in toolResult &&
316
- typeof toolResult.success === "boolean") {
317
- // Result is already a ToolResult, enhance with metadata
318
- const toolResultObj = toolResult;
319
- result = {
320
- ...toolResultObj,
321
- usage: {
322
- ...(toolResultObj.usage || {}),
323
- executionTime: Date.now() - startTime,
324
- },
325
- metadata: {
326
- ...(toolResultObj.metadata || {}),
327
- toolName,
328
- serverId: tool.serverId,
329
- sessionId: execContext.sessionId,
330
- executionTime: Date.now() - startTime,
331
- },
332
- };
333
- }
334
- else {
335
- // Result is a raw value, wrap it in ToolResult format
336
- result = {
337
- success: true,
338
- data: toolResult,
417
+ catch (error) {
418
+ registryLogger.error(`Tool execution failed: ${toolName}`, error);
419
+ // Record failure on span
420
+ span.setAttribute("tool.success", false);
421
+ // Rethrow precondition errors (tool not found, not executable)
422
+ const errMsg = error instanceof Error ? error.message : String(error);
423
+ if (errMsg.includes("not found in registry") ||
424
+ errMsg.includes("not executable")) {
425
+ throw error;
426
+ }
427
+ // Return runtime execution errors in ToolResult format
428
+ const errorResult = {
429
+ success: false,
430
+ data: null,
431
+ error: error instanceof Error ? error.message : String(error),
339
432
  usage: {
340
433
  executionTime: Date.now() - startTime,
341
434
  },
342
435
  metadata: {
343
436
  toolName,
344
- serverId: tool.serverId,
345
- sessionId: execContext.sessionId,
346
- executionTime: Date.now() - startTime,
437
+ sessionId: context?.sessionId,
347
438
  },
348
439
  };
440
+ return errorResult;
349
441
  }
350
- // Update statistics
351
- const duration = Date.now() - startTime;
352
- this.updateStats(toolName, duration);
353
- registryLogger.debug(`Tool '${toolName}' executed successfully in ${duration}ms`);
354
- return result;
355
- }
356
- catch (error) {
357
- registryLogger.error(`Tool execution failed: ${toolName}`, error);
358
- // Return error in ToolResult format
359
- const errorResult = {
360
- success: false,
361
- data: null,
362
- error: error instanceof Error ? error.message : String(error),
363
- usage: {
364
- executionTime: Date.now() - startTime,
365
- },
366
- metadata: {
367
- toolName,
368
- sessionId: context?.sessionId,
369
- },
370
- };
371
- return errorResult;
372
- }
442
+ });
373
443
  }
374
444
  async listTools(filterOrContext) {
375
445
  // FIXED: Return unique tools (avoid duplicates from dual registration)
@@ -0,0 +1,267 @@
1
+ /**
2
+ * Anthropic Models - Subscription Tier Access and Capabilities
3
+ *
4
+ * This module defines Anthropic Claude models, their availability by subscription tier,
5
+ * model capabilities, and provides helper functions for tier-based access control.
6
+ */
7
+ import type { ClaudeSubscriptionTier, AnthropicModelMetadata } from "../types/subscriptionTypes.js";
8
+ import { ModelAccessError } from "../types/errors.js";
9
+ export type { ClaudeSubscriptionTier, AnthropicModelMetadata };
10
+ export { ModelAccessError };
11
+ /**
12
+ * Anthropic Claude model identifiers
13
+ *
14
+ * @description Enum of all available Claude models with their exact API identifiers.
15
+ * Models are organized by family (Haiku, Sonnet, Opus) and version.
16
+ */
17
+ export declare enum AnthropicModel {
18
+ CLAUDE_3_HAIKU = "claude-3-haiku-20240307",
19
+ CLAUDE_3_5_HAIKU = "claude-3-5-haiku-20241022",
20
+ CLAUDE_3_5_SONNET = "claude-3-5-sonnet-20241022",
21
+ CLAUDE_3_5_SONNET_V2 = "claude-3-5-sonnet-v2-20241022",
22
+ CLAUDE_SONNET_4 = "claude-sonnet-4-20250514",
23
+ CLAUDE_3_OPUS = "claude-3-opus-20240229",
24
+ CLAUDE_OPUS_4 = "claude-opus-4-20250514"
25
+ }
26
+ /**
27
+ * Model access mapping by subscription tier
28
+ *
29
+ * Each tier includes progressively more models:
30
+ * - free: Basic models for casual use (Haiku only)
31
+ * - pro: Professional tier with Sonnet models
32
+ * - max: All models including the latest flagship Opus
33
+ * - api: Full API access to all models (based on API access)
34
+ */
35
+ export declare const MODEL_TIER_ACCESS: Record<ClaudeSubscriptionTier, string[]>;
36
+ /**
37
+ * Model metadata by model ID
38
+ *
39
+ * Comprehensive mapping of each Anthropic model's metadata,
40
+ * including display names, context windows, vision support, and extended thinking.
41
+ */
42
+ export declare const MODEL_METADATA: Record<string, AnthropicModelMetadata>;
43
+ /**
44
+ * Default model for each subscription tier
45
+ *
46
+ * These are the recommended default models that provide the best
47
+ * balance of capability and cost for each tier level.
48
+ */
49
+ export declare const DEFAULT_MODELS_BY_TIER: Record<ClaudeSubscriptionTier, string>;
50
+ /**
51
+ * Check if a model is available for a given subscription tier
52
+ *
53
+ * @param model - The model ID to check (can be enum value or string)
54
+ * @param tier - The subscription tier to check against
55
+ * @returns true if the model is available for the tier
56
+ *
57
+ * @example
58
+ * ```typescript
59
+ * if (isModelAvailableForTier(AnthropicModel.CLAUDE_OPUS_4, "pro")) {
60
+ * // Model not available for pro tier
61
+ * }
62
+ *
63
+ * if (isModelAvailableForTier(AnthropicModel.CLAUDE_OPUS_4, "max")) {
64
+ * // Model available for max tier
65
+ * }
66
+ * ```
67
+ */
68
+ export declare function isModelAvailableForTier(model: string, tier: ClaudeSubscriptionTier): boolean;
69
+ /**
70
+ * Get all models available for a given subscription tier
71
+ *
72
+ * @param tier - The subscription tier
73
+ * @returns Array of model IDs available for the tier
74
+ *
75
+ * @example
76
+ * ```typescript
77
+ * const models = getAvailableModelsForTier("pro");
78
+ * console.log(models);
79
+ * // ["claude-3-haiku-20240307", "claude-3-5-haiku-20241022", "claude-3-5-sonnet-20241022", ...]
80
+ * ```
81
+ */
82
+ export declare function getAvailableModelsForTier(tier: ClaudeSubscriptionTier): string[];
83
+ /**
84
+ * Get the human-readable display name for a model
85
+ *
86
+ * @param model - The model ID
87
+ * @returns The display name, or the model ID if not found
88
+ *
89
+ * @example
90
+ * ```typescript
91
+ * const name = getModelDisplayName(AnthropicModel.CLAUDE_OPUS_4);
92
+ * console.log(name); // "Claude Opus 4"
93
+ *
94
+ * const unknown = getModelDisplayName("unknown-model");
95
+ * console.log(unknown); // "unknown-model"
96
+ * ```
97
+ */
98
+ export declare function getModelDisplayName(model: string): string;
99
+ /**
100
+ * Get the default/recommended model for a given subscription tier
101
+ *
102
+ * Returns the best default model that should be used for each tier.
103
+ *
104
+ * @param tier - The subscription tier
105
+ * @returns The default model ID for the tier
106
+ *
107
+ * @example
108
+ * ```typescript
109
+ * const model = getDefaultModelForTier("max");
110
+ * console.log(model); // "claude-opus-4-20250514"
111
+ *
112
+ * const proModel = getDefaultModelForTier("pro");
113
+ * console.log(proModel); // "claude-sonnet-4-20250514"
114
+ * ```
115
+ */
116
+ export declare function getDefaultModelForTier(tier: ClaudeSubscriptionTier): string;
117
+ /**
118
+ * Get metadata for a specific model
119
+ *
120
+ * @param model - The model ID
121
+ * @returns The model metadata, or undefined if not found
122
+ *
123
+ * @example
124
+ * ```typescript
125
+ * const metadata = getModelMetadata(AnthropicModel.CLAUDE_OPUS_4);
126
+ * if (metadata?.supportsExtendedThinking) {
127
+ * // Enable extended thinking mode
128
+ * }
129
+ * ```
130
+ */
131
+ export declare function getModelMetadata(model: string): AnthropicModelMetadata | undefined;
132
+ /**
133
+ * Check if a model supports a specific capability
134
+ *
135
+ * @param model - The model ID
136
+ * @param capability - The capability to check
137
+ * @returns true if the model supports the capability
138
+ *
139
+ * @example
140
+ * ```typescript
141
+ * if (modelSupportsCapability(AnthropicModel.CLAUDE_OPUS_4, "supportsExtendedThinking")) {
142
+ * // Use extended thinking
143
+ * }
144
+ * ```
145
+ */
146
+ export declare function modelSupportsCapability(model: string, capability: keyof Omit<AnthropicModelMetadata, "displayName" | "description" | "family">): boolean;
147
+ /**
148
+ * Get the minimum subscription tier required for a model
149
+ *
150
+ * @param model - The model ID to check
151
+ * @returns The minimum tier required, or "api" if model not found
152
+ *
153
+ * @example
154
+ * ```typescript
155
+ * const tier = getMinimumTierForModel(AnthropicModel.CLAUDE_OPUS_4);
156
+ * console.log(tier); // "max"
157
+ *
158
+ * const haikuTier = getMinimumTierForModel(AnthropicModel.CLAUDE_3_HAIKU);
159
+ * console.log(haikuTier); // "free"
160
+ * ```
161
+ */
162
+ export declare function getMinimumTierForModel(model: string): ClaudeSubscriptionTier;
163
+ /**
164
+ * Get all models that support a specific capability
165
+ *
166
+ * @param capability - The capability to filter by
167
+ * @returns Array of model IDs that have the capability
168
+ *
169
+ * @example
170
+ * ```typescript
171
+ * const thinkingModels = getModelsWithCapability("supportsExtendedThinking");
172
+ * console.log(thinkingModels);
173
+ * // ["claude-sonnet-4-20250514", "claude-opus-4-20250514"]
174
+ * ```
175
+ */
176
+ export declare function getModelsWithCapability(capability: keyof Omit<AnthropicModelMetadata, "displayName" | "description" | "family">): string[];
177
+ /**
178
+ * Get models filtered by family (haiku, sonnet, opus)
179
+ *
180
+ * @param family - The model family to filter by
181
+ * @returns Array of model IDs in the specified family
182
+ *
183
+ * @example
184
+ * ```typescript
185
+ * const opusModels = getModelsByFamily("opus");
186
+ * // ["claude-3-opus-20240229", "claude-opus-4-20250514"]
187
+ * ```
188
+ */
189
+ export declare function getModelsByFamily(family: AnthropicModelMetadata["family"]): string[];
190
+ /**
191
+ * Get the latest (non-deprecated) model in each family
192
+ *
193
+ * @returns Object mapping family name to the latest model in that family
194
+ *
195
+ * @example
196
+ * ```typescript
197
+ * const latest = getLatestModelsByFamily();
198
+ * console.log(latest.opus); // "claude-opus-4-20250514"
199
+ * console.log(latest.sonnet); // "claude-sonnet-4-20250514"
200
+ * ```
201
+ */
202
+ export declare function getLatestModelsByFamily(): Record<AnthropicModelMetadata["family"], string | undefined>;
203
+ /**
204
+ * Validate that a model is accessible for a given tier, throwing if not
205
+ *
206
+ * @param model - The model ID to validate
207
+ * @param tier - The subscription tier to validate against
208
+ * @throws {ModelAccessError} If the model is not available for the tier
209
+ *
210
+ * @example
211
+ * ```typescript
212
+ * try {
213
+ * validateModelAccess(AnthropicModel.CLAUDE_OPUS_4, "free");
214
+ * } catch (error) {
215
+ * if (error instanceof ModelAccessError) {
216
+ * console.log(`Upgrade to ${error.requiredTier} to use this model`);
217
+ * }
218
+ * }
219
+ * ```
220
+ */
221
+ export declare function validateModelAccess(model: string, tier: ClaudeSubscriptionTier): void;
222
+ /**
223
+ * Compare subscription tiers
224
+ *
225
+ * @param tier1 - First tier to compare
226
+ * @param tier2 - Second tier to compare
227
+ * @returns Negative if tier1 < tier2, positive if tier1 > tier2, 0 if equal
228
+ */
229
+ export declare function compareTiers(tier1: ClaudeSubscriptionTier, tier2: ClaudeSubscriptionTier): number;
230
+ /**
231
+ * Get context window size for a model
232
+ *
233
+ * @param model - The model ID
234
+ * @returns The context window size in tokens, or 0 if model not found
235
+ */
236
+ export declare function getContextWindow(model: string): number;
237
+ /**
238
+ * Get max output tokens for a model
239
+ *
240
+ * @param model - The model ID
241
+ * @returns The max output tokens, or 0 if model not found
242
+ */
243
+ export declare function getMaxOutputTokens(model: string): number;
244
+ /**
245
+ * Check if a model supports vision/image input
246
+ *
247
+ * @param model - The model ID
248
+ * @returns true if the model supports vision
249
+ */
250
+ export declare function supportsVision(model: string): boolean;
251
+ /**
252
+ * Check if a model supports extended thinking
253
+ *
254
+ * @param model - The model ID
255
+ * @returns true if the model supports extended thinking
256
+ */
257
+ export declare function supportsExtendedThinking(model: string): boolean;
258
+ /**
259
+ * Alias for getDefaultModelForTier for backward compatibility
260
+ * @deprecated Use getDefaultModelForTier instead
261
+ */
262
+ export declare const getRecommendedModelForTier: typeof getDefaultModelForTier;
263
+ /**
264
+ * Alias for getModelMetadata for backward compatibility
265
+ * @deprecated Use getModelMetadata instead
266
+ */
267
+ export declare const getModelCapabilities: typeof getModelMetadata;