@mcp-b/chrome-devtools-mcp 2.3.1 → 3.0.0-beta.20260529000441
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.
- package/package.json +1 -1
- package/build/src/DevToolsConnectionAdapter.js +0 -70
- package/build/src/DevtoolsUtils.js +0 -290
- package/build/src/McpContext.js +0 -687
- package/build/src/McpPage.js +0 -95
- package/build/src/McpResponse.js +0 -588
- package/build/src/Mutex.js +0 -37
- package/build/src/PageCollector.js +0 -308
- package/build/src/SlimMcpResponse.js +0 -18
- package/build/src/WaitForHelper.js +0 -135
- package/build/src/bin/chrome-devtools-cli-options.js +0 -651
- package/build/src/bin/chrome-devtools-mcp-cli-options.js +0 -317
- package/build/src/bin/chrome-devtools-mcp-main.js +0 -35
- package/build/src/bin/chrome-devtools-mcp.js +0 -21
- package/build/src/bin/chrome-devtools.js +0 -185
- package/build/src/bin/cliDefinitions.js +0 -615
- package/build/src/browser.js +0 -198
- package/build/src/daemon/client.js +0 -152
- package/build/src/daemon/daemon.js +0 -206
- package/build/src/daemon/types.js +0 -6
- package/build/src/daemon/utils.js +0 -108
- package/build/src/formatters/ConsoleFormatter.js +0 -234
- package/build/src/formatters/IssueFormatter.js +0 -192
- package/build/src/formatters/NetworkFormatter.js +0 -215
- package/build/src/formatters/SnapshotFormatter.js +0 -131
- package/build/src/index.js +0 -202
- package/build/src/issue-descriptions.js +0 -39
- package/build/src/logger.js +0 -36
- package/build/src/polyfill.js +0 -7
- package/build/src/telemetry/ClearcutLogger.js +0 -102
- package/build/src/telemetry/WatchdogClient.js +0 -60
- package/build/src/telemetry/flagUtils.js +0 -45
- package/build/src/telemetry/metricUtils.js +0 -14
- package/build/src/telemetry/persistence.js +0 -53
- package/build/src/telemetry/types.js +0 -33
- package/build/src/telemetry/watchdog/ClearcutSender.js +0 -203
- package/build/src/telemetry/watchdog/main.js +0 -127
- package/build/src/third_party/devtools-formatter-worker.js +0 -7
- package/build/src/third_party/index.js +0 -26
- package/build/src/third_party/lighthouse-devtools-mcp-bundle.js +0 -54183
- package/build/src/tools/ToolDefinition.js +0 -72
- package/build/src/tools/categories.js +0 -24
- package/build/src/tools/console.js +0 -85
- package/build/src/tools/emulation.js +0 -55
- package/build/src/tools/extensions.js +0 -96
- package/build/src/tools/input.js +0 -368
- package/build/src/tools/lighthouse.js +0 -123
- package/build/src/tools/memory.js +0 -28
- package/build/src/tools/network.js +0 -120
- package/build/src/tools/pages.js +0 -319
- package/build/src/tools/performance.js +0 -190
- package/build/src/tools/screencast.js +0 -79
- package/build/src/tools/screenshot.js +0 -84
- package/build/src/tools/script.js +0 -119
- package/build/src/tools/slim/tools.js +0 -81
- package/build/src/tools/snapshot.js +0 -56
- package/build/src/tools/tools.js +0 -52
- package/build/src/tools/webmcp.js +0 -416
- package/build/src/trace-processing/parse.js +0 -84
- package/build/src/types.js +0 -6
- package/build/src/utils/ExtensionRegistry.js +0 -35
- package/build/src/utils/files.js +0 -19
- package/build/src/utils/keyboard.js +0 -296
- package/build/src/utils/pagination.js +0 -49
- package/build/src/utils/string.js +0 -36
- package/build/src/utils/types.js +0 -6
- package/build/src/version.js +0 -9
package/build/src/McpPage.js
DELETED
|
@@ -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
|
-
}
|
package/build/src/McpResponse.js
DELETED
|
@@ -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
|
-
}
|