@juspay/neurolink 7.8.0 → 7.10.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 (52) hide show
  1. package/CHANGELOG.md +22 -5
  2. package/README.md +22 -7
  3. package/dist/agent/directTools.d.ts +23 -843
  4. package/dist/agent/directTools.js +1 -3
  5. package/dist/cli/commands/mcp.js +66 -27
  6. package/dist/cli/commands/ollama.js +7 -3
  7. package/dist/cli/commands/sagemaker.js +145 -144
  8. package/dist/cli/factories/commandFactory.js +10 -6
  9. package/dist/core/dynamicModels.js +6 -0
  10. package/dist/core/types.d.ts +15 -4
  11. package/dist/core/types.js +23 -3
  12. package/dist/factories/providerFactory.js +10 -1
  13. package/dist/factories/providerRegistry.js +1 -1
  14. package/dist/lib/agent/directTools.d.ts +23 -843
  15. package/dist/lib/agent/directTools.js +1 -3
  16. package/dist/lib/core/dynamicModels.js +6 -0
  17. package/dist/lib/core/types.d.ts +15 -4
  18. package/dist/lib/core/types.js +23 -3
  19. package/dist/lib/factories/providerFactory.js +10 -1
  20. package/dist/lib/factories/providerRegistry.js +1 -1
  21. package/dist/lib/neurolink.d.ts +15 -0
  22. package/dist/lib/neurolink.js +73 -1
  23. package/dist/lib/providers/googleVertex.d.ts +4 -0
  24. package/dist/lib/providers/googleVertex.js +44 -3
  25. package/dist/lib/providers/sagemaker/client.js +2 -2
  26. package/dist/lib/sdk/toolRegistration.d.ts +1 -1
  27. package/dist/lib/sdk/toolRegistration.js +13 -5
  28. package/dist/lib/utils/providerHealth.js +20 -5
  29. package/dist/mcp/servers/agent/directToolsServer.js +0 -1
  30. package/dist/mcp/servers/aiProviders/aiCoreServer.js +0 -1
  31. package/dist/models/modelResolver.js +0 -1
  32. package/dist/neurolink.d.ts +15 -0
  33. package/dist/neurolink.js +73 -1
  34. package/dist/providers/amazonBedrock.js +2 -2
  35. package/dist/providers/anthropic.js +2 -2
  36. package/dist/providers/anthropicBaseProvider.js +2 -2
  37. package/dist/providers/googleAiStudio.js +2 -3
  38. package/dist/providers/googleVertex.d.ts +4 -0
  39. package/dist/providers/googleVertex.js +44 -3
  40. package/dist/providers/litellm.js +4 -4
  41. package/dist/providers/ollama.js +1 -2
  42. package/dist/providers/openAI.js +2 -2
  43. package/dist/providers/openaiCompatible.js +1 -2
  44. package/dist/providers/sagemaker/client.js +2 -2
  45. package/dist/providers/sagemaker/errors.js +1 -1
  46. package/dist/providers/sagemaker/language-model.js +1 -1
  47. package/dist/sdk/toolRegistration.d.ts +1 -1
  48. package/dist/sdk/toolRegistration.js +13 -6
  49. package/dist/telemetry/telemetryService.js +0 -2
  50. package/dist/types/tools.js +0 -1
  51. package/dist/utils/providerHealth.js +20 -5
  52. package/package.json +43 -5
package/dist/neurolink.js CHANGED
@@ -26,15 +26,32 @@ import { validateTool, createMCPServerFromTools, } from "./sdk/toolRegistration.
26
26
  import { processFactoryOptions, enhanceTextGenerationOptions, validateFactoryConfig, processStreamingFactoryOptions, createCleanStreamOptions, } from "./utils/factoryProcessing.js";
27
27
  // Enhanced error handling imports
28
28
  import { ErrorFactory, NeuroLinkError, withTimeout, withRetry, isRetriableError, logStructuredError, CircuitBreaker, } from "./utils/errorHandling.js";
29
+ import { EventEmitter } from "events";
29
30
  // Core types imported from core/types.js
