@principal-ai/control-tower-core 0.1.9 → 0.1.11
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/adapters/websocket/WebSocketClientTransportAdapter.d.ts +78 -0
- package/dist/adapters/websocket/WebSocketClientTransportAdapter.d.ts.map +1 -0
- package/dist/adapters/websocket/WebSocketClientTransportAdapter.js +227 -0
- package/dist/adapters/websocket/WebSocketServerTransportAdapter.d.ts +60 -0
- package/dist/adapters/websocket/WebSocketServerTransportAdapter.d.ts.map +1 -0
- package/dist/adapters/websocket/WebSocketServerTransportAdapter.js +386 -0
- package/dist/adapters/websocket/index.d.ts +2 -1
- package/dist/adapters/websocket/index.d.ts.map +1 -1
- package/dist/adapters/websocket/index.js +5 -3
- package/dist/client/BaseClient.d.ts.map +1 -1
- package/dist/client/BaseClient.js +4 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +6 -5
- package/dist/index.mjs +188 -4
- package/dist/index.mjs.map +6 -5
- package/package.json +1 -1
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { ITransportAdapter } from '../../abstractions/TransportAdapter.js';
|
|
2
|
+
import type { ConnectionState, ConnectionOptions, Message, MessageHandler, ErrorHandler, CloseHandler } from '../../types/index.js';
|
|
3
|
+
import { WebSocket } from 'ws';
|
|
4
|
+
export interface WebSocketClientConfig {
|
|
5
|
+
/**
|
|
6
|
+
* Additional headers to send with the WebSocket connection request
|
|
7
|
+
*/
|
|
8
|
+
headers?: Record<string, string>;
|
|
9
|
+
/**
|
|
10
|
+
* Connection timeout in milliseconds
|
|
11
|
+
* @default 30000
|
|
12
|
+
*/
|
|
13
|
+
connectionTimeout?: number;
|
|
14
|
+
/**
|
|
15
|
+
* Enable automatic ping/pong for connection health checks
|
|
16
|
+
* @default true
|
|
17
|
+
*/
|
|
18
|
+
enableHeartbeat?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Heartbeat interval in milliseconds
|
|
21
|
+
* @default 30000
|
|
22
|
+
*/
|
|
23
|
+
heartbeatInterval?: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* WebSocket client transport adapter for connecting to remote WebSocket servers.
|
|
27
|
+
*
|
|
28
|
+
* This adapter creates an outgoing WebSocket connection and is intended for use
|
|
29
|
+
* with BaseClient. For server-side operations (accepting incoming connections),
|
|
30
|
+
* use WebSocketServerTransportAdapter instead.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```typescript
|
|
34
|
+
* const transport = new WebSocketClientTransportAdapter();
|
|
35
|
+
* const client = new ClientBuilder()
|
|
36
|
+
* .withTransport(transport)
|
|
37
|
+
* .build();
|
|
38
|
+
*
|
|
39
|
+
* await client.connect('ws://localhost:3000');
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare class WebSocketClientTransportAdapter implements ITransportAdapter {
|
|
43
|
+
private ws?;
|
|
44
|
+
private state;
|
|
45
|
+
private messageHandlers;
|
|
46
|
+
private errorHandlers;
|
|
47
|
+
private closeHandlers;
|
|
48
|
+
private config;
|
|
49
|
+
private heartbeatTimer?;
|
|
50
|
+
private connectionTimer?;
|
|
51
|
+
constructor(config?: WebSocketClientConfig);
|
|
52
|
+
connect(url: string, options?: ConnectionOptions): Promise<void>;
|
|
53
|
+
disconnect(): Promise<void>;
|
|
54
|
+
send(message: Message): Promise<void>;
|
|
55
|
+
onMessage(handler: MessageHandler): void;
|
|
56
|
+
onError(handler: ErrorHandler): void;
|
|
57
|
+
onClose(handler: CloseHandler): void;
|
|
58
|
+
getState(): ConnectionState;
|
|
59
|
+
isConnected(): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Get the underlying WebSocket instance
|
|
62
|
+
* Useful for advanced use cases
|
|
63
|
+
*/
|
|
64
|
+
getWebSocket(): WebSocket | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* Set custom headers for the WebSocket connection
|
|
67
|
+
* Must be called before connect()
|
|
68
|
+
*/
|
|
69
|
+
setHeaders(headers: Record<string, string>): void;
|
|
70
|
+
/**
|
|
71
|
+
* Add an authorization header for authentication
|
|
72
|
+
* Must be called before connect()
|
|
73
|
+
*/
|
|
74
|
+
setAuthToken(token: string): void;
|
|
75
|
+
private startHeartbeat;
|
|
76
|
+
private stopHeartbeat;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=WebSocketClientTransportAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebSocketClientTransportAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/websocket/WebSocketClientTransportAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAChF,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EACjB,OAAO,EACP,cAAc,EACd,YAAY,EACZ,YAAY,EACb,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAE/B,MAAM,WAAW,qBAAqB;IACpC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,+BAAgC,YAAW,iBAAiB;IACvE,OAAO,CAAC,EAAE,CAAC,CAAY;IACvB,OAAO,CAAC,KAAK,CAAmC;IAChD,OAAO,CAAC,eAAe,CAAkC;IACzD,OAAO,CAAC,aAAa,CAAgC;IACrD,OAAO,CAAC,aAAa,CAAgC;IACrD,OAAO,CAAC,MAAM,CAAkC;IAChD,OAAO,CAAC,cAAc,CAAC,CAAiB;IACxC,OAAO,CAAC,eAAe,CAAC,CAAiB;gBAE7B,MAAM,CAAC,EAAE,qBAAqB;IASpC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IA2GhE,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAsC3B,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB3C,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAIxC,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAIpC,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAIpC,QAAQ,IAAI,eAAe;IAI3B,WAAW,IAAI,OAAO;IAItB;;;OAGG;IACH,YAAY,IAAI,SAAS,GAAG,SAAS;IAIrC;;;OAGG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAOjD;;;OAGG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAMjC,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,aAAa;CAMtB"}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WebSocketClientTransportAdapter = void 0;
|
|
4
|
+
const ws_1 = require("ws");
|
|
5
|
+
/**
|
|
6
|
+
* WebSocket client transport adapter for connecting to remote WebSocket servers.
|
|
7
|
+
*
|
|
8
|
+
* This adapter creates an outgoing WebSocket connection and is intended for use
|
|
9
|
+
* with BaseClient. For server-side operations (accepting incoming connections),
|
|
10
|
+
* use WebSocketServerTransportAdapter instead.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const transport = new WebSocketClientTransportAdapter();
|
|
15
|
+
* const client = new ClientBuilder()
|
|
16
|
+
* .withTransport(transport)
|
|
17
|
+
* .build();
|
|
18
|
+
*
|
|
19
|
+
* await client.connect('ws://localhost:3000');
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
class WebSocketClientTransportAdapter {
|
|
23
|
+
constructor(config) {
|
|
24
|
+
this.state = 'disconnected';
|
|
25
|
+
this.messageHandlers = new Set();
|
|
26
|
+
this.errorHandlers = new Set();
|
|
27
|
+
this.closeHandlers = new Set();
|
|
28
|
+
this.config = {
|
|
29
|
+
headers: config?.headers ?? {},
|
|
30
|
+
connectionTimeout: config?.connectionTimeout ?? 30000,
|
|
31
|
+
enableHeartbeat: config?.enableHeartbeat ?? true,
|
|
32
|
+
heartbeatInterval: config?.heartbeatInterval ?? 30000
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
async connect(url, options) {
|
|
36
|
+
if (this.state === 'connected' || this.state === 'connecting') {
|
|
37
|
+
throw new Error('Already connected or connecting');
|
|
38
|
+
}
|
|
39
|
+
this.state = 'connecting';
|
|
40
|
+
return new Promise((resolve, reject) => {
|
|
41
|
+
try {
|
|
42
|
+
// Create WebSocket client connection
|
|
43
|
+
const wsOptions = {};
|
|
44
|
+
// Add custom headers if provided
|
|
45
|
+
if (Object.keys(this.config.headers).length > 0) {
|
|
46
|
+
wsOptions.headers = this.config.headers;
|
|
47
|
+
}
|
|
48
|
+
this.ws = new ws_1.WebSocket(url, wsOptions);
|
|
49
|
+
// Set up connection timeout
|
|
50
|
+
this.connectionTimer = setTimeout(() => {
|
|
51
|
+
if (this.state === 'connecting') {
|
|
52
|
+
this.ws?.terminate();
|
|
53
|
+
this.state = 'disconnected';
|
|
54
|
+
const error = new Error('Connection timeout');
|
|
55
|
+
this.errorHandlers.forEach(handler => handler(error));
|
|
56
|
+
reject(error);
|
|
57
|
+
}
|
|
58
|
+
}, this.config.connectionTimeout);
|
|
59
|
+
// Handle connection open
|
|
60
|
+
this.ws.on('open', () => {
|
|
61
|
+
if (this.connectionTimer) {
|
|
62
|
+
clearTimeout(this.connectionTimer);
|
|
63
|
+
this.connectionTimer = undefined;
|
|
64
|
+
}
|
|
65
|
+
this.state = 'connected';
|
|
66
|
+
// Start heartbeat if enabled
|
|
67
|
+
if (this.config.enableHeartbeat) {
|
|
68
|
+
this.startHeartbeat();
|
|
69
|
+
}
|
|
70
|
+
resolve();
|
|
71
|
+
});
|
|
72
|
+
// Handle incoming messages
|
|
73
|
+
this.ws.on('message', (data) => {
|
|
74
|
+
try {
|
|
75
|
+
const message = JSON.parse(data.toString());
|
|
76
|
+
this.messageHandlers.forEach(handler => handler(message));
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
this.errorHandlers.forEach(handler => handler(error));
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
// Handle errors
|
|
83
|
+
this.ws.on('error', (error) => {
|
|
84
|
+
if (this.connectionTimer) {
|
|
85
|
+
clearTimeout(this.connectionTimer);
|
|
86
|
+
this.connectionTimer = undefined;
|
|
87
|
+
}
|
|
88
|
+
this.errorHandlers.forEach(handler => handler(error));
|
|
89
|
+
// If error occurs during connection, reject the promise
|
|
90
|
+
if (this.state === 'connecting') {
|
|
91
|
+
this.state = 'disconnected';
|
|
92
|
+
reject(error);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
// Handle connection close
|
|
96
|
+
this.ws.on('close', (code, reason) => {
|
|
97
|
+
if (this.connectionTimer) {
|
|
98
|
+
clearTimeout(this.connectionTimer);
|
|
99
|
+
this.connectionTimer = undefined;
|
|
100
|
+
}
|
|
101
|
+
this.stopHeartbeat();
|
|
102
|
+
const wasConnected = this.state === 'connected';
|
|
103
|
+
this.state = 'disconnected';
|
|
104
|
+
if (wasConnected) {
|
|
105
|
+
this.closeHandlers.forEach(handler => handler(code, reason.toString()));
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
// Handle pong responses for heartbeat
|
|
109
|
+
if (this.config.enableHeartbeat) {
|
|
110
|
+
this.ws.on('pong', () => {
|
|
111
|
+
// Connection is alive
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
if (this.connectionTimer) {
|
|
117
|
+
clearTimeout(this.connectionTimer);
|
|
118
|
+
this.connectionTimer = undefined;
|
|
119
|
+
}
|
|
120
|
+
this.state = 'disconnected';
|
|
121
|
+
reject(error);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
async disconnect() {
|
|
126
|
+
if (this.state === 'disconnected') {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
this.state = 'disconnecting';
|
|
130
|
+
this.stopHeartbeat();
|
|
131
|
+
if (this.connectionTimer) {
|
|
132
|
+
clearTimeout(this.connectionTimer);
|
|
133
|
+
this.connectionTimer = undefined;
|
|
134
|
+
}
|
|
135
|
+
if (this.ws) {
|
|
136
|
+
// Close with normal closure code
|
|
137
|
+
this.ws.close(1000, 'Client disconnecting');
|
|
138
|
+
// Wait for close event or timeout
|
|
139
|
+
await new Promise((resolve) => {
|
|
140
|
+
const timeout = setTimeout(() => {
|
|
141
|
+
this.ws?.terminate();
|
|
142
|
+
resolve();
|
|
143
|
+
}, 5000);
|
|
144
|
+
const onClose = () => {
|
|
145
|
+
clearTimeout(timeout);
|
|
146
|
+
resolve();
|
|
147
|
+
};
|
|
148
|
+
this.ws?.once('close', onClose);
|
|
149
|
+
});
|
|
150
|
+
this.ws = undefined;
|
|
151
|
+
}
|
|
152
|
+
this.state = 'disconnected';
|
|
153
|
+
}
|
|
154
|
+
async send(message) {
|
|
155
|
+
if (this.state !== 'connected') {
|
|
156
|
+
throw new Error('Not connected');
|
|
157
|
+
}
|
|
158
|
+
if (!this.ws || this.ws.readyState !== ws_1.WebSocket.OPEN) {
|
|
159
|
+
throw new Error('WebSocket connection is not open');
|
|
160
|
+
}
|
|
161
|
+
try {
|
|
162
|
+
const data = JSON.stringify(message);
|
|
163
|
+
this.ws.send(data);
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
this.errorHandlers.forEach(handler => handler(error));
|
|
167
|
+
throw error;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
onMessage(handler) {
|
|
171
|
+
this.messageHandlers.add(handler);
|
|
172
|
+
}
|
|
173
|
+
onError(handler) {
|
|
174
|
+
this.errorHandlers.add(handler);
|
|
175
|
+
}
|
|
176
|
+
onClose(handler) {
|
|
177
|
+
this.closeHandlers.add(handler);
|
|
178
|
+
}
|
|
179
|
+
getState() {
|
|
180
|
+
return this.state;
|
|
181
|
+
}
|
|
182
|
+
isConnected() {
|
|
183
|
+
return this.state === 'connected' && this.ws?.readyState === ws_1.WebSocket.OPEN;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Get the underlying WebSocket instance
|
|
187
|
+
* Useful for advanced use cases
|
|
188
|
+
*/
|
|
189
|
+
getWebSocket() {
|
|
190
|
+
return this.ws;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Set custom headers for the WebSocket connection
|
|
194
|
+
* Must be called before connect()
|
|
195
|
+
*/
|
|
196
|
+
setHeaders(headers) {
|
|
197
|
+
if (this.state !== 'disconnected') {
|
|
198
|
+
throw new Error('Cannot set headers while connected');
|
|
199
|
+
}
|
|
200
|
+
this.config.headers = { ...this.config.headers, ...headers };
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Add an authorization header for authentication
|
|
204
|
+
* Must be called before connect()
|
|
205
|
+
*/
|
|
206
|
+
setAuthToken(token) {
|
|
207
|
+
this.setHeaders({ Authorization: `Bearer ${token}` });
|
|
208
|
+
}
|
|
209
|
+
// Private methods
|
|
210
|
+
startHeartbeat() {
|
|
211
|
+
if (this.heartbeatTimer) {
|
|
212
|
+
clearInterval(this.heartbeatTimer);
|
|
213
|
+
}
|
|
214
|
+
this.heartbeatTimer = setInterval(() => {
|
|
215
|
+
if (this.ws && this.ws.readyState === ws_1.WebSocket.OPEN) {
|
|
216
|
+
this.ws.ping();
|
|
217
|
+
}
|
|
218
|
+
}, this.config.heartbeatInterval);
|
|
219
|
+
}
|
|
220
|
+
stopHeartbeat() {
|
|
221
|
+
if (this.heartbeatTimer) {
|
|
222
|
+
clearInterval(this.heartbeatTimer);
|
|
223
|
+
this.heartbeatTimer = undefined;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
exports.WebSocketClientTransportAdapter = WebSocketClientTransportAdapter;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { ITransportAdapter } from '../../abstractions/TransportAdapter.js';
|
|
2
|
+
import type { IAuthAdapter } from '../../abstractions/AuthAdapter.js';
|
|
3
|
+
import type { ConnectionState, ConnectionOptions, Message, MessageHandler, ErrorHandler, CloseHandler } from '../../types/index.js';
|
|
4
|
+
import type { Server as HttpServer } from 'http';
|
|
5
|
+
import type { Server as HttpsServer } from 'https';
|
|
6
|
+
import { WebSocketServer, WebSocket } from 'ws';
|
|
7
|
+
interface ClientConnection {
|
|
8
|
+
id: string;
|
|
9
|
+
ws: WebSocket;
|
|
10
|
+
userId?: string;
|
|
11
|
+
authenticated: boolean;
|
|
12
|
+
metadata?: Record<string, unknown>;
|
|
13
|
+
authTimeout?: NodeJS.Timeout;
|
|
14
|
+
connectedAt: number;
|
|
15
|
+
}
|
|
16
|
+
export interface WebSocketServerTransportConfig {
|
|
17
|
+
authTimeout?: number;
|
|
18
|
+
closeOnAuthFailure?: boolean;
|
|
19
|
+
requireAuth?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export declare class WebSocketServerTransportAdapter implements ITransportAdapter {
|
|
22
|
+
private state;
|
|
23
|
+
private messageHandlers;
|
|
24
|
+
private errorHandlers;
|
|
25
|
+
private closeHandlers;
|
|
26
|
+
private wss?;
|
|
27
|
+
private serverUrl?;
|
|
28
|
+
private attachedServer?;
|
|
29
|
+
private attachedWss?;
|
|
30
|
+
private webSocketPath?;
|
|
31
|
+
private clients;
|
|
32
|
+
private mode;
|
|
33
|
+
private authAdapter?;
|
|
34
|
+
private config;
|
|
35
|
+
constructor(config?: WebSocketServerTransportConfig);
|
|
36
|
+
setAuthAdapter(auth: IAuthAdapter): void;
|
|
37
|
+
connect(url: string, _options?: ConnectionOptions): Promise<void>;
|
|
38
|
+
attach(server: HttpServer | HttpsServer, path?: string): Promise<void>;
|
|
39
|
+
attachToWebSocketServer(wss: WebSocketServer): Promise<void>;
|
|
40
|
+
private handleConnection;
|
|
41
|
+
private handleClientMessage;
|
|
42
|
+
private handleAuthMessage;
|
|
43
|
+
private extractBearerToken;
|
|
44
|
+
private sendToClient;
|
|
45
|
+
disconnect(): Promise<void>;
|
|
46
|
+
send(message: Message): Promise<void>;
|
|
47
|
+
onMessage(handler: MessageHandler): void;
|
|
48
|
+
onError(handler: ErrorHandler): void;
|
|
49
|
+
onClose(handler: CloseHandler): void;
|
|
50
|
+
getState(): ConnectionState;
|
|
51
|
+
isConnected(): boolean;
|
|
52
|
+
getConnectedClients(): ClientConnection[];
|
|
53
|
+
getAuthenticatedClients(): ClientConnection[];
|
|
54
|
+
getClientCount(): number;
|
|
55
|
+
getMode(): 'standalone' | 'integration';
|
|
56
|
+
isAuthRequired(): boolean;
|
|
57
|
+
private generateId;
|
|
58
|
+
}
|
|
59
|
+
export {};
|
|
60
|
+
//# sourceMappingURL=WebSocketServerTransportAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebSocketServerTransportAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/websocket/WebSocketServerTransportAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAChF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EACjB,OAAO,EACP,cAAc,EACd,YAAY,EACZ,YAAY,EAGb,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,IAAI,WAAW,EAAE,MAAM,OAAO,CAAC;AAEnD,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAEhD,UAAU,gBAAgB;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,SAAS,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,8BAA8B;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,qBAAa,+BAAgC,YAAW,iBAAiB;IACvE,OAAO,CAAC,KAAK,CAAmC;IAChD,OAAO,CAAC,eAAe,CAAkC;IACzD,OAAO,CAAC,aAAa,CAAgC;IACrD,OAAO,CAAC,aAAa,CAAgC;IAGrD,OAAO,CAAC,GAAG,CAAC,CAAkB;IAC9B,OAAO,CAAC,SAAS,CAAC,CAAS;IAG3B,OAAO,CAAC,cAAc,CAAC,CAA2B;IAClD,OAAO,CAAC,WAAW,CAAC,CAAkB;IACtC,OAAO,CAAC,aAAa,CAAC,CAAS;IAG/B,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,IAAI,CAA8C;IAG1D,OAAO,CAAC,WAAW,CAAC,CAAe;IACnC,OAAO,CAAC,MAAM,CAAiC;gBAEnC,MAAM,CAAC,EAAE,8BAA8B;IAUnD,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAclC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAsCjE,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,WAAW,EAAE,IAAI,GAAE,MAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAiC7E,uBAAuB,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;YA2BpD,gBAAgB;YA6EhB,mBAAmB;YAuCnB,iBAAiB;IA4E/B,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,YAAY;IAMd,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAiC3B,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IA8B3C,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAIxC,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAIpC,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAIpC,QAAQ,IAAI,eAAe;IAI3B,WAAW,IAAI,OAAO;IAKtB,mBAAmB,IAAI,gBAAgB,EAAE;IAIzC,uBAAuB,IAAI,gBAAgB,EAAE;IAI7C,cAAc,IAAI,MAAM;IAIxB,OAAO,IAAI,YAAY,GAAG,aAAa;IAIvC,cAAc,IAAI,OAAO;IAIzB,OAAO,CAAC,UAAU;CAGnB"}
|