@rookdaemon/agora 0.1.2 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +265 -1
  2. package/dist/cli.js +481 -36
  3. package/dist/cli.js.map +1 -1
  4. package/dist/config.d.ts +44 -0
  5. package/dist/config.d.ts.map +1 -0
  6. package/dist/config.js +74 -0
  7. package/dist/config.js.map +1 -0
  8. package/dist/index.d.ts +5 -0
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +5 -0
  11. package/dist/index.js.map +1 -1
  12. package/dist/message/envelope.d.ts +1 -1
  13. package/dist/message/envelope.d.ts.map +1 -1
  14. package/dist/message/envelope.js.map +1 -1
  15. package/dist/message/types/paper-discovery.d.ts +28 -0
  16. package/dist/message/types/paper-discovery.d.ts.map +1 -0
  17. package/dist/message/types/paper-discovery.js +2 -0
  18. package/dist/message/types/paper-discovery.js.map +1 -0
  19. package/dist/peer/client.d.ts +50 -0
  20. package/dist/peer/client.d.ts.map +1 -0
  21. package/dist/peer/client.js +138 -0
  22. package/dist/peer/client.js.map +1 -0
  23. package/dist/peer/manager.d.ts +65 -0
  24. package/dist/peer/manager.d.ts.map +1 -0
  25. package/dist/peer/manager.js +153 -0
  26. package/dist/peer/manager.js.map +1 -0
  27. package/dist/peer/server.d.ts +65 -0
  28. package/dist/peer/server.d.ts.map +1 -0
  29. package/dist/peer/server.js +154 -0
  30. package/dist/peer/server.js.map +1 -0
  31. package/dist/relay/client.d.ts +112 -0
  32. package/dist/relay/client.d.ts.map +1 -0
  33. package/dist/relay/client.js +281 -0
  34. package/dist/relay/client.js.map +1 -0
  35. package/dist/relay/server.d.ts +60 -0
  36. package/dist/relay/server.d.ts.map +1 -0
  37. package/dist/relay/server.js +266 -0
  38. package/dist/relay/server.js.map +1 -0
  39. package/dist/relay/types.d.ts +35 -0
  40. package/dist/relay/types.d.ts.map +1 -0
  41. package/dist/relay/types.js +2 -0
  42. package/dist/relay/types.js.map +1 -0
  43. package/dist/transport/peer-config.d.ts +3 -2
  44. package/dist/transport/peer-config.d.ts.map +1 -1
  45. package/dist/transport/peer-config.js.map +1 -1
  46. package/dist/transport/relay.d.ts +23 -0
  47. package/dist/transport/relay.d.ts.map +1 -0
  48. package/dist/transport/relay.js +85 -0
  49. package/dist/transport/relay.js.map +1 -0
  50. package/package.json +1 -38
