@vibebrowser/chrome-devtools-mcp 0.26.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 (294) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +873 -0
  3. package/build/src/DevToolsConnectionAdapter.js +70 -0
  4. package/build/src/DevtoolsUtils.js +295 -0
  5. package/build/src/HeapSnapshotManager.js +110 -0
  6. package/build/src/McpContext.js +605 -0
  7. package/build/src/McpPage.js +315 -0
  8. package/build/src/McpResponse.js +858 -0
  9. package/build/src/Mutex.js +38 -0
  10. package/build/src/PageCollector.js +297 -0
  11. package/build/src/SlimMcpResponse.js +19 -0
  12. package/build/src/TextSnapshot.js +236 -0
  13. package/build/src/ToolHandler.js +217 -0
  14. package/build/src/WaitForHelper.js +190 -0
  15. package/build/src/bin/check-latest-version.js +50 -0
  16. package/build/src/bin/chrome-devtools-cli-options.js +840 -0
  17. package/build/src/bin/chrome-devtools-mcp-cli-options.js +350 -0
  18. package/build/src/bin/chrome-devtools-mcp-main.js +94 -0
  19. package/build/src/bin/chrome-devtools-mcp.js +31 -0
  20. package/build/src/bin/chrome-devtools.js +189 -0
  21. package/build/src/bin/install-service.js +246 -0
  22. package/build/src/bin/service/chrome-devtools-mcp.service.template +17 -0
  23. package/build/src/bin/service/com.vibebrowser.chrome-devtools-mcp.plist.template +37 -0
  24. package/build/src/browser.js +204 -0
  25. package/build/src/daemon/client.js +154 -0
  26. package/build/src/daemon/daemon.js +204 -0
  27. package/build/src/daemon/types.js +7 -0
  28. package/build/src/daemon/utils.js +115 -0
  29. package/build/src/formatters/ConsoleFormatter.js +288 -0
  30. package/build/src/formatters/HeapSnapshotFormatter.js +54 -0
  31. package/build/src/formatters/IssueFormatter.js +193 -0
  32. package/build/src/formatters/NetworkFormatter.js +236 -0
  33. package/build/src/formatters/SnapshotFormatter.js +135 -0
  34. package/build/src/index.js +140 -0
  35. package/build/src/issue-descriptions.js +40 -0
  36. package/build/src/logger.js +37 -0
  37. package/build/src/polyfill.js +8 -0
  38. package/build/src/telemetry/ClearcutLogger.js +169 -0
  39. package/build/src/telemetry/WatchdogClient.js +61 -0
  40. package/build/src/telemetry/errors.js +18 -0
  41. package/build/src/telemetry/flagUtils.js +89 -0
  42. package/build/src/telemetry/metricsRegistry.js +89 -0
  43. package/build/src/telemetry/persistence.js +72 -0
  44. package/build/src/telemetry/transformation.js +134 -0
  45. package/build/src/telemetry/types.js +31 -0
  46. package/build/src/telemetry/watchdog/ClearcutSender.js +205 -0
  47. package/build/src/telemetry/watchdog/main.js +128 -0
  48. package/build/src/third_party/devtools-formatter-worker.js +8 -0
  49. package/build/src/third_party/devtools-heap-snapshot-worker.js +8 -0
  50. package/build/src/third_party/index.js +32 -0
  51. package/build/src/third_party/issue-descriptions/CoepCoopSandboxedIframeCannotNavigateToCoopPage.md +4 -0
  52. package/build/src/third_party/issue-descriptions/CoepCorpNotSameOrigin.md +8 -0
  53. package/build/src/third_party/issue-descriptions/CoepCorpNotSameOriginAfterDefaultedToSameOriginByCoep.md +18 -0
  54. package/build/src/third_party/issue-descriptions/CoepCorpNotSameSite.md +7 -0
  55. package/build/src/third_party/issue-descriptions/CoepFrameResourceNeedsCoepHeader.md +10 -0
  56. package/build/src/third_party/issue-descriptions/CompatibilityModeQuirks.md +5 -0
  57. package/build/src/third_party/issue-descriptions/CookieAttributeValueExceedsMaxSize.md +5 -0
  58. package/build/src/third_party/issue-descriptions/LowTextContrast.md +5 -0
  59. package/build/src/third_party/issue-descriptions/SameSiteExcludeContextDowngradeRead.md +8 -0
  60. package/build/src/third_party/issue-descriptions/SameSiteExcludeContextDowngradeSet.md +8 -0
  61. package/build/src/third_party/issue-descriptions/SameSiteExcludeNavigationContextDowngrade.md +8 -0
  62. package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureErrorRead.md +8 -0
  63. package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureErrorSet.md +8 -0
  64. package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureWarnRead.md +8 -0
  65. package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureWarnSet.md +8 -0
  66. package/build/src/third_party/issue-descriptions/SameSiteUnspecifiedLaxAllowUnsafeRead.md +9 -0
  67. package/build/src/third_party/issue-descriptions/SameSiteUnspecifiedLaxAllowUnsafeSet.md +9 -0
  68. package/build/src/third_party/issue-descriptions/SameSiteWarnCrossDowngradeRead.md +8 -0
  69. package/build/src/third_party/issue-descriptions/SameSiteWarnCrossDowngradeSet.md +8 -0
  70. package/build/src/third_party/issue-descriptions/SameSiteWarnStrictLaxDowngradeStrict.md +8 -0
  71. package/build/src/third_party/issue-descriptions/arInsecureContext.md +7 -0
  72. package/build/src/third_party/issue-descriptions/arInvalidInfoHeader.md +5 -0
  73. package/build/src/third_party/issue-descriptions/arInvalidRegisterOsSourceHeader.md +5 -0
  74. package/build/src/third_party/issue-descriptions/arInvalidRegisterOsTriggerHeader.md +5 -0
  75. package/build/src/third_party/issue-descriptions/arInvalidRegisterSourceHeader.md +5 -0
  76. package/build/src/third_party/issue-descriptions/arInvalidRegisterTriggerHeader.md +5 -0
  77. package/build/src/third_party/issue-descriptions/arNavigationRegistrationUniqueScopeAlreadySet.md +5 -0
  78. package/build/src/third_party/issue-descriptions/arNavigationRegistrationWithoutTransientUserActivation.md +6 -0
  79. package/build/src/third_party/issue-descriptions/arNoRegisterOsSourceHeader.md +5 -0
  80. package/build/src/third_party/issue-descriptions/arNoRegisterOsTriggerHeader.md +5 -0
  81. package/build/src/third_party/issue-descriptions/arNoRegisterSourceHeader.md +5 -0
  82. package/build/src/third_party/issue-descriptions/arNoRegisterTriggerHeader.md +5 -0
  83. package/build/src/third_party/issue-descriptions/arNoWebOrOsSupport.md +4 -0
  84. package/build/src/third_party/issue-descriptions/arOsSourceIgnored.md +18 -0
  85. package/build/src/third_party/issue-descriptions/arOsTriggerIgnored.md +19 -0
  86. package/build/src/third_party/issue-descriptions/arPermissionPolicyDisabled.md +8 -0
  87. package/build/src/third_party/issue-descriptions/arSourceAndTriggerHeaders.md +9 -0
  88. package/build/src/third_party/issue-descriptions/arSourceIgnored.md +13 -0
  89. package/build/src/third_party/issue-descriptions/arTriggerIgnored.md +12 -0
  90. package/build/src/third_party/issue-descriptions/arUntrustworthyReportingOrigin.md +10 -0
  91. package/build/src/third_party/issue-descriptions/arWebAndOsHeaders.md +11 -0
  92. package/build/src/third_party/issue-descriptions/bounceTrackingMitigations.md +3 -0
  93. package/build/src/third_party/issue-descriptions/clientHintMetaTagAllowListInvalidOrigin.md +4 -0
  94. package/build/src/third_party/issue-descriptions/clientHintMetaTagModifiedHTML.md +4 -0
  95. package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidAllowlistItemType.md +12 -0
  96. package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidHeader.md +12 -0
  97. package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidUrlPattern.md +8 -0
  98. package/build/src/third_party/issue-descriptions/connectionAllowlistItemNotInnerList.md +12 -0
  99. package/build/src/third_party/issue-descriptions/connectionAllowlistMoreThanOneList.md +7 -0
  100. package/build/src/third_party/issue-descriptions/connectionAllowlistReportingEndpointNotToken.md +10 -0
  101. package/build/src/third_party/issue-descriptions/cookieCrossSiteRedirectDowngrade.md +12 -0
  102. package/build/src/third_party/issue-descriptions/cookieExcludeBlockedWithinRelatedWebsiteSet.md +4 -0
  103. package/build/src/third_party/issue-descriptions/cookieExcludeDomainNonAscii.md +11 -0
  104. package/build/src/third_party/issue-descriptions/cookieExcludePortMismatch.md +8 -0
  105. package/build/src/third_party/issue-descriptions/cookieExcludeSchemeMismatch.md +7 -0
  106. package/build/src/third_party/issue-descriptions/cookieExcludeThirdPartyPhaseoutRead.md +6 -0
  107. package/build/src/third_party/issue-descriptions/cookieExcludeThirdPartyPhaseoutSet.md +6 -0
  108. package/build/src/third_party/issue-descriptions/cookieWarnDomainNonAscii.md +11 -0
  109. package/build/src/third_party/issue-descriptions/cookieWarnMetadataGrantRead.md +4 -0
  110. package/build/src/third_party/issue-descriptions/cookieWarnMetadataGrantSet.md +4 -0
  111. package/build/src/third_party/issue-descriptions/cookieWarnThirdPartyPhaseoutRead.md +6 -0
  112. package/build/src/third_party/issue-descriptions/cookieWarnThirdPartyPhaseoutSet.md +6 -0
  113. package/build/src/third_party/issue-descriptions/corsAllowCredentialsRequired.md +6 -0
  114. package/build/src/third_party/issue-descriptions/corsDisabledScheme.md +7 -0
  115. package/build/src/third_party/issue-descriptions/corsDisallowedByMode.md +7 -0
  116. package/build/src/third_party/issue-descriptions/corsHeaderDisallowedByPreflightResponse.md +5 -0
  117. package/build/src/third_party/issue-descriptions/corsInvalidHeaderValues.md +7 -0
  118. package/build/src/third_party/issue-descriptions/corsLocalNetworkAccessPermissionDenied.md +19 -0
  119. package/build/src/third_party/issue-descriptions/corsMethodDisallowedByPreflightResponse.md +5 -0
  120. package/build/src/third_party/issue-descriptions/corsNoCorsRedirectModeNotFollow.md +5 -0
  121. package/build/src/third_party/issue-descriptions/corsOriginMismatch.md +6 -0
  122. package/build/src/third_party/issue-descriptions/corsPreflightResponseInvalid.md +5 -0
  123. package/build/src/third_party/issue-descriptions/corsRedirectContainsCredentials.md +5 -0
  124. package/build/src/third_party/issue-descriptions/corsWildcardOriginNotAllowed.md +8 -0
  125. package/build/src/third_party/issue-descriptions/cspEvalViolation.md +9 -0
  126. package/build/src/third_party/issue-descriptions/cspInlineViolation.md +10 -0
  127. package/build/src/third_party/issue-descriptions/cspTrustedTypesPolicyViolation.md +5 -0
  128. package/build/src/third_party/issue-descriptions/cspTrustedTypesSinkViolation.md +8 -0
  129. package/build/src/third_party/issue-descriptions/cspURLViolation.md +10 -0
  130. package/build/src/third_party/issue-descriptions/deprecation.md +3 -0
  131. package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsHttpNotFound.md +1 -0
  132. package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsInvalidResponse.md +1 -0
  133. package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsNoResponse.md +1 -0
  134. package/build/src/third_party/issue-descriptions/federatedAuthRequestApprovalDeclined.md +1 -0
  135. package/build/src/third_party/issue-descriptions/federatedAuthRequestCanceled.md +1 -0
  136. package/build/src/third_party/issue-descriptions/federatedAuthRequestErrorFetchingSignin.md +1 -0
  137. package/build/src/third_party/issue-descriptions/federatedAuthRequestErrorIdToken.md +1 -0
  138. package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenHttpNotFound.md +1 -0
  139. package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenInvalidRequest.md +1 -0
  140. package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenInvalidResponse.md +1 -0
  141. package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenNoResponse.md +1 -0
  142. package/build/src/third_party/issue-descriptions/federatedAuthRequestInvalidSigninResponse.md +1 -0
  143. package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestHttpNotFound.md +1 -0
  144. package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestInvalidResponse.md +1 -0
  145. package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestNoResponse.md +1 -0
  146. package/build/src/third_party/issue-descriptions/federatedAuthRequestTooManyRequests.md +1 -0
  147. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestInvalidAccountsResponse.md +1 -0
  148. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestInvalidConfigOrWellKnown.md +1 -0
  149. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoAccountSharingPermission.md +1 -0
  150. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoApiPermission.md +1 -0
  151. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoReturningUserFromFetchedAccounts.md +1 -0
  152. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotIframe.md +1 -0
  153. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotPotentiallyTrustworthy.md +1 -0
  154. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotSameOrigin.md +1 -0
  155. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotSignedInWithIdp.md +1 -0
  156. package/build/src/third_party/issue-descriptions/fetchingPartitionedBlobURL.md +7 -0
  157. package/build/src/third_party/issue-descriptions/genericFormAriaLabelledByToNonExistingIdError.md +8 -0
  158. package/build/src/third_party/issue-descriptions/genericFormAutocompleteAttributeEmptyError.md +5 -0
  159. package/build/src/third_party/issue-descriptions/genericFormDuplicateIdForInputError.md +5 -0
  160. package/build/src/third_party/issue-descriptions/genericFormEmptyIdAndNameAttributesForInputError.md +5 -0
  161. package/build/src/third_party/issue-descriptions/genericFormInputAssignedAutocompleteValueToIdOrNameAttributeError.md +5 -0
  162. package/build/src/third_party/issue-descriptions/genericFormInputHasWrongButWellIntendedAutocompleteValueError.md +5 -0
  163. package/build/src/third_party/issue-descriptions/genericFormInputWithNoLabelError.md +5 -0
  164. package/build/src/third_party/issue-descriptions/genericFormLabelForMatchesNonExistingIdError.md +5 -0
  165. package/build/src/third_party/issue-descriptions/genericFormLabelForNameError.md +5 -0
  166. package/build/src/third_party/issue-descriptions/genericFormLabelHasNeitherForNorNestedInputError.md +5 -0
  167. package/build/src/third_party/issue-descriptions/genericFormModelContextMissingToolDescription.md +5 -0
  168. package/build/src/third_party/issue-descriptions/genericFormModelContextMissingToolName.md +5 -0
  169. package/build/src/third_party/issue-descriptions/genericFormModelContextParameterMissingName.md +5 -0
  170. package/build/src/third_party/issue-descriptions/genericFormModelContextParameterMissingTitleAndDescription.md +5 -0
  171. package/build/src/third_party/issue-descriptions/genericFormModelContextRequiredParameterMissingName.md +5 -0
  172. package/build/src/third_party/issue-descriptions/genericNavigationEntryMarkedSkippable.md +7 -0
  173. package/build/src/third_party/issue-descriptions/genericResponseWasBlockedByORB.md +4 -0
  174. package/build/src/third_party/issue-descriptions/heavyAd.md +10 -0
  175. package/build/src/third_party/issue-descriptions/mixedContent.md +5 -0
  176. package/build/src/third_party/issue-descriptions/navigatingPartitionedBlobURL.md +5 -0
  177. package/build/src/third_party/issue-descriptions/permissionElementActivationDisabled.md +7 -0
  178. package/build/src/third_party/issue-descriptions/permissionElementActivationDisabledWithOccluder.md +9 -0
  179. package/build/src/third_party/issue-descriptions/permissionElementActivationDisabledWithOccluderParent.md +9 -0
  180. package/build/src/third_party/issue-descriptions/permissionElementCspFrameAncestorsMissing.md +5 -0
  181. package/build/src/third_party/issue-descriptions/permissionElementFencedFrameDisallowed.md +5 -0
  182. package/build/src/third_party/issue-descriptions/permissionElementFontSizeTooLarge.md +5 -0
  183. package/build/src/third_party/issue-descriptions/permissionElementFontSizeTooSmall.md +5 -0
  184. package/build/src/third_party/issue-descriptions/permissionElementGeolocationDeprecated.md +5 -0
  185. package/build/src/third_party/issue-descriptions/permissionElementInsetBoxShadowUnsupported.md +5 -0
  186. package/build/src/third_party/issue-descriptions/permissionElementInvalidDisplayStyle.md +5 -0
  187. package/build/src/third_party/issue-descriptions/permissionElementInvalidSizeValue.md +5 -0
  188. package/build/src/third_party/issue-descriptions/permissionElementInvalidType.md +5 -0
  189. package/build/src/third_party/issue-descriptions/permissionElementInvalidTypeActivation.md +5 -0
  190. package/build/src/third_party/issue-descriptions/permissionElementLowContrast.md +5 -0
  191. package/build/src/third_party/issue-descriptions/permissionElementNonOpaqueColor.md +5 -0
  192. package/build/src/third_party/issue-descriptions/permissionElementPaddingBottomUnsupported.md +6 -0
  193. package/build/src/third_party/issue-descriptions/permissionElementPaddingRightUnsupported.md +6 -0
  194. package/build/src/third_party/issue-descriptions/permissionElementPermissionsPolicyBlocked.md +5 -0
  195. package/build/src/third_party/issue-descriptions/permissionElementRegistrationFailed.md +5 -0
  196. package/build/src/third_party/issue-descriptions/permissionElementRequestInProgress.md +5 -0
  197. package/build/src/third_party/issue-descriptions/permissionElementSecurityChecksFailed.md +5 -0
  198. package/build/src/third_party/issue-descriptions/permissionElementTypeNotSupported.md +5 -0
  199. package/build/src/third_party/issue-descriptions/permissionElementUntrustedEvent.md +7 -0
  200. package/build/src/third_party/issue-descriptions/placeholderDescriptionForInvisibleIssues.md +3 -0
  201. package/build/src/third_party/issue-descriptions/propertyRuleInvalidNameIssue.md +3 -0
  202. package/build/src/third_party/issue-descriptions/propertyRuleIssue.md +7 -0
  203. package/build/src/third_party/issue-descriptions/selectElementAccessibilityDisallowedOptGroupChild.md +7 -0
  204. package/build/src/third_party/issue-descriptions/selectElementAccessibilityDisallowedSelectChild.md +7 -0
  205. package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentAttributesSelectDescendant.md +3 -0
  206. package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentLegendChild.md +3 -0
  207. package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentOptionChild.md +3 -0
  208. package/build/src/third_party/issue-descriptions/selectElementAccessibilityNonPhrasingContentOptionChild.md +3 -0
  209. package/build/src/third_party/issue-descriptions/selectivePermissionsIntervention.md +7 -0
  210. package/build/src/third_party/issue-descriptions/sharedArrayBuffer.md +7 -0
  211. package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorCrossOriginNoCorsRequest.md +1 -0
  212. package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorDictionaryLoadFailure.md +3 -0
  213. package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorMatchingDictionaryNotUsed.md +3 -0
  214. package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorUnexpectedContentDictionaryHeader.md +1 -0
  215. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorCossOriginNoCorsRequest.md +1 -0
  216. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorDisallowedBySettings.md +1 -0
  217. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorExpiredResponse.md +3 -0
  218. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorFeatureDisabled.md +3 -0
  219. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorInsufficientResources.md +1 -0
  220. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorInvalidMatchField.md +1 -0
  221. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorInvalidStructuredHeader.md +1 -0
  222. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorInvalidTTLField.md +1 -0
  223. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNavigationRequest.md +3 -0
  224. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNoMatchField.md +1 -0
  225. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonIntegerTTLField.md +1 -0
  226. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonListMatchDestField.md +1 -0
  227. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonSecureContext.md +3 -0
  228. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonStringIdField.md +1 -0
  229. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonStringInMatchDestList.md +1 -0
  230. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonStringMatchField.md +1 -0
  231. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonTokenTypeField.md +1 -0
  232. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorRequestAborted.md +1 -0
  233. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorShuttingDown.md +1 -0
  234. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorTooLongIdField.md +3 -0
  235. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorUnsupportedType.md +3 -0
  236. package/build/src/third_party/issue-descriptions/sriInvalidSignatureHeader.md +14 -0
  237. package/build/src/third_party/issue-descriptions/sriInvalidSignatureInputHeader.md +15 -0
  238. package/build/src/third_party/issue-descriptions/sriMissingSignatureHeader.md +8 -0
  239. package/build/src/third_party/issue-descriptions/sriMissingSignatureInputHeader.md +7 -0
  240. package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsIncorrectLength.md +11 -0
  241. package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsNotByteSequence.md +14 -0
  242. package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsParameterized.md +15 -0
  243. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidComponentName.md +8 -0
  244. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidComponentType.md +13 -0
  245. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidDerivedComponentParameter.md +4 -0
  246. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidHeaderComponentParameter.md +5 -0
  247. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidParameter.md +11 -0
  248. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderKeyIdLength.md +12 -0
  249. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderMissingLabel.md +6 -0
  250. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderMissingRequiredParameters.md +8 -0
  251. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderValueMissingComponents.md +11 -0
  252. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderValueNotInnerList.md +11 -0
  253. package/build/src/third_party/issue-descriptions/sriValidationFailedIntegrityMismatch.md +10 -0
  254. package/build/src/third_party/issue-descriptions/sriValidationFailedInvalidLength.md +5 -0
  255. package/build/src/third_party/issue-descriptions/sriValidationFailedSignatureExpired.md +6 -0
  256. package/build/src/third_party/issue-descriptions/sriValidationFailedSignatureMismatch.md +11 -0
  257. package/build/src/third_party/issue-descriptions/stylesheetLateImport.md +4 -0
  258. package/build/src/third_party/issue-descriptions/stylesheetRequestFailed.md +3 -0
  259. package/build/src/third_party/issue-descriptions/summaryElementAccessibilityInteractiveContentSummaryDescendant.md +3 -0
  260. package/build/src/third_party/issue-descriptions/unencodedDigestIncorrectDigestLength.md +12 -0
  261. package/build/src/third_party/issue-descriptions/unencodedDigestIncorrectDigestType.md +17 -0
  262. package/build/src/third_party/issue-descriptions/unencodedDigestMalformedDictionary.md +14 -0
  263. package/build/src/third_party/issue-descriptions/unencodedDigestUnknownAlgorithm.md +15 -0
  264. package/build/src/third_party/lighthouse-devtools-mcp-bundle.js +61598 -0
  265. package/build/src/tools/ToolDefinition.js +73 -0
  266. package/build/src/tools/categories.js +36 -0
  267. package/build/src/tools/console.js +91 -0
  268. package/build/src/tools/emulation.js +57 -0
  269. package/build/src/tools/extensions.js +96 -0
  270. package/build/src/tools/input.js +461 -0
  271. package/build/src/tools/lighthouse.js +131 -0
  272. package/build/src/tools/memory.js +106 -0
  273. package/build/src/tools/network.js +125 -0
  274. package/build/src/tools/pages.js +411 -0
  275. package/build/src/tools/performance.js +196 -0
  276. package/build/src/tools/screencast.js +95 -0
  277. package/build/src/tools/screenshot.js +87 -0
  278. package/build/src/tools/script.js +151 -0
  279. package/build/src/tools/slim/tools.js +85 -0
  280. package/build/src/tools/snapshot.js +60 -0
  281. package/build/src/tools/thirdPartyDeveloper.js +75 -0
  282. package/build/src/tools/tools.js +56 -0
  283. package/build/src/tools/webmcp.js +64 -0
  284. package/build/src/trace-processing/parse.js +85 -0
  285. package/build/src/types.js +7 -0
  286. package/build/src/utils/check-for-updates.js +74 -0
  287. package/build/src/utils/files.js +18 -0
  288. package/build/src/utils/id.js +16 -0
  289. package/build/src/utils/keyboard.js +297 -0
  290. package/build/src/utils/pagination.js +50 -0
  291. package/build/src/utils/string.js +37 -0
  292. package/build/src/utils/types.js +7 -0
  293. package/build/src/version.js +10 -0
  294. package/package.json +93 -0
