@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.
Files changed (360) hide show
  1. package/FORK-NOTICE.md +45 -0
  2. package/LICENSE +202 -0
  3. package/README.md +45 -2
  4. package/build/src/BrowserManager.js +401 -0
  5. package/build/src/McpContext.js +642 -0
  6. package/build/src/McpPage.js +850 -0
  7. package/build/src/McpResponse.js +1086 -0
  8. package/build/src/SlimMcpResponse.js +19 -0
  9. package/build/src/TextSnapshot.js +315 -0
  10. package/build/src/ToolHandler.js +322 -0
  11. package/build/src/bin/check-latest-version.js +51 -0
  12. package/build/src/bin/chrome-devtools-mcp-main.js +77 -0
  13. package/build/src/bin/chrome-devtools-mcp.js +23 -0
  14. package/build/src/bin/chrome-devtools.js +222 -0
  15. package/build/src/collectors/PageCollector.js +291 -0
  16. package/build/src/collectors/ServiceWorkerCollector.js +171 -0
  17. package/build/src/config/browser-options.js +125 -0
  18. package/build/src/config/category-options.js +89 -0
  19. package/build/src/config/cli-commands.js +26 -0
  20. package/build/src/config/cli-options.js +1473 -0
  21. package/build/src/config/mcp-options.js +417 -0
  22. package/build/src/daemon/client.js +221 -0
  23. package/build/src/daemon/daemon.js +266 -0
  24. package/build/src/daemon/types.js +7 -0
  25. package/build/src/daemon/utils.js +136 -0
  26. package/build/src/devtools/DevToolsCommentBridge.js +91 -0
  27. package/build/src/devtools/DevtoolsUtils.js +307 -0
  28. package/build/src/devtools/McpHostBindingAdapter.js +165 -0
  29. package/build/src/devtools/issueDescriptions.js +42 -0
  30. package/build/src/formatters/CommentFormatter.js +82 -0
  31. package/build/src/formatters/ConsoleFormatter.js +321 -0
  32. package/build/src/formatters/CssFormatter.js +812 -0
  33. package/build/src/formatters/HeapSnapshotFormatter.js +185 -0
  34. package/build/src/formatters/IssueFormatter.js +193 -0
  35. package/build/src/formatters/NetworkFormatter.js +241 -0
  36. package/build/src/formatters/SnapshotFormatter.js +135 -0
  37. package/build/src/index.js +237 -0
  38. package/build/src/processors/ChunkedTraceParser.js +361 -0
  39. package/build/src/processors/HeapSnapshotManager.js +270 -0
  40. package/build/src/processors/PerformanceTrace.js +132 -0
  41. package/build/src/telemetry/ClearcutLogger.js +242 -0
  42. package/build/src/telemetry/WatchdogClient.js +61 -0
  43. package/build/src/telemetry/errors.js +18 -0
  44. package/build/src/telemetry/flagUtils.js +90 -0
  45. package/build/src/telemetry/metricsRegistry.js +85 -0
  46. package/build/src/telemetry/persistence.js +82 -0
  47. package/build/src/telemetry/transformation.js +233 -0
  48. package/build/src/telemetry/types.js +36 -0
  49. package/build/src/telemetry/watchdog/ClearcutSender.js +205 -0
  50. package/build/src/telemetry/watchdog/main.js +128 -0
  51. package/build/src/third_party/THIRD_PARTY_NOTICES +4077 -0
  52. package/build/src/third_party/bundled-packages.json +12 -0
  53. package/build/src/third_party/devtools-formatter-worker.js +15494 -0
  54. package/build/src/third_party/devtools-heap-snapshot-worker.js +10979 -0
  55. package/build/src/third_party/index.js +200978 -0
  56. package/build/src/third_party/issue-descriptions/CoepCoopSandboxedIframeCannotNavigateToCoopPage.md +4 -0
  57. package/build/src/third_party/issue-descriptions/CoepCorpNotSameOrigin.md +8 -0
  58. package/build/src/third_party/issue-descriptions/CoepCorpNotSameOriginAfterDefaultedToSameOriginByCoep.md +18 -0
  59. package/build/src/third_party/issue-descriptions/CoepCorpNotSameSite.md +7 -0
  60. package/build/src/third_party/issue-descriptions/CoepFrameResourceNeedsCoepHeader.md +10 -0
  61. package/build/src/third_party/issue-descriptions/CompatibilityModeQuirks.md +5 -0
  62. package/build/src/third_party/issue-descriptions/CookieAttributeValueExceedsMaxSize.md +5 -0
  63. package/build/src/third_party/issue-descriptions/LowTextContrast.md +5 -0
  64. package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureErrorRead.md +8 -0
  65. package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureErrorSet.md +8 -0
  66. package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureWarnRead.md +8 -0
  67. package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureWarnSet.md +8 -0
  68. package/build/src/third_party/issue-descriptions/SameSiteUnspecifiedLaxAllowUnsafeRead.md +9 -0
  69. package/build/src/third_party/issue-descriptions/SameSiteUnspecifiedLaxAllowUnsafeSet.md +9 -0
  70. package/build/src/third_party/issue-descriptions/bounceTrackingMitigations.md +3 -0
  71. package/build/src/third_party/issue-descriptions/clientHintMetaTagAllowListInvalidOrigin.md +4 -0
  72. package/build/src/third_party/issue-descriptions/clientHintMetaTagModifiedHTML.md +4 -0
  73. package/build/src/third_party/issue-descriptions/connectionAllowlistEmbeddingRequirementNotSatisfied.md +26 -0
  74. package/build/src/third_party/issue-descriptions/connectionAllowlistIFrameAttributeLoosensEmbeddingRequirement.md +19 -0
  75. package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidAllowConnectionAllowlistFrom.md +21 -0
  76. package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidAllowlistItemType.md +12 -0
  77. package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidHeader.md +12 -0
  78. package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidUrlPattern.md +8 -0
  79. package/build/src/third_party/issue-descriptions/connectionAllowlistItemNotInnerList.md +12 -0
  80. package/build/src/third_party/issue-descriptions/connectionAllowlistMoreThanOneList.md +7 -0
  81. package/build/src/third_party/issue-descriptions/connectionAllowlistReportingEndpointNotToken.md +10 -0
  82. package/build/src/third_party/issue-descriptions/cookieCrossSiteRedirectDowngrade.md +12 -0
  83. package/build/src/third_party/issue-descriptions/cookieExcludeDomainNonAscii.md +11 -0
  84. package/build/src/third_party/issue-descriptions/cookieExcludePortMismatch.md +8 -0
  85. package/build/src/third_party/issue-descriptions/cookieExcludeSchemeMismatch.md +7 -0
  86. package/build/src/third_party/issue-descriptions/cookieExcludeThirdPartyPhaseoutRead.md +6 -0
  87. package/build/src/third_party/issue-descriptions/cookieExcludeThirdPartyPhaseoutSet.md +6 -0
  88. package/build/src/third_party/issue-descriptions/cookieWarnDomainNonAscii.md +11 -0
  89. package/build/src/third_party/issue-descriptions/cookieWarnMetadataGrantRead.md +4 -0
  90. package/build/src/third_party/issue-descriptions/cookieWarnMetadataGrantSet.md +4 -0
  91. package/build/src/third_party/issue-descriptions/cookieWarnThirdPartyPhaseoutRead.md +6 -0
  92. package/build/src/third_party/issue-descriptions/cookieWarnThirdPartyPhaseoutSet.md +6 -0
  93. package/build/src/third_party/issue-descriptions/corsAllowCredentialsRequired.md +6 -0
  94. package/build/src/third_party/issue-descriptions/corsDisabledScheme.md +7 -0
  95. package/build/src/third_party/issue-descriptions/corsDisallowedByMode.md +7 -0
  96. package/build/src/third_party/issue-descriptions/corsHeaderDisallowedByPreflightResponse.md +5 -0
  97. package/build/src/third_party/issue-descriptions/corsInvalidHeaderValues.md +7 -0
  98. package/build/src/third_party/issue-descriptions/corsLocalNetworkAccessPermissionDenied.md +19 -0
  99. package/build/src/third_party/issue-descriptions/corsMethodDisallowedByPreflightResponse.md +5 -0
  100. package/build/src/third_party/issue-descriptions/corsNoCorsRedirectModeNotFollow.md +5 -0
  101. package/build/src/third_party/issue-descriptions/corsOriginMismatch.md +6 -0
  102. package/build/src/third_party/issue-descriptions/corsPreflightResponseInvalid.md +5 -0
  103. package/build/src/third_party/issue-descriptions/corsRedirectContainsCredentials.md +5 -0
  104. package/build/src/third_party/issue-descriptions/corsWildcardOriginNotAllowed.md +9 -0
  105. package/build/src/third_party/issue-descriptions/cspEvalViolation.md +9 -0
  106. package/build/src/third_party/issue-descriptions/cspInlineViolation.md +10 -0
  107. package/build/src/third_party/issue-descriptions/cspTrustedTypesPolicyViolation.md +5 -0
  108. package/build/src/third_party/issue-descriptions/cspTrustedTypesSinkViolation.md +8 -0
  109. package/build/src/third_party/issue-descriptions/cspURLViolation.md +10 -0
  110. package/build/src/third_party/issue-descriptions/deprecation.md +3 -0
  111. package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsEmptyList.md +1 -0
  112. package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsHttpNotFound.md +1 -0
  113. package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsInvalidContentType.md +1 -0
  114. package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsInvalidResponse.md +1 -0
  115. package/build/src/third_party/issue-descriptions/emailVerificationRequestAccountsNoResponse.md +1 -0
  116. package/build/src/third_party/issue-descriptions/emailVerificationRequestDnsFetchFailed.md +1 -0
  117. package/build/src/third_party/issue-descriptions/emailVerificationRequestDnsInvalidRecord.md +1 -0
  118. package/build/src/third_party/issue-descriptions/emailVerificationRequestEmailVerificationWellKnownHttpNotFound.md +1 -0
  119. package/build/src/third_party/issue-descriptions/emailVerificationRequestEmailVerificationWellKnownInvalidContentType.md +1 -0
  120. package/build/src/third_party/issue-descriptions/emailVerificationRequestEmailVerificationWellKnownInvalidResponse.md +1 -0
  121. package/build/src/third_party/issue-descriptions/emailVerificationRequestEmailVerificationWellKnownNoResponse.md +1 -0
  122. package/build/src/third_party/issue-descriptions/emailVerificationRequestInvalidEmail.md +1 -0
  123. package/build/src/third_party/issue-descriptions/emailVerificationRequestJwksHttpNotFound.md +1 -0
  124. package/build/src/third_party/issue-descriptions/emailVerificationRequestJwksInvalidResponse.md +1 -0
  125. package/build/src/third_party/issue-descriptions/emailVerificationRequestKeyBindingSigningFailed.md +1 -0
  126. package/build/src/third_party/issue-descriptions/emailVerificationRequestRpOriginIsOpaque.md +1 -0
  127. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenHttpNotFound.md +1 -0
  128. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenInvalidContentType.md +1 -0
  129. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenInvalidResponse.md +1 -0
  130. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenInvalidSdJwt.md +1 -0
  131. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenMalformedSdJwt.md +1 -0
  132. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenNoResponse.md +1 -0
  133. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidAudience.md +1 -0
  134. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidIssuedAt.md +1 -0
  135. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidNonce.md +1 -0
  136. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidSdHash.md +1 -0
  137. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbInvalidTyp.md +1 -0
  138. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingAud.md +1 -0
  139. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingCnf.md +1 -0
  140. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingIat.md +1 -0
  141. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingNonce.md +1 -0
  142. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbMissingSdHash.md +1 -0
  143. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationKbSignatureFailed.md +1 -0
  144. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidEmail.md +1 -0
  145. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidEmailVerified.md +1 -0
  146. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidHolderKey.md +1 -0
  147. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidIssuedAt.md +1 -0
  148. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtInvalidIssuer.md +1 -0
  149. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtJwksMissingKeys.md +1 -0
  150. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtMissingCnf.md +1 -0
  151. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtMissingEmail.md +1 -0
  152. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtMissingIat.md +1 -0
  153. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtMissingIss.md +1 -0
  154. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtSignatureFailed.md +1 -0
  155. package/build/src/third_party/issue-descriptions/emailVerificationRequestTokenVerificationSdJwtUnsupportedHeaderAlg.md +1 -0
  156. package/build/src/third_party/issue-descriptions/emailVerificationRequestUserLoggedOut.md +1 -0
  157. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownAccountsEndpointCrossOrigin.md +1 -0
  158. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownHttpNotFound.md +1 -0
  159. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownInvalidContentType.md +1 -0
  160. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownInvalidResponse.md +1 -0
  161. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownIssuanceEndpointCrossOrigin.md +1 -0
  162. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownListEmpty.md +1 -0
  163. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownMissingAccountsEndpoint.md +1 -0
  164. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownMissingIssuanceEndpoint.md +1 -0
  165. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownNoResponse.md +1 -0
  166. package/build/src/third_party/issue-descriptions/emailVerificationRequestWellKnownUnsupportedSigningAlgorithm.md +1 -0
  167. package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsBlockedByConnectionAllowlist.md +1 -0
  168. package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsHttpNotFound.md +1 -0
  169. package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsInvalidResponse.md +1 -0
  170. package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsNoResponse.md +1 -0
  171. package/build/src/third_party/issue-descriptions/federatedAuthRequestApprovalDeclined.md +1 -0
  172. package/build/src/third_party/issue-descriptions/federatedAuthRequestCanceled.md +1 -0
  173. package/build/src/third_party/issue-descriptions/federatedAuthRequestConfigBlockedByConnectionAllowlist.md +1 -0
  174. package/build/src/third_party/issue-descriptions/federatedAuthRequestErrorFetchingSignin.md +1 -0
  175. package/build/src/third_party/issue-descriptions/federatedAuthRequestErrorIdToken.md +1 -0
  176. package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenBlockedByConnectionAllowlist.md +1 -0
  177. package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenHttpNotFound.md +1 -0
  178. package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenInvalidRequest.md +1 -0
  179. package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenInvalidResponse.md +1 -0
  180. package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenNoResponse.md +1 -0
  181. package/build/src/third_party/issue-descriptions/federatedAuthRequestInvalidSigninResponse.md +1 -0
  182. package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestHttpNotFound.md +1 -0
  183. package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestInvalidResponse.md +1 -0
  184. package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestNoResponse.md +1 -0
  185. package/build/src/third_party/issue-descriptions/federatedAuthRequestTooManyRequests.md +1 -0
  186. package/build/src/third_party/issue-descriptions/federatedAuthRequestWellKnownBlockedByConnectionAllowlist.md +1 -0
  187. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestInvalidAccountsResponse.md +1 -0
  188. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestInvalidConfigOrWellKnown.md +1 -0
  189. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoAccountSharingPermission.md +1 -0
  190. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoApiPermission.md +1 -0
  191. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoReturningUserFromFetchedAccounts.md +1 -0
  192. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotIframe.md +1 -0
  193. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotPotentiallyTrustworthy.md +1 -0
  194. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotSameOrigin.md +1 -0
  195. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotSignedInWithIdp.md +1 -0
  196. package/build/src/third_party/issue-descriptions/fetchingPartitionedBlobURL.md +7 -0
  197. package/build/src/third_party/issue-descriptions/genericBackUINavigationWouldSkipAd.md +4 -0
  198. package/build/src/third_party/issue-descriptions/genericFormAriaLabelledByToNonExistingIdError.md +8 -0
  199. package/build/src/third_party/issue-descriptions/genericFormAutocompleteAttributeEmptyError.md +5 -0
  200. package/build/src/third_party/issue-descriptions/genericFormDuplicateIdForInputError.md +5 -0
  201. package/build/src/third_party/issue-descriptions/genericFormEmptyIdAndNameAttributesForInputError.md +5 -0
  202. package/build/src/third_party/issue-descriptions/genericFormInputAssignedAutocompleteValueToIdOrNameAttributeError.md +5 -0
  203. package/build/src/third_party/issue-descriptions/genericFormInputHasWrongButWellIntendedAutocompleteValueError.md +5 -0
  204. package/build/src/third_party/issue-descriptions/genericFormInputWithNoLabelError.md +5 -0
  205. package/build/src/third_party/issue-descriptions/genericFormLabelForMatchesNonExistingIdError.md +5 -0
  206. package/build/src/third_party/issue-descriptions/genericFormLabelForNameError.md +5 -0
  207. package/build/src/third_party/issue-descriptions/genericFormLabelHasNeitherForNorNestedInputError.md +5 -0
  208. package/build/src/third_party/issue-descriptions/genericFormModelContextMissingToolDescription.md +5 -0
  209. package/build/src/third_party/issue-descriptions/genericFormModelContextMissingToolName.md +5 -0
  210. package/build/src/third_party/issue-descriptions/genericFormModelContextParameterMissingName.md +5 -0
  211. package/build/src/third_party/issue-descriptions/genericFormModelContextParameterMissingTitleAndDescription.md +5 -0
  212. package/build/src/third_party/issue-descriptions/genericFormModelContextRequiredParameterMissingName.md +5 -0
  213. package/build/src/third_party/issue-descriptions/genericNavigationEntryMarkedSkippable.md +7 -0
  214. package/build/src/third_party/issue-descriptions/genericResponseWasBlockedByORB.md +4 -0
  215. package/build/src/third_party/issue-descriptions/heavyAd.md +10 -0
  216. package/build/src/third_party/issue-descriptions/lazyLoadImageZeroSize.md +7 -0
  217. package/build/src/third_party/issue-descriptions/mixedContent.md +5 -0
  218. package/build/src/third_party/issue-descriptions/navigatingPartitionedBlobURL.md +5 -0
  219. package/build/src/third_party/issue-descriptions/permissionElementActivationDisabled.md +7 -0
  220. package/build/src/third_party/issue-descriptions/permissionElementActivationDisabledWithOccluder.md +9 -0
  221. package/build/src/third_party/issue-descriptions/permissionElementActivationDisabledWithOccluderParent.md +9 -0
  222. package/build/src/third_party/issue-descriptions/permissionElementCspFrameAncestorsMissing.md +5 -0
  223. package/build/src/third_party/issue-descriptions/permissionElementFencedFrameDisallowed.md +5 -0
  224. package/build/src/third_party/issue-descriptions/permissionElementFontSizeTooLarge.md +5 -0
  225. package/build/src/third_party/issue-descriptions/permissionElementFontSizeTooSmall.md +5 -0
  226. package/build/src/third_party/issue-descriptions/permissionElementGeolocationDeprecated.md +5 -0
  227. package/build/src/third_party/issue-descriptions/permissionElementInsetBoxShadowUnsupported.md +5 -0
  228. package/build/src/third_party/issue-descriptions/permissionElementInvalidDisplayStyle.md +5 -0
  229. package/build/src/third_party/issue-descriptions/permissionElementInvalidSizeValue.md +5 -0
  230. package/build/src/third_party/issue-descriptions/permissionElementInvalidType.md +5 -0
  231. package/build/src/third_party/issue-descriptions/permissionElementInvalidTypeActivation.md +5 -0
  232. package/build/src/third_party/issue-descriptions/permissionElementLowContrast.md +5 -0
  233. package/build/src/third_party/issue-descriptions/permissionElementNonOpaqueColor.md +5 -0
  234. package/build/src/third_party/issue-descriptions/permissionElementPaddingBottomUnsupported.md +6 -0
  235. package/build/src/third_party/issue-descriptions/permissionElementPaddingRightUnsupported.md +6 -0
  236. package/build/src/third_party/issue-descriptions/permissionElementPermissionsPolicyBlocked.md +5 -0
  237. package/build/src/third_party/issue-descriptions/permissionElementRegistrationFailed.md +5 -0
  238. package/build/src/third_party/issue-descriptions/permissionElementRequestInProgress.md +5 -0
  239. package/build/src/third_party/issue-descriptions/permissionElementSecurityChecksFailed.md +5 -0
  240. package/build/src/third_party/issue-descriptions/permissionElementTypeNotSupported.md +5 -0
  241. package/build/src/third_party/issue-descriptions/permissionElementUntrustedEvent.md +7 -0
  242. package/build/src/third_party/issue-descriptions/placeholderDescriptionForInvisibleIssues.md +3 -0
  243. package/build/src/third_party/issue-descriptions/propertyRuleInvalidNameIssue.md +3 -0
  244. package/build/src/third_party/issue-descriptions/propertyRuleIssue.md +7 -0
  245. package/build/src/third_party/issue-descriptions/selectElementAccessibilityDisallowedOptGroupChild.md +7 -0
  246. package/build/src/third_party/issue-descriptions/selectElementAccessibilityDisallowedSelectChild.md +7 -0
  247. package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentAttributesSelectDescendant.md +3 -0
  248. package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentLegendChild.md +3 -0
  249. package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentOptionChild.md +3 -0
  250. package/build/src/third_party/issue-descriptions/selectElementAccessibilityNonPhrasingContentOptionChild.md +3 -0
  251. package/build/src/third_party/issue-descriptions/selectivePermissionsIntervention.md +7 -0
  252. package/build/src/third_party/issue-descriptions/sharedArrayBuffer.md +7 -0
  253. package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorCrossOriginNoCorsRequest.md +1 -0
  254. package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorDictionaryLoadFailure.md +3 -0
  255. package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorMatchingDictionaryNotUsed.md +3 -0
  256. package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorUnexpectedContentDictionaryHeader.md +1 -0
  257. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorCossOriginNoCorsRequest.md +1 -0
  258. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorDisallowedBySettings.md +1 -0
  259. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorExpiredResponse.md +3 -0
  260. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorFeatureDisabled.md +3 -0
  261. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorInsufficientResources.md +1 -0
  262. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorInvalidMatchField.md +1 -0
  263. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorInvalidStructuredHeader.md +1 -0
  264. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorInvalidTTLField.md +1 -0
  265. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNavigationRequest.md +3 -0
  266. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNoMatchField.md +1 -0
  267. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonIntegerTTLField.md +1 -0
  268. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonListMatchDestField.md +1 -0
  269. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonSecureContext.md +3 -0
  270. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonStringIdField.md +1 -0
  271. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonStringInMatchDestList.md +1 -0
  272. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonStringMatchField.md +1 -0
  273. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonTokenTypeField.md +1 -0
  274. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorRequestAborted.md +1 -0
  275. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorShuttingDown.md +1 -0
  276. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorTooLongIdField.md +3 -0
  277. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorUnsupportedType.md +3 -0
  278. package/build/src/third_party/issue-descriptions/sriInvalidSignatureHeader.md +14 -0
  279. package/build/src/third_party/issue-descriptions/sriInvalidSignatureInputHeader.md +15 -0
  280. package/build/src/third_party/issue-descriptions/sriMissingSignatureHeader.md +8 -0
  281. package/build/src/third_party/issue-descriptions/sriMissingSignatureInputHeader.md +7 -0
  282. package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsIncorrectLength.md +11 -0
  283. package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsNotByteSequence.md +14 -0
  284. package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsParameterized.md +15 -0
  285. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidComponentName.md +8 -0
  286. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidComponentType.md +13 -0
  287. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidDerivedComponentParameter.md +4 -0
  288. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidHeaderComponentParameter.md +5 -0
  289. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidParameter.md +11 -0
  290. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderKeyIdLength.md +12 -0
  291. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderMissingLabel.md +6 -0
  292. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderMissingRequiredParameters.md +8 -0
  293. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderValueMissingComponents.md +11 -0
  294. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderValueNotInnerList.md +11 -0
  295. package/build/src/third_party/issue-descriptions/sriValidationFailedIntegrityMismatch.md +10 -0
  296. package/build/src/third_party/issue-descriptions/sriValidationFailedInvalidLength.md +5 -0
  297. package/build/src/third_party/issue-descriptions/sriValidationFailedSignatureExpired.md +6 -0
  298. package/build/src/third_party/issue-descriptions/sriValidationFailedSignatureMismatch.md +11 -0
  299. package/build/src/third_party/issue-descriptions/stylesheetLateImport.md +4 -0
  300. package/build/src/third_party/issue-descriptions/stylesheetRequestFailed.md +3 -0
  301. package/build/src/third_party/issue-descriptions/summaryElementAccessibilityInteractiveContentSummaryDescendant.md +3 -0
  302. package/build/src/third_party/issue-descriptions/unencodedDigestIncorrectDigestLength.md +12 -0
  303. package/build/src/third_party/issue-descriptions/unencodedDigestIncorrectDigestType.md +17 -0
  304. package/build/src/third_party/issue-descriptions/unencodedDigestMalformedDictionary.md +14 -0
  305. package/build/src/third_party/issue-descriptions/unencodedDigestUnknownAlgorithm.md +15 -0
  306. package/build/src/third_party/issue-descriptions/webInstallManifestMissingId.md +3 -0
  307. package/build/src/third_party/issue-descriptions/webInstallManifestMissingNameOrShortName.md +3 -0
  308. package/build/src/third_party/issue-descriptions/webInstallManifestParsingOrNetworkError.md +3 -0
  309. package/build/src/third_party/issue-descriptions/webInstallNoManifest.md +3 -0
  310. package/build/src/third_party/issue-descriptions/webInstallStartUrlInvalid.md +3 -0
  311. package/build/src/third_party/lighthouse-devtools-mcp-bundle.js +58435 -0
  312. package/build/src/tools/ToolDefinition.js +80 -0
  313. package/build/src/tools/categories.js +33 -0
  314. package/build/src/tools/comments.js +169 -0
  315. package/build/src/tools/console.js +104 -0
  316. package/build/src/tools/css.js +45 -0
  317. package/build/src/tools/emulation.js +84 -0
  318. package/build/src/tools/extensions.js +103 -0
  319. package/build/src/tools/input.js +652 -0
  320. package/build/src/tools/lighthouse.js +149 -0
  321. package/build/src/tools/memory.js +424 -0
  322. package/build/src/tools/network.js +128 -0
  323. package/build/src/tools/pages.js +363 -0
  324. package/build/src/tools/performance.js +212 -0
  325. package/build/src/tools/pwa.js +128 -0
  326. package/build/src/tools/screencast.js +119 -0
  327. package/build/src/tools/screenshot.js +277 -0
  328. package/build/src/tools/script.js +232 -0
  329. package/build/src/tools/slim/tools.js +96 -0
  330. package/build/src/tools/snapshot.js +63 -0
  331. package/build/src/tools/thirdPartyDeveloper.js +85 -0
  332. package/build/src/tools/tools.js +55 -0
  333. package/build/src/tools/webmcp.js +66 -0
  334. package/build/src/types.js +10 -0
  335. package/build/src/utils/WaitForHelper.js +316 -0
  336. package/build/src/utils/bytes.js +105 -0
  337. package/build/src/utils/check-for-updates.js +75 -0
  338. package/build/src/utils/files.js +57 -0
  339. package/build/src/utils/id.js +16 -0
  340. package/build/src/utils/keyboard.js +297 -0
  341. package/build/src/utils/logger.js +52 -0
  342. package/build/src/utils/pagination.js +50 -0
  343. package/build/src/utils/polyfill.js +11 -0
  344. package/build/src/utils/url.js +116 -0
  345. package/build/src/version.js +10 -0
  346. package/package.json +41 -4
  347. package/skills/a11y-debugging/SKILL.md +91 -0
  348. package/skills/a11y-debugging/references/a11y-snippets.md +92 -0
  349. package/skills/chrome-devtools/SKILL.md +74 -0
  350. package/skills/chrome-devtools-cli/SKILL.md +194 -0
  351. package/skills/chrome-devtools-cli/references/installation.md +14 -0
  352. package/skills/cookie-debugging/SKILL.md +149 -0
  353. package/skills/debug-optimize-lcp/SKILL.md +121 -0
  354. package/skills/debug-optimize-lcp/references/elements-and-size.md +27 -0
  355. package/skills/debug-optimize-lcp/references/lcp-breakdown.md +23 -0
  356. package/skills/debug-optimize-lcp/references/lcp-snippets.md +79 -0
  357. package/skills/debug-optimize-lcp/references/optimization-strategies.md +38 -0
  358. package/skills/memory-leak-debugging/SKILL.md +58 -0
  359. package/skills/memory-leak-debugging/references/common-leaks.md +33 -0
  360. package/skills/troubleshooting/SKILL.md +99 -0
