chrome-devtools-frontend 1.0.1545096 → 1.0.1547147

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 (124) hide show
  1. package/docs/styleguide/ux/styles.md +1 -1
  2. package/eslint.config.mjs +1 -1
  3. package/front_end/Images/src/arrow-down.svg +8 -1
  4. package/front_end/Images/src/arrow-up.svg +8 -1
  5. package/front_end/core/host/AidaClient.ts +1 -1
  6. package/front_end/core/host/InspectorFrontendHostAPI.ts +0 -1
  7. package/front_end/core/host/UserMetrics.ts +0 -5
  8. package/front_end/core/platform/HostRuntime.ts +18 -0
  9. package/front_end/core/platform/KeyboardUtilities.ts +2 -2
  10. package/front_end/core/platform/StringUtilities.ts +1 -1
  11. package/front_end/core/platform/api/HostRuntime.ts +20 -0
  12. package/front_end/core/platform/api/api.ts +7 -0
  13. package/front_end/core/platform/browser/HostRuntime.ts +14 -0
  14. package/front_end/core/platform/browser/browser.ts +7 -0
  15. package/front_end/core/platform/node/HostRuntime.ts +13 -0
  16. package/front_end/core/platform/node/node.ts +7 -0
  17. package/front_end/core/platform/platform.ts +2 -2
  18. package/front_end/core/sdk/SourceMapScopesInfo.ts +141 -23
  19. package/front_end/core/sdk/Target.ts +5 -14
  20. package/front_end/core/sdk/TargetManager.ts +26 -4
  21. package/front_end/core/sdk/sdk-meta.ts +62 -0
  22. package/front_end/devtools_compatibility.js +0 -1
  23. package/front_end/entrypoints/main/MainImpl.ts +2 -2
  24. package/front_end/foundation/Universe.ts +2 -2
  25. package/front_end/generated/Deprecation.ts +7 -0
  26. package/front_end/generated/InspectorBackendCommands.ts +1 -1
  27. package/front_end/generated/SupportedCSSProperties.js +4 -2
  28. package/front_end/generated/protocol.ts +3 -2
  29. package/front_end/models/ai_assistance/AiConversation.ts +188 -0
  30. package/front_end/models/ai_assistance/AiHistoryStorage.ts +1 -172
  31. package/front_end/models/ai_assistance/ConversationHandler.ts +5 -5
  32. package/front_end/models/ai_assistance/agents/AiAgent.ts +1 -3
  33. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +6 -2
  34. package/front_end/models/ai_assistance/agents/StylingAgent.snapshot.txt +1 -1
  35. package/front_end/models/ai_assistance/agents/StylingAgent.ts +3 -9
  36. package/front_end/models/ai_assistance/ai_assistance.ts +2 -0
  37. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +313 -313
  38. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +8 -6
  39. package/front_end/models/ai_assistance/performance/AICallTree.snapshot.txt +33 -33
  40. package/front_end/models/ai_assistance/performance/AICallTree.ts +9 -3
  41. package/front_end/models/bindings/CSSWorkspaceBinding.ts +5 -3
  42. package/front_end/models/bindings/SASSSourceMapping.ts +6 -4
  43. package/front_end/models/cpu_profile/CPUProfileDataModel.ts +10 -7
  44. package/front_end/models/crux-manager/CrUXManager.ts +7 -4
  45. package/front_end/models/issues_manager/GenericIssue.ts +12 -9
  46. package/front_end/models/javascript_metadata/NativeFunctions.js +4 -0
  47. package/front_end/models/trace/handlers/SamplesHandler.ts +3 -0
  48. package/front_end/models/trace/helpers/Trace.ts +13 -0
  49. package/front_end/models/trace/types/TraceEvents.ts +2 -1
  50. package/front_end/models/trace_source_maps_resolver/SourceMapsResolver.ts +29 -0
  51. package/front_end/models/workspace/IgnoreListManager.ts +1 -2
  52. package/front_end/models/workspace/UISourceCode.ts +50 -0
  53. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +9 -9
  54. package/front_end/panels/ai_assistance/ai_assistance-meta.ts +8 -0
  55. package/front_end/panels/ai_assistance/components/ChatView.ts +2 -2
  56. package/front_end/panels/animation/AnimationTimeline.ts +0 -8
  57. package/front_end/panels/application/FrameDetailsView.ts +8 -8
  58. package/front_end/panels/application/components/StackTrace.ts +84 -85
  59. package/front_end/panels/common/AiCodeGenerationTeaser.ts +80 -0
  60. package/front_end/panels/common/common.ts +2 -1
  61. package/front_end/panels/console/ConsolePrompt.ts +3 -1
  62. package/front_end/panels/console/ConsoleViewport.ts +1 -2
  63. package/front_end/panels/elements/ElementIssueUtils.ts +2 -2
  64. package/front_end/panels/elements/StylePropertyTreeElement.ts +23 -19
  65. package/front_end/panels/elements/StylesSidebarPane.ts +1 -1
  66. package/front_end/panels/elements/cssValueTraceView.css +1 -1
  67. package/front_end/panels/elements/elements-meta.ts +1 -0
  68. package/front_end/panels/explain/components/ConsoleInsight.ts +44 -57
  69. package/front_end/panels/explain/components/consoleInsight.css +46 -1
  70. package/front_end/panels/layer_viewer/LayerTreeOutline.ts +1 -2
  71. package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +19 -0
  72. package/front_end/panels/network/RequestConditionsDrawer.ts +54 -24
  73. package/front_end/panels/network/networkLogView.css +11 -0
  74. package/front_end/panels/network/networkTimingTable.css +8 -6
  75. package/front_end/panels/network/requestConditionsDrawer.css +10 -1
  76. package/front_end/panels/profiler/ProfilesPanel.ts +1 -2
  77. package/front_end/panels/settings/KeybindsSettingsTab.ts +20 -21
  78. package/front_end/panels/sources/CoveragePlugin.ts +5 -5
  79. package/front_end/panels/sources/Plugin.ts +1 -1
  80. package/front_end/panels/sources/ProfilePlugin.ts +22 -14
  81. package/front_end/panels/sources/UISourceCodeFrame.ts +2 -1
  82. package/front_end/panels/sources/sources-meta.ts +0 -62
  83. package/front_end/panels/timeline/README.md +1 -9
  84. package/front_end/panels/timeline/ThreadAppender.ts +0 -7
  85. package/front_end/panels/timeline/TimelinePanel.ts +1 -1
  86. package/front_end/panels/timeline/TimelineUIUtils.ts +2 -0
  87. package/front_end/panels/timeline/components/ExportTraceOptions.ts +15 -1
  88. package/front_end/panels/timeline/components/LiveMetricsView.ts +37 -1
  89. package/front_end/panels/timeline/components/exportTraceOptions.css +11 -2
  90. package/front_end/third_party/chromium/README.chromium +1 -1
  91. package/front_end/ui/components/markdown_view/MarkdownLinksMap.ts +1 -0
  92. package/front_end/ui/legacy/ARIAUtils.ts +2 -2
  93. package/front_end/ui/legacy/ActionRegistration.ts +11 -0
  94. package/front_end/ui/legacy/SoftDropDown.ts +2 -2
  95. package/front_end/ui/legacy/TextPrompt.ts +3 -2
  96. package/front_end/ui/legacy/Treeoutline.ts +2 -1
  97. package/front_end/ui/legacy/UIUtils.ts +11 -10
  98. package/front_end/ui/legacy/Widget.ts +3 -2
  99. package/front_end/ui/legacy/components/data_grid/DataGrid.ts +2 -2
  100. package/front_end/ui/legacy/components/perf_ui/LineLevelProfile.ts +62 -39
  101. package/front_end/ui/legacy/components/perf_ui/OverviewGrid.ts +1 -1
  102. package/front_end/ui/legacy/components/perf_ui/TimelineGrid.ts +2 -2
  103. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +2 -7
  104. package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +1 -2
  105. package/front_end/ui/legacy/inspectorCommon.css +2 -2
  106. package/front_end/ui/legacy/legacy.ts +2 -0
  107. package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
  108. package/package.json +1 -1
  109. package/front_end/panels/explain/components/consoleInsightSourcesList.css +0 -51
  110. package/front_end/ui/components/docs/README.md +0 -6
  111. package/front_end/ui/components/docs/building-ui-documentation/ComponentEvents.md +0 -54
  112. package/front_end/ui/components/docs/building-ui-documentation/ComponentPerformance.md +0 -136
  113. package/front_end/ui/components/docs/building-ui-documentation/CreatingComponents.md +0 -242
  114. package/front_end/ui/components/docs/building-ui-documentation/README.md +0 -23
  115. package/front_end/ui/components/docs/building-ui-documentation/StylingComponents.md +0 -66
  116. package/front_end/ui/components/docs/building-ui-documentation/TestingComponents.md +0 -111
  117. package/front_end/ui/components/docs/component_docs.ts +0 -24
  118. package/front_end/ui/components/docs/component_docs_styles.css +0 -53
  119. package/front_end/ui/components/docs/create_breadcrumbs.ts +0 -44
  120. package/front_end/ui/components/docs/slider/basic.html +0 -20
  121. package/front_end/ui/components/docs/switch/basic.html +0 -20
  122. /package/front_end/models/issues_manager/descriptions/{genericFormAriaLabelledByToNonExistingId.md → genericFormAriaLabelledByToNonExistingIdError.md} +0 -0
  123. /package/front_end/models/issues_manager/descriptions/{genericFormLabelHasNeitherForNorNestedInput.md → genericFormLabelHasNeitherForNorNestedInputError.md} +0 -0
  124. /package/front_end/{core/platform → ui/legacy}/DOMUtilities.ts +0 -0