@@ -0,0 +1,605 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import fs from 'node:fs/promises';
7
+ import os from 'node:os';
8
+ import path from 'node:path';
9
+ import { fileURLToPath, pathToFileURL } from 'node:url';
10
+ import { UniverseManager } from './DevtoolsUtils.js';
11
+ import { HeapSnapshotManager } from './HeapSnapshotManager.js';
12
+ import { McpPage } from './McpPage.js';
13
+ import { NetworkCollector, ConsoleCollector, } from './PageCollector.js';
14
+ import { Locator, PredefinedNetworkConditions, } from './third_party/index.js';
15
+ import { listPages } from './tools/pages.js';
16
+ import { CLOSE_PAGE_ERROR } from './tools/ToolDefinition.js';
17
+ import { ensureExtension, getTempFilePath } from './utils/files.js';
18
+ import { getNetworkMultiplierFromString } from './WaitForHelper.js';
19
+ const DEFAULT_TIMEOUT = 5_000;
20
+ const NAVIGATION_TIMEOUT = 10_000;
21
+ export class McpContext {
22
+ browser;
23
+ logger;
24
+ // Maps LLM-provided isolatedContext name → Puppeteer BrowserContext.
25
+ #isolatedContexts = new Map();
26
+ // Auto-generated name counter for when no name is provided.
27
+ #nextIsolatedContextId = 1;
28
+ #pages = [];
29
+ #extensionServiceWorkers = [];
30
+ #mcpPages = new Map();
31
+ #selectedPage;
32
+ #networkCollector;
33
+ #consoleCollector;
34
+ #devtoolsUniverseManager;
35
+ #isRunningTrace = false;
36
+ #screenRecorderData = null;
37
+ #nextPageId = 1;
38
+ #extensionPages = new WeakMap();
39
+ #extensionServiceWorkerMap = new WeakMap();
40
+ #nextExtensionServiceWorkerId = 1;
41
+ #traceResults = [];
42
+ #locatorClass;
43
+ #options;
44
+ #heapSnapshotManager = new HeapSnapshotManager();
45
+ #roots = undefined;
46
+ constructor(browser, logger, options, locatorClass) {
47
+ this.browser = browser;
48
+ this.logger = logger;
49
+ this.#locatorClass = locatorClass;
50
+ this.#options = options;
51
+ this.#networkCollector = new NetworkCollector(this.browser);
52
+ this.#consoleCollector = new ConsoleCollector(this.browser, collect => {
53
+ return {
54
+ console: event => {
55
+ collect(event);
56
+ },
57
+ uncaughtError: event => {
58
+ collect(event);
59
+ },
60
+ devtoolsAggregatedIssue: event => {
61
+ collect(event);
62
+ },
63
+ };
64
+ });
65
+ this.#devtoolsUniverseManager = new UniverseManager(this.browser);
66
+ }
67
+ async #init() {
68
+ const pages = await this.createPagesSnapshot();
69
+ await this.createExtensionServiceWorkersSnapshot();
70
+ await this.#networkCollector.init(pages);
71
+ await this.#consoleCollector.init(pages);
72
+ await this.#devtoolsUniverseManager.init(pages);
73
+ }
74
+ dispose() {
75
+ this.#networkCollector.dispose();
76
+ this.#consoleCollector.dispose();
77
+ this.#devtoolsUniverseManager.dispose();
78
+ for (const mcpPage of this.#mcpPages.values()) {
79
+ mcpPage.dispose();
80
+ }
81
+ this.#mcpPages.clear();
82
+ // Isolated contexts are intentionally not closed here.
83
+ // Either the entire browser will be closed or we disconnect
84
+ // without destroying browser state.
85
+ this.#isolatedContexts.clear();
86
+ }
87
+ static async from(browser, logger, opts,
88
+ /* Let tests use unbundled Locator class to avoid overly strict checks within puppeteer that fail when mixing bundled and unbundled class instances */
89
+ locatorClass = Locator) {
90
+ const context = new McpContext(browser, logger, opts, locatorClass);
91
+ await context.#init();
92
+ return context;
93
+ }
94
+ roots() {
95
+ if (this.#roots === undefined) {
96
+ return undefined;
97
+ }
98
+ return [
99
+ ...this.#roots,
100
+ {
101
+ uri: pathToFileURL(os.tmpdir()).href,
102
+ name: 'temp',
103
+ },
104
+ ];
105
+ }
106
+ setRoots(roots) {
107
+ this.#roots = roots;
108
+ }
109
+ validatePath(filePath) {
110
+ if (filePath === undefined) {
111
+ return;
112
+ }
113
+ const roots = this.roots();
114
+ if (roots === undefined) {
115
+ return;
116
+ }
117
+ const absolutePath = path.resolve(filePath);
118
+ for (const root of roots) {
119
+ const rootPath = path.resolve(fileURLToPath(root.uri));
120
+ if (absolutePath === rootPath ||
121
+ absolutePath.startsWith(rootPath + path.sep)) {
122
+ return;
123
+ }
124
+ }
125
+ throw new Error(`Access denied: path ${filePath} is not within any of the workspace roots ${JSON.stringify(roots)}.`);
126
+ }
127
+ resolveCdpRequestId(page, cdpRequestId) {
128
+ if (!cdpRequestId) {
129
+ this.logger('no network request');
130
+ return;
131
+ }
132
+ const request = this.#networkCollector.find(page.pptrPage, request => {
133
+ // @ts-expect-error id is internal.
134
+ return request.id === cdpRequestId;
135
+ });
136
+ if (!request) {
137
+ this.logger('no network request for ' + cdpRequestId);
138
+ return;
139
+ }
140
+ return this.#networkCollector.getIdForResource(request);
141
+ }
142
+ getNetworkRequests(page, includePreservedRequests) {
143
+ return this.#networkCollector.getData(page.pptrPage, includePreservedRequests);
144
+ }
145
+ getConsoleData(page, includePreservedMessages) {
146
+ return this.#consoleCollector.getData(page.pptrPage, includePreservedMessages);
147
+ }
148
+ getDevToolsUniverse(page) {
149
+ return this.#devtoolsUniverseManager.get(page.pptrPage);
150
+ }
151
+ getConsoleMessageStableId(message) {
152
+ return this.#consoleCollector.getIdForResource(message);
153
+ }
154
+ getConsoleMessageById(page, id) {
155
+ return this.#consoleCollector.getById(page.pptrPage, id);
156
+ }
157
+ async newPage(background, isolatedContextName) {
158
+ let page;
159
+ if (isolatedContextName !== undefined) {
160
+ let ctx = this.#isolatedContexts.get(isolatedContextName);
161
+ if (!ctx) {
162
+ ctx = await this.browser.createBrowserContext();
163
+ this.#isolatedContexts.set(isolatedContextName, ctx);
164
+ }
165
+ page = await ctx.newPage();
166
+ }
167
+ else {
168
+ page = await this.browser.newPage({ background });
169
+ }
170
+ await this.createPagesSnapshot();
171
+ this.selectPage(this.#getMcpPage(page));
172
+ this.#networkCollector.addPage(page);
173
+ this.#consoleCollector.addPage(page);
174
+ return this.#getMcpPage(page);
175
+ }
176
+ async closePage(pageId) {
177
+ if (this.#pages.length === 1) {
178
+ throw new Error(CLOSE_PAGE_ERROR);
179
+ }
180
+ const page = this.getPageById(pageId);
181
+ if (page) {
182
+ page.dispose();
183
+ this.#mcpPages.delete(page.pptrPage);
184
+ }
185
+ await page.pptrPage.close({ runBeforeUnload: false });
186
+ }
187
+ getNetworkRequestById(page, reqid) {
188
+ return this.#networkCollector.getById(page.pptrPage, reqid);
189
+ }
190
+ async restoreEmulation(page) {
191
+ const currentSetting = page.emulationSettings;
192
+ await this.emulate(currentSetting, page.pptrPage);
193
+ }
194
+ async emulate(options, targetPage) {
195
+ const page = targetPage ?? this.getSelectedPptrPage();
196
+ const mcpPage = this.#getMcpPage(page);
197
+ const newSettings = { ...mcpPage.emulationSettings };
198
+ if (!options.networkConditions) {
199
+ await page.emulateNetworkConditions(null);
200
+ delete newSettings.networkConditions;
201
+ }
202
+ else if (options.networkConditions === 'Offline') {
203
+ await page.emulateNetworkConditions({
204
+ offline: true,
205
+ download: 0,
206
+ upload: 0,
207
+ latency: 0,
208
+ });
209
+ newSettings.networkConditions = 'Offline';
210
+ }
211
+ else if (options.networkConditions in PredefinedNetworkConditions) {
212
+ const networkCondition = PredefinedNetworkConditions[options.networkConditions];
213
+ await page.emulateNetworkConditions(networkCondition);
214
+ newSettings.networkConditions = options.networkConditions;
215
+ }
216
+ if (!options.cpuThrottlingRate) {
217
+ await page.emulateCPUThrottling(1);
218
+ delete newSettings.cpuThrottlingRate;
219
+ }
220
+ else {
221
+ await page.emulateCPUThrottling(options.cpuThrottlingRate);
222
+ newSettings.cpuThrottlingRate = options.cpuThrottlingRate;
223
+ }
224
+ if (!options.geolocation) {
225
+ await page.setGeolocation({ latitude: 0, longitude: 0 });
226
+ delete newSettings.geolocation;
227
+ }
228
+ else {
229
+ await page.setGeolocation(options.geolocation);
230
+ newSettings.geolocation = options.geolocation;
231
+ }
232
+ if (!options.userAgent) {
233
+ await page.setUserAgent({ userAgent: undefined });
234
+ delete newSettings.userAgent;
235
+ }
236
+ else {
237
+ await page.setUserAgent({ userAgent: options.userAgent });
238
+ newSettings.userAgent = options.userAgent;
239
+ }
240
+ if (!options.colorScheme || options.colorScheme === 'auto') {
241
+ await page.emulateMediaFeatures([
242
+ { name: 'prefers-color-scheme', value: '' },
243
+ ]);
244
+ delete newSettings.colorScheme;
245
+ }
246
+ else {
247
+ await page.emulateMediaFeatures([
248
+ { name: 'prefers-color-scheme', value: options.colorScheme },
249
+ ]);
250
+ newSettings.colorScheme = options.colorScheme;
251
+ }
252
+ if (!options.viewport) {
253
+ await page.setViewport(null);
254
+ delete newSettings.viewport;
255
+ }
256
+ else {
257
+ const defaults = {
258
+ deviceScaleFactor: 1,
259
+ isMobile: false,
260
+ hasTouch: false,
261
+ isLandscape: false,
262
+ };
263
+ const viewport = { ...defaults, ...options.viewport };
264
+ await page.setViewport(viewport);
265
+ newSettings.viewport = viewport;
266
+ }
267
+ mcpPage.emulationSettings = Object.keys(newSettings).length
268
+ ? newSettings
269
+ : {};
270
+ this.#updateSelectedPageTimeouts();
271
+ }
272
+ setIsRunningPerformanceTrace(x) {
273
+ this.#isRunningTrace = x;
274
+ }
275
+ isRunningPerformanceTrace() {
276
+ return this.#isRunningTrace;
277
+ }
278
+ getScreenRecorder() {
279
+ return this.#screenRecorderData;
280
+ }
281
+ setScreenRecorder(data) {
282
+ this.#screenRecorderData = data;
283
+ }
284
+ isCruxEnabled() {
285
+ return this.#options.performanceCrux;
286
+ }
287
+ getSelectedPptrPage() {
288
+ const page = this.#selectedPage;
289
+ if (!page) {
290
+ throw new Error('No page selected');
291
+ }
292
+ if (page.pptrPage.isClosed()) {
293
+ throw new Error(`The selected page has been closed. Call ${listPages().name} to see open pages.`);
294
+ }
295
+ return page.pptrPage;
296
+ }
297
+ getSelectedMcpPage() {
298
+ const page = this.getSelectedPptrPage();
299
+ return this.#getMcpPage(page);
300
+ }
301
+ getPageById(pageId) {
302
+ const page = this.#mcpPages.values().find(mcpPage => mcpPage.id === pageId);
303
+ if (!page) {
304
+ throw new Error('No page found');
305
+ }
306
+ return page;
307
+ }
308
+ getPageId(page) {
309
+ return this.#mcpPages.get(page)?.id;
310
+ }
311
+ #getMcpPage(page) {
312
+ const mcpPage = this.#mcpPages.get(page);
313
+ if (!mcpPage) {
314
+ throw new Error('No McpPage found for the given page.');
315
+ }
316
+ return mcpPage;
317
+ }
318
+ #getSelectedMcpPage() {
319
+ return this.#getMcpPage(this.getSelectedPptrPage());
320
+ }
321
+ isPageSelected(page) {
322
+ return this.#selectedPage?.pptrPage === page;
323
+ }
324
+ selectPage(newPage) {
325
+ this.#selectedPage = newPage;
326
+ this.#updateSelectedPageTimeouts();
327
+ }
328
+ #updateSelectedPageTimeouts() {
329
+ const page = this.#getSelectedMcpPage();
330
+ // For waiters 5sec timeout should be sufficient.
331
+ // Increased in case we throttle the CPU
332
+ const cpuMultiplier = page.cpuThrottlingRate;
333
+ page.pptrPage.setDefaultTimeout(DEFAULT_TIMEOUT * cpuMultiplier);
334
+ // 10sec should be enough for the load event to be emitted during
335
+ // navigations.
336
+ // Increased in case we throttle the network requests
337
+ const networkMultiplier = getNetworkMultiplierFromString(page.networkConditions);
338
+ page.pptrPage.setDefaultNavigationTimeout(NAVIGATION_TIMEOUT * networkMultiplier);
339
+ }
340
+ // Linear scan over per-page snapshots. The page count is small (typically
341
+ // 2-10) so a reverse index isn't worthwhile given the uid-reuse lifecycle
342
+ // complexity it would introduce.
343
+ getAXNodeByUid(uid) {
344
+ for (const mcpPage of this.#mcpPages.values()) {
345
+ const node = mcpPage.textSnapshot?.idToNode.get(uid);
346
+ if (node) {
347
+ return node;
348
+ }
349
+ }
350
+ return undefined;
351
+ }
352
+ /**
353
+ * Creates a snapshot of the extension service workers.
354
+ */
355
+ async createExtensionServiceWorkersSnapshot() {
356
+ const allTargets = await this.browser.targets();
357
+ const serviceWorkers = allTargets.filter(target => {
358
+ return (target.type() === 'service_worker' &&
359
+ target.url().includes('chrome-extension://'));
360
+ });
361
+ for (const serviceWorker of serviceWorkers) {
362
+ if (!this.#extensionServiceWorkerMap.has(serviceWorker)) {
363
+ this.#extensionServiceWorkerMap.set(serviceWorker, 'sw-' + this.#nextExtensionServiceWorkerId++);
364
+ }
365
+ }
366
+ this.#extensionServiceWorkers = serviceWorkers.map(serviceWorker => {
367
+ return {
368
+ target: serviceWorker,
369
+ id: this.#extensionServiceWorkerMap.get(serviceWorker),
370
+ url: serviceWorker.url(),
371
+ };
372
+ });
373
+ return this.#extensionServiceWorkers;
374
+ }
375
+ async createPagesSnapshot() {
376
+ const { pages: allPages, isolatedContextNames } = await this.#getAllPages();
377
+ for (const page of allPages) {
378
+ let mcpPage = this.#mcpPages.get(page);
379
+ if (!mcpPage) {
380
+ mcpPage = new McpPage(page, this.#nextPageId++);
381
+ this.#mcpPages.set(page, mcpPage);
382
+ // We emulate a focused page for all pages to support multi-agent workflows.
383
+ void page.emulateFocusedPage(true).catch(error => {
384
+ this.logger('Error turning on focused page emulation', error);
385
+ });
386
+ }
387
+ mcpPage.isolatedContextName = isolatedContextNames.get(page);
388
+ }
389
+ // Prune orphaned #mcpPages entries (pages that no longer exist).
390
+ const currentPages = new Set(allPages);
391
+ for (const [page, mcpPage] of this.#mcpPages) {
392
+ if (!currentPages.has(page)) {
393
+ mcpPage.dispose();
394
+ this.#mcpPages.delete(page);
395
+ }
396
+ }
397
+ this.#pages = allPages.filter(page => {
398
+ return (this.#options.experimentalDevToolsDebugging ||
399
+ !page.url().startsWith('devtools://'));
400
+ });
401
+ if ((!this.#selectedPage ||
402
+ this.#pages.indexOf(this.#selectedPage.pptrPage) === -1) &&
403
+ this.#pages[0]) {
404
+ this.selectPage(this.#getMcpPage(this.#pages[0]));
405
+ }
406
+ await this.detectOpenDevToolsWindows();
407
+ return this.#pages;
408
+ }
409
+ async #getAllPages() {
410
+ const defaultCtx = this.browser.defaultBrowserContext();
411
+ const allPages = await this.browser.pages(this.#options.experimentalIncludeAllPages);
412
+ const allTargets = this.browser.targets();
413
+ const extensionTargets = allTargets.filter(target => {
414
+ return (target.url().startsWith('chrome-extension://') &&
415
+ target.type() === 'page');
416
+ });
417
+ for (const target of extensionTargets) {
418
+ // Right now target.page() returns null for popup and side panel pages.
419
+ let page = await target.page();
420
+ if (!page) {
421
+ // We need to cache pages instances for targets because target.asPage()
422
+ // returns a new page instance every time.
423
+ page = this.#extensionPages.get(target) ?? null;
424
+ if (!page) {
425
+ try {
426
+ page = await target.asPage();
427
+ this.#extensionPages.set(target, page);
428
+ }
429
+ catch (e) {
430
+ this.logger('Failed to get page for extension target', e);
431
+ }
432
+ }
433
+ }
434
+ if (page && !allPages.includes(page)) {
435
+ allPages.push(page);
436
+ }
437
+ }
438
+ // Build a reverse lookup from BrowserContext instance → name.
439
+ const contextToName = new Map();
440
+ for (const [name, ctx] of this.#isolatedContexts) {
441
+ contextToName.set(ctx, name);
442
+ }
443
+ // Auto-discover BrowserContexts not in our mapping (e.g., externally
444
+ // created incognito contexts) and assign generated names.
445
+ const knownContexts = new Set(this.#isolatedContexts.values());
446
+ for (const ctx of this.browser.browserContexts()) {
447
+ if (ctx !== defaultCtx && !ctx.closed && !knownContexts.has(ctx)) {
448
+ const name = `isolated-context-${this.#nextIsolatedContextId++}`;
449
+ this.#isolatedContexts.set(name, ctx);
450
+ contextToName.set(ctx, name);
451
+ }
452
+ }
453
+ // Map each page to its isolated context name (if any).
454
+ const isolatedContextNames = new Map();
455
+ for (const page of allPages) {
456
+ const ctx = page.browserContext();
457
+ const name = contextToName.get(ctx);
458
+ if (name) {
459
+ isolatedContextNames.set(page, name);
460
+ }
461
+ }
462
+ return { pages: allPages, isolatedContextNames };
463
+ }
464
+ async detectOpenDevToolsWindows() {
465
+ this.logger('Detecting open DevTools windows');
466
+ const { pages } = await this.#getAllPages();
467
+ await Promise.all(pages.map(async (page) => {
468
+ const mcpPage = this.#mcpPages.get(page);
469
+ if (!mcpPage) {
470
+ return;
471
+ }
472
+ // Prior to Chrome 144.0.7559.59, the command fails,
473
+ // Some Electron apps still use older version
474
+ // Fall back to not exposing DevTools at all.
475
+ try {
476
+ if (await page.hasDevTools()) {
477
+ mcpPage.devToolsPage = await page.openDevTools();
478
+ }
479
+ else {
480
+ mcpPage.devToolsPage = undefined;
481
+ }
482
+ }
483
+ catch {
484
+ mcpPage.devToolsPage = undefined;
485
+ }
486
+ }));
487
+ }
488
+ getExtensionServiceWorkers() {
489
+ return this.#extensionServiceWorkers;
490
+ }
491
+ getExtensionServiceWorkerId(extensionServiceWorker) {
492
+ return this.#extensionServiceWorkerMap.get(extensionServiceWorker.target);
493
+ }
494
+ getPages() {
495
+ return this.#pages;
496
+ }
497
+ getIsolatedContextName(page) {
498
+ return this.#mcpPages.get(page)?.isolatedContextName;
499
+ }
500
+ async saveTemporaryFile(data, filename) {
501
+ const filepath = await getTempFilePath(filename);
502
+ this.validatePath(filepath);
503
+ try {
504
+ await fs.writeFile(filepath, data);
505
+ }
506
+ catch (err) {
507
+ throw new Error('Could not save a file', { cause: err });
508
+ }
509
+ return { filepath };
510
+ }
511
+ async saveFile(data, clientProvidedFilePath, extension) {
512
+ this.validatePath(clientProvidedFilePath);
513
+ try {
514
+ const filePath = ensureExtension(path.resolve(clientProvidedFilePath), extension);
515
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
516
+ await fs.writeFile(filePath, data);
517
+ return { filename: filePath };
518
+ }
519
+ catch (err) {
520
+ this.logger(err);
521
+ throw new Error('Could not save a file', { cause: err });
522
+ }
523
+ }
524
+ storeTraceRecording(result) {
525
+ // Clear the trace results because we only consume the latest trace currently.
526
+ this.#traceResults = [];
527
+ this.#traceResults.push(result);
528
+ }
529
+ recordedTraces() {
530
+ return this.#traceResults;
531
+ }
532
+ getNetworkRequestStableId(request) {
533
+ return this.#networkCollector.getIdForResource(request);
534
+ }
535
+ waitForTextOnPage(text, timeout, targetPage) {
536
+ const page = targetPage ?? this.getSelectedPptrPage();
537
+ const frames = page.frames();
538
+ let locator = this.#locatorClass.race(frames.flatMap(frame => text.flatMap(value => [
539
+ frame.locator(`aria/${value}`),
540
+ frame.locator(`text/${value}`),
541
+ ])));
542
+ if (timeout) {
543
+ locator = locator.setTimeout(timeout);
544
+ }
545
+ return locator.wait();
546
+ }
547
+ /**
548
+ * We need to ignore favicon request as they make our test flaky
549
+ */
550
+ async setUpNetworkCollectorForTesting() {
551
+ this.#networkCollector = new NetworkCollector(this.browser, collect => {
552
+ return {
553
+ request: req => {
554
+ if (req.url().includes('favicon.ico')) {
555
+ return;
556
+ }
557
+ collect(req);
558
+ },
559
+ };
560
+ });
561
+ const { pages } = await this.#getAllPages();
562
+ await this.#networkCollector.init(pages);
563
+ }
564
+ async installExtension(extensionPath) {
565
+ this.validatePath(extensionPath);
566
+ const id = await this.browser.installExtension(extensionPath);
567
+ return id;
568
+ }
569
+ async uninstallExtension(id) {
570
+ await this.browser.uninstallExtension(id);
571
+ }
572
+ async triggerExtensionAction(id) {
573
+ const extensions = await this.browser.extensions();
574
+ const extension = extensions.get(id);
575
+ if (!extension) {
576
+ throw new Error(`Extension with ID ${id} not found.`);
577
+ }
578
+ const page = this.getSelectedPptrPage();
579
+ await extension.triggerAction(page);
580
+ }
581
+ listExtensions() {
582
+ return this.browser.extensions();
583
+ }
584
+ async getExtension(id) {
585
+ const pptrExtensions = await this.browser.extensions();
586
+ return pptrExtensions.get(id);
587
+ }
588
+ async getHeapSnapshotAggregates(filePath) {
589
+ this.validatePath(filePath);
590
+ return await this.#heapSnapshotManager.getAggregates(filePath);
591
+ }
592
+ async getHeapSnapshotStats(filePath) {
593
+ this.validatePath(filePath);
594
+ return await this.#heapSnapshotManager.getStats(filePath);
595
+ }
596
+ async getHeapSnapshotStaticData(filePath) {
597
+ this.validatePath(filePath);
598
+ return await this.#heapSnapshotManager.getStaticData(filePath);
599
+ }
600
+ async getHeapSnapshotNodesByUid(filePath, uid) {
601
+ this.validatePath(filePath);
602
+ return await this.#heapSnapshotManager.getNodesByUid(filePath, uid);
603
+ }
604
+ }
605
+ //# sourceMappingURL=McpContext.js.map