chrome-devtools-frontend 1.0.1606789 → 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.
Files changed (75) hide show
  1. package/docs/ui_engineering.md +2 -0
  2. package/eslint.config.mjs +2 -0
  3. package/front_end/core/common/VersionController.ts +18 -1
  4. package/front_end/core/host/UserMetrics.ts +0 -2
  5. package/front_end/core/platform/node/HostRuntime.ts +1 -1
  6. package/front_end/core/root/ExperimentNames.ts +0 -2
  7. package/front_end/core/sdk/AccessibilityModel.ts +13 -1
  8. package/front_end/core/sdk/ServiceWorkerCacheModel.ts +0 -13
  9. package/front_end/core/sdk/StorageBucketsModel.ts +0 -12
  10. package/front_end/entrypoints/main/MainImpl.ts +2 -11
  11. package/front_end/generated/InspectorBackendCommands.ts +3 -33
  12. package/front_end/generated/SupportedCSSProperties.js +8 -4
  13. package/front_end/generated/protocol-mapping.d.ts +7 -26
  14. package/front_end/generated/protocol-proxy-api.d.ts +5 -24
  15. package/front_end/generated/protocol.ts +2 -296
  16. package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +2 -2
  17. package/front_end/models/ai_assistance/agents/BreakpointDebuggerAgent.ts +1 -1
  18. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +6 -6
  19. package/front_end/models/ai_assistance/agents/ConversationSummaryAgent.ts +2 -1
  20. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +46 -21
  21. package/front_end/{panels/profiler → models/heap_snapshot_model}/ChildrenProvider.ts +3 -4
  22. package/front_end/{panels/profiler → models/heap_snapshot_model}/HeapSnapshotProxy.ts +19 -36
  23. package/front_end/models/heap_snapshot_model/heap_snapshot_model.ts +4 -0
  24. package/front_end/models/javascript_metadata/NativeFunctions.js +0 -4
  25. package/front_end/panels/accessibility/AccessibilitySidebarView.ts +53 -10
  26. package/front_end/panels/accessibility/accessibility.ts +0 -2
  27. package/front_end/panels/accessibility/accessibilitySidebarView.css +10 -0
  28. package/front_end/panels/ai_assistance/components/ChatMessage.ts +6 -5
  29. package/front_end/panels/ai_assistance/components/WalkthroughView.ts +36 -17
  30. package/front_end/panels/ai_assistance/components/chatMessage.css +7 -0
  31. package/front_end/panels/ai_assistance/components/walkthroughView.css +39 -11
  32. package/front_end/panels/application/CrashReportContextView.ts +237 -0
  33. package/front_end/panels/application/IndexedDBModel.ts +0 -10
  34. package/front_end/panels/application/InterestGroupStorageModel.ts +0 -11
  35. package/front_end/panels/application/ReportingApiTreeElement.ts +40 -1
  36. package/front_end/panels/application/SharedStorageModel.ts +0 -11
  37. package/front_end/panels/application/WebMCPView.ts +389 -52
  38. package/front_end/panels/application/application.ts +4 -0
  39. package/front_end/panels/application/components/CrashReportContextGrid.ts +154 -0
  40. package/front_end/panels/application/components/components.ts +2 -0
  41. package/front_end/panels/application/webMCPView.css +107 -10
  42. package/front_end/panels/common/AiCodeCompletionDisclaimer.ts +12 -2
  43. package/front_end/panels/elements/AccessibilityTreeView.ts +10 -6
  44. package/front_end/panels/elements/ElementsPanel.ts +9 -50
  45. package/front_end/panels/elements/StylePropertiesSection.ts +1 -1
  46. package/front_end/panels/elements/elements-meta.ts +1 -0
  47. package/front_end/panels/elements/elementsPanel.css +4 -14
  48. package/front_end/panels/profiler/HeapSnapshotDataGrids.ts +23 -13
  49. package/front_end/panels/profiler/HeapSnapshotGridNodes.ts +30 -30
  50. package/front_end/panels/profiler/HeapSnapshotView.ts +16 -13
  51. package/front_end/panels/profiler/profiler.ts +0 -4
  52. package/front_end/panels/snippets/SnippetsQuickOpen.ts +5 -5
  53. package/front_end/panels/sources/FilteredUISourceCodeListProvider.ts +2 -2
  54. package/front_end/panels/sources/sources-meta.ts +7 -7
  55. package/front_end/panels/timeline/CompatibilityTracksAppender.ts +1 -3
  56. package/front_end/panels/timeline/ThirdPartyTreeView.ts +6 -1
  57. package/front_end/panels/timeline/ThreadAppender.ts +1 -3
  58. package/front_end/panels/timeline/TimelineController.ts +2 -2
  59. package/front_end/panels/timeline/TimelinePanel.ts +2 -4
  60. package/front_end/panels/timeline/TimelineTreeView.ts +32 -2
  61. package/front_end/panels/timeline/components/LiveMetricsView.ts +75 -54
  62. package/front_end/panels/timeline/components/timelineRangeSummaryView.css +8 -0
  63. package/front_end/panels/timeline/thirdPartyTreeView.css +0 -1
  64. package/front_end/panels/timeline/timeline-meta.ts +13 -0
  65. package/front_end/third_party/chromium/README.chromium +1 -1
  66. package/front_end/ui/legacy/TabbedPane.ts +3 -1
  67. package/front_end/ui/legacy/components/quick_open/CommandMenu.ts +3 -3
  68. package/front_end/ui/legacy/components/quick_open/FilteredListWidget.ts +2 -5
  69. package/front_end/ui/legacy/components/quick_open/HelpQuickOpen.ts +4 -4
  70. package/front_end/ui/legacy/components/quick_open/QuickOpen.ts +5 -1
  71. package/front_end/ui/legacy/components/utils/Linkifier.ts +2 -1
  72. package/front_end/ui/legacy/components/utils/imagePreview.css +1 -1
  73. package/front_end/ui/visual_logging/KnownContextValues.ts +2 -3
  74. package/package.json +1 -1
  75. package/front_end/panels/accessibility/AXBreadcrumbsPane.ts +0 -653
