chrome-devtools-frontend 1.0.1596260 → 1.0.1597448

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 (114) hide show
  1. package/agents/prompts/ui-widgets.md +7 -8
  2. package/docs/ui_engineering.md +10 -11
  3. package/front_end/core/common/Console.ts +6 -6
  4. package/front_end/core/common/Settings.ts +12 -8
  5. package/front_end/core/host/InspectorFrontendHostAPI.ts +1 -0
  6. package/front_end/core/host/UserMetrics.ts +12 -0
  7. package/front_end/core/root/DevToolsContext.ts +13 -7
  8. package/front_end/core/root/Runtime.ts +5 -0
  9. package/front_end/core/sdk/FrameManager.ts +7 -8
  10. package/front_end/core/sdk/PageResourceLoader.ts +22 -1
  11. package/front_end/devtools_compatibility.js +2 -1
  12. package/front_end/entrypoints/greendev_floaty/FloatyEntrypoint.ts +1 -1
  13. package/front_end/entrypoints/main/MainImpl.ts +1 -2
  14. package/front_end/foundation/Universe.ts +22 -11
  15. package/front_end/generated/InspectorBackendCommands.ts +7 -0
  16. package/front_end/generated/protocol-mapping.d.ts +16 -0
  17. package/front_end/generated/protocol-proxy-api.d.ts +25 -0
  18. package/front_end/generated/protocol.ts +71 -0
  19. package/front_end/models/ai_assistance/AiConversation.ts +11 -95
  20. package/front_end/models/ai_assistance/agents/AiAgent.ts +15 -1
  21. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +14 -0
  22. package/front_end/models/ai_assistance/agents/StylingAgent.snapshot.txt +24 -0
  23. package/front_end/models/ai_assistance/agents/StylingAgent.ts +289 -12
  24. package/front_end/models/greendev/Prototypes.ts +7 -1
  25. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +36 -33
  26. package/front_end/panels/ai_assistance/PatchWidget.ts +6 -6
  27. package/front_end/panels/ai_assistance/components/ChatMessage.ts +28 -32
  28. package/front_end/panels/ai_assistance/components/ChatView.ts +6 -11
  29. package/front_end/panels/ai_assistance/components/StylingAgentMarkdownRenderer.ts +200 -0
  30. package/front_end/panels/ai_assistance/components/WalkthroughView.ts +2 -2
  31. package/front_end/panels/ai_assistance/components/chatMessage.css +0 -8
  32. package/front_end/panels/application/ServiceWorkerCacheViews.ts +1 -1
  33. package/front_end/panels/common/ExtensionServer.ts +15 -0
  34. package/front_end/panels/elements/ElementsTreeElement.ts +55 -47
  35. package/front_end/panels/elements/ElementsTreeOutline.ts +149 -28
  36. package/front_end/panels/elements/StandaloneStylesContainer.ts +48 -12
  37. package/front_end/panels/elements/StylePropertiesSection.ts +97 -1
  38. package/front_end/panels/elements/StylePropertyTreeElement.ts +16 -0
  39. package/front_end/panels/elements/StylesContainer.ts +1 -0
  40. package/front_end/panels/elements/StylesSidebarPane.ts +48 -32
  41. package/front_end/panels/elements/stylePropertiesTreeOutline.css +1 -1
  42. package/front_end/panels/lighthouse/LighthouseController.ts +13 -5
  43. package/front_end/panels/lighthouse/LighthousePanel.ts +30 -5
  44. package/front_end/panels/recorder/components/StepView.ts +0 -2
  45. package/front_end/panels/recorder/components/stepView.css +13 -13
  46. package/front_end/panels/recorder/components/timelineSection.css +6 -7
  47. package/front_end/panels/settings/SettingsScreen.ts +3 -2
  48. package/front_end/panels/timeline/TimelinePanel.ts +18 -0
  49. package/front_end/panels/timeline/components/CWVMetrics.ts +339 -0
  50. package/front_end/panels/timeline/components/Sidebar.ts +17 -0
  51. package/front_end/panels/timeline/components/SidebarInsightsTab.ts +10 -0
  52. package/front_end/panels/timeline/components/SidebarSingleInsightSet.ts +25 -267
  53. package/front_end/panels/timeline/components/components.ts +2 -0
  54. package/front_end/panels/timeline/components/cwvMetrics.css +107 -0
  55. package/front_end/panels/timeline/components/sidebarSingleInsightSet.css +0 -102
  56. package/front_end/panels/timeline/timeline-meta.ts +11 -0
  57. package/front_end/panels/timeline/utils/Helpers.ts +5 -1
  58. package/front_end/third_party/chromium/README.chromium +1 -1
  59. package/front_end/third_party/puppeteer/README.chromium +2 -2
  60. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.d.ts +7 -0
  61. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.d.ts.map +1 -1
  62. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.js.map +1 -1
  63. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.d.ts +1 -0
  64. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.d.ts.map +1 -1
  65. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.js +3 -0
  66. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.js.map +1 -1
  67. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.d.ts +1 -0
  68. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.d.ts.map +1 -1
  69. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.js +6 -0
  70. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.js.map +1 -1
  71. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.d.ts +1 -0
  72. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.d.ts.map +1 -1
  73. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.js +5 -0
  74. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.js.map +1 -1
  75. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
  76. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +2 -2
  77. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +2 -2
  78. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
  79. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.d.ts +1 -1
  80. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.js +1 -1
  81. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +7 -0
  82. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +14 -3
  83. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts +7 -0
  84. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts.map +1 -1
  85. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.js.map +1 -1
  86. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.d.ts +1 -0
  87. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.d.ts.map +1 -1
  88. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.js +3 -0
  89. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.js.map +1 -1
  90. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.d.ts +1 -0
  91. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.d.ts.map +1 -1
  92. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.js +6 -0
  93. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.js.map +1 -1
  94. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.d.ts +1 -0
  95. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.d.ts.map +1 -1
  96. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.js +5 -0
  97. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.js.map +1 -1
  98. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +2 -2
  99. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +2 -2
  100. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.d.ts +1 -1
  101. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.js +1 -1
  102. package/front_end/third_party/puppeteer/package/lib/types.d.ts +7 -0
  103. package/front_end/third_party/puppeteer/package/package.json +1 -1
  104. package/front_end/third_party/puppeteer/package/src/api/Page.ts +8 -0
  105. package/front_end/third_party/puppeteer/package/src/bidi/Page.ts +4 -0
  106. package/front_end/third_party/puppeteer/package/src/cdp/Browser.ts +7 -0
  107. package/front_end/third_party/puppeteer/package/src/cdp/Page.ts +6 -0
  108. package/front_end/third_party/puppeteer/package/src/revisions.ts +2 -2
  109. package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
  110. package/front_end/ui/components/text_editor/AutocompleteHistory.ts +89 -5
  111. package/front_end/ui/legacy/UIUtils.ts +5 -5
  112. package/front_end/ui/legacy/Widget.ts +33 -2
  113. package/front_end/ui/visual_logging/KnownContextValues.ts +2 -0
  114. package/package.json +1 -1
