chrome-devtools-frontend 1.0.1616061 → 1.0.1621064

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 (318) hide show
  1. package/AUTHORS +1 -0
  2. package/docs/checklist/README.md +8 -7
  3. package/eslint.config.mjs +7 -0
  4. package/front_end/core/common/Object.ts +11 -2
  5. package/front_end/core/dom_extension/DOMExtension.ts +11 -8
  6. package/front_end/core/host/AidaClient.ts +8 -0
  7. package/front_end/core/host/AidaGcaTranslation.ts +1 -0
  8. package/front_end/core/host/UserMetrics.ts +0 -1
  9. package/front_end/core/platform/api/HostRuntime.ts +2 -2
  10. package/front_end/core/platform/browser/HostRuntime.ts +4 -2
  11. package/front_end/core/platform/node/HostRuntime.ts +2 -2
  12. package/front_end/core/root/ExperimentNames.ts +0 -1
  13. package/front_end/core/sdk/NetworkManager.ts +30 -4
  14. package/front_end/core/sdk/NetworkRequest.ts +2 -10
  15. package/front_end/core/sdk/Resource.ts +2 -1
  16. package/front_end/core/sdk/ServerSentEventsProtocol.ts +1 -1
  17. package/front_end/core/sdk/TraceObject.ts +7 -2
  18. package/front_end/entrypoint_template.html +1 -2
  19. package/front_end/entrypoints/greendev_floaty/FloatyEntrypoint.ts +119 -15
  20. package/front_end/entrypoints/greendev_floaty/greendev_floaty.ts +0 -2
  21. package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +43 -33
  22. package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshotLoader.ts +2 -1
  23. package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshotWorkerDispatcher.ts +9 -6
  24. package/front_end/entrypoints/main/MainImpl.ts +0 -2
  25. package/front_end/generated/InspectorBackendCommands.ts +8 -7
  26. package/front_end/generated/SupportedCSSProperties.js +119 -100
  27. package/front_end/generated/protocol-mapping.d.ts +1 -9
  28. package/front_end/generated/protocol-proxy-api.d.ts +1 -9
  29. package/front_end/generated/protocol.ts +24 -1
  30. package/front_end/legacy/legacy-defs.d.ts +1 -1
  31. package/front_end/models/ai_assistance/AiConversation.ts +1 -0
  32. package/front_end/models/ai_assistance/AiHistoryStorage.ts +39 -0
  33. package/front_end/models/ai_assistance/agents/AiAgent.ts +2 -0
  34. package/front_end/models/ai_assistance/agents/ConversationSummaryAgent.ts +28 -16
  35. package/front_end/models/ai_assistance/agents/GreenDevAgent.ts +512 -0
  36. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +112 -145
  37. package/front_end/models/ai_assistance/agents/README.md +0 -5
  38. package/front_end/models/ai_assistance/agents/StylingAgent.ts +9 -16
  39. package/front_end/models/ai_assistance/ai_assistance.ts +2 -0
  40. package/front_end/models/ai_code_completion/AiCodeCompletion.ts +19 -1
  41. package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +48 -13
  42. package/front_end/models/bindings/SymbolizedError.ts +95 -8
  43. package/front_end/models/emulation/DeviceModeModel.ts +42 -13
  44. package/front_end/models/emulation/EmulatedDevices.ts +1 -1
  45. package/front_end/models/issues_manager/IssuesManager.ts +13 -6
  46. package/front_end/models/issues_manager/IssuesManagerEvents.ts +1 -0
  47. package/front_end/models/javascript_metadata/NativeFunctions.js +2 -2
  48. package/front_end/models/live-metrics/web-vitals-injected/web-vitals-injected.ts +1 -0
  49. package/front_end/models/stack_trace/DetailedErrorStackParser.ts +49 -10
  50. package/front_end/models/stack_trace/ErrorStackParser.ts +18 -0
  51. package/front_end/models/stack_trace/StackTraceModel.ts +5 -1
  52. package/front_end/models/text_utils/ContentData.ts +71 -10
  53. package/front_end/models/trace/types/File.ts +8 -1
  54. package/front_end/models/web_mcp/WebMCPModel.ts +22 -0
  55. package/front_end/models/workspace/UISourceCode.ts +4 -4
  56. package/front_end/panels/accessibility/ARIAAttributesView.ts +4 -4
  57. package/front_end/panels/accessibility/AccessibilitySubPane.ts +3 -2
  58. package/front_end/panels/accessibility/SourceOrderView.ts +4 -4
  59. package/front_end/panels/ai_assistance/ai_assistance.ts +1 -0
  60. package/front_end/panels/ai_assistance/components/ChatInput.ts +66 -0
  61. package/front_end/panels/ai_assistance/components/ChatMessage.ts +144 -21
  62. package/front_end/panels/ai_assistance/components/ChatView.ts +43 -8
  63. package/front_end/panels/ai_assistance/components/ExportForAgentsDialog.ts +1 -0
  64. package/front_end/panels/ai_assistance/components/WalkthroughUtils.ts +74 -0
  65. package/front_end/panels/ai_assistance/components/WalkthroughView.ts +34 -5
  66. package/front_end/panels/ai_assistance/components/chatMessage.css +11 -0
  67. package/front_end/panels/ai_assistance/components/walkthroughView.css +7 -0
  68. package/front_end/panels/application/ApplicationPanelTreeElement.ts +1 -1
  69. package/front_end/panels/application/CookieItemsView.ts +8 -9
  70. package/front_end/panels/application/DOMStorageItemsView.ts +3 -3
  71. package/front_end/panels/application/DeviceBoundSessionsModel.ts +7 -0
  72. package/front_end/panels/application/DeviceBoundSessionsTreeElement.ts +21 -0
  73. package/front_end/panels/application/DeviceBoundSessionsView.ts +2 -2
  74. package/front_end/panels/application/ExtensionStorageItemsView.ts +1 -1
  75. package/front_end/panels/application/KeyValueStorageItemsView.ts +32 -14
  76. package/front_end/panels/application/ResourcesPanel.ts +5 -5
  77. package/front_end/panels/application/StorageItemsToolbar.ts +0 -19
  78. package/front_end/panels/application/WebMCPView.ts +285 -86
  79. package/front_end/panels/application/components/BounceTrackingMitigationsView.ts +4 -4
  80. package/front_end/panels/application/preloading/components/MismatchedPreloadingGrid.ts +4 -4
  81. package/front_end/panels/application/webMCPView.css +261 -182
  82. package/front_end/panels/browser_debugger/CategorizedBreakpointsSidebarPane.ts +9 -5
  83. package/front_end/panels/changes/ChangesSidebar.ts +2 -2
  84. package/front_end/panels/changes/ChangesView.ts +9 -14
  85. package/front_end/panels/console/ConsolePanel.ts +10 -3
  86. package/front_end/panels/console/ConsoleSidebar.ts +5 -5
  87. package/front_end/panels/console/ConsoleView.ts +11 -4
  88. package/front_end/panels/console/ConsoleViewMessage.ts +1 -19
  89. package/front_end/panels/coverage/CoverageView.ts +4 -5
  90. package/front_end/panels/elements/ElementsPanel.ts +9 -12
  91. package/front_end/panels/elements/ElementsSidebarPane.ts +4 -5
  92. package/front_end/panels/elements/ElementsTreeElement.ts +61 -0
  93. package/front_end/panels/elements/ElementsTreeOutline.ts +46 -0
  94. package/front_end/panels/elements/LayersWidget.ts +2 -2
  95. package/front_end/panels/elements/MetricsSidebarPane.ts +5 -4
  96. package/front_end/panels/elements/StylePropertiesSection.ts +1 -1
  97. package/front_end/panels/elements/StylePropertyTreeElement.ts +11 -6
  98. package/front_end/panels/elements/StylesSidebarPane.ts +4 -1
  99. package/front_end/panels/elements/components/ElementsBreadcrumbs.ts +19 -20
  100. package/front_end/panels/elements/components/ElementsBreadcrumbsUtils.ts +29 -29
  101. package/front_end/panels/elements/components/QueryContainer.ts +5 -6
  102. package/front_end/panels/elements/components/components.ts +0 -2
  103. package/front_end/panels/emulation/MediaQueryInspector.ts +4 -7
  104. package/front_end/panels/layer_viewer/LayerDetailsView.ts +4 -7
  105. package/front_end/panels/layer_viewer/Layers3DView.ts +2 -2
  106. package/front_end/panels/lighthouse/LighthouseStartView.ts +2 -2
  107. package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +47 -66
  108. package/front_end/panels/network/NetworkConfigView.ts +11 -11
  109. package/front_end/panels/network/RequestConditionsDrawer.ts +6 -4
  110. package/front_end/panels/network/RequestCookiesView.ts +2 -2
  111. package/front_end/panels/network/RequestDeviceBoundSessionsView.ts +2 -2
  112. package/front_end/panels/network/RequestHeadersView.ts +2 -2
  113. package/front_end/panels/network/components/DirectSocketConnectionView.ts +4 -5
  114. package/front_end/panels/performance_monitor/PerformanceMonitor.ts +6 -9
  115. package/front_end/panels/profiler/HeapProfileView.ts +29 -4
  116. package/front_end/panels/profiler/ProfilesPanel.ts +1 -1
  117. package/front_end/panels/protocol_monitor/JSONEditor.css +8 -1
  118. package/front_end/panels/protocol_monitor/JSONEditor.ts +7 -2
  119. package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +6 -4
  120. package/front_end/panels/recorder/components/ControlButton.ts +4 -4
  121. package/front_end/panels/recorder/components/StepView.ts +6 -6
  122. package/front_end/panels/search/SearchView.ts +4 -7
  123. package/front_end/panels/sources/DebuggerPausedMessage.ts +18 -22
  124. package/front_end/panels/sources/SourcesView.ts +1 -1
  125. package/front_end/panels/sources/TabbedEditorContainer.ts +2 -2
  126. package/front_end/panels/sources/ThreadsSidebarPane.ts +2 -4
  127. package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +24 -20
  128. package/front_end/panels/timeline/StatusDialog.ts +5 -8
  129. package/front_end/panels/timeline/ThirdPartyTreeView.ts +10 -0
  130. package/front_end/panels/timeline/TimelineLoader.ts +3 -4
  131. package/front_end/panels/timeline/TimelineSelectorStatsView.ts +2 -2
  132. package/front_end/panels/timeline/components/TimelineRangeSummaryView.ts +2 -0
  133. package/front_end/panels/timeline/components/TimelineSummary.ts +9 -1
  134. package/front_end/panels/timeline/components/timelineSummary.css +4 -0
  135. package/front_end/panels/timeline/overlays/components/TimespanBreakdownOverlay.ts +2 -2
  136. package/front_end/panels/timeline/thirdPartyTreeView.css +8 -1
  137. package/front_end/panels/web_audio/WebAudioView.ts +5 -4
  138. package/front_end/panels/whats_new/ReleaseNoteText.ts +9 -9
  139. package/front_end/panels/whats_new/resources/WNDT.md +9 -6
  140. package/front_end/third_party/chromium/README.chromium +1 -1
  141. package/front_end/third_party/puppeteer/README.chromium +2 -2
  142. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/ElementHandle.d.ts +41 -2
  143. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/ElementHandle.d.ts.map +1 -1
  144. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/ElementHandle.js.map +1 -1
  145. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Extension.d.ts +13 -1
  146. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Extension.d.ts.map +1 -1
  147. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Extension.js +21 -1
  148. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Extension.js.map +1 -1
  149. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/ElementHandle.d.ts.map +1 -1
  150. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/ElementHandle.js +1 -0
  151. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/ElementHandle.js.map +1 -1
  152. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.d.ts +2 -2
  153. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.d.ts.map +1 -1
  154. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.js +5 -5
  155. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.js.map +1 -1
  156. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/BrowserConnector.d.ts.map +1 -1
  157. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/BrowserConnector.js +2 -2
  158. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/BrowserConnector.js.map +1 -1
  159. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/ElementHandle.d.ts.map +1 -1
  160. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/ElementHandle.js +1 -0
  161. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/ElementHandle.js.map +1 -1
  162. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Extension.d.ts +1 -1
  163. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Extension.d.ts.map +1 -1
  164. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Extension.js +2 -2
  165. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Extension.js.map +1 -1
  166. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/TargetManager.d.ts +1 -1
  167. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/TargetManager.d.ts.map +1 -1
  168. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/TargetManager.js +52 -1
  169. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/TargetManager.js.map +1 -1
  170. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/WebMCP.d.ts.map +1 -1
  171. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/WebMCP.js.map +1 -1
  172. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ConnectOptions.d.ts +25 -0
  173. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ConnectOptions.d.ts.map +1 -1
  174. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
  175. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.d.ts.map +1 -1
  176. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js +2 -2
  177. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js.map +1 -1
  178. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.d.ts.map +1 -1
  179. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.js +0 -1
  180. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.js.map +1 -1
  181. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +2 -2
  182. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +2 -2
  183. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
  184. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.d.ts +1 -1
  185. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.js +1 -1
  186. package/front_end/third_party/puppeteer/package/lib/cjs/third_party/urlpattern-polyfill/urlpattern-polyfill.d.ts +1 -0
  187. package/front_end/third_party/puppeteer/package/lib/cjs/third_party/urlpattern-polyfill/urlpattern-polyfill.js +853 -0
  188. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +91 -11
  189. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +1046 -33
  190. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/ElementHandle.d.ts +41 -2
  191. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/ElementHandle.d.ts.map +1 -1
  192. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/ElementHandle.js.map +1 -1
  193. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Extension.d.ts +13 -1
  194. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Extension.d.ts.map +1 -1
  195. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Extension.js +21 -1
  196. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Extension.js.map +1 -1
  197. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/ElementHandle.d.ts.map +1 -1
  198. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/ElementHandle.js +1 -0
  199. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/ElementHandle.js.map +1 -1
  200. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.d.ts +2 -2
  201. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.d.ts.map +1 -1
  202. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.js +5 -5
  203. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.js.map +1 -1
  204. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/BrowserConnector.d.ts.map +1 -1
  205. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/BrowserConnector.js +2 -2
  206. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/BrowserConnector.js.map +1 -1
  207. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/ElementHandle.d.ts.map +1 -1
  208. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/ElementHandle.js +1 -0
  209. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/ElementHandle.js.map +1 -1
  210. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Extension.d.ts +1 -1
  211. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Extension.d.ts.map +1 -1
  212. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Extension.js +2 -2
  213. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Extension.js.map +1 -1
  214. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/TargetManager.d.ts +1 -1
  215. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/TargetManager.d.ts.map +1 -1
  216. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/TargetManager.js +52 -1
  217. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/TargetManager.js.map +1 -1
  218. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/WebMCP.d.ts.map +1 -1
  219. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/WebMCP.js.map +1 -1
  220. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/ConnectOptions.d.ts +25 -0
  221. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/ConnectOptions.d.ts.map +1 -1
  222. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/injected/injected.d.ts +1 -1
  223. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.d.ts.map +1 -1
  224. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js +2 -2
  225. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js.map +1 -1
  226. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.d.ts.map +1 -1
  227. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.js +0 -1
  228. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.js.map +1 -1
  229. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +2 -2
  230. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +2 -2
  231. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/Mutex.d.ts +2 -2
  232. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.d.ts +1 -1
  233. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.js +1 -1
  234. package/front_end/third_party/puppeteer/package/lib/esm/third_party/urlpattern-polyfill/urlpattern-polyfill.d.ts +1 -0
  235. package/front_end/third_party/puppeteer/package/lib/esm/third_party/urlpattern-polyfill/urlpattern-polyfill.js +805 -0
  236. package/front_end/third_party/puppeteer/package/lib/types.d.ts +91 -11
  237. package/front_end/third_party/puppeteer/package/package.json +3 -2
  238. package/front_end/third_party/puppeteer/package/src/api/ElementHandle.ts +53 -11
  239. package/front_end/third_party/puppeteer/package/src/api/Extension.ts +29 -1
  240. package/front_end/third_party/puppeteer/package/src/bidi/ElementHandle.ts +1 -0
  241. package/front_end/third_party/puppeteer/package/src/cdp/Browser.ts +6 -0
  242. package/front_end/third_party/puppeteer/package/src/cdp/BrowserConnector.ts +2 -0
  243. package/front_end/third_party/puppeteer/package/src/cdp/ElementHandle.ts +1 -0
  244. package/front_end/third_party/puppeteer/package/src/cdp/Extension.ts +9 -2
  245. package/front_end/third_party/puppeteer/package/src/cdp/TargetManager.ts +59 -0
  246. package/front_end/third_party/puppeteer/package/src/cdp/WebMCP.ts +6 -1
  247. package/front_end/third_party/puppeteer/package/src/common/ConnectOptions.ts +26 -0
  248. package/front_end/third_party/puppeteer/package/src/node/BrowserLauncher.ts +2 -0
  249. package/front_end/third_party/puppeteer/package/src/node/ChromeLauncher.ts +0 -1
  250. package/front_end/third_party/puppeteer/package/src/revisions.ts +2 -2
  251. package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
  252. package/front_end/third_party/puppeteer/puppeteer-tsconfig.json +2 -1
  253. package/front_end/third_party/web-vitals/README.chromium +2 -2
  254. package/front_end/third_party/web-vitals/package/README.md +21 -10
  255. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onCLS.js +2 -4
  256. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onFCP.js +1 -2
  257. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onINP.d.ts +4 -0
  258. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onINP.js +44 -39
  259. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onLCP.js +25 -19
  260. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onTTFB.js +1 -2
  261. package/front_end/third_party/web-vitals/package/dist/modules/lib/doubleRAF.js +1 -1
  262. package/front_end/third_party/web-vitals/package/dist/modules/lib/getActivationStart.js +1 -2
  263. package/front_end/third_party/web-vitals/package/dist/modules/lib/getLoadState.js +16 -18
  264. package/front_end/third_party/web-vitals/package/dist/modules/lib/getVisibilityWatcher.js +2 -1
  265. package/front_end/third_party/web-vitals/package/dist/modules/lib/initMetric.d.ts +1 -1
  266. package/front_end/third_party/web-vitals/package/dist/modules/lib/observe.js +1 -1
  267. package/front_end/third_party/web-vitals/package/dist/modules/lib/polyfills/interactionCountPolyfill.d.ts +1 -1
  268. package/front_end/third_party/web-vitals/package/dist/modules/lib/polyfills/interactionCountPolyfill.js +1 -3
  269. package/front_end/third_party/web-vitals/package/dist/modules/lib/whenActivated.js +1 -1
  270. package/front_end/third_party/web-vitals/package/dist/modules/lib/whenIdleOrHidden.js +11 -7
  271. package/front_end/third_party/web-vitals/package/dist/modules/onCLS.js +1 -1
  272. package/front_end/third_party/web-vitals/package/dist/modules/types/inp.d.ts +4 -0
  273. package/front_end/third_party/web-vitals/package/dist/modules/types.d.ts +1 -2
  274. package/front_end/third_party/web-vitals/package/dist/modules/types.js +0 -1
  275. package/front_end/third_party/web-vitals/package/package.json +24 -27
  276. package/front_end/third_party/web-vitals/package/src/attribution/onCLS.ts +2 -7
  277. package/front_end/third_party/web-vitals/package/src/attribution/onFCP.ts +1 -2
  278. package/front_end/third_party/web-vitals/package/src/attribution/onINP.ts +49 -43
  279. package/front_end/third_party/web-vitals/package/src/attribution/onLCP.ts +27 -24
  280. package/front_end/third_party/web-vitals/package/src/attribution/onTTFB.ts +1 -2
  281. package/front_end/third_party/web-vitals/package/src/lib/doubleRAF.ts +1 -1
  282. package/front_end/third_party/web-vitals/package/src/lib/getActivationStart.ts +1 -2
  283. package/front_end/third_party/web-vitals/package/src/lib/getLoadState.ts +21 -20
  284. package/front_end/third_party/web-vitals/package/src/lib/getVisibilityWatcher.ts +2 -3
  285. package/front_end/third_party/web-vitals/package/src/lib/observe.ts +1 -1
  286. package/front_end/third_party/web-vitals/package/src/lib/polyfills/interactionCountPolyfill.ts +2 -4
  287. package/front_end/third_party/web-vitals/package/src/lib/whenActivated.ts +1 -1
  288. package/front_end/third_party/web-vitals/package/src/lib/whenIdleOrHidden.ts +13 -7
  289. package/front_end/third_party/web-vitals/package/src/onCLS.ts +1 -1
  290. package/front_end/third_party/web-vitals/package/src/types/inp.ts +4 -0
  291. package/front_end/third_party/web-vitals/package/src/types.ts +1 -2
  292. package/front_end/third_party/web-vitals/patches/0001-Add-onEachInteraction-to-onINP-options.patch +13 -74
  293. package/front_end/third_party/web-vitals/rebuild.sh +3 -3
  294. package/front_end/third_party/web-vitals/web-vitals-tsconfig.json +0 -1
  295. package/front_end/ui/components/icon_button/iconButton.css +1 -0
  296. package/front_end/ui/components/legacy_wrapper/LegacyWrapper.ts +6 -6
  297. package/front_end/ui/components/lists/list.css +4 -0
  298. package/front_end/ui/legacy/Dialog.ts +21 -2
  299. package/front_end/ui/legacy/SoftContextMenu.ts +3 -3
  300. package/front_end/ui/legacy/SplitWidget.ts +9 -9
  301. package/front_end/ui/legacy/TabbedPane.ts +12 -12
  302. package/front_end/ui/legacy/View.ts +24 -22
  303. package/front_end/ui/legacy/ViewManager.ts +12 -12
  304. package/front_end/ui/legacy/ViewRegistration.ts +2 -2
  305. package/front_end/ui/legacy/Widget.ts +165 -119
  306. package/front_end/ui/legacy/components/source_frame/ImageView.ts +10 -5
  307. package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +9 -6
  308. package/front_end/ui/legacy/components/utils/Linkifier.ts +37 -11
  309. package/front_end/ui/legacy/components/utils/jsUtils.css +1 -0
  310. package/front_end/ui/legacy/inspectorCommon.css +0 -6
  311. package/front_end/ui/lit/render.ts +11 -9
  312. package/front_end/ui/visual_logging/KnownContextValues.ts +36 -0
  313. package/package.json +1 -1
  314. package/front_end/Images/src/dots-circle.svg +0 -10
  315. package/front_end/panels/elements/components/Helper.ts +0 -35
  316. package/front_end/third_party/web-vitals/package/dist/modules/types/polyfills.d.ts +0 -4
  317. package/front_end/third_party/web-vitals/package/dist/modules/types/polyfills.js +0 -16
  318. package/front_end/third_party/web-vitals/package/src/types/polyfills.ts +0 -24
