chrome-devtools-mcp 0.8.1 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/README.md +69 -9
  2. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Console.js +1 -8
  3. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Gzip.js +8 -6
  4. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/ParsedURL.js +10 -20
  5. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/SegmentedRange.js +1 -2
  6. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Settings.js +4 -1
  7. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/StringOutputStream.js +1 -4
  8. package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Worker.js +10 -2
  9. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/AidaClient.js +19 -0
  10. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/DispatchHttpRequestClient.js +54 -0
  11. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/GdpClient.js +6 -51
  12. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/InspectorFrontendHost.js +2 -2
  13. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/InspectorFrontendHostAPI.js +32 -29
  14. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/UserMetrics.js +15 -6
  15. package/build/node_modules/chrome-devtools-frontend/front_end/core/host/host.js +2 -1
  16. package/build/node_modules/chrome-devtools-frontend/front_end/core/platform/ArrayUtilities.js +1 -1
  17. package/build/node_modules/chrome-devtools-frontend/front_end/core/protocol_client/CDPConnection.js +17 -0
  18. package/build/node_modules/chrome-devtools-frontend/front_end/core/protocol_client/ConnectionTransport.js +12 -0
  19. package/build/node_modules/chrome-devtools-frontend/front_end/core/protocol_client/InspectorBackend.js +81 -213
  20. package/build/node_modules/chrome-devtools-frontend/front_end/core/protocol_client/protocol_client.js +3 -8
  21. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/AnimationModel.js +1 -2
  22. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSMatchedStyles.js +45 -10
  23. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSModel.js +1 -1
  24. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSProperty.js +3 -6
  25. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSPropertyParserMatchers.js +14 -10
  26. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSRule.js +34 -6
  27. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/CSSStyleDeclaration.js +4 -4
  28. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/ChildTargetManager.js +8 -33
  29. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/Connections.js +10 -47
  30. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/DOMModel.js +4 -0
  31. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/DebuggerModel.js +3 -3
  32. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/EnhancedTracesParser.js +17 -3
  33. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/NetworkManager.js +371 -53
  34. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/NetworkRequest.js +5 -0
  35. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/PreloadingModel.js +56 -13
  36. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/RehydratingConnection.js +133 -10
  37. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/ResourceTreeModel.js +1 -1
  38. package/build/node_modules/chrome-devtools-frontend/front_end/{models/source_map_scopes → core/sdk}/ScopeTreeCache.js +9 -5
  39. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/SourceMap.js +50 -14
  40. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/SourceMapManager.js +8 -2
  41. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/SourceMapScopesInfo.js +131 -8
  42. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/TargetManager.js +0 -21
  43. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/TraceObject.js +9 -6
  44. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/sdk-meta.js +8 -1
  45. package/build/node_modules/chrome-devtools-frontend/front_end/core/sdk/sdk.js +2 -1
  46. package/build/node_modules/chrome-devtools-frontend/front_end/generated/ARIAProperties.js +1301 -174
  47. package/build/node_modules/chrome-devtools-frontend/front_end/generated/Deprecation.js +7 -0
  48. package/build/node_modules/chrome-devtools-frontend/front_end/generated/InspectorBackendCommands.js +9 -45
  49. package/build/node_modules/chrome-devtools-frontend/front_end/generated/SupportedCSSProperties.js +74 -19
  50. package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.js +50 -34
  51. package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.js +46 -45
  52. package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/performance/AICallTree.js +2 -3
  53. package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/performance/AIContext.js +10 -25
  54. package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/CompilerScriptMapping.js +45 -2
  55. package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/DebuggerWorkspaceBinding.js +1 -1
  56. package/build/node_modules/chrome-devtools-frontend/front_end/models/cpu_profile/ProfileTreeModel.js +6 -7
  57. package/build/node_modules/chrome-devtools-frontend/front_end/models/formatter/FormatterWorkerPool.js +14 -0
  58. package/build/node_modules/chrome-devtools-frontend/front_end/models/source_map_scopes/NamesResolver.js +5 -11
  59. package/build/node_modules/chrome-devtools-frontend/front_end/models/source_map_scopes/source_map_scopes.js +1 -2
  60. package/build/node_modules/chrome-devtools-frontend/front_end/models/stack_trace/StackTraceModel.js +1 -1
  61. package/build/node_modules/chrome-devtools-frontend/front_end/models/stack_trace/Trie.js +8 -0
  62. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/ModelImpl.js +6 -3
  63. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/extras/TraceTree.js +10 -3
  64. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/MetaHandler.js +4 -1
  65. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/NetworkRequestsHandler.js +12 -3
  66. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/handlers/UserTimingsHandler.js +1 -1
  67. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/CLSCulprits.js +2 -1
  68. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/Cache.js +2 -1
  69. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/DOMSize.js +2 -1
  70. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/DocumentLatency.js +2 -1
  71. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/DuplicatedJavaScript.js +2 -1
  72. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/FontDisplay.js +2 -1
  73. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/ForcedReflow.js +3 -2
  74. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/INPBreakdown.js +2 -1
  75. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/ImageDelivery.js +2 -1
  76. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/LCPBreakdown.js +2 -1
  77. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/LCPDiscovery.js +2 -1
  78. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/LegacyJavaScript.js +2 -1
  79. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/ModernHTTP.js +2 -1
  80. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/NetworkDependencyTree.js +2 -1
  81. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/RenderBlocking.js +2 -1
  82. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/SlowCSSSelector.js +2 -1
  83. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/ThirdParties.js +2 -1
  84. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/Viewport.js +2 -1
  85. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/types/TraceEvents.js +3 -0
  86. package/build/node_modules/chrome-devtools-frontend/front_end/models/trace_source_maps_resolver/SourceMapsResolver.js +1 -1
  87. package/build/node_modules/chrome-devtools-frontend/mcp/mcp.js +14 -0
  88. package/build/src/DevToolsConnectionAdapter.js +33 -0
  89. package/build/src/DevtoolsUtils.js +44 -0
  90. package/build/src/McpContext.js +182 -33
  91. package/build/src/McpResponse.js +169 -57
  92. package/build/src/PageCollector.js +123 -27
  93. package/build/src/WaitForHelper.js +5 -0
  94. package/build/src/browser.js +24 -12
  95. package/build/src/cli.js +87 -6
  96. package/build/src/formatters/consoleFormatter.js +29 -62
  97. package/build/src/formatters/networkFormatter.js +5 -6
  98. package/build/src/formatters/snapshotFormatter.js +28 -11
  99. package/build/src/logger.js +1 -1
  100. package/build/src/main.js +24 -6
  101. package/build/src/polyfill.js +2 -2
  102. package/build/src/third_party/THIRD_PARTY_NOTICES +1413 -0
  103. package/build/src/third_party/index.js +82791 -0
  104. package/build/src/tools/ToolDefinition.js +2 -2
  105. package/build/src/tools/categories.js +17 -9
  106. package/build/src/tools/console.js +71 -6
  107. package/build/src/tools/emulation.js +40 -48
  108. package/build/src/tools/input.js +57 -27
  109. package/build/src/tools/network.js +43 -13
  110. package/build/src/tools/pages.js +75 -49
  111. package/build/src/tools/performance.js +13 -10
  112. package/build/src/tools/screenshot.js +10 -9
  113. package/build/src/tools/script.js +29 -15
  114. package/build/src/tools/snapshot.js +27 -23
  115. package/build/src/trace-processing/parse.js +6 -16
  116. package/build/src/utils/keyboard.js +291 -0
  117. package/build/src/utils/types.js +6 -0
  118. package/package.json +16 -12
