@mcp-b/chrome-devtools-mcp 2.3.0 → 2.3.1-beta.20260528050333

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 (67) hide show
  1. package/package.json +1 -1
  2. package/build/src/DevToolsConnectionAdapter.js +0 -70
  3. package/build/src/DevtoolsUtils.js +0 -290
  4. package/build/src/McpContext.js +0 -687
  5. package/build/src/McpPage.js +0 -95
  6. package/build/src/McpResponse.js +0 -588
  7. package/build/src/Mutex.js +0 -37
  8. package/build/src/PageCollector.js +0 -308
  9. package/build/src/SlimMcpResponse.js +0 -18
  10. package/build/src/WaitForHelper.js +0 -135
  11. package/build/src/bin/chrome-devtools-cli-options.js +0 -651
  12. package/build/src/bin/chrome-devtools-mcp-cli-options.js +0 -317
  13. package/build/src/bin/chrome-devtools-mcp-main.js +0 -35
  14. package/build/src/bin/chrome-devtools-mcp.js +0 -21
  15. package/build/src/bin/chrome-devtools.js +0 -185
  16. package/build/src/bin/cliDefinitions.js +0 -615
  17. package/build/src/browser.js +0 -198
  18. package/build/src/daemon/client.js +0 -152
  19. package/build/src/daemon/daemon.js +0 -206
  20. package/build/src/daemon/types.js +0 -6
  21. package/build/src/daemon/utils.js +0 -108
  22. package/build/src/formatters/ConsoleFormatter.js +0 -234
  23. package/build/src/formatters/IssueFormatter.js +0 -192
  24. package/build/src/formatters/NetworkFormatter.js +0 -215
  25. package/build/src/formatters/SnapshotFormatter.js +0 -131
  26. package/build/src/index.js +0 -202
  27. package/build/src/issue-descriptions.js +0 -39
  28. package/build/src/logger.js +0 -36
  29. package/build/src/polyfill.js +0 -7
  30. package/build/src/telemetry/ClearcutLogger.js +0 -102
  31. package/build/src/telemetry/WatchdogClient.js +0 -60
  32. package/build/src/telemetry/flagUtils.js +0 -45
  33. package/build/src/telemetry/metricUtils.js +0 -14
  34. package/build/src/telemetry/persistence.js +0 -53
  35. package/build/src/telemetry/types.js +0 -33
  36. package/build/src/telemetry/watchdog/ClearcutSender.js +0 -203
  37. package/build/src/telemetry/watchdog/main.js +0 -127
  38. package/build/src/third_party/devtools-formatter-worker.js +0 -7
  39. package/build/src/third_party/index.js +0 -26
  40. package/build/src/third_party/lighthouse-devtools-mcp-bundle.js +0 -54183
  41. package/build/src/tools/ToolDefinition.js +0 -72
  42. package/build/src/tools/categories.js +0 -24
  43. package/build/src/tools/console.js +0 -85
  44. package/build/src/tools/emulation.js +0 -55
  45. package/build/src/tools/extensions.js +0 -96
  46. package/build/src/tools/input.js +0 -368
  47. package/build/src/tools/lighthouse.js +0 -123
  48. package/build/src/tools/memory.js +0 -28
  49. package/build/src/tools/network.js +0 -120
  50. package/build/src/tools/pages.js +0 -319
  51. package/build/src/tools/performance.js +0 -190
  52. package/build/src/tools/screencast.js +0 -79
  53. package/build/src/tools/screenshot.js +0 -84
  54. package/build/src/tools/script.js +0 -119
  55. package/build/src/tools/slim/tools.js +0 -81
  56. package/build/src/tools/snapshot.js +0 -56
  57. package/build/src/tools/tools.js +0 -52
  58. package/build/src/tools/webmcp.js +0 -416
  59. package/build/src/trace-processing/parse.js +0 -84
  60. package/build/src/types.js +0 -6
  61. package/build/src/utils/ExtensionRegistry.js +0 -35
  62. package/build/src/utils/files.js +0 -19
  63. package/build/src/utils/keyboard.js +0 -296
  64. package/build/src/utils/pagination.js +0 -49
  65. package/build/src/utils/string.js +0 -36
  66. package/build/src/utils/types.js +0 -6
  67. package/build/src/version.js +0 -9
