@juspay/neurolink 3.0.1 → 4.0.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 (192) hide show
  1. package/CHANGELOG.md +57 -6
  2. package/README.md +235 -2
  3. package/dist/agent/direct-tools.d.ts +6 -6
  4. package/dist/chat/client-utils.d.ts +92 -0
  5. package/dist/chat/client-utils.js +298 -0
  6. package/dist/chat/index.d.ts +27 -0
  7. package/dist/chat/index.js +41 -0
  8. package/dist/chat/session-storage.d.ts +77 -0
  9. package/dist/chat/session-storage.js +233 -0
  10. package/dist/chat/session.d.ts +95 -0
  11. package/dist/chat/session.js +257 -0
  12. package/dist/chat/sse-handler.d.ts +49 -0
  13. package/dist/chat/sse-handler.js +266 -0
  14. package/dist/chat/types.d.ts +73 -0
  15. package/dist/chat/types.js +5 -0
  16. package/dist/chat/websocket-chat-handler.d.ts +36 -0
  17. package/dist/chat/websocket-chat-handler.js +262 -0
  18. package/dist/cli/commands/config.js +12 -12
  19. package/dist/cli/commands/mcp.js +3 -4
  20. package/dist/cli/index.d.ts +0 -7
  21. package/dist/cli/index.js +247 -28
  22. package/dist/config/configManager.d.ts +60 -0
  23. package/dist/config/configManager.js +300 -0
  24. package/dist/config/types.d.ts +136 -0
  25. package/dist/config/types.js +43 -0
  26. package/dist/core/analytics.d.ts +23 -0
  27. package/dist/core/analytics.js +131 -0
  28. package/dist/core/constants.d.ts +41 -0
  29. package/dist/core/constants.js +50 -0
  30. package/dist/core/defaults.d.ts +18 -0
  31. package/dist/core/defaults.js +29 -0
  32. package/dist/core/evaluation-config.d.ts +29 -0
  33. package/dist/core/evaluation-config.js +144 -0
  34. package/dist/core/evaluation-providers.d.ts +30 -0
  35. package/dist/core/evaluation-providers.js +187 -0
  36. package/dist/core/evaluation.d.ts +117 -0
  37. package/dist/core/evaluation.js +528 -0
  38. package/dist/core/factory.js +33 -25
  39. package/dist/core/types.d.ts +165 -6
  40. package/dist/core/types.js +3 -4
  41. package/dist/index.d.ts +9 -4
  42. package/dist/index.js +25 -4
  43. package/dist/lib/agent/direct-tools.d.ts +6 -6
  44. package/dist/lib/chat/client-utils.d.ts +92 -0
  45. package/dist/lib/chat/client-utils.js +298 -0
  46. package/dist/lib/chat/index.d.ts +27 -0
  47. package/dist/lib/chat/index.js +41 -0
  48. package/dist/lib/chat/session-storage.d.ts +77 -0
  49. package/dist/lib/chat/session-storage.js +233 -0
  50. package/dist/lib/chat/session.d.ts +95 -0
  51. package/dist/lib/chat/session.js +257 -0
  52. package/dist/lib/chat/sse-handler.d.ts +49 -0
  53. package/dist/lib/chat/sse-handler.js +266 -0
  54. package/dist/lib/chat/types.d.ts +73 -0
  55. package/dist/lib/chat/types.js +5 -0
  56. package/dist/lib/chat/websocket-chat-handler.d.ts +36 -0
  57. package/dist/lib/chat/websocket-chat-handler.js +262 -0
  58. package/dist/lib/config/configManager.d.ts +60 -0
  59. package/dist/lib/config/configManager.js +300 -0
  60. package/dist/lib/config/types.d.ts +136 -0
  61. package/dist/lib/config/types.js +43 -0
  62. package/dist/lib/core/analytics.d.ts +23 -0
  63. package/dist/lib/core/analytics.js +131 -0
  64. package/dist/lib/core/constants.d.ts +41 -0
  65. package/dist/lib/core/constants.js +50 -0
  66. package/dist/lib/core/defaults.d.ts +18 -0
  67. package/dist/lib/core/defaults.js +29 -0
  68. package/dist/lib/core/evaluation-config.d.ts +29 -0
  69. package/dist/lib/core/evaluation-config.js +144 -0
  70. package/dist/lib/core/evaluation-providers.d.ts +30 -0
  71. package/dist/lib/core/evaluation-providers.js +187 -0
  72. package/dist/lib/core/evaluation.d.ts +117 -0
  73. package/dist/lib/core/evaluation.js +528 -0
  74. package/dist/lib/core/factory.js +33 -26
  75. package/dist/lib/core/types.d.ts +165 -6
  76. package/dist/lib/core/types.js +3 -4
  77. package/dist/lib/index.d.ts +9 -4
  78. package/dist/lib/index.js +25 -4
  79. package/dist/lib/mcp/contracts/mcpContract.d.ts +118 -0
  80. package/dist/lib/mcp/contracts/mcpContract.js +5 -0
  81. package/dist/lib/mcp/function-calling.js +11 -3
  82. package/dist/lib/mcp/logging.js +5 -0
  83. package/dist/lib/mcp/neurolink-mcp-client.js +2 -1
  84. package/dist/lib/mcp/orchestrator.js +18 -9
  85. package/dist/lib/mcp/registry.d.ts +49 -16
  86. package/dist/lib/mcp/registry.js +80 -6
  87. package/dist/lib/mcp/servers/ai-providers/ai-workflow-tools.js +5 -4
  88. package/dist/lib/mcp/tool-integration.js +1 -1
  89. package/dist/lib/mcp/tool-registry.d.ts +55 -34
  90. package/dist/lib/mcp/tool-registry.js +111 -97
  91. package/dist/lib/mcp/unified-mcp.js +6 -1
  92. package/dist/lib/mcp/unified-registry.d.ts +12 -4
  93. package/dist/lib/mcp/unified-registry.js +17 -4
  94. package/dist/lib/neurolink.d.ts +26 -0
  95. package/dist/lib/neurolink.js +43 -1
  96. package/dist/lib/providers/agent-enhanced-provider.d.ts +11 -2
  97. package/dist/lib/providers/agent-enhanced-provider.js +86 -15
  98. package/dist/lib/providers/amazonBedrock.d.ts +9 -1
  99. package/dist/lib/providers/amazonBedrock.js +26 -2
  100. package/dist/lib/providers/analytics-helper.d.ts +53 -0
  101. package/dist/lib/providers/analytics-helper.js +151 -0
  102. package/dist/lib/providers/anthropic.d.ts +11 -1
  103. package/dist/lib/providers/anthropic.js +29 -4
  104. package/dist/lib/providers/azureOpenAI.d.ts +3 -1
  105. package/dist/lib/providers/azureOpenAI.js +28 -4
  106. package/dist/lib/providers/function-calling-provider.d.ts +9 -1
  107. package/dist/lib/providers/function-calling-provider.js +14 -1
  108. package/dist/lib/providers/googleAIStudio.d.ts +15 -1
  109. package/dist/lib/providers/googleAIStudio.js +32 -2
  110. package/dist/lib/providers/googleVertexAI.d.ts +9 -1
  111. package/dist/lib/providers/googleVertexAI.js +31 -2
  112. package/dist/lib/providers/huggingFace.d.ts +3 -1
  113. package/dist/lib/providers/huggingFace.js +26 -3
  114. package/dist/lib/providers/mcp-provider.d.ts +9 -1
  115. package/dist/lib/providers/mcp-provider.js +12 -0
  116. package/dist/lib/providers/mistralAI.d.ts +3 -1
  117. package/dist/lib/providers/mistralAI.js +25 -2
  118. package/dist/lib/providers/ollama.d.ts +3 -1
  119. package/dist/lib/providers/ollama.js +27 -4
  120. package/dist/lib/providers/openAI.d.ts +15 -1
  121. package/dist/lib/providers/openAI.js +32 -2
  122. package/dist/lib/proxy/proxy-fetch.js +8 -7
  123. package/dist/lib/services/streaming/streaming-manager.d.ts +29 -0
  124. package/dist/lib/services/streaming/streaming-manager.js +244 -0
  125. package/dist/lib/services/types.d.ts +155 -0
  126. package/dist/lib/services/types.js +2 -0
  127. package/dist/lib/services/websocket/websocket-server.d.ts +34 -0
  128. package/dist/lib/services/websocket/websocket-server.js +304 -0
  129. package/dist/lib/telemetry/index.d.ts +15 -0
  130. package/dist/lib/telemetry/index.js +22 -0
  131. package/dist/lib/telemetry/telemetry-service.d.ts +47 -0
  132. package/dist/lib/telemetry/telemetry-service.js +259 -0
  133. package/dist/lib/utils/streaming-utils.d.ts +67 -0
  134. package/dist/lib/utils/streaming-utils.js +201 -0
  135. package/dist/mcp/contracts/mcpContract.d.ts +118 -0
  136. package/dist/mcp/contracts/mcpContract.js +5 -0
  137. package/dist/mcp/function-calling.js +11 -3
  138. package/dist/mcp/logging.js +5 -0
  139. package/dist/mcp/neurolink-mcp-client.js +2 -1
  140. package/dist/mcp/orchestrator.js +18 -9
  141. package/dist/mcp/registry.d.ts +49 -16
  142. package/dist/mcp/registry.js +80 -6
  143. package/dist/mcp/servers/ai-providers/ai-workflow-tools.d.ts +2 -2
  144. package/dist/mcp/servers/ai-providers/ai-workflow-tools.js +5 -4
  145. package/dist/mcp/tool-integration.js +1 -1
  146. package/dist/mcp/tool-registry.d.ts +55 -34
  147. package/dist/mcp/tool-registry.js +111 -97
  148. package/dist/mcp/unified-mcp.js +6 -1
  149. package/dist/mcp/unified-registry.d.ts +12 -4
  150. package/dist/mcp/unified-registry.js +17 -4
  151. package/dist/neurolink.d.ts +26 -0
  152. package/dist/neurolink.js +43 -1
  153. package/dist/providers/agent-enhanced-provider.d.ts +11 -2
  154. package/dist/providers/agent-enhanced-provider.js +86 -15
  155. package/dist/providers/amazonBedrock.d.ts +9 -1
  156. package/dist/providers/amazonBedrock.js +26 -2
  157. package/dist/providers/analytics-helper.d.ts +53 -0
  158. package/dist/providers/analytics-helper.js +151 -0
  159. package/dist/providers/anthropic.d.ts +11 -1
  160. package/dist/providers/anthropic.js +29 -4
  161. package/dist/providers/azureOpenAI.d.ts +3 -1
  162. package/dist/providers/azureOpenAI.js +29 -4
  163. package/dist/providers/function-calling-provider.d.ts +9 -1
  164. package/dist/providers/function-calling-provider.js +14 -1
  165. package/dist/providers/googleAIStudio.d.ts +15 -1
  166. package/dist/providers/googleAIStudio.js +32 -2
  167. package/dist/providers/googleVertexAI.d.ts +9 -1
  168. package/dist/providers/googleVertexAI.js +31 -2
  169. package/dist/providers/huggingFace.d.ts +3 -1
  170. package/dist/providers/huggingFace.js +26 -3
  171. package/dist/providers/mcp-provider.d.ts +9 -1
  172. package/dist/providers/mcp-provider.js +12 -0
  173. package/dist/providers/mistralAI.d.ts +3 -1
  174. package/dist/providers/mistralAI.js +25 -2
  175. package/dist/providers/ollama.d.ts +3 -1
  176. package/dist/providers/ollama.js +27 -4
  177. package/dist/providers/openAI.d.ts +15 -1
  178. package/dist/providers/openAI.js +33 -2
  179. package/dist/proxy/proxy-fetch.js +8 -7
  180. package/dist/services/streaming/streaming-manager.d.ts +29 -0
  181. package/dist/services/streaming/streaming-manager.js +244 -0
  182. package/dist/services/types.d.ts +155 -0
  183. package/dist/services/types.js +2 -0
  184. package/dist/services/websocket/websocket-server.d.ts +34 -0
  185. package/dist/services/websocket/websocket-server.js +304 -0
  186. package/dist/telemetry/index.d.ts +15 -0
  187. package/dist/telemetry/index.js +22 -0
  188. package/dist/telemetry/telemetry-service.d.ts +47 -0
  189. package/dist/telemetry/telemetry-service.js +261 -0
  190. package/dist/utils/streaming-utils.d.ts +67 -0
  191. package/dist/utils/streaming-utils.js +201 -0
  192. package/package.json +18 -2
