@cilow/sdk 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +412 -199
- package/dist/client.d.mts +224 -0
- package/dist/client.d.ts +224 -0
- package/dist/client.js +509 -0
- package/dist/client.js.map +1 -0
- package/dist/client.mjs +505 -0
- package/dist/client.mjs.map +1 -0
- package/dist/index.d.mts +94 -390
- package/dist/index.d.ts +94 -390
- package/dist/index.js +745 -350
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +732 -318
- package/dist/index.mjs.map +1 -0
- package/dist/providers/langchain.js +821 -0
- package/dist/providers/langchain.js.map +1 -0
- package/dist/providers/langchain.mjs +816 -0
- package/dist/providers/langchain.mjs.map +1 -0
- package/dist/providers/openai.js +737 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/openai.mjs +732 -0
- package/dist/providers/openai.mjs.map +1 -0
- package/dist/providers/vercel.js +866 -0
- package/dist/providers/vercel.js.map +1 -0
- package/dist/providers/vercel.mjs +860 -0
- package/dist/providers/vercel.mjs.map +1 -0
- package/dist/react/hooks.d.mts +327 -0
- package/dist/react/hooks.d.ts +327 -0
- package/dist/react/hooks.js +1183 -0
- package/dist/react/hooks.js.map +1 -0
- package/dist/react/hooks.mjs +1172 -0
- package/dist/react/hooks.mjs.map +1 -0
- package/dist/types.d.mts +494 -0
- package/dist/types.d.ts +494 -0
- package/dist/types.js +18 -0
- package/dist/types.js.map +1 -0
- package/dist/types.mjs +14 -0
- package/dist/types.mjs.map +1 -0
- package/dist/websocket.d.mts +160 -0
- package/dist/websocket.d.ts +160 -0
- package/dist/websocket.js +342 -0
- package/dist/websocket.js.map +1 -0
- package/dist/websocket.mjs +339 -0
- package/dist/websocket.mjs.map +1 -0
- package/package.json +90 -31
- package/LICENSE +0 -21
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { CilowConfig, WebSocketConfig, CilowEvent, MemoryCreatedEvent, MemoryUpdatedEvent, MemoryDeletedEvent, MemoryTierChangedEvent, GraphNodeCreatedEvent, GraphEdgeCreatedEvent, ConnectionStatusEvent } from './types.mjs';
|
|
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 };
|
|
@@ -0,0 +1,160 @@
|
|
|
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 };
|
|
@@ -0,0 +1,342 @@
|
|
|
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
|