30
31
  export class NeuroLink {
31
32
  mcpInitialized = false;
33
+ emitter = new EventEmitter();
32
34
  // Tool registration support
33
35
  customTools = new Map();
34
36
  inMemoryServers = new Map();
35
37
  // Enhanced error handling support
36
38
  toolCircuitBreakers = new Map();
37
39
  toolExecutionMetrics = new Map();
40
+ /**
41
+ * Helper method to emit tool end event in a consistent way
42
+ * Used by executeTool in both success and error paths
43
+ * @param toolName - Name of the tool
44
+ * @param startTime - Timestamp when tool execution started
45
+ * @param success - Whether the tool execution was successful
46
+ */
47
+ emitToolEndEvent(toolName, startTime, success) {
48
+ this.emitter.emit("tool:end", {
49
+ toolName,
50
+ responseTime: Date.now() - startTime,
51
+ success,
52
+ timestamp: Date.now(),
53
+ });
54
+ }
38
55
  constructor() {
39
56
  // SDK always disables manual MCP config for security
40
57
  ProviderRegistry.setOptions({
@@ -91,7 +108,6 @@ export class NeuroLink {
91
108
  * Replaces both generateText and legacy methods
92
109
  */
93
110
  async generate(optionsOrPrompt) {
94
- const startTime = Date.now();
95
111
  // Convert string prompt to full options
96
112
  const options = typeof optionsOrPrompt === "string"
97
113
  ? { input: { text: optionsOrPrompt } }
@@ -100,6 +116,12 @@ export class NeuroLink {
100
116
  if (!options.input?.text || typeof options.input.text !== "string") {
101
117
  throw new Error("Input text is required and must be a non-empty string");
102
118
  }
119
+ const startTime = Date.now();
120
+ // Emit generation start event
121
+ this.emitter.emit("generation:start", {
122
+ provider: options.provider || "auto",
123
+ timestamp: startTime,
124
+ });
103
125
  // Process factory configuration
104
126
  const factoryResult = processFactoryOptions(options);
105
127
  // Validate factory configuration if present
@@ -142,6 +164,13 @@ export class NeuroLink {
142
164
  }
143
165
  // Use redesigned generation logic
144
166
  const textResult = await this.generateTextInternal(textOptions);
167
+ // Emit generation completion event
168
+ this.emitter.emit("generation:end", {
169
+ provider: textResult.provider,
170
+ responseTime: Date.now() - startTime,
171
+ toolsUsed: textResult.toolsUsed,
172
+ timestamp: Date.now(),
173
+ });
145
174
  // Convert back to GenerateResult
146
175
  const generateResult = {
147
176
  content: textResult.content,
@@ -509,6 +538,11 @@ export class NeuroLink {
509
538
  options.input.text.trim() === "") {
510
539
  throw new Error("Stream options must include input.text as a non-empty string");
511
540
  }
541
+ // Emit stream start event
542
+ this.emitter.emit("stream:start", {
543
+ provider: options.provider || "auto",
544
+ timestamp: startTime,
545
+ });
512
546
  // Process factory configuration for streaming
513
547
  const factoryResult = processFactoryOptions(options);
514
548
  const streamingResult = processStreamingFactoryOptions(options);
@@ -576,6 +610,11 @@ export class NeuroLink {
576
610
  responseTime,
577
611
  provider: providerName,
578
612
  });
613
+ // Emit stream completion event
614
+ this.emitter.emit("stream:end", {
615
+ provider: providerName,
616
+ responseTime,
617
+ });
579
618
  // Convert to StreamResult format - Include analytics and evaluation from provider
580
619
  return {
581
620
  stream,
@@ -615,6 +654,12 @@ export class NeuroLink {
615
654
  const cleanOptions = createCleanStreamOptions(enhancedOptions);
616
655
  const streamResult = await provider.stream(cleanOptions);
617
656
  const responseTime = Date.now() - startTime;
657
+ // Emit stream completion event for fallback
658
+ this.emitter.emit("stream:end", {
659
+ provider: providerName,
660
+ responseTime,
661
+ fallback: true,
662
+ });
618
663
  return {
619
664
  stream: streamResult.stream,
620
665
  provider: providerName,
@@ -643,6 +688,13 @@ export class NeuroLink {
643
688
  };
644
689
  }
645
690
  }
691
+ /**
692
+ * Get the EventEmitter to listen to NeuroLink events
693
+ * @returns EventEmitter instance
694
+ */
695
+ getEventEmitter() {
696
+ return this.emitter;
697
+ }
646
698
  // ========================================
647
699
  // Tool Registration API
648
700
  // ========================================
@@ -652,6 +704,11 @@ export class NeuroLink {
652
704
  * @param tool - Tool configuration
653
705
  */
654
706
  registerTool(name, tool) {
707
+ // Emit tool registration start event
708
+ this.emitter.emit("tools-register:start", {
709
+ toolName: name,
710
+ timestamp: Date.now(),
711
+ });
655
712
  try {
656
713
  // Validate tool configuration
657
714
  validateTool(name, tool);
@@ -666,6 +723,12 @@ export class NeuroLink {
666
723
  // Store as in-memory server
667
724
  this.inMemoryServers.set(serverId, mcpServer);
668
725
  logger.info(`Registered custom tool: ${name}`);
726
+ // Emit tool registration success event
727
+ this.emitter.emit("tools-register:end", {
728
+ toolName: name,
729
+ success: true,
730
+ timestamp: Date.now(),
731
+ });
669
732
  }
670
733
  catch (error) {
671
734
  logger.error(`Failed to register tool ${name}:`, error);
@@ -758,6 +821,11 @@ export class NeuroLink {
758
821
  async executeTool(toolName, params = {}, options) {
759
822
  const functionTag = "NeuroLink.executeTool";
760
823
  const executionStartTime = Date.now();
824
+ // Emit tool start event
825
+ this.emitter.emit("tool:start", {
826
+ toolName,
827
+ timestamp: executionStartTime,
828
+ });
761
829
  // Set default options
762
830
  const finalOptions = {
763
831
  timeout: options?.timeout || 30000, // 30 second default timeout
@@ -832,6 +900,8 @@ export class NeuroLink {
832
900
  memoryDelta,
833
901
  circuitBreakerState: circuitBreaker.getState(),
834
902
  });
903
+ // Emit tool end event using the helper method
904
+ this.emitToolEndEvent(toolName, executionStartTime, true);
835
905
  return result;
836
906
  }
837
907
  catch (error) {
@@ -867,6 +937,8 @@ export class NeuroLink {
867
937
  else {
868
938
  structuredError = ErrorFactory.toolExecutionFailed(toolName, new Error(String(error)));
869
939
  }
940
+ // Emit tool end event using the helper method
941
+ this.emitToolEndEvent(toolName, executionStartTime, false);
870
942
  // Add execution context to structured error
871
943
  structuredError = new NeuroLinkError({
872
944
  ...structuredError,
@@ -1,8 +1,8 @@
1
1
  import { createAmazonBedrock } from "@ai-sdk/amazon-bedrock";
2
- import { streamText, Output } from "ai";
2
+ import { streamText } from "ai";
3
3
  import { BaseProvider } from "../core/baseProvider.js";
4
4
  import { logger } from "../utils/logger.js";
5
- import { createTimeoutController, TimeoutError, getDefaultTimeout, } from "../utils/timeout.js";
5
+ import { TimeoutError, } from "../utils/timeout.js";
6
6
  import { DEFAULT_MAX_TOKENS } from "../core/constants.js";
7
7
  import { validateApiKey, createAWSAccessKeyConfig, createAWSSecretConfig, getAWSRegion, getAWSSessionToken, } from "../utils/providerConfig.js";
8
8
  // Configuration helpers
@@ -1,8 +1,8 @@
1
1
  import { anthropic } from "@ai-sdk/anthropic";
2
- import { streamText, Output } from "ai";
2
+ import { streamText } from "ai";
3
3
  import { BaseProvider } from "../core/baseProvider.js";
4
4
  import { logger } from "../utils/logger.js";
5
- import { createTimeoutController, TimeoutError, getDefaultTimeout, } from "../utils/timeout.js";
5
+ import { createTimeoutController, TimeoutError, } from "../utils/timeout.js";
6
6
  import { DEFAULT_MAX_TOKENS } from "../core/constants.js";
7
7
  import { validateApiKey, createAnthropicConfig, getProviderModel, } from "../utils/providerConfig.js";
8
8
  // Configuration helpers - now using consolidated utility
@@ -1,8 +1,8 @@
1
1
  import { createAnthropic } from "@ai-sdk/anthropic";
2
- import { streamText, Output } from "ai";
2
+ import { streamText } from "ai";
3
3
  import { BaseProvider } from "../core/baseProvider.js";
4
4
  import { logger } from "../utils/logger.js";
5
- import { createTimeoutController, TimeoutError, getDefaultTimeout, } from "../utils/timeout.js";
5
+ import { createTimeoutController, TimeoutError, } from "../utils/timeout.js";
6
6
  import { DEFAULT_MAX_TOKENS } from "../core/constants.js";
7
7
  import { validateApiKey, createAnthropicBaseConfig, } from "../utils/providerConfig.js";
8
8
  /**
@@ -1,11 +1,10 @@
1
1
  import { createGoogleGenerativeAI } from "@ai-sdk/google";
2
- import { streamText, Output } from "ai";
2
+ import { streamText } from "ai";
3
3
  import { GoogleAIModels } from "../core/types.js";
4
4
  import { BaseProvider } from "../core/baseProvider.js";
5
5
  import { logger } from "../utils/logger.js";
6
- import { createTimeoutController, TimeoutError, getDefaultTimeout, } from "../utils/timeout.js";
6
+ import { createTimeoutController, TimeoutError, } from "../utils/timeout.js";
7
7
  import { DEFAULT_MAX_TOKENS } from "../core/constants.js";
8
- import { createProxyFetch } from "../proxy/proxyFetch.js";
9
8
  import { streamAnalyticsCollector } from "../core/streamAnalytics.js";
10
9
  // Environment variable setup
11
10
  if (!process.env.GOOGLE_GENERATIVE_AI_API_KEY &&
@@ -108,6 +108,10 @@ export declare class GoogleVertexProvider extends BaseProvider {
108
108
  maxTokens: number;
109
109
  };
110
110
  };
111
+ /**
112
+ * Get model suggestions when a model is not found
113
+ */
114
+ private getModelSuggestions;
111
115
  }
112
116
  export default GoogleVertexProvider;
113
117
  export { GoogleVertexProvider as GoogleVertexAI };
@@ -40,9 +40,9 @@ const getVertexLocation = () => {
40
40
  "us-central1");
41
41
  };
42
42
  const getDefaultVertexModel = () => {
43
- // Use gemini-1.5-pro as default - stable and widely supported model
43
+ // Use gemini-2.5-flash as default - latest and best price-performance model
44
44
  // Override with VERTEX_MODEL environment variable if needed
45
- return process.env.VERTEX_MODEL || "gemini-1.5-pro";
45
+ return process.env.VERTEX_MODEL || "gemini-2.5-flash";
46
46
  };
47
47
  const hasGoogleCredentials = () => {
48
48
  return !!(process.env.GOOGLE_APPLICATION_CREDENTIALS ||
@@ -276,7 +276,8 @@ export class GoogleVertexProvider extends BaseProvider {
276
276
  return new Error(`❌ Google Vertex AI Permission Denied\n\nYour Google Cloud credentials don't have permission to access Vertex AI.\n\nRequired Steps:\n1. Ensure your service account has Vertex AI User role\n2. Check if Vertex AI API is enabled in your project\n3. Verify your project ID is correct\n4. Confirm your location/region has Vertex AI available`);
277
277
  }
278
278
  if (message.includes("NOT_FOUND")) {
279
- return new Error(`❌ Google Vertex AI Model Not Found\n\n${message}\n\nCheck:\n1. Model name is correct (e.g., 'gemini-1.5-pro')\n2. Model is available in your region (${this.location})\n3. Your project has access to the model\n4. Model supports your request parameters`);
279
+ const modelSuggestions = this.getModelSuggestions(this.modelName);
280
+ return new Error(`❌ Google Vertex AI Model Not Found\n\n${message}\n\nModel '${this.modelName}' is not available.\n\nSuggested alternatives:\n${modelSuggestions}\n\nTroubleshooting:\n1. Check model name spelling and format\n2. Verify model is available in your region (${this.location})\n3. Ensure your project has access to the model\n4. For Claude models, enable Anthropic integration in Google Cloud Console`);
280
281
  }
281
282
  if (message.includes("QUOTA_EXCEEDED")) {
282
283
  return new Error(`❌ Google Vertex AI Quota Exceeded\n\n${message}\n\nSolutions:\n1. Check your Vertex AI quotas in Google Cloud Console\n2. Request quota increase if needed\n3. Try a different model or reduce request frequency\n4. Consider using a different region`);
@@ -520,6 +521,46 @@ export class GoogleVertexProvider extends BaseProvider {
520
521
  },
521
522
  };
522
523
  }
524
+ /**
525
+ * Get model suggestions when a model is not found
526
+ */
527
+ getModelSuggestions(requestedModel) {
528
+ const availableModels = {
529
+ google: [
530
+ "gemini-2.5-pro",
531
+ "gemini-2.5-flash",
532
+ "gemini-2.5-flash-lite",
533
+ "gemini-2.0-flash-001",
534
+ "gemini-1.5-pro",
535
+ "gemini-1.5-flash",
536
+ ],
537
+ claude: [
538
+ "claude-sonnet-4@20250514",
539
+ "claude-opus-4@20250514",
540
+ "claude-3-5-sonnet-20241022",
541
+ "claude-3-5-haiku-20241022",
542
+ "claude-3-sonnet-20240229",
543
+ "claude-3-haiku-20240307",
544
+ "claude-3-opus-20240229",
545
+ ],
546
+ };
547
+ let suggestions = "\n🤖 Google Models (always available):\n";
548
+ availableModels.google.forEach((model) => {
549
+ suggestions += ` • ${model}\n`;
550
+ });
551
+ suggestions += "\n🧠 Claude Models (requires Anthropic integration):\n";
552
+ availableModels.claude.forEach((model) => {
553
+ suggestions += ` • ${model}\n`;
554
+ });
555
+ // If the requested model looks like a Claude model, provide specific guidance
556
+ if (requestedModel && requestedModel.toLowerCase().includes("claude")) {
557
+ suggestions += `\n💡 Tip: "${requestedModel}" appears to be a Claude model.\n`;
558
+ suggestions +=
559
+ "Ensure Anthropic integration is enabled in your Google Cloud project.\n";
560
+ suggestions += "Try using an available Claude model from the list above.";
561
+ }
562
+ return suggestions;
563
+ }
523
564
  }
524
565
  export default GoogleVertexProvider;
525
566
  // Re-export for compatibility
@@ -1,10 +1,10 @@
1
- import { openai, createOpenAI } from "@ai-sdk/openai";
2
- import { streamText, Output } from "ai";
1
+ import { createOpenAI } from "@ai-sdk/openai";
2
+ import { streamText } from "ai";
3
3
  import { BaseProvider } from "../core/baseProvider.js";
4
4
  import { logger } from "../utils/logger.js";
5
- import { createTimeoutController, TimeoutError, getDefaultTimeout, } from "../utils/timeout.js";
5
+ import { createTimeoutController, TimeoutError, } from "../utils/timeout.js";
6
6
  import { DEFAULT_MAX_TOKENS } from "../core/constants.js";
7
- import { validateApiKey, getProviderModel } from "../utils/providerConfig.js";
7
+ import { getProviderModel } from "../utils/providerConfig.js";
8
8
  import { streamAnalyticsCollector } from "../core/streamAnalytics.js";
9
9
  // Configuration helpers
10
10
  const getLiteLLMConfig = () => {
@@ -1,7 +1,6 @@
1
- import { streamText, Output } from "ai";
2
1
  import { BaseProvider } from "../core/baseProvider.js";
3
2
  import { logger } from "../utils/logger.js";
4
- import { getDefaultTimeout, TimeoutError } from "../utils/timeout.js";
3
+ import { TimeoutError } from "../utils/timeout.js";
5
4
  import { DEFAULT_MAX_TOKENS } from "../core/constants.js";
6
5
  import { modelConfig } from "../core/modelConfiguration.js";
7
6
  // Model version constants (configurable via environment)
@@ -1,9 +1,9 @@
1
1
  import { openai } from "@ai-sdk/openai";
2
- import { streamText, Output } from "ai";
2
+ import { streamText } from "ai";
3
3
  import { AIProviderName } from "../core/types.js";
4
4
  import { BaseProvider } from "../core/baseProvider.js";
5
5
  import { logger } from "../utils/logger.js";
6
- import { createTimeoutController, TimeoutError, getDefaultTimeout, } from "../utils/timeout.js";
6
+ import { createTimeoutController, TimeoutError, } from "../utils/timeout.js";
7
7
  import { DEFAULT_MAX_TOKENS } from "../core/constants.js";
8
8
  import { validateApiKey, createOpenAIConfig, getProviderModel, } from "../utils/providerConfig.js";
9
9
  import { streamAnalyticsCollector } from "../core/streamAnalytics.js";
@@ -2,9 +2,8 @@ import { createOpenAI } from "@ai-sdk/openai";
2
2
  import { streamText } from "ai";
3
3
  import { BaseProvider } from "../core/baseProvider.js";
4
4
  import { logger } from "../utils/logger.js";
5
- import { createTimeoutController, TimeoutError, getDefaultTimeout, } from "../utils/timeout.js";
5
+ import { createTimeoutController, TimeoutError, } from "../utils/timeout.js";
6
6
  import { DEFAULT_MAX_TOKENS } from "../core/constants.js";
7
- import { validateApiKey, getProviderModel } from "../utils/providerConfig.js";
8
7
  import { streamAnalyticsCollector } from "../core/streamAnalytics.js";
9
8
  // Constants
10
9
  const FALLBACK_OPENAI_COMPATIBLE_MODEL = "gpt-3.5-turbo";
@@ -77,7 +77,7 @@ export class SageMakerRuntimeClient {
77
77
  if (!client) {
78
78
  throw new Error("SageMaker client has been disposed");
79
79
  }
80
- const response = await this.executeWithRetry(() => client.send(command), params.EndpointName);
80
+ const response = (await this.executeWithRetry(() => client.send(command), params.EndpointName));
81
81
  const duration = Date.now() - startTime;
82
82
  logger.debug("SageMaker endpoint invocation successful", {
83
83
  endpointName: params.EndpointName,
@@ -134,7 +134,7 @@ export class SageMakerRuntimeClient {
134
134
  if (!client) {
135
135
  throw new Error("SageMaker client has been disposed");
136
136
  }
137
- const response = await this.executeWithRetry(() => client.send(command), params.EndpointName);
137
+ const response = (await this.executeWithRetry(() => client.send(command), params.EndpointName));
138
138
  logger.debug("SageMaker streaming invocation started", {
139
139
  endpointName: params.EndpointName,
140
140
  setupDuration: Date.now() - startTime,
@@ -4,7 +4,7 @@
4
4
  * This module provides comprehensive error handling, categorization,
5
5
  * and user-friendly error messages for SageMaker operations.
6
6
  */
7
- import { ERROR_MESSAGE_TEMPLATES, ERROR_MESSAGE_PREFIXES, RETRY_DELAYS, RETRYABLE_ERROR_CONDITIONS, AWS_ERROR_MAPPINGS, ERROR_KEYWORDS, } from "./error-constants.js";
7
+ import { ERROR_MESSAGE_TEMPLATES, ERROR_MESSAGE_PREFIXES, RETRY_DELAYS, RETRYABLE_ERROR_CONDITIONS, ERROR_KEYWORDS, } from "./error-constants.js";
8
8
  /**
9
9
  * Custom error class for SageMaker-specific errors
10
10
  */
@@ -8,7 +8,7 @@ import { randomUUID } from "crypto";
8
8
  import { SageMakerRuntimeClient } from "./client.js";
9
9
  import { handleSageMakerError } from "./errors.js";
10
10
  import { estimateTokenUsage, createSageMakerStream } from "./streaming.js";
11
- import { AdaptiveSemaphore, createAdaptiveSemaphore, } from "./adaptive-semaphore.js";
11
+ import { createAdaptiveSemaphore, } from "./adaptive-semaphore.js";
12
12
  import { logger } from "../../utils/logger.js";
13
13
  /**
14
14
  * Base synthetic streaming delay in milliseconds for simulating real-time response
@@ -13,7 +13,7 @@ import type { JsonValue } from "../types/common.js";
13
13
  */
14
14
  declare const VALIDATION_CONFIG: {
15
15
  readonly NAME_MIN_LENGTH: 2;
16
- readonly NAME_MAX_LENGTH: 50;
16
+ readonly NAME_MAX_LENGTH: number;
17
17
  readonly DESCRIPTION_MIN_LENGTH: 10;
18
18
  readonly DESCRIPTION_MAX_LENGTH: number;
19
19
  readonly RESERVED_NAMES: Set<string>;
@@ -4,20 +4,23 @@
4
4
  */
5
5
  import { z } from "zod";
6
6
  import { tool as createAISDKTool } from "ai";
7
- import { zodToJsonSchema } from "zod-to-json-schema";
8
7
  import { logger } from "../utils/logger.js";
9
8
  /**
10
9
  * Configuration constants for tool validation
11
10
  */
12
- const envValue = parseInt(process.env.NEUROLINK_TOOL_DESCRIPTION_MAX_LENGTH || "200", 10);
13
- const DEFAULT_DESCRIPTION_MAX_LENGTH = Number.isInteger(envValue) && envValue > 0 ? envValue : 200;
11
+ const envDescValue = parseInt(process.env.NEUROLINK_TOOL_DESCRIPTION_MAX_LENGTH || "200", 10);
12
+ // Allow 0 to mean unlimited (no length restriction)
13
+ const DEFAULT_DESCRIPTION_MAX_LENGTH = Number.isInteger(envDescValue) && envDescValue >= 0 ? envDescValue : 200;
14
+ const envNameValue = parseInt(process.env.NEUROLINK_TOOL_NAME_MAX_LENGTH || "50", 10);
15
+ // Allow 0 to mean unlimited (no length restriction)
16
+ const DEFAULT_NAME_MAX_LENGTH = Number.isInteger(envNameValue) && envNameValue >= 0 ? envNameValue : 50;
14
17
  /**
15
18
  * Enhanced validation configuration
16
19
  */
17
20
  const VALIDATION_CONFIG = {
18
21
  // Tool name constraints
19
22
  NAME_MIN_LENGTH: 2,
20
- NAME_MAX_LENGTH: 50,
23
+ NAME_MAX_LENGTH: DEFAULT_NAME_MAX_LENGTH,
21
24
  // Description constraints
22
25
  DESCRIPTION_MIN_LENGTH: 10,
23
26
  DESCRIPTION_MAX_LENGTH: DEFAULT_DESCRIPTION_MAX_LENGTH,
@@ -211,7 +214,9 @@ function validateToolName(name) {
211
214
  `Minimum length: ${VALIDATION_CONFIG.NAME_MIN_LENGTH} characters. ` +
212
215
  `Example: 'get_data', 'send_email'`);
213
216
  }
214
- if (trimmedName.length > VALIDATION_CONFIG.NAME_MAX_LENGTH) {
217
+ // Only check name length if limit is greater than 0 (0 means unlimited)
218
+ if (VALIDATION_CONFIG.NAME_MAX_LENGTH > 0 &&
219
+ trimmedName.length > VALIDATION_CONFIG.NAME_MAX_LENGTH) {
215
220
  throw new Error(`Tool name too long: '${name}' (${trimmedName.length} chars). ` +
216
221
  `Maximum length: ${VALIDATION_CONFIG.NAME_MAX_LENGTH} characters. ` +
217
222
  `Consider shortening: '${trimmedName.substring(0, 20)}...'`);
@@ -255,7 +260,9 @@ function validateToolDescription(name, description) {
255
260
  `The description should clearly explain what the tool does and when to use it. ` +
256
261
  `Example: "Fetches current weather data for a specified location using coordinates or city name"`);
257
262
  }
258
- if (trimmedDescription.length > VALIDATION_CONFIG.DESCRIPTION_MAX_LENGTH) {
263
+ // Only check description length if limit is greater than 0 (0 means unlimited)
264
+ if (VALIDATION_CONFIG.DESCRIPTION_MAX_LENGTH > 0 &&
265
+ trimmedDescription.length > VALIDATION_CONFIG.DESCRIPTION_MAX_LENGTH) {
259
266
  throw new Error(`Tool '${name}' description too long: ${trimmedDescription.length} characters. ` +
260
267
  `Maximum length: ${VALIDATION_CONFIG.DESCRIPTION_MAX_LENGTH} characters. ` +
261
268
  `Current description: "${trimmedDescription.substring(0, 50)}..." ` +
@@ -2,10 +2,8 @@ import { NodeSDK } from "@opentelemetry/sdk-node";
2
2
  import { metrics, trace, } from "@opentelemetry/api";
3
3
  import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
4
4
  import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
5
- import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
6
5
  import { Resource } from "@opentelemetry/resources";
7
6
  import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION, } from "@opentelemetry/semantic-conventions";
8
- import { PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
9
7
  import { logger } from "../utils/logger.js";
10
8
  export class TelemetryService {
11
9
  static instance;
@@ -2,7 +2,6 @@
2
2
  * Tool system type definitions for NeuroLink
3
3
  * Replaces 'any' types in tool registration and execution
4
4
  */
5
- import { z } from "zod";
6
5
  /**
7
6
  * Type guard for tool result
8
7
  */
@@ -21,7 +21,7 @@ export class ProviderHealthChecker {
21
21
  }
22
22
  const parsed = Number(envValue);
23
23
  if (isNaN(parsed) || parsed <= 0 || parsed > 10) {
24
- console.warn(`Invalid PROVIDER_FAILURE_THRESHOLD: ${envValue} (must be between 1 and 10), using default: 3`);
24
+ logger.warn(`Invalid PROVIDER_FAILURE_THRESHOLD: ${envValue} (must be between 1 and 10), using default: 3`);
25
25
  return 3;
26
26
  }
27
27
  return parsed;
@@ -229,11 +229,19 @@ export class ProviderHealthChecker {
229
229
  * Check model availability (if possible without making API calls)
230
230
  */
231
231
  static async checkModelAvailability(providerName, healthStatus) {
232
- // For now, we'll do basic model name validation
233
- // In the future, this could be enhanced with actual API calls
232
+ // Basic model name validation and recommendations
234
233
  const commonModels = this.getCommonModelsForProvider(providerName);
235
234
  if (commonModels.length > 0) {
236
- healthStatus.recommendations.push(`Common models for ${providerName}: ${commonModels.slice(0, 3).join(", ")}`);
235
+ if (providerName === AIProviderName.VERTEX) {
236
+ // Provide more detailed information for Vertex AI
237
+ healthStatus.recommendations.push(`Available models for ${providerName}:\n` +
238
+ ` Google Models: gemini-1.5-pro, gemini-1.5-flash\n` +
239
+ ` Claude Models: claude-3-5-sonnet-20241022, claude-3-sonnet-20240229, claude-3-haiku-20240307, claude-3-opus-20240229\n` +
240
+ ` Note: Claude models require Anthropic integration to be enabled in your Google Cloud project`);
241
+ }
242
+ else {
243
+ healthStatus.recommendations.push(`Common models for ${providerName}: ${commonModels.slice(0, 3).join(", ")}`);
244
+ }
237
245
  }
238
246
  }
239
247
  /**
@@ -408,7 +416,14 @@ export class ProviderHealthChecker {
408
416
  case AIProviderName.GOOGLE_AI:
409
417
  return ["gemini-1.5-pro", "gemini-1.5-flash", "gemini-pro"];
410
418
  case AIProviderName.VERTEX:
411
- return ["gemini-1.5-pro", "gemini-1.5-flash"];
419
+ return [
420
+ "gemini-1.5-pro",
421
+ "gemini-1.5-flash",
422
+ "claude-3-5-sonnet-20241022",
423
+ "claude-3-sonnet-20240229",
424
+ "claude-3-haiku-20240307",
425
+ "claude-3-opus-20240229",
426
+ ];
412
427
  case AIProviderName.BEDROCK:
413
428
  return [
414
429
  "anthropic.claude-3-sonnet-20240229-v1:0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "7.8.0",
3
+ "version": "7.10.0",
4
4
  "description": "Universal AI Development Platform with working MCP integration, multi-provider support, and professional CLI. Built-in tools operational, 58+ external MCP servers discoverable. Connect to filesystem, GitHub, database operations, and more. Build, test, and deploy AI applications with 9 major providers: OpenAI, Anthropic, Google AI, AWS Bedrock, Azure, Hugging Face, Ollama, and Mistral AI.",
5
5
  "author": {
6
6
  "name": "Juspay Technologies",
@@ -31,7 +31,7 @@
31
31
  "build:cli": "echo 'Building CLI...' && tsc --project tsconfig.cli.json",
32
32
  "cli": "node dist/cli/index.js",
33
33
  "preview": "vite preview",
34
- "prepare": "svelte-kit sync || echo ''",
34
+ "prepare": "git rev-parse --git-dir > /dev/null 2>&1 && husky install || echo 'Skipping husky in non-git environment'",
35
35
  "prepack": "svelte-kit sync && svelte-package && pnpm run build:cli && publint",
36
36
  "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
37
37
  "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
@@ -43,6 +43,7 @@
43
43
  "format": "prettier --write .",
44
44
  "changeset": "changeset",
45
45
  "changeset:version": "changeset version && git add --all",
46
+ "format:changelog": "node scripts/format-changelog.cjs",
46
47
  "// ===== NEUROLINK DEVELOPER EXPERIENCE ENHANCEMENT 2.0 =====": "",
47
48
  "// Environment & Setup (pnpm-first)": "",
48
49
  "setup": "pnpm install && node tools/automation/environmentManager.js",
@@ -86,7 +87,20 @@
86
87
  "reset": "pnpm run clean && pnpm install",
87
88
  "audit": "pnpm audit && pnpm run build:analyze",
88
89
  "// Release & Publishing": "",
89
- "release": "pnpm run build:complete && pnpm run test:ci && changeset publish"
90
+ "release": "pnpm run build:complete && pnpm run test:ci && changeset publish",
91
+ "test:semantic-release": "node scripts/test-semantic-release.js",
92
+ "release:dry-run": "npx semantic-release --dry-run",
93
+ "// Build Rule Enforcement Scripts": "",
94
+ "validate": "node scripts/build-validations.cjs",
95
+ "validate:env": "node scripts/env-validation.cjs",
96
+ "validate:security": "node scripts/security-check.cjs",
97
+ "validate:all": "pnpm run validate && pnpm run validate:env && pnpm run validate:security",
98
+ "validate:commit": "node scripts/commit-validation.cjs",
99
+ "quality:metrics": "node scripts/quality-metrics.cjs",
100
+ "quality:report": "pnpm run quality:metrics && echo 'Quality metrics saved to quality-metrics.json'",
101
+ "pre-commit": "lint-staged",
102
+ "pre-push": "pnpm run validate && pnpm run test:run",
103
+ "check:all": "pnpm run lint && pnpm run format --check && pnpm run validate && pnpm run validate:commit"
90
104
  },
91
105
  "files": [
92
106
  "dist",
@@ -168,6 +182,7 @@
168
182
  "zod-to-json-schema": "^3.24.5"
169
183
  },
170
184
  "devDependencies": {
185
+ "@biomejs/biome": "^2.1.4",
171
186
  "@changesets/changelog-github": "^0.5.1",
172
187
  "@changesets/cli": "^2.26.2",
173
188
  "@eslint/js": "^9.0.0",
@@ -190,9 +205,12 @@
190
205
  "@typescript-eslint/eslint-plugin": "^8.0.0",
191
206
  "@typescript-eslint/parser": "^8.0.0",
192
207
  "@vitest/coverage-v8": "^2.1.9",
208
+ "conventional-changelog-conventionalcommits": "^9.1.0",
193
209
  "cors": "^2.8.5",
194
210
  "eslint": "^9.0.0",
195
211
  "express": "^5.1.0",
212
+ "husky": "^9.1.7",
213
+ "lint-staged": "^16.1.5",
196
214
  "playwright": "^1.52.0",
197
215
  "prettier": "^3.0.0",
198
216
  "publint": "^0.3.2",
@@ -249,7 +267,13 @@
249
267
  "esbuild",
250
268
  "protobufjs",
251
269
  "puppeteer"
252
- ]
270
+ ],
271
+ "overrides": {
272
+ "esbuild@<=0.24.2": ">=0.25.0",
273
+ "cookie@<0.7.0": ">=0.7.0",
274
+ "@eslint/plugin-kit@<0.3.4": ">=0.3.4",
275
+ "tmp@<=0.2.3": ">=0.2.4"
276
+ }
253
277
  },
254
278
  "os": [
255
279
  "darwin",
@@ -258,6 +282,20 @@
258
282
  ],
259
283
  "prettier": {
260
284
  "tabWidth": 2,
261
- "useTabs": false
285
+ "useTabs": false,
286
+ "proseWrap": "preserve"
287
+ },
288
+ "lint-staged": {
289
+ "src/**/*.{ts,tsx}": [
290
+ "eslint --fix --max-warnings=50",
291
+ "prettier --write"
292
+ ],
293
+ "test/**/*.{ts,tsx}": [
294
+ "eslint --fix --max-warnings=0",
295
+ "prettier --write"
296
+ ],
297
+ "*.{json,md}": [
298
+ "prettier --write"
299
+ ]
262
300
  }
263
301
  }