mindheal 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 (255) hide show
  1. package/.env.example +48 -0
  2. package/CHANGELOG.md +27 -0
  3. package/LICENSE +21 -0
  4. package/README.md +481 -0
  5. package/dist/cjs/ai/ai-provider.js +46 -0
  6. package/dist/cjs/ai/ai-provider.js.map +1 -0
  7. package/dist/cjs/ai/anthropic-provider.js +106 -0
  8. package/dist/cjs/ai/anthropic-provider.js.map +1 -0
  9. package/dist/cjs/ai/azure-openai-provider.js +130 -0
  10. package/dist/cjs/ai/azure-openai-provider.js.map +1 -0
  11. package/dist/cjs/ai/bedrock-provider.js +183 -0
  12. package/dist/cjs/ai/bedrock-provider.js.map +1 -0
  13. package/dist/cjs/ai/deepseek-provider.js +118 -0
  14. package/dist/cjs/ai/deepseek-provider.js.map +1 -0
  15. package/dist/cjs/ai/gemini-provider.js +129 -0
  16. package/dist/cjs/ai/gemini-provider.js.map +1 -0
  17. package/dist/cjs/ai/groq-provider.js +118 -0
  18. package/dist/cjs/ai/groq-provider.js.map +1 -0
  19. package/dist/cjs/ai/meta-provider.js +118 -0
  20. package/dist/cjs/ai/meta-provider.js.map +1 -0
  21. package/dist/cjs/ai/ollama-provider.js +127 -0
  22. package/dist/cjs/ai/ollama-provider.js.map +1 -0
  23. package/dist/cjs/ai/openai-provider.js +117 -0
  24. package/dist/cjs/ai/openai-provider.js.map +1 -0
  25. package/dist/cjs/ai/perplexity-provider.js +118 -0
  26. package/dist/cjs/ai/perplexity-provider.js.map +1 -0
  27. package/dist/cjs/ai/prompt-templates.js +174 -0
  28. package/dist/cjs/ai/prompt-templates.js.map +1 -0
  29. package/dist/cjs/ai/qwen-provider.js +118 -0
  30. package/dist/cjs/ai/qwen-provider.js.map +1 -0
  31. package/dist/cjs/analytics/healing-analytics.js +263 -0
  32. package/dist/cjs/analytics/healing-analytics.js.map +1 -0
  33. package/dist/cjs/cli/init.js +517 -0
  34. package/dist/cjs/cli/init.js.map +1 -0
  35. package/dist/cjs/config/config-loader.js +135 -0
  36. package/dist/cjs/config/config-loader.js.map +1 -0
  37. package/dist/cjs/config/defaults.js +109 -0
  38. package/dist/cjs/config/defaults.js.map +1 -0
  39. package/dist/cjs/core/dom-snapshot.js +280 -0
  40. package/dist/cjs/core/dom-snapshot.js.map +1 -0
  41. package/dist/cjs/core/enterprise-strategy.js +702 -0
  42. package/dist/cjs/core/enterprise-strategy.js.map +1 -0
  43. package/dist/cjs/core/healer.js +283 -0
  44. package/dist/cjs/core/healer.js.map +1 -0
  45. package/dist/cjs/core/interceptor.js +945 -0
  46. package/dist/cjs/core/interceptor.js.map +1 -0
  47. package/dist/cjs/core/locator-analyzer.js +172 -0
  48. package/dist/cjs/core/locator-analyzer.js.map +1 -0
  49. package/dist/cjs/core/locator-strategies.js +891 -0
  50. package/dist/cjs/core/locator-strategies.js.map +1 -0
  51. package/dist/cjs/core/self-heal-cache.js +178 -0
  52. package/dist/cjs/core/self-heal-cache.js.map +1 -0
  53. package/dist/cjs/core/smart-retry.js +248 -0
  54. package/dist/cjs/core/smart-retry.js.map +1 -0
  55. package/dist/cjs/core/visual-verification.js +262 -0
  56. package/dist/cjs/core/visual-verification.js.map +1 -0
  57. package/dist/cjs/git/code-modifier.js +184 -0
  58. package/dist/cjs/git/code-modifier.js.map +1 -0
  59. package/dist/cjs/git/git-operations.js +145 -0
  60. package/dist/cjs/git/git-operations.js.map +1 -0
  61. package/dist/cjs/git/pr-creator.js +190 -0
  62. package/dist/cjs/git/pr-creator.js.map +1 -0
  63. package/dist/cjs/index.js +97 -0
  64. package/dist/cjs/index.js.map +1 -0
  65. package/dist/cjs/rag/context-retriever.js +289 -0
  66. package/dist/cjs/rag/context-retriever.js.map +1 -0
  67. package/dist/cjs/rag/embeddings.js +82 -0
  68. package/dist/cjs/rag/embeddings.js.map +1 -0
  69. package/dist/cjs/rag/knowledge-store.js +159 -0
  70. package/dist/cjs/rag/knowledge-store.js.map +1 -0
  71. package/dist/cjs/reporters/heal-report.js +279 -0
  72. package/dist/cjs/reporters/heal-report.js.map +1 -0
  73. package/dist/cjs/reporters/heal-reporter.js +294 -0
  74. package/dist/cjs/reporters/heal-reporter.js.map +1 -0
  75. package/dist/cjs/server/review-server.js +166 -0
  76. package/dist/cjs/server/review-server.js.map +1 -0
  77. package/dist/cjs/server/routes.js +92 -0
  78. package/dist/cjs/server/routes.js.map +1 -0
  79. package/dist/cjs/utils/environment.js +57 -0
  80. package/dist/cjs/utils/environment.js.map +1 -0
  81. package/dist/cjs/utils/file-lock.js +136 -0
  82. package/dist/cjs/utils/file-lock.js.map +1 -0
  83. package/dist/cjs/utils/file-utils.js +49 -0
  84. package/dist/cjs/utils/file-utils.js.map +1 -0
  85. package/dist/cjs/utils/logger.js +78 -0
  86. package/dist/cjs/utils/logger.js.map +1 -0
  87. package/dist/esm/ai/ai-provider.js +44 -0
  88. package/dist/esm/ai/ai-provider.js.map +1 -0
  89. package/dist/esm/ai/anthropic-provider.js +104 -0
  90. package/dist/esm/ai/anthropic-provider.js.map +1 -0
  91. package/dist/esm/ai/azure-openai-provider.js +128 -0
  92. package/dist/esm/ai/azure-openai-provider.js.map +1 -0
  93. package/dist/esm/ai/bedrock-provider.js +181 -0
  94. package/dist/esm/ai/bedrock-provider.js.map +1 -0
  95. package/dist/esm/ai/deepseek-provider.js +116 -0
  96. package/dist/esm/ai/deepseek-provider.js.map +1 -0
  97. package/dist/esm/ai/gemini-provider.js +127 -0
  98. package/dist/esm/ai/gemini-provider.js.map +1 -0
  99. package/dist/esm/ai/groq-provider.js +116 -0
  100. package/dist/esm/ai/groq-provider.js.map +1 -0
  101. package/dist/esm/ai/meta-provider.js +116 -0
  102. package/dist/esm/ai/meta-provider.js.map +1 -0
  103. package/dist/esm/ai/ollama-provider.js +125 -0
  104. package/dist/esm/ai/ollama-provider.js.map +1 -0
  105. package/dist/esm/ai/openai-provider.js +115 -0
  106. package/dist/esm/ai/openai-provider.js.map +1 -0
  107. package/dist/esm/ai/perplexity-provider.js +116 -0
  108. package/dist/esm/ai/perplexity-provider.js.map +1 -0
  109. package/dist/esm/ai/prompt-templates.js +171 -0
  110. package/dist/esm/ai/prompt-templates.js.map +1 -0
  111. package/dist/esm/ai/qwen-provider.js +116 -0
  112. package/dist/esm/ai/qwen-provider.js.map +1 -0
  113. package/dist/esm/analytics/healing-analytics.js +261 -0
  114. package/dist/esm/analytics/healing-analytics.js.map +1 -0
  115. package/dist/esm/cli/init.js +495 -0
  116. package/dist/esm/cli/init.js.map +1 -0
  117. package/dist/esm/config/config-loader.js +132 -0
  118. package/dist/esm/config/config-loader.js.map +1 -0
  119. package/dist/esm/config/defaults.js +107 -0
  120. package/dist/esm/config/defaults.js.map +1 -0
  121. package/dist/esm/core/dom-snapshot.js +278 -0
  122. package/dist/esm/core/dom-snapshot.js.map +1 -0
  123. package/dist/esm/core/enterprise-strategy.js +695 -0
  124. package/dist/esm/core/enterprise-strategy.js.map +1 -0
  125. package/dist/esm/core/healer.js +281 -0
  126. package/dist/esm/core/healer.js.map +1 -0
  127. package/dist/esm/core/interceptor.js +940 -0
  128. package/dist/esm/core/interceptor.js.map +1 -0
  129. package/dist/esm/core/locator-analyzer.js +169 -0
  130. package/dist/esm/core/locator-analyzer.js.map +1 -0
  131. package/dist/esm/core/locator-strategies.js +882 -0
  132. package/dist/esm/core/locator-strategies.js.map +1 -0
  133. package/dist/esm/core/self-heal-cache.js +176 -0
  134. package/dist/esm/core/self-heal-cache.js.map +1 -0
  135. package/dist/esm/core/smart-retry.js +246 -0
  136. package/dist/esm/core/smart-retry.js.map +1 -0
  137. package/dist/esm/core/visual-verification.js +260 -0
  138. package/dist/esm/core/visual-verification.js.map +1 -0
  139. package/dist/esm/git/code-modifier.js +182 -0
  140. package/dist/esm/git/code-modifier.js.map +1 -0
  141. package/dist/esm/git/git-operations.js +143 -0
  142. package/dist/esm/git/git-operations.js.map +1 -0
  143. package/dist/esm/git/pr-creator.js +188 -0
  144. package/dist/esm/git/pr-creator.js.map +1 -0
  145. package/dist/esm/index.js +37 -0
  146. package/dist/esm/index.js.map +1 -0
  147. package/dist/esm/rag/context-retriever.js +287 -0
  148. package/dist/esm/rag/context-retriever.js.map +1 -0
  149. package/dist/esm/rag/embeddings.js +77 -0
  150. package/dist/esm/rag/embeddings.js.map +1 -0
  151. package/dist/esm/rag/knowledge-store.js +157 -0
  152. package/dist/esm/rag/knowledge-store.js.map +1 -0
  153. package/dist/esm/reporters/heal-report.js +277 -0
  154. package/dist/esm/reporters/heal-report.js.map +1 -0
  155. package/dist/esm/reporters/heal-reporter.js +290 -0
  156. package/dist/esm/reporters/heal-reporter.js.map +1 -0
  157. package/dist/esm/server/review-server.js +164 -0
  158. package/dist/esm/server/review-server.js.map +1 -0
  159. package/dist/esm/server/routes.js +90 -0
  160. package/dist/esm/server/routes.js.map +1 -0
  161. package/dist/esm/utils/environment.js +53 -0
  162. package/dist/esm/utils/environment.js.map +1 -0
  163. package/dist/esm/utils/file-lock.js +134 -0
  164. package/dist/esm/utils/file-lock.js.map +1 -0
  165. package/dist/esm/utils/file-utils.js +43 -0
  166. package/dist/esm/utils/file-utils.js.map +1 -0
  167. package/dist/esm/utils/logger.js +75 -0
  168. package/dist/esm/utils/logger.js.map +1 -0
  169. package/dist/types/ai/ai-provider.d.ts +4 -0
  170. package/dist/types/ai/ai-provider.d.ts.map +1 -0
  171. package/dist/types/ai/anthropic-provider.d.ts +11 -0
  172. package/dist/types/ai/anthropic-provider.d.ts.map +1 -0
  173. package/dist/types/ai/azure-openai-provider.d.ts +13 -0
  174. package/dist/types/ai/azure-openai-provider.d.ts.map +1 -0
  175. package/dist/types/ai/bedrock-provider.d.ts +14 -0
  176. package/dist/types/ai/bedrock-provider.d.ts.map +1 -0
  177. package/dist/types/ai/deepseek-provider.d.ts +12 -0
  178. package/dist/types/ai/deepseek-provider.d.ts.map +1 -0
  179. package/dist/types/ai/gemini-provider.d.ts +12 -0
  180. package/dist/types/ai/gemini-provider.d.ts.map +1 -0
  181. package/dist/types/ai/groq-provider.d.ts +12 -0
  182. package/dist/types/ai/groq-provider.d.ts.map +1 -0
  183. package/dist/types/ai/meta-provider.d.ts +12 -0
  184. package/dist/types/ai/meta-provider.d.ts.map +1 -0
  185. package/dist/types/ai/ollama-provider.d.ts +10 -0
  186. package/dist/types/ai/ollama-provider.d.ts.map +1 -0
  187. package/dist/types/ai/openai-provider.d.ts +11 -0
  188. package/dist/types/ai/openai-provider.d.ts.map +1 -0
  189. package/dist/types/ai/perplexity-provider.d.ts +12 -0
  190. package/dist/types/ai/perplexity-provider.d.ts.map +1 -0
  191. package/dist/types/ai/prompt-templates.d.ts +11 -0
  192. package/dist/types/ai/prompt-templates.d.ts.map +1 -0
  193. package/dist/types/ai/qwen-provider.d.ts +12 -0
  194. package/dist/types/ai/qwen-provider.d.ts.map +1 -0
  195. package/dist/types/analytics/healing-analytics.d.ts +36 -0
  196. package/dist/types/analytics/healing-analytics.d.ts.map +1 -0
  197. package/dist/types/cli/init.d.ts +15 -0
  198. package/dist/types/cli/init.d.ts.map +1 -0
  199. package/dist/types/config/config-loader.d.ts +4 -0
  200. package/dist/types/config/config-loader.d.ts.map +1 -0
  201. package/dist/types/config/defaults.d.ts +3 -0
  202. package/dist/types/config/defaults.d.ts.map +1 -0
  203. package/dist/types/core/dom-snapshot.d.ts +12 -0
  204. package/dist/types/core/dom-snapshot.d.ts.map +1 -0
  205. package/dist/types/core/enterprise-strategy.d.ts +56 -0
  206. package/dist/types/core/enterprise-strategy.d.ts.map +1 -0
  207. package/dist/types/core/healer.d.ts +52 -0
  208. package/dist/types/core/healer.d.ts.map +1 -0
  209. package/dist/types/core/interceptor.d.ts +64 -0
  210. package/dist/types/core/interceptor.d.ts.map +1 -0
  211. package/dist/types/core/locator-analyzer.d.ts +31 -0
  212. package/dist/types/core/locator-analyzer.d.ts.map +1 -0
  213. package/dist/types/core/locator-strategies.d.ts +45 -0
  214. package/dist/types/core/locator-strategies.d.ts.map +1 -0
  215. package/dist/types/core/self-heal-cache.d.ts +51 -0
  216. package/dist/types/core/self-heal-cache.d.ts.map +1 -0
  217. package/dist/types/core/smart-retry.d.ts +64 -0
  218. package/dist/types/core/smart-retry.d.ts.map +1 -0
  219. package/dist/types/core/visual-verification.d.ts +46 -0
  220. package/dist/types/core/visual-verification.d.ts.map +1 -0
  221. package/dist/types/git/code-modifier.d.ts +51 -0
  222. package/dist/types/git/code-modifier.d.ts.map +1 -0
  223. package/dist/types/git/git-operations.d.ts +40 -0
  224. package/dist/types/git/git-operations.d.ts.map +1 -0
  225. package/dist/types/git/pr-creator.d.ts +27 -0
  226. package/dist/types/git/pr-creator.d.ts.map +1 -0
  227. package/dist/types/index.d.ts +40 -0
  228. package/dist/types/index.d.ts.map +1 -0
  229. package/dist/types/rag/context-retriever.d.ts +69 -0
  230. package/dist/types/rag/context-retriever.d.ts.map +1 -0
  231. package/dist/types/rag/embeddings.d.ts +32 -0
  232. package/dist/types/rag/embeddings.d.ts.map +1 -0
  233. package/dist/types/rag/index.d.ts +12 -0
  234. package/dist/types/rag/index.d.ts.map +1 -0
  235. package/dist/types/rag/knowledge-store.d.ts +38 -0
  236. package/dist/types/rag/knowledge-store.d.ts.map +1 -0
  237. package/dist/types/reporters/heal-report.d.ts +29 -0
  238. package/dist/types/reporters/heal-report.d.ts.map +1 -0
  239. package/dist/types/reporters/heal-reporter.d.ts +49 -0
  240. package/dist/types/reporters/heal-reporter.d.ts.map +1 -0
  241. package/dist/types/server/review-server.d.ts +20 -0
  242. package/dist/types/server/review-server.d.ts.map +1 -0
  243. package/dist/types/server/routes.d.ts +4 -0
  244. package/dist/types/server/routes.d.ts.map +1 -0
  245. package/dist/types/types/index.d.ts +433 -0
  246. package/dist/types/types/index.d.ts.map +1 -0
  247. package/dist/types/utils/environment.d.ts +10 -0
  248. package/dist/types/utils/environment.d.ts.map +1 -0
  249. package/dist/types/utils/file-lock.d.ts +37 -0
  250. package/dist/types/utils/file-lock.d.ts.map +1 -0
  251. package/dist/types/utils/file-utils.d.ts +7 -0
  252. package/dist/types/utils/file-utils.d.ts.map +1 -0
  253. package/dist/types/utils/logger.d.ts +9 -0
  254. package/dist/types/utils/logger.d.ts.map +1 -0
  255. package/package.json +106 -0
