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,545 @@
1
+ // Per-session Web Bluetooth / WebUSB / WebHID device emulation. Sibling of
2
+ // `permission` / `notification` / `fs-picker` — but a posture step further:
3
+ // where those modules govern access to APIs the browser already exposes,
4
+ // this one synthesises *responses* for three powerful platform APIs whose
5
+ // real semantics talk to physical devices the agent doesn't have. The use
6
+ // case is letting agents drive a page that gates a flow behind a Web
7
+ // Bluetooth / WebUSB / WebHID device picker without owning the hardware —
8
+ // the page believes it found and connected to a device because the
9
+ // init-script-wrapped `navigator.bluetooth.requestDevice()` /
10
+ // `navigator.usb.requestDevice()` / `navigator.hid.requestDevice()` resolve
11
+ // with synthetic objects matching the W3C shapes.
12
+ //
13
+ // Why this is its own capability (`device-emulation`, off-by-default):
14
+ // The wrappers tell the page it has access to physical devices that don't
15
+ // exist. A page that scans, names, and pairs against a Bluetooth heart-rate
16
+ // monitor will believe one is present. That's a posture-broadening change
17
+ // distinct from the surrounding policies — those say "the page CAN'T do X
18
+ // (and we record it)"; this one says "the page CAN do X (and we lie about
19
+ // what it found)". Off by default and loud-warned at boot, same posture
20
+ // class as `eval` / `network-body` / `secrets` / `extensions`.
21
+ //
22
+ // What the wrappers cover (v1 scope):
23
+ // - `navigator.bluetooth.requestDevice(options)` →
24
+ // resolves to a synthetic BluetoothDevice (`{ id, name, gatt }`); empty
25
+ // catalog rejects with `NotFoundError` ("User cancelled the requestDevice
26
+ // chooser") — same as the real picker when the human dismisses it.
27
+ // - `navigator.usb.requestDevice(options)` →
28
+ // resolves to a synthetic USBDevice (`{ vendorId, productId, productName,
29
+ // manufacturerName, serialNumber, deviceClass, … }`); empty catalog
30
+ // rejects with `NotFoundError`.
31
+ // - `navigator.hid.requestDevice(options)` →
32
+ // resolves to an Array<HIDDevice> (the HID API is multi-result by
33
+ // construction); empty catalog resolves with `[]` (real HID picker
34
+ // returns `[]` when the user picks nothing).
35
+ //
36
+ // The page-side requestDevice CATALOG (the synthetic device list) is set by
37
+ // the three tools (`emulate_bluetooth` / `emulate_usb` / `emulate_hid`).
38
+ // Calling with `{}` (no `devices`) clears the catalog — the next
39
+ // `requestDevice` rejects (Bluetooth/USB) or returns `[]` (HID), same as a
40
+ // human dismissing the picker. Calling with `{devices:[…]}` installs a new
41
+ // catalog — the next `requestDevice` resolves with the matching synthetic
42
+ // device. The pattern intentionally mirrors `fs_picker_respond`'s "stage
43
+ // the agent-supplied response, let the page's own action trigger the API
44
+ // call" model — the agent doesn't drive a tool when the page calls
45
+ // `requestDevice`; the page does, and the wrapper consults the catalog.
46
+ //
47
+ // What the wrappers DELIBERATELY do not cover (v1):
48
+ // - GATT service emulation for Bluetooth. The synthetic `BluetoothDevice`
49
+ // carries a stub `gatt` with `connect()` resolving to a stub server
50
+ // whose `getPrimaryService()` rejects with `NotFoundError`. A page that
51
+ // only needs the device-picker step to clear (a common pattern in BLE-
52
+ // onboarding flows) works as-is; a page that then exchanges
53
+ // characteristic reads/writes does not. Surfaced as deferred follow-up.
54
+ // - WebUSB transfer endpoints. `USBDevice.open()` / `selectConfiguration()`
55
+ // / `transferIn()` / `transferOut()` are stubs that resolve with empty/
56
+ // zero-byte results. Same justification: enough for picker-clearing.
57
+ // - HID input/output reports. `HIDDevice.open()` resolves; `sendReport()`
58
+ // resolves; `oninputreport` never fires (no synthetic device traffic).
59
+ // - Permission-style `getDevices()` enumeration (the W3C API has a
60
+ // post-permission read-side: `navigator.bluetooth.getDevices()`,
61
+ // `navigator.usb.getDevices()`, `navigator.hid.getDevices()`). v1
62
+ // wraps requestDevice only; getDevices returns the native value (which
63
+ // is `[]` on a Chromium without any granted devices). Surfaced as
64
+ // deferred follow-up.
65
+ //
66
+ // Per-action capture. Every page-side `requestDevice` call is appended to a
67
+ // buffer with a timestamp + the API + the agent-facing outcome (`resolved`
68
+ // / `rejected` / `empty`). `device_requests({session})` is the read-side
69
+ // view — separate from `ActionResult`'s policy-failure flips because
70
+ // `device-emulation` is an opt-in capability (you don't get a no-op-flips-
71
+ // ActionResult.ok footgun from a capability you explicitly enabled).
72
+ import { log } from "../util/logging.js";
73
+ import { PolicyRecordBuffer } from "./policy-buffer.js";
74
+ /** The three Web platform APIs browxai's device-emulation governs. */
75
+ export const SUPPORTED_DEVICE_APIS = ["bluetooth", "usb", "hid"];
76
+ /** Mutable per-session state. The page-side wrapper consults `catalog(api)`
77
+ * via the bridge binding on every `requestDevice` call, so a `set` call
78
+ * takes effect on the very next page-side request without a navigation. */
79
+ export class DeviceEmulationState {
80
+ /** Per-API catalog. Empty list (or absent entry) → wrapper falls into
81
+ * the user-dismissed-picker shape for that API. */
82
+ catalogs = {
83
+ bluetooth: { devices: [] },
84
+ usb: { devices: [] },
85
+ hid: { devices: [] },
86
+ };
87
+ /** Captured `requestDevice` calls — a bounded record ring (shared
88
+ * `PolicyRecordBuffer`; chatty pages can't grow this without bound,
89
+ * `device_requests` slices on `since`). */
90
+ records;
91
+ /** Contexts we've already installed the init-script + binding on.
92
+ * Idempotent install guard — BYOB reconnect / context rebuild MUST not
93
+ * double-wire. */
94
+ wired = new WeakSet();
95
+ /** True iff `device-emulation` capability was on at the time of attach.
96
+ * The page-side wrapper installs regardless (so a runtime capability
97
+ * toggle that adds the cap takes effect — though the canonical
98
+ * resolve-once-at-boot model means it doesn't), but the check binding
99
+ * short-circuits to `refused` when off. */
100
+ enabledByCapability;
101
+ constructor(enabledByCapability, cap = 200) {
102
+ this.enabledByCapability = enabledByCapability;
103
+ this.records = new PolicyRecordBuffer(cap);
104
+ }
105
+ /** Snapshot of one API's catalog. */
106
+ catalog(api) {
107
+ return { devices: [...this.catalogs[api].devices] };
108
+ }
109
+ /** Replace one API's catalog. `devices` may be empty (clears the catalog —
110
+ * next requestDevice rejects/empty). Returns the resolved catalog
111
+ * (echoed back so the tool's response shows what the wrapper will
112
+ * serve). */
113
+ set(api, devices) {
114
+ if (!Array.isArray(devices)) {
115
+ throw new Error(`emulate_${api}: \`devices\` must be an array (pass [] to clear the catalog)`);
116
+ }
117
+ // Normalise each entry: every field is optional on the agent side, but
118
+ // the page-side script needs deterministic defaults to compose a
119
+ // synthetic device object the page won't trip on.
120
+ this.catalogs[api] = {
121
+ devices: devices.map((d, i) => normaliseDevice(api, d, i)),
122
+ };
123
+ return this.catalog(api);
124
+ }
125
+ /** Append a request record. Caps the buffer at `cap`. */
126
+ record(rec) {
127
+ this.records.record(rec);
128
+ }
129
+ /** Slice records with `ts >= since`. Default since=0 returns all. */
130
+ since(since = 0) {
131
+ return this.records.since(since);
132
+ }
133
+ /** Capability gate snapshot. The check binding consults this on every
134
+ * page-side request. */
135
+ capabilityEnabled() {
136
+ return this.enabledByCapability;
137
+ }
138
+ /** Has this context already been wired? Idempotent install guard. */
139
+ hasContext(c) {
140
+ return this.wired.has(c);
141
+ }
142
+ /** Mark a context as wired. */
143
+ markContext(c) {
144
+ this.wired.add(c);
145
+ }
146
+ }
147
+ /** Default field values per API. Each tool call defaults missing fields so
148
+ * the page sees a complete synthetic device shape regardless of how
149
+ * sparsely the agent populated it. */
150
+ function normaliseDevice(api, d, index) {
151
+ const out = {
152
+ name: d.name ?? "browxai-virtual",
153
+ id: d.id ?? `browxai-${api}-${index}`,
154
+ vendorId: d.vendorId ?? 0x0000,
155
+ productId: d.productId ?? 0x0000,
156
+ manufacturerName: d.manufacturerName ?? "browxai virtual",
157
+ serialNumber: d.serialNumber ?? "BROWX-VIRTUAL",
158
+ deviceClass: d.deviceClass ?? 0xff,
159
+ deviceSubclass: d.deviceSubclass ?? 0x00,
160
+ deviceProtocol: d.deviceProtocol ?? 0x00,
161
+ services: d.services ?? [],
162
+ collections: d.collections ?? [],
163
+ };
164
+ return out;
165
+ }
166
+ /** Capture-safe stringify with a 4KB ceiling. Filters from a Web Bluetooth
167
+ * `requestDevice` call are typically a few hundred bytes (filter array
168
+ * with a couple of service UUIDs); we truncate aggressively only to defend
169
+ * the buffer from a chatty page composing absurd filters. */
170
+ function safeFilters(raw) {
171
+ try {
172
+ const s = JSON.stringify(raw);
173
+ if (s.length <= 4096)
174
+ return raw;
175
+ return JSON.parse(s.slice(0, 4096) + '"…"}'); // best-effort
176
+ }
177
+ catch {
178
+ return undefined;
179
+ }
180
+ }
181
+ /** BYOB warning — the init-script wrappers patch every new document in the
182
+ * attached Chrome's session-isolated context; the patches do NOT escape
183
+ * the context, but the per-deployment posture (the operator's main Chrome
184
+ * running with `--remote-debugging-port`) magnifies the consequences of a
185
+ * page that the agent told "you have a hardware device". Surfaced when
186
+ * `open_session({mode:"attached"})` engages with `device-emulation` on. */
187
+ export const BYOB_DEVICE_EMU_WARNING = "BYOB caveat: device-emulation wrappers patch `navigator.bluetooth` / `navigator.usb` / `navigator.hid` " +
188
+ "on an attached (not-owned) Chrome session. The wrappers are scoped to the context browxai opened, " +
189
+ "but the operator's main Chrome shares the same browser binary; treat any page reached during the " +
190
+ "session as having believed the synthetic catalog while it was set. Clearing the catalog (`emulate_*({devices:[]})`) " +
191
+ "restores the user-dismissed-picker shape on the next requestDevice; the wrapper itself stays installed " +
192
+ "for the life of the context.";
193
+ /** Init script that wraps the three Web platform device-picker APIs. Each
194
+ * wrapper consults `window.__browx_device_check({api, filters?})` (the
195
+ * exposeBinding from the server side) on every page-side `requestDevice`
196
+ * call — the binding returns a `{decision, devices?}` envelope the wrapper
197
+ * unpacks into the API-specific shape the spec expects. Keep browser-only
198
+ * JS (no TS-only syntax). Re-injected on `framenavigated` (idempotent:
199
+ * guards on `window.__browx_device_emu_installed`). */
200
+ export const DEVICE_EMU_PAGE_SCRIPT = `(() => {
201
+ if (window.__browx_device_emu_installed) return;
202
+ window.__browx_device_emu_installed = true;
203
+
204
+ function check(api, filters) {
205
+ try {
206
+ if (typeof window.__browx_device_check === "function") {
207
+ return Promise.resolve(window.__browx_device_check(JSON.stringify({
208
+ api: api,
209
+ filters: filters == null ? null : safeFilters(filters),
210
+ })));
211
+ }
212
+ } catch (_) {}
213
+ // Binding missing — safe-by-default empty catalog so the page sees the
214
+ // user-dismissed shape rather than a hung promise.
215
+ return Promise.resolve(JSON.stringify({ decision: "refused", devices: [] }));
216
+ }
217
+
218
+ function safeFilters(f) {
219
+ // Defensive shallow clone — page may pass non-serialisable garbage
220
+ // (BigInt, function, circular). Best-effort.
221
+ try { return JSON.parse(JSON.stringify(f)); } catch (_) { return null; }
222
+ }
223
+
224
+ function notFound(msg) {
225
+ var e = new Error(msg || "User cancelled the requestDevice() chooser.");
226
+ try { e.name = "NotFoundError"; } catch (_) {}
227
+ return e;
228
+ }
229
+
230
+ function parseResponse(raw) {
231
+ try {
232
+ var r = typeof raw === "string" ? JSON.parse(raw) : (raw || {});
233
+ var decision = r.decision;
234
+ var devices = Array.isArray(r.devices) ? r.devices : [];
235
+ return { decision: decision, devices: devices };
236
+ } catch (_) {
237
+ return { decision: "refused", devices: [] };
238
+ }
239
+ }
240
+
241
+ // ---- Bluetooth -------------------------------------------------------
242
+ // Synthesise the minimal BluetoothDevice + BluetoothRemoteGATTServer
243
+ // surface modern BLE-onboarding flows touch: id / name / gatt.connect()
244
+ // → stub server whose getPrimaryService() rejects (no GATT emulation in
245
+ // v1). Pages that gate on "we found a device" pass; pages that go on to
246
+ // exchange characteristic data do not.
247
+ function syntheticBluetoothDevice(spec) {
248
+ var name = spec.name || "browxai-virtual";
249
+ var id = spec.id || "browxai-bt-0";
250
+ var services = Array.isArray(spec.services) ? spec.services : [];
251
+ var device;
252
+ var gatt = {
253
+ get connected() { return gatt.__connected; },
254
+ __connected: false,
255
+ device: null, // set after device is created (circular ref)
256
+ connect: function () {
257
+ gatt.__connected = true;
258
+ return Promise.resolve(gatt);
259
+ },
260
+ disconnect: function () { gatt.__connected = false; },
261
+ getPrimaryService: function () {
262
+ return Promise.reject(notFound("GATT service emulation not supported in browxai v1"));
263
+ },
264
+ getPrimaryServices: function () {
265
+ return Promise.reject(notFound("GATT service emulation not supported in browxai v1"));
266
+ },
267
+ };
268
+ device = {
269
+ id: id,
270
+ name: name,
271
+ uuids: services,
272
+ gatt: gatt,
273
+ // EventTarget stubs — pages sometimes attach gattserverdisconnected;
274
+ // we accept and ignore.
275
+ addEventListener: function () {},
276
+ removeEventListener: function () {},
277
+ dispatchEvent: function () { return true; },
278
+ watchAdvertisements: function () { return Promise.resolve(undefined); },
279
+ unwatchAdvertisements: function () {},
280
+ get watchingAdvertisements() { return false; },
281
+ // forget() — modern API for revoking the permission; resolves no-op.
282
+ forget: function () { return Promise.resolve(undefined); },
283
+ };
284
+ gatt.device = device;
285
+ return device;
286
+ }
287
+ try {
288
+ var bt = navigator.bluetooth;
289
+ if (bt && typeof bt.requestDevice === "function") {
290
+ // Replace the entire requestDevice; we intentionally do NOT call
291
+ // through to the native API even when the agent didn't stage a
292
+ // catalog — calling through on a headless Chromium often hangs the
293
+ // promise indefinitely (no picker UI to dismiss).
294
+ Object.defineProperty(bt, "requestDevice", {
295
+ configurable: true,
296
+ writable: true,
297
+ value: function (options) {
298
+ var filters = options || null;
299
+ return check("bluetooth", filters).then(function (raw) {
300
+ var r = parseResponse(raw);
301
+ if (!r.devices.length) {
302
+ throw notFound();
303
+ }
304
+ return syntheticBluetoothDevice(r.devices[0]);
305
+ });
306
+ },
307
+ });
308
+ // getDevices — read-side: pre-paired devices. v1 returns the live
309
+ // catalog so a page polling for an already-paired device sees one.
310
+ if (typeof bt.getDevices === "function") {
311
+ Object.defineProperty(bt, "getDevices", {
312
+ configurable: true,
313
+ writable: true,
314
+ value: function () {
315
+ return check("bluetooth", null).then(function (raw) {
316
+ var r = parseResponse(raw);
317
+ return r.devices.map(syntheticBluetoothDevice);
318
+ });
319
+ },
320
+ });
321
+ }
322
+ }
323
+ } catch (_) {}
324
+
325
+ // ---- WebUSB ----------------------------------------------------------
326
+ // USBDevice synthesises the picker-resolve surface + stub
327
+ // open/close/selectConfiguration; transferIn/transferOut resolve with
328
+ // zero-byte responses so a page sequence doesn't reject mid-flight, but
329
+ // there's no actual data flow.
330
+ function syntheticUSBDevice(spec) {
331
+ var name = spec.name || "browxai-virtual";
332
+ return {
333
+ vendorId: spec.vendorId || 0,
334
+ productId: spec.productId || 0,
335
+ productName: name,
336
+ manufacturerName: spec.manufacturerName || "browxai virtual",
337
+ serialNumber: spec.serialNumber || "BROWX-VIRTUAL",
338
+ deviceClass: spec.deviceClass != null ? spec.deviceClass : 0xFF,
339
+ deviceSubclass: spec.deviceSubclass || 0,
340
+ deviceProtocol: spec.deviceProtocol || 0,
341
+ usbVersionMajor: 2,
342
+ usbVersionMinor: 0,
343
+ usbVersionSubminor: 0,
344
+ deviceVersionMajor: 1,
345
+ deviceVersionMinor: 0,
346
+ deviceVersionSubminor: 0,
347
+ configuration: null,
348
+ configurations: [],
349
+ opened: false,
350
+ open: function () { this.opened = true; return Promise.resolve(undefined); },
351
+ close: function () { this.opened = false; return Promise.resolve(undefined); },
352
+ selectConfiguration: function () { return Promise.resolve(undefined); },
353
+ claimInterface: function () { return Promise.resolve(undefined); },
354
+ releaseInterface: function () { return Promise.resolve(undefined); },
355
+ selectAlternateInterface: function () { return Promise.resolve(undefined); },
356
+ controlTransferIn: function () { return Promise.resolve({ data: new DataView(new ArrayBuffer(0)), status: "ok" }); },
357
+ controlTransferOut: function () { return Promise.resolve({ bytesWritten: 0, status: "ok" }); },
358
+ clearHalt: function () { return Promise.resolve(undefined); },
359
+ transferIn: function () { return Promise.resolve({ data: new DataView(new ArrayBuffer(0)), status: "ok" }); },
360
+ transferOut: function () { return Promise.resolve({ bytesWritten: 0, status: "ok" }); },
361
+ isochronousTransferIn: function () { return Promise.resolve({ data: new DataView(new ArrayBuffer(0)), packets: [] }); },
362
+ isochronousTransferOut: function () { return Promise.resolve({ packets: [] }); },
363
+ reset: function () { return Promise.resolve(undefined); },
364
+ forget: function () { return Promise.resolve(undefined); },
365
+ };
366
+ }
367
+ try {
368
+ var usb = navigator.usb;
369
+ if (usb && typeof usb.requestDevice === "function") {
370
+ Object.defineProperty(usb, "requestDevice", {
371
+ configurable: true,
372
+ writable: true,
373
+ value: function (options) {
374
+ var filters = options || null;
375
+ return check("usb", filters).then(function (raw) {
376
+ var r = parseResponse(raw);
377
+ if (!r.devices.length) {
378
+ throw notFound();
379
+ }
380
+ return syntheticUSBDevice(r.devices[0]);
381
+ });
382
+ },
383
+ });
384
+ if (typeof usb.getDevices === "function") {
385
+ Object.defineProperty(usb, "getDevices", {
386
+ configurable: true,
387
+ writable: true,
388
+ value: function () {
389
+ return check("usb", null).then(function (raw) {
390
+ var r = parseResponse(raw);
391
+ return r.devices.map(syntheticUSBDevice);
392
+ });
393
+ },
394
+ });
395
+ }
396
+ }
397
+ } catch (_) {}
398
+
399
+ // ---- WebHID ----------------------------------------------------------
400
+ // HIDDevice differs from USB in two ways the wrapper preserves:
401
+ // - requestDevice resolves to an Array<HIDDevice>, NOT a single
402
+ // device (even when only one match — see W3C spec).
403
+ // - Empty result is the user-dismissed shape, NOT a rejection.
404
+ function syntheticHIDDevice(spec) {
405
+ var name = spec.name || "browxai-virtual";
406
+ return {
407
+ opened: false,
408
+ vendorId: spec.vendorId || 0,
409
+ productId: spec.productId || 0,
410
+ productName: name,
411
+ collections: Array.isArray(spec.collections) ? spec.collections : [],
412
+ open: function () { this.opened = true; return Promise.resolve(undefined); },
413
+ close: function () { this.opened = false; return Promise.resolve(undefined); },
414
+ forget: function () { return Promise.resolve(undefined); },
415
+ sendReport: function () { return Promise.resolve(undefined); },
416
+ sendFeatureReport: function () { return Promise.resolve(undefined); },
417
+ receiveFeatureReport: function () { return Promise.resolve(new DataView(new ArrayBuffer(0))); },
418
+ addEventListener: function () {},
419
+ removeEventListener: function () {},
420
+ dispatchEvent: function () { return true; },
421
+ oninputreport: null,
422
+ };
423
+ }
424
+ try {
425
+ var hid = navigator.hid;
426
+ if (hid && typeof hid.requestDevice === "function") {
427
+ Object.defineProperty(hid, "requestDevice", {
428
+ configurable: true,
429
+ writable: true,
430
+ value: function (options) {
431
+ var filters = options || null;
432
+ return check("hid", filters).then(function (raw) {
433
+ var r = parseResponse(raw);
434
+ return r.devices.map(syntheticHIDDevice);
435
+ });
436
+ },
437
+ });
438
+ if (typeof hid.getDevices === "function") {
439
+ Object.defineProperty(hid, "getDevices", {
440
+ configurable: true,
441
+ writable: true,
442
+ value: function () {
443
+ return check("hid", null).then(function (raw) {
444
+ var r = parseResponse(raw);
445
+ return r.devices.map(syntheticHIDDevice);
446
+ });
447
+ },
448
+ });
449
+ }
450
+ }
451
+ } catch (_) {}
452
+ })();`;
453
+ /** Server-side wire-up. Installs:
454
+ * - `__browx_device_check` exposeBinding: page-side `requestDevice` calls
455
+ * route here; we read the catalog for the requested API, record the
456
+ * call, and return `{decision, devices}`. `decision` is informational
457
+ * (the page-side wrapper consults `devices.length` to pick the
458
+ * spec-correct empty-result shape per API).
459
+ * - The page-side init script (re-injected by Playwright on every new
460
+ * document).
461
+ *
462
+ * Idempotent on the same context. Errors during install are logged and
463
+ * swallowed — the page-side wrapper falls back to "decision: refused,
464
+ * devices: []" when the binding is missing, so a page calling
465
+ * requestDevice never deadlocks.
466
+ */
467
+ export async function attachDeviceEmulation(context, state) {
468
+ if (state.hasContext(context))
469
+ return;
470
+ state.markContext(context);
471
+ try {
472
+ await context.exposeBinding("__browx_device_check", (_source, payload) => {
473
+ try {
474
+ const o = JSON.parse(payload);
475
+ const api = o.api;
476
+ if (!SUPPORTED_DEVICE_APIS.includes(api)) {
477
+ return JSON.stringify({ decision: "refused", devices: [] });
478
+ }
479
+ const ts = Date.now();
480
+ const filters = safeFilters(o.filters ?? null);
481
+ // Capability is off → refuse: page-side wrapper still resolves
482
+ // to the user-dismissed shape (Bluetooth/USB reject; HID returns
483
+ // []), but we record the call so `device_requests` shows "the
484
+ // page asked for hardware and you didn't have the capability on".
485
+ if (!state.capabilityEnabled()) {
486
+ state.record({
487
+ api,
488
+ handledAs: "refused",
489
+ returned: 0,
490
+ ts,
491
+ ...(filters !== undefined && filters !== null ? { filters } : {}),
492
+ });
493
+ return JSON.stringify({ decision: "refused", devices: [] });
494
+ }
495
+ const cat = state.catalog(api);
496
+ const devices = cat.devices;
497
+ const handledAs = devices.length > 0 ? "resolved" : api === "hid" ? "empty" : "rejected";
498
+ const returned = api === "hid" ? devices.length : devices.length > 0 ? 1 : 0;
499
+ state.record({
500
+ api,
501
+ handledAs,
502
+ returned,
503
+ ts,
504
+ ...(filters !== undefined && filters !== null ? { filters } : {}),
505
+ });
506
+ // Bluetooth/USB are single-result picker APIs: the page-side
507
+ // wrapper expects to find devices[0] in the response and rejects
508
+ // when the list is empty. HID is multi-result: empty resolves
509
+ // with []. We pass the catalog verbatim; the wrapper knows the
510
+ // shape.
511
+ const responseDevices = api === "hid" ? devices : devices.slice(0, 1);
512
+ return JSON.stringify({ decision: handledAs, devices: responseDevices });
513
+ }
514
+ catch (err) {
515
+ log.warn("session.device-emu: check handler error", {
516
+ error: err instanceof Error ? err.message : String(err),
517
+ });
518
+ return JSON.stringify({ decision: "refused", devices: [] });
519
+ }
520
+ });
521
+ }
522
+ catch (err) {
523
+ log.warn("session.device-emu: exposeBinding install failed; page-side wrapper falls back to refused", {
524
+ error: err instanceof Error ? err.message : String(err),
525
+ });
526
+ }
527
+ try {
528
+ await context.addInitScript({ content: DEVICE_EMU_PAGE_SCRIPT });
529
+ for (const page of context.pages()) {
530
+ await page.evaluate(DEVICE_EMU_PAGE_SCRIPT).catch(() => undefined);
531
+ }
532
+ }
533
+ catch (err) {
534
+ log.warn("session.device-emu: addInitScript failed", {
535
+ error: err instanceof Error ? err.message : String(err),
536
+ });
537
+ }
538
+ }
539
+ /** Re-apply the init script to an existing page (no-op when the page-side
540
+ * guard is already set). Used by callers that opened pages BEFORE the
541
+ * attach engaged (rare). Public for tests; production callers go through
542
+ * `attachDeviceEmulation` which handles existing pages too. */
543
+ export async function reinjectDeviceEmuOnPage(page) {
544
+ await page.evaluate(DEVICE_EMU_PAGE_SCRIPT).catch(() => undefined);
545
+ }
@@ -0,0 +1,14 @@
1
+ import type { DeviceConfig } from "./types.js";
2
+ export interface DeviceSpec {
3
+ device?: string;
4
+ viewport?: {
5
+ width: number;
6
+ height: number;
7
+ };
8
+ }
9
+ export declare class UnknownDeviceError extends Error {
10
+ constructor(name: string, sample: string[]);
11
+ }
12
+ /** Resolve a spec into a DeviceConfig, or undefined when nothing was asked for.
13
+ * Throws UnknownDeviceError for an unrecognised preset name. */
14
+ export declare function resolveDevice(spec: DeviceSpec | undefined): DeviceConfig | undefined;
@@ -0,0 +1,44 @@
1
+ // resolve a device/viewport spec into a DeviceConfig.
2
+ //
3
+ // Two inputs, either or both:
4
+ // - `device`: a Playwright built-in device preset name ("iPhone 14",
5
+ // "Pixel 7", "Desktop Chrome", …) → viewport + DPR + isMobile + hasTouch
6
+ // + userAgent.
7
+ // - `viewport`: explicit { width, height } — overrides the preset's viewport
8
+ // (lets you pin a custom size while keeping a preset's mobile/touch/UA).
9
+ //
10
+ // Pure + dependency-light: `devices` is a static table from playwright-core.
11
+ import { devices } from "playwright-core";
12
+ export class UnknownDeviceError extends Error {
13
+ constructor(name, sample) {
14
+ super(`unknown device preset "${name}". Examples: ${sample.join(", ")}. ` +
15
+ `Any Playwright device name works (see playwright devices registry).`);
16
+ this.name = "UnknownDeviceError";
17
+ }
18
+ }
19
+ /** Resolve a spec into a DeviceConfig, or undefined when nothing was asked for.
20
+ * Throws UnknownDeviceError for an unrecognised preset name. */
21
+ export function resolveDevice(spec) {
22
+ if (!spec || (!spec.device && !spec.viewport))
23
+ return undefined;
24
+ let cfg = {};
25
+ if (spec.device) {
26
+ const preset = devices[spec.device];
27
+ if (!preset) {
28
+ const sample = Object.keys(devices)
29
+ .filter((n) => /iPhone 1[34]|Pixel 7|Desktop Chrome/.test(n))
30
+ .slice(0, 4);
31
+ throw new UnknownDeviceError(spec.device, sample.length ? sample : Object.keys(devices).slice(0, 4));
32
+ }
33
+ cfg = {
34
+ viewport: preset.viewport,
35
+ deviceScaleFactor: preset.deviceScaleFactor,
36
+ isMobile: preset.isMobile,
37
+ hasTouch: preset.hasTouch,
38
+ userAgent: preset.userAgent,
39
+ };
40
+ }
41
+ if (spec.viewport)
42
+ cfg = { ...cfg, viewport: spec.viewport };
43
+ return cfg;
44
+ }
@@ -0,0 +1,62 @@
1
+ import type { BrowserContext, Page } from "playwright-core";
2
+ export type DialogMode = "accept" | "dismiss" | "raise" | "accept-prompt-with";
3
+ /** Public, runtime-mutable shape. `mode:"accept-prompt-with"` requires `text`. */
4
+ export interface DialogPolicy {
5
+ mode: DialogMode;
6
+ /** Required for `accept-prompt-with`. Used as the answer for prompts;
7
+ * alert/confirm still accept (no answer needed). */
8
+ text?: string;
9
+ }
10
+ /** One captured dialog event, exposed on `ActionResult.dialogs[]`. */
11
+ export interface DialogRecord {
12
+ kind: "alert" | "confirm" | "prompt" | "beforeunload";
13
+ message: string;
14
+ defaultValue?: string;
15
+ /** What the server actually did. `"raised"` means we dismissed it
16
+ * server-side (to unblock the page) AND the policy was `raise`, so the
17
+ * action will be marked failed. */
18
+ handledAs: "accepted" | "dismissed" | "raised";
19
+ /** epoch ms — used by the action-window slice. */
20
+ ts: number;
21
+ }
22
+ /** Hint emitted on `ActionResult.failure.hint` when `raise` mode fired.
23
+ * Stable, agent-facing string — referenced in docs/tool-reference.md. */
24
+ export declare const UNHANDLED_DIALOG_HINT: string;
25
+ /** Mutable per-session state. The handler reads `current()` on every fire,
26
+ * so a `set_dialog_policy` call takes effect on the very next dialog. */
27
+ export declare class DialogPolicyState {
28
+ private policy;
29
+ /** Bounded record ring (shared `PolicyRecordBuffer` — the hard cap so a chatty
30
+ * page can't grow this without bound; the per-action slice is the only
31
+ * consumer, older records are noise). */
32
+ private readonly records;
33
+ /** Pages we've already installed the handler on. Lets the
34
+ * `context.on('page')` wiring be idempotent — re-attaching to an existing
35
+ * page (BYOB reconnect, profile-restore) doesn't double-fire. */
36
+ private wired;
37
+ constructor(initial?: DialogPolicy, cap?: number);
38
+ current(): DialogPolicy;
39
+ set(next: DialogPolicy): DialogPolicy;
40
+ /** Append a dialog record. Caps the buffer at `cap`. */
41
+ record(rec: DialogRecord): void;
42
+ /** Slice records with `ts >= since`. Used by the action-window. */
43
+ since(since: number): DialogRecord[];
44
+ /** True if any record in `[since, now]` was handled in `raise` mode.
45
+ * When true, the action-window flips the result to `ok:false`. */
46
+ raisedSince(since: number): boolean;
47
+ /** Has this page already been wired? Idempotent install guard. */
48
+ hasPage(p: Page): boolean;
49
+ /** Mark a page as wired. */
50
+ markPage(p: Page): void;
51
+ }
52
+ /** Parse the spec's compact string form (`"accept-prompt-with:<text>"`) into
53
+ * the runtime `DialogPolicy` shape. Idempotent — also accepts the object form. */
54
+ export declare function parseDialogPolicyArg(v: string | DialogPolicy | undefined): DialogPolicy;
55
+ /** Install the `page.on('dialog')` handler on a single page if not already
56
+ * wired. Safe to call repeatedly; no-op when the page is already known. */
57
+ export declare function installDialogHandler(page: Page, state: DialogPolicyState): void;
58
+ /** Wire the dialog handler into every page in a context, plus a `context.on(
59
+ * 'page')` listener that wires future pages. Call once per session-creation;
60
+ * the `context.on('page')` install is idempotent because `installDialogHandler`
61
+ * short-circuits already-wired pages. */
62
+ export declare function attachDialogPolicy(context: BrowserContext, state: DialogPolicyState): void;