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,561 @@
1
+ /**
2
+ * Centralized relay state: one immutable atom for domain state + runtime resources.
3
+ *
4
+ * Follows the zustand-centralized-state skill pattern:
5
+ * - Single Zustand vanilla store holds all relay state
6
+ * - setState() callbacks remain deterministic data transitions
7
+ * - Runtime resources (WebSocket/timers/pending callbacks) are co-located on
8
+ * each extension entry in the same map
9
+ *
10
+ * See docs/plan-centralize-relay-state.md for the full refactor plan.
11
+ */
12
+ import { createStore, type StoreApi } from 'zustand/vanilla'
13
+ import type { WSContext } from 'hono/ws'
14
+ import type WebSocket from 'ws'
15
+ import type { Protocol } from './cdp-types.js'
16
+ import { EXTENSION_FEATURE } from './protocol.js'
17
+
18
+ // ---------------------------------------------------------------------------
19
+ // Types
20
+ // ---------------------------------------------------------------------------
21
+
22
+ export type ConnectedTarget = {
23
+ sessionId: string
24
+ targetId: string
25
+ targetInfo: Protocol.Target.TargetInfo
26
+ frameIds: Set<string>
27
+ }
28
+
29
+ export type ExtensionInfo = {
30
+ browser?: string
31
+ email?: string
32
+ id?: string
33
+ installId?: string
34
+ /** Tabwright package version the extension was built with (sent as ?v= query param) */
35
+ version?: string
36
+ /** Extension/relay protocol version sent during the additive query-string handshake. */
37
+ protocolVersion?: number
38
+ /** Optional features supported by this extension. Missing means a legacy connection. */
39
+ features?: string[]
40
+ }
41
+
42
+ export type ExtensionPendingRequest = {
43
+ resolve: (result: unknown) => void
44
+ reject: (error: Error) => void
45
+ }
46
+
47
+ /**
48
+ * Single aggregated extension object: domain state + runtime I/O.
49
+ */
50
+ export type ExtensionEntry = {
51
+ id: string
52
+ info: ExtensionInfo
53
+ stableKey: string
54
+ connectedTargets: Map<string, ConnectedTarget>
55
+ // Runtime I/O fields
56
+ ws: WSContext<WebSocket> | null
57
+ pendingRequests: Map<number, ExtensionPendingRequest>
58
+ messageId: number
59
+ pingInterval: ReturnType<typeof setInterval> | null
60
+ lastPongAt: number | null
61
+ }
62
+
63
+ export type PlaywrightClient = {
64
+ id: string
65
+ extensionId: string | null
66
+ ws: WSContext
67
+ }
68
+
69
+ export type RelayState = {
70
+ extensions: Map<string, ExtensionEntry>
71
+ playwrightClients: Map<string, PlaywrightClient>
72
+ }
73
+
74
+ export const EXTENSION_HEARTBEAT_TIMEOUT_MS = 15_000
75
+
76
+ export type ExtensionNegotiationStatus = {
77
+ connectionHealth: 'ready' | 'limited' | 'legacy'
78
+ missingFeatures: string[]
79
+ }
80
+
81
+ // ---------------------------------------------------------------------------
82
+ // Store factory
83
+ // ---------------------------------------------------------------------------
84
+
85
+ export function createRelayStore(): StoreApi<RelayState> {
86
+ return createStore<RelayState>(() => ({
87
+ extensions: new Map(),
88
+ playwrightClients: new Map(),
89
+ }))
90
+ }
91
+
92
+ // ---------------------------------------------------------------------------
93
+ // Derivation helpers
94
+ // ---------------------------------------------------------------------------
95
+
96
+ export function getExtensionNegotiationStatus(info: ExtensionInfo | undefined): ExtensionNegotiationStatus {
97
+ if (!info?.features) {
98
+ return { connectionHealth: 'legacy', missingFeatures: [] }
99
+ }
100
+ const missingFeatures = Object.values(EXTENSION_FEATURE).filter((feature) => {
101
+ return !info.features?.includes(feature)
102
+ })
103
+ return {
104
+ connectionHealth: missingFeatures.length === 0 ? 'ready' : 'limited',
105
+ missingFeatures,
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Linear scan over extensions to find one by stableKey. With <10 extensions this is free.
111
+ * Returns the LAST (newest) match because during reconnect both old and new connections
112
+ * coexist briefly. Map iteration order is insertion order, so last wins.
113
+ */
114
+ export function findExtensionByStableKey(state: RelayState, stableKey: string): ExtensionEntry | undefined {
115
+ let match: ExtensionEntry | undefined
116
+ for (const ext of state.extensions.values()) {
117
+ if (ext.stableKey === stableKey) {
118
+ match = ext
119
+ }
120
+ }
121
+ return match
122
+ }
123
+
124
+ export function buildStableExtensionKey(info: ExtensionInfo, connectionId: string): string {
125
+ // chrome.identity ids and emails identify the signed-in Google account, not
126
+ // the Chrome profile. Use the per-profile extension storage install id first
127
+ // so two profiles signed into the same account never replace each other.
128
+ if (info.installId) {
129
+ return `install:${info.browser || 'unknown'}:${info.installId}`
130
+ }
131
+ if (info.id) {
132
+ return `profile:${info.id}`
133
+ }
134
+ if (info.email) {
135
+ return `email:${info.email}`
136
+ }
137
+ if (info.browser) {
138
+ return `browser:${info.browser}`
139
+ }
140
+ return `connection:${connectionId}`
141
+ }
142
+
143
+ /** Find which extension owns a CDP tab sessionId (e.g. "pw-tab-1"). */
144
+ export function findExtensionIdByCdpSession(state: RelayState, cdpSessionId: string): string | null {
145
+ for (const [connectionId, ext] of state.extensions.entries()) {
146
+ if (ext.connectedTargets.has(cdpSessionId)) {
147
+ return connectionId
148
+ }
149
+ }
150
+ return null
151
+ }
152
+
153
+ export function hasExtensionHeartbeatExpired({
154
+ lastPongAt,
155
+ now,
156
+ timeoutMs = EXTENSION_HEARTBEAT_TIMEOUT_MS,
157
+ }: {
158
+ lastPongAt: number | null
159
+ now: number
160
+ timeoutMs?: number
161
+ }): boolean {
162
+ if (lastPongAt === null) {
163
+ return false
164
+ }
165
+ return now - lastPongAt > timeoutMs
166
+ }
167
+
168
+ // ---------------------------------------------------------------------------
169
+ // Pure state transition functions
170
+ //
171
+ // Each takes RelayState + event data and returns a new RelayState.
172
+ // No I/O, no side effects. Testable with data in / data out.
173
+ // ---------------------------------------------------------------------------
174
+
175
+ /**
176
+ * Add a new extension connection.
177
+ * Does NOT remove an existing connection with the same stableKey — that old
178
+ * connection stays routable until its WebSocket onClose fires and calls
179
+ * removeExtension(). This preserves in-flight message routing during reconnect.
180
+ * findExtensionByStableKey() returns the newest match so stableKey lookups
181
+ * resolve to the new connection immediately.
182
+ */
183
+ export function addExtension(
184
+ state: RelayState,
185
+ {
186
+ id,
187
+ info,
188
+ stableKey,
189
+ ws,
190
+ }: {
191
+ id: string
192
+ info: ExtensionInfo
193
+ stableKey: string
194
+ ws: WSContext<WebSocket> | null
195
+ },
196
+ ): RelayState {
197
+ const newExtensions = new Map(state.extensions)
198
+
199
+ newExtensions.set(id, {
200
+ id,
201
+ info,
202
+ stableKey,
203
+ connectedTargets: new Map(),
204
+ ws,
205
+ pendingRequests: new Map(),
206
+ messageId: 0,
207
+ pingInterval: null,
208
+ lastPongAt: null,
209
+ })
210
+ return { ...state, extensions: newExtensions }
211
+ }
212
+
213
+ /** Remove an extension, its targets, and any playwright clients bound to it. */
214
+ export function removeExtension(state: RelayState, { extensionId }: { extensionId: string }): RelayState {
215
+ if (!state.extensions.has(extensionId)) {
216
+ return state
217
+ }
218
+ const newExtensions = new Map(state.extensions)
219
+ newExtensions.delete(extensionId)
220
+
221
+ // Also remove playwright clients bound to this extension
222
+ const clientsToRemove = Array.from(state.playwrightClients.values())
223
+ .filter((client) => client.extensionId === extensionId)
224
+ if (clientsToRemove.length === 0) {
225
+ return { ...state, extensions: newExtensions }
226
+ }
227
+
228
+ const newClients = new Map(state.playwrightClients)
229
+ for (const client of clientsToRemove) {
230
+ newClients.delete(client.id)
231
+ }
232
+ return { ...state, extensions: newExtensions, playwrightClients: newClients }
233
+ }
234
+
235
+ /** Add a playwright client (state + ws handle co-located). */
236
+ export function addPlaywrightClient(
237
+ state: RelayState,
238
+ { id, extensionId, ws }: { id: string; extensionId: string | null; ws: WSContext },
239
+ ): RelayState {
240
+ const newClients = new Map(state.playwrightClients)
241
+ newClients.set(id, { id, extensionId, ws })
242
+ return { ...state, playwrightClients: newClients }
243
+ }
244
+
245
+ /** Remove a playwright client. */
246
+ export function removePlaywrightClient(state: RelayState, { clientId }: { clientId: string }): RelayState {
247
+ if (!state.playwrightClients.has(clientId)) {
248
+ return state
249
+ }
250
+ const newClients = new Map(state.playwrightClients)
251
+ newClients.delete(clientId)
252
+ return { ...state, playwrightClients: newClients }
253
+ }
254
+
255
+ /** Rebind all clients from one extension id to another. */
256
+ export function rebindClientsToExtension(
257
+ state: RelayState,
258
+ { fromExtensionId, toExtensionId }: { fromExtensionId: string; toExtensionId: string },
259
+ ): RelayState {
260
+ if (fromExtensionId === toExtensionId) {
261
+ return state
262
+ }
263
+
264
+ let updated = false
265
+ const newClients = new Map(state.playwrightClients)
266
+ for (const [clientId, client] of newClients) {
267
+ if (client.extensionId !== fromExtensionId) {
268
+ continue
269
+ }
270
+ newClients.set(clientId, { ...client, extensionId: toExtensionId })
271
+ updated = true
272
+ }
273
+
274
+ if (!updated) {
275
+ return state
276
+ }
277
+
278
+ return { ...state, playwrightClients: newClients }
279
+ }
280
+
281
+ /** Update an extension entry's I/O fields (ws, pingInterval, lastPongAt). */
282
+ export function updateExtensionIO(
283
+ state: RelayState,
284
+ {
285
+ extensionId,
286
+ ws,
287
+ pingInterval,
288
+ lastPongAt,
289
+ }: {
290
+ extensionId: string
291
+ ws?: WSContext<WebSocket> | null
292
+ pingInterval?: ReturnType<typeof setInterval> | null
293
+ lastPongAt?: number | null
294
+ },
295
+ ): RelayState {
296
+ const ext = state.extensions.get(extensionId)
297
+ if (!ext) {
298
+ return state
299
+ }
300
+ const newExtensions = new Map(state.extensions)
301
+ newExtensions.set(extensionId, {
302
+ ...ext,
303
+ ...(ws !== undefined ? { ws } : {}),
304
+ ...(pingInterval !== undefined ? { pingInterval } : {}),
305
+ ...(lastPongAt !== undefined ? { lastPongAt } : {}),
306
+ })
307
+ return { ...state, extensions: newExtensions }
308
+ }
309
+
310
+ /** Add or replace one pending extension request callback pair. */
311
+ export function addExtensionPendingRequest(
312
+ state: RelayState,
313
+ {
314
+ extensionId,
315
+ requestId,
316
+ pendingRequest,
317
+ }: {
318
+ extensionId: string
319
+ requestId: number
320
+ pendingRequest: ExtensionPendingRequest
321
+ },
322
+ ): RelayState {
323
+ const ext = state.extensions.get(extensionId)
324
+ if (!ext) {
325
+ return state
326
+ }
327
+
328
+ const pendingRequests = new Map(ext.pendingRequests)
329
+ pendingRequests.set(requestId, pendingRequest)
330
+ const newExtensions = new Map(state.extensions)
331
+ newExtensions.set(extensionId, { ...ext, pendingRequests })
332
+ return { ...state, extensions: newExtensions }
333
+ }
334
+
335
+ /** Remove one pending extension request callback pair. */
336
+ export function removeExtensionPendingRequest(
337
+ state: RelayState,
338
+ { extensionId, requestId }: { extensionId: string; requestId: number },
339
+ ): RelayState {
340
+ const ext = state.extensions.get(extensionId)
341
+ if (!ext || !ext.pendingRequests.has(requestId)) {
342
+ return state
343
+ }
344
+
345
+ const pendingRequests = new Map(ext.pendingRequests)
346
+ pendingRequests.delete(requestId)
347
+ const newExtensions = new Map(state.extensions)
348
+ newExtensions.set(extensionId, { ...ext, pendingRequests })
349
+ return { ...state, extensions: newExtensions }
350
+ }
351
+
352
+ /** Add a target to an extension's connectedTargets. No-op if extension doesn't exist. */
353
+ export function addTarget(
354
+ state: RelayState,
355
+ {
356
+ extensionId,
357
+ sessionId,
358
+ targetId,
359
+ targetInfo,
360
+ existingFrameIds,
361
+ }: {
362
+ extensionId: string
363
+ sessionId: string
364
+ targetId: string
365
+ targetInfo: Protocol.Target.TargetInfo
366
+ /** Preserve existing frameIds if target already existed (update scenario). */
367
+ existingFrameIds?: Set<string>
368
+ },
369
+ ): RelayState {
370
+ const ext = state.extensions.get(extensionId)
371
+ if (!ext) {
372
+ return state
373
+ }
374
+
375
+ const existingTarget = ext.connectedTargets.get(sessionId)
376
+ const newTargets = new Map(ext.connectedTargets)
377
+ newTargets.set(sessionId, {
378
+ sessionId,
379
+ targetId,
380
+ targetInfo,
381
+ frameIds: existingFrameIds ?? existingTarget?.frameIds ?? new Set(),
382
+ })
383
+
384
+ const newExtensions = new Map(state.extensions)
385
+ newExtensions.set(extensionId, { ...ext, connectedTargets: newTargets })
386
+ return { ...state, extensions: newExtensions }
387
+ }
388
+
389
+ /** Remove a target by sessionId. No-op if extension or target doesn't exist. */
390
+ export function removeTarget(
391
+ state: RelayState,
392
+ { extensionId, sessionId }: { extensionId: string; sessionId: string },
393
+ ): RelayState {
394
+ const ext = state.extensions.get(extensionId)
395
+ if (!ext || !ext.connectedTargets.has(sessionId)) {
396
+ return state
397
+ }
398
+
399
+ const newTargets = new Map(ext.connectedTargets)
400
+ newTargets.delete(sessionId)
401
+
402
+ const newExtensions = new Map(state.extensions)
403
+ newExtensions.set(extensionId, { ...ext, connectedTargets: newTargets })
404
+ return { ...state, extensions: newExtensions }
405
+ }
406
+
407
+ /** Remove a crashed target by targetId (not sessionId). */
408
+ export function removeTargetByCrash(
409
+ state: RelayState,
410
+ { extensionId, targetId }: { extensionId: string; targetId: string },
411
+ ): RelayState {
412
+ const ext = state.extensions.get(extensionId)
413
+ if (!ext) {
414
+ return state
415
+ }
416
+
417
+ let found = false
418
+ const newTargets = new Map(ext.connectedTargets)
419
+ for (const [sid, target] of newTargets) {
420
+ if (target.targetId === targetId) {
421
+ newTargets.delete(sid)
422
+ found = true
423
+ break
424
+ }
425
+ }
426
+
427
+ if (!found) {
428
+ return state
429
+ }
430
+
431
+ const newExtensions = new Map(state.extensions)
432
+ newExtensions.set(extensionId, { ...ext, connectedTargets: newTargets })
433
+ return { ...state, extensions: newExtensions }
434
+ }
435
+
436
+ /** Update targetInfo on a target matched by targetId. */
437
+ export function updateTargetInfo(
438
+ state: RelayState,
439
+ { extensionId, targetInfo }: { extensionId: string; targetInfo: Protocol.Target.TargetInfo },
440
+ ): RelayState {
441
+ const ext = state.extensions.get(extensionId)
442
+ if (!ext) {
443
+ return state
444
+ }
445
+
446
+ let updated = false
447
+ const newTargets = new Map(ext.connectedTargets)
448
+ for (const [sid, target] of newTargets) {
449
+ if (target.targetId === targetInfo.targetId) {
450
+ newTargets.set(sid, { ...target, targetInfo })
451
+ updated = true
452
+ break
453
+ }
454
+ }
455
+
456
+ if (!updated) {
457
+ return state
458
+ }
459
+
460
+ const newExtensions = new Map(state.extensions)
461
+ newExtensions.set(extensionId, { ...ext, connectedTargets: newTargets })
462
+ return { ...state, extensions: newExtensions }
463
+ }
464
+
465
+ /** Add a frameId to a target's frameIds set. */
466
+ export function addFrameId(
467
+ state: RelayState,
468
+ { extensionId, sessionId, frameId }: { extensionId: string; sessionId: string; frameId: string },
469
+ ): RelayState {
470
+ const ext = state.extensions.get(extensionId)
471
+ if (!ext) {
472
+ return state
473
+ }
474
+ const target = ext.connectedTargets.get(sessionId)
475
+ if (!target) {
476
+ return state
477
+ }
478
+
479
+ // Already present — no-op
480
+ if (target.frameIds.has(frameId)) {
481
+ return state
482
+ }
483
+
484
+ const newFrameIds = new Set(target.frameIds)
485
+ newFrameIds.add(frameId)
486
+
487
+ const newTargets = new Map(ext.connectedTargets)
488
+ newTargets.set(sessionId, { ...target, frameIds: newFrameIds })
489
+
490
+ const newExtensions = new Map(state.extensions)
491
+ newExtensions.set(extensionId, { ...ext, connectedTargets: newTargets })
492
+ return { ...state, extensions: newExtensions }
493
+ }
494
+
495
+ /** Remove a frameId from the target that owns it (scans all targets in the extension). */
496
+ export function removeFrameId(
497
+ state: RelayState,
498
+ { extensionId, frameId }: { extensionId: string; frameId: string },
499
+ ): RelayState {
500
+ const ext = state.extensions.get(extensionId)
501
+ if (!ext) {
502
+ return state
503
+ }
504
+
505
+ for (const [sid, target] of ext.connectedTargets) {
506
+ if (target.frameIds.has(frameId)) {
507
+ const newFrameIds = new Set(target.frameIds)
508
+ newFrameIds.delete(frameId)
509
+
510
+ const newTargets = new Map(ext.connectedTargets)
511
+ newTargets.set(sid, { ...target, frameIds: newFrameIds })
512
+
513
+ const newExtensions = new Map(state.extensions)
514
+ newExtensions.set(extensionId, { ...ext, connectedTargets: newTargets })
515
+ return { ...state, extensions: newExtensions }
516
+ }
517
+ }
518
+
519
+ return state
520
+ }
521
+
522
+ /**
523
+ * Update URL (and optionally title) on a target.
524
+ * Used by Page.frameNavigated (top-level) and Page.navigatedWithinDocument.
525
+ */
526
+ export function updateTargetUrl(
527
+ state: RelayState,
528
+ {
529
+ extensionId,
530
+ sessionId,
531
+ url,
532
+ title,
533
+ }: {
534
+ extensionId: string
535
+ sessionId: string
536
+ url: string
537
+ title?: string
538
+ },
539
+ ): RelayState {
540
+ const ext = state.extensions.get(extensionId)
541
+ if (!ext) {
542
+ return state
543
+ }
544
+ const target = ext.connectedTargets.get(sessionId)
545
+ if (!target) {
546
+ return state
547
+ }
548
+
549
+ const newTargetInfo = {
550
+ ...target.targetInfo,
551
+ url,
552
+ ...(title !== undefined ? { title } : {}),
553
+ }
554
+
555
+ const newTargets = new Map(ext.connectedTargets)
556
+ newTargets.set(sessionId, { ...target, targetInfo: newTargetInfo })
557
+
558
+ const newExtensions = new Map(state.extensions)
559
+ newExtensions.set(extensionId, { ...ext, connectedTargets: newTargets })
560
+ return { ...state, extensions: newExtensions }
561
+ }