opera-devtools-mcp 0.2.3 → 0.3.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 (330) hide show
  1. package/README.md +104 -7
  2. package/build/src/McpContext.js +365 -365
  3. package/build/src/McpPage.js +475 -48
  4. package/build/src/McpResponse.js +462 -288
  5. package/build/src/SlimMcpResponse.js +1 -1
  6. package/build/src/TextSnapshot.js +101 -22
  7. package/build/src/ToolHandler.js +142 -20
  8. package/build/src/bin/check-latest-version.js +27 -1
  9. package/build/src/bin/chrome-devtools-cli-options.js +573 -10
  10. package/build/src/bin/chrome-devtools-mcp-cli-options.js +119 -32
  11. package/build/src/bin/chrome-devtools-mcp-main.js +50 -7
  12. package/build/src/bin/chrome-devtools-mcp.js +7 -4
  13. package/build/src/bin/chrome-devtools.js +57 -14
  14. package/build/src/bin/opera-devtools-cli-options.js +3 -829
  15. package/build/src/bin/opera-devtools-mcp-cli-options.js +3 -348
  16. package/build/src/bin/opera-devtools-mcp-main.js +3 -37
  17. package/build/src/bin/opera-devtools-mcp.js +4 -19
  18. package/build/src/bin/opera-devtools.js +4 -185
  19. package/build/src/browser.js +45 -5
  20. package/build/src/{PageCollector.js → collectors/PageCollector.js} +64 -133
  21. package/build/src/collectors/ServiceWorkerCollector.js +171 -0
  22. package/build/src/daemon/client.js +75 -17
  23. package/build/src/daemon/daemon.js +92 -30
  24. package/build/src/daemon/utils.js +24 -8
  25. package/build/src/{DevtoolsUtils.js → devtools/DevtoolsUtils.js} +94 -88
  26. package/build/src/devtools/McpHostBindingAdapter.js +165 -0
  27. package/build/src/{issue-descriptions.js → devtools/issueDescriptions.js} +8 -6
  28. package/build/src/formatters/ConsoleFormatter.js +44 -11
  29. package/build/src/formatters/HeapSnapshotFormatter.js +140 -9
  30. package/build/src/formatters/IssueFormatter.js +7 -7
  31. package/build/src/formatters/NetworkFormatter.js +10 -8
  32. package/build/src/index.js +101 -232
  33. package/build/src/opera/branding.js +34 -0
  34. package/build/src/opera/browserFlags.js +85 -0
  35. package/build/src/opera/browserLaunch.js +52 -0
  36. package/build/src/opera/policy.js +50 -0
  37. package/build/src/opera/serviceWorkerRetry.js +37 -0
  38. package/build/src/opera/toolHandlerHooks.js +39 -0
  39. package/build/src/{tools → opera/tools}/opera.js +9 -21
  40. package/build/src/processors/HeapSnapshotManager.js +258 -0
  41. package/build/src/{trace-processing/parse.js → processors/PerformanceTrace.js} +9 -9
  42. package/build/src/telemetry/ClearcutLogger.js +12 -119
  43. package/build/src/telemetry/WatchdogClient.js +5 -5
  44. package/build/src/telemetry/errors.js +1 -1
  45. package/build/src/telemetry/flagUtils.js +6 -6
  46. package/build/src/telemetry/{toolMetricsUtils.js → metricsRegistry.js} +4 -11
  47. package/build/src/telemetry/persistence.js +3 -3
  48. package/build/src/telemetry/transformation.js +184 -0
  49. package/build/src/telemetry/watchdog/ClearcutSender.js +11 -11
  50. package/build/src/telemetry/watchdog/main.js +6 -6
  51. package/build/src/third_party/THIRD_PARTY_NOTICES +3493 -0
  52. package/build/src/third_party/bundled-packages.json +9 -0
  53. package/build/src/third_party/devtools-formatter-worker.js +15340 -7
  54. package/build/src/third_party/devtools-heap-snapshot-worker.js +10337 -7
  55. package/build/src/third_party/index.js +179960 -26
  56. package/build/src/third_party/issue-descriptions/CoepCorpNotSameOrigin.md +2 -2
  57. package/build/src/third_party/issue-descriptions/CoepCorpNotSameOriginAfterDefaultedToSameOriginByCoep.md +3 -3
  58. package/build/src/third_party/issue-descriptions/CoepCorpNotSameSite.md +2 -2
  59. package/build/src/third_party/issue-descriptions/CoepFrameResourceNeedsCoepHeader.md +1 -1
  60. package/build/src/third_party/issue-descriptions/CompatibilityModeQuirks.md +1 -1
  61. package/build/src/third_party/issue-descriptions/CookieAttributeValueExceedsMaxSize.md +2 -2
  62. package/build/src/third_party/issue-descriptions/LowTextContrast.md +1 -1
  63. package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureErrorRead.md +1 -1
  64. package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureErrorSet.md +1 -1
  65. package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureWarnRead.md +1 -1
  66. package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureWarnSet.md +1 -1
  67. package/build/src/third_party/issue-descriptions/SameSiteUnspecifiedLaxAllowUnsafeRead.md +3 -3
  68. package/build/src/third_party/issue-descriptions/SameSiteUnspecifiedLaxAllowUnsafeSet.md +3 -3
  69. package/build/src/third_party/issue-descriptions/bounceTrackingMitigations.md +1 -1
  70. package/build/src/third_party/issue-descriptions/connectionAllowlistEmbeddingRequirementNotSatisfied.md +26 -0
  71. package/build/src/third_party/issue-descriptions/connectionAllowlistIFrameAttributeLoosensEmbeddingRequirement.md +19 -0
  72. package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidAllowConnectionAllowlistFrom.md +21 -0
  73. package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidAllowlistItemType.md +2 -2
  74. package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidHeader.md +2 -2
  75. package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidUrlPattern.md +3 -3
  76. package/build/src/third_party/issue-descriptions/connectionAllowlistItemNotInnerList.md +2 -2
  77. package/build/src/third_party/issue-descriptions/connectionAllowlistMoreThanOneList.md +2 -2
  78. package/build/src/third_party/issue-descriptions/connectionAllowlistReportingEndpointNotToken.md +1 -1
  79. package/build/src/third_party/issue-descriptions/cookieCrossSiteRedirectDowngrade.md +3 -3
  80. package/build/src/third_party/issue-descriptions/cookieExcludeBlockedWithinRelatedWebsiteSet.md +1 -1
  81. package/build/src/third_party/issue-descriptions/cookieExcludePortMismatch.md +1 -1
  82. package/build/src/third_party/issue-descriptions/cookieExcludeSchemeMismatch.md +1 -1
  83. package/build/src/third_party/issue-descriptions/cookieExcludeThirdPartyPhaseoutSet.md +1 -1
  84. package/build/src/third_party/issue-descriptions/cookieWarnThirdPartyPhaseoutRead.md +1 -1
  85. package/build/src/third_party/issue-descriptions/corsAllowCredentialsRequired.md +1 -1
  86. package/build/src/third_party/issue-descriptions/corsDisabledScheme.md +2 -2
  87. package/build/src/third_party/issue-descriptions/corsDisallowedByMode.md +2 -2
  88. package/build/src/third_party/issue-descriptions/corsHeaderDisallowedByPreflightResponse.md +1 -1
  89. package/build/src/third_party/issue-descriptions/corsInvalidHeaderValues.md +3 -3
  90. package/build/src/third_party/issue-descriptions/corsLocalNetworkAccessPermissionDenied.md +1 -1
  91. package/build/src/third_party/issue-descriptions/corsMethodDisallowedByPreflightResponse.md +1 -1
  92. package/build/src/third_party/issue-descriptions/corsNoCorsRedirectModeNotFollow.md +1 -1
  93. package/build/src/third_party/issue-descriptions/corsOriginMismatch.md +3 -3
  94. package/build/src/third_party/issue-descriptions/corsPreflightResponseInvalid.md +2 -2
  95. package/build/src/third_party/issue-descriptions/corsRedirectContainsCredentials.md +3 -3
  96. package/build/src/third_party/issue-descriptions/corsWildcardOriginNotAllowed.md +4 -3
  97. package/build/src/third_party/issue-descriptions/cspEvalViolation.md +4 -4
  98. package/build/src/third_party/issue-descriptions/cspInlineViolation.md +2 -2
  99. package/build/src/third_party/issue-descriptions/cspTrustedTypesPolicyViolation.md +2 -2
  100. package/build/src/third_party/issue-descriptions/cspTrustedTypesSinkViolation.md +4 -4
  101. package/build/src/third_party/issue-descriptions/cspURLViolation.md +4 -4
  102. package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsEmptyList.md +1 -0
  103. package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsHttpNotFound.md +1 -0
  104. package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsInvalidContentType.md +1 -0
  105. package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsInvalidResponse.md +1 -0
  106. package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsNoResponse.md +1 -0
  107. package/build/src/third_party/issue-descriptions/emailVerificationRequestDnsFetchFailed.md +1 -0
  108. package/build/src/third_party/issue-descriptions/emailVerificationRequestDnsInvalidRecord.md +1 -0
  109. package/build/src/third_party/issue-descriptions/emailVerificationRequestEmailVerificationWellKnownHttpNotFound.md +1 -0
  110. package/build/src/third_party/issue-descriptions/emailVerificationRequestEmailVerificationWellKnownInvalidContentType.md +1 -0
  111. package/build/src/third_party/issue-descriptions/emailVerificationRequestEmailVerificationWellKnownInvalidResponse.md +1 -0
  112. package/build/src/third_party/issue-descriptions/emailVerificationRequestEmailVerificationWellKnownNoResponse.md +1 -0
  113. package/build/src/third_party/issue-descriptions/emailVerificationRequestInvalidEmail.md +1 -0
  114. package/build/src/third_party/issue-descriptions/emailVerificationRequestJwksHttpNotFound.md +1 -0
  115. package/build/src/third_party/issue-descriptions/emailVerificationRequestJwksInvalidResponse.md +1 -0
  116. package/build/src/third_party/issue-descriptions/emailVerificationRequestKeyBindingSigningFailed.md +1 -0
  117. package/build/src/third_party/issue-descriptions/emailVerificationRequestRpOriginIsOpaque.md +1 -0
  118. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenHttpNotFound.md +1 -0
  119. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenInvalidContentType.md +1 -0
  120. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenInvalidResponse.md +1 -0
  121. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenInvalidSdJwt.md +1 -0
  122. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenMalformedSdJwt.md +1 -0
  123. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenNoResponse.md +1 -0
  124. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidAudience.md +1 -0
  125. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidIssuedAt.md +1 -0
  126. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidNonce.md +1 -0
  127. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidSdHash.md +1 -0
  128. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidTyp.md +1 -0
  129. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingAud.md +1 -0
  130. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingCnf.md +1 -0
  131. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingIat.md +1 -0
  132. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingNonce.md +1 -0
  133. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingSdHash.md +1 -0
  134. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbSignatureFailed.md +1 -0
  135. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidEmail.md +1 -0
  136. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidEmailVerified.md +1 -0
  137. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidHolderKey.md +1 -0
  138. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidIssuedAt.md +1 -0
  139. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidIssuer.md +1 -0
  140. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtJwksMissingKeys.md +1 -0
  141. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtMissingCnf.md +1 -0
  142. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtMissingEmail.md +1 -0
  143. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtMissingIat.md +1 -0
  144. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtMissingIss.md +1 -0
  145. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtSignatureFailed.md +1 -0
  146. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtUnsupportedHeaderAlg.md +1 -0
  147. package/build/src/third_party/issue-descriptions/emailVerificationRequestUserLoggedOut.md +1 -0
  148. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownAccountsEndpointCrossOrigin.md +1 -0
  149. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownHttpNotFound.md +1 -0
  150. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownInvalidContentType.md +1 -0
  151. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownInvalidResponse.md +1 -0
  152. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownIssuanceEndpointCrossOrigin.md +1 -0
  153. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownListEmpty.md +1 -0
  154. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownMissingAccountsEndpoint.md +1 -0
  155. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownMissingIssuanceEndpoint.md +1 -0
  156. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownNoResponse.md +1 -0
  157. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownUnsupportedSigningAlgorithm.md +1 -0
  158. package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsHttpNotFound.md +1 -1
  159. package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsInvalidResponse.md +1 -1
  160. package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsNoResponse.md +1 -1
  161. package/build/src/third_party/issue-descriptions/federatedAuthRequestApprovalDeclined.md +1 -1
  162. package/build/src/third_party/issue-descriptions/federatedAuthRequestCanceled.md +1 -1
  163. package/build/src/third_party/issue-descriptions/federatedAuthRequestErrorFetchingSignin.md +1 -1
  164. package/build/src/third_party/issue-descriptions/federatedAuthRequestErrorIdToken.md +1 -1
  165. package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenHttpNotFound.md +1 -1
  166. package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenInvalidRequest.md +1 -1
  167. package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenInvalidResponse.md +1 -1
  168. package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenNoResponse.md +1 -1
  169. package/build/src/third_party/issue-descriptions/federatedAuthRequestInvalidSigninResponse.md +1 -1
  170. package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestHttpNotFound.md +1 -1
  171. package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestInvalidResponse.md +1 -1
  172. package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestNoResponse.md +1 -1
  173. package/build/src/third_party/issue-descriptions/federatedAuthRequestTooManyRequests.md +1 -1
  174. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestInvalidAccountsResponse.md +1 -1
  175. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestInvalidConfigOrWellKnown.md +1 -1
  176. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoAccountSharingPermission.md +1 -1
  177. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoApiPermission.md +1 -1
  178. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoReturningUserFromFetchedAccounts.md +1 -1
  179. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotIframe.md +1 -1
  180. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotPotentiallyTrustworthy.md +1 -1
  181. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotSameOrigin.md +1 -1
  182. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotSignedInWithIdp.md +1 -1
  183. package/build/src/third_party/issue-descriptions/fetchingPartitionedBlobURL.md +2 -2
  184. package/build/src/third_party/issue-descriptions/genericBackUINavigationWouldSkipAd.md +4 -0
  185. package/build/src/third_party/issue-descriptions/genericFormAriaLabelledByToNonExistingIdError.md +2 -2
  186. package/build/src/third_party/issue-descriptions/genericFormAutocompleteAttributeEmptyError.md +1 -1
  187. package/build/src/third_party/issue-descriptions/genericFormDuplicateIdForInputError.md +1 -1
  188. package/build/src/third_party/issue-descriptions/genericFormEmptyIdAndNameAttributesForInputError.md +2 -2
  189. package/build/src/third_party/issue-descriptions/genericFormInputAssignedAutocompleteValueToIdOrNameAttributeError.md +2 -2
  190. package/build/src/third_party/issue-descriptions/genericFormInputHasWrongButWellIntendedAutocompleteValueError.md +1 -1
  191. package/build/src/third_party/issue-descriptions/genericFormInputWithNoLabelError.md +1 -1
  192. package/build/src/third_party/issue-descriptions/genericFormLabelForMatchesNonExistingIdError.md +2 -2
  193. package/build/src/third_party/issue-descriptions/genericFormLabelForNameError.md +1 -1
  194. package/build/src/third_party/issue-descriptions/genericFormLabelHasNeitherForNorNestedInputError.md +1 -1
  195. package/build/src/third_party/issue-descriptions/genericFormModelContextMissingToolName.md +1 -1
  196. package/build/src/third_party/issue-descriptions/genericFormModelContextParameterMissingName.md +1 -1
  197. package/build/src/third_party/issue-descriptions/genericFormModelContextRequiredParameterMissingName.md +1 -1
  198. package/build/src/third_party/issue-descriptions/genericNavigationEntryMarkedSkippable.md +2 -2
  199. package/build/src/third_party/issue-descriptions/heavyAd.md +1 -1
  200. package/build/src/third_party/issue-descriptions/lazyLoadImageZeroSize.md +7 -0
  201. package/build/src/third_party/issue-descriptions/navigatingPartitionedBlobURL.md +3 -3
  202. package/build/src/third_party/issue-descriptions/permissionElementActivationDisabled.md +1 -1
  203. package/build/src/third_party/issue-descriptions/permissionElementActivationDisabledWithOccluder.md +1 -1
  204. package/build/src/third_party/issue-descriptions/permissionElementActivationDisabledWithOccluderParent.md +1 -1
  205. package/build/src/third_party/issue-descriptions/permissionElementFencedFrameDisallowed.md +2 -2
  206. package/build/src/third_party/issue-descriptions/permissionElementFontSizeTooLarge.md +2 -2
  207. package/build/src/third_party/issue-descriptions/permissionElementFontSizeTooSmall.md +2 -2
  208. package/build/src/third_party/issue-descriptions/permissionElementInsetBoxShadowUnsupported.md +1 -1
  209. package/build/src/third_party/issue-descriptions/permissionElementInvalidDisplayStyle.md +2 -2
  210. package/build/src/third_party/issue-descriptions/permissionElementInvalidSizeValue.md +2 -2
  211. package/build/src/third_party/issue-descriptions/permissionElementInvalidType.md +2 -2
  212. package/build/src/third_party/issue-descriptions/permissionElementInvalidTypeActivation.md +2 -2
  213. package/build/src/third_party/issue-descriptions/permissionElementNonOpaqueColor.md +1 -1
  214. package/build/src/third_party/issue-descriptions/permissionElementPaddingBottomUnsupported.md +2 -2
  215. package/build/src/third_party/issue-descriptions/permissionElementPaddingRightUnsupported.md +2 -2
  216. package/build/src/third_party/issue-descriptions/permissionElementRequestInProgress.md +2 -2
  217. package/build/src/third_party/issue-descriptions/permissionElementSecurityChecksFailed.md +1 -1
  218. package/build/src/third_party/issue-descriptions/permissionElementTypeNotSupported.md +2 -2
  219. package/build/src/third_party/issue-descriptions/permissionElementUntrustedEvent.md +1 -1
  220. package/build/src/third_party/issue-descriptions/placeholderDescriptionForInvisibleIssues.md +1 -1
  221. package/build/src/third_party/issue-descriptions/selectElementAccessibilityDisallowedOptGroupChild.md +1 -1
  222. package/build/src/third_party/issue-descriptions/selectElementAccessibilityDisallowedSelectChild.md +1 -1
  223. package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentAttributesSelectDescendant.md +1 -1
  224. package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentLegendChild.md +1 -1
  225. package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentOptionChild.md +1 -1
  226. package/build/src/third_party/issue-descriptions/selectElementAccessibilityNonPhrasingContentOptionChild.md +1 -1
  227. package/build/src/third_party/issue-descriptions/selectivePermissionsIntervention.md +3 -3
  228. package/build/src/third_party/issue-descriptions/sharedArrayBuffer.md +1 -1
  229. package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorCrossOriginNoCorsRequest.md +1 -1
  230. package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorMatchingDictionaryNotUsed.md +1 -1
  231. package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorUnexpectedContentDictionaryHeader.md +1 -1
  232. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorCossOriginNoCorsRequest.md +1 -1
  233. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorDisallowedBySettings.md +1 -1
  234. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorExpiredResponse.md +1 -1
  235. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorFeatureDisabled.md +2 -2
  236. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorInvalidStructuredHeader.md +1 -1
  237. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNavigationRequest.md +2 -2
  238. package/build/src/third_party/issue-descriptions/sriInvalidSignatureHeader.md +4 -4
  239. package/build/src/third_party/issue-descriptions/sriInvalidSignatureInputHeader.md +4 -4
  240. package/build/src/third_party/issue-descriptions/sriMissingSignatureHeader.md +1 -1
  241. package/build/src/third_party/issue-descriptions/sriMissingSignatureInputHeader.md +2 -2
  242. package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsIncorrectLength.md +2 -2
  243. package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsNotByteSequence.md +4 -4
  244. package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsParameterized.md +4 -4
  245. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidComponentName.md +1 -1
  246. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidComponentType.md +2 -2
  247. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidDerivedComponentParameter.md +1 -1
  248. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidHeaderComponentParameter.md +1 -1
  249. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidParameter.md +2 -2
  250. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderKeyIdLength.md +5 -5
  251. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderMissingLabel.md +3 -3
  252. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderMissingRequiredParameters.md +2 -2
  253. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderValueMissingComponents.md +2 -2
  254. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderValueNotInnerList.md +2 -2
  255. package/build/src/third_party/issue-descriptions/sriValidationFailedIntegrityMismatch.md +4 -4
  256. package/build/src/third_party/issue-descriptions/sriValidationFailedInvalidLength.md +3 -3
  257. package/build/src/third_party/issue-descriptions/sriValidationFailedSignatureExpired.md +2 -2
  258. package/build/src/third_party/issue-descriptions/sriValidationFailedSignatureMismatch.md +2 -2
  259. package/build/src/third_party/issue-descriptions/stylesheetLateImport.md +1 -1
  260. package/build/src/third_party/issue-descriptions/summaryElementAccessibilityInteractiveContentSummaryDescendant.md +1 -1
  261. package/build/src/third_party/issue-descriptions/unencodedDigestIncorrectDigestLength.md +2 -2
  262. package/build/src/third_party/issue-descriptions/unencodedDigestIncorrectDigestType.md +3 -3
  263. package/build/src/third_party/issue-descriptions/unencodedDigestMalformedDictionary.md +2 -2
  264. package/build/src/third_party/issue-descriptions/unencodedDigestUnknownAlgorithm.md +1 -1
  265. package/build/src/third_party/lighthouse-devtools-mcp-bundle.js +3177 -6340
  266. package/build/src/tools/ToolDefinition.js +2 -2
  267. package/build/src/tools/categories.js +3 -0
  268. package/build/src/tools/console.js +13 -0
  269. package/build/src/tools/emulation.js +30 -3
  270. package/build/src/tools/extensions.js +8 -1
  271. package/build/src/tools/input.js +246 -128
  272. package/build/src/tools/lighthouse.js +14 -7
  273. package/build/src/tools/memory.js +289 -25
  274. package/build/src/tools/network.js +10 -7
  275. package/build/src/tools/pages.js +33 -92
  276. package/build/src/tools/performance.js +67 -52
  277. package/build/src/tools/pwa.js +128 -0
  278. package/build/src/tools/screencast.js +35 -12
  279. package/build/src/tools/screenshot.js +234 -75
  280. package/build/src/tools/script.js +130 -45
  281. package/build/src/tools/slim/tools.js +3 -0
  282. package/build/src/tools/snapshot.js +7 -4
  283. package/build/src/tools/thirdPartyDeveloper.js +19 -9
  284. package/build/src/tools/tools.js +3 -1
  285. package/build/src/tools/webmcp.js +3 -1
  286. package/build/src/utils/WaitForHelper.js +299 -0
  287. package/build/src/utils/check-for-updates.js +8 -2
  288. package/build/src/utils/files.js +42 -3
  289. package/build/src/utils/logger.js +51 -0
  290. package/build/src/utils/polyfill.js +11 -0
  291. package/build/src/utils/url.js +43 -0
  292. package/build/src/version.js +1 -1
  293. package/package.json +42 -33
  294. package/build/src/DevToolsConnectionAdapter.js +0 -70
  295. package/build/src/HeapSnapshotManager.js +0 -110
  296. package/build/src/Mutex.js +0 -38
  297. package/build/src/WaitForHelper.js +0 -195
  298. package/build/src/bin/cliDefinitions.js +0 -616
  299. package/build/src/logger.js +0 -37
  300. package/build/src/polyfill.js +0 -8
  301. package/build/src/telemetry/metricUtils.js +0 -15
  302. package/build/src/third_party/issue-descriptions/SameSiteExcludeContextDowngradeRead.md +0 -8
  303. package/build/src/third_party/issue-descriptions/SameSiteExcludeContextDowngradeSet.md +0 -8
  304. package/build/src/third_party/issue-descriptions/SameSiteExcludeNavigationContextDowngrade.md +0 -8
  305. package/build/src/third_party/issue-descriptions/SameSiteWarnCrossDowngradeRead.md +0 -8
  306. package/build/src/third_party/issue-descriptions/SameSiteWarnCrossDowngradeSet.md +0 -8
  307. package/build/src/third_party/issue-descriptions/SameSiteWarnStrictLaxDowngradeStrict.md +0 -8
  308. package/build/src/third_party/issue-descriptions/arInsecureContext.md +0 -7
  309. package/build/src/third_party/issue-descriptions/arInvalidInfoHeader.md +0 -5
  310. package/build/src/third_party/issue-descriptions/arInvalidRegisterOsSourceHeader.md +0 -5
  311. package/build/src/third_party/issue-descriptions/arInvalidRegisterOsTriggerHeader.md +0 -5
  312. package/build/src/third_party/issue-descriptions/arInvalidRegisterSourceHeader.md +0 -5
  313. package/build/src/third_party/issue-descriptions/arInvalidRegisterTriggerHeader.md +0 -5
  314. package/build/src/third_party/issue-descriptions/arNavigationRegistrationUniqueScopeAlreadySet.md +0 -5
  315. package/build/src/third_party/issue-descriptions/arNavigationRegistrationWithoutTransientUserActivation.md +0 -6
  316. package/build/src/third_party/issue-descriptions/arNoRegisterOsSourceHeader.md +0 -5
  317. package/build/src/third_party/issue-descriptions/arNoRegisterOsTriggerHeader.md +0 -5
  318. package/build/src/third_party/issue-descriptions/arNoRegisterSourceHeader.md +0 -5
  319. package/build/src/third_party/issue-descriptions/arNoRegisterTriggerHeader.md +0 -5
  320. package/build/src/third_party/issue-descriptions/arNoWebOrOsSupport.md +0 -4
  321. package/build/src/third_party/issue-descriptions/arOsSourceIgnored.md +0 -18
  322. package/build/src/third_party/issue-descriptions/arOsTriggerIgnored.md +0 -19
  323. package/build/src/third_party/issue-descriptions/arPermissionPolicyDisabled.md +0 -8
  324. package/build/src/third_party/issue-descriptions/arSourceAndTriggerHeaders.md +0 -9
  325. package/build/src/third_party/issue-descriptions/arSourceIgnored.md +0 -13
  326. package/build/src/third_party/issue-descriptions/arTriggerIgnored.md +0 -12
  327. package/build/src/third_party/issue-descriptions/arUntrustworthyReportingOrigin.md +0 -10
  328. package/build/src/third_party/issue-descriptions/arWebAndOsHeaders.md +0 -11
  329. package/build/src/utils/string.js +0 -37
  330. package/build/src/utils/types.js +0 -7
