@compilr-dev/agents-coding-go 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/LICENSE +21 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/parser/go-parser.d.ts +104 -0
- package/dist/parser/go-parser.d.ts.map +1 -0
- package/dist/parser/go-parser.js +492 -0
- package/dist/parser/index.d.ts +6 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +5 -0
- package/dist/parser/node-types.d.ts +130 -0
- package/dist/parser/node-types.d.ts.map +1 -0
- package/dist/parser/node-types.js +4 -0
- package/dist/skills/go-best-practices.d.ts +7 -0
- package/dist/skills/go-best-practices.d.ts.map +1 -0
- package/dist/skills/go-best-practices.js +78 -0
- package/dist/skills/go-code-health.d.ts +7 -0
- package/dist/skills/go-code-health.d.ts.map +1 -0
- package/dist/skills/go-code-health.js +209 -0
- package/dist/skills/go-code-structure.d.ts +7 -0
- package/dist/skills/go-code-structure.d.ts.map +1 -0
- package/dist/skills/go-code-structure.js +155 -0
- package/dist/skills/go-dependency-audit.d.ts +7 -0
- package/dist/skills/go-dependency-audit.d.ts.map +1 -0
- package/dist/skills/go-dependency-audit.js +246 -0
- package/dist/skills/go-refactor-impact.d.ts +7 -0
- package/dist/skills/go-refactor-impact.d.ts.map +1 -0
- package/dist/skills/go-refactor-impact.js +232 -0
- package/dist/skills/index.d.ts +26 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +36 -0
- package/dist/tools/extract-docstrings.d.ts +51 -0
- package/dist/tools/extract-docstrings.d.ts.map +1 -0
- package/dist/tools/extract-docstrings.js +292 -0
- package/dist/tools/find-dead-code.d.ts +62 -0
- package/dist/tools/find-dead-code.d.ts.map +1 -0
- package/dist/tools/find-dead-code.js +422 -0
- package/dist/tools/find-duplicates.d.ts +65 -0
- package/dist/tools/find-duplicates.d.ts.map +1 -0
- package/dist/tools/find-duplicates.js +289 -0
- package/dist/tools/find-implementations.d.ts +71 -0
- package/dist/tools/find-implementations.d.ts.map +1 -0
- package/dist/tools/find-implementations.js +342 -0
- package/dist/tools/find-patterns.d.ts +71 -0
- package/dist/tools/find-patterns.d.ts.map +1 -0
- package/dist/tools/find-patterns.js +477 -0
- package/dist/tools/find-references.d.ts +66 -0
- package/dist/tools/find-references.d.ts.map +1 -0
- package/dist/tools/find-references.js +306 -0
- package/dist/tools/find-symbol.d.ts +86 -0
- package/dist/tools/find-symbol.d.ts.map +1 -0
- package/dist/tools/find-symbol.js +380 -0
- package/dist/tools/get-call-graph.d.ts +89 -0
- package/dist/tools/get-call-graph.d.ts.map +1 -0
- package/dist/tools/get-call-graph.js +431 -0
- package/dist/tools/get-class-hierarchy.d.ts +34 -0
- package/dist/tools/get-class-hierarchy.d.ts.map +1 -0
- package/dist/tools/get-class-hierarchy.js +250 -0
- package/dist/tools/get-complexity.d.ts +53 -0
- package/dist/tools/get-complexity.d.ts.map +1 -0
- package/dist/tools/get-complexity.js +357 -0
- package/dist/tools/get-dependency-graph.d.ts +85 -0
- package/dist/tools/get-dependency-graph.d.ts.map +1 -0
- package/dist/tools/get-dependency-graph.js +389 -0
- package/dist/tools/get-exports.d.ts +78 -0
- package/dist/tools/get-exports.d.ts.map +1 -0
- package/dist/tools/get-exports.js +437 -0
- package/dist/tools/get-file-structure.d.ts +28 -0
- package/dist/tools/get-file-structure.d.ts.map +1 -0
- package/dist/tools/get-file-structure.js +172 -0
- package/dist/tools/get-imports.d.ts +30 -0
- package/dist/tools/get-imports.d.ts.map +1 -0
- package/dist/tools/get-imports.js +420 -0
- package/dist/tools/get-signature.d.ts +100 -0
- package/dist/tools/get-signature.d.ts.map +1 -0
- package/dist/tools/get-signature.js +800 -0
- package/dist/tools/index.d.ts +55 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +75 -0
- package/dist/tools/types.d.ts +408 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +4 -0
- package/package.json +86 -0
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* extractDocstrings Tool
|
|
3
|
+
*
|
|
4
|
+
* Extract documentation comments from Go code.
|
|
5
|
+
* Go uses godoc-style comments above declarations.
|
|
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, parseMethod, parseClass, extractDocComment, walkTree, } from "../parser/go-parser.js";
|
|
11
|
+
// Tool description
|
|
12
|
+
const TOOL_DESCRIPTION = `Extract documentation comments from Go code.
|
|
13
|
+
Returns parsed godoc-style comments for functions, types, and methods.
|
|
14
|
+
Helps understand code documentation coverage and quality.`;
|
|
15
|
+
// Tool input schema
|
|
16
|
+
const TOOL_INPUT_SCHEMA = {
|
|
17
|
+
type: "object",
|
|
18
|
+
properties: {
|
|
19
|
+
path: {
|
|
20
|
+
type: "string",
|
|
21
|
+
description: "Go file or directory to analyze",
|
|
22
|
+
},
|
|
23
|
+
recursive: {
|
|
24
|
+
type: "boolean",
|
|
25
|
+
description: "Recursively scan directories (default: false)",
|
|
26
|
+
default: false,
|
|
27
|
+
},
|
|
28
|
+
name: {
|
|
29
|
+
type: "string",
|
|
30
|
+
description: "Filter to specific symbol name",
|
|
31
|
+
},
|
|
32
|
+
includeUndocumented: {
|
|
33
|
+
type: "boolean",
|
|
34
|
+
description: "Include symbols without documentation (default: false)",
|
|
35
|
+
default: false,
|
|
36
|
+
},
|
|
37
|
+
maxFiles: {
|
|
38
|
+
type: "number",
|
|
39
|
+
description: "Maximum files to process (default: 50)",
|
|
40
|
+
default: 50,
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
required: ["path"],
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* extractDocstrings tool - Extract Go documentation
|
|
47
|
+
*/
|
|
48
|
+
export const extractDocstringsTool = defineTool({
|
|
49
|
+
name: "extract_docstrings_go",
|
|
50
|
+
description: TOOL_DESCRIPTION,
|
|
51
|
+
inputSchema: TOOL_INPUT_SCHEMA,
|
|
52
|
+
execute: executeExtractDocstrings,
|
|
53
|
+
});
|
|
54
|
+
/**
|
|
55
|
+
* Execute the extractDocstrings tool
|
|
56
|
+
*/
|
|
57
|
+
async function executeExtractDocstrings(input) {
|
|
58
|
+
const { path: inputPath, recursive = false, name, includeUndocumented = false, maxFiles = 50, } = input;
|
|
59
|
+
if (!inputPath) {
|
|
60
|
+
return createErrorResult("Path is required");
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
const stats = await fs.stat(inputPath);
|
|
64
|
+
const docs = [];
|
|
65
|
+
if (stats.isFile()) {
|
|
66
|
+
if (!inputPath.endsWith(".go")) {
|
|
67
|
+
return createErrorResult("File must be a .go file");
|
|
68
|
+
}
|
|
69
|
+
const fileDocs = await extractFileDocstrings(inputPath, name, includeUndocumented);
|
|
70
|
+
docs.push(...fileDocs);
|
|
71
|
+
}
|
|
72
|
+
else if (stats.isDirectory()) {
|
|
73
|
+
const goFiles = await collectGoFiles(inputPath, recursive, maxFiles);
|
|
74
|
+
for (const filePath of goFiles) {
|
|
75
|
+
const fileDocs = await extractFileDocstrings(filePath, name, includeUndocumented);
|
|
76
|
+
docs.push(...fileDocs);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
return createErrorResult("Path must be a file or directory");
|
|
81
|
+
}
|
|
82
|
+
const documented = docs.filter((d) => d.doc);
|
|
83
|
+
const percentage = docs.length > 0 ? Math.round((documented.length / docs.length) * 100) : 0;
|
|
84
|
+
const result = {
|
|
85
|
+
path: inputPath,
|
|
86
|
+
docs,
|
|
87
|
+
stats: {
|
|
88
|
+
total: docs.length,
|
|
89
|
+
documented: documented.length,
|
|
90
|
+
undocumented: docs.length - documented.length,
|
|
91
|
+
percentage,
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
return createSuccessResult(result);
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
98
|
+
return createErrorResult(`Failed to extract documentation: ${message}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Collect Go files from a directory
|
|
103
|
+
*/
|
|
104
|
+
async function collectGoFiles(dir, recursive, maxFiles) {
|
|
105
|
+
const files = [];
|
|
106
|
+
async function walk(currentDir) {
|
|
107
|
+
if (files.length >= maxFiles)
|
|
108
|
+
return;
|
|
109
|
+
const entries = await fs.readdir(currentDir, { withFileTypes: true });
|
|
110
|
+
for (const entry of entries) {
|
|
111
|
+
if (files.length >= maxFiles)
|
|
112
|
+
break;
|
|
113
|
+
const fullPath = path.join(currentDir, entry.name);
|
|
114
|
+
if (entry.isDirectory()) {
|
|
115
|
+
if (recursive &&
|
|
116
|
+
!entry.name.startsWith(".") &&
|
|
117
|
+
entry.name !== "vendor" &&
|
|
118
|
+
entry.name !== "testdata") {
|
|
119
|
+
await walk(fullPath);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
else if (entry.isFile() && entry.name.endsWith(".go")) {
|
|
123
|
+
files.push(fullPath);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
await walk(dir);
|
|
128
|
+
return files;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Extract documentation from a single file
|
|
132
|
+
*/
|
|
133
|
+
async function extractFileDocstrings(filePath, nameFilter, includeUndocumented) {
|
|
134
|
+
const docs = [];
|
|
135
|
+
try {
|
|
136
|
+
const parseResult = await parseFile(filePath);
|
|
137
|
+
const { tree, source } = parseResult;
|
|
138
|
+
for (const node of walkTree(tree.rootNode)) {
|
|
139
|
+
// Functions
|
|
140
|
+
if (node.type === "function_declaration") {
|
|
141
|
+
const funcInfo = parseFunction(node, source);
|
|
142
|
+
if (nameFilter && funcInfo.name !== nameFilter)
|
|
143
|
+
continue;
|
|
144
|
+
const doc = extractDocComment(node, source);
|
|
145
|
+
if (!doc && !includeUndocumented)
|
|
146
|
+
continue;
|
|
147
|
+
docs.push({
|
|
148
|
+
name: funcInfo.name,
|
|
149
|
+
path: filePath,
|
|
150
|
+
line: funcInfo.line,
|
|
151
|
+
doc,
|
|
152
|
+
parsed: doc ? parseGodoc(doc) : undefined,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
// Methods
|
|
156
|
+
if (node.type === "method_declaration") {
|
|
157
|
+
const methodInfo = parseMethod(node, source);
|
|
158
|
+
const fullName = methodInfo.receiverType
|
|
159
|
+
? `${methodInfo.receiverType}.${methodInfo.name}`
|
|
160
|
+
: methodInfo.name;
|
|
161
|
+
if (nameFilter &&
|
|
162
|
+
methodInfo.name !== nameFilter &&
|
|
163
|
+
fullName !== nameFilter)
|
|
164
|
+
continue;
|
|
165
|
+
const doc = extractDocComment(node, source);
|
|
166
|
+
if (!doc && !includeUndocumented)
|
|
167
|
+
continue;
|
|
168
|
+
docs.push({
|
|
169
|
+
name: fullName,
|
|
170
|
+
path: filePath,
|
|
171
|
+
line: methodInfo.line,
|
|
172
|
+
doc,
|
|
173
|
+
parsed: doc ? parseGodoc(doc) : undefined,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
// Types (structs and interfaces)
|
|
177
|
+
if (node.type === "type_declaration") {
|
|
178
|
+
const typeInfo = parseClass(node, source);
|
|
179
|
+
if (nameFilter && typeInfo.name !== nameFilter)
|
|
180
|
+
continue;
|
|
181
|
+
const doc = extractDocComment(node, source);
|
|
182
|
+
if (!doc && !includeUndocumented)
|
|
183
|
+
continue;
|
|
184
|
+
docs.push({
|
|
185
|
+
name: typeInfo.name,
|
|
186
|
+
path: filePath,
|
|
187
|
+
line: typeInfo.line,
|
|
188
|
+
doc,
|
|
189
|
+
parsed: doc ? parseGodoc(doc) : undefined,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
// Skip files that can't be parsed
|
|
196
|
+
}
|
|
197
|
+
return docs;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Parse godoc-style documentation comment
|
|
201
|
+
*
|
|
202
|
+
* Godoc uses a simple format:
|
|
203
|
+
* - First sentence is the summary
|
|
204
|
+
* - Blank line separates summary from body
|
|
205
|
+
* - Deprecated: prefix marks deprecated items
|
|
206
|
+
* - Example blocks with indentation
|
|
207
|
+
*/
|
|
208
|
+
function parseGodoc(doc) {
|
|
209
|
+
const lines = doc.split("\n");
|
|
210
|
+
const summary = [];
|
|
211
|
+
const description = [];
|
|
212
|
+
const examples = [];
|
|
213
|
+
const params = [];
|
|
214
|
+
const errors = [];
|
|
215
|
+
let deprecated;
|
|
216
|
+
let inExample = false;
|
|
217
|
+
let currentExample = [];
|
|
218
|
+
let foundBlankLine = false;
|
|
219
|
+
for (const line of lines) {
|
|
220
|
+
const trimmed = line.trim();
|
|
221
|
+
// Check for Deprecated marker
|
|
222
|
+
if (trimmed.startsWith("Deprecated:")) {
|
|
223
|
+
deprecated = trimmed.substring("Deprecated:".length).trim();
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
// Check for example (indented code block)
|
|
227
|
+
if (line.startsWith(" ") || line.startsWith("\t")) {
|
|
228
|
+
if (!inExample) {
|
|
229
|
+
inExample = true;
|
|
230
|
+
currentExample = [];
|
|
231
|
+
}
|
|
232
|
+
currentExample.push(line);
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
else if (inExample) {
|
|
236
|
+
// End of example
|
|
237
|
+
examples.push(currentExample.join("\n"));
|
|
238
|
+
inExample = false;
|
|
239
|
+
currentExample = [];
|
|
240
|
+
}
|
|
241
|
+
// Check for blank line
|
|
242
|
+
if (trimmed === "") {
|
|
243
|
+
foundBlankLine = true;
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
// Add to summary or description
|
|
247
|
+
if (!foundBlankLine) {
|
|
248
|
+
summary.push(trimmed);
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
description.push(trimmed);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
// Handle trailing example
|
|
255
|
+
if (inExample && currentExample.length > 0) {
|
|
256
|
+
examples.push(currentExample.join("\n"));
|
|
257
|
+
}
|
|
258
|
+
// Attempt to extract return info from description
|
|
259
|
+
let returns;
|
|
260
|
+
const returnMatch = description.join(" ").match(/returns?\s+(.+?)(?:\.|$)/i);
|
|
261
|
+
if (returnMatch) {
|
|
262
|
+
returns = { description: returnMatch[1].trim() };
|
|
263
|
+
}
|
|
264
|
+
return {
|
|
265
|
+
summary: summary.join(" "),
|
|
266
|
+
description: description.length > 0 ? description.join("\n") : undefined,
|
|
267
|
+
parameters: params, // Go doesn't have param docs in comments typically
|
|
268
|
+
returns,
|
|
269
|
+
errors, // Would need to parse "returns error if..." patterns
|
|
270
|
+
examples,
|
|
271
|
+
deprecated,
|
|
272
|
+
format: "godoc",
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Factory function to create a customized extractDocstrings tool
|
|
277
|
+
*/
|
|
278
|
+
export function createExtractDocstringsTool(options) {
|
|
279
|
+
const { defaultMaxFiles = 50, defaultIncludeUndocumented = false } = options ?? {};
|
|
280
|
+
return defineTool({
|
|
281
|
+
name: "extract_docstrings_go",
|
|
282
|
+
description: TOOL_DESCRIPTION,
|
|
283
|
+
inputSchema: TOOL_INPUT_SCHEMA,
|
|
284
|
+
execute: async (input) => {
|
|
285
|
+
return executeExtractDocstrings({
|
|
286
|
+
...input,
|
|
287
|
+
maxFiles: input.maxFiles ?? defaultMaxFiles,
|
|
288
|
+
includeUndocumented: input.includeUndocumented ?? defaultIncludeUndocumented,
|
|
289
|
+
});
|
|
290
|
+
},
|
|
291
|
+
});
|
|
292
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* findDeadCode Tool
|
|
3
|
+
*
|
|
4
|
+
* Find potentially unused functions, classes, and variables in Go code.
|
|
5
|
+
* Uses static analysis to identify code that may be dead.
|
|
6
|
+
*/
|
|
7
|
+
import type { Tool } from "@compilr-dev/agents";
|
|
8
|
+
/**
|
|
9
|
+
* Input for findDeadCode tool
|
|
10
|
+
*/
|
|
11
|
+
export interface FindDeadCodeInput {
|
|
12
|
+
/** Directory to analyze */
|
|
13
|
+
path: string;
|
|
14
|
+
/** Include test files in analysis (default: false) */
|
|
15
|
+
includeTests?: boolean;
|
|
16
|
+
/** Check for unused functions (default: true) */
|
|
17
|
+
checkFunctions?: boolean;
|
|
18
|
+
/** Check for unused classes (default: true) */
|
|
19
|
+
checkClasses?: boolean;
|
|
20
|
+
/** Check for unused variables (default: false) */
|
|
21
|
+
checkVariables?: boolean;
|
|
22
|
+
/** Maximum files to analyze (default: 100) */
|
|
23
|
+
maxFiles?: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Dead code item
|
|
27
|
+
*/
|
|
28
|
+
export interface DeadCodeItem {
|
|
29
|
+
name: string;
|
|
30
|
+
path: string;
|
|
31
|
+
line: number;
|
|
32
|
+
kind: "function" | "class" | "variable" | "method";
|
|
33
|
+
confidence: "high" | "medium" | "low";
|
|
34
|
+
reason: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Result of findDeadCode
|
|
38
|
+
*/
|
|
39
|
+
export interface FindDeadCodeResult {
|
|
40
|
+
path: string;
|
|
41
|
+
deadCode: DeadCodeItem[];
|
|
42
|
+
stats: {
|
|
43
|
+
filesAnalyzed: number;
|
|
44
|
+
totalFunctions: number;
|
|
45
|
+
unusedFunctions: number;
|
|
46
|
+
totalClasses: number;
|
|
47
|
+
unusedClasses: number;
|
|
48
|
+
totalVariables: number;
|
|
49
|
+
unusedVariables: number;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* findDeadCode tool
|
|
54
|
+
*/
|
|
55
|
+
export declare const findDeadCodeTool: Tool<FindDeadCodeInput>;
|
|
56
|
+
/**
|
|
57
|
+
* Factory function to create a customized findDeadCode tool
|
|
58
|
+
*/
|
|
59
|
+
export declare function createFindDeadCodeTool(options?: {
|
|
60
|
+
defaultMaxFiles?: number;
|
|
61
|
+
}): Tool<FindDeadCodeInput>;
|
|
62
|
+
//# sourceMappingURL=find-dead-code.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find-dead-code.d.ts","sourceRoot":"","sources":["../../src/tools/find-dead-code.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,OAAO,KAAK,EAAE,IAAI,EAAuB,MAAM,qBAAqB,CAAC;AAIrE;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,iDAAiD;IACjD,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,+CAA+C;IAC/C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,kDAAkD;IAClD,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,CAAC;IACnD,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACtC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,KAAK,EAAE;QACL,aAAa,EAAE,MAAM,CAAC;QACtB,cAAc,EAAE,MAAM,CAAC;QACvB,eAAe,EAAE,MAAM,CAAC;QACxB,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;QACtB,cAAc,EAAE,MAAM,CAAC;QACvB,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC;CACH;AAuED;;GAEG;AACH,eAAO,MAAM,gBAAgB,yBAK3B,CAAC;AA4ZH;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,GAAG,IAAI,CAAC,iBAAiB,CAAC,CAa1B"}
|