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,931 @@
1
+ import crypto from 'node:crypto';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { z } from 'zod';
5
+ import { getTabwrightProjectDataDir, getTabwrightUserDataDir } from './product-paths.js';
6
+ const CapabilityStatusSchema = z.enum(['draft', 'trusted', 'disabled']);
7
+ const CapabilityRuntimeSchema = z.enum(['browser', 'node']);
8
+ const CapabilitySideEffectSchema = z.enum(['read', 'write', 'dangerous']);
9
+ const CapabilityRoutingHintSchema = z.enum(['search-first', 'exact-match-direct-run']);
10
+ const CapabilityAuthConfigSchema = z
11
+ .object({
12
+ type: z.enum(['none', 'cookie', 'token', 'custom']).default('none'),
13
+ refresh: z.enum(['none', 'manual', 'from-browser']).default('none'),
14
+ secretKey: z.string().optional(),
15
+ browserUrls: z.array(z.string()).default([]),
16
+ requiredCookieNames: z.array(z.string()).default([]),
17
+ failureSignals: z.array(z.string()).default([]),
18
+ })
19
+ .default({
20
+ type: 'none',
21
+ refresh: 'none',
22
+ browserUrls: [],
23
+ requiredCookieNames: [],
24
+ failureSignals: [],
25
+ });
26
+ const CapabilityExampleSchema = z
27
+ .object({
28
+ description: z.string().optional(),
29
+ input: z.unknown().optional(),
30
+ output: z.unknown().optional(),
31
+ })
32
+ .passthrough();
33
+ const CapabilityOperationSchema = z
34
+ .object({
35
+ title: z.string().default(''),
36
+ description: z.string().default(''),
37
+ match: z.array(z.string()).default([]),
38
+ routingHint: CapabilityRoutingHintSchema.default('search-first'),
39
+ inputSchema: z.record(z.string(), z.unknown()).default({ type: 'object', properties: {} }),
40
+ outputSchema: z.record(z.string(), z.unknown()).default({ type: 'object', properties: {} }),
41
+ permissions: z.array(z.string()).optional(),
42
+ sideEffect: CapabilitySideEffectSchema.default('read'),
43
+ requiresConfirmation: z.boolean().default(false),
44
+ })
45
+ .passthrough();
46
+ const CapabilityRunRecordSchema = z.object({
47
+ id: z.string(),
48
+ operation: z.string().optional(),
49
+ status: z.enum(['success', 'error']),
50
+ url: z.string().optional(),
51
+ durationMs: z.number(),
52
+ inputHash: z.string(),
53
+ error: z.string().optional(),
54
+ contract: z
55
+ .object({
56
+ schemaVersion: z.literal(1),
57
+ fingerprint: z.string(),
58
+ status: z.enum(['passed', 'failed', 'unknown']),
59
+ failures: z.array(z.object({
60
+ kind: z.enum(['output-schema', 'undeclared-host']),
61
+ message: z.string(),
62
+ })),
63
+ output: z.object({
64
+ status: z.enum(['passed', 'failed', 'not-applicable', 'unknown']),
65
+ errors: z.array(z.string()),
66
+ }),
67
+ network: z.object({
68
+ status: z.enum(['passed', 'failed', 'not-applicable', 'unknown']),
69
+ observedHosts: z.array(z.string()),
70
+ undeclaredHosts: z.array(z.string()),
71
+ }),
72
+ trust: z.object({
73
+ before: CapabilityStatusSchema,
74
+ after: CapabilityStatusSchema,
75
+ downgraded: z.boolean(),
76
+ }),
77
+ })
78
+ .optional(),
79
+ createdAt: z.string(),
80
+ });
81
+ const CapabilityManifestSchema = z
82
+ .object({
83
+ schemaVersion: z.literal(1),
84
+ id: z.string().regex(/^[a-z0-9][a-z0-9-]*[a-z0-9]$|^[a-z0-9]$/),
85
+ title: z.string().min(1),
86
+ description: z.string().default(''),
87
+ whenToUse: z.array(z.string()).default([]),
88
+ whenNotToUse: z.array(z.string()).default([]),
89
+ tags: z.array(z.string()).default([]),
90
+ match: z.array(z.string()).default([]),
91
+ routingHint: CapabilityRoutingHintSchema.default('search-first'),
92
+ inputSchema: z.record(z.string(), z.unknown()).default({ type: 'object', properties: {} }),
93
+ outputSchema: z.record(z.string(), z.unknown()).default({ type: 'object', properties: {} }),
94
+ permissions: z.array(z.string()).default([]),
95
+ sideEffect: CapabilitySideEffectSchema.default('read'),
96
+ requiresConfirmation: z.boolean().default(false),
97
+ operations: z
98
+ .record(z.string().regex(/^[a-z0-9][a-z0-9-]*[a-z0-9]$|^[a-z0-9]$/), CapabilityOperationSchema)
99
+ .default({}),
100
+ auth: CapabilityAuthConfigSchema,
101
+ examples: z.array(CapabilityExampleSchema).default([]),
102
+ entry: z.string().default('script.js'),
103
+ runtime: CapabilityRuntimeSchema.default('browser'),
104
+ status: CapabilityStatusSchema.default('draft'),
105
+ createdBy: z.enum(['user', 'ai']).default('user'),
106
+ createdAt: z.string().optional(),
107
+ updatedAt: z.string().optional(),
108
+ })
109
+ .passthrough();
110
+ export function parseCapabilityManifest(value) {
111
+ return CapabilityManifestSchema.parse(value);
112
+ }
113
+ export function getUserCapabilitiesDir() {
114
+ return path.join(getTabwrightUserDataDir(), 'capabilities');
115
+ }
116
+ export function getProjectCapabilitiesDir(options = {}) {
117
+ return path.join(getTabwrightProjectDataDir({ cwd: options.cwd }), 'capabilities');
118
+ }
119
+ export function getCapabilityRoots(options = {}) {
120
+ return [
121
+ { dir: getProjectCapabilitiesDir({ cwd: options.cwd }), location: 'project' },
122
+ { dir: getUserCapabilitiesDir(), location: 'user' },
123
+ ];
124
+ }
125
+ export function validateCapabilityId(id) {
126
+ if (!/^[a-z0-9][a-z0-9-]*[a-z0-9]$|^[a-z0-9]$/.test(id)) {
127
+ throw new Error(`Invalid capability id "${id}". Use kebab-case letters and numbers only.`);
128
+ }
129
+ }
130
+ export function getCapabilityDir(options) {
131
+ validateCapabilityId(options.id);
132
+ const root = options.location === 'project' ? getProjectCapabilitiesDir({ cwd: options.cwd }) : getUserCapabilitiesDir();
133
+ return path.join(root, options.id);
134
+ }
135
+ function readJsonFile(filePath) {
136
+ const content = fs.readFileSync(filePath, 'utf-8');
137
+ return JSON.parse(content);
138
+ }
139
+ function writeJsonFile(options) {
140
+ fs.writeFileSync(options.filePath, `${JSON.stringify(options.value, null, 2)}\n`);
141
+ }
142
+ function resolveCapabilityEntry(options) {
143
+ const resolvedDir = path.resolve(options.dir);
144
+ const scriptPath = path.resolve(resolvedDir, options.entry);
145
+ if (scriptPath !== resolvedDir && !scriptPath.startsWith(`${resolvedDir}${path.sep}`)) {
146
+ throw new Error(`Capability entry must stay inside capability directory: ${options.entry}`);
147
+ }
148
+ return scriptPath;
149
+ }
150
+ function parseManifest(options) {
151
+ const raw = readJsonFile(options.manifestPath);
152
+ return parseCapabilityManifest(raw);
153
+ }
154
+ export function readCapability(options) {
155
+ const manifestPath = path.join(options.dir, 'capability.json');
156
+ const manifest = parseManifest({ manifestPath });
157
+ const scriptPath = resolveCapabilityEntry({ dir: options.dir, entry: manifest.entry });
158
+ return {
159
+ manifest,
160
+ dir: options.dir,
161
+ manifestPath,
162
+ scriptPath,
163
+ location: options.location,
164
+ };
165
+ }
166
+ export function listCapabilities(options = {}) {
167
+ return getCapabilityRoots({ cwd: options.cwd }).flatMap((root) => {
168
+ if (!fs.existsSync(root.dir)) {
169
+ return [];
170
+ }
171
+ return fs
172
+ .readdirSync(root.dir, { withFileTypes: true })
173
+ .filter((entry) => {
174
+ return entry.isDirectory();
175
+ })
176
+ .flatMap((entry) => {
177
+ const dir = path.join(root.dir, entry.name);
178
+ const manifestPath = path.join(dir, 'capability.json');
179
+ if (!fs.existsSync(manifestPath)) {
180
+ return [];
181
+ }
182
+ try {
183
+ return [readCapability({ dir, location: root.location })];
184
+ }
185
+ catch {
186
+ return [];
187
+ }
188
+ });
189
+ });
190
+ }
191
+ export function findCapability(options) {
192
+ validateCapabilityId(options.id);
193
+ return (getCapabilityRoots({ cwd: options.cwd })
194
+ .map((root) => {
195
+ const dir = path.join(root.dir, options.id);
196
+ if (!fs.existsSync(path.join(dir, 'capability.json'))) {
197
+ return null;
198
+ }
199
+ return readCapability({ dir, location: root.location });
200
+ })
201
+ .find((record) => {
202
+ return record !== null;
203
+ }) || null);
204
+ }
205
+ export function requireCapability(options) {
206
+ const capability = findCapability(options);
207
+ if (!capability) {
208
+ throw new Error(`Capability not found: ${options.id}`);
209
+ }
210
+ return capability;
211
+ }
212
+ export function capabilityMatchesText(options) {
213
+ return matchesCapabilityPatterns({ patterns: options.capability.match, text: options.text });
214
+ }
215
+ export function capabilityOperationMatchesText(options) {
216
+ return matchesCapabilityPatterns({ patterns: options.operation.match, text: options.text });
217
+ }
218
+ function matchesCapabilityPatterns(options) {
219
+ if (options.patterns.length === 0) {
220
+ return true;
221
+ }
222
+ return options.patterns.some((pattern) => {
223
+ const regex = new RegExp(`^${pattern.split('*').map(escapeRegex).join('.*')}$`);
224
+ return regex.test(options.text);
225
+ });
226
+ }
227
+ export function capabilityMatchesUrl(options) {
228
+ return capabilityMatchesText({ capability: options.capability, text: options.url });
229
+ }
230
+ function escapeRegex(value) {
231
+ return value.replace(/[|\\{}()[\]^$+?.]/g, '\\$&');
232
+ }
233
+ export function getCapabilityOperations(capability) {
234
+ const operations = Object.entries(capability.manifest.operations);
235
+ if (operations.length === 0) {
236
+ return [
237
+ {
238
+ id: undefined,
239
+ title: capability.manifest.title,
240
+ description: capability.manifest.description,
241
+ match: capability.manifest.match,
242
+ routingHint: capability.manifest.routingHint,
243
+ inputSchema: capability.manifest.inputSchema,
244
+ outputSchema: capability.manifest.outputSchema,
245
+ permissions: capability.manifest.permissions,
246
+ sideEffect: capability.manifest.sideEffect,
247
+ requiresConfirmation: capability.manifest.requiresConfirmation,
248
+ confirmationToken: capability.manifest.id,
249
+ },
250
+ ];
251
+ }
252
+ return operations.map(([id, operation]) => {
253
+ return {
254
+ ...operation,
255
+ id,
256
+ permissions: operation.permissions || capability.manifest.permissions,
257
+ confirmationToken: `${capability.manifest.id}:${id}`,
258
+ };
259
+ });
260
+ }
261
+ export function getCapabilitySafetySummary(capability) {
262
+ const operations = getCapabilityOperations(capability);
263
+ const sideEffects = new Set(operations.map((operation) => {
264
+ return operation.sideEffect;
265
+ }));
266
+ return {
267
+ sideEffect: sideEffects.size === 1 ? operations[0]?.sideEffect || capability.manifest.sideEffect : 'mixed',
268
+ requiresConfirmation: operations.some((operation) => {
269
+ return operation.requiresConfirmation;
270
+ }),
271
+ };
272
+ }
273
+ export function resolveCapabilityOperation(options) {
274
+ const operations = getCapabilityOperations(options.capability);
275
+ if (operations.length === 1 && operations[0]?.id === undefined) {
276
+ return operations[0];
277
+ }
278
+ if (!isPlainObject(options.input) || typeof options.input.action !== 'string') {
279
+ throw new Error(`Capability ${options.capability.manifest.id} requires input.action. Use one of: ${operations
280
+ .map((operation) => {
281
+ return operation.id;
282
+ })
283
+ .join(', ')}`);
284
+ }
285
+ const action = options.input.action;
286
+ const operation = operations.find((candidate) => {
287
+ return candidate.id === action;
288
+ });
289
+ if (!operation) {
290
+ throw new Error(`Unsupported capability action "${action}". Use one of: ${operations
291
+ .map((candidate) => {
292
+ return candidate.id;
293
+ })
294
+ .join(', ')}`);
295
+ }
296
+ return operation;
297
+ }
298
+ export function createCapability(options) {
299
+ validateCapabilityId(options.id);
300
+ const location = options.location || 'user';
301
+ const dir = getCapabilityDir({ id: options.id, location, cwd: options.cwd });
302
+ if (fs.existsSync(dir) && !options.overwrite) {
303
+ throw new Error(`Capability already exists: ${options.id}`);
304
+ }
305
+ fs.mkdirSync(dir, { recursive: true });
306
+ const now = new Date().toISOString();
307
+ const manifest = {
308
+ schemaVersion: 1,
309
+ id: options.id,
310
+ title: options.title || options.id,
311
+ description: options.description || '',
312
+ whenToUse: options.description ? [options.description] : [],
313
+ whenNotToUse: [],
314
+ tags: [],
315
+ match: [],
316
+ routingHint: 'search-first',
317
+ inputSchema: { type: 'object', properties: {}, required: [] },
318
+ outputSchema: { type: 'object', properties: {} },
319
+ permissions: options.runtime === 'node' ? ['network'] : ['browser.read'],
320
+ sideEffect: 'read',
321
+ requiresConfirmation: false,
322
+ operations: {},
323
+ auth: {
324
+ type: 'none',
325
+ refresh: 'none',
326
+ browserUrls: [],
327
+ requiredCookieNames: [],
328
+ failureSignals: [],
329
+ },
330
+ examples: [],
331
+ entry: 'script.js',
332
+ runtime: options.runtime || 'browser',
333
+ status: 'draft',
334
+ createdBy: options.createdBy || 'user',
335
+ createdAt: now,
336
+ updatedAt: now,
337
+ };
338
+ writeJsonFile({ filePath: path.join(dir, 'capability.json'), value: manifest });
339
+ fs.writeFileSync(path.join(dir, 'script.js'), getDefaultCapabilityScript({ runtime: manifest.runtime }));
340
+ fs.writeFileSync(path.join(dir, 'README.md'), `# ${manifest.title}\n\n${manifest.description}\n`);
341
+ return readCapability({ dir, location });
342
+ }
343
+ export function updateCapabilityManifest(options) {
344
+ const capability = requireCapability({ id: options.id, cwd: options.cwd });
345
+ const changesContract = Object.keys(options.patch).some((key) => {
346
+ return key !== 'status' && key !== 'updatedAt';
347
+ });
348
+ if (options.patch.status === 'trusted' && !options.allowUnvalidatedTrust) {
349
+ if (changesContract) {
350
+ throw new Error(`Capability ${capability.manifest.id} cannot change its contract and become trusted in the same update. Save it as draft, validate the current contract, then trust it.`);
351
+ }
352
+ if (getCapabilityContractHealth(capability).state !== 'healthy') {
353
+ throw new Error(`Capability ${capability.manifest.id} has no passing conformance evidence for its current contract. Run it with --force after repairing it before trusting it.`);
354
+ }
355
+ }
356
+ const nextStatus = (() => {
357
+ if (options.patch.status) {
358
+ return options.patch.status;
359
+ }
360
+ if (changesContract && capability.manifest.status === 'trusted') {
361
+ return 'draft';
362
+ }
363
+ return capability.manifest.status;
364
+ })();
365
+ const nextManifest = {
366
+ ...capability.manifest,
367
+ ...options.patch,
368
+ id: capability.manifest.id,
369
+ schemaVersion: 1,
370
+ status: nextStatus,
371
+ createdAt: capability.manifest.createdAt,
372
+ updatedAt: new Date().toISOString(),
373
+ };
374
+ writeJsonFile({ filePath: capability.manifestPath, value: CapabilityManifestSchema.parse(nextManifest) });
375
+ return readCapability({ dir: capability.dir, location: capability.location });
376
+ }
377
+ export function updateCapabilityScript(options) {
378
+ const capability = requireCapability({ id: options.id, cwd: options.cwd });
379
+ fs.writeFileSync(capability.scriptPath, options.source);
380
+ const nextStatus = capability.manifest.status === 'trusted' ? 'draft' : capability.manifest.status;
381
+ return updateCapabilityManifest({
382
+ id: options.id,
383
+ cwd: options.cwd,
384
+ patch: { status: nextStatus },
385
+ });
386
+ }
387
+ export function readCapabilityScript(options) {
388
+ const capability = requireCapability({ id: options.id, cwd: options.cwd });
389
+ return fs.readFileSync(capability.scriptPath, 'utf-8');
390
+ }
391
+ export function readCapabilitySecrets(options) {
392
+ const secretsPath = path.join(options.capability.dir, 'secrets.json');
393
+ if (!fs.existsSync(secretsPath)) {
394
+ return {};
395
+ }
396
+ const parsed = JSON.parse(fs.readFileSync(secretsPath, 'utf-8'));
397
+ if (!isPlainObject(parsed)) {
398
+ throw new Error(`Capability secrets.json must contain an object: ${secretsPath}`);
399
+ }
400
+ return parsed;
401
+ }
402
+ export function writeCapabilitySecrets(options) {
403
+ const secretsPath = path.join(options.capability.dir, 'secrets.json');
404
+ fs.mkdirSync(options.capability.dir, { recursive: true });
405
+ fs.writeFileSync(secretsPath, `${JSON.stringify(options.secrets, null, 2)}\n`, { mode: 0o600 });
406
+ if (process.platform === 'win32') {
407
+ return;
408
+ }
409
+ fs.chmodSync(secretsPath, 0o600);
410
+ }
411
+ export function validateJsonAgainstSchema(options) {
412
+ const errors = [];
413
+ const type = typeof options.schema.type === 'string' ? options.schema.type : undefined;
414
+ if (type && !matchesJsonType({ value: options.value, type })) {
415
+ errors.push(`${options.label} must be ${type}`);
416
+ return { valid: errors.length === 0, errors };
417
+ }
418
+ if (type === 'object' || options.schema.properties || options.schema.required) {
419
+ if (!isPlainObject(options.value)) {
420
+ errors.push(`${options.label} must be object`);
421
+ return { valid: false, errors };
422
+ }
423
+ const objectValue = options.value;
424
+ const required = Array.isArray(options.schema.required)
425
+ ? options.schema.required.filter((value) => {
426
+ return typeof value === 'string';
427
+ })
428
+ : [];
429
+ const properties = isPlainObject(options.schema.properties) ? options.schema.properties : {};
430
+ errors.push(...required
431
+ .filter((key) => {
432
+ return !(key in objectValue);
433
+ })
434
+ .map((key) => {
435
+ return `${options.label}.${key} is required`;
436
+ }));
437
+ errors.push(...Object.entries(properties).flatMap(([key, rawPropertySchema]) => {
438
+ if (!(key in objectValue)) {
439
+ return [];
440
+ }
441
+ if (!isPlainObject(rawPropertySchema)) {
442
+ return [];
443
+ }
444
+ const propertyType = typeof rawPropertySchema.type === 'string' ? rawPropertySchema.type : undefined;
445
+ if (!propertyType) {
446
+ return [];
447
+ }
448
+ if (matchesJsonType({ value: objectValue[key], type: propertyType })) {
449
+ return [];
450
+ }
451
+ return [`${options.label}.${key} must be ${propertyType}`];
452
+ }));
453
+ }
454
+ return { valid: errors.length === 0, errors };
455
+ }
456
+ function matchesJsonType(options) {
457
+ if (options.type === 'array') {
458
+ return Array.isArray(options.value);
459
+ }
460
+ if (options.type === 'object') {
461
+ return isPlainObject(options.value);
462
+ }
463
+ if (options.type === 'integer') {
464
+ return Number.isInteger(options.value);
465
+ }
466
+ if (options.type === 'number') {
467
+ return typeof options.value === 'number';
468
+ }
469
+ if (options.type === 'string') {
470
+ return typeof options.value === 'string';
471
+ }
472
+ if (options.type === 'boolean') {
473
+ return typeof options.value === 'boolean';
474
+ }
475
+ if (options.type === 'null') {
476
+ return options.value === null;
477
+ }
478
+ return true;
479
+ }
480
+ function isPlainObject(value) {
481
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
482
+ }
483
+ export function appendCapabilityRun(options) {
484
+ fs.appendFileSync(path.join(options.capability.dir, 'runs.jsonl'), `${JSON.stringify(options.record)}\n`);
485
+ }
486
+ export function readCapabilityRuns(options) {
487
+ const runsPath = path.join(options.capability.dir, 'runs.jsonl');
488
+ if (!fs.existsSync(runsPath)) {
489
+ return [];
490
+ }
491
+ const lines = fs
492
+ .readFileSync(runsPath, 'utf-8')
493
+ .split(/\r?\n/)
494
+ .filter((line) => {
495
+ return line.trim().length > 0;
496
+ });
497
+ const selectedLines = typeof options.limit === 'number' ? lines.slice(-options.limit) : lines;
498
+ return selectedLines.flatMap((line) => {
499
+ const value = (() => {
500
+ try {
501
+ return JSON.parse(line);
502
+ }
503
+ catch {
504
+ return null;
505
+ }
506
+ })();
507
+ const parsed = CapabilityRunRecordSchema.safeParse(value);
508
+ if (!parsed.success) {
509
+ return [];
510
+ }
511
+ return [parsed.data];
512
+ });
513
+ }
514
+ export function getCapabilityContractFingerprint(capability) {
515
+ const { status: _status, createdAt: _createdAt, updatedAt: _updatedAt, ...contractManifest } = capability.manifest;
516
+ const script = fs.readFileSync(capability.scriptPath, 'utf-8');
517
+ return crypto
518
+ .createHash('sha256')
519
+ .update(JSON.stringify({ manifest: contractManifest, script }))
520
+ .digest('hex');
521
+ }
522
+ export function getCapabilityContractHealth(capability) {
523
+ const fingerprintResult = (() => {
524
+ try {
525
+ return { success: true, fingerprint: getCapabilityContractFingerprint(capability) };
526
+ }
527
+ catch (error) {
528
+ const message = error instanceof Error ? error.message : String(error);
529
+ return { success: false, reason: `Cannot validate the capability entry script: ${message}` };
530
+ }
531
+ })();
532
+ if (!fingerprintResult.success) {
533
+ return {
534
+ state: 'drifted',
535
+ reasons: [fingerprintResult.reason],
536
+ };
537
+ }
538
+ const fingerprint = fingerprintResult.fingerprint;
539
+ const latestContractRun = readCapabilityRuns({ capability, limit: 100 })
540
+ .reverse()
541
+ .find((run) => {
542
+ return run.contract?.fingerprint === fingerprint && run.contract.status !== 'unknown';
543
+ });
544
+ if (!latestContractRun?.contract) {
545
+ return {
546
+ state: 'unknown',
547
+ reasons: ['No conformance evidence exists for the current script and contract.'],
548
+ };
549
+ }
550
+ if (latestContractRun.contract.status === 'failed') {
551
+ return {
552
+ state: 'drifted',
553
+ checkedAt: latestContractRun.createdAt,
554
+ reasons: latestContractRun.contract.failures.map((failure) => {
555
+ return failure.message;
556
+ }),
557
+ };
558
+ }
559
+ return {
560
+ state: 'healthy',
561
+ checkedAt: latestContractRun.createdAt,
562
+ reasons: [],
563
+ };
564
+ }
565
+ export function getCapabilityLifecycle(capability) {
566
+ const contractHealth = getCapabilityContractHealth(capability);
567
+ const stage = (() => {
568
+ if (capability.manifest.status === 'disabled') {
569
+ return 'disabled';
570
+ }
571
+ if (contractHealth.state === 'drifted') {
572
+ return 'drifted';
573
+ }
574
+ if (capability.manifest.status === 'trusted') {
575
+ return 'trusted';
576
+ }
577
+ if (contractHealth.state === 'healthy') {
578
+ return 'validated';
579
+ }
580
+ return 'drafted';
581
+ })();
582
+ const nextAction = (() => {
583
+ if (stage === 'disabled') {
584
+ return 'enable';
585
+ }
586
+ if (stage === 'drifted') {
587
+ return 'repair';
588
+ }
589
+ if (stage === 'validated') {
590
+ return 'trust';
591
+ }
592
+ if (stage === 'trusted') {
593
+ return 'run';
594
+ }
595
+ return 'validate';
596
+ })();
597
+ const nextCommand = (() => {
598
+ if (nextAction === 'enable') {
599
+ return `tabwright capability draft ${capability.manifest.id}`;
600
+ }
601
+ if (nextAction === 'repair') {
602
+ return `tabwright capability show ${capability.manifest.id}`;
603
+ }
604
+ if (nextAction === 'trust') {
605
+ return `tabwright capability trust ${capability.manifest.id}`;
606
+ }
607
+ const exampleInput = capability.manifest.examples.find((example) => {
608
+ return isPlainObject(example.input);
609
+ })?.input;
610
+ const input = isPlainObject(exampleInput) ? exampleInput : {};
611
+ const operation = (() => {
612
+ try {
613
+ return resolveCapabilityOperation({ capability, input });
614
+ }
615
+ catch {
616
+ return undefined;
617
+ }
618
+ })();
619
+ const args = [
620
+ 'tabwright',
621
+ 'capability',
622
+ 'run',
623
+ capability.manifest.id,
624
+ ...(capability.manifest.runtime === 'browser' ? ['--browser', 'user'] : []),
625
+ '--input-json',
626
+ quoteShell(JSON.stringify(input)),
627
+ ...(nextAction === 'validate' ? ['--force'] : []),
628
+ ...(operation?.requiresConfirmation ? ['--confirm', operation.confirmationToken] : []),
629
+ '--json',
630
+ ];
631
+ return args.join(' ');
632
+ })();
633
+ return { stage, nextAction, nextCommand, contractHealth };
634
+ }
635
+ export function getCapabilityAutonomy(capability, operation) {
636
+ const contractHealth = getCapabilityContractHealth(capability);
637
+ const operations = operation ? [operation] : getCapabilityOperations(capability);
638
+ const blockers = [
639
+ capability.manifest.status === 'trusted' ? '' : `status is ${capability.manifest.status}`,
640
+ contractHealth.state === 'drifted' ? 'current contract failed conformance' : '',
641
+ ...operations.flatMap((candidate) => {
642
+ return [
643
+ candidate.sideEffect === 'read'
644
+ ? ''
645
+ : `${candidate.id ? `operation ${candidate.id} ` : ''}sideEffect is ${candidate.sideEffect}`,
646
+ candidate.requiresConfirmation
647
+ ? `${candidate.id ? `operation ${candidate.id} ` : ''}requires confirmation`
648
+ : '',
649
+ ];
650
+ }),
651
+ ].filter((reason) => {
652
+ return reason.length > 0;
653
+ });
654
+ return {
655
+ allowed: blockers.length === 0,
656
+ reasons: blockers.length === 0 ? ['trusted read-only capability'] : blockers,
657
+ };
658
+ }
659
+ export function toCapabilityContract(capability) {
660
+ const safety = getCapabilitySafetySummary(capability);
661
+ const operations = Object.fromEntries(getCapabilityOperations(capability)
662
+ .filter((operation) => {
663
+ return operation.id !== undefined;
664
+ })
665
+ .map((operation) => {
666
+ return [
667
+ operation.id,
668
+ {
669
+ title: operation.title,
670
+ description: operation.description,
671
+ match: operation.match,
672
+ routingHint: operation.routingHint,
673
+ inputSchema: operation.inputSchema,
674
+ outputSchema: operation.outputSchema,
675
+ permissions: operation.permissions,
676
+ sideEffect: operation.sideEffect,
677
+ requiresConfirmation: operation.requiresConfirmation,
678
+ confirmationToken: operation.confirmationToken,
679
+ autonomousInvocation: getCapabilityAutonomy(capability, operation),
680
+ },
681
+ ];
682
+ }));
683
+ return {
684
+ ...toCapabilitySummary(capability),
685
+ whenToUse: capability.manifest.whenToUse,
686
+ whenNotToUse: capability.manifest.whenNotToUse,
687
+ tags: capability.manifest.tags,
688
+ sideEffect: safety.sideEffect,
689
+ requiresConfirmation: safety.requiresConfirmation,
690
+ auth: capability.manifest.auth,
691
+ examples: capability.manifest.examples,
692
+ autonomousInvocation: getCapabilityAutonomy(capability),
693
+ operations,
694
+ recentRuns: readCapabilityRuns({ capability, limit: 5 }),
695
+ lifecycle: getCapabilityLifecycle(capability),
696
+ };
697
+ }
698
+ export function searchCapabilities(options) {
699
+ const tokens = tokenizeSearchQuery(options.query);
700
+ if (options.query.trim() && tokens.length === 0) {
701
+ return [];
702
+ }
703
+ const results = dedupeCapabilitiesById(listCapabilities({ cwd: options.cwd }))
704
+ .map((capability) => {
705
+ return scoreCapabilitySearch({ capability, tokens });
706
+ })
707
+ .filter((result) => {
708
+ if (tokens.length === 0) {
709
+ return true;
710
+ }
711
+ if (tokens.length === 1) {
712
+ return result.score > 0;
713
+ }
714
+ return result.matchedTokenCount >= 2;
715
+ })
716
+ .sort((left, right) => {
717
+ return right.score - left.score || left.capability.manifest.id.localeCompare(right.capability.manifest.id);
718
+ });
719
+ const limitedResults = typeof options.limit === 'number' ? results.slice(0, options.limit) : results;
720
+ return limitedResults.map((result) => {
721
+ return {
722
+ capability: result.capability,
723
+ score: result.score,
724
+ reasons: result.reasons,
725
+ };
726
+ });
727
+ }
728
+ export function routeCapabilities(options) {
729
+ const task = options.task.trim();
730
+ if (!task) {
731
+ return [];
732
+ }
733
+ const candidates = getRouteCandidateTexts(task);
734
+ const routes = dedupeCapabilitiesById(listCapabilities({ cwd: options.cwd })).flatMap((capability) => {
735
+ return getCapabilityOperations(capability)
736
+ .filter((operation) => {
737
+ return operation.routingHint === 'exact-match-direct-run';
738
+ })
739
+ .filter((operation) => {
740
+ return getCapabilityAutonomy(capability, operation).allowed;
741
+ })
742
+ .flatMap((operation) => {
743
+ const matchedText = candidates.find((candidate) => {
744
+ return operation.match.length > 0 && capabilityOperationMatchesText({ operation, text: candidate });
745
+ });
746
+ if (!matchedText) {
747
+ return [];
748
+ }
749
+ const input = buildRouteInput({ capability, operation, task, matchedText });
750
+ const shellCommand = buildCapabilityRunCommand({ id: capability.manifest.id, input });
751
+ return [
752
+ {
753
+ capability,
754
+ operation: operation.id,
755
+ input,
756
+ command: shellCommand,
757
+ shellCommand,
758
+ commandWarning: buildCapabilityCommandWarning({ id: capability.manifest.id }),
759
+ executionHint: {
760
+ routeCanRunSandboxed: true,
761
+ runRequiresEscalatedSandbox: true,
762
+ commandMustStartWith: 'tabwright capability run ',
763
+ reason: 'capability run writes runs.jsonl and may write artifacts under ~/.tabwright/capabilities; use escalated/unsandboxed execution in Codex sandbox',
764
+ },
765
+ reasons: [
766
+ `${operation.id ? `operation: ${operation.id}, ` : ''}routingHint: exact-match-direct-run`,
767
+ 'autonomousInvocation: trusted read-only capability',
768
+ `matched: ${matchedText}`,
769
+ ],
770
+ matchedText,
771
+ },
772
+ ];
773
+ });
774
+ });
775
+ return typeof options.limit === 'number' ? routes.slice(0, options.limit) : routes;
776
+ }
777
+ function dedupeCapabilitiesById(capabilities) {
778
+ return capabilities.filter((capability, index) => {
779
+ return (capabilities.findIndex((candidate) => {
780
+ return candidate.manifest.id === capability.manifest.id;
781
+ }) === index);
782
+ });
783
+ }
784
+ function getRouteCandidateTexts(task) {
785
+ const urls = task.match(/https?:\/\/[^\s<>"']+/g) || [];
786
+ return Array.from(new Set([task, ...urls].map((value) => {
787
+ return value.replace(/[),,。;;]+$/g, '');
788
+ })));
789
+ }
790
+ function buildRouteInput(options) {
791
+ const actionInput = options.operation.id ? { action: options.operation.id } : {};
792
+ if (options.matchedText.startsWith('http') &&
793
+ hasInputProperty({ schema: options.operation.inputSchema, name: 'url' })) {
794
+ return { ...actionInput, url: options.matchedText };
795
+ }
796
+ if (hasInputProperty({ schema: options.operation.inputSchema, name: 'query' })) {
797
+ return { ...actionInput, query: options.task };
798
+ }
799
+ return actionInput;
800
+ }
801
+ function hasInputProperty(options) {
802
+ const properties = isPlainObject(options.schema.properties) ? options.schema.properties : {};
803
+ return properties[options.name] !== undefined;
804
+ }
805
+ export function buildCapabilityRunCommand(options) {
806
+ return `tabwright capability run ${options.id} --input-json ${quoteShell(JSON.stringify(options.input))} --json`;
807
+ }
808
+ function buildCapabilityCommandWarning(options) {
809
+ return `${options.id} is a Tabwright capability id, not a shell command. Do not run "${options.id} ..."; run shellCommand exactly.`;
810
+ }
811
+ function quoteShell(value) {
812
+ return `'${value.replace(/'/g, "'\\''")}'`;
813
+ }
814
+ export function toCapabilitySummary(capability) {
815
+ const safety = getCapabilitySafetySummary(capability);
816
+ return {
817
+ id: capability.manifest.id,
818
+ title: capability.manifest.title,
819
+ description: capability.manifest.description,
820
+ status: capability.manifest.status,
821
+ runtime: capability.manifest.runtime,
822
+ match: capability.manifest.match,
823
+ routingHint: capability.manifest.routingHint,
824
+ permissions: capability.manifest.permissions,
825
+ sideEffect: safety.sideEffect,
826
+ requiresConfirmation: safety.requiresConfirmation,
827
+ operations: capability.manifest.operations,
828
+ whenToUse: capability.manifest.whenToUse,
829
+ whenNotToUse: capability.manifest.whenNotToUse,
830
+ tags: capability.manifest.tags,
831
+ auth: capability.manifest.auth,
832
+ inputSchema: capability.manifest.inputSchema,
833
+ outputSchema: capability.manifest.outputSchema,
834
+ location: capability.location,
835
+ dir: capability.dir,
836
+ };
837
+ }
838
+ const CAPABILITY_SEARCH_STOP_WORDS = new Set([
839
+ 'a',
840
+ 'an',
841
+ 'and',
842
+ 'for',
843
+ 'in',
844
+ 'of',
845
+ 'on',
846
+ 'only',
847
+ 'or',
848
+ 'please',
849
+ 'read',
850
+ 'the',
851
+ 'to',
852
+ 'use',
853
+ 'with',
854
+ ]);
855
+ function tokenizeSearchQuery(query) {
856
+ return query
857
+ .toLowerCase()
858
+ .split(/[^a-z0-9\u4e00-\u9fff]+/)
859
+ .map((token) => {
860
+ return token.trim();
861
+ })
862
+ .filter((token) => {
863
+ return token.length > 0 && !CAPABILITY_SEARCH_STOP_WORDS.has(token);
864
+ });
865
+ }
866
+ function scoreCapabilitySearch(options) {
867
+ const operations = Object.entries(options.capability.manifest.operations);
868
+ const weightedFields = [
869
+ { label: 'id', weight: 5, values: [options.capability.manifest.id] },
870
+ { label: 'title', weight: 6, values: [options.capability.manifest.title] },
871
+ { label: 'description', weight: 4, values: [options.capability.manifest.description] },
872
+ { label: 'whenToUse', weight: 8, values: options.capability.manifest.whenToUse },
873
+ { label: 'tags', weight: 6, values: options.capability.manifest.tags },
874
+ { label: 'match', weight: 3, values: options.capability.manifest.match },
875
+ {
876
+ label: 'operations',
877
+ weight: 6,
878
+ values: operations.flatMap(([id, operation]) => {
879
+ return [id, operation.title, operation.description, ...operation.match];
880
+ }),
881
+ },
882
+ ];
883
+ const matches = weightedFields.flatMap((field) => {
884
+ const text = field.values.join(' ').toLowerCase();
885
+ const matchedTokens = options.tokens.filter((token) => {
886
+ return text.includes(token);
887
+ });
888
+ if (matchedTokens.length === 0) {
889
+ return [];
890
+ }
891
+ return [
892
+ {
893
+ score: matchedTokens.length * field.weight,
894
+ reason: `${field.label}: ${matchedTokens.join(', ')}`,
895
+ matchedTokens,
896
+ },
897
+ ];
898
+ });
899
+ const negativeMatches = options.capability.manifest.whenNotToUse.flatMap((text) => {
900
+ const lowerText = text.toLowerCase();
901
+ const matchedTokens = options.tokens.filter((token) => {
902
+ return lowerText.includes(token);
903
+ });
904
+ if (matchedTokens.length === 0) {
905
+ return [];
906
+ }
907
+ return [matchedTokens.length * 3];
908
+ });
909
+ return {
910
+ capability: options.capability,
911
+ score: matches.reduce((total, match) => {
912
+ return total + match.score;
913
+ }, 0) -
914
+ negativeMatches.reduce((total, score) => {
915
+ return total + score;
916
+ }, 0),
917
+ reasons: matches.map((match) => {
918
+ return match.reason;
919
+ }),
920
+ matchedTokenCount: new Set(matches.flatMap((match) => {
921
+ return match.matchedTokens;
922
+ })).size,
923
+ };
924
+ }
925
+ function getDefaultCapabilityScript(options) {
926
+ if (options.runtime === 'node') {
927
+ return ['return {', ' input,', ' hasSecrets: Object.keys(secrets).length > 0,', '}', ''].join('\n');
928
+ }
929
+ return ['const currentUrl = page.url()', '', 'return {', ' currentUrl,', ' input,', '}', ''].join('\n');
930
+ }
931
+ //# sourceMappingURL=capability-registry.js.map