@metamask/client-mcp-core 0.1.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 (486) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/LICENSE +6 -0
  3. package/LICENSE.APACHE2 +201 -0
  4. package/LICENSE.MIT +21 -0
  5. package/README.md +1459 -0
  6. package/dist/capabilities/context.cjs +34 -0
  7. package/dist/capabilities/context.cjs.map +1 -0
  8. package/dist/capabilities/context.d.cts +101 -0
  9. package/dist/capabilities/context.d.cts.map +1 -0
  10. package/dist/capabilities/context.d.mts +101 -0
  11. package/dist/capabilities/context.d.mts.map +1 -0
  12. package/dist/capabilities/context.mjs +29 -0
  13. package/dist/capabilities/context.mjs.map +1 -0
  14. package/dist/capabilities/index.cjs +18 -0
  15. package/dist/capabilities/index.cjs.map +1 -0
  16. package/dist/capabilities/index.d.cts +3 -0
  17. package/dist/capabilities/index.d.cts.map +1 -0
  18. package/dist/capabilities/index.d.mts +3 -0
  19. package/dist/capabilities/index.d.mts.map +1 -0
  20. package/dist/capabilities/index.mjs +2 -0
  21. package/dist/capabilities/index.mjs.map +1 -0
  22. package/dist/capabilities/types.cjs +3 -0
  23. package/dist/capabilities/types.cjs.map +1 -0
  24. package/dist/capabilities/types.d.cts +152 -0
  25. package/dist/capabilities/types.d.cts.map +1 -0
  26. package/dist/capabilities/types.d.mts +152 -0
  27. package/dist/capabilities/types.d.mts.map +1 -0
  28. package/dist/capabilities/types.mjs +2 -0
  29. package/dist/capabilities/types.mjs.map +1 -0
  30. package/dist/index.cjs +59 -0
  31. package/dist/index.cjs.map +1 -0
  32. package/dist/index.d.cts +33 -0
  33. package/dist/index.d.cts.map +1 -0
  34. package/dist/index.d.mts +33 -0
  35. package/dist/index.d.mts.map +1 -0
  36. package/dist/index.mjs +43 -0
  37. package/dist/index.mjs.map +1 -0
  38. package/dist/launcher/console-error-buffer.cjs +72 -0
  39. package/dist/launcher/console-error-buffer.cjs.map +1 -0
  40. package/dist/launcher/console-error-buffer.d.cts +43 -0
  41. package/dist/launcher/console-error-buffer.d.cts.map +1 -0
  42. package/dist/launcher/console-error-buffer.d.mts +43 -0
  43. package/dist/launcher/console-error-buffer.d.mts.map +1 -0
  44. package/dist/launcher/console-error-buffer.mjs +68 -0
  45. package/dist/launcher/console-error-buffer.mjs.map +1 -0
  46. package/dist/launcher/extension-id-resolver.cjs +177 -0
  47. package/dist/launcher/extension-id-resolver.cjs.map +1 -0
  48. package/dist/launcher/extension-id-resolver.d.cts +32 -0
  49. package/dist/launcher/extension-id-resolver.d.cts.map +1 -0
  50. package/dist/launcher/extension-id-resolver.d.mts +32 -0
  51. package/dist/launcher/extension-id-resolver.d.mts.map +1 -0
  52. package/dist/launcher/extension-id-resolver.mjs +173 -0
  53. package/dist/launcher/extension-id-resolver.mjs.map +1 -0
  54. package/dist/launcher/extension-readiness.cjs +50 -0
  55. package/dist/launcher/extension-readiness.cjs.map +1 -0
  56. package/dist/launcher/extension-readiness.d.cts +37 -0
  57. package/dist/launcher/extension-readiness.d.cts.map +1 -0
  58. package/dist/launcher/extension-readiness.d.mts +37 -0
  59. package/dist/launcher/extension-readiness.d.mts.map +1 -0
  60. package/dist/launcher/extension-readiness.mjs +43 -0
  61. package/dist/launcher/extension-readiness.mjs.map +1 -0
  62. package/dist/launcher/index.cjs +21 -0
  63. package/dist/launcher/index.cjs.map +1 -0
  64. package/dist/launcher/index.d.cts +5 -0
  65. package/dist/launcher/index.d.cts.map +1 -0
  66. package/dist/launcher/index.d.mts +5 -0
  67. package/dist/launcher/index.d.mts.map +1 -0
  68. package/dist/launcher/index.mjs +5 -0
  69. package/dist/launcher/index.mjs.map +1 -0
  70. package/dist/launcher/retry.cjs +35 -0
  71. package/dist/launcher/retry.cjs.map +1 -0
  72. package/dist/launcher/retry.d.cts +20 -0
  73. package/dist/launcher/retry.d.cts.map +1 -0
  74. package/dist/launcher/retry.d.mts +20 -0
  75. package/dist/launcher/retry.d.mts.map +1 -0
  76. package/dist/launcher/retry.mjs +31 -0
  77. package/dist/launcher/retry.mjs.map +1 -0
  78. package/dist/mcp-server/constants.cjs +22 -0
  79. package/dist/mcp-server/constants.cjs.map +1 -0
  80. package/dist/mcp-server/constants.d.cts +13 -0
  81. package/dist/mcp-server/constants.d.cts.map +1 -0
  82. package/dist/mcp-server/constants.d.mts +13 -0
  83. package/dist/mcp-server/constants.d.mts.map +1 -0
  84. package/dist/mcp-server/constants.mjs +19 -0
  85. package/dist/mcp-server/constants.mjs.map +1 -0
  86. package/dist/mcp-server/discovery.cjs +299 -0
  87. package/dist/mcp-server/discovery.cjs.map +1 -0
  88. package/dist/mcp-server/discovery.d.cts +56 -0
  89. package/dist/mcp-server/discovery.d.cts.map +1 -0
  90. package/dist/mcp-server/discovery.d.mts +56 -0
  91. package/dist/mcp-server/discovery.d.mts.map +1 -0
  92. package/dist/mcp-server/discovery.mjs +292 -0
  93. package/dist/mcp-server/discovery.mjs.map +1 -0
  94. package/dist/mcp-server/knowledge-store.cjs +1196 -0
  95. package/dist/mcp-server/knowledge-store.cjs.map +1 -0
  96. package/dist/mcp-server/knowledge-store.d.cts +249 -0
  97. package/dist/mcp-server/knowledge-store.d.cts.map +1 -0
  98. package/dist/mcp-server/knowledge-store.d.mts +249 -0
  99. package/dist/mcp-server/knowledge-store.d.mts.map +1 -0
  100. package/dist/mcp-server/knowledge-store.mjs +1154 -0
  101. package/dist/mcp-server/knowledge-store.mjs.map +1 -0
  102. package/dist/mcp-server/schemas.cjs +433 -0
  103. package/dist/mcp-server/schemas.cjs.map +1 -0
  104. package/dist/mcp-server/schemas.d.cts +557 -0
  105. package/dist/mcp-server/schemas.d.cts.map +1 -0
  106. package/dist/mcp-server/schemas.d.mts +557 -0
  107. package/dist/mcp-server/schemas.d.mts.map +1 -0
  108. package/dist/mcp-server/schemas.mjs +430 -0
  109. package/dist/mcp-server/schemas.mjs.map +1 -0
  110. package/dist/mcp-server/server.cjs +161 -0
  111. package/dist/mcp-server/server.cjs.map +1 -0
  112. package/dist/mcp-server/server.d.cts +24 -0
  113. package/dist/mcp-server/server.d.cts.map +1 -0
  114. package/dist/mcp-server/server.d.mts +24 -0
  115. package/dist/mcp-server/server.d.mts.map +1 -0
  116. package/dist/mcp-server/server.mjs +158 -0
  117. package/dist/mcp-server/server.mjs.map +1 -0
  118. package/dist/mcp-server/session-manager.cjs +53 -0
  119. package/dist/mcp-server/session-manager.cjs.map +1 -0
  120. package/dist/mcp-server/session-manager.d.cts +240 -0
  121. package/dist/mcp-server/session-manager.d.cts.map +1 -0
  122. package/dist/mcp-server/session-manager.d.mts +240 -0
  123. package/dist/mcp-server/session-manager.d.mts.map +1 -0
  124. package/dist/mcp-server/session-manager.mjs +48 -0
  125. package/dist/mcp-server/session-manager.mjs.map +1 -0
  126. package/dist/mcp-server/test-utils/flush-promises.cjs +10 -0
  127. package/dist/mcp-server/test-utils/flush-promises.cjs.map +1 -0
  128. package/dist/mcp-server/test-utils/flush-promises.d.cts +2 -0
  129. package/dist/mcp-server/test-utils/flush-promises.d.cts.map +1 -0
  130. package/dist/mcp-server/test-utils/flush-promises.d.mts +2 -0
  131. package/dist/mcp-server/test-utils/flush-promises.d.mts.map +1 -0
  132. package/dist/mcp-server/test-utils/flush-promises.mjs +7 -0
  133. package/dist/mcp-server/test-utils/flush-promises.mjs.map +1 -0
  134. package/dist/mcp-server/test-utils/index.cjs +13 -0
  135. package/dist/mcp-server/test-utils/index.cjs.map +1 -0
  136. package/dist/mcp-server/test-utils/index.d.cts +4 -0
  137. package/dist/mcp-server/test-utils/index.d.cts.map +1 -0
  138. package/dist/mcp-server/test-utils/index.d.mts +4 -0
  139. package/dist/mcp-server/test-utils/index.d.mts.map +1 -0
  140. package/dist/mcp-server/test-utils/index.mjs +4 -0
  141. package/dist/mcp-server/test-utils/index.mjs.map +1 -0
  142. package/dist/mcp-server/test-utils/mock-factories.cjs +129 -0
  143. package/dist/mcp-server/test-utils/mock-factories.cjs.map +1 -0
  144. package/dist/mcp-server/test-utils/mock-factories.d.cts +89 -0
  145. package/dist/mcp-server/test-utils/mock-factories.d.cts.map +1 -0
  146. package/dist/mcp-server/test-utils/mock-factories.d.mts +89 -0
  147. package/dist/mcp-server/test-utils/mock-factories.d.mts.map +1 -0
  148. package/dist/mcp-server/test-utils/mock-factories.mjs +125 -0
  149. package/dist/mcp-server/test-utils/mock-factories.mjs.map +1 -0
  150. package/dist/mcp-server/test-utils/mock-playwright.cjs +205 -0
  151. package/dist/mcp-server/test-utils/mock-playwright.cjs.map +1 -0
  152. package/dist/mcp-server/test-utils/mock-playwright.d.cts +69 -0
  153. package/dist/mcp-server/test-utils/mock-playwright.d.cts.map +1 -0
  154. package/dist/mcp-server/test-utils/mock-playwright.d.mts +69 -0
  155. package/dist/mcp-server/test-utils/mock-playwright.d.mts.map +1 -0
  156. package/dist/mcp-server/test-utils/mock-playwright.mjs +200 -0
  157. package/dist/mcp-server/test-utils/mock-playwright.mjs.map +1 -0
  158. package/dist/mcp-server/tokenization.cjs +117 -0
  159. package/dist/mcp-server/tokenization.cjs.map +1 -0
  160. package/dist/mcp-server/tokenization.d.cts +22 -0
  161. package/dist/mcp-server/tokenization.d.cts.map +1 -0
  162. package/dist/mcp-server/tokenization.d.mts +22 -0
  163. package/dist/mcp-server/tokenization.d.mts.map +1 -0
  164. package/dist/mcp-server/tokenization.mjs +112 -0
  165. package/dist/mcp-server/tokenization.mjs.map +1 -0
  166. package/dist/mcp-server/tools/batch.cjs +199 -0
  167. package/dist/mcp-server/tools/batch.cjs.map +1 -0
  168. package/dist/mcp-server/tools/batch.d.cts +81 -0
  169. package/dist/mcp-server/tools/batch.d.cts.map +1 -0
  170. package/dist/mcp-server/tools/batch.d.mts +81 -0
  171. package/dist/mcp-server/tools/batch.d.mts.map +1 -0
  172. package/dist/mcp-server/tools/batch.mjs +191 -0
  173. package/dist/mcp-server/tools/batch.mjs.map +1 -0
  174. package/dist/mcp-server/tools/build.cjs +47 -0
  175. package/dist/mcp-server/tools/build.cjs.map +1 -0
  176. package/dist/mcp-server/tools/build.d.cts +22 -0
  177. package/dist/mcp-server/tools/build.d.cts.map +1 -0
  178. package/dist/mcp-server/tools/build.d.mts +22 -0
  179. package/dist/mcp-server/tools/build.d.mts.map +1 -0
  180. package/dist/mcp-server/tools/build.mjs +44 -0
  181. package/dist/mcp-server/tools/build.mjs.map +1 -0
  182. package/dist/mcp-server/tools/cleanup.cjs +20 -0
  183. package/dist/mcp-server/tools/cleanup.cjs.map +1 -0
  184. package/dist/mcp-server/tools/cleanup.d.cts +10 -0
  185. package/dist/mcp-server/tools/cleanup.d.cts.map +1 -0
  186. package/dist/mcp-server/tools/cleanup.d.mts +10 -0
  187. package/dist/mcp-server/tools/cleanup.d.mts.map +1 -0
  188. package/dist/mcp-server/tools/cleanup.mjs +17 -0
  189. package/dist/mcp-server/tools/cleanup.mjs.map +1 -0
  190. package/dist/mcp-server/tools/clipboard.cjs +100 -0
  191. package/dist/mcp-server/tools/clipboard.cjs.map +1 -0
  192. package/dist/mcp-server/tools/clipboard.d.cts +16 -0
  193. package/dist/mcp-server/tools/clipboard.d.cts.map +1 -0
  194. package/dist/mcp-server/tools/clipboard.d.mts +16 -0
  195. package/dist/mcp-server/tools/clipboard.d.mts.map +1 -0
  196. package/dist/mcp-server/tools/clipboard.mjs +97 -0
  197. package/dist/mcp-server/tools/clipboard.mjs.map +1 -0
  198. package/dist/mcp-server/tools/context.cjs +66 -0
  199. package/dist/mcp-server/tools/context.cjs.map +1 -0
  200. package/dist/mcp-server/tools/context.d.cts +35 -0
  201. package/dist/mcp-server/tools/context.d.cts.map +1 -0
  202. package/dist/mcp-server/tools/context.d.mts +35 -0
  203. package/dist/mcp-server/tools/context.d.mts.map +1 -0
  204. package/dist/mcp-server/tools/context.mjs +62 -0
  205. package/dist/mcp-server/tools/context.mjs.map +1 -0
  206. package/dist/mcp-server/tools/definitions.cjs +463 -0
  207. package/dist/mcp-server/tools/definitions.cjs.map +1 -0
  208. package/dist/mcp-server/tools/definitions.d.cts +97 -0
  209. package/dist/mcp-server/tools/definitions.d.cts.map +1 -0
  210. package/dist/mcp-server/tools/definitions.d.mts +97 -0
  211. package/dist/mcp-server/tools/definitions.d.mts.map +1 -0
  212. package/dist/mcp-server/tools/definitions.mjs +451 -0
  213. package/dist/mcp-server/tools/definitions.mjs.map +1 -0
  214. package/dist/mcp-server/tools/discovery-tools.cjs +162 -0
  215. package/dist/mcp-server/tools/discovery-tools.cjs.map +1 -0
  216. package/dist/mcp-server/tools/discovery-tools.d.cts +26 -0
  217. package/dist/mcp-server/tools/discovery-tools.d.cts.map +1 -0
  218. package/dist/mcp-server/tools/discovery-tools.d.mts +26 -0
  219. package/dist/mcp-server/tools/discovery-tools.d.mts.map +1 -0
  220. package/dist/mcp-server/tools/discovery-tools.mjs +157 -0
  221. package/dist/mcp-server/tools/discovery-tools.mjs.map +1 -0
  222. package/dist/mcp-server/tools/error-classification.cjs +296 -0
  223. package/dist/mcp-server/tools/error-classification.cjs.map +1 -0
  224. package/dist/mcp-server/tools/error-classification.d.cts +135 -0
  225. package/dist/mcp-server/tools/error-classification.d.cts.map +1 -0
  226. package/dist/mcp-server/tools/error-classification.d.mts +135 -0
  227. package/dist/mcp-server/tools/error-classification.d.mts.map +1 -0
  228. package/dist/mcp-server/tools/error-classification.mjs +281 -0
  229. package/dist/mcp-server/tools/error-classification.mjs.map +1 -0
  230. package/dist/mcp-server/tools/helpers.cjs +149 -0
  231. package/dist/mcp-server/tools/helpers.cjs.map +1 -0
  232. package/dist/mcp-server/tools/helpers.d.cts +149 -0
  233. package/dist/mcp-server/tools/helpers.d.cts.map +1 -0
  234. package/dist/mcp-server/tools/helpers.d.mts +149 -0
  235. package/dist/mcp-server/tools/helpers.d.mts.map +1 -0
  236. package/dist/mcp-server/tools/helpers.mjs +141 -0
  237. package/dist/mcp-server/tools/helpers.mjs.map +1 -0
  238. package/dist/mcp-server/tools/index.cjs +27 -0
  239. package/dist/mcp-server/tools/index.cjs.map +1 -0
  240. package/dist/mcp-server/tools/index.d.cts +11 -0
  241. package/dist/mcp-server/tools/index.d.cts.map +1 -0
  242. package/dist/mcp-server/tools/index.d.mts +11 -0
  243. package/dist/mcp-server/tools/index.d.mts.map +1 -0
  244. package/dist/mcp-server/tools/index.mjs +11 -0
  245. package/dist/mcp-server/tools/index.mjs.map +1 -0
  246. package/dist/mcp-server/tools/interaction.cjs +190 -0
  247. package/dist/mcp-server/tools/interaction.cjs.map +1 -0
  248. package/dist/mcp-server/tools/interaction.d.cts +26 -0
  249. package/dist/mcp-server/tools/interaction.d.cts.map +1 -0
  250. package/dist/mcp-server/tools/interaction.d.mts +26 -0
  251. package/dist/mcp-server/tools/interaction.d.mts.map +1 -0
  252. package/dist/mcp-server/tools/interaction.mjs +185 -0
  253. package/dist/mcp-server/tools/interaction.mjs.map +1 -0
  254. package/dist/mcp-server/tools/knowledge.cjs +120 -0
  255. package/dist/mcp-server/tools/knowledge.cjs.map +1 -0
  256. package/dist/mcp-server/tools/knowledge.d.cts +34 -0
  257. package/dist/mcp-server/tools/knowledge.d.cts.map +1 -0
  258. package/dist/mcp-server/tools/knowledge.d.mts +34 -0
  259. package/dist/mcp-server/tools/knowledge.d.mts.map +1 -0
  260. package/dist/mcp-server/tools/knowledge.mjs +114 -0
  261. package/dist/mcp-server/tools/knowledge.mjs.map +1 -0
  262. package/dist/mcp-server/tools/launch.cjs +51 -0
  263. package/dist/mcp-server/tools/launch.cjs.map +1 -0
  264. package/dist/mcp-server/tools/launch.d.cts +10 -0
  265. package/dist/mcp-server/tools/launch.d.cts.map +1 -0
  266. package/dist/mcp-server/tools/launch.d.mts +10 -0
  267. package/dist/mcp-server/tools/launch.d.mts.map +1 -0
  268. package/dist/mcp-server/tools/launch.mjs +48 -0
  269. package/dist/mcp-server/tools/launch.mjs.map +1 -0
  270. package/dist/mcp-server/tools/navigation.cjs +242 -0
  271. package/dist/mcp-server/tools/navigation.cjs.map +1 -0
  272. package/dist/mcp-server/tools/navigation.d.cts +34 -0
  273. package/dist/mcp-server/tools/navigation.d.cts.map +1 -0
  274. package/dist/mcp-server/tools/navigation.d.mts +34 -0
  275. package/dist/mcp-server/tools/navigation.d.mts.map +1 -0
  276. package/dist/mcp-server/tools/navigation.mjs +236 -0
  277. package/dist/mcp-server/tools/navigation.mjs.map +1 -0
  278. package/dist/mcp-server/tools/registry.cjs +10 -0
  279. package/dist/mcp-server/tools/registry.cjs.map +1 -0
  280. package/dist/mcp-server/tools/registry.d.cts +4 -0
  281. package/dist/mcp-server/tools/registry.d.cts.map +1 -0
  282. package/dist/mcp-server/tools/registry.d.mts +4 -0
  283. package/dist/mcp-server/tools/registry.d.mts.map +1 -0
  284. package/dist/mcp-server/tools/registry.mjs +4 -0
  285. package/dist/mcp-server/tools/registry.mjs.map +1 -0
  286. package/dist/mcp-server/tools/run-tool.cjs +140 -0
  287. package/dist/mcp-server/tools/run-tool.cjs.map +1 -0
  288. package/dist/mcp-server/tools/run-tool.d.cts +39 -0
  289. package/dist/mcp-server/tools/run-tool.d.cts.map +1 -0
  290. package/dist/mcp-server/tools/run-tool.d.mts +39 -0
  291. package/dist/mcp-server/tools/run-tool.d.mts.map +1 -0
  292. package/dist/mcp-server/tools/run-tool.mjs +137 -0
  293. package/dist/mcp-server/tools/run-tool.mjs.map +1 -0
  294. package/dist/mcp-server/tools/screenshot.cjs +55 -0
  295. package/dist/mcp-server/tools/screenshot.cjs.map +1 -0
  296. package/dist/mcp-server/tools/screenshot.d.cts +10 -0
  297. package/dist/mcp-server/tools/screenshot.d.cts.map +1 -0
  298. package/dist/mcp-server/tools/screenshot.d.mts +10 -0
  299. package/dist/mcp-server/tools/screenshot.d.mts.map +1 -0
  300. package/dist/mcp-server/tools/screenshot.mjs +52 -0
  301. package/dist/mcp-server/tools/screenshot.mjs.map +1 -0
  302. package/dist/mcp-server/tools/seeding.cjs +214 -0
  303. package/dist/mcp-server/tools/seeding.cjs.map +1 -0
  304. package/dist/mcp-server/tools/seeding.d.cts +38 -0
  305. package/dist/mcp-server/tools/seeding.d.cts.map +1 -0
  306. package/dist/mcp-server/tools/seeding.d.mts +38 -0
  307. package/dist/mcp-server/tools/seeding.d.mts.map +1 -0
  308. package/dist/mcp-server/tools/seeding.mjs +208 -0
  309. package/dist/mcp-server/tools/seeding.mjs.map +1 -0
  310. package/dist/mcp-server/tools/state.cjs +69 -0
  311. package/dist/mcp-server/tools/state.cjs.map +1 -0
  312. package/dist/mcp-server/tools/state.d.cts +19 -0
  313. package/dist/mcp-server/tools/state.d.cts.map +1 -0
  314. package/dist/mcp-server/tools/state.d.mts +19 -0
  315. package/dist/mcp-server/tools/state.d.mts.map +1 -0
  316. package/dist/mcp-server/tools/state.mjs +66 -0
  317. package/dist/mcp-server/tools/state.mjs.map +1 -0
  318. package/dist/mcp-server/types/discovery.cjs +24 -0
  319. package/dist/mcp-server/types/discovery.cjs.map +1 -0
  320. package/dist/mcp-server/types/discovery.d.cts +30 -0
  321. package/dist/mcp-server/types/discovery.d.cts.map +1 -0
  322. package/dist/mcp-server/types/discovery.d.mts +30 -0
  323. package/dist/mcp-server/types/discovery.d.mts.map +1 -0
  324. package/dist/mcp-server/types/discovery.mjs +21 -0
  325. package/dist/mcp-server/types/discovery.mjs.map +1 -0
  326. package/dist/mcp-server/types/errors.cjs +33 -0
  327. package/dist/mcp-server/types/errors.cjs.map +1 -0
  328. package/dist/mcp-server/types/errors.d.cts +31 -0
  329. package/dist/mcp-server/types/errors.d.cts.map +1 -0
  330. package/dist/mcp-server/types/errors.d.mts +31 -0
  331. package/dist/mcp-server/types/errors.d.mts.map +1 -0
  332. package/dist/mcp-server/types/errors.mjs +30 -0
  333. package/dist/mcp-server/types/errors.mjs.map +1 -0
  334. package/dist/mcp-server/types/index.cjs +21 -0
  335. package/dist/mcp-server/types/index.cjs.map +1 -0
  336. package/dist/mcp-server/types/index.d.cts +10 -0
  337. package/dist/mcp-server/types/index.d.cts.map +1 -0
  338. package/dist/mcp-server/types/index.d.mts +10 -0
  339. package/dist/mcp-server/types/index.d.mts.map +1 -0
  340. package/dist/mcp-server/types/index.mjs +5 -0
  341. package/dist/mcp-server/types/index.mjs.map +1 -0
  342. package/dist/mcp-server/types/knowledge.cjs +3 -0
  343. package/dist/mcp-server/types/knowledge.cjs.map +1 -0
  344. package/dist/mcp-server/types/knowledge.d.cts +116 -0
  345. package/dist/mcp-server/types/knowledge.d.cts.map +1 -0
  346. package/dist/mcp-server/types/knowledge.d.mts +116 -0
  347. package/dist/mcp-server/types/knowledge.d.mts.map +1 -0
  348. package/dist/mcp-server/types/knowledge.mjs +2 -0
  349. package/dist/mcp-server/types/knowledge.mjs.map +1 -0
  350. package/dist/mcp-server/types/responses.cjs +3 -0
  351. package/dist/mcp-server/types/responses.cjs.map +1 -0
  352. package/dist/mcp-server/types/responses.d.cts +22 -0
  353. package/dist/mcp-server/types/responses.d.cts.map +1 -0
  354. package/dist/mcp-server/types/responses.d.mts +22 -0
  355. package/dist/mcp-server/types/responses.d.mts.map +1 -0
  356. package/dist/mcp-server/types/responses.mjs +2 -0
  357. package/dist/mcp-server/types/responses.mjs.map +1 -0
  358. package/dist/mcp-server/types/seeding.cjs +34 -0
  359. package/dist/mcp-server/types/seeding.cjs.map +1 -0
  360. package/dist/mcp-server/types/seeding.d.cts +40 -0
  361. package/dist/mcp-server/types/seeding.d.cts.map +1 -0
  362. package/dist/mcp-server/types/seeding.d.mts +40 -0
  363. package/dist/mcp-server/types/seeding.d.mts.map +1 -0
  364. package/dist/mcp-server/types/seeding.mjs +31 -0
  365. package/dist/mcp-server/types/seeding.mjs.map +1 -0
  366. package/dist/mcp-server/types/session.cjs +3 -0
  367. package/dist/mcp-server/types/session.cjs.map +1 -0
  368. package/dist/mcp-server/types/session.d.cts +11 -0
  369. package/dist/mcp-server/types/session.d.cts.map +1 -0
  370. package/dist/mcp-server/types/session.d.mts +11 -0
  371. package/dist/mcp-server/types/session.d.mts.map +1 -0
  372. package/dist/mcp-server/types/session.mjs +2 -0
  373. package/dist/mcp-server/types/session.mjs.map +1 -0
  374. package/dist/mcp-server/types/step-record.cjs +20 -0
  375. package/dist/mcp-server/types/step-record.cjs.map +1 -0
  376. package/dist/mcp-server/types/step-record.d.cts +86 -0
  377. package/dist/mcp-server/types/step-record.d.cts.map +1 -0
  378. package/dist/mcp-server/types/step-record.d.mts +86 -0
  379. package/dist/mcp-server/types/step-record.d.mts.map +1 -0
  380. package/dist/mcp-server/types/step-record.mjs +17 -0
  381. package/dist/mcp-server/types/step-record.mjs.map +1 -0
  382. package/dist/mcp-server/types/tool-inputs.cjs +3 -0
  383. package/dist/mcp-server/types/tool-inputs.cjs.map +1 -0
  384. package/dist/mcp-server/types/tool-inputs.d.cts +118 -0
  385. package/dist/mcp-server/types/tool-inputs.d.cts.map +1 -0
  386. package/dist/mcp-server/types/tool-inputs.d.mts +118 -0
  387. package/dist/mcp-server/types/tool-inputs.d.mts.map +1 -0
  388. package/dist/mcp-server/types/tool-inputs.mjs +2 -0
  389. package/dist/mcp-server/types/tool-inputs.mjs.map +1 -0
  390. package/dist/mcp-server/types/tool-outputs.cjs +3 -0
  391. package/dist/mcp-server/types/tool-outputs.cjs.map +1 -0
  392. package/dist/mcp-server/types/tool-outputs.d.cts +121 -0
  393. package/dist/mcp-server/types/tool-outputs.d.cts.map +1 -0
  394. package/dist/mcp-server/types/tool-outputs.d.mts +121 -0
  395. package/dist/mcp-server/types/tool-outputs.d.mts.map +1 -0
  396. package/dist/mcp-server/types/tool-outputs.mjs +2 -0
  397. package/dist/mcp-server/types/tool-outputs.mjs.map +1 -0
  398. package/dist/mcp-server/utils/errors.cjs +14 -0
  399. package/dist/mcp-server/utils/errors.cjs.map +1 -0
  400. package/dist/mcp-server/utils/errors.d.cts +9 -0
  401. package/dist/mcp-server/utils/errors.d.cts.map +1 -0
  402. package/dist/mcp-server/utils/errors.d.mts +9 -0
  403. package/dist/mcp-server/utils/errors.d.mts.map +1 -0
  404. package/dist/mcp-server/utils/errors.mjs +11 -0
  405. package/dist/mcp-server/utils/errors.mjs.map +1 -0
  406. package/dist/mcp-server/utils/index.cjs +22 -0
  407. package/dist/mcp-server/utils/index.cjs.map +1 -0
  408. package/dist/mcp-server/utils/index.d.cts +8 -0
  409. package/dist/mcp-server/utils/index.d.cts.map +1 -0
  410. package/dist/mcp-server/utils/index.d.mts +8 -0
  411. package/dist/mcp-server/utils/index.d.mts.map +1 -0
  412. package/dist/mcp-server/utils/index.mjs +8 -0
  413. package/dist/mcp-server/utils/index.mjs.map +1 -0
  414. package/dist/mcp-server/utils/logger.cjs +25 -0
  415. package/dist/mcp-server/utils/logger.cjs.map +1 -0
  416. package/dist/mcp-server/utils/logger.d.cts +9 -0
  417. package/dist/mcp-server/utils/logger.d.cts.map +1 -0
  418. package/dist/mcp-server/utils/logger.d.mts +9 -0
  419. package/dist/mcp-server/utils/logger.d.mts.map +1 -0
  420. package/dist/mcp-server/utils/logger.mjs +22 -0
  421. package/dist/mcp-server/utils/logger.mjs.map +1 -0
  422. package/dist/mcp-server/utils/redaction.cjs +24 -0
  423. package/dist/mcp-server/utils/redaction.cjs.map +1 -0
  424. package/dist/mcp-server/utils/redaction.d.cts +9 -0
  425. package/dist/mcp-server/utils/redaction.d.cts.map +1 -0
  426. package/dist/mcp-server/utils/redaction.d.mts +9 -0
  427. package/dist/mcp-server/utils/redaction.d.mts.map +1 -0
  428. package/dist/mcp-server/utils/redaction.mjs +20 -0
  429. package/dist/mcp-server/utils/redaction.mjs.map +1 -0
  430. package/dist/mcp-server/utils/response.cjs +49 -0
  431. package/dist/mcp-server/utils/response.cjs.map +1 -0
  432. package/dist/mcp-server/utils/response.d.cts +22 -0
  433. package/dist/mcp-server/utils/response.d.cts.map +1 -0
  434. package/dist/mcp-server/utils/response.d.mts +22 -0
  435. package/dist/mcp-server/utils/response.d.mts.map +1 -0
  436. package/dist/mcp-server/utils/response.mjs +45 -0
  437. package/dist/mcp-server/utils/response.mjs.map +1 -0
  438. package/dist/mcp-server/utils/targets.cjs +32 -0
  439. package/dist/mcp-server/utils/targets.cjs.map +1 -0
  440. package/dist/mcp-server/utils/targets.d.cts +25 -0
  441. package/dist/mcp-server/utils/targets.d.cts.map +1 -0
  442. package/dist/mcp-server/utils/targets.d.mts +25 -0
  443. package/dist/mcp-server/utils/targets.d.mts.map +1 -0
  444. package/dist/mcp-server/utils/targets.mjs +29 -0
  445. package/dist/mcp-server/utils/targets.mjs.map +1 -0
  446. package/dist/mcp-server/utils/time.cjs +39 -0
  447. package/dist/mcp-server/utils/time.cjs.map +1 -0
  448. package/dist/mcp-server/utils/time.d.cts +15 -0
  449. package/dist/mcp-server/utils/time.d.cts.map +1 -0
  450. package/dist/mcp-server/utils/time.d.mts +15 -0
  451. package/dist/mcp-server/utils/time.d.mts.map +1 -0
  452. package/dist/mcp-server/utils/time.mjs +35 -0
  453. package/dist/mcp-server/utils/time.mjs.map +1 -0
  454. package/dist/mcp-server/utils/type-guards.cjs +42 -0
  455. package/dist/mcp-server/utils/type-guards.cjs.map +1 -0
  456. package/dist/mcp-server/utils/type-guards.d.cts +30 -0
  457. package/dist/mcp-server/utils/type-guards.d.cts.map +1 -0
  458. package/dist/mcp-server/utils/type-guards.d.mts +30 -0
  459. package/dist/mcp-server/utils/type-guards.d.mts.map +1 -0
  460. package/dist/mcp-server/utils/type-guards.mjs +38 -0
  461. package/dist/mcp-server/utils/type-guards.mjs.map +1 -0
  462. package/dist/utils/fetch.cjs +36 -0
  463. package/dist/utils/fetch.cjs.map +1 -0
  464. package/dist/utils/fetch.d.cts +20 -0
  465. package/dist/utils/fetch.d.cts.map +1 -0
  466. package/dist/utils/fetch.d.mts +20 -0
  467. package/dist/utils/fetch.d.mts.map +1 -0
  468. package/dist/utils/fetch.mjs +33 -0
  469. package/dist/utils/fetch.mjs.map +1 -0
  470. package/dist/utils/index.cjs +11 -0
  471. package/dist/utils/index.cjs.map +1 -0
  472. package/dist/utils/index.d.cts +6 -0
  473. package/dist/utils/index.d.cts.map +1 -0
  474. package/dist/utils/index.d.mts +6 -0
  475. package/dist/utils/index.d.mts.map +1 -0
  476. package/dist/utils/index.mjs +6 -0
  477. package/dist/utils/index.mjs.map +1 -0
  478. package/dist/utils/service-readiness.cjs +75 -0
  479. package/dist/utils/service-readiness.cjs.map +1 -0
  480. package/dist/utils/service-readiness.d.cts +61 -0
  481. package/dist/utils/service-readiness.d.cts.map +1 -0
  482. package/dist/utils/service-readiness.d.mts +61 -0
  483. package/dist/utils/service-readiness.d.mts.map +1 -0
  484. package/dist/utils/service-readiness.mjs +72 -0
  485. package/dist/utils/service-readiness.mjs.map +1 -0
  486. package/package.json +119 -0