@@ -16932,6 +16932,7 @@ export namespace Preload {
16932
16932
  loaderId: Network.LoaderId;
16933
16933
  action: SpeculationAction;
16934
16934
  url: string;
16935
+ formSubmission?: boolean;
16935
16936
  targetHint?: SpeculationTargetHint;
16936
16937
  }
16937
16938
 
@@ -17037,6 +17038,7 @@ export namespace Preload {
17037
17038
  PrerenderFailedDuringPrefetch = 'PrerenderFailedDuringPrefetch',
17038
17039
  BrowsingDataRemoved = 'BrowsingDataRemoved',
17039
17040
  PrerenderHostReused = 'PrerenderHostReused',
17041
+ FormSubmitWhenPrerendering = 'FormSubmitWhenPrerendering',
17040
17042
  }
17041
17043
 
17042
17044
  /**
@@ -18282,253 +18284,6 @@ export namespace Storage {
18282
18284
  durability: StorageBucketsDurability;
18283
18285
  }
18284
18286
 
18285
- export const enum AttributionReportingSourceType {
18286
- Navigation = 'navigation',
18287
- Event = 'event',
18288
- }
18289
-
18290
- export type UnsignedInt64AsBase10 = string;
18291
-
18292
- export type UnsignedInt128AsBase16 = string;
18293
-
18294
- export type SignedInt64AsBase10 = string;
18295
-
18296
- export interface AttributionReportingFilterDataEntry {
18297
- key: string;
18298
- values: string[];
18299
- }
18300
-
18301
- export interface AttributionReportingFilterConfig {
18302
- filterValues: AttributionReportingFilterDataEntry[];
18303
- /**
18304
- * duration in seconds
18305
- */
18306
- lookbackWindow?: integer;
18307
- }
18308
-
18309
- export interface AttributionReportingFilterPair {
18310
- filters: AttributionReportingFilterConfig[];
18311
- notFilters: AttributionReportingFilterConfig[];
18312
- }
18313
-
18314
- export interface AttributionReportingAggregationKeysEntry {
18315
- key: string;
18316
- value: UnsignedInt128AsBase16;
18317
- }
18318
-
18319
- export interface AttributionReportingEventReportWindows {
18320
- /**
18321
- * duration in seconds
18322
- */
18323
- start: integer;
18324
- /**
18325
- * duration in seconds
18326
- */
18327
- ends: integer[];
18328
- }
18329
-
18330
- export const enum AttributionReportingTriggerDataMatching {
18331
- Exact = 'exact',
18332
- Modulus = 'modulus',
18333
- }
18334
-
18335
- export interface AttributionReportingAggregatableDebugReportingData {
18336
- keyPiece: UnsignedInt128AsBase16;
18337
- /**
18338
- * number instead of integer because not all uint32 can be represented by
18339
- * int
18340
- */
18341
- value: number;
18342
- types: string[];
18343
- }
18344
-
18345
- export interface AttributionReportingAggregatableDebugReportingConfig {
18346
- /**
18347
- * number instead of integer because not all uint32 can be represented by
18348
- * int, only present for source registrations
18349
- */
18350
- budget?: number;
18351
- keyPiece: UnsignedInt128AsBase16;
18352
- debugData: AttributionReportingAggregatableDebugReportingData[];
18353
- aggregationCoordinatorOrigin?: string;
18354
- }
18355
-
18356
- export interface AttributionScopesData {
18357
- values: string[];
18358
- /**
18359
- * number instead of integer because not all uint32 can be represented by
18360
- * int
18361
- */
18362
- limit: number;
18363
- maxEventStates: number;
18364
- }
18365
-
18366
- export interface AttributionReportingNamedBudgetDef {
18367
- name: string;
18368
- budget: integer;
18369
- }
18370
-
18371
- export interface AttributionReportingSourceRegistration {
18372
- time: Network.TimeSinceEpoch;
18373
- /**
18374
- * duration in seconds
18375
- */
18376
- expiry: integer;
18377
- /**
18378
- * number instead of integer because not all uint32 can be represented by
18379
- * int
18380
- */
18381
- triggerData: number[];
18382
- eventReportWindows: AttributionReportingEventReportWindows;
18383
- /**
18384
- * duration in seconds
18385
- */
18386
- aggregatableReportWindow: integer;
18387
- type: AttributionReportingSourceType;
18388
- sourceOrigin: string;
18389
- reportingOrigin: string;
18390
- destinationSites: string[];
18391
- eventId: UnsignedInt64AsBase10;
18392
- priority: SignedInt64AsBase10;
18393
- filterData: AttributionReportingFilterDataEntry[];
18394
- aggregationKeys: AttributionReportingAggregationKeysEntry[];
18395
- debugKey?: UnsignedInt64AsBase10;
18396
- triggerDataMatching: AttributionReportingTriggerDataMatching;
18397
- destinationLimitPriority: SignedInt64AsBase10;
18398
- aggregatableDebugReportingConfig: AttributionReportingAggregatableDebugReportingConfig;
18399
- scopesData?: AttributionScopesData;
18400
- maxEventLevelReports: integer;
18401
- namedBudgets: AttributionReportingNamedBudgetDef[];
18402
- debugReporting: boolean;
18403
- eventLevelEpsilon: number;
18404
- }
18405
-
18406
- export const enum AttributionReportingSourceRegistrationResult {
18407
- Success = 'success',
18408
- InternalError = 'internalError',
18409
- InsufficientSourceCapacity = 'insufficientSourceCapacity',
18410
- InsufficientUniqueDestinationCapacity = 'insufficientUniqueDestinationCapacity',
18411
- ExcessiveReportingOrigins = 'excessiveReportingOrigins',
18412
- ProhibitedByBrowserPolicy = 'prohibitedByBrowserPolicy',
18413
- SuccessNoised = 'successNoised',
18414
- DestinationReportingLimitReached = 'destinationReportingLimitReached',
18415
- DestinationGlobalLimitReached = 'destinationGlobalLimitReached',
18416
- DestinationBothLimitsReached = 'destinationBothLimitsReached',
18417
- ReportingOriginsPerSiteLimitReached = 'reportingOriginsPerSiteLimitReached',
18418
- ExceedsMaxChannelCapacity = 'exceedsMaxChannelCapacity',
18419
- ExceedsMaxScopesChannelCapacity = 'exceedsMaxScopesChannelCapacity',
18420
- ExceedsMaxTriggerStateCardinality = 'exceedsMaxTriggerStateCardinality',
18421
- ExceedsMaxEventStatesLimit = 'exceedsMaxEventStatesLimit',
18422
- DestinationPerDayReportingLimitReached = 'destinationPerDayReportingLimitReached',
18423
- }
18424
-
18425
- export const enum AttributionReportingSourceRegistrationTimeConfig {
18426
- Include = 'include',
18427
- Exclude = 'exclude',
18428
- }
18429
-
18430
- export interface AttributionReportingAggregatableValueDictEntry {
18431
- key: string;
18432
- /**
18433
- * number instead of integer because not all uint32 can be represented by
18434
- * int
18435
- */
18436
- value: number;
18437
- filteringId: UnsignedInt64AsBase10;
18438
- }
18439
-
18440
- export interface AttributionReportingAggregatableValueEntry {
18441
- values: AttributionReportingAggregatableValueDictEntry[];
18442
- filters: AttributionReportingFilterPair;
18443
- }
18444
-
18445
- export interface AttributionReportingEventTriggerData {
18446
- data: UnsignedInt64AsBase10;
18447
- priority: SignedInt64AsBase10;
18448
- dedupKey?: UnsignedInt64AsBase10;
18449
- filters: AttributionReportingFilterPair;
18450
- }
18451
-
18452
- export interface AttributionReportingAggregatableTriggerData {
18453
- keyPiece: UnsignedInt128AsBase16;
18454
- sourceKeys: string[];
18455
- filters: AttributionReportingFilterPair;
18456
- }
18457
-
18458
- export interface AttributionReportingAggregatableDedupKey {
18459
- dedupKey?: UnsignedInt64AsBase10;
18460
- filters: AttributionReportingFilterPair;
18461
- }
18462
-
18463
- export interface AttributionReportingNamedBudgetCandidate {
18464
- name?: string;
18465
- filters: AttributionReportingFilterPair;
18466
- }
18467
-
18468
- export interface AttributionReportingTriggerRegistration {
18469
- filters: AttributionReportingFilterPair;
18470
- debugKey?: UnsignedInt64AsBase10;
18471
- aggregatableDedupKeys: AttributionReportingAggregatableDedupKey[];
18472
- eventTriggerData: AttributionReportingEventTriggerData[];
18473
- aggregatableTriggerData: AttributionReportingAggregatableTriggerData[];
18474
- aggregatableValues: AttributionReportingAggregatableValueEntry[];
18475
- aggregatableFilteringIdMaxBytes: integer;
18476
- debugReporting: boolean;
18477
- aggregationCoordinatorOrigin?: string;
18478
- sourceRegistrationTimeConfig: AttributionReportingSourceRegistrationTimeConfig;
18479
- triggerContextId?: string;
18480
- aggregatableDebugReportingConfig: AttributionReportingAggregatableDebugReportingConfig;
18481
- scopes: string[];
18482
- namedBudgets: AttributionReportingNamedBudgetCandidate[];
18483
- }
18484
-
18485
- export const enum AttributionReportingEventLevelResult {
18486
- Success = 'success',
18487
- SuccessDroppedLowerPriority = 'successDroppedLowerPriority',
18488
- InternalError = 'internalError',
18489
- NoCapacityForAttributionDestination = 'noCapacityForAttributionDestination',
18490
- NoMatchingSources = 'noMatchingSources',
18491
- Deduplicated = 'deduplicated',
18492
- ExcessiveAttributions = 'excessiveAttributions',
18493
- PriorityTooLow = 'priorityTooLow',
18494
- NeverAttributedSource = 'neverAttributedSource',
18495
- ExcessiveReportingOrigins = 'excessiveReportingOrigins',
18496
- NoMatchingSourceFilterData = 'noMatchingSourceFilterData',
18497
- ProhibitedByBrowserPolicy = 'prohibitedByBrowserPolicy',
18498
- NoMatchingConfigurations = 'noMatchingConfigurations',
18499
- ExcessiveReports = 'excessiveReports',
18500
- FalselyAttributedSource = 'falselyAttributedSource',
18501
- ReportWindowPassed = 'reportWindowPassed',
18502
- NotRegistered = 'notRegistered',
18503
- ReportWindowNotStarted = 'reportWindowNotStarted',
18504
- NoMatchingTriggerData = 'noMatchingTriggerData',
18505
- }
18506
-
18507
- export const enum AttributionReportingAggregatableResult {
18508
- Success = 'success',
18509
- InternalError = 'internalError',
18510
- NoCapacityForAttributionDestination = 'noCapacityForAttributionDestination',
18511
- NoMatchingSources = 'noMatchingSources',
18512
- ExcessiveAttributions = 'excessiveAttributions',
18513
- ExcessiveReportingOrigins = 'excessiveReportingOrigins',
18514
- NoHistograms = 'noHistograms',
18515
- InsufficientBudget = 'insufficientBudget',
18516
- InsufficientNamedBudget = 'insufficientNamedBudget',
18517
- NoMatchingSourceFilterData = 'noMatchingSourceFilterData',
18518
- NotRegistered = 'notRegistered',
18519
- ProhibitedByBrowserPolicy = 'prohibitedByBrowserPolicy',
18520
- Deduplicated = 'deduplicated',
18521
- ReportWindowPassed = 'reportWindowPassed',
18522
- ExcessiveReports = 'excessiveReports',
18523
- }
18524
-
18525
- export const enum AttributionReportingReportResult {
18526
- Sent = 'sent',
18527
- Prohibited = 'prohibited',
18528
- FailedToAssemble = 'failedToAssemble',
18529
- Expired = 'expired',
18530
- }
18531
-
18532
18287
  /**
18533
18288
  * A single Related Website Set object.
18534
18289
  */
