@vibebrowser/chrome-devtools-mcp 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (294) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +873 -0
  3. package/build/src/DevToolsConnectionAdapter.js +70 -0
  4. package/build/src/DevtoolsUtils.js +295 -0
  5. package/build/src/HeapSnapshotManager.js +110 -0
  6. package/build/src/McpContext.js +605 -0
  7. package/build/src/McpPage.js +315 -0
  8. package/build/src/McpResponse.js +858 -0
  9. package/build/src/Mutex.js +38 -0
  10. package/build/src/PageCollector.js +297 -0
  11. package/build/src/SlimMcpResponse.js +19 -0
  12. package/build/src/TextSnapshot.js +236 -0
  13. package/build/src/ToolHandler.js +217 -0
  14. package/build/src/WaitForHelper.js +190 -0
  15. package/build/src/bin/check-latest-version.js +50 -0
  16. package/build/src/bin/chrome-devtools-cli-options.js +840 -0
  17. package/build/src/bin/chrome-devtools-mcp-cli-options.js +350 -0
  18. package/build/src/bin/chrome-devtools-mcp-main.js +94 -0
  19. package/build/src/bin/chrome-devtools-mcp.js +31 -0
  20. package/build/src/bin/chrome-devtools.js +189 -0
  21. package/build/src/bin/install-service.js +246 -0
  22. package/build/src/bin/service/chrome-devtools-mcp.service.template +17 -0
  23. package/build/src/bin/service/com.vibebrowser.chrome-devtools-mcp.plist.template +37 -0
  24. package/build/src/browser.js +204 -0
  25. package/build/src/daemon/client.js +154 -0
  26. package/build/src/daemon/daemon.js +204 -0
  27. package/build/src/daemon/types.js +7 -0
  28. package/build/src/daemon/utils.js +115 -0
  29. package/build/src/formatters/ConsoleFormatter.js +288 -0
  30. package/build/src/formatters/HeapSnapshotFormatter.js +54 -0
  31. package/build/src/formatters/IssueFormatter.js +193 -0
  32. package/build/src/formatters/NetworkFormatter.js +236 -0
  33. package/build/src/formatters/SnapshotFormatter.js +135 -0
  34. package/build/src/index.js +140 -0
  35. package/build/src/issue-descriptions.js +40 -0
  36. package/build/src/logger.js +37 -0
  37. package/build/src/polyfill.js +8 -0
  38. package/build/src/telemetry/ClearcutLogger.js +169 -0
  39. package/build/src/telemetry/WatchdogClient.js +61 -0
  40. package/build/src/telemetry/errors.js +18 -0
  41. package/build/src/telemetry/flagUtils.js +89 -0
  42. package/build/src/telemetry/metricsRegistry.js +89 -0
  43. package/build/src/telemetry/persistence.js +72 -0
  44. package/build/src/telemetry/transformation.js +134 -0
  45. package/build/src/telemetry/types.js +31 -0
  46. package/build/src/telemetry/watchdog/ClearcutSender.js +205 -0
  47. package/build/src/telemetry/watchdog/main.js +128 -0
  48. package/build/src/third_party/devtools-formatter-worker.js +8 -0
  49. package/build/src/third_party/devtools-heap-snapshot-worker.js +8 -0
  50. package/build/src/third_party/index.js +32 -0
  51. package/build/src/third_party/issue-descriptions/CoepCoopSandboxedIframeCannotNavigateToCoopPage.md +4 -0
  52. package/build/src/third_party/issue-descriptions/CoepCorpNotSameOrigin.md +8 -0
  53. package/build/src/third_party/issue-descriptions/CoepCorpNotSameOriginAfterDefaultedToSameOriginByCoep.md +18 -0
  54. package/build/src/third_party/issue-descriptions/CoepCorpNotSameSite.md +7 -0
  55. package/build/src/third_party/issue-descriptions/CoepFrameResourceNeedsCoepHeader.md +10 -0
  56. package/build/src/third_party/issue-descriptions/CompatibilityModeQuirks.md +5 -0
  57. package/build/src/third_party/issue-descriptions/CookieAttributeValueExceedsMaxSize.md +5 -0
  58. package/build/src/third_party/issue-descriptions/LowTextContrast.md +5 -0
  59. package/build/src/third_party/issue-descriptions/SameSiteExcludeContextDowngradeRead.md +8 -0
  60. package/build/src/third_party/issue-descriptions/SameSiteExcludeContextDowngradeSet.md +8 -0
  61. package/build/src/third_party/issue-descriptions/SameSiteExcludeNavigationContextDowngrade.md +8 -0
  62. package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureErrorRead.md +8 -0
  63. package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureErrorSet.md +8 -0
  64. package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureWarnRead.md +8 -0
  65. package/build/src/third_party/issue-descriptions/SameSiteNoneInsecureWarnSet.md +8 -0
  66. package/build/src/third_party/issue-descriptions/SameSiteUnspecifiedLaxAllowUnsafeRead.md +9 -0
  67. package/build/src/third_party/issue-descriptions/SameSiteUnspecifiedLaxAllowUnsafeSet.md +9 -0
  68. package/build/src/third_party/issue-descriptions/SameSiteWarnCrossDowngradeRead.md +8 -0
  69. package/build/src/third_party/issue-descriptions/SameSiteWarnCrossDowngradeSet.md +8 -0
  70. package/build/src/third_party/issue-descriptions/SameSiteWarnStrictLaxDowngradeStrict.md +8 -0
  71. package/build/src/third_party/issue-descriptions/arInsecureContext.md +7 -0
  72. package/build/src/third_party/issue-descriptions/arInvalidInfoHeader.md +5 -0
  73. package/build/src/third_party/issue-descriptions/arInvalidRegisterOsSourceHeader.md +5 -0
  74. package/build/src/third_party/issue-descriptions/arInvalidRegisterOsTriggerHeader.md +5 -0
  75. package/build/src/third_party/issue-descriptions/arInvalidRegisterSourceHeader.md +5 -0
  76. package/build/src/third_party/issue-descriptions/arInvalidRegisterTriggerHeader.md +5 -0
  77. package/build/src/third_party/issue-descriptions/arNavigationRegistrationUniqueScopeAlreadySet.md +5 -0
  78. package/build/src/third_party/issue-descriptions/arNavigationRegistrationWithoutTransientUserActivation.md +6 -0
  79. package/build/src/third_party/issue-descriptions/arNoRegisterOsSourceHeader.md +5 -0
  80. package/build/src/third_party/issue-descriptions/arNoRegisterOsTriggerHeader.md +5 -0
  81. package/build/src/third_party/issue-descriptions/arNoRegisterSourceHeader.md +5 -0
  82. package/build/src/third_party/issue-descriptions/arNoRegisterTriggerHeader.md +5 -0
  83. package/build/src/third_party/issue-descriptions/arNoWebOrOsSupport.md +4 -0
  84. package/build/src/third_party/issue-descriptions/arOsSourceIgnored.md +18 -0
  85. package/build/src/third_party/issue-descriptions/arOsTriggerIgnored.md +19 -0
  86. package/build/src/third_party/issue-descriptions/arPermissionPolicyDisabled.md +8 -0
  87. package/build/src/third_party/issue-descriptions/arSourceAndTriggerHeaders.md +9 -0
  88. package/build/src/third_party/issue-descriptions/arSourceIgnored.md +13 -0
  89. package/build/src/third_party/issue-descriptions/arTriggerIgnored.md +12 -0
  90. package/build/src/third_party/issue-descriptions/arUntrustworthyReportingOrigin.md +10 -0
  91. package/build/src/third_party/issue-descriptions/arWebAndOsHeaders.md +11 -0
  92. package/build/src/third_party/issue-descriptions/bounceTrackingMitigations.md +3 -0
  93. package/build/src/third_party/issue-descriptions/clientHintMetaTagAllowListInvalidOrigin.md +4 -0
  94. package/build/src/third_party/issue-descriptions/clientHintMetaTagModifiedHTML.md +4 -0
  95. package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidAllowlistItemType.md +12 -0
  96. package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidHeader.md +12 -0
  97. package/build/src/third_party/issue-descriptions/connectionAllowlistInvalidUrlPattern.md +8 -0
  98. package/build/src/third_party/issue-descriptions/connectionAllowlistItemNotInnerList.md +12 -0
  99. package/build/src/third_party/issue-descriptions/connectionAllowlistMoreThanOneList.md +7 -0
  100. package/build/src/third_party/issue-descriptions/connectionAllowlistReportingEndpointNotToken.md +10 -0
  101. package/build/src/third_party/issue-descriptions/cookieCrossSiteRedirectDowngrade.md +12 -0
  102. package/build/src/third_party/issue-descriptions/cookieExcludeBlockedWithinRelatedWebsiteSet.md +4 -0
  103. package/build/src/third_party/issue-descriptions/cookieExcludeDomainNonAscii.md +11 -0
  104. package/build/src/third_party/issue-descriptions/cookieExcludePortMismatch.md +8 -0
  105. package/build/src/third_party/issue-descriptions/cookieExcludeSchemeMismatch.md +7 -0
  106. package/build/src/third_party/issue-descriptions/cookieExcludeThirdPartyPhaseoutRead.md +6 -0
  107. package/build/src/third_party/issue-descriptions/cookieExcludeThirdPartyPhaseoutSet.md +6 -0
  108. package/build/src/third_party/issue-descriptions/cookieWarnDomainNonAscii.md +11 -0
  109. package/build/src/third_party/issue-descriptions/cookieWarnMetadataGrantRead.md +4 -0
  110. package/build/src/third_party/issue-descriptions/cookieWarnMetadataGrantSet.md +4 -0
  111. package/build/src/third_party/issue-descriptions/cookieWarnThirdPartyPhaseoutRead.md +6 -0
  112. package/build/src/third_party/issue-descriptions/cookieWarnThirdPartyPhaseoutSet.md +6 -0
  113. package/build/src/third_party/issue-descriptions/corsAllowCredentialsRequired.md +6 -0
  114. package/build/src/third_party/issue-descriptions/corsDisabledScheme.md +7 -0
  115. package/build/src/third_party/issue-descriptions/corsDisallowedByMode.md +7 -0
  116. package/build/src/third_party/issue-descriptions/corsHeaderDisallowedByPreflightResponse.md +5 -0
  117. package/build/src/third_party/issue-descriptions/corsInvalidHeaderValues.md +7 -0
  118. package/build/src/third_party/issue-descriptions/corsLocalNetworkAccessPermissionDenied.md +19 -0
  119. package/build/src/third_party/issue-descriptions/corsMethodDisallowedByPreflightResponse.md +5 -0
  120. package/build/src/third_party/issue-descriptions/corsNoCorsRedirectModeNotFollow.md +5 -0
  121. package/build/src/third_party/issue-descriptions/corsOriginMismatch.md +6 -0
  122. package/build/src/third_party/issue-descriptions/corsPreflightResponseInvalid.md +5 -0
  123. package/build/src/third_party/issue-descriptions/corsRedirectContainsCredentials.md +5 -0
  124. package/build/src/third_party/issue-descriptions/corsWildcardOriginNotAllowed.md +8 -0
  125. package/build/src/third_party/issue-descriptions/cspEvalViolation.md +9 -0
  126. package/build/src/third_party/issue-descriptions/cspInlineViolation.md +10 -0
  127. package/build/src/third_party/issue-descriptions/cspTrustedTypesPolicyViolation.md +5 -0
  128. package/build/src/third_party/issue-descriptions/cspTrustedTypesSinkViolation.md +8 -0
  129. package/build/src/third_party/issue-descriptions/cspURLViolation.md +10 -0
  130. package/build/src/third_party/issue-descriptions/deprecation.md +3 -0
  131. package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsHttpNotFound.md +1 -0
  132. package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsInvalidResponse.md +1 -0
  133. package/build/src/third_party/issue-descriptions/federatedAuthRequestAccountsNoResponse.md +1 -0
  134. package/build/src/third_party/issue-descriptions/federatedAuthRequestApprovalDeclined.md +1 -0
  135. package/build/src/third_party/issue-descriptions/federatedAuthRequestCanceled.md +1 -0
  136. package/build/src/third_party/issue-descriptions/federatedAuthRequestErrorFetchingSignin.md +1 -0
  137. package/build/src/third_party/issue-descriptions/federatedAuthRequestErrorIdToken.md +1 -0
  138. package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenHttpNotFound.md +1 -0
  139. package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenInvalidRequest.md +1 -0
  140. package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenInvalidResponse.md +1 -0
  141. package/build/src/third_party/issue-descriptions/federatedAuthRequestIdTokenNoResponse.md +1 -0
  142. package/build/src/third_party/issue-descriptions/federatedAuthRequestInvalidSigninResponse.md +1 -0
  143. package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestHttpNotFound.md +1 -0
  144. package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestInvalidResponse.md +1 -0
  145. package/build/src/third_party/issue-descriptions/federatedAuthRequestManifestNoResponse.md +1 -0
  146. package/build/src/third_party/issue-descriptions/federatedAuthRequestTooManyRequests.md +1 -0
  147. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestInvalidAccountsResponse.md +1 -0
  148. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestInvalidConfigOrWellKnown.md +1 -0
  149. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoAccountSharingPermission.md +1 -0
  150. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoApiPermission.md +1 -0
  151. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNoReturningUserFromFetchedAccounts.md +1 -0
  152. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotIframe.md +1 -0
  153. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotPotentiallyTrustworthy.md +1 -0
  154. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotSameOrigin.md +1 -0
  155. package/build/src/third_party/issue-descriptions/federatedAuthUserInfoRequestNotSignedInWithIdp.md +1 -0
  156. package/build/src/third_party/issue-descriptions/fetchingPartitionedBlobURL.md +7 -0
  157. package/build/src/third_party/issue-descriptions/genericFormAriaLabelledByToNonExistingIdError.md +8 -0
  158. package/build/src/third_party/issue-descriptions/genericFormAutocompleteAttributeEmptyError.md +5 -0
  159. package/build/src/third_party/issue-descriptions/genericFormDuplicateIdForInputError.md +5 -0
  160. package/build/src/third_party/issue-descriptions/genericFormEmptyIdAndNameAttributesForInputError.md +5 -0
  161. package/build/src/third_party/issue-descriptions/genericFormInputAssignedAutocompleteValueToIdOrNameAttributeError.md +5 -0
  162. package/build/src/third_party/issue-descriptions/genericFormInputHasWrongButWellIntendedAutocompleteValueError.md +5 -0
  163. package/build/src/third_party/issue-descriptions/genericFormInputWithNoLabelError.md +5 -0
  164. package/build/src/third_party/issue-descriptions/genericFormLabelForMatchesNonExistingIdError.md +5 -0
  165. package/build/src/third_party/issue-descriptions/genericFormLabelForNameError.md +5 -0
  166. package/build/src/third_party/issue-descriptions/genericFormLabelHasNeitherForNorNestedInputError.md +5 -0
  167. package/build/src/third_party/issue-descriptions/genericFormModelContextMissingToolDescription.md +5 -0
  168. package/build/src/third_party/issue-descriptions/genericFormModelContextMissingToolName.md +5 -0
  169. package/build/src/third_party/issue-descriptions/genericFormModelContextParameterMissingName.md +5 -0
  170. package/build/src/third_party/issue-descriptions/genericFormModelContextParameterMissingTitleAndDescription.md +5 -0
  171. package/build/src/third_party/issue-descriptions/genericFormModelContextRequiredParameterMissingName.md +5 -0
  172. package/build/src/third_party/issue-descriptions/genericNavigationEntryMarkedSkippable.md +7 -0
  173. package/build/src/third_party/issue-descriptions/genericResponseWasBlockedByORB.md +4 -0
  174. package/build/src/third_party/issue-descriptions/heavyAd.md +10 -0
  175. package/build/src/third_party/issue-descriptions/mixedContent.md +5 -0
  176. package/build/src/third_party/issue-descriptions/navigatingPartitionedBlobURL.md +5 -0
  177. package/build/src/third_party/issue-descriptions/permissionElementActivationDisabled.md +7 -0
  178. package/build/src/third_party/issue-descriptions/permissionElementActivationDisabledWithOccluder.md +9 -0
  179. package/build/src/third_party/issue-descriptions/permissionElementActivationDisabledWithOccluderParent.md +9 -0
  180. package/build/src/third_party/issue-descriptions/permissionElementCspFrameAncestorsMissing.md +5 -0
  181. package/build/src/third_party/issue-descriptions/permissionElementFencedFrameDisallowed.md +5 -0
  182. package/build/src/third_party/issue-descriptions/permissionElementFontSizeTooLarge.md +5 -0
  183. package/build/src/third_party/issue-descriptions/permissionElementFontSizeTooSmall.md +5 -0
  184. package/build/src/third_party/issue-descriptions/permissionElementGeolocationDeprecated.md +5 -0
  185. package/build/src/third_party/issue-descriptions/permissionElementInsetBoxShadowUnsupported.md +5 -0
  186. package/build/src/third_party/issue-descriptions/permissionElementInvalidDisplayStyle.md +5 -0
  187. package/build/src/third_party/issue-descriptions/permissionElementInvalidSizeValue.md +5 -0
  188. package/build/src/third_party/issue-descriptions/permissionElementInvalidType.md +5 -0
  189. package/build/src/third_party/issue-descriptions/permissionElementInvalidTypeActivation.md +5 -0
  190. package/build/src/third_party/issue-descriptions/permissionElementLowContrast.md +5 -0
  191. package/build/src/third_party/issue-descriptions/permissionElementNonOpaqueColor.md +5 -0
  192. package/build/src/third_party/issue-descriptions/permissionElementPaddingBottomUnsupported.md +6 -0
  193. package/build/src/third_party/issue-descriptions/permissionElementPaddingRightUnsupported.md +6 -0
  194. package/build/src/third_party/issue-descriptions/permissionElementPermissionsPolicyBlocked.md +5 -0
  195. package/build/src/third_party/issue-descriptions/permissionElementRegistrationFailed.md +5 -0
  196. package/build/src/third_party/issue-descriptions/permissionElementRequestInProgress.md +5 -0
  197. package/build/src/third_party/issue-descriptions/permissionElementSecurityChecksFailed.md +5 -0
  198. package/build/src/third_party/issue-descriptions/permissionElementTypeNotSupported.md +5 -0
  199. package/build/src/third_party/issue-descriptions/permissionElementUntrustedEvent.md +7 -0
  200. package/build/src/third_party/issue-descriptions/placeholderDescriptionForInvisibleIssues.md +3 -0
  201. package/build/src/third_party/issue-descriptions/propertyRuleInvalidNameIssue.md +3 -0
  202. package/build/src/third_party/issue-descriptions/propertyRuleIssue.md +7 -0
  203. package/build/src/third_party/issue-descriptions/selectElementAccessibilityDisallowedOptGroupChild.md +7 -0
  204. package/build/src/third_party/issue-descriptions/selectElementAccessibilityDisallowedSelectChild.md +7 -0
  205. package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentAttributesSelectDescendant.md +3 -0
  206. package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentLegendChild.md +3 -0
  207. package/build/src/third_party/issue-descriptions/selectElementAccessibilityInteractiveContentOptionChild.md +3 -0
  208. package/build/src/third_party/issue-descriptions/selectElementAccessibilityNonPhrasingContentOptionChild.md +3 -0
  209. package/build/src/third_party/issue-descriptions/selectivePermissionsIntervention.md +7 -0
  210. package/build/src/third_party/issue-descriptions/sharedArrayBuffer.md +7 -0
  211. package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorCrossOriginNoCorsRequest.md +1 -0
  212. package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorDictionaryLoadFailure.md +3 -0
  213. package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorMatchingDictionaryNotUsed.md +3 -0
  214. package/build/src/third_party/issue-descriptions/sharedDictionaryUseErrorUnexpectedContentDictionaryHeader.md +1 -0
  215. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorCossOriginNoCorsRequest.md +1 -0
  216. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorDisallowedBySettings.md +1 -0
  217. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorExpiredResponse.md +3 -0
  218. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorFeatureDisabled.md +3 -0
  219. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorInsufficientResources.md +1 -0
  220. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorInvalidMatchField.md +1 -0
  221. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorInvalidStructuredHeader.md +1 -0
  222. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorInvalidTTLField.md +1 -0
  223. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNavigationRequest.md +3 -0
  224. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNoMatchField.md +1 -0
  225. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonIntegerTTLField.md +1 -0
  226. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonListMatchDestField.md +1 -0
  227. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonSecureContext.md +3 -0
  228. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonStringIdField.md +1 -0
  229. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonStringInMatchDestList.md +1 -0
  230. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonStringMatchField.md +1 -0
  231. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorNonTokenTypeField.md +1 -0
  232. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorRequestAborted.md +1 -0
  233. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorShuttingDown.md +1 -0
  234. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorTooLongIdField.md +3 -0
  235. package/build/src/third_party/issue-descriptions/sharedDictionaryWriteErrorUnsupportedType.md +3 -0
  236. package/build/src/third_party/issue-descriptions/sriInvalidSignatureHeader.md +14 -0
  237. package/build/src/third_party/issue-descriptions/sriInvalidSignatureInputHeader.md +15 -0
  238. package/build/src/third_party/issue-descriptions/sriMissingSignatureHeader.md +8 -0
  239. package/build/src/third_party/issue-descriptions/sriMissingSignatureInputHeader.md +7 -0
  240. package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsIncorrectLength.md +11 -0
  241. package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsNotByteSequence.md +14 -0
  242. package/build/src/third_party/issue-descriptions/sriSignatureHeaderValueIsParameterized.md +15 -0
  243. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidComponentName.md +8 -0
  244. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidComponentType.md +13 -0
  245. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidDerivedComponentParameter.md +4 -0
  246. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidHeaderComponentParameter.md +5 -0
  247. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderInvalidParameter.md +11 -0
  248. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderKeyIdLength.md +12 -0
  249. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderMissingLabel.md +6 -0
  250. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderMissingRequiredParameters.md +8 -0
  251. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderValueMissingComponents.md +11 -0
  252. package/build/src/third_party/issue-descriptions/sriSignatureInputHeaderValueNotInnerList.md +11 -0
  253. package/build/src/third_party/issue-descriptions/sriValidationFailedIntegrityMismatch.md +10 -0
  254. package/build/src/third_party/issue-descriptions/sriValidationFailedInvalidLength.md +5 -0
  255. package/build/src/third_party/issue-descriptions/sriValidationFailedSignatureExpired.md +6 -0
  256. package/build/src/third_party/issue-descriptions/sriValidationFailedSignatureMismatch.md +11 -0
  257. package/build/src/third_party/issue-descriptions/stylesheetLateImport.md +4 -0
  258. package/build/src/third_party/issue-descriptions/stylesheetRequestFailed.md +3 -0
  259. package/build/src/third_party/issue-descriptions/summaryElementAccessibilityInteractiveContentSummaryDescendant.md +3 -0
  260. package/build/src/third_party/issue-descriptions/unencodedDigestIncorrectDigestLength.md +12 -0
  261. package/build/src/third_party/issue-descriptions/unencodedDigestIncorrectDigestType.md +17 -0
  262. package/build/src/third_party/issue-descriptions/unencodedDigestMalformedDictionary.md +14 -0
  263. package/build/src/third_party/issue-descriptions/unencodedDigestUnknownAlgorithm.md +15 -0
  264. package/build/src/third_party/lighthouse-devtools-mcp-bundle.js +61598 -0
  265. package/build/src/tools/ToolDefinition.js +73 -0
  266. package/build/src/tools/categories.js +36 -0
  267. package/build/src/tools/console.js +91 -0
  268. package/build/src/tools/emulation.js +57 -0
  269. package/build/src/tools/extensions.js +96 -0
  270. package/build/src/tools/input.js +461 -0
  271. package/build/src/tools/lighthouse.js +131 -0
  272. package/build/src/tools/memory.js +106 -0
  273. package/build/src/tools/network.js +125 -0
  274. package/build/src/tools/pages.js +411 -0
  275. package/build/src/tools/performance.js +196 -0
  276. package/build/src/tools/screencast.js +95 -0
  277. package/build/src/tools/screenshot.js +87 -0
  278. package/build/src/tools/script.js +151 -0
  279. package/build/src/tools/slim/tools.js +85 -0
  280. package/build/src/tools/snapshot.js +60 -0
  281. package/build/src/tools/thirdPartyDeveloper.js +75 -0
  282. package/build/src/tools/tools.js +56 -0
  283. package/build/src/tools/webmcp.js +64 -0
  284. package/build/src/trace-processing/parse.js +85 -0
  285. package/build/src/types.js +7 -0
  286. package/build/src/utils/check-for-updates.js +74 -0
  287. package/build/src/utils/files.js +18 -0
  288. package/build/src/utils/id.js +16 -0
  289. package/build/src/utils/keyboard.js +297 -0
  290. package/build/src/utils/pagination.js +50 -0
  291. package/build/src/utils/string.js +37 -0
  292. package/build/src/utils/types.js +7 -0
  293. package/build/src/version.js +10 -0
  294. package/package.json +93 -0