@@ -106,9 +106,6 @@ export class StorageItemsToolbar extends
106
106
  #deleteAllButtonIconName = 'clear';
107
107
  #deleteAllButtonTitle: string = i18nString(UIStrings.clearAll);
108
108
  #mainToolbarItems: UI.Toolbar.ToolbarItem[] = [];
109
- #onRefreshCallback?: () => void;
110
- #onDeleteAllCallback?: () => void;
111
- #onDeleteSelectedCallback?: () => void;
112
109
 
113
110
  constructor(element?: HTMLElement, view: View = DEFAULT_VIEW) {
114
111
  super(element);
@@ -116,18 +113,6 @@ export class StorageItemsToolbar extends
116
113
  this.filterRegex = null;
117
114
  }
118
115
 
119
- set onRefreshCallback(callback: () => void) {
120
- this.#onRefreshCallback = callback;
121
- }
122
-
123
- set onDeleteAllCallback(callback: () => void) {
124
- this.#onDeleteAllCallback = callback;
125
- }
126
-
127
- set onDeleteSelectedCallback(callback: () => void) {
128
- this.#onDeleteSelectedCallback = callback;
129
- }
130
-
131
116
  set metadataView(view: ApplicationComponents.StorageMetadataView.StorageMetadataView) {
132
117
  this.#metadataView = view;
133
118
  }
