chrome-devtools-frontend 1.0.1571007 → 1.0.1572937

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 (168) hide show
  1. package/agents/prompts/README.md +18 -0
  2. package/agents/prompts/devtools-imports.md +47 -0
  3. package/agents/prompts/verification.md +27 -0
  4. package/front_end/Images/geminiInDevTools.png +0 -0
  5. package/front_end/Images/geminiInDevTools_2x.png +0 -0
  6. package/front_end/Images/src/database-off.svg +1 -0
  7. package/front_end/Images/src/lock-person.svg +1 -1
  8. package/front_end/core/common/Debouncer.ts +10 -1
  9. package/front_end/core/common/SettingRegistration.ts +1 -1
  10. package/front_end/core/host/AidaClient.ts +8 -0
  11. package/front_end/core/host/InspectorFrontendHostAPI.ts +0 -6
  12. package/front_end/core/host/UserMetrics.ts +1 -31
  13. package/front_end/core/root/ExperimentNames.ts +30 -0
  14. package/front_end/core/root/Runtime.ts +47 -48
  15. package/front_end/core/root/root.ts +2 -0
  16. package/front_end/core/sdk/CSSModel.ts +36 -13
  17. package/front_end/core/sdk/CSSProperty.ts +1 -1
  18. package/front_end/core/sdk/CSSPropertyParserMatchers.ts +9 -0
  19. package/front_end/core/sdk/CookieModel.ts +2 -1
  20. package/front_end/core/sdk/DOMModel.ts +1 -1
  21. package/front_end/core/sdk/DebuggerModel.ts +1 -1
  22. package/front_end/core/sdk/OverlayModel.ts +3 -2
  23. package/front_end/core/sdk/SourceMap.ts +1 -1
  24. package/front_end/devtools_compatibility.js +0 -6
  25. package/front_end/entrypoints/main/MainImpl.ts +44 -24
  26. package/front_end/entrypoints/main/main-meta.ts +1 -1
  27. package/front_end/generated/SupportedCSSProperties.js +6 -14
  28. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +0 -180
  29. package/front_end/models/ai_assistance/ai_assistance.ts +0 -2
  30. package/front_end/models/breakpoints/BreakpointManager.ts +3 -3
  31. package/front_end/models/issues_manager/ContrastCheckTrigger.ts +2 -2
  32. package/front_end/models/javascript_metadata/NativeFunctions.js +8 -0
  33. package/front_end/models/source_map_scopes/NamesResolver.ts +1 -1
  34. package/front_end/models/trace/EventsSerializer.ts +5 -1
  35. package/front_end/models/trace/ModelImpl.ts +0 -4
  36. package/front_end/models/trace/types/TraceEvents.ts +4 -0
  37. package/front_end/panels/accessibility/AXBreadcrumbsPane.ts +1 -1
  38. package/front_end/panels/accessibility/AccessibilitySidebarView.ts +1 -1
  39. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +8 -63
  40. package/front_end/panels/ai_assistance/PatchWidget.ts +10 -15
  41. package/front_end/panels/ai_assistance/SelectWorkspaceDialog.ts +5 -4
  42. package/front_end/panels/ai_assistance/aiAssistancePanel.css +0 -16
  43. package/front_end/panels/ai_assistance/ai_assistance.ts +0 -1
  44. package/front_end/panels/ai_assistance/components/ChatMessage.ts +3 -2
  45. package/front_end/panels/ai_assistance/components/ChatView.ts +123 -108
  46. package/front_end/panels/ai_assistance/components/PerformanceAgentMarkdownRenderer.ts +1 -145
  47. package/front_end/panels/application/DeviceBoundSessionsModel.ts +23 -1
  48. package/front_end/panels/application/DeviceBoundSessionsTreeElement.ts +23 -0
  49. package/front_end/panels/application/FrameDetailsView.ts +12 -10
  50. package/front_end/panels/application/components/BackForwardCacheView.ts +6 -8
  51. package/front_end/panels/application/components/BounceTrackingMitigationsView.ts +4 -3
  52. package/front_end/panels/application/components/ProtocolHandlersView.ts +5 -6
  53. package/front_end/panels/application/components/ReportsGrid.ts +9 -9
  54. package/front_end/panels/application/components/SharedStorageAccessGrid.ts +5 -4
  55. package/front_end/panels/application/components/TrustTokensView.ts +4 -6
  56. package/front_end/panels/application/preloading/PreloadingView.ts +9 -8
  57. package/front_end/panels/application/preloading/components/PreloadingDetailsReportView.ts +237 -230
  58. package/front_end/panels/application/preloading/components/PreloadingGrid.ts +3 -2
  59. package/front_end/panels/application/preloading/components/UsedPreloadingView.ts +6 -10
  60. package/front_end/panels/application/resourcesSidebar.css +8 -0
  61. package/front_end/panels/autofill/AutofillView.ts +4 -3
  62. package/front_end/panels/common/AiCodeCompletionSummaryToolbar.ts +3 -5
  63. package/front_end/panels/common/AiCodeCompletionTeaser.ts +5 -5
  64. package/front_end/panels/common/AiCodeGenerationTeaser.ts +35 -4
  65. package/front_end/panels/common/BadgeNotification.ts +17 -14
  66. package/front_end/panels/common/GdpSignUpDialog.ts +5 -6
  67. package/front_end/panels/common/GeminiRebrandPromoDialog.ts +192 -0
  68. package/front_end/panels/common/aiCodeGenerationTeaser.css +16 -1
  69. package/front_end/panels/common/common.ts +1 -0
  70. package/front_end/panels/common/geminiRebrandPromoDialog.css +47 -0
  71. package/front_end/panels/console/ConsoleInsightTeaser.ts +10 -11
  72. package/front_end/panels/console/ErrorStackParser.ts +11 -16
  73. package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +2 -2
  74. package/front_end/panels/css_overview/CSSOverviewModel.ts +1 -1
  75. package/front_end/panels/elements/ComputedStyleModel.ts +16 -65
  76. package/front_end/panels/elements/ComputedStyleWidget.ts +3 -3
  77. package/front_end/panels/elements/ElementsPanel.ts +35 -5
  78. package/front_end/panels/elements/ElementsSidebarPane.ts +1 -1
  79. package/front_end/panels/elements/ElementsTreeOutline.ts +1 -1
  80. package/front_end/panels/elements/PlatformFontsWidget.ts +1 -1
  81. package/front_end/panels/elements/StylePropertiesSection.ts +16 -8
  82. package/front_end/panels/elements/StylePropertyTreeElement.ts +67 -32
  83. package/front_end/panels/elements/StylesSidebarPane.ts +28 -11
  84. package/front_end/panels/elements/components/CSSHintDetailsView.ts +3 -2
  85. package/front_end/panels/elements/components/CSSPropertyDocsView.ts +3 -2
  86. package/front_end/panels/elements/elements-meta.ts +1 -1
  87. package/front_end/panels/emulation/DeviceModeWrapper.ts +101 -62
  88. package/front_end/panels/explain/components/ConsoleInsight.ts +27 -23
  89. package/front_end/panels/explain/components/consoleInsight.css +1 -1
  90. package/front_end/panels/issues/IssueView.ts +6 -6
  91. package/front_end/panels/network/RequestConditionsDrawer.ts +4 -3
  92. package/front_end/panels/network/RequestCookiesView.ts +3 -4
  93. package/front_end/panels/network/RequestTimingView.ts +6 -10
  94. package/front_end/panels/network/components/HeaderSectionRow.ts +3 -2
  95. package/front_end/panels/network/components/RequestHeaderSection.ts +3 -1
  96. package/front_end/panels/network/components/RequestHeadersView.css +2 -2
  97. package/front_end/panels/network/components/RequestHeadersView.ts +7 -6
  98. package/front_end/panels/profiler/HeapProfileView.ts +3 -3
  99. package/front_end/panels/profiler/HeapSnapshotView.ts +2 -2
  100. package/front_end/panels/profiler/profiler-meta.ts +3 -3
  101. package/front_end/panels/protocol_monitor/protocol_monitor-meta.ts +1 -1
  102. package/front_end/panels/recorder/RecorderController.ts +7 -13
  103. package/front_end/panels/recorder/components/CreateRecordingView.ts +6 -6
  104. package/front_end/panels/recorder/components/RecordingView.ts +0 -38
  105. package/front_end/panels/recorder/components/ReplaySection.ts +0 -14
  106. package/front_end/panels/recorder/components/StepEditor.ts +2 -40
  107. package/front_end/panels/recorder/recorderController.css +4 -4
  108. package/front_end/panels/security/CookieControlsView.ts +2 -2
  109. package/front_end/panels/security/CookieReportView.ts +21 -21
  110. package/front_end/panels/security/cookieControlsView.css +1 -1
  111. package/front_end/panels/security/cookieReportView.css +1 -1
  112. package/front_end/panels/settings/AISettingsTab.ts +13 -15
  113. package/front_end/panels/settings/components/SyncSection.ts +4 -3
  114. package/front_end/panels/settings/emulation/components/UserAgentClientHintsForm.ts +4 -12
  115. package/front_end/panels/settings/settings-meta.ts +1 -1
  116. package/front_end/panels/sources/BreakpointEditDialog.ts +4 -3
  117. package/front_end/panels/sources/CallStackSidebarPane.ts +4 -1
  118. package/front_end/panels/sources/FilteredUISourceCodeListProvider.ts +1 -1
  119. package/front_end/panels/sources/NavigatorView.ts +4 -4
  120. package/front_end/panels/sources/SourcesPanel.ts +7 -4
  121. package/front_end/panels/sources/components/HeadersView.ts +2 -2
  122. package/front_end/panels/timeline/CompatibilityTracksAppender.ts +3 -2
  123. package/front_end/panels/timeline/ThreadAppender.ts +2 -1
  124. package/front_end/panels/timeline/TimelineController.ts +4 -3
  125. package/front_end/panels/timeline/TimelinePanel.ts +7 -4
  126. package/front_end/panels/timeline/TimelineUIUtils.ts +2 -2
  127. package/front_end/panels/timeline/components/ExportTraceOptions.ts +4 -4
  128. package/front_end/panels/timeline/components/FieldSettingsDialog.ts +13 -6
  129. package/front_end/panels/timeline/components/LiveMetricsView.ts +13 -9
  130. package/front_end/panels/timeline/components/exportTraceOptions.css +1 -1
  131. package/front_end/panels/timeline/components/fieldSettingsDialog.css +1 -1
  132. package/front_end/panels/timeline/components/insights/BaseInsightComponent.ts +2 -19
  133. package/front_end/panels/timeline/components/insights/InsightRenderer.ts +3 -4
  134. package/front_end/panels/timeline/components/insights/baseInsightComponent.css +0 -5
  135. package/front_end/panels/timeline/components/liveMetricsView.css +1 -1
  136. package/front_end/panels/whats_new/ReleaseNoteView.ts +4 -3
  137. package/front_end/third_party/chromium/README.chromium +1 -1
  138. package/front_end/ui/components/buttons/button.css +4 -0
  139. package/front_end/ui/components/markdown_view/CodeBlock.ts +3 -6
  140. package/front_end/ui/components/markdown_view/MarkdownLink.ts +3 -4
  141. package/front_end/ui/components/panel_feedback/PanelFeedback.ts +3 -4
  142. package/front_end/ui/components/panel_feedback/PreviewToggle.ts +10 -7
  143. package/front_end/ui/components/panel_feedback/panelFeedback.css +2 -2
  144. package/front_end/ui/components/panel_feedback/previewToggle.css +2 -2
  145. package/front_end/ui/components/text_editor/AiCodeGenerationParser.ts +27 -8
  146. package/front_end/ui/components/text_editor/AiCodeGenerationProvider.ts +36 -6
  147. package/front_end/ui/kit/link/Link.ts +1 -14
  148. package/front_end/ui/legacy/ActionRegistration.ts +1 -1
  149. package/front_end/ui/legacy/ContextMenu.ts +2 -2
  150. package/front_end/ui/legacy/EmptyWidget.ts +3 -3
  151. package/front_end/ui/legacy/LinkContextMenuProvider.ts +42 -0
  152. package/front_end/ui/legacy/ViewRegistration.ts +1 -1
  153. package/front_end/ui/legacy/XLink.ts +0 -27
  154. package/front_end/ui/legacy/components/color_picker/ContrastDetails.ts +1 -1
  155. package/front_end/ui/legacy/components/color_picker/ContrastOverlay.ts +5 -4
  156. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +2 -2
  157. package/front_end/ui/legacy/components/perf_ui/perf_ui-meta.ts +1 -1
  158. package/front_end/ui/legacy/inspectorCommon.css +2 -1
  159. package/front_end/ui/legacy/legacy.ts +3 -1
  160. package/front_end/ui/visual_logging/KnownContextValues.ts +4 -1
  161. package/front_end/ui/visual_logging/LoggingDriver.ts +3 -0
  162. package/package.json +1 -1
  163. package/front_end/models/ai_assistance/ArtifactsManager.ts +0 -67
  164. package/front_end/panels/ai_assistance/components/ArtifactsViewer.ts +0 -183
  165. package/front_end/panels/ai_assistance/components/CollapsibleAssistanceContentWidget.ts +0 -89
  166. package/front_end/panels/ai_assistance/components/PerformanceAgentFlameChart.ts +0 -133
  167. package/front_end/panels/ai_assistance/components/artifactsViewer.css +0 -15
  168. package/front_end/panels/ai_assistance/components/collapsibleAssistanceContentWidget.css +0 -32
