tabwright 1.0.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 (599) hide show
  1. package/LICENSE +21 -0
  2. package/bin.js +4 -0
  3. package/dist/a11y-client.js +204 -0
  4. package/dist/agent-skills/tabwright/SKILL.md +119 -0
  5. package/dist/aria-snapshot.d.ts +262 -0
  6. package/dist/aria-snapshot.d.ts.map +1 -0
  7. package/dist/aria-snapshot.js +1256 -0
  8. package/dist/aria-snapshot.js.map +1 -0
  9. package/dist/aria-snapshot.test.d.ts +2 -0
  10. package/dist/aria-snapshot.test.d.ts.map +1 -0
  11. package/dist/aria-snapshot.test.js +270 -0
  12. package/dist/aria-snapshot.test.js.map +1 -0
  13. package/dist/aria-snapshot.unit.test.d.ts +2 -0
  14. package/dist/aria-snapshot.unit.test.d.ts.map +1 -0
  15. package/dist/aria-snapshot.unit.test.js +542 -0
  16. package/dist/aria-snapshot.unit.test.js.map +1 -0
  17. package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.d.ts +5 -0
  18. package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.d.ts.map +1 -0
  19. package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.js +5 -0
  20. package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.js.map +1 -0
  21. package/dist/bippy.js +894 -0
  22. package/dist/browser-config.d.ts +13 -0
  23. package/dist/browser-config.d.ts.map +1 -0
  24. package/dist/browser-config.js +126 -0
  25. package/dist/browser-config.js.map +1 -0
  26. package/dist/browser-install.d.ts +16 -0
  27. package/dist/browser-install.d.ts.map +1 -0
  28. package/dist/browser-install.js +238 -0
  29. package/dist/browser-install.js.map +1 -0
  30. package/dist/browser-launch.d.ts +17 -0
  31. package/dist/browser-launch.d.ts.map +1 -0
  32. package/dist/browser-launch.js +44 -0
  33. package/dist/browser-launch.js.map +1 -0
  34. package/dist/builtin-capabilities.d.ts +28 -0
  35. package/dist/builtin-capabilities.d.ts.map +1 -0
  36. package/dist/builtin-capabilities.js +2673 -0
  37. package/dist/builtin-capabilities.js.map +1 -0
  38. package/dist/capability-agent-skill.d.ts +60 -0
  39. package/dist/capability-agent-skill.d.ts.map +1 -0
  40. package/dist/capability-agent-skill.js +225 -0
  41. package/dist/capability-agent-skill.js.map +1 -0
  42. package/dist/capability-auth-state.d.ts +34 -0
  43. package/dist/capability-auth-state.d.ts.map +1 -0
  44. package/dist/capability-auth-state.js +157 -0
  45. package/dist/capability-auth-state.js.map +1 -0
  46. package/dist/capability-auth.d.ts +36 -0
  47. package/dist/capability-auth.d.ts.map +1 -0
  48. package/dist/capability-auth.js +198 -0
  49. package/dist/capability-auth.js.map +1 -0
  50. package/dist/capability-cli-confirmation.test.d.ts +2 -0
  51. package/dist/capability-cli-confirmation.test.d.ts.map +1 -0
  52. package/dist/capability-cli-confirmation.test.js +79 -0
  53. package/dist/capability-cli-confirmation.test.js.map +1 -0
  54. package/dist/capability-options.d.ts +20 -0
  55. package/dist/capability-options.d.ts.map +1 -0
  56. package/dist/capability-options.js +31 -0
  57. package/dist/capability-options.js.map +1 -0
  58. package/dist/capability-options.test.d.ts +2 -0
  59. package/dist/capability-options.test.d.ts.map +1 -0
  60. package/dist/capability-options.test.js +81 -0
  61. package/dist/capability-options.test.js.map +1 -0
  62. package/dist/capability-package.d.ts +27 -0
  63. package/dist/capability-package.d.ts.map +1 -0
  64. package/dist/capability-package.js +444 -0
  65. package/dist/capability-package.js.map +1 -0
  66. package/dist/capability-package.test.d.ts +2 -0
  67. package/dist/capability-package.test.d.ts.map +1 -0
  68. package/dist/capability-package.test.js +179 -0
  69. package/dist/capability-package.test.js.map +1 -0
  70. package/dist/capability-registry.d.ts +262 -0
  71. package/dist/capability-registry.d.ts.map +1 -0
  72. package/dist/capability-registry.js +931 -0
  73. package/dist/capability-registry.js.map +1 -0
  74. package/dist/capability-registry.test.d.ts +2 -0
  75. package/dist/capability-registry.test.d.ts.map +1 -0
  76. package/dist/capability-registry.test.js +1683 -0
  77. package/dist/capability-registry.test.js.map +1 -0
  78. package/dist/capability-runner.d.ts +99 -0
  79. package/dist/capability-runner.d.ts.map +1 -0
  80. package/dist/capability-runner.js +608 -0
  81. package/dist/capability-runner.js.map +1 -0
  82. package/dist/capability-search-relevance.test.d.ts +2 -0
  83. package/dist/capability-search-relevance.test.d.ts.map +1 -0
  84. package/dist/capability-search-relevance.test.js +67 -0
  85. package/dist/capability-search-relevance.test.js.map +1 -0
  86. package/dist/capability-studio.d.ts +11 -0
  87. package/dist/capability-studio.d.ts.map +1 -0
  88. package/dist/capability-studio.js +593 -0
  89. package/dist/capability-studio.js.map +1 -0
  90. package/dist/capability-studio.test.d.ts +2 -0
  91. package/dist/capability-studio.test.d.ts.map +1 -0
  92. package/dist/capability-studio.test.js +41 -0
  93. package/dist/capability-studio.test.js.map +1 -0
  94. package/dist/cdp-log.d.ts +19 -0
  95. package/dist/cdp-log.d.ts.map +1 -0
  96. package/dist/cdp-log.js +83 -0
  97. package/dist/cdp-log.js.map +1 -0
  98. package/dist/cdp-log.test.d.ts +2 -0
  99. package/dist/cdp-log.test.d.ts.map +1 -0
  100. package/dist/cdp-log.test.js +109 -0
  101. package/dist/cdp-log.test.js.map +1 -0
  102. package/dist/cdp-relay.d.ts +19 -0
  103. package/dist/cdp-relay.d.ts.map +1 -0
  104. package/dist/cdp-relay.js +2375 -0
  105. package/dist/cdp-relay.js.map +1 -0
  106. package/dist/cdp-session.d.ts +37 -0
  107. package/dist/cdp-session.d.ts.map +1 -0
  108. package/dist/cdp-session.js +36 -0
  109. package/dist/cdp-session.js.map +1 -0
  110. package/dist/cdp-types.d.ts +65 -0
  111. package/dist/cdp-types.d.ts.map +1 -0
  112. package/dist/cdp-types.js +91 -0
  113. package/dist/cdp-types.js.map +1 -0
  114. package/dist/channel-owner-inspect.test.d.ts +2 -0
  115. package/dist/channel-owner-inspect.test.d.ts.map +1 -0
  116. package/dist/channel-owner-inspect.test.js +75 -0
  117. package/dist/channel-owner-inspect.test.js.map +1 -0
  118. package/dist/chrome-discovery.d.ts +65 -0
  119. package/dist/chrome-discovery.d.ts.map +1 -0
  120. package/dist/chrome-discovery.js +173 -0
  121. package/dist/chrome-discovery.js.map +1 -0
  122. package/dist/chrome-discovery.test.d.ts +2 -0
  123. package/dist/chrome-discovery.test.d.ts.map +1 -0
  124. package/dist/chrome-discovery.test.js +41 -0
  125. package/dist/chrome-discovery.test.js.map +1 -0
  126. package/dist/clean-html.d.ts +11 -0
  127. package/dist/clean-html.d.ts.map +1 -0
  128. package/dist/clean-html.js +106 -0
  129. package/dist/clean-html.js.map +1 -0
  130. package/dist/cli-help.test.d.ts +2 -0
  131. package/dist/cli-help.test.d.ts.map +1 -0
  132. package/dist/cli-help.test.js +98 -0
  133. package/dist/cli-help.test.js.map +1 -0
  134. package/dist/cli.d.ts +3 -0
  135. package/dist/cli.d.ts.map +1 -0
  136. package/dist/cli.js +2709 -0
  137. package/dist/cli.js.map +1 -0
  138. package/dist/cloud-client.d.ts +56 -0
  139. package/dist/cloud-client.d.ts.map +1 -0
  140. package/dist/cloud-client.js +127 -0
  141. package/dist/cloud-client.js.map +1 -0
  142. package/dist/create-logger.d.ts +9 -0
  143. package/dist/create-logger.d.ts.map +1 -0
  144. package/dist/create-logger.js +27 -0
  145. package/dist/create-logger.js.map +1 -0
  146. package/dist/debugger-api.md +458 -0
  147. package/dist/debugger-examples-types.d.ts +24 -0
  148. package/dist/debugger-examples-types.d.ts.map +1 -0
  149. package/dist/debugger-examples-types.js +2 -0
  150. package/dist/debugger-examples-types.js.map +1 -0
  151. package/dist/debugger-examples.d.ts +6 -0
  152. package/dist/debugger-examples.d.ts.map +1 -0
  153. package/dist/debugger-examples.js +53 -0
  154. package/dist/debugger-examples.js.map +1 -0
  155. package/dist/debugger.d.ts +381 -0
  156. package/dist/debugger.d.ts.map +1 -0
  157. package/dist/debugger.js +630 -0
  158. package/dist/debugger.js.map +1 -0
  159. package/dist/diff-utils.d.ts +20 -0
  160. package/dist/diff-utils.d.ts.map +1 -0
  161. package/dist/diff-utils.js +50 -0
  162. package/dist/diff-utils.js.map +1 -0
  163. package/dist/diff-utils.test.d.ts +2 -0
  164. package/dist/diff-utils.test.d.ts.map +1 -0
  165. package/dist/diff-utils.test.js +137 -0
  166. package/dist/diff-utils.test.js.map +1 -0
  167. package/dist/doctor.d.ts +44 -0
  168. package/dist/doctor.d.ts.map +1 -0
  169. package/dist/doctor.js +246 -0
  170. package/dist/doctor.js.map +1 -0
  171. package/dist/doctor.test.d.ts +2 -0
  172. package/dist/doctor.test.d.ts.map +1 -0
  173. package/dist/doctor.test.js +208 -0
  174. package/dist/doctor.test.js.map +1 -0
  175. package/dist/editor-api.md +374 -0
  176. package/dist/editor-examples.d.ts +11 -0
  177. package/dist/editor-examples.d.ts.map +1 -0
  178. package/dist/editor-examples.js +124 -0
  179. package/dist/editor-examples.js.map +1 -0
  180. package/dist/editor.d.ts +203 -0
  181. package/dist/editor.d.ts.map +1 -0
  182. package/dist/editor.js +363 -0
  183. package/dist/editor.js.map +1 -0
  184. package/dist/env-compat.d.ts +2 -0
  185. package/dist/env-compat.d.ts.map +1 -0
  186. package/dist/env-compat.js +27 -0
  187. package/dist/env-compat.js.map +1 -0
  188. package/dist/executor.d.ts +229 -0
  189. package/dist/executor.d.ts.map +1 -0
  190. package/dist/executor.js +1465 -0
  191. package/dist/executor.js.map +1 -0
  192. package/dist/executor.unit.test.d.ts +2 -0
  193. package/dist/executor.unit.test.d.ts.map +1 -0
  194. package/dist/executor.unit.test.js +143 -0
  195. package/dist/executor.unit.test.js.map +1 -0
  196. package/dist/extension/_locales/en/messages.json +278 -0
  197. package/dist/extension/_locales/zh_CN/messages.json +256 -0
  198. package/dist/extension/assets/options-CYH96Lcx.css +1349 -0
  199. package/dist/extension/background.js +3994 -0
  200. package/dist/extension/icons/SolarCursorSquareBold.png +0 -0
  201. package/dist/extension/icons/icon-black-128.png +0 -0
  202. package/dist/extension/icons/icon-black-16.png +0 -0
  203. package/dist/extension/icons/icon-black-32.png +0 -0
  204. package/dist/extension/icons/icon-black-48.png +0 -0
  205. package/dist/extension/icons/icon-gray-128.png +0 -0
  206. package/dist/extension/icons/icon-gray-16.png +0 -0
  207. package/dist/extension/icons/icon-gray-32.png +0 -0
  208. package/dist/extension/icons/icon-gray-48.png +0 -0
  209. package/dist/extension/icons/icon-green-128.png +0 -0
  210. package/dist/extension/icons/icon-green-16.png +0 -0
  211. package/dist/extension/icons/icon-green-32.png +0 -0
  212. package/dist/extension/icons/icon-green-48.png +0 -0
  213. package/dist/extension/icons/tabwright-icon-black.png +0 -0
  214. package/dist/extension/icons/tabwright-icon-gray-disabled.png +0 -0
  215. package/dist/extension/icons/tabwright-icon-gray-disabled.svg +1 -0
  216. package/dist/extension/manifest.json +54 -0
  217. package/dist/extension/options.js +16145 -0
  218. package/dist/extension/rrweb-recorder.js +12952 -0
  219. package/dist/extension/src/options.html +165 -0
  220. package/dist/extension/src/prism-bash.min.js +1 -0
  221. package/dist/extension/src/prism.min.js +1 -0
  222. package/dist/extension/src/welcome.html +396 -0
  223. package/dist/extension-connection.test.d.ts +2 -0
  224. package/dist/extension-connection.test.d.ts.map +1 -0
  225. package/dist/extension-connection.test.js +708 -0
  226. package/dist/extension-connection.test.js.map +1 -0
  227. package/dist/extension-icon-warning.test.d.ts +2 -0
  228. package/dist/extension-icon-warning.test.d.ts.map +1 -0
  229. package/dist/extension-icon-warning.test.js +33 -0
  230. package/dist/extension-icon-warning.test.js.map +1 -0
  231. package/dist/ghost-browser.d.ts +62 -0
  232. package/dist/ghost-browser.d.ts.map +1 -0
  233. package/dist/ghost-browser.js +107 -0
  234. package/dist/ghost-browser.js.map +1 -0
  235. package/dist/ghost-cursor-client.js +374 -0
  236. package/dist/ghost-cursor-controller.d.ts +46 -0
  237. package/dist/ghost-cursor-controller.d.ts.map +1 -0
  238. package/dist/ghost-cursor-controller.js +98 -0
  239. package/dist/ghost-cursor-controller.js.map +1 -0
  240. package/dist/ghost-cursor.d.ts +27 -0
  241. package/dist/ghost-cursor.d.ts.map +1 -0
  242. package/dist/ghost-cursor.js +79 -0
  243. package/dist/ghost-cursor.js.map +1 -0
  244. package/dist/htmlrewrite.d.ts +8 -0
  245. package/dist/htmlrewrite.d.ts.map +1 -0
  246. package/dist/htmlrewrite.js +339 -0
  247. package/dist/htmlrewrite.js.map +1 -0
  248. package/dist/htmlrewrite.test.d.ts +2 -0
  249. package/dist/htmlrewrite.test.d.ts.map +1 -0
  250. package/dist/htmlrewrite.test.js +7975 -0
  251. package/dist/htmlrewrite.test.js.map +1 -0
  252. package/dist/index.d.ts +20 -0
  253. package/dist/index.d.ts.map +1 -0
  254. package/dist/index.js +11 -0
  255. package/dist/index.js.map +1 -0
  256. package/dist/kill-port.d.ts +29 -0
  257. package/dist/kill-port.d.ts.map +1 -0
  258. package/dist/kill-port.js +190 -0
  259. package/dist/kill-port.js.map +1 -0
  260. package/dist/kitty-graphics.d.ts +22 -0
  261. package/dist/kitty-graphics.d.ts.map +1 -0
  262. package/dist/kitty-graphics.js +71 -0
  263. package/dist/kitty-graphics.js.map +1 -0
  264. package/dist/kitty-graphics.test.d.ts +2 -0
  265. package/dist/kitty-graphics.test.d.ts.map +1 -0
  266. package/dist/kitty-graphics.test.js +125 -0
  267. package/dist/kitty-graphics.test.js.map +1 -0
  268. package/dist/locator-selector.test.d.ts +2 -0
  269. package/dist/locator-selector.test.d.ts.map +1 -0
  270. package/dist/locator-selector.test.js +98 -0
  271. package/dist/locator-selector.test.js.map +1 -0
  272. package/dist/mcp-client.d.ts +20 -0
  273. package/dist/mcp-client.d.ts.map +1 -0
  274. package/dist/mcp-client.js +56 -0
  275. package/dist/mcp-client.js.map +1 -0
  276. package/dist/mcp.d.ts +6 -0
  277. package/dist/mcp.d.ts.map +1 -0
  278. package/dist/mcp.js +511 -0
  279. package/dist/mcp.js.map +1 -0
  280. package/dist/on-mouse-action.test.d.ts +2 -0
  281. package/dist/on-mouse-action.test.d.ts.map +1 -0
  282. package/dist/on-mouse-action.test.js +180 -0
  283. package/dist/on-mouse-action.test.js.map +1 -0
  284. package/dist/options-page.test.d.ts +2 -0
  285. package/dist/options-page.test.d.ts.map +1 -0
  286. package/dist/options-page.test.js +773 -0
  287. package/dist/options-page.test.js.map +1 -0
  288. package/dist/package-paths.d.ts +4 -0
  289. package/dist/package-paths.d.ts.map +1 -0
  290. package/dist/package-paths.js +30 -0
  291. package/dist/package-paths.js.map +1 -0
  292. package/dist/page-markdown.d.ts +40 -0
  293. package/dist/page-markdown.d.ts.map +1 -0
  294. package/dist/page-markdown.js +181 -0
  295. package/dist/page-markdown.js.map +1 -0
  296. package/dist/performance-examples.d.ts +5 -0
  297. package/dist/performance-examples.d.ts.map +1 -0
  298. package/dist/performance-examples.js +112 -0
  299. package/dist/performance-examples.js.map +1 -0
  300. package/dist/performance-profiling.md +417 -0
  301. package/dist/playwright-import.d.ts +19 -0
  302. package/dist/playwright-import.d.ts.map +1 -0
  303. package/dist/playwright-import.js +40 -0
  304. package/dist/playwright-import.js.map +1 -0
  305. package/dist/popup-relocation.test.d.ts +7 -0
  306. package/dist/popup-relocation.test.d.ts.map +1 -0
  307. package/dist/popup-relocation.test.js +139 -0
  308. package/dist/popup-relocation.test.js.map +1 -0
  309. package/dist/product-paths.d.ts +9 -0
  310. package/dist/product-paths.d.ts.map +1 -0
  311. package/dist/product-paths.js +24 -0
  312. package/dist/product-paths.js.map +1 -0
  313. package/dist/product-paths.test.d.ts +2 -0
  314. package/dist/product-paths.test.d.ts.map +1 -0
  315. package/dist/product-paths.test.js +39 -0
  316. package/dist/product-paths.test.js.map +1 -0
  317. package/dist/prompt.md +1004 -0
  318. package/dist/protocol.d.ts +248 -0
  319. package/dist/protocol.d.ts.map +1 -0
  320. package/dist/protocol.js +59 -0
  321. package/dist/protocol.js.map +1 -0
  322. package/dist/protocol.test.d.ts +2 -0
  323. package/dist/protocol.test.d.ts.map +1 -0
  324. package/dist/protocol.test.js +31 -0
  325. package/dist/protocol.test.js.map +1 -0
  326. package/dist/react-source.d.ts +57 -0
  327. package/dist/react-source.d.ts.map +1 -0
  328. package/dist/react-source.js +254 -0
  329. package/dist/react-source.js.map +1 -0
  330. package/dist/readability.js +1674 -0
  331. package/dist/relay-client.d.ts +104 -0
  332. package/dist/relay-client.d.ts.map +1 -0
  333. package/dist/relay-client.js +426 -0
  334. package/dist/relay-client.js.map +1 -0
  335. package/dist/relay-client.test.d.ts +2 -0
  336. package/dist/relay-client.test.d.ts.map +1 -0
  337. package/dist/relay-client.test.js +305 -0
  338. package/dist/relay-client.test.js.map +1 -0
  339. package/dist/relay-core.test.d.ts +2 -0
  340. package/dist/relay-core.test.d.ts.map +1 -0
  341. package/dist/relay-core.test.js +1427 -0
  342. package/dist/relay-core.test.js.map +1 -0
  343. package/dist/relay-navigation.test.d.ts +2 -0
  344. package/dist/relay-navigation.test.d.ts.map +1 -0
  345. package/dist/relay-navigation.test.js +661 -0
  346. package/dist/relay-navigation.test.js.map +1 -0
  347. package/dist/relay-session.test.d.ts +2 -0
  348. package/dist/relay-session.test.d.ts.map +1 -0
  349. package/dist/relay-session.test.js +1121 -0
  350. package/dist/relay-session.test.js.map +1 -0
  351. package/dist/relay-state.d.ts +178 -0
  352. package/dist/relay-state.d.ts.map +1 -0
  353. package/dist/relay-state.js +346 -0
  354. package/dist/relay-state.js.map +1 -0
  355. package/dist/relay-state.test.d.ts +2 -0
  356. package/dist/relay-state.test.d.ts.map +1 -0
  357. package/dist/relay-state.test.js +594 -0
  358. package/dist/relay-state.test.js.map +1 -0
  359. package/dist/replay-ai-index.d.ts +99 -0
  360. package/dist/replay-ai-index.d.ts.map +1 -0
  361. package/dist/replay-ai-index.js +677 -0
  362. package/dist/replay-ai-index.js.map +1 -0
  363. package/dist/replay-ai-index.test.d.ts +2 -0
  364. package/dist/replay-ai-index.test.d.ts.map +1 -0
  365. package/dist/replay-ai-index.test.js +255 -0
  366. package/dist/replay-ai-index.test.js.map +1 -0
  367. package/dist/replay-cli.test.d.ts +2 -0
  368. package/dist/replay-cli.test.d.ts.map +1 -0
  369. package/dist/replay-cli.test.js +275 -0
  370. package/dist/replay-cli.test.js.map +1 -0
  371. package/dist/replay-eval.d.ts +44 -0
  372. package/dist/replay-eval.d.ts.map +1 -0
  373. package/dist/replay-eval.js +902 -0
  374. package/dist/replay-eval.js.map +1 -0
  375. package/dist/replay-handoff.d.ts +29 -0
  376. package/dist/replay-handoff.d.ts.map +1 -0
  377. package/dist/replay-handoff.js +83 -0
  378. package/dist/replay-handoff.js.map +1 -0
  379. package/dist/replay-handoff.test.d.ts +2 -0
  380. package/dist/replay-handoff.test.d.ts.map +1 -0
  381. package/dist/replay-handoff.test.js +123 -0
  382. package/dist/replay-handoff.test.js.map +1 -0
  383. package/dist/replay-workflow-compiler.d.ts +44 -0
  384. package/dist/replay-workflow-compiler.d.ts.map +1 -0
  385. package/dist/replay-workflow-compiler.js +601 -0
  386. package/dist/replay-workflow-compiler.js.map +1 -0
  387. package/dist/replay-workflow-compiler.test.d.ts +2 -0
  388. package/dist/replay-workflow-compiler.test.d.ts.map +1 -0
  389. package/dist/replay-workflow-compiler.test.js +223 -0
  390. package/dist/replay-workflow-compiler.test.js.map +1 -0
  391. package/dist/rrweb-recording-relay.d.ts +56 -0
  392. package/dist/rrweb-recording-relay.d.ts.map +1 -0
  393. package/dist/rrweb-recording-relay.js +299 -0
  394. package/dist/rrweb-recording-relay.js.map +1 -0
  395. package/dist/rrweb-recording-relay.test.d.ts +2 -0
  396. package/dist/rrweb-recording-relay.test.d.ts.map +1 -0
  397. package/dist/rrweb-recording-relay.test.js +85 -0
  398. package/dist/rrweb-recording-relay.test.js.map +1 -0
  399. package/dist/rrweb-recording.d.ts +104 -0
  400. package/dist/rrweb-recording.d.ts.map +1 -0
  401. package/dist/rrweb-recording.js +180 -0
  402. package/dist/rrweb-recording.js.map +1 -0
  403. package/dist/scoped-fs.d.ts +95 -0
  404. package/dist/scoped-fs.d.ts.map +1 -0
  405. package/dist/scoped-fs.js +358 -0
  406. package/dist/scoped-fs.js.map +1 -0
  407. package/dist/scoped-fs.test.d.ts +5 -0
  408. package/dist/scoped-fs.test.d.ts.map +1 -0
  409. package/dist/scoped-fs.test.js +73 -0
  410. package/dist/scoped-fs.test.js.map +1 -0
  411. package/dist/selector-generator.js +7378 -0
  412. package/dist/skill-stub.test.d.ts +2 -0
  413. package/dist/skill-stub.test.d.ts.map +1 -0
  414. package/dist/skill-stub.test.js +22 -0
  415. package/dist/skill-stub.test.js.map +1 -0
  416. package/dist/snapshot-tools.test.d.ts +2 -0
  417. package/dist/snapshot-tools.test.d.ts.map +1 -0
  418. package/dist/snapshot-tools.test.js +856 -0
  419. package/dist/snapshot-tools.test.js.map +1 -0
  420. package/dist/start-relay-server.d.ts +6 -0
  421. package/dist/start-relay-server.d.ts.map +1 -0
  422. package/dist/start-relay-server.js +57 -0
  423. package/dist/start-relay-server.js.map +1 -0
  424. package/dist/styles-api.md +124 -0
  425. package/dist/styles-examples.d.ts +8 -0
  426. package/dist/styles-examples.d.ts.map +1 -0
  427. package/dist/styles-examples.js +64 -0
  428. package/dist/styles-examples.js.map +1 -0
  429. package/dist/styles.d.ts +27 -0
  430. package/dist/styles.d.ts.map +1 -0
  431. package/dist/styles.js +231 -0
  432. package/dist/styles.js.map +1 -0
  433. package/dist/tabwright-agent-skill.d.ts +30 -0
  434. package/dist/tabwright-agent-skill.d.ts.map +1 -0
  435. package/dist/tabwright-agent-skill.js +74 -0
  436. package/dist/tabwright-agent-skill.js.map +1 -0
  437. package/dist/tabwright-agent-skill.test.d.ts +2 -0
  438. package/dist/tabwright-agent-skill.test.d.ts.map +1 -0
  439. package/dist/tabwright-agent-skill.test.js +51 -0
  440. package/dist/tabwright-agent-skill.test.js.map +1 -0
  441. package/dist/test-declarations.d.ts +13 -0
  442. package/dist/test-declarations.d.ts.map +1 -0
  443. package/dist/test-declarations.js +2 -0
  444. package/dist/test-declarations.js.map +1 -0
  445. package/dist/test-utils.d.ts +69 -0
  446. package/dist/test-utils.d.ts.map +1 -0
  447. package/dist/test-utils.js +448 -0
  448. package/dist/test-utils.js.map +1 -0
  449. package/dist/test-utils.test.d.ts +2 -0
  450. package/dist/test-utils.test.d.ts.map +1 -0
  451. package/dist/test-utils.test.js +55 -0
  452. package/dist/test-utils.test.js.map +1 -0
  453. package/dist/utils.d.ts +26 -0
  454. package/dist/utils.d.ts.map +1 -0
  455. package/dist/utils.js +60 -0
  456. package/dist/utils.js.map +1 -0
  457. package/dist/wait-for-page-load.d.ts +16 -0
  458. package/dist/wait-for-page-load.d.ts.map +1 -0
  459. package/dist/wait-for-page-load.js +146 -0
  460. package/dist/wait-for-page-load.js.map +1 -0
  461. package/dist/workflow-capability.d.ts +72 -0
  462. package/dist/workflow-capability.d.ts.map +1 -0
  463. package/dist/workflow-capability.js +316 -0
  464. package/dist/workflow-capability.js.map +1 -0
  465. package/dist/workflow-script-flow.test.d.ts +2 -0
  466. package/dist/workflow-script-flow.test.d.ts.map +1 -0
  467. package/dist/workflow-script-flow.test.js +285 -0
  468. package/dist/workflow-script-flow.test.js.map +1 -0
  469. package/package.json +80 -0
  470. package/src/__snapshots__/x.com.processed.html +1003 -0
  471. package/src/__snapshots__/x.com.processed.withStyles.html +2720 -0
  472. package/src/a11y-client.ts +241 -0
  473. package/src/agent-skills/conan-config/SKILL.md +141 -0
  474. package/src/agent-skills/conan-config/agents/openai.yaml +4 -0
  475. package/src/aria-snapshot.test.ts +311 -0
  476. package/src/aria-snapshot.ts +1681 -0
  477. package/src/aria-snapshot.unit.test.ts +615 -0
  478. package/src/aria-snapshots/github-interactive.txt +193 -0
  479. package/src/aria-snapshots/github-raw.txt +309 -0
  480. package/src/aria-snapshots/hackernews-interactive.txt +477 -0
  481. package/src/aria-snapshots/hackernews-raw.txt +428 -0
  482. package/src/aria-snapshots/prosemirror-interactive.txt +66 -0
  483. package/src/aria-snapshots/prosemirror-raw.txt +145 -0
  484. package/src/assets/aria-labels-hacker-news.png +0 -0
  485. package/src/assets/aria-labels-old-reddit.png +0 -0
  486. package/src/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.ts +5 -0
  487. package/src/assets/cursors/screen-studio/pointer-macos-tahoe.svg +18 -0
  488. package/src/assets/x.com.html +32946 -0
  489. package/src/browser-config.ts +179 -0
  490. package/src/browser-install.ts +284 -0
  491. package/src/browser-launch.ts +75 -0
  492. package/src/builtin-capabilities.ts +2765 -0
  493. package/src/capability-agent-skill.ts +305 -0
  494. package/src/capability-auth-state.ts +197 -0
  495. package/src/capability-auth.ts +249 -0
  496. package/src/capability-cli-confirmation.test.ts +90 -0
  497. package/src/capability-options.test.ts +89 -0
  498. package/src/capability-options.ts +57 -0
  499. package/src/capability-package.test.ts +204 -0
  500. package/src/capability-package.ts +555 -0
  501. package/src/capability-registry.test.ts +1905 -0
  502. package/src/capability-registry.ts +1234 -0
  503. package/src/capability-runner.ts +801 -0
  504. package/src/capability-search-relevance.test.ts +73 -0
  505. package/src/capability-studio.test.ts +45 -0
  506. package/src/capability-studio.ts +641 -0
  507. package/src/cdp-log.test.ts +131 -0
  508. package/src/cdp-log.ts +112 -0
  509. package/src/cdp-relay.ts +2944 -0
  510. package/src/cdp-session.ts +77 -0
  511. package/src/cdp-types.ts +158 -0
  512. package/src/channel-owner-inspect.test.ts +94 -0
  513. package/src/chrome-discovery.test.ts +50 -0
  514. package/src/chrome-discovery.ts +220 -0
  515. package/src/clean-html.ts +141 -0
  516. package/src/cli-help.test.ts +123 -0
  517. package/src/cli.ts +3181 -0
  518. package/src/cloud-client.ts +179 -0
  519. package/src/create-logger.ts +38 -0
  520. package/src/debugger-examples-types.ts +16 -0
  521. package/src/debugger-examples.ts +66 -0
  522. package/src/debugger.ts +708 -0
  523. package/src/diff-utils.test.ts +152 -0
  524. package/src/diff-utils.ts +70 -0
  525. package/src/doctor.test.ts +244 -0
  526. package/src/doctor.ts +321 -0
  527. package/src/editor-examples.ts +158 -0
  528. package/src/editor.ts +426 -0
  529. package/src/env-compat.ts +28 -0
  530. package/src/executor.ts +1824 -0
  531. package/src/executor.unit.test.ts +168 -0
  532. package/src/extension-connection.test.ts +855 -0
  533. package/src/extension-icon-warning.test.ts +45 -0
  534. package/src/ghost-browser.ts +149 -0
  535. package/src/ghost-cursor-client.ts +494 -0
  536. package/src/ghost-cursor-controller.ts +129 -0
  537. package/src/ghost-cursor.ts +123 -0
  538. package/src/htmlrewrite.test.ts +8008 -0
  539. package/src/htmlrewrite.ts +390 -0
  540. package/src/index.ts +53 -0
  541. package/src/kill-port.ts +219 -0
  542. package/src/kitty-graphics.test.ts +139 -0
  543. package/src/kitty-graphics.ts +79 -0
  544. package/src/locator-selector.test.ts +119 -0
  545. package/src/mcp-client.ts +78 -0
  546. package/src/mcp.ts +629 -0
  547. package/src/on-mouse-action.test.ts +226 -0
  548. package/src/options-page.test.ts +839 -0
  549. package/src/package-paths.ts +38 -0
  550. package/src/page-markdown.ts +240 -0
  551. package/src/performance-examples.ts +186 -0
  552. package/src/playwright-import.ts +59 -0
  553. package/src/popup-relocation.test.ts +163 -0
  554. package/src/product-paths.test.ts +47 -0
  555. package/src/product-paths.ts +28 -0
  556. package/src/protocol.test.ts +52 -0
  557. package/src/protocol.ts +351 -0
  558. package/src/react-source.ts +379 -0
  559. package/src/relay-client.test.ts +375 -0
  560. package/src/relay-client.ts +572 -0
  561. package/src/relay-core.test.ts +1603 -0
  562. package/src/relay-navigation.test.ts +790 -0
  563. package/src/relay-session.test.ts +1375 -0
  564. package/src/relay-state.test.ts +729 -0
  565. package/src/relay-state.ts +561 -0
  566. package/src/replay-ai-index.test.ts +278 -0
  567. package/src/replay-ai-index.ts +872 -0
  568. package/src/replay-cli.test.ts +325 -0
  569. package/src/replay-eval.ts +1039 -0
  570. package/src/replay-handoff.test.ts +163 -0
  571. package/src/replay-handoff.ts +109 -0
  572. package/src/replay-workflow-compiler.test.ts +250 -0
  573. package/src/replay-workflow-compiler.ts +700 -0
  574. package/src/resource.md +409 -0
  575. package/src/rrweb-recording-relay.test.ts +99 -0
  576. package/src/rrweb-recording-relay.ts +400 -0
  577. package/src/rrweb-recording.ts +322 -0
  578. package/src/scoped-fs.test.ts +80 -0
  579. package/src/scoped-fs.ts +420 -0
  580. package/src/skill-stub.test.ts +24 -0
  581. package/src/skill.md +1413 -0
  582. package/src/snapshot-tools.test.ts +1017 -0
  583. package/src/snapshots/hacker-news-accessibility-full.md +81 -0
  584. package/src/snapshots/hacker-news-accessibility-interactive.md +43 -0
  585. package/src/snapshots/page-markdown-output.txt +16 -0
  586. package/src/snapshots/shadcn-ui-accessibility-full.md +201 -0
  587. package/src/snapshots/shadcn-ui-accessibility-interactive.md +109 -0
  588. package/src/start-relay-server.ts +69 -0
  589. package/src/styles-examples.ts +84 -0
  590. package/src/styles.ts +343 -0
  591. package/src/tabwright-agent-skill.test.ts +61 -0
  592. package/src/tabwright-agent-skill.ts +105 -0
  593. package/src/test-declarations.ts +13 -0
  594. package/src/test-utils.test.ts +70 -0
  595. package/src/test-utils.ts +566 -0
  596. package/src/utils.ts +78 -0
  597. package/src/wait-for-page-load.ts +198 -0
  598. package/src/workflow-capability.ts +417 -0
  599. package/src/workflow-script-flow.test.ts +388 -0
