browxai 0.7.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 (520) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +139 -0
  3. package/THIRD_PARTY_NOTICES.md +45 -0
  4. package/dist/cli/chrome.d.ts +1 -0
  5. package/dist/cli/chrome.js +130 -0
  6. package/dist/cli/command-registry.d.ts +15 -0
  7. package/dist/cli/command-registry.js +35 -0
  8. package/dist/cli/doctor-plugins.d.ts +18 -0
  9. package/dist/cli/doctor-plugins.js +338 -0
  10. package/dist/cli/doctor.d.ts +9 -0
  11. package/dist/cli/doctor.js +407 -0
  12. package/dist/cli/init.d.ts +1 -0
  13. package/dist/cli/init.js +200 -0
  14. package/dist/cli/register-commands.d.ts +1 -0
  15. package/dist/cli/register-commands.js +22 -0
  16. package/dist/cli/serve.d.ts +14 -0
  17. package/dist/cli/serve.js +151 -0
  18. package/dist/cli.d.ts +3 -0
  19. package/dist/cli.js +129 -0
  20. package/dist/engine/adapters/adb.d.ts +72 -0
  21. package/dist/engine/adapters/adb.js +200 -0
  22. package/dist/engine/adapters/android-cdp.d.ts +54 -0
  23. package/dist/engine/adapters/android-cdp.js +110 -0
  24. package/dist/engine/adapters/android.engine.d.ts +1 -0
  25. package/dist/engine/adapters/android.engine.js +31 -0
  26. package/dist/engine/adapters/chromium.engine.d.ts +1 -0
  27. package/dist/engine/adapters/chromium.engine.js +44 -0
  28. package/dist/engine/adapters/firefox.engine.d.ts +1 -0
  29. package/dist/engine/adapters/firefox.engine.js +43 -0
  30. package/dist/engine/adapters/playwright-chromium.d.ts +43 -0
  31. package/dist/engine/adapters/playwright-chromium.js +56 -0
  32. package/dist/engine/adapters/playwright-firefox.d.ts +52 -0
  33. package/dist/engine/adapters/playwright-firefox.js +97 -0
  34. package/dist/engine/adapters/playwright-webkit.d.ts +40 -0
  35. package/dist/engine/adapters/playwright-webkit.js +79 -0
  36. package/dist/engine/adapters/safari/bidi-client.d.ts +46 -0
  37. package/dist/engine/adapters/safari/bidi-client.js +130 -0
  38. package/dist/engine/adapters/safari/launch.d.ts +56 -0
  39. package/dist/engine/adapters/safari/launch.js +104 -0
  40. package/dist/engine/adapters/safari/webdriver-client.d.ts +102 -0
  41. package/dist/engine/adapters/safari/webdriver-client.js +175 -0
  42. package/dist/engine/adapters/safari.engine.d.ts +1 -0
  43. package/dist/engine/adapters/safari.engine.js +52 -0
  44. package/dist/engine/adapters/safaridriver-hybrid.d.ts +56 -0
  45. package/dist/engine/adapters/safaridriver-hybrid.js +127 -0
  46. package/dist/engine/adapters/webkit.engine.d.ts +1 -0
  47. package/dist/engine/adapters/webkit.engine.js +47 -0
  48. package/dist/engine/capabilities.d.ts +53 -0
  49. package/dist/engine/capabilities.js +122 -0
  50. package/dist/engine/capability-registry.d.ts +9 -0
  51. package/dist/engine/capability-registry.js +20 -0
  52. package/dist/engine/index.d.ts +18 -0
  53. package/dist/engine/index.js +14 -0
  54. package/dist/engine/register-engines.d.ts +5 -0
  55. package/dist/engine/register-engines.js +16 -0
  56. package/dist/engine/registry.d.ts +145 -0
  57. package/dist/engine/registry.js +67 -0
  58. package/dist/engine/select.d.ts +48 -0
  59. package/dist/engine/select.js +128 -0
  60. package/dist/engine/session-cdp.d.ts +13 -0
  61. package/dist/engine/session-cdp.js +22 -0
  62. package/dist/engine/tool-gate.d.ts +19 -0
  63. package/dist/engine/tool-gate.js +226 -0
  64. package/dist/engine/types.d.ts +71 -0
  65. package/dist/engine/types.js +16 -0
  66. package/dist/helper/bridge.d.ts +48 -0
  67. package/dist/helper/bridge.js +200 -0
  68. package/dist/helper/browx-page.d.ts +1 -0
  69. package/dist/helper/browx-page.js +47 -0
  70. package/dist/helper/overlay-hide.d.ts +9 -0
  71. package/dist/helper/overlay-hide.js +49 -0
  72. package/dist/helper/stealth.d.ts +10 -0
  73. package/dist/helper/stealth.js +88 -0
  74. package/dist/index.d.ts +7 -0
  75. package/dist/index.js +15 -0
  76. package/dist/page/a11y.d.ts +81 -0
  77. package/dist/page/a11y.js +219 -0
  78. package/dist/page/action-substrate.d.ts +64 -0
  79. package/dist/page/action-substrate.js +118 -0
  80. package/dist/page/actionresult-blocks.d.ts +99 -0
  81. package/dist/page/actionresult-blocks.js +144 -0
  82. package/dist/page/actionresult-shape.d.ts +48 -0
  83. package/dist/page/actionresult-shape.js +155 -0
  84. package/dist/page/actionresult-types.d.ts +368 -0
  85. package/dist/page/actionresult-types.js +4 -0
  86. package/dist/page/actionresult.d.ts +4 -0
  87. package/dist/page/actionresult.js +299 -0
  88. package/dist/page/actions-probe.d.ts +32 -0
  89. package/dist/page/actions-probe.js +294 -0
  90. package/dist/page/actions-scroll.d.ts +40 -0
  91. package/dist/page/actions-scroll.js +53 -0
  92. package/dist/page/actions.d.ts +132 -0
  93. package/dist/page/actions.js +453 -0
  94. package/dist/page/archive-assets.d.ts +39 -0
  95. package/dist/page/archive-assets.js +187 -0
  96. package/dist/page/archive.d.ts +47 -0
  97. package/dist/page/archive.js +349 -0
  98. package/dist/page/asset-export.d.ts +122 -0
  99. package/dist/page/asset-export.js +376 -0
  100. package/dist/page/await_network.d.ts +16 -0
  101. package/dist/page/await_network.js +23 -0
  102. package/dist/page/bbox.d.ts +37 -0
  103. package/dist/page/bbox.js +115 -0
  104. package/dist/page/canvas-capture.d.ts +82 -0
  105. package/dist/page/canvas-capture.js +257 -0
  106. package/dist/page/canvas-diff.d.ts +51 -0
  107. package/dist/page/canvas-diff.js +131 -0
  108. package/dist/page/canvas-gesture.d.ts +53 -0
  109. package/dist/page/canvas-gesture.js +167 -0
  110. package/dist/page/canvas-transform.d.ts +96 -0
  111. package/dist/page/canvas-transform.js +150 -0
  112. package/dist/page/canvas.d.ts +8 -0
  113. package/dist/page/canvas.js +50 -0
  114. package/dist/page/capture-substrate.d.ts +111 -0
  115. package/dist/page/capture-substrate.js +139 -0
  116. package/dist/page/clipboard.d.ts +25 -0
  117. package/dist/page/clipboard.js +50 -0
  118. package/dist/page/clock.d.ts +36 -0
  119. package/dist/page/clock.js +167 -0
  120. package/dist/page/compose.d.ts +55 -0
  121. package/dist/page/compose.js +169 -0
  122. package/dist/page/console.d.ts +39 -0
  123. package/dist/page/console.js +73 -0
  124. package/dist/page/coverage.d.ts +97 -0
  125. package/dist/page/coverage.js +280 -0
  126. package/dist/page/dom-export.d.ts +41 -0
  127. package/dist/page/dom-export.js +193 -0
  128. package/dist/page/dom-walk.d.ts +91 -0
  129. package/dist/page/dom-walk.js +267 -0
  130. package/dist/page/dom_diff.d.ts +48 -0
  131. package/dist/page/dom_diff.js +121 -0
  132. package/dist/page/downloads.d.ts +80 -0
  133. package/dist/page/downloads.js +244 -0
  134. package/dist/page/drop-files.d.ts +78 -0
  135. package/dist/page/drop-files.js +310 -0
  136. package/dist/page/element-export-discovery.d.ts +64 -0
  137. package/dist/page/element-export-discovery.js +346 -0
  138. package/dist/page/element-export.d.ts +46 -0
  139. package/dist/page/element-export.js +251 -0
  140. package/dist/page/emulation-substrate.d.ts +53 -0
  141. package/dist/page/emulation-substrate.js +87 -0
  142. package/dist/page/emulation.d.ts +60 -0
  143. package/dist/page/emulation.js +162 -0
  144. package/dist/page/export-playwright-script.d.ts +47 -0
  145. package/dist/page/export-playwright-script.js +304 -0
  146. package/dist/page/extract-resolve.d.ts +22 -0
  147. package/dist/page/extract-resolve.js +341 -0
  148. package/dist/page/extract-schema.d.ts +20 -0
  149. package/dist/page/extract-schema.js +200 -0
  150. package/dist/page/extract-types.d.ts +127 -0
  151. package/dist/page/extract-types.js +8 -0
  152. package/dist/page/extract-warnings.d.ts +8 -0
  153. package/dist/page/extract-warnings.js +56 -0
  154. package/dist/page/extract.d.ts +9 -0
  155. package/dist/page/extract.js +174 -0
  156. package/dist/page/fill-form.d.ts +58 -0
  157. package/dist/page/fill-form.js +261 -0
  158. package/dist/page/find.d.ts +158 -0
  159. package/dist/page/find.js +470 -0
  160. package/dist/page/frames.d.ts +45 -0
  161. package/dist/page/frames.js +133 -0
  162. package/dist/page/generate-locator.d.ts +57 -0
  163. package/dist/page/generate-locator.js +136 -0
  164. package/dist/page/gestures.d.ts +128 -0
  165. package/dist/page/gestures.js +198 -0
  166. package/dist/page/har.d.ts +91 -0
  167. package/dist/page/har.js +174 -0
  168. package/dist/page/heap.d.ts +97 -0
  169. package/dist/page/heap.js +285 -0
  170. package/dist/page/inspect.d.ts +34 -0
  171. package/dist/page/inspect.js +75 -0
  172. package/dist/page/layout-thrash.d.ts +34 -0
  173. package/dist/page/layout-thrash.js +232 -0
  174. package/dist/page/learning.d.ts +21 -0
  175. package/dist/page/learning.js +84 -0
  176. package/dist/page/locator.d.ts +54 -0
  177. package/dist/page/locator.js +142 -0
  178. package/dist/page/memory-diff.d.ts +48 -0
  179. package/dist/page/memory-diff.js +105 -0
  180. package/dist/page/network-mask.d.ts +8 -0
  181. package/dist/page/network-mask.js +18 -0
  182. package/dist/page/network-playwright.d.ts +96 -0
  183. package/dist/page/network-playwright.js +353 -0
  184. package/dist/page/network-substrate-select.d.ts +18 -0
  185. package/dist/page/network-substrate-select.js +32 -0
  186. package/dist/page/network-substrate.d.ts +109 -0
  187. package/dist/page/network-substrate.js +161 -0
  188. package/dist/page/network-ws.d.ts +46 -0
  189. package/dist/page/network-ws.js +113 -0
  190. package/dist/page/network.d.ts +194 -0
  191. package/dist/page/network.js +415 -0
  192. package/dist/page/overflow-detect.d.ts +102 -0
  193. package/dist/page/overflow-detect.js +449 -0
  194. package/dist/page/pdf.d.ts +69 -0
  195. package/dist/page/pdf.js +109 -0
  196. package/dist/page/perf-audit-analysers.d.ts +40 -0
  197. package/dist/page/perf-audit-analysers.js +369 -0
  198. package/dist/page/perf-audit-runner.d.ts +20 -0
  199. package/dist/page/perf-audit-runner.js +195 -0
  200. package/dist/page/perf-audit-types.d.ts +41 -0
  201. package/dist/page/perf-audit-types.js +5 -0
  202. package/dist/page/perf-audit.d.ts +37 -0
  203. package/dist/page/perf-audit.js +377 -0
  204. package/dist/page/perf.d.ts +127 -0
  205. package/dist/page/perf.js +373 -0
  206. package/dist/page/plan.d.ts +192 -0
  207. package/dist/page/plan.js +308 -0
  208. package/dist/page/point_probe.d.ts +46 -0
  209. package/dist/page/point_probe.js +99 -0
  210. package/dist/page/recording.d.ts +67 -0
  211. package/dist/page/recording.js +172 -0
  212. package/dist/page/refs.d.ts +92 -0
  213. package/dist/page/refs.js +134 -0
  214. package/dist/page/regions.d.ts +23 -0
  215. package/dist/page/regions.js +32 -0
  216. package/dist/page/routes.d.ts +40 -0
  217. package/dist/page/routes.js +87 -0
  218. package/dist/page/safari-actions.d.ts +12 -0
  219. package/dist/page/safari-actions.js +144 -0
  220. package/dist/page/sample.d.ts +64 -0
  221. package/dist/page/sample.js +216 -0
  222. package/dist/page/screenshot-on.d.ts +51 -0
  223. package/dist/page/screenshot-on.js +150 -0
  224. package/dist/page/screenshot-save.d.ts +36 -0
  225. package/dist/page/screenshot-save.js +53 -0
  226. package/dist/page/screenshot-schedule.d.ts +50 -0
  227. package/dist/page/screenshot-schedule.js +155 -0
  228. package/dist/page/script-substrate.d.ts +32 -0
  229. package/dist/page/script-substrate.js +47 -0
  230. package/dist/page/seed-random.d.ts +45 -0
  231. package/dist/page/seed-random.js +144 -0
  232. package/dist/page/set-of-marks.d.ts +96 -0
  233. package/dist/page/set-of-marks.js +245 -0
  234. package/dist/page/shadow.d.ts +136 -0
  235. package/dist/page/shadow.js +400 -0
  236. package/dist/page/shortcut.d.ts +50 -0
  237. package/dist/page/shortcut.js +147 -0
  238. package/dist/page/snapshot-substrate-safari.d.ts +30 -0
  239. package/dist/page/snapshot-substrate-safari.js +84 -0
  240. package/dist/page/snapshot-substrate-select.d.ts +24 -0
  241. package/dist/page/snapshot-substrate-select.js +34 -0
  242. package/dist/page/snapshot-substrate.d.ts +58 -0
  243. package/dist/page/snapshot-substrate.js +135 -0
  244. package/dist/page/snapshot.d.ts +24 -0
  245. package/dist/page/snapshot.js +162 -0
  246. package/dist/page/solve-captcha.d.ts +76 -0
  247. package/dist/page/solve-captcha.js +286 -0
  248. package/dist/page/storage-substrate-types.d.ts +221 -0
  249. package/dist/page/storage-substrate-types.js +6 -0
  250. package/dist/page/storage-substrate.d.ts +215 -0
  251. package/dist/page/storage-substrate.js +280 -0
  252. package/dist/page/structural.d.ts +9 -0
  253. package/dist/page/structural.js +152 -0
  254. package/dist/page/substrate-bundle-safari.d.ts +8 -0
  255. package/dist/page/substrate-bundle-safari.js +42 -0
  256. package/dist/page/substrate-bundle.d.ts +6 -0
  257. package/dist/page/substrate-bundle.js +53 -0
  258. package/dist/page/text_search.d.ts +44 -0
  259. package/dist/page/text_search.js +90 -0
  260. package/dist/page/upload.d.ts +28 -0
  261. package/dist/page/upload.js +62 -0
  262. package/dist/page/verify.d.ts +63 -0
  263. package/dist/page/verify.js +451 -0
  264. package/dist/page/video.d.ts +115 -0
  265. package/dist/page/video.js +169 -0
  266. package/dist/page/visibility.d.ts +22 -0
  267. package/dist/page/visibility.js +94 -0
  268. package/dist/page/watch.d.ts +29 -0
  269. package/dist/page/watch.js +99 -0
  270. package/dist/page/workers.d.ts +126 -0
  271. package/dist/page/workers.js +490 -0
  272. package/dist/page/ws-interactive.d.ts +82 -0
  273. package/dist/page/ws-interactive.js +318 -0
  274. package/dist/plugin/cli.d.ts +45 -0
  275. package/dist/plugin/cli.js +496 -0
  276. package/dist/plugin/command-registry.d.ts +9 -0
  277. package/dist/plugin/command-registry.js +23 -0
  278. package/dist/plugin/depgraph.d.ts +37 -0
  279. package/dist/plugin/depgraph.js +186 -0
  280. package/dist/plugin/manifest.d.ts +182 -0
  281. package/dist/plugin/manifest.js +219 -0
  282. package/dist/plugin/package-manager.d.ts +22 -0
  283. package/dist/plugin/package-manager.js +40 -0
  284. package/dist/plugin/resolver.d.ts +85 -0
  285. package/dist/plugin/resolver.js +166 -0
  286. package/dist/plugin/runtime.d.ts +77 -0
  287. package/dist/plugin/runtime.js +402 -0
  288. package/dist/plugin/types.d.ts +113 -0
  289. package/dist/plugin/types.js +4 -0
  290. package/dist/policy/confirm.d.ts +76 -0
  291. package/dist/policy/confirm.js +162 -0
  292. package/dist/policy/origin.d.ts +17 -0
  293. package/dist/policy/origin.js +79 -0
  294. package/dist/sdk/client.d.ts +21 -0
  295. package/dist/sdk/client.js +174 -0
  296. package/dist/sdk/index.d.ts +32 -0
  297. package/dist/sdk/index.js +61 -0
  298. package/dist/sdk/plugin-types.d.ts +33 -0
  299. package/dist/sdk/plugin-types.js +22 -0
  300. package/dist/sdk/registry.d.ts +17 -0
  301. package/dist/sdk/registry.js +94 -0
  302. package/dist/sdk/socket-transport.d.ts +20 -0
  303. package/dist/sdk/socket-transport.js +90 -0
  304. package/dist/sdk/tool-types.d.ts +634 -0
  305. package/dist/sdk/tool-types.js +28 -0
  306. package/dist/sdk/transport-in-process.d.ts +21 -0
  307. package/dist/sdk/transport-in-process.js +44 -0
  308. package/dist/sdk/transport-registry.d.ts +19 -0
  309. package/dist/sdk/transport-registry.js +31 -0
  310. package/dist/sdk/transport-socket.d.ts +12 -0
  311. package/dist/sdk/transport-socket.js +77 -0
  312. package/dist/sdk/transport-stdio-child.d.ts +10 -0
  313. package/dist/sdk/transport-stdio-child.js +47 -0
  314. package/dist/sdk/transport.d.ts +10 -0
  315. package/dist/sdk/transport.js +35 -0
  316. package/dist/sdk/types.d.ts +176 -0
  317. package/dist/sdk/types.js +10 -0
  318. package/dist/server.d.ts +33 -0
  319. package/dist/server.js +327 -0
  320. package/dist/session/artifacts.d.ts +52 -0
  321. package/dist/session/artifacts.js +177 -0
  322. package/dist/session/byob-attach.d.ts +26 -0
  323. package/dist/session/byob-attach.js +187 -0
  324. package/dist/session/byob.d.ts +8 -0
  325. package/dist/session/byob.js +20 -0
  326. package/dist/session/cache-storage.d.ts +100 -0
  327. package/dist/session/cache-storage.js +166 -0
  328. package/dist/session/device-emu.d.ts +149 -0
  329. package/dist/session/device-emu.js +545 -0
  330. package/dist/session/device.d.ts +14 -0
  331. package/dist/session/device.js +44 -0
  332. package/dist/session/dialog.d.ts +62 -0
  333. package/dist/session/dialog.js +164 -0
  334. package/dist/session/emulation.d.ts +69 -0
  335. package/dist/session/emulation.js +168 -0
  336. package/dist/session/extensions.d.ts +113 -0
  337. package/dist/session/extensions.js +237 -0
  338. package/dist/session/fs-picker.d.ts +144 -0
  339. package/dist/session/fs-picker.js +666 -0
  340. package/dist/session/idb-storage.d.ts +86 -0
  341. package/dist/session/idb-storage.js +229 -0
  342. package/dist/session/incognito.d.ts +3 -0
  343. package/dist/session/incognito.js +20 -0
  344. package/dist/session/launch-options.d.ts +41 -0
  345. package/dist/session/launch-options.js +200 -0
  346. package/dist/session/managed.d.ts +3 -0
  347. package/dist/session/managed.js +16 -0
  348. package/dist/session/metrics.d.ts +45 -0
  349. package/dist/session/metrics.js +75 -0
  350. package/dist/session/notification.d.ts +122 -0
  351. package/dist/session/notification.js +426 -0
  352. package/dist/session/permission.d.ts +144 -0
  353. package/dist/session/permission.js +600 -0
  354. package/dist/session/playwright-post-wire.d.ts +8 -0
  355. package/dist/session/playwright-post-wire.js +148 -0
  356. package/dist/session/policy-buffer.d.ts +21 -0
  357. package/dist/session/policy-buffer.js +47 -0
  358. package/dist/session/profile-snapshot.d.ts +11 -0
  359. package/dist/session/profile-snapshot.js +53 -0
  360. package/dist/session/registry.d.ts +365 -0
  361. package/dist/session/registry.js +98 -0
  362. package/dist/session/safari-post-wire.d.ts +8 -0
  363. package/dist/session/safari-post-wire.js +28 -0
  364. package/dist/session/safari-session.d.ts +10 -0
  365. package/dist/session/safari-session.js +39 -0
  366. package/dist/session/storage.d.ts +148 -0
  367. package/dist/session/storage.js +350 -0
  368. package/dist/session/types.d.ts +113 -0
  369. package/dist/session/types.js +5 -0
  370. package/dist/session/wedge.d.ts +15 -0
  371. package/dist/session/wedge.js +41 -0
  372. package/dist/tools/action-core-tools.d.ts +13 -0
  373. package/dist/tools/action-core-tools.js +156 -0
  374. package/dist/tools/action-form-tools.d.ts +12 -0
  375. package/dist/tools/action-form-tools.js +179 -0
  376. package/dist/tools/action-gesture-tools.d.ts +9 -0
  377. package/dist/tools/action-gesture-tools.js +115 -0
  378. package/dist/tools/action-history-tools.d.ts +8 -0
  379. package/dist/tools/action-history-tools.js +67 -0
  380. package/dist/tools/action-tool.d.ts +42 -0
  381. package/dist/tools/action-tool.js +58 -0
  382. package/dist/tools/action-tools.d.ts +20 -0
  383. package/dist/tools/action-tools.js +28 -0
  384. package/dist/tools/batch-act-tools.d.ts +10 -0
  385. package/dist/tools/batch-act-tools.js +276 -0
  386. package/dist/tools/batch-human-tools.d.ts +8 -0
  387. package/dist/tools/batch-human-tools.js +148 -0
  388. package/dist/tools/canvas-tools.d.ts +40 -0
  389. package/dist/tools/canvas-tools.js +368 -0
  390. package/dist/tools/capture-report-diagnostics-tools.d.ts +7 -0
  391. package/dist/tools/capture-report-diagnostics-tools.js +318 -0
  392. package/dist/tools/capture-report-element-export-tools.d.ts +8 -0
  393. package/dist/tools/capture-report-element-export-tools.js +197 -0
  394. package/dist/tools/capture-report-export-tools.d.ts +8 -0
  395. package/dist/tools/capture-report-export-tools.js +246 -0
  396. package/dist/tools/capture-report-marks-tools.d.ts +9 -0
  397. package/dist/tools/capture-report-marks-tools.js +221 -0
  398. package/dist/tools/capture-report-upload-tools.d.ts +8 -0
  399. package/dist/tools/capture-report-upload-tools.js +277 -0
  400. package/dist/tools/config-approval-tools.d.ts +8 -0
  401. package/dist/tools/config-approval-tools.js +166 -0
  402. package/dist/tools/deep-coverage-tools.d.ts +8 -0
  403. package/dist/tools/deep-coverage-tools.js +325 -0
  404. package/dist/tools/deep-determinism-tools.d.ts +8 -0
  405. package/dist/tools/deep-determinism-tools.js +276 -0
  406. package/dist/tools/deep-perf-tools.d.ts +19 -0
  407. package/dist/tools/deep-perf-tools.js +324 -0
  408. package/dist/tools/device-emulation-tools.d.ts +9 -0
  409. package/dist/tools/device-emulation-tools.js +137 -0
  410. package/dist/tools/extensions-batch-tools.d.ts +18 -0
  411. package/dist/tools/extensions-batch-tools.js +24 -0
  412. package/dist/tools/extensions-rebuild.d.ts +22 -0
  413. package/dist/tools/extensions-rebuild.js +208 -0
  414. package/dist/tools/extensions-tools.d.ts +2 -0
  415. package/dist/tools/extensions-tools.js +331 -0
  416. package/dist/tools/forms-fill-tools.d.ts +8 -0
  417. package/dist/tools/forms-fill-tools.js +109 -0
  418. package/dist/tools/forms-plan-tools.d.ts +7 -0
  419. package/dist/tools/forms-plan-tools.js +159 -0
  420. package/dist/tools/forms-recording-mode-tools.d.ts +8 -0
  421. package/dist/tools/forms-recording-mode-tools.js +71 -0
  422. package/dist/tools/forms-recording-tools.d.ts +14 -0
  423. package/dist/tools/forms-recording-tools.js +22 -0
  424. package/dist/tools/forms-refs-tools.d.ts +8 -0
  425. package/dist/tools/forms-refs-tools.js +90 -0
  426. package/dist/tools/gesture-coord-tools.d.ts +8 -0
  427. package/dist/tools/gesture-coord-tools.js +168 -0
  428. package/dist/tools/gesture-emulation-tools.d.ts +8 -0
  429. package/dist/tools/gesture-emulation-tools.js +135 -0
  430. package/dist/tools/gesture-network-tools.d.ts +17 -0
  431. package/dist/tools/gesture-network-tools.js +27 -0
  432. package/dist/tools/gesture-route-tools.d.ts +8 -0
  433. package/dist/tools/gesture-route-tools.js +142 -0
  434. package/dist/tools/gesture-websocket-tools.d.ts +8 -0
  435. package/dist/tools/gesture-websocket-tools.js +122 -0
  436. package/dist/tools/gesture-worker-tools.d.ts +9 -0
  437. package/dist/tools/gesture-worker-tools.js +200 -0
  438. package/dist/tools/host-build.d.ts +76 -0
  439. package/dist/tools/host-build.js +516 -0
  440. package/dist/tools/host.d.ts +287 -0
  441. package/dist/tools/host.js +1 -0
  442. package/dist/tools/input-tools.d.ts +10 -0
  443. package/dist/tools/input-tools.js +176 -0
  444. package/dist/tools/live-emulation-tools.d.ts +9 -0
  445. package/dist/tools/live-emulation-tools.js +353 -0
  446. package/dist/tools/plugin-runtime.d.ts +36 -0
  447. package/dist/tools/plugin-runtime.js +274 -0
  448. package/dist/tools/read-observe-buffer-tools.d.ts +9 -0
  449. package/dist/tools/read-observe-buffer-tools.js +385 -0
  450. package/dist/tools/read-observe-capture-tools.d.ts +12 -0
  451. package/dist/tools/read-observe-capture-tools.js +376 -0
  452. package/dist/tools/read-observe-dom-tools.d.ts +8 -0
  453. package/dist/tools/read-observe-dom-tools.js +308 -0
  454. package/dist/tools/read-observe-extract-tools.d.ts +8 -0
  455. package/dist/tools/read-observe-extract-tools.js +232 -0
  456. package/dist/tools/read-observe-verify-tools.d.ts +8 -0
  457. package/dist/tools/read-observe-verify-tools.js +316 -0
  458. package/dist/tools/schemas.d.ts +29 -0
  459. package/dist/tools/schemas.js +58 -0
  460. package/dist/tools/secrets-captcha-tools.d.ts +9 -0
  461. package/dist/tools/secrets-captcha-tools.js +231 -0
  462. package/dist/tools/session-dialog-permission-tools.d.ts +9 -0
  463. package/dist/tools/session-dialog-permission-tools.js +287 -0
  464. package/dist/tools/session-lifecycle-tools.d.ts +8 -0
  465. package/dist/tools/session-lifecycle-tools.js +314 -0
  466. package/dist/tools/session-notification-device-tools.d.ts +9 -0
  467. package/dist/tools/session-notification-device-tools.js +156 -0
  468. package/dist/tools/session-policy-tools.d.ts +16 -0
  469. package/dist/tools/session-policy-tools.js +22 -0
  470. package/dist/tools/session-registry.d.ts +28 -0
  471. package/dist/tools/session-registry.js +427 -0
  472. package/dist/tools/storage-artifact-har-video-tools.d.ts +8 -0
  473. package/dist/tools/storage-artifact-har-video-tools.js +311 -0
  474. package/dist/tools/storage-cache-idb-tools.d.ts +8 -0
  475. package/dist/tools/storage-cache-idb-tools.js +347 -0
  476. package/dist/tools/storage-state-cookies-tools.d.ts +8 -0
  477. package/dist/tools/storage-state-cookies-tools.js +223 -0
  478. package/dist/tools/storage-tools.d.ts +17 -0
  479. package/dist/tools/storage-tools.js +25 -0
  480. package/dist/tools/storage-web-auth-tools.d.ts +10 -0
  481. package/dist/tools/storage-web-auth-tools.js +230 -0
  482. package/dist/tools/tool-metadata.d.ts +8 -0
  483. package/dist/tools/tool-metadata.js +185 -0
  484. package/dist/util/batch.d.ts +83 -0
  485. package/dist/util/batch.js +191 -0
  486. package/dist/util/capabilities.d.ts +504 -0
  487. package/dist/util/capabilities.js +254 -0
  488. package/dist/util/config-store.d.ts +103 -0
  489. package/dist/util/config-store.js +206 -0
  490. package/dist/util/config.d.ts +11 -0
  491. package/dist/util/config.js +28 -0
  492. package/dist/util/credentials.d.ts +136 -0
  493. package/dist/util/credentials.js +622 -0
  494. package/dist/util/deadline.d.ts +22 -0
  495. package/dist/util/deadline.js +62 -0
  496. package/dist/util/diagnostics.d.ts +161 -0
  497. package/dist/util/diagnostics.js +579 -0
  498. package/dist/util/egress-sanitiser.d.ts +29 -0
  499. package/dist/util/egress-sanitiser.js +52 -0
  500. package/dist/util/failure.d.ts +8 -0
  501. package/dist/util/failure.js +50 -0
  502. package/dist/util/flake-check.d.ts +109 -0
  503. package/dist/util/flake-check.js +342 -0
  504. package/dist/util/invariant.d.ts +25 -0
  505. package/dist/util/invariant.js +66 -0
  506. package/dist/util/logging.d.ts +6 -0
  507. package/dist/util/logging.js +12 -0
  508. package/dist/util/predicates.d.ts +62 -0
  509. package/dist/util/predicates.js +340 -0
  510. package/dist/util/secrets.d.ts +104 -0
  511. package/dist/util/secrets.js +219 -0
  512. package/dist/util/tokens.d.ts +6 -0
  513. package/dist/util/tokens.js +24 -0
  514. package/dist/util/url-sanitizer.d.ts +19 -0
  515. package/dist/util/url-sanitizer.js +70 -0
  516. package/dist/util/version.d.ts +2 -0
  517. package/dist/util/version.js +21 -0
  518. package/dist/util/workspace.d.ts +7 -0
  519. package/dist/util/workspace.js +22 -0
  520. package/package.json +120 -0
