@cilow/sdk 0.2.1 → 0.3.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 (84) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +109 -492
  3. package/dist/abstain.d.ts +43 -0
  4. package/dist/abstain.d.ts.map +1 -0
  5. package/dist/abstain.js +42 -0
  6. package/dist/abstain.js.map +1 -0
  7. package/dist/adapters/anthropic.d.ts +57 -0
  8. package/dist/adapters/anthropic.d.ts.map +1 -0
  9. package/dist/adapters/anthropic.js +57 -0
  10. package/dist/adapters/anthropic.js.map +1 -0
  11. package/dist/adapters/index.d.ts +16 -0
  12. package/dist/adapters/index.d.ts.map +1 -0
  13. package/dist/adapters/index.js +16 -0
  14. package/dist/adapters/index.js.map +1 -0
  15. package/dist/adapters/langchain.d.ts +62 -0
  16. package/dist/adapters/langchain.d.ts.map +1 -0
  17. package/dist/adapters/langchain.js +68 -0
  18. package/dist/adapters/langchain.js.map +1 -0
  19. package/dist/adapters/memory.d.ts +105 -0
  20. package/dist/adapters/memory.d.ts.map +1 -0
  21. package/dist/adapters/memory.js +105 -0
  22. package/dist/adapters/memory.js.map +1 -0
  23. package/dist/adapters/openai.d.ts +56 -0
  24. package/dist/adapters/openai.d.ts.map +1 -0
  25. package/dist/adapters/openai.js +64 -0
  26. package/dist/adapters/openai.js.map +1 -0
  27. package/dist/adapters/remaining.d.ts +52 -0
  28. package/dist/adapters/remaining.d.ts.map +1 -0
  29. package/dist/adapters/remaining.js +67 -0
  30. package/dist/adapters/remaining.js.map +1 -0
  31. package/dist/client.d.ts +512 -173
  32. package/dist/client.d.ts.map +1 -0
  33. package/dist/client.js +648 -504
  34. package/dist/client.js.map +1 -1
  35. package/dist/errors.d.ts +25 -0
  36. package/dist/errors.d.ts.map +1 -0
  37. package/dist/errors.js +28 -0
  38. package/dist/errors.js.map +1 -0
  39. package/dist/hash.d.ts +13 -0
  40. package/dist/hash.d.ts.map +1 -0
  41. package/dist/hash.js +92 -0
  42. package/dist/hash.js.map +1 -0
  43. package/dist/index.d.ts +18 -109
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +16 -876
  46. package/dist/index.js.map +1 -1
  47. package/dist/types.d.ts +809 -486
  48. package/dist/types.d.ts.map +1 -0
  49. package/dist/types.js +18 -17
  50. package/dist/types.js.map +1 -1
  51. package/package.json +30 -103
  52. package/dist/client.d.mts +0 -224
  53. package/dist/client.mjs +0 -505
  54. package/dist/client.mjs.map +0 -1
  55. package/dist/index.d.mts +0 -111
  56. package/dist/index.mjs +0 -863
  57. package/dist/index.mjs.map +0 -1
  58. package/dist/providers/langchain.js +0 -821
  59. package/dist/providers/langchain.js.map +0 -1
  60. package/dist/providers/langchain.mjs +0 -816
  61. package/dist/providers/langchain.mjs.map +0 -1
  62. package/dist/providers/openai.js +0 -737
  63. package/dist/providers/openai.js.map +0 -1
  64. package/dist/providers/openai.mjs +0 -732
  65. package/dist/providers/openai.mjs.map +0 -1
  66. package/dist/providers/vercel.js +0 -866
  67. package/dist/providers/vercel.js.map +0 -1
  68. package/dist/providers/vercel.mjs +0 -860
  69. package/dist/providers/vercel.mjs.map +0 -1
  70. package/dist/react/hooks.d.mts +0 -327
  71. package/dist/react/hooks.d.ts +0 -327
  72. package/dist/react/hooks.js +0 -1183
  73. package/dist/react/hooks.js.map +0 -1
  74. package/dist/react/hooks.mjs +0 -1172
  75. package/dist/react/hooks.mjs.map +0 -1
  76. package/dist/types.d.mts +0 -494
  77. package/dist/types.mjs +0 -14
  78. package/dist/types.mjs.map +0 -1
  79. package/dist/websocket.d.mts +0 -160
  80. package/dist/websocket.d.ts +0 -160
  81. package/dist/websocket.js +0 -342
  82. package/dist/websocket.js.map +0 -1
  83. package/dist/websocket.mjs +0 -339
  84. package/dist/websocket.mjs.map +0 -1