@@ -150,16 +135,13 @@ export class StorageItemsToolbar extends
150
135
  metadataView: this.metadataView,
151
136
  onFilterChanged: this.filterChanged.bind(this),
152
137
  onRefresh: () => {
153
- this.#onRefreshCallback?.();
154
138
  this.dispatchEventToListeners(StorageItemsToolbar.Events.REFRESH);
155
139
  UI.ARIAUtils.LiveAnnouncer.alert(i18nString(UIStrings.refreshedStatus));
156
140
  },
157
141
  onDeleteAll: () => {
158
- this.#onDeleteAllCallback?.();
159
142
  this.dispatchEventToListeners(StorageItemsToolbar.Events.DELETE_ALL);
160
143
  },
161
144
  onDeleteSelected: () => {
162
- this.#onDeleteSelectedCallback?.();
163
145
  this.dispatchEventToListeners(StorageItemsToolbar.Events.DELETE_SELECTED);
164
146
  },
165
147
  };
@@ -187,7 +169,6 @@ export class StorageItemsToolbar extends
187
169
 
188
170
  filterChanged({detail: text}: CustomEvent<string|null>): void {
189
171
  this.filterRegex = text ? new RegExp(Platform.StringUtilities.escapeForRegExp(text), 'i') : null;
190
- this.#onRefreshCallback?.();
191
172
  this.dispatchEventToListeners(StorageItemsToolbar.Events.REFRESH);
192
173
  }
