execbro 2.3.0 → 2.5.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 (549) hide show
  1. package/build/__tests__/helpers/fake-cdp-server.d.ts +0 -12
  2. package/build/__tests__/helpers/fake-cdp-server.d.ts.map +1 -1
  3. package/build/__tests__/helpers/fake-cdp-server.js +0 -22
  4. package/build/__tests__/helpers/fake-cdp-server.js.map +1 -1
  5. package/build/__tests__/helpers/tap-test-helpers.d.ts +0 -23
  6. package/build/__tests__/helpers/tap-test-helpers.d.ts.map +1 -1
  7. package/build/__tests__/helpers/tap-test-helpers.js +2 -29
  8. package/build/__tests__/helpers/tap-test-helpers.js.map +1 -1
  9. package/build/__tests__/integration/auto-reconnect.test.js +4 -14
  10. package/build/__tests__/integration/auto-reconnect.test.js.map +1 -1
  11. package/build/__tests__/integration/connection-health.test.js +1 -10
  12. package/build/__tests__/integration/connection-health.test.js.map +1 -1
  13. package/build/__tests__/integration/execute-in-app.test.js +1 -11
  14. package/build/__tests__/integration/execute-in-app.test.js.map +1 -1
  15. package/build/__tests__/integration/native-logs.test.js +0 -5
  16. package/build/__tests__/integration/native-logs.test.js.map +1 -1
  17. package/build/__tests__/integration/per-call-timeout.test.js +1 -5
  18. package/build/__tests__/integration/per-call-timeout.test.js.map +1 -1
  19. package/build/__tests__/integration/socket-close-midflight.test.js +2 -12
  20. package/build/__tests__/integration/socket-close-midflight.test.js.map +1 -1
  21. package/build/__tests__/integration/stale-target-probe.test.js +2 -17
  22. package/build/__tests__/integration/stale-target-probe.test.js.map +1 -1
  23. package/build/__tests__/integration/tap-strategies.test.js +2 -36
  24. package/build/__tests__/integration/tap-strategies.test.js.map +1 -1
  25. package/build/__tests__/integration/text-input.test.js +0 -39
  26. package/build/__tests__/integration/text-input.test.js.map +1 -1
  27. package/build/__tests__/integration/tools.test.js +1 -7
  28. package/build/__tests__/integration/tools.test.js.map +1 -1
  29. package/build/__tests__/setup.js +0 -2
  30. package/build/__tests__/setup.js.map +1 -1
  31. package/build/__tests__/unit/androidEmulatorAvds.test.js +0 -10
  32. package/build/__tests__/unit/androidEmulatorAvds.test.js.map +1 -1
  33. package/build/__tests__/unit/appContext.test.js +0 -2
  34. package/build/__tests__/unit/appContext.test.js.map +1 -1
  35. package/build/__tests__/unit/appRequest.test.js +0 -3
  36. package/build/__tests__/unit/appRequest.test.js.map +1 -1
  37. package/build/__tests__/unit/buildToken.test.js +0 -6
  38. package/build/__tests__/unit/buildToken.test.js.map +1 -1
  39. package/build/__tests__/unit/burst.test.js +0 -1
  40. package/build/__tests__/unit/burst.test.js.map +1 -1
  41. package/build/__tests__/unit/clearLogsNative.test.js +0 -8
  42. package/build/__tests__/unit/clearLogsNative.test.js.map +1 -1
  43. package/build/__tests__/unit/componentFormatNaming.test.js +0 -13
  44. package/build/__tests__/unit/componentFormatNaming.test.js.map +1 -1
  45. package/build/__tests__/unit/componentSource.test.js +0 -4
  46. package/build/__tests__/unit/componentSource.test.js.map +1 -1
  47. package/build/__tests__/unit/componentSourceResolve.test.js +0 -1
  48. package/build/__tests__/unit/componentSourceResolve.test.js.map +1 -1
  49. package/build/__tests__/unit/contextWiring.test.js +0 -3
  50. package/build/__tests__/unit/contextWiring.test.js.map +1 -1
  51. package/build/__tests__/unit/coordinateMiss.test.js +0 -16
  52. package/build/__tests__/unit/coordinateMiss.test.js.map +1 -1
  53. package/build/__tests__/unit/deviceDiscovery.test.js +0 -4
  54. package/build/__tests__/unit/deviceDiscovery.test.js.map +1 -1
  55. package/build/__tests__/unit/deviceResolution.test.js +0 -2
  56. package/build/__tests__/unit/deviceResolution.test.js.map +1 -1
  57. package/build/__tests__/unit/deviceResolver.test.js +0 -1
  58. package/build/__tests__/unit/deviceResolver.test.js.map +1 -1
  59. package/build/__tests__/unit/deviceResolverStaleRetry.test.js +0 -8
  60. package/build/__tests__/unit/deviceResolverStaleRetry.test.js.map +1 -1
  61. package/build/__tests__/unit/epochRender.test.js +0 -3
  62. package/build/__tests__/unit/epochRender.test.js.map +1 -1
  63. package/build/__tests__/unit/errorCategorization.test.js +0 -18
  64. package/build/__tests__/unit/errorCategorization.test.js.map +1 -1
  65. package/build/__tests__/unit/exec.test.js +0 -1
  66. package/build/__tests__/unit/exec.test.js.map +1 -1
  67. package/build/__tests__/unit/executor.test.js +0 -15
  68. package/build/__tests__/unit/executor.test.js.map +1 -1
  69. package/build/__tests__/unit/findElementTreeReuse.test.js +0 -12
  70. package/build/__tests__/unit/findElementTreeReuse.test.js.map +1 -1
  71. package/build/__tests__/unit/fingerprint.test.js +0 -4
  72. package/build/__tests__/unit/fingerprint.test.js.map +1 -1
  73. package/build/__tests__/unit/focusedInputTools.test.js +0 -4
  74. package/build/__tests__/unit/focusedInputTools.test.js.map +1 -1
  75. package/build/__tests__/unit/getLogsEmptyContract.test.js +0 -30
  76. package/build/__tests__/unit/getLogsEmptyContract.test.js.map +1 -1
  77. package/build/__tests__/unit/getLogsNativeSource.test.js +0 -22
  78. package/build/__tests__/unit/getLogsNativeSource.test.js.map +1 -1
  79. package/build/__tests__/unit/graphqlOperation.test.d.ts +2 -0
  80. package/build/__tests__/unit/graphqlOperation.test.d.ts.map +1 -0
  81. package/build/__tests__/unit/graphqlOperation.test.js +107 -0
  82. package/build/__tests__/unit/graphqlOperation.test.js.map +1 -0
  83. package/build/__tests__/unit/inputTarget.test.js +0 -16
  84. package/build/__tests__/unit/inputTarget.test.js.map +1 -1
  85. package/build/__tests__/unit/inputTextTool.test.js +0 -3
  86. package/build/__tests__/unit/inputTextTool.test.js.map +1 -1
  87. package/build/__tests__/unit/jsLogEvents.test.js +0 -3
  88. package/build/__tests__/unit/jsLogEvents.test.js.map +1 -1
  89. package/build/__tests__/unit/keyboardMetrics.test.js +0 -2
  90. package/build/__tests__/unit/keyboardMetrics.test.js.map +1 -1
  91. package/build/__tests__/unit/keyboardRaise.test.js +0 -2
  92. package/build/__tests__/unit/keyboardRaise.test.js.map +1 -1
  93. package/build/__tests__/unit/licenseGrace.test.js +1 -4
  94. package/build/__tests__/unit/licenseGrace.test.js.map +1 -1
  95. package/build/__tests__/unit/logEventFormat.test.js +0 -27
  96. package/build/__tests__/unit/logEventFormat.test.js.map +1 -1
  97. package/build/__tests__/unit/logEvents.test.js +1 -5
  98. package/build/__tests__/unit/logEvents.test.js.map +1 -1
  99. package/build/__tests__/unit/logGrouping.test.js +0 -2
  100. package/build/__tests__/unit/logGrouping.test.js.map +1 -1
  101. package/build/__tests__/unit/logOwnership.test.js +0 -11
  102. package/build/__tests__/unit/logOwnership.test.js.map +1 -1
  103. package/build/__tests__/unit/logRelevance.test.js +0 -6
  104. package/build/__tests__/unit/logRelevance.test.js.map +1 -1
  105. package/build/__tests__/unit/logSourceAndroid.test.js +0 -4
  106. package/build/__tests__/unit/logSourceAndroid.test.js.map +1 -1
  107. package/build/__tests__/unit/logSourceIos.test.js +0 -5
  108. package/build/__tests__/unit/logSourceIos.test.js.map +1 -1
  109. package/build/__tests__/unit/logs.test.js +0 -1
  110. package/build/__tests__/unit/logs.test.js.map +1 -1
  111. package/build/__tests__/unit/measureComponentTools.test.js +0 -1
  112. package/build/__tests__/unit/measureComponentTools.test.js.map +1 -1
  113. package/build/__tests__/unit/metro.test.js +0 -2
  114. package/build/__tests__/unit/metro.test.js.map +1 -1
  115. package/build/__tests__/unit/nativeInputValue.test.js +0 -4
  116. package/build/__tests__/unit/nativeInputValue.test.js.map +1 -1
  117. package/build/__tests__/unit/nativeLogs.test.js +1 -23
  118. package/build/__tests__/unit/nativeLogs.test.js.map +1 -1
  119. package/build/__tests__/unit/navigateVerify.test.js +0 -6
  120. package/build/__tests__/unit/navigateVerify.test.js.map +1 -1
  121. package/build/__tests__/unit/navigation.test.js +0 -5
  122. package/build/__tests__/unit/navigation.test.js.map +1 -1
  123. package/build/__tests__/unit/networkInterceptor.test.js +0 -2
  124. package/build/__tests__/unit/networkInterceptor.test.js.map +1 -1
  125. package/build/__tests__/unit/overlayGuard.test.d.ts +2 -0
  126. package/build/__tests__/unit/overlayGuard.test.d.ts.map +1 -0
  127. package/build/__tests__/unit/overlayGuard.test.js +123 -0
  128. package/build/__tests__/unit/overlayGuard.test.js.map +1 -0
  129. package/build/__tests__/unit/pendingExecutions.test.js +0 -6
  130. package/build/__tests__/unit/pendingExecutions.test.js.map +1 -1
  131. package/build/__tests__/unit/probe.test.js +0 -1
  132. package/build/__tests__/unit/probe.test.js.map +1 -1
  133. package/build/__tests__/unit/projectMemory.test.js +6 -7
  134. package/build/__tests__/unit/projectMemory.test.js.map +1 -1
  135. package/build/__tests__/unit/projectStore.test.js +2 -2
  136. package/build/__tests__/unit/projectStore.test.js.map +1 -1
  137. package/build/__tests__/unit/reloadAppAutoConnect.test.js +0 -9
  138. package/build/__tests__/unit/reloadAppAutoConnect.test.js.map +1 -1
  139. package/build/__tests__/unit/rnGlobalsBootstrap.test.js +3 -3
  140. package/build/__tests__/unit/rnGlobalsBootstrap.test.js.map +1 -1
  141. package/build/__tests__/unit/routeHistory.test.d.ts +2 -0
  142. package/build/__tests__/unit/routeHistory.test.d.ts.map +1 -0
  143. package/build/__tests__/unit/routeHistory.test.js +136 -0
  144. package/build/__tests__/unit/routeHistory.test.js.map +1 -0
  145. package/build/__tests__/unit/screenSpace.test.js +30 -13
  146. package/build/__tests__/unit/screenSpace.test.js.map +1 -1
  147. package/build/__tests__/unit/screenState.test.js +3 -6
  148. package/build/__tests__/unit/screenState.test.js.map +1 -1
  149. package/build/__tests__/unit/screenStateInputValue.test.js +0 -7
  150. package/build/__tests__/unit/screenStateInputValue.test.js.map +1 -1
  151. package/build/__tests__/unit/screenStateKeyboard.test.js +0 -1
  152. package/build/__tests__/unit/screenStateKeyboard.test.js.map +1 -1
  153. package/build/__tests__/unit/screenshot-diff.test.js +0 -6
  154. package/build/__tests__/unit/screenshot-diff.test.js.map +1 -1
  155. package/build/__tests__/unit/sdkMirrorPoller.test.js +0 -8
  156. package/build/__tests__/unit/sdkMirrorPoller.test.js.map +1 -1
  157. package/build/__tests__/unit/settleAndDiff.test.js +0 -11
  158. package/build/__tests__/unit/settleAndDiff.test.js.map +1 -1
  159. package/build/__tests__/unit/signedVerdict.test.js +0 -5
  160. package/build/__tests__/unit/signedVerdict.test.js.map +1 -1
  161. package/build/__tests__/unit/swipeDirection.test.js +6 -9
  162. package/build/__tests__/unit/swipeDirection.test.js.map +1 -1
  163. package/build/__tests__/unit/symbolicate.test.js +0 -1
  164. package/build/__tests__/unit/symbolicate.test.js.map +1 -1
  165. package/build/__tests__/unit/tap.test.js +2 -40
  166. package/build/__tests__/unit/tap.test.js.map +1 -1
  167. package/build/__tests__/unit/textEntry.test.js +0 -27
  168. package/build/__tests__/unit/textEntry.test.js.map +1 -1
  169. package/build/__tests__/unit/toolDescriptions.test.js +0 -40
  170. package/build/__tests__/unit/toolDescriptions.test.js.map +1 -1
  171. package/build/__tests__/unit/toolsJson.test.js +0 -10
  172. package/build/__tests__/unit/toolsJson.test.js.map +1 -1
  173. package/build/__tests__/unit/transportClassify.test.js +0 -20
  174. package/build/__tests__/unit/transportClassify.test.js.map +1 -1
  175. package/build/__tests__/unit/truncate.test.js +0 -5
  176. package/build/__tests__/unit/truncate.test.js.map +1 -1
  177. package/build/__tests__/unit/usageCache.test.js +0 -3
  178. package/build/__tests__/unit/usageCache.test.js.map +1 -1
  179. package/build/__tests__/unit/usageGate.test.js +1 -1
  180. package/build/__tests__/unit/usageGate.test.js.map +1 -1
  181. package/build/__tests__/unit/visibility.test.js +0 -8
  182. package/build/__tests__/unit/visibility.test.js.map +1 -1
  183. package/build/__tests__/unit/waitForMeasurements.test.js +2 -7
  184. package/build/__tests__/unit/waitForMeasurements.test.js.map +1 -1
  185. package/build/bin.js +0 -18
  186. package/build/bin.js.map +1 -1
  187. package/build/core/android.d.ts +0 -120
  188. package/build/core/android.d.ts.map +1 -1
  189. package/build/core/android.js +4 -259
  190. package/build/core/android.js.map +1 -1
  191. package/build/core/appContext.d.ts +0 -50
  192. package/build/core/appContext.d.ts.map +1 -1
  193. package/build/core/appContext.js +0 -50
  194. package/build/core/appContext.js.map +1 -1
  195. package/build/core/appDetection.d.ts +0 -16
  196. package/build/core/appDetection.d.ts.map +1 -1
  197. package/build/core/appDetection.js +0 -36
  198. package/build/core/appDetection.js.map +1 -1
  199. package/build/core/appRequest.d.ts +0 -12
  200. package/build/core/appRequest.d.ts.map +1 -1
  201. package/build/core/appRequest.js +0 -15
  202. package/build/core/appRequest.js.map +1 -1
  203. package/build/core/bufferConfig.d.ts +0 -2
  204. package/build/core/bufferConfig.d.ts.map +1 -1
  205. package/build/core/bufferConfig.js +0 -2
  206. package/build/core/bufferConfig.js.map +1 -1
  207. package/build/core/bundle.js +0 -40
  208. package/build/core/bundle.js.map +1 -1
  209. package/build/core/componentSearch.d.ts +0 -19
  210. package/build/core/componentSearch.d.ts.map +1 -1
  211. package/build/core/componentSearch.js +1 -22
  212. package/build/core/componentSearch.js.map +1 -1
  213. package/build/core/componentSource.d.ts +0 -21
  214. package/build/core/componentSource.d.ts.map +1 -1
  215. package/build/core/componentSource.js +0 -27
  216. package/build/core/componentSource.js.map +1 -1
  217. package/build/core/componentTree.js +0 -12
  218. package/build/core/componentTree.js.map +1 -1
  219. package/build/core/config.d.ts +0 -8
  220. package/build/core/config.d.ts.map +1 -1
  221. package/build/core/config.js +0 -10
  222. package/build/core/config.js.map +1 -1
  223. package/build/core/connection.d.ts +0 -76
  224. package/build/core/connection.d.ts.map +1 -1
  225. package/build/core/connection.js +15 -340
  226. package/build/core/connection.js.map +1 -1
  227. package/build/core/connectionState.d.ts +0 -78
  228. package/build/core/connectionState.d.ts.map +1 -1
  229. package/build/core/connectionState.js +4 -92
  230. package/build/core/connectionState.js.map +1 -1
  231. package/build/core/debugGlobals.js +0 -68
  232. package/build/core/debugGlobals.js.map +1 -1
  233. package/build/core/deviceDiscovery.d.ts +0 -5
  234. package/build/core/deviceDiscovery.d.ts.map +1 -1
  235. package/build/core/deviceDiscovery.js +0 -12
  236. package/build/core/deviceDiscovery.js.map +1 -1
  237. package/build/core/deviceResolver.d.ts +0 -10
  238. package/build/core/deviceResolver.d.ts.map +1 -1
  239. package/build/core/deviceResolver.js +0 -54
  240. package/build/core/deviceResolver.js.map +1 -1
  241. package/build/core/epochRender.d.ts +0 -12
  242. package/build/core/epochRender.d.ts.map +1 -1
  243. package/build/core/epochRender.js +0 -12
  244. package/build/core/epochRender.js.map +1 -1
  245. package/build/core/errorScreenParser.d.ts +0 -21
  246. package/build/core/errorScreenParser.d.ts.map +1 -1
  247. package/build/core/errorScreenParser.js +0 -50
  248. package/build/core/errorScreenParser.js.map +1 -1
  249. package/build/core/errors.d.ts +0 -15
  250. package/build/core/errors.d.ts.map +1 -1
  251. package/build/core/errors.js +0 -15
  252. package/build/core/errors.js.map +1 -1
  253. package/build/core/escapeNonAscii.d.ts +0 -9
  254. package/build/core/escapeNonAscii.d.ts.map +1 -1
  255. package/build/core/escapeNonAscii.js +1 -43
  256. package/build/core/escapeNonAscii.js.map +1 -1
  257. package/build/core/exec.d.ts +0 -12
  258. package/build/core/exec.d.ts.map +1 -1
  259. package/build/core/exec.js +2 -14
  260. package/build/core/exec.js.map +1 -1
  261. package/build/core/executor.js +0 -3
  262. package/build/core/executor.js.map +1 -1
  263. package/build/core/fastRefreshRecorder.js +0 -4
  264. package/build/core/fastRefreshRecorder.js.map +1 -1
  265. package/build/core/fastRefreshTools.js +0 -3
  266. package/build/core/fastRefreshTools.js.map +1 -1
  267. package/build/core/feedback.js +0 -4
  268. package/build/core/feedback.js.map +1 -1
  269. package/build/core/graphqlOperation.d.ts +13 -0
  270. package/build/core/graphqlOperation.d.ts.map +1 -0
  271. package/build/core/graphqlOperation.js +80 -0
  272. package/build/core/graphqlOperation.js.map +1 -0
  273. package/build/core/guides.d.ts +0 -10
  274. package/build/core/guides.d.ts.map +1 -1
  275. package/build/core/guides.js +0 -10
  276. package/build/core/guides.js.map +1 -1
  277. package/build/core/iconSemantics.d.ts +0 -15
  278. package/build/core/iconSemantics.d.ts.map +1 -1
  279. package/build/core/iconSemantics.js +0 -31
  280. package/build/core/iconSemantics.js.map +1 -1
  281. package/build/core/index.js +4 -47
  282. package/build/core/index.js.map +1 -1
  283. package/build/core/injected/visibility.d.ts +0 -30
  284. package/build/core/injected/visibility.d.ts.map +1 -1
  285. package/build/core/injected/visibility.js +0 -33
  286. package/build/core/injected/visibility.js.map +1 -1
  287. package/build/core/injectedFilters.d.ts +0 -28
  288. package/build/core/injectedFilters.d.ts.map +1 -1
  289. package/build/core/injectedFilters.js +0 -28
  290. package/build/core/injectedFilters.js.map +1 -1
  291. package/build/core/inputTarget.d.ts +1 -34
  292. package/build/core/inputTarget.d.ts.map +1 -1
  293. package/build/core/inputTarget.js +0 -26
  294. package/build/core/inputTarget.js.map +1 -1
  295. package/build/core/inputTargetTools.d.ts +0 -7
  296. package/build/core/inputTargetTools.d.ts.map +1 -1
  297. package/build/core/inputTargetTools.js +0 -7
  298. package/build/core/inputTargetTools.js.map +1 -1
  299. package/build/core/inspector.d.ts +0 -33
  300. package/build/core/inspector.d.ts.map +1 -1
  301. package/build/core/inspector.js +27 -40
  302. package/build/core/inspector.js.map +1 -1
  303. package/build/core/ios.d.ts +11 -122
  304. package/build/core/ios.d.ts.map +1 -1
  305. package/build/core/ios.js +32 -299
  306. package/build/core/ios.js.map +1 -1
  307. package/build/core/jsExecute.d.ts +0 -100
  308. package/build/core/jsExecute.d.ts.map +1 -1
  309. package/build/core/jsExecute.js +0 -261
  310. package/build/core/jsExecute.js.map +1 -1
  311. package/build/core/jsLogEvents.d.ts +0 -8
  312. package/build/core/jsLogEvents.d.ts.map +1 -1
  313. package/build/core/jsLogEvents.js +0 -8
  314. package/build/core/jsLogEvents.js.map +1 -1
  315. package/build/core/keyboardMetrics.js +0 -8
  316. package/build/core/keyboardMetrics.js.map +1 -1
  317. package/build/core/keyboardRaise.d.ts +0 -8
  318. package/build/core/keyboardRaise.d.ts.map +1 -1
  319. package/build/core/keyboardRaise.js +0 -23
  320. package/build/core/keyboardRaise.js.map +1 -1
  321. package/build/core/license.d.ts +0 -4
  322. package/build/core/license.d.ts.map +1 -1
  323. package/build/core/license.js +2 -55
  324. package/build/core/license.js.map +1 -1
  325. package/build/core/logDiagnosis.d.ts +0 -34
  326. package/build/core/logDiagnosis.d.ts.map +1 -1
  327. package/build/core/logDiagnosis.js +0 -15
  328. package/build/core/logDiagnosis.js.map +1 -1
  329. package/build/core/logEventFormat.d.ts +0 -1
  330. package/build/core/logEventFormat.d.ts.map +1 -1
  331. package/build/core/logEventFormat.js +0 -30
  332. package/build/core/logEventFormat.js.map +1 -1
  333. package/build/core/logEvents.d.ts +0 -54
  334. package/build/core/logEvents.d.ts.map +1 -1
  335. package/build/core/logEvents.js +0 -37
  336. package/build/core/logEvents.js.map +1 -1
  337. package/build/core/logGrouping.d.ts +0 -9
  338. package/build/core/logGrouping.d.ts.map +1 -1
  339. package/build/core/logGrouping.js +0 -17
  340. package/build/core/logGrouping.js.map +1 -1
  341. package/build/core/logOwnership.d.ts +0 -17
  342. package/build/core/logOwnership.d.ts.map +1 -1
  343. package/build/core/logOwnership.js +0 -34
  344. package/build/core/logOwnership.js.map +1 -1
  345. package/build/core/logRelevance.d.ts +0 -8
  346. package/build/core/logRelevance.d.ts.map +1 -1
  347. package/build/core/logRelevance.js +0 -15
  348. package/build/core/logRelevance.js.map +1 -1
  349. package/build/core/logSourceAndroid.d.ts +0 -8
  350. package/build/core/logSourceAndroid.d.ts.map +1 -1
  351. package/build/core/logSourceAndroid.js +0 -11
  352. package/build/core/logSourceAndroid.js.map +1 -1
  353. package/build/core/logSourceIos.d.ts +0 -8
  354. package/build/core/logSourceIos.d.ts.map +1 -1
  355. package/build/core/logSourceIos.js +1 -24
  356. package/build/core/logSourceIos.js.map +1 -1
  357. package/build/core/logbox.d.ts +0 -30
  358. package/build/core/logbox.d.ts.map +1 -1
  359. package/build/core/logbox.js +0 -43
  360. package/build/core/logbox.js.map +1 -1
  361. package/build/core/logs.d.ts +0 -6
  362. package/build/core/logs.d.ts.map +1 -1
  363. package/build/core/logs.js +0 -19
  364. package/build/core/logs.js.map +1 -1
  365. package/build/core/metro.d.ts +0 -14
  366. package/build/core/metro.d.ts.map +1 -1
  367. package/build/core/metro.js +1 -32
  368. package/build/core/metro.js.map +1 -1
  369. package/build/core/moduleRegistry.d.ts +0 -17
  370. package/build/core/moduleRegistry.d.ts.map +1 -1
  371. package/build/core/moduleRegistry.js +0 -17
  372. package/build/core/moduleRegistry.js.map +1 -1
  373. package/build/core/nativeInputValue.d.ts +0 -29
  374. package/build/core/nativeInputValue.d.ts.map +1 -1
  375. package/build/core/nativeInputValue.js +0 -18
  376. package/build/core/nativeInputValue.js.map +1 -1
  377. package/build/core/nativeLogs.d.ts +0 -47
  378. package/build/core/nativeLogs.d.ts.map +1 -1
  379. package/build/core/nativeLogs.js +0 -82
  380. package/build/core/nativeLogs.js.map +1 -1
  381. package/build/core/nativeOnlyHints.js +0 -4
  382. package/build/core/nativeOnlyHints.js.map +1 -1
  383. package/build/core/navigate.d.ts +0 -15
  384. package/build/core/navigate.d.ts.map +1 -1
  385. package/build/core/navigate.js +0 -22
  386. package/build/core/navigate.js.map +1 -1
  387. package/build/core/navigation.d.ts +0 -60
  388. package/build/core/navigation.d.ts.map +1 -1
  389. package/build/core/navigation.js +0 -60
  390. package/build/core/navigation.js.map +1 -1
  391. package/build/core/network.d.ts +0 -5
  392. package/build/core/network.d.ts.map +1 -1
  393. package/build/core/network.js +10 -31
  394. package/build/core/network.js.map +1 -1
  395. package/build/core/networkInterceptor.d.ts +0 -19
  396. package/build/core/networkInterceptor.d.ts.map +1 -1
  397. package/build/core/networkInterceptor.js +3 -27
  398. package/build/core/networkInterceptor.js.map +1 -1
  399. package/build/core/ocr.d.ts +0 -31
  400. package/build/core/ocr.d.ts.map +1 -1
  401. package/build/core/ocr.js +1 -71
  402. package/build/core/ocr.js.map +1 -1
  403. package/build/core/paths.js +0 -1
  404. package/build/core/paths.js.map +1 -1
  405. package/build/core/posthog.js +0 -7
  406. package/build/core/posthog.js.map +1 -1
  407. package/build/core/pressables.d.ts +0 -25
  408. package/build/core/pressables.d.ts.map +1 -1
  409. package/build/core/pressables.js +0 -37
  410. package/build/core/pressables.js.map +1 -1
  411. package/build/core/probe.d.ts +0 -9
  412. package/build/core/probe.d.ts.map +1 -1
  413. package/build/core/probe.js +0 -9
  414. package/build/core/probe.js.map +1 -1
  415. package/build/core/projectMemory.d.ts +0 -2
  416. package/build/core/projectMemory.d.ts.map +1 -1
  417. package/build/core/projectMemory.js +2 -7
  418. package/build/core/projectMemory.js.map +1 -1
  419. package/build/core/projectStore.d.ts +0 -18
  420. package/build/core/projectStore.d.ts.map +1 -1
  421. package/build/core/projectStore.js +0 -19
  422. package/build/core/projectStore.js.map +1 -1
  423. package/build/core/promiseHandles.d.ts +0 -13
  424. package/build/core/promiseHandles.d.ts.map +1 -1
  425. package/build/core/promiseHandles.js +0 -25
  426. package/build/core/promiseHandles.js.map +1 -1
  427. package/build/core/register.js +0 -44
  428. package/build/core/register.js.map +1 -1
  429. package/build/core/rnGlobalsBootstrap.d.ts +0 -13
  430. package/build/core/rnGlobalsBootstrap.d.ts.map +1 -1
  431. package/build/core/rnGlobalsBootstrap.js +0 -22
  432. package/build/core/rnGlobalsBootstrap.js.map +1 -1
  433. package/build/core/routeHistory.d.ts +24 -0
  434. package/build/core/routeHistory.d.ts.map +1 -0
  435. package/build/core/routeHistory.js +186 -0
  436. package/build/core/routeHistory.js.map +1 -0
  437. package/build/core/screenLayout.d.ts +0 -11
  438. package/build/core/screenLayout.d.ts.map +1 -1
  439. package/build/core/screenLayout.js +24 -61
  440. package/build/core/screenLayout.js.map +1 -1
  441. package/build/core/screenSpace.d.ts +32 -44
  442. package/build/core/screenSpace.d.ts.map +1 -1
  443. package/build/core/screenSpace.js +80 -46
  444. package/build/core/screenSpace.js.map +1 -1
  445. package/build/core/screenSpaceDevice.d.ts +0 -8
  446. package/build/core/screenSpaceDevice.d.ts.map +1 -1
  447. package/build/core/screenSpaceDevice.js +31 -14
  448. package/build/core/screenSpaceDevice.js.map +1 -1
  449. package/build/core/screenState.d.ts +2 -74
  450. package/build/core/screenState.d.ts.map +1 -1
  451. package/build/core/screenState.js +204 -145
  452. package/build/core/screenState.js.map +1 -1
  453. package/build/core/sdkBridge.js +0 -8
  454. package/build/core/sdkBridge.js.map +1 -1
  455. package/build/core/sdkMirrorPoller.d.ts +0 -18
  456. package/build/core/sdkMirrorPoller.d.ts.map +1 -1
  457. package/build/core/sdkMirrorPoller.js +0 -47
  458. package/build/core/sdkMirrorPoller.js.map +1 -1
  459. package/build/core/selectionBuffer.d.ts +0 -6
  460. package/build/core/selectionBuffer.d.ts.map +1 -1
  461. package/build/core/selectionBuffer.js +0 -5
  462. package/build/core/selectionBuffer.js.map +1 -1
  463. package/build/core/signedVerdict.js +0 -6
  464. package/build/core/signedVerdict.js.map +1 -1
  465. package/build/core/state.d.ts +0 -31
  466. package/build/core/state.d.ts.map +1 -1
  467. package/build/core/state.js +0 -57
  468. package/build/core/state.js.map +1 -1
  469. package/build/core/symbolicate.js +0 -11
  470. package/build/core/symbolicate.js.map +1 -1
  471. package/build/core/telemetry.d.ts +0 -47
  472. package/build/core/telemetry.d.ts.map +1 -1
  473. package/build/core/telemetry.js +1 -173
  474. package/build/core/telemetry.js.map +1 -1
  475. package/build/core/textEntry.d.ts +0 -34
  476. package/build/core/textEntry.d.ts.map +1 -1
  477. package/build/core/textEntry.js +0 -73
  478. package/build/core/textEntry.js.map +1 -1
  479. package/build/core/toolHelpers.d.ts +0 -12
  480. package/build/core/toolHelpers.d.ts.map +1 -1
  481. package/build/core/toolHelpers.js +2 -47
  482. package/build/core/toolHelpers.js.map +1 -1
  483. package/build/core/truncate.d.ts +0 -17
  484. package/build/core/truncate.d.ts.map +1 -1
  485. package/build/core/truncate.js +0 -32
  486. package/build/core/truncate.js.map +1 -1
  487. package/build/core/types.d.ts +0 -6
  488. package/build/core/types.d.ts.map +1 -1
  489. package/build/core/usageCache.js +0 -12
  490. package/build/core/usageCache.js.map +1 -1
  491. package/build/index.js +0 -18
  492. package/build/index.js.map +1 -1
  493. package/build/pro/coordinateMiss.d.ts +0 -30
  494. package/build/pro/coordinateMiss.d.ts.map +1 -1
  495. package/build/pro/coordinateMiss.js +0 -17
  496. package/build/pro/coordinateMiss.js.map +1 -1
  497. package/build/pro/overlayGuard.d.ts +27 -0
  498. package/build/pro/overlayGuard.d.ts.map +1 -0
  499. package/build/pro/overlayGuard.js +103 -0
  500. package/build/pro/overlayGuard.js.map +1 -0
  501. package/build/pro/screenshot-diff.js +4 -6
  502. package/build/pro/screenshot-diff.js.map +1 -1
  503. package/build/pro/tap.d.ts +0 -55
  504. package/build/pro/tap.d.ts.map +1 -1
  505. package/build/pro/tap.js +72 -316
  506. package/build/pro/tap.js.map +1 -1
  507. package/build/pro/usageGate.js +0 -9
  508. package/build/pro/usageGate.js.map +1 -1
  509. package/build/pro/usageNotifications.js +1 -13
  510. package/build/pro/usageNotifications.js.map +1 -1
  511. package/build/pro/verifyAction.d.ts +0 -13
  512. package/build/pro/verifyAction.d.ts.map +1 -1
  513. package/build/pro/verifyAction.js +0 -45
  514. package/build/pro/verifyAction.js.map +1 -1
  515. package/build/tools/_deviceArg.d.ts +0 -35
  516. package/build/tools/_deviceArg.d.ts.map +1 -1
  517. package/build/tools/_deviceArg.js +0 -35
  518. package/build/tools/_deviceArg.js.map +1 -1
  519. package/build/tools/accountTools.js +2 -2
  520. package/build/tools/accountTools.js.map +1 -1
  521. package/build/tools/bundleTools.js +0 -16
  522. package/build/tools/bundleTools.js.map +1 -1
  523. package/build/tools/componentTools.d.ts.map +1 -1
  524. package/build/tools/componentTools.js +47 -53
  525. package/build/tools/componentTools.js.map +1 -1
  526. package/build/tools/connectionTools.js +1 -59
  527. package/build/tools/connectionTools.js.map +1 -1
  528. package/build/tools/deviceTools.js +0 -11
  529. package/build/tools/deviceTools.js.map +1 -1
  530. package/build/tools/executionTools.js +1 -18
  531. package/build/tools/executionTools.js.map +1 -1
  532. package/build/tools/interactionTools.d.ts +0 -10
  533. package/build/tools/interactionTools.d.ts.map +1 -1
  534. package/build/tools/interactionTools.js +0 -57
  535. package/build/tools/interactionTools.js.map +1 -1
  536. package/build/tools/logTools.d.ts +0 -13
  537. package/build/tools/logTools.d.ts.map +1 -1
  538. package/build/tools/logTools.js +2 -126
  539. package/build/tools/logTools.js.map +1 -1
  540. package/build/tools/metaTools.js +0 -10
  541. package/build/tools/metaTools.js.map +1 -1
  542. package/build/tools/networkTools.js +4 -43
  543. package/build/tools/networkTools.js.map +1 -1
  544. package/build/tools/requestTools.js +0 -5
  545. package/build/tools/requestTools.js.map +1 -1
  546. package/build/tools/screenshotTools.js +5 -111
  547. package/build/tools/screenshotTools.js.map +1 -1
  548. package/package.json +2 -2
  549. package/tools.json +1 -0
