chrome-devtools-frontend 1.0.1597624 → 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.
Files changed (140) hide show
  1. package/.agents/README.md +13 -0
  2. package/{agents/prompts/creating-a-model.md → .agents/skills/creating-a-model/SKILL.md} +7 -1
  3. package/{agents/prompts/devtools-imports.md → .agents/skills/devtools-imports/SKILL.md} +10 -5
  4. package/{agents/prompts/merging-devtools-module.md → .agents/skills/merging-devtools-module/SKILL.md} +5 -0
  5. package/{agents/prompts/ui-widgets.md → .agents/skills/ui-widgets/SKILL.md} +5 -0
  6. package/{agents/prompts/verification.md → .agents/skills/verification/SKILL.md} +5 -0
  7. package/docs/ui_engineering.md +6 -6
  8. package/front_end/core/host/AidaClient.ts +2 -0
  9. package/front_end/core/host/GcaTypes.ts +518 -0
  10. package/front_end/core/host/UserMetrics.ts +0 -1
  11. package/front_end/core/host/host.ts +2 -0
  12. package/front_end/core/root/ExperimentNames.ts +0 -1
  13. package/front_end/entrypoints/main/MainImpl.ts +0 -2
  14. package/front_end/generated/InspectorBackendCommands.ts +1 -1
  15. package/front_end/generated/protocol.ts +2 -1
  16. package/front_end/models/ai_assistance/AiConversation.ts +28 -15
  17. package/front_end/models/ai_assistance/AiHistoryStorage.snapshot.txt +1 -1
  18. package/front_end/models/ai_assistance/AiHistoryStorage.ts +1 -0
  19. package/front_end/models/ai_assistance/ConversationHandler.ts +8 -2
  20. package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +3 -18
  21. package/front_end/models/ai_assistance/agents/AiAgent.ts +39 -5
  22. package/front_end/models/ai_assistance/agents/BreakpointDebuggerAgent.ts +0 -1
  23. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +1 -0
  24. package/front_end/models/ai_assistance/agents/ConversationSummaryAgent.ts +108 -0
  25. package/front_end/models/ai_assistance/agents/FileAgent.ts +0 -15
  26. package/front_end/models/ai_assistance/agents/NetworkAgent.ts +0 -5
  27. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +76 -13
  28. package/front_end/models/ai_assistance/agents/PerformanceAnnotationsAgent.ts +0 -10
  29. package/front_end/models/ai_assistance/agents/StylingAgent.snapshot.txt +0 -6
  30. package/front_end/models/ai_assistance/agents/StylingAgent.ts +0 -5
  31. package/front_end/models/ai_assistance/ai_assistance.ts +2 -0
  32. package/front_end/models/emulation/DeviceModeModel.ts +5 -1
  33. package/front_end/models/emulation/EmulatedDevices.ts +3 -2
  34. package/front_end/models/issues_manager/SharedDictionaryIssue.ts +15 -5
  35. package/front_end/models/issues_manager/descriptions/sharedDictionaryUseErrorNoCorpCrossOriginNoCorsRequest.md +3 -0
  36. package/front_end/models/issues_manager/descriptions/sharedDictionaryWriteErrorNoCorpCossOriginNoCorsRequest.md +3 -0
  37. package/front_end/models/javascript_metadata/NativeFunctions.js +8 -0
  38. package/front_end/models/lighthouse/RunTypes.ts +41 -0
  39. package/front_end/models/lighthouse/lighthouse.ts +2 -0
  40. package/front_end/models/trace/ModelImpl.ts +4 -0
  41. package/front_end/models/trace/helpers/SamplesIntegrator.ts +1 -8
  42. package/front_end/models/trace/types/Configuration.ts +0 -5
  43. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +90 -14
  44. package/front_end/panels/ai_assistance/PatchWidget.ts +1 -1
  45. package/front_end/panels/ai_assistance/components/ChatInput.ts +2 -0
  46. package/front_end/panels/ai_assistance/components/ChatMessage.ts +153 -42
  47. package/front_end/panels/ai_assistance/components/ChatView.ts +1 -1
  48. package/front_end/panels/ai_assistance/components/chatMessage.css +61 -0
  49. package/front_end/panels/application/AppManifestView.ts +2 -2
  50. package/front_end/panels/application/CookieItemsView.ts +9 -15
  51. package/front_end/panels/application/DeviceBoundSessionsView.ts +3 -5
  52. package/front_end/panels/application/FrameDetailsView.ts +2 -2
  53. package/front_end/panels/application/ReportingApiView.ts +2 -2
  54. package/front_end/panels/application/preloading/PreloadingView.ts +20 -7
  55. package/front_end/panels/application/preloading/components/PreloadingDetailsReportView.ts +6 -3
  56. package/front_end/panels/application/preloading/components/PreloadingString.ts +15 -2
  57. package/front_end/panels/application/preloading/helper/PreloadingForward.ts +31 -2
  58. package/front_end/panels/changes/ChangesView.ts +7 -11
  59. package/front_end/panels/coverage/CoverageView.ts +4 -4
  60. package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +3 -3
  61. package/front_end/panels/elements/ElementsTreeOutline.ts +34 -8
  62. package/front_end/panels/elements/StylePropertiesSection.ts +129 -1
  63. package/front_end/panels/elements/StylePropertyHighlighter.ts +3 -0
  64. package/front_end/panels/elements/stylesSidebarPane.css +34 -0
  65. package/front_end/panels/issues/AffectedSelectivePermissionsInterventionView.ts +3 -5
  66. package/front_end/panels/layer_viewer/LayerDetailsView.ts +2 -1
  67. package/front_end/panels/lighthouse/LighthouseController.ts +148 -162
  68. package/front_end/panels/lighthouse/LighthousePanel.ts +2 -7
  69. package/front_end/panels/lighthouse/LighthouseStartView.ts +7 -6
  70. package/front_end/panels/lighthouse/LighthouseStatusView.ts +3 -3
  71. package/front_end/panels/linear_memory_inspector/components/LinearMemoryInspector.ts +7 -3
  72. package/front_end/panels/network/RequestConditionsDrawer.ts +4 -4
  73. package/front_end/panels/network/RequestCookiesView.ts +2 -2
  74. package/front_end/panels/network/RequestHeadersView.ts +4 -4
  75. package/front_end/panels/network/RequestResponseView.ts +2 -2
  76. package/front_end/panels/performance_monitor/PerformanceMonitor.ts +2 -2
  77. package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +3 -3
  78. package/front_end/panels/recorder/components/StepView.ts +2 -1
  79. package/front_end/panels/search/SearchView.ts +2 -2
  80. package/front_end/panels/sensors/SensorsView.ts +32 -22
  81. package/front_end/panels/settings/emulation/DevicesSettingsTab.ts +18 -4
  82. package/front_end/panels/timeline/StatusDialog.ts +159 -83
  83. package/front_end/panels/timeline/TimelineController.ts +0 -4
  84. package/front_end/panels/timeline/TimelineDetailsView.ts +8 -6
  85. package/front_end/panels/timeline/TimelinePanel.ts +29 -2
  86. package/front_end/panels/timeline/components/LiveMetricsView.ts +2 -2
  87. package/front_end/panels/timeline/components/Sidebar.ts +1 -1
  88. package/front_end/panels/timeline/components/SidebarInsightsTab.ts +1 -1
  89. package/front_end/panels/timeline/components/SidebarSingleInsightSet.ts +62 -34
  90. package/front_end/panels/timeline/components/insights/BaseInsightComponent.ts +53 -28
  91. package/front_end/panels/timeline/components/insights/CharacterSet.ts +2 -6
  92. package/front_end/panels/timeline/components/insights/EventRef.ts +2 -2
  93. package/front_end/panels/timeline/components/insights/baseInsightComponent.css +7 -0
  94. package/front_end/panels/timeline/components/insights/insights.ts +0 -2
  95. package/front_end/panels/timeline/timeline-meta.ts +11 -0
  96. package/front_end/panels/webauthn/WebauthnPane.ts +2 -2
  97. package/front_end/third_party/chromium/README.chromium +1 -1
  98. package/front_end/third_party/puppeteer/README.chromium +2 -2
  99. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Realm.js +1 -1
  100. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Realm.js.map +1 -1
  101. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/util.d.ts +4 -0
  102. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/util.d.ts.map +1 -1
  103. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/util.js +13 -0
  104. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/util.js.map +1 -1
  105. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
  106. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +3 -3
  107. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +3 -3
  108. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js.map +1 -1
  109. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
  110. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.d.ts +1 -1
  111. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.js +1 -1
  112. package/front_end/third_party/puppeteer/package/lib/cjs/third_party/mitt/mitt.js +2 -2
  113. package/front_end/third_party/puppeteer/package/lib/cjs/third_party/parsel-js/parsel-js.js +1 -1
  114. package/front_end/third_party/puppeteer/package/lib/cjs/third_party/rxjs/rxjs.js +446 -446
  115. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +166 -167
  116. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Realm.js +2 -2
  117. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Realm.js.map +1 -1
  118. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/util.d.ts +4 -0
  119. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/util.d.ts.map +1 -1
  120. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/util.js +12 -0
  121. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/util.js.map +1 -1
  122. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +3 -3
  123. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +3 -3
  124. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js.map +1 -1
  125. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.d.ts +1 -1
  126. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.js +1 -1
  127. package/front_end/third_party/puppeteer/package/lib/esm/third_party/mitt/mitt.js +1 -1
  128. package/front_end/third_party/puppeteer/package/lib/esm/third_party/parsel-js/parsel-js.js +1 -1
  129. package/front_end/third_party/puppeteer/package/lib/esm/third_party/rxjs/rxjs.js +97 -97
  130. package/front_end/third_party/puppeteer/package/package.json +1 -1
  131. package/front_end/third_party/puppeteer/package/src/bidi/Realm.ts +2 -2
  132. package/front_end/third_party/puppeteer/package/src/bidi/util.ts +17 -0
  133. package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
  134. package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
  135. package/front_end/ui/legacy/Widget.ts +47 -9
  136. package/front_end/ui/visual_logging/KnownContextValues.ts +1 -1
  137. package/package.json +1 -1
  138. package/agents/prompts/README.md +0 -18
  139. package/front_end/models/issues_manager/descriptions/sharedDictionaryUseErrorCrossOriginNoCorsRequest.md +0 -1
  140. package/front_end/panels/timeline/components/insights/InsightRenderer.ts +0 -93
