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,254 @@
1
+ // Capability toggles — security model. See `docs/threat-model.md` for the
2
+ // full design. The gist:
3
+ //
4
+ // - Tools group into coarse categories (`read`, `navigation`, `action`, `human`,
5
+ // `eval`, `byob-attach`, `file-io`). Each is independently enable/disable-able at
6
+ // server start.
7
+ // - Default set: read + navigation + action + human. `eval` / `byob-attach` /
8
+ // `file-io` are off-by-default — opt in via `BROWX_CAPABILITIES`.
9
+ // - The server's startup log lists the active set; `browxai doctor` warns when
10
+ // dangerous capabilities are on (`eval`, `byob-attach`).
11
+ //
12
+ // Configuring:
13
+ // BROWX_CAPABILITIES=read,navigation,action,human # the default
14
+ // BROWX_CAPABILITIES=read # read-only server
15
+ // BROWX_CAPABILITIES=read,navigation,action,human,eval # opts in to eval_js
16
+ export const ALL_CAPABILITIES = [
17
+ "read",
18
+ "navigation",
19
+ "action",
20
+ "human",
21
+ "eval",
22
+ "byob-attach",
23
+ "file-io",
24
+ "network-body",
25
+ "clipboard",
26
+ "secrets",
27
+ "extensions",
28
+ "stealth",
29
+ "captcha",
30
+ "credentials",
31
+ "device-emulation",
32
+ "diagnostics",
33
+ "canvas",
34
+ ];
35
+ export const DEFAULT_CAPABILITIES = [
36
+ "read",
37
+ "navigation",
38
+ "action",
39
+ "human",
40
+ ];
41
+ /**
42
+ * Capabilities that USED to be valid and have since been retired. A retired
43
+ * capability is still ACCEPTED in `BROWX_CAPABILITIES` (and the `capabilities`
44
+ * config key) — it is ignored with a deprecation warning, never an error — so
45
+ * evolving the capability set can't crash an existing adopter's config.
46
+ * Genuine typos (a name that was never a capability) are still rejected loudly.
47
+ * A retired entry may be dropped entirely only in a major version bump.
48
+ * See the "API evolution" rule in CLAUDE.md.
49
+ *
50
+ * The value is the agent/operator-facing reason + what to do instead.
51
+ */
52
+ export const RETIRED_CAPABILITIES = {
53
+ unstable: "the tools it gated (gestures, route mocking, compound act-and-observe " +
54
+ "tools, visual regions, profile snapshot/restore) were promoted into the " +
55
+ "default stable surface — it no longer gates anything; drop it from " +
56
+ "BROWX_CAPABILITIES",
57
+ };
58
+ /**
59
+ * The per-tool capability assignment is DERIVED (RFC 0004 P2 / D2): it lives at
60
+ * each tool's `host.register({ capability })` call (the single source of truth,
61
+ * src/tools/host.ts), not in a hand-maintained list here. This module owns the
62
+ * closed *vocabulary* (`Capability` / `ALL_CAPABILITIES` above); the per-tool
63
+ * rows are populated from the registration metadata via `declareToolCapability`,
64
+ * collected once by the tools-layer bootstrap (`src/tools/tool-metadata.ts`).
65
+ *
66
+ * A tool with no declared capability is treated as `human` (coordination
67
+ * primitive, always safe) — the same permissive default as before, now reachable
68
+ * only for the control-plane primitives that legitimately carry no browser
69
+ * capability (open_session, batch, get_config, …), never by a silent omission
70
+ * (the completeness fitness test asserts every browser tool declares one).
71
+ */
72
+ const TOOL_CAPABILITY_MAP = new Map();
73
+ /** Record one tool's capability assignment from its colocated
74
+ * `host.register({ capability })` metadata (RFC 0004 P2). Idempotent for an
75
+ * identical re-declaration; a *conflicting* one throws (two registrations cannot
76
+ * disagree on one tool's gate). The only writer of the derived map. */
77
+ export function declareToolCapability(tool, capability) {
78
+ const existing = TOOL_CAPABILITY_MAP.get(tool);
79
+ if (existing !== undefined && existing !== capability) {
80
+ throw new Error(`declareToolCapability: "${tool}" already declared as "${existing}", got "${capability}"`);
81
+ }
82
+ TOOL_CAPABILITY_MAP.set(tool, capability);
83
+ }
84
+ /** Lazy-collection seam (RFC 0004 P2). The tools layer installs a collector that
85
+ * runs the registration metadata once and populates the derived maps;
86
+ * `capabilities.ts` (a leaf) cannot import the tools layer, so the dependency is
87
+ * inverted through this setter. Every real entry point (`createServer`, the SDK
88
+ * client, the CLI, the package entry) reaches the tools-layer bootstrap, which
89
+ * installs the collector AND eagerly populates the map — so in production a gate
90
+ * read always sees the full derived rows. */
91
+ let toolMetadataCollector;
92
+ let toolMetadataLoaded = false;
93
+ /** True while the collector is mid-run. A re-entrant read during collection (the
94
+ * collector's own `resolveCapabilities`/`buildHost` path touches the gate) must
95
+ * tolerate the partially-populated map WITHOUT tripping the fail-safe — the
96
+ * collector is installed and running, so the map is about to be complete. */
97
+ let toolMetadataCollecting = false;
98
+ export function installToolMetadataCollector(collect) {
99
+ toolMetadataCollector = collect;
100
+ // A late install (after the first read already ran the empty map) still takes
101
+ // effect: clear the loaded flag so the next read collects.
102
+ toolMetadataLoaded = false;
103
+ }
104
+ function ensureToolMetadataLoaded() {
105
+ if (toolMetadataLoaded || toolMetadataCollector === undefined)
106
+ return;
107
+ toolMetadataLoaded = true; // set before running so re-entrant declares don't recurse
108
+ toolMetadataCollecting = true;
109
+ try {
110
+ toolMetadataCollector();
111
+ }
112
+ finally {
113
+ toolMetadataCollecting = false;
114
+ }
115
+ }
116
+ /**
117
+ * D1 fail-safe (RFC 0004 P2, SECURITY-CRITICAL): the capability gate must NEVER
118
+ * fail OPEN. If a reader hits the derived map while it is empty AND no collector
119
+ * was ever installed, the tools-layer bootstrap did not run — `isToolEnabled`
120
+ * would otherwise pass EVERYTHING through the permissive `human` default,
121
+ * silently un-gating `eval_js` / `register_secret` / `network_body` / the engine
122
+ * gate. Rather than fail open we throw a structured, actionable error so the
123
+ * misconfiguration is loud and impossible to ship. The guaranteed bootstrap
124
+ * (`tool-metadata.ts`, imported by every real entry point) is the primary
125
+ * mechanism that keeps this throw from firing in production; this is the backstop.
126
+ *
127
+ * The throw is suppressed only DURING collection (the collector's own gate read
128
+ * legitimately sees a partial map) — at that point a collector is installed and
129
+ * running, so the map is about to be complete.
130
+ */
131
+ function assertGateBootstrapped() {
132
+ if (TOOL_CAPABILITY_MAP.size > 0 || toolMetadataCollecting)
133
+ return;
134
+ throw new Error("browxai capability gate read before the tool-metadata bootstrap ran: the derived " +
135
+ "TOOL_CAPABILITY map is empty and no collector was installed. Refusing to fail OPEN " +
136
+ "(which would un-gate eval_js / register_secret / network_body). Import the package " +
137
+ 'entry ("browxai") or call createServer before reading the capability gate. ' +
138
+ "(RFC 0004 P2 / D1.)");
139
+ }
140
+ /** The derived tool→capability map. Reading drives the lazy collection so the
141
+ * rows declared at registration are present for a standalone caller, then
142
+ * asserts the gate is bootstrapped (fail-safe — never returns an empty
143
+ * un-gated map to a consumer). */
144
+ export function toolCapabilityMap() {
145
+ ensureToolMetadataLoaded();
146
+ assertGateBootstrapped();
147
+ return TOOL_CAPABILITY_MAP;
148
+ }
149
+ /** Back-compat `Record` view of the derived map for the consumers that index it
150
+ * by name (`TOOL_CAPABILITY[tool]`). A `Proxy` so a read both triggers the lazy
151
+ * collection and reflects any registration that ran after a prior read. Every
152
+ * access path that resolves a capability (the by-name `get`, the membership
153
+ * `has`, key enumeration, and the D2 `Symbol.iterator` Map-parity iterator)
154
+ * runs the D1 fail-safe — the gate never answers from an empty unbootstrapped
155
+ * map. */
156
+ export const TOOL_CAPABILITY = new Proxy(Object.create(null), {
157
+ get(_t, key) {
158
+ ensureToolMetadataLoaded();
159
+ // D2: Map-parity iteration — `for (const [tool, cap] of TOOL_CAPABILITY)`
160
+ // and `[...TOOL_CAPABILITY]` delegate to the backing Map's iterator. Bound
161
+ // to the Map so the internal-slot read keeps the right receiver.
162
+ if (key === Symbol.iterator) {
163
+ assertGateBootstrapped();
164
+ return TOOL_CAPABILITY_MAP[Symbol.iterator].bind(TOOL_CAPABILITY_MAP);
165
+ }
166
+ if (typeof key !== "string")
167
+ return undefined;
168
+ assertGateBootstrapped();
169
+ return TOOL_CAPABILITY_MAP.get(key);
170
+ },
171
+ has(_t, key) {
172
+ ensureToolMetadataLoaded();
173
+ assertGateBootstrapped();
174
+ return typeof key === "string" && TOOL_CAPABILITY_MAP.has(key);
175
+ },
176
+ ownKeys() {
177
+ ensureToolMetadataLoaded();
178
+ assertGateBootstrapped();
179
+ return [...TOOL_CAPABILITY_MAP.keys()];
180
+ },
181
+ getOwnPropertyDescriptor(_t, key) {
182
+ ensureToolMetadataLoaded();
183
+ assertGateBootstrapped();
184
+ if (typeof key === "string" && TOOL_CAPABILITY_MAP.has(key)) {
185
+ return { enumerable: true, configurable: true, value: TOOL_CAPABILITY_MAP.get(key) };
186
+ }
187
+ return undefined;
188
+ },
189
+ });
190
+ export function resolveCapabilities(env = process.env) {
191
+ const raw = env.BROWX_CAPABILITIES?.trim();
192
+ const list = raw
193
+ ? raw
194
+ .split(",")
195
+ .map((s) => s.trim())
196
+ .filter(Boolean)
197
+ : [...DEFAULT_CAPABILITIES];
198
+ const warnings = [];
199
+ const live = [];
200
+ const unknown = [];
201
+ for (const c of list) {
202
+ if (ALL_CAPABILITIES.includes(c)) {
203
+ live.push(c);
204
+ }
205
+ else if (Object.prototype.hasOwnProperty.call(RETIRED_CAPABILITIES, c)) {
206
+ // Retired, not unknown — tolerate it so an old config never crashes.
207
+ warnings.push(`BROWX_CAPABILITIES: "${c}" is a retired capability — ${RETIRED_CAPABILITIES[c]}. ` +
208
+ `It is ignored (no effect); the rest of your config is honoured.`);
209
+ }
210
+ else {
211
+ unknown.push(c);
212
+ }
213
+ }
214
+ if (unknown.length) {
215
+ throw new Error(`BROWX_CAPABILITIES: unknown capability/capabilities ${unknown.map((u) => JSON.stringify(u)).join(", ")}. ` +
216
+ `Valid: ${ALL_CAPABILITIES.join(", ")}.`);
217
+ }
218
+ const enabled = new Set(live);
219
+ const disabledTools = [];
220
+ for (const [tool, cap] of toolCapabilityMap()) {
221
+ if (!enabled.has(cap))
222
+ disabledTools.push({ tool, capability: cap });
223
+ }
224
+ return { enabled, disabledTools, warnings };
225
+ }
226
+ /** Returns true iff the tool is enabled given the active capability set. */
227
+ export function isToolEnabled(tool, caps) {
228
+ const cap = toolCapabilityMap().get(tool);
229
+ if (!cap)
230
+ return true; // unknown tool: pass through (human-coordination default)
231
+ return caps.enabled.has(cap);
232
+ }
233
+ const ALL_CONFIRM_HOOKS = [
234
+ "navigate_off_allowlist",
235
+ "file_download",
236
+ "file_upload",
237
+ "byob_action",
238
+ ];
239
+ const DEFAULT_CONFIRM_HOOKS = ["navigate_off_allowlist", "byob_action"];
240
+ export function resolveConfirmHooks(env = process.env) {
241
+ const raw = env.BROWX_CONFIRM_REQUIRED?.trim();
242
+ if (!raw)
243
+ return new Set(DEFAULT_CONFIRM_HOOKS);
244
+ const list = raw
245
+ .split(",")
246
+ .map((s) => s.trim())
247
+ .filter(Boolean);
248
+ const unknown = list.filter((h) => !ALL_CONFIRM_HOOKS.includes(h));
249
+ if (unknown.length) {
250
+ throw new Error(`BROWX_CONFIRM_REQUIRED: unknown hook(s) ${unknown.map((u) => JSON.stringify(u)).join(", ")}. ` +
251
+ `Valid: ${ALL_CONFIRM_HOOKS.join(", ")}.`);
252
+ }
253
+ return new Set(list);
254
+ }
@@ -0,0 +1,103 @@
1
+ /** Full resolved view consumed by the server. */
2
+ export interface ResolvedConfig {
3
+ testAttributes: string[];
4
+ capabilities: string[];
5
+ confirmRequired: string[];
6
+ allowedOrigins: string[];
7
+ blockedOrigins: string[];
8
+ headless: boolean;
9
+ /** hard anti-wedge deadline (ms) applied to every action body /
10
+ * `eval_js` / read-CDP path. Default 5000. Per-call `timeoutMs` overrides.
11
+ * Clamped to [1, 3_600_000] at use. A real op completes well under this;
12
+ * raising it as a blanket masks no-ops/wedges. */
13
+ actionTimeoutMs?: number;
14
+ /** when true, `managed` / `incognito` sessions launch with
15
+ * `--disable-web-security --disable-site-isolation-trials` (SOP/CORS OFF
16
+ * browser-wide). Dangerous opt-in — off by default, loud-warned, and
17
+ * deliberately NOT mappable from the legacy env layer (set via MCP
18
+ * `set_config` or the managed config file only). No effect on
19
+ * `attached`/BYOB (externally launched). */
20
+ disableWebSecurity?: boolean;
21
+ /** default device-preset name for new sessions (Playwright device
22
+ * registry, e.g. "iPhone 14"). Overridable per `open_session`. */
23
+ defaultDevice?: string;
24
+ /** default viewport for new sessions. Overrides a preset's viewport
25
+ * when both are set. Overridable per `open_session`. */
26
+ defaultViewport?: {
27
+ width: number;
28
+ height: number;
29
+ };
30
+ /** CSS selectors for chrome/overlay elements (dev-build HMR widgets,
31
+ * devtools iframes, cookie/consent banners) that should be neutralised
32
+ * before the agent interacts with the page. A server-injected init
33
+ * script applies `pointer-events:none; display:none` to matches on every
34
+ * navigation — non-destructive (no node removal), config-driven, no
35
+ * agent JS. Default `[]` (feature off). */
36
+ hideOverlaySelectors: string[];
37
+ /** declarative plugin set. Mirrors what `plugins.json`
38
+ * declares; persisted alongside other config so `set_config({plugins})`
39
+ * and `get_config({scope:"resolved"}).plugins` work without hand-editing
40
+ * the plugins.json file. Plugin lifecycle is RESOLVED ONCE AT SERVER
41
+ * START — `set_config` persists, but takes effect on next restart
42
+ * (mirrors `capabilities`). Empty array = "no plugins declared". */
43
+ plugins: string[];
44
+ /** Experimental / feature-flag knobs. Not stable; shallow-merged across layers. */
45
+ unstable: Record<string, unknown>;
46
+ }
47
+ /** A partial override at one precedence layer. Every key optional. */
48
+ export type ConfigLayer = Partial<Omit<ResolvedConfig, "unstable">> & {
49
+ unstable?: Record<string, unknown>;
50
+ };
51
+ export type PersistentScope = "user" | "project";
52
+ export type ConfigScope = "defaults" | "env" | PersistentScope | "session";
53
+ export declare const BUILTIN_DEFAULTS: ResolvedConfig;
54
+ /** Legacy `BROWX_*` env vars as a low-precedence layer (above defaults). */
55
+ export declare function envLayer(env?: NodeJS.ProcessEnv): ConfigLayer;
56
+ export declare class ConfigStore {
57
+ private filePath;
58
+ private persisted;
59
+ private env;
60
+ constructor(workspaceRoot: string, env?: NodeJS.ProcessEnv);
61
+ private load;
62
+ private save;
63
+ /** Merge one layer onto an accumulator. Arrays replace; unstable shallow-merges. */
64
+ private static apply;
65
+ /** The precedence chain as DATA (RFC 0004 P4 / D6) — replacing the four
66
+ * fixed-order `apply` calls + the `getLayer` switch. The array order IS the
67
+ * precedence, applied lowest → highest: env < user < project < session, atop
68
+ * the built-in defaults base. CRITICAL: reordering this array silently
69
+ * changes which layer wins, so the order is pinned by the config-store unit
70
+ * tests for every layer permutation. `read(store, sessionPatch)` returns the
71
+ * raw pre-merge layer for that scope (the same value the old `getLayer` arm
72
+ * returned). Adding a layer is one entry here, not edits to two methods.
73
+ *
74
+ * `defaults` is NOT in this array: it is the base accumulator, not an
75
+ * override layer (`getLayer("defaults")` returns the resolved base directly).
76
+ * `session` reads `sessionPatch` during `resolve()` but is not held on the
77
+ * store, so its `getLayer` view is `{}` — preserved exactly. */
78
+ private static readonly PRECEDENCE;
79
+ /** Resolve the full config. `sessionPatch` is the highest-precedence layer.
80
+ * Iterates `PRECEDENCE` low → high atop the defaults base — byte-identical to
81
+ * the old fixed `apply(env) → apply(user) → apply(project) → apply(session)`
82
+ * sequence, now data-driven. */
83
+ resolve(sessionPatch?: ConfigLayer): ResolvedConfig;
84
+ /** Inspect one layer (raw, pre-merge) — for `get_config({ scope })`. Reads the
85
+ * same `PRECEDENCE` array `resolve()` iterates, so the inspected layer and the
86
+ * applied layer can never diverge. `defaults` returns the base directly (it is
87
+ * not an override layer); `session` is never held here, so its raw view is
88
+ * `{}` — both preserved exactly. */
89
+ getLayer(scope: ConfigScope): ConfigLayer | ResolvedConfig;
90
+ /** Persist a patch into `user` or `project`. The only writer of config.json. */
91
+ setLayer(scope: PersistentScope, patch: ConfigLayer): void;
92
+ /** Clear a persistent layer entirely. */
93
+ resetLayer(scope: PersistentScope): void;
94
+ }
95
+ /**
96
+ * Adapter: render a `ResolvedConfig` as an env-shaped record so the existing
97
+ * env-driven resolvers (`resolveCapabilities` / `resolveOriginPolicy` /
98
+ * `resolveConfirmHooks` / `resolveConfig`) can consume the *fully resolved*
99
+ * precedence chain without each being rewritten. Precedence is already applied
100
+ * in `ConfigStore.resolve()`; this just re-expresses the result in the shape
101
+ * those functions parse.
102
+ */
103
+ export declare function resolvedToEnv(c: ResolvedConfig): NodeJS.ProcessEnv;
@@ -0,0 +1,206 @@
1
+ // browxai-managed config store.
2
+ //
3
+ // Precedence (lowest → highest):
4
+ // built-in defaults < env (legacy BROWX_*) < user < project < session patch
5
+ //
6
+ // Persistent layers live in `<workspace>/config.json` as
7
+ // `{ "user": {...}, "project": {...} }` and are mutated ONLY via
8
+ // set_config / reset_config (the MCP tools). The file is machine-managed —
9
+ // a malformed file degrades to "ignore that layer + warn", never a crash.
10
+ //
11
+ // `workspace` (root path) is intentionally NOT config — it's the *location*
12
+ // the store itself lives at, resolved before the store exists.
13
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
14
+ import { join } from "node:path";
15
+ import { log } from "./logging.js";
16
+ import { invariant } from "./invariant.js";
17
+ export const BUILTIN_DEFAULTS = {
18
+ testAttributes: ["data-testid", "data-test", "data-cy", "data-qa"],
19
+ capabilities: ["read", "navigation", "action", "human"],
20
+ confirmRequired: ["navigate_off_allowlist", "byob_action"],
21
+ allowedOrigins: [],
22
+ blockedOrigins: [],
23
+ headless: false,
24
+ hideOverlaySelectors: [],
25
+ plugins: [],
26
+ unstable: {},
27
+ };
28
+ const CONFIG_FILE = "config.json";
29
+ /** Legacy `BROWX_*` env vars as a low-precedence layer (above defaults). */
30
+ export function envLayer(env = process.env) {
31
+ const layer = {};
32
+ const list = (v) => v
33
+ ? v
34
+ .split(",")
35
+ .map((s) => s.trim())
36
+ .filter(Boolean)
37
+ : undefined;
38
+ const ta = list(env.BROWX_TEST_ATTRIBUTES?.trim());
39
+ if (ta)
40
+ layer.testAttributes = ta;
41
+ const caps = list(env.BROWX_CAPABILITIES?.trim());
42
+ if (caps)
43
+ layer.capabilities = caps;
44
+ const cr = list(env.BROWX_CONFIRM_REQUIRED?.trim());
45
+ if (cr)
46
+ layer.confirmRequired = cr;
47
+ const ao = list(env.BROWX_ALLOWED_ORIGINS?.trim());
48
+ if (ao)
49
+ layer.allowedOrigins = ao;
50
+ const bo = list(env.BROWX_BLOCKED_ORIGINS?.trim());
51
+ if (bo)
52
+ layer.blockedOrigins = bo;
53
+ const hl = env.BROWX_HEADLESS?.trim();
54
+ if (hl)
55
+ layer.headless = hl === "1" || hl.toLowerCase() === "true";
56
+ const hos = list(env.BROWX_HIDE_OVERLAY_SELECTORS?.trim());
57
+ if (hos)
58
+ layer.hideOverlaySelectors = hos;
59
+ return layer;
60
+ }
61
+ export class ConfigStore {
62
+ filePath;
63
+ persisted = {};
64
+ env;
65
+ constructor(workspaceRoot, env = process.env) {
66
+ this.filePath = join(workspaceRoot, CONFIG_FILE);
67
+ this.env = envLayer(env);
68
+ this.load();
69
+ }
70
+ load() {
71
+ if (!existsSync(this.filePath))
72
+ return;
73
+ try {
74
+ const raw = JSON.parse(readFileSync(this.filePath, "utf8"));
75
+ // Defensive: only accept the two known sections; ignore anything else.
76
+ this.persisted = {
77
+ ...(raw.user && typeof raw.user === "object" ? { user: raw.user } : {}),
78
+ ...(raw.project && typeof raw.project === "object" ? { project: raw.project } : {}),
79
+ };
80
+ }
81
+ catch (e) {
82
+ log.warn(`config: ${CONFIG_FILE} is malformed — ignoring persistent layers`, {
83
+ error: e instanceof Error ? e.message : String(e),
84
+ });
85
+ this.persisted = {};
86
+ }
87
+ }
88
+ save() {
89
+ try {
90
+ writeFileSync(this.filePath, JSON.stringify(this.persisted, null, 2) + "\n", "utf8");
91
+ }
92
+ catch (e) {
93
+ log.warn(`config: failed to write ${CONFIG_FILE}`, {
94
+ error: e instanceof Error ? e.message : String(e),
95
+ });
96
+ }
97
+ }
98
+ /** Merge one layer onto an accumulator. Arrays replace; unstable shallow-merges. */
99
+ static apply(acc, layer) {
100
+ if (!layer)
101
+ return acc;
102
+ return {
103
+ testAttributes: layer.testAttributes ?? acc.testAttributes,
104
+ capabilities: layer.capabilities ?? acc.capabilities,
105
+ confirmRequired: layer.confirmRequired ?? acc.confirmRequired,
106
+ allowedOrigins: layer.allowedOrigins ?? acc.allowedOrigins,
107
+ blockedOrigins: layer.blockedOrigins ?? acc.blockedOrigins,
108
+ headless: layer.headless ?? acc.headless,
109
+ actionTimeoutMs: layer.actionTimeoutMs ?? acc.actionTimeoutMs,
110
+ disableWebSecurity: layer.disableWebSecurity ?? acc.disableWebSecurity,
111
+ defaultDevice: layer.defaultDevice ?? acc.defaultDevice,
112
+ defaultViewport: layer.defaultViewport ?? acc.defaultViewport,
113
+ hideOverlaySelectors: layer.hideOverlaySelectors ?? acc.hideOverlaySelectors,
114
+ plugins: layer.plugins ?? acc.plugins,
115
+ unstable: layer.unstable ? { ...acc.unstable, ...layer.unstable } : acc.unstable,
116
+ };
117
+ }
118
+ /** The precedence chain as DATA (RFC 0004 P4 / D6) — replacing the four
119
+ * fixed-order `apply` calls + the `getLayer` switch. The array order IS the
120
+ * precedence, applied lowest → highest: env < user < project < session, atop
121
+ * the built-in defaults base. CRITICAL: reordering this array silently
122
+ * changes which layer wins, so the order is pinned by the config-store unit
123
+ * tests for every layer permutation. `read(store, sessionPatch)` returns the
124
+ * raw pre-merge layer for that scope (the same value the old `getLayer` arm
125
+ * returned). Adding a layer is one entry here, not edits to two methods.
126
+ *
127
+ * `defaults` is NOT in this array: it is the base accumulator, not an
128
+ * override layer (`getLayer("defaults")` returns the resolved base directly).
129
+ * `session` reads `sessionPatch` during `resolve()` but is not held on the
130
+ * store, so its `getLayer` view is `{}` — preserved exactly. */
131
+ static PRECEDENCE = [
132
+ { scope: "env", read: (s) => s.env },
133
+ { scope: "user", read: (s) => s.persisted.user },
134
+ { scope: "project", read: (s) => s.persisted.project },
135
+ { scope: "session", read: (_s, sessionPatch) => sessionPatch },
136
+ ];
137
+ /** Resolve the full config. `sessionPatch` is the highest-precedence layer.
138
+ * Iterates `PRECEDENCE` low → high atop the defaults base — byte-identical to
139
+ * the old fixed `apply(env) → apply(user) → apply(project) → apply(session)`
140
+ * sequence, now data-driven. */
141
+ resolve(sessionPatch) {
142
+ // L8: the precedence chain must be non-empty and `session` must be its
143
+ // highest-precedence (last) layer — the whole contract of `resolve()` is
144
+ // "apply lowest → highest, session wins". A reordering that demoted `session`
145
+ // would silently let a persisted layer override an open_session patch. The
146
+ // PRECEDENCE array is a fixed module constant ending in `session`, so this
147
+ // holds on every call; the invariant pins the ordering contract at the one
148
+ // place it is depended on, complementing the per-permutation unit tests.
149
+ const chain = ConfigStore.PRECEDENCE;
150
+ invariant(chain.length > 0, "config precedence chain is empty");
151
+ invariant(chain[chain.length - 1].scope === "session", "config precedence: `session` must be the highest-precedence layer");
152
+ let acc = { ...BUILTIN_DEFAULTS, unstable: { ...BUILTIN_DEFAULTS.unstable } };
153
+ for (const layer of chain) {
154
+ acc = ConfigStore.apply(acc, layer.read(this, sessionPatch));
155
+ }
156
+ return acc;
157
+ }
158
+ /** Inspect one layer (raw, pre-merge) — for `get_config({ scope })`. Reads the
159
+ * same `PRECEDENCE` array `resolve()` iterates, so the inspected layer and the
160
+ * applied layer can never diverge. `defaults` returns the base directly (it is
161
+ * not an override layer); `session` is never held here, so its raw view is
162
+ * `{}` — both preserved exactly. */
163
+ getLayer(scope) {
164
+ if (scope === "defaults")
165
+ return BUILTIN_DEFAULTS;
166
+ const entry = ConfigStore.PRECEDENCE.find((l) => l.scope === scope);
167
+ // session config isn't held here (it's per open_session), so its raw layer
168
+ // is `{}`; every other scope returns its stored layer (or `{}` when unset).
169
+ return entry?.read(this) ?? {};
170
+ }
171
+ /** Persist a patch into `user` or `project`. The only writer of config.json. */
172
+ setLayer(scope, patch) {
173
+ const current = this.persisted[scope] ?? {};
174
+ this.persisted[scope] = {
175
+ ...current,
176
+ ...patch,
177
+ ...(patch.unstable ? { unstable: { ...(current.unstable ?? {}), ...patch.unstable } } : {}),
178
+ };
179
+ this.save();
180
+ log.info(`config: set scope="${scope}"`, { keys: Object.keys(patch) });
181
+ }
182
+ /** Clear a persistent layer entirely. */
183
+ resetLayer(scope) {
184
+ delete this.persisted[scope];
185
+ this.save();
186
+ log.info(`config: reset scope="${scope}"`);
187
+ }
188
+ }
189
+ /**
190
+ * Adapter: render a `ResolvedConfig` as an env-shaped record so the existing
191
+ * env-driven resolvers (`resolveCapabilities` / `resolveOriginPolicy` /
192
+ * `resolveConfirmHooks` / `resolveConfig`) can consume the *fully resolved*
193
+ * precedence chain without each being rewritten. Precedence is already applied
194
+ * in `ConfigStore.resolve()`; this just re-expresses the result in the shape
195
+ * those functions parse.
196
+ */
197
+ export function resolvedToEnv(c) {
198
+ return {
199
+ BROWX_TEST_ATTRIBUTES: c.testAttributes.join(","),
200
+ BROWX_CAPABILITIES: c.capabilities.join(","),
201
+ BROWX_CONFIRM_REQUIRED: c.confirmRequired.join(","),
202
+ BROWX_ALLOWED_ORIGINS: c.allowedOrigins.join(","),
203
+ BROWX_BLOCKED_ORIGINS: c.blockedOrigins.join(","),
204
+ BROWX_HEADLESS: c.headless ? "1" : "",
205
+ };
206
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Threshold below which `snapshot()` emits the "low-content" warning (
3
+ * ). Tuned conservatively — most non-trivial pages have well more than 5
4
+ * interactive descendants in the a11y tree; a hydrated page returning fewer is
5
+ * almost always a sparse-a11y SPA where the DOM-walk fallback wins.
6
+ */
7
+ export declare const LOW_A11Y_THRESHOLD = 5;
8
+ export interface BrowxConfig {
9
+ testAttributes: string[];
10
+ }
11
+ export declare function resolveConfig(env?: NodeJS.ProcessEnv): BrowxConfig;
@@ -0,0 +1,28 @@
1
+ // Runtime configuration sourced from env. Resolved once at startup so behaviour
2
+ // is predictable per-session. Adopters who need to add a project-conventional
3
+ // data-attribute (e.g. some codebases use `data-type`, `data-cy`, `data-qa`)
4
+ // can do so without code changes:
5
+ //
6
+ // BROWX_TEST_ATTRIBUTES=data-testid,data-test,data-cy,data-qa,data-type
7
+ //
8
+ // The list is order-sensitive: the **first** match on a node wins as its `testId`
9
+ // and the matched attribute name flows through to selectorHint so the agent
10
+ // transcribes the right selector ("[data-type=\"foo\"]", not "[data-testid=\"foo\"]").
11
+ const DEFAULT_TEST_ATTRIBUTES = ["data-testid", "data-test", "data-cy", "data-qa"];
12
+ /**
13
+ * Threshold below which `snapshot()` emits the "low-content" warning (
14
+ * ). Tuned conservatively — most non-trivial pages have well more than 5
15
+ * interactive descendants in the a11y tree; a hydrated page returning fewer is
16
+ * almost always a sparse-a11y SPA where the DOM-walk fallback wins.
17
+ */
18
+ export const LOW_A11Y_THRESHOLD = 5;
19
+ export function resolveConfig(env = process.env) {
20
+ const raw = env.BROWX_TEST_ATTRIBUTES?.trim();
21
+ const list = raw
22
+ ? raw
23
+ .split(",")
24
+ .map((s) => s.trim())
25
+ .filter(Boolean)
26
+ : DEFAULT_TEST_ATTRIBUTES;
27
+ return { testAttributes: list };
28
+ }