@@ -18811,24 +18566,6 @@ export namespace Storage {
18811
18566
  deletedSites: string[];
18812
18567
  }
18813
18568
 
18814
- export interface SetAttributionReportingLocalTestingModeRequest {
18815
- /**
18816
- * If enabled, noise is suppressed and reports are sent immediately.
18817
- */
18818
- enabled: boolean;
18819
- }
18820
-
18821
- export interface SetAttributionReportingTrackingRequest {
18822
- enable: boolean;
18823
- }
18824
-
18825
- export interface SendPendingAttributionReportsResponse extends ProtocolResponseWithError {
18826
- /**
18827
- * The number of reports that were sent.
18828
- */
18829
- numSent: integer;
18830
- }
18831
-
18832
18569
  export interface GetRelatedWebsiteSetsResponse extends ProtocolResponseWithError {
18833
18570
  sets: RelatedWebsiteSet[];
18834
18571
  }
@@ -19082,37 +18819,6 @@ export namespace Storage {
19082
18819
  export interface StorageBucketDeletedEvent {
19083
18820
  bucketId: string;
19084
18821
  }
19085
-
19086
- export interface AttributionReportingSourceRegisteredEvent {
19087
- registration: AttributionReportingSourceRegistration;
19088
- result: AttributionReportingSourceRegistrationResult;
19089
- }
19090
-
19091
- export interface AttributionReportingTriggerRegisteredEvent {
19092
- registration: AttributionReportingTriggerRegistration;
19093
- eventLevel: AttributionReportingEventLevelResult;
19094
- aggregatable: AttributionReportingAggregatableResult;
19095
- }
19096
-
19097
- export interface AttributionReportingReportSentEvent {
19098
- url: string;
19099
- body: any;
19100
- result: AttributionReportingReportResult;
19101
- /**
19102
- * If result is `sent`, populated with net/HTTP status.
19103
- */
19104
- netError?: integer;
19105
- netErrorName?: string;
19106
- httpStatusCode?: integer;
19107
- }
19108
-
19109
- export interface AttributionReportingVerboseDebugReportSentEvent {
19110
- url: string;
19111
- body?: any[];
19112
- netError?: integer;
19113
- netErrorName?: string;
19114
- httpStatusCode?: integer;
19115
- }
19116
18822
  }
