@juspay/neurolink 6.2.0 → 6.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -2
- package/dist/agent/direct-tools.js +6 -5
- package/dist/config/configManager.js +11 -10
- package/dist/lib/agent/direct-tools.js +6 -5
- package/dist/lib/config/configManager.js +11 -10
- package/dist/lib/mcp/index.d.ts +2 -2
- package/dist/lib/mcp/index.js +1 -1
- package/dist/lib/mcp/registry.js +1 -1
- package/dist/lib/mcp/servers/ai-providers/ai-analysis-tools.js +2 -1
- package/dist/lib/mcp/tool-registry.js +1 -1
- package/dist/lib/neurolink.js +1 -1
- package/dist/lib/providers/azure-openai.js +2 -1
- package/dist/lib/telemetry/index.js +2 -1
- package/dist/lib/utils/logger.d.ts +62 -2
- package/dist/lib/utils/logger.js +174 -9
- package/dist/mcp/index.d.ts +2 -2
- package/dist/mcp/index.js +1 -1
- package/dist/mcp/registry.js +1 -1
- package/dist/mcp/servers/ai-providers/ai-analysis-tools.js +2 -1
- package/dist/mcp/tool-registry.js +1 -1
- package/dist/neurolink.js +1 -1
- package/dist/providers/azure-openai.js +2 -1
- package/dist/telemetry/index.js +2 -1
- package/dist/utils/logger.d.ts +62 -2
- package/dist/utils/logger.js +174 -9
- package/package.json +1 -1
- package/dist/lib/mcp/logging.d.ts +0 -38
- package/dist/lib/mcp/logging.js +0 -100
- package/dist/mcp/logging.d.ts +0 -38
- package/dist/mcp/logging.js +0 -100
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
## [6.2.1](https://github.com/juspay/neurolink/compare/v6.2.0...v6.2.1) (2025-07-31)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **logging:** consolidate MCP logging and add debug flag control ([ea0132d](https://github.com/juspay/neurolink/commit/ea0132dd954966cb42238dc3736f6cee9cc7b18d))
|
|
2
7
|
|
|
8
|
+
# [6.2.0](https://github.com/juspay/neurolink/compare/v6.1.0...v6.2.0) (2025-07-30)
|
|
3
9
|
|
|
4
10
|
### Features
|
|
5
11
|
|
|
6
|
-
|
|
12
|
+
- systematic dead code elimination across entire codebase ([571060a](https://github.com/juspay/neurolink/commit/571060a6146dc13e486da22610122d599420fcb2))
|
|
7
13
|
|
|
8
14
|
# [6.1.0](https://github.com/juspay/neurolink/compare/v6.0.0...v6.1.0) (2025-07-24)
|
|
9
15
|
|
|
@@ -6,6 +6,7 @@ import { tool } from "ai";
|
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import * as fs from "fs";
|
|
8
8
|
import * as path from "path";
|
|
9
|
+
import { logger } from "../utils/logger.js";
|
|
9
10
|
/**
|
|
10
11
|
* Direct tool definitions that work immediately with Gemini/AI SDK
|
|
11
12
|
* These bypass MCP complexity and provide reliable agent functionality
|
|
@@ -365,23 +366,23 @@ export function validateToolStructure() {
|
|
|
365
366
|
try {
|
|
366
367
|
for (const [name, tool] of Object.entries(directAgentTools)) {
|
|
367
368
|
if (!tool.description || typeof tool.description !== "string") {
|
|
368
|
-
|
|
369
|
+
logger.error(`❌ Tool ${name} missing description`);
|
|
369
370
|
return false;
|
|
370
371
|
}
|
|
371
372
|
if (!tool.parameters) {
|
|
372
|
-
|
|
373
|
+
logger.error(`❌ Tool ${name} missing parameters`);
|
|
373
374
|
return false;
|
|
374
375
|
}
|
|
375
376
|
if (!tool.execute || typeof tool.execute !== "function") {
|
|
376
|
-
|
|
377
|
+
logger.error(`❌ Tool ${name} missing execute function`);
|
|
377
378
|
return false;
|
|
378
379
|
}
|
|
379
380
|
}
|
|
380
|
-
|
|
381
|
+
logger.info("✅ All tools have valid structure");
|
|
381
382
|
return true;
|
|
382
383
|
}
|
|
383
384
|
catch (error) {
|
|
384
|
-
|
|
385
|
+
logger.error("❌ Tool validation failed:", error);
|
|
385
386
|
return false;
|
|
386
387
|
}
|
|
387
388
|
}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { promises as fs } from "fs";
|
|
6
6
|
import path from "path";
|
|
7
7
|
import crypto from "crypto";
|
|
8
|
+
import { logger } from "../utils/logger.js";
|
|
8
9
|
const { readFile, writeFile, readdir, mkdir, unlink, access } = fs;
|
|
9
10
|
/**
|
|
10
11
|
* Enhanced Config Manager with automatic backup/restore capabilities
|
|
@@ -32,7 +33,7 @@ export class NeuroLinkConfigManager {
|
|
|
32
33
|
if (createBackup) {
|
|
33
34
|
await this.createBackup(reason);
|
|
34
35
|
if (!silent) {
|
|
35
|
-
|
|
36
|
+
logger.info("💾 Backup created before config update");
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
39
|
const existing = await this.loadConfig();
|
|
@@ -50,7 +51,7 @@ export class NeuroLinkConfigManager {
|
|
|
50
51
|
try {
|
|
51
52
|
await this.persistConfig(this.config);
|
|
52
53
|
if (!silent) {
|
|
53
|
-
|
|
54
|
+
logger.info("✅ Configuration updated successfully");
|
|
54
55
|
}
|
|
55
56
|
}
|
|
56
57
|
catch (error) {
|
|
@@ -58,7 +59,7 @@ export class NeuroLinkConfigManager {
|
|
|
58
59
|
if (createBackup) {
|
|
59
60
|
await this.restoreLatestBackup();
|
|
60
61
|
if (!silent) {
|
|
61
|
-
|
|
62
|
+
logger.info("🔄 Auto-restored from backup due to error");
|
|
62
63
|
}
|
|
63
64
|
}
|
|
64
65
|
throw new Error(`Config update failed, restored from backup: ${error.message}`);
|
|
@@ -115,13 +116,13 @@ export default ${JSON.stringify(currentConfig, null, 2)};`;
|
|
|
115
116
|
});
|
|
116
117
|
}
|
|
117
118
|
catch (error) {
|
|
118
|
-
|
|
119
|
+
logger.warn(`Failed to read backup ${file}:`, error.message);
|
|
119
120
|
}
|
|
120
121
|
}
|
|
121
122
|
return backups.sort((a, b) => b.metadata.timestamp - a.metadata.timestamp);
|
|
122
123
|
}
|
|
123
124
|
catch (error) {
|
|
124
|
-
|
|
125
|
+
logger.warn("Failed to list backups:", error.message);
|
|
125
126
|
return [];
|
|
126
127
|
}
|
|
127
128
|
}
|
|
@@ -142,7 +143,7 @@ export default ${JSON.stringify(currentConfig, null, 2)};`;
|
|
|
142
143
|
}
|
|
143
144
|
this.config = restoredConfig;
|
|
144
145
|
await this.persistConfig(this.config);
|
|
145
|
-
|
|
146
|
+
logger.info(`✅ Config restored from backup: ${backupFilename}`);
|
|
146
147
|
}
|
|
147
148
|
catch (error) {
|
|
148
149
|
throw new Error(`Failed to restore from backup ${backupFilename}: ${error.message}`);
|
|
@@ -167,10 +168,10 @@ export default ${JSON.stringify(currentConfig, null, 2)};`;
|
|
|
167
168
|
for (const backup of toDelete) {
|
|
168
169
|
try {
|
|
169
170
|
await unlink(backup.path);
|
|
170
|
-
|
|
171
|
+
logger.info(`🗑️ Deleted old backup: ${backup.filename}`);
|
|
171
172
|
}
|
|
172
173
|
catch (error) {
|
|
173
|
-
|
|
174
|
+
logger.warn(`Failed to delete backup ${backup.filename}:`, error.message);
|
|
174
175
|
}
|
|
175
176
|
}
|
|
176
177
|
}
|
|
@@ -248,7 +249,7 @@ export default ${JSON.stringify(currentConfig, null, 2)};`;
|
|
|
248
249
|
await mkdir(this.backupDir, { recursive: true });
|
|
249
250
|
}
|
|
250
251
|
catch (error) {
|
|
251
|
-
|
|
252
|
+
logger.warn("Failed to create backup directory:", error.message);
|
|
252
253
|
}
|
|
253
254
|
}
|
|
254
255
|
async readConfigFile() {
|
|
@@ -265,7 +266,7 @@ export default ${JSON.stringify(currentConfig, null, 2)};`;
|
|
|
265
266
|
throw new Error("Invalid config file format");
|
|
266
267
|
}
|
|
267
268
|
catch (error) {
|
|
268
|
-
|
|
269
|
+
logger.info("Config file not found, generating default...");
|
|
269
270
|
return await this.generateDefaultConfig();
|
|
270
271
|
}
|
|
271
272
|
}
|
|
@@ -6,6 +6,7 @@ import { tool } from "ai";
|
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import * as fs from "fs";
|
|
8
8
|
import * as path from "path";
|
|
9
|
+
import { logger } from "../utils/logger.js";
|
|
9
10
|
/**
|
|
10
11
|
* Direct tool definitions that work immediately with Gemini/AI SDK
|
|
11
12
|
* These bypass MCP complexity and provide reliable agent functionality
|
|
@@ -365,23 +366,23 @@ export function validateToolStructure() {
|
|
|
365
366
|
try {
|
|
366
367
|
for (const [name, tool] of Object.entries(directAgentTools)) {
|
|
367
368
|
if (!tool.description || typeof tool.description !== "string") {
|
|
368
|
-
|
|
369
|
+
logger.error(`❌ Tool ${name} missing description`);
|
|
369
370
|
return false;
|
|
370
371
|
}
|
|
371
372
|
if (!tool.parameters) {
|
|
372
|
-
|
|
373
|
+
logger.error(`❌ Tool ${name} missing parameters`);
|
|
373
374
|
return false;
|
|
374
375
|
}
|
|
375
376
|
if (!tool.execute || typeof tool.execute !== "function") {
|
|
376
|
-
|
|
377
|
+
logger.error(`❌ Tool ${name} missing execute function`);
|
|
377
378
|
return false;
|
|
378
379
|
}
|
|
379
380
|
}
|
|
380
|
-
|
|
381
|
+
logger.info("✅ All tools have valid structure");
|
|
381
382
|
return true;
|
|
382
383
|
}
|
|
383
384
|
catch (error) {
|
|
384
|
-
|
|
385
|
+
logger.error("❌ Tool validation failed:", error);
|
|
385
386
|
return false;
|
|
386
387
|
}
|
|
387
388
|
}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { promises as fs } from "fs";
|
|
6
6
|
import path from "path";
|
|
7
7
|
import crypto from "crypto";
|
|
8
|
+
import { logger } from "../utils/logger.js";
|
|
8
9
|
const { readFile, writeFile, readdir, mkdir, unlink, access } = fs;
|
|
9
10
|
/**
|
|
10
11
|
* Enhanced Config Manager with automatic backup/restore capabilities
|
|
@@ -32,7 +33,7 @@ export class NeuroLinkConfigManager {
|
|
|
32
33
|
if (createBackup) {
|
|
33
34
|
await this.createBackup(reason);
|
|
34
35
|
if (!silent) {
|
|
35
|
-
|
|
36
|
+
logger.info("💾 Backup created before config update");
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
39
|
const existing = await this.loadConfig();
|
|
@@ -50,7 +51,7 @@ export class NeuroLinkConfigManager {
|
|
|
50
51
|
try {
|
|
51
52
|
await this.persistConfig(this.config);
|
|
52
53
|
if (!silent) {
|
|
53
|
-
|
|
54
|
+
logger.info("✅ Configuration updated successfully");
|
|
54
55
|
}
|
|
55
56
|
}
|
|
56
57
|
catch (error) {
|
|
@@ -58,7 +59,7 @@ export class NeuroLinkConfigManager {
|
|
|
58
59
|
if (createBackup) {
|
|
59
60
|
await this.restoreLatestBackup();
|
|
60
61
|
if (!silent) {
|
|
61
|
-
|
|
62
|
+
logger.info("🔄 Auto-restored from backup due to error");
|
|
62
63
|
}
|
|
63
64
|
}
|
|
64
65
|
throw new Error(`Config update failed, restored from backup: ${error.message}`);
|
|
@@ -115,13 +116,13 @@ export default ${JSON.stringify(currentConfig, null, 2)};`;
|
|
|
115
116
|
});
|
|
116
117
|
}
|
|
117
118
|
catch (error) {
|
|
118
|
-
|
|
119
|
+
logger.warn(`Failed to read backup ${file}:`, error.message);
|
|
119
120
|
}
|
|
120
121
|
}
|
|
121
122
|
return backups.sort((a, b) => b.metadata.timestamp - a.metadata.timestamp);
|
|
122
123
|
}
|
|
123
124
|
catch (error) {
|
|
124
|
-
|
|
125
|
+
logger.warn("Failed to list backups:", error.message);
|
|
125
126
|
return [];
|
|
126
127
|
}
|
|
127
128
|
}
|
|
@@ -142,7 +143,7 @@ export default ${JSON.stringify(currentConfig, null, 2)};`;
|
|
|
142
143
|
}
|
|
143
144
|
this.config = restoredConfig;
|
|
144
145
|
await this.persistConfig(this.config);
|
|
145
|
-
|
|
146
|
+
logger.info(`✅ Config restored from backup: ${backupFilename}`);
|
|
146
147
|
}
|
|
147
148
|
catch (error) {
|
|
148
149
|
throw new Error(`Failed to restore from backup ${backupFilename}: ${error.message}`);
|
|
@@ -167,10 +168,10 @@ export default ${JSON.stringify(currentConfig, null, 2)};`;
|
|
|
167
168
|
for (const backup of toDelete) {
|
|
168
169
|
try {
|
|
169
170
|
await unlink(backup.path);
|
|
170
|
-
|
|
171
|
+
logger.info(`🗑️ Deleted old backup: ${backup.filename}`);
|
|
171
172
|
}
|
|
172
173
|
catch (error) {
|
|
173
|
-
|
|
174
|
+
logger.warn(`Failed to delete backup ${backup.filename}:`, error.message);
|
|
174
175
|
}
|
|
175
176
|
}
|
|
176
177
|
}
|
|
@@ -248,7 +249,7 @@ export default ${JSON.stringify(currentConfig, null, 2)};`;
|
|
|
248
249
|
await mkdir(this.backupDir, { recursive: true });
|
|
249
250
|
}
|
|
250
251
|
catch (error) {
|
|
251
|
-
|
|
252
|
+
logger.warn("Failed to create backup directory:", error.message);
|
|
252
253
|
}
|
|
253
254
|
}
|
|
254
255
|
async readConfigFile() {
|
|
@@ -265,7 +266,7 @@ export default ${JSON.stringify(currentConfig, null, 2)};`;
|
|
|
265
266
|
throw new Error("Invalid config file format");
|
|
266
267
|
}
|
|
267
268
|
catch (error) {
|
|
268
|
-
|
|
269
|
+
logger.info("Config file not found, generating default...");
|
|
269
270
|
return await this.generateDefaultConfig();
|
|
270
271
|
}
|
|
271
272
|
}
|
package/dist/lib/mcp/index.d.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* Implementation based on research blueprint
|
|
5
5
|
*/
|
|
6
6
|
export type { McpMetadata, ExecutionContext, DiscoveredMcp, ToolInfo, ToolExecutionResult, } from "./contracts/mcpContract.js";
|
|
7
|
-
export { mcpLogger } from "
|
|
8
|
-
export type { LogLevel } from "
|
|
7
|
+
export { mcpLogger } from "../utils/logger.js";
|
|
8
|
+
export type { LogLevel } from "../utils/logger.js";
|
|
9
9
|
import type { McpMetadata } from "./contracts/mcpContract.js";
|
|
10
10
|
/**
|
|
11
11
|
* Initialize the MCP ecosystem - simplified
|
package/dist/lib/mcp/index.js
CHANGED
package/dist/lib/mcp/registry.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MCP Registry - Industry Standard Interface with camelCase
|
|
3
3
|
*/
|
|
4
|
-
import { registryLogger } from "
|
|
4
|
+
import { registryLogger } from "../utils/logger.js";
|
|
5
5
|
/**
|
|
6
6
|
* Simple MCP registry for plugin management
|
|
7
7
|
* Maintains backward compatibility with existing code
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { AIProviderFactory } from "../../../core/factory.js";
|
|
8
8
|
import { getBestProvider, getAvailableProviders, } from "../../../utils/providerUtils.js";
|
|
9
|
+
import { logger } from "../../../utils/logger.js";
|
|
9
10
|
/**
|
|
10
11
|
* Input Schemas for AI Analysis Tools
|
|
11
12
|
*/
|
|
@@ -89,7 +90,7 @@ const analyzeAIUsageTool = {
|
|
|
89
90
|
const typedParams = params;
|
|
90
91
|
const startTime = Date.now();
|
|
91
92
|
try {
|
|
92
|
-
|
|
93
|
+
logger.debug(`[AI-Analysis] Starting real AI-powered usage analysis for timeRange: ${typedParams.timeRange}`);
|
|
93
94
|
const providerName = await getBestProvider();
|
|
94
95
|
const provider = await AIProviderFactory.createProvider(providerName);
|
|
95
96
|
if (!provider) {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Updated to match industry standard camelCase interfaces
|
|
4
4
|
*/
|
|
5
5
|
import { MCPRegistry } from "./registry.js";
|
|
6
|
-
import { registryLogger } from "
|
|
6
|
+
import { registryLogger } from "../utils/logger.js";
|
|
7
7
|
import { randomUUID } from "crypto";
|
|
8
8
|
export class MCPToolRegistry extends MCPRegistry {
|
|
9
9
|
tools = new Map();
|
package/dist/lib/neurolink.js
CHANGED
|
@@ -14,7 +14,7 @@ catch (error) {
|
|
|
14
14
|
// Environment variables should be set externally in production
|
|
15
15
|
}
|
|
16
16
|
import { AIProviderFactory } from "./core/factory.js";
|
|
17
|
-
import { mcpLogger } from "./
|
|
17
|
+
import { mcpLogger } from "./utils/logger.js";
|
|
18
18
|
import { toolRegistry } from "./mcp/tool-registry.js";
|
|
19
19
|
import { logger } from "./utils/logger.js";
|
|
20
20
|
import { getBestProvider } from "./utils/providerUtils.js";
|
|
@@ -2,6 +2,7 @@ import { createAzure } from "@ai-sdk/azure";
|
|
|
2
2
|
import { streamText } from "ai";
|
|
3
3
|
import { BaseProvider } from "../core/base-provider.js";
|
|
4
4
|
import { validateApiKey, createAzureAPIKeyConfig, createAzureEndpointConfig, } from "../utils/providerConfig.js";
|
|
5
|
+
import { logger } from "../utils/logger.js";
|
|
5
6
|
export class AzureOpenAIProvider extends BaseProvider {
|
|
6
7
|
apiKey;
|
|
7
8
|
resourceName;
|
|
@@ -35,7 +36,7 @@ export class AzureOpenAIProvider extends BaseProvider {
|
|
|
35
36
|
apiKey: this.apiKey,
|
|
36
37
|
apiVersion: this.apiVersion,
|
|
37
38
|
});
|
|
38
|
-
|
|
39
|
+
logger.debug("Azure Vercel Provider initialized", {
|
|
39
40
|
deployment: this.deployment,
|
|
40
41
|
resourceName: this.resourceName,
|
|
41
42
|
provider: "azure-vercel",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Optional Telemetry Infrastructure (Phase 2)
|
|
2
2
|
export { TelemetryService } from "./telemetry-service.js";
|
|
3
|
+
import { logger } from "../utils/logger.js";
|
|
3
4
|
/**
|
|
4
5
|
* Initialize telemetry for NeuroLink
|
|
5
6
|
* OPTIONAL - Only works when NEUROLINK_TELEMETRY_ENABLED=true
|
|
@@ -9,7 +10,7 @@ export async function initializeTelemetry() {
|
|
|
9
10
|
const telemetry = TelemetryService.getInstance();
|
|
10
11
|
if (telemetry.isEnabled()) {
|
|
11
12
|
await telemetry.initialize();
|
|
12
|
-
|
|
13
|
+
logger.info("[NeuroLink] Telemetry initialized");
|
|
13
14
|
}
|
|
14
15
|
return telemetry;
|
|
15
16
|
}
|
|
@@ -1,12 +1,72 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* NeuroLink Logger Utility
|
|
2
|
+
* NeuroLink Unified Logger Utility
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Centralized logging for the entire NeuroLink ecosystem
|
|
5
|
+
* Supports both CLI --debug flag and NEUROLINK_DEBUG environment variable
|
|
6
|
+
* Migrated from MCP logging with enhanced features
|
|
5
7
|
*/
|
|
8
|
+
export type LogLevel = "debug" | "info" | "warn" | "error";
|
|
9
|
+
interface LogEntry {
|
|
10
|
+
level: LogLevel;
|
|
11
|
+
message: string;
|
|
12
|
+
timestamp: Date;
|
|
13
|
+
data?: unknown;
|
|
14
|
+
}
|
|
15
|
+
declare class NeuroLinkLogger {
|
|
16
|
+
private logLevel;
|
|
17
|
+
private logs;
|
|
18
|
+
private maxLogs;
|
|
19
|
+
private isDebugMode;
|
|
20
|
+
constructor();
|
|
21
|
+
setLogLevel(level: LogLevel): void;
|
|
22
|
+
shouldLog(level: LogLevel): boolean;
|
|
23
|
+
private getLogPrefix;
|
|
24
|
+
/**
|
|
25
|
+
* Outputs a log entry to the console based on the log level.
|
|
26
|
+
*
|
|
27
|
+
* @param level - The log level (debug, info, warn, error).
|
|
28
|
+
* @param prefix - The formatted log prefix.
|
|
29
|
+
* @param message - The log message.
|
|
30
|
+
* @param data - Optional additional data to log.
|
|
31
|
+
*/
|
|
32
|
+
private outputToConsole;
|
|
33
|
+
private log;
|
|
34
|
+
debug(message: string, data?: unknown): void;
|
|
35
|
+
info(message: string, data?: unknown): void;
|
|
36
|
+
warn(message: string, data?: unknown): void;
|
|
37
|
+
error(message: string, data?: unknown): void;
|
|
38
|
+
getLogs(level?: LogLevel): LogEntry[];
|
|
39
|
+
clearLogs(): void;
|
|
40
|
+
/**
|
|
41
|
+
* Logs messages unconditionally using `console.log`.
|
|
42
|
+
*
|
|
43
|
+
* This method is part of a legacy simple logger interface for backward compatibility.
|
|
44
|
+
* It bypasses the structured logging mechanism and should only be used when
|
|
45
|
+
* unstructured, unconditional logging is required.
|
|
46
|
+
*
|
|
47
|
+
* @param args - The arguments to log. These are passed directly to `console.log`.
|
|
48
|
+
*/
|
|
49
|
+
always(...args: unknown[]): void;
|
|
50
|
+
}
|
|
6
51
|
export declare const logger: {
|
|
7
52
|
debug: (...args: unknown[]) => void;
|
|
8
53
|
info: (...args: unknown[]) => void;
|
|
9
54
|
warn: (...args: unknown[]) => void;
|
|
10
55
|
error: (...args: unknown[]) => void;
|
|
11
56
|
always: (...args: unknown[]) => void;
|
|
57
|
+
setLogLevel: (level: LogLevel) => void;
|
|
58
|
+
getLogs: (level?: LogLevel) => LogEntry[];
|
|
59
|
+
clearLogs: () => void;
|
|
12
60
|
};
|
|
61
|
+
export declare const mcpLogger: NeuroLinkLogger;
|
|
62
|
+
export declare const autoDiscoveryLogger: NeuroLinkLogger;
|
|
63
|
+
export declare const registryLogger: NeuroLinkLogger;
|
|
64
|
+
export declare const unifiedRegistryLogger: NeuroLinkLogger;
|
|
65
|
+
export declare function setGlobalMCPLogLevel(level: LogLevel): void;
|
|
66
|
+
export declare const LogLevels: {
|
|
67
|
+
readonly debug: "debug";
|
|
68
|
+
readonly info: "info";
|
|
69
|
+
readonly warn: "warn";
|
|
70
|
+
readonly error: "error";
|
|
71
|
+
};
|
|
72
|
+
export type { LogEntry };
|
package/dist/lib/utils/logger.js
CHANGED
|
@@ -1,25 +1,190 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* NeuroLink Logger Utility
|
|
2
|
+
* NeuroLink Unified Logger Utility
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Centralized logging for the entire NeuroLink ecosystem
|
|
5
|
+
* Supports both CLI --debug flag and NEUROLINK_DEBUG environment variable
|
|
6
|
+
* Migrated from MCP logging with enhanced features
|
|
5
7
|
*/
|
|
8
|
+
// Pre-computed uppercase log levels for performance optimization
|
|
9
|
+
const UPPERCASE_LOG_LEVELS = {
|
|
10
|
+
debug: "DEBUG",
|
|
11
|
+
info: "INFO",
|
|
12
|
+
warn: "WARN",
|
|
13
|
+
error: "ERROR",
|
|
14
|
+
};
|
|
15
|
+
class NeuroLinkLogger {
|
|
16
|
+
logLevel = "info";
|
|
17
|
+
logs = [];
|
|
18
|
+
maxLogs = 1000;
|
|
19
|
+
isDebugMode;
|
|
20
|
+
constructor() {
|
|
21
|
+
// Cache debug mode check to avoid repeated array searches
|
|
22
|
+
this.isDebugMode =
|
|
23
|
+
process.argv.includes("--debug") ||
|
|
24
|
+
process.env.NEUROLINK_DEBUG === "true";
|
|
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
|
+
}
|
|
31
|
+
if (envLevel && ["debug", "info", "warn", "error"].includes(envLevel)) {
|
|
32
|
+
this.logLevel = envLevel;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
setLogLevel(level) {
|
|
36
|
+
this.logLevel = level;
|
|
37
|
+
}
|
|
38
|
+
shouldLog(level) {
|
|
39
|
+
// Hide all logs except errors unless debugging
|
|
40
|
+
if (!this.isDebugMode && level !== "error") {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
const levels = ["debug", "info", "warn", "error"];
|
|
44
|
+
return levels.indexOf(level) >= levels.indexOf(this.logLevel);
|
|
45
|
+
}
|
|
46
|
+
getLogPrefix(timestamp, level) {
|
|
47
|
+
return `[${timestamp}] [NEUROLINK:${UPPERCASE_LOG_LEVELS[level]}]`;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Outputs a log entry to the console based on the log level.
|
|
51
|
+
*
|
|
52
|
+
* @param level - The log level (debug, info, warn, error).
|
|
53
|
+
* @param prefix - The formatted log prefix.
|
|
54
|
+
* @param message - The log message.
|
|
55
|
+
* @param data - Optional additional data to log.
|
|
56
|
+
*/
|
|
57
|
+
outputToConsole(level, prefix, message, data) {
|
|
58
|
+
const logMethod = {
|
|
59
|
+
debug: console.debug,
|
|
60
|
+
info: console.info,
|
|
61
|
+
warn: console.warn,
|
|
62
|
+
error: console.error,
|
|
63
|
+
}[level];
|
|
64
|
+
if (data !== undefined && data !== null) {
|
|
65
|
+
logMethod(prefix, message, data);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
logMethod(prefix, message);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
log(level, message, data) {
|
|
72
|
+
if (!this.shouldLog(level)) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const entry = {
|
|
76
|
+
level,
|
|
77
|
+
message,
|
|
78
|
+
timestamp: new Date(),
|
|
79
|
+
data,
|
|
80
|
+
};
|
|
81
|
+
// Store log entry
|
|
82
|
+
this.logs.push(entry);
|
|
83
|
+
// Trim old logs
|
|
84
|
+
if (this.logs.length > this.maxLogs) {
|
|
85
|
+
this.logs = this.logs.slice(-this.maxLogs);
|
|
86
|
+
}
|
|
87
|
+
// Console output
|
|
88
|
+
const timestamp = entry.timestamp.toISOString();
|
|
89
|
+
const prefix = this.getLogPrefix(timestamp, level);
|
|
90
|
+
this.outputToConsole(level, prefix, message, data);
|
|
91
|
+
}
|
|
92
|
+
debug(message, data) {
|
|
93
|
+
this.log("debug", message, data);
|
|
94
|
+
}
|
|
95
|
+
info(message, data) {
|
|
96
|
+
this.log("info", message, data);
|
|
97
|
+
}
|
|
98
|
+
warn(message, data) {
|
|
99
|
+
this.log("warn", message, data);
|
|
100
|
+
}
|
|
101
|
+
error(message, data) {
|
|
102
|
+
this.log("error", message, data);
|
|
103
|
+
}
|
|
104
|
+
getLogs(level) {
|
|
105
|
+
if (level) {
|
|
106
|
+
return this.logs.filter((log) => log.level === level);
|
|
107
|
+
}
|
|
108
|
+
return [...this.logs];
|
|
109
|
+
}
|
|
110
|
+
clearLogs() {
|
|
111
|
+
this.logs = [];
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Logs messages unconditionally using `console.log`.
|
|
115
|
+
*
|
|
116
|
+
* This method is part of a legacy simple logger interface for backward compatibility.
|
|
117
|
+
* It bypasses the structured logging mechanism and should only be used when
|
|
118
|
+
* unstructured, unconditional logging is required.
|
|
119
|
+
*
|
|
120
|
+
* @param args - The arguments to log. These are passed directly to `console.log`.
|
|
121
|
+
*/
|
|
122
|
+
always(...args) {
|
|
123
|
+
console.log(...args);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// Export singleton instance
|
|
127
|
+
const neuroLinkLogger = new NeuroLinkLogger();
|
|
128
|
+
// Helper function to process arguments with minimal overhead
|
|
129
|
+
function processLoggerArgs(args, logMethod) {
|
|
130
|
+
if (args.length === 0) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
// Serialize the first argument robustly to handle complex objects
|
|
134
|
+
const message = (() => {
|
|
135
|
+
try {
|
|
136
|
+
return typeof args[0] === "string" ? args[0] : JSON.stringify(args[0]);
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
return "[Unserializable Object]";
|
|
140
|
+
}
|
|
141
|
+
})();
|
|
142
|
+
const data = args.length === 2 ? args[1] : args.length > 2 ? args.slice(1) : undefined;
|
|
143
|
+
logMethod(message, data);
|
|
144
|
+
}
|
|
145
|
+
// Main unified logger export
|
|
6
146
|
export const logger = {
|
|
7
147
|
debug: (...args) => {
|
|
8
|
-
if (
|
|
9
|
-
|
|
148
|
+
if (neuroLinkLogger.shouldLog("debug")) {
|
|
149
|
+
processLoggerArgs(args, (message, data) => neuroLinkLogger.debug(message, data));
|
|
10
150
|
}
|
|
11
151
|
},
|
|
12
152
|
info: (...args) => {
|
|
13
|
-
|
|
153
|
+
if (neuroLinkLogger.shouldLog("info")) {
|
|
154
|
+
processLoggerArgs(args, (message, data) => neuroLinkLogger.info(message, data));
|
|
155
|
+
}
|
|
14
156
|
},
|
|
15
157
|
warn: (...args) => {
|
|
16
|
-
|
|
158
|
+
if (neuroLinkLogger.shouldLog("warn")) {
|
|
159
|
+
processLoggerArgs(args, (message, data) => neuroLinkLogger.warn(message, data));
|
|
160
|
+
}
|
|
17
161
|
},
|
|
18
162
|
error: (...args) => {
|
|
19
|
-
|
|
20
|
-
|
|
163
|
+
if (neuroLinkLogger.shouldLog("error")) {
|
|
164
|
+
processLoggerArgs(args, (message, data) => neuroLinkLogger.error(message, data));
|
|
165
|
+
}
|
|
21
166
|
},
|
|
22
167
|
always: (...args) => {
|
|
23
|
-
|
|
168
|
+
neuroLinkLogger.always(...args);
|
|
24
169
|
},
|
|
170
|
+
// Expose structured logging methods
|
|
171
|
+
setLogLevel: (level) => neuroLinkLogger.setLogLevel(level),
|
|
172
|
+
getLogs: (level) => neuroLinkLogger.getLogs(level),
|
|
173
|
+
clearLogs: () => neuroLinkLogger.clearLogs(),
|
|
174
|
+
};
|
|
175
|
+
// MCP compatibility exports - all use the same unified logger
|
|
176
|
+
export const mcpLogger = neuroLinkLogger;
|
|
177
|
+
export const autoDiscoveryLogger = neuroLinkLogger;
|
|
178
|
+
export const registryLogger = neuroLinkLogger;
|
|
179
|
+
export const unifiedRegistryLogger = neuroLinkLogger;
|
|
180
|
+
// Global log level setter
|
|
181
|
+
export function setGlobalMCPLogLevel(level) {
|
|
182
|
+
neuroLinkLogger.setLogLevel(level);
|
|
183
|
+
}
|
|
184
|
+
// Export LogLevel enum for runtime use
|
|
185
|
+
export const LogLevels = {
|
|
186
|
+
debug: "debug",
|
|
187
|
+
info: "info",
|
|
188
|
+
warn: "warn",
|
|
189
|
+
error: "error",
|
|
25
190
|
};
|
package/dist/mcp/index.d.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* Implementation based on research blueprint
|
|
5
5
|
*/
|
|
6
6
|
export type { McpMetadata, ExecutionContext, DiscoveredMcp, ToolInfo, ToolExecutionResult, } from "./contracts/mcpContract.js";
|
|
7
|
-
export { mcpLogger } from "
|
|
8
|
-
export type { LogLevel } from "
|
|
7
|
+
export { mcpLogger } from "../utils/logger.js";
|
|
8
|
+
export type { LogLevel } from "../utils/logger.js";
|
|
9
9
|
import type { McpMetadata } from "./contracts/mcpContract.js";
|
|
10
10
|
/**
|
|
11
11
|
* Initialize the MCP ecosystem - simplified
|