@agentxjs/network 1.8.1 → 1.9.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.
- package/README.md +294 -0
- package/dist/index.d.ts +95 -9
- package/dist/index.js +358 -213
- package/dist/index.js.map +10 -5
- package/package.json +6 -4
package/README.md
ADDED
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
# @agentxjs/network
|
|
2
|
+
|
|
3
|
+
WebSocket communication layer for AgentX with reliable message delivery.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Reliable Message Delivery** - ACK-based confirmation with timeout handling
|
|
8
|
+
- **Cross-Platform Client** - Node.js and Browser support with auto-reconnect
|
|
9
|
+
- **Heartbeat** - Connection health monitoring via ping/pong
|
|
10
|
+
- **Modular Design** - Separate protocol, server, and client modules
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
bun add @agentxjs/network
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
### Server
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import { WebSocketServer } from "@agentxjs/network";
|
|
24
|
+
|
|
25
|
+
const server = new WebSocketServer({
|
|
26
|
+
heartbeat: true,
|
|
27
|
+
heartbeatInterval: 30000,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
server.onConnection((connection) => {
|
|
31
|
+
console.log("Client connected:", connection.id);
|
|
32
|
+
|
|
33
|
+
connection.onMessage((message) => {
|
|
34
|
+
console.log("Received:", message);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// Send with delivery confirmation
|
|
38
|
+
connection.sendReliable(JSON.stringify({ type: "welcome" }), {
|
|
39
|
+
onAck: () => console.log("Client received the message"),
|
|
40
|
+
timeout: 5000,
|
|
41
|
+
onTimeout: () => console.log("Client did not acknowledge"),
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
await server.listen(5200);
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Client (Node.js)
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
import { createWebSocketClient } from "@agentxjs/network";
|
|
52
|
+
|
|
53
|
+
const client = await createWebSocketClient({
|
|
54
|
+
serverUrl: "ws://localhost:5200",
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
client.onMessage((message) => {
|
|
58
|
+
console.log("Received:", message);
|
|
59
|
+
// ACK is sent automatically for reliable messages
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
client.send(JSON.stringify({ type: "hello" }));
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Client (Browser)
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
import { createWebSocketClient } from "@agentxjs/network";
|
|
69
|
+
|
|
70
|
+
const client = await createWebSocketClient({
|
|
71
|
+
serverUrl: "ws://localhost:5200",
|
|
72
|
+
autoReconnect: true,
|
|
73
|
+
maxReconnectionDelay: 10000,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
client.onMessage((message) => {
|
|
77
|
+
console.log("Received:", message);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
client.onClose(() => {
|
|
81
|
+
console.log("Disconnected, will auto-reconnect...");
|
|
82
|
+
});
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## API Reference
|
|
86
|
+
|
|
87
|
+
### WebSocketServer
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
import { WebSocketServer } from "@agentxjs/network";
|
|
91
|
+
|
|
92
|
+
const server = new WebSocketServer(options?: ChannelServerOptions);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Options:**
|
|
96
|
+
|
|
97
|
+
| Option | Type | Default | Description |
|
|
98
|
+
| ------------------- | --------- | ------- | -------------------------- |
|
|
99
|
+
| `heartbeat` | `boolean` | `true` | Enable ping/pong heartbeat |
|
|
100
|
+
| `heartbeatInterval` | `number` | `30000` | Heartbeat interval in ms |
|
|
101
|
+
|
|
102
|
+
**Methods:**
|
|
103
|
+
|
|
104
|
+
| Method | Description |
|
|
105
|
+
| --------------------------- | ------------------------------ |
|
|
106
|
+
| `listen(port, host?)` | Start standalone server |
|
|
107
|
+
| `attach(httpServer, path?)` | Attach to existing HTTP server |
|
|
108
|
+
| `onConnection(handler)` | Register connection handler |
|
|
109
|
+
| `broadcast(message)` | Send to all connections |
|
|
110
|
+
| `close()` | Close all connections |
|
|
111
|
+
| `dispose()` | Release all resources |
|
|
112
|
+
|
|
113
|
+
### WebSocketConnection
|
|
114
|
+
|
|
115
|
+
Server-side representation of a client connection.
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
interface ChannelConnection {
|
|
119
|
+
readonly id: string;
|
|
120
|
+
|
|
121
|
+
// Basic send (fire-and-forget)
|
|
122
|
+
send(message: string): void;
|
|
123
|
+
|
|
124
|
+
// Reliable send with ACK
|
|
125
|
+
sendReliable(message: string, options?: SendReliableOptions): void;
|
|
126
|
+
|
|
127
|
+
// Event handlers
|
|
128
|
+
onMessage(handler: (message: string) => void): Unsubscribe;
|
|
129
|
+
onClose(handler: () => void): Unsubscribe;
|
|
130
|
+
onError(handler: (error: Error) => void): Unsubscribe;
|
|
131
|
+
|
|
132
|
+
close(): void;
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**SendReliableOptions:**
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
interface SendReliableOptions {
|
|
140
|
+
onAck?: () => void; // Called when client acknowledges
|
|
141
|
+
timeout?: number; // ACK timeout in ms (default: 5000)
|
|
142
|
+
onTimeout?: () => void; // Called if ACK times out
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### WebSocketClient
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
import { createWebSocketClient } from "@agentxjs/network";
|
|
150
|
+
|
|
151
|
+
const client = await createWebSocketClient(options: ChannelClientOptions);
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**Options:**
|
|
155
|
+
|
|
156
|
+
| Option | Type | Default | Description |
|
|
157
|
+
| ---------------------- | -------------------- | ---------------- | ----------------------------- |
|
|
158
|
+
| `serverUrl` | `string` | required | WebSocket server URL |
|
|
159
|
+
| `autoReconnect` | `boolean` | `true` (browser) | Auto-reconnect on disconnect |
|
|
160
|
+
| `minReconnectionDelay` | `number` | `1000` | Min delay between reconnects |
|
|
161
|
+
| `maxReconnectionDelay` | `number` | `10000` | Max delay between reconnects |
|
|
162
|
+
| `maxRetries` | `number` | `Infinity` | Max reconnection attempts |
|
|
163
|
+
| `connectionTimeout` | `number` | `4000` | Connection timeout in ms |
|
|
164
|
+
| `headers` | `object \| function` | - | Custom headers (Node.js only) |
|
|
165
|
+
|
|
166
|
+
**Methods:**
|
|
167
|
+
|
|
168
|
+
| Method | Description |
|
|
169
|
+
| -------------------- | ------------------------ |
|
|
170
|
+
| `send(message)` | Send message to server |
|
|
171
|
+
| `onMessage(handler)` | Handle incoming messages |
|
|
172
|
+
| `onOpen(handler)` | Handle connection open |
|
|
173
|
+
| `onClose(handler)` | Handle connection close |
|
|
174
|
+
| `onError(handler)` | Handle errors |
|
|
175
|
+
| `close()` | Close connection |
|
|
176
|
+
| `dispose()` | Release all resources |
|
|
177
|
+
|
|
178
|
+
## Reliable Message Protocol
|
|
179
|
+
|
|
180
|
+
The `sendReliable()` method provides guaranteed message delivery:
|
|
181
|
+
|
|
182
|
+
```
|
|
183
|
+
Server Client
|
|
184
|
+
│ │
|
|
185
|
+
│ ──── { __msgId, __payload } ──► │
|
|
186
|
+
│ │
|
|
187
|
+
│ ◄──── { __ack: msgId } ──────── │
|
|
188
|
+
│ │
|
|
189
|
+
▼ onAck() called ▼
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
**How it works:**
|
|
193
|
+
|
|
194
|
+
1. Server wraps message with unique `__msgId`
|
|
195
|
+
2. Client receives, extracts payload, auto-sends `__ack`
|
|
196
|
+
3. Server receives ACK, triggers `onAck` callback
|
|
197
|
+
4. If no ACK within timeout, triggers `onTimeout`
|
|
198
|
+
|
|
199
|
+
**Use cases:**
|
|
200
|
+
|
|
201
|
+
- Persist data only after client confirms receipt
|
|
202
|
+
- Track message delivery status
|
|
203
|
+
- Implement at-least-once delivery semantics
|
|
204
|
+
|
|
205
|
+
## Architecture
|
|
206
|
+
|
|
207
|
+
```
|
|
208
|
+
@agentxjs/network
|
|
209
|
+
├── protocol/
|
|
210
|
+
│ └── reliable-message.ts # ACK protocol types
|
|
211
|
+
│
|
|
212
|
+
├── server/
|
|
213
|
+
│ ├── WebSocketConnection.ts # Connection with sendReliable
|
|
214
|
+
│ └── WebSocketServer.ts # Server management
|
|
215
|
+
│
|
|
216
|
+
├── client/
|
|
217
|
+
│ ├── WebSocketClient.ts # Node.js client
|
|
218
|
+
│ └── BrowserWebSocketClient.ts # Browser client with reconnect
|
|
219
|
+
│
|
|
220
|
+
└── factory.ts # createWebSocketClient
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Examples
|
|
224
|
+
|
|
225
|
+
### Attach to HTTP Server
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
import { createServer } from "node:http";
|
|
229
|
+
import { WebSocketServer } from "@agentxjs/network";
|
|
230
|
+
|
|
231
|
+
const httpServer = createServer((req, res) => {
|
|
232
|
+
res.end("HTTP endpoint");
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
const wsServer = new WebSocketServer();
|
|
236
|
+
wsServer.attach(httpServer, "/ws");
|
|
237
|
+
|
|
238
|
+
httpServer.listen(5200);
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Custom Headers (Node.js)
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
const client = await createWebSocketClient({
|
|
245
|
+
serverUrl: "ws://localhost:5200",
|
|
246
|
+
headers: {
|
|
247
|
+
Authorization: "Bearer token123",
|
|
248
|
+
},
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
// Or dynamic headers
|
|
252
|
+
const client = await createWebSocketClient({
|
|
253
|
+
serverUrl: "ws://localhost:5200",
|
|
254
|
+
headers: async () => ({
|
|
255
|
+
Authorization: `Bearer ${await getToken()}`,
|
|
256
|
+
}),
|
|
257
|
+
});
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Reliable Delivery with Persistence
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
server.onConnection((connection) => {
|
|
264
|
+
// Only persist after client confirms receipt
|
|
265
|
+
connection.sendReliable(JSON.stringify(event), {
|
|
266
|
+
onAck: () => {
|
|
267
|
+
database.save(event);
|
|
268
|
+
console.log("Event persisted after client ACK");
|
|
269
|
+
},
|
|
270
|
+
timeout: 10000,
|
|
271
|
+
onTimeout: () => {
|
|
272
|
+
console.log("Client did not acknowledge, will retry...");
|
|
273
|
+
},
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## Testing
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
bun test
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
52 tests covering:
|
|
285
|
+
|
|
286
|
+
- Protocol type guards
|
|
287
|
+
- Connection send/sendReliable
|
|
288
|
+
- ACK handling and timeouts
|
|
289
|
+
- Server lifecycle
|
|
290
|
+
- Client auto-ACK
|
|
291
|
+
|
|
292
|
+
## License
|
|
293
|
+
|
|
294
|
+
MIT
|
package/dist/index.d.ts
CHANGED
|
@@ -17,9 +17,36 @@ declare class WebSocketServer implements ChannelServer {
|
|
|
17
17
|
close(): Promise<void>;
|
|
18
18
|
dispose(): Promise<void>;
|
|
19
19
|
}
|
|
20
|
-
import {
|
|
20
|
+
import { WebSocket as WS } from "ws";
|
|
21
|
+
import { ChannelConnection as ChannelConnection2, ChannelServerOptions as ChannelServerOptions2, Unsubscribe as Unsubscribe2, SendReliableOptions } from "@agentxjs/types/network";
|
|
21
22
|
/**
|
|
22
|
-
* WebSocket
|
|
23
|
+
* WebSocket connection implementation
|
|
24
|
+
*/
|
|
25
|
+
declare class WebSocketConnection implements ChannelConnection2 {
|
|
26
|
+
readonly id: string;
|
|
27
|
+
private ws;
|
|
28
|
+
private messageHandlers;
|
|
29
|
+
private closeHandlers;
|
|
30
|
+
private errorHandlers;
|
|
31
|
+
private heartbeatInterval?;
|
|
32
|
+
private isAlive;
|
|
33
|
+
private pendingAcks;
|
|
34
|
+
private msgIdCounter;
|
|
35
|
+
constructor(ws: WS, options: ChannelServerOptions2);
|
|
36
|
+
private setupHeartbeat;
|
|
37
|
+
private setupMessageHandler;
|
|
38
|
+
private setupCloseHandler;
|
|
39
|
+
private setupErrorHandler;
|
|
40
|
+
send(message: string): void;
|
|
41
|
+
sendReliable(message: string, options?: SendReliableOptions): void;
|
|
42
|
+
onMessage(handler: (message: string) => void): Unsubscribe2;
|
|
43
|
+
onClose(handler: () => void): Unsubscribe2;
|
|
44
|
+
onError(handler: (error: Error) => void): Unsubscribe2;
|
|
45
|
+
close(): void;
|
|
46
|
+
}
|
|
47
|
+
import { ChannelClient, ChannelClientOptions, Unsubscribe as Unsubscribe3 } from "@agentxjs/types/network";
|
|
48
|
+
/**
|
|
49
|
+
* WebSocket Client (Node.js version)
|
|
23
50
|
*/
|
|
24
51
|
declare class WebSocketClient implements ChannelClient {
|
|
25
52
|
private ws;
|
|
@@ -32,17 +59,76 @@ declare class WebSocketClient implements ChannelClient {
|
|
|
32
59
|
constructor(options: ChannelClientOptions);
|
|
33
60
|
get readyState(): "connecting" | "open" | "closing" | "closed";
|
|
34
61
|
connect(): Promise<void>;
|
|
62
|
+
private handleMessage;
|
|
35
63
|
send(message: string): void;
|
|
36
|
-
onMessage(handler: (message: string) => void):
|
|
37
|
-
onOpen(handler: () => void):
|
|
38
|
-
onClose(handler: () => void):
|
|
39
|
-
onError(handler: (error: Error) => void):
|
|
64
|
+
onMessage(handler: (message: string) => void): Unsubscribe3;
|
|
65
|
+
onOpen(handler: () => void): Unsubscribe3;
|
|
66
|
+
onClose(handler: () => void): Unsubscribe3;
|
|
67
|
+
onError(handler: (error: Error) => void): Unsubscribe3;
|
|
68
|
+
close(): void;
|
|
69
|
+
dispose(): void;
|
|
70
|
+
}
|
|
71
|
+
import { ChannelClient as ChannelClient2, ChannelClientOptions as ChannelClientOptions2, Unsubscribe as Unsubscribe4 } from "@agentxjs/types/network";
|
|
72
|
+
/**
|
|
73
|
+
* Browser WebSocket Client with auto-reconnect
|
|
74
|
+
*/
|
|
75
|
+
declare class BrowserWebSocketClient implements ChannelClient2 {
|
|
76
|
+
private ws;
|
|
77
|
+
private serverUrl;
|
|
78
|
+
private options;
|
|
79
|
+
private messageHandlers;
|
|
80
|
+
private openHandlers;
|
|
81
|
+
private closeHandlers;
|
|
82
|
+
private errorHandlers;
|
|
83
|
+
private hasConnectedBefore;
|
|
84
|
+
constructor(options: ChannelClientOptions2);
|
|
85
|
+
get readyState(): "connecting" | "open" | "closing" | "closed";
|
|
86
|
+
connect(): Promise<void>;
|
|
87
|
+
private handleMessage;
|
|
88
|
+
send(message: string): void;
|
|
89
|
+
onMessage(handler: (message: string) => void): Unsubscribe4;
|
|
90
|
+
onOpen(handler: () => void): Unsubscribe4;
|
|
91
|
+
onClose(handler: () => void): Unsubscribe4;
|
|
92
|
+
onError(handler: (error: Error) => void): Unsubscribe4;
|
|
40
93
|
close(): void;
|
|
41
94
|
dispose(): void;
|
|
42
95
|
}
|
|
96
|
+
import { ChannelClient as ChannelClient3, ChannelClientOptions as ChannelClientOptions3 } from "@agentxjs/types/network";
|
|
43
97
|
/**
|
|
44
98
|
* Factory function to create the appropriate WebSocket client
|
|
99
|
+
*
|
|
100
|
+
* @param options - Client configuration
|
|
101
|
+
* @returns Connected WebSocket client
|
|
102
|
+
*/
|
|
103
|
+
declare function createWebSocketClient(options: ChannelClientOptions3): Promise<ChannelClient3>;
|
|
104
|
+
/**
|
|
105
|
+
* Reliable Message Protocol
|
|
106
|
+
*
|
|
107
|
+
* Internal protocol for message acknowledgment between server and client.
|
|
108
|
+
* This is transparent to the application layer.
|
|
109
|
+
*/
|
|
110
|
+
/**
|
|
111
|
+
* Wrapper for reliable messages (server -> client)
|
|
112
|
+
* Contains the original message payload with a unique ID for tracking
|
|
113
|
+
*/
|
|
114
|
+
interface ReliableWrapper {
|
|
115
|
+
__msgId: string;
|
|
116
|
+
__payload: string;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* ACK message (client -> server)
|
|
120
|
+
* Sent automatically by client when receiving a reliable message
|
|
121
|
+
*/
|
|
122
|
+
interface AckMessage {
|
|
123
|
+
__ack: string;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Type guard for ACK messages
|
|
127
|
+
*/
|
|
128
|
+
declare function isAckMessage(data: unknown): data is AckMessage;
|
|
129
|
+
/**
|
|
130
|
+
* Type guard for reliable message wrappers
|
|
45
131
|
*/
|
|
46
|
-
declare function
|
|
47
|
-
import { ChannelServer as ChannelServer2, ChannelClient as
|
|
48
|
-
export { createWebSocketClient, WebSocketServer, WebSocketClient,
|
|
132
|
+
declare function isReliableWrapper(data: unknown): data is ReliableWrapper;
|
|
133
|
+
import { ChannelServer as ChannelServer2, ChannelClient as ChannelClient4, ChannelConnection as ChannelConnection3, ChannelClientOptions as ChannelClientOptions4, ChannelServerOptions as ChannelServerOptions3, SendReliableOptions as SendReliableOptions2, Unsubscribe as Unsubscribe5 } from "@agentxjs/types/network";
|
|
134
|
+
export { isReliableWrapper, isAckMessage, createWebSocketClient, WebSocketServer, WebSocketConnection, WebSocketClient, Unsubscribe5 as Unsubscribe, SendReliableOptions2 as SendReliableOptions, ReliableWrapper, ChannelServerOptions3 as ChannelServerOptions, ChannelServer2 as ChannelServer, ChannelConnection3 as ChannelConnection, ChannelClientOptions4 as ChannelClientOptions, ChannelClient4 as ChannelClient, BrowserWebSocketClient, AckMessage };
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,16 @@ var __toESM = (mod, isNodeMode, target) => {
|
|
|
14
14
|
});
|
|
15
15
|
return to;
|
|
16
16
|
};
|
|
17
|
+
var __export = (target, all) => {
|
|
18
|
+
for (var name in all)
|
|
19
|
+
__defProp(target, name, {
|
|
20
|
+
get: all[name],
|
|
21
|
+
enumerable: true,
|
|
22
|
+
configurable: true,
|
|
23
|
+
set: (newValue) => all[name] = () => newValue
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
17
27
|
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
18
28
|
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
19
29
|
}) : x)(function(x) {
|
|
@@ -22,191 +32,20 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
22
32
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
23
33
|
});
|
|
24
34
|
|
|
25
|
-
// src/
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
class WebSocketConnection {
|
|
30
|
-
id;
|
|
31
|
-
ws;
|
|
32
|
-
messageHandlers = new Set;
|
|
33
|
-
closeHandlers = new Set;
|
|
34
|
-
errorHandlers = new Set;
|
|
35
|
-
heartbeatInterval;
|
|
36
|
-
isAlive = true;
|
|
37
|
-
constructor(ws, options) {
|
|
38
|
-
this.ws = ws;
|
|
39
|
-
this.id = `conn_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
|
|
40
|
-
if (options.heartbeat !== false) {
|
|
41
|
-
const interval = options.heartbeatInterval || 30000;
|
|
42
|
-
ws.on("pong", () => {
|
|
43
|
-
this.isAlive = true;
|
|
44
|
-
logger.debug("Heartbeat pong received", { id: this.id });
|
|
45
|
-
});
|
|
46
|
-
this.heartbeatInterval = setInterval(() => {
|
|
47
|
-
if (!this.isAlive) {
|
|
48
|
-
logger.warn("Client heartbeat timeout, terminating connection", { id: this.id });
|
|
49
|
-
clearInterval(this.heartbeatInterval);
|
|
50
|
-
ws.terminate();
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
this.isAlive = false;
|
|
54
|
-
ws.ping();
|
|
55
|
-
logger.debug("Heartbeat ping sent", { id: this.id });
|
|
56
|
-
}, interval);
|
|
57
|
-
}
|
|
58
|
-
ws.on("message", (data) => {
|
|
59
|
-
const message = data.toString();
|
|
60
|
-
for (const handler of this.messageHandlers) {
|
|
61
|
-
handler(message);
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
ws.on("close", () => {
|
|
65
|
-
if (this.heartbeatInterval) {
|
|
66
|
-
clearInterval(this.heartbeatInterval);
|
|
67
|
-
}
|
|
68
|
-
for (const handler of this.closeHandlers) {
|
|
69
|
-
handler();
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
ws.on("error", (err) => {
|
|
73
|
-
if (this.heartbeatInterval) {
|
|
74
|
-
clearInterval(this.heartbeatInterval);
|
|
75
|
-
}
|
|
76
|
-
for (const handler of this.errorHandlers) {
|
|
77
|
-
handler(err);
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
send(message) {
|
|
82
|
-
if (this.ws.readyState === 1) {
|
|
83
|
-
this.ws.send(message);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
onMessage(handler) {
|
|
87
|
-
this.messageHandlers.add(handler);
|
|
88
|
-
return () => {
|
|
89
|
-
this.messageHandlers.delete(handler);
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
onClose(handler) {
|
|
93
|
-
this.closeHandlers.add(handler);
|
|
94
|
-
return () => {
|
|
95
|
-
this.closeHandlers.delete(handler);
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
onError(handler) {
|
|
99
|
-
this.errorHandlers.add(handler);
|
|
100
|
-
return () => {
|
|
101
|
-
this.errorHandlers.delete(handler);
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
close() {
|
|
105
|
-
if (this.heartbeatInterval) {
|
|
106
|
-
clearInterval(this.heartbeatInterval);
|
|
107
|
-
}
|
|
108
|
-
this.ws.close();
|
|
109
|
-
}
|
|
35
|
+
// src/protocol/reliable-message.ts
|
|
36
|
+
function isAckMessage(data) {
|
|
37
|
+
return typeof data === "object" && data !== null && "__ack" in data;
|
|
110
38
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
wss = null;
|
|
114
|
-
connections = new Set;
|
|
115
|
-
connectionHandlers = new Set;
|
|
116
|
-
options;
|
|
117
|
-
attachedToServer = false;
|
|
118
|
-
constructor(options = {}) {
|
|
119
|
-
this.options = options;
|
|
120
|
-
}
|
|
121
|
-
async listen(port, host = "0.0.0.0") {
|
|
122
|
-
if (this.wss) {
|
|
123
|
-
throw new Error("Server already listening");
|
|
124
|
-
}
|
|
125
|
-
if (this.attachedToServer) {
|
|
126
|
-
throw new Error("Cannot listen when attached to existing server. The server should call listen() instead.");
|
|
127
|
-
}
|
|
128
|
-
const { WebSocketServer: WSS } = await import("ws");
|
|
129
|
-
this.wss = new WSS({ port, host });
|
|
130
|
-
this.wss.on("connection", (ws) => {
|
|
131
|
-
this.handleConnection(ws);
|
|
132
|
-
});
|
|
133
|
-
logger.info("WebSocket server listening", { port, host });
|
|
134
|
-
}
|
|
135
|
-
attach(server, path = "/ws") {
|
|
136
|
-
if (this.wss) {
|
|
137
|
-
throw new Error("Server already initialized");
|
|
138
|
-
}
|
|
139
|
-
import("ws").then(({ WebSocketServer: WSS }) => {
|
|
140
|
-
this.wss = new WSS({ noServer: true });
|
|
141
|
-
server.on("upgrade", (request, socket, head) => {
|
|
142
|
-
const url = new URL(request.url || "", `http://${request.headers.host}`);
|
|
143
|
-
if (url.pathname === path) {
|
|
144
|
-
this.wss.handleUpgrade(request, socket, head, (ws) => {
|
|
145
|
-
this.wss.emit("connection", ws, request);
|
|
146
|
-
});
|
|
147
|
-
} else {
|
|
148
|
-
socket.destroy();
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
this.wss.on("connection", (ws) => {
|
|
152
|
-
this.handleConnection(ws);
|
|
153
|
-
});
|
|
154
|
-
this.attachedToServer = true;
|
|
155
|
-
logger.info("WebSocket attached to existing HTTP server", { path });
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
handleConnection(ws) {
|
|
159
|
-
const connection = new WebSocketConnection(ws, this.options);
|
|
160
|
-
this.connections.add(connection);
|
|
161
|
-
logger.info("Client connected", {
|
|
162
|
-
connectionId: connection.id,
|
|
163
|
-
totalConnections: this.connections.size
|
|
164
|
-
});
|
|
165
|
-
connection.onClose(() => {
|
|
166
|
-
this.connections.delete(connection);
|
|
167
|
-
logger.info("Client disconnected", {
|
|
168
|
-
connectionId: connection.id,
|
|
169
|
-
totalConnections: this.connections.size
|
|
170
|
-
});
|
|
171
|
-
});
|
|
172
|
-
for (const handler of this.connectionHandlers) {
|
|
173
|
-
handler(connection);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
onConnection(handler) {
|
|
177
|
-
this.connectionHandlers.add(handler);
|
|
178
|
-
return () => {
|
|
179
|
-
this.connectionHandlers.delete(handler);
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
broadcast(message) {
|
|
183
|
-
for (const connection of this.connections) {
|
|
184
|
-
connection.send(message);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
async close() {
|
|
188
|
-
if (!this.wss)
|
|
189
|
-
return;
|
|
190
|
-
for (const connection of this.connections) {
|
|
191
|
-
connection.close();
|
|
192
|
-
}
|
|
193
|
-
this.connections.clear();
|
|
194
|
-
if (!this.attachedToServer) {
|
|
195
|
-
await new Promise((resolve) => {
|
|
196
|
-
this.wss.close(() => resolve());
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
this.wss = null;
|
|
200
|
-
}
|
|
201
|
-
async dispose() {
|
|
202
|
-
await this.close();
|
|
203
|
-
this.connectionHandlers.clear();
|
|
204
|
-
}
|
|
39
|
+
function isReliableWrapper(data) {
|
|
40
|
+
return typeof data === "object" && data !== null && "__msgId" in data && "__payload" in data;
|
|
205
41
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
var
|
|
209
|
-
|
|
42
|
+
|
|
43
|
+
// src/client/WebSocketClient.ts
|
|
44
|
+
var exports_WebSocketClient = {};
|
|
45
|
+
__export(exports_WebSocketClient, {
|
|
46
|
+
WebSocketClient: () => WebSocketClient
|
|
47
|
+
});
|
|
48
|
+
import { createLogger as createLogger3 } from "@agentxjs/common";
|
|
210
49
|
|
|
211
50
|
class WebSocketClient {
|
|
212
51
|
ws = null;
|
|
@@ -217,9 +56,6 @@ class WebSocketClient {
|
|
|
217
56
|
closeHandlers = new Set;
|
|
218
57
|
errorHandlers = new Set;
|
|
219
58
|
constructor(options) {
|
|
220
|
-
if (isBrowser) {
|
|
221
|
-
throw new Error("Use createBrowserWebSocketClient() in browser environment for auto-reconnect support");
|
|
222
|
-
}
|
|
223
59
|
this.serverUrl = options.serverUrl;
|
|
224
60
|
this.headers = options.headers;
|
|
225
61
|
}
|
|
@@ -253,14 +89,14 @@ class WebSocketClient {
|
|
|
253
89
|
});
|
|
254
90
|
return new Promise((resolve, reject) => {
|
|
255
91
|
const onOpen = () => {
|
|
256
|
-
|
|
92
|
+
logger3.info("WebSocket connected", { serverUrl: this.serverUrl });
|
|
257
93
|
for (const handler of this.openHandlers) {
|
|
258
94
|
handler();
|
|
259
95
|
}
|
|
260
96
|
resolve();
|
|
261
97
|
};
|
|
262
98
|
const onError = (err) => {
|
|
263
|
-
|
|
99
|
+
logger3.error("WebSocket connection failed", {
|
|
264
100
|
serverUrl: this.serverUrl,
|
|
265
101
|
error: err?.message
|
|
266
102
|
});
|
|
@@ -270,24 +106,38 @@ class WebSocketClient {
|
|
|
270
106
|
this.ws.once("error", onError);
|
|
271
107
|
this.ws.on("message", (data) => {
|
|
272
108
|
const message = data.toString();
|
|
273
|
-
|
|
274
|
-
handler(message);
|
|
275
|
-
}
|
|
109
|
+
this.handleMessage(message);
|
|
276
110
|
});
|
|
277
111
|
this.ws.on("close", () => {
|
|
278
|
-
|
|
112
|
+
logger3.warn("WebSocket closed");
|
|
279
113
|
for (const handler of this.closeHandlers) {
|
|
280
114
|
handler();
|
|
281
115
|
}
|
|
282
116
|
});
|
|
283
117
|
this.ws.on("error", (err) => {
|
|
284
|
-
|
|
118
|
+
logger3.error("WebSocket error", { error: err.message });
|
|
285
119
|
for (const handler of this.errorHandlers) {
|
|
286
120
|
handler(err);
|
|
287
121
|
}
|
|
288
122
|
});
|
|
289
123
|
});
|
|
290
124
|
}
|
|
125
|
+
handleMessage(message) {
|
|
126
|
+
try {
|
|
127
|
+
const parsed = JSON.parse(message);
|
|
128
|
+
if (isReliableWrapper(parsed)) {
|
|
129
|
+
this.ws.send(JSON.stringify({ __ack: parsed.__msgId }));
|
|
130
|
+
logger3.debug("Auto-sent ACK", { msgId: parsed.__msgId });
|
|
131
|
+
for (const handler of this.messageHandlers) {
|
|
132
|
+
handler(parsed.__payload);
|
|
133
|
+
}
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
} catch {}
|
|
137
|
+
for (const handler of this.messageHandlers) {
|
|
138
|
+
handler(message);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
291
141
|
send(message) {
|
|
292
142
|
if (!this.ws || this.ws.readyState !== 1) {
|
|
293
143
|
throw new Error("WebSocket is not open");
|
|
@@ -332,6 +182,17 @@ class WebSocketClient {
|
|
|
332
182
|
this.errorHandlers.clear();
|
|
333
183
|
}
|
|
334
184
|
}
|
|
185
|
+
var logger3;
|
|
186
|
+
var init_WebSocketClient = __esm(() => {
|
|
187
|
+
logger3 = createLogger3("network/WebSocketClient");
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// src/client/BrowserWebSocketClient.ts
|
|
191
|
+
var exports_BrowserWebSocketClient = {};
|
|
192
|
+
__export(exports_BrowserWebSocketClient, {
|
|
193
|
+
BrowserWebSocketClient: () => BrowserWebSocketClient
|
|
194
|
+
});
|
|
195
|
+
import { createLogger as createLogger4 } from "@agentxjs/common";
|
|
335
196
|
|
|
336
197
|
class BrowserWebSocketClient {
|
|
337
198
|
ws = null;
|
|
@@ -343,9 +204,6 @@ class BrowserWebSocketClient {
|
|
|
343
204
|
errorHandlers = new Set;
|
|
344
205
|
hasConnectedBefore = false;
|
|
345
206
|
constructor(options) {
|
|
346
|
-
if (!isBrowser) {
|
|
347
|
-
throw new Error("BrowserWebSocketClient can only be used in browser environment");
|
|
348
|
-
}
|
|
349
207
|
this.serverUrl = options.serverUrl;
|
|
350
208
|
this.options = {
|
|
351
209
|
autoReconnect: true,
|
|
@@ -381,14 +239,14 @@ class BrowserWebSocketClient {
|
|
|
381
239
|
resolvedHeaders = this.options.headers;
|
|
382
240
|
}
|
|
383
241
|
}
|
|
384
|
-
|
|
242
|
+
logger4.debug("Connecting to WebSocket", {
|
|
385
243
|
serverUrl: this.serverUrl,
|
|
386
244
|
autoReconnect: this.options.autoReconnect,
|
|
387
245
|
connectionTimeout: this.options.connectionTimeout
|
|
388
246
|
});
|
|
389
247
|
if (this.options.autoReconnect) {
|
|
390
248
|
const ReconnectingWebSocket = (await import("reconnecting-websocket")).default;
|
|
391
|
-
|
|
249
|
+
logger4.debug("Using ReconnectingWebSocket");
|
|
392
250
|
this.ws = new ReconnectingWebSocket(this.serverUrl, [], {
|
|
393
251
|
maxReconnectionDelay: this.options.maxReconnectionDelay,
|
|
394
252
|
minReconnectionDelay: this.options.minReconnectionDelay,
|
|
@@ -398,15 +256,15 @@ class BrowserWebSocketClient {
|
|
|
398
256
|
debug: this.options.debug
|
|
399
257
|
});
|
|
400
258
|
} else {
|
|
401
|
-
|
|
259
|
+
logger4.debug("Using native WebSocket");
|
|
402
260
|
this.ws = new WebSocket(this.serverUrl);
|
|
403
261
|
}
|
|
404
262
|
return new Promise((resolve, reject) => {
|
|
405
263
|
const onOpen = async () => {
|
|
406
264
|
if (this.hasConnectedBefore) {
|
|
407
|
-
|
|
265
|
+
logger4.info("WebSocket reconnected successfully", { serverUrl: this.serverUrl });
|
|
408
266
|
} else {
|
|
409
|
-
|
|
267
|
+
logger4.info("WebSocket connected", { serverUrl: this.serverUrl });
|
|
410
268
|
this.hasConnectedBefore = true;
|
|
411
269
|
}
|
|
412
270
|
if (resolvedHeaders && Object.keys(resolvedHeaders).length > 0) {
|
|
@@ -416,9 +274,9 @@ class BrowserWebSocketClient {
|
|
|
416
274
|
headers: resolvedHeaders
|
|
417
275
|
});
|
|
418
276
|
this.ws.send(authMessage);
|
|
419
|
-
|
|
277
|
+
logger4.info("Sent authentication message to server");
|
|
420
278
|
} catch (error) {
|
|
421
|
-
|
|
279
|
+
logger4.error("Failed to send authentication message", { error });
|
|
422
280
|
}
|
|
423
281
|
}
|
|
424
282
|
for (const handler of this.openHandlers) {
|
|
@@ -427,7 +285,7 @@ class BrowserWebSocketClient {
|
|
|
427
285
|
resolve();
|
|
428
286
|
};
|
|
429
287
|
const onError = (_event) => {
|
|
430
|
-
|
|
288
|
+
logger4.error("WebSocket connection failed", { serverUrl: this.serverUrl });
|
|
431
289
|
const error = new Error("WebSocket connection failed");
|
|
432
290
|
for (const handler of this.errorHandlers) {
|
|
433
291
|
handler(error);
|
|
@@ -438,18 +296,16 @@ class BrowserWebSocketClient {
|
|
|
438
296
|
this.ws.addEventListener("error", onError, { once: true });
|
|
439
297
|
this.ws.addEventListener("message", (event) => {
|
|
440
298
|
const message = event.data;
|
|
441
|
-
|
|
442
|
-
handler(message);
|
|
443
|
-
}
|
|
299
|
+
this.handleMessage(message);
|
|
444
300
|
});
|
|
445
301
|
this.ws.addEventListener("close", () => {
|
|
446
|
-
|
|
302
|
+
logger4.info("WebSocket closed, attempting to reconnect...");
|
|
447
303
|
for (const handler of this.closeHandlers) {
|
|
448
304
|
handler();
|
|
449
305
|
}
|
|
450
306
|
});
|
|
451
307
|
this.ws.addEventListener("error", (_event) => {
|
|
452
|
-
|
|
308
|
+
logger4.error("WebSocket error");
|
|
453
309
|
const error = new Error("WebSocket error");
|
|
454
310
|
for (const handler of this.errorHandlers) {
|
|
455
311
|
handler(error);
|
|
@@ -457,6 +313,22 @@ class BrowserWebSocketClient {
|
|
|
457
313
|
});
|
|
458
314
|
});
|
|
459
315
|
}
|
|
316
|
+
handleMessage(message) {
|
|
317
|
+
try {
|
|
318
|
+
const parsed = JSON.parse(message);
|
|
319
|
+
if (isReliableWrapper(parsed)) {
|
|
320
|
+
this.ws.send(JSON.stringify({ __ack: parsed.__msgId }));
|
|
321
|
+
logger4.debug("Auto-sent ACK", { msgId: parsed.__msgId });
|
|
322
|
+
for (const handler of this.messageHandlers) {
|
|
323
|
+
handler(parsed.__payload);
|
|
324
|
+
}
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
} catch {}
|
|
328
|
+
for (const handler of this.messageHandlers) {
|
|
329
|
+
handler(message);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
460
332
|
send(message) {
|
|
461
333
|
if (!this.ws || this.ws.readyState !== 1) {
|
|
462
334
|
throw new Error("WebSocket is not open");
|
|
@@ -501,21 +373,294 @@ class BrowserWebSocketClient {
|
|
|
501
373
|
this.errorHandlers.clear();
|
|
502
374
|
}
|
|
503
375
|
}
|
|
376
|
+
var logger4;
|
|
377
|
+
var init_BrowserWebSocketClient = __esm(() => {
|
|
378
|
+
logger4 = createLogger4("network/BrowserWebSocketClient");
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
// src/server/WebSocketServer.ts
|
|
382
|
+
import { createLogger as createLogger2 } from "@agentxjs/common";
|
|
383
|
+
|
|
384
|
+
// src/server/WebSocketConnection.ts
|
|
385
|
+
import { createLogger } from "@agentxjs/common";
|
|
386
|
+
var logger = createLogger("network/WebSocketConnection");
|
|
387
|
+
|
|
388
|
+
class WebSocketConnection {
|
|
389
|
+
id;
|
|
390
|
+
ws;
|
|
391
|
+
messageHandlers = new Set;
|
|
392
|
+
closeHandlers = new Set;
|
|
393
|
+
errorHandlers = new Set;
|
|
394
|
+
heartbeatInterval;
|
|
395
|
+
isAlive = true;
|
|
396
|
+
pendingAcks = new Map;
|
|
397
|
+
msgIdCounter = 0;
|
|
398
|
+
constructor(ws, options) {
|
|
399
|
+
this.ws = ws;
|
|
400
|
+
this.id = `conn_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
|
|
401
|
+
this.setupHeartbeat(options);
|
|
402
|
+
this.setupMessageHandler();
|
|
403
|
+
this.setupCloseHandler();
|
|
404
|
+
this.setupErrorHandler();
|
|
405
|
+
}
|
|
406
|
+
setupHeartbeat(options) {
|
|
407
|
+
if (options.heartbeat === false)
|
|
408
|
+
return;
|
|
409
|
+
const interval = options.heartbeatInterval || 30000;
|
|
410
|
+
this.ws.on("pong", () => {
|
|
411
|
+
this.isAlive = true;
|
|
412
|
+
logger.debug("Heartbeat pong received", { id: this.id });
|
|
413
|
+
});
|
|
414
|
+
this.heartbeatInterval = setInterval(() => {
|
|
415
|
+
if (!this.isAlive) {
|
|
416
|
+
logger.warn("Client heartbeat timeout, terminating connection", { id: this.id });
|
|
417
|
+
clearInterval(this.heartbeatInterval);
|
|
418
|
+
this.ws.terminate();
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
this.isAlive = false;
|
|
422
|
+
this.ws.ping();
|
|
423
|
+
logger.debug("Heartbeat ping sent", { id: this.id });
|
|
424
|
+
}, interval);
|
|
425
|
+
}
|
|
426
|
+
setupMessageHandler() {
|
|
427
|
+
this.ws.on("message", (data) => {
|
|
428
|
+
const message = data.toString();
|
|
429
|
+
try {
|
|
430
|
+
const parsed = JSON.parse(message);
|
|
431
|
+
if (isAckMessage(parsed)) {
|
|
432
|
+
const pending = this.pendingAcks.get(parsed.__ack);
|
|
433
|
+
if (pending) {
|
|
434
|
+
clearTimeout(pending.timer);
|
|
435
|
+
pending.resolve();
|
|
436
|
+
this.pendingAcks.delete(parsed.__ack);
|
|
437
|
+
logger.debug("ACK received", { msgId: parsed.__ack, connectionId: this.id });
|
|
438
|
+
}
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
} catch {}
|
|
442
|
+
for (const handler of this.messageHandlers) {
|
|
443
|
+
handler(message);
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
setupCloseHandler() {
|
|
448
|
+
this.ws.on("close", () => {
|
|
449
|
+
if (this.heartbeatInterval) {
|
|
450
|
+
clearInterval(this.heartbeatInterval);
|
|
451
|
+
}
|
|
452
|
+
for (const handler of this.closeHandlers) {
|
|
453
|
+
handler();
|
|
454
|
+
}
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
setupErrorHandler() {
|
|
458
|
+
this.ws.on("error", (err) => {
|
|
459
|
+
if (this.heartbeatInterval) {
|
|
460
|
+
clearInterval(this.heartbeatInterval);
|
|
461
|
+
}
|
|
462
|
+
for (const handler of this.errorHandlers) {
|
|
463
|
+
handler(err);
|
|
464
|
+
}
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
send(message) {
|
|
468
|
+
if (this.ws.readyState === 1) {
|
|
469
|
+
this.ws.send(message);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
sendReliable(message, options) {
|
|
473
|
+
if (this.ws.readyState !== 1) {
|
|
474
|
+
options?.onTimeout?.();
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
if (!options?.onAck) {
|
|
478
|
+
this.send(message);
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
const msgId = `${this.id}_${++this.msgIdCounter}`;
|
|
482
|
+
const wrapped = {
|
|
483
|
+
__msgId: msgId,
|
|
484
|
+
__payload: message
|
|
485
|
+
};
|
|
486
|
+
const timeout = options.timeout ?? 5000;
|
|
487
|
+
const timer = setTimeout(() => {
|
|
488
|
+
if (this.pendingAcks.has(msgId)) {
|
|
489
|
+
this.pendingAcks.delete(msgId);
|
|
490
|
+
logger.warn("ACK timeout", { msgId, connectionId: this.id, timeout });
|
|
491
|
+
options.onTimeout?.();
|
|
492
|
+
}
|
|
493
|
+
}, timeout);
|
|
494
|
+
this.pendingAcks.set(msgId, {
|
|
495
|
+
resolve: options.onAck,
|
|
496
|
+
timer
|
|
497
|
+
});
|
|
498
|
+
this.ws.send(JSON.stringify(wrapped));
|
|
499
|
+
logger.debug("Sent reliable message", { msgId, connectionId: this.id });
|
|
500
|
+
}
|
|
501
|
+
onMessage(handler) {
|
|
502
|
+
this.messageHandlers.add(handler);
|
|
503
|
+
return () => {
|
|
504
|
+
this.messageHandlers.delete(handler);
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
onClose(handler) {
|
|
508
|
+
this.closeHandlers.add(handler);
|
|
509
|
+
return () => {
|
|
510
|
+
this.closeHandlers.delete(handler);
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
onError(handler) {
|
|
514
|
+
this.errorHandlers.add(handler);
|
|
515
|
+
return () => {
|
|
516
|
+
this.errorHandlers.delete(handler);
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
close() {
|
|
520
|
+
if (this.heartbeatInterval) {
|
|
521
|
+
clearInterval(this.heartbeatInterval);
|
|
522
|
+
}
|
|
523
|
+
for (const pending of this.pendingAcks.values()) {
|
|
524
|
+
clearTimeout(pending.timer);
|
|
525
|
+
}
|
|
526
|
+
this.pendingAcks.clear();
|
|
527
|
+
this.ws.close();
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
// src/server/WebSocketServer.ts
|
|
532
|
+
var logger2 = createLogger2("network/WebSocketServer");
|
|
533
|
+
|
|
534
|
+
class WebSocketServer {
|
|
535
|
+
wss = null;
|
|
536
|
+
connections = new Set;
|
|
537
|
+
connectionHandlers = new Set;
|
|
538
|
+
options;
|
|
539
|
+
attachedToServer = false;
|
|
540
|
+
constructor(options = {}) {
|
|
541
|
+
this.options = options;
|
|
542
|
+
}
|
|
543
|
+
async listen(port, host = "0.0.0.0") {
|
|
544
|
+
if (this.wss) {
|
|
545
|
+
throw new Error("Server already listening");
|
|
546
|
+
}
|
|
547
|
+
if (this.attachedToServer) {
|
|
548
|
+
throw new Error("Cannot listen when attached to existing server. The server should call listen() instead.");
|
|
549
|
+
}
|
|
550
|
+
const { WebSocketServer: WSS } = await import("ws");
|
|
551
|
+
this.wss = new WSS({ port, host });
|
|
552
|
+
this.wss.on("connection", (ws) => {
|
|
553
|
+
this.handleConnection(ws);
|
|
554
|
+
});
|
|
555
|
+
logger2.info("WebSocket server listening", { port, host });
|
|
556
|
+
}
|
|
557
|
+
attach(server, path = "/ws") {
|
|
558
|
+
if (this.wss) {
|
|
559
|
+
throw new Error("Server already initialized");
|
|
560
|
+
}
|
|
561
|
+
import("ws").then(({ WebSocketServer: WSS }) => {
|
|
562
|
+
this.wss = new WSS({ noServer: true });
|
|
563
|
+
server.on("upgrade", (request, socket, head) => {
|
|
564
|
+
const url = new URL(request.url || "", `http://${request.headers.host}`);
|
|
565
|
+
if (url.pathname === path) {
|
|
566
|
+
this.wss.handleUpgrade(request, socket, head, (ws) => {
|
|
567
|
+
this.wss.emit("connection", ws, request);
|
|
568
|
+
});
|
|
569
|
+
} else {
|
|
570
|
+
socket.destroy();
|
|
571
|
+
}
|
|
572
|
+
});
|
|
573
|
+
this.wss.on("connection", (ws) => {
|
|
574
|
+
this.handleConnection(ws);
|
|
575
|
+
});
|
|
576
|
+
this.attachedToServer = true;
|
|
577
|
+
logger2.info("WebSocket attached to existing HTTP server", { path });
|
|
578
|
+
});
|
|
579
|
+
}
|
|
580
|
+
handleConnection(ws) {
|
|
581
|
+
const connection = new WebSocketConnection(ws, this.options);
|
|
582
|
+
this.connections.add(connection);
|
|
583
|
+
logger2.info("Client connected", {
|
|
584
|
+
connectionId: connection.id,
|
|
585
|
+
totalConnections: this.connections.size
|
|
586
|
+
});
|
|
587
|
+
connection.onClose(() => {
|
|
588
|
+
this.connections.delete(connection);
|
|
589
|
+
logger2.info("Client disconnected", {
|
|
590
|
+
connectionId: connection.id,
|
|
591
|
+
totalConnections: this.connections.size
|
|
592
|
+
});
|
|
593
|
+
});
|
|
594
|
+
for (const handler of this.connectionHandlers) {
|
|
595
|
+
handler(connection);
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
onConnection(handler) {
|
|
599
|
+
this.connectionHandlers.add(handler);
|
|
600
|
+
return () => {
|
|
601
|
+
this.connectionHandlers.delete(handler);
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
broadcast(message) {
|
|
605
|
+
for (const connection of this.connections) {
|
|
606
|
+
connection.send(message);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
async close() {
|
|
610
|
+
if (!this.wss)
|
|
611
|
+
return;
|
|
612
|
+
for (const connection of this.connections) {
|
|
613
|
+
connection.close();
|
|
614
|
+
}
|
|
615
|
+
this.connections.clear();
|
|
616
|
+
if (!this.attachedToServer) {
|
|
617
|
+
await new Promise((resolve) => {
|
|
618
|
+
const timeout = setTimeout(() => {
|
|
619
|
+
logger2.warn("WebSocket server close timeout, forcing close");
|
|
620
|
+
resolve();
|
|
621
|
+
}, 1000);
|
|
622
|
+
this.wss.close(() => {
|
|
623
|
+
clearTimeout(timeout);
|
|
624
|
+
resolve();
|
|
625
|
+
});
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
this.wss = null;
|
|
629
|
+
logger2.info("WebSocket server closed");
|
|
630
|
+
}
|
|
631
|
+
async dispose() {
|
|
632
|
+
await this.close();
|
|
633
|
+
this.connectionHandlers.clear();
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
// src/index.ts
|
|
638
|
+
init_WebSocketClient();
|
|
639
|
+
init_BrowserWebSocketClient();
|
|
640
|
+
|
|
641
|
+
// src/factory.ts
|
|
642
|
+
var isBrowser = typeof globalThis !== "undefined" && typeof globalThis.window !== "undefined" && typeof globalThis.window.WebSocket !== "undefined";
|
|
504
643
|
async function createWebSocketClient(options) {
|
|
505
644
|
if (isBrowser) {
|
|
506
|
-
const
|
|
645
|
+
const { BrowserWebSocketClient: BrowserWebSocketClient2 } = await Promise.resolve().then(() => (init_BrowserWebSocketClient(), exports_BrowserWebSocketClient));
|
|
646
|
+
const client = new BrowserWebSocketClient2(options);
|
|
507
647
|
await client.connect();
|
|
508
648
|
return client;
|
|
509
649
|
} else {
|
|
510
|
-
const
|
|
650
|
+
const { WebSocketClient: WebSocketClient2 } = await Promise.resolve().then(() => (init_WebSocketClient(), exports_WebSocketClient));
|
|
651
|
+
const client = new WebSocketClient2(options);
|
|
511
652
|
await client.connect();
|
|
512
653
|
return client;
|
|
513
654
|
}
|
|
514
655
|
}
|
|
515
656
|
export {
|
|
657
|
+
isReliableWrapper,
|
|
658
|
+
isAckMessage,
|
|
516
659
|
createWebSocketClient,
|
|
517
660
|
WebSocketServer,
|
|
518
|
-
|
|
661
|
+
WebSocketConnection,
|
|
662
|
+
WebSocketClient,
|
|
663
|
+
BrowserWebSocketClient
|
|
519
664
|
};
|
|
520
665
|
|
|
521
|
-
//# debugId=
|
|
666
|
+
//# debugId=41D375A37CDC1ED664756E2164756E21
|
package/dist/index.js.map
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/
|
|
3
|
+
"sources": ["../src/protocol/reliable-message.ts", "../src/client/WebSocketClient.ts", "../src/client/BrowserWebSocketClient.ts", "../src/server/WebSocketServer.ts", "../src/server/WebSocketConnection.ts", "../src/index.ts", "../src/factory.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/**\n *
|
|
6
|
-
"/**\n * WebSocket Client implementation of ChannelClient\n */\n\nimport type { ChannelClient, ChannelClientOptions, Unsubscribe } from \"@agentxjs/types/network\";\nimport { createLogger } from \"@agentxjs/common\";\n\nconst logger = createLogger(\"network/WebSocketClient\");\n\n// Detect browser environment\nconst isBrowser =\n typeof globalThis !== \"undefined\" &&\n typeof (globalThis as any).window !== \"undefined\" &&\n typeof (globalThis as any).window.WebSocket !== \"undefined\";\n\n/**\n * WebSocket Client (Node.js version - no auto-reconnect)\n */\nexport class WebSocketClient implements ChannelClient {\n private ws: WebSocket | null = null;\n private serverUrl: string;\n private headers?:\n | Record<string, string>\n | (() => Record<string, string> | Promise<Record<string, string>>);\n private messageHandlers = new Set<(message: string) => void>();\n private openHandlers = new Set<() => void>();\n private closeHandlers = new Set<() => void>();\n private errorHandlers = new Set<(error: Error) => void>();\n\n constructor(options: ChannelClientOptions) {\n if (isBrowser) {\n throw new Error(\n \"Use createBrowserWebSocketClient() in browser environment for auto-reconnect support\"\n );\n }\n\n this.serverUrl = options.serverUrl;\n this.headers = options.headers;\n }\n\n get readyState(): \"connecting\" | \"open\" | \"closing\" | \"closed\" {\n if (!this.ws) return \"closed\";\n const state = this.ws.readyState;\n if (state === 0) return \"connecting\";\n if (state === 1) return \"open\";\n if (state === 2) return \"closing\";\n return \"closed\";\n }\n\n async connect(): Promise<void> {\n if (this.ws) {\n throw new Error(\"Already connected or connecting\");\n }\n\n const { WebSocket: NodeWebSocket } = await import(\"ws\");\n\n // Resolve headers (support static, sync function, and async function)\n let resolvedHeaders: Record<string, string> | undefined;\n if (this.headers) {\n if (typeof this.headers === \"function\") {\n resolvedHeaders = await Promise.resolve(this.headers());\n } else {\n resolvedHeaders = this.headers;\n }\n }\n\n // Create WebSocket with headers (Node.js ws library supports this)\n this.ws = new NodeWebSocket(this.serverUrl, {\n headers: resolvedHeaders,\n }) as unknown as WebSocket;\n\n return new Promise<void>((resolve, reject) => {\n const onOpen = () => {\n logger.info(\"WebSocket connected\", { serverUrl: this.serverUrl });\n for (const handler of this.openHandlers) {\n handler();\n }\n resolve();\n };\n\n const onError = (err?: Error) => {\n logger.error(\"WebSocket connection failed\", {\n serverUrl: this.serverUrl,\n error: err?.message,\n });\n reject(err || new Error(\"WebSocket connection failed\"));\n };\n\n (this.ws as any).once(\"open\", onOpen);\n (this.ws as any).once(\"error\", onError);\n\n // Setup permanent handlers\n (this.ws as any).on(\"message\", (data: Buffer) => {\n const message = data.toString();\n for (const handler of this.messageHandlers) {\n handler(message);\n }\n });\n\n (this.ws as any).on(\"close\", () => {\n logger.warn(\"WebSocket closed\");\n for (const handler of this.closeHandlers) {\n handler();\n }\n });\n\n (this.ws as any).on(\"error\", (err: Error) => {\n logger.error(\"WebSocket error\", { error: err.message });\n for (const handler of this.errorHandlers) {\n handler(err);\n }\n });\n });\n }\n\n send(message: string): void {\n if (!this.ws || this.ws.readyState !== 1) {\n throw new Error(\"WebSocket is not open\");\n }\n this.ws.send(message);\n }\n\n onMessage(handler: (message: string) => void): Unsubscribe {\n this.messageHandlers.add(handler);\n return () => {\n this.messageHandlers.delete(handler);\n };\n }\n\n onOpen(handler: () => void): Unsubscribe {\n this.openHandlers.add(handler);\n return () => {\n this.openHandlers.delete(handler);\n };\n }\n\n onClose(handler: () => void): Unsubscribe {\n this.closeHandlers.add(handler);\n return () => {\n this.closeHandlers.delete(handler);\n };\n }\n\n onError(handler: (error: Error) => void): Unsubscribe {\n this.errorHandlers.add(handler);\n return () => {\n this.errorHandlers.delete(handler);\n };\n }\n\n close(): void {\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n }\n }\n\n dispose(): void {\n this.close();\n this.messageHandlers.clear();\n this.openHandlers.clear();\n this.closeHandlers.clear();\n this.errorHandlers.clear();\n }\n}\n\n/**\n * Browser WebSocket Client with auto-reconnect\n */\nexport class BrowserWebSocketClient implements ChannelClient {\n private ws: WebSocket | null = null;\n private serverUrl: string;\n private options: ChannelClientOptions;\n private messageHandlers = new Set<(message: string) => void>();\n private openHandlers = new Set<() => void>();\n private closeHandlers = new Set<() => void>();\n private errorHandlers = new Set<(error: Error) => void>();\n private hasConnectedBefore = false; // Track if this is a reconnection\n\n constructor(options: ChannelClientOptions) {\n if (!isBrowser) {\n throw new Error(\"BrowserWebSocketClient can only be used in browser environment\");\n }\n\n this.serverUrl = options.serverUrl;\n this.options = {\n autoReconnect: true,\n minReconnectionDelay: 1000,\n maxReconnectionDelay: 10000,\n maxRetries: Infinity,\n connectionTimeout: 4000,\n debug: false,\n ...options,\n };\n }\n\n get readyState(): \"connecting\" | \"open\" | \"closing\" | \"closed\" {\n if (!this.ws) return \"closed\";\n const state = this.ws.readyState;\n if (state === 0) return \"connecting\";\n if (state === 1) return \"open\";\n if (state === 2) return \"closing\";\n return \"closed\";\n }\n\n async connect(): Promise<void> {\n if (this.ws) {\n throw new Error(\"Already connected or connecting\");\n }\n\n // Resolve headers before creating WebSocket (if any)\n let resolvedHeaders: Record<string, string> | undefined;\n if (this.options.headers) {\n if (typeof this.options.headers === \"function\") {\n resolvedHeaders = await Promise.resolve(this.options.headers());\n } else {\n resolvedHeaders = this.options.headers;\n }\n }\n\n logger.debug(\"Connecting to WebSocket\", {\n serverUrl: this.serverUrl,\n autoReconnect: this.options.autoReconnect,\n connectionTimeout: this.options.connectionTimeout,\n });\n\n if (this.options.autoReconnect) {\n // Use reconnecting-websocket for auto-reconnect\n const ReconnectingWebSocket = (await import(\"reconnecting-websocket\")).default;\n logger.debug(\"Using ReconnectingWebSocket\");\n this.ws = new ReconnectingWebSocket(this.serverUrl, [], {\n maxReconnectionDelay: this.options.maxReconnectionDelay,\n minReconnectionDelay: this.options.minReconnectionDelay,\n reconnectionDelayGrowFactor: 1.3,\n connectionTimeout: this.options.connectionTimeout,\n maxRetries: this.options.maxRetries,\n debug: this.options.debug,\n });\n } else {\n // Use native WebSocket\n logger.debug(\"Using native WebSocket\");\n this.ws = new WebSocket(this.serverUrl);\n }\n\n return new Promise<void>((resolve, reject) => {\n const onOpen = async () => {\n if (this.hasConnectedBefore) {\n logger.info(\"WebSocket reconnected successfully\", { serverUrl: this.serverUrl });\n } else {\n logger.info(\"WebSocket connected\", { serverUrl: this.serverUrl });\n this.hasConnectedBefore = true;\n }\n\n // Browser WebSocket API doesn't support custom headers in handshake\n // Send authentication message as first message instead\n if (resolvedHeaders && Object.keys(resolvedHeaders).length > 0) {\n try {\n const authMessage = JSON.stringify({\n type: \"auth\",\n headers: resolvedHeaders,\n });\n this.ws!.send(authMessage);\n logger.info(\"Sent authentication message to server\");\n } catch (error) {\n logger.error(\"Failed to send authentication message\", { error });\n }\n }\n\n for (const handler of this.openHandlers) {\n handler();\n }\n resolve();\n };\n\n const onError = (_event: Event) => {\n logger.error(\"WebSocket connection failed\", { serverUrl: this.serverUrl });\n const error = new Error(\"WebSocket connection failed\");\n for (const handler of this.errorHandlers) {\n handler(error);\n }\n reject(error);\n };\n\n this.ws!.addEventListener(\"open\", onOpen as any, { once: true });\n this.ws!.addEventListener(\"error\", onError as any, { once: true });\n\n // Setup permanent handlers\n this.ws!.addEventListener(\"message\", ((event: any) => {\n const message = event.data;\n for (const handler of this.messageHandlers) {\n handler(message);\n }\n }) as any);\n\n this.ws!.addEventListener(\"close\", (() => {\n logger.info(\"WebSocket closed, attempting to reconnect...\");\n for (const handler of this.closeHandlers) {\n handler();\n }\n }) as any);\n\n this.ws!.addEventListener(\"error\", ((_event: Event) => {\n logger.error(\"WebSocket error\");\n const error = new Error(\"WebSocket error\");\n for (const handler of this.errorHandlers) {\n handler(error);\n }\n }) as any);\n });\n }\n\n send(message: string): void {\n if (!this.ws || this.ws.readyState !== 1) {\n throw new Error(\"WebSocket is not open\");\n }\n this.ws.send(message);\n }\n\n onMessage(handler: (message: string) => void): Unsubscribe {\n this.messageHandlers.add(handler);\n return () => {\n this.messageHandlers.delete(handler);\n };\n }\n\n onOpen(handler: () => void): Unsubscribe {\n this.openHandlers.add(handler);\n return () => {\n this.openHandlers.delete(handler);\n };\n }\n\n onClose(handler: () => void): Unsubscribe {\n this.closeHandlers.add(handler);\n return () => {\n this.closeHandlers.delete(handler);\n };\n }\n\n onError(handler: (error: Error) => void): Unsubscribe {\n this.errorHandlers.add(handler);\n return () => {\n this.errorHandlers.delete(handler);\n };\n }\n\n close(): void {\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n }\n }\n\n dispose(): void {\n this.close();\n this.messageHandlers.clear();\n this.openHandlers.clear();\n this.closeHandlers.clear();\n this.errorHandlers.clear();\n }\n}\n\n/**\n * Factory function to create the appropriate WebSocket client\n */\nexport async function createWebSocketClient(options: ChannelClientOptions): Promise<ChannelClient> {\n if (isBrowser) {\n const client = new BrowserWebSocketClient(options);\n await client.connect();\n return client;\n } else {\n const client = new WebSocketClient(options);\n await client.connect();\n return client;\n }\n}\n"
|
|
5
|
+
"/**\n * Reliable Message Protocol\n *\n * Internal protocol for message acknowledgment between server and client.\n * This is transparent to the application layer.\n */\n\n/**\n * Wrapper for reliable messages (server -> client)\n * Contains the original message payload with a unique ID for tracking\n */\nexport interface ReliableWrapper {\n __msgId: string;\n __payload: string;\n}\n\n/**\n * ACK message (client -> server)\n * Sent automatically by client when receiving a reliable message\n */\nexport interface AckMessage {\n __ack: string;\n}\n\n/**\n * Type guard for ACK messages\n */\nexport function isAckMessage(data: unknown): data is AckMessage {\n return typeof data === \"object\" && data !== null && \"__ack\" in data;\n}\n\n/**\n * Type guard for reliable message wrappers\n */\nexport function isReliableWrapper(data: unknown): data is ReliableWrapper {\n return typeof data === \"object\" && data !== null && \"__msgId\" in data && \"__payload\" in data;\n}\n",
|
|
6
|
+
"/**\n * WebSocket Client - Node.js implementation\n *\n * Features:\n * - ws library based\n * - Custom headers support\n * - Auto ACK for reliable messages\n */\n\nimport type { ChannelClient, ChannelClientOptions, Unsubscribe } from \"@agentxjs/types/network\";\nimport { createLogger } from \"@agentxjs/common\";\nimport { isReliableWrapper } from \"../protocol/reliable-message\";\n\nconst logger = createLogger(\"network/WebSocketClient\");\n\n/**\n * WebSocket Client (Node.js version)\n */\nexport class WebSocketClient implements ChannelClient {\n private ws: WebSocket | null = null;\n private serverUrl: string;\n private headers?:\n | Record<string, string>\n | (() => Record<string, string> | Promise<Record<string, string>>);\n private messageHandlers = new Set<(message: string) => void>();\n private openHandlers = new Set<() => void>();\n private closeHandlers = new Set<() => void>();\n private errorHandlers = new Set<(error: Error) => void>();\n\n constructor(options: ChannelClientOptions) {\n this.serverUrl = options.serverUrl;\n this.headers = options.headers;\n }\n\n get readyState(): \"connecting\" | \"open\" | \"closing\" | \"closed\" {\n if (!this.ws) return \"closed\";\n const state = this.ws.readyState;\n if (state === 0) return \"connecting\";\n if (state === 1) return \"open\";\n if (state === 2) return \"closing\";\n return \"closed\";\n }\n\n async connect(): Promise<void> {\n if (this.ws) {\n throw new Error(\"Already connected or connecting\");\n }\n\n const { WebSocket: NodeWebSocket } = await import(\"ws\");\n\n // Resolve headers (support static, sync function, and async function)\n let resolvedHeaders: Record<string, string> | undefined;\n if (this.headers) {\n if (typeof this.headers === \"function\") {\n resolvedHeaders = await Promise.resolve(this.headers());\n } else {\n resolvedHeaders = this.headers;\n }\n }\n\n // Create WebSocket with headers (Node.js ws library supports this)\n this.ws = new NodeWebSocket(this.serverUrl, {\n headers: resolvedHeaders,\n }) as unknown as WebSocket;\n\n return new Promise<void>((resolve, reject) => {\n const onOpen = () => {\n logger.info(\"WebSocket connected\", { serverUrl: this.serverUrl });\n for (const handler of this.openHandlers) {\n handler();\n }\n resolve();\n };\n\n const onError = (err?: Error) => {\n logger.error(\"WebSocket connection failed\", {\n serverUrl: this.serverUrl,\n error: err?.message,\n });\n reject(err || new Error(\"WebSocket connection failed\"));\n };\n\n (this.ws as any).once(\"open\", onOpen);\n (this.ws as any).once(\"error\", onError);\n\n // Setup permanent handlers\n (this.ws as any).on(\"message\", (data: Buffer) => {\n const message = data.toString();\n this.handleMessage(message);\n });\n\n (this.ws as any).on(\"close\", () => {\n logger.warn(\"WebSocket closed\");\n for (const handler of this.closeHandlers) {\n handler();\n }\n });\n\n (this.ws as any).on(\"error\", (err: Error) => {\n logger.error(\"WebSocket error\", { error: err.message });\n for (const handler of this.errorHandlers) {\n handler(err);\n }\n });\n });\n }\n\n private handleMessage(message: string): void {\n // Check for reliable message wrapper and auto-send ACK\n try {\n const parsed = JSON.parse(message);\n if (isReliableWrapper(parsed)) {\n // Send ACK immediately\n this.ws!.send(JSON.stringify({ __ack: parsed.__msgId }));\n logger.debug(\"Auto-sent ACK\", { msgId: parsed.__msgId });\n\n // Pass unwrapped payload to handlers\n for (const handler of this.messageHandlers) {\n handler(parsed.__payload);\n }\n return;\n }\n } catch {\n // Not JSON, pass through as normal message\n }\n\n for (const handler of this.messageHandlers) {\n handler(message);\n }\n }\n\n send(message: string): void {\n if (!this.ws || this.ws.readyState !== 1) {\n throw new Error(\"WebSocket is not open\");\n }\n this.ws.send(message);\n }\n\n onMessage(handler: (message: string) => void): Unsubscribe {\n this.messageHandlers.add(handler);\n return () => {\n this.messageHandlers.delete(handler);\n };\n }\n\n onOpen(handler: () => void): Unsubscribe {\n this.openHandlers.add(handler);\n return () => {\n this.openHandlers.delete(handler);\n };\n }\n\n onClose(handler: () => void): Unsubscribe {\n this.closeHandlers.add(handler);\n return () => {\n this.closeHandlers.delete(handler);\n };\n }\n\n onError(handler: (error: Error) => void): Unsubscribe {\n this.errorHandlers.add(handler);\n return () => {\n this.errorHandlers.delete(handler);\n };\n }\n\n close(): void {\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n }\n }\n\n dispose(): void {\n this.close();\n this.messageHandlers.clear();\n this.openHandlers.clear();\n this.closeHandlers.clear();\n this.errorHandlers.clear();\n }\n}\n",
|
|
7
|
+
"/**\n * Browser WebSocket Client - Browser implementation with auto-reconnect\n *\n * Features:\n * - reconnecting-websocket based\n * - Auto reconnect on disconnect\n * - Auth headers via first message (browser limitation)\n * - Auto ACK for reliable messages\n */\n\nimport type { ChannelClient, ChannelClientOptions, Unsubscribe } from \"@agentxjs/types/network\";\nimport { createLogger } from \"@agentxjs/common\";\nimport { isReliableWrapper } from \"../protocol/reliable-message\";\n\nconst logger = createLogger(\"network/BrowserWebSocketClient\");\n\n/**\n * Browser WebSocket Client with auto-reconnect\n */\nexport class BrowserWebSocketClient implements ChannelClient {\n private ws: WebSocket | null = null;\n private serverUrl: string;\n private options: ChannelClientOptions;\n private messageHandlers = new Set<(message: string) => void>();\n private openHandlers = new Set<() => void>();\n private closeHandlers = new Set<() => void>();\n private errorHandlers = new Set<(error: Error) => void>();\n private hasConnectedBefore = false;\n\n constructor(options: ChannelClientOptions) {\n this.serverUrl = options.serverUrl;\n this.options = {\n autoReconnect: true,\n minReconnectionDelay: 1000,\n maxReconnectionDelay: 10000,\n maxRetries: Infinity,\n connectionTimeout: 4000,\n debug: false,\n ...options,\n };\n }\n\n get readyState(): \"connecting\" | \"open\" | \"closing\" | \"closed\" {\n if (!this.ws) return \"closed\";\n const state = this.ws.readyState;\n if (state === 0) return \"connecting\";\n if (state === 1) return \"open\";\n if (state === 2) return \"closing\";\n return \"closed\";\n }\n\n async connect(): Promise<void> {\n if (this.ws) {\n throw new Error(\"Already connected or connecting\");\n }\n\n // Resolve headers before creating WebSocket (if any)\n let resolvedHeaders: Record<string, string> | undefined;\n if (this.options.headers) {\n if (typeof this.options.headers === \"function\") {\n resolvedHeaders = await Promise.resolve(this.options.headers());\n } else {\n resolvedHeaders = this.options.headers;\n }\n }\n\n logger.debug(\"Connecting to WebSocket\", {\n serverUrl: this.serverUrl,\n autoReconnect: this.options.autoReconnect,\n connectionTimeout: this.options.connectionTimeout,\n });\n\n if (this.options.autoReconnect) {\n // Use reconnecting-websocket for auto-reconnect\n const ReconnectingWebSocket = (await import(\"reconnecting-websocket\")).default;\n logger.debug(\"Using ReconnectingWebSocket\");\n this.ws = new ReconnectingWebSocket(this.serverUrl, [], {\n maxReconnectionDelay: this.options.maxReconnectionDelay,\n minReconnectionDelay: this.options.minReconnectionDelay,\n reconnectionDelayGrowFactor: 1.3,\n connectionTimeout: this.options.connectionTimeout,\n maxRetries: this.options.maxRetries,\n debug: this.options.debug,\n });\n } else {\n // Use native WebSocket\n logger.debug(\"Using native WebSocket\");\n this.ws = new WebSocket(this.serverUrl);\n }\n\n return new Promise<void>((resolve, reject) => {\n const onOpen = async () => {\n if (this.hasConnectedBefore) {\n logger.info(\"WebSocket reconnected successfully\", { serverUrl: this.serverUrl });\n } else {\n logger.info(\"WebSocket connected\", { serverUrl: this.serverUrl });\n this.hasConnectedBefore = true;\n }\n\n // Browser WebSocket API doesn't support custom headers in handshake\n // Send authentication message as first message instead\n if (resolvedHeaders && Object.keys(resolvedHeaders).length > 0) {\n try {\n const authMessage = JSON.stringify({\n type: \"auth\",\n headers: resolvedHeaders,\n });\n this.ws!.send(authMessage);\n logger.info(\"Sent authentication message to server\");\n } catch (error) {\n logger.error(\"Failed to send authentication message\", { error });\n }\n }\n\n for (const handler of this.openHandlers) {\n handler();\n }\n resolve();\n };\n\n const onError = (_event: Event) => {\n logger.error(\"WebSocket connection failed\", { serverUrl: this.serverUrl });\n const error = new Error(\"WebSocket connection failed\");\n for (const handler of this.errorHandlers) {\n handler(error);\n }\n reject(error);\n };\n\n this.ws!.addEventListener(\"open\", onOpen as any, { once: true });\n this.ws!.addEventListener(\"error\", onError as any, { once: true });\n\n // Setup permanent handlers\n this.ws!.addEventListener(\"message\", ((event: any) => {\n const message = event.data;\n this.handleMessage(message);\n }) as any);\n\n this.ws!.addEventListener(\"close\", (() => {\n logger.info(\"WebSocket closed, attempting to reconnect...\");\n for (const handler of this.closeHandlers) {\n handler();\n }\n }) as any);\n\n this.ws!.addEventListener(\"error\", ((_event: Event) => {\n logger.error(\"WebSocket error\");\n const error = new Error(\"WebSocket error\");\n for (const handler of this.errorHandlers) {\n handler(error);\n }\n }) as any);\n });\n }\n\n private handleMessage(message: string): void {\n // Check for reliable message wrapper and auto-send ACK\n try {\n const parsed = JSON.parse(message);\n if (isReliableWrapper(parsed)) {\n // Send ACK immediately\n this.ws!.send(JSON.stringify({ __ack: parsed.__msgId }));\n logger.debug(\"Auto-sent ACK\", { msgId: parsed.__msgId });\n\n // Pass unwrapped payload to handlers\n for (const handler of this.messageHandlers) {\n handler(parsed.__payload);\n }\n return;\n }\n } catch {\n // Not JSON, pass through as normal message\n }\n\n for (const handler of this.messageHandlers) {\n handler(message);\n }\n }\n\n send(message: string): void {\n if (!this.ws || this.ws.readyState !== 1) {\n throw new Error(\"WebSocket is not open\");\n }\n this.ws.send(message);\n }\n\n onMessage(handler: (message: string) => void): Unsubscribe {\n this.messageHandlers.add(handler);\n return () => {\n this.messageHandlers.delete(handler);\n };\n }\n\n onOpen(handler: () => void): Unsubscribe {\n this.openHandlers.add(handler);\n return () => {\n this.openHandlers.delete(handler);\n };\n }\n\n onClose(handler: () => void): Unsubscribe {\n this.closeHandlers.add(handler);\n return () => {\n this.closeHandlers.delete(handler);\n };\n }\n\n onError(handler: (error: Error) => void): Unsubscribe {\n this.errorHandlers.add(handler);\n return () => {\n this.errorHandlers.delete(handler);\n };\n }\n\n close(): void {\n if (this.ws) {\n this.ws.close();\n this.ws = null;\n }\n }\n\n dispose(): void {\n this.close();\n this.messageHandlers.clear();\n this.openHandlers.clear();\n this.closeHandlers.clear();\n this.errorHandlers.clear();\n }\n}\n",
|
|
8
|
+
"/**\n * WebSocket Server - Manages WebSocket connections\n *\n * Supports:\n * - Standalone mode (listen on port)\n * - Attached mode (attach to existing HTTP server)\n */\n\nimport type { WebSocket as WS, WebSocketServer as WSS } from \"ws\";\nimport type {\n ChannelServer,\n ChannelConnection,\n ChannelServerOptions,\n MinimalHTTPServer,\n Unsubscribe,\n} from \"@agentxjs/types/network\";\nimport { createLogger } from \"@agentxjs/common\";\nimport { WebSocketConnection } from \"./WebSocketConnection\";\n\nconst logger = createLogger(\"network/WebSocketServer\");\n\n/**\n * WebSocket Server\n */\nexport class WebSocketServer implements ChannelServer {\n private wss: WSS | null = null;\n private connections = new Set<WebSocketConnection>();\n private connectionHandlers = new Set<(connection: ChannelConnection) => void>();\n private options: ChannelServerOptions;\n private attachedToServer = false;\n\n constructor(options: ChannelServerOptions = {}) {\n this.options = options;\n }\n\n async listen(port: number, host: string = \"0.0.0.0\"): Promise<void> {\n if (this.wss) {\n throw new Error(\"Server already listening\");\n }\n if (this.attachedToServer) {\n throw new Error(\n \"Cannot listen when attached to existing server. The server should call listen() instead.\"\n );\n }\n\n const { WebSocketServer: WSS } = await import(\"ws\");\n this.wss = new WSS({ port, host });\n\n this.wss.on(\"connection\", (ws: WS) => {\n this.handleConnection(ws);\n });\n\n logger.info(\"WebSocket server listening\", { port, host });\n }\n\n attach(server: MinimalHTTPServer, path: string = \"/ws\"): void {\n if (this.wss) {\n throw new Error(\"Server already initialized\");\n }\n\n import(\"ws\").then(({ WebSocketServer: WSS }) => {\n this.wss = new WSS({ noServer: true });\n\n // Handle WebSocket upgrade on the HTTP server\n server.on(\"upgrade\", (request, socket, head) => {\n const url = new URL(request.url || \"\", `http://${request.headers.host}`);\n if (url.pathname === path) {\n this.wss!.handleUpgrade(request as any, socket as any, head as any, (ws: WS) => {\n this.wss!.emit(\"connection\", ws, request);\n });\n } else {\n (socket as any).destroy();\n }\n });\n\n this.wss.on(\"connection\", (ws: WS) => {\n this.handleConnection(ws);\n });\n\n this.attachedToServer = true;\n logger.info(\"WebSocket attached to existing HTTP server\", { path });\n });\n }\n\n private handleConnection(ws: WS): void {\n const connection = new WebSocketConnection(ws, this.options);\n this.connections.add(connection);\n\n logger.info(\"Client connected\", {\n connectionId: connection.id,\n totalConnections: this.connections.size,\n });\n\n connection.onClose(() => {\n this.connections.delete(connection);\n\n logger.info(\"Client disconnected\", {\n connectionId: connection.id,\n totalConnections: this.connections.size,\n });\n });\n\n // Notify handlers\n for (const handler of this.connectionHandlers) {\n handler(connection);\n }\n }\n\n onConnection(handler: (connection: ChannelConnection) => void): Unsubscribe {\n this.connectionHandlers.add(handler);\n return () => {\n this.connectionHandlers.delete(handler);\n };\n }\n\n broadcast(message: string): void {\n for (const connection of this.connections) {\n connection.send(message);\n }\n }\n\n async close(): Promise<void> {\n if (!this.wss) return;\n\n for (const connection of this.connections) {\n connection.close();\n }\n this.connections.clear();\n\n // Don't close the server if attached to existing HTTP server\n if (!this.attachedToServer) {\n await new Promise<void>((resolve) => {\n // Add timeout to prevent hanging\n const timeout = setTimeout(() => {\n logger.warn(\"WebSocket server close timeout, forcing close\");\n resolve();\n }, 1000);\n\n this.wss!.close(() => {\n clearTimeout(timeout);\n resolve();\n });\n });\n }\n this.wss = null;\n logger.info(\"WebSocket server closed\");\n }\n\n async dispose(): Promise<void> {\n await this.close();\n this.connectionHandlers.clear();\n }\n}\n",
|
|
9
|
+
"/**\n * WebSocket Connection - Server-side connection wrapper\n *\n * Handles:\n * - Heartbeat (ping/pong)\n * - Reliable message delivery with ACK\n * - Message routing\n */\n\nimport type { WebSocket as WS } from \"ws\";\nimport type {\n ChannelConnection,\n ChannelServerOptions,\n Unsubscribe,\n SendReliableOptions,\n} from \"@agentxjs/types/network\";\nimport { createLogger } from \"@agentxjs/common\";\nimport { isAckMessage, type ReliableWrapper } from \"../protocol/reliable-message\";\n\nconst logger = createLogger(\"network/WebSocketConnection\");\n\n/**\n * WebSocket connection implementation\n */\nexport class WebSocketConnection implements ChannelConnection {\n public readonly id: string;\n private ws: WS;\n private messageHandlers = new Set<(message: string) => void>();\n private closeHandlers = new Set<() => void>();\n private errorHandlers = new Set<(error: Error) => void>();\n private heartbeatInterval?: ReturnType<typeof setInterval>;\n private isAlive = true;\n private pendingAcks = new Map<\n string,\n { resolve: () => void; timer: ReturnType<typeof setTimeout> }\n >();\n private msgIdCounter = 0;\n\n constructor(ws: WS, options: ChannelServerOptions) {\n this.ws = ws;\n this.id = `conn_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;\n\n this.setupHeartbeat(options);\n this.setupMessageHandler();\n this.setupCloseHandler();\n this.setupErrorHandler();\n }\n\n private setupHeartbeat(options: ChannelServerOptions): void {\n if (options.heartbeat === false) return;\n\n const interval = options.heartbeatInterval || 30000;\n\n this.ws.on(\"pong\", () => {\n this.isAlive = true;\n logger.debug(\"Heartbeat pong received\", { id: this.id });\n });\n\n this.heartbeatInterval = setInterval(() => {\n if (!this.isAlive) {\n logger.warn(\"Client heartbeat timeout, terminating connection\", { id: this.id });\n clearInterval(this.heartbeatInterval);\n this.ws.terminate();\n return;\n }\n this.isAlive = false;\n this.ws.ping();\n logger.debug(\"Heartbeat ping sent\", { id: this.id });\n }, interval);\n }\n\n private setupMessageHandler(): void {\n this.ws.on(\"message\", (data: Buffer) => {\n const message = data.toString();\n\n // Try to parse as JSON to check for ACK messages\n try {\n const parsed = JSON.parse(message);\n\n // Handle ACK response from client\n if (isAckMessage(parsed)) {\n const pending = this.pendingAcks.get(parsed.__ack);\n if (pending) {\n clearTimeout(pending.timer);\n pending.resolve();\n this.pendingAcks.delete(parsed.__ack);\n logger.debug(\"ACK received\", { msgId: parsed.__ack, connectionId: this.id });\n }\n return; // Don't pass ACK messages to application layer\n }\n } catch {\n // Not JSON, pass through as normal message\n }\n\n // Pass message to handlers\n for (const handler of this.messageHandlers) {\n handler(message);\n }\n });\n }\n\n private setupCloseHandler(): void {\n this.ws.on(\"close\", () => {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n }\n for (const handler of this.closeHandlers) {\n handler();\n }\n });\n }\n\n private setupErrorHandler(): void {\n this.ws.on(\"error\", (err: Error) => {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n }\n for (const handler of this.errorHandlers) {\n handler(err);\n }\n });\n }\n\n send(message: string): void {\n if (this.ws.readyState === 1) {\n // WebSocket.OPEN\n this.ws.send(message);\n }\n }\n\n sendReliable(message: string, options?: SendReliableOptions): void {\n if (this.ws.readyState !== 1) {\n // WebSocket not open, trigger timeout immediately if callback provided\n options?.onTimeout?.();\n return;\n }\n\n // If no ACK callback needed, just send normally\n if (!options?.onAck) {\n this.send(message);\n return;\n }\n\n // Generate unique message ID\n const msgId = `${this.id}_${++this.msgIdCounter}`;\n\n // Wrap message with msgId\n const wrapped: ReliableWrapper = {\n __msgId: msgId,\n __payload: message,\n };\n\n // Set up timeout\n const timeout = options.timeout ?? 5000;\n const timer = setTimeout(() => {\n if (this.pendingAcks.has(msgId)) {\n this.pendingAcks.delete(msgId);\n logger.warn(\"ACK timeout\", { msgId, connectionId: this.id, timeout });\n options.onTimeout?.();\n }\n }, timeout);\n\n // Store pending ACK\n this.pendingAcks.set(msgId, {\n resolve: options.onAck,\n timer,\n });\n\n // Send wrapped message\n this.ws.send(JSON.stringify(wrapped));\n logger.debug(\"Sent reliable message\", { msgId, connectionId: this.id });\n }\n\n onMessage(handler: (message: string) => void): Unsubscribe {\n this.messageHandlers.add(handler);\n return () => {\n this.messageHandlers.delete(handler);\n };\n }\n\n onClose(handler: () => void): Unsubscribe {\n this.closeHandlers.add(handler);\n return () => {\n this.closeHandlers.delete(handler);\n };\n }\n\n onError(handler: (error: Error) => void): Unsubscribe {\n this.errorHandlers.add(handler);\n return () => {\n this.errorHandlers.delete(handler);\n };\n }\n\n close(): void {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n }\n // Clean up pending ACKs\n for (const pending of this.pendingAcks.values()) {\n clearTimeout(pending.timer);\n }\n this.pendingAcks.clear();\n this.ws.close();\n }\n}\n",
|
|
10
|
+
"/**\n * @agentxjs/network - Network communication layer\n *\n * Provides WebSocket server and client with reliable message delivery.\n */\n\n// Server exports\nexport { WebSocketServer } from \"./server/WebSocketServer\";\nexport { WebSocketConnection } from \"./server/WebSocketConnection\";\n\n// Client exports\nexport { WebSocketClient } from \"./client/WebSocketClient\";\nexport { BrowserWebSocketClient } from \"./client/BrowserWebSocketClient\";\n\n// Factory\nexport { createWebSocketClient } from \"./factory\";\n\n// Protocol (for advanced usage)\nexport {\n isReliableWrapper,\n isAckMessage,\n type ReliableWrapper,\n type AckMessage,\n} from \"./protocol/reliable-message\";\n\n// Re-export types\nexport type {\n ChannelServer,\n ChannelClient,\n ChannelConnection,\n ChannelClientOptions,\n ChannelServerOptions,\n SendReliableOptions,\n Unsubscribe,\n} from \"@agentxjs/types/network\";\n",
|
|
11
|
+
"/**\n * WebSocket Client Factory\n *\n * Creates the appropriate WebSocket client based on environment.\n */\n\nimport type { ChannelClient, ChannelClientOptions } from \"@agentxjs/types/network\";\n\n// Detect browser environment\nconst isBrowser =\n typeof globalThis !== \"undefined\" &&\n typeof (globalThis as any).window !== \"undefined\" &&\n typeof (globalThis as any).window.WebSocket !== \"undefined\";\n\n/**\n * Factory function to create the appropriate WebSocket client\n *\n * @param options - Client configuration\n * @returns Connected WebSocket client\n */\nexport async function createWebSocketClient(options: ChannelClientOptions): Promise<ChannelClient> {\n if (isBrowser) {\n const { BrowserWebSocketClient } = await import(\"./client/BrowserWebSocketClient\");\n const client = new BrowserWebSocketClient(options);\n await client.connect();\n return client;\n } else {\n const { WebSocketClient } = await import(\"./client/WebSocketClient\");\n const client = new WebSocketClient(options);\n await client.connect();\n return client;\n }\n}\n"
|
|
7
12
|
],
|
|
8
|
-
"mappings": "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",
|
|
9
|
-
"debugId": "
|
|
13
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BO,SAAS,YAAY,CAAC,MAAmC;AAAA,EAC9D,OAAO,OAAO,SAAS,YAAY,SAAS,QAAQ,WAAW;AAAA;AAM1D,SAAS,iBAAiB,CAAC,MAAwC;AAAA,EACxE,OAAO,OAAO,SAAS,YAAY,SAAS,QAAQ,aAAa,QAAQ,eAAe;AAAA;;;;;;;ACzB1F,yBAAS;AAAA;AAQF,MAAM,gBAAyC;AAAA,EAC5C,KAAuB;AAAA,EACvB;AAAA,EACA;AAAA,EAGA,kBAAkB,IAAI;AAAA,EACtB,eAAe,IAAI;AAAA,EACnB,gBAAgB,IAAI;AAAA,EACpB,gBAAgB,IAAI;AAAA,EAE5B,WAAW,CAAC,SAA+B;AAAA,IACzC,KAAK,YAAY,QAAQ;AAAA,IACzB,KAAK,UAAU,QAAQ;AAAA;AAAA,MAGrB,UAAU,GAAiD;AAAA,IAC7D,IAAI,CAAC,KAAK;AAAA,MAAI,OAAO;AAAA,IACrB,MAAM,QAAQ,KAAK,GAAG;AAAA,IACtB,IAAI,UAAU;AAAA,MAAG,OAAO;AAAA,IACxB,IAAI,UAAU;AAAA,MAAG,OAAO;AAAA,IACxB,IAAI,UAAU;AAAA,MAAG,OAAO;AAAA,IACxB,OAAO;AAAA;AAAA,OAGH,QAAO,GAAkB;AAAA,IAC7B,IAAI,KAAK,IAAI;AAAA,MACX,MAAM,IAAI,MAAM,iCAAiC;AAAA,IACnD;AAAA,IAEA,QAAQ,WAAW,kBAAkB,MAAa;AAAA,IAGlD,IAAI;AAAA,IACJ,IAAI,KAAK,SAAS;AAAA,MAChB,IAAI,OAAO,KAAK,YAAY,YAAY;AAAA,QACtC,kBAAkB,MAAM,QAAQ,QAAQ,KAAK,QAAQ,CAAC;AAAA,MACxD,EAAO;AAAA,QACL,kBAAkB,KAAK;AAAA;AAAA,IAE3B;AAAA,IAGA,KAAK,KAAK,IAAI,cAAc,KAAK,WAAW;AAAA,MAC1C,SAAS;AAAA,IACX,CAAC;AAAA,IAED,OAAO,IAAI,QAAc,CAAC,SAAS,WAAW;AAAA,MAC5C,MAAM,SAAS,MAAM;AAAA,QACnB,QAAO,KAAK,uBAAuB,EAAE,WAAW,KAAK,UAAU,CAAC;AAAA,QAChE,WAAW,WAAW,KAAK,cAAc;AAAA,UACvC,QAAQ;AAAA,QACV;AAAA,QACA,QAAQ;AAAA;AAAA,MAGV,MAAM,UAAU,CAAC,QAAgB;AAAA,QAC/B,QAAO,MAAM,+BAA+B;AAAA,UAC1C,WAAW,KAAK;AAAA,UAChB,OAAO,KAAK;AAAA,QACd,CAAC;AAAA,QACD,OAAO,OAAO,IAAI,MAAM,6BAA6B,CAAC;AAAA;AAAA,MAGvD,KAAK,GAAW,KAAK,QAAQ,MAAM;AAAA,MACnC,KAAK,GAAW,KAAK,SAAS,OAAO;AAAA,MAGrC,KAAK,GAAW,GAAG,WAAW,CAAC,SAAiB;AAAA,QAC/C,MAAM,UAAU,KAAK,SAAS;AAAA,QAC9B,KAAK,cAAc,OAAO;AAAA,OAC3B;AAAA,MAEA,KAAK,GAAW,GAAG,SAAS,MAAM;AAAA,QACjC,QAAO,KAAK,kBAAkB;AAAA,QAC9B,WAAW,WAAW,KAAK,eAAe;AAAA,UACxC,QAAQ;AAAA,QACV;AAAA,OACD;AAAA,MAEA,KAAK,GAAW,GAAG,SAAS,CAAC,QAAe;AAAA,QAC3C,QAAO,MAAM,mBAAmB,EAAE,OAAO,IAAI,QAAQ,CAAC;AAAA,QACtD,WAAW,WAAW,KAAK,eAAe;AAAA,UACxC,QAAQ,GAAG;AAAA,QACb;AAAA,OACD;AAAA,KACF;AAAA;AAAA,EAGK,aAAa,CAAC,SAAuB;AAAA,IAE3C,IAAI;AAAA,MACF,MAAM,SAAS,KAAK,MAAM,OAAO;AAAA,MACjC,IAAI,kBAAkB,MAAM,GAAG;AAAA,QAE7B,KAAK,GAAI,KAAK,KAAK,UAAU,EAAE,OAAO,OAAO,QAAQ,CAAC,CAAC;AAAA,QACvD,QAAO,MAAM,iBAAiB,EAAE,OAAO,OAAO,QAAQ,CAAC;AAAA,QAGvD,WAAW,WAAW,KAAK,iBAAiB;AAAA,UAC1C,QAAQ,OAAO,SAAS;AAAA,QAC1B;AAAA,QACA;AAAA,MACF;AAAA,MACA,MAAM;AAAA,IAIR,WAAW,WAAW,KAAK,iBAAiB;AAAA,MAC1C,QAAQ,OAAO;AAAA,IACjB;AAAA;AAAA,EAGF,IAAI,CAAC,SAAuB;AAAA,IAC1B,IAAI,CAAC,KAAK,MAAM,KAAK,GAAG,eAAe,GAAG;AAAA,MACxC,MAAM,IAAI,MAAM,uBAAuB;AAAA,IACzC;AAAA,IACA,KAAK,GAAG,KAAK,OAAO;AAAA;AAAA,EAGtB,SAAS,CAAC,SAAiD;AAAA,IACzD,KAAK,gBAAgB,IAAI,OAAO;AAAA,IAChC,OAAO,MAAM;AAAA,MACX,KAAK,gBAAgB,OAAO,OAAO;AAAA;AAAA;AAAA,EAIvC,MAAM,CAAC,SAAkC;AAAA,IACvC,KAAK,aAAa,IAAI,OAAO;AAAA,IAC7B,OAAO,MAAM;AAAA,MACX,KAAK,aAAa,OAAO,OAAO;AAAA;AAAA;AAAA,EAIpC,OAAO,CAAC,SAAkC;AAAA,IACxC,KAAK,cAAc,IAAI,OAAO;AAAA,IAC9B,OAAO,MAAM;AAAA,MACX,KAAK,cAAc,OAAO,OAAO;AAAA;AAAA;AAAA,EAIrC,OAAO,CAAC,SAA8C;AAAA,IACpD,KAAK,cAAc,IAAI,OAAO;AAAA,IAC9B,OAAO,MAAM;AAAA,MACX,KAAK,cAAc,OAAO,OAAO;AAAA;AAAA;AAAA,EAIrC,KAAK,GAAS;AAAA,IACZ,IAAI,KAAK,IAAI;AAAA,MACX,KAAK,GAAG,MAAM;AAAA,MACd,KAAK,KAAK;AAAA,IACZ;AAAA;AAAA,EAGF,OAAO,GAAS;AAAA,IACd,KAAK,MAAM;AAAA,IACX,KAAK,gBAAgB,MAAM;AAAA,IAC3B,KAAK,aAAa,MAAM;AAAA,IACxB,KAAK,cAAc,MAAM;AAAA,IACzB,KAAK,cAAc,MAAM;AAAA;AAE7B;AAAA,IAvKM;AAAA;AAAA,YAAS,cAAa,yBAAyB;AAAA;;;;;;;ACFrD,yBAAS;AAAA;AAQF,MAAM,uBAAgD;AAAA,EACnD,KAAuB;AAAA,EACvB;AAAA,EACA;AAAA,EACA,kBAAkB,IAAI;AAAA,EACtB,eAAe,IAAI;AAAA,EACnB,gBAAgB,IAAI;AAAA,EACpB,gBAAgB,IAAI;AAAA,EACpB,qBAAqB;AAAA,EAE7B,WAAW,CAAC,SAA+B;AAAA,IACzC,KAAK,YAAY,QAAQ;AAAA,IACzB,KAAK,UAAU;AAAA,MACb,eAAe;AAAA,MACf,sBAAsB;AAAA,MACtB,sBAAsB;AAAA,MACtB,YAAY;AAAA,MACZ,mBAAmB;AAAA,MACnB,OAAO;AAAA,SACJ;AAAA,IACL;AAAA;AAAA,MAGE,UAAU,GAAiD;AAAA,IAC7D,IAAI,CAAC,KAAK;AAAA,MAAI,OAAO;AAAA,IACrB,MAAM,QAAQ,KAAK,GAAG;AAAA,IACtB,IAAI,UAAU;AAAA,MAAG,OAAO;AAAA,IACxB,IAAI,UAAU;AAAA,MAAG,OAAO;AAAA,IACxB,IAAI,UAAU;AAAA,MAAG,OAAO;AAAA,IACxB,OAAO;AAAA;AAAA,OAGH,QAAO,GAAkB;AAAA,IAC7B,IAAI,KAAK,IAAI;AAAA,MACX,MAAM,IAAI,MAAM,iCAAiC;AAAA,IACnD;AAAA,IAGA,IAAI;AAAA,IACJ,IAAI,KAAK,QAAQ,SAAS;AAAA,MACxB,IAAI,OAAO,KAAK,QAAQ,YAAY,YAAY;AAAA,QAC9C,kBAAkB,MAAM,QAAQ,QAAQ,KAAK,QAAQ,QAAQ,CAAC;AAAA,MAChE,EAAO;AAAA,QACL,kBAAkB,KAAK,QAAQ;AAAA;AAAA,IAEnC;AAAA,IAEA,QAAO,MAAM,2BAA2B;AAAA,MACtC,WAAW,KAAK;AAAA,MAChB,eAAe,KAAK,QAAQ;AAAA,MAC5B,mBAAmB,KAAK,QAAQ;AAAA,IAClC,CAAC;AAAA,IAED,IAAI,KAAK,QAAQ,eAAe;AAAA,MAE9B,MAAM,yBAAyB,MAAa,kCAA2B;AAAA,MACvE,QAAO,MAAM,6BAA6B;AAAA,MAC1C,KAAK,KAAK,IAAI,sBAAsB,KAAK,WAAW,CAAC,GAAG;AAAA,QACtD,sBAAsB,KAAK,QAAQ;AAAA,QACnC,sBAAsB,KAAK,QAAQ;AAAA,QACnC,6BAA6B;AAAA,QAC7B,mBAAmB,KAAK,QAAQ;AAAA,QAChC,YAAY,KAAK,QAAQ;AAAA,QACzB,OAAO,KAAK,QAAQ;AAAA,MACtB,CAAC;AAAA,IACH,EAAO;AAAA,MAEL,QAAO,MAAM,wBAAwB;AAAA,MACrC,KAAK,KAAK,IAAI,UAAU,KAAK,SAAS;AAAA;AAAA,IAGxC,OAAO,IAAI,QAAc,CAAC,SAAS,WAAW;AAAA,MAC5C,MAAM,SAAS,YAAY;AAAA,QACzB,IAAI,KAAK,oBAAoB;AAAA,UAC3B,QAAO,KAAK,sCAAsC,EAAE,WAAW,KAAK,UAAU,CAAC;AAAA,QACjF,EAAO;AAAA,UACL,QAAO,KAAK,uBAAuB,EAAE,WAAW,KAAK,UAAU,CAAC;AAAA,UAChE,KAAK,qBAAqB;AAAA;AAAA,QAK5B,IAAI,mBAAmB,OAAO,KAAK,eAAe,EAAE,SAAS,GAAG;AAAA,UAC9D,IAAI;AAAA,YACF,MAAM,cAAc,KAAK,UAAU;AAAA,cACjC,MAAM;AAAA,cACN,SAAS;AAAA,YACX,CAAC;AAAA,YACD,KAAK,GAAI,KAAK,WAAW;AAAA,YACzB,QAAO,KAAK,uCAAuC;AAAA,YACnD,OAAO,OAAO;AAAA,YACd,QAAO,MAAM,yCAAyC,EAAE,MAAM,CAAC;AAAA;AAAA,QAEnE;AAAA,QAEA,WAAW,WAAW,KAAK,cAAc;AAAA,UACvC,QAAQ;AAAA,QACV;AAAA,QACA,QAAQ;AAAA;AAAA,MAGV,MAAM,UAAU,CAAC,WAAkB;AAAA,QACjC,QAAO,MAAM,+BAA+B,EAAE,WAAW,KAAK,UAAU,CAAC;AAAA,QACzE,MAAM,QAAQ,IAAI,MAAM,6BAA6B;AAAA,QACrD,WAAW,WAAW,KAAK,eAAe;AAAA,UACxC,QAAQ,KAAK;AAAA,QACf;AAAA,QACA,OAAO,KAAK;AAAA;AAAA,MAGd,KAAK,GAAI,iBAAiB,QAAQ,QAAe,EAAE,MAAM,KAAK,CAAC;AAAA,MAC/D,KAAK,GAAI,iBAAiB,SAAS,SAAgB,EAAE,MAAM,KAAK,CAAC;AAAA,MAGjE,KAAK,GAAI,iBAAiB,WAAY,CAAC,UAAe;AAAA,QACpD,MAAM,UAAU,MAAM;AAAA,QACtB,KAAK,cAAc,OAAO;AAAA,OACnB;AAAA,MAET,KAAK,GAAI,iBAAiB,SAAU,MAAM;AAAA,QACxC,QAAO,KAAK,8CAA8C;AAAA,QAC1D,WAAW,WAAW,KAAK,eAAe;AAAA,UACxC,QAAQ;AAAA,QACV;AAAA,OACO;AAAA,MAET,KAAK,GAAI,iBAAiB,SAAU,CAAC,WAAkB;AAAA,QACrD,QAAO,MAAM,iBAAiB;AAAA,QAC9B,MAAM,QAAQ,IAAI,MAAM,iBAAiB;AAAA,QACzC,WAAW,WAAW,KAAK,eAAe;AAAA,UACxC,QAAQ,KAAK;AAAA,QACf;AAAA,OACO;AAAA,KACV;AAAA;AAAA,EAGK,aAAa,CAAC,SAAuB;AAAA,IAE3C,IAAI;AAAA,MACF,MAAM,SAAS,KAAK,MAAM,OAAO;AAAA,MACjC,IAAI,kBAAkB,MAAM,GAAG;AAAA,QAE7B,KAAK,GAAI,KAAK,KAAK,UAAU,EAAE,OAAO,OAAO,QAAQ,CAAC,CAAC;AAAA,QACvD,QAAO,MAAM,iBAAiB,EAAE,OAAO,OAAO,QAAQ,CAAC;AAAA,QAGvD,WAAW,WAAW,KAAK,iBAAiB;AAAA,UAC1C,QAAQ,OAAO,SAAS;AAAA,QAC1B;AAAA,QACA;AAAA,MACF;AAAA,MACA,MAAM;AAAA,IAIR,WAAW,WAAW,KAAK,iBAAiB;AAAA,MAC1C,QAAQ,OAAO;AAAA,IACjB;AAAA;AAAA,EAGF,IAAI,CAAC,SAAuB;AAAA,IAC1B,IAAI,CAAC,KAAK,MAAM,KAAK,GAAG,eAAe,GAAG;AAAA,MACxC,MAAM,IAAI,MAAM,uBAAuB;AAAA,IACzC;AAAA,IACA,KAAK,GAAG,KAAK,OAAO;AAAA;AAAA,EAGtB,SAAS,CAAC,SAAiD;AAAA,IACzD,KAAK,gBAAgB,IAAI,OAAO;AAAA,IAChC,OAAO,MAAM;AAAA,MACX,KAAK,gBAAgB,OAAO,OAAO;AAAA;AAAA;AAAA,EAIvC,MAAM,CAAC,SAAkC;AAAA,IACvC,KAAK,aAAa,IAAI,OAAO;AAAA,IAC7B,OAAO,MAAM;AAAA,MACX,KAAK,aAAa,OAAO,OAAO;AAAA;AAAA;AAAA,EAIpC,OAAO,CAAC,SAAkC;AAAA,IACxC,KAAK,cAAc,IAAI,OAAO;AAAA,IAC9B,OAAO,MAAM;AAAA,MACX,KAAK,cAAc,OAAO,OAAO;AAAA;AAAA;AAAA,EAIrC,OAAO,CAAC,SAA8C;AAAA,IACpD,KAAK,cAAc,IAAI,OAAO;AAAA,IAC9B,OAAO,MAAM;AAAA,MACX,KAAK,cAAc,OAAO,OAAO;AAAA;AAAA;AAAA,EAIrC,KAAK,GAAS;AAAA,IACZ,IAAI,KAAK,IAAI;AAAA,MACX,KAAK,GAAG,MAAM;AAAA,MACd,KAAK,KAAK;AAAA,IACZ;AAAA;AAAA,EAGF,OAAO,GAAS;AAAA,IACd,KAAK,MAAM;AAAA,IACX,KAAK,gBAAgB,MAAM;AAAA,IAC3B,KAAK,aAAa,MAAM;AAAA,IACxB,KAAK,cAAc,MAAM;AAAA,IACzB,KAAK,cAAc,MAAM;AAAA;AAE7B;AAAA,IAtNM;AAAA;AAAA,YAAS,cAAa,gCAAgC;AAAA;;;ACE5D,yBAAS;;;ACAT;AAGA,IAAM,SAAS,aAAa,6BAA6B;AAAA;AAKlD,MAAM,oBAAiD;AAAA,EAC5C;AAAA,EACR;AAAA,EACA,kBAAkB,IAAI;AAAA,EACtB,gBAAgB,IAAI;AAAA,EACpB,gBAAgB,IAAI;AAAA,EACpB;AAAA,EACA,UAAU;AAAA,EACV,cAAc,IAAI;AAAA,EAIlB,eAAe;AAAA,EAEvB,WAAW,CAAC,IAAQ,SAA+B;AAAA,IACjD,KAAK,KAAK;AAAA,IACV,KAAK,KAAK,QAAQ,KAAK,IAAI,KAAK,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,GAAG,CAAC;AAAA,IAEzE,KAAK,eAAe,OAAO;AAAA,IAC3B,KAAK,oBAAoB;AAAA,IACzB,KAAK,kBAAkB;AAAA,IACvB,KAAK,kBAAkB;AAAA;AAAA,EAGjB,cAAc,CAAC,SAAqC;AAAA,IAC1D,IAAI,QAAQ,cAAc;AAAA,MAAO;AAAA,IAEjC,MAAM,WAAW,QAAQ,qBAAqB;AAAA,IAE9C,KAAK,GAAG,GAAG,QAAQ,MAAM;AAAA,MACvB,KAAK,UAAU;AAAA,MACf,OAAO,MAAM,2BAA2B,EAAE,IAAI,KAAK,GAAG,CAAC;AAAA,KACxD;AAAA,IAED,KAAK,oBAAoB,YAAY,MAAM;AAAA,MACzC,IAAI,CAAC,KAAK,SAAS;AAAA,QACjB,OAAO,KAAK,oDAAoD,EAAE,IAAI,KAAK,GAAG,CAAC;AAAA,QAC/E,cAAc,KAAK,iBAAiB;AAAA,QACpC,KAAK,GAAG,UAAU;AAAA,QAClB;AAAA,MACF;AAAA,MACA,KAAK,UAAU;AAAA,MACf,KAAK,GAAG,KAAK;AAAA,MACb,OAAO,MAAM,uBAAuB,EAAE,IAAI,KAAK,GAAG,CAAC;AAAA,OAClD,QAAQ;AAAA;AAAA,EAGL,mBAAmB,GAAS;AAAA,IAClC,KAAK,GAAG,GAAG,WAAW,CAAC,SAAiB;AAAA,MACtC,MAAM,UAAU,KAAK,SAAS;AAAA,MAG9B,IAAI;AAAA,QACF,MAAM,SAAS,KAAK,MAAM,OAAO;AAAA,QAGjC,IAAI,aAAa,MAAM,GAAG;AAAA,UACxB,MAAM,UAAU,KAAK,YAAY,IAAI,OAAO,KAAK;AAAA,UACjD,IAAI,SAAS;AAAA,YACX,aAAa,QAAQ,KAAK;AAAA,YAC1B,QAAQ,QAAQ;AAAA,YAChB,KAAK,YAAY,OAAO,OAAO,KAAK;AAAA,YACpC,OAAO,MAAM,gBAAgB,EAAE,OAAO,OAAO,OAAO,cAAc,KAAK,GAAG,CAAC;AAAA,UAC7E;AAAA,UACA;AAAA,QACF;AAAA,QACA,MAAM;AAAA,MAKR,WAAW,WAAW,KAAK,iBAAiB;AAAA,QAC1C,QAAQ,OAAO;AAAA,MACjB;AAAA,KACD;AAAA;AAAA,EAGK,iBAAiB,GAAS;AAAA,IAChC,KAAK,GAAG,GAAG,SAAS,MAAM;AAAA,MACxB,IAAI,KAAK,mBAAmB;AAAA,QAC1B,cAAc,KAAK,iBAAiB;AAAA,MACtC;AAAA,MACA,WAAW,WAAW,KAAK,eAAe;AAAA,QACxC,QAAQ;AAAA,MACV;AAAA,KACD;AAAA;AAAA,EAGK,iBAAiB,GAAS;AAAA,IAChC,KAAK,GAAG,GAAG,SAAS,CAAC,QAAe;AAAA,MAClC,IAAI,KAAK,mBAAmB;AAAA,QAC1B,cAAc,KAAK,iBAAiB;AAAA,MACtC;AAAA,MACA,WAAW,WAAW,KAAK,eAAe;AAAA,QACxC,QAAQ,GAAG;AAAA,MACb;AAAA,KACD;AAAA;AAAA,EAGH,IAAI,CAAC,SAAuB;AAAA,IAC1B,IAAI,KAAK,GAAG,eAAe,GAAG;AAAA,MAE5B,KAAK,GAAG,KAAK,OAAO;AAAA,IACtB;AAAA;AAAA,EAGF,YAAY,CAAC,SAAiB,SAAqC;AAAA,IACjE,IAAI,KAAK,GAAG,eAAe,GAAG;AAAA,MAE5B,SAAS,YAAY;AAAA,MACrB;AAAA,IACF;AAAA,IAGA,IAAI,CAAC,SAAS,OAAO;AAAA,MACnB,KAAK,KAAK,OAAO;AAAA,MACjB;AAAA,IACF;AAAA,IAGA,MAAM,QAAQ,GAAG,KAAK,MAAM,EAAE,KAAK;AAAA,IAGnC,MAAM,UAA2B;AAAA,MAC/B,SAAS;AAAA,MACT,WAAW;AAAA,IACb;AAAA,IAGA,MAAM,UAAU,QAAQ,WAAW;AAAA,IACnC,MAAM,QAAQ,WAAW,MAAM;AAAA,MAC7B,IAAI,KAAK,YAAY,IAAI,KAAK,GAAG;AAAA,QAC/B,KAAK,YAAY,OAAO,KAAK;AAAA,QAC7B,OAAO,KAAK,eAAe,EAAE,OAAO,cAAc,KAAK,IAAI,QAAQ,CAAC;AAAA,QACpE,QAAQ,YAAY;AAAA,MACtB;AAAA,OACC,OAAO;AAAA,IAGV,KAAK,YAAY,IAAI,OAAO;AAAA,MAC1B,SAAS,QAAQ;AAAA,MACjB;AAAA,IACF,CAAC;AAAA,IAGD,KAAK,GAAG,KAAK,KAAK,UAAU,OAAO,CAAC;AAAA,IACpC,OAAO,MAAM,yBAAyB,EAAE,OAAO,cAAc,KAAK,GAAG,CAAC;AAAA;AAAA,EAGxE,SAAS,CAAC,SAAiD;AAAA,IACzD,KAAK,gBAAgB,IAAI,OAAO;AAAA,IAChC,OAAO,MAAM;AAAA,MACX,KAAK,gBAAgB,OAAO,OAAO;AAAA;AAAA;AAAA,EAIvC,OAAO,CAAC,SAAkC;AAAA,IACxC,KAAK,cAAc,IAAI,OAAO;AAAA,IAC9B,OAAO,MAAM;AAAA,MACX,KAAK,cAAc,OAAO,OAAO;AAAA;AAAA;AAAA,EAIrC,OAAO,CAAC,SAA8C;AAAA,IACpD,KAAK,cAAc,IAAI,OAAO;AAAA,IAC9B,OAAO,MAAM;AAAA,MACX,KAAK,cAAc,OAAO,OAAO;AAAA;AAAA;AAAA,EAIrC,KAAK,GAAS;AAAA,IACZ,IAAI,KAAK,mBAAmB;AAAA,MAC1B,cAAc,KAAK,iBAAiB;AAAA,IACtC;AAAA,IAEA,WAAW,WAAW,KAAK,YAAY,OAAO,GAAG;AAAA,MAC/C,aAAa,QAAQ,KAAK;AAAA,IAC5B;AAAA,IACA,KAAK,YAAY,MAAM;AAAA,IACvB,KAAK,GAAG,MAAM;AAAA;AAElB;;;AD1LA,IAAM,UAAS,cAAa,yBAAyB;AAAA;AAK9C,MAAM,gBAAyC;AAAA,EAC5C,MAAkB;AAAA,EAClB,cAAc,IAAI;AAAA,EAClB,qBAAqB,IAAI;AAAA,EACzB;AAAA,EACA,mBAAmB;AAAA,EAE3B,WAAW,CAAC,UAAgC,CAAC,GAAG;AAAA,IAC9C,KAAK,UAAU;AAAA;AAAA,OAGX,OAAM,CAAC,MAAc,OAAe,WAA0B;AAAA,IAClE,IAAI,KAAK,KAAK;AAAA,MACZ,MAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAAA,IACA,IAAI,KAAK,kBAAkB;AAAA,MACzB,MAAM,IAAI,MACR,0FACF;AAAA,IACF;AAAA,IAEA,QAAQ,iBAAiB,QAAQ,MAAa;AAAA,IAC9C,KAAK,MAAM,IAAI,IAAI,EAAE,MAAM,KAAK,CAAC;AAAA,IAEjC,KAAK,IAAI,GAAG,cAAc,CAAC,OAAW;AAAA,MACpC,KAAK,iBAAiB,EAAE;AAAA,KACzB;AAAA,IAED,QAAO,KAAK,8BAA8B,EAAE,MAAM,KAAK,CAAC;AAAA;AAAA,EAG1D,MAAM,CAAC,QAA2B,OAAe,OAAa;AAAA,IAC5D,IAAI,KAAK,KAAK;AAAA,MACZ,MAAM,IAAI,MAAM,4BAA4B;AAAA,IAC9C;AAAA,IAEO,aAAM,KAAK,GAAG,iBAAiB,UAAU;AAAA,MAC9C,KAAK,MAAM,IAAI,IAAI,EAAE,UAAU,KAAK,CAAC;AAAA,MAGrC,OAAO,GAAG,WAAW,CAAC,SAAS,QAAQ,SAAS;AAAA,QAC9C,MAAM,MAAM,IAAI,IAAI,QAAQ,OAAO,IAAI,UAAU,QAAQ,QAAQ,MAAM;AAAA,QACvE,IAAI,IAAI,aAAa,MAAM;AAAA,UACzB,KAAK,IAAK,cAAc,SAAgB,QAAe,MAAa,CAAC,OAAW;AAAA,YAC9E,KAAK,IAAK,KAAK,cAAc,IAAI,OAAO;AAAA,WACzC;AAAA,QACH,EAAO;AAAA,UACJ,OAAe,QAAQ;AAAA;AAAA,OAE3B;AAAA,MAED,KAAK,IAAI,GAAG,cAAc,CAAC,OAAW;AAAA,QACpC,KAAK,iBAAiB,EAAE;AAAA,OACzB;AAAA,MAED,KAAK,mBAAmB;AAAA,MACxB,QAAO,KAAK,8CAA8C,EAAE,KAAK,CAAC;AAAA,KACnE;AAAA;AAAA,EAGK,gBAAgB,CAAC,IAAc;AAAA,IACrC,MAAM,aAAa,IAAI,oBAAoB,IAAI,KAAK,OAAO;AAAA,IAC3D,KAAK,YAAY,IAAI,UAAU;AAAA,IAE/B,QAAO,KAAK,oBAAoB;AAAA,MAC9B,cAAc,WAAW;AAAA,MACzB,kBAAkB,KAAK,YAAY;AAAA,IACrC,CAAC;AAAA,IAED,WAAW,QAAQ,MAAM;AAAA,MACvB,KAAK,YAAY,OAAO,UAAU;AAAA,MAElC,QAAO,KAAK,uBAAuB;AAAA,QACjC,cAAc,WAAW;AAAA,QACzB,kBAAkB,KAAK,YAAY;AAAA,MACrC,CAAC;AAAA,KACF;AAAA,IAGD,WAAW,WAAW,KAAK,oBAAoB;AAAA,MAC7C,QAAQ,UAAU;AAAA,IACpB;AAAA;AAAA,EAGF,YAAY,CAAC,SAA+D;AAAA,IAC1E,KAAK,mBAAmB,IAAI,OAAO;AAAA,IACnC,OAAO,MAAM;AAAA,MACX,KAAK,mBAAmB,OAAO,OAAO;AAAA;AAAA;AAAA,EAI1C,SAAS,CAAC,SAAuB;AAAA,IAC/B,WAAW,cAAc,KAAK,aAAa;AAAA,MACzC,WAAW,KAAK,OAAO;AAAA,IACzB;AAAA;AAAA,OAGI,MAAK,GAAkB;AAAA,IAC3B,IAAI,CAAC,KAAK;AAAA,MAAK;AAAA,IAEf,WAAW,cAAc,KAAK,aAAa;AAAA,MACzC,WAAW,MAAM;AAAA,IACnB;AAAA,IACA,KAAK,YAAY,MAAM;AAAA,IAGvB,IAAI,CAAC,KAAK,kBAAkB;AAAA,MAC1B,MAAM,IAAI,QAAc,CAAC,YAAY;AAAA,QAEnC,MAAM,UAAU,WAAW,MAAM;AAAA,UAC/B,QAAO,KAAK,+CAA+C;AAAA,UAC3D,QAAQ;AAAA,WACP,IAAI;AAAA,QAEP,KAAK,IAAK,MAAM,MAAM;AAAA,UACpB,aAAa,OAAO;AAAA,UACpB,QAAQ;AAAA,SACT;AAAA,OACF;AAAA,IACH;AAAA,IACA,KAAK,MAAM;AAAA,IACX,QAAO,KAAK,yBAAyB;AAAA;AAAA,OAGjC,QAAO,GAAkB;AAAA,IAC7B,MAAM,KAAK,MAAM;AAAA,IACjB,KAAK,mBAAmB,MAAM;AAAA;AAElC;;;AE7IA;AACA;;;ACHA,IAAM,YACJ,OAAO,eAAe,eACtB,OAAQ,WAAmB,WAAW,eACtC,OAAQ,WAAmB,OAAO,cAAc;AAQlD,eAAsB,qBAAqB,CAAC,SAAuD;AAAA,EACjG,IAAI,WAAW;AAAA,IACb,QAAQ,oDAA2B;AAAA,IACnC,MAAM,SAAS,IAAI,wBAAuB,OAAO;AAAA,IACjD,MAAM,OAAO,QAAQ;AAAA,IACrB,OAAO;AAAA,EACT,EAAO;AAAA,IACL,QAAQ,sCAAoB;AAAA,IAC5B,MAAM,SAAS,IAAI,iBAAgB,OAAO;AAAA,IAC1C,MAAM,OAAO,QAAQ;AAAA,IACrB,OAAO;AAAA;AAAA;",
|
|
14
|
+
"debugId": "41D375A37CDC1ED664756E2164756E21",
|
|
10
15
|
"names": []
|
|
11
16
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentxjs/network",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.0",
|
|
4
4
|
"description": "Network layer abstraction for AgentX platform - WebSocket client/server with heartbeat and auto-reconnect",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agentx",
|
|
@@ -35,11 +35,13 @@
|
|
|
35
35
|
"build": "bun run build.ts",
|
|
36
36
|
"lint": "eslint .",
|
|
37
37
|
"typecheck": "tsc --noEmit",
|
|
38
|
-
"clean": "rm -rf dist"
|
|
38
|
+
"clean": "rm -rf dist",
|
|
39
|
+
"test": "bun test",
|
|
40
|
+
"test:watch": "bun test --watch"
|
|
39
41
|
},
|
|
40
42
|
"dependencies": {
|
|
41
|
-
"@agentxjs/common": "^1.
|
|
42
|
-
"@agentxjs/types": "^1.
|
|
43
|
+
"@agentxjs/common": "^1.9.0",
|
|
44
|
+
"@agentxjs/types": "^1.9.0",
|
|
43
45
|
"reconnecting-websocket": "^4.4.0",
|
|
44
46
|
"ws": "^8.18.0"
|
|
45
47
|
},
|