@@ -1,160 +0,0 @@
1
- import { CilowConfig, WebSocketConfig, CilowEvent, MemoryCreatedEvent, MemoryUpdatedEvent, MemoryDeletedEvent, MemoryTierChangedEvent, GraphNodeCreatedEvent, GraphEdgeCreatedEvent, ConnectionStatusEvent } from './types.js';
2
-
3
- /**
4
- * Cilow WebSocket Client
5
- *
6
- * Real-time connection for memory updates, graph changes, and event streaming.
7
- */
8
-
9
- /**
10
- * WebSocket connection states
11
- */
12
- type ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'reconnecting';
13
- /**
14
- * Event listener type
15
- */
16
- type EventListener<T extends CilowEvent = CilowEvent> = (event: T) => void;
17
- /**
18
- * Subscription filter options
19
- */
20
- interface SubscriptionFilter {
21
- /** Filter by user ID */
22
- userId?: string;
23
- /** Filter by session ID */
24
- sessionId?: string;
25
- /** Filter by tags */
26
- tags?: string[];
27
- /** Filter by event types */
28
- eventTypes?: string[];
29
- }
30
- /**
31
- * CilowWebSocket - Real-time WebSocket client for Cilow
32
- *
33
- * @example
34
- * ```typescript
35
- * const ws = new CilowWebSocket({
36
- * apiUrl: 'https://api.cilow.ai',
37
- * apiKey: 'your-key'
38
- * });
39
- *
40
- * // Subscribe to memory events
41
- * ws.on('memory.created', (event) => {
42
- * console.log('New memory:', event.memory);
43
- * });
44
- *
45
- * // Connect
46
- * await ws.connect();
47
- *
48
- * // Subscribe to specific user's events
49
- * ws.subscribe({ userId: 'user-123' });
50
- * ```
51
- */
52
- declare class CilowWebSocket {
53
- private ws;
54
- private readonly wsUrl;
55
- private readonly apiKey;
56
- private readonly reconnectAttempts;
57
- private readonly reconnectDelay;
58
- private readonly heartbeatInterval;
59
- private readonly messageQueueSize;
60
- private state;
61
- private reconnectCount;
62
- private heartbeatTimer;
63
- private reconnectTimer;
64
- private messageQueue;
65
- private subscriptions;
66
- private listeners;
67
- private allListeners;
68
- constructor(config: CilowConfig & WebSocketConfig);
69
- /**
70
- * Get current connection state
71
- */
72
- get connectionState(): ConnectionState;
73
- /**
74
- * Check if connected
75
- */
76
- get isConnected(): boolean;
77
- /**
78
- * Connect to the WebSocket server
79
- */
80
- connect(): Promise<void>;
81
- /**
82
- * Disconnect from the WebSocket server
83
- */
84
- disconnect(): void;
85
- /**
86
- * Subscribe to events with optional filter
87
- */
88
- subscribe(filter?: SubscriptionFilter): void;
89
- /**
90
- * Unsubscribe from events
91
- */
92
- unsubscribe(filter?: SubscriptionFilter): void;
93
- /**
94
- * Add event listener for specific event type
95
- */
96
- on<T extends CilowEvent>(eventType: T['type'], listener: EventListener<T>): () => void;
97
- /**
98
- * Add listener for all events
99
- */
100
- onAny(listener: EventListener): () => void;
101
- /**
102
- * Remove event listener
103
- */
104
- off<T extends CilowEvent>(eventType: T['type'], listener: EventListener<T>): void;
105
- /**
106
- * Remove all listeners for an event type
107
- */
108
- offAll(eventType?: string): void;
109
- /**
110
- * Listen for memory created events
111
- */
112
- onMemoryCreated(listener: EventListener<MemoryCreatedEvent>): () => void;
113
- /**
114
- * Listen for memory updated events
115
- */
116
- onMemoryUpdated(listener: EventListener<MemoryUpdatedEvent>): () => void;
117
- /**
118
- * Listen for memory deleted events
119
- */
120
- onMemoryDeleted(listener: EventListener<MemoryDeletedEvent>): () => void;
121
- /**
122
- * Listen for memory tier changed events
123
- */
124
- onMemoryTierChanged(listener: EventListener<MemoryTierChangedEvent>): () => void;
125
- /**
126
- * Listen for graph node created events
127
- */
128
- onGraphNodeCreated(listener: EventListener<GraphNodeCreatedEvent>): () => void;
129
- /**
130
- * Listen for graph edge created events
131
- */
132
- onGraphEdgeCreated(listener: EventListener<GraphEdgeCreatedEvent>): () => void;
133
- /**
134
- * Listen for connection status changes
135
- */
136
- onConnectionStatus(listener: EventListener<ConnectionStatusEvent>): () => void;
137
- /**
138
- * Wait for specific event (one-time)
139
- */
140
- once<T extends CilowEvent>(eventType: T['type'], timeout?: number): Promise<T>;
141
- private send;
142
- private sendSubscription;
143
- private resubscribe;
144
- private flushMessageQueue;
145
- private handleMessage;
146
- private handleClose;
147
- private handleError;
148
- private scheduleReconnect;
149
- private clearReconnectTimer;
150
- private startHeartbeat;
151
- private stopHeartbeat;
152
- private emit;
153
- private emitStatusEvent;
154
- }
155
- /**
156
- * Create a WebSocket client instance (convenience function)
157
- */
158
- declare function createWebSocket(config: CilowConfig & WebSocketConfig): CilowWebSocket;
159
-
160
- export { CilowWebSocket, type ConnectionState, type EventListener, type SubscriptionFilter, createWebSocket };
package/dist/websocket.js DELETED
@@ -1,342 +0,0 @@
1
- 'use strict';
2
-
3
- // src/websocket.ts
4
- var CilowWebSocket = class {
5
- constructor(config) {
6
- this.ws = null;
7
- this.state = "disconnected";
8
- this.reconnectCount = 0;
9
- this.heartbeatTimer = null;
10
- this.reconnectTimer = null;
11
- this.messageQueue = [];
12
- this.subscriptions = [];
13
- this.listeners = /* @__PURE__ */ new Map();
14
- this.allListeners = /* @__PURE__ */ new Set();
15
- const httpUrl = config.apiUrl.replace(/\/$/, "");
16
- this.wsUrl = config.wsUrl ?? httpUrl.replace(/^http/, "ws") + "/ws";
17
- this.apiKey = config.apiKey;
18
- this.reconnectAttempts = config.reconnectAttempts ?? 5;
19
- this.reconnectDelay = config.reconnectDelay ?? 1e3;
20
- this.heartbeatInterval = config.heartbeatInterval ?? 3e4;
21
- this.messageQueueSize = config.messageQueueSize ?? 100;
22
- }
23
- /**
24
- * Get current connection state
25
- */
26
- get connectionState() {
27
- return this.state;
28
- }
29
- /**
30
- * Check if connected
31
- */
32
- get isConnected() {
33
- return this.state === "connected";
34
- }
35
- /**
36
- * Connect to the WebSocket server
37
- */
38
- async connect() {
39
- if (this.state === "connected" || this.state === "connecting") {
40
- return;
41
- }
42
- this.state = "connecting";
43
- this.emitStatusEvent("connecting");
44
- return new Promise((resolve, reject) => {
45
- try {
46
- const url = new URL(this.wsUrl);
47
- url.searchParams.set("token", this.apiKey);
48
- this.ws = new WebSocket(url.toString());
49
- this.ws.onopen = () => {
50
- this.state = "connected";
51
- this.reconnectCount = 0;
52
- this.emitStatusEvent("connected");
53
- this.startHeartbeat();
54
- this.flushMessageQueue();
55
- this.resubscribe();
56
- resolve();
57
- };
58
- this.ws.onclose = (event) => {
59
- this.handleClose(event);
60
- };
61
- this.ws.onerror = (error) => {
62
- if (this.state === "connecting") {
63
- reject(new Error("WebSocket connection failed"));
64
- }
65
- this.handleError(error);
66
- };
67
- this.ws.onmessage = (event) => {
68
- this.handleMessage(event);
69
- };
70
- } catch (error) {
71
- this.state = "disconnected";
72
- reject(error);
73
- }
74
- });
75
- }
76
- /**
77
- * Disconnect from the WebSocket server
78
- */
79
- disconnect() {
80
- this.stopHeartbeat();
81
- this.clearReconnectTimer();
82
- if (this.ws) {
83
- this.ws.onclose = null;
84
- this.ws.close(1e3, "Client disconnect");
85
- this.ws = null;
86
- }
87
- this.state = "disconnected";
88
- this.emitStatusEvent("disconnected", "Client initiated disconnect");
89
- }
90
- /**
91
- * Subscribe to events with optional filter
92
- */
93
- subscribe(filter) {
94
- if (filter) {
95
- this.subscriptions.push(filter);
96
- }
97
- if (this.isConnected) {
98
- this.sendSubscription(filter);
99
- }
100
- }
101
- /**
102
- * Unsubscribe from events
103
- */
104
- unsubscribe(filter) {
105
- if (filter) {
106
- this.subscriptions = this.subscriptions.filter(
107
- (s) => s.userId !== filter.userId || s.sessionId !== filter.sessionId || JSON.stringify(s.tags) !== JSON.stringify(filter.tags)
108
- );
109
- } else {
110
- this.subscriptions = [];
111
- }
112
- if (this.isConnected) {
113
- this.send({
114
- type: "unsubscribe",
115
- filter
116
- });
117
- }
118
- }
119
- /**
120
- * Add event listener for specific event type
121
- */
122
- on(eventType, listener) {
123
- if (!this.listeners.has(eventType)) {
124
- this.listeners.set(eventType, /* @__PURE__ */ new Set());
125
- }
126
- this.listeners.get(eventType).add(listener);
127
- return () => {
128
- this.listeners.get(eventType)?.delete(listener);
129
- };
130
- }
131
- /**
132
- * Add listener for all events
133
- */
134
- onAny(listener) {
135
- this.allListeners.add(listener);
136
- return () => {
137
- this.allListeners.delete(listener);
138
- };
139
- }
140
- /**
141
- * Remove event listener
142
- */
143
- off(eventType, listener) {
144
- this.listeners.get(eventType)?.delete(listener);
145
- }
146
- /**
147
- * Remove all listeners for an event type
148
- */
149
- offAll(eventType) {
150
- if (eventType) {
151
- this.listeners.delete(eventType);
152
- } else {
153
- this.listeners.clear();
154
- this.allListeners.clear();
155
- }
156
- }
157
- /**
158
- * Listen for memory created events
159
- */
160
- onMemoryCreated(listener) {
161
- return this.on("memory.created", listener);
162
- }
163
- /**
164
- * Listen for memory updated events
165
- */
166
- onMemoryUpdated(listener) {
167
- return this.on("memory.updated", listener);
168
- }
169
- /**
170
- * Listen for memory deleted events
171
- */
172
- onMemoryDeleted(listener) {
173
- return this.on("memory.deleted", listener);
174
- }
175
- /**
176
- * Listen for memory tier changed events
177
- */
178
- onMemoryTierChanged(listener) {
179
- return this.on("memory.tier_changed", listener);
180
- }
181
- /**
182
- * Listen for graph node created events
183
- */
184
- onGraphNodeCreated(listener) {
185
- return this.on("graph.node_created", listener);
186
- }
187
- /**
188
- * Listen for graph edge created events
189
- */
190
- onGraphEdgeCreated(listener) {
191
- return this.on("graph.edge_created", listener);
192
- }
193
- /**
194
- * Listen for connection status changes
195
- */
196
- onConnectionStatus(listener) {
197
- return this.on("connection.status", listener);
198
- }
199
- /**
200
- * Wait for specific event (one-time)
201
- */
202
- once(eventType, timeout) {
203
- return new Promise((resolve, reject) => {
204
- const timeoutId = timeout ? setTimeout(() => {
205
- unsubscribe();
206
- reject(new Error(`Timeout waiting for event: ${eventType}`));
207
- }, timeout) : null;
208
- const unsubscribe = this.on(eventType, (event) => {
209
- if (timeoutId) clearTimeout(timeoutId);
210
- unsubscribe();
211
- resolve(event);
212
- });
213
- });
214
- }
215
- // ===========================================================================
216
- // Private Methods
217
- // ===========================================================================
218
- send(message) {
219
- const data = JSON.stringify(message);
220
- if (this.isConnected && this.ws) {
221
- this.ws.send(data);
222
- } else {
223
- if (this.messageQueue.length >= this.messageQueueSize) {
224
- this.messageQueue.shift();
225
- }
226
- this.messageQueue.push(data);
227
- }
228
- }
229
- sendSubscription(filter) {
230
- this.send({
231
- type: "subscribe",
232
- filter: filter ?? {}
233
- });
234
- }
235
- resubscribe() {
236
- for (const filter of this.subscriptions) {
237
- this.sendSubscription(filter);
238
- }
239
- }
240
- flushMessageQueue() {
241
- while (this.messageQueue.length > 0 && this.isConnected && this.ws) {
242
- const message = this.messageQueue.shift();
243
- if (message) {
244
- this.ws.send(message);
245
- }
246
- }
247
- }
248
- handleMessage(event) {
249
- try {
250
- const data = JSON.parse(event.data);
251
- this.emit(data);
252
- } catch (error) {
253
- console.error("Failed to parse WebSocket message:", error);
254
- }
255
- }
256
- handleClose(event) {
257
- this.stopHeartbeat();
258
- if (event.code === 1e3) {
259
- this.state = "disconnected";
260
- this.emitStatusEvent("disconnected", "Connection closed normally");
261
- return;
262
- }
263
- if (this.reconnectCount < this.reconnectAttempts) {
264
- this.state = "reconnecting";
265
- this.emitStatusEvent("reconnecting", `Reconnecting (attempt ${this.reconnectCount + 1}/${this.reconnectAttempts})`);
266
- this.scheduleReconnect();
267
- } else {
268
- this.state = "disconnected";
269
- this.emitStatusEvent("disconnected", "Max reconnection attempts reached");
270
- }
271
- }
272
- handleError(_error) {
273
- console.error("WebSocket error occurred");
274
- }
275
- scheduleReconnect() {
276
- this.clearReconnectTimer();
277
- const delay = this.reconnectDelay * Math.pow(2, this.reconnectCount);
278
- this.reconnectCount++;
279
- this.reconnectTimer = setTimeout(async () => {
280
- try {
281
- await this.connect();
282
- } catch {
283
- }
284
- }, delay);
285
- }
286
- clearReconnectTimer() {
287
- if (this.reconnectTimer) {
288
- clearTimeout(this.reconnectTimer);
289
- this.reconnectTimer = null;
290
- }
291
- }
292
- startHeartbeat() {
293
- this.stopHeartbeat();
294
- this.heartbeatTimer = setInterval(() => {
295
- if (this.isConnected) {
296
- this.send({ type: "ping" });
297
- }
298
- }, this.heartbeatInterval);
299
- }
300
- stopHeartbeat() {
301
- if (this.heartbeatTimer) {
302
- clearInterval(this.heartbeatTimer);
303
- this.heartbeatTimer = null;
304
- }
305
- }
306
- emit(event) {
307
- const typeListeners = this.listeners.get(event.type);
308
- if (typeListeners) {
309
- for (const listener of typeListeners) {
310
- try {
311
- listener(event);
312
- } catch (error) {
313
- console.error("Error in event listener:", error);
314
- }
315
- }
316
- }
317
- for (const listener of this.allListeners) {
318
- try {
319
- listener(event);
320
- } catch (error) {
321
- console.error("Error in event listener:", error);
322
- }
323
- }
324
- }
325
- emitStatusEvent(status, reason) {
326
- const event = {
327
- type: "connection.status",
328
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
329
- status: status === "connecting" ? "reconnecting" : status,
330
- reason
331
- };
332
- this.emit(event);
333
- }
334
- };
335
- function createWebSocket(config) {
336
- return new CilowWebSocket(config);
337
- }
338
-
339
- exports.CilowWebSocket = CilowWebSocket;
340
- exports.createWebSocket = createWebSocket;
341
- //# sourceMappingURL=websocket.js.map
342
- //# sourceMappingURL=websocket.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/websocket.ts"],"names":[],"mappings":";;;AAiEO,IAAM,iBAAN,MAAqB;AAAA,EAmB1B,YAAY,MAAA,EAAuC;AAlBnD,IAAA,IAAA,CAAQ,EAAA,GAAuB,IAAA;AAQ/B,IAAA,IAAA,CAAQ,KAAA,GAAyB,cAAA;AACjC,IAAA,IAAA,CAAQ,cAAA,GAAiB,CAAA;AACzB,IAAA,IAAA,CAAQ,cAAA,GAAwD,IAAA;AAChE,IAAA,IAAA,CAAQ,cAAA,GAAuD,IAAA;AAC/D,IAAA,IAAA,CAAQ,eAAyB,EAAC;AAClC,IAAA,IAAA,CAAQ,gBAAsC,EAAC;AAE/C,IAAA,IAAA,CAAQ,SAAA,uBAAiD,GAAA,EAAI;AAC7D,IAAA,IAAA,CAAQ,YAAA,uBAAuC,GAAA,EAAI;AAIjD,IAAA,MAAM,OAAA,GAAU,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,OAAO,EAAE,CAAA;AAC/C,IAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,KAAA,IAAS,QAAQ,OAAA,CAAQ,OAAA,EAAS,IAAI,CAAA,GAAI,KAAA;AAC9D,IAAA,IAAA,CAAK,SAAS,MAAA,CAAO,MAAA;AAErB,IAAA,IAAA,CAAK,iBAAA,GAAoB,OAAO,iBAAA,IAAqB,CAAA;AACrD,IAAA,IAAA,CAAK,cAAA,GAAiB,OAAO,cAAA,IAAkB,GAAA;AAC/C,IAAA,IAAA,CAAK,iBAAA,GAAoB,OAAO,iBAAA,IAAqB,GAAA;AACrD,IAAA,IAAA,CAAK,gBAAA,GAAmB,OAAO,gBAAA,IAAoB,GAAA;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,eAAA,GAAmC;AACrC,IAAA,OAAO,IAAA,CAAK,KAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,WAAA,GAAuB;AACzB,IAAA,OAAO,KAAK,KAAA,KAAU,WAAA;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAA,GAAyB;AAC7B,IAAA,IAAI,IAAA,CAAK,KAAA,KAAU,WAAA,IAAe,IAAA,CAAK,UAAU,YAAA,EAAc;AAC7D,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,KAAA,GAAQ,YAAA;AACb,IAAA,IAAA,CAAK,gBAAgB,YAAY,CAAA;AAEjC,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,MAAA,IAAI;AAEF,QAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,IAAA,CAAK,KAAK,CAAA;AAC9B,QAAA,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,OAAA,EAAS,IAAA,CAAK,MAAM,CAAA;AAEzC,QAAA,IAAA,CAAK,EAAA,GAAK,IAAI,SAAA,CAAU,GAAA,CAAI,UAAU,CAAA;AAEtC,QAAA,IAAA,CAAK,EAAA,CAAG,SAAS,MAAM;AACrB,UAAA,IAAA,CAAK,KAAA,GAAQ,WAAA;AACb,UAAA,IAAA,CAAK,cAAA,GAAiB,CAAA;AACtB,UAAA,IAAA,CAAK,gBAAgB,WAAW,CAAA;AAChC,UAAA,IAAA,CAAK,cAAA,EAAe;AACpB,UAAA,IAAA,CAAK,iBAAA,EAAkB;AACvB,UAAA,IAAA,CAAK,WAAA,EAAY;AACjB,UAAA,OAAA,EAAQ;AAAA,QACV,CAAA;AAEA,QAAA,IAAA,CAAK,EAAA,CAAG,OAAA,GAAU,CAAC,KAAA,KAAU;AAC3B,UAAA,IAAA,CAAK,YAAY,KAAK,CAAA;AAAA,QACxB,CAAA;AAEA,QAAA,IAAA,CAAK,EAAA,CAAG,OAAA,GAAU,CAAC,KAAA,KAAU;AAC3B,UAAA,IAAI,IAAA,CAAK,UAAU,YAAA,EAAc;AAC/B,YAAA,MAAA,CAAO,IAAI,KAAA,CAAM,6BAA6B,CAAC,CAAA;AAAA,UACjD;AACA,UAAA,IAAA,CAAK,YAAY,KAAK,CAAA;AAAA,QACxB,CAAA;AAEA,QAAA,IAAA,CAAK,EAAA,CAAG,SAAA,GAAY,CAAC,KAAA,KAAU;AAC7B,UAAA,IAAA,CAAK,cAAc,KAAK,CAAA;AAAA,QAC1B,CAAA;AAAA,MACF,SAAS,KAAA,EAAO;AACd,QAAA,IAAA,CAAK,KAAA,GAAQ,cAAA;AACb,QAAA,MAAA,CAAO,KAAK,CAAA;AAAA,MACd;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,UAAA,GAAmB;AACjB,IAAA,IAAA,CAAK,aAAA,EAAc;AACnB,IAAA,IAAA,CAAK,mBAAA,EAAoB;AAEzB,IAAA,IAAI,KAAK,EAAA,EAAI;AACX,MAAA,IAAA,CAAK,GAAG,OAAA,GAAU,IAAA;AAClB,MAAA,IAAA,CAAK,EAAA,CAAG,KAAA,CAAM,GAAA,EAAM,mBAAmB,CAAA;AACvC,MAAA,IAAA,CAAK,EAAA,GAAK,IAAA;AAAA,IACZ;AAEA,IAAA,IAAA,CAAK,KAAA,GAAQ,cAAA;AACb,IAAA,IAAA,CAAK,eAAA,CAAgB,gBAAgB,6BAA6B,CAAA;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,MAAA,EAAmC;AAC3C,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,IAAA,CAAK,aAAA,CAAc,KAAK,MAAM,CAAA;AAAA,IAChC;AAEA,IAAA,IAAI,KAAK,WAAA,EAAa;AACpB,MAAA,IAAA,CAAK,iBAAiB,MAAM,CAAA;AAAA,IAC9B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,MAAA,EAAmC;AAC7C,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,IAAA,CAAK,aAAA,GAAgB,KAAK,aAAA,CAAc,MAAA;AAAA,QACtC,CAAC,CAAA,KACC,CAAA,CAAE,WAAW,MAAA,CAAO,MAAA,IACpB,EAAE,SAAA,KAAc,MAAA,CAAO,SAAA,IACvB,IAAA,CAAK,UAAU,CAAA,CAAE,IAAI,MAAM,IAAA,CAAK,SAAA,CAAU,OAAO,IAAI;AAAA,OACzD;AAAA,IACF,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,gBAAgB,EAAC;AAAA,IACxB;AAEA,IAAA,IAAI,KAAK,WAAA,EAAa;AACpB,MAAA,IAAA,CAAK,IAAA,CAAK;AAAA,QACR,IAAA,EAAM,aAAA;AAAA,QACN;AAAA,OACD,CAAA;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,EAAA,CAAyB,WAAsB,QAAA,EAAwC;AACrF,IAAA,IAAI,CAAC,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,SAAS,CAAA,EAAG;AAClC,MAAA,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,SAAA,kBAAW,IAAI,KAAK,CAAA;AAAA,IACzC;AACA,IAAA,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,SAAS,CAAA,CAAG,IAAI,QAAyB,CAAA;AAG5D,IAAA,OAAO,MAAM;AACX,MAAA,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,SAAS,CAAA,EAAG,OAAO,QAAyB,CAAA;AAAA,IACjE,CAAA;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAA,EAAqC;AACzC,IAAA,IAAA,CAAK,YAAA,CAAa,IAAI,QAAQ,CAAA;AAC9B,IAAA,OAAO,MAAM;AACX,MAAA,IAAA,CAAK,YAAA,CAAa,OAAO,QAAQ,CAAA;AAAA,IACnC,CAAA;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,GAAA,CAA0B,WAAsB,QAAA,EAAkC;AAChF,IAAA,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,SAAS,CAAA,EAAG,OAAO,QAAyB,CAAA;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,SAAA,EAA0B;AAC/B,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,IAAA,CAAK,SAAA,CAAU,OAAO,SAAS,CAAA;AAAA,IACjC,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,UAAU,KAAA,EAAM;AACrB,MAAA,IAAA,CAAK,aAAa,KAAA,EAAM;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,QAAA,EAAyD;AACvE,IAAA,OAAO,IAAA,CAAK,EAAA,CAAG,gBAAA,EAAkB,QAAQ,CAAA;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,QAAA,EAAyD;AACvE,IAAA,OAAO,IAAA,CAAK,EAAA,CAAG,gBAAA,EAAkB,QAAQ,CAAA;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,QAAA,EAAyD;AACvE,IAAA,OAAO,IAAA,CAAK,EAAA,CAAG,gBAAA,EAAkB,QAAQ,CAAA;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,oBAAoB,QAAA,EAA6D;AAC/E,IAAA,OAAO,IAAA,CAAK,EAAA,CAAG,qBAAA,EAAuB,QAAQ,CAAA;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAmB,QAAA,EAA4D;AAC7E,IAAA,OAAO,IAAA,CAAK,EAAA,CAAG,oBAAA,EAAsB,QAAQ,CAAA;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAmB,QAAA,EAA4D;AAC7E,IAAA,OAAO,IAAA,CAAK,EAAA,CAAG,oBAAA,EAAsB,QAAQ,CAAA;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAmB,QAAA,EAA4D;AAC7E,IAAA,OAAO,IAAA,CAAK,EAAA,CAAG,mBAAA,EAAqB,QAAQ,CAAA;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA,EAKA,IAAA,CAA2B,WAAsB,OAAA,EAA8B;AAC7E,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,MAAA,MAAM,SAAA,GAAY,OAAA,GACd,UAAA,CAAW,MAAM;AACf,QAAA,WAAA,EAAY;AACZ,QAAA,MAAA,CAAO,IAAI,KAAA,CAAM,CAAA,2BAAA,EAA8B,SAAS,EAAE,CAAC,CAAA;AAAA,MAC7D,CAAA,EAAG,OAAO,CAAA,GACV,IAAA;AAEJ,MAAA,MAAM,WAAA,GAAc,IAAA,CAAK,EAAA,CAAG,SAAA,EAAW,CAAC,KAAA,KAAU;AAChD,QAAA,IAAI,SAAA,eAAwB,SAAS,CAAA;AACrC,QAAA,WAAA,EAAY;AACZ,QAAA,OAAA,CAAQ,KAAU,CAAA;AAAA,MACpB,CAAC,CAAA;AAAA,IACH,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAMQ,KAAK,OAAA,EAAwC;AACnD,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,OAAO,CAAA;AAEnC,IAAA,IAAI,IAAA,CAAK,WAAA,IAAe,IAAA,CAAK,EAAA,EAAI;AAC/B,MAAA,IAAA,CAAK,EAAA,CAAG,KAAK,IAAI,CAAA;AAAA,IACnB,CAAA,MAAO;AAEL,MAAA,IAAI,IAAA,CAAK,YAAA,CAAa,MAAA,IAAU,IAAA,CAAK,gBAAA,EAAkB;AACrD,QAAA,IAAA,CAAK,aAAa,KAAA,EAAM;AAAA,MAC1B;AACA,MAAA,IAAA,CAAK,YAAA,CAAa,KAAK,IAAI,CAAA;AAAA,IAC7B;AAAA,EACF;AAAA,EAEQ,iBAAiB,MAAA,EAAmC;AAC1D,IAAA,IAAA,CAAK,IAAA,CAAK;AAAA,MACR,IAAA,EAAM,WAAA;AAAA,MACN,MAAA,EAAQ,UAAU;AAAC,KACpB,CAAA;AAAA,EACH;AAAA,EAEQ,WAAA,GAAoB;AAC1B,IAAA,KAAA,MAAW,MAAA,IAAU,KAAK,aAAA,EAAe;AACvC,MAAA,IAAA,CAAK,iBAAiB,MAAM,CAAA;AAAA,IAC9B;AAAA,EACF;AAAA,EAEQ,iBAAA,GAA0B;AAChC,IAAA,OAAO,KAAK,YAAA,CAAa,MAAA,GAAS,KAAK,IAAA,CAAK,WAAA,IAAe,KAAK,EAAA,EAAI;AAClE,MAAA,MAAM,OAAA,GAAU,IAAA,CAAK,YAAA,CAAa,KAAA,EAAM;AACxC,MAAA,IAAI,OAAA,EAAS;AACX,QAAA,IAAA,CAAK,EAAA,CAAG,KAAK,OAAO,CAAA;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,cAAc,KAAA,EAA2B;AAC/C,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,IAAI,CAAA;AAClC,MAAA,IAAA,CAAK,KAAK,IAAI,CAAA;AAAA,IAChB,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,KAAA,CAAM,sCAAsC,KAAK,CAAA;AAAA,IAC3D;AAAA,EACF;AAAA,EAEQ,YAAY,KAAA,EAAyB;AAC3C,IAAA,IAAA,CAAK,aAAA,EAAc;AAEnB,IAAA,IAAI,KAAA,CAAM,SAAS,GAAA,EAAM;AAEvB,MAAA,IAAA,CAAK,KAAA,GAAQ,cAAA;AACb,MAAA,IAAA,CAAK,eAAA,CAAgB,gBAAgB,4BAA4B,CAAA;AACjE,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,IAAA,CAAK,cAAA,GAAiB,IAAA,CAAK,iBAAA,EAAmB;AAChD,MAAA,IAAA,CAAK,KAAA,GAAQ,cAAA;AACb,MAAA,IAAA,CAAK,eAAA,CAAgB,gBAAgB,CAAA,sBAAA,EAAyB,IAAA,CAAK,iBAAiB,CAAC,CAAA,CAAA,EAAI,IAAA,CAAK,iBAAiB,CAAA,CAAA,CAAG,CAAA;AAClH,MAAA,IAAA,CAAK,iBAAA,EAAkB;AAAA,IACzB,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,KAAA,GAAQ,cAAA;AACb,MAAA,IAAA,CAAK,eAAA,CAAgB,gBAAgB,mCAAmC,CAAA;AAAA,IAC1E;AAAA,EACF;AAAA,EAEQ,YAAY,MAAA,EAAqB;AAGvC,IAAA,OAAA,CAAQ,MAAM,0BAA0B,CAAA;AAAA,EAC1C;AAAA,EAEQ,iBAAA,GAA0B;AAChC,IAAA,IAAA,CAAK,mBAAA,EAAoB;AAEzB,IAAA,MAAM,QAAQ,IAAA,CAAK,cAAA,GAAiB,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,cAAc,CAAA;AACnE,IAAA,IAAA,CAAK,cAAA,EAAA;AAEL,IAAA,IAAA,CAAK,cAAA,GAAiB,WAAW,YAAY;AAC3C,MAAA,IAAI;AACF,QAAA,MAAM,KAAK,OAAA,EAAQ;AAAA,MACrB,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF,GAAG,KAAK,CAAA;AAAA,EACV;AAAA,EAEQ,mBAAA,GAA4B;AAClC,IAAA,IAAI,KAAK,cAAA,EAAgB;AACvB,MAAA,YAAA,CAAa,KAAK,cAAc,CAAA;AAChC,MAAA,IAAA,CAAK,cAAA,GAAiB,IAAA;AAAA,IACxB;AAAA,EACF;AAAA,EAEQ,cAAA,GAAuB;AAC7B,IAAA,IAAA,CAAK,aAAA,EAAc;AACnB,IAAA,IAAA,CAAK,cAAA,GAAiB,YAAY,MAAM;AACtC,MAAA,IAAI,KAAK,WAAA,EAAa;AACpB,QAAA,IAAA,CAAK,IAAA,CAAK,EAAE,IAAA,EAAM,MAAA,EAAQ,CAAA;AAAA,MAC5B;AAAA,IACF,CAAA,EAAG,KAAK,iBAAiB,CAAA;AAAA,EAC3B;AAAA,EAEQ,aAAA,GAAsB;AAC5B,IAAA,IAAI,KAAK,cAAA,EAAgB;AACvB,MAAA,aAAA,CAAc,KAAK,cAAc,CAAA;AACjC,MAAA,IAAA,CAAK,cAAA,GAAiB,IAAA;AAAA,IACxB;AAAA,EACF;AAAA,EAEQ,KAAK,KAAA,EAAyB;AAEpC,IAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,MAAM,IAAI,CAAA;AACnD,IAAA,IAAI,aAAA,EAAe;AACjB,MAAA,KAAA,MAAW,YAAY,aAAA,EAAe;AACpC,QAAA,IAAI;AACF,UAAA,QAAA,CAAS,KAAK,CAAA;AAAA,QAChB,SAAS,KAAA,EAAO;AACd,UAAA,OAAA,CAAQ,KAAA,CAAM,4BAA4B,KAAK,CAAA;AAAA,QACjD;AAAA,MACF;AAAA,IACF;AAGA,IAAA,KAAA,MAAW,QAAA,IAAY,KAAK,YAAA,EAAc;AACxC,MAAA,IAAI;AACF,QAAA,QAAA,CAAS,KAAK,CAAA;AAAA,MAChB,SAAS,KAAA,EAAO;AACd,QAAA,OAAA,CAAQ,KAAA,CAAM,4BAA4B,KAAK,CAAA;AAAA,MACjD;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,eAAA,CAAgB,QAAsE,MAAA,EAAuB;AACnH,IAAA,MAAM,KAAA,GAA+B;AAAA,MACnC,IAAA,EAAM,mBAAA;AAAA,MACN,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,MAClC,MAAA,EAAQ,MAAA,KAAW,YAAA,GAAe,cAAA,GAAiB,MAAA;AAAA,MACnD;AAAA,KACF;AACA,IAAA,IAAA,CAAK,KAAK,KAAK,CAAA;AAAA,EACjB;AACF;AAKO,SAAS,gBAAgB,MAAA,EAAuD;AACrF,EAAA,OAAO,IAAI,eAAe,MAAM,CAAA;AAClC","file":"websocket.js","sourcesContent":["/**\n * Cilow WebSocket Client\n *\n * Real-time connection for memory updates, graph changes, and event streaming.\n */\n\nimport type {\n CilowConfig,\n WebSocketConfig,\n CilowEvent,\n MemoryCreatedEvent,\n MemoryUpdatedEvent,\n MemoryDeletedEvent,\n MemoryTierChangedEvent,\n GraphNodeCreatedEvent,\n GraphEdgeCreatedEvent,\n ConnectionStatusEvent,\n} from './types';\n\n/**\n * WebSocket connection states\n */\nexport type ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'reconnecting';\n\n/**\n * Event listener type\n */\nexport type EventListener<T extends CilowEvent = CilowEvent> = (event: T) => void;\n\n/**\n * Subscription filter options\n */\nexport interface SubscriptionFilter {\n /** Filter by user ID */\n userId?: string;\n /** Filter by session ID */\n sessionId?: string;\n /** Filter by tags */\n tags?: string[];\n /** Filter by event types */\n eventTypes?: string[];\n}\n\n/**\n * CilowWebSocket - Real-time WebSocket client for Cilow\n *\n * @example\n * ```typescript\n * const ws = new CilowWebSocket({\n * apiUrl: 'https://api.cilow.ai',\n * apiKey: 'your-key'\n * });\n *\n * // Subscribe to memory events\n * ws.on('memory.created', (event) => {\n * console.log('New memory:', event.memory);\n * });\n *\n * // Connect\n * await ws.connect();\n *\n * // Subscribe to specific user's events\n * ws.subscribe({ userId: 'user-123' });\n * ```\n */\nexport class CilowWebSocket {\n private ws: WebSocket | null = null;\n private readonly wsUrl: string;\n private readonly apiKey: string;\n private readonly reconnectAttempts: number;\n private readonly reconnectDelay: number;\n private readonly heartbeatInterval: number;\n private readonly messageQueueSize: number;\n\n private state: ConnectionState = 'disconnected';\n private reconnectCount = 0;\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private messageQueue: string[] = [];\n private subscriptions: SubscriptionFilter[] = [];\n\n private listeners: Map<string, Set<EventListener>> = new Map();\n private allListeners: Set<EventListener> = new Set();\n\n constructor(config: CilowConfig & WebSocketConfig) {\n // Convert HTTP URL to WebSocket URL\n const httpUrl = config.apiUrl.replace(/\\/$/, '');\n this.wsUrl = config.wsUrl ?? httpUrl.replace(/^http/, 'ws') + '/ws';\n this.apiKey = config.apiKey;\n\n this.reconnectAttempts = config.reconnectAttempts ?? 5;\n this.reconnectDelay = config.reconnectDelay ?? 1000;\n this.heartbeatInterval = config.heartbeatInterval ?? 30000;\n this.messageQueueSize = config.messageQueueSize ?? 100;\n }\n\n /**\n * Get current connection state\n */\n get connectionState(): ConnectionState {\n return this.state;\n }\n\n /**\n * Check if connected\n */\n get isConnected(): boolean {\n return this.state === 'connected';\n }\n\n /**\n * Connect to the WebSocket server\n */\n async connect(): Promise<void> {\n if (this.state === 'connected' || this.state === 'connecting') {\n return;\n }\n\n this.state = 'connecting';\n this.emitStatusEvent('connecting');\n\n return new Promise((resolve, reject) => {\n try {\n // Add authentication to URL\n const url = new URL(this.wsUrl);\n url.searchParams.set('token', this.apiKey);\n\n this.ws = new WebSocket(url.toString());\n\n this.ws.onopen = () => {\n this.state = 'connected';\n this.reconnectCount = 0;\n this.emitStatusEvent('connected');\n this.startHeartbeat();\n this.flushMessageQueue();\n this.resubscribe();\n resolve();\n };\n\n this.ws.onclose = (event) => {\n this.handleClose(event);\n };\n\n this.ws.onerror = (error) => {\n if (this.state === 'connecting') {\n reject(new Error('WebSocket connection failed'));\n }\n this.handleError(error);\n };\n\n this.ws.onmessage = (event) => {\n this.handleMessage(event);\n };\n } catch (error) {\n this.state = 'disconnected';\n reject(error);\n }\n });\n }\n\n /**\n * Disconnect from the WebSocket server\n */\n disconnect(): void {\n this.stopHeartbeat();\n this.clearReconnectTimer();\n\n if (this.ws) {\n this.ws.onclose = null; // Prevent reconnection\n this.ws.close(1000, 'Client disconnect');\n this.ws = null;\n }\n\n this.state = 'disconnected';\n this.emitStatusEvent('disconnected', 'Client initiated disconnect');\n }\n\n /**\n * Subscribe to events with optional filter\n */\n subscribe(filter?: SubscriptionFilter): void {\n if (filter) {\n this.subscriptions.push(filter);\n }\n\n if (this.isConnected) {\n this.sendSubscription(filter);\n }\n }\n\n /**\n * Unsubscribe from events\n */\n unsubscribe(filter?: SubscriptionFilter): void {\n if (filter) {\n this.subscriptions = this.subscriptions.filter(\n (s) =>\n s.userId !== filter.userId ||\n s.sessionId !== filter.sessionId ||\n JSON.stringify(s.tags) !== JSON.stringify(filter.tags)\n );\n } else {\n this.subscriptions = [];\n }\n\n if (this.isConnected) {\n this.send({\n type: 'unsubscribe',\n filter,\n });\n }\n }\n\n /**\n * Add event listener for specific event type\n */\n on<T extends CilowEvent>(eventType: T['type'], listener: EventListener<T>): () => void {\n if (!this.listeners.has(eventType)) {\n this.listeners.set(eventType, new Set());\n }\n this.listeners.get(eventType)!.add(listener as EventListener);\n\n // Return unsubscribe function\n return () => {\n this.listeners.get(eventType)?.delete(listener as EventListener);\n };\n }\n\n /**\n * Add listener for all events\n */\n onAny(listener: EventListener): () => void {\n this.allListeners.add(listener);\n return () => {\n this.allListeners.delete(listener);\n };\n }\n\n /**\n * Remove event listener\n */\n off<T extends CilowEvent>(eventType: T['type'], listener: EventListener<T>): void {\n this.listeners.get(eventType)?.delete(listener as EventListener);\n }\n\n /**\n * Remove all listeners for an event type\n */\n offAll(eventType?: string): void {\n if (eventType) {\n this.listeners.delete(eventType);\n } else {\n this.listeners.clear();\n this.allListeners.clear();\n }\n }\n\n /**\n * Listen for memory created events\n */\n onMemoryCreated(listener: EventListener<MemoryCreatedEvent>): () => void {\n return this.on('memory.created', listener);\n }\n\n /**\n * Listen for memory updated events\n */\n onMemoryUpdated(listener: EventListener<MemoryUpdatedEvent>): () => void {\n return this.on('memory.updated', listener);\n }\n\n /**\n * Listen for memory deleted events\n */\n onMemoryDeleted(listener: EventListener<MemoryDeletedEvent>): () => void {\n return this.on('memory.deleted', listener);\n }\n\n /**\n * Listen for memory tier changed events\n */\n onMemoryTierChanged(listener: EventListener<MemoryTierChangedEvent>): () => void {\n return this.on('memory.tier_changed', listener);\n }\n\n /**\n * Listen for graph node created events\n */\n onGraphNodeCreated(listener: EventListener<GraphNodeCreatedEvent>): () => void {\n return this.on('graph.node_created', listener);\n }\n\n /**\n * Listen for graph edge created events\n */\n onGraphEdgeCreated(listener: EventListener<GraphEdgeCreatedEvent>): () => void {\n return this.on('graph.edge_created', listener);\n }\n\n /**\n * Listen for connection status changes\n */\n onConnectionStatus(listener: EventListener<ConnectionStatusEvent>): () => void {\n return this.on('connection.status', listener);\n }\n\n /**\n * Wait for specific event (one-time)\n */\n once<T extends CilowEvent>(eventType: T['type'], timeout?: number): Promise<T> {\n return new Promise((resolve, reject) => {\n const timeoutId = timeout\n ? setTimeout(() => {\n unsubscribe();\n reject(new Error(`Timeout waiting for event: ${eventType}`));\n }, timeout)\n : null;\n\n const unsubscribe = this.on(eventType, (event) => {\n if (timeoutId) clearTimeout(timeoutId);\n unsubscribe();\n resolve(event as T);\n });\n });\n }\n\n // ===========================================================================\n // Private Methods\n // ===========================================================================\n\n private send(message: Record<string, unknown>): void {\n const data = JSON.stringify(message);\n\n if (this.isConnected && this.ws) {\n this.ws.send(data);\n } else {\n // Queue message for later\n if (this.messageQueue.length >= this.messageQueueSize) {\n this.messageQueue.shift(); // Remove oldest\n }\n this.messageQueue.push(data);\n }\n }\n\n private sendSubscription(filter?: SubscriptionFilter): void {\n this.send({\n type: 'subscribe',\n filter: filter ?? {},\n });\n }\n\n private resubscribe(): void {\n for (const filter of this.subscriptions) {\n this.sendSubscription(filter);\n }\n }\n\n private flushMessageQueue(): void {\n while (this.messageQueue.length > 0 && this.isConnected && this.ws) {\n const message = this.messageQueue.shift();\n if (message) {\n this.ws.send(message);\n }\n }\n }\n\n private handleMessage(event: MessageEvent): void {\n try {\n const data = JSON.parse(event.data) as CilowEvent;\n this.emit(data);\n } catch (error) {\n console.error('Failed to parse WebSocket message:', error);\n }\n }\n\n private handleClose(event: CloseEvent): void {\n this.stopHeartbeat();\n\n if (event.code === 1000) {\n // Normal close\n this.state = 'disconnected';\n this.emitStatusEvent('disconnected', 'Connection closed normally');\n return;\n }\n\n // Attempt reconnection\n if (this.reconnectCount < this.reconnectAttempts) {\n this.state = 'reconnecting';\n this.emitStatusEvent('reconnecting', `Reconnecting (attempt ${this.reconnectCount + 1}/${this.reconnectAttempts})`);\n this.scheduleReconnect();\n } else {\n this.state = 'disconnected';\n this.emitStatusEvent('disconnected', 'Max reconnection attempts reached');\n }\n }\n\n private handleError(_error: Event): void {\n // Errors are typically followed by close events\n // Just log for debugging\n console.error('WebSocket error occurred');\n }\n\n private scheduleReconnect(): void {\n this.clearReconnectTimer();\n\n const delay = this.reconnectDelay * Math.pow(2, this.reconnectCount);\n this.reconnectCount++;\n\n this.reconnectTimer = setTimeout(async () => {\n try {\n await this.connect();\n } catch {\n // Connection failed, will retry in handleClose\n }\n }, delay);\n }\n\n private clearReconnectTimer(): void {\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n }\n\n private startHeartbeat(): void {\n this.stopHeartbeat();\n this.heartbeatTimer = setInterval(() => {\n if (this.isConnected) {\n this.send({ type: 'ping' });\n }\n }, this.heartbeatInterval);\n }\n\n private stopHeartbeat(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n }\n\n private emit(event: CilowEvent): void {\n // Emit to type-specific listeners\n const typeListeners = this.listeners.get(event.type);\n if (typeListeners) {\n for (const listener of typeListeners) {\n try {\n listener(event);\n } catch (error) {\n console.error('Error in event listener:', error);\n }\n }\n }\n\n // Emit to all-event listeners\n for (const listener of this.allListeners) {\n try {\n listener(event);\n } catch (error) {\n console.error('Error in event listener:', error);\n }\n }\n }\n\n private emitStatusEvent(status: 'connected' | 'disconnected' | 'reconnecting' | 'connecting', reason?: string): void {\n const event: ConnectionStatusEvent = {\n type: 'connection.status',\n timestamp: new Date().toISOString(),\n status: status === 'connecting' ? 'reconnecting' : status,\n reason,\n };\n this.emit(event);\n }\n}\n\n/**\n * Create a WebSocket client instance (convenience function)\n */\nexport function createWebSocket(config: CilowConfig & WebSocketConfig): CilowWebSocket {\n return new CilowWebSocket(config);\n}\n"]}