19117
18823
 
19118
18824
  /**
@@ -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
 
@@ -28,6 +28,7 @@ import {
28
28
  type AiWidget,
29
29
  type ContextResponse,
30
30
  ConversationContext,
31
+ type ConversationSuggestion,
31
32
  type ConversationSuggestions,
32
33
  type FunctionCallHandlerResult,
33
34
  type ParsedResponse,
@@ -40,11 +41,11 @@ const UIStringsNotTranslated = {
40
41
  /**
41
42
  * @description Shown when the agent is investigating network activity
42
43
  */
43
- networkActivitySummary: 'Investigating network activity',
44
+ networkActivitySummary: 'Investigating network activity',
44
45
  /**
45
46
  * @description Shown when the agent is investigating main thread activity
46
47
  */
47
- mainThreadActivity: 'Investigating main thread activity',
48
+ mainThreadActivity: 'Investigating main thread activity',
48
49
  } as const;
49
50
  const lockedString = i18n.i18n.lockedString;
50
51
 
@@ -173,7 +174,7 @@ const extraPreambleWhenNotExternal = `Additional notes:
173
174
  When referring to a trace event that has a corresponding \`eventKey\`, annotate your output using markdown link syntax. For example:
174
175
  - When referring to an event that is a long task: [Long task](#r-123)
175
176
  - When referring to a URL for which you know the eventKey of: [https://www.example.com](#s-1827)
176
- - Never show the eventKey (like "eventKey: s-1852"); instead, use a markdown link as described above.
177
+ - Never show the eventKey (like "eventKey: s-1852") in your running text. When using markdown links, the URL must be only the hash (e.g., \`#s-1852\`), never \`eventKey: s-1852\`.
177
178
 
178
179
  When asking the user to make a choice between options, output a list of choices at the end of your text response. The format is \`SUGGESTIONS: ["suggestion1", "suggestion2", "suggestion3"]\`. This MUST start on a newline, and be a single line.
179
180
  `;