@@ -27,7 +27,6 @@ import * as NetworkPanel from '../network/network.js';
27
27
  import * as TimelinePanel from '../timeline/timeline.js';
28
28
 
29
29
  import aiAssistancePanelStyles from './aiAssistancePanel.css.js';
30
- import {ArtifactsViewer} from './components/ArtifactsViewer.js';
31
30
  import {
32
31
  type AnswerPart,
33
32
  ChatMessageEntity,
@@ -273,7 +272,7 @@ function getMarkdownRenderer(conversation?: AiAssistanceModel.AiConversation.AiC
273
272
  if (!context.external) {
274
273
  const focus = context.getItem();
275
274
  return new PerformanceAgentMarkdownRenderer(
276
- focus.parsedTrace.data.Meta.mainFrameId, focus.lookupEvent.bind(focus), focus.parsedTrace);
275
+ focus.parsedTrace.data.Meta.mainFrameId, focus.lookupEvent.bind(focus));
277
276
  }
278
277
  } else if (conversation?.type === AiAssistanceModel.AiHistoryStorage.ConversationType.PERFORMANCE) {
279
278
  // Handle historical conversations (can't linkify anything).
@@ -290,8 +289,6 @@ interface ToolbarViewInput {
290
289
  onExportConversationClick: () => void;
291
290
  onHelpClick: () => void;
292
291
  onSettingsClick: () => void;
293
- onArtifactsSidebarToggle: () => void;
294
- artifactsSidebarVisible: boolean;
295
292
  isLoading: boolean;
296
293
  showChatActions: boolean;
297
294
  showActiveConversationActions: boolean;
@@ -384,13 +381,6 @@ function toolbarView(input: ToolbarViewInput): Lit.LitTemplate {
384
381
  .jslogContext=${'freestyler.settings'}
385
382
  .variant=${Buttons.Button.Variant.TOOLBAR}
386
383
  @click=${input.onSettingsClick}></devtools-button>
387
- <!-- If the green experiment is enabled, render the artifacts sidebar toggle button -->
388
- ${GreenDev.Prototypes.instance().isEnabled('artifactViewer') ? html`<devtools-button
389
- title=${i18nString(UIStrings.settings)}
390
- aria-label=${i18nString(UIStrings.settings)}
391
- .iconName=${input.artifactsSidebarVisible ? 'left-panel-open' : 'left-panel-close'}
392
- .variant=${Buttons.Button.Variant.TOOLBAR}
393
- @click=${input.onArtifactsSidebarToggle}></devtools-button>` : Lit.nothing}
394
384
  </devtools-toolbar>
395
385
  </div>
396
386
  `;
@@ -428,40 +418,13 @@ function defaultView(input: ViewInput, output: PanelViewOutput, target: HTMLElem
428
418
  }
429
419
  }
430
420
 
431
- const panelWithToolbar = html`
432
- ${toolbarView(input)}
433
- <div class="ai-assistance-view-container">${renderState()}</div>`;
434
-
435
- // If the green experiment is enabled, render the chat view inside
436
- // a split view to also have an artifacts viewer sidebar.
437
- if(GreenDev.Prototypes.instance().isEnabled('artifactViewer')) {
438
- Lit.render(
439
- html`
440
- <devtools-split-view
441
- direction="column"
442
- sidebar-visibility=${input.artifactsSidebarVisible ? 'visible' : 'hidden'}
443
- sidebar-position="second"
444
- sidebar-initial-size="520"
445
- style="width: 100%;">
446
- <div slot="main" class="assistance-view-wrapper-with-sidebar">
447
- ${panelWithToolbar}
448
- </div>
449
- <div slot="sidebar">
450
- <div class="artifacts-toolbar-container" role="toolbar">
451
- <div>Artifacts Viewer</div>
452
- </div>
453
- <devtools-widget
454
- class="fill-panel"
455
- .widgetConfig=${UI.Widget.widgetConfig(ArtifactsViewer)}
456
- ></devtools-widget>
457
- </div>
458
- </devtools-split-view>
459
- `,
460
- target
461
- );
462
- } else {
463
- Lit.render(panelWithToolbar, target);
464
- }
421
+ Lit.render(
422
+ html`
423
+ ${toolbarView(input)}
424
+ <div class="ai-assistance-view-container">${renderState()}</div>
425
+ `,
426
+ target
427
+ );
465
428
  // clang-format on
466
429
  }
467
430
 
@@ -516,7 +479,6 @@ export class AiAssistancePanel extends UI.Panel.Panel {
516
479
  #selectedElement: AiAssistanceModel.StylingAgent.NodeContext|null = null;
517
480
  #selectedPerformanceTrace: AiAssistanceModel.PerformanceAgent.PerformanceTraceContext|null = null;
518
481
  #selectedRequest: AiAssistanceModel.NetworkAgent.RequestContext|null = null;
519
- #isArtifactsSidebarOpen = false;
520
482
  // Messages displayed in the `ChatView` component.
521
483
  #messages: Message[] = [];
522
484
 
@@ -555,10 +517,6 @@ export class AiAssistancePanel extends UI.Panel.Panel {
555
517
  }
556
518
  AiAssistanceModel.AiHistoryStorage.AiHistoryStorage.instance().addEventListener(
557
519
  AiAssistanceModel.AiHistoryStorage.Events.HISTORY_DELETED, this.#onHistoryDeleted, this);
558
- if (GreenDev.Prototypes.instance().isEnabled('artifactViewer')) {
559
- AiAssistanceModel.ArtifactsManager.ArtifactsManager.instance().addEventListener(
560
- AiAssistanceModel.ArtifactsManager.ArtifactAddedEvent.eventName, this.#onArtifactAdded.bind(this));
561
- }
562
520
  }
563
521
 
564
522
  async #getPanelViewInput(): Promise<PanelViewInput> {
@@ -601,7 +559,6 @@ export class AiAssistancePanel extends UI.Panel.Panel {
601
559
  uploadImageInputEnabled: isAiAssistanceMultimodalUploadInputEnabled() &&
602
560
  this.#conversation.type === AiAssistanceModel.AiHistoryStorage.ConversationType.STYLING,
603
561
  markdownRenderer,
604
- isArtifactsSidebarOpen: this.#isArtifactsSidebarOpen,
605
562
  onTextSubmit: async (
606
563
  text: string, imageInput?: Host.AidaClient.Part,
607
564
  multimodalInputType?: AiAssistanceModel.AiAgent.MultimodalInputType) => {
@@ -803,13 +760,6 @@ export class AiAssistancePanel extends UI.Panel.Panel {
803
760
  }
804
761
  }
805
762
 
806
- #onArtifactAdded(): void {
807
- if (AiAssistanceModel.ArtifactsManager.ArtifactsManager.instance().artifacts.length > 0) {
808
- this.#isArtifactsSidebarOpen = true;
809
- this.requestUpdate();
810
- }
811
- }
812
-
813
763
  override willHide(): void {
814
764
  super.willHide();
815
765
  this.#aiAssistanceEnabledSetting?.removeChangeListener(this.requestUpdate, this);
@@ -941,11 +891,6 @@ export class AiAssistancePanel extends UI.Panel.Panel {
941
891
  onSettingsClick: () => {
942
892
  void UI.ViewManager.ViewManager.instance().showView('chrome-ai');
943
893
  },
944
- onArtifactsSidebarToggle: () => {
945
- this.#isArtifactsSidebarOpen = !this.#isArtifactsSidebarOpen;
946
- this.requestUpdate();
947
- },
948
- artifactsSidebarVisible: this.#isArtifactsSidebarOpen,
949
894
  };
950
895
  }
951
896
 
@@ -5,6 +5,7 @@
5
5
  import '../../ui/legacy/legacy.js';
6
6
  import '../../ui/components/markdown_view/markdown_view.js';
7
7
  import '../../ui/components/spinners/spinners.js';
8
+ import '../../ui/kit/kit.js';
8
9
 
9
10
  import * as Common from '../../core/common/common.js';
10
11
  import * as Host from '../../core/host/host.js';
@@ -200,15 +201,13 @@ const DEFAULT_VIEW: View = (input, output, target) => {
200
201
  return nothing;
201
202
  }
202
203
 
203
- return html`<x-link
204
+ return html`<devtools-link
204
205
  class="link"
205
206
  title="${UIStringsNotTranslate.viewUploadedFiles} ${UIStringsNotTranslate.opensInNewTab}"
206
207
  href="data:text/plain;charset=utf-8,${encodeURIComponent(input.sources)}"
207
- jslog=${VisualLogging.link('files-used-in-patching').track({
208
- click: true
209
- })}>
208
+ .jslogContext=${'files-used-in-patching'}>
210
209
  ${UIStringsNotTranslate.viewUploadedFiles}
211
- </x-link>`;
210
+ </devtools-link>`;
212
211
  }
213
212
 
214
213
  function renderHeader(): LitTemplate {
@@ -297,12 +296,10 @@ const DEFAULT_VIEW: View = (input, output, target) => {
297
296
  return html`
298
297
  <div class="footer">
299
298
  <div class="left-side">
300
- <x-link class="link disclaimer-link" href="https://support.google.com/legal/answer/13505487" jslog=${
301
- VisualLogging.link('code-disclaimer').track({
302
- click: true,
303
- })}>
299
+ <devtools-link class="link disclaimer-link" href="https://support.google.com/legal/answer/13505487" .jslogContext=${
300
+ 'code-disclaimer'}>
304
301
  ${lockedString(UIStringsNotTranslate.codeDisclaimer)}
305
- </x-link>
302
+ </devtools-link>
306
303
  ${renderSourcesLink()}
307
304
  </div>
308
305
  <div class="save-or-discard-buttons">
@@ -575,13 +572,11 @@ export class PatchWidget extends UI.Widget.Widget {
575
572
  {
576
573
  iconName: 'warning',
577
574
  // clang-format off
578
- content: html`<x-link
575
+ content: html`<devtools-link
579
576
  href=${CODE_SNIPPET_WARNING_URL}
580
577
  class="link devtools-link"
581
- jslog=${VisualLogging.link('code-snippets-explainer.patch-widget').track({
582
- click: true
583
- })}
584
- >${lockedString(UIStringsNotTranslate.freDisclaimerTextUseWithCaution)}</x-link>`,
578
+ .jslogContext=${'code-snippets-explainer.patch-widget'}
579
+ >${lockedString(UIStringsNotTranslate.freDisclaimerTextUseWithCaution)}</devtools-link>`,
585
580
  // clang-format on
586
581
  }
587
582
  ],
@@ -2,6 +2,8 @@
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
4
 
5
+ import '../../ui/kit/kit.js';
6
+
5
7
  import * as Common from '../../core/common/common.js';
6
8
  import * as Host from '../../core/host/host.js';
7
9
  import * as i18n from '../../core/i18n/i18n.js';
@@ -13,7 +15,6 @@ import * as Workspace from '../../models/workspace/workspace.js';
13
15
  import * as Buttons from '../../ui/components/buttons/buttons.js';
14
16
  import * as UI from '../../ui/legacy/legacy.js';
15
17
  import {html, nothing, render} from '../../ui/lit/lit.js';
16
- import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
17
18
 
18
19
  import selectWorkspaceDialogStyles from './selectWorkspaceDialog.css.js';
19
20
 
@@ -89,11 +90,11 @@ export const SELECT_WORKSPACE_DIALOG_DEFAULT_VIEW: View = (input, _output, targe
89
90
  <!-- Hardcoding, because there is no 'getFormatLocalizedString' equivalent for 'lockedString' -->
90
91
  <div>
91
92
  Tip: provide a
92
- <x-link
93
+ <devtools-link
93
94
  class="devtools-link"
94
95
  href="https://goo.gle/devtools-automatic-workspace-folders"
95
- jslog=${VisualLogging.link().track({click: true, keydown:'Enter|Space'}).context('automatic-workspaces-documentation')}
96
- >com.chrome.devtools.json</x-link>
96
+ .jslogContext=${'automatic-workspaces-documentation'}
97
+ >com.chrome.devtools.json</devtools-link>
97
98
  file to automatically connect your project to DevTools.
98
99
  </div>
99
100
  ` : nothing}
@@ -13,22 +13,6 @@
13
13
  justify-content: space-between;
14
14
  }
15
15
 
16
- .artifacts-toolbar-container {
17
- display: flex;
18
- align-items: center;
19
- justify-content: flex-start;
20
- height: 27px;
21
- padding: 5px;
22
- border-bottom: 1px solid var(--sys-color-divider);
23
- }
24
-
25
- .assistance-view-wrapper-with-sidebar {
26
- display: flex;
27
- flex-direction: column;
28
- height: 100%;
29
- overflow: hidden;
30
- }
31
-
32
16
  .ai-assistance-view-container {
33
17
  display: flex;
34
18
  flex-direction: column;
@@ -6,7 +6,6 @@ export * from './AiAssistancePanel.js';
6
6
  export * from './components/ChatView.js';
7
7
  export * as ChatInput from './components/ChatInput.js';
8
8
  export * from './components/MarkdownRendererWithCodeBlock.js';
9
- export * from './components/PerformanceAgentFlameChart.js';
10
9
  export * from './SelectWorkspaceDialog.js';
11
10
  export * as ChatMessage from './components/ChatMessage.js';
12
11
  export * as ExploreWidget from './components/ExploreWidget.js';
@@ -3,6 +3,7 @@
3
3
  // found in the LICENSE file.
4
4
 
5
5
  import '../../../ui/components/markdown_view/markdown_view.js';
6
+ import '../../../ui/kit/kit.js';
6
7
 
7
8
  import * as Common from '../../../core/common/common.js';
8
9
  import * as Host from '../../../core/host/host.js';
@@ -576,12 +577,12 @@ function renderImageChatMessage(inlineData: Host.AidaClient.MediaBlob): Lit.LitT
576
577
  }
577
578
  const imageUrl = `data:${inlineData.mimeType};base64,${inlineData.data}`;
578
579
  // clang-format off
579
- return html`<x-link
580
+ return html`<devtools-link
580
581
  class="image-link" title=${UIStringsNotTranslate.openImageInNewTab}
581
582
  href=${imageUrl}
582
583
  >
583
584
  <img src=${imageUrl} alt=${UIStringsNotTranslate.imageInputSentToTheModel} />
584
- </x-link>`;
585
+ </devtools-link>`;
585
586
  // clang-format on
586
587
  }
587
588
 
@@ -2,8 +2,6 @@
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
4
 
5
- /* eslint-disable @devtools/no-lit-render-outside-of-view */
6
-
7
5
  import '../../../ui/components/spinners/spinners.js';
8
6
 
9
7
  import * as Host from '../../../core/host/host.js';
@@ -13,7 +11,7 @@ import type * as AiAssistanceModel from '../../../models/ai_assistance/ai_assist
13
11
  import * as Buttons from '../../../ui/components/buttons/buttons.js';
14
12
  import type {MarkdownLitRenderer} from '../../../ui/components/markdown_view/MarkdownView.js';
15
13
  import * as UI from '../../../ui/legacy/legacy.js';
16
- import * as Lit from '../../../ui/lit/lit.js';
14
+ import {Directives, html, nothing, render} from '../../../ui/lit/lit.js';
17
15
  import {PatchWidget} from '../PatchWidget.js';
18
16
 
19
17
  import {ChatInput} from './ChatInput.js';
@@ -22,7 +20,7 @@ import chatViewStyles from './chatView.css.js';
22
20
 
23
21
  export {ChatInput, type ImageInputData} from './ChatInput.js';
24
22
 
25
- const {html, Directives: {ref, repeat, createRef}} = Lit;
23
+ const {ref, repeat, classMap} = Directives;
26
24
 
27
25
  /*
28
26
  * Strings that don't need to be translated at this time.
@@ -38,6 +36,12 @@ const lockedString = i18n.i18n.lockedString;
38
36
 
39
37
  const SCROLL_ROUNDING_OFFSET = 1;
40
38
 
39
+ interface ViewOutput {
40
+ mainElement?: HTMLElement;
41
+ input?: UI.Widget.WidgetElement<ChatInput>;
42
+ }
43
+ type View = (input: ChatWidgetInput, output: ViewOutput, target: HTMLElement|ShadowRoot) => void;
44
+
41
45
  export interface Props {
42
46
  onTextSubmit:
43
47
  (text: string, imageInput?: Host.AidaClient.Part,
@@ -64,18 +68,110 @@ export interface Props {
64
68
  emptyStateSuggestions: AiAssistanceModel.AiAgent.ConversationSuggestion[];
65
69
  inputPlaceholder: Platform.UIString.LocalizedString;
66
70
  disclaimerText: Platform.UIString.LocalizedString;
67
- isArtifactsSidebarOpen: boolean;
68
71
  uploadImageInputEnabled?: boolean;
69
72
  markdownRenderer: MarkdownLitRenderer;
70
73
  additionalFloatyContext: UI.Floaty.FloatyContextSelection[];
71
74
  }
72
75
 
76
+ interface ChatWidgetInput extends Props {
77
+ handleScroll: (ev: Event) => void;
78
+ handleSuggestionClick: (title: string) => void;
79
+ handleMessageContainerRef: (el: Element|undefined) => void;
80
+ }
81
+
82
+ const DEFAULT_VIEW: View = (input, output, target) => {
83
+ const inputWidgetClasses = classMap({
84
+ 'chat-input-widget': true,
85
+ sticky: !input.isReadOnly,
86
+ });
87
+
88
+ // clang-format off
89
+ render(html`
90
+ <style>${chatViewStyles}</style>
91
+ <div class="chat-ui">
92
+ <main @scroll=${input.handleScroll} ${ref(element => { output.mainElement = element as HTMLElement; } )}>
93
+ ${input.messages.length > 0 ? html`
94
+ <div class="messages-container" ${ref(input.handleMessageContainerRef)}>
95
+ ${repeat(input.messages, message =>
96
+ html`<devtools-widget .widgetConfig=${UI.Widget.widgetConfig(ChatMessage, {
97
+ message,
98
+ isLoading: input.isLoading,
99
+ isReadOnly: input.isReadOnly,
100
+ canShowFeedbackForm: input.canShowFeedbackForm,
101
+ userInfo: input.userInfo,
102
+ markdownRenderer: input.markdownRenderer,
103
+ isLastMessage: input.messages.at(-1) === message,
104
+ onSuggestionClick: input.handleSuggestionClick,
105
+ onFeedbackSubmit: input.onFeedbackSubmit,
106
+ onCopyResponseClick: input.onCopyResponseClick,
107
+ })}></devtools-widget>`
108
+ )}
109
+ ${input.isLoading ? nothing : html`<devtools-widget
110
+ .widgetConfig=${UI.Widget.widgetConfig(PatchWidget, {
111
+ changeSummary: input.changeSummary ?? '',
112
+ changeManager: input.changeManager,
113
+ })}
114
+ ></devtools-widget>`}
115
+ </div>
116
+ ` : html`
117
+ <div class="empty-state-container">
118
+ <div class="header">
119
+ <div class="icon">
120
+ <devtools-icon
121
+ name="smart-assistant"
122
+ ></devtools-icon>
123
+ </div>
124
+ <h1>${lockedString(UIStringsNotTranslate.emptyStateText)}</h1>
125
+ </div>
126
+ <div class="empty-state-content">
127
+ ${input.emptyStateSuggestions.map(({title, jslogContext}) => {
128
+ return html`<devtools-button
129
+ class="suggestion"
130
+ @click=${() => input.handleSuggestionClick(title)}
131
+ .data=${
132
+ {
133
+ variant: Buttons.Button.Variant.OUTLINED,
134
+ size: Buttons.Button.Size.REGULAR,
135
+ title,
136
+ jslogContext: jslogContext ?? 'suggestion',
137
+ disabled: input.isTextInputDisabled,
138
+ } as Buttons.Button.ButtonData
139
+ }
140
+ >${title}</devtools-button>`;
141
+ })}
142
+ </div>
143
+ </div>
144
+ `}
145
+ <devtools-widget class=${inputWidgetClasses} .widgetConfig=${UI.Widget.widgetConfig(ChatInput, {
146
+ isLoading: input.isLoading,
147
+ blockedByCrossOrigin: input.blockedByCrossOrigin,
148
+ isTextInputDisabled: input.isTextInputDisabled,
149
+ inputPlaceholder: input.inputPlaceholder,
150
+ disclaimerText: input.disclaimerText,
151
+ selectedContext: input.selectedContext,
152
+ inspectElementToggled: input.inspectElementToggled,
153
+ multimodalInputEnabled: input.multimodalInputEnabled ?? false,
154
+ conversationType: input.conversationType,
155
+ uploadImageInputEnabled: input.uploadImageInputEnabled ?? false,
156
+ isReadOnly: input.isReadOnly,
157
+ additionalFloatyContext: input.additionalFloatyContext,
158
+ onContextClick: input.onContextClick,
159
+ onInspectElementClick: input.onInspectElementClick,
160
+ onTextSubmit: input.onTextSubmit,
161
+ onCancelClick: input.onCancelClick,
162
+ onNewConversation: input.onNewConversation,
163
+ })} ${ref(element => { output.input = element as UI.Widget.WidgetElement<ChatInput>; } )}></devtools-widget>
164
+ </main>
165
+ </div>
166
+ `, target);
167
+ // clang-format on
168
+ };
73
169
  export class ChatView extends HTMLElement {
74
170
  readonly #shadow = this.attachShadow({mode: 'open'});
75
171
  #scrollTop?: number;
76
172
  #props: Props;
77
173
  #messagesContainerElement?: Element;
78
- #mainElementRef = createRef<HTMLElement>();
174
+ #output: ViewOutput = {};
79
175
  #messagesContainerResizeObserver = new ResizeObserver(() => this.#handleMessagesContainerResize());
80
176
  /**
81
177
  * Indicates whether the chat scroll position should be pinned to the bottom.
@@ -94,11 +190,12 @@ export class ChatView extends HTMLElement {
94
190
  * whether to pin the content to the bottom.
95
191
  */
96
192
  #isProgrammaticScroll = false;
97
- #inputRef = createRef<UI.Widget.WidgetElement<ChatInput>>();
193
+ #view: View;
98
194
 
99
- constructor(props: Props) {
195
+ constructor(props: Props, view = DEFAULT_VIEW) {
100
196
  super();
101
197
  this.#props = props;
198
+ this.#view = view;
102
199
  }
103
200
 
104
201
  set props(props: Props) {
@@ -132,7 +229,7 @@ export class ChatView extends HTMLElement {
132
229
  return;
133
230
  }
134
231
 
135
- if (!this.#mainElementRef?.value) {
232
+ if (!this.#output.mainElement) {
136
233
  return;
137
234
  }
138
235
 
@@ -140,11 +237,11 @@ export class ChatView extends HTMLElement {
140
237
  }
141
238
 
142
239
  scrollToBottom(): void {
143
- if (!this.#mainElementRef?.value) {
240
+ if (!this.#output.mainElement) {
144
241
  return;
145
242
  }
146
243
 
147
- this.#setMainElementScrollTop(this.#mainElementRef.value.scrollHeight);
244
+ this.#setMainElementScrollTop(this.#output.mainElement.scrollHeight);
148
245
  }
149
246
 
150
247
  #handleMessagesContainerResize(): void {
@@ -152,26 +249,26 @@ export class ChatView extends HTMLElement {
152
249
  return;
153
250
  }
154
251
 
155
- if (!this.#mainElementRef?.value) {
252
+ if (!this.#output.mainElement) {
156
253
  return;
157
254
  }
158
255
 
159
256
  if (this.#pinScrollToBottom) {
160
- this.#setMainElementScrollTop(this.#mainElementRef.value.scrollHeight);
257
+ this.#setMainElementScrollTop(this.#output.mainElement.scrollHeight);
161
258
  }
162
259
  }
163
260
 
164
261
  #setMainElementScrollTop(scrollTop: number): void {
165
- if (!this.#mainElementRef?.value) {
262
+ if (!this.#output.mainElement) {
166
263
  return;
167
264
  }
168
265
 
169
266
  this.#scrollTop = scrollTop;
170
267
  this.#isProgrammaticScroll = true;
171
- this.#mainElementRef.value.scrollTop = scrollTop;
268
+ this.#output.mainElement.scrollTop = scrollTop;
172
269
  }
173
270
 
174
- #handleMessageContainerRef(el: Element|undefined): void {
271
+ #handleMessageContainerRef = (el: Element|undefined): void => {
175
272
  this.#messagesContainerElement = el;
176
273
 
177
274
  if (el) {
@@ -180,7 +277,7 @@ export class ChatView extends HTMLElement {
180
277
  this.#pinScrollToBottom = true;
181
278
  this.#messagesContainerResizeObserver.disconnect();
182
279
  }
183
- }
280
+ };
184
281
 
185
282
  #handleScroll = (ev: Event): void => {
186
283
  if (!ev.target || !(ev.target instanceof HTMLElement)) {
@@ -201,103 +298,21 @@ export class ChatView extends HTMLElement {
201
298
  };
202
299
 
203
300
  #handleSuggestionClick = (suggestion: string): void => {
204
- this.#inputRef.value?.getWidget()?.setInputValue(suggestion);
301
+ this.#output.input?.getWidget()?.setInputValue(suggestion);
205
302
  this.#render();
206
303
  this.focusTextInput();
207
304
  Host.userMetrics.actionTaken(Host.UserMetrics.Action.AiAssistanceDynamicSuggestionClicked);
208
305
  };
209
306
 
210
307
  #render(): void {
211
- const inputWidgetClasses = Lit.Directives.classMap({
212
- 'chat-input-widget': true,
213
- sticky: !this.#props.isReadOnly,
214
- });
215
-
216
- // clang-format off
217
- Lit.render(html`
218
- <style>${chatViewStyles}</style>
219
- <div class="chat-ui">
220
- <main @scroll=${this.#handleScroll} ${ref(this.#mainElementRef)}>
221
- ${this.#props.messages.length > 0 ? html`
222
- <div class="messages-container" ${ref(this.#handleMessageContainerRef)}>
223
- ${repeat(this.#props.messages, message =>
224
- html`<devtools-widget .widgetConfig=${UI.Widget.widgetConfig(ChatMessage, {
225
- message,
226
- isLoading: this.#props.isLoading,
227
- isReadOnly: this.#props.isReadOnly,
228
- canShowFeedbackForm: this.#props.canShowFeedbackForm,
229
- userInfo: this.#props.userInfo,
230
- markdownRenderer: this.#props.markdownRenderer,
231
- isLastMessage: this.#props.messages.at(-1) === message,
232
- onSuggestionClick: this.#handleSuggestionClick,
233
- onFeedbackSubmit: this.#props.onFeedbackSubmit,
234
- onCopyResponseClick: this.#props.onCopyResponseClick,
235
- })}></devtools-widget>`
236
- )}
237
- ${this.#props.isLoading ? Lit.nothing : html`<devtools-widget
238
- .widgetConfig=${UI.Widget.widgetConfig(PatchWidget, {
239
- changeSummary: this.#props.changeSummary ?? '',
240
- changeManager: this.#props.changeManager,
241
- })}
242
- ></devtools-widget>`}
243
- </div>
244
- ` : html`
245
- <div class="empty-state-container">
246
- <div class="header">
247
- <div class="icon">
248
- <devtools-icon
249
- name="smart-assistant"
250
- ></devtools-icon>
251
- </div>
252
- <h1>${lockedString(UIStringsNotTranslate.emptyStateText)}</h1>
253
- </div>
254
- <div class="empty-state-content">
255
- ${this.#props.emptyStateSuggestions.map(({title, jslogContext}) => {
256
- return html`<devtools-button
257
- class="suggestion"
258
- @click=${() => this.#handleSuggestionClick(title)}
259
- .data=${
260
- {
261
- variant: Buttons.Button.Variant.OUTLINED,
262
- size: Buttons.Button.Size.REGULAR,
263
- title,
264
- jslogContext: jslogContext ?? 'suggestion',
265
- disabled: this.#props.isTextInputDisabled,
266
- } as Buttons.Button.ButtonData
267
- }
268
- >${title}</devtools-button>`;
269
- })}
270
- </div>
271
- </div>
272
- `}
273
- <devtools-widget class=${inputWidgetClasses} .widgetConfig=${UI.Widget.widgetConfig(ChatInput, {
274
- isLoading: this.#props.isLoading,
275
- blockedByCrossOrigin: this.#props.blockedByCrossOrigin,
276
- isTextInputDisabled: this.#props.isTextInputDisabled,
277
- inputPlaceholder: this.#props.inputPlaceholder,
278
- disclaimerText: this.#props.disclaimerText,
279
- selectedContext: this.#props.selectedContext,
280
- inspectElementToggled: this.#props.inspectElementToggled,
281
- multimodalInputEnabled: this.#props.multimodalInputEnabled ?? false,
282
- conversationType: this.#props.conversationType,
283
- uploadImageInputEnabled: this.#props.uploadImageInputEnabled ?? false,
284
- isReadOnly: this.#props.isReadOnly,
285
- additionalFloatyContext: this.#props.additionalFloatyContext,
286
- onContextClick: this.#props.onContextClick,
287
- onInspectElementClick: this.#props.onInspectElementClick,
288
- onTextSubmit: (
289
- text: string, imageInput?: Host.AidaClient.Part,
290
- multimodalInputType?: AiAssistanceModel.AiAgent.MultimodalInputType) => {
291
- this.#props.onTextSubmit(text, imageInput, multimodalInputType);
292
- this.#render();
293
- },
294
- onCancelClick: this.#props.onCancelClick,
295
- onNewConversation: this.#props.onNewConversation,
296
- })} ${ref(this.#inputRef)}></devtools-widget>
297
- </main>
298
- </div>
299
- `, this.#shadow, {host: this});
300
- // clang-format on
308
+ this.#view(
309
+ {
310
+ ...this.#props,
311
+ handleScroll: this.#handleScroll,
312
+ handleSuggestionClick: this.#handleSuggestionClick,
313
+ handleMessageContainerRef: this.#handleMessageContainerRef,
314
+ },
315
+ this.#output, this.#shadow);
301
316
  }
302
317
  }
303
318