@@ -0,0 +1,151 @@
1
+ // `browxai serve --socket /tmp/foo.sock` — long-running server that listens
2
+ // on a Unix domain socket (or named pipe on Windows) and accepts MCP-over-
3
+ // socket connections. The wire framing is byte-identical to the stdio path
4
+ // (same JSON-lines + ReadBuffer), but the listener lets multiple SDK
5
+ // clients attach to ONE browser/session registry — the wrightxai
6
+ // loop-plus-script scenario.
7
+ //
8
+ // Off by default: there is no `serve` exposed unless the operator explicitly
9
+ // runs this subcommand and passes `--socket`. There is no auto-discovery; an
10
+ // SDK client must be given the endpoint URL out-of-band.
11
+ //
12
+ // Security posture: the socket is created with restrictive perms (0700) so
13
+ // only the owning user can connect. Capability gates are enforced at the
14
+ // server, identical to stdio.
15
+ import { chmodSync, existsSync, unlinkSync } from "node:fs";
16
+ import { createServer as createNetServer } from "node:net";
17
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
18
+ import { createServer } from "../server.js";
19
+ import { SocketTransport } from "../sdk/socket-transport.js";
20
+ import { log } from "../util/logging.js";
21
+ function parseFlagString(args, flag) {
22
+ const i = args.indexOf(flag);
23
+ if (i === -1)
24
+ return undefined;
25
+ const v = args[i + 1];
26
+ if (!v || v.startsWith("--"))
27
+ return undefined;
28
+ return v;
29
+ }
30
+ export async function runServe(rawArgs) {
31
+ const socketPath = parseFlagString(rawArgs, "--socket");
32
+ if (!socketPath) {
33
+ process.stderr.write("usage: browxai serve --socket <unix-socket-path-or-windows-pipe-name>\n" +
34
+ " Example (macOS/Linux): browxai serve --socket /tmp/browxai.sock\n" +
35
+ " Example (Windows): browxai serve --socket \\\\\\\\.\\\\pipe\\\\browxai\n");
36
+ return 2;
37
+ }
38
+ const attachCdp = process.env.BROWX_ATTACH_CDP?.trim() || undefined;
39
+ const headless = process.env.BROWX_HEADLESS === "1";
40
+ const code = await startServe({ socketPath, attachCdp, headless });
41
+ return code;
42
+ }
43
+ /** Exposed for tests — programmatic `browxai serve` startup that returns the
44
+ * underlying net.Server so a test can `close()` it cleanly. */
45
+ export async function startServeForTests(opts) {
46
+ // Existing socket file → remove. A stale socket left over from a crashed
47
+ // run would otherwise block .listen() with EADDRINUSE.
48
+ if (opts.socketPath.startsWith("/") && existsSync(opts.socketPath)) {
49
+ try {
50
+ unlinkSync(opts.socketPath);
51
+ }
52
+ catch {
53
+ /* race; the listen() below will fail loudly if it actually mattered */
54
+ }
55
+ }
56
+ const browxai = await createServer({ attachCdp: opts.attachCdp, headless: opts.headless });
57
+ // We share ONE McpServer per attached client connection by creating a
58
+ // fresh adapter per connection. The simplest correct approach: each
59
+ // connection gets its OWN McpServer instance that re-registers against
60
+ // the SAME `browxai.handlers` map. Since `handlers` is shared,
61
+ // session-state isolation is the SessionRegistry's job (already true),
62
+ // and the per-connection McpServer just routes the JSON-RPC.
63
+ //
64
+ // Implementation detail: re-creating tools from scratch on every connect
65
+ // would require duplicating server.ts's input schemas. Instead we expose
66
+ // a thin tool-call proxy: the connection's McpServer registers a single
67
+ // catch-all? No — the MCP SDK requires tools to be registered by name.
68
+ // The cleanest path is: register the same tool names that the in-process
69
+ // server already has, with `inputSchema: { additionalProperties: true }`
70
+ // (open schema — the underlying handler still validates). Each tool's
71
+ // handler delegates to `browxai.handlers[name]`.
72
+ const liveConnections = new Set();
73
+ const netServer = createNetServer((socket) => {
74
+ void (async () => {
75
+ try {
76
+ const mcp = new McpServer({ name: "browxai", version: "0.2.3" });
77
+ for (const [name, handler] of Object.entries(browxai.handlers)) {
78
+ mcp.registerTool(name, { description: `browxai/${name}`, inputSchema: {} }, async (args) => handler(args));
79
+ }
80
+ const transport = new SocketTransport(socket);
81
+ await mcp.connect(transport);
82
+ const conn = {
83
+ close: async () => {
84
+ await mcp.close().catch(() => undefined);
85
+ await transport.close().catch(() => undefined);
86
+ },
87
+ };
88
+ liveConnections.add(conn);
89
+ socket.on("close", () => {
90
+ liveConnections.delete(conn);
91
+ });
92
+ }
93
+ catch (err) {
94
+ log.error("browxai serve: connection setup failed", {
95
+ error: err instanceof Error ? err.message : String(err),
96
+ });
97
+ socket.destroy();
98
+ }
99
+ })();
100
+ });
101
+ await new Promise((resolve, reject) => {
102
+ netServer.once("error", reject);
103
+ netServer.listen(opts.socketPath, () => resolve());
104
+ });
105
+ // Tighten perms on the listening socket (POSIX only — chmod is a no-op /
106
+ // throws on Windows pipes).
107
+ if (opts.socketPath.startsWith("/")) {
108
+ try {
109
+ chmodSync(opts.socketPath, 0o700);
110
+ }
111
+ catch {
112
+ /* best-effort; on macOS the socket inherits umask which is usually fine */
113
+ }
114
+ }
115
+ const shutdown = async () => {
116
+ for (const conn of liveConnections) {
117
+ await conn.close().catch(() => undefined);
118
+ }
119
+ liveConnections.clear();
120
+ await new Promise((resolve) => {
121
+ netServer.close(() => resolve());
122
+ });
123
+ await browxai.shutdown().catch(() => undefined);
124
+ if (opts.socketPath.startsWith("/") && existsSync(opts.socketPath)) {
125
+ try {
126
+ unlinkSync(opts.socketPath);
127
+ }
128
+ catch {
129
+ /* tolerated */
130
+ }
131
+ }
132
+ };
133
+ return { server: netServer, shutdown };
134
+ }
135
+ async function startServe(opts) {
136
+ const { shutdown } = await startServeForTests(opts);
137
+ log.info("browxai: serve listening", { socket: opts.socketPath });
138
+ // Keep the process alive until a signal.
139
+ const onSignal = async (sig) => {
140
+ log.info(`browxai: serve shutdown (${sig})`);
141
+ await shutdown();
142
+ process.exit(0);
143
+ };
144
+ process.on("SIGINT", () => void onSignal("SIGINT"));
145
+ process.on("SIGTERM", () => void onSignal("SIGTERM"));
146
+ // Block indefinitely.
147
+ await new Promise(() => {
148
+ /* never resolves; signals exit */
149
+ });
150
+ return 0;
151
+ }
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import "./tools/tool-metadata.js";
3
+ import "./cli/register-commands.js";
package/dist/cli.js ADDED
@@ -0,0 +1,129 @@
1
+ #!/usr/bin/env node
2
+ // browxai canonical entrypoint. See USAGE below for the sub-command surface.
3
+ //
4
+ // All transient state lives at $BROWX_WORKSPACE (default ~/.browxai/). NEVER cwd.
5
+ // RFC 0004 P2 / D1 (SECURITY-CRITICAL): EAGERLY populate the derived
6
+ // `TOOL_CAPABILITY` / `DEEP_TOOLS` maps for every CLI sub-command. `doctor` reads
7
+ // `resolveCapabilities` without building a server, so it must reach the
8
+ // tool-metadata bootstrap; importing it here covers the whole CLI surface, not
9
+ // only the default `createServer` path.
10
+ import "./tools/tool-metadata.js";
11
+ import { createServer } from "./server.js";
12
+ // RFC 0004 P4 / D6 — the extensibility subcommands (doctor/chrome/init/serve/
13
+ // plugin) dispatch through an add-only registry. Importing the registrations
14
+ // for their side effect populates the map; `commandFor` resolves the SAME
15
+ // handler the old `switch (subcommand)` case did.
16
+ import "./cli/register-commands.js";
17
+ import { commandFor, registeredCommands } from "./cli/command-registry.js";
18
+ import { log } from "./util/logging.js";
19
+ import { resolveConfig } from "./util/config.js";
20
+ import { resolveWorkspace } from "./util/workspace.js";
21
+ import { PACKAGE_VERSION } from "./util/version.js";
22
+ import { resolveEngineSelection, UnknownEngineError } from "./engine/index.js";
23
+ const USAGE = `Usage: browxai [subcommand]
24
+
25
+ browxai start the MCP server (stdio) — default
26
+ browxai doctor env + connectivity health-check
27
+ browxai chrome start [opts] launch an attachable Chrome (BYOB host)
28
+ browxai chrome stop kill the Chrome that \`chrome start\` launched
29
+ browxai init <workspace> bootstrap a per-app workspace (.mcp.json + sniff)
30
+ browxai serve --socket <p> long-running server on a Unix socket / named pipe
31
+ — accepts MCP-over-socket connections from SDK clients
32
+ (\`createBrowxai({ endpoint: "unix:///..." })\`).
33
+ Off-by-default; explicit operator opt-in.
34
+ browxai plugin <sub> install / remove / list / info / upgrade / sync
35
+ plugins. All ops are workspace-rooted.
36
+
37
+ --engine <kind> browser engine for the MCP server: chromium
38
+ (default) | firefox | webkit | android. Overrides
39
+ BROWX_ENGINE. android implies attach-mode (real
40
+ Chrome-on-Android over adb — no BROWX_ATTACH_CDP).
41
+ --version, -v print the browxai version
42
+ --help, -h print this usage text
43
+
44
+ All transient state lives at $BROWX_WORKSPACE (default ~/.browxai/).
45
+ `;
46
+ async function main() {
47
+ const [, , subcommand, ...rest] = process.argv;
48
+ // Sub-command dispatch. The extensibility subcommands resolve through the
49
+ // add-only registry; the `--version` / `--help` literal fast paths and the
50
+ // `undefined` / `--engine` server-fallthrough stay inline (they are the bin's
51
+ // own argv contract, not extension points). Resolving the registry FIRST keeps
52
+ // the same precedence the old `switch` encoded by case order: a registered
53
+ // subcommand wins, then the flag literals, then the server fallthrough.
54
+ if (subcommand !== undefined) {
55
+ const handler = commandFor(subcommand);
56
+ if (handler) {
57
+ process.exit(await handler(rest));
58
+ }
59
+ }
60
+ switch (subcommand) {
61
+ case "--version":
62
+ case "-v":
63
+ process.stdout.write(`${PACKAGE_VERSION}\n`);
64
+ process.exit(0);
65
+ break;
66
+ case "--help":
67
+ case "-h":
68
+ process.stdout.write(USAGE);
69
+ process.exit(0);
70
+ break;
71
+ case undefined:
72
+ break; // fall through to MCP server
73
+ default:
74
+ // `--engine <kind>` / `--engine=<kind>` is a SERVER-mode flag, not a
75
+ // subcommand — when it appears first (`browxai --engine firefox`) it lands
76
+ // in `subcommand`, so fall through to the MCP server path (which parses the
77
+ // full argv for it) instead of treating it as unknown.
78
+ if (subcommand === "--engine" || subcommand.startsWith("--engine="))
79
+ break;
80
+ // Unknown subcommand — print help and exit non-zero (don't silently start the
81
+ // MCP server, since stdout is the MCP wire and we'd corrupt any caller's expectation).
82
+ // The valid-subcommand list is derived from the registry so it can't drift.
83
+ process.stderr.write(`unknown subcommand "${subcommand}". Valid: ${registeredCommands().join(" | ")} | (no args = start MCP server). Run \`browxai --help\` for details.\n`);
84
+ process.exit(2);
85
+ }
86
+ // Default: MCP server.
87
+ const workspace = resolveWorkspace();
88
+ const config = resolveConfig();
89
+ const attachCdp = process.env.BROWX_ATTACH_CDP?.trim() || undefined;
90
+ const headless = process.env.BROWX_HEADLESS === "1";
91
+ // Engine selection: explicit `--engine <kind>` > `BROWX_ENGINE` env > default
92
+ // chromium (left to server.ts when this resolves undefined — byte-identical to
93
+ // never passing browserType). An unknown engine fails loudly here, before the
94
+ // server starts, with a structured message listing the implemented engines —
95
+ // never a stack trace, never a silent fallback to chromium.
96
+ let browserType;
97
+ try {
98
+ browserType = resolveEngineSelection(process.argv.slice(2));
99
+ }
100
+ catch (err) {
101
+ if (err instanceof UnknownEngineError ||
102
+ (err instanceof Error && err.message.includes("--engine"))) {
103
+ process.stderr.write(`${err.message}\n`);
104
+ process.exit(2);
105
+ }
106
+ throw err;
107
+ }
108
+ log.info("browxai: starting", {
109
+ workspace: workspace.root,
110
+ mode: attachCdp ? "byob" : "managed",
111
+ attachCdp,
112
+ headless,
113
+ engine: browserType ?? "chromium",
114
+ testAttributes: config.testAttributes,
115
+ });
116
+ const server = await createServer({ attachCdp, headless, browserType });
117
+ const shutdown = async (signal) => {
118
+ log.info(`browxai: shutdown (${signal})`);
119
+ await server.shutdown();
120
+ process.exit(0);
121
+ };
122
+ process.on("SIGINT", () => void shutdown("SIGINT"));
123
+ process.on("SIGTERM", () => void shutdown("SIGTERM"));
124
+ await server.start();
125
+ }
126
+ main().catch((err) => {
127
+ log.error("browxai: fatal", { error: err instanceof Error ? err.message : String(err) });
128
+ process.exit(1);
129
+ });
@@ -0,0 +1,72 @@
1
+ /** The abstract-namespace socket Chrome-on-Android publishes its DevTools
2
+ * endpoint on. WebView publishes per-process `webview_devtools_remote_<pid>`
3
+ * sockets; this adapter targets the browser socket (the user's real Chrome). */
4
+ export declare const CHROME_ANDROID_SOCKET = "localabstract:chrome_devtools_remote";
5
+ /** A connected adb device row. `state` is `device` for a ready, authorized
6
+ * device; `unauthorized` / `offline` are surfaced so the caller can tell the
7
+ * user to accept the on-device RSA prompt rather than fail opaquely. */
8
+ export interface AdbDevice {
9
+ serial: string;
10
+ state: string;
11
+ }
12
+ /** Runs an adb command and resolves its stdout. Injected so the pure command-
13
+ * construction + parsing logic is unit-testable without a device or a binary. */
14
+ export type AdbRunner = (args: readonly string[]) => Promise<string>;
15
+ /** GETs a URL and resolves the parsed JSON body. Injected for the same reason —
16
+ * the /json/version → wsUrl extraction is testable with a mock. */
17
+ export type Fetcher = (url: string) => Promise<unknown>;
18
+ /** adb is not installed / not on PATH. Structured (names the requirement), not a
19
+ * raw ENOENT crash. */
20
+ export declare class AdbNotInstalledError extends Error {
21
+ constructor(detail?: string);
22
+ }
23
+ /** No usable Android device is connected (none listed, or all unauthorized /
24
+ * offline). Structured — names exactly what the user must do. */
25
+ export declare class NoAndroidDeviceError extends Error {
26
+ readonly devices: readonly AdbDevice[];
27
+ constructor(devices: readonly AdbDevice[]);
28
+ }
29
+ /** The Chrome DevTools socket couldn't be reached on the forwarded port — Chrome
30
+ * isn't open on the device, or web-debugging isn't enabled. Structured. */
31
+ export declare class ChromeSocketUnreachableError extends Error {
32
+ constructor(detail: string);
33
+ }
34
+ /** `adb [-s serial] devices` argv. */
35
+ export declare function devicesArgs(): readonly string[];
36
+ /** `adb [-s serial] forward tcp:<localPort> localabstract:chrome_devtools_remote` argv. */
37
+ export declare function forwardArgs(localPort: number, serial?: string, socket?: string): readonly string[];
38
+ /** `adb [-s serial] forward --remove tcp:<localPort>` argv — the cleanup. */
39
+ export declare function forwardRemoveArgs(localPort: number, serial?: string): readonly string[];
40
+ /** Parse the multi-line `adb devices` output into rows. The first line is the
41
+ * "List of devices attached" header; each subsequent non-empty line is
42
+ * `<serial>\t<state>`. Blank lines + the header are skipped. */
43
+ export declare function parseDevices(stdout: string): AdbDevice[];
44
+ /** Choose the device to attach to. Prefers the requested `serial` if given and
45
+ * ready; else the single ready (`state === "device"`) device. Throws
46
+ * `NoAndroidDeviceError` (naming the unauthorized/offline rows) when no ready
47
+ * device exists, or a structured ambiguity error when several are ready and no
48
+ * serial was specified. */
49
+ export declare function selectDevice(devices: readonly AdbDevice[], serial?: string): AdbDevice;
50
+ /** The DevTools HTTP base URL for a forwarded local port (loopback by
51
+ * construction — adb forwards to 127.0.0.1, reusing byob.ts's loopback policy). */
52
+ export declare function devToolsBaseUrl(localPort: number): string;
53
+ /** The /json/version probe URL for a forwarded local port. */
54
+ export declare function versionUrl(localPort: number): string;
55
+ /** Extract the `webSocketDebuggerUrl` from a parsed /json/version body. Throws
56
+ * `ChromeSocketUnreachableError` when the field is absent (Chrome closed, or an
57
+ * HTML error page came back instead of JSON). This is the field
58
+ * `chromium.connectOverCDP` attaches to — the same browser-level ws endpoint the
59
+ * desktop BYOB path uses. */
60
+ export declare function extractWsUrl(versionBody: unknown): string;
61
+ /** The default adb runner — `execFile("adb", args)`. Maps ENOENT to the
62
+ * structured `AdbNotInstalledError`, and a non-zero exit (with adb present) to a
63
+ * message carrying adb's own stderr. No shell → no injection. */
64
+ export declare const defaultAdbRunner: AdbRunner;
65
+ /** The default fetcher — a JSON GET with a short timeout. A non-OK status or a
66
+ * non-JSON body surfaces as `ChromeSocketUnreachableError` at the call site. */
67
+ export declare const defaultFetcher: Fetcher;
68
+ /** Pick a free local TCP port (loopback) for the adb forward. Lets the OS choose
69
+ * by binding to port 0, then releases it — there's an inherent TOCTOU window,
70
+ * but adb's `forward tcp:<port>` re-binds immediately after, and a clash surfaces
71
+ * as a loud adb error rather than a silent wrong-port attach. */
72
+ export declare function pickFreePort(): Promise<number>;
@@ -0,0 +1,200 @@
1
+ // adb plumbing for the Android engine — discover the Chrome
2
+ // DevTools socket on a USB-connected device and forward it to a loopback port so
3
+ // `chromium.connectOverCDP` can attach to the user's REAL Chrome-on-Android.
4
+ //
5
+ // This module is split into PURE logic (command construction, `adb devices`
6
+ // parsing, the /json/version → webSocketDebuggerUrl extraction, free-port pick)
7
+ // and a thin IO seam (the `AdbRunner` that actually shells out to `adb`, the
8
+ // `Fetcher` that GETs the DevTools HTTP endpoint). The pure half is unit-tested
9
+ // WITHOUT a device; the IO half is exercised by the device-gated keystone.
10
+ //
11
+ // The Chrome-136 default-profile-attach block does NOT apply here. That block
12
+ // targets the DESKTOP `--remote-debugging-port` switch when combined with the
13
+ // default `--user-data-dir`. Android does not use that switch at all: the
14
+ // DevTools endpoint is exposed by the OS as an abstract-namespace unix socket
15
+ // (`localabstract:chrome_devtools_remote`), reachable only after the user
16
+ // enables USB debugging + on-device USB web-debugging. So the full-fidelity
17
+ // BYOB-to-the-real-profile win survives on Android — this is the one
18
+ // place real-profile attach still works post-Chrome-136. See
19
+ // developer.chrome.com/blog/remote-debugging-port (desktop-only) and
20
+ // developer.chrome.com/docs/devtools/remote-debugging (the Android adb path).
21
+ import { execFile } from "node:child_process";
22
+ import { createServer } from "node:net";
23
+ /** The abstract-namespace socket Chrome-on-Android publishes its DevTools
24
+ * endpoint on. WebView publishes per-process `webview_devtools_remote_<pid>`
25
+ * sockets; this adapter targets the browser socket (the user's real Chrome). */
26
+ export const CHROME_ANDROID_SOCKET = "localabstract:chrome_devtools_remote";
27
+ /** adb is not installed / not on PATH. Structured (names the requirement), not a
28
+ * raw ENOENT crash. */
29
+ export class AdbNotInstalledError extends Error {
30
+ constructor(detail) {
31
+ super("adb-missing: the Android Debug Bridge (`adb`) was not found on PATH. The android " +
32
+ "engine attaches to real Chrome-on-Android over adb + CDP. Install the " +
33
+ "Android platform-tools (https://developer.android.com/tools/releases/platform-tools) " +
34
+ "and ensure `adb` is on PATH" +
35
+ (detail ? ` (${detail})` : "") +
36
+ ".");
37
+ this.name = "AdbNotInstalledError";
38
+ }
39
+ }
40
+ /** No usable Android device is connected (none listed, or all unauthorized /
41
+ * offline). Structured — names exactly what the user must do. */
42
+ export class NoAndroidDeviceError extends Error {
43
+ devices;
44
+ constructor(devices) {
45
+ const seen = devices.length
46
+ ? `adb sees ${devices.length} device entr${devices.length === 1 ? "y" : "ies"}: ` +
47
+ devices.map((d) => `${d.serial} (${d.state})`).join(", ") +
48
+ ". An `unauthorized` device needs you to accept the USB-debugging RSA prompt on the " +
49
+ "phone; an `offline` device needs a re-plug."
50
+ : "adb sees no connected devices.";
51
+ super("no-device: no ready Android device is connected. " +
52
+ seen +
53
+ " Connect a phone over USB, enable Developer Options → USB debugging, open Chrome, and " +
54
+ "(for web debugging) enable Chrome → Settings → Developer tools / the on-device USB " +
55
+ "web-debugging toggle.");
56
+ this.name = "NoAndroidDeviceError";
57
+ this.devices = devices;
58
+ }
59
+ }
60
+ /** The Chrome DevTools socket couldn't be reached on the forwarded port — Chrome
61
+ * isn't open on the device, or web-debugging isn't enabled. Structured. */
62
+ export class ChromeSocketUnreachableError extends Error {
63
+ constructor(detail) {
64
+ super("chrome-socket-unreachable: forwarded the adb socket but the Chrome DevTools endpoint did " +
65
+ `not answer (${detail}). Open Chrome on the device and enable USB web-debugging ` +
66
+ "(chrome://inspect from the desktop should list the device's tabs).");
67
+ this.name = "ChromeSocketUnreachableError";
68
+ }
69
+ }
70
+ // ─── PURE: adb argv construction ──────────────────────────────────────────────
71
+ // `adb -s <serial>` scopes a command to one device; omitted when no serial (adb
72
+ // targets the single connected device, or errors if ambiguous — which we pre-empt
73
+ // by always resolving a serial first). These build argv arrays for `execFile`
74
+ // (no shell, no injection surface) — they are the unit-tested core.
75
+ /** `adb [-s serial] devices` argv. */
76
+ export function devicesArgs() {
77
+ return ["devices"];
78
+ }
79
+ /** `adb [-s serial] forward tcp:<localPort> localabstract:chrome_devtools_remote` argv. */
80
+ export function forwardArgs(localPort, serial, socket = CHROME_ANDROID_SOCKET) {
81
+ return [...serialFlag(serial), "forward", `tcp:${localPort}`, socket];
82
+ }
83
+ /** `adb [-s serial] forward --remove tcp:<localPort>` argv — the cleanup. */
84
+ export function forwardRemoveArgs(localPort, serial) {
85
+ return [...serialFlag(serial), "forward", "--remove", `tcp:${localPort}`];
86
+ }
87
+ function serialFlag(serial) {
88
+ return serial ? ["-s", serial] : [];
89
+ }
90
+ // ─── PURE: parsers + extractors ───────────────────────────────────────────────
91
+ /** Parse the multi-line `adb devices` output into rows. The first line is the
92
+ * "List of devices attached" header; each subsequent non-empty line is
93
+ * `<serial>\t<state>`. Blank lines + the header are skipped. */
94
+ export function parseDevices(stdout) {
95
+ const rows = [];
96
+ for (const line of stdout.split("\n")) {
97
+ const trimmed = line.trim();
98
+ if (!trimmed)
99
+ continue;
100
+ if (trimmed.toLowerCase().startsWith("list of devices"))
101
+ continue;
102
+ // serial and state are whitespace/tab separated; serial has no spaces.
103
+ const parts = trimmed.split(/\s+/);
104
+ const serial = parts[0];
105
+ const state = parts[1];
106
+ if (!serial || !state)
107
+ continue;
108
+ rows.push({ serial, state });
109
+ }
110
+ return rows;
111
+ }
112
+ /** Choose the device to attach to. Prefers the requested `serial` if given and
113
+ * ready; else the single ready (`state === "device"`) device. Throws
114
+ * `NoAndroidDeviceError` (naming the unauthorized/offline rows) when no ready
115
+ * device exists, or a structured ambiguity error when several are ready and no
116
+ * serial was specified. */
117
+ export function selectDevice(devices, serial) {
118
+ const ready = devices.filter((d) => d.state === "device");
119
+ if (serial) {
120
+ const match = ready.find((d) => d.serial === serial);
121
+ if (match)
122
+ return match;
123
+ throw new NoAndroidDeviceError(devices);
124
+ }
125
+ if (ready.length === 1)
126
+ return ready[0];
127
+ if (ready.length === 0)
128
+ throw new NoAndroidDeviceError(devices);
129
+ throw new Error(`ambiguous-device: ${ready.length} ready Android devices are connected ` +
130
+ `(${ready.map((d) => d.serial).join(", ")}). Pass a serial via BROWX_ANDROID_SERIAL ` +
131
+ "to pick one.");
132
+ }
133
+ /** The DevTools HTTP base URL for a forwarded local port (loopback by
134
+ * construction — adb forwards to 127.0.0.1, reusing byob.ts's loopback policy). */
135
+ export function devToolsBaseUrl(localPort) {
136
+ return `http://127.0.0.1:${localPort}`;
137
+ }
138
+ /** The /json/version probe URL for a forwarded local port. */
139
+ export function versionUrl(localPort) {
140
+ return `${devToolsBaseUrl(localPort)}/json/version`;
141
+ }
142
+ /** Extract the `webSocketDebuggerUrl` from a parsed /json/version body. Throws
143
+ * `ChromeSocketUnreachableError` when the field is absent (Chrome closed, or an
144
+ * HTML error page came back instead of JSON). This is the field
145
+ * `chromium.connectOverCDP` attaches to — the same browser-level ws endpoint the
146
+ * desktop BYOB path uses. */
147
+ export function extractWsUrl(versionBody) {
148
+ const ws = versionBody?.webSocketDebuggerUrl;
149
+ if (typeof ws !== "string" || !ws) {
150
+ throw new ChromeSocketUnreachableError("/json/version returned no webSocketDebuggerUrl (Chrome may be closed or web-debugging off)");
151
+ }
152
+ return ws;
153
+ }
154
+ // ─── IO seam: the default runners ─────────────────────────────────────────────
155
+ /** The default adb runner — `execFile("adb", args)`. Maps ENOENT to the
156
+ * structured `AdbNotInstalledError`, and a non-zero exit (with adb present) to a
157
+ * message carrying adb's own stderr. No shell → no injection. */
158
+ export const defaultAdbRunner = (args) => new Promise((resolve, reject) => {
159
+ execFile("adb", [...args], { timeout: 10_000 }, (err, stdout, stderr) => {
160
+ if (err) {
161
+ const code = err.code;
162
+ if (code === "ENOENT") {
163
+ reject(new AdbNotInstalledError());
164
+ return;
165
+ }
166
+ reject(new Error(`adb ${args.join(" ")} failed: ${stderr || err.message}`));
167
+ return;
168
+ }
169
+ resolve(stdout);
170
+ });
171
+ });
172
+ /** The default fetcher — a JSON GET with a short timeout. A non-OK status or a
173
+ * non-JSON body surfaces as `ChromeSocketUnreachableError` at the call site. */
174
+ export const defaultFetcher = async (url) => {
175
+ const res = await fetch(url, { signal: AbortSignal.timeout(3000) });
176
+ if (!res.ok) {
177
+ throw new ChromeSocketUnreachableError(`HTTP ${res.status} from ${url}`);
178
+ }
179
+ return res.json();
180
+ };
181
+ /** Pick a free local TCP port (loopback) for the adb forward. Lets the OS choose
182
+ * by binding to port 0, then releases it — there's an inherent TOCTOU window,
183
+ * but adb's `forward tcp:<port>` re-binds immediately after, and a clash surfaces
184
+ * as a loud adb error rather than a silent wrong-port attach. */
185
+ export function pickFreePort() {
186
+ return new Promise((resolve, reject) => {
187
+ const srv = createServer();
188
+ srv.once("error", reject);
189
+ srv.listen(0, "127.0.0.1", () => {
190
+ const addr = srv.address();
191
+ if (addr && typeof addr === "object") {
192
+ const port = addr.port;
193
+ srv.close(() => resolve(port));
194
+ }
195
+ else {
196
+ srv.close(() => reject(new Error("could not determine a free local port for adb forward")));
197
+ }
198
+ });
199
+ });
200
+ }
@@ -0,0 +1,54 @@
1
+ import type { Browser, CDPSession, Page } from "playwright-core";
2
+ import type { EngineCapabilities, EngineKind } from "../types.js";
3
+ import { type AdbRunner, type Fetcher } from "./adb.js";
4
+ /** The handles an Android attach surfaces — the same shape as the Chromium
5
+ * adapter's (a `Browser` + an eager `CDPSession`), plus the bookkeeping the
6
+ * session layer needs to tear the adb forward down on close. */
7
+ export interface AndroidAttachHandles {
8
+ browser: Browser;
9
+ page: Page;
10
+ cdp: CDPSession;
11
+ /** The loopback port the device socket was forwarded to. */
12
+ localPort: number;
13
+ /** The device serial the forward was scoped to (for `forward --remove`). */
14
+ serial: string;
15
+ /** Tears down the adb forward (`adb forward --remove tcp:<port>`). Best-effort;
16
+ * resolves even if the device was unplugged (the forward dies with it). */
17
+ removeForward(): Promise<void>;
18
+ }
19
+ /** Injectable dependencies — the IO seam. Defaults shell out to real adb + a real
20
+ * HTTP GET; the unit tests pass mocks so the orchestration is tested device-free. */
21
+ export interface AndroidAdapterDeps {
22
+ runAdb?: AdbRunner;
23
+ fetchJson?: Fetcher;
24
+ pickPort?: () => Promise<number>;
25
+ }
26
+ export declare class AndroidCdpAdapter {
27
+ readonly engine: EngineKind;
28
+ readonly capabilities: EngineCapabilities;
29
+ private readonly runAdb;
30
+ private readonly fetchJson;
31
+ private readonly pickPort;
32
+ constructor(deps?: AndroidAdapterDeps);
33
+ /** Discover a ready device. Lists devices via adb, parses, and selects (the
34
+ * requested serial if given, else the single ready one — structured errors
35
+ * otherwise). Surfaces `adb-missing` / `no-device` without a device crash. */
36
+ discoverDevice(serial?: string): Promise<string>;
37
+ /** The real BYOB path: discover device → forward the Chrome DevTools socket to
38
+ * a free loopback port → GET /json/version → webSocketDebuggerUrl →
39
+ * `chromium.connectOverCDP(wsUrl)`. Returns the `Browser` + eager `CDPSession`
40
+ * the session layer wires its bookkeeping onto, exactly like the Chromium
41
+ * attach, plus the forward-teardown handle. On any failure after the forward
42
+ * is established, the forward is removed before the error propagates (no leaked
43
+ * adb forwards). */
44
+ attach(opts?: {
45
+ serial?: string;
46
+ }): Promise<AndroidAttachHandles>;
47
+ /** Managed / ephemeral LAUNCH is not supported on Android. A phone's Chrome is
48
+ * the user's to open; browxai cannot spawn a browser process it owns on the
49
+ * device. Per the doctrine's no-silent-no-op rule this rejects with a
50
+ * structured, RFC-naming error rather than pretending. Promise-returning (not
51
+ * `async`) so the eslint require-await rule is honest — there is no awaited
52
+ * work, it is a structured refusal. */
53
+ launch(): Promise<never>;
54
+ }