@@ -0,0 +1,198 @@
1
+ import type { Page } from '@xmorse/playwright-core'
2
+ import { sleep } from './utils.js'
3
+
4
+ const FILTERED_DOMAINS = [
5
+ 'doubleclick',
6
+ 'googlesyndication',
7
+ 'googleadservices',
8
+ 'google-analytics',
9
+ 'googletagmanager',
10
+ 'facebook.net',
11
+ 'fbcdn.net',
12
+ 'twitter.com',
13
+ 'linkedin.com',
14
+ 'hotjar',
15
+ 'mixpanel',
16
+ 'segment.io',
17
+ 'segment.com',
18
+ 'newrelic',
19
+ 'datadoghq',
20
+ 'sentry.io',
21
+ 'fullstory',
22
+ 'amplitude',
23
+ 'intercom',
24
+ 'crisp.chat',
25
+ 'zdassets.com',
26
+ 'zendesk',
27
+ 'tawk.to',
28
+ 'hubspot',
29
+ 'marketo',
30
+ 'pardot',
31
+ 'optimizely',
32
+ 'crazyegg',
33
+ 'mouseflow',
34
+ 'clarity.ms',
35
+ 'bing.com/bat',
36
+ 'ads.',
37
+ 'analytics.',
38
+ 'tracking.',
39
+ 'pixel.',
40
+ ]
41
+
42
+ const FILTERED_EXTENSIONS = ['.gif', '.ico', '.cur', '.woff', '.woff2', '.ttf', '.otf', '.eot']
43
+
44
+ export interface WaitForPageLoadOptions {
45
+ page: Page
46
+ timeout?: number
47
+ pollInterval?: number
48
+ minWait?: number
49
+ }
50
+
51
+ export interface WaitForPageLoadResult {
52
+ success: boolean
53
+ readyState: string
54
+ pendingRequests: string[]
55
+ waitTimeMs: number
56
+ timedOut: boolean
57
+ }
58
+
59
+ export async function waitForPageLoad(options: WaitForPageLoadOptions): Promise<WaitForPageLoadResult> {
60
+ const { page, timeout = 30000, pollInterval = 100, minWait = 500 } = options
61
+
62
+ const startTime = Date.now()
63
+ let timedOut = false
64
+ let lastReadyState = ''
65
+ let lastPendingRequests: string[] = []
66
+
67
+ const checkPageReady = async (): Promise<{ ready: boolean; readyState: string; pendingRequests: string[] }> => {
68
+ const result = await page.evaluate(
69
+ ({
70
+ filteredDomains,
71
+ filteredExtensions,
72
+ stuckThreshold,
73
+ slowResourceThreshold,
74
+ }): {
75
+ ready: boolean
76
+ readyState: string
77
+ pendingRequests: string[]
78
+ } => {
79
+ const doc = globalThis.document as { readyState: string }
80
+ const readyState = doc.readyState
81
+
82
+ if (readyState !== 'complete') {
83
+ return { ready: false, readyState, pendingRequests: [`document.readyState: ${readyState}`] }
84
+ }
85
+
86
+ const resources = (performance as any).getEntriesByType('resource') as Array<{
87
+ name: string
88
+ startTime: number
89
+ responseEnd: number
90
+ }>
91
+ const now = (performance as any).now() as number
92
+
93
+ const pendingRequests = resources
94
+ .filter((r) => {
95
+ if (r.responseEnd > 0) {
96
+ return false
97
+ }
98
+
99
+ const elapsed = now - r.startTime
100
+ const url = r.name.toLowerCase()
101
+
102
+ if (url.startsWith('data:')) {
103
+ return false
104
+ }
105
+
106
+ if (filteredDomains.some((domain: string) => url.includes(domain))) {
107
+ return false
108
+ }
109
+
110
+ if (elapsed > stuckThreshold) {
111
+ return false
112
+ }
113
+
114
+ if (elapsed > slowResourceThreshold && filteredExtensions.some((ext: string) => url.includes(ext))) {
115
+ return false
116
+ }
117
+
118
+ return true
119
+ })
120
+ .map((r) => r.name)
121
+
122
+ return {
123
+ ready: pendingRequests.length === 0,
124
+ readyState,
125
+ pendingRequests,
126
+ }
127
+ },
128
+ {
129
+ filteredDomains: FILTERED_DOMAINS,
130
+ filteredExtensions: FILTERED_EXTENSIONS,
131
+ stuckThreshold: 10000,
132
+ slowResourceThreshold: 3000,
133
+ },
134
+ )
135
+
136
+ return result
137
+ }
138
+
139
+ // Fast path: check immediately first. If already ready, return without waiting.
140
+ try {
141
+ const firstCheck = await checkPageReady()
142
+ if (firstCheck.ready) {
143
+ return {
144
+ success: true,
145
+ readyState: firstCheck.readyState,
146
+ pendingRequests: [],
147
+ waitTimeMs: Date.now() - startTime,
148
+ timedOut: false,
149
+ }
150
+ }
151
+ lastReadyState = firstCheck.readyState
152
+ lastPendingRequests = firstCheck.pendingRequests
153
+ } catch (e) {
154
+ // First check failed, continue with polling
155
+ }
156
+
157
+ // Not ready yet - wait minWait to let JS settle and catch late-starting requests
158
+ await sleep(minWait)
159
+
160
+ while (Date.now() - startTime < timeout) {
161
+ try {
162
+ const { ready, readyState, pendingRequests } = await checkPageReady()
163
+ lastReadyState = readyState
164
+ lastPendingRequests = pendingRequests
165
+
166
+ if (ready) {
167
+ return {
168
+ success: true,
169
+ readyState,
170
+ pendingRequests: [],
171
+ waitTimeMs: Date.now() - startTime,
172
+ timedOut: false,
173
+ }
174
+ }
175
+ } catch (e) {
176
+ console.error('[waitForPageLoad] page.evaluate failed:', e)
177
+ return {
178
+ success: false,
179
+ readyState: 'error',
180
+ pendingRequests: ['page.evaluate failed - page may have closed or navigated'],
181
+ waitTimeMs: Date.now() - startTime,
182
+ timedOut: false,
183
+ }
184
+ }
185
+
186
+ await sleep(pollInterval)
187
+ }
188
+
189
+ timedOut = true
190
+
191
+ return {
192
+ success: false,
193
+ readyState: lastReadyState,
194
+ pendingRequests: lastPendingRequests.slice(0, 10),
195
+ waitTimeMs: Date.now() - startTime,
196
+ timedOut,
197
+ }
198
+ }
@@ -0,0 +1,417 @@
1
+ import {
2
+ createCapability,
3
+ readCapabilityScript,
4
+ toCapabilitySummary,
5
+ updateCapabilityManifest,
6
+ updateCapabilityScript,
7
+ type CapabilityExample,
8
+ type CapabilityLocation,
9
+ type CapabilityRecord,
10
+ type CapabilitySideEffect,
11
+ } from './capability-registry.js'
12
+
13
+ export interface SaveWorkflowCapabilityOptions {
14
+ id: string
15
+ title: string
16
+ description?: string
17
+ script: string
18
+ cwd?: string
19
+ location?: CapabilityLocation
20
+ overwrite?: boolean
21
+ sourceRecordingId?: string
22
+ whenToUse?: string[]
23
+ whenNotToUse?: string[]
24
+ match?: string[]
25
+ tags?: string[]
26
+ inputSchema?: Record<string, unknown>
27
+ outputSchema?: Record<string, unknown>
28
+ examples?: CapabilityExample[]
29
+ sideEffect?: CapabilitySideEffect
30
+ requiresConfirmation?: boolean
31
+ }
32
+
33
+ export interface SavedWorkflowCapability {
34
+ capability: Record<string, unknown>
35
+ script: string
36
+ }
37
+
38
+ type WorkflowValue =
39
+ | {
40
+ inputPath: string
41
+ fallback?: unknown
42
+ }
43
+ | {
44
+ value: unknown
45
+ }
46
+
47
+ export type RecordingWorkflowStep =
48
+ | {
49
+ action: 'goto'
50
+ url: string | WorkflowValue
51
+ }
52
+ | {
53
+ action: 'fill'
54
+ locator: string
55
+ value: WorkflowValue
56
+ }
57
+ | {
58
+ action: 'click'
59
+ locator: string
60
+ }
61
+ | {
62
+ action: 'setInputFiles'
63
+ locator: string
64
+ path: WorkflowValue
65
+ }
66
+ | {
67
+ action: 'selectOption'
68
+ locator: string
69
+ value: WorkflowValue
70
+ }
71
+ | {
72
+ action: 'waitForURL'
73
+ url: string | WorkflowValue
74
+ }
75
+
76
+ export interface RecordingWorkflowFinalRequest {
77
+ url: string
78
+ method?: string | string[]
79
+ title?: string
80
+ description?: string
81
+ trigger: RecordingWorkflowStep
82
+ }
83
+
84
+ export interface SaveWorkflowFromRecordingOptions
85
+ extends Omit<SaveWorkflowCapabilityOptions, 'script' | 'sourceRecordingId'> {
86
+ recordingId: string
87
+ steps: RecordingWorkflowStep[]
88
+ finalRequest?: RecordingWorkflowFinalRequest
89
+ batch?: {
90
+ inputPath?: string
91
+ continueOnError?: boolean
92
+ }
93
+ }
94
+
95
+ function workflowTags(options: SaveWorkflowCapabilityOptions): string[] {
96
+ const tags = new Set(['workflow', 'recording-derived', ...(options.tags || [])])
97
+ if (options.sourceRecordingId) {
98
+ tags.add(`recording:${options.sourceRecordingId}`)
99
+ }
100
+ return Array.from(tags)
101
+ }
102
+
103
+ function workflowWhenToUse(options: SaveWorkflowCapabilityOptions): string[] {
104
+ const whenToUse = options.whenToUse || []
105
+ if (whenToUse.length > 0) {
106
+ return whenToUse
107
+ }
108
+ return [
109
+ options.description ||
110
+ `Run the workflow generated from recording ${options.sourceRecordingId || 'a user demonstration'}.`,
111
+ ]
112
+ }
113
+
114
+ function saveScriptCapability(options: SaveWorkflowCapabilityOptions): CapabilityRecord {
115
+ const capability = createCapability({
116
+ id: options.id,
117
+ title: options.title,
118
+ description: options.description,
119
+ location: options.location || 'project',
120
+ cwd: options.cwd,
121
+ overwrite: options.overwrite,
122
+ createdBy: 'ai',
123
+ runtime: 'browser',
124
+ })
125
+
126
+ updateCapabilityScript({
127
+ id: capability.manifest.id,
128
+ cwd: options.cwd,
129
+ source: options.script,
130
+ })
131
+
132
+ return updateCapabilityManifest({
133
+ id: capability.manifest.id,
134
+ cwd: options.cwd,
135
+ patch: {
136
+ description: options.description || capability.manifest.description,
137
+ whenToUse: workflowWhenToUse(options),
138
+ whenNotToUse: options.whenNotToUse || [],
139
+ match: options.match || [],
140
+ tags: workflowTags(options),
141
+ inputSchema: options.inputSchema || { type: 'object', properties: {}, required: [] },
142
+ outputSchema: options.outputSchema || { type: 'object', properties: {} },
143
+ permissions: ['browser.read', 'browser.write'],
144
+ sideEffect: options.sideEffect || 'write',
145
+ requiresConfirmation: options.requiresConfirmation ?? true,
146
+ examples: options.examples || [],
147
+ status: 'draft',
148
+ createdBy: 'ai',
149
+ runtime: 'browser',
150
+ },
151
+ })
152
+ }
153
+
154
+ export function saveWorkflowCapability(options: SaveWorkflowCapabilityOptions): SavedWorkflowCapability {
155
+ const capability = saveScriptCapability(options)
156
+ return {
157
+ capability: toCapabilitySummary(capability),
158
+ script: readCapabilityScript({ id: capability.manifest.id, cwd: options.cwd }),
159
+ }
160
+ }
161
+
162
+ function workflowLiteral(value: unknown): string {
163
+ return JSON.stringify(value, null, 2)
164
+ }
165
+
166
+ function buildWorkflowScript(options: SaveWorkflowFromRecordingOptions): string {
167
+ const continueOnError = options.batch?.continueOnError ?? false
168
+ const batchInputPath = options.batch?.inputPath || 'items'
169
+
170
+ return [
171
+ '// Generated from a user recording: run fast by default, and return needs_ai when the live page diverges.',
172
+ `const workflowSteps = ${workflowLiteral(options.steps)};`,
173
+ `const finalRequest = ${workflowLiteral(options.finalRequest)};`,
174
+ `const batchInputPath = ${workflowLiteral(batchInputPath)};`,
175
+ `const sourceRecordingId = ${workflowLiteral(options.recordingId)};`,
176
+ `const continueOnError = ${continueOnError ? 'true' : 'false'};`,
177
+ '',
178
+ 'function getPathValue(source, path, fallback) {',
179
+ ' if (!path) return fallback;',
180
+ ' const parts = path.split(".").filter((part) => part.length > 0);',
181
+ ' const value = parts.reduce((current, part) => {',
182
+ ' if (!current || typeof current !== "object") return undefined;',
183
+ ' if (!Object.prototype.hasOwnProperty.call(current, part)) return undefined;',
184
+ ' return current[part];',
185
+ ' }, source);',
186
+ ' return value === undefined ? fallback : value;',
187
+ '}',
188
+ '',
189
+ 'function resolveWorkflowValue(item, value) {',
190
+ ' if (typeof value === "string") return value;',
191
+ ' if (!value || typeof value !== "object") return value;',
192
+ ' if (Object.prototype.hasOwnProperty.call(value, "inputPath")) return getPathValue(item, value.inputPath, value.fallback);',
193
+ ' if (Object.prototype.hasOwnProperty.call(value, "value")) return value.value;',
194
+ ' return value;',
195
+ '}',
196
+ '',
197
+ 'function errorMessage(error) {',
198
+ ' if (error && typeof error === "object" && typeof error.message === "string") return error.message;',
199
+ ' return String(error);',
200
+ '}',
201
+ '',
202
+ 'function escapeRegex(value) {',
203
+ ' return value.replace(/[.*+?^${}()|[\\]\\\\]/g, "\\\\$&");',
204
+ '}',
205
+ '',
206
+ 'function globToRegExp(pattern) {',
207
+ ' return new RegExp("^" + String(pattern).split("*").map(escapeRegex).join(".*") + "$");',
208
+ '}',
209
+ '',
210
+ 'function normalizedMethods(method) {',
211
+ ' if (Array.isArray(method)) return method.map((item) => String(item).toUpperCase());',
212
+ ' if (method) return [String(method).toUpperCase()];',
213
+ ' return ["POST", "PUT", "PATCH", "DELETE"];',
214
+ '}',
215
+ '',
216
+ 'function requestMatchesFinalRequest(request) {',
217
+ ' if (!finalRequest || !finalRequest.url) return false;',
218
+ ' const methods = normalizedMethods(finalRequest.method);',
219
+ ' if (!methods.includes(request.method().toUpperCase())) return false;',
220
+ ' return globToRegExp(finalRequest.url).test(request.url());',
221
+ '}',
222
+ '',
223
+ 'async function readSnapshotText() {',
224
+ ' if (typeof snapshot !== "function") return undefined;',
225
+ ' try {',
226
+ ' const value = await snapshot({ page });',
227
+ ' const text = typeof value === "string" ? value : JSON.stringify(value, null, 2);',
228
+ ' return text.slice(0, 12000);',
229
+ ' } catch (error) {',
230
+ ' return "snapshot failed: " + errorMessage(error);',
231
+ ' }',
232
+ '}',
233
+ '',
234
+ 'async function captureWorkflowContext({ step, item, index, phase, reason, error }) {',
235
+ ' return {',
236
+ ' status: "needs_ai",',
237
+ ' reason,',
238
+ ' error: error ? errorMessage(error) : undefined,',
239
+ ' phase,',
240
+ ' step,',
241
+ ' item,',
242
+ ' index,',
243
+ ' sourceRecordingId,',
244
+ ' context: {',
245
+ ' url: page.url(),',
246
+ ' title: await page.title().catch(() => ""),',
247
+ ' snapshot: await readSnapshotText(),',
248
+ ' },',
249
+ ' };',
250
+ '}',
251
+ '',
252
+ 'async function getWorkflowLocator(step, item, index, phase) {',
253
+ ' const target = page.locator(step.locator).first();',
254
+ ' try {',
255
+ ' await target.waitFor({ state: "attached", timeout: 2500 });',
256
+ ' return { target };',
257
+ ' } catch (error) {',
258
+ ' return {',
259
+ ' handoff: await captureWorkflowContext({',
260
+ ' step,',
261
+ ' item,',
262
+ ' index,',
263
+ ' phase,',
264
+ ' reason: "Expected locator was not found on the live page.",',
265
+ ' error,',
266
+ ' }),',
267
+ ' };',
268
+ ' }',
269
+ '}',
270
+ '',
271
+ 'async function runWorkflowStep(step, item, options) {',
272
+ ' const index = options.index;',
273
+ ' const phase = options.phase;',
274
+ ' try {',
275
+ ' if (step.action === "goto") {',
276
+ ' await page.goto(String(resolveWorkflowValue(item, step.url)));',
277
+ ' return { status: "ok" };',
278
+ ' }',
279
+ ' if (step.action === "waitForURL") {',
280
+ ' await page.waitForURL(String(resolveWorkflowValue(item, step.url)));',
281
+ ' return { status: "ok" };',
282
+ ' }',
283
+ ' if (!step.locator) {',
284
+ ' return await captureWorkflowContext({ step, item, index, phase, reason: "Workflow step is missing a locator." });',
285
+ ' }',
286
+ ' const located = await getWorkflowLocator(step, item, index, phase);',
287
+ ' if (located.handoff) return located.handoff;',
288
+ ' if (step.action === "fill") {',
289
+ ' await located.target.fill(String(resolveWorkflowValue(item, step.value) ?? ""));',
290
+ ' return { status: "ok" };',
291
+ ' }',
292
+ ' if (step.action === "click") {',
293
+ ' await located.target.click();',
294
+ ' return { status: "ok" };',
295
+ ' }',
296
+ ' if (step.action === "setInputFiles") {',
297
+ ' await located.target.setInputFiles(String(resolveWorkflowValue(item, step.path)));',
298
+ ' return { status: "ok" };',
299
+ ' }',
300
+ ' if (step.action === "selectOption") {',
301
+ ' await located.target.selectOption(String(resolveWorkflowValue(item, step.value)));',
302
+ ' return { status: "ok" };',
303
+ ' }',
304
+ ' return await captureWorkflowContext({ step, item, index, phase, reason: "Unsupported workflow step." });',
305
+ ' } catch (error) {',
306
+ ' return await captureWorkflowContext({ step, item, index, phase, reason: "Workflow step failed on the live page.", error });',
307
+ ' }',
308
+ '}',
309
+ '',
310
+ 'async function runFinalRequestTrigger(item, index) {',
311
+ ' if (!finalRequest || !finalRequest.trigger) return { status: "completed" };',
312
+ ' const requestPromise = page.waitForRequest((request) => {',
313
+ ' return requestMatchesFinalRequest(request);',
314
+ ' }, { timeout: 8000 }).catch((error) => {',
315
+ ' return { error };',
316
+ ' });',
317
+ ' const triggerResult = await runWorkflowStep(finalRequest.trigger, item, { index, phase: "final-request" });',
318
+ ' if (triggerResult.status !== "ok") return triggerResult;',
319
+ ' const request = await requestPromise;',
320
+ ' if (request && request.error) {',
321
+ ' return await captureWorkflowContext({',
322
+ ' step: finalRequest.trigger,',
323
+ ' item,',
324
+ ' index,',
325
+ ' phase: "final-request",',
326
+ ' reason: "The expected final request was not observed after the trigger.",',
327
+ ' error: request.error,',
328
+ ' });',
329
+ ' }',
330
+ ' const response = await request.response().catch(() => null);',
331
+ ' return {',
332
+ ' status: "completed",',
333
+ ' finalRequest: {',
334
+ ' method: request.method(),',
335
+ ' url: request.url(),',
336
+ ' headers: request.headers(),',
337
+ ' postData: request.postData(),',
338
+ ' responseStatus: response ? response.status() : undefined,',
339
+ ' },',
340
+ ' };',
341
+ '}',
342
+ '',
343
+ 'async function runOneWorkflowItem({ item, index }) {',
344
+ ' for (let stepIndex = 0; stepIndex < workflowSteps.length; stepIndex += 1) {',
345
+ ' const step = workflowSteps[stepIndex];',
346
+ ' const result = await runWorkflowStep(step, item, { index, phase: "step-" + (stepIndex + 1) });',
347
+ ' if (result.status !== "ok") return result;',
348
+ ' }',
349
+ ' if (!finalRequest || !finalRequest.trigger) {',
350
+ ' return {',
351
+ ' status: "completed",',
352
+ ' item,',
353
+ ' index,',
354
+ ' };',
355
+ ' }',
356
+ ' const finalResult = await runFinalRequestTrigger(item, index);',
357
+ ' if (finalResult.status !== "completed") return finalResult;',
358
+ ' return {',
359
+ ' status: "completed",',
360
+ ' item,',
361
+ ' index,',
362
+ ' finalRequest: finalResult.finalRequest,',
363
+ ' };',
364
+ '}',
365
+ '',
366
+ 'const batchInput = getPathValue(input, batchInputPath, undefined);',
367
+ 'const items = Array.isArray(batchInput) ? batchInput : [input];',
368
+ 'const results = [];',
369
+ 'let completed = 0;',
370
+ 'let failed = 0;',
371
+ 'let needsAi = null;',
372
+ 'for (let index = 0; index < items.length; index += 1) {',
373
+ ' const item = items[index];',
374
+ ' try {',
375
+ ' const result = await runOneWorkflowItem({ item, index });',
376
+ ' results.push(result);',
377
+ ' if (result.status === "completed") {',
378
+ ' completed += 1;',
379
+ ' } else if (result.status === "needs_ai") {',
380
+ ' needsAi = result;',
381
+ ' if (!continueOnError) break;',
382
+ ' } else {',
383
+ ' failed += 1;',
384
+ ' if (!continueOnError) break;',
385
+ ' }',
386
+ ' } catch (error) {',
387
+ ' const result = await captureWorkflowContext({',
388
+ ' item,',
389
+ ' index,',
390
+ ' phase: "item",',
391
+ ' reason: "Workflow item failed before completion.",',
392
+ ' error,',
393
+ ' });',
394
+ ' results.push(result);',
395
+ ' needsAi = result;',
396
+ ' if (!continueOnError) break;',
397
+ ' }',
398
+ '}',
399
+ 'return {',
400
+ ' status: needsAi ? "needs_ai" : failed > 0 ? "failed" : "completed",',
401
+ ' total: items.length,',
402
+ ' completed,',
403
+ ' failed,',
404
+ ' needsAi,',
405
+ ' results,',
406
+ '};',
407
+ '',
408
+ ].join('\n')
409
+ }
410
+
411
+ export function saveWorkflowFromRecording(options: SaveWorkflowFromRecordingOptions): SavedWorkflowCapability {
412
+ return saveWorkflowCapability({
413
+ ...options,
414
+ sourceRecordingId: options.recordingId,
415
+ script: buildWorkflowScript(options),
416
+ })
417
+ }