@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.
- package/CHANGELOG.md +17 -0
- package/LICENSE +6 -0
- package/LICENSE.APACHE2 +201 -0
- package/LICENSE.MIT +21 -0
- package/README.md +1459 -0
- package/dist/capabilities/context.cjs +34 -0
- package/dist/capabilities/context.cjs.map +1 -0
- package/dist/capabilities/context.d.cts +101 -0
- package/dist/capabilities/context.d.cts.map +1 -0
- package/dist/capabilities/context.d.mts +101 -0
- package/dist/capabilities/context.d.mts.map +1 -0
- package/dist/capabilities/context.mjs +29 -0
- package/dist/capabilities/context.mjs.map +1 -0
- package/dist/capabilities/index.cjs +18 -0
- package/dist/capabilities/index.cjs.map +1 -0
- package/dist/capabilities/index.d.cts +3 -0
- package/dist/capabilities/index.d.cts.map +1 -0
- package/dist/capabilities/index.d.mts +3 -0
- package/dist/capabilities/index.d.mts.map +1 -0
- package/dist/capabilities/index.mjs +2 -0
- package/dist/capabilities/index.mjs.map +1 -0
- package/dist/capabilities/types.cjs +3 -0
- package/dist/capabilities/types.cjs.map +1 -0
- package/dist/capabilities/types.d.cts +152 -0
- package/dist/capabilities/types.d.cts.map +1 -0
- package/dist/capabilities/types.d.mts +152 -0
- package/dist/capabilities/types.d.mts.map +1 -0
- package/dist/capabilities/types.mjs +2 -0
- package/dist/capabilities/types.mjs.map +1 -0
- package/dist/index.cjs +59 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +33 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +33 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +43 -0
- package/dist/index.mjs.map +1 -0
- package/dist/launcher/console-error-buffer.cjs +72 -0
- package/dist/launcher/console-error-buffer.cjs.map +1 -0
- package/dist/launcher/console-error-buffer.d.cts +43 -0
- package/dist/launcher/console-error-buffer.d.cts.map +1 -0
- package/dist/launcher/console-error-buffer.d.mts +43 -0
- package/dist/launcher/console-error-buffer.d.mts.map +1 -0
- package/dist/launcher/console-error-buffer.mjs +68 -0
- package/dist/launcher/console-error-buffer.mjs.map +1 -0
- package/dist/launcher/extension-id-resolver.cjs +177 -0
- package/dist/launcher/extension-id-resolver.cjs.map +1 -0
- package/dist/launcher/extension-id-resolver.d.cts +32 -0
- package/dist/launcher/extension-id-resolver.d.cts.map +1 -0
- package/dist/launcher/extension-id-resolver.d.mts +32 -0
- package/dist/launcher/extension-id-resolver.d.mts.map +1 -0
- package/dist/launcher/extension-id-resolver.mjs +173 -0
- package/dist/launcher/extension-id-resolver.mjs.map +1 -0
- package/dist/launcher/extension-readiness.cjs +50 -0
- package/dist/launcher/extension-readiness.cjs.map +1 -0
- package/dist/launcher/extension-readiness.d.cts +37 -0
- package/dist/launcher/extension-readiness.d.cts.map +1 -0
- package/dist/launcher/extension-readiness.d.mts +37 -0
- package/dist/launcher/extension-readiness.d.mts.map +1 -0
- package/dist/launcher/extension-readiness.mjs +43 -0
- package/dist/launcher/extension-readiness.mjs.map +1 -0
- package/dist/launcher/index.cjs +21 -0
- package/dist/launcher/index.cjs.map +1 -0
- package/dist/launcher/index.d.cts +5 -0
- package/dist/launcher/index.d.cts.map +1 -0
- package/dist/launcher/index.d.mts +5 -0
- package/dist/launcher/index.d.mts.map +1 -0
- package/dist/launcher/index.mjs +5 -0
- package/dist/launcher/index.mjs.map +1 -0
- package/dist/launcher/retry.cjs +35 -0
- package/dist/launcher/retry.cjs.map +1 -0
- package/dist/launcher/retry.d.cts +20 -0
- package/dist/launcher/retry.d.cts.map +1 -0
- package/dist/launcher/retry.d.mts +20 -0
- package/dist/launcher/retry.d.mts.map +1 -0
- package/dist/launcher/retry.mjs +31 -0
- package/dist/launcher/retry.mjs.map +1 -0
- package/dist/mcp-server/constants.cjs +22 -0
- package/dist/mcp-server/constants.cjs.map +1 -0
- package/dist/mcp-server/constants.d.cts +13 -0
- package/dist/mcp-server/constants.d.cts.map +1 -0
- package/dist/mcp-server/constants.d.mts +13 -0
- package/dist/mcp-server/constants.d.mts.map +1 -0
- package/dist/mcp-server/constants.mjs +19 -0
- package/dist/mcp-server/constants.mjs.map +1 -0
- package/dist/mcp-server/discovery.cjs +299 -0
- package/dist/mcp-server/discovery.cjs.map +1 -0
- package/dist/mcp-server/discovery.d.cts +56 -0
- package/dist/mcp-server/discovery.d.cts.map +1 -0
- package/dist/mcp-server/discovery.d.mts +56 -0
- package/dist/mcp-server/discovery.d.mts.map +1 -0
- package/dist/mcp-server/discovery.mjs +292 -0
- package/dist/mcp-server/discovery.mjs.map +1 -0
- package/dist/mcp-server/knowledge-store.cjs +1196 -0
- package/dist/mcp-server/knowledge-store.cjs.map +1 -0
- package/dist/mcp-server/knowledge-store.d.cts +249 -0
- package/dist/mcp-server/knowledge-store.d.cts.map +1 -0
- package/dist/mcp-server/knowledge-store.d.mts +249 -0
- package/dist/mcp-server/knowledge-store.d.mts.map +1 -0
- package/dist/mcp-server/knowledge-store.mjs +1154 -0
- package/dist/mcp-server/knowledge-store.mjs.map +1 -0
- package/dist/mcp-server/schemas.cjs +433 -0
- package/dist/mcp-server/schemas.cjs.map +1 -0
- package/dist/mcp-server/schemas.d.cts +557 -0
- package/dist/mcp-server/schemas.d.cts.map +1 -0
- package/dist/mcp-server/schemas.d.mts +557 -0
- package/dist/mcp-server/schemas.d.mts.map +1 -0
- package/dist/mcp-server/schemas.mjs +430 -0
- package/dist/mcp-server/schemas.mjs.map +1 -0
- package/dist/mcp-server/server.cjs +161 -0
- package/dist/mcp-server/server.cjs.map +1 -0
- package/dist/mcp-server/server.d.cts +24 -0
- package/dist/mcp-server/server.d.cts.map +1 -0
- package/dist/mcp-server/server.d.mts +24 -0
- package/dist/mcp-server/server.d.mts.map +1 -0
- package/dist/mcp-server/server.mjs +158 -0
- package/dist/mcp-server/server.mjs.map +1 -0
- package/dist/mcp-server/session-manager.cjs +53 -0
- package/dist/mcp-server/session-manager.cjs.map +1 -0
- package/dist/mcp-server/session-manager.d.cts +240 -0
- package/dist/mcp-server/session-manager.d.cts.map +1 -0
- package/dist/mcp-server/session-manager.d.mts +240 -0
- package/dist/mcp-server/session-manager.d.mts.map +1 -0
- package/dist/mcp-server/session-manager.mjs +48 -0
- package/dist/mcp-server/session-manager.mjs.map +1 -0
- package/dist/mcp-server/test-utils/flush-promises.cjs +10 -0
- package/dist/mcp-server/test-utils/flush-promises.cjs.map +1 -0
- package/dist/mcp-server/test-utils/flush-promises.d.cts +2 -0
- package/dist/mcp-server/test-utils/flush-promises.d.cts.map +1 -0
- package/dist/mcp-server/test-utils/flush-promises.d.mts +2 -0
- package/dist/mcp-server/test-utils/flush-promises.d.mts.map +1 -0
- package/dist/mcp-server/test-utils/flush-promises.mjs +7 -0
- package/dist/mcp-server/test-utils/flush-promises.mjs.map +1 -0
- package/dist/mcp-server/test-utils/index.cjs +13 -0
- package/dist/mcp-server/test-utils/index.cjs.map +1 -0
- package/dist/mcp-server/test-utils/index.d.cts +4 -0
- package/dist/mcp-server/test-utils/index.d.cts.map +1 -0
- package/dist/mcp-server/test-utils/index.d.mts +4 -0
- package/dist/mcp-server/test-utils/index.d.mts.map +1 -0
- package/dist/mcp-server/test-utils/index.mjs +4 -0
- package/dist/mcp-server/test-utils/index.mjs.map +1 -0
- package/dist/mcp-server/test-utils/mock-factories.cjs +129 -0
- package/dist/mcp-server/test-utils/mock-factories.cjs.map +1 -0
- package/dist/mcp-server/test-utils/mock-factories.d.cts +89 -0
- package/dist/mcp-server/test-utils/mock-factories.d.cts.map +1 -0
- package/dist/mcp-server/test-utils/mock-factories.d.mts +89 -0
- package/dist/mcp-server/test-utils/mock-factories.d.mts.map +1 -0
- package/dist/mcp-server/test-utils/mock-factories.mjs +125 -0
- package/dist/mcp-server/test-utils/mock-factories.mjs.map +1 -0
- package/dist/mcp-server/test-utils/mock-playwright.cjs +205 -0
- package/dist/mcp-server/test-utils/mock-playwright.cjs.map +1 -0
- package/dist/mcp-server/test-utils/mock-playwright.d.cts +69 -0
- package/dist/mcp-server/test-utils/mock-playwright.d.cts.map +1 -0
- package/dist/mcp-server/test-utils/mock-playwright.d.mts +69 -0
- package/dist/mcp-server/test-utils/mock-playwright.d.mts.map +1 -0
- package/dist/mcp-server/test-utils/mock-playwright.mjs +200 -0
- package/dist/mcp-server/test-utils/mock-playwright.mjs.map +1 -0
- package/dist/mcp-server/tokenization.cjs +117 -0
- package/dist/mcp-server/tokenization.cjs.map +1 -0
- package/dist/mcp-server/tokenization.d.cts +22 -0
- package/dist/mcp-server/tokenization.d.cts.map +1 -0
- package/dist/mcp-server/tokenization.d.mts +22 -0
- package/dist/mcp-server/tokenization.d.mts.map +1 -0
- package/dist/mcp-server/tokenization.mjs +112 -0
- package/dist/mcp-server/tokenization.mjs.map +1 -0
- package/dist/mcp-server/tools/batch.cjs +199 -0
- package/dist/mcp-server/tools/batch.cjs.map +1 -0
- package/dist/mcp-server/tools/batch.d.cts +81 -0
- package/dist/mcp-server/tools/batch.d.cts.map +1 -0
- package/dist/mcp-server/tools/batch.d.mts +81 -0
- package/dist/mcp-server/tools/batch.d.mts.map +1 -0
- package/dist/mcp-server/tools/batch.mjs +191 -0
- package/dist/mcp-server/tools/batch.mjs.map +1 -0
- package/dist/mcp-server/tools/build.cjs +47 -0
- package/dist/mcp-server/tools/build.cjs.map +1 -0
- package/dist/mcp-server/tools/build.d.cts +22 -0
- package/dist/mcp-server/tools/build.d.cts.map +1 -0
- package/dist/mcp-server/tools/build.d.mts +22 -0
- package/dist/mcp-server/tools/build.d.mts.map +1 -0
- package/dist/mcp-server/tools/build.mjs +44 -0
- package/dist/mcp-server/tools/build.mjs.map +1 -0
- package/dist/mcp-server/tools/cleanup.cjs +20 -0
- package/dist/mcp-server/tools/cleanup.cjs.map +1 -0
- package/dist/mcp-server/tools/cleanup.d.cts +10 -0
- package/dist/mcp-server/tools/cleanup.d.cts.map +1 -0
- package/dist/mcp-server/tools/cleanup.d.mts +10 -0
- package/dist/mcp-server/tools/cleanup.d.mts.map +1 -0
- package/dist/mcp-server/tools/cleanup.mjs +17 -0
- package/dist/mcp-server/tools/cleanup.mjs.map +1 -0
- package/dist/mcp-server/tools/clipboard.cjs +100 -0
- package/dist/mcp-server/tools/clipboard.cjs.map +1 -0
- package/dist/mcp-server/tools/clipboard.d.cts +16 -0
- package/dist/mcp-server/tools/clipboard.d.cts.map +1 -0
- package/dist/mcp-server/tools/clipboard.d.mts +16 -0
- package/dist/mcp-server/tools/clipboard.d.mts.map +1 -0
- package/dist/mcp-server/tools/clipboard.mjs +97 -0
- package/dist/mcp-server/tools/clipboard.mjs.map +1 -0
- package/dist/mcp-server/tools/context.cjs +66 -0
- package/dist/mcp-server/tools/context.cjs.map +1 -0
- package/dist/mcp-server/tools/context.d.cts +35 -0
- package/dist/mcp-server/tools/context.d.cts.map +1 -0
- package/dist/mcp-server/tools/context.d.mts +35 -0
- package/dist/mcp-server/tools/context.d.mts.map +1 -0
- package/dist/mcp-server/tools/context.mjs +62 -0
- package/dist/mcp-server/tools/context.mjs.map +1 -0
- package/dist/mcp-server/tools/definitions.cjs +463 -0
- package/dist/mcp-server/tools/definitions.cjs.map +1 -0
- package/dist/mcp-server/tools/definitions.d.cts +97 -0
- package/dist/mcp-server/tools/definitions.d.cts.map +1 -0
- package/dist/mcp-server/tools/definitions.d.mts +97 -0
- package/dist/mcp-server/tools/definitions.d.mts.map +1 -0
- package/dist/mcp-server/tools/definitions.mjs +451 -0
- package/dist/mcp-server/tools/definitions.mjs.map +1 -0
- package/dist/mcp-server/tools/discovery-tools.cjs +162 -0
- package/dist/mcp-server/tools/discovery-tools.cjs.map +1 -0
- package/dist/mcp-server/tools/discovery-tools.d.cts +26 -0
- package/dist/mcp-server/tools/discovery-tools.d.cts.map +1 -0
- package/dist/mcp-server/tools/discovery-tools.d.mts +26 -0
- package/dist/mcp-server/tools/discovery-tools.d.mts.map +1 -0
- package/dist/mcp-server/tools/discovery-tools.mjs +157 -0
- package/dist/mcp-server/tools/discovery-tools.mjs.map +1 -0
- package/dist/mcp-server/tools/error-classification.cjs +296 -0
- package/dist/mcp-server/tools/error-classification.cjs.map +1 -0
- package/dist/mcp-server/tools/error-classification.d.cts +135 -0
- package/dist/mcp-server/tools/error-classification.d.cts.map +1 -0
- package/dist/mcp-server/tools/error-classification.d.mts +135 -0
- package/dist/mcp-server/tools/error-classification.d.mts.map +1 -0
- package/dist/mcp-server/tools/error-classification.mjs +281 -0
- package/dist/mcp-server/tools/error-classification.mjs.map +1 -0
- package/dist/mcp-server/tools/helpers.cjs +149 -0
- package/dist/mcp-server/tools/helpers.cjs.map +1 -0
- package/dist/mcp-server/tools/helpers.d.cts +149 -0
- package/dist/mcp-server/tools/helpers.d.cts.map +1 -0
- package/dist/mcp-server/tools/helpers.d.mts +149 -0
- package/dist/mcp-server/tools/helpers.d.mts.map +1 -0
- package/dist/mcp-server/tools/helpers.mjs +141 -0
- package/dist/mcp-server/tools/helpers.mjs.map +1 -0
- package/dist/mcp-server/tools/index.cjs +27 -0
- package/dist/mcp-server/tools/index.cjs.map +1 -0
- package/dist/mcp-server/tools/index.d.cts +11 -0
- package/dist/mcp-server/tools/index.d.cts.map +1 -0
- package/dist/mcp-server/tools/index.d.mts +11 -0
- package/dist/mcp-server/tools/index.d.mts.map +1 -0
- package/dist/mcp-server/tools/index.mjs +11 -0
- package/dist/mcp-server/tools/index.mjs.map +1 -0
- package/dist/mcp-server/tools/interaction.cjs +190 -0
- package/dist/mcp-server/tools/interaction.cjs.map +1 -0
- package/dist/mcp-server/tools/interaction.d.cts +26 -0
- package/dist/mcp-server/tools/interaction.d.cts.map +1 -0
- package/dist/mcp-server/tools/interaction.d.mts +26 -0
- package/dist/mcp-server/tools/interaction.d.mts.map +1 -0
- package/dist/mcp-server/tools/interaction.mjs +185 -0
- package/dist/mcp-server/tools/interaction.mjs.map +1 -0
- package/dist/mcp-server/tools/knowledge.cjs +120 -0
- package/dist/mcp-server/tools/knowledge.cjs.map +1 -0
- package/dist/mcp-server/tools/knowledge.d.cts +34 -0
- package/dist/mcp-server/tools/knowledge.d.cts.map +1 -0
- package/dist/mcp-server/tools/knowledge.d.mts +34 -0
- package/dist/mcp-server/tools/knowledge.d.mts.map +1 -0
- package/dist/mcp-server/tools/knowledge.mjs +114 -0
- package/dist/mcp-server/tools/knowledge.mjs.map +1 -0
- package/dist/mcp-server/tools/launch.cjs +51 -0
- package/dist/mcp-server/tools/launch.cjs.map +1 -0
- package/dist/mcp-server/tools/launch.d.cts +10 -0
- package/dist/mcp-server/tools/launch.d.cts.map +1 -0
- package/dist/mcp-server/tools/launch.d.mts +10 -0
- package/dist/mcp-server/tools/launch.d.mts.map +1 -0
- package/dist/mcp-server/tools/launch.mjs +48 -0
- package/dist/mcp-server/tools/launch.mjs.map +1 -0
- package/dist/mcp-server/tools/navigation.cjs +242 -0
- package/dist/mcp-server/tools/navigation.cjs.map +1 -0
- package/dist/mcp-server/tools/navigation.d.cts +34 -0
- package/dist/mcp-server/tools/navigation.d.cts.map +1 -0
- package/dist/mcp-server/tools/navigation.d.mts +34 -0
- package/dist/mcp-server/tools/navigation.d.mts.map +1 -0
- package/dist/mcp-server/tools/navigation.mjs +236 -0
- package/dist/mcp-server/tools/navigation.mjs.map +1 -0
- package/dist/mcp-server/tools/registry.cjs +10 -0
- package/dist/mcp-server/tools/registry.cjs.map +1 -0
- package/dist/mcp-server/tools/registry.d.cts +4 -0
- package/dist/mcp-server/tools/registry.d.cts.map +1 -0
- package/dist/mcp-server/tools/registry.d.mts +4 -0
- package/dist/mcp-server/tools/registry.d.mts.map +1 -0
- package/dist/mcp-server/tools/registry.mjs +4 -0
- package/dist/mcp-server/tools/registry.mjs.map +1 -0
- package/dist/mcp-server/tools/run-tool.cjs +140 -0
- package/dist/mcp-server/tools/run-tool.cjs.map +1 -0
- package/dist/mcp-server/tools/run-tool.d.cts +39 -0
- package/dist/mcp-server/tools/run-tool.d.cts.map +1 -0
- package/dist/mcp-server/tools/run-tool.d.mts +39 -0
- package/dist/mcp-server/tools/run-tool.d.mts.map +1 -0
- package/dist/mcp-server/tools/run-tool.mjs +137 -0
- package/dist/mcp-server/tools/run-tool.mjs.map +1 -0
- package/dist/mcp-server/tools/screenshot.cjs +55 -0
- package/dist/mcp-server/tools/screenshot.cjs.map +1 -0
- package/dist/mcp-server/tools/screenshot.d.cts +10 -0
- package/dist/mcp-server/tools/screenshot.d.cts.map +1 -0
- package/dist/mcp-server/tools/screenshot.d.mts +10 -0
- package/dist/mcp-server/tools/screenshot.d.mts.map +1 -0
- package/dist/mcp-server/tools/screenshot.mjs +52 -0
- package/dist/mcp-server/tools/screenshot.mjs.map +1 -0
- package/dist/mcp-server/tools/seeding.cjs +214 -0
- package/dist/mcp-server/tools/seeding.cjs.map +1 -0
- package/dist/mcp-server/tools/seeding.d.cts +38 -0
- package/dist/mcp-server/tools/seeding.d.cts.map +1 -0
- package/dist/mcp-server/tools/seeding.d.mts +38 -0
- package/dist/mcp-server/tools/seeding.d.mts.map +1 -0
- package/dist/mcp-server/tools/seeding.mjs +208 -0
- package/dist/mcp-server/tools/seeding.mjs.map +1 -0
- package/dist/mcp-server/tools/state.cjs +69 -0
- package/dist/mcp-server/tools/state.cjs.map +1 -0
- package/dist/mcp-server/tools/state.d.cts +19 -0
- package/dist/mcp-server/tools/state.d.cts.map +1 -0
- package/dist/mcp-server/tools/state.d.mts +19 -0
- package/dist/mcp-server/tools/state.d.mts.map +1 -0
- package/dist/mcp-server/tools/state.mjs +66 -0
- package/dist/mcp-server/tools/state.mjs.map +1 -0
- package/dist/mcp-server/types/discovery.cjs +24 -0
- package/dist/mcp-server/types/discovery.cjs.map +1 -0
- package/dist/mcp-server/types/discovery.d.cts +30 -0
- package/dist/mcp-server/types/discovery.d.cts.map +1 -0
- package/dist/mcp-server/types/discovery.d.mts +30 -0
- package/dist/mcp-server/types/discovery.d.mts.map +1 -0
- package/dist/mcp-server/types/discovery.mjs +21 -0
- package/dist/mcp-server/types/discovery.mjs.map +1 -0
- package/dist/mcp-server/types/errors.cjs +33 -0
- package/dist/mcp-server/types/errors.cjs.map +1 -0
- package/dist/mcp-server/types/errors.d.cts +31 -0
- package/dist/mcp-server/types/errors.d.cts.map +1 -0
- package/dist/mcp-server/types/errors.d.mts +31 -0
- package/dist/mcp-server/types/errors.d.mts.map +1 -0
- package/dist/mcp-server/types/errors.mjs +30 -0
- package/dist/mcp-server/types/errors.mjs.map +1 -0
- package/dist/mcp-server/types/index.cjs +21 -0
- package/dist/mcp-server/types/index.cjs.map +1 -0
- package/dist/mcp-server/types/index.d.cts +10 -0
- package/dist/mcp-server/types/index.d.cts.map +1 -0
- package/dist/mcp-server/types/index.d.mts +10 -0
- package/dist/mcp-server/types/index.d.mts.map +1 -0
- package/dist/mcp-server/types/index.mjs +5 -0
- package/dist/mcp-server/types/index.mjs.map +1 -0
- package/dist/mcp-server/types/knowledge.cjs +3 -0
- package/dist/mcp-server/types/knowledge.cjs.map +1 -0
- package/dist/mcp-server/types/knowledge.d.cts +116 -0
- package/dist/mcp-server/types/knowledge.d.cts.map +1 -0
- package/dist/mcp-server/types/knowledge.d.mts +116 -0
- package/dist/mcp-server/types/knowledge.d.mts.map +1 -0
- package/dist/mcp-server/types/knowledge.mjs +2 -0
- package/dist/mcp-server/types/knowledge.mjs.map +1 -0
- package/dist/mcp-server/types/responses.cjs +3 -0
- package/dist/mcp-server/types/responses.cjs.map +1 -0
- package/dist/mcp-server/types/responses.d.cts +22 -0
- package/dist/mcp-server/types/responses.d.cts.map +1 -0
- package/dist/mcp-server/types/responses.d.mts +22 -0
- package/dist/mcp-server/types/responses.d.mts.map +1 -0
- package/dist/mcp-server/types/responses.mjs +2 -0
- package/dist/mcp-server/types/responses.mjs.map +1 -0
- package/dist/mcp-server/types/seeding.cjs +34 -0
- package/dist/mcp-server/types/seeding.cjs.map +1 -0
- package/dist/mcp-server/types/seeding.d.cts +40 -0
- package/dist/mcp-server/types/seeding.d.cts.map +1 -0
- package/dist/mcp-server/types/seeding.d.mts +40 -0
- package/dist/mcp-server/types/seeding.d.mts.map +1 -0
- package/dist/mcp-server/types/seeding.mjs +31 -0
- package/dist/mcp-server/types/seeding.mjs.map +1 -0
- package/dist/mcp-server/types/session.cjs +3 -0
- package/dist/mcp-server/types/session.cjs.map +1 -0
- package/dist/mcp-server/types/session.d.cts +11 -0
- package/dist/mcp-server/types/session.d.cts.map +1 -0
- package/dist/mcp-server/types/session.d.mts +11 -0
- package/dist/mcp-server/types/session.d.mts.map +1 -0
- package/dist/mcp-server/types/session.mjs +2 -0
- package/dist/mcp-server/types/session.mjs.map +1 -0
- package/dist/mcp-server/types/step-record.cjs +20 -0
- package/dist/mcp-server/types/step-record.cjs.map +1 -0
- package/dist/mcp-server/types/step-record.d.cts +86 -0
- package/dist/mcp-server/types/step-record.d.cts.map +1 -0
- package/dist/mcp-server/types/step-record.d.mts +86 -0
- package/dist/mcp-server/types/step-record.d.mts.map +1 -0
- package/dist/mcp-server/types/step-record.mjs +17 -0
- package/dist/mcp-server/types/step-record.mjs.map +1 -0
- package/dist/mcp-server/types/tool-inputs.cjs +3 -0
- package/dist/mcp-server/types/tool-inputs.cjs.map +1 -0
- package/dist/mcp-server/types/tool-inputs.d.cts +118 -0
- package/dist/mcp-server/types/tool-inputs.d.cts.map +1 -0
- package/dist/mcp-server/types/tool-inputs.d.mts +118 -0
- package/dist/mcp-server/types/tool-inputs.d.mts.map +1 -0
- package/dist/mcp-server/types/tool-inputs.mjs +2 -0
- package/dist/mcp-server/types/tool-inputs.mjs.map +1 -0
- package/dist/mcp-server/types/tool-outputs.cjs +3 -0
- package/dist/mcp-server/types/tool-outputs.cjs.map +1 -0
- package/dist/mcp-server/types/tool-outputs.d.cts +121 -0
- package/dist/mcp-server/types/tool-outputs.d.cts.map +1 -0
- package/dist/mcp-server/types/tool-outputs.d.mts +121 -0
- package/dist/mcp-server/types/tool-outputs.d.mts.map +1 -0
- package/dist/mcp-server/types/tool-outputs.mjs +2 -0
- package/dist/mcp-server/types/tool-outputs.mjs.map +1 -0
- package/dist/mcp-server/utils/errors.cjs +14 -0
- package/dist/mcp-server/utils/errors.cjs.map +1 -0
- package/dist/mcp-server/utils/errors.d.cts +9 -0
- package/dist/mcp-server/utils/errors.d.cts.map +1 -0
- package/dist/mcp-server/utils/errors.d.mts +9 -0
- package/dist/mcp-server/utils/errors.d.mts.map +1 -0
- package/dist/mcp-server/utils/errors.mjs +11 -0
- package/dist/mcp-server/utils/errors.mjs.map +1 -0
- package/dist/mcp-server/utils/index.cjs +22 -0
- package/dist/mcp-server/utils/index.cjs.map +1 -0
- package/dist/mcp-server/utils/index.d.cts +8 -0
- package/dist/mcp-server/utils/index.d.cts.map +1 -0
- package/dist/mcp-server/utils/index.d.mts +8 -0
- package/dist/mcp-server/utils/index.d.mts.map +1 -0
- package/dist/mcp-server/utils/index.mjs +8 -0
- package/dist/mcp-server/utils/index.mjs.map +1 -0
- package/dist/mcp-server/utils/logger.cjs +25 -0
- package/dist/mcp-server/utils/logger.cjs.map +1 -0
- package/dist/mcp-server/utils/logger.d.cts +9 -0
- package/dist/mcp-server/utils/logger.d.cts.map +1 -0
- package/dist/mcp-server/utils/logger.d.mts +9 -0
- package/dist/mcp-server/utils/logger.d.mts.map +1 -0
- package/dist/mcp-server/utils/logger.mjs +22 -0
- package/dist/mcp-server/utils/logger.mjs.map +1 -0
- package/dist/mcp-server/utils/redaction.cjs +24 -0
- package/dist/mcp-server/utils/redaction.cjs.map +1 -0
- package/dist/mcp-server/utils/redaction.d.cts +9 -0
- package/dist/mcp-server/utils/redaction.d.cts.map +1 -0
- package/dist/mcp-server/utils/redaction.d.mts +9 -0
- package/dist/mcp-server/utils/redaction.d.mts.map +1 -0
- package/dist/mcp-server/utils/redaction.mjs +20 -0
- package/dist/mcp-server/utils/redaction.mjs.map +1 -0
- package/dist/mcp-server/utils/response.cjs +49 -0
- package/dist/mcp-server/utils/response.cjs.map +1 -0
- package/dist/mcp-server/utils/response.d.cts +22 -0
- package/dist/mcp-server/utils/response.d.cts.map +1 -0
- package/dist/mcp-server/utils/response.d.mts +22 -0
- package/dist/mcp-server/utils/response.d.mts.map +1 -0
- package/dist/mcp-server/utils/response.mjs +45 -0
- package/dist/mcp-server/utils/response.mjs.map +1 -0
- package/dist/mcp-server/utils/targets.cjs +32 -0
- package/dist/mcp-server/utils/targets.cjs.map +1 -0
- package/dist/mcp-server/utils/targets.d.cts +25 -0
- package/dist/mcp-server/utils/targets.d.cts.map +1 -0
- package/dist/mcp-server/utils/targets.d.mts +25 -0
- package/dist/mcp-server/utils/targets.d.mts.map +1 -0
- package/dist/mcp-server/utils/targets.mjs +29 -0
- package/dist/mcp-server/utils/targets.mjs.map +1 -0
- package/dist/mcp-server/utils/time.cjs +39 -0
- package/dist/mcp-server/utils/time.cjs.map +1 -0
- package/dist/mcp-server/utils/time.d.cts +15 -0
- package/dist/mcp-server/utils/time.d.cts.map +1 -0
- package/dist/mcp-server/utils/time.d.mts +15 -0
- package/dist/mcp-server/utils/time.d.mts.map +1 -0
- package/dist/mcp-server/utils/time.mjs +35 -0
- package/dist/mcp-server/utils/time.mjs.map +1 -0
- package/dist/mcp-server/utils/type-guards.cjs +42 -0
- package/dist/mcp-server/utils/type-guards.cjs.map +1 -0
- package/dist/mcp-server/utils/type-guards.d.cts +30 -0
- package/dist/mcp-server/utils/type-guards.d.cts.map +1 -0
- package/dist/mcp-server/utils/type-guards.d.mts +30 -0
- package/dist/mcp-server/utils/type-guards.d.mts.map +1 -0
- package/dist/mcp-server/utils/type-guards.mjs +38 -0
- package/dist/mcp-server/utils/type-guards.mjs.map +1 -0
- package/dist/utils/fetch.cjs +36 -0
- package/dist/utils/fetch.cjs.map +1 -0
- package/dist/utils/fetch.d.cts +20 -0
- package/dist/utils/fetch.d.cts.map +1 -0
- package/dist/utils/fetch.d.mts +20 -0
- package/dist/utils/fetch.d.mts.map +1 -0
- package/dist/utils/fetch.mjs +33 -0
- package/dist/utils/fetch.mjs.map +1 -0
- package/dist/utils/index.cjs +11 -0
- package/dist/utils/index.cjs.map +1 -0
- package/dist/utils/index.d.cts +6 -0
- package/dist/utils/index.d.cts.map +1 -0
- package/dist/utils/index.d.mts +6 -0
- package/dist/utils/index.d.mts.map +1 -0
- package/dist/utils/index.mjs +6 -0
- package/dist/utils/index.mjs.map +1 -0
- package/dist/utils/service-readiness.cjs +75 -0
- package/dist/utils/service-readiness.cjs.map +1 -0
- package/dist/utils/service-readiness.d.cts +61 -0
- package/dist/utils/service-readiness.d.cts.map +1 -0
- package/dist/utils/service-readiness.d.mts +61 -0
- package/dist/utils/service-readiness.d.mts.map +1 -0
- package/dist/utils/service-readiness.mjs +72 -0
- package/dist/utils/service-readiness.mjs.map +1 -0
- 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"}
|