chrome-devtools-frontend 1.0.1608453 → 1.0.1608868

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.
@@ -240,7 +240,7 @@ export class AccessibilityAgent extends AiAgent<LHModel.ReporterTypes.ReportJSON
240
240
  },
241
241
  displayInfoFromArgs: params => {
242
242
  return {
243
- title: i18n.i18n.lockedString('Running accessibility audits'),
243
+ title: i18n.i18n.lockedString('Running accessibility audits'),
244
244
  thought: params.explanation,
245
245
  action: 'runAccessibilityAudits()'
246
246
  };
@@ -282,7 +282,7 @@ export class AccessibilityAgent extends AiAgent<LHModel.ReporterTypes.ReportJSON
282
282
  },
283
283
  displayInfoFromArgs: params => {
284
284
  return {
285
- title: i18n.i18n.lockedString(`Getting Lighthouse audits for ${params.categoryId}…`),
285
+ title: i18n.i18n.lockedString(`Getting Lighthouse audits for ${params.categoryId}`),
286
286
  action: `getLighthouseAudits('${params.categoryId}')`
287
287
  };
288
288
  },
@@ -407,7 +407,7 @@ export class BreakpointDebuggerAgent extends AiAgent<Workspace.UISourceCode.UILo
407
407
  },
408
408
  displayInfoFromArgs: () => {
409
409
  return {
410
- title: 'Waiting for user action...',
410
+ title: 'Waiting for user action',
411
411
  thought: 'I am waiting for you to trigger a breakpoint in the application.',
412
412
  };
413
413
  },
@@ -110,7 +110,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
110
110
  },
111
111
  displayInfoFromArgs: () => {
112
112
  return {
113
- title: lockedString('Listing network requests'),
113
+ title: lockedString('Listing network requests'),
114
114
  action: 'listNetworkRequest()',
115
115
  };
116
116
  },
@@ -175,7 +175,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
175
175
  },
176
176
  displayInfoFromArgs: args => {
177
177
  return {
178
- title: lockedString('Getting network request'),
178
+ title: lockedString('Getting network request'),
179
179
  action: `selectNetworkRequest(${args.id})`,
180
180
  };
181
181
  },
@@ -215,7 +215,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
215
215
  },
216
216
  displayInfoFromArgs: () => {
217
217
  return {
218
- title: lockedString('Listing source requests'),
218
+ title: lockedString('Listing source requests'),
219
219
  action: 'listSourceFiles()',
220
220
  };
221
221
  },
@@ -252,7 +252,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
252
252
  },
253
253
  displayInfoFromArgs: args => {
254
254
  return {
255
- title: lockedString('Getting source file'),
255
+ title: lockedString('Getting source file'),
256
256
  action: `selectSourceFile(${args.id})`,
257
257
  };
258
258
  },
@@ -285,7 +285,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
285
285
  },
286
286
  displayInfoFromArgs: () => {
287
287
  return {
288
- title: 'Recording a performance trace',
288
+ title: 'Recording a performance trace',
289
289
  action: 'performanceRecordAndReload()',
290
290
  };
291
291
  },
@@ -317,7 +317,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
317
317
  },
318
318
  displayInfoFromArgs: () => {
319
319
  return {
320
- title: 'Auditing your page with Lighthouse',
320
+ title: 'Auditing your page with Lighthouse',
321
321
  action: 'runLighthouseAudits()',
322
322
  };
323
323
  },
