@mseep/ai-tech-app-agent 1.0.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 (67) hide show
  1. package/.env +24 -0
  2. package/.env.example +24 -0
  3. package/Jenkinsfile +210 -0
  4. package/MCP-SERVER-GUIDE.md +405 -0
  5. package/README.MD +450 -0
  6. package/dist/config/app.config.d.ts +65 -0
  7. package/dist/config/app.config.d.ts.map +1 -0
  8. package/dist/config/app.config.js +94 -0
  9. package/dist/config/app.config.js.map +1 -0
  10. package/dist/config/llm.config.d.ts +63 -0
  11. package/dist/config/llm.config.d.ts.map +1 -0
  12. package/dist/config/llm.config.js +158 -0
  13. package/dist/config/llm.config.js.map +1 -0
  14. package/dist/config/mcp.config.d.ts +175 -0
  15. package/dist/config/mcp.config.d.ts.map +1 -0
  16. package/dist/config/mcp.config.js +215 -0
  17. package/dist/config/mcp.config.js.map +1 -0
  18. package/dist/index.d.ts +3 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +175 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/llm/llamaClient.d.ts +14 -0
  23. package/dist/llm/llamaClient.d.ts.map +1 -0
  24. package/dist/llm/llamaClient.js +136 -0
  25. package/dist/llm/llamaClient.js.map +1 -0
  26. package/dist/mcp/mcpClient.d.ts +132 -0
  27. package/dist/mcp/mcpClient.d.ts.map +1 -0
  28. package/dist/mcp/mcpClient.js +784 -0
  29. package/dist/mcp/mcpClient.js.map +1 -0
  30. package/dist/models/testSpec.d.ts +78 -0
  31. package/dist/models/testSpec.d.ts.map +1 -0
  32. package/dist/models/testSpec.js +3 -0
  33. package/dist/models/testSpec.js.map +1 -0
  34. package/dist/orchestrator/aiTestRunner.d.ts +18 -0
  35. package/dist/orchestrator/aiTestRunner.d.ts.map +1 -0
  36. package/dist/orchestrator/aiTestRunner.js +247 -0
  37. package/dist/orchestrator/aiTestRunner.js.map +1 -0
  38. package/dist/utils/logger.d.ts +4 -0
  39. package/dist/utils/logger.d.ts.map +1 -0
  40. package/dist/utils/logger.js +49 -0
  41. package/dist/utils/logger.js.map +1 -0
  42. package/dist/utils/promptBuilder.d.ts +62 -0
  43. package/dist/utils/promptBuilder.d.ts.map +1 -0
  44. package/dist/utils/promptBuilder.js +333 -0
  45. package/dist/utils/promptBuilder.js.map +1 -0
  46. package/knowledge/app-knowledge.txt +100 -0
  47. package/logs/combined.log +486 -0
  48. package/logs/error.log +50 -0
  49. package/package.json +62 -0
  50. package/reports/screenshots/screenshot_1764535110518.png +0 -0
  51. package/reports/test-report.json +106 -0
  52. package/scripts/check-mcp-server.sh +100 -0
  53. package/scripts/extract-pom-knowledge.js +222 -0
  54. package/scripts/pre-test-setup.js +262 -0
  55. package/scripts/start-mcp-server.sh +76 -0
  56. package/src/config/app.config.ts +175 -0
  57. package/src/config/llm.config.ts +220 -0
  58. package/src/config/mcp.config.ts +291 -0
  59. package/src/index.ts +161 -0
  60. package/src/llm/llamaClient.ts +159 -0
  61. package/src/mcp/mcpClient.ts +878 -0
  62. package/src/models/testSpec.ts +85 -0
  63. package/src/orchestrator/aiTestRunner.ts +286 -0
  64. package/src/utils/logger.ts +59 -0
  65. package/src/utils/promptBuilder.ts +384 -0
  66. package/tests/nlp-specs/login-flow.yaml +31 -0
  67. package/tsconfig.json +31 -0
