@icure/cardinal-mcp-server 1.0.0 → 1.0.1
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/resources/search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/resources/search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAqFpE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,QAqKnD"}
|
package/dist/resources/search.js
CHANGED
|
@@ -1,35 +1,107 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { getManifest } from "../helpers/docs-loader.js";
|
|
3
|
+
/**
|
|
4
|
+
* Tokenize a query into lowercase words, splitting on spaces and camelCase boundaries.
|
|
5
|
+
* "filterContactsBy" -> ["filter", "contacts", "by"]
|
|
6
|
+
* "contact filter" -> ["contact", "filter"]
|
|
7
|
+
*/
|
|
8
|
+
function tokenize(text) {
|
|
9
|
+
return text
|
|
10
|
+
// Split camelCase: "filterContactsBy" -> "filter Contacts By"
|
|
11
|
+
.replace(/([a-z])([A-Z])/g, "$1 $2")
|
|
12
|
+
.toLowerCase()
|
|
13
|
+
.split(/[\s_\-./]+/)
|
|
14
|
+
.filter(w => w.length > 0);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Score how well a text matches the query tokens.
|
|
18
|
+
* Returns 0 if any token has no match at all.
|
|
19
|
+
* Higher scores = better matches. Exact substring match of full query scores highest.
|
|
20
|
+
*/
|
|
21
|
+
function scoreMatch(text, queryTokens, fullQueryLower) {
|
|
22
|
+
const textLower = text.toLowerCase();
|
|
23
|
+
const textTokens = tokenize(text);
|
|
24
|
+
// Exact full-query substring match gets highest score
|
|
25
|
+
if (textLower.includes(fullQueryLower))
|
|
26
|
+
return 100;
|
|
27
|
+
// Check each query token against the text
|
|
28
|
+
let totalScore = 0;
|
|
29
|
+
let allMatched = true;
|
|
30
|
+
for (const qt of queryTokens) {
|
|
31
|
+
// Direct substring match in full text
|
|
32
|
+
if (textLower.includes(qt)) {
|
|
33
|
+
totalScore += 10;
|
|
34
|
+
// Bonus for matching a whole token exactly
|
|
35
|
+
if (textTokens.includes(qt))
|
|
36
|
+
totalScore += 5;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
// Prefix match on any text token (e.g., "form" matches "formId")
|
|
40
|
+
const prefixMatch = textTokens.some(tt => tt.startsWith(qt) || qt.startsWith(tt));
|
|
41
|
+
if (prefixMatch) {
|
|
42
|
+
totalScore += 5;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
allMatched = false;
|
|
46
|
+
}
|
|
47
|
+
// If not all query tokens matched, heavily penalize but don't zero out
|
|
48
|
+
// (allows partial matches to still appear, ranked lower)
|
|
49
|
+
if (!allMatched) {
|
|
50
|
+
totalScore = Math.floor(totalScore / 3);
|
|
51
|
+
}
|
|
52
|
+
return totalScore;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Build a searchable text blob for an item, combining all relevant fields.
|
|
56
|
+
*/
|
|
57
|
+
function apiSearchText(apiKey, apiName, description) {
|
|
58
|
+
return `${apiKey} ${apiName} ${description}`;
|
|
59
|
+
}
|
|
60
|
+
function methodSearchText(apiKey, methodName, description, paramNames) {
|
|
61
|
+
return `${apiKey} ${methodName} ${description} ${paramNames.join(" ")}`;
|
|
62
|
+
}
|
|
63
|
+
function filterSearchText(entityName, methodName, paramNames) {
|
|
64
|
+
return `${entityName} ${entityName}Filters ${methodName} filter ${paramNames.join(" ")}`;
|
|
65
|
+
}
|
|
3
66
|
export function registerSearchTool(server) {
|
|
4
|
-
server.tool("search_documentation", "Search Cardinal SDK documentation: API methods, models, and filters. No SDK initialization required.", {
|
|
5
|
-
query: z.string().describe("Search term (e.g., 'patient', 'createCalendarItem', 'filter by
|
|
67
|
+
server.tool("search_documentation", "Search Cardinal SDK documentation: API methods, models, and filters. No SDK initialization required. Supports multi-word queries (e.g., 'contact filter', 'form patient', 'filter by date').", {
|
|
68
|
+
query: z.string().describe("Search term (e.g., 'patient', 'createCalendarItem', 'contact filter', 'filter forms by patient')"),
|
|
6
69
|
category: z.enum(["all", "apis", "models", "filters", "tutorials"]).optional().default("all")
|
|
7
70
|
.describe("Limit search to a category"),
|
|
8
71
|
limit: z.number().optional().default(20).describe("Max results to return"),
|
|
9
72
|
}, async ({ query, category, limit }) => {
|
|
10
73
|
const manifest = getManifest();
|
|
11
|
-
const
|
|
74
|
+
const queryTokens = tokenize(query);
|
|
75
|
+
const fullQueryLower = query.toLowerCase();
|
|
76
|
+
if (queryTokens.length === 0) {
|
|
77
|
+
return {
|
|
78
|
+
content: [{ type: "text", text: JSON.stringify({ query, resultCount: 0, results: [] }) }],
|
|
79
|
+
};
|
|
80
|
+
}
|
|
12
81
|
const results = [];
|
|
13
82
|
// Search APIs
|
|
14
83
|
if (category === "all" || category === "apis") {
|
|
15
84
|
for (const [key, api] of Object.entries(manifest.apis)) {
|
|
16
|
-
|
|
17
|
-
if (
|
|
85
|
+
const score = scoreMatch(apiSearchText(key, api.name, api.description), queryTokens, fullQueryLower);
|
|
86
|
+
if (score > 0) {
|
|
18
87
|
results.push({
|
|
19
88
|
type: "api",
|
|
20
89
|
name: api.name,
|
|
21
90
|
description: api.description,
|
|
22
91
|
uri: `cardinal://docs/api/${key}`,
|
|
92
|
+
score,
|
|
23
93
|
});
|
|
24
94
|
}
|
|
25
|
-
// Match methods
|
|
26
95
|
for (const method of api.methods) {
|
|
27
|
-
|
|
96
|
+
const paramNames = method.params.map(p => p.name);
|
|
97
|
+
const score = scoreMatch(methodSearchText(key, method.name, method.description, paramNames), queryTokens, fullQueryLower);
|
|
98
|
+
if (score > 0) {
|
|
28
99
|
results.push({
|
|
29
100
|
type: "method",
|
|
30
101
|
name: `${api.name}.${method.name}`,
|
|
31
|
-
description: method.description || `${method.name}(${
|
|
102
|
+
description: method.description || `${method.name}(${paramNames.join(", ")}): ${method.returnType}`,
|
|
32
103
|
uri: `cardinal://docs/api/${key}`,
|
|
104
|
+
score,
|
|
33
105
|
});
|
|
34
106
|
}
|
|
35
107
|
}
|
|
@@ -38,22 +110,27 @@ export function registerSearchTool(server) {
|
|
|
38
110
|
// Search models
|
|
39
111
|
if (category === "all" || category === "models") {
|
|
40
112
|
for (const [key, model] of Object.entries(manifest.models)) {
|
|
41
|
-
|
|
113
|
+
const modelText = `${key} ${model.name} ${(model.variants || []).join(" ")} ${(model.implements || []).join(" ")}`;
|
|
114
|
+
const score = scoreMatch(modelText, queryTokens, fullQueryLower);
|
|
115
|
+
if (score > 0) {
|
|
42
116
|
results.push({
|
|
43
117
|
type: "model",
|
|
44
118
|
name: model.name,
|
|
45
119
|
description: model.variants ? `Encryptable: ${model.variants.join(", ")}` : `${model.fields.length} fields`,
|
|
46
120
|
uri: `cardinal://docs/model/${key}`,
|
|
121
|
+
score,
|
|
47
122
|
});
|
|
48
123
|
}
|
|
49
|
-
// Also search field names
|
|
50
124
|
for (const field of model.fields) {
|
|
51
|
-
|
|
125
|
+
const fieldText = `${key} ${model.name} ${field.name} ${field.type}`;
|
|
126
|
+
const score = scoreMatch(fieldText, queryTokens, fullQueryLower);
|
|
127
|
+
if (score > 0) {
|
|
52
128
|
results.push({
|
|
53
129
|
type: "model_field",
|
|
54
130
|
name: `${model.name}.${field.name}`,
|
|
55
131
|
description: `${field.type}${field.description ? " — " + field.description : ""}`,
|
|
56
132
|
uri: `cardinal://docs/model/${key}`,
|
|
133
|
+
score,
|
|
57
134
|
});
|
|
58
135
|
}
|
|
59
136
|
}
|
|
@@ -62,21 +139,27 @@ export function registerSearchTool(server) {
|
|
|
62
139
|
// Search filters
|
|
63
140
|
if (category === "all" || category === "filters") {
|
|
64
141
|
for (const [key, filter] of Object.entries(manifest.filters)) {
|
|
65
|
-
|
|
142
|
+
const filterText = `${key} ${key}Filters filter`;
|
|
143
|
+
const score = scoreMatch(filterText, queryTokens, fullQueryLower);
|
|
144
|
+
if (score > 0) {
|
|
66
145
|
results.push({
|
|
67
146
|
type: "filter",
|
|
68
147
|
name: `${key}Filters`,
|
|
69
|
-
description: `${filter.methods.length} filter methods`,
|
|
148
|
+
description: `${filter.methods.length} filter methods for ${key}`,
|
|
70
149
|
uri: `cardinal://docs/filter/${key}`,
|
|
150
|
+
score,
|
|
71
151
|
});
|
|
72
152
|
}
|
|
73
153
|
for (const method of filter.methods) {
|
|
74
|
-
|
|
154
|
+
const paramNames = method.params.map(p => p.name);
|
|
155
|
+
const score = scoreMatch(filterSearchText(key, method.name, paramNames), queryTokens, fullQueryLower);
|
|
156
|
+
if (score > 0) {
|
|
75
157
|
results.push({
|
|
76
158
|
type: "filter_method",
|
|
77
159
|
name: `${key}Filters.${method.name}`,
|
|
78
160
|
description: `(${method.params.map(p => `${p.name}: ${p.type}`).join(", ")})`,
|
|
79
161
|
uri: `cardinal://docs/filter/${key}`,
|
|
162
|
+
score,
|
|
80
163
|
});
|
|
81
164
|
}
|
|
82
165
|
}
|
|
@@ -85,19 +168,21 @@ export function registerSearchTool(server) {
|
|
|
85
168
|
// Search tutorials
|
|
86
169
|
if (category === "all" || category === "tutorials") {
|
|
87
170
|
for (const tutorial of manifest.tutorials) {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
171
|
+
const tutorialText = `${tutorial.title} ${tutorial.slug} ${tutorial.content}`;
|
|
172
|
+
const score = scoreMatch(tutorialText, queryTokens, fullQueryLower);
|
|
173
|
+
if (score > 0) {
|
|
91
174
|
results.push({
|
|
92
175
|
type: "tutorial",
|
|
93
176
|
name: tutorial.title,
|
|
94
177
|
description: `Tutorial: ${tutorial.slug}`,
|
|
95
178
|
uri: `cardinal://docs/tutorial/${tutorial.slug}`,
|
|
179
|
+
score,
|
|
96
180
|
});
|
|
97
181
|
}
|
|
98
182
|
}
|
|
99
183
|
}
|
|
100
|
-
//
|
|
184
|
+
// Sort by score descending, deduplicate, limit
|
|
185
|
+
results.sort((a, b) => b.score - a.score);
|
|
101
186
|
const seen = new Set();
|
|
102
187
|
const unique = results.filter(r => {
|
|
103
188
|
const key = `${r.type}:${r.name}`;
|
|
@@ -106,13 +191,15 @@ export function registerSearchTool(server) {
|
|
|
106
191
|
seen.add(key);
|
|
107
192
|
return true;
|
|
108
193
|
}).slice(0, limit);
|
|
194
|
+
// Strip score from output
|
|
195
|
+
const output = unique.map(({ score: _score, ...rest }) => rest);
|
|
109
196
|
return {
|
|
110
197
|
content: [{
|
|
111
198
|
type: "text",
|
|
112
199
|
text: JSON.stringify({
|
|
113
200
|
query,
|
|
114
|
-
resultCount:
|
|
115
|
-
results:
|
|
201
|
+
resultCount: output.length,
|
|
202
|
+
results: output,
|
|
116
203
|
}, null, 2),
|
|
117
204
|
}],
|
|
118
205
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/resources/search.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/resources/search.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAUxD;;;;GAIG;AACH,SAAS,QAAQ,CAAC,IAAY;IAC7B,OAAO,IAAI;QACV,8DAA8D;SAC7D,OAAO,CAAC,iBAAiB,EAAE,OAAO,CAAC;SACnC,WAAW,EAAE;SACb,KAAK,CAAC,YAAY,CAAC;SACnB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAC7B,CAAC;AAED;;;;GAIG;AACH,SAAS,UAAU,CAAC,IAAY,EAAE,WAAqB,EAAE,cAAsB;IAC9E,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACrC,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAElC,sDAAsD;IACtD,IAAI,SAAS,CAAC,QAAQ,CAAC,cAAc,CAAC;QAAE,OAAO,GAAG,CAAC;IAEnD,0CAA0C;IAC1C,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,UAAU,GAAG,IAAI,CAAC;IAEtB,KAAK,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC;QAC9B,sCAAsC;QACtC,IAAI,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;YAC5B,UAAU,IAAI,EAAE,CAAC;YACjB,2CAA2C;YAC3C,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAAE,UAAU,IAAI,CAAC,CAAC;YAC7C,SAAS;QACV,CAAC;QAED,iEAAiE;QACjE,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;QAClF,IAAI,WAAW,EAAE,CAAC;YACjB,UAAU,IAAI,CAAC,CAAC;YAChB,SAAS;QACV,CAAC;QAED,UAAU,GAAG,KAAK,CAAC;IACpB,CAAC;IAED,uEAAuE;IACvE,yDAAyD;IACzD,IAAI,CAAC,UAAU,EAAE,CAAC;QACjB,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,UAAU,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,MAAc,EAAE,OAAe,EAAE,WAAmB;IAC1E,OAAO,GAAG,MAAM,IAAI,OAAO,IAAI,WAAW,EAAE,CAAC;AAC9C,CAAC;AAED,SAAS,gBAAgB,CAAC,MAAc,EAAE,UAAkB,EAAE,WAAmB,EAAE,UAAoB;IACtG,OAAO,GAAG,MAAM,IAAI,UAAU,IAAI,WAAW,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AACzE,CAAC;AAED,SAAS,gBAAgB,CAAC,UAAkB,EAAE,UAAkB,EAAE,UAAoB;IACrF,OAAO,GAAG,UAAU,IAAI,UAAU,WAAW,UAAU,WAAW,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AAC1F,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAiB;IACnD,MAAM,CAAC,IAAI,CACV,sBAAsB,EACtB,8LAA8L,EAC9L;QACC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kGAAkG,CAAC;QAC9H,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;aAC3F,QAAQ,CAAC,4BAA4B,CAAC;QACxC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,uBAAuB,CAAC;KAC1E,EACD,KAAK,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE;QACpC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;QAC/B,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;QACpC,MAAM,cAAc,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;QAE3C,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,OAAO;gBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC;aAClG,CAAC;QACH,CAAC;QAED,MAAM,OAAO,GAAmB,EAAE,CAAC;QAEnC,cAAc;QACd,IAAI,QAAQ,KAAK,KAAK,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;YAC/C,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxD,MAAM,KAAK,GAAG,UAAU,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,WAAW,CAAC,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC;gBACrG,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;oBACf,OAAO,CAAC,IAAI,CAAC;wBACZ,IAAI,EAAE,KAAK;wBACX,IAAI,EAAE,GAAG,CAAC,IAAI;wBACd,WAAW,EAAE,GAAG,CAAC,WAAW;wBAC5B,GAAG,EAAE,uBAAuB,GAAG,EAAE;wBACjC,KAAK;qBACL,CAAC,CAAC;gBACJ,CAAC;gBAED,KAAK,MAAM,MAAM,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;oBAClC,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;oBAClD,MAAM,KAAK,GAAG,UAAU,CACvB,gBAAgB,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,WAAW,EAAE,UAAU,CAAC,EAClE,WAAW,EACX,cAAc,CACd,CAAC;oBACF,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;wBACf,OAAO,CAAC,IAAI,CAAC;4BACZ,IAAI,EAAE,QAAQ;4BACd,IAAI,EAAE,GAAG,GAAG,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,EAAE;4BAClC,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,MAAM,CAAC,UAAU,EAAE;4BACnG,GAAG,EAAE,uBAAuB,GAAG,EAAE;4BACjC,KAAK;yBACL,CAAC,CAAC;oBACJ,CAAC;gBACF,CAAC;YACF,CAAC;QACF,CAAC;QAED,gBAAgB;QAChB,IAAI,QAAQ,KAAK,KAAK,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACjD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC5D,MAAM,SAAS,GAAG,GAAG,GAAG,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBACnH,MAAM,KAAK,GAAG,UAAU,CAAC,SAAS,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC;gBACjE,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;oBACf,OAAO,CAAC,IAAI,CAAC;wBACZ,IAAI,EAAE,OAAO;wBACb,IAAI,EAAE,KAAK,CAAC,IAAI;wBAChB,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,gBAAgB,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,SAAS;wBAC3G,GAAG,EAAE,yBAAyB,GAAG,EAAE;wBACnC,KAAK;qBACL,CAAC,CAAC;gBACJ,CAAC;gBAED,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;oBAClC,MAAM,SAAS,GAAG,GAAG,GAAG,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;oBACrE,MAAM,KAAK,GAAG,UAAU,CAAC,SAAS,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC;oBACjE,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;wBACf,OAAO,CAAC,IAAI,CAAC;4BACZ,IAAI,EAAE,aAAa;4BACnB,IAAI,EAAE,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE;4BACnC,WAAW,EAAE,GAAG,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE;4BACjF,GAAG,EAAE,yBAAyB,GAAG,EAAE;4BACnC,KAAK;yBACL,CAAC,CAAC;oBACJ,CAAC;gBACF,CAAC;YACF,CAAC;QACF,CAAC;QAED,iBAAiB;QACjB,IAAI,QAAQ,KAAK,KAAK,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAClD,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC9D,MAAM,UAAU,GAAG,GAAG,GAAG,IAAI,GAAG,gBAAgB,CAAC;gBACjD,MAAM,KAAK,GAAG,UAAU,CAAC,UAAU,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC;gBAClE,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;oBACf,OAAO,CAAC,IAAI,CAAC;wBACZ,IAAI,EAAE,QAAQ;wBACd,IAAI,EAAE,GAAG,GAAG,SAAS;wBACrB,WAAW,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,uBAAuB,GAAG,EAAE;wBACjE,GAAG,EAAE,0BAA0B,GAAG,EAAE;wBACpC,KAAK;qBACL,CAAC,CAAC;gBACJ,CAAC;gBAED,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;oBACrC,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;oBAClD,MAAM,KAAK,GAAG,UAAU,CACvB,gBAAgB,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,EAC9C,WAAW,EACX,cAAc,CACd,CAAC;oBACF,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;wBACf,OAAO,CAAC,IAAI,CAAC;4BACZ,IAAI,EAAE,eAAe;4BACrB,IAAI,EAAE,GAAG,GAAG,WAAW,MAAM,CAAC,IAAI,EAAE;4BACpC,WAAW,EAAE,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;4BAC7E,GAAG,EAAE,0BAA0B,GAAG,EAAE;4BACpC,KAAK;yBACL,CAAC,CAAC;oBACJ,CAAC;gBACF,CAAC;YACF,CAAC;QACF,CAAC;QAED,mBAAmB;QACnB,IAAI,QAAQ,KAAK,KAAK,IAAI,QAAQ,KAAK,WAAW,EAAE,CAAC;YACpD,KAAK,MAAM,QAAQ,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC;gBAC3C,MAAM,YAAY,GAAG,GAAG,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;gBAC9E,MAAM,KAAK,GAAG,UAAU,CAAC,YAAY,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC;gBACpE,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;oBACf,OAAO,CAAC,IAAI,CAAC;wBACZ,IAAI,EAAE,UAAU;wBAChB,IAAI,EAAE,QAAQ,CAAC,KAAK;wBACpB,WAAW,EAAE,aAAa,QAAQ,CAAC,IAAI,EAAE;wBACzC,GAAG,EAAE,4BAA4B,QAAQ,CAAC,IAAI,EAAE;wBAChD,KAAK;qBACL,CAAC,CAAC;gBACJ,CAAC;YACF,CAAC;QACF,CAAC;QAED,+CAA+C;QAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;QAC1C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;YACjC,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;YAClC,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,OAAO,KAAK,CAAC;YAChC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACd,OAAO,IAAI,CAAC;QACb,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QAEnB,0BAA0B;QAC1B,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;QAEhE,OAAO;YACN,OAAO,EAAE,CAAC;oBACT,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;wBACpB,KAAK;wBACL,WAAW,EAAE,MAAM,CAAC,MAAM;wBAC1B,OAAO,EAAE,MAAM;qBACf,EAAE,IAAI,EAAE,CAAC,CAAC;iBACX,CAAC;SACF,CAAC;IACH,CAAC,CACD,CAAC;AACH,CAAC"}
|