@@ -0,0 +1,263 @@
1
+ 'use strict';
2
+
3
+ var logger = require('../utils/logger.js');
4
+ var fileUtils = require('../utils/file-utils.js');
5
+
6
+ /**
7
+ * Healing Analytics & Metrics
8
+ *
9
+ * Tracks healing success rates, strategy effectiveness, per-locator healing
10
+ * frequency, confidence trends, and test stability scores over time.
11
+ * File-backed with auto-pruning and exportable JSON.
12
+ */
13
+ const ANALYTICS_VERSION = '1';
14
+ class HealingAnalytics {
15
+ constructor(config) {
16
+ this.dirty = false;
17
+ this.config = config;
18
+ this.snapshot = this.emptySnapshot();
19
+ }
20
+ // ─── Lifecycle ──────────────────────────────────────────────────────────
21
+ load() {
22
+ if (!this.config.enabled)
23
+ return;
24
+ try {
25
+ if (!fileUtils.fileExists(this.config.storePath)) {
26
+ this.snapshot = this.emptySnapshot();
27
+ return;
28
+ }
29
+ const data = fileUtils.readJsonFile(this.config.storePath);
30
+ if (!data || data.version !== ANALYTICS_VERSION) {
31
+ this.snapshot = this.emptySnapshot();
32
+ return;
33
+ }
34
+ this.snapshot = data;
35
+ this.prune();
36
+ logger.logger.debug(`[Analytics] Loaded ${this.snapshot.entries.length} entries`);
37
+ }
38
+ catch (err) {
39
+ const msg = err instanceof Error ? err.message : String(err);
40
+ logger.logger.warn(`[Analytics] Failed to load: ${msg}`);
41
+ this.snapshot = this.emptySnapshot();
42
+ }
43
+ }
44
+ save() {
45
+ if (!this.config.enabled || !this.dirty)
46
+ return;
47
+ try {
48
+ const pathModule = require('path');
49
+ fileUtils.ensureDirectory(pathModule.dirname(this.config.storePath));
50
+ this.snapshot.lastUpdated = Date.now();
51
+ fileUtils.writeJsonFile(this.config.storePath, this.snapshot);
52
+ this.dirty = false;
53
+ logger.logger.debug(`[Analytics] Saved ${this.snapshot.entries.length} entries`);
54
+ }
55
+ catch (err) {
56
+ const msg = err instanceof Error ? err.message : String(err);
57
+ logger.logger.warn(`[Analytics] Failed to save: ${msg}`);
58
+ }
59
+ }
60
+ // ─── Recording ──────────────────────────────────────────────────────────
61
+ recordEvent(event) {
62
+ if (!this.config.enabled)
63
+ return;
64
+ const entry = {
65
+ timestamp: event.timestamp,
66
+ testFile: event.testFile,
67
+ testTitle: event.testTitle,
68
+ pageUrl: event.pageUrl,
69
+ locatorExpression: event.originalLocator.playwrightExpression,
70
+ action: event.action,
71
+ strategy: event.strategy,
72
+ confidence: event.confidence,
73
+ duration: event.duration,
74
+ success: event.status === 'healed',
75
+ };
76
+ this.snapshot.entries.push(entry);
77
+ this.dirty = true;
78
+ // Update aggregates
79
+ if (this.config.trackStrategies && event.strategy) {
80
+ this.updateStrategyStats(event.strategy, entry);
81
+ }
82
+ if (this.config.trackLocators) {
83
+ this.updateLocatorStats(entry);
84
+ }
85
+ if (this.config.trackTestStability) {
86
+ this.updateTestStability(entry);
87
+ }
88
+ // Enforce max entries
89
+ if (this.snapshot.entries.length > this.config.maxEntries) {
90
+ this.snapshot.entries = this.snapshot.entries.slice(-this.config.maxEntries);
91
+ }
92
+ }
93
+ // ─── Strategy Stats ─────────────────────────────────────────────────────
94
+ updateStrategyStats(strategy, entry) {
95
+ const key = strategy;
96
+ const existing = this.snapshot.strategyStats[key];
97
+ if (!existing) {
98
+ this.snapshot.strategyStats[key] = {
99
+ name: strategy,
100
+ totalAttempts: 1,
101
+ successCount: entry.success ? 1 : 0,
102
+ failCount: entry.success ? 0 : 1,
103
+ avgConfidence: entry.confidence,
104
+ avgDuration: entry.duration,
105
+ successRate: entry.success ? 1 : 0,
106
+ };
107
+ return;
108
+ }
109
+ existing.totalAttempts++;
110
+ if (entry.success) {
111
+ existing.successCount++;
112
+ }
113
+ else {
114
+ existing.failCount++;
115
+ }
116
+ existing.successRate = existing.successCount / existing.totalAttempts;
117
+ existing.avgConfidence =
118
+ (existing.avgConfidence * (existing.totalAttempts - 1) + entry.confidence) /
119
+ existing.totalAttempts;
120
+ existing.avgDuration =
121
+ (existing.avgDuration * (existing.totalAttempts - 1) + entry.duration) /
122
+ existing.totalAttempts;
123
+ }
124
+ // ─── Locator Stats ──────────────────────────────────────────────────────
125
+ updateLocatorStats(entry) {
126
+ const key = entry.locatorExpression;
127
+ const existing = this.snapshot.locatorStats[key];
128
+ if (!existing) {
129
+ this.snapshot.locatorStats[key] = {
130
+ expression: entry.locatorExpression,
131
+ healCount: entry.success ? 1 : 0,
132
+ failCount: entry.success ? 0 : 1,
133
+ lastHealed: entry.timestamp,
134
+ strategies: entry.strategy ? [entry.strategy] : [],
135
+ pages: [entry.pageUrl],
136
+ };
137
+ return;
138
+ }
139
+ if (entry.success) {
140
+ existing.healCount++;
141
+ }
142
+ else {
143
+ existing.failCount++;
144
+ }
145
+ existing.lastHealed = entry.timestamp;
146
+ if (entry.strategy && !existing.strategies.includes(entry.strategy)) {
147
+ existing.strategies.push(entry.strategy);
148
+ }
149
+ if (!existing.pages.includes(entry.pageUrl)) {
150
+ existing.pages.push(entry.pageUrl);
151
+ }
152
+ }
153
+ // ─── Test Stability ─────────────────────────────────────────────────────
154
+ updateTestStability(entry) {
155
+ const key = `${entry.testFile}::${entry.testTitle}`;
156
+ const existing = this.snapshot.testStability[key];
157
+ if (!existing) {
158
+ this.snapshot.testStability[key] = {
159
+ testFile: entry.testFile,
160
+ testTitle: entry.testTitle,
161
+ totalRuns: 1,
162
+ healsNeeded: 1,
163
+ failedHeals: entry.success ? 0 : 1,
164
+ stabilityScore: entry.success ? 80 : 40,
165
+ lastRun: entry.timestamp,
166
+ trend: 'stable',
167
+ };
168
+ return;
169
+ }
170
+ existing.totalRuns++;
171
+ existing.healsNeeded++;
172
+ if (!entry.success) {
173
+ existing.failedHeals++;
174
+ }
175
+ existing.lastRun = entry.timestamp;
176
+ // Compute stability score (0-100)
177
+ // Score decreases with more healing needed and more failures
178
+ const healRatio = existing.healsNeeded / existing.totalRuns;
179
+ const failRatio = existing.failedHeals / existing.healsNeeded;
180
+ existing.stabilityScore = Math.round(Math.max(0, 100 - healRatio * 60 - failRatio * 40));
181
+ // Compute trend from recent entries
182
+ const recentEntries = this.snapshot.entries
183
+ .filter((e) => e.testFile === entry.testFile && e.testTitle === entry.testTitle)
184
+ .slice(-10);
185
+ if (recentEntries.length >= 3) {
186
+ const firstHalf = recentEntries.slice(0, Math.floor(recentEntries.length / 2));
187
+ const secondHalf = recentEntries.slice(Math.floor(recentEntries.length / 2));
188
+ const firstRate = firstHalf.filter((e) => e.success).length / firstHalf.length;
189
+ const secondRate = secondHalf.filter((e) => e.success).length / secondHalf.length;
190
+ if (secondRate > firstRate + 0.1) {
191
+ existing.trend = 'improving';
192
+ }
193
+ else if (secondRate < firstRate - 0.1) {
194
+ existing.trend = 'degrading';
195
+ }
196
+ else {
197
+ existing.trend = 'stable';
198
+ }
199
+ }
200
+ }
201
+ // ─── Queries ────────────────────────────────────────────────────────────
202
+ getStrategyStats() {
203
+ return Object.values(this.snapshot.strategyStats)
204
+ .sort((a, b) => b.successRate - a.successRate);
205
+ }
206
+ getMostHealedLocators(limit = 10) {
207
+ return Object.values(this.snapshot.locatorStats)
208
+ .sort((a, b) => (b.healCount + b.failCount) - (a.healCount + a.failCount))
209
+ .slice(0, limit);
210
+ }
211
+ getUnstableTests(limit = 10) {
212
+ return Object.values(this.snapshot.testStability)
213
+ .sort((a, b) => a.stabilityScore - b.stabilityScore)
214
+ .slice(0, limit);
215
+ }
216
+ getDegradingTests() {
217
+ return Object.values(this.snapshot.testStability)
218
+ .filter((t) => t.trend === 'degrading');
219
+ }
220
+ getOverallStats() {
221
+ const entries = this.snapshot.entries;
222
+ const total = entries.length;
223
+ const successful = entries.filter((e) => e.success).length;
224
+ return {
225
+ totalHeals: total,
226
+ successRate: total > 0 ? successful / total : 0,
227
+ avgConfidence: total > 0
228
+ ? entries.reduce((sum, e) => sum + e.confidence, 0) / total
229
+ : 0,
230
+ avgDuration: total > 0
231
+ ? entries.reduce((sum, e) => sum + e.duration, 0) / total
232
+ : 0,
233
+ uniqueLocators: Object.keys(this.snapshot.locatorStats).length,
234
+ uniqueTests: Object.keys(this.snapshot.testStability).length,
235
+ };
236
+ }
237
+ getSnapshot() {
238
+ return { ...this.snapshot };
239
+ }
240
+ // ─── Maintenance ────────────────────────────────────────────────────────
241
+ prune() {
242
+ const cutoff = Date.now() - this.config.retentionDays * 24 * 60 * 60 * 1000;
243
+ const before = this.snapshot.entries.length;
244
+ this.snapshot.entries = this.snapshot.entries.filter((e) => e.timestamp > cutoff);
245
+ if (this.snapshot.entries.length < before) {
246
+ this.dirty = true;
247
+ logger.logger.debug(`[Analytics] Pruned ${before - this.snapshot.entries.length} old entries`);
248
+ }
249
+ }
250
+ emptySnapshot() {
251
+ return {
252
+ version: ANALYTICS_VERSION,
253
+ entries: [],
254
+ strategyStats: {},
255
+ locatorStats: {},
256
+ testStability: {},
257
+ lastUpdated: Date.now(),
258
+ };
259
+ }
260
+ }
261
+
262
+ exports.HealingAnalytics = HealingAnalytics;
263
+ //# sourceMappingURL=healing-analytics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"healing-analytics.js","sources":["../../../../src/analytics/healing-analytics.ts"],"sourcesContent":[null],"names":["fileExists","readJsonFile","logger","ensureDirectory","writeJsonFile"],"mappings":";;;;;AAAA;;;;;;AAMG;AAeH,MAAM,iBAAiB,GAAG,GAAG;MAEhB,gBAAgB,CAAA;AAK3B,IAAA,WAAA,CAAY,MAAuB,EAAA;QAF3B,IAAA,CAAA,KAAK,GAAG,KAAK;AAGnB,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM;AACpB,QAAA,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,aAAa,EAAE;IACtC;;IAIA,IAAI,GAAA;AACF,QAAA,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE;AAC1B,QAAA,IAAI;YACF,IAAI,CAACA,oBAAU,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE;AACtC,gBAAA,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,aAAa,EAAE;gBACpC;YACF;YAEA,MAAM,IAAI,GAAGC,sBAAY,CAAoB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;YACnE,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,KAAK,iBAAiB,EAAE;AAC/C,gBAAA,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,aAAa,EAAE;gBACpC;YACF;AAEA,YAAA,IAAI,CAAC,QAAQ,GAAG,IAAI;YACpB,IAAI,CAAC,KAAK,EAAE;AACZ,YAAAC,aAAM,CAAC,KAAK,CAAC,CAAA,mBAAA,EAAsB,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAA,QAAA,CAAU,CAAC;QAC5E;QAAE,OAAO,GAAG,EAAE;AACZ,YAAA,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,GAAG,GAAG,CAAC,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC;AAC5D,YAAAA,aAAM,CAAC,IAAI,CAAC,+BAA+B,GAAG,CAAA,CAAE,CAAC;AACjD,YAAA,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,aAAa,EAAE;QACtC;IACF;IAEA,IAAI,GAAA;QACF,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE;AACzC,QAAA,IAAI;AACF,YAAA,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;AAClC,YAAAC,yBAAe,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YAC1D,IAAI,CAAC,QAAQ,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE;YACtCC,uBAAa,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC;AACnD,YAAA,IAAI,CAAC,KAAK,GAAG,KAAK;AAClB,YAAAF,aAAM,CAAC,KAAK,CAAC,CAAA,kBAAA,EAAqB,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAA,QAAA,CAAU,CAAC;QAC3E;QAAE,OAAO,GAAG,EAAE;AACZ,YAAA,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,GAAG,GAAG,CAAC,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC;AAC5D,YAAAA,aAAM,CAAC,IAAI,CAAC,+BAA+B,GAAG,CAAA,CAAE,CAAC;QACnD;IACF;;AAIA,IAAA,WAAW,CAAC,KAAmB,EAAA;AAC7B,QAAA,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE;AAE1B,QAAA,MAAM,KAAK,GAAmB;YAC5B,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;AACtB,YAAA,iBAAiB,EAAE,KAAK,CAAC,eAAe,CAAC,oBAAoB;YAC7D,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,QAAQ,EAAE,KAAK,CAAC,QAAQ;AACxB,YAAA,OAAO,EAAE,KAAK,CAAC,MAAM,KAAK,QAAQ;SACnC;QAED,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;AACjC,QAAA,IAAI,CAAC,KAAK,GAAG,IAAI;;QAGjB,IAAI,IAAI,CAAC,MAAM,CAAC,eAAe,IAAI,KAAK,CAAC,QAAQ,EAAE;YACjD,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC;QACjD;AACA,QAAA,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE;AAC7B,YAAA,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC;QAChC;AACA,QAAA,IAAI,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE;AAClC,YAAA,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC;QACjC;;AAGA,QAAA,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE;YACzD,IAAI,CAAC,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC;QAC9E;IACF;;IAIQ,mBAAmB,CAAC,QAA6B,EAAE,KAAqB,EAAA;QAC9E,MAAM,GAAG,GAAG,QAAQ;QACpB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC;QAEjD,IAAI,CAAC,QAAQ,EAAE;AACb,YAAA,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG;AACjC,gBAAA,IAAI,EAAE,QAAQ;AACd,gBAAA,aAAa,EAAE,CAAC;gBAChB,YAAY,EAAE,KAAK,CAAC,OAAO,GAAG,CAAC,GAAG,CAAC;gBACnC,SAAS,EAAE,KAAK,CAAC,OAAO,GAAG,CAAC,GAAG,CAAC;gBAChC,aAAa,EAAE,KAAK,CAAC,UAAU;gBAC/B,WAAW,EAAE,KAAK,CAAC,QAAQ;gBAC3B,WAAW,EAAE,KAAK,CAAC,OAAO,GAAG,CAAC,GAAG,CAAC;aACnC;YACD;QACF;QAEA,QAAQ,CAAC,aAAa,EAAE;AACxB,QAAA,IAAI,KAAK,CAAC,OAAO,EAAE;YACjB,QAAQ,CAAC,YAAY,EAAE;QACzB;aAAO;YACL,QAAQ,CAAC,SAAS,EAAE;QACtB;QACA,QAAQ,CAAC,WAAW,GAAG,QAAQ,CAAC,YAAY,GAAG,QAAQ,CAAC,aAAa;AACrE,QAAA,QAAQ,CAAC,aAAa;AACpB,YAAA,CAAC,QAAQ,CAAC,aAAa,IAAI,QAAQ,CAAC,aAAa,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,UAAU;gBACzE,QAAQ,CAAC,aAAa;AACxB,QAAA,QAAQ,CAAC,WAAW;AAClB,YAAA,CAAC,QAAQ,CAAC,WAAW,IAAI,QAAQ,CAAC,aAAa,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,QAAQ;gBACrE,QAAQ,CAAC,aAAa;IAC1B;;AAIQ,IAAA,kBAAkB,CAAC,KAAqB,EAAA;AAC9C,QAAA,MAAM,GAAG,GAAG,KAAK,CAAC,iBAAiB;QACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,GAAG,CAAC;QAEhD,IAAI,CAAC,QAAQ,EAAE;AACb,YAAA,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG;gBAChC,UAAU,EAAE,KAAK,CAAC,iBAAiB;gBACnC,SAAS,EAAE,KAAK,CAAC,OAAO,GAAG,CAAC,GAAG,CAAC;gBAChC,SAAS,EAAE,KAAK,CAAC,OAAO,GAAG,CAAC,GAAG,CAAC;gBAChC,UAAU,EAAE,KAAK,CAAC,SAAS;AAC3B,gBAAA,UAAU,EAAE,KAAK,CAAC,QAAQ,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE;AAClD,gBAAA,KAAK,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC;aACvB;YACD;QACF;AAEA,QAAA,IAAI,KAAK,CAAC,OAAO,EAAE;YACjB,QAAQ,CAAC,SAAS,EAAE;QACtB;aAAO;YACL,QAAQ,CAAC,SAAS,EAAE;QACtB;AACA,QAAA,QAAQ,CAAC,UAAU,GAAG,KAAK,CAAC,SAAS;AACrC,QAAA,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE;YACnE,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;QAC1C;AACA,QAAA,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE;YAC3C,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;QACpC;IACF;;AAIQ,IAAA,mBAAmB,CAAC,KAAqB,EAAA;QAC/C,MAAM,GAAG,GAAG,CAAA,EAAG,KAAK,CAAC,QAAQ,CAAA,EAAA,EAAK,KAAK,CAAC,SAAS,CAAA,CAAE;QACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC;QAEjD,IAAI,CAAC,QAAQ,EAAE;AACb,YAAA,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG;gBACjC,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,SAAS,EAAE,KAAK,CAAC,SAAS;AAC1B,gBAAA,SAAS,EAAE,CAAC;AACZ,gBAAA,WAAW,EAAE,CAAC;gBACd,WAAW,EAAE,KAAK,CAAC,OAAO,GAAG,CAAC,GAAG,CAAC;gBAClC,cAAc,EAAE,KAAK,CAAC,OAAO,GAAG,EAAE,GAAG,EAAE;gBACvC,OAAO,EAAE,KAAK,CAAC,SAAS;AACxB,gBAAA,KAAK,EAAE,QAAQ;aAChB;YACD;QACF;QAEA,QAAQ,CAAC,SAAS,EAAE;QACpB,QAAQ,CAAC,WAAW,EAAE;AACtB,QAAA,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE;YAClB,QAAQ,CAAC,WAAW,EAAE;QACxB;AACA,QAAA,QAAQ,CAAC,OAAO,GAAG,KAAK,CAAC,SAAS;;;QAIlC,MAAM,SAAS,GAAG,QAAQ,CAAC,WAAW,GAAG,QAAQ,CAAC,SAAS;QAC3D,MAAM,SAAS,GAAG,QAAQ,CAAC,WAAW,GAAG,QAAQ,CAAC,WAAW;QAC7D,QAAQ,CAAC,cAAc,GAAG,IAAI,CAAC,KAAK,CAClC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,SAAS,GAAG,EAAE,GAAG,SAAS,GAAG,EAAE,CAAC,CACnD;;AAGD,QAAA,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,CAAC;aACjC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,KAAK,KAAK,CAAC,QAAQ,IAAI,CAAC,CAAC,SAAS,KAAK,KAAK,CAAC,SAAS;AAC9E,aAAA,KAAK,CAAC,GAAG,CAAC;AAEb,QAAA,IAAI,aAAa,CAAC,MAAM,IAAI,CAAC,EAAE;AAC7B,YAAA,MAAM,SAAS,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAC9E,YAAA,MAAM,UAAU,GAAG,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC5E,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM;YAC9E,MAAM,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,UAAU,CAAC,MAAM;AAEjF,YAAA,IAAI,UAAU,GAAG,SAAS,GAAG,GAAG,EAAE;AAChC,gBAAA,QAAQ,CAAC,KAAK,GAAG,WAAW;YAC9B;AAAO,iBAAA,IAAI,UAAU,GAAG,SAAS,GAAG,GAAG,EAAE;AACvC,gBAAA,QAAQ,CAAC,KAAK,GAAG,WAAW;YAC9B;iBAAO;AACL,gBAAA,QAAQ,CAAC,KAAK,GAAG,QAAQ;YAC3B;QACF;IACF;;IAIA,gBAAgB,GAAA;QACd,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa;AAC7C,aAAA,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW,CAAC;IAClD;IAEA,qBAAqB,CAAC,KAAK,GAAG,EAAE,EAAA;QAC9B,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY;aAC5C,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC;AACxE,aAAA,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC;IACpB;IAEA,gBAAgB,CAAC,KAAK,GAAG,EAAE,EAAA;QACzB,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa;AAC7C,aAAA,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,cAAc,GAAG,CAAC,CAAC,cAAc;AAClD,aAAA,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC;IACpB;IAEA,iBAAiB,GAAA;QACf,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa;AAC7C,aAAA,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,KAAK,WAAW,CAAC;IAC3C;IAEA,eAAe,GAAA;AAQb,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO;AACrC,QAAA,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM;AAC5B,QAAA,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM;QAE1D,OAAO;AACL,YAAA,UAAU,EAAE,KAAK;AACjB,YAAA,WAAW,EAAE,KAAK,GAAG,CAAC,GAAG,UAAU,GAAG,KAAK,GAAG,CAAC;YAC/C,aAAa,EAAE,KAAK,GAAG;kBACnB,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,GAAG;AACtD,kBAAE,CAAC;YACL,WAAW,EAAE,KAAK,GAAG;kBACjB,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,GAAG;AACpD,kBAAE,CAAC;AACL,YAAA,cAAc,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,MAAM;AAC9D,YAAA,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,MAAM;SAC7D;IACH;IAEA,WAAW,GAAA;AACT,QAAA,OAAO,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE;IAC7B;;IAIQ,KAAK,GAAA;QACX,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI;QAC3E,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM;QAC3C,IAAI,CAAC,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,SAAS,GAAG,MAAM,CAAC;QAEjF,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,GAAG,MAAM,EAAE;AACzC,YAAA,IAAI,CAAC,KAAK,GAAG,IAAI;AACjB,YAAAA,aAAM,CAAC,KAAK,CACV,CAAA,mBAAA,EAAsB,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAA,YAAA,CAAc,CAC1E;QACH;IACF;IAEQ,aAAa,GAAA;QACnB,OAAO;AACL,YAAA,OAAO,EAAE,iBAAiB;AAC1B,YAAA,OAAO,EAAE,EAAE;AACX,YAAA,aAAa,EAAE,EAAE;AACjB,YAAA,YAAY,EAAE,EAAE;AAChB,YAAA,aAAa,EAAE,EAAE;AACjB,YAAA,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;SACxB;IACH;AACD;;;;"}