chrome-devtools-frontend 1.0.1642899 → 1.0.1643099

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 (93) hide show
  1. package/front_end/core/protocol_client/InspectorBackend.ts +4 -0
  2. package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +4 -5
  3. package/front_end/generated/InspectorBackendCommands.ts +1 -1
  4. package/front_end/generated/protocol.ts +7 -0
  5. package/front_end/models/ai_assistance/AiAgent2.ts +23 -5
  6. package/front_end/models/ai_assistance/AiConversation.ts +15 -12
  7. package/front_end/models/ai_assistance/AiUtils.ts +71 -0
  8. package/front_end/models/ai_assistance/ChangeManager.ts +2 -5
  9. package/front_end/models/ai_assistance/{agents/ConversationSummaryAgent.ts → ConversationSummary.ts} +29 -66
  10. package/front_end/models/ai_assistance/ExtensionScope.ts +1 -4
  11. package/front_end/models/ai_assistance/{agents/PerformanceAnnotationsAgent.ts → PerformanceAnnotations.ts} +47 -89
  12. package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +31 -21
  13. package/front_end/models/ai_assistance/agents/AiAgent.ts +21 -6
  14. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.snapshot.txt +11 -0
  15. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +53 -3
  16. package/front_end/models/ai_assistance/agents/ExecuteJavascript.ts +2 -0
  17. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +72 -79
  18. package/front_end/models/ai_assistance/agents/StorageAgent.ts +47 -38
  19. package/front_end/models/ai_assistance/agents/StylingAgent.ts +22 -21
  20. package/front_end/models/ai_assistance/ai_assistance.ts +6 -4
  21. package/front_end/models/ai_assistance/skills/styling.md +12 -4
  22. package/front_end/models/ai_assistance/tools/ExecuteJavaScript.ts +140 -0
  23. package/front_end/models/ai_assistance/tools/GetStyles.ts +6 -2
  24. package/front_end/models/ai_assistance/tools/Tool.ts +10 -1
  25. package/front_end/models/ai_assistance/tools/ToolRegistry.ts +2 -0
  26. package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +5 -7
  27. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +6 -7
  28. package/front_end/panels/ai_assistance/components/ChatMessage.ts +96 -4
  29. package/front_end/panels/ai_assistance/components/chatMessage.css +6 -0
  30. package/front_end/panels/application/components/AdsView.ts +219 -0
  31. package/front_end/panels/application/components/adsView.css +54 -0
  32. package/front_end/panels/application/components/components.ts +2 -0
  33. package/front_end/panels/console/SymbolizedErrorWidget.ts +73 -22
  34. package/front_end/panels/network/NetworkLogView.ts +5 -1
  35. package/front_end/panels/timeline/overlays/components/EntryLabelOverlay.ts +5 -4
  36. package/front_end/third_party/chromium/README.chromium +1 -1
  37. package/front_end/third_party/lighthouse/README.chromium +2 -2
  38. package/front_end/third_party/lighthouse/lighthouse-dt-bundle.js +1607 -5733
  39. package/front_end/third_party/lighthouse/locales/ar-XB.json +290 -65
  40. package/front_end/third_party/lighthouse/locales/ar.json +290 -65
  41. package/front_end/third_party/lighthouse/locales/bg.json +290 -65
  42. package/front_end/third_party/lighthouse/locales/ca.json +295 -70
  43. package/front_end/third_party/lighthouse/locales/cs.json +290 -65
  44. package/front_end/third_party/lighthouse/locales/da.json +294 -69
  45. package/front_end/third_party/lighthouse/locales/de.json +295 -70
  46. package/front_end/third_party/lighthouse/locales/el.json +290 -65
  47. package/front_end/third_party/lighthouse/locales/en-GB.json +290 -65
  48. package/front_end/third_party/lighthouse/locales/en-US.json +79 -67
  49. package/front_end/third_party/lighthouse/locales/en-XA.json +253 -64
  50. package/front_end/third_party/lighthouse/locales/en-XL.json +79 -67
  51. package/front_end/third_party/lighthouse/locales/es-419.json +290 -65
  52. package/front_end/third_party/lighthouse/locales/es.json +298 -73
  53. package/front_end/third_party/lighthouse/locales/fi.json +290 -65
  54. package/front_end/third_party/lighthouse/locales/fil.json +290 -65
  55. package/front_end/third_party/lighthouse/locales/fr.json +294 -69
  56. package/front_end/third_party/lighthouse/locales/he.json +293 -68
  57. package/front_end/third_party/lighthouse/locales/hi.json +291 -66
  58. package/front_end/third_party/lighthouse/locales/hr.json +290 -65
  59. package/front_end/third_party/lighthouse/locales/hu.json +290 -65
  60. package/front_end/third_party/lighthouse/locales/id.json +290 -65
  61. package/front_end/third_party/lighthouse/locales/it.json +294 -69
  62. package/front_end/third_party/lighthouse/locales/ja.json +290 -65
  63. package/front_end/third_party/lighthouse/locales/ko.json +290 -65
  64. package/front_end/third_party/lighthouse/locales/lt.json +290 -65
  65. package/front_end/third_party/lighthouse/locales/lv.json +290 -65
  66. package/front_end/third_party/lighthouse/locales/nl.json +290 -65
  67. package/front_end/third_party/lighthouse/locales/no.json +290 -65
  68. package/front_end/third_party/lighthouse/locales/pl.json +290 -65
  69. package/front_end/third_party/lighthouse/locales/pt-PT.json +291 -66
  70. package/front_end/third_party/lighthouse/locales/pt.json +290 -65
  71. package/front_end/third_party/lighthouse/locales/ro.json +290 -65
  72. package/front_end/third_party/lighthouse/locales/ru.json +301 -76
  73. package/front_end/third_party/lighthouse/locales/sk.json +291 -66
  74. package/front_end/third_party/lighthouse/locales/sl.json +290 -65
  75. package/front_end/third_party/lighthouse/locales/sr-Latn.json +290 -65
  76. package/front_end/third_party/lighthouse/locales/sr.json +290 -65
  77. package/front_end/third_party/lighthouse/locales/sv.json +297 -72
  78. package/front_end/third_party/lighthouse/locales/ta.json +291 -66
  79. package/front_end/third_party/lighthouse/locales/te.json +293 -68
  80. package/front_end/third_party/lighthouse/locales/th.json +291 -66
  81. package/front_end/third_party/lighthouse/locales/tr.json +290 -65
  82. package/front_end/third_party/lighthouse/locales/uk.json +290 -65
  83. package/front_end/third_party/lighthouse/locales/vi.json +291 -66
  84. package/front_end/third_party/lighthouse/locales/zh-HK.json +292 -67
  85. package/front_end/third_party/lighthouse/locales/zh-TW.json +291 -66
  86. package/front_end/third_party/lighthouse/locales/zh.json +291 -66
  87. package/front_end/third_party/lighthouse/report/bundle.d.ts +6 -6
  88. package/front_end/third_party/lighthouse/report/bundle.js +4 -7
  89. package/front_end/third_party/lighthouse/report-assets/report-generator.mjs +2 -2
  90. package/front_end/ui/legacy/Widget.ts +32 -8
  91. package/front_end/ui/visual_logging/KnownContextValues.ts +2 -0
  92. package/mcp/mcp.ts +1 -0
  93. package/package.json +1 -1
