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,305 @@
1
+ import fs from 'node:fs'
2
+ import os from 'node:os'
3
+ import path from 'node:path'
4
+ import { requireCapability, type CapabilityRecord } from './capability-registry.js'
5
+
6
+ export type AgentSkillTarget = 'codex'
7
+ export type AgentSkillFileStatus = 'created' | 'updated' | 'unchanged'
8
+
9
+ export interface AgentSkillFileResult {
10
+ relativePath: string
11
+ path: string
12
+ status: AgentSkillFileStatus
13
+ }
14
+
15
+ export interface CapabilityAgentSkillResult {
16
+ target: AgentSkillTarget
17
+ capabilityId: string
18
+ dir: string
19
+ files: AgentSkillFileResult[]
20
+ next: string[]
21
+ }
22
+
23
+ export interface CapabilityAgentSkillShowResult {
24
+ target: AgentSkillTarget
25
+ capabilityId: string
26
+ dir: string
27
+ files: Array<{
28
+ relativePath: string
29
+ path: string
30
+ content: string
31
+ }>
32
+ }
33
+
34
+ export interface CapabilityAgentSkillStatus {
35
+ target: AgentSkillTarget
36
+ draftExists: boolean
37
+ draftPath: string
38
+ installedExists: boolean
39
+ installedPath: string
40
+ initCommand: string
41
+ showCommand: string
42
+ installCommand: string
43
+ }
44
+
45
+ const SKILL_TEMPLATE_MARKER = '<!-- TABWRIGHT_AGENT_SKILL_TEMPLATE: edit before install -->'
46
+
47
+ export function initCapabilityAgentSkill(options: {
48
+ id: string
49
+ cwd?: string
50
+ target?: AgentSkillTarget
51
+ overwrite?: boolean
52
+ }): CapabilityAgentSkillResult {
53
+ const target = options.target || 'codex'
54
+ const capability = requireCapability({ id: options.id, cwd: options.cwd })
55
+ const dir = getCapabilityAgentSkillDir({ capability, target })
56
+ const files = [
57
+ writeSkillFile({
58
+ filePath: path.join(dir, 'SKILL.md'),
59
+ relativePath: 'SKILL.md',
60
+ content: buildCodexSkillTemplate(capability),
61
+ overwrite: options.overwrite,
62
+ }),
63
+ writeSkillFile({
64
+ filePath: path.join(dir, 'agents', 'openai.yaml'),
65
+ relativePath: 'agents/openai.yaml',
66
+ content: buildOpenAiAgentTemplate(capability),
67
+ overwrite: options.overwrite,
68
+ }),
69
+ ]
70
+ return {
71
+ target,
72
+ capabilityId: capability.manifest.id,
73
+ dir,
74
+ files,
75
+ next: [
76
+ `Edit ${path.join(dir, 'SKILL.md')} with the real usage workflow and display rules.`,
77
+ `tabwright capability skill install ${capability.manifest.id}`,
78
+ ],
79
+ }
80
+ }
81
+
82
+ export function installCapabilityAgentSkill(options: {
83
+ id: string
84
+ cwd?: string
85
+ target?: AgentSkillTarget
86
+ overwrite?: boolean
87
+ codexHome?: string
88
+ capability?: CapabilityRecord
89
+ }): CapabilityAgentSkillResult {
90
+ const target = options.target || 'codex'
91
+ const capability = options.capability || requireCapability({ id: options.id, cwd: options.cwd })
92
+ const dir = getCapabilityAgentSkillDir({ capability, target })
93
+ const skillPath = path.join(dir, 'SKILL.md')
94
+ if (!fs.existsSync(skillPath)) {
95
+ throw new Error(`Agent skill draft not found for ${capability.manifest.id}. Run: tabwright capability skill init ${capability.manifest.id}`)
96
+ }
97
+ const skillContent = fs.readFileSync(skillPath, 'utf-8')
98
+ assertSkillReadyToInstall({ capability, content: skillContent, filePath: skillPath })
99
+ const sourceFiles = getExistingAgentSkillFiles(dir)
100
+ const codexSkillDir = path.join(getCodexHome(options.codexHome), 'skills', capability.manifest.id)
101
+ const files = sourceFiles.map((file) => {
102
+ return writeSkillFile({
103
+ filePath: path.join(codexSkillDir, ...file.relativePath.split('/')),
104
+ relativePath: file.relativePath,
105
+ content: fs.readFileSync(file.path, 'utf-8'),
106
+ overwrite: options.overwrite,
107
+ })
108
+ })
109
+ return {
110
+ target,
111
+ capabilityId: capability.manifest.id,
112
+ dir: codexSkillDir,
113
+ files,
114
+ next: [`Restart or open a new agent thread so it can load the ${capability.manifest.id} skill.`],
115
+ }
116
+ }
117
+
118
+ export function showCapabilityAgentSkill(options: {
119
+ id: string
120
+ cwd?: string
121
+ target?: AgentSkillTarget
122
+ }): CapabilityAgentSkillShowResult {
123
+ const target = options.target || 'codex'
124
+ const capability = requireCapability({ id: options.id, cwd: options.cwd })
125
+ const dir = getCapabilityAgentSkillDir({ capability, target })
126
+ const files = getExistingAgentSkillFiles(dir).map((file) => {
127
+ return {
128
+ relativePath: file.relativePath,
129
+ path: file.path,
130
+ content: fs.readFileSync(file.path, 'utf-8'),
131
+ }
132
+ })
133
+ if (!files.some((file) => {
134
+ return file.relativePath === 'SKILL.md'
135
+ })) {
136
+ throw new Error(`Agent skill draft not found for ${capability.manifest.id}. Run: tabwright capability skill init ${capability.manifest.id}`)
137
+ }
138
+ return {
139
+ target,
140
+ capabilityId: capability.manifest.id,
141
+ dir,
142
+ files,
143
+ }
144
+ }
145
+
146
+ export function getCapabilityAgentSkillStatus(options: {
147
+ capability: CapabilityRecord
148
+ target?: AgentSkillTarget
149
+ codexHome?: string
150
+ }): CapabilityAgentSkillStatus {
151
+ const target = options.target || 'codex'
152
+ const draftDir = getCapabilityAgentSkillDir({ capability: options.capability, target })
153
+ const installedDir = path.join(getCodexHome(options.codexHome), 'skills', options.capability.manifest.id)
154
+ return {
155
+ target,
156
+ draftExists: fs.existsSync(path.join(draftDir, 'SKILL.md')),
157
+ draftPath: path.join(draftDir, 'SKILL.md'),
158
+ installedExists: fs.existsSync(path.join(installedDir, 'SKILL.md')),
159
+ installedPath: path.join(installedDir, 'SKILL.md'),
160
+ initCommand: `tabwright capability skill init ${options.capability.manifest.id}`,
161
+ showCommand: `tabwright capability skill show ${options.capability.manifest.id}`,
162
+ installCommand: `tabwright capability skill install ${options.capability.manifest.id}`,
163
+ }
164
+ }
165
+
166
+ function getCapabilityAgentSkillDir(options: { capability: CapabilityRecord; target: AgentSkillTarget }): string {
167
+ return path.join(options.capability.dir, 'agent-skills', options.target)
168
+ }
169
+
170
+ function getCodexHome(codexHome?: string): string {
171
+ return codexHome || process.env.CODEX_HOME || path.join(os.homedir(), '.codex')
172
+ }
173
+
174
+ function getExistingAgentSkillFiles(dir: string): Array<{ relativePath: string; path: string }> {
175
+ const skillPath = path.join(dir, 'SKILL.md')
176
+ const openAiPath = path.join(dir, 'agents', 'openai.yaml')
177
+ const files: Array<{ relativePath: string; path: string }> = []
178
+ if (fs.existsSync(skillPath)) {
179
+ files.push({ relativePath: 'SKILL.md', path: skillPath })
180
+ }
181
+ if (fs.existsSync(openAiPath)) {
182
+ files.push({ relativePath: 'agents/openai.yaml', path: openAiPath })
183
+ }
184
+ return files
185
+ }
186
+
187
+ function writeSkillFile(options: {
188
+ filePath: string
189
+ relativePath: string
190
+ content: string
191
+ overwrite?: boolean
192
+ }): AgentSkillFileResult {
193
+ if (fs.existsSync(options.filePath)) {
194
+ const existing = fs.readFileSync(options.filePath, 'utf-8')
195
+ if (existing === options.content) {
196
+ return { relativePath: options.relativePath, path: options.filePath, status: 'unchanged' }
197
+ }
198
+ if (!options.overwrite) {
199
+ throw new Error(`Agent skill file already exists with different content: ${options.filePath}. Use --force to overwrite.`)
200
+ }
201
+ }
202
+ fs.mkdirSync(path.dirname(options.filePath), { recursive: true })
203
+ const status = fs.existsSync(options.filePath) ? 'updated' : 'created'
204
+ fs.writeFileSync(options.filePath, options.content)
205
+ return { relativePath: options.relativePath, path: options.filePath, status }
206
+ }
207
+
208
+ function assertSkillReadyToInstall(options: {
209
+ capability: CapabilityRecord
210
+ content: string
211
+ filePath: string
212
+ }): void {
213
+ if (options.content.includes(SKILL_TEMPLATE_MARKER)) {
214
+ throw new Error(`Agent skill still contains the scaffold marker: ${options.filePath}. Edit the skill content before installing it.`)
215
+ }
216
+ if (!options.content.includes(`name: ${options.capability.manifest.id}`)) {
217
+ throw new Error(`Agent skill frontmatter must include name: ${options.capability.manifest.id}`)
218
+ }
219
+ }
220
+
221
+ function buildCodexSkillTemplate(capability: CapabilityRecord): string {
222
+ const operationIds = Object.keys(capability.manifest.operations)
223
+ const hasOperations = operationIds.length > 0
224
+ const requiresConfirmation = hasOperations
225
+ ? Object.values(capability.manifest.operations).some((operation) => {
226
+ return operation.requiresConfirmation
227
+ })
228
+ : capability.manifest.requiresConfirmation
229
+ const description = [
230
+ `TODO: Explain when agents should use the ${capability.manifest.id} Tabwright capability.`,
231
+ 'Mention concrete user phrasing, exact-match signals, and when not to use it.',
232
+ ].join(' ')
233
+ const routeCommand = `tabwright capability route "<user-task-or-url>" --json`
234
+ const runCommand = [
235
+ 'tabwright capability run',
236
+ capability.manifest.id,
237
+ capability.manifest.runtime === 'browser' ? '--browser user' : '',
238
+ "--input-json '<json-input>'",
239
+ '--json',
240
+ capability.manifest.status === 'trusted' ? '' : '--force',
241
+ requiresConfirmation
242
+ ? hasOperations
243
+ ? '--confirm <confirmation-token>'
244
+ : `--confirm ${capability.manifest.id}`
245
+ : '',
246
+ ]
247
+ .filter((part) => {
248
+ return part.length > 0
249
+ })
250
+ .join(' ')
251
+ return [
252
+ '---',
253
+ `name: ${capability.manifest.id}`,
254
+ `description: ${quoteYamlString(description)}`,
255
+ '---',
256
+ '',
257
+ SKILL_TEMPLATE_MARKER,
258
+ '',
259
+ '## When To Use',
260
+ '',
261
+ '- TODO: Describe the concrete user intent, URL pattern, page state, or data shape that should trigger this capability.',
262
+ '- TODO: State when this capability should not be used.',
263
+ '',
264
+ '## Workflow',
265
+ '',
266
+ '1. Use route when exact-match metadata may apply:',
267
+ '',
268
+ '```bash',
269
+ routeCommand,
270
+ '```',
271
+ '',
272
+ requiresConfirmation
273
+ ? hasOperations
274
+ ? `2. Select one operation (${operationIds.join(', ')}). Read operations may run directly; for a confirmation-required operation, stop for approval and use its exact confirmationToken:`
275
+ : '2. Stop and obtain explicit user approval for the concrete input and side effect. Only then run with structured input:'
276
+ : '2. Run the returned `shellCommand` exactly, or run the capability with structured input:',
277
+ '',
278
+ '```bash',
279
+ runCommand,
280
+ '```',
281
+ '',
282
+ '3. If the capability requires browser/session/auth state, describe the required refresh or browser command.',
283
+ '',
284
+ '## Output And Display',
285
+ '',
286
+ '- TODO: Define the default answer shape.',
287
+ '- TODO: Say when to show a short summary versus when to point to artifacts.',
288
+ '- TODO: Say whether large outputs should be saved, filtered, or exported only on request.',
289
+ '',
290
+ ].join('\n')
291
+ }
292
+
293
+ function buildOpenAiAgentTemplate(capability: CapabilityRecord): string {
294
+ return [
295
+ 'interface:',
296
+ ` display_name: ${quoteYamlString(capability.manifest.title)}`,
297
+ ` short_description: ${quoteYamlString(capability.manifest.description || capability.manifest.title)}`,
298
+ ` default_prompt: ${quoteYamlString(`Use ${capability.manifest.id} for <task>`)}`,
299
+ '',
300
+ ].join('\n')
301
+ }
302
+
303
+ function quoteYamlString(value: string): string {
304
+ return JSON.stringify(value)
305
+ }
@@ -0,0 +1,197 @@
1
+ import fs from 'node:fs'
2
+ import path from 'node:path'
3
+ import {
4
+ readCapabilityRuns,
5
+ readCapabilitySecrets,
6
+ type CapabilityAuthType,
7
+ type CapabilityRecord,
8
+ } from './capability-registry.js'
9
+
10
+ const AUTH_STATE_FILENAME = 'auth-state.json'
11
+ const EXPIRING_WINDOW_MS = 24 * 60 * 60 * 1000
12
+
13
+ export type CapabilityAuthStatus = 'not-required' | 'missing' | 'authenticated' | 'expiring' | 'expired' | 'unknown'
14
+
15
+ export interface StoredCapabilityAuthState {
16
+ schemaVersion: 1
17
+ refreshedAt: string
18
+ expiresAt?: string
19
+ cookieNames: string[]
20
+ browserKey?: string
21
+ }
22
+
23
+ export interface CapabilityAuthState {
24
+ type: CapabilityAuthType
25
+ status: CapabilityAuthStatus
26
+ canRefresh: boolean
27
+ browserUrls: string[]
28
+ requiredCookieNames: string[]
29
+ cookieNames: string[]
30
+ refreshedAt?: string
31
+ expiresAt?: string
32
+ browserKey?: string
33
+ reason?: string
34
+ refreshCommand?: string
35
+ }
36
+
37
+ export function writeStoredCapabilityAuthState(options: {
38
+ capability: CapabilityRecord
39
+ state: StoredCapabilityAuthState
40
+ }): string {
41
+ const statePath = path.join(options.capability.dir, AUTH_STATE_FILENAME)
42
+ fs.mkdirSync(options.capability.dir, { recursive: true })
43
+ fs.writeFileSync(statePath, `${JSON.stringify(options.state, null, 2)}\n`, { mode: 0o600 })
44
+ if (process.platform !== 'win32') {
45
+ fs.chmodSync(statePath, 0o600)
46
+ }
47
+ return statePath
48
+ }
49
+
50
+ export function removeCapabilityAuthFiles(options: { capabilityDir: string }): void {
51
+ const filenames: string[] = ['secrets.json', AUTH_STATE_FILENAME]
52
+ filenames.map((filename) => {
53
+ fs.rmSync(path.join(options.capabilityDir, filename), { force: true })
54
+ return filename
55
+ })
56
+ }
57
+
58
+ export function getCapabilityAuthState(options: { capability: CapabilityRecord; now?: Date }): CapabilityAuthState {
59
+ const auth = options.capability.manifest.auth
60
+ const canRefresh = auth.type === 'cookie' && auth.refresh === 'from-browser' && auth.browserUrls.length > 0
61
+ const refreshCommand = canRefresh
62
+ ? `tabwright capability refresh-auth ${options.capability.manifest.id} --browser user --json`
63
+ : undefined
64
+ const base = {
65
+ type: auth.type,
66
+ canRefresh,
67
+ browserUrls: auth.browserUrls,
68
+ requiredCookieNames: auth.requiredCookieNames,
69
+ refreshCommand,
70
+ }
71
+ if (auth.type === 'none') {
72
+ return { ...base, status: 'not-required', cookieNames: [] }
73
+ }
74
+
75
+ const secretKey = auth.secretKey || 'cookieHeader'
76
+ const secrets = (() => {
77
+ try {
78
+ return readCapabilitySecrets({ capability: options.capability })
79
+ } catch {
80
+ return {}
81
+ }
82
+ })()
83
+ if (typeof secrets[secretKey] !== 'string' || secrets[secretKey].length === 0) {
84
+ return {
85
+ ...base,
86
+ status: 'missing',
87
+ cookieNames: [],
88
+ reason: 'No saved authentication is available on this device.',
89
+ }
90
+ }
91
+
92
+ const stored = readStoredCapabilityAuthState({ capability: options.capability })
93
+ if (!stored) {
94
+ return {
95
+ ...base,
96
+ status: 'unknown',
97
+ cookieNames: [],
98
+ reason: 'Saved authentication predates status tracking. Refresh it to inspect expiry.',
99
+ }
100
+ }
101
+
102
+ const runFailure = latestAuthFailure({ capability: options.capability, refreshedAt: stored.refreshedAt })
103
+ if (runFailure) {
104
+ return {
105
+ ...base,
106
+ ...stored,
107
+ status: 'expired',
108
+ reason: runFailure,
109
+ }
110
+ }
111
+
112
+ // Cookie timestamps cover client-side expiry; failure signals cover sessions revoked earlier by the server.
113
+ const now = options.now || new Date()
114
+ const expiresAt = stored.expiresAt ? Date.parse(stored.expiresAt) : Number.NaN
115
+ if (!Number.isNaN(expiresAt) && expiresAt <= now.getTime()) {
116
+ return {
117
+ ...base,
118
+ ...stored,
119
+ status: 'expired',
120
+ reason: 'The saved browser cookies have expired.',
121
+ }
122
+ }
123
+ if (!Number.isNaN(expiresAt) && expiresAt - now.getTime() <= EXPIRING_WINDOW_MS) {
124
+ return {
125
+ ...base,
126
+ ...stored,
127
+ status: 'expiring',
128
+ reason: 'The saved browser cookies expire within 24 hours.',
129
+ }
130
+ }
131
+ return { ...base, ...stored, status: 'authenticated' }
132
+ }
133
+
134
+ function readStoredCapabilityAuthState(options: { capability: CapabilityRecord }): StoredCapabilityAuthState | null {
135
+ const statePath = path.join(options.capability.dir, AUTH_STATE_FILENAME)
136
+ if (!fs.existsSync(statePath)) {
137
+ return null
138
+ }
139
+ const parsed: unknown = (() => {
140
+ try {
141
+ return JSON.parse(fs.readFileSync(statePath, 'utf-8'))
142
+ } catch {
143
+ return null
144
+ }
145
+ })()
146
+ if (!isRecord(parsed) || parsed.schemaVersion !== 1 || typeof parsed.refreshedAt !== 'string') {
147
+ return null
148
+ }
149
+ const cookieNames = Array.isArray(parsed.cookieNames)
150
+ ? parsed.cookieNames.filter((value): value is string => {
151
+ return typeof value === 'string'
152
+ })
153
+ : []
154
+ return {
155
+ schemaVersion: 1,
156
+ refreshedAt: parsed.refreshedAt,
157
+ expiresAt: typeof parsed.expiresAt === 'string' ? parsed.expiresAt : undefined,
158
+ cookieNames,
159
+ browserKey: typeof parsed.browserKey === 'string' ? parsed.browserKey : undefined,
160
+ }
161
+ }
162
+
163
+ function latestAuthFailure(options: { capability: CapabilityRecord; refreshedAt: string }): string | null {
164
+ const refreshedAt = Date.parse(options.refreshedAt)
165
+ const relevantRun = readCapabilityRuns({ capability: options.capability, limit: 50 })
166
+ .filter((run) => {
167
+ return Number.isNaN(refreshedAt) || Date.parse(run.createdAt) >= refreshedAt
168
+ })
169
+ .reverse()
170
+ .find((run) => {
171
+ if (run.status === 'success') {
172
+ return true
173
+ }
174
+ if (!run.error) {
175
+ return false
176
+ }
177
+ const normalizedError = run.error.toLowerCase()
178
+ return options.capability.manifest.auth.failureSignals.some((signal) => {
179
+ return normalizedError.includes(signal.toLowerCase())
180
+ })
181
+ })
182
+ if (!relevantRun || relevantRun.status === 'success' || !relevantRun.error) {
183
+ return null
184
+ }
185
+ const normalizedError = relevantRun.error.toLowerCase()
186
+ const matchedSignal = options.capability.manifest.auth.failureSignals.find((signal) => {
187
+ return normalizedError.includes(signal.toLowerCase())
188
+ })
189
+ if (!matchedSignal) {
190
+ return null
191
+ }
192
+ return `The latest run reported an authentication failure: ${matchedSignal}`
193
+ }
194
+
195
+ function isRecord(value: unknown): value is Record<string, unknown> {
196
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
197
+ }