chrome-devtools-frontend 1.0.1519267 → 1.0.1520535

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 (94) hide show
  1. package/config/owner/COMMON_OWNERS +1 -2
  2. package/config/typescript/tsconfig.eslint.json +12 -1
  3. package/docs/ui_engineering.md +1011 -0
  4. package/front_end/core/host/GdpClient.ts +26 -5
  5. package/front_end/core/sdk/NetworkManager.ts +1 -0
  6. package/front_end/core/sdk/NetworkRequest.ts +10 -0
  7. package/front_end/entrypoints/main/MainImpl.ts +6 -1
  8. package/front_end/entrypoints/main/main-meta.ts +3 -3
  9. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +50 -48
  10. package/front_end/models/ai_assistance/agents/PerformanceAnnotationsAgent.ts +4 -4
  11. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +128 -30
  12. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +98 -63
  13. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +317 -640
  14. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +36 -21
  15. package/front_end/models/ai_assistance/performance/AICallTree.snapshot.txt +75 -0
  16. package/front_end/models/ai_assistance/performance/AICallTree.ts +14 -6
  17. package/front_end/models/ai_assistance/performance/AIContext.ts +62 -7
  18. package/front_end/models/ai_code_completion/AiCodeCompletion.ts +5 -5
  19. package/front_end/models/badges/Badge.ts +6 -1
  20. package/front_end/models/badges/StarterBadge.ts +5 -0
  21. package/front_end/models/badges/UserBadges.ts +5 -4
  22. package/front_end/models/javascript_metadata/NativeFunctions.js +5 -1
  23. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +14 -7
  24. package/front_end/panels/ai_assistance/PatchWidget.ts +17 -55
  25. package/front_end/panels/ai_assistance/components/ChatView.ts +45 -69
  26. package/front_end/panels/ai_assistance/components/PerformanceAgentMarkdownRenderer.ts +47 -1
  27. package/front_end/panels/ai_assistance/components/chatView.css +13 -1
  28. package/front_end/panels/animation/AnimationTimeline.ts +1 -1
  29. package/front_end/panels/animation/animationTimeline.css +4 -0
  30. package/front_end/panels/application/preloading/components/PreloadingString.ts +2 -5
  31. package/front_end/panels/common/AiCodeCompletionTeaser.ts +5 -0
  32. package/front_end/panels/common/aiCodeCompletionTeaser.css +6 -1
  33. package/front_end/panels/console/ConsolePrompt.ts +6 -0
  34. package/front_end/panels/console/ConsoleView.ts +4 -2
  35. package/front_end/panels/coverage/CoverageListView.ts +146 -198
  36. package/front_end/panels/coverage/CoverageView.ts +48 -18
  37. package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +2 -0
  38. package/front_end/panels/network/NetworkDataGridNode.ts +22 -0
  39. package/front_end/panels/network/NetworkLogViewColumns.ts +9 -0
  40. package/front_end/panels/recorder/components/CreateRecordingView.ts +2 -0
  41. package/front_end/panels/search/SearchResultsPane.ts +48 -15
  42. package/front_end/panels/search/SearchView.ts +33 -30
  43. package/front_end/panels/search/searchView.css +0 -2
  44. package/front_end/panels/settings/components/SyncSection.ts +4 -4
  45. package/front_end/panels/sources/AiCodeCompletionPlugin.ts +1 -4
  46. package/front_end/panels/sources/DebuggerPlugin.ts +4 -0
  47. package/front_end/panels/timeline/ThirdPartyTreeView.ts +1 -1
  48. package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +0 -8
  49. package/front_end/panels/timeline/TimelineFlameChartView.ts +5 -5
  50. package/front_end/panels/timeline/TimelinePanel.ts +2 -0
  51. package/front_end/panels/timeline/TimelineTreeView.ts +1 -1
  52. package/front_end/panels/timeline/components/ExportTraceOptions.ts +56 -4
  53. package/front_end/panels/timeline/components/exportTraceOptions.css +5 -0
  54. package/front_end/third_party/chromium/README.chromium +1 -1
  55. package/front_end/third_party/lighthouse/README.chromium +8 -1
  56. package/front_end/third_party/puppeteer/README.chromium +2 -2
  57. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Realm.d.ts +2 -2
  58. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/version.d.ts +1 -1
  59. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/version.js +1 -1
  60. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
  61. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js +1 -1
  62. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js.map +1 -1
  63. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/PipeTransport.d.ts.map +1 -1
  64. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/PipeTransport.js +15 -16
  65. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/PipeTransport.js.map +1 -1
  66. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +2 -2
  67. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +2 -2
  68. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Function.js +1 -1
  69. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Function.js.map +1 -1
  70. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
  71. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +4 -4
  72. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.d.ts +1 -1
  73. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.js +1 -1
  74. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js +1 -1
  75. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js.map +1 -1
  76. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/PipeTransport.d.ts.map +1 -1
  77. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/PipeTransport.js +15 -16
  78. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/PipeTransport.js.map +1 -1
  79. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +2 -2
  80. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +2 -2
  81. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/Function.js +1 -1
  82. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/Function.js.map +1 -1
  83. package/front_end/third_party/puppeteer/package/package.json +3 -2
  84. package/front_end/third_party/puppeteer/package/src/generated/version.ts +1 -1
  85. package/front_end/third_party/puppeteer/package/src/node/BrowserLauncher.ts +1 -1
  86. package/front_end/third_party/puppeteer/package/src/node/PipeTransport.ts +15 -17
  87. package/front_end/third_party/puppeteer/package/src/revisions.ts +2 -2
  88. package/front_end/third_party/puppeteer/package/src/util/Function.ts +1 -1
  89. package/front_end/tsconfig.json +12 -1
  90. package/front_end/ui/legacy/InspectorView.ts +86 -13
  91. package/front_end/ui/legacy/TabbedPane.ts +2 -1
  92. package/front_end/ui/visual_logging/KnownContextValues.ts +6 -0
  93. package/front_end/ui/visual_logging/LoggingEvents.ts +1 -1
  94. package/package.json +1 -1