@@ -1,95 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2025 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
- import { takeSnapshot } from './tools/snapshot.js';
7
- /**
8
- * Per-page state wrapper. Consolidates dialog, snapshot, emulation,
9
- * and metadata that were previously scattered across Maps in McpContext.
10
- *
11
- * Internal class consumed only by McpContext. Fields are public for direct
12
- * read/write access. The dialog field is private because it requires an
13
- * event listener lifecycle managed by the constructor/dispose pair.
14
- */
15
- export class McpPage {
16
- pptrPage;
17
- id;
18
- // Snapshot
19
- textSnapshot = null;
20
- uniqueBackendNodeIdToMcpId = new Map();
21
- // Emulation
22
- emulationSettings = {};
23
- // Metadata
24
- isolatedContextName;
25
- devToolsPage;
26
- // Dialog
27
- #dialog;
28
- #dialogHandler;
29
- constructor(page, id) {
30
- this.pptrPage = page;
31
- this.id = id;
32
- this.#dialogHandler = (dialog) => {
33
- this.#dialog = dialog;
34
- };
35
- page.on('dialog', this.#dialogHandler);
36
- }
37
- get dialog() {
38
- return this.#dialog;
39
- }
40
- getDialog() {
41
- return this.dialog;
42
- }
43
- clearDialog() {
44
- this.#dialog = undefined;
45
- }
46
- get networkConditions() {
47
- return this.emulationSettings.networkConditions ?? null;
48
- }
49
- get cpuThrottlingRate() {
50
- return this.emulationSettings.cpuThrottlingRate ?? 1;
51
- }
52
- get geolocation() {
53
- return this.emulationSettings.geolocation ?? null;
54
- }
55
- get viewport() {
56
- return this.emulationSettings.viewport ?? null;
57
- }
58
- get userAgent() {
59
- return this.emulationSettings.userAgent ?? null;
60
- }
61
- get colorScheme() {
62
- return this.emulationSettings.colorScheme ?? null;
63
- }
64
- dispose() {
65
- this.pptrPage.off('dialog', this.#dialogHandler);
66
- }
67
- async getElementByUid(uid) {
68
- if (!this.textSnapshot) {
69
- throw new Error(`No snapshot found for page ${this.id ?? '?'}. Use ${takeSnapshot.name} to capture one.`);
70
- }
71
- const node = this.textSnapshot.idToNode.get(uid);
72
- if (!node) {
73
- throw new Error(`Element uid "${uid}" not found on page ${this.id}.`);
74
- }
75
- return this.#resolveElementHandle(node, uid);
76
- }
77
- async #resolveElementHandle(node, uid) {
78
- const message = `Element with uid ${uid} no longer exists on the page.`;
79
- try {
80
- const handle = await node.elementHandle();
81
- if (!handle) {
82
- throw new Error(message);
83
- }
84
- return handle;
85
- }
86
- catch (error) {
87
- throw new Error(message, {
88
- cause: error,
89
- });
90
- }
91
- }
92
- getAXNodeByUid(uid) {
93
- return this.textSnapshot?.idToNode.get(uid);
94
- }
95
- }
@@ -1,588 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2025 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
- import { ConsoleFormatter } from './formatters/consoleFormatter.js';
7
- import { IssueFormatter } from './formatters/IssueFormatter.js';
8
- import { NetworkFormatter } from './formatters/networkFormatter.js';
9
- import { SnapshotFormatter } from './formatters/snapshotFormatter.js';
10
- import { UncaughtError } from './PageCollector.js';
11
- import { DevTools } from './third_party/index.js';
12
- import { handleDialog } from './tools/pages.js';
13
- import { getInsightOutput, getTraceSummary } from './trace-processing/parse.js';
14
- import { paginate } from './utils/pagination.js';
15
- export class McpResponse {
16
- #includePages = false;
17
- #includeExtensionServiceWorkers = false;
18
- #includeExtensionPages = false;
19
- #snapshotParams;
20
- #attachedNetworkRequestId;
21
- #attachedNetworkRequestOptions;
22
- #attachedConsoleMessageId;
23
- #attachedTraceSummary;
24
- #attachedTraceInsight;
25
- #attachedLighthouseResult;
26
- #textResponseLines = [];
27
- #images = [];
28
- #networkRequestsOptions;
29
- #consoleDataOptions;
30
- #listExtensions;
31
- #devToolsData;
32
- #tabId;
33
- #args;
34
- #page;
35
- constructor(args) {
36
- this.#args = args;
37
- }
38
- setPage(page) {
39
- this.#page = page;
40
- }
41
- attachDevToolsData(data) {
42
- this.#devToolsData = data;
43
- }
44
- setTabId(tabId) {
45
- this.#tabId = tabId;
46
- }
47
- setIncludePages(value) {
48
- this.#includePages = value;
49
- if (this.#args.categoryExtensions) {
50
- this.#includeExtensionServiceWorkers = value;
51
- this.#includeExtensionPages = value;
52
- }
53
- }
54
- includeSnapshot(params) {
55
- this.#snapshotParams = params ?? {
56
- verbose: false,
57
- };
58
- }
59
- setListExtensions() {
60
- this.#listExtensions = true;
61
- }
62
- setIncludeNetworkRequests(value, options) {
63
- if (!value) {
64
- this.#networkRequestsOptions = undefined;
65
- return;
66
- }
67
- this.#networkRequestsOptions = {
68
- include: value,
69
- pagination: options?.pageSize || options?.pageIdx
70
- ? {
71
- pageSize: options.pageSize,
72
- pageIdx: options.pageIdx,
73
- }
74
- : undefined,
75
- resourceTypes: options?.resourceTypes,
76
- includePreservedRequests: options?.includePreservedRequests,
77
- networkRequestIdInDevToolsUI: options?.networkRequestIdInDevToolsUI,
78
- };
79
- }
80
- setIncludeConsoleData(value, options) {
81
- if (!value) {
82
- this.#consoleDataOptions = undefined;
83
- return;
84
- }
85
- this.#consoleDataOptions = {
86
- include: value,
87
- pagination: options?.pageSize || options?.pageIdx
88
- ? {
89
- pageSize: options.pageSize,
90
- pageIdx: options.pageIdx,
91
- }
92
- : undefined,
93
- types: options?.types,
94
- includePreservedMessages: options?.includePreservedMessages,
95
- };
96
- }
97
- attachNetworkRequest(reqid, options) {
98
- this.#attachedNetworkRequestId = reqid;
99
- this.#attachedNetworkRequestOptions = options;
100
- }
101
- attachConsoleMessage(msgid) {
102
- this.#attachedConsoleMessageId = msgid;
103
- }
104
- attachTraceSummary(result) {
105
- this.#attachedTraceSummary = result;
106
- }
107
- attachTraceInsight(trace, insightSetId, insightName) {
108
- this.#attachedTraceInsight = {
109
- trace,
110
- insightSetId,
111
- insightName,
112
- };
113
- }
114
- attachLighthouseResult(result) {
115
- this.#attachedLighthouseResult = result;
116
- }
117
- get includePages() {
118
- return this.#includePages;
119
- }
120
- get attachedTraceSummary() {
121
- return this.#attachedTraceSummary;
122
- }
123
- get attachedTracedInsight() {
124
- return this.#attachedTraceInsight;
125
- }
126
- get attachedLighthouseResult() {
127
- return this.#attachedLighthouseResult;
128
- }
129
- get includeNetworkRequests() {
130
- return this.#networkRequestsOptions?.include ?? false;
131
- }
132
- get includeConsoleData() {
133
- return this.#consoleDataOptions?.include ?? false;
134
- }
135
- get attachedNetworkRequestId() {
136
- return this.#attachedNetworkRequestId;
137
- }
138
- get networkRequestsPageIdx() {
139
- return this.#networkRequestsOptions?.pagination?.pageIdx;
140
- }
141
- get consoleMessagesPageIdx() {
142
- return this.#consoleDataOptions?.pagination?.pageIdx;
143
- }
144
- get consoleMessagesTypes() {
145
- return this.#consoleDataOptions?.types;
146
- }
147
- appendResponseLine(value) {
148
- this.#textResponseLines.push(value);
149
- }
150
- attachImage(value) {
151
- this.#images.push(value);
152
- }
153
- get responseLines() {
154
- return this.#textResponseLines;
155
- }
156
- get images() {
157
- return this.#images;
158
- }
159
- get snapshotParams() {
160
- return this.#snapshotParams;
161
- }
162
- async handle(toolName, context) {
163
- if (this.#includePages) {
164
- await context.createPagesSnapshot();
165
- }
166
- if (this.#includeExtensionServiceWorkers) {
167
- await context.createExtensionServiceWorkersSnapshot();
168
- }
169
- let snapshot;
170
- if (this.#snapshotParams) {
171
- if (!this.#page) {
172
- throw new Error('Response must have a page');
173
- }
174
- await context.createTextSnapshot(this.#page, this.#snapshotParams.verbose, this.#devToolsData);
175
- const textSnapshot = this.#page.textSnapshot;
176
- if (textSnapshot) {
177
- const formatter = new SnapshotFormatter(textSnapshot);
178
- if (this.#snapshotParams.filePath) {
179
- await context.saveFile(new TextEncoder().encode(formatter.toString()), this.#snapshotParams.filePath);
180
- snapshot = this.#snapshotParams.filePath;
181
- }
182
- else {
183
- snapshot = formatter;
184
- }
185
- }
186
- }
187
- let detailedNetworkRequest;
188
- if (this.#attachedNetworkRequestId) {
189
- if (!this.#page) {
190
- throw new Error(`Response must have an McpPage`);
191
- }
192
- const request = context.getNetworkRequestById(this.#page, this.#attachedNetworkRequestId);
193
- const formatter = await NetworkFormatter.from(request, {
194
- requestId: this.#attachedNetworkRequestId,
195
- requestIdResolver: (req) => context.getNetworkRequestStableId(req),
196
- fetchData: true,
197
- requestFilePath: this.#attachedNetworkRequestOptions?.requestFilePath,
198
- responseFilePath: this.#attachedNetworkRequestOptions?.responseFilePath,
199
- saveFile: (data, filename) => context.saveFile(data, filename),
200
- });
201
- detailedNetworkRequest = formatter;
202
- }
203
- let detailedConsoleMessage;
204
- if (this.#attachedConsoleMessageId) {
205
- if (!this.#page) {
206
- throw new Error(`Response must have an McpPage`);
207
- }
208
- const message = context.getConsoleMessageById(this.#page, this.#attachedConsoleMessageId);
209
- const consoleMessageStableId = this.#attachedConsoleMessageId;
210
- if ('args' in message || message instanceof UncaughtError) {
211
- const consoleMessage = message;
212
- const devTools = context.getDevToolsUniverse(this.#page);
213
- detailedConsoleMessage = await ConsoleFormatter.from(consoleMessage, {
214
- id: consoleMessageStableId,
215
- fetchDetailedData: true,
216
- devTools: devTools ?? undefined,
217
- });
218
- }
219
- else if (message instanceof DevTools.AggregatedIssue) {
220
- const formatter = new IssueFormatter(message, {
221
- id: consoleMessageStableId,
222
- requestIdResolver: context.resolveCdpRequestId.bind(context, this.#page),
223
- elementIdResolver: context.resolveCdpElementId.bind(context, this.#page),
224
- });
225
- if (!formatter.isValid()) {
226
- throw new Error("Can't provide detals for the msgid " + consoleMessageStableId);
227
- }
228
- detailedConsoleMessage = formatter;
229
- }
230
- }
231
- let extensions;
232
- if (this.#listExtensions) {
233
- extensions = context.listExtensions();
234
- }
235
- let consoleMessages;
236
- if (this.#consoleDataOptions?.include) {
237
- if (!this.#page) {
238
- throw new Error(`Response must have an McpPage`);
239
- }
240
- const page = this.#page;
241
- let messages = context.getConsoleData(this.#page, this.#consoleDataOptions.includePreservedMessages);
242
- if (this.#consoleDataOptions.types?.length) {
243
- const normalizedTypes = new Set(this.#consoleDataOptions.types);
244
- messages = messages.filter((message) => {
245
- if ('type' in message) {
246
- return normalizedTypes.has(message.type());
247
- }
248
- if (message instanceof DevTools.AggregatedIssue) {
249
- return normalizedTypes.has('issue');
250
- }
251
- return normalizedTypes.has('error');
252
- });
253
- }
254
- consoleMessages = (await Promise.all(messages.map(async (item) => {
255
- const consoleMessageStableId = context.getConsoleMessageStableId(item);
256
- if ('args' in item || item instanceof UncaughtError) {
257
- const consoleMessage = item;
258
- const devTools = context.getDevToolsUniverse(page);
259
- return await ConsoleFormatter.from(consoleMessage, {
260
- id: consoleMessageStableId,
261
- fetchDetailedData: false,
262
- devTools: devTools ?? undefined,
263
- });
264
- }
265
- if (item instanceof DevTools.AggregatedIssue) {
266
- const formatter = new IssueFormatter(item, {
267
- id: consoleMessageStableId,
268
- });
269
- if (!formatter.isValid()) {
270
- return null;
271
- }
272
- return formatter;
273
- }
274
- return null;
275
- }))).filter((item) => item !== null);
276
- }
277
- let networkRequests;
278
- if (this.#networkRequestsOptions?.include) {
279
- if (!this.#page) {
280
- throw new Error(`Response must have an McpPage`);
281
- }
282
- let requests = context.getNetworkRequests(this.#page, this.#networkRequestsOptions?.includePreservedRequests);
283
- // Apply resource type filtering if specified
284
- if (this.#networkRequestsOptions.resourceTypes?.length) {
285
- const normalizedTypes = new Set(this.#networkRequestsOptions.resourceTypes);
286
- requests = requests.filter((request) => {
287
- const type = request.resourceType();
288
- return normalizedTypes.has(type);
289
- });
290
- }
291
- if (requests.length) {
292
- networkRequests = await Promise.all(requests.map((request) => NetworkFormatter.from(request, {
293
- requestId: context.getNetworkRequestStableId(request),
294
- selectedInDevToolsUI: context.getNetworkRequestStableId(request) ===
295
- this.#networkRequestsOptions?.networkRequestIdInDevToolsUI,
296
- fetchData: false,
297
- saveFile: (data, filename) => context.saveFile(data, filename),
298
- })));
299
- }
300
- }
301
- return this.format(toolName, context, {
302
- detailedConsoleMessage,
303
- consoleMessages,
304
- snapshot,
305
- detailedNetworkRequest,
306
- networkRequests,
307
- traceInsight: this.#attachedTraceInsight,
308
- traceSummary: this.#attachedTraceSummary,
309
- extensions,
310
- lighthouseResult: this.#attachedLighthouseResult,
311
- });
312
- }
313
- format(toolName, context, data) {
314
- const structuredContent = {};
315
- const response = [];
316
- if (this.#textResponseLines.length) {
317
- structuredContent.message = this.#textResponseLines.join('\n');
318
- response.push(...this.#textResponseLines);
319
- }
320
- const networkConditions = this.#page?.networkConditions;
321
- if (networkConditions) {
322
- const timeout = this.#page.pptrPage.getDefaultNavigationTimeout();
323
- response.push(`Emulating network conditions: ${networkConditions}`);
324
- response.push(`Default navigation timeout set to ${timeout} ms`);
325
- structuredContent.networkConditions = networkConditions;
326
- structuredContent.navigationTimeout = timeout;
327
- }
328
- const viewport = this.#page?.viewport;
329
- if (viewport) {
330
- response.push(`Emulating viewport: ${JSON.stringify(viewport)}`);
331
- structuredContent.viewport = viewport;
332
- }
333
- const userAgent = this.#page?.userAgent;
334
- if (userAgent) {
335
- response.push(`Emulating user agent: ${userAgent}`);
336
- structuredContent.userAgent = userAgent;
337
- }
338
- const cpuThrottlingRate = this.#page?.cpuThrottlingRate ?? 1;
339
- if (cpuThrottlingRate > 1) {
340
- response.push(`Emulating CPU throttling: ${cpuThrottlingRate}x slowdown`);
341
- structuredContent.cpuThrottlingRate = cpuThrottlingRate;
342
- }
343
- const colorScheme = this.#page?.colorScheme;
344
- if (colorScheme) {
345
- response.push(`Emulating color scheme: ${colorScheme}`);
346
- structuredContent.colorScheme = colorScheme;
347
- }
348
- const dialog = this.#page?.getDialog();
349
- if (dialog) {
350
- const defaultValueIfNeeded = dialog.type() === 'prompt' ? ` (default value: "${dialog.defaultValue()}")` : '';
351
- response.push(`# Open dialog
352
- ${dialog.type()}: ${dialog.message()}${defaultValueIfNeeded}.
353
- Call ${handleDialog.name} to handle it before continuing.`);
354
- structuredContent.dialog = {
355
- type: dialog.type(),
356
- message: dialog.message(),
357
- defaultValue: dialog.defaultValue(),
358
- };
359
- }
360
- if (this.#includePages) {
361
- const allPages = context.getPages();
362
- const { regularPages, extensionPages } = allPages.reduce((acc, page) => {
363
- if (page.url().startsWith('chrome-extension://')) {
364
- acc.extensionPages.push(page);
365
- }
366
- else {
367
- acc.regularPages.push(page);
368
- }
369
- return acc;
370
- }, { regularPages: [], extensionPages: [] });
371
- if (regularPages.length) {
372
- const parts = [`## Pages`];
373
- const structuredPages = [];
374
- for (const page of regularPages) {
375
- const isolatedContextName = context.getIsolatedContextName(page);
376
- const contextLabel = isolatedContextName ? ` isolatedContext=${isolatedContextName}` : '';
377
- parts.push(`${context.getPageId(page)}: ${page.url()}${context.isPageSelected(page) ? ' [selected]' : ''}${contextLabel}`);
378
- structuredPages.push(createStructuredPage(page, context));
379
- }
380
- response.push(...parts);
381
- structuredContent.pages = structuredPages;
382
- }
383
- if (this.#includeExtensionPages) {
384
- if (extensionPages.length) {
385
- response.push(`## Extension Pages`);
386
- const structuredExtensionPages = [];
387
- for (const page of extensionPages) {
388
- const isolatedContextName = context.getIsolatedContextName(page);
389
- const contextLabel = isolatedContextName
390
- ? ` isolatedContext=${isolatedContextName}`
391
- : '';
392
- response.push(`${context.getPageId(page)}: ${page.url()}${context.isPageSelected(page) ? ' [selected]' : ''}${contextLabel}`);
393
- structuredExtensionPages.push(createStructuredPage(page, context));
394
- }
395
- structuredContent.extensionPages = structuredExtensionPages;
396
- }
397
- }
398
- }
399
- if (this.#includeExtensionServiceWorkers) {
400
- if (context.getExtensionServiceWorkers().length) {
401
- response.push(`## Extension Service Workers`);
402
- }
403
- for (const extensionServiceWorker of context.getExtensionServiceWorkers()) {
404
- response.push(`${extensionServiceWorker.id}: ${extensionServiceWorker.url}`);
405
- }
406
- structuredContent.extensionServiceWorkers = context
407
- .getExtensionServiceWorkers()
408
- .map((extensionServiceWorker) => {
409
- return {
410
- id: extensionServiceWorker.id,
411
- url: extensionServiceWorker.url,
412
- };
413
- });
414
- }
415
- if (this.#tabId) {
416
- structuredContent.tabId = this.#tabId;
417
- }
418
- if (data.traceSummary) {
419
- const summary = getTraceSummary(data.traceSummary);
420
- response.push(summary);
421
- structuredContent.traceSummary = summary;
422
- structuredContent.traceInsights = [];
423
- for (const insightSet of data.traceSummary.insights?.values() ?? []) {
424
- for (const [insightName, model] of Object.entries(insightSet.model)) {
425
- structuredContent.traceInsights.push({
426
- insightName,
427
- insightKey: model.insightKey,
428
- });
429
- }
430
- }
431
- }
432
- if (data.traceInsight) {
433
- const insightOutput = getInsightOutput(data.traceInsight.trace, data.traceInsight.insightSetId, data.traceInsight.insightName);
434
- if ('error' in insightOutput) {
435
- response.push(insightOutput.error);
436
- }
437
- else {
438
- response.push(insightOutput.output);
439
- }
440
- }
441
- if (data.lighthouseResult) {
442
- structuredContent.lighthouseResult = data.lighthouseResult;
443
- const { summary, reports } = data.lighthouseResult;
444
- response.push('## Lighthouse Audit Results');
445
- response.push(`Mode: ${summary.mode}`);
446
- response.push(`Device: ${summary.device}`);
447
- response.push(`URL: ${summary.url}`);
448
- response.push('### Category Scores');
449
- for (const score of summary.scores) {
450
- response.push(`- ${score.title}: ${(score.score ?? 0) * 100} (${score.id})`);
451
- }
452
- response.push('### Audit Summary');
453
- response.push(`Passed: ${summary.audits.passed}`);
454
- response.push(`Failed: ${summary.audits.failed}`);
455
- response.push(`Total Timing: ${summary.timing.total}ms`);
456
- response.push('### Reports');
457
- for (const report of reports) {
458
- response.push(`- ${report}`);
459
- }
460
- }
461
- if (data.snapshot) {
462
- if (typeof data.snapshot === 'string') {
463
- response.push(`Saved snapshot to ${data.snapshot}.`);
464
- structuredContent.snapshotFilePath = data.snapshot;
465
- }
466
- else {
467
- response.push('## Latest page snapshot');
468
- response.push(data.snapshot.toString());
469
- structuredContent.snapshot = data.snapshot.toJSON();
470
- }
471
- }
472
- if (data.detailedNetworkRequest) {
473
- response.push(data.detailedNetworkRequest.toStringDetailed());
474
- structuredContent.networkRequest = data.detailedNetworkRequest.toJSONDetailed();
475
- }
476
- if (data.detailedConsoleMessage) {
477
- response.push(data.detailedConsoleMessage.toStringDetailed());
478
- structuredContent.consoleMessage = data.detailedConsoleMessage.toJSONDetailed();
479
- }
480
- if (data.extensions) {
481
- structuredContent.extensions = data.extensions;
482
- response.push('## Extensions');
483
- if (data.extensions.length === 0) {
484
- response.push('No extensions installed.');
485
- }
486
- else {
487
- const extensionsMessage = data.extensions
488
- .map((extension) => {
489
- return `id=${extension.id} "${extension.name}" v${extension.version} ${extension.isEnabled ? 'Enabled' : 'Disabled'}`;
490
- })
491
- .join('\n');
492
- response.push(extensionsMessage);
493
- }
494
- }
495
- if (this.#networkRequestsOptions?.include && data.networkRequests) {
496
- const requests = data.networkRequests;
497
- response.push('## Network requests');
498
- if (requests.length) {
499
- const paginationData = this.#dataWithPagination(requests, this.#networkRequestsOptions.pagination);
500
- structuredContent.pagination = paginationData.pagination;
501
- response.push(...paginationData.info);
502
- if (data.networkRequests) {
503
- structuredContent.networkRequests = [];
504
- for (const formatter of paginationData.items) {
505
- response.push(formatter.toString());
506
- structuredContent.networkRequests.push(formatter.toJSON());
507
- }
508
- }
509
- }
510
- else {
511
- response.push('No requests found.');
512
- }
513
- }
514
- if (this.#consoleDataOptions?.include) {
515
- const messages = data.consoleMessages ?? [];
516
- response.push('## Console messages');
517
- if (messages.length) {
518
- const paginationData = this.#dataWithPagination(messages, this.#consoleDataOptions.pagination);
519
- structuredContent.pagination = paginationData.pagination;
520
- response.push(...paginationData.info);
521
- response.push(...paginationData.items.map((message) => message.toString()));
522
- structuredContent.consoleMessages = paginationData.items.map((message) => message.toJSON());
523
- }
524
- else {
525
- response.push('<no console messages found>');
526
- }
527
- }
528
- const text = {
529
- type: 'text',
530
- text: response.join('\n'),
531
- };
532
- const images = this.#images.map((imageData) => {
533
- return {
534
- type: 'image',
535
- ...imageData,
536
- };
537
- });
538
- return {
539
- content: [text, ...images],
540
- structuredContent,
541
- };
542
- }
543
- #dataWithPagination(data, pagination) {
544
- const response = [];
545
- const paginationResult = paginate(data, pagination);
546
- if (paginationResult.invalidPage) {
547
- response.push('Invalid page number provided. Showing first page.');
548
- }
549
- const { startIndex, endIndex, currentPage, totalPages } = paginationResult;
550
- response.push(`Showing ${startIndex + 1}-${endIndex} of ${data.length} (Page ${currentPage + 1} of ${totalPages}).`);
551
- if (pagination) {
552
- if (paginationResult.hasNextPage) {
553
- response.push(`Next page: ${currentPage + 1}`);
554
- }
555
- if (paginationResult.hasPreviousPage) {
556
- response.push(`Previous page: ${currentPage - 1}`);
557
- }
558
- }
559
- return {
560
- info: response,
561
- items: paginationResult.items,
562
- pagination: {
563
- currentPage: paginationResult.currentPage,
564
- totalPages: paginationResult.totalPages,
565
- hasNextPage: paginationResult.hasNextPage,
566
- hasPreviousPage: paginationResult.hasPreviousPage,
567
- startIndex: paginationResult.startIndex,
568
- endIndex: paginationResult.endIndex,
569
- invalidPage: paginationResult.invalidPage,
570
- },
571
- };
572
- }
573
- resetResponseLineForTesting() {
574
- this.#textResponseLines = [];
575
- }
576
- }
577
- function createStructuredPage(page, context) {
578
- const isolatedContextName = context.getIsolatedContextName(page);
579
- const entry = {
580
- id: context.getPageId(page),
581
- url: page.url(),
582
- selected: context.isPageSelected(page),
583
- };
584
- if (isolatedContextName) {
585
- entry.isolatedContext = isolatedContextName;
586
- }
587
- return entry;
588
- }