package/dist/index.js ADDED
@@ -0,0 +1,175 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ var __importDefault = (this && this.__importDefault) || function (mod) {
37
+ return (mod && mod.__esModule) ? mod : { "default": mod };
38
+ };
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ const commander_1 = require("commander");
41
+ const path_1 = __importDefault(require("path"));
42
+ const fs_1 = __importDefault(require("fs"));
43
+ const dotenv_1 = __importDefault(require("dotenv"));
44
+ const logger_1 = __importDefault(require("./utils/logger"));
45
+ const aiTestRunner_1 = __importDefault(require("./orchestrator/aiTestRunner"));
46
+ dotenv_1.default.config();
47
+ const program = new commander_1.Command();
48
+ program
49
+ .name('ai-test-runner')
50
+ .description('AI-powered mobile test automation using MCP and LLM')
51
+ .version('1.0.0');
52
+ program
53
+ .command('run')
54
+ .description('Run AI-powered test specs')
55
+ .argument('<spec-path>', 'Path to test spec file or directory')
56
+ .option('-s, --session-id <id>', 'Existing Appium session ID')
57
+ .option('-k, --knowledge <path>', 'Path to app knowledge file')
58
+ .option('-o, --output <path>', 'Output path for test report', './reports/test-report.json')
59
+ .action(async (specPath, options) => {
60
+ try {
61
+ logger_1.default.info('Starting AI Test Runner...');
62
+ logger_1.default.info(`Spec path: ${specPath}`);
63
+ const runner = new aiTestRunner_1.default();
64
+ // Load app knowledge if provided
65
+ if (options.knowledge) {
66
+ await runner.loadAppKnowledge(options.knowledge);
67
+ }
68
+ const results = [];
69
+ // Check if spec path is a file or directory
70
+ const stats = fs_1.default.statSync(specPath);
71
+ if (stats.isDirectory()) {
72
+ // Run all specs in directory
73
+ const files = fs_1.default.readdirSync(specPath)
74
+ .filter(f => f.endsWith('.yaml') || f.endsWith('.yml') || f.endsWith('.json'))
75
+ .map(f => path_1.default.join(specPath, f));
76
+ logger_1.default.info(`Found ${files.length} test spec(s) in directory`);
77
+ for (const file of files) {
78
+ const result = await runner.runTestSpec(file, options.sessionId);
79
+ results.push(result);
80
+ }
81
+ }
82
+ else {
83
+ // Run single spec
84
+ const result = await runner.runTestSpec(specPath, options.sessionId);
85
+ results.push(result);
86
+ }
87
+ // Generate report
88
+ await runner.generateReport(results, options.output);
89
+ // Print summary
90
+ console.log('\n' + '='.repeat(60));
91
+ console.log('TEST EXECUTION SUMMARY');
92
+ console.log('='.repeat(60));
93
+ const passed = results.filter(r => r.status === 'passed').length;
94
+ const failed = results.filter(r => r.status === 'failed').length;
95
+ const total = results.length;
96
+ console.log(`Total Tests: ${total}`);
97
+ console.log(`Passed: ${passed}`);
98
+ console.log(`Failed: ${failed}`);
99
+ console.log(`Success Rate: ${((passed / total) * 100).toFixed(2)}%`);
100
+ console.log('='.repeat(60) + '\n');
101
+ // Exit with appropriate code
102
+ process.exit(failed > 0 ? 1 : 0);
103
+ }
104
+ catch (error) {
105
+ logger_1.default.error(`Test execution failed: ${error.message}`);
106
+ console.error(`Error: ${error.message}`);
107
+ process.exit(1);
108
+ }
109
+ });
110
+ program
111
+ .command('validate')
112
+ .description('Validate test spec file(s)')
113
+ .argument('<spec-path>', 'Path to test spec file or directory')
114
+ .action((specPath) => {
115
+ try {
116
+ const stats = fs_1.default.statSync(specPath);
117
+ const files = stats.isDirectory()
118
+ ? fs_1.default.readdirSync(specPath)
119
+ .filter(f => f.endsWith('.yaml') || f.endsWith('.yml') || f.endsWith('.json'))
120
+ .map(f => path_1.default.join(specPath, f))
121
+ : [specPath];
122
+ let valid = 0;
123
+ let invalid = 0;
124
+ files.forEach(file => {
125
+ try {
126
+ const content = fs_1.default.readFileSync(file, 'utf-8');
127
+ const ext = path_1.default.extname(file).toLowerCase();
128
+ if (ext === '.json') {
129
+ JSON.parse(content);
130
+ }
131
+ else {
132
+ // For YAML, we'd need to validate structure
133
+ // This is a basic check
134
+ }
135
+ console.log(`✓ ${file} - Valid`);
136
+ valid++;
137
+ }
138
+ catch (error) {
139
+ console.error(`✗ ${file} - Invalid: ${error.message}`);
140
+ invalid++;
141
+ }
142
+ });
143
+ console.log(`\nValidation complete: ${valid} valid, ${invalid} invalid`);
144
+ process.exit(invalid > 0 ? 1 : 0);
145
+ }
146
+ catch (error) {
147
+ console.error(`Validation failed: ${error.message}`);
148
+ process.exit(1);
149
+ }
150
+ });
151
+ program
152
+ .command('health')
153
+ .description('Check health of LLM and MCP components')
154
+ .action(async () => {
155
+ try {
156
+ const runner = new aiTestRunner_1.default();
157
+ console.log('Checking LLM health...');
158
+ const llamaClient = new (await Promise.resolve().then(() => __importStar(require('./llm/llamaClient')))).default();
159
+ const llmHealthy = await llamaClient.healthCheck();
160
+ if (llmHealthy) {
161
+ console.log('✓ LLM is healthy');
162
+ }
163
+ else {
164
+ console.error('✗ LLM is not available');
165
+ }
166
+ // Add MCP health check here if needed
167
+ process.exit(llmHealthy ? 0 : 1);
168
+ }
169
+ catch (error) {
170
+ console.error(`Health check failed: ${error.message}`);
171
+ process.exit(1);
172
+ }
173
+ });
174
+ program.parse(process.argv);
175
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { ActionPlan } from '../models/testSpec';
2
+ export declare class LlamaClient {
3
+ private client;
4
+ private model;
5
+ private temperature;
6
+ private maxTokens;
7
+ constructor();
8
+ generateActionPlan(stepText: string, uiContext: string, appKnowledge?: string): Promise<ActionPlan>;
9
+ private buildPrompt;
10
+ private parseActionPlan;
11
+ healthCheck(): Promise<boolean>;
12
+ }
13
+ export default LlamaClient;
14
+ //# sourceMappingURL=llamaClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llamaClient.d.ts","sourceRoot":"","sources":["../../src/llm/llamaClient.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAIhD,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,SAAS,CAAS;;IAmBpB,kBAAkB,CACtB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,UAAU,CAAC;IA+BtB,OAAO,CAAC,WAAW;IA6CnB,OAAO,CAAC,eAAe;IA4BjB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;CAkBtC;AAED,eAAe,WAAW,CAAC"}
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.LlamaClient = void 0;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const dotenv_1 = __importDefault(require("dotenv"));
9
+ const logger_1 = __importDefault(require("../utils/logger"));
10
+ dotenv_1.default.config();
11
+ class LlamaClient {
12
+ constructor() {
13
+ const baseURL = process.env.OLLAMA_BASE_URL || 'http://localhost:11434';
14
+ this.model = process.env.LLM_MODEL || 'llama3.2:3b';
15
+ this.temperature = parseFloat(process.env.LLM_TEMPERATURE || '0.1');
16
+ this.maxTokens = parseInt(process.env.LLM_MAX_TOKENS || '2000');
17
+ this.client = axios_1.default.create({
18
+ baseURL,
19
+ timeout: 60000,
20
+ headers: {
21
+ 'Content-Type': 'application/json',
22
+ },
23
+ });
24
+ logger_1.default.info(`LlamaClient initialized with model: ${this.model}`);
25
+ }
26
+ async generateActionPlan(stepText, uiContext, appKnowledge) {
27
+ const prompt = this.buildPrompt(stepText, uiContext, appKnowledge);
28
+ try {
29
+ logger_1.default.debug(`Sending prompt to LLM for step: "${stepText}"`);
30
+ const response = await this.client.post('/api/generate', {
31
+ model: this.model,
32
+ prompt,
33
+ stream: false,
34
+ options: {
35
+ temperature: this.temperature,
36
+ num_predict: this.maxTokens,
37
+ },
38
+ format: 'json', // Request JSON output
39
+ });
40
+ const rawResponse = response.data.response;
41
+ logger_1.default.debug(`LLM raw response: ${rawResponse}`);
42
+ // Parse the JSON response
43
+ const actionPlan = this.parseActionPlan(rawResponse);
44
+ logger_1.default.info(`Generated ${actionPlan.actions.length} actions for step`);
45
+ return actionPlan;
46
+ }
47
+ catch (error) {
48
+ logger_1.default.error(`Error generating action plan: ${error.message}`);
49
+ throw new Error(`LLM generation failed: ${error.message}`);
50
+ }
51
+ }
52
+ buildPrompt(stepText, uiContext, appKnowledge) {
53
+ return `You are an expert mobile test automation agent. Your task is to generate precise Appium actions to accomplish a test step.
54
+
55
+ **App Context:**
56
+ ${appKnowledge || 'A mobile application with standard Android/iOS UI patterns.'}
57
+
58
+ **Current UI State:**
59
+ ${uiContext}
60
+
61
+ **Test Step to Execute:**
62
+ "${stepText}"
63
+
64
+ **Instructions:**
65
+ 1. Analyze the current UI state carefully
66
+ 2. Identify the most reliable element selectors (prefer text, accessibility-id, or resource-id over XPath)
67
+ 3. Generate a sequence of actions to accomplish the test step
68
+ 4. Minimize screenshot-based coordinate selection - use it only as last resort
69
+ 5. Ensure actions are reliable across different device sizes
70
+
71
+ **Output Format (JSON only, no markdown):**
72
+ {
73
+ "actions": [
74
+ {
75
+ "type": "tap|type|scroll|swipe|wait|assert",
76
+ "selector": {
77
+ "strategy": "text|id|accessibility-id|xpath|class",
78
+ "value": "selector_value",
79
+ "index": 0
80
+ },
81
+ "value": "text_to_type (only for type action)",
82
+ "direction": "up|down|left|right (only for scroll/swipe)",
83
+ "assertionType": "exists|visible|text|enabled (only for assert)",
84
+ "expectedValue": "expected_value (only for assert)"
85
+ }
86
+ ],
87
+ "reasoning": "Brief explanation of the action sequence"
88
+ }
89
+
90
+ Generate the JSON action plan now:`;
91
+ }
92
+ parseActionPlan(rawResponse) {
93
+ try {
94
+ // Remove any markdown code blocks if present
95
+ let cleanedResponse = rawResponse
96
+ .replace(/```json\n?/g, '')
97
+ .replace(/```\n?/g, '')
98
+ .trim();
99
+ const parsed = JSON.parse(cleanedResponse);
100
+ // Validate the structure
101
+ if (!parsed.actions || !Array.isArray(parsed.actions)) {
102
+ throw new Error('Invalid action plan structure: missing actions array');
103
+ }
104
+ return parsed;
105
+ }
106
+ catch (error) {
107
+ logger_1.default.error(`Failed to parse action plan: ${error.message}`);
108
+ logger_1.default.error(`Raw response: ${rawResponse}`);
109
+ // Return a fallback empty action plan
110
+ return {
111
+ actions: [],
112
+ reasoning: `Parsing failed: ${error.message}`,
113
+ };
114
+ }
115
+ }
116
+ async healthCheck() {
117
+ try {
118
+ const response = await this.client.get('/api/tags');
119
+ const models = response.data.models || [];
120
+ const modelExists = models.some((m) => m.name === this.model);
121
+ if (!modelExists) {
122
+ logger_1.default.warn(`Model ${this.model} not found in Ollama. Available models: ${models.map((m) => m.name).join(', ')}`);
123
+ return false;
124
+ }
125
+ logger_1.default.info('LLM health check passed');
126
+ return true;
127
+ }
128
+ catch (error) {
129
+ logger_1.default.error(`LLM health check failed: ${error.message}`);
130
+ return false;
131
+ }
132
+ }
133
+ }
134
+ exports.LlamaClient = LlamaClient;
135
+ exports.default = LlamaClient;
136
+ //# sourceMappingURL=llamaClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llamaClient.js","sourceRoot":"","sources":["../../src/llm/llamaClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,132 @@
1
+ import { Action, UIContext } from '../models/testSpec';
2
+ export declare class MCPClient {
3
+ private mcpProcess;
4
+ private sessionId;
5
+ private appiumServerUrl;
6
+ private appiumClient;
7
+ private xmlParser;
8
+ private platform;
9
+ constructor(sessionId?: string);
10
+ /**
11
+ * Initialize MCP server and establish connection
12
+ */
13
+ initialize(): Promise<void>;
14
+ /**
15
+ * Start MCP server process (if using stdio)
16
+ */
17
+ private startMCPProcess;
18
+ /**
19
+ * Verify Appium server connection
20
+ */
21
+ private verifyAppiumConnection;
22
+ /**
23
+ * Create a new Appium session with device capabilities
24
+ */
25
+ private createSession;
26
+ /**
27
+ * Detect platform from capabilities
28
+ */
29
+ private detectPlatformFromCapabilities;
30
+ /**
31
+ * Set the active Appium session ID
32
+ */
33
+ setSessionId(sessionId: string, platform?: 'android' | 'ios'): void;
34
+ /**
35
+ * Get current UI context (page source + parsed elements)
36
+ */
37
+ getUIContext(): Promise<UIContext>;
38
+ /**
39
+ * Get page source (XML hierarchy)
40
+ */
41
+ private getPageSource;
42
+ /**
43
+ * Get current activity (Android) or current view (iOS)
44
+ */
45
+ private getCurrentActivity;
46
+ /**
47
+ * Get current package (Android only)
48
+ */
49
+ private getCurrentPackage;
50
+ /**
51
+ * Detect platform from session capabilities
52
+ */
53
+ private detectPlatform;
54
+ /**
55
+ * Detect platform from page source XML
56
+ */
57
+ private detectPlatformFromPageSource;
58
+ /**
59
+ * Parse UI elements from XML page source
60
+ */
61
+ private parseUIElements;
62
+ /**
63
+ * Recursively extract elements from parsed XML
64
+ */
65
+ private extractElementsRecursive;
66
+ /**
67
+ * Filter elements based on configuration
68
+ */
69
+ private filterElements;
70
+ /**
71
+ * Execute an action
72
+ */
73
+ executeAction(action: Action): Promise<boolean>;
74
+ /**
75
+ * Tap/click on an element
76
+ */
77
+ private tap;
78
+ /**
79
+ * Type text into an element
80
+ */
81
+ private type;
82
+ /**
83
+ * Scroll the screen
84
+ */
85
+ private scroll;
86
+ /**
87
+ * Swipe gesture
88
+ */
89
+ private swipe;
90
+ /**
91
+ * Perform swipe gesture using touch actions
92
+ */
93
+ private performSwipeGesture;
94
+ /**
95
+ * Wait for duration or element
96
+ */
97
+ private wait;
98
+ /**
99
+ * Assert element state
100
+ */
101
+ private assert;
102
+ /**
103
+ * Launch an app or return to home screen
104
+ */
105
+ private launch;
106
+ /**
107
+ * Take screenshot
108
+ */
109
+ private screenshot;
110
+ /**
111
+ * Find element using selector
112
+ */
113
+ private findElement;
114
+ /**
115
+ * Get screen size
116
+ */
117
+ private getScreenSize;
118
+ /**
119
+ * Delay helper
120
+ */
121
+ private delay;
122
+ /**
123
+ * Stop the current Appium session
124
+ */
125
+ stopSession(): Promise<void>;
126
+ /**
127
+ * Cleanup and shutdown
128
+ */
129
+ cleanup(): Promise<void>;
130
+ }
131
+ export default MCPClient;
132
+ //# sourceMappingURL=mcpClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcpClient.d.ts","sourceRoot":"","sources":["../../src/mcp/mcpClient.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAuB,MAAM,oBAAoB,CAAC;AAE5E,qBAAa,SAAS;IACpB,OAAO,CAAC,UAAU,CAA6B;IAC/C,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,QAAQ,CAAkC;gBAEtC,SAAS,CAAC,EAAE,MAAM;IAwB9B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAwBjC;;OAEG;YACW,eAAe;IAkC7B;;OAEG;YACW,sBAAsB;IAUpC;;OAEG;YACW,aAAa;IAmF3B;;OAEG;IACH,OAAO,CAAC,8BAA8B;IAKtC;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,SAAS,GAAG,KAAK,GAAG,IAAI;IAMnE;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,SAAS,CAAC;IAuCxC;;OAEG;YACW,aAAa;IAU3B;;OAEG;YACW,kBAAkB;IAoBhC;;OAEG;YACW,iBAAiB;IAY/B;;OAEG;YACW,cAAc;IAmB5B;;OAEG;IACH,OAAO,CAAC,4BAA4B;IAOpC;;OAEG;IACH,OAAO,CAAC,eAAe;IAgBvB;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAwChC;;OAEG;IACH,OAAO,CAAC,cAAc;IAuBtB;;OAEG;IACG,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAoCrD;;OAEG;YACW,GAAG;IA2BjB;;OAEG;YACW,IAAI;IAiClB;;OAEG;YACW,MAAM;IAsBpB;;OAEG;YACW,KAAK;IAmDnB;;OAEG;YACW,mBAAmB;IAmBjC;;OAEG;YACW,IAAI;IAQlB;;OAEG;YACW,MAAM;IAwCpB;;OAEG;YACW,MAAM;IAoCpB;;OAEG;YACW,UAAU;IA2BxB;;OAEG;YACW,WAAW;IAqDzB;;OAEG;YACW,aAAa;IAc3B;;OAEG;IACH,OAAO,CAAC,KAAK;IAIb;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAelC;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAU/B;AAED,eAAe,SAAS,CAAC"}