@@ -81,12 +81,6 @@ If the user asks a question that requires an investigation of a problem, use thi
81
81
  - [Suggestion 2]
82
82
  `;
83
83
 
84
- const SECURITY_WARNING = `**CRITICAL CONSTRAINT**: This Lighthouse report was imported from a file and is static.
85
- You do NOT have access to the inspected page.
86
- Tools like \`executeJavaScript\`, \`getStyles\`, or \`runAccessibilityAudits\` are disabled.
87
- Do NOT attempt to use them or instruct the user that you will use them.
88
- Rely ONLY on the static report data below.`;
89
-
90
84
  export class AccessibilityContext extends ConversationContext<LHModel.ReporterTypes.ReportJSON> {
91
85
  #lh: LHModel.ReporterTypes.ReportJSON;
92
86
 
@@ -126,17 +120,15 @@ export class AccessibilityAgent extends AiAgent<LHModel.ReporterTypes.ReportJSON
126
120
  #javascriptExecutor: JavascriptExecutor;
127
121
  #changes: ChangeManager;
128
122
  #createExtensionScope: CreateExtensionScopeFunction;
129
- #currentTurnId = 0;
130
123
 
131
124
  constructor(opts: ExecuteJsAgentOptions) {
132
125
  super(opts);
133
126
  this.#lighthouseRecording = opts.lighthouseRecording;
134
127
  this.#changes = opts.changeManager || new ChangeManager();
135
128
  this.#execJs = opts.execJs ?? executeJsCode;
136
- this.#createExtensionScope =
137
- opts.createExtensionScope ?? ((changes: ChangeManager) => {
138
- return new ExtensionScope(changes, this.sessionId, this.#getDocumentBodyNode(), this.#currentTurnId);
139
- });
129
+ this.#createExtensionScope = opts.createExtensionScope ?? ((changes: ChangeManager) => {
130
+ return new ExtensionScope(changes, this.sessionId, this.#getDocumentBodyNode());
131
+ });
140
132
  this.#javascriptExecutor = new JavascriptExecutor(
141
133
  {
142
134
  executionMode: this.executionMode,
@@ -168,7 +160,6 @@ export class AccessibilityAgent extends AiAgent<LHModel.ReporterTypes.ReportJSON
168
160
  }
169
161
 
170
162
  protected override async preRun(): Promise<void> {
171
- this.#currentTurnId++;
172
163
  const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
173
164
  const domModel = target?.model(SDK.DOMModel.DOMModel);
174
165
  // We need to ensure the document is requested so that #getDocumentBodyNode()
@@ -280,11 +271,18 @@ export class AccessibilityAgent extends AiAgent<LHModel.ReporterTypes.ReportJSON
280
271
  }
281
272
  });
