crewly 1.4.58 → 1.4.60
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/backend/backend/src/controllers/cloud/cloud.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/cloud/cloud.controller.js +8 -0
- package/dist/backend/backend/src/controllers/cloud/cloud.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js +41 -0
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-initializer.d.ts +10 -0
- package/dist/backend/backend/src/services/cloud/cloud-initializer.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-initializer.js +72 -8
- package/dist/backend/backend/src/services/cloud/cloud-initializer.js.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-sync.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-sync.service.js +20 -6
- package/dist/backend/backend/src/services/cloud/cloud-sync.service.js.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-sync.types.d.ts +39 -1
- package/dist/backend/backend/src/services/cloud/cloud-sync.types.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-sync.types.js +16 -0
- package/dist/backend/backend/src/services/cloud/cloud-sync.types.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/message-router.service.d.ts +157 -0
- package/dist/backend/backend/src/services/messaging/message-router.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/messaging/message-router.service.js +317 -0
- package/dist/backend/backend/src/services/messaging/message-router.service.js.map +1 -0
- package/frontend/dist/assets/{index-78e43622.css → index-e2a673d6.css} +1 -1
- package/frontend/dist/assets/{index-988e322e.js → index-e830dc67.js} +309 -309
- package/frontend/dist/index.html +2 -2
- package/package.json +1 -1
|
@@ -26,6 +26,15 @@ export interface CloudSyncConfig {
|
|
|
26
26
|
/** Human-readable device name (OS hostname) */
|
|
27
27
|
deviceName: string;
|
|
28
28
|
}
|
|
29
|
+
/** Summary of an agent running on a device, included in heartbeat payloads. */
|
|
30
|
+
export interface SyncAgentInfo {
|
|
31
|
+
/** Agent PTY session name (e.g. "crewly-product-leo-member-n") */
|
|
32
|
+
sessionName: string;
|
|
33
|
+
/** Agent role (e.g. "developer", "orchestrator") */
|
|
34
|
+
role: string;
|
|
35
|
+
/** Agent working status */
|
|
36
|
+
workingStatus: string;
|
|
37
|
+
}
|
|
29
38
|
/** Summary of a team on a device, included in heartbeat payloads. */
|
|
30
39
|
export interface SyncTeamSummary {
|
|
31
40
|
/** Team identifier */
|
|
@@ -36,6 +45,8 @@ export interface SyncTeamSummary {
|
|
|
36
45
|
memberCount: number;
|
|
37
46
|
/** Number of currently active agents */
|
|
38
47
|
activeAgents: number;
|
|
48
|
+
/** Active agent session details (for cross-device routing) */
|
|
49
|
+
agents?: SyncAgentInfo[];
|
|
39
50
|
}
|
|
40
51
|
/**
|
|
41
52
|
* A device visible in the same Cloud account.
|
|
@@ -88,7 +99,7 @@ export interface HeartbeatPayload {
|
|
|
88
99
|
timestamp: string;
|
|
89
100
|
}
|
|
90
101
|
/** All supported message types for inter-device communication. */
|
|
91
|
-
export type MessageType = 'command' | 'sync_teams' | 'sync_settings' | 'notification' | 'relay' | 'ping' | 'task_update';
|
|
102
|
+
export type MessageType = 'command' | 'sync_teams' | 'sync_settings' | 'notification' | 'relay' | 'ping' | 'task_update' | 'agent_message';
|
|
92
103
|
/** Valid message type values for runtime validation. */
|
|
93
104
|
export declare const MESSAGE_TYPES: readonly MessageType[];
|
|
94
105
|
/**
|
|
@@ -151,6 +162,33 @@ export interface TaskUpdatePayload {
|
|
|
151
162
|
/** Summary of what was done */
|
|
152
163
|
summary?: string;
|
|
153
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* Payload for an agent_message sent between devices for transparent
|
|
167
|
+
* cross-device agent communication. The orchestrator's send-message /
|
|
168
|
+
* delegate-task skills remain unchanged — the message router transparently
|
|
169
|
+
* wraps undeliverable local messages into this payload and routes via Cloud.
|
|
170
|
+
*/
|
|
171
|
+
export interface AgentMessagePayload {
|
|
172
|
+
/** Target agent session name on the remote device */
|
|
173
|
+
targetSession: string;
|
|
174
|
+
/** The message content to deliver */
|
|
175
|
+
message: string;
|
|
176
|
+
/** Source device ID */
|
|
177
|
+
fromDevice: string;
|
|
178
|
+
/** Human-readable source device name */
|
|
179
|
+
fromDeviceName: string;
|
|
180
|
+
/** Delivery priority */
|
|
181
|
+
priority?: 'high' | 'normal';
|
|
182
|
+
/** Optional correlation ID for request-response patterns */
|
|
183
|
+
correlationId?: string;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Check if an object satisfies the AgentMessagePayload interface shape.
|
|
187
|
+
*
|
|
188
|
+
* @param value - Value to check
|
|
189
|
+
* @returns True if the value has the required AgentMessagePayload fields
|
|
190
|
+
*/
|
|
191
|
+
export declare function isAgentMessagePayload(value: unknown): value is AgentMessagePayload;
|
|
154
192
|
/**
|
|
155
193
|
* Check if a value is a valid CloudSyncState.
|
|
156
194
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloud-sync.types.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/cloud/cloud-sync.types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,yDAAyD;AACzD,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAE7D,4DAA4D;AAC5D,eAAO,MAAM,iBAAiB,0CAA2C,CAAC;AAM1E;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,UAAU,EAAE,MAAM,CAAC;CACpB;AAMD,qEAAqE;AACrE,MAAM,WAAW,eAAe;IAC9B,sBAAsB;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,YAAY,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"cloud-sync.types.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/cloud/cloud-sync.types.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,7 +19,23 @@ export const MESSAGE_TYPES = [
|
|
|
19
19
|
'relay',
|
|
20
20
|
'ping',
|
|
21
21
|
'task_update',
|
|
22
|
+
'agent_message',
|
|
22
23
|
];
|
|
24
|
+
/**
|
|
25
|
+
* Check if an object satisfies the AgentMessagePayload interface shape.
|
|
26
|
+
*
|
|
27
|
+
* @param value - Value to check
|
|
28
|
+
* @returns True if the value has the required AgentMessagePayload fields
|
|
29
|
+
*/
|
|
30
|
+
export function isAgentMessagePayload(value) {
|
|
31
|
+
if (typeof value !== 'object' || value === null)
|
|
32
|
+
return false;
|
|
33
|
+
const obj = value;
|
|
34
|
+
return (typeof obj.targetSession === 'string' &&
|
|
35
|
+
typeof obj.message === 'string' &&
|
|
36
|
+
typeof obj.fromDevice === 'string' &&
|
|
37
|
+
typeof obj.fromDeviceName === 'string');
|
|
38
|
+
}
|
|
23
39
|
// ---------------------------------------------------------------------------
|
|
24
40
|
// Type Guards
|
|
25
41
|
// ---------------------------------------------------------------------------
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloud-sync.types.js","sourceRoot":"","sources":["../../../../../../backend/src/services/cloud/cloud-sync.types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AASH,4DAA4D;AAC5D,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,CAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"cloud-sync.types.js","sourceRoot":"","sources":["../../../../../../backend/src/services/cloud/cloud-sync.types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AASH,4DAA4D;AAC5D,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,CAAU,CAAC;AAwH1E,wDAAwD;AACxD,MAAM,CAAC,MAAM,aAAa,GAA2B;IACnD,SAAS;IACT,YAAY;IACZ,eAAe;IACf,cAAc;IACd,OAAO;IACP,MAAM;IACN,aAAa;IACb,eAAe;CACP,CAAC;AAuFX;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAc;IAClD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC9D,MAAM,GAAG,GAAG,KAAgC,CAAC;IAC7C,OAAO,CACL,OAAO,GAAG,CAAC,aAAa,KAAK,QAAQ;QACrC,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;QAC/B,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ;QAClC,OAAO,GAAG,CAAC,cAAc,KAAK,QAAQ,CACvC,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,cAAc;AACd,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,iBAAiB,CAAC,QAAQ,CAAC,KAAuB,CAAC,CAAC;AAC1F,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,aAAa,CAAC,QAAQ,CAAC,KAAoB,CAAC,CAAC;AACnF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC9D,MAAM,GAAG,GAAG,KAAgC,CAAC;IAC7C,OAAO,CACL,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ;QAChC,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ;QAClC,CAAC,GAAG,CAAC,MAAM,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC;QACrD,OAAO,GAAG,CAAC,eAAe,KAAK,QAAQ,CACxC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC9D,MAAM,GAAG,GAAG,KAAgC,CAAC;IAC7C,OAAO,CACL,OAAO,GAAG,CAAC,EAAE,KAAK,QAAQ;QAC1B,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ;QAC5B,OAAO,GAAG,CAAC,cAAc,KAAK,QAAQ;QACtC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC;QACvB,OAAO,GAAG,CAAC,SAAS,KAAK,SAAS;QAClC,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,CAC/B,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC9D,MAAM,GAAG,GAAG,KAAgC,CAAC;IAC7C,OAAO,CACL,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ;QAChC,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ;QAC7B,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ;QAChC,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ,CACnC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,157 @@
|
|
|
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 type { SyncDevice, IncomingMessage } from '../cloud/cloud-sync.types.js';
|
|
19
|
+
/** Constants for the MessageRouterService. */
|
|
20
|
+
export declare const MESSAGE_ROUTER_CONSTANTS: {
|
|
21
|
+
/** Maximum time to wait for remote delivery confirmation (ms) */
|
|
22
|
+
readonly REMOTE_DELIVERY_TIMEOUT_MS: 15000;
|
|
23
|
+
/** Log component name */
|
|
24
|
+
readonly COMPONENT_NAME: "MessageRouterService";
|
|
25
|
+
};
|
|
26
|
+
/** Result of a remote routing attempt. */
|
|
27
|
+
export interface RouteResult {
|
|
28
|
+
/** Whether the message was successfully routed to a remote device */
|
|
29
|
+
routed: boolean;
|
|
30
|
+
/** Target device ID (if routed) */
|
|
31
|
+
deviceId?: string;
|
|
32
|
+
/** Target device name (if routed) */
|
|
33
|
+
deviceName?: string;
|
|
34
|
+
/** Error message (if routing failed) */
|
|
35
|
+
error?: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Handler function for delivering a message to a local agent session.
|
|
39
|
+
* Injected via setLocalDeliveryHandler() to avoid circular dependencies
|
|
40
|
+
* with terminal.controller / AgentRegistrationService.
|
|
41
|
+
*/
|
|
42
|
+
export type LocalDeliveryHandler = (sessionName: string, message: string) => Promise<{
|
|
43
|
+
success: boolean;
|
|
44
|
+
error?: string;
|
|
45
|
+
}>;
|
|
46
|
+
/**
|
|
47
|
+
* MessageRouterService singleton.
|
|
48
|
+
*
|
|
49
|
+
* Transparently routes agent messages across devices under the same
|
|
50
|
+
* Cloud account. Local sessions are delivered directly; remote sessions
|
|
51
|
+
* are forwarded via the Cloud message queue.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* const router = MessageRouterService.getInstance();
|
|
56
|
+
* router.setLocalDeliveryHandler(myDeliveryFn);
|
|
57
|
+
* router.startListening();
|
|
58
|
+
*
|
|
59
|
+
* // Route a message — automatically determines local vs remote
|
|
60
|
+
* const result = await router.routeRemote('crewly-product-leo', 'Hello Leo');
|
|
61
|
+
* if (result.routed) {
|
|
62
|
+
* console.log(`Routed to device ${result.deviceName}`);
|
|
63
|
+
* }
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export declare class MessageRouterService {
|
|
67
|
+
private static instance;
|
|
68
|
+
private readonly logger;
|
|
69
|
+
/** Whether we are listening for incoming agent_message events */
|
|
70
|
+
private listening;
|
|
71
|
+
/** Bound handler reference for cleanup */
|
|
72
|
+
private boundMessageHandler;
|
|
73
|
+
/** Handler for delivering messages to local agent sessions */
|
|
74
|
+
private localDeliveryHandler;
|
|
75
|
+
private constructor();
|
|
76
|
+
/**
|
|
77
|
+
* Get the singleton instance.
|
|
78
|
+
*
|
|
79
|
+
* @returns MessageRouterService instance
|
|
80
|
+
*/
|
|
81
|
+
static getInstance(): MessageRouterService;
|
|
82
|
+
/**
|
|
83
|
+
* Reset the singleton (for testing).
|
|
84
|
+
*/
|
|
85
|
+
static resetInstance(): void;
|
|
86
|
+
/**
|
|
87
|
+
* Set the handler used to deliver messages to local agent sessions.
|
|
88
|
+
* Must be called before startListening() to enable incoming message delivery.
|
|
89
|
+
*
|
|
90
|
+
* @param handler - Function that delivers a message to a local session
|
|
91
|
+
*/
|
|
92
|
+
setLocalDeliveryHandler(handler: LocalDeliveryHandler): void;
|
|
93
|
+
/**
|
|
94
|
+
* Find which remote device hosts the given agent session.
|
|
95
|
+
*
|
|
96
|
+
* Searches the cached device list from CloudSyncService, inspecting
|
|
97
|
+
* each device's team summaries for matching agent session names.
|
|
98
|
+
*
|
|
99
|
+
* @param sessionName - Target agent session name
|
|
100
|
+
* @returns The SyncDevice hosting the session, or null if not found
|
|
101
|
+
*/
|
|
102
|
+
findDeviceForSession(sessionName: string): SyncDevice | null;
|
|
103
|
+
/**
|
|
104
|
+
* Route a message to a remote device via the Cloud message queue.
|
|
105
|
+
*
|
|
106
|
+
* Called when a target agent session is not found locally. Queries
|
|
107
|
+
* CloudSyncService for the device hosting that session and sends
|
|
108
|
+
* an `agent_message` through the Cloud queue.
|
|
109
|
+
*
|
|
110
|
+
* @param targetSession - Target agent session name
|
|
111
|
+
* @param message - Message content to deliver
|
|
112
|
+
* @param priority - Delivery priority (default: 'normal')
|
|
113
|
+
* @returns RouteResult indicating success/failure
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* const result = await router.routeRemote('crewly-product-leo', 'Build the feature');
|
|
118
|
+
* if (!result.routed) {
|
|
119
|
+
* console.error('Remote routing failed:', result.error);
|
|
120
|
+
* }
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
routeRemote(targetSession: string, message: string, priority?: 'high' | 'normal'): Promise<RouteResult>;
|
|
124
|
+
/**
|
|
125
|
+
* Start listening for incoming `agent_message` events from CloudSyncService.
|
|
126
|
+
*
|
|
127
|
+
* When an `agent_message` is received, it extracts the target session name
|
|
128
|
+
* and delivers the message to the local agent via the configured
|
|
129
|
+
* localDeliveryHandler.
|
|
130
|
+
*/
|
|
131
|
+
startListening(): void;
|
|
132
|
+
/**
|
|
133
|
+
* Stop listening for incoming messages.
|
|
134
|
+
*/
|
|
135
|
+
stopListening(): void;
|
|
136
|
+
/**
|
|
137
|
+
* Handle an incoming message from CloudSyncService.
|
|
138
|
+
* Only processes messages of type `agent_message`.
|
|
139
|
+
*
|
|
140
|
+
* @param msg - The incoming message from another device
|
|
141
|
+
*/
|
|
142
|
+
handleIncomingMessage(msg: IncomingMessage): Promise<void>;
|
|
143
|
+
/**
|
|
144
|
+
* Check if the router is currently listening for incoming messages.
|
|
145
|
+
*
|
|
146
|
+
* @returns True if listening
|
|
147
|
+
*/
|
|
148
|
+
isListening(): boolean;
|
|
149
|
+
/**
|
|
150
|
+
* Get local device identity info from CloudSyncService config.
|
|
151
|
+
* Falls back to defaults if sync is not started.
|
|
152
|
+
*
|
|
153
|
+
* @returns Object with deviceId and deviceName
|
|
154
|
+
*/
|
|
155
|
+
private getLocalDeviceInfo;
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=message-router.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-router.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/messaging/message-router.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,KAAK,EACV,UAAU,EACV,eAAe,EAEhB,MAAM,8BAA8B,CAAC;AAOtC,8CAA8C;AAC9C,eAAO,MAAM,wBAAwB;IACnC,iEAAiE;;IAEjE,yBAAyB;;CAEjB,CAAC;AAMX,0CAA0C;AAC1C,MAAM,WAAW,WAAW;IAC1B,qEAAqE;IACrE,MAAM,EAAE,OAAO,CAAC;IAChB,mCAAmC;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qCAAqC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,CACjC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,KACZ,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAMnD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAqC;IAC5D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IAEzC,iEAAiE;IACjE,OAAO,CAAC,SAAS,CAAS;IAC1B,0CAA0C;IAC1C,OAAO,CAAC,mBAAmB,CAAiD;IAC5E,8DAA8D;IAC9D,OAAO,CAAC,oBAAoB,CAAqC;IAEjE,OAAO;IAMP;;;;OAIG;IACH,MAAM,CAAC,WAAW,IAAI,oBAAoB;IAO1C;;OAEG;IACH,MAAM,CAAC,aAAa,IAAI,IAAI;IAW5B;;;;;OAKG;IACH,uBAAuB,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI;IAQ5D;;;;;;;;OAQG;IACH,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAqB5D;;;;;;;;;;;;;;;;;;;OAmBG;IACG,WAAW,CACf,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACf,QAAQ,GAAE,MAAM,GAAG,QAAmB,GACrC,OAAO,CAAC,WAAW,CAAC;IAyDvB;;;;;;OAMG;IACH,cAAc,IAAI,IAAI;IAkBtB;;OAEG;IACH,aAAa,IAAI,IAAI;IAUrB;;;;;OAKG;IACG,qBAAqB,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAqDhE;;;;OAIG;IACH,WAAW,IAAI,OAAO;IAQtB;;;;;OAKG;IACH,OAAO,CAAC,kBAAkB;CAa3B"}
|
|
@@ -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"}
|