@@ -9,8 +9,8 @@ import * as Bindings from '../models/bindings/bindings.js';
9
9
  import * as Workspace from '../models/workspace/workspace.js';
10
10
 
11
11
  export interface CreationOptions {
12
- // Settings things
13
12
  settingsCreationOptions: Common.Settings.SettingsCreationOptions;
13
+ overrideAutoStartModels?: Set<SDK.SDKModel.SDKModelConstructor>;
14
14
  }
15
15
 
16
16
  export class Universe {
@@ -24,7 +24,7 @@ export class Universe {
24
24
  ...options.settingsCreationOptions,
25
25
  });
26
26
 
27
- const targetManager = new SDK.TargetManager.TargetManager();
27
+ const targetManager = new SDK.TargetManager.TargetManager(options.overrideAutoStartModels);
28
28
  this.context.set(SDK.TargetManager.TargetManager, targetManager);
29
29
 
30
30
  const workspace = new Workspace.Workspace.WorkspaceImpl();
@@ -6,6 +6,10 @@
6
6
  // Re-generate with: npm run generate-protocol-resources
7
7
 
8
8
  export const UIStrings = {
9
+ /**
10
+ * @description This warning occurs when the website uses Attribution Reporting.
11
+ */
12
+ AttributionReporting: "Attribution Reporting is deprecated and will be removed. See https://goo.gle/ps-status for details.",
9
13
  /**
10
14
  * @description We show this warning when 1) an 'authorization' header is attached to the request by scripts, 2) there is no 'authorization' in the 'access-control-allow-headers' header in the response, and 3) there is a wildcard symbol ('*') in the 'access-control-allow-header' header in the response. This is allowed now, but we're planning to reject such responses and require responses to have an 'access-control-allow-headers' containing 'authorization'.
11
15
  */
@@ -238,6 +242,9 @@ export interface DeprecationDescriptor {
238
242
  }
239
243
 
240
244
  export const DEPRECATIONS_METADATA: Partial<Record<string, DeprecationDescriptor>> = {
245
+ "AttributionReporting": {
246
+ "chromeStatusFeature": 6320639375966208
247
+ },
241
248
  "AuthorizationCoveredByWildcard": {
242
249
  "milestone": 97
243
250
  },
@@ -81,7 +81,7 @@ inspectorBackend.registerEnum("Audits.AttributionReportingIssueType", {Permissio
81
81
  inspectorBackend.registerEnum("Audits.SharedDictionaryError", {UseErrorCrossOriginNoCorsRequest: "UseErrorCrossOriginNoCorsRequest", UseErrorDictionaryLoadFailure: "UseErrorDictionaryLoadFailure", UseErrorMatchingDictionaryNotUsed: "UseErrorMatchingDictionaryNotUsed", UseErrorUnexpectedContentDictionaryHeader: "UseErrorUnexpectedContentDictionaryHeader", WriteErrorCossOriginNoCorsRequest: "WriteErrorCossOriginNoCorsRequest", WriteErrorDisallowedBySettings: "WriteErrorDisallowedBySettings", WriteErrorExpiredResponse: "WriteErrorExpiredResponse", WriteErrorFeatureDisabled: "WriteErrorFeatureDisabled", WriteErrorInsufficientResources: "WriteErrorInsufficientResources", WriteErrorInvalidMatchField: "WriteErrorInvalidMatchField", WriteErrorInvalidStructuredHeader: "WriteErrorInvalidStructuredHeader", WriteErrorInvalidTTLField: "WriteErrorInvalidTTLField", WriteErrorNavigationRequest: "WriteErrorNavigationRequest", WriteErrorNoMatchField: "WriteErrorNoMatchField", WriteErrorNonIntegerTTLField: "WriteErrorNonIntegerTTLField", WriteErrorNonListMatchDestField: "WriteErrorNonListMatchDestField", WriteErrorNonSecureContext: "WriteErrorNonSecureContext", WriteErrorNonStringIdField: "WriteErrorNonStringIdField", WriteErrorNonStringInMatchDestList: "WriteErrorNonStringInMatchDestList", WriteErrorNonStringMatchField: "WriteErrorNonStringMatchField", WriteErrorNonTokenTypeField: "WriteErrorNonTokenTypeField", WriteErrorRequestAborted: "WriteErrorRequestAborted", WriteErrorShuttingDown: "WriteErrorShuttingDown", WriteErrorTooLongIdField: "WriteErrorTooLongIdField", WriteErrorUnsupportedType: "WriteErrorUnsupportedType"});
82
82
  inspectorBackend.registerEnum("Audits.SRIMessageSignatureError", {MissingSignatureHeader: "MissingSignatureHeader", MissingSignatureInputHeader: "MissingSignatureInputHeader", InvalidSignatureHeader: "InvalidSignatureHeader", InvalidSignatureInputHeader: "InvalidSignatureInputHeader", SignatureHeaderValueIsNotByteSequence: "SignatureHeaderValueIsNotByteSequence", SignatureHeaderValueIsParameterized: "SignatureHeaderValueIsParameterized", SignatureHeaderValueIsIncorrectLength: "SignatureHeaderValueIsIncorrectLength", SignatureInputHeaderMissingLabel: "SignatureInputHeaderMissingLabel", SignatureInputHeaderValueNotInnerList: "SignatureInputHeaderValueNotInnerList", SignatureInputHeaderValueMissingComponents: "SignatureInputHeaderValueMissingComponents", SignatureInputHeaderInvalidComponentType: "SignatureInputHeaderInvalidComponentType", SignatureInputHeaderInvalidComponentName: "SignatureInputHeaderInvalidComponentName", SignatureInputHeaderInvalidHeaderComponentParameter: "SignatureInputHeaderInvalidHeaderComponentParameter", SignatureInputHeaderInvalidDerivedComponentParameter: "SignatureInputHeaderInvalidDerivedComponentParameter", SignatureInputHeaderKeyIdLength: "SignatureInputHeaderKeyIdLength", SignatureInputHeaderInvalidParameter: "SignatureInputHeaderInvalidParameter", SignatureInputHeaderMissingRequiredParameters: "SignatureInputHeaderMissingRequiredParameters", ValidationFailedSignatureExpired: "ValidationFailedSignatureExpired", ValidationFailedInvalidLength: "ValidationFailedInvalidLength", ValidationFailedSignatureMismatch: "ValidationFailedSignatureMismatch", ValidationFailedIntegrityMismatch: "ValidationFailedIntegrityMismatch"});
83
83
  inspectorBackend.registerEnum("Audits.UnencodedDigestError", {MalformedDictionary: "MalformedDictionary", UnknownAlgorithm: "UnknownAlgorithm", IncorrectDigestType: "IncorrectDigestType", IncorrectDigestLength: "IncorrectDigestLength"});
84
- inspectorBackend.registerEnum("Audits.GenericIssueErrorType", {FormLabelForNameError: "FormLabelForNameError", FormDuplicateIdForInputError: "FormDuplicateIdForInputError", FormInputWithNoLabelError: "FormInputWithNoLabelError", FormAutocompleteAttributeEmptyError: "FormAutocompleteAttributeEmptyError", FormEmptyIdAndNameAttributesForInputError: "FormEmptyIdAndNameAttributesForInputError", FormAriaLabelledByToNonExistingId: "FormAriaLabelledByToNonExistingId", FormInputAssignedAutocompleteValueToIdOrNameAttributeError: "FormInputAssignedAutocompleteValueToIdOrNameAttributeError", FormLabelHasNeitherForNorNestedInput: "FormLabelHasNeitherForNorNestedInput", FormLabelForMatchesNonExistingIdError: "FormLabelForMatchesNonExistingIdError", FormInputHasWrongButWellIntendedAutocompleteValueError: "FormInputHasWrongButWellIntendedAutocompleteValueError", ResponseWasBlockedByORB: "ResponseWasBlockedByORB"});
84
+ inspectorBackend.registerEnum("Audits.GenericIssueErrorType", {FormLabelForNameError: "FormLabelForNameError", FormDuplicateIdForInputError: "FormDuplicateIdForInputError", FormInputWithNoLabelError: "FormInputWithNoLabelError", FormAutocompleteAttributeEmptyError: "FormAutocompleteAttributeEmptyError", FormEmptyIdAndNameAttributesForInputError: "FormEmptyIdAndNameAttributesForInputError", FormAriaLabelledByToNonExistingIdError: "FormAriaLabelledByToNonExistingIdError", FormInputAssignedAutocompleteValueToIdOrNameAttributeError: "FormInputAssignedAutocompleteValueToIdOrNameAttributeError", FormLabelHasNeitherForNorNestedInputError: "FormLabelHasNeitherForNorNestedInputError", FormLabelForMatchesNonExistingIdError: "FormLabelForMatchesNonExistingIdError", FormInputHasWrongButWellIntendedAutocompleteValueError: "FormInputHasWrongButWellIntendedAutocompleteValueError", ResponseWasBlockedByORB: "ResponseWasBlockedByORB", NavigationEntryMarkedSkippable: "NavigationEntryMarkedSkippable"});
85
85
  inspectorBackend.registerEnum("Audits.ClientHintIssueReason", {MetaTagAllowListInvalidOrigin: "MetaTagAllowListInvalidOrigin", MetaTagModifiedHTML: "MetaTagModifiedHTML"});
86
86
  inspectorBackend.registerEnum("Audits.FederatedAuthRequestIssueReason", {ShouldEmbargo: "ShouldEmbargo", TooManyRequests: "TooManyRequests", WellKnownHttpNotFound: "WellKnownHttpNotFound", WellKnownNoResponse: "WellKnownNoResponse", WellKnownInvalidResponse: "WellKnownInvalidResponse", WellKnownListEmpty: "WellKnownListEmpty", WellKnownInvalidContentType: "WellKnownInvalidContentType", ConfigNotInWellKnown: "ConfigNotInWellKnown", WellKnownTooBig: "WellKnownTooBig", ConfigHttpNotFound: "ConfigHttpNotFound", ConfigNoResponse: "ConfigNoResponse", ConfigInvalidResponse: "ConfigInvalidResponse", ConfigInvalidContentType: "ConfigInvalidContentType", ClientMetadataHttpNotFound: "ClientMetadataHttpNotFound", ClientMetadataNoResponse: "ClientMetadataNoResponse", ClientMetadataInvalidResponse: "ClientMetadataInvalidResponse", ClientMetadataInvalidContentType: "ClientMetadataInvalidContentType", IdpNotPotentiallyTrustworthy: "IdpNotPotentiallyTrustworthy", DisabledInSettings: "DisabledInSettings", DisabledInFlags: "DisabledInFlags", ErrorFetchingSignin: "ErrorFetchingSignin", InvalidSigninResponse: "InvalidSigninResponse", AccountsHttpNotFound: "AccountsHttpNotFound", AccountsNoResponse: "AccountsNoResponse", AccountsInvalidResponse: "AccountsInvalidResponse", AccountsListEmpty: "AccountsListEmpty", AccountsInvalidContentType: "AccountsInvalidContentType", IdTokenHttpNotFound: "IdTokenHttpNotFound", IdTokenNoResponse: "IdTokenNoResponse", IdTokenInvalidResponse: "IdTokenInvalidResponse", IdTokenIdpErrorResponse: "IdTokenIdpErrorResponse", IdTokenCrossSiteIdpErrorResponse: "IdTokenCrossSiteIdpErrorResponse", IdTokenInvalidRequest: "IdTokenInvalidRequest", IdTokenInvalidContentType: "IdTokenInvalidContentType", ErrorIdToken: "ErrorIdToken", Canceled: "Canceled", RpPageNotVisible: "RpPageNotVisible", SilentMediationFailure: "SilentMediationFailure", ThirdPartyCookiesBlocked: "ThirdPartyCookiesBlocked", NotSignedInWithIdp: "NotSignedInWithIdp", MissingTransientUserActivation: "MissingTransientUserActivation", ReplacedByActiveMode: "ReplacedByActiveMode", InvalidFieldsSpecified: "InvalidFieldsSpecified", RelyingPartyOriginIsOpaque: "RelyingPartyOriginIsOpaque", TypeNotMatching: "TypeNotMatching", UiDismissedNoEmbargo: "UiDismissedNoEmbargo", CorsError: "CorsError", SuppressedBySegmentationPlatform: "SuppressedBySegmentationPlatform"});
87
87
  inspectorBackend.registerEnum("Audits.FederatedAuthUserInfoRequestIssueReason", {NotSameOrigin: "NotSameOrigin", NotIframe: "NotIframe", NotPotentiallyTrustworthy: "NotPotentiallyTrustworthy", NoAPIPermission: "NoApiPermission", NotSignedInWithIdp: "NotSignedInWithIdp", NoAccountSharingPermission: "NoAccountSharingPermission", InvalidConfigOrWellKnown: "InvalidConfigOrWellKnown", InvalidAccountsResponse: "InvalidAccountsResponse", NoReturningUserFromFetchedAccounts: "NoReturningUserFromFetchedAccounts"});
@@ -3582,7 +3582,8 @@ export const generatedProperties = [
3582
3582
  },
3583
3583
  {
3584
3584
  "keywords": [
3585
- "auto"
3585
+ "auto",
3586
+ "none"
3586
3587
  ],
3587
3588
  "name": "position-anchor"
3588
3589
  },
@@ -6438,7 +6439,8 @@ export const generatedPropertyValues = {
6438
6439
  },
6439
6440
  "position-anchor": {
6440
6441
  "values": [
6441
- "auto"
6442
+ "auto",
6443
+ "none"
6442
6444
  ]
6443
6445
  },
6444
6446
  "position-area": {
@@ -1187,12 +1187,13 @@ export namespace Audits {
1187
1187
  FormInputWithNoLabelError = 'FormInputWithNoLabelError',
1188
1188
  FormAutocompleteAttributeEmptyError = 'FormAutocompleteAttributeEmptyError',
1189
1189
  FormEmptyIdAndNameAttributesForInputError = 'FormEmptyIdAndNameAttributesForInputError',
1190
- FormAriaLabelledByToNonExistingId = 'FormAriaLabelledByToNonExistingId',
1190
+ FormAriaLabelledByToNonExistingIdError = 'FormAriaLabelledByToNonExistingIdError',
1191
1191
  FormInputAssignedAutocompleteValueToIdOrNameAttributeError = 'FormInputAssignedAutocompleteValueToIdOrNameAttributeError',
1192
- FormLabelHasNeitherForNorNestedInput = 'FormLabelHasNeitherForNorNestedInput',
1192
+ FormLabelHasNeitherForNorNestedInputError = 'FormLabelHasNeitherForNorNestedInputError',
1193
1193
  FormLabelForMatchesNonExistingIdError = 'FormLabelForMatchesNonExistingIdError',
1194
1194
  FormInputHasWrongButWellIntendedAutocompleteValueError = 'FormInputHasWrongButWellIntendedAutocompleteValueError',
1195
1195
  ResponseWasBlockedByORB = 'ResponseWasBlockedByORB',
1196
+ NavigationEntryMarkedSkippable = 'NavigationEntryMarkedSkippable',
1196
1197
  }
1197
1198
 
1198
1199
  /**
@@ -0,0 +1,188 @@
1
+ // Copyright 2024 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 {type ContextDetail, type ResponseData, ResponseType} from './agents/AiAgent.js';
6
+ import {AiHistoryStorage, type ConversationType, type SerializedConversation} from './AiHistoryStorage.js';
7
+
8
+ export const NOT_FOUND_IMAGE_DATA = '';
9
+ const MAX_TITLE_LENGTH = 80;
10
+
11
+ export class AiConversation {
12
+ readonly id: string;
13
+ type: ConversationType;
14
+ #isReadOnly: boolean;
15
+ readonly history: ResponseData[];
16
+ #isExternal: boolean;
17
+
18
+ static generateContextDetailsMarkdown(details: ContextDetail[]): string {
19
+ const detailsMarkdown: string[] = [];
20
+ for (const detail of details) {
21
+ const text = `\`\`\`\`${detail.codeLang || ''}\n${detail.text.trim()}\n\`\`\`\``;
22
+ detailsMarkdown.push(`**${detail.title}:**\n${text}`);
23
+ }
24
+ return detailsMarkdown.join('\n\n');
25
+ }
26
+
27
+ constructor(
28
+ type: ConversationType,
29
+ data: ResponseData[] = [],
30
+ id: string = crypto.randomUUID(),
31
+ isReadOnly = true,
32
+ isExternal = false,
33
+ ) {
34
+ this.type = type;
35
+ this.id = id;
36
+ this.#isReadOnly = isReadOnly;
37
+ this.#isExternal = isExternal;
38
+ this.history = this.#reconstructHistory(data);
39
+ }
40
+
41
+ get isReadOnly(): boolean {
42
+ return this.#isReadOnly;
43
+ }
44
+
45
+ get title(): string|undefined {
46
+ const query = this.history.find(response => response.type === ResponseType.USER_QUERY)?.query;
47
+
48
+ if (!query) {
49
+ return;
50
+ }
51
+
52
+ if (this.#isExternal) {
53
+ return `[External] ${query.substring(0, MAX_TITLE_LENGTH - 11)}${
54
+ query.length > MAX_TITLE_LENGTH - 11 ? '…' : ''}`;
55
+ }
56
+ return `${query.substring(0, MAX_TITLE_LENGTH)}${query.length > MAX_TITLE_LENGTH ? '…' : ''}`;
57
+ }
58
+
59
+ get isEmpty(): boolean {
60
+ return this.history.length === 0;
61
+ }
62
+
63
+ #reconstructHistory(historyWithoutImages: ResponseData[]): ResponseData[] {
64
+ const imageHistory = AiHistoryStorage.instance().getImageHistory();
65
+ if (imageHistory && imageHistory.length > 0) {
66
+ const history: ResponseData[] = [];
67
+ for (const data of historyWithoutImages) {
68
+ if (data.type === ResponseType.USER_QUERY && data.imageId) {
69
+ const image = imageHistory.find(item => item.id === data.imageId);
70
+ const inlineData = image ? {data: image.data, mimeType: image.mimeType} :
71
+ {data: NOT_FOUND_IMAGE_DATA, mimeType: 'image/jpeg'};
72
+ history.push({...data, imageInput: {inlineData}});
73
+ } else {
74
+ history.push(data);
75
+ }
76
+ }
77
+ return history;
78
+ }
79
+ return historyWithoutImages;
80
+ }
81
+
82
+ getConversationMarkdown(): string {
83
+ const contentParts: string[] = [];
84
+ contentParts.push(
85
+ '# Exported Chat from Chrome DevTools AI Assistance\n\n' +
86
+ `**Export Timestamp (UTC):** ${new Date().toISOString()}\n\n` +
87
+ '---',
88
+ );
89
+ for (const item of this.history) {
90
+ switch (item.type) {
91
+ case ResponseType.USER_QUERY: {
92
+ contentParts.push(`## User\n\n${item.query}`);
93
+ if (item.imageInput) {
94
+ contentParts.push('User attached an image');
95
+ }
96
+ contentParts.push('## AI');
97
+ break;
98
+ }
99
+ case ResponseType.CONTEXT: {
100
+ contentParts.push(`### ${item.title}`);
101
+ if (item.details && item.details.length > 0) {
102
+ contentParts.push(AiConversation.generateContextDetailsMarkdown(item.details));
103
+ }
104
+ break;
105
+ }
106
+ case ResponseType.TITLE: {
107
+ contentParts.push(`### ${item.title}`);
108
+ break;
109
+ }
110
+ case ResponseType.THOUGHT: {
111
+ contentParts.push(`${item.thought}`);
112
+ break;
113
+ }
114
+ case ResponseType.ACTION: {
115
+ // We want to export only actions with output field
116
+ if (!item.output) {
117
+ break;
118
+ }
119
+ if (item.code) {
120
+ contentParts.push(`**Code executed:**\n\`\`\`\n${item.code.trim()}\n\`\`\``);
121
+ }
122
+ contentParts.push(`**Data returned:**\n\`\`\`\n${item.output}\n\`\`\``);
123
+ break;
124
+ }
125
+ case ResponseType.ANSWER: {
126
+ if (item.complete) {
127
+ contentParts.push(`### Answer\n\n${item.text.trim()}`);
128
+ }
129
+ break;
130
+ }
131
+ }
132
+ }
133
+ return contentParts.join('\n\n');
134
+ }
135
+
136
+ archiveConversation(): void {
137
+ this.#isReadOnly = true;
138
+ }
139
+
140
+ async addHistoryItem(item: ResponseData): Promise<void> {
141
+ this.history.push(item);
142
+ await AiHistoryStorage.instance().upsertHistoryEntry(this.serialize());
143
+ if (item.type === ResponseType.USER_QUERY) {
144
+ if (item.imageId && item.imageInput && 'inlineData' in item.imageInput) {
145
+ const inlineData = item.imageInput.inlineData;
146
+ await AiHistoryStorage.instance().upsertImage({
147
+ id: item.imageId,
148
+ data: inlineData.data,
149
+ mimeType: inlineData.mimeType,
150
+ });
151
+ }
152
+ }
153
+ }
154
+
155
+ serialize(): SerializedConversation {
156
+ return {
157
+ id: this.id,
158
+ history: this.history.map(item => {
159
+ if (item.type === ResponseType.USER_QUERY) {
160
+ return {...item, imageInput: undefined};
161
+ }
162
+ // Remove the `confirm()`-function because `structuredClone()` throws on functions
163
+ if (item.type === ResponseType.SIDE_EFFECT) {
164
+ return {...item, confirm: undefined};
165
+ }
166
+ return item;
167
+ }),
168
+ type: this.type,
169
+ isExternal: this.#isExternal,
170
+ };
171
+ }
172
+
173
+ static fromSerializedConversation(serializedConversation: SerializedConversation): AiConversation {
174
+ const history = serializedConversation.history.map(entry => {
175
+ if (entry.type === ResponseType.SIDE_EFFECT) {
176
+ return {...entry, confirm: () => {}};
177
+ }
178
+ return entry;
179
+ });
180
+ return new AiConversation(
181
+ serializedConversation.type,
182
+ history,
183
+ serializedConversation.id,
184
+ true,
185
+ serializedConversation.isExternal,
186
+ );
187
+ }
188
+ }
@@ -5,9 +5,7 @@
5
5
 
6
6
  import * as Common from '../../core/common/common.js';
7
7
 
8
- import {type ContextDetail, type ResponseData, ResponseType, type SerializedResponseData} from './agents/AiAgent.js';
9
-
10
- const MAX_TITLE_LENGTH = 80;
8
+ import {ResponseType, type SerializedResponseData} from './agents/AiAgent.js';
11
9
 
12
10
  export const enum ConversationType {
13
11
  STYLING = 'freestyler',
@@ -16,8 +14,6 @@ export const enum ConversationType {
16
14
  PERFORMANCE = 'drjones-performance-full',
17
15
  }
18
16
 
19
- export const NOT_FOUND_IMAGE_DATA = '';
20
-
21
17
  export interface SerializedConversation {
22
18
  id: string;
23
19
  type: ConversationType;
@@ -35,173 +31,6 @@ export interface SerializedImage {
35
31
  data: string;
36
32
  }
37
33
 
38
- export class Conversation {
39
- readonly id: string;
40
- readonly type: ConversationType;
41
- #isReadOnly: boolean;
42
- readonly history: ResponseData[];
43
- #isExternal: boolean;
44
-
45
- static generateContextDetailsMarkdown(details: ContextDetail[]): string {
46
- const detailsMarkdown: string[] = [];
47
- for (const detail of details) {
48
- const text = `\`\`\`\`${detail.codeLang || ''}\n${detail.text.trim()}\n\`\`\`\``;
49
- detailsMarkdown.push(`**${detail.title}:**\n${text}`);
50
- }
51
- return detailsMarkdown.join('\n\n');
52
- }
53
-
54
- constructor(
55
- type: ConversationType, data: ResponseData[] = [], id: string = crypto.randomUUID(), isReadOnly = true,
56
- isExternal = false) {
57
- this.type = type;
58
- this.id = id;
59
- this.#isReadOnly = isReadOnly;
60
- this.#isExternal = isExternal;
61
- this.history = this.#reconstructHistory(data);
62
- }
63
-
64
- get isReadOnly(): boolean {
65
- return this.#isReadOnly;
66
- }
67
-
68
- get title(): string|undefined {
69
- const query = this.history.find(response => response.type === ResponseType.USER_QUERY)?.query;
70
-
71
- if (!query) {
72
- return;
73
- }
74
-
75
- if (this.#isExternal) {
76
- return `[External] ${query.substring(0, MAX_TITLE_LENGTH - 11)}${
77
- query.length > MAX_TITLE_LENGTH - 11 ? '…' : ''}`;
78
- }
79
- return `${query.substring(0, MAX_TITLE_LENGTH)}${query.length > MAX_TITLE_LENGTH ? '…' : ''}`;
80
- }
81
-
82
- get isEmpty(): boolean {
83
- return this.history.length === 0;
84
- }
85
-
86
- #reconstructHistory(historyWithoutImages: ResponseData[]): ResponseData[] {
87
- const imageHistory = AiHistoryStorage.instance().getImageHistory();
88
- if (imageHistory && imageHistory.length > 0) {
89
- const history: ResponseData[] = [];
90
- for (const data of historyWithoutImages) {
91
- if (data.type === ResponseType.USER_QUERY && data.imageId) {
92
- const image = imageHistory.find(item => item.id === data.imageId);
93
- const inlineData = image ? {data: image.data, mimeType: image.mimeType} :
94
- {data: NOT_FOUND_IMAGE_DATA, mimeType: 'image/jpeg'};
95
- history.push({...data, imageInput: {inlineData}});
96
- } else {
97
- history.push(data);
98
- }
99
- }
100
- return history;
101
- }
102
- return historyWithoutImages;
103
- }
104
-
105
- getConversationMarkdown(): string {
106
- const contentParts: string[] = [];
107
- contentParts.push(
108
- '# Exported Chat from Chrome DevTools AI Assistance\n\n' +
109
- `**Export Timestamp (UTC):** ${new Date().toISOString()}\n\n` +
110
- '---',
111
- );
112
- for (const item of this.history) {
113
- switch (item.type) {
114
- case ResponseType.USER_QUERY: {
115
- contentParts.push(`## User\n\n${item.query}`);
116
- if (item.imageInput) {
117
- contentParts.push('User attached an image');
118
- }
119
- contentParts.push('## AI');
120
- break;
121
- }
122
- case ResponseType.CONTEXT: {
123
- contentParts.push(`### ${item.title}`);
124
- if (item.details && item.details.length > 0) {
125
- contentParts.push(Conversation.generateContextDetailsMarkdown(item.details));
126
- }
127
- break;
128
- }
129
- case ResponseType.TITLE: {
130
- contentParts.push(`### ${item.title}`);
131
- break;
132
- }
133
- case ResponseType.THOUGHT: {
134
- contentParts.push(`${item.thought}`);
135
- break;
136
- }
137
- case ResponseType.ACTION: {
138
- // We want to export only actions with output field
139
- if (!item.output) {
140
- break;
141
- }
142
- if (item.code) {
143
- contentParts.push(`**Code executed:**\n\`\`\`\n${item.code.trim()}\n\`\`\``);
144
- }
145
- contentParts.push(`**Data returned:**\n\`\`\`\n${item.output}\n\`\`\``);
146
- break;
147
- }
148
- case ResponseType.ANSWER: {
149
- if (item.complete) {
150
- contentParts.push(`### Answer\n\n${item.text.trim()}`);
151
- }
152
- break;
153
- }
154
- }
155
- }
156
- return contentParts.join('\n\n');
157
- }
158
-
159
- archiveConversation(): void {
160
- this.#isReadOnly = true;
161
- }
162
-
163
- async addHistoryItem(item: ResponseData): Promise<void> {
164
- this.history.push(item);
165
- await AiHistoryStorage.instance().upsertHistoryEntry(this.serialize());
166
- if (item.type === ResponseType.USER_QUERY) {
167
- if (item.imageId && item.imageInput && 'inlineData' in item.imageInput) {
168
- const inlineData = item.imageInput.inlineData;
169
- await AiHistoryStorage.instance().upsertImage(
170
- {id: item.imageId, data: inlineData.data, mimeType: inlineData.mimeType});
171
- }
172
- }
173
- }
174
-
175
- serialize(): SerializedConversation {
176
- return {
177
- id: this.id,
178
- history: this.history.map(item => {
179
- if (item.type === ResponseType.USER_QUERY) {
180
- return {...item, imageInput: undefined};
181
- }
182
- // Remove the `confirm()`-function because `structuredClone()` throws on functions
183
- if (item.type === ResponseType.SIDE_EFFECT) {
184
- return {...item, confirm: undefined};
185
- }
186
- return item;
187
- }),
188
- type: this.type,
189
- isExternal: this.#isExternal,
190
- };
191
- }
192
-
193
- static fromSerializedConversation(serializedConversation: SerializedConversation): Conversation {
194
- const history = serializedConversation.history.map(entry => {
195
- if (entry.type === ResponseType.SIDE_EFFECT) {
196
- return {...entry, confirm: () => {}};
197
- }
198
- return entry;
199
- });
200
- return new Conversation(
201
- serializedConversation.type, history, serializedConversation.id, true, serializedConversation.isExternal);
202
- }
203
- }
204
-
205
34
  let instance: AiHistoryStorage|null = null;
206
35
 
207
36
  const DEFAULT_MAX_STORAGE_SIZE = 50 * 1024 * 1024;
@@ -21,8 +21,8 @@ import {FileAgent} from './agents/FileAgent.js';
21
21
  import {NetworkAgent, RequestContext} from './agents/NetworkAgent.js';
22
22
  import {PerformanceAgent, type PerformanceTraceContext} from './agents/PerformanceAgent.js';
23
23
  import {NodeContext, StylingAgent} from './agents/StylingAgent.js';
24
+ import {AiConversation} from './AiConversation.js';
24
25
  import {
25
- Conversation,
26
26
  ConversationType,
27
27
  } from './AiHistoryStorage.js';
28
28
  import {getDisabledReasons} from './AiUtils.js';
@@ -42,7 +42,7 @@ interface ExternalNetworkRequestParameters {
42
42
 
43
43
  export interface ExternalPerformanceAIConversationData {
44
44
  conversationHandler: ConversationHandler;
45
- conversation: Conversation;
45
+ conversation: AiConversation;
46
46
  agent: AiAgent<unknown>;
47
47
  selected: PerformanceTraceContext;
48
48
  }
@@ -207,7 +207,7 @@ export class ConversationHandler extends Common.ObjectWrapper.ObjectWrapper<Even
207
207
 
208
208
  async *
209
209
  handleConversationWithHistory(
210
- items: AsyncIterable<ResponseData, void, void>, conversation: Conversation|undefined):
210
+ items: AsyncIterable<ResponseData, void, void>, conversation: AiConversation|undefined):
211
211
  AsyncGenerator<ResponseData, void, void> {
212
212
  for await (const data of items) {
213
213
  // We don't want to save partial responses to the conversation history.
@@ -225,7 +225,7 @@ export class ConversationHandler extends Common.ObjectWrapper.ObjectWrapper<Even
225
225
  selected: NodeContext|PerformanceTraceContext|RequestContext|null,
226
226
  }): AsyncGenerator<ExternalRequestResponse, ExternalRequestResponse> {
227
227
  const {conversationType, aiAgent, prompt, selected} = opts;
228
- const conversation = new Conversation(
228
+ const conversation = new AiConversation(
229
229
  conversationType,
230
230
  [],
231
231
  aiAgent.id,
@@ -236,7 +236,7 @@ export class ConversationHandler extends Common.ObjectWrapper.ObjectWrapper<Even
236
236
  }
237
237
 
238
238
  async * #doExternalConversation(opts: {
239
- conversation: Conversation,
239
+ conversation: AiConversation,
240
240
  aiAgent: AiAgent<unknown>,
241
241
  prompt: string,
242
242
  selected: NodeContext|PerformanceTraceContext|RequestContext|null,
@@ -682,9 +682,7 @@ export abstract class AiAgent<T> {
682
682
 
683
683
  yield {
684
684
  type: ResponseType.SIDE_EFFECT,
685
- confirm: (result: boolean) => {
686
- sideEffectConfirmationPromiseWithResolvers.resolve(result);
687
- },
685
+ confirm: sideEffectConfirmationPromiseWithResolvers.resolve,
688
686
  };
689
687
 
690
688
  const approvedRun = await sideEffectConfirmationPromiseWithResolvers.promise;
@@ -492,7 +492,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
492
492
  this.#addFacts(options.selected);
493
493
  }
494
494
 
495
- return yield* super.run(initialQuery, options);
495
+ yield* super.run(initialQuery, options);
496
496
  }
497
497
 
498
498
  #createFactForTraceSummary(): void {
@@ -870,7 +870,11 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
870
870
  }
871
871
 
872
872
  const tree = AICallTree.fromEvent(event, parsedTrace);
873
- const callTree = tree ? this.#formatter.formatCallTree(tree) : 'No call tree found';
873
+ if (!tree) {
874
+ return {error: 'No call tree found'};
875
+ }
876
+
877
+ const callTree = this.#formatter.formatCallTree(tree);
874
878
 
875
879
  const key = `getDetailedCallTree(${args.eventKey})`;
876
880
  this.#cacheFunctionResult(focus, key, callTree);
@@ -119,7 +119,7 @@ Content:
119
119
  "metadata": {
120
120
  "disable_user_content_logging": false,
121
121
  "string_session_id": "sessionId",
122
- "user_tier": 2,
122
+ "user_tier": 3,
123
123
  "client_version": "unit_test+function_calling"
124
124
  },
125
125
  "functionality_type": 5,
@@ -327,11 +327,8 @@ export class StylingAgent extends AiAgent<SDK.DOMModel.DOMNode> {
327
327
  action: `getStyles(${JSON.stringify(params.elements)}, ${JSON.stringify(params.styleProperties)})`,
328
328
  };
329
329
  },
330
- handler: async (
331
- params,
332
- options,
333
- ) => {
334
- return await this.getStyles(params.elements, params.styleProperties, options);
330
+ handler: async params => {
331
+ return await this.getStyles(params.elements, params.styleProperties);
335
332
  },
336
333
  });
337
334
 
@@ -583,10 +580,7 @@ const data = {
583
580
  return this.context?.getItem() ?? null;
584
581
  }
585
582
 
586
- async getStyles(elements: string[], properties: string[], _options?: {
587
- signal?: AbortSignal,
588
- approved?: boolean,
589
- }): Promise<FunctionCallHandlerResult<unknown>> {
583
+ async getStyles(elements: string[], properties: string[]): Promise<FunctionCallHandlerResult<unknown>> {
590
584
  const result:
591
585
  Record<string, {computed: Record<string, string|undefined>, authored: Record<string, string|undefined>}> = {};
592
586
  for (const uid of elements) {
@@ -10,6 +10,7 @@ import * as PatchAgent from './agents/PatchAgent.js';
10
10
  import * as PerformanceAgent from './agents/PerformanceAgent.js';
11
11
  import * as PerformanceAnnotationsAgent from './agents/PerformanceAnnotationsAgent.js';
12
12
  import * as StylingAgent from './agents/StylingAgent.js';
13
+ import * as AiConversation from './AiConversation.js';
13
14
  import * as AiHistoryStorage from './AiHistoryStorage.js';
14
15
  import * as AiUtils from './AiUtils.js';
15
16
  import * as BuiltInAi from './BuiltInAi.js';
@@ -33,6 +34,7 @@ export {
33
34
  AiAgent,
34
35
  AICallTree,
35
36
  AIContext,
37
+ AiConversation,
36
38
  AiHistoryStorage,
37
39
  AIQueries,
38
40
  AiUtils,