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.
- package/front_end/core/protocol_client/InspectorBackend.ts +4 -0
- package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +4 -5
- package/front_end/generated/InspectorBackendCommands.ts +1 -1
- package/front_end/generated/protocol.ts +7 -0
- package/front_end/models/ai_assistance/AiAgent2.ts +23 -5
- package/front_end/models/ai_assistance/AiConversation.ts +15 -12
- package/front_end/models/ai_assistance/AiUtils.ts +71 -0
- package/front_end/models/ai_assistance/ChangeManager.ts +2 -5
- package/front_end/models/ai_assistance/{agents/ConversationSummaryAgent.ts → ConversationSummary.ts} +29 -66
- package/front_end/models/ai_assistance/ExtensionScope.ts +1 -4
- package/front_end/models/ai_assistance/{agents/PerformanceAnnotationsAgent.ts → PerformanceAnnotations.ts} +47 -89
- package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +31 -21
- package/front_end/models/ai_assistance/agents/AiAgent.ts +21 -6
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.snapshot.txt +11 -0
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +53 -3
- package/front_end/models/ai_assistance/agents/ExecuteJavascript.ts +2 -0
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +72 -79
- package/front_end/models/ai_assistance/agents/StorageAgent.ts +47 -38
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +22 -21
- package/front_end/models/ai_assistance/ai_assistance.ts +6 -4
- package/front_end/models/ai_assistance/skills/styling.md +12 -4
- package/front_end/models/ai_assistance/tools/ExecuteJavaScript.ts +140 -0
- package/front_end/models/ai_assistance/tools/GetStyles.ts +6 -2
- package/front_end/models/ai_assistance/tools/Tool.ts +10 -1
- package/front_end/models/ai_assistance/tools/ToolRegistry.ts +2 -0
- package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +5 -7
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +6 -7
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +96 -4
- package/front_end/panels/ai_assistance/components/chatMessage.css +6 -0
- package/front_end/panels/application/components/AdsView.ts +219 -0
- package/front_end/panels/application/components/adsView.css +54 -0
- package/front_end/panels/application/components/components.ts +2 -0
- package/front_end/panels/console/SymbolizedErrorWidget.ts +73 -22
- package/front_end/panels/network/NetworkLogView.ts +5 -1
- package/front_end/panels/timeline/overlays/components/EntryLabelOverlay.ts +5 -4
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/lighthouse/README.chromium +2 -2
- package/front_end/third_party/lighthouse/lighthouse-dt-bundle.js +1607 -5733
- package/front_end/third_party/lighthouse/locales/ar-XB.json +290 -65
- package/front_end/third_party/lighthouse/locales/ar.json +290 -65
- package/front_end/third_party/lighthouse/locales/bg.json +290 -65
- package/front_end/third_party/lighthouse/locales/ca.json +295 -70
- package/front_end/third_party/lighthouse/locales/cs.json +290 -65
- package/front_end/third_party/lighthouse/locales/da.json +294 -69
- package/front_end/third_party/lighthouse/locales/de.json +295 -70
- package/front_end/third_party/lighthouse/locales/el.json +290 -65
- package/front_end/third_party/lighthouse/locales/en-GB.json +290 -65
- package/front_end/third_party/lighthouse/locales/en-US.json +79 -67
- package/front_end/third_party/lighthouse/locales/en-XA.json +253 -64
- package/front_end/third_party/lighthouse/locales/en-XL.json +79 -67
- package/front_end/third_party/lighthouse/locales/es-419.json +290 -65
- package/front_end/third_party/lighthouse/locales/es.json +298 -73
- package/front_end/third_party/lighthouse/locales/fi.json +290 -65
- package/front_end/third_party/lighthouse/locales/fil.json +290 -65
- package/front_end/third_party/lighthouse/locales/fr.json +294 -69
- package/front_end/third_party/lighthouse/locales/he.json +293 -68
- package/front_end/third_party/lighthouse/locales/hi.json +291 -66
- package/front_end/third_party/lighthouse/locales/hr.json +290 -65
- package/front_end/third_party/lighthouse/locales/hu.json +290 -65
- package/front_end/third_party/lighthouse/locales/id.json +290 -65
- package/front_end/third_party/lighthouse/locales/it.json +294 -69
- package/front_end/third_party/lighthouse/locales/ja.json +290 -65
- package/front_end/third_party/lighthouse/locales/ko.json +290 -65
- package/front_end/third_party/lighthouse/locales/lt.json +290 -65
- package/front_end/third_party/lighthouse/locales/lv.json +290 -65
- package/front_end/third_party/lighthouse/locales/nl.json +290 -65
- package/front_end/third_party/lighthouse/locales/no.json +290 -65
- package/front_end/third_party/lighthouse/locales/pl.json +290 -65
- package/front_end/third_party/lighthouse/locales/pt-PT.json +291 -66
- package/front_end/third_party/lighthouse/locales/pt.json +290 -65
- package/front_end/third_party/lighthouse/locales/ro.json +290 -65
- package/front_end/third_party/lighthouse/locales/ru.json +301 -76
- package/front_end/third_party/lighthouse/locales/sk.json +291 -66
- package/front_end/third_party/lighthouse/locales/sl.json +290 -65
- package/front_end/third_party/lighthouse/locales/sr-Latn.json +290 -65
- package/front_end/third_party/lighthouse/locales/sr.json +290 -65
- package/front_end/third_party/lighthouse/locales/sv.json +297 -72
- package/front_end/third_party/lighthouse/locales/ta.json +291 -66
- package/front_end/third_party/lighthouse/locales/te.json +293 -68
- package/front_end/third_party/lighthouse/locales/th.json +291 -66
- package/front_end/third_party/lighthouse/locales/tr.json +290 -65
- package/front_end/third_party/lighthouse/locales/uk.json +290 -65
- package/front_end/third_party/lighthouse/locales/vi.json +291 -66
- package/front_end/third_party/lighthouse/locales/zh-HK.json +292 -67
- package/front_end/third_party/lighthouse/locales/zh-TW.json +291 -66
- package/front_end/third_party/lighthouse/locales/zh.json +291 -66
- package/front_end/third_party/lighthouse/report/bundle.d.ts +6 -6
- package/front_end/third_party/lighthouse/report/bundle.js +4 -7
- package/front_end/third_party/lighthouse/report-assets/report-generator.mjs +2 -2
- package/front_end/ui/legacy/Widget.ts +32 -8
- package/front_end/ui/visual_logging/KnownContextValues.ts +2 -0
- package/mcp/mcp.ts +1 -0
- 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
|
-
|
|
138
|
-
|
|
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
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
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
|
-
|
|
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
|
-
|
|
371
|
-
|
|
372
|
-
|
|
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
|
-
|
|
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
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1373
|
+
if (args.line === undefined) {
|
|
1374
|
+
return {error: 'Missing arg: line'};
|
|
1375
|
+
}
|
|
1382
1376
|
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1377
|
+
if (args.column === undefined) {
|
|
1378
|
+
return {error: 'Missing arg: column'};
|
|
1379
|
+
}
|
|
1386
1380
|
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1381
|
+
if (!this.#formatter) {
|
|
1382
|
+
throw new Error('missing formatter');
|
|
1383
|
+
}
|
|
1390
1384
|
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1385
|
+
const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
|
|
1386
|
+
if (!target) {
|
|
1387
|
+
throw new Error('missing target');
|
|
1388
|
+
}
|
|
1395
1389
|
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
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
|
-
|
|
1396
|
+
const result = this.#formatter.formatFunctionCode(code);
|
|
1403
1397
|
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
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
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
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
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
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
|
-
|
|
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
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
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> {
|