chrome-devtools-frontend 1.0.1541169 → 1.0.1542501

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 (69) hide show
  1. package/docs/get_the_code.md +9 -0
  2. package/front_end/Tests.js +6 -1
  3. package/front_end/core/common/Settings.ts +140 -106
  4. package/front_end/core/host/UserMetrics.ts +5 -0
  5. package/front_end/core/sdk/IOModel.ts +1 -4
  6. package/front_end/core/sdk/ServerSentEventsProtocol.ts +4 -0
  7. package/front_end/entrypoints/main/MainImpl.ts +18 -7
  8. package/front_end/foundation/README.md +10 -0
  9. package/front_end/foundation/Universe.ts +21 -0
  10. package/front_end/foundation/foundation.ts +7 -0
  11. package/front_end/generated/SupportedCSSProperties.js +42 -42
  12. package/front_end/models/ai_assistance/BuiltInAi.ts +2 -1
  13. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +44 -34
  14. package/front_end/models/ai_code_completion/AiCodeCompletion.ts +72 -31
  15. package/front_end/models/har/Importer.ts +14 -0
  16. package/front_end/models/issues_manager/IssuesManager.ts +0 -5
  17. package/front_end/models/javascript_metadata/NativeFunctions.js +0 -4
  18. package/front_end/models/trace/handlers/ScriptsHandler.ts +26 -0
  19. package/front_end/models/trace/types/TraceEvents.ts +1 -1
  20. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +117 -103
  21. package/front_end/panels/ai_assistance/components/ChatView.ts +7 -31
  22. package/front_end/panels/ai_assistance/components/MarkdownRendererWithCodeBlock.ts +1 -1
  23. package/front_end/panels/ai_assistance/components/PerformanceAgentMarkdownRenderer.ts +1 -1
  24. package/front_end/panels/ai_assistance/components/chatView.css +1 -1
  25. package/front_end/panels/console/ConsoleInsightTeaser.ts +5 -0
  26. package/front_end/panels/console/ConsolePrompt.ts +8 -1
  27. package/front_end/panels/sources/AiCodeCompletionPlugin.ts +17 -1
  28. package/front_end/panels/timeline/overlays/components/EntryLabelOverlay.ts +4 -1
  29. package/front_end/third_party/chromium/README.chromium +1 -1
  30. package/front_end/third_party/puppeteer/README.chromium +2 -2
  31. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
  32. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.js +3 -1
  33. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.js.map +1 -1
  34. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +2 -2
  35. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +2 -2
  36. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.d.ts +1 -1
  37. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.js +1 -1
  38. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +4 -4
  39. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
  40. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.js +3 -1
  41. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.js.map +1 -1
  42. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +2 -2
  43. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +2 -2
  44. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.d.ts +1 -1
  45. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.js +1 -1
  46. package/front_end/third_party/puppeteer/package/package.json +1 -1
  47. package/front_end/third_party/puppeteer/package/src/cdp/NetworkManager.ts +3 -1
  48. package/front_end/third_party/puppeteer/package/src/revisions.ts +2 -2
  49. package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
  50. package/front_end/ui/components/markdown_view/MarkdownLinksMap.ts +0 -4
  51. package/front_end/ui/components/markdown_view/MarkdownView.docs.ts +95 -0
  52. package/front_end/ui/components/markdown_view/MarkdownView.ts +6 -7
  53. package/front_end/ui/components/text_editor/AiCodeCompletionProvider.ts +246 -13
  54. package/front_end/ui/components/text_editor/config.ts +1 -1
  55. package/front_end/ui/legacy/Widget.ts +13 -4
  56. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +43 -33
  57. package/front_end/ui/visual_logging/KnownContextValues.ts +12 -0
  58. package/mcp/mcp.ts +2 -0
  59. package/package.json +1 -1
  60. package/front_end/models/issues_manager/UserReidentificationIssue.ts +0 -72
  61. package/front_end/models/issues_manager/descriptions/userReidentificationBlocked.md +0 -5
  62. package/front_end/ui/components/docs/markdown_image/basic.html +0 -19
  63. package/front_end/ui/components/docs/markdown_image/basic.ts +0 -38
  64. package/front_end/ui/components/docs/markdown_link/basic.html +0 -17
  65. package/front_end/ui/components/docs/markdown_link/basic.ts +0 -19
  66. package/front_end/ui/components/docs/markdown_view/basic.html +0 -25
  67. package/front_end/ui/components/docs/markdown_view/basic.ts +0 -67
  68. package/front_end/ui/components/docs/markdown_view/code-block.html +0 -30
  69. package/front_end/ui/components/docs/markdown_view/code-block.ts +0 -71
@@ -44,6 +44,7 @@ type GeneratedFileSizes = {
44
44
  }|{files: Record<string, number>, unmappedBytes: number, totalBytes: number};
45
45
 
46
46
  let scriptById = new Map<string, Script>();
47
+ let frameIdByIsolate = new Map<string, string>();
47
48
 
