chrome-devtools-frontend 1.0.1605219 → 1.0.1606789
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/front_end/Images/src/dots-circle.svg +10 -0
- package/front_end/core/host/UserMetrics.ts +0 -1
- package/front_end/core/platform/api/HostRuntime.ts +9 -6
- package/front_end/core/platform/browser/HostRuntime.ts +2 -2
- package/front_end/core/platform/node/HostRuntime.ts +7 -7
- package/front_end/core/protocol_client/InspectorBackend.ts +4 -0
- package/front_end/core/root/ExperimentNames.ts +0 -1
- package/front_end/core/sdk/CrashReportContextModel.ts +28 -0
- package/front_end/core/sdk/sdk.ts +2 -2
- package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshotWorkerDispatcher.ts +3 -3
- package/front_end/entrypoints/heap_snapshot_worker/heap_snapshot_worker-entrypoint.ts +5 -4
- package/front_end/entrypoints/main/MainImpl.ts +0 -101
- package/front_end/models/ai_assistance/ChangeManager.ts +6 -6
- package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +112 -5
- package/front_end/models/ai_assistance/agents/AiAgent.ts +9 -25
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.snapshot.txt +2 -2
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +6 -3
- package/front_end/models/ai_assistance/agents/ConversationSummaryAgent.ts +10 -9
- package/front_end/models/ai_assistance/agents/ExecuteJavascript.ts +313 -0
- package/front_end/models/ai_assistance/agents/FileAgent.ts +15 -1
- package/front_end/models/ai_assistance/agents/NetworkAgent.ts +15 -1
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +19 -8
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +35 -278
- package/front_end/models/ai_assistance/ai_assistance.ts +0 -2
- package/front_end/models/javascript_metadata/NativeFunctions.js +1 -5
- package/front_end/models/web_mcp/WebMCPModel.ts +187 -0
- package/front_end/models/web_mcp/web_mcp.ts +9 -0
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +8 -1
- package/front_end/panels/ai_assistance/ai_assistance.ts +1 -0
- package/front_end/panels/ai_assistance/components/AccessibilityAgentMarkdownRenderer.ts +88 -0
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +149 -49
- package/front_end/panels/ai_assistance/components/ChatView.ts +11 -15
- package/front_end/panels/ai_assistance/components/ExportForAgentsDialog.ts +13 -4
- package/front_end/panels/ai_assistance/components/chatMessage.css +53 -1
- package/front_end/panels/ai_assistance/components/chatView.css +0 -10
- package/front_end/panels/ai_assistance/components/exportForAgentsDialog.css +13 -0
- package/front_end/panels/application/WebMCPView.ts +471 -25
- package/front_end/panels/application/webMCPView.css +53 -2
- package/front_end/panels/elements/ElementsTreeElement.ts +1 -1
- package/front_end/panels/elements/ElementsTreeOutline.ts +87 -0
- package/front_end/panels/elements/StylePropertiesSection.ts +0 -4
- package/front_end/panels/elements/elements.ts +3 -0
- package/front_end/panels/elements/elementsTreeOutline.css +21 -0
- package/front_end/panels/elements/stylePropertiesTreeOutline.css +7 -0
- package/front_end/panels/lighthouse/LighthousePanel.ts +7 -1
- package/front_end/panels/lighthouse/LighthouseProtocolService.ts +25 -2
- package/front_end/panels/profiler/HeapDetachedElementsView.ts +0 -4
- package/front_end/panels/profiler/HeapProfileView.ts +0 -4
- package/front_end/panels/profiler/HeapProfilerPanel.ts +4 -13
- package/front_end/panels/profiler/HeapSnapshotProxy.ts +2 -6
- package/front_end/panels/profiler/HeapSnapshotView.ts +19 -32
- package/front_end/panels/profiler/ProfileHeader.ts +1 -15
- package/front_end/panels/profiler/ProfileTypeRegistry.ts +4 -12
- package/front_end/panels/profiler/ProfileView.ts +1 -6
- package/front_end/panels/profiler/ProfilesPanel.ts +60 -7
- package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +27 -22
- package/front_end/panels/timeline/EventsTimelineTreeView.ts +1 -1
- package/front_end/panels/timeline/ThirdPartyTreeView.ts +2 -2
- package/front_end/panels/timeline/TimelinePanel.ts +11 -153
- package/front_end/panels/timeline/TimelineTreeView.ts +147 -48
- package/front_end/panels/timeline/TimelineUIUtils.ts +2 -1
- package/front_end/panels/timeline/components/CWVMetrics.ts +18 -2
- package/front_end/panels/timeline/timeline-meta.ts +11 -0
- package/front_end/panels/timeline/utils/Helpers.ts +5 -0
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/components/markdown_view/CodeBlock.ts +47 -1
- package/front_end/ui/components/markdown_view/codeBlock.css +8 -0
- package/front_end/ui/legacy/FilterBar.ts +2 -0
- package/front_end/ui/legacy/SplitWidget.ts +33 -27
- package/front_end/ui/legacy/TabbedPane.ts +123 -3
- package/front_end/ui/legacy/Widget.ts +95 -48
- package/front_end/ui/legacy/components/source_frame/JSONView.ts +1 -1
- package/front_end/ui/legacy/components/utils/jsUtils.css +2 -0
- package/front_end/ui/legacy/infobar.css +1 -0
- package/front_end/ui/visual_logging/KnownContextValues.ts +6 -1
- package/package.json +1 -1
- package/front_end/core/sdk/WebMCPModel.ts +0 -104
- package/front_end/models/ai_assistance/ConversationHandler.ts +0 -325
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<g clip-path="url(#clip0_367_65863)">
|
|
3
|
+
<path d="M5.2 8.875C5.44306 8.875 5.64722 8.79236 5.8125 8.62708C5.9875 8.45208 6.075 8.24306 6.075 8C6.075 7.75694 5.9875 7.55278 5.8125 7.3875C5.64722 7.2125 5.44306 7.125 5.2 7.125C4.95694 7.125 4.74792 7.2125 4.57292 7.3875C4.40764 7.55278 4.325 7.75694 4.325 8C4.325 8.24306 4.40764 8.45208 4.57292 8.62708C4.74792 8.79236 4.95694 8.875 5.2 8.875ZM8 8.875C8.24306 8.875 8.44722 8.79236 8.6125 8.62708C8.7875 8.45208 8.875 8.24306 8.875 8C8.875 7.75694 8.7875 7.55278 8.6125 7.3875C8.44722 7.2125 8.24306 7.125 8 7.125C7.75694 7.125 7.54792 7.2125 7.37292 7.3875C7.20764 7.55278 7.125 7.75694 7.125 8C7.125 8.24306 7.20764 8.45208 7.37292 8.62708C7.54792 8.79236 7.75694 8.875 8 8.875ZM10.8 8.875C11.0431 8.875 11.2472 8.79236 11.4125 8.62708C11.5875 8.45208 11.675 8.24306 11.675 8C11.675 7.75694 11.5875 7.55278 11.4125 7.3875C11.2472 7.2125 11.0431 7.125 10.8 7.125C10.5569 7.125 10.3479 7.2125 10.1729 7.3875C10.0076 7.55278 9.925 7.75694 9.925 8C9.925 8.24306 10.0076 8.45208 10.1729 8.62708C10.3479 8.79236 10.5569 8.875 10.8 8.875ZM8 13.6C7.23194 13.6 6.50764 13.4542 5.82708 13.1625C5.14653 12.8708 4.54861 12.4722 4.03333 11.9667C3.52778 11.4514 3.12917 10.8535 2.8375 10.1729C2.54583 9.49236 2.4 8.76806 2.4 8C2.4 7.22222 2.54583 6.49792 2.8375 5.82708C3.12917 5.14653 3.52778 4.55347 4.03333 4.04792C4.54861 3.53264 5.14653 3.12917 5.82708 2.8375C6.50764 2.54583 7.23194 2.4 8 2.4C8.77778 2.4 9.50208 2.54583 10.1729 2.8375C10.8535 3.12917 11.4465 3.53264 11.9521 4.04792C12.4674 4.55347 12.8708 5.14653 13.1625 5.82708C13.4542 6.49792 13.6 7.22222 13.6 8C13.6 8.76806 13.4542 9.49236 13.1625 10.1729C12.8708 10.8535 12.4674 11.4514 11.9521 11.9667C11.4465 12.4722 10.8535 12.8708 10.1729 13.1625C9.50208 13.4542 8.77778 13.6 8 13.6ZM8 12.55C9.26389 12.55 10.3382 12.1076 11.2229 11.2229C12.1076 10.3382 12.55 9.26389 12.55 8C12.55 6.73611 12.1076 5.66181 11.2229 4.77708C10.3382 3.89236 9.26389 3.45 8 3.45C6.73611 3.45 5.66181 3.89236 4.77708 4.77708C3.89236 5.66181 3.45 6.73611 3.45 8C3.45 9.26389 3.89236 10.3382 4.77708 11.2229C5.66181 12.1076 6.73611 12.55 8 12.55Z" fill="#474747"/>
|
|
4
|
+
</g>
|
|
5
|
+
<defs>
|
|
6
|
+
<clipPath id="clip0_367_65863">
|
|
7
|
+
<rect width="16" height="16" fill="white"/>
|
|
8
|
+
</clipPath>
|
|
9
|
+
</defs>
|
|
10
|
+
</svg>
|
|
@@ -815,7 +815,6 @@ export enum DevtoolsExperiments {
|
|
|
815
815
|
'live-heap-profile' = 11,
|
|
816
816
|
'protocol-monitor' = 13,
|
|
817
817
|
'sampling-heap-profiler-timeline' = 17,
|
|
818
|
-
'show-option-to-expose-internals-in-heap-snapshot' = 18,
|
|
819
818
|
'timeline-invalidation-tracking' = 26,
|
|
820
819
|
'timeline-show-all-events' = 27,
|
|
821
820
|
apca = 39,
|
|
@@ -25,21 +25,24 @@ export interface Worker {
|
|
|
25
25
|
set onerror(listener: (event: any) => void);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
type WorkerMessagePort = typeof MessagePort.prototype;
|
|
29
|
+
|
|
28
30
|
/**
|
|
29
|
-
* Currently we
|
|
31
|
+
* Currently we only transfer MessagePorts to workers, but it's possible to add
|
|
30
32
|
* more things (like ReadableStream) as long as it's present in all runtimes.
|
|
31
33
|
*/
|
|
32
|
-
export type WorkerTransferable =
|
|
34
|
+
export type WorkerTransferable = WorkerMessagePort;
|
|
33
35
|
|
|
34
36
|
/**
|
|
35
37
|
* Used by workers to communicate with their parent.
|
|
36
38
|
*/
|
|
37
39
|
export interface WorkerScope {
|
|
38
40
|
postMessage(message: unknown): void;
|
|
39
|
-
set onmessage(listener: (event: WorkerMessageEvent) => void);
|
|
41
|
+
set onmessage(listener: (event: WorkerMessageEvent) => Promise<void>| void);
|
|
40
42
|
}
|
|
41
43
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
readonly data:
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
45
|
+
export interface WorkerMessageEvent<T = any> {
|
|
46
|
+
readonly data: T;
|
|
47
|
+
ports: readonly WorkerMessagePort[];
|
|
45
48
|
}
|
|
@@ -9,8 +9,8 @@ class WebWorkerScope implements Api.HostRuntime.WorkerScope {
|
|
|
9
9
|
self.postMessage(message);
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
set onmessage(listener: (event: Api.HostRuntime.WorkerMessageEvent) => void) {
|
|
13
|
-
self.
|
|
12
|
+
set onmessage(listener: (event: Api.HostRuntime.WorkerMessageEvent) => Promise<void>| void) {
|
|
13
|
+
self.addEventListener('message', listener);
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -12,8 +12,8 @@ class NodeWorkerScope implements Api.HostRuntime.WorkerScope {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
set onmessage(listener: (event: Api.HostRuntime.WorkerMessageEvent) => void) {
|
|
15
|
-
WorkerThreads.parentPort?.
|
|
16
|
-
listener(
|
|
15
|
+
WorkerThreads.parentPort?.addEventListener('message', msg => {
|
|
16
|
+
listener(msg as unknown as Api.HostRuntime.WorkerMessageEvent);
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
19
|
}
|
|
@@ -36,10 +36,10 @@ class NodeWorker implements Api.HostRuntime.Worker {
|
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
postMessage(message: unknown): void {
|
|
39
|
+
postMessage(message: unknown, transfer?: Api.HostRuntime.WorkerTransferable[]): void {
|
|
40
40
|
void this.#workerPromise.then(worker => {
|
|
41
41
|
if (!this.#disposed) {
|
|
42
|
-
worker.postMessage(message);
|
|
42
|
+
worker.postMessage(message, transfer);
|
|
43
43
|
}
|
|
44
44
|
});
|
|
45
45
|
}
|
|
@@ -56,11 +56,11 @@ class NodeWorker implements Api.HostRuntime.Worker {
|
|
|
56
56
|
this.dispose();
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
set onmessage(listener: (event:
|
|
59
|
+
set onmessage(listener: (event: Api.HostRuntime.WorkerMessageEvent) => void) {
|
|
60
60
|
void this.#workerPromise.then(worker => {
|
|
61
|
-
worker.on('message', data => {
|
|
61
|
+
worker.on('message', (data: unknown) => {
|
|
62
62
|
if (!this.#disposed) {
|
|
63
|
-
listener({data});
|
|
63
|
+
listener({data, ports: []});
|
|
64
64
|
}
|
|
65
65
|
});
|
|
66
66
|
});
|
|
@@ -351,6 +351,10 @@ export class TargetBase {
|
|
|
351
351
|
return this.getAgent('CacheStorage');
|
|
352
352
|
}
|
|
353
353
|
|
|
354
|
+
crashReportContextAgent(): ProtocolProxyApi.CrashReportContextApi {
|
|
355
|
+
return this.getAgent('CrashReportContext');
|
|
356
|
+
}
|
|
357
|
+
|
|
354
358
|
cssAgent(): ProtocolProxyApi.CSSApi {
|
|
355
359
|
return this.getAgent('CSS');
|
|
356
360
|
}
|
|
@@ -8,7 +8,6 @@ export enum ExperimentName {
|
|
|
8
8
|
LIVE_HEAP_PROFILE = 'live-heap-profile',
|
|
9
9
|
PROTOCOL_MONITOR = 'protocol-monitor',
|
|
10
10
|
SAMPLING_HEAP_PROFILER_TIMELINE = 'sampling-heap-profiler-timeline',
|
|
11
|
-
SHOW_OPTION_TO_EXPOSE_INTERNALS_IN_HEAP_SNAPSHOT = 'show-option-to-expose-internals-in-heap-snapshot',
|
|
12
11
|
TIMELINE_INVALIDATION_TRACKING = 'timeline-invalidation-tracking',
|
|
13
12
|
TIMELINE_SHOW_ALL_EVENTS = 'timeline-show-all-events',
|
|
14
13
|
APCA = 'apca',
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Copyright 2026 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
|
+
|
|
5
|
+
import type * as ProtocolProxyApi from '../../generated/protocol-proxy-api.js';
|
|
6
|
+
import type * as Protocol from '../../generated/protocol.js';
|
|
7
|
+
|
|
8
|
+
import {SDKModel} from './SDKModel.js';
|
|
9
|
+
import {Capability, type Target} from './Target.js';
|
|
10
|
+
|
|
11
|
+
export class CrashReportContextModel extends SDKModel<void> {
|
|
12
|
+
readonly #agent: ProtocolProxyApi.CrashReportContextApi;
|
|
13
|
+
|
|
14
|
+
constructor(target: Target) {
|
|
15
|
+
super(target);
|
|
16
|
+
this.#agent = target.crashReportContextAgent();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async getEntries(): Promise<Protocol.CrashReportContext.CrashReportContextEntry[]|null> {
|
|
20
|
+
const response = await this.#agent.invoke_getEntries();
|
|
21
|
+
if (response.getError()) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
return response.entries;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
SDKModel.register(CrashReportContextModel, {capabilities: Capability.JS, autostart: false});
|
|
@@ -22,6 +22,7 @@ import * as CookieModel from './CookieModel.js';
|
|
|
22
22
|
import * as CookieParser from './CookieParser.js';
|
|
23
23
|
import * as CPUProfilerModel from './CPUProfilerModel.js';
|
|
24
24
|
import * as CPUThrottlingManager from './CPUThrottlingManager.js';
|
|
25
|
+
import * as CrashReportContextModel from './CrashReportContextModel.js';
|
|
25
26
|
import * as CSSContainerQuery from './CSSContainerQuery.js';
|
|
26
27
|
import * as CSSFontFace from './CSSFontFace.js';
|
|
27
28
|
import * as CSSLayer from './CSSLayer.js';
|
|
@@ -90,7 +91,6 @@ import * as Target from './Target.js';
|
|
|
90
91
|
import * as TargetManager from './TargetManager.js';
|
|
91
92
|
import * as TraceObject from './TraceObject.js';
|
|
92
93
|
import * as WebAuthnModel from './WebAuthnModel.js';
|
|
93
|
-
import * as WebMCPModel from './WebMCPModel.js';
|
|
94
94
|
|
|
95
95
|
export {
|
|
96
96
|
AccessibilityModel,
|
|
@@ -106,6 +106,7 @@ export {
|
|
|
106
106
|
CookieParser,
|
|
107
107
|
CPUProfilerModel,
|
|
108
108
|
CPUThrottlingManager,
|
|
109
|
+
CrashReportContextModel,
|
|
109
110
|
CSSContainerQuery,
|
|
110
111
|
CSSFontFace,
|
|
111
112
|
CSSLayer,
|
|
@@ -174,5 +175,4 @@ export {
|
|
|
174
175
|
TargetManager,
|
|
175
176
|
TraceObject,
|
|
176
177
|
WebAuthnModel,
|
|
177
|
-
WebMCPModel,
|
|
178
178
|
};
|
|
@@ -2,6 +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
|
|
|
5
|
+
import type * as PlatformApi from '../../core/platform/api/api.js';
|
|
5
6
|
import * as HeapSnapshotModel from '../../models/heap_snapshot_model/heap_snapshot_model.js';
|
|
6
7
|
|
|
7
8
|
// We mirror what heap_snapshot_worker.ts does, but we can't use it here as we'd have a
|
|
@@ -33,9 +34,8 @@ export class HeapSnapshotWorkerDispatcher {
|
|
|
33
34
|
this.#postMessage({eventName: name, data});
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
async dispatchMessage({data, ports}:
|
|
37
|
-
|
|
38
|
-
Promise<void> {
|
|
37
|
+
async dispatchMessage({data, ports}: PlatformApi.HostRuntime
|
|
38
|
+
.WorkerMessageEvent<HeapSnapshotModel.HeapSnapshotModel.WorkerCommand>): Promise<void> {
|
|
39
39
|
const response: DispatcherResponse = {
|
|
40
40
|
callId: data.callId,
|
|
41
41
|
result: null,
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
// Copyright 2020 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
|
+
import * as Platform from '../../core/platform/platform.js';
|
|
4
5
|
|
|
5
6
|
import * as HeapSnapshotWorker from './heap_snapshot_worker.js';
|
|
6
7
|
|
|
7
|
-
const dispatcher =
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
const dispatcher = new HeapSnapshotWorker.HeapSnapshotWorkerDispatcher.HeapSnapshotWorkerDispatcher(
|
|
9
|
+
Platform.HostRuntime.HOST_RUNTIME.workerScope.postMessage.bind(Platform.HostRuntime.HOST_RUNTIME.workerScope));
|
|
10
|
+
Platform.HostRuntime.HOST_RUNTIME.workerScope.onmessage = dispatcher.dispatchMessage.bind(dispatcher);
|
|
11
|
+
Platform.HostRuntime.HOST_RUNTIME.workerScope.postMessage('workerReady');
|
|
@@ -121,10 +121,6 @@ const UIStrings = {
|
|
|
121
121
|
* @description Text describing how to navigate the dock side menu
|
|
122
122
|
*/
|
|
123
123
|
dockSideNavigation: 'Use left and right arrow keys to navigate the options',
|
|
124
|
-
/**
|
|
125
|
-
* @description Notification shown to the user whenever DevTools receives an external request.
|
|
126
|
-
*/
|
|
127
|
-
externalRequestReceived: '`DevTools` received an external request',
|
|
128
124
|
/**
|
|
129
125
|
* @description Notification shown to the user whenever DevTools has finished downloading a local AI model.
|
|
130
126
|
*/
|
|
@@ -360,9 +356,6 @@ export class MainImpl {
|
|
|
360
356
|
Root.ExperimentNames.ExperimentName.PROTOCOL_MONITOR, protocolMonitorExperiment);
|
|
361
357
|
Root.Runtime.experiments.register(
|
|
362
358
|
Root.ExperimentNames.ExperimentName.SAMPLING_HEAP_PROFILER_TIMELINE, 'Sampling heap profiler timeline');
|
|
363
|
-
Root.Runtime.experiments.register(
|
|
364
|
-
Root.ExperimentNames.ExperimentName.SHOW_OPTION_TO_EXPOSE_INTERNALS_IN_HEAP_SNAPSHOT,
|
|
365
|
-
'Show option to expose internals in heap snapshots');
|
|
366
359
|
|
|
367
360
|
// Timeline
|
|
368
361
|
Root.Runtime.experiments.register(
|
|
@@ -581,14 +574,6 @@ export class MainImpl {
|
|
|
581
574
|
});
|
|
582
575
|
}
|
|
583
576
|
|
|
584
|
-
const conversationHandler = AiAssistanceModel.ConversationHandler.ConversationHandler.instance();
|
|
585
|
-
conversationHandler.addEventListener(
|
|
586
|
-
AiAssistanceModel.ConversationHandler.ConversationHandlerEvents.EXTERNAL_REQUEST_RECEIVED,
|
|
587
|
-
() => Snackbar.Snackbar.Snackbar.show({message: i18nString(UIStrings.externalRequestReceived)}));
|
|
588
|
-
conversationHandler.addEventListener(
|
|
589
|
-
AiAssistanceModel.ConversationHandler.ConversationHandlerEvents.EXTERNAL_CONVERSATION_STARTED,
|
|
590
|
-
event => void VisualLogging.logFunctionCall(`start-conversation-${event.data}`, 'external'));
|
|
591
|
-
|
|
592
577
|
if (Root.Runtime.hostConfig.devToolsGeminiRebranding?.enabled) {
|
|
593
578
|
await PanelCommon.GeminiRebrandPromoDialog.maybeShow();
|
|
594
579
|
}
|
|
@@ -1104,89 +1089,3 @@ export class ReloadActionDelegate implements UI.ActionRegistration.ActionDelegat
|
|
|
1104
1089
|
return false;
|
|
1105
1090
|
}
|
|
1106
1091
|
}
|
|
1107
|
-
|
|
1108
|
-
type ExternalRequestInput = {
|
|
1109
|
-
kind: 'LIVE_STYLE_DEBUGGER',
|
|
1110
|
-
args: {prompt: string, selector: string},
|
|
1111
|
-
}|{
|
|
1112
|
-
kind: 'PERFORMANCE_RELOAD_GATHER_INSIGHTS',
|
|
1113
|
-
}|{
|
|
1114
|
-
kind: 'PERFORMANCE_ANALYZE',
|
|
1115
|
-
args: {prompt: string},
|
|
1116
|
-
}|{
|
|
1117
|
-
kind: 'NETWORK_DEBUGGER',
|
|
1118
|
-
args: {requestUrl: string, prompt: string},
|
|
1119
|
-
};
|
|
1120
|
-
|
|
1121
|
-
/**
|
|
1122
|
-
* For backwards-compatibility we iterate over the generator and drop the
|
|
1123
|
-
* intermediate results. The final response is transformed to its legacy type.
|
|
1124
|
-
* Instead of sending responses of type error, errors are throws.
|
|
1125
|
-
**/
|
|
1126
|
-
export async function handleExternalRequest(input: ExternalRequestInput):
|
|
1127
|
-
Promise<{response: string, devToolsLogs: object[]}> {
|
|
1128
|
-
const generator = await handleExternalRequestGenerator(input);
|
|
1129
|
-
let result: IteratorResult<
|
|
1130
|
-
AiAssistanceModel.AiAgent.ExternalRequestResponse, AiAssistanceModel.AiAgent.ExternalRequestResponse>;
|
|
1131
|
-
do {
|
|
1132
|
-
result = await generator.next();
|
|
1133
|
-
} while (!result.done);
|
|
1134
|
-
const response = result.value;
|
|
1135
|
-
if (response.type === AiAssistanceModel.AiAgent.ExternalRequestResponseType.ERROR) {
|
|
1136
|
-
throw new Error(response.message);
|
|
1137
|
-
}
|
|
1138
|
-
if (response.type === AiAssistanceModel.AiAgent.ExternalRequestResponseType.ANSWER) {
|
|
1139
|
-
return {
|
|
1140
|
-
response: response.message,
|
|
1141
|
-
devToolsLogs: response.devToolsLogs,
|
|
1142
|
-
};
|
|
1143
|
-
}
|
|
1144
|
-
throw new Error('Received no response of type answer or type error');
|
|
1145
|
-
}
|
|
1146
|
-
|
|
1147
|
-
// @ts-expect-error
|
|
1148
|
-
globalThis.handleExternalRequest = handleExternalRequest;
|
|
1149
|
-
|
|
1150
|
-
export async function handleExternalRequestGenerator(input: ExternalRequestInput): Promise<AsyncGenerator<
|
|
1151
|
-
AiAssistanceModel.AiAgent.ExternalRequestResponse, AiAssistanceModel.AiAgent.ExternalRequestResponse>> {
|
|
1152
|
-
switch (input.kind) {
|
|
1153
|
-
case 'PERFORMANCE_RELOAD_GATHER_INSIGHTS': {
|
|
1154
|
-
const TimelinePanel = await import('../../panels/timeline/timeline.js');
|
|
1155
|
-
return TimelinePanel.TimelinePanel.TimelinePanel.handleExternalRecordRequest();
|
|
1156
|
-
}
|
|
1157
|
-
case 'PERFORMANCE_ANALYZE': {
|
|
1158
|
-
const TimelinePanel = await import('../../panels/timeline/timeline.js');
|
|
1159
|
-
return await TimelinePanel.TimelinePanel.TimelinePanel.handleExternalAnalyzeRequest(input.args.prompt);
|
|
1160
|
-
}
|
|
1161
|
-
case 'NETWORK_DEBUGGER': {
|
|
1162
|
-
const AiAssistanceModel = await import('../../models/ai_assistance/ai_assistance.js');
|
|
1163
|
-
const conversationHandler = AiAssistanceModel.ConversationHandler.ConversationHandler.instance();
|
|
1164
|
-
return await conversationHandler.handleExternalRequest({
|
|
1165
|
-
conversationType: AiAssistanceModel.AiHistoryStorage.ConversationType.NETWORK,
|
|
1166
|
-
prompt: input.args.prompt,
|
|
1167
|
-
requestUrl: input.args.requestUrl,
|
|
1168
|
-
});
|
|
1169
|
-
}
|
|
1170
|
-
case 'LIVE_STYLE_DEBUGGER': {
|
|
1171
|
-
const AiAssistanceModel = await import('../../models/ai_assistance/ai_assistance.js');
|
|
1172
|
-
const conversationHandler = AiAssistanceModel.ConversationHandler.ConversationHandler.instance();
|
|
1173
|
-
return await conversationHandler.handleExternalRequest({
|
|
1174
|
-
conversationType: AiAssistanceModel.AiHistoryStorage.ConversationType.STYLING,
|
|
1175
|
-
prompt: input.args.prompt,
|
|
1176
|
-
selector: input.args.selector,
|
|
1177
|
-
});
|
|
1178
|
-
}
|
|
1179
|
-
}
|
|
1180
|
-
// eslint-disable-next-line require-yield
|
|
1181
|
-
return (async function*(): AsyncGenerator<
|
|
1182
|
-
AiAssistanceModel.AiAgent.ExternalRequestResponse, AiAssistanceModel.AiAgent.ExternalRequestResponse> {
|
|
1183
|
-
return {
|
|
1184
|
-
type: AiAssistanceModel.AiAgent.ExternalRequestResponseType.ERROR,
|
|
1185
|
-
// @ts-expect-error
|
|
1186
|
-
message: `Debugging with an agent of type '${input.kind}' is not implemented yet.`,
|
|
1187
|
-
};
|
|
1188
|
-
})();
|
|
1189
|
-
}
|
|
1190
|
-
|
|
1191
|
-
// @ts-expect-error
|
|
1192
|
-
globalThis.handleExternalRequestGenerator = handleExternalRequestGenerator;
|
|
@@ -117,11 +117,11 @@ export class ChangeManager {
|
|
|
117
117
|
return content;
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
formatChangesForPatching(groupId: string,
|
|
120
|
+
formatChangesForPatching(groupId: string, includeMetadata = false): string {
|
|
121
121
|
return Array.from(this.#stylesheetChanges.values())
|
|
122
122
|
.flatMap(
|
|
123
123
|
changesPerStylesheet => changesPerStylesheet.filter(change => change.groupId === groupId)
|
|
124
|
-
.map(change => this.#formatChange(change,
|
|
124
|
+
.map(change => this.#formatChange(change, includeMetadata)))
|
|
125
125
|
.filter(change => change !== '')
|
|
126
126
|
.join('\n\n');
|
|
127
127
|
}
|
|
@@ -150,13 +150,13 @@ ${formatStyles(change.styles, 4)}
|
|
|
150
150
|
.join('\n');
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
#formatChange(change: Change,
|
|
153
|
+
#formatChange(change: Change, includeMetadata = false): string {
|
|
154
154
|
const sourceLocation =
|
|
155
|
-
|
|
156
|
-
// TODO:
|
|
155
|
+
includeMetadata && change.sourceLocation ? `/* related resource: ${change.sourceLocation} */\n` : '';
|
|
156
|
+
// TODO: includeMetadata indicates whether we are using Patch
|
|
157
157
|
// agent. If needed we can have an separate knob.
|
|
158
158
|
const simpleSelector =
|
|
159
|
-
|
|
159
|
+
includeMetadata && change.simpleSelector ? ` /* the element was ${change.simpleSelector} */` : '';
|
|
160
160
|
return `${sourceLocation}${change.selector} {${simpleSelector}
|
|
161
161
|
${formatStyles(change.styles)}
|
|
162
162
|
}`;
|
|
@@ -7,18 +7,27 @@ import * as i18n from '../../../core/i18n/i18n.js';
|
|
|
7
7
|
import * as Root from '../../../core/root/root.js';
|
|
8
8
|
import * as SDK from '../../../core/sdk/sdk.js';
|
|
9
9
|
import type * as LHModel from '../../lighthouse/lighthouse.js';
|
|
10
|
+
import {ChangeManager} from '../ChangeManager.js';
|
|
10
11
|
import {LighthouseFormatter} from '../data_formatters/LighthouseFormatter.js';
|
|
11
12
|
import {debugLog} from '../debug.js';
|
|
13
|
+
import {ExtensionScope} from '../ExtensionScope.js';
|
|
12
14
|
|
|
13
15
|
import {
|
|
14
|
-
type AgentOptions,
|
|
15
16
|
AiAgent,
|
|
17
|
+
type AiWidget,
|
|
16
18
|
type ContextDetail,
|
|
17
19
|
type ContextResponse,
|
|
18
20
|
ConversationContext,
|
|
19
21
|
type RequestOptions,
|
|
20
22
|
ResponseType,
|
|
21
23
|
} from './AiAgent.js';
|
|
24
|
+
import {
|
|
25
|
+
type CreateExtensionScopeFunction,
|
|
26
|
+
executeJavaScriptFunction,
|
|
27
|
+
type ExecuteJsAgentOptions,
|
|
28
|
+
executeJsCode,
|
|
29
|
+
JavascriptExecutor
|
|
30
|
+
} from './ExecuteJavascript.js';
|
|
22
31
|
|
|
23
32
|
/**
|
|
24
33
|
* WARNING: preamble defined in code is only used when userTier is
|
|
@@ -29,7 +38,7 @@ const preamble = `You are an accessibility expert agent integrated into Chrome D
|
|
|
29
38
|
Your role is to help users understand and fix accessibility issues found in Lighthouse reports.
|
|
30
39
|
|
|
31
40
|
# Style Guidelines
|
|
32
|
-
* **
|
|
41
|
+
* **General style**: Use the precision of Strunk & White, the brevity of Hemingway, and the simple clarity of Vonnegut. Don't add repeated information, and keep the whole answer short.
|
|
33
42
|
* **Structured**: Organize your findings by problem, root cause, and next steps, but do NOT use those literal words as headings.
|
|
34
43
|
* **No Internal Identifiers**: NEVER show Lighthouse paths (e.g., "1,HTML,1,BODY...") to the user. Refer to elements by their tag name, classes, or IDs.
|
|
35
44
|
* **Managing Volume**: If the report contains many issues, provide a brief summary of the top 2-3 most critical ones. Tell the user that there are more issues and invite them to ask for more details or to explore a specific area.
|
|
@@ -45,10 +54,28 @@ Your role is to help users understand and fix accessibility issues found in Ligh
|
|
|
45
54
|
* \`runAccessibilityAudits\`: Trigger new accessibility snapshot audits.
|
|
46
55
|
* \`getStyles\`: Get computed styles for an element by its path.
|
|
47
56
|
* \`getElementAccessibilityDetails\`: Get A11y properties for an element by its path.
|
|
57
|
+
* \`executeJavaScript\`: Run JavaScript code on the inspected page to gather additional information or investigate the page state.
|
|
58
|
+
|
|
59
|
+
# Linkification
|
|
60
|
+
* **Linkify elements**: When you know the Lighthouse path of an element (found in the report audits), linkify it using \`([Label](#path-PATH))\` syntax. Never show the path to the user directly, only use it in the link href.
|
|
48
61
|
|
|
49
62
|
# Constraints
|
|
50
63
|
* **CRITICAL**: ALWAYS call a tool before providing an answer if an element path is available.
|
|
51
64
|
* **CRITICAL**: You are an accessibility agent. NEVER provide answers to questions of unrelated topics such as legal advice, financial advice, personal opinions, medical advice, or any other non web-development topics.
|
|
65
|
+
|
|
66
|
+
## Response Structure
|
|
67
|
+
|
|
68
|
+
If the user asks a question that requires an investigation of a problem, use this structure:
|
|
69
|
+
- If available, point out the root cause(s) of the problem.
|
|
70
|
+
- Example: "**Root Cause**: The page is slow because of [reason]."
|
|
71
|
+
- Example: "**Root Causes**:"
|
|
72
|
+
- [Reason 1]
|
|
73
|
+
- [Reason 2]
|
|
74
|
+
- if applicable, list actionable solution suggestion(s) in order of impact:
|
|
75
|
+
- Example: "**Suggestion**: [Suggestion 1]
|
|
76
|
+
- Example: "**Suggestions**:"
|
|
77
|
+
- [Suggestion 1]
|
|
78
|
+
- [Suggestion 2]
|
|
52
79
|
`;
|
|
53
80
|
|
|
54
81
|
export class AccessibilityContext extends ConversationContext<LHModel.ReporterTypes.ReportJSON> {
|
|
@@ -86,15 +113,40 @@ export class AccessibilityAgent extends AiAgent<LHModel.ReporterTypes.ReportJSON
|
|
|
86
113
|
readonly #lighthouseRecording?:
|
|
87
114
|
(overrides?: LHModel.RunTypes.RunOverrides) => Promise<LHModel.ReporterTypes.ReportJSON|null>;
|
|
88
115
|
|
|
89
|
-
|
|
116
|
+
#execJs: typeof executeJsCode;
|
|
117
|
+
#javascriptExecutor: JavascriptExecutor;
|
|
118
|
+
#changes: ChangeManager;
|
|
119
|
+
#createExtensionScope: CreateExtensionScopeFunction;
|
|
120
|
+
#currentTurnId = 0;
|
|
121
|
+
|
|
122
|
+
constructor(opts: ExecuteJsAgentOptions) {
|
|
90
123
|
super(opts);
|
|
91
124
|
this.#lighthouseRecording = opts.lighthouseRecording;
|
|
125
|
+
this.#changes = opts.changeManager || new ChangeManager();
|
|
126
|
+
this.#execJs = opts.execJs ?? executeJsCode;
|
|
127
|
+
this.#createExtensionScope =
|
|
128
|
+
opts.createExtensionScope ?? ((changes: ChangeManager) => {
|
|
129
|
+
return new ExtensionScope(changes, this.sessionId, this.#getDocumentBodyNode(), this.#currentTurnId);
|
|
130
|
+
});
|
|
131
|
+
this.#javascriptExecutor = new JavascriptExecutor(
|
|
132
|
+
{
|
|
133
|
+
executionMode: this.executionMode,
|
|
134
|
+
getContextNode: () => this.#getDocumentBodyNode(),
|
|
135
|
+
createExtensionScope: this.#createExtensionScope.bind(this),
|
|
136
|
+
changes: this.#changes,
|
|
137
|
+
},
|
|
138
|
+
this.#execJs);
|
|
92
139
|
}
|
|
93
140
|
|
|
94
141
|
get userTier(): string|undefined {
|
|
95
142
|
return Root.Runtime.hostConfig.devToolsFreestyler?.userTier;
|
|
96
143
|
}
|
|
97
144
|
|
|
145
|
+
get executionMode(): Root.Runtime.HostConfigFreestylerExecutionMode {
|
|
146
|
+
return Root.Runtime.hostConfig.devToolsFreestyler?.executionMode ??
|
|
147
|
+
Root.Runtime.HostConfigFreestylerExecutionMode.ALL_SCRIPTS;
|
|
148
|
+
}
|
|
149
|
+
|
|
98
150
|
get options(): RequestOptions {
|
|
99
151
|
// TODO(b/491772868): tidy up userTier & feature flags in the backend.
|
|
100
152
|
const temperature = Root.Runtime.hostConfig.devToolsAiAssistanceFileAgent?.temperature;
|
|
@@ -106,6 +158,38 @@ export class AccessibilityAgent extends AiAgent<LHModel.ReporterTypes.ReportJSON
|
|
|
106
158
|
};
|
|
107
159
|
}
|
|
108
160
|
|
|
161
|
+
override preambleFeatures(): string[] {
|
|
162
|
+
return ['function_calling'];
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
protected override async preRun(): Promise<void> {
|
|
166
|
+
this.#currentTurnId++;
|
|
167
|
+
const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
|
|
168
|
+
const domModel = target?.model(SDK.DOMModel.DOMModel);
|
|
169
|
+
// We need to ensure the document is requested so that #getDocumentBodyNode()
|
|
170
|
+
// can return a valid node for the JavaScript execution context.
|
|
171
|
+
if (domModel && !domModel.existingDocument()) {
|
|
172
|
+
try {
|
|
173
|
+
await domModel.requestDocument();
|
|
174
|
+
} catch (e) {
|
|
175
|
+
debugLog('Failed to request document', e);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* For the Accessibility Agent, there is no single "selected" node.
|
|
182
|
+
* We use the document body as the default context node for JavaScript execution
|
|
183
|
+
* so that the AI has a valid $0 to start with.
|
|
184
|
+
*/
|
|
185
|
+
#getDocumentBodyNode(): SDK.DOMModel.DOMNode|null {
|
|
186
|
+
const document = SDK.TargetManager.TargetManager.instance()
|
|
187
|
+
.primaryPageTarget()
|
|
188
|
+
?.model(SDK.DOMModel.DOMModel)
|
|
189
|
+
?.existingDocument();
|
|
190
|
+
return document?.body ?? document ?? null;
|
|
191
|
+
}
|
|
192
|
+
|
|
109
193
|
async *
|
|
110
194
|
handleContextDetails(lhr: ConversationContext<LHModel.ReporterTypes.ReportJSON>|null):
|
|
111
195
|
AsyncGenerator<ContextResponse, void, void> {
|
|
@@ -136,6 +220,8 @@ export class AccessibilityAgent extends AiAgent<LHModel.ReporterTypes.ReportJSON
|
|
|
136
220
|
}
|
|
137
221
|
|
|
138
222
|
#declareFunctions(): void {
|
|
223
|
+
this.declareFunction('executeJavaScript', executeJavaScriptFunction(this.#javascriptExecutor));
|
|
224
|
+
|
|
139
225
|
this.declareFunction<{explanation: string}, {audits: string}>('runAccessibilityAudits', {
|
|
140
226
|
description:
|
|
141
227
|
'Triggers new Lighthouse accessibility audits in snapshot mode. Use this if the user has made changes to the page and you want to re-evaluate the accessibility audits.',
|
|
@@ -262,11 +348,31 @@ export class AccessibilityAgent extends AiAgent<LHModel.ReporterTypes.ReportJSON
|
|
|
262
348
|
if (!styles) {
|
|
263
349
|
return {error: 'Could not get computed styles.'};
|
|
264
350
|
}
|
|
265
|
-
const result: Record<string, string|undefined> = {};
|
|
351
|
+
const result: Record<string, string|number|undefined> = {};
|
|
266
352
|
for (const prop of params.styleProperties) {
|
|
267
353
|
result[prop] = styles.get(prop);
|
|
268
354
|
}
|
|
269
|
-
|
|
355
|
+
|
|
356
|
+
result['backendNodeId'] = node.backendNodeId();
|
|
357
|
+
|
|
358
|
+
const widgets: AiWidget[] = [];
|
|
359
|
+
const matchedStyles = await node.domModel().cssModel().getMatchedStyles(node.id);
|
|
360
|
+
if (matchedStyles) {
|
|
361
|
+
widgets.push({
|
|
362
|
+
name: 'COMPUTED_STYLES',
|
|
363
|
+
data: {
|
|
364
|
+
computedStyles: styles,
|
|
365
|
+
backendNodeId: node.backendNodeId(),
|
|
366
|
+
matchedCascade: matchedStyles,
|
|
367
|
+
properties: params.styleProperties,
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
return {
|
|
373
|
+
result: JSON.stringify(result, null, 2),
|
|
374
|
+
widgets: widgets.length > 0 ? widgets : undefined,
|
|
375
|
+
};
|
|
270
376
|
},
|
|
271
377
|
});
|
|
272
378
|
|
|
@@ -337,6 +443,7 @@ export class AccessibilityAgent extends AiAgent<LHModel.ReporterTypes.ReportJSON
|
|
|
337
443
|
{} as Record<string, string>),
|
|
338
444
|
isIgnored: axNode.ignored(),
|
|
339
445
|
ignoredReasons: axNode.ignoredReasons(),
|
|
446
|
+
backendNodeId: node.backendNodeId(),
|
|
340
447
|
};
|
|
341
448
|
|
|
342
449
|
return {result: JSON.stringify(result, null, 2)};
|
|
@@ -172,30 +172,6 @@ export interface ConversationSuggestion {
|
|
|
172
172
|
/** At least one. */
|
|
173
173
|
export type ConversationSuggestions = [ConversationSuggestion, ...ConversationSuggestion[]];
|
|
174
174
|
|
|
175
|
-
export const enum ExternalRequestResponseType {
|
|
176
|
-
ANSWER = 'answer',
|
|
177
|
-
NOTIFICATION = 'notification',
|
|
178
|
-
ERROR = 'error',
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
export interface ExternalRequestAnswer {
|
|
182
|
-
type: ExternalRequestResponseType.ANSWER;
|
|
183
|
-
message: string;
|
|
184
|
-
devToolsLogs: object[];
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
export interface ExternalRequestNotification {
|
|
188
|
-
type: ExternalRequestResponseType.NOTIFICATION;
|
|
189
|
-
message: string;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
export interface ExternalRequestError {
|
|
193
|
-
type: ExternalRequestResponseType.ERROR;
|
|
194
|
-
message: string;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
export type ExternalRequestResponse = ExternalRequestAnswer|ExternalRequestNotification|ExternalRequestError;
|
|
198
|
-
|
|
199
175
|
export abstract class ConversationContext<T> {
|
|
200
176
|
abstract getOrigin(): string;
|
|
201
177
|
abstract getItem(): T;
|
|
@@ -290,9 +266,17 @@ export interface TimelineRangeSummaryAiWidget {
|
|
|
290
266
|
};
|
|
291
267
|
}
|
|
292
268
|
|
|
269
|
+
export interface BottomUpTreeAiWidget {
|
|
270
|
+
name: 'BOTTOM_UP_TREE';
|
|
271
|
+
data: {
|
|
272
|
+
bounds: Trace.Types.Timing.TraceWindowMicro,
|
|
273
|
+
parsedTrace: Trace.TraceModel.ParsedTrace,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
|
|
293
277
|
// This type will grow as we add more widgets.
|
|
294
278
|
export type AiWidget = ComputedStyleAiWidget|CoreVitalsAiWidget|StylePropertiesAiWidget|DomTreeAiWidget|
|
|
295
|
-
PerformanceTraceAiWidget|LcpBreakdownAiWidget|TimelineRangeSummaryAiWidget;
|
|
279
|
+
PerformanceTraceAiWidget|LcpBreakdownAiWidget|TimelineRangeSummaryAiWidget|BottomUpTreeAiWidget;
|
|
296
280
|
|
|
297
281
|
export type FunctionCallHandlerResult<Result> = {
|
|
298
282
|
requiresApproval: true,
|
|
@@ -91,7 +91,7 @@ Content:
|
|
|
91
91
|
},
|
|
92
92
|
{
|
|
93
93
|
"name": "performanceRecordAndReload",
|
|
94
|
-
"description": "Records a new performance trace
|
|
94
|
+
"description": "Records a new performance trace. Use this to measure and debug performance metrics and Core Web Vitals like Largest Contentful Paint (LCP), Interaction to Next Paint (INP), and Cumulative Layout Shift (CLS).",
|
|
95
95
|
"parameters": {
|
|
96
96
|
"type": 6,
|
|
97
97
|
"description": "",
|
|
@@ -102,7 +102,7 @@ Content:
|
|
|
102
102
|
},
|
|
103
103
|
{
|
|
104
104
|
"name": "runLighthouseAudits",
|
|
105
|
-
"description": "Records a Lighthouse audit on the current page
|
|
105
|
+
"description": "Records a Lighthouse audit on the current page. Use this to debug accessibility, SEO, and best practices. (For performance metrics like LCP, use performanceRecordAndReload instead).",
|
|
106
106
|
"parameters": {
|
|
107
107
|
"type": 6,
|
|
108
108
|
"description": "",
|