193
174
 
@@ -167,6 +167,26 @@ const UIStrings = {
167
167
  * @description Context menu action to copy the description of a tool
168
168
  */
169
169
  copyDescription: 'Copy description',
170
+ /**
171
+ * @description Text for the header of the tool run section
172
+ */
173
+ runTool: 'Run Tool',
174
+ /**
175
+ * @description Context menu action to reveal the tool in the tool list
176
+ */
177
+ revealTool: 'Reveal tool',
178
+ /**
179
+ * @description Context menu action to edit and run the tool
180
+ */
181
+ editAndRun: 'Edit and run',
182
+ /**
183
+ * @description Tooltip for the paste button
184
+ */
185
+ paste: 'Paste',
186
+ /**
187
+ * @description Notice to display when a tool has been unregistered
188
+ */
189
+ toolUnregisteredNotice: 'This tool has been unregistered',
170
190
  } as const;
171
191
  const str_ = i18n.i18n.registerUIStrings('panels/application/WebMCPView.ts', UIStrings);
172
192
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
@@ -182,6 +202,7 @@ export interface FilterState {
182
202
  completed?: boolean,
183
203
  error?: boolean,
184
204
  pending?: boolean,
205
+ canceled?: boolean,
185
206
  };
186
207
  }
187
208
 
@@ -194,10 +215,15 @@ export interface FilterMenuButtons {
194
215
  toolTypes: FilterMenuButton;
195
216
  statusTypes: FilterMenuButton;
196
217
  }
