chrome-devtools-frontend 1.0.1598808 → 1.0.1599001
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/.agents/README.md +13 -0
- package/{agents/prompts/creating-a-model.md → .agents/skills/creating-a-model/SKILL.md} +7 -1
- package/{agents/prompts/devtools-imports.md → .agents/skills/devtools-imports/SKILL.md} +10 -5
- package/{agents/prompts/merging-devtools-module.md → .agents/skills/merging-devtools-module/SKILL.md} +5 -0
- package/{agents/prompts/ui-widgets.md → .agents/skills/ui-widgets/SKILL.md} +5 -0
- package/{agents/prompts/verification.md → .agents/skills/verification/SKILL.md} +5 -0
- package/front_end/core/host/GcaTypes.ts +518 -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/entrypoints/main/MainImpl.ts +0 -2
- package/front_end/generated/InspectorBackendCommands.ts +1 -1
- package/front_end/generated/protocol.ts +2 -1
- package/front_end/models/ai_assistance/AiConversation.ts +12 -1
- package/front_end/models/ai_assistance/AiHistoryStorage.snapshot.txt +1 -1
- package/front_end/models/ai_assistance/AiHistoryStorage.ts +1 -0
- package/front_end/models/ai_assistance/ConversationHandler.ts +8 -2
- package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +3 -18
- package/front_end/models/ai_assistance/agents/AiAgent.ts +26 -2
- package/front_end/models/ai_assistance/agents/BreakpointDebuggerAgent.ts +0 -1
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +1 -0
- package/front_end/models/ai_assistance/agents/ConversationSummaryAgent.ts +0 -1
- package/front_end/models/ai_assistance/agents/FileAgent.ts +0 -15
- package/front_end/models/ai_assistance/agents/NetworkAgent.ts +0 -5
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +48 -14
- package/front_end/models/ai_assistance/agents/PerformanceAnnotationsAgent.ts +0 -10
- package/front_end/models/ai_assistance/agents/StylingAgent.snapshot.txt +0 -6
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +0 -5
- package/front_end/models/emulation/DeviceModeModel.ts +5 -1
- package/front_end/models/emulation/EmulatedDevices.ts +3 -2
- package/front_end/models/issues_manager/SharedDictionaryIssue.ts +15 -5
- package/front_end/models/issues_manager/descriptions/sharedDictionaryUseErrorNoCorpCrossOriginNoCorsRequest.md +3 -0
- package/front_end/models/issues_manager/descriptions/sharedDictionaryWriteErrorNoCorpCossOriginNoCorsRequest.md +3 -0
- package/front_end/models/javascript_metadata/NativeFunctions.js +8 -0
- package/front_end/models/lighthouse/RunTypes.ts +41 -0
- package/front_end/models/lighthouse/lighthouse.ts +2 -0
- package/front_end/models/trace/ModelImpl.ts +4 -0
- package/front_end/models/trace/helpers/SamplesIntegrator.ts +1 -8
- package/front_end/models/trace/types/Configuration.ts +0 -5
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +84 -5
- package/front_end/panels/ai_assistance/components/ChatInput.ts +2 -0
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +107 -20
- package/front_end/panels/ai_assistance/components/chatMessage.css +61 -0
- package/front_end/panels/application/preloading/PreloadingView.ts +2 -4
- package/front_end/panels/application/preloading/components/PreloadingDetailsReportView.ts +6 -3
- package/front_end/panels/application/preloading/components/PreloadingString.ts +15 -2
- package/front_end/panels/application/preloading/helper/PreloadingForward.ts +31 -2
- package/front_end/panels/lighthouse/LighthouseController.ts +148 -162
- package/front_end/panels/lighthouse/LighthousePanel.ts +2 -7
- package/front_end/panels/lighthouse/LighthouseStartView.ts +7 -6
- package/front_end/panels/lighthouse/LighthouseStatusView.ts +3 -3
- package/front_end/panels/linear_memory_inspector/components/LinearMemoryInspector.ts +7 -3
- package/front_end/panels/sensors/SensorsView.ts +32 -22
- package/front_end/panels/settings/emulation/DevicesSettingsTab.ts +18 -4
- package/front_end/panels/timeline/StatusDialog.ts +159 -83
- package/front_end/panels/timeline/TimelineController.ts +0 -4
- package/front_end/panels/timeline/TimelinePanel.ts +29 -2
- package/front_end/panels/timeline/components/LiveMetricsView.ts +2 -2
- package/front_end/panels/timeline/components/Sidebar.ts +1 -1
- package/front_end/panels/timeline/components/SidebarInsightsTab.ts +1 -1
- package/front_end/panels/timeline/components/SidebarSingleInsightSet.ts +60 -27
- package/front_end/panels/timeline/components/insights/BaseInsightComponent.ts +53 -28
- package/front_end/panels/timeline/components/insights/baseInsightComponent.css +7 -0
- package/front_end/panels/timeline/components/insights/insights.ts +0 -2
- package/front_end/panels/timeline/timeline-meta.ts +11 -0
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/legacy/Widget.ts +5 -3
- package/front_end/ui/visual_logging/KnownContextValues.ts +1 -1
- package/package.json +1 -1
- package/agents/prompts/README.md +0 -18
- package/front_end/models/issues_manager/descriptions/sharedDictionaryUseErrorCrossOriginNoCorsRequest.md +0 -1
- package/front_end/panels/timeline/components/insights/InsightRenderer.ts +0 -93
|
@@ -1071,9 +1071,9 @@ export namespace Audits {
|
|
|
1071
1071
|
}
|
|
1072
1072
|
|
|
1073
1073
|
export const enum SharedDictionaryError {
|
|
1074
|
-
UseErrorCrossOriginNoCorsRequest = 'UseErrorCrossOriginNoCorsRequest',
|
|
1075
1074
|
UseErrorDictionaryLoadFailure = 'UseErrorDictionaryLoadFailure',
|
|
1076
1075
|
UseErrorMatchingDictionaryNotUsed = 'UseErrorMatchingDictionaryNotUsed',
|
|
1076
|
+
UseErrorNoCorpCrossOriginNoCorsRequest = 'UseErrorNoCorpCrossOriginNoCorsRequest',
|
|
1077
1077
|
UseErrorUnexpectedContentDictionaryHeader = 'UseErrorUnexpectedContentDictionaryHeader',
|
|
1078
1078
|
WriteErrorCossOriginNoCorsRequest = 'WriteErrorCossOriginNoCorsRequest',
|
|
1079
1079
|
WriteErrorDisallowedBySettings = 'WriteErrorDisallowedBySettings',
|
|
@@ -1084,6 +1084,7 @@ export namespace Audits {
|
|
|
1084
1084
|
WriteErrorInvalidStructuredHeader = 'WriteErrorInvalidStructuredHeader',
|
|
1085
1085
|
WriteErrorInvalidTTLField = 'WriteErrorInvalidTTLField',
|
|
1086
1086
|
WriteErrorNavigationRequest = 'WriteErrorNavigationRequest',
|
|
1087
|
+
WriteErrorNoCorpCossOriginNoCorsRequest = 'WriteErrorNoCorpCossOriginNoCorsRequest',
|
|
1087
1088
|
WriteErrorNoMatchField = 'WriteErrorNoMatchField',
|
|
1088
1089
|
WriteErrorNonIntegerTTLField = 'WriteErrorNonIntegerTTLField',
|
|
1089
1090
|
WriteErrorNonListMatchDestField = 'WriteErrorNonListMatchDestField',
|
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
import * as Common from '../../core/common/common.js';
|
|
5
5
|
import * as Host from '../../core/host/host.js';
|
|
6
|
+
import * as Platform from '../../core/platform/platform.js';
|
|
6
7
|
import * as Root from '../../core/root/root.js';
|
|
7
8
|
import * as SDK from '../../core/sdk/sdk.js';
|
|
8
9
|
import type * as Trace from '../../models/trace/trace.js';
|
|
9
10
|
import * as Greendev from '../greendev/greendev.js';
|
|
10
11
|
import type * as NetworkTimeCalculator from '../network_time_calculator/network_time_calculator.js';
|
|
11
12
|
|
|
13
|
+
import {AccessibilityAgent, AccessibilityContext} from './agents/AccessibilityAgent.js';
|
|
12
14
|
import {
|
|
13
15
|
type AiAgent,
|
|
14
16
|
type ContextDetail,
|
|
@@ -29,6 +31,7 @@ import {AiHistoryStorage, ConversationType, type SerializedConversation} from '.
|
|
|
29
31
|
import type {ChangeManager} from './ChangeManager.js';
|
|
30
32
|
|
|
31
33
|
export const NOT_FOUND_IMAGE_DATA = '';
|
|
34
|
+
export const CONTEXT_TITLE = 'Analyzing data';
|
|
32
35
|
const MAX_TITLE_LENGTH = 80;
|
|
33
36
|
|
|
34
37
|
export function generateContextDetailsMarkdown(details: ContextDetail[]): string {
|
|
@@ -155,6 +158,8 @@ export class AiConversation {
|
|
|
155
158
|
this.#updateAgent(ConversationType.NETWORK);
|
|
156
159
|
} else if (updateContext instanceof PerformanceTraceContext) {
|
|
157
160
|
this.#updateAgent(ConversationType.PERFORMANCE);
|
|
161
|
+
} else if (updateContext instanceof AccessibilityContext) {
|
|
162
|
+
this.#updateAgent(ConversationType.ACCESSIBILITY);
|
|
158
163
|
}
|
|
159
164
|
}
|
|
160
165
|
}
|
|
@@ -205,7 +210,7 @@ export class AiConversation {
|
|
|
205
210
|
break;
|
|
206
211
|
}
|
|
207
212
|
case ResponseType.CONTEXT: {
|
|
208
|
-
contentParts.push(`### ${
|
|
213
|
+
contentParts.push(`### ${CONTEXT_TITLE}`);
|
|
209
214
|
if (item.details && item.details.length > 0) {
|
|
210
215
|
contentParts.push(generateContextDetailsMarkdown(item.details));
|
|
211
216
|
}
|
|
@@ -343,10 +348,16 @@ export class AiConversation {
|
|
|
343
348
|
}
|
|
344
349
|
break;
|
|
345
350
|
}
|
|
351
|
+
case ConversationType.ACCESSIBILITY: {
|
|
352
|
+
this.#agent = new AccessibilityAgent(options);
|
|
353
|
+
break;
|
|
354
|
+
}
|
|
346
355
|
case ConversationType.NONE: {
|
|
347
356
|
this.#agent = new ContextSelectionAgent(options);
|
|
348
357
|
break;
|
|
349
358
|
}
|
|
359
|
+
default:
|
|
360
|
+
Platform.assertNever(type, 'Unknown conversation type');
|
|
350
361
|
}
|
|
351
362
|
}
|
|
352
363
|
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
import {NetworkAgent, RequestContext} from './agents/NetworkAgent.js';
|
|
20
20
|
import type {PerformanceTraceContext} from './agents/PerformanceAgent.js';
|
|
21
21
|
import {NodeContext, StylingAgent} from './agents/StylingAgent.js';
|
|
22
|
-
import {AiConversation} from './AiConversation.js';
|
|
22
|
+
import {AiConversation, CONTEXT_TITLE} from './AiConversation.js';
|
|
23
23
|
import {
|
|
24
24
|
ConversationType,
|
|
25
25
|
} from './AiHistoryStorage.js';
|
|
@@ -235,12 +235,18 @@ export class ConversationHandler extends Common.ObjectWrapper.ObjectWrapper<Even
|
|
|
235
235
|
if (data.type !== ResponseType.ANSWER || data.complete) {
|
|
236
236
|
devToolsLogs.push(data);
|
|
237
237
|
}
|
|
238
|
-
if (data.type === ResponseType.
|
|
238
|
+
if (data.type === ResponseType.TITLE) {
|
|
239
239
|
yield {
|
|
240
240
|
type: ExternalRequestResponseType.NOTIFICATION,
|
|
241
241
|
message: data.title,
|
|
242
242
|
};
|
|
243
243
|
}
|
|
244
|
+
if (data.type === ResponseType.CONTEXT) {
|
|
245
|
+
yield {
|
|
246
|
+
type: ExternalRequestResponseType.NOTIFICATION,
|
|
247
|
+
message: CONTEXT_TITLE,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
244
250
|
if (data.type === ResponseType.SIDE_EFFECT) {
|
|
245
251
|
data.confirm(true);
|
|
246
252
|
}
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
|
|
5
5
|
import * as Host from '../../../core/host/host.js';
|
|
6
|
-
import * as i18n from '../../../core/i18n/i18n.js';
|
|
7
6
|
import * as Root from '../../../core/root/root.js';
|
|
8
7
|
import type * as LHModel from '../../lighthouse/lighthouse.js';
|
|
9
8
|
|
|
@@ -23,26 +22,14 @@ import {
|
|
|
23
22
|
*/
|
|
24
23
|
const preamble = `You are an accessibility agent.
|
|
25
24
|
|
|
25
|
+
However, you also include a little pun or funny joke in every response to lighten the mood.
|
|
26
|
+
|
|
26
27
|
# Considerations
|
|
27
28
|
* Keep your analysis concise and focused, highlighting only the most critical aspects for a software engineer.
|
|
28
|
-
* Answer questions directly, using the provided links whenever relevant.
|
|
29
|
-
* Always double-check links to make sure they are complete and correct.
|
|
30
29
|
* **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.
|
|
31
30
|
`;
|
|
32
31
|
|
|
33
|
-
|
|
34
|
-
* Strings that don't need to be translated at this time.
|
|
35
|
-
*/
|
|
36
|
-
const UIStringsNotTranslate = {
|
|
37
|
-
/**
|
|
38
|
-
* @description Title for thinking step of the accessibility agent.
|
|
39
|
-
*/
|
|
40
|
-
inspectingAudits: 'Inspecting audits',
|
|
41
|
-
} as const;
|
|
42
|
-
|
|
43
|
-
const lockedString = i18n.i18n.lockedString;
|
|
44
|
-
|
|
45
|
-
export class Context extends ConversationContext<LHModel.ReporterTypes.ReportJSON> {
|
|
32
|
+
export class AccessibilityContext extends ConversationContext<LHModel.ReporterTypes.ReportJSON> {
|
|
46
33
|
#lh: LHModel.ReporterTypes.ReportJSON;
|
|
47
34
|
|
|
48
35
|
constructor(report: LHModel.ReporterTypes.ReportJSON) {
|
|
@@ -76,7 +63,6 @@ export class AccessibilityAgent extends AiAgent<LHModel.ReporterTypes.ReportJSON
|
|
|
76
63
|
readonly clientFeature = Host.AidaClient.ClientFeature.CHROME_ACCESSIBILITY_AGENT;
|
|
77
64
|
|
|
78
65
|
get userTier(): string|undefined {
|
|
79
|
-
// TODO(b/491772868): tidy up userTier & feature flags in the backend.
|
|
80
66
|
return Root.Runtime.hostConfig.devToolsFreestyler?.userTier;
|
|
81
67
|
}
|
|
82
68
|
|
|
@@ -100,7 +86,6 @@ export class AccessibilityAgent extends AiAgent<LHModel.ReporterTypes.ReportJSON
|
|
|
100
86
|
|
|
101
87
|
yield {
|
|
102
88
|
type: ResponseType.CONTEXT,
|
|
103
|
-
title: lockedString(UIStringsNotTranslate.inspectingAudits),
|
|
104
89
|
details: createContextDetails(selectedFile),
|
|
105
90
|
};
|
|
106
91
|
}
|
|
@@ -70,7 +70,6 @@ export interface ContextDetail {
|
|
|
70
70
|
}
|
|
71
71
|
export interface ContextResponse {
|
|
72
72
|
type: ResponseType.CONTEXT;
|
|
73
|
-
title: string;
|
|
74
73
|
details: [ContextDetail, ...ContextDetail[]];
|
|
75
74
|
widgets?: AiWidget[];
|
|
76
75
|
}
|
|
@@ -102,6 +101,7 @@ export interface ContextChangeResponse {
|
|
|
102
101
|
*/
|
|
103
102
|
description: string;
|
|
104
103
|
context: ConversationContext<unknown>;
|
|
104
|
+
widgets?: AiWidget[];
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
interface SerializedSideEffectResponse extends Omit<SideEffectResponse, 'confirm'> {}
|
|
@@ -253,11 +253,33 @@ export interface DomTreeAiWidget {
|
|
|
253
253
|
name: 'DOM_TREE';
|
|
254
254
|
data: {
|
|
255
255
|
root: SDK.DOMModel.DOMNodeSnapshot,
|
|
256
|
+
networkRequest?: {
|
|
257
|
+
url: string,
|
|
258
|
+
size: number,
|
|
259
|
+
resourceType: Protocol.Network.ResourceType,
|
|
260
|
+
mimeType: string,
|
|
261
|
+
imageUrl?: string,
|
|
262
|
+
},
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export interface PerformanceTraceAiWidget {
|
|
267
|
+
name: 'PERFORMANCE_TRACE';
|
|
268
|
+
data: {
|
|
269
|
+
parsedTrace: Trace.TraceModel.ParsedTrace,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export interface LcpBreakdownAiWidget {
|
|
274
|
+
name: 'LCP_BREAKDOWN';
|
|
275
|
+
data: {
|
|
276
|
+
lcpData: Trace.Insights.Models.LCPBreakdown.LCPBreakdownInsightModel,
|
|
256
277
|
};
|
|
257
278
|
}
|
|
258
279
|
|
|
259
280
|
// This type will grow as we add more widgets.
|
|
260
|
-
export type AiWidget = ComputedStyleAiWidget|CoreVitalsAiWidget|StylePropertiesAiWidget|DomTreeAiWidget
|
|
281
|
+
export type AiWidget = ComputedStyleAiWidget|CoreVitalsAiWidget|StylePropertiesAiWidget|DomTreeAiWidget|
|
|
282
|
+
PerformanceTraceAiWidget|LcpBreakdownAiWidget;
|
|
261
283
|
|
|
262
284
|
export type FunctionCallHandlerResult<Result> = {
|
|
263
285
|
requiresApproval: true,
|
|
@@ -272,6 +294,7 @@ export type FunctionCallHandlerResult<Result> = {
|
|
|
272
294
|
}|{
|
|
273
295
|
context: ConversationContext<unknown>,
|
|
274
296
|
description: string,
|
|
297
|
+
widgets?: AiWidget[],
|
|
275
298
|
}|{
|
|
276
299
|
error: string,
|
|
277
300
|
};
|
|
@@ -692,6 +715,7 @@ export abstract class AiAgent<T> {
|
|
|
692
715
|
type: ResponseType.CONTEXT_CHANGE,
|
|
693
716
|
description: result.description,
|
|
694
717
|
context: result.context,
|
|
718
|
+
widgets: result.widgets,
|
|
695
719
|
};
|
|
696
720
|
|
|
697
721
|
return;
|
|
@@ -608,7 +608,6 @@ export class BreakpointDebuggerAgent extends AiAgent<Workspace.UISourceCode.UILo
|
|
|
608
608
|
}
|
|
609
609
|
yield {
|
|
610
610
|
type: ResponseType.CONTEXT,
|
|
611
|
-
title: 'Analyzing breakpoint location',
|
|
612
611
|
details: [{title: 'Location', text: selectedBreakpoint.getTitle()}]
|
|
613
612
|
};
|
|
614
613
|
}
|
|
@@ -278,6 +278,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
278
278
|
return {
|
|
279
279
|
context: PerformanceTraceContext.fromParsedTrace(result),
|
|
280
280
|
description: 'User recorded a performance trace',
|
|
281
|
+
widgets: [{name: 'PERFORMANCE_TRACE', data: {parsedTrace: result}}]
|
|
281
282
|
};
|
|
282
283
|
}
|
|
283
284
|
});
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
|
|
5
5
|
import * as Host from '../../../core/host/host.js';
|
|
6
|
-
import * as i18n from '../../../core/i18n/i18n.js';
|
|
7
6
|
import * as Root from '../../../core/root/root.js';
|
|
8
7
|
import type * as Workspace from '../../workspace/workspace.js';
|
|
9
8
|
import {FileFormatter} from '../data_formatters/FileFormatter.js';
|
|
@@ -62,18 +61,6 @@ External Resources:
|
|
|
62
61
|
MDN Web Docs: JavaScript Functions: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions
|
|
63
62
|
`;
|
|
64
63
|
|
|
65
|
-
/*
|
|
66
|
-
* Strings that don't need to be translated at this time.
|
|
67
|
-
*/
|
|
68
|
-
const UIStringsNotTranslate = {
|
|
69
|
-
/**
|
|
70
|
-
* @description Title for thinking step of File agent.
|
|
71
|
-
*/
|
|
72
|
-
analyzingFile: 'Analyzing file',
|
|
73
|
-
} as const;
|
|
74
|
-
|
|
75
|
-
const lockedString = i18n.i18n.lockedString;
|
|
76
|
-
|
|
77
64
|
export class FileContext extends ConversationContext<Workspace.UISourceCode.UISourceCode> {
|
|
78
65
|
#file: Workspace.UISourceCode.UISourceCode;
|
|
79
66
|
|
|
@@ -118,7 +105,6 @@ export class FileAgent extends AiAgent<Workspace.UISourceCode.UISourceCode> {
|
|
|
118
105
|
modelId,
|
|
119
106
|
};
|
|
120
107
|
}
|
|
121
|
-
|
|
122
108
|
async *
|
|
123
109
|
handleContextDetails(selectedFile: ConversationContext<Workspace.UISourceCode.UISourceCode>|null):
|
|
124
110
|
AsyncGenerator<ContextResponse, void, void> {
|
|
@@ -128,7 +114,6 @@ export class FileAgent extends AiAgent<Workspace.UISourceCode.UISourceCode> {
|
|
|
128
114
|
|
|
129
115
|
yield {
|
|
130
116
|
type: ResponseType.CONTEXT,
|
|
131
|
-
title: lockedString(UIStringsNotTranslate.analyzingFile),
|
|
132
117
|
details: createContextDetailsForFileAgent(selectedFile),
|
|
133
118
|
};
|
|
134
119
|
}
|
|
@@ -60,10 +60,6 @@ This request aims to retrieve a list of products matching the search query "lapt
|
|
|
60
60
|
* Strings that don't need to be translated at this time.
|
|
61
61
|
*/
|
|
62
62
|
const UIStringsNotTranslate = {
|
|
63
|
-
/**
|
|
64
|
-
* @description Title for thinking step of Network agent.
|
|
65
|
-
*/
|
|
66
|
-
analyzingNetworkData: 'Analyzing network data',
|
|
67
63
|
/**
|
|
68
64
|
* @description Heading text for the block that shows the network request details.
|
|
69
65
|
*/
|
|
@@ -144,7 +140,6 @@ export class NetworkAgent extends AiAgent<SDK.NetworkRequest.NetworkRequest> {
|
|
|
144
140
|
|
|
145
141
|
yield {
|
|
146
142
|
type: ResponseType.CONTEXT,
|
|
147
|
-
title: lockedString(UIStringsNotTranslate.analyzingNetworkData),
|
|
148
143
|
details: await createContextDetailsForNetworkAgent(selectedNetworkRequest),
|
|
149
144
|
};
|
|
150
145
|
}
|
|
@@ -11,7 +11,9 @@ import * as SDK from '../../../core/sdk/sdk.js';
|
|
|
11
11
|
import type * as Protocol from '../../../generated/protocol.js';
|
|
12
12
|
import * as Tracing from '../../../services/tracing/tracing.js';
|
|
13
13
|
import * as Annotations from '../../annotations/annotations.js';
|
|
14
|
+
import * as Logs from '../../logs/logs.js';
|
|
14
15
|
import * as SourceMapScopes from '../../source_map_scopes/source_map_scopes.js';
|
|
16
|
+
import * as TextUtils from '../../text_utils/text_utils.js';
|
|
15
17
|
import * as Trace from '../../trace/trace.js';
|
|
16
18
|
import {
|
|
17
19
|
PerformanceInsightFormatter,
|
|
@@ -35,10 +37,6 @@ import {
|
|
|
35
37
|
} from './AiAgent.js';
|
|
36
38
|
|
|
37
39
|
const UIStringsNotTranslated = {
|
|
38
|
-
/**
|
|
39
|
-
*@description Shown when the agent is investigating a trace
|
|
40
|
-
*/
|
|
41
|
-
analyzingTrace: 'Analyzing trace',
|
|
42
40
|
/**
|
|
43
41
|
* @description Shown when the agent is investigating network activity
|
|
44
42
|
*/
|
|
@@ -318,7 +316,6 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
318
316
|
#formatter: PerformanceTraceFormatter|null = null;
|
|
319
317
|
#lastEventForEnhancedQuery: Trace.Types.Events.Event|undefined;
|
|
320
318
|
#lastInsightForEnhancedQuery: Trace.Insights.Types.InsightModel|undefined;
|
|
321
|
-
#hasShownAnalyzeTraceContext = false;
|
|
322
319
|
|
|
323
320
|
/**
|
|
324
321
|
* Cache of all function calls made by the agent. This allows us to include (as a
|
|
@@ -379,10 +376,6 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
379
376
|
return;
|
|
380
377
|
}
|
|
381
378
|
|
|
382
|
-
if (this.#hasShownAnalyzeTraceContext) {
|
|
383
|
-
return;
|
|
384
|
-
}
|
|
385
|
-
|
|
386
379
|
const widgets: AiWidget[] = [];
|
|
387
380
|
const primaryInsightSet = context.getItem().primaryInsightSet;
|
|
388
381
|
if (primaryInsightSet) {
|
|
@@ -397,7 +390,6 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
397
390
|
|
|
398
391
|
yield {
|
|
399
392
|
type: ResponseType.CONTEXT,
|
|
400
|
-
title: lockedString(UIStringsNotTranslated.analyzingTrace),
|
|
401
393
|
details: [
|
|
402
394
|
{
|
|
403
395
|
title: 'Trace',
|
|
@@ -406,8 +398,6 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
406
398
|
],
|
|
407
399
|
widgets,
|
|
408
400
|
};
|
|
409
|
-
|
|
410
|
-
this.#hasShownAnalyzeTraceContext = true;
|
|
411
401
|
}
|
|
412
402
|
|
|
413
403
|
#callTreeContextSet = new WeakSet();
|
|
@@ -752,7 +742,8 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
752
742
|
const details = new PerformanceInsightFormatter(focus, insight).formatInsight();
|
|
753
743
|
|
|
754
744
|
const widgets: AiWidget[] = [];
|
|
755
|
-
if (
|
|
745
|
+
if (Trace.Insights.Models.LCPDiscovery.isLCPDiscoveryInsight(insight) ||
|
|
746
|
+
Trace.Insights.Models.LCPBreakdown.isLCPBreakdownInsight(insight)) {
|
|
756
747
|
const lcpMetric = Trace.Insights.Common.getLCP(insightSet);
|
|
757
748
|
const lcpEvent = lcpMetric?.event;
|
|
758
749
|
if (lcpEvent && Trace.Types.Events.isAnyLargestContentfulPaintCandidate(lcpEvent)) {
|
|
@@ -767,15 +758,38 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
767
758
|
const node = nodeMap?.get(nodeId);
|
|
768
759
|
if (node) {
|
|
769
760
|
const snapshot = await node.takeSnapshot();
|
|
761
|
+
let networkRequest;
|
|
762
|
+
const lcpSyntheticRequest = insight.lcpRequest;
|
|
763
|
+
if (lcpSyntheticRequest) {
|
|
764
|
+
networkRequest = {
|
|
765
|
+
url: lcpSyntheticRequest.args.data.url,
|
|
766
|
+
size: lcpSyntheticRequest.args.data.decodedBodyLength ??
|
|
767
|
+
lcpSyntheticRequest.args.data.encodedDataLength ?? 0,
|
|
768
|
+
resourceType: lcpSyntheticRequest.args.data.resourceType,
|
|
769
|
+
mimeType: lcpSyntheticRequest.args.data.mimeType ?? '',
|
|
770
|
+
imageUrl: await this.#getNetworkRequestImageData(lcpSyntheticRequest),
|
|
771
|
+
};
|
|
772
|
+
}
|
|
770
773
|
widgets.push({
|
|
771
774
|
name: 'DOM_TREE',
|
|
772
|
-
data: {
|
|
775
|
+
data: {
|
|
776
|
+
root: snapshot,
|
|
777
|
+
networkRequest,
|
|
778
|
+
},
|
|
773
779
|
});
|
|
774
780
|
processedNodeIds.add(nodeId);
|
|
775
781
|
}
|
|
776
782
|
}
|
|
777
783
|
}
|
|
778
784
|
}
|
|
785
|
+
if (params.insightName === 'LCPBreakdown') {
|
|
786
|
+
widgets.push({
|
|
787
|
+
name: 'LCP_BREAKDOWN',
|
|
788
|
+
data: {
|
|
789
|
+
lcpData: insight as Trace.Insights.Models.LCPBreakdown.LCPBreakdownInsightModel,
|
|
790
|
+
},
|
|
791
|
+
});
|
|
792
|
+
}
|
|
779
793
|
}
|
|
780
794
|
|
|
781
795
|
const key = `getInsightDetails('${params.insightSetId}', '${params.insightName}')`;
|
|
@@ -1258,4 +1272,24 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
1258
1272
|
Annotations.AnnotationRepository.instance().addNetworkRequestAnnotation(annotationMessage, requestId);
|
|
1259
1273
|
return {result: {success: true}};
|
|
1260
1274
|
}
|
|
1275
|
+
|
|
1276
|
+
async #getNetworkRequestImageData(lcpRequest: Trace.Types.Events.SyntheticNetworkRequest): Promise<string|undefined> {
|
|
1277
|
+
const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
|
|
1278
|
+
const networkManager = target?.model(SDK.NetworkManager.NetworkManager);
|
|
1279
|
+
if (!target || !networkManager) {
|
|
1280
|
+
return undefined;
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
const networkLog = Logs.NetworkLog.NetworkLog.instance();
|
|
1284
|
+
const requestId = lcpRequest.args.data.requestId;
|
|
1285
|
+
const sdkRequest = networkLog.requestByManagerAndId(networkManager, requestId);
|
|
1286
|
+
|
|
1287
|
+
if (sdkRequest?.contentType().isImage()) {
|
|
1288
|
+
const contentData = await sdkRequest.requestContentData();
|
|
1289
|
+
if (!TextUtils.ContentData.ContentData.isError(contentData)) {
|
|
1290
|
+
return contentData.asDataUrl() ?? undefined;
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
return undefined;
|
|
1294
|
+
}
|
|
1261
1295
|
}
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
|
|
5
5
|
import * as Host from '../../../core/host/host.js';
|
|
6
|
-
import * as i18n from '../../../core/i18n/i18n.js';
|
|
7
6
|
import * as Root from '../../../core/root/root.js';
|
|
8
7
|
import type {AICallTree} from '../performance/AICallTree.js';
|
|
9
8
|
import type {AgentFocus} from '../performance/AIContext.js';
|
|
@@ -11,14 +10,6 @@ import type {AgentFocus} from '../performance/AIContext.js';
|
|
|
11
10
|
import {AiAgent, type ContextResponse, type ConversationContext, type RequestOptions, ResponseType} from './AiAgent.js';
|
|
12
11
|
import {PerformanceTraceContext} from './PerformanceAgent.js';
|
|
13
12
|
|
|
14
|
-
const UIStringsNotTranslated = {
|
|
15
|
-
analyzingCallTree: 'Analyzing call tree',
|
|
16
|
-
/**
|
|
17
|
-
* @description Shown when the agent is investigating network activity
|
|
18
|
-
*/
|
|
19
|
-
} as const;
|
|
20
|
-
const lockedString = i18n.i18n.lockedString;
|
|
21
|
-
|
|
22
13
|
/**
|
|
23
14
|
* Preamble clocks in at ~970 tokens.
|
|
24
15
|
* The prose is around 4.5 chars per token.
|
|
@@ -124,7 +115,6 @@ export class PerformanceAnnotationsAgent extends AiAgent<AgentFocus> {
|
|
|
124
115
|
|
|
125
116
|
yield {
|
|
126
117
|
type: ResponseType.CONTEXT,
|
|
127
|
-
title: lockedString(UIStringsNotTranslated.analyzingCallTree),
|
|
128
118
|
details: [
|
|
129
119
|
{
|
|
130
120
|
title: 'Selected call tree',
|
|
@@ -216,7 +216,6 @@ Content:
|
|
|
216
216
|
[
|
|
217
217
|
{
|
|
218
218
|
"type": "context",
|
|
219
|
-
"title": "Analyzing the prompt",
|
|
220
219
|
"details": [
|
|
221
220
|
{
|
|
222
221
|
"title": "Data used",
|
|
@@ -296,7 +295,6 @@ Content:
|
|
|
296
295
|
[
|
|
297
296
|
{
|
|
298
297
|
"type": "context",
|
|
299
|
-
"title": "Analyzing the prompt",
|
|
300
298
|
"details": [
|
|
301
299
|
{
|
|
302
300
|
"title": "Data used",
|
|
@@ -321,7 +319,6 @@ Content:
|
|
|
321
319
|
[
|
|
322
320
|
{
|
|
323
321
|
"type": "context",
|
|
324
|
-
"title": "Analyzing the prompt",
|
|
325
322
|
"details": [
|
|
326
323
|
{
|
|
327
324
|
"title": "Data used",
|
|
@@ -349,7 +346,6 @@ Content:
|
|
|
349
346
|
[
|
|
350
347
|
{
|
|
351
348
|
"type": "context",
|
|
352
|
-
"title": "Analyzing the prompt",
|
|
353
349
|
"details": [
|
|
354
350
|
{
|
|
355
351
|
"title": "Data used",
|
|
@@ -374,7 +370,6 @@ Content:
|
|
|
374
370
|
[
|
|
375
371
|
{
|
|
376
372
|
"type": "context",
|
|
377
|
-
"title": "Analyzing the prompt",
|
|
378
373
|
"details": [
|
|
379
374
|
{
|
|
380
375
|
"title": "Data used",
|
|
@@ -397,7 +392,6 @@ Content:
|
|
|
397
392
|
[
|
|
398
393
|
{
|
|
399
394
|
"type": "context",
|
|
400
|
-
"title": "Analyzing the prompt",
|
|
401
395
|
"details": [
|
|
402
396
|
{
|
|
403
397
|
"title": "Data used",
|
|
@@ -37,10 +37,6 @@ import {
|
|
|
37
37
|
* Strings that don't need to be translated at this time.
|
|
38
38
|
*/
|
|
39
39
|
const UIStringsNotTranslate = {
|
|
40
|
-
/**
|
|
41
|
-
* @description Title for context details for Freestyler.
|
|
42
|
-
*/
|
|
43
|
-
analyzingThePrompt: 'Analyzing the prompt',
|
|
44
40
|
/**
|
|
45
41
|
* @description Heading text for context details of Freestyler agent.
|
|
46
42
|
*/
|
|
@@ -1045,7 +1041,6 @@ const data = {
|
|
|
1045
1041
|
}
|
|
1046
1042
|
yield {
|
|
1047
1043
|
type: ResponseType.CONTEXT,
|
|
1048
|
-
title: lockedString(UIStringsNotTranslate.analyzingThePrompt),
|
|
1049
1044
|
details: [{
|
|
1050
1045
|
title: lockedString(UIStringsNotTranslate.dataUsed),
|
|
1051
1046
|
text: await StylingAgent.describeElement(selectedElement.getItem()),
|
|
@@ -680,7 +680,11 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
|
680
680
|
}
|
|
681
681
|
|
|
682
682
|
private applyUserAgent(userAgent: string, userAgentMetadata: Protocol.Emulation.UserAgentMetadata|null): void {
|
|
683
|
-
|
|
683
|
+
// When the user agent string is empty (e.g. custom desktop device without
|
|
684
|
+
// a UA override), metadata must also be cleared. The backend rejects
|
|
685
|
+
// setUserAgentOverride calls that provide metadata without a UA string.
|
|
686
|
+
SDK.NetworkManager.MultitargetNetworkManager.instance().setUserAgentOverride(
|
|
687
|
+
userAgent, userAgent ? userAgentMetadata : null);
|
|
684
688
|
}
|
|
685
689
|
|
|
686
690
|
private applyDeviceMetrics(
|
|
@@ -201,7 +201,8 @@ export class EmulatedDevice {
|
|
|
201
201
|
const rawUserAgent = (parseValue(json, 'user-agent', 'string') as string);
|
|
202
202
|
result.userAgent = SDK.NetworkManager.MultitargetNetworkManager.patchUserAgentWithChromeVersion(rawUserAgent);
|
|
203
203
|
|
|
204
|
-
|
|
204
|
+
const userAgentMetadata = parseValue(json, 'user-agent-metadata', 'object', null);
|
|
205
|
+
result.userAgentMetadata = result.userAgent ? userAgentMetadata : null;
|
|
205
206
|
|
|
206
207
|
const capabilities = parseValue(json, 'capabilities', 'object', []);
|
|
207
208
|
if (!Array.isArray(capabilities)) {
|
|
@@ -366,7 +367,7 @@ export class EmulatedDevice {
|
|
|
366
367
|
json['foldable-screen'] = this.isFoldableScreen;
|
|
367
368
|
json['show'] = this.#show;
|
|
368
369
|
|
|
369
|
-
if (this.userAgentMetadata) {
|
|
370
|
+
if (this.userAgent && this.userAgentMetadata) {
|
|
370
371
|
json['user-agent-metadata'] = this.userAgentMetadata;
|
|
371
372
|
}
|
|
372
373
|
|
|
@@ -23,7 +23,7 @@ const str_ = i18n.i18n.registerUIStrings('models/issues_manager/SharedDictionary
|
|
|
23
23
|
const i18nLazyString = i18n.i18n.getLazilyComputedLocalizedString.bind(undefined, str_);
|
|
24
24
|
|
|
25
25
|
export const enum IssueCode {
|
|
26
|
-
|
|
26
|
+
USE_ERROR_NO_CORP_CROSS_ORIGIN_NO_CORS_REQUEST = 'SharedDictionaryIssue::UseErrorNoCorpCrossOriginNoCorsRequest',
|
|
27
27
|
USE_ERROR_DICTIONARY_LOAD_FAILURE = 'SharedDictionaryIssue::UseErrorDictionaryLoadFailure',
|
|
28
28
|
USE_ERROR_MATCHING_DICTIONARY_NOT_USED = 'SharedDictionaryIssue::UseErrorMatchingDictionaryNotUsed',
|
|
29
29
|
USE_ERROR_UNEXPECTED_CONTENT_DICTIONARY_HEADER = 'SharedDictionaryIssue::UseErrorUnexpectedContentDictionaryHeader',
|
|
@@ -36,6 +36,7 @@ export const enum IssueCode {
|
|
|
36
36
|
WRITE_ERROR_INVALID_STRUCTURED_HEADER = 'SharedDictionaryIssue::WriteErrorInvalidStructuredHeader',
|
|
37
37
|
WRITE_ERROR_INVALID_TTL_FIELD = 'SharedDictionaryIssue::WriteErrorInvalidTTLField',
|
|
38
38
|
WRITE_ERROR_NAVIGATION_REQUEST = 'SharedDictionaryIssue::WriteErrorNavigationRequest',
|
|
39
|
+
WRITE_ERROR_NO_CORP_COSS_ORIGIN_NO_CORS_REQUEST = 'SharedDictionaryIssue::WriteErrorNoCorpCossOriginNoCorsRequest',
|
|
39
40
|
WRITE_ERROR_NO_MATCH_FIELD = 'SharedDictionaryIssue::WriteErrorNoMatchField',
|
|
40
41
|
WRITE_ERROR_NON_INTEGER_TTL_FIELD = 'SharedDictionaryIssue::WriteErrorNonIntegerTTLField',
|
|
41
42
|
WRITE_ERROR_NON_LIST_MATCH_DEST_FIELD = 'SharedDictionaryIssue::WriteErrorNonListMatchDestField',
|
|
@@ -53,8 +54,8 @@ export const enum IssueCode {
|
|
|
53
54
|
|
|
54
55
|
function getIssueCode(details: Protocol.Audits.SharedDictionaryIssueDetails): IssueCode {
|
|
55
56
|
switch (details.sharedDictionaryError) {
|
|
56
|
-
case Protocol.Audits.SharedDictionaryError.
|
|
57
|
-
return IssueCode.
|
|
57
|
+
case Protocol.Audits.SharedDictionaryError.UseErrorNoCorpCrossOriginNoCorsRequest:
|
|
58
|
+
return IssueCode.USE_ERROR_NO_CORP_CROSS_ORIGIN_NO_CORS_REQUEST;
|
|
58
59
|
case Protocol.Audits.SharedDictionaryError.UseErrorDictionaryLoadFailure:
|
|
59
60
|
return IssueCode.USE_ERROR_DICTIONARY_LOAD_FAILURE;
|
|
60
61
|
case Protocol.Audits.SharedDictionaryError.UseErrorMatchingDictionaryNotUsed:
|
|
@@ -79,6 +80,8 @@ function getIssueCode(details: Protocol.Audits.SharedDictionaryIssueDetails): Is
|
|
|
79
80
|
return IssueCode.WRITE_ERROR_INVALID_TTL_FIELD;
|
|
80
81
|
case Protocol.Audits.SharedDictionaryError.WriteErrorNavigationRequest:
|
|
81
82
|
return IssueCode.WRITE_ERROR_NAVIGATION_REQUEST;
|
|
83
|
+
case Protocol.Audits.SharedDictionaryError.WriteErrorNoCorpCossOriginNoCorsRequest:
|
|
84
|
+
return IssueCode.WRITE_ERROR_NO_CORP_COSS_ORIGIN_NO_CORS_REQUEST;
|
|
82
85
|
case Protocol.Audits.SharedDictionaryError.WriteErrorNoMatchField:
|
|
83
86
|
return IssueCode.WRITE_ERROR_NO_MATCH_FIELD;
|
|
84
87
|
case Protocol.Audits.SharedDictionaryError.WriteErrorNonIntegerTTLField:
|
|
@@ -168,9 +171,9 @@ const specLinks = [{
|
|
|
168
171
|
const issueDescriptions = new Map<Protocol.Audits.SharedDictionaryError, LazyMarkdownIssueDescription>([
|
|
169
172
|
|
|
170
173
|
[
|
|
171
|
-
Protocol.Audits.SharedDictionaryError.
|
|
174
|
+
Protocol.Audits.SharedDictionaryError.UseErrorNoCorpCrossOriginNoCorsRequest,
|
|
172
175
|
{
|
|
173
|
-
file: '
|
|
176
|
+
file: 'sharedDictionaryUseErrorNoCorpCrossOriginNoCorsRequest.md',
|
|
174
177
|
links: specLinks,
|
|
175
178
|
},
|
|
176
179
|
],
|
|
@@ -258,6 +261,13 @@ const issueDescriptions = new Map<Protocol.Audits.SharedDictionaryError, LazyMar
|
|
|
258
261
|
links: specLinks,
|
|
259
262
|
},
|
|
260
263
|
],
|
|
264
|
+
[
|
|
265
|
+
Protocol.Audits.SharedDictionaryError.WriteErrorNoCorpCossOriginNoCorsRequest,
|
|
266
|
+
{
|
|
267
|
+
file: 'sharedDictionaryWriteErrorNoCorpCossOriginNoCorsRequest.md',
|
|
268
|
+
links: specLinks,
|
|
269
|
+
},
|
|
270
|
+
],
|
|
261
271
|
[
|
|
262
272
|
Protocol.Audits.SharedDictionaryError.WriteErrorNoMatchField,
|
|
263
273
|
{
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
# Dictionary compression cannot be used for cross-origin no-cors requests without a Cross-Origin-Resource-Policy response header
|
|
2
|
+
|
|
3
|
+
To use dictionary compression for a cross-origin no-cors request, the response must have a `Cross-Origin-Resource-Policy: cross-origin` header. Without it, the response can not be decoded and will fail.
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
# A cross-origin no-cors response cannot be stored as a shared dictionary for future requests without a Cross-Origin-Resource-Policy response header
|
|
2
|
+
|
|
3
|
+
To store a response from a cross-origin no-cors request as a shared dictionary for future requests, the response must have a `Cross-Origin-Resource-Policy: cross-origin` header. Without it, the response will not be stored as a dictionary.
|