@@ -3,10 +3,113 @@
3
3
  * Copyright 2025 Google LLC
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
- import { logger } from './logger.js';
6
+ var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
7
+ if (value !== null && value !== void 0) {
8
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
9
+ var dispose, inner;
10
+ if (async) {
11
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
12
+ dispose = value[Symbol.asyncDispose];
13
+ }
14
+ if (dispose === void 0) {
15
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
16
+ dispose = value[Symbol.dispose];
17
+ if (async) inner = dispose;
18
+ }
19
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
20
+ if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
21
+ env.stack.push({ value: value, dispose: dispose, async: async });
22
+ }
23
+ else if (async) {
24
+ env.stack.push({ async: true });
25
+ }
26
+ return value;
27
+ };
28
+ var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
29
+ return function (env) {
30
+ function fail(e) {
31
+ env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
32
+ env.hasError = true;
33
+ }
34
+ var r, s = 0;
35
+ function next() {
36
+ while (r = env.stack.pop()) {
37
+ try {
38
+ if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
39
+ if (r.dispose) {
40
+ var result = r.dispose.call(r.value);
41
+ if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
42
+ }
43
+ else s |= 1;
44
+ }
45
+ catch (e) {
46
+ fail(e);
47
+ }
48
+ }
49
+ if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
50
+ if (env.hasError) throw env.error;
51
+ }
52
+ return next();
53
+ };
54
+ })(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
55
+ var e = new Error(message);
56
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
57
+ });
58
+ export function replaceHtmlElementsWithUids(schema) {
59
+ if (typeof schema === 'boolean') {
60
+ return;
61
+ }
62
+ let isHtmlElement = false;
63
+ for (const [key, value] of Object.entries(schema)) {
64
+ if (key === 'x-mcp-type' && value === 'HTMLElement') {
65
+ isHtmlElement = true;
66
+ break;
67
+ }
68
+ }
69
+ if (isHtmlElement) {
70
+ schema.properties = { uid: { type: 'string' } };
71
+ schema.required = ['uid'];
72
+ }
73
+ if (schema.properties) {
74
+ for (const key of Object.keys(schema.properties)) {
75
+ replaceHtmlElementsWithUids(schema.properties[key]);
76
+ }
77
+ }
78
+ if (schema.items) {
79
+ if (Array.isArray(schema.items)) {
80
+ for (const item of schema.items) {
81
+ replaceHtmlElementsWithUids(item);
82
+ }
83
+ }
84
+ else {
85
+ replaceHtmlElementsWithUids(schema.items);
86
+ }
87
+ }
88
+ if (schema.anyOf) {
89
+ for (const s of schema.anyOf) {
90
+ replaceHtmlElementsWithUids(s);
91
+ }
92
+ }
93
+ if (schema.allOf) {
94
+ for (const s of schema.allOf) {
95
+ replaceHtmlElementsWithUids(s);
96
+ }
97
+ }
98
+ if (schema.oneOf) {
99
+ for (const s of schema.oneOf) {
100
+ replaceHtmlElementsWithUids(s);
101
+ }
102
+ }
103
+ }
104
+ import { createTargetUniverse, } from './devtools/DevtoolsUtils.js';
105
+ import { ConsoleCollector, NetworkCollector, } from './collectors/PageCollector.js';
7
106
  import { TextSnapshot } from './TextSnapshot.js';
