opera-devtools-mcp 0.2.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +104 -7
- package/build/src/McpContext.js +365 -365
- package/build/src/McpPage.js +475 -48
- package/build/src/McpResponse.js +462 -288
- package/build/src/SlimMcpResponse.js +1 -1
- package/build/src/TextSnapshot.js +101 -22
- package/build/src/ToolHandler.js +142 -20
- package/build/src/bin/check-latest-version.js +27 -1
- package/build/src/bin/chrome-devtools-cli-options.js +573 -10
- package/build/src/bin/chrome-devtools-mcp-cli-options.js +119 -32
- package/build/src/bin/chrome-devtools-mcp-main.js +50 -7
- package/build/src/bin/chrome-devtools-mcp.js +7 -4
- package/build/src/bin/chrome-devtools.js +57 -14
- package/build/src/bin/opera-devtools-cli-options.js +3 -829
- package/build/src/bin/opera-devtools-mcp-cli-options.js +3 -348
- package/build/src/bin/opera-devtools-mcp-main.js +3 -37
- package/build/src/bin/opera-devtools-mcp.js +4 -19
- package/build/src/bin/opera-devtools.js +4 -185
- package/build/src/browser.js +45 -5
- package/build/src/{PageCollector.js → collectors/PageCollector.js} +64 -133
- package/build/src/collectors/ServiceWorkerCollector.js +171 -0
- package/build/src/daemon/client.js +75 -17
- package/build/src/daemon/daemon.js +92 -30
- package/build/src/daemon/utils.js +24 -8
- package/build/src/{DevtoolsUtils.js → devtools/DevtoolsUtils.js} +94 -88
- package/build/src/devtools/McpHostBindingAdapter.js +165 -0
- package/build/src/{issue-descriptions.js → devtools/issueDescriptions.js} +8 -6
- package/build/src/formatters/ConsoleFormatter.js +44 -11
- package/build/src/formatters/HeapSnapshotFormatter.js +140 -9
- package/build/src/formatters/IssueFormatter.js +7 -7
- package/build/src/formatters/NetworkFormatter.js +10 -8
- package/build/src/index.js +101 -232
- package/build/src/opera/branding.js +34 -0
- package/build/src/opera/browserFlags.js +85 -0
- package/build/src/opera/browserLaunch.js +52 -0
- package/build/src/opera/policy.js +50 -0
- package/build/src/opera/serviceWorkerRetry.js +37 -0
- package/build/src/opera/toolHandlerHooks.js +39 -0
- package/build/src/{tools → opera/tools}/opera.js +9 -21
- package/build/src/processors/HeapSnapshotManager.js +258 -0
- package/build/src/{trace-processing/parse.js → processors/PerformanceTrace.js} +9 -9
- package/build/src/telemetry/ClearcutLogger.js +12 -119
- package/build/src/telemetry/WatchdogClient.js +5 -5
- package/build/src/telemetry/errors.js +1 -1
- package/build/src/telemetry/flagUtils.js +6 -6
- package/build/src/telemetry/{toolMetricsUtils.js → metricsRegistry.js} +4 -11
- package/build/src/telemetry/persistence.js +3 -3
- package/build/src/telemetry/transformation.js +184 -0
- package/build/src/telemetry/watchdog/ClearcutSender.js +11 -11
- package/build/src/telemetry/watchdog/main.js +6 -6
- package/build/src/third_party/THIRD_PARTY_NOTICES +3493 -0
- package/build/src/third_party/bundled-packages.json +9 -0
- package/build/src/third_party/devtools-formatter-worker.js +15340 -7
- package/build/src/third_party/devtools-heap-snapshot-worker.js +10337 -7
- package/build/src/third_party/index.js +179960 -26
- package/build/src/third_party/issue-descriptions/CoepCorpNotSameOrigin.md +2 -2
- package/build/src/third_party/issue-descriptions/CoepCorpNotSameOriginAfterDefaultedToSameOriginByCoep.md +3 -3
- package/build/src/third_party/issue-descriptions/CoepCorpNotSameSite.md +2 -2
- package/build/src/third_party/issue-descriptions/CoepFrameResourceNeedsCoepHeader.md +1 -1
- package/build/src/third_party/issue-descriptions/CompatibilityModeQuirks.md +1 -1
- package/build/src/third_party/issue-descriptions/CookieAttributeValueExceedsMaxSize.md +2 -2
- package/build/src/third_party/issue-descriptions/LowTextContrast.md +1 -1
- package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureErrorRead.md +1 -1
- package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureErrorSet.md +1 -1
- package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureWarnRead.md +1 -1
- package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureWarnSet.md +1 -1
- package/build/src/third_party/issue-descriptions/SameSiteUnspecifiedLaxAllowUnsafeRead.md +3 -3
- package/build/src/third_party/issue-descriptions/SameSiteUnspecifiedLaxAllowUnsafeSet.md +3 -3
- package/build/src/third_party/issue-descriptions/bounceTrackingMitigations.md +1 -1
- 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 +2 -2
- package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidHeader.md +2 -2
- package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidUrlPattern.md +3 -3
- package/build/src/third_party/issue-descriptions/connectionAllowlistItemNotInnerList.md +2 -2
- package/build/src/third_party/issue-descriptions/connectionAllowlistMoreThanOneList.md +2 -2
- package/build/src/third_party/issue-descriptions/connectionAllowlistReportingEndpointNotToken.md +1 -1
- package/build/src/third_party/issue-descriptions/cookieCrossSiteRedirectDowngrade.md +3 -3
- package/build/src/third_party/issue-descriptions/cookieExcludeBlockedWithinRelatedWebsiteSet.md +1 -1
- package/build/src/third_party/issue-descriptions/cookieExcludePortMismatch.md +1 -1
- package/build/src/third_party/issue-descriptions/cookieExcludeSchemeMismatch.md +1 -1
- package/build/src/third_party/issue-descriptions/cookieExcludeThirdPartyPhaseoutSet.md +1 -1
- package/build/src/third_party/issue-descriptions/cookieWarnThirdPartyPhaseoutRead.md +1 -1
- package/build/src/third_party/issue-descriptions/corsAllowCredentialsRequired.md +1 -1
- package/build/src/third_party/issue-descriptions/corsDisabledScheme.md +2 -2
- package/build/src/third_party/issue-descriptions/corsDisallowedByMode.md +2 -2
- package/build/src/third_party/issue-descriptions/corsHeaderDisallowedByPreflightResponse.md +1 -1
- package/build/src/third_party/issue-descriptions/corsInvalidHeaderValues.md +3 -3
- package/build/src/third_party/issue-descriptions/corsLocalNetworkAccessPermissionDenied.md +1 -1
- package/build/src/third_party/issue-descriptions/corsMethodDisallowedByPreflightResponse.md +1 -1
- package/build/src/third_party/issue-descriptions/corsNoCorsRedirectModeNotFollow.md +1 -1
- package/build/src/third_party/issue-descriptions/corsOriginMismatch.md +3 -3
- package/build/src/third_party/issue-descriptions/corsPreflightResponseInvalid.md +2 -2
- package/build/src/third_party/issue-descriptions/corsRedirectContainsCredentials.md +3 -3
- package/build/src/third_party/issue-descriptions/corsWildcardOriginNotAllowed.md +4 -3
- package/build/src/third_party/issue-descriptions/cspEvalViolation.md +4 -4
- package/build/src/third_party/issue-descriptions/cspInlineViolation.md +2 -2
- package/build/src/third_party/issue-descriptions/cspTrustedTypesPolicyViolation.md +2 -2
- package/build/src/third_party/issue-descriptions/cspTrustedTypesSinkViolation.md +4 -4
- package/build/src/third_party/issue-descriptions/cspURLViolation.md +4 -4
- 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/federatedAuthRequestAccountsHttpNotFound.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsInvalidResponse.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsNoResponse.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestApprovalDeclined.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestCanceled.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestErrorFetchingSignin.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestErrorIdToken.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenHttpNotFound.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenInvalidRequest.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenInvalidResponse.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenNoResponse.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestInvalidSigninResponse.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestHttpNotFound.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestInvalidResponse.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestNoResponse.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthRequestTooManyRequests.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestInvalidAccountsResponse.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestInvalidConfigOrWellKnown.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoAccountSharingPermission.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoApiPermission.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoReturningUserFromFetchedAccounts.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotIframe.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotPotentiallyTrustworthy.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotSameOrigin.md +1 -1
- package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotSignedInWithIdp.md +1 -1
- package/build/src/third_party/issue-descriptions/fetchingPartitionedBlobURL.md +2 -2
- package/build/src/third_party/issue-descriptions/genericBackUINavigationWouldSkipAd.md +4 -0
- package/build/src/third_party/issue-descriptions/genericFormAriaLabelledByToNonExistingIdError.md +2 -2
- package/build/src/third_party/issue-descriptions/genericFormAutocompleteAttributeEmptyError.md +1 -1
- package/build/src/third_party/issue-descriptions/genericFormDuplicateIdForInputError.md +1 -1
- package/build/src/third_party/issue-descriptions/genericFormEmptyIdAndNameAttributesForInputError.md +2 -2
- package/build/src/third_party/issue-descriptions/genericFormInputAssignedAutocompleteValueToIdOrNameAttributeError.md +2 -2
- package/build/src/third_party/issue-descriptions/genericFormInputHasWrongButWellIntendedAutocompleteValueError.md +1 -1
- package/build/src/third_party/issue-descriptions/genericFormInputWithNoLabelError.md +1 -1
- package/build/src/third_party/issue-descriptions/genericFormLabelForMatchesNonExistingIdError.md +2 -2
- package/build/src/third_party/issue-descriptions/genericFormLabelForNameError.md +1 -1
- package/build/src/third_party/issue-descriptions/genericFormLabelHasNeitherForNorNestedInputError.md +1 -1
- package/build/src/third_party/issue-descriptions/genericFormModelContextMissingToolName.md +1 -1
- package/build/src/third_party/issue-descriptions/genericFormModelContextParameterMissingName.md +1 -1
- package/build/src/third_party/issue-descriptions/genericFormModelContextRequiredParameterMissingName.md +1 -1
- package/build/src/third_party/issue-descriptions/genericNavigationEntryMarkedSkippable.md +2 -2
- package/build/src/third_party/issue-descriptions/heavyAd.md +1 -1
- package/build/src/third_party/issue-descriptions/lazyLoadImageZeroSize.md +7 -0
- package/build/src/third_party/issue-descriptions/navigatingPartitionedBlobURL.md +3 -3
- package/build/src/third_party/issue-descriptions/permissionElementActivationDisabled.md +1 -1
- package/build/src/third_party/issue-descriptions/permissionElementActivationDisabledWithOccluder.md +1 -1
- package/build/src/third_party/issue-descriptions/permissionElementActivationDisabledWithOccluderParent.md +1 -1
- package/build/src/third_party/issue-descriptions/permissionElementFencedFrameDisallowed.md +2 -2
- package/build/src/third_party/issue-descriptions/permissionElementFontSizeTooLarge.md +2 -2
- package/build/src/third_party/issue-descriptions/permissionElementFontSizeTooSmall.md +2 -2
- package/build/src/third_party/issue-descriptions/permissionElementInsetBoxShadowUnsupported.md +1 -1
- package/build/src/third_party/issue-descriptions/permissionElementInvalidDisplayStyle.md +2 -2
- package/build/src/third_party/issue-descriptions/permissionElementInvalidSizeValue.md +2 -2
- package/build/src/third_party/issue-descriptions/permissionElementInvalidType.md +2 -2
- package/build/src/third_party/issue-descriptions/permissionElementInvalidTypeActivation.md +2 -2
- package/build/src/third_party/issue-descriptions/permissionElementNonOpaqueColor.md +1 -1
- package/build/src/third_party/issue-descriptions/permissionElementPaddingBottomUnsupported.md +2 -2
- package/build/src/third_party/issue-descriptions/permissionElementPaddingRightUnsupported.md +2 -2
- package/build/src/third_party/issue-descriptions/permissionElementRequestInProgress.md +2 -2
- package/build/src/third_party/issue-descriptions/permissionElementSecurityChecksFailed.md +1 -1
- package/build/src/third_party/issue-descriptions/permissionElementTypeNotSupported.md +2 -2
- package/build/src/third_party/issue-descriptions/permissionElementUntrustedEvent.md +1 -1
- package/build/src/third_party/issue-descriptions/placeholderDescriptionForInvisibleIssues.md +1 -1
- package/build/src/third_party/issue-descriptions/selectElementAccessibilityDisallowedOptGroupChild.md +1 -1
- package/build/src/third_party/issue-descriptions/selectElementAccessibilityDisallowedSelectChild.md +1 -1
- package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentAttributesSelectDescendant.md +1 -1
- package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentLegendChild.md +1 -1
- package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentOptionChild.md +1 -1
- package/build/src/third_party/issue-descriptions/selectElementAccessibilityNonPhrasingContentOptionChild.md +1 -1
- package/build/src/third_party/issue-descriptions/selectivePermissionsIntervention.md +3 -3
- package/build/src/third_party/issue-descriptions/sharedArrayBuffer.md +1 -1
- package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorCrossOriginNoCorsRequest.md +1 -1
- package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorMatchingDictionaryNotUsed.md +1 -1
- package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorUnexpectedContentDictionaryHeader.md +1 -1
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorCossOriginNoCorsRequest.md +1 -1
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorDisallowedBySettings.md +1 -1
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorExpiredResponse.md +1 -1
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorFeatureDisabled.md +2 -2
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorInvalidStructuredHeader.md +1 -1
- package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNavigationRequest.md +2 -2
- package/build/src/third_party/issue-descriptions/sriInvalidSignatureHeader.md +4 -4
- package/build/src/third_party/issue-descriptions/sriInvalidSignatureInputHeader.md +4 -4
- package/build/src/third_party/issue-descriptions/sriMissingSignatureHeader.md +1 -1
- package/build/src/third_party/issue-descriptions/sriMissingSignatureInputHeader.md +2 -2
- package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsIncorrectLength.md +2 -2
- package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsNotByteSequence.md +4 -4
- package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsParameterized.md +4 -4
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidComponentName.md +1 -1
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidComponentType.md +2 -2
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidDerivedComponentParameter.md +1 -1
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidHeaderComponentParameter.md +1 -1
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidParameter.md +2 -2
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderKeyIdLength.md +5 -5
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderMissingLabel.md +3 -3
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderMissingRequiredParameters.md +2 -2
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderValueMissingComponents.md +2 -2
- package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderValueNotInnerList.md +2 -2
- package/build/src/third_party/issue-descriptions/sriValidationFailedIntegrityMismatch.md +4 -4
- package/build/src/third_party/issue-descriptions/sriValidationFailedInvalidLength.md +3 -3
- package/build/src/third_party/issue-descriptions/sriValidationFailedSignatureExpired.md +2 -2
- package/build/src/third_party/issue-descriptions/sriValidationFailedSignatureMismatch.md +2 -2
- package/build/src/third_party/issue-descriptions/stylesheetLateImport.md +1 -1
- package/build/src/third_party/issue-descriptions/summaryElementAccessibilityInteractiveContentSummaryDescendant.md +1 -1
- package/build/src/third_party/issue-descriptions/unencodedDigestIncorrectDigestLength.md +2 -2
- package/build/src/third_party/issue-descriptions/unencodedDigestIncorrectDigestType.md +3 -3
- package/build/src/third_party/issue-descriptions/unencodedDigestMalformedDictionary.md +2 -2
- package/build/src/third_party/issue-descriptions/unencodedDigestUnknownAlgorithm.md +1 -1
- package/build/src/third_party/lighthouse-devtools-mcp-bundle.js +3177 -6340
- package/build/src/tools/ToolDefinition.js +2 -2
- package/build/src/tools/categories.js +3 -0
- package/build/src/tools/console.js +13 -0
- package/build/src/tools/emulation.js +30 -3
- package/build/src/tools/extensions.js +8 -1
- package/build/src/tools/input.js +246 -128
- package/build/src/tools/lighthouse.js +14 -7
- package/build/src/tools/memory.js +289 -25
- package/build/src/tools/network.js +10 -7
- package/build/src/tools/pages.js +33 -92
- package/build/src/tools/performance.js +67 -52
- package/build/src/tools/pwa.js +128 -0
- package/build/src/tools/screencast.js +35 -12
- package/build/src/tools/screenshot.js +234 -75
- package/build/src/tools/script.js +130 -45
- package/build/src/tools/slim/tools.js +3 -0
- package/build/src/tools/snapshot.js +7 -4
- package/build/src/tools/thirdPartyDeveloper.js +19 -9
- package/build/src/tools/tools.js +3 -1
- package/build/src/tools/webmcp.js +3 -1
- package/build/src/utils/WaitForHelper.js +299 -0
- package/build/src/utils/check-for-updates.js +8 -2
- package/build/src/utils/files.js +42 -3
- package/build/src/utils/logger.js +51 -0
- package/build/src/utils/polyfill.js +11 -0
- package/build/src/utils/url.js +43 -0
- package/build/src/version.js +1 -1
- package/package.json +42 -33
- package/build/src/DevToolsConnectionAdapter.js +0 -70
- package/build/src/HeapSnapshotManager.js +0 -110
- package/build/src/Mutex.js +0 -38
- package/build/src/WaitForHelper.js +0 -195
- package/build/src/bin/cliDefinitions.js +0 -616
- package/build/src/logger.js +0 -37
- package/build/src/polyfill.js +0 -8
- package/build/src/telemetry/metricUtils.js +0 -15
- package/build/src/third_party/issue-descriptions/SameSiteExcludeContextDowngradeRead.md +0 -8
- package/build/src/third_party/issue-descriptions/SameSiteExcludeContextDowngradeSet.md +0 -8
- package/build/src/third_party/issue-descriptions/SameSiteExcludeNavigationContextDowngrade.md +0 -8
- package/build/src/third_party/issue-descriptions/SameSiteWarnCrossDowngradeRead.md +0 -8
- package/build/src/third_party/issue-descriptions/SameSiteWarnCrossDowngradeSet.md +0 -8
- package/build/src/third_party/issue-descriptions/SameSiteWarnStrictLaxDowngradeStrict.md +0 -8
- package/build/src/third_party/issue-descriptions/arInsecureContext.md +0 -7
- package/build/src/third_party/issue-descriptions/arInvalidInfoHeader.md +0 -5
- package/build/src/third_party/issue-descriptions/arInvalidRegisterOsSourceHeader.md +0 -5
- package/build/src/third_party/issue-descriptions/arInvalidRegisterOsTriggerHeader.md +0 -5
- package/build/src/third_party/issue-descriptions/arInvalidRegisterSourceHeader.md +0 -5
- package/build/src/third_party/issue-descriptions/arInvalidRegisterTriggerHeader.md +0 -5
- package/build/src/third_party/issue-descriptions/arNavigationRegistrationUniqueScopeAlreadySet.md +0 -5
- package/build/src/third_party/issue-descriptions/arNavigationRegistrationWithoutTransientUserActivation.md +0 -6
- package/build/src/third_party/issue-descriptions/arNoRegisterOsSourceHeader.md +0 -5
- package/build/src/third_party/issue-descriptions/arNoRegisterOsTriggerHeader.md +0 -5
- package/build/src/third_party/issue-descriptions/arNoRegisterSourceHeader.md +0 -5
- package/build/src/third_party/issue-descriptions/arNoRegisterTriggerHeader.md +0 -5
- package/build/src/third_party/issue-descriptions/arNoWebOrOsSupport.md +0 -4
- package/build/src/third_party/issue-descriptions/arOsSourceIgnored.md +0 -18
- package/build/src/third_party/issue-descriptions/arOsTriggerIgnored.md +0 -19
- package/build/src/third_party/issue-descriptions/arPermissionPolicyDisabled.md +0 -8
- package/build/src/third_party/issue-descriptions/arSourceAndTriggerHeaders.md +0 -9
- package/build/src/third_party/issue-descriptions/arSourceIgnored.md +0 -13
- package/build/src/third_party/issue-descriptions/arTriggerIgnored.md +0 -12
- package/build/src/third_party/issue-descriptions/arUntrustworthyReportingOrigin.md +0 -10
- package/build/src/third_party/issue-descriptions/arWebAndOsHeaders.md +0 -11
- package/build/src/utils/string.js +0 -37
- package/build/src/utils/types.js +0 -7
package/build/src/tools/input.js
CHANGED
|
@@ -3,10 +3,61 @@
|
|
|
3
3
|
* Copyright 2025 Google LLC
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
-
|
|
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
|
+
});
|
|
7
58
|
import { zod } from '../third_party/index.js';
|
|
8
59
|
import { parseKey } from '../utils/keyboard.js';
|
|
9
|
-
import {
|
|
60
|
+
import { logger } from '../utils/logger.js';
|
|
10
61
|
import { ToolCategory } from './categories.js';
|
|
11
62
|
import { definePageTool } from './ToolDefinition.js';
|
|
12
63
|
const dblClickSchema = zod
|
|
@@ -22,47 +73,47 @@ const submitKeySchema = zod
|
|
|
22
73
|
.optional()
|
|
23
74
|
.describe('Optional key to press after typing. E.g., "Enter", "Tab", "Escape"');
|
|
24
75
|
function handleActionError(error, uid) {
|
|
25
|
-
logger('failed to act using a locator', error);
|
|
76
|
+
logger?.('failed to act using a locator', error);
|
|
26
77
|
throw new Error(`Failed to interact with the element with uid ${uid}. The element did not become interactive within the configured timeout.`, {
|
|
27
78
|
cause: error,
|
|
28
79
|
});
|
|
29
80
|
}
|
|
30
81
|
async function selectNativeSelectOption(handle) {
|
|
31
|
-
const
|
|
32
|
-
if (!(node instanceof HTMLOptionElement)) {
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
const select = node.closest('select');
|
|
36
|
-
if (!select || select.multiple || select.disabled || node.disabled) {
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
const parentElement = node.parentElement;
|
|
40
|
-
if (parentElement instanceof HTMLOptGroupElement &&
|
|
41
|
-
parentElement.disabled) {
|
|
42
|
-
return null;
|
|
43
|
-
}
|
|
44
|
-
return select;
|
|
45
|
-
});
|
|
82
|
+
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
46
83
|
try {
|
|
47
|
-
const
|
|
84
|
+
const selectHandle = __addDisposableResource(env_1, await handle.evaluateHandle(node => {
|
|
85
|
+
if (!(node instanceof HTMLOptionElement)) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
const select = node.closest('select');
|
|
89
|
+
if (!select || select.multiple || select.disabled || node.disabled) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
const parentElement = node.parentElement;
|
|
93
|
+
if (parentElement instanceof HTMLOptGroupElement &&
|
|
94
|
+
parentElement.disabled) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
return select;
|
|
98
|
+
}), false);
|
|
99
|
+
const select = __addDisposableResource(env_1, selectHandle.asElement(), false);
|
|
48
100
|
if (!select) {
|
|
49
101
|
return false;
|
|
50
102
|
}
|
|
51
|
-
const valueHandle = await handle.getProperty('value');
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
57
|
-
await select.asLocator().fill(value);
|
|
58
|
-
}
|
|
59
|
-
finally {
|
|
60
|
-
void valueHandle.dispose();
|
|
103
|
+
const valueHandle = __addDisposableResource(env_1, await handle.getProperty('value'), false);
|
|
104
|
+
const value = await valueHandle.jsonValue();
|
|
105
|
+
if (typeof value !== 'string') {
|
|
106
|
+
return false;
|
|
61
107
|
}
|
|
108
|
+
await select.asLocator().fill(value);
|
|
62
109
|
return true;
|
|
63
110
|
}
|
|
111
|
+
catch (e_1) {
|
|
112
|
+
env_1.error = e_1;
|
|
113
|
+
env_1.hasError = true;
|
|
114
|
+
}
|
|
64
115
|
finally {
|
|
65
|
-
|
|
116
|
+
__disposeResources(env_1);
|
|
66
117
|
}
|
|
67
118
|
}
|
|
68
119
|
export const click = definePageTool({
|
|
@@ -80,34 +131,42 @@ export const click = definePageTool({
|
|
|
80
131
|
includeSnapshot: includeSnapshotSchema,
|
|
81
132
|
},
|
|
82
133
|
blockedByDialog: true,
|
|
134
|
+
verifyFilesSchema: {},
|
|
83
135
|
handler: async (request, response) => {
|
|
84
|
-
const
|
|
85
|
-
const handle = await request.page.getElementByUid(uid);
|
|
86
|
-
const aXNode = request.page.getAXNodeByUid(uid);
|
|
87
|
-
const shouldSelectNativeOption = !request.params.dblClick && aXNode?.role === 'option';
|
|
136
|
+
const env_2 = { stack: [], error: void 0, hasError: false };
|
|
88
137
|
try {
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
await
|
|
95
|
-
|
|
138
|
+
const uid = request.params.uid;
|
|
139
|
+
const handle = __addDisposableResource(env_2, await request.page.getElementByUid(uid), false);
|
|
140
|
+
const aXNode = request.page.getAXNodeByUid(uid);
|
|
141
|
+
const shouldSelectNativeOption = !request.params.dblClick && aXNode?.role === 'option';
|
|
142
|
+
try {
|
|
143
|
+
const result = await request.page.waitForEventsAfterAction(async () => {
|
|
144
|
+
if (shouldSelectNativeOption &&
|
|
145
|
+
(await selectNativeSelectOption(handle))) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
await handle.asLocator().click({
|
|
149
|
+
count: request.params.dblClick ? 2 : 1,
|
|
150
|
+
});
|
|
96
151
|
});
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
152
|
+
response.appendResponseLine(request.params.dblClick
|
|
153
|
+
? `Successfully double clicked on the element`
|
|
154
|
+
: `Successfully clicked on the element`);
|
|
155
|
+
response.attachWaitForResult(result);
|
|
156
|
+
if (request.params.includeSnapshot) {
|
|
157
|
+
response.includeSnapshot();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
handleActionError(error, uid);
|
|
104
162
|
}
|
|
105
163
|
}
|
|
106
|
-
catch (
|
|
107
|
-
|
|
164
|
+
catch (e_2) {
|
|
165
|
+
env_2.error = e_2;
|
|
166
|
+
env_2.hasError = true;
|
|
108
167
|
}
|
|
109
168
|
finally {
|
|
110
|
-
|
|
169
|
+
__disposeResources(env_2);
|
|
111
170
|
}
|
|
112
171
|
},
|
|
113
172
|
});
|
|
@@ -126,17 +185,18 @@ export const clickAt = definePageTool({
|
|
|
126
185
|
includeSnapshot: includeSnapshotSchema,
|
|
127
186
|
},
|
|
128
187
|
blockedByDialog: true,
|
|
188
|
+
verifyFilesSchema: {},
|
|
129
189
|
handler: async (request, response) => {
|
|
130
190
|
const page = request.page;
|
|
131
191
|
const result = await page.waitForEventsAfterAction(async () => {
|
|
132
192
|
await page.pptrPage.mouse.click(request.params.x, request.params.y, {
|
|
133
|
-
|
|
193
|
+
count: request.params.dblClick ? 2 : 1,
|
|
134
194
|
});
|
|
135
195
|
});
|
|
136
196
|
response.appendResponseLine(request.params.dblClick
|
|
137
197
|
? `Successfully double clicked at the coordinates`
|
|
138
198
|
: `Successfully clicked at the coordinates`);
|
|
139
|
-
|
|
199
|
+
response.attachWaitForResult(result);
|
|
140
200
|
if (request.params.includeSnapshot) {
|
|
141
201
|
response.includeSnapshot();
|
|
142
202
|
}
|
|
@@ -156,24 +216,32 @@ export const hover = definePageTool({
|
|
|
156
216
|
includeSnapshot: includeSnapshotSchema,
|
|
157
217
|
},
|
|
158
218
|
blockedByDialog: true,
|
|
219
|
+
verifyFilesSchema: {},
|
|
159
220
|
handler: async (request, response) => {
|
|
160
|
-
const
|
|
161
|
-
const handle = await request.page.getElementByUid(uid);
|
|
221
|
+
const env_3 = { stack: [], error: void 0, hasError: false };
|
|
162
222
|
try {
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
response.
|
|
223
|
+
const uid = request.params.uid;
|
|
224
|
+
const handle = __addDisposableResource(env_3, await request.page.getElementByUid(uid), false);
|
|
225
|
+
try {
|
|
226
|
+
const result = await request.page.waitForEventsAfterAction(async () => {
|
|
227
|
+
await handle.asLocator().hover();
|
|
228
|
+
});
|
|
229
|
+
response.appendResponseLine(`Successfully hovered over the element`);
|
|
230
|
+
response.attachWaitForResult(result);
|
|
231
|
+
if (request.params.includeSnapshot) {
|
|
232
|
+
response.includeSnapshot();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
catch (error) {
|
|
236
|
+
handleActionError(error, uid);
|
|
170
237
|
}
|
|
171
238
|
}
|
|
172
|
-
catch (
|
|
173
|
-
|
|
239
|
+
catch (e_3) {
|
|
240
|
+
env_3.error = e_3;
|
|
241
|
+
env_3.hasError = true;
|
|
174
242
|
}
|
|
175
243
|
finally {
|
|
176
|
-
|
|
244
|
+
__disposeResources(env_3);
|
|
177
245
|
}
|
|
178
246
|
},
|
|
179
247
|
});
|
|
@@ -185,26 +253,36 @@ async function selectOption(handle, aXNode, value) {
|
|
|
185
253
|
let optionFound = false;
|
|
186
254
|
for (const child of aXNode.children) {
|
|
187
255
|
if (child.role === 'option' && child.name === value && child.value) {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
256
|
+
const env_4 = { stack: [], error: void 0, hasError: false };
|
|
257
|
+
try {
|
|
258
|
+
optionFound = true;
|
|
259
|
+
const childHandle = __addDisposableResource(env_4, await child.elementHandle(), false);
|
|
260
|
+
if (childHandle) {
|
|
261
|
+
const env_5 = { stack: [], error: void 0, hasError: false };
|
|
193
262
|
try {
|
|
263
|
+
const childValueHandle = __addDisposableResource(env_5, await childHandle.getProperty('value'), false);
|
|
194
264
|
const childValue = await childValueHandle.jsonValue();
|
|
195
|
-
if (childValue) {
|
|
196
|
-
await handle.asLocator().fill(childValue
|
|
265
|
+
if (typeof childValue === 'string') {
|
|
266
|
+
await handle.asLocator().fill(childValue);
|
|
197
267
|
}
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
catch (e_4) {
|
|
271
|
+
env_5.error = e_4;
|
|
272
|
+
env_5.hasError = true;
|
|
198
273
|
}
|
|
199
274
|
finally {
|
|
200
|
-
|
|
275
|
+
__disposeResources(env_5);
|
|
201
276
|
}
|
|
202
|
-
break;
|
|
203
|
-
}
|
|
204
|
-
finally {
|
|
205
|
-
void childHandle.dispose();
|
|
206
277
|
}
|
|
207
278
|
}
|
|
279
|
+
catch (e_5) {
|
|
280
|
+
env_4.error = e_5;
|
|
281
|
+
env_4.hasError = true;
|
|
282
|
+
}
|
|
283
|
+
finally {
|
|
284
|
+
__disposeResources(env_4);
|
|
285
|
+
}
|
|
208
286
|
}
|
|
209
287
|
}
|
|
210
288
|
if (!optionFound) {
|
|
@@ -215,43 +293,50 @@ function hasOptionChildren(aXNode) {
|
|
|
215
293
|
return aXNode.children.some(child => child.role === 'option');
|
|
216
294
|
}
|
|
217
295
|
async function fillFormElement(uid, value, context, page) {
|
|
218
|
-
const
|
|
296
|
+
const env_6 = { stack: [], error: void 0, hasError: false };
|
|
219
297
|
try {
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
298
|
+
const handle = __addDisposableResource(env_6, await page.getElementByUid(uid), false);
|
|
299
|
+
try {
|
|
300
|
+
const aXNode = page.getAXNodeByUid(uid);
|
|
301
|
+
// We assume that combobox needs to be handled as select if it has
|
|
302
|
+
// role='combobox' and option children.
|
|
303
|
+
if (aXNode && aXNode.role === 'combobox' && hasOptionChildren(aXNode)) {
|
|
304
|
+
await selectOption(handle, aXNode, value);
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
const isToggle = await handle.evaluate(el => {
|
|
308
|
+
if (el instanceof HTMLInputElement) {
|
|
309
|
+
return el.type === 'checkbox' || el.type === 'radio';
|
|
310
|
+
}
|
|
311
|
+
const role = el.getAttribute('role');
|
|
312
|
+
return role === 'checkbox' || role === 'radio' || role === 'switch';
|
|
313
|
+
});
|
|
314
|
+
if (isToggle) {
|
|
315
|
+
if (['true', 'false'].includes(value)) {
|
|
316
|
+
await handle.asLocator().fill(value === 'true');
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
throw new Error(`Checkboxes, radio boxes and toggles require "true" or "false" value, but ${value} was used`);
|
|
320
|
+
}
|
|
237
321
|
}
|
|
238
322
|
else {
|
|
239
|
-
|
|
323
|
+
// Increase timeout for longer input values.
|
|
324
|
+
const timeoutPerChar = 10; // ms
|
|
325
|
+
const fillTimeout = page.pptrPage.getDefaultTimeout() + value.length * timeoutPerChar;
|
|
326
|
+
await handle.asLocator().setTimeout(fillTimeout).fill(value);
|
|
240
327
|
}
|
|
241
328
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
const fillTimeout = page.pptrPage.getDefaultTimeout() + value.length * timeoutPerChar;
|
|
246
|
-
await handle.asLocator().setTimeout(fillTimeout).fill(value);
|
|
247
|
-
}
|
|
329
|
+
}
|
|
330
|
+
catch (error) {
|
|
331
|
+
handleActionError(error, uid);
|
|
248
332
|
}
|
|
249
333
|
}
|
|
250
|
-
catch (
|
|
251
|
-
|
|
334
|
+
catch (e_6) {
|
|
335
|
+
env_6.error = e_6;
|
|
336
|
+
env_6.hasError = true;
|
|
252
337
|
}
|
|
253
338
|
finally {
|
|
254
|
-
|
|
339
|
+
__disposeResources(env_6);
|
|
255
340
|
}
|
|
256
341
|
}
|
|
257
342
|
export const fill = definePageTool({
|
|
@@ -271,13 +356,14 @@ export const fill = definePageTool({
|
|
|
271
356
|
includeSnapshot: includeSnapshotSchema,
|
|
272
357
|
},
|
|
273
358
|
blockedByDialog: true,
|
|
359
|
+
verifyFilesSchema: {},
|
|
274
360
|
handler: async (request, response, context) => {
|
|
275
361
|
const page = request.page;
|
|
276
362
|
const result = await page.waitForEventsAfterAction(async () => {
|
|
277
363
|
await fillFormElement(request.params.uid, request.params.value, context, page);
|
|
278
364
|
});
|
|
279
365
|
response.appendResponseLine(`Successfully filled out the element`);
|
|
280
|
-
|
|
366
|
+
response.attachWaitForResult(result);
|
|
281
367
|
if (request.params.includeSnapshot) {
|
|
282
368
|
response.includeSnapshot();
|
|
283
369
|
}
|
|
@@ -295,6 +381,7 @@ export const typeText = definePageTool({
|
|
|
295
381
|
submitKey: submitKeySchema,
|
|
296
382
|
},
|
|
297
383
|
blockedByDialog: true,
|
|
384
|
+
verifyFilesSchema: {},
|
|
298
385
|
handler: async (request, response) => {
|
|
299
386
|
const page = request.page;
|
|
300
387
|
const result = await page.waitForEventsAfterAction(async () => {
|
|
@@ -304,7 +391,7 @@ export const typeText = definePageTool({
|
|
|
304
391
|
}
|
|
305
392
|
});
|
|
306
393
|
response.appendResponseLine(`Typed text "${request.params.text}${request.params.submitKey ? ` + ${request.params.submitKey}` : ''}"`);
|
|
307
|
-
|
|
394
|
+
response.attachWaitForResult(result);
|
|
308
395
|
},
|
|
309
396
|
});
|
|
310
397
|
export const drag = definePageTool({
|
|
@@ -320,24 +407,29 @@ export const drag = definePageTool({
|
|
|
320
407
|
includeSnapshot: includeSnapshotSchema,
|
|
321
408
|
},
|
|
322
409
|
blockedByDialog: true,
|
|
410
|
+
verifyFilesSchema: {},
|
|
323
411
|
handler: async (request, response) => {
|
|
324
|
-
const
|
|
325
|
-
const toHandle = await request.page.getElementByUid(request.params.to_uid);
|
|
412
|
+
const env_7 = { stack: [], error: void 0, hasError: false };
|
|
326
413
|
try {
|
|
414
|
+
const fromHandle = __addDisposableResource(env_7, await request.page.getElementByUid(request.params.from_uid), false);
|
|
415
|
+
const toHandle = __addDisposableResource(env_7, await request.page.getElementByUid(request.params.to_uid), false);
|
|
327
416
|
const result = await request.page.waitForEventsAfterAction(async () => {
|
|
328
417
|
await fromHandle.drag(toHandle);
|
|
329
418
|
await new Promise(resolve => setTimeout(resolve, 50));
|
|
330
419
|
await toHandle.drop(fromHandle);
|
|
331
420
|
});
|
|
332
421
|
response.appendResponseLine(`Successfully dragged an element`);
|
|
333
|
-
|
|
422
|
+
response.attachWaitForResult(result);
|
|
334
423
|
if (request.params.includeSnapshot) {
|
|
335
424
|
response.includeSnapshot();
|
|
336
425
|
}
|
|
337
426
|
}
|
|
427
|
+
catch (e_7) {
|
|
428
|
+
env_7.error = e_7;
|
|
429
|
+
env_7.hasError = true;
|
|
430
|
+
}
|
|
338
431
|
finally {
|
|
339
|
-
|
|
340
|
-
void toHandle.dispose();
|
|
432
|
+
__disposeResources(env_7);
|
|
341
433
|
}
|
|
342
434
|
},
|
|
343
435
|
});
|
|
@@ -362,6 +454,7 @@ export const fillForm = definePageTool({
|
|
|
362
454
|
includeSnapshot: includeSnapshotSchema,
|
|
363
455
|
},
|
|
364
456
|
blockedByDialog: true,
|
|
457
|
+
verifyFilesSchema: {},
|
|
365
458
|
handler: async (request, response, context) => {
|
|
366
459
|
const page = request.page;
|
|
367
460
|
let lastResult = {};
|
|
@@ -371,7 +464,7 @@ export const fillForm = definePageTool({
|
|
|
371
464
|
});
|
|
372
465
|
}
|
|
373
466
|
response.appendResponseLine(`Successfully filled out the form`);
|
|
374
|
-
|
|
467
|
+
response.attachWaitForResult(lastResult);
|
|
375
468
|
if (request.params.includeSnapshot) {
|
|
376
469
|
response.includeSnapshot();
|
|
377
470
|
}
|
|
@@ -388,17 +481,28 @@ export const uploadFile = definePageTool({
|
|
|
388
481
|
uid: zod
|
|
389
482
|
.string()
|
|
390
483
|
.describe('The uid of the file input element or an element that will open file chooser on the page from the page content snapshot'),
|
|
391
|
-
|
|
484
|
+
filePaths: zod
|
|
485
|
+
.array(zod.string())
|
|
486
|
+
.min(1)
|
|
487
|
+
.describe('One or more files paths to upload. File paths have to be local to the browser instance (not the MCP).'),
|
|
392
488
|
includeSnapshot: includeSnapshotSchema,
|
|
393
489
|
},
|
|
394
490
|
blockedByDialog: true,
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
491
|
+
// We do not validate file paths for remote browser instances
|
|
492
|
+
// because they are on the remote host and not accessed by the MCP server.
|
|
493
|
+
verifyFilesSchema: {
|
|
494
|
+
filePaths: {
|
|
495
|
+
local: true,
|
|
496
|
+
remote: false,
|
|
497
|
+
},
|
|
498
|
+
},
|
|
499
|
+
handler: async (request, response) => {
|
|
500
|
+
const env_8 = { stack: [], error: void 0, hasError: false };
|
|
399
501
|
try {
|
|
502
|
+
const { uid, filePaths } = request.params;
|
|
503
|
+
const handle = __addDisposableResource(env_8, (await request.page.getElementByUid(uid)), false);
|
|
400
504
|
try {
|
|
401
|
-
await handle.uploadFile(
|
|
505
|
+
await handle.uploadFile(...filePaths);
|
|
402
506
|
}
|
|
403
507
|
catch {
|
|
404
508
|
// Some sites use a proxy element to trigger file upload instead of
|
|
@@ -409,7 +513,7 @@ export const uploadFile = definePageTool({
|
|
|
409
513
|
request.page.pptrPage.waitForFileChooser({ timeout: 3000 }),
|
|
410
514
|
handle.asLocator().click(),
|
|
411
515
|
]);
|
|
412
|
-
await fileChooser.accept(
|
|
516
|
+
await fileChooser.accept(filePaths);
|
|
413
517
|
}
|
|
414
518
|
catch {
|
|
415
519
|
throw new Error(`Failed to upload file. The element could not accept the file directly, and clicking it did not trigger a file chooser.`);
|
|
@@ -418,10 +522,14 @@ export const uploadFile = definePageTool({
|
|
|
418
522
|
if (request.params.includeSnapshot) {
|
|
419
523
|
response.includeSnapshot();
|
|
420
524
|
}
|
|
421
|
-
response.appendResponseLine(`File uploaded from ${
|
|
525
|
+
response.appendResponseLine(`File uploaded from ${filePaths.join(', ')}.`);
|
|
526
|
+
}
|
|
527
|
+
catch (e_8) {
|
|
528
|
+
env_8.error = e_8;
|
|
529
|
+
env_8.hasError = true;
|
|
422
530
|
}
|
|
423
531
|
finally {
|
|
424
|
-
|
|
532
|
+
__disposeResources(env_8);
|
|
425
533
|
}
|
|
426
534
|
},
|
|
427
535
|
});
|
|
@@ -439,21 +547,31 @@ export const pressKey = definePageTool({
|
|
|
439
547
|
includeSnapshot: includeSnapshotSchema,
|
|
440
548
|
},
|
|
441
549
|
blockedByDialog: true,
|
|
550
|
+
verifyFilesSchema: {},
|
|
442
551
|
handler: async (request, response) => {
|
|
443
552
|
const page = request.page;
|
|
444
553
|
const tokens = parseKey(request.params.key);
|
|
445
554
|
const [key, ...modifiers] = tokens;
|
|
446
555
|
const result = await page.waitForEventsAfterAction(async () => {
|
|
447
|
-
|
|
448
|
-
|
|
556
|
+
const heldModifiers = [];
|
|
557
|
+
try {
|
|
558
|
+
for (const modifier of modifiers) {
|
|
559
|
+
await page.pptrPage.keyboard.down(modifier);
|
|
560
|
+
heldModifiers.push(modifier);
|
|
561
|
+
}
|
|
562
|
+
await page.pptrPage.keyboard.press(key);
|
|
449
563
|
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
564
|
+
finally {
|
|
565
|
+
// Release every modifier that was successfully pressed, even if a
|
|
566
|
+
// later key event throws. Otherwise a failed press leaves modifiers
|
|
567
|
+
// logically held down in the browser (see #2309).
|
|
568
|
+
for (const modifier of heldModifiers.toReversed()) {
|
|
569
|
+
await page.pptrPage.keyboard.up(modifier);
|
|
570
|
+
}
|
|
453
571
|
}
|
|
454
572
|
});
|
|
455
573
|
response.appendResponseLine(`Successfully pressed key: ${request.params.key}`);
|
|
456
|
-
|
|
574
|
+
response.attachWaitForResult(result);
|
|
457
575
|
if (request.params.includeSnapshot) {
|
|
458
576
|
response.includeSnapshot();
|
|
459
577
|
}
|
|
@@ -30,6 +30,9 @@ export const lighthouseAudit = definePageTool({
|
|
|
30
30
|
.describe('Directory for reports. If omitted, uses temporary files.'),
|
|
31
31
|
},
|
|
32
32
|
blockedByDialog: true,
|
|
33
|
+
verifyFilesSchema: {
|
|
34
|
+
outputDirPath: true,
|
|
35
|
+
},
|
|
33
36
|
handler: async (request, response, context) => {
|
|
34
37
|
const page = request.page;
|
|
35
38
|
const categories = [
|
|
@@ -40,7 +43,6 @@ export const lighthouseAudit = definePageTool({
|
|
|
40
43
|
];
|
|
41
44
|
const formats = ['json', 'html'];
|
|
42
45
|
const { mode = 'navigation', device = 'desktop', outputDirPath, } = request.params;
|
|
43
|
-
context.validatePath(outputDirPath);
|
|
44
46
|
const flags = {
|
|
45
47
|
onlyCategories: categories,
|
|
46
48
|
output: formats,
|
|
@@ -84,23 +86,28 @@ export const lighthouseAudit = definePageTool({
|
|
|
84
86
|
}
|
|
85
87
|
}
|
|
86
88
|
finally {
|
|
87
|
-
await
|
|
89
|
+
await page.restoreEmulation();
|
|
88
90
|
}
|
|
89
91
|
const lhr = result.lhr;
|
|
90
92
|
const reportPaths = [];
|
|
91
93
|
const encoder = new TextEncoder();
|
|
92
|
-
|
|
94
|
+
const savePromises = formats.map(async (format) => {
|
|
93
95
|
const report = generateReport(lhr, format);
|
|
94
96
|
const data = encoder.encode(report);
|
|
95
97
|
if (outputDirPath) {
|
|
96
98
|
const reportPath = path.join(outputDirPath, `report`);
|
|
97
99
|
const { filename } = await context.saveFile(data, reportPath, `.${format}`);
|
|
98
|
-
|
|
100
|
+
return filename;
|
|
99
101
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
102
|
+
const { filepath } = await context.saveTemporaryFile(data, `report.${format}`);
|
|
103
|
+
return filepath;
|
|
104
|
+
});
|
|
105
|
+
const results = await Promise.allSettled(savePromises);
|
|
106
|
+
for (const res of results) {
|
|
107
|
+
if (res.status === 'rejected') {
|
|
108
|
+
throw res.reason;
|
|
103
109
|
}
|
|
110
|
+
reportPaths.push(res.value);
|
|
104
111
|
}
|
|
105
112
|
const categoryScores = Object.values(lhr.categories).map(c => ({
|
|
106
113
|
id: c.id,
|