@@ -11,7 +11,7 @@ Adhere strictly to the Model-View-Presenter (MVP) architecture.
11
11
  ### Presenter (`Widget`) Rules
12
12
 
13
13
  * Location: Co-located in the same file as its View.
14
- * MUST extend a base `UI.Widget` class (e.g., `UI.Widget.Widget`). Note that `UI.Widget.Widget` is not an `HTMLElement` and must be appended via `.show()` or `<devtools-widget>`.
14
+ * MUST extend a base `UI.Widget` class (e.g., `UI.Widget.Widget`). Note that `UI.Widget.Widget` is not an `HTMLElement` and must be appended via `.show()` or `UI.Widget.widget`
15
15
  * Constructor MUST assign the injected view function to a private `#view` field.
16
16
  * Constructor MUST call `super()`. If taking `element?: HTMLElement`, pass it to `super(element)`. `super(true)` is forbidden.
17
17
  * Styling MUST be handled within the View. `this.registerCSSFiles()` is forbidden.
@@ -50,10 +50,10 @@ const DEFAULT_VIEW = (input: ViewInput, output: ViewOutput, target: HTMLElement)
50
50
  // clang-format on
51
51
  ```
52
52
 
53
- ### Composition (`<devtools-widget>`)
53
+ ### Composition
54
54
 
55
- * To render a child widget, the parent's View MUST use `<devtools-widget>`.
56
- * Configuration is passed via the `.widgetConfig` property using `UI.Widget.widgetConfig()`.
55
+ * To render a child widget, the parent's View MUST use lit-html directive `UI.Widget.wiget`
56
+ * Configuration is passed via the parameters.
57
57
  * Properties passed from a parent MUST be declared as public fields on the child presenter class.
58
58
  * The framework automatically updates these properties and calls `requestUpdate()` on the child when the parent re-renders.
59
59
 
@@ -66,7 +66,7 @@ When migrating imperative components (extending `UI.VBox`, `UI.Panel`, or `HTMLE
66
66
  * Prefer extending `UI.Widget.Widget`.
67
67
  * **Special Case:** If the component *must* extend `UI.Panel.Panel` or `UI.Dialog.Dialog` (to retain specific functionality), you cannot use `requestUpdate()`. Instead, call `this.performUpdate()` directly on state changes.
68
68
  3. **State Migration:** Move DOM-stored state to private class fields.
69
- 4. **Update Usage:** Replace `new MyComponent()` instantiations with declarative `<devtools-widget .widgetConfig=...>` in parent templates.
69
+ 4. **Update Usage:** Replace `new MyComponent()` instantiations with declarative `widget(MyComponent, {params})` in parent templates.
70
70
  5. **Scoping Styles:** Ensure your CSS file uses the `@scope` block to prevent style leaks:
71
71
  ```css
72
72
  @scope to (devtools-widget > *) {
@@ -101,7 +101,7 @@ render(html`
101
101
 
102
102
  ### Legacy Interop & Refs
103
103
  * **Raw Elements:** Use `Lit.Directives.ref` to obtain a reference to a raw `HTMLElement` if needed for imperative APIs (e.g., `splitWidget.installResizer(element)`).
104
- * **Child Widgets:** Use `UI.Widget.widgetRef` to obtain the class instance of a child `<devtools-widget>` if you need to call methods on it directly (though declarative data flow is preferred).
104
+ * **Child Widgets:** Use `UI.Widget.widgetRef` to obtain the class instance of a child widget if you need to call methods on it directly (though declarative data flow is preferred).
105
105
 
106
106
  ### Dependencies
107
107
  The `DEFAULT_VIEW` is typically a module-level function. Ensure all dependencies (enums, constants, other components) are imported at the top of the file so they are available in the function scope.
@@ -236,8 +236,7 @@ const DEFAULT_VIEW = (input: ViewInput, output: undefined, target: HTMLElement):
236
236
  <button @click=${input.onTitleChange}>Change Child Title</button>
237
237
 
238
238
  <!-- Pass properties to the child widget. -->
239
- <devtools-widget .widgetConfig=${widgetConfig(MyExampleWidget, {title: input.title})}>
240
- </devtools-widget>
239
+ ${widget(MyExampleWidget, {title: input.title})}
241
240
  </div>
