@rookdaemon/agora 0.2.8 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-JUOGKXFN.js +1645 -0
- package/dist/chunk-JUOGKXFN.js.map +1 -0
- package/dist/cli.d.ts +0 -2
- package/dist/cli.js +1163 -1137
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +1613 -30
- package/dist/index.js +1135 -29
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
- package/dist/cli.d.ts.map +0 -1
- package/dist/config.d.ts +0 -59
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js +0 -115
- package/dist/config.js.map +0 -1
- package/dist/discovery/bootstrap.d.ts +0 -32
- package/dist/discovery/bootstrap.d.ts.map +0 -1
- package/dist/discovery/bootstrap.js +0 -36
- package/dist/discovery/bootstrap.js.map +0 -1
- package/dist/discovery/peer-discovery.d.ts +0 -59
- package/dist/discovery/peer-discovery.d.ts.map +0 -1
- package/dist/discovery/peer-discovery.js +0 -108
- package/dist/discovery/peer-discovery.js.map +0 -1
- package/dist/identity/keypair.d.ts +0 -42
- package/dist/identity/keypair.d.ts.map +0 -1
- package/dist/identity/keypair.js +0 -83
- package/dist/identity/keypair.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/message/envelope.d.ts +0 -59
- package/dist/message/envelope.d.ts.map +0 -1
- package/dist/message/envelope.js +0 -83
- package/dist/message/envelope.js.map +0 -1
- package/dist/message/types/paper-discovery.d.ts +0 -28
- package/dist/message/types/paper-discovery.d.ts.map +0 -1
- package/dist/message/types/paper-discovery.js +0 -2
- package/dist/message/types/paper-discovery.js.map +0 -1
- package/dist/message/types/peer-discovery.d.ts +0 -78
- package/dist/message/types/peer-discovery.d.ts.map +0 -1
- package/dist/message/types/peer-discovery.js +0 -90
- package/dist/message/types/peer-discovery.js.map +0 -1
- package/dist/peer/client.d.ts +0 -50
- package/dist/peer/client.d.ts.map +0 -1
- package/dist/peer/client.js +0 -138
- package/dist/peer/client.js.map +0 -1
- package/dist/peer/manager.d.ts +0 -65
- package/dist/peer/manager.d.ts.map +0 -1
- package/dist/peer/manager.js +0 -153
- package/dist/peer/manager.js.map +0 -1
- package/dist/peer/server.d.ts +0 -65
- package/dist/peer/server.d.ts.map +0 -1
- package/dist/peer/server.js +0 -154
- package/dist/peer/server.js.map +0 -1
- package/dist/registry/capability.d.ts +0 -44
- package/dist/registry/capability.d.ts.map +0 -1
- package/dist/registry/capability.js +0 -94
- package/dist/registry/capability.js.map +0 -1
- package/dist/registry/discovery-service.d.ts +0 -64
- package/dist/registry/discovery-service.d.ts.map +0 -1
- package/dist/registry/discovery-service.js +0 -129
- package/dist/registry/discovery-service.js.map +0 -1
- package/dist/registry/messages.d.ts +0 -105
- package/dist/registry/messages.d.ts.map +0 -1
- package/dist/registry/messages.js +0 -2
- package/dist/registry/messages.js.map +0 -1
- package/dist/registry/peer-store.d.ts +0 -57
- package/dist/registry/peer-store.d.ts.map +0 -1
- package/dist/registry/peer-store.js +0 -92
- package/dist/registry/peer-store.js.map +0 -1
- package/dist/registry/peer.d.ts +0 -20
- package/dist/registry/peer.d.ts.map +0 -1
- package/dist/registry/peer.js +0 -2
- package/dist/registry/peer.js.map +0 -1
- package/dist/relay/client.d.ts +0 -112
- package/dist/relay/client.d.ts.map +0 -1
- package/dist/relay/client.js +0 -281
- package/dist/relay/client.js.map +0 -1
- package/dist/relay/jwt-auth.d.ts +0 -40
- package/dist/relay/jwt-auth.d.ts.map +0 -1
- package/dist/relay/jwt-auth.js +0 -109
- package/dist/relay/jwt-auth.js.map +0 -1
- package/dist/relay/message-buffer.d.ts +0 -41
- package/dist/relay/message-buffer.d.ts.map +0 -1
- package/dist/relay/message-buffer.js +0 -53
- package/dist/relay/message-buffer.js.map +0 -1
- package/dist/relay/rest-api.d.ts +0 -68
- package/dist/relay/rest-api.d.ts.map +0 -1
- package/dist/relay/rest-api.js +0 -225
- package/dist/relay/rest-api.js.map +0 -1
- package/dist/relay/run-relay.d.ts +0 -33
- package/dist/relay/run-relay.d.ts.map +0 -1
- package/dist/relay/run-relay.js +0 -57
- package/dist/relay/run-relay.js.map +0 -1
- package/dist/relay/server.d.ts +0 -91
- package/dist/relay/server.d.ts.map +0 -1
- package/dist/relay/server.js +0 -385
- package/dist/relay/server.js.map +0 -1
- package/dist/relay/store.d.ts +0 -19
- package/dist/relay/store.d.ts.map +0 -1
- package/dist/relay/store.js +0 -55
- package/dist/relay/store.js.map +0 -1
- package/dist/relay/types.d.ts +0 -35
- package/dist/relay/types.d.ts.map +0 -1
- package/dist/relay/types.js +0 -2
- package/dist/relay/types.js.map +0 -1
- package/dist/reputation/commit-reveal.d.ts +0 -45
- package/dist/reputation/commit-reveal.d.ts.map +0 -1
- package/dist/reputation/commit-reveal.js +0 -125
- package/dist/reputation/commit-reveal.js.map +0 -1
- package/dist/reputation/scoring.d.ts +0 -31
- package/dist/reputation/scoring.d.ts.map +0 -1
- package/dist/reputation/scoring.js +0 -105
- package/dist/reputation/scoring.js.map +0 -1
- package/dist/reputation/store.d.ts +0 -83
- package/dist/reputation/store.d.ts.map +0 -1
- package/dist/reputation/store.js +0 -202
- package/dist/reputation/store.js.map +0 -1
- package/dist/reputation/types.d.ts +0 -150
- package/dist/reputation/types.d.ts.map +0 -1
- package/dist/reputation/types.js +0 -113
- package/dist/reputation/types.js.map +0 -1
- package/dist/reputation/verification.d.ts +0 -28
- package/dist/reputation/verification.d.ts.map +0 -1
- package/dist/reputation/verification.js +0 -91
- package/dist/reputation/verification.js.map +0 -1
- package/dist/service.d.ts +0 -90
- package/dist/service.d.ts.map +0 -1
- package/dist/service.js +0 -176
- package/dist/service.js.map +0 -1
- package/dist/transport/http.d.ts +0 -41
- package/dist/transport/http.d.ts.map +0 -1
- package/dist/transport/http.js +0 -103
- package/dist/transport/http.js.map +0 -1
- package/dist/transport/peer-config.d.ts +0 -38
- package/dist/transport/peer-config.d.ts.map +0 -1
- package/dist/transport/peer-config.js +0 -41
- package/dist/transport/peer-config.js.map +0 -1
- package/dist/transport/relay.d.ts +0 -30
- package/dist/transport/relay.d.ts.map +0 -1
- package/dist/transport/relay.js +0 -85
- package/dist/transport/relay.js.map +0 -1
- package/dist/utils.d.ts +0 -40
- package/dist/utils.d.ts.map +0 -1
- package/dist/utils.js +0 -59
- package/dist/utils.js.map +0 -1
package/dist/relay/client.d.ts
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { EventEmitter } from 'node:events';
|
|
2
|
-
import { type Envelope } from '../message/envelope.js';
|
|
3
|
-
import type { RelayPeer } from './types.js';
|
|
4
|
-
/**
|
|
5
|
-
* Configuration for RelayClient
|
|
6
|
-
*/
|
|
7
|
-
export interface RelayClientConfig {
|
|
8
|
-
/** WebSocket URL of the relay server */
|
|
9
|
-
relayUrl: string;
|
|
10
|
-
/** Agent's public key */
|
|
11
|
-
publicKey: string;
|
|
12
|
-
/** Agent's private key (for signing) */
|
|
13
|
-
privateKey: string;
|
|
14
|
-
/** Optional name for this agent */
|
|
15
|
-
name?: string;
|
|
16
|
-
/** Keepalive ping interval in milliseconds (default: 30000) */
|
|
17
|
-
pingInterval?: number;
|
|
18
|
-
/** Maximum reconnection delay in milliseconds (default: 60000) */
|
|
19
|
-
maxReconnectDelay?: number;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Events emitted by RelayClient
|
|
23
|
-
*/
|
|
24
|
-
export interface RelayClientEvents {
|
|
25
|
-
/** Emitted when successfully connected and registered */
|
|
26
|
-
'connected': () => void;
|
|
27
|
-
/** Emitted when disconnected from relay */
|
|
28
|
-
'disconnected': () => void;
|
|
29
|
-
/** Emitted when a verified message is received */
|
|
30
|
-
'message': (envelope: Envelope, from: string, fromName?: string) => void;
|
|
31
|
-
/** Emitted when a peer comes online */
|
|
32
|
-
'peer_online': (peer: RelayPeer) => void;
|
|
33
|
-
/** Emitted when a peer goes offline */
|
|
34
|
-
'peer_offline': (peer: RelayPeer) => void;
|
|
35
|
-
/** Emitted on errors */
|
|
36
|
-
'error': (error: Error) => void;
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Persistent WebSocket client for the Agora relay server.
|
|
40
|
-
* Maintains a long-lived connection, handles reconnection, and routes messages.
|
|
41
|
-
*/
|
|
42
|
-
export declare class RelayClient extends EventEmitter {
|
|
43
|
-
private ws;
|
|
44
|
-
private config;
|
|
45
|
-
private reconnectAttempts;
|
|
46
|
-
private reconnectTimeout;
|
|
47
|
-
private pingInterval;
|
|
48
|
-
private isConnected;
|
|
49
|
-
private isRegistered;
|
|
50
|
-
private shouldReconnect;
|
|
51
|
-
private onlinePeers;
|
|
52
|
-
constructor(config: RelayClientConfig);
|
|
53
|
-
/**
|
|
54
|
-
* Connect to the relay server
|
|
55
|
-
*/
|
|
56
|
-
connect(): Promise<void>;
|
|
57
|
-
/**
|
|
58
|
-
* Disconnect from the relay server
|
|
59
|
-
*/
|
|
60
|
-
disconnect(): void;
|
|
61
|
-
/**
|
|
62
|
-
* Check if currently connected and registered
|
|
63
|
-
*/
|
|
64
|
-
connected(): boolean;
|
|
65
|
-
/**
|
|
66
|
-
* Send a message to a specific peer
|
|
67
|
-
*/
|
|
68
|
-
send(to: string, envelope: Envelope): Promise<{
|
|
69
|
-
ok: boolean;
|
|
70
|
-
error?: string;
|
|
71
|
-
}>;
|
|
72
|
-
/**
|
|
73
|
-
* Broadcast a message to all connected peers
|
|
74
|
-
*/
|
|
75
|
-
broadcast(envelope: Envelope): Promise<{
|
|
76
|
-
ok: boolean;
|
|
77
|
-
error?: string;
|
|
78
|
-
}>;
|
|
79
|
-
/**
|
|
80
|
-
* Get list of currently online peers
|
|
81
|
-
*/
|
|
82
|
-
getOnlinePeers(): RelayPeer[];
|
|
83
|
-
/**
|
|
84
|
-
* Check if a specific peer is online
|
|
85
|
-
*/
|
|
86
|
-
isPeerOnline(publicKey: string): boolean;
|
|
87
|
-
/**
|
|
88
|
-
* Internal: Perform connection
|
|
89
|
-
*/
|
|
90
|
-
private doConnect;
|
|
91
|
-
/**
|
|
92
|
-
* Handle incoming message from relay
|
|
93
|
-
*/
|
|
94
|
-
private handleMessage;
|
|
95
|
-
/**
|
|
96
|
-
* Schedule reconnection with exponential backoff
|
|
97
|
-
*/
|
|
98
|
-
private scheduleReconnect;
|
|
99
|
-
/**
|
|
100
|
-
* Start periodic ping messages
|
|
101
|
-
*/
|
|
102
|
-
private startPingInterval;
|
|
103
|
-
/**
|
|
104
|
-
* Stop ping interval
|
|
105
|
-
*/
|
|
106
|
-
private stopPingInterval;
|
|
107
|
-
/**
|
|
108
|
-
* Cleanup resources
|
|
109
|
-
*/
|
|
110
|
-
private cleanup;
|
|
111
|
-
}
|
|
112
|
-
//# sourceMappingURL=client.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/relay/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvE,OAAO,KAAK,EAA0C,SAAS,EAAE,MAAM,YAAY,CAAC;AAEpF;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kEAAkE;IAClE,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,yDAAyD;IACzD,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,2CAA2C;IAC3C,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,kDAAkD;IAClD,SAAS,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACzE,uCAAuC;IACvC,aAAa,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IACzC,uCAAuC;IACvC,cAAc,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IAC1C,wBAAwB;IACxB,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACjC;AAED;;;GAGG;AACH,qBAAa,WAAY,SAAQ,YAAY;IAC3C,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,gBAAgB,CAA+B;IACvD,OAAO,CAAC,YAAY,CAA+B;IACnD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,WAAW,CAAgC;gBAEvC,MAAM,EAAE,iBAAiB;IASrC;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAS9B;;OAEG;IACH,UAAU,IAAI,IAAI;IASlB;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACG,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAmBpF;;OAEG;IACG,SAAS,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAkB7E;;OAEG;IACH,cAAc,IAAI,SAAS,EAAE;IAI7B;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAIxC;;OAEG;YACW,SAAS;IAoEvB;;OAEG;IACH,OAAO,CAAC,aAAa;IAoErB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAuBzB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAUzB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAOxB;;OAEG;IACH,OAAO,CAAC,OAAO;CAQhB"}
|
package/dist/relay/client.js
DELETED
|
@@ -1,281 +0,0 @@
|
|
|
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
|
package/dist/relay/client.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/relay/client.ts"],"names":[],"mappings":"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"}
|
package/dist/relay/jwt-auth.d.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* jwt-auth.ts — JWT token creation and validation middleware.
|
|
3
|
-
*
|
|
4
|
-
* Tokens are signed with AGORA_RELAY_JWT_SECRET (required env var).
|
|
5
|
-
* Expiry defaults to 3600 seconds (1 hour), configurable via AGORA_JWT_EXPIRY_SECONDS.
|
|
6
|
-
*
|
|
7
|
-
* Token payload: { publicKey, name }
|
|
8
|
-
*/
|
|
9
|
-
import type { Request, Response, NextFunction } from 'express';
|
|
10
|
-
export interface JwtPayload {
|
|
11
|
-
publicKey: string;
|
|
12
|
-
name?: string;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Augment Express Request to carry decoded JWT payload.
|
|
16
|
-
*/
|
|
17
|
-
export interface AuthenticatedRequest extends Request {
|
|
18
|
-
agent?: JwtPayload;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Create a signed JWT for a registered agent.
|
|
22
|
-
* Returns the token string and its expiry timestamp (ms since epoch).
|
|
23
|
-
*/
|
|
24
|
-
export declare function createToken(payload: JwtPayload): {
|
|
25
|
-
token: string;
|
|
26
|
-
expiresAt: number;
|
|
27
|
-
};
|
|
28
|
-
/**
|
|
29
|
-
* Revoke a token by its jti claim so it cannot be used again.
|
|
30
|
-
* The revocation entry is stored with the token's expiry so it can be
|
|
31
|
-
* pruned automatically once the token would no longer be valid anyway.
|
|
32
|
-
*/
|
|
33
|
-
export declare function revokeToken(token: string): void;
|
|
34
|
-
/**
|
|
35
|
-
* Express middleware that validates the Authorization: Bearer <token> header.
|
|
36
|
-
* Attaches decoded payload to `req.agent` on success.
|
|
37
|
-
* Responds with 401 if missing/invalid/expired/revoked.
|
|
38
|
-
*/
|
|
39
|
-
export declare function requireAuth(req: AuthenticatedRequest, res: Response, next: NextFunction): void;
|
|
40
|
-
//# sourceMappingURL=jwt-auth.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"jwt-auth.d.ts","sourceRoot":"","sources":["../../src/relay/jwt-auth.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE/D,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,OAAO;IACnD,KAAK,CAAC,EAAE,UAAU,CAAC;CACpB;AA4CD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,UAAU,GAAG;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB,CAaA;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAe/C;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,oBAAoB,EACzB,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,YAAY,GACjB,IAAI,CA8BN"}
|
package/dist/relay/jwt-auth.js
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* jwt-auth.ts — JWT token creation and validation middleware.
|
|
3
|
-
*
|
|
4
|
-
* Tokens are signed with AGORA_RELAY_JWT_SECRET (required env var).
|
|
5
|
-
* Expiry defaults to 3600 seconds (1 hour), configurable via AGORA_JWT_EXPIRY_SECONDS.
|
|
6
|
-
*
|
|
7
|
-
* Token payload: { publicKey, name }
|
|
8
|
-
*/
|
|
9
|
-
import jwt from 'jsonwebtoken';
|
|
10
|
-
import { randomBytes } from 'node:crypto';
|
|
11
|
-
/**
|
|
12
|
-
* Revocation set for invalidated tokens (populated by DELETE /v1/disconnect).
|
|
13
|
-
* Stored as a Map of JWT `jti` → expiry timestamp (ms).
|
|
14
|
-
* Entries are automatically removed once their JWT would have expired anyway,
|
|
15
|
-
* preventing unbounded memory growth.
|
|
16
|
-
*/
|
|
17
|
-
const revokedJtis = new Map();
|
|
18
|
-
/**
|
|
19
|
-
* Remove revoked JTI entries whose token expiry has already passed.
|
|
20
|
-
* These tokens can no longer be used regardless, so no need to keep them.
|
|
21
|
-
*/
|
|
22
|
-
function pruneExpiredRevocations() {
|
|
23
|
-
const now = Date.now();
|
|
24
|
-
for (const [jti, expiry] of revokedJtis) {
|
|
25
|
-
if (expiry <= now) {
|
|
26
|
-
revokedJtis.delete(jti);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
function getJwtSecret() {
|
|
31
|
-
const secret = process.env.AGORA_RELAY_JWT_SECRET;
|
|
32
|
-
if (!secret) {
|
|
33
|
-
throw new Error('AGORA_RELAY_JWT_SECRET environment variable is required but not set');
|
|
34
|
-
}
|
|
35
|
-
return secret;
|
|
36
|
-
}
|
|
37
|
-
function getExpirySeconds() {
|
|
38
|
-
const raw = process.env.AGORA_JWT_EXPIRY_SECONDS;
|
|
39
|
-
if (raw) {
|
|
40
|
-
const parsed = parseInt(raw, 10);
|
|
41
|
-
if (!isNaN(parsed) && parsed > 0) {
|
|
42
|
-
return parsed;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
return 3600; // 1 hour default
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Create a signed JWT for a registered agent.
|
|
49
|
-
* Returns the token string and its expiry timestamp (ms since epoch).
|
|
50
|
-
*/
|
|
51
|
-
export function createToken(payload) {
|
|
52
|
-
const secret = getJwtSecret();
|
|
53
|
-
const expirySeconds = getExpirySeconds();
|
|
54
|
-
const jti = `${Date.now()}-${randomBytes(16).toString('hex')}`;
|
|
55
|
-
const token = jwt.sign({ publicKey: payload.publicKey, name: payload.name, jti }, secret, { expiresIn: expirySeconds });
|
|
56
|
-
const expiresAt = Date.now() + expirySeconds * 1000;
|
|
57
|
-
return { token, expiresAt };
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Revoke a token by its jti claim so it cannot be used again.
|
|
61
|
-
* The revocation entry is stored with the token's expiry so it can be
|
|
62
|
-
* pruned automatically once the token would no longer be valid anyway.
|
|
63
|
-
*/
|
|
64
|
-
export function revokeToken(token) {
|
|
65
|
-
try {
|
|
66
|
-
const secret = getJwtSecret();
|
|
67
|
-
const decoded = jwt.verify(token, secret);
|
|
68
|
-
if (decoded.jti) {
|
|
69
|
-
const expiry = decoded.exp ? decoded.exp * 1000 : Date.now();
|
|
70
|
-
revokedJtis.set(decoded.jti, expiry);
|
|
71
|
-
pruneExpiredRevocations();
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
catch {
|
|
75
|
-
// Token already invalid — nothing to revoke
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Express middleware that validates the Authorization: Bearer <token> header.
|
|
80
|
-
* Attaches decoded payload to `req.agent` on success.
|
|
81
|
-
* Responds with 401 if missing/invalid/expired/revoked.
|
|
82
|
-
*/
|
|
83
|
-
export function requireAuth(req, res, next) {
|
|
84
|
-
const authHeader = req.headers.authorization;
|
|
85
|
-
if (!authHeader || !authHeader.startsWith('Bearer ')) {
|
|
86
|
-
res.status(401).json({ error: 'Missing or malformed Authorization header' });
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
const token = authHeader.slice(7);
|
|
90
|
-
try {
|
|
91
|
-
const secret = getJwtSecret();
|
|
92
|
-
const decoded = jwt.verify(token, secret);
|
|
93
|
-
if (decoded.jti && revokedJtis.has(decoded.jti)) {
|
|
94
|
-
res.status(401).json({ error: 'Token has been revoked' });
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
req.agent = { publicKey: decoded.publicKey, name: decoded.name };
|
|
98
|
-
next();
|
|
99
|
-
}
|
|
100
|
-
catch (err) {
|
|
101
|
-
if (err instanceof jwt.TokenExpiredError) {
|
|
102
|
-
res.status(401).json({ error: 'Token expired' });
|
|
103
|
-
}
|
|
104
|
-
else {
|
|
105
|
-
res.status(401).json({ error: 'Invalid token' });
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
//# sourceMappingURL=jwt-auth.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"jwt-auth.js","sourceRoot":"","sources":["../../src/relay/jwt-auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* message-buffer.ts — In-memory bounded message queue per agent.
|
|
3
|
-
*
|
|
4
|
-
* When messages are delivered to an agent via the relay, they are also
|
|
5
|
-
* stored here so that HTTP polling clients can retrieve them via GET /v1/messages.
|
|
6
|
-
*/
|
|
7
|
-
export interface BufferedMessage {
|
|
8
|
-
id: string;
|
|
9
|
-
from: string;
|
|
10
|
-
fromName?: string;
|
|
11
|
-
type: string;
|
|
12
|
-
payload: unknown;
|
|
13
|
-
timestamp: number;
|
|
14
|
-
inReplyTo?: string;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* MessageBuffer stores inbound messages per agent public key.
|
|
18
|
-
* FIFO eviction when the buffer is full (max 100 messages).
|
|
19
|
-
*/
|
|
20
|
-
export declare class MessageBuffer {
|
|
21
|
-
private buffers;
|
|
22
|
-
/**
|
|
23
|
-
* Add a message to an agent's buffer.
|
|
24
|
-
* Evicts the oldest message if the buffer is full.
|
|
25
|
-
*/
|
|
26
|
-
add(publicKey: string, message: BufferedMessage): void;
|
|
27
|
-
/**
|
|
28
|
-
* Retrieve messages for an agent, optionally filtering by `since` timestamp.
|
|
29
|
-
* Returns messages with timestamp > since (exclusive).
|
|
30
|
-
*/
|
|
31
|
-
get(publicKey: string, since?: number): BufferedMessage[];
|
|
32
|
-
/**
|
|
33
|
-
* Clear all messages for an agent (after polling without `since`).
|
|
34
|
-
*/
|
|
35
|
-
clear(publicKey: string): void;
|
|
36
|
-
/**
|
|
37
|
-
* Remove all state for a disconnected agent.
|
|
38
|
-
*/
|
|
39
|
-
delete(publicKey: string): void;
|
|
40
|
-
}
|
|
41
|
-
//# sourceMappingURL=message-buffer.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"message-buffer.d.ts","sourceRoot":"","sources":["../../src/relay/message-buffer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAID;;;GAGG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAA6C;IAE5D;;;OAGG;IACH,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI;IAYtD;;;OAGG;IACH,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,eAAe,EAAE;IAQzD;;OAEG;IACH,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAI9B;;OAEG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;CAGhC"}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* message-buffer.ts — In-memory bounded message queue per agent.
|
|
3
|
-
*
|
|
4
|
-
* When messages are delivered to an agent via the relay, they are also
|
|
5
|
-
* stored here so that HTTP polling clients can retrieve them via GET /v1/messages.
|
|
6
|
-
*/
|
|
7
|
-
const MAX_MESSAGES_PER_AGENT = 100;
|
|
8
|
-
/**
|
|
9
|
-
* MessageBuffer stores inbound messages per agent public key.
|
|
10
|
-
* FIFO eviction when the buffer is full (max 100 messages).
|
|
11
|
-
*/
|
|
12
|
-
export class MessageBuffer {
|
|
13
|
-
buffers = new Map();
|
|
14
|
-
/**
|
|
15
|
-
* Add a message to an agent's buffer.
|
|
16
|
-
* Evicts the oldest message if the buffer is full.
|
|
17
|
-
*/
|
|
18
|
-
add(publicKey, message) {
|
|
19
|
-
let queue = this.buffers.get(publicKey);
|
|
20
|
-
if (!queue) {
|
|
21
|
-
queue = [];
|
|
22
|
-
this.buffers.set(publicKey, queue);
|
|
23
|
-
}
|
|
24
|
-
queue.push(message);
|
|
25
|
-
if (queue.length > MAX_MESSAGES_PER_AGENT) {
|
|
26
|
-
queue.shift(); // FIFO eviction
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Retrieve messages for an agent, optionally filtering by `since` timestamp.
|
|
31
|
-
* Returns messages with timestamp > since (exclusive).
|
|
32
|
-
*/
|
|
33
|
-
get(publicKey, since) {
|
|
34
|
-
const queue = this.buffers.get(publicKey) ?? [];
|
|
35
|
-
if (since === undefined) {
|
|
36
|
-
return [...queue];
|
|
37
|
-
}
|
|
38
|
-
return queue.filter((m) => m.timestamp > since);
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Clear all messages for an agent (after polling without `since`).
|
|
42
|
-
*/
|
|
43
|
-
clear(publicKey) {
|
|
44
|
-
this.buffers.set(publicKey, []);
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Remove all state for a disconnected agent.
|
|
48
|
-
*/
|
|
49
|
-
delete(publicKey) {
|
|
50
|
-
this.buffers.delete(publicKey);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
//# sourceMappingURL=message-buffer.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"message-buffer.js","sourceRoot":"","sources":["../../src/relay/message-buffer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,MAAM,sBAAsB,GAAG,GAAG,CAAC;AAEnC;;;GAGG;AACH,MAAM,OAAO,aAAa;IAChB,OAAO,GAAmC,IAAI,GAAG,EAAE,CAAC;IAE5D;;;OAGG;IACH,GAAG,CAAC,SAAiB,EAAE,OAAwB;QAC7C,IAAI,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACxC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,KAAK,GAAG,EAAE,CAAC;YACX,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACrC,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpB,IAAI,KAAK,CAAC,MAAM,GAAG,sBAAsB,EAAE,CAAC;YAC1C,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,gBAAgB;QACjC,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,GAAG,CAAC,SAAiB,EAAE,KAAc;QACnC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;QAChD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC;QACpB,CAAC;QACD,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,KAAK,CAAC,CAAC;IAClD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,SAAiB;QACrB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,SAAiB;QACtB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACjC,CAAC;CACF"}
|