chrome-devtools-frontend 1.0.1581708 → 1.0.1582745

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 (53) hide show
  1. package/front_end/core/sdk/RemoteObject.ts +7 -1
  2. package/front_end/entrypoint_template.html +5 -1
  3. package/front_end/entrypoints/greendev_floaty/FloatyEntrypoint.ts +9 -24
  4. package/front_end/entrypoints/greendev_floaty/floaty.css +1 -1
  5. package/front_end/entrypoints/greendev_floaty/greendev_floaty.ts +1 -1
  6. package/front_end/generated/InspectorBackendCommands.ts +1 -1
  7. package/front_end/generated/SupportedCSSProperties.js +2 -0
  8. package/front_end/generated/protocol.ts +0 -6
  9. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.snapshot.txt +6 -6
  10. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +17 -9
  11. package/front_end/models/ai_assistance/agents/NetworkAgent.ts +2 -6
  12. package/front_end/models/ai_assistance/data_formatters/NetworkRequestFormatter.ts +66 -2
  13. package/front_end/models/greendev/Prototypes.ts +1 -10
  14. package/front_end/models/issues_manager/ConnectionAllowlistIssue.ts +75 -0
  15. package/front_end/models/issues_manager/FederatedAuthRequestIssue.ts +0 -30
  16. package/front_end/models/issues_manager/IssuesManager.ts +5 -0
  17. package/front_end/models/issues_manager/descriptions/connectionAllowlistInvalidAllowlistItemType.md +12 -0
  18. package/front_end/models/issues_manager/descriptions/connectionAllowlistInvalidHeader.md +12 -0
  19. package/front_end/models/issues_manager/descriptions/connectionAllowlistInvalidUrlPattern.md +8 -0
  20. package/front_end/models/issues_manager/descriptions/connectionAllowlistItemNotInnerList.md +12 -0
  21. package/front_end/models/issues_manager/descriptions/connectionAllowlistMoreThanOneList.md +7 -0
  22. package/front_end/models/issues_manager/descriptions/connectionAllowlistReportingEndpointNotToken.md +10 -0
  23. package/front_end/models/issues_manager/issues_manager.ts +2 -0
  24. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +7 -1
  25. package/front_end/panels/ai_assistance/components/ChatInput.ts +7 -3
  26. package/front_end/panels/application/preloading/PreloadingView.ts +8 -1
  27. package/front_end/panels/application/preloading/components/PreloadingDetailsReportView.ts +4 -1
  28. package/front_end/panels/application/preloading/components/PreloadingGrid.ts +2 -1
  29. package/front_end/panels/application/preloading/components/PreloadingString.ts +12 -3
  30. package/front_end/panels/application/preloading/helper/PreloadingForward.ts +14 -0
  31. package/front_end/panels/browser_debugger/CategorizedBreakpointsSidebarPane.ts +37 -3
  32. package/front_end/panels/changes/ChangesSidebar.ts +2 -6
  33. package/front_end/panels/console/ConsoleSidebar.ts +3 -11
  34. package/front_end/panels/lighthouse/LighthouseStartView.ts +3 -5
  35. package/front_end/panels/lighthouse/lighthouseStartView.css +6 -0
  36. package/front_end/panels/network/NetworkLogView.ts +6 -6
  37. package/front_end/panels/network/RequestInitiatorView.ts +19 -8
  38. package/front_end/panels/settings/AISettingsTab.ts +1 -5
  39. package/front_end/panels/settings/SettingsScreen.ts +0 -51
  40. package/front_end/panels/timeline/AnimationsTrackAppender.ts +4 -1
  41. package/front_end/panels/timeline/InteractionsTrackAppender.ts +1 -1
  42. package/front_end/panels/timeline/TimelineUIUtils.ts +13 -16
  43. package/front_end/third_party/chromium/README.chromium +1 -1
  44. package/front_end/ui/components/markdown_view/MarkdownLinksMap.ts +5 -1
  45. package/front_end/ui/legacy/Toolbar.ts +4 -4
  46. package/front_end/ui/legacy/Treeoutline.ts +4 -4
  47. package/front_end/ui/legacy/UIUtils.ts +9 -3
  48. package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +6 -11
  49. package/front_end/ui/legacy/components/utils/Linkifier.ts +4 -7
  50. package/package.json +1 -1
  51. package/front_end/models/issues_manager/descriptions/federatedAuthRequestClientMetadataHttpNotFound.md +0 -1
  52. package/front_end/models/issues_manager/descriptions/federatedAuthRequestClientMetadataInvalidResponse.md +0 -1
  53. package/front_end/models/issues_manager/descriptions/federatedAuthRequestClientMetadataNoResponse.md +0 -1