@@ -0,0 +1,132 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { DevTools } from '../third_party/index.js';
7
+ import { logger } from '../utils/logger.js';
8
+ import { parseTraceEventsFromBuffer } from './ChunkedTraceParser.js';
9
+ /**
10
+ * Type guard that verifies if an operation returned a valid TraceResult.
11
+ *
12
+ * @param x - The result or error object to inspect.
13
+ * @returns True if the object is a TraceResult; otherwise false.
14
+ */
15
+ export function traceResultIsSuccess(x) {
16
+ return 'parsedTrace' in x;
17
+ }
18
+ /**
19
+ * Parses raw JSON trace buffer bytes into a DevTools TraceEngine representation.
20
+ *
21
+ * Accepts either a JSON array of trace events or an object with a `traceEvents` field.
22
+ * Events are parsed in chunks directly from the raw byte buffer to avoid V8 string
23
+ * allocation limits. A new trace engine model is created per call to ensure session
24
+ * isolation and prevent memory retention.
25
+ *
26
+ * @param buffer - Raw binary trace data representing trace events and metadata.
27
+ * @param metadata - Optional throttling configurations applied during recording; overrides embedded file metadata when defined.
28
+ * @returns A promise resolving to a {@link TraceResult} with parsed traces and insights, or a {@link TraceParseError} on failure.
29
+ */
30
+ export async function parseRawTraceBuffer(buffer, metadata) {
31
+ if (!buffer || buffer.length === 0) {
32
+ return {
33
+ error: 'No buffer was provided.',
34
+ };
35
+ }
36
+ try {
37
+ const { events, metadata: fileMetadata } = parseTraceEventsFromBuffer(buffer);
38
+ if (events.length === 0) {
39
+ return {
40
+ error: 'No trace events were found in the trace buffer.',
41
+ };
42
+ }
43
+ const combinedMetadata = {
44
+ ...fileMetadata,
45
+ ...(metadata?.cpuThrottling !== undefined
46
+ ? { cpuThrottling: metadata.cpuThrottling }
47
+ : {}),
48
+ ...(metadata?.networkThrottling !== undefined
49
+ ? { networkThrottling: metadata.networkThrottling }
50
+ : {}),
51
+ };
52
+ const hasMetadata = Object.keys(combinedMetadata).length > 0;
53
+ // Instantiate a fresh TraceModel per invocation because Model permanently
54
+ // retains parsed traces in its internal `#traces` array, which causes an
55
+ // unbounded memory leak if reused across sessions.
56
+ const engine = DevTools.TraceEngine.TraceModel.Model.createWithAllHandlers();
57
+ await engine.parse(events, {
58
+ metadata: hasMetadata ? combinedMetadata : undefined,
59
+ });
60
+ const parsedTrace = engine.parsedTrace();
61
+ if (!parsedTrace) {
62
+ return {
63
+ error: 'No parsed trace was returned from the trace engine.',
64
+ };
65
+ }
66
+ const insights = parsedTrace.insights ?? null;
67
+ return {
68
+ parsedTrace,
69
+ insights,
70
+ };
71
+ }
72
+ catch (e) {
73
+ const errorText = e instanceof Error ? e.message : JSON.stringify(e);
74
+ logger?.(`Unexpected error parsing trace: ${errorText}`);
75
+ return {
76
+ error: errorText,
77
+ };
78
+ }
79
+ }
80
+ const extraFormatDescriptions = `Information on performance traces may contain main thread activity represented as call frames and network requests.
81
+
82
+ ${DevTools.PerformanceTraceFormatter.callFrameDataFormatDescription}
83
+
84
+ ${DevTools.PerformanceTraceFormatter.networkDataFormatDescription}`;
85
+ /**
86
+ * Generates a Markdown summary of main thread activity and network metrics from a parsed trace.
87
+ *
88
+ * @param result - The parsed trace result to summarize.
89
+ * @param deviceScope - Optional CrUX device scope to filter field data.
90
+ * @returns Formatted Markdown text describing performance findings.
91
+ */
92
+ export function getTraceSummary(result, deviceScope) {
93
+ const focus = DevTools.AgentFocus.fromParsedTrace(result.parsedTrace);
94
+ const formatter = new DevTools.PerformanceTraceFormatter(focus, deviceScope);
95
+ const summaryText = formatter.formatTraceSummary();
96
+ return `## Summary of Performance trace findings:
97
+ ${summaryText}
98
+
99
+ ## Details on call tree & network request formats:
100
+ ${extraFormatDescriptions}`;
101
+ }
102
+ /**
103
+ * Formats a specific performance insight from a parsed trace for display.
104
+ *
105
+ * @param result - The parsed trace result containing computed insight sets.
106
+ * @param insightSetId - The identifier of the target insight set.
107
+ * @param insightName - The name of the insight model to extract.
108
+ * @param deviceScope - Optional CrUX device scope to contextualize metrics.
109
+ * @returns An object containing the formatted insight output text or an error message.
110
+ */
111
+ export function getInsightOutput(result, insightSetId, insightName, deviceScope) {
112
+ if (!result.insights) {
113
+ return {
114
+ error: 'No Performance insights are available for this trace.',
115
+ };
116
+ }
117
+ const insightSet = result.insights.get(insightSetId);
118
+ if (!insightSet) {
119
+ return {
120
+ error: 'No Performance Insights for the given insight set id. Only use ids given in the "Available insight sets" list.',
121
+ };
122
+ }
123
+ const matchingInsight = insightName in insightSet.model ? insightSet.model[insightName] : null;
124
+ if (!matchingInsight) {
125
+ return {
126
+ error: `No Insight with the name ${insightName} found. Double check the name you provided is accurate and try again.`,
127
+ };
128
+ }
129
+ const formatter = new DevTools.PerformanceInsightFormatter(DevTools.AgentFocus.fromParsedTrace(result.parsedTrace), matchingInsight, deviceScope);
130
+ return { output: formatter.formatInsight() };
131
+ }
132
+ //# sourceMappingURL=PerformanceTrace.js.map
@@ -0,0 +1,242 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import process from 'node:process';
7
+ import { DAEMON_CLIENT_NAME } from '../daemon/utils.js';
8
+ import { logger } from '../utils/logger.js';
9
+ import { bucketizeDaysSince, bucketizeLatency, buildContext, sanitizeClientName, sanitizeParams, stripUnderscoreBeforeNumber, } from './transformation.js';
10
+ import { McpClient, WatchdogMessageType, OsType, } from './types.js';
11
+ import { WatchdogClient } from './WatchdogClient.js';
12
+ const MS_PER_DAY = 24 * 60 * 60 * 1000;
13
+ function detectOsType() {
14
+ switch (process.platform) {
15
+ case 'win32':
16
+ return OsType.OS_TYPE_WINDOWS;
17
+ case 'darwin':
18
+ return OsType.OS_TYPE_MACOS;
19
+ case 'linux':
20
+ return OsType.OS_TYPE_LINUX;
21
+ default:
22
+ return OsType.OS_TYPE_UNSPECIFIED;
23
+ }
24
+ }
25
+ function isSameDay(d1, d2) {
26
+ return (d1.getUTCFullYear() === d2.getUTCFullYear() &&
27
+ d1.getUTCMonth() === d2.getUTCMonth() &&
28
+ d1.getUTCDate() === d2.getUTCDate());
29
+ }
30
+ function shouldLogDailyActive(state) {
31
+ if (!state.lastActive) {
32
+ return true;
33
+ }
34
+ return !isSameDay(new Date(state.lastActive), new Date());
35
+ }
36
+ function calculateDaysSince(lastDateString, now = new Date()) {
37
+ if (!lastDateString) {
38
+ return -1;
39
+ }
40
+ const lastDate = new Date(lastDateString);
41
+ const diffTime = Math.abs(now.getTime() - lastDate.getTime());
42
+ return Math.ceil(diffTime / MS_PER_DAY);
43
+ }
44
+ // Not const to allow resetting the instance for testing purposes.
45
+ let _clearcut_logger_instance;
46
+ export class ClearcutLogger {
47
+ #persistence;
48
+ #watchdog;
49
+ #mcpClient;
50
+ #rawClientName;
51
+ #state;
52
+ static initialize(options) {
53
+ if (_clearcut_logger_instance) {
54
+ throw new Error('ClearcutLogger is already initialized');
55
+ }
56
+ _clearcut_logger_instance = new ClearcutLogger(options);
57
+ return _clearcut_logger_instance;
58
+ }
59
+ static get() {
60
+ return _clearcut_logger_instance;
61
+ }
62
+ static resetForTesting() {
63
+ _clearcut_logger_instance = undefined;
64
+ }
65
+ constructor(options) {
66
+ this.#persistence = options.persistence;
67
+ this.#watchdog =
68
+ options.watchdogClient ??
69
+ new WatchdogClient({
70
+ parentPid: process.pid,
71
+ appVersion: options.appVersion,
72
+ osType: detectOsType(),
73
+ logFile: options.logFile,
74
+ clearcutEndpoint: options.clearcutEndpoint,
75
+ clearcutForceFlushIntervalMs: options.clearcutForceFlushIntervalMs,
76
+ clearcutIncludePidHeader: options.clearcutIncludePidHeader,
77
+ });
78
+ this.#mcpClient = McpClient.MCP_CLIENT_UNSPECIFIED;
79
+ void this.#persistence
80
+ .loadState()
81
+ .then(state => {
82
+ this.#state = state;
83
+ })
84
+ .catch(error => {
85
+ this.#state = undefined;
86
+ logger?.('Failed to load telemetry state:', error);
87
+ });
88
+ }
89
+ setClientName(clientName) {
90
+ const lowerName = clientName.toLowerCase();
91
+ if (lowerName.includes('claude-desktop')) {
92
+ this.#mcpClient = McpClient.MCP_CLIENT_CLAUDE_DESKTOP;
93
+ }
94
+ else if (lowerName.includes('claude')) {
95
+ this.#mcpClient = McpClient.MCP_CLIENT_CLAUDE_CODE;
96
+ }
97
+ else if (lowerName.includes('gemini')) {
98
+ this.#mcpClient = McpClient.MCP_CLIENT_GEMINI_CLI;
99
+ }
100
+ else if (clientName === DAEMON_CLIENT_NAME) {
101
+ this.#mcpClient = McpClient.MCP_CLIENT_DT_MCP_CLI;
102
+ }
103
+ else if (lowerName.includes('openclaw')) {
104
+ this.#mcpClient = McpClient.MCP_CLIENT_OPENCLAW;
105
+ }
106
+ else if (lowerName.includes('opencode')) {
107
+ this.#mcpClient = McpClient.MCP_CLIENT_OPENCODE;
108
+ }
109
+ else if (lowerName.includes('codex')) {
110
+ this.#mcpClient = McpClient.MCP_CLIENT_CODEX;
111
+ }
112
+ else if (lowerName.includes('antigravity')) {
113
+ this.#mcpClient = McpClient.MCP_CLIENT_ANTIGRAVITY;
114
+ }
115
+ else if (lowerName.includes('grok') || lowerName.includes('xai')) {
116
+ this.#mcpClient = McpClient.MCP_CLIENT_GROK;
117
+ }
118
+ else if (lowerName.includes('copilot')) {
119
+ this.#mcpClient = McpClient.MCP_CLIENT_GITHUB_COPILOT;
120
+ }
121
+ else if (lowerName.includes('hermes-agent')) {
122
+ this.#mcpClient = McpClient.MCP_CLIENT_HERMES;
123
+ }
124
+ else {
125
+ this.#mcpClient = McpClient.MCP_CLIENT_OTHER;
126
+ this.#rawClientName = sanitizeClientName(clientName);
127
+ }
128
+ }
129
+ #addMcpClient(payload) {
130
+ const ext = {
131
+ ...payload,
132
+ mcp_client: this.#mcpClient,
133
+ };
134
+ if (this.#mcpClient === McpClient.MCP_CLIENT_OTHER &&
135
+ this.#rawClientName !== undefined) {
136
+ ext.raw_mcp_client_info = {
137
+ raw_client_name: this.#rawClientName,
138
+ };
139
+ }
140
+ return ext;
141
+ }
142
+ async logToolInvocation(args) {
143
+ void this.#logToolActiveIfNeeded().catch(error => {
144
+ logger?.('Error in logToolActiveIfNeeded:', error);
145
+ });
146
+ const context = buildContext(args.devToolsData, args.pageUrl);
147
+ const sanitizedToolName = stripUnderscoreBeforeNumber(args.toolName);
148
+ const tool_invocation = {
149
+ tool_name: sanitizedToolName,
150
+ success: args.success,
151
+ latency_ms: bucketizeLatency(args.latencyMs),
152
+ };
153
+ if (Object.keys(context).length > 0) {
154
+ tool_invocation.context = context;
155
+ }
156
+ if (Object.keys(args.params).length > 0) {
157
+ tool_invocation.tool_params = {
158
+ [`${sanitizedToolName}_params`]: sanitizeParams(args.params, args.schema),
159
+ };
160
+ }
161
+ this.#watchdog.send({
162
+ type: WatchdogMessageType.LOG_EVENT,
163
+ payload: this.#addMcpClient({
164
+ tool_invocation: tool_invocation,
165
+ }),
166
+ });
167
+ }
168
+ async logServerStart(flagUsage) {
169
+ this.#watchdog.send({
170
+ type: WatchdogMessageType.LOG_EVENT,
171
+ payload: this.#addMcpClient({
172
+ server_start: {
173
+ flag_usage: flagUsage,
174
+ },
175
+ }),
176
+ });
177
+ }
178
+ async logDailyActiveIfNeeded() {
179
+ try {
180
+ this.#state = await this.#persistence.loadState();
181
+ if (shouldLogDailyActive(this.#state)) {
182
+ const daysSince = calculateDaysSince(this.#state.lastActive);
183
+ this.#watchdog.send({
184
+ type: WatchdogMessageType.LOG_EVENT,
185
+ payload: this.#addMcpClient({
186
+ daily_active: {
187
+ days_since_last_active: bucketizeDaysSince(daysSince),
188
+ },
189
+ }),
190
+ });
191
+ this.#state.lastActive = new Date().toISOString();
192
+ await this.#persistence.saveState(this.#state);
193
+ }
194
+ }
195
+ catch (err) {
196
+ logger?.('Error in logDailyActiveIfNeeded:', err);
197
+ }
198
+ }
199
+ async logServerError(args) {
200
+ this.#watchdog.send({
201
+ type: WatchdogMessageType.LOG_EVENT,
202
+ payload: this.#addMcpClient({
203
+ server_error: {
204
+ tool_name: args.toolName
205
+ ? stripUnderscoreBeforeNumber(args.toolName)
206
+ : '',
207
+ error_code: args.errorCode,
208
+ },
209
+ }),
210
+ });
211
+ }
212
+ async #logToolActiveIfNeeded() {
213
+ // Expect state loaded at first tool call, if not, just skip logging.
214
+ if (!this.#state) {
215
+ return;
216
+ }
217
+ // Don't log tool active if it has already been logged today.
218
+ const now = new Date();
219
+ if (this.#state.lastToolCall &&
220
+ isSameDay(now, new Date(this.#state.lastToolCall))) {
221
+ return;
222
+ }
223
+ // Refresh state in case it now contains more recent value, and test again.
224
+ const state = await this.#persistence.loadState();
225
+ this.#state = state;
226
+ if (state.lastToolCall && isSameDay(now, new Date(state.lastToolCall))) {
227
+ return;
228
+ }
229
+ const daysSinceToolCall = calculateDaysSince(state.lastToolCall, now);
230
+ this.#watchdog.send({
231
+ type: WatchdogMessageType.LOG_EVENT,
232
+ payload: this.#addMcpClient({
233
+ tool_active: {
234
+ days_since_last_tool_call: bucketizeDaysSince(daysSinceToolCall),
235
+ },
236
+ }),
237
+ });
238
+ this.#state.lastToolCall = now.toISOString();
239
+ await this.#persistence.saveState(this.#state);
240
+ }
241
+ }
242
+ //# sourceMappingURL=ClearcutLogger.js.map
@@ -0,0 +1,61 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { spawn } from 'node:child_process';
7
+ import { fileURLToPath } from 'node:url';
8
+ import { logger } from '../utils/logger.js';
9
+ export class WatchdogClient {
10
+ #childProcess;
11
+ constructor(config, options) {
12
+ const watchdogPath = fileURLToPath(new URL('./watchdog/main.js', import.meta.url));
13
+ const args = [
14
+ watchdogPath,
15
+ `--parent-pid=${config.parentPid}`,
16
+ `--app-version=${config.appVersion}`,
17
+ `--os-type=${config.osType}`,
18
+ ];
19
+ if (config.logFile) {
20
+ args.push(`--log-file=${config.logFile}`);
21
+ }
22
+ if (config.clearcutEndpoint) {
23
+ args.push(`--clearcut-endpoint=${config.clearcutEndpoint}`);
24
+ }
25
+ if (config.clearcutForceFlushIntervalMs) {
26
+ args.push(`--clearcut-force-flush-interval-ms=${config.clearcutForceFlushIntervalMs}`);
27
+ }
28
+ if (config.clearcutIncludePidHeader) {
29
+ args.push('--clearcut-include-pid-header');
30
+ }
31
+ const spawner = options?.spawn ?? spawn;
32
+ this.#childProcess = spawner(process.execPath, args, {
33
+ stdio: ['pipe', 'ignore', 'ignore'],
34
+ detached: true,
35
+ });
36
+ this.#childProcess.unref();
37
+ this.#childProcess.on('error', err => {
38
+ logger?.('Watchdog process error:', err);
39
+ });
40
+ this.#childProcess.on('exit', (code, signal) => {
41
+ logger?.(`Watchdog exited with code ${code} and signal ${signal}`);
42
+ });
43
+ }
44
+ send(message) {
45
+ if (this.#childProcess.stdin &&
46
+ !this.#childProcess.stdin.destroyed &&
47
+ this.#childProcess.pid) {
48
+ try {
49
+ const line = JSON.stringify(message) + '\n';
50
+ this.#childProcess.stdin.write(line);
51
+ }
52
+ catch (err) {
53
+ logger?.('Failed to write to watchdog stdin', err);
54
+ }
55
+ }
56
+ else {
57
+ logger?.('Watchdog stdin not available, dropping message');
58
+ }
59
+ }
60
+ }
61
+ //# sourceMappingURL=WatchdogClient.js.map
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ * IMPORTANT:
7
+ * 1. this module must only contain ErrorCode.
8
+ * 2. do not refactor ErrorCode to elsewhere.
9
+ * 3. prefix new enum values with "ERROR_CODE_". This makes it easier to
10
+ * programmtically parse this file.
11
+ */
12
+ export var ErrorCode;
13
+ (function (ErrorCode) {
14
+ ErrorCode[ErrorCode["ERROR_CODE_UNSPECIFIED"] = 0] = "ERROR_CODE_UNSPECIFIED";
15
+ ErrorCode[ErrorCode["ERROR_CODE_PERSISTENCE_FILE_READ_FAILED"] = 1] = "ERROR_CODE_PERSISTENCE_FILE_READ_FAILED";
16
+ ErrorCode[ErrorCode["ERROR_CODE_PERSISTENCE_FILE_SAVE_FAILED"] = 2] = "ERROR_CODE_PERSISTENCE_FILE_SAVE_FAILED";
17
+ })(ErrorCode || (ErrorCode = {}));
18
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1,90 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { DevTools } from '../third_party/index.js';
7
+ import { stripUnderscoreBeforeNumber } from './transformation.js';
8
+ const { StringUtilities } = DevTools.Platform;
9
+ /**
10
+ * For enums, log the value as uppercase.
11
+ * We're going to have an enum for such flags with choices represented
12
+ * as an `enum` where the keys of the enum will map to the uppercase `choice`.
13
+ */
14
+ function formatEnumChoice(snakeCaseName, choice) {
15
+ return stripUnderscoreBeforeNumber(`${snakeCaseName}_${choice}`).toUpperCase();
16
+ }
17
+ /**
18
+ * Computes telemetry flag usage from parsed arguments and CLI options.
19
+ *
20
+ * Iterates over the defined CLI options to construct a payload:
21
+ * - Flag names are converted to snake_case (e.g. `browserUrl` -> `browser_url`).
22
+ * - A flag is logged as `{flag_name}_present` if:
23
+ * - It has no default value, OR
24
+ * - The provided value differs from the default value.
25
+ * - Boolean flags are logged with their literal value.
26
+ * - String flags with defined `choices` (Enums) are logged as their uppercase value.
27
+ *
28
+ * IMPORTANT: keep getPossibleFlagMetrics() in sync with this function.
29
+ */
30
+ export function computeFlagUsage(args, options) {
31
+ const usage = {};
32
+ for (const [flagName, config] of Object.entries(options)) {
33
+ const value = args[flagName];
34
+ const snakeCaseName = stripUnderscoreBeforeNumber(StringUtilities.toSnakeCase(flagName));
35
+ // If there isn't a default value provided for the flag,
36
+ // we're going to log whether it's present on the args user
37
+ // provided or not. If there is a default value, we only log presence
38
+ // if the value differs from the default, implying explicit user intent.
39
+ if (!('default' in config) || value !== config.default) {
40
+ usage[`${snakeCaseName}_present`] = value !== undefined && value !== null;
41
+ }
42
+ if (config.type === 'boolean' && typeof value === 'boolean') {
43
+ // For boolean options, we're going to log the value directly.
44
+ usage[snakeCaseName] = value;
45
+ }
46
+ else if (config.type === 'string' &&
47
+ typeof value === 'string' &&
48
+ 'choices' in config &&
49
+ config.choices) {
50
+ usage[snakeCaseName] = formatEnumChoice(snakeCaseName, value);
51
+ }
52
+ }
53
+ return usage;
54
+ }
55
+ /**
56
+ * Computes the list of possible flag metrics based on the CLI options.
57
+ *
58
+ * IMPORTANT: keep this function in sync with computeFlagUsage().
59
+ */
60
+ export function getPossibleFlagMetrics(options) {
61
+ const metrics = [];
62
+ for (const [flagName, config] of Object.entries(options)) {
63
+ const snakeCaseName = stripUnderscoreBeforeNumber(StringUtilities.toSnakeCase(flagName));
64
+ // _present is always a possible metric
65
+ metrics.push({
66
+ name: `${snakeCaseName}_present`,
67
+ flagType: 'boolean',
68
+ });
69
+ if (config.type === 'boolean') {
70
+ metrics.push({
71
+ name: snakeCaseName,
72
+ flagType: 'boolean',
73
+ });
74
+ }
75
+ else if (config.type === 'string' &&
76
+ 'choices' in config &&
77
+ config.choices) {
78
+ metrics.push({
79
+ name: snakeCaseName,
80
+ flagType: 'enum',
81
+ choices: [
82
+ `${snakeCaseName.toUpperCase()}_UNSPECIFIED`,
83
+ ...config.choices.map(choice => formatEnumChoice(snakeCaseName, choice)),
84
+ ],
85
+ });
86
+ }
87
+ }
88
+ return metrics;
89
+ }
90
+ //# sourceMappingURL=flagUtils.js.map
@@ -0,0 +1,85 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { transformArgName, transformArgType, getZodType, getEnumValues, PARAM_BLOCKLIST, stripUnderscoreBeforeNumber, } from './transformation.js';
7
+ /**
8
+ * Validates that all values in an enum are of the homogeneous primitive type.
9
+ * Returns the primitive type string. Throws an error if heterogeneous.
10
+ */
11
+ export function validateEnumHomogeneity(values) {
12
+ const firstType = typeof values[0];
13
+ for (const val of values) {
14
+ if (typeof val !== firstType) {
15
+ throw new Error('Heterogeneous enum types found');
16
+ }
17
+ }
18
+ return firstType;
19
+ }
20
+ export function applyToExistingMetrics(existing, update) {
21
+ const updated = applyToExisting(existing, update);
22
+ const existingByName = new Map(existing.map(tool => [tool.name, tool]));
23
+ const updatedByName = new Map(update.map(tool => [tool.name, tool]));
24
+ return updated.map(tool => {
25
+ const existingTool = existingByName.get(tool.name);
26
+ const updatedTool = updatedByName.get(tool.name);
27
+ // If the tool still exists in the update, we will update the args.
28
+ if (existingTool && updatedTool) {
29
+ const updatedArgs = applyToExisting(existingTool.args, updatedTool.args);
30
+ return { ...tool, args: updatedArgs };
31
+ }
32
+ return tool;
33
+ });
34
+ }
35
+ export function applyToExisting(existing, update) {
36
+ const existingNames = new Set(existing.map(item => item.name));
37
+ const updatedNames = new Set(update.map(item => item.name));
38
+ const result = [];
39
+ // Keep the original ordering.
40
+ for (const entry of existing) {
41
+ const toAdd = { ...entry };
42
+ if (!updatedNames.has(entry.name)) {
43
+ toAdd.isDeprecated = true;
44
+ }
45
+ else {
46
+ delete toAdd.isDeprecated;
47
+ }
48
+ result.push(toAdd);
49
+ }
50
+ // New entries must be added to the very back of the list.
51
+ for (const entry of update) {
52
+ if (!existingNames.has(entry.name)) {
53
+ result.push({ ...entry });
54
+ }
55
+ }
56
+ return result;
57
+ }
58
+ /**
59
+ * Generates tool metrics from tool definitions.
60
+ */
61
+ export function generateToolMetrics(tools) {
62
+ return tools.map(tool => {
63
+ const args = [];
64
+ for (const [name, schema] of Object.entries(tool.schema)) {
65
+ if (PARAM_BLOCKLIST.has(name)) {
66
+ continue;
67
+ }
68
+ const zodType = getZodType(schema);
69
+ const transformedName = transformArgName(zodType, name);
70
+ let argType = transformArgType(zodType);
71
+ if (argType === 'enum') {
72
+ argType = validateEnumHomogeneity(getEnumValues(schema));
73
+ }
74
+ args.push({
75
+ name: transformedName,
76
+ argType,
77
+ });
78
+ }
79
+ return {
80
+ name: stripUnderscoreBeforeNumber(tool.name),
81
+ args,
82
+ };
83
+ });
84
+ }
85
+ //# sourceMappingURL=metricsRegistry.js.map