242
241
  `, target);
243
242
  };
@@ -40,11 +40,11 @@ To test the `DEFAULT_VIEW` function itself, we should use screenshot and e2e tes
40
40
 
41
41
  We should no longer use imperative API to update DOM. Instead we rely on orchestrated rendering of lit-html templates. The view function described above should be a call to lit-html `render`. The view function should be called from `UI.Widget`’s `performUpdate` method, which by default is scheduled using `requestAnimationFrame`.
42
42
 
43
- To embed another presenter (`UI.Widget`) in the lit-html template, use `<devtools-widget .widgetConfig=${widgetConfig(<class>, {foo: 1, bar: 2})}`
43
+ To embed another presenter (`UI.Widget`) in the lit-html template, use `widget(<class>, {foo: 1, bar: 2})`
44
44
 
45
45
  This will instantiate a `Widget` class with the web component as its `element` and, optionally, will set the properties provided in the second parameter. The widget won’t be re-instantiated on the subsequent template renders, but the properties would be updated. For this to work, the widget needs to accept `HTMLElement` as a sole constructor parameter and properties need to be public members or setters.
46
46
 
47
- For backwards compatibility, the first argument to `widgetConfig` can also be a factory function: `<devtools-widget .widgetConfig=${widgetConfig(element => new MyWidget(foo, bar, element))}>`. Similar to the class constructor version, `element` is the actual `<devtools-widget>` so the following two invocations of `widgetConfig` are equivalent: `widgetConfig(MyWidget)` and `widgetConfig(element => new MyWidget(element))`.
47
+ For backwards compatibility, the first argument to `widgetConfig` can also be a factory function: `widget(element => new MyWidget(foo, bar, element))`. Similar to the class constructor version, `element` is the actual `<devtools-widget>` so the following two invocations of `widgetConfig` are equivalent: `widget(MyWidget)` and `widget(element => new MyWidget(element))`.
48
48
 
49
49
  ## Styling
50
50
  To prevent style conflicts in widgets without relying on shadow DOM, we use the CSS [`@scope`](https://developer.mozilla.org/en-US/docs/Web/CSS/@scope) at-rule for style encapsulation. This ensures that styles defined for a widget do not leak out and affect other components.
@@ -83,12 +83,12 @@ render(html`
83
83
  <div class="container">
84
84
  <h3 class="title">My Widget</h3>
85
85
  ...
86
- <devtools-widget .widgetConfig=${widgetConfig(NestedWidget)}></devtools-widget>
86
+ ${widget(NestedWidget)}
87
87
  </div>
88
88
  `, this.element);
89
89
  ```
90
90
 
91
- In this example, the `.title` style will apply within the parent widget but will not leak into the nested `<devtools-widget>`. Because this convention relies on developer discipline, it is important to verify its correct application during code reviews.
91
+ In this example, the `.title` style will apply within the parent widget but will not leak into the nested widget. Because this convention relies on developer discipline, it is important to verify its correct application during code reviews.
92
92
 
93
93
  ## Examples
94
94
 
@@ -97,8 +97,8 @@ In this example, the `.title` style will apply within the parent widget but will
97
97
  <devtools-split-view>
98
98
  <devtools-widget slot="main" .widgetConfig=${widgetConfig(ElementsTree)}></devtools-widget>
99
99
  <devtools-tab-pane slot="sidebar">
100
- <devtools-widget .widgetConfig=${widgetConfig(StylesPane, {element: input.element})}></devtools-widget>
101
- <devtools-widget .widgetConfig=${widgetConfig(ComputedPane, {element: input.element})}></devtools-widget>
100
+ ${widget(StylesPane, {element: input.element})}
101
+ ${widget(ComputedPane, {element: input.element})}
102
102
  ...
103
103
  </devtools-tab-pane>
104
104
  </devtools-split-view>
@@ -109,8 +109,7 @@ In this example, the `.title` style will apply within the parent widget but will
109
109
  type View = (input: ViewInput, output: ViewOutput, target: HTMLElement) => void;
