chrome-devtools-frontend 1.0.1537268 → 1.0.1538310
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/.env.template +10 -0
- package/docs/get_the_code.md +27 -0
- package/eslint.config.mjs +151 -149
- package/front_end/core/common/SettingRegistration.ts +10 -7
- package/front_end/core/common/Settings.ts +3 -0
- package/front_end/core/host/AidaClient.ts +1 -0
- package/front_end/core/host/UserMetrics.ts +3 -1
- package/front_end/core/root/Runtime.ts +8 -0
- package/front_end/core/sdk/sdk-meta.ts +8 -2
- package/front_end/entrypoints/inspector_main/RenderingOptions.ts +4 -3
- package/front_end/generated/SupportedCSSProperties.js +1 -0
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +23 -7
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +110 -5
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +50 -45
- package/front_end/models/ai_code_generation/AiCodeGeneration.ts +151 -0
- package/front_end/models/ai_code_generation/ai_code_generation.ts +6 -0
- package/front_end/models/ai_code_generation/debug.ts +30 -0
- package/front_end/models/cpu_profile/ProfileTreeModel.ts +7 -7
- package/front_end/models/trace_source_maps_resolver/SourceMapsResolver.ts +1 -1
- package/front_end/panels/application/PreloadingTreeElement.ts +10 -2
- package/front_end/panels/application/StorageView.ts +3 -2
- package/front_end/panels/application/components/BackForwardCacheView.ts +34 -51
- package/front_end/panels/application/components/OriginTrialTreeView.ts +141 -170
- package/front_end/panels/application/components/backForwardCacheView.css +4 -0
- package/front_end/panels/application/components/originTrialTreeView.css +37 -7
- package/front_end/panels/application/preloading/components/PreloadingGrid.ts +2 -2
- package/front_end/panels/application/preloading/components/PreloadingString.ts +30 -1
- package/front_end/panels/autofill/AutofillView.ts +1 -1
- package/front_end/panels/console/ConsoleView.ts +11 -9
- package/front_end/panels/coverage/CoverageView.ts +1 -2
- package/front_end/panels/css_overview/CSSOverviewSidebarPanel.ts +1 -1
- package/front_end/panels/developer_resources/DeveloperResourcesView.ts +1 -1
- package/front_end/panels/elements/ElementStatePaneWidget.ts +1 -1
- package/front_end/panels/elements/EventListenersWidget.ts +1 -2
- package/front_end/panels/elements/PropertiesWidget.ts +1 -1
- package/front_end/panels/emulation/components/DeviceSizeInputElement.ts +1 -0
- package/front_end/panels/network/NetworkConfigView.ts +2 -1
- package/front_end/panels/network/NetworkItemView.ts +1 -1
- package/front_end/panels/network/NetworkPanel.ts +5 -4
- package/front_end/panels/network/NetworkWaterfallColumn.ts +5 -6
- package/front_end/panels/network/RequestCookiesView.ts +2 -1
- package/front_end/panels/network/RequestTimingView.ts +404 -348
- package/front_end/panels/network/networkTimingTable.css +22 -2
- package/front_end/panels/profiler/HeapSnapshotView.ts +3 -2
- package/front_end/panels/sensors/SensorsView.ts +4 -3
- package/front_end/panels/settings/FrameworkIgnoreListSettingsTab.ts +8 -6
- package/front_end/panels/settings/KeybindsSettingsTab.ts +3 -2
- package/front_end/panels/settings/SettingsScreen.ts +2 -1
- package/front_end/panels/settings/WorkspaceSettingsTab.ts +1 -1
- package/front_end/panels/sources/AiCodeCompletionPlugin.ts +2 -1
- package/front_end/panels/sources/SourcesPanel.ts +2 -1
- package/front_end/panels/sources/sources-meta.ts +8 -1
- package/front_end/panels/timeline/TimelinePanel.ts +4 -3
- package/front_end/panels/timeline/TimelineUIUtils.ts +4 -20
- package/front_end/panels/timeline/components/LiveMetricsView.ts +1 -0
- package/front_end/panels/timeline/components/NetworkRequestTooltip.ts +42 -3
- package/front_end/panels/timeline/components/SidebarAnnotationsTab.ts +2 -0
- package/front_end/panels/timeline/components/networkRequestTooltip.css +19 -0
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/components/adorners/Adorner.ts +3 -1
- package/front_end/ui/components/buttons/Button.docs.ts +195 -0
- package/front_end/ui/components/icon_button/IconButton.ts +1 -0
- package/front_end/ui/components/settings/SettingCheckbox.ts +50 -14
- package/front_end/ui/components/settings/settingCheckbox.css +6 -1
- package/front_end/ui/components/spinners/Spinners.docs.ts +13 -0
- package/front_end/ui/components/tooltips/Tooltip.docs.ts +76 -0
- package/front_end/ui/legacy/FilterBar.ts +1 -2
- package/front_end/ui/legacy/RadioButton.docs.ts +41 -0
- package/front_end/ui/legacy/SelectMenu.docs.ts +98 -0
- package/front_end/ui/legacy/Toolbar.ts +4 -6
- package/front_end/ui/legacy/Treeoutline.ts +15 -0
- package/front_end/ui/legacy/UIUtils.ts +117 -1
- package/front_end/ui/legacy/Widget.ts +68 -38
- package/front_end/ui/legacy/XLink.ts +1 -0
- package/front_end/ui/legacy/components/inline_editor/Swatches.ts +1 -0
- package/front_end/ui/legacy/components/perf_ui/BrickBreaker.ts +1 -0
- package/front_end/ui/legacy/components/settings_ui/SettingsUI.ts +125 -0
- package/front_end/ui/legacy/components/settings_ui/settings_ui.ts +8 -0
- package/front_end/ui/legacy/legacy.ts +0 -2
- package/front_end/ui/legacy/popover.css +12 -11
- package/front_end/ui/visual_logging/KnownContextValues.ts +3 -0
- package/package.json +1 -1
- package/front_end/models/trace/lantern/testing/MetricTestUtils.ts +0 -62
- package/front_end/models/trace/lantern/testing/testing.ts +0 -5
- package/front_end/panels/application/components/badge.css +0 -25
- package/front_end/ui/components/docs/button/basic.html +0 -44
- package/front_end/ui/components/docs/button/basic.ts +0 -175
- package/front_end/ui/components/docs/radio_button/basic.html +0 -23
- package/front_end/ui/components/docs/radio_button/basic.ts +0 -50
- package/front_end/ui/components/docs/select_menu/basic.html +0 -19
- package/front_end/ui/components/docs/select_menu/basic.ts +0 -95
- package/front_end/ui/components/docs/select_menu/wide-option.html +0 -38
- package/front_end/ui/components/docs/select_menu/wide-option.ts +0 -43
- package/front_end/ui/components/docs/spinners/basic.html +0 -17
- package/front_end/ui/components/docs/spinners/basic.ts +0 -22
- package/front_end/ui/components/docs/tooltip/basic.html +0 -20
- package/front_end/ui/components/docs/tooltip/basic.ts +0 -82
- package/front_end/ui/legacy/SettingsUI.ts +0 -240
|
@@ -299,21 +299,24 @@ export interface SettingRegistration {
|
|
|
299
299
|
* jump to the experiment. If a setting is not disabled, the experiment entry will be ignored.
|
|
300
300
|
*/
|
|
301
301
|
deprecationNotice?: {disabled: boolean, warning: () => Platform.UIString.LocalizedString, experiment?: string};
|
|
302
|
-
|
|
303
302
|
/**
|
|
304
|
-
*
|
|
305
|
-
* in the Settings panel with a link to learn more, and the `tooltip` will be presented to the user when hovering
|
|
306
|
-
* the `(?)` icon.
|
|
303
|
+
* See {@link LearnMore} for more info.
|
|
307
304
|
*/
|
|
308
305
|
learnMore?: LearnMore;
|
|
309
306
|
}
|
|
310
307
|
|
|
311
308
|
/**
|
|
312
|
-
*
|
|
313
|
-
*
|
|
309
|
+
* Optional information to learn more about the setting.
|
|
310
|
+
*
|
|
311
|
+
* If tooltip is provided creates a (i) icon with rich tooltip with said tooltip
|
|
312
|
+
*
|
|
313
|
+
* If url is provided creates a (?) icon with a link to said url
|
|
314
|
+
*
|
|
315
|
+
* If both tooltip is provided creates a (i) icon with rich tooltip
|
|
316
|
+
* and a link inside the rich tool tip with text `Learn more`
|
|
314
317
|
*/
|
|
315
318
|
export interface LearnMore {
|
|
316
|
-
tooltip
|
|
319
|
+
tooltip?: () => Platform.UIString.LocalizedString;
|
|
317
320
|
url?: Platform.DevToolsPath.UrlString;
|
|
318
321
|
}
|
|
319
322
|
|
|
@@ -342,6 +342,7 @@ export interface AidaRegisterClientEvent {
|
|
|
342
342
|
disable_user_content_logging: boolean;
|
|
343
343
|
do_conversation_client_event?: DoConversationClientEvent;
|
|
344
344
|
complete_code_client_event?: {user_acceptance: UserAcceptance}|{user_impression: UserImpression};
|
|
345
|
+
generate_code_client_event?: {user_acceptance: UserAcceptance}|{user_impression: UserImpression};
|
|
345
346
|
}
|
|
346
347
|
/* eslint-enable @typescript-eslint/naming-convention */
|
|
347
348
|
|
|
@@ -527,7 +527,9 @@ export enum Action {
|
|
|
527
527
|
InsightTeaserGenerationCompleted = 192,
|
|
528
528
|
InsightTeaserGenerationAborted = 193,
|
|
529
529
|
InsightTeaserGenerationErrored = 194,
|
|
530
|
-
|
|
530
|
+
AiCodeGenerationSuggestionDisplayed = 195,
|
|
531
|
+
AiCodeGenerationSuggestionAccepted = 196,
|
|
532
|
+
MAX_VALUE = 197,
|
|
531
533
|
/* eslint-enable @typescript-eslint/naming-convention */
|
|
532
534
|
}
|
|
533
535
|
|
|
@@ -422,6 +422,13 @@ export interface HostConfigAiCodeCompletion {
|
|
|
422
422
|
userTier: string;
|
|
423
423
|
}
|
|
424
424
|
|
|
425
|
+
export interface HostConfigAiCodeGeneration {
|
|
426
|
+
modelId: string;
|
|
427
|
+
temperature: number;
|
|
428
|
+
enabled: boolean;
|
|
429
|
+
userTier: string;
|
|
430
|
+
}
|
|
431
|
+
|
|
425
432
|
export interface HostConfigDeepLinksViaExtensibilityApi {
|
|
426
433
|
enabled: boolean;
|
|
427
434
|
}
|
|
@@ -556,6 +563,7 @@ export type HostConfig = Platform.TypeScriptUtilities.RecursivePartial<{
|
|
|
556
563
|
devToolsAiAssistanceFileAgent: HostConfigAiAssistanceFileAgent,
|
|
557
564
|
devToolsAiAssistancePerformanceAgent: HostConfigAiAssistancePerformanceAgent,
|
|
558
565
|
devToolsAiCodeCompletion: HostConfigAiCodeCompletion,
|
|
566
|
+
devToolsAiCodeGeneration: HostConfigAiCodeGeneration,
|
|
559
567
|
devToolsVeLogging: HostConfigVeLogging,
|
|
560
568
|
devToolsWellKnown: HostConfigWellKnown,
|
|
561
569
|
devToolsPrivacyUI: HostConfigPrivacyUI,
|
|
@@ -353,8 +353,11 @@ const UIStrings = {
|
|
|
353
353
|
/**
|
|
354
354
|
* @description Label of a checkbox in the DevTools settings UI.
|
|
355
355
|
*/
|
|
356
|
-
enableRemoteFileLoading:
|
|
357
|
-
|
|
356
|
+
enableRemoteFileLoading: 'Allow loading remote file path resources in DevTools',
|
|
357
|
+
/**
|
|
358
|
+
* @description Tooltip text for a setting that controls whether external resource can be loaded in DevTools.
|
|
359
|
+
*/
|
|
360
|
+
remoteFileLoadingInfo: 'Example resource are source maps. Disabled by default for security reasons.',
|
|
358
361
|
/**
|
|
359
362
|
* @description Tooltip text for a setting that controls the network cache. Disabling the network cache can simulate the network connections of users that are visiting a page for the first time.
|
|
360
363
|
*/
|
|
@@ -1160,4 +1163,7 @@ Common.Settings.registerSettingExtension({
|
|
|
1160
1163
|
settingName: 'network.enable-remote-file-loading',
|
|
1161
1164
|
settingType: Common.Settings.SettingType.BOOLEAN,
|
|
1162
1165
|
defaultValue: false,
|
|
1166
|
+
learnMore: {
|
|
1167
|
+
tooltip: i18nLazyString(UIStrings.remoteFileLoadingInfo),
|
|
1168
|
+
}
|
|
1163
1169
|
});
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import * as Common from '../../core/common/common.js';
|
|
8
8
|
import * as Host from '../../core/host/host.js';
|
|
9
9
|
import * as i18n from '../../core/i18n/i18n.js';
|
|
10
|
+
import * as SettingsUI from '../../ui/legacy/components/settings_ui/settings_ui.js';
|
|
10
11
|
import * as UI from '../../ui/legacy/legacy.js';
|
|
11
12
|
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
|
12
13
|
|
|
@@ -278,15 +279,15 @@ export class RenderingOptionsView extends UI.Widget.VBox {
|
|
|
278
279
|
|
|
279
280
|
#appendCheckbox(
|
|
280
281
|
label: Common.UIString.LocalizedString, subtitle: Common.UIString.LocalizedString,
|
|
281
|
-
setting: Common.Settings.Setting<boolean>, metric?: UI.
|
|
282
|
+
setting: Common.Settings.Setting<boolean>, metric?: UI.UIUtils.UserMetricOptions): UI.UIUtils.CheckboxLabel {
|
|
282
283
|
const checkbox = UI.UIUtils.CheckboxLabel.create(label, false, subtitle, setting.name);
|
|
283
|
-
UI.
|
|
284
|
+
UI.UIUtils.bindCheckbox(checkbox, setting, metric);
|
|
284
285
|
this.contentElement.appendChild(checkbox);
|
|
285
286
|
return checkbox;
|
|
286
287
|
}
|
|
287
288
|
|
|
288
289
|
#appendSelect(label: string, setting: Common.Settings.Setting<unknown>): void {
|
|
289
|
-
const control =
|
|
290
|
+
const control = SettingsUI.SettingsUI.createControlForSetting(setting, label);
|
|
290
291
|
if (control) {
|
|
291
292
|
this.contentElement.appendChild(control);
|
|
292
293
|
}
|
|
@@ -627,19 +627,24 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
627
627
|
#declareFunctions(context: PerformanceTraceContext): void {
|
|
628
628
|
const focus = context.getItem();
|
|
629
629
|
const {parsedTrace} = focus;
|
|
630
|
-
const insightSet = focus.primaryInsightSet;
|
|
631
630
|
|
|
632
|
-
this.declareFunction<{insightName: string}, {details: string}>('getInsightDetails', {
|
|
631
|
+
this.declareFunction<{insightSetId: string, insightName: string}, {details: string}>('getInsightDetails', {
|
|
633
632
|
description:
|
|
634
|
-
'Returns detailed information about a specific insight. Use this before commenting on any specific issue to get more information.',
|
|
633
|
+
'Returns detailed information about a specific insight of an insight set. Use this before commenting on any specific issue to get more information.',
|
|
635
634
|
parameters: {
|
|
636
635
|
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
637
636
|
description: '',
|
|
638
637
|
nullable: false,
|
|
639
638
|
properties: {
|
|
639
|
+
insightSetId: {
|
|
640
|
+
type: Host.AidaClient.ParametersTypes.STRING,
|
|
641
|
+
description:
|
|
642
|
+
'The id for the specific insight set. Only use the ids given in the "Available insight sets" list.',
|
|
643
|
+
nullable: false,
|
|
644
|
+
},
|
|
640
645
|
insightName: {
|
|
641
646
|
type: Host.AidaClient.ParametersTypes.STRING,
|
|
642
|
-
description: 'The name of the insight. Only use the insight names given in the Available
|
|
647
|
+
description: 'The name of the insight. Only use the insight names given in the "Available insights" list.',
|
|
643
648
|
nullable: false,
|
|
644
649
|
}
|
|
645
650
|
},
|
|
@@ -647,19 +652,30 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
647
652
|
displayInfoFromArgs: params => {
|
|
648
653
|
return {
|
|
649
654
|
title: lockedString(`Investigating insight ${params.insightName}…`),
|
|
650
|
-
action: `getInsightDetails('${params.insightName}')`
|
|
655
|
+
action: `getInsightDetails('${params.insightSetId}', '${params.insightName}')`
|
|
651
656
|
};
|
|
652
657
|
},
|
|
653
658
|
handler: async params => {
|
|
654
659
|
debugLog('Function call: getInsightDetails', params);
|
|
660
|
+
const insightSet = parsedTrace.insights?.get(params.insightSetId);
|
|
661
|
+
if (!insightSet) {
|
|
662
|
+
const valid = ([...parsedTrace.insights?.values() ?? []])
|
|
663
|
+
.map(
|
|
664
|
+
insightSet => `id: ${insightSet.id}, url: ${insightSet.url}, bounds: ${
|
|
665
|
+
this.#formatter?.serializeBounds(insightSet.bounds)}`)
|
|
666
|
+
.join('; ');
|
|
667
|
+
return {error: `Invalid insight set id. Valid insight set ids are: ${valid}`};
|
|
668
|
+
}
|
|
669
|
+
|
|
655
670
|
const insight = insightSet?.model[params.insightName as keyof Trace.Insights.Types.InsightModels];
|
|
656
671
|
if (!insight) {
|
|
657
|
-
|
|
672
|
+
const valid = Object.keys(insightSet?.model).join(', ');
|
|
673
|
+
return {error: `No insight available. Valid insight names are: ${valid}`};
|
|
658
674
|
}
|
|
659
675
|
|
|
660
676
|
const details = new PerformanceInsightFormatter(focus, insight).formatInsight();
|
|
661
677
|
|
|
662
|
-
const key = `getInsightDetails('${params.insightName}')`;
|
|
678
|
+
const key = `getInsightDetails('${params.insightSetId}', '${params.insightName}')`;
|
|
663
679
|
this.#cacheFunctionResult(focus, key, details);
|
|
664
680
|
return {result: {details}};
|
|
665
681
|
},
|
package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt
CHANGED
|
@@ -504,9 +504,18 @@ IMPORTANT: Never show eventKey to the user.
|
|
|
504
504
|
Title: PerformanceTraceFormatter formatTraceSummary web-dev.json.gz
|
|
505
505
|
Content:
|
|
506
506
|
URL: https://web.dev/cls/
|
|
507
|
-
|
|
507
|
+
Trace bounds: {min: 1020034823047, max: 1020036087961}
|
|
508
508
|
CPU throttling: none
|
|
509
509
|
Network throttling: none
|
|
510
|
+
|
|
511
|
+
# Available insight sets
|
|
512
|
+
|
|
513
|
+
The following is a list of insight sets. An insight set covers a specific part of the trace, split by navigations. The insights within each insight set are specific to that part of the trace. Be sure to consider the insight set id and bounds when calling functions. If no specific insight set or navigation is mentioned, assume the user is referring to the first one.
|
|
514
|
+
|
|
515
|
+
## insight set id: 86EB5E5C401E3E17ECE461B3FC627867
|
|
516
|
+
|
|
517
|
+
URL: https://web.dev/cls/
|
|
518
|
+
Bounds: {min: 1020034834921, max: 1020036087961}
|
|
510
519
|
Metrics (lab / observed):
|
|
511
520
|
- LCP: 118 ms, event: (eventKey: r-1802, ts: 1020034953358), nodeId: 209
|
|
512
521
|
- LCP breakdown:
|
|
@@ -537,9 +546,18 @@ Available insights:
|
|
|
537
546
|
Title: PerformanceTraceFormatter formatTraceSummary yahoo-news.json.gz
|
|
538
547
|
Content:
|
|
539
548
|
URL: https://news.yahoo.com/
|
|
540
|
-
|
|
549
|
+
Trace bounds: {min: 157423484442, max: 157427277166}
|
|
541
550
|
CPU throttling: none
|
|
542
551
|
Network throttling: none
|
|
552
|
+
|
|
553
|
+
# Available insight sets
|
|
554
|
+
|
|
555
|
+
The following is a list of insight sets. An insight set covers a specific part of the trace, split by navigations. The insights within each insight set are specific to that part of the trace. Be sure to consider the insight set id and bounds when calling functions. If no specific insight set or navigation is mentioned, assume the user is referring to the first one.
|
|
556
|
+
|
|
557
|
+
## insight set id: 513BDA1E9EC088611B53BFF7A859B5DD
|
|
558
|
+
|
|
559
|
+
URL: https://news.yahoo.com/
|
|
560
|
+
Bounds: {min: 157423488682, max: 157427277166}
|
|
543
561
|
Metrics (lab / observed):
|
|
544
562
|
- LCP: 464 ms, event: (eventKey: r-33210, ts: 157423953162), nodeId: 8
|
|
545
563
|
- LCP breakdown:
|
|
@@ -596,12 +614,81 @@ Available insights:
|
|
|
596
614
|
example question: How can I reduce the amount of legacy JavaScript on my page?
|
|
597
615
|
=== end content
|
|
598
616
|
|
|
617
|
+
Title: PerformanceTraceFormatter formatTraceSummary multiple-navigations-render-blocking.json.gz
|
|
618
|
+
Content:
|
|
619
|
+
URL: http://localhost:8080/render-blocking
|
|
620
|
+
Trace bounds: {min: 171605647473, max: 171616667355}
|
|
621
|
+
CPU throttling: 1x
|
|
622
|
+
Network throttling: Fast 3G
|
|
623
|
+
|
|
624
|
+
# Available insight sets
|
|
625
|
+
|
|
626
|
+
The following is a list of insight sets. An insight set covers a specific part of the trace, split by navigations. The insights within each insight set are specific to that part of the trace. Be sure to consider the insight set id and bounds when calling functions. If no specific insight set or navigation is mentioned, assume the user is referring to the first one.
|
|
627
|
+
|
|
628
|
+
## insight set id: 8671F33ECE0C8DBAEFBC2F9A2D1D6107
|
|
629
|
+
|
|
630
|
+
URL: http://localhost:8080/render-blocking
|
|
631
|
+
Bounds: {min: 171607579779, max: 171613750571}
|
|
632
|
+
Metrics (lab / observed):
|
|
633
|
+
- LCP: 1317 ms, event: (eventKey: r-6686, ts: 171608897210), nodeId: 10
|
|
634
|
+
- LCP breakdown:
|
|
635
|
+
- TTFB: 10 ms, bounds: {min: 171607579779, max: 171607589981.99997}
|
|
636
|
+
- Render delay: 1,307 ms, bounds: {min: 171607589981.99997, max: 171608897210}
|
|
637
|
+
- CLS: 0.00
|
|
638
|
+
Metrics (field / real users): n/a – no data for this page in CrUX
|
|
639
|
+
Available insights:
|
|
640
|
+
- insight name: LCPBreakdown
|
|
641
|
+
description: Each [subpart has specific improvement strategies](https://developer.chrome.com/docs/performance/insights/lcp-breakdown). Ideally, most of the LCP time should be spent on loading the resources, not within delays.
|
|
642
|
+
relevant trace bounds: {min: 171607579779, max: 171608897210}
|
|
643
|
+
example question: Help me optimize my LCP score
|
|
644
|
+
example question: Which LCP phase was most problematic?
|
|
645
|
+
example question: What can I do to reduce the LCP time for this page load?
|
|
646
|
+
- insight name: RenderBlocking
|
|
647
|
+
description: Requests are blocking the page's initial render, which may delay LCP. [Deferring or inlining](https://developer.chrome.com/docs/performance/insights/render-blocking) can move these network requests out of the critical path.
|
|
648
|
+
relevant trace bounds: {min: 171608170438, max: 171608877165}
|
|
649
|
+
example question: Show me the most impactful render blocking requests that I should focus on
|
|
650
|
+
example question: How can I reduce the number of render blocking requests?
|
|
651
|
+
|
|
652
|
+
## insight set id: 1AE2016BBCC48AA090FDAE2CBBA01900
|
|
653
|
+
|
|
654
|
+
URL: http://localhost:8080/render-blocking
|
|
655
|
+
Bounds: {min: 171613750571, max: 171616667355}
|
|
656
|
+
Metrics (lab / observed):
|
|
657
|
+
- LCP: 1310 ms, event: (eventKey: r-15639, ts: 171615060776), nodeId: 18
|
|
658
|
+
- LCP breakdown:
|
|
659
|
+
- TTFB: 3 ms, bounds: {min: 171613750571, max: 171613753188}
|
|
660
|
+
- Render delay: 1,308 ms, bounds: {min: 171613753188, max: 171615060776}
|
|
661
|
+
- CLS: 0.00
|
|
662
|
+
Metrics (field / real users): n/a – no data for this page in CrUX
|
|
663
|
+
Available insights:
|
|
664
|
+
- insight name: LCPBreakdown
|
|
665
|
+
description: Each [subpart has specific improvement strategies](https://developer.chrome.com/docs/performance/insights/lcp-breakdown). Ideally, most of the LCP time should be spent on loading the resources, not within delays.
|
|
666
|
+
relevant trace bounds: {min: 171613750571, max: 171615060776}
|
|
667
|
+
example question: Help me optimize my LCP score
|
|
668
|
+
example question: Which LCP phase was most problematic?
|
|
669
|
+
example question: What can I do to reduce the LCP time for this page load?
|
|
670
|
+
- insight name: RenderBlocking
|
|
671
|
+
description: Requests are blocking the page's initial render, which may delay LCP. [Deferring or inlining](https://developer.chrome.com/docs/performance/insights/render-blocking) can move these network requests out of the critical path.
|
|
672
|
+
relevant trace bounds: {min: 171614330544, max: 171615043224}
|
|
673
|
+
example question: Show me the most impactful render blocking requests that I should focus on
|
|
674
|
+
example question: How can I reduce the number of render blocking requests?
|
|
675
|
+
=== end content
|
|
676
|
+
|
|
599
677
|
Title: PerformanceTraceFormatter formatTraceSummary deals with CrUX manager errors
|
|
600
678
|
Content:
|
|
601
679
|
URL: http://localhost/image-delivery-cases.html
|
|
602
|
-
|
|
680
|
+
Trace bounds: {min: 59728641874, max: 59734400108}
|
|
603
681
|
CPU throttling: 1x
|
|
604
682
|
Network throttling: No throttling
|
|
683
|
+
|
|
684
|
+
# Available insight sets
|
|
685
|
+
|
|
686
|
+
The following is a list of insight sets. An insight set covers a specific part of the trace, split by navigations. The insights within each insight set are specific to that part of the trace. Be sure to consider the insight set id and bounds when calling functions. If no specific insight set or navigation is mentioned, assume the user is referring to the first one.
|
|
687
|
+
|
|
688
|
+
## insight set id: 9094E106056B51D078CE44F3356FE194
|
|
689
|
+
|
|
690
|
+
URL: http://localhost/image-delivery-cases.html
|
|
691
|
+
Bounds: {min: 59728649746, max: 59734400108}
|
|
605
692
|
Metrics (lab / observed):
|
|
606
693
|
- LCP: 663 ms, event: (eventKey: r-14753, ts: 59729312744), nodeId: 12
|
|
607
694
|
- LCP breakdown:
|
|
@@ -663,9 +750,18 @@ Available insights:
|
|
|
663
750
|
Title: PerformanceTraceFormatter formatTraceSummary image-delivery.json.gz
|
|
664
751
|
Content:
|
|
665
752
|
URL: http://localhost/image-delivery-cases.html
|
|
666
|
-
|
|
753
|
+
Trace bounds: {min: 59728641874, max: 59734400108}
|
|
667
754
|
CPU throttling: 1x
|
|
668
755
|
Network throttling: No throttling
|
|
756
|
+
|
|
757
|
+
# Available insight sets
|
|
758
|
+
|
|
759
|
+
The following is a list of insight sets. An insight set covers a specific part of the trace, split by navigations. The insights within each insight set are specific to that part of the trace. Be sure to consider the insight set id and bounds when calling functions. If no specific insight set or navigation is mentioned, assume the user is referring to the first one.
|
|
760
|
+
|
|
761
|
+
## insight set id: 9094E106056B51D078CE44F3356FE194
|
|
762
|
+
|
|
763
|
+
URL: http://localhost/image-delivery-cases.html
|
|
764
|
+
Bounds: {min: 59728649746, max: 59734400108}
|
|
669
765
|
Metrics (lab / observed):
|
|
670
766
|
- LCP: 663 ms, event: (eventKey: r-14753, ts: 59729312744), nodeId: 12
|
|
671
767
|
- LCP breakdown:
|
|
@@ -734,9 +830,18 @@ Available insights:
|
|
|
734
830
|
Title: PerformanceTraceFormatter formatTraceSummary includes INP insight when there is no navigation
|
|
735
831
|
Content:
|
|
736
832
|
URL: https://b2607f8b04800100000289cb1c0a82ba72253000000000000000001.proxy.googlers.com/long-interaction/index.html?x=35
|
|
737
|
-
|
|
833
|
+
Trace bounds: {min: 337943614456, max: 337947260898}
|
|
738
834
|
CPU throttling: none
|
|
739
835
|
Network throttling: none
|
|
836
|
+
|
|
837
|
+
# Available insight sets
|
|
838
|
+
|
|
839
|
+
The following is a list of insight sets. An insight set covers a specific part of the trace, split by navigations. The insights within each insight set are specific to that part of the trace. Be sure to consider the insight set id and bounds when calling functions. If no specific insight set or navigation is mentioned, assume the user is referring to the first one.
|
|
840
|
+
|
|
841
|
+
## insight set id: NO_NAVIGATION
|
|
842
|
+
|
|
843
|
+
URL: https://b2607f8b04800100000289cb1c0a82ba72253000000000000000001.proxy.googlers.com/long-interaction/index.html?x=35
|
|
844
|
+
Bounds: {min: 337943614456, max: 337947260898}
|
|
740
845
|
Metrics (lab / observed):
|
|
741
846
|
- INP: 139 ms, event: (eventKey: s-3347, ts: 337944870984)
|
|
742
847
|
- CLS: 0.00
|
|
@@ -116,62 +116,69 @@ export class PerformanceTraceFormatter {
|
|
|
116
116
|
|
|
117
117
|
formatTraceSummary(): string {
|
|
118
118
|
const parsedTrace = this.#parsedTrace;
|
|
119
|
-
const insightSet = this.#insightSet;
|
|
120
119
|
const traceMetadata = this.#parsedTrace.metadata;
|
|
121
120
|
const data = parsedTrace.data;
|
|
122
121
|
|
|
123
122
|
const parts = [];
|
|
124
123
|
|
|
125
|
-
const lcp = insightSet ? Trace.Insights.Common.getLCP(insightSet) : null;
|
|
126
|
-
const cls = insightSet ? Trace.Insights.Common.getCLS(insightSet) : null;
|
|
127
|
-
const inp = insightSet ? Trace.Insights.Common.getINP(insightSet) : null;
|
|
128
|
-
|
|
129
124
|
parts.push(`URL: ${data.Meta.mainFrameURL}`);
|
|
130
|
-
parts.push(`
|
|
125
|
+
parts.push(`Trace bounds: ${this.serializeBounds(data.Meta.traceBounds)}`);
|
|
131
126
|
parts.push('CPU throttling: ' + (traceMetadata.cpuThrottling ? `${traceMetadata.cpuThrottling}x` : 'none'));
|
|
132
127
|
parts.push(`Network throttling: ${traceMetadata.networkThrottling ?? 'none'}`);
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
128
|
+
|
|
129
|
+
parts.push('\n# Available insight sets\n');
|
|
130
|
+
parts.push(
|
|
131
|
+
'The following is a list of insight sets. An insight set covers a specific part of the trace, split by navigations. The insights within each insight set are specific to that part of the trace. Be sure to consider the insight set id and bounds when calling functions. If no specific insight set or navigation is mentioned, assume the user is referring to the first one.');
|
|
132
|
+
|
|
133
|
+
for (const insightSet of parsedTrace.insights?.values() ?? []) {
|
|
134
|
+
const lcp = insightSet ? Trace.Insights.Common.getLCP(insightSet) : null;
|
|
135
|
+
const cls = insightSet ? Trace.Insights.Common.getCLS(insightSet) : null;
|
|
136
|
+
const inp = insightSet ? Trace.Insights.Common.getINP(insightSet) : null;
|
|
137
|
+
|
|
138
|
+
parts.push(`\n## insight set id: ${insightSet.id}\n`);
|
|
139
|
+
parts.push(`URL: ${insightSet.url}`);
|
|
140
|
+
parts.push(`Bounds: ${this.serializeBounds(insightSet.bounds)}`);
|
|
141
|
+
if (lcp || cls || inp) {
|
|
142
|
+
parts.push('Metrics (lab / observed):');
|
|
143
|
+
if (lcp) {
|
|
144
|
+
const nodeId = insightSet?.model.LCPBreakdown.lcpEvent?.args.data?.nodeId;
|
|
145
|
+
const nodeIdText = nodeId !== undefined ? `, nodeId: ${nodeId}` : '';
|
|
146
|
+
parts.push(
|
|
147
|
+
` - LCP: ${Math.round(lcp.value / 1000)} ms, event: ${this.serializeEvent(lcp.event)}${nodeIdText}`);
|
|
148
|
+
const subparts = insightSet?.model.LCPBreakdown.subparts;
|
|
149
|
+
if (subparts) {
|
|
150
|
+
const serializeSubpart = (subpart: Trace.Insights.Models.LCPBreakdown.Subpart): string => {
|
|
151
|
+
return `${micros(subpart.range)}, bounds: ${this.serializeBounds(subpart)}`;
|
|
152
|
+
};
|
|
153
|
+
parts.push(' - LCP breakdown:');
|
|
154
|
+
parts.push(` - TTFB: ${serializeSubpart(subparts.ttfb)}`);
|
|
155
|
+
if (subparts.loadDelay !== undefined) {
|
|
156
|
+
parts.push(` - Load delay: ${serializeSubpart(subparts.loadDelay)}`);
|
|
157
|
+
}
|
|
158
|
+
if (subparts.loadDuration !== undefined) {
|
|
159
|
+
parts.push(` - Load duration: ${serializeSubpart(subparts.loadDuration)}`);
|
|
160
|
+
}
|
|
161
|
+
parts.push(` - Render delay: ${serializeSubpart(subparts.renderDelay)}`);
|
|
152
162
|
}
|
|
153
|
-
parts.push(` - Render delay: ${serializeSubpart(subparts.renderDelay)}`);
|
|
154
163
|
}
|
|
164
|
+
if (inp) {
|
|
165
|
+
parts.push(` - INP: ${Math.round(inp.value / 1000)} ms, event: ${this.serializeEvent(inp.event)}`);
|
|
166
|
+
}
|
|
167
|
+
if (cls) {
|
|
168
|
+
const eventText = cls.worstClusterEvent ? `, event: ${this.serializeEvent(cls.worstClusterEvent)}` : '';
|
|
169
|
+
parts.push(` - CLS: ${cls.value.toFixed(2)}${eventText}`);
|
|
170
|
+
}
|
|
171
|
+
} else {
|
|
172
|
+
parts.push('Metrics (lab / observed): n/a');
|
|
155
173
|
}
|
|
156
|
-
if (inp) {
|
|
157
|
-
parts.push(` - INP: ${Math.round(inp.value / 1000)} ms, event: ${this.serializeEvent(inp.event)}`);
|
|
158
|
-
}
|
|
159
|
-
if (cls) {
|
|
160
|
-
const eventText = cls.worstClusterEvent ? `, event: ${this.serializeEvent(cls.worstClusterEvent)}` : '';
|
|
161
|
-
parts.push(` - CLS: ${cls.value.toFixed(2)}${eventText}`);
|
|
162
|
-
}
|
|
163
|
-
} else {
|
|
164
|
-
parts.push('Metrics (lab / observed): n/a');
|
|
165
|
-
}
|
|
166
174
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
175
|
+
const cruxParts = insightSet && this.#getCruxTraceSummary(insightSet);
|
|
176
|
+
if (cruxParts?.length) {
|
|
177
|
+
parts.push(...cruxParts);
|
|
178
|
+
} else {
|
|
179
|
+
parts.push('Metrics (field / real users): n/a – no data for this page in CrUX');
|
|
180
|
+
}
|
|
173
181
|
|
|
174
|
-
if (insightSet) {
|
|
175
182
|
parts.push('Available insights:');
|
|
176
183
|
for (const [insightName, model] of Object.entries(insightSet.model)) {
|
|
177
184
|
if (model.state === 'pass') {
|
|
@@ -202,8 +209,6 @@ export class PerformanceTraceFormatter {
|
|
|
202
209
|
const insightPartsText = insightParts.join('\n ');
|
|
203
210
|
parts.push(` - ${insightPartsText}`);
|
|
204
211
|
}
|
|
205
|
-
} else {
|
|
206
|
-
parts.push('Available insights: none');
|
|
207
212
|
}
|
|
208
213
|
|
|
209
214
|
return parts.join('\n');
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
// Copyright 2025 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 {debugLog} from './debug.js';
|
|
9
|
+
|
|
10
|
+
export const basePreamble =
|
|
11
|
+
`You are a highly skilled senior software engineer with deep expertise across multiple web technologies and programming languages, including JavaScript, TypeScript, HTML, and CSS.
|
|
12
|
+
Your role is to act as an expert pair programmer within the Chrome DevTools environment.
|
|
13
|
+
|
|
14
|
+
**Core Directives (Adhere to these strictly):**
|
|
15
|
+
|
|
16
|
+
1. **Language and Quality:**
|
|
17
|
+
* Generate code that is modern, efficient, and idiomatic for the inferred language (e.g., modern JavaScript/ES6+, semantic HTML5, efficient CSS).
|
|
18
|
+
* Where appropriate, include basic error handling (e.g., for API calls).
|
|
19
|
+
`;
|
|
20
|
+
|
|
21
|
+
export const additionalContextForConsole = `
|
|
22
|
+
You are operating within the execution environment of the Chrome DevTools Console.
|
|
23
|
+
The console has direct access to the inspected page's \`window\` and \`document\`.
|
|
24
|
+
|
|
25
|
+
* **Utilize Console Utilities:** You have access to the Console Utilities API. You **should** use these helper functions and variables when they are the most direct way to accomplish the user's goal.
|
|
26
|
+
`;
|
|
27
|
+
|
|
28
|
+
interface Options {
|
|
29
|
+
aidaClient: Host.AidaClient.AidaClient;
|
|
30
|
+
serverSideLoggingEnabled?: boolean;
|
|
31
|
+
confirmSideEffectForTest?: typeof Promise.withResolvers;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface RequestOptions {
|
|
35
|
+
temperature?: number;
|
|
36
|
+
modelId?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The AiCodeGeneration class is responsible for fetching generated code suggestions
|
|
41
|
+
* from the AIDA backend.
|
|
42
|
+
*/
|
|
43
|
+
export class AiCodeGeneration {
|
|
44
|
+
readonly #sessionId: string = crypto.randomUUID();
|
|
45
|
+
readonly #aidaClient: Host.AidaClient.AidaClient;
|
|
46
|
+
readonly #serverSideLoggingEnabled: boolean;
|
|
47
|
+
|
|
48
|
+
constructor(opts: Options) {
|
|
49
|
+
this.#aidaClient = opts.aidaClient;
|
|
50
|
+
this.#serverSideLoggingEnabled = opts.serverSideLoggingEnabled ?? false;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
#buildRequest(
|
|
54
|
+
prompt: string,
|
|
55
|
+
preamble: string,
|
|
56
|
+
inferenceLanguage: Host.AidaClient.AidaInferenceLanguage = Host.AidaClient.AidaInferenceLanguage.JAVASCRIPT,
|
|
57
|
+
): Host.AidaClient.GenerateCodeRequest {
|
|
58
|
+
const userTier = Host.AidaClient.convertToUserTierEnum(this.#userTier);
|
|
59
|
+
function validTemperature(temperature: number|undefined): number|undefined {
|
|
60
|
+
return typeof temperature === 'number' && temperature >= 0 ? temperature : undefined;
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
client: Host.AidaClient.CLIENT_NAME,
|
|
64
|
+
preamble,
|
|
65
|
+
current_message: {
|
|
66
|
+
parts: [{
|
|
67
|
+
text: prompt,
|
|
68
|
+
}],
|
|
69
|
+
role: Host.AidaClient.Role.USER,
|
|
70
|
+
},
|
|
71
|
+
use_case: Host.AidaClient.UseCase.CODE_GENERATION,
|
|
72
|
+
options: {
|
|
73
|
+
inference_language: inferenceLanguage,
|
|
74
|
+
temperature: validTemperature(this.#options.temperature),
|
|
75
|
+
model_id: this.#options.modelId || undefined,
|
|
76
|
+
},
|
|
77
|
+
metadata: {
|
|
78
|
+
disable_user_content_logging: !(this.#serverSideLoggingEnabled ?? false),
|
|
79
|
+
string_session_id: this.#sessionId,
|
|
80
|
+
user_tier: userTier,
|
|
81
|
+
client_version: Root.Runtime.getChromeVersion(),
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
get #userTier(): string|undefined {
|
|
87
|
+
return Root.Runtime.hostConfig.devToolsAiCodeGeneration?.userTier;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
get #options(): RequestOptions {
|
|
91
|
+
const temperature = Root.Runtime.hostConfig.devToolsAiCodeGeneration?.temperature;
|
|
92
|
+
const modelId = Root.Runtime.hostConfig.devToolsAiCodeGeneration?.modelId;
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
temperature,
|
|
96
|
+
modelId,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
registerUserImpression(rpcGlobalId: Host.AidaClient.RpcGlobalId, latency: number, sampleId?: number): void {
|
|
101
|
+
const seconds = Math.floor(latency / 1_000);
|
|
102
|
+
const remainingMs = latency % 1_000;
|
|
103
|
+
const nanos = Math.floor(remainingMs * 1_000_000);
|
|
104
|
+
|
|
105
|
+
void this.#aidaClient.registerClientEvent({
|
|
106
|
+
corresponding_aida_rpc_global_id: rpcGlobalId,
|
|
107
|
+
disable_user_content_logging: true,
|
|
108
|
+
generate_code_client_event: {
|
|
109
|
+
user_impression: {
|
|
110
|
+
sample: {
|
|
111
|
+
sample_id: sampleId,
|
|
112
|
+
},
|
|
113
|
+
latency: {
|
|
114
|
+
duration: {
|
|
115
|
+
seconds,
|
|
116
|
+
nanos,
|
|
117
|
+
},
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
debugLog('Registered user impression with latency {seconds:', seconds, ', nanos:', nanos, '}');
|
|
123
|
+
Host.userMetrics.actionTaken(Host.UserMetrics.Action.AiCodeGenerationSuggestionDisplayed);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
registerUserAcceptance(rpcGlobalId: Host.AidaClient.RpcGlobalId, sampleId?: number): void {
|
|
127
|
+
void this.#aidaClient.registerClientEvent({
|
|
128
|
+
corresponding_aida_rpc_global_id: rpcGlobalId,
|
|
129
|
+
disable_user_content_logging: true,
|
|
130
|
+
generate_code_client_event: {
|
|
131
|
+
user_acceptance: {
|
|
132
|
+
sample: {
|
|
133
|
+
sample_id: sampleId,
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
debugLog('Registered user acceptance');
|
|
139
|
+
Host.userMetrics.actionTaken(Host.UserMetrics.Action.AiCodeGenerationSuggestionAccepted);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async generateCode(prompt: string, preamble: string, inferenceLanguage?: Host.AidaClient.AidaInferenceLanguage):
|
|
143
|
+
Promise<Host.AidaClient.GenerateCodeResponse|null> {
|
|
144
|
+
const request = this.#buildRequest(prompt, preamble, inferenceLanguage);
|
|
145
|
+
const response = await this.#aidaClient.generateCode(request);
|
|
146
|
+
|
|
147
|
+
debugLog({request, response});
|
|
148
|
+
|
|
149
|
+
return response;
|
|
150
|
+
}
|
|
151
|
+
}
|