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,555 @@
1
+ import crypto from 'node:crypto'
2
+ import fs from 'node:fs'
3
+ import path from 'node:path'
4
+ import { Readable } from 'node:stream'
5
+ import { pipeline } from 'node:stream/promises'
6
+ import zlib from 'node:zlib'
7
+ import * as tar from 'tar-stream'
8
+ import { z } from 'zod'
9
+ import {
10
+ getCapabilityDir,
11
+ parseCapabilityManifest,
12
+ readCapability,
13
+ requireCapability,
14
+ type CapabilityLocation,
15
+ type CapabilityManifest,
16
+ type CapabilityRecord,
17
+ } from './capability-registry.js'
18
+ import { removeCapabilityAuthFiles } from './capability-auth-state.js'
19
+
20
+ const PACKAGE_METADATA_PATH = 'tabwright-package.json'
21
+ const LEGACY_PACKAGE_METADATA_PATH = 'playwriter-package.json'
22
+ const PACKAGE_ROOT = 'package'
23
+ const MAX_ARCHIVE_BYTES = 10 * 1024 * 1024
24
+ const MAX_EXTRACTED_BYTES = 20 * 1024 * 1024
25
+ const MAX_PACKAGE_FILES = 100
26
+
27
+ const CapabilityPackageMetadataSchema = z.object({
28
+ schemaVersion: z.literal(1),
29
+ capabilityId: z.string(),
30
+ packedAt: z.string(),
31
+ files: z.array(
32
+ z.object({
33
+ path: z.string(),
34
+ sha256: z.string(),
35
+ }),
36
+ ),
37
+ })
38
+
39
+ interface CapabilityPackageFile {
40
+ path: string
41
+ content: Buffer
42
+ }
43
+
44
+ export interface PackedCapability {
45
+ capabilityId: string
46
+ path: string
47
+ files: string[]
48
+ integrity: string
49
+ }
50
+
51
+ export interface InstalledCapabilityPackage {
52
+ source: string
53
+ capability: CapabilityRecord
54
+ files: string[]
55
+ integrity: string
56
+ agentSkillAvailable: boolean
57
+ }
58
+
59
+ export async function packCapability(options: {
60
+ id: string
61
+ cwd?: string
62
+ output?: string
63
+ overwrite?: boolean
64
+ }): Promise<PackedCapability> {
65
+ const capability = requireCapability({ id: options.id, cwd: options.cwd })
66
+ const files = readCapabilityPackageFiles({
67
+ sourceDir: capability.dir,
68
+ manifest: {
69
+ ...capability.manifest,
70
+ status: 'draft',
71
+ },
72
+ })
73
+ const metadata = buildPackageMetadata({ capabilityId: capability.manifest.id, files })
74
+ const archiveFiles: CapabilityPackageFile[] = [
75
+ ...files,
76
+ {
77
+ path: PACKAGE_METADATA_PATH,
78
+ content: Buffer.from(`${JSON.stringify(metadata, null, 2)}\n`),
79
+ },
80
+ ]
81
+ const outputPath = path.resolve(options.cwd || process.cwd(), options.output || `${capability.manifest.id}.tgz`)
82
+ if (fs.existsSync(outputPath) && !options.overwrite) {
83
+ throw new Error(`Capability package already exists: ${outputPath}. Use --force to overwrite it.`)
84
+ }
85
+ fs.mkdirSync(path.dirname(outputPath), { recursive: true })
86
+ const temporaryPath = `${outputPath}.partial-${process.pid}`
87
+
88
+ try {
89
+ await writeArchive({ outputPath: temporaryPath, files: archiveFiles })
90
+ if (options.overwrite) {
91
+ fs.rmSync(outputPath, { force: true })
92
+ }
93
+ fs.renameSync(temporaryPath, outputPath)
94
+ } catch (error) {
95
+ if (fs.existsSync(temporaryPath)) {
96
+ fs.rmSync(temporaryPath, { force: true })
97
+ }
98
+ throw new Error(`Failed to pack capability ${capability.manifest.id}`, { cause: error })
99
+ }
100
+
101
+ return {
102
+ capabilityId: capability.manifest.id,
103
+ path: outputPath,
104
+ files: files.map((file) => {
105
+ return file.path
106
+ }),
107
+ integrity: fileIntegrity(outputPath),
108
+ }
109
+ }
110
+
111
+ export async function installCapabilityPackage(options: {
112
+ source: string
113
+ cwd?: string
114
+ location?: CapabilityLocation
115
+ overwrite?: boolean
116
+ }): Promise<InstalledCapabilityPackage> {
117
+ const cwd = options.cwd || process.cwd()
118
+ const source = await readPackageSource({ source: options.source, cwd })
119
+ const manifestFile = requirePackageFile({ files: source.files, filePath: 'capability.json' })
120
+ const manifest = parsePackageManifest(manifestFile.content)
121
+ validatePackageMetadata({ files: source.files, metadataFile: source.metadataFile, manifest })
122
+ const files = normalizeInstallFiles({ files: source.files, manifest })
123
+
124
+ const location = options.location || 'user'
125
+ const capabilityDir = getCapabilityDir({ id: manifest.id, location, cwd })
126
+ if (fs.existsSync(capabilityDir) && !options.overwrite) {
127
+ throw new Error(`Capability already exists: ${manifest.id}. Use --force to overwrite package files.`)
128
+ }
129
+ if (options.overwrite) {
130
+ fs.rmSync(path.join(capabilityDir, 'agent-skills'), { recursive: true, force: true })
131
+ removeCapabilityAuthFiles({ capabilityDir })
132
+ }
133
+ fs.mkdirSync(capabilityDir, { recursive: true })
134
+ files.map((file) => {
135
+ const destination = resolvePackageDestination({ capabilityDir, filePath: file.path })
136
+ fs.mkdirSync(path.dirname(destination), { recursive: true })
137
+ fs.writeFileSync(destination, file.content)
138
+ return destination
139
+ })
140
+
141
+ const capability = readCapability({ dir: capabilityDir, location })
142
+ return {
143
+ source: source.label,
144
+ capability,
145
+ files: files.map((file) => {
146
+ return file.path
147
+ }),
148
+ integrity: source.integrity,
149
+ agentSkillAvailable: fs.existsSync(path.join(capabilityDir, 'agent-skills', 'codex', 'SKILL.md')),
150
+ }
151
+ }
152
+
153
+ function readCapabilityPackageFiles(options: {
154
+ sourceDir: string
155
+ manifest: CapabilityManifest
156
+ }): CapabilityPackageFile[] {
157
+ const entryPath = normalizeRelativePath(options.manifest.entry)
158
+ const requiredPaths = ['capability.json', entryPath]
159
+ const missing = requiredPaths.filter((filePath) => {
160
+ return !fs.existsSync(path.join(options.sourceDir, ...filePath.split('/')))
161
+ })
162
+ if (missing.length > 0) {
163
+ throw new Error(`Capability package is missing required files: ${missing.join(', ')}`)
164
+ }
165
+ const optionalPaths = ['README.md'].filter((filePath) => {
166
+ return fs.existsSync(path.join(options.sourceDir, filePath))
167
+ })
168
+ const agentSkillDir = path.join(options.sourceDir, 'agent-skills')
169
+ const agentSkillPaths = fs.existsSync(agentSkillDir)
170
+ ? listRegularFiles({ dir: agentSkillDir }).map((filePath) => {
171
+ return path.posix.join('agent-skills', filePath)
172
+ })
173
+ : []
174
+ const packagePaths = [...new Set([...requiredPaths, ...optionalPaths, ...agentSkillPaths])].sort()
175
+ assertPackageLimits({ paths: packagePaths })
176
+
177
+ const files = packagePaths.map((filePath) => {
178
+ if (filePath === 'capability.json') {
179
+ return {
180
+ path: filePath,
181
+ content: Buffer.from(`${JSON.stringify(options.manifest, null, 2)}\n`),
182
+ }
183
+ }
184
+ const sourcePath = resolvePackageDestination({ capabilityDir: options.sourceDir, filePath })
185
+ const sourceStat = fs.lstatSync(sourcePath)
186
+ if (!sourceStat.isFile() || sourceStat.isSymbolicLink()) {
187
+ throw new Error(`Capability packages can only contain regular files: ${filePath}`)
188
+ }
189
+ return { path: filePath, content: fs.readFileSync(sourcePath) }
190
+ })
191
+ assertExtractedSize(files)
192
+ return files
193
+ }
194
+
195
+ function listRegularFiles(options: { dir: string; prefix?: string }): string[] {
196
+ return fs.readdirSync(options.dir, { withFileTypes: true }).flatMap((entry) => {
197
+ const relativePath = path.posix.join(options.prefix || '', entry.name)
198
+ const absolutePath = path.join(options.dir, entry.name)
199
+ if (entry.isSymbolicLink()) {
200
+ throw new Error(`Capability packages cannot contain symbolic links: ${relativePath}`)
201
+ }
202
+ if (entry.isDirectory()) {
203
+ return listRegularFiles({ dir: absolutePath, prefix: relativePath })
204
+ }
205
+ if (!entry.isFile()) {
206
+ throw new Error(`Capability packages can only contain regular files: ${relativePath}`)
207
+ }
208
+ return [relativePath]
209
+ })
210
+ }
211
+
212
+ function buildPackageMetadata(options: {
213
+ capabilityId: string
214
+ files: CapabilityPackageFile[]
215
+ }): z.infer<typeof CapabilityPackageMetadataSchema> {
216
+ return {
217
+ schemaVersion: 1,
218
+ capabilityId: options.capabilityId,
219
+ packedAt: new Date().toISOString(),
220
+ files: options.files.map((file) => {
221
+ return { path: file.path, sha256: bufferSha256(file.content) }
222
+ }),
223
+ }
224
+ }
225
+
226
+ async function writeArchive(options: { outputPath: string; files: CapabilityPackageFile[] }): Promise<void> {
227
+ const archive = tar.pack()
228
+ const output = pipeline(archive, zlib.createGzip({ level: 9 }), fs.createWriteStream(options.outputPath))
229
+ await Promise.all(
230
+ options.files.map((file) => {
231
+ return new Promise<void>((resolve, reject) => {
232
+ archive.entry(
233
+ {
234
+ name: path.posix.join(PACKAGE_ROOT, file.path),
235
+ size: file.content.length,
236
+ mode: 0o644,
237
+ mtime: new Date(0),
238
+ type: 'file',
239
+ },
240
+ file.content,
241
+ (error) => {
242
+ if (error) {
243
+ reject(error)
244
+ return
245
+ }
246
+ resolve()
247
+ },
248
+ )
249
+ })
250
+ }),
251
+ )
252
+ archive.finalize()
253
+ await output
254
+ }
255
+
256
+ async function readPackageSource(options: {
257
+ source: string
258
+ cwd: string
259
+ }): Promise<{
260
+ label: string
261
+ files: CapabilityPackageFile[]
262
+ metadataFile?: CapabilityPackageFile
263
+ integrity: string
264
+ }> {
265
+ const localPath = path.resolve(options.cwd, options.source)
266
+ if (fs.existsSync(localPath)) {
267
+ if (fs.statSync(localPath).isDirectory()) {
268
+ const manifestPath = path.join(localPath, 'capability.json')
269
+ if (!fs.existsSync(manifestPath)) {
270
+ throw new Error(`Capability directory is missing capability.json: ${localPath}`)
271
+ }
272
+ const manifest = parsePackageManifest(fs.readFileSync(manifestPath))
273
+ const files = readCapabilityPackageFiles({ sourceDir: localPath, manifest: { ...manifest, status: 'draft' } })
274
+ return {
275
+ label: localPath,
276
+ files,
277
+ integrity: filesIntegrity(files),
278
+ }
279
+ }
280
+ const archive = fs.readFileSync(localPath)
281
+ assertArchiveSize({ size: archive.length, label: localPath })
282
+ const extracted = await readArchive(archive)
283
+ return {
284
+ label: localPath,
285
+ files: extracted.files,
286
+ metadataFile: extracted.metadataFile,
287
+ integrity: bufferIntegrity(archive),
288
+ }
289
+ }
290
+
291
+ if (!/^https?:\/\//.test(options.source)) {
292
+ throw new Error(`Capability source not found: ${options.source}`)
293
+ }
294
+ const response = await fetch(options.source, { redirect: 'follow' })
295
+ if (!response.ok) {
296
+ throw new Error(`Failed to download capability package: ${response.status} ${response.statusText}`)
297
+ }
298
+ const contentLength = Number(response.headers.get('content-length') || 0)
299
+ assertArchiveSize({ size: contentLength, label: options.source })
300
+ const archive = Buffer.from(await response.arrayBuffer())
301
+ assertArchiveSize({ size: archive.length, label: options.source })
302
+ const extracted = await readArchive(archive)
303
+ return {
304
+ label: options.source,
305
+ files: extracted.files,
306
+ metadataFile: extracted.metadataFile,
307
+ integrity: bufferIntegrity(archive),
308
+ }
309
+ }
310
+
311
+ async function readArchive(archive: Buffer): Promise<{
312
+ files: CapabilityPackageFile[]
313
+ metadataFile: CapabilityPackageFile
314
+ }> {
315
+ const extracted = await extractArchiveFiles(archive)
316
+ const metadataFile =
317
+ extracted.find((file) => {
318
+ return file.path === PACKAGE_METADATA_PATH
319
+ }) || requirePackageFile({ files: extracted, filePath: LEGACY_PACKAGE_METADATA_PATH })
320
+ const files = extracted.filter((file) => {
321
+ return file.path !== PACKAGE_METADATA_PATH && file.path !== LEGACY_PACKAGE_METADATA_PATH
322
+ })
323
+ return { files, metadataFile }
324
+ }
325
+
326
+ async function extractArchiveFiles(archive: Buffer): Promise<CapabilityPackageFile[]> {
327
+ const extractor = tar.extract()
328
+ const files: CapabilityPackageFile[] = []
329
+ let totalBytes = 0
330
+ const extraction = new Promise<void>((resolve, reject) => {
331
+ extractor.on('entry', (header, stream, next) => {
332
+ const relativePath = normalizeArchiveEntryPath(header.name)
333
+ if (header.type === 'directory') {
334
+ stream.resume()
335
+ next()
336
+ return
337
+ }
338
+ if (header.type !== 'file' && header.type !== null && header.type !== undefined) {
339
+ stream.resume()
340
+ next(new Error(`Capability archives cannot contain ${header.type} entries: ${header.name}`))
341
+ return
342
+ }
343
+ readStreamWithLimit({ stream, limit: MAX_EXTRACTED_BYTES })
344
+ .then((content) => {
345
+ if (files.some((file) => file.path === relativePath)) {
346
+ next(new Error(`Capability package contains duplicate path: ${relativePath}`))
347
+ return
348
+ }
349
+ totalBytes += content.length
350
+ if (totalBytes > MAX_EXTRACTED_BYTES) {
351
+ next(new Error(`Capability package expands beyond ${MAX_EXTRACTED_BYTES} bytes`))
352
+ return
353
+ }
354
+ files.push({ path: relativePath, content })
355
+ if (files.length > MAX_PACKAGE_FILES) {
356
+ next(new Error(`Capability package exceeds ${MAX_PACKAGE_FILES} files`))
357
+ return
358
+ }
359
+ next()
360
+ })
361
+ .catch((error: unknown) => {
362
+ next(error)
363
+ })
364
+ })
365
+ extractor.on('finish', resolve)
366
+ extractor.on('error', reject)
367
+ })
368
+ await pipeline(Readable.from(archive), zlib.createGunzip(), extractor)
369
+ await extraction
370
+ assertExtractedSize(files, totalBytes)
371
+ return files
372
+ }
373
+
374
+ async function readStreamWithLimit(options: { stream: Readable; limit: number }): Promise<Buffer> {
375
+ const chunks: Buffer[] = []
376
+ let size = 0
377
+ for await (const rawChunk of options.stream) {
378
+ const chunk = Buffer.isBuffer(rawChunk) ? rawChunk : Buffer.from(rawChunk)
379
+ size += chunk.length
380
+ if (size > options.limit) {
381
+ throw new Error(`Capability package entry exceeds ${options.limit} bytes`)
382
+ }
383
+ chunks.push(chunk)
384
+ }
385
+ return Buffer.concat(chunks)
386
+ }
387
+
388
+ function parsePackageManifest(content: Buffer): CapabilityManifest {
389
+ const raw: unknown = (() => {
390
+ try {
391
+ return JSON.parse(content.toString('utf-8'))
392
+ } catch (error) {
393
+ throw new Error('Capability package has invalid capability.json', { cause: error })
394
+ }
395
+ })()
396
+ return parseCapabilityManifest({
397
+ ...assertJsonObject(raw),
398
+ status: 'draft',
399
+ })
400
+ }
401
+
402
+ function normalizeInstallFiles(options: {
403
+ files: CapabilityPackageFile[]
404
+ manifest: CapabilityManifest
405
+ }): CapabilityPackageFile[] {
406
+ const entryPath = normalizeRelativePath(options.manifest.entry)
407
+ const allowed = options.files.filter((file) => {
408
+ return (
409
+ file.path === 'capability.json' ||
410
+ file.path === entryPath ||
411
+ file.path === 'README.md' ||
412
+ file.path.startsWith('agent-skills/')
413
+ )
414
+ })
415
+ requirePackageFile({ files: allowed, filePath: entryPath })
416
+ const normalizedManifest = {
417
+ ...options.manifest,
418
+ status: 'draft' as const,
419
+ updatedAt: new Date().toISOString(),
420
+ }
421
+ return allowed.map((file) => {
422
+ if (file.path !== 'capability.json') {
423
+ return file
424
+ }
425
+ return {
426
+ path: file.path,
427
+ content: Buffer.from(`${JSON.stringify(normalizedManifest, null, 2)}\n`),
428
+ }
429
+ })
430
+ }
431
+
432
+ function validatePackageMetadata(options: {
433
+ files: CapabilityPackageFile[]
434
+ metadataFile?: CapabilityPackageFile
435
+ manifest: CapabilityManifest
436
+ }): void {
437
+ if (!options.metadataFile) {
438
+ return
439
+ }
440
+ const metadata = CapabilityPackageMetadataSchema.parse(JSON.parse(options.metadataFile.content.toString('utf-8')))
441
+ if (metadata.capabilityId !== options.manifest.id) {
442
+ throw new Error(`Capability package id mismatch: ${metadata.capabilityId} !== ${options.manifest.id}`)
443
+ }
444
+ const actualHashes = new Map(
445
+ options.files.map((file) => {
446
+ return [file.path, bufferSha256(file.content)]
447
+ }),
448
+ )
449
+ const mismatches = metadata.files.filter((file) => {
450
+ return actualHashes.get(file.path) !== file.sha256
451
+ })
452
+ if (mismatches.length > 0 || metadata.files.length !== options.files.length) {
453
+ const detail = mismatches.length > 0 ? mismatches.map((file) => file.path).join(', ') : 'file count mismatch'
454
+ throw new Error(`Capability package integrity check failed: ${detail}`)
455
+ }
456
+ }
457
+
458
+ function requirePackageFile(options: {
459
+ files: CapabilityPackageFile[]
460
+ filePath: string
461
+ }): CapabilityPackageFile {
462
+ const file = options.files.find((candidate) => {
463
+ return candidate.path === options.filePath
464
+ })
465
+ if (!file) {
466
+ throw new Error(`Capability package is missing ${options.filePath}`)
467
+ }
468
+ return file
469
+ }
470
+
471
+ function normalizeArchiveEntryPath(entryPath: string): string {
472
+ const normalized = normalizeRelativePath(entryPath)
473
+ if (!normalized.startsWith(`${PACKAGE_ROOT}/`)) {
474
+ throw new Error(`Capability archive entries must stay under ${PACKAGE_ROOT}/: ${entryPath}`)
475
+ }
476
+ return normalizeRelativePath(normalized.slice(PACKAGE_ROOT.length + 1))
477
+ }
478
+
479
+ function normalizeRelativePath(filePath: string): string {
480
+ const slashPath = filePath.replaceAll('\\', '/')
481
+ const normalized = path.posix.normalize(slashPath)
482
+ if (
483
+ normalized === '.' ||
484
+ normalized.startsWith('/') ||
485
+ normalized === '..' ||
486
+ normalized.startsWith('../') ||
487
+ normalized.includes('\0')
488
+ ) {
489
+ throw new Error(`Capability package path must be relative and stay inside the package: ${filePath}`)
490
+ }
491
+ return normalized
492
+ }
493
+
494
+ function resolvePackageDestination(options: { capabilityDir: string; filePath: string }): string {
495
+ const normalized = normalizeRelativePath(options.filePath)
496
+ const root = path.resolve(options.capabilityDir)
497
+ const destination = path.resolve(root, ...normalized.split('/'))
498
+ if (destination !== root && !destination.startsWith(`${root}${path.sep}`)) {
499
+ throw new Error(`Capability package path escapes its destination: ${options.filePath}`)
500
+ }
501
+ return destination
502
+ }
503
+
504
+ function assertPackageLimits(options: { paths: string[] }): void {
505
+ if (options.paths.length > MAX_PACKAGE_FILES) {
506
+ throw new Error(`Capability package exceeds ${MAX_PACKAGE_FILES} files`)
507
+ }
508
+ }
509
+
510
+ function assertArchiveSize(options: { size: number; label: string }): void {
511
+ if (options.size > MAX_ARCHIVE_BYTES) {
512
+ throw new Error(`Capability package exceeds ${MAX_ARCHIVE_BYTES} bytes: ${options.label}`)
513
+ }
514
+ }
515
+
516
+ function assertExtractedSize(files: CapabilityPackageFile[], knownSize?: number): void {
517
+ const totalBytes =
518
+ knownSize ??
519
+ files.reduce((total, file) => {
520
+ return total + file.content.length
521
+ }, 0)
522
+ if (totalBytes > MAX_EXTRACTED_BYTES) {
523
+ throw new Error(`Capability package expands beyond ${MAX_EXTRACTED_BYTES} bytes`)
524
+ }
525
+ }
526
+
527
+ function assertJsonObject(value: unknown): Record<string, unknown> {
528
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
529
+ throw new Error('Capability package manifest must be an object')
530
+ }
531
+ return value as Record<string, unknown>
532
+ }
533
+
534
+ function bufferSha256(content: Buffer): string {
535
+ return crypto.createHash('sha256').update(content).digest('hex')
536
+ }
537
+
538
+ function bufferIntegrity(content: Buffer): string {
539
+ return `sha256-${crypto.createHash('sha256').update(content).digest('base64')}`
540
+ }
541
+
542
+ function fileIntegrity(filePath: string): string {
543
+ return bufferIntegrity(fs.readFileSync(filePath))
544
+ }
545
+
546
+ function filesIntegrity(files: CapabilityPackageFile[]): string {
547
+ const hash = crypto.createHash('sha256')
548
+ files.map((file) => {
549
+ hash.update(file.path)
550
+ hash.update('\0')
551
+ hash.update(file.content)
552
+ return file.path
553
+ })
554
+ return `sha256-${hash.digest('base64')}`
555
+ }