@juspay/neurolink 3.0.1 → 4.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.
Files changed (232) hide show
  1. package/CHANGELOG.md +66 -6
  2. package/README.md +318 -27
  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/dynamic-chain-executor.d.ts +201 -0
  82. package/dist/lib/mcp/dynamic-chain-executor.js +489 -0
  83. package/dist/lib/mcp/dynamic-orchestrator.d.ts +109 -0
  84. package/dist/lib/mcp/dynamic-orchestrator.js +351 -0
  85. package/dist/lib/mcp/error-manager.d.ts +254 -0
  86. package/dist/lib/mcp/error-manager.js +501 -0
  87. package/dist/lib/mcp/error-recovery.d.ts +158 -0
  88. package/dist/lib/mcp/error-recovery.js +405 -0
  89. package/dist/lib/mcp/function-calling.js +11 -3
  90. package/dist/lib/mcp/health-monitor.d.ts +256 -0
  91. package/dist/lib/mcp/health-monitor.js +621 -0
  92. package/dist/lib/mcp/logging.js +5 -0
  93. package/dist/lib/mcp/neurolink-mcp-client.js +2 -1
  94. package/dist/lib/mcp/orchestrator.d.ts +136 -5
  95. package/dist/lib/mcp/orchestrator.js +332 -16
  96. package/dist/lib/mcp/registry.d.ts +71 -16
  97. package/dist/lib/mcp/registry.js +104 -6
  98. package/dist/lib/mcp/semaphore-manager.d.ts +137 -0
  99. package/dist/lib/mcp/semaphore-manager.js +329 -0
  100. package/dist/lib/mcp/servers/ai-providers/ai-workflow-tools.d.ts +2 -2
  101. package/dist/lib/mcp/servers/ai-providers/ai-workflow-tools.js +5 -4
  102. package/dist/lib/mcp/session-manager.d.ts +186 -0
  103. package/dist/lib/mcp/session-manager.js +400 -0
  104. package/dist/lib/mcp/session-persistence.d.ts +93 -0
  105. package/dist/lib/mcp/session-persistence.js +298 -0
  106. package/dist/lib/mcp/tool-integration.js +1 -1
  107. package/dist/lib/mcp/tool-registry.d.ts +55 -34
  108. package/dist/lib/mcp/tool-registry.js +111 -97
  109. package/dist/lib/mcp/transport-manager.d.ts +153 -0
  110. package/dist/lib/mcp/transport-manager.js +330 -0
  111. package/dist/lib/mcp/unified-mcp.js +6 -1
  112. package/dist/lib/mcp/unified-registry.d.ts +54 -5
  113. package/dist/lib/mcp/unified-registry.js +139 -6
  114. package/dist/lib/neurolink.d.ts +101 -0
  115. package/dist/lib/neurolink.js +147 -1
  116. package/dist/lib/providers/agent-enhanced-provider.d.ts +11 -2
  117. package/dist/lib/providers/agent-enhanced-provider.js +86 -15
  118. package/dist/lib/providers/amazonBedrock.d.ts +9 -1
  119. package/dist/lib/providers/amazonBedrock.js +26 -2
  120. package/dist/lib/providers/analytics-helper.d.ts +53 -0
  121. package/dist/lib/providers/analytics-helper.js +151 -0
  122. package/dist/lib/providers/anthropic.d.ts +11 -1
  123. package/dist/lib/providers/anthropic.js +29 -4
  124. package/dist/lib/providers/azureOpenAI.d.ts +3 -1
  125. package/dist/lib/providers/azureOpenAI.js +28 -4
  126. package/dist/lib/providers/function-calling-provider.d.ts +9 -1
  127. package/dist/lib/providers/function-calling-provider.js +14 -1
  128. package/dist/lib/providers/googleAIStudio.d.ts +15 -1
  129. package/dist/lib/providers/googleAIStudio.js +32 -2
  130. package/dist/lib/providers/googleVertexAI.d.ts +9 -1
  131. package/dist/lib/providers/googleVertexAI.js +31 -2
  132. package/dist/lib/providers/huggingFace.d.ts +3 -1
  133. package/dist/lib/providers/huggingFace.js +26 -3
  134. package/dist/lib/providers/mcp-provider.d.ts +9 -1
  135. package/dist/lib/providers/mcp-provider.js +12 -0
  136. package/dist/lib/providers/mistralAI.d.ts +3 -1
  137. package/dist/lib/providers/mistralAI.js +25 -2
  138. package/dist/lib/providers/ollama.d.ts +3 -1
  139. package/dist/lib/providers/ollama.js +27 -4
  140. package/dist/lib/providers/openAI.d.ts +15 -1
  141. package/dist/lib/providers/openAI.js +32 -2
  142. package/dist/lib/proxy/proxy-fetch.js +8 -7
  143. package/dist/lib/services/streaming/streaming-manager.d.ts +29 -0
  144. package/dist/lib/services/streaming/streaming-manager.js +244 -0
  145. package/dist/lib/services/types.d.ts +155 -0
  146. package/dist/lib/services/types.js +2 -0
  147. package/dist/lib/services/websocket/websocket-server.d.ts +34 -0
  148. package/dist/lib/services/websocket/websocket-server.js +304 -0
  149. package/dist/lib/telemetry/index.d.ts +15 -0
  150. package/dist/lib/telemetry/index.js +22 -0
  151. package/dist/lib/telemetry/telemetry-service.d.ts +47 -0
  152. package/dist/lib/telemetry/telemetry-service.js +259 -0
  153. package/dist/lib/utils/streaming-utils.d.ts +67 -0
  154. package/dist/lib/utils/streaming-utils.js +201 -0
  155. package/dist/mcp/contracts/mcpContract.d.ts +118 -0
  156. package/dist/mcp/contracts/mcpContract.js +5 -0
  157. package/dist/mcp/dynamic-chain-executor.d.ts +201 -0
  158. package/dist/mcp/dynamic-chain-executor.js +489 -0
  159. package/dist/mcp/dynamic-orchestrator.d.ts +109 -0
  160. package/dist/mcp/dynamic-orchestrator.js +351 -0
  161. package/dist/mcp/error-manager.d.ts +254 -0
  162. package/dist/mcp/error-manager.js +501 -0
  163. package/dist/mcp/error-recovery.d.ts +158 -0
  164. package/dist/mcp/error-recovery.js +405 -0
  165. package/dist/mcp/function-calling.js +11 -3
  166. package/dist/mcp/health-monitor.d.ts +256 -0
  167. package/dist/mcp/health-monitor.js +621 -0
  168. package/dist/mcp/logging.js +5 -0
  169. package/dist/mcp/neurolink-mcp-client.js +2 -1
  170. package/dist/mcp/orchestrator.d.ts +136 -5
  171. package/dist/mcp/orchestrator.js +332 -16
  172. package/dist/mcp/plugins/core/neurolink-mcp.json +15 -15
  173. package/dist/mcp/registry.d.ts +71 -16
  174. package/dist/mcp/registry.js +104 -6
  175. package/dist/mcp/semaphore-manager.d.ts +137 -0
  176. package/dist/mcp/semaphore-manager.js +329 -0
  177. package/dist/mcp/servers/ai-providers/ai-workflow-tools.d.ts +2 -2
  178. package/dist/mcp/servers/ai-providers/ai-workflow-tools.js +5 -4
  179. package/dist/mcp/session-manager.d.ts +186 -0
  180. package/dist/mcp/session-manager.js +400 -0
  181. package/dist/mcp/session-persistence.d.ts +93 -0
  182. package/dist/mcp/session-persistence.js +299 -0
  183. package/dist/mcp/tool-integration.js +1 -1
  184. package/dist/mcp/tool-registry.d.ts +55 -34
  185. package/dist/mcp/tool-registry.js +111 -97
  186. package/dist/mcp/transport-manager.d.ts +153 -0
  187. package/dist/mcp/transport-manager.js +331 -0
  188. package/dist/mcp/unified-mcp.js +6 -1
  189. package/dist/mcp/unified-registry.d.ts +54 -5
  190. package/dist/mcp/unified-registry.js +139 -6
  191. package/dist/neurolink.d.ts +101 -0
  192. package/dist/neurolink.js +147 -1
  193. package/dist/providers/agent-enhanced-provider.d.ts +11 -2
  194. package/dist/providers/agent-enhanced-provider.js +86 -15
  195. package/dist/providers/amazonBedrock.d.ts +9 -1
  196. package/dist/providers/amazonBedrock.js +26 -2
  197. package/dist/providers/analytics-helper.d.ts +53 -0
  198. package/dist/providers/analytics-helper.js +151 -0
  199. package/dist/providers/anthropic.d.ts +11 -1
  200. package/dist/providers/anthropic.js +29 -4
  201. package/dist/providers/azureOpenAI.d.ts +3 -1
  202. package/dist/providers/azureOpenAI.js +29 -4
  203. package/dist/providers/function-calling-provider.d.ts +9 -1
  204. package/dist/providers/function-calling-provider.js +14 -1
  205. package/dist/providers/googleAIStudio.d.ts +15 -1
  206. package/dist/providers/googleAIStudio.js +32 -2
  207. package/dist/providers/googleVertexAI.d.ts +9 -1
  208. package/dist/providers/googleVertexAI.js +31 -2
  209. package/dist/providers/huggingFace.d.ts +3 -1
  210. package/dist/providers/huggingFace.js +26 -3
  211. package/dist/providers/mcp-provider.d.ts +9 -1
  212. package/dist/providers/mcp-provider.js +12 -0
  213. package/dist/providers/mistralAI.d.ts +3 -1
  214. package/dist/providers/mistralAI.js +25 -2
  215. package/dist/providers/ollama.d.ts +3 -1
  216. package/dist/providers/ollama.js +27 -4
  217. package/dist/providers/openAI.d.ts +15 -1
  218. package/dist/providers/openAI.js +33 -2
  219. package/dist/proxy/proxy-fetch.js +8 -7
  220. package/dist/services/streaming/streaming-manager.d.ts +29 -0
  221. package/dist/services/streaming/streaming-manager.js +244 -0
  222. package/dist/services/types.d.ts +155 -0
  223. package/dist/services/types.js +2 -0
  224. package/dist/services/websocket/websocket-server.d.ts +34 -0
  225. package/dist/services/websocket/websocket-server.js +304 -0
  226. package/dist/telemetry/index.d.ts +15 -0
  227. package/dist/telemetry/index.js +22 -0
  228. package/dist/telemetry/telemetry-service.d.ts +47 -0
  229. package/dist/telemetry/telemetry-service.js +261 -0
  230. package/dist/utils/streaming-utils.d.ts +67 -0
  231. package/dist/utils/streaming-utils.js +201 -0
  232. package/package.json +245 -228
