tabwright 1.0.0 → 2.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 (568) hide show
  1. package/dist/agent-skills/tabwright/SKILL.md +3 -0
  2. package/dist/aria-snapshot.d.ts +0 -1
  3. package/dist/aria-snapshot.js +9 -1
  4. package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.d.ts +0 -1
  5. package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.js +0 -1
  6. package/dist/bippy.js +5 -5
  7. package/dist/browser-config.d.ts +0 -1
  8. package/dist/browser-config.js +0 -1
  9. package/dist/browser-install.d.ts +0 -1
  10. package/dist/browser-install.js +0 -1
  11. package/dist/browser-launch.d.ts +0 -1
  12. package/dist/browser-launch.js +0 -1
  13. package/dist/capability-agent-skill.d.ts +0 -1
  14. package/dist/capability-agent-skill.js +0 -1
  15. package/dist/capability-auth-state.d.ts +0 -1
  16. package/dist/capability-auth-state.js +0 -1
  17. package/dist/capability-auth.d.ts +0 -1
  18. package/dist/capability-auth.js +0 -1
  19. package/dist/capability-options.d.ts +0 -1
  20. package/dist/capability-options.js +0 -1
  21. package/dist/capability-package.d.ts +0 -1
  22. package/dist/capability-package.js +47 -2
  23. package/dist/capability-registry.d.ts +0 -1
  24. package/dist/capability-registry.js +0 -1
  25. package/dist/capability-runner.d.ts +0 -1
  26. package/dist/capability-runner.js +0 -1
  27. package/dist/capability-studio.d.ts +0 -1
  28. package/dist/capability-studio.js +0 -1
  29. package/dist/cdp-log.d.ts +0 -1
  30. package/dist/cdp-log.js +0 -1
  31. package/dist/cdp-relay.d.ts +0 -1
  32. package/dist/cdp-relay.js +0 -1
  33. package/dist/cdp-session.d.ts +0 -1
  34. package/dist/cdp-session.js +0 -1
  35. package/dist/cdp-types.d.ts +0 -1
  36. package/dist/cdp-types.js +0 -1
  37. package/dist/chrome-discovery.d.ts +0 -1
  38. package/dist/chrome-discovery.js +0 -1
  39. package/dist/clean-html.d.ts +0 -1
  40. package/dist/clean-html.js +0 -1
  41. package/dist/cli.d.ts +0 -1
  42. package/dist/cli.js +10 -56
  43. package/dist/cloud-client.d.ts +0 -1
  44. package/dist/cloud-client.js +0 -1
  45. package/dist/create-logger.d.ts +0 -1
  46. package/dist/create-logger.js +0 -1
  47. package/dist/debugger-examples-types.d.ts +0 -1
  48. package/dist/debugger-examples-types.js +0 -1
  49. package/dist/debugger-examples.d.ts +0 -1
  50. package/dist/debugger-examples.js +0 -1
  51. package/dist/debugger.d.ts +0 -1
  52. package/dist/debugger.js +0 -1
  53. package/dist/diff-utils.d.ts +0 -1
  54. package/dist/diff-utils.js +0 -1
  55. package/dist/doctor.d.ts +0 -1
  56. package/dist/doctor.js +5 -7
  57. package/dist/editor-examples.d.ts +0 -1
  58. package/dist/editor-examples.js +0 -1
  59. package/dist/editor.d.ts +0 -1
  60. package/dist/editor.js +0 -1
  61. package/dist/env-compat.d.ts +0 -1
  62. package/dist/env-compat.js +0 -1
  63. package/dist/executor.d.ts +0 -1
  64. package/dist/executor.js +1 -2
  65. package/dist/extension/background.js +10 -6
  66. package/dist/extension/manifest.json +1 -1
  67. package/dist/extension/options.js +1 -1
  68. package/dist/extension/rrweb-recorder.js +1 -1
  69. package/dist/ghost-browser.d.ts +0 -1
  70. package/dist/ghost-browser.js +0 -1
  71. package/dist/ghost-cursor-controller.d.ts +0 -1
  72. package/dist/ghost-cursor-controller.js +0 -1
  73. package/dist/ghost-cursor.d.ts +0 -1
  74. package/dist/ghost-cursor.js +0 -1
  75. package/dist/htmlrewrite.d.ts +0 -1
  76. package/dist/htmlrewrite.js +0 -1
  77. package/dist/index.d.ts +0 -1
  78. package/dist/index.js +0 -1
  79. package/dist/kill-port.d.ts +0 -1
  80. package/dist/kill-port.js +0 -1
  81. package/dist/kitty-graphics.d.ts +0 -1
  82. package/dist/kitty-graphics.js +0 -1
  83. package/dist/mcp.d.ts +0 -1
  84. package/dist/mcp.js +0 -1
  85. package/dist/package-paths.d.ts +0 -1
  86. package/dist/package-paths.js +0 -1
  87. package/dist/page-markdown.d.ts +0 -1
  88. package/dist/page-markdown.js +0 -1
  89. package/dist/performance-examples.d.ts +0 -1
  90. package/dist/performance-examples.js +0 -1
  91. package/dist/playwright-import.d.ts +0 -1
  92. package/dist/playwright-import.js +0 -1
  93. package/dist/product-paths.d.ts +0 -1
  94. package/dist/product-paths.js +0 -1
  95. package/dist/protocol.d.ts +0 -1
  96. package/dist/protocol.js +0 -1
  97. package/dist/react-source.d.ts +0 -1
  98. package/dist/react-source.js +0 -1
  99. package/dist/readability.js +4 -4
  100. package/dist/relay-client.d.ts +0 -1
  101. package/dist/relay-client.js +0 -1
  102. package/dist/relay-state.d.ts +0 -1
  103. package/dist/relay-state.js +0 -1
  104. package/dist/replay-ai-index.d.ts +0 -1
  105. package/dist/replay-ai-index.js +0 -1
  106. package/dist/replay-eval.d.ts +0 -1
  107. package/dist/replay-eval.js +0 -1
  108. package/dist/replay-handoff.d.ts +0 -1
  109. package/dist/replay-handoff.js +0 -1
  110. package/dist/replay-workflow-compiler.d.ts +0 -1
  111. package/dist/replay-workflow-compiler.js +0 -1
  112. package/dist/rrweb-recording-relay.d.ts +0 -1
  113. package/dist/rrweb-recording-relay.js +0 -1
  114. package/dist/rrweb-recording.d.ts +0 -1
  115. package/dist/rrweb-recording.js +0 -1
  116. package/dist/scoped-fs.d.ts +0 -1
  117. package/dist/scoped-fs.js +0 -1
  118. package/dist/selector-generator.js +2 -2
  119. package/dist/start-relay-server.d.ts +0 -1
  120. package/dist/start-relay-server.js +0 -1
  121. package/dist/styles-examples.d.ts +0 -1
  122. package/dist/styles-examples.js +0 -1
  123. package/dist/styles.d.ts +0 -1
  124. package/dist/styles.js +0 -1
  125. package/dist/tabwright-agent-skill.d.ts +0 -1
  126. package/dist/tabwright-agent-skill.js +0 -1
  127. package/dist/test-declarations.d.ts +0 -1
  128. package/dist/test-declarations.js +0 -1
  129. package/dist/utils.d.ts +0 -1
  130. package/dist/utils.js +2 -2
  131. package/dist/wait-for-page-load.d.ts +0 -1
  132. package/dist/wait-for-page-load.js +0 -1
  133. package/dist/workflow-capability.d.ts +0 -1
  134. package/dist/workflow-capability.js +0 -1
  135. package/package.json +8 -4
  136. package/readme.md +43 -0
  137. package/src/skill.md +5 -2
  138. package/dist/aria-snapshot.d.ts.map +0 -1
  139. package/dist/aria-snapshot.js.map +0 -1
  140. package/dist/aria-snapshot.test.d.ts +0 -2
  141. package/dist/aria-snapshot.test.d.ts.map +0 -1
  142. package/dist/aria-snapshot.test.js +0 -270
  143. package/dist/aria-snapshot.test.js.map +0 -1
  144. package/dist/aria-snapshot.unit.test.d.ts +0 -2
  145. package/dist/aria-snapshot.unit.test.d.ts.map +0 -1
  146. package/dist/aria-snapshot.unit.test.js +0 -542
  147. package/dist/aria-snapshot.unit.test.js.map +0 -1
  148. package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.d.ts.map +0 -1
  149. package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.js.map +0 -1
  150. package/dist/browser-config.d.ts.map +0 -1
  151. package/dist/browser-config.js.map +0 -1
  152. package/dist/browser-install.d.ts.map +0 -1
  153. package/dist/browser-install.js.map +0 -1
  154. package/dist/browser-launch.d.ts.map +0 -1
  155. package/dist/browser-launch.js.map +0 -1
  156. package/dist/builtin-capabilities.d.ts +0 -28
  157. package/dist/builtin-capabilities.d.ts.map +0 -1
  158. package/dist/builtin-capabilities.js +0 -2673
  159. package/dist/builtin-capabilities.js.map +0 -1
  160. package/dist/capability-agent-skill.d.ts.map +0 -1
  161. package/dist/capability-agent-skill.js.map +0 -1
  162. package/dist/capability-auth-state.d.ts.map +0 -1
  163. package/dist/capability-auth-state.js.map +0 -1
  164. package/dist/capability-auth.d.ts.map +0 -1
  165. package/dist/capability-auth.js.map +0 -1
  166. package/dist/capability-cli-confirmation.test.d.ts +0 -2
  167. package/dist/capability-cli-confirmation.test.d.ts.map +0 -1
  168. package/dist/capability-cli-confirmation.test.js +0 -79
  169. package/dist/capability-cli-confirmation.test.js.map +0 -1
  170. package/dist/capability-options.d.ts.map +0 -1
  171. package/dist/capability-options.js.map +0 -1
  172. package/dist/capability-options.test.d.ts +0 -2
  173. package/dist/capability-options.test.d.ts.map +0 -1
  174. package/dist/capability-options.test.js +0 -81
  175. package/dist/capability-options.test.js.map +0 -1
  176. package/dist/capability-package.d.ts.map +0 -1
  177. package/dist/capability-package.js.map +0 -1
  178. package/dist/capability-package.test.d.ts +0 -2
  179. package/dist/capability-package.test.d.ts.map +0 -1
  180. package/dist/capability-package.test.js +0 -179
  181. package/dist/capability-package.test.js.map +0 -1
  182. package/dist/capability-registry.d.ts.map +0 -1
  183. package/dist/capability-registry.js.map +0 -1
  184. package/dist/capability-registry.test.d.ts +0 -2
  185. package/dist/capability-registry.test.d.ts.map +0 -1
  186. package/dist/capability-registry.test.js +0 -1683
  187. package/dist/capability-registry.test.js.map +0 -1
  188. package/dist/capability-runner.d.ts.map +0 -1
  189. package/dist/capability-runner.js.map +0 -1
  190. package/dist/capability-search-relevance.test.d.ts +0 -2
  191. package/dist/capability-search-relevance.test.d.ts.map +0 -1
  192. package/dist/capability-search-relevance.test.js +0 -67
  193. package/dist/capability-search-relevance.test.js.map +0 -1
  194. package/dist/capability-studio.d.ts.map +0 -1
  195. package/dist/capability-studio.js.map +0 -1
  196. package/dist/capability-studio.test.d.ts +0 -2
  197. package/dist/capability-studio.test.d.ts.map +0 -1
  198. package/dist/capability-studio.test.js +0 -41
  199. package/dist/capability-studio.test.js.map +0 -1
  200. package/dist/cdp-log.d.ts.map +0 -1
  201. package/dist/cdp-log.js.map +0 -1
  202. package/dist/cdp-log.test.d.ts +0 -2
  203. package/dist/cdp-log.test.d.ts.map +0 -1
  204. package/dist/cdp-log.test.js +0 -109
  205. package/dist/cdp-log.test.js.map +0 -1
  206. package/dist/cdp-relay.d.ts.map +0 -1
  207. package/dist/cdp-relay.js.map +0 -1
  208. package/dist/cdp-session.d.ts.map +0 -1
  209. package/dist/cdp-session.js.map +0 -1
  210. package/dist/cdp-types.d.ts.map +0 -1
  211. package/dist/cdp-types.js.map +0 -1
  212. package/dist/channel-owner-inspect.test.d.ts +0 -2
  213. package/dist/channel-owner-inspect.test.d.ts.map +0 -1
  214. package/dist/channel-owner-inspect.test.js +0 -75
  215. package/dist/channel-owner-inspect.test.js.map +0 -1
  216. package/dist/chrome-discovery.d.ts.map +0 -1
  217. package/dist/chrome-discovery.js.map +0 -1
  218. package/dist/chrome-discovery.test.d.ts +0 -2
  219. package/dist/chrome-discovery.test.d.ts.map +0 -1
  220. package/dist/chrome-discovery.test.js +0 -41
  221. package/dist/chrome-discovery.test.js.map +0 -1
  222. package/dist/clean-html.d.ts.map +0 -1
  223. package/dist/clean-html.js.map +0 -1
  224. package/dist/cli-help.test.d.ts +0 -2
  225. package/dist/cli-help.test.d.ts.map +0 -1
  226. package/dist/cli-help.test.js +0 -98
  227. package/dist/cli-help.test.js.map +0 -1
  228. package/dist/cli.d.ts.map +0 -1
  229. package/dist/cli.js.map +0 -1
  230. package/dist/cloud-client.d.ts.map +0 -1
  231. package/dist/cloud-client.js.map +0 -1
  232. package/dist/create-logger.d.ts.map +0 -1
  233. package/dist/create-logger.js.map +0 -1
  234. package/dist/debugger-examples-types.d.ts.map +0 -1
  235. package/dist/debugger-examples-types.js.map +0 -1
  236. package/dist/debugger-examples.d.ts.map +0 -1
  237. package/dist/debugger-examples.js.map +0 -1
  238. package/dist/debugger.d.ts.map +0 -1
  239. package/dist/debugger.js.map +0 -1
  240. package/dist/diff-utils.d.ts.map +0 -1
  241. package/dist/diff-utils.js.map +0 -1
  242. package/dist/diff-utils.test.d.ts +0 -2
  243. package/dist/diff-utils.test.d.ts.map +0 -1
  244. package/dist/diff-utils.test.js +0 -137
  245. package/dist/diff-utils.test.js.map +0 -1
  246. package/dist/doctor.d.ts.map +0 -1
  247. package/dist/doctor.js.map +0 -1
  248. package/dist/doctor.test.d.ts +0 -2
  249. package/dist/doctor.test.d.ts.map +0 -1
  250. package/dist/doctor.test.js +0 -208
  251. package/dist/doctor.test.js.map +0 -1
  252. package/dist/editor-examples.d.ts.map +0 -1
  253. package/dist/editor-examples.js.map +0 -1
  254. package/dist/editor.d.ts.map +0 -1
  255. package/dist/editor.js.map +0 -1
  256. package/dist/env-compat.d.ts.map +0 -1
  257. package/dist/env-compat.js.map +0 -1
  258. package/dist/executor.d.ts.map +0 -1
  259. package/dist/executor.js.map +0 -1
  260. package/dist/executor.unit.test.d.ts +0 -2
  261. package/dist/executor.unit.test.d.ts.map +0 -1
  262. package/dist/executor.unit.test.js +0 -143
  263. package/dist/executor.unit.test.js.map +0 -1
  264. package/dist/extension-connection.test.d.ts +0 -2
  265. package/dist/extension-connection.test.d.ts.map +0 -1
  266. package/dist/extension-connection.test.js +0 -708
  267. package/dist/extension-connection.test.js.map +0 -1
  268. package/dist/extension-icon-warning.test.d.ts +0 -2
  269. package/dist/extension-icon-warning.test.d.ts.map +0 -1
  270. package/dist/extension-icon-warning.test.js +0 -33
  271. package/dist/extension-icon-warning.test.js.map +0 -1
  272. package/dist/ghost-browser.d.ts.map +0 -1
  273. package/dist/ghost-browser.js.map +0 -1
  274. package/dist/ghost-cursor-controller.d.ts.map +0 -1
  275. package/dist/ghost-cursor-controller.js.map +0 -1
  276. package/dist/ghost-cursor.d.ts.map +0 -1
  277. package/dist/ghost-cursor.js.map +0 -1
  278. package/dist/htmlrewrite.d.ts.map +0 -1
  279. package/dist/htmlrewrite.js.map +0 -1
  280. package/dist/htmlrewrite.test.d.ts +0 -2
  281. package/dist/htmlrewrite.test.d.ts.map +0 -1
  282. package/dist/htmlrewrite.test.js +0 -7975
  283. package/dist/htmlrewrite.test.js.map +0 -1
  284. package/dist/index.d.ts.map +0 -1
  285. package/dist/index.js.map +0 -1
  286. package/dist/kill-port.d.ts.map +0 -1
  287. package/dist/kill-port.js.map +0 -1
  288. package/dist/kitty-graphics.d.ts.map +0 -1
  289. package/dist/kitty-graphics.js.map +0 -1
  290. package/dist/kitty-graphics.test.d.ts +0 -2
  291. package/dist/kitty-graphics.test.d.ts.map +0 -1
  292. package/dist/kitty-graphics.test.js +0 -125
  293. package/dist/kitty-graphics.test.js.map +0 -1
  294. package/dist/locator-selector.test.d.ts +0 -2
  295. package/dist/locator-selector.test.d.ts.map +0 -1
  296. package/dist/locator-selector.test.js +0 -98
  297. package/dist/locator-selector.test.js.map +0 -1
  298. package/dist/mcp-client.d.ts +0 -20
  299. package/dist/mcp-client.d.ts.map +0 -1
  300. package/dist/mcp-client.js +0 -56
  301. package/dist/mcp-client.js.map +0 -1
  302. package/dist/mcp.d.ts.map +0 -1
  303. package/dist/mcp.js.map +0 -1
  304. package/dist/on-mouse-action.test.d.ts +0 -2
  305. package/dist/on-mouse-action.test.d.ts.map +0 -1
  306. package/dist/on-mouse-action.test.js +0 -180
  307. package/dist/on-mouse-action.test.js.map +0 -1
  308. package/dist/options-page.test.d.ts +0 -2
  309. package/dist/options-page.test.d.ts.map +0 -1
  310. package/dist/options-page.test.js +0 -773
  311. package/dist/options-page.test.js.map +0 -1
  312. package/dist/package-paths.d.ts.map +0 -1
  313. package/dist/package-paths.js.map +0 -1
  314. package/dist/page-markdown.d.ts.map +0 -1
  315. package/dist/page-markdown.js.map +0 -1
  316. package/dist/performance-examples.d.ts.map +0 -1
  317. package/dist/performance-examples.js.map +0 -1
  318. package/dist/playwright-import.d.ts.map +0 -1
  319. package/dist/playwright-import.js.map +0 -1
  320. package/dist/popup-relocation.test.d.ts +0 -7
  321. package/dist/popup-relocation.test.d.ts.map +0 -1
  322. package/dist/popup-relocation.test.js +0 -139
  323. package/dist/popup-relocation.test.js.map +0 -1
  324. package/dist/product-paths.d.ts.map +0 -1
  325. package/dist/product-paths.js.map +0 -1
  326. package/dist/product-paths.test.d.ts +0 -2
  327. package/dist/product-paths.test.d.ts.map +0 -1
  328. package/dist/product-paths.test.js +0 -39
  329. package/dist/product-paths.test.js.map +0 -1
  330. package/dist/protocol.d.ts.map +0 -1
  331. package/dist/protocol.js.map +0 -1
  332. package/dist/protocol.test.d.ts +0 -2
  333. package/dist/protocol.test.d.ts.map +0 -1
  334. package/dist/protocol.test.js +0 -31
  335. package/dist/protocol.test.js.map +0 -1
  336. package/dist/react-source.d.ts.map +0 -1
  337. package/dist/react-source.js.map +0 -1
  338. package/dist/relay-client.d.ts.map +0 -1
  339. package/dist/relay-client.js.map +0 -1
  340. package/dist/relay-client.test.d.ts +0 -2
  341. package/dist/relay-client.test.d.ts.map +0 -1
  342. package/dist/relay-client.test.js +0 -305
  343. package/dist/relay-client.test.js.map +0 -1
  344. package/dist/relay-core.test.d.ts +0 -2
  345. package/dist/relay-core.test.d.ts.map +0 -1
  346. package/dist/relay-core.test.js +0 -1427
  347. package/dist/relay-core.test.js.map +0 -1
  348. package/dist/relay-navigation.test.d.ts +0 -2
  349. package/dist/relay-navigation.test.d.ts.map +0 -1
  350. package/dist/relay-navigation.test.js +0 -661
  351. package/dist/relay-navigation.test.js.map +0 -1
  352. package/dist/relay-session.test.d.ts +0 -2
  353. package/dist/relay-session.test.d.ts.map +0 -1
  354. package/dist/relay-session.test.js +0 -1121
  355. package/dist/relay-session.test.js.map +0 -1
  356. package/dist/relay-state.d.ts.map +0 -1
  357. package/dist/relay-state.js.map +0 -1
  358. package/dist/relay-state.test.d.ts +0 -2
  359. package/dist/relay-state.test.d.ts.map +0 -1
  360. package/dist/relay-state.test.js +0 -594
  361. package/dist/relay-state.test.js.map +0 -1
  362. package/dist/replay-ai-index.d.ts.map +0 -1
  363. package/dist/replay-ai-index.js.map +0 -1
  364. package/dist/replay-ai-index.test.d.ts +0 -2
  365. package/dist/replay-ai-index.test.d.ts.map +0 -1
  366. package/dist/replay-ai-index.test.js +0 -255
  367. package/dist/replay-ai-index.test.js.map +0 -1
  368. package/dist/replay-cli.test.d.ts +0 -2
  369. package/dist/replay-cli.test.d.ts.map +0 -1
  370. package/dist/replay-cli.test.js +0 -275
  371. package/dist/replay-cli.test.js.map +0 -1
  372. package/dist/replay-eval.d.ts.map +0 -1
  373. package/dist/replay-eval.js.map +0 -1
  374. package/dist/replay-handoff.d.ts.map +0 -1
  375. package/dist/replay-handoff.js.map +0 -1
  376. package/dist/replay-handoff.test.d.ts +0 -2
  377. package/dist/replay-handoff.test.d.ts.map +0 -1
  378. package/dist/replay-handoff.test.js +0 -123
  379. package/dist/replay-handoff.test.js.map +0 -1
  380. package/dist/replay-workflow-compiler.d.ts.map +0 -1
  381. package/dist/replay-workflow-compiler.js.map +0 -1
  382. package/dist/replay-workflow-compiler.test.d.ts +0 -2
  383. package/dist/replay-workflow-compiler.test.d.ts.map +0 -1
  384. package/dist/replay-workflow-compiler.test.js +0 -223
  385. package/dist/replay-workflow-compiler.test.js.map +0 -1
  386. package/dist/rrweb-recording-relay.d.ts.map +0 -1
  387. package/dist/rrweb-recording-relay.js.map +0 -1
  388. package/dist/rrweb-recording-relay.test.d.ts +0 -2
  389. package/dist/rrweb-recording-relay.test.d.ts.map +0 -1
  390. package/dist/rrweb-recording-relay.test.js +0 -85
  391. package/dist/rrweb-recording-relay.test.js.map +0 -1
  392. package/dist/rrweb-recording.d.ts.map +0 -1
  393. package/dist/rrweb-recording.js.map +0 -1
  394. package/dist/scoped-fs.d.ts.map +0 -1
  395. package/dist/scoped-fs.js.map +0 -1
  396. package/dist/scoped-fs.test.d.ts +0 -5
  397. package/dist/scoped-fs.test.d.ts.map +0 -1
  398. package/dist/scoped-fs.test.js +0 -73
  399. package/dist/scoped-fs.test.js.map +0 -1
  400. package/dist/skill-stub.test.d.ts +0 -2
  401. package/dist/skill-stub.test.d.ts.map +0 -1
  402. package/dist/skill-stub.test.js +0 -22
  403. package/dist/skill-stub.test.js.map +0 -1
  404. package/dist/snapshot-tools.test.d.ts +0 -2
  405. package/dist/snapshot-tools.test.d.ts.map +0 -1
  406. package/dist/snapshot-tools.test.js +0 -856
  407. package/dist/snapshot-tools.test.js.map +0 -1
  408. package/dist/start-relay-server.d.ts.map +0 -1
  409. package/dist/start-relay-server.js.map +0 -1
  410. package/dist/styles-examples.d.ts.map +0 -1
  411. package/dist/styles-examples.js.map +0 -1
  412. package/dist/styles.d.ts.map +0 -1
  413. package/dist/styles.js.map +0 -1
  414. package/dist/tabwright-agent-skill.d.ts.map +0 -1
  415. package/dist/tabwright-agent-skill.js.map +0 -1
  416. package/dist/tabwright-agent-skill.test.d.ts +0 -2
  417. package/dist/tabwright-agent-skill.test.d.ts.map +0 -1
  418. package/dist/tabwright-agent-skill.test.js +0 -51
  419. package/dist/tabwright-agent-skill.test.js.map +0 -1
  420. package/dist/test-declarations.d.ts.map +0 -1
  421. package/dist/test-declarations.js.map +0 -1
  422. package/dist/test-utils.d.ts +0 -69
  423. package/dist/test-utils.d.ts.map +0 -1
  424. package/dist/test-utils.js +0 -448
  425. package/dist/test-utils.js.map +0 -1
  426. package/dist/test-utils.test.d.ts +0 -2
  427. package/dist/test-utils.test.d.ts.map +0 -1
  428. package/dist/test-utils.test.js +0 -55
  429. package/dist/test-utils.test.js.map +0 -1
  430. package/dist/utils.d.ts.map +0 -1
  431. package/dist/utils.js.map +0 -1
  432. package/dist/wait-for-page-load.d.ts.map +0 -1
  433. package/dist/wait-for-page-load.js.map +0 -1
  434. package/dist/workflow-capability.d.ts.map +0 -1
  435. package/dist/workflow-capability.js.map +0 -1
  436. package/dist/workflow-script-flow.test.d.ts +0 -2
  437. package/dist/workflow-script-flow.test.d.ts.map +0 -1
  438. package/dist/workflow-script-flow.test.js +0 -285
  439. package/dist/workflow-script-flow.test.js.map +0 -1
  440. package/src/__snapshots__/x.com.processed.html +0 -1003
  441. package/src/__snapshots__/x.com.processed.withStyles.html +0 -2720
  442. package/src/a11y-client.ts +0 -241
  443. package/src/agent-skills/conan-config/SKILL.md +0 -141
  444. package/src/agent-skills/conan-config/agents/openai.yaml +0 -4
  445. package/src/aria-snapshot.test.ts +0 -311
  446. package/src/aria-snapshot.ts +0 -1681
  447. package/src/aria-snapshot.unit.test.ts +0 -615
  448. package/src/aria-snapshots/github-interactive.txt +0 -193
  449. package/src/aria-snapshots/github-raw.txt +0 -309
  450. package/src/aria-snapshots/hackernews-interactive.txt +0 -477
  451. package/src/aria-snapshots/hackernews-raw.txt +0 -428
  452. package/src/aria-snapshots/prosemirror-interactive.txt +0 -66
  453. package/src/aria-snapshots/prosemirror-raw.txt +0 -145
  454. package/src/assets/aria-labels-hacker-news.png +0 -0
  455. package/src/assets/aria-labels-old-reddit.png +0 -0
  456. package/src/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.ts +0 -5
  457. package/src/assets/cursors/screen-studio/pointer-macos-tahoe.svg +0 -18
  458. package/src/assets/x.com.html +0 -32946
  459. package/src/browser-config.ts +0 -179
  460. package/src/browser-install.ts +0 -284
  461. package/src/browser-launch.ts +0 -75
  462. package/src/builtin-capabilities.ts +0 -2765
  463. package/src/capability-agent-skill.ts +0 -305
  464. package/src/capability-auth-state.ts +0 -197
  465. package/src/capability-auth.ts +0 -249
  466. package/src/capability-cli-confirmation.test.ts +0 -90
  467. package/src/capability-options.test.ts +0 -89
  468. package/src/capability-options.ts +0 -57
  469. package/src/capability-package.test.ts +0 -204
  470. package/src/capability-package.ts +0 -555
  471. package/src/capability-registry.test.ts +0 -1905
  472. package/src/capability-registry.ts +0 -1234
  473. package/src/capability-runner.ts +0 -801
  474. package/src/capability-search-relevance.test.ts +0 -73
  475. package/src/capability-studio.test.ts +0 -45
  476. package/src/capability-studio.ts +0 -641
  477. package/src/cdp-log.test.ts +0 -131
  478. package/src/cdp-log.ts +0 -112
  479. package/src/cdp-relay.ts +0 -2944
  480. package/src/cdp-session.ts +0 -77
  481. package/src/cdp-types.ts +0 -158
  482. package/src/channel-owner-inspect.test.ts +0 -94
  483. package/src/chrome-discovery.test.ts +0 -50
  484. package/src/chrome-discovery.ts +0 -220
  485. package/src/clean-html.ts +0 -141
  486. package/src/cli-help.test.ts +0 -123
  487. package/src/cli.ts +0 -3181
  488. package/src/cloud-client.ts +0 -179
  489. package/src/create-logger.ts +0 -38
  490. package/src/debugger-examples-types.ts +0 -16
  491. package/src/debugger-examples.ts +0 -66
  492. package/src/debugger.ts +0 -708
  493. package/src/diff-utils.test.ts +0 -152
  494. package/src/diff-utils.ts +0 -70
  495. package/src/doctor.test.ts +0 -244
  496. package/src/doctor.ts +0 -321
  497. package/src/editor-examples.ts +0 -158
  498. package/src/editor.ts +0 -426
  499. package/src/env-compat.ts +0 -28
  500. package/src/executor.ts +0 -1824
  501. package/src/executor.unit.test.ts +0 -168
  502. package/src/extension-connection.test.ts +0 -855
  503. package/src/extension-icon-warning.test.ts +0 -45
  504. package/src/ghost-browser.ts +0 -149
  505. package/src/ghost-cursor-client.ts +0 -494
  506. package/src/ghost-cursor-controller.ts +0 -129
  507. package/src/ghost-cursor.ts +0 -123
  508. package/src/htmlrewrite.test.ts +0 -8008
  509. package/src/htmlrewrite.ts +0 -390
  510. package/src/index.ts +0 -53
  511. package/src/kill-port.ts +0 -219
  512. package/src/kitty-graphics.test.ts +0 -139
  513. package/src/kitty-graphics.ts +0 -79
  514. package/src/locator-selector.test.ts +0 -119
  515. package/src/mcp-client.ts +0 -78
  516. package/src/mcp.ts +0 -629
  517. package/src/on-mouse-action.test.ts +0 -226
  518. package/src/options-page.test.ts +0 -839
  519. package/src/package-paths.ts +0 -38
  520. package/src/page-markdown.ts +0 -240
  521. package/src/performance-examples.ts +0 -186
  522. package/src/playwright-import.ts +0 -59
  523. package/src/popup-relocation.test.ts +0 -163
  524. package/src/product-paths.test.ts +0 -47
  525. package/src/product-paths.ts +0 -28
  526. package/src/protocol.test.ts +0 -52
  527. package/src/protocol.ts +0 -351
  528. package/src/react-source.ts +0 -379
  529. package/src/relay-client.test.ts +0 -375
  530. package/src/relay-client.ts +0 -572
  531. package/src/relay-core.test.ts +0 -1603
  532. package/src/relay-navigation.test.ts +0 -790
  533. package/src/relay-session.test.ts +0 -1375
  534. package/src/relay-state.test.ts +0 -729
  535. package/src/relay-state.ts +0 -561
  536. package/src/replay-ai-index.test.ts +0 -278
  537. package/src/replay-ai-index.ts +0 -872
  538. package/src/replay-cli.test.ts +0 -325
  539. package/src/replay-eval.ts +0 -1039
  540. package/src/replay-handoff.test.ts +0 -163
  541. package/src/replay-handoff.ts +0 -109
  542. package/src/replay-workflow-compiler.test.ts +0 -250
  543. package/src/replay-workflow-compiler.ts +0 -700
  544. package/src/resource.md +0 -409
  545. package/src/rrweb-recording-relay.test.ts +0 -99
  546. package/src/rrweb-recording-relay.ts +0 -400
  547. package/src/rrweb-recording.ts +0 -322
  548. package/src/scoped-fs.test.ts +0 -80
  549. package/src/scoped-fs.ts +0 -420
  550. package/src/skill-stub.test.ts +0 -24
  551. package/src/snapshot-tools.test.ts +0 -1017
  552. package/src/snapshots/hacker-news-accessibility-full.md +0 -81
  553. package/src/snapshots/hacker-news-accessibility-interactive.md +0 -43
  554. package/src/snapshots/page-markdown-output.txt +0 -16
  555. package/src/snapshots/shadcn-ui-accessibility-full.md +0 -201
  556. package/src/snapshots/shadcn-ui-accessibility-interactive.md +0 -109
  557. package/src/start-relay-server.ts +0 -69
  558. package/src/styles-examples.ts +0 -84
  559. package/src/styles.ts +0 -343
  560. package/src/tabwright-agent-skill.test.ts +0 -61
  561. package/src/tabwright-agent-skill.ts +0 -105
  562. package/src/test-declarations.ts +0 -13
  563. package/src/test-utils.test.ts +0 -70
  564. package/src/test-utils.ts +0 -566
  565. package/src/utils.ts +0 -78
  566. package/src/wait-for-page-load.ts +0 -198
  567. package/src/workflow-capability.ts +0 -417
  568. package/src/workflow-script-flow.test.ts +0 -388
