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,187 @@
1
+ // BYOB / CDP-attach primitives — the per-engine attach bodies the engine modules
2
+ // (adapters/<engine>.engine.ts) call from their `makeAdapter` byob branch. Split
3
+ // out of byob.ts so the engine-registration graph (register-engines → the engine
4
+ // modules → here) does NOT cycle back through `byob.ts`'s `openByobSession` (which
5
+ // imports the registry + register-engines for its mode dispatch). Every body here
6
+ // is verbatim from the pre-P1 `openByobSession` chromium/android branches.
7
+ //
8
+ // Off by default; the canonical entrypoint must opt in via BROWX_ATTACH_CDP=<loopback>.
9
+ // Loopback-only (127.0.0.1 / localhost / ::1) — refuses non-loopback hosts.
10
+ // Not-owned semantics: on close we detach the CDP session, but never close the
11
+ // browser or reset its storage — that's the consumer's Chrome, not ours.
12
+ import { log } from "../util/logging.js";
13
+ import { AndroidCdpAdapter, PlaywrightChromiumAdapter } from "../engine/index.js";
14
+ const LOOPBACK_HOSTS = new Set(["127.0.0.1", "localhost", "::1", "[::1]"]);
15
+ function assertLoopback(endpoint) {
16
+ let url;
17
+ try {
18
+ url = new URL(endpoint);
19
+ }
20
+ catch {
21
+ throw new Error(`BROWX_ATTACH_CDP: invalid URL "${endpoint}"`);
22
+ }
23
+ if (!LOOPBACK_HOSTS.has(url.hostname)) {
24
+ throw new Error(`BROWX_ATTACH_CDP: refusing non-loopback host "${url.hostname}". ` +
25
+ `Only 127.0.0.1, localhost, ::1 are allowed (CDP port is unauthenticated).`);
26
+ }
27
+ return url;
28
+ }
29
+ const ATTACH_WARNING = [
30
+ "================================================================",
31
+ " browxai is attaching to an EXTERNAL Chrome over CDP (BYOB).",
32
+ " This Chrome is treated as NOT-OWNED: on shutdown browxai detaches",
33
+ " but does NOT close the browser or reset its storage.",
34
+ "",
35
+ " Sharp edges (you accepted these by setting BROWX_ATTACH_CDP):",
36
+ " - The browser may have --disable-web-security (SOP off).",
37
+ " - The browser holds your real profile: every cookie, password,",
38
+ " and authed tab is in scope of any page the agent visits.",
39
+ " - The CDP port is unauthenticated; any local process can attach.",
40
+ "",
41
+ " Managed mode (the default) avoids all of the above. See docs/threat-model.md.",
42
+ "================================================================",
43
+ ].join("\n");
44
+ // The attached page may pre-paint with zero metrics; ensure a usable viewport so
45
+ // the visible-rect bbox path (page/bbox.ts) doesn't intersect against
46
+ // `innerWidth=0 innerHeight=0` and produce `null + clipped: true` for every
47
+ // visible element. Read the *layout* viewport via CDP (authoritative regardless
48
+ // of `window.inner*`), cross-check the window dims, and install a 1280x800
49
+ // default only if BOTH read as zero. Shared by the desktop-CDP attach and the
50
+ // Android-over-adb attach — both ride a real CDPSession. Best-effort; a failure
51
+ // is non-fatal (bbox falls back to the un-clipped client rect).
52
+ async function ensureViewport(cdp) {
53
+ try {
54
+ const layout = (await cdp.send("Page.getLayoutMetrics").catch(() => null));
55
+ const lw = layout?.layoutViewport?.clientWidth ?? 0;
56
+ const lh = layout?.layoutViewport?.clientHeight ?? 0;
57
+ const { result } = (await cdp.send("Runtime.evaluate", {
58
+ expression: "({ w: window.innerWidth || 0, h: window.innerHeight || 0 })",
59
+ returnByValue: true,
60
+ }));
61
+ const v = result.value ?? { w: 0, h: 0 };
62
+ const goodLayout = lw > 0 && lh > 0;
63
+ const goodWindow = v.w > 0 && v.h > 0;
64
+ if (!goodLayout && !goodWindow) {
65
+ log.info("session.byob: attached page has zero viewport; setting 1280x800 default", {
66
+ layout: { lw, lh },
67
+ window: v,
68
+ });
69
+ await cdp
70
+ .send("Emulation.setDeviceMetricsOverride", {
71
+ width: 1280,
72
+ height: 800,
73
+ deviceScaleFactor: 0,
74
+ mobile: false,
75
+ })
76
+ .catch(() => undefined);
77
+ }
78
+ else {
79
+ log.info("session.byob: attached page viewport ok", { layout: { lw, lh }, window: v });
80
+ }
81
+ }
82
+ catch {
83
+ /* not fatal — the bbox path falls back to un-clipped client rect when both probes fail */
84
+ }
85
+ }
86
+ const ANDROID_ATTACH_WARNING = [
87
+ "================================================================",
88
+ " browxai is attaching to your REAL Chrome-on-Android over adb + CDP.",
89
+ " This is the full-fidelity BYOB lane: the device's",
90
+ " Chrome is treated as NOT-OWNED — on shutdown browxai detaches and",
91
+ " removes the adb forward, but never closes the browser or resets its",
92
+ " storage. The phone holds your real profile: every cookie, password,",
93
+ " and authed tab is in scope of any page the agent visits.",
94
+ " Managed mode (the default) avoids all of the above. See docs/threat-model.md.",
95
+ "================================================================",
96
+ ].join("\n");
97
+ /** Android BYOB — discover real Chrome-on-Android over adb + CDP and attach.
98
+ * Distinct from the desktop URL-attach path: the endpoint is DISCOVERED
99
+ * (adb forward → /json/version → wsUrl), not configured. The forwarded socket is
100
+ * loopback by construction (adb forwards to 127.0.0.1), so the same not-owned
101
+ * policy applies; close additionally removes the adb forward. Full CDP, so the
102
+ * session carries `cdp()` and the substrates pick the CDP path automatically. */
103
+ export async function openAndroidByobSession() {
104
+ log.warn(ANDROID_ATTACH_WARNING);
105
+ const adapter = new AndroidCdpAdapter();
106
+ const serial = process.env.BROWX_ANDROID_SERIAL?.trim() || undefined;
107
+ // Keep the handles object intact (don't destructure `removeForward` — it is the
108
+ // adapter's bound teardown, called below).
109
+ const handles = await adapter.attach({ serial });
110
+ const { page, cdp } = handles;
111
+ log.info("session.byob: attached to Chrome-on-Android", {
112
+ serial: handles.serial,
113
+ localPort: handles.localPort,
114
+ engine: "android",
115
+ });
116
+ await ensureViewport(cdp);
117
+ let closed = false;
118
+ return {
119
+ mode: "byob",
120
+ ownsBrowser: false,
121
+ engine: "android",
122
+ page: () => page,
123
+ // Android Chrome speaks full CDP — the eager session is always present.
124
+ cdp: () => cdp,
125
+ close: async () => {
126
+ if (closed)
127
+ return;
128
+ closed = true;
129
+ log.info("session.byob: detaching Chrome-on-Android (device stays open — not-owned)");
130
+ await cdp.detach().catch(() => undefined);
131
+ await handles.removeForward();
132
+ // Do NOT call browser.close() — not-owned (it's the user's phone Chrome).
133
+ },
134
+ };
135
+ }
136
+ /** Assert the BYOB attach endpoint is present + loopback, returning it as a
137
+ * string. The firefox / webkit engine modules call this before surfacing their
138
+ * structured attach refusal, preserving the EXACT pre-relocation order (the
139
+ * `!attachCdp` throw, then the loopback assertion, then the per-engine refusal).
140
+ * Shared so the loopback policy lives in one place. */
141
+ export function assertByobAttach(opts) {
142
+ if (!opts.attachCdp) {
143
+ throw new Error("session.byob: the CDP-attach lane requires BROWX_ATTACH_CDP (a loopback CDP endpoint). " +
144
+ 'For the android engine use browserType:"android" (endpoint discovered over adb).');
145
+ }
146
+ return assertLoopback(opts.attachCdp).toString();
147
+ }
148
+ /** The Chromium CDP-attach (BYOB) lane — the desktop URL-attach path, extracted
149
+ * verbatim from the old `openByobSession` chromium body. Asserts the loopback
150
+ * endpoint, attaches over CDP, ensures a usable viewport, and builds the
151
+ * not-owned `BrowserSession`. The chromium engine module's `makeAdapter` byob
152
+ * branch calls this; firefox/webkit/safari surface their own structured attach
153
+ * refusals from their own engine modules, and android attaches over adb via
154
+ * `openAndroidByobSession` — so no engine-name branch survives here. */
155
+ export async function attachByobChromium(opts) {
156
+ if (!opts.attachCdp) {
157
+ throw new Error("session.byob: the CDP-attach lane requires BROWX_ATTACH_CDP (a loopback CDP endpoint). " +
158
+ 'For the android engine use browserType:"android" (endpoint discovered over adb).');
159
+ }
160
+ const url = assertLoopback(opts.attachCdp);
161
+ log.warn(ATTACH_WARNING);
162
+ log.info("session.byob: attaching", {
163
+ endpoint: url.toString(),
164
+ owner: "external",
165
+ engine: "chromium",
166
+ });
167
+ const adapter = new PlaywrightChromiumAdapter();
168
+ const { page, cdp } = await adapter.attachOverCdp(url.toString());
169
+ await ensureViewport(cdp);
170
+ let closed = false;
171
+ return {
172
+ mode: "byob",
173
+ ownsBrowser: false,
174
+ engine: "chromium",
175
+ page: () => page,
176
+ // chromium always mints a CDP session; `cdp` is non-undefined here.
177
+ cdp: () => cdp,
178
+ close: async () => {
179
+ if (closed)
180
+ return;
181
+ closed = true;
182
+ log.info("session.byob: detaching (browser stays open — not-owned)");
183
+ await cdp.detach().catch(() => undefined);
184
+ // Do NOT call browser.close() / context.close() — not-owned.
185
+ },
186
+ };
187
+ }
@@ -0,0 +1,8 @@
1
+ import "../engine/register-engines.js";
2
+ import type { BrowserSession, SessionOptions } from "./types.js";
3
+ export { attachByobChromium, openAndroidByobSession, assertByobAttach } from "./byob-attach.js";
4
+ /** BYOB / attach session — resolves the engine and hands off to the
5
+ * EngineRegistry's per-engine attach body. */
6
+ export declare function openByobSession(opts: SessionOptions & {
7
+ attachCdp?: string;
8
+ }): Promise<BrowserSession>;
@@ -0,0 +1,20 @@
1
+ // BYOB / attach session — the MODE-concern entry point. Post-RFC-0004-P1 this
2
+ // keeps only its mode concern: it resolves the engine and hands off to the
3
+ // EngineRegistry, whose `makeAdapter` owns the per-engine attach body (android
4
+ // over adb; chromium over CDP; firefox/webkit/safari structured refusals — all in
5
+ // adapters/<engine>.engine.ts). The `engine === "…"` dispatch chain that used to
6
+ // live here is now data-driven — byte-identical, only relocated.
7
+ //
8
+ // The attach PRIMITIVES (`attachByobChromium` / `openAndroidByobSession` /
9
+ // `assertByobAttach`) live in byob-attach.ts so the engine-registration graph does
10
+ // not cycle back through this module's `engineEntry` import; they are re-exported
11
+ // here for back-compat with existing importers.
12
+ import { engineEntry } from "../engine/registry.js";
13
+ import "../engine/register-engines.js";
14
+ export { attachByobChromium, openAndroidByobSession, assertByobAttach } from "./byob-attach.js";
15
+ /** BYOB / attach session — resolves the engine and hands off to the
16
+ * EngineRegistry's per-engine attach body. */
17
+ export async function openByobSession(opts) {
18
+ const engine = opts.browserType ?? "chromium";
19
+ return engineEntry(engine).makeAdapter({ ...opts, launchMode: "byob" });
20
+ }
@@ -0,0 +1,100 @@
1
+ import type { Page } from "playwright-core";
2
+ /** Result envelope for a cache-entry body — text-like content lands as a
3
+ * string, anything binary-ish as base64 + the byte count. */
4
+ export type CacheEntryBody = {
5
+ kind: "text";
6
+ text: string;
7
+ contentType: string | null;
8
+ status: number;
9
+ headers: Record<string, string>;
10
+ } | {
11
+ kind: "binary";
12
+ contentBase64: string;
13
+ byteLength: number;
14
+ contentType: string | null;
15
+ status: number;
16
+ headers: Record<string, string>;
17
+ };
18
+ /** List every cache storage name visible to the current origin. */
19
+ export declare function cachesListStorages(page: Page, tool: string): Promise<{
20
+ names: string[];
21
+ origin: string;
22
+ }>;
23
+ /** List the entries in a single cache. Optional `urlPattern` is a
24
+ * substring match against each entry's `request.url` (case-sensitive
25
+ * — adopters that want regex can filter the result themselves). */
26
+ export declare function cachesList(page: Page, args: {
27
+ cacheName: string;
28
+ urlPattern?: string;
29
+ }, tool: string): Promise<{
30
+ entries: Array<{
31
+ url: string;
32
+ method: string;
33
+ }>;
34
+ origin: string;
35
+ cacheName: string;
36
+ }>;
37
+ /** Return the response body of a single entry. Text-like content types
38
+ * arrive as a UTF-8 string; everything else as base64. */
39
+ export declare function cachesGet(page: Page, args: {
40
+ cacheName: string;
41
+ url: string;
42
+ }, tool: string): Promise<{
43
+ found: false;
44
+ cacheName: string;
45
+ url: string;
46
+ origin: string;
47
+ } | (CacheEntryBody & {
48
+ found: true;
49
+ cacheName: string;
50
+ url: string;
51
+ origin: string;
52
+ })>;
53
+ /** Put an entry. `response.body` is either a UTF-8 string (default —
54
+ * same shape as the Cache API's `new Response(string)`) or base64 bytes
55
+ * via `{contentBase64: ...}`. Auto-opens (= creates) the cache storage. */
56
+ export declare function cachesPut(page: Page, args: {
57
+ cacheName: string;
58
+ url: string;
59
+ response: {
60
+ status?: number;
61
+ headers?: Record<string, string>;
62
+ body?: string;
63
+ contentBase64?: string;
64
+ };
65
+ }, tool: string): Promise<{
66
+ ok: true;
67
+ cacheName: string;
68
+ url: string;
69
+ origin: string;
70
+ }>;
71
+ /** Delete one entry. Returns `existed:true` if the entry was present. */
72
+ export declare function cachesDelete(page: Page, args: {
73
+ cacheName: string;
74
+ url: string;
75
+ }, tool: string): Promise<{
76
+ ok: true;
77
+ existed: boolean;
78
+ cacheName: string;
79
+ url: string;
80
+ origin: string;
81
+ }>;
82
+ /** Clear every entry from a cache (the cache storage itself remains). */
83
+ export declare function cachesClear(page: Page, args: {
84
+ cacheName: string;
85
+ }, tool: string): Promise<{
86
+ ok: true;
87
+ cleared: number;
88
+ cacheName: string;
89
+ origin: string;
90
+ }>;
91
+ /** Delete a cache storage entirely. Returns `existed:true` if the storage
92
+ * was present (idempotent for callers — repeat calls return `existed:false`). */
93
+ export declare function cachesDeleteStorage(page: Page, args: {
94
+ cacheName: string;
95
+ }, tool: string): Promise<{
96
+ ok: true;
97
+ existed: boolean;
98
+ cacheName: string;
99
+ origin: string;
100
+ }>;
@@ -0,0 +1,166 @@
1
+ // Cache API CRUD — storage-state surface extension.
2
+ //
3
+ // Sibling of cookies / localStorage / sessionStorage CRUD. Drives the W3C
4
+ // Cache API (`window.caches`) via `page.evaluate` — the same pattern the
5
+ // web-storage helpers in `storage.ts` use, and for the same reason: the
6
+ // Cache API is ORIGIN-SCOPED. The session MUST be navigated to the target
7
+ // origin before any of these tools work; on `about:blank` or a different
8
+ // origin the call rejects with a navigation hint.
9
+ //
10
+ // What's actually stored: each cache entry is keyed by a Request and
11
+ // carries a Response. The CRUD surface here treats the request side as a
12
+ // URL (the common shape Service Workers populate) and the response side
13
+ // as `{status, headers?, body}` with the body delivered as a UTF-8 string
14
+ // or base64 (auto-detected on the way out — text/* / application/json
15
+ // arrive as strings, anything else as `{contentBase64, byteLength}`).
16
+ //
17
+ // Capability split (server.ts):
18
+ // - reads (`caches_list_storages`, `caches_list`, `caches_get`) → `read`
19
+ // - writes (`caches_put`, `caches_delete`, `caches_clear`,
20
+ // `caches_delete_storage`) → `action`
21
+ //
22
+ // Tracker-ID hygiene: zero. Each cache entry is identified by its
23
+ // `(cacheName, url)` pair — the platform's native key. No synthetic IDs.
24
+ /** Storage object on `window.caches`. */
25
+ const CACHE_API = "caches";
26
+ /** Origin-scope guard — same posture as web-storage. The Cache API is
27
+ * defined on every secure context Chromium ships, but it's still origin-
28
+ * bound: `window.caches.open()` returns the cache for the page's origin,
29
+ * not a global store. Navigate first. */
30
+ function cacheOriginGuard(page, tool) {
31
+ let url;
32
+ try {
33
+ url = page.url();
34
+ }
35
+ catch {
36
+ url = "";
37
+ }
38
+ if (!url || url === "about:blank") {
39
+ throw new Error(`${tool}: Cache API is origin-scoped and the page is at "${url || "(unknown)"}". ` +
40
+ `Navigate the session to the target origin first.`);
41
+ }
42
+ }
43
+ // ---- reads -----------------------------------------------------------------
44
+ /** List every cache storage name visible to the current origin. */
45
+ export async function cachesListStorages(page, tool) {
46
+ cacheOriginGuard(page, tool);
47
+ const expr = `(async () => { if (typeof ${CACHE_API} === "undefined") return { names: [], origin: location.origin }; ` +
48
+ `var n = await ${CACHE_API}.keys(); ` +
49
+ `return { names: n, origin: location.origin }; })()`;
50
+ return await page.evaluate(expr);
51
+ }
52
+ /** List the entries in a single cache. Optional `urlPattern` is a
53
+ * substring match against each entry's `request.url` (case-sensitive
54
+ * — adopters that want regex can filter the result themselves). */
55
+ export async function cachesList(page, args, tool) {
56
+ if (!args.cacheName)
57
+ throw new Error(`${tool}: \`cacheName\` is required`);
58
+ cacheOriginGuard(page, tool);
59
+ const expr = `(async () => { ` +
60
+ `var c = await ${CACHE_API}.open(${JSON.stringify(args.cacheName)}); ` +
61
+ `var reqs = await c.keys(); ` +
62
+ `var pat = ${JSON.stringify(args.urlPattern ?? "")}; ` +
63
+ `var out = []; ` +
64
+ `for (var i = 0; i < reqs.length; i++) { ` +
65
+ ` var r = reqs[i]; ` +
66
+ ` if (pat && r.url.indexOf(pat) === -1) continue; ` +
67
+ ` out.push({ url: r.url, method: r.method }); ` +
68
+ `} ` +
69
+ `return { entries: out, origin: location.origin, cacheName: ${JSON.stringify(args.cacheName)} }; })()`;
70
+ return await page.evaluate(expr);
71
+ }
72
+ /** Return the response body of a single entry. Text-like content types
73
+ * arrive as a UTF-8 string; everything else as base64. */
74
+ export async function cachesGet(page, args, tool) {
75
+ if (!args.cacheName)
76
+ throw new Error(`${tool}: \`cacheName\` is required`);
77
+ if (!args.url)
78
+ throw new Error(`${tool}: \`url\` is required`);
79
+ cacheOriginGuard(page, tool);
80
+ const expr = `(async () => { ` +
81
+ `var c = await ${CACHE_API}.open(${JSON.stringify(args.cacheName)}); ` +
82
+ `var res = await c.match(${JSON.stringify(args.url)}); ` +
83
+ `if (!res) return { found: false, cacheName: ${JSON.stringify(args.cacheName)}, url: ${JSON.stringify(args.url)}, origin: location.origin }; ` +
84
+ `var headers = {}; res.headers.forEach(function (v, k) { headers[k] = v; }); ` +
85
+ `var ct = res.headers.get("content-type"); ` +
86
+ `var isText = ct && /^(text\\/|application\\/(json|javascript|xml|x-www-form-urlencoded))|charset=/i.test(ct); ` +
87
+ `if (isText) { var t = await res.text(); return { found: true, kind: "text", text: t, contentType: ct, status: res.status, headers: headers, cacheName: ${JSON.stringify(args.cacheName)}, url: ${JSON.stringify(args.url)}, origin: location.origin }; } ` +
88
+ `var buf = await res.arrayBuffer(); ` +
89
+ `var bytes = new Uint8Array(buf); var bin = ""; ` +
90
+ `for (var i = 0; i < bytes.length; i++) bin += String.fromCharCode(bytes[i]); ` +
91
+ `var b64 = btoa(bin); ` +
92
+ `return { found: true, kind: "binary", contentBase64: b64, byteLength: bytes.length, contentType: ct, status: res.status, headers: headers, cacheName: ${JSON.stringify(args.cacheName)}, url: ${JSON.stringify(args.url)}, origin: location.origin }; })()`;
93
+ return await page.evaluate(expr);
94
+ }
95
+ // ---- writes ----------------------------------------------------------------
96
+ /** Put an entry. `response.body` is either a UTF-8 string (default —
97
+ * same shape as the Cache API's `new Response(string)`) or base64 bytes
98
+ * via `{contentBase64: ...}`. Auto-opens (= creates) the cache storage. */
99
+ export async function cachesPut(page, args, tool) {
100
+ if (!args.cacheName)
101
+ throw new Error(`${tool}: \`cacheName\` is required`);
102
+ if (!args.url)
103
+ throw new Error(`${tool}: \`url\` is required`);
104
+ if (!args.response)
105
+ throw new Error(`${tool}: \`response\` is required`);
106
+ if (args.response.body !== undefined && args.response.contentBase64 !== undefined) {
107
+ throw new Error(`${tool}: pass exactly one of \`response.body\` (string) or \`response.contentBase64\` — not both`);
108
+ }
109
+ cacheOriginGuard(page, tool);
110
+ const bodyArg = JSON.stringify({
111
+ body: args.response.body ?? null,
112
+ contentBase64: args.response.contentBase64 ?? null,
113
+ status: args.response.status ?? 200,
114
+ headers: args.response.headers ?? {},
115
+ });
116
+ const expr = `(async () => { ` +
117
+ `var spec = ${bodyArg}; ` +
118
+ `var c = await ${CACHE_API}.open(${JSON.stringify(args.cacheName)}); ` +
119
+ `var body; ` +
120
+ `if (spec.contentBase64 !== null) { ` +
121
+ ` var bin = atob(spec.contentBase64); ` +
122
+ ` var bytes = new Uint8Array(bin.length); ` +
123
+ ` for (var i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i); ` +
124
+ ` body = bytes; ` +
125
+ `} else if (spec.body !== null) { body = spec.body; } else { body = ""; } ` +
126
+ `var res = new Response(body, { status: spec.status, headers: spec.headers }); ` +
127
+ `await c.put(${JSON.stringify(args.url)}, res); ` +
128
+ `return { ok: true, cacheName: ${JSON.stringify(args.cacheName)}, url: ${JSON.stringify(args.url)}, origin: location.origin }; })()`;
129
+ return await page.evaluate(expr);
130
+ }
131
+ /** Delete one entry. Returns `existed:true` if the entry was present. */
132
+ export async function cachesDelete(page, args, tool) {
133
+ if (!args.cacheName)
134
+ throw new Error(`${tool}: \`cacheName\` is required`);
135
+ if (!args.url)
136
+ throw new Error(`${tool}: \`url\` is required`);
137
+ cacheOriginGuard(page, tool);
138
+ const expr = `(async () => { ` +
139
+ `var c = await ${CACHE_API}.open(${JSON.stringify(args.cacheName)}); ` +
140
+ `var existed = await c.delete(${JSON.stringify(args.url)}); ` +
141
+ `return { ok: true, existed: existed, cacheName: ${JSON.stringify(args.cacheName)}, url: ${JSON.stringify(args.url)}, origin: location.origin }; })()`;
142
+ return await page.evaluate(expr);
143
+ }
144
+ /** Clear every entry from a cache (the cache storage itself remains). */
145
+ export async function cachesClear(page, args, tool) {
146
+ if (!args.cacheName)
147
+ throw new Error(`${tool}: \`cacheName\` is required`);
148
+ cacheOriginGuard(page, tool);
149
+ const expr = `(async () => { ` +
150
+ `var c = await ${CACHE_API}.open(${JSON.stringify(args.cacheName)}); ` +
151
+ `var reqs = await c.keys(); ` +
152
+ `for (var i = 0; i < reqs.length; i++) await c.delete(reqs[i]); ` +
153
+ `return { ok: true, cleared: reqs.length, cacheName: ${JSON.stringify(args.cacheName)}, origin: location.origin }; })()`;
154
+ return await page.evaluate(expr);
155
+ }
156
+ /** Delete a cache storage entirely. Returns `existed:true` if the storage
157
+ * was present (idempotent for callers — repeat calls return `existed:false`). */
158
+ export async function cachesDeleteStorage(page, args, tool) {
159
+ if (!args.cacheName)
160
+ throw new Error(`${tool}: \`cacheName\` is required`);
161
+ cacheOriginGuard(page, tool);
162
+ const expr = `(async () => { ` +
163
+ `var existed = await ${CACHE_API}.delete(${JSON.stringify(args.cacheName)}); ` +
164
+ `return { ok: true, existed: existed, cacheName: ${JSON.stringify(args.cacheName)}, origin: location.origin }; })()`;
165
+ return await page.evaluate(expr);
166
+ }
@@ -0,0 +1,149 @@
1
+ import type { BrowserContext, Page } from "playwright-core";
2
+ /** The three Web platform APIs browxai's device-emulation governs. */
3
+ export declare const SUPPORTED_DEVICE_APIS: readonly ["bluetooth", "usb", "hid"];
4
+ export type DeviceApi = (typeof SUPPORTED_DEVICE_APIS)[number];
5
+ /** Agent-supplied synthetic device entry. All three APIs share the union
6
+ * shape; the wrapper picks the fields relevant to its API (Bluetooth uses
7
+ * `name` + `id` + `services`; USB uses the vendor/product/class fields;
8
+ * HID uses `vendorId` + `productId` + `productName`). A single entry can
9
+ * carry every field — the page sees only what the spec exposes for its API. */
10
+ export interface SyntheticDevice {
11
+ /** Display name. Bluetooth uses this as `.name`; USB exposes it as
12
+ * `.productName`; HID as `.productName`. Default `"browxai-virtual"`. */
13
+ name?: string;
14
+ /** Bluetooth: stable device id (UUID-style string). Default
15
+ * `"browxai-<api>-<index>"`. */
16
+ id?: string;
17
+ /** USB / HID: 16-bit USB-IF vendor id. Default `0x0000`. */
18
+ vendorId?: number;
19
+ /** USB / HID: 16-bit product id. Default `0x0000`. */
20
+ productId?: number;
21
+ /** USB: human-readable manufacturer string. Default `"browxai virtual"`. */
22
+ manufacturerName?: string;
23
+ /** USB: serial number string. Default `"BROWX-VIRTUAL"`. */
24
+ serialNumber?: string;
25
+ /** USB: 8-bit device class (e.g. 0x03 = HID). Default 0xFF (vendor-
26
+ * specific). */
27
+ deviceClass?: number;
28
+ /** USB: 8-bit device subclass. Default 0x00. */
29
+ deviceSubclass?: number;
30
+ /** USB: 8-bit device protocol. Default 0x00. */
31
+ deviceProtocol?: number;
32
+ /** Bluetooth: GATT primary service UUIDs the device advertises. Default
33
+ * `[]`. The synthetic `gatt.getPrimaryService()` still rejects (no
34
+ * full GATT emulation in v1) — the list is exposed only via the
35
+ * picker-time filter match + on the resolved device's metadata for
36
+ * pages that introspect `device.uuids`-style fields. */
37
+ services?: string[];
38
+ /** HID: report descriptor's collection topology (output only — the
39
+ * agent describes what `collections[]` looks like). Default `[]`. */
40
+ collections?: unknown[];
41
+ }
42
+ /** Public, runtime-mutable per-API catalog. Empty list → next requestDevice
43
+ * rejects (Bluetooth/USB) or returns [] (HID). */
44
+ export interface DeviceCatalog {
45
+ devices: SyntheticDevice[];
46
+ }
47
+ /** One captured `requestDevice` call, surfaced on `device_requests`. */
48
+ export interface DeviceRequestRecord {
49
+ api: DeviceApi;
50
+ /** What the wrapper actually did:
51
+ * - `"resolved"` — catalog non-empty; picker resolved with a synthetic
52
+ * device (Bluetooth/USB) or device list (HID).
53
+ * - `"rejected"` — catalog empty for Bluetooth/USB; picker rejected
54
+ * with NotFoundError ("user dismissed").
55
+ * - `"empty"` — catalog empty for HID; picker resolved with []
56
+ * (the HID picker's user-dismissed shape).
57
+ * - `"refused"` — capability `device-emulation` was OFF at the time
58
+ * of the call; the wrapper let the native API run
59
+ * (which in headless Chromium rejects/returns empty
60
+ * anyway). Recorded so the read-side surfaces "the
61
+ * page asked but you didn't have the capability on". */
62
+ handledAs: "resolved" | "rejected" | "empty" | "refused";
63
+ /** Filter the page supplied in `requestDevice(options.filters[])` /
64
+ * `acceptAllDevices` / etc. — sliced down to a single JSON-safe shape
65
+ * the agent can read. Best-effort: shapes that exceed 4KB stringified
66
+ * are truncated with a `…` marker. */
67
+ filters?: unknown;
68
+ /** Count of devices returned to the page on this call. For Bluetooth/USB:
69
+ * always 0 or 1. For HID: 0..N. */
70
+ returned: number;
71
+ /** epoch ms — used by `device_requests({since?})` slice. */
72
+ ts: number;
73
+ }
74
+ /** Mutable per-session state. The page-side wrapper consults `catalog(api)`
75
+ * via the bridge binding on every `requestDevice` call, so a `set` call
76
+ * takes effect on the very next page-side request without a navigation. */
77
+ export declare class DeviceEmulationState {
78
+ /** Per-API catalog. Empty list (or absent entry) → wrapper falls into
79
+ * the user-dismissed-picker shape for that API. */
80
+ private catalogs;
81
+ /** Captured `requestDevice` calls — a bounded record ring (shared
82
+ * `PolicyRecordBuffer`; chatty pages can't grow this without bound,
83
+ * `device_requests` slices on `since`). */
84
+ private readonly records;
85
+ /** Contexts we've already installed the init-script + binding on.
86
+ * Idempotent install guard — BYOB reconnect / context rebuild MUST not
87
+ * double-wire. */
88
+ private wired;
89
+ /** True iff `device-emulation` capability was on at the time of attach.
90
+ * The page-side wrapper installs regardless (so a runtime capability
91
+ * toggle that adds the cap takes effect — though the canonical
92
+ * resolve-once-at-boot model means it doesn't), but the check binding
93
+ * short-circuits to `refused` when off. */
94
+ private enabledByCapability;
95
+ constructor(enabledByCapability: boolean, cap?: number);
96
+ /** Snapshot of one API's catalog. */
97
+ catalog(api: DeviceApi): DeviceCatalog;
98
+ /** Replace one API's catalog. `devices` may be empty (clears the catalog —
99
+ * next requestDevice rejects/empty). Returns the resolved catalog
100
+ * (echoed back so the tool's response shows what the wrapper will
101
+ * serve). */
102
+ set(api: DeviceApi, devices: SyntheticDevice[]): DeviceCatalog;
103
+ /** Append a request record. Caps the buffer at `cap`. */
104
+ record(rec: DeviceRequestRecord): void;
105
+ /** Slice records with `ts >= since`. Default since=0 returns all. */
106
+ since(since?: number): DeviceRequestRecord[];
107
+ /** Capability gate snapshot. The check binding consults this on every
108
+ * page-side request. */
109
+ capabilityEnabled(): boolean;
110
+ /** Has this context already been wired? Idempotent install guard. */
111
+ hasContext(c: BrowserContext): boolean;
112
+ /** Mark a context as wired. */
113
+ markContext(c: BrowserContext): void;
114
+ }
115
+ /** BYOB warning — the init-script wrappers patch every new document in the
116
+ * attached Chrome's session-isolated context; the patches do NOT escape
117
+ * the context, but the per-deployment posture (the operator's main Chrome
118
+ * running with `--remote-debugging-port`) magnifies the consequences of a
119
+ * page that the agent told "you have a hardware device". Surfaced when
120
+ * `open_session({mode:"attached"})` engages with `device-emulation` on. */
121
+ export declare const BYOB_DEVICE_EMU_WARNING: string;
122
+ /** Init script that wraps the three Web platform device-picker APIs. Each
123
+ * wrapper consults `window.__browx_device_check({api, filters?})` (the
124
+ * exposeBinding from the server side) on every page-side `requestDevice`
125
+ * call — the binding returns a `{decision, devices?}` envelope the wrapper
126
+ * unpacks into the API-specific shape the spec expects. Keep browser-only
127
+ * JS (no TS-only syntax). Re-injected on `framenavigated` (idempotent:
128
+ * guards on `window.__browx_device_emu_installed`). */
129
+ export declare const DEVICE_EMU_PAGE_SCRIPT = "(() => {\n if (window.__browx_device_emu_installed) return;\n window.__browx_device_emu_installed = true;\n\n function check(api, filters) {\n try {\n if (typeof window.__browx_device_check === \"function\") {\n return Promise.resolve(window.__browx_device_check(JSON.stringify({\n api: api,\n filters: filters == null ? null : safeFilters(filters),\n })));\n }\n } catch (_) {}\n // Binding missing \u2014 safe-by-default empty catalog so the page sees the\n // user-dismissed shape rather than a hung promise.\n return Promise.resolve(JSON.stringify({ decision: \"refused\", devices: [] }));\n }\n\n function safeFilters(f) {\n // Defensive shallow clone \u2014 page may pass non-serialisable garbage\n // (BigInt, function, circular). Best-effort.\n try { return JSON.parse(JSON.stringify(f)); } catch (_) { return null; }\n }\n\n function notFound(msg) {\n var e = new Error(msg || \"User cancelled the requestDevice() chooser.\");\n try { e.name = \"NotFoundError\"; } catch (_) {}\n return e;\n }\n\n function parseResponse(raw) {\n try {\n var r = typeof raw === \"string\" ? JSON.parse(raw) : (raw || {});\n var decision = r.decision;\n var devices = Array.isArray(r.devices) ? r.devices : [];\n return { decision: decision, devices: devices };\n } catch (_) {\n return { decision: \"refused\", devices: [] };\n }\n }\n\n // ---- Bluetooth -------------------------------------------------------\n // Synthesise the minimal BluetoothDevice + BluetoothRemoteGATTServer\n // surface modern BLE-onboarding flows touch: id / name / gatt.connect()\n // \u2192 stub server whose getPrimaryService() rejects (no GATT emulation in\n // v1). Pages that gate on \"we found a device\" pass; pages that go on to\n // exchange characteristic data do not.\n function syntheticBluetoothDevice(spec) {\n var name = spec.name || \"browxai-virtual\";\n var id = spec.id || \"browxai-bt-0\";\n var services = Array.isArray(spec.services) ? spec.services : [];\n var device;\n var gatt = {\n get connected() { return gatt.__connected; },\n __connected: false,\n device: null, // set after device is created (circular ref)\n connect: function () {\n gatt.__connected = true;\n return Promise.resolve(gatt);\n },\n disconnect: function () { gatt.__connected = false; },\n getPrimaryService: function () {\n return Promise.reject(notFound(\"GATT service emulation not supported in browxai v1\"));\n },\n getPrimaryServices: function () {\n return Promise.reject(notFound(\"GATT service emulation not supported in browxai v1\"));\n },\n };\n device = {\n id: id,\n name: name,\n uuids: services,\n gatt: gatt,\n // EventTarget stubs \u2014 pages sometimes attach gattserverdisconnected;\n // we accept and ignore.\n addEventListener: function () {},\n removeEventListener: function () {},\n dispatchEvent: function () { return true; },\n watchAdvertisements: function () { return Promise.resolve(undefined); },\n unwatchAdvertisements: function () {},\n get watchingAdvertisements() { return false; },\n // forget() \u2014 modern API for revoking the permission; resolves no-op.\n forget: function () { return Promise.resolve(undefined); },\n };\n gatt.device = device;\n return device;\n }\n try {\n var bt = navigator.bluetooth;\n if (bt && typeof bt.requestDevice === \"function\") {\n // Replace the entire requestDevice; we intentionally do NOT call\n // through to the native API even when the agent didn't stage a\n // catalog \u2014 calling through on a headless Chromium often hangs the\n // promise indefinitely (no picker UI to dismiss).\n Object.defineProperty(bt, \"requestDevice\", {\n configurable: true,\n writable: true,\n value: function (options) {\n var filters = options || null;\n return check(\"bluetooth\", filters).then(function (raw) {\n var r = parseResponse(raw);\n if (!r.devices.length) {\n throw notFound();\n }\n return syntheticBluetoothDevice(r.devices[0]);\n });\n },\n });\n // getDevices \u2014 read-side: pre-paired devices. v1 returns the live\n // catalog so a page polling for an already-paired device sees one.\n if (typeof bt.getDevices === \"function\") {\n Object.defineProperty(bt, \"getDevices\", {\n configurable: true,\n writable: true,\n value: function () {\n return check(\"bluetooth\", null).then(function (raw) {\n var r = parseResponse(raw);\n return r.devices.map(syntheticBluetoothDevice);\n });\n },\n });\n }\n }\n } catch (_) {}\n\n // ---- WebUSB ----------------------------------------------------------\n // USBDevice synthesises the picker-resolve surface + stub\n // open/close/selectConfiguration; transferIn/transferOut resolve with\n // zero-byte responses so a page sequence doesn't reject mid-flight, but\n // there's no actual data flow.\n function syntheticUSBDevice(spec) {\n var name = spec.name || \"browxai-virtual\";\n return {\n vendorId: spec.vendorId || 0,\n productId: spec.productId || 0,\n productName: name,\n manufacturerName: spec.manufacturerName || \"browxai virtual\",\n serialNumber: spec.serialNumber || \"BROWX-VIRTUAL\",\n deviceClass: spec.deviceClass != null ? spec.deviceClass : 0xFF,\n deviceSubclass: spec.deviceSubclass || 0,\n deviceProtocol: spec.deviceProtocol || 0,\n usbVersionMajor: 2,\n usbVersionMinor: 0,\n usbVersionSubminor: 0,\n deviceVersionMajor: 1,\n deviceVersionMinor: 0,\n deviceVersionSubminor: 0,\n configuration: null,\n configurations: [],\n opened: false,\n open: function () { this.opened = true; return Promise.resolve(undefined); },\n close: function () { this.opened = false; return Promise.resolve(undefined); },\n selectConfiguration: function () { return Promise.resolve(undefined); },\n claimInterface: function () { return Promise.resolve(undefined); },\n releaseInterface: function () { return Promise.resolve(undefined); },\n selectAlternateInterface: function () { return Promise.resolve(undefined); },\n controlTransferIn: function () { return Promise.resolve({ data: new DataView(new ArrayBuffer(0)), status: \"ok\" }); },\n controlTransferOut: function () { return Promise.resolve({ bytesWritten: 0, status: \"ok\" }); },\n clearHalt: function () { return Promise.resolve(undefined); },\n transferIn: function () { return Promise.resolve({ data: new DataView(new ArrayBuffer(0)), status: \"ok\" }); },\n transferOut: function () { return Promise.resolve({ bytesWritten: 0, status: \"ok\" }); },\n isochronousTransferIn: function () { return Promise.resolve({ data: new DataView(new ArrayBuffer(0)), packets: [] }); },\n isochronousTransferOut: function () { return Promise.resolve({ packets: [] }); },\n reset: function () { return Promise.resolve(undefined); },\n forget: function () { return Promise.resolve(undefined); },\n };\n }\n try {\n var usb = navigator.usb;\n if (usb && typeof usb.requestDevice === \"function\") {\n Object.defineProperty(usb, \"requestDevice\", {\n configurable: true,\n writable: true,\n value: function (options) {\n var filters = options || null;\n return check(\"usb\", filters).then(function (raw) {\n var r = parseResponse(raw);\n if (!r.devices.length) {\n throw notFound();\n }\n return syntheticUSBDevice(r.devices[0]);\n });\n },\n });\n if (typeof usb.getDevices === \"function\") {\n Object.defineProperty(usb, \"getDevices\", {\n configurable: true,\n writable: true,\n value: function () {\n return check(\"usb\", null).then(function (raw) {\n var r = parseResponse(raw);\n return r.devices.map(syntheticUSBDevice);\n });\n },\n });\n }\n }\n } catch (_) {}\n\n // ---- WebHID ----------------------------------------------------------\n // HIDDevice differs from USB in two ways the wrapper preserves:\n // - requestDevice resolves to an Array<HIDDevice>, NOT a single\n // device (even when only one match \u2014 see W3C spec).\n // - Empty result is the user-dismissed shape, NOT a rejection.\n function syntheticHIDDevice(spec) {\n var name = spec.name || \"browxai-virtual\";\n return {\n opened: false,\n vendorId: spec.vendorId || 0,\n productId: spec.productId || 0,\n productName: name,\n collections: Array.isArray(spec.collections) ? spec.collections : [],\n open: function () { this.opened = true; return Promise.resolve(undefined); },\n close: function () { this.opened = false; return Promise.resolve(undefined); },\n forget: function () { return Promise.resolve(undefined); },\n sendReport: function () { return Promise.resolve(undefined); },\n sendFeatureReport: function () { return Promise.resolve(undefined); },\n receiveFeatureReport: function () { return Promise.resolve(new DataView(new ArrayBuffer(0))); },\n addEventListener: function () {},\n removeEventListener: function () {},\n dispatchEvent: function () { return true; },\n oninputreport: null,\n };\n }\n try {\n var hid = navigator.hid;\n if (hid && typeof hid.requestDevice === \"function\") {\n Object.defineProperty(hid, \"requestDevice\", {\n configurable: true,\n writable: true,\n value: function (options) {\n var filters = options || null;\n return check(\"hid\", filters).then(function (raw) {\n var r = parseResponse(raw);\n return r.devices.map(syntheticHIDDevice);\n });\n },\n });\n if (typeof hid.getDevices === \"function\") {\n Object.defineProperty(hid, \"getDevices\", {\n configurable: true,\n writable: true,\n value: function () {\n return check(\"hid\", null).then(function (raw) {\n var r = parseResponse(raw);\n return r.devices.map(syntheticHIDDevice);\n });\n },\n });\n }\n }\n } catch (_) {}\n})();";
130
+ /** Server-side wire-up. Installs:
131
+ * - `__browx_device_check` exposeBinding: page-side `requestDevice` calls
132
+ * route here; we read the catalog for the requested API, record the
133
+ * call, and return `{decision, devices}`. `decision` is informational
134
+ * (the page-side wrapper consults `devices.length` to pick the
135
+ * spec-correct empty-result shape per API).
136
+ * - The page-side init script (re-injected by Playwright on every new
137
+ * document).
138
+ *
139
+ * Idempotent on the same context. Errors during install are logged and
140
+ * swallowed — the page-side wrapper falls back to "decision: refused,
141
+ * devices: []" when the binding is missing, so a page calling
142
+ * requestDevice never deadlocks.
143
+ */
144
+ export declare function attachDeviceEmulation(context: BrowserContext, state: DeviceEmulationState): Promise<void>;
145
+ /** Re-apply the init script to an existing page (no-op when the page-side
146
+ * guard is already set). Used by callers that opened pages BEFORE the
147
+ * attach engaged (rare). Public for tests; production callers go through
148
+ * `attachDeviceEmulation` which handles existing pages too. */
149
+ export declare function reinjectDeviceEmuOnPage(page: Page): Promise<void>;