@@ -66,6 +66,11 @@ export abstract class RemoteObject {
66
66
  return matches ? parseInt(matches[1], 10) : 0;
67
67
  }
68
68
 
69
+ static isEmptyArray(object: RemoteObject|Protocol.Runtime.RemoteObject|Protocol.Runtime.ObjectPreview): boolean {
70
+ const matches = object.description?.match(descriptionLengthParenRegex);
71
+ return Boolean(matches?.[1] === '0');
72
+ }
73
+
69
74
  static unserializableDescription(object: unknown): string|null {
70
75
  if (typeof object === 'number') {
71
76
  const description = String(object);
@@ -582,7 +587,8 @@ export class RemoteObjectImpl extends RemoteObject {
582
587
 
583
588
  override isLinearMemoryInspectable(): boolean {
584
589
  return this.type === 'object' && this.subtype !== undefined &&
585
- ['webassemblymemory', 'typedarray', 'dataview', 'arraybuffer'].includes(this.subtype);
590
+ ['webassemblymemory', 'typedarray', 'dataview', 'arraybuffer'].includes(this.subtype) &&
591
+ !RemoteObject.isEmptyArray(this);
586
592
  }
587
593
  }
588
594
 
@@ -14,7 +14,11 @@
14
14
  }
15
15
  }
16
16
  </style>
17
- <meta http-equiv="Content-Security-Policy" content="object-src 'none'; script-src 'self' https://chrome-devtools-frontend.appspot.com">
17
+ <meta
18
+ http-equiv="Content-Security-Policy"
19
+ content="default-src 'self' devtools: data:; style-src 'self' 'unsafe-inline' devtools:; object-src 'none'; script-src
20
+ 'self' https://chrome-devtools-frontend.appspot.com; img-src 'self' data:; frame-src * data:; connect-src data:
21
+ https://chromeuxreport.googleapis.com 'self' devtools:;">
18
22
  <meta name="referrer" content="no-referrer">
19
23
  <script type="module" src="./entrypoints/%ENTRYPOINT_NAME%/%ENTRYPOINT_NAME%.js"></script>
20
24
  <link href="./application_tokens.css" rel="stylesheet">
@@ -254,6 +254,10 @@ class GreenDevFloaty {
254
254
  return messages;
255
255
  }
256
256
 