package/README.md CHANGED
@@ -125,8 +125,7 @@ Configure the following fields and press `CTRL+S` to save the configuration:
125
125
 
126
126
  - **Server name:** `chrome-devtools`
127
127
  - **Server Type:** `[1] Local`
128
- - **Command:** `npx`
129
- - **Arguments:** `-y, chrome-devtools-mcp@latest`
128
+ - **Command:** `npx -y chrome-devtools-mcp@latest`
130
129
 
131
130
  </details>
132
131
 
@@ -196,6 +195,15 @@ Or, from the IDE **Activity Bar** > `Kiro` > `MCP Servers` > `Click Open MCP Con
196
195
 
197
196
  </details>
198
197
 
198
+ <details>
199
+ <summary>Qoder</summary>
200
+
201
+ In **Qoder Settings**, go to `MCP Server` > `+ Add` > Use the configuration snippet provided above.
202
+
203
+ Alternatively, follow the <a href="https://docs.qoder.com/user-guide/chat/model-context-protocol">MCP guide</a> and use the standard config from above.
204
+
205
+ </details>
206
+
199
207
  <details>
200
208
  <summary>Visual Studio</summary>
201
209
 
@@ -211,6 +219,12 @@ Go to `Settings | AI | Manage MCP Servers` -> `+ Add` to [add an MCP Server](htt
211
219
 
212
220
  </details>
213
221
 
222
+ <details>
223
+ <summary>Windsurf</summary>
224
+ Follow the <a href="https://docs.windsurf.com/windsurf/cascade/mcp#mcp-config-json">configure MCP guide</a>
225
+ using the standard config from above.
226
+ </details>
227
+
214
228
  ### Your first prompt
215
229
 
216
230
  Enter the following prompt in your MCP Client to check if everything is working:
@@ -230,25 +244,24 @@ If you run into any issues, checkout our [troubleshooting guide](./docs/troubles
230
244
 
231
245
  <!-- BEGIN AUTO GENERATED TOOLS -->
232
246
 
233
- - **Input automation** (7 tools)
247
+ - **Input automation** (8 tools)
234
248
  - [`click`](docs/tool-reference.md#click)
235
249
  - [`drag`](docs/tool-reference.md#drag)
236
250
  - [`fill`](docs/tool-reference.md#fill)
237
251
  - [`fill_form`](docs/tool-reference.md#fill_form)
238
252
  - [`handle_dialog`](docs/tool-reference.md#handle_dialog)
239
253
  - [`hover`](docs/tool-reference.md#hover)
254
+ - [`press_key`](docs/tool-reference.md#press_key)
240
255
  - [`upload_file`](docs/tool-reference.md#upload_file)
241
- - **Navigation automation** (7 tools)
256
+ - **Navigation automation** (6 tools)
242
257
  - [`close_page`](docs/tool-reference.md#close_page)
243
258
  - [`list_pages`](docs/tool-reference.md#list_pages)
244
259
  - [`navigate_page`](docs/tool-reference.md#navigate_page)
245
- - [`navigate_page_history`](docs/tool-reference.md#navigate_page_history)
246
260
  - [`new_page`](docs/tool-reference.md#new_page)
247
261
  - [`select_page`](docs/tool-reference.md#select_page)
248
262
  - [`wait_for`](docs/tool-reference.md#wait_for)
249
- - **Emulation** (3 tools)
250
- - [`emulate_cpu`](docs/tool-reference.md#emulate_cpu)
251
- - [`emulate_network`](docs/tool-reference.md#emulate_network)
263
+ - **Emulation** (2 tools)
264
+ - [`emulate`](docs/tool-reference.md#emulate)
252
265
  - [`resize_page`](docs/tool-reference.md#resize_page)
253
266
  - **Performance** (3 tools)
254
267
  - [`performance_analyze_insight`](docs/tool-reference.md#performance_analyze_insight)
@@ -257,8 +270,9 @@ If you run into any issues, checkout our [troubleshooting guide](./docs/troubles
257
270
  - **Network** (2 tools)
258
271
  - [`get_network_request`](docs/tool-reference.md#get_network_request)
259
272
  - [`list_network_requests`](docs/tool-reference.md#list_network_requests)
260
- - **Debugging** (4 tools)
273
+ - **Debugging** (5 tools)
261
274
  - [`evaluate_script`](docs/tool-reference.md#evaluate_script)
275
+ - [`get_console_message`](docs/tool-reference.md#get_console_message)
262
276
  - [`list_console_messages`](docs/tool-reference.md#list_console_messages)
263
277
  - [`take_screenshot`](docs/tool-reference.md#take_screenshot)
264
278
  - [`take_snapshot`](docs/tool-reference.md#take_snapshot)
@@ -275,6 +289,14 @@ The Chrome DevTools MCP server supports the following configuration option:
275
289
  Connect to a running Chrome instance using port forwarding. For more details see: https://developer.chrome.com/docs/devtools/remote-debugging/local-server.
276
290
  - **Type:** string
277
291
 
292
+ - **`--wsEndpoint`, `-w`**
293
+ WebSocket endpoint to connect to a running Chrome instance (e.g., ws://127.0.0.1:9222/devtools/browser/<id>). Alternative to --browserUrl.
294
+ - **Type:** string
295
+
296
+ - **`--wsHeaders`**
297
+ Custom headers for WebSocket connection in JSON format (e.g., '{"Authorization":"Bearer token"}'). Only works with --wsEndpoint.
298
+ - **Type:** string
299
+
278
300
  - **`--headless`**
279
301
  Whether to run in headless (no UI) mode.
280
302
  - **Type:** boolean
@@ -314,6 +336,21 @@ The Chrome DevTools MCP server supports the following configuration option:
314
336
  Additional arguments for Chrome. Only applies when Chrome is launched by chrome-devtools-mcp.
315
337
  - **Type:** array
316
338
 
339
+ - **`--categoryEmulation`**
340
+ Set to false to exclude tools related to emulation.
341
+ - **Type:** boolean
342
+ - **Default:** `true`
343
+
344
+ - **`--categoryPerformance`**
345
+ Set to false to exclude tools related to performance.
346
+ - **Type:** boolean
347
+ - **Default:** `true`
348
+
349
+ - **`--categoryNetwork`**
350
+ Set to false to exclude tools related to network.
351
+ - **Type:** boolean
352
+ - **Default:** `true`
353
+
317
354
  <!-- END AUTO GENERATED OPTIONS -->
318
355
 
319
356
  Pass them via the `args` property in the JSON configuration. For example:
@@ -334,6 +371,27 @@ Pass them via the `args` property in the JSON configuration. For example:
334
371
  }
335
372
  ```