@@ -11,6 +11,7 @@ const preamble = `### Role
11
11
  You are a Conversation Summarizer. Your task is to take a transcript of a conversation between a user and a DevTools AI agent and produce a succinct, actionable Markdown summary. This summary will be used to help apply fixes in an IDE, so it must capture all relevant technical details, findings, and proposed code changes without any conversational fluff.
12
12
 
13
13
  ### Critical Constraints
14
+ - **Strict Groundedness:** Only summarize information explicitly present in the provided transcript. Do not assume, hallucinate, or infer actions (like accessibility audits, performance tests, or network analysis) unless they are clearly documented in the conversation history. If a topic was not discussed, do not include it in the summary.
14
15
  - **Persona:** Do not mention that you are an AI or refer to yourself in the third person.
15
16
  - **Domain Scope:** Do not provide answers on non-web-development topics (e.g., legal, financial, medical, or personal advice).
16
17
  - **Sensitive Topics:** If the conversation history touches on sensitive topics (religion, race, politics, sexuality, gender, etc.), respond only with: "My expertise is limited to summarizing DevTools AI conversations. I cannot provide information on that topic."
@@ -23,7 +24,7 @@ You are a Conversation Summarizer. Your task is to take a transcript of a conver
23
24
 
24
25
  ### Objectives
25
26
  1. **Identify Intent:** Define the core technical goal of the session.
26
- 2. **Value-Only Diagnostics:** List only the technical data points and findings discovered during the conversation. Omit steps that didn't yield a result.
27
+ 2. **Value-Only Diagnostics:** List only the technical data points and findings discovered during the conversation. Omit steps that didn't yield a result and NEVER include information that wasn't explicitly mentioned in the conversation.
27
28
  3. **Summarize Code Changes:** When code is executed or suggested in the logs, summarize the **purpose** and the **result**. Include specific code snippets if they are a specific fix for the user to implement.
28
29
  4. **Actionable Recommendations:** Provide specific code/strategy fixes based on the findings as guidance for the user's source code.
29
30
 
@@ -41,11 +41,11 @@ const UIStringsNotTranslated = {
41
41
  /**
42
42
  * @description Shown when the agent is investigating network activity
43
43
  */
44
- networkActivitySummary: 'Investigating network activity',
44
+ networkActivitySummary: 'Investigating network activity',
45
45
  /**
46
46
  * @description Shown when the agent is investigating main thread activity
47
47
  */
48
- mainThreadActivity: 'Investigating main thread activity',
48
+ mainThreadActivity: 'Investigating main thread activity',
49
49
  } as const;
50
50
  const lockedString = i18n.i18n.lockedString;
51
51
 
@@ -805,7 +805,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
805
805
  },
806
806
  displayInfoFromArgs: params => {
807
807
  return {
808
- title: lockedString(`Investigating insight ${params.insightName}…`),
808
+ title: lockedString(`Investigating insight ${params.insightName}`),
809
809
  action: `getInsightDetails('${params.insightSetId}', '${params.insightName}')`
810
810
  };
811
811
  },
@@ -903,7 +903,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
903
903
  required: ['eventKey']
904
904
  },
905
905
  displayInfoFromArgs: params => {
906
- return {title: lockedString('Looking at trace event'), action: `getEventByKey('${params.eventKey}')`};
906
+ return {title: lockedString('Looking at trace event'), action: `getEventByKey('${params.eventKey}')`};
907
907
  },
908
908
  handler: async params => {
909
909
  debugLog('Function call: getEventByKey', params);
@@ -1093,7 +1093,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
1093
1093
  required: ['eventKey']
1094
1094
  },
1095
1095
  displayInfoFromArgs: args => {
1096
- return {title: lockedString('Looking at call tree'), action: `getDetailedCallTree('${args.eventKey}')`};
1096
+ return {title: lockedString('Looking at call tree'), action: `getDetailedCallTree('${args.eventKey}')`};
1097
1097
  },
1098
1098
  handler: async args => {
1099
1099
  debugLog('Function call: getDetailedCallTree');
@@ -1213,7 +1213,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
1213
1213
  },
1214
1214
  displayInfoFromArgs: args => {
1215
1215
  return {
1216
- title: lockedString('Looking up function code'),
1216
+ title: lockedString('Looking up function code'),
1217
1217
  action: `getFunctionCode('${args.scriptUrl}', ${args.line}, ${args.column})`
1218
1218
  };
1219
1219
  },
@@ -1271,7 +1271,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
1271
1271
  required: ['url']
1272
1272
  },
1273
1273
  displayInfoFromArgs: args => {
1274
- return {title: lockedString('Looking at resource content'), action: `getResourceContent('${args.url}')`};
1274
+ return {title: lockedString('Looking at resource content'), action: `getResourceContent('${args.url}')`};
1275
1275
  },
1276
1276
  handler: async args => {
1277
1277
  debugLog('Function call: getResourceContent');
@@ -1326,7 +1326,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
1326
1326
  required: ['eventKey']
1327
1327
  },
1328
1328
  displayInfoFromArgs: params => {
1329
- return {title: lockedString('Selecting event'), action: `selectEventByKey('${params.eventKey}')`};
1329
+ return {title: lockedString('Selecting event'), action: `selectEventByKey('${params.eventKey}')`};
1330
1330
  },
1331
1331
  handler: async params => {
1332
1332
  debugLog('Function call: selectEventByKey', params);
@@ -8,6 +8,7 @@ import type * as Platform from '../../core/platform/platform.js';
8
8
  import {createIcon} from '../../ui/kit/kit.js';
9
9
 
10
10
  import {ApplicationPanelTreeElement} from './ApplicationPanelTreeElement.js';
11
+ import {CrashReportContextView} from './CrashReportContextView.js';
11
12
  import {ReportingApiView} from './ReportingApiView.js';
12
13
  import type {ResourcesPanel} from './ResourcesPanel.js';
13
14
 
@@ -16,19 +17,32 @@ const UIStrings = {
16
17
  * @description Label for an item in the Application Panel Sidebar of the Application panel
17
18
  */
18
19
  reportingApi: 'Reporting API',
20
+ /**
21
+ * @description Label for the Crash Report Context child item in the Reporting API section.
22
+ */
23
+ crashReportContext: 'Crash Report Context',
19
24
  } as const;
20
25
  const str_ = i18n.i18n.registerUIStrings('panels/application/ReportingApiTreeElement.ts', UIStrings);
21
26
  export const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
22
27
 
23
28
  export class ReportingApiTreeElement extends ApplicationPanelTreeElement {
24
29
  private view?: ReportingApiView;
30
+ #childrenInitialized = false;
25
31
 
26
32
  constructor(storagePanel: ResourcesPanel) {
27
- super(storagePanel, i18nString(UIStrings.reportingApi), false, 'reporting-api');
33
+ super(storagePanel, i18nString(UIStrings.reportingApi), true, 'reporting-api');
28
34
  const icon = createIcon('document');
29
35
  this.setLeadingIcons([icon]);
30
36
  }
31
37
 
38
+ override onattach(): void {
39
+ super.onattach();
40
+ if (!this.#childrenInitialized) {
41
+ this.#childrenInitialized = true;
42
+ this.appendChild(new CrashReportContextTreeElement(this.resourcesPanel));
43
+ }
44
+ }
45
+
32
46
  override get itemURL(): Platform.DevToolsPath.UrlString {
33
47
  return 'reportingApi://' as Platform.DevToolsPath.UrlString;
34
48
  }
@@ -43,3 +57,28 @@ export class ReportingApiTreeElement extends ApplicationPanelTreeElement {
43
57
  return false;
44
58
  }
45
59
  }
60
+
61
+ export class CrashReportContextTreeElement extends ApplicationPanelTreeElement {
62
+ private view?: CrashReportContextView;
63
+
64
+ constructor(storagePanel: ResourcesPanel) {
65
+ super(storagePanel, i18nString(UIStrings.crashReportContext), false, 'crash-report-context');
66
+ const icon = createIcon('table');
67
+ this.setLeadingIcons([icon]);
68
+ }
69
+
70
+ override get itemURL(): Platform.DevToolsPath.UrlString {
71
+ return 'reportingApi://crash-report-context' as Platform.DevToolsPath.UrlString;
72
+ }
73
+
74
+ override onselect(selectedByUser?: boolean): boolean {
75
+ super.onselect(selectedByUser);
76
+ if (!this.view) {
77
+ this.view = new CrashReportContextView();
78
+ }
79
+ this.view.requestUpdate();
80
+ this.showView(this.view);
81
+ Host.userMetrics.panelShown('crash-report-context');
82
+ return false;
83
+ }
84
+ }
@@ -19,6 +19,7 @@ import * as Adorners from '../../ui/components/adorners/adorners.js';
19
19
  import * as Buttons from '../../ui/components/buttons/buttons.js';
20
20
  import type * as IconButton from '../../ui/components/icon_button/icon_button.js';
21
21
  import type * as NodeText from '../../ui/components/node_text/node_text.js';
22
+ import * as ObjectUI from '../../ui/legacy/components/object_ui/object_ui.js';
22
23
  import * as Components from '../../ui/legacy/components/utils/utils.js';
23
24
  import * as UI from '../../ui/legacy/legacy.js';
24
25
  import {
@@ -26,6 +27,7 @@ import {
26
27
  html,
27
28
  nothing,
28
29
  render,
30
+ type TemplateResult,
29
31
  } from '../../ui/lit/lit.js';
30
32
  import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
31
33
 
@@ -299,6 +301,23 @@ function getIconGroupsFromStats(toolStats: ReturnType<typeof calculateToolStats>
299
301
  return groups;
300
302
  }
301
303
 
304
+ export function parsePayload(payload?: unknown): {
305
+ valueObject: unknown,
306
+ valueString: string|undefined,
307
+ } {
308
+ if (payload === undefined) {
309
+ return {valueObject: undefined, valueString: undefined};
310
+ }
311
+ if (typeof payload === 'string') {
312
+ try {
313
+ return {valueObject: JSON.parse(payload), valueString: undefined};
314
+ } catch {
315
+ return {valueObject: undefined, valueString: payload};
316
+ }
317
+ }
318
+ return {valueObject: payload, valueString: undefined};
319
+ }
320
+
302
321
  export const DEFAULT_VIEW: View = (input, output, target) => {
303
322
  const tools = input.tools;
304
323
  const stats = calculateToolStats(input.toolCalls);
@@ -393,11 +412,11 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
393
412
  <span>${statusString(call)}</span>
394
413
  </div>
395
414
  </td>
396
- ${!input.selectedCall ? html`
397
- <td>${call.input}</td>
398
- <td>${call.result?.output ? JSON.stringify(call.result.output)
415
+ ${!input.selectedCall ? html`
416
+ <td>${call.input}</td>
417
+ <td>${call.result?.output ? JSON.stringify(call.result.output)
399
418
  : call.result?.errorText ?? ''}</td>
400
- ` : nothing}
419
+ ` : nothing}
401
420
  </tr>
402
421
  `)}
