@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 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 { ChannelClient, ChannelClientOptions, Unsubscribe as Unsubscribe2 } from "@agentxjs/types/network";
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 Client (Node.js version - no auto-reconnect)
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): Unsubscribe2;
37
- onOpen(handler: () => void): Unsubscribe2;
38
- onClose(handler: () => void): Unsubscribe2;
39
- onError(handler: (error: Error) => void): Unsubscribe2;
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 createWebSocketClient(options: ChannelClientOptions): Promise<ChannelClient>;
47
- import { ChannelServer as ChannelServer2, ChannelClient as ChannelClient2, ChannelConnection as ChannelConnection2, ChannelClientOptions as ChannelClientOptions2, ChannelServerOptions as ChannelServerOptions2, Unsubscribe as Unsubscribe3 } from "@agentxjs/types/network";
48
- export { createWebSocketClient, WebSocketServer, WebSocketClient, Unsubscribe3 as Unsubscribe, ChannelServerOptions2 as ChannelServerOptions, ChannelServer2 as ChannelServer, ChannelConnection2 as ChannelConnection, ChannelClientOptions2 as ChannelClientOptions, ChannelClient2 as ChannelClient };
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/WebSocketServer.ts
26
- import { createLogger } from "@agentxjs/common";
27
- var logger = createLogger("network/WebSocketServer");
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
- class WebSocketServer {
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
- // src/WebSocketClient.ts
207
- import { createLogger as createLogger2 } from "@agentxjs/common";
208
- var logger2 = createLogger2("network/WebSocketClient");
209
- var isBrowser = typeof globalThis !== "undefined" && typeof globalThis.window !== "undefined" && typeof globalThis.window.WebSocket !== "undefined";
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
- logger2.info("WebSocket connected", { serverUrl: this.serverUrl });
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
- logger2.error("WebSocket connection failed", {
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
- for (const handler of this.messageHandlers) {
274
- handler(message);
275
- }
109
+ this.handleMessage(message);
276
110
  });
277
111
  this.ws.on("close", () => {
278
- logger2.warn("WebSocket closed");
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
- logger2.error("WebSocket error", { error: err.message });
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
- logger2.debug("Connecting to WebSocket", {
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
- logger2.debug("Using ReconnectingWebSocket");
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
- logger2.debug("Using native WebSocket");
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
- logger2.info("WebSocket reconnected successfully", { serverUrl: this.serverUrl });
265
+ logger4.info("WebSocket reconnected successfully", { serverUrl: this.serverUrl });
408
266
  } else {
409
- logger2.info("WebSocket connected", { serverUrl: this.serverUrl });
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
- logger2.info("Sent authentication message to server");
277
+ logger4.info("Sent authentication message to server");
420
278
  } catch (error) {
421
- logger2.error("Failed to send authentication message", { error });
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
- logger2.error("WebSocket connection failed", { serverUrl: this.serverUrl });
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
- for (const handler of this.messageHandlers) {
442
- handler(message);
443
- }
299
+ this.handleMessage(message);
444
300
  });
445
301
  this.ws.addEventListener("close", () => {
446
- logger2.info("WebSocket closed, attempting to reconnect...");
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
- logger2.error("WebSocket error");
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 client = new BrowserWebSocketClient(options);
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 client = new WebSocketClient(options);
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
- WebSocketClient
661
+ WebSocketConnection,
662
+ WebSocketClient,
663
+ BrowserWebSocketClient
519
664
  };
520
665
 
521
- //# debugId=11069204D1FF528964756E2164756E21
666
+ //# debugId=41D375A37CDC1ED664756E2164756E21
package/dist/index.js.map CHANGED
@@ -1,11 +1,16 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/WebSocketServer.ts", "../src/WebSocketClient.ts"],
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 * WebSocket Server implementation of ChannelServer\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\";\n\nconst logger = createLogger(\"network/WebSocketServer\");\n\n/**\n * WebSocket connection implementation\n */\nclass 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\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 // Setup heartbeat if enabled\n if (options.heartbeat !== false) {\n const interval = options.heartbeatInterval || 30000;\n\n 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 ws.terminate();\n return;\n }\n this.isAlive = false;\n ws.ping();\n logger.debug(\"Heartbeat ping sent\", { id: this.id });\n }, interval);\n }\n\n // Setup message handler\n ws.on(\"message\", (data: Buffer) => {\n const message = data.toString();\n for (const handler of this.messageHandlers) {\n handler(message);\n }\n });\n\n // Setup close handler\n 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 // Setup error handler\n 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 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 this.ws.close();\n }\n}\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 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 this.wss!.close(() => resolve());\n });\n }\n this.wss = null;\n }\n\n async dispose(): Promise<void> {\n await this.close();\n this.connectionHandlers.clear();\n }\n}\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": "11069204D1FF528964756E2164756E21",
13
+ "mappings": "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",
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.8.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.8.1",
42
- "@agentxjs/types": "^1.8.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
  },