chrome-devtools-frontend 1.0.1642845 → 1.0.1643099
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/SECURITY.md +1 -0
- package/front_end/core/host/UserMetrics.ts +2 -1
- package/front_end/core/protocol_client/InspectorBackend.ts +4 -0
- package/front_end/core/sdk/CSSMatchedStyles.ts +55 -26
- package/front_end/core/sdk/CSSRule.ts +1 -0
- package/front_end/core/sdk/DebuggerModel.ts +5 -0
- package/front_end/entrypoints/greendev_floaty/FloatyEntrypoint.ts +4 -3
- package/front_end/entrypoints/greendev_floaty/greendev_floaty.ts +4 -3
- package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +4 -5
- package/front_end/generated/InspectorBackendCommands.ts +1 -1
- package/front_end/generated/protocol.ts +7 -0
- package/front_end/models/ai_assistance/AiAgent2.ts +100 -18
- package/front_end/models/ai_assistance/AiConversation.ts +18 -14
- package/front_end/models/ai_assistance/AiUtils.ts +71 -0
- package/front_end/models/ai_assistance/ChangeManager.ts +2 -5
- package/front_end/models/ai_assistance/{agents/ConversationSummaryAgent.ts → ConversationSummary.ts} +29 -66
- package/front_end/models/ai_assistance/ExtensionScope.ts +1 -4
- package/front_end/models/ai_assistance/{agents/PerformanceAnnotationsAgent.ts → PerformanceAnnotations.ts} +47 -89
- package/front_end/models/ai_assistance/README.md +8 -0
- package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +65 -40
- package/front_end/models/ai_assistance/agents/AiAgent.ts +37 -6
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.snapshot.txt +11 -0
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +55 -5
- package/front_end/models/ai_assistance/agents/ExecuteJavascript.ts +2 -0
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +119 -78
- package/front_end/models/ai_assistance/agents/StorageAgent.ts +47 -38
- package/front_end/models/ai_assistance/agents/StylingAgent.snapshot.txt +0 -25
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +46 -326
- package/front_end/models/ai_assistance/ai_assistance.ts +14 -4
- package/front_end/models/ai_assistance/contexts/DOMNodeContext.snapshot.txt +51 -0
- package/front_end/models/ai_assistance/contexts/DOMNodeContext.ts +200 -0
- package/front_end/models/ai_assistance/skills/styling.md +44 -2
- package/front_end/models/ai_assistance/tools/ExecuteJavaScript.ts +140 -0
- package/front_end/models/ai_assistance/tools/GetStyles.ts +141 -0
- package/front_end/models/ai_assistance/tools/Tool.ts +64 -0
- package/front_end/models/ai_assistance/tools/ToolRegistry.ts +36 -0
- package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +5 -7
- package/front_end/models/lighthouse/LighthouseReporterTypes.ts +5 -0
- package/front_end/models/live-metrics/LiveMetrics.ts +24 -13
- package/front_end/models/stack_trace/DetailedErrorStackParser.ts +2 -2
- package/front_end/models/stack_trace/StackTrace.ts +4 -1
- package/front_end/models/stack_trace/StackTraceImpl.ts +9 -2
- package/front_end/models/stack_trace/StackTraceModel.ts +17 -4
- package/front_end/models/stack_trace/Trie.ts +1 -1
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +25 -22
- package/front_end/panels/ai_assistance/ai_assistance-meta.ts +16 -0
- package/front_end/panels/ai_assistance/components/ChatInput.ts +2 -2
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +96 -4
- package/front_end/panels/ai_assistance/components/chatMessage.css +6 -0
- package/front_end/panels/application/DOMStorageItemsView.ts +4 -0
- package/front_end/panels/application/KeyValueStorageItemsView.ts +39 -7
- package/front_end/panels/application/components/AdsView.ts +219 -0
- package/front_end/panels/application/components/adsView.css +54 -0
- package/front_end/panels/application/components/components.ts +2 -0
- package/front_end/panels/common/ExtensionServer.ts +26 -15
- package/front_end/panels/console/SymbolizedErrorWidget.ts +73 -22
- package/front_end/panels/elements/StandaloneStylesContainer.ts +1 -1
- package/front_end/panels/elements/StylePropertiesSection.ts +8 -0
- package/front_end/panels/elements/StylePropertyHighlighter.ts +4 -2
- package/front_end/panels/elements/StylePropertyTreeElement.ts +6 -5
- package/front_end/panels/elements/StylesContainer.ts +1 -1
- package/front_end/panels/elements/StylesSidebarPane.ts +4 -4
- package/front_end/panels/layer_viewer/PaintProfilerView.ts +106 -132
- package/front_end/panels/lighthouse/LighthousePanel.ts +4 -3
- package/front_end/panels/network/NetworkLogView.ts +8 -1
- package/front_end/panels/network/networkLogView.css +0 -15
- package/front_end/panels/timeline/overlays/components/EntryLabelOverlay.ts +5 -4
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/lighthouse/README.chromium +2 -2
- package/front_end/third_party/lighthouse/lighthouse-dt-bundle.js +1607 -5733
- package/front_end/third_party/lighthouse/locales/ar-XB.json +290 -65
- package/front_end/third_party/lighthouse/locales/ar.json +290 -65
- package/front_end/third_party/lighthouse/locales/bg.json +290 -65
- package/front_end/third_party/lighthouse/locales/ca.json +295 -70
- package/front_end/third_party/lighthouse/locales/cs.json +290 -65
- package/front_end/third_party/lighthouse/locales/da.json +294 -69
- package/front_end/third_party/lighthouse/locales/de.json +295 -70
- package/front_end/third_party/lighthouse/locales/el.json +290 -65
- package/front_end/third_party/lighthouse/locales/en-GB.json +290 -65
- package/front_end/third_party/lighthouse/locales/en-US.json +79 -67
- package/front_end/third_party/lighthouse/locales/en-XA.json +253 -64
- package/front_end/third_party/lighthouse/locales/en-XL.json +79 -67
- package/front_end/third_party/lighthouse/locales/es-419.json +290 -65
- package/front_end/third_party/lighthouse/locales/es.json +298 -73
- package/front_end/third_party/lighthouse/locales/fi.json +290 -65
- package/front_end/third_party/lighthouse/locales/fil.json +290 -65
- package/front_end/third_party/lighthouse/locales/fr.json +294 -69
- package/front_end/third_party/lighthouse/locales/he.json +293 -68
- package/front_end/third_party/lighthouse/locales/hi.json +291 -66
- package/front_end/third_party/lighthouse/locales/hr.json +290 -65
- package/front_end/third_party/lighthouse/locales/hu.json +290 -65
- package/front_end/third_party/lighthouse/locales/id.json +290 -65
- package/front_end/third_party/lighthouse/locales/it.json +294 -69
- package/front_end/third_party/lighthouse/locales/ja.json +290 -65
- package/front_end/third_party/lighthouse/locales/ko.json +290 -65
- package/front_end/third_party/lighthouse/locales/lt.json +290 -65
- package/front_end/third_party/lighthouse/locales/lv.json +290 -65
- package/front_end/third_party/lighthouse/locales/nl.json +290 -65
- package/front_end/third_party/lighthouse/locales/no.json +290 -65
- package/front_end/third_party/lighthouse/locales/pl.json +290 -65
- package/front_end/third_party/lighthouse/locales/pt-PT.json +291 -66
- package/front_end/third_party/lighthouse/locales/pt.json +290 -65
- package/front_end/third_party/lighthouse/locales/ro.json +290 -65
- package/front_end/third_party/lighthouse/locales/ru.json +301 -76
- package/front_end/third_party/lighthouse/locales/sk.json +291 -66
- package/front_end/third_party/lighthouse/locales/sl.json +290 -65
- package/front_end/third_party/lighthouse/locales/sr-Latn.json +290 -65
- package/front_end/third_party/lighthouse/locales/sr.json +290 -65
- package/front_end/third_party/lighthouse/locales/sv.json +297 -72
- package/front_end/third_party/lighthouse/locales/ta.json +291 -66
- package/front_end/third_party/lighthouse/locales/te.json +293 -68
- package/front_end/third_party/lighthouse/locales/th.json +291 -66
- package/front_end/third_party/lighthouse/locales/tr.json +290 -65
- package/front_end/third_party/lighthouse/locales/uk.json +290 -65
- package/front_end/third_party/lighthouse/locales/vi.json +291 -66
- package/front_end/third_party/lighthouse/locales/zh-HK.json +292 -67
- package/front_end/third_party/lighthouse/locales/zh-TW.json +291 -66
- package/front_end/third_party/lighthouse/locales/zh.json +291 -66
- package/front_end/third_party/lighthouse/report/bundle.d.ts +6 -6
- package/front_end/third_party/lighthouse/report/bundle.js +4 -7
- package/front_end/third_party/lighthouse/report-assets/report-generator.mjs +2 -2
- package/front_end/ui/legacy/Widget.ts +32 -8
- package/front_end/ui/legacy/components/cookie_table/CookiesTable.ts +36 -3
- package/front_end/ui/legacy/components/data_grid/dataGridAiButton.css +20 -0
- package/front_end/ui/legacy/components/utils/Linkifier.ts +19 -4
- package/front_end/ui/visual_logging/KnownContextValues.ts +3 -0
- package/mcp/mcp.ts +1 -0
- package/package.json +1 -1
|
@@ -77,6 +77,11 @@ export interface ReportJSON {
|
|
|
77
77
|
audits: Record<string, AuditResultJSON>;
|
|
78
78
|
categories: Record<CategoryId, CategoryJSON>;
|
|
79
79
|
categoryGroups: Record<string, GroupJSON>;
|
|
80
|
+
/**
|
|
81
|
+
* Identifies if the report was imported from a file (untrusted).
|
|
82
|
+
* Used to disable page-touching AI assistance tools for security.
|
|
83
|
+
*/
|
|
84
|
+
isImported?: boolean;
|
|
80
85
|
}
|
|
81
86
|
|
|
82
87
|
export type DetailsJSON =
|
|
@@ -64,17 +64,22 @@ export class LiveMetrics extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
|
|
|
64
64
|
super();
|
|
65
65
|
const targetManager = SDK.TargetManager.TargetManager.instance();
|
|
66
66
|
targetManager.observeTargets(this, {scoped: true});
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
targetManager.addEventListener(
|
|
71
|
-
SDK.TargetManager.Events.AVAILABLE_TARGETS_CHANGED, this.#onAvailableTargetsChanged, this);
|
|
67
|
+
targetManager.addModelListener(
|
|
68
|
+
SDK.ResourceTreeModel.ResourceTreeModel, SDK.ResourceTreeModel.Events.PrimaryPageChanged,
|
|
69
|
+
this.#onPrimaryPageChanged, this);
|
|
72
70
|
}
|
|
73
71
|
|
|
74
|
-
#
|
|
72
|
+
#onPrimaryPageChanged(
|
|
73
|
+
event: Common.EventTarget.EventTargetEvent<
|
|
74
|
+
{frame: SDK.ResourceTreeModel.ResourceTreeFrame, type: SDK.ResourceTreeModel.PrimaryPageChangeType}>): void {
|
|
75
75
|
const primaryTarget = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
|
|
76
|
-
if (primaryTarget
|
|
77
|
-
|
|
76
|
+
if (!primaryTarget) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (primaryTarget !== this.#target || event.data.type === SDK.ResourceTreeModel.PrimaryPageChangeType.ACTIVATION) {
|
|
80
|
+
// Primary target changed or prerender activated. Switch to it and reset metrics.
|
|
81
|
+
this.#clearMetrics();
|
|
82
|
+
this.#sendStatusUpdate();
|
|
78
83
|
void this.#switchToTarget(primaryTarget);
|
|
79
84
|
}
|
|
80
85
|
}
|
|
@@ -381,11 +386,7 @@ export class LiveMetrics extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
|
|
|
381
386
|
break;
|
|
382
387
|
}
|
|
383
388
|
case 'reset': {
|
|
384
|
-
this.#
|
|
385
|
-
this.#clsValue = undefined;
|
|
386
|
-
this.#inpValue = undefined;
|
|
387
|
-
this.#interactions.clear();
|
|
388
|
-
this.#layoutShifts = [];
|
|
389
|
+
this.#clearMetrics();
|
|
389
390
|
break;
|
|
390
391
|
}
|
|
391
392
|
}
|
|
@@ -393,6 +394,15 @@ export class LiveMetrics extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
|
|
|
393
394
|
this.#sendStatusUpdate();
|
|
394
395
|
}
|
|
395
396
|
|
|
397
|
+
#clearMetrics(): void {
|
|
398
|
+
this.#lcpValue = undefined;
|
|
399
|
+
this.#clsValue = undefined;
|
|
400
|
+
this.#inpValue = undefined;
|
|
401
|
+
this.#interactions.clear();
|
|
402
|
+
this.#interactionsByGroupId.clear();
|
|
403
|
+
this.#layoutShifts = [];
|
|
404
|
+
}
|
|
405
|
+
|
|
396
406
|
#isPrimaryFrameExecutionContext(executionContextId: Protocol.Runtime.ExecutionContextId): boolean {
|
|
397
407
|
if (!this.#target) {
|
|
398
408
|
return false;
|
|
@@ -460,6 +470,7 @@ export class LiveMetrics extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
|
|
|
460
470
|
|
|
461
471
|
clearInteractions(): void {
|
|
462
472
|
this.#interactions.clear();
|
|
473
|
+
this.#interactionsByGroupId.clear();
|
|
463
474
|
this.#sendStatusUpdate();
|
|
464
475
|
}
|
|
465
476
|
|
|
@@ -142,12 +142,12 @@ export function parseRawFramesFromErrorStack(stack: string): RawFrame[]|null {
|
|
|
142
142
|
functionName,
|
|
143
143
|
lineNumber,
|
|
144
144
|
columnNumber,
|
|
145
|
+
isWasm,
|
|
145
146
|
parsedFrameInfo: {
|
|
146
147
|
isAsync,
|
|
147
148
|
isConstructor,
|
|
148
149
|
isEval,
|
|
149
150
|
evalOrigin,
|
|
150
|
-
isWasm,
|
|
151
151
|
wasmModuleName,
|
|
152
152
|
wasmFunctionIndex,
|
|
153
153
|
typeName,
|
|
@@ -181,7 +181,7 @@ export function parseMessage(stack: string): string {
|
|
|
181
181
|
export function augmentRawFramesWithScriptIds(
|
|
182
182
|
rawFrames: RawFrame[], protocolStackTrace: Protocol.Runtime.StackTrace): void {
|
|
183
183
|
function augmentFrame(rawFrame: RawFrame): void {
|
|
184
|
-
const isWasm = rawFrame.
|
|
184
|
+
const isWasm = rawFrame.isWasm;
|
|
185
185
|
const protocolFrame = protocolStackTrace.callFrames.find(frame => {
|
|
186
186
|
if (isWasm) {
|
|
187
187
|
// The parser parses Wasm offsets into the `columnNumber` field. The `lineNumber` is always -1.
|
|
@@ -44,6 +44,10 @@ export interface Frame {
|
|
|
44
44
|
* of the containing function.
|
|
45
45
|
*/
|
|
46
46
|
readonly rawName?: string;
|
|
47
|
+
/**
|
|
48
|
+
* Whether the corresponding raw frame is JS or WASM.
|
|
49
|
+
*/
|
|
50
|
+
readonly isWasm?: boolean;
|
|
47
51
|
}
|
|
48
52
|
|
|
49
53
|
export interface ParsedErrorStackFrame extends Frame {
|
|
@@ -51,7 +55,6 @@ export interface ParsedErrorStackFrame extends Frame {
|
|
|
51
55
|
readonly isConstructor?: boolean;
|
|
52
56
|
readonly isEval?: boolean;
|
|
53
57
|
readonly evalOrigin?: ParsedErrorStackFrame;
|
|
54
|
-
readonly isWasm?: boolean;
|
|
55
58
|
readonly wasmModuleName?: string;
|
|
56
59
|
readonly wasmFunctionIndex?: number;
|
|
57
60
|
readonly typeName?: string;
|
|
@@ -88,10 +88,12 @@ export class FrameImpl implements StackTrace.StackTrace.Frame {
|
|
|
88
88
|
|
|
89
89
|
readonly missingDebugInfo?: StackTrace.StackTrace.MissingDebugInfo;
|
|
90
90
|
readonly rawName?: string;
|
|
91
|
+
readonly isWasm?: boolean;
|
|
91
92
|
|
|
92
93
|
constructor(
|
|
93
94
|
url: string|undefined, uiSourceCode: Workspace.UISourceCode.UISourceCode|undefined, name: string|undefined,
|
|
94
|
-
line: number, column: number, missingDebugInfo?: StackTrace.StackTrace.MissingDebugInfo, rawName?: string
|
|
95
|
+
line: number, column: number, missingDebugInfo?: StackTrace.StackTrace.MissingDebugInfo, rawName?: string,
|
|
96
|
+
isWasm?: boolean) {
|
|
95
97
|
this.url = url;
|
|
96
98
|
this.uiSourceCode = uiSourceCode;
|
|
97
99
|
this.name = name;
|
|
@@ -99,6 +101,7 @@ export class FrameImpl implements StackTrace.StackTrace.Frame {
|
|
|
99
101
|
this.column = column;
|
|
100
102
|
this.missingDebugInfo = missingDebugInfo;
|
|
101
103
|
this.rawName = rawName;
|
|
104
|
+
this.isWasm = isWasm;
|
|
102
105
|
}
|
|
103
106
|
}
|
|
104
107
|
|
|
@@ -192,7 +195,7 @@ export class ParsedErrorStackFrameImpl implements StackTrace.StackTrace.ParsedEr
|
|
|
192
195
|
return this.#evalOrigin;
|
|
193
196
|
}
|
|
194
197
|
get isWasm(): boolean|undefined {
|
|
195
|
-
return this.#
|
|
198
|
+
return this.#frame.isWasm;
|
|
196
199
|
}
|
|
197
200
|
get wasmModuleName(): string|undefined {
|
|
198
201
|
return this.#parsedFrameInfo?.wasmModuleName;
|
|
@@ -284,6 +287,10 @@ export class DebuggableFrameImpl implements StackTrace.StackTrace.DebuggableFram
|
|
|
284
287
|
return this.#frame.rawName;
|
|
285
288
|
}
|
|
286
289
|
|
|
290
|
+
get isWasm(): boolean|undefined {
|
|
291
|
+
return this.#frame.isWasm;
|
|
292
|
+
}
|
|
293
|
+
|
|
287
294
|
get sdkFrame(): SDK.DebuggerModel.CallFrame {
|
|
288
295
|
return this.#sdkFrame;
|
|
289
296
|
}
|
|
@@ -48,8 +48,14 @@ export class StackTraceModel extends SDK.SDKModel.SDKModel<unknown> {
|
|
|
48
48
|
|
|
49
49
|
async createFromProtocolRuntime(stackTrace: Protocol.Runtime.StackTrace, rawFramesToUIFrames: TranslateRawFrames):
|
|
50
50
|
Promise<StackTrace.StackTrace.StackTrace> {
|
|
51
|
+
const debuggerModel = this.target().model(SDK.DebuggerModel.DebuggerModel);
|
|
52
|
+
const syncFrames = stackTrace.callFrames.map((frame): RawFrame => {
|
|
53
|
+
const isWasm = debuggerModel?.isWasm(frame.scriptId) ?? false;
|
|
54
|
+
return {...frame, isWasm};
|
|
55
|
+
});
|
|
56
|
+
|
|
51
57
|
const [syncFragment, asyncFragments] = await Promise.all([
|
|
52
|
-
this.#createFragment(
|
|
58
|
+
this.#createFragment(syncFrames, rawFramesToUIFrames),
|
|
53
59
|
this.#createAsyncFragments(stackTrace, rawFramesToUIFrames),
|
|
54
60
|
]);
|
|
55
61
|
|
|
@@ -126,6 +132,7 @@ export class StackTraceModel extends SDK.SDKModel.SDKModel<unknown> {
|
|
|
126
132
|
functionName: frame.functionName,
|
|
127
133
|
lineNumber: frame.location().lineNumber,
|
|
128
134
|
columnNumber: frame.location().columnNumber,
|
|
135
|
+
isWasm: frame.script.isWasm(),
|
|
129
136
|
})),
|
|
130
137
|
rawFramesToUIFrames);
|
|
131
138
|
return new DebuggableFragmentImpl(fragment, pausedDetails.callFrames);
|
|
@@ -144,8 +151,14 @@ export class StackTraceModel extends SDK.SDKModel.SDKModel<unknown> {
|
|
|
144
151
|
continue;
|
|
145
152
|
}
|
|
146
153
|
const model = StackTraceModel.#modelForTarget(target);
|
|
154
|
+
const targetDebuggerModel = target.model(SDK.DebuggerModel.DebuggerModel);
|
|
155
|
+
const asyncFrames = asyncStackTrace.callFrames.map((frame): RawFrame => {
|
|
156
|
+
const isWasm = targetDebuggerModel?.isWasm(frame.scriptId) ?? false;
|
|
157
|
+
return {...frame, isWasm};
|
|
158
|
+
});
|
|
159
|
+
|
|
147
160
|
const asyncFragmentPromise =
|
|
148
|
-
model.#createFragment(
|
|
161
|
+
model.#createFragment(asyncFrames, rawFramesToUIFrames)
|
|
149
162
|
.then(fragment => new AsyncFragmentImpl(asyncStackTrace.description ?? '', fragment));
|
|
150
163
|
asyncFragments.push(asyncFragmentPromise);
|
|
151
164
|
}
|
|
@@ -201,7 +214,7 @@ export class StackTraceModel extends SDK.SDKModel.SDKModel<unknown> {
|
|
|
201
214
|
node.frames = uiFrames[i++].map(
|
|
202
215
|
frame => new FrameImpl(
|
|
203
216
|
frame.url, frame.uiSourceCode, frame.name, frame.line, frame.column, frame.missingDebugInfo,
|
|
204
|
-
node.rawFrame.functionName));
|
|
217
|
+
node.rawFrame.functionName, node.rawFrame.isWasm));
|
|
205
218
|
|
|
206
219
|
if (node.parsedFrameInfo?.evalOrigin) {
|
|
207
220
|
node.evalOrigin = evalOrigins[evalI++];
|
|
@@ -243,7 +256,7 @@ async function translateEvalOrigin(
|
|
|
243
256
|
const frames = uiFrames[0].map(
|
|
244
257
|
frame => new FrameImpl(
|
|
245
258
|
frame.url, frame.uiSourceCode, frame.name, frame.line, frame.column, frame.missingDebugInfo,
|
|
246
|
-
rawFrame.functionName));
|
|
259
|
+
rawFrame.functionName, rawFrame.isWasm));
|
|
247
260
|
|
|
248
261
|
let parentEvalOrigin: EvalOrigin|undefined;
|
|
249
262
|
if (rawFrame.parsedFrameInfo?.evalOrigin) {
|
|
@@ -11,7 +11,6 @@ export interface ParsedFrameInfo {
|
|
|
11
11
|
readonly isConstructor?: boolean;
|
|
12
12
|
readonly isEval?: boolean;
|
|
13
13
|
readonly evalOrigin?: RawFrame;
|
|
14
|
-
readonly isWasm?: boolean;
|
|
15
14
|
readonly wasmModuleName?: string;
|
|
16
15
|
readonly wasmFunctionIndex?: number;
|
|
17
16
|
readonly typeName?: string;
|
|
@@ -30,6 +29,7 @@ export interface RawFrame {
|
|
|
30
29
|
readonly columnNumber: number;
|
|
31
30
|
|
|
32
31
|
readonly parsedFrameInfo?: ParsedFrameInfo;
|
|
32
|
+
readonly isWasm?: boolean;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
/**
|
|
@@ -362,23 +362,22 @@ function getMarkdownRenderer(conversation?: AiAssistanceModel.AiConversation.AiC
|
|
|
362
362
|
const context = conversation?.selectedContext;
|
|
363
363
|
|
|
364
364
|
if (context instanceof AiAssistanceModel.PerformanceAgent.PerformanceTraceContext) {
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
}
|
|
370
|
-
} else if (conversation?.type === AiAssistanceModel.AiHistoryStorage.ConversationType.PERFORMANCE) {
|
|
365
|
+
const focus = context.getItem();
|
|
366
|
+
return new PerformanceAgentMarkdownRenderer(focus.parsedTrace.data.Meta.mainFrameId, focus.lookupEvent.bind(focus));
|
|
367
|
+
}
|
|
368
|
+
if (conversation?.type === AiAssistanceModel.AiHistoryStorage.ConversationType.PERFORMANCE) {
|
|
371
369
|
// Handle historical conversations (can't linkify anything).
|
|
372
370
|
return new PerformanceAgentMarkdownRenderer();
|
|
373
|
-
}
|
|
374
|
-
|
|
371
|
+
}
|
|
372
|
+
if (Greendev.Prototypes.instance().isEnabled('emulationCapabilities') &&
|
|
375
373
|
conversation?.type === AiAssistanceModel.AiHistoryStorage.ConversationType.STYLING &&
|
|
376
374
|
SDK.TargetManager.TargetManager.instance().primaryPageTarget()?.model(SDK.DOMModel.DOMModel)) {
|
|
377
375
|
const domModel = SDK.TargetManager.TargetManager.instance().primaryPageTarget()?.model(SDK.DOMModel.DOMModel);
|
|
378
376
|
const resourceTreeModel = domModel?.target().model(SDK.ResourceTreeModel.ResourceTreeModel);
|
|
379
377
|
const mainFrameId = resourceTreeModel?.mainFrame?.id;
|
|
380
378
|
return new StylingAgentMarkdownRenderer(mainFrameId);
|
|
381
|
-
}
|
|
379
|
+
}
|
|
380
|
+
if (conversation?.type === AiAssistanceModel.AiHistoryStorage.ConversationType.ACCESSIBILITY) {
|
|
382
381
|
const domModel = SDK.TargetManager.TargetManager.instance().primaryPageTarget()?.model(SDK.DOMModel.DOMModel);
|
|
383
382
|
const mainDocumentURL = domModel?.existingDocument()?.documentURL;
|
|
384
383
|
return new AccessibilityAgentMarkdownRenderer(mainDocumentURL);
|
|
@@ -570,11 +569,11 @@ function defaultView(input: ViewInput, output: PanelViewOutput, target: HTMLElem
|
|
|
570
569
|
// clang-format on
|
|
571
570
|
}
|
|
572
571
|
|
|
573
|
-
function
|
|
572
|
+
function createDOMNodeContext(node: SDK.DOMModel.DOMNode|null): AiAssistanceModel.DOMNodeContext.DOMNodeContext|null {
|
|
574
573
|
if (!node) {
|
|
575
574
|
return null;
|
|
576
575
|
}
|
|
577
|
-
return new AiAssistanceModel.
|
|
576
|
+
return new AiAssistanceModel.DOMNodeContext.DOMNodeContext(node);
|
|
578
577
|
}
|
|
579
578
|
|
|
580
579
|
function createFileContext(file: Workspace.UISourceCode.UISourceCode|null): AiAssistanceModel.FileAgent.FileContext|
|
|
@@ -658,7 +657,7 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
658
657
|
// NodeJS debugging does not have Elements panel, thus this action might not exist.
|
|
659
658
|
#toggleSearchElementAction?: UI.ActionRegistration.Action;
|
|
660
659
|
#aidaClient: Host.AidaClient.AidaClient;
|
|
661
|
-
#
|
|
660
|
+
#conversationSummary?: AiAssistanceModel.ConversationSummary.ConversationSummary;
|
|
662
661
|
#viewOutput: PanelViewOutput = {};
|
|
663
662
|
#serverSideLoggingEnabled = isAiAssistanceServerSideLoggingEnabled();
|
|
664
663
|
#aiAssistanceEnabledSetting: Common.Settings.Setting<boolean>|undefined;
|
|
@@ -668,7 +667,7 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
668
667
|
#conversation?: AiAssistanceModel.AiConversation.AiConversation;
|
|
669
668
|
|
|
670
669
|
#selectedFile: AiAssistanceModel.FileAgent.FileContext|null = null;
|
|
671
|
-
#selectedElement: AiAssistanceModel.
|
|
670
|
+
#selectedElement: AiAssistanceModel.DOMNodeContext.DOMNodeContext|null = null;
|
|
672
671
|
#selectedPerformanceTrace: AiAssistanceModel.PerformanceAgent.PerformanceTraceContext|null = null;
|
|
673
672
|
#selectedRequest: AiAssistanceModel.NetworkAgent.RequestContext|null = null;
|
|
674
673
|
|
|
@@ -785,17 +784,16 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
785
784
|
markdownRenderer,
|
|
786
785
|
conversationMarkdown: this.#conversation.getConversationMarkdown(),
|
|
787
786
|
generateConversationSummary: async (markdown: string) => {
|
|
788
|
-
if (!this.#
|
|
789
|
-
this.#
|
|
787
|
+
if (!this.#conversationSummary) {
|
|
788
|
+
this.#conversationSummary = new AiAssistanceModel.ConversationSummary.ConversationSummary({
|
|
790
789
|
aidaClient: this.#aidaClient,
|
|
791
790
|
serverSideLoggingEnabled: this.#serverSideLoggingEnabled,
|
|
792
791
|
});
|
|
793
792
|
}
|
|
794
|
-
return await this.#
|
|
793
|
+
return await this.#conversationSummary.summarizeConversation(markdown);
|
|
795
794
|
},
|
|
796
|
-
onTextSubmit: async (
|
|
797
|
-
|
|
798
|
-
multimodalInputType?: AiAssistanceModel.AiAgent.MultimodalInputType) => {
|
|
795
|
+
onTextSubmit: async (text: string, imageInput?: Host.AidaClient.Part,
|
|
796
|
+
multimodalInputType?: AiAssistanceModel.AiAgent.MultimodalInputType) => {
|
|
799
797
|
const submit = (): void => {
|
|
800
798
|
Host.userMetrics.actionTaken(Host.UserMetrics.Action.AiAssistanceQuerySubmitted);
|
|
801
799
|
void this.#startConversation(text, imageInput, multimodalInputType);
|
|
@@ -1117,7 +1115,7 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
1117
1115
|
this.#viewOutput.chatView?.focusTextInput();
|
|
1118
1116
|
void this.#handleAidaAvailabilityChange();
|
|
1119
1117
|
this.#selectedElement =
|
|
1120
|
-
|
|
1118
|
+
createDOMNodeContext(selectedElementFilter(UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode)));
|
|
1121
1119
|
this.#selectedRequest =
|
|
1122
1120
|
createRequestContext(UI.Context.Context.instance().flavor(SDK.NetworkRequest.NetworkRequest));
|
|
1123
1121
|
this.#selectedPerformanceTrace =
|
|
@@ -1225,7 +1223,7 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
1225
1223
|
return;
|
|
1226
1224
|
}
|
|
1227
1225
|
|
|
1228
|
-
this.#selectedElement =
|
|
1226
|
+
this.#selectedElement = createDOMNodeContext(selectedElementFilter(ev.data));
|
|
1229
1227
|
this.#updateConversationState(this.#conversation);
|
|
1230
1228
|
};
|
|
1231
1229
|
|
|
@@ -1576,6 +1574,11 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
1576
1574
|
targetConversationType = AiAssistanceModel.AiHistoryStorage.ConversationType.FILE;
|
|
1577
1575
|
break;
|
|
1578
1576
|
}
|
|
1577
|
+
case 'ai-assistance.storage-floating-button': {
|
|
1578
|
+
Host.userMetrics.actionTaken(Host.UserMetrics.Action.AiAssistanceOpenedFromStoragePanelFloatingButton);
|
|
1579
|
+
targetConversationType = AiAssistanceModel.AiHistoryStorage.ConversationType.STORAGE;
|
|
1580
|
+
break;
|
|
1581
|
+
}
|
|
1579
1582
|
}
|
|
1580
1583
|
|
|
1581
1584
|
if (!targetConversationType) {
|
|
@@ -1727,7 +1730,7 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
1727
1730
|
#handleConversationContextChange = (data: unknown): void => {
|
|
1728
1731
|
if (data instanceof AiAssistanceModel.FileAgent.FileContext) {
|
|
1729
1732
|
this.#selectedFile = data;
|
|
1730
|
-
} else if (data instanceof AiAssistanceModel.
|
|
1733
|
+
} else if (data instanceof AiAssistanceModel.DOMNodeContext.DOMNodeContext) {
|
|
1731
1734
|
this.#selectedElement = data;
|
|
1732
1735
|
} else if (data instanceof AiAssistanceModel.NetworkAgent.RequestContext) {
|
|
1733
1736
|
this.#selectedRequest = data;
|
|
@@ -297,3 +297,19 @@ UI.ActionRegistration.registerActionExtension({
|
|
|
297
297
|
},
|
|
298
298
|
condition: config => isFileAgentFeatureAvailable(config) && !isPolicyRestricted(config) && !isGeoRestricted(config),
|
|
299
299
|
});
|
|
300
|
+
|
|
301
|
+
UI.ActionRegistration.registerActionExtension({
|
|
302
|
+
actionId: 'ai-assistance.storage-floating-button',
|
|
303
|
+
contextTypes(): [] {
|
|
304
|
+
return [];
|
|
305
|
+
},
|
|
306
|
+
category: UI.ActionRegistration.ActionCategory.GLOBAL,
|
|
307
|
+
title: i18nAiBrandedString(UIStrings.debugWithGemini, UIStrings.debugWithAi),
|
|
308
|
+
configurableBindings: false,
|
|
309
|
+
async loadActionDelegate() {
|
|
310
|
+
const AiAssistance = await loadAiAssistanceModule();
|
|
311
|
+
return new AiAssistance.ActionDelegate();
|
|
312
|
+
},
|
|
313
|
+
condition: config =>
|
|
314
|
+
isStorageAgentFeatureAvailable(config) && !isPolicyRestricted(config) && !isGeoRestricted(config),
|
|
315
|
+
});
|
|
@@ -174,7 +174,7 @@ function getContextRemoveLabel(context: AiAssistanceModel.AiAgent.ConversationCo
|
|
|
174
174
|
if (context instanceof AiAssistanceModel.FileAgent.FileContext) {
|
|
175
175
|
return lockedString(UIStringsNotTranslate.removeContextFile);
|
|
176
176
|
}
|
|
177
|
-
if (context instanceof AiAssistanceModel.
|
|
177
|
+
if (context instanceof AiAssistanceModel.DOMNodeContext.DOMNodeContext) {
|
|
178
178
|
return lockedString(UIStringsNotTranslate.removeContextElement);
|
|
179
179
|
}
|
|
180
180
|
if (context instanceof AiAssistanceModel.NetworkAgent.RequestContext) {
|
|
@@ -336,7 +336,7 @@ export const DEFAULT_VIEW = (input: ViewInput, _output: ViewOutput, target: HTML
|
|
|
336
336
|
})}
|
|
337
337
|
>
|
|
338
338
|
${
|
|
339
|
-
input.context instanceof AiAssistanceModel.
|
|
339
|
+
input.context instanceof AiAssistanceModel.DOMNodeContext.DOMNodeContext ?
|
|
340
340
|
html`
|
|
341
341
|
<devtools-widget
|
|
342
342
|
class="title"
|
|
@@ -14,9 +14,9 @@ import * as SDK from '../../../core/sdk/sdk.js';
|
|
|
14
14
|
import type * as Protocol from '../../../generated/protocol.js';
|
|
15
15
|
import type {
|
|
16
16
|
AiWidget, BottomUpTreeAiWidget, ComputedStyleAiWidget, CoreVitalsAiWidget, DomTreeAiWidget, LighthouseReportAiWidget,
|
|
17
|
-
NetworkRequestGeneralHeadersAiWidget, PerfInsightAiWidget, PerformanceTraceAiWidget,
|
|
18
|
-
SourceFileAiWidget, SourceFilesListAiWidget, StylePropertiesAiWidget,
|
|
19
|
-
TimelineRangeSummaryAiWidget} from '../../../models/ai_assistance/agents/AiAgent.js';
|
|
17
|
+
NetworkRequestGeneralHeadersAiWidget, NetworkRequestsListAiWidget, PerfInsightAiWidget, PerformanceTraceAiWidget,
|
|
18
|
+
SourceCodeAiWidget, SourceFileAiWidget, SourceFilesListAiWidget, StylePropertiesAiWidget,
|
|
19
|
+
TimelineEventSummaryAiWidget, TimelineRangeSummaryAiWidget} from '../../../models/ai_assistance/agents/AiAgent.js';
|
|
20
20
|
import * as AiAssistanceModel from '../../../models/ai_assistance/ai_assistance.js';
|
|
21
21
|
import * as ComputedStyle from '../../../models/computed_style/computed_style.js';
|
|
22
22
|
import * as Formatter from '../../../models/formatter/formatter.js';
|
|
@@ -30,6 +30,7 @@ import * as Buttons from '../../../ui/components/buttons/buttons.js';
|
|
|
30
30
|
import * as Input from '../../../ui/components/input/input.js';
|
|
31
31
|
import type * as MarkdownView from '../../../ui/components/markdown_view/markdown_view.js';
|
|
32
32
|
import type {MarkdownLitRenderer} from '../../../ui/components/markdown_view/MarkdownView.js';
|
|
33
|
+
import * as Snackbars from '../../../ui/components/snackbars/snackbars.js';
|
|
33
34
|
import * as UIHelpers from '../../../ui/helpers/helpers.js';
|
|
34
35
|
import * as UI from '../../../ui/legacy/legacy.js';
|
|
35
36
|
import * as Lit from '../../../ui/lit/lit.js';
|
|
@@ -414,6 +415,14 @@ const UIStringsNotTranslate = {
|
|
|
414
415
|
* @description Title for the character set declaration widget.
|
|
415
416
|
*/
|
|
416
417
|
characterSet: 'Character set declaration',
|
|
418
|
+
/**
|
|
419
|
+
* @description Title for the network requests list widget.
|
|
420
|
+
*/
|
|
421
|
+
networkRequests: 'Network requests',
|
|
422
|
+
/**
|
|
423
|
+
* @description Accessible label for the reveal button in the network requests list widget.
|
|
424
|
+
*/
|
|
425
|
+
revealFirstNetworkRequest: 'Reveal first network request in Network panel',
|
|
417
426
|
/**
|
|
418
427
|
* @description Title for the source files list widget.
|
|
419
428
|
*/
|
|
@@ -1300,7 +1309,12 @@ function renderWidgetResponse(response: WidgetMakerResponse|null): Lit.LitTempla
|
|
|
1300
1309
|
if (response === null) {
|
|
1301
1310
|
return;
|
|
1302
1311
|
}
|
|
1303
|
-
|
|
1312
|
+
Common.Revealer.reveal(response?.revealable).catch((error: Error) => {
|
|
1313
|
+
if (!error.message) {
|
|
1314
|
+
return;
|
|
1315
|
+
}
|
|
1316
|
+
Snackbars.Snackbar.Snackbar.show({message: error.message});
|
|
1317
|
+
});
|
|
1304
1318
|
}
|
|
1305
1319
|
|
|
1306
1320
|
const classes = Lit.Directives.classMap({
|
|
@@ -1466,6 +1480,79 @@ async function makeSourceFilesListWidget(widgetData: SourceFilesListAiWidget): P
|
|
|
1466
1480
|
};
|
|
1467
1481
|
}
|
|
1468
1482
|
|
|
1483
|
+
const expandedNetworkRequestsWidgets = new WeakSet<NetworkRequestsListAiWidget>();
|
|
1484
|
+
|
|
1485
|
+
// A widget with a table of the list of network requests sent to the agent.
|
|
1486
|
+
// Only show 15 requests maximum in collapsed version. The rest of the requests
|
|
1487
|
+
// will be hidden unless the user clicks "Show all".
|
|
1488
|
+
async function makeNetworkRequestsListWidget(widgetData: NetworkRequestsListAiWidget):
|
|
1489
|
+
Promise<WidgetMakerResponse|null> {
|
|
1490
|
+
const requests = widgetData.data.requests;
|
|
1491
|
+
if (requests.length === 0) {
|
|
1492
|
+
return null;
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
const isExpanded = expandedNetworkRequestsWidgets.has(widgetData);
|
|
1496
|
+
// We only want just expanded widget to be expanded, if the user closed and reopened the walkthrought, the widget should be collapsed again.
|
|
1497
|
+
// Therefore, after rendering the widget, we remove the widget from the set of expanded widgets so that it is collapsed on next render.
|
|
1498
|
+
if (isExpanded) {
|
|
1499
|
+
expandedNetworkRequestsWidgets.delete(widgetData);
|
|
1500
|
+
}
|
|
1501
|
+
const displayedRequests = isExpanded ? requests : requests.slice(0, 15);
|
|
1502
|
+
|
|
1503
|
+
// The table contains same fields as the ones sent to the agent.
|
|
1504
|
+
// clang-format off
|
|
1505
|
+
const renderedWidget = html`
|
|
1506
|
+
<div class="network-requests-widget">
|
|
1507
|
+
<devtools-data-grid striped inline>
|
|
1508
|
+
<table>
|
|
1509
|
+
<tr>
|
|
1510
|
+
<th id="name" weight="4">${i18n.i18n.lockedString('Name')}</th>
|
|
1511
|
+
<th id="status" weight="1">${i18n.i18n.lockedString('Status')}</th>
|
|
1512
|
+
<th id="size" weight="1">${i18n.i18n.lockedString('Size')}</th>
|
|
1513
|
+
<th id="time" weight="1">${i18n.i18n.lockedString('Time')}</th>
|
|
1514
|
+
</tr>
|
|
1515
|
+
${displayedRequests.map(request => html`
|
|
1516
|
+
<tr>
|
|
1517
|
+
<td>${request.name()}</td>
|
|
1518
|
+
<td>${request.statusCode}</td>
|
|
1519
|
+
<td>${i18n.ByteUtilities.formatBytesToKb(request.transferSize)}</td>
|
|
1520
|
+
<td>${i18n.TimeUtilities.secondsToString(request.duration)}</td>
|
|
1521
|
+
</tr>
|
|
1522
|
+
`)}
|
|
1523
|
+
</table>
|
|
1524
|
+
</devtools-data-grid>
|
|
1525
|
+
${!isExpanded && requests.length > 15 ? html`
|
|
1526
|
+
<div class="show-all-container">
|
|
1527
|
+
<button class="show-all-widget-requests-button text-button"
|
|
1528
|
+
jslog=${VisualLogging.action('show-all-widget-requests-button').track({click: true})}
|
|
1529
|
+
@click=${(e: Event) => {
|
|
1530
|
+
expandedNetworkRequestsWidgets.add(widgetData);
|
|
1531
|
+
const widgetEl = (e.target as HTMLElement).closest('.widget');
|
|
1532
|
+
if (widgetEl) {
|
|
1533
|
+
const widget = UI.Widget.Widget.get(widgetEl) as ChatMessage;
|
|
1534
|
+
if (widget && widget.performUpdate) {
|
|
1535
|
+
void widget.performUpdate();
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
}}>
|
|
1539
|
+
${i18n.i18n.lockedString(`Show all ${requests.length} network requests`)}
|
|
1540
|
+
</button>
|
|
1541
|
+
</div>
|
|
1542
|
+
` : Lit.nothing}
|
|
1543
|
+
</div>
|
|
1544
|
+
`;
|
|
1545
|
+
// clang-format on
|
|
1546
|
+
|
|
1547
|
+
return {
|
|
1548
|
+
renderedWidget,
|
|
1549
|
+
title: lockedString(UIStringsNotTranslate.networkRequests),
|
|
1550
|
+
revealable: requests[0],
|
|
1551
|
+
accessibleRevealLabel: lockedString(UIStringsNotTranslate.revealFirstNetworkRequest),
|
|
1552
|
+
jslogContext: 'network-requests-list-widget',
|
|
1553
|
+
};
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1469
1556
|
function renderNetworkRequestPreview(networkRequest: NonNullable<DomTreeAiWidget['data']['networkRequest']>):
|
|
1470
1557
|
Lit.TemplateResult {
|
|
1471
1558
|
const filename = networkRequest.url.split('/').pop() || networkRequest.url;
|
|
@@ -1583,6 +1670,8 @@ export function getWidgetSignature(widget: AiWidget): string {
|
|
|
1583
1670
|
return `${widget.name}:${widget.data.request.requestId()}`;
|
|
1584
1671
|
case 'SOURCE_CODE':
|
|
1585
1672
|
return `${widget.name}:${widget.data.url}:${widget.data.line ?? ''}:${widget.data.column ?? ''}`;
|
|
1673
|
+
case 'NETWORK_REQUESTS_LIST':
|
|
1674
|
+
return `${widget.name}:${widget.data.requests.map(r => r.requestId()).join(',')}`;
|
|
1586
1675
|
default:
|
|
1587
1676
|
Platform.assertNever(widget, 'Unknown AiWidget name');
|
|
1588
1677
|
}
|
|
@@ -1672,6 +1761,9 @@ async function renderWidgets(
|
|
|
1672
1761
|
case 'SOURCE_FILES_LIST':
|
|
1673
1762
|
response = await makeSourceFilesListWidget(widgetData);
|
|
1674
1763
|
break;
|
|
1764
|
+
case 'NETWORK_REQUESTS_LIST':
|
|
1765
|
+
response = await makeNetworkRequestsListWidget(widgetData);
|
|
1766
|
+
break;
|
|
1675
1767
|
case 'LIGHTHOUSE_REPORT':
|
|
1676
1768
|
response = await makeLighthouseReportWidget(widgetData);
|
|
1677
1769
|
break;
|
|
@@ -205,6 +205,10 @@ export class DOMStorageItemsView extends KeyValueStorageItemsView {
|
|
|
205
205
|
UI.Context.Context.instance().setFlavor(AiAssistanceModel.StorageItem.StorageItem, storageItem);
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
+
protected override isAiButtonEnabled(): boolean {
|
|
209
|
+
return UI.ActionRegistry.ActionRegistry.instance().hasAction('ai-assistance.storage-floating-button');
|
|
210
|
+
}
|
|
211
|
+
|
|
208
212
|
protected removeItem(key: string): void {
|
|
209
213
|
this.domStorage?.removeItem(key);
|
|
210
214
|
}
|