@@ -299,31 +300,44 @@ export class PerformanceTraceContext extends ConversationContext<AgentFocus> {
299
300
 
300
301
  const insightSet = focus.primaryInsightSet;
301
302
  if (insightSet) {
302
- const lcp = insightSet ? Trace.Insights.Common.getLCP(insightSet) : null;
303
- const cls = insightSet ? Trace.Insights.Common.getCLS(insightSet) : null;
304
- const inp = insightSet ? Trace.Insights.Common.getINP(insightSet) : null;
303
+ const lcp = Trace.Insights.Common.getLCP(insightSet);
304
+ const cls = Trace.Insights.Common.getCLS(insightSet);
305
+ const inp = Trace.Insights.Common.getINP(insightSet);
305
306
 
306
307
  const ModelHandlers = Trace.Handlers.ModelHandlers;
307
308
  const GOOD = Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.GOOD;
308
309
 
310
+ const poorMetrics = new Set<Trace.Insights.Types.InsightKeys>();
311
+
309
312
  if (lcp && ModelHandlers.PageLoadMetrics.scoreClassificationForLargestContentfulPaint(lcp.value) !== GOOD) {
310
313
  suggestions.push({title: 'How can I improve LCP?', jslogContext: 'performance-default'});
314
+ poorMetrics.add(Trace.Insights.Types.InsightKeys.LCP_BREAKDOWN);
315
+ poorMetrics.add(Trace.Insights.Types.InsightKeys.LCP_DISCOVERY);
311
316
  }
312
317
  if (inp && ModelHandlers.UserInteractions.scoreClassificationForInteractionToNextPaint(inp.value) !== GOOD) {
313
318
  suggestions.push({title: 'How can I improve INP?', jslogContext: 'performance-default'});
319
+ poorMetrics.add(Trace.Insights.Types.InsightKeys.INP_BREAKDOWN);
314
320
  }
315
321
  if (cls && ModelHandlers.LayoutShifts.scoreClassificationForLayoutShift(cls.value) !== GOOD) {
316
322
  suggestions.push({title: 'How can I improve CLS?', jslogContext: 'performance-default'});
323
+ poorMetrics.add(Trace.Insights.Types.InsightKeys.CLS_CULPRITS);
317
324
  }
318
325
 
319
- // Add up to 3 suggestions from the top failing insights.
320
- const top3FailingInsightSuggestions =
321
- Object.values(insightSet.model)
322
- .filter(model => model.state !== 'pass')
323
- .map(model => new PerformanceInsightFormatter(focus, model).getSuggestions().at(-1))
324
- .filter(suggestion => !!suggestion)
325
- .slice(0, 3);
326
- suggestions.push(...top3FailingInsightSuggestions);
326
+ // Add up to 4 suggestions total (including those already added) from the top failing insights
327
+ // that aren't already covered by CWV suggestions.
328
+ const additionalSuggestionsRequired = Math.max(0, 4 - suggestions.length);
329
+ if (additionalSuggestionsRequired > 0) {
330
+ const failingInsightSuggestions =
331
+ Object.values(insightSet.model)
332
+ .filter(model => {
333
+ return model.state !== 'pass' &&
334
+ !poorMetrics.has(model.insightKey as Trace.Insights.Types.InsightKeys);
335
+ })
336
+ .map(model => new PerformanceInsightFormatter(focus, model).getSuggestions().at(-1))
337
+ .filter((suggestion): suggestion is ConversationSuggestion => !!suggestion)
338
+ .slice(0, additionalSuggestionsRequired);
339
+ suggestions.push(...failingInsightSuggestions);
340
+ }
327
341
  }
328
342
 
329
343
  return suggestions;
@@ -491,13 +505,24 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
491
505
  // - Group 3: The link destination, e.g., "url"
492
506
  // 2. (https?:\/\/[^\s<>()]+): Captures a standalone URL.
493
507
  // - Group 4: The standalone URL, e.g., "https://google.com"
494
- const urlRegex = /(\[(.*?)\]\((.*?)\))|(https?:\/\/[^\s<>()]+)/g;
508
+ const urlRegex = /(\[(.*?)\][ \t]*\((.*?)\))|(https?:\/\/[^\s<>()]+)/g;
495
509
 
496
510
  return response.replace(urlRegex, (match, markdownLink, linkText, linkDest, standaloneUrlText) => {
497
511
  if (markdownLink) {
498
512
  if (linkDest.startsWith('#')) {
499
513
  return match;
500
514
  }
515
+
516
+ const eventKeyMatch = linkDest.match(/eventKey:\s*([^\s,)]+)/);
517
+ if (eventKeyMatch) {
518
+ const eventKey = eventKeyMatch[1];
519
+ return `[${linkText}](#${eventKey})`;
520
+ }
521
+
522
+ const event = focus.lookupEvent(linkDest as Trace.Types.File.SerializableKey);
523
+ if (event) {
524
+ return `[${linkText}](#${linkDest})`;
525
+ }
501
526
  }
502
527
 
503
528
  const urlText = linkDest ?? standaloneUrlText;
@@ -780,7 +805,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
780
805
  },
781
806
  displayInfoFromArgs: params => {
782
807
  return {
783
- title: lockedString(`Investigating insight ${params.insightName}…`),
808
+ title: lockedString(`Investigating insight ${params.insightName}`),
784
809
  action: `getInsightDetails('${params.insightSetId}', '${params.insightName}')`
785
810
  };
786
811
  },
@@ -878,7 +903,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
878
903
  required: ['eventKey']
879
904
  },
