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
@@ -317,6 +317,11 @@ export class UserMetrics {
317
317
  InspectorFrontendHostInstance.recordPerformanceHistogram(
318
318
  'DevTools.Insights.TeaserGenerationTime', timeInMilliseconds);
319
319
  }
320
+
321
+ consoleInsightTeaserFirstChunkGenerated(timeInMilliseconds: number): void {
322
+ InspectorFrontendHostInstance.recordPerformanceHistogram(
323
+ 'DevTools.Insights.TeaserFirstChunkGenerationTime', timeInMilliseconds);
324
+ }
320
325
  }
321
326
 
322
327
  /**
@@ -25,10 +25,7 @@ export class IOModel extends SDKModel<void> {
25
25
  }
26
26
 
27
27
  async close(handle: Protocol.IO.StreamHandle): Promise<void> {
28
- const result = await this.target().ioAgent().invoke_close({handle});
29
- if (result.getError()) {
30
- console.error('Could not close stream.');
31
- }
28
+ await this.target().ioAgent().invoke_close({handle});
32
29
  }
33
30
 
34
31
  async resolveBlob(objectOrObjectId: Protocol.Runtime.RemoteObjectId|RemoteObject): Promise<string> {
@@ -35,6 +35,10 @@ export class ServerSentEventsParser {
35
35
  await this.#decoder.addBase64Chunk(raw);
36
36
  }
37
37
 
38
+ addTextChunk(chunk: string): void {
39
+ this.#onTextChunk(chunk);
40
+ }
41
+
38
42
  #onTextChunk(chunk: string): void {
39
43
  // A line consists of "this.#line" plus a slice of "chunk[start:<next new cr/lf>]".
40
44
  let start = 0;
@@ -41,6 +41,7 @@ import * as Platform from '../../core/platform/platform.js';
41
41
  import * as ProtocolClient from '../../core/protocol_client/protocol_client.js';
42
42
  import * as Root from '../../core/root/root.js';
43
43
  import * as SDK from '../../core/sdk/sdk.js';
44
+ import * as Foundation from '../../foundation/foundation.js';
44
45
  import * as AiAssistanceModel from '../../models/ai_assistance/ai_assistance.js';
45
46
  import * as AutofillManager from '../../models/autofill_manager/autofill_manager.js';
46
47
  import * as Badges from '../../models/badges/badges.js';
@@ -165,7 +166,17 @@ export class MainImpl {
165
166
  console.timeStamp('Main._gotPreferences');
166
167
  this.#initializeGlobalsForLayoutTests();
167
168
  Object.assign(Root.Runtime.hostConfig, config);
168
- this.createSettings(prefs);
169
+
170
+ const creationOptions: Foundation.Universe.CreationOptions = {
171
+ settingsCreationOptions: {
172
+ ...this.createSettingsStorage(prefs),
173
+ settingRegistrations: Common.SettingRegistration.getRegisteredSettings(),
174
+ logSettingAccess: VisualLogging.logSettingAccess,
175
+ runSettingsMigration: !Host.InspectorFrontendHost.isUnderTest(),
176
+ },
177
+ };
178
+ new Foundation.Universe.Universe(creationOptions);
179
+
169
180
  await this.requestAndRegisterLocaleData();
170
181
 
171
182
  Host.userMetrics.syncSetting(Common.Settings.Settings.instance().moduleSetting<boolean>('sync-preferences').get());
@@ -243,7 +254,11 @@ export class MainImpl {
243
254
  }
244
255
  }
245
256
 
246
- createSettings(prefs: Record<string, string>): void {
257
+ createSettingsStorage(prefs: Record<string, string>): {
258
+ syncedStorage: Common.Settings.SettingsStorage,
259
+ globalStorage: Common.Settings.SettingsStorage,
260
+ localStorage: Common.Settings.SettingsStorage,
261
+ } {
247
262
  this.#initializeExperiments();
248
263
  let storagePrefix = '';
249
264
  if (Host.Platform.isCustomDevtoolsFrontend()) {
@@ -287,12 +302,8 @@ export class MainImpl {
287
302
  // setting can't change storage buckets during a single DevTools session.
288
303
  const syncedStorage = new Common.Settings.SettingsStorage(prefs, hostSyncedStorage, storagePrefix);
289
304
  const globalStorage = new Common.Settings.SettingsStorage(prefs, hostUnsyncedStorage, storagePrefix);
290
- Common.Settings.Settings.instance(
291
- {forceNew: true, syncedStorage, globalStorage, localStorage, logSettingAccess: VisualLogging.logSettingAccess});
292
305
 
293
- if (!Host.InspectorFrontendHost.isUnderTest()) {
294
- new Common.Settings.VersionController().updateVersion();
295
- }
306
+ return {syncedStorage, globalStorage, localStorage};
296
307
  }
297
308
 
298
309
  #initializeExperiments(): void {
@@ -0,0 +1,10 @@
1
+ # DevTools foundation
2
+
3
+ DevTools foundation is the core business logic of DevTools: mainly core/ and models/.
4
+ The difference between "foundation" and the rest of DevTools is
5
+ that the code is targeted not just for the browser, but also the Node.js runtime.
6
+ As such, allowed use of APIs is restricted to what is available in both runtimes.
7
+
8
+ A `DevToolsUniverse` is a concrete, encapsulated instance of "foundation" scoped
9
+ to a single root CDP target. It is valid to create multiple `DevToolsUniverse`
10
+ instances simultaneously.
@@ -0,0 +1,21 @@
1
+ // Copyright 2025 The Chromium Authors
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ import * as Common from '../core/common/common.js';
6
+
7
+ export interface CreationOptions {
8
+ // Settings things
9
+ settingsCreationOptions: Common.Settings.SettingsCreationOptions;
10
+ }
11
+
12
+ export class Universe {
13
+ constructor(options: CreationOptions) {
14
+ // TODO(crbug.com/458180550): Store instance on a "DevToolsContext" instead.
15
+ // For now the global is fine as we don't anticipate the MCP server to change settings.
16
+ Common.Settings.Settings.instance({
17
+ forceNew: true,
18
+ ...options.settingsCreationOptions,
19
+ });
20
+ }
21
+ }
@@ -0,0 +1,7 @@
1
+ // Copyright 2025 The Chromium Authors
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ import * as Universe from './Universe.js';
6
+
7
+ export {Universe};
@@ -419,10 +419,10 @@ export const generatedProperties = [
419
419
  "column-height",
420
420
  "column-rule-break",
421
421
  "column-rule-color",
422
- "column-rule-edge-end-outset",
423
- "column-rule-edge-start-outset",
424
- "column-rule-interior-end-outset",
425
- "column-rule-interior-start-outset",
422
+ "column-rule-edge-end-inset",
423
+ "column-rule-edge-start-inset",
424
+ "column-rule-interior-end-inset",
425
+ "column-rule-interior-start-inset",
426
426
  "column-rule-style",
427
427
  "column-rule-visibility-items",
428
428
  "column-rule-width",
@@ -642,10 +642,10 @@ export const generatedProperties = [
642
642
  "row-gap",
643
643
  "row-rule-break",
644
644
  "row-rule-color",
645
- "row-rule-edge-end-outset",
646
- "row-rule-edge-start-outset",
647
- "row-rule-interior-end-outset",
648
- "row-rule-interior-start-outset",
645
+ "row-rule-edge-end-inset",
646
+ "row-rule-edge-start-inset",
647
+ "row-rule-interior-end-inset",
648
+ "row-rule-interior-start-inset",
649
649
  "row-rule-style",
650
650
  "row-rule-visibility-items",
651
651
  "row-rule-width",
@@ -1729,28 +1729,28 @@ export const generatedProperties = [
1729
1729
  },
1730
1730
  {
1731
1731
  "inherited": false,
1732
- "name": "column-rule-edge-end-outset"
1732
+ "name": "column-rule-edge-end-inset"
1733
1733
  },
1734
1734
  {
1735
1735
  "inherited": false,
1736
- "name": "column-rule-edge-start-outset"
1736
+ "name": "column-rule-edge-start-inset"
1737
1737
  },
1738
1738
  {
1739
- "inherited": false,
1740
- "name": "column-rule-interior-end-outset"
1739
+ "longhands": [
1740
+ "column-rule-edge-start-inset",
1741
+ "column-rule-edge-end-inset",
1742
+ "column-rule-interior-start-inset",
1743
+ "column-rule-interior-end-inset"
1744
+ ],
1745
+ "name": "column-rule-inset"
1741
1746
  },
1742
1747
  {
1743
1748
  "inherited": false,
1744
- "name": "column-rule-interior-start-outset"
1749
+ "name": "column-rule-interior-end-inset"
1745
1750
  },
1746
1751
  {
1747
- "longhands": [
1748
- "column-rule-edge-start-outset",
1749
- "column-rule-edge-end-outset",
1750
- "column-rule-interior-start-outset",
1751
- "column-rule-interior-end-outset"
1752
- ],
1753
- "name": "column-rule-outset"
1752
+ "inherited": false,
1753
+ "name": "column-rule-interior-start-inset"
1754
1754
  },
1755
1755
  {
1756
1756
  "keywords": [
@@ -3738,28 +3738,28 @@ export const generatedProperties = [
3738
3738
  },
3739
3739
  {
3740
3740
  "inherited": false,
3741
- "name": "row-rule-edge-end-outset"
3741
+ "name": "row-rule-edge-end-inset"
3742
3742
  },
3743
3743
  {
3744
3744
  "inherited": false,
3745
- "name": "row-rule-edge-start-outset"
3745
+ "name": "row-rule-edge-start-inset"
3746
3746
  },
3747
3747
  {
3748
- "inherited": false,
3749
- "name": "row-rule-interior-end-outset"
3748
+ "longhands": [
3749
+ "row-rule-edge-start-inset",
3750
+ "row-rule-edge-end-inset",
3751
+ "row-rule-interior-start-inset",
3752
+ "row-rule-interior-end-inset"
3753
+ ],
3754
+ "name": "row-rule-inset"
3750
3755
  },
3751
3756
  {
3752
3757
  "inherited": false,
3753
- "name": "row-rule-interior-start-outset"
3758
+ "name": "row-rule-interior-end-inset"
3754
3759
  },
3755
3760
  {
3756
- "longhands": [
3757
- "row-rule-edge-start-outset",
3758
- "row-rule-edge-end-outset",
3759
- "row-rule-interior-start-outset",
3760
- "row-rule-interior-end-outset"
3761
- ],
3762
- "name": "row-rule-outset"
3761
+ "inherited": false,
3762
+ "name": "row-rule-interior-start-inset"
3763
3763
  },
3764
3764
  {
3765
3765
  "keywords": [
@@ -3847,16 +3847,16 @@ export const generatedProperties = [
3847
3847
  },
3848
3848
  {
3849
3849
  "longhands": [
3850
- "row-rule-edge-start-outset",
3851
- "row-rule-edge-end-outset",
3852
- "row-rule-interior-start-outset",
3853
- "row-rule-interior-end-outset",
3854
- "column-rule-edge-start-outset",
3855
- "column-rule-edge-end-outset",
3856
- "column-rule-interior-start-outset",
3857
- "column-rule-interior-end-outset"
3858
- ],
3859
- "name": "rule-outset"
3850
+ "row-rule-edge-start-inset",
3851
+ "row-rule-edge-end-inset",
3852
+ "row-rule-interior-start-inset",
3853
+ "row-rule-interior-end-inset",
3854
+ "column-rule-edge-start-inset",
3855
+ "column-rule-edge-end-inset",
3856
+ "column-rule-interior-start-inset",
3857
+ "column-rule-interior-end-inset"
3858
+ ],
3859
+ "name": "rule-inset"
3860
3860
  },
3861
3861
  {
3862
3862
  "longhands": [
@@ -44,7 +44,8 @@ export class BuiltInAi {
44
44
  }
45
45
 
46
46
  static cachedIsAvailable(): boolean {
47
- return availability === LanguageModelAvailability.AVAILABLE;
47
+ return availability === LanguageModelAvailability.AVAILABLE &&
48
+ (hasGpu || Boolean(Root.Runtime.hostConfig.devToolsAiPromptApi?.allowWithoutGpu));
48
49
  }
49
50
 
50
51
  static isGpuAvailable(): boolean {
@@ -885,50 +885,60 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
885
885
  });
886
886
 
887
887
  const isFresh = Tracing.FreshRecording.Tracker.instance().recordingIsFresh(parsedTrace);
888
- const hasScriptContents =
889
- parsedTrace.metadata.enhancedTraceVersion && parsedTrace.data.Scripts.scripts.some(s => s.content);
888
+ const isTraceApp = Root.Runtime.Runtime.isTraceApp();
890
889
 
891
- if (isFresh || hasScriptContents) {
892
- this.declareFunction<{url: string}, {content: string}>('getResourceContent', {
893
- description: 'Returns the content of the resource with the given url. Only use this for text resource types.',
894
- parameters: {
895
- type: Host.AidaClient.ParametersTypes.OBJECT,
896
- description: '',
897
- nullable: false,
898
- properties: {
899
- url: {
900
- type: Host.AidaClient.ParametersTypes.STRING,
901
- description: 'The url for the resource.',
902
- nullable: false,
903
- },
890
+ this.declareFunction<{url: string}, {content: string}>('getResourceContent', {
891
+ description:
892
+ 'Returns the content of the resource with the given url. Only use this for text resource types. This function is helpful for getting script contents in order to further analyze main thread activity and suggest code improvements. When analyzing the main thread activity, always call this function to get more detail. Always call this function when asked to provide specifics about what is happening in the code. Never ask permission to call this function, just do it.',
893
+ parameters: {
894
+ type: Host.AidaClient.ParametersTypes.OBJECT,
895
+ description: '',
896
+ nullable: false,
897
+ properties: {
898
+ url: {
899
+ type: Host.AidaClient.ParametersTypes.STRING,
900
+ description: 'The url for the resource.',
901
+ nullable: false,
904
902
  },
905
903
  },
906
- displayInfoFromArgs: args => {
907
- return {title: lockedString('Looking at resource content…'), action: `getResourceContent('${args.url}')`};
908
- },
909
- handler: async args => {
910
- debugLog('Function call: getResourceContent');
911
-
912
- const url = args.url as Platform.DevToolsPath.UrlString;
904
+ },
905
+ displayInfoFromArgs: args => {
906
+ return {title: lockedString('Looking at resource content…'), action: `getResourceContent('${args.url}')`};
907
+ },
908
+ handler: async args => {
909
+ debugLog('Function call: getResourceContent');
910
+
911
+ const url = args.url as Platform.DevToolsPath.UrlString;
912
+ let content: string|undefined;
913
+
914
+ // First check parsedTrace.data.Scripts.
915
+ // Then, check ResourceTreeModel, but only when it is valid. Don't want to
916
+ // use if viewing a loaded trace from DevTools attached to an unrelated
917
+ // page.
918
+ const script = parsedTrace.data.Scripts.scripts.find(script => script.url === url);
919
+ if (script?.content !== undefined) {
920
+ content = script.content;
921
+ } else if (isFresh || isTraceApp) {
913
922
  const resource = SDK.ResourceTreeModel.ResourceTreeModel.resourceForURL(url);
914
923
  if (!resource) {
915
- if (!resource) {
916
- return {error: 'Resource not found'};
917
- }
924
+ return {error: 'Resource not found'};
918
925
  }
919
926
 
920
- const content = await resource.requestContentData();
921
- if ('error' in content) {
922
- return {error: `Could not get resource content: ${content.error}`};
927
+ const data = await resource.requestContentData();
928
+ if ('error' in data) {
929
+ return {error: `Could not get resource content: ${data.error}`};
923
930
  }
924
931
 
925
- const key = `getResourceContent(${args.url})`;
926
- this.#cacheFunctionResult(focus, key, content.text);
927
- return {result: {content: content.text}};
928
- },
932
+ content = data.text;
933
+ } else {
934
+ return {error: 'Resource not found'};
935
+ }
929
936
 
930
- });
931
- }
937
+ const key = `getResourceContent(${args.url})`;
938
+ this.#cacheFunctionResult(focus, key, content);
939
+ return {result: {content}};
940
+ },
941
+ });
932
942
 
933
943
  if (!context.external) {
934
944
  this.declareFunction<{eventKey: string}, {success: boolean}>('selectEventByKey', {
@@ -5,7 +5,6 @@
5
5
  import * as Common from '../../core/common/common.js';
6
6
  import * as Host from '../../core/host/host.js';
7
7
  import * as Root from '../../core/root/root.js';
8
- import * as TextEditor from '../../ui/components/text_editor/text_editor.js';
9
8
 
10
9
  import {debugLog} from './debug.js';
11
10
 
@@ -32,6 +31,20 @@ interface CachedRequest {
32
31
  response: Host.AidaClient.CompletionResponse;
33
32
  }
34
33
 
34
+ export interface Callbacks {
35
+ getSelectionHead: () => number;
36
+ getCompletionHint: () => string | undefined | null;
37
+ setAiAutoCompletion: (args: {
38
+ text: string,
39
+ from: number,
40
+ startTime: number,
41
+ onImpression: (rpcGlobalId: Host.AidaClient.RpcGlobalId, latency: number, sampleId?: number) => void,
42
+ clearCachedRequest: () => void,
43
+ rpcGlobalId?: Host.AidaClient.RpcGlobalId,
44
+ sampleId?: number,
45
+ }|null) => void;
46
+ }
47
+
35
48
  /* clang-format off */