110
110
  const DEFAULT_VIEW = (input, output, target) => {
111
111
  render(html`
112
- <devtools-widget .widgetConfig=${widgetConfig(MetricsPane, {element: input.element})}>
113
- </devtools-widget>
112
+ ${widget(MetricsPane, {element: input.element})}
114
113
  <devtools-toolbar>
115
114
  <devtools-filter-input @change=${input.onFilter}></devtools-filter-input>
116
115
  <devtools-checkbox @change=${input.onShowAll}>Show All</devtools-checkbox>
@@ -1236,7 +1235,7 @@ export const DEFAULT_VIEW = (input, _output, target) => {
1236
1235
 
1237
1236
  ## Migrating `EmptyWidget`
1238
1237
 
1239
- Replace the imperative `EmptyWidget` with a declarative `<devtools-widget>` and configure it with `widgetConfig` to render an `EmptyWidget`.
1238
+ Replace the imperative `EmptyWidget` with a declarative `widget` and configure it to render an `EmptyWidget`.
1240
1239
 
1241
1240
  **Before:**
1242
1241
  ```typescript
@@ -1258,9 +1257,9 @@ class SomeWidget extends UI.Widget.Widget {
1258
1257
  export const DEFAULT_VIEW = (input, _output, target) => {
1259
1258
  render(html`
1260
1259
  <div>
1261
- <devtools-widget .widgetConfig=${widgetConfig(UI.EmptyWidget.EmptyWidget,{
1260
+ ${widget(UI.EmptyWidget.EmptyWidget,{
1262
1261
  header: i18nString(UIStrings.nothingToSeeHere), text: this.explanation,
1263
- link: 'http://www.google.com',})}></devtools-widget>
1262
+ link: 'http://www.google.com',})}
1264
1263
  </div>`,
1265
1264
  target, {host: input});
1266
1265
  };
@@ -2,24 +2,24 @@
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
4
 
5
+ import * as Root from '../root/root.js';
6
+
5
7
  import {ObjectWrapper} from './Object.js';
6
8
  import {reveal} from './Revealer.js';
7
9
 
8
- let consoleInstance: Console|undefined;
9
-
10
10
  export class Console extends ObjectWrapper<EventTypes> {
11
11
  readonly #messages: Message[] = [];
12
12
 
13
13
  static instance(opts?: {forceNew: boolean}): Console {
14
- if (!consoleInstance || opts?.forceNew) {
15
- consoleInstance = new Console();
14
+ if (!Root.DevToolsContext.globalInstance().has(Console) || opts?.forceNew) {
15
+ Root.DevToolsContext.globalInstance().set(Console, new Console());
16
16
  }
17
17
 
18
- return consoleInstance;
18
+ return Root.DevToolsContext.globalInstance().get(Console);
19
19
  }
20
20
 
21
21
  static removeInstance(): void {
22
- consoleInstance = undefined;
22
+ Root.DevToolsContext.globalInstance().delete(Console);
23
23
  }
24
24
 
25
25
  /**
@@ -22,8 +22,6 @@ import {
22
22
  SettingType,
23
23
  } from './SettingRegistration.js';
24
24
 
25
- let settingsInstance: Settings|undefined;
26
-
27
25
  export interface SettingsCreationOptions {
28
26
  syncedStorage: SettingsStorage;
29
27
  globalStorage: SettingsStorage;
@@ -85,7 +83,7 @@ export class Settings {
85
83
  }
86
84
 
87
85
  static hasInstance(): boolean {
88
- return typeof settingsInstance !== 'undefined';
86
+ return Root.DevToolsContext.globalInstance().has(Settings);
89
87
  }
90
88
 
91
89
  static instance(opts: {
@@ -107,20 +105,26 @@ export class Settings {
107
105
  logSettingAccess,
108
106
  runSettingsMigration
109
107
  } = opts;
110
- if (!settingsInstance || forceNew) {
108
+ if (!Root.DevToolsContext.globalInstance().has(Settings) || forceNew) {
111
109
  if (!syncedStorage || !globalStorage || !localStorage || !settingRegistrations) {
112
110
  throw new Error(`Unable to create settings: global and local storage must be provided: ${new Error().stack}`);
113
111
  }
114
112
 
115
- settingsInstance = new Settings(
116
- {syncedStorage, globalStorage, localStorage, settingRegistrations, logSettingAccess, runSettingsMigration});
113
+ Root.DevToolsContext.globalInstance().set(Settings, new Settings({
114
+ syncedStorage,
115
+ globalStorage,
116
+ localStorage,
117
+ settingRegistrations,
118
+ logSettingAccess,
119
+ runSettingsMigration
120
+ }));
117
121
  }
118
122
 
119
- return settingsInstance;
123
+ return Root.DevToolsContext.globalInstance().get(Settings);
120
124
  }
121
125
 
122
126
  static removeInstance(): void {
123
- settingsInstance = undefined;
127
+ Root.DevToolsContext.globalInstance().delete(Settings);
124
128
  }
125
129
 
126
130
  private registerModuleSetting(setting: Setting<unknown>): void {
@@ -556,5 +556,6 @@ export const enum EnumeratedHistogram {
556
556
  LighthouseCategoryUsed = 'DevTools.LighthouseCategoryUsed',
557
557
  SwatchActivated = 'DevTools.SwatchActivated',
558
558
  BuiltInAiAvailability = 'DevTools.BuiltInAiAvailability',
559
+ ExtensionEvalTarget = 'DevTools.ExtensionEvalTarget',
559
560
  // LINT.ThenChange(/front_end/devtools_compatibility.js:EnumeratedHistogram)
560
561
  }
@@ -322,6 +322,11 @@ export class UserMetrics {
322
322
  InspectorFrontendHostInstance.recordPerformanceHistogram(
323
323
  'DevTools.Insights.ShortTeaserGenerationTime', timeInMilliseconds);
324
324
  }
325
+
326
+ extensionEvalTarget(target: ExtensionEvalTarget): void {
327
+ InspectorFrontendHostInstance.recordEnumeratedHistogram(
328
+ EnumeratedHistogram.ExtensionEvalTarget, target, ExtensionEvalTarget.MAX_VALUE);
329
+ }
325
330
  }
326
331
 
327
332
  /**
@@ -1264,3 +1269,10 @@ export const enum BuiltInAiAvailability {
1264
1269
  DISABLED_NO_GPU = 9,
1265
1270
  MAX_VALUE = 10,
1266
1271
  }
1272
+
1273
+ export const enum ExtensionEvalTarget {
1274
+ WEB_PAGE = 0,
1275
+ SAME_EXTENSION = 1,
1276
+ OTHER_EXTENSION = 2,
1277
+ MAX_VALUE = 3,
1278
+ }
@@ -11,7 +11,14 @@ export type ConstructorT<T> = new (...args: any[]) => T;
11
11
  * via constructor, and not just pass a {@link DevToolsContext} around. That would hide
12
12
  * dependencies and we want to be explicit.
13
13
  */
14
- export class DevToolsContext {
14
+ export interface DevToolsContext {
15
+ get<T>(ctor: ConstructorT<T>): T;
16
+ }
17
+
18
+ /**
19
+ * The actual implementation. Should only be accessed by test-setup code or the bootstrapper.
20
+ */
21
+ export class WritableDevToolsContext implements DevToolsContext {
15
22
  readonly #instances = new Map<ConstructorT<unknown>, unknown>();
16
23
 
17
24
  get<T>(ctor: ConstructorT<T>): T {
@@ -28,8 +35,7 @@ export class DevToolsContext {
28
35
  }
29
36
 
30
37
  /**
31
- * @deprecated Should only be used by existing `instance` accessors and the bootstrapper.
32
- * Exists on the public interface only for migration purposes for now.
38
+ * Should only be used by existing `instance` accessors and the bootstrapper.
33
39
  */
34
40
  set<T>(ctor: ConstructorT<T>, instance: T): void {
35
41
  // TODO(crbug.com/458180550): We need to throw here if an instance was already set!
@@ -42,16 +48,16 @@ export class DevToolsContext {
42
48
  }
43
49
  }
44
50
 
45
- let gInstance: DevToolsContext|null = null;
51
+ let gInstance: WritableDevToolsContext|null = null;
46
52
 
47
53
  /**
48
54
  * @deprecated Exists to migrate instance() methods.
49
55
  */
50
- export function globalInstance(): DevToolsContext {
56
+ export function globalInstance(): WritableDevToolsContext {
51
57
  if (!gInstance) {
52
58
  // TODO(crbug.com/458180550): This should really throw to prevent side-effects and globals
53
59
  // from leaking all over the place.
54
- gInstance = new DevToolsContext();
60
+ gInstance = new WritableDevToolsContext();
55
61
  }
56
62
  return gInstance;
57
63
  }
@@ -59,6 +65,6 @@ export function globalInstance(): DevToolsContext {
59
65
  /**
60
66
  * @deprecated Should only be called by test setup and MainImpl
61
67
  */
62
- export function setGlobalInstance(context: DevToolsContext|null): void {
68
+ export function setGlobalInstance(context: WritableDevToolsContext|null): void {
63
69
  gInstance = context;
64
70
  }
@@ -476,6 +476,10 @@ export interface HostConfigAiAssistanceFileAgent {
476
476
  userTier: string;
477
477
  }
478
478
 
479
+ export interface HostConfigAiAssistanceAccessibilityAgent {
480
+ enabled: boolean;
481
+ }
482
+
479
483
  export interface HostConfigAiCodeCompletion {
480
484
  modelId: string;
481
485
  temperature: number;
@@ -632,6 +636,7 @@ export type HostConfig = Platform.TypeScriptUtilities.RecursivePartial<{
632
636
  devToolsAiAssistanceNetworkAgent: HostConfigAiAssistanceNetworkAgent,
633
637
  devToolsAiAssistanceFileAgent: HostConfigAiAssistanceFileAgent,
634
638
  devToolsAiAssistancePerformanceAgent: HostConfigAiAssistancePerformanceAgent,
639
+ devToolsAiAssistanceAccessibilityAgent: HostConfigAiAssistanceAccessibilityAgent,
635
640
  devToolsAiAssistanceV2: HostConfigAiAssistanceV2,
636
641
  devToolsAiCodeCompletion: HostConfigAiCodeCompletion,
637
642
  devToolsAiCodeGeneration: HostConfigAiCodeGeneration,
@@ -4,14 +4,13 @@
4
4
 
5
5
  import type * as Protocol from '../../generated/protocol.js';
6
6
  import * as Common from '../common/common.js';
7
+ import * as Root from '../root/root.js';
7
8
 
8
9
  import type {Resource} from './Resource.js';
9
10
  import {Events as ResourceTreeModelEvents, type ResourceTreeFrame, ResourceTreeModel} from './ResourceTreeModel.js';
10
11
  import type {Target} from './Target.js';
11
12
  import {type SDKModelObserver, TargetManager} from './TargetManager.js';
12
13
 
13
- let frameManagerInstance: FrameManager|null = null;
14
-
15
14
  /**
16
15
  * The FrameManager is a central storage for all #frames. It collects #frames from all
17
16
  * ResourceTreeModel-instances (one per target), so that #frames can be found by id
@@ -37,22 +36,22 @@ export class FrameManager extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
37
36
  }>();
38
37
  #awaitedFrames = new Map<string, Array<{resolve: (frame: ResourceTreeFrame) => void, notInTarget?: Target}>>();
39
38
 
40
- constructor() {
39
+ constructor(targetManager: TargetManager) {
41
40
  super();
42
- TargetManager.instance().observeModels(ResourceTreeModel, this);
41
+ targetManager.observeModels(ResourceTreeModel, this);
43
42
  }
44
43
 
45
44
  static instance({forceNew}: {
46
45
  forceNew: boolean,
47
46
  } = {forceNew: false}): FrameManager {
48
- if (!frameManagerInstance || forceNew) {
49
- frameManagerInstance = new FrameManager();
47
+ if (!Root.DevToolsContext.globalInstance().has(FrameManager) || forceNew) {
48
+ Root.DevToolsContext.globalInstance().set(FrameManager, new FrameManager(TargetManager.instance()));
50
49
  }
51
- return frameManagerInstance;
50
+ return Root.DevToolsContext.globalInstance().get(FrameManager);
52
51
  }
53
52
 
54
53
  static removeInstance(): void {
55
- frameManagerInstance = null;
54
+ Root.DevToolsContext.globalInstance().delete(FrameManager);
56
55
  }
57
56
 
58
57
  modelAdded(resourceTreeModel: ResourceTreeModel): void {
@@ -334,6 +334,27 @@ export class PageResourceLoader extends Common.ObjectWrapper.ObjectWrapper<Event
334
334
  initiator.target;
335
335
  Host.userMetrics.developerResourceScheme(this.getDeveloperResourceScheme(parsedURL));
336
336
  if (eligibleForLoadFromTarget) {
337
+ let mustEnforceCSP = false;
338
+ const isHttp = parsedURL.scheme === 'http' || parsedURL.scheme === 'https';
339
+ if (isHttp && initiator.target) {
340
+ const networkManager = initiator.target.model(NetworkManager);
341
+ if (networkManager) {
342
+ let status = await networkManager.getSecurityIsolationStatus(initiator.frameId);
343
+ if (!status && initiator.frameId) {
344
+ status = await networkManager.getSecurityIsolationStatus(null);
345
+ }
346
+ if (status?.csp) {
347
+ for (const csp of status.csp) {
348
+ const directives = csp.effectiveDirectives;
349
+ if (directives.includes('connect-src') || directives.includes('default-src')) {
350
+ mustEnforceCSP = true;
351
+ break;
352
+ }
353
+ }
354
+ }
355
+ }
356
+ }
357
+
337
358
  try {
338
359
  Host.userMetrics.developerResourceLoaded(Host.UserMetrics.DeveloperResourceLoaded.LOAD_THROUGH_PAGE_VIA_TARGET);
339
360
  const result = await this.loadFromTarget(initiator.target, initiator.frameId, url, isBinary);
@@ -341,7 +362,7 @@ export class PageResourceLoader extends Common.ObjectWrapper.ObjectWrapper<Event
341
362
  } catch (e) {
342
363
  if (e instanceof Error) {
343
364
  Host.userMetrics.developerResourceLoaded(Host.UserMetrics.DeveloperResourceLoaded.LOAD_THROUGH_PAGE_FAILURE);
344
- if (e.message.includes('CSP violation')) {
365
+ if (mustEnforceCSP || e.message.includes('CSP violation')) {
345
366
  return {
346
367
  success: false,
347
368
  content: '',
@@ -444,7 +444,8 @@
444
444
  TimelineNavigationSettingState: 'DevTools.TimelineNavigationSettingState',
445
445
  SyncSetting: 'DevTools.SyncSetting',
446
446
  SwatchActivated: 'DevTools.SwatchActivated',
447
- BuiltInAiAvailability: 'DevTools.BuiltInAiAvailability'
447
+ BuiltInAiAvailability: 'DevTools.BuiltInAiAvailability',
448
+ ExtensionEvalTarget: 'DevTools.ExtensionEvalTarget'
448
449
  // LINT.ThenChange(/front_end/core/host/InspectorFrontendHostAPI.ts:EnumeratedHistogram)
449
450
  };
450
451
 
@@ -431,7 +431,7 @@ async function init(): Promise<void> {
431
431
  settingRegistrations: Common.SettingRegistration.getRegisteredSettings(),
432
432
  }
433
433
  });
434
- Root.DevToolsContext.setGlobalInstance(universe.context);
434
+ Root.DevToolsContext.setGlobalInstance(universe.context as Root.DevToolsContext.WritableDevToolsContext);
435
435
 
436
436
  await i18n.i18n.fetchAndRegisterLocaleData('en-US');
437
437
  Host.InspectorFrontendHost.InspectorFrontendHostInstance.connectionReady();
@@ -201,7 +201,7 @@ export class MainImpl {
201
201
  },
202
202
  };
203
203
  this.#universe = new Foundation.Universe.Universe(creationOptions);
204
- Root.DevToolsContext.setGlobalInstance(this.#universe.context);
204
+ Root.DevToolsContext.setGlobalInstance(this.#universe.context as Root.DevToolsContext.WritableDevToolsContext);
205
205
 
206
206
  await this.requestAndRegisterLocaleData();
207
207
 
@@ -488,7 +488,6 @@ export class MainImpl {
488
488
 
489
489
  // These instances need to be created early so they don't miss any events about requests/issues/etc.
490
490
  Logs.NetworkLog.NetworkLog.instance();
491
- SDK.FrameManager.FrameManager.instance();
492
491
  Logs.LogManager.LogManager.instance();
493
492
  IssuesManager.IssuesManager.IssuesManager.instance({
494
493
  forceNew: true,
@@ -14,38 +14,49 @@ export interface CreationOptions {
14
14
  }
15
15
 
16
16
  export class Universe {
17
- readonly context = new Root.DevToolsContext.DevToolsContext();
17
+ readonly context: Root.DevToolsContext.DevToolsContext;
18
18
 
19
19
  constructor(options: CreationOptions) {
20
- // TODO(crbug.com/458180550): Store instance on a "DevToolsContext" instead.
21
- // For now the global is fine as we don't anticipate the MCP server to change settings.
20
+ const context = new Root.DevToolsContext.WritableDevToolsContext();
21
+ this.context = context;
22
+
23
+ // TODO(crbug.com/458180550): Store instance only on this.context instead.
24
+ // For now the global is required as not everything in foundation cleanly
25
+ // reads from the scoped `Settings` instance.
22
26
  const settings = Common.Settings.Settings.instance({
23
27
  forceNew: true,
24
28
  ...options.settingsCreationOptions,
25
29
  });
30
+ context.set(Common.Settings.Settings, settings);
31
+
32
+ const console = new Common.Console.Console();
33
+ context.set(Common.Console.Console, console);
34
+
35
+ const targetManager = new SDK.TargetManager.TargetManager(context, options.overrideAutoStartModels);
36
+ context.set(SDK.TargetManager.TargetManager, targetManager);
26
37
 
27
- const targetManager = new SDK.TargetManager.TargetManager(this.context, options.overrideAutoStartModels);
28
- this.context.set(SDK.TargetManager.TargetManager, targetManager);
38
+ const frameManager = new SDK.FrameManager.FrameManager(targetManager);
39
+ context.set(SDK.FrameManager.FrameManager, frameManager);
29
40
 
30
41
  const multitargetNetworkManager = new SDK.NetworkManager.MultitargetNetworkManager(targetManager);
31
- this.context.set(SDK.NetworkManager.MultitargetNetworkManager, multitargetNetworkManager);
42
+ context.set(SDK.NetworkManager.MultitargetNetworkManager, multitargetNetworkManager);
32
43
 
33
44
  const pageResourceLoader =
34
45
  new SDK.PageResourceLoader.PageResourceLoader(targetManager, settings, multitargetNetworkManager, null);
35
- this.context.set(SDK.PageResourceLoader.PageResourceLoader, pageResourceLoader);
46
+ context.set(SDK.PageResourceLoader.PageResourceLoader, pageResourceLoader);
36
47
 
37
48
  const workspace = new Workspace.Workspace.WorkspaceImpl();
38
- this.context.set(Workspace.Workspace.WorkspaceImpl, workspace);
49
+ context.set(Workspace.Workspace.WorkspaceImpl, workspace);
39
50
 
40
51
  const ignoreListManager = new Workspace.IgnoreListManager.IgnoreListManager(settings, targetManager);
41
- this.context.set(Workspace.IgnoreListManager.IgnoreListManager, ignoreListManager);
52
+ context.set(Workspace.IgnoreListManager.IgnoreListManager, ignoreListManager);
42
53
 
43
54
  const resourceMapping = new Bindings.ResourceMapping.ResourceMapping(targetManager, workspace);
44
55
  const cssWorkspaceBinding = new Bindings.CSSWorkspaceBinding.CSSWorkspaceBinding(resourceMapping, targetManager);
45
- this.context.set(Bindings.CSSWorkspaceBinding.CSSWorkspaceBinding, cssWorkspaceBinding);
56
+ context.set(Bindings.CSSWorkspaceBinding.CSSWorkspaceBinding, cssWorkspaceBinding);
46
57
 
47
58
  const debuggerWorkspaceBinding = new Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding(
48
59
  resourceMapping, targetManager, ignoreListManager, workspace);
49
- this.context.set(Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding, debuggerWorkspaceBinding);
60
+ context.set(Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding, debuggerWorkspaceBinding);
50
61
  }
51
62
  }
@@ -1517,6 +1517,13 @@ inspectorBackend.registerCommand("WebAuthn.setCredentialProperties", [{"name": "
1517
1517
  inspectorBackend.registerType("WebAuthn.VirtualAuthenticatorOptions", [{"name": "protocol", "type": "string", "optional": false, "description": "", "typeRef": "WebAuthn.AuthenticatorProtocol"}, {"name": "ctap2Version", "type": "string", "optional": true, "description": "Defaults to ctap2_0. Ignored if |protocol| == u2f.", "typeRef": "WebAuthn.Ctap2Version"}, {"name": "transport", "type": "string", "optional": false, "description": "", "typeRef": "WebAuthn.AuthenticatorTransport"}, {"name": "hasResidentKey", "type": "boolean", "optional": true, "description": "Defaults to false.", "typeRef": null}, {"name": "hasUserVerification", "type": "boolean", "optional": true, "description": "Defaults to false.", "typeRef": null}, {"name": "hasLargeBlob", "type": "boolean", "optional": true, "description": "If set to true, the authenticator will support the largeBlob extension. https://w3c.github.io/webauthn#largeBlob Defaults to false.", "typeRef": null}, {"name": "hasCredBlob", "type": "boolean", "optional": true, "description": "If set to true, the authenticator will support the credBlob extension. https://fidoalliance.org/specs/fido-v2.1-rd-20201208/fido-client-to-authenticator-protocol-v2.1-rd-20201208.html#sctn-credBlob-extension Defaults to false.", "typeRef": null}, {"name": "hasMinPinLength", "type": "boolean", "optional": true, "description": "If set to true, the authenticator will support the minPinLength extension. https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html#sctn-minpinlength-extension Defaults to false.", "typeRef": null}, {"name": "hasPrf", "type": "boolean", "optional": true, "description": "If set to true, the authenticator will support the prf extension. https://w3c.github.io/webauthn/#prf-extension Defaults to false.", "typeRef": null}, {"name": "automaticPresenceSimulation", "type": "boolean", "optional": true, "description": "If set to true, tests of user presence will succeed immediately. Otherwise, they will not be resolved. Defaults to true.", "typeRef": null}, {"name": "isUserVerified", "type": "boolean", "optional": true, "description": "Sets whether User Verification succeeds or fails for an authenticator. Defaults to false.", "typeRef": null}, {"name": "defaultBackupEligibility", "type": "boolean", "optional": true, "description": "Credentials created by this authenticator will have the backup eligibility (BE) flag set to this value. Defaults to false. https://w3c.github.io/webauthn/#sctn-credential-backup", "typeRef": null}, {"name": "defaultBackupState", "type": "boolean", "optional": true, "description": "Credentials created by this authenticator will have the backup state (BS) flag set to this value. Defaults to false. https://w3c.github.io/webauthn/#sctn-credential-backup", "typeRef": null}]);
1518
1518
  inspectorBackend.registerType("WebAuthn.Credential", [{"name": "credentialId", "type": "string", "optional": false, "description": "", "typeRef": null}, {"name": "isResidentCredential", "type": "boolean", "optional": false, "description": "", "typeRef": null}, {"name": "rpId", "type": "string", "optional": true, "description": "Relying Party ID the credential is scoped to. Must be set when adding a credential.", "typeRef": null}, {"name": "privateKey", "type": "string", "optional": false, "description": "The ECDSA P-256 private key in PKCS#8 format.", "typeRef": null}, {"name": "userHandle", "type": "string", "optional": true, "description": "An opaque byte sequence with a maximum size of 64 bytes mapping the credential to a specific user.", "typeRef": null}, {"name": "signCount", "type": "number", "optional": false, "description": "Signature counter. This is incremented by one for each successful assertion. See https://w3c.github.io/webauthn/#signature-counter", "typeRef": null}, {"name": "largeBlob", "type": "string", "optional": true, "description": "The large blob associated with the credential. See https://w3c.github.io/webauthn/#sctn-large-blob-extension", "typeRef": null}, {"name": "backupEligibility", "type": "boolean", "optional": true, "description": "Assertions returned by this credential will have the backup eligibility (BE) flag set to this value. Defaults to the authenticator's defaultBackupEligibility value.", "typeRef": null}, {"name": "backupState", "type": "boolean", "optional": true, "description": "Assertions returned by this credential will have the backup state (BS) flag set to this value. Defaults to the authenticator's defaultBackupState value.", "typeRef": null}, {"name": "userName", "type": "string", "optional": true, "description": "The credential's user.name property. Equivalent to empty if not set. https://w3c.github.io/webauthn/#dom-publickeycredentialentity-name", "typeRef": null}, {"name": "userDisplayName", "type": "string", "optional": true, "description": "The credential's user.displayName property. Equivalent to empty if not set. https://w3c.github.io/webauthn/#dom-publickeycredentialuserentity-displayname", "typeRef": null}]);
1519
1519
 
1520
+ // WebMCP.
1521
+ inspectorBackend.registerEvent("WebMCP.toolsAdded", ["tools"]);
1522
+ inspectorBackend.registerEvent("WebMCP.toolsRemoved", ["tools"]);
1523
+ inspectorBackend.registerCommand("WebMCP.enable", [], [], "Enables the WebMCP domain, allowing events to be sent. Enabling the domain will trigger a toolsAdded event for all currently registered tools.");
1524
+ inspectorBackend.registerType("WebMCP.Annotation", [{"name": "readOnly", "type": "boolean", "optional": true, "description": "A hint indicating that the tool does not modify any state.", "typeRef": null}, {"name": "autosubmit", "type": "boolean", "optional": true, "description": "If the declarative tool was declared with the autosubmit attribute.", "typeRef": null}]);
1525
+ inspectorBackend.registerType("WebMCP.Tool", [{"name": "name", "type": "string", "optional": false, "description": "Tool name.", "typeRef": null}, {"name": "description", "type": "string", "optional": false, "description": "Tool description.", "typeRef": null}, {"name": "inputSchema", "type": "object", "optional": true, "description": "Schema for the tool's input parameters.", "typeRef": null}, {"name": "annotations", "type": "object", "optional": true, "description": "Optional annotations for the tool.", "typeRef": "WebMCP.Annotation"}, {"name": "frameId", "type": "string", "optional": false, "description": "Frame identifier associated with the tool registration.", "typeRef": "Page.FrameId"}, {"name": "backendNodeId", "type": "number", "optional": true, "description": "Optional node ID for declarative tools.", "typeRef": "DOM.BackendNodeId"}, {"name": "stackTrace", "type": "object", "optional": true, "description": "The stack trace at the time of the registration.", "typeRef": "Runtime.StackTrace"}]);
1526
+
1520
1527
  // Debugger.
1521
1528
  inspectorBackend.registerEnum("Debugger.ScopeType", {Global: "global", Local: "local", With: "with", Closure: "closure", Catch: "catch", Block: "block", Script: "script", Eval: "eval", Module: "module", WasmExpressionStack: "wasm-expression-stack"});
1522
1529
  inspectorBackend.registerEnum("Debugger.BreakLocationType", {DebuggerStatement: "debuggerStatement", Call: "call", Return: "return"});
@@ -930,6 +930,14 @@ export namespace ProtocolMapping {
930
930
  * Triggered when a credential is used in a webauthn assertion.
931
931
  */
932
932
  'WebAuthn.credentialAsserted': [Protocol.WebAuthn.CredentialAssertedEvent];
933
+ /**
934
+ * Event fired when new tools are added.
935
+ */
936
+ 'WebMCP.toolsAdded': [Protocol.WebMCP.ToolsAddedEvent];
937
+ /**
938
+ * Event fired when tools are removed.
939
+ */
940
+ 'WebMCP.toolsRemoved': [Protocol.WebMCP.ToolsRemovedEvent];
933
941
  /**
934
942
  * Fired when breakpoint is resolved to an actual script and location.
935
943
  * Deprecated in favor of `resolvedBreakpoints` in the `scriptParsed` event.
@@ -5372,6 +5380,14 @@ export namespace ProtocolMapping {
5372
5380
  paramsType: [Protocol.WebAuthn.SetCredentialPropertiesRequest];
5373
5381
  returnType: void;
5374
5382
  };
5383
+ /**
5384
+ * Enables the WebMCP domain, allowing events to be sent. Enabling the domain will trigger a toolsAdded event for
5385
+ * all currently registered tools.
5386
+ */
5387
+ 'WebMCP.enable': {
5388
+ paramsType: [];
5389
+ returnType: void;
5390
+ };
5375
5391
  /**
5376
5392
  * Continues execution until specific location is reached.
5377
5393
  */
@@ -114,6 +114,8 @@ declare namespace ProtocolProxyApi {
114
114
 
115
115
  WebAuthn: WebAuthnApi;
116
116
 
117
+ WebMCP: WebMCPApi;
118
+
117
119
  Debugger: DebuggerApi;
118
120
 
119
121
  HeapProfiler: HeapProfilerApi;
@@ -223,6 +225,8 @@ declare namespace ProtocolProxyApi {
223
225
 
224
226
  WebAuthn: WebAuthnDispatcher;
225
227
 
228
+ WebMCP: WebMCPDispatcher;
229
+
226
230
  Debugger: DebuggerDispatcher;
227
231
 
228
232
  HeapProfiler: HeapProfilerDispatcher;
@@ -4849,6 +4853,27 @@ declare namespace ProtocolProxyApi {
4849
4853
 
4850
4854
  }
4851
4855
 
4856
+ export interface WebMCPApi {
4857
+ /**
4858
+ * Enables the WebMCP domain, allowing events to be sent. Enabling the domain will trigger a toolsAdded event for
4859
+ * all currently registered tools.
4860
+ */
4861
+ invoke_enable(): Promise<Protocol.ProtocolResponseWithError>;
4862
+
4863
+ }
4864
+ export interface WebMCPDispatcher {
4865
+ /**
4866
+ * Event fired when new tools are added.
4867
+ */
4868
+ toolsAdded(params: Protocol.WebMCP.ToolsAddedEvent): void;
4869
+
4870
+ /**
4871
+ * Event fired when tools are removed.
4872
+ */
4873
+ toolsRemoved(params: Protocol.WebMCP.ToolsRemovedEvent): void;
4874
+
4875
+ }
4876
+
4852
4877
  export interface DebuggerApi {
4853
4878
  /**
4854
4879
  * Continues execution until specific location is reached.