@@ -0,0 +1,298 @@
1
+ /**
2
+ * Phase 3: SSE Chat Utilities
3
+ * Client-side utilities for SSE chat integration
4
+ */
5
+ /**
6
+ * Client for SSE chat communication
7
+ */
8
+ export class ChatClient {
9
+ eventSource;
10
+ options;
11
+ messages = [];
12
+ reconnectCount = 0;
13
+ isConnected = false;
14
+ isReconnecting = false;
15
+ reconnectTimeout;
16
+ constructor(options) {
17
+ this.options = {
18
+ ...options,
19
+ onMessage: options.onMessage || (() => { }),
20
+ onError: options.onError || (() => { }),
21
+ onConnect: options.onConnect || (() => { }),
22
+ onDisconnect: options.onDisconnect || (() => { }),
23
+ reconnectAttempts: options.reconnectAttempts ?? 5,
24
+ reconnectDelay: options.reconnectDelay ?? 1000,
25
+ };
26
+ }
27
+ /**
28
+ * Connect to SSE endpoint
29
+ */
30
+ connect() {
31
+ if (this.eventSource) {
32
+ this.disconnect();
33
+ }
34
+ const url = new URL("/chat/stream", this.options.endpoint);
35
+ url.searchParams.set("sessionId", this.options.sessionId);
36
+ this.eventSource = new EventSource(url.toString());
37
+ this.eventSource.onopen = () => {
38
+ this.isConnected = true;
39
+ this.isReconnecting = false;
40
+ this.reconnectCount = 0;
41
+ this.options.onConnect();
42
+ };
43
+ this.eventSource.onmessage = (event) => {
44
+ try {
45
+ const sseEvent = JSON.parse(event.data);
46
+ this.handleSSEEvent(sseEvent);
47
+ }
48
+ catch (error) {
49
+ console.error("Failed to parse SSE event:", error);
50
+ }
51
+ };
52
+ this.eventSource.onerror = (error) => {
53
+ this.isConnected = false;
54
+ this.options.onDisconnect();
55
+ if (this.reconnectCount < this.options.reconnectAttempts) {
56
+ this.isReconnecting = true;
57
+ this.scheduleReconnect();
58
+ }
59
+ else {
60
+ this.isReconnecting = false;
61
+ this.options.onError(new Error("Max reconnection attempts reached"));
62
+ }
63
+ };
64
+ // Handle specific event types
65
+ this.eventSource.addEventListener("data", (event) => {
66
+ this.handleDataEvent(JSON.parse(event.data));
67
+ });
68
+ this.eventSource.addEventListener("errMsg", (event) => {
69
+ this.handleErrorEvent(JSON.parse(event.data));
70
+ });
71
+ this.eventSource.addEventListener("complete", (event) => {
72
+ this.handleCompleteEvent(JSON.parse(event.data));
73
+ });
74
+ }
75
+ /**
76
+ * Send message to chat
77
+ */
78
+ async sendMessage(content) {
79
+ if (!this.isConnected) {
80
+ throw new Error("Not connected to chat server");
81
+ }
82
+ try {
83
+ const response = await fetch(`${this.options.endpoint}/chat/send`, {
84
+ method: "POST",
85
+ headers: {
86
+ "Content-Type": "application/json",
87
+ },
88
+ body: JSON.stringify({
89
+ sessionId: this.options.sessionId,
90
+ message: content,
91
+ }),
92
+ });
93
+ if (!response.ok) {
94
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
95
+ }
96
+ }
97
+ catch (error) {
98
+ this.options.onError(error);
99
+ throw error;
100
+ }
101
+ }
102
+ /**
103
+ * Disconnect from SSE endpoint
104
+ */
105
+ disconnect() {
106
+ if (this.eventSource) {
107
+ this.eventSource.close();
108
+ this.eventSource = undefined;
109
+ }
110
+ if (this.reconnectTimeout) {
111
+ clearTimeout(this.reconnectTimeout);
112
+ this.reconnectTimeout = undefined;
113
+ }
114
+ this.isConnected = false;
115
+ this.isReconnecting = false;
116
+ this.options.onDisconnect();
117
+ }
118
+ /**
119
+ * Get message history
120
+ */
121
+ getMessages() {
122
+ return [...this.messages];
123
+ }
124
+ /**
125
+ * Clear message history
126
+ */
127
+ clearMessages() {
128
+ this.messages = [];
129
+ }
130
+ /**
131
+ * Check connection status
132
+ */
133
+ getConnectionStatus() {
134
+ return {
135
+ connected: this.isConnected,
136
+ reconnecting: this.isReconnecting,
137
+ reconnectCount: this.reconnectCount,
138
+ };
139
+ }
140
+ handleSSEEvent(event) {
141
+ switch (event.type) {
142
+ case "data":
143
+ this.handleDataEvent(event.data);
144
+ break;
145
+ case "error":
146
+ this.handleErrorEvent(event.data);
147
+ break;
148
+ case "complete":
149
+ this.handleCompleteEvent(event.data);
150
+ break;
151
+ case "heartbeat":
152
+ // Heartbeat received, connection is alive
153
+ break;
154
+ }
155
+ }
156
+ handleDataEvent(data) {
157
+ if (data.type === "chunk") {
158
+ // Handle streaming response chunk
159
+ const lastMessage = this.messages[this.messages.length - 1];
160
+ if (lastMessage && lastMessage.role === "assistant") {
161
+ // Append to existing assistant message
162
+ lastMessage.content += data.content;
163
+ this.options.onMessage(lastMessage);
164
+ }
165
+ else {
166
+ // Create new assistant message
167
+ const message = {
168
+ id: `msg_${Date.now()}_assistant`,
169
+ role: "assistant",
170
+ content: data.content,
171
+ timestamp: Date.now(),
172
+ };
173
+ this.messages.push(message);
174
+ this.options.onMessage(message);
175
+ }
176
+ }
177
+ else if (data.type === "start") {
178
+ // New conversation started
179
+ const userMessage = {
180
+ id: data.messageId,
181
+ role: "user",
182
+ content: data.content || "", // Use data content if available
183
+ timestamp: Date.now(),
184
+ };
185
+ this.messages.push(userMessage);
186
+ }
187
+ }
188
+ handleErrorEvent(data) {
189
+ this.options.onError(new Error(data.message || "Chat error"));
190
+ }
191
+ handleCompleteEvent(data) {
192
+ // Message completion - final processing
193
+ if (data.totalTokens) {
194
+ const lastMessage = this.messages[this.messages.length - 1];
195
+ if (lastMessage) {
196
+ // Initialize metadata if it doesn't exist
197
+ if (!lastMessage.metadata) {
198
+ lastMessage.metadata = {};
199
+ }
200
+ lastMessage.metadata.tokens = data.totalTokens;
201
+ }
202
+ }
203
+ }
204
+ scheduleReconnect() {
205
+ const delay = this.options.reconnectDelay * Math.pow(2, this.reconnectCount);
206
+ this.reconnectTimeout = setTimeout(() => {
207
+ this.reconnectCount++;
208
+ this.reconnectTimeout = undefined;
209
+ this.connect();
210
+ }, delay);
211
+ }
212
+ }
213
+ /**
214
+ * Create chat client instance
215
+ */
216
+ export function createChatClient(options) {
217
+ return new ChatClient(options);
218
+ }
219
+ /**
220
+ * React-style hook for chat streaming (can be adapted for other frameworks)
221
+ */
222
+ export function useChatStream(options) {
223
+ // This would typically use React hooks or similar framework state management
224
+ // For now, providing a basic implementation that can be extended
225
+ const client = new ChatClient(options);
226
+ // Connect on creation
227
+ client.connect();
228
+ return {
229
+ get messages() {
230
+ return client.getMessages();
231
+ },
232
+ get isConnected() {
233
+ return client.getConnectionStatus().connected;
234
+ },
235
+ get isReconnecting() {
236
+ return client.getConnectionStatus().reconnecting;
237
+ },
238
+ sendMessage: async (content) => {
239
+ await client.sendMessage(content);
240
+ },
241
+ disconnect: () => {
242
+ client.disconnect();
243
+ },
244
+ reconnect: () => {
245
+ client.connect();
246
+ },
247
+ clearHistory: () => {
248
+ client.clearMessages();
249
+ },
250
+ };
251
+ }
252
+ /**
253
+ * Utility for creating SSE EventSource with automatic reconnection
254
+ */
255
+ export function createSSEConnection(url, options = {}) {
256
+ let eventSource = null;
257
+ let reconnectCount = 0;
258
+ let isConnected = false;
259
+ const maxAttempts = options.maxReconnectAttempts ?? 5;
260
+ const connect = () => {
261
+ if (eventSource) {
262
+ eventSource.close();
263
+ }
264
+ eventSource = new EventSource(url);
265
+ eventSource.onopen = () => {
266
+ isConnected = true;
267
+ reconnectCount = 0;
268
+ options.onOpen?.();
269
+ };
270
+ eventSource.onmessage = (event) => {
271
+ options.onMessage?.(event);
272
+ };
273
+ eventSource.onerror = () => {
274
+ isConnected = false;
275
+ if (options.reconnect && reconnectCount < maxAttempts) {
276
+ setTimeout(() => {
277
+ reconnectCount++;
278
+ connect();
279
+ }, 1000 * Math.pow(2, reconnectCount));
280
+ }
281
+ else {
282
+ options.onError?.(new Error("SSE connection failed"));
283
+ }
284
+ };
285
+ };
286
+ const disconnect = () => {
287
+ if (eventSource) {
288
+ eventSource.close();
289
+ eventSource = null;
290
+ }
291
+ isConnected = false;
292
+ };
293
+ return {
294
+ connect,
295
+ disconnect,
296
+ isConnected: () => isConnected,
297
+ };
298
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Phase 3: SSE Chat Utilities
3
+ * Main chat module exports
4
+ */
5
+ import { SSEChatHandler } from "./sse-handler.js";
6
+ export { SSEChatHandler } from "./sse-handler.js";
7
+ export { ChatSession } from "./session.js";
8
+ export { MemorySessionStorage, FileSessionStorage, RedisSessionStorage, SessionStorageFactory, } from "./session-storage.js";
9
+ export { createChatClient, useChatStream } from "./client-utils.js";
10
+ export type { ChatMessage, ChatRequest, SSEOptions, SessionOptions, SSEEvent, ChatSessionState, StreamingChatResponse, SessionStorage, ContextManager, } from "./types.js";
11
+ /**
12
+ * Quick setup helper for SSE chat
13
+ */
14
+ export declare function createSSEChat(provider: any, options?: any): Promise<SSEChatHandler>;
15
+ /**
16
+ * Quick setup helper for chat session
17
+ */
18
+ export declare function createChatSession(sessionId: string, options?: any): Promise<import("./session.js").ChatSession>;
19
+ /**
20
+ * Enhanced factory function for real-time chat
21
+ */
22
+ export declare function createEnhancedChatService(options: {
23
+ provider: any;
24
+ enableSSE?: boolean;
25
+ enableWebSocket?: boolean;
26
+ streamingConfig?: any;
27
+ }): Promise<SSEChatHandler>;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Phase 3: SSE Chat Utilities
3
+ * Main chat module exports
4
+ */
5
+ import { SSEChatHandler } from "./sse-handler.js";
6
+ export { SSEChatHandler } from "./sse-handler.js";
7
+ export { ChatSession } from "./session.js";
8
+ export { MemorySessionStorage, FileSessionStorage, RedisSessionStorage, SessionStorageFactory, } from "./session-storage.js";
9
+ export { createChatClient, useChatStream } from "./client-utils.js";
10
+ /**
11
+ * Quick setup helper for SSE chat
12
+ */
13
+ export async function createSSEChat(provider, options) {
14
+ const { SSEChatHandler } = await import("./sse-handler.js");
15
+ return new SSEChatHandler(provider, options);
16
+ }
17
+ /**
18
+ * Quick setup helper for chat session
19
+ */
20
+ export async function createChatSession(sessionId, options) {
21
+ const { ChatSession } = await import("./session.js");
22
+ return new ChatSession(sessionId, options);
23
+ }
24
+ // Real-time Services (Phase 4) - Temporarily disabled for testing
25
+ // export { WebSocketChatHandler } from './websocket-chat-handler.js';
26
+ // export { NeuroLinkWebSocketServer } from '../services/websocket/websocket-server.js';
27
+ // export { StreamingManager } from '../services/streaming/streaming-manager.js';
28
+ // export * from '../services/types.js';
29
+ /**
30
+ * Enhanced factory function for real-time chat
31
+ */
32
+ export async function createEnhancedChatService(options) {
33
+ if (options.enableWebSocket) {
34
+ const { WebSocketChatHandler } = await import("./websocket-chat-handler.js");
35
+ return new WebSocketChatHandler(options.provider, {
36
+ sseOptions: options.enableSSE ? {} : undefined,
37
+ wsOptions: options.streamingConfig,
38
+ });
39
+ }
40
+ return new SSEChatHandler(options.provider);
41
+ }
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Phase 3: SSE Chat Utilities
3
+ * Session storage adapters for persistence
4
+ */
5
+ import type { SessionStorage, ChatSessionState } from "./types.js";
6
+ /**
7
+ * In-memory session storage (default)
8
+ */
9
+ export declare class MemorySessionStorage implements SessionStorage {
10
+ private sessions;
11
+ get(sessionId: string): Promise<ChatSessionState | null>;
12
+ set(sessionId: string, state: ChatSessionState): Promise<void>;
13
+ delete(sessionId: string): Promise<void>;
14
+ list(): Promise<string[]>;
15
+ cleanup(maxAge: number): Promise<number>;
16
+ /**
17
+ * Get storage statistics
18
+ */
19
+ getStats(): {
20
+ totalSessions: number;
21
+ memoryUsageBytes: number;
22
+ oldestSession?: number;
23
+ newestSession?: number;
24
+ };
25
+ /**
26
+ * Clear all sessions
27
+ */
28
+ clear(): Promise<void>;
29
+ }
30
+ /**
31
+ * File-based session storage
32
+ */
33
+ export declare class FileSessionStorage implements SessionStorage {
34
+ private basePath;
35
+ private constructor();
36
+ static create(basePath?: string): Promise<FileSessionStorage>;
37
+ get(sessionId: string): Promise<ChatSessionState | null>;
38
+ set(sessionId: string, state: ChatSessionState): Promise<void>;
39
+ delete(sessionId: string): Promise<void>;
40
+ list(): Promise<string[]>;
41
+ cleanup(maxAge: number): Promise<number>;
42
+ private getFilePath;
43
+ private ensureDirectory;
44
+ }
45
+ /**
46
+ * Redis session storage (for production scaling)
47
+ */
48
+ interface RedisClient {
49
+ get(key: string): Promise<string | null>;
50
+ set(key: string, value: string, options?: any): Promise<any>;
51
+ del(key: string): Promise<number>;
52
+ exists(key: string): Promise<number>;
53
+ expire?(key: string, ttl: number): Promise<any>;
54
+ keys?(pattern: string): Promise<string[]>;
55
+ }
56
+ export declare class RedisSessionStorage implements SessionStorage {
57
+ private client;
58
+ private keyPrefix;
59
+ constructor(redisClient: RedisClient, keyPrefix?: string);
60
+ get(sessionId: string): Promise<ChatSessionState | null>;
61
+ set(sessionId: string, state: ChatSessionState): Promise<void>;
62
+ delete(sessionId: string): Promise<void>;
63
+ list(): Promise<string[]>;
64
+ cleanup(maxAge: number): Promise<number>;
65
+ private getKey;
66
+ }
67
+ /**
68
+ * Session storage factory
69
+ */
70
+ export declare class SessionStorageFactory {
71
+ static create(type: "memory" | "file" | "redis", options?: {
72
+ basePath?: string;
73
+ redisClient?: RedisClient;
74
+ keyPrefix?: string;
75
+ }): Promise<SessionStorage>;
76
+ }
77
+ export {};
@@ -0,0 +1,233 @@
1
+ /**
2
+ * Phase 3: SSE Chat Utilities
3
+ * Session storage adapters for persistence
4
+ */
5
+ import { promises as fs } from "fs";
6
+ /**
7
+ * In-memory session storage (default)
8
+ */
9
+ export class MemorySessionStorage {
10
+ sessions = new Map();
11
+ async get(sessionId) {
12
+ return this.sessions.get(sessionId) || null;
13
+ }
14
+ async set(sessionId, state) {
15
+ this.sessions.set(sessionId, state);
16
+ }
17
+ async delete(sessionId) {
18
+ this.sessions.delete(sessionId);
19
+ }
20
+ async list() {
21
+ return Array.from(this.sessions.keys());
22
+ }
23
+ async cleanup(maxAge) {
24
+ const now = Date.now();
25
+ let removed = 0;
26
+ for (const [sessionId, state] of this.sessions.entries()) {
27
+ if (now - state.lastActivity > maxAge) {
28
+ this.sessions.delete(sessionId);
29
+ removed++;
30
+ }
31
+ }
32
+ return removed;
33
+ }
34
+ /**
35
+ * Get storage statistics
36
+ */
37
+ getStats() {
38
+ const sessions = Array.from(this.sessions.values());
39
+ const memoryUsageBytes = Buffer.byteLength(JSON.stringify(sessions), "utf8");
40
+ const timestamps = sessions.map((s) => s.lastActivity);
41
+ return {
42
+ totalSessions: this.sessions.size,
43
+ memoryUsageBytes,
44
+ oldestSession: timestamps.length > 0 ? Math.min(...timestamps) : undefined,
45
+ newestSession: timestamps.length > 0 ? Math.max(...timestamps) : undefined,
46
+ };
47
+ }
48
+ /**
49
+ * Clear all sessions
50
+ */
51
+ async clear() {
52
+ this.sessions.clear();
53
+ }
54
+ }
55
+ /**
56
+ * File-based session storage
57
+ */
58
+ export class FileSessionStorage {
59
+ basePath;
60
+ constructor(basePath) {
61
+ this.basePath = basePath;
62
+ }
63
+ static async create(basePath = "./sessions") {
64
+ const instance = new FileSessionStorage(basePath);
65
+ await instance.ensureDirectory();
66
+ return instance;
67
+ }
68
+ async get(sessionId) {
69
+ try {
70
+ const filePath = this.getFilePath(sessionId);
71
+ const data = await fs.readFile(filePath, "utf-8");
72
+ return JSON.parse(data);
73
+ }
74
+ catch (error) {
75
+ if (error?.code === "ENOENT") {
76
+ return null; // File doesn't exist
77
+ }
78
+ throw error;
79
+ }
80
+ }
81
+ async set(sessionId, state) {
82
+ const filePath = this.getFilePath(sessionId);
83
+ const data = JSON.stringify({
84
+ ...state,
85
+ lastActivity: state.lastActivity ?? Date.now(),
86
+ }, null, 2);
87
+ await fs.writeFile(filePath, data, "utf-8");
88
+ }
89
+ async delete(sessionId) {
90
+ try {
91
+ const filePath = this.getFilePath(sessionId);
92
+ await fs.unlink(filePath);
93
+ }
94
+ catch (error) {
95
+ if (error?.code !== "ENOENT") {
96
+ throw error;
97
+ }
98
+ }
99
+ }
100
+ async list() {
101
+ try {
102
+ const files = await fs.readdir(this.basePath);
103
+ return files
104
+ .filter((file) => file.endsWith(".json"))
105
+ .map((file) => file.replace(".json", ""));
106
+ }
107
+ catch (error) {
108
+ return [];
109
+ }
110
+ }
111
+ async cleanup(maxAge) {
112
+ const sessionIds = await this.list();
113
+ const now = Date.now();
114
+ let removed = 0;
115
+ for (const sessionId of sessionIds) {
116
+ const state = await this.get(sessionId);
117
+ if (state && now - state.lastActivity > maxAge) {
118
+ await this.delete(sessionId);
119
+ removed++;
120
+ }
121
+ }
122
+ return removed;
123
+ }
124
+ getFilePath(sessionId) {
125
+ return `${this.basePath}/${sessionId}.json`;
126
+ }
127
+ async ensureDirectory() {
128
+ try {
129
+ await fs.mkdir(this.basePath, { recursive: true });
130
+ }
131
+ catch (error) {
132
+ if (error?.code !== "EEXIST") {
133
+ throw error; // Rethrow unexpected errors
134
+ }
135
+ // Directory already exists, which is fine
136
+ }
137
+ }
138
+ }
139
+ export class RedisSessionStorage {
140
+ client;
141
+ keyPrefix;
142
+ constructor(redisClient, keyPrefix = "neurolink:session:") {
143
+ this.client = redisClient;
144
+ this.keyPrefix = keyPrefix;
145
+ }
146
+ async get(sessionId) {
147
+ try {
148
+ const data = await this.client.get(this.getKey(sessionId));
149
+ return data ? JSON.parse(data) : null;
150
+ }
151
+ catch (error) {
152
+ console.error("Redis get error:", error);
153
+ return null;
154
+ }
155
+ }
156
+ async set(sessionId, state) {
157
+ try {
158
+ const key = this.getKey(sessionId);
159
+ const data = JSON.stringify({
160
+ ...state,
161
+ lastActivity: Date.now(),
162
+ });
163
+ await this.client.set(key, data);
164
+ // Set TTL if supported
165
+ if (this.client.expire) {
166
+ await this.client.expire(key, 3600); // 1 hour default
167
+ }
168
+ }
169
+ catch (error) {
170
+ console.error("Redis set error:", error);
171
+ throw error;
172
+ }
173
+ }
174
+ async delete(sessionId) {
175
+ try {
176
+ await this.client.del(this.getKey(sessionId));
177
+ }
178
+ catch (error) {
179
+ console.error("Redis delete error:", error);
180
+ throw error;
181
+ }
182
+ }
183
+ async list() {
184
+ try {
185
+ if (!this.client.keys) {
186
+ console.warn("Redis client does not support keys operation");
187
+ return [];
188
+ }
189
+ const keys = await this.client.keys(`${this.keyPrefix}*`);
190
+ return keys.map((key) => key.replace(this.keyPrefix, ""));
191
+ }
192
+ catch (error) {
193
+ console.error("Redis list error:", error);
194
+ return [];
195
+ }
196
+ }
197
+ async cleanup(maxAge) {
198
+ const sessionIds = await this.list();
199
+ const now = Date.now();
200
+ let removed = 0;
201
+ for (const sessionId of sessionIds) {
202
+ const state = await this.get(sessionId);
203
+ if (state && now - state.lastActivity > maxAge) {
204
+ await this.delete(sessionId);
205
+ removed++;
206
+ }
207
+ }
208
+ return removed;
209
+ }
210
+ getKey(sessionId) {
211
+ return `${this.keyPrefix}${sessionId}`;
212
+ }
213
+ }
214
+ /**
215
+ * Session storage factory
216
+ */
217
+ export class SessionStorageFactory {
218
+ static async create(type, options) {
219
+ switch (type) {
220
+ case "memory":
221
+ return new MemorySessionStorage();
222
+ case "file":
223
+ return await FileSessionStorage.create(options?.basePath);
224
+ case "redis":
225
+ if (!options?.redisClient) {
226
+ throw new Error("Redis client required for Redis storage");
227
+ }
228
+ return new RedisSessionStorage(options.redisClient, options.keyPrefix);
229
+ default:
230
+ throw new Error(`Unknown storage type: ${type}`);
231
+ }
232
+ }
233
+ }