leangraph 1.1.1 → 1.1.3
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/db.d.ts.map +1 -1
- package/dist/db.js +42 -3
- package/dist/db.js.map +1 -1
- package/dist/engine/hybrid-executor.d.ts +118 -0
- package/dist/engine/hybrid-executor.d.ts.map +1 -0
- package/dist/engine/hybrid-executor.js +205 -0
- package/dist/engine/hybrid-executor.js.map +1 -0
- package/dist/engine/index.d.ts +36 -0
- package/dist/engine/index.d.ts.map +1 -0
- package/dist/engine/index.js +34 -0
- package/dist/engine/index.js.map +1 -0
- package/dist/engine/memory-graph.d.ts +68 -0
- package/dist/engine/memory-graph.d.ts.map +1 -0
- package/dist/engine/memory-graph.js +176 -0
- package/dist/engine/memory-graph.js.map +1 -0
- package/dist/engine/query-planner.d.ts +62 -0
- package/dist/engine/query-planner.d.ts.map +1 -0
- package/dist/engine/query-planner.js +481 -0
- package/dist/engine/query-planner.js.map +1 -0
- package/dist/engine/subgraph-loader.d.ts +41 -0
- package/dist/engine/subgraph-loader.d.ts.map +1 -0
- package/dist/engine/subgraph-loader.js +172 -0
- package/dist/engine/subgraph-loader.js.map +1 -0
- package/dist/executor.d.ts +17 -0
- package/dist/executor.d.ts.map +1 -1
- package/dist/executor.js +286 -100
- package/dist/executor.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/parser.d.ts +47 -3
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +228 -41
- package/dist/parser.js.map +1 -1
- package/dist/translator.d.ts +53 -0
- package/dist/translator.d.ts.map +1 -1
- package/dist/translator.js +1548 -183
- package/dist/translator.js.map +1 -1
- package/package.json +9 -3
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory graph structure for hybrid query execution.
|
|
3
|
+
* Optimized for traversal operations with O(1) node lookups
|
|
4
|
+
* and adjacency list access.
|
|
5
|
+
*/
|
|
6
|
+
export interface MemoryNode {
|
|
7
|
+
id: string;
|
|
8
|
+
labels: string[];
|
|
9
|
+
properties: Record<string, unknown>;
|
|
10
|
+
}
|
|
11
|
+
export interface MemoryEdge {
|
|
12
|
+
id: string;
|
|
13
|
+
type: string;
|
|
14
|
+
sourceId: string;
|
|
15
|
+
targetId: string;
|
|
16
|
+
properties: Record<string, unknown>;
|
|
17
|
+
}
|
|
18
|
+
export interface Path {
|
|
19
|
+
nodes: MemoryNode[];
|
|
20
|
+
edges: MemoryEdge[];
|
|
21
|
+
}
|
|
22
|
+
export type Direction = "out" | "in" | "both";
|
|
23
|
+
/** Row format from SQLite nodes table */
|
|
24
|
+
export interface NodeRow {
|
|
25
|
+
id: string;
|
|
26
|
+
label: string;
|
|
27
|
+
properties: string;
|
|
28
|
+
}
|
|
29
|
+
/** Row format from SQLite edges table */
|
|
30
|
+
export interface EdgeRow {
|
|
31
|
+
id: string;
|
|
32
|
+
type: string;
|
|
33
|
+
source_id: string;
|
|
34
|
+
target_id: string;
|
|
35
|
+
properties: string;
|
|
36
|
+
}
|
|
37
|
+
export declare class MemoryGraph {
|
|
38
|
+
private nodes;
|
|
39
|
+
private outEdges;
|
|
40
|
+
private inEdges;
|
|
41
|
+
/**
|
|
42
|
+
* Build a MemoryGraph from SQLite row data.
|
|
43
|
+
*/
|
|
44
|
+
static fromRows(nodeRows: NodeRow[], edgeRows: EdgeRow[]): MemoryGraph;
|
|
45
|
+
/**
|
|
46
|
+
* Get a node by ID. O(1) lookup.
|
|
47
|
+
*/
|
|
48
|
+
getNode(id: string): MemoryNode | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* Get outgoing edges from a node, optionally filtered by type.
|
|
51
|
+
*/
|
|
52
|
+
getOutEdges(nodeId: string, type?: string): MemoryEdge[];
|
|
53
|
+
/**
|
|
54
|
+
* Get incoming edges to a node, optionally filtered by type.
|
|
55
|
+
*/
|
|
56
|
+
getInEdges(nodeId: string, type?: string): MemoryEdge[];
|
|
57
|
+
/**
|
|
58
|
+
* Get neighboring nodes in a given direction, optionally filtered by edge type.
|
|
59
|
+
*/
|
|
60
|
+
neighbors(nodeId: string, direction: Direction, type?: string): MemoryNode[];
|
|
61
|
+
/**
|
|
62
|
+
* Traverse variable-length paths from a starting node.
|
|
63
|
+
* Yields paths lazily using a generator for memory efficiency.
|
|
64
|
+
* Handles cycle detection to prevent infinite loops.
|
|
65
|
+
*/
|
|
66
|
+
traversePaths(startId: string, edgeType: string | null, minDepth: number, maxDepth: number, direction: Direction): Generator<Path>;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=memory-graph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-graph.d.ts","sourceRoot":"","sources":["../../src/engine/memory-graph.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,IAAI;IACnB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB;AAED,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,IAAI,GAAG,MAAM,CAAC;AAE9C,yCAAyC;AACzC,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,yCAAyC;AACzC,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,KAAK,CAAsC;IACnD,OAAO,CAAC,QAAQ,CAAwC;IACxD,OAAO,CAAC,OAAO,CAAwC;IAEvD;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,WAAW;IA0CtE;;OAEG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS;IAI3C;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,EAAE;IAQxD;;OAEG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,EAAE;IAQvD;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,EAAE;IA2B5E;;;;OAIG;IACF,aAAa,CACZ,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,SAAS,GACnB,SAAS,CAAC,IAAI,CAAC;CA2FnB"}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory graph structure for hybrid query execution.
|
|
3
|
+
* Optimized for traversal operations with O(1) node lookups
|
|
4
|
+
* and adjacency list access.
|
|
5
|
+
*/
|
|
6
|
+
export class MemoryGraph {
|
|
7
|
+
nodes = new Map();
|
|
8
|
+
outEdges = new Map();
|
|
9
|
+
inEdges = new Map();
|
|
10
|
+
/**
|
|
11
|
+
* Build a MemoryGraph from SQLite row data.
|
|
12
|
+
*/
|
|
13
|
+
static fromRows(nodeRows, edgeRows) {
|
|
14
|
+
const graph = new MemoryGraph();
|
|
15
|
+
// Parse and index nodes
|
|
16
|
+
for (const row of nodeRows) {
|
|
17
|
+
const node = {
|
|
18
|
+
id: row.id,
|
|
19
|
+
labels: JSON.parse(row.label),
|
|
20
|
+
properties: JSON.parse(row.properties),
|
|
21
|
+
};
|
|
22
|
+
graph.nodes.set(node.id, node);
|
|
23
|
+
// Initialize adjacency lists
|
|
24
|
+
graph.outEdges.set(node.id, []);
|
|
25
|
+
graph.inEdges.set(node.id, []);
|
|
26
|
+
}
|
|
27
|
+
// Parse and index edges
|
|
28
|
+
for (const row of edgeRows) {
|
|
29
|
+
const edge = {
|
|
30
|
+
id: row.id,
|
|
31
|
+
type: row.type,
|
|
32
|
+
sourceId: row.source_id,
|
|
33
|
+
targetId: row.target_id,
|
|
34
|
+
properties: JSON.parse(row.properties),
|
|
35
|
+
};
|
|
36
|
+
// Add to outgoing edges of source
|
|
37
|
+
const outList = graph.outEdges.get(edge.sourceId);
|
|
38
|
+
if (outList) {
|
|
39
|
+
outList.push(edge);
|
|
40
|
+
}
|
|
41
|
+
// Add to incoming edges of target
|
|
42
|
+
const inList = graph.inEdges.get(edge.targetId);
|
|
43
|
+
if (inList) {
|
|
44
|
+
inList.push(edge);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return graph;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get a node by ID. O(1) lookup.
|
|
51
|
+
*/
|
|
52
|
+
getNode(id) {
|
|
53
|
+
return this.nodes.get(id);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get outgoing edges from a node, optionally filtered by type.
|
|
57
|
+
*/
|
|
58
|
+
getOutEdges(nodeId, type) {
|
|
59
|
+
const edges = this.outEdges.get(nodeId) ?? [];
|
|
60
|
+
if (type === undefined) {
|
|
61
|
+
return edges;
|
|
62
|
+
}
|
|
63
|
+
return edges.filter((e) => e.type === type);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Get incoming edges to a node, optionally filtered by type.
|
|
67
|
+
*/
|
|
68
|
+
getInEdges(nodeId, type) {
|
|
69
|
+
const edges = this.inEdges.get(nodeId) ?? [];
|
|
70
|
+
if (type === undefined) {
|
|
71
|
+
return edges;
|
|
72
|
+
}
|
|
73
|
+
return edges.filter((e) => e.type === type);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get neighboring nodes in a given direction, optionally filtered by edge type.
|
|
77
|
+
*/
|
|
78
|
+
neighbors(nodeId, direction, type) {
|
|
79
|
+
const result = [];
|
|
80
|
+
const seen = new Set();
|
|
81
|
+
if (direction === "out" || direction === "both") {
|
|
82
|
+
for (const edge of this.getOutEdges(nodeId, type)) {
|
|
83
|
+
const node = this.nodes.get(edge.targetId);
|
|
84
|
+
if (node && !seen.has(node.id)) {
|
|
85
|
+
seen.add(node.id);
|
|
86
|
+
result.push(node);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (direction === "in" || direction === "both") {
|
|
91
|
+
for (const edge of this.getInEdges(nodeId, type)) {
|
|
92
|
+
const node = this.nodes.get(edge.sourceId);
|
|
93
|
+
if (node && !seen.has(node.id)) {
|
|
94
|
+
seen.add(node.id);
|
|
95
|
+
result.push(node);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Traverse variable-length paths from a starting node.
|
|
103
|
+
* Yields paths lazily using a generator for memory efficiency.
|
|
104
|
+
* Handles cycle detection to prevent infinite loops.
|
|
105
|
+
*/
|
|
106
|
+
*traversePaths(startId, edgeType, minDepth, maxDepth, direction) {
|
|
107
|
+
const startNode = this.nodes.get(startId);
|
|
108
|
+
if (!startNode) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
// Handle minDepth = 0 case (include start node as a path)
|
|
112
|
+
if (minDepth === 0) {
|
|
113
|
+
yield { nodes: [startNode], edges: [] };
|
|
114
|
+
}
|
|
115
|
+
const initialEntry = {
|
|
116
|
+
nodeId: startId,
|
|
117
|
+
nodes: [startNode],
|
|
118
|
+
edges: [],
|
|
119
|
+
visitedEdges: new Set(),
|
|
120
|
+
};
|
|
121
|
+
const stack = [initialEntry];
|
|
122
|
+
while (stack.length > 0) {
|
|
123
|
+
const current = stack.pop();
|
|
124
|
+
const depth = current.edges.length;
|
|
125
|
+
// Get edges to traverse
|
|
126
|
+
const edgesToTraverse = [];
|
|
127
|
+
if (direction === "out" || direction === "both") {
|
|
128
|
+
const outEdges = this.getOutEdges(current.nodeId, edgeType ?? undefined);
|
|
129
|
+
edgesToTraverse.push(...outEdges);
|
|
130
|
+
}
|
|
131
|
+
if (direction === "in" || direction === "both") {
|
|
132
|
+
const inEdges = this.getInEdges(current.nodeId, edgeType ?? undefined);
|
|
133
|
+
edgesToTraverse.push(...inEdges);
|
|
134
|
+
}
|
|
135
|
+
// Explore each edge
|
|
136
|
+
for (const edge of edgesToTraverse) {
|
|
137
|
+
// Skip if edge already used in this path (cycle prevention)
|
|
138
|
+
if (current.visitedEdges.has(edge.id)) {
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
// Determine the target node based on direction
|
|
142
|
+
let targetId;
|
|
143
|
+
if (edge.sourceId === current.nodeId) {
|
|
144
|
+
targetId = edge.targetId;
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
targetId = edge.sourceId;
|
|
148
|
+
}
|
|
149
|
+
const targetNode = this.nodes.get(targetId);
|
|
150
|
+
if (!targetNode) {
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
// Build new path
|
|
154
|
+
const newNodes = [...current.nodes, targetNode];
|
|
155
|
+
const newEdges = [...current.edges, edge];
|
|
156
|
+
const newVisited = new Set(current.visitedEdges);
|
|
157
|
+
newVisited.add(edge.id);
|
|
158
|
+
const newDepth = newEdges.length;
|
|
159
|
+
// Yield if within depth range
|
|
160
|
+
if (newDepth >= minDepth && newDepth <= maxDepth) {
|
|
161
|
+
yield { nodes: newNodes, edges: newEdges };
|
|
162
|
+
}
|
|
163
|
+
// Continue exploring if we haven't reached max depth
|
|
164
|
+
if (newDepth < maxDepth) {
|
|
165
|
+
stack.push({
|
|
166
|
+
nodeId: targetId,
|
|
167
|
+
nodes: newNodes,
|
|
168
|
+
edges: newEdges,
|
|
169
|
+
visitedEdges: newVisited,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=memory-graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-graph.js","sourceRoot":"","sources":["../../src/engine/memory-graph.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Query Planner - Analyzes Cypher AST to determine if a query
|
|
3
|
+
* can use the hybrid execution engine.
|
|
4
|
+
*
|
|
5
|
+
* Supports generalized pattern chains with:
|
|
6
|
+
* - N nodes (arbitrary chain length)
|
|
7
|
+
* - Multiple variable-length edges
|
|
8
|
+
* - Var-length edges at any position
|
|
9
|
+
*/
|
|
10
|
+
import { Query, WhereCondition, NodePattern } from "../parser.js";
|
|
11
|
+
import { PatternChainParams } from "./hybrid-executor.js";
|
|
12
|
+
import { MemoryNode } from "./memory-graph.js";
|
|
13
|
+
export interface HybridAnalysisResult {
|
|
14
|
+
/** Whether the query is suitable for hybrid execution */
|
|
15
|
+
suitable: boolean;
|
|
16
|
+
/** Extracted parameters for HybridExecutor (if suitable) */
|
|
17
|
+
params?: PatternChainParams;
|
|
18
|
+
/** Reason why the query is not suitable (for debugging) */
|
|
19
|
+
reason?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Analyze a parsed query to determine if it can use the hybrid executor.
|
|
23
|
+
* Returns extracted parameters if suitable, or a reason if not.
|
|
24
|
+
*
|
|
25
|
+
* Supports generalized pattern chains:
|
|
26
|
+
* (a)-[*]->(b)-[:R1]->(c)-[:R2]->(d) -- N nodes
|
|
27
|
+
* (a)-[*]->(b)-[*]->(c) -- multiple var-length
|
|
28
|
+
*/
|
|
29
|
+
export declare function analyzeForHybrid(query: Query, params: Record<string, unknown>): HybridAnalysisResult;
|
|
30
|
+
/**
|
|
31
|
+
* Check if a query's structure matches a hybrid-compatible pattern.
|
|
32
|
+
*
|
|
33
|
+
* Supported patterns:
|
|
34
|
+
* (a:Label)-[*min..max]->(b:Label)-[:TYPE]->(c:Label) -- original
|
|
35
|
+
* (a)-[*]->(b)-[:R1]->(c)-[:R2]->(d) -- longer chains
|
|
36
|
+
* (a)-[*]->(b)-[*]->(c) -- multiple var-length
|
|
37
|
+
* (a)-[:R1]->(b)-[*]->(c) -- var-length anywhere
|
|
38
|
+
*
|
|
39
|
+
* Requirements:
|
|
40
|
+
* - No mutations (CREATE, SET, DELETE, MERGE)
|
|
41
|
+
* - Has RETURN clause
|
|
42
|
+
* - Exactly one MATCH clause
|
|
43
|
+
* - At least 1 relationship pattern
|
|
44
|
+
* - At least one variable-length edge
|
|
45
|
+
* - No relationship property predicates (not supported in hybrid)
|
|
46
|
+
* - All nodes must have labels (checked in analyzeForHybrid)
|
|
47
|
+
*/
|
|
48
|
+
export declare function isHybridCompatiblePattern(query: Query): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Extract node information (label, properties) from a NodePattern.
|
|
51
|
+
*/
|
|
52
|
+
export declare function extractNodeInfo(node: NodePattern, params: Record<string, unknown>): {
|
|
53
|
+
label: string;
|
|
54
|
+
properties: Record<string, unknown>;
|
|
55
|
+
} | null;
|
|
56
|
+
/**
|
|
57
|
+
* Convert a WHERE condition to a filter function for the middle node.
|
|
58
|
+
* Returns null if the condition references nodes other than the middle node,
|
|
59
|
+
* or if it contains unsupported expressions.
|
|
60
|
+
*/
|
|
61
|
+
export declare function convertWhereToFilter(where: WhereCondition | undefined, middleVar: string, params: Record<string, unknown>): ((node: MemoryNode) => boolean) | null;
|
|
62
|
+
//# sourceMappingURL=query-planner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-planner.d.ts","sourceRoot":"","sources":["../../src/engine/query-planner.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,KAAK,EAGL,cAAc,EACd,WAAW,EAIZ,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,kBAAkB,EAAuB,MAAM,sBAAsB,CAAC;AAC/E,OAAO,EAAE,UAAU,EAAa,MAAM,mBAAmB,CAAC;AAK1D,MAAM,WAAW,oBAAoB;IACnC,yDAAyD;IACzD,QAAQ,EAAE,OAAO,CAAC;IAClB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,oBAAoB,CA8HtB;AAyHD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAuF/D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,WAAW,EACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAAG,IAAI,CAsB/D;AAuBD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,cAAc,GAAG,SAAS,EACjC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,CAAC,CAAC,IAAI,EAAE,UAAU,KAAK,OAAO,CAAC,GAAG,IAAI,CAOxC"}
|