257
+ #formatError(errorMessage: string): string {
258
+ return `Error: '${errorMessage}' - Protip: to use AI features you need to be signed in.`;
259
+ }
260
+
257
261
  runConversation = async(): Promise<void> => {
258
262
  if (!this.#textField || !this.#node) {
259
263
  return;
@@ -276,7 +280,7 @@ class GreenDevFloaty {
276
280
  nodeDescription: document.querySelector('.green-dev-floaty-dialog-node-description')?.textContent,
277
281
  });
278
282
 
279
- const {content: aiContent} = this.#addMessageInternal('Thinking...', false);
283
+ const aiContent = this.#addMessageInternal('Thinking...', false);
280
284
  this.#syncChannel.postMessage({
281
285
  type: 'new-message',
282
286
  text: 'Thinking...',
@@ -297,9 +301,9 @@ class GreenDevFloaty {
297
301
  {type: 'update-last-message', text: result.text, sessionId: this.#backendNodeId});
298
302
  break;
299
303
  case ResponseType.ERROR:
300
- aiContent.textContent = `Error: ${result.error}`;
304
+ aiContent.textContent = this.#formatError(result.error);
301
305
  this.#syncChannel.postMessage(
302
- {type: 'update-last-message', text: `Error: ${result.error}`, sessionId: this.#backendNodeId});
306
+ {type: 'update-last-message', text: this.#formatError(result.error), sessionId: this.#backendNodeId});
303
307
  break;
304
308
  case ResponseType.SIDE_EFFECT:
305
309
  result.confirm(true);
@@ -316,7 +320,7 @@ class GreenDevFloaty {
316
320
  }
317
321
  };
318
322
 
319
- #addMessageInternal(text: string, isUser: boolean): {content: HTMLDivElement, details?: HTMLDivElement} {
323
+ #addMessageInternal(text: string, isUser: boolean): HTMLDivElement {
320
324
  const messageElement = document.createElement('div');
321
325
  messageElement.className = `message ${isUser ? 'user-message' : 'ai-message'}`;
322
326
 
@@ -325,30 +329,11 @@ class GreenDevFloaty {
325
329
  content.textContent = text;
326
330
  messageElement.appendChild(content);
327
331
 
328
- let details: HTMLDivElement|undefined;
329
- if (!isUser) {
330
- details = document.createElement('div');
331
- details.className = 'message-details';
332
- details.style.display = 'none';
333
- messageElement.appendChild(details);
334
-
335
- const toggle = document.createElement('div');
336
- toggle.className = 'message-details-toggle';
337
- toggle.textContent = 'Show details';
338
- toggle.onclick = () => {
339
- if (details) {
340
- const isHidden = details.style.display === 'none';
341
- details.style.display = isHidden ? 'block' : 'none';
342
- toggle.textContent = isHidden ? 'Hide details' : 'Show details';
343
- }
344
- };
345
- messageElement.appendChild(toggle);
346
- }
347
332
  if (this.#chatContainer) {
348
333
  this.#chatContainer.appendChild(messageElement);
349
334
  this.#chatContainer.scrollTop = this.#chatContainer.scrollHeight;
350
335
  }
351
- return {content, details};
336
+ return content;
352
337
  }
353
338
  }
354
339
 
@@ -251,7 +251,7 @@ html, body {
251
251
  }
252
252
 
253
253
  .green-dev-floaty-disclaimer {
254
- font-size: 16px;
254
+ font-size: 15px;
255
255
  color: #666;
256
256
  text-align: center;
257
257
  margin-top: 8px;
@@ -186,7 +186,7 @@ class GreenDevFloaty {
186
186
  aiContent.textContent = result.text;
187
187
  break;
188
188
  case ResponseType.ERROR:
189
- aiContent.textContent = `Error: ${result.error}`;
189
+ aiContent.textContent = `Error: '${result.error}' - Protip: to use AI features you need to be signed in.`;
190
190
  break;
191
191
  case ResponseType.THOUGHT:
192
192
  if (aiDetails) {
@@ -84,7 +84,7 @@ inspectorBackend.registerEnum("Audits.UnencodedDigestError", {MalformedDictionar
84
84
  inspectorBackend.registerEnum("Audits.ConnectionAllowlistError", {InvalidHeader: "InvalidHeader", MoreThanOneList: "MoreThanOneList", ItemNotInnerList: "ItemNotInnerList", InvalidAllowlistItemType: "InvalidAllowlistItemType", ReportingEndpointNotToken: "ReportingEndpointNotToken", InvalidUrlPattern: "InvalidUrlPattern"});
85
85
  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", AutofillAndManualTextPolicyControlledFeaturesInfo: "AutofillAndManualTextPolicyControlledFeaturesInfo", AutofillPolicyControlledFeatureInfo: "AutofillPolicyControlledFeatureInfo", ManualTextPolicyControlledFeatureInfo: "ManualTextPolicyControlledFeatureInfo"});
86
86
  inspectorBackend.registerEnum("Audits.ClientHintIssueReason", {MetaTagAllowListInvalidOrigin: "MetaTagAllowListInvalidOrigin", MetaTagModifiedHTML: "MetaTagModifiedHTML"});
87
- 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
+ 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", 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", NotSignedInWithIdp: "NotSignedInWithIdp", MissingTransientUserActivation: "MissingTransientUserActivation", ReplacedByActiveMode: "ReplacedByActiveMode", RelyingPartyOriginIsOpaque: "RelyingPartyOriginIsOpaque", TypeNotMatching: "TypeNotMatching", UiDismissedNoEmbargo: "UiDismissedNoEmbargo", CorsError: "CorsError", SuppressedBySegmentationPlatform: "SuppressedBySegmentationPlatform"});
88
88
  inspectorBackend.registerEnum("Audits.FederatedAuthUserInfoRequestIssueReason", {NotSameOrigin: "NotSameOrigin", NotIframe: "NotIframe", NotPotentiallyTrustworthy: "NotPotentiallyTrustworthy", NoAPIPermission: "NoApiPermission", NotSignedInWithIdp: "NotSignedInWithIdp", NoAccountSharingPermission: "NoAccountSharingPermission", InvalidConfigOrWellKnown: "InvalidConfigOrWellKnown", InvalidAccountsResponse: "InvalidAccountsResponse", NoReturningUserFromFetchedAccounts: "NoReturningUserFromFetchedAccounts"});
89
89
  inspectorBackend.registerEnum("Audits.PartitioningBlobURLInfo", {BlockedCrossPartitionFetching: "BlockedCrossPartitionFetching", EnforceNoopenerForNavigation: "EnforceNoopenerForNavigation"});
90
90
  inspectorBackend.registerEnum("Audits.ElementAccessibilityIssueReason", {DisallowedSelectChild: "DisallowedSelectChild", DisallowedOptGroupChild: "DisallowedOptGroupChild", NonPhrasingContentOptionChild: "NonPhrasingContentOptionChild", InteractiveContentOptionChild: "InteractiveContentOptionChild", InteractiveContentLegendChild: "InteractiveContentLegendChild", InteractiveContentSummaryDescendant: "InteractiveContentSummaryDescendant"});
@@ -4552,6 +4552,7 @@ export const generatedProperties = [
4552
4552
  "uppercase",
4553
4553
  "lowercase",
4554
4554
  "full-width",
4555
+ "full-size-kana",
4555
4556
  "none",
4556
4557
  "math-auto"
4557
4558
  ],
@@ -7048,6 +7049,7 @@ export const generatedPropertyValues = {
7048
7049
  "uppercase",
7049
7050
  "lowercase",
7050
7051
  "full-width",
7052
+ "full-size-kana",
7051
7053
  "none",
7052
7054
  "math-auto"
7053
7055
  ]
@@ -1292,10 +1292,6 @@ export namespace Audits {
1292
1292
  ConfigNoResponse = 'ConfigNoResponse',
1293
1293
  ConfigInvalidResponse = 'ConfigInvalidResponse',
1294
1294
  ConfigInvalidContentType = 'ConfigInvalidContentType',
1295
- ClientMetadataHttpNotFound = 'ClientMetadataHttpNotFound',
1296
- ClientMetadataNoResponse = 'ClientMetadataNoResponse',
1297
- ClientMetadataInvalidResponse = 'ClientMetadataInvalidResponse',
1298
- ClientMetadataInvalidContentType = 'ClientMetadataInvalidContentType',
1299
1295
  IdpNotPotentiallyTrustworthy = 'IdpNotPotentiallyTrustworthy',
1300
1296
  DisabledInSettings = 'DisabledInSettings',
1301
1297
  DisabledInFlags = 'DisabledInFlags',
@@ -1317,11 +1313,9 @@ export namespace Audits {
1317
1313
  Canceled = 'Canceled',
1318
1314
  RpPageNotVisible = 'RpPageNotVisible',
1319
1315
  SilentMediationFailure = 'SilentMediationFailure',
1320
- ThirdPartyCookiesBlocked = 'ThirdPartyCookiesBlocked',
1321
1316
  NotSignedInWithIdp = 'NotSignedInWithIdp',
1322
1317
  MissingTransientUserActivation = 'MissingTransientUserActivation',
1323
1318
  ReplacedByActiveMode = 'ReplacedByActiveMode',
1324
- InvalidFieldsSpecified = 'InvalidFieldsSpecified',
1325
1319
  RelyingPartyOriginIsOpaque = 'RelyingPartyOriginIsOpaque',
1326
1320
  TypeNotMatching = 'TypeNotMatching',
1327
1321
  UiDismissedNoEmbargo = 'UiDismissedNoEmbargo',
@@ -31,7 +31,7 @@ Content:
31
31
  "function_declarations": [
32
32
  {
33
33
  "name": "listNetworkRequests",
34
- "description": "Gives a list of network requests including URL, status code, and duration in ms",
34
+ "description": "Gives a list of network requests including URL, status code, and duration in ms.",
35
35
  "parameters": {
36
36
  "type": 6,
37
37
  "description": "",
@@ -42,7 +42,7 @@ Content:
42
42
  },
43
43
  {
44
44
  "name": "selectNetworkRequest",
45
- "description": "From the list of selected request select one to debug",
45
+ "description": "Selects a specific network request to further provide information about. Use this when asked about network requests issues.",
46
46
  "parameters": {
47
47
  "type": 6,
48
48
  "description": "",
@@ -72,7 +72,7 @@ Content:
72
72
  },
73
73
  {
74
74
  "name": "selectSourceFile",
75
- "description": "Returns a list of all files in the project.",
75
+ "description": "Selects a source file. Use this when asked about files on the page.",
76
76
  "parameters": {
77
77
  "type": 6,
78
78
  "description": "",
@@ -83,7 +83,7 @@ Content:
83
83
  "properties": {
84
84
  "name": {
85
85
  "type": 1,
86
- "description": "The name of the file",
86
+ "description": "The name of the file you want to select.",
87
87
  "nullable": false
88
88
  }
89
89
  }
@@ -91,7 +91,7 @@ Content:
91
91
  },
92
92
  {
93
93
  "name": "performanceRecordAndReload",
94
- "description": "Start a new performance recording and reload the page.",
94
+ "description": "Records a new performance trace, to help debug performance issue.",
95
95
  "parameters": {
96
96
  "type": 6,
97
97
  "description": "",
@@ -102,7 +102,7 @@ Content:
102
102
  },
103
103
  {
104
104
  "name": "inspectDom",
105
- "description": "Prompts user to select a DOM element from the page.",
105
+ "description": "Prompts user to select a DOM element from the page. Use this when you don't know which element is selected.",
106
106
  "parameters": {
107
107
  "type": 6,
108
108
  "description": "",
@@ -32,7 +32,7 @@ You aim to help developers of all levels, prioritizing teaching web concepts as
32
32
 
33
33
  # Considerations
34
34
  * Determine what the question the domain of the question is - styling, network, sources, performance or other part of DevTools.
35
- * When possible proactively try to gather additional data and select context that they user may find relevant to the question they are asking utilizing the function calls available to you.
35
+ * Proactively try to gather additional data. If a select specific data can be selected, select one.
36
36
  * Avoid making assumptions without sufficient evidence, and always seek further clarification if needed.
37
37
  * Always explore multiple possible explanations for the observed behavior before settling on a conclusion.
38
38
  * When presenting solutions, clearly distinguish between the primary cause and contributing factors.
@@ -85,7 +85,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
85
85
  this.#onInspectElement = opts.onInspectElement;
86
86
 
87
87
  this.declareFunction<Record<string, never>>('listNetworkRequests', {
88
- description: `Gives a list of network requests including URL, status code, and duration in ms`,
88
+ description: `Gives a list of network requests including URL, status code, and duration in ms.`,
89
89
  parameters: {
90
90
  type: Host.AidaClient.ParametersTypes.OBJECT,
91
91
  description: '',
@@ -116,6 +116,12 @@ export class ContextSelectionAgent extends AiAgent<never> {
116
116
  });
117
117
  }
118
118
 
119
+ if (requests.length === 0) {
120
+ return {
121
+ error: 'No requests recorded by DevTools',
122
+ };
123
+ }
124
+
119
125
  return {
120
126
  result: requests,
121
127
  };
@@ -123,7 +129,8 @@ export class ContextSelectionAgent extends AiAgent<never> {
123
129
  });
124
130
 
125
131
  this.declareFunction<{url: string}>('selectNetworkRequest', {
126
- description: `From the list of selected request select one to debug`,
132
+ description:
133
+ `Selects a specific network request to further provide information about. Use this when asked about network requests issues.`,
127
134
  parameters: {
128
135
  type: Host.AidaClient.ParametersTypes.OBJECT,
129
136
  description: '',
@@ -191,7 +198,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
191
198
  });
192
199
 
193
200
  this.declareFunction<{name: string}>('selectSourceFile', {
194
- description: `Returns a list of all files in the project.`,
201
+ description: `Selects a source file. Use this when asked about files on the page.`,
195
202
  parameters: {
196
203
  type: Host.AidaClient.ParametersTypes.OBJECT,
197
204
  description: '',
@@ -200,14 +207,14 @@ export class ContextSelectionAgent extends AiAgent<never> {
200
207
  properties: {
201
208
  name: {
202
209
  type: Host.AidaClient.ParametersTypes.STRING,
203
- description: 'The name of the file',
210
+ description: 'The name of the file you want to select.',
204
211
  nullable: false,
205
212
  },
206
213
  },
207
214
  },
208
215
  displayInfoFromArgs: args => {
209
216
  return {
210
- title: lockedString('Getting source file'),
217
+ title: lockedString('Getting source file'),
211
218
  action: `selectSourceFile(${args.name})`,
212
219
  };
213
220
  },
@@ -225,7 +232,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
225
232
  });
226
233
 
227
234
  this.declareFunction('performanceRecordAndReload', {
228
- description: 'Start a new performance recording and reload the page.',
235
+ description: 'Records a new performance trace, to help debug performance issue.',
229
236
  parameters: {
230
237
  type: Host.AidaClient.ParametersTypes.OBJECT,
231
238
  description: '',
@@ -254,7 +261,8 @@ export class ContextSelectionAgent extends AiAgent<never> {
254
261
  });
255
262
 
256
263
  this.declareFunction<Record<string, never>>('inspectDom', {
257
- description: `Prompts user to select a DOM element from the page.`,
264
+ description:
265
+ `Prompts user to select a DOM element from the page. Use this when you don't know which element is selected.`,
258
266
  parameters: {
259
267
  type: Host.AidaClient.ParametersTypes.OBJECT,
260
268
  description: '',
@@ -264,7 +272,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
264
272
  },
265
273
  displayInfoFromArgs: () => {
266
274
  return {
267
- title: lockedString('Please select an element on the page...'),
275
+ title: lockedString('Please select an element on the page'),
268
276
  action: 'selectElement()',
269
277
  };
270
278
  },
@@ -80,10 +80,6 @@ const UIStringsNotTranslate = {
80
80
  * @description Title text for request timing details.
81
81
  */
82
82
  timing: 'Timing',
83
- /**
84
- * @description Prefix text for response status.
85
- */
86
- responseStatus: 'Response Status',
87
83
  /**
88
84
  * @description Title text for request initiator chain.
89
85
  */
@@ -178,8 +174,8 @@ async function createContextDetailsForNetworkAgent(
178
174
 
179
175
  const responseContextDetail: ContextDetail = {
180
176
  title: lockedString(UIStringsNotTranslate.response),
181
- text: lockedString(UIStringsNotTranslate.responseStatus) + ': ' + request.statusCode + ' ' + request.statusText +
182
- `\n\n${formatter.formatResponseHeaders()}` + responseBodyString,
177
+ text: formatter.formatResponseHeaders() + responseBodyString +
178
+ `\n\n${formatter.formatStatus()}${formatter.formatFailureReasons()}`,
183
179
  };
184
180
  const timingContextDetail: ContextDetail = {
185
181
  title: lockedString(UIStringsNotTranslate.timing),
@@ -3,6 +3,7 @@
3
3
  // found in the LICENSE file.
4
4
 
5
5
  import type * as SDK from '../../../core/sdk/sdk.js';
6
+ import type * as Protocol from '../../../generated/protocol.js';
6
7
  import * as Annotations from '../../annotations/annotations.js';
7
8
  import * as Logs from '../../logs/logs.js';
8
9
  import * as NetworkTimeCalculator from '../../network_time_calculator/network_time_calculator.js';
@@ -75,6 +76,51 @@ export class NetworkRequestFormatter {
75
76
  return '<redacted cross-origin initiator URL>';
76
77
  }
77
78
 
79
+ static formatStatus(status: {
80
+ statusCode: number,
81
+ statusText: string,
82
+ failed: boolean,
83
+ canceled: boolean,
84
+ preserved: boolean,
85
+ finished: boolean,
86
+ }): string {
87
+ let responseStatus = '';
88
+ if (status.statusCode) {
89
+ responseStatus = `Response status: ${status.statusCode} ${status.statusText}\n`;
90
+ }
91
+ const flags = [];
92
+ flags.push(status.finished ? 'finished' : 'pending');
93
+ if (status.failed) {
94
+ flags.push('failed');
95
+ }
96
+ if (status.canceled) {
97
+ flags.push('canceled');
98
+ }
99
+ if (status.preserved) {
100
+ flags.push('preserved');
101
+ }
102
+ const requestStatus = flags.length > 0 ? `Network request status: ${flags.join(', ')}\n` : '';
103
+ return `${responseStatus}${requestStatus}`;
104
+ }
105
+
106
+ static formatFailureReasons(reasons: {
107
+ blockedReason?: Protocol.Network.BlockedReason,
108
+ corsErrorStatus?: Protocol.Network.CorsErrorStatus,
109
+ localizedFailDescription?: string|null,
110
+ }): string {
111
+ const lines = [];
112
+ if (reasons.blockedReason) {
113
+ lines.push(`Blocked reason: ${reasons.blockedReason}`);
114
+ }
115
+ if (reasons.corsErrorStatus) {
116
+ lines.push(`CORS error: ${reasons.corsErrorStatus.corsError} ${reasons.corsErrorStatus.failedParameter}`);
117
+ }
118
+ if (reasons.localizedFailDescription) {
119
+ lines.push(`Fail description: ${reasons.localizedFailDescription}`);
120
+ }
121
+ return lines.length > 0 ? `${lines.join('\n')}\n` : '';
122
+ }
123
+
78
124
  constructor(
79
125
  request: SDK.NetworkRequest.NetworkRequest, calculator: NetworkTimeCalculator.NetworkTransferTimeCalculator) {
80
126
  this.#request = request;
@@ -111,13 +157,31 @@ ${this.formatRequestHeaders()}
111
157
 
112
158
  ${this.formatResponseHeaders()}${responseBody}
113
159
 
114
- Response status: ${this.#request.statusCode} ${this.#request.statusText}
115
-
160
+ ${this.formatStatus()}${this.formatFailureReasons()}
116
161
  Request timing:\n${this.formatNetworkRequestTiming()}
117
162
 
118
163
  Request initiator chain:\n${this.formatRequestInitiatorChain()}`;
119
164
  }
120
165
 
166
+ formatStatus(): string {
167
+ return NetworkRequestFormatter.formatStatus({
168
+ statusCode: this.#request.statusCode,
169
+ statusText: this.#request.statusText,
170
+ failed: this.#request.failed,
171
+ canceled: this.#request.canceled,
172
+ preserved: this.#request.preserved,
173
+ finished: this.#request.finished,
174
+ });
175
+ }
176
+
177
+ formatFailureReasons(): string {
178
+ return NetworkRequestFormatter.formatFailureReasons({
179
+ blockedReason: this.#request.blockedReason(),
180
+ corsErrorStatus: this.#request.corsErrorStatus(),
181
+ localizedFailDescription: this.#request.localizedFailDescription,
182
+ });
183
+ }
184
+
121
185
  /**
122
186
  * Note: nothing here should include information from origins other than
123
187
  * the request's origin.
@@ -9,8 +9,6 @@ let instance: Prototypes|null = null;
9
9
 
10
10
  export interface GreenDevSettings {
11
11
  inDevToolsFloaty: Common.Settings.Setting<boolean>;
12
- inlineWidgets: Common.Settings.Setting<boolean>;
13
- artifactViewer: Common.Settings.Setting<boolean>;
14
12
  aiAnnotations: Common.Settings.Setting<boolean>;
15
13
  copyToGemini: Common.Settings.Setting<boolean>;
16
14
  }
@@ -41,21 +39,14 @@ export class Prototypes {
41
39
  const inDevToolsFloaty =
42
40
  settings.createSetting('greendev-in-devtools-floaty-enabled', false, Common.Settings.SettingStorageType.LOCAL);
43
41
 
44
- const inlineWidgets =
45
- settings.createSetting('greendev-inline-widgets-enabled', false, Common.Settings.SettingStorageType.LOCAL);
46
-
47
42
  const aiAnnotations = settings.createSetting(
48
43
  'greendev-ai-annotations-enabled',
49
44
  false,
50
45
  Common.Settings.SettingStorageType.LOCAL,
51
46
  );
52
-
53
- const artifactViewer =
54
- settings.createSetting('greendev-artifact-viewer-enabled', false, Common.Settings.SettingStorageType.LOCAL);
55
-
56
47
  const copyToGemini =
57
48
  settings.createSetting('greendev-copy-to-gemini-enabled', false, Common.Settings.SettingStorageType.LOCAL);
58
49
 
59
- return {inDevToolsFloaty, inlineWidgets, aiAnnotations, artifactViewer, copyToGemini};
50
+ return {inDevToolsFloaty, aiAnnotations, copyToGemini};
60
51
  }
61
52
  }
@@ -0,0 +1,75 @@
1
+ // Copyright 2026 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 i18n from '../../core/i18n/i18n.js';
6
+ import type * as SDK from '../../core/sdk/sdk.js';
7
+ import * as Protocol from '../../generated/protocol.js';
8
+
9
+ import {Issue, IssueCategory, IssueKind} from './Issue.js';
10
+ import {
11
+ type LazyMarkdownIssueDescription,
12
+ type MarkdownIssueDescription,
13
+ resolveLazyDescription,
14
+ } from './MarkdownIssueDescription.js';
15
+
16
+ const UIStrings = {
17
+ /**
18
+ *@description Title for Connection-Allowlist specification url
19
+ */
20
+ connectionAllowlistHeader: 'Connection-Allowlist specification',
21
+ } as const;
22
+ const str_ = i18n.i18n.registerUIStrings('models/issues_manager/ConnectionAllowlistIssue.ts', UIStrings);
23
+ const i18nLazyString = i18n.i18n.getLazilyComputedLocalizedString.bind(undefined, str_);
24
+
25
+ export class ConnectionAllowlistIssue extends Issue<Protocol.Audits.ConnectionAllowlistIssueDetails> {
26
+ constructor(
27
+ issueDetails: Protocol.Audits.ConnectionAllowlistIssueDetails, issuesModel: SDK.IssuesModel.IssuesModel|null) {
28
+ super(
29
+ {
30
+ code: `${Protocol.Audits.InspectorIssueCode.ConnectionAllowlistIssue}::${issueDetails.error}`,
31
+ umaCode: `${Protocol.Audits.InspectorIssueCode.ConnectionAllowlistIssue}::${issueDetails.error}`,
32
+ },
33
+ issueDetails, issuesModel);
34
+ }
35
+
36
+ override primaryKey(): string {
37
+ return JSON.stringify(this.details());
38
+ }
39
+
40
+ override getDescription(): MarkdownIssueDescription|null {
41
+ const description: LazyMarkdownIssueDescription = {
42
+ file: `connectionAllowlist${this.details().error}.md`,
43
+ links: [
44
+ {
45
+ link: 'https://wicg.github.io/private-network-access/#connection-allowlist',
46
+ linkTitle: i18nLazyString(UIStrings.connectionAllowlistHeader),
47
+ },
48
+ ],
49
+ };
50
+ return resolveLazyDescription(description);
51
+ }
52
+
53
+ override getCategory(): IssueCategory {
54
+ return IssueCategory.OTHER;
55
+ }
56
+
57
+ override getKind(): IssueKind {
58
+ return IssueKind.PAGE_ERROR;
59
+ }
60
+
61
+ override requests(): Iterable<Protocol.Audits.AffectedRequest> {
62
+ return this.details().request ? [this.details().request] : [];
63
+ }
64
+
65
+ static fromInspectorIssue(
66
+ issuesModel: SDK.IssuesModel.IssuesModel|null,
67
+ inspectorIssue: Protocol.Audits.InspectorIssue): ConnectionAllowlistIssue[] {
68
+ const details = inspectorIssue.details.connectionAllowlistIssueDetails;
69
+ if (!details) {
70
+ console.warn('Connection-Allowlist issue without details received.');
71
+ return [];
72
+ }
73
+ return [new ConnectionAllowlistIssue(details, issuesModel)];
74
+ }
75
+ }
@@ -109,36 +109,6 @@ const issueDescriptions = new Map<Protocol.Audits.FederatedAuthRequestIssueReaso
109
109
  }],
110
110
  },
111
111
  ],
112
- [
113
- Protocol.Audits.FederatedAuthRequestIssueReason.ClientMetadataHttpNotFound,
114
- {
115
- file: 'federatedAuthRequestClientMetadataHttpNotFound.md',
116
- links: [{
117
- link: 'https://fedidcg.github.io/FedCM/',
118
- linkTitle: i18nLazyString(UIStrings.fedCm),
119
- }],
120
- },
121
- ],
122
- [
123
- Protocol.Audits.FederatedAuthRequestIssueReason.ClientMetadataNoResponse,
124
- {
125
- file: 'federatedAuthRequestClientMetadataNoResponse.md',
126
- links: [{
127
- link: 'https://fedidcg.github.io/FedCM/',
128
- linkTitle: i18nLazyString(UIStrings.fedCm),
129
- }],
130
- },
131
- ],
132
- [
133
- Protocol.Audits.FederatedAuthRequestIssueReason.ClientMetadataInvalidResponse,
134
- {
135
- file: 'federatedAuthRequestClientMetadataInvalidResponse.md',
136
- links: [{
137
- link: 'https://fedidcg.github.io/FedCM/',
138
- linkTitle: i18nLazyString(UIStrings.fedCm),
139
- }],
140
- },
141
- ],
142
112
  [
143
113
  Protocol.Audits.FederatedAuthRequestIssueReason.ErrorFetchingSignin,
144
114
  {
@@ -9,6 +9,7 @@ import * as Protocol from '../../generated/protocol.js';
9
9
  import {AttributionReportingIssue} from './AttributionReportingIssue.js';
10
10
  import {BounceTrackingIssue} from './BounceTrackingIssue.js';
11
11
  import {ClientHintIssue} from './ClientHintIssue.js';
12
+ import {ConnectionAllowlistIssue} from './ConnectionAllowlistIssue.js';
12
13
  import {ContentSecurityPolicyIssue} from './ContentSecurityPolicyIssue.js';
13
14
  import {CookieDeprecationMetadataIssue} from './CookieDeprecationMetadataIssue.js';
14
15
  import {CookieIssue} from './CookieIssue.js';
@@ -144,6 +145,10 @@ const issueCodeHandlers = new Map<
144
145
  Protocol.Audits.InspectorIssueCode.UnencodedDigestIssue,
145
146
  UnencodedDigestIssue.fromInspectorIssue,
146
147
  ],
148
+ [
149
+ Protocol.Audits.InspectorIssueCode.ConnectionAllowlistIssue,
150
+ ConnectionAllowlistIssue.fromInspectorIssue,
151
+ ],
147
152
  [
148
153
  Protocol.Audits.InspectorIssueCode.PermissionElementIssue,
149
154
  PermissionElementIssue.fromInspectorIssue,
@@ -0,0 +1,12 @@
1
+ # An item in the `Connection-Allowlist` header is invalid.
2
+
3
+ Each item in the `Connection-Allowlist`'s header's [Inner List](sfInnerList)
4
+ must be a [String](sfString) representing a [URL Pattern](urlPatternSpec), or
5
+ the [Token](sfToken) `response-origin`.
6
+
7
+ For example, the following header allows connections to (only)
8
+ `https://example.com/` and the origin from which the response was delivered:
9
+
10
+ ```
11
+ Connection-Allowlist: ("https://example.com" response-origin)
12
+ ```
@@ -0,0 +1,12 @@
1
+ # The `Connection-Allowlist` header is not formatted as a Structured Field List.
2
+
3
+ Responses' `Connection-Allowlist` header should be formatted as a [List](sfList)
4
+ containing a single [Inner List](sfInnerList) that declares the allowed set of
5
+ [URL Patterns](urlPatternSpec) for a given context.
6
+
7
+ For example, the following header allows connections to (only)
8
+ `https://example.com/`:
9
+
10
+ ```
11
+ Connection-Allowlist: ("https://example.com")
12
+ ```
@@ -0,0 +1,8 @@
1
+ # An item in the `Connection-Allowlist` header is not a valid URL pattern.
2
+
3
+ Each item in the `Connection-Allowlist` header must be a valid
4
+ [URL Pattern](urlPatternSpec) that can be used to match against the request's
5
+ origin.
6
+
7
+ Note that our current implementation does not allow regular expressions to be
8
+ used as part of the pattern.