@@ -1,45 +0,0 @@
1
- import { describe, expect, it } from 'vitest'
2
- import {
3
- getRelayReviewIssue,
4
- RELAY_RECOVERY_COMMAND,
5
- RelayConnectionProblemError,
6
- relayIssueText,
7
- relayReviewIssueText,
8
- } from 'mcp-extension/src/relay-warning.js'
9
-
10
- describe('extension relay warning copy', () => {
11
- it('tells users how to recover when the relay is outdated', () => {
12
- const text = relayIssueText({ issue: 'outdated' })
13
-
14
- expect(text).toContain('Tabwright local service is outdated')
15
- expect(text).toContain('Restart or update the Tabwright CLI')
16
- expect(text).toContain(RELAY_RECOVERY_COMMAND)
17
- expect(text).toContain('npm install -g tabwright@latest')
18
- expect(text).toContain('tabwright session list')
19
- })
20
-
21
- it('distinguishes offline and unhealthy relay states', () => {
22
- expect(relayIssueText({ issue: 'offline' })).toContain('is not running')
23
- expect(relayIssueText({ issue: 'unavailable' })).toContain('is not responding correctly')
24
- })
25
-
26
- it('keeps the issue type on the thrown error', () => {
27
- const cause = new Error('connect failed')
28
- const error = new RelayConnectionProblemError({ issue: 'offline', cause })
29
-
30
- expect(error.issue).toBe('offline')
31
- expect(error.message).toContain('Tabwright local service is not running')
32
- expect(error.cause).toBe(cause)
33
- })
34
-
35
- it('keeps browser control available while review endpoints are degraded', () => {
36
- expect(getRelayReviewIssue({ statuses: [404, 404] })).toBe('outdated')
37
- expect(getRelayReviewIssue({ statuses: [200, 503] })).toBe('unavailable')
38
- expect(getRelayReviewIssue({ statuses: [200, 204] })).toBeUndefined()
39
-
40
- const text = relayReviewIssueText({ issue: 'outdated' })
41
- expect(text).toContain('Browser control is connected')
42
- expect(text).toContain('Your files were not deleted')
43
- expect(text).toContain(RELAY_RECOVERY_COMMAND)
44
- })
45
- })
@@ -1,149 +0,0 @@
1
- /**
2
- * Ghost Browser API integration for Tabwright
3
- *
4
- * Shared code for both executor (Node.js) and extension (Chrome) environments.
5
- * See extension/src/ghost-browser-api.d.ts for full API documentation.
6
- */
7
-
8
- // =============================================================================
9
- // Constants - same values as in Ghost Browser
10
- // =============================================================================
11
-
12
- export const GHOST_PUBLIC_API_CONSTANTS = {
13
- NEW_TEMPORARY_IDENTITY: 'OpenInNewSession',
14
- DEFAULT_IDENTITY: '',
15
- MAX_TEMPORARY_IDENTITIES: 25,
16
- } as const
17
-
18
- export const GHOST_PROXIES_CONSTANTS = {
19
- DIRECT_PROXY: '8f513494-8cf5-41c7-b318-936392222104',
20
- SYSTEM_PROXY: '2485b989-7ffb-4442-a45a-d7f9a10c6171',
21
- } as const
22
-
23
- export const GHOST_PROJECTS_CONSTANTS = {
24
- PROJECT_ID_HOME: 'f0673216-13b9-48be-aa41-90763e229e78',
25
- PROJECT_ID_UNSAVED: 'fe061488-8a8e-40f0-9e5e-93a1a5e2c273',
26
- SESSIONS_MAX: 25,
27
- NEW_SESSION: 'OpenInNewSession',
28
- GLOBAL_SESSION: '',
29
- } as const
30
-
31
- // =============================================================================
32
- // Types
33
- // =============================================================================
34
-
35
- export type GhostBrowserNamespace = 'ghostPublicAPI' | 'ghostProxies' | 'projects'
36
-
37
- export type GhostBrowserCommandParams = {
38
- namespace: GhostBrowserNamespace
39
- method: string
40
- args: unknown[]
41
- }
42
-
43
- export type GhostBrowserCommandResult = { success: true; result: unknown } | { success: false; error: string }
44
-
45
- /**
46
- * Function signature for sending ghost-browser commands.
47
- * In executor: sends via CDP session
48
- * In extension: calls chrome.* APIs directly
49
- */
50
- export type SendGhostBrowserCommand = (
51
- namespace: GhostBrowserNamespace,
52
- method: string,
53
- args: unknown[],
54
- ) => Promise<unknown>
55
-
56
- // =============================================================================
57
- // Executor: Chrome object factory
58
- // =============================================================================
59
-
60
- /**
61
- * Creates a proxy object for a Ghost Browser API namespace.
62
- * Constants are returned directly, methods are forwarded via sendCommand.
63
- */
64
- function createGhostBrowserProxy(
65
- namespace: GhostBrowserNamespace,
66
- constants: Record<string, unknown>,
67
- sendCommand: SendGhostBrowserCommand,
68
- ) {
69
- return new Proxy(constants, {
70
- get(target, prop: string) {
71
- // Return constants directly (no await needed)
72
- if (prop in target) {
73
- return target[prop]
74
- }
75
- // Return function that sends ghost-browser command
76
- return (...args: unknown[]) => sendCommand(namespace, prop, args)
77
- },
78
- })
79
- }
80
-
81
- /**
82
- * Creates the chrome object with Ghost Browser API namespaces for the executor sandbox.
83
- * Mirrors the exact shape of chrome.ghostPublicAPI, chrome.ghostProxies, chrome.projects.
84
- *
85
- * @param sendCommand - Function to send commands to the extension
86
- */
87
- export function createGhostBrowserChrome(sendCommand: SendGhostBrowserCommand) {
88
- return {
89
- ghostPublicAPI: createGhostBrowserProxy('ghostPublicAPI', GHOST_PUBLIC_API_CONSTANTS, sendCommand),
90
- ghostProxies: createGhostBrowserProxy('ghostProxies', GHOST_PROXIES_CONSTANTS, sendCommand),
91
- projects: createGhostBrowserProxy('projects', GHOST_PROJECTS_CONSTANTS, sendCommand),
92
- }
93
- }
94
-
95
- // =============================================================================
96
- // Extension: Command handler
97
- // =============================================================================
98
-
99
- /**
100
- * Handles ghost-browser commands in the extension.
101
- * Calls the appropriate chrome.* API and returns the result.
102
- *
103
- * @param params - Command parameters (namespace, method, args)
104
- * @param chromeApi - The chrome object (passed to avoid global dependency)
105
- * @returns Result object with success/error status
106
- */
107
- export async function handleGhostBrowserCommand(
108
- params: GhostBrowserCommandParams,
109
- chromeApi: typeof chrome,
110
- ): Promise<GhostBrowserCommandResult> {
111
- const { namespace, method, args } = params
112
-
113
- try {
114
- const api = (chromeApi as any)[namespace]
115
- if (!api) {
116
- return {
117
- success: false,
118
- error: `chrome.${namespace} not available (not running in Ghost Browser?)`,
119
- }
120
- }
121
-
122
- const fn = api[method]
123
- if (typeof fn !== 'function') {
124
- // Check if it's a constant/property
125
- if (method in api) {
126
- return { success: true, result: api[method] }
127
- }
128
- return {
129
- success: false,
130
- error: `chrome.${namespace}.${method} is not a function or property`,
131
- }
132
- }
133
-
134
- // Ghost Browser APIs use callback pattern, wrap in Promise
135
- const result = await new Promise((resolve, reject) => {
136
- fn.call(api, ...args, (result: unknown) => {
137
- if (chromeApi.runtime.lastError) {
138
- reject(new Error(chromeApi.runtime.lastError.message))
139
- } else {
140
- resolve(result)
141
- }
142
- })
143
- })
144
-
145
- return { success: true, result }
146
- } catch (error: any) {
147
- return { success: false, error: error.message }
148
- }
149
- }
@@ -1,494 +0,0 @@
1
- /**
2
- * Browser-side ghost cursor renderer, injected into every Tabwright-attached tab.
3
- * Auto-enables on load (top frame only). Idles out after 5s of no activity.
4
- *
5
- * Two-element DOM structure so move and press have independent CSS transitions:
6
- * outer (#__playwriter_ghost_cursor__) → translate3d, move easing/duration
7
- * inner (first child) → scale + opacity, press easing/duration
8
- */
9
-
10
- import { SCREENSTUDIO_POINTER_MACOS_TAHOE_DATA_URL } from './assets/cursors/screen-studio/pointer-macos-tahoe-data-url.js'
11
-
12
- // Top-frame only — skip iframes. try/catch for sandboxed iframes that throw.
13
- const isTopFrame = (() => {
14
- try {
15
- return window === window.top
16
- } catch {
17
- return false
18
- }
19
- })()
20
-
21
- type GhostCursorActionType = 'move' | 'down' | 'up' | 'wheel'
22
- type GhostCursorButton = 'left' | 'right' | 'middle' | 'none'
23
- type GhostCursorStyle = 'minimal' | 'dot' | 'screenstudio'
24
-
25
- interface GhostCursorAction {
26
- type: GhostCursorActionType
27
- x: number
28
- y: number
29
- button: GhostCursorButton
30
- }
31
-
32
- export interface GhostCursorClientOptions {
33
- style?: GhostCursorStyle
34
- color?: string
35
- size?: number
36
- zIndex?: number
37
- easing?: string
38
- minDurationMs?: number
39
- maxDurationMs?: number
40
- speedPxPerMs?: number
41
- }
42
-
43
- interface GhostCursorRuntimeOptions {
44
- style: GhostCursorStyle
45
- color: string
46
- size: number
47
- zIndex: number
48
- easing: string
49
- minDurationMs: number
50
- maxDurationMs: number
51
- speedPxPerMs: number
52
- }
53
-
54
- interface GhostCursorRuntimeState {
55
- outerElement: HTMLDivElement | null
56
- innerElement: HTMLDivElement | null
57
- options: GhostCursorRuntimeOptions
58
- x: number
59
- y: number
60
- scale: number
61
- hasPosition: boolean
62
- enabled: boolean
63
- idleHidden: boolean
64
- }
65
-
66
- interface GhostCursorApi {
67
- enable: (options?: GhostCursorClientOptions) => void
68
- disable: () => void
69
- applyMouseAction: (action: GhostCursorAction) => void
70
- isEnabled: () => boolean
71
- }
72
-
73
- declare global {
74
- var __playwriterGhostCursor: GhostCursorApi | undefined
75
- }
76
-
77
- const CURSOR_ID = '__playwriter_ghost_cursor__'
78
- const SCREENSTUDIO_POINTER_ASPECT_RATIO = 618 / 958
79
- const SCREENSTUDIO_HOTSPOT_X_RATIO = 0.14
80
- const SCREENSTUDIO_HOTSPOT_Y_RATIO = 0.06
81
- const MINIMAL_TRIANGLE_HOTSPOT_X_RATIO = 0.07
82
- const MINIMAL_TRIANGLE_HOTSPOT_Y_RATIO = 0.06
83
-
84
- // Animation curves from Emil Kowalski's guidelines (https://animations.dev):
85
- // moves use ease-in-out (accel/decel), presses use strong ease-out (100-160ms).
86
- const MOVE_EASING = 'cubic-bezier(0.65, 0, 0.35, 1)' // easeInOutCubic
87
- const PRESS_EASING = 'cubic-bezier(0.23, 1, 0.32, 1)' // strong ease-out
88
- const PRESS_DURATION_MS = 140
89
-
90
- // Cursor fades out after 5s of no activity, wakes on next action.
91
- const IDLE_HIDE_DELAY_MS = 5000
92
- const IDLE_FADE_OUT_MS = 600
93
-
94
- const DEFAULT_OPTIONS: GhostCursorRuntimeOptions = {
95
- style: 'minimal',
96
- color: '#111827',
97
- size: 22,
98
- zIndex: 2147483647,
99
- easing: MOVE_EASING,
100
- // Slow enough to track with the eye. Override per-call via ghostCursor.show().
101
- minDurationMs: 220,
102
- maxDurationMs: 1500,
103
- speedPxPerMs: 1.2,
104
- }
105
-
106
- const runtime: GhostCursorRuntimeState = {
107
- outerElement: null,
108
- innerElement: null,
109
- options: DEFAULT_OPTIONS,
110
- x: 0,
111
- y: 0,
112
- scale: 1,
113
- hasPosition: false,
114
- enabled: false,
115
- idleHidden: false,
116
- }
117
-
118
- let idleHideTimer: ReturnType<typeof setTimeout> | null = null
119
-
120
- function clamp(options: { value: number; min: number; max: number }): number {
121
- const { value, min, max } = options
122
- return Math.min(max, Math.max(min, value))
123
- }
124
-
125
- function mergeOptions(options?: GhostCursorClientOptions): GhostCursorRuntimeOptions {
126
- if (!options) {
127
- return DEFAULT_OPTIONS
128
- }
129
-
130
- return {
131
- style: options.style ?? DEFAULT_OPTIONS.style,
132
- color: options.color ?? DEFAULT_OPTIONS.color,
133
- size: options.size ?? DEFAULT_OPTIONS.size,
134
- zIndex: options.zIndex ?? DEFAULT_OPTIONS.zIndex,
135
- easing: options.easing ?? DEFAULT_OPTIONS.easing,
136
- minDurationMs: options.minDurationMs ?? DEFAULT_OPTIONS.minDurationMs,
137
- maxDurationMs: options.maxDurationMs ?? DEFAULT_OPTIONS.maxDurationMs,
138
- speedPxPerMs: options.speedPxPerMs ?? DEFAULT_OPTIONS.speedPxPerMs,
139
- }
140
- }
141
-
142
- function getCursorDimensions(): { width: number; height: number } {
143
- if (runtime.options.style === 'screenstudio') {
144
- const height = runtime.options.size
145
- const width = Math.max(10, Math.round(height * SCREENSTUDIO_POINTER_ASPECT_RATIO))
146
- return { width, height }
147
- }
148
-
149
- if (runtime.options.style === 'minimal') {
150
- const size = Math.max(12, runtime.options.size)
151
- return { width: size, height: size }
152
- }
153
-
154
- return { width: runtime.options.size, height: runtime.options.size }
155
- }
156
-
157
- function getHotspotOffsetPx(): { x: number; y: number } {
158
- const dimensions = getCursorDimensions()
159
-
160
- if (runtime.options.style === 'screenstudio') {
161
- return {
162
- x: Math.round(dimensions.width * SCREENSTUDIO_HOTSPOT_X_RATIO),
163
- y: Math.round(dimensions.height * SCREENSTUDIO_HOTSPOT_Y_RATIO),
164
- }
165
- }
166
-
167
- if (runtime.options.style === 'minimal') {
168
- return {
169
- x: Math.round(dimensions.width * MINIMAL_TRIANGLE_HOTSPOT_X_RATIO),
170
- y: Math.round(dimensions.height * MINIMAL_TRIANGLE_HOTSPOT_Y_RATIO),
171
- }
172
- }
173
-
174
- return {
175
- x: Math.round(dimensions.width / 2),
176
- y: Math.round(dimensions.height / 2),
177
- }
178
- }
179
-
180
- function getBaseOpacity(): string {
181
- if (runtime.options.style === 'screenstudio') {
182
- return '0.95'
183
- }
184
-
185
- if (runtime.options.style === 'minimal') {
186
- return '1'
187
- }
188
-
189
- return '0.72'
190
- }
191
-
192
- // Outer element: translate only (move timing).
193
- function applyTranslate(): void {
194
- if (!runtime.outerElement) {
195
- return
196
- }
197
-
198
- const hotspot = getHotspotOffsetPx()
199
- runtime.outerElement.style.transform = `translate3d(${runtime.x - hotspot.x}px, ${runtime.y - hotspot.y}px, 0)`
200
- }
201
-
202
- // Inner element: scale only (press timing).
203
- function applyScale(): void {
204
- if (!runtime.innerElement) {
205
- return
206
- }
207
-
208
- runtime.innerElement.style.transform = `scale(${runtime.scale})`
209
- }
210
-
211
- function computeDurationMs(options: { targetX: number; targetY: number }): number {
212
- if (!runtime.hasPosition) {
213
- return 0
214
- }
215
-
216
- const dx = options.targetX - runtime.x
217
- const dy = options.targetY - runtime.y
218
- const distance = Math.hypot(dx, dy)
219
- const rawDurationMs = distance / runtime.options.speedPxPerMs
220
-
221
- return clamp({
222
- value: rawDurationMs,
223
- min: runtime.options.minDurationMs,
224
- max: runtime.options.maxDurationMs,
225
- })
226
- }
227
-
228
- function createCursorElement(): HTMLDivElement {
229
- const outer = document.createElement('div')
230
- outer.id = CURSOR_ID
231
- outer.setAttribute('aria-hidden', 'true')
232
- outer.style.position = 'fixed'
233
- outer.style.left = '0'
234
- outer.style.top = '0'
235
- outer.style.pointerEvents = 'none'
236
- outer.style.zIndex = `${runtime.options.zIndex}`
237
- outer.style.transitionProperty = 'transform'
238
- outer.style.transitionTimingFunction = runtime.options.easing
239
- outer.style.transitionDuration = '0ms'
240
- outer.style.willChange = 'transform'
241
-
242
- const inner = document.createElement('div')
243
- inner.style.transitionProperty = 'transform, opacity'
244
- inner.style.transitionTimingFunction = PRESS_EASING
245
- inner.style.transitionDuration = `${PRESS_DURATION_MS}ms`
246
- inner.style.opacity = getBaseOpacity()
247
- outer.appendChild(inner)
248
-
249
- runtime.outerElement = outer
250
- runtime.innerElement = inner
251
- applyRuntimeVisualOptions()
252
-
253
- return outer
254
- }
255
-
256
- function ensureCursorElement(): HTMLDivElement {
257
- const existing = document.getElementById(CURSOR_ID) as HTMLDivElement | null
258
- if (existing) {
259
- runtime.outerElement = existing
260
- runtime.innerElement = (existing.firstElementChild as HTMLDivElement) || null
261
- return existing
262
- }
263
-
264
- const outer = createCursorElement()
265
- const root = document.documentElement || document.body
266
- root.appendChild(outer)
267
- return outer
268
- }
269
-
270
- function applyRuntimeVisualOptions(): void {
271
- if (!runtime.innerElement) {
272
- return
273
- }
274
-
275
- const dimensions = getCursorDimensions()
276
- runtime.innerElement.style.width = `${dimensions.width}px`
277
- runtime.innerElement.style.height = `${dimensions.height}px`
278
-
279
- if (runtime.outerElement) {
280
- runtime.outerElement.style.zIndex = `${runtime.options.zIndex}`
281
- runtime.outerElement.style.transitionTimingFunction = runtime.options.easing
282
- }
283
-
284
- // Scale around the hotspot so press doesn't shift the arrow tip.
285
- const hotspot = getHotspotOffsetPx()
286
- runtime.innerElement.style.transformOrigin = `${hotspot.x}px ${hotspot.y}px`
287
-
288
- if (runtime.options.style === 'screenstudio') {
289
- runtime.innerElement.style.borderRadius = '0'
290
- runtime.innerElement.style.border = 'none'
291
- runtime.innerElement.style.backgroundColor = 'transparent'
292
- runtime.innerElement.style.backgroundImage = `url("${SCREENSTUDIO_POINTER_MACOS_TAHOE_DATA_URL}")`
293
- runtime.innerElement.style.backgroundRepeat = 'no-repeat'
294
- runtime.innerElement.style.backgroundPosition = 'left top'
295
- runtime.innerElement.style.backgroundSize = 'contain'
296
- runtime.innerElement.style.backdropFilter = 'none'
297
- runtime.innerElement.style.filter = 'none'
298
- runtime.innerElement.style.boxShadow = 'none'
299
- runtime.innerElement.style.opacity = getBaseOpacity()
300
- return
301
- }
302
-
303
- if (runtime.options.style === 'minimal') {
304
- const triangleSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="-1 -1 26 26"><path fill="white" stroke="${runtime.options.color}" stroke-width="1.5" stroke-linejoin="round" d="m23.284 19.124l-6.866-6.895a.4.4 0 0 1-.118-.296a.43.43 0 0 1 .163-.282l4.439-3.077a1.48 1.48 0 0 0 .621-1.48a1.48 1.48 0 0 0-1.036-1.198L1.623.302a1.14 1.14 0 0 0-1.11.282A1.13 1.13 0 0 0 .29 1.649L5.928 20.44a1.48 1.48 0 0 0 1.183 1.035a1.48 1.48 0 0 0 1.48-.621l3.078-4.44a.37.37 0 0 1 .31-.118a.43.43 0 0 1 .296.104l6.91 6.91a1.48 1.48 0 0 0 2.087 0l2.086-2.086a1.48 1.48 0 0 0-.074-2.101"/></svg>`
305
- const triangleDataUrl = `url("data:image/svg+xml,${encodeURIComponent(triangleSvg)}")`
306
- runtime.innerElement.style.borderRadius = '0'
307
- runtime.innerElement.style.border = 'none'
308
- runtime.innerElement.style.backgroundColor = 'transparent'
309
- runtime.innerElement.style.backgroundImage = triangleDataUrl
310
- runtime.innerElement.style.backgroundRepeat = 'no-repeat'
311
- runtime.innerElement.style.backgroundSize = 'contain'
312
- runtime.innerElement.style.backgroundPosition = 'left top'
313
- runtime.innerElement.style.backdropFilter = 'none'
314
- runtime.innerElement.style.boxShadow = 'none'
315
- runtime.innerElement.style.filter = 'drop-shadow(0 1px 2px rgba(0, 0, 0, 0.4))'
316
- runtime.innerElement.style.opacity = getBaseOpacity()
317
- return
318
- }
319
-
320
- runtime.innerElement.style.borderRadius = '999px'
321
- runtime.innerElement.style.border = 'none'
322
- runtime.innerElement.style.backgroundColor = runtime.options.color
323
- runtime.innerElement.style.backgroundImage = 'none'
324
- runtime.innerElement.style.backdropFilter = 'none'
325
- runtime.innerElement.style.filter = 'none'
326
- runtime.innerElement.style.boxShadow = '0 2px 10px rgba(0, 0, 0, 0.18), inset 0 0 0 2px rgba(255, 255, 255, 0.55)'
327
- runtime.innerElement.style.opacity = getBaseOpacity()
328
- }
329
-
330
- function clearIdleHideTimer(): void {
331
- if (idleHideTimer !== null) {
332
- clearTimeout(idleHideTimer)
333
- idleHideTimer = null
334
- }
335
- }
336
-
337
- function scheduleIdleHide(): void {
338
- clearIdleHideTimer()
339
- idleHideTimer = setTimeout(() => {
340
- idleHideTimer = null
341
- if (!runtime.enabled || !runtime.innerElement) {
342
- return
343
- }
344
- runtime.idleHidden = true
345
- runtime.innerElement.style.transitionDuration = `${IDLE_FADE_OUT_MS}ms`
346
- runtime.innerElement.style.transitionTimingFunction = PRESS_EASING
347
- runtime.innerElement.style.opacity = '0'
348
- }, IDLE_HIDE_DELAY_MS)
349
- }
350
-
351
- function wakeFromIdle(options: { x: number; y: number }): void {
352
- // Teleport so moveCursor sees zero distance.
353
- runtime.x = options.x
354
- runtime.y = options.y
355
- runtime.hasPosition = true
356
- if (runtime.innerElement) {
357
- runtime.innerElement.style.transitionDuration = `${PRESS_DURATION_MS}ms`
358
- runtime.innerElement.style.transitionTimingFunction = PRESS_EASING
359
- runtime.innerElement.style.opacity = getBaseOpacity()
360
- }
361
- }
362
-
363
- function moveCursor(options: { x: number; y: number }): void {
364
- if (!runtime.enabled) {
365
- return
366
- }
367
-
368
- ensureCursorElement()
369
- const durationMs = computeDurationMs({ targetX: options.x, targetY: options.y })
370
- if (runtime.outerElement) {
371
- runtime.outerElement.style.transitionDuration = `${Math.round(durationMs)}ms`
372
- runtime.outerElement.style.transitionTimingFunction = runtime.options.easing
373
- }
374
-
375
- runtime.x = options.x
376
- runtime.y = options.y
377
- runtime.hasPosition = true
378
- applyTranslate()
379
- }
380
-
381
- function setPressed(options: { pressed: boolean }): void {
382
- if (!runtime.enabled || !runtime.innerElement) {
383
- return
384
- }
385
-
386
- // Subtle press feedback (0.95). Dot style uses 0.92 — needs a bigger pulse.
387
- runtime.scale = options.pressed
388
- ? runtime.options.style === 'dot'
389
- ? 0.92
390
- : 0.95
391
- : 1
392
- runtime.innerElement.style.transitionDuration = `${PRESS_DURATION_MS}ms`
393
- runtime.innerElement.style.transitionTimingFunction = PRESS_EASING
394
- runtime.innerElement.style.opacity = options.pressed ? '1' : getBaseOpacity()
395
- applyScale()
396
- }
397
-
398
- function enable(options?: GhostCursorClientOptions): void {
399
- runtime.options = mergeOptions(options)
400
- runtime.enabled = true
401
- ensureCursorElement()
402
- applyRuntimeVisualOptions()
403
-
404
- if (!runtime.hasPosition) {
405
- runtime.x = Math.round(window.innerWidth / 2)
406
- runtime.y = Math.round(window.innerHeight / 2)
407
- runtime.scale = 1
408
- runtime.hasPosition = true
409
- }
410
-
411
- runtime.idleHidden = false
412
- if (runtime.innerElement) {
413
- runtime.innerElement.style.opacity = getBaseOpacity()
414
- }
415
-
416
- applyTranslate()
417
- applyScale()
418
- scheduleIdleHide()
419
- }
420
-
421
- function disable(): void {
422
- runtime.enabled = false
423
- runtime.scale = 1
424
- runtime.hasPosition = false
425
- runtime.idleHidden = false
426
- clearIdleHideTimer()
427
-
428
- if (runtime.outerElement) {
429
- runtime.outerElement.remove()
430
- runtime.outerElement = null
431
- runtime.innerElement = null
432
- }
433
- }
434
-
435
- function applyMouseAction(action: GhostCursorAction): void {
436
- if (!runtime.enabled) {
437
- return
438
- }
439
-
440
- if (runtime.idleHidden) {
441
- runtime.idleHidden = false
442
- wakeFromIdle({ x: action.x, y: action.y })
443
- }
444
-
445
- if (action.type === 'move' || action.type === 'wheel') {
446
- moveCursor({ x: action.x, y: action.y })
447
- } else if (action.type === 'down') {
448
- moveCursor({ x: action.x, y: action.y })
449
- setPressed({ pressed: true })
450
- } else if (action.type === 'up') {
451
- moveCursor({ x: action.x, y: action.y })
452
- setPressed({ pressed: false })
453
- }
454
-
455
- scheduleIdleHide()
456
- }
457
-
458
- const api: GhostCursorApi = {
459
- enable,
460
- disable,
461
- applyMouseAction,
462
- isEnabled: () => {
463
- return runtime.enabled
464
- },
465
- }
466
-
467
- if (isTopFrame) {
468
- globalThis.__playwriterGhostCursor = api
469
-
470
- // Auto-enable. Defer for early injection (addScriptToEvaluateOnNewDocument)
471
- // when DOM isn't ready yet. After hard navigations the cursor re-centers
472
- // until the next mouse action arrives.
473
- try {
474
- if (document.readyState === 'loading') {
475
- document.addEventListener(
476
- 'DOMContentLoaded',
477
- () => {
478
- try {
479
- api.enable()
480
- } catch {
481
- // Non-fatal — DOM may be in an unexpected state.
482
- }
483
- },
484
- { once: true },
485
- )
486
- } else {
487
- api.enable()
488
- }
489
- } catch {
490
- // Restricted contexts (chrome://, devtools://) — silently skip.
491
- }
492
- }
493
-
494
- export {}