@@ -0,0 +1,155 @@
1
+ export interface StreamingSession {
2
+ id: string;
3
+ connectionId: string;
4
+ provider: string;
5
+ status: "active" | "paused" | "terminated";
6
+ startTime: number;
7
+ lastActivity: number;
8
+ config: StreamingConfig;
9
+ metrics: {
10
+ bytesTransferred: number;
11
+ messagesCount: number;
12
+ averageLatency: number;
13
+ errorCount: number;
14
+ };
15
+ }
16
+ export interface WebSocketOptions {
17
+ port?: number;
18
+ maxConnections?: number;
19
+ heartbeatInterval?: number;
20
+ enableCompression?: boolean;
21
+ enableBackpressure?: boolean;
22
+ bufferSize?: number;
23
+ timeoutMs?: number;
24
+ }
25
+ export interface StreamingConfig {
26
+ provider: string;
27
+ model: string;
28
+ streamingMode: "real-time" | "buffered" | "adaptive";
29
+ compressionEnabled: boolean;
30
+ maxChunkSize: number;
31
+ bufferSize: number;
32
+ latencyTarget: number;
33
+ }
34
+ export interface StreamingPool {
35
+ id: string;
36
+ maxSessions: number;
37
+ activeSessions: Set<string>;
38
+ config: StreamingPoolConfig;
39
+ loadBalancer: LoadBalancingStrategy;
40
+ }
41
+ export interface StreamingPoolConfig {
42
+ maxConcurrentSessions: number;
43
+ sessionTimeout: number;
44
+ loadBalancing: LoadBalancingStrategy;
45
+ autoScaling: {
46
+ enabled: boolean;
47
+ minSessions: number;
48
+ maxSessions: number;
49
+ scaleUpThreshold: number;
50
+ scaleDownThreshold: number;
51
+ };
52
+ }
53
+ export type LoadBalancingStrategy = "round-robin" | "least-connections" | "weighted" | "adaptive";
54
+ export interface StreamingChannel {
55
+ id: string;
56
+ connectionId: string;
57
+ type: "ai-response" | "mcp-tool" | "chat" | "notification";
58
+ status: "open" | "closed" | "error";
59
+ buffer: StreamingBuffer;
60
+ onData: (data: any) => void;
61
+ onError: (error: Error) => void;
62
+ onClose: () => void;
63
+ }
64
+ export interface StreamingBuffer {
65
+ data: any[];
66
+ maxSize: number;
67
+ currentSize: number;
68
+ flushThreshold: number;
69
+ lastFlush: number;
70
+ }
71
+ export interface StreamingMetrics {
72
+ sessionId?: string;
73
+ activeSessions: number;
74
+ totalBytesTransferred: number;
75
+ averageLatency: number;
76
+ throughputBps: number;
77
+ errorRate: number;
78
+ connectionCount: number;
79
+ uptime: number;
80
+ }
81
+ export interface StreamingHealthStatus {
82
+ status: "healthy" | "degraded" | "unhealthy";
83
+ activeSessions: number;
84
+ errorRate: number;
85
+ averageLatency: number;
86
+ lastHealthCheck: number;
87
+ issues: string[];
88
+ }
89
+ export interface WebSocketMessage {
90
+ id: string;
91
+ type: "chat" | "ai-response" | "tool-result" | "system" | "heartbeat" | "error";
92
+ connectionId: string;
93
+ roomId?: string;
94
+ timestamp: number;
95
+ data: any;
96
+ metadata?: {
97
+ provider?: string;
98
+ model?: string;
99
+ tokens?: number;
100
+ latency?: number;
101
+ };
102
+ }
103
+ export interface ChatRequest {
104
+ prompt: string;
105
+ sessionId?: string;
106
+ options?: {
107
+ temperature?: number;
108
+ maxTokens?: number;
109
+ streaming?: boolean;
110
+ enableTools?: boolean;
111
+ };
112
+ }
113
+ export interface GroupChatRequest extends ChatRequest {
114
+ roomId: string;
115
+ userId?: string;
116
+ broadcastToRoom?: boolean;
117
+ }
118
+ export interface StreamingChatRequest extends ChatRequest {
119
+ streamingOptions?: {
120
+ chunkSize?: number;
121
+ flushInterval?: number;
122
+ enableCompression?: boolean;
123
+ };
124
+ }
125
+ export interface MultiModalContent {
126
+ type: "text" | "image" | "audio" | "video" | "file";
127
+ content: string | Buffer;
128
+ metadata?: {
129
+ mimeType?: string;
130
+ size?: number;
131
+ duration?: number;
132
+ dimensions?: {
133
+ width: number;
134
+ height: number;
135
+ };
136
+ };
137
+ }
138
+ export interface BufferConfig {
139
+ maxSize: number;
140
+ flushThreshold: number;
141
+ flushInterval: number;
142
+ compressionEnabled: boolean;
143
+ persistToDisk: boolean;
144
+ }
145
+ export interface ConnectionInfo {
146
+ id: string;
147
+ userId?: string;
148
+ userAgent?: string;
149
+ ipAddress?: string;
150
+ connectedAt: number;
151
+ lastActivity: number;
152
+ rooms: Set<string>;
153
+ subscriptions: Set<string>;
154
+ metadata: Record<string, any>;
155
+ }
@@ -0,0 +1,2 @@
1
+ // Real-time Services Types
2
+ export {};
@@ -0,0 +1,34 @@
1
+ import { EventEmitter } from "events";
2
+ import type { WebSocketOptions, WebSocketMessage, StreamingChannel } from "../types.js";
3
+ export declare class NeuroLinkWebSocketServer extends EventEmitter {
4
+ private wss;
5
+ private connections;
6
+ private connectionInfo;
7
+ private rooms;
8
+ private streamingChannels;
9
+ private heartbeatInterval?;
10
+ private options;
11
+ constructor(options?: WebSocketOptions);
12
+ private setupEventHandlers;
13
+ private handleConnection;
14
+ private handleMessage;
15
+ private handleDisconnection;
16
+ joinRoom(connectionId: string, roomId: string): boolean;
17
+ leaveRoom(connectionId: string, roomId: string): boolean;
18
+ broadcastToRoom(roomId: string, message: WebSocketMessage): void;
19
+ createStreamingChannel(connectionId: string, channelId: string): StreamingChannel;
20
+ destroyStreamingChannel(channelId: string): void;
21
+ private sendMessage;
22
+ private sendError;
23
+ private updateLastActivity;
24
+ private handleHeartbeat;
25
+ private handleChatMessage;
26
+ private startHeartbeat;
27
+ getConnectionCount(): number;
28
+ getRoomCount(): number;
29
+ getActiveChannels(): number;
30
+ close(): void;
31
+ private handleChannelData;
32
+ private handleChannelError;
33
+ private handleChannelClose;
34
+ }
@@ -0,0 +1,304 @@
1
+ import { WebSocketServer, WebSocket } from "ws";
2
+ import { EventEmitter } from "events";
3
+ import { randomUUID } from "crypto";
4
+ export class NeuroLinkWebSocketServer extends EventEmitter {
5
+ wss;
6
+ connections = new Map();
7
+ connectionInfo = new Map();
8
+ rooms = new Map();
9
+ streamingChannels = new Map();
10
+ heartbeatInterval;
11
+ options;
12
+ constructor(options = {}) {
13
+ super();
14
+ this.options = {
15
+ port: options.port || 8080,
16
+ maxConnections: options.maxConnections || 1000,
17
+ heartbeatInterval: options.heartbeatInterval || 30000,
18
+ enableCompression: options.enableCompression ?? true,
19
+ enableBackpressure: options.enableBackpressure ?? true,
20
+ bufferSize: options.bufferSize || 8192,
21
+ timeoutMs: options.timeoutMs || 30000,
22
+ };
23
+ this.wss = new WebSocketServer({
24
+ port: this.options.port,
25
+ perMessageDeflate: this.options.enableCompression,
26
+ });
27
+ this.setupEventHandlers();
28
+ this.startHeartbeat();
29
+ }
30
+ setupEventHandlers() {
31
+ this.wss.on("connection", (ws, request) => {
32
+ this.handleConnection(ws, request);
33
+ });
34
+ this.wss.on("error", (error) => {
35
+ console.error("[WebSocket Server] Error:", error);
36
+ this.emit("error", error);
37
+ });
38
+ }
39
+ handleConnection(ws, request) {
40
+ if (this.connections.size >= this.options.maxConnections) {
41
+ ws.close(1013, "Server at capacity");
42
+ return;
43
+ }
44
+ const connectionId = randomUUID();
45
+ const userAgent = request.headers["user-agent"];
46
+ const ipAddress = request.socket.remoteAddress;
47
+ // Store connection
48
+ this.connections.set(connectionId, ws);
49
+ this.connectionInfo.set(connectionId, {
50
+ id: connectionId,
51
+ userAgent,
52
+ ipAddress,
53
+ connectedAt: Date.now(),
54
+ lastActivity: Date.now(),
55
+ rooms: new Set(),
56
+ subscriptions: new Set(),
57
+ metadata: {},
58
+ });
59
+ // Setup WebSocket event handlers
60
+ ws.on("message", (data) => {
61
+ this.handleMessage(connectionId, data);
62
+ });
63
+ ws.on("close", () => {
64
+ this.handleDisconnection(connectionId);
65
+ });
66
+ ws.on("error", (error) => {
67
+ console.error(`[WebSocket] Connection ${connectionId} error:`, error);
68
+ this.handleDisconnection(connectionId);
69
+ });
70
+ // Send connection confirmation
71
+ this.sendMessage(connectionId, {
72
+ id: randomUUID(),
73
+ type: "system",
74
+ connectionId,
75
+ timestamp: Date.now(),
76
+ data: {
77
+ event: "connected",
78
+ connectionId,
79
+ serverInfo: {
80
+ version: "3.0.1",
81
+ features: ["streaming", "rooms", "tools"],
82
+ },
83
+ },
84
+ });
85
+ console.log(`[WebSocket] New connection: ${connectionId} (${this.connections.size}/${this.options.maxConnections})`);
86
+ this.emit("connection", { connectionId, userAgent, ipAddress });
87
+ }
88
+ handleMessage(connectionId, data) {
89
+ try {
90
+ const message = JSON.parse(data.toString());
91
+ this.updateLastActivity(connectionId);
92
+ switch (message.type) {
93
+ case "heartbeat":
94
+ this.handleHeartbeat(connectionId);
95
+ break;
96
+ case "chat":
97
+ this.handleChatMessage(connectionId, message);
98
+ break;
99
+ default:
100
+ this.emit("message", { connectionId, message });
101
+ }
102
+ }
103
+ catch (error) {
104
+ console.error(`[WebSocket] Invalid message from ${connectionId}:`, error);
105
+ this.sendError(connectionId, "Invalid message format");
106
+ }
107
+ }
108
+ handleDisconnection(connectionId) {
109
+ const connection = this.connectionInfo.get(connectionId);
110
+ if (!connection) {
111
+ return;
112
+ }
113
+ // Leave all rooms
114
+ connection.rooms.forEach((roomId) => {
115
+ this.leaveRoom(connectionId, roomId);
116
+ });
117
+ // Close streaming channels
118
+ this.streamingChannels.forEach((channel, channelId) => {
119
+ if (channel.connectionId === connectionId) {
120
+ channel.onClose();
121
+ this.streamingChannels.delete(channelId);
122
+ }
123
+ });
124
+ // Clean up
125
+ this.connections.delete(connectionId);
126
+ this.connectionInfo.delete(connectionId);
127
+ console.log(`[WebSocket] Disconnected: ${connectionId} (${this.connections.size}/${this.options.maxConnections})`);
128
+ this.emit("disconnection", { connectionId });
129
+ }
130
+ // Room Management
131
+ joinRoom(connectionId, roomId) {
132
+ const connection = this.connectionInfo.get(connectionId);
133
+ if (!connection) {
134
+ return false;
135
+ }
136
+ if (!this.rooms.has(roomId)) {
137
+ this.rooms.set(roomId, new Set());
138
+ }
139
+ this.rooms.get(roomId).add(connectionId);
140
+ connection.rooms.add(roomId);
141
+ this.sendMessage(connectionId, {
142
+ id: randomUUID(),
143
+ type: "system",
144
+ connectionId,
145
+ roomId,
146
+ timestamp: Date.now(),
147
+ data: {
148
+ event: "room_joined",
149
+ roomId,
150
+ memberCount: this.rooms.get(roomId).size,
151
+ },
152
+ });
153
+ console.log(`[WebSocket] ${connectionId} joined room ${roomId}`);
154
+ return true;
155
+ }
156
+ leaveRoom(connectionId, roomId) {
157
+ const connection = this.connectionInfo.get(connectionId);
158
+ if (!connection) {
159
+ return false;
160
+ }
161
+ const room = this.rooms.get(roomId);
162
+ if (!room) {
163
+ return false;
164
+ }
165
+ room.delete(connectionId);
166
+ connection.rooms.delete(roomId);
167
+ if (room.size === 0) {
168
+ this.rooms.delete(roomId);
169
+ }
170
+ this.sendMessage(connectionId, {
171
+ id: randomUUID(),
172
+ type: "system",
173
+ connectionId,
174
+ roomId,
175
+ timestamp: Date.now(),
176
+ data: {
177
+ event: "room_left",
178
+ roomId,
179
+ memberCount: room.size,
180
+ },
181
+ });
182
+ console.log(`[WebSocket] ${connectionId} left room ${roomId}`);
183
+ return true;
184
+ }
185
+ broadcastToRoom(roomId, message) {
186
+ const room = this.rooms.get(roomId);
187
+ if (!room) {
188
+ return;
189
+ }
190
+ room.forEach((connectionId) => {
191
+ this.sendMessage(connectionId, { ...message, roomId });
192
+ });
193
+ }
194
+ // Streaming Support
195
+ createStreamingChannel(connectionId, channelId) {
196
+ const channel = {
197
+ id: channelId,
198
+ connectionId,
199
+ type: "ai-response",
200
+ status: "open",
201
+ buffer: {
202
+ data: [],
203
+ maxSize: this.options.bufferSize,
204
+ currentSize: 0,
205
+ flushThreshold: Math.floor(this.options.bufferSize * 0.8),
206
+ lastFlush: Date.now(),
207
+ },
208
+ onData: (data) => this.handleChannelData(channelId, data),
209
+ onError: (error) => this.handleChannelError(channelId, error),
210
+ onClose: () => this.handleChannelClose(channelId),
211
+ };
212
+ this.streamingChannels.set(channelId, channel);
213
+ return channel;
214
+ }
215
+ destroyStreamingChannel(channelId) {
216
+ const channel = this.streamingChannels.get(channelId);
217
+ if (channel) {
218
+ channel.status = "closed";
219
+ channel.onClose();
220
+ this.streamingChannels.delete(channelId);
221
+ }
222
+ }
223
+ // Helper methods
224
+ sendMessage(connectionId, message) {
225
+ const ws = this.connections.get(connectionId);
226
+ if (!ws || ws.readyState !== WebSocket.OPEN) {
227
+ return false;
228
+ }
229
+ try {
230
+ ws.send(JSON.stringify(message));
231
+ return true;
232
+ }
233
+ catch (error) {
234
+ console.error(`[WebSocket] Failed to send message to ${connectionId}:`, error);
235
+ return false;
236
+ }
237
+ }
238
+ sendError(connectionId, errorMessage) {
239
+ this.sendMessage(connectionId, {
240
+ id: randomUUID(),
241
+ type: "error",
242
+ connectionId,
243
+ timestamp: Date.now(),
244
+ data: { error: errorMessage },
245
+ });
246
+ }
247
+ updateLastActivity(connectionId) {
248
+ const connection = this.connectionInfo.get(connectionId);
249
+ if (connection) {
250
+ connection.lastActivity = Date.now();
251
+ }
252
+ }
253
+ handleHeartbeat(connectionId) {
254
+ this.sendMessage(connectionId, {
255
+ id: randomUUID(),
256
+ type: "heartbeat",
257
+ connectionId,
258
+ timestamp: Date.now(),
259
+ data: { pong: true },
260
+ });
261
+ }
262
+ handleChatMessage(connectionId, message) {
263
+ this.emit("chat-message", { connectionId, message });
264
+ }
265
+ startHeartbeat() {
266
+ this.heartbeatInterval = setInterval(() => {
267
+ this.connections.forEach((ws, connectionId) => {
268
+ if (ws.readyState === WebSocket.OPEN) {
269
+ const connection = this.connectionInfo.get(connectionId);
270
+ if (connection &&
271
+ Date.now() - connection.lastActivity > this.options.timeoutMs) {
272
+ console.log(`[WebSocket] Timeout for connection ${connectionId}`);
273
+ ws.terminate();
274
+ }
275
+ }
276
+ });
277
+ }, this.options.heartbeatInterval);
278
+ }
279
+ // Public getters
280
+ getConnectionCount() {
281
+ return this.connections.size;
282
+ }
283
+ getRoomCount() {
284
+ return this.rooms.size;
285
+ }
286
+ getActiveChannels() {
287
+ return this.streamingChannels.size;
288
+ }
289
+ close() {
290
+ if (this.heartbeatInterval) {
291
+ clearInterval(this.heartbeatInterval);
292
+ }
293
+ this.wss.close();
294
+ }
295
+ handleChannelData(channelId, data) {
296
+ // Implementation for channel data handling
297
+ }
298
+ handleChannelError(channelId, error) {
299
+ console.error(`[Streaming Channel] ${channelId} error:`, error);
300
+ }
301
+ handleChannelClose(channelId) {
302
+ console.log(`[Streaming Channel] ${channelId} closed`);
303
+ }
304
+ }
@@ -0,0 +1,15 @@
1
+ export { TelemetryService, type HealthMetrics } from "./telemetry-service.js";
2
+ /**
3
+ * Initialize telemetry for NeuroLink
4
+ * OPTIONAL - Only works when NEUROLINK_TELEMETRY_ENABLED=true
5
+ */
6
+ export declare function initializeTelemetry(): Promise<import("./telemetry-service.js").TelemetryService>;
7
+ /**
8
+ * Get telemetry status
9
+ */
10
+ export declare function getTelemetryStatus(): Promise<{
11
+ enabled: boolean;
12
+ endpoint?: string;
13
+ service?: string;
14
+ version?: string;
15
+ }>;
@@ -0,0 +1,22 @@
1
+ // Optional Telemetry Infrastructure (Phase 2)
2
+ export { TelemetryService } from "./telemetry-service.js";
3
+ /**
4
+ * Initialize telemetry for NeuroLink
5
+ * OPTIONAL - Only works when NEUROLINK_TELEMETRY_ENABLED=true
6
+ */
7
+ export async function initializeTelemetry() {
8
+ const { TelemetryService } = await import("./telemetry-service.js");
9
+ const telemetry = TelemetryService.getInstance();
10
+ if (telemetry.isEnabled()) {
11
+ await telemetry.initialize();
12
+ console.log("[NeuroLink] Telemetry initialized");
13
+ }
14
+ return telemetry;
15
+ }
16
+ /**
17
+ * Get telemetry status
18
+ */
19
+ export async function getTelemetryStatus() {
20
+ const { TelemetryService } = await import("./telemetry-service.js");
21
+ return TelemetryService.getInstance().getStatus();
22
+ }
@@ -0,0 +1,47 @@
1
+ export interface HealthMetrics {
2
+ timestamp: number;
3
+ memoryUsage: NodeJS.MemoryUsage;
4
+ uptime: number;
5
+ activeConnections: number;
6
+ errorRate: number;
7
+ averageResponseTime: number;
8
+ }
9
+ export declare class TelemetryService {
10
+ private static instance;
11
+ private sdk?;
12
+ private enabled;
13
+ private meter?;
14
+ private tracer?;
15
+ private aiRequestCounter?;
16
+ private aiRequestDuration?;
17
+ private aiTokensUsed?;
18
+ private aiProviderErrors?;
19
+ private mcpToolCalls?;
20
+ private connectionCounter?;
21
+ private responseTimeHistogram?;
22
+ private constructor();
23
+ static getInstance(): TelemetryService;
24
+ private isTelemetryEnabled;
25
+ private initializeTelemetry;
26
+ private initializeMetrics;
27
+ initialize(): Promise<void>;
28
+ traceAIRequest<T>(provider: string, operation: () => Promise<T>): Promise<T>;
29
+ recordAIRequest(provider: string, model: string, tokens: number, duration: number): void;
30
+ recordAIError(provider: string, error: Error): void;
31
+ recordMCPToolCall(toolName: string, duration: number, success: boolean): void;
32
+ recordConnection(type: "websocket" | "sse" | "http"): void;
33
+ recordResponseTime(endpoint: string, method: string, duration: number): void;
34
+ recordCustomMetric(name: string, value: number, labels?: Record<string, string>): void;
35
+ recordCustomHistogram(name: string, value: number, labels?: Record<string, string>): void;
36
+ getHealthMetrics(): Promise<HealthMetrics>;
37
+ isEnabled(): boolean;
38
+ getStatus(): {
39
+ enabled: boolean;
40
+ endpoint?: string;
41
+ service?: string;
42
+ version?: string;
43
+ };
44
+ private getDurationBucket;
45
+ private getStatusBucket;
46
+ shutdown(): Promise<void>;
47
+ }