chrome-devtools-frontend 1.0.1604514 → 1.0.1605390
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/AUTHORS +1 -0
- package/front_end/Images/src/dots-circle.svg +10 -0
- package/front_end/Tests.js +23 -7
- package/front_end/core/host/AidaClient.ts +114 -63
- package/front_end/core/host/AidaGcaTranslation.ts +6 -0
- package/front_end/core/host/GcaClient.ts +112 -0
- package/front_end/core/host/UserMetrics.ts +0 -1
- package/front_end/core/host/host.ts +2 -0
- package/front_end/core/root/ExperimentNames.ts +0 -1
- package/front_end/core/root/Runtime.ts +5 -0
- package/front_end/core/sdk/AutofillModel.ts +3 -2
- package/front_end/core/sdk/CSSModel.ts +3 -4
- package/front_end/core/sdk/CSSProperty.ts +1 -1
- package/front_end/core/sdk/ConsoleModel.ts +15 -13
- package/front_end/core/sdk/CookieModel.ts +5 -4
- package/front_end/core/sdk/DOMDebuggerModel.ts +20 -14
- package/front_end/core/sdk/DebuggerModel.ts +21 -36
- package/front_end/core/sdk/EventBreakpointsModel.ts +16 -6
- package/front_end/core/sdk/IsolateManager.ts +12 -7
- package/front_end/core/sdk/WebMCPModel.ts +57 -2
- package/front_end/entrypoints/main/MainImpl.ts +0 -4
- package/front_end/models/ai_assistance/agents/AiAgent.ts +9 -1
- package/front_end/models/ai_assistance/agents/ConversationSummaryAgent.ts +10 -9
- package/front_end/models/ai_assistance/agents/ExecuteJavascript.ts +301 -0
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +50 -25
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +12 -264
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +1 -1
- package/front_end/models/emulation/DeviceModeModel.ts +21 -26
- package/front_end/models/trace/insights/LCPDiscovery.ts +14 -6
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +2 -17
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +165 -65
- package/front_end/panels/ai_assistance/components/ChatView.ts +2 -13
- package/front_end/panels/ai_assistance/components/ExportForAgentsDialog.ts +1 -1
- package/front_end/panels/ai_assistance/components/chatMessage.css +48 -2
- package/front_end/panels/ai_assistance/components/chatView.css +0 -8
- package/front_end/panels/application/ApplicationPanelSidebar.ts +6 -0
- package/front_end/panels/application/IndexedDBViews.ts +0 -9
- package/front_end/panels/application/WebMCPTreeElement.ts +35 -0
- package/front_end/panels/application/WebMCPView.ts +468 -0
- package/front_end/panels/application/application.ts +4 -0
- package/front_end/panels/application/webMCPView.css +90 -0
- package/front_end/panels/common/aiCodeCompletionSummaryToolbar.css +1 -1
- package/front_end/panels/console/consoleView.css +4 -0
- package/front_end/panels/elements/ElementsTreeOutline.ts +87 -0
- package/front_end/panels/elements/StylesAiCodeCompletionProvider.ts +23 -2
- package/front_end/panels/elements/StylesSidebarPane.ts +85 -20
- package/front_end/panels/elements/elementsPanel.css +14 -0
- package/front_end/panels/elements/elementsTreeOutline.css +21 -0
- package/front_end/panels/network/NetworkLogViewColumns.ts +3 -3
- 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/HeapSnapshotView.ts +12 -16
- package/front_end/panels/profiler/ProfileHeader.ts +0 -11
- 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/recorder/components/recordingView.css +0 -6
- package/front_end/panels/sensors/SensorsView.ts +28 -59
- package/front_end/panels/timeline/EventsTimelineTreeView.ts +3 -3
- package/front_end/panels/timeline/ThirdPartyTreeView.ts +37 -38
- package/front_end/panels/timeline/TimelineDetailsView.ts +47 -41
- package/front_end/panels/timeline/TimelinePanel.ts +11 -0
- package/front_end/panels/timeline/TimelineTreeView.ts +149 -60
- package/front_end/panels/timeline/components/CWVMetrics.ts +18 -2
- package/front_end/panels/timeline/components/LiveMetricsView.ts +839 -783
- package/front_end/panels/timeline/thirdPartyTreeView.css +2 -2
- package/front_end/panels/timeline/timeline-meta.ts +11 -0
- package/front_end/panels/timeline/utils/Helpers.ts +5 -0
- package/front_end/ui/components/buttons/button.css +2 -2
- package/front_end/ui/components/text_editor/AiCodeCompletionProvider.ts +0 -11
- package/front_end/ui/legacy/FilterBar.ts +2 -0
- package/front_end/ui/legacy/InspectorDrawerView.ts +206 -0
- package/front_end/ui/legacy/InspectorView.ts +41 -91
- package/front_end/ui/legacy/SplitWidget.ts +33 -27
- package/front_end/ui/legacy/ViewManager.ts +14 -5
- package/front_end/ui/legacy/Widget.ts +36 -28
- package/front_end/ui/legacy/inspectorDrawerTabbedPane.css +5 -0
- package/front_end/ui/visual_logging/KnownContextValues.ts +8 -1
- package/package.json +1 -1
|
@@ -99,8 +99,9 @@ export class CookieModel extends SDKModel<EventTypes> {
|
|
|
99
99
|
if (cookie.expires()) {
|
|
100
100
|
expires = Math.floor(Date.parse(`${cookie.expires()}`) / 1000);
|
|
101
101
|
}
|
|
102
|
-
const
|
|
103
|
-
Root.Runtime.
|
|
102
|
+
const schemeBindingEnabled =
|
|
103
|
+
Boolean(Root.Runtime.hostConfig.devToolsEnableOriginBoundCookies?.schemeBindingEnabled);
|
|
104
|
+
const portBindingEnabled = Boolean(Root.Runtime.hostConfig.devToolsEnableOriginBoundCookies?.portBindingEnabled);
|
|
104
105
|
const preserveUnset = (scheme: Protocol.Network.CookieSourceScheme): Protocol.Network.CookieSourceScheme.Unset|
|
|
105
106
|
undefined => scheme === Protocol.Network.CookieSourceScheme.Unset ? scheme : undefined;
|
|
106
107
|
const protocolCookie = {
|
|
@@ -115,8 +116,8 @@ export class CookieModel extends SDKModel<EventTypes> {
|
|
|
115
116
|
expires,
|
|
116
117
|
priority: cookie.priority(),
|
|
117
118
|
partitionKey: cookie.partitionKey(),
|
|
118
|
-
sourceScheme:
|
|
119
|
-
sourcePort:
|
|
119
|
+
sourceScheme: schemeBindingEnabled ? cookie.sourceScheme() : preserveUnset(cookie.sourceScheme()),
|
|
120
|
+
sourcePort: portBindingEnabled ? cookie.sourcePort() : undefined,
|
|
120
121
|
};
|
|
121
122
|
const response = await this.target().networkAgent().invoke_setCookie(protocolCookie);
|
|
122
123
|
const error = response.getError();
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import type * as ProtocolProxyApi from '../../generated/protocol-proxy-api.js';
|
|
6
6
|
import * as Protocol from '../../generated/protocol.js';
|
|
7
|
-
import * as Common from '../common/common.js';
|
|
7
|
+
import type * as Common from '../common/common.js';
|
|
8
8
|
import * as Platform from '../platform/platform.js';
|
|
9
9
|
|
|
10
10
|
import {CategorizedBreakpoint, Category} from './CategorizedBreakpoint.js';
|
|
@@ -38,7 +38,7 @@ export class DOMDebuggerModel extends SDKModel<EventTypes> {
|
|
|
38
38
|
this.#domModel.addEventListener(DOMModelEvents.NodeRemoved, this.nodeRemoved, this);
|
|
39
39
|
|
|
40
40
|
this.#domBreakpoints = [];
|
|
41
|
-
this.#domBreakpointsSetting =
|
|
41
|
+
this.#domBreakpointsSetting = this.target().targetManager().settings.createLocalSetting('dom-breakpoints', []);
|
|
42
42
|
if (this.#domModel.existingDocument()) {
|
|
43
43
|
void this.documentUpdated();
|
|
44
44
|
}
|
|
@@ -498,9 +498,11 @@ export class CSPViolationBreakpoint extends CategorizedBreakpoint {
|
|
|
498
498
|
|
|
499
499
|
export class DOMEventListenerBreakpoint extends CategorizedBreakpoint {
|
|
500
500
|
readonly eventTargetNames: string[];
|
|
501
|
-
|
|
501
|
+
readonly #targetManager: TargetManager;
|
|
502
|
+
constructor(eventName: string, eventTargetNames: string[], category: Category, targetManager: TargetManager) {
|
|
502
503
|
super(category, eventName);
|
|
503
504
|
this.eventTargetNames = eventTargetNames;
|
|
505
|
+
this.#targetManager = targetManager;
|
|
504
506
|
}
|
|
505
507
|
|
|
506
508
|
override setEnabled(enabled: boolean): void {
|
|
@@ -508,7 +510,7 @@ export class DOMEventListenerBreakpoint extends CategorizedBreakpoint {
|
|
|
508
510
|
return;
|
|
509
511
|
}
|
|
510
512
|
super.setEnabled(enabled);
|
|
511
|
-
for (const model of
|
|
513
|
+
for (const model of this.#targetManager.models(DOMDebuggerModel)) {
|
|
512
514
|
this.updateOnModel(model);
|
|
513
515
|
}
|
|
514
516
|
}
|
|
@@ -534,9 +536,11 @@ export class DOMDebuggerManager implements SDKModelObserver<DOMDebuggerModel> {
|
|
|
534
536
|
|
|
535
537
|
readonly #cspViolationsToBreakOn: CSPViolationBreakpoint[] = [];
|
|
536
538
|
readonly #eventListenerBreakpoints: DOMEventListenerBreakpoint[] = [];
|
|
539
|
+
readonly #targetManager: TargetManager;
|
|
537
540
|
|
|
538
|
-
constructor() {
|
|
539
|
-
this.#
|
|
541
|
+
constructor(targetManager: TargetManager = TargetManager.instance()) {
|
|
542
|
+
this.#targetManager = targetManager;
|
|
543
|
+
this.#xhrBreakpointsSetting = this.#targetManager.settings.createLocalSetting('xhr-breakpoints', []);
|
|
540
544
|
for (const breakpoint of this.#xhrBreakpointsSetting.get()) {
|
|
541
545
|
this.#xhrBreakpoints.set(breakpoint.url, breakpoint.enabled);
|
|
542
546
|
}
|
|
@@ -659,15 +663,16 @@ export class DOMDebuggerManager implements SDKModelObserver<DOMDebuggerModel> {
|
|
|
659
663
|
Category.XHR, ['readystatechange', 'load', 'loadstart', 'loadend', 'abort', 'error', 'progress', 'timeout'],
|
|
660
664
|
['xmlhttprequest', 'xmlhttprequestupload']);
|
|
661
665
|
|
|
662
|
-
|
|
666
|
+
this.#targetManager.observeModels(DOMDebuggerModel, this);
|
|
663
667
|
}
|
|
664
668
|
|
|
665
669
|
static instance(opts: {
|
|
666
670
|
forceNew: boolean|null,
|
|
671
|
+
targetManager?: TargetManager,
|
|
667
672
|
} = {forceNew: null}): DOMDebuggerManager {
|
|
668
|
-
const {forceNew} = opts;
|
|
673
|
+
const {forceNew, targetManager} = opts;
|
|
669
674
|
if (!domDebuggerManagerInstance || forceNew) {
|
|
670
|
-
domDebuggerManagerInstance = new DOMDebuggerManager();
|
|
675
|
+
domDebuggerManagerInstance = new DOMDebuggerManager(targetManager);
|
|
671
676
|
}
|
|
672
677
|
|
|
673
678
|
return domDebuggerManagerInstance;
|
|
@@ -679,7 +684,8 @@ export class DOMDebuggerManager implements SDKModelObserver<DOMDebuggerModel> {
|
|
|
679
684
|
|
|
680
685
|
private createEventListenerBreakpoints(category: Category, eventNames: string[], eventTargetNames: string[]): void {
|
|
681
686
|
for (const eventName of eventNames) {
|
|
682
|
-
this.#eventListenerBreakpoints.push(
|
|
687
|
+
this.#eventListenerBreakpoints.push(
|
|
688
|
+
new DOMEventListenerBreakpoint(eventName, eventTargetNames, category, this.#targetManager));
|
|
683
689
|
}
|
|
684
690
|
}
|
|
685
691
|
|
|
@@ -710,7 +716,7 @@ export class DOMDebuggerManager implements SDKModelObserver<DOMDebuggerModel> {
|
|
|
710
716
|
|
|
711
717
|
updateCSPViolationBreakpoints(): void {
|
|
712
718
|
const violationTypes = this.#cspViolationsToBreakOn.filter(v => v.enabled()).map(v => v.type());
|
|
713
|
-
for (const model of
|
|
719
|
+
for (const model of this.#targetManager.models(DOMDebuggerModel)) {
|
|
714
720
|
this.updateCSPViolationBreakpointsForModel(model, violationTypes);
|
|
715
721
|
}
|
|
716
722
|
}
|
|
@@ -735,7 +741,7 @@ export class DOMDebuggerManager implements SDKModelObserver<DOMDebuggerModel> {
|
|
|
735
741
|
addXHRBreakpoint(url: string, enabled: boolean): void {
|
|
736
742
|
this.#xhrBreakpoints.set(url, enabled);
|
|
737
743
|
if (enabled) {
|
|
738
|
-
for (const model of
|
|
744
|
+
for (const model of this.#targetManager.models(DOMDebuggerModel)) {
|
|
739
745
|
void model.agent.invoke_setXHRBreakpoint({url});
|
|
740
746
|
}
|
|
741
747
|
}
|
|
@@ -746,7 +752,7 @@ export class DOMDebuggerManager implements SDKModelObserver<DOMDebuggerModel> {
|
|
|
746
752
|
const enabled = this.#xhrBreakpoints.get(url);
|
|
747
753
|
this.#xhrBreakpoints.delete(url);
|
|
748
754
|
if (enabled) {
|
|
749
|
-
for (const model of
|
|
755
|
+
for (const model of this.#targetManager.models(DOMDebuggerModel)) {
|
|
750
756
|
void model.agent.invoke_removeXHRBreakpoint({url});
|
|
751
757
|
}
|
|
752
758
|
}
|
|
@@ -755,7 +761,7 @@ export class DOMDebuggerManager implements SDKModelObserver<DOMDebuggerModel> {
|
|
|
755
761
|
|
|
756
762
|
toggleXHRBreakpoint(url: string, enabled: boolean): void {
|
|
757
763
|
this.#xhrBreakpoints.set(url, enabled);
|
|
758
|
-
for (const model of
|
|
764
|
+
for (const model of this.#targetManager.models(DOMDebuggerModel)) {
|
|
759
765
|
if (enabled) {
|
|
760
766
|
void model.agent.invoke_setXHRBreakpoint({url});
|
|
761
767
|
} else {
|
|
@@ -173,30 +173,19 @@ export class DebuggerModel extends SDKModel<EventTypes> {
|
|
|
173
173
|
(compiledURL, sourceMappingURL, payload, script) =>
|
|
174
174
|
new SourceMap(compiledURL, sourceMappingURL, payload, script));
|
|
175
175
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
Common.Settings.Settings.instance()
|
|
183
|
-
.moduleSetting('pause-on-uncaught-exception')
|
|
184
|
-
.addChangeListener(this.pauseOnExceptionStateChanged, this);
|
|
185
|
-
Common.Settings.Settings.instance()
|
|
186
|
-
.moduleSetting('disable-async-stack-traces')
|
|
187
|
-
.addChangeListener(this.asyncStackTracesStateChanged, this);
|
|
188
|
-
Common.Settings.Settings.instance()
|
|
189
|
-
.moduleSetting('breakpoints-active')
|
|
190
|
-
.addChangeListener(this.breakpointsActiveChanged, this);
|
|
176
|
+
const settings = this.target().targetManager().settings;
|
|
177
|
+
settings.moduleSetting('pause-on-exception-enabled').addChangeListener(this.pauseOnExceptionStateChanged, this);
|
|
178
|
+
settings.moduleSetting('pause-on-caught-exception').addChangeListener(this.pauseOnExceptionStateChanged, this);
|
|
179
|
+
settings.moduleSetting('pause-on-uncaught-exception').addChangeListener(this.pauseOnExceptionStateChanged, this);
|
|
180
|
+
settings.moduleSetting('disable-async-stack-traces').addChangeListener(this.asyncStackTracesStateChanged, this);
|
|
181
|
+
settings.moduleSetting('breakpoints-active').addChangeListener(this.breakpointsActiveChanged, this);
|
|
191
182
|
|
|
192
183
|
if (!target.suspended()) {
|
|
193
184
|
void this.enableDebugger();
|
|
194
185
|
}
|
|
195
186
|
|
|
196
|
-
this.#sourceMapManager.setEnabled(
|
|
197
|
-
|
|
198
|
-
Common.Settings.Settings.instance()
|
|
199
|
-
.moduleSetting('js-source-maps-enabled')
|
|
187
|
+
this.#sourceMapManager.setEnabled(settings.moduleSetting('js-source-maps-enabled').get());
|
|
188
|
+
settings.moduleSetting('js-source-maps-enabled')
|
|
200
189
|
.addChangeListener(event => this.#sourceMapManager.setEnabled((event.data as boolean)));
|
|
201
190
|
|
|
202
191
|
const resourceTreeModel = (target.model(ResourceTreeModel) as ResourceTreeModel);
|
|
@@ -273,7 +262,8 @@ export class DebuggerModel extends SDKModel<EventTypes> {
|
|
|
273
262
|
}
|
|
274
263
|
this.pauseOnExceptionStateChanged();
|
|
275
264
|
void this.asyncStackTracesStateChanged();
|
|
276
|
-
|
|
265
|
+
const settings = this.target().targetManager().settings;
|
|
266
|
+
if (!settings.moduleSetting('breakpoints-active').get()) {
|
|
277
267
|
this.breakpointsActiveChanged();
|
|
278
268
|
}
|
|
279
269
|
this.dispatchEventToListeners(Events.DebuggerWasEnabled, this);
|
|
@@ -364,11 +354,11 @@ export class DebuggerModel extends SDKModel<EventTypes> {
|
|
|
364
354
|
}
|
|
365
355
|
|
|
366
356
|
private pauseOnExceptionStateChanged(): void {
|
|
367
|
-
const
|
|
357
|
+
const settings = this.target().targetManager().settings;
|
|
358
|
+
const pauseOnCaughtEnabled = settings.moduleSetting('pause-on-caught-exception').get();
|
|
368
359
|
let state: Protocol.Debugger.SetPauseOnExceptionsRequestState;
|
|
369
360
|
|
|
370
|
-
const pauseOnUncaughtEnabled =
|
|
371
|
-
Common.Settings.Settings.instance().moduleSetting('pause-on-uncaught-exception').get();
|
|
361
|
+
const pauseOnUncaughtEnabled = settings.moduleSetting('pause-on-uncaught-exception').get();
|
|
372
362
|
if (pauseOnCaughtEnabled && pauseOnUncaughtEnabled) {
|
|
373
363
|
state = Protocol.Debugger.SetPauseOnExceptionsRequestState.All;
|
|
374
364
|
} else if (pauseOnCaughtEnabled) {
|
|
@@ -383,15 +373,15 @@ export class DebuggerModel extends SDKModel<EventTypes> {
|
|
|
383
373
|
|
|
384
374
|
private asyncStackTracesStateChanged(): Promise<Protocol.ProtocolResponseWithError> {
|
|
385
375
|
const maxAsyncStackChainDepth = 32;
|
|
386
|
-
const
|
|
387
|
-
|
|
376
|
+
const settings = this.target().targetManager().settings;
|
|
377
|
+
const enabled = !settings.moduleSetting('disable-async-stack-traces').get() && this.#debuggerEnabled;
|
|
388
378
|
const maxDepth = enabled ? maxAsyncStackChainDepth : 0;
|
|
389
379
|
return this.agent.invoke_setAsyncCallStackDepth({maxDepth});
|
|
390
380
|
}
|
|
391
381
|
|
|
392
382
|
private breakpointsActiveChanged(): void {
|
|
393
|
-
|
|
394
|
-
|
|
383
|
+
const settings = this.target().targetManager().settings;
|
|
384
|
+
void this.agent.invoke_setBreakpointsActive({active: settings.moduleSetting('breakpoints-active').get()});
|
|
395
385
|
}
|
|
396
386
|
|
|
397
387
|
setComputeAutoStepRangesCallback(callback: ((arg0: StepMode, arg1: CallFrame) => Promise<LocationRange[]>)|null):
|
|
@@ -872,15 +862,10 @@ export class DebuggerModel extends SDKModel<EventTypes> {
|
|
|
872
862
|
if (this.#debuggerId) {
|
|
873
863
|
debuggerIdToModel.delete(this.#debuggerId);
|
|
874
864
|
}
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
.moduleSetting('pause-on-caught-exception')
|
|
880
|
-
.removeChangeListener(this.pauseOnExceptionStateChanged, this);
|
|
881
|
-
Common.Settings.Settings.instance()
|
|
882
|
-
.moduleSetting('disable-async-stack-traces')
|
|
883
|
-
.removeChangeListener(this.asyncStackTracesStateChanged, this);
|
|
865
|
+
const settings = this.target().targetManager().settings;
|
|
866
|
+
settings.moduleSetting('pause-on-exception-enabled').removeChangeListener(this.pauseOnExceptionStateChanged, this);
|
|
867
|
+
settings.moduleSetting('pause-on-caught-exception').removeChangeListener(this.pauseOnExceptionStateChanged, this);
|
|
868
|
+
settings.moduleSetting('disable-async-stack-traces').removeChangeListener(this.asyncStackTracesStateChanged, this);
|
|
884
869
|
}
|
|
885
870
|
|
|
886
871
|
override async suspendModel(): Promise<void> {
|
|
@@ -56,12 +56,18 @@ export class EventBreakpointsModel extends SDKModel<void> {
|
|
|
56
56
|
* instrumentation breakpoints in targets that run JS but do not have a DOM.
|
|
57
57
|
**/
|
|
58
58
|
class EventListenerBreakpoint extends CategorizedBreakpoint {
|
|
59
|
+
readonly #targetManager: TargetManager;
|
|
60
|
+
constructor(category: Category, name: string, targetManager: TargetManager) {
|
|
61
|
+
super(category, name);
|
|
62
|
+
this.#targetManager = targetManager;
|
|
63
|
+
}
|
|
64
|
+
|
|
59
65
|
override setEnabled(enabled: boolean): void {
|
|
60
66
|
if (this.enabled() === enabled) {
|
|
61
67
|
return;
|
|
62
68
|
}
|
|
63
69
|
super.setEnabled(enabled);
|
|
64
|
-
for (const model of
|
|
70
|
+
for (const model of this.#targetManager.models(EventBreakpointsModel)) {
|
|
65
71
|
this.updateOnModel(model);
|
|
66
72
|
}
|
|
67
73
|
}
|
|
@@ -81,8 +87,10 @@ let eventBreakpointManagerInstance: EventBreakpointsManager;
|
|
|
81
87
|
|
|
82
88
|
export class EventBreakpointsManager implements SDKModelObserver<EventBreakpointsModel> {
|
|
83
89
|
readonly #eventListenerBreakpoints: EventListenerBreakpoint[] = [];
|
|
90
|
+
readonly #targetManager: TargetManager;
|
|
84
91
|
|
|
85
|
-
constructor() {
|
|
92
|
+
constructor(targetManager: TargetManager = TargetManager.instance()) {
|
|
93
|
+
this.#targetManager = targetManager;
|
|
86
94
|
this.createInstrumentationBreakpoints(Category.AUCTION_WORKLET, [
|
|
87
95
|
InstrumentationNames.BEFORE_BIDDER_WORKLET_BIDDING_START,
|
|
88
96
|
InstrumentationNames.BEFORE_BIDDER_WORKLET_REPORTING_START,
|
|
@@ -135,15 +143,16 @@ export class EventBreakpointsManager implements SDKModelObserver<EventBreakpoint
|
|
|
135
143
|
InstrumentationNames.AUDIO_CONTEXT_SUSPENDED,
|
|
136
144
|
]);
|
|
137
145
|
|
|
138
|
-
|
|
146
|
+
this.#targetManager.observeModels(EventBreakpointsModel, this);
|
|
139
147
|
}
|
|
140
148
|
|
|
141
149
|
static instance(opts: {
|
|
142
150
|
forceNew: boolean|null,
|
|
151
|
+
targetManager?: TargetManager,
|
|
143
152
|
} = {forceNew: null}): EventBreakpointsManager {
|
|
144
|
-
const {forceNew} = opts;
|
|
153
|
+
const {forceNew, targetManager} = opts;
|
|
145
154
|
if (!eventBreakpointManagerInstance || forceNew) {
|
|
146
|
-
eventBreakpointManagerInstance = new EventBreakpointsManager();
|
|
155
|
+
eventBreakpointManagerInstance = new EventBreakpointsManager(targetManager);
|
|
147
156
|
}
|
|
148
157
|
|
|
149
158
|
return eventBreakpointManagerInstance;
|
|
@@ -151,7 +160,8 @@ export class EventBreakpointsManager implements SDKModelObserver<EventBreakpoint
|
|
|
151
160
|
|
|
152
161
|
private createInstrumentationBreakpoints(category: Category, instrumentationNames: InstrumentationNames[]): void {
|
|
153
162
|
for (const instrumentationName of instrumentationNames) {
|
|
154
|
-
this.#eventListenerBreakpoints.push(
|
|
163
|
+
this.#eventListenerBreakpoints.push(
|
|
164
|
+
new EventListenerBreakpoint(category, instrumentationName, this.#targetManager));
|
|
155
165
|
}
|
|
156
166
|
}
|
|
157
167
|
|
|
@@ -19,18 +19,21 @@ export class IsolateManager extends Common.ObjectWrapper.ObjectWrapper<EventType
|
|
|
19
19
|
#isolateIdByModel = new Map<RuntimeModel, string|null>();
|
|
20
20
|
#observers = new Set<Observer>();
|
|
21
21
|
#pollId = 0;
|
|
22
|
+
readonly #targetManager: TargetManager;
|
|
22
23
|
|
|
23
|
-
constructor() {
|
|
24
|
+
constructor(targetManager: TargetManager = TargetManager.instance()) {
|
|
24
25
|
super();
|
|
26
|
+
this.#targetManager = targetManager;
|
|
25
27
|
|
|
26
|
-
|
|
28
|
+
this.#targetManager.observeModels(RuntimeModel, this);
|
|
27
29
|
}
|
|
28
30
|
|
|
29
|
-
static instance({forceNew}: {
|
|
31
|
+
static instance({forceNew, targetManager}: {
|
|
30
32
|
forceNew: boolean,
|
|
33
|
+
targetManager?: TargetManager,
|
|
31
34
|
} = {forceNew: false}): IsolateManager {
|
|
32
35
|
if (!isolateManagerInstance || forceNew) {
|
|
33
|
-
isolateManagerInstance = new IsolateManager();
|
|
36
|
+
isolateManagerInstance = new IsolateManager(targetManager);
|
|
34
37
|
}
|
|
35
38
|
|
|
36
39
|
return isolateManagerInstance;
|
|
@@ -67,7 +70,7 @@ export class IsolateManager extends Common.ObjectWrapper.ObjectWrapper<EventType
|
|
|
67
70
|
this.#isolateIdByModel.set(model, isolateId);
|
|
68
71
|
let isolate = this.#isolates.get(isolateId);
|
|
69
72
|
if (!isolate) {
|
|
70
|
-
isolate = new Isolate(isolateId);
|
|
73
|
+
isolate = new Isolate(isolateId, this);
|
|
71
74
|
this.#isolates.set(isolateId, isolate);
|
|
72
75
|
}
|
|
73
76
|
isolate.models().add(model);
|
|
@@ -145,9 +148,11 @@ export class Isolate {
|
|
|
145
148
|
readonly #models: Set<RuntimeModel>;
|
|
146
149
|
#usedHeapSize: number;
|
|
147
150
|
readonly #memoryTrend: MemoryTrend;
|
|
151
|
+
readonly #manager: IsolateManager;
|
|
148
152
|
|
|
149
|
-
constructor(id: string) {
|
|
153
|
+
constructor(id: string, manager: IsolateManager) {
|
|
150
154
|
this.#id = id;
|
|
155
|
+
this.#manager = manager;
|
|
151
156
|
this.#models = new Set();
|
|
152
157
|
this.#usedHeapSize = 0;
|
|
153
158
|
const count = MemoryTrendWindowMs / PollIntervalMs;
|
|
@@ -179,7 +184,7 @@ export class Isolate {
|
|
|
179
184
|
}
|
|
180
185
|
this.#usedHeapSize = usage.usedSize + (usage.embedderHeapUsedSize ?? 0) + (usage.backingStorageSize ?? 0);
|
|
181
186
|
this.#memoryTrend.add(this.#usedHeapSize);
|
|
182
|
-
|
|
187
|
+
this.#manager.dispatchEventToListeners(Events.MEMORY_CHANGED, this);
|
|
183
188
|
}
|
|
184
189
|
|
|
185
190
|
samplesCount(): number {
|
|
@@ -13,15 +13,32 @@ import {Capability, type Target} from './Target.js';
|
|
|
13
13
|
export const enum Events {
|
|
14
14
|
TOOLS_ADDED = 'ToolsAdded',
|
|
15
15
|
TOOLS_REMOVED = 'ToolsRemoved',
|
|
16
|
+
TOOL_INVOKED = 'ToolInvoked',
|
|
17
|
+
TOOL_RESPONDED = 'ToolResponded',
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface Call {
|
|
21
|
+
invocationId: string;
|
|
22
|
+
input: string;
|
|
23
|
+
tool: Protocol.WebMCP.Tool;
|
|
24
|
+
result?: {
|
|
25
|
+
status: Protocol.WebMCP.InvocationStatus,
|
|
26
|
+
output?: unknown,
|
|
27
|
+
errorText?: string,
|
|
28
|
+
exception?: Protocol.Runtime.RemoteObject,
|
|
29
|
+
};
|
|
16
30
|
}
|
|
17
31
|
|
|
18
32
|
export interface EventTypes {
|
|
19
33
|
[Events.TOOLS_ADDED]: ReadonlyArray<Readonly<Protocol.WebMCP.Tool>>;
|
|
20
34
|
[Events.TOOLS_REMOVED]: ReadonlyArray<Readonly<Protocol.WebMCP.Tool>>;
|
|
35
|
+
[Events.TOOL_INVOKED]: Call;
|
|
36
|
+
[Events.TOOL_RESPONDED]: Call;
|
|
21
37
|
}
|
|
22
38
|
|
|
23
39
|
export class WebMCPModel extends SDKModel<EventTypes> {
|
|
24
40
|
readonly #tools = new Map<Protocol.Page.FrameId, Map<string, Protocol.WebMCP.Tool>>();
|
|
41
|
+
readonly #calls = new Map<string, Call>();
|
|
25
42
|
readonly agent: ProtocolProxyApi.WebMCPApi;
|
|
26
43
|
#enabled = false;
|
|
27
44
|
|
|
@@ -43,6 +60,14 @@ export class WebMCPModel extends SDKModel<EventTypes> {
|
|
|
43
60
|
return this.#tools.values().flatMap(toolMap => toolMap.values());
|
|
44
61
|
}
|
|
45
62
|
|
|
63
|
+
get toolCalls(): Call[] {
|
|
64
|
+
return [...this.#calls.values()];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
clearCalls(): void {
|
|
68
|
+
this.#calls.clear();
|
|
69
|
+
}
|
|
70
|
+
|
|
46
71
|
async enable(): Promise<void> {
|
|
47
72
|
if (this.#enabled) {
|
|
48
73
|
return;
|
|
@@ -78,6 +103,34 @@ export class WebMCPModel extends SDKModel<EventTypes> {
|
|
|
78
103
|
}
|
|
79
104
|
this.dispatchEventToListeners(Events.TOOLS_ADDED, tools);
|
|
80
105
|
}
|
|
106
|
+
|
|
107
|
+
toolInvoked(params: Protocol.WebMCP.ToolInvokedEvent): void {
|
|
108
|
+
const tool = this.#tools.get(params.frameId)?.get(params.toolName);
|
|
109
|
+
if (!tool) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const call: Call = {
|
|
113
|
+
invocationId: params.invocationId,
|
|
114
|
+
input: params.input,
|
|
115
|
+
tool,
|
|
116
|
+
};
|
|
117
|
+
this.#calls.set(params.invocationId, call);
|
|
118
|
+
this.dispatchEventToListeners(Events.TOOL_INVOKED, call);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
toolResponded(params: Protocol.WebMCP.ToolRespondedEvent): void {
|
|
122
|
+
const call = this.#calls.get(params.invocationId);
|
|
123
|
+
if (!call) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
call.result = {
|
|
127
|
+
status: params.status,
|
|
128
|
+
output: params.output,
|
|
129
|
+
errorText: params.errorText,
|
|
130
|
+
exception: params.exception,
|
|
131
|
+
};
|
|
132
|
+
this.dispatchEventToListeners(Events.TOOL_RESPONDED, call);
|
|
133
|
+
}
|
|
81
134
|
}
|
|
82
135
|
|
|
83
136
|
class WebMCPDispatcher implements ProtocolProxyApi.WebMCPDispatcher {
|
|
@@ -94,10 +147,12 @@ class WebMCPDispatcher implements ProtocolProxyApi.WebMCPDispatcher {
|
|
|
94
147
|
this.#model.onToolsRemoved(params.tools);
|
|
95
148
|
}
|
|
96
149
|
|
|
97
|
-
toolInvoked(): void {
|
|
150
|
+
toolInvoked(params: Protocol.WebMCP.ToolInvokedEvent): void {
|
|
151
|
+
this.#model.toolInvoked(params);
|
|
98
152
|
}
|
|
99
153
|
|
|
100
|
-
toolResponded(): void {
|
|
154
|
+
toolResponded(params: Protocol.WebMCP.ToolRespondedEvent): void {
|
|
155
|
+
this.#model.toolResponded(params);
|
|
101
156
|
}
|
|
102
157
|
}
|
|
103
158
|
|
|
@@ -397,10 +397,6 @@ export class MainImpl {
|
|
|
397
397
|
Root.ExperimentNames.ExperimentName.FONT_EDITOR, 'New font editor in the Styles tab',
|
|
398
398
|
'https://developer.chrome.com/blog/new-in-devtools-89/#font');
|
|
399
399
|
|
|
400
|
-
// New cookie features.
|
|
401
|
-
Root.Runtime.experiments.register(
|
|
402
|
-
Root.ExperimentNames.ExperimentName.EXPERIMENTAL_COOKIE_FEATURES, 'Experimental cookie features');
|
|
403
|
-
|
|
404
400
|
Root.Runtime.experiments.registerHostExperiment({
|
|
405
401
|
name: Root.ExperimentNames.ExperimentName.DURABLE_MESSAGES,
|
|
406
402
|
title: 'Durable Messages',
|
|
@@ -290,9 +290,17 @@ export interface TimelineRangeSummaryAiWidget {
|
|
|
290
290
|
};
|
|
291
291
|
}
|
|
292
292
|
|
|
293
|
+
export interface BottomUpTreeAiWidget {
|
|
294
|
+
name: 'BOTTOM_UP_TREE';
|
|
295
|
+
data: {
|
|
296
|
+
bounds: Trace.Types.Timing.TraceWindowMicro,
|
|
297
|
+
parsedTrace: Trace.TraceModel.ParsedTrace,
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
|
|
293
301
|
// This type will grow as we add more widgets.
|
|
294
302
|
export type AiWidget = ComputedStyleAiWidget|CoreVitalsAiWidget|StylePropertiesAiWidget|DomTreeAiWidget|
|
|
295
|
-
PerformanceTraceAiWidget|LcpBreakdownAiWidget|TimelineRangeSummaryAiWidget;
|
|
303
|
+
PerformanceTraceAiWidget|LcpBreakdownAiWidget|TimelineRangeSummaryAiWidget|BottomUpTreeAiWidget;
|
|
296
304
|
|
|
297
305
|
export type FunctionCallHandlerResult<Result> = {
|
|
298
306
|
requiresApproval: true,
|
|
@@ -8,30 +8,31 @@ import * as Root from '../../../core/root/root.js';
|
|
|
8
8
|
import {AiAgent, type ContextResponse, ConversationContext, type RequestOptions, ResponseType} from './AiAgent.js';
|
|
9
9
|
|
|
10
10
|
const preamble = `### Role
|
|
11
|
-
You are a
|
|
11
|
+
You are a Conversation Summarizer. Your task is to take a transcript of a conversation between a user and a DevTools AI agent and produce a succinct, actionable Markdown summary. This summary will be used to help apply fixes in an IDE, so it must capture all relevant technical details, findings, and proposed code changes without any conversational fluff.
|
|
12
12
|
|
|
13
13
|
### Critical Constraints
|
|
14
14
|
- **Persona:** Do not mention that you are an AI or refer to yourself in the third person.
|
|
15
15
|
- **Domain Scope:** Do not provide answers on non-web-development topics (e.g., legal, financial, medical, or personal advice).
|
|
16
|
-
- **Sensitive Topics:** If the conversation history touches on sensitive topics (religion, race, politics, sexuality, gender, etc.), respond only with: "My expertise is limited to
|
|
17
|
-
- **Data Portability:** The recipient of this summary does NOT have access to the raw logs.
|
|
16
|
+
- **Sensitive Topics:** If the conversation history touches on sensitive topics (religion, race, politics, sexuality, gender, etc.), respond only with: "My expertise is limited to summarizing DevTools AI conversations. I cannot provide information on that topic."
|
|
17
|
+
- **Data Portability:** The recipient of this summary does NOT have access to the raw logs or the full conversation transcript.
|
|
18
18
|
- **No UIDs/Internal IDs:** Never refer to elements by internal IDs (e.g., \`uid=123\`).
|
|
19
19
|
- **Standard Selectors:** Identify elements using HTML tags, classes, or IDs (e.g., \`button.submit-form\`).
|
|
20
20
|
- **No Metadata:** Remove internal constants like \`NAVIGATION_0\` or \`INSIGHT_0\`.
|
|
21
|
-
- **No Process Narration:** Do not describe internal "thinking" or API calls. Skip phrases like "The agent investigated..." or "The user then asked...". Jump straight to the findings.
|
|
21
|
+
- **No Process Narration:** Do not describe internal "thinking" or API calls. Skip phrases like "The agent investigated..." or "The user then asked...". Jump straight to the findings and their technical context.
|
|
22
|
+
- **Suggest, Don't Prescribe:** When summarizing code changes made during the session (e.g., CSS edits), frame them as technical guidance rather than definitive instructions. Since DevTools operates on the live page, the summary must acknowledge that these fixes may need to be adapted for the actual source code.
|
|
22
23
|
|
|
23
24
|
### Objectives
|
|
24
25
|
1. **Identify Intent:** Define the core technical goal of the session.
|
|
25
|
-
2. **Value-Only Diagnostics:** List only the technical data points discovered. Omit steps that didn't yield a result.
|
|
26
|
-
3. **
|
|
27
|
-
4. **Actionable Recommendations:** Provide specific code/strategy fixes based on the findings.
|
|
26
|
+
2. **Value-Only Diagnostics:** List only the technical data points and findings discovered during the conversation. Omit steps that didn't yield a result.
|
|
27
|
+
3. **Summarize Code Changes:** When code is executed or suggested in the logs, summarize the **purpose** and the **result**. Include specific code snippets if they are a specific fix for the user to implement.
|
|
28
|
+
4. **Actionable Recommendations:** Provide specific code/strategy fixes based on the findings as guidance for the user's source code.
|
|
28
29
|
|
|
29
30
|
### Formatting Rules
|
|
30
31
|
- **Header:** Use ## [Brief Topic Title]
|
|
31
|
-
- **Context:** Describe the target element/page and the core
|
|
32
|
+
- **Context:** Describe the target element/page and the core issue or technical goal being analyzed.
|
|
32
33
|
- **Diagnostics:** A bulleted list of technical findings.
|
|
33
34
|
- **Tabular Data:** Use a **Markdown Table** for any lists of URLs, metrics, or comparison data.
|
|
34
|
-
- **Code Fixes:** Use fenced code blocks for suggested
|
|
35
|
+
- **Code Fixes:** Use fenced code blocks for suggested code optimizations. Use language that frames them as illustrative examples or context (e.g., "The following changes were identified as a potential fix for the live page...") rather than strict instructions.
|
|
35
36
|
|
|
36
37
|
---
|
|
37
38
|
|