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,369 @@
1
+ // perf_audit category analysers — the eight `AuditCategoryAnalyser` functions
2
+ // and the `ANALYSERS` registry that maps each category to its analyser. Split
3
+ // out of perf-audit.ts so the analysers (the bulk of the file) live apart from
4
+ // the report composer; re-exported through `./perf-audit.js`.
5
+ //
6
+ // RFC 0004 P4 / D6 — `ANALYSERS` is the SINGLE source of truth for the audit
7
+ // category set: an add-only registry (one entry per category). The
8
+ // `AuditCategory` union and the `ALL_AUDIT_CATEGORIES` array are DERIVED from
9
+ // its keys, so adding a category is ONE edit (a new `ANALYSERS` entry) and a
10
+ // typo'd category string is a compile error, not a silently-dropped key. This
11
+ // makes the perf-audit registry — the doctrine's own cited OCP exemplar
12
+ // (architecture-principles §2) — genuinely exemplary.
13
+ /** The audit category registry — the ONE place a category is declared. Each
14
+ * key is a category name; each value is its analyser. `as const satisfies`
15
+ * pins the keys as string literals (so `AuditCategory` derives a closed union)
16
+ * while still type-checking every value against the analyser signature.
17
+ *
18
+ * Order is meaningful — issues are surfaced in this order when severity ties. */
19
+ export const ANALYSERS = {
20
+ "render-blocking": analyseRenderBlocking,
21
+ "unused-code": analyseUnusedCode,
22
+ "oversize-images": analyseOversizeImages,
23
+ "layout-thrashing": analyseLayoutThrashing,
24
+ "long-tasks": analyseLongTasks,
25
+ "leak-suspects": analyseLeakSuspects,
26
+ "cache-opportunities": analyseCacheOpportunities,
27
+ "font-loading": analyseFontLoading,
28
+ };
29
+ /** Every audit category, in declaration order — DERIVED from `ANALYSERS`. The
30
+ * `Object.keys` cast is sound because the keys ARE the `AuditCategory` union. */
31
+ export const ALL_AUDIT_CATEGORIES = Object.keys(ANALYSERS);
32
+ // ---------------------------------------------------------------------------
33
+ // Category analysers
34
+ // ---------------------------------------------------------------------------
35
+ /** render-blocking — `ParseHTML`/`Layout` events with VeryHigh-priority
36
+ * resources blocking first paint. Heuristic: any `ResourceSendRequest`
37
+ * with `args.data.renderBlocking == "blocking"` or
38
+ * `args.data.priority == "VeryHigh"` BEFORE the first `firstPaint` event. */
39
+ /** Detect whether a `ResourceSendRequest` event (before first paint) is a render
40
+ * blocker, returning its `{url, priority}` or null. */
41
+ function renderBlocker(e, firstPaintTs) {
42
+ if (e.name !== "ResourceSendRequest")
43
+ return null;
44
+ const ts = typeof e.ts === "number" ? e.ts : 0;
45
+ if (ts >= firstPaintTs)
46
+ return null;
47
+ const data = ((e.args ?? {}).data ?? {});
48
+ const url = typeof data.url === "string" ? data.url : "";
49
+ const blocking = typeof data.renderBlocking === "string" ? data.renderBlocking : "";
50
+ const priority = typeof data.priority === "string" ? data.priority : "";
51
+ if (!url)
52
+ return null;
53
+ const isBlocker = blocking === "blocking" || blocking === "in_body_parser_blocking" || priority === "VeryHigh";
54
+ return isBlocker ? { url, priority: priority || blocking } : null;
55
+ }
56
+ export function analyseRenderBlocking(ctx) {
57
+ let firstPaintTs = Infinity;
58
+ for (const e of ctx.trace) {
59
+ if (e.name === "firstPaint" && typeof e.ts === "number") {
60
+ firstPaintTs = e.ts;
61
+ break;
62
+ }
63
+ }
64
+ const blockers = [];
65
+ for (const e of ctx.trace) {
66
+ const b = renderBlocker(e, firstPaintTs);
67
+ if (b)
68
+ blockers.push(b);
69
+ }
70
+ const issues = blockers.map((b) => ({
71
+ category: "render-blocking",
72
+ severity: b.priority === "VeryHigh" || b.priority === "blocking"
73
+ ? "high"
74
+ : "medium",
75
+ title: `Render-blocking resource: ${b.url}`,
76
+ details: { url: b.url, priority: b.priority },
77
+ }));
78
+ const remediations = blockers.map((b) => ({
79
+ category: "render-blocking",
80
+ action: b.url.endsWith(".css")
81
+ ? "Inline critical CSS in <head>; defer the rest with rel=preload + onload."
82
+ : "Add `defer` or `async` to the script tag, or move below the fold.",
83
+ target: b.url,
84
+ }));
85
+ return { issues, remediations };
86
+ }
87
+ /** unused-code — scripts + CSS files with `usagePercent < 30`. Severity tied
88
+ * to absolute waste (bytes), not percent, because a 90%-dead 2KB file
89
+ * doesn't matter. */
90
+ export function analyseUnusedCode(ctx) {
91
+ const issues = [];
92
+ const remediations = [];
93
+ for (const js of ctx.jsCoverage ?? []) {
94
+ if (js.usagePercent >= 30)
95
+ continue;
96
+ const wasted = js.totalBytes - js.usedBytes;
97
+ if (wasted < 5000)
98
+ continue;
99
+ issues.push({
100
+ category: "unused-code",
101
+ severity: wasted > 100_000 ? "high" : wasted > 20_000 ? "medium" : "low",
102
+ title: `Unused JS in ${js.url}: ${Math.round(wasted / 1024)}KB dead (${js.usagePercent}% used)`,
103
+ details: {
104
+ url: js.url,
105
+ totalBytes: js.totalBytes,
106
+ usedBytes: js.usedBytes,
107
+ usagePercent: js.usagePercent,
108
+ },
109
+ });
110
+ remediations.push({
111
+ category: "unused-code",
112
+ action: "Tree-shake / code-split this bundle; dead code is the largest opportunity.",
113
+ target: js.url,
114
+ });
115
+ }
116
+ for (const css of ctx.cssCoverage ?? []) {
117
+ if (css.usagePercent >= 30)
118
+ continue;
119
+ const wasted = css.totalBytes - css.usedBytes;
120
+ if (wasted < 5000)
121
+ continue;
122
+ issues.push({
123
+ category: "unused-code",
124
+ severity: wasted > 50_000 ? "high" : wasted > 10_000 ? "medium" : "low",
125
+ title: `Unused CSS in ${css.url}: ${Math.round(wasted / 1024)}KB dead (${css.usagePercent}% used)`,
126
+ details: {
127
+ url: css.url,
128
+ totalBytes: css.totalBytes,
129
+ usedBytes: css.usedBytes,
130
+ usagePercent: css.usagePercent,
131
+ },
132
+ });
133
+ remediations.push({
134
+ category: "unused-code",
135
+ action: "PurgeCSS / Tailwind-style on-demand generation; ship only selectors the page uses.",
136
+ target: css.url,
137
+ });
138
+ }
139
+ return { issues, remediations };
140
+ }
141
+ const IMAGE_EXTENSIONS = new Set(["png", "jpg", "jpeg", "gif", "webp", "avif", "svg"]);
142
+ /** Record one oversize image (deduped) into the issue/remediation accumulators. */
143
+ function pushOversizeImage(acc, url, bytes, action, extraDetails = {}) {
144
+ if (acc.seen.has(url))
145
+ return;
146
+ acc.seen.add(url);
147
+ acc.issues.push({
148
+ category: "oversize-images",
149
+ severity: bytes > 2_000_000 ? "high" : "medium",
150
+ title: `Oversize image: ${url} (${Math.round(bytes / 1024)}KB)`,
151
+ details: { url, bytes, ...extraDetails },
152
+ });
153
+ acc.remediations.push({ category: "oversize-images", action, target: url });
154
+ }
155
+ /** oversize-images — images > 500KB. */
156
+ export function analyseOversizeImages(ctx) {
157
+ const acc = {
158
+ issues: [],
159
+ remediations: [],
160
+ seen: new Set(),
161
+ };
162
+ // Prefer network responses metadata; fall back to ResourceFinish events.
163
+ for (const r of ctx.responses ?? []) {
164
+ if (!r.mimeType?.startsWith("image/"))
165
+ continue;
166
+ const bytes = r.encodedDataLength ?? 0;
167
+ if (bytes < 500_000)
168
+ continue;
169
+ pushOversizeImage(acc, r.url, bytes, "Compress + resize to displayed dimensions; switch to AVIF/WebP; add srcset for responsive sizing.", { mimeType: r.mimeType });
170
+ }
171
+ for (const e of ctx.trace) {
172
+ const img = oversizeImageFromTrace(e);
173
+ if (img) {
174
+ pushOversizeImage(acc, img.url, img.bytes, "Compress + resize to displayed dimensions; switch to AVIF/WebP.");
175
+ }
176
+ }
177
+ return { issues: acc.issues, remediations: acc.remediations };
178
+ }
179
+ /** Pull an oversize-image `{url, bytes}` out of a `ResourceFinish` trace event
180
+ * (image extension + ≥500KB), or null. */
181
+ function oversizeImageFromTrace(e) {
182
+ if (e.name !== "ResourceFinish")
183
+ return null;
184
+ const data = ((e.args ?? {}).data ?? {});
185
+ const url = typeof data.url === "string" ? data.url : "";
186
+ const bytes = typeof data.encodedDataLength === "number" ? data.encodedDataLength : 0;
187
+ if (!url || bytes < 500_000)
188
+ return null;
189
+ const ext = url.split("?")[0]?.split(".").pop()?.toLowerCase() ?? "";
190
+ return IMAGE_EXTENSIONS.has(ext) ? { url, bytes } : null;
191
+ }
192
+ /** layout-thrashing — > 5 forced sync layouts. */
193
+ export function analyseLayoutThrashing(ctx) {
194
+ let forcedCount = 0;
195
+ let shiftCount = 0;
196
+ for (const e of ctx.trace) {
197
+ if (e.name === "LayoutShift")
198
+ shiftCount++;
199
+ if (e.name === "ForcedSyncLayout")
200
+ forcedCount++;
201
+ if (e.name === "Layout" && hasForcedFlag(e))
202
+ forcedCount++;
203
+ }
204
+ const issues = [];
205
+ const remediations = [];
206
+ if (forcedCount > 5) {
207
+ issues.push({
208
+ category: "layout-thrashing",
209
+ severity: forcedCount > 50 ? "high" : forcedCount > 20 ? "medium" : "low",
210
+ title: `${forcedCount} forced synchronous layouts in window`,
211
+ details: { forcedCount, layoutShiftCount: shiftCount },
212
+ });
213
+ remediations.push({
214
+ category: "layout-thrashing",
215
+ action: "Batch DOM reads + writes; avoid alternating offsetWidth/offsetHeight measurements with style writes.",
216
+ });
217
+ }
218
+ return { issues, remediations };
219
+ }
220
+ function hasForcedFlag(e) {
221
+ const args = e.args;
222
+ if (!args)
223
+ return false;
224
+ const data = args.data ?? args.beginData ?? {};
225
+ return Array.isArray(data.stackTrace) && data.stackTrace.length > 0;
226
+ }
227
+ /** long-tasks — `RunTask` events > 50ms. */
228
+ export function analyseLongTasks(ctx) {
229
+ const tasks = [];
230
+ for (const e of ctx.trace) {
231
+ if (e.name !== "RunTask" && e.name !== "LongTask")
232
+ continue;
233
+ const dur = typeof e.dur === "number" ? e.dur / 1000 : 0;
234
+ if (dur >= 50)
235
+ tasks.push({ durationMs: dur });
236
+ }
237
+ tasks.sort((a, b) => b.durationMs - a.durationMs);
238
+ const issues = tasks.map((t) => ({
239
+ category: "long-tasks",
240
+ severity: t.durationMs > 200
241
+ ? "high"
242
+ : t.durationMs > 100
243
+ ? "medium"
244
+ : "low",
245
+ title: `Long task: ${Math.round(t.durationMs)}ms blocking main thread`,
246
+ details: { durationMs: t.durationMs },
247
+ }));
248
+ const remediations = tasks.length > 0
249
+ ? [
250
+ {
251
+ category: "long-tasks",
252
+ action: "Yield to the event loop with scheduler.postTask() or requestIdleCallback; move heavy work to a Web Worker.",
253
+ },
254
+ ]
255
+ : [];
256
+ return { issues, remediations };
257
+ }
258
+ /** leak-suspects — retainer-growth rows with deltaPercent > 10. */
259
+ export function analyseLeakSuspects(ctx) {
260
+ const issues = [];
261
+ const remediations = [];
262
+ if (!ctx.memoryDiff)
263
+ return { issues, remediations };
264
+ for (const row of ctx.memoryDiff.retainerGrowth) {
265
+ const pct = row.deltaPercent === "+inf" ? Infinity : row.deltaPercent;
266
+ if (pct <= 10)
267
+ continue;
268
+ if (row.deltaBytes <= 0)
269
+ continue;
270
+ issues.push({
271
+ category: "leak-suspects",
272
+ severity: row.deltaBytes > 1_000_000 ? "high" : row.deltaBytes > 100_000 ? "medium" : "low",
273
+ title: `Retainer growth: ${row.node} +${Math.round(row.deltaBytes / 1024)}KB (${row.deltaPercent}%)`,
274
+ details: {
275
+ node: row.node,
276
+ type: row.type,
277
+ deltaBytes: row.deltaBytes,
278
+ deltaPercent: row.deltaPercent,
279
+ },
280
+ });
281
+ remediations.push({
282
+ category: "leak-suspects",
283
+ action: "Check listeners + cached references on this type; pair with heap_retainers({snapshotPath, query:{name}}) for the retention path.",
284
+ target: row.node,
285
+ });
286
+ }
287
+ return { issues, remediations };
288
+ }
289
+ /** cache-opportunities — static assets missing `Cache-Control` header. */
290
+ export function analyseCacheOpportunities(ctx) {
291
+ const issues = [];
292
+ const remediations = [];
293
+ const seen = new Set();
294
+ for (const r of ctx.responses ?? []) {
295
+ if (r.status !== 200)
296
+ continue;
297
+ const ext = r.url.split("?")[0]?.split(".").pop()?.toLowerCase() ?? "";
298
+ const isStatic = [
299
+ "js",
300
+ "css",
301
+ "png",
302
+ "jpg",
303
+ "jpeg",
304
+ "gif",
305
+ "webp",
306
+ "avif",
307
+ "svg",
308
+ "woff",
309
+ "woff2",
310
+ "ttf",
311
+ ].includes(ext);
312
+ if (!isStatic)
313
+ continue;
314
+ if (r.cacheControl && /max-age=\d+/i.test(r.cacheControl))
315
+ continue;
316
+ if (seen.has(r.url))
317
+ continue;
318
+ seen.add(r.url);
319
+ issues.push({
320
+ category: "cache-opportunities",
321
+ severity: "medium",
322
+ title: `Missing/short Cache-Control on static asset: ${r.url}`,
323
+ details: { url: r.url, cacheControl: r.cacheControl ?? null },
324
+ });
325
+ remediations.push({
326
+ category: "cache-opportunities",
327
+ action: "Add Cache-Control: public, max-age=31536000, immutable on content-hashed static assets.",
328
+ target: r.url,
329
+ });
330
+ }
331
+ return { issues, remediations };
332
+ }
333
+ /** font-loading — fonts loaded > 200ms after document start. */
334
+ export function analyseFontLoading(ctx) {
335
+ let docStartMs = 0;
336
+ for (const e of ctx.trace) {
337
+ if (e.name === "navigationStart" && typeof e.ts === "number") {
338
+ docStartMs = e.ts / 1000;
339
+ break;
340
+ }
341
+ }
342
+ const fontLoads = [];
343
+ for (const e of ctx.trace) {
344
+ if (e.name !== "ResourceFinish")
345
+ continue;
346
+ const args = e.args ?? {};
347
+ const data = (args.data ?? {});
348
+ const url = typeof data.url === "string" ? data.url : "";
349
+ const ext = url.split("?")[0]?.split(".").pop()?.toLowerCase() ?? "";
350
+ if (!["woff", "woff2", "ttf", "otf"].includes(ext))
351
+ continue;
352
+ const ts = typeof e.ts === "number" ? e.ts / 1000 : 0;
353
+ const offset = ts - docStartMs;
354
+ if (offset > 200)
355
+ fontLoads.push({ url, offsetMs: offset });
356
+ }
357
+ const issues = fontLoads.map((f) => ({
358
+ category: "font-loading",
359
+ severity: f.offsetMs > 1000 ? "high" : "medium",
360
+ title: `Font loaded ${Math.round(f.offsetMs)}ms after document start: ${f.url}`,
361
+ details: { url: f.url, offsetMs: f.offsetMs },
362
+ }));
363
+ const remediations = fontLoads.map((f) => ({
364
+ category: "font-loading",
365
+ action: "<link rel=preload as=font crossorigin> in <head>, or self-host with font-display: swap.",
366
+ target: f.url,
367
+ }));
368
+ return { issues, remediations };
369
+ }
@@ -0,0 +1,20 @@
1
+ import type { CDPSession } from "playwright-core";
2
+ import { type AuditCategory, type AuditReport } from "./perf-audit.js";
3
+ export interface RunPerfAuditOptions {
4
+ categories?: string[];
5
+ durationMs?: number;
6
+ format?: "summary" | "full";
7
+ }
8
+ export interface RunPerfAuditResult {
9
+ report: AuditReport;
10
+ evidence: {
11
+ tracePath: string;
12
+ coveragePath?: string;
13
+ memoryPath?: string;
14
+ };
15
+ durationMs: number;
16
+ categoriesRun: AuditCategory[];
17
+ }
18
+ /** Default trace filename under `<workspace>/perf/<sessionId>-audit-<ts>.json`. */
19
+ export declare function defaultAuditTracePath(workspaceRoot: string, sessionId: string): string;
20
+ export declare function runPerfAudit(cdp: CDPSession, workspaceRoot: string, sessionId: string, opts?: RunPerfAuditOptions): Promise<RunPerfAuditResult>;
@@ -0,0 +1,195 @@
1
+ // perf_audit runner — orchestrates trace collection + coverage capture +
2
+ // network-response gathering for the duration of the audit window, then
3
+ // hands the assembled context to `composeReport`.
4
+ //
5
+ // Kept separate from `perf-audit.ts` (analysers) so the analysers stay
6
+ // pure-function + unit-testable, and the runner can be replaced /
7
+ // stubbed without dragging the registry along.
8
+ import { writeFileSync, mkdirSync, existsSync } from "node:fs";
9
+ import { join, dirname, resolve, sep } from "node:path";
10
+ import { CoverageTrackerState } from "./coverage.js";
11
+ import { composeReport, resolveCategories, } from "./perf-audit.js";
12
+ const DEFAULT_DURATION_MS = 5_000;
13
+ const MAX_DURATION_MS = 30_000;
14
+ /** Same broad category set used by the audit's standalone trace window — we
15
+ * want everything render/loading/longtask-related so the analysers have
16
+ * enough to look at. */
17
+ const AUDIT_TRACE_CATEGORIES = [
18
+ "devtools.timeline",
19
+ "loading",
20
+ "blink.user_timing",
21
+ "disabled-by-default-devtools.timeline",
22
+ "disabled-by-default-devtools.timeline.frame",
23
+ "latencyInfo",
24
+ ];
25
+ function clampDuration(d) {
26
+ if (typeof d !== "number" || !Number.isFinite(d) || d <= 0)
27
+ return DEFAULT_DURATION_MS;
28
+ if (d > MAX_DURATION_MS)
29
+ return MAX_DURATION_MS;
30
+ return Math.floor(d);
31
+ }
32
+ function resolveAuditPath(workspaceRoot, p, tool) {
33
+ const resolved = resolve(workspaceRoot, p);
34
+ if (resolved !== workspaceRoot && !resolved.startsWith(workspaceRoot + sep)) {
35
+ throw new Error(`${tool}: \`path\` must resolve inside $BROWX_WORKSPACE — got "${p}".`);
36
+ }
37
+ return resolved;
38
+ }
39
+ /** Default trace filename under `<workspace>/perf/<sessionId>-audit-<ts>.json`. */
40
+ export function defaultAuditTracePath(workspaceRoot, sessionId) {
41
+ const safe = (sessionId || "default").replace(/[^A-Za-z0-9._-]/g, "_");
42
+ const ts = new Date().toISOString().replace(/[:.]/g, "-");
43
+ return join(workspaceRoot, "perf", `${safe}-audit-${ts}.json`);
44
+ }
45
+ function defaultCoveragePath(workspaceRoot, sessionId) {
46
+ const safe = (sessionId || "default").replace(/[^A-Za-z0-9._-]/g, "_");
47
+ const ts = new Date().toISOString().replace(/[:.]/g, "-");
48
+ return join(workspaceRoot, "perf", `${safe}-coverage-${ts}.json`);
49
+ }
50
+ /** Build the CDP network-response listeners, accumulating `responses[]` from
51
+ * `responseReceived` (+ a best-effort `loadingFinished` size patch). Returns the
52
+ * listeners + the shared accumulator. */
53
+ function makeNetworkListeners(responses) {
54
+ const responseHeaders = new Map();
55
+ return {
56
+ onResponseReceived: (raw) => {
57
+ const e = raw;
58
+ const r = e?.response;
59
+ if (!r || typeof r.url !== "string")
60
+ return;
61
+ const headers = r.headers ?? {};
62
+ responseHeaders.set(e.requestId, headers);
63
+ responses.push({
64
+ url: r.url,
65
+ status: r.status ?? 0,
66
+ mimeType: r.mimeType,
67
+ encodedDataLength: r.encodedDataLength,
68
+ cacheControl: headers["cache-control"] ?? headers["Cache-Control"],
69
+ });
70
+ },
71
+ onLoadingFinished: (raw) => {
72
+ const e = raw;
73
+ if (typeof e.encodedDataLength !== "number" || !responseHeaders.has(e.requestId))
74
+ return;
75
+ for (let i = responses.length - 1; i >= 0; i--) {
76
+ if (responses[i].encodedDataLength == null || responses[i].encodedDataLength === 0) {
77
+ responses[i].encodedDataLength = e.encodedDataLength;
78
+ break;
79
+ }
80
+ }
81
+ },
82
+ };
83
+ }
84
+ /** Run the trace + coverage + network collection window, detaching all listeners
85
+ * in `finally`. */
86
+ async function collectAuditData(cdp, durationMs) {
87
+ const traceEvents = [];
88
+ let traceComplete = null;
89
+ const onData = (e) => {
90
+ if (Array.isArray(e?.value))
91
+ for (const ev of e.value)
92
+ traceEvents.push(ev);
93
+ };
94
+ const onTraceComplete = () => {
95
+ if (traceComplete)
96
+ traceComplete();
97
+ };
98
+ const responses = [];
99
+ const net = makeNetworkListeners(responses);
100
+ const coverage = new CoverageTrackerState();
101
+ cdp.on("Tracing.dataCollected", onData);
102
+ cdp.on("Tracing.tracingComplete", onTraceComplete);
103
+ cdp.on("Network.responseReceived", net.onResponseReceived);
104
+ cdp.on("Network.loadingFinished", net.onLoadingFinished);
105
+ const data = { traceEvents, responses };
106
+ try {
107
+ await cdp.send("Network.enable").catch(() => undefined);
108
+ await cdp.send("Tracing.start", {
109
+ transferMode: "ReportEvents",
110
+ traceConfig: { recordMode: "recordContinuously", includedCategories: AUDIT_TRACE_CATEGORIES },
111
+ });
112
+ await coverage.start(cdp).catch(() => undefined);
113
+ await new Promise((res) => setTimeout(res, durationMs));
114
+ const traceCompletePromise = new Promise((res) => {
115
+ traceComplete = res;
116
+ });
117
+ await cdp.send("Tracing.end").catch(() => undefined);
118
+ await Promise.race([traceCompletePromise, new Promise((res) => setTimeout(res, 30_000))]);
119
+ const covResult = await coverage.stop(cdp).catch(() => undefined);
120
+ if (covResult && !covResult.notRunning) {
121
+ data.jsCoverage = covResult.jsCoverage;
122
+ data.cssCoverage = covResult.cssCoverage;
123
+ }
124
+ }
125
+ finally {
126
+ for (const [event, h] of [
127
+ ["Tracing.dataCollected", onData],
128
+ ["Tracing.tracingComplete", onTraceComplete],
129
+ ["Network.responseReceived", net.onResponseReceived],
130
+ ["Network.loadingFinished", net.onLoadingFinished],
131
+ ]) {
132
+ try {
133
+ cdp.off(event, h);
134
+ }
135
+ catch {
136
+ /* best-effort */
137
+ }
138
+ }
139
+ }
140
+ return data;
141
+ }
142
+ /** Write the trace + coverage evidence files (workspace-rooted) and return their
143
+ * resolved paths. */
144
+ function writeAuditEvidence(workspaceRoot, sessionId, durationMs, data) {
145
+ const resolvedTrace = resolveAuditPath(workspaceRoot, defaultAuditTracePath(workspaceRoot, sessionId), "perf_audit");
146
+ const traceParent = dirname(resolvedTrace);
147
+ if (traceParent && !existsSync(traceParent))
148
+ mkdirSync(traceParent, { recursive: true });
149
+ // ws.root-rooted path — resolveAuditPath guards the escape.
150
+ writeFileSync(resolvedTrace, JSON.stringify({
151
+ traceEvents: data.traceEvents,
152
+ metadata: {
153
+ source: "browxai",
154
+ sessionId,
155
+ categories: AUDIT_TRACE_CATEGORIES,
156
+ durationMs,
157
+ eventCount: data.traceEvents.length,
158
+ capturedAt: new Date().toISOString(),
159
+ kind: "perf-audit",
160
+ },
161
+ }), "utf8");
162
+ if (!data.jsCoverage || !data.cssCoverage)
163
+ return { tracePath: resolvedTrace };
164
+ const resolvedCov = resolveAuditPath(workspaceRoot, defaultCoveragePath(workspaceRoot, sessionId), "perf_audit");
165
+ writeFileSync(resolvedCov, JSON.stringify({
166
+ jsCoverage: data.jsCoverage,
167
+ cssCoverage: data.cssCoverage,
168
+ durationMs,
169
+ capturedAt: new Date().toISOString(),
170
+ }), "utf8");
171
+ return { tracePath: resolvedTrace, coveragePath: resolvedCov };
172
+ }
173
+ export async function runPerfAudit(cdp, workspaceRoot, sessionId, opts = {}) {
174
+ const durationMs = clampDuration(opts.durationMs);
175
+ const format = opts.format === "full" ? "full" : "summary";
176
+ const categoriesRun = resolveCategories(opts.categories);
177
+ const data = await collectAuditData(cdp, durationMs);
178
+ const evidencePaths = writeAuditEvidence(workspaceRoot, sessionId, durationMs, data);
179
+ const ctx = {
180
+ trace: data.traceEvents,
181
+ jsCoverage: data.jsCoverage,
182
+ cssCoverage: data.cssCoverage,
183
+ responses: data.responses,
184
+ };
185
+ const report = composeReport(ctx, categoriesRun, format);
186
+ return {
187
+ report,
188
+ evidence: {
189
+ tracePath: evidencePaths.tracePath,
190
+ ...(evidencePaths.coveragePath ? { coveragePath: evidencePaths.coveragePath } : {}),
191
+ },
192
+ durationMs,
193
+ categoriesRun,
194
+ };
195
+ }
@@ -0,0 +1,41 @@
1
+ import type { TraceEvent } from "./perf.js";
2
+ import type { JsCoverageEntry, CssCoverageEntry } from "./coverage.js";
3
+ import type { MemoryDiffResult } from "./memory-diff.js";
4
+ import type { AuditCategory } from "./perf-audit-analysers.js";
5
+ export type { AuditCategory } from "./perf-audit-analysers.js";
6
+ export type IssueSeverity = "high" | "medium" | "low";
7
+ export interface AuditIssue {
8
+ category: AuditCategory;
9
+ severity: IssueSeverity;
10
+ title: string;
11
+ /** Free-form additional context, structured per category. */
12
+ details?: Record<string, unknown>;
13
+ }
14
+ export interface AuditRemediation {
15
+ category: AuditCategory;
16
+ /** Imperative one-liner: "Defer non-critical CSS in <head>". */
17
+ action: string;
18
+ /** Optional URL pointing at the offending resource the remediation applies
19
+ * to (when the analyser identified a specific target). */
20
+ target?: string;
21
+ }
22
+ export interface CategoryResult {
23
+ issues: AuditIssue[];
24
+ remediations: AuditRemediation[];
25
+ }
26
+ export interface AuditContext {
27
+ trace: TraceEvent[];
28
+ jsCoverage?: JsCoverageEntry[];
29
+ cssCoverage?: CssCoverageEntry[];
30
+ memoryDiff?: MemoryDiffResult;
31
+ /** Network response metadata, when available, for cache-opportunities
32
+ * + oversize-images + font-loading categories. */
33
+ responses?: Array<{
34
+ url: string;
35
+ status: number;
36
+ mimeType?: string;
37
+ encodedDataLength?: number;
38
+ cacheControl?: string;
39
+ }>;
40
+ }
41
+ export type AuditCategoryAnalyser = (ctx: AuditContext) => CategoryResult;
@@ -0,0 +1,5 @@
1
+ // perf_audit type vocabulary — the audit category union, issue/remediation/
2
+ // result shapes, and the analyser context. Split out of perf-audit.ts so the
3
+ // analysers and the report composer share one type home without either file
4
+ // exceeding the size budget. Re-exported through `./perf-audit.js`.
5
+ export {};
@@ -0,0 +1,37 @@
1
+ import { type IssueSeverity, type AuditContext, type CategoryResult } from "./perf-audit-types.js";
2
+ import { type AuditCategory } from "./perf-audit-analysers.js";
3
+ export type { IssueSeverity, AuditIssue, AuditRemediation, CategoryResult, AuditContext, AuditCategoryAnalyser, } from "./perf-audit-types.js";
4
+ export { ANALYSERS, ALL_AUDIT_CATEGORIES, type AuditCategory, analyseRenderBlocking, analyseUnusedCode, analyseOversizeImages, analyseLayoutThrashing, analyseLongTasks, analyseLeakSuspects, analyseCacheOpportunities, analyseFontLoading, } from "./perf-audit-analysers.js";
5
+ export interface AuditReport {
6
+ summary: {
7
+ score: number;
8
+ topIssues: Array<{
9
+ category: AuditCategory;
10
+ severity: IssueSeverity;
11
+ title: string;
12
+ }>;
13
+ };
14
+ byCategory: Record<string, CategoryResult>;
15
+ warnings: string[];
16
+ }
17
+ export declare const SUMMARY_TOKEN_BUDGET = 2000;
18
+ export declare const SUMMARY_BUDGET_CEILING_FACTOR = 2.5;
19
+ export declare const SUMMARY_TOKEN_HARD_CEILING: number;
20
+ /** Compose an audit report from already-collected context. The category set
21
+ * is the categories the caller asked for (default = all). `format`
22
+ * controls whether each category's `issues`/`remediations` are capped at
23
+ * 3 (summary mode) or unbounded (full mode). The summary itself (the
24
+ * short `summary.topIssues` list + score) always exists; in summary mode
25
+ * the per-category bodies are also capped.
26
+ *
27
+ * Token-budget enforcement: when `format:"summary"`, the function checks
28
+ * estimated token count and drops lowest-severity issues + remediations
29
+ * until under 2000. If even after total trimming the body exceeds the
30
+ * cap, a `warnings[]` entry surfaces it. */
31
+ export declare function composeReport(ctx: AuditContext, categories: AuditCategory[], format: "summary" | "full"): AuditReport;
32
+ /** Drop lowest-severity issues across all categories until estimated tokens
33
+ * are within the summary budget. Adds a warnings[] entry if the cap binds. */
34
+ export declare function enforceSummaryBudget(report: AuditReport): AuditReport;
35
+ /** Resolve the requested category set — empty/undefined → all. Unknown
36
+ * category names are dropped silently. */
37
+ export declare function resolveCategories(requested?: string[]): AuditCategory[];