@yezack/chrome-devtools-mcp-108 0.0.0-stage → 1.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/FORK-NOTICE.md +45 -0
- package/LICENSE +202 -0
- package/README.md +45 -2
- package/build/src/BrowserManager.js +401 -0
- package/build/src/McpContext.js +642 -0
- package/build/src/McpPage.js +850 -0
- package/build/src/McpResponse.js +1086 -0
- package/build/src/SlimMcpResponse.js +19 -0
- package/build/src/TextSnapshot.js +315 -0
- package/build/src/ToolHandler.js +322 -0
- package/build/src/bin/check-latest-version.js +51 -0
- package/build/src/bin/chrome-devtools-mcp-main.js +77 -0
- package/build/src/bin/chrome-devtools-mcp.js +23 -0
- package/build/src/bin/chrome-devtools.js +222 -0
- package/build/src/collectors/PageCollector.js +291 -0
- package/build/src/collectors/ServiceWorkerCollector.js +171 -0
- package/build/src/config/browser-options.js +125 -0
- package/build/src/config/category-options.js +89 -0
- package/build/src/config/cli-commands.js +26 -0
- package/build/src/config/cli-options.js +1473 -0
- package/build/src/config/mcp-options.js +417 -0
- package/build/src/daemon/client.js +221 -0
- package/build/src/daemon/daemon.js +266 -0
- package/build/src/daemon/types.js +7 -0
- package/build/src/daemon/utils.js +136 -0
- package/build/src/devtools/DevToolsCommentBridge.js +91 -0
- package/build/src/devtools/DevtoolsUtils.js +307 -0
- package/build/src/devtools/McpHostBindingAdapter.js +165 -0
- package/build/src/devtools/issueDescriptions.js +42 -0
- package/build/src/formatters/CommentFormatter.js +82 -0
- package/build/src/formatters/ConsoleFormatter.js +321 -0
- package/build/src/formatters/CssFormatter.js +812 -0
- package/build/src/formatters/HeapSnapshotFormatter.js +185 -0
- package/build/src/formatters/IssueFormatter.js +193 -0
- package/build/src/formatters/NetworkFormatter.js +241 -0
- package/build/src/formatters/SnapshotFormatter.js +135 -0
- package/build/src/index.js +237 -0
- package/build/src/processors/ChunkedTraceParser.js +361 -0
- package/build/src/processors/HeapSnapshotManager.js +270 -0
- package/build/src/processors/PerformanceTrace.js +132 -0
- package/build/src/telemetry/ClearcutLogger.js +242 -0
- package/build/src/telemetry/WatchdogClient.js +61 -0
- package/build/src/telemetry/errors.js +18 -0
- package/build/src/telemetry/flagUtils.js +90 -0
- package/build/src/telemetry/metricsRegistry.js +85 -0
- package/build/src/telemetry/persistence.js +82 -0
- package/build/src/telemetry/transformation.js +233 -0
- package/build/src/telemetry/types.js +36 -0
- package/build/src/telemetry/watchdog/ClearcutSender.js +205 -0
- package/build/src/telemetry/watchdog/main.js +128 -0
- package/build/src/third_party/THIRD_PARTY_NOTICES +4077 -0
- package/build/src/third_party/bundled-packages.json +12 -0
- package/build/src/third_party/devtools-formatter-worker.js +15494 -0
- package/build/src/third_party/devtools-heap-snapshot-worker.js +10979 -0
- package/build/src/third_party/index.js +200978 -0
- package/build/src/third_party/issue-descriptions/CoepCoopSandboxedIframeCannotNavigateToCoopPage.md +4 -0
- package/build/src/third_party/issue-descriptions/CoepCorpNotSameOrigin.md +8 -0
- package/build/src/third_party/issue-descriptions/CoepCorpNotSameOriginAfterDefaultedToSameOriginByCoep.md +18 -0
- package/build/src/third_party/issue-descriptions/CoepCorpNotSameSite.md +7 -0
- package/build/src/third_party/issue-descriptions/CoepFrameResourceNeedsCoepHeader.md +10 -0
- package/build/src/third_party/issue-descriptions/CompatibilityModeQuirks.md +5 -0
- package/build/src/third_party/issue-descriptions/CookieAttributeValueExceedsMaxSize.md +5 -0
- package/build/src/third_party/issue-descriptions/LowTextContrast.md +5 -0
- package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureErrorRead.md +8 -0
- package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureErrorSet.md +8 -0
- package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureWarnRead.md +8 -0
- package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureWarnSet.md +8 -0
- package/build/src/third_party/issue-descriptions/SameSiteUnspecifiedLaxAllowUnsafeRead.md +9 -0
- package/build/src/third_party/issue-descriptions/SameSiteUnspecifiedLaxAllowUnsafeSet.md +9 -0
- package/build/src/third_party/issue-descriptions/bounceTrackingMitigations.md +3 -0
- package/build/src/third_party/issue-descriptions/clientHintMetaTagAllowListInvalidOrigin.md +4 -0
- package/build/src/third_party/issue-descriptions/clientHintMetaTagModifiedHTML.md +4 -0
- package/build/src/third_party/issue-descriptions/connectionAllowlistEmbeddingRequirementNotSatisfied.md +26 -0
- package/build/src/third_party/issue-descriptions/connectionAllowlistIFrameAttributeLoosensEmbeddingRequirement.md +19 -0
- package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidAllowConnectionAllowlistFrom.md +21 -0
- package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidAllowlistItemType.md +12 -0
- package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidHeader.md +12 -0
- package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidUrlPattern.md +8 -0
- package/build/src/third_party/issue-descriptions/connectionAllowlistItemNotInnerList.md +12 -0
- package/build/src/third_party/issue-descriptions/connectionAllowlistMoreThanOneList.md +7 -0
- package/build/src/third_party/issue-descriptions/connectionAllowlistReportingEndpointNotToken.md +10 -0
- package/build/src/third_party/issue-descriptions/cookieCrossSiteRedirectDowngrade.md +12 -0
- package/build/src/third_party/issue-descriptions/cookieExcludeDomainNonAscii.md +11 -0
- package/build/src/third_party/issue-descriptions/cookieExcludePortMismatch.md +8 -0
- package/build/src/third_party/issue-descriptions/cookieExcludeSchemeMismatch.md +7 -0
- package/build/src/third_party/issue-descriptions/cookieExcludeThirdPartyPhaseoutRead.md +6 -0
- package/build/src/third_party/issue-descriptions/cookieExcludeThirdPartyPhaseoutSet.md +6 -0
- package/build/src/third_party/issue-descriptions/cookieWarnDomainNonAscii.md +11 -0
- package/build/src/third_party/issue-descriptions/cookieWarnMetadataGrantRead.md +4 -0
- package/build/src/third_party/issue-descriptions/cookieWarnMetadataGrantSet.md +4 -0
- package/build/src/third_party/issue-descriptions/cookieWarnThirdPartyPhaseoutRead.md +6 -0
- package/build/src/third_party/issue-descriptions/cookieWarnThirdPartyPhaseoutSet.md +6 -0
- package/build/src/third_party/issue-descriptions/corsAllowCredentialsRequired.md +6 -0
- package/build/src/third_party/issue-descriptions/corsDisabledScheme.md +7 -0
- package/build/src/third_party/issue-descriptions/corsDisallowedByMode.md +7 -0
- package/build/src/third_party/issue-descriptions/corsHeaderDisallowedByPreflightResponse.md +5 -0
- package/build/src/third_party/issue-descriptions/corsInvalidHeaderValues.md +7 -0
- package/build/src/third_party/issue-descriptions/corsLocalNetworkAccessPermissionDenied.md +19 -0
- package/build/src/third_party/issue-descriptions/corsMethodDisallowedByPreflightResponse.md +5 -0
- package/build/src/third_party/issue-descriptions/corsNoCorsRedirectModeNotFollow.md +5 -0
- package/build/src/third_party/issue-descriptions/corsOriginMismatch.md +6 -0
- package/build/src/third_party/issue-descriptions/corsPreflightResponseInvalid.md +5 -0
- package/build/src/third_party/issue-descriptions/corsRedirectContainsCredentials.md +5 -0
- package/build/src/third_party/issue-descriptions/corsWildcardOriginNotAllowed.md +9 -0
- package/build/src/third_party/issue-descriptions/cspEvalViolation.md +9 -0
- package/build/src/third_party/issue-descriptions/cspInlineViolation.md +10 -0
- package/build/src/third_party/issue-descriptions/cspTrustedTypesPolicyViolation.md +5 -0
- package/build/src/third_party/issue-descriptions/cspTrustedTypesSinkViolation.md +8 -0
- package/build/src/third_party/issue-descriptions/cspURLViolation.md +10 -0
- package/build/src/third_party/issue-descriptions/deprecation.md +3 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsEmptyList.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsHttpNotFound.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsInvalidContentType.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsInvalidResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsNoResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestDnsFetchFailed.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestDnsInvalidRecord.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestEmailVerificationWellKnownHttpNotFound.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestEmailVerificationWellKnownInvalidContentType.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestEmailVerificationWellKnownInvalidResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestEmailVerificationWellKnownNoResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestInvalidEmail.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestJwksHttpNotFound.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestJwksInvalidResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestKeyBindingSigningFailed.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestRpOriginIsOpaque.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenHttpNotFound.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenInvalidContentType.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenInvalidResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenInvalidSdJwt.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenMalformedSdJwt.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenNoResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidAudience.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidIssuedAt.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidNonce.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidSdHash.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidTyp.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingAud.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingCnf.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingIat.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingNonce.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingSdHash.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbSignatureFailed.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidEmail.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidEmailVerified.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidHolderKey.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidIssuedAt.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidIssuer.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtJwksMissingKeys.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtMissingCnf.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtMissingEmail.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtMissingIat.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtMissingIss.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtSignatureFailed.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtUnsupportedHeaderAlg.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestUserLoggedOut.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownAccountsEndpointCrossOrigin.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownHttpNotFound.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownInvalidContentType.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownInvalidResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownIssuanceEndpointCrossOrigin.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownListEmpty.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownMissingAccountsEndpoint.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownMissingIssuanceEndpoint.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownNoResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownUnsupportedSigningAlgorithm.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsBlockedByConnectionAllowlist.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsHttpNotFound.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsInvalidResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsNoResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestApprovalDeclined.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestCanceled.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestConfigBlockedByConnectionAllowlist.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestErrorFetchingSignin.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestErrorIdToken.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenBlockedByConnectionAllowlist.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenHttpNotFound.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenInvalidRequest.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenInvalidResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenNoResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestInvalidSigninResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestHttpNotFound.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestInvalidResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestNoResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestTooManyRequests.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthRequestWellKnownBlockedByConnectionAllowlist.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestInvalidAccountsResponse.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestInvalidConfigOrWellKnown.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoAccountSharingPermission.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoApiPermission.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoReturningUserFromFetchedAccounts.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotIframe.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotPotentiallyTrustworthy.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotSameOrigin.md +1 -0
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotSignedInWithIdp.md +1 -0
- package/build/src/third_party/issue-descriptions/fetchingPartitionedBlobURL.md +7 -0
- package/build/src/third_party/issue-descriptions/genericBackUINavigationWouldSkipAd.md +4 -0
- package/build/src/third_party/issue-descriptions/genericFormAriaLabelledByToNonExistingIdError.md +8 -0
- package/build/src/third_party/issue-descriptions/genericFormAutocompleteAttributeEmptyError.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormDuplicateIdForInputError.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormEmptyIdAndNameAttributesForInputError.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormInputAssignedAutocompleteValueToIdOrNameAttributeError.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormInputHasWrongButWellIntendedAutocompleteValueError.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormInputWithNoLabelError.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormLabelForMatchesNonExistingIdError.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormLabelForNameError.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormLabelHasNeitherForNorNestedInputError.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormModelContextMissingToolDescription.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormModelContextMissingToolName.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormModelContextParameterMissingName.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormModelContextParameterMissingTitleAndDescription.md +5 -0
- package/build/src/third_party/issue-descriptions/genericFormModelContextRequiredParameterMissingName.md +5 -0
- package/build/src/third_party/issue-descriptions/genericNavigationEntryMarkedSkippable.md +7 -0
- package/build/src/third_party/issue-descriptions/genericResponseWasBlockedByORB.md +4 -0
- package/build/src/third_party/issue-descriptions/heavyAd.md +10 -0
- package/build/src/third_party/issue-descriptions/lazyLoadImageZeroSize.md +7 -0
- package/build/src/third_party/issue-descriptions/mixedContent.md +5 -0
- package/build/src/third_party/issue-descriptions/navigatingPartitionedBlobURL.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementActivationDisabled.md +7 -0
- package/build/src/third_party/issue-descriptions/permissionElementActivationDisabledWithOccluder.md +9 -0
- package/build/src/third_party/issue-descriptions/permissionElementActivationDisabledWithOccluderParent.md +9 -0
- package/build/src/third_party/issue-descriptions/permissionElementCspFrameAncestorsMissing.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementFencedFrameDisallowed.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementFontSizeTooLarge.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementFontSizeTooSmall.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementGeolocationDeprecated.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementInsetBoxShadowUnsupported.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementInvalidDisplayStyle.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementInvalidSizeValue.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementInvalidType.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementInvalidTypeActivation.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementLowContrast.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementNonOpaqueColor.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementPaddingBottomUnsupported.md +6 -0
- package/build/src/third_party/issue-descriptions/permissionElementPaddingRightUnsupported.md +6 -0
- package/build/src/third_party/issue-descriptions/permissionElementPermissionsPolicyBlocked.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementRegistrationFailed.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementRequestInProgress.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementSecurityChecksFailed.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementTypeNotSupported.md +5 -0
- package/build/src/third_party/issue-descriptions/permissionElementUntrustedEvent.md +7 -0
- package/build/src/third_party/issue-descriptions/placeholderDescriptionForInvisibleIssues.md +3 -0
- package/build/src/third_party/issue-descriptions/propertyRuleInvalidNameIssue.md +3 -0
- package/build/src/third_party/issue-descriptions/propertyRuleIssue.md +7 -0
- package/build/src/third_party/issue-descriptions/selectElementAccessibilityDisallowedOptGroupChild.md +7 -0
- package/build/src/third_party/issue-descriptions/selectElementAccessibilityDisallowedSelectChild.md +7 -0
- package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentAttributesSelectDescendant.md +3 -0
- package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentLegendChild.md +3 -0
- package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentOptionChild.md +3 -0
- package/build/src/third_party/issue-descriptions/selectElementAccessibilityNonPhrasingContentOptionChild.md +3 -0
- package/build/src/third_party/issue-descriptions/selectivePermissionsIntervention.md +7 -0
- package/build/src/third_party/issue-descriptions/sharedArrayBuffer.md +7 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorCrossOriginNoCorsRequest.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorDictionaryLoadFailure.md +3 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorMatchingDictionaryNotUsed.md +3 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorUnexpectedContentDictionaryHeader.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorCossOriginNoCorsRequest.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorDisallowedBySettings.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorExpiredResponse.md +3 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorFeatureDisabled.md +3 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorInsufficientResources.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorInvalidMatchField.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorInvalidStructuredHeader.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorInvalidTTLField.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNavigationRequest.md +3 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNoMatchField.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonIntegerTTLField.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonListMatchDestField.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonSecureContext.md +3 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonStringIdField.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonStringInMatchDestList.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonStringMatchField.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonTokenTypeField.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorRequestAborted.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorShuttingDown.md +1 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorTooLongIdField.md +3 -0
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorUnsupportedType.md +3 -0
- package/build/src/third_party/issue-descriptions/sriInvalidSignatureHeader.md +14 -0
- package/build/src/third_party/issue-descriptions/sriInvalidSignatureInputHeader.md +15 -0
- package/build/src/third_party/issue-descriptions/sriMissingSignatureHeader.md +8 -0
- package/build/src/third_party/issue-descriptions/sriMissingSignatureInputHeader.md +7 -0
- package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsIncorrectLength.md +11 -0
- package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsNotByteSequence.md +14 -0
- package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsParameterized.md +15 -0
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidComponentName.md +8 -0
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidComponentType.md +13 -0
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidDerivedComponentParameter.md +4 -0
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidHeaderComponentParameter.md +5 -0
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidParameter.md +11 -0
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderKeyIdLength.md +12 -0
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderMissingLabel.md +6 -0
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderMissingRequiredParameters.md +8 -0
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderValueMissingComponents.md +11 -0
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderValueNotInnerList.md +11 -0
- package/build/src/third_party/issue-descriptions/sriValidationFailedIntegrityMismatch.md +10 -0
- package/build/src/third_party/issue-descriptions/sriValidationFailedInvalidLength.md +5 -0
- package/build/src/third_party/issue-descriptions/sriValidationFailedSignatureExpired.md +6 -0
- package/build/src/third_party/issue-descriptions/sriValidationFailedSignatureMismatch.md +11 -0
- package/build/src/third_party/issue-descriptions/stylesheetLateImport.md +4 -0
- package/build/src/third_party/issue-descriptions/stylesheetRequestFailed.md +3 -0
- package/build/src/third_party/issue-descriptions/summaryElementAccessibilityInteractiveContentSummaryDescendant.md +3 -0
- package/build/src/third_party/issue-descriptions/unencodedDigestIncorrectDigestLength.md +12 -0
- package/build/src/third_party/issue-descriptions/unencodedDigestIncorrectDigestType.md +17 -0
- package/build/src/third_party/issue-descriptions/unencodedDigestMalformedDictionary.md +14 -0
- package/build/src/third_party/issue-descriptions/unencodedDigestUnknownAlgorithm.md +15 -0
- package/build/src/third_party/issue-descriptions/webInstallManifestMissingId.md +3 -0
- package/build/src/third_party/issue-descriptions/webInstallManifestMissingNameOrShortName.md +3 -0
- package/build/src/third_party/issue-descriptions/webInstallManifestParsingOrNetworkError.md +3 -0
- package/build/src/third_party/issue-descriptions/webInstallNoManifest.md +3 -0
- package/build/src/third_party/issue-descriptions/webInstallStartUrlInvalid.md +3 -0
- package/build/src/third_party/lighthouse-devtools-mcp-bundle.js +58435 -0
- package/build/src/tools/ToolDefinition.js +80 -0
- package/build/src/tools/categories.js +33 -0
- package/build/src/tools/comments.js +169 -0
- package/build/src/tools/console.js +104 -0
- package/build/src/tools/css.js +45 -0
- package/build/src/tools/emulation.js +84 -0
- package/build/src/tools/extensions.js +103 -0
- package/build/src/tools/input.js +652 -0
- package/build/src/tools/lighthouse.js +149 -0
- package/build/src/tools/memory.js +424 -0
- package/build/src/tools/network.js +128 -0
- package/build/src/tools/pages.js +363 -0
- package/build/src/tools/performance.js +212 -0
- package/build/src/tools/pwa.js +128 -0
- package/build/src/tools/screencast.js +119 -0
- package/build/src/tools/screenshot.js +277 -0
- package/build/src/tools/script.js +232 -0
- package/build/src/tools/slim/tools.js +96 -0
- package/build/src/tools/snapshot.js +63 -0
- package/build/src/tools/thirdPartyDeveloper.js +85 -0
- package/build/src/tools/tools.js +55 -0
- package/build/src/tools/webmcp.js +66 -0
- package/build/src/types.js +10 -0
- package/build/src/utils/WaitForHelper.js +316 -0
- package/build/src/utils/bytes.js +105 -0
- package/build/src/utils/check-for-updates.js +75 -0
- package/build/src/utils/files.js +57 -0
- package/build/src/utils/id.js +16 -0
- package/build/src/utils/keyboard.js +297 -0
- package/build/src/utils/logger.js +52 -0
- package/build/src/utils/pagination.js +50 -0
- package/build/src/utils/polyfill.js +11 -0
- package/build/src/utils/url.js +116 -0
- package/build/src/version.js +10 -0
- package/package.json +41 -4
- package/skills/a11y-debugging/SKILL.md +91 -0
- package/skills/a11y-debugging/references/a11y-snippets.md +92 -0
- package/skills/chrome-devtools/SKILL.md +74 -0
- package/skills/chrome-devtools-cli/SKILL.md +194 -0
- package/skills/chrome-devtools-cli/references/installation.md +14 -0
- package/skills/cookie-debugging/SKILL.md +149 -0
- package/skills/debug-optimize-lcp/SKILL.md +121 -0
- package/skills/debug-optimize-lcp/references/elements-and-size.md +27 -0
- package/skills/debug-optimize-lcp/references/lcp-breakdown.md +23 -0
- package/skills/debug-optimize-lcp/references/lcp-snippets.md +79 -0
- package/skills/debug-optimize-lcp/references/optimization-strategies.md +38 -0
- package/skills/memory-leak-debugging/SKILL.md +58 -0
- package/skills/memory-leak-debugging/references/common-leaks.md +33 -0
- package/skills/troubleshooting/SKILL.md +99 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { zod, ajv } from '../third_party/index.js';
|
|
7
|
+
import { ToolCategory } from './categories.js';
|
|
8
|
+
import { definePageTool } from './ToolDefinition.js';
|
|
9
|
+
export const listThirdPartyDeveloperTools = definePageTool(() => ({
|
|
10
|
+
name: 'list_3p_developer_tools',
|
|
11
|
+
description: `Lists all third-party developer tools the page exposes for providing runtime information.
|
|
12
|
+
Third-party developer tools can be called via the 'execute_3p_developer_tool()' MCP tool.
|
|
13
|
+
Alternatively, third-party developer tools can be executed by calling 'evaluate_script' and adding the
|
|
14
|
+
following command to the script:
|
|
15
|
+
\`window.__dtmcp.executeTool(toolName, params)\`
|
|
16
|
+
This might be helpful when the third-party developer tools return non-serializable values or when composing
|
|
17
|
+
third-party developer tools with additional functionality.`,
|
|
18
|
+
annotations: {
|
|
19
|
+
category: ToolCategory.THIRD_PARTY,
|
|
20
|
+
readOnlyHint: true,
|
|
21
|
+
},
|
|
22
|
+
schema: {},
|
|
23
|
+
blockedByDialog: false,
|
|
24
|
+
verifyFilesSchema: {},
|
|
25
|
+
handler: async (_request, response) => {
|
|
26
|
+
response.setListThirdPartyDeveloperTools();
|
|
27
|
+
},
|
|
28
|
+
}));
|
|
29
|
+
export const executeThirdPartyDeveloperTool = definePageTool(() => ({
|
|
30
|
+
name: 'execute_3p_developer_tool',
|
|
31
|
+
description: `Executes a tool exposed by the page.`,
|
|
32
|
+
annotations: {
|
|
33
|
+
category: ToolCategory.THIRD_PARTY,
|
|
34
|
+
readOnlyHint: false,
|
|
35
|
+
},
|
|
36
|
+
schema: {
|
|
37
|
+
toolName: zod.string().describe('The name of the tool to execute'),
|
|
38
|
+
params: zod
|
|
39
|
+
.string()
|
|
40
|
+
.optional()
|
|
41
|
+
.describe('The JSON-stringified parameters to pass to the tool'),
|
|
42
|
+
},
|
|
43
|
+
blockedByDialog: false,
|
|
44
|
+
verifyFilesSchema: {},
|
|
45
|
+
handler: async (request, response) => {
|
|
46
|
+
const toolName = request.params.toolName;
|
|
47
|
+
let params = {};
|
|
48
|
+
if (request.params.params) {
|
|
49
|
+
try {
|
|
50
|
+
const parsed = JSON.parse(request.params.params);
|
|
51
|
+
if (typeof parsed === 'object' && parsed !== null) {
|
|
52
|
+
params = parsed;
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
throw new Error('Parsed params is not an object');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch (e) {
|
|
59
|
+
const errorMessage = e instanceof Error ? e.message : String(e);
|
|
60
|
+
throw new Error(`Failed to parse params as JSON: ${errorMessage}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const toolGroups = request.page.getThirdPartyDeveloperTools();
|
|
64
|
+
let tool;
|
|
65
|
+
if (toolGroups) {
|
|
66
|
+
for (const group of toolGroups) {
|
|
67
|
+
tool = group.tools?.find(t => t.name === toolName);
|
|
68
|
+
if (tool) {
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (!tool) {
|
|
74
|
+
throw new Error(`Tool ${toolName} not found`);
|
|
75
|
+
}
|
|
76
|
+
const ajvInstance = new ajv();
|
|
77
|
+
const validate = ajvInstance.compile(tool.inputSchema);
|
|
78
|
+
const valid = validate(params);
|
|
79
|
+
if (!valid) {
|
|
80
|
+
throw new Error(`Invalid parameters for tool ${toolName}: ${ajvInstance.errorsText(validate.errors)}`);
|
|
81
|
+
}
|
|
82
|
+
await request.page.executeThirdPartyDeveloperTool(toolName, params, response);
|
|
83
|
+
},
|
|
84
|
+
}));
|
|
85
|
+
//# sourceMappingURL=thirdPartyDeveloper.js.map
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import * as commentsTools from './comments.js';
|
|
7
|
+
import * as consoleTools from './console.js';
|
|
8
|
+
import * as cssTools from './css.js';
|
|
9
|
+
import * as emulationTools from './emulation.js';
|
|
10
|
+
import * as extensionTools from './extensions.js';
|
|
11
|
+
import * as inputTools from './input.js';
|
|
12
|
+
import * as lighthouseTools from './lighthouse.js';
|
|
13
|
+
import * as memoryTools from './memory.js';
|
|
14
|
+
import * as networkTools from './network.js';
|
|
15
|
+
import * as pagesTools from './pages.js';
|
|
16
|
+
import * as performanceTools from './performance.js';
|
|
17
|
+
import * as pwaTools from './pwa.js';
|
|
18
|
+
import * as screencastTools from './screencast.js';
|
|
19
|
+
import * as screenshotTools from './screenshot.js';
|
|
20
|
+
import * as scriptTools from './script.js';
|
|
21
|
+
import * as slimTools from './slim/tools.js';
|
|
22
|
+
import * as snapshotTools from './snapshot.js';
|
|
23
|
+
import * as thirdPartyDeveloperTools from './thirdPartyDeveloper.js';
|
|
24
|
+
import * as webmcpTools from './webmcp.js';
|
|
25
|
+
export const createTools = (args) => {
|
|
26
|
+
const rawTools = args.slim
|
|
27
|
+
? Object.values(slimTools)
|
|
28
|
+
: [
|
|
29
|
+
...(args.devtoolsComments ? Object.values(commentsTools) : []),
|
|
30
|
+
...Object.values(consoleTools),
|
|
31
|
+
...Object.values(cssTools),
|
|
32
|
+
...Object.values(emulationTools),
|
|
33
|
+
...Object.values(extensionTools),
|
|
34
|
+
...Object.values(inputTools),
|
|
35
|
+
...Object.values(lighthouseTools),
|
|
36
|
+
...Object.values(memoryTools),
|
|
37
|
+
...Object.values(networkTools),
|
|
38
|
+
...Object.values(pagesTools),
|
|
39
|
+
...Object.values(performanceTools),
|
|
40
|
+
...Object.values(pwaTools),
|
|
41
|
+
...Object.values(screencastTools),
|
|
42
|
+
...Object.values(screenshotTools),
|
|
43
|
+
...Object.values(scriptTools),
|
|
44
|
+
...Object.values(snapshotTools),
|
|
45
|
+
...Object.values(thirdPartyDeveloperTools),
|
|
46
|
+
...Object.values(webmcpTools),
|
|
47
|
+
];
|
|
48
|
+
const tools = [];
|
|
49
|
+
for (const tool of rawTools) {
|
|
50
|
+
tools.push(tool(args));
|
|
51
|
+
}
|
|
52
|
+
tools.sort((a, b) => a.name.localeCompare(b.name));
|
|
53
|
+
return tools;
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { zod } from '../third_party/index.js';
|
|
7
|
+
import { ToolCategory } from './categories.js';
|
|
8
|
+
import { definePageTool } from './ToolDefinition.js';
|
|
9
|
+
export const listWebMcpTools = definePageTool(() => ({
|
|
10
|
+
name: 'list_webmcp_tools',
|
|
11
|
+
description: `Lists all WebMCP tools the page exposes.`,
|
|
12
|
+
annotations: {
|
|
13
|
+
category: ToolCategory.WEBMCP,
|
|
14
|
+
readOnlyHint: true,
|
|
15
|
+
},
|
|
16
|
+
schema: {},
|
|
17
|
+
blockedByDialog: false,
|
|
18
|
+
verifyFilesSchema: {},
|
|
19
|
+
handler: async (_request, response) => {
|
|
20
|
+
response.setListWebMcpTools();
|
|
21
|
+
},
|
|
22
|
+
}));
|
|
23
|
+
export const executeWebMcpTool = definePageTool(() => ({
|
|
24
|
+
name: 'execute_webmcp_tool',
|
|
25
|
+
description: `Executes a WebMCP tool exposed by the page.`,
|
|
26
|
+
annotations: {
|
|
27
|
+
category: ToolCategory.WEBMCP,
|
|
28
|
+
readOnlyHint: false,
|
|
29
|
+
},
|
|
30
|
+
schema: {
|
|
31
|
+
toolName: zod.string().describe('The name of the WebMCP tool to execute'),
|
|
32
|
+
input: zod
|
|
33
|
+
.string()
|
|
34
|
+
.optional()
|
|
35
|
+
.describe('The JSON-stringified parameters to pass to the WebMCP tool'),
|
|
36
|
+
},
|
|
37
|
+
blockedByDialog: false,
|
|
38
|
+
verifyFilesSchema: {},
|
|
39
|
+
handler: async (request, response) => {
|
|
40
|
+
const toolName = request.params.toolName;
|
|
41
|
+
let input = {};
|
|
42
|
+
if (request.params.input) {
|
|
43
|
+
try {
|
|
44
|
+
const parsed = JSON.parse(request.params.input);
|
|
45
|
+
if (typeof parsed === 'object' && parsed !== null) {
|
|
46
|
+
input = parsed;
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
throw new Error('Parsed input is not an object');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch (e) {
|
|
53
|
+
const errorMessage = e instanceof Error ? e.message : String(e);
|
|
54
|
+
throw new Error(`Failed to parse input as JSON: ${errorMessage}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const tools = request.page.pptrPage.webmcp.tools();
|
|
58
|
+
const tool = tools.find(t => t.name === toolName);
|
|
59
|
+
if (!tool) {
|
|
60
|
+
throw new Error(`Tool ${toolName} not found`);
|
|
61
|
+
}
|
|
62
|
+
const { status, output, errorText } = await tool.execute(input);
|
|
63
|
+
response.appendResponseLine(JSON.stringify({ status, output, errorText }, null, 2));
|
|
64
|
+
},
|
|
65
|
+
}));
|
|
66
|
+
//# sourceMappingURL=webmcp.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
export var CD4ABridgeEvents;
|
|
7
|
+
(function (CD4ABridgeEvents) {
|
|
8
|
+
CD4ABridgeEvents["COMMENT_THREADS_CHANGED"] = "CommentThreadsChanged";
|
|
9
|
+
})(CD4ABridgeEvents || (CD4ABridgeEvents = {}));
|
|
10
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
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
|
+
import { logger } from './logger.js';
|
|
59
|
+
export class WaitForHelper {
|
|
60
|
+
#abortController = new AbortController();
|
|
61
|
+
#page;
|
|
62
|
+
#stableDomTimeout;
|
|
63
|
+
#stableDomFor;
|
|
64
|
+
#expectNavigationIn;
|
|
65
|
+
#navigationTimeout;
|
|
66
|
+
#dialogHandled = false;
|
|
67
|
+
/** Track all dialogs as they pause the renderer. */
|
|
68
|
+
#dialogDetected = false;
|
|
69
|
+
#initialUrl;
|
|
70
|
+
constructor(page, cpuTimeoutMultiplier, networkTimeoutMultiplier) {
|
|
71
|
+
this.#stableDomTimeout = 3000 * cpuTimeoutMultiplier;
|
|
72
|
+
this.#stableDomFor = 100 * cpuTimeoutMultiplier;
|
|
73
|
+
this.#expectNavigationIn = 100 * cpuTimeoutMultiplier;
|
|
74
|
+
this.#navigationTimeout = 3000 * networkTimeoutMultiplier;
|
|
75
|
+
this.#page = page;
|
|
76
|
+
this.#initialUrl = page.url();
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* A wrapper that executes a action and waits for
|
|
80
|
+
* a potential navigation, after which it waits
|
|
81
|
+
* for the DOM to be stable before returning.
|
|
82
|
+
*/
|
|
83
|
+
async waitForStableDom() {
|
|
84
|
+
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
85
|
+
try {
|
|
86
|
+
// Bound the setup evaluation against the stable-DOM timeout. Without this
|
|
87
|
+
// cap a paused renderer (e.g. an open dialog) would make evaluateHandle
|
|
88
|
+
// hang until protocolTimeout (default 180s) while the tool mutex is held.
|
|
89
|
+
const stableDomObserver = __addDisposableResource(env_1, await Promise.race([
|
|
90
|
+
this.#page.evaluateHandle(timeout => {
|
|
91
|
+
let timeoutId;
|
|
92
|
+
function callback() {
|
|
93
|
+
clearTimeout(timeoutId);
|
|
94
|
+
timeoutId = setTimeout(() => {
|
|
95
|
+
domObserver.resolver.resolve();
|
|
96
|
+
domObserver.observer.disconnect();
|
|
97
|
+
}, timeout);
|
|
98
|
+
}
|
|
99
|
+
const domObserver = {
|
|
100
|
+
resolver: Promise.withResolvers(),
|
|
101
|
+
observer: new MutationObserver(callback),
|
|
102
|
+
};
|
|
103
|
+
// It's possible that the DOM is not gonna change so we
|
|
104
|
+
// need to start the timeout initially.
|
|
105
|
+
callback();
|
|
106
|
+
domObserver.observer.observe(document.body, {
|
|
107
|
+
childList: true,
|
|
108
|
+
subtree: true,
|
|
109
|
+
attributes: true,
|
|
110
|
+
});
|
|
111
|
+
return domObserver;
|
|
112
|
+
}, this.#stableDomFor),
|
|
113
|
+
this.timeout(this.#stableDomTimeout),
|
|
114
|
+
]).catch(() => undefined), false);
|
|
115
|
+
if (!stableDomObserver) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
this.#abortController.signal.addEventListener('abort', async () => {
|
|
119
|
+
try {
|
|
120
|
+
await stableDomObserver.evaluate(observer => {
|
|
121
|
+
observer.observer.disconnect();
|
|
122
|
+
observer.resolver.resolve();
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
// Ignored cleanup errors
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
return Promise.race([
|
|
130
|
+
stableDomObserver.evaluate(async (observer) => {
|
|
131
|
+
return await observer.resolver.promise;
|
|
132
|
+
}),
|
|
133
|
+
this.timeout(this.#stableDomTimeout).then(() => {
|
|
134
|
+
throw new Error('Timeout');
|
|
135
|
+
}),
|
|
136
|
+
]);
|
|
137
|
+
}
|
|
138
|
+
catch (e_1) {
|
|
139
|
+
env_1.error = e_1;
|
|
140
|
+
env_1.hasError = true;
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
__disposeResources(env_1);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
timeout(time) {
|
|
147
|
+
if (this.#abortController.signal.aborted) {
|
|
148
|
+
return Promise.resolve();
|
|
149
|
+
}
|
|
150
|
+
return new Promise(res => {
|
|
151
|
+
const id = setTimeout(res, time);
|
|
152
|
+
this.#abortController.signal.addEventListener('abort', () => {
|
|
153
|
+
res();
|
|
154
|
+
clearTimeout(id);
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
async waitForEventsAfterAction(action, options) {
|
|
159
|
+
if (this.#abortController.signal.aborted) {
|
|
160
|
+
throw new Error("Can't re-use a WaitForHelper");
|
|
161
|
+
}
|
|
162
|
+
const dialogHandler = (dialog) => {
|
|
163
|
+
this.#dialogDetected = true;
|
|
164
|
+
let actionToTake;
|
|
165
|
+
if (typeof options?.handleDialog === 'object') {
|
|
166
|
+
actionToTake = options.handleDialog[dialog.type()];
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
actionToTake = options?.handleDialog;
|
|
170
|
+
}
|
|
171
|
+
if (actionToTake) {
|
|
172
|
+
this.#dialogHandled = true;
|
|
173
|
+
if (actionToTake === 'dismiss') {
|
|
174
|
+
void dialog.dismiss();
|
|
175
|
+
}
|
|
176
|
+
else if (actionToTake === 'accept') {
|
|
177
|
+
void dialog.accept();
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
void dialog.accept(actionToTake);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
this.#abortController.abort(new Error('Action interrupted by a dialog'));
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
this.#page.on('dialog', dialogHandler);
|
|
188
|
+
this.#abortController.signal.addEventListener('abort', () => {
|
|
189
|
+
this.#page.off('dialog', dialogHandler);
|
|
190
|
+
});
|
|
191
|
+
// A scoped AbortController used to clean up navigation probe listeners.
|
|
192
|
+
// When aborted (either after navigation detection finishes or if this.#abortController
|
|
193
|
+
// aborts), it removes CDP navigation probe listeners and automatically
|
|
194
|
+
// detaches the abort listener from this.#abortController.signal.
|
|
195
|
+
const navigationAbortController = new AbortController();
|
|
196
|
+
const navigationStartedResolvers = Promise.withResolvers();
|
|
197
|
+
const navigationListener = (event) => {
|
|
198
|
+
if (event.frameId !== this.#page.mainFrame()._id) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (event.navigationType === 'sameDocument' ||
|
|
202
|
+
event.navigationType === 'historySameDocument') {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
navigationStartedResolvers.resolve(true);
|
|
206
|
+
};
|
|
207
|
+
const requestedNavigationListener = (event) => {
|
|
208
|
+
if (event.frameId === this.#page.mainFrame()._id) {
|
|
209
|
+
navigationStartedResolvers.resolve(true);
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
this.#page._client().on('Page.frameStartedNavigating', navigationListener);
|
|
213
|
+
this.#page
|
|
214
|
+
._client()
|
|
215
|
+
.on('Page.frameRequestedNavigation', requestedNavigationListener);
|
|
216
|
+
navigationAbortController.signal.addEventListener('abort', () => {
|
|
217
|
+
this.#page
|
|
218
|
+
._client()
|
|
219
|
+
.off('Page.frameStartedNavigating', navigationListener);
|
|
220
|
+
this.#page
|
|
221
|
+
._client()
|
|
222
|
+
.off('Page.frameRequestedNavigation', requestedNavigationListener);
|
|
223
|
+
});
|
|
224
|
+
this.#abortController.signal.addEventListener('abort', () => {
|
|
225
|
+
navigationStartedResolvers.resolve(false);
|
|
226
|
+
navigationAbortController.abort();
|
|
227
|
+
}, { signal: navigationAbortController.signal });
|
|
228
|
+
// Puppeteer's waitForNavigation must be started before the action runs so that
|
|
229
|
+
// it captures the pre-action loader ID. If started after the action triggers navigation,
|
|
230
|
+
// it risks recording the new loader ID and hanging until timeout.
|
|
231
|
+
// If no navigation occurs, this.#abortController will cancel it in the finally block.
|
|
232
|
+
const navigationFinished = this.#page
|
|
233
|
+
.waitForNavigation({
|
|
234
|
+
timeout: 0,
|
|
235
|
+
signal: this.#abortController.signal,
|
|
236
|
+
ignoreSameDocumentNavigation: true,
|
|
237
|
+
})
|
|
238
|
+
.then(result => {
|
|
239
|
+
navigationStartedResolvers.resolve(true);
|
|
240
|
+
return result;
|
|
241
|
+
})
|
|
242
|
+
.catch(error => {
|
|
243
|
+
if (this.#abortController.signal.aborted ||
|
|
244
|
+
(error instanceof Error && error.name === 'AbortError')) {
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
logger?.(error);
|
|
248
|
+
});
|
|
249
|
+
try {
|
|
250
|
+
await action(this.#abortController.signal);
|
|
251
|
+
}
|
|
252
|
+
catch (error) {
|
|
253
|
+
// Clear up pending promises
|
|
254
|
+
this.#abortController.abort();
|
|
255
|
+
throw error;
|
|
256
|
+
}
|
|
257
|
+
const expectNavigationIn = options?.expectNavigationIn ?? this.#expectNavigationIn;
|
|
258
|
+
const navigationStarted = await Promise.race([
|
|
259
|
+
navigationStartedResolvers.promise,
|
|
260
|
+
this.timeout(expectNavigationIn).then(() => {
|
|
261
|
+
navigationStartedResolvers.resolve(false);
|
|
262
|
+
return false;
|
|
263
|
+
}),
|
|
264
|
+
]);
|
|
265
|
+
navigationAbortController.abort();
|
|
266
|
+
try {
|
|
267
|
+
// Only await navigation if one was actually initiated; otherwise, the
|
|
268
|
+
// pending waitForNavigation promise will be cancelled when this.#abortController aborts.
|
|
269
|
+
if (navigationStarted) {
|
|
270
|
+
await Promise.race([
|
|
271
|
+
navigationFinished,
|
|
272
|
+
this.timeout(options?.timeout ?? this.#navigationTimeout),
|
|
273
|
+
]);
|
|
274
|
+
}
|
|
275
|
+
if (this.#dialogDetected) {
|
|
276
|
+
return this.#getResult();
|
|
277
|
+
}
|
|
278
|
+
// Wait for stable dom after navigation so we execute in
|
|
279
|
+
// the correct context
|
|
280
|
+
if (options?.waitForStableDom !== false) {
|
|
281
|
+
await this.waitForStableDom();
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
catch (error) {
|
|
285
|
+
logger?.(error);
|
|
286
|
+
}
|
|
287
|
+
finally {
|
|
288
|
+
this.#abortController.abort();
|
|
289
|
+
}
|
|
290
|
+
return this.#getResult();
|
|
291
|
+
}
|
|
292
|
+
#getResult() {
|
|
293
|
+
const urlAfterAction = this.#page.url();
|
|
294
|
+
return {
|
|
295
|
+
...(urlAfterAction !== this.#initialUrl
|
|
296
|
+
? { navigatedToUrl: urlAfterAction }
|
|
297
|
+
: {}),
|
|
298
|
+
dialogHandled: this.#dialogHandled,
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
export function getNetworkMultiplierFromString(condition) {
|
|
303
|
+
const puppeteerCondition = condition;
|
|
304
|
+
switch (puppeteerCondition) {
|
|
305
|
+
case 'Fast 4G':
|
|
306
|
+
return 1;
|
|
307
|
+
case 'Slow 4G':
|
|
308
|
+
return 2.5;
|
|
309
|
+
case 'Fast 3G':
|
|
310
|
+
return 5;
|
|
311
|
+
case 'Slow 3G':
|
|
312
|
+
return 10;
|
|
313
|
+
}
|
|
314
|
+
return 1;
|
|
315
|
+
}
|
|
316
|
+
//# sourceMappingURL=WaitForHelper.js.map
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { zod } from '../third_party/index.js';
|
|
7
|
+
const BYTE_UNITS = {
|
|
8
|
+
b: 1,
|
|
9
|
+
byte: 1,
|
|
10
|
+
bytes: 1,
|
|
11
|
+
k: 1000,
|
|
12
|
+
kb: 1000,
|
|
13
|
+
kib: 1024,
|
|
14
|
+
m: 1000 * 1000,
|
|
15
|
+
mb: 1000 * 1000,
|
|
16
|
+
mib: 1024 * 1024,
|
|
17
|
+
g: 1000 * 1000 * 1000,
|
|
18
|
+
gb: 1000 * 1000 * 1000,
|
|
19
|
+
gib: 1024 * 1024 * 1024,
|
|
20
|
+
t: 1000 * 1000 * 1000 * 1000,
|
|
21
|
+
tb: 1000 * 1000 * 1000 * 1000,
|
|
22
|
+
tib: 1024 * 1024 * 1024 * 1024,
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Parses a byte size string (e.g. "1M", "1MB", "500KB", "1.5GB", "1024") into bytes.
|
|
26
|
+
*/
|
|
27
|
+
export function parseByteSize(value) {
|
|
28
|
+
const trimmed = value.trim();
|
|
29
|
+
if (trimmed === '') {
|
|
30
|
+
throw new Error(`Invalid byte size: "${value}"`);
|
|
31
|
+
}
|
|
32
|
+
const match = trimmed.match(/^(\d+(?:\.\d+)?)\s*([a-zA-Z]+)?$/);
|
|
33
|
+
if (!match) {
|
|
34
|
+
throw new Error(`Invalid byte size format: "${value}". Expected a number or format like "1024", "1M", "1MB", "1G", "1GB".`);
|
|
35
|
+
}
|
|
36
|
+
const numMatch = match[1];
|
|
37
|
+
if (numMatch === undefined) {
|
|
38
|
+
throw new Error(`Invalid byte size: "${value}"`);
|
|
39
|
+
}
|
|
40
|
+
const num = Number(numMatch);
|
|
41
|
+
if (!Number.isFinite(num) || num < 0) {
|
|
42
|
+
throw new Error(`Invalid byte size: "${value}"`);
|
|
43
|
+
}
|
|
44
|
+
const unitMatch = match[2];
|
|
45
|
+
if (unitMatch === undefined) {
|
|
46
|
+
return Math.round(num);
|
|
47
|
+
}
|
|
48
|
+
const unit = unitMatch.toLowerCase();
|
|
49
|
+
const multiplier = BYTE_UNITS[unit];
|
|
50
|
+
if (multiplier === undefined) {
|
|
51
|
+
throw new Error(`Unknown unit "${unitMatch}" in "${value}". Supported units: B, KB, KiB, MB, MiB, GB, GiB, TB, TiB.`);
|
|
52
|
+
}
|
|
53
|
+
const bytes = Math.round(num * multiplier);
|
|
54
|
+
if (!Number.isFinite(bytes)) {
|
|
55
|
+
throw new Error(`Invalid byte size: "${value}"`);
|
|
56
|
+
}
|
|
57
|
+
return bytes;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Parses an inclusive byte-size range (e.g. "1MB", "1MB-2MB", "-1MB", "1MB-").
|
|
61
|
+
*/
|
|
62
|
+
export function parseByteSizeRange(value) {
|
|
63
|
+
const trimmed = value.trim();
|
|
64
|
+
if (!trimmed.includes('-')) {
|
|
65
|
+
return { min: parseByteSize(trimmed), max: undefined };
|
|
66
|
+
}
|
|
67
|
+
const parts = trimmed.split('-');
|
|
68
|
+
if (parts.length !== 2) {
|
|
69
|
+
throw new Error(`Invalid byte size range: "${value}". Expected a size or range like "1MB", "1MB-2MB", "-1MB", or "1MB-".`);
|
|
70
|
+
}
|
|
71
|
+
const minValue = parts[0];
|
|
72
|
+
const maxValue = parts[1];
|
|
73
|
+
if (minValue === undefined || maxValue === undefined) {
|
|
74
|
+
throw new Error(`Invalid byte size range: "${value}"`);
|
|
75
|
+
}
|
|
76
|
+
const minText = minValue.trim();
|
|
77
|
+
const maxText = maxValue.trim();
|
|
78
|
+
if (minText === '' && maxText === '') {
|
|
79
|
+
throw new Error(`Invalid byte size range: "${value}". At least one bound is required.`);
|
|
80
|
+
}
|
|
81
|
+
const min = minText === '' ? 0 : parseByteSize(minText);
|
|
82
|
+
const max = maxText === '' ? undefined : parseByteSize(maxText);
|
|
83
|
+
if (max !== undefined && min > max) {
|
|
84
|
+
throw new Error(`Invalid byte size range: "${value}". The lower bound must not exceed the upper bound.`);
|
|
85
|
+
}
|
|
86
|
+
return { min, max };
|
|
87
|
+
}
|
|
88
|
+
export function byteSizeRangeSchema(description) {
|
|
89
|
+
return zod
|
|
90
|
+
.string()
|
|
91
|
+
.transform((value, context) => {
|
|
92
|
+
try {
|
|
93
|
+
return parseByteSizeRange(value);
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
context.addIssue({
|
|
97
|
+
code: zod.ZodIssueCode.custom,
|
|
98
|
+
message: error instanceof Error ? error.message : 'Invalid byte size range',
|
|
99
|
+
});
|
|
100
|
+
return zod.NEVER;
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
.describe(description);
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=bytes.js.map
|