chrome-devtools-frontend 1.0.1597448 → 1.0.1598808
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/docs/ui_engineering.md +6 -6
- package/front_end/core/host/AidaClient.ts +6 -0
- package/front_end/core/sdk/CPUThrottlingManager.ts +5 -1
- package/front_end/core/sdk/CSSMatchedStyles.ts +2 -0
- package/front_end/core/sdk/CSSPropertyParserMatchers.ts +28 -0
- package/front_end/models/ai_assistance/AiConversation.ts +40 -22
- package/front_end/models/ai_assistance/ChangeManager.ts +16 -0
- package/front_end/models/ai_assistance/ExtensionScope.ts +11 -3
- package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +127 -0
- package/front_end/models/ai_assistance/agents/AiAgent.ts +35 -6
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.snapshot.txt +1 -1
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +11 -8
- package/front_end/models/ai_assistance/agents/ConversationSummaryAgent.ts +109 -0
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +30 -1
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +34 -4
- package/front_end/models/ai_assistance/ai_assistance.ts +4 -0
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +27 -0
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +21 -0
- package/front_end/models/trace/Processor.ts +1 -0
- package/front_end/models/trace/handlers/PageLoadMetricsHandler.ts +33 -0
- package/front_end/models/trace/insights/CharacterSet.ts +172 -0
- package/front_end/models/trace/insights/Models.ts +1 -0
- package/front_end/models/trace/insights/types.ts +1 -0
- package/front_end/models/trace/types/TraceEvents.ts +17 -0
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +22 -12
- package/front_end/panels/ai_assistance/PatchWidget.ts +1 -1
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +131 -63
- package/front_end/panels/ai_assistance/components/ChatView.ts +1 -1
- package/front_end/panels/ai_assistance/components/MarkdownRendererWithCodeBlock.ts +18 -9
- package/front_end/panels/ai_assistance/components/chatMessage.css +11 -0
- package/front_end/panels/application/AppManifestView.ts +4 -5
- package/front_end/panels/application/CookieItemsView.ts +9 -15
- package/front_end/panels/application/DeviceBoundSessionsView.ts +20 -26
- package/front_end/panels/application/FrameDetailsView.ts +10 -16
- package/front_end/panels/application/OriginTrialTreeView.ts +2 -3
- package/front_end/panels/application/ReportingApiView.ts +14 -18
- package/front_end/panels/application/components/BackForwardCacheView.ts +3 -3
- package/front_end/panels/application/preloading/PreloadingView.ts +18 -3
- package/front_end/panels/application/preloading/components/UsedPreloadingView.ts +2 -3
- package/front_end/panels/browser_debugger/DOMBreakpointsSidebarPane.ts +3 -2
- package/front_end/panels/changes/ChangesView.ts +13 -15
- package/front_end/panels/console/ConsolePinPane.ts +3 -3
- package/front_end/panels/coverage/CoverageListView.ts +1 -1
- package/front_end/panels/coverage/CoverageView.ts +4 -4
- package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +3 -3
- package/front_end/panels/css_overview/CSSOverviewPanel.ts +11 -15
- package/front_end/panels/developer_resources/DeveloperResourcesView.ts +3 -5
- package/front_end/panels/elements/ElementsTreeOutline.ts +34 -8
- package/front_end/panels/elements/EventListenersWidget.ts +3 -2
- package/front_end/panels/elements/StandaloneStylesContainer.ts +21 -6
- package/front_end/panels/elements/StylePropertiesSection.ts +129 -1
- package/front_end/panels/elements/StylePropertyHighlighter.ts +3 -0
- package/front_end/panels/elements/StylePropertyTreeElement.ts +49 -4
- package/front_end/panels/elements/stylesSidebarPane.css +34 -0
- package/front_end/panels/issues/AffectedSelectivePermissionsInterventionView.ts +3 -5
- package/front_end/panels/layer_viewer/LayerDetailsView.ts +2 -1
- package/front_end/panels/layer_viewer/Layers3DView.ts +5 -4
- package/front_end/panels/linear_memory_inspector/components/LinearMemoryInspector.ts +5 -6
- package/front_end/panels/linear_memory_inspector/components/LinearMemoryValueInterpreter.ts +6 -11
- package/front_end/panels/network/RequestConditionsDrawer.ts +4 -4
- package/front_end/panels/network/RequestCookiesView.ts +5 -6
- package/front_end/panels/network/RequestHeadersView.ts +4 -4
- package/front_end/panels/network/RequestInitiatorView.ts +7 -5
- package/front_end/panels/network/RequestResponseView.ts +10 -15
- package/front_end/panels/performance_monitor/PerformanceMonitor.ts +2 -2
- package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +5 -6
- package/front_end/panels/recorder/components/RecordingView.ts +31 -36
- package/front_end/panels/recorder/components/StepEditor.ts +6 -7
- package/front_end/panels/recorder/components/StepView.ts +2 -1
- package/front_end/panels/search/SearchView.ts +3 -4
- package/front_end/panels/settings/WorkspaceSettingsTab.ts +2 -5
- package/front_end/panels/timeline/TimelineDetailsView.ts +8 -6
- package/front_end/panels/timeline/components/LiveMetricsView.ts +5 -8
- package/front_end/panels/timeline/components/SidebarSingleInsightSet.ts +2 -7
- package/front_end/panels/timeline/components/insights/Cache.ts +8 -10
- package/front_end/panels/timeline/components/insights/CharacterSet.ts +34 -0
- package/front_end/panels/timeline/components/insights/DOMSize.ts +16 -20
- package/front_end/panels/timeline/components/insights/DocumentLatency.ts +2 -6
- package/front_end/panels/timeline/components/insights/DuplicatedJavaScript.ts +3 -4
- package/front_end/panels/timeline/components/insights/EventRef.ts +2 -2
- package/front_end/panels/timeline/components/insights/FontDisplay.ts +3 -4
- package/front_end/panels/timeline/components/insights/ForcedReflow.ts +5 -7
- package/front_end/panels/timeline/components/insights/INPBreakdown.ts +3 -4
- package/front_end/panels/timeline/components/insights/ImageDelivery.ts +3 -4
- package/front_end/panels/timeline/components/insights/ImageRef.ts +2 -4
- package/front_end/panels/timeline/components/insights/InsightRenderer.ts +2 -0
- package/front_end/panels/timeline/components/insights/LCPBreakdown.ts +5 -7
- package/front_end/panels/timeline/components/insights/LCPDiscovery.ts +2 -4
- package/front_end/panels/timeline/components/insights/LegacyJavaScript.ts +3 -4
- package/front_end/panels/timeline/components/insights/ModernHTTP.ts +3 -4
- package/front_end/panels/timeline/components/insights/NetworkDependencyTree.ts +7 -11
- package/front_end/panels/timeline/components/insights/NodeLink.ts +2 -4
- package/front_end/panels/timeline/components/insights/RenderBlocking.ts +3 -4
- package/front_end/panels/timeline/components/insights/SlowCSSSelector.ts +7 -10
- package/front_end/panels/timeline/components/insights/ThirdParties.ts +5 -7
- package/front_end/panels/timeline/components/insights/insights.ts +2 -0
- package/front_end/panels/web_audio/WebAudioView.ts +3 -4
- package/front_end/panels/webauthn/WebauthnPane.ts +2 -2
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/puppeteer/README.chromium +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Realm.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Realm.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/util.d.ts +4 -0
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/util.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/util.js +13 -0
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/util.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +3 -3
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +3 -3
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/third_party/mitt/mitt.js +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/third_party/parsel-js/parsel-js.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/third_party/rxjs/rxjs.js +446 -446
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +166 -167
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Realm.js +2 -2
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Realm.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/util.d.ts +4 -0
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/util.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/util.js +12 -0
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/util.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +3 -3
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +3 -3
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/third_party/mitt/mitt.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/third_party/parsel-js/parsel-js.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/third_party/rxjs/rxjs.js +97 -97
- package/front_end/third_party/puppeteer/package/package.json +1 -1
- package/front_end/third_party/puppeteer/package/src/bidi/Realm.ts +2 -2
- package/front_end/third_party/puppeteer/package/src/bidi/util.ts +17 -0
- package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
- package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
- package/front_end/ui/components/settings/SettingCheckbox.ts +2 -0
- package/front_end/ui/legacy/Widget.ts +42 -6
- package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +3 -3
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +8 -8
- package/front_end/ui/visual_logging/Debugging.ts +0 -32
- package/front_end/ui/visual_logging/KnownContextValues.ts +2 -0
- package/package.json +1 -1
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
|
|
5
|
-
import * as Common from '../../../core/common/common.js';
|
|
6
5
|
import * as Host from '../../../core/host/host.js';
|
|
7
6
|
import * as i18n from '../../../core/i18n/i18n.js';
|
|
8
7
|
import * as Root from '../../../core/root/root.js';
|
|
9
|
-
import * as SDK from '../../../core/sdk/sdk.js';
|
|
8
|
+
import type * as SDK from '../../../core/sdk/sdk.js';
|
|
10
9
|
import * as Logs from '../../logs/logs.js';
|
|
11
10
|
import * as NetworkTimeCalculator from '../../network_time_calculator/network_time_calculator.js';
|
|
12
11
|
import type * as Trace from '../../trace/trace.js';
|
|
@@ -63,7 +62,7 @@ You aim to help developers of all levels, prioritizing teaching web concepts as
|
|
|
63
62
|
*/
|
|
64
63
|
export class ContextSelectionAgent extends AiAgent<never> {
|
|
65
64
|
readonly preamble = preamble;
|
|
66
|
-
readonly clientFeature = Host.AidaClient.ClientFeature.
|
|
65
|
+
readonly clientFeature = Host.AidaClient.ClientFeature.CHROME_CONTEXT_SELECTION_AGENT;
|
|
67
66
|
get userTier(): string|undefined {
|
|
68
67
|
// TODO: Make this depend on variable.
|
|
69
68
|
return Root.Runtime.hostConfig.devToolsFreestyler?.userTier;
|
|
@@ -81,6 +80,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
81
80
|
readonly #performanceRecordAndReload?: () => Promise<Trace.TraceModel.ParsedTrace>;
|
|
82
81
|
readonly #onInspectElement?: () => Promise<SDK.DOMModel.DOMNode|null>;
|
|
83
82
|
readonly #networkTimeCalculator?: NetworkTimeCalculator.NetworkTransferTimeCalculator;
|
|
83
|
+
#allowedOrigin: () => string | undefined;
|
|
84
84
|
|
|
85
85
|
constructor(opts: AgentOptions&{
|
|
86
86
|
performanceRecordAndReload?: () => Promise<Trace.TraceModel.ParsedTrace>,
|
|
@@ -91,6 +91,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
91
91
|
this.#performanceRecordAndReload = opts.performanceRecordAndReload;
|
|
92
92
|
this.#onInspectElement = opts.onInspectElement;
|
|
93
93
|
this.#networkTimeCalculator = opts.networkTimeCalculator;
|
|
94
|
+
this.#allowedOrigin = opts.allowedOrigin ?? (() => undefined);
|
|
94
95
|
|
|
95
96
|
this.declareFunction<Record<string, never>>('listNetworkRequests', {
|
|
96
97
|
description: `Gives a list of network requests including URL, status code, and duration.`,
|
|
@@ -109,12 +110,12 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
109
110
|
},
|
|
110
111
|
handler: async () => {
|
|
111
112
|
const requests = [];
|
|
112
|
-
const
|
|
113
|
-
const inspectedURL = target?.inspectedURL();
|
|
114
|
-
const mainSecurityOrigin = inspectedURL ? new Common.ParsedURL.ParsedURL(inspectedURL).securityOrigin() : null;
|
|
113
|
+
const origin = this.#allowedOrigin();
|
|
115
114
|
|
|
115
|
+
let hasCrossOriginRequest = false;
|
|
116
116
|
for (const request of Logs.NetworkLog.NetworkLog.instance().requests()) {
|
|
117
|
-
if (
|
|
117
|
+
if (origin && request.securityOrigin() !== origin) {
|
|
118
|
+
hasCrossOriginRequest = true;
|
|
118
119
|
continue;
|
|
119
120
|
}
|
|
120
121
|
|
|
@@ -129,7 +130,9 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
129
130
|
|
|
130
131
|
if (requests.length === 0) {
|
|
131
132
|
return {
|
|
132
|
-
error:
|
|
133
|
+
error: hasCrossOriginRequest ?
|
|
134
|
+
`No requests showing with origin ${origin}. Tell the user to start a new chat` :
|
|
135
|
+
'No requests recorded by DevTools',
|
|
133
136
|
};
|
|
134
137
|
}
|
|
135
138
|
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// Copyright 2026 The Chromium Authors
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file.
|
|
4
|
+
|
|
5
|
+
import * as Host from '../../../core/host/host.js';
|
|
6
|
+
import * as Root from '../../../core/root/root.js';
|
|
7
|
+
|
|
8
|
+
import {AiAgent, type ContextResponse, ConversationContext, type RequestOptions, ResponseType} from './AiAgent.js';
|
|
9
|
+
|
|
10
|
+
const preamble =
|
|
11
|
+
`You are an expert technical assistant specializing in summarizing debugging conversations from Chrome DevTools.
|
|
12
|
+
You will receive a markdown-formatted transcript of a conversation between a user and a DevTools AI assistant.
|
|
13
|
+
Your goal is to produce a succinct, structured summary that a local AI agent in the user's IDE can use to apply code fixes.
|
|
14
|
+
|
|
15
|
+
Focus on extracting:
|
|
16
|
+
1. **Core Issue:** The primary problem or question the user was investigating.
|
|
17
|
+
2. **Diagnostic Findings:** Key technical details discovered (e.g., specific functions, bottlenecks, error messages, URLs, or CSS properties).
|
|
18
|
+
3. **Proposed Solution:** The specific changes or optimizations recommended by the DevTools assistant.
|
|
19
|
+
4. **Actionable Steps:** A clear, step-by-step list of instructions for the IDE agent to implement the fix.
|
|
20
|
+
|
|
21
|
+
Maintain a professional, technical, and extremely concise tone. Avoid conversational filler or introductory/concluding remarks.
|
|
22
|
+
The output must be structured markdown.`;
|
|
23
|
+
|
|
24
|
+
export class ConversationSummaryContext extends ConversationContext<string> {
|
|
25
|
+
#conversation: string;
|
|
26
|
+
constructor(conversation: string) {
|
|
27
|
+
super();
|
|
28
|
+
this.#conversation = conversation;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
getOrigin(): string {
|
|
32
|
+
return 'devtools://ai-assistance';
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
getItem(): string {
|
|
36
|
+
return this.#conversation;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
override getTitle(): string {
|
|
40
|
+
return 'Conversation';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* An agent that takes a full conversation between a user and an agent in markdown
|
|
46
|
+
* format and produces a succinct summary of the conversation.
|
|
47
|
+
*
|
|
48
|
+
* This summary is designed to be read by a local agent in the user's IDE and it
|
|
49
|
+
* will be used to help apply fixes to the user's local codebase based on the
|
|
50
|
+
* debugging information the devtools agent found.
|
|
51
|
+
*
|
|
52
|
+
* This agent is not intended to be used directly by users in the AI Assistance
|
|
53
|
+
* panel when chatting with DevTools AI.
|
|
54
|
+
*/
|
|
55
|
+
export class ConversationSummaryAgent extends AiAgent<string> {
|
|
56
|
+
override preamble = preamble;
|
|
57
|
+
|
|
58
|
+
get clientFeature(): Host.AidaClient.ClientFeature {
|
|
59
|
+
return Host.AidaClient.ClientFeature.CHROME_CONVERSATION_SUMMARY_AGENT;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
get userTier(): string|undefined {
|
|
63
|
+
// TODO(b/491772868): tidy up userTier & feature flags in the backend.
|
|
64
|
+
return Root.Runtime.hostConfig.devToolsFreestyler?.userTier;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
get options(): RequestOptions {
|
|
68
|
+
// TODO(b/491772868): tidy up userTier & feature flags in the backend.
|
|
69
|
+
const temperature = Root.Runtime.hostConfig.devToolsFreestyler?.temperature;
|
|
70
|
+
const modelId = Root.Runtime.hostConfig.devToolsFreestyler?.modelId;
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
temperature,
|
|
74
|
+
modelId,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async * handleContextDetails(context: ConversationContext<string>|null): AsyncGenerator<ContextResponse, void, void> {
|
|
79
|
+
if (!context) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
yield {
|
|
84
|
+
type: ResponseType.CONTEXT,
|
|
85
|
+
title: 'Summarizing conversation',
|
|
86
|
+
details: [
|
|
87
|
+
{
|
|
88
|
+
title: 'Conversation transcript',
|
|
89
|
+
text: context.getItem(),
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
override async enhanceQuery(query: string, context: ConversationContext<string>|null): Promise<string> {
|
|
96
|
+
const conversation = context ? context.getItem() : query;
|
|
97
|
+
return `Summarize the following conversation:\n\n${conversation}`;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async summarizeConversation(conversation: string): Promise<string> {
|
|
101
|
+
const context = new ConversationSummaryContext(conversation);
|
|
102
|
+
const response = await Array.fromAsync(this.run('', {selected: context}));
|
|
103
|
+
const lastResponse = response.at(-1);
|
|
104
|
+
if (lastResponse && lastResponse.type === ResponseType.ANSWER && lastResponse.complete === true) {
|
|
105
|
+
return lastResponse.text.trim();
|
|
106
|
+
}
|
|
107
|
+
throw new Error('Failed to summarize conversation');
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -8,6 +8,7 @@ import * as i18n from '../../../core/i18n/i18n.js';
|
|
|
8
8
|
import * as Platform from '../../../core/platform/platform.js';
|
|
9
9
|
import * as Root from '../../../core/root/root.js';
|
|
10
10
|
import * as SDK from '../../../core/sdk/sdk.js';
|
|
11
|
+
import type * as Protocol from '../../../generated/protocol.js';
|
|
11
12
|
import * as Tracing from '../../../services/tracing/tracing.js';
|
|
12
13
|
import * as Annotations from '../../annotations/annotations.js';
|
|
13
14
|
import * as SourceMapScopes from '../../source_map_scopes/source_map_scopes.js';
|
|
@@ -700,6 +701,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
700
701
|
#declareFunctions(context: PerformanceTraceContext): void {
|
|
701
702
|
const focus = context.getItem();
|
|
702
703
|
const {parsedTrace} = focus;
|
|
704
|
+
const processedNodeIds = new Set<Protocol.DOM.BackendNodeId>();
|
|
703
705
|
|
|
704
706
|
this.declareFunction<{insightSetId: string, insightName: string}, {details: string}>('getInsightDetails', {
|
|
705
707
|
description:
|
|
@@ -749,9 +751,36 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
749
751
|
|
|
750
752
|
const details = new PerformanceInsightFormatter(focus, insight).formatInsight();
|
|
751
753
|
|
|
754
|
+
const widgets: AiWidget[] = [];
|
|
755
|
+
if (params.insightName === 'LCPDiscovery' || params.insightName === 'LCPBreakdown') {
|
|
756
|
+
const lcpMetric = Trace.Insights.Common.getLCP(insightSet);
|
|
757
|
+
const lcpEvent = lcpMetric?.event;
|
|
758
|
+
if (lcpEvent && Trace.Types.Events.isAnyLargestContentfulPaintCandidate(lcpEvent)) {
|
|
759
|
+
const nodeId = lcpEvent.args.data?.nodeId;
|
|
760
|
+
// We want to show only one DOM tree widget per walkthrough per node.
|
|
761
|
+
// We do want to show the widget for the same node again, if it's within a new walkthrough.
|
|
762
|
+
if (nodeId && !processedNodeIds.has(nodeId)) {
|
|
763
|
+
const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
|
|
764
|
+
const domModel = target?.model(SDK.DOMModel.DOMModel);
|
|
765
|
+
if (domModel) {
|
|
766
|
+
const nodeMap = await domModel.pushNodesByBackendIdsToFrontend(new Set([nodeId]));
|
|
767
|
+
const node = nodeMap?.get(nodeId);
|
|
768
|
+
if (node) {
|
|
769
|
+
const snapshot = await node.takeSnapshot();
|
|
770
|
+
widgets.push({
|
|
771
|
+
name: 'DOM_TREE',
|
|
772
|
+
data: {root: snapshot},
|
|
773
|
+
});
|
|
774
|
+
processedNodeIds.add(nodeId);
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
|
|
752
781
|
const key = `getInsightDetails('${params.insightSetId}', '${params.insightName}')`;
|
|
753
782
|
this.#cacheFunctionResult(focus, key, details);
|
|
754
|
-
return {result: {details}};
|
|
783
|
+
return {result: {details}, widgets};
|
|
755
784
|
},
|
|
756
785
|
});
|
|
757
786
|
|
|
@@ -15,11 +15,12 @@ import {ChangeManager} from '../ChangeManager.js';
|
|
|
15
15
|
import {debugLog} from '../debug.js';
|
|
16
16
|
import {EvaluateAction, formatError, SideEffectError} from '../EvaluateAction.js';
|
|
17
17
|
import {ExtensionScope} from '../ExtensionScope.js';
|
|
18
|
-
import {FREESTYLER_WORLD_NAME} from '../injected.js';
|
|
18
|
+
import {AI_ASSISTANCE_CSS_CLASS_NAME, FREESTYLER_WORLD_NAME} from '../injected.js';
|
|
19
19
|
|
|
20
20
|
import {
|
|
21
21
|
type AgentOptions as BaseAgentOptions,
|
|
22
22
|
AiAgent,
|
|
23
|
+
type AnswerResponse,
|
|
23
24
|
type ComputedStyleAiWidget,
|
|
24
25
|
type ContextResponse,
|
|
25
26
|
ConversationContext,
|
|
@@ -194,6 +195,8 @@ async function executeJsCode(
|
|
|
194
195
|
const MAX_OBSERVATION_BYTE_LENGTH = 25_000;
|
|
195
196
|
const OBSERVATION_TIMEOUT = 5_000;
|
|
196
197
|
|
|
198
|
+
export const AI_ASSISTANCE_FILTER_REGEX = `\\.${AI_ASSISTANCE_CSS_CLASS_NAME}-.*&`;
|
|
199
|
+
|
|
197
200
|
type CreateExtensionScopeFunction = (changes: ChangeManager) => {
|
|
198
201
|
install(): Promise<void>, uninstall(): Promise<void>,
|
|
199
202
|
};
|
|
@@ -317,15 +320,17 @@ export class StylingAgent extends AiAgent<SDK.DOMModel.DOMNode> {
|
|
|
317
320
|
#createExtensionScope: CreateExtensionScopeFunction;
|
|
318
321
|
#greenDevEmulationScreenshot: string|null = null;
|
|
319
322
|
#greenDevEmulationAxTree: string|null = null;
|
|
323
|
+
#currentTurnId = 0;
|
|
320
324
|
|
|
321
325
|
constructor(opts: AgentOptions) {
|
|
322
326
|
super(opts);
|
|
323
327
|
|
|
324
328
|
this.#changes = opts.changeManager || new ChangeManager();
|
|
325
329
|
this.#execJs = opts.execJs ?? executeJsCode;
|
|
326
|
-
this.#createExtensionScope =
|
|
327
|
-
|
|
328
|
-
|
|
330
|
+
this.#createExtensionScope =
|
|
331
|
+
opts.createExtensionScope ?? ((changes: ChangeManager) => {
|
|
332
|
+
return new ExtensionScope(changes, this.sessionId, this.context?.getItem() ?? null, this.#currentTurnId);
|
|
333
|
+
});
|
|
329
334
|
|
|
330
335
|
this.declareFunction<{
|
|
331
336
|
elements: number[],
|
|
@@ -1048,6 +1053,31 @@ const data = {
|
|
|
1048
1053
|
};
|
|
1049
1054
|
}
|
|
1050
1055
|
|
|
1056
|
+
protected override async preRun(): Promise<void> {
|
|
1057
|
+
this.#currentTurnId++;
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
protected override async finalizeAnswer(answer: AnswerResponse): Promise<AnswerResponse> {
|
|
1061
|
+
if (!Root.Runtime.hostConfig.devToolsAiAssistanceV2?.enabled) {
|
|
1062
|
+
return answer;
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
const changedNodeIds = this.#changes.getChangedNodesForGroupId(this.sessionId, this.#currentTurnId);
|
|
1066
|
+
if (changedNodeIds.length === 0) {
|
|
1067
|
+
return answer;
|
|
1068
|
+
}
|
|
1069
|
+
answer.widgets = [
|
|
1070
|
+
...(answer.widgets ?? []),
|
|
1071
|
+
...changedNodeIds.map(id => ({
|
|
1072
|
+
name: 'STYLE_PROPERTIES' as const,
|
|
1073
|
+
data: {
|
|
1074
|
+
backendNodeId: id,
|
|
1075
|
+
selector: AI_ASSISTANCE_FILTER_REGEX,
|
|
1076
|
+
},
|
|
1077
|
+
})),
|
|
1078
|
+
];
|
|
1079
|
+
return answer;
|
|
1080
|
+
}
|
|
1051
1081
|
override async enhanceQuery(
|
|
1052
1082
|
query: string, selectedElement: ConversationContext<SDK.DOMModel.DOMNode>|null,
|
|
1053
1083
|
multimodalInputType?: MultimodalInputType): Promise<string> {
|
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
|
|
5
5
|
import * as AgentProject from './AgentProject.js';
|
|
6
|
+
import * as AccessibilityAgent from './agents/AccessibilityAgent.js';
|
|
6
7
|
import * as AiAgent from './agents/AiAgent.js';
|
|
7
8
|
import * as BreakpointDebuggerAgent from './agents/BreakpointDebuggerAgent.js';
|
|
8
9
|
import * as ContextSelectionAgent from './agents/ContextSelectionAgent.js';
|
|
10
|
+
import * as ConversationSummaryAgent from './agents/ConversationSummaryAgent.js';
|
|
9
11
|
import * as FileAgent from './agents/FileAgent.js';
|
|
10
12
|
import * as NetworkAgent from './agents/NetworkAgent.js';
|
|
11
13
|
import * as PatchAgent from './agents/PatchAgent.js';
|
|
@@ -32,6 +34,7 @@ import * as AIContext from './performance/AIContext.js';
|
|
|
32
34
|
import * as AIQueries from './performance/AIQueries.js';
|
|
33
35
|
|
|
34
36
|
export {
|
|
37
|
+
AccessibilityAgent,
|
|
35
38
|
AgentProject,
|
|
36
39
|
AiAgent,
|
|
37
40
|
AICallTree,
|
|
@@ -45,6 +48,7 @@ export {
|
|
|
45
48
|
ChangeManager,
|
|
46
49
|
ContextSelectionAgent,
|
|
47
50
|
ConversationHandler,
|
|
51
|
+
ConversationSummaryAgent,
|
|
48
52
|
Debug,
|
|
49
53
|
EvaluateAction,
|
|
50
54
|
ExtensionScope,
|
|
@@ -203,6 +203,10 @@ export class PerformanceInsightFormatter {
|
|
|
203
203
|
{title: 'Is my site polyfilling modern JavaScript features?'},
|
|
204
204
|
{title: 'How can I reduce the amount of legacy JavaScript on my page?'},
|
|
205
205
|
];
|
|
206
|
+
case 'CharacterSet':
|
|
207
|
+
return [
|
|
208
|
+
{title: 'How do I declare a character encoding for my page?'},
|
|
209
|
+
];
|
|
206
210
|
default:
|
|
207
211
|
throw new Error(`Unknown insight key '${this.#insight.insightKey}'`);
|
|
208
212
|
}
|
|
@@ -881,6 +885,20 @@ ${requestSummary}`;
|
|
|
881
885
|
* @param insight The Network Dependency Tree Insight Model to query.
|
|
882
886
|
* @returns a string formatted for sending to Ask AI.
|
|
883
887
|
*/
|
|
888
|
+
formatCharacterSetInsight(insight: Trace.Insights.Models.CharacterSet.CharacterSetInsightModel): string {
|
|
889
|
+
let output = '';
|
|
890
|
+
if (insight.data) {
|
|
891
|
+
output += 'HTTP Content-Type header charset: ' + (insight.data.hasHttpCharset ? 'present' : 'missing') + '.\n';
|
|
892
|
+
output += 'HTML meta charset disposition: ' + (insight.data.metaCharsetDisposition ?? 'unknown') + '.\n';
|
|
893
|
+
|
|
894
|
+
if (!insight.data.hasHttpCharset && insight.data.metaCharsetDisposition !== 'found-in-first-1024-bytes') {
|
|
895
|
+
output +=
|
|
896
|
+
'\nThe page does not declare character encoding via HTTP header or a meta charset tag in the first 1024 bytes.\n';
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
return output;
|
|
900
|
+
}
|
|
901
|
+
|
|
884
902
|
formatViewportInsight(insight: Trace.Insights.Models.Viewport.ViewportInsightModel): string {
|
|
885
903
|
let output = '';
|
|
886
904
|
|
|
@@ -995,6 +1013,10 @@ ${this.#links()}`;
|
|
|
995
1013
|
return this.formatViewportInsight(this.#insight);
|
|
996
1014
|
}
|
|
997
1015
|
|
|
1016
|
+
if (Trace.Insights.Models.CharacterSet.isCharacterSetInsight(this.#insight)) {
|
|
1017
|
+
return this.formatCharacterSetInsight(this.#insight);
|
|
1018
|
+
}
|
|
1019
|
+
|
|
998
1020
|
return '';
|
|
999
1021
|
}
|
|
1000
1022
|
|
|
@@ -1074,6 +1096,9 @@ ${this.#links()}`;
|
|
|
1074
1096
|
links.push('https://web.dev/articles/baseline-and-polyfills');
|
|
1075
1097
|
links.push('https://philipwalton.com/articles/the-state-of-es5-on-the-web/');
|
|
1076
1098
|
break;
|
|
1099
|
+
case 'CharacterSet':
|
|
1100
|
+
links.push('https://developer.chrome.com/docs/insights/charset/');
|
|
1101
|
+
break;
|
|
1077
1102
|
}
|
|
1078
1103
|
|
|
1079
1104
|
return links.map(link => '- ' + link).join('\n');
|
|
@@ -1158,6 +1183,8 @@ To pass this insight, ensure your server supports and prioritizes a modern HTTP
|
|
|
1158
1183
|
return `This insight identified legacy JavaScript in your application's modules that may be creating unnecessary code.
|
|
1159
1184
|
|
|
1160
1185
|
Polyfills and transforms enable older browsers to use new JavaScript features. However, many are not necessary for modern browsers. Consider modifying your JavaScript build process to not transpile Baseline features, unless you know you must support older browsers.`;
|
|
1186
|
+
case 'CharacterSet':
|
|
1187
|
+
return `This insight checks that the page declares a character encoding, ideally via the Content-Type HTTP response header. A missing or late charset declaration can force the browser to re-parse the document once it finally determines the encoding, delaying first contentful paint. Best practice: include charset=utf-8 in the Content-Type header and add <meta charset="utf-8"> as the very first element inside <head>.`;
|
|
1161
1188
|
}
|
|
1162
1189
|
}
|
|
1163
1190
|
}
|
package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt
CHANGED
|
@@ -467,6 +467,7 @@ Here are all the insights that contain some related request from the given range
|
|
|
467
467
|
- DocumentLatency: news.yahoo.com/ (news.yahoo.com) (eventKey: s-2116, ts: 157423489126)
|
|
468
468
|
- ThirdParties: cmp.js (consent.cmp.oath.com) (eventKey: s-3382, ts: 157423742399), gpt.js (securepubads.g.doubleclick.net) (eventKey: s-6244, ts: 157423760529), loader.js (cdn.taboola.com) (eventKey: s-6352, ts: 157423761978)
|
|
469
469
|
- Cache: prebid-2.0.js (s.yimg.com) (eventKey: s-6279, ts: 157423760925), cmp.js (consent.cmp.oath.com) (eventKey: s-3382, ts: 157423742399), d1irmdsmbztlvx.js (s.yimg.com) (eventKey: s-6185, ts: 157423759200), consent.js (s.yimg.com) (eventKey: s-3384, ts: 157423742450), wnsrvbjmeprtfrnfx.js (s.yimg.com) (eventKey: s-6273, ts: 157423760794)
|
|
470
|
+
- CharacterSet: news.yahoo.com/ (news.yahoo.com) (eventKey: s-2116, ts: 157423489126)
|
|
470
471
|
- LegacyJavaScript: benji-2.2.99.js (s.yimg.com) (eventKey: s-3387, ts: 157423742567), 25fa214.caas-news_web.min.js (s.yimg.com) (eventKey: s-3412, ts: 157423743431), wnsrvbjmeprtfrnfx.js (s.yimg.com) (eventKey: s-6273, ts: 157423760794), consent.js (s.yimg.com) (eventKey: s-3384, ts: 157423742450), news.yahoo.com/ (news.yahoo.com) (eventKey: s-2116, ts: 157423489126)
|
|
471
472
|
=== end content
|
|
472
473
|
|
|
@@ -510,6 +511,10 @@ Available insights:
|
|
|
510
511
|
description: 3rd party code can significantly impact load performance. [Reduce and defer loading of 3rd party code](https://developer.chrome.com/docs/performance/insights/third-parties) to prioritize your page's content.
|
|
511
512
|
relevant trace bounds: {min: 1020034871372, max: 1020035171789}
|
|
512
513
|
example question: Which third parties are having the largest impact on my page performance?
|
|
514
|
+
- insight name: CharacterSet
|
|
515
|
+
description: A character encoding declaration is required. It can be done with a meta charset tag in the first 1024 bytes of the HTML or in the Content-Type HTTP response header. [Learn more about declaring the character encoding](https://developer.chrome.com/docs/insights/charset/).
|
|
516
|
+
relevant trace bounds: {min: 1020034836013, max: 1020034892491}
|
|
517
|
+
example question: How do I declare a character encoding for my page?
|
|
513
518
|
=== end content
|
|
514
519
|
|
|
515
520
|
Title: PerformanceTraceFormatter formatTraceSummary yahoo-news.json.gz
|
|
@@ -617,6 +622,10 @@ Available insights:
|
|
|
617
622
|
relevant trace bounds: {min: 171608170438, max: 171608877165}
|
|
618
623
|
example question: Show me the most impactful render-blocking requests that I should focus on
|
|
619
624
|
example question: How can I reduce the number of render-blocking requests?
|
|
625
|
+
- insight name: CharacterSet
|
|
626
|
+
description: A character encoding declaration is required. It can be done with a meta charset tag in the first 1024 bytes of the HTML or in the Content-Type HTTP response header. [Learn more about declaring the character encoding](https://developer.chrome.com/docs/insights/charset/).
|
|
627
|
+
relevant trace bounds: {min: 171607584346, max: 171608171143}
|
|
628
|
+
example question: How do I declare a character encoding for my page?
|
|
620
629
|
|
|
621
630
|
## insight set id: NAVIGATION_1
|
|
622
631
|
|
|
@@ -641,6 +650,10 @@ Available insights:
|
|
|
641
650
|
relevant trace bounds: {min: 171614330544, max: 171615043224}
|
|
642
651
|
example question: Show me the most impactful render-blocking requests that I should focus on
|
|
643
652
|
example question: How can I reduce the number of render-blocking requests?
|
|
653
|
+
- insight name: CharacterSet
|
|
654
|
+
description: A character encoding declaration is required. It can be done with a meta charset tag in the first 1024 bytes of the HTML or in the Content-Type HTTP response header. [Learn more about declaring the character encoding](https://developer.chrome.com/docs/insights/charset/).
|
|
655
|
+
relevant trace bounds: {min: 171613750986, max: 171614330870}
|
|
656
|
+
example question: How do I declare a character encoding for my page?
|
|
644
657
|
=== end content
|
|
645
658
|
|
|
646
659
|
Title: PerformanceTraceFormatter formatTraceSummary deals with CrUX manager errors
|
|
@@ -714,6 +727,10 @@ Available insights:
|
|
|
714
727
|
description: 3rd party code can significantly impact load performance. [Reduce and defer loading of 3rd party code](https://developer.chrome.com/docs/performance/insights/third-parties) to prioritize your page's content.
|
|
715
728
|
relevant trace bounds: {min: 59728701403, max: 59729465969}
|
|
716
729
|
example question: Which third parties are having the largest impact on my page performance?
|
|
730
|
+
- insight name: CharacterSet
|
|
731
|
+
description: A character encoding declaration is required. It can be done with a meta charset tag in the first 1024 bytes of the HTML or in the Content-Type HTTP response header. [Learn more about declaring the character encoding](https://developer.chrome.com/docs/insights/charset/).
|
|
732
|
+
relevant trace bounds: {min: 59728651057, max: 59728790724}
|
|
733
|
+
example question: How do I declare a character encoding for my page?
|
|
717
734
|
=== end content
|
|
718
735
|
|
|
719
736
|
Title: PerformanceTraceFormatter formatTraceSummary image-delivery.json.gz
|
|
@@ -794,6 +811,10 @@ Available insights:
|
|
|
794
811
|
description: 3rd party code can significantly impact load performance. [Reduce and defer loading of 3rd party code](https://developer.chrome.com/docs/performance/insights/third-parties) to prioritize your page's content.
|
|
795
812
|
relevant trace bounds: {min: 59728701403, max: 59729465969}
|
|
796
813
|
example question: Which third parties are having the largest impact on my page performance?
|
|
814
|
+
- insight name: CharacterSet
|
|
815
|
+
description: A character encoding declaration is required. It can be done with a meta charset tag in the first 1024 bytes of the HTML or in the Content-Type HTTP response header. [Learn more about declaring the character encoding](https://developer.chrome.com/docs/insights/charset/).
|
|
816
|
+
relevant trace bounds: {min: 59728651057, max: 59728790724}
|
|
817
|
+
example question: How do I declare a character encoding for my page?
|
|
797
818
|
=== end content
|
|
798
819
|
|
|
799
820
|
Title: PerformanceTraceFormatter formatTraceSummary includes INP insight when there is no navigation
|
|
@@ -40,11 +40,17 @@ let metricScoresByFrameId = new Map<FrameId, Map<AnyNavigationStart, Map<MetricN
|
|
|
40
40
|
*/
|
|
41
41
|
let allMarkerEvents: Types.Events.PageLoadEvent[] = [];
|
|
42
42
|
|
|
43
|
+
// Grouped by navigation to make it easier for insights to scope checks.
|
|
44
|
+
let metaCharsetCheckEventsByNavigation = new Map<AnyNavigationStart, Types.Events.MetaCharsetCheck[]>();
|
|
45
|
+
let metaCharsetCheckEventsArray: Types.Events.MetaCharsetCheck[] = [];
|
|
46
|
+
|
|
43
47
|
export function reset(): void {
|
|
44
48
|
metricScoresByFrameId = new Map();
|
|
45
49
|
pageLoadEventsArray = [];
|
|
46
50
|
allMarkerEvents = [];
|
|
47
51
|
selectedLCPCandidateEvents = new Set();
|
|
52
|
+
metaCharsetCheckEventsByNavigation = new Map();
|
|
53
|
+
metaCharsetCheckEventsArray = [];
|
|
48
54
|
}
|
|
49
55
|
|
|
50
56
|
let pageLoadEventsArray: Types.Events.PageLoadEvent[] = [];
|
|
@@ -60,6 +66,11 @@ let pageLoadEventsArray: Types.Events.PageLoadEvent[] = [];
|
|
|
60
66
|
let selectedLCPCandidateEvents = new Set<Types.Events.AnyLargestContentfulPaintCandidate>();
|
|
61
67
|
|
|
62
68
|
export function handleEvent(event: Types.Events.Event): void {
|
|
69
|
+
if (Types.Events.isMetaCharsetCheck(event)) {
|
|
70
|
+
metaCharsetCheckEventsArray.push(event);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
63
74
|
if (!Types.Events.eventIsPageLoadEvent(event)) {
|
|
64
75
|
return;
|
|
65
76
|
}
|
|
@@ -393,6 +404,23 @@ export async function finalize(): Promise<void> {
|
|
|
393
404
|
storePageLoadMetricAgainstNavigationId(navigation, pageLoadEvent);
|
|
394
405
|
}
|
|
395
406
|
}
|
|
407
|
+
|
|
408
|
+
const {navigationsByFrameId} = metaHandlerData();
|
|
409
|
+
metaCharsetCheckEventsArray.sort((a, b) => a.ts - b.ts);
|
|
410
|
+
for (const metaCharsetCheckEvent of metaCharsetCheckEventsArray) {
|
|
411
|
+
const frameId = metaCharsetCheckEvent.args.data?.frame;
|
|
412
|
+
if (!frameId) {
|
|
413
|
+
continue;
|
|
414
|
+
}
|
|
415
|
+
const navigation = Helpers.Trace.getNavigationForTraceEvent(metaCharsetCheckEvent, frameId, navigationsByFrameId);
|
|
416
|
+
if (!navigation) {
|
|
417
|
+
continue;
|
|
418
|
+
}
|
|
419
|
+
const eventsForNavigation =
|
|
420
|
+
Platform.MapUtilities.getWithDefault(metaCharsetCheckEventsByNavigation, navigation, () => []);
|
|
421
|
+
eventsForNavigation.push(metaCharsetCheckEvent);
|
|
422
|
+
}
|
|
423
|
+
|
|
396
424
|
// NOTE: if you are looking for the TBT calculation, it has temporarily been
|
|
397
425
|
// removed. See crbug.com/1424335 for details.
|
|
398
426
|
const allFinalLCPEvents = gatherFinalLCPEvents();
|
|
@@ -421,12 +449,17 @@ export interface PageLoadMetricsData {
|
|
|
421
449
|
* main frame.
|
|
422
450
|
*/
|
|
423
451
|
allMarkerEvents: Types.Events.PageLoadEvent[];
|
|
452
|
+
/**
|
|
453
|
+
* MetaCharsetCheck events grouped by navigation.
|
|
454
|
+
*/
|
|
455
|
+
metaCharsetCheckEventsByNavigation: Map<AnyNavigationStart, Types.Events.MetaCharsetCheck[]>;
|
|
424
456
|
}
|
|
425
457
|
|
|
426
458
|
export function data(): PageLoadMetricsData {
|
|
427
459
|
return {
|
|
428
460
|
metricScoresByFrameId,
|
|
429
461
|
allMarkerEvents,
|
|
462
|
+
metaCharsetCheckEventsByNavigation,
|
|
430
463
|
};
|
|
431
464
|
}
|
|
432
465
|
|