@testdroid-ai/cli 0.1.2

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 (229) hide show
  1. package/dist/adb/adb-path-resolver.d.ts +6 -0
  2. package/dist/adb/adb-path-resolver.d.ts.map +1 -0
  3. package/dist/adb/adb-path-resolver.js +93 -0
  4. package/dist/adb/adb-path-resolver.js.map +1 -0
  5. package/dist/adb/adb-shell.d.ts +29 -0
  6. package/dist/adb/adb-shell.d.ts.map +1 -0
  7. package/dist/adb/adb-shell.js +128 -0
  8. package/dist/adb/adb-shell.js.map +1 -0
  9. package/dist/adb/detector.d.ts +12 -0
  10. package/dist/adb/detector.d.ts.map +1 -0
  11. package/dist/adb/detector.js +44 -0
  12. package/dist/adb/detector.js.map +1 -0
  13. package/dist/adb/device-tracker.d.ts +23 -0
  14. package/dist/adb/device-tracker.d.ts.map +1 -0
  15. package/dist/adb/device-tracker.js +134 -0
  16. package/dist/adb/device-tracker.js.map +1 -0
  17. package/dist/adb/emulator-detector.d.ts +11 -0
  18. package/dist/adb/emulator-detector.d.ts.map +1 -0
  19. package/dist/adb/emulator-detector.js +54 -0
  20. package/dist/adb/emulator-detector.js.map +1 -0
  21. package/dist/appium/health-check.d.ts +6 -0
  22. package/dist/appium/health-check.d.ts.map +1 -0
  23. package/dist/appium/health-check.js +61 -0
  24. package/dist/appium/health-check.js.map +1 -0
  25. package/dist/appium/session-manager.d.ts +15 -0
  26. package/dist/appium/session-manager.d.ts.map +1 -0
  27. package/dist/appium/session-manager.js +82 -0
  28. package/dist/appium/session-manager.js.map +1 -0
  29. package/dist/auth/credential-store.d.ts +31 -0
  30. package/dist/auth/credential-store.d.ts.map +1 -0
  31. package/dist/auth/credential-store.js +154 -0
  32. package/dist/auth/credential-store.js.map +1 -0
  33. package/dist/auth/pairing-auth.d.ts +26 -0
  34. package/dist/auth/pairing-auth.d.ts.map +1 -0
  35. package/dist/auth/pairing-auth.js +177 -0
  36. package/dist/auth/pairing-auth.js.map +1 -0
  37. package/dist/auth/token-manager.d.ts +20 -0
  38. package/dist/auth/token-manager.d.ts.map +1 -0
  39. package/dist/auth/token-manager.js +101 -0
  40. package/dist/auth/token-manager.js.map +1 -0
  41. package/dist/commands/connect.d.ts +9 -0
  42. package/dist/commands/connect.d.ts.map +1 -0
  43. package/dist/commands/connect.js +270 -0
  44. package/dist/commands/connect.js.map +1 -0
  45. package/dist/commands/devices.d.ts +2 -0
  46. package/dist/commands/devices.d.ts.map +1 -0
  47. package/dist/commands/devices.js +52 -0
  48. package/dist/commands/devices.js.map +1 -0
  49. package/dist/commands/doctor.d.ts +2 -0
  50. package/dist/commands/doctor.d.ts.map +1 -0
  51. package/dist/commands/doctor.js +214 -0
  52. package/dist/commands/doctor.js.map +1 -0
  53. package/dist/commands/mirror.d.ts +2 -0
  54. package/dist/commands/mirror.d.ts.map +1 -0
  55. package/dist/commands/mirror.js +77 -0
  56. package/dist/commands/mirror.js.map +1 -0
  57. package/dist/commands/prompt.d.ts +12 -0
  58. package/dist/commands/prompt.d.ts.map +1 -0
  59. package/dist/commands/prompt.js +174 -0
  60. package/dist/commands/prompt.js.map +1 -0
  61. package/dist/commands/record.d.ts +7 -0
  62. package/dist/commands/record.d.ts.map +1 -0
  63. package/dist/commands/record.js +129 -0
  64. package/dist/commands/record.js.map +1 -0
  65. package/dist/commands/run.d.ts +16 -0
  66. package/dist/commands/run.d.ts.map +1 -0
  67. package/dist/commands/run.js +271 -0
  68. package/dist/commands/run.js.map +1 -0
  69. package/dist/commands/setup.d.ts +6 -0
  70. package/dist/commands/setup.d.ts.map +1 -0
  71. package/dist/commands/setup.js +50 -0
  72. package/dist/commands/setup.js.map +1 -0
  73. package/dist/commands/status.d.ts +2 -0
  74. package/dist/commands/status.d.ts.map +1 -0
  75. package/dist/commands/status.js +32 -0
  76. package/dist/commands/status.js.map +1 -0
  77. package/dist/healing/ai-adapter.d.ts +44 -0
  78. package/dist/healing/ai-adapter.d.ts.map +1 -0
  79. package/dist/healing/ai-adapter.js +87 -0
  80. package/dist/healing/ai-adapter.js.map +1 -0
  81. package/dist/healing/healer.d.ts +109 -0
  82. package/dist/healing/healer.d.ts.map +1 -0
  83. package/dist/healing/healer.js +475 -0
  84. package/dist/healing/healer.js.map +1 -0
  85. package/dist/healing/similarity.d.ts +63 -0
  86. package/dist/healing/similarity.d.ts.map +1 -0
  87. package/dist/healing/similarity.js +172 -0
  88. package/dist/healing/similarity.js.map +1 -0
  89. package/dist/index.d.ts +3 -0
  90. package/dist/index.d.ts.map +1 -0
  91. package/dist/index.js +107 -0
  92. package/dist/index.js.map +1 -0
  93. package/dist/recording/capture-strategies/capture-strategy.interface.d.ts +6 -0
  94. package/dist/recording/capture-strategies/capture-strategy.interface.d.ts.map +1 -0
  95. package/dist/recording/capture-strategies/capture-strategy.interface.js +3 -0
  96. package/dist/recording/capture-strategies/capture-strategy.interface.js.map +1 -0
  97. package/dist/recording/capture-strategies/getevent.strategy.d.ts +27 -0
  98. package/dist/recording/capture-strategies/getevent.strategy.d.ts.map +1 -0
  99. package/dist/recording/capture-strategies/getevent.strategy.js +163 -0
  100. package/dist/recording/capture-strategies/getevent.strategy.js.map +1 -0
  101. package/dist/recording/capture-strategies/key-capture.strategy.d.ts +16 -0
  102. package/dist/recording/capture-strategies/key-capture.strategy.d.ts.map +1 -0
  103. package/dist/recording/capture-strategies/key-capture.strategy.js +67 -0
  104. package/dist/recording/capture-strategies/key-capture.strategy.js.map +1 -0
  105. package/dist/recording/capture-strategies/logcat-capture.strategy.d.ts +32 -0
  106. package/dist/recording/capture-strategies/logcat-capture.strategy.d.ts.map +1 -0
  107. package/dist/recording/capture-strategies/logcat-capture.strategy.js +176 -0
  108. package/dist/recording/capture-strategies/logcat-capture.strategy.js.map +1 -0
  109. package/dist/recording/confidence-scorer.d.ts +13 -0
  110. package/dist/recording/confidence-scorer.d.ts.map +1 -0
  111. package/dist/recording/confidence-scorer.js +34 -0
  112. package/dist/recording/confidence-scorer.js.map +1 -0
  113. package/dist/recording/event-capture.d.ts +40 -0
  114. package/dist/recording/event-capture.d.ts.map +1 -0
  115. package/dist/recording/event-capture.js +168 -0
  116. package/dist/recording/event-capture.js.map +1 -0
  117. package/dist/recording/recorder.d.ts +32 -0
  118. package/dist/recording/recorder.d.ts.map +1 -0
  119. package/dist/recording/recorder.js +107 -0
  120. package/dist/recording/recorder.js.map +1 -0
  121. package/dist/runner/adb-executor.d.ts +116 -0
  122. package/dist/runner/adb-executor.d.ts.map +1 -0
  123. package/dist/runner/adb-executor.js +323 -0
  124. package/dist/runner/adb-executor.js.map +1 -0
  125. package/dist/runner/appium-executor.d.ts +35 -0
  126. package/dist/runner/appium-executor.d.ts.map +1 -0
  127. package/dist/runner/appium-executor.js +191 -0
  128. package/dist/runner/appium-executor.js.map +1 -0
  129. package/dist/runner/parse-strategies/appium-default.strategy.d.ts +12 -0
  130. package/dist/runner/parse-strategies/appium-default.strategy.d.ts.map +1 -0
  131. package/dist/runner/parse-strategies/appium-default.strategy.js +342 -0
  132. package/dist/runner/parse-strategies/appium-default.strategy.js.map +1 -0
  133. package/dist/runner/parse-strategies/index.d.ts +7 -0
  134. package/dist/runner/parse-strategies/index.d.ts.map +1 -0
  135. package/dist/runner/parse-strategies/index.js +14 -0
  136. package/dist/runner/parse-strategies/index.js.map +1 -0
  137. package/dist/runner/parse-strategies/java.strategy.d.ts +8 -0
  138. package/dist/runner/parse-strategies/java.strategy.d.ts.map +1 -0
  139. package/dist/runner/parse-strategies/java.strategy.js +170 -0
  140. package/dist/runner/parse-strategies/java.strategy.js.map +1 -0
  141. package/dist/runner/parse-strategies/maestro.strategy.d.ts +8 -0
  142. package/dist/runner/parse-strategies/maestro.strategy.d.ts.map +1 -0
  143. package/dist/runner/parse-strategies/maestro.strategy.js +105 -0
  144. package/dist/runner/parse-strategies/maestro.strategy.js.map +1 -0
  145. package/dist/runner/parse-strategies/python.strategy.d.ts +8 -0
  146. package/dist/runner/parse-strategies/python.strategy.d.ts.map +1 -0
  147. package/dist/runner/parse-strategies/python.strategy.js +140 -0
  148. package/dist/runner/parse-strategies/python.strategy.js.map +1 -0
  149. package/dist/runner/parse-strategies/robot.strategy.d.ts +8 -0
  150. package/dist/runner/parse-strategies/robot.strategy.d.ts.map +1 -0
  151. package/dist/runner/parse-strategies/robot.strategy.js +81 -0
  152. package/dist/runner/parse-strategies/robot.strategy.js.map +1 -0
  153. package/dist/runner/parse-strategies/types.d.ts +17 -0
  154. package/dist/runner/parse-strategies/types.d.ts.map +1 -0
  155. package/dist/runner/parse-strategies/types.js +3 -0
  156. package/dist/runner/parse-strategies/types.js.map +1 -0
  157. package/dist/runner/parse-strategies/utils.d.ts +39 -0
  158. package/dist/runner/parse-strategies/utils.d.ts.map +1 -0
  159. package/dist/runner/parse-strategies/utils.js +217 -0
  160. package/dist/runner/parse-strategies/utils.js.map +1 -0
  161. package/dist/runner/script-parser.d.ts +43 -0
  162. package/dist/runner/script-parser.d.ts.map +1 -0
  163. package/dist/runner/script-parser.js +68 -0
  164. package/dist/runner/script-parser.js.map +1 -0
  165. package/dist/runner/selector-resolver.d.ts +87 -0
  166. package/dist/runner/selector-resolver.d.ts.map +1 -0
  167. package/dist/runner/selector-resolver.js +206 -0
  168. package/dist/runner/selector-resolver.js.map +1 -0
  169. package/dist/runner/step-executor.d.ts +112 -0
  170. package/dist/runner/step-executor.d.ts.map +1 -0
  171. package/dist/runner/step-executor.js +518 -0
  172. package/dist/runner/step-executor.js.map +1 -0
  173. package/dist/runner/test-runner.d.ts +89 -0
  174. package/dist/runner/test-runner.d.ts.map +1 -0
  175. package/dist/runner/test-runner.js +320 -0
  176. package/dist/runner/test-runner.js.map +1 -0
  177. package/dist/scrcpy/launcher.d.ts +16 -0
  178. package/dist/scrcpy/launcher.d.ts.map +1 -0
  179. package/dist/scrcpy/launcher.js +87 -0
  180. package/dist/scrcpy/launcher.js.map +1 -0
  181. package/dist/services/device-poller.d.ts +10 -0
  182. package/dist/services/device-poller.d.ts.map +1 -0
  183. package/dist/services/device-poller.js +44 -0
  184. package/dist/services/device-poller.js.map +1 -0
  185. package/dist/services/execution-manager.d.ts +18 -0
  186. package/dist/services/execution-manager.d.ts.map +1 -0
  187. package/dist/services/execution-manager.js +185 -0
  188. package/dist/services/execution-manager.js.map +1 -0
  189. package/dist/services/recording-manager.d.ts +13 -0
  190. package/dist/services/recording-manager.d.ts.map +1 -0
  191. package/dist/services/recording-manager.js +234 -0
  192. package/dist/services/recording-manager.js.map +1 -0
  193. package/dist/setup/adb-installer.d.ts +8 -0
  194. package/dist/setup/adb-installer.d.ts.map +1 -0
  195. package/dist/setup/adb-installer.js +115 -0
  196. package/dist/setup/adb-installer.js.map +1 -0
  197. package/dist/setup/appium-installer.d.ts +8 -0
  198. package/dist/setup/appium-installer.d.ts.map +1 -0
  199. package/dist/setup/appium-installer.js +113 -0
  200. package/dist/setup/appium-installer.js.map +1 -0
  201. package/dist/setup/base-installer.d.ts +33 -0
  202. package/dist/setup/base-installer.d.ts.map +1 -0
  203. package/dist/setup/base-installer.js +170 -0
  204. package/dist/setup/base-installer.js.map +1 -0
  205. package/dist/setup/build-tools-installer.d.ts +8 -0
  206. package/dist/setup/build-tools-installer.d.ts.map +1 -0
  207. package/dist/setup/build-tools-installer.js +109 -0
  208. package/dist/setup/build-tools-installer.js.map +1 -0
  209. package/dist/setup/java-installer.d.ts +8 -0
  210. package/dist/setup/java-installer.d.ts.map +1 -0
  211. package/dist/setup/java-installer.js +132 -0
  212. package/dist/setup/java-installer.js.map +1 -0
  213. package/dist/setup/paths.d.ts +12 -0
  214. package/dist/setup/paths.d.ts.map +1 -0
  215. package/dist/setup/paths.js +90 -0
  216. package/dist/setup/paths.js.map +1 -0
  217. package/dist/setup/scrcpy-installer.d.ts +8 -0
  218. package/dist/setup/scrcpy-installer.d.ts.map +1 -0
  219. package/dist/setup/scrcpy-installer.js +143 -0
  220. package/dist/setup/scrcpy-installer.js.map +1 -0
  221. package/dist/setup/setup-manager.d.ts +18 -0
  222. package/dist/setup/setup-manager.d.ts.map +1 -0
  223. package/dist/setup/setup-manager.js +113 -0
  224. package/dist/setup/setup-manager.js.map +1 -0
  225. package/dist/ws/socket.d.ts +38 -0
  226. package/dist/ws/socket.d.ts.map +1 -0
  227. package/dist/ws/socket.js +91 -0
  228. package/dist/ws/socket.js.map +1 -0
  229. package/package.json +53 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"similarity.d.ts","sourceRoot":"","sources":["../../src/healing/similarity.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAiChE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAgB3D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAa/D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,CAmBxD;AAWD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,SAAS,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,GAAG,YAAY,GAAG,aAAa,GAAG,WAAW,CAAC;CAChE;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,SAAS,EAAE,EACrB,MAAM,EAAE;IACN,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GACA,mBAAmB,EAAE,CA8DvB"}
