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,135 @@
1
+ 'use strict';
2
+
3
+ var fs = require('fs');
4
+ var path = require('path');
5
+ var defaults = require('./defaults.js');
6
+ var logger = require('../utils/logger.js');
7
+ var environment = require('../utils/environment.js');
8
+
9
+ const CONFIG_FILE_NAMES = [
10
+ 'mindheal.config.ts',
11
+ 'mindheal.config.js',
12
+ 'mindheal.config.json',
13
+ 'mindheal.config.mjs',
14
+ ];
15
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
16
+ function deepMerge(target, source) {
17
+ const result = { ...target };
18
+ for (const key of Object.keys(source)) {
19
+ const sourceVal = source[key];
20
+ const targetVal = target[key];
21
+ if (sourceVal !== undefined &&
22
+ sourceVal !== null &&
23
+ typeof sourceVal === 'object' &&
24
+ !Array.isArray(sourceVal) &&
25
+ typeof targetVal === 'object' &&
26
+ targetVal !== null &&
27
+ !Array.isArray(targetVal)) {
28
+ result[key] = deepMerge(targetVal, sourceVal);
29
+ }
30
+ else if (sourceVal !== undefined) {
31
+ result[key] = sourceVal;
32
+ }
33
+ }
34
+ return result;
35
+ }
36
+ function validateConfig(config) {
37
+ const validProviders = [
38
+ 'anthropic', 'openai', 'azure-openai', 'gemini', 'ollama',
39
+ 'aws-bedrock', 'deepseek', 'groq', 'qwen', 'meta', 'perplexity',
40
+ ];
41
+ if (!validProviders.includes(config.ai.provider)) {
42
+ throw new Error(`[MindHeal] Invalid AI provider: "${config.ai.provider}". Supported: ${validProviders.join(', ')}`);
43
+ }
44
+ if (config.healing.enabled && !config.ai.apiKey) {
45
+ const aiStrategiesEnabled = config.healing.strategies.includes('ai');
46
+ if (aiStrategiesEnabled) {
47
+ logger.logger.warn('AI strategy is enabled but no API key provided. AI strategy will be skipped during healing.');
48
+ }
49
+ }
50
+ if (config.healing.confidenceThreshold < 0 || config.healing.confidenceThreshold > 1) {
51
+ throw new Error(`[MindHeal] confidenceThreshold must be between 0 and 1, got ${config.healing.confidenceThreshold}`);
52
+ }
53
+ if (config.healing.maxRetries < 1 || config.healing.maxRetries > 10) {
54
+ throw new Error(`[MindHeal] maxRetries must be between 1 and 10, got ${config.healing.maxRetries}`);
55
+ }
56
+ if (config.git.enabled && config.git.autoCreatePR && !config.git.token) {
57
+ logger.logger.warn('Git PR creation is enabled but no token provided. PR creation will be skipped.');
58
+ }
59
+ // Validate Enterprise config
60
+ if (config.enterprise) {
61
+ const validPlatforms = ['auto', 'salesforce', 'sap', 'oracle', 'workday', 'servicenow', 'dynamics'];
62
+ if (!validPlatforms.includes(config.enterprise.platform)) {
63
+ throw new Error(`[MindHeal] Invalid enterprise platform: "${config.enterprise.platform}". Valid: ${validPlatforms.join(', ')}`);
64
+ }
65
+ if (config.enterprise.loadTimeout < 1000 || config.enterprise.loadTimeout > 60000) {
66
+ throw new Error(`[MindHeal] Enterprise loadTimeout must be between 1000 and 60000, got ${config.enterprise.loadTimeout}`);
67
+ }
68
+ }
69
+ // Validate RAG config
70
+ if (config.rag) {
71
+ if (config.rag.similarityThreshold < 0 || config.rag.similarityThreshold > 1) {
72
+ throw new Error(`[MindHeal] RAG similarityThreshold must be between 0 and 1, got ${config.rag.similarityThreshold}`);
73
+ }
74
+ if (config.rag.maxContextChunks < 1 || config.rag.maxContextChunks > 20) {
75
+ throw new Error(`[MindHeal] RAG maxContextChunks must be between 1 and 20, got ${config.rag.maxContextChunks}`);
76
+ }
77
+ const validSources = [
78
+ 'healing-history', 'page-objects', 'git-changes',
79
+ 'dom-snapshots', 'component-docs', 'test-specs',
80
+ ];
81
+ for (const source of config.rag.sources) {
82
+ if (!validSources.includes(source)) {
83
+ throw new Error(`[MindHeal] Invalid RAG source: "${source}". Valid sources: ${validSources.join(', ')}`);
84
+ }
85
+ }
86
+ }
87
+ }
88
+ function resolveAutoSettings(config) {
89
+ const resolved = { ...config };
90
+ if (resolved.reviewServer.enabled === 'auto') {
91
+ resolved.reviewServer = {
92
+ ...resolved.reviewServer,
93
+ enabled: !environment.isCI(),
94
+ };
95
+ }
96
+ return resolved;
97
+ }
98
+ function loadConfig(userConfig) {
99
+ let fileConfig = {};
100
+ if (!userConfig) {
101
+ for (const fileName of CONFIG_FILE_NAMES) {
102
+ const filePath = path.resolve(process.cwd(), fileName);
103
+ if (fs.existsSync(filePath)) {
104
+ try {
105
+ if (fileName.endsWith('.json')) {
106
+ const { readFileSync } = require('fs');
107
+ fileConfig = JSON.parse(readFileSync(filePath, 'utf-8'));
108
+ }
109
+ else {
110
+ // For TS/JS config files, require them
111
+ const loaded = require(filePath);
112
+ fileConfig = loaded.default || loaded;
113
+ }
114
+ logger.logger.debug(`Loaded config from ${fileName}`);
115
+ break;
116
+ }
117
+ catch (error) {
118
+ logger.logger.warn(`Failed to load config from ${fileName}`, error);
119
+ }
120
+ }
121
+ }
122
+ }
123
+ const mergedConfig = deepMerge(defaults.DEFAULT_CONFIG, deepMerge(fileConfig, (userConfig || {})));
124
+ const resolvedConfig = resolveAutoSettings(mergedConfig);
125
+ logger.configureLogger(resolvedConfig.logging);
126
+ validateConfig(resolvedConfig);
127
+ return resolvedConfig;
128
+ }
129
+ function createConfig(userConfig) {
130
+ return loadConfig(userConfig);
131
+ }
132
+
133
+ exports.createConfig = createConfig;
134
+ exports.loadConfig = loadConfig;
135
+ //# sourceMappingURL=config-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-loader.js","sources":["../../../../src/config/config-loader.ts"],"sourcesContent":[null],"names":["logger","isCI","resolve","existsSync","DEFAULT_CONFIG","configureLogger"],"mappings":"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"}
@@ -0,0 +1,109 @@
1
+ 'use strict';
2
+
3
+ const DEFAULT_CONFIG = {
4
+ ai: {
5
+ provider: 'anthropic',
6
+ apiKey: '',
7
+ model: 'claude-sonnet-4-20250514',
8
+ maxTokens: 1024,
9
+ temperature: 0.1,
10
+ },
11
+ healing: {
12
+ enabled: true,
13
+ maxRetries: 3,
14
+ strategies: ['cache', 'attribute', 'text', 'role', 'css', 'xpath', 'table', 'modal', 'enterprise', 'ai'],
15
+ confidenceThreshold: 0.7,
16
+ cacheHeals: true,
17
+ cachePath: '.mindheal/cache.json',
18
+ excludePatterns: [],
19
+ domSnapshotDepth: 3,
20
+ handleDialogs: true,
21
+ },
22
+ git: {
23
+ enabled: true,
24
+ provider: 'github',
25
+ token: '',
26
+ baseBranch: 'main',
27
+ branchPrefix: 'mindheal/auto-fix',
28
+ autoCreatePR: true,
29
+ commitMessagePrefix: 'fix(locators):',
30
+ prLabels: ['auto-heal', 'mindheal'],
31
+ prReviewers: [],
32
+ },
33
+ reviewServer: {
34
+ enabled: 'auto',
35
+ port: 3000,
36
+ openBrowser: true,
37
+ autoCloseAfterReview: true,
38
+ },
39
+ reporting: {
40
+ outputDir: '.mindheal/reports',
41
+ generateHTML: true,
42
+ generateJSON: true,
43
+ },
44
+ enterprise: {
45
+ enabled: true,
46
+ platform: 'auto',
47
+ waitForLoad: true,
48
+ loadTimeout: 15000,
49
+ virtualScrolling: true,
50
+ customStableAttributes: [],
51
+ customDynamicIdPatterns: [],
52
+ },
53
+ analytics: {
54
+ enabled: true,
55
+ storePath: '.mindheal/analytics.json',
56
+ trackLocators: true,
57
+ trackStrategies: true,
58
+ trackTestStability: true,
59
+ maxEntries: 5000,
60
+ retentionDays: 90,
61
+ },
62
+ smartRetry: {
63
+ enabled: true,
64
+ waitForNetworkIdle: true,
65
+ networkIdleTimeout: 5000,
66
+ exponentialBackoff: true,
67
+ backoffBaseDelay: 500,
68
+ backoffMaxDelay: 10000,
69
+ flakyDetection: true,
70
+ flakyThreshold: 3,
71
+ flakyStorePath: '.mindheal/flaky-tests.json',
72
+ },
73
+ parallel: {
74
+ enabled: true,
75
+ lockTimeout: 10000,
76
+ lockRetryInterval: 50,
77
+ staleLockThreshold: 30000,
78
+ },
79
+ visualVerification: {
80
+ enabled: false,
81
+ screenshotDir: '.mindheal/screenshots',
82
+ diffThreshold: 0.1,
83
+ captureElement: true,
84
+ captureFullPage: false,
85
+ keepScreenshots: true,
86
+ },
87
+ rag: {
88
+ enabled: true,
89
+ storePath: '.mindheal/knowledge.json',
90
+ maxContextChunks: 5,
91
+ similarityThreshold: 0.3,
92
+ sources: [
93
+ 'healing-history',
94
+ 'page-objects',
95
+ 'git-changes',
96
+ 'dom-snapshots',
97
+ 'component-docs',
98
+ 'test-specs',
99
+ ],
100
+ pageObjectPaths: ['pages', 'src/pages', 'page-objects'],
101
+ componentDocPaths: [],
102
+ },
103
+ logging: {
104
+ level: 'info',
105
+ },
106
+ };
107
+
108
+ exports.DEFAULT_CONFIG = DEFAULT_CONFIG;
109
+ //# sourceMappingURL=defaults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.js","sources":["../../../../src/config/defaults.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -0,0 +1,280 @@
1
+ 'use strict';
2
+
3
+ var logger = require('../utils/logger.js');
4
+
5
+ /**
6
+ * Approximate token limit for the HTML snapshot.
7
+ * ~4 chars per token is a conservative estimate.
8
+ */
9
+ const MAX_SNAPSHOT_CHARS = 16000;
10
+ /**
11
+ * Attribute names and text patterns that indicate sensitive data.
12
+ */
13
+ const SENSITIVE_ATTR_NAMES = new Set([
14
+ 'password',
15
+ 'passwd',
16
+ 'secret',
17
+ 'token',
18
+ 'apikey',
19
+ 'api-key',
20
+ 'api_key',
21
+ 'authorization',
22
+ 'auth',
23
+ 'credential',
24
+ 'access-token',
25
+ 'access_token',
26
+ 'refresh-token',
27
+ 'refresh_token',
28
+ 'session-id',
29
+ 'session_id',
30
+ 'csrf',
31
+ 'ssn',
32
+ ]);
33
+ const SENSITIVE_ATTR_PATTERNS = [
34
+ /password/i,
35
+ /token/i,
36
+ /secret/i,
37
+ /apikey/i,
38
+ /api[_-]?key/i,
39
+ /authorization/i,
40
+ /credential/i,
41
+ /session[_-]?id/i,
42
+ ];
43
+ const SENSITIVE_VALUE_PATTERNS = [
44
+ // Bearer tokens
45
+ /^Bearer\s+\S+/i,
46
+ // Long hex/base64 strings that look like tokens (32+ chars)
47
+ /^[A-Za-z0-9+/=_-]{32,}$/,
48
+ ];
49
+ /**
50
+ * Sanitizes an attribute value by redacting sensitive content.
51
+ */
52
+ function sanitizeAttributeValue(name, value) {
53
+ const lowerName = name.toLowerCase();
54
+ if (SENSITIVE_ATTR_NAMES.has(lowerName)) {
55
+ return '[REDACTED]';
56
+ }
57
+ for (const pattern of SENSITIVE_ATTR_PATTERNS) {
58
+ if (pattern.test(lowerName)) {
59
+ return '[REDACTED]';
60
+ }
61
+ }
62
+ for (const pattern of SENSITIVE_VALUE_PATTERNS) {
63
+ if (pattern.test(value)) {
64
+ return '[REDACTED]';
65
+ }
66
+ }
67
+ // Redact type=password input values
68
+ if (lowerName === 'value' || lowerName === 'type') {
69
+ // value is left alone unless caught above; type is informational
70
+ return value;
71
+ }
72
+ return value;
73
+ }
74
+ /**
75
+ * Sanitizes text content by removing potential sensitive data patterns.
76
+ */
77
+ function sanitizeTextContent(text) {
78
+ if (!text.trim())
79
+ return '';
80
+ // Redact long token-like strings embedded in text
81
+ return text.replace(/[A-Za-z0-9+/=_-]{40,}/g, '[REDACTED]');
82
+ }
83
+ /**
84
+ * Serializes a DOMElement tree into sanitized HTML, respecting depth and size limits.
85
+ */
86
+ function serializeElement(element, currentDepth, maxDepth) {
87
+ if (currentDepth > maxDepth) {
88
+ return element.children.length > 0 ? '<!-- truncated -->' : '';
89
+ }
90
+ const tag = element.tag.toLowerCase();
91
+ // Build attribute string
92
+ const attrs = [];
93
+ for (const [name, value] of Object.entries(element.attributes)) {
94
+ const sanitized = sanitizeAttributeValue(name, value);
95
+ attrs.push(`${name}="${escapeHtml(sanitized)}"`);
96
+ }
97
+ const attrStr = attrs.length > 0 ? ' ' + attrs.join(' ') : '';
98
+ // Self-closing tags
99
+ const selfClosing = new Set(['input', 'br', 'hr', 'img', 'meta', 'link', 'area', 'base', 'col', 'embed', 'source', 'track', 'wbr']);
100
+ if (selfClosing.has(tag)) {
101
+ return `<${tag}${attrStr} />`;
102
+ }
103
+ // Text content
104
+ const textContent = element.text ? sanitizeTextContent(element.text) : '';
105
+ // Children
106
+ const childHtml = element.children
107
+ .map((child) => serializeElement(child, currentDepth + 1, maxDepth))
108
+ .filter(Boolean)
109
+ .join('\n');
110
+ const inner = [textContent, childHtml].filter(Boolean).join('\n');
111
+ return `<${tag}${attrStr}>${inner}</${tag}>`;
112
+ }
113
+ /**
114
+ * Escapes special HTML characters in attribute values.
115
+ */
116
+ function escapeHtml(str) {
117
+ return str
118
+ .replace(/&/g, '&amp;')
119
+ .replace(/"/g, '&quot;')
120
+ .replace(/</g, '&lt;')
121
+ .replace(/>/g, '&gt;');
122
+ }
123
+ /**
124
+ * Truncates HTML to approximately the target character count,
125
+ * cutting at the last complete tag boundary when possible.
126
+ */
127
+ function truncateHtml(html, maxChars) {
128
+ if (html.length <= maxChars)
129
+ return html;
130
+ // Find the last closing tag boundary before the limit
131
+ const truncated = html.substring(0, maxChars);
132
+ const lastCloseTag = truncated.lastIndexOf('</');
133
+ const lastSelfClose = truncated.lastIndexOf('/>');
134
+ const cutPoint = Math.max(lastCloseTag, lastSelfClose);
135
+ if (cutPoint > maxChars * 0.5) {
136
+ // Find the end of that closing tag
137
+ const endOfTag = html.indexOf('>', cutPoint);
138
+ if (endOfTag !== -1 && endOfTag < maxChars + 100) {
139
+ return html.substring(0, endOfTag + 1) + '\n<!-- snapshot truncated -->';
140
+ }
141
+ }
142
+ return truncated + '\n<!-- snapshot truncated -->';
143
+ }
144
+ /**
145
+ * Captures a sanitized DOM snapshot from the given Playwright page.
146
+ *
147
+ * @param page - Playwright Page object
148
+ * @param rootSelector - Optional CSS selector to scope the snapshot. Defaults to 'body'.
149
+ * @param maxDepth - Maximum depth of the DOM tree to capture. Defaults to 3.
150
+ * @returns A DOMSnapshot containing sanitized HTML, URL, title, and timestamp.
151
+ */
152
+ async function captureDOMSnapshot(page, rootSelector, maxDepth = 3) {
153
+ const startTime = Date.now();
154
+ const selector = rootSelector ?? 'body';
155
+ logger.logger.debug(`Capturing DOM snapshot for selector: ${selector}, maxDepth: ${maxDepth}`);
156
+ try {
157
+ const [url, title] = await Promise.all([
158
+ page.url(),
159
+ page.title(),
160
+ ]);
161
+ // Extract the DOM tree from the page context
162
+ const domTree = await page.evaluate(({ sel, depth }) => {
163
+ function extractElement(el, currentDepth, maxD) {
164
+ if (currentDepth > maxD)
165
+ return null;
166
+ const tag = el.tagName.toLowerCase();
167
+ // Skip script, style, and noscript elements
168
+ if (['script', 'style', 'noscript', 'svg'].includes(tag))
169
+ return null;
170
+ const attributes = {};
171
+ for (let ai = 0; ai < el.attributes.length; ai++) {
172
+ const attr = el.attributes[ai];
173
+ attributes[attr.name] = attr.value;
174
+ }
175
+ const id = el.id || undefined;
176
+ const classes = el.className && typeof el.className === 'string'
177
+ ? el.className.split(/\s+/).filter(Boolean)
178
+ : undefined;
179
+ // Get direct text (not from children)
180
+ let text;
181
+ const directText = Array.from(el.childNodes)
182
+ .filter((n) => n.nodeType === Node.TEXT_NODE)
183
+ .map((n) => n.textContent?.trim() ?? '')
184
+ .filter(Boolean)
185
+ .join(' ');
186
+ if (directText) {
187
+ text = directText.substring(0, 200);
188
+ }
189
+ const role = el.getAttribute('role') || undefined;
190
+ const ariaLabel = el.getAttribute('aria-label') || undefined;
191
+ const testId = el.getAttribute('data-testid') ??
192
+ el.getAttribute('data-test-id') ??
193
+ el.getAttribute('data-test') ??
194
+ undefined;
195
+ const children = [];
196
+ if (currentDepth < maxD) {
197
+ // Traverse regular children
198
+ for (let ci = 0; ci < el.children.length; ci++) {
199
+ const child = el.children[ci];
200
+ const extracted = extractElement(child, currentDepth + 1, maxD);
201
+ if (extracted) {
202
+ children.push(extracted);
203
+ }
204
+ }
205
+ // Traverse Shadow DOM if present
206
+ if (el.shadowRoot) {
207
+ const shadowMarker = {
208
+ tag: '#shadow-root',
209
+ attributes: {},
210
+ children: [],
211
+ };
212
+ for (let si = 0; si < el.shadowRoot.children.length; si++) {
213
+ const shadowChild = el.shadowRoot.children[si];
214
+ const extracted = extractElement(shadowChild, currentDepth + 1, maxD);
215
+ if (extracted) {
216
+ shadowMarker.children.push(extracted);
217
+ }
218
+ }
219
+ if (shadowMarker.children.length > 0) {
220
+ children.push(shadowMarker);
221
+ }
222
+ }
223
+ }
224
+ return { tag, id, classes, attributes, text, children, role, ariaLabel, testId };
225
+ }
226
+ const root = document.querySelector(sel);
227
+ if (!root)
228
+ return null;
229
+ return extractElement(root, 0, depth);
230
+ }, { sel: selector, depth: maxDepth });
231
+ if (!domTree) {
232
+ logger.logger.warn(`Root element not found for selector: ${selector}`);
233
+ return {
234
+ html: `<!-- element not found: ${escapeHtml(selector)} -->`,
235
+ url,
236
+ title,
237
+ timestamp: Date.now(),
238
+ rootSelector: selector !== 'body' ? selector : undefined,
239
+ };
240
+ }
241
+ // Cast to DOMElement for serialization
242
+ const element = domTree;
243
+ const rawHtml = serializeElement(element, 0, maxDepth);
244
+ const html = truncateHtml(rawHtml, MAX_SNAPSHOT_CHARS);
245
+ const duration = Date.now() - startTime;
246
+ logger.logger.debug(`DOM snapshot captured in ${duration}ms, size: ${html.length} chars`);
247
+ return {
248
+ html,
249
+ url,
250
+ title,
251
+ timestamp: Date.now(),
252
+ rootSelector: selector !== 'body' ? selector : undefined,
253
+ };
254
+ }
255
+ catch (error) {
256
+ const message = error instanceof Error ? error.message : String(error);
257
+ logger.logger.error(`Failed to capture DOM snapshot: ${message}`);
258
+ // Return a minimal snapshot on failure so healing can still proceed
259
+ let fallbackUrl = 'unknown';
260
+ let fallbackTitle = 'unknown';
261
+ try {
262
+ fallbackUrl = page.url();
263
+ }
264
+ catch { /* ignore */ }
265
+ try {
266
+ fallbackTitle = await page.title();
267
+ }
268
+ catch { /* ignore */ }
269
+ return {
270
+ html: `<!-- snapshot capture failed: ${escapeHtml(message)} -->`,
271
+ url: fallbackUrl,
272
+ title: fallbackTitle,
273
+ timestamp: Date.now(),
274
+ rootSelector: selector !== 'body' ? selector : undefined,
275
+ };
276
+ }
277
+ }
278
+
279
+ exports.captureDOMSnapshot = captureDOMSnapshot;
280
+ //# sourceMappingURL=dom-snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dom-snapshot.js","sources":["../../../../src/core/dom-snapshot.ts"],"sourcesContent":[null],"names":["logger"],"mappings":"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"}