107
+ import { PredefinedNetworkConditions, } from './third_party/index.js';
8
108
  import { takeSnapshot } from './tools/snapshot.js';
9
- import { getNetworkMultiplierFromString, WaitForHelper, } from './WaitForHelper.js';
109
+ const DEFAULT_TIMEOUT = 5_000;
110
+ const NAVIGATION_TIMEOUT = 10_000;
111
+ import { logger } from './utils/logger.js';
112
+ import { getNetworkMultiplierFromString, WaitForHelper, } from './utils/WaitForHelper.js';
10
113
  /**
11
114
  * Per-page state wrapper. Consolidates dialog, snapshot, emulation,
12
115
  * and metadata that were previously scattered across Maps in McpContext.
@@ -26,39 +129,224 @@ export class McpPage {
26
129
  emulationSettings = {};
27
130
  // Metadata
28
131
  isolatedContextName;
29
- devToolsPage;
132
+ #devtoolsUniverse;
30
133
  // Dialog
31
134
  #dialog;
32
135
  #dialogHandler;
33
- thirdPartyDeveloperTools;
34
- constructor(page, id) {
136
+ thirdPartyDeveloperTools = [];
137
+ networkCollector;
138
+ consoleCollector;
139
+ #hasNetworkBlockOrAllowlist;
140
+ #locatorClass;
141
+ #navigationTimeout;
142
+ constructor(page, id, options) {
143
+ this.#hasNetworkBlockOrAllowlist = options.hasNetworkBlockOrAllowlist;
144
+ this.#locatorClass = options.locatorClass;
145
+ this.#navigationTimeout = options.navigationTimeout ?? NAVIGATION_TIMEOUT;
35
146
  this.pptrPage = page;
36
147
  this.id = id;
148
+ this.isolatedContextName = options.isolatedContextName;
37
149
  this.#dialogHandler = (dialog) => {
38
150
  this.#dialog = dialog;
39
151
  };
40
152
  page.on('dialog', this.#dialogHandler);
153
+ this.networkCollector = new NetworkCollector(page);
154
+ this.consoleCollector = new ConsoleCollector(page, collect => {
155
+ return {
156
+ console: event => {
157
+ collect(event);
158
+ },
159
+ uncaughtError: event => {
160
+ collect(event);
161
+ },
162
+ devtoolsAggregatedIssue: event => {
163
+ collect(event);
164
+ },
165
+ };
166
+ });
41
167
  }
42
- get dialog() {
43
- return this.#dialog;
168
+ async init() {
169
+ await Promise.allSettled([
170
+ this.#initDevToolsUniverseNoThrow(),
171
+ this.#initFocusEmulationNoThrow(),
172
+ ]);
173
+ }
174
+ async #initFocusEmulationNoThrow() {
175
+ // We emulate a focused page for all pages to support multi-agent workflows.
176
+ void this.pptrPage.emulateFocusedPage(true).catch(error => {
177
+ logger?.('Error turning on focused page emulation', error);
178
+ });
179
+ }
180
+ async #initDevToolsUniverseNoThrow() {
181
+ if (this.#devtoolsUniverse) {
182
+ return undefined;
183
+ }
184
+ try {
185
+ const session = await this.pptrPage.createCDPSession();
186
+ this.#devtoolsUniverse = await createTargetUniverse(session);
187
+ }
188
+ catch (e) {
189
+ logger?.('Failed to initialize DevTools universe', e);
190
+ }
191
+ }
192
+ get devtoolsUniverse() {
193
+ return this.#devtoolsUniverse;
44
194
  }
45
195
  getDialog() {
46
- return this.dialog;
196
+ return this.#dialog;
47
197
  }
48
198
  clearDialog() {
49
199
  this.#dialog = undefined;
50
200
  }
51
201
  throwIfDialogOpen() {
52
- if (this.#dialog) {
202
+ if (this.#dialog && !this.#dialog.handled) {
53
203
  throw new Error(`A dialog is open (${this.#dialog.type()}: ${this.#dialog.message()}).`);
54
204
  }
55
205
  }
56
206
  getThirdPartyDeveloperTools() {
57
207
  return this.thirdPartyDeveloperTools;
58
208
  }
209
+ async getToolGroups() {
210
+ const env_1 = { stack: [], error: void 0, hasError: false };
211
+ try {
212
+ // Check if there is a `devtoolstooldiscovery` event listener
213
+ const windowHandle = __addDisposableResource(env_1, await this.pptrPage.evaluateHandle(() => window), false);
214
+ // @ts-expect-error internal API
215
+ const client = this.pptrPage._client();
216
+ const { listeners } = await client.send('DOMDebugger.getEventListeners', {
217
+ objectId: windowHandle.remoteObject().objectId,
218
+ });
219
+ if (listeners.find(l => l.type === 'devtoolstooldiscovery') === undefined) {
220
+ return [];
221
+ }
222
+ const toolGroups = await this.pptrPage.evaluate(() => {
223
+ if (window.__dtmcp) {
224
+ window.__dtmcp.toolGroups = [];
225
+ }
226
+ return new Promise(resolve => {
227
+ const event = new CustomEvent('devtoolstooldiscovery');
228
+ const groups = [];
229
+ // @ts-expect-error Adding custom property
230
+ event.respondWith = toolGroup => {
231
+ if (!window.__dtmcp) {
232
+ window.__dtmcp = {};
233
+ }
234
+ if (!window.__dtmcp.toolGroups) {
235
+ window.__dtmcp.toolGroups = [];
236
+ }
237
+ if (typeof toolGroup.name !== 'string' ||
238
+ (toolGroup.description &&
239
+ typeof toolGroup.description !== 'string') ||
240
+ !Array.isArray(toolGroup.tools)) {
241
+ console.error('Invalid toolGroup:', toolGroup);
242
+ return;
243
+ }
244
+ for (const tool of toolGroup.tools) {
245
+ if (typeof tool.name !== 'string' ||
246
+ typeof tool.description !== 'string' ||
247
+ typeof tool.inputSchema !== 'object' ||
248
+ typeof tool.execute !== 'function') {
249
+ console.error('Invalid tool:', tool);
250
+ return;
251
+ }
252
+ }
253
+ window.__dtmcp.toolGroups.push(toolGroup);
254
+ // When receiving a toolGroup for the first time, expose a simple execution helper
255
+ if (!window.__dtmcp.executeTool) {
256
+ window.__dtmcp.executeTool = async (toolName, args) => {
257
+ if (!window.__dtmcp?.toolGroups ||
258
+ window.__dtmcp.toolGroups.length === 0) {
259
+ throw new Error('No tools found on the page');
260
+ }
261
+ for (const group of window.__dtmcp.toolGroups) {
262
+ const tool = group.tools?.find(t => t.name === toolName);
263
+ if (tool) {
264
+ return await tool.execute(args);
265
+ }
266
+ }
267
+ throw new Error(`Tool ${toolName} not found`);
268
+ };
269
+ }
270
+ groups.push(toolGroup);
271
+ };
272
+ window.dispatchEvent(event);
273
+ // If at least one toolGroup was added synchronously, resolve with the array.
274
+ // Otherwise, use setTimeout to allow for any microtask/asynchronous respondWith calls, or resolve with an empty array.
275
+ if (groups.length > 0) {
276
+ resolve(groups);
277
+ }
278
+ else {
279
+ setTimeout(() => {
280
+ if (groups.length > 0) {
281
+ resolve(groups);
282
+ }
283
+ else {
284
+ resolve([]);
285
+ }
286
+ }, 0);
287
+ }
288
+ });
289
+ });
290
+ for (const group of toolGroups) {
291
+ for (const tool of group.tools ?? []) {
292
+ replaceHtmlElementsWithUids(tool.inputSchema);
293
+ }
294
+ }
295
+ this.thirdPartyDeveloperTools = toolGroups;
296
+ return toolGroups;
297
+ }
298
+ catch (e_1) {
299
+ env_1.error = e_1;
300
+ env_1.hasError = true;
301
+ }
302
+ finally {
303
+ __disposeResources(env_1);
304
+ }
305
+ }
59
306
  getWebMcpTools() {
60
307
  return this.pptrPage.webmcp.tools();
61
308
  }
309
+ resolveCdpRequestId(cdpRequestId) {
310
+ if (!cdpRequestId) {
311
+ logger?.('no network request');
312
+ return;
313
+ }
314
+ const request = this.networkCollector.find(request => {
315
+ // @ts-expect-error id is internal.
316
+ return request.id === cdpRequestId;
317
+ });
318
+ if (!request) {
319
+ logger?.('no network request for ' + cdpRequestId);
320
+ return;
321
+ }
322
+ return this.networkCollector.getIdForResource(request);
323
+ }
324
+ getNetworkRequests(includePreservedRequests) {
325
+ return this.networkCollector.getData(includePreservedRequests);
326
+ }
327
+ async getDevToolsPage() {
328
+ try {
329
+ if (await this.pptrPage.hasDevTools()) {
330
+ return await this.pptrPage.openDevTools();
331
+ }
332
+ return undefined;
333
+ }
334
+ catch {
335
+ // Prior to Chrome 144.0.7559.59, the command fails,
336
+ // Some Electron apps still use older version
337
+ // Fall back to not exposing DevTools at all.
338
+ return undefined;
339
+ }
340
+ }
341
+ getConsoleData(includePreservedMessages) {
342
+ return this.consoleCollector.getData(includePreservedMessages);
343
+ }
344
+ getConsoleMessageById(id) {
345
+ return this.consoleCollector.getById(id);
346
+ }
347
+ getNetworkRequestById(reqid) {
348
+ return this.networkCollector.getById(reqid);
349
+ }
62
350
  get networkConditions() {
63
351
  return this.emulationSettings.networkConditions ?? null;
64
352
  }
@@ -87,6 +375,14 @@ export class McpPage {
87
375
  }
88
376
  dispose() {
89
377
  this.pptrPage.off('dialog', this.#dialogHandler);
378
+ this.networkCollector.dispose();
379
+ this.consoleCollector.dispose();
380
+ const devtoolsUniverse = this.#devtoolsUniverse;
381
+ this.#devtoolsUniverse = undefined;
382
+ devtoolsUniverse?.universe.dispose();
383
+ void devtoolsUniverse?.session.detach().catch(e => {
384
+ logger?.('Failed to detach DevTools session', e);
385
+ });
90
386
  }
91
387
  async executeThirdPartyDeveloperTool(toolName, params, response) {
92
388
  // Creates array of ElementHandles from the UIDs in the params.
@@ -185,27 +481,40 @@ export class McpPage {
185
481
  }, i);
186
482
  elementHandles.push(elementHandle);
187
483
  }
484
+ await this.pptrPage.evaluate(() => {
485
+ if (window.__dtmcp) {
486
+ window.__dtmcp.stashedElements = undefined;
487
+ }
488
+ });
188
489
  if (elementHandles.length) {
189
- const oldHandles = [...this.extraHandles];
190
- this.textSnapshot = await TextSnapshot.create(this, {
191
- extraHandles: elementHandles,
192
- });
193
- response.includeSnapshot();
194
- for (const handle of oldHandles) {
195
- await handle
196
- .dispose()
197
- .catch(e => logger('Failed to dispose old handle', e));
490
+ const env_2 = { stack: [], error: void 0, hasError: false };
491
+ try {
492
+ const stack = __addDisposableResource(env_2, new DisposableStack(), false);
493
+ for (const handle of this.extraHandles) {
494
+ stack.use(handle);
495
+ }
496
+ this.textSnapshot = await TextSnapshot.create(this, {
497
+ extraHandles: elementHandles,
498
+ });
499
+ response.includeSnapshot();
500
+ }
501
+ catch (e_2) {
502
+ env_2.error = e_2;
503
+ env_2.hasError = true;
504
+ }
505
+ finally {
506
+ __disposeResources(env_2);
198
507
  }
199
508
  }
200
509
  const cdpElementIds = await Promise.all(elementHandles.map(async (elementHandle, index) => {
201
510
  const backendNodeId = await elementHandle.backendNodeId();
202
511
  if (!backendNodeId) {
203
- logger(`No backendNodeId for stashed DOM element with index ${index}`);
512
+ logger?.(`No backendNodeId for stashed DOM element with index ${index}`);
204
513
  return `stashed-${index}`;
205
514
  }
206
- const cdpElementId = this.resolveCdpElementId(backendNodeId);
515
+ const cdpElementId = this.textSnapshot?.resolveCdpElementId(backendNodeId);
207
516
  if (!cdpElementId) {
208
- logger(`Could not get cdpElementId for backend node ${backendNodeId}`);
517
+ logger?.(`Could not get cdpElementId for backend node ${backendNodeId}`);
209
518
  return `stashed-${index}`;
210
519
  }
211
520
  return cdpElementId;
@@ -261,35 +570,12 @@ export class McpPage {
261
570
  getAXNodeByUid(uid) {
262
571
  return this.textSnapshot?.idToNode.get(uid);
263
572
  }
264
- resolveCdpElementId(cdpBackendNodeId) {
265
- if (!cdpBackendNodeId) {
266
- logger('no cdpBackendNodeId');
267
- return;
268
- }
269
- const snapshot = this.textSnapshot;
270
- if (!snapshot) {
271
- logger('no text snapshot');
272
- return;
273
- }
274
- // TODO: index by backendNodeId instead.
275
- const queue = [snapshot.root];
276
- while (queue.length) {
277
- const current = queue.pop();
278
- if (current.backendNodeId === cdpBackendNodeId) {
279
- return current.id;
280
- }
281
- for (const child of current.children) {
282
- queue.push(child);
283
- }
284
- }
285
- return;
286
- }
287
573
  async getDevToolsData() {
288
574
  try {
289
- logger('Getting DevTools UI data');
290
- const devtoolsPage = this.devToolsPage;
575
+ logger?.('Getting DevTools UI data');
576
+ const devtoolsPage = await this.getDevToolsPage();
291
577
  if (!devtoolsPage) {
292
- logger('No DevTools page detected');
578
+ logger?.('No DevTools page detected');
293
579
  return {};
294
580
  }
295
581
  const { cdpRequestId, cdpBackendNodeId } = await devtoolsPage.evaluate(async () => {
@@ -307,9 +593,150 @@ export class McpPage {
307
593
  return { cdpBackendNodeId, cdpRequestId };
308
594
  }
309
595
  catch (err) {
310
- logger('error getting devtools data', err);
596
+ logger?.('error getting devtools data', err);
311
597
  }
312
598
  return {};
313
599
  }
600
+ async restoreEmulation() {
601
+ const currentSetting = this.emulationSettings;
602
+ await this.emulate(currentSetting);
603
+ }
604
+ async emulate(options) {
605
+ const page = this.pptrPage;
606
+ const newSettings = { ...this.emulationSettings };
607
+ // Skip network emulation if blocklist/allowlist is configured, as it conflicts with blocking rules in Puppeteer.
608
+ if (this.#hasNetworkBlockOrAllowlist) {
609
+ if (options.networkConditions !== undefined) {
610
+ throw new Error('Network throttling is not supported when network blocking (allowlist/blocklist) is configured.');
611
+ }
612
+ }
613
+ else if (!options.networkConditions) {
614
+ await page.emulateNetworkConditions(null);
615
+ delete newSettings.networkConditions;
616
+ }
617
+ else if (options.networkConditions === 'Offline') {
618
+ await page.emulateNetworkConditions({
619
+ offline: true,
620
+ download: 0,
621
+ upload: 0,
622
+ latency: 0,
623
+ });
624
+ newSettings.networkConditions = 'Offline';
625
+ }
626
+ else if (options.networkConditions in PredefinedNetworkConditions) {
627
+ const networkCondition = PredefinedNetworkConditions[options.networkConditions];
628
+ await page.emulateNetworkConditions(networkCondition);
629
+ newSettings.networkConditions = options.networkConditions;
630
+ }
631
+ const secondarySession = this.devtoolsUniverse?.session;
632
+ if (!options.cpuThrottlingRate) {
633
+ await page.emulateCPUThrottling(1);
634
+ if (secondarySession) {
635
+ await secondarySession.send('Emulation.setCPUThrottlingRate', {
636
+ rate: 1,
637
+ });
638
+ }
639
+ delete newSettings.cpuThrottlingRate;
640
+ }
641
+ else {
642
+ await page.emulateCPUThrottling(options.cpuThrottlingRate);
643
+ if (secondarySession) {
644
+ await secondarySession.send('Emulation.setCPUThrottlingRate', {
645
+ rate: options.cpuThrottlingRate,
646
+ });
647
+ }
648
+ newSettings.cpuThrottlingRate = options.cpuThrottlingRate;
649
+ }
650
+ if (!options.geolocation) {
651
+ await page.setGeolocation({ latitude: 0, longitude: 0 });
652
+ delete newSettings.geolocation;
653
+ }
654
+ else {
655
+ await page.setGeolocation(options.geolocation);
656
+ newSettings.geolocation = options.geolocation;
657
+ }
658
+ if (!options.userAgent) {
659
+ await page.setUserAgent({ userAgent: undefined });
660
+ delete newSettings.userAgent;
661
+ }
662
+ else {
663
+ await page.setUserAgent({ userAgent: options.userAgent });
664
+ newSettings.userAgent = options.userAgent;
665
+ }
666
+ if (!options.colorScheme || options.colorScheme === 'auto') {
667
+ await page.emulateMediaFeatures([
668
+ { name: 'prefers-color-scheme', value: '' },
669
+ ]);
670
+ delete newSettings.colorScheme;
671
+ }
672
+ else {
673
+ await page.emulateMediaFeatures([
674
+ { name: 'prefers-color-scheme', value: options.colorScheme },
675
+ ]);
676
+ newSettings.colorScheme = options.colorScheme;
677
+ }
678
+ if (!options.viewport) {
679
+ delete newSettings.viewport;
680
+ }
681
+ else {
682
+ const defaults = {
683
+ deviceScaleFactor: 1,
684
+ isMobile: false,
685
+ hasTouch: false,
686
+ isLandscape: false,
687
+ };
688
+ newSettings.viewport = { ...defaults, ...options.viewport };
689
+ }
690
+ if (options.extraHttpHeaders !== undefined) {
691
+ await page.setExtraHTTPHeaders(options.extraHttpHeaders);
692
+ newSettings.extraHttpHeaders = options.extraHttpHeaders;
693
+ if (Object.keys(options.extraHttpHeaders).length === 0) {
694
+ delete newSettings.extraHttpHeaders;
695
+ }
696
+ }
697
+ this.emulationSettings = Object.keys(newSettings).length ? newSettings : {};
698
+ this.updateTimeouts();
699
+ // This should happen after updating the page timeouts.
700
+ // Setting the viewport can trigger a reload which we don't want to timeout.
701
+ await page.setViewport(newSettings.viewport ?? null);
702
+ }
703
+ updateTimeouts() {
704
+ // For waiters 5sec timeout should be sufficient.
705
+ // Increased in case we throttle the CPU
706
+ const cpuMultiplier = this.cpuThrottlingRate;
707
+ this.pptrPage.setDefaultTimeout(DEFAULT_TIMEOUT * cpuMultiplier);
708
+ // 10sec should be enough for the load event to be emitted during
709
+ // navigations.
710
+ // Increased in case we throttle the network requests or the CPU
711
+ const networkMultiplier = getNetworkMultiplierFromString(this.networkConditions);
712
+ this.pptrPage.setDefaultNavigationTimeout(this.#navigationTimeout * networkMultiplier * cpuMultiplier);
713
+ }
714
+ waitForTextOnPage(text, timeout) {
715
+ const frames = this.pptrPage.frames();
716
+ let locator = this.#locatorClass.race(frames.flatMap(frame => text.flatMap(value => [
717
+ frame.locator(`aria/${value}`),
718
+ frame.locator(`text/${value}`),
719
+ ])));
720
+ if (timeout) {
721
+ locator = locator.setTimeout(timeout);
722
+ }
723
+ return locator.wait();
724
+ }
725
+ /**
726
+ * We need to ignore favicon request as they make our test flaky
727
+ */
728
+ async setUpNetworkCollectorForTesting() {
729
+ this.networkCollector.dispose();
730
+ this.networkCollector = new NetworkCollector(this.pptrPage, undefined, collect => {
731
+ return {
732
+ request: req => {
733
+ if (req.url().includes('favicon.ico')) {
734
+ return;
735
+ }
736
+ collect(req);
737
+ },
738
+ };
739
+ });
740
+ }
314
741
  }
315
742
  //# sourceMappingURL=McpPage.js.map