403
422
  </table>`}>
@@ -418,6 +437,16 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
418
437
  title=${i18nString(UIStrings.toolDetails)}
419
438
  ${widget(ToolDetailsWidget, {tool: input.selectedCall?.tool})}>
420
439
  </devtools-widget>
440
+ <devtools-widget
441
+ id="inputs"
442
+ title=${i18nString(UIStrings.input)}
443
+ ${widget(PayloadWidget, parsePayload(input.selectedCall?.input))}>
444
+ </devtools-widget>
445
+ <devtools-widget
446
+ id="outputs"
447
+ title=${i18nString(UIStrings.output)}
448
+ ${widget(PayloadWidget, parsePayload(input.selectedCall?.result?.output))}>
449
+ </devtools-widget>
421
450
  </devtools-tabbed-pane>
422
451
  </div>
423
452
  </devtools-split-view>
@@ -653,6 +682,95 @@ export class WebMCPView extends UI.Widget.VBox {
653
682
  this.#view(input, {}, this.contentElement);
654
683
  }
655
684
  }
685
+ export interface PayloadViewInput {
686
+ valueObject?: unknown;
687
+ valueString?: string;
688
+ }
689
+
690
+ export const PAYLOAD_DEFAULT_VIEW = (input: PayloadViewInput, output: object, target: HTMLElement): void => {
691
+ if (input.valueObject === undefined && input.valueString === undefined) {
692
+ render(nothing, target);
693
+ return;
694
+ }
695
+ const isParsable = input.valueObject !== undefined;
696
+
697
+ const createPayload = (parsedInput: unknown): TemplateResult => {
698
+ const object = new SDK.RemoteObject.LocalJSONObject(parsedInput);
699
+ const section =
700
+ new ObjectUI.ObjectPropertiesSection.RootElement(new ObjectUI.ObjectPropertiesSection.ObjectTree(object, {
701
+ readOnly: true,
702
+ propertiesMode: ObjectUI.ObjectPropertiesSection.ObjectPropertiesMode.OWN_AND_INTERNAL_AND_INHERITED,
703
+ }));
704
+ section.title = document.createTextNode(object.description);
705
+ section.listItemElement.classList.add('source-code', 'object-properties-section');
706
+ section.childrenListElement.classList.add('source-code', 'object-properties-section');
707
+ section.expand();
708
+ return html`<devtools-tree .template=${html`
709
+ <style>${ObjectUI.ObjectPropertiesSection.objectValueStyles}</style>
710
+ <style>${ObjectUI.ObjectPropertiesSection.objectPropertiesSectionStyles}</style>
711
+ <ul role="tree">
712
+ <devtools-tree-wrapper .treeElement=${section}></devtools-tree-wrapper>
713
+ </ul>
714
+ `}></devtools-tree>`;
715
+ };
716
+
717
+ const createSourceText = (text: string): TemplateResult => html`<div class="payload-value source-code">${text}</div>`;
718
+
719
+ render(
720
+ html`
721
+ <style>${webMCPViewStyles}</style>
722
+ <div class="call-payload-view">
723
+ <div class="call-payload-content">
724
+ ${
725
+ isParsable ? createPayload(input.valueObject) :
726
+ (input.valueString !== undefined ? createSourceText(input.valueString) : nothing)}
727
+ </div>
728
+ </div>
729
+ `,
730
+ target);
731
+ };
732
+
733
+ export class PayloadWidget extends UI.Widget.Widget {
734
+ #valueObject?: unknown;
735
+ #valueString?: string;
736
+ #view: typeof PAYLOAD_DEFAULT_VIEW;
737
+
738
+ constructor(element?: HTMLElement, view = PAYLOAD_DEFAULT_VIEW) {
739
+ super(element);
740
+ this.#view = view;
741
+ }
742
+
743
+ set valueObject(valueObject: unknown) {
744
+ this.#valueObject = valueObject;
745
+ this.requestUpdate();
746
+ }
747
+
748
+ get valueObject(): unknown {
749
+ return this.#valueObject;
750
+ }
751
+
752
+ set valueString(valueString: string|undefined) {
753
+ this.#valueString = valueString;
754
+ this.requestUpdate();
755
+ }
756
+
757
+ get valueString(): string|undefined {
758
+ return this.#valueString;
759
+ }
760
+
761
+ override wasShown(): void {
762
+ super.wasShown();
763
+ this.requestUpdate();
764
+ }
765
+
766
+ override performUpdate(): void {
767
+ const input: PayloadViewInput = {
768
+ valueObject: this.#valueObject,
769
+ valueString: this.#valueString,
770
+ };
771
+ this.#view(input, {}, this.contentElement);
772
+ }
773
+ }
656
774
 
657
775
  export interface ToolDetailsViewInput {
658
776
  tool: WebMCP.WebMCPModel.Tool|null|undefined;
@@ -27,6 +27,7 @@ import * as OpenedWindowDetailsView from './OpenedWindowDetailsView.js';
27
27
  import * as OriginTrialTreeView from './OriginTrialTreeView.js';
28
28
  import * as PreloadingView from './preloading/PreloadingView.js';
29
29
  import * as PreloadingTreeElement from './PreloadingTreeElement.js';
30
+ import * as ReportingApiTreeElement from './ReportingApiTreeElement.js';
30
31
  import * as ReportingApiView from './ReportingApiView.js';
31
32
  import * as ResourcesPanel from './ResourcesPanel.js';
32
33
  import * as ServiceWorkerCacheViews from './ServiceWorkerCacheViews.js';
@@ -70,6 +71,7 @@ export {
70
71
  OriginTrialTreeView,
71
72
  PreloadingTreeElement,
72
73
  PreloadingView,
74
+ ReportingApiTreeElement,
73
75
  ReportingApiView,
74
76
  ResourcesPanel,
75
77
  ServiceWorkerCacheViews,
@@ -198,4 +198,16 @@
198
198
  flex: auto;
199
199
  border-bottom: 1px solid var(--sys-color-divider);
200
200
  }
201
+
202
+ .call-payload-view {
203
+ display: flex;
204
+ flex-direction: column;
205
+ height: 100%;
206
+ }
207
+
208
+ .call-payload-content {
209
+ padding: var(--sys-size-5);
210
+ flex: auto;
211
+ overflow: auto;
212
+ }
201
213
  }
@@ -611,7 +611,8 @@ export class Linkifier extends Common.ObjectWrapper.ObjectWrapper<EventTypes> im
611
611
  jslogContext: options.jslogContext || 'url',
612
612
  lineNumber,
613
613
  columnNumber,
614
- userMetric: options?.userMetric
614
+ userMetric: options?.userMetric,
615
+ onRef: options.onRef,
615
616
  };
616
617
  return Linkifier.renderLink(linkText, className, linkOptions);
617
618
  }
@@ -12,7 +12,7 @@
12
12
 
13
13
  .image-preview-container img {
14
14
  margin: 6px 0;
15
- max-width: 100px;
15
+ width: auto;
16
16
  max-height: 100px;
17
17
  background-image: var(--image-file-checker);
18
18
  user-select: text;
package/package.json CHANGED
@@ -105,5 +105,5 @@
105
105
  "flat-cache": "6.1.12"
106
106
  }
107
107
  },
108
- "version": "1.0.1608453"
108
+ "version": "1.0.1608868"
109
109
  }