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,579 @@
1
+ // Diagnostics — structured per-call recording + agent self-feedback.
2
+ //
3
+ // . Off-by-default `diagnostics` capability; once enabled, every MCP
4
+ // tool call is recorded as a JSONL line in
5
+ // $BROWX_WORKSPACE/diagnostics/<sessionId>/<server-start-ISO>.jsonl
6
+ // and the three diagnostics_* tools surface a read-side query / report.
7
+ //
8
+ // Recorder posture (LOAD-BEARING):
9
+ // 1. ZERO observable side-effect when the capability is OFF — no allocations
10
+ // beyond a single boolean gate check, no file IO, no recorder method
11
+ // calls. The dispatch wrapper in server.ts short-circuits on
12
+ // `recorder.enabled` before doing anything else.
13
+ // 2. Runs DOWNSTREAM of the URL sanitiser + secrets-masking egress
14
+ // chokepoint — by the time the recorder sees a tool result, every
15
+ // egress sink has already rewritten registered secret values back to
16
+ // `<NAME>` aliases. The recorder additionally walks args through the
17
+ // same `applyMaskDeep` helper so a secret echoed in the call ARGS (e.g.
18
+ // a `fill({value:<PASSWORD>})` that materialised at dispatch) never
19
+ // lands raw in the JSONL.
20
+ // 3. Workspace-rooted by construction via `resolveWorkspacePath` — a
21
+ // session id of `../escape` is rejected at the path-resolution chokepoint
22
+ // and the dispatch path falls back to a no-op (the call still runs;
23
+ // only the recording is skipped).
24
+ //
25
+ // Storage shape (JSONL — one record per line, append-only):
26
+ // { kind:"call", ts, tool, sessionId, argsRedacted, resultMeta:{ok,
27
+ // sizeBytes, warningsCount, failureKind}, durationMs, capabilityDenials,
28
+ // agentId?, evalJs?:{exprSha, exprHead, returnType, returnSizeBytes,
29
+ // taxonomy} }
30
+ // { kind:"note", ts, sessionId, insight, category, severity, ref?, agentId? }
31
+ //
32
+ // Retention: env `BROWX_DIAGNOSTICS_RETENTION_DAYS` (default 30). Expired
33
+ // session directories are removed at server start AND on session close.
34
+ import { createHash } from "node:crypto";
35
+ import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, appendFileSync, } from "node:fs";
36
+ import { join, sep as pathSep } from "node:path";
37
+ import { resolveWorkspacePath } from "../session/storage.js";
38
+ // ---------------------------------------------------------------------------
39
+ // Recorder
40
+ // ---------------------------------------------------------------------------
41
+ /** Default retention window in days. Mirrors the standing rule that
42
+ * diagnostics is a development-time aid, not a long-term log archive. */
43
+ export const DEFAULT_RETENTION_DAYS = 30;
44
+ /** Workspace subdir for diagnostics JSONL. */
45
+ const DIAG_DIR = "diagnostics";
46
+ /** Field names whose payload is opportunistically rewritten to sha256 +
47
+ * byteLength when the string is large (above the inline threshold). Small
48
+ * strings — a `fill({value:"hi"})` or a typed `<NAME>` alias — pass through
49
+ * the standard string-truncation path so the JSONL stays human-debuggable
50
+ * for the common short-value case. The threshold mirrors the structural
51
+ * intent: redact for content blobs (caches_put body, idb_put value,
52
+ * eval_js expr fragments), not for typed UI strings. */
53
+ const BIG_BLOB_FIELDS = new Set([
54
+ "body",
55
+ "contentBase64",
56
+ "value",
57
+ "expr",
58
+ "expression",
59
+ "data",
60
+ "contents",
61
+ "html",
62
+ "source",
63
+ ]);
64
+ /** Threshold (bytes) above which a `BIG_BLOB_FIELDS` field is rewritten to
65
+ * sha256 + byteLength. Below this, the standard truncation path applies. */
66
+ const BIG_BLOB_REDACT_BYTES = 512;
67
+ /** Args fields the recorder rewrites to the `<NAME>` alias before writing,
68
+ * using the same `applyMaskDeep` the egress sinks do — so a secret echoed in
69
+ * args never reaches the JSONL raw. (The masking layer at egress catches it
70
+ * on result side; this catches it on args side.) */
71
+ function maskedArgs(args, secrets) {
72
+ if (!secrets)
73
+ return args;
74
+ return secrets.applyMaskDeep(args);
75
+ }
76
+ /** Resolve the diagnostics root path under the workspace. Rejects any
77
+ * session id that escapes the diagnostics subdir (`../escape`,
78
+ * absolute paths). The thrown error carries a stable prefix the dispatch
79
+ * wrapper recognises to fall back to no-op. */
80
+ export function resolveDiagnosticsPath(workspaceRoot, sessionId, serverStartIso) {
81
+ // `resolveWorkspacePath` rejects anything escaping the workspace root;
82
+ // we want stricter — the path must escape NEITHER the workspace nor the
83
+ // diagnostics subdir. Compose by resolving the full relative path and
84
+ // checking the prefix.
85
+ const rel = join(DIAG_DIR, sessionId, `${serverStartIso}.jsonl`);
86
+ const resolved = resolveWorkspacePath(workspaceRoot, rel, "diagnostics");
87
+ const diagRoot = resolveWorkspacePath(workspaceRoot, DIAG_DIR, "diagnostics");
88
+ if (resolved !== diagRoot && !resolved.startsWith(diagRoot + pathSep)) {
89
+ throw new Error(`diagnostics: sessionId "${sessionId}" must not escape the diagnostics ` +
90
+ `subdir — got resolved path "${resolved}"`);
91
+ }
92
+ return resolved;
93
+ }
94
+ /** Returns the diagnostics root dir (creating it if needed). The path is
95
+ * workspace.root-rooted by construction — caller passes `workspace.root`
96
+ * from `resolveWorkspace()`. */
97
+ export function ensureDiagnosticsRoot(workspaceRoot) {
98
+ // workspace.root-rooted by construction (see comment above).
99
+ const root = join(workspaceRoot, DIAG_DIR);
100
+ if (!existsSync(root))
101
+ mkdirSync(root, { recursive: true });
102
+ return root;
103
+ }
104
+ /** Resolve retention window from env. Defaults to 30 days; negative /
105
+ * non-numeric falls back to the default with no error. `0` disables the
106
+ * sweep (everything is kept). */
107
+ export function resolveRetentionDays(env = process.env) {
108
+ const raw = env.BROWX_DIAGNOSTICS_RETENTION_DAYS?.trim();
109
+ if (!raw)
110
+ return DEFAULT_RETENTION_DAYS;
111
+ const parsed = Number(raw);
112
+ if (!Number.isFinite(parsed) || parsed < 0)
113
+ return DEFAULT_RETENTION_DAYS;
114
+ return Math.floor(parsed);
115
+ }
116
+ /** Remove session directories whose newest JSONL file is older than the
117
+ * retention window. `0` disables the sweep entirely. Best-effort: a
118
+ * permission error on one session doesn't block the rest. */
119
+ export function sweepRetention(workspaceRoot, retentionDays, now = Date.now()) {
120
+ const root = join(workspaceRoot, DIAG_DIR);
121
+ if (!existsSync(root) || retentionDays <= 0)
122
+ return { removed: [], kept: [] };
123
+ const cutoff = now - retentionDays * 24 * 60 * 60 * 1000;
124
+ const removed = [];
125
+ const kept = [];
126
+ let entries = [];
127
+ try {
128
+ entries = readdirSync(root);
129
+ }
130
+ catch {
131
+ return { removed, kept };
132
+ }
133
+ for (const id of entries) {
134
+ const sessionDir = join(root, id);
135
+ let st;
136
+ try {
137
+ st = statSync(sessionDir);
138
+ }
139
+ catch {
140
+ continue;
141
+ }
142
+ if (!st.isDirectory())
143
+ continue;
144
+ // Newest mtime across the session's JSONL files. If none, treat as
145
+ // ancient — the directory predates any retained run.
146
+ let newest = 0;
147
+ try {
148
+ for (const file of readdirSync(sessionDir)) {
149
+ const full = join(sessionDir, file);
150
+ const fst = statSync(full);
151
+ if (fst.mtimeMs > newest)
152
+ newest = fst.mtimeMs;
153
+ }
154
+ }
155
+ catch {
156
+ /* best-effort */
157
+ }
158
+ if (newest === 0 || newest < cutoff) {
159
+ try {
160
+ rmSync(sessionDir, { recursive: true, force: true });
161
+ removed.push(id);
162
+ }
163
+ catch {
164
+ /* best-effort */
165
+ }
166
+ }
167
+ else {
168
+ kept.push(id);
169
+ }
170
+ }
171
+ return { removed, kept };
172
+ }
173
+ /** Remove a single session's diagnostics directory. Used on session close. */
174
+ export function removeSessionDiagnostics(workspaceRoot, sessionId) {
175
+ const root = join(workspaceRoot, DIAG_DIR);
176
+ // Reject escape attempts the same way the write path does.
177
+ let dir;
178
+ try {
179
+ dir = resolveWorkspacePath(workspaceRoot, join(DIAG_DIR, sessionId), "diagnostics");
180
+ }
181
+ catch {
182
+ return false;
183
+ }
184
+ const diagRoot = root;
185
+ if (dir !== diagRoot && !dir.startsWith(diagRoot + pathSep))
186
+ return false;
187
+ if (!existsSync(dir))
188
+ return false;
189
+ try {
190
+ rmSync(dir, { recursive: true, force: true });
191
+ return true;
192
+ }
193
+ catch {
194
+ return false;
195
+ }
196
+ }
197
+ /**
198
+ * The recorder. One instance per server. The capability gate is captured at
199
+ * construction; `enabled` is the public hot-path flag the dispatch wrapper
200
+ * checks BEFORE allocating anything (zero-overhead off-path).
201
+ */
202
+ export class DiagnosticsRecorder {
203
+ /** Hot-path gate — checked at the dispatch boundary. When false, every
204
+ * recorder method short-circuits to a no-op AND the dispatch wrapper
205
+ * is expected to NOT enter the recorder code path at all. */
206
+ enabled;
207
+ serverStartIso;
208
+ workspaceRoot;
209
+ retentionDays;
210
+ /** Capability denials accumulator (process-wide). Mirrors the snapshot the
211
+ * session-metrics module tracks per-session; diagnostics tracks it across
212
+ * every session to surface a single "how many gate hits did this server
213
+ * see" rollup in `diagnostics_report`. */
214
+ denials = 0;
215
+ constructor(opts) {
216
+ this.enabled = opts.enabled;
217
+ this.workspaceRoot = opts.workspaceRoot;
218
+ this.serverStartIso = opts.serverStartIso ?? new Date().toISOString().replace(/[:.]/g, "-");
219
+ this.retentionDays = opts.retentionDays ?? DEFAULT_RETENTION_DAYS;
220
+ }
221
+ /** Write one record. No-op when the recorder is disabled or the path
222
+ * resolution fails (workspace escape — the call still runs, only the
223
+ * recording is skipped). */
224
+ write(record) {
225
+ if (!this.enabled)
226
+ return;
227
+ let path;
228
+ try {
229
+ path = resolveDiagnosticsPath(this.workspaceRoot, record.sessionId, this.serverStartIso);
230
+ }
231
+ catch {
232
+ // Workspace-escape: skip silently. The session id was already
233
+ // validated upstream (session ids are agent-provided strings); a
234
+ // pathological id here means the agent passed `../escape` to a tool
235
+ // that didn't validate — the call still runs, just unrecorded.
236
+ return;
237
+ }
238
+ // `dir` is workspace.root-rooted by construction — `resolveDiagnosticsPath`
239
+ // (above) rejects any path that escapes `workspace.root`, so a successful
240
+ // resolve guarantees `<workspace>/diagnostics/<sessionId>/` lives under
241
+ // BROWX_WORKSPACE.
242
+ const dir = join(this.workspaceRoot, DIAG_DIR, record.sessionId);
243
+ try {
244
+ // ws.sub-equivalent: parent dir creation rooted at workspace.root.
245
+ if (!existsSync(dir))
246
+ mkdirSync(dir, { recursive: true });
247
+ // workspace.root-rooted by construction (see comment above).
248
+ appendFileSync(path, JSON.stringify(record) + "\n", "utf8");
249
+ }
250
+ catch {
251
+ // Best-effort — a disk-full / permission error on the diagnostics
252
+ // path must NEVER take down a tool call.
253
+ }
254
+ }
255
+ /** Increment the capability-denials counter — surfaced on
256
+ * `diagnostics_report` so the agent's "tried to use a gated tool"
257
+ * pattern is one read. */
258
+ noteDenial() {
259
+ if (!this.enabled)
260
+ return;
261
+ this.denials += 1;
262
+ }
263
+ /** Read-back: enumerate every record in the workspace's diagnostics
264
+ * store. Order: by session id, then by file mtime (oldest first), then
265
+ * by line order within a file. Used by the read-side query tools.
266
+ * Best-effort — unreadable files are skipped. */
267
+ readAll() {
268
+ const out = [];
269
+ const root = join(this.workspaceRoot, DIAG_DIR);
270
+ if (!existsSync(root))
271
+ return out;
272
+ let sessionDirs = [];
273
+ try {
274
+ sessionDirs = readdirSync(root).sort();
275
+ }
276
+ catch {
277
+ return out;
278
+ }
279
+ for (const id of sessionDirs) {
280
+ const sd = join(root, id);
281
+ let st;
282
+ try {
283
+ st = statSync(sd);
284
+ }
285
+ catch {
286
+ continue;
287
+ }
288
+ if (!st.isDirectory())
289
+ continue;
290
+ let files = [];
291
+ try {
292
+ files = readdirSync(sd);
293
+ }
294
+ catch {
295
+ continue;
296
+ }
297
+ // Order files by mtime, oldest first.
298
+ const withMtime = [];
299
+ for (const f of files) {
300
+ try {
301
+ withMtime.push({ file: f, mtime: statSync(join(sd, f)).mtimeMs });
302
+ }
303
+ catch {
304
+ /* skip */
305
+ }
306
+ }
307
+ withMtime.sort((a, b) => a.mtime - b.mtime);
308
+ for (const { file } of withMtime) {
309
+ const full = join(sd, file);
310
+ let raw = "";
311
+ try {
312
+ raw = readFileSync(full, "utf8");
313
+ }
314
+ catch {
315
+ continue;
316
+ }
317
+ for (const line of raw.split("\n")) {
318
+ if (!line)
319
+ continue;
320
+ try {
321
+ const obj = JSON.parse(line);
322
+ out.push(obj);
323
+ }
324
+ catch {
325
+ /* skip malformed */
326
+ }
327
+ }
328
+ }
329
+ }
330
+ return out;
331
+ }
332
+ /** Snapshot the cumulative capability-denials counter. */
333
+ denialsCount() {
334
+ return this.denials;
335
+ }
336
+ }
337
+ // ---------------------------------------------------------------------------
338
+ // Args-redaction
339
+ // ---------------------------------------------------------------------------
340
+ /** Structural redaction — keep keys + types + sizes, drop raw values for
341
+ * known large / sensitive fields. Bounded depth. The output is small,
342
+ * diff-friendly, and never includes a registered secret value (the
343
+ * recorder applies the secrets mask on top of this before writing). */
344
+ export function redactArgs(args, depth = 0) {
345
+ if (depth > 6)
346
+ return { __truncated: true };
347
+ if (args == null)
348
+ return {};
349
+ if (typeof args !== "object" || Array.isArray(args)) {
350
+ return { __scalar: typeof args, __value: args };
351
+ }
352
+ const out = {};
353
+ for (const [k, v] of Object.entries(args)) {
354
+ if (BIG_BLOB_FIELDS.has(k) && typeof v === "string") {
355
+ const byteLen = Buffer.byteLength(v, "utf8");
356
+ // Only redact when the payload is genuinely large — small strings
357
+ // (typed `<NAME>` aliases, single-line CSS values, short URLs) stay
358
+ // readable so the JSONL keeps its diff-friendly debuggability.
359
+ if (byteLen >= BIG_BLOB_REDACT_BYTES) {
360
+ out[k] = {
361
+ __redacted: true,
362
+ sha256: createHash("sha256").update(v, "utf8").digest("hex"),
363
+ byteLength: byteLen,
364
+ };
365
+ continue;
366
+ }
367
+ }
368
+ if (typeof v === "string") {
369
+ out[k] = v.length > 256 ? `${v.slice(0, 256)}…[+${v.length - 256}]` : v;
370
+ continue;
371
+ }
372
+ if (typeof v === "number" || typeof v === "boolean" || v === null) {
373
+ out[k] = v;
374
+ continue;
375
+ }
376
+ if (Array.isArray(v)) {
377
+ out[k] = { __array: true, length: v.length };
378
+ continue;
379
+ }
380
+ if (typeof v === "object") {
381
+ out[k] = redactArgs(v, depth + 1);
382
+ continue;
383
+ }
384
+ out[k] = { __type: typeof v };
385
+ }
386
+ return out;
387
+ }
388
+ // ---------------------------------------------------------------------------
389
+ // eval_js taxonomy classifier
390
+ // ---------------------------------------------------------------------------
391
+ /** Heuristic substring classifier over the first 80 chars of an `eval_js`
392
+ * expression. Drives the "what curated primitive is missing?" inference
393
+ * downstream (high-count non-custom buckets → propose a primitive). */
394
+ export function classifyEvalExpr(exprHead) {
395
+ const s = exprHead;
396
+ // dom-query — querySelector / getElementBy* / closest / matches
397
+ if (/document\.querySelector|querySelectorAll|getElementBy|\.closest\(|\.matches\(/.test(s)) {
398
+ return "dom-query";
399
+ }
400
+ // storage-access — localStorage / sessionStorage / indexedDB / caches / cookies
401
+ if (/localStorage|sessionStorage|indexedDB|\bcaches\b|document\.cookie|\bcookies\b/.test(s)) {
402
+ return "storage-access";
403
+ }
404
+ // computed-style + layout-box measures
405
+ if (/getComputedStyle|getBoundingClientRect|offsetWidth|offsetHeight|clientWidth|clientHeight|scrollWidth|scrollHeight/.test(s)) {
406
+ return "computed-style";
407
+ }
408
+ // callback-trigger — .click() / .focus() / .blur() / .dispatchEvent( / .submit()
409
+ if (/\.click\(\)|\.focus\(\)|\.blur\(\)|\.dispatchEvent\(|\.submit\(\)/.test(s)) {
410
+ return "callback-trigger";
411
+ }
412
+ // feature-detect — typeof window./navigator. / 'X' in window/navigator
413
+ if (/typeof\s+window\.|typeof\s+navigator\.|['"][^'"]+['"]\s+in\s+(window|navigator)|window\.[A-Za-z_]+\s*!==\s*undefined/.test(s)) {
414
+ return "feature-detect";
415
+ }
416
+ return "custom";
417
+ }
418
+ // ---------------------------------------------------------------------------
419
+ // Result classification — drives the resultMeta + failureKind fields.
420
+ // ---------------------------------------------------------------------------
421
+ export function failureKindOf(parsed) {
422
+ if (Object.prototype.hasOwnProperty.call(parsed, "requiredCapability"))
423
+ return "capability-denied";
424
+ const err = typeof parsed.error === "string" ? parsed.error : "";
425
+ if (/anti-wedge timeout/i.test(err))
426
+ return "timeout";
427
+ if (/not found|no element matches|ref not found|locator did not resolve/i.test(err))
428
+ return "target-not-found";
429
+ if (/must |invalid |unknown |expected /i.test(err))
430
+ return "bad-arg";
431
+ return "internal";
432
+ }
433
+ /** Build the `resultMeta` field for a recorded tool call. `firstJsonObj` is
434
+ * the parsed first text item (when applicable); `sizeBytes` is the
435
+ * JSON-string length of the entire content envelope; `warningsCount` is
436
+ * pulled from the parsed object's `warnings` field when it's an array. */
437
+ export function buildResultMeta(firstJsonObj, sizeBytes) {
438
+ if (!firstJsonObj)
439
+ return { ok: true, sizeBytes, warningsCount: 0 };
440
+ const ok = firstJsonObj.ok !== false;
441
+ const warningsCount = Array.isArray(firstJsonObj.warnings) ? firstJsonObj.warnings.length : 0;
442
+ if (ok)
443
+ return { ok: true, sizeBytes, warningsCount };
444
+ return {
445
+ ok: false,
446
+ sizeBytes,
447
+ warningsCount,
448
+ failureKind: failureKindOf(firstJsonObj),
449
+ };
450
+ }
451
+ // ---------------------------------------------------------------------------
452
+ // eval_js deep-capture helpers
453
+ // ---------------------------------------------------------------------------
454
+ const EVAL_HEAD_LEN = 80;
455
+ /** Build the eval_js-specific deep-capture envelope from a tool call's
456
+ * args + result. Returns undefined when the tool isn't eval_js. */
457
+ export function buildEvalJsCapture(toolName, args, firstJsonObj) {
458
+ if (toolName !== "eval_js" && toolName !== "poll_eval")
459
+ return undefined;
460
+ const expr = args && typeof args === "object"
461
+ ? (args.expr ?? args.expression)
462
+ : undefined;
463
+ if (typeof expr !== "string")
464
+ return undefined;
465
+ const exprHead = expr.slice(0, EVAL_HEAD_LEN);
466
+ const exprSha = createHash("sha256").update(expr, "utf8").digest("hex");
467
+ const taxonomy = classifyEvalExpr(exprHead);
468
+ let returnType = "unknown";
469
+ let returnSizeBytes = 0;
470
+ if (firstJsonObj) {
471
+ const v = firstJsonObj.value;
472
+ returnType = v === null ? "null" : Array.isArray(v) ? "array" : typeof v;
473
+ try {
474
+ returnSizeBytes = Buffer.byteLength(JSON.stringify(v ?? null), "utf8");
475
+ }
476
+ catch {
477
+ returnSizeBytes = 0;
478
+ }
479
+ }
480
+ return { exprSha, exprHead, returnType, returnSizeBytes, taxonomy };
481
+ }
482
+ // ---------------------------------------------------------------------------
483
+ // Report
484
+ // ---------------------------------------------------------------------------
485
+ /** Compute the percentile (p50, p95) over an unsorted number array. */
486
+ function percentile(values, pct) {
487
+ if (values.length === 0)
488
+ return 0;
489
+ const sorted = [...values].sort((a, b) => a - b);
490
+ const idx = Math.min(sorted.length - 1, Math.max(0, Math.floor((pct / 100) * (sorted.length - 1))));
491
+ return sorted[idx] ?? 0;
492
+ }
493
+ export function buildReportSummary(records, opts = {}) {
494
+ const sinceMs = opts.since ? Date.parse(opts.since) : undefined;
495
+ const perTool = new Map();
496
+ const evalByPattern = new Map();
497
+ const capabilityDenials = {};
498
+ const notesByCategory = {};
499
+ const evalTaxonomyCounts = new Map();
500
+ for (const r of records) {
501
+ if (sinceMs !== undefined && Date.parse(r.ts) < sinceMs)
502
+ continue;
503
+ if (opts.session && r.sessionId !== opts.session)
504
+ continue;
505
+ if (r.kind === "note") {
506
+ notesByCategory[r.category] = (notesByCategory[r.category] ?? 0) + 1;
507
+ continue;
508
+ }
509
+ // call record
510
+ const row = perTool.get(r.tool) ?? { count: 0, failureCount: 0, durations: [] };
511
+ row.count += 1;
512
+ if (!r.resultMeta.ok)
513
+ row.failureCount += 1;
514
+ row.durations.push(r.durationMs);
515
+ perTool.set(r.tool, row);
516
+ if (r.resultMeta.failureKind === "capability-denied") {
517
+ // Pull the capability name from the tool's static map if available.
518
+ // We don't import the map here (avoid a cycle); the report tool injects
519
+ // a hint via the dispatcher. For now bucket by tool name — the report
520
+ // tool overlay rewrites this to capability where possible.
521
+ capabilityDenials[r.tool] = (capabilityDenials[r.tool] ?? 0) + 1;
522
+ }
523
+ if (r.evalJs) {
524
+ const e = evalByPattern.get(r.evalJs.exprSha) ?? {
525
+ count: 0,
526
+ exprHead: r.evalJs.exprHead,
527
+ taxonomy: r.evalJs.taxonomy,
528
+ };
529
+ e.count += 1;
530
+ evalByPattern.set(r.evalJs.exprSha, e);
531
+ const t = evalTaxonomyCounts.get(r.evalJs.taxonomy) ?? {
532
+ count: 0,
533
+ sampleHead: r.evalJs.exprHead,
534
+ };
535
+ t.count += 1;
536
+ evalTaxonomyCounts.set(r.evalJs.taxonomy, t);
537
+ }
538
+ }
539
+ const perToolOut = {};
540
+ for (const [tool, row] of perTool) {
541
+ perToolOut[tool] = {
542
+ count: row.count,
543
+ failureCount: row.failureCount,
544
+ p50Duration: percentile(row.durations, 50),
545
+ p95Duration: percentile(row.durations, 95),
546
+ };
547
+ }
548
+ const topEvalJsPatterns = [];
549
+ for (const [exprSha, info] of evalByPattern) {
550
+ topEvalJsPatterns.push({
551
+ exprSha,
552
+ exprHead: info.exprHead,
553
+ count: info.count,
554
+ taxonomy: info.taxonomy,
555
+ });
556
+ }
557
+ topEvalJsPatterns.sort((a, b) => b.count - a.count);
558
+ topEvalJsPatterns.splice(10); // top 10
559
+ const missingPrimitiveHypotheses = [];
560
+ for (const [taxonomy, info] of evalTaxonomyCounts) {
561
+ // Heuristic: non-custom with count >= 3 OR custom with count >= 5.
562
+ const threshold = taxonomy === "custom" ? 5 : 3;
563
+ if (info.count >= threshold) {
564
+ missingPrimitiveHypotheses.push({ taxonomy, sampleHead: info.sampleHead, count: info.count });
565
+ }
566
+ }
567
+ missingPrimitiveHypotheses.sort((a, b) => b.count - a.count);
568
+ return {
569
+ perTool: perToolOut,
570
+ topEvalJsPatterns,
571
+ capabilityDenials,
572
+ notesByCategory,
573
+ missingPrimitiveHypotheses,
574
+ };
575
+ }
576
+ // ---------------------------------------------------------------------------
577
+ // Mask helper re-exported for the dispatch wrapper
578
+ // ---------------------------------------------------------------------------
579
+ export { maskedArgs };
@@ -0,0 +1,29 @@
1
+ import type { SecretRegistry } from "./secrets.js";
2
+ /** The single egress masking surface. Every client-facing output path masks
3
+ * through one of these. Constructed with the session's `SecretRegistry` when the
4
+ * `secrets` capability is on, or `null` when it is off — so the capability gate
5
+ * is an injection-time decision, not a per-sink inline check. URL-sanitisation
6
+ * applies regardless of the secrets registry (it is structural, not value-based). */
7
+ export declare class EgressSanitiser {
8
+ private readonly secrets;
9
+ constructor(secrets: SecretRegistry | null);
10
+ /** Whether a real secrets registry is attached (the `secrets` capability is on
11
+ * AND at least one secret is registered). Lets a sink skip an expensive
12
+ * side-channel sweep (e.g. the screenshot page-text probe) when there is
13
+ * nothing to find. */
14
+ get active(): boolean;
15
+ /** URL-sanitise then secrets-mask a single string, in the audited order. The
16
+ * composition `composeUrlAndSecretsInText` used to make every caller remember. */
17
+ maskText(text: string): string;
18
+ /** Deep-mask the string leaves of a structured payload (secrets only — the
19
+ * structured masking the verify / JSON families used `applyMaskDeep` for).
20
+ * No-op when the registry is null/empty. */
21
+ maskDeep<T>(value: T): T;
22
+ /** Best-effort detection: does `text` contain any registered real-value? The
23
+ * screenshot text-content sweep uses this to decide whether to warn. Returns
24
+ * no hit when no registry is attached. */
25
+ containsAnySecret(text: string): {
26
+ hit: boolean;
27
+ names: string[];
28
+ };
29
+ }
@@ -0,0 +1,52 @@
1
+ // RFC 0004 P3 / D4 (DRY) — the egress-masking chokepoint.
2
+ //
3
+ // Secrets-masking + URL-sanitisation was a *discipline*, not a *guarantee*: every
4
+ // output sink hand-called `composeUrlAndSecretsInText` / `applyMaskDeep` /
5
+ // `containsAnySecret`, each first deciding `caps.enabled.has("secrets")` inline,
6
+ // and a sink that forgot the call leaked. `EgressSanitiser` is the one object
7
+ // every sink masks through. The capability decision is made ONCE, at
8
+ // construction (a sink injected with a secrets-off sanitiser holds a null
9
+ // registry — URL-sanitisation still applies), so a sink no longer inlines the
10
+ // gate; it just calls `maskText` / `maskDeep`.
11
+ //
12
+ // This wraps the existing primitives verbatim (`SecretRegistry.applyMaskInText` /
13
+ // `applyMaskDeep` / `containsAnySecret` and `sanitizeUrlsInText`), in the audited
14
+ // order (URL pass first, then secrets) — so the masking behaviour is byte-identical
15
+ // to the prior hand-calls; only the *who-decides-and-when* moves.
16
+ import { sanitizeUrlsInText } from "./url-sanitizer.js";
17
+ /** The single egress masking surface. Every client-facing output path masks
18
+ * through one of these. Constructed with the session's `SecretRegistry` when the
19
+ * `secrets` capability is on, or `null` when it is off — so the capability gate
20
+ * is an injection-time decision, not a per-sink inline check. URL-sanitisation
21
+ * applies regardless of the secrets registry (it is structural, not value-based). */
22
+ export class EgressSanitiser {
23
+ secrets;
24
+ constructor(secrets) {
25
+ this.secrets = secrets;
26
+ }
27
+ /** Whether a real secrets registry is attached (the `secrets` capability is on
28
+ * AND at least one secret is registered). Lets a sink skip an expensive
29
+ * side-channel sweep (e.g. the screenshot page-text probe) when there is
30
+ * nothing to find. */
31
+ get active() {
32
+ return this.secrets !== null && this.secrets.size() > 0;
33
+ }
34
+ /** URL-sanitise then secrets-mask a single string, in the audited order. The
35
+ * composition `composeUrlAndSecretsInText` used to make every caller remember. */
36
+ maskText(text) {
37
+ const afterUrl = sanitizeUrlsInText(text);
38
+ return this.secrets ? this.secrets.applyMaskInText(afterUrl) : afterUrl;
39
+ }
40
+ /** Deep-mask the string leaves of a structured payload (secrets only — the
41
+ * structured masking the verify / JSON families used `applyMaskDeep` for).
42
+ * No-op when the registry is null/empty. */
43
+ maskDeep(value) {
44
+ return this.secrets ? this.secrets.applyMaskDeep(value) : value;
45
+ }
46
+ /** Best-effort detection: does `text` contain any registered real-value? The
47
+ * screenshot text-content sweep uses this to decide whether to warn. Returns
48
+ * no hit when no registry is attached. */
49
+ containsAnySecret(text) {
50
+ return this.secrets ? this.secrets.containsAnySecret(text) : { hit: false, names: [] };
51
+ }
52
+ }
@@ -0,0 +1,8 @@
1
+ export type FailureSource = "app" | "browxai" | "unknown";
2
+ export interface FailureClass {
3
+ source: FailureSource;
4
+ /** one-line, agent-facing: what this almost certainly is + what to do. */
5
+ hint: string;
6
+ }
7
+ /** Pure; exported for unit tests. */
8
+ export declare function classifyFailure(message: string): FailureClass;