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,376 @@
1
+ // `asset_export` — filter the session's network ring and persist matching
2
+ // responses to a workspace-rooted directory.
3
+ //
4
+ // Design posture (mirrors `downloads.ts`):
5
+ // - **Workspace-rooted paths only.** Exports land under
6
+ // `$BROWX_WORKSPACE/assets/<sessionId>-<ISO>/` by default; an explicit
7
+ // `intoDir` is resolved INSIDE the workspace (escape rejected).
8
+ // - **Filename sanitisation** is the same posture as `downloads.sanitiseFilename`
9
+ // — no path separators, no NUL/control bytes, no leading dots, length-capped,
10
+ // all-stripped names fall back to `"asset"`. Collisions are resolved by
11
+ // appending `-N` to the stem so a second `logo.png` becomes `logo-1.png`.
12
+ // - **Bounded.** Caller can raise `maxCount` / `maxBytes` but never above a
13
+ // hard ceiling — a misconfigured filter on a long-running session must not
14
+ // fill the workspace. Defaults: 10000 files / 500 MiB.
15
+ // - **CORS tolerance.** When the response body isn't in the renderer's cache
16
+ // (CDP `Network.getResponseBody` returns "not available" — bodies are
17
+ // short-lived) we fall back to a same-origin in-page `fetch()` for the
18
+ // original URL. Cross-origin URLs without CORS headers may reject; we record
19
+ // the failure on `droppedCount` and keep going.
20
+ // - **No new capability.** Reuses `file-io` (same as `upload_file` /
21
+ // `downloads_capture` / `download_get`).
22
+ import { mkdirSync, writeFileSync, statSync } from "node:fs";
23
+ import { join, resolve, sep, basename } from "node:path";
24
+ import { log } from "../util/logging.js";
25
+ // ---------- caps & defaults --------------------------------------------------
26
+ /** Hard ceiling on the per-call file count cap — even a caller-supplied
27
+ * `maxCount` is clamped to this. Bounds a runaway export on a long session. */
28
+ export const ASSET_EXPORT_HARD_MAX_COUNT = 50_000;
29
+ /** Hard ceiling on the per-call byte cap. */
30
+ export const ASSET_EXPORT_HARD_MAX_BYTES = 2 * 1024 * 1024 * 1024; // 2 GiB
31
+ /** Default per-call file count cap. Caller can override up to the hard max. */
32
+ export const ASSET_EXPORT_DEFAULT_MAX_COUNT = 10_000;
33
+ /** Default per-call byte cap (500 MiB). */
34
+ export const ASSET_EXPORT_DEFAULT_MAX_BYTES = 500 * 1024 * 1024;
35
+ /** Maximum bytes for a single response body — same posture as
36
+ * `fetchResponseBody`'s default. Larger responses are skipped with a
37
+ * warning so one huge video can't blow the whole export. */
38
+ const SINGLE_BODY_MAX_BYTES = 64 * 1024 * 1024; // 64 MiB
39
+ /** Cap on the on-disk filename length, accounting for the `-N` collision
40
+ * suffix room and 255-byte filesystem name limits. */
41
+ const FILENAME_MAX_CHARS = 200;
42
+ // ---------- pure helpers (exported for unit tests) ---------------------------
43
+ /** Build the regex once at the boundary. Throws `Error` on invalid source so
44
+ * the tool layer surfaces a structured failure instead of a runtime crash
45
+ * deep inside the loop. */
46
+ export function compileUrlPattern(src) {
47
+ if (!src)
48
+ return null;
49
+ try {
50
+ return new RegExp(src, "i");
51
+ }
52
+ catch (err) {
53
+ throw new Error(`asset_export: invalid \`filter.urlPattern\` — ${err instanceof Error ? err.message : String(err)}`);
54
+ }
55
+ }
56
+ /** Status gate: an explicit allow-list, else default 2xx. */
57
+ function statusMatches(entry, status) {
58
+ if (entry.status === undefined)
59
+ return false;
60
+ return status ? status.has(entry.status) : entry.status >= 200 && entry.status < 300;
61
+ }
62
+ /** MIME gate: substring on the captured Content-Type; no mime info → reject
63
+ * (an entry that never reported a Content-Type can't be classified). */
64
+ function mimeMatches(entry, mime) {
65
+ if (!mime || mime.length === 0)
66
+ return true;
67
+ if (!entry.mimeType)
68
+ return false;
69
+ const lower = entry.mimeType.toLowerCase();
70
+ return mime.some((m) => lower.includes(m.toLowerCase()));
71
+ }
72
+ /** Byte-bound gate: only enforced when bytes have landed (still-in-flight
73
+ * entries are admitted here; the fetch step counts actual bytes). */
74
+ function bytesMatch(entry, minBytes, maxBytes) {
75
+ if (typeof entry.bytes !== "number")
76
+ return true;
77
+ if (typeof minBytes === "number" && entry.bytes < minBytes)
78
+ return false;
79
+ if (typeof maxBytes === "number" && entry.bytes > maxBytes)
80
+ return false;
81
+ return true;
82
+ }
83
+ /** Filter a single `NetworkEntry` against a normalised filter. Pure — uses only
84
+ * the entry's captured metadata; no I/O. Exported so the test suite can pin
85
+ * every branch without spinning a NetworkBuffer. */
86
+ export function matchesFilter(entry, filter) {
87
+ if (!statusMatches(entry, filter.status))
88
+ return false;
89
+ if (!mimeMatches(entry, filter.mime))
90
+ return false;
91
+ if (filter.urlPattern && !filter.urlPattern.test(entry.url))
92
+ return false;
93
+ return bytesMatch(entry, filter.minBytes, filter.maxBytes);
94
+ }
95
+ /** Sanitise a URL-derived asset filename. Same posture as
96
+ * `downloads.sanitiseFilename`:
97
+ * - strip path separators (`/`, `\`) and NUL/control bytes — collapses any
98
+ * traversal attempt to a flat filename.
99
+ * - collapse runs of dots so the literal `..` substring never survives.
100
+ * - strip leading dots so we don't write a hidden file.
101
+ * - cap length (leaves room for a `-N` collision suffix).
102
+ * - empty / all-stripped → fall back to `"asset"`.
103
+ * Exported for unit tests. */
104
+ export function sanitiseAssetFilename(raw) {
105
+ if (typeof raw !== "string")
106
+ return "asset";
107
+ // strip NUL + control bytes (0x00-0x1f, 0x7f) and path separators.
108
+ // eslint-disable-next-line no-control-regex
109
+ let name = raw.replace(/[\x00-\x1f\x7f/\\]/g, "_");
110
+ // collapse runs of dots ("../.." → ".") so the literal substring `..`
111
+ // never survives — eliminates "looks-like-traversal" even though the
112
+ // lack of separators already makes traversal impossible.
113
+ name = name.replace(/\.{2,}/g, ".");
114
+ // collapse repeated underscores from the strip pass.
115
+ name = name.replace(/_+/g, "_");
116
+ // strip leading dots so we don't write a hidden file.
117
+ name = name.replace(/^\.+/, "");
118
+ // strip leading/trailing whitespace, dots, underscores — these only exist
119
+ // because of the strip passes above.
120
+ name = name.replace(/^[._\s]+|[._\s]+$/g, "");
121
+ if (name.length > FILENAME_MAX_CHARS)
122
+ name = name.slice(0, FILENAME_MAX_CHARS);
123
+ if (!name)
124
+ return "asset";
125
+ return name;
126
+ }
127
+ /** Derive a base filename from a URL: take the last path segment, decode
128
+ * percent-encoding, drop a query string. Falls back to `"asset"` when the
129
+ * URL has no usable basename (e.g. `https://example.com/`). Exported for
130
+ * unit tests. */
131
+ export function filenameFromUrl(url) {
132
+ let pathname;
133
+ try {
134
+ pathname = new URL(url).pathname;
135
+ }
136
+ catch {
137
+ pathname = url;
138
+ }
139
+ // basename strips the trailing slash; pathname like `/` → `""`.
140
+ let base = basename(pathname);
141
+ if (!base)
142
+ base = "asset";
143
+ try {
144
+ base = decodeURIComponent(base);
145
+ }
146
+ catch {
147
+ // malformed percent-encoding — keep the raw form, sanitisation handles it.
148
+ }
149
+ return sanitiseAssetFilename(base);
150
+ }
151
+ /** Resolve a collision by appending `-N` before the extension. Pure; uses
152
+ * the supplied `Set` of already-used names. Exported for unit tests. */
153
+ export function resolveCollision(name, used) {
154
+ if (!used.has(name))
155
+ return name;
156
+ const dot = name.lastIndexOf(".");
157
+ const stem = dot > 0 ? name.slice(0, dot) : name;
158
+ const ext = dot > 0 ? name.slice(dot) : "";
159
+ for (let i = 1; i < 1_000_000; i++) {
160
+ const candidate = `${stem}-${i}${ext}`;
161
+ if (!used.has(candidate))
162
+ return candidate;
163
+ }
164
+ // 1M collisions on the same stem is effectively impossible; if it happens,
165
+ // disambiguate with the current timestamp + a random tail.
166
+ return `${stem}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}${ext}`;
167
+ }
168
+ /** ISO-8601 timestamp safe for use in a directory name (`:` replaced with `-`). */
169
+ export function timestampForDir(d = new Date()) {
170
+ return d.toISOString().replace(/[:.]/g, "-");
171
+ }
172
+ // ---------- workspace path safety -------------------------------------------
173
+ /** Resolve the export dir. Default: `assets/<sessionId>-<ISO>/`. Caller-
174
+ * supplied `intoDir` is resolved INSIDE `workspaceRoot`; any escape throws
175
+ * the same structured error as `upload_file` / `pdf_save`. */
176
+ export function resolveAssetExportDir(workspaceRoot, sessionId, intoDir) {
177
+ const rel = intoDir ?? `assets/${sessionId}-${timestampForDir()}`;
178
+ const resolved = resolve(workspaceRoot, rel);
179
+ if (resolved !== workspaceRoot && !resolved.startsWith(workspaceRoot + sep)) {
180
+ throw new Error(`asset_export: \`intoDir\` must resolve inside $BROWX_WORKSPACE — got "${rel}". ` +
181
+ `Use a workspace-relative path.`);
182
+ }
183
+ return resolved;
184
+ }
185
+ // ---------- body fetch -------------------------------------------------------
186
+ /** Try CDP `Network.getResponseBody` first; on "not available" fall back to
187
+ * an in-page `fetch()` against the original URL. Returns the bytes (decoded)
188
+ * + the effective content-type, or an `{ error }` envelope when both attempts
189
+ * fail. The CORS caveat: cross-origin URLs without permissive CORS headers
190
+ * will reject the in-page fetch; that's surfaced as `droppedCount` by the
191
+ * caller, not a crash. */
192
+ export async function fetchBodyBytes(cdp, page, entry) {
193
+ // First try the renderer's cached body — short-lived but free.
194
+ if (entry.requestId) {
195
+ try {
196
+ const { body, base64Encoded } = await cdp.send("Network.getResponseBody", {
197
+ requestId: entry.requestId,
198
+ });
199
+ const buf = base64Encoded ? Buffer.from(body, "base64") : Buffer.from(body, "utf8");
200
+ const out = { ok: true, bytes: buf };
201
+ if (entry.mimeType !== undefined)
202
+ out.mimeType = entry.mimeType;
203
+ return out;
204
+ }
205
+ catch {
206
+ // body discarded by the renderer — fall through to the in-page fetch.
207
+ }
208
+ }
209
+ // Fallback: in-page `fetch()`. CORS caveat — cross-origin URLs without
210
+ // permissive headers will throw; we report it as a drop, not a crash.
211
+ try {
212
+ const result = await page.evaluate(async (url) => {
213
+ try {
214
+ const res = await fetch(url);
215
+ const buf = await res.arrayBuffer();
216
+ const arr = new Uint8Array(buf);
217
+ // Encode as base64 inside the page so the bridge marshalling is
218
+ // string-only (avoids the structured-clone size cliff on big buffers).
219
+ let bin = "";
220
+ const chunk = 0x8000;
221
+ for (let i = 0; i < arr.length; i += chunk) {
222
+ bin += String.fromCharCode(...arr.subarray(i, Math.min(i + chunk, arr.length)));
223
+ }
224
+ return {
225
+ ok: true,
226
+ base64: btoa(bin),
227
+ mimeType: res.headers.get("content-type") ?? undefined,
228
+ };
229
+ }
230
+ catch (e) {
231
+ return { ok: false, error: e instanceof Error ? e.message : String(e) };
232
+ }
233
+ }, entry.url);
234
+ if (!result.ok)
235
+ return { ok: false, error: `in-page fetch failed: ${result.error}` };
236
+ const out = {
237
+ ok: true,
238
+ bytes: Buffer.from(result.base64, "base64"),
239
+ };
240
+ const mt = result.mimeType ?? entry.mimeType;
241
+ if (mt !== undefined)
242
+ out.mimeType = mt;
243
+ return out;
244
+ }
245
+ catch (e) {
246
+ return { ok: false, error: e instanceof Error ? e.message : String(e) };
247
+ }
248
+ }
249
+ /** Persist one fetched body to disk, appending its manifest entry (or recording
250
+ * a drop / workspace-escape refusal). Returns "break" only on a maxBytes stop. */
251
+ function persistAssetBody(st, entry, fetched) {
252
+ if (st.runningBytes + fetched.bytes.length > st.maxBytes) {
253
+ st.warnings.push(`maxBytes (${st.maxBytes}) would be exceeded by ${entry.url} (${fetched.bytes.length} bytes); stopping export`);
254
+ return "break";
255
+ }
256
+ const finalName = resolveCollision(filenameFromUrl(entry.url), st.used);
257
+ st.used.add(finalName);
258
+ // Defence in depth — the sanitised name has no separators, so the join can't
259
+ // escape `intoDir`; verify anyway ($BROWX_WORKSPACE-rooted by construction).
260
+ const resolved = resolve(join(st.intoDir, finalName));
261
+ if (resolved !== st.intoDir && !resolved.startsWith(st.intoDir + sep)) {
262
+ st.droppedCount += 1;
263
+ st.warnings.push(`refused to write outside intoDir: ${entry.url}`);
264
+ return "continue";
265
+ }
266
+ try {
267
+ writeFileSync(resolved, fetched.bytes);
268
+ }
269
+ catch (err) {
270
+ st.droppedCount += 1;
271
+ st.warnings.push(`write failed for ${entry.url}: ${err instanceof Error ? err.message : String(err)}`);
272
+ return "continue";
273
+ }
274
+ let sizeBytes = fetched.bytes.length;
275
+ try {
276
+ sizeBytes = statSync(resolved).size;
277
+ }
278
+ catch {
279
+ /* best-effort */
280
+ }
281
+ st.runningBytes += sizeBytes;
282
+ const m = { url: entry.url, sizeBytes, savedAs: finalName };
283
+ const mt = fetched.mimeType ?? entry.mimeType;
284
+ if (mt !== undefined)
285
+ m.mime = mt;
286
+ if (entry.status !== undefined)
287
+ m.status = entry.status;
288
+ st.manifest.push(m);
289
+ return "continue";
290
+ }
291
+ /** Process one matched entry: cap checks → fetch → size checks → persist. */
292
+ async function processAssetEntry(deps, st, entry) {
293
+ st.matchedCount += 1;
294
+ if (st.manifest.length >= st.maxCount) {
295
+ st.warnings.push(`maxCount (${st.maxCount}) reached — ${st.matchedCount - st.manifest.length} additional matches were not persisted`);
296
+ return "break";
297
+ }
298
+ if (typeof entry.bytes === "number" && entry.bytes > SINGLE_BODY_MAX_BYTES) {
299
+ st.droppedCount += 1;
300
+ st.warnings.push(`skipped ${entry.url} — single-response size (${entry.bytes} bytes) exceeds SINGLE_BODY_MAX_BYTES (${SINGLE_BODY_MAX_BYTES})`);
301
+ return "continue";
302
+ }
303
+ const fetched = await fetchBodyBytes(deps.cdp, deps.page, entry);
304
+ if (!fetched.ok) {
305
+ st.droppedCount += 1;
306
+ st.warnings.push(`skipped ${entry.url} — ${fetched.error}`);
307
+ return "continue";
308
+ }
309
+ if (fetched.bytes.length > SINGLE_BODY_MAX_BYTES) {
310
+ st.droppedCount += 1;
311
+ st.warnings.push(`skipped ${entry.url} — fetched body (${fetched.bytes.length} bytes) exceeds SINGLE_BODY_MAX_BYTES (${SINGLE_BODY_MAX_BYTES})`);
312
+ return "continue";
313
+ }
314
+ return persistAssetBody(st, entry, fetched);
315
+ }
316
+ export async function assetExport(deps, args) {
317
+ const filter = args.filter ?? {};
318
+ const urlPattern = compileUrlPattern(filter.urlPattern);
319
+ const statusSet = filter.status && filter.status.length > 0 ? new Set(filter.status) : null;
320
+ const intoDir = resolveAssetExportDir(deps.workspaceRoot, deps.sessionId, args.intoDir);
321
+ // `intoDir` is workspace-rooted by construction: `resolveAssetExportDir`
322
+ // resolves it inside `workspaceRoot` ($BROWX_WORKSPACE) and rejects any escape.
323
+ // Every write below is under this dir, never cwd.
324
+ mkdirSync(intoDir, { recursive: true });
325
+ const all = deps.buffer.iter();
326
+ const totalCount = all.length;
327
+ const st = {
328
+ intoDir,
329
+ maxCount: Math.min(Math.max(1, args.maxCount ?? ASSET_EXPORT_DEFAULT_MAX_COUNT), ASSET_EXPORT_HARD_MAX_COUNT),
330
+ maxBytes: Math.min(Math.max(1, args.maxBytes ?? ASSET_EXPORT_DEFAULT_MAX_BYTES), ASSET_EXPORT_HARD_MAX_BYTES),
331
+ warnings: [],
332
+ manifest: [],
333
+ used: new Set(),
334
+ matchedCount: 0,
335
+ droppedCount: 0,
336
+ runningBytes: 0,
337
+ };
338
+ for (const entry of all) {
339
+ const matched = matchesFilter(entry, {
340
+ mime: filter.mime,
341
+ urlPattern,
342
+ minBytes: filter.minBytes,
343
+ maxBytes: filter.maxBytes,
344
+ status: statusSet,
345
+ });
346
+ if (!matched)
347
+ continue;
348
+ if ((await processAssetEntry(deps, st, entry)) === "break")
349
+ break;
350
+ }
351
+ const { warnings, manifest, matchedCount, droppedCount } = st;
352
+ // Write `_manifest.json` last so a crash mid-export doesn't leave a
353
+ // misleading manifest pointing at files that weren't all written.
354
+ // `intoDir` is workspace-rooted ($BROWX_WORKSPACE / workspaceRoot) by
355
+ // construction — see `resolveAssetExportDir` above.
356
+ try {
357
+ const manifestPath = join(intoDir, "_manifest.json");
358
+ writeFileSync(manifestPath, JSON.stringify({ intoDir, manifest }, null, 2));
359
+ }
360
+ catch (err) {
361
+ log.warn("asset_export: writing _manifest.json failed", {
362
+ error: err instanceof Error ? err.message : String(err),
363
+ });
364
+ warnings.push(`writing _manifest.json failed: ${err instanceof Error ? err.message : String(err)}`);
365
+ }
366
+ return {
367
+ ok: true,
368
+ intoDir,
369
+ totalCount,
370
+ matchedCount,
371
+ persistedCount: manifest.length,
372
+ droppedCount,
373
+ manifest,
374
+ warnings,
375
+ };
376
+ }
@@ -0,0 +1,16 @@
1
+ export interface NetworkMatch {
2
+ /** case-insensitive substring of the request URL. */
3
+ urlPattern?: string;
4
+ /** exact HTTP method (case-insensitive). */
5
+ method?: string;
6
+ /** exact response status. */
7
+ status?: number;
8
+ }
9
+ export interface ResponseLike {
10
+ url: string;
11
+ method: string;
12
+ status: number;
13
+ }
14
+ /** Pure predicate — does this response satisfy the match? An empty match
15
+ * matches nothing (refuse to "wait for anything"). Exported for tests. */
16
+ export declare function matchesResponse(resp: ResponseLike, match: NetworkMatch): boolean;
@@ -0,0 +1,23 @@
1
+ // act_and_wait_for_network matcher.
2
+ //
3
+ // `ActionResult.network` only sees requests inside the action window; async
4
+ // SPAs fire follow-up requests after it. This lets a caller drive an action
5
+ // and wait for a *specific* request to complete, with a precise match.
6
+ /** Pure predicate — does this response satisfy the match? An empty match
7
+ * matches nothing (refuse to "wait for anything"). Exported for tests. */
8
+ export function matchesResponse(resp, match) {
9
+ if (match.urlPattern === undefined && match.method === undefined && match.status === undefined) {
10
+ return false;
11
+ }
12
+ if (match.urlPattern !== undefined &&
13
+ !resp.url.toLowerCase().includes(match.urlPattern.toLowerCase())) {
14
+ return false;
15
+ }
16
+ if (match.method !== undefined && resp.method.toUpperCase() !== match.method.toUpperCase()) {
17
+ return false;
18
+ }
19
+ if (match.status !== undefined && resp.status !== match.status) {
20
+ return false;
21
+ }
22
+ return true;
23
+ }
@@ -0,0 +1,37 @@
1
+ import type { CDPSession, Frame, Page } from "playwright-core";
2
+ export interface VisibleRect {
3
+ x: number;
4
+ y: number;
5
+ width: number;
6
+ height: number;
7
+ }
8
+ /**
9
+ * Compute the visible-rect bbox of a CDP-known DOM node. Returns null when the
10
+ * element is fully clipped (offscreen, inside a collapsed overflow container,
11
+ * detached). The caller surfaces null as `bbox: null, clipped: true`.
12
+ */
13
+ export declare function visibleRect(cdp: CDPSession, backendDOMNodeId: number): Promise<VisibleRect | null>;
14
+ /**
15
+ * Playwright locator-based bounding box, used as a *fallback* when the CDP
16
+ * `visibleRect` path returns null. On attached/BYOB Chromes the CDP
17
+ * `DOM.resolveNode` → `Runtime.callFunctionOn` rect path can spuriously fail
18
+ * for DOM-walk-sourced nodes (no live backend node, cross-frame quirks),
19
+ * producing a bogus `bbox:null` → `off-screen` for an element that is in fact
20
+ * rendered. Playwright's own `boundingBox()` resolves the element through the
21
+ * locator engine and reports its real rendered box; a non-empty box means
22
+ * "this is on the page" regardless of what the CDP path said. Best-effort:
23
+ * any error / empty box → null (the caller then treats it as truly clipped).
24
+ *
25
+ * `opts.timeoutMs` caps Playwright's auto-wait so a probe call against an
26
+ * unmatched selector fails fast instead of pinning the default `actionTimeout`
27
+ * (30 s). This is the perf hot-path for `find()` candidate evaluation — find()
28
+ * emits locator hints derived from DOM-walk-sourced roles that don't always
29
+ * map to a real Playwright role selector (e.g. `role=a` when the tag is `<a>`),
30
+ * and the bounding-box probe on those mismatched hints would otherwise hang
31
+ * for the full action-timeout window per candidate. Default cap is 500 ms —
32
+ * the wedge class is now a known hazard on every call site; per-caller opt-in
33
+ * (e.g. `{ timeoutMs: 1000 }`) raises it when the caller can absorb the wait.
34
+ */
35
+ export declare function locatorBoundingBox(root: Page | Frame, selector: string, opts?: {
36
+ timeoutMs?: number;
37
+ }): Promise<VisibleRect | null>;
@@ -0,0 +1,115 @@
1
+ // Visible-rect bbox computation — .
2
+ //
3
+ // `getBoundingClientRect()` intersected with each ancestor whose `overflow` isn't
4
+ // `visible`, then with the viewport. Returns null + clipped:true when the result
5
+ // is empty. Same definition site-docs's runtime computes, so calibration-time
6
+ // bbox == execution-time bbox for the same selector.
7
+ // Function source (runs in page context). Stringified so we can pass it to
8
+ // `Runtime.callFunctionOn` with the resolved DOM node as `this`.
9
+ //
10
+ // clipping is *only* triggered by `overflow: hidden` or `overflow: clip`.
11
+ // `overflow: auto` / `scroll` are scrollable, **not** clipping — the element's
12
+ // `getBoundingClientRect()` already accounts for the current scroll position,
13
+ // so the rect reflects the element's actual visible position. The previous
14
+ // check treated any non-`visible` overflow as clipping, which collapsed bboxes
15
+ // to zero on attached Chromes whose body/html or layout containers used
16
+ // `overflow: auto` (common pattern). Reported by the non-Claude verification
17
+ // run: visible elements returned `bbox: null` + `actionable: "off-screen"`.
18
+ const VISIBLE_RECT_FN = `function () {
19
+ function r(rect) { return { left: rect.left, top: rect.top, right: rect.right, bottom: rect.bottom }; }
20
+ function clips(cs) {
21
+ return cs.overflow === 'hidden' || cs.overflow === 'clip'
22
+ || cs.overflowX === 'hidden' || cs.overflowX === 'clip'
23
+ || cs.overflowY === 'hidden' || cs.overflowY === 'clip';
24
+ }
25
+ let b = r(this.getBoundingClientRect());
26
+ let n = this.parentElement;
27
+ while (n) {
28
+ const cs = getComputedStyle(n);
29
+ if (clips(cs)) {
30
+ const pr = r(n.getBoundingClientRect());
31
+ b = {
32
+ left: Math.max(b.left, pr.left),
33
+ top: Math.max(b.top, pr.top),
34
+ right: Math.min(b.right, pr.right),
35
+ bottom: Math.min(b.bottom, pr.bottom),
36
+ };
37
+ }
38
+ n = n.parentElement;
39
+ }
40
+ // Viewport. Fall back to documentElement / document.body dims when innerWidth/
41
+ // innerHeight read as zero (some attached contexts report bogus window metrics
42
+ // before first paint).
43
+ var vw = window.innerWidth || (document.documentElement && document.documentElement.clientWidth) || 0;
44
+ var vh = window.innerHeight || (document.documentElement && document.documentElement.clientHeight) || 0;
45
+ if (!vw || !vh) {
46
+ // Last resort: skip viewport intersection — return the un-clipped client rect.
47
+ // Better to over-report bbox than to under-report (which currently produces
48
+ // bogus 'off-screen' actionability).
49
+ if (b.right <= b.left || b.bottom <= b.top) return null;
50
+ return { x: b.left, y: b.top, width: b.right - b.left, height: b.bottom - b.top };
51
+ }
52
+ b = {
53
+ left: Math.max(b.left, 0),
54
+ top: Math.max(b.top, 0),
55
+ right: Math.min(b.right, vw),
56
+ bottom: Math.min(b.bottom, vh),
57
+ };
58
+ if (b.right <= b.left || b.bottom <= b.top) return null;
59
+ return { x: b.left, y: b.top, width: b.right - b.left, height: b.bottom - b.top };
60
+ }`;
61
+ /**
62
+ * Compute the visible-rect bbox of a CDP-known DOM node. Returns null when the
63
+ * element is fully clipped (offscreen, inside a collapsed overflow container,
64
+ * detached). The caller surfaces null as `bbox: null, clipped: true`.
65
+ */
66
+ export async function visibleRect(cdp, backendDOMNodeId) {
67
+ try {
68
+ const { object } = (await cdp.send("DOM.resolveNode", { backendNodeId: backendDOMNodeId }));
69
+ if (!object?.objectId)
70
+ return null;
71
+ const { result } = (await cdp.send("Runtime.callFunctionOn", {
72
+ objectId: object.objectId,
73
+ functionDeclaration: VISIBLE_RECT_FN,
74
+ returnByValue: true,
75
+ }));
76
+ return result.value ?? null;
77
+ }
78
+ catch {
79
+ // Node detached, no live DOM, etc. Treat as clipped.
80
+ return null;
81
+ }
82
+ }
83
+ /**
84
+ * Playwright locator-based bounding box, used as a *fallback* when the CDP
85
+ * `visibleRect` path returns null. On attached/BYOB Chromes the CDP
86
+ * `DOM.resolveNode` → `Runtime.callFunctionOn` rect path can spuriously fail
87
+ * for DOM-walk-sourced nodes (no live backend node, cross-frame quirks),
88
+ * producing a bogus `bbox:null` → `off-screen` for an element that is in fact
89
+ * rendered. Playwright's own `boundingBox()` resolves the element through the
90
+ * locator engine and reports its real rendered box; a non-empty box means
91
+ * "this is on the page" regardless of what the CDP path said. Best-effort:
92
+ * any error / empty box → null (the caller then treats it as truly clipped).
93
+ *
94
+ * `opts.timeoutMs` caps Playwright's auto-wait so a probe call against an
95
+ * unmatched selector fails fast instead of pinning the default `actionTimeout`
96
+ * (30 s). This is the perf hot-path for `find()` candidate evaluation — find()
97
+ * emits locator hints derived from DOM-walk-sourced roles that don't always
98
+ * map to a real Playwright role selector (e.g. `role=a` when the tag is `<a>`),
99
+ * and the bounding-box probe on those mismatched hints would otherwise hang
100
+ * for the full action-timeout window per candidate. Default cap is 500 ms —
101
+ * the wedge class is now a known hazard on every call site; per-caller opt-in
102
+ * (e.g. `{ timeoutMs: 1000 }`) raises it when the caller can absorb the wait.
103
+ */
104
+ export async function locatorBoundingBox(root, selector, opts = {}) {
105
+ const timeoutMs = opts.timeoutMs ?? 500;
106
+ try {
107
+ const box = await root.locator(selector).first().boundingBox({ timeout: timeoutMs });
108
+ if (!box || box.width <= 0 || box.height <= 0)
109
+ return null;
110
+ return { x: box.x, y: box.y, width: box.width, height: box.height };
111
+ }
112
+ catch {
113
+ return null;
114
+ }
115
+ }
@@ -0,0 +1,82 @@
1
+ export type CanvasFormat = "png" | "webgl-framebuffer" | "2d-imagedata";
2
+ export interface CanvasCaptureArgs {
3
+ /** Stable ref of the target `<canvas>` element (from snapshot/find).
4
+ * Omit to capture the first `<canvas>` in the document. */
5
+ ref?: string;
6
+ /** Optional CSS selector used as a fallback when `ref` lookup fails
7
+ * (or for callers who want a raw selector path). Honoured by the
8
+ * page-side capture function. */
9
+ selector?: string;
10
+ /** Output format. */
11
+ format: CanvasFormat;
12
+ }
13
+ export interface CanvasCapturePngResult {
14
+ ok: true;
15
+ format: "png";
16
+ /** Base64-encoded PNG bytes. */
17
+ contentBase64: string;
18
+ byteLength: number;
19
+ width: number;
20
+ height: number;
21
+ }
22
+ export interface CanvasCaptureRgbaResult {
23
+ ok: true;
24
+ format: "2d-imagedata" | "webgl-framebuffer";
25
+ /** Base64-encoded RGBA byte array (row-major, top-left origin for
26
+ * 2d-imagedata; for webgl-framebuffer, the page-side capture flips
27
+ * the readPixels result into top-left order to match imagedata's
28
+ * convention, so downstream `canvas_diff` math is consistent). */
29
+ contentBase64: string;
30
+ width: number;
31
+ height: number;
32
+ channelCount: 4;
33
+ /** Only set for `webgl-framebuffer` so the caller can tell the two
34
+ * RGBA formats apart on result. */
35
+ isWebGL?: true;
36
+ }
37
+ export type CanvasCaptureResult = CanvasCapturePngResult | CanvasCaptureRgbaResult | {
38
+ ok: false;
39
+ error: string;
40
+ code?: string;
41
+ };
42
+ /** Max canvas dimensions accepted by `canvas_capture`. Larger canvases
43
+ * refuse with a structured error rather than allocating a giant byte
44
+ * payload. 16384 matches Chromium's `max_texture_size` for most
45
+ * hardware — a `<canvas>` larger than this would not paint correctly
46
+ * anyway. */
47
+ export declare const CANVAS_MAX_DIMENSION = 16384;
48
+ /** Page-side raw-capture return — the loose discriminated union the page
49
+ * function produces (every field optional so it serializes cleanly across
50
+ * the CDP boundary). The host side narrows it back into CanvasCaptureResult. */
51
+ export interface PageCaptureRaw {
52
+ ok: boolean;
53
+ format?: CanvasFormat;
54
+ contentBase64?: string;
55
+ byteLength?: number;
56
+ width?: number;
57
+ height?: number;
58
+ channelCount?: number;
59
+ isWebGL?: boolean;
60
+ error?: string;
61
+ code?: string;
62
+ }
63
+ /** Page-side capture function — REAL function literal (NOT stringified).
64
+ * Playwright's `page.evaluate(fn, arg)` serializes the source + invokes
65
+ * in-page with the arg. Mirror of the pattern used in `dom_export` /
66
+ * `element_export` / `overflow_detect` — a stringified arrow function
67
+ * evaluates to the function value uncalled, which CDP can't serialize.
68
+ *
69
+ * Returns a structured discriminated union (mirror of CanvasCaptureResult)
70
+ * so the host side can pass it straight back. */
71
+ export declare const PAGE_CAPTURE_FN: (args: {
72
+ ref?: string;
73
+ selector?: string;
74
+ format: CanvasFormat;
75
+ maxDimension: number;
76
+ }) => PageCaptureRaw;
77
+ /** Thin adapter so unit tests can stub `page.evaluate` without launching
78
+ * Chromium. */
79
+ export interface CanvasCapturePage {
80
+ evaluate<T, Arg>(fn: (arg: Arg) => T | Promise<T>, args?: Arg): Promise<T>;
81
+ }
82
+ export declare function canvasCapture(page: CanvasCapturePage, args: CanvasCaptureArgs): Promise<CanvasCaptureResult>;