@compilr-dev/agents-coding-python 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.
Files changed (83) hide show
  1. package/LICENSE +21 -0
  2. package/dist/index.d.ts +40 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +27 -0
  5. package/dist/parser/index.d.ts +6 -0
  6. package/dist/parser/index.d.ts.map +1 -0
  7. package/dist/parser/index.js +5 -0
  8. package/dist/parser/node-types.d.ts +119 -0
  9. package/dist/parser/node-types.d.ts.map +1 -0
  10. package/dist/parser/node-types.js +4 -0
  11. package/dist/parser/python-parser.d.ts +85 -0
  12. package/dist/parser/python-parser.d.ts.map +1 -0
  13. package/dist/parser/python-parser.js +477 -0
  14. package/dist/skills/index.d.ts +26 -0
  15. package/dist/skills/index.d.ts.map +1 -0
  16. package/dist/skills/index.js +36 -0
  17. package/dist/skills/python-best-practices.d.ts +7 -0
  18. package/dist/skills/python-best-practices.d.ts.map +1 -0
  19. package/dist/skills/python-best-practices.js +78 -0
  20. package/dist/skills/python-code-health.d.ts +7 -0
  21. package/dist/skills/python-code-health.d.ts.map +1 -0
  22. package/dist/skills/python-code-health.js +209 -0
  23. package/dist/skills/python-code-structure.d.ts +7 -0
  24. package/dist/skills/python-code-structure.d.ts.map +1 -0
  25. package/dist/skills/python-code-structure.js +155 -0
  26. package/dist/skills/python-dependency-audit.d.ts +7 -0
  27. package/dist/skills/python-dependency-audit.d.ts.map +1 -0
  28. package/dist/skills/python-dependency-audit.js +246 -0
  29. package/dist/skills/python-refactor-impact.d.ts +7 -0
  30. package/dist/skills/python-refactor-impact.d.ts.map +1 -0
  31. package/dist/skills/python-refactor-impact.js +232 -0
  32. package/dist/tools/extract-docstrings.d.ts +70 -0
  33. package/dist/tools/extract-docstrings.d.ts.map +1 -0
  34. package/dist/tools/extract-docstrings.js +575 -0
  35. package/dist/tools/find-dead-code.d.ts +62 -0
  36. package/dist/tools/find-dead-code.d.ts.map +1 -0
  37. package/dist/tools/find-dead-code.js +422 -0
  38. package/dist/tools/find-duplicates.d.ts +65 -0
  39. package/dist/tools/find-duplicates.d.ts.map +1 -0
  40. package/dist/tools/find-duplicates.js +289 -0
  41. package/dist/tools/find-implementations.d.ts +71 -0
  42. package/dist/tools/find-implementations.d.ts.map +1 -0
  43. package/dist/tools/find-implementations.js +342 -0
  44. package/dist/tools/find-patterns.d.ts +71 -0
  45. package/dist/tools/find-patterns.d.ts.map +1 -0
  46. package/dist/tools/find-patterns.js +477 -0
  47. package/dist/tools/find-references.d.ts +66 -0
  48. package/dist/tools/find-references.d.ts.map +1 -0
  49. package/dist/tools/find-references.js +306 -0
  50. package/dist/tools/find-symbol.d.ts +86 -0
  51. package/dist/tools/find-symbol.d.ts.map +1 -0
  52. package/dist/tools/find-symbol.js +414 -0
  53. package/dist/tools/get-call-graph.d.ts +89 -0
  54. package/dist/tools/get-call-graph.d.ts.map +1 -0
  55. package/dist/tools/get-call-graph.js +431 -0
  56. package/dist/tools/get-class-hierarchy.d.ts +38 -0
  57. package/dist/tools/get-class-hierarchy.d.ts.map +1 -0
  58. package/dist/tools/get-class-hierarchy.js +289 -0
  59. package/dist/tools/get-complexity.d.ts +61 -0
  60. package/dist/tools/get-complexity.d.ts.map +1 -0
  61. package/dist/tools/get-complexity.js +384 -0
  62. package/dist/tools/get-dependency-graph.d.ts +85 -0
  63. package/dist/tools/get-dependency-graph.d.ts.map +1 -0
  64. package/dist/tools/get-dependency-graph.js +387 -0
  65. package/dist/tools/get-exports.d.ts +78 -0
  66. package/dist/tools/get-exports.d.ts.map +1 -0
  67. package/dist/tools/get-exports.js +437 -0
  68. package/dist/tools/get-file-structure.d.ts +28 -0
  69. package/dist/tools/get-file-structure.d.ts.map +1 -0
  70. package/dist/tools/get-file-structure.js +186 -0
  71. package/dist/tools/get-imports.d.ts +34 -0
  72. package/dist/tools/get-imports.d.ts.map +1 -0
  73. package/dist/tools/get-imports.js +455 -0
  74. package/dist/tools/get-signature.d.ts +100 -0
  75. package/dist/tools/get-signature.d.ts.map +1 -0
  76. package/dist/tools/get-signature.js +800 -0
  77. package/dist/tools/index.d.ts +55 -0
  78. package/dist/tools/index.d.ts.map +1 -0
  79. package/dist/tools/index.js +75 -0
  80. package/dist/tools/types.d.ts +378 -0
  81. package/dist/tools/types.d.ts.map +1 -0
  82. package/dist/tools/types.js +4 -0
  83. package/package.json +85 -0