@@ -0,0 +1,204 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @license
4
+ * Copyright 2026 Google LLC
5
+ * SPDX-License-Identifier: Apache-2.0
6
+ */
7
+ import fs from 'node:fs';
8
+ import { createServer } from 'node:net';
9
+ import path from 'node:path';
10
+ import process from 'node:process';
11
+ import { logger } from '../logger.js';
12
+ import { Client, PipeTransport, StdioClientTransport, } from '../third_party/index.js';
13
+ import { VERSION } from '../version.js';
14
+ import { DAEMON_CLIENT_NAME, getPidFilePath, getSocketPath, INDEX_SCRIPT_PATH, IS_WINDOWS, isDaemonRunning, } from './utils.js';
15
+ const sessionId = process.env.CHROME_DEVTOOLS_MCP_SESSION_ID || '';
16
+ logger(`Daemon sessionId: ${sessionId}`);
17
+ if (isDaemonRunning(sessionId)) {
18
+ logger('Another daemon process is running.');
19
+ process.exit(1);
20
+ }
21
+ const pidFilePath = getPidFilePath(sessionId);
22
+ fs.mkdirSync(path.dirname(pidFilePath), {
23
+ recursive: true,
24
+ });
25
+ fs.writeFileSync(pidFilePath, process.pid.toString());
26
+ logger(`Writing ${process.pid.toString()} to ${pidFilePath}`);
27
+ const socketPath = getSocketPath(sessionId);
28
+ const startDate = new Date();
29
+ const mcpServerArgs = process.argv.slice(2);
30
+ let mcpClient = null;
31
+ let mcpTransport = null;
32
+ let server = null;
33
+ async function setupMCPClient() {
34
+ console.log('Setting up MCP client connection...');
35
+ // Create stdio transport for chrome-devtools-mcp
36
+ mcpTransport = new StdioClientTransport({
37
+ command: process.execPath,
38
+ args: [INDEX_SCRIPT_PATH, ...mcpServerArgs],
39
+ env: process.env,
40
+ });
41
+ mcpClient = new Client({
42
+ name: DAEMON_CLIENT_NAME,
43
+ version: VERSION,
44
+ }, {
45
+ capabilities: {},
46
+ });
47
+ await mcpClient.connect(mcpTransport);
48
+ console.log('MCP client connected');
49
+ }
50
+ async function handleRequest(msg) {
51
+ try {
52
+ if (msg.method === 'invoke_tool') {
53
+ if (!mcpClient) {
54
+ throw new Error('MCP client not initialized');
55
+ }
56
+ const { tool, args } = msg;
57
+ const result = (await mcpClient.callTool({
58
+ name: tool,
59
+ arguments: args || {},
60
+ }));
61
+ return {
62
+ success: true,
63
+ result: JSON.stringify(result),
64
+ };
65
+ }
66
+ else if (msg.method === 'stop') {
67
+ // Ensure we are not interrupting in-progress starting.
68
+ await started;
69
+ // Trigger cleanup asynchronously.
70
+ setImmediate(() => {
71
+ void cleanup();
72
+ });
73
+ return {
74
+ success: true,
75
+ message: 'stopping',
76
+ };
77
+ }
78
+ else if (msg.method === 'status') {
79
+ return {
80
+ success: true,
81
+ result: JSON.stringify({
82
+ pid: process.pid,
83
+ socketPath,
84
+ startDate: startDate.toISOString(),
85
+ version: VERSION,
86
+ args: mcpServerArgs,
87
+ }),
88
+ };
89
+ }
90
+ {
91
+ return {
92
+ success: false,
93
+ error: `Unknown method: ${JSON.stringify(msg, null, 2)}`,
94
+ };
95
+ }
96
+ }
97
+ catch (error) {
98
+ const errorMessage = error instanceof Error ? error.message : String(error);
99
+ return {
100
+ success: false,
101
+ error: errorMessage,
102
+ };
103
+ }
104
+ }
105
+ async function startSocketServer() {
106
+ // Remove existing socket file if it exists (only on non-Windows)
107
+ if (!IS_WINDOWS) {
108
+ try {
109
+ fs.unlinkSync(socketPath);
110
+ }
111
+ catch {
112
+ // ignore errors.
113
+ }
114
+ }
115
+ return await new Promise((resolve, reject) => {
116
+ server = createServer(socket => {
117
+ const transport = new PipeTransport(socket, socket);
118
+ transport.onmessage = async (message) => {
119
+ logger('onmessage', message);
120
+ const response = await handleRequest(JSON.parse(message));
121
+ transport.send(JSON.stringify(response));
122
+ socket.end();
123
+ };
124
+ socket.on('error', error => {
125
+ logger('Socket error:', error);
126
+ });
127
+ });
128
+ server.listen({
129
+ path: socketPath,
130
+ readableAll: false,
131
+ writableAll: false,
132
+ }, async () => {
133
+ console.log(`Daemon server listening on ${socketPath}`);
134
+ try {
135
+ // Setup MCP client
136
+ await setupMCPClient();
137
+ resolve();
138
+ }
139
+ catch (err) {
140
+ reject(err);
141
+ }
142
+ });
143
+ server.on('error', error => {
144
+ logger('Server error:', error);
145
+ reject(error);
146
+ });
147
+ });
148
+ }
149
+ async function cleanup() {
150
+ console.log('Cleaning up daemon...');
151
+ try {
152
+ await mcpClient?.close();
153
+ }
154
+ catch (error) {
155
+ logger('Error closing MCP client:', error);
156
+ }
157
+ try {
158
+ await mcpTransport?.close();
159
+ }
160
+ catch (error) {
161
+ logger('Error closing MCP transport:', error);
162
+ }
163
+ if (server) {
164
+ await new Promise(resolve => {
165
+ server.close(() => resolve());
166
+ });
167
+ }
168
+ if (!IS_WINDOWS) {
169
+ try {
170
+ fs.unlinkSync(socketPath);
171
+ }
172
+ catch {
173
+ // ignore errors
174
+ }
175
+ }
176
+ logger(`unlinking ${pidFilePath}`);
177
+ if (fs.existsSync(pidFilePath)) {
178
+ fs.unlinkSync(pidFilePath);
179
+ }
180
+ process.exit(0);
181
+ }
182
+ // Handle shutdown signals
183
+ process.on('SIGTERM', () => {
184
+ void cleanup();
185
+ });
186
+ process.on('SIGINT', () => {
187
+ void cleanup();
188
+ });
189
+ process.on('SIGHUP', () => {
190
+ void cleanup();
191
+ });
192
+ // Handle uncaught errors
193
+ process.on('uncaughtException', error => {
194
+ logger('Uncaught exception:', error);
195
+ });
196
+ process.on('unhandledRejection', error => {
197
+ logger('Unhandled rejection:', error);
198
+ });
199
+ // Start the server
200
+ const started = startSocketServer().catch(error => {
201
+ logger('Failed to start daemon server:', error);
202
+ process.exit(1);
203
+ });
204
+ //# sourceMappingURL=daemon.js.map
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,115 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import fs from 'node:fs';
7
+ import os from 'node:os';
8
+ import path from 'node:path';
9
+ import process from 'node:process';
10
+ import { logger } from '../logger.js';
11
+ export const DAEMON_SCRIPT_PATH = path.join(import.meta.dirname, 'daemon.js');
12
+ export const INDEX_SCRIPT_PATH = path.join(import.meta.dirname, '..', 'bin', 'chrome-devtools-mcp.js');
13
+ const APP_NAME = 'chrome-devtools-mcp';
14
+ export const DAEMON_CLIENT_NAME = 'chrome-devtools-cli-daemon';
15
+ // Using these paths due to strict limits on the POSIX socket path length.
16
+ export function getSocketPath(sessionId) {
17
+ const uid = os.userInfo().uid;
18
+ const suffix = sessionId ? `-${sessionId}` : '';
19
+ const appName = APP_NAME + suffix;
20
+ if (IS_WINDOWS) {
21
+ // Windows uses Named Pipes, not file paths.
22
+ // This format is required for server.listen()
23
+ return path.join('\\\\.\\pipe', appName, 'server.sock');
24
+ }
25
+ // 1. Try XDG_RUNTIME_DIR (Linux standard, sometimes macOS)
26
+ if (process.env.XDG_RUNTIME_DIR) {
27
+ return path.join(process.env.XDG_RUNTIME_DIR, appName, 'server.sock');
28
+ }
29
+ // 2. macOS/Unix Fallback: Use /tmp/
30
+ // We use /tmp/ because it is much shorter than ~/Library/Application Support/
31
+ // and keeps us well under the 104-character limit.
32
+ return path.join('/tmp', `${appName}-${uid}.sock`);
33
+ }
34
+ export function getRuntimeHome(sessionId) {
35
+ const platform = os.platform();
36
+ const uid = os.userInfo().uid;
37
+ const suffix = sessionId ? `-${sessionId}` : '';
38
+ const appName = APP_NAME + suffix;
39
+ // 1. Check for the modern Unix standard
40
+ if (process.env.XDG_RUNTIME_DIR) {
41
+ return path.join(process.env.XDG_RUNTIME_DIR, appName);
42
+ }
43
+ // 2. Fallback for macOS and older Linux
44
+ if (platform === 'darwin' || platform === 'linux') {
45
+ // /tmp is cleared on boot, making it perfect for PIDs
46
+ return path.join('/tmp', `${appName}-${uid}`);
47
+ }
48
+ // 3. Windows Fallback
49
+ return path.join(os.tmpdir(), appName);
50
+ }
51
+ export const IS_WINDOWS = os.platform() === 'win32';
52
+ export function getPidFilePath(sessionId) {
53
+ const runtimeDir = getRuntimeHome(sessionId);
54
+ return path.join(runtimeDir, 'daemon.pid');
55
+ }
56
+ export function getDaemonPid(sessionId) {
57
+ try {
58
+ const pidFile = getPidFilePath(sessionId);
59
+ logger(`Daemon pid file ${pidFile} sessionId=${sessionId}`);
60
+ if (!fs.existsSync(pidFile)) {
61
+ return null;
62
+ }
63
+ const pidContent = fs.readFileSync(pidFile, 'utf-8');
64
+ const pid = parseInt(pidContent.trim(), 10);
65
+ logger(`Daemon pid: ${pid}`);
66
+ if (isNaN(pid)) {
67
+ return null;
68
+ }
69
+ return pid;
70
+ }
71
+ catch {
72
+ return null;
73
+ }
74
+ }
75
+ export function isDaemonRunning(sessionId) {
76
+ const pid = getDaemonPid(sessionId);
77
+ if (pid) {
78
+ try {
79
+ process.kill(pid, 0); // Throws if process doesn't exist
80
+ return true;
81
+ }
82
+ catch {
83
+ // Process is dead, stale PID file. Proceed with startup.
84
+ }
85
+ }
86
+ return false;
87
+ }
88
+ export function serializeArgs(options, argv) {
89
+ const args = [];
90
+ for (const key of Object.keys(options)) {
91
+ if (argv[key] === undefined || argv[key] === null) {
92
+ continue;
93
+ }
94
+ const value = argv[key];
95
+ const kebabKey = key.replace(/[A-Z]/g, m => `-${m.toLowerCase()}`);
96
+ if (typeof value === 'boolean') {
97
+ if (value) {
98
+ args.push(`--${kebabKey}`);
99
+ }
100
+ else {
101
+ args.push(`--no-${kebabKey}`);
102
+ }
103
+ }
104
+ else if (Array.isArray(value)) {
105
+ for (const item of value) {
106
+ args.push(`--${kebabKey}`, String(item));
107
+ }
108
+ }
109
+ else {
110
+ args.push(`--${kebabKey}`, String(value));
111
+ }
112
+ }
113
+ return args;
114
+ }
115
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1,288 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { createStackTraceForConsoleMessage, SymbolizedError, } from '../DevtoolsUtils.js';
7
+ import { UncaughtError } from '../PageCollector.js';
8
+ import * as DevTools from '../third_party/index.js';
9
+ export class ConsoleFormatter {
10
+ #id;
11
+ #type;
12
+ #text;
13
+ #argCount;
14
+ #resolvedArgs;
15
+ #stack;
16
+ #cause;
17
+ isIgnored;
18
+ constructor(params) {
19
+ this.#id = params.id;
20
+ this.#type = params.type;
21
+ this.#text = params.text;
22
+ this.#argCount = params.argCount ?? 0;
23
+ this.#resolvedArgs = params.resolvedArgs ?? [];
24
+ this.#stack = params.stack;
25
+ this.#cause = params.cause;
26
+ this.isIgnored = params.isIgnored;
27
+ }
28
+ static async from(msg, options) {
29
+ const ignoreListManager = options?.devTools?.universe.context.get(DevTools.DevTools.IgnoreListManager);
30
+ const isIgnored = options.isIgnoredForTesting ||
31
+ (frame => {
32
+ if (!ignoreListManager) {
33
+ return false;
34
+ }
35
+ if (frame.uiSourceCode) {
36
+ return ignoreListManager.isUserOrSourceMapIgnoreListedUISourceCode(frame.uiSourceCode);
37
+ }
38
+ if (frame.url) {
39
+ return ignoreListManager.isUserIgnoreListedURL(frame.url);
40
+ }
41
+ return false;
42
+ });
43
+ if (msg instanceof UncaughtError) {
44
+ const error = await SymbolizedError.fromDetails({
45
+ devTools: options?.devTools,
46
+ details: msg.details,
47
+ targetId: msg.targetId,
48
+ includeStackAndCause: options?.fetchDetailedData,
49
+ resolvedStackTraceForTesting: options?.resolvedStackTraceForTesting,
50
+ resolvedCauseForTesting: options?.resolvedCauseForTesting,
51
+ });
52
+ return new ConsoleFormatter({
53
+ id: options.id,
54
+ type: 'error',
55
+ text: error.message,
56
+ stack: error.stackTrace,
57
+ cause: error.cause,
58
+ isIgnored,
59
+ });
60
+ }
61
+ let resolvedArgs = [];
62
+ if (options.resolvedArgsForTesting) {
63
+ resolvedArgs = options.resolvedArgsForTesting;
64
+ }
65
+ else if (options.fetchDetailedData) {
66
+ resolvedArgs = await Promise.all(msg.args().map(async (arg, i) => {
67
+ try {
68
+ const remoteObject = arg.remoteObject();
69
+ if (remoteObject.type === 'object' &&
70
+ remoteObject.subtype === 'error') {
71
+ return await SymbolizedError.fromError({
72
+ devTools: options.devTools,
73
+ error: remoteObject,
74
+ // @ts-expect-error Internal ConsoleMessage API
75
+ targetId: msg._targetId(),
76
+ });
77
+ }
78
+ return await arg.jsonValue();
79
+ }
80
+ catch {
81
+ return `<error: Argument ${i} is no longer available>`;
82
+ }
83
+ }));
84
+ }
85
+ let stack;
86
+ if (options.resolvedStackTraceForTesting) {
87
+ stack = options.resolvedStackTraceForTesting;
88
+ }
89
+ else if (options.fetchDetailedData && options.devTools) {
90
+ try {
91
+ stack = await createStackTraceForConsoleMessage(options.devTools, msg);
92
+ }
93
+ catch {
94
+ // ignore
95
+ }
96
+ }
97
+ return new ConsoleFormatter({
98
+ id: options.id,
99
+ type: msg.type(),
100
+ text: msg.text(),
101
+ argCount: resolvedArgs.length || msg.args().length,
102
+ resolvedArgs,
103
+ stack,
104
+ isIgnored,
105
+ });
106
+ }
107
+ // The short format for a console message.
108
+ toString() {
109
+ return convertConsoleMessageConciseToString(this.toJSON());
110
+ }
111
+ // The verbose format for a console message, including all details.
112
+ toStringDetailed() {
113
+ return convertConsoleMessageConciseDetailedToString(this.toJSONDetailed());
114
+ }
115
+ #getArgs() {
116
+ if (this.#resolvedArgs.length > 0) {
117
+ const args = [...this.#resolvedArgs];
118
+ // If there is no text, the first argument serves as text (see formatMessage).
119
+ if (!this.#text) {
120
+ args.shift();
121
+ }
122
+ return args;
123
+ }
124
+ return [];
125
+ }
126
+ toJSON() {
127
+ return {
128
+ type: this.#type,
129
+ text: this.#text,
130
+ argsCount: this.#argCount,
131
+ id: this.#id,
132
+ };
133
+ }
134
+ /**
135
+ * Groups consecutive messages with the same type, text, and argument count.
136
+ * Similar to Chrome DevTools' console grouping behavior.
137
+ */
138
+ static groupConsecutive(messages) {
139
+ const grouped = [];
140
+ for (const msg of messages) {
141
+ const prev = grouped[grouped.length - 1];
142
+ if (prev &&
143
+ prev.message instanceof ConsoleFormatter &&
144
+ msg instanceof ConsoleFormatter &&
145
+ prev.message.#type === msg.#type &&
146
+ prev.message.#text === msg.#text &&
147
+ prev.message.#argCount === msg.#argCount) {
148
+ prev.count++;
149
+ }
150
+ else {
151
+ grouped.push({ message: msg, count: 1 });
152
+ }
153
+ }
154
+ return grouped.map(({ message, count }) => count > 1 && message instanceof ConsoleFormatter
155
+ ? new GroupedConsoleFormatter({
156
+ id: message.#id,
157
+ type: message.#type,
158
+ text: message.#text,
159
+ argCount: message.#argCount,
160
+ isIgnored: message.isIgnored,
161
+ }, count)
162
+ : message);
163
+ }
164
+ toJSONDetailed() {
165
+ return {
166
+ id: this.#id,
167
+ type: this.#type,
168
+ text: this.#text,
169
+ argsCount: this.#argCount,
170
+ args: this.#getArgs().map(arg => formatArg(arg, this)),
171
+ stackTrace: this.#stack
172
+ ? formatStackTrace(this.#stack, this.#cause, this)
173
+ : undefined,
174
+ };
175
+ }
176
+ }
177
+ export class GroupedConsoleFormatter extends ConsoleFormatter {
178
+ #count;
179
+ constructor(params, count) {
180
+ super(params);
181
+ this.#count = count;
182
+ }
183
+ toString() {
184
+ return convertConsoleMessageConciseToString(this.toJSON());
185
+ }
186
+ toJSON() {
187
+ const json = super.toJSON();
188
+ json.count = this.#count;
189
+ return json;
190
+ }
191
+ }
192
+ function convertConsoleMessageConciseToString(msg) {
193
+ const countSuffix = msg.count && msg.count > 1 ? ` [${msg.count} times]` : '';
194
+ return `msgid=${msg.id} [${msg.type}] ${msg.text} (${msg.argsCount} args)${countSuffix}`;
195
+ }
196
+ function convertConsoleMessageConciseDetailedToString(msg) {
197
+ const result = [
198
+ `ID: ${msg.id}`,
199
+ `Message: ${msg.type}> ${msg.text}`,
200
+ formatArgs(msg),
201
+ ...(msg.stackTrace ? ['### Stack trace', msg.stackTrace] : []),
202
+ ].filter(line => !!line);
203
+ return result.join('\n');
204
+ }
205
+ function formatArgs(msg) {
206
+ const args = msg.args;
207
+ if (!args.length) {
208
+ return '';
209
+ }
210
+ const result = ['### Arguments'];
211
+ for (const [key, arg] of args.entries()) {
212
+ result.push(`Arg #${key}: ${arg}`);
213
+ }
214
+ return result.join('\n');
215
+ }
216
+ function formatArg(arg, formatter) {
217
+ if (arg instanceof SymbolizedError) {
218
+ return [
219
+ arg.message,
220
+ arg.stackTrace
221
+ ? formatStackTrace(arg.stackTrace, arg.cause, formatter)
222
+ : undefined,
223
+ ]
224
+ .filter(line => !!line)
225
+ .join('\n');
226
+ }
227
+ return typeof arg === 'object' ? JSON.stringify(arg) : String(arg);
228
+ }
229
+ const STACK_TRACE_MAX_LINES = 50;
230
+ function formatStackTrace(stackTrace, cause, formatter) {
231
+ const lines = formatStackTraceInner(stackTrace, cause, formatter);
232
+ const includedLines = lines.slice(0, STACK_TRACE_MAX_LINES);
233
+ const reminderCount = lines.length - includedLines.length;
234
+ return [
235
+ ...includedLines,
236
+ reminderCount > 0 ? `... and ${reminderCount} more frames` : '',
237
+ 'Note: line and column numbers use 1-based indexing',
238
+ ]
239
+ .filter(line => !!line)
240
+ .join('\n');
241
+ }
242
+ function formatStackTraceInner(stackTrace, cause, formatter) {
243
+ if (!stackTrace) {
244
+ return [];
245
+ }
246
+ return [
247
+ ...formatFragment(stackTrace.syncFragment, formatter),
248
+ ...stackTrace.asyncFragments
249
+ .map(item => formatAsyncFragment(item, formatter))
250
+ .flat(),
251
+ ...formatCause(cause, formatter),
252
+ ];
253
+ }
254
+ function formatFragment(fragment, formatter) {
255
+ const frames = fragment.frames.filter(frame => !formatter.isIgnored(frame));
256
+ return frames.map(formatFrame);
257
+ }
258
+ function formatAsyncFragment(fragment, formatter) {
259
+ const formattedFrames = formatFragment(fragment, formatter);
260
+ if (formattedFrames.length === 0) {
261
+ return [];
262
+ }
263
+ const separatorLineLength = 40;
264
+ const prefix = `--- ${fragment.description || 'async'} `;
265
+ const separator = prefix + '-'.repeat(separatorLineLength - prefix.length);
266
+ return [separator, ...formattedFrames];
267
+ }
268
+ function formatFrame(frame) {
269
+ let result = `at ${frame.name ?? '<anonymous>'}`;
270
+ if (frame.uiSourceCode) {
271
+ const location = frame.uiSourceCode.uiLocation(frame.line, frame.column);
272
+ result += ` (${location.linkText(/* skipTrim */ false, /* showColumnNumber */ true)})`;
273
+ }
274
+ else if (frame.url) {
275
+ result += ` (${frame.url}:${frame.line}:${frame.column})`;
276
+ }
277
+ return result;
278
+ }
279
+ function formatCause(cause, formatter) {
280
+ if (!cause) {
281
+ return [];
282
+ }
283
+ return [
284
+ `Caused by: ${cause.message}`,
285
+ ...formatStackTraceInner(cause.stackTrace, cause.cause, formatter),
286
+ ];
287
+ }
288
+ //# sourceMappingURL=ConsoleFormatter.js.map
@@ -0,0 +1,54 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { stableIdSymbol } from '../utils/id.js';
7
+ export function isNodeLike(item) {
8
+ return (typeof item === 'object' && item !== null && 'id' in item && 'name' in item);
9
+ }
10
+ export class HeapSnapshotFormatter {
11
+ #aggregates;
12
+ constructor(aggregates) {
13
+ this.#aggregates = aggregates;
14
+ }
15
+ static formatNodes(items) {
16
+ const lines = [];
17
+ if (items.length > 0 && isNodeLike(items[0])) {
18
+ lines.push('id,name,type,distance,selfSize,retainedSize');
19
+ }
20
+ for (const item of items) {
21
+ if (isNodeLike(item)) {
22
+ lines.push(`${item.id},"${item.name}",${item.type},${item.distance},${item.selfSize},${item.retainedSize}`);
23
+ }
24
+ }
25
+ return lines.join('\n');
26
+ }
27
+ #getSortedAggregates() {
28
+ return Object.values(this.#aggregates).sort((a, b) => b.maxRet - a.maxRet);
29
+ }
30
+ toString() {
31
+ const sorted = this.#getSortedAggregates();
32
+ const lines = [];
33
+ lines.push('uid,className,count,selfSize,maxRetainedSize');
34
+ for (const info of sorted) {
35
+ const uid = info[stableIdSymbol] ?? '';
36
+ lines.push(`${uid},"${info.name}",${info.count},${info.self},${info.maxRet}`);
37
+ }
38
+ return lines.join('\n');
39
+ }
40
+ toJSON() {
41
+ const sorted = this.#getSortedAggregates();
42
+ return sorted.map(info => ({
43
+ uid: info[stableIdSymbol],
44
+ className: info.name,
45
+ count: info.count,
46
+ selfSize: info.self,
47
+ retainedSize: info.maxRet,
48
+ }));
49
+ }
50
+ static sort(aggregates) {
51
+ return Object.entries(aggregates).sort((a, b) => b[1].maxRet - a[1].maxRet);
52
+ }
53
+ }
54
+ //# sourceMappingURL=HeapSnapshotFormatter.js.map