crewly 1.4.57 → 1.4.59

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 (30) hide show
  1. package/dist/backend/backend/src/controllers/cloud/cloud.controller.d.ts +13 -0
  2. package/dist/backend/backend/src/controllers/cloud/cloud.controller.d.ts.map +1 -1
  3. package/dist/backend/backend/src/controllers/cloud/cloud.controller.js +39 -0
  4. package/dist/backend/backend/src/controllers/cloud/cloud.controller.js.map +1 -1
  5. package/dist/backend/backend/src/controllers/cloud/cloud.routes.d.ts +1 -0
  6. package/dist/backend/backend/src/controllers/cloud/cloud.routes.d.ts.map +1 -1
  7. package/dist/backend/backend/src/controllers/cloud/cloud.routes.js +3 -1
  8. package/dist/backend/backend/src/controllers/cloud/cloud.routes.js.map +1 -1
  9. package/dist/backend/backend/src/controllers/monitoring/terminal.controller.d.ts.map +1 -1
  10. package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js +41 -0
  11. package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js.map +1 -1
  12. package/dist/backend/backend/src/services/cloud/cloud-initializer.d.ts +10 -0
  13. package/dist/backend/backend/src/services/cloud/cloud-initializer.d.ts.map +1 -1
  14. package/dist/backend/backend/src/services/cloud/cloud-initializer.js +55 -0
  15. package/dist/backend/backend/src/services/cloud/cloud-initializer.js.map +1 -1
  16. package/dist/backend/backend/src/services/cloud/cloud-sync.service.d.ts.map +1 -1
  17. package/dist/backend/backend/src/services/cloud/cloud-sync.service.js +44 -7
  18. package/dist/backend/backend/src/services/cloud/cloud-sync.service.js.map +1 -1
  19. package/dist/backend/backend/src/services/cloud/cloud-sync.types.d.ts +39 -1
  20. package/dist/backend/backend/src/services/cloud/cloud-sync.types.d.ts.map +1 -1
  21. package/dist/backend/backend/src/services/cloud/cloud-sync.types.js +16 -0
  22. package/dist/backend/backend/src/services/cloud/cloud-sync.types.js.map +1 -1
  23. package/dist/backend/backend/src/services/messaging/message-router.service.d.ts +157 -0
  24. package/dist/backend/backend/src/services/messaging/message-router.service.d.ts.map +1 -0
  25. package/dist/backend/backend/src/services/messaging/message-router.service.js +317 -0
  26. package/dist/backend/backend/src/services/messaging/message-router.service.js.map +1 -0
  27. package/frontend/dist/assets/{index-78e43622.css → index-e2a673d6.css} +1 -1
  28. package/frontend/dist/assets/{index-1b67fa33.js → index-e830dc67.js} +309 -309
  29. package/frontend/dist/index.html +2 -2
  30. package/package.json +1 -1