282
273
 
283
- if (isImported) {
284
- return;
285
- }
286
-
287
- this.declareFunction('executeJavaScript', executeJavaScriptFunction(this.#javascriptExecutor));
274
+ const executeJsDeclaration = executeJavaScriptFunction(this.#javascriptExecutor);
275
+ this.declareFunction('executeJavaScript', {
276
+ ...executeJsDeclaration,
277
+ handler: async (params, options) => {
278
+ if (isImported) {
279
+ return {
280
+ error: 'Cannot use this tool on an imported file.',
281
+ };
282
+ }
283
+ return await executeJsDeclaration.handler(params, options);
284
+ },
285
+ });
288
286
 
289
287
  this.declareFunction<{explanation: string}, {audits: string}>('runAccessibilityAudits', {
290
288
  description:
@@ -311,6 +309,11 @@ export class AccessibilityAgent extends AiAgent<LHModel.ReporterTypes.ReportJSON
311
309
  },
312
310
  handler: async params => {
313
311
  debugLog('Function call: runAccessibilityAudits', params);
312
+ if (isImported) {
313
+ return {
314
+ error: 'Cannot use this tool on an imported file.',
315
+ };
316
+ }
314
317
  if (!this.#lighthouseRecording) {
315
318
  return {error: 'Lighthouse recording is not available.'};
316
319
  }
@@ -375,6 +378,11 @@ export class AccessibilityAgent extends AiAgent<LHModel.ReporterTypes.ReportJSON
375
378
  },
376
379
  handler: async params => {
377
380
  debugLog('Function call: getStyles', params);
381
+ if (isImported) {
382
+ return {
383
+ error: 'Cannot use this tool on an imported file.',
384
+ };
385
+ }
378
386
  const node = await this.#resolvePathToNode(params.path);
379
387
  if (!node) {
380
388
  return {error: `Could not find the element with path: ${params.path}`};
@@ -445,6 +453,11 @@ export class AccessibilityAgent extends AiAgent<LHModel.ReporterTypes.ReportJSON
445
453
  },
446
454
  handler: async params => {
447
455
  debugLog('Function call: getElementAccessibilityDetails', params);
456
+ if (isImported) {
457
+ return {
458
+ error: 'Cannot use this tool on an imported file.',
459
+ };
460
+ }
448
461
  const node = await this.#resolvePathToNode(params.path);
449
462
  if (!node) {
450
463
  return {error: `Could not find the element with path: ${params.path}`};
@@ -522,10 +535,7 @@ export class AccessibilityAgent extends AiAgent<LHModel.ReporterTypes.ReportJSON
522
535
  if (lhr) {
523
536
  this.#declareFunctions();
524
537
  }
525
- let enhancedQuery = lhr ? `${this.#getInitialPayload(lhr)}\n# User request:\n\n` : '';
526
- if (lhr?.getItem().isImported) {
527
- enhancedQuery = `${SECURITY_WARNING}\n\n${enhancedQuery}`;
528
- }
538
+ const enhancedQuery = lhr ? `${this.#getInitialPayload(lhr)}\n# User request:\n\n` : '';
529
539
  return `${enhancedQuery}${query}`;
530
540
  }
531
541
 
@@ -332,6 +332,13 @@ export interface SourceFilesListAiWidget {
332
332
  };
333
333
  }
334
334
 
335
+ export interface NetworkRequestsListAiWidget {
336
+ name: 'NETWORK_REQUESTS_LIST';
337
+ data: {
338
+ requests: SDK.NetworkRequest.NetworkRequest[],
339
+ };
340
+ }
341
+
335
342
  export interface LighthouseReportAiWidget {
336
343
  name: 'LIGHTHOUSE_REPORT';
337
344
  data: {
@@ -366,10 +373,10 @@ export interface SourceCodeAiWidget {
366
373
  };
367
374
  }
368
375
 
369
- export type AiWidget =
370
- ComputedStyleAiWidget|CoreVitalsAiWidget|StylePropertiesAiWidget|DomTreeAiWidget|PerformanceTraceAiWidget|
371
- PerfInsightAiWidget|TimelineRangeSummaryAiWidget|BottomUpTreeAiWidget|SourceFileAiWidget|LighthouseReportAiWidget|
372
- TimelineEventSummaryAiWidget|NetworkRequestGeneralHeadersAiWidget|SourceCodeAiWidget|SourceFilesListAiWidget;
376
+ export type AiWidget = ComputedStyleAiWidget|CoreVitalsAiWidget|StylePropertiesAiWidget|DomTreeAiWidget|
377
+ PerformanceTraceAiWidget|PerfInsightAiWidget|TimelineRangeSummaryAiWidget|BottomUpTreeAiWidget|SourceFileAiWidget|
378
+ LighthouseReportAiWidget|TimelineEventSummaryAiWidget|NetworkRequestGeneralHeadersAiWidget|SourceCodeAiWidget|
379
+ SourceFilesListAiWidget|NetworkRequestsListAiWidget;
373
380
 
374
381
  export type FunctionCallHandlerResult<Result> = {
375
382
  requiresApproval: true,
@@ -463,7 +470,7 @@ export abstract class AiAgent<T> {
463
470
 
464
471
  readonly #sessionId: string;
465
472
  readonly #aidaClient: Host.AidaClient.AidaClient;
466
- readonly #serverSideLoggingEnabled: boolean;
473
+ #serverSideLoggingEnabled: boolean;
467
474
  readonly confirmSideEffect: typeof Promise.withResolvers;
468
475
  readonly #functionDeclarations = new Map<string, FunctionDeclaration<Record<string, unknown>, unknown>>();
469
476
  readonly #allowedOrigin?: () => AllowedOriginResult;
@@ -542,6 +549,10 @@ export abstract class AiAgent<T> {
542
549
  clearCache(): void {
543
550
  }
544
551
 
552
+ protected disableServerSideLogging(): void {
553
+ this.#serverSideLoggingEnabled = false;
554
+ }
555
+
545
556
  popPendingMultimodalInput(): MultimodalInput|undefined {
546
557
  return undefined;
547
558
  }
@@ -693,6 +704,10 @@ export abstract class AiAgent<T> {
693
704
  this.#functionDeclarations.clear();
694
705
  }
695
706
 
707
+ /**
708
+ * Executed immediately after the current context is populated with the selected
709
+ * context and before the request is built.
710
+ */
696
711
  protected async preRun(): Promise<void> {
697
712
  }
698
713
 
@@ -705,11 +720,11 @@ export abstract class AiAgent<T> {
705
720
  },
706
721
  multimodalInput?: MultimodalInput,
707
722
  ): AsyncGenerator<ResponseData, void, void> {
708
- await this.preRun();
709
723
  await options.selected?.refresh();
710
724
  if (options.selected) {
711
725
  this.context = options.selected;
712
726
  }
727
+ await this.preRun();
713
728
 
714
729
  const enhancedQuery = await this.enhanceQuery(initialQuery, options.selected, multimodalInput?.type);
715
730
  Host.userMetrics.freestylerQueryLength(enhancedQuery.length);
@@ -129,6 +129,17 @@ Content:
129
129
  "required": [],
130
130
  "properties": {}
131
131
  }
132
+ },
133
+ {
134
+ "name": "analyzeStorage",
135
+ "description": "Selects the page storage. Use this when asked about browser storage (localStorage, sessionStorage, cookies) and issues related to these.",
136
+ "parameters": {
137
+ "type": 6,
138
+ "description": "",
139
+ "nullable": true,
140
+ "required": [],
141
+ "properties": {}
142
+ }
132
143
  }
133
144
  ],
134
145
  "options": {},
@@ -6,6 +6,7 @@ import * as Common from '../../../core/common/common.js';
6
6
  import * as Host from '../../../core/host/host.js';
7
7
  import * as i18n from '../../../core/i18n/i18n.js';
8
8
  import * as Root from '../../../core/root/root.js';
9
+ import type {NetworkRequest} from '../../../core/sdk/NetworkRequest.js';
9
10
  import type * as SDK from '../../../core/sdk/sdk.js';
10
11
  import type * as LHModel from '../../lighthouse/lighthouse.js';
11
12
  import * as Logs from '../../logs/logs.js';
@@ -15,6 +16,7 @@ import * as Workspace from '../../workspace/workspace.js';
15
16
  import {isOpaqueOrigin} from '../AiOrigins.js';
16
17
  import {DOMNodeContext} from '../contexts/DOMNodeContext.js';
17
18
  import {debugLog} from '../debug.js';
19
+ import {StorageItem} from '../StorageItem.js';
18
20
 
19
21
  import {AccessibilityContext} from './AccessibilityAgent.js';
20
22
  import {
@@ -27,6 +29,7 @@ import {
27
29
  import {FileContext} from './FileAgent.js';
28
30
  import {RequestContext} from './NetworkAgent.js';
29
31
  import {PerformanceTraceContext} from './PerformanceAgent.js';
32
+ import {StorageContext} from './StorageAgent.js';
30
33
 
31
34
  const lockedString = i18n.i18n.lockedString;
32
35
  /**
@@ -41,12 +44,12 @@ Your role is to understand the user's query, identify the appropriate specialize
41
44
 
42
45
  # Workflow
43
46
  1. **Analyze**: Understand the user's intent and what they are trying to achieve.
44
- 2. **Classify**: Determine which specialized agent is best suited for the task (e.g., StylingAgent for CSS/styling issues, NetworkAgent for network requests, FileAgent for source files, PerformanceAgent for performance details, AccessibilityAgent for accessibility reports, or StorageAgent for storage issues).
45
- 3. **Gather Context**: Identify what information the specialized agent will need. Proactively use your tools to find and select this context (e.g., finding the relevant DOM node, network request, file, or performance trace). Always try to select a single specific context before answering the question.
47
+ 2. **Classify**: Determine which specialized agent is best suited for the task (e.g., StylingAgent for CSS/styling issues, NetworkAgent for network requests, FileAgent for source files, PerformanceAgent for performance details, AccessibilityAgent for accessibility reports, or StorageAgent for analyzing and explaining storage but not editing).
48
+ 3. **Gather Context**: Identify what information the specialized agent will need. Proactively use your tools to find and select this context (e.g., finding the relevant DOM node, network request, file, performance trace, or storage). Always try to select a single specific context before answering the question.
46
49
  4. **Delegate**: Once context is selected, hand over to the specialized agent. If you are unable to delegate or gather more information, provide a comprehensive guide on how to fix the issue using Chrome DevTools, explaining how and why, or suggest any panel/flow that may help.
47
50
 
48
51
  # Considerations
49
- * Determine what is the domain of the question - styling, network, sources, performance or other part of DevTools.
52
+ * Determine what is the domain of the question - styling, network, sources, performance, storage, or other part of DevTools.
50
53
  * For questions about performance (e.g., general performance issues, page speed, performance metrics like LCP, INP, CLS), use performanceRecordAndReload to record a performance trace.
51
54
  * Proactively try to gather additional data. If a specific piece of data can be selected, select it.
52
55
  * Always try to select a single specific context before answering the question.
@@ -141,6 +144,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
141
144
  }
142
145
 
143
146
  let hasCrossOriginRequest = false;
147
+ const requestsToShow: NetworkRequest[] = [];
144
148
  for (const request of Logs.NetworkLog.NetworkLog.instance().requests()) {
145
149
  const documentOrigin = Common.ParsedURL.ParsedURL.extractOrigin(request.documentURL);
146
150
  /**
@@ -163,6 +167,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
163
167
  duration: i18n.TimeUtilities.secondsToString(request.duration),
164
168
  transferSize: i18n.ByteUtilities.formatBytesToKb(request.transferSize),
165
169
  });
170
+ requestsToShow.push(request);
166
171
  }
167
172
 
168
173
  if (requests.length === 0) {
@@ -175,6 +180,12 @@ export class ContextSelectionAgent extends AiAgent<never> {
175
180
 
176
181
  return {
177
182
  result: requests,
183
+ widgets: [{
184
+ name: 'NETWORK_REQUESTS_LIST',
185
+ data: {
186
+ requests: requestsToShow,
187
+ },
188
+ }],
178
189
  };
179
190
  },
180
191
  });
@@ -478,6 +489,45 @@ export class ContextSelectionAgent extends AiAgent<never> {
478
489
  };
479
490
  },
480
491
  });
492
+
493
+ if (Root.Runtime.hostConfig.devToolsAiAssistanceStorageAgent?.enabled) {
494
+ this.declareFunction<Record<string, never>>('analyzeStorage', {
495
+ description:
496
+ 'Selects the page storage. Use this when asked about browser storage (localStorage, sessionStorage, cookies) and issues related to these.',
497
+ parameters: {
498
+ type: Host.AidaClient.ParametersTypes.OBJECT,
499
+ description: '',
500
+ nullable: true,
501
+ required: [],
502
+ properties: {},
503
+ },
504
+ displayInfoFromArgs: () => {
505
+ return {
506
+ title: lockedString('Prepare storage analysis'),
507
+ action: 'analyzeStorage()',
508
+ };
509
+ },
510
+ handler: async () => {
511
+ const allowedOriginResult = this.#allowedOrigin();
512
+ if ('blocked' in allowedOriginResult) {
513
+ return {
514
+ error: 'Cross-origin access blocked due to navigation. Please start a new chat.',
515
+ };
516
+ }
517
+ const origin = allowedOriginResult.origin;
518
+ if (!origin) {
519
+ return {
520
+ error: 'Unable to find page storage.',
521
+ };
522
+ }
523
+
524
+ return {
525
+ context: new StorageContext(new StorageItem(origin, origin)),
526
+ description: 'User selected page storage',
527
+ };
528
+ },
529
+ });
530
+ }
481
531
  }
482
532
 
483
533
  async * handleContextDetails(): AsyncGenerator<ContextResponse, void, void> {
@@ -28,6 +28,8 @@ export interface ExecuteJsAgentOptions extends BaseAgentOptions {
28
28
  execJs?: typeof executeJsCode;
29
29
  }
30
30
 
31
+ // TODO(crbug.com/510206549): De-duplicate this function by migrating AccessibilityAgent to use
32
+ // the registry-based ExecuteJavaScriptTool in tools/ExecuteJavaScript.ts.
31
33
  export function executeJavaScriptFunction(executor: JavascriptExecutor): FunctionDeclaration<
32
34
  {
33
35
  title: string,
@@ -63,12 +63,6 @@ export type MainThreadSectionLabel = 'nav-to-lcp'|'lcp-ttfb'|'lcp-render-delay'|
63
63
  * chrome_preambles.gcl). Sync local changes with the server-side.
64
64
  */
65
65
 
66
- const SECURITY_WARNING = `**CRITICAL CONSTRAINT**: This performance trace was loaded from a file and is static.
67
- You do NOT have access to the live page.
68
- The tool \`getFunctionCode\` is disabled.
69
- Do NOT attempt to use it or instruct the user that you will use it.
70
- Rely only on the trace data and other available tools.`;
71
-
72
66
  const GREEN_DEV_ANNOTATIONS_INSTRUCTIONS = `
73
67
  - CRITICAL: You also have access to functions called addElementAnnotation and addNeworkRequestAnnotation,
74
68
  which should be used to highlight elements and network requests (respectively).
@@ -710,18 +704,14 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
710
704
  }
711
705
  }
712
706
 
713
- const isFresh = Tracing.FreshRecording.Tracker.instance().recordingIsFresh(focus.parsedTrace);
714
-
715
707
  if (!selected.length) {
716
708
  this.#additionalSelectionsForDisclosure = [];
717
- const finalQuery = query;
718
- return isFresh ? finalQuery : `${SECURITY_WARNING}\n\n${finalQuery}`;
709
+ return query;
719
710
  }
720
711
 
721
712
  selected.push(`# User query\n\n${query}`);
722
713
  this.#additionalSelectionsForDisclosure = [...selected];
723
- const finalQuery = selected.join('');
724
- return isFresh ? finalQuery : `${SECURITY_WARNING}\n\n${finalQuery}`;
714
+ return selected.join('');
725
715
  }
726
716
 
727
717
  override async * run(initialQuery: string, options: {
@@ -1340,84 +1330,87 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
1340
1330
  });
1341
1331
  }
1342
1332
 
1343
- if (isFresh) {
1344
- this.declareFunction<{scriptUrl: UrlString, line: number, column: number}, {result: string}>('getFunctionCode', {
1345
- description:
1346
- 'Returns the code for a function defined at the given location. The result is annotated with the runtime performance of each line of code.',
1347
- parameters: {
1348
- type: Host.AidaClient.ParametersTypes.OBJECT,
1349
- description: '',
1350
- nullable: false,
1351
- properties: {
1352
- scriptUrl: {
1353
- type: Host.AidaClient.ParametersTypes.STRING,
1354
- description: 'The url of the function.',
1355
- nullable: false,
1356
- },
1357
- line: {
1358
- type: Host.AidaClient.ParametersTypes.INTEGER,
1359
- description: 'The line number where the function is defined.',
1360
- nullable: false,
1361
- },
1362
- column: {
1363
- type: Host.AidaClient.ParametersTypes.INTEGER,
1364
- description: 'The column number where the function is defined.',
1365
- nullable: false,
1366
- },
1333
+ this.declareFunction<{scriptUrl: UrlString, line: number, column: number}, {result: string}>('getFunctionCode', {
1334
+ description:
1335
+ 'Returns the code for a function defined at the given location. The result is annotated with the runtime performance of each line of code.',
1336
+ parameters: {
1337
+ type: Host.AidaClient.ParametersTypes.OBJECT,
1338
+ description: '',
1339
+ nullable: false,
1340
+ properties: {
1341
+ scriptUrl: {
1342
+ type: Host.AidaClient.ParametersTypes.STRING,
1343
+ description: 'The url of the function.',
1344
+ nullable: false,
1345
+ },
1346
+ line: {
1347
+ type: Host.AidaClient.ParametersTypes.INTEGER,
1348
+ description: 'The line number where the function is defined.',
1349
+ nullable: false,
1350
+ },
1351
+ column: {
1352
+ type: Host.AidaClient.ParametersTypes.INTEGER,
1353
+ description: 'The column number where the function is defined.',
1354
+ nullable: false,
1367
1355
  },
1368
- required: ['scriptUrl', 'line', 'column']
1369
1356
  },
1370
- displayInfoFromArgs: args => {
1357
+ required: ['scriptUrl', 'line', 'column']
1358
+ },
1359
+ displayInfoFromArgs: args => {
1360
+ return {
1361
+ title: lockedString('Looking up function code'),
1362
+ action: `getFunctionCode('${args.scriptUrl}', ${args.line}, ${args.column})`
1363
+ };
1364
+ },
1365
+ handler: async args => {
1366
+ debugLog('Function call: getFunctionCode');
1367
+ if (!isFresh) {
1371
1368
  return {
1372
- title: lockedString('Looking up function code'),
1373
- action: `getFunctionCode('${args.scriptUrl}', ${args.line}, ${args.column})`
1369
+ error: 'Cannot use this tool on an imported file.',
1374
1370
  };
1375
- },
1376
- handler: async args => {
1377
- debugLog('Function call: getFunctionCode');
1371
+ }
1378
1372
 
1379
- if (args.line === undefined) {
1380
- return {error: 'Missing arg: line'};
1381
- }
1373
+ if (args.line === undefined) {
1374
+ return {error: 'Missing arg: line'};
1375
+ }
1382
1376
 
1383
- if (args.column === undefined) {
1384
- return {error: 'Missing arg: column'};
1385
- }
1377
+ if (args.column === undefined) {
1378
+ return {error: 'Missing arg: column'};
1379
+ }
1386
1380
 
1387
- if (!this.#formatter) {
1388
- throw new Error('missing formatter');
1389
- }
1381
+ if (!this.#formatter) {
1382
+ throw new Error('missing formatter');
1383
+ }
1390
1384
 
1391
- const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
1392
- if (!target) {
1393
- throw new Error('missing target');
1394
- }
1385
+ const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
1386
+ if (!target) {
1387
+ throw new Error('missing target');
1388
+ }
1395
1389
 
1396
- const url = args.scriptUrl as Platform.DevToolsPath.UrlString;
1397
- const code = await this.#formatter.resolveFunctionCodeAtLocation(url, args.line, args.column);
1398
- if (!code) {
1399
- return {error: 'Could not find code'};
1400
- }
1390
+ const url = args.scriptUrl as Platform.DevToolsPath.UrlString;
1391
+ const code = await this.#formatter.resolveFunctionCodeAtLocation(url, args.line, args.column);
1392
+ if (!code) {
1393
+ return {error: 'Could not find code'};
1394
+ }
1401
1395
 
1402
- const result = this.#formatter.formatFunctionCode(code);
1396
+ const result = this.#formatter.formatFunctionCode(code);
1403
1397
 
1404
- const key = `getFunctionCode('${args.scriptUrl}', ${args.line}, ${args.column})`;
1405
- this.#cacheFunctionResult(focus, key, result);
1406
- return {
1407
- result: {result},
1408
- widgets: [{
1409
- name: 'SOURCE_CODE',
1410
- data: {
1411
- url: args.scriptUrl,
1412
- line: args.line,
1413
- column: args.column,
1414
- code: code.code,
1415
- },
1416
- }],
1417
- };
1418
- },
1419
- });
1420
- }
1398
+ const key = `getFunctionCode('${args.scriptUrl}', ${args.line}, ${args.column})`;
1399
+ this.#cacheFunctionResult(focus, key, result);
1400
+ return {
1401
+ result: {result},
1402
+ widgets: [{
1403
+ name: 'SOURCE_CODE',
1404
+ data: {
1405
+ url: args.scriptUrl,
1406
+ line: args.line,
1407
+ column: args.column,
1408
+ code: code.code,
1409
+ },
1410
+ }],
1411
+ };
1412
+ },
1413
+ });
1421
1414
 
1422
1415
  const isTraceApp = Root.Runtime.Runtime.isTraceApp();
1423
1416
 
@@ -173,18 +173,17 @@ export class StorageAgent extends AiAgent<StorageItem> {
173
173
  },
174
174
  });
175
175
 
176
- this.declareFunction<
177
- {
178
- type: 'localStorage' | 'sessionStorage',
179
- origin: string,
180
- storageKey?: string,
181
- },
182
- {
183
- partitions: Array<{
184
- storageKey: string,
185
- keys: string[],
186
- }>,
187
- }>('listStorageKeys', {
176
+ this.declareFunction<{
177
+ type: 'localStorage' | 'sessionStorage',
178
+ origin: string,
179
+ storageKey?: string,
180
+ },
181
+ {
182
+ partitions: Array<{
183
+ storageKey: string,
184
+ keys: string[],
185
+ }>,
186
+ }>('listStorageKeys', {
188
187
  description:
189
188
  'Lists all keys for a given storage type for the requested origin. Returns keys grouped by storage partition.',
190
189
  parameters: {
@@ -218,6 +217,7 @@ export class StorageAgent extends AiAgent<StorageItem> {
218
217
  },
219
218
 
220
219
  handler: async args => {
220
+ this.disableServerSideLogging();
221
221
  if (!isSamePrimaryPageOrigin(this.context)) {
222
222
  return {error: 'No origin available or not allowed.'};
223
223
  }
@@ -244,19 +244,18 @@ export class StorageAgent extends AiAgent<StorageItem> {
244
244
  },
245
245
  });
246
246
 
247
- this.declareFunction<
248
- {
249
- type: 'localStorage' | 'sessionStorage',
250
- keys: string[],
251
- origin: string,
252
- storageKey?: string,
253
- },
254
- {
255
- items: Array<{
256
- storageKey: string,
257
- values: Record<string, string>,
258
- }>,
259
- }>('getStorageValues', {
247
+ this.declareFunction<{
248
+ type: 'localStorage' | 'sessionStorage',
249
+ keys: string[],
250
+ origin: string,
251
+ storageKey?: string,
252
+ },
253
+ {
254
+ items: Array<{
255
+ storageKey: string,
256
+ values: Record<string, string>,
257
+ }>,
258
+ }>('getStorageValues', {
260
259
  description: 'Retrieve specific string values from storage partitions for requested keys.',
261
260
  parameters: {
262
261
  type: Host.AidaClient.ParametersTypes.OBJECT,
@@ -296,6 +295,7 @@ export class StorageAgent extends AiAgent<StorageItem> {
296
295
  },
297
296
 
298
297
  handler: async (args, options) => {
298
+ this.disableServerSideLogging();
299
299
  if (!isSamePrimaryPageOrigin(this.context)) {
300
300
  return {error: 'No origin available or not allowed.'};
301
301
  }
@@ -353,11 +353,10 @@ export class StorageAgent extends AiAgent<StorageItem> {
353
353
  },
354
354
  });
355
355
 
356
- this.declareFunction<
357
- {
358
- origin: string,
359
- },
360
- {cookies: string[]}>('listCookies', {
356
+ this.declareFunction<{
357
+ origin: string,
358
+ },
359
+ {cookies: string[]}>('listCookies', {
361
360
  description: 'Lists all cookies for the requested origin, strictly excluding their values.',
362
361
  parameters: {
363
362
  type: Host.AidaClient.ParametersTypes.OBJECT,
@@ -379,6 +378,7 @@ export class StorageAgent extends AiAgent<StorageItem> {
379
378
  };
380
379
  },
381
380
  handler: async args => {
381
+ this.disableServerSideLogging();
382
382
  if (!isSamePrimaryPageOrigin(this.context)) {
383
383
  return {error: 'No origin available or not allowed.'};
384
384
  }
@@ -396,14 +396,13 @@ export class StorageAgent extends AiAgent<StorageItem> {
396
396
  },
397
397
  });
398
398
 
399
- this.declareFunction<
400
- {
401
- cookieNames: string[],
402
- origin: string,
403
- },
404
- {
405
- cookies: CookieDetails[],
406
- }>('getCookieValues', {
399
+ this.declareFunction<{
400
+ cookieNames: string[],
401
+ origin: string,
402
+ },
403
+ {
404
+ cookies: CookieDetails[],
405
+ }>('getCookieValues', {
407
406
  description: 'Retrieve the values and detailed metadata of specific cookies by their names.',
408
407
  parameters: {
409
408
  type: Host.AidaClient.ParametersTypes.OBJECT,
@@ -431,6 +430,7 @@ export class StorageAgent extends AiAgent<StorageItem> {
431
430
  };
432
431
  },
433
432
  handler: async (args, options) => {
433
+ this.disableServerSideLogging();
434
434
  if (!isSamePrimaryPageOrigin(this.context)) {
435
435
  return {error: 'No origin available or not allowed.'};
436
436
  }
@@ -498,6 +498,15 @@ export class StorageAgent extends AiAgent<StorageItem> {
498
498
  return primaryTargetOrigin;
499
499
  }
500
500
 
501
+ protected override async preRun(): Promise<void> {
502
+ const item = this.context?.getItem();
503
+ if (item instanceof CookieItem && Boolean(item.name)) {
504
+ this.disableServerSideLogging();
505
+ } else if (item instanceof DOMStorageItem && Boolean(item.key)) {
506
+ this.disableServerSideLogging();
507
+ }
508
+ }
509
+
501
510
  async *
502
511
  handleContextDetails(context: ConversationContext<StorageItem>|null):
503
512
  AsyncGenerator<ContextResponse, void, void> {