48
49
  export function deps(): HandlerName[] {
49
50
  return ['Meta', 'NetworkRequests'];
@@ -51,6 +52,7 @@ export function deps(): HandlerName[] {
51
52
 
52
53
  export function reset(): void {
53
54
  scriptById = new Map();
55
+ frameIdByIsolate = new Map();
54
56
  }
55
57
 
56
58
  export function handleEvent(event: Types.Events.Event): void {
@@ -73,6 +75,9 @@ export function handleEvent(event: Types.Events.Event): void {
73
75
  if (Types.Events.isRundownScript(event)) {
74
76
  const {isolate, scriptId, url, sourceUrl, sourceMapUrl, sourceMapUrlElided} = event.args.data;
75
77
  const script = getOrMakeScript(isolate, scriptId);
78
+ if (!script.frame) {
79
+ script.frame = frameIdByIsolate.get(String(isolate)) ?? '';
80
+ }
76
81
  script.url = url;
77
82
  script.ts = event.ts;
78
83
  if (sourceUrl) {
@@ -105,6 +110,27 @@ export function handleEvent(event: Types.Events.Event): void {
105
110
  script.content = (script.content ?? '') + sourceText;
106
111
  return;
107
112
  }
113
+
114
+ // Setup frameIdByIsolate, which is used only in the case that we are missing
115
+ // rundown events for a script. We won't get a frame association from the rundown
116
+ // events if the recording started only after the script was first compiled. In
117
+ // that scenario, derive the frame via the isolate / FunctionCall events.
118
+ // TODO: ideally, we put the frame on ScriptCatchup event. So much easier. This approach has some
119
+ // issues.
120
+ if (Types.Events.isFunctionCall(event) && event.args.data?.isolate && event.args.data.frame) {
121
+ const {isolate, frame} = event.args.data;
122
+ const existingValue = frameIdByIsolate.get(isolate);
123
+ if (existingValue !== frame) {
124
+ frameIdByIsolate.set(isolate, frame);
125
+
126
+ // Update the scripts we discovered but without knowing their frame.
127
+ for (const script of scriptById.values()) {
128
+ if (!script.frame && script.isolate === isolate) {
129
+ script.frame = frame;
130
+ }
131
+ }
132
+ }
133
+ }
108
134
  }
109
135
 
110
136
  function findFrame(meta: MetaHandlerData, frameId: string): Types.Events.TraceFrame|null {
@@ -2804,7 +2804,7 @@ export interface FunctionCall extends Complete {
2804
2804
  args: Args&{
2805
2805
  data?: Partial<CallFrame>& {
2806
2806
  frame?: string,
2807
- isolate?: number,
2807
+ isolate?: string,
2808
2808
  },
2809
2809
  };
2810
2810
  }
@@ -302,11 +302,17 @@ export const enum ViewState {
302
302
  EXPLORE_VIEW = 'explore-view'
303
303
  }
304
304
 
305
- interface PanelViewProps {
306
- state: ViewState;
307
- }
308
-
309
- export type ViewInput = ChatViewProps&ToolbarViewInput&PanelViewProps;
305
+ type PanelViewInput = {
306
+ state: ViewState.CHAT_VIEW,
307
+ props: ChatViewProps,
308
+ }|{
309
+ state: ViewState.DISABLED_VIEW,
310
+ props: {aidaAvailability: Host.AidaClient.AidaAccessPreconditions},
311
+ }|{
312
+ state: ViewState.EXPLORE_VIEW,
313
+ };
314
+
315
+ export type ViewInput = ToolbarViewInput&PanelViewInput;
310
316
  export interface PanelViewOutput {
311
317
  chatView?: ChatView;
312
318
  }
@@ -389,7 +395,7 @@ function defaultView(input: ViewInput, output: PanelViewOutput, target: HTMLElem
389
395
  switch (input.state) {
390
396
  case ViewState.CHAT_VIEW:
391
397
  return html`<devtools-ai-chat-view
392
- .props=${input}
398
+ .props=${input.props}
393
399
  ${Lit.Directives.ref((el: Element | undefined) => {
394
400
  if (!el || !(el instanceof ChatView)) {
395
401
  return;
@@ -407,9 +413,7 @@ function defaultView(input: ViewInput, output: PanelViewOutput, target: HTMLElem
407
413
  case ViewState.DISABLED_VIEW:
408
414
  return html`<devtools-widget
409
415
  class="fill-panel"
410
- .widgetConfig=${UI.Widget.widgetConfig(DisabledWidget, {
411
- aidaAvailability: input.aidaAvailability,
412
- })}
416
+ .widgetConfig=${UI.Widget.widgetConfig(DisabledWidget, input.props)}
413
417
  ></devtools-widget>`;
414
418
  }
415
419
  }
@@ -551,19 +555,73 @@ export class AiAssistancePanel extends UI.Panel.Panel {
551
555
  AiAssistanceModel.AiHistoryStorage.Events.HISTORY_DELETED, this.#onHistoryDeleted, this);
552
556
  }
553
557
 
554
- #getChatUiState(): ViewState {
558
+ async #getPanelViewInput(): Promise<PanelViewInput> {
555
559
  const blockedByAge = Root.Runtime.hostConfig.aidaAvailability?.blockedByAge === true;
556
560
 
557
561
  if (this.#aidaAvailability !== Host.AidaClient.AidaAccessPreconditions.AVAILABLE ||
558
562
  !this.#aiAssistanceEnabledSetting?.getIfNotDisabled() || blockedByAge) {
559
- return ViewState.DISABLED_VIEW;
563
+ return {
564
+ state: ViewState.DISABLED_VIEW,
565
+ props: {
566
+ aidaAvailability: this.#aidaAvailability,
567
+ },
568
+ };
560
569
  }
561
570
 
562
571
  if (this.#conversation?.type) {
563
- return ViewState.CHAT_VIEW;
572
+ const emptyStateSuggestions = await getEmptyStateSuggestions(this.#selectedContext, this.#conversation);
573
+ const markdownRenderer = getMarkdownRenderer(this.#selectedContext, this.#conversation);
574
+ return {
575
+ state: ViewState.CHAT_VIEW,
576
+ props: {
577
+ blockedByCrossOrigin: this.#blockedByCrossOrigin,
578
+ isLoading: this.#isLoading,
579
+ messages: this.#messages,
580
+ selectedContext: this.#selectedContext,
581
+ conversationType: this.#conversation.type,
582
+ isReadOnly: this.#conversation.isReadOnly ?? false,
583
+ changeSummary: this.#getChangeSummary(),
584
+ inspectElementToggled: this.#toggleSearchElementAction?.toggled() ?? false,
585
+ userInfo: this.#userInfo,
586
+ canShowFeedbackForm: this.#serverSideLoggingEnabled,
587
+ multimodalInputEnabled: isAiAssistanceMultimodalInputEnabled() &&
588
+ this.#conversation.type === AiAssistanceModel.AiHistoryStorage.ConversationType.STYLING,
589
+ imageInput: this.#imageInput,
590
+ isTextInputDisabled: this.#isTextInputDisabled(),
591
+ emptyStateSuggestions,
592
+ inputPlaceholder: this.#getChatInputPlaceholder(),
593
+ disclaimerText: this.#getDisclaimerText(),
594
+ isTextInputEmpty: this.#isTextInputEmpty,
595
+ changeManager: this.#changeManager,
596
+ uploadImageInputEnabled: isAiAssistanceMultimodalUploadInputEnabled() &&
597
+ this.#conversation.type === AiAssistanceModel.AiHistoryStorage.ConversationType.STYLING,
598
+ markdownRenderer,
599
+ onTextSubmit: async (
600
+ text: string, imageInput?: Host.AidaClient.Part,
601
+ multimodalInputType?: AiAssistanceModel.AiAgent.MultimodalInputType) => {
602
+ this.#imageInput = undefined;
603
+ this.#isTextInputEmpty = true;
604
+ Host.userMetrics.actionTaken(Host.UserMetrics.Action.AiAssistanceQuerySubmitted);
605
+ await this.#startConversation(text, imageInput, multimodalInputType);
606
+ },
607
+ onInspectElementClick: this.#handleSelectElementClick.bind(this),
608
+ onFeedbackSubmit: this.#handleFeedbackSubmit.bind(this),
609
+ onCancelClick: this.#cancel.bind(this),
610
+ onContextClick: this.#handleContextClick.bind(this),
611
+ onNewConversation: this.#handleNewChatRequest.bind(this),
612
+ onTakeScreenshot: isAiAssistanceMultimodalInputEnabled() ? this.#handleTakeScreenshot.bind(this) : undefined,
613
+ onRemoveImageInput: isAiAssistanceMultimodalInputEnabled() ? this.#handleRemoveImageInput.bind(this) :
614
+ undefined,
615
+ onCopyResponseClick: this.#onCopyResponseClick.bind(this),
616
+ onTextInputChange: this.#handleTextInputChange.bind(this),
617
+ onLoadImage: isAiAssistanceMultimodalUploadInputEnabled() ? this.#handleLoadImage.bind(this) : undefined,
618
+ }
619
+ };
564
620
  }
565
621
 
566
- return ViewState.EXPLORE_VIEW;
622
+ return {
623
+ state: ViewState.EXPLORE_VIEW,
624
+ };
567
625
  }
568
626
 
569
627
  #getAiAssistanceEnabledSetting(): Common.Settings.Setting<boolean>|undefined {
@@ -616,15 +674,7 @@ export class AiAssistancePanel extends UI.Panel.Panel {
616
674
  }
617
675
  }
618
676
 
619
- // We select the default agent based on the open panels if
620
- // there isn't any active conversation.
621
- #selectDefaultAgentIfNeeded(): void {
622
- // If there already is an agent and if it is not empty,
623
- // we don't automatically change the agent. In addition to this,
624
- // we don't change the current agent when there is a message in flight.
625
- if ((this.#conversationAgent && this.#conversation && !this.#conversation.isEmpty) || this.#isLoading) {
626
- return;
627
- }
677
+ #getDefaultConversationType(): AiAssistanceModel.AiHistoryStorage.ConversationType|undefined {
628
678
  const {hostConfig} = Root.Runtime;
629
679
  const viewManager = UI.ViewManager.ViewManager.instance();
630
680
  const isElementsPanelVisible = viewManager.isViewVisible('elements');
@@ -643,12 +693,24 @@ export class AiAssistancePanel extends UI.Panel.Panel {
643
693
  targetConversationType = AiAssistanceModel.AiHistoryStorage.ConversationType.PERFORMANCE;
644
694
  }
645
695
 
696
+ return targetConversationType;
697
+ }
698
+
699
+ // We select the default agent based on the open panels if
700
+ // there isn't any active conversation.
701
+ #selectDefaultAgentIfNeeded(): void {
702
+ // If there already is an agent and if it is not empty,
703
+ // we don't automatically change the agent. In addition to this,
704
+ // we don't change the current agent when there is a message in flight.
705
+ if ((this.#conversationAgent && this.#conversation && !this.#conversation.isEmpty) || this.#isLoading) {
706
+ return;
707
+ }
708
+ const targetConversationType = this.#getDefaultConversationType();
646
709
  if (this.#conversation?.type === targetConversationType) {
647
710
  // The above if makes sure even if we have an active agent it's empty
648
711
  // So we can just reuse it
649
712
  return;
650
713
  }
651
-
652
714
  const agent = targetConversationType ?
653
715
  this.#conversationHandler.createAgent(targetConversationType, this.#changeManager) :
654
716
  undefined;
@@ -671,9 +733,9 @@ export class AiAssistancePanel extends UI.Panel.Panel {
671
733
  // create a new conversation along side it
672
734
  if (opts?.agent) {
673
735
  this.#conversation = new AiAssistanceModel.AiHistoryStorage.Conversation(
674
- agentToConversationType(opts?.agent),
736
+ agentToConversationType(opts.agent),
675
737
  [],
676
- opts?.agent.id,
738
+ opts.agent.id,
677
739
  false,
678
740
  );
679
741
  }
@@ -687,15 +749,21 @@ export class AiAssistancePanel extends UI.Panel.Panel {
687
749
  // but conversation is
688
750
  // update with history conversation
689
751
  if (opts?.conversation) {
690
- this.#conversation = opts?.conversation;
752
+ this.#conversation = opts.conversation;
691
753
  }
692
754
  }
693
755
 
694
756
  if (!this.#conversationAgent && !this.#conversation) {
695
- this.#selectDefaultAgentIfNeeded();
757
+ const conversationType = this.#getDefaultConversationType();
758
+ if (conversationType) {
759
+ const agent = this.#conversationHandler.createAgent(conversationType, this.#changeManager);
760
+ this.#updateConversationState({agent});
761
+ return;
762
+ }
696
763
  }
697
764
 
698
765
  this.#onContextSelectionChanged();
766
+
699
767
  this.requestUpdate();
700
768
  }
701
769
 
@@ -879,67 +947,29 @@ export class AiAssistancePanel extends UI.Panel.Panel {
879
947
  return this.#changeManager.formatChangesForPatching(this.#conversationAgent.id, /* includeSourceLocation= */ true);
880
948
  }
881
949
 
882
- override async performUpdate(): Promise<void> {
883
- const emptyStateSuggestions = await getEmptyStateSuggestions(this.#selectedContext, this.#conversation);
884
- const markdownRenderer = getMarkdownRenderer(this.#selectedContext, this.#conversation);
950
+ #getToolbarInput(): ToolbarViewInput {
951
+ return {
952
+ isLoading: this.#isLoading,
953
+ showChatActions: this.#shouldShowChatActions(),
954
+ showActiveConversationActions: Boolean(this.#conversation && !this.#conversation.isEmpty),
955
+ onNewChatClick: this.#handleNewChatRequest.bind(this),
956
+ populateHistoryMenu: this.#populateHistoryMenu.bind(this),
957
+ onDeleteClick: this.#onDeleteClicked.bind(this),
958
+ onExportConversationClick: this.#onExportConversationClick.bind(this),
959
+ onHelpClick: () => {
960
+ UI.UIUtils.openInNewTab(AI_ASSISTANCE_HELP);
961
+ },
962
+ onSettingsClick: () => {
963
+ void UI.ViewManager.ViewManager.instance().showView('chrome-ai');
964
+ },
965
+ };
966
+ }
885
967
 
968
+ override async performUpdate(): Promise<void> {
886
969
  this.view(
887
970
  {
888
- state: this.#getChatUiState(),
889
- blockedByCrossOrigin: this.#blockedByCrossOrigin,
890
- aidaAvailability: this.#aidaAvailability,
891
- isLoading: this.#isLoading,
892
- messages: this.#messages,
893
- selectedContext: this.#selectedContext,
894
- conversationType: this.#conversation?.type,
895
- isReadOnly: this.#conversation?.isReadOnly ?? false,
896
- changeSummary: this.#getChangeSummary(),
897
- inspectElementToggled: this.#toggleSearchElementAction?.toggled() ?? false,
898
- userInfo: this.#userInfo,
899
- canShowFeedbackForm: this.#serverSideLoggingEnabled,
900
- multimodalInputEnabled: isAiAssistanceMultimodalInputEnabled() &&
901
- this.#conversation?.type === AiAssistanceModel.AiHistoryStorage.ConversationType.STYLING,
902
- imageInput: this.#imageInput,
903
- showChatActions: this.#shouldShowChatActions(),
904
- showActiveConversationActions: Boolean(this.#conversation && !this.#conversation.isEmpty),
905
- isTextInputDisabled: this.#isTextInputDisabled(),
906
- emptyStateSuggestions,
907
- inputPlaceholder: this.#getChatInputPlaceholder(),
908
- disclaimerText: this.#getDisclaimerText(),
909
- isTextInputEmpty: this.#isTextInputEmpty,
910
- changeManager: this.#changeManager,
911
- uploadImageInputEnabled: isAiAssistanceMultimodalUploadInputEnabled() &&
912
- this.#conversation?.type === AiAssistanceModel.AiHistoryStorage.ConversationType.STYLING,
913
- markdownRenderer,
914
- onNewChatClick: this.#handleNewChatRequest.bind(this),
915
- populateHistoryMenu: this.#populateHistoryMenu.bind(this),
916
- onDeleteClick: this.#onDeleteClicked.bind(this),
917
- onExportConversationClick: this.#onExportConversationClick.bind(this),
918
- onHelpClick: () => {
919
- UI.UIUtils.openInNewTab(AI_ASSISTANCE_HELP);
920
- },
921
- onSettingsClick: () => {
922
- void UI.ViewManager.ViewManager.instance().showView('chrome-ai');
923
- },
924
- onTextSubmit: async (
925
- text: string, imageInput?: Host.AidaClient.Part,
926
- multimodalInputType?: AiAssistanceModel.AiAgent.MultimodalInputType) => {
927
- this.#imageInput = undefined;
928
- this.#isTextInputEmpty = true;
929
- Host.userMetrics.actionTaken(Host.UserMetrics.Action.AiAssistanceQuerySubmitted);
930
- await this.#startConversation(text, imageInput, multimodalInputType);
931
- },
932
- onInspectElementClick: this.#handleSelectElementClick.bind(this),
933
- onFeedbackSubmit: this.#handleFeedbackSubmit.bind(this),
934
- onCancelClick: this.#cancel.bind(this),
935
- onContextClick: this.#handleContextClick.bind(this),
936
- onNewConversation: this.#handleNewChatRequest.bind(this),
937
- onTakeScreenshot: isAiAssistanceMultimodalInputEnabled() ? this.#handleTakeScreenshot.bind(this) : undefined,
938
- onRemoveImageInput: isAiAssistanceMultimodalInputEnabled() ? this.#handleRemoveImageInput.bind(this) :
939
- undefined,
940
- onCopyResponseClick: this.#onCopyResponseClick.bind(this),
941
- onTextInputChange: this.#handleTextInputChange.bind(this),
942
- onLoadImage: isAiAssistanceMultimodalUploadInputEnabled() ? this.#handleLoadImage.bind(this) : undefined,
971
+ ...this.#getToolbarInput(),
972
+ ...await this.#getPanelViewInput(),
943
973
  },
944
974
  this.#viewOutput, this.contentElement);
945
975
  }
@@ -961,20 +991,6 @@ export class AiAssistancePanel extends UI.Panel.Panel {
961
991
  }
962
992
 
963
993
  #isTextInputDisabled(): boolean {
964
- // If the `aiAssistanceSetting` is not enabled
965
- // or if the user is blocked by age, the text input is disabled.
966
- const aiAssistanceSetting = this.#aiAssistanceEnabledSetting?.getIfNotDisabled();
967
- const isBlockedByAge = Root.Runtime.hostConfig.aidaAvailability?.blockedByAge === true;
968
- if (!aiAssistanceSetting || isBlockedByAge) {
969
- return true;
970
- }
971
-
972
- // If the Aida is not available, the text input is disabled.
973
- const isAidaAvailable = this.#aidaAvailability === Host.AidaClient.AidaAccessPreconditions.AVAILABLE;
974
- if (!isAidaAvailable) {
975
- return true;
976
- }
977
-
978
994
  // If sending a new message is blocked by cross origin context
979
995
  // the text input is disabled.
980
996
  if (this.#blockedByCrossOrigin) {
@@ -1004,8 +1020,7 @@ export class AiAssistancePanel extends UI.Panel.Panel {
1004
1020
  }
1005
1021
 
1006
1022
  #getChatInputPlaceholder(): Platform.UIString.LocalizedString {
1007
- const state = this.#getChatUiState();
1008
- if (state === ViewState.DISABLED_VIEW || !this.#conversation) {
1023
+ if (!this.#conversation) {
1009
1024
  return i18nString(UIStrings.followTheSteps);
1010
1025
  }
1011
1026
 
@@ -1037,8 +1052,7 @@ export class AiAssistancePanel extends UI.Panel.Panel {
1037
1052
  }
1038
1053
 
1039
1054
  #getDisclaimerText(): Platform.UIString.LocalizedString {
1040
- const state = this.#getChatUiState();
1041
- if (state === ViewState.DISABLED_VIEW || !this.#conversation || this.#conversation.isReadOnly) {
1055
+ if (!this.#conversation || this.#conversation.isReadOnly) {
1042
1056
  return i18nString(UIStrings.inputDisclaimerForEmptyState);
1043
1057
  }
1044
1058
 
@@ -236,13 +236,12 @@ export interface Props {
236
236
  onLoadImage?: (file: File) => Promise<void>;
237
237
  changeManager: AiAssistanceModel.ChangeManager.ChangeManager;
238
238
  inspectElementToggled: boolean;
239
- aidaAvailability: Host.AidaClient.AidaAccessPreconditions;
240
239
  messages: ChatMessage[];
241
240
  selectedContext: AiAssistanceModel.AiAgent.ConversationContext<unknown>|null;
242
241
  isLoading: boolean;
243
242
  canShowFeedbackForm: boolean;
244
243
  userInfo: Pick<Host.InspectorFrontendHostAPI.SyncInformation, 'accountImage'|'accountFullName'>;
245
- conversationType?: AiAssistanceModel.AiHistoryStorage.ConversationType;
244
+ conversationType: AiAssistanceModel.AiHistoryStorage.ConversationType;
246
245
  isReadOnly: boolean;
247
246
  blockedByCrossOrigin: boolean;
248
247
  changeSummary?: string;
@@ -469,7 +468,6 @@ export class ChatView extends HTMLElement {
469
468
  const renderFooter = (): Lit.LitTemplate => {
470
469
  const classes = Lit.Directives.classMap({
471
470
  'chat-view-footer': true,
472
- 'has-conversation': !!this.#props.conversationType,
473
471
  'is-read-only': this.#props.isReadOnly,
474
472
  });
475
473
 
@@ -488,9 +486,8 @@ export class ChatView extends HTMLElement {
488
486
  };
489
487
 
490
488
  const renderInputOrReadOnlySection = (): Lit.LitTemplate => {
491
- if (this.#props.conversationType && this.#props.isReadOnly) {
489
+ if (this.#props.isReadOnly) {
492
490
  return renderReadOnlySection({
493
- conversationType: this.#props.conversationType,
494
491
  onNewConversation: this.#props.onNewConversation,
495
492
  });
496
493
  }
@@ -506,7 +503,6 @@ export class ChatView extends HTMLElement {
506
503
  multimodalInputEnabled: this.#props.multimodalInputEnabled,
507
504
  conversationType: this.#props.conversationType,
508
505
  imageInput: this.#props.imageInput,
509
- aidaAvailability: this.#props.aidaAvailability,
510
506
  isTextInputEmpty: this.#props.isTextInputEmpty,
511
507
  uploadImageInputEnabled: this.#props.uploadImageInputEnabled,
512
508
  onContextClick: this.#props.onContextClick,
@@ -957,12 +953,8 @@ function renderSelection({
957
953
  isTextInputDisabled: boolean,
958
954
  onContextClick: () => void | Promise<void>,
959
955
  onInspectElementClick: () => void,
960
- conversationType?: AiAssistanceModel.AiHistoryStorage.ConversationType,
956
+ conversationType: AiAssistanceModel.AiHistoryStorage.ConversationType,
961
957
  }): Lit.LitTemplate {
962
- if (!conversationType) {
963
- return Lit.nothing;
964
- }
965
-
966
958
  // TODO: currently the picker behavior is SDKNode specific.
967
959
  const hasPickerBehavior = conversationType === AiAssistanceModel.AiHistoryStorage.ConversationType.STYLING;
968
960
 
@@ -1119,14 +1111,9 @@ function renderEmptyState({isTextInputDisabled, suggestions, onSuggestionClick}:
1119
1111
  // clang-format on
1120
1112
  }
1121
1113
 
1122
- function renderReadOnlySection({onNewConversation, conversationType}: {
1114
+ function renderReadOnlySection({onNewConversation}: {
1123
1115
  onNewConversation: () => void,
1124
- conversationType?: AiAssistanceModel.AiHistoryStorage.ConversationType,
1125
1116
  }): Lit.LitTemplate {
1126
- if (!conversationType) {
1127
- return Lit.nothing;
1128
- }
1129
-
1130
1117
  // clang-format off
1131
1118
  return html`<div
1132
1119
  class="chat-readonly-container"
@@ -1355,7 +1342,6 @@ function renderChatInput({
1355
1342
  imageInput,
1356
1343
  isTextInputEmpty,
1357
1344
  uploadImageInputEnabled,
1358
- aidaAvailability,
1359
1345
  disclaimerText,
1360
1346
  onContextClick,
1361
1347
  onInspectElementClick,
@@ -1375,7 +1361,6 @@ function renderChatInput({
1375
1361
  selectedContext: AiAssistanceModel.AiAgent.ConversationContext<unknown>|null,
1376
1362
  inspectElementToggled: boolean,
1377
1363
  isTextInputEmpty: boolean,
1378
- aidaAvailability: Host.AidaClient.AidaAccessPreconditions,
1379
1364
  disclaimerText: string,
1380
1365
  onContextClick: () => void,
1381
1366
  onInspectElementClick: () => void,
@@ -1384,19 +1369,15 @@ function renderChatInput({
1384
1369
  onCancel: (ev: SubmitEvent) => void,
1385
1370
  onNewConversation: () => void,
1386
1371
  onTextInputChange: (input: string) => void,
1372
+ conversationType: AiAssistanceModel.AiHistoryStorage.ConversationType,
1387
1373
  multimodalInputEnabled?: boolean,
1388
- conversationType?: AiAssistanceModel.AiHistoryStorage.ConversationType,
1389
1374
  imageInput?: ImageInputData,
1390
1375
  uploadImageInputEnabled?: boolean,
1391
1376
  onTakeScreenshot?: () => void,
1392
1377
  onRemoveImageInput?: () => void,
1393
1378
  onImageUpload?: (ev: Event) => void,
1394
1379
  }): Lit.LitTemplate {
1395
- if (!conversationType) {
1396
- return Lit.nothing;
1397
- }
1398
-
1399
- const shouldShowMultiLine = aidaAvailability === Host.AidaClient.AidaAccessPreconditions.AVAILABLE && selectedContext;
1380
+ const shouldShowMultiLine = selectedContext;
1400
1381
  const chatInputContainerCls = Lit.Directives.classMap({
1401
1382
  'chat-input-container': true,
1402
1383
  'single-line-layout': !shouldShowMultiLine,
@@ -1457,7 +1438,6 @@ function renderMainContents({
1457
1438
  suggestions,
1458
1439
  userInfo,
1459
1440
  markdownRenderer,
1460
- conversationType,
1461
1441
  changeSummary,
1462
1442
  changeManager,
1463
1443
  onSuggestionClick,
@@ -1478,13 +1458,9 @@ function renderMainContents({
1478
1458
  onFeedbackSubmit: (rpcId: Host.AidaClient.RpcGlobalId, rate: Host.AidaClient.Rating, feedback?: string) => void,
1479
1459
  onCopyResponseClick: (message: ModelChatMessage) => void,
1480
1460
  onMessageContainerRef: (el: Element|undefined) => void,
1481
- conversationType?: AiAssistanceModel.AiHistoryStorage.ConversationType,
1461
+ conversationType: AiAssistanceModel.AiHistoryStorage.ConversationType,
1482
1462
  changeSummary?: string,
1483
1463
  }): Lit.LitTemplate {
1484
- if (!conversationType) {
1485
- return Lit.nothing;
1486
- }
1487
-
1488
1464
  if (messages.length > 0) {
1489
1465
  return renderMessages({
1490
1466
  messages,
@@ -19,7 +19,7 @@ import type * as Lit from '../../../ui/lit/lit.js';
19
19
  * ```
20
20
  **/
21
21
  export class MarkdownRendererWithCodeBlock extends MarkdownView.MarkdownView.MarkdownInsightRenderer {
22
- override templateForToken(token: Marked.Marked.MarkedToken): Lit.TemplateResult|null {
22
+ override templateForToken(token: Marked.Marked.MarkedToken): Lit.LitTemplate|null {
23
23
  if (token.type === 'code') {
24
24
  const lines = (token.text).split('\n');
25
25
  if (lines[0]?.trim() === 'css') {
@@ -21,7 +21,7 @@ export class PerformanceAgentMarkdownRenderer extends MarkdownRendererWithCodeBl
21
21
  super();
22
22
  }
23
23
 
24
- override templateForToken(token: Marked.Marked.MarkedToken): Lit.TemplateResult|null {
24
+ override templateForToken(token: Marked.Marked.MarkedToken): Lit.LitTemplate|null {
25
25
  if (token.type === 'link' && token.href.startsWith('#')) {
26
26
  if (token.href.startsWith('#node-')) {
27
27
  const nodeId = Number(token.href.replace('#node-', '')) as Protocol.DOM.BackendNodeId;
@@ -294,7 +294,7 @@ footer.chat-view-footer {
294
294
  The footer (for active conversations) is hidden by default on wider screens
295
295
  because the disclaimer is shown inline within the chat input actions. Show it only on narrow widths (< 400px).
296
296
  */
297
- &.has-conversation:not(.is-read-only) {
297
+ &:not(.is-read-only) {
298
298
  display: none;
299
299
  border: none;
300
300
 
@@ -357,11 +357,16 @@ export class ConsoleInsightTeaser extends UI.Widget.Widget {
357
357
  this.#timeoutId = setTimeout(this.#setSlow.bind(this), SLOW_GENERATION_CUTOFF_MILLISECONDS);
358
358
  const startTime = performance.now();
359
359
  let teaserText = '';
360
+ let firstChunkReceived = false;
360
361
  try {
361
362
  for await (const chunk of this.#getOnDeviceInsight()) {
362
363
  teaserText += chunk;
363
364
  this.#mainText = teaserText;
364
365
  this.requestUpdate();
366
+ if (!firstChunkReceived) {
367
+ firstChunkReceived = true;
368
+ Host.userMetrics.consoleInsightTeaserFirstChunkGenerated(performance.now() - startTime);
369
+ }
365
370
  }
366
371
  } catch (err) {
367
372
  // Ignore `AbortError` errors, which are thrown on mouse leave.
@@ -554,7 +554,14 @@ export class ConsolePrompt extends Common.ObjectWrapper.eventMixin<EventTypes, t
554
554
  this.teaser = undefined;
555
555
  }
556
556
  this.aiCodeCompletion = new AiCodeCompletion.AiCodeCompletion.AiCodeCompletion(
557
- {aidaClient: this.aidaClient}, this.editor, AiCodeCompletion.AiCodeCompletion.ContextFlavor.CONSOLE, ['\n\n']);
557
+ {aidaClient: this.aidaClient}, AiCodeCompletion.AiCodeCompletion.ContextFlavor.CONSOLE, {
558
+ getSelectionHead: () => this.editor.editor.state.selection.main.head,
559
+ getCompletionHint: () => this.editor.editor.plugin(TextEditor.Config.showCompletionHint)?.currentHint,
560
+ setAiAutoCompletion: (suggestion: TextEditor.Config.ActiveSuggestion|null) => {
561
+ this.editor.dispatch({effects: TextEditor.Config.setAiAutoCompleteSuggestion.of(suggestion)});
562
+ }
563
+ },
564
+ ['\n\n']);
558
565
  this.aiCodeCompletion.addEventListener(AiCodeCompletion.AiCodeCompletion.Events.RESPONSE_RECEIVED, event => {
559
566
  this.aiCodeCompletionCitations = event.data.citations;
560
567
  this.dispatchEventToListeners(Events.AI_CODE_COMPLETION_RESPONSE_RECEIVED, event.data);
@@ -22,6 +22,22 @@ const DISCLAIMER_TOOLTIP_ID = 'sources-ai-code-completion-disclaimer-tooltip';
22
22
  const SPINNER_TOOLTIP_ID = 'sources-ai-code-completion-spinner-tooltip';
23
23
  const CITATIONS_TOOLTIP_ID = 'sources-ai-code-completion-citations-tooltip';
24
24
 
25
+ function createCallbacks(editor: TextEditor.TextEditor.TextEditor): AiCodeCompletion.AiCodeCompletion.Callbacks {
26
+ return {
27
+ getSelectionHead: () => editor.editor.state.selection.main.head,
28
+ getCompletionHint: () => editor.editor.plugin(TextEditor.Config.showCompletionHint)?.currentHint,
29
+ setAiAutoCompletion: (args: {
30
+ text: string,
31
+ from: number,
32
+ startTime: number,
33
+ onImpression: (rpcGlobalId: Host.AidaClient.RpcGlobalId, latency: number, sampleId?: number) => void,
34
+ clearCachedRequest: () => void,
35
+ rpcGlobalId?: Host.AidaClient.RpcGlobalId,
36
+ sampleId?: number,
37
+ }|null) => editor.editor.dispatch({effects: TextEditor.Config.setAiAutoCompleteSuggestion.of(args)}),
38
+ };
39
+ }
40
+
25
41
  export class AiCodeCompletionPlugin extends Plugin {
26
42
  #aidaClient?: Host.AidaClient.AidaClient;
27
43
  #aidaAvailability?: Host.AidaClient.AidaAccessPreconditions;
@@ -215,7 +231,7 @@ export class AiCodeCompletionPlugin extends Plugin {
215
231
  AiCodeCompletion.AiCodeCompletion.ContextFlavor.CONSOLE :
216
232
  AiCodeCompletion.AiCodeCompletion.ContextFlavor.SOURCES;
217
233
  this.#aiCodeCompletion = new AiCodeCompletion.AiCodeCompletion.AiCodeCompletion(
218
- {aidaClient: this.#aidaClient}, this.#editor, contextFlavor);
234
+ {aidaClient: this.#aidaClient}, contextFlavor, createCallbacks(this.#editor));
219
235
  this.#aiCodeCompletion.addEventListener(
220
236
  AiCodeCompletion.AiCodeCompletion.Events.REQUEST_TRIGGERED, this.#onAiRequestTriggered, this);
221
237
  this.#aiCodeCompletion.addEventListener(
@@ -676,7 +676,10 @@ export class EntryLabelOverlay extends HTMLElement {
676
676
  @mousedown=${(e: Event) => e.preventDefault()}>
677
677
  <button
678
678
  class="ai-label-button enabled"
679
- @click=${this.#handleAiButtonClick}>
679
+ @click=${this.#handleAiButtonClick}
680
+ jslog=${VisualLogging.link('timeline.annotations.ai-generate-label').track({
681
+ click: true,
682
+ })}>
680
683
  <devtools-icon
681
684
  class="pen-icon extra-large"
682
685
  name="pen-spark"
@@ -1,7 +1,7 @@
1
1
  Name: Dependencies sourced from the upstream `chromium` repository
2
2
  URL: https://chromium.googlesource.com/chromium/src
3
3
  Version: N/A
4
- Revision: 33096dd334d53eb095e196b5663cc1921f646cae
4
+ Revision: 5270546e53b6cf52712ff2091c6a405e61dc0873
5
5
  Update Mechanism: Manual (https://crbug.com/428069060)
6
6
  License: BSD-3-Clause
7
7
  License File: LICENSE
@@ -1,10 +1,10 @@
1
1
  Name: Puppeteer Core
2
2
  Short Name: Puppeteer Core
3
3
  URL: https://github.com/puppeteer/puppeteer/tree/main/packages/puppeteer-core
4
- Version: 24.29.0
4
+ Version: 24.29.1
5
5
  License: Apache-2.0
6
6
  License File: LICENSE
7
- Revision: 05f61366ee61f480c7be6f237ec890c907fea67f
7
+ Revision: ebadd3c75ee1af68e3febe7f73fa850f6d27c2a6
8
8
  Security Critical: no
9
9
  Shipped: yes
10
10
  Update Mechanism: Autoroll
@@ -1 +1 @@
1
- {"version":3,"file":"NetworkManager.d.ts","sourceRoot":"","sources":["../../../../src/cdp/NetworkManager.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAkB,KAAK,UAAU,EAAC,MAAM,sBAAsB,CAAC;AACtE,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,iBAAiB,CAAC;AAC3C,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAC,YAAY,EAAC,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,mCAAmC,CAAC;AAc3C;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,yBAA0B,SAAQ,iBAAiB;IAClE,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAAC;CACjC;AAED;;GAEG;AACH,qBAAa,cAAe,SAAQ,YAAY,CAAC,oBAAoB,CAAC;;gBA6BxD,YAAY,EAAE,aAAa,EAAE,cAAc,CAAC,EAAE,OAAO;IAa3D,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAoC5C,YAAY,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAY5D,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BzE,gBAAgB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAI1C,qBAAqB,IAAI,MAAM;IAIzB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAa7C,wBAAwB,CAC5B,iBAAiB,EAAE,iBAAiB,GAAG,IAAI,GAC1C,OAAO,CAAC,IAAI,CAAC;IAkDV,YAAY,CAChB,SAAS,EAAE,MAAM,EACjB,iBAAiB,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,iBAAiB,EACxD,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC;IAyBV,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAKhD,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAwf5D"}
1
+ {"version":3,"file":"NetworkManager.d.ts","sourceRoot":"","sources":["../../../../src/cdp/NetworkManager.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAkB,KAAK,UAAU,EAAC,MAAM,sBAAsB,CAAC;AACtE,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,iBAAiB,CAAC;AAC3C,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAC,YAAY,EAAC,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,mCAAmC,CAAC;AAc3C;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,yBAA0B,SAAQ,iBAAiB;IAClE,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAAC;CACjC;AAED;;GAEG;AACH,qBAAa,cAAe,SAAQ,YAAY,CAAC,oBAAoB,CAAC;;gBA6BxD,YAAY,EAAE,aAAa,EAAE,cAAc,CAAC,EAAE,OAAO;IAe3D,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAoC5C,YAAY,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAY5D,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BzE,gBAAgB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAI1C,qBAAqB,IAAI,MAAM;IAIzB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAa7C,wBAAwB,CAC5B,iBAAiB,EAAE,iBAAiB,GAAG,IAAI,GAC1C,OAAO,CAAC,IAAI,CAAC;IAkDV,YAAY,CAChB,SAAS,EAAE,MAAM,EACjB,iBAAiB,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,iBAAiB,EACxD,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC;IAyBV,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAKhD,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAwf5D"}