@@ -0,0 +1,384 @@
1
+ /**
2
+ * getComplexity Tool
3
+ *
4
+ * Calculate cyclomatic and cognitive complexity for Python functions.
5
+ * Identifies complex code that may need refactoring.
6
+ */
7
+ import * as fs from "node:fs/promises";
8
+ import * as path from "node:path";
9
+ import { defineTool, createSuccessResult, createErrorResult, } from "@compilr-dev/agents";
10
+ import { parseFile, parseFunction, parseClass, parseDecorators, } from "../parser/python-parser.js";
11
+ // Tool description
12
+ const TOOL_DESCRIPTION = `Calculate cyclomatic and cognitive complexity for Python functions.
13
+ Identifies code that may be hard to understand or maintain.
14
+ Returns complexity metrics and highlights hotspots that may need refactoring.`;
15
+ // Tool input schema
16
+ const TOOL_INPUT_SCHEMA = {
17
+ type: "object",
18
+ properties: {
19
+ path: {
20
+ type: "string",
21
+ description: "File or directory to analyze",
22
+ },
23
+ recursive: {
24
+ type: "boolean",
25
+ description: "Recursively analyze directory (default: false)",
26
+ default: false,
27
+ },
28
+ threshold: {
29
+ type: "number",
30
+ description: "Complexity threshold for warnings (default: 10)",
31
+ default: 10,
32
+ },
33
+ onlyAboveThreshold: {
34
+ type: "boolean",
35
+ description: "Only return items above threshold (default: false)",
36
+ default: false,
37
+ },
38
+ maxFiles: {
39
+ type: "number",
40
+ description: "Maximum files to analyze (default: 50)",
41
+ default: 50,
42
+ },
43
+ },
44
+ required: ["path"],
45
+ };
46
+ /**
47
+ * getComplexity tool - Calculate code complexity
48
+ */
49
+ export const getComplexityTool = defineTool({
50
+ name: "get_complexity_python",
51
+ description: TOOL_DESCRIPTION,
52
+ inputSchema: TOOL_INPUT_SCHEMA,
53
+ execute: executeGetComplexity,
54
+ });
55
+ /**
56
+ * Execute the getComplexity tool
57
+ */
58
+ async function executeGetComplexity(input) {
59
+ const { path: targetPath, recursive = false, threshold = 10, onlyAboveThreshold = false, maxFiles = 50, } = input;
60
+ const resolvedPath = path.resolve(targetPath);
61
+ try {
62
+ await fs.access(resolvedPath);
63
+ }
64
+ catch {
65
+ return createErrorResult(`Path not found: ${resolvedPath}`);
66
+ }
67
+ const stats = await fs.stat(resolvedPath);
68
+ try {
69
+ const files = [];
70
+ if (stats.isFile()) {
71
+ if (!resolvedPath.endsWith(".py") && !resolvedPath.endsWith(".pyi")) {
72
+ return createErrorResult(`Not a Python file: ${resolvedPath}`);
73
+ }
74
+ const fileResult = await analyzeFileComplexity(resolvedPath, threshold, onlyAboveThreshold);
75
+ files.push(fileResult);
76
+ }
77
+ else if (stats.isDirectory()) {
78
+ const pythonFiles = await collectPythonFiles(resolvedPath, recursive, maxFiles);
79
+ for (const filePath of pythonFiles) {
80
+ const fileResult = await analyzeFileComplexity(filePath, threshold, onlyAboveThreshold);
81
+ if (fileResult.functions.length > 0 || !onlyAboveThreshold) {
82
+ files.push(fileResult);
83
+ }
84
+ }
85
+ }
86
+ // Calculate summary
87
+ let totalFunctions = 0;
88
+ let totalComplexity = 0;
89
+ let maxComplexity = 0;
90
+ let aboveThreshold = 0;
91
+ const hotspots = [];
92
+ for (const file of files) {
93
+ totalFunctions += file.functions.length;
94
+ for (const func of file.functions) {
95
+ totalComplexity += func.metrics.cyclomatic;
96
+ if (func.metrics.cyclomatic > maxComplexity) {
97
+ maxComplexity = func.metrics.cyclomatic;
98
+ }
99
+ if (func.isComplex) {
100
+ aboveThreshold++;
101
+ }
102
+ hotspots.push({
103
+ name: func.name,
104
+ path: file.path,
105
+ line: func.line,
106
+ cyclomatic: func.metrics.cyclomatic,
107
+ cognitive: func.metrics.cognitive,
108
+ });
109
+ }
110
+ }
111
+ // Sort hotspots by complexity and take top 5
112
+ hotspots.sort((a, b) => b.cyclomatic - a.cyclomatic);
113
+ const topHotspots = hotspots.slice(0, 5);
114
+ const result = {
115
+ path: resolvedPath,
116
+ files,
117
+ summary: {
118
+ totalFiles: files.length,
119
+ totalFunctions,
120
+ averageComplexity: totalFunctions > 0 ? totalComplexity / totalFunctions : 0,
121
+ maxComplexity,
122
+ aboveThreshold,
123
+ threshold,
124
+ },
125
+ hotspots: topHotspots,
126
+ };
127
+ return createSuccessResult(result);
128
+ }
129
+ catch (error) {
130
+ const message = error instanceof Error ? error.message : String(error);
131
+ return createErrorResult(`Failed to analyze complexity: ${message}`);
132
+ }
133
+ }
134
+ /**
135
+ * Analyze complexity for a single file
136
+ */
137
+ async function analyzeFileComplexity(filePath, threshold, onlyAboveThreshold) {
138
+ const parseResult = await parseFile(filePath);
139
+ const { tree, source } = parseResult;
140
+ const functions = [];
141
+ // Analyze top-level functions
142
+ for (const child of tree.rootNode.children) {
143
+ if (child.type === "function_definition" ||
144
+ child.type === "async_function_definition") {
145
+ const funcInfo = parseFunction(child, source);
146
+ const metrics = calculateComplexity(child, source);
147
+ const isComplex = metrics.cyclomatic >= threshold;
148
+ if (!onlyAboveThreshold || isComplex) {
149
+ functions.push({
150
+ name: funcInfo.name,
151
+ path: filePath,
152
+ line: funcInfo.line,
153
+ metrics,
154
+ isComplex,
155
+ });
156
+ }
157
+ }
158
+ // Decorated functions
159
+ if (child.type === "decorated_definition") {
160
+ const funcNode = child.children.find((c) => c.type === "function_definition" ||
161
+ c.type === "async_function_definition");
162
+ if (funcNode) {
163
+ const decorators = parseDecorators(child, source);
164
+ const funcInfo = parseFunction(funcNode, source, decorators);
165
+ const metrics = calculateComplexity(funcNode, source);
166
+ const isComplex = metrics.cyclomatic >= threshold;
167
+ if (!onlyAboveThreshold || isComplex) {
168
+ functions.push({
169
+ name: funcInfo.name,
170
+ path: filePath,
171
+ line: funcInfo.line,
172
+ metrics,
173
+ isComplex,
174
+ });
175
+ }
176
+ }
177
+ }
178
+ // Class methods
179
+ if (child.type === "class_definition") {
180
+ const classInfo = parseClass(child, source);
181
+ const body = child.childForFieldName("body");
182
+ if (body) {
183
+ for (const member of body.children) {
184
+ if (member.type === "function_definition" ||
185
+ member.type === "async_function_definition") {
186
+ const funcInfo = parseFunction(member, source);
187
+ const metrics = calculateComplexity(member, source);
188
+ const isComplex = metrics.cyclomatic >= threshold;
189
+ if (!onlyAboveThreshold || isComplex) {
190
+ functions.push({
191
+ name: `${classInfo.name}.${funcInfo.name}`,
192
+ path: filePath,
193
+ line: funcInfo.line,
194
+ metrics,
195
+ isComplex,
196
+ });
197
+ }
198
+ }
199
+ if (member.type === "decorated_definition") {
200
+ const funcNode = member.children.find((c) => c.type === "function_definition" ||
201
+ c.type === "async_function_definition");
202
+ if (funcNode) {
203
+ const decorators = parseDecorators(member, source);
204
+ const funcInfo = parseFunction(funcNode, source, decorators);
205
+ const metrics = calculateComplexity(funcNode, source);
206
+ const isComplex = metrics.cyclomatic >= threshold;
207
+ if (!onlyAboveThreshold || isComplex) {
208
+ functions.push({
209
+ name: `${classInfo.name}.${funcInfo.name}`,
210
+ path: filePath,
211
+ line: funcInfo.line,
212
+ metrics,
213
+ isComplex,
214
+ });
215
+ }
216
+ }
217
+ }
218
+ }
219
+ }
220
+ }
221
+ }
222
+ // Calculate file-level averages
223
+ const totalCyclomatic = functions.reduce((sum, f) => sum + f.metrics.cyclomatic, 0);
224
+ const maxCyclomatic = Math.max(0, ...functions.map((f) => f.metrics.cyclomatic));
225
+ const complexCount = functions.filter((f) => f.isComplex).length;
226
+ return {
227
+ path: filePath,
228
+ functions,
229
+ averageComplexity: functions.length > 0 ? totalCyclomatic / functions.length : 0,
230
+ maxComplexity: maxCyclomatic,
231
+ stats: {
232
+ totalFunctions: functions.length,
233
+ complexFunctions: complexCount,
234
+ simpleAverage: functions.length > 0 ? totalCyclomatic / functions.length : 0,
235
+ },
236
+ };
237
+ }
238
+ /**
239
+ * Calculate complexity metrics for a function
240
+ */
241
+ function calculateComplexity(node, _source) {
242
+ let cyclomatic = 1; // Base complexity
243
+ let cognitive = 0;
244
+ let maxNesting = 0;
245
+ let paramCount = 0;
246
+ // Count parameters
247
+ const paramsNode = node.childForFieldName("parameters");
248
+ if (paramsNode) {
249
+ for (const child of paramsNode.children) {
250
+ if (child.type === "identifier" ||
251
+ child.type === "typed_parameter" ||
252
+ child.type === "default_parameter" ||
253
+ child.type === "typed_default_parameter") {
254
+ paramCount++;
255
+ }
256
+ }
257
+ }
258
+ // Walk the AST and count complexity contributors
259
+ function walk(n, depth) {
260
+ // Track nesting
261
+ const isNestingConstruct = n.type === "if_statement" ||
262
+ n.type === "for_statement" ||
263
+ n.type === "while_statement" ||
264
+ n.type === "try_statement" ||
265
+ n.type === "with_statement" ||
266
+ n.type === "match_statement";
267
+ if (isNestingConstruct) {
268
+ if (depth > maxNesting) {
269
+ maxNesting = depth;
270
+ }
271
+ }
272
+ // Cyclomatic complexity contributors
273
+ switch (n.type) {
274
+ case "if_statement":
275
+ case "elif_clause":
276
+ cyclomatic++;
277
+ cognitive += 1 + depth; // Cognitive adds nesting penalty
278
+ break;
279
+ case "for_statement":
280
+ case "while_statement":
281
+ cyclomatic++;
282
+ cognitive += 1 + depth;
283
+ break;
284
+ case "except_clause":
285
+ cyclomatic++;
286
+ cognitive++;
287
+ break;
288
+ case "conditional_expression": // Ternary
289
+ cyclomatic++;
290
+ cognitive++;
291
+ break;
292
+ case "boolean_operator":
293
+ // and/or add to cyclomatic
294
+ cyclomatic++;
295
+ break;
296
+ case "match_statement":
297
+ cyclomatic++;
298
+ cognitive += 1 + depth;
299
+ break;
300
+ case "case_clause":
301
+ cyclomatic++;
302
+ break;
303
+ case "lambda":
304
+ cognitive++; // Lambdas add cognitive load
305
+ break;
306
+ case "list_comprehension":
307
+ case "dictionary_comprehension":
308
+ case "set_comprehension":
309
+ case "generator_expression":
310
+ cognitive++; // Comprehensions add cognitive load
311
+ break;
312
+ }
313
+ // Recurse into children
314
+ const newDepth = isNestingConstruct ? depth + 1 : depth;
315
+ for (const child of n.children) {
316
+ walk(child, newDepth);
317
+ }
318
+ }
319
+ const body = node.childForFieldName("body");
320
+ if (body) {
321
+ walk(body, 0);
322
+ }
323
+ // Calculate lines of code
324
+ const startLine = node.startPosition.row;
325
+ const endLine = node.endPosition.row;
326
+ const linesOfCode = endLine - startLine + 1;
327
+ return {
328
+ cyclomatic,
329
+ cognitive,
330
+ linesOfCode,
331
+ parameters: paramCount,
332
+ nestingDepth: maxNesting,
333
+ };
334
+ }
335
+ /**
336
+ * Collect Python files in a directory
337
+ */
338
+ async function collectPythonFiles(dir, recursive, maxFiles) {
339
+ const files = [];
340
+ async function walk(currentDir) {
341
+ if (files.length >= maxFiles)
342
+ return;
343
+ const entries = await fs.readdir(currentDir, { withFileTypes: true });
344
+ for (const entry of entries) {
345
+ if (files.length >= maxFiles)
346
+ break;
347
+ const fullPath = path.join(currentDir, entry.name);
348
+ if (entry.isDirectory() && recursive) {
349
+ if (entry.name.startsWith(".") ||
350
+ entry.name === "__pycache__" ||
351
+ entry.name === "venv" ||
352
+ entry.name === ".venv" ||
353
+ entry.name === "node_modules") {
354
+ continue;
355
+ }
356
+ await walk(fullPath);
357
+ }
358
+ else if (entry.isFile() &&
359
+ (fullPath.endsWith(".py") || fullPath.endsWith(".pyi"))) {
360
+ files.push(fullPath);
361
+ }
362
+ }
363
+ }
364
+ await walk(dir);
365
+ return files;
366
+ }
367
+ /**
368
+ * Factory function to create a customized getComplexity tool
369
+ */
370
+ export function createGetComplexityTool(options) {
371
+ const { defaultThreshold = 10, defaultRecursive = false } = options ?? {};
372
+ return defineTool({
373
+ name: "get_complexity_python",
374
+ description: TOOL_DESCRIPTION,
375
+ inputSchema: TOOL_INPUT_SCHEMA,
376
+ execute: async (input) => {
377
+ return executeGetComplexity({
378
+ ...input,
379
+ threshold: input.threshold ?? defaultThreshold,
380
+ recursive: input.recursive ?? defaultRecursive,
381
+ });
382
+ },
383
+ });
384
+ }
@@ -0,0 +1,85 @@
1
+ /**
2
+ * getDependencyGraph Tool
3
+ *
4
+ * Analyze module-level dependencies in Python code.
5
+ * Builds a dependency graph and detects circular dependencies.
6
+ */
7
+ import type { Tool } from "@compilr-dev/agents";
8
+ /**
9
+ * Module node in the dependency graph
10
+ */
11
+ export interface ModuleNode {
12
+ path: string;
13
+ absolutePath: string;
14
+ isExternal: boolean;
15
+ packageName?: string;
16
+ }
17
+ /**
18
+ * Dependency edge
19
+ */
20
+ export interface DependencyEdge {
21
+ from: string;
22
+ to: string;
23
+ importType: "import" | "from_import";
24
+ symbols: string[];
25
+ isRelative: boolean;
26
+ }
27
+ /**
28
+ * Circular dependency
29
+ */
30
+ export interface CircularDependency {
31
+ cycle: string[];
32
+ length: number;
33
+ }
34
+ /**
35
+ * Dependency graph stats
36
+ */
37
+ export interface DependencyGraphStats {
38
+ totalModules: number;
39
+ internalModules: number;
40
+ externalPackages: number;
41
+ totalEdges: number;
42
+ circularDependencies: number;
43
+ externalPackageList: string[];
44
+ mostDependencies?: {
45
+ module: string;
46
+ count: number;
47
+ };
48
+ mostDependents?: {
49
+ module: string;
50
+ count: number;
51
+ };
52
+ }
53
+ /**
54
+ * Input for getDependencyGraph tool
55
+ */
56
+ export interface GetDependencyGraphInput {
57
+ /** Directory or file to analyze */
58
+ path: string;
59
+ /** Include external package dependencies (default: true) */
60
+ includeExternal?: boolean;
61
+ /** Maximum depth for directory traversal (default: 10) */
62
+ maxDepth?: number;
63
+ }
64
+ /**
65
+ * Result of getDependencyGraph
66
+ */
67
+ export interface GetDependencyGraphResult {
68
+ root: string;
69
+ modules: ModuleNode[];
70
+ edges: DependencyEdge[];
71
+ circularDependencies: CircularDependency[];
72
+ stats: DependencyGraphStats;
73
+ }
74
+ /**
75
+ * getDependencyGraph tool
76
+ */
77
+ export declare const getDependencyGraphTool: Tool<GetDependencyGraphInput>;
78
+ /**
79
+ * Factory function to create a customized getDependencyGraph tool
80
+ */
81
+ export declare function createGetDependencyGraphTool(options?: {
82
+ defaultIncludeExternal?: boolean;
83
+ defaultMaxDepth?: number;
84
+ }): Tool<GetDependencyGraphInput>;
85
+ //# sourceMappingURL=get-dependency-graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-dependency-graph.d.ts","sourceRoot":"","sources":["../../src/tools/get-dependency-graph.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,OAAO,KAAK,EAAE,IAAI,EAAuB,MAAM,qBAAqB,CAAC;AAGrE;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,QAAQ,GAAG,aAAa,CAAC;IACrC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,gBAAgB,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACrD,cAAc,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CACpD;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,oBAAoB,EAAE,kBAAkB,EAAE,CAAC;IAC3C,KAAK,EAAE,oBAAoB,CAAC;CAC7B;AA2CD;;GAEG;AACH,eAAO,MAAM,sBAAsB,+BAKjC,CAAC;AA8YH;;GAEG;AACH,wBAAgB,4BAA4B,CAAC,OAAO,CAAC,EAAE;IACrD,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,GAAG,IAAI,CAAC,uBAAuB,CAAC,CAiBhC"}