@@ -214,8 +214,8 @@ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
214
214
  const lockedString = i18n.i18n.lockedString;
215
215
 
216
216
  const SCROLL_ROUNDING_OFFSET = 1;
217
- const TOOLTIP_POPOVER_OFFSET = 4;
218
- const RELEVANT_DATA_LINK_ID = 'relevant-data-link';
217
+ const RELEVANT_DATA_LINK_FOOTER_ID = 'relevant-data-link-footer';
218
+ const RELEVANT_DATA_LINK_CHAT_ID = 'relevant-data-link-chat';
219
219
 
220
220
  export interface Step {
221
221
  isLoading: boolean;
@@ -313,7 +313,6 @@ export class ChatView extends HTMLElement {
313
313
  #messagesContainerElement?: Element;
314
314
  #mainElementRef?: Lit.Directives.Ref<Element> = Lit.Directives.createRef();
315
315
  #messagesContainerResizeObserver = new ResizeObserver(() => this.#handleMessagesContainerResize());
316
- #popoverHelper: UI.PopoverHelper.PopoverHelper|null = null;
317
316
  /**
318
317
  * Indicates whether the chat scroll position should be pinned to the bottom.
319
318
  *
@@ -391,63 +390,6 @@ export class ChatView extends HTMLElement {
391
390
  this.#setMainElementScrollTop(this.#mainElementRef.value.scrollHeight);
392
391
  }
393
392
 
394
- #handleChatUiRef(el: Element|undefined): void {
395
- if (!el || this.#popoverHelper) {
396
- return;
397
- }
398
-
399
- // TODO: Update here when b/409965560 is fixed.
400
- this.#popoverHelper = new UI.PopoverHelper.PopoverHelper((el as HTMLElement), event => {
401
- const popoverShownNode =
402
- event.target instanceof HTMLElement && event.target.id === RELEVANT_DATA_LINK_ID ? event.target : null;
403
- if (!popoverShownNode) {
404
- return null;
405
- }
406
-
407
- // We move the glass pane to be a bit lower so
408
- // that it does not disappear when moving the cursor
409
- // over to link.
410
- const nodeBox = popoverShownNode.boxInWindow();
411
- nodeBox.y = nodeBox.y + TOOLTIP_POPOVER_OFFSET;
412
- return {
413
- box: nodeBox,
414
- show: async (popover: UI.GlassPane.GlassPane) => {
415
- // clang-format off
416
- Lit.render(html`
417
- <style>
418
- .info-tooltip-container {
419
- max-width: var(--sys-size-28);
420
- padding: var(--sys-size-4) var(--sys-size-5);
421
-
422
- .tooltip-link {
423
- display: block;
424
- margin-top: var(--sys-size-4);
425
- color: var(--sys-color-primary);
426
- padding-left: 0;
427
- }
428
- }
429
- </style>
430
- <div class="info-tooltip-container">
431
- ${this.#props.disclaimerText}
432
- <button
433
- class="link tooltip-link"
434
- role="link"
435
- jslog=${VisualLogging.link('open-ai-settings').track({
436
- click: true,
437
- })}
438
- @click=${() => {
439
- void UI.ViewManager.ViewManager.instance().showView('chrome-ai');
440
- }}
441
- >${i18nString(UIStrings.learnAbout)}</button>
442
- </div>`, popover.contentElement, {host: this});
443
- // clang-format on
444
- return true;
445
- },
446
- };
447
- });
448
- this.#popoverHelper.setTimeout(0);
449
- }
450
-
451
393
  #handleMessagesContainerResize(): void {
452
394
  if (!this.#pinScrollToBottom) {
453
395
  return;
@@ -583,9 +525,11 @@ export class ChatView extends HTMLElement {
583
525
  // clang-format off
584
526
  const footerContents = this.#props.conversationType
585
527
  ? renderRelevantDataDisclaimer({
586
- isLoading: this.#props.isLoading,
587
- blockedByCrossOrigin: this.#props.blockedByCrossOrigin,
588
- })
528
+ isLoading: this.#props.isLoading,
529
+ blockedByCrossOrigin: this.#props.blockedByCrossOrigin,
530
+ tooltipId: RELEVANT_DATA_LINK_FOOTER_ID,
531
+ disclaimerText: this.#props.disclaimerText,
532
+ })
589
533
  : html`<p>
590
534
  ${lockedString(UIStringsNotTranslate.inputDisclaimerForEmptyState)}
591
535
  <button
@@ -611,7 +555,7 @@ export class ChatView extends HTMLElement {
611
555
  // clang-format off
612
556
  Lit.render(html`
613
557
  <style>${chatViewStyles}</style>
614
- <div class="chat-ui" ${Lit.Directives.ref(this.#handleChatUiRef)}>
558
+ <div class="chat-ui">
615
559
  <main @scroll=${this.#handleScroll} ${ref(this.#mainElementRef)}>
616
560
  ${renderMainContents({
617
561
  state: this.#props.state,
@@ -643,6 +587,7 @@ export class ChatView extends HTMLElement {
643
587
  isTextInputDisabled: this.#props.isTextInputDisabled,
644
588
  inputPlaceholder: this.#props.inputPlaceholder,
645
589
  state: this.#props.state,
590
+ disclaimerText: this.#props.disclaimerText,
646
591
  selectedContext: this.#props.selectedContext,
647
592
  inspectElementToggled: this.#props.inspectElementToggled,
648
593
  multimodalInputEnabled: this.#props.multimodalInputEnabled,
@@ -1433,8 +1378,12 @@ function renderImageInput({
1433
1378
  // clang-format on
1434
1379
  }
1435
1380
 
1436
- function renderRelevantDataDisclaimer(
1437
- {isLoading, blockedByCrossOrigin}: {isLoading: boolean, blockedByCrossOrigin: boolean}): Lit.LitTemplate {
1381
+ function renderRelevantDataDisclaimer({isLoading, blockedByCrossOrigin, tooltipId, disclaimerText}: {
1382
+ isLoading: boolean,
1383
+ blockedByCrossOrigin: boolean,
1384
+ tooltipId: string,
1385
+ disclaimerText: string,
1386
+ }): Lit.LitTemplate {
1438
1387
  const classes =
1439
1388
  Lit.Directives.classMap({'chat-input-disclaimer': true, 'hide-divider': !isLoading && blockedByCrossOrigin});
1440
1389
  // clang-format off
@@ -1443,7 +1392,7 @@ function renderRelevantDataDisclaimer(
1443
1392
  <button
1444
1393
  class="link"
1445
1394
  role="link"
1446
- id=${RELEVANT_DATA_LINK_ID}
1395
+ aria-details=${tooltipId}
1447
1396
  jslog=${VisualLogging.link('open-ai-settings').track({
1448
1397
  click: true,
1449
1398
  })}
@@ -1451,6 +1400,7 @@ function renderRelevantDataDisclaimer(
1451
1400
  void UI.ViewManager.ViewManager.instance().showView('chrome-ai');
1452
1401
  }}
1453
1402
  >${lockedString('Relevant data')}</button>&nbsp;${lockedString('is sent to Google')}
1403
+ ${renderDisclamerTooltip(tooltipId, disclaimerText)}
1454
1404
  </p>
1455
1405
  `;
1456
1406
  // clang-format on
@@ -1470,6 +1420,7 @@ function renderChatInput({
1470
1420
  isTextInputEmpty,
1471
1421
  uploadImageInputEnabled,
1472
1422
  aidaAvailability,
1423
+ disclaimerText,
1473
1424
  onContextClick,
1474
1425
  onInspectElementClick,
1475
1426
  onSubmit,
@@ -1490,6 +1441,7 @@ function renderChatInput({
1490
1441
  inspectElementToggled: boolean,
1491
1442
  isTextInputEmpty: boolean,
1492
1443
  aidaAvailability: Host.AidaClient.AidaAccessPreconditions,
1444
+ disclaimerText: string,
1493
1445
  onContextClick: () => void,
1494
1446
  onInspectElementClick: () => void,
1495
1447
  onSubmit: (ev: SubmitEvent) => void,
@@ -1547,7 +1499,7 @@ function renderChatInput({
1547
1499
  </div>
1548
1500
  <div class="chat-input-actions-right">
1549
1501
  <div class="chat-input-disclaimer-container">
1550
- ${renderRelevantDataDisclaimer({isLoading, blockedByCrossOrigin})}
1502
+ ${renderRelevantDataDisclaimer({ isLoading, blockedByCrossOrigin, tooltipId: RELEVANT_DATA_LINK_CHAT_ID, disclaimerText})}
1551
1503
  </div>
1552
1504
  ${renderMultimodalInputButtons({
1553
1505
  multimodalInputEnabled, blockedByCrossOrigin, isTextInputDisabled, imageInput, uploadImageInputEnabled, onTakeScreenshot, onImageUpload
@@ -1578,7 +1530,7 @@ function renderAidaUnavailableContents(
1578
1530
  }
1579
1531
 
1580
1532
  function renderConsentViewContents(): Lit.TemplateResult {
1581
- const settingsLink = document.createElement('button');
1533
+ const settingsLink = document.createElement('span');
1582
1534
  settingsLink.textContent = i18nString(UIStrings.settingsLink);
1583
1535
  settingsLink.classList.add('link');
1584
1536
  UI.ARIAUtils.markAsLink(settingsLink);
@@ -1697,6 +1649,30 @@ function renderMainContents({
1697
1649
  return renderEmptyState({isTextInputDisabled, suggestions, onSuggestionClick});
1698
1650
  }
1699
1651
 
1652
+ function renderDisclamerTooltip(id: string, disclaimerText: string): Lit.TemplateResult {
1653
+ // clang-format off
1654
+ return html`
1655
+ <devtools-tooltip
1656
+ id=${id}
1657
+ variant=${'rich'}
1658
+ >
1659
+ <div class="info-tooltip-container">
1660
+ ${disclaimerText}
1661
+ <button
1662
+ class="link tooltip-link"
1663
+ role="link"
1664
+ jslog=${VisualLogging.link('open-ai-settings').track({
1665
+ click: true,
1666
+ })}
1667
+ @click=${() => {
1668
+ void UI.ViewManager.ViewManager.instance().showView('chrome-ai');
1669
+ }}>${i18nString(UIStrings.learnAbout)}
1670
+ </button>
1671
+ </div>
1672
+ </devtools-tooltip>`;
1673
+ // clang-format on
1674
+ }
1675
+
1700
1676
  declare global {
1701
1677
  interface HTMLElementTagNameMap {
1702
1678
  'devtools-ai-chat-view': ChatView;
@@ -4,6 +4,7 @@
4
4
 
5
5
  import * as Common from '../../../core/common/common.js';
6
6
  import * as SDK from '../../../core/sdk/sdk.js';
7
+ import type * as Protocol from '../../../generated/protocol.js';
7
8
  import * as Trace from '../../../models/trace/trace.js';
8
9
  import type * as Marked from '../../../third_party/marked/marked.js';
9
10
  import * as Lit from '../../../ui/lit/lit.js';
@@ -11,14 +12,32 @@ import * as Lit from '../../../ui/lit/lit.js';
11
12
  import {MarkdownRendererWithCodeBlock} from './MarkdownRendererWithCodeBlock.js';
12
13
 
13
14
  const {html} = Lit;
15
+ const {ref, createRef} = Lit.Directives;
14
16
 
15
17
  export class PerformanceAgentMarkdownRenderer extends MarkdownRendererWithCodeBlock {
16
- constructor(private lookupEvent: (key: Trace.Types.File.SerializableKey) => Trace.Types.Events.Event | null) {
18
+ constructor(
19
+ private mainFrameId = '',
20
+ private lookupEvent: (key: Trace.Types.File.SerializableKey) => Trace.Types.Events.Event | null = () => null) {
17
21
  super();
18
22
  }
19
23
 
20
24
  override templateForToken(token: Marked.Marked.MarkedToken): Lit.TemplateResult|null {
21
25
  if (token.type === 'link' && token.href.startsWith('#')) {
26
+ if (token.href.startsWith('#node-')) {
27
+ const nodeId = Number(token.href.replace('#node-', '')) as Protocol.DOM.BackendNodeId;
28
+
29
+ const templateRef = createRef();
30
+ void this.#linkifyNode(nodeId, token.text).then(node => {
31
+ if (!templateRef.value || !node) {
32
+ return;
33
+ }
34
+
35
+ templateRef.value.textContent = '';
36
+ templateRef.value.append(node);
37
+ });
38
+ return html`<span ${ref(templateRef)}>${token.text}</span>`;
39
+ }
40
+
22
41
  const event = this.lookupEvent(token.href.slice(1) as Trace.Types.File.SerializableKey);
23
42
  if (!event) {
24
43
  return html`${token.text}`;
@@ -41,4 +60,31 @@ export class PerformanceAgentMarkdownRenderer extends MarkdownRendererWithCodeBl
41
60
 
42
61
  return super.templateForToken(token);
43
62
  }
63
+
64
+ // Taken from front_end/panels/timeline/components/insights/NodeLink.ts
65
+ // Would be nice to move the above component to somewhere that allows the AI
66
+ // Assistance panel to also use it.
67
+ async #linkifyNode(backendNodeId: Protocol.DOM.BackendNodeId, label: string): Promise<Node|undefined> {
68
+ if (backendNodeId === undefined) {
69
+ return;
70
+ }
71
+
72
+ const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
73
+ const domModel = target?.model(SDK.DOMModel.DOMModel);
74
+ if (!domModel) {
75
+ return undefined;
76
+ }
77
+ const domNodesMap = await domModel.pushNodesByBackendIdsToFrontend(new Set([backendNodeId]));
78
+ const node = domNodesMap?.get(backendNodeId);
79
+ if (!node) {
80
+ return;
81
+ }
82
+
83
+ if (node.frameId() !== this.mainFrameId) {
84
+ return;
85
+ }
86
+
87
+ const linkedNode = await Common.Linkifier.Linkifier.linkify(node, {textContent: label});
88
+ return linkedNode;
89
+ }
44
90
  }
@@ -89,6 +89,18 @@
89
89
  color: var(--sys-color-on-surface-subtle);
90
90
  }
91
91
 
92
+ .info-tooltip-container {
93
+ max-width: var(--sys-size-28);
94
+ padding: var(--sys-size-4) var(--sys-size-5);
95
+ }
96
+
97
+ .tooltip-link {
98
+ display: block;
99
+ margin-top: var(--sys-size-4);
100
+ color: var(--sys-color-primary);
101
+ padding-left: 0;
102
+ }
103
+
92
104
  .chat-input-container {
93
105
  width: 100%;
94
106
  display: flex;
@@ -662,7 +674,7 @@ main {
662
674
  justify-content: center;
663
675
  font: var(--sys-typescale-headline4);
664
676
  gap: var(--sys-size-8);
665
- padding: var(--sys-size-3);
677
+ padding: var(--sys-size-4);
666
678
  max-width: var(--sys-size-33);
667
679
 
668
680
  /* Prevents the container from jumping when the scrollbar is shown */
@@ -282,7 +282,7 @@ export class AnimationTimeline extends UI.Widget.VBox implements
282
282
  this.#playbackRate = 1;
283
283
  this.#allPaused = false;
284
284
  this.#animationGroupPausedBeforeScrub = false;
285
- this.#toolbarViewContainer = this.contentElement.createChild('div');
285
+ this.#toolbarViewContainer = this.contentElement.createChild('div', 'toolbar-view-container');
286
286
  this.createHeader();
287
287
  this.#animationsContainer = this.contentElement.createChild('div', 'animation-timeline-rows');
288
288
  this.#animationsContainer.setAttribute('jslog', `${VisualLogging.section('animations')}`);
@@ -10,6 +10,10 @@
10
10
  --timeline-controls-width: 150px;
11
11
  }
12
12
 
13
+ .toolbar-view-container {
14
+ min-height: fit-content;
15
+ }
16
+
13
17
  .animation-node-row {
14
18
  width: 100%;
15
19
  display: flex;
@@ -723,11 +723,8 @@ export function ruleSetLocationShort(
723
723
 
724
724
  export function ruleSetTagOrLocationShort(
725
725
  ruleSet: Protocol.Preload.RuleSet, pageURL: Platform.DevToolsPath.UrlString): string {
726
- if (!ruleSet.errorMessage) {
727
- const parsedRuleset = JSON.parse(ruleSet['sourceText']);
728
- if ('tag' in parsedRuleset) {
729
- return '"' + parsedRuleset['tag'] + '"';
730
- }
726
+ if (!ruleSet.errorMessage && ruleSet.tag) {
727
+ return '"' + ruleSet.tag + '"';
731
728
  }
732
729
  return ruleSetLocationShort(ruleSet, pageURL);
733
730
  }
@@ -86,6 +86,7 @@ const UIStringsNotTranslate = {
86
86
 
87
87
  const lockedString = i18n.i18n.lockedString;
88
88
  const CODE_SNIPPET_WARNING_URL = 'https://support.google.com/legal/answer/13505487';
89
+ const PROMOTION_ID = 'ai-code-completion';
89
90
 
90
91
  export interface ViewInput {
91
92
  aidaAvailability?: Host.AidaClient.AidaAccessPreconditions;
@@ -106,10 +107,13 @@ export const DEFAULT_VIEW: View = (input, _output, target) => {
106
107
  lockedString(UIStringsNotTranslate.i) + ' ' + lockedString(UIStringsNotTranslate.toTurnOnCodeSuggestions) + ' ' +
107
108
  lockedString(UIStringsNotTranslate.press) + ' ' + cmdOrCtrl + ' ' + lockedString(UIStringsNotTranslate.x) + ' ' +
108
109
  lockedString(UIStringsNotTranslate.toDisableCodeSuggestions);
110
+ const newBadge = UI.UIUtils.maybeCreateNewBadge(PROMOTION_ID);
111
+ const newBadgeTemplate = newBadge ? html`&nbsp;${newBadge}` : nothing;
109
112
  // clang-format off
110
113
  render(
111
114
  html`
112
115
  <style>${styles}</style>
116
+ <style>@scope to (devtools-widget > *) { ${UI.inspectorCommonStyles} }</style>
113
117
  <div class="ai-code-completion-teaser-screen-reader-only">${teaserAriaLabel}</div>
114
118
  <div class="ai-code-completion-teaser" aria-hidden="true">
115
119
  <span class="ai-code-completion-teaser-action">
@@ -121,6 +125,7 @@ export const DEFAULT_VIEW: View = (input, _output, target) => {
121
125
  jslog=${VisualLogging.action('ai-code-completion-teaser.dismiss').track({click: true})}>
122
126
  ${lockedString(UIStringsNotTranslate.dontShowAgain)}
123
127
  </span>
128
+ ${newBadgeTemplate}
124
129
  </div>
125
130
  `, target
126
131
  );
@@ -18,7 +18,7 @@
18
18
 
19
19
  .ai-code-completion-teaser {
20
20
  padding-left: var(--sys-size-3);
21
- line-height: normal;
21
+ line-height: var(--sys-size-7);
22
22
  pointer-events: all;
23
23
  align-items: center;
24
24
  font-style: italic;
@@ -38,5 +38,10 @@
38
38
  padding: 0 var(--sys-size-3);
39
39
  }
40
40
  }
41
+
42
+ .new-badge {
43
+ font-style: normal;
44
+ display: inline-block;
45
+ }
41
46
  }
42
47
  }
@@ -9,6 +9,7 @@ import * as i18n from '../../core/i18n/i18n.js';
9
9
  import * as Root from '../../core/root/root.js';
10
10
  import * as SDK from '../../core/sdk/sdk.js';
11
11
  import * as AiCodeCompletion from '../../models/ai_code_completion/ai_code_completion.js';
12
+ import * as Badges from '../../models/badges/badges.js';
12
13
  import * as Formatter from '../../models/formatter/formatter.js';
13
14
  import * as SourceMapScopes from '../../models/source_map_scopes/source_map_scopes.js';
14
15
  import * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';
@@ -317,6 +318,10 @@ export class ConsolePrompt extends Common.ObjectWrapper.eventMixin<EventTypes, t
317
318
  CodeMirror.closeCompletion(this.editor.editor);
318
319
  }
319
320
 
321
+ clearAiCodeCompletionCache(): void {
322
+ this.aiCodeCompletion?.clearCachedRequest();
323
+ }
324
+
320
325
  moveCaretToEndOfPrompt(): void {
321
326
  this.editor.dispatch({
322
327
  selection: CodeMirror.EditorSelection.cursor(this.editor.state.doc.length),
@@ -474,6 +479,7 @@ export class ConsolePrompt extends Common.ObjectWrapper.eventMixin<EventTypes, t
474
479
  void this.evaluateCommandInConsole(executionContext, message, expression, useCommandLineAPI);
475
480
  if (ConsolePanel.instance().isShowing()) {
476
481
  Host.userMetrics.actionTaken(Host.UserMetrics.Action.CommandEvaluatedInConsolePanel);
482
+ Badges.UserBadges.instance().recordAction(Badges.BadgeAction.CONSOLE_PROMPT_EXECUTED);
477
483
  }
478
484
  }
479
485
  }
@@ -657,8 +657,9 @@ export class ConsoleView extends UI.Widget.VBox implements
657
657
  this.aiCodeCompletionSummaryToolbar?.setLoading(false);
658
658
  }
659
659
 
660
- static clearConsole(): void {
660
+ clearConsole(): void {
661
661
  SDK.ConsoleModel.ConsoleModel.requestClearMessages();
662
+ this.prompt.clearAiCodeCompletionCache();
662
663
  }
663
664
 
664
665
  #onIssuesCountUpdate(): void {
@@ -704,6 +705,7 @@ export class ConsoleView extends UI.Widget.VBox implements
704
705
 
705
706
  clearHistory(): void {
706
707
  this.prompt.history().clear();
708
+ this.prompt.clearAiCodeCompletionCache();
707
709
  }
708
710
 
709
711
  private consoleHistoryAutocompleteChanged(): void {
@@ -1922,7 +1924,7 @@ export class ActionDelegate implements UI.ActionRegistration.ActionDelegate {
1922
1924
  ConsoleView.instance().focusPrompt();
1923
1925
  return true;
1924
1926
  case 'console.clear':
1925
- ConsoleView.clearConsole();
1927
+ ConsoleView.instance().clearConsole();
1926
1928
  return true;
1927
1929
  case 'console.clear.history':
1928
1930
  ConsoleView.instance().clearHistory();