@apart-tech/intelligence-core 0.1.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/config/index.d.ts +3 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +97 -0
- package/dist/config/index.js.map +1 -0
- package/dist/db/connection.d.ts +7 -0
- package/dist/db/connection.d.ts.map +1 -0
- package/dist/db/connection.js +49 -0
- package/dist/db/connection.js.map +1 -0
- package/dist/db/schema.d.ts +507 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +77 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/db/tenant.d.ts +8 -0
- package/dist/db/tenant.d.ts.map +1 -0
- package/dist/db/tenant.js +92 -0
- package/dist/db/tenant.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/index.d.ts +5 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +16 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/openai.d.ts +9 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +34 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/services/cleaning-service.d.ts +152 -0
- package/dist/services/cleaning-service.d.ts.map +1 -0
- package/dist/services/cleaning-service.js +632 -0
- package/dist/services/cleaning-service.js.map +1 -0
- package/dist/services/context-service.d.ts +13 -0
- package/dist/services/context-service.d.ts.map +1 -0
- package/dist/services/context-service.js +74 -0
- package/dist/services/context-service.js.map +1 -0
- package/dist/services/domain-seed-data.d.ts +8 -0
- package/dist/services/domain-seed-data.d.ts.map +1 -0
- package/dist/services/domain-seed-data.js +84 -0
- package/dist/services/domain-seed-data.js.map +1 -0
- package/dist/services/domain-service.d.ts +26 -0
- package/dist/services/domain-service.d.ts.map +1 -0
- package/dist/services/domain-service.js +101 -0
- package/dist/services/domain-service.js.map +1 -0
- package/dist/services/edge-service.d.ts +25 -0
- package/dist/services/edge-service.d.ts.map +1 -0
- package/dist/services/edge-service.js +90 -0
- package/dist/services/edge-service.js.map +1 -0
- package/dist/services/node-service.d.ts +34 -0
- package/dist/services/node-service.d.ts.map +1 -0
- package/dist/services/node-service.js +113 -0
- package/dist/services/node-service.js.map +1 -0
- package/dist/services/search-service.d.ts +15 -0
- package/dist/services/search-service.d.ts.map +1 -0
- package/dist/services/search-service.js +118 -0
- package/dist/services/search-service.js.map +1 -0
- package/dist/types/index.d.ts +74 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +42 -0
- package/prisma/schema.prisma +114 -0
|
@@ -0,0 +1,632 @@
|
|
|
1
|
+
import { tenantWhere, SINGLE_TENANT_ORG_ID } from "../db/tenant.js";
|
|
2
|
+
// ── Service ─────────────────────────────────────────────────────────────────
|
|
3
|
+
export class CleaningService {
|
|
4
|
+
db;
|
|
5
|
+
tenantCtx;
|
|
6
|
+
constructor(db, tenantCtx) {
|
|
7
|
+
this.db = db;
|
|
8
|
+
this.tenantCtx = tenantCtx ?? { organizationId: SINGLE_TENANT_ORG_ID };
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Find nodes with zero edges.
|
|
12
|
+
*/
|
|
13
|
+
async findOrphans() {
|
|
14
|
+
const orgFilter = tenantWhere(this.tenantCtx, "n");
|
|
15
|
+
const orphanIds = await this.db.$queryRaw `
|
|
16
|
+
SELECT n.id
|
|
17
|
+
FROM nodes n
|
|
18
|
+
LEFT JOIN edges e ON e.source_node_id = n.id OR e.target_node_id = n.id
|
|
19
|
+
WHERE e.id IS NULL
|
|
20
|
+
AND ${orgFilter}
|
|
21
|
+
ORDER BY n.created_at DESC
|
|
22
|
+
`;
|
|
23
|
+
if (orphanIds.length === 0)
|
|
24
|
+
return [];
|
|
25
|
+
const nodes = await this.db.node.findMany({
|
|
26
|
+
where: { id: { in: orphanIds.map((r) => r.id) } },
|
|
27
|
+
orderBy: { createdAt: "desc" },
|
|
28
|
+
});
|
|
29
|
+
return nodes.map((node) => ({ node }));
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Find node pairs with cosine similarity above threshold.
|
|
33
|
+
*/
|
|
34
|
+
async findDuplicates(threshold = 0.95, limit = 50) {
|
|
35
|
+
const orgFilterA = tenantWhere(this.tenantCtx, "a");
|
|
36
|
+
const pairs = await this.db.$queryRaw `
|
|
37
|
+
SELECT
|
|
38
|
+
a.id AS a_id,
|
|
39
|
+
b.id AS b_id,
|
|
40
|
+
1 - (a.embedding <=> b.embedding) AS similarity
|
|
41
|
+
FROM nodes a
|
|
42
|
+
JOIN nodes b ON a.id < b.id
|
|
43
|
+
WHERE a.embedding IS NOT NULL
|
|
44
|
+
AND b.embedding IS NOT NULL
|
|
45
|
+
AND 1 - (a.embedding <=> b.embedding) >= ${threshold}
|
|
46
|
+
AND ${orgFilterA}
|
|
47
|
+
ORDER BY similarity DESC
|
|
48
|
+
LIMIT ${limit}
|
|
49
|
+
`;
|
|
50
|
+
if (pairs.length === 0)
|
|
51
|
+
return [];
|
|
52
|
+
// Batch-fetch all involved nodes
|
|
53
|
+
const nodeIds = new Set();
|
|
54
|
+
for (const p of pairs) {
|
|
55
|
+
nodeIds.add(p.a_id);
|
|
56
|
+
nodeIds.add(p.b_id);
|
|
57
|
+
}
|
|
58
|
+
const nodes = await this.db.node.findMany({
|
|
59
|
+
where: { id: { in: [...nodeIds] } },
|
|
60
|
+
});
|
|
61
|
+
const nodeMap = new Map(nodes.map((n) => [n.id, n]));
|
|
62
|
+
return pairs
|
|
63
|
+
.filter((p) => nodeMap.has(p.a_id) && nodeMap.has(p.b_id))
|
|
64
|
+
.map((p) => ({
|
|
65
|
+
nodeA: nodeMap.get(p.a_id),
|
|
66
|
+
nodeB: nodeMap.get(p.b_id),
|
|
67
|
+
similarity: Number(p.similarity),
|
|
68
|
+
}));
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Comprehensive graph health report.
|
|
72
|
+
*/
|
|
73
|
+
async getHealthReport(staleDays = 90) {
|
|
74
|
+
const staleDate = new Date();
|
|
75
|
+
staleDate.setDate(staleDate.getDate() - staleDays);
|
|
76
|
+
const orgFilterN = tenantWhere(this.tenantCtx, "n");
|
|
77
|
+
const orgFilterE = tenantWhere(this.tenantCtx);
|
|
78
|
+
const orgFilterA = tenantWhere(this.tenantCtx, "a");
|
|
79
|
+
// Run independent queries in parallel
|
|
80
|
+
const [totalNodes, totalEdges, byStatus, byType, byRelType, orphanCount, undomainedCount, staleCount, selfLoopCount, duplicateEdgeRows, duplicateCandidateCount, allEdges,] = await Promise.all([
|
|
81
|
+
this.db.node.count(),
|
|
82
|
+
this.db.edge.count(),
|
|
83
|
+
this.db.node.groupBy({
|
|
84
|
+
by: ["status"],
|
|
85
|
+
_count: { status: true },
|
|
86
|
+
orderBy: { _count: { status: "desc" } },
|
|
87
|
+
}),
|
|
88
|
+
this.db.node.groupBy({
|
|
89
|
+
by: ["type"],
|
|
90
|
+
_count: { type: true },
|
|
91
|
+
orderBy: { _count: { type: "desc" } },
|
|
92
|
+
}),
|
|
93
|
+
this.db.edge.groupBy({
|
|
94
|
+
by: ["relationshipType"],
|
|
95
|
+
_count: { relationshipType: true },
|
|
96
|
+
orderBy: { _count: { relationshipType: "desc" } },
|
|
97
|
+
}),
|
|
98
|
+
this.db.$queryRaw `
|
|
99
|
+
SELECT COUNT(*) as count FROM nodes n
|
|
100
|
+
LEFT JOIN edges e ON e.source_node_id = n.id OR e.target_node_id = n.id
|
|
101
|
+
WHERE e.id IS NULL
|
|
102
|
+
AND ${orgFilterN}
|
|
103
|
+
`.then((r) => Number(r[0].count)),
|
|
104
|
+
this.db.node.count({ where: { domainId: null } }),
|
|
105
|
+
this.db.node.count({ where: { updatedAt: { lt: staleDate } } }),
|
|
106
|
+
this.db.$queryRaw `
|
|
107
|
+
SELECT COUNT(*) as count FROM edges
|
|
108
|
+
WHERE source_node_id = target_node_id
|
|
109
|
+
AND ${orgFilterE}
|
|
110
|
+
`.then((r) => Number(r[0].count)),
|
|
111
|
+
this.db.$queryRaw `
|
|
112
|
+
SELECT COUNT(*) as count FROM (
|
|
113
|
+
SELECT source_node_id, target_node_id, relationship_type
|
|
114
|
+
FROM edges
|
|
115
|
+
WHERE ${orgFilterE}
|
|
116
|
+
GROUP BY source_node_id, target_node_id, relationship_type
|
|
117
|
+
HAVING COUNT(*) > 1
|
|
118
|
+
) dupes
|
|
119
|
+
`.then((r) => Number(r[0].count)),
|
|
120
|
+
this.db.$queryRaw `
|
|
121
|
+
SELECT COUNT(*) as count FROM (
|
|
122
|
+
SELECT a.id
|
|
123
|
+
FROM nodes a
|
|
124
|
+
JOIN nodes b ON a.id < b.id
|
|
125
|
+
WHERE a.embedding IS NOT NULL
|
|
126
|
+
AND b.embedding IS NOT NULL
|
|
127
|
+
AND 1 - (a.embedding <=> b.embedding) >= 0.95
|
|
128
|
+
AND ${orgFilterA}
|
|
129
|
+
LIMIT 1
|
|
130
|
+
) pairs
|
|
131
|
+
`.then((r) => Number(r[0].count)),
|
|
132
|
+
this.db.edge.findMany({ select: { sourceNodeId: true, targetNodeId: true } }),
|
|
133
|
+
]);
|
|
134
|
+
// Compute connected components via union-find
|
|
135
|
+
const componentMap = this.computeComponentMap(allEdges);
|
|
136
|
+
const { components, largestSize } = this.summarizeComponents(componentMap, totalNodes);
|
|
137
|
+
const avgEdgesPerNode = totalNodes > 0 ? (totalEdges * 2) / totalNodes : 0;
|
|
138
|
+
return {
|
|
139
|
+
nodes: {
|
|
140
|
+
total: totalNodes,
|
|
141
|
+
byStatus: byStatus.map((r) => ({
|
|
142
|
+
status: r.status,
|
|
143
|
+
count: r._count.status,
|
|
144
|
+
})),
|
|
145
|
+
byType: byType.map((r) => ({
|
|
146
|
+
type: r.type,
|
|
147
|
+
count: r._count.type,
|
|
148
|
+
})),
|
|
149
|
+
orphanCount,
|
|
150
|
+
undomainedCount,
|
|
151
|
+
staleCount,
|
|
152
|
+
},
|
|
153
|
+
edges: {
|
|
154
|
+
total: totalEdges,
|
|
155
|
+
byRelationshipType: byRelType.map((r) => ({
|
|
156
|
+
relationshipType: r.relationshipType,
|
|
157
|
+
count: r._count.relationshipType,
|
|
158
|
+
})),
|
|
159
|
+
selfLoopCount,
|
|
160
|
+
duplicateCount: duplicateEdgeRows,
|
|
161
|
+
},
|
|
162
|
+
graph: {
|
|
163
|
+
avgEdgesPerNode: Math.round(avgEdgesPerNode * 100) / 100,
|
|
164
|
+
connectedComponents: components,
|
|
165
|
+
largestComponentSize: largestSize,
|
|
166
|
+
},
|
|
167
|
+
duplicateCandidates: duplicateCandidateCount > 0 ? duplicateCandidateCount : 0,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Validate edges for integrity issues.
|
|
172
|
+
*/
|
|
173
|
+
async validateEdges({ lowRelevanceThreshold = 0.3, rareTypeThreshold = 1 } = {}) {
|
|
174
|
+
const issues = [];
|
|
175
|
+
const orgFilterE = tenantWhere(this.tenantCtx);
|
|
176
|
+
const orgFilterEdge = tenantWhere(this.tenantCtx, "e");
|
|
177
|
+
const [selfLoopRows, duplicateEdges, lowRelevancePairs, relTypeCounts, allEdges,] = await Promise.all([
|
|
178
|
+
this.db.$queryRaw `
|
|
179
|
+
SELECT id, source_node_id FROM edges WHERE source_node_id = target_node_id AND ${orgFilterE}
|
|
180
|
+
`,
|
|
181
|
+
this.db.$queryRaw `
|
|
182
|
+
SELECT source_node_id, target_node_id, relationship_type, COUNT(*) as cnt,
|
|
183
|
+
array_agg(id::text) as ids
|
|
184
|
+
FROM edges
|
|
185
|
+
WHERE ${orgFilterE}
|
|
186
|
+
GROUP BY source_node_id, target_node_id, relationship_type
|
|
187
|
+
HAVING COUNT(*) > 1
|
|
188
|
+
`,
|
|
189
|
+
this.db.$queryRaw `
|
|
190
|
+
SELECT e.id as edge_id, e.source_node_id, e.target_node_id, e.relationship_type,
|
|
191
|
+
1 - (a.embedding <=> b.embedding) AS similarity
|
|
192
|
+
FROM edges e
|
|
193
|
+
JOIN nodes a ON a.id = e.source_node_id
|
|
194
|
+
JOIN nodes b ON b.id = e.target_node_id
|
|
195
|
+
WHERE a.embedding IS NOT NULL AND b.embedding IS NOT NULL
|
|
196
|
+
AND 1 - (a.embedding <=> b.embedding) < ${lowRelevanceThreshold}
|
|
197
|
+
AND ${orgFilterEdge}
|
|
198
|
+
ORDER BY similarity ASC
|
|
199
|
+
`,
|
|
200
|
+
this.db.edge.groupBy({
|
|
201
|
+
by: ["relationshipType"],
|
|
202
|
+
_count: { relationshipType: true },
|
|
203
|
+
}),
|
|
204
|
+
this.db.edge.findMany(),
|
|
205
|
+
]);
|
|
206
|
+
const totalEdgesChecked = allEdges.length;
|
|
207
|
+
// Batch-fetch nodes for all issues
|
|
208
|
+
const nodeIdsNeeded = new Set();
|
|
209
|
+
for (const e of selfLoopRows)
|
|
210
|
+
nodeIdsNeeded.add(e.source_node_id);
|
|
211
|
+
for (const d of duplicateEdges) {
|
|
212
|
+
nodeIdsNeeded.add(d.source_node_id);
|
|
213
|
+
nodeIdsNeeded.add(d.target_node_id);
|
|
214
|
+
}
|
|
215
|
+
for (const lr of lowRelevancePairs) {
|
|
216
|
+
nodeIdsNeeded.add(lr.source_node_id);
|
|
217
|
+
nodeIdsNeeded.add(lr.target_node_id);
|
|
218
|
+
}
|
|
219
|
+
const nodesById = nodeIdsNeeded.size > 0
|
|
220
|
+
? new Map((await this.db.node.findMany({
|
|
221
|
+
where: { id: { in: [...nodeIdsNeeded] } },
|
|
222
|
+
})).map((n) => [n.id, n]))
|
|
223
|
+
: new Map();
|
|
224
|
+
// 1. Self-loops
|
|
225
|
+
for (const row of selfLoopRows) {
|
|
226
|
+
const edge = allEdges.find((e) => e.id === row.id);
|
|
227
|
+
if (!edge)
|
|
228
|
+
continue;
|
|
229
|
+
const node = nodesById.get(row.source_node_id);
|
|
230
|
+
issues.push({
|
|
231
|
+
severity: "error",
|
|
232
|
+
category: "self-loop",
|
|
233
|
+
message: `Edge points to itself: ${node?.title ?? row.source_node_id}`,
|
|
234
|
+
edges: [edge],
|
|
235
|
+
sourceNode: node,
|
|
236
|
+
targetNode: node,
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
// 2. Duplicate edges
|
|
240
|
+
for (const dupe of duplicateEdges) {
|
|
241
|
+
const edgeIds = dupe.ids;
|
|
242
|
+
const edges = allEdges.filter((e) => edgeIds.includes(e.id));
|
|
243
|
+
issues.push({
|
|
244
|
+
severity: "warning",
|
|
245
|
+
category: "duplicate-edge",
|
|
246
|
+
message: `${Number(dupe.cnt)} duplicate "${dupe.relationship_type}" edges between nodes`,
|
|
247
|
+
edges,
|
|
248
|
+
sourceNode: nodesById.get(dupe.source_node_id),
|
|
249
|
+
targetNode: nodesById.get(dupe.target_node_id),
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
// 3. Low-relevance connections
|
|
253
|
+
for (const lr of lowRelevancePairs) {
|
|
254
|
+
const edge = allEdges.find((e) => e.id === lr.edge_id);
|
|
255
|
+
if (!edge)
|
|
256
|
+
continue;
|
|
257
|
+
issues.push({
|
|
258
|
+
severity: "warning",
|
|
259
|
+
category: "low-relevance",
|
|
260
|
+
message: `Low similarity (${(Number(lr.similarity) * 100).toFixed(1)}%) between connected nodes`,
|
|
261
|
+
edges: [edge],
|
|
262
|
+
sourceNode: nodesById.get(lr.source_node_id),
|
|
263
|
+
targetNode: nodesById.get(lr.target_node_id),
|
|
264
|
+
similarity: Number(lr.similarity),
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
// 4. Contradictory edges (same node pair with opposing relationship types)
|
|
268
|
+
const contradictionPairs = [
|
|
269
|
+
["supports", "contradicts"],
|
|
270
|
+
["enables", "blocks"],
|
|
271
|
+
["requires", "excludes"],
|
|
272
|
+
];
|
|
273
|
+
const edgesByPair = new Map();
|
|
274
|
+
for (const edge of allEdges) {
|
|
275
|
+
const key = [edge.sourceNodeId, edge.targetNodeId].sort().join("|");
|
|
276
|
+
if (!edgesByPair.has(key))
|
|
277
|
+
edgesByPair.set(key, []);
|
|
278
|
+
edgesByPair.get(key).push(edge);
|
|
279
|
+
}
|
|
280
|
+
for (const [, pairEdges] of edgesByPair) {
|
|
281
|
+
if (pairEdges.length < 2)
|
|
282
|
+
continue;
|
|
283
|
+
const types = new Set(pairEdges.map((e) => e.relationshipType));
|
|
284
|
+
for (const [typeA, typeB] of contradictionPairs) {
|
|
285
|
+
if (types.has(typeA) && types.has(typeB)) {
|
|
286
|
+
const contradicting = pairEdges.filter((e) => e.relationshipType === typeA || e.relationshipType === typeB);
|
|
287
|
+
// Fetch nodes if not already loaded
|
|
288
|
+
for (const e of contradicting) {
|
|
289
|
+
if (!nodesById.has(e.sourceNodeId)) {
|
|
290
|
+
const n = await this.db.node.findUnique({ where: { id: e.sourceNodeId } });
|
|
291
|
+
if (n)
|
|
292
|
+
nodesById.set(n.id, n);
|
|
293
|
+
}
|
|
294
|
+
if (!nodesById.has(e.targetNodeId)) {
|
|
295
|
+
const n = await this.db.node.findUnique({ where: { id: e.targetNodeId } });
|
|
296
|
+
if (n)
|
|
297
|
+
nodesById.set(n.id, n);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
issues.push({
|
|
301
|
+
severity: "error",
|
|
302
|
+
category: "contradictory",
|
|
303
|
+
message: `Contradictory edges: "${typeA}" and "${typeB}" between same nodes`,
|
|
304
|
+
edges: contradicting,
|
|
305
|
+
sourceNode: nodesById.get(contradicting[0].sourceNodeId),
|
|
306
|
+
targetNode: nodesById.get(contradicting[0].targetNodeId),
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
// 5. Rare relationship types (potential typos)
|
|
312
|
+
const rareTypes = relTypeCounts.filter((r) => r._count.relationshipType <= rareTypeThreshold);
|
|
313
|
+
for (const rare of rareTypes) {
|
|
314
|
+
const rareEdges = allEdges.filter((e) => e.relationshipType === rare.relationshipType);
|
|
315
|
+
// Fetch nodes for rare edges
|
|
316
|
+
for (const e of rareEdges) {
|
|
317
|
+
if (!nodesById.has(e.sourceNodeId)) {
|
|
318
|
+
const n = await this.db.node.findUnique({ where: { id: e.sourceNodeId } });
|
|
319
|
+
if (n)
|
|
320
|
+
nodesById.set(n.id, n);
|
|
321
|
+
}
|
|
322
|
+
if (!nodesById.has(e.targetNodeId)) {
|
|
323
|
+
const n = await this.db.node.findUnique({ where: { id: e.targetNodeId } });
|
|
324
|
+
if (n)
|
|
325
|
+
nodesById.set(n.id, n);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
issues.push({
|
|
329
|
+
severity: "info",
|
|
330
|
+
category: "rare-relationship-type",
|
|
331
|
+
message: `Relationship type "${rare.relationshipType}" used only ${rare._count.relationshipType} time(s) — possible typo?`,
|
|
332
|
+
edges: rareEdges,
|
|
333
|
+
sourceNode: rareEdges[0] ? nodesById.get(rareEdges[0].sourceNodeId) : undefined,
|
|
334
|
+
targetNode: rareEdges[0] ? nodesById.get(rareEdges[0].targetNodeId) : undefined,
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
// Build summary
|
|
338
|
+
const summary = {
|
|
339
|
+
"self-loop": 0,
|
|
340
|
+
"duplicate-edge": 0,
|
|
341
|
+
"low-relevance": 0,
|
|
342
|
+
"contradictory": 0,
|
|
343
|
+
"rare-relationship-type": 0,
|
|
344
|
+
};
|
|
345
|
+
for (const issue of issues) {
|
|
346
|
+
summary[issue.category]++;
|
|
347
|
+
}
|
|
348
|
+
return {
|
|
349
|
+
issues,
|
|
350
|
+
summary,
|
|
351
|
+
totalIssues: issues.length,
|
|
352
|
+
totalEdgesChecked,
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Suggest links for a specific node based on embedding similarity,
|
|
357
|
+
* excluding nodes already connected to it.
|
|
358
|
+
*/
|
|
359
|
+
async suggestLinksForNode(nodeId, { limit = 10, minSimilarity = 0.7 } = {}) {
|
|
360
|
+
const orgFilterA = tenantWhere(this.tenantCtx, "a");
|
|
361
|
+
const suggestions = await this.db.$queryRaw `
|
|
362
|
+
SELECT
|
|
363
|
+
b.id AS target_id,
|
|
364
|
+
1 - (a.embedding <=> b.embedding) AS similarity
|
|
365
|
+
FROM nodes a
|
|
366
|
+
JOIN nodes b ON a.id != b.id
|
|
367
|
+
WHERE a.id = ${nodeId}::uuid
|
|
368
|
+
AND a.embedding IS NOT NULL
|
|
369
|
+
AND b.embedding IS NOT NULL
|
|
370
|
+
AND b.id NOT IN (
|
|
371
|
+
SELECT CASE WHEN source_node_id = ${nodeId}::uuid THEN target_node_id ELSE source_node_id END
|
|
372
|
+
FROM edges
|
|
373
|
+
WHERE source_node_id = ${nodeId}::uuid OR target_node_id = ${nodeId}::uuid
|
|
374
|
+
)
|
|
375
|
+
AND 1 - (a.embedding <=> b.embedding) >= ${minSimilarity}
|
|
376
|
+
AND ${orgFilterA}
|
|
377
|
+
ORDER BY similarity DESC
|
|
378
|
+
LIMIT ${limit}
|
|
379
|
+
`;
|
|
380
|
+
if (suggestions.length === 0)
|
|
381
|
+
return [];
|
|
382
|
+
const sourceNode = await this.db.node.findUnique({ where: { id: nodeId } });
|
|
383
|
+
if (!sourceNode)
|
|
384
|
+
return [];
|
|
385
|
+
const targetNodes = await this.db.node.findMany({
|
|
386
|
+
where: { id: { in: suggestions.map((s) => s.target_id) } },
|
|
387
|
+
});
|
|
388
|
+
const targetMap = new Map(targetNodes.map((n) => [n.id, n]));
|
|
389
|
+
return suggestions
|
|
390
|
+
.filter((s) => targetMap.has(s.target_id))
|
|
391
|
+
.map((s) => ({
|
|
392
|
+
source: sourceNode,
|
|
393
|
+
target: targetMap.get(s.target_id),
|
|
394
|
+
similarity: Number(s.similarity),
|
|
395
|
+
}));
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Scan the full graph for high-similarity unconnected pairs.
|
|
399
|
+
*/
|
|
400
|
+
async suggestLinksGlobal({ limit = 20, minSimilarity = 0.8 } = {}) {
|
|
401
|
+
const orgFilterA = tenantWhere(this.tenantCtx, "a");
|
|
402
|
+
const pairs = await this.db.$queryRaw `
|
|
403
|
+
SELECT
|
|
404
|
+
a.id AS a_id,
|
|
405
|
+
b.id AS b_id,
|
|
406
|
+
1 - (a.embedding <=> b.embedding) AS similarity
|
|
407
|
+
FROM nodes a
|
|
408
|
+
JOIN nodes b ON a.id < b.id
|
|
409
|
+
WHERE a.embedding IS NOT NULL
|
|
410
|
+
AND b.embedding IS NOT NULL
|
|
411
|
+
AND 1 - (a.embedding <=> b.embedding) >= ${minSimilarity}
|
|
412
|
+
AND NOT EXISTS (
|
|
413
|
+
SELECT 1 FROM edges e
|
|
414
|
+
WHERE (e.source_node_id = a.id AND e.target_node_id = b.id)
|
|
415
|
+
OR (e.source_node_id = b.id AND e.target_node_id = a.id)
|
|
416
|
+
)
|
|
417
|
+
AND ${orgFilterA}
|
|
418
|
+
ORDER BY similarity DESC
|
|
419
|
+
LIMIT ${limit}
|
|
420
|
+
`;
|
|
421
|
+
if (pairs.length === 0)
|
|
422
|
+
return [];
|
|
423
|
+
const nodeIds = new Set();
|
|
424
|
+
for (const p of pairs) {
|
|
425
|
+
nodeIds.add(p.a_id);
|
|
426
|
+
nodeIds.add(p.b_id);
|
|
427
|
+
}
|
|
428
|
+
const nodes = await this.db.node.findMany({
|
|
429
|
+
where: { id: { in: [...nodeIds] } },
|
|
430
|
+
});
|
|
431
|
+
const nodeMap = new Map(nodes.map((n) => [n.id, n]));
|
|
432
|
+
return pairs
|
|
433
|
+
.filter((p) => nodeMap.has(p.a_id) && nodeMap.has(p.b_id))
|
|
434
|
+
.map((p) => ({
|
|
435
|
+
source: nodeMap.get(p.a_id),
|
|
436
|
+
target: nodeMap.get(p.b_id),
|
|
437
|
+
similarity: Number(p.similarity),
|
|
438
|
+
}));
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Find all disconnected clusters (islands) in the graph.
|
|
442
|
+
* Returns islands sorted by size descending, excluding orphan nodes (size 1).
|
|
443
|
+
*/
|
|
444
|
+
async findIslands() {
|
|
445
|
+
const allEdges = await this.db.edge.findMany({
|
|
446
|
+
select: { sourceNodeId: true, targetNodeId: true },
|
|
447
|
+
});
|
|
448
|
+
const componentMap = this.computeComponentMap(allEdges);
|
|
449
|
+
// Group node IDs by component root
|
|
450
|
+
const groups = new Map();
|
|
451
|
+
for (const [nodeId, root] of componentMap.entries()) {
|
|
452
|
+
if (!groups.has(root))
|
|
453
|
+
groups.set(root, []);
|
|
454
|
+
groups.get(root).push(nodeId);
|
|
455
|
+
}
|
|
456
|
+
// Filter to multi-node components, sort by size desc
|
|
457
|
+
const sortedGroups = [...groups.values()]
|
|
458
|
+
.filter((g) => g.length > 1)
|
|
459
|
+
.sort((a, b) => b.length - a.length);
|
|
460
|
+
// Batch-fetch all nodes involved
|
|
461
|
+
const allNodeIds = sortedGroups.flat();
|
|
462
|
+
const nodes = await this.db.node.findMany({
|
|
463
|
+
where: { id: { in: allNodeIds } },
|
|
464
|
+
});
|
|
465
|
+
const nodeMap = new Map(nodes.map((n) => [n.id, n]));
|
|
466
|
+
return sortedGroups.map((group, idx) => ({
|
|
467
|
+
id: idx + 1,
|
|
468
|
+
size: group.length,
|
|
469
|
+
nodes: group
|
|
470
|
+
.map((id) => nodeMap.get(id))
|
|
471
|
+
.filter((n) => n !== undefined),
|
|
472
|
+
}));
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Suggest bridges between the top islands using embedding similarity.
|
|
476
|
+
*/
|
|
477
|
+
async suggestBridges(maxBridges = 10) {
|
|
478
|
+
const islands = await this.findIslands();
|
|
479
|
+
if (islands.length < 2)
|
|
480
|
+
return [];
|
|
481
|
+
const bridges = [];
|
|
482
|
+
// For each pair of islands (largest first), find the best cross-island link
|
|
483
|
+
for (let i = 0; i < islands.length && bridges.length < maxBridges; i++) {
|
|
484
|
+
for (let j = i + 1; j < islands.length && bridges.length < maxBridges; j++) {
|
|
485
|
+
const fromIds = islands[i].nodes.map((n) => n.id);
|
|
486
|
+
const toIds = islands[j].nodes.map((n) => n.id);
|
|
487
|
+
const orgFilterA = tenantWhere(this.tenantCtx, "a");
|
|
488
|
+
const best = await this.db.$queryRaw `
|
|
489
|
+
SELECT
|
|
490
|
+
a.id AS a_id,
|
|
491
|
+
b.id AS b_id,
|
|
492
|
+
1 - (a.embedding <=> b.embedding) AS similarity
|
|
493
|
+
FROM nodes a
|
|
494
|
+
JOIN nodes b ON a.id != b.id
|
|
495
|
+
WHERE a.id = ANY(${fromIds}::uuid[])
|
|
496
|
+
AND b.id = ANY(${toIds}::uuid[])
|
|
497
|
+
AND a.embedding IS NOT NULL
|
|
498
|
+
AND b.embedding IS NOT NULL
|
|
499
|
+
AND ${orgFilterA}
|
|
500
|
+
ORDER BY similarity DESC
|
|
501
|
+
LIMIT 1
|
|
502
|
+
`;
|
|
503
|
+
if (best.length > 0) {
|
|
504
|
+
const nodeA = islands[i].nodes.find((n) => n.id === best[0].a_id);
|
|
505
|
+
const nodeB = islands[j].nodes.find((n) => n.id === best[0].b_id);
|
|
506
|
+
if (nodeA && nodeB) {
|
|
507
|
+
bridges.push({
|
|
508
|
+
from: islands[i],
|
|
509
|
+
to: islands[j],
|
|
510
|
+
suggestion: {
|
|
511
|
+
source: nodeA,
|
|
512
|
+
target: nodeB,
|
|
513
|
+
similarity: Number(best[0].similarity),
|
|
514
|
+
},
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
return bridges.sort((a, b) => b.suggestion.similarity - a.suggestion.similarity);
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Analyze relationship types and suggest normalizations using embedding similarity.
|
|
524
|
+
* Compares type names semantically to find ones that likely mean the same thing.
|
|
525
|
+
*/
|
|
526
|
+
async analyzeRelationshipTypes(embeddings, { minSimilarity = 0.7 } = {}) {
|
|
527
|
+
const typeCounts = await this.db.edge.groupBy({
|
|
528
|
+
by: ["relationshipType"],
|
|
529
|
+
_count: { relationshipType: true },
|
|
530
|
+
orderBy: { _count: { relationshipType: "desc" } },
|
|
531
|
+
});
|
|
532
|
+
const allTypes = typeCounts.map((r) => ({
|
|
533
|
+
relationshipType: r.relationshipType,
|
|
534
|
+
count: r._count.relationshipType,
|
|
535
|
+
}));
|
|
536
|
+
if (allTypes.length < 2) {
|
|
537
|
+
return { suggestions: [], allTypes };
|
|
538
|
+
}
|
|
539
|
+
// Embed all relationship type names (expand hyphens to spaces for better semantics)
|
|
540
|
+
const typeNames = allTypes.map((t) => t.relationshipType.replace(/-/g, " "));
|
|
541
|
+
const typeEmbeddings = await embeddings.embedBatch(typeNames);
|
|
542
|
+
// Compare all pairs, suggest merging rare → common when similar
|
|
543
|
+
const suggestions = [];
|
|
544
|
+
for (let i = 0; i < allTypes.length; i++) {
|
|
545
|
+
for (let j = i + 1; j < allTypes.length; j++) {
|
|
546
|
+
const sim = cosineSimilarity(typeEmbeddings[i], typeEmbeddings[j]);
|
|
547
|
+
if (sim < minSimilarity)
|
|
548
|
+
continue;
|
|
549
|
+
// Suggest merging the less-used type into the more-used one
|
|
550
|
+
const [from, to] = allTypes[i].count >= allTypes[j].count ? [j, i] : [i, j];
|
|
551
|
+
suggestions.push({
|
|
552
|
+
fromType: allTypes[from].relationshipType,
|
|
553
|
+
fromCount: allTypes[from].count,
|
|
554
|
+
toType: allTypes[to].relationshipType,
|
|
555
|
+
toCount: allTypes[to].count,
|
|
556
|
+
similarity: Math.round(sim * 1000) / 1000,
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
suggestions.sort((a, b) => b.similarity - a.similarity);
|
|
561
|
+
return { suggestions, allTypes };
|
|
562
|
+
}
|
|
563
|
+
// ── Private helpers ─────────────────────────────────────────────────────
|
|
564
|
+
/**
|
|
565
|
+
* Union-find returning a map of nodeId -> component root.
|
|
566
|
+
*/
|
|
567
|
+
computeComponentMap(edges) {
|
|
568
|
+
const parent = new Map();
|
|
569
|
+
function find(x) {
|
|
570
|
+
if (!parent.has(x))
|
|
571
|
+
parent.set(x, x);
|
|
572
|
+
let root = x;
|
|
573
|
+
while (parent.get(root) !== root)
|
|
574
|
+
root = parent.get(root);
|
|
575
|
+
let cur = x;
|
|
576
|
+
while (cur !== root) {
|
|
577
|
+
const next = parent.get(cur);
|
|
578
|
+
parent.set(cur, root);
|
|
579
|
+
cur = next;
|
|
580
|
+
}
|
|
581
|
+
return root;
|
|
582
|
+
}
|
|
583
|
+
function union(a, b) {
|
|
584
|
+
const ra = find(a);
|
|
585
|
+
const rb = find(b);
|
|
586
|
+
if (ra !== rb)
|
|
587
|
+
parent.set(ra, rb);
|
|
588
|
+
}
|
|
589
|
+
for (const edge of edges) {
|
|
590
|
+
union(edge.sourceNodeId, edge.targetNodeId);
|
|
591
|
+
}
|
|
592
|
+
// Normalize all roots
|
|
593
|
+
for (const nodeId of parent.keys()) {
|
|
594
|
+
find(nodeId);
|
|
595
|
+
}
|
|
596
|
+
return parent;
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* Summarize component map into counts for the health report.
|
|
600
|
+
*/
|
|
601
|
+
summarizeComponents(componentMap, totalNodes) {
|
|
602
|
+
const componentSizes = new Map();
|
|
603
|
+
for (const [, root] of componentMap.entries()) {
|
|
604
|
+
componentSizes.set(root, (componentSizes.get(root) ?? 0) + 1);
|
|
605
|
+
}
|
|
606
|
+
const connectedNodeCount = componentMap.size;
|
|
607
|
+
const orphanNodeCount = totalNodes - connectedNodeCount;
|
|
608
|
+
const totalComponents = componentSizes.size + orphanNodeCount;
|
|
609
|
+
let largestSize = 0;
|
|
610
|
+
for (const size of componentSizes.values()) {
|
|
611
|
+
if (size > largestSize)
|
|
612
|
+
largestSize = size;
|
|
613
|
+
}
|
|
614
|
+
if (largestSize === 0 && totalNodes > 0)
|
|
615
|
+
largestSize = 1;
|
|
616
|
+
return { components: totalComponents, largestSize };
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
// ── Utilities ───────────────────────────────────────────────────────────────
|
|
620
|
+
function cosineSimilarity(a, b) {
|
|
621
|
+
let dot = 0;
|
|
622
|
+
let magA = 0;
|
|
623
|
+
let magB = 0;
|
|
624
|
+
for (let i = 0; i < a.length; i++) {
|
|
625
|
+
dot += a[i] * b[i];
|
|
626
|
+
magA += a[i] * a[i];
|
|
627
|
+
magB += b[i] * b[i];
|
|
628
|
+
}
|
|
629
|
+
const denom = Math.sqrt(magA) * Math.sqrt(magB);
|
|
630
|
+
return denom === 0 ? 0 : dot / denom;
|
|
631
|
+
}
|
|
632
|
+
//# sourceMappingURL=cleaning-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cleaning-service.js","sourceRoot":"","sources":["../../src/services/cleaning-service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAsB,MAAM,iBAAiB,CAAC;AA6FxF,+EAA+E;AAE/E,MAAM,OAAO,eAAe;IAGN;IAFZ,SAAS,CAAgB;IAEjC,YAAoB,EAAgB,EAAE,SAAyB;QAA3C,OAAE,GAAF,EAAE,CAAc;QAClC,IAAI,CAAC,SAAS,GAAG,SAAS,IAAI,EAAE,cAAc,EAAE,oBAAoB,EAAE,CAAC;IACzE,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW;QACf,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QACnD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,SAAS,CAAkB;;;;;cAKjD,SAAS;;KAElB,CAAC;QAEF,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAEtC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC;YACxC,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACjD,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE;SAC/B,CAAC,CAAC;QAEH,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,cAAc,CAAC,SAAS,GAAG,IAAI,EAAE,KAAK,GAAG,EAAE;QAC/C,MAAM,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QACpD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,SAAS,CAEpC;;;;;;;;;mDAS8C,SAAS;cAC9C,UAAU;;cAEV,KAAK;KACd,CAAC;QAEF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAElC,iCAAiC;QACjC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;QAClC,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACpB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC;YACxC,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,OAAO,CAAC,EAAE,EAAE;SACpC,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAErD,OAAO,KAAK;aACT,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;aACzD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACX,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAE;YAC3B,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAE;YAC3B,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC;SACjC,CAAC,CAAC,CAAC;IACR,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe,CAAC,SAAS,GAAG,EAAE;QAClC,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;QAC7B,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,SAAS,CAAC,CAAC;QAEnD,MAAM,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QACpD,MAAM,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/C,MAAM,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAEpD,sCAAsC;QACtC,MAAM,CACJ,UAAU,EACV,UAAU,EACV,QAAQ,EACR,MAAM,EACN,SAAS,EACT,WAAW,EACX,eAAe,EACf,UAAU,EACV,aAAa,EACb,iBAAiB,EACjB,uBAAuB,EACvB,QAAQ,EACT,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACpB,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE;YACpB,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE;YACpB,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC;gBACnB,EAAE,EAAE,CAAC,QAAQ,CAAC;gBACd,MAAM,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;gBACxB,OAAO,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;aACxC,CAAC;YACF,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC;gBACnB,EAAE,EAAE,CAAC,MAAM,CAAC;gBACZ,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;gBACtB,OAAO,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;aACtC,CAAC;YACF,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC;gBACnB,EAAE,EAAE,CAAC,kBAAkB,CAAC;gBACxB,MAAM,EAAE,EAAE,gBAAgB,EAAE,IAAI,EAAE;gBAClC,OAAO,EAAE,EAAE,MAAM,EAAE,EAAE,gBAAgB,EAAE,MAAM,EAAE,EAAE;aAClD,CAAC;YACF,IAAI,CAAC,EAAE,CAAC,SAAS,CAAqB;;;;gBAI5B,UAAU;OACnB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YACjC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC;YACjD,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;YAC/D,IAAI,CAAC,EAAE,CAAC,SAAS,CAAqB;;;gBAG5B,UAAU;OACnB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YACjC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAqB;;;;kBAI1B,UAAU;;;;OAIrB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YACjC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAqB;;;;;;;;kBAQ1B,UAAU;;;OAGrB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YACjC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,EAAE,CAAC;SAC9E,CAAC,CAAC;QAEH,8CAA8C;QAC9C,MAAM,YAAY,GAAG,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QACxD,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC,mBAAmB,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;QAEvF,MAAM,eAAe,GAAG,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;QAE3E,OAAO;YACL,KAAK,EAAE;gBACL,KAAK,EAAE,UAAU;gBACjB,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBAC7B,MAAM,EAAE,CAAC,CAAC,MAAM;oBAChB,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM;iBACvB,CAAC,CAAC;gBACH,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACzB,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI;iBACrB,CAAC,CAAC;gBACH,WAAW;gBACX,eAAe;gBACf,UAAU;aACX;YACD,KAAK,EAAE;gBACL,KAAK,EAAE,UAAU;gBACjB,kBAAkB,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACxC,gBAAgB,EAAE,CAAC,CAAC,gBAAgB;oBACpC,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,gBAAgB;iBACjC,CAAC,CAAC;gBACH,aAAa;gBACb,cAAc,EAAE,iBAAiB;aAClC;YACD,KAAK,EAAE;gBACL,eAAe,EAAE,IAAI,CAAC,KAAK,CAAC,eAAe,GAAG,GAAG,CAAC,GAAG,GAAG;gBACxD,mBAAmB,EAAE,UAAU;gBAC/B,oBAAoB,EAAE,WAAW;aAClC;YACD,mBAAmB,EAAE,uBAAuB,GAAG,CAAC,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC;SAC/E,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa,CACjB,EAAE,qBAAqB,GAAG,GAAG,EAAE,iBAAiB,GAAG,CAAC,KACa,EAAE;QAEnE,MAAM,MAAM,GAAsB,EAAE,CAAC;QAErC,MAAM,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/C,MAAM,aAAa,GAAG,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAEvD,MAAM,CACJ,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,QAAQ,EACT,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACpB,IAAI,CAAC,EAAE,CAAC,SAAS,CAA0C;yFACwB,UAAU;OAC5F;YACD,IAAI,CAAC,EAAE,CAAC,SAAS,CAA6G;;;;gBAIpH,UAAU;;;OAGnB;YACD,IAAI,CAAC,EAAE,CAAC,SAAS,CAAsH;;;;;;;oDAOzF,qBAAqB;gBACzD,aAAa;;OAEtB;YACD,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC;gBACnB,EAAE,EAAE,CAAC,kBAAkB,CAAC;gBACxB,MAAM,EAAE,EAAE,gBAAgB,EAAE,IAAI,EAAE;aACnC,CAAC;YACF,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE;SACxB,CAAC,CAAC;QAEH,MAAM,iBAAiB,GAAG,QAAQ,CAAC,MAAM,CAAC;QAE1C,mCAAmC;QACnC,MAAM,aAAa,GAAG,IAAI,GAAG,EAAU,CAAC;QACxC,KAAK,MAAM,CAAC,IAAI,YAAY;YAAE,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;QAClE,KAAK,MAAM,CAAC,IAAI,cAAc,EAAE,CAAC;YAC/B,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;YACpC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;QACtC,CAAC;QACD,KAAK,MAAM,EAAE,IAAI,iBAAiB,EAAE,CAAC;YACnC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC;YACrC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC;QACvC,CAAC;QAED,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC;YACtC,CAAC,CAAC,IAAI,GAAG,CACL,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC;gBAC3B,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,aAAa,CAAC,EAAE,EAAE;aAC1C,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAC1B;YACH,CAAC,CAAC,IAAI,GAAG,EAAgB,CAAC;QAE5B,gBAAgB;QAChB,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;YAC/B,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC;YACnD,IAAI,CAAC,IAAI;gBAAE,SAAS;YACpB,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;YAC/C,MAAM,CAAC,IAAI,CAAC;gBACV,QAAQ,EAAE,OAAO;gBACjB,QAAQ,EAAE,WAAW;gBACrB,OAAO,EAAE,0BAA0B,IAAI,EAAE,KAAK,IAAI,GAAG,CAAC,cAAc,EAAE;gBACtE,KAAK,EAAE,CAAC,IAAI,CAAC;gBACb,UAAU,EAAE,IAAI;gBAChB,UAAU,EAAE,IAAI;aACjB,CAAC,CAAC;QACL,CAAC;QAED,qBAAqB;QACrB,KAAK,MAAM,IAAI,IAAI,cAAc,EAAE,CAAC;YAClC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC;YACzB,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAC7D,MAAM,CAAC,IAAI,CAAC;gBACV,QAAQ,EAAE,SAAS;gBACnB,QAAQ,EAAE,gBAAgB;gBAC1B,OAAO,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,eAAe,IAAI,CAAC,iBAAiB,uBAAuB;gBACxF,KAAK;gBACL,UAAU,EAAE,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC;gBAC9C,UAAU,EAAE,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC;aAC/C,CAAC,CAAC;QACL,CAAC;QAED,+BAA+B;QAC/B,KAAK,MAAM,EAAE,IAAI,iBAAiB,EAAE,CAAC;YACnC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,OAAO,CAAC,CAAC;YACvD,IAAI,CAAC,IAAI;gBAAE,SAAS;YACpB,MAAM,CAAC,IAAI,CAAC;gBACV,QAAQ,EAAE,SAAS;gBACnB,QAAQ,EAAE,eAAe;gBACzB,OAAO,EAAE,mBAAmB,CAAC,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,4BAA4B;gBAChG,KAAK,EAAE,CAAC,IAAI,CAAC;gBACb,UAAU,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,cAAc,CAAC;gBAC5C,UAAU,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,cAAc,CAAC;gBAC5C,UAAU,EAAE,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC;aAClC,CAAC,CAAC;QACL,CAAC;QAED,2EAA2E;QAC3E,MAAM,kBAAkB,GAAG;YACzB,CAAC,UAAU,EAAE,aAAa,CAAC;YAC3B,CAAC,SAAS,EAAE,QAAQ,CAAC;YACrB,CAAC,UAAU,EAAE,UAAU,CAAC;SACzB,CAAC;QAEF,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;QAC9C,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC5B,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACpE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACpD,WAAW,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnC,CAAC;QAED,KAAK,MAAM,CAAC,EAAE,SAAS,CAAC,IAAI,WAAW,EAAE,CAAC;YACxC,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC;gBAAE,SAAS;YACnC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC;YAChE,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,kBAAkB,EAAE,CAAC;gBAChD,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;oBACzC,MAAM,aAAa,GAAG,SAAS,CAAC,MAAM,CACpC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,gBAAgB,KAAK,KAAK,IAAI,CAAC,CAAC,gBAAgB,KAAK,KAAK,CACpE,CAAC;oBACF,oCAAoC;oBACpC,KAAK,MAAM,CAAC,IAAI,aAAa,EAAE,CAAC;wBAC9B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC;4BACnC,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;4BAC3E,IAAI,CAAC;gCAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;wBAChC,CAAC;wBACD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC;4BACnC,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;4BAC3E,IAAI,CAAC;gCAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;wBAChC,CAAC;oBACH,CAAC;oBACD,MAAM,CAAC,IAAI,CAAC;wBACV,QAAQ,EAAE,OAAO;wBACjB,QAAQ,EAAE,eAAe;wBACzB,OAAO,EAAE,yBAAyB,KAAK,UAAU,KAAK,sBAAsB;wBAC5E,KAAK,EAAE,aAAa;wBACpB,UAAU,EAAE,SAAS,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;wBACxD,UAAU,EAAE,SAAS,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;qBACzD,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;QAED,+CAA+C;QAC/C,MAAM,SAAS,GAAG,aAAa,CAAC,MAAM,CACpC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,IAAI,iBAAiB,CACtD,CAAC;QACF,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;YAC7B,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAC/B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,gBAAgB,KAAK,IAAI,CAAC,gBAAgB,CACpD,CAAC;YACF,6BAA6B;YAC7B,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;gBAC1B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC;oBACnC,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;oBAC3E,IAAI,CAAC;wBAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;gBAChC,CAAC;gBACD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC;oBACnC,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;oBAC3E,IAAI,CAAC;wBAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;gBAChC,CAAC;YACH,CAAC;YACD,MAAM,CAAC,IAAI,CAAC;gBACV,QAAQ,EAAE,MAAM;gBAChB,QAAQ,EAAE,wBAAwB;gBAClC,OAAO,EAAE,sBAAsB,IAAI,CAAC,gBAAgB,eAAe,IAAI,CAAC,MAAM,CAAC,gBAAgB,2BAA2B;gBAC1H,KAAK,EAAE,SAAS;gBAChB,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS;gBAC/E,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS;aAChF,CAAC,CAAC;QACL,CAAC;QAED,gBAAgB;QAChB,MAAM,OAAO,GAAuC;YAClD,WAAW,EAAE,CAAC;YACd,gBAAgB,EAAE,CAAC;YACnB,eAAe,EAAE,CAAC;YAClB,eAAe,EAAE,CAAC;YAClB,wBAAwB,EAAE,CAAC;SAC5B,CAAC;QACF,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,CAAC;QAED,OAAO;YACL,MAAM;YACN,OAAO;YACP,WAAW,EAAE,MAAM,CAAC,MAAM;YAC1B,iBAAiB;SAClB,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,mBAAmB,CACvB,MAAc,EACd,EAAE,KAAK,GAAG,EAAE,EAAE,aAAa,GAAG,GAAG,KAAiD,EAAE;QAEpF,MAAM,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QACpD,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,SAAS,CAE1C;;;;;;qBAMgB,MAAM;;;;8CAImB,MAAM;;mCAEjB,MAAM,8BAA8B,MAAM;;mDAE1B,aAAa;cAClD,UAAU;;cAEV,KAAK;KACd,CAAC;QAEF,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAExC,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;QAC5E,IAAI,CAAC,UAAU;YAAE,OAAO,EAAE,CAAC;QAE3B,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC;YAC9C,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE;SAC3D,CAAC,CAAC;QACH,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAE7D,OAAO,WAAW;aACf,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;aACzC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACX,MAAM,EAAE,UAAU;YAClB,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAE;YACnC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC;SACjC,CAAC,CAAC,CAAC;IACR,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,kBAAkB,CACtB,EAAE,KAAK,GAAG,EAAE,EAAE,aAAa,GAAG,GAAG,KAAiD,EAAE;QAEpF,MAAM,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QACpD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,SAAS,CAEpC;;;;;;;;;mDAS8C,aAAa;;;;;;cAMlD,UAAU;;cAEV,KAAK;KACd,CAAC;QAEF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAElC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;QAClC,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACpB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC;YACxC,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,OAAO,CAAC,EAAE,EAAE;SACpC,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAErD,OAAO,KAAK;aACT,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;aACzD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACX,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAE;YAC5B,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAE;YAC5B,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC;SACjC,CAAC,CAAC,CAAC;IACR,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,WAAW;QACf,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC;YAC3C,MAAM,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE;SACnD,CAAC,CAAC;QAEH,MAAM,YAAY,GAAG,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QAExD,mCAAmC;QACnC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAoB,CAAC;QAC3C,KAAK,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,YAAY,CAAC,OAAO,EAAE,EAAE,CAAC;YACpD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC5C,MAAM,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC;QAED,qDAAqD;QACrD,MAAM,YAAY,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;aACtC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;aAC3B,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;QAEvC,iCAAiC;QACjC,MAAM,UAAU,GAAG,YAAY,CAAC,IAAI,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC;YACxC,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE;SAClC,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAErD,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;YACvC,EAAE,EAAE,GAAG,GAAG,CAAC;YACX,IAAI,EAAE,KAAK,CAAC,MAAM;YAClB,KAAK,EAAE,KAAK;iBACT,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;iBAC5B,MAAM,CAAC,CAAC,CAAC,EAAa,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC;SAC7C,CAAC,CAAC,CAAC;IACN,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,cAAc,CAAC,UAAU,GAAG,EAAE;QAClC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QACzC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,EAAE,CAAC;QAElC,MAAM,OAAO,GAAmB,EAAE,CAAC;QAEnC,4EAA4E;QAC5E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;YACvE,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3E,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBAClD,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBAEhD,MAAM,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;gBACpD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,SAAS,CAEnC;;;;;;;6BAOoB,OAAO;6BACP,KAAK;;;kBAGhB,UAAU;;;SAGnB,CAAC;gBAEF,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACpB,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;oBAClE,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;oBAClE,IAAI,KAAK,IAAI,KAAK,EAAE,CAAC;wBACnB,OAAO,CAAC,IAAI,CAAC;4BACX,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;4BAChB,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;4BACd,UAAU,EAAE;gCACV,MAAM,EAAE,KAAK;gCACb,MAAM,EAAE,KAAK;gCACb,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;6BACvC;yBACF,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;IACnF,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,wBAAwB,CAC5B,UAA6B,EAC7B,EAAE,aAAa,GAAG,GAAG,KAAiC,EAAE;QAExD,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC;YAC5C,EAAE,EAAE,CAAC,kBAAkB,CAAC;YACxB,MAAM,EAAE,EAAE,gBAAgB,EAAE,IAAI,EAAE;YAClC,OAAO,EAAE,EAAE,MAAM,EAAE,EAAE,gBAAgB,EAAE,MAAM,EAAE,EAAE;SAClD,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACtC,gBAAgB,EAAE,CAAC,CAAC,gBAAgB;YACpC,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,gBAAgB;SACjC,CAAC,CAAC,CAAC;QAEJ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC;QACvC,CAAC;QAED,oFAAoF;QACpF,MAAM,SAAS,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;QAC7E,MAAM,cAAc,GAAG,MAAM,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QAE9D,gEAAgE;QAChE,MAAM,WAAW,GAA0B,EAAE,CAAC;QAE9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACzC,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7C,MAAM,GAAG,GAAG,gBAAgB,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;gBACnE,IAAI,GAAG,GAAG,aAAa;oBAAE,SAAS;gBAElC,4DAA4D;gBAC5D,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,GACd,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;gBAE3D,WAAW,CAAC,IAAI,CAAC;oBACf,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,gBAAgB;oBACzC,SAAS,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK;oBAC/B,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,gBAAgB;oBACrC,OAAO,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK;oBAC3B,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI;iBAC1C,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;QAExD,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC;IACnC,CAAC;IAED,2EAA2E;IAE3E;;OAEG;IACK,mBAAmB,CACzB,KAAuD;QAEvD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;QAEzC,SAAS,IAAI,CAAC,CAAS;YACrB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;gBAAE,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACrC,IAAI,IAAI,GAAG,CAAC,CAAC;YACb,OAAO,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI;gBAAE,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC;YAC3D,IAAI,GAAG,GAAG,CAAC,CAAC;YACZ,OAAO,GAAG,KAAK,IAAI,EAAE,CAAC;gBACpB,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;gBAC9B,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;gBACtB,GAAG,GAAG,IAAI,CAAC;YACb,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,SAAS,KAAK,CAAC,CAAS,EAAE,CAAS;YACjC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACnB,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACnB,IAAI,EAAE,KAAK,EAAE;gBAAE,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QACpC,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,KAAK,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAC9C,CAAC;QAED,sBAAsB;QACtB,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;YACnC,IAAI,CAAC,MAAM,CAAC,CAAC;QACf,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACK,mBAAmB,CACzB,YAAiC,EACjC,UAAkB;QAElB,MAAM,cAAc,GAAG,IAAI,GAAG,EAAkB,CAAC;QACjD,KAAK,MAAM,CAAC,EAAE,IAAI,CAAC,IAAI,YAAY,CAAC,OAAO,EAAE,EAAE,CAAC;YAC9C,cAAc,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,kBAAkB,GAAG,YAAY,CAAC,IAAI,CAAC;QAC7C,MAAM,eAAe,GAAG,UAAU,GAAG,kBAAkB,CAAC;QACxD,MAAM,eAAe,GAAG,cAAc,CAAC,IAAI,GAAG,eAAe,CAAC;QAE9D,IAAI,WAAW,GAAG,CAAC,CAAC;QACpB,KAAK,MAAM,IAAI,IAAI,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC;YAC3C,IAAI,IAAI,GAAG,WAAW;gBAAE,WAAW,GAAG,IAAI,CAAC;QAC7C,CAAC;QACD,IAAI,WAAW,KAAK,CAAC,IAAI,UAAU,GAAG,CAAC;YAAE,WAAW,GAAG,CAAC,CAAC;QAEzD,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,WAAW,EAAE,CAAC;IACtD,CAAC;CACF;AAED,+EAA+E;AAE/E,SAAS,gBAAgB,CAAC,CAAW,EAAE,CAAW;IAChD,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACnB,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACtB,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChD,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC;AACvC,CAAC"}
|