@@ -23,6 +23,7 @@ import * as UIHelpers from '../../ui/helpers/helpers.js';
23
23
  import * as UI from '../../ui/legacy/legacy.js';
24
24
  import * as Lit from '../../ui/lit/lit.js';
25
25
  import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
26
+ import * as LighthousePanel from '../lighthouse/lighthouse.js';
26
27
  import * as NetworkForward from '../network/forward/forward.js';
27
28
  import * as NetworkPanel from '../network/network.js';
28
29
  import * as TimelinePanel from '../timeline/timeline.js';
@@ -50,6 +51,7 @@ import {
50
51
  import {isAiAssistancePatchingEnabled} from './PatchWidget.js';
51
52
 
52
53
  const {html} = Lit;
54
+ const {widget} = UI.Widget;
53
55
 
54
56
  const AI_ASSISTANCE_SEND_FEEDBACK = 'https://crbug.com/364805393' as Platform.DevToolsPath.UrlString;
55
57
  const AI_ASSISTANCE_HELP =
@@ -128,6 +130,10 @@ const UIStringsNotTranslate = {
128
130
  * @description Announcement text for screen readers when the answer comes.
129
131
  */
130
132
  answerReady: 'Answer ready',
133
+ /**
134
+ * @description Title for the first step of the walkthrough.
135
+ */
136
+ analyzingData: 'Analyzing data',
131
137
  /**
132
138
  * @description Placeholder text for the input shown when the conversation is blocked because a cross-origin context was selected.
133
139
  */
@@ -226,6 +232,24 @@ const UIStringsNotTranslate = {
226
232
  */
227
233
  inputDisclaimerForNoContextEnterpriseNoLogging:
228
234
  'Chat messages, any data the inspected page can see using Web APIs, and the items you select such as files, network requests, and performance traces are sent to Google. This data will not be used to improve Google’s AI models. This is an experimental AI feature and won’t always get it right.',
235
+ /**
236
+ * @description Placeholder text for the chat UI input.
237
+ */
238
+ inputPlaceholderForAccessibility: 'Ask a question about the selected Lighthouse report',
239
+ /**
240
+ * @description Placeholder text for the chat UI input when there is no context selected.
241
+ */
242
+ inputPlaceholderForAccessibilityNoContext: 'Generate a Lighthouse report to ask a question',
243
+ /**
244
+ * @description Disclaimer text right after the chat input.
245
+ */
246
+ inputDisclaimerForAccessibility:
247
+ 'Chat messages and the selected Lighthouse report are sent to Google and may be seen by human reviewers to improve this feature. This is an experimental AI feature and won’t always get it right.',
248
+ /**
249
+ * @description Disclaimer text right after the chat input.
250
+ */
251
+ inputDisclaimerForAccessibilityEnterpriseNoLogging:
252
+ 'Chat messages and the selected Lighthouse report are sent to Google. The content you submit and that is generated by this feature will not be used to improve Google’s AI models. This is an experimental AI feature and won’t always get it right.',
229
253
  } as const;
230
254
 
231
255
  const str_ = i18n.i18n.registerUIStrings('panels/ai_assistance/AiAssistancePanel.ts', UIStrings);
@@ -278,7 +302,14 @@ async function getEmptyStateSuggestions(conversation?: AiAssistanceModel.AiConve
278
302
  {title: 'Is the script optimized for performance?', jslogContext: 'file-default'},
279
303
  {title: 'Does the script handle user input safely?', jslogContext: 'file-default'},
280
304
  ];
305
+ case AiAssistanceModel.AiHistoryStorage.ConversationType.ACCESSIBILITY:
306
+ return [
307
+ {title: 'What are the accessibility issues on this page?', jslogContext: 'accessibility-default'},
308
+ {title: 'How can I fix these accessibility issues?', jslogContext: 'accessibility-default'},
309
+ {title: 'What does this Lighthouse report say about accessibility?', jslogContext: 'accessibility-default'},
310
+ ];
281
311
  case AiAssistanceModel.AiHistoryStorage.ConversationType.NETWORK:
312
+
282
313
  return [
283
314
  {title: 'Why is this network request taking so long?', jslogContext: 'network-default'},
284
315
  {title: 'Are there any security headers present?', jslogContext: 'network-default'},
@@ -465,16 +496,12 @@ function defaultView(input: ViewInput, output: PanelViewOutput, target: HTMLElem
465
496
  ></devtools-ai-chat-view>`;
466
497
  }
467
498
  case ViewState.EXPLORE_VIEW:
468
- return html`<devtools-widget
469
- class="fill-panel"
470
- .widgetConfig=${UI.Widget.widgetConfig(ExploreWidget)}
471
- ></devtools-widget>`;
499
+ return html`<devtools-widget class="fill-panel" ${widget(ExploreWidget)}>
500
+ </devtools-widget>`;
472
501
 
473
502
  case ViewState.DISABLED_VIEW:
474
- return html`<devtools-widget
475
- class="fill-panel"
476
- .widgetConfig=${UI.Widget.widgetConfig(DisabledWidget, input.props)}
477
- ></devtools-widget>`;
503
+ return html`<devtools-widget class="fill-panel" ${widget(DisabledWidget, input.props)}>
504
+ </devtools-widget>`;
478
505
  }
479
506
  }
480
507
 
@@ -510,7 +537,7 @@ function defaultView(input: ViewInput, output: PanelViewOutput, target: HTMLElem
510
537
  </div>
511
538
  <div slot="sidebar" class="sidebar-view">
512
539
  ${shouldShowWalkthrough ? html`
513
- <devtools-widget .widgetConfig=${UI.Widget.widgetConfig(WalkthroughView, {
540
+ <devtools-widget ${widget(WalkthroughView, {
514
541
  message: input.props.walkthrough.activeMessage,
515
542
  isLoading: input.props.isLoading && walkthroughIsForLastMessage,
516
543
  markdownRenderer: input.props.markdownRenderer,
@@ -552,6 +579,14 @@ function createBreakpointContext(uiLocation: Workspace.UISourceCode.UILocation|n
552
579
  return new AiAssistanceModel.BreakpointDebuggerAgent.BreakpointContext(uiLocation);
553
580
  }
554
581
 
582
+ function createAccessibilityContext(report: LighthousePanel.LighthousePanel.ActiveLighthouseReport|null):
583
+ AiAssistanceModel.AccessibilityAgent.AccessibilityContext|null {
584
+ if (!report) {
585
+ return null;
586
+ }
587
+ return new AiAssistanceModel.AccessibilityAgent.AccessibilityContext(report.report);
588
+ }
589
+
555
590
  function createRequestContext(request: SDK.NetworkRequest.NetworkRequest|null):
556
591
  AiAssistanceModel.NetworkAgent.RequestContext|null {
557
592
  if (!request) {
@@ -613,7 +648,9 @@ export class AiAssistancePanel extends UI.Panel.Panel {
613
648
  #selectedPerformanceTrace: AiAssistanceModel.PerformanceAgent.PerformanceTraceContext|null = null;
614
649
  #selectedRequest: AiAssistanceModel.NetworkAgent.RequestContext|null = null;
615
650
  #selectedBreakpoint: AiAssistanceModel.BreakpointDebuggerAgent.BreakpointContext|null = null;
651
+ #selectedAccessibility: AiAssistanceModel.AccessibilityAgent.AccessibilityContext|null = null;
616
652
  // Messages displayed in the `ChatView` component.
653
+
617
654
  #messages: Message[] = [];
618
655
 
619
656
  // Whether the UI should show loading or not.
@@ -841,6 +878,7 @@ export class AiAssistancePanel extends UI.Panel.Panel {
841
878
  const isNetworkPanelVisible = viewManager.isViewVisible('network');
842
879
  const isSourcesPanelVisible = viewManager.isViewVisible('sources');
843
880
  const isPerformancePanelVisible = viewManager.isViewVisible('timeline');
881
+ const isLighthousePanelVisible = viewManager.isViewVisible('lighthouse');
844
882
 
845
883
  let targetConversationType: AiAssistanceModel.AiHistoryStorage.ConversationType|undefined;
846
884
  if (isElementsPanelVisible && hostConfig.devToolsFreestyler?.enabled) {
@@ -855,6 +893,8 @@ export class AiAssistancePanel extends UI.Panel.Panel {
855
893
  targetConversationType = AiAssistanceModel.AiHistoryStorage.ConversationType.FILE;
856
894
  } else if (isPerformancePanelVisible && hostConfig.devToolsAiAssistancePerformanceAgent?.enabled) {
857
895
  targetConversationType = AiAssistanceModel.AiHistoryStorage.ConversationType.PERFORMANCE;
896
+ } else if (isLighthousePanelVisible && hostConfig.devToolsAiAssistanceAccessibilityAgent?.enabled) {
897
+ targetConversationType = AiAssistanceModel.AiHistoryStorage.ConversationType.ACCESSIBILITY;
858
898
  }
859
899
 
860
900
  if (isAiAssistanceContextSelectionAgentEnabled() && !targetConversationType) {
@@ -930,7 +970,8 @@ export class AiAssistancePanel extends UI.Panel.Panel {
930
970
 
931
971
  if (this.#conversation) {
932
972
  if (this.#conversation.isEmpty && isAiAssistanceContextSelectionAgentEnabled()) {
933
- this.#conversation.setContext(this.#getConversationContext(this.#getDefaultConversationType()));
973
+ const context = this.#getConversationContext(this.#getDefaultConversationType());
974
+ this.#conversation.setContext(context);
934
975
  } else {
935
976
  const context = this.#getConversationContext(this.#conversation.type);
936
977
  // Don't reset to the context selection agent if
@@ -983,6 +1024,8 @@ export class AiAssistancePanel extends UI.Panel.Panel {
983
1024
  this.#selectedFile = createFileContext(UI.Context.Context.instance().flavor(Workspace.UISourceCode.UISourceCode));
984
1025
  this.#selectedBreakpoint =
985
1026
  createBreakpointContext(UI.Context.Context.instance().flavor(Workspace.UISourceCode.UILocation));
1027
+ this.#selectedAccessibility = createAccessibilityContext(
1028
+ UI.Context.Context.instance().flavor(LighthousePanel.LighthousePanel.ActiveLighthouseReport));
986
1029
  this.#updateConversationState(this.#conversation);
987
1030
 
988
1031
  this.#aiAssistanceEnabledSetting?.addChangeListener(this.requestUpdate, this);
@@ -999,6 +1042,8 @@ export class AiAssistancePanel extends UI.Panel.Panel {
999
1042
  Workspace.UISourceCode.UISourceCode, this.#handleUISourceCodeFlavorChange);
1000
1043
  UI.Context.Context.instance().addFlavorChangeListener(
1001
1044
  Workspace.UISourceCode.UILocation, this.#handleBreakpointFlavorChange);
1045
+ UI.Context.Context.instance().addFlavorChangeListener(
1046
+ LighthousePanel.LighthousePanel.ActiveLighthouseReport, this.#handleLighthouseReportFlavorChange);
1002
1047
 
1003
1048
  UI.ViewManager.ViewManager.instance().addEventListener(
1004
1049
  UI.ViewManager.Events.VIEW_VISIBILITY_CHANGED, this.#selectDefaultAgentIfNeeded, this);
@@ -1033,6 +1078,9 @@ export class AiAssistancePanel extends UI.Panel.Panel {
1033
1078
  AiAssistanceModel.AIContext.AgentFocus, this.#handlePerformanceTraceFlavorChange);
1034
1079
  UI.Context.Context.instance().removeFlavorChangeListener(
1035
1080
  Workspace.UISourceCode.UISourceCode, this.#handleUISourceCodeFlavorChange);
1081
+ UI.Context.Context.instance().removeFlavorChangeListener(
1082
+ LighthousePanel.LighthousePanel.ActiveLighthouseReport, this.#handleLighthouseReportFlavorChange);
1083
+
1036
1084
  UI.ViewManager.ViewManager.instance().removeEventListener(
1037
1085
  UI.ViewManager.Events.VIEW_VISIBILITY_CHANGED, this.#selectDefaultAgentIfNeeded, this);
1038
1086
  UI.Context.Context.instance().removeFlavorChangeListener(
@@ -1132,6 +1180,17 @@ export class AiAssistancePanel extends UI.Panel.Panel {
1132
1180
  this.#updateConversationState(this.#conversation);
1133
1181
  };
1134
1182
 
1183
+ #handleLighthouseReportFlavorChange =
1184
+ (ev: Common.EventTarget.EventTargetEvent<LighthousePanel.LighthousePanel.ActiveLighthouseReport>): void => {
1185
+ const newReport = ev.data;
1186
+
1187
+ if (this.#selectedAccessibility?.getItem() === newReport?.report) {
1188
+ return;
1189
+ }
1190
+ this.#selectedAccessibility = createAccessibilityContext(newReport);
1191
+ this.#updateConversationState(this.#conversation);
1192
+ };
1193
+
1135
1194
  #getChangeSummary(): string|undefined {
1136
1195
  if (!isAiAssistancePatchingEnabled() || !this.#conversation || this.#conversation?.isReadOnly) {
1137
1196
  return;
@@ -1230,7 +1289,12 @@ export class AiAssistancePanel extends UI.Panel.Panel {
1230
1289
  }
1231
1290
  case AiAssistanceModel.AiHistoryStorage.ConversationType.BREAKPOINT:
1232
1291
  return lockedString(UIStringsNotTranslate.inputPlaceholderForNoContext);
1292
+ case AiAssistanceModel.AiHistoryStorage.ConversationType.ACCESSIBILITY:
1293
+ return this.#conversation.selectedContext ?
1294
+ lockedString(UIStringsNotTranslate.inputPlaceholderForAccessibility) :
1295
+ lockedString(UIStringsNotTranslate.inputPlaceholderForAccessibilityNoContext);
1233
1296
  case AiAssistanceModel.AiHistoryStorage.ConversationType.NONE:
1297
+
1234
1298
  if (AiAssistanceModel.AiUtils.isGeminiBranding()) {
1235
1299
  return lockedString(UIStringsNotTranslate.inputPlaceholderForNoContextBranded);
1236
1300
  }
@@ -1270,7 +1334,14 @@ export class AiAssistancePanel extends UI.Panel.Panel {
1270
1334
  }
1271
1335
  return lockedString(UIStringsNotTranslate.inputDisclaimerForPerformance);
1272
1336
 
1337
+ case AiAssistanceModel.AiHistoryStorage.ConversationType.ACCESSIBILITY:
1338
+ if (noLogging) {
1339
+ return lockedString(UIStringsNotTranslate.inputDisclaimerForAccessibilityEnterpriseNoLogging);
1340
+ }
1341
+ return lockedString(UIStringsNotTranslate.inputDisclaimerForAccessibility);
1342
+
1273
1343
  case AiAssistanceModel.AiHistoryStorage.ConversationType.BREAKPOINT:
1344
+
1274
1345
  case AiAssistanceModel.AiHistoryStorage.ConversationType.NONE:
1275
1346
  if (noLogging) {
1276
1347
  return lockedString(UIStringsNotTranslate.inputDisclaimerForNoContextEnterpriseNoLogging);
@@ -1536,7 +1607,10 @@ export class AiAssistancePanel extends UI.Panel.Panel {
1536
1607
  return this.#selectedPerformanceTrace;
1537
1608
  case AiAssistanceModel.AiHistoryStorage.ConversationType.BREAKPOINT:
1538
1609
  return this.#selectedBreakpoint;
1610
+ case AiAssistanceModel.AiHistoryStorage.ConversationType.ACCESSIBILITY:
1611
+ return this.#selectedAccessibility;
1539
1612
  case AiAssistanceModel.AiHistoryStorage.ConversationType.NONE:
1613
+
1540
1614
  case undefined:
1541
1615
  return null;
1542
1616
  }
@@ -1553,6 +1627,8 @@ export class AiAssistancePanel extends UI.Panel.Panel {
1553
1627
  this.#selectedPerformanceTrace = data;
1554
1628
  } else if (data instanceof AiAssistanceModel.BreakpointDebuggerAgent.BreakpointContext) {
1555
1629
  this.#selectedBreakpoint = data;
1630
+ } else if (data instanceof AiAssistanceModel.AccessibilityAgent.AccessibilityContext) {
1631
+ this.#selectedAccessibility = data;
1556
1632
  }
1557
1633
 
1558
1634
  void VisualLogging.logFunctionCall(`context-change-${this.#conversation?.type}`);
@@ -1720,7 +1796,7 @@ export class AiAssistancePanel extends UI.Panel.Panel {
1720
1796
  break;
1721
1797
  }
1722
1798
  case AiAssistanceModel.AiAgent.ResponseType.CONTEXT: {
1723
- step.title = data.title;
1799
+ step.title = lockedString(UIStringsNotTranslate.analyzingData);
1724
1800
  step.contextDetails = data.details;
1725
1801
  step.widgets = data.widgets;
1726
1802
  step.isLoading = false;
@@ -1839,9 +1915,9 @@ export class AiAssistancePanel extends UI.Panel.Panel {
1839
1915
  case AiAssistanceModel.AiAgent.ResponseType.CONTEXT_CHANGE: {
1840
1916
  this.#handleConversationContextChange(data.context);
1841
1917
  step.isLoading = false;
1918
+ step.widgets = data.widgets;
1842
1919
  commitStep();
1843
1920
  step = {isLoading: true};
1844
-
1845
1921
  break;
1846
1922
  }
1847
1923
  }
@@ -1860,12 +1936,12 @@ export class AiAssistancePanel extends UI.Panel.Panel {
1860
1936
  }
1861
1937
 
1862
1938
  // Announce as status update to screen readers when:
1863
- // * Context is received (e.g. Analyzing the prompt)
1939
+ // * Context is received (e.g. Analyzing data)
1864
1940
  // * Answer started streaming
1865
1941
  // * Answer finished streaming
1866
1942
  switch (data.type) {
1867
1943
  case AiAssistanceModel.AiAgent.ResponseType.CONTEXT:
1868
- UI.ARIAUtils.LiveAnnouncer.status(data.title);
1944
+ UI.ARIAUtils.LiveAnnouncer.status(lockedString(UIStringsNotTranslate.analyzingData));
1869
1945
  break;
1870
1946
  case AiAssistanceModel.AiAgent.ResponseType.ANSWER: {
1871
1947
  if (!data.complete && !announcedAnswerLoading) {
@@ -280,7 +280,7 @@ const DEFAULT_VIEW: View = (input, output, target) => {
280
280
 
281
281
  // clang-format off
282
282
  return html`<devtools-widget class="copy-to-prompt"
283
- .widgetConfig=${UI.Widget.widgetConfig(PanelCommon.CopyChangesToPrompt, {
283
+ ${widget(PanelCommon.CopyChangesToPrompt, {
284
284
  workspaceDiff: input.workspaceDiff,
285
285
  patchAgentCSSChange: changedCode,
286
286
  })}></devtools-widget>`;
@@ -347,6 +347,8 @@ export const DEFAULT_VIEW = (input: ViewInput, _output: ViewOutput, target: HTML
347
347
  PanelUtils.PanelUtils.getIconForNetworkRequest(input.context.getItem()) :
348
348
  input.context instanceof AiAssistanceModel.FileAgent.FileContext ?
349
349
  PanelUtils.PanelUtils.getIconForSourceFile(input.context.getItem()) :
350
+ input.context instanceof AiAssistanceModel.AccessibilityAgent.AccessibilityContext ?
351
+ html`<devtools-icon class="icon" name="performance" title="Lighthouse"></devtools-icon>` :
350
352
  input.context instanceof AiAssistanceModel.PerformanceAgent.PerformanceTraceContext ?
351
353
  html`<devtools-icon class="icon" name="performance" title="Performance"></devtools-icon>` :
352
354
  Lit.nothing}
@@ -8,13 +8,13 @@ import '../../../ui/kit/kit.js';
8
8
  import * as Common from '../../../core/common/common.js';
9
9
  import * as Host from '../../../core/host/host.js';
10
10
  import * as i18n from '../../../core/i18n/i18n.js';
11
- import type * as Platform from '../../../core/platform/platform.js';
11
+ import * as Platform from '../../../core/platform/platform.js';
12
12
  import * as Root from '../../../core/root/root.js';
13
13
  import * as SDK from '../../../core/sdk/sdk.js';
14
14
  import type * as Protocol from '../../../generated/protocol.js';
15
15
  import type {
16
- AiWidget, ComputedStyleAiWidget, CoreVitalsAiWidget, StylePropertiesAiWidget} from
17
- '../../../models/ai_assistance/agents/AiAgent.js';
16
+ AiWidget, ComputedStyleAiWidget, CoreVitalsAiWidget, DomTreeAiWidget, LcpBreakdownAiWidget, PerformanceTraceAiWidget,
17
+ StylePropertiesAiWidget} from '../../../models/ai_assistance/agents/AiAgent.js';
18
18
  import * as AiAssistanceModel from '../../../models/ai_assistance/ai_assistance.js';
19
19
  import * as ComputedStyle from '../../../models/computed_style/computed_style.js';
20
20
  import * as Marked from '../../../third_party/marked/marked.js';
@@ -28,7 +28,10 @@ import * as Lit from '../../../ui/lit/lit.js';
28
28
  import * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';
29
29
  import * as Elements from '../../elements/elements.js';
30
30
  import * as TimelineComponents from '../../timeline/components/components.js';
31
+ import * as TimelineInsights from '../../timeline/components/insights/insights.js';
32
+ import * as Timeline from '../../timeline/timeline.js';
31
33
  import * as TimelineUtils from '../../timeline/utils/utils.js';
34
+ import {PanelUtils} from '../../utils/utils.js';
32
35
 
33
36
  import chatMessageStyles from './chatMessage.css.js';
34
37
  import {walkthroughTitle, WalkthroughView} from './WalkthroughView.js';
@@ -174,7 +177,11 @@ const UIStringsNotTranslate = {
174
177
  /**
175
178
  * @description Title for the button that takes the user into other DevTools panels to reveal items the AI references.
176
179
  */
177
- reveal: 'Reveal'
180
+ reveal: 'Reveal',
181
+ /**
182
+ * @description Title used for revealing the performance trace.
183
+ */
184
+ revealTrace: 'Reveal trace'
178
185
  } as const;
179
186
 
180
187
  export interface Step {
@@ -644,8 +651,10 @@ export function renderStep({step, isLoading, markdownRenderer, isLast}: {
644
651
  }
645
652
 
646
653
  interface WidgetMakerResponse {
647
- renderedWidget: Lit.LitTemplate;
654
+ // Can be null if the widget is only used to add the Reveal CTA.
655
+ renderedWidget: Lit.LitTemplate|null;
648
656
  revealable: unknown;
657
+ customRevealTitle?: Platform.UIString.LocalizedString;
649
658
  }
650
659
 
651
660
  const nodeCache = new Map<Protocol.DOM.BackendNodeId, SDK.DOMModel.DOMNode>();
@@ -676,33 +685,29 @@ async function makeComputedStyleWidget(widgetData: ComputedStyleAiWidget): Promi
676
685
  }
677
686
  const styles = new ComputedStyle.ComputedStyleModel.ComputedStyle(domNodeForId, widgetData.data.computedStyles);
678
687
 
679
- const widgetConfig = UI.Widget.widgetConfig(Elements.ComputedStyleWidget.ComputedStyleWidget, {
680
- nodeStyle: styles,
681
- matchedStyles: widgetData.data.matchedCascade,
682
- // This disables showing the nested traces and detailed information in the widget.
683
- propertyTraces: null,
684
- allowUserControl: false,
685
- filterText: new RegExp(widgetData.data.properties.join('|'), 'i')
686
- });
687
-
688
688
  // clang-format off
689
- const widget = html`<devtools-widget class="computed-styles-widget" .widgetConfig=${widgetConfig}></devtools-widget>`;
689
+ const renderedWidget = html`<devtools-widget
690
+ class="computed-styles-widget" ${widget(Elements.ComputedStyleWidget.ComputedStyleWidget, {
691
+ nodeStyle: styles,
692
+ matchedStyles: widgetData.data.matchedCascade,
693
+ // This disables showing the nested traces and detailed information in the widget.
694
+ propertyTraces: null,
695
+ allowUserControl: false,
696
+ filterText: new RegExp(widgetData.data.properties.join('|'), 'i')
697
+ })}></devtools-widget>`;
690
698
  // clang-format on
691
699
 
692
- return {renderedWidget: widget, revealable: new Elements.ElementsPanel.NodeComputedStyles(domNodeForId)};
700
+ return {renderedWidget, revealable: new Elements.ElementsPanel.NodeComputedStyles(domNodeForId)};
693
701
  }
694
702
 
695
703
  async function makeCoreVitalsWidget(widgetData: CoreVitalsAiWidget): Promise<WidgetMakerResponse|null> {
696
- const widgetConfig = UI.Widget.widgetConfig(TimelineComponents.CWVMetrics.CWVMetrics, {data: widgetData.data});
697
-
698
704
  // clang-format off
699
- const widget = html`<devtools-widget class="core-vitals-widget" .widgetConfig=${widgetConfig}></devtools-widget>`;
705
+ const renderedWidget = html`<devtools-widget
706
+ class="core-vitals-widget" ${widget(TimelineComponents.CWVMetrics.CWVMetrics, {data: widgetData.data})}>
707
+ </devtools-widget>`;
700
708
  // clang-format on
701
709
 
702
- return {
703
- renderedWidget: widget,
704
- revealable: new TimelineUtils.Helpers.RevealableCoreVitals(widgetData.data.insightSetKey)
705
- };
710
+ return {renderedWidget, revealable: new TimelineUtils.Helpers.RevealableCoreVitals(widgetData.data.insightSetKey)};
706
711
  }
707
712
 
708
713
  async function makeStylePropertiesWidget(widgetData: StylePropertiesAiWidget): Promise<WidgetMakerResponse|null> {
@@ -711,19 +716,37 @@ async function makeStylePropertiesWidget(widgetData: StylePropertiesAiWidget): P
711
716
  return null;
712
717
  }
713
718
 
714
- const widgetConfig = UI.Widget.widgetConfig(Elements.StandaloneStylesContainer.StandaloneStylesContainer, {
715
- domNode: domNodeForId,
716
- filter: widgetData.data.selector ? new RegExp(widgetData.data.selector) : null,
719
+ // clang-format off
720
+ const renderedWidget = html`<devtools-widget
721
+ class="styling-preview-widget"
722
+ ${widget(Elements.StandaloneStylesContainer.StandaloneStylesContainer, {
723
+ domNode: domNodeForId,
724
+ filter: widgetData.data.selector ? new RegExp(widgetData.data.selector) : null,
725
+ })}>
726
+ </devtools-widget>`;
727
+ // clang-format on
728
+
729
+ return {renderedWidget, revealable: domNodeForId};
730
+ }
731
+
732
+ async function makeLcpBreakdownWidget(widgetData: LcpBreakdownAiWidget): Promise<WidgetMakerResponse|null> {
733
+ const insight = widgetData.data.lcpData;
734
+ if (!insight) {
735
+ return null;
736
+ }
737
+
738
+ const widgetConfig = UI.Widget.widgetConfig(TimelineInsights.LCPBreakdown.LCPBreakdown, {
739
+ model: insight,
740
+ minimal: true,
717
741
  });
718
742
 
719
743
  // clang-format off
720
- const widget = html`<devtools-widget
721
- class="styling-preview-widget"
722
- .widgetConfig=${widgetConfig}
723
- ></devtools-widget>`;
744
+ const renderedWidget = html`<devtools-widget
745
+ class="lcp-breakdown-widget"
746
+ .widgetConfig=${widgetConfig}></devtools-widget>`;
724
747
  // clang-format on
725
748
 
726
- return {renderedWidget: widget, revealable: domNodeForId};
749
+ return {renderedWidget, revealable: new TimelineUtils.Helpers.RevealableInsight(insight)};
727
750
  }
728
751
 
729
752
  function renderWidgetResponse(response: WidgetMakerResponse|null): Lit.LitTemplate {
@@ -738,24 +761,97 @@ function renderWidgetResponse(response: WidgetMakerResponse|null): Lit.LitTempla
738
761
  void Common.Revealer.reveal(response?.revealable);
739
762
  }
740
763
 
764
+ const classes = Lit.Directives.classMap({
765
+ 'widget-and-revealer-container': true,
766
+ 'revealer-only': response.renderedWidget === null,
767
+ });
741
768
  // clang-format off
742
769
  return html`
743
- <div class="widget-and-revealer-container">
744
- <div class="widget-content-container">
745
- ${response.renderedWidget}
746
- </div>
770
+ <div class=${classes}>
771
+ ${response.renderedWidget ? html`
772
+ <div class="widget-content-container">
773
+ ${response.renderedWidget}
774
+ </div>` : Lit.nothing
775
+ }
747
776
  <div class="widget-reveal-container">
748
777
  <devtools-button class="widget-reveal"
749
778
  .iconName=${'tab-move'}
750
779
  .variant=${Buttons.Button.Variant.TEXT}
751
780
  @click=${onReveal}
752
- >${lockedString(UIStringsNotTranslate.reveal)}</devtools-button>
781
+ >${response.customRevealTitle ?? lockedString(UIStringsNotTranslate.reveal)}</devtools-button>
753
782
  </div>
754
783
  </div>
755
784
  `;
756
785
  // clang-format on
757
786
  }
758
787
 
788
+ async function makePerformanceTraceWidget(widgetData: PerformanceTraceAiWidget): Promise<WidgetMakerResponse|null> {
789
+ return {
790
+ renderedWidget: null,
791
+ revealable: new Timeline.TimelinePanel.ParsedTraceRevealable(widgetData.data.parsedTrace),
792
+ customRevealTitle: lockedString(UIStringsNotTranslate.revealTrace),
793
+ };
794
+ }
795
+
796
+ function renderNetworkRequestPreview(networkRequest: NonNullable<DomTreeAiWidget['data']['networkRequest']>):
797
+ Lit.TemplateResult {
798
+ const filename = networkRequest.url.split('/').pop() || networkRequest.url;
799
+ const size = i18n.ByteUtilities.bytesToString(networkRequest.size);
800
+ const resourceType = Common.ResourceType.resourceTypes[networkRequest.resourceType];
801
+ const {iconName, color} = PanelUtils.iconDataForResourceType(resourceType);
802
+
803
+ return html`
804
+ <div class="network-request-preview">
805
+ <div class="network-request-header">
806
+ <div class="network-request-icon">
807
+ ${
808
+ resourceType.isImage() ? html`<img src=${networkRequest.imageUrl ?? networkRequest.url} alt=${filename} />` :
809
+ html`<devtools-icon name=${iconName} style=${Lit.Directives.styleMap({
810
+ color: color ?? ''
811
+ })}></devtools-icon>`}
812
+ </div>
813
+ <div class="network-request-details">
814
+ <div class="network-request-name" title=${networkRequest.url}>${filename}</div>
815
+ <div class="network-request-size">${size}</div>
816
+ </div>
817
+ </div>
818
+ </div>
819
+ `;
820
+ }
821
+
822
+ async function makeDomTreeWidget(widgetData: DomTreeAiWidget): Promise<WidgetMakerResponse|null> {
823
+ const root = widgetData.data.root;
824
+ if (!(root instanceof SDK.DOMModel.DOMNodeSnapshot)) {
825
+ return null;
826
+ }
827
+
828
+ const widgetConfig = UI.Widget.widgetConfig(Elements.ElementsTreeOutline.DOMTreeWidget, {
829
+ maxTreeDepth: 2,
830
+ enableContextMenu: false,
831
+ showComments: false,
832
+ showAIButton: false,
833
+ disableEdits: true,
834
+ expandRoot: true,
835
+ rootDOMNode: root,
836
+ visibleWidth: 400,
837
+ wrap: true,
838
+ });
839
+
840
+ const networkRequest = widgetData.data.networkRequest;
841
+
842
+ // clang-format off
843
+ const renderedWidget = html`
844
+ ${networkRequest ? renderNetworkRequestPreview(networkRequest) : Lit.nothing}
845
+ <devtools-widget class="dom-tree-widget" .widgetConfig=${widgetConfig}></devtools-widget>
846
+ `;
847
+ // clang-format on
848
+
849
+ return {
850
+ renderedWidget,
851
+ revealable: new SDK.DOMModel.DeferredDOMNode(root.domModel().target(), root.backendNodeId()),
852
+ };
853
+ }
854
+
759
855
  /**
760
856
  * Renders AI-defined UI widgets.
761
857
  * When a ModelChatMessage contains a WidgetPart, or a Step has widgets,
@@ -780,12 +876,27 @@ async function renderWidgets(
780
876
  }
781
877
  const ui = await Promise.all(widgets.map(async widgetData => {
782
878
  let response: WidgetMakerResponse|null = null;
783
- if (widgetData.name === 'COMPUTED_STYLES') {
784
- response = await makeComputedStyleWidget(widgetData);
785
- } else if (widgetData.name === 'CORE_VITALS') {
786
- response = await makeCoreVitalsWidget(widgetData);
787
- } else if (widgetData.name === 'STYLE_PROPERTIES') {
788
- response = await makeStylePropertiesWidget(widgetData);
879
+ switch (widgetData.name) {
880
+ case 'COMPUTED_STYLES':
881
+ response = await makeComputedStyleWidget(widgetData);
882
+ break;
883
+ case 'CORE_VITALS':
884
+ response = await makeCoreVitalsWidget(widgetData);
885
+ break;
886
+ case 'STYLE_PROPERTIES':
887
+ response = await makeStylePropertiesWidget(widgetData);
888
+ break;
889
+ case 'DOM_TREE':
890
+ response = await makeDomTreeWidget(widgetData);
891
+ break;
892
+ case 'PERFORMANCE_TRACE':
893
+ response = await makePerformanceTraceWidget(widgetData);
894
+ break;
895
+ case 'LCP_BREAKDOWN':
896
+ response = await makeLcpBreakdownWidget(widgetData);
897
+ break;
898
+ default:
899
+ Platform.assertNever(widgetData, 'Unknown AiWidget name');
789
900
  }
790
901
  return renderWidgetResponse(response);
791
902
  }));
@@ -169,7 +169,7 @@ const DEFAULT_VIEW: View = (input, output, target) => {
169
169
  </div>
170
170
  </div>
171
171
  `}
172
- <devtools-widget class=${inputWidgetClasses} .widgetConfig=${UI.Widget.widgetConfig(ChatInput, {
172
+ <devtools-widget class=${inputWidgetClasses} ${widget(ChatInput, {
173
173
  isLoading: input.isLoading,
174
174
  blockedByCrossOrigin: input.blockedByCrossOrigin,
175
175
  isTextInputDisabled: input.isTextInputDisabled,
@@ -380,6 +380,11 @@
380
380
  padding: 0 var(--sys-size-4) var(--sys-size-4) 0;
381
381
  }
382
382
 
383
+ .revealer-only .widget-reveal-container {
384
+ background: none;
385
+ border-radius: unset;
386
+ }
387
+
383
388
  .widget-content-container {
384
389
  padding: var(--sys-size-4);
385
390
  border-top-left-radius: var(--sys-shape-corner-medium);
@@ -389,4 +394,60 @@
389
394
 
390
395
  --override-computed-style-property-white-space: normal;
391
396
  }
397
+
398
+ .network-request-preview {
399
+ display: flex;
400
+ flex-direction: column;
401
+ gap: var(--sys-size-4);
402
+ margin-bottom: var(--sys-size-5);
403
+ padding-bottom: var(--sys-size-5);
404
+ border-bottom: 1px solid var(--sys-color-divider);
405
+
406
+ .network-request-header {
407
+ display: flex;
408
+ align-items: center;
409
+ gap: var(--sys-size-5);
410
+
411
+ .network-request-icon {
412
+ width: 32px;
413
+ height: 32px;
414
+ display: flex;
415
+ align-items: center;
416
+ justify-content: center;
417
+ background-color: var(--sys-color-surface1);
418
+ border-radius: var(--sys-shape-corner-small);
419
+ border: 1px solid var(--sys-color-divider);
420
+ overflow: hidden;
421
+
422
+ img {
423
+ max-width: 100%;
424
+ max-height: 100%;
425
+ object-fit: contain;
426
+ }
427
+
428
+ devtools-icon {
429
+ width: 20px;
430
+ height: 20px;
431
+ }
432
+ }
433
+
434
+ .network-request-details {
435
+ display: flex;
436
+ flex-direction: column;
437
+ overflow: hidden;
438
+
439
+ .network-request-name {
440
+ font: var(--sys-typescale-body4-bold);
441
+ overflow: hidden;
442
+ text-overflow: ellipsis;
443
+ white-space: nowrap;
444
+ }
445
+
446
+ .network-request-size {
447
+ font: var(--sys-typescale-body4-regular);
448
+ color: var(--sys-color-on-surface-subtle);
449
+ }
450
+ }
451
+ }
452
+ }
392
453
  }