@@ -0,0 +1,172 @@
1
+ "use strict";
2
+ /**
3
+ * Funcoes de similaridade para o motor de self-healing.
4
+ *
5
+ * Implementa Levenshtein distance sem dependencias externas
6
+ * para comparar seletores e encontrar elementos semelhantes.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.levenshteinDistance = levenshteinDistance;
10
+ exports.textSimilarity = textSimilarity;
11
+ exports.containsSimilarity = containsSimilarity;
12
+ exports.parseUiElements = parseUiElements;
13
+ exports.findSimilarElements = findSimilarElements;
14
+ /**
15
+ * Calcula a distancia de Levenshtein entre duas strings.
16
+ * Retorna o numero minimo de edicoes (insercoes, remocoes, substituicoes)
17
+ * necessarias para transformar `a` em `b`.
18
+ */
19
+ function levenshteinDistance(a, b) {
20
+ const lenA = a.length;
21
+ const lenB = b.length;
22
+ // Caso base
23
+ if (lenA === 0)
24
+ return lenB;
25
+ if (lenB === 0)
26
+ return lenA;
27
+ // Matriz de distancias (otimizada para usar apenas 2 linhas)
28
+ let prevRow = new Array(lenB + 1);
29
+ let currRow = new Array(lenB + 1);
30
+ for (let j = 0; j <= lenB; j++) {
31
+ prevRow[j] = j;
32
+ }
33
+ for (let i = 1; i <= lenA; i++) {
34
+ currRow[0] = i;
35
+ for (let j = 1; j <= lenB; j++) {
36
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
37
+ currRow[j] = Math.min(prevRow[j] + 1, // remocao
38
+ currRow[j - 1] + 1, // insercao
39
+ prevRow[j - 1] + cost);
40
+ }
41
+ // Trocar linhas
42
+ [prevRow, currRow] = [currRow, prevRow];
43
+ }
44
+ return prevRow[lenB];
45
+ }
46
+ /**
47
+ * Calcula a similaridade entre duas strings (0-100).
48
+ * Baseado na distancia de Levenshtein normalizada.
49
+ *
50
+ * @returns Valor de 0 (completamente diferente) a 100 (identico)
51
+ */
52
+ function textSimilarity(a, b) {
53
+ if (a === b)
54
+ return 100;
55
+ if (!a || !b)
56
+ return 0;
57
+ const aLower = a.toLowerCase();
58
+ const bLower = b.toLowerCase();
59
+ if (aLower === bLower)
60
+ return 95;
61
+ const distance = levenshteinDistance(aLower, bLower);
62
+ const maxLen = Math.max(aLower.length, bLower.length);
63
+ if (maxLen === 0)
64
+ return 100;
65
+ const similarity = ((maxLen - distance) / maxLen) * 100;
66
+ return Math.round(similarity);
67
+ }
68
+ /**
69
+ * Verifica se uma string contem a outra (match parcial).
70
+ * Retorna confianca de 0-100.
71
+ */
72
+ function containsSimilarity(a, b) {
73
+ if (!a || !b)
74
+ return 0;
75
+ const aLower = a.toLowerCase();
76
+ const bLower = b.toLowerCase();
77
+ if (aLower.includes(bLower) || bLower.includes(aLower)) {
78
+ const shorter = Math.min(aLower.length, bLower.length);
79
+ const longer = Math.max(aLower.length, bLower.length);
80
+ return Math.round((shorter / longer) * 90);
81
+ }
82
+ return 0;
83
+ }
84
+ /**
85
+ * Extrai todos os elementos do XML do UI dump.
86
+ */
87
+ function parseUiElements(xml) {
88
+ const elements = [];
89
+ const nodeRegex = /<node\s[^>]*>/g;
90
+ let match;
91
+ while ((match = nodeRegex.exec(xml)) !== null) {
92
+ const nodeStr = match[0];
93
+ elements.push({
94
+ nodeStr,
95
+ resourceId: extractAttr(nodeStr, 'resource-id'),
96
+ text: extractAttr(nodeStr, 'text'),
97
+ className: extractAttr(nodeStr, 'class'),
98
+ contentDesc: extractAttr(nodeStr, 'content-desc'),
99
+ bounds: extractAttr(nodeStr, 'bounds'),
100
+ clickable: extractAttr(nodeStr, 'clickable') === 'true',
101
+ });
102
+ }
103
+ return elements;
104
+ }
105
+ /**
106
+ * Extrai o valor de um atributo de um node XML.
107
+ */
108
+ function extractAttr(nodeStr, attrName) {
109
+ const regex = new RegExp(`${attrName}="([^"]*)"`);
110
+ const match = nodeStr.match(regex);
111
+ return match ? match[1] : '';
112
+ }
113
+ /**
114
+ * Encontra elementos similares ao alvo no UI dump.
115
+ * Retorna candidatos ordenados por confianca (maior primeiro).
116
+ *
117
+ * @param elements Lista de elementos do UI dump
118
+ * @param target Atributos do elemento original
119
+ * @returns Lista de matches ordenados por confianca
120
+ */
121
+ function findSimilarElements(elements, target) {
122
+ const matches = [];
123
+ for (const element of elements) {
124
+ let bestConfidence = 0;
125
+ let bestMatchedBy = 'text';
126
+ // Comparar por resourceId
127
+ if (target.resourceId && element.resourceId) {
128
+ const sim = textSimilarity(target.resourceId, element.resourceId);
129
+ const containsSim = containsSimilarity(target.resourceId, element.resourceId);
130
+ const bestSim = Math.max(sim, containsSim);
131
+ if (bestSim > bestConfidence) {
132
+ bestConfidence = bestSim;
133
+ bestMatchedBy = 'resourceId';
134
+ }
135
+ }
136
+ // Comparar por texto
137
+ if (target.text && element.text) {
138
+ const sim = textSimilarity(target.text, element.text);
139
+ if (sim > bestConfidence) {
140
+ bestConfidence = sim;
141
+ bestMatchedBy = 'text';
142
+ }
143
+ }
144
+ // Comparar por content-desc
145
+ if (target.contentDesc && element.contentDesc) {
146
+ const sim = textSimilarity(target.contentDesc, element.contentDesc);
147
+ if (sim > bestConfidence) {
148
+ bestConfidence = sim;
149
+ bestMatchedBy = 'contentDesc';
150
+ }
151
+ }
152
+ // Comparar por classe (bonus se mesma classe)
153
+ if (target.className && element.className === target.className) {
154
+ // Se ja tem match parcial, boost a confianca
155
+ if (bestConfidence > 0) {
156
+ bestConfidence = Math.min(100, bestConfidence + 10);
157
+ }
158
+ }
159
+ // Apenas incluir se tem alguma similaridade relevante
160
+ if (bestConfidence >= 40) {
161
+ matches.push({
162
+ element,
163
+ confidence: bestConfidence,
164
+ matchedBy: bestMatchedBy,
165
+ });
166
+ }
167
+ }
168
+ // Ordenar por confianca (maior primeiro)
169
+ matches.sort((a, b) => b.confidence - a.confidence);
170
+ return matches;
171
+ }
172
+ //# sourceMappingURL=similarity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"similarity.js","sourceRoot":"","sources":["../../src/healing/similarity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ // Node.js version check
5
+ const [nodeMajor] = process.versions.node.split('.').map(Number);
6
+ if (nodeMajor < 20) {
7
+ console.error(`TestDroid requires Node.js >= 20. Current: ${process.version}`);
8
+ process.exit(1);
9
+ }
10
+ const commander_1 = require("commander");
11
+ const devices_1 = require("./commands/devices");
12
+ const mirror_1 = require("./commands/mirror");
13
+ const connect_1 = require("./commands/connect");
14
+ const record_1 = require("./commands/record");
15
+ const run_1 = require("./commands/run");
16
+ const prompt_1 = require("./commands/prompt");
17
+ const doctor_1 = require("./commands/doctor");
18
+ const status_1 = require("./commands/status");
19
+ const setup_1 = require("./commands/setup");
20
+ const program = new commander_1.Command();
21
+ program
22
+ .name('testdroid')
23
+ .description('TestDroid AI - CLI for mobile test automation')
24
+ .version('0.1.0');
25
+ program
26
+ .command('devices')
27
+ .description('List all connected Android devices')
28
+ .action(async () => {
29
+ await (0, devices_1.devicesCommand)();
30
+ });
31
+ program
32
+ .command('mirror [serial]')
33
+ .description('Mirror device screen via scrcpy')
34
+ .action(async (serial) => {
35
+ await (0, mirror_1.mirrorCommand)(serial);
36
+ });
37
+ program
38
+ .command('connect')
39
+ .description('Connect local devices to TestDroid server')
40
+ .option('--server <url>', 'Server URL')
41
+ .option('--token <token>', 'Auth token (legacy, prefer pairing)')
42
+ .option('--no-browser', 'Do not auto-open browser for pairing')
43
+ .option('--poll', 'Use polling instead of event-driven tracking')
44
+ .action(async (options) => {
45
+ await (0, connect_1.connectCommand)(options);
46
+ });
47
+ program
48
+ .command('doctor')
49
+ .description('Check prerequisites and system health')
50
+ .action(async () => {
51
+ await (0, doctor_1.doctorCommand)();
52
+ });
53
+ program
54
+ .command('setup')
55
+ .description('Install all dependencies (ADB, Java, Appium, scrcpy)')
56
+ .option('--check', 'Show installation status')
57
+ .option('--clean', 'Remove all installed dependencies')
58
+ .option('--component <name>', 'Install specific component (adb, java, appium, scrcpy)')
59
+ .action(async (options) => {
60
+ await (0, setup_1.setupCommand)(options);
61
+ });
62
+ program
63
+ .command('status')
64
+ .description('Show current session and connection status')
65
+ .action(async () => {
66
+ await (0, status_1.statusCommand)();
67
+ });
68
+ program
69
+ .command('record [serial]')
70
+ .description('Record touch events from an Android device')
71
+ .option('--output <file>', 'Output file path')
72
+ .option('--no-screenshots', 'Disable screenshot capture')
73
+ .option('--no-appium', 'Desabilitar auto-deteccao do Appium')
74
+ .option('--appium-url <url>', 'URL do servidor Appium (default: http://localhost:4723)')
75
+ .action(async (serial, options) => {
76
+ await (0, record_1.recordCommand)(serial, {
77
+ output: options?.output,
78
+ noScreenshots: options?.screenshots === false,
79
+ appium: options?.appium,
80
+ appiumUrl: options?.appiumUrl,
81
+ });
82
+ });
83
+ program
84
+ .command('run <file>')
85
+ .description('Execute a test file on a connected Android device')
86
+ .option('--serial <serial>', 'Device serial')
87
+ .option('--package <package>', 'Android app package name')
88
+ .option('--timeout <ms>', 'Timeout in milliseconds')
89
+ .option('--report-to <url>', 'Backend URL for result reporting')
90
+ .option('--no-heal', 'Disable selector self-healing')
91
+ .option('--appium-url <url>', 'URL do servidor Appium (default: http://localhost:4723)')
92
+ .action(async (file, options) => {
93
+ await (0, run_1.runCommand)(file, options);
94
+ });
95
+ program
96
+ .command('prompt <texto>')
97
+ .description('Generate test code from natural language description')
98
+ .option('--package <package>', 'Android app package name')
99
+ .option('--language <language>', 'Test language (appium-ts, appium-js, playwright)')
100
+ .option('--output <file>', 'Output file path')
101
+ .option('--url <url>', 'Backend server URL')
102
+ .option('--token <token>', 'Backend auth token')
103
+ .action(async (texto, options) => {
104
+ await (0, prompt_1.promptCommand)(texto, options);
105
+ });
106
+ program.parse(process.argv);
107
+ //# 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,6 @@
1
+ import { RecordingEvent } from '@testdroid-ai/shared';
2
+ export interface CaptureStrategy {
3
+ start(onEvent: (event: RecordingEvent) => void): Promise<void>;
4
+ stop(): void;
5
+ }
6
+ //# sourceMappingURL=capture-strategy.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture-strategy.interface.d.ts","sourceRoot":"","sources":["../../../src/recording/capture-strategies/capture-strategy.interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D,IAAI,IAAI,IAAI,CAAC;CACd"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=capture-strategy.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture-strategy.interface.js","sourceRoot":"","sources":["../../../src/recording/capture-strategies/capture-strategy.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,27 @@
1
+ import { RecordingEvent } from '@testdroid-ai/shared';
2
+ import { CaptureStrategy } from './capture-strategy.interface';
3
+ export declare class GeteventStrategy implements CaptureStrategy {
4
+ private serial;
5
+ private process;
6
+ private eventCount;
7
+ private screenSize;
8
+ private rawX;
9
+ private rawY;
10
+ private touchDown;
11
+ private touchStartCaptured;
12
+ private touchStartTime;
13
+ private touchStartX;
14
+ private touchStartY;
15
+ private inputMax;
16
+ constructor(serial: string);
17
+ setScreenSize(size: {
18
+ width: number;
19
+ height: number;
20
+ }): void;
21
+ start(onEvent: (event: RecordingEvent) => void): Promise<void>;
22
+ stop(): void;
23
+ private detectInputRange;
24
+ private parseRawGetevent;
25
+ private emitGesture;
26
+ }
27
+ //# sourceMappingURL=getevent.strategy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getevent.strategy.d.ts","sourceRoot":"","sources":["../../../src/recording/capture-strategies/getevent.strategy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAsB,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAE/D,qBAAa,gBAAiB,YAAW,eAAe;IAe1C,OAAO,CAAC,MAAM;IAd1B,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,UAAU,CAAiC;IAGnD,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,QAAQ,CAA0B;gBAEtB,MAAM,EAAE,MAAM;IAElC,aAAa,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAItD,KAAK,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBpE,IAAI,IAAI,IAAI;IAWZ,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,gBAAgB;IA4CxB,OAAO,CAAC,WAAW;CA+CpB"}
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GeteventStrategy = void 0;
4
+ const child_process_1 = require("child_process");
5
+ class GeteventStrategy {
6
+ serial;
7
+ process = null;
8
+ eventCount = 0;
9
+ screenSize = { width: 1080, height: 2400 };
10
+ // getevent state
11
+ rawX = 0;
12
+ rawY = 0;
13
+ touchDown = false;
14
+ touchStartCaptured = false; // true once we've captured start position
15
+ touchStartTime = 0;
16
+ touchStartX = 0;
17
+ touchStartY = 0;
18
+ inputMax = { x: 32767, y: 32767 };
19
+ constructor(serial) {
20
+ this.serial = serial;
21
+ }
22
+ setScreenSize(size) {
23
+ this.screenSize = size;
24
+ }
25
+ async start(onEvent) {
26
+ this.eventCount = 0;
27
+ this.detectInputRange();
28
+ this.process = (0, child_process_1.spawn)('adb', ['-s', this.serial, 'shell', 'getevent', '-t'], {
29
+ stdio: ['ignore', 'pipe', 'pipe'],
30
+ });
31
+ let buffer = '';
32
+ this.process.stdout?.on('data', (data) => {
33
+ buffer += data.toString();
34
+ const lines = buffer.split('\n');
35
+ buffer = lines.pop() || '';
36
+ for (const line of lines) {
37
+ this.parseRawGetevent(line.trim(), onEvent);
38
+ }
39
+ });
40
+ this.process.stderr?.on('data', () => { });
41
+ this.process.on('error', () => { });
42
+ }
43
+ stop() {
44
+ if (this.process) {
45
+ try {
46
+ this.process.kill('SIGKILL');
47
+ }
48
+ catch {
49
+ // process may already be dead
50
+ }
51
+ this.process = null;
52
+ }
53
+ }
54
+ detectInputRange() {
55
+ try {
56
+ const output = (0, child_process_1.execFileSync)('adb', ['-s', this.serial, 'shell', 'getevent', '-lp'], { encoding: 'utf-8', stdio: 'pipe', timeout: 5000 });
57
+ // Try multitouch first, fall back to single-touch (emulator virtio)
58
+ const xMax = output.match(/ABS_MT_POSITION_X[\s\S]*?max\s+(\d+)/)
59
+ || output.match(/ABS_X[\s\S]*?max\s+(\d+)/);
60
+ const yMax = output.match(/ABS_MT_POSITION_Y[\s\S]*?max\s+(\d+)/)
61
+ || output.match(/ABS_Y[\s\S]*?max\s+(\d+)/);
62
+ if (xMax)
63
+ this.inputMax.x = parseInt(xMax[1], 10);
64
+ if (yMax)
65
+ this.inputMax.y = parseInt(yMax[1], 10);
66
+ }
67
+ catch { }
68
+ }
69
+ parseRawGetevent(line, onEvent) {
70
+ if (!line || line.startsWith('add device'))
71
+ return;
72
+ const match = line.match(/\[\s*[\d.]+\]\s*\/dev\/input\/event\d+:\s*([0-9a-f]+)\s+([0-9a-f]+)\s+([0-9a-f]+)/);
73
+ if (!match)
74
+ return;
75
+ const type = parseInt(match[1], 16);
76
+ const code = parseInt(match[2], 16);
77
+ // Parse as unsigned, then convert to signed 32-bit for tracking ID comparison
78
+ const rawValue = parseInt(match[3], 16);
79
+ const value = rawValue > 0x7fffffff ? rawValue - 0x100000000 : rawValue;
80
+ if (type === 3) {
81
+ // ABS_MT_POSITION_X (0x35) for multitouch, ABS_X (0x00) for emulator virtio
82
+ if (code === 0x35 || code === 0x00)
83
+ this.rawX = value;
84
+ // ABS_MT_POSITION_Y (0x36) for multitouch, ABS_Y (0x01) for emulator virtio
85
+ else if (code === 0x36 || code === 0x01)
86
+ this.rawY = value;
87
+ else if (code === 0x39) {
88
+ if (value === -1)
89
+ this.emitGesture(onEvent);
90
+ else if (!this.touchDown) {
91
+ this.touchDown = true;
92
+ this.touchStartCaptured = false; // will capture on next SYN_REPORT
93
+ this.touchStartTime = Date.now();
94
+ }
95
+ }
96
+ // BTN_TOUCH (0x14a), BTN_TOOL_FINGER (0x145), BTN_LEFT (0x110 — emulator mouse input)
97
+ }
98
+ else if (type === 1 && (code === 0x14a || code === 0x145 || code === 0x110)) {
99
+ if (value === 1 && !this.touchDown) {
100
+ this.touchDown = true;
101
+ this.touchStartCaptured = false;
102
+ this.touchStartTime = Date.now();
103
+ }
104
+ else if (value === 0) {
105
+ this.emitGesture(onEvent);
106
+ }
107
+ }
108
+ else if (type === 0 && code === 0 && value === 0) {
109
+ // SYN_REPORT — capture start position on first sync after touch down
110
+ if (this.touchDown && !this.touchStartCaptured) {
111
+ this.touchStartX = this.rawX;
112
+ this.touchStartY = this.rawY;
113
+ this.touchStartCaptured = true;
114
+ }
115
+ }
116
+ }
117
+ emitGesture(onEvent) {
118
+ if (!this.touchDown)
119
+ return;
120
+ this.touchDown = false;
121
+ const duration = Date.now() - this.touchStartTime;
122
+ const startX = Math.round((this.touchStartX / this.inputMax.x) * this.screenSize.width);
123
+ const startY = Math.round((this.touchStartY / this.inputMax.y) * this.screenSize.height);
124
+ const endX = Math.round((this.rawX / this.inputMax.x) * this.screenSize.width);
125
+ const endY = Math.round((this.rawY / this.inputMax.y) * this.screenSize.height);
126
+ // Calculate distance in SCREEN PIXELS (not raw input coords)
127
+ // Raw coords range is 0-32767 on emulators, so raw distance is misleading
128
+ const dxPx = endX - startX;
129
+ const dyPx = endY - startY;
130
+ const distancePx = Math.sqrt(dxPx * dxPx + dyPx * dyPx);
131
+ // Gesture classification:
132
+ // - Tap: short distance (<50px) + short duration (<400ms)
133
+ // Fingers naturally move 20-40px even on intentional taps
134
+ // - Long press: short distance (<50px) + long duration (>=400ms)
135
+ // - Swipe: large distance (>=50px)
136
+ let eventType;
137
+ if (distancePx < 50 && duration < 400)
138
+ eventType = 'tap';
139
+ else if (distancePx < 50)
140
+ eventType = 'long_press';
141
+ else
142
+ eventType = 'swipe';
143
+ const event = {
144
+ type: eventType,
145
+ timestamp: Date.now(),
146
+ x: startX,
147
+ y: startY,
148
+ gestureDetails: {
149
+ duration,
150
+ distance: Math.round(distancePx),
151
+ velocity: duration > 0 ? Math.round(distancePx / duration * 1000) : 0,
152
+ },
153
+ };
154
+ if (eventType === 'swipe') {
155
+ event.endX = endX;
156
+ event.endY = endY;
157
+ }
158
+ this.eventCount++;
159
+ onEvent(event);
160
+ }
161
+ }
162
+ exports.GeteventStrategy = GeteventStrategy;
163
+ //# sourceMappingURL=getevent.strategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getevent.strategy.js","sourceRoot":"","sources":["../../../src/recording/capture-strategies/getevent.strategy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { RecordingEvent } from '@testdroid-ai/shared';
2
+ import { CaptureStrategy } from './capture-strategy.interface';
3
+ /**
4
+ * Captures hardware key events (Back, Home, etc.) via getevent.
5
+ * Runs in parallel with the main capture strategy.
6
+ * Only emits key events — does NOT capture touch/swipe.
7
+ */
8
+ export declare class KeyCaptureStrategy implements CaptureStrategy {
9
+ private serial;
10
+ private process;
11
+ constructor(serial: string);
12
+ start(onEvent: (event: RecordingEvent) => void): Promise<void>;
13
+ stop(): void;
14
+ private parseLine;
15
+ }
16
+ //# sourceMappingURL=key-capture.strategy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key-capture.strategy.d.ts","sourceRoot":"","sources":["../../../src/recording/capture-strategies/key-capture.strategy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAE/D;;;;GAIG;AACH,qBAAa,kBAAmB,YAAW,eAAe;IAG5C,OAAO,CAAC,MAAM;IAF1B,OAAO,CAAC,OAAO,CAA6B;gBAExB,MAAM,EAAE,MAAM;IAE5B,KAAK,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBpE,IAAI,IAAI,IAAI;IAOZ,OAAO,CAAC,SAAS;CAsBlB"}
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.KeyCaptureStrategy = void 0;
4
+ const child_process_1 = require("child_process");
5
+ /**
6
+ * Captures hardware key events (Back, Home, etc.) via getevent.
7
+ * Runs in parallel with the main capture strategy.
8
+ * Only emits key events — does NOT capture touch/swipe.
9
+ */
10
+ class KeyCaptureStrategy {
11
+ serial;
12
+ process = null;
13
+ constructor(serial) {
14
+ this.serial = serial;
15
+ }
16
+ async start(onEvent) {
17
+ // getevent -lt gives labeled events with timestamps
18
+ this.process = (0, child_process_1.spawn)('adb', [
19
+ '-s', this.serial, 'shell', 'getevent', '-lt',
20
+ ], {
21
+ stdio: ['ignore', 'pipe', 'pipe'],
22
+ });
23
+ let buffer = '';
24
+ this.process.stdout?.on('data', (data) => {
25
+ buffer += data.toString();
26
+ const lines = buffer.split('\n');
27
+ buffer = lines.pop() || '';
28
+ for (const line of lines) {
29
+ this.parseLine(line.trim(), onEvent);
30
+ }
31
+ });
32
+ this.process.stderr?.on('data', () => { });
33
+ this.process.on('error', () => { });
34
+ }
35
+ stop() {
36
+ if (this.process) {
37
+ try {
38
+ this.process.kill('SIGKILL');
39
+ }
40
+ catch { }
41
+ this.process = null;
42
+ }
43
+ }
44
+ parseLine(line, onEvent) {
45
+ // Format: [timestamp] /dev/input/eventN: EV_KEY KEY_BACK DOWN/UP
46
+ // We only care about KEY UP events (action completed)
47
+ if (!line.includes('EV_KEY'))
48
+ return;
49
+ if (!line.includes('UP'))
50
+ return;
51
+ let type = null;
52
+ if (line.includes('KEY_BACK')) {
53
+ type = 'back';
54
+ }
55
+ else if (line.includes('KEY_HOMEPAGE') || line.includes('KEY_HOME')) {
56
+ type = 'home';
57
+ }
58
+ if (!type)
59
+ return;
60
+ onEvent({
61
+ type,
62
+ timestamp: Date.now(),
63
+ });
64
+ }
65
+ }
66
+ exports.KeyCaptureStrategy = KeyCaptureStrategy;
67
+ //# sourceMappingURL=key-capture.strategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key-capture.strategy.js","sourceRoot":"","sources":["../../../src/recording/capture-strategies/key-capture.strategy.ts"],"names":[],"mappings":";;;AAAA,iDAAoD;AAIpD;;;;GAIG;AACH,MAAa,kBAAkB;IAGT;IAFZ,OAAO,GAAwB,IAAI,CAAC;IAE5C,YAAoB,MAAc;QAAd,WAAM,GAAN,MAAM,CAAQ;IAAG,CAAC;IAEtC,KAAK,CAAC,KAAK,CAAC,OAAwC;QAClD,oDAAoD;QACpD,IAAI,CAAC,OAAO,GAAG,IAAA,qBAAK,EAAC,KAAK,EAAE;YAC1B,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK;SAC9C,EAAE;YACD,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;SAClC,CAAC,CAAC;QAEH,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;YAC/C,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC1B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACjC,MAAM,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;YAC3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC;YACvC,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC1C,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACrC,CAAC;IAED,IAAI;QACF,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC;gBAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;YAC9C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACtB,CAAC;IACH,CAAC;IAEO,SAAS,CAAC,IAAY,EAAE,OAAwC;QACtE,iEAAiE;QACjE,sDAAsD;QAEtD,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAAE,OAAO;QACrC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,OAAO;QAEjC,IAAI,IAAI,GAA2B,IAAI,CAAC;QAExC,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9B,IAAI,GAAG,MAAM,CAAC;QAChB,CAAC;aAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YACtE,IAAI,GAAG,MAAM,CAAC;QAChB,CAAC;QAED,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,OAAO,CAAC;YACN,IAAI;YACJ,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC,CAAC;IACL,CAAC;CACF;AAxDD,gDAwDC"}