@@ -0,0 +1,177 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_EXTENSION_ID_CONFIG = void 0;
4
+ exports.resolveExtensionId = resolveExtensionId;
5
+ /**
6
+ * Default configuration that matches "MetaMask" extension.
7
+ */
8
+ exports.DEFAULT_EXTENSION_ID_CONFIG = {
9
+ extensionNamePattern: 'MetaMask',
10
+ };
11
+ /**
12
+ * Resolve the extension ID by checking service worker or chrome://extensions page.
13
+ *
14
+ * @param deps - Dependencies including browser context and logger
15
+ * @param config - Configuration for extension name pattern matching
16
+ * @returns The extension ID if found, undefined otherwise
17
+ */
18
+ async function resolveExtensionId(deps, config = exports.DEFAULT_EXTENSION_ID_CONFIG) {
19
+ const { context, log } = deps;
20
+ const fromWorker = await getExtensionIdFromServiceWorker(context, log);
21
+ if (fromWorker) {
22
+ return fromWorker;
23
+ }
24
+ log.info('Service worker discovery failed, falling back to chrome://extensions');
25
+ return getExtensionIdFromExtensionsPage(context, log, config);
26
+ }
27
+ /**
28
+ * Extract the extension ID from a chrome-extension:// URL.
29
+ *
30
+ * @param url - The URL to extract the extension ID from
31
+ * @returns The 32-character extension ID if found, undefined otherwise
32
+ */
33
+ function extractExtensionIdFromUrl(url) {
34
+ const match = url.match(/chrome-extension:\/\/([a-z]{32})\//u);
35
+ return match ? match[1] : undefined;
36
+ }
37
+ /**
38
+ * Attempt to resolve extension ID from existing or new service worker.
39
+ *
40
+ * @param context - The browser context to search for service workers
41
+ * @param log - Logger for debug information
42
+ * @returns The extension ID if found, undefined otherwise
43
+ */
44
+ async function getExtensionIdFromServiceWorker(context, log) {
45
+ try {
46
+ const existingWorkers = context.serviceWorkers();
47
+ for (const worker of existingWorkers) {
48
+ const extensionId = extractExtensionIdFromUrl(worker.url());
49
+ if (extensionId) {
50
+ log.info(`Found extension ID from existing service worker: ${extensionId}`);
51
+ return extensionId;
52
+ }
53
+ }
54
+ const worker = await Promise.race([
55
+ context.waitForEvent('serviceworker', { timeout: 10000 }),
56
+ new Promise((resolve) => setTimeout(() => resolve(null), 10000)),
57
+ ]);
58
+ if (worker && typeof worker !== 'number') {
59
+ const extensionId = extractExtensionIdFromUrl(worker.url());
60
+ if (extensionId) {
61
+ log.info(`Found extension ID from new service worker: ${extensionId}`);
62
+ return extensionId;
63
+ }
64
+ }
65
+ }
66
+ catch (error) {
67
+ log.warn('Service worker extension ID discovery failed:', error);
68
+ }
69
+ return undefined;
70
+ }
71
+ /**
72
+ * Resolve extension ID by navigating to chrome://extensions and matching name pattern.
73
+ *
74
+ * @param context - The browser context to use for navigation
75
+ * @param log - Logger for debug information
76
+ * @param config - Configuration with extension name pattern to match
77
+ * @param maxRetries - Maximum number of retry attempts (default: 3)
78
+ * @returns The extension ID if found, undefined otherwise
79
+ */
80
+ async function getExtensionIdFromExtensionsPage(context, log, config, maxRetries = 3) {
81
+ const page = await ensurePage(context);
82
+ const { extensionNamePattern } = config;
83
+ const patternString = extensionNamePattern instanceof RegExp
84
+ ? extensionNamePattern.source
85
+ : extensionNamePattern;
86
+ const isRegex = extensionNamePattern instanceof RegExp;
87
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
88
+ try {
89
+ await page.goto('chrome://extensions');
90
+ await page.waitForLoadState('domcontentloaded');
91
+ await waitForExtensionsPageReady(page);
92
+ const extensionId = await page.evaluate(({ pattern, useRegex, }) => {
93
+ const extensionsManager = document.querySelector('extensions-manager');
94
+ if (!extensionsManager?.shadowRoot) {
95
+ return undefined;
96
+ }
97
+ const itemList = extensionsManager.shadowRoot.querySelector('extensions-item-list');
98
+ if (!itemList?.shadowRoot) {
99
+ return undefined;
100
+ }
101
+ const items = itemList.shadowRoot.querySelectorAll('extensions-item');
102
+ for (const item of Array.from(items)) {
103
+ const nameEl = item.shadowRoot?.querySelector('#name');
104
+ const name = nameEl?.textContent ?? '';
105
+ const matches = useRegex
106
+ ? new RegExp(pattern, 'u').test(name)
107
+ : name.includes(pattern);
108
+ if (matches) {
109
+ return item.getAttribute('id') ?? undefined;
110
+ }
111
+ }
112
+ return undefined;
113
+ }, { pattern: patternString, useRegex: isRegex });
114
+ if (extensionId) {
115
+ return extensionId;
116
+ }
117
+ if (attempt < maxRetries) {
118
+ log.warn(`Extension not found (attempt ${attempt}/${maxRetries}), retrying...`);
119
+ await new Promise((resolve) => setTimeout(resolve, 1000));
120
+ }
121
+ }
122
+ catch (error) {
123
+ if (attempt < maxRetries) {
124
+ log.warn(`Error getting extension ID (attempt ${attempt}/${maxRetries}):`, error);
125
+ await new Promise((resolve) => setTimeout(resolve, 1000));
126
+ }
127
+ else {
128
+ throw new Error(`Failed to get extension ID after ${maxRetries} attempts. ` +
129
+ 'Ensure the extension is built at the configured extension path.');
130
+ }
131
+ }
132
+ }
133
+ return undefined;
134
+ }
135
+ /**
136
+ * Wait for the chrome://extensions page to fully load and render extensions.
137
+ *
138
+ * @param page - The page to wait for
139
+ * @param maxAttempts - Maximum number of polling attempts (default: 20)
140
+ */
141
+ async function waitForExtensionsPageReady(page, maxAttempts = 20) {
142
+ for (let i = 0; i < maxAttempts; i++) {
143
+ const isReady = await page.evaluate(() => {
144
+ const extensionsManager = document.querySelector('extensions-manager');
145
+ if (!extensionsManager?.shadowRoot) {
146
+ return false;
147
+ }
148
+ const itemList = extensionsManager.shadowRoot.querySelector('extensions-item-list');
149
+ if (!itemList?.shadowRoot) {
150
+ return false;
151
+ }
152
+ const items = itemList.shadowRoot.querySelectorAll('extensions-item');
153
+ return items.length > 0;
154
+ });
155
+ if (isReady) {
156
+ return;
157
+ }
158
+ await new Promise((resolve) => setTimeout(resolve, 100));
159
+ }
160
+ throw new Error(`chrome://extensions page did not load extensions within ${maxAttempts * 100}ms. ` +
161
+ 'The shadow DOM structure was not fully populated. ' +
162
+ 'This may indicate a Chrome version incompatibility or slow system.');
163
+ }
164
+ /**
165
+ * Get an existing page or create a new one for the browser context.
166
+ *
167
+ * @param context - The browser context to get or create a page for
168
+ * @returns An existing page or a newly created page
169
+ */
170
+ async function ensurePage(context) {
171
+ const pages = context.pages();
172
+ if (pages[0]) {
173
+ return pages[0];
174
+ }
175
+ return context.newPage();
176
+ }
177
+ //# sourceMappingURL=extension-id-resolver.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension-id-resolver.cjs","sourceRoot":"","sources":["../../src/launcher/extension-id-resolver.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BrowserContext, Page } from '@playwright/test';\n\nexport type ExtensionIdResolverDeps = {\n context: BrowserContext;\n log: {\n info: (message: string) => void;\n warn: (message: string, error?: unknown) => void;\n };\n};\n\n/**\n * Configuration for extension ID resolution.\n * Allows different extensions to specify their own identification criteria.\n */\nexport type ExtensionIdResolverConfig = {\n /**\n * Name pattern to match the extension in chrome://extensions page.\n * Can be a string (partial match) or RegExp.\n */\n extensionNamePattern: string | RegExp;\n};\n\n/**\n * Default configuration that matches \"MetaMask\" extension.\n */\nexport const DEFAULT_EXTENSION_ID_CONFIG: ExtensionIdResolverConfig = {\n extensionNamePattern: 'MetaMask',\n};\n\n/**\n * Resolve the extension ID by checking service worker or chrome://extensions page.\n *\n * @param deps - Dependencies including browser context and logger\n * @param config - Configuration for extension name pattern matching\n * @returns The extension ID if found, undefined otherwise\n */\nexport async function resolveExtensionId(\n deps: ExtensionIdResolverDeps,\n config: ExtensionIdResolverConfig = DEFAULT_EXTENSION_ID_CONFIG,\n): Promise<string | undefined> {\n const { context, log } = deps;\n\n const fromWorker = await getExtensionIdFromServiceWorker(context, log);\n if (fromWorker) {\n return fromWorker;\n }\n\n log.info(\n 'Service worker discovery failed, falling back to chrome://extensions',\n );\n return getExtensionIdFromExtensionsPage(context, log, config);\n}\n\n/**\n * Extract the extension ID from a chrome-extension:// URL.\n *\n * @param url - The URL to extract the extension ID from\n * @returns The 32-character extension ID if found, undefined otherwise\n */\nfunction extractExtensionIdFromUrl(url: string): string | undefined {\n const match = url.match(/chrome-extension:\\/\\/([a-z]{32})\\//u);\n return match ? match[1] : undefined;\n}\n\n/**\n * Attempt to resolve extension ID from existing or new service worker.\n *\n * @param context - The browser context to search for service workers\n * @param log - Logger for debug information\n * @returns The extension ID if found, undefined otherwise\n */\nasync function getExtensionIdFromServiceWorker(\n context: BrowserContext,\n log: ExtensionIdResolverDeps['log'],\n): Promise<string | undefined> {\n try {\n const existingWorkers = context.serviceWorkers();\n for (const worker of existingWorkers) {\n const extensionId = extractExtensionIdFromUrl(worker.url());\n if (extensionId) {\n log.info(\n `Found extension ID from existing service worker: ${extensionId}`,\n );\n return extensionId;\n }\n }\n\n const worker = await Promise.race([\n context.waitForEvent('serviceworker', { timeout: 10000 }),\n new Promise<null>((resolve) => setTimeout(() => resolve(null), 10000)),\n ]);\n\n if (worker && typeof worker !== 'number') {\n const extensionId = extractExtensionIdFromUrl(worker.url());\n if (extensionId) {\n log.info(`Found extension ID from new service worker: ${extensionId}`);\n return extensionId;\n }\n }\n } catch (error) {\n log.warn('Service worker extension ID discovery failed:', error);\n }\n\n return undefined;\n}\n\n/**\n * Resolve extension ID by navigating to chrome://extensions and matching name pattern.\n *\n * @param context - The browser context to use for navigation\n * @param log - Logger for debug information\n * @param config - Configuration with extension name pattern to match\n * @param maxRetries - Maximum number of retry attempts (default: 3)\n * @returns The extension ID if found, undefined otherwise\n */\nasync function getExtensionIdFromExtensionsPage(\n context: BrowserContext,\n log: ExtensionIdResolverDeps['log'],\n config: ExtensionIdResolverConfig,\n maxRetries = 3,\n): Promise<string | undefined> {\n const page = await ensurePage(context);\n const { extensionNamePattern } = config;\n\n const patternString =\n extensionNamePattern instanceof RegExp\n ? extensionNamePattern.source\n : extensionNamePattern;\n const isRegex = extensionNamePattern instanceof RegExp;\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n await page.goto('chrome://extensions');\n await page.waitForLoadState('domcontentloaded');\n await waitForExtensionsPageReady(page);\n\n const extensionId = await page.evaluate(\n ({\n pattern,\n useRegex,\n }: {\n /**\n * The extension name pattern to match\n */\n pattern: string;\n /**\n * Whether the pattern should be treated as a regular expression\n */\n useRegex: boolean;\n }) => {\n const extensionsManager =\n document.querySelector('extensions-manager');\n if (!extensionsManager?.shadowRoot) {\n return undefined;\n }\n\n const itemList = extensionsManager.shadowRoot.querySelector(\n 'extensions-item-list',\n );\n if (!itemList?.shadowRoot) {\n return undefined;\n }\n\n const items = itemList.shadowRoot.querySelectorAll('extensions-item');\n\n for (const item of Array.from(items)) {\n const nameEl = item.shadowRoot?.querySelector('#name');\n const name = nameEl?.textContent ?? '';\n\n const matches = useRegex\n ? new RegExp(pattern, 'u').test(name)\n : name.includes(pattern);\n\n if (matches) {\n return item.getAttribute('id') ?? undefined;\n }\n }\n\n return undefined;\n },\n { pattern: patternString, useRegex: isRegex },\n );\n\n if (extensionId) {\n return extensionId;\n }\n\n if (attempt < maxRetries) {\n log.warn(\n `Extension not found (attempt ${attempt}/${maxRetries}), retrying...`,\n );\n await new Promise((resolve) => setTimeout(resolve, 1000));\n }\n } catch (error) {\n if (attempt < maxRetries) {\n log.warn(\n `Error getting extension ID (attempt ${attempt}/${maxRetries}):`,\n error,\n );\n await new Promise((resolve) => setTimeout(resolve, 1000));\n } else {\n throw new Error(\n `Failed to get extension ID after ${maxRetries} attempts. ` +\n 'Ensure the extension is built at the configured extension path.',\n );\n }\n }\n }\n\n return undefined;\n}\n\n/**\n * Wait for the chrome://extensions page to fully load and render extensions.\n *\n * @param page - The page to wait for\n * @param maxAttempts - Maximum number of polling attempts (default: 20)\n */\nasync function waitForExtensionsPageReady(\n page: Page,\n maxAttempts = 20,\n): Promise<void> {\n for (let i = 0; i < maxAttempts; i++) {\n const isReady = await page.evaluate(() => {\n const extensionsManager = document.querySelector('extensions-manager');\n if (!extensionsManager?.shadowRoot) {\n return false;\n }\n\n const itemList = extensionsManager.shadowRoot.querySelector(\n 'extensions-item-list',\n );\n if (!itemList?.shadowRoot) {\n return false;\n }\n\n const items = itemList.shadowRoot.querySelectorAll('extensions-item');\n return items.length > 0;\n });\n\n if (isReady) {\n return;\n }\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n\n throw new Error(\n `chrome://extensions page did not load extensions within ${maxAttempts * 100}ms. ` +\n 'The shadow DOM structure was not fully populated. ' +\n 'This may indicate a Chrome version incompatibility or slow system.',\n );\n}\n\n/**\n * Get an existing page or create a new one for the browser context.\n *\n * @param context - The browser context to get or create a page for\n * @returns An existing page or a newly created page\n */\nasync function ensurePage(context: BrowserContext): Promise<Page> {\n const pages = context.pages();\n if (pages[0]) {\n return pages[0];\n }\n\n return context.newPage();\n}\n"]}
@@ -0,0 +1,32 @@
1
+ import type { BrowserContext } from "@playwright/test";
2
+ export type ExtensionIdResolverDeps = {
3
+ context: BrowserContext;
4
+ log: {
5
+ info: (message: string) => void;
6
+ warn: (message: string, error?: unknown) => void;
7
+ };
8
+ };
9
+ /**
10
+ * Configuration for extension ID resolution.
11
+ * Allows different extensions to specify their own identification criteria.
12
+ */
13
+ export type ExtensionIdResolverConfig = {
14
+ /**
15
+ * Name pattern to match the extension in chrome://extensions page.
16
+ * Can be a string (partial match) or RegExp.
17
+ */
18
+ extensionNamePattern: string | RegExp;
19
+ };
20
+ /**
21
+ * Default configuration that matches "MetaMask" extension.
22
+ */
23
+ export declare const DEFAULT_EXTENSION_ID_CONFIG: ExtensionIdResolverConfig;
24
+ /**
25
+ * Resolve the extension ID by checking service worker or chrome://extensions page.
26
+ *
27
+ * @param deps - Dependencies including browser context and logger
28
+ * @param config - Configuration for extension name pattern matching
29
+ * @returns The extension ID if found, undefined otherwise
30
+ */
31
+ export declare function resolveExtensionId(deps: ExtensionIdResolverDeps, config?: ExtensionIdResolverConfig): Promise<string | undefined>;
32
+ //# sourceMappingURL=extension-id-resolver.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension-id-resolver.d.cts","sourceRoot":"","sources":["../../src/launcher/extension-id-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAQ,yBAAyB;AAE7D,MAAM,MAAM,uBAAuB,GAAG;IACpC,OAAO,EAAE,cAAc,CAAC;IACxB,GAAG,EAAE;QACH,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;QAChC,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;KAClD,CAAC;CACH,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACtC;;;OAGG;IACH,oBAAoB,EAAE,MAAM,GAAG,MAAM,CAAC;CACvC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,2BAA2B,EAAE,yBAEzC,CAAC;AAEF;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,uBAAuB,EAC7B,MAAM,GAAE,yBAAuD,GAC9D,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAY7B"}
@@ -0,0 +1,32 @@
1
+ import type { BrowserContext } from "@playwright/test";
2
+ export type ExtensionIdResolverDeps = {
3
+ context: BrowserContext;
4
+ log: {
5
+ info: (message: string) => void;
6
+ warn: (message: string, error?: unknown) => void;
7
+ };
8
+ };
9
+ /**
10
+ * Configuration for extension ID resolution.
11
+ * Allows different extensions to specify their own identification criteria.
12
+ */
13
+ export type ExtensionIdResolverConfig = {
14
+ /**
15
+ * Name pattern to match the extension in chrome://extensions page.
16
+ * Can be a string (partial match) or RegExp.
17
+ */
18
+ extensionNamePattern: string | RegExp;
19
+ };
20
+ /**
21
+ * Default configuration that matches "MetaMask" extension.
22
+ */
23
+ export declare const DEFAULT_EXTENSION_ID_CONFIG: ExtensionIdResolverConfig;
24
+ /**
25
+ * Resolve the extension ID by checking service worker or chrome://extensions page.
26
+ *
27
+ * @param deps - Dependencies including browser context and logger
28
+ * @param config - Configuration for extension name pattern matching
29
+ * @returns The extension ID if found, undefined otherwise
30
+ */
31
+ export declare function resolveExtensionId(deps: ExtensionIdResolverDeps, config?: ExtensionIdResolverConfig): Promise<string | undefined>;
32
+ //# sourceMappingURL=extension-id-resolver.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension-id-resolver.d.mts","sourceRoot":"","sources":["../../src/launcher/extension-id-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAQ,yBAAyB;AAE7D,MAAM,MAAM,uBAAuB,GAAG;IACpC,OAAO,EAAE,cAAc,CAAC;IACxB,GAAG,EAAE;QACH,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;QAChC,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;KAClD,CAAC;CACH,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACtC;;;OAGG;IACH,oBAAoB,EAAE,MAAM,GAAG,MAAM,CAAC;CACvC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,2BAA2B,EAAE,yBAEzC,CAAC;AAEF;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,uBAAuB,EAC7B,MAAM,GAAE,yBAAuD,GAC9D,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAY7B"}
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Default configuration that matches "MetaMask" extension.
3
+ */
4
+ export const DEFAULT_EXTENSION_ID_CONFIG = {
5
+ extensionNamePattern: 'MetaMask',
6
+ };
7
+ /**
8
+ * Resolve the extension ID by checking service worker or chrome://extensions page.
9
+ *
10
+ * @param deps - Dependencies including browser context and logger
11
+ * @param config - Configuration for extension name pattern matching
12
+ * @returns The extension ID if found, undefined otherwise
13
+ */
14
+ export async function resolveExtensionId(deps, config = DEFAULT_EXTENSION_ID_CONFIG) {
15
+ const { context, log } = deps;
16
+ const fromWorker = await getExtensionIdFromServiceWorker(context, log);
17
+ if (fromWorker) {
18
+ return fromWorker;
19
+ }
20
+ log.info('Service worker discovery failed, falling back to chrome://extensions');
21
+ return getExtensionIdFromExtensionsPage(context, log, config);
22
+ }
23
+ /**
24
+ * Extract the extension ID from a chrome-extension:// URL.
25
+ *
26
+ * @param url - The URL to extract the extension ID from
27
+ * @returns The 32-character extension ID if found, undefined otherwise
28
+ */
29
+ function extractExtensionIdFromUrl(url) {
30
+ const match = url.match(/chrome-extension:\/\/([a-z]{32})\//u);
31
+ return match ? match[1] : undefined;
32
+ }
33
+ /**
34
+ * Attempt to resolve extension ID from existing or new service worker.
35
+ *
36
+ * @param context - The browser context to search for service workers
37
+ * @param log - Logger for debug information
38
+ * @returns The extension ID if found, undefined otherwise
39
+ */
40
+ async function getExtensionIdFromServiceWorker(context, log) {
41
+ try {
42
+ const existingWorkers = context.serviceWorkers();
43
+ for (const worker of existingWorkers) {
44
+ const extensionId = extractExtensionIdFromUrl(worker.url());
45
+ if (extensionId) {
46
+ log.info(`Found extension ID from existing service worker: ${extensionId}`);
47
+ return extensionId;
48
+ }
49
+ }
50
+ const worker = await Promise.race([
51
+ context.waitForEvent('serviceworker', { timeout: 10000 }),
52
+ new Promise((resolve) => setTimeout(() => resolve(null), 10000)),
53
+ ]);
54
+ if (worker && typeof worker !== 'number') {
55
+ const extensionId = extractExtensionIdFromUrl(worker.url());
56
+ if (extensionId) {
57
+ log.info(`Found extension ID from new service worker: ${extensionId}`);
58
+ return extensionId;
59
+ }
60
+ }
61
+ }
62
+ catch (error) {
63
+ log.warn('Service worker extension ID discovery failed:', error);
64
+ }
65
+ return undefined;
66
+ }
67
+ /**
68
+ * Resolve extension ID by navigating to chrome://extensions and matching name pattern.
69
+ *
70
+ * @param context - The browser context to use for navigation
71
+ * @param log - Logger for debug information
72
+ * @param config - Configuration with extension name pattern to match
73
+ * @param maxRetries - Maximum number of retry attempts (default: 3)
74
+ * @returns The extension ID if found, undefined otherwise
75
+ */
76
+ async function getExtensionIdFromExtensionsPage(context, log, config, maxRetries = 3) {
77
+ const page = await ensurePage(context);
78
+ const { extensionNamePattern } = config;
79
+ const patternString = extensionNamePattern instanceof RegExp
80
+ ? extensionNamePattern.source
81
+ : extensionNamePattern;
82
+ const isRegex = extensionNamePattern instanceof RegExp;
83
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
84
+ try {
85
+ await page.goto('chrome://extensions');
86
+ await page.waitForLoadState('domcontentloaded');
87
+ await waitForExtensionsPageReady(page);
88
+ const extensionId = await page.evaluate(({ pattern, useRegex, }) => {
89
+ const extensionsManager = document.querySelector('extensions-manager');
90
+ if (!extensionsManager?.shadowRoot) {
91
+ return undefined;
92
+ }
93
+ const itemList = extensionsManager.shadowRoot.querySelector('extensions-item-list');
94
+ if (!itemList?.shadowRoot) {
95
+ return undefined;
96
+ }
97
+ const items = itemList.shadowRoot.querySelectorAll('extensions-item');
98
+ for (const item of Array.from(items)) {
99
+ const nameEl = item.shadowRoot?.querySelector('#name');
100
+ const name = nameEl?.textContent ?? '';
101
+ const matches = useRegex
102
+ ? new RegExp(pattern, 'u').test(name)
103
+ : name.includes(pattern);
104
+ if (matches) {
105
+ return item.getAttribute('id') ?? undefined;
106
+ }
107
+ }
108
+ return undefined;
109
+ }, { pattern: patternString, useRegex: isRegex });
110
+ if (extensionId) {
111
+ return extensionId;
112
+ }
113
+ if (attempt < maxRetries) {
114
+ log.warn(`Extension not found (attempt ${attempt}/${maxRetries}), retrying...`);
115
+ await new Promise((resolve) => setTimeout(resolve, 1000));
116
+ }
117
+ }
118
+ catch (error) {
119
+ if (attempt < maxRetries) {
120
+ log.warn(`Error getting extension ID (attempt ${attempt}/${maxRetries}):`, error);
121
+ await new Promise((resolve) => setTimeout(resolve, 1000));
122
+ }
123
+ else {
124
+ throw new Error(`Failed to get extension ID after ${maxRetries} attempts. ` +
125
+ 'Ensure the extension is built at the configured extension path.');
126
+ }
127
+ }
128
+ }
129
+ return undefined;
130
+ }
131
+ /**
132
+ * Wait for the chrome://extensions page to fully load and render extensions.
133
+ *
134
+ * @param page - The page to wait for
135
+ * @param maxAttempts - Maximum number of polling attempts (default: 20)
136
+ */
137
+ async function waitForExtensionsPageReady(page, maxAttempts = 20) {
138
+ for (let i = 0; i < maxAttempts; i++) {
139
+ const isReady = await page.evaluate(() => {
140
+ const extensionsManager = document.querySelector('extensions-manager');
141
+ if (!extensionsManager?.shadowRoot) {
142
+ return false;
143
+ }
144
+ const itemList = extensionsManager.shadowRoot.querySelector('extensions-item-list');
145
+ if (!itemList?.shadowRoot) {
146
+ return false;
147
+ }
148
+ const items = itemList.shadowRoot.querySelectorAll('extensions-item');
149
+ return items.length > 0;
150
+ });
151
+ if (isReady) {
152
+ return;
153
+ }
154
+ await new Promise((resolve) => setTimeout(resolve, 100));
155
+ }
156
+ throw new Error(`chrome://extensions page did not load extensions within ${maxAttempts * 100}ms. ` +
157
+ 'The shadow DOM structure was not fully populated. ' +
158
+ 'This may indicate a Chrome version incompatibility or slow system.');
159
+ }
160
+ /**
161
+ * Get an existing page or create a new one for the browser context.
162
+ *
163
+ * @param context - The browser context to get or create a page for
164
+ * @returns An existing page or a newly created page
165
+ */
166
+ async function ensurePage(context) {
167
+ const pages = context.pages();
168
+ if (pages[0]) {
169
+ return pages[0];
170
+ }
171
+ return context.newPage();
172
+ }
173
+ //# sourceMappingURL=extension-id-resolver.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension-id-resolver.mjs","sourceRoot":"","sources":["../../src/launcher/extension-id-resolver.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BrowserContext, Page } from '@playwright/test';\n\nexport type ExtensionIdResolverDeps = {\n context: BrowserContext;\n log: {\n info: (message: string) => void;\n warn: (message: string, error?: unknown) => void;\n };\n};\n\n/**\n * Configuration for extension ID resolution.\n * Allows different extensions to specify their own identification criteria.\n */\nexport type ExtensionIdResolverConfig = {\n /**\n * Name pattern to match the extension in chrome://extensions page.\n * Can be a string (partial match) or RegExp.\n */\n extensionNamePattern: string | RegExp;\n};\n\n/**\n * Default configuration that matches \"MetaMask\" extension.\n */\nexport const DEFAULT_EXTENSION_ID_CONFIG: ExtensionIdResolverConfig = {\n extensionNamePattern: 'MetaMask',\n};\n\n/**\n * Resolve the extension ID by checking service worker or chrome://extensions page.\n *\n * @param deps - Dependencies including browser context and logger\n * @param config - Configuration for extension name pattern matching\n * @returns The extension ID if found, undefined otherwise\n */\nexport async function resolveExtensionId(\n deps: ExtensionIdResolverDeps,\n config: ExtensionIdResolverConfig = DEFAULT_EXTENSION_ID_CONFIG,\n): Promise<string | undefined> {\n const { context, log } = deps;\n\n const fromWorker = await getExtensionIdFromServiceWorker(context, log);\n if (fromWorker) {\n return fromWorker;\n }\n\n log.info(\n 'Service worker discovery failed, falling back to chrome://extensions',\n );\n return getExtensionIdFromExtensionsPage(context, log, config);\n}\n\n/**\n * Extract the extension ID from a chrome-extension:// URL.\n *\n * @param url - The URL to extract the extension ID from\n * @returns The 32-character extension ID if found, undefined otherwise\n */\nfunction extractExtensionIdFromUrl(url: string): string | undefined {\n const match = url.match(/chrome-extension:\\/\\/([a-z]{32})\\//u);\n return match ? match[1] : undefined;\n}\n\n/**\n * Attempt to resolve extension ID from existing or new service worker.\n *\n * @param context - The browser context to search for service workers\n * @param log - Logger for debug information\n * @returns The extension ID if found, undefined otherwise\n */\nasync function getExtensionIdFromServiceWorker(\n context: BrowserContext,\n log: ExtensionIdResolverDeps['log'],\n): Promise<string | undefined> {\n try {\n const existingWorkers = context.serviceWorkers();\n for (const worker of existingWorkers) {\n const extensionId = extractExtensionIdFromUrl(worker.url());\n if (extensionId) {\n log.info(\n `Found extension ID from existing service worker: ${extensionId}`,\n );\n return extensionId;\n }\n }\n\n const worker = await Promise.race([\n context.waitForEvent('serviceworker', { timeout: 10000 }),\n new Promise<null>((resolve) => setTimeout(() => resolve(null), 10000)),\n ]);\n\n if (worker && typeof worker !== 'number') {\n const extensionId = extractExtensionIdFromUrl(worker.url());\n if (extensionId) {\n log.info(`Found extension ID from new service worker: ${extensionId}`);\n return extensionId;\n }\n }\n } catch (error) {\n log.warn('Service worker extension ID discovery failed:', error);\n }\n\n return undefined;\n}\n\n/**\n * Resolve extension ID by navigating to chrome://extensions and matching name pattern.\n *\n * @param context - The browser context to use for navigation\n * @param log - Logger for debug information\n * @param config - Configuration with extension name pattern to match\n * @param maxRetries - Maximum number of retry attempts (default: 3)\n * @returns The extension ID if found, undefined otherwise\n */\nasync function getExtensionIdFromExtensionsPage(\n context: BrowserContext,\n log: ExtensionIdResolverDeps['log'],\n config: ExtensionIdResolverConfig,\n maxRetries = 3,\n): Promise<string | undefined> {\n const page = await ensurePage(context);\n const { extensionNamePattern } = config;\n\n const patternString =\n extensionNamePattern instanceof RegExp\n ? extensionNamePattern.source\n : extensionNamePattern;\n const isRegex = extensionNamePattern instanceof RegExp;\n\n for (let attempt = 1; attempt <= maxRetries; attempt++) {\n try {\n await page.goto('chrome://extensions');\n await page.waitForLoadState('domcontentloaded');\n await waitForExtensionsPageReady(page);\n\n const extensionId = await page.evaluate(\n ({\n pattern,\n useRegex,\n }: {\n /**\n * The extension name pattern to match\n */\n pattern: string;\n /**\n * Whether the pattern should be treated as a regular expression\n */\n useRegex: boolean;\n }) => {\n const extensionsManager =\n document.querySelector('extensions-manager');\n if (!extensionsManager?.shadowRoot) {\n return undefined;\n }\n\n const itemList = extensionsManager.shadowRoot.querySelector(\n 'extensions-item-list',\n );\n if (!itemList?.shadowRoot) {\n return undefined;\n }\n\n const items = itemList.shadowRoot.querySelectorAll('extensions-item');\n\n for (const item of Array.from(items)) {\n const nameEl = item.shadowRoot?.querySelector('#name');\n const name = nameEl?.textContent ?? '';\n\n const matches = useRegex\n ? new RegExp(pattern, 'u').test(name)\n : name.includes(pattern);\n\n if (matches) {\n return item.getAttribute('id') ?? undefined;\n }\n }\n\n return undefined;\n },\n { pattern: patternString, useRegex: isRegex },\n );\n\n if (extensionId) {\n return extensionId;\n }\n\n if (attempt < maxRetries) {\n log.warn(\n `Extension not found (attempt ${attempt}/${maxRetries}), retrying...`,\n );\n await new Promise((resolve) => setTimeout(resolve, 1000));\n }\n } catch (error) {\n if (attempt < maxRetries) {\n log.warn(\n `Error getting extension ID (attempt ${attempt}/${maxRetries}):`,\n error,\n );\n await new Promise((resolve) => setTimeout(resolve, 1000));\n } else {\n throw new Error(\n `Failed to get extension ID after ${maxRetries} attempts. ` +\n 'Ensure the extension is built at the configured extension path.',\n );\n }\n }\n }\n\n return undefined;\n}\n\n/**\n * Wait for the chrome://extensions page to fully load and render extensions.\n *\n * @param page - The page to wait for\n * @param maxAttempts - Maximum number of polling attempts (default: 20)\n */\nasync function waitForExtensionsPageReady(\n page: Page,\n maxAttempts = 20,\n): Promise<void> {\n for (let i = 0; i < maxAttempts; i++) {\n const isReady = await page.evaluate(() => {\n const extensionsManager = document.querySelector('extensions-manager');\n if (!extensionsManager?.shadowRoot) {\n return false;\n }\n\n const itemList = extensionsManager.shadowRoot.querySelector(\n 'extensions-item-list',\n );\n if (!itemList?.shadowRoot) {\n return false;\n }\n\n const items = itemList.shadowRoot.querySelectorAll('extensions-item');\n return items.length > 0;\n });\n\n if (isReady) {\n return;\n }\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n\n throw new Error(\n `chrome://extensions page did not load extensions within ${maxAttempts * 100}ms. ` +\n 'The shadow DOM structure was not fully populated. ' +\n 'This may indicate a Chrome version incompatibility or slow system.',\n );\n}\n\n/**\n * Get an existing page or create a new one for the browser context.\n *\n * @param context - The browser context to get or create a page for\n * @returns An existing page or a newly created page\n */\nasync function ensurePage(context: BrowserContext): Promise<Page> {\n const pages = context.pages();\n if (pages[0]) {\n return pages[0];\n }\n\n return context.newPage();\n}\n"]}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.DEFAULT_EXTENSION_READINESS_CONFIG = void 0;
7
+ exports.waitForExtensionUiReady = waitForExtensionUiReady;
8
+ const path_1 = __importDefault(require("path"));
9
+ /**
10
+ * Default MetaMask extension readiness configuration.
11
+ */
12
+ exports.DEFAULT_EXTENSION_READINESS_CONFIG = {
13
+ readySelectors: [
14
+ '[data-testid="unlock-password"]',
15
+ '[data-testid="onboarding-create-wallet"]',
16
+ '[data-testid="onboarding-import-wallet"]',
17
+ '[data-testid="account-menu-icon"]',
18
+ '[data-testid="get-started"]',
19
+ '[data-testid="onboarding-terms-checkbox"]',
20
+ '[data-testid="onboarding-privacy-policy"]',
21
+ ],
22
+ expectedStatesDescription: 'unlock page, onboarding page, or home page',
23
+ };
24
+ /**
25
+ * Wait for the extension UI to be ready by checking for expected selectors.
26
+ *
27
+ * @param deps - Dependencies including page, screenshot directory, and logger
28
+ * @param config - Configuration with ready selectors to wait for
29
+ * @param timeout - Maximum time to wait in milliseconds (default: 30000)
30
+ */
31
+ async function waitForExtensionUiReady(deps, config = exports.DEFAULT_EXTENSION_READINESS_CONFIG, timeout = 30000) {
32
+ const { page, screenshotDir, log } = deps;
33
+ const { readySelectors, expectedStatesDescription } = config;
34
+ try {
35
+ await Promise.race(readySelectors.map(async (selector) => page.waitForSelector(selector, { timeout })));
36
+ log.info('Extension UI is ready');
37
+ }
38
+ catch {
39
+ const currentUrl = page.url();
40
+ const screenshotPath = path_1.default.join(screenshotDir, `ui-ready-failure-${Date.now()}.png`);
41
+ await page.screenshot({ path: screenshotPath, fullPage: true });
42
+ log.error(`Debug screenshot saved: ${screenshotPath}`);
43
+ const expectedStates = expectedStatesDescription ?? 'one of the expected ready states';
44
+ throw new Error(`Extension UI did not reach expected state within ${timeout}ms. ` +
45
+ `Current URL: ${currentUrl}. ` +
46
+ `Expected: ${expectedStates}. ` +
47
+ `Debug screenshot saved to: ${screenshotPath}`);
48
+ }
49
+ }
50
+ //# sourceMappingURL=extension-readiness.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension-readiness.cjs","sourceRoot":"","sources":["../../src/launcher/extension-readiness.ts"],"names":[],"mappings":";;;;;;AAmDA,0DAkCC;AApFD,gDAAwB;AA2BxB;;GAEG;AACU,QAAA,kCAAkC,GAA6B;IAC1E,cAAc,EAAE;QACd,iCAAiC;QACjC,0CAA0C;QAC1C,0CAA0C;QAC1C,mCAAmC;QACnC,6BAA6B;QAC7B,2CAA2C;QAC3C,2CAA2C;KAC5C;IACD,yBAAyB,EAAE,4CAA4C;CACxE,CAAC;AAEF;;;;;;GAMG;AACI,KAAK,UAAU,uBAAuB,CAC3C,IAA4B,EAC5B,SAAmC,0CAAkC,EACrE,OAAO,GAAG,KAAK;IAEf,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAC1C,MAAM,EAAE,cAAc,EAAE,yBAAyB,EAAE,GAAG,MAAM,CAAC;IAE7D,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,IAAI,CAChB,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,CACpC,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,CAAC,CAC5C,CACF,CAAC;QACF,GAAG,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC9B,MAAM,cAAc,GAAG,cAAI,CAAC,IAAI,CAC9B,aAAa,EACb,oBAAoB,IAAI,CAAC,GAAG,EAAE,MAAM,CACrC,CAAC;QACF,MAAM,IAAI,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QAChE,GAAG,CAAC,KAAK,CAAC,2BAA2B,cAAc,EAAE,CAAC,CAAC;QAEvD,MAAM,cAAc,GAClB,yBAAyB,IAAI,kCAAkC,CAAC;QAElE,MAAM,IAAI,KAAK,CACb,oDAAoD,OAAO,MAAM;YAC/D,gBAAgB,UAAU,IAAI;YAC9B,aAAa,cAAc,IAAI;YAC/B,8BAA8B,cAAc,EAAE,CACjD,CAAC;IACJ,CAAC;AACH,CAAC","sourcesContent":["import type { Page } from '@playwright/test';\nimport path from 'path';\n\nexport type ExtensionReadinessDeps = {\n page: Page;\n screenshotDir: string;\n log: {\n info: (message: string) => void;\n error: (message: string) => void;\n };\n};\n\n/**\n * Configuration for extension readiness detection.\n * Allows different extensions to specify their own UI ready selectors.\n */\nexport type ExtensionReadinessConfig = {\n /**\n * CSS selectors that indicate the extension UI is ready.\n * The function waits for ANY of these selectors to appear.\n */\n readySelectors: string[];\n /**\n * Human-readable description of expected states for error messages.\n */\n expectedStatesDescription?: string;\n};\n\n/**\n * Default MetaMask extension readiness configuration.\n */\nexport const DEFAULT_EXTENSION_READINESS_CONFIG: ExtensionReadinessConfig = {\n readySelectors: [\n '[data-testid=\"unlock-password\"]',\n '[data-testid=\"onboarding-create-wallet\"]',\n '[data-testid=\"onboarding-import-wallet\"]',\n '[data-testid=\"account-menu-icon\"]',\n '[data-testid=\"get-started\"]',\n '[data-testid=\"onboarding-terms-checkbox\"]',\n '[data-testid=\"onboarding-privacy-policy\"]',\n ],\n expectedStatesDescription: 'unlock page, onboarding page, or home page',\n};\n\n/**\n * Wait for the extension UI to be ready by checking for expected selectors.\n *\n * @param deps - Dependencies including page, screenshot directory, and logger\n * @param config - Configuration with ready selectors to wait for\n * @param timeout - Maximum time to wait in milliseconds (default: 30000)\n */\nexport async function waitForExtensionUiReady(\n deps: ExtensionReadinessDeps,\n config: ExtensionReadinessConfig = DEFAULT_EXTENSION_READINESS_CONFIG,\n timeout = 30000,\n): Promise<void> {\n const { page, screenshotDir, log } = deps;\n const { readySelectors, expectedStatesDescription } = config;\n\n try {\n await Promise.race(\n readySelectors.map(async (selector) =>\n page.waitForSelector(selector, { timeout }),\n ),\n );\n log.info('Extension UI is ready');\n } catch {\n const currentUrl = page.url();\n const screenshotPath = path.join(\n screenshotDir,\n `ui-ready-failure-${Date.now()}.png`,\n );\n await page.screenshot({ path: screenshotPath, fullPage: true });\n log.error(`Debug screenshot saved: ${screenshotPath}`);\n\n const expectedStates =\n expectedStatesDescription ?? 'one of the expected ready states';\n\n throw new Error(\n `Extension UI did not reach expected state within ${timeout}ms. ` +\n `Current URL: ${currentUrl}. ` +\n `Expected: ${expectedStates}. ` +\n `Debug screenshot saved to: ${screenshotPath}`,\n );\n }\n}\n"]}
@@ -0,0 +1,37 @@
1
+ import type { Page } from "@playwright/test";
2
+ export type ExtensionReadinessDeps = {
3
+ page: Page;
4
+ screenshotDir: string;
5
+ log: {
6
+ info: (message: string) => void;
7
+ error: (message: string) => void;
8
+ };
9
+ };
10
+ /**
11
+ * Configuration for extension readiness detection.
12
+ * Allows different extensions to specify their own UI ready selectors.
13
+ */
14
+ export type ExtensionReadinessConfig = {
15
+ /**
16
+ * CSS selectors that indicate the extension UI is ready.
17
+ * The function waits for ANY of these selectors to appear.
18
+ */
19
+ readySelectors: string[];
20
+ /**
21
+ * Human-readable description of expected states for error messages.
22
+ */
23
+ expectedStatesDescription?: string;
24
+ };
25
+ /**
26
+ * Default MetaMask extension readiness configuration.
27
+ */
28
+ export declare const DEFAULT_EXTENSION_READINESS_CONFIG: ExtensionReadinessConfig;
29
+ /**
30
+ * Wait for the extension UI to be ready by checking for expected selectors.
31
+ *
32
+ * @param deps - Dependencies including page, screenshot directory, and logger
33
+ * @param config - Configuration with ready selectors to wait for
34
+ * @param timeout - Maximum time to wait in milliseconds (default: 30000)
35
+ */
36
+ export declare function waitForExtensionUiReady(deps: ExtensionReadinessDeps, config?: ExtensionReadinessConfig, timeout?: number): Promise<void>;
37
+ //# sourceMappingURL=extension-readiness.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension-readiness.d.cts","sourceRoot":"","sources":["../../src/launcher/extension-readiness.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,yBAAyB;AAG7C,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,EAAE,IAAI,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,GAAG,EAAE;QACH,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;QAChC,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;KAClC,CAAC;CACH,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC;;;OAGG;IACH,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB;;OAEG;IACH,yBAAyB,CAAC,EAAE,MAAM,CAAC;CACpC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kCAAkC,EAAE,wBAWhD,CAAC;AAEF;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,sBAAsB,EAC5B,MAAM,GAAE,wBAA6D,EACrE,OAAO,SAAQ,GACd,OAAO,CAAC,IAAI,CAAC,CA8Bf"}
@@ -0,0 +1,37 @@
1
+ import type { Page } from "@playwright/test";
2
+ export type ExtensionReadinessDeps = {
3
+ page: Page;
4
+ screenshotDir: string;
5
+ log: {
6
+ info: (message: string) => void;
7
+ error: (message: string) => void;
8
+ };
9
+ };
10
+ /**
11
+ * Configuration for extension readiness detection.
12
+ * Allows different extensions to specify their own UI ready selectors.
13
+ */
14
+ export type ExtensionReadinessConfig = {
15
+ /**
16
+ * CSS selectors that indicate the extension UI is ready.
17
+ * The function waits for ANY of these selectors to appear.
18
+ */
19
+ readySelectors: string[];
20
+ /**
21
+ * Human-readable description of expected states for error messages.
22
+ */
23
+ expectedStatesDescription?: string;
24
+ };
25
+ /**
26
+ * Default MetaMask extension readiness configuration.
27
+ */
28
+ export declare const DEFAULT_EXTENSION_READINESS_CONFIG: ExtensionReadinessConfig;
29
+ /**
30
+ * Wait for the extension UI to be ready by checking for expected selectors.
31
+ *
32
+ * @param deps - Dependencies including page, screenshot directory, and logger
33
+ * @param config - Configuration with ready selectors to wait for
34
+ * @param timeout - Maximum time to wait in milliseconds (default: 30000)
35
+ */
36
+ export declare function waitForExtensionUiReady(deps: ExtensionReadinessDeps, config?: ExtensionReadinessConfig, timeout?: number): Promise<void>;
37
+ //# sourceMappingURL=extension-readiness.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension-readiness.d.mts","sourceRoot":"","sources":["../../src/launcher/extension-readiness.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,yBAAyB;AAG7C,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,EAAE,IAAI,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,GAAG,EAAE;QACH,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;QAChC,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;KAClC,CAAC;CACH,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC;;;OAGG;IACH,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB;;OAEG;IACH,yBAAyB,CAAC,EAAE,MAAM,CAAC;CACpC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kCAAkC,EAAE,wBAWhD,CAAC;AAEF;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,sBAAsB,EAC5B,MAAM,GAAE,wBAA6D,EACrE,OAAO,SAAQ,GACd,OAAO,CAAC,IAAI,CAAC,CA8Bf"}