336
373
 
374
+ ### Connecting via WebSocket with custom headers
375
+
376
+ You can connect directly to a Chrome WebSocket endpoint and include custom headers (e.g., for authentication):
377
+
378
+ ```json
379
+ {
380
+ "mcpServers": {
381
+ "chrome-devtools": {
382
+ "command": "npx",
383
+ "args": [
384
+ "chrome-devtools-mcp@latest",
385
+ "--wsEndpoint=ws://127.0.0.1:9222/devtools/browser/<id>",
386
+ "--wsHeaders={\"Authorization\":\"Bearer YOUR_TOKEN\"}"
387
+ ]
388
+ }
389
+ }
390
+ }
391
+ ```
392
+
393
+ To get the WebSocket endpoint from a running Chrome instance, visit `http://127.0.0.1:9222/json/version` and look for the `webSocketDebuggerUrl` field.
394
+
337
395
  You can also run `npx chrome-devtools-mcp@latest --help` to see all available configuration options.
338
396
 
339
397
  ## Concepts
@@ -412,6 +470,8 @@ Check the performance of https://developers.chrome.com
412
470
 
413
471
  Your MCP client should connect to the running Chrome instance and receive a performance report.
414
472
 
473
+ If you hit VM-to-host port forwarding issues, see the “Remote debugging between virtual machine (VM) and host fails” section in [`docs/troubleshooting.md`](./docs/troubleshooting.md#remote-debugging-between-virtual-machine-vm-and-host-fails).
474
+
415
475
  For more details on remote debugging, see the [Chrome DevTools documentation](https://developer.chrome.com/docs/devtools/remote-debugging/).
416
476
 
417
477
  ## Known limitations
@@ -5,14 +5,7 @@ import { ObjectWrapper } from './Object.js';
5
5
  import { reveal } from './Revealer.js';
6
6
  let consoleInstance;
7
7
  export class Console extends ObjectWrapper {
8
- #messages;
9
- /**
10
- * Instantiable via the instance() factory below.
11
- */
12
- constructor() {
13
- super();
14
- this.#messages = [];
15
- }
8
+ #messages = [];
16
9
  static instance(opts) {
17
10
  if (!consoleInstance || opts?.forceNew) {
18
11
  consoleInstance = new Console();
@@ -44,14 +44,16 @@ export async function compress(str) {
44
44
  return buffer;
45
45
  }
46
46
  /** Private coder/decoder **/
47
- function gzipCodec(buffer, codecStream) {
48
- const { readable, writable } = new TransformStream();
47
+ async function gzipCodec(buffer, codecStream) {
48
+ const readable = new ReadableStream({
49
+ start(controller) {
50
+ controller.enqueue(buffer);
51
+ controller.close();
52
+ }
53
+ });
49
54
  const codecReadable = readable.pipeThrough(codecStream);
50
- const writer = writable.getWriter();
51
- void writer.write(buffer);
52
- void writer.close();
53
55
  // A response is a convenient way to get an ArrayBuffer from a ReadableStream.
54
- return new Response(codecReadable).arrayBuffer();
56
+ return await new Response(codecReadable).arrayBuffer();
55
57
  }
56
58
  export function decompressStream(stream) {
57
59
  // https://github.com/wicg/compression/blob/main/explainer.md#deflate-compress-an-arraybuffer
@@ -44,32 +44,22 @@ export function schemeIs(url, scheme) {
44
44
  }
45
45
  }
46
46
  export class ParsedURL {
47
- isValid;
47
+ isValid = false;
48
48
  url;
49
- scheme;
50
- user;
51
- host;
52
- port;
53
- path;
54
- queryParams;
55
- fragment;
56
- folderPathComponents;
57
- lastPathComponent;
49
+ scheme = '';
50
+ user = '';
51
+ host = '';
52
+ port = '';
53
+ path = '';
54
+ queryParams = '';
55
+ fragment = '';
56
+ folderPathComponents = '';
57
+ lastPathComponent = '';
58
58
  blobInnerScheme;
59
59
  #displayName;
60
60
  #dataURLDisplayName;
61
61
  constructor(url) {
62
- this.isValid = false;
63
62
  this.url = url;
64
- this.scheme = '';
65
- this.user = '';
66
- this.host = '';
67
- this.port = '';
68
- this.path = '';
69
- this.queryParams = '';
70
- this.fragment = '';
71
- this.folderPathComponents = '';
72
- this.lastPathComponent = '';
73
63
  const isBlobUrl = this.url.startsWith('blob:');
74
64
  const urlToMatch = isBlobUrl ? url.substring(5) : url;
75
65
  const match = urlToMatch.match(ParsedURL.urlRegex());
@@ -19,10 +19,9 @@ export class Segment {
19
19
  }
20
20
  }
21
21
  export class SegmentedRange {
22
- #segments;
22
+ #segments = [];
23
23
  #mergeCallback;
24
24
  constructor(mergeCallback) {
25
- this.#segments = [];
26
25
  this.#mergeCallback = mergeCallback;
27
26
  }
28
27
  append(newSegment) {
@@ -93,7 +93,7 @@ export class Settings {
93
93
  * to store UI state such as how a user choses to position a split widget or
94
94
  * which panel they last opened.
95
95
  * If you are creating a setting that you expect the user to control, and
96
- * sync, prefer {@see createSetting}
96
+ * sync, prefer {@link Settings.createSetting}
97
97
  */
98
98
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
99
99
  moduleSetting(settingName) {
@@ -473,6 +473,9 @@ export class Setting {
473
473
  }
474
474
  return null;
475
475
  }
476
+ /**
477
+ * See {@link LearnMore} for more info
478
+ */
476
479
  learnMore() {
477
480
  return this.#registration?.learnMore ?? null;
478
481
  }
@@ -2,10 +2,7 @@
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
  export class StringOutputStream {
5
- #data;
6
- constructor() {
7
- this.#data = '';
8
- }
5
+ #data = '';
9
6
  async write(chunk) {
10
7
  this.#data += chunk;
11
8
  }
@@ -4,9 +4,14 @@
4
4
  export class WorkerWrapper {
5
5
  #workerPromise;
6
6
  #disposed;
7
+ #rejectWorkerPromise;
7
8
  constructor(workerLocation) {
8
- this.#workerPromise = new Promise(fulfill => {
9
+ this.#workerPromise = new Promise((fulfill, reject) => {
10
+ this.#rejectWorkerPromise = reject;
9
11
  const worker = new Worker(workerLocation, { type: 'module' });
12
+ worker.onerror = event => {
13
+ console.error(`Failed to load worker for ${workerLocation.href}:`, event);
14
+ };
10
15
  worker.onmessage = (event) => {
11
16
  console.assert(event.data === 'workerReady');
12
17
  worker.onmessage = null;
@@ -28,7 +33,10 @@ export class WorkerWrapper {
28
33
  this.#disposed = true;
29
34
  void this.#workerPromise.then(worker => worker.terminate());
30
35
  }
31
- terminate() {
36
+ terminate(immediately = false) {
37
+ if (immediately) {
38
+ this.#rejectWorkerPromise?.(new Error('Worker terminated'));
39
+ }
32
40
  this.dispose();
33
41
  }
34
42
  set onmessage(listener) {
@@ -3,6 +3,7 @@
3
3
  // found in the LICENSE file.
4
4
  import * as Common from '../common/common.js';
5
5
  import * as Root from '../root/root.js';
6
+ import * as DispatchHttpRequestClient from './DispatchHttpRequestClient.js';
6
7
  import { InspectorFrontendHostInstance } from './InspectorFrontendHost.js';
7
8
  import { bindOutputStream } from './ResourceLoader.js';
8
9
  export var Role;
@@ -95,6 +96,14 @@ export var Reason;
95
96
  Reason[Reason["RELATED_FILE"] = 5] = "RELATED_FILE";
96
97
  })(Reason || (Reason = {}));
97
98
  /* eslint-enable @typescript-eslint/naming-convention */
99
+ export var UseCase;
100
+ (function (UseCase) {
101
+ // Unspecified usecase.
102
+ UseCase[UseCase["USE_CASE_UNSPECIFIED"] = 0] = "USE_CASE_UNSPECIFIED";
103
+ // Code generation use case is expected to generate code from scratch
104
+ UseCase[UseCase["CODE_GENERATION"] = 1] = "CODE_GENERATION";
105
+ })(UseCase || (UseCase = {}));
106
+ /* eslint-enable @typescript-eslint/naming-convention */
98
107
  export var RecitationAction;
99
108
  (function (RecitationAction) {
100
109
  RecitationAction["ACTION_UNSPECIFIED"] = "ACTION_UNSPECIFIED";
@@ -129,6 +138,7 @@ const AidaLanguageToMarkdown = {
129
138
  XML: 'xml',
130
139
  };
131
140
  export const CLIENT_NAME = 'CHROME_DEVTOOLS';
141
+ export const SERVICE_NAME = 'aidaService';
132
142
  const CODE_CHUNK_SEPARATOR = (lang = '') => ('\n`````' + lang + '\n');
133
143
  export class AidaAbortError extends Error {
134
144
  }
@@ -358,6 +368,15 @@ export class AidaClient {
358
368
  }
359
369
  return { generatedSamples, metadata };
360
370
  }
371
+ async generateCode(request) {
372
+ const response = await DispatchHttpRequestClient.makeHttpRequest({
373
+ service: SERVICE_NAME,
374
+ path: '/v1/aida:generateCode',
375
+ method: 'POST',
376
+ body: JSON.stringify(request),
377
+ });
378
+ return response;
379
+ }
361
380
  }
362
381
  export function convertToUserTierEnum(userTier) {
363
382
  if (userTier) {
@@ -0,0 +1,54 @@
1
+ // Copyright 2025 The Chromium Authors
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+ import { InspectorFrontendHostInstance } from './InspectorFrontendHost.js';
5
+ export var ErrorType;
6
+ (function (ErrorType) {
7
+ ErrorType["HTTP_RESPONSE_UNAVAILABLE"] = "HTTP_RESPONSE_UNAVAILABLE";
8
+ ErrorType["NOT_FOUND"] = "NOT_FOUND";
9
+ })(ErrorType || (ErrorType = {}));
10
+ export class DispatchHttpRequestError extends Error {
11
+ type;
12
+ constructor(type, options) {
13
+ super(undefined, options);
14
+ this.type = type;
15
+ }
16
+ }
17
+ export async function makeHttpRequest(request) {
18
+ const response = await new Promise(resolve => {
19
+ InspectorFrontendHostInstance.dispatchHttpRequest(request, resolve);
20
+ });
21
+ debugLog({ request, response });
22
+ if (response.statusCode === 404) {
23
+ throw new DispatchHttpRequestError(ErrorType.NOT_FOUND);
24
+ }
25
+ if ('response' in response && response.statusCode === 200) {
26
+ try {
27
+ return JSON.parse(response.response);
28
+ }
29
+ catch (err) {
30
+ throw new DispatchHttpRequestError(ErrorType.HTTP_RESPONSE_UNAVAILABLE, { cause: err });
31
+ }
32
+ }
33
+ throw new DispatchHttpRequestError(ErrorType.HTTP_RESPONSE_UNAVAILABLE);
34
+ }
35
+ function isDebugMode() {
36
+ return Boolean(localStorage.getItem('debugDispatchHttpRequestEnabled'));
37
+ }
38
+ function debugLog(...log) {
39
+ if (!isDebugMode()) {
40
+ return;
41
+ }
42
+ // eslint-disable-next-line no-console
43
+ console.log('debugLog', ...log);
44
+ }
45
+ function setDebugDispatchHttpRequestEnabled(enabled) {
46
+ if (enabled) {
47
+ localStorage.setItem('debugDispatchHttpRequestEnabled', 'true');
48
+ }
49
+ else {
50
+ localStorage.removeItem('debugDispatchHttpRequestEnabled');
51
+ }
52
+ }
53
+ // @ts-expect-error
54
+ globalThis.setDebugDispatchHttpRequestEnabled = setDebugDispatchHttpRequestEnabled;
@@ -2,7 +2,7 @@
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
  import * as Root from '../root/root.js';
5
- import { InspectorFrontendHostInstance } from './InspectorFrontendHost.js';
5
+ import * as DispatchHttpRequestClient from './DispatchHttpRequestClient.js';
6
6
  export var SubscriptionStatus;
7
7
  (function (SubscriptionStatus) {
8
8
  SubscriptionStatus["ENABLED"] = "SUBSCRIPTION_STATE_ENABLED";
@@ -29,18 +29,6 @@ export var EmailPreference;
29
29
  EmailPreference["ENABLED"] = "ENABLED";
30
30
  EmailPreference["DISABLED"] = "DISABLED";
31
31
  })(EmailPreference || (EmailPreference = {}));
32
- export var GdpErrorType;
33
- (function (GdpErrorType) {
34
- GdpErrorType["HTTP_RESPONSE_UNAVAILABLE"] = "HTTP_RESPONSE_UNAVAILABLE";
35
- GdpErrorType["NOT_FOUND"] = "NOT_FOUND";
36
- })(GdpErrorType || (GdpErrorType = {}));
37
- class GdpError extends Error {
38
- type;
39
- constructor(type, options) {
40
- super(undefined, options);
41
- this.type = type;
42
- }
43
- }
44
32
  /**
45
33
  * The `batchGet` awards endpoint returns badge names with an
46
34
  * obfuscated user ID (e.g., `profiles/12345/awards/badge-name`).
@@ -54,24 +42,10 @@ function normalizeBadgeName(name) {
54
42
  export const GOOGLE_DEVELOPER_PROGRAM_PROFILE_LINK = 'https://developers.google.com/profile/u/me';
55
43
  async function makeHttpRequest(request) {
56
44
  if (!isGdpProfilesAvailable()) {
57
- throw new GdpError(GdpErrorType.HTTP_RESPONSE_UNAVAILABLE);
58
- }
59
- const response = await new Promise(resolve => {
60
- InspectorFrontendHostInstance.dispatchHttpRequest(request, resolve);
61
- });
62
- debugLog({ request, response });
63
- if (response.statusCode === 404) {
64
- throw new GdpError(GdpErrorType.NOT_FOUND);
65
- }
66
- if ('response' in response && response.statusCode === 200) {
67
- try {
68
- return JSON.parse(response.response);
69
- }
70
- catch (err) {
71
- throw new GdpError(GdpErrorType.HTTP_RESPONSE_UNAVAILABLE, { cause: err });
72
- }
45
+ throw new DispatchHttpRequestClient.DispatchHttpRequestError(DispatchHttpRequestClient.ErrorType.HTTP_RESPONSE_UNAVAILABLE);
73
46
  }
74
- throw new GdpError(GdpErrorType.HTTP_RESPONSE_UNAVAILABLE);
47
+ const response = await DispatchHttpRequestClient.makeHttpRequest(request);
48
+ return response;
75
49
  }
76
50
  const SERVICE_NAME = 'gdpService';
77
51
  let gdpClientInstance = null;
@@ -105,7 +79,8 @@ export class GdpClient {
105
79
  };
106
80
  }
107
81
  catch (err) {
108
- if (err instanceof GdpError && err.type === GdpErrorType.HTTP_RESPONSE_UNAVAILABLE) {
82
+ if (err instanceof DispatchHttpRequestClient.DispatchHttpRequestError &&
83
+ err.type === DispatchHttpRequestClient.ErrorType.HTTP_RESPONSE_UNAVAILABLE) {
109
84
  return null;
110
85
  }
111
86
  }
@@ -202,24 +177,6 @@ export class GdpClient {
202
177
  }
203
178
  }
204
179
  }
205
- function isDebugMode() {
206
- return Boolean(localStorage.getItem('debugGdpIntegrationEnabled'));
207
- }
208
- function debugLog(...log) {
209
- if (!isDebugMode()) {
210
- return;
211
- }
212
- // eslint-disable-next-line no-console
213
- console.log('debugLog', ...log);
214
- }
215
- function setDebugGdpIntegrationEnabled(enabled) {
216
- if (enabled) {
217
- localStorage.setItem('debugGdpIntegrationEnabled', 'true');
218
- }
219
- else {
220
- localStorage.removeItem('debugGdpIntegrationEnabled');
221
- }
222
- }
223
180
  export function isGdpProfilesAvailable() {
224
181
  const isBaseFeatureEnabled = Boolean(Root.Runtime.hostConfig.devToolsGdpProfiles?.enabled);
225
182
  const isBrandedBuild = Boolean(Root.Runtime.hostConfig.devToolsGdpProfilesAvailability?.enabled);
@@ -239,5 +196,3 @@ export function isBadgesEnabled() {
239
196
  export function isStarterBadgeEnabled() {
240
197
  return Boolean(Root.Runtime.hostConfig.devToolsGdpProfiles?.starterBadgeEnabled);
241
198
  }
242
- // @ts-expect-error
243
- globalThis.setDebugGdpIntegrationEnabled = setDebugGdpIntegrationEnabled;
@@ -140,7 +140,7 @@ export class InspectorFrontendHostStub {
140
140
  fileName = url;
141
141
  }
142
142
  }
143
- /* eslint-disable-next-line rulesdir/no-imperative-dom-api */
143
+ /* eslint-disable-next-line @devtools/no-imperative-dom-api */
144
144
  const link = document.createElement('a');
145
145
  link.download = fileName;
146
146
  let blob;
@@ -439,7 +439,7 @@ class InspectorFrontendAPIImpl {
439
439
  constructor() {
440
440
  for (const descriptor of EventDescriptors) {
441
441
  // @ts-expect-error Dispatcher magic
442
- this[descriptor[1]] = this.dispatch.bind(this, descriptor[0], descriptor[2], descriptor[3]);
442
+ this[descriptor[0]] = this.dispatch.bind(this, descriptor[0], descriptor[1], descriptor[2]);
443
443
  }
444
444
  }
445
445
  dispatch(name, signature, _runOnceLoaded, ...params) {
@@ -1,6 +1,9 @@
1
1
  // Copyright 2015 The Chromium Authors
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
+ /**
5
+ * This values should match the one getting called from Chromium
6
+ */
4
7
  export var Events;
5
8
  (function (Events) {
6
9
  /* eslint-disable @typescript-eslint/naming-convention -- Accessed from web_tests */
@@ -20,7 +23,7 @@ export var Events;
20
23
  Events["FileSystemsLoaded"] = "fileSystemsLoaded";
21
24
  Events["FileSystemRemoved"] = "fileSystemRemoved";
22
25
  Events["FileSystemAdded"] = "fileSystemAdded";
23
- Events["FileSystemFilesChangedAddedRemoved"] = "FileSystemFilesChangedAddedRemoved";
26
+ Events["FileSystemFilesChangedAddedRemoved"] = "fileSystemFilesChangedAddedRemoved";
24
27
  Events["IndexingTotalWorkCalculated"] = "indexingTotalWorkCalculated";
25
28
  Events["IndexingWorked"] = "indexingWorked";
26
29
  Events["IndexingDone"] = "indexingDone";
@@ -35,32 +38,32 @@ export var Events;
35
38
  /* eslint-enable @typescript-eslint/naming-convention */
36
39
  })(Events || (Events = {}));
37
40
  export const EventDescriptors = [
38
- [Events.AppendedToURL, 'appendedToURL', ['url']],
39
- [Events.CanceledSaveURL, 'canceledSaveURL', ['url']],
40
- [Events.ColorThemeChanged, 'colorThemeChanged', []],
41
- [Events.ContextMenuCleared, 'contextMenuCleared', []],
42
- [Events.ContextMenuItemSelected, 'contextMenuItemSelected', ['id']],
43
- [Events.DeviceCountUpdated, 'deviceCountUpdated', ['count']],
44
- [Events.DevicesDiscoveryConfigChanged, 'devicesDiscoveryConfigChanged', ['config']],
45
- [Events.DevicesPortForwardingStatusChanged, 'devicesPortForwardingStatusChanged', ['status']],
46
- [Events.DevicesUpdated, 'devicesUpdated', ['devices']],
47
- [Events.DispatchMessage, 'dispatchMessage', ['messageObject']],
48
- [Events.DispatchMessageChunk, 'dispatchMessageChunk', ['messageChunk', 'messageSize']],
49
- [Events.EnterInspectElementMode, 'enterInspectElementMode', []],
50
- [Events.EyeDropperPickedColor, 'eyeDropperPickedColor', ['color']],
51
- [Events.FileSystemsLoaded, 'fileSystemsLoaded', ['fileSystems']],
52
- [Events.FileSystemRemoved, 'fileSystemRemoved', ['fileSystemPath']],
53
- [Events.FileSystemAdded, 'fileSystemAdded', ['errorMessage', 'fileSystem']],
54
- [Events.FileSystemFilesChangedAddedRemoved, 'fileSystemFilesChangedAddedRemoved', ['changed', 'added', 'removed']],
55
- [Events.IndexingTotalWorkCalculated, 'indexingTotalWorkCalculated', ['requestId', 'fileSystemPath', 'totalWork']],
56
- [Events.IndexingWorked, 'indexingWorked', ['requestId', 'fileSystemPath', 'worked']],
57
- [Events.IndexingDone, 'indexingDone', ['requestId', 'fileSystemPath']],
58
- [Events.KeyEventUnhandled, 'keyEventUnhandled', ['event']],
59
- [Events.ReloadInspectedPage, 'reloadInspectedPage', ['hard']],
60
- [Events.RevealSourceLine, 'revealSourceLine', ['url', 'lineNumber', 'columnNumber']],
61
- [Events.SavedURL, 'savedURL', ['url', 'fileSystemPath']],
62
- [Events.SearchCompleted, 'searchCompleted', ['requestId', 'fileSystemPath', 'files']],
63
- [Events.SetInspectedTabId, 'setInspectedTabId', ['tabId']],
64
- [Events.SetUseSoftMenu, 'setUseSoftMenu', ['useSoftMenu']],
65
- [Events.ShowPanel, 'showPanel', ['panelName']],
41
+ [Events.AppendedToURL, ['url']],
42
+ [Events.CanceledSaveURL, ['url']],
43
+ [Events.ColorThemeChanged, []],
44
+ [Events.ContextMenuCleared, []],
45
+ [Events.ContextMenuItemSelected, ['id']],
46
+ [Events.DeviceCountUpdated, ['count']],
47
+ [Events.DevicesDiscoveryConfigChanged, ['config']],
48
+ [Events.DevicesPortForwardingStatusChanged, ['status']],
49
+ [Events.DevicesUpdated, ['devices']],
50
+ [Events.DispatchMessage, ['messageObject']],
51
+ [Events.DispatchMessageChunk, ['messageChunk', 'messageSize']],
52
+ [Events.EnterInspectElementMode, []],
53
+ [Events.EyeDropperPickedColor, ['color']],
54
+ [Events.FileSystemsLoaded, ['fileSystems']],
55
+ [Events.FileSystemRemoved, ['fileSystemPath']],
56
+ [Events.FileSystemAdded, ['errorMessage', 'fileSystem']],
57
+ [Events.FileSystemFilesChangedAddedRemoved, ['changed', 'added', 'removed']],
58
+ [Events.IndexingTotalWorkCalculated, , ['requestId', 'fileSystemPath', 'totalWork']],
59
+ [Events.IndexingWorked, ['requestId', 'fileSystemPath', 'worked']],
60
+ [Events.IndexingDone, ['requestId', 'fileSystemPath']],
61
+ [Events.KeyEventUnhandled, ['event']],
62
+ [Events.ReloadInspectedPage, ['hard']],
63
+ [Events.RevealSourceLine, ['url', 'lineNumber', 'columnNumber']],
64
+ [Events.SavedURL, ['url', 'fileSystemPath']],
65
+ [Events.SearchCompleted, ['requestId', 'fileSystemPath', 'files']],
66
+ [Events.SetInspectedTabId, ['tabId']],
67
+ [Events.SetUseSoftMenu, ['useSoftMenu']],
68
+ [Events.ShowPanel, ['panelName']],
66
69
  ];
@@ -193,7 +193,7 @@ export class UserMetrics {
193
193
  InspectorFrontendHostInstance.recordEnumeratedHistogram("DevTools.LighthouseCategoryUsed" /* EnumeratedHistogram.LighthouseCategoryUsed */, type, 6 /* LighthouseCategoryUsed.MAX_VALUE */);
194
194
  }
195
195
  swatchActivated(swatch) {
196
- InspectorFrontendHostInstance.recordEnumeratedHistogram("DevTools.SwatchActivated" /* EnumeratedHistogram.SwatchActivated */, swatch, 12 /* SwatchType.MAX_VALUE */);
196
+ InspectorFrontendHostInstance.recordEnumeratedHistogram("DevTools.SwatchActivated" /* EnumeratedHistogram.SwatchActivated */, swatch, 13 /* SwatchType.MAX_VALUE */);
197
197
  }
198
198
  animationPlaybackRateChanged(playbackRate) {
199
199
  InspectorFrontendHostInstance.recordEnumeratedHistogram("DevTools.AnimationPlaybackRateChanged" /* EnumeratedHistogram.AnimationPlaybackRateChanged */, playbackRate, 4 /* AnimationsPlaybackRate.MAX_VALUE */);
@@ -219,6 +219,12 @@ export class UserMetrics {
219
219
  performanceAIMainThreadActivityResponseSize(bytes) {
220
220
  InspectorFrontendHostInstance.recordCountHistogram('DevTools.PerformanceAI.MainThreadActivityResponseSize', bytes, 0, 100_000, 100);
221
221
  }
222
+ builtInAiAvailability(availability) {
223
+ InspectorFrontendHostInstance.recordEnumeratedHistogram("DevTools.BuiltInAiAvailability" /* EnumeratedHistogram.BuiltInAiAvailability */, availability, 10 /* BuiltInAiAvailability.MAX_VALUE */);
224
+ }
225
+ consoleInsightTeaserGenerated(timeInMilliseconds) {
226
+ InspectorFrontendHostInstance.recordPerformanceHistogram('DevTools.Insights.TeaserGenerationTime', timeInMilliseconds);
227
+ }
222
228
  }
223
229
  /**
224
230
  * The numeric enum values are not necessarily continuous! It is possible that
@@ -417,15 +423,20 @@ export var Action;
417
423
  Action[Action["AiAssistanceSideEffectConfirmed"] = 179] = "AiAssistanceSideEffectConfirmed";
418
424
  Action[Action["AiAssistanceSideEffectRejected"] = 180] = "AiAssistanceSideEffectRejected";
419
425
  Action[Action["AiAssistanceError"] = 181] = "AiAssistanceError";
420
- Action[Action["AiAssistanceOpenedFromPerformanceInsight"] = 182] = "AiAssistanceOpenedFromPerformanceInsight";
421
- Action[Action["AiAssistanceOpenedFromPerformanceFullButton"] = 183] = "AiAssistanceOpenedFromPerformanceFullButton";
422
426
  Action[Action["AiCodeCompletionResponseServedFromCache"] = 184] = "AiCodeCompletionResponseServedFromCache";
423
427
  Action[Action["AiCodeCompletionRequestTriggered"] = 185] = "AiCodeCompletionRequestTriggered";
424
428
  Action[Action["AiCodeCompletionSuggestionDisplayed"] = 186] = "AiCodeCompletionSuggestionDisplayed";
425
429
  Action[Action["AiCodeCompletionSuggestionAccepted"] = 187] = "AiCodeCompletionSuggestionAccepted";
426
430
  Action[Action["AiCodeCompletionError"] = 188] = "AiCodeCompletionError";
427
431
  Action[Action["AttributeLinkClicked"] = 189] = "AttributeLinkClicked";
428
- Action[Action["MAX_VALUE"] = 190] = "MAX_VALUE";
432
+ Action[Action["InsightRequestedViaTeaser"] = 190] = "InsightRequestedViaTeaser";
433
+ Action[Action["InsightTeaserGenerationStarted"] = 191] = "InsightTeaserGenerationStarted";
434
+ Action[Action["InsightTeaserGenerationCompleted"] = 192] = "InsightTeaserGenerationCompleted";
435
+ Action[Action["InsightTeaserGenerationAborted"] = 193] = "InsightTeaserGenerationAborted";
436
+ Action[Action["InsightTeaserGenerationErrored"] = 194] = "InsightTeaserGenerationErrored";
437
+ Action[Action["AiCodeGenerationSuggestionDisplayed"] = 195] = "AiCodeGenerationSuggestionDisplayed";
438
+ Action[Action["AiCodeGenerationSuggestionAccepted"] = 196] = "AiCodeGenerationSuggestionAccepted";
439
+ Action[Action["MAX_VALUE"] = 197] = "MAX_VALUE";
429
440
  /* eslint-enable @typescript-eslint/naming-convention */
430
441
  })(Action || (Action = {}));
431
442
  export var PanelCodes;
@@ -701,8 +712,6 @@ export var DevtoolsExperiments;
701
712
  DevtoolsExperiments[DevtoolsExperiments["just-my-code"] = 65] = "just-my-code";
702
713
  DevtoolsExperiments[DevtoolsExperiments["use-source-map-scopes"] = 76] = "use-source-map-scopes";
703
714
  DevtoolsExperiments[DevtoolsExperiments["timeline-show-postmessage-events"] = 86] = "timeline-show-postmessage-events";
704
- DevtoolsExperiments[DevtoolsExperiments["timeline-enhanced-traces"] = 90] = "timeline-enhanced-traces";
705
- DevtoolsExperiments[DevtoolsExperiments["timeline-compiled-sources"] = 91] = "timeline-compiled-sources";
706
715
  DevtoolsExperiments[DevtoolsExperiments["timeline-debug-mode"] = 93] = "timeline-debug-mode";
707
716
  /* eslint-enable @typescript-eslint/naming-convention */
708
717
  // Increment this when new experiments are added.