880
905
  displayInfoFromArgs: params => {
881
- return {title: lockedString('Looking at trace event'), action: `getEventByKey('${params.eventKey}')`};
906
+ return {title: lockedString('Looking at trace event'), action: `getEventByKey('${params.eventKey}')`};
882
907
  },
883
908
  handler: async params => {
884
909
  debugLog('Function call: getEventByKey', params);
@@ -1068,7 +1093,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
1068
1093
  required: ['eventKey']
1069
1094
  },
1070
1095
  displayInfoFromArgs: args => {
1071
- return {title: lockedString('Looking at call tree'), action: `getDetailedCallTree('${args.eventKey}')`};
1096
+ return {title: lockedString('Looking at call tree'), action: `getDetailedCallTree('${args.eventKey}')`};
1072
1097
  },
1073
1098
  handler: async args => {
1074
1099
  debugLog('Function call: getDetailedCallTree');
@@ -1188,7 +1213,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
1188
1213
  },
1189
1214
  displayInfoFromArgs: args => {
1190
1215
  return {
1191
- title: lockedString('Looking up function code'),
1216
+ title: lockedString('Looking up function code'),
1192
1217
  action: `getFunctionCode('${args.scriptUrl}', ${args.line}, ${args.column})`
1193
1218
  };
1194
1219
  },