@@ -0,0 +1,317 @@
1
+ /**
2
+ * Message Router Service
3
+ *
4
+ * Provides transparent cross-device message routing for agent communication.
5
+ * When a target agent session is not found locally, the router queries
6
+ * CloudSyncService for same-account devices that host the agent and forwards
7
+ * the message through the Cloud message queue.
8
+ *
9
+ * On the receiving end, listens for incoming `agent_message` events from
10
+ * CloudSyncService and delivers them to the local agent session via the
11
+ * standard terminal delivery path.
12
+ *
13
+ * This makes cross-device communication fully transparent to callers —
14
+ * orchestrator skills (send-message, delegate-task) require zero changes.
15
+ *
16
+ * @module services/messaging/message-router.service
17
+ */
18
+ import { LoggerService } from '../core/logger.service.js';
19
+ import { CloudSyncService } from '../cloud/cloud-sync.service.js';
20
+ import { isAgentMessagePayload } from '../cloud/cloud-sync.types.js';
21
+ // ---------------------------------------------------------------------------
22
+ // Constants
23
+ // ---------------------------------------------------------------------------
24
+ /** Constants for the MessageRouterService. */
25
+ export const MESSAGE_ROUTER_CONSTANTS = {
26
+ /** Maximum time to wait for remote delivery confirmation (ms) */
27
+ REMOTE_DELIVERY_TIMEOUT_MS: 15_000,
28
+ /** Log component name */
29
+ COMPONENT_NAME: 'MessageRouterService',
30
+ };
31
+ // ---------------------------------------------------------------------------
32
+ // Service
33
+ // ---------------------------------------------------------------------------
34
+ /**
35
+ * MessageRouterService singleton.
36
+ *
37
+ * Transparently routes agent messages across devices under the same
38
+ * Cloud account. Local sessions are delivered directly; remote sessions
39
+ * are forwarded via the Cloud message queue.
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * const router = MessageRouterService.getInstance();
44
+ * router.setLocalDeliveryHandler(myDeliveryFn);
45
+ * router.startListening();
46
+ *
47
+ * // Route a message — automatically determines local vs remote
48
+ * const result = await router.routeRemote('crewly-product-leo', 'Hello Leo');
49
+ * if (result.routed) {
50
+ * console.log(`Routed to device ${result.deviceName}`);
51
+ * }
52
+ * ```
53
+ */
54
+ export class MessageRouterService {
55
+ static instance = null;
56
+ logger;
57
+ /** Whether we are listening for incoming agent_message events */
58
+ listening = false;
59
+ /** Bound handler reference for cleanup */
60
+ boundMessageHandler = null;
61
+ /** Handler for delivering messages to local agent sessions */
62
+ localDeliveryHandler = null;
63
+ constructor() {
64
+ this.logger = LoggerService.getInstance().createComponentLogger(MESSAGE_ROUTER_CONSTANTS.COMPONENT_NAME);
65
+ }
66
+ /**
67
+ * Get the singleton instance.
68
+ *
69
+ * @returns MessageRouterService instance
70
+ */
71
+ static getInstance() {
72
+ if (!MessageRouterService.instance) {
73
+ MessageRouterService.instance = new MessageRouterService();
74
+ }
75
+ return MessageRouterService.instance;
76
+ }
77
+ /**
78
+ * Reset the singleton (for testing).
79
+ */
80
+ static resetInstance() {
81
+ if (MessageRouterService.instance) {
82
+ MessageRouterService.instance.stopListening();
83
+ }
84
+ MessageRouterService.instance = null;
85
+ }
86
+ // -------------------------------------------------------------------------
87
+ // Configuration
88
+ // -------------------------------------------------------------------------
89
+ /**
90
+ * Set the handler used to deliver messages to local agent sessions.
91
+ * Must be called before startListening() to enable incoming message delivery.
92
+ *
93
+ * @param handler - Function that delivers a message to a local session
94
+ */
95
+ setLocalDeliveryHandler(handler) {
96
+ this.localDeliveryHandler = handler;
97
+ }
98
+ // -------------------------------------------------------------------------
99
+ // Outbound: Remote Routing
100
+ // -------------------------------------------------------------------------
101
+ /**
102
+ * Find which remote device hosts the given agent session.
103
+ *
104
+ * Searches the cached device list from CloudSyncService, inspecting
105
+ * each device's team summaries for matching agent session names.
106
+ *
107
+ * @param sessionName - Target agent session name
108
+ * @returns The SyncDevice hosting the session, or null if not found
109
+ */
110
+ findDeviceForSession(sessionName) {
111
+ const sync = CloudSyncService.getInstance();
112
+ if (!sync.isStarted())
113
+ return null;
114
+ const onlineDevices = sync.getOnlineDevices();
115
+ for (const device of onlineDevices) {
116
+ if (!device.teams)
117
+ continue;
118
+ for (const team of device.teams) {
119
+ if (!team.agents)
120
+ continue;
121
+ for (const agent of team.agents) {
122
+ if (agent.sessionName === sessionName) {
123
+ return device;
124
+ }
125
+ }
126
+ }
127
+ }
128
+ return null;
129
+ }
130
+ /**
131
+ * Route a message to a remote device via the Cloud message queue.
132
+ *
133
+ * Called when a target agent session is not found locally. Queries
134
+ * CloudSyncService for the device hosting that session and sends
135
+ * an `agent_message` through the Cloud queue.
136
+ *
137
+ * @param targetSession - Target agent session name
138
+ * @param message - Message content to deliver
139
+ * @param priority - Delivery priority (default: 'normal')
140
+ * @returns RouteResult indicating success/failure
141
+ *
142
+ * @example
143
+ * ```typescript
144
+ * const result = await router.routeRemote('crewly-product-leo', 'Build the feature');
145
+ * if (!result.routed) {
146
+ * console.error('Remote routing failed:', result.error);
147
+ * }
148
+ * ```
149
+ */
150
+ async routeRemote(targetSession, message, priority = 'normal') {
151
+ const sync = CloudSyncService.getInstance();
152
+ // Guard: CloudSync must be running
153
+ if (!sync.isStarted()) {
154
+ return { routed: false, error: 'CloudSyncService not started' };
155
+ }
156
+ // Find the device hosting this session
157
+ const targetDevice = this.findDeviceForSession(targetSession);
158
+ if (!targetDevice) {
159
+ return {
160
+ routed: false,
161
+ error: `Session '${targetSession}' not found on any online device`,
162
+ };
163
+ }
164
+ // Build the agent_message payload
165
+ const config = this.getLocalDeviceInfo();
166
+ const payload = {
167
+ targetSession,
168
+ message,
169
+ fromDevice: config.deviceId,
170
+ fromDeviceName: config.deviceName,
171
+ priority,
172
+ };
173
+ try {
174
+ await sync.sendMessage(targetDevice.deviceId, 'agent_message', payload);
175
+ this.logger.info('Message routed to remote device', {
176
+ targetSession,
177
+ deviceId: targetDevice.deviceId,
178
+ deviceName: targetDevice.deviceName,
179
+ messageLength: message.length,
180
+ });
181
+ return {
182
+ routed: true,
183
+ deviceId: targetDevice.deviceId,
184
+ deviceName: targetDevice.deviceName,
185
+ };
186
+ }
187
+ catch (error) {
188
+ const errorMsg = error instanceof Error ? error.message : String(error);
189
+ this.logger.error('Failed to route message to remote device', {
190
+ targetSession,
191
+ deviceId: targetDevice.deviceId,
192
+ error: errorMsg,
193
+ });
194
+ return { routed: false, error: errorMsg };
195
+ }
196
+ }
197
+ // -------------------------------------------------------------------------
198
+ // Inbound: Incoming Message Handling
199
+ // -------------------------------------------------------------------------
200
+ /**
201
+ * Start listening for incoming `agent_message` events from CloudSyncService.
202
+ *
203
+ * When an `agent_message` is received, it extracts the target session name
204
+ * and delivers the message to the local agent via the configured
205
+ * localDeliveryHandler.
206
+ */
207
+ startListening() {
208
+ if (this.listening)
209
+ return;
210
+ const sync = CloudSyncService.getInstance();
211
+ this.boundMessageHandler = (msg) => {
212
+ this.handleIncomingMessage(msg).catch((err) => {
213
+ this.logger.error('Error handling incoming agent_message', {
214
+ error: err instanceof Error ? err.message : String(err),
215
+ messageId: msg.id,
216
+ });
217
+ });
218
+ };
219
+ sync.on('message', this.boundMessageHandler);
220
+ this.listening = true;
221
+ this.logger.info('MessageRouterService started listening for agent_message events');
222
+ }
223
+ /**
224
+ * Stop listening for incoming messages.
225
+ */
226
+ stopListening() {
227
+ if (!this.listening || !this.boundMessageHandler)
228
+ return;
229
+ const sync = CloudSyncService.getInstance();
230
+ sync.removeListener('message', this.boundMessageHandler);
231
+ this.boundMessageHandler = null;
232
+ this.listening = false;
233
+ this.logger.info('MessageRouterService stopped listening');
234
+ }
235
+ /**
236
+ * Handle an incoming message from CloudSyncService.
237
+ * Only processes messages of type `agent_message`.
238
+ *
239
+ * @param msg - The incoming message from another device
240
+ */
241
+ async handleIncomingMessage(msg) {
242
+ // Only handle agent_message type
243
+ if (msg.type !== 'agent_message')
244
+ return;
245
+ const payload = msg.payload;
246
+ if (!isAgentMessagePayload(payload)) {
247
+ this.logger.warn('Received agent_message with invalid payload', {
248
+ messageId: msg.id,
249
+ from: msg.from,
250
+ });
251
+ return;
252
+ }
253
+ this.logger.info('Received remote agent_message', {
254
+ messageId: msg.id,
255
+ from: msg.fromDeviceName,
256
+ targetSession: payload.targetSession,
257
+ messageLength: payload.message.length,
258
+ });
259
+ // Deliver to the local agent session
260
+ if (!this.localDeliveryHandler) {
261
+ this.logger.error('No localDeliveryHandler configured — cannot deliver remote message', {
262
+ targetSession: payload.targetSession,
263
+ });
264
+ return;
265
+ }
266
+ try {
267
+ const result = await this.localDeliveryHandler(payload.targetSession, payload.message);
268
+ if (result.success) {
269
+ this.logger.info('Remote message delivered to local agent', {
270
+ targetSession: payload.targetSession,
271
+ from: payload.fromDeviceName,
272
+ });
273
+ }
274
+ else {
275
+ this.logger.warn('Failed to deliver remote message to local agent', {
276
+ targetSession: payload.targetSession,
277
+ error: result.error,
278
+ });
279
+ }
280
+ }
281
+ catch (error) {
282
+ this.logger.error('Exception delivering remote message to local agent', {
283
+ targetSession: payload.targetSession,
284
+ error: error instanceof Error ? error.message : String(error),
285
+ });
286
+ }
287
+ }
288
+ /**
289
+ * Check if the router is currently listening for incoming messages.
290
+ *
291
+ * @returns True if listening
292
+ */
293
+ isListening() {
294
+ return this.listening;
295
+ }
296
+ // -------------------------------------------------------------------------
297
+ // Internal Helpers
298
+ // -------------------------------------------------------------------------
299
+ /**
300
+ * Get local device identity info from CloudSyncService config.
301
+ * Falls back to defaults if sync is not started.
302
+ *
303
+ * @returns Object with deviceId and deviceName
304
+ */
305
+ getLocalDeviceInfo() {
306
+ // Access the device list and find our own entry
307
+ const sync = CloudSyncService.getInstance();
308
+ const devices = sync.getDevices();
309
+ const local = devices.find((d) => d.isLocal);
310
+ if (local) {
311
+ return { deviceId: local.deviceId, deviceName: local.deviceName };
312
+ }
313
+ // Fallback: return placeholder (will still work for logging)
314
+ return { deviceId: 'unknown', deviceName: 'unknown' };
315
+ }
316
+ }
317
+ //# sourceMappingURL=message-router.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-router.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/messaging/message-router.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,aAAa,EAAwB,MAAM,2BAA2B,CAAC;AAChF,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAMlE,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAErE,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E,8CAA8C;AAC9C,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,iEAAiE;IACjE,0BAA0B,EAAE,MAAM;IAClC,yBAAyB;IACzB,cAAc,EAAE,sBAAsB;CAC9B,CAAC;AA4BX,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,oBAAoB;IACvB,MAAM,CAAC,QAAQ,GAAgC,IAAI,CAAC;IAC3C,MAAM,CAAkB;IAEzC,iEAAiE;IACzD,SAAS,GAAG,KAAK,CAAC;IAC1B,0CAA0C;IAClC,mBAAmB,GAA4C,IAAI,CAAC;IAC5E,8DAA8D;IACtD,oBAAoB,GAAgC,IAAI,CAAC;IAEjE;QACE,IAAI,CAAC,MAAM,GAAG,aAAa,CAAC,WAAW,EAAE,CAAC,qBAAqB,CAC7D,wBAAwB,CAAC,cAAc,CACxC,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,WAAW;QAChB,IAAI,CAAC,oBAAoB,CAAC,QAAQ,EAAE,CAAC;YACnC,oBAAoB,CAAC,QAAQ,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC7D,CAAC;QACD,OAAO,oBAAoB,CAAC,QAAQ,CAAC;IACvC,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,aAAa;QAClB,IAAI,oBAAoB,CAAC,QAAQ,EAAE,CAAC;YAClC,oBAAoB,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;QAChD,CAAC;QACD,oBAAoB,CAAC,QAAQ,GAAG,IAAI,CAAC;IACvC,CAAC;IAED,4EAA4E;IAC5E,gBAAgB;IAChB,4EAA4E;IAE5E;;;;;OAKG;IACH,uBAAuB,CAAC,OAA6B;QACnD,IAAI,CAAC,oBAAoB,GAAG,OAAO,CAAC;IACtC,CAAC;IAED,4EAA4E;IAC5E,2BAA2B;IAC3B,4EAA4E;IAE5E;;;;;;;;OAQG;IACH,oBAAoB,CAAC,WAAmB;QACtC,MAAM,IAAI,GAAG,gBAAgB,CAAC,WAAW,EAAE,CAAC;QAC5C,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;YAAE,OAAO,IAAI,CAAC;QAEnC,MAAM,aAAa,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAE9C,KAAK,MAAM,MAAM,IAAI,aAAa,EAAE,CAAC;YACnC,IAAI,CAAC,MAAM,CAAC,KAAK;gBAAE,SAAS;YAC5B,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;gBAChC,IAAI,CAAC,IAAI,CAAC,MAAM;oBAAE,SAAS;gBAC3B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;oBAChC,IAAI,KAAK,CAAC,WAAW,KAAK,WAAW,EAAE,CAAC;wBACtC,OAAO,MAAM,CAAC;oBAChB,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,KAAK,CAAC,WAAW,CACf,aAAqB,EACrB,OAAe,EACf,WAA8B,QAAQ;QAEtC,MAAM,IAAI,GAAG,gBAAgB,CAAC,WAAW,EAAE,CAAC;QAE5C,mCAAmC;QACnC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;YACtB,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,8BAA8B,EAAE,CAAC;QAClE,CAAC;QAED,uCAAuC;QACvC,MAAM,YAAY,GAAG,IAAI,CAAC,oBAAoB,CAAC,aAAa,CAAC,CAAC;QAC9D,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,OAAO;gBACL,MAAM,EAAE,KAAK;gBACb,KAAK,EAAE,YAAY,aAAa,kCAAkC;aACnE,CAAC;QACJ,CAAC;QAED,kCAAkC;QAClC,MAAM,MAAM,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACzC,MAAM,OAAO,GAAwB;YACnC,aAAa;YACb,OAAO;YACP,UAAU,EAAE,MAAM,CAAC,QAAQ;YAC3B,cAAc,EAAE,MAAM,CAAC,UAAU;YACjC,QAAQ;SACT,CAAC;QAEF,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,QAAQ,EAAE,eAAe,EAAE,OAAO,CAAC,CAAC;YAExE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,iCAAiC,EAAE;gBAClD,aAAa;gBACb,QAAQ,EAAE,YAAY,CAAC,QAAQ;gBAC/B,UAAU,EAAE,YAAY,CAAC,UAAU;gBACnC,aAAa,EAAE,OAAO,CAAC,MAAM;aAC9B,CAAC,CAAC;YAEH,OAAO;gBACL,MAAM,EAAE,IAAI;gBACZ,QAAQ,EAAE,YAAY,CAAC,QAAQ;gBAC/B,UAAU,EAAE,YAAY,CAAC,UAAU;aACpC,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,QAAQ,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACxE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,0CAA0C,EAAE;gBAC5D,aAAa;gBACb,QAAQ,EAAE,YAAY,CAAC,QAAQ;gBAC/B,KAAK,EAAE,QAAQ;aAChB,CAAC,CAAC;YACH,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,4EAA4E;IAC5E,qCAAqC;IACrC,4EAA4E;IAE5E;;;;;;OAMG;IACH,cAAc;QACZ,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAE3B,MAAM,IAAI,GAAG,gBAAgB,CAAC,WAAW,EAAE,CAAC;QAC5C,IAAI,CAAC,mBAAmB,GAAG,CAAC,GAAoB,EAAE,EAAE;YAClD,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;gBAC5C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,uCAAuC,EAAE;oBACzD,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;oBACvD,SAAS,EAAE,GAAG,CAAC,EAAE;iBAClB,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC,CAAC;QAEF,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAC7C,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,iEAAiE,CAAC,CAAC;IACtF,CAAC;IAED;;OAEG;IACH,aAAa;QACX,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,mBAAmB;YAAE,OAAO;QAEzD,MAAM,IAAI,GAAG,gBAAgB,CAAC,WAAW,EAAE,CAAC;QAC5C,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,IAAI,CAAC,mBAAmB,CAAC,CAAC;QACzD,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC;QAChC,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;IAC7D,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,qBAAqB,CAAC,GAAoB;QAC9C,iCAAiC;QACjC,IAAI,GAAG,CAAC,IAAI,KAAK,eAAe;YAAE,OAAO;QAEzC,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;QAC5B,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,EAAE,CAAC;YACpC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,6CAA6C,EAAE;gBAC9D,SAAS,EAAE,GAAG,CAAC,EAAE;gBACjB,IAAI,EAAE,GAAG,CAAC,IAAI;aACf,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,+BAA+B,EAAE;YAChD,SAAS,EAAE,GAAG,CAAC,EAAE;YACjB,IAAI,EAAE,GAAG,CAAC,cAAc;YACxB,aAAa,EAAE,OAAO,CAAC,aAAa;YACpC,aAAa,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM;SACtC,CAAC,CAAC;QAEH,qCAAqC;QACrC,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC/B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,oEAAoE,EAAE;gBACtF,aAAa,EAAE,OAAO,CAAC,aAAa;aACrC,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAC5C,OAAO,CAAC,aAAa,EACrB,OAAO,CAAC,OAAO,CAChB,CAAC;YAEF,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,yCAAyC,EAAE;oBAC1D,aAAa,EAAE,OAAO,CAAC,aAAa;oBACpC,IAAI,EAAE,OAAO,CAAC,cAAc;iBAC7B,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,iDAAiD,EAAE;oBAClE,aAAa,EAAE,OAAO,CAAC,aAAa;oBACpC,KAAK,EAAE,MAAM,CAAC,KAAK;iBACpB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,oDAAoD,EAAE;gBACtE,aAAa,EAAE,OAAO,CAAC,aAAa;gBACpC,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAC9D,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,WAAW;QACT,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,4EAA4E;IAC5E,mBAAmB;IACnB,4EAA4E;IAE5E;;;;;OAKG;IACK,kBAAkB;QACxB,gDAAgD;QAChD,MAAM,IAAI,GAAG,gBAAgB,CAAC,WAAW,EAAE,CAAC;QAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QAE7C,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC;QACpE,CAAC;QAED,6DAA6D;QAC7D,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;IACxD,CAAC"}