36
49
  const consoleAdditionalContextFileContent = `/**
37
50
  * This file describes the execution environment of the Chrome DevTools Console.
@@ -141,24 +154,24 @@ const console = {
141
154
  * the suggestion is displayed.
142
155
  */
143
156
  export class AiCodeCompletion extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
144
- #editor: TextEditor.TextEditor.TextEditor;
145
157
  #stopSequences: string[];
146
158
  #renderingTimeout?: number;
147
159
  #aidaRequestCache?: CachedRequest;
160
+ // TODO(b/445394511): Remove panel from the class
148
161
  #panel: ContextFlavor;
162
+ #callbacks?: Callbacks;
149
163
 
150
164
  readonly #sessionId: string = crypto.randomUUID();
151
165
  readonly #aidaClient: Host.AidaClient.AidaClient;
152
166
  readonly #serverSideLoggingEnabled: boolean;
153
167
 
154
- constructor(
155
- opts: AgentOptions, editor: TextEditor.TextEditor.TextEditor, panel: ContextFlavor, stopSequences?: string[]) {
168
+ constructor(opts: AgentOptions, panel: ContextFlavor, callbacks?: Callbacks, stopSequences?: string[]) {
156
169
  super();
157
170
  this.#aidaClient = opts.aidaClient;
158
171
  this.#serverSideLoggingEnabled = opts.serverSideLoggingEnabled ?? false;
159
- this.#editor = editor;
160
172
  this.#panel = panel;
161
173
  this.#stopSequences = stopSequences ?? [];
174
+ this.#callbacks = callbacks;
162
175
  }
163
176
 
164
177
  #debouncedRequestAidaSuggestion = Common.Debouncer.debounce(
@@ -171,8 +184,8 @@ export class AiCodeCompletion extends Common.ObjectWrapper.ObjectWrapper<EventTy
171
184
 
172
185
  #buildRequest(
173
186
  prefix: string, suffix: string,
174
- inferenceLanguage: Host.AidaClient.AidaInferenceLanguage = Host.AidaClient.AidaInferenceLanguage.JAVASCRIPT):
175
- Host.AidaClient.CompletionRequest {
187
+ inferenceLanguage: Host.AidaClient.AidaInferenceLanguage = Host.AidaClient.AidaInferenceLanguage.JAVASCRIPT,
188
+ additionalFiles?: Host.AidaClient.AdditionalFile[]): Host.AidaClient.CompletionRequest {
176
189
  const userTier = Host.AidaClient.convertToUserTierEnum(this.#userTier);
177
190
  function validTemperature(temperature: number|undefined): number|undefined {
178
191
  return typeof temperature === 'number' && temperature >= 0 ? temperature : undefined;
@@ -180,13 +193,15 @@ export class AiCodeCompletion extends Common.ObjectWrapper.ObjectWrapper<EventTy
180
193
  // As a temporary fix for b/441221870 we are prepending a newline for each prefix.
181
194
  prefix = '\n' + prefix;
182
195
 
183
- const additionalFiles = this.#panel === ContextFlavor.CONSOLE ? [{
184
- path: 'devtools-console-context.js',
185
- content: consoleAdditionalContextFileContent,
186
- included_reason: Host.AidaClient.Reason.RELATED_FILE,
187
- }] :
188
- undefined;
189
-
196
+ let additionalContextFiles = additionalFiles ?? undefined;
197
+ if (!additionalContextFiles) {
198
+ additionalContextFiles = this.#panel === ContextFlavor.CONSOLE ? [{
199
+ path: 'devtools-console-context.js',
200
+ content: consoleAdditionalContextFileContent,
201
+ included_reason: Host.AidaClient.Reason.RELATED_FILE,
202
+ }] :
203
+ undefined;
204
+ }
190
205
  return {
191
206
  client: Host.AidaClient.CLIENT_NAME,
192
207
  prefix,
@@ -203,7 +218,7 @@ export class AiCodeCompletion extends Common.ObjectWrapper.ObjectWrapper<EventTy
203
218
  user_tier: userTier,
204
219
  client_version: Root.Runtime.getChromeVersion(),
205
220
  },
206
- additional_files: additionalFiles,
221
+ additional_files: additionalContextFiles,
207
222
  };
208
223
  }
209
224
 
@@ -239,7 +254,7 @@ export class AiCodeCompletion extends Common.ObjectWrapper.ObjectWrapper<EventTy
239
254
  // `currentHint` is the portion of a standard autocomplete suggestion that the user has not yet typed.
240
255
  // For example, if the user types `document.queryS` and the autocomplete suggests `document.querySelector`,
241
256
  // the `currentHint` is `elector`.
242
- const currentHintInMenu = this.#editor.editor.plugin(TextEditor.Config.showCompletionHint)?.currentHint;
257
+ const currentHintInMenu = this.#callbacks?.getCompletionHint();
243
258
  // TODO(ergunsh): We should not do this check here. Instead, the AI code suggestions should be provided
244
259
  // as it is to the view plugin. The view plugin should choose which one to use based on the completion hint
245
260
  // and selected completion.
@@ -321,21 +336,19 @@ export class AiCodeCompletion extends Common.ObjectWrapper.ObjectWrapper<EventTy
321
336
  } = sampleResponse;
322
337
  const remainingDelay = Math.max(DELAY_BEFORE_SHOWING_RESPONSE_MS - (performance.now() - startTime), 0);
323
338
  this.#renderingTimeout = window.setTimeout(() => {
324
- const currentCursorPosition = this.#editor.editor.state.selection.main.head;
339
+ const currentCursorPosition = this.#callbacks?.getSelectionHead();
325
340
  if (currentCursorPosition !== cursorPositionAtRequest) {
326
341
  this.dispatchEventToListeners(Events.RESPONSE_RECEIVED, {});
327
342
  return;
328
343
  }
329
- this.#editor.dispatch({
330
- effects: TextEditor.Config.setAiAutoCompleteSuggestion.of({
331
- text: suggestionText,
332
- from: cursorPositionAtRequest,
333
- rpcGlobalId,
334
- sampleId,
335
- startTime,
336
- onImpression: this.#registerUserImpression.bind(this),
337
- clearCachedRequest: this.clearCachedRequest.bind(this),
338
- })
344
+ this.#callbacks?.setAiAutoCompletion({
345
+ text: suggestionText,
346
+ from: cursorPositionAtRequest,
347
+ rpcGlobalId,
348
+ sampleId,
349
+ startTime,
350
+ onImpression: this.registerUserImpression.bind(this),
351
+ clearCachedRequest: this.clearCachedRequest.bind(this),
339
352
  });
340
353
 
341
354
  if (fromCache) {
@@ -417,7 +430,7 @@ export class AiCodeCompletion extends Common.ObjectWrapper.ObjectWrapper<EventTy
417
430
  this.#aidaRequestCache = {request, response};
418
431
  }
419
432
 
420
- #registerUserImpression(rpcGlobalId: Host.AidaClient.RpcGlobalId, latency: number, sampleId?: number): void {
433
+ registerUserImpression(rpcGlobalId: Host.AidaClient.RpcGlobalId, latency: number, sampleId?: number): void {
421
434
  const seconds = Math.floor(latency / 1_000);
422
435
  const remainingMs = latency % 1_000;
423
436
  const nanos = Math.floor(remainingMs * 1_000_000);
@@ -469,14 +482,42 @@ export class AiCodeCompletion extends Common.ObjectWrapper.ObjectWrapper<EventTy
469
482
  this.#debouncedRequestAidaSuggestion(prefix, suffix, cursorPositionAtRequest, inferenceLanguage);
470
483
  }
471
484
 
485
+ async completeCode(
486
+ prefix: string, suffix: string, cursorPositionAtRequest: number,
487
+ inferenceLanguage?: Host.AidaClient.AidaInferenceLanguage,
488
+ additionalFiles?: Host.AidaClient.AdditionalFile[]): Promise<{
489
+ response: Host.AidaClient.CompletionResponse | null,
490
+ fromCache: boolean,
491
+ }> {
492
+ const request = this.#buildRequest(prefix, suffix, inferenceLanguage, additionalFiles);
493
+ const {response, fromCache} = await this.#completeCodeCached(request);
494
+
495
+ debugLog('At cursor position', cursorPositionAtRequest, {request, response, fromCache});
496
+ if (!response) {
497
+ return {response: null, fromCache: false};
498
+ }
499
+
500
+ return {response, fromCache};
501
+ }
502
+
472
503
  remove(): void {
473
504
  if (this.#renderingTimeout) {
474
505
  clearTimeout(this.#renderingTimeout);
475
506
  this.#renderingTimeout = undefined;
476
507
  }
477
- this.#editor.dispatch({
478
- effects: TextEditor.Config.setAiAutoCompleteSuggestion.of(null),
479
- });
508
+ this.#callbacks?.setAiAutoCompletion(null);
509
+ }
510
+
511
+ static isAiCodeCompletionEnabled(locale: string): boolean {
512
+ if (!locale.startsWith('en-')) {
513
+ return false;
514
+ }
515
+ const aidaAvailability = Root.Runtime.hostConfig.aidaAvailability;
516
+ if (!aidaAvailability || aidaAvailability.blockedByGeo || aidaAvailability.blockedByAge ||
517
+ aidaAvailability.blockedByEnterprisePolicy) {
518
+ return false;
519
+ }
520
+ return Boolean(aidaAvailability.enabled && Root.Runtime.hostConfig.devToolsAiCodeCompletion?.enabled);
480
521
  }
481
522
  }
482
523
 
@@ -137,6 +137,20 @@ export class Importer {
137
137
  async () =>
138
138
  new TextUtils.ContentData.ContentData(contentText ?? '', isBase64, mimeType ?? '', charset ?? undefined));
139
139
 
140
+ if (request.mimeType === Platform.MimeType.MimeType.EVENTSTREAM && contentText) {
141
+ const issueTime = entry.startedDateTime.getTime() / 1000;
142
+ const onEvent = (eventName: string, data: string, eventId: string): void => {
143
+ request.addEventSourceMessage(issueTime, eventName, eventId, data);
144
+ };
145
+ const parser = new SDK.ServerSentEventProtocol.ServerSentEventsParser(onEvent, charset ?? undefined);
146
+ let text = contentText;
147
+ if (isBase64) {
148
+ const bytes = Common.Base64.decode(contentText);
149
+ text = new TextDecoder(charset ?? undefined).decode(bytes);
150
+ }
151
+ parser.addTextChunk(text);
152
+ }
153
+
140
154
  // Timing data.
141
155
  Importer.setupTiming(request, issueTime, entry.time, entry.timings);
142
156
 
@@ -33,7 +33,6 @@ import {SourceFrameIssuesManager} from './SourceFrameIssuesManager.js';
33
33
  import {SRIMessageSignatureIssue} from './SRIMessageSignatureIssue.js';
34
34
  import {StylesheetLoadingIssue} from './StylesheetLoadingIssue.js';
35
35
  import {UnencodedDigestIssue} from './UnencodedDigestIssue.js';
36
- import {UserReidentificationIssue} from './UserReidentificationIssue.js';
37
36
 
38
37
  export {Events} from './IssuesManagerEvents.js';
39
38
 
@@ -145,10 +144,6 @@ const issueCodeHandlers = new Map<
145
144
  Protocol.Audits.InspectorIssueCode.UnencodedDigestIssue,
146
145
  UnencodedDigestIssue.fromInspectorIssue,
147
146
  ],
148
- [
149
- Protocol.Audits.InspectorIssueCode.UserReidentificationIssue,
150
- UserReidentificationIssue.fromInspectorIssue,
151
- ],
152
147
  ]);
153
148
 
154
149
  /**
@@ -7617,10 +7617,6 @@ export const NativeFunctions = [
7617
7617
  name: "drawElementImage",
7618
7618
  signatures: [["element","x","y","?dwidth","?dheight"]]
7619
7619
  },
7620
- {
7621
- name: "setHitTestRegions",
7622
- signatures: [["hitTestRegions"]]
7623
- },
7624
7620
  {
7625
7621
  name: "Path2D",
7626
7622
  signatures: [["?path"]]