218
+ export interface SelectedTool {
219
+ tool: WebMCP.WebMCPModel.Tool;
220
+ parameters?: Record<string, unknown>;
221
+ }
197
222
  export interface ViewInput {
198
223
  tools: WebMCP.WebMCPModel.Tool[];
199
- selectedTool: WebMCP.WebMCPModel.Tool|null;
224
+ selectedTool: SelectedTool|null;
200
225
  onToolSelect: (tool: WebMCP.WebMCPModel.Tool|null) => void;
226
+ onRevealTool: (tool: WebMCP.WebMCPModel.Tool, parameters?: Record<string, unknown>) => void;
201
227
  selectedCall: WebMCP.WebMCPModel.Call|null;
202
228
  onCallSelect: (call: WebMCP.WebMCPModel.Call|null) => void;
203
229
  filters: FilterState;
@@ -205,6 +231,8 @@ export interface ViewInput {
205
231
  onClearLogClick: () => void;
206
232
  onFilterChange: (filters: FilterState) => void;
207
233
  toolCalls: WebMCP.WebMCPModel.Call[];
234
+ onRunTool: (event: Common.EventTarget.EventTargetEvent<ProtocolMonitor.JSONEditor.Command>) => void;
235
+ onPaste: () => void;
208
236
  }
209
237
 
210
238
  export function filterToolCalls(
@@ -214,13 +242,16 @@ export function filterToolCalls(
214
242
  const statusTypes = filterState.statusTypes;
215
243
  if (statusTypes) {
216
244
  filtered = filtered.filter(call => {
217
- const {completed, error, pending} = statusTypes;
245
+ const {completed, error, pending, canceled} = statusTypes;
218
246
  if (completed && call.result?.status === Protocol.WebMCP.InvocationStatus.Completed) {
219
247
  return true;
220
248
  }
221
249
  if (error && call.result?.status === Protocol.WebMCP.InvocationStatus.Error) {
222
250
  return true;
223
251
  }
252
+ if (canceled && call.result?.status === Protocol.WebMCP.InvocationStatus.Canceled) {
253
+ return true;
254
+ }
224
255
  if (pending && call.result === undefined) {
225
256
  return true;
226
257
  }
@@ -254,63 +285,54 @@ export function filterToolCalls(
254
285
  return filtered;
255
286
  }
256
287
  export type View = (input: ViewInput, output: object, target: HTMLElement) => void;
288
+
289
+ type ToolStats = Map<Protocol.WebMCP.InvocationStatus|undefined, number>;
290
+
257
291
  function calculateToolStats(calls: WebMCP.WebMCPModel.Call[]):
258
- {total: number, completed: number, failed: number, canceled: number, inProgress: number} {
259
- let total = 0, completed = 0, failed = 0, canceled = 0, inProgress = 0;
292
+ {stats: Map<WebMCP.WebMCPModel.Tool, ToolStats>, totals: ToolStats} {
293
+ const stats = new Map<WebMCP.WebMCPModel.Tool, ToolStats>();
294
+ const totals: ToolStats = new Map();
295
+
260
296
  for (const call of calls) {
261
- total++;
262
- if (call.result?.status === Protocol.WebMCP.InvocationStatus.Error) {
263
- failed++;
264
- } else if (call.result?.status === Protocol.WebMCP.InvocationStatus.Canceled) {
265
- canceled++;
266
- } else if (call.result?.status === Protocol.WebMCP.InvocationStatus.Completed) {
267
- completed++;
268
- } else if (call.result === undefined) {
269
- inProgress++;
297
+ let toolStats = stats.get(call.tool);
298
+ if (!toolStats) {
299
+ toolStats = new Map();
300
+ stats.set(call.tool, toolStats);
270
301
  }
302
+ toolStats.set(call.result?.status, (toolStats.get(call.result?.status) ?? 0) + 1);
303
+ totals.set(call.result?.status, (totals.get(call.result?.status) ?? 0) + 1);
271
304
  }
272
- return {total, completed, failed, canceled, inProgress};
305
+ return {totals, stats};
273
306
  }
274
307
 
275
- function getIconGroupsFromStats(toolStats: ReturnType<typeof calculateToolStats>):
276
- IconButton.IconButton.IconWithTextData[] {
277
- const groups = [];
278
- if (toolStats.completed > 0) {
279
- groups.push({
280
- iconName: 'check-circle',
281
- iconColor: 'var(--sys-color-green)',
282
- iconWidth: '16px',
283
- iconHeight: '16px',
284
- text: String(toolStats.completed),
285
- });
286
- }
287
- if (toolStats.failed > 0) {
288
- groups.push({
289
- iconName: 'cross-circle-filled',
290
- iconColor: 'var(--sys-color-error)',
291
- iconWidth: '16px',
292
- iconHeight: '16px',
293
- text: String(toolStats.failed),
294
- });
295
- }
296
- if (toolStats.canceled > 0) {
297
- groups.push({
298
- iconName: 'record-stop',
299
- iconColor: 'var(--sys-color-on-surface-light)',
300
- iconWidth: '16px',
301
- iconHeight: '16px',
302
- text: String(toolStats.canceled),
303
- });
304
- }
305
- if (toolStats.inProgress > 0) {
306
- groups.push({
307
- iconName: 'dots-circle',
308
- iconWidth: '16px',
309
- iconHeight: '16px',
310
- text: String(toolStats.inProgress),
311
- });
308
+ function toolStatsIcon(status: Protocol.WebMCP.InvocationStatus|undefined): {iconName: string, iconColor?: string} {
309
+ switch (status) {
310
+ case Protocol.WebMCP.InvocationStatus.Completed:
311
+ return {iconName: 'check-circle', iconColor: 'var(--sys-color-green)'};
312
+ case Protocol.WebMCP.InvocationStatus.Error:
313
+ return {iconName: 'cross-circle-filled', iconColor: 'var(--sys-color-error)'};
314
+ case Protocol.WebMCP.InvocationStatus.Canceled:
315
+ return {iconName: 'record-stop', iconColor: 'var(--sys-color-on-surface-light)'};
316
+ case undefined:
317
+ return {iconName: 'watch'};
312
318
  }
313
- return groups;
319
+ }
320
+
321
+ function getIconGroupsFromStats(toolStats?: ToolStats):
322
+ Array<IconButton.IconButton.IconWithTextData&{status: Protocol.WebMCP.InvocationStatus | undefined}> {
323
+ const status = [
324
+ Protocol.WebMCP.InvocationStatus.Completed, Protocol.WebMCP.InvocationStatus.Error,
325
+ Protocol.WebMCP.InvocationStatus.Canceled, undefined
326
+ ];
327
+ return status
328
+ .map(status => ({
329
+ ...toolStatsIcon(status),
330
+ iconWidth: 'var(--sys-size-8)',
331
+ iconHeight: 'var(--sys-size-8)',
332
+ text: String(toolStats?.get(status) ?? 0),
333
+ status,
334
+ }))
335
+ .filter(({text}) => text !== '0');
314
336
  }
315
337
 
316
338
  export function parsePayload(payload?: unknown): {
@@ -330,9 +352,32 @@ export function parsePayload(payload?: unknown): {
330
352
  return {valueObject: payload, valueString: undefined};
331
353
  }
332
354
 
355
+ export function getJSONEditorParameters(tool: WebMCP.WebMCPModel.Tool): {
356
+ metadataByCommand: Map<string, {
357
+ parameters: ProtocolMonitor.JSONEditor.Parameter[],
358
+ description: string,
359
+ replyArgs: string[],
360
+ }>,
361
+ typesByName: Map<string, ProtocolMonitor.JSONEditor.Parameter[]>,
362
+ enumsByName: Map<string, Record<string, string>>,
363
+ } {
364
+ const parsedSchema = parseToolSchema(tool.inputSchema);
365
+ const metadataByCommand = new Map();
366
+ metadataByCommand.set(tool.name, {
367
+ parameters: parsedSchema.parameters,
368
+ description: tool.description,
369
+ replyArgs: [],
370
+ });
371
+ return {
372
+ metadataByCommand,
373
+ typesByName: parsedSchema.typesByName,
374
+ enumsByName: parsedSchema.enumsByName,
375
+ };
376
+ }
333
377
  export const DEFAULT_VIEW: View = (input, output, target) => {
334
378
  const tools = input.tools;
335
- const stats = calculateToolStats(input.toolCalls);
379
+ let editorWidget: ProtocolMonitor.JSONEditor.JSONEditor|null = null;
380
+ const toolStats = calculateToolStats(input.toolCalls);
336
381
  const isFilterActive =
337
382
  Boolean(input.filters.text) || Boolean(input.filters.toolTypes) || Boolean(input.filters.statusTypes);
338
383
  const iconName = (call: WebMCP.WebMCPModel.Call): string => {
@@ -342,7 +387,7 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
342
387
  case Protocol.WebMCP.InvocationStatus.Canceled:
343
388
  return 'record-stop';
344
389
  case undefined:
345
- return 'dots-circle';
390
+ return 'watch';
346
391
  default:
347
392
  return '';
348
393
  }
@@ -359,6 +404,23 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
359
404
  return i18nString(UIStrings.inProgress);
360
405
  }
361
406
  };
407
+ const onIconClick = (toolName: string, status: Protocol.WebMCP.InvocationStatus|undefined): void => {
408
+ let statusTypes: FilterState['statusTypes'] = undefined;
409
+ if (status === Protocol.WebMCP.InvocationStatus.Completed) {
410
+ statusTypes = {completed: true};
411
+ } else if (status === Protocol.WebMCP.InvocationStatus.Error) {
412
+ statusTypes = {error: true};
413
+ } else if (status === Protocol.WebMCP.InvocationStatus.Canceled) {
414
+ statusTypes = {canceled: true};
415
+ } else if (status === undefined) {
416
+ statusTypes = {pending: true};
417
+ }
418
+ input.onFilterChange({
419
+ ...input.filters,
420
+ text: toolName,
421
+ statusTypes,
422
+ });
423
+ };
362
424
  const onToolContextMenu = (event: Event, tool: WebMCP.WebMCPModel.Tool): void => {
363
425
  const contextMenu = new UI.ContextMenu.ContextMenu(event);
364
426
  contextMenu.defaultSection().appendItem(i18nString(UIStrings.copyName), () => {
@@ -384,9 +446,9 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
384
446
  <div class="toolbar-divider"></div>
385
447
  <devtools-toolbar-input type="filter"
386
448
  placeholder=${i18nString(UIStrings.filter)}
387
- .value=${input.filters.text}
388
449
  @change=${(e: CustomEvent<string>) =>
389
- input.onFilterChange({...input.filters, text: e.detail})}>
450
+ input.onFilterChange({...input.filters, text: e.detail})}
451
+ .value=${input.filters.text}>
390
452
  </devtools-toolbar-input>
391
453
  <div class="toolbar-divider"></div>
392
454
  ${input.filterButtons.toolTypes.button.element}
@@ -425,8 +487,34 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
425
487
  'status-error': call.result?.status === Protocol.WebMCP.InvocationStatus.Error,
426
488
  'status-cancelled': call.result?.status === Protocol.WebMCP.InvocationStatus.Canceled,
427
489
  selected: call === input.selectedCall,
428
- })} @click=${() => input.onCallSelect(call)}>
429
- <td>${call.tool.name}</td>
490
+ })} @click=${() => input.onCallSelect(call)}
491
+ @contextmenu=${(e: CustomEvent<UI.ContextMenu.ContextMenu>) => {
492
+ const contextMenu = e.detail;
493
+ const isUnregistered = !input.tools.includes(call.tool);
494
+ contextMenu.defaultSection().appendItem(i18nString(UIStrings.revealTool), () => {
495
+ input.onRevealTool(call.tool);
496
+ }, {jslogContext: 'webmcp.reveal-tool', disabled: isUnregistered});
497
+ contextMenu.defaultSection().appendItem(i18nString(UIStrings.editAndRun), () => {
498
+ const payload = parsePayload(call.input);
499
+ input.onRevealTool(call.tool, payload.valueObject as Record<string, unknown> | undefined);
500
+ }, {jslogContext: 'webmcp.edit-and-run', disabled: isUnregistered});
501
+ }}>
502
+ <td>
503
+ <div class="name-cell">
504
+ <span>${call.tool.name}</span>
505
+ <button class="run-tool-action-button"
506
+ title=${i18nString(UIStrings.editAndRun)}
507
+ aria-label=${i18nString(UIStrings.editAndRun)}
508
+ @click=${(e: Event) => {
509
+ e.stopPropagation();
510
+ const payload = parsePayload(call.input);
511
+ input.onRevealTool(call.tool,
512
+ payload.valueObject as Record<string, unknown> | undefined);
513
+ }}>
514
+ <devtools-icon name="goto-filled"></devtools-icon>
515
+ </button>
516
+ </div>
517
+ </td>
430
518
  <td>
431
519
  <div class="status-cell">
432
520
  ${iconName(call) ? html`<devtools-icon class="small" name=${iconName(call)}></devtools-icon>`
@@ -457,7 +545,7 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
457
545
  <devtools-widget
458
546
  id="webmcp.tool-details"
459
547
  title=${i18nString(UIStrings.toolDetails)}
460
- ${widget(ToolDetailsWidget, {tool: input.selectedCall?.tool})}>
548
+ ${widget(ToolDetailsWidget, {tool: input.selectedCall?.tool, isUnregistered: input.selectedCall ? !input.tools.includes(input.selectedCall.tool) : false})}>
461
549
  </devtools-widget>
462
550
  <devtools-widget
463
551
  id="webmcp.call-inputs"
@@ -478,14 +566,18 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
478
566
  </devtools-split-view>
479
567
  <div class="webmcp-toolbar-container" role="toolbar">
480
568
  <devtools-toolbar class="webmcp-toolbar" role="presentation" wrappable>
481
- <span class="toolbar-text">${i18nString(UIStrings.totalCalls, {PH1: stats.total})}</span>
569
+ <span class="toolbar-text">${i18nString(UIStrings.totalCalls, {PH1: input.toolCalls.length})}</span>
482
570
  <div class="toolbar-divider"></div>
483
- <span class="toolbar-text status-error-text">${i18nString(UIStrings.failed, {PH1: stats.failed})}</span>
571
+ <span class="toolbar-text status-error-text">${
572
+ i18nString(UIStrings.failed,
573
+ {PH1: toolStats.totals.get(Protocol.WebMCP.InvocationStatus.Error) ?? 0})}</span>
484
574
  <div class="toolbar-divider"></div>
485
575
  <span class="toolbar-text status-cancelled-text">${
486
- i18nString(UIStrings.canceledCount, {PH1: stats.canceled})}</span>
576
+ i18nString(UIStrings.canceledCount,
577
+ {PH1: toolStats.totals.get(Protocol.WebMCP.InvocationStatus.Canceled) ?? 0})}</span>
487
578
  <div class="toolbar-divider"></div>
488
- <span class="toolbar-text">${i18nString(UIStrings.inProgressCount, {PH1: stats.inProgress})}</span>
579
+ <span class="toolbar-text">${i18nString(UIStrings.inProgressCount,
580
+ {PH1: toolStats.totals.get(undefined) ?? 0})}</span>
489
581
  </devtools-toolbar>
490
582
  </div>
491
583
  ` : html`
@@ -504,23 +596,26 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
504
596
  ${UI.Widget.widget(UI.EmptyWidget.EmptyWidget, {header: i18nString(UIStrings.noToolsPlaceholderTitle),
505
597
  text: i18nString(UIStrings.noToolsPlaceholder)})}
506
598
  ` : html`
507
- <devtools-list>
508
- ${tools.map(tool => {
509
- const toolStats = calculateToolStats(input.toolCalls.filter(c => c.tool === tool));
510
- const groups = getIconGroupsFromStats(toolStats);
511
- return html`
512
- <div class=${Directives.classMap({'tool-item': true, selected: tool === input.selectedTool})}
513
- @click=${() => input.onToolSelect(tool)}
514
- @contextmenu=${(e: Event) => onToolContextMenu(e, tool)}>
515
- <div class="tool-name-container">
516
- <div class="tool-name source-code">${tool.name}</div>
517
- ${groups.length > 0 ? html`<icon-button .data=${
518
- {groups, compact: false} as IconButton.IconButton.IconButtonData}></icon-button>` : ''}
599
+ <devtools-list class="square-corners">
600
+ ${tools.map(tool => html`
601
+ <div class=${Directives.classMap({'tool-item': true, selected: tool === input.selectedTool?.tool})}
602
+ @click=${() => input.onToolSelect(tool)}
603
+ @contextmenu=${(e: Event) => onToolContextMenu(e, tool)}>
604
+ <div class="tool-name-container">
605
+ <div class="tool-name source-code">${tool.name}</div>
606
+ <div class="tool-icons">
607
+ ${getIconGroupsFromStats(toolStats.stats.get(tool)).map(group => html`
608
+ <icon-button
609
+ .data=${{
610
+ groups: [group],
611
+ compact: false,
612
+ clickHandler: () => onIconClick(tool.name, group.status),
613
+ } as IconButton.IconButton.IconButtonData}
614
+ @click=${(e: Event) => e.stopPropagation()}></icon-button>`)}
519
615
  </div>
520
- <div class="tool-description">${tool.description}</div>
521
616
  </div>
522
- `;
523
- })}
617
+ <div class="tool-description">${tool.description}</div>
618
+ </div>`)}
524
619
  </devtools-list>
525
620
  `}
526
621
  </div>
@@ -535,7 +630,53 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
535
630
  ></devtools-button>
536
631
  <span>${i18nString(UIStrings.toolDetails)}</span>
537
632
  </div>
538
- ${widget(ToolDetailsWidget, {tool: input.selectedTool})}
633
+ ${input.selectedTool ? html`
634
+ <div class="sidebar-tool-details">
635
+ ${widget(ToolDetailsWidget, {tool: input.selectedTool.tool})}
636
+ </div>
637
+ <div class="section-title">
638
+ <span>${i18nString(UIStrings.runTool)}</span>
639
+ <div style="flex: auto;"></div>
640
+ <devtools-button
641
+ .iconName=${'import'}
642
+ .size=${Buttons.Button.Size.SMALL}
643
+ .variant=${Buttons.Button.Variant.TEXT}
644
+ title=${i18nString(UIStrings.paste)}
645
+ @click=${input.onPaste}
646
+ >${i18nString(UIStrings.paste)}</devtools-button>
647
+ </div>
648
+ <devtools-widget
649
+ class="json-editor-widget"
650
+ ${widget(ProtocolMonitor.JSONEditor.JSONEditor, {
651
+ displayTargetSelector: false,
652
+ displayCommandInput: false,
653
+ displayToolbar: false,
654
+ ...getJSONEditorParameters(input.selectedTool.tool),
655
+ commandToDisplay: {
656
+ command: input.selectedTool.tool.name,
657
+ parameters: input.selectedTool.parameters || {}
658
+ },
659
+ })}
660
+ ${UI.Widget.widgetRef(ProtocolMonitor.JSONEditor.JSONEditor, e => { editorWidget = e; })}
661
+ @submiteditor=${(e: CustomEvent<ProtocolMonitor.JSONEditor.Command>) => input.onRunTool({data: e.detail})}
662
+ ></devtools-widget>
663
+ <devtools-button
664
+ class="webmcp-run-tool-button"
665
+ .variant=${Buttons.Button.Variant.OUTLINED}
666
+ .size=${Buttons.Button.Size.SMALL}
667
+ jslogContext="webmcp.run-tool"
668
+ @click=${() => {
669
+ if (editorWidget && input.selectedTool) {
670
+ const params = editorWidget.getParameters();
671
+ input.onRunTool({
672
+ data: {
673
+ command: input.selectedTool.tool.name,
674
+ parameters: params,
675
+ } as ProtocolMonitor.JSONEditor.Command
676
+ });
677
+ }
678
+ }}>Run tool</devtools-button>
679
+ ` : nothing}
539
680
  </div>
540
681
  </devtools-split-view>
541
682
  </devtools-split-view>
@@ -545,7 +686,7 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
545
686
 
546
687
  export class WebMCPView extends UI.Widget.VBox {
547
688
  readonly #view: View;
548
- #selectedTool: WebMCP.WebMCPModel.Tool|null = null;
689
+ #selectedTool: SelectedTool|null = null;
549
690
  #selectedCall: WebMCP.WebMCPModel.Call|null = null;
550
691
 
551
692
  #filterState: FilterState = {
@@ -623,11 +764,11 @@ export class WebMCPView extends UI.Widget.VBox {
623
764
  }
624
765
 
625
766
  #showStatusTypesContextMenu(contextMenu: UI.ContextMenu.ContextMenu): void {
626
- const toggle = (key: 'completed'|'error'|'pending'): void => {
767
+ const toggle = (key: 'completed'|'error'|'pending'|'canceled'): void => {
627
768
  const current = this.#filterState.statusTypes ?? {};
628
769
  const next = {...current, [key]: !current[key]};
629
770
  let statusTypesToPass: FilterState['statusTypes'] = next;
630
- if (!next.completed && !next.error && !next.pending) {
771
+ if (!next.completed && !next.error && !next.pending && !next.canceled) {
631
772
  statusTypesToPass = undefined;
632
773
  }
633
774
  this.#handleFilterChange({...this.#filterState, statusTypes: statusTypesToPass});
@@ -639,24 +780,34 @@ export class WebMCPView extends UI.Widget.VBox {
639
780
  contextMenu.defaultSection().appendCheckboxItem(
640
781
  i18nString(UIStrings.error), () => toggle('error'),
641
782
  {checked: this.#filterState.statusTypes?.['error'] ?? false, jslogContext: 'webmcp.error'});
783
+ contextMenu.defaultSection().appendCheckboxItem(
784
+ i18nString(UIStrings.canceled), () => toggle('canceled'),
785
+ {checked: this.#filterState.statusTypes?.['canceled'] ?? false, jslogContext: 'webmcp.canceled'});
642
786
  contextMenu.defaultSection().appendCheckboxItem(
643
787
  i18nString(UIStrings.pending), () => toggle('pending'),
644
788
  {checked: this.#filterState.statusTypes?.['pending'] ?? false, jslogContext: 'webmcp.pending'});
645
789
  }
646
790
  #webMCPModelAdded(model: WebMCP.WebMCPModel.WebMCPModel): void {
647
791
  model.addEventListener(WebMCP.WebMCPModel.Events.TOOLS_ADDED, this.requestUpdate, this);
648
- model.addEventListener(WebMCP.WebMCPModel.Events.TOOLS_REMOVED, this.requestUpdate, this);
792
+ model.addEventListener(WebMCP.WebMCPModel.Events.TOOLS_REMOVED, this.#toolsRemoved, this);
649
793
  model.addEventListener(WebMCP.WebMCPModel.Events.TOOL_INVOKED, this.requestUpdate, this);
650
794
  model.addEventListener(WebMCP.WebMCPModel.Events.TOOL_RESPONDED, this.requestUpdate, this);
651
795
  }
652
796
 
653
797
  #webMCPModelRemoved(model: WebMCP.WebMCPModel.WebMCPModel): void {
654
798
  model.removeEventListener(WebMCP.WebMCPModel.Events.TOOLS_ADDED, this.requestUpdate, this);
655
- model.removeEventListener(WebMCP.WebMCPModel.Events.TOOLS_REMOVED, this.requestUpdate, this);
799
+ model.removeEventListener(WebMCP.WebMCPModel.Events.TOOLS_REMOVED, this.#toolsRemoved, this);
656
800
  model.removeEventListener(WebMCP.WebMCPModel.Events.TOOL_INVOKED, this.requestUpdate, this);
657
801
  model.removeEventListener(WebMCP.WebMCPModel.Events.TOOL_RESPONDED, this.requestUpdate, this);
658
802
  }
659
803
 
804
+ #toolsRemoved(event: Common.EventTarget.EventTargetEvent<readonly WebMCP.WebMCPModel.Tool[]>): void {
805
+ if (this.#selectedTool && event.data.includes(this.#selectedTool.tool)) {
806
+ this.#selectedTool = null;
807
+ }
808
+ this.requestUpdate();
809
+ }
810
+
660
811
  #handleClearLogClick = (): void => {
661
812
  const models = SDK.TargetManager.TargetManager.instance().models(WebMCP.WebMCPModel.WebMCPModel);
662
813
  for (const model of models) {
@@ -688,11 +839,16 @@ export class WebMCPView extends UI.Widget.VBox {
688
839
  const models = SDK.TargetManager.TargetManager.instance().models(WebMCP.WebMCPModel.WebMCPModel);
689
840
  const toolCalls = models.flatMap(model => model.toolCalls);
690
841
  const filteredCalls = filterToolCalls(toolCalls, this.#filterState);
842
+ const tools = this.#getTools();
691
843
  const input: ViewInput = {
692
- tools: this.#getTools(),
844
+ tools,
693
845
  selectedTool: this.#selectedTool,
694
846
  onToolSelect: tool => {
695
- this.#selectedTool = tool;
847
+ this.#selectedTool = tool ? {tool} : null;
848
+ this.requestUpdate();
849
+ },
850
+ onRevealTool: (tool, parameters) => {
851
+ this.#selectedTool = {tool, parameters};
696
852
  this.requestUpdate();
697
853
  },
698
854
  selectedCall: this.#selectedCall,
@@ -705,6 +861,25 @@ export class WebMCPView extends UI.Widget.VBox {
705
861
  filterButtons: this.#filterButtons,
706
862
  onClearLogClick: this.#handleClearLogClick,
707
863
  onFilterChange: this.#handleFilterChange,
864
+ onRunTool: event => {
865
+ if (this.#selectedTool) {
866
+ void this.#selectedTool.tool.invoke(event.data.parameters || {});
867
+ }
868
+ },
869
+ onPaste: async () => {
870
+ try {
871
+ const text = await navigator.clipboard.readText();
872
+ const json = JSON.parse(text);
873
+ if (typeof json !== 'object' || json === null || Array.isArray(json)) {
874
+ throw new Error('Pasted JSON must be an object');
875
+ }
876
+ if (this.#selectedTool) {
877
+ this.#selectedTool.parameters = json as Record<string, unknown>;
878
+ this.requestUpdate();
879
+ }
880
+ } catch {
881
+ }
882
+ },
708
883
  };
709
884
  this.#view(input, {}, this.contentElement);
710
885
  }
@@ -888,6 +1063,7 @@ export class PayloadWidget extends UI.Widget.Widget {
888
1063
 
889
1064
  export interface ToolDetailsViewInput {
890
1065
  tool: WebMCP.WebMCPModel.Tool|null|undefined;
1066
+ isUnregistered?: boolean;
891
1067
  origin: SDK.DOMModel.DOMNode|StackTrace.StackTrace.StackTrace|undefined;
892
1068
  highlightNode: (node: SDK.DOMModel.DOMNode) => void;
893
1069
  clearHighlight: () => void;
@@ -944,6 +1120,16 @@ const TOOL_DETAILS_VIEW = (input: ToolDetailsViewInput, output: undefined, targe
944
1120
  {stackTrace: origin, options: { expandable: true}})}
945
1121
  </div>` : nothing}
946
1122
  </div>
1123
+ ${input.isUnregistered ? html`
1124
+ <div class="call-to-action">
1125
+ <div class="call-to-action-body">
1126
+ <div class="explanation">
1127
+ <devtools-icon class="inline-icon medium" name="warning-filled"></devtools-icon>
1128
+ ${i18nString(UIStrings.toolUnregisteredNotice)}
1129
+ </div>
1130
+ </div>
1131
+ </div>
1132
+ ` : nothing}
947
1133
  `, target);
948
1134
  };
949
1135
  // clang-format on
@@ -951,6 +1137,7 @@ const TOOL_DETAILS_VIEW = (input: ToolDetailsViewInput, output: undefined, targe
951
1137
  export class ToolDetailsWidget extends UI.Widget.Widget {
952
1138
  #tool: WebMCP.WebMCPModel.Tool|null|undefined = null;
953
1139
  #origin: SDK.DOMModel.DOMNode|StackTrace.StackTrace.StackTrace|undefined;
1140
+ #isUnregistered = false;
954
1141
 
955
1142
  #view: typeof TOOL_DETAILS_VIEW;
956
1143
 
@@ -959,6 +1146,17 @@ export class ToolDetailsWidget extends UI.Widget.Widget {
959
1146
  this.#view = view;
960
1147
  }
961
1148
 
1149
+ set isUnregistered(isUnregistered: boolean) {
1150
+ if (this.#isUnregistered === isUnregistered) {
1151
+ return;
1152
+ }
1153
+ this.#isUnregistered = isUnregistered;
1154
+ this.requestUpdate();
1155
+ }
1156
+
1157
+ get isUnregistered(): boolean {
1158
+ return this.#isUnregistered;
1159
+ }
962
1160
  set tool(tool: WebMCP.WebMCPModel.Tool|null|undefined) {
963
1161
  if (this.#tool === tool) {
964
1162
  return;
@@ -1000,6 +1198,7 @@ export class ToolDetailsWidget extends UI.Widget.Widget {
1000
1198
  override performUpdate(): void {
1001
1199
  const viewInput = {
1002
1200
  tool: this.#tool,
1201
+ isUnregistered: this.#isUnregistered,
1003
1202
  origin: this.#origin,
1004
1203
  highlightNode: this.#highlightNode,
1005
1204
  clearHighlight: this.#clearHighlight,
@@ -167,7 +167,7 @@ const renderMainFrameInformation = (input: ViewInput): Lit.LitTemplate => {
167
167
  // clang-format on
168
168
  };
169
169
 
170
- export const DEFAULT_VIEW = (input: ViewInput, _output: undefined, target: HTMLElement): void => {
170
+ export const DEFAULT_VIEW = (input: ViewInput, _output: undefined, target: HTMLElement|DocumentFragment): void => {
171
171
  // clang-format off
172
172
  Lit.render(html`
173
173
  <style>${bounceTrackingMitigationsViewStyles}</style>
@@ -176,20 +176,20 @@ export const DEFAULT_VIEW = (input: ViewInput, _output: undefined, target: HTMLE
176
176
  jslog=${VisualLogging.pane('bounce-tracking-mitigations')}>
177
177
  ${renderMainFrameInformation(input)}
178
178
  </devtools-report>
179
- `, target);
179
+ `, target, {container: {classes: ['overflow-auto']}});
180
180
  // clang-format on
181
181
  };
182
182
 
183
183
  type ViewFunction = typeof DEFAULT_VIEW;
184
184
 
185
- export class BounceTrackingMitigationsView extends UI.Widget.Widget {
185
+ export class BounceTrackingMitigationsView extends UI.Widget.Widget<ShadowRoot> {
186
186
  #trackingSites: string[] = [];
187
187
  #screenStatus = ScreenStatusType.INITIALIZING;
188
188
  #seenButtonClick = false;
189
189
  #view: ViewFunction;
190
190
 
191
191
  constructor(element?: HTMLElement, view: ViewFunction = DEFAULT_VIEW) {
192
- super(element, {useShadowDom: true, classes: ['overflow-auto']});
192
+ super(element, {useShadowDom: 'pure'});
193
193
 
194
194
  this.#view = view;
195
195