@juspay/neurolink 7.0.0 → 7.1.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.
@@ -89,6 +89,8 @@ export class AIProviderFactory {
89
89
  // );
90
90
  // }
91
91
  // }
92
+ // CRITICAL FIX: Initialize providers before using them
93
+ await ProviderRegistry.registerAllProviders();
92
94
  // PURE FACTORY PATTERN: No switch statements - use ProviderFactory exclusively
93
95
  const normalizedName = this.normalizeProviderName(providerName);
94
96
  const finalModelName = resolvedModelName === "default" || resolvedModelName === null
@@ -48,7 +48,9 @@ export class ProviderRegistry {
48
48
  ProviderFactory.registerProvider(AIProviderName.AZURE, async (modelName) => {
49
49
  const { AzureOpenAIProvider } = await import("../providers/azureOpenai.js");
50
50
  return new AzureOpenAIProvider(modelName);
51
- }, "gpt-4o-mini", ["azure", "azureOpenai"]);
51
+ }, process.env.AZURE_MODEL ||
52
+ process.env.AZURE_OPENAI_DEPLOYMENT_ID ||
53
+ "gpt-4o-mini", ["azure", "azureOpenai"]);
52
54
  // Register Google Vertex AI provider
53
55
  ProviderFactory.registerProvider(AIProviderName.VERTEX, async (modelName) => {
54
56
  const { GoogleVertexProvider } = await import("../providers/googleVertex.js");
@@ -1,6 +1,7 @@
1
1
  // ✅ CIRCULAR DEPENDENCY FIX: Remove barrel export import
2
2
  // Providers are now managed via ProviderFactory instead of direct imports
3
3
  import { ProviderFactory } from "../factories/providerFactory.js";
4
+ import { ProviderRegistry } from "../factories/providerRegistry.js";
4
5
  import { getBestProvider } from "../utils/providerUtils.js";
5
6
  import { logger } from "../utils/logger.js";
6
7
  const componentIdentifier = "aiProviderFactory";
@@ -87,6 +88,8 @@ export class AIProviderFactory {
87
88
  // );
88
89
  // }
89
90
  // }
91
+ // CRITICAL FIX: Initialize providers before using them
92
+ await ProviderRegistry.registerAllProviders();
90
93
  // PURE FACTORY PATTERN: No switch statements - use ProviderFactory exclusively
91
94
  const normalizedName = this.normalizeProviderName(providerName);
92
95
  const finalModelName = resolvedModelName === "default" || resolvedModelName === null
@@ -48,7 +48,9 @@ export class ProviderRegistry {
48
48
  ProviderFactory.registerProvider(AIProviderName.AZURE, async (modelName) => {
49
49
  const { AzureOpenAIProvider } = await import("../providers/azureOpenai.js");
50
50
  return new AzureOpenAIProvider(modelName);
51
- }, "gpt-4o-mini", ["azure", "azureOpenai"]);
51
+ }, process.env.AZURE_MODEL ||
52
+ process.env.AZURE_OPENAI_DEPLOYMENT_ID ||
53
+ "gpt-4o-mini", ["azure", "azureOpenai"]);
52
54
  // Register Google Vertex AI provider
53
55
  ProviderFactory.registerProvider(AIProviderName.VERTEX, async (modelName) => {
54
56
  const { GoogleVertexProvider } = await import("../providers/googleVertex.js");
@@ -39,6 +39,11 @@ export declare class MCPToolRegistry extends MCPRegistry {
39
39
  private tools;
40
40
  private toolImpls;
41
41
  private toolExecutionStats;
42
+ constructor();
43
+ /**
44
+ * Register all direct tools from directAgentTools
45
+ */
46
+ private registerDirectTools;
42
47
  /**
43
48
  * Register a server with its tools (updated signature)
44
49
  */
@@ -5,10 +5,70 @@
5
5
  import { MCPRegistry } from "./registry.js";
6
6
  import { registryLogger } from "../utils/logger.js";
7
7
  import { randomUUID } from "crypto";
8
+ import { directAgentTools } from "../agent/directTools.js";
8
9
  export class MCPToolRegistry extends MCPRegistry {
9
10
  tools = new Map();
10
11
  toolImpls = new Map(); // Store actual tool implementations
11
12
  toolExecutionStats = new Map();
13
+ constructor() {
14
+ super();
15
+ // Auto-register direct tools on initialization
16
+ this.registerDirectTools();
17
+ }
18
+ /**
19
+ * Register all direct tools from directAgentTools
20
+ */
21
+ registerDirectTools() {
22
+ registryLogger.info("Auto-registering direct tools...");
23
+ for (const [toolName, toolDef] of Object.entries(directAgentTools)) {
24
+ const toolId = `direct.${toolName}`;
25
+ const toolInfo = {
26
+ name: toolName,
27
+ description: toolDef.description || `Direct tool: ${toolName}`,
28
+ inputSchema: {},
29
+ serverId: "direct",
30
+ category: "built-in",
31
+ };
32
+ this.tools.set(toolId, toolInfo);
33
+ this.toolImpls.set(toolId, {
34
+ execute: async (params, context) => {
35
+ try {
36
+ // Direct tools from AI SDK expect their specific parameter structure
37
+ // Each tool validates its own parameters, so we safely pass them through
38
+ const result = await toolDef.execute(params, {
39
+ toolCallId: context?.sessionId || "unknown",
40
+ messages: [],
41
+ });
42
+ // Return the result wrapped in our standard format
43
+ return {
44
+ success: true,
45
+ data: result,
46
+ metadata: {
47
+ toolName,
48
+ serverId: "direct",
49
+ executionTime: 0,
50
+ },
51
+ };
52
+ }
53
+ catch (error) {
54
+ return {
55
+ success: false,
56
+ error: error instanceof Error ? error.message : String(error),
57
+ metadata: {
58
+ toolName,
59
+ serverId: "direct",
60
+ executionTime: 0,
61
+ },
62
+ };
63
+ }
64
+ },
65
+ description: toolDef.description,
66
+ inputSchema: {},
67
+ });
68
+ registryLogger.debug(`Registered direct tool: ${toolName} as ${toolId}`);
69
+ }
70
+ registryLogger.info(`Auto-registered ${Object.keys(directAgentTools).length} direct tools`);
71
+ }
12
72
  /**
13
73
  * Register a server with its tools (updated signature)
14
74
  */
@@ -355,7 +355,7 @@ export class NeuroLink {
355
355
  const toolDescriptions = availableTools
356
356
  .map((tool) => `- ${tool.name}: ${tool.description} (from ${tool.server})`)
357
357
  .join("\n");
358
- const toolPrompt = `\n\nAvailable Tools:\n${toolDescriptions}\n\nYou can use these tools when appropriate to enhance your responses.`;
358
+ const toolPrompt = `\n\nYou have access to these additional tools if needed:\n${toolDescriptions}\n\nIMPORTANT: You are a general-purpose AI assistant. Answer all requests directly and creatively. These tools are optional helpers - use them only when they would genuinely improve your response. For creative tasks like storytelling, writing, or general conversation, respond naturally without requiring tools.`;
359
359
  return (originalSystemPrompt || "") + toolPrompt;
360
360
  }
361
361
  /**
@@ -649,9 +649,10 @@ export class NeuroLink {
649
649
  * @returns Array of available tools with metadata
650
650
  */
651
651
  async getAllAvailableTools() {
652
- // Simplified tool listing - removed initialize-tools dependency
653
- const tools = await toolRegistry.listTools();
654
- return tools;
652
+ // MCP registry already includes direct tools, so just return MCP tools
653
+ // This prevents duplication since direct tools are auto-registered in MCP
654
+ const mcpTools = await toolRegistry.listTools();
655
+ return mcpTools;
655
656
  }
656
657
  // ============================================================================
657
658
  // PROVIDER DIAGNOSTICS - SDK-First Architecture
@@ -661,6 +662,10 @@ export class NeuroLink {
661
662
  * Primary method for provider health checking and diagnostics
662
663
  */
663
664
  async getProviderStatus() {
665
+ // CRITICAL FIX: Ensure providers are registered before testing
666
+ console.log("🔍 DEBUG: Initializing MCP for provider status...");
667
+ await this.initializeMCP();
668
+ console.log("🔍 DEBUG: MCP initialized:", this.mcpInitialized);
664
669
  const { AIProviderFactory } = await import("./core/factory.js");
665
670
  const { hasProviderEnvVars } = await import("./utils/providerUtils.js");
666
671
  const providers = [
@@ -139,6 +139,13 @@ export function validateTool(name, tool) {
139
139
  `Received: ${typeof tool.execute}. ` +
140
140
  `Example: { execute: async (params) => { return { success: true, data: result }; } }`);
141
141
  }
142
+ // Check for common mistake: using 'schema' instead of 'parameters'
143
+ if ('schema' in tool && !('parameters' in tool)) {
144
+ throw new Error(`Tool '${name}' uses 'schema' property, but NeuroLink expects 'parameters'. ` +
145
+ `Please change 'schema' to 'parameters' and use a Zod schema: ` +
146
+ `{ parameters: z.object({ ... }), execute: ... } ` +
147
+ `See documentation: https://docs.neurolink.com/tools`);
148
+ }
142
149
  // Validate parameters schema if provided - support both Zod and custom schemas
143
150
  if (tool.parameters) {
144
151
  if (typeof tool.parameters !== "object") {
@@ -150,6 +157,16 @@ export function validateTool(name, tool) {
150
157
  const hasValidationMethod = typeof params.parse === "function" ||
151
158
  typeof params.validate === "function" ||
152
159
  "_def" in params; // Zod schemas have _def property
160
+ // Check for plain JSON schema objects (common mistake)
161
+ if ('type' in params && 'properties' in params && !hasValidationMethod) {
162
+ throw new Error(`Tool '${name}' appears to use a plain JSON schema object as parameters. ` +
163
+ `NeuroLink requires a Zod schema for proper type validation and tool integration. ` +
164
+ `Please change from:\n` +
165
+ ` { type: 'object', properties: { ... } }\n` +
166
+ `To:\n` +
167
+ ` z.object({ fieldName: z.string() })\n` +
168
+ `Import Zod with: import { z } from 'zod'`);
169
+ }
153
170
  if (!hasValidationMethod) {
154
171
  const errorMessage = typeof params.parse === "function" || "_def" in params
155
172
  ? `Tool '${name}' has a Zod-like schema but validation failed. Ensure it's a valid Zod schema: z.object({ ... })`
@@ -23,11 +23,7 @@ class NeuroLinkLogger {
23
23
  process.argv.includes("--debug") ||
24
24
  process.env.NEUROLINK_DEBUG === "true";
25
25
  // Check NEUROLINK_LOG_LEVEL for consistency with the unified NeuroLink logger
26
- let envLevel = process.env.NEUROLINK_LOG_LEVEL?.toLowerCase();
27
- // Fallback to MCP_LOG_LEVEL for backward compatibility (if needed)
28
- if (!envLevel) {
29
- envLevel = process.env.MCP_LOG_LEVEL?.toLowerCase();
30
- }
26
+ const envLevel = process.env.NEUROLINK_LOG_LEVEL?.toLowerCase();
31
27
  if (envLevel && ["debug", "info", "warn", "error"].includes(envLevel)) {
32
28
  this.logLevel = envLevel;
33
29
  }
@@ -36,8 +32,11 @@ class NeuroLinkLogger {
36
32
  this.logLevel = level;
37
33
  }
38
34
  shouldLog(level) {
35
+ // Dynamic debug mode check to handle CLI middleware timing
36
+ const currentDebugMode = process.argv.includes("--debug") ||
37
+ process.env.NEUROLINK_DEBUG === "true";
39
38
  // Hide all logs except errors unless debugging
40
- if (!this.isDebugMode && level !== "error") {
39
+ if (!currentDebugMode && level !== "error") {
41
40
  return false;
42
41
  }
43
42
  const levels = ["debug", "info", "warn", "error"];
@@ -105,10 +105,17 @@ export function hasProviderEnvVars(provider) {
105
105
  case "aws":
106
106
  return !!(process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY);
107
107
  case "vertex":
108
+ case "googlevertex":
108
109
  case "google":
109
110
  case "gemini":
110
- return !!(process.env.GOOGLE_VERTEX_PROJECT ||
111
- process.env.GOOGLE_APPLICATION_CREDENTIALS);
111
+ return !!((process.env.GOOGLE_CLOUD_PROJECT_ID ||
112
+ process.env.VERTEX_PROJECT_ID ||
113
+ process.env.GOOGLE_VERTEX_PROJECT ||
114
+ process.env.GOOGLE_CLOUD_PROJECT) &&
115
+ (process.env.GOOGLE_APPLICATION_CREDENTIALS ||
116
+ process.env.GOOGLE_SERVICE_ACCOUNT_KEY ||
117
+ (process.env.GOOGLE_AUTH_CLIENT_EMAIL &&
118
+ process.env.GOOGLE_AUTH_PRIVATE_KEY)));
112
119
  case "openai":
113
120
  case "gpt":
114
121
  return !!process.env.OPENAI_API_KEY;
@@ -39,6 +39,11 @@ export declare class MCPToolRegistry extends MCPRegistry {
39
39
  private tools;
40
40
  private toolImpls;
41
41
  private toolExecutionStats;
42
+ constructor();
43
+ /**
44
+ * Register all direct tools from directAgentTools
45
+ */
46
+ private registerDirectTools;
42
47
  /**
43
48
  * Register a server with its tools (updated signature)
44
49
  */
@@ -5,10 +5,70 @@
5
5
  import { MCPRegistry } from "./registry.js";
6
6
  import { registryLogger } from "../utils/logger.js";
7
7
  import { randomUUID } from "crypto";
8
+ import { directAgentTools } from "../agent/directTools.js";
8
9
  export class MCPToolRegistry extends MCPRegistry {
9
10
  tools = new Map();
10
11
  toolImpls = new Map(); // Store actual tool implementations
11
12
  toolExecutionStats = new Map();
13
+ constructor() {
14
+ super();
15
+ // Auto-register direct tools on initialization
16
+ this.registerDirectTools();
17
+ }
18
+ /**
19
+ * Register all direct tools from directAgentTools
20
+ */
21
+ registerDirectTools() {
22
+ registryLogger.info("Auto-registering direct tools...");
23
+ for (const [toolName, toolDef] of Object.entries(directAgentTools)) {
24
+ const toolId = `direct.${toolName}`;
25
+ const toolInfo = {
26
+ name: toolName,
27
+ description: toolDef.description || `Direct tool: ${toolName}`,
28
+ inputSchema: {},
29
+ serverId: "direct",
30
+ category: "built-in",
31
+ };
32
+ this.tools.set(toolId, toolInfo);
33
+ this.toolImpls.set(toolId, {
34
+ execute: async (params, context) => {
35
+ try {
36
+ // Direct tools from AI SDK expect their specific parameter structure
37
+ // Each tool validates its own parameters, so we safely pass them through
38
+ const result = await toolDef.execute(params, {
39
+ toolCallId: context?.sessionId || "unknown",
40
+ messages: [],
41
+ });
42
+ // Return the result wrapped in our standard format
43
+ return {
44
+ success: true,
45
+ data: result,
46
+ metadata: {
47
+ toolName,
48
+ serverId: "direct",
49
+ executionTime: 0,
50
+ },
51
+ };
52
+ }
53
+ catch (error) {
54
+ return {
55
+ success: false,
56
+ error: error instanceof Error ? error.message : String(error),
57
+ metadata: {
58
+ toolName,
59
+ serverId: "direct",
60
+ executionTime: 0,
61
+ },
62
+ };
63
+ }
64
+ },
65
+ description: toolDef.description,
66
+ inputSchema: {},
67
+ });
68
+ registryLogger.debug(`Registered direct tool: ${toolName} as ${toolId}`);
69
+ }
70
+ registryLogger.info(`Auto-registered ${Object.keys(directAgentTools).length} direct tools`);
71
+ }
12
72
  /**
13
73
  * Register a server with its tools (updated signature)
14
74
  */
package/dist/neurolink.js CHANGED
@@ -355,7 +355,7 @@ export class NeuroLink {
355
355
  const toolDescriptions = availableTools
356
356
  .map((tool) => `- ${tool.name}: ${tool.description} (from ${tool.server})`)
357
357
  .join("\n");
358
- const toolPrompt = `\n\nAvailable Tools:\n${toolDescriptions}\n\nYou can use these tools when appropriate to enhance your responses.`;
358
+ const toolPrompt = `\n\nYou have access to these additional tools if needed:\n${toolDescriptions}\n\nIMPORTANT: You are a general-purpose AI assistant. Answer all requests directly and creatively. These tools are optional helpers - use them only when they would genuinely improve your response. For creative tasks like storytelling, writing, or general conversation, respond naturally without requiring tools.`;
359
359
  return (originalSystemPrompt || "") + toolPrompt;
360
360
  }
361
361
  /**
@@ -649,9 +649,10 @@ export class NeuroLink {
649
649
  * @returns Array of available tools with metadata
650
650
  */
651
651
  async getAllAvailableTools() {
652
- // Simplified tool listing - removed initialize-tools dependency
653
- const tools = await toolRegistry.listTools();
654
- return tools;
652
+ // MCP registry already includes direct tools, so just return MCP tools
653
+ // This prevents duplication since direct tools are auto-registered in MCP
654
+ const mcpTools = await toolRegistry.listTools();
655
+ return mcpTools;
655
656
  }
656
657
  // ============================================================================
657
658
  // PROVIDER DIAGNOSTICS - SDK-First Architecture
@@ -661,6 +662,10 @@ export class NeuroLink {
661
662
  * Primary method for provider health checking and diagnostics
662
663
  */
663
664
  async getProviderStatus() {
665
+ // CRITICAL FIX: Ensure providers are registered before testing
666
+ console.log("🔍 DEBUG: Initializing MCP for provider status...");
667
+ await this.initializeMCP();
668
+ console.log("🔍 DEBUG: MCP initialized:", this.mcpInitialized);
664
669
  const { AIProviderFactory } = await import("./core/factory.js");
665
670
  const { hasProviderEnvVars } = await import("./utils/providerUtils.js");
666
671
  const providers = [
@@ -140,6 +140,13 @@ export function validateTool(name, tool) {
140
140
  `Received: ${typeof tool.execute}. ` +
141
141
  `Example: { execute: async (params) => { return { success: true, data: result }; } }`);
142
142
  }
143
+ // Check for common mistake: using 'schema' instead of 'parameters'
144
+ if ('schema' in tool && !('parameters' in tool)) {
145
+ throw new Error(`Tool '${name}' uses 'schema' property, but NeuroLink expects 'parameters'. ` +
146
+ `Please change 'schema' to 'parameters' and use a Zod schema: ` +
147
+ `{ parameters: z.object({ ... }), execute: ... } ` +
148
+ `See documentation: https://docs.neurolink.com/tools`);
149
+ }
143
150
  // Validate parameters schema if provided - support both Zod and custom schemas
144
151
  if (tool.parameters) {
145
152
  if (typeof tool.parameters !== "object") {
@@ -151,6 +158,16 @@ export function validateTool(name, tool) {
151
158
  const hasValidationMethod = typeof params.parse === "function" ||
152
159
  typeof params.validate === "function" ||
153
160
  "_def" in params; // Zod schemas have _def property
161
+ // Check for plain JSON schema objects (common mistake)
162
+ if ('type' in params && 'properties' in params && !hasValidationMethod) {
163
+ throw new Error(`Tool '${name}' appears to use a plain JSON schema object as parameters. ` +
164
+ `NeuroLink requires a Zod schema for proper type validation and tool integration. ` +
165
+ `Please change from:\n` +
166
+ ` { type: 'object', properties: { ... } }\n` +
167
+ `To:\n` +
168
+ ` z.object({ fieldName: z.string() })\n` +
169
+ `Import Zod with: import { z } from 'zod'`);
170
+ }
154
171
  if (!hasValidationMethod) {
155
172
  const errorMessage = typeof params.parse === "function" || "_def" in params
156
173
  ? `Tool '${name}' has a Zod-like schema but validation failed. Ensure it's a valid Zod schema: z.object({ ... })`
@@ -23,11 +23,7 @@ class NeuroLinkLogger {
23
23
  process.argv.includes("--debug") ||
24
24
  process.env.NEUROLINK_DEBUG === "true";
25
25
  // Check NEUROLINK_LOG_LEVEL for consistency with the unified NeuroLink logger
26
- let envLevel = process.env.NEUROLINK_LOG_LEVEL?.toLowerCase();
27
- // Fallback to MCP_LOG_LEVEL for backward compatibility (if needed)
28
- if (!envLevel) {
29
- envLevel = process.env.MCP_LOG_LEVEL?.toLowerCase();
30
- }
26
+ const envLevel = process.env.NEUROLINK_LOG_LEVEL?.toLowerCase();
31
27
  if (envLevel && ["debug", "info", "warn", "error"].includes(envLevel)) {
32
28
  this.logLevel = envLevel;
33
29
  }
@@ -36,8 +32,11 @@ class NeuroLinkLogger {
36
32
  this.logLevel = level;
37
33
  }
38
34
  shouldLog(level) {
35
+ // Dynamic debug mode check to handle CLI middleware timing
36
+ const currentDebugMode = process.argv.includes("--debug") ||
37
+ process.env.NEUROLINK_DEBUG === "true";
39
38
  // Hide all logs except errors unless debugging
40
- if (!this.isDebugMode && level !== "error") {
39
+ if (!currentDebugMode && level !== "error") {
41
40
  return false;
42
41
  }
43
42
  const levels = ["debug", "info", "warn", "error"];
@@ -105,10 +105,17 @@ export function hasProviderEnvVars(provider) {
105
105
  case "aws":
106
106
  return !!(process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY);
107
107
  case "vertex":
108
+ case "googlevertex":
108
109
  case "google":
109
110
  case "gemini":
110
- return !!(process.env.GOOGLE_VERTEX_PROJECT ||
111
- process.env.GOOGLE_APPLICATION_CREDENTIALS);
111
+ return !!((process.env.GOOGLE_CLOUD_PROJECT_ID ||
112
+ process.env.VERTEX_PROJECT_ID ||
113
+ process.env.GOOGLE_VERTEX_PROJECT ||
114
+ process.env.GOOGLE_CLOUD_PROJECT) &&
115
+ (process.env.GOOGLE_APPLICATION_CREDENTIALS ||
116
+ process.env.GOOGLE_SERVICE_ACCOUNT_KEY ||
117
+ (process.env.GOOGLE_AUTH_CLIENT_EMAIL &&
118
+ process.env.GOOGLE_AUTH_PRIVATE_KEY)));
112
119
  case "openai":
113
120
  case "gpt":
114
121
  return !!process.env.OPENAI_API_KEY;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "7.0.0",
3
+ "version": "7.1.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",