@@ -4,19 +4,10 @@ import os from "os";
4
4
  import sharp from "sharp";
5
5
  import { notifyDriverMissing } from "./logbox.js";
6
6
  import { execAsync } from "./exec.js";
7
- // XML parsing for uiautomator dump
8
7
  import { XMLParser } from "fast-xml-parser";
9
- // ADB command timeout in milliseconds
10
8
  const ADB_TIMEOUT = 30000;
11
- // Module-level cache for ADB availability — checked once per session.
12
- // `null` = unchecked, boolean = decided. Reset only via `resetAdbAvailabilityCache()` (tests).
13
9
  let adbAvailableCache = null;
14
10
  let adbPathFixApplied = false;
15
- /**
16
- * Standard locations where the Android SDK platform-tools may live when adb is
17
- * installed but not on the spawned process's PATH (very common on macOS where
18
- * users add platform-tools only to ~/.zshrc, which GUI-spawned processes don't read).
19
- */
20
11
  function candidateAdbDirs() {
21
12
  const dirs = [];
22
13
  const env = process.env;
@@ -40,19 +31,6 @@ function candidateAdbDirs() {
40
31
  function adbBinaryName() {
41
32
  return process.platform === "win32" ? "adb.exe" : "adb";
42
33
  }
43
- /**
44
- * Check if ADB is reachable. Caches the result for the lifetime of the process.
45
- *
46
- * Resolution order:
47
- * 1. `adb version` against the inherited PATH.
48
- * 2. Standard SDK install paths (ANDROID_HOME, ~/Library/Android/sdk/..., etc).
49
- * If found, prepend the directory to process.env.PATH so subsequent bare
50
- * `adb` invocations work without any call-site changes.
51
- *
52
- * The recovery path covers the common case of macOS users with Android Studio
53
- * installed but adb missing from PATH because ~/.zshrc isn't sourced by GUI-spawned
54
- * processes (Claude Code, VS Code MCP, etc).
55
- */
56
34
  export async function isAdbAvailable() {
57
35
  if (adbAvailableCache !== null)
58
36
  return adbAvailableCache;
@@ -62,7 +40,6 @@ export async function isAdbAvailable() {
62
40
  return true;
63
41
  }
64
42
  catch {
65
- // Fall through to path discovery below.
66
43
  }
67
44
  if (!adbPathFixApplied) {
68
45
  for (const dir of candidateAdbDirs()) {
@@ -78,7 +55,6 @@ export async function isAdbAvailable() {
78
55
  return true;
79
56
  }
80
57
  catch {
81
- // Found the binary but it didn't run — try next candidate.
82
58
  continue;
83
59
  }
84
60
  }
@@ -86,27 +62,17 @@ export async function isAdbAvailable() {
86
62
  adbAvailableCache = false;
87
63
  return false;
88
64
  }
89
- /**
90
- * Test-only: clear the ADB availability cache so the next call re-probes.
91
- */
92
65
  export function resetAdbAvailabilityCache() {
93
66
  adbAvailableCache = null;
94
67
  adbPathFixApplied = false;
95
68
  }
96
69
  const ADB_MISSING_ERROR = "ADB is not installed or not in PATH. To fix:\n1. Install Android SDK Platform Tools: https://developer.android.com/tools/releases/platform-tools\n2. Add to PATH: export PATH=$PATH:~/Library/Android/sdk/platform-tools\n3. Verify: run 'adb devices' in terminal";
97
- /**
98
- * Check ADB availability and push a LogBox notification if missing.
99
- * Returns an AdbResult error if ADB is unavailable, or null if ready.
100
- */
101
70
  async function requireAdb() {
102
71
  if (await isAdbAvailable())
103
72
  return null;
104
73
  notifyDriverMissing("android");
105
74
  return { success: false, error: ADB_MISSING_ERROR };
106
75
  }
107
- /**
108
- * List connected Android devices
109
- */
110
76
  export async function listAndroidDevices() {
111
77
  try {
112
78
  const adbMissing = await requireAdb();
@@ -114,7 +80,6 @@ export async function listAndroidDevices() {
114
80
  return adbMissing;
115
81
  const { stdout } = await execAsync("adb devices -l", { timeout: ADB_TIMEOUT });
116
82
  const lines = stdout.trim().split("\n");
117
- // Skip the "List of devices attached" header
118
83
  const deviceLines = lines.slice(1).filter((line) => line.trim().length > 0);
119
84
  if (deviceLines.length === 0) {
120
85
  return {
@@ -127,7 +92,6 @@ export async function listAndroidDevices() {
127
92
  const id = parts[0];
128
93
  const status = parts[1];
129
94
  const device = { id, status };
130
- // Parse additional info like product:xxx model:xxx device:xxx transport_id:xxx
131
95
  for (let i = 2; i < parts.length; i++) {
132
96
  const [key, value] = parts[i].split(":");
133
97
  if (key === "product")
@@ -164,9 +128,6 @@ export async function listAndroidDevices() {
164
128
  };
165
129
  }
166
130
  }
167
- /**
168
- * Get the first connected Android device ID
169
- */
170
131
  export async function getDefaultAndroidDevice() {
171
132
  try {
172
133
  const { stdout } = await execAsync("adb devices", { timeout: ADB_TIMEOUT });
@@ -184,19 +145,12 @@ export async function getDefaultAndroidDevice() {
184
145
  return null;
185
146
  }
186
147
  }
187
- /**
188
- * Locate the `emulator` binary. Returns the command string to invoke it
189
- * (either bare "emulator" if it's on PATH, or a quoted absolute path).
190
- * Returns null when the binary cannot be located. Mirrors `isAdbAvailable`'s
191
- * PATH → ANDROID_HOME → common-install-paths discovery order.
192
- */
193
148
  async function findEmulatorBinary() {
194
149
  try {
195
150
  await execAsync("emulator -help", { timeout: 3000 });
196
151
  return "emulator";
197
152
  }
198
153
  catch {
199
- // not on PATH — try standard install locations
200
154
  }
201
155
  const env = process.env;
202
156
  const candidates = [];
@@ -211,20 +165,10 @@ async function findEmulatorBinary() {
211
165
  return `"${candidate}"`;
212
166
  }
213
167
  catch {
214
- // try next
215
168
  }
216
169
  }
217
170
  return null;
218
171
  }
219
- /**
220
- * List all Android Virtual Devices defined on the host machine, regardless of
221
- * whether they are currently running.
222
- *
223
- * Returns `[]` when adb is missing, the emulator binary cannot be located, or
224
- * the listing fails. Callers should treat that as "no inventory available"
225
- * rather than an error so the surrounding tool can still surface other
226
- * platforms.
227
- */
228
172
  export async function getAndroidEmulatorAvds() {
229
173
  const adbMissing = await requireAdb();
230
174
  if (adbMissing)
@@ -243,22 +187,13 @@ export async function getAndroidEmulatorAvds() {
243
187
  return [];
244
188
  }
245
189
  }
246
- /**
247
- * Map a running emulator's AVD name to its adb serial (e.g. "emulator-5554").
248
- *
249
- * Strategy: list adb devices, filter to `emulator-NNNN` serials, then call
250
- * `adb -s <serial> emu avd name` per serial until one matches the requested
251
- * AVD name. Returns `null` if no running emulator matches or if adb is
252
- * unavailable. This is the slow path for the resolver — callers should prefer
253
- * the cached registry entry first.
254
- */
255
190
  export async function getAdbIdForAvd(avdName) {
256
191
  const adbMissing = await requireAdb();
257
192
  if (adbMissing)
258
193
  return null;
259
194
  try {
260
195
  const { stdout: devicesOut } = await execAsync("adb devices", { timeout: ADB_TIMEOUT });
261
- const lines = devicesOut.trim().split("\n").slice(1); // skip "List of devices attached" header
196
+ const lines = devicesOut.trim().split("\n").slice(1);
262
197
  const emulatorSerials = lines
263
198
  .map((line) => line.trim().split(/\s+/)[0])
264
199
  .filter((id) => /^emulator-\d+$/.test(id));
@@ -273,7 +208,6 @@ export async function getAdbIdForAvd(avdName) {
273
208
  return serial;
274
209
  }
275
210
  catch {
276
- // skip this serial, try next
277
211
  }
278
212
  }
279
213
  return null;
@@ -282,15 +216,9 @@ export async function getAdbIdForAvd(avdName) {
282
216
  return null;
283
217
  }
284
218
  }
285
- /**
286
- * Build device selector for ADB command
287
- */
288
219
  function buildDeviceArg(deviceId) {
289
220
  return deviceId ? `-s ${deviceId}` : "";
290
221
  }
291
- /**
292
- * Take a screenshot from an Android device
293
- */
294
222
  export async function androidScreenshot(outputPath, deviceId, signal) {
295
223
  try {
296
224
  const adbMissing = await requireAdb();
@@ -304,29 +232,22 @@ export async function androidScreenshot(outputPath, deviceId, signal) {
304
232
  };
305
233
  }
306
234
  const deviceArg = buildDeviceArg(device);
307
- // Generate output path if not provided
308
235
  const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
309
236
  const finalOutputPath = outputPath || path.join(os.tmpdir(), `android-screenshot-${timestamp}.png`);
310
- // Capture screenshot on device
311
237
  const remotePath = "/sdcard/screenshot-temp.png";
312
238
  await execAsync(`adb ${deviceArg} shell screencap -p ${remotePath}`, {
313
239
  timeout: ADB_TIMEOUT,
314
240
  signal
315
241
  });
316
- // Pull screenshot to local machine
317
242
  await execAsync(`adb ${deviceArg} pull ${remotePath} "${finalOutputPath}"`, {
318
243
  timeout: ADB_TIMEOUT,
319
244
  signal
320
245
  });
321
- // Clean up remote file
322
246
  await execAsync(`adb ${deviceArg} shell rm ${remotePath}`, {
323
247
  timeout: ADB_TIMEOUT,
324
248
  signal
325
249
  }).catch(() => {
326
- // Ignore cleanup errors
327
250
  });
328
- // Resize image if needed (API limit: 2000px max for multi-image requests)
329
- // Return scale factor so AI can convert image coords to device coords
330
251
  const MAX_DIMENSION = 2000;
331
252
  const image = sharp(finalOutputPath);
332
253
  const metadata = await image.metadata();
@@ -335,7 +256,6 @@ export async function androidScreenshot(outputPath, deviceId, signal) {
335
256
  let imageData;
336
257
  let scaleFactor = 1;
337
258
  if (originalWidth > MAX_DIMENSION || originalHeight > MAX_DIMENSION) {
338
- // Calculate scale to fit within MAX_DIMENSION
339
259
  scaleFactor = Math.max(originalWidth, originalHeight) / MAX_DIMENSION;
340
260
  imageData = await image
341
261
  .resize(MAX_DIMENSION, MAX_DIMENSION, {
@@ -366,15 +286,11 @@ export async function androidScreenshot(outputPath, deviceId, signal) {
366
286
  };
367
287
  }
368
288
  }
369
- /**
370
- * Install an APK on an Android device
371
- */
372
289
  export async function androidInstallApp(apkPath, deviceId, options) {
373
290
  try {
374
291
  const adbMissing = await requireAdb();
375
292
  if (adbMissing)
376
293
  return adbMissing;
377
- // Verify APK exists
378
294
  if (!existsSync(apkPath)) {
379
295
  return {
380
296
  success: false,
@@ -389,15 +305,13 @@ export async function androidInstallApp(apkPath, deviceId, options) {
389
305
  };
390
306
  }
391
307
  const deviceArg = buildDeviceArg(device);
392
- // Build install flags
393
308
  const flags = [];
394
309
  if (options?.replace)
395
310
  flags.push("-r");
396
311
  if (options?.grantPermissions)
397
312
  flags.push("-g");
398
313
  const flagsStr = flags.length > 0 ? flags.join(" ") + " " : "";
399
- const { stdout, stderr } = await execAsync(`adb ${deviceArg} install ${flagsStr}"${apkPath}"`, { timeout: 120000 } // 2 minute timeout for install
400
- );
314
+ const { stdout, stderr } = await execAsync(`adb ${deviceArg} install ${flagsStr}"${apkPath}"`, { timeout: 120000 });
401
315
  const output = stdout + stderr;
402
316
  if (output.includes("Success")) {
403
317
  return {
@@ -419,9 +333,6 @@ export async function androidInstallApp(apkPath, deviceId, options) {
419
333
  };
420
334
  }
421
335
  }
422
- /**
423
- * Launch an app on an Android device
424
- */
425
336
  export async function androidLaunchApp(packageName, activityName, deviceId) {
426
337
  try {
427
338
  const adbMissing = await requireAdb();
@@ -437,16 +348,13 @@ export async function androidLaunchApp(packageName, activityName, deviceId) {
437
348
  const deviceArg = buildDeviceArg(device);
438
349
  let command;
439
350
  if (activityName) {
440
- // Launch specific activity
441
351
  command = `adb ${deviceArg} shell am start -n ${packageName}/${activityName}`;
442
352
  }
443
353
  else {
444
- // Launch main/launcher activity
445
354
  command = `adb ${deviceArg} shell monkey -p ${packageName} -c android.intent.category.LAUNCHER 1`;
446
355
  }
447
356
  const { stdout, stderr } = await execAsync(command, { timeout: ADB_TIMEOUT });
448
357
  const output = stdout + stderr;
449
- // Check for errors
450
358
  if (output.includes("Error") || output.includes("Exception")) {
451
359
  return {
452
360
  success: false,
@@ -465,9 +373,6 @@ export async function androidLaunchApp(packageName, activityName, deviceId) {
465
373
  };
466
374
  }
467
375
  }
468
- /**
469
- * Get list of installed packages on the device
470
- */
471
376
  export async function androidListPackages(deviceId, filter) {
472
377
  try {
473
378
  const adbMissing = await requireAdb();
@@ -511,12 +416,6 @@ export async function androidListPackages(deviceId, filter) {
511
416
  };
512
417
  }
513
418
  }
514
- // ============================================================================
515
- // UI Input Functions (Phase 2)
516
- // ============================================================================
517
- /**
518
- * Common key event codes for Android
519
- */
520
419
  export const ANDROID_KEY_EVENTS = {
521
420
  HOME: 3,
522
421
  BACK: 4,
@@ -541,9 +440,6 @@ export const ANDROID_KEY_EVENTS = {
541
440
  APP_SWITCH: 187,
542
441
  ESCAPE: 111
543
442
  };
544
- /**
545
- * Tap at coordinates on an Android device
546
- */
547
443
  export async function androidTap(x, y, deviceId) {
548
444
  try {
549
445
  const adbMissing = await requireAdb();
@@ -572,9 +468,6 @@ export async function androidTap(x, y, deviceId) {
572
468
  };
573
469
  }
574
470
  }
575
- /**
576
- * Long press at coordinates on an Android device
577
- */
578
471
  export async function androidLongPress(x, y, durationMs = 1000, deviceId) {
579
472
  try {
580
473
  const adbMissing = await requireAdb();
@@ -588,7 +481,6 @@ export async function androidLongPress(x, y, durationMs = 1000, deviceId) {
588
481
  };
589
482
  }
590
483
  const deviceArg = buildDeviceArg(device);
591
- // Long press is implemented as a swipe from the same point to the same point
592
484
  const xRounded = Math.round(x);
593
485
  const yRounded = Math.round(y);
594
486
  await execAsync(`adb ${deviceArg} shell input swipe ${xRounded} ${yRounded} ${xRounded} ${yRounded} ${durationMs}`, { timeout: ADB_TIMEOUT + durationMs });
@@ -604,9 +496,6 @@ export async function androidLongPress(x, y, durationMs = 1000, deviceId) {
604
496
  };
605
497
  }
606
498
  }
607
- /**
608
- * Swipe on an Android device
609
- */
610
499
  export async function androidSwipe(startX, startY, endX, endY, durationMs = 300, deviceId) {
611
500
  try {
612
501
  const adbMissing = await requireAdb();
@@ -637,12 +526,6 @@ export async function androidSwipe(startX, startY, endX, endY, durationMs = 300,
637
526
  };
638
527
  }
639
528
  }
640
- /**
641
- * Input text on an Android device
642
- *
643
- * ADB input text has limitations with special characters.
644
- * This function handles escaping properly for URLs, emails, and special strings.
645
- */
646
529
  export async function androidInputText(text, deviceId) {
647
530
  try {
648
531
  const adbMissing = await requireAdb();
@@ -656,21 +539,15 @@ export async function androidInputText(text, deviceId) {
656
539
  };
657
540
  }
658
541
  const deviceArg = buildDeviceArg(device);
659
- // For complex strings with special characters, type character by character
660
- // using key events for reliability
661
542
  const hasComplexChars = /[/:?=&#@%+]/.test(text);
662
543
  if (hasComplexChars) {
663
- // Use character-by-character input for strings with special chars
664
- // This is slower but more reliable for URLs, emails, etc.
665
544
  for (const char of text) {
666
545
  let keyCmd;
667
- // Map special characters to their escaped form or use direct input
668
546
  switch (char) {
669
547
  case " ":
670
548
  keyCmd = `adb ${deviceArg} shell input text "%s"`;
671
549
  break;
672
550
  case "'":
673
- // Single quote needs special handling
674
551
  keyCmd = `adb ${deviceArg} shell input text "\\'"`;
675
552
  break;
676
553
  case '"':
@@ -707,13 +584,9 @@ export async function androidInputText(text, deviceId) {
707
584
  keyCmd = `adb ${deviceArg} shell input text "\\\`"`;
708
585
  break;
709
586
  case "#":
710
- // # is a shell comment character — single quotes don't prevent interpretation
711
- // on some Android shell versions, so use backslash escaping in double quotes
712
587
  keyCmd = `adb ${deviceArg} shell input text "\\#"`;
713
588
  break;
714
589
  default:
715
- // For most characters, wrap in single quotes to prevent shell interpretation
716
- // Single quotes preserve literal meaning of all characters except single quote itself
717
590
  keyCmd = `adb ${deviceArg} shell input text '${char}'`;
718
591
  }
719
592
  await execAsync(keyCmd, { timeout: 5000 });
@@ -723,8 +596,6 @@ export async function androidInputText(text, deviceId) {
723
596
  result: `Typed: "${text}"`
724
597
  };
725
598
  }
726
- // For simple alphanumeric strings, use the faster bulk input
727
- // Escape basic special characters
728
599
  const escapedText = text
729
600
  .replace(/\\/g, "\\\\")
730
601
  .replace(/"/g, '\\"')
@@ -747,9 +618,6 @@ export async function androidInputText(text, deviceId) {
747
618
  };
748
619
  }
749
620
  }
750
- /**
751
- * Send a key event to an Android device
752
- */
753
621
  export async function androidKeyEvent(keyCode, deviceId) {
754
622
  try {
755
623
  const adbMissing = await requireAdb();
@@ -763,7 +631,6 @@ export async function androidKeyEvent(keyCode, deviceId) {
763
631
  };
764
632
  }
765
633
  const deviceArg = buildDeviceArg(device);
766
- // Resolve key code from name if needed
767
634
  const resolvedKeyCode = typeof keyCode === "string" ? ANDROID_KEY_EVENTS[keyCode] : keyCode;
768
635
  if (resolvedKeyCode === undefined) {
769
636
  return {
@@ -774,7 +641,6 @@ export async function androidKeyEvent(keyCode, deviceId) {
774
641
  await execAsync(`adb ${deviceArg} shell input keyevent ${resolvedKeyCode}`, {
775
642
  timeout: ADB_TIMEOUT
776
643
  });
777
- // Get key name for display
778
644
  const keyName = typeof keyCode === "string"
779
645
  ? keyCode
780
646
  : Object.entries(ANDROID_KEY_EVENTS).find(([_, v]) => v === keyCode)?.[0] ||
@@ -791,9 +657,6 @@ export async function androidKeyEvent(keyCode, deviceId) {
791
657
  };
792
658
  }
793
659
  }
794
- /**
795
- * Parse bounds string like "[0,0][1080,1920]" to AndroidUIElement bounds
796
- */
797
660
  function parseBoundsForUIElement(boundsStr) {
798
661
  const match = boundsStr.match(/\[(\d+),(\d+)\]\[(\d+),(\d+)\]/);
799
662
  if (!match)
@@ -811,19 +674,14 @@ function parseBoundsForUIElement(boundsStr) {
811
674
  height: bottom - top
812
675
  };
813
676
  }
814
- /**
815
- * Parse uiautomator XML dump into element array
816
- */
817
677
  function parseUIAutomatorXML(xml) {
818
678
  const elements = [];
819
- // Match all node elements with their attributes
820
679
  const nodeRegex = /<node\s+([^>]+)\/?>|<node\s+([^>]+)>/g;
821
680
  let match;
822
681
  while ((match = nodeRegex.exec(xml)) !== null) {
823
682
  const attrStr = match[1] || match[2];
824
683
  if (!attrStr)
825
684
  continue;
826
- // Extract attributes
827
685
  const getAttr = (name) => {
828
686
  const attrMatch = attrStr.match(new RegExp(`${name}="([^"]*)"`));
829
687
  return attrMatch ? attrMatch[1] : "";
@@ -852,23 +710,11 @@ function parseUIAutomatorXML(xml) {
852
710
  }
853
711
  return elements;
854
712
  }
855
- /**
856
- * Match element against find options
857
- */
858
- /**
859
- * Check if an element's center is within the screen viewport.
860
- * Filters out off-screen elements in scroll views, pagers, etc.
861
- */
862
713
  function isAndroidElementInViewport(element, screenWidth, screenHeight) {
863
714
  const { center } = element;
864
715
  return center.x >= 0 && center.x <= screenWidth && center.y >= 0 && center.y <= screenHeight;
865
716
  }
866
- /**
867
- * Extract screen dimensions from the uiautomator XML.
868
- * The root hierarchy node's bounds represent the screen size.
869
- */
870
717
  function extractAndroidScreenSize(rawXml) {
871
- // Match the first node's bounds (root element = screen)
872
718
  const match = rawXml.match(/<(?:hierarchy|node)[^>]*bounds="\[0,0\]\[(\d+),(\d+)\]"/);
873
719
  if (match) {
874
720
  return { width: parseInt(match[1], 10), height: parseInt(match[2], 10) };
@@ -893,16 +739,12 @@ function matchesElement(element, options) {
893
739
  return false;
894
740
  }
895
741
  if (options.resourceId !== undefined) {
896
- // Support both full "com.app:id/button" and short "button" forms
897
742
  const shortId = element.resourceId.split("/").pop() || "";
898
743
  if (element.resourceId !== options.resourceId && shortId !== options.resourceId)
899
744
  return false;
900
745
  }
901
746
  return true;
902
747
  }
903
- /**
904
- * Get UI accessibility tree from Android device using uiautomator
905
- */
906
748
  export async function androidGetUITree(deviceId, signal) {
907
749
  try {
908
750
  const adbMissing = await requireAdb();
@@ -916,21 +758,15 @@ export async function androidGetUITree(deviceId, signal) {
916
758
  };
917
759
  }
918
760
  const deviceArg = buildDeviceArg(device);
919
- // Dump UI hierarchy to device. The `signal` is passed so a strategy-level
920
- // timeout in tap.ts can SIGKILL the host adb process — the device-side
921
- // uiautomator dump is independent and finishes silently, but we stop
922
- // waiting on the ADB channel so the next strategy can use it.
923
761
  const remotePath = "/sdcard/ui_dump.xml";
924
762
  await execAsync(`adb ${deviceArg} shell uiautomator dump ${remotePath}`, {
925
763
  timeout: ADB_TIMEOUT,
926
764
  signal
927
765
  });
928
- // Read the XML content
929
766
  const { stdout } = await execAsync(`adb ${deviceArg} shell cat ${remotePath}`, {
930
767
  timeout: ADB_TIMEOUT,
931
768
  signal
932
769
  });
933
- // Clean up remote file
934
770
  await execAsync(`adb ${deviceArg} shell rm ${remotePath}`, {
935
771
  timeout: ADB_TIMEOUT,
936
772
  signal
@@ -951,7 +787,6 @@ export async function androidGetUITree(deviceId, signal) {
951
787
  }
952
788
  export async function androidFindElement(options, deviceId, signal, tree) {
953
789
  try {
954
- // Validate that at least one search criteria is provided
955
790
  if (!options.text && !options.textContains && !options.contentDesc &&
956
791
  !options.contentDescContains && !options.resourceId) {
957
792
  return {
@@ -960,9 +795,6 @@ export async function androidFindElement(options, deviceId, signal, tree) {
960
795
  error: "At least one search criteria (text, textContains, contentDesc, contentDescContains, or resourceId) must be provided"
961
796
  };
962
797
  }
963
- // A caller that already dumped the hierarchy can pass it in — uiautomator
964
- // dumps are the single most expensive step of an Android accessibility
965
- // tap, and the tap strategy runs two passes over the same screen.
966
798
  const treeResult = tree ?? (await androidGetUITree(deviceId, signal));
967
799
  if (!treeResult.success || !treeResult.elements) {
968
800
  return {
@@ -971,15 +803,11 @@ export async function androidFindElement(options, deviceId, signal, tree) {
971
803
  error: treeResult.error
972
804
  };
973
805
  }
974
- // Filter to viewport-visible elements first, then match criteria.
975
- // This prevents selecting off-screen duplicates in scroll views / pagers.
976
806
  const screenSize = treeResult.rawXml ? extractAndroidScreenSize(treeResult.rawXml) : null;
977
807
  const visibleElements = screenSize
978
808
  ? treeResult.elements.filter(el => isAndroidElementInViewport(el, screenSize.width, screenSize.height))
979
809
  : treeResult.elements;
980
810
  let matches = visibleElements.filter(el => matchesElement(el, options));
981
- // If no visible matches, fall back to all elements (element may be partially visible
982
- // or the screen size extraction failed)
983
811
  if (matches.length === 0) {
984
812
  matches = treeResult.elements.filter(el => matchesElement(el, options));
985
813
  }
@@ -990,7 +818,6 @@ export async function androidFindElement(options, deviceId, signal, tree) {
990
818
  matchCount: 0
991
819
  };
992
820
  }
993
- // Select the element at the specified index (default 0)
994
821
  const index = options.index ?? 0;
995
822
  const selectedElement = matches[index];
996
823
  if (!selectedElement) {
@@ -1017,14 +844,10 @@ export async function androidFindElement(options, deviceId, signal, tree) {
1017
844
  };
1018
845
  }
1019
846
  }
1020
- /**
1021
- * Wait for element to appear on screen with polling
1022
- */
1023
847
  export async function androidWaitForElement(options, deviceId) {
1024
848
  const timeoutMs = options.timeoutMs ?? 10000;
1025
849
  const pollIntervalMs = options.pollIntervalMs ?? 500;
1026
850
  const startTime = Date.now();
1027
- // Validate that at least one search criteria is provided
1028
851
  if (!options.text && !options.textContains && !options.contentDesc &&
1029
852
  !options.contentDescContains && !options.resourceId) {
1030
853
  return {
@@ -1043,7 +866,6 @@ export async function androidWaitForElement(options, deviceId) {
1043
866
  timedOut: false
1044
867
  };
1045
868
  }
1046
- // If there was an error (not just "not found"), return it
1047
869
  if (!result.success) {
1048
870
  return {
1049
871
  ...result,
@@ -1051,7 +873,6 @@ export async function androidWaitForElement(options, deviceId) {
1051
873
  timedOut: false
1052
874
  };
1053
875
  }
1054
- // Wait before next poll
1055
876
  await new Promise(resolve => setTimeout(resolve, pollIntervalMs));
1056
877
  }
1057
878
  return {
@@ -1062,9 +883,6 @@ export async function androidWaitForElement(options, deviceId) {
1062
883
  error: `Timed out after ${timeoutMs}ms waiting for element`
1063
884
  };
1064
885
  }
1065
- /**
1066
- * Get device screen size
1067
- */
1068
886
  export async function androidGetScreenSize(deviceId) {
1069
887
  try {
1070
888
  const adbMissing = await requireAdb();
@@ -1081,7 +899,6 @@ export async function androidGetScreenSize(deviceId) {
1081
899
  const { stdout } = await execAsync(`adb ${deviceArg} shell wm size`, {
1082
900
  timeout: ADB_TIMEOUT
1083
901
  });
1084
- // Parse output like "Physical size: 1080x1920"
1085
902
  const match = stdout.match(/(\d+)x(\d+)/);
1086
903
  if (match) {
1087
904
  return {
@@ -1102,9 +919,6 @@ export async function androidGetScreenSize(deviceId) {
1102
919
  };
1103
920
  }
1104
921
  }
1105
- /**
1106
- * Get device display density (dpi)
1107
- */
1108
922
  export async function androidGetDensity(deviceId) {
1109
923
  try {
1110
924
  const adbMissing = await requireAdb();
@@ -1121,7 +935,6 @@ export async function androidGetDensity(deviceId) {
1121
935
  const { stdout } = await execAsync(`adb ${deviceArg} shell wm density`, {
1122
936
  timeout: ADB_TIMEOUT
1123
937
  });
1124
- // Parse output like "Physical density: 440" or "Override density: 440"
1125
938
  const match = stdout.match(/density:\s*(\d+)/i);
1126
939
  if (match) {
1127
940
  return {
@@ -1141,30 +954,21 @@ export async function androidGetDensity(deviceId) {
1141
954
  };
1142
955
  }
1143
956
  }
1144
- /**
1145
- * Get status bar height in pixels
1146
- * Android status bar is typically 24dp, but can vary by device/OS version
1147
- */
1148
957
  export async function androidGetStatusBarHeight(deviceId) {
1149
958
  try {
1150
- // Get density first
1151
959
  const densityResult = await androidGetDensity(deviceId);
1152
960
  if (!densityResult.success || !densityResult.density) {
1153
- // Fallback to common estimate
1154
961
  return {
1155
962
  success: true,
1156
- heightPixels: 63, // Common for 420dpi devices (24dp * 2.625)
963
+ heightPixels: 63,
1157
964
  heightDp: 24
1158
965
  };
1159
966
  }
1160
967
  const density = densityResult.density;
1161
- const densityScale = density / 160; // Android baseline is 160dpi
1162
- // Try to get actual status bar height from resources
968
+ const densityScale = density / 160;
1163
969
  const deviceArg = buildDeviceArg(deviceId);
1164
970
  try {
1165
971
  const { stdout } = await execAsync(`adb ${deviceArg} shell "dumpsys window | grep -E 'statusBars|mStatusBarLayer|InsetsSource.*statusBars'"`, { timeout: ADB_TIMEOUT });
1166
- // Try to parse status bar height from dumpsys output
1167
- // Look for patterns like "statusBars frame=[0,0][1080,63]"
1168
972
  const frameMatch = stdout.match(/statusBars.*frame=\[[\d,]+\]\[(\d+),(\d+)\]/);
1169
973
  if (frameMatch) {
1170
974
  const heightPixels = parseInt(frameMatch[2], 10);
@@ -1176,9 +980,7 @@ export async function androidGetStatusBarHeight(deviceId) {
1176
980
  }
1177
981
  }
1178
982
  catch {
1179
- // Fallback to standard calculation
1180
983
  }
1181
- // Standard status bar height is 24dp on most devices
1182
984
  const statusBarDp = 24;
1183
985
  const statusBarPixels = Math.round(statusBarDp * densityScale);
1184
986
  return {
@@ -1194,20 +996,12 @@ export async function androidGetStatusBarHeight(deviceId) {
1194
996
  };
1195
997
  }
1196
998
  }
1197
- /**
1198
- * Simplify Android class name for display
1199
- * android.widget.Button -> Button
1200
- * android.widget.TextView -> TextView
1201
- */
1202
999
  function simplifyClassName(className) {
1203
1000
  if (!className)
1204
1001
  return "Unknown";
1205
1002
  const parts = className.split(".");
1206
1003
  return parts[parts.length - 1];
1207
1004
  }
1208
- /**
1209
- * Parse bounds string "[left,top][right,bottom]" to object
1210
- */
1211
1005
  function parseBounds(boundsStr) {
1212
1006
  const match = boundsStr?.match(/\[(\d+),(\d+)\]\[(\d+),(\d+)\]/);
1213
1007
  if (!match)
@@ -1219,9 +1013,6 @@ function parseBounds(boundsStr) {
1219
1013
  bottom: parseInt(match[4], 10)
1220
1014
  };
1221
1015
  }
1222
- /**
1223
- * Parse a single node from uiautomator XML
1224
- */
1225
1016
  function parseUiNode(node) {
1226
1017
  const attrs = node["@_bounds"]
1227
1018
  ? node
@@ -1253,7 +1044,6 @@ function parseUiNode(node) {
1253
1044
  },
1254
1045
  children: []
1255
1046
  };
1256
- // Add optional attributes
1257
1047
  if (attrs["@_text"])
1258
1048
  element.text = attrs["@_text"];
1259
1049
  if (attrs["@_content-desc"])
@@ -1278,16 +1068,11 @@ function parseUiNode(node) {
1278
1068
  element.selected = true;
1279
1069
  return element;
1280
1070
  }
1281
- /**
1282
- * Recursively parse UI hierarchy from XML node
1283
- */
1284
1071
  function parseHierarchy(node) {
1285
1072
  const results = [];
1286
- // Handle the node itself
1287
1073
  if (node["@_bounds"]) {
1288
1074
  const element = parseUiNode(node);
1289
1075
  if (element) {
1290
- // Parse children
1291
1076
  if (node.node) {
1292
1077
  const children = Array.isArray(node.node) ? node.node : [node.node];
1293
1078
  for (const child of children) {
@@ -1298,7 +1083,6 @@ function parseHierarchy(node) {
1298
1083
  }
1299
1084
  }
1300
1085
  else if (node.node) {
1301
- // This is a container without bounds (like hierarchy root)
1302
1086
  const children = Array.isArray(node.node) ? node.node : [node.node];
1303
1087
  for (const child of children) {
1304
1088
  results.push(...parseHierarchy(child));
@@ -1306,35 +1090,25 @@ function parseHierarchy(node) {
1306
1090
  }
1307
1091
  return results;
1308
1092
  }
1309
- /**
1310
- * Format accessibility tree for display (similar to iOS format)
1311
- */
1312
1093
  function formatAndroidAccessibilityTree(elements, indent = 0) {
1313
1094
  const lines = [];
1314
1095
  const prefix = " ".repeat(indent);
1315
1096
  for (const element of elements) {
1316
1097
  const parts = [];
1317
- // [ClassName] "text" or "content-desc"
1318
1098
  parts.push(`[${element.class}]`);
1319
- // Add label (text or content-desc)
1320
1099
  const label = element.text || element.contentDesc;
1321
1100
  if (label) {
1322
1101
  parts.push(`"${label}"`);
1323
1102
  }
1324
- // Add frame and tap coordinates
1325
1103
  const f = element.frame;
1326
1104
  parts.push(`frame=(${f.x}, ${f.y}, ${f.width}x${f.height}) tap=(${element.tap.x}, ${element.tap.y})`);
1327
1105
  lines.push(`${prefix}${parts.join(" ")}`);
1328
- // Recurse into children
1329
1106
  if (element.children.length > 0) {
1330
1107
  lines.push(formatAndroidAccessibilityTree(element.children, indent + 1));
1331
1108
  }
1332
1109
  }
1333
1110
  return lines.join("\n");
1334
1111
  }
1335
- /**
1336
- * Flatten element tree to array for searching
1337
- */
1338
1112
  function flattenElements(elements) {
1339
1113
  const result = [];
1340
1114
  for (const element of elements) {
@@ -1345,9 +1119,6 @@ function flattenElements(elements) {
1345
1119
  }
1346
1120
  return result;
1347
1121
  }
1348
- /**
1349
- * Get the UI hierarchy from the connected Android device using uiautomator dump
1350
- */
1351
1122
  export async function androidDescribeAll(deviceId) {
1352
1123
  try {
1353
1124
  const adbMissing = await requireAdb();
@@ -1361,8 +1132,6 @@ export async function androidDescribeAll(deviceId) {
1361
1132
  };
1362
1133
  }
1363
1134
  const deviceArg = buildDeviceArg(device);
1364
- // Use file-based approach (most reliable across devices)
1365
- // /dev/tty doesn't work on most emulators/devices
1366
1135
  const remotePath = "/sdcard/ui_dump.xml";
1367
1136
  await execAsync(`adb ${deviceArg} shell uiautomator dump ${remotePath}`, {
1368
1137
  timeout: ADB_TIMEOUT
@@ -1372,7 +1141,6 @@ export async function androidDescribeAll(deviceId) {
1372
1141
  maxBuffer: 10 * 1024 * 1024
1373
1142
  });
1374
1143
  const xmlContent = stdout.trim();
1375
- // Clean up
1376
1144
  await execAsync(`adb ${deviceArg} shell rm ${remotePath}`, {
1377
1145
  timeout: 5000
1378
1146
  }).catch(() => { });
@@ -1382,7 +1150,6 @@ export async function androidDescribeAll(deviceId) {
1382
1150
  error: "Failed to get UI hierarchy. Make sure the device screen is unlocked and the app is in foreground."
1383
1151
  };
1384
1152
  }
1385
- // Parse XML
1386
1153
  const parser = new XMLParser({
1387
1154
  ignoreAttributes: false,
1388
1155
  attributeNamePrefix: "@_"
@@ -1409,19 +1176,13 @@ export async function androidDescribeAll(deviceId) {
1409
1176
  };
1410
1177
  }
1411
1178
  }
1412
- /**
1413
- * Get accessibility info for the UI element at specific coordinates
1414
- */
1415
1179
  export async function androidDescribePoint(x, y, deviceId) {
1416
1180
  try {
1417
- // First get the full hierarchy
1418
1181
  const result = await androidDescribeAll(deviceId);
1419
1182
  if (!result.success || !result.elements) {
1420
1183
  return result;
1421
1184
  }
1422
- // Flatten and find elements containing the point
1423
1185
  const allElements = flattenElements(result.elements);
1424
- // Find all elements whose bounds contain the point
1425
1186
  const matchingElements = allElements.filter((el) => {
1426
1187
  const b = el.bounds;
1427
1188
  return x >= b.left && x <= b.right && y >= b.top && y <= b.bottom;
@@ -1432,15 +1193,12 @@ export async function androidDescribePoint(x, y, deviceId) {
1432
1193
  formatted: `No element found at (${x}, ${y})`
1433
1194
  };
1434
1195
  }
1435
- // Return the deepest (smallest) element that contains the point
1436
- // Sort by area (smallest first) to get the most specific element
1437
1196
  matchingElements.sort((a, b) => {
1438
1197
  const areaA = a.frame.width * a.frame.height;
1439
1198
  const areaB = b.frame.width * b.frame.height;
1440
1199
  return areaA - areaB;
1441
1200
  });
1442
1201
  const element = matchingElements[0];
1443
- // Format detailed output
1444
1202
  const lines = [];
1445
1203
  const label = element.text || element.contentDesc;
1446
1204
  lines.push(`[${element.class}]${label ? ` "${label}"` : ""} frame=(${element.frame.x}, ${element.frame.y}, ${element.frame.width}x${element.frame.height}) tap=(${element.tap.x}, ${element.tap.y})`);
@@ -1448,14 +1206,11 @@ export async function androidDescribePoint(x, y, deviceId) {
1448
1206
  lines.push(` resource-id: ${element.resourceId}`);
1449
1207
  }
1450
1208
  if (element.contentDesc && element.text) {
1451
- // Show content-desc separately if we showed text as label
1452
1209
  lines.push(` content-desc: ${element.contentDesc}`);
1453
1210
  }
1454
1211
  if (element.text && element.contentDesc) {
1455
- // Show text separately if we showed content-desc as label
1456
1212
  lines.push(` text: ${element.text}`);
1457
1213
  }
1458
- // Show state flags
1459
1214
  const flags = [];
1460
1215
  if (element.clickable)
1461
1216
  flags.push("clickable");
@@ -1487,20 +1242,15 @@ export async function androidDescribePoint(x, y, deviceId) {
1487
1242
  };
1488
1243
  }
1489
1244
  }
1490
- /**
1491
- * Tap an element by its text, content-description, or resource-id
1492
- */
1493
1245
  export async function androidTapElement(options) {
1494
1246
  try {
1495
1247
  const { text, textContains, contentDesc, contentDescContains, resourceId, index = 0, deviceId } = options;
1496
- // Validate that at least one search criterion is provided
1497
1248
  if (!text && !textContains && !contentDesc && !contentDescContains && !resourceId) {
1498
1249
  return {
1499
1250
  success: false,
1500
1251
  error: "At least one of text, textContains, contentDesc, contentDescContains, or resourceId must be provided"
1501
1252
  };
1502
1253
  }
1503
- // Get the UI hierarchy
1504
1254
  const result = await androidDescribeAll(deviceId);
1505
1255
  if (!result.success || !result.elements) {
1506
1256
  return {
@@ -1508,9 +1258,7 @@ export async function androidTapElement(options) {
1508
1258
  error: result.error || "Failed to get UI hierarchy"
1509
1259
  };
1510
1260
  }
1511
- // Flatten and search
1512
1261
  const allElements = flattenElements(result.elements);
1513
- // Filter elements based on search criteria
1514
1262
  const matchingElements = allElements.filter((el) => {
1515
1263
  if (text && el.text !== text)
1516
1264
  return false;
@@ -1521,7 +1269,6 @@ export async function androidTapElement(options) {
1521
1269
  if (contentDescContains && (!el.contentDesc || !el.contentDesc.toLowerCase().includes(contentDescContains.toLowerCase())))
1522
1270
  return false;
1523
1271
  if (resourceId) {
1524
- // Support both full resource-id and short form
1525
1272
  if (!el.resourceId)
1526
1273
  return false;
1527
1274
  if (el.resourceId !== resourceId && !el.resourceId.endsWith(`:id/${resourceId}`))
@@ -1554,7 +1301,6 @@ export async function androidTapElement(options) {
1554
1301
  }
1555
1302
  const element = matchingElements[index];
1556
1303
  const label = element.text || element.contentDesc || element.resourceId || element.class;
1557
- // Log if multiple matches
1558
1304
  let resultMessage;
1559
1305
  if (matchingElements.length > 1) {
1560
1306
  resultMessage = `Found ${matchingElements.length} elements, tapping "${label}" (index ${index}) at (${element.tap.x}, ${element.tap.y})`;
@@ -1562,7 +1308,6 @@ export async function androidTapElement(options) {
1562
1308
  else {
1563
1309
  resultMessage = `Tapped "${label}" at (${element.tap.x}, ${element.tap.y})`;
1564
1310
  }
1565
- // Perform the tap
1566
1311
  const tapResult = await androidTap(element.tap.x, element.tap.y, deviceId);
1567
1312
  if (!tapResult.success) {
1568
1313
  return tapResult;