@@ -1246,7 +1271,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
1246
1271
  required: ['url']
1247
1272
  },
1248
1273
  displayInfoFromArgs: args => {
1249
- return {title: lockedString('Looking at resource content'), action: `getResourceContent('${args.url}')`};
1274
+ return {title: lockedString('Looking at resource content'), action: `getResourceContent('${args.url}')`};
1250
1275
  },
1251
1276
  handler: async args => {
1252
1277
  debugLog('Function call: getResourceContent');
@@ -1301,7 +1326,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
1301
1326
  required: ['eventKey']
1302
1327
  },
1303
1328
  displayInfoFromArgs: params => {
1304
- return {title: lockedString('Selecting event'), action: `selectEventByKey('${params.eventKey}')`};
1329
+ return {title: lockedString('Selecting event'), action: `selectEventByKey('${params.eventKey}')`};
1305
1330
  },
1306
1331
  handler: async params => {
1307
1332
  debugLog('Function call: selectEventByKey', params);
@@ -2,13 +2,12 @@
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
4
 
5
- import type * as HeapSnapshotModel from '../../models/heap_snapshot_model/heap_snapshot_model.js';
5
+ import type {ComparatorConfig, ItemsRange} from './HeapSnapshotModel.js';
6
6
 
7
7
  export interface ChildrenProvider {
8
8
  dispose(): void;
9
9
  nodePosition(snapshotObjectId: number): Promise<number>;
10
10
  isEmpty(): Promise<boolean>;
11
- serializeItemsRange(startPosition: number, endPosition: number):
12
- Promise<HeapSnapshotModel.HeapSnapshotModel.ItemsRange>;
13
- sortAndRewind(comparator: HeapSnapshotModel.HeapSnapshotModel.ComparatorConfig): Promise<void>;
11
+ serializeItemsRange(startPosition: number, endPosition: number): Promise<ItemsRange>;
12
+ sortAndRewind(comparator: ComparatorConfig): Promise<void>;
14
13
  }