@@ -0,0 +1,281 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import WebSocket from 'ws';
3
+ import { verifyEnvelope } from '../message/envelope.js';
4
+ /**
5
+ * Persistent WebSocket client for the Agora relay server.
6
+ * Maintains a long-lived connection, handles reconnection, and routes messages.
7
+ */
8
+ export class RelayClient extends EventEmitter {
9
+ ws = null;
10
+ config;
11
+ reconnectAttempts = 0;
12
+ reconnectTimeout = null;
13
+ pingInterval = null;
14
+ isConnected = false;
15
+ isRegistered = false;
16
+ shouldReconnect = true;
17
+ onlinePeers = new Map();
18
+ constructor(config) {
19
+ super();
20
+ this.config = {
21
+ pingInterval: 30000,
22
+ maxReconnectDelay: 60000,
23
+ ...config,
24
+ };
25
+ }
26
+ /**
27
+ * Connect to the relay server
28
+ */
29
+ async connect() {
30
+ if (this.ws && (this.ws.readyState === WebSocket.CONNECTING || this.ws.readyState === WebSocket.OPEN)) {
31
+ return;
32
+ }
33
+ this.shouldReconnect = true;
34
+ return this.doConnect();
35
+ }
36
+ /**
37
+ * Disconnect from the relay server
38
+ */
39
+ disconnect() {
40
+ this.shouldReconnect = false;
41
+ this.cleanup();
42
+ if (this.ws) {
43
+ this.ws.close();
44
+ this.ws = null;
45
+ }
46
+ }
47
+ /**
48
+ * Check if currently connected and registered
49
+ */
50
+ connected() {
51
+ return this.isConnected && this.isRegistered;
52
+ }
53
+ /**
54
+ * Send a message to a specific peer
55
+ */
56
+ async send(to, envelope) {
57
+ if (!this.connected()) {
58
+ return { ok: false, error: 'Not connected to relay' };
59
+ }
60
+ const message = {
61
+ type: 'message',
62
+ to,
63
+ envelope,
64
+ };
65
+ try {
66
+ this.ws.send(JSON.stringify(message));
67
+ return { ok: true };
68
+ }
69
+ catch (err) {
70
+ return { ok: false, error: err instanceof Error ? err.message : String(err) };
71
+ }
72
+ }
73
+ /**
74
+ * Broadcast a message to all connected peers
75
+ */
76
+ async broadcast(envelope) {
77
+ if (!this.connected()) {
78
+ return { ok: false, error: 'Not connected to relay' };
79
+ }
80
+ const message = {
81
+ type: 'broadcast',
82
+ envelope,
83
+ };
84
+ try {
85
+ this.ws.send(JSON.stringify(message));
86
+ return { ok: true };
87
+ }
88
+ catch (err) {
89
+ return { ok: false, error: err instanceof Error ? err.message : String(err) };
90
+ }
91
+ }
92
+ /**
93
+ * Get list of currently online peers
94
+ */
95
+ getOnlinePeers() {
96
+ return Array.from(this.onlinePeers.values());
97
+ }
98
+ /**
99
+ * Check if a specific peer is online
100
+ */
101
+ isPeerOnline(publicKey) {
102
+ return this.onlinePeers.has(publicKey);
103
+ }
104
+ /**
105
+ * Internal: Perform connection
106
+ */
107
+ async doConnect() {
108
+ return new Promise((resolve, reject) => {
109
+ try {
110
+ this.ws = new WebSocket(this.config.relayUrl);
111
+ let resolved = false;
112
+ const resolveOnce = (callback) => {
113
+ if (!resolved) {
114
+ resolved = true;
115
+ callback();
116
+ }
117
+ };
118
+ this.ws.on('open', () => {
119
+ this.isConnected = true;
120
+ this.reconnectAttempts = 0;
121
+ this.startPingInterval();
122
+ // Send registration message
123
+ const registerMsg = {
124
+ type: 'register',
125
+ publicKey: this.config.publicKey,
126
+ name: this.config.name,
127
+ };
128
+ this.ws.send(JSON.stringify(registerMsg));
129
+ });
130
+ this.ws.on('message', (data) => {
131
+ try {
132
+ const msg = JSON.parse(data.toString());
133
+ this.handleMessage(msg);
134
+ // Resolve promise on successful registration
135
+ if (msg.type === 'registered' && !resolved) {
136
+ resolveOnce(() => resolve());
137
+ }
138
+ }
139
+ catch (err) {
140
+ this.emit('error', new Error(`Failed to parse message: ${err instanceof Error ? err.message : String(err)}`));
141
+ }
142
+ });
143
+ this.ws.on('close', () => {
144
+ this.isConnected = false;
145
+ this.isRegistered = false;
146
+ this.cleanup();
147
+ this.emit('disconnected');
148
+ if (this.shouldReconnect) {
149
+ this.scheduleReconnect();
150
+ }
151
+ if (!resolved) {
152
+ resolveOnce(() => reject(new Error('Connection closed before registration')));
153
+ }
154
+ });
155
+ this.ws.on('error', (err) => {
156
+ this.emit('error', err);
157
+ if (!resolved) {
158
+ resolveOnce(() => reject(err));
159
+ }
160
+ });
161
+ }
162
+ catch (err) {
163
+ reject(err);
164
+ }
165
+ });
166
+ }
167
+ /**
168
+ * Handle incoming message from relay
169
+ */
170
+ handleMessage(msg) {
171
+ switch (msg.type) {
172
+ case 'registered':
173
+ this.isRegistered = true;
174
+ if (msg.peers) {
175
+ // Populate initial peer list
176
+ for (const peer of msg.peers) {
177
+ this.onlinePeers.set(peer.publicKey, peer);
178
+ }
179
+ }
180
+ this.emit('connected');
181
+ break;
182
+ case 'message':
183
+ if (msg.envelope && msg.from) {
184
+ // Verify envelope signature
185
+ const verification = verifyEnvelope(msg.envelope);
186
+ if (!verification.valid) {
187
+ this.emit('error', new Error(`Invalid envelope signature: ${verification.reason}`));
188
+ return;
189
+ }
190
+ // Verify sender matches 'from' field
191
+ if (msg.envelope.sender !== msg.from) {
192
+ this.emit('error', new Error('Envelope sender does not match relay from field'));
193
+ return;
194
+ }
195
+ // Emit verified message
196
+ this.emit('message', msg.envelope, msg.from, msg.name);
197
+ }
198
+ break;
199
+ case 'peer_online':
200
+ if (msg.publicKey) {
201
+ const peer = {
202
+ publicKey: msg.publicKey,
203
+ name: msg.name,
204
+ };
205
+ this.onlinePeers.set(msg.publicKey, peer);
206
+ this.emit('peer_online', peer);
207
+ }
208
+ break;
209
+ case 'peer_offline':
210
+ if (msg.publicKey) {
211
+ const peer = this.onlinePeers.get(msg.publicKey);
212
+ if (peer) {
213
+ this.onlinePeers.delete(msg.publicKey);
214
+ this.emit('peer_offline', peer);
215
+ }
216
+ }
217
+ break;
218
+ case 'error':
219
+ this.emit('error', new Error(`Relay error: ${msg.message || 'Unknown error'}`));
220
+ break;
221
+ case 'pong':
222
+ // Keepalive response, no action needed
223
+ break;
224
+ default:
225
+ // Unknown message type, ignore
226
+ break;
227
+ }
228
+ }
229
+ /**
230
+ * Schedule reconnection with exponential backoff
231
+ */
232
+ scheduleReconnect() {
233
+ if (this.reconnectTimeout) {
234
+ return;
235
+ }
236
+ // Exponential backoff: 1s, 2s, 4s, 8s, 16s, 32s, 60s (max)
237
+ const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), this.config.maxReconnectDelay);
238
+ this.reconnectAttempts++;
239
+ this.reconnectTimeout = setTimeout(() => {
240
+ this.reconnectTimeout = null;
241
+ if (this.shouldReconnect) {
242
+ this.doConnect().catch((err) => {
243
+ this.emit('error', err);
244
+ });
245
+ }
246
+ }, delay);
247
+ }
248
+ /**
249
+ * Start periodic ping messages
250
+ */
251
+ startPingInterval() {
252
+ this.stopPingInterval();
253
+ this.pingInterval = setInterval(() => {
254
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
255
+ const ping = { type: 'ping' };
256
+ this.ws.send(JSON.stringify(ping));
257
+ }
258
+ }, this.config.pingInterval);
259
+ }
260
+ /**
261
+ * Stop ping interval
262
+ */
263
+ stopPingInterval() {
264
+ if (this.pingInterval) {
265
+ clearInterval(this.pingInterval);
266
+ this.pingInterval = null;
267
+ }
268
+ }
269
+ /**
270
+ * Cleanup resources
271
+ */
272
+ cleanup() {
273
+ this.stopPingInterval();
274
+ if (this.reconnectTimeout) {
275
+ clearTimeout(this.reconnectTimeout);
276
+ this.reconnectTimeout = null;
277
+ }
278
+ this.onlinePeers.clear();
279
+ }
280
+ }
281
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/relay/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import { WebSocket } from 'ws';
3
+ import { type Envelope } from '../message/envelope.js';
4
+ /**
5
+ * Represents a connected agent in the relay
6
+ */
7
+ interface ConnectedAgent {
8
+ /** Agent's public key */
9
+ publicKey: string;
10
+ /** Optional agent name */
11
+ name?: string;
12
+ /** WebSocket connection */
13
+ socket: WebSocket;
14
+ }
15
+ /**
16
+ * Events emitted by RelayServer
17
+ */
18
+ export interface RelayServerEvents {
19
+ 'agent-registered': (publicKey: string) => void;
20
+ 'agent-disconnected': (publicKey: string) => void;
21
+ 'message-relayed': (from: string, to: string, envelope: Envelope) => void;
22
+ 'error': (error: Error) => void;
23
+ }
24
+ /**
25
+ * WebSocket relay server for routing messages between agents.
26
+ *
27
+ * Agents connect to the relay and register with their public key.
28
+ * Messages are routed to recipients based on the 'to' field.
29
+ * All envelopes are verified before being forwarded.
30
+ */
31
+ export declare class RelayServer extends EventEmitter {
32
+ private wss;
33
+ private agents;
34
+ /**
35
+ * Start the relay server
36
+ */
37
+ start(port: number): Promise<void>;
38
+ /**
39
+ * Stop the relay server
40
+ */
41
+ stop(): Promise<void>;
42
+ /**
43
+ * Get all connected agents
44
+ */
45
+ getAgents(): Map<string, ConnectedAgent>;
46
+ /**
47
+ * Handle incoming connection
48
+ */
49
+ private handleConnection;
50
+ /**
51
+ * Send an error message to a client
52
+ */
53
+ private sendError;
54
+ /**
55
+ * Broadcast a peer event to all connected agents
56
+ */
57
+ private broadcastPeerEvent;
58
+ }
59
+ export {};
60
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/relay/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAmB,SAAS,EAAE,MAAM,IAAI,CAAC;AAChD,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAEvE;;GAEG;AACH,UAAU,cAAc;IACtB,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,0BAA0B;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2BAA2B;IAC3B,MAAM,EAAE,SAAS,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,oBAAoB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;IAC1E,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACjC;AAED;;;;;;GAMG;AACH,qBAAa,WAAY,SAAQ,YAAY;IAC3C,OAAO,CAAC,GAAG,CAAgC;IAC3C,OAAO,CAAC,MAAM,CAAqC;IAEnD;;OAEG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BlC;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAwB3B;;OAEG;IACH,SAAS,IAAI,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC;IAIxC;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA+KxB;;OAEG;IACH,OAAO,CAAC,SAAS;IAWjB;;OAEG;IACH,OAAO,CAAC,kBAAkB;CAmB3B"}
@@ -0,0 +1,266 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import { WebSocketServer, WebSocket } from 'ws';
3
+ import { verifyEnvelope } from '../message/envelope.js';
4
+ /**
5
+ * WebSocket relay server for routing messages between agents.
6
+ *
7
+ * Agents connect to the relay and register with their public key.
8
+ * Messages are routed to recipients based on the 'to' field.
9
+ * All envelopes are verified before being forwarded.
10
+ */
11
+ export class RelayServer extends EventEmitter {
12
+ wss = null;
13
+ agents = new Map();
14
+ /**
15
+ * Start the relay server
16
+ */
17
+ start(port) {
18
+ return new Promise((resolve, reject) => {
19
+ try {
20
+ this.wss = new WebSocketServer({ port });
21
+ let resolved = false;
22
+ this.wss.on('error', (error) => {
23
+ this.emit('error', error);
24
+ if (!resolved) {
25
+ resolved = true;
26
+ reject(error);
27
+ }
28
+ });
29
+ this.wss.on('listening', () => {
30
+ if (!resolved) {
31
+ resolved = true;
32
+ resolve();
33
+ }
34
+ });
35
+ this.wss.on('connection', (socket) => {
36
+ this.handleConnection(socket);
37
+ });
38
+ }
39
+ catch (error) {
40
+ reject(error);
41
+ }
42
+ });
43
+ }
44
+ /**
45
+ * Stop the relay server
46
+ */
47
+ async stop() {
48
+ return new Promise((resolve, reject) => {
49
+ if (!this.wss) {
50
+ resolve();
51
+ return;
52
+ }
53
+ // Close all agent connections
54
+ for (const agent of this.agents.values()) {
55
+ agent.socket.close();
56
+ }
57
+ this.agents.clear();
58
+ this.wss.close((err) => {
59
+ if (err) {
60
+ reject(err);
61
+ }
62
+ else {
63
+ this.wss = null;
64
+ resolve();
65
+ }
66
+ });
67
+ });
68
+ }
69
+ /**
70
+ * Get all connected agents
71
+ */
72
+ getAgents() {
73
+ return new Map(this.agents);
74
+ }
75
+ /**
76
+ * Handle incoming connection
77
+ */
78
+ handleConnection(socket) {
79
+ let agentPublicKey = null;
80
+ socket.on('message', (data) => {
81
+ try {
82
+ const msg = JSON.parse(data.toString());
83
+ // Handle registration
84
+ if (msg.type === 'register' && !agentPublicKey) {
85
+ if (!msg.publicKey || typeof msg.publicKey !== 'string') {
86
+ this.sendError(socket, 'Invalid registration: missing or invalid publicKey');
87
+ socket.close();
88
+ return;
89
+ }
90
+ const publicKey = msg.publicKey;
91
+ const name = msg.name;
92
+ agentPublicKey = publicKey;
93
+ const agent = {
94
+ publicKey,
95
+ name,
96
+ socket,
97
+ };
98
+ this.agents.set(publicKey, agent);
99
+ this.emit('agent-registered', publicKey);
100
+ // Send registration confirmation with list of online peers
101
+ const peers = Array.from(this.agents.values())
102
+ .filter(a => a.publicKey !== publicKey)
103
+ .map(a => ({ publicKey: a.publicKey, name: a.name }));
104
+ socket.send(JSON.stringify({
105
+ type: 'registered',
106
+ publicKey,
107
+ peers,
108
+ }));
109
+ // Notify other agents that this agent is now online
110
+ this.broadcastPeerEvent('peer_online', publicKey, name);
111
+ return;
112
+ }
113
+ // Require registration before processing messages
114
+ if (!agentPublicKey) {
115
+ this.sendError(socket, 'Not registered: send registration message first');
116
+ socket.close();
117
+ return;
118
+ }
119
+ // Handle message relay
120
+ if (msg.type === 'message') {
121
+ if (!msg.to || typeof msg.to !== 'string') {
122
+ this.sendError(socket, 'Invalid message: missing or invalid "to" field');
123
+ return;
124
+ }
125
+ if (!msg.envelope || typeof msg.envelope !== 'object') {
126
+ this.sendError(socket, 'Invalid message: missing or invalid "envelope" field');
127
+ return;
128
+ }
129
+ const envelope = msg.envelope;
130
+ // Verify envelope signature
131
+ const verification = verifyEnvelope(envelope);
132
+ if (!verification.valid) {
133
+ this.sendError(socket, `Invalid envelope: ${verification.reason || 'verification failed'}`);
134
+ return;
135
+ }
136
+ // Verify sender matches registered agent
137
+ if (envelope.sender !== agentPublicKey) {
138
+ this.sendError(socket, 'Envelope sender does not match registered public key');
139
+ return;
140
+ }
141
+ // Find recipient
142
+ const recipient = this.agents.get(msg.to);
143
+ if (!recipient || recipient.socket.readyState !== WebSocket.OPEN) {
144
+ this.sendError(socket, 'Recipient not connected');
145
+ return;
146
+ }
147
+ // Forward envelope to recipient wrapped in relay message format
148
+ try {
149
+ const senderAgent = this.agents.get(agentPublicKey);
150
+ const relayMessage = {
151
+ type: 'message',
152
+ from: agentPublicKey,
153
+ name: senderAgent?.name,
154
+ envelope,
155
+ };
156
+ recipient.socket.send(JSON.stringify(relayMessage));
157
+ this.emit('message-relayed', agentPublicKey, msg.to, envelope);
158
+ }
159
+ catch (err) {
160
+ this.sendError(socket, 'Failed to relay message');
161
+ this.emit('error', err);
162
+ }
163
+ return;
164
+ }
165
+ // Handle broadcast: same validation as message, then forward to all other agents
166
+ if (msg.type === 'broadcast') {
167
+ if (!msg.envelope || typeof msg.envelope !== 'object') {
168
+ this.sendError(socket, 'Invalid broadcast: missing or invalid "envelope" field');
169
+ return;
170
+ }
171
+ const envelope = msg.envelope;
172
+ const verification = verifyEnvelope(envelope);
173
+ if (!verification.valid) {
174
+ this.sendError(socket, `Invalid envelope: ${verification.reason || 'verification failed'}`);
175
+ return;
176
+ }
177
+ if (envelope.sender !== agentPublicKey) {
178
+ this.sendError(socket, 'Envelope sender does not match registered public key');
179
+ return;
180
+ }
181
+ const senderAgent = this.agents.get(agentPublicKey);
182
+ const relayMessage = {
183
+ type: 'message',
184
+ from: agentPublicKey,
185
+ name: senderAgent?.name,
186
+ envelope,
187
+ };
188
+ const messageStr = JSON.stringify(relayMessage);
189
+ for (const agent of this.agents.values()) {
190
+ if (agent.publicKey !== agentPublicKey && agent.socket.readyState === WebSocket.OPEN) {
191
+ try {
192
+ agent.socket.send(messageStr);
193
+ }
194
+ catch (err) {
195
+ this.emit('error', err);
196
+ }
197
+ }
198
+ }
199
+ return;
200
+ }
201
+ // Handle ping
202
+ if (msg.type === 'ping') {
203
+ socket.send(JSON.stringify({ type: 'pong' }));
204
+ return;
205
+ }
206
+ // Unknown message type
207
+ this.sendError(socket, `Unknown message type: ${msg.type}`);
208
+ }
209
+ catch (err) {
210
+ // Invalid JSON or other parsing errors
211
+ this.emit('error', new Error(`Message parsing failed: ${err instanceof Error ? err.message : String(err)}`));
212
+ this.sendError(socket, 'Invalid message format');
213
+ }
214
+ });
215
+ socket.on('close', () => {
216
+ if (agentPublicKey) {
217
+ const agent = this.agents.get(agentPublicKey);
218
+ const agentName = agent?.name;
219
+ this.agents.delete(agentPublicKey);
220
+ this.emit('agent-disconnected', agentPublicKey);
221
+ // Notify other agents that this agent went offline
222
+ this.broadcastPeerEvent('peer_offline', agentPublicKey, agentName);
223
+ }
224
+ });
225
+ socket.on('error', (error) => {
226
+ this.emit('error', error);
227
+ });
228
+ }
229
+ /**
230
+ * Send an error message to a client
231
+ */
232
+ sendError(socket, message) {
233
+ try {
234
+ if (socket.readyState === WebSocket.OPEN) {
235
+ socket.send(JSON.stringify({ type: 'error', message }));
236
+ }
237
+ }
238
+ catch (err) {
239
+ // Log errors when sending error messages, but don't propagate to avoid cascading failures
240
+ this.emit('error', new Error(`Failed to send error message: ${err instanceof Error ? err.message : String(err)}`));
241
+ }
242
+ }
243
+ /**
244
+ * Broadcast a peer event to all connected agents
245
+ */
246
+ broadcastPeerEvent(eventType, publicKey, name) {
247
+ const message = {
248
+ type: eventType,
249
+ publicKey,
250
+ name,
251
+ };
252
+ const messageStr = JSON.stringify(message);
253
+ for (const agent of this.agents.values()) {
254
+ // Don't send the event to the agent it's about
255
+ if (agent.publicKey !== publicKey && agent.socket.readyState === WebSocket.OPEN) {
256
+ try {
257
+ agent.socket.send(messageStr);
258
+ }
259
+ catch (err) {
260
+ this.emit('error', new Error(`Failed to send ${eventType} event: ${err instanceof Error ? err.message : String(err)}`));
261
+ }
262
+ }
263
+ }
264
+ }
265
+ }
266
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/relay/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import type { Envelope } from '../message/envelope.js';
2
+ /**
3
+ * Messages sent from client to relay server
4
+ */
5
+ export interface RelayClientMessage {
6
+ type: 'register' | 'message' | 'broadcast' | 'ping';
7
+ publicKey?: string;
8
+ name?: string;
9
+ to?: string;
10
+ envelope?: Envelope;
11
+ }
12
+ /**
13
+ * Messages received from relay server
14
+ */
15
+ export interface RelayServerMessage {
16
+ type: 'registered' | 'message' | 'error' | 'pong' | 'peer_online' | 'peer_offline';
17
+ publicKey?: string;
18
+ name?: string;
19
+ from?: string;
20
+ envelope?: Envelope;
21
+ peers?: Array<{
22
+ publicKey: string;
23
+ name?: string;
24
+ }>;
25
+ code?: string;
26
+ message?: string;
27
+ }
28
+ /**
29
+ * Peer presence information
30
+ */
31
+ export interface RelayPeer {
32
+ publicKey: string;
33
+ name?: string;
34
+ }
35
+ //# sourceMappingURL=types.d.ts.map