chrome-devtools-frontend 1.0.1642845 → 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/SECURITY.md +1 -0
- package/front_end/core/host/UserMetrics.ts +2 -1
- package/front_end/core/protocol_client/InspectorBackend.ts +4 -0
- package/front_end/core/sdk/CSSMatchedStyles.ts +55 -26
- package/front_end/core/sdk/CSSRule.ts +1 -0
- package/front_end/core/sdk/DebuggerModel.ts +5 -0
- package/front_end/entrypoints/greendev_floaty/FloatyEntrypoint.ts +4 -3
- package/front_end/entrypoints/greendev_floaty/greendev_floaty.ts +4 -3
- 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 +100 -18
- package/front_end/models/ai_assistance/AiConversation.ts +18 -14
- 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/README.md +8 -0
- package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +65 -40
- package/front_end/models/ai_assistance/agents/AiAgent.ts +37 -6
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.snapshot.txt +11 -0
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +55 -5
- package/front_end/models/ai_assistance/agents/ExecuteJavascript.ts +2 -0
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +119 -78
- package/front_end/models/ai_assistance/agents/StorageAgent.ts +47 -38
- package/front_end/models/ai_assistance/agents/StylingAgent.snapshot.txt +0 -25
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +46 -326
- package/front_end/models/ai_assistance/ai_assistance.ts +14 -4
- package/front_end/models/ai_assistance/contexts/DOMNodeContext.snapshot.txt +51 -0
- package/front_end/models/ai_assistance/contexts/DOMNodeContext.ts +200 -0
- package/front_end/models/ai_assistance/skills/styling.md +44 -2
- package/front_end/models/ai_assistance/tools/ExecuteJavaScript.ts +140 -0
- package/front_end/models/ai_assistance/tools/GetStyles.ts +141 -0
- package/front_end/models/ai_assistance/tools/Tool.ts +64 -0
- package/front_end/models/ai_assistance/tools/ToolRegistry.ts +36 -0
- package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +5 -7
- package/front_end/models/lighthouse/LighthouseReporterTypes.ts +5 -0
- package/front_end/models/live-metrics/LiveMetrics.ts +24 -13
- package/front_end/models/stack_trace/DetailedErrorStackParser.ts +2 -2
- package/front_end/models/stack_trace/StackTrace.ts +4 -1
- package/front_end/models/stack_trace/StackTraceImpl.ts +9 -2
- package/front_end/models/stack_trace/StackTraceModel.ts +17 -4
- package/front_end/models/stack_trace/Trie.ts +1 -1
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +25 -22
- package/front_end/panels/ai_assistance/ai_assistance-meta.ts +16 -0
- package/front_end/panels/ai_assistance/components/ChatInput.ts +2 -2
- 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/DOMStorageItemsView.ts +4 -0
- package/front_end/panels/application/KeyValueStorageItemsView.ts +39 -7
- 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/common/ExtensionServer.ts +26 -15
- package/front_end/panels/console/SymbolizedErrorWidget.ts +73 -22
- package/front_end/panels/elements/StandaloneStylesContainer.ts +1 -1
- package/front_end/panels/elements/StylePropertiesSection.ts +8 -0
- package/front_end/panels/elements/StylePropertyHighlighter.ts +4 -2
- package/front_end/panels/elements/StylePropertyTreeElement.ts +6 -5
- package/front_end/panels/elements/StylesContainer.ts +1 -1
- package/front_end/panels/elements/StylesSidebarPane.ts +4 -4
- package/front_end/panels/layer_viewer/PaintProfilerView.ts +106 -132
- package/front_end/panels/lighthouse/LighthousePanel.ts +4 -3
- package/front_end/panels/network/NetworkLogView.ts +8 -1
- package/front_end/panels/network/networkLogView.css +0 -15
- 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/legacy/components/cookie_table/CookiesTable.ts +36 -3
- package/front_end/ui/legacy/components/data_grid/dataGridAiButton.css +20 -0
- package/front_end/ui/legacy/components/utils/Linkifier.ts +19 -4
- package/front_end/ui/visual_logging/KnownContextValues.ts +3 -0
- package/mcp/mcp.ts +1 -0
- package/package.json +1 -1
|
@@ -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';
|
|
@@ -13,7 +14,9 @@ import * as NetworkTimeCalculator from '../../network_time_calculator/network_ti
|
|
|
13
14
|
import type * as Trace from '../../trace/trace.js';
|
|
14
15
|
import * as Workspace from '../../workspace/workspace.js';
|
|
15
16
|
import {isOpaqueOrigin} from '../AiOrigins.js';
|
|
17
|
+
import {DOMNodeContext} from '../contexts/DOMNodeContext.js';
|
|
16
18
|
import {debugLog} from '../debug.js';
|
|
19
|
+
import {StorageItem} from '../StorageItem.js';
|
|
17
20
|
|
|
18
21
|
import {AccessibilityContext} from './AccessibilityAgent.js';
|
|
19
22
|
import {
|
|
@@ -26,7 +29,7 @@ import {
|
|
|
26
29
|
import {FileContext} from './FileAgent.js';
|
|
27
30
|
import {RequestContext} from './NetworkAgent.js';
|
|
28
31
|
import {PerformanceTraceContext} from './PerformanceAgent.js';
|
|
29
|
-
import {
|
|
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
|
});
|
|
@@ -469,7 +480,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
469
480
|
const node = await this.#onInspectElement();
|
|
470
481
|
if (node) {
|
|
471
482
|
return {
|
|
472
|
-
context: new
|
|
483
|
+
context: new DOMNodeContext(node),
|
|
473
484
|
description: 'User selected an element',
|
|
474
485
|
};
|
|
475
486
|
}
|
|
@@ -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,
|
|
@@ -239,7 +239,6 @@ export class PerformanceTraceContext extends ConversationContext<AgentFocus> {
|
|
|
239
239
|
}
|
|
240
240
|
|
|
241
241
|
#focus: AgentFocus;
|
|
242
|
-
external = false;
|
|
243
242
|
|
|
244
243
|
constructor(focus: AgentFocus) {
|
|
245
244
|
super();
|
|
@@ -456,7 +455,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
456
455
|
* so we can show it in the disclosure UI. This is cleared and then populated
|
|
457
456
|
* on each prompt.
|
|
458
457
|
*/
|
|
459
|
-
#
|
|
458
|
+
#additionalSelectionsForDisclosure: string[] = [];
|
|
460
459
|
|
|
461
460
|
get clientFeature(): Host.AidaClient.ClientFeature {
|
|
462
461
|
return Host.AidaClient.ClientFeature.CHROME_PERFORMANCE_FULL_AGENT;
|
|
@@ -490,7 +489,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
490
489
|
}
|
|
491
490
|
contextDisclosure.push(fact.text);
|
|
492
491
|
}
|
|
493
|
-
contextDisclosure.push(...this.#
|
|
492
|
+
contextDisclosure.push(...this.#additionalSelectionsForDisclosure);
|
|
494
493
|
|
|
495
494
|
const focus = context.getItem();
|
|
496
495
|
const widgets = this.#getWidgetsForFocus(focus);
|
|
@@ -705,12 +704,13 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
705
704
|
}
|
|
706
705
|
}
|
|
707
706
|
|
|
708
|
-
this.#additionalSelectionsForQuery = selected;
|
|
709
707
|
if (!selected.length) {
|
|
708
|
+
this.#additionalSelectionsForDisclosure = [];
|
|
710
709
|
return query;
|
|
711
710
|
}
|
|
712
711
|
|
|
713
712
|
selected.push(`# User query\n\n${query}`);
|
|
713
|
+
this.#additionalSelectionsForDisclosure = [...selected];
|
|
714
714
|
return selected.join('');
|
|
715
715
|
}
|
|
716
716
|
|
|
@@ -818,9 +818,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
818
818
|
async #addFacts(context: PerformanceTraceContext): Promise<void> {
|
|
819
819
|
const focus = context.getItem();
|
|
820
820
|
|
|
821
|
-
|
|
822
|
-
this.addFact(this.#notExternalExtraPreambleFact);
|
|
823
|
-
}
|
|
821
|
+
this.addFact(this.#notExternalExtraPreambleFact);
|
|
824
822
|
|
|
825
823
|
const annotationsEnabled = Annotations.AnnotationRepository.annotationsEnabled();
|
|
826
824
|
if (annotationsEnabled) {
|
|
@@ -847,7 +845,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
847
845
|
this.#formatter = new PerformanceTraceFormatter(focus);
|
|
848
846
|
this.#formatter.resolveFunctionCode =
|
|
849
847
|
async (url: Platform.DevToolsPath.UrlString, line: number, column: number) => {
|
|
850
|
-
if (!target) {
|
|
848
|
+
if (!target || !isFresh) {
|
|
851
849
|
return null;
|
|
852
850
|
}
|
|
853
851
|
|
|
@@ -932,6 +930,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
932
930
|
#declareFunctions(context: PerformanceTraceContext): void {
|
|
933
931
|
const focus = context.getItem();
|
|
934
932
|
const {parsedTrace} = focus;
|
|
933
|
+
const isFresh = Tracing.FreshRecording.Tracker.instance().recordingIsFresh(parsedTrace);
|
|
935
934
|
|
|
936
935
|
this.declareFunction<{insightSetId: string, insightName: string}, {details: string}>('getInsightDetails', {
|
|
937
936
|
description:
|
|
@@ -1070,35 +1069,7 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
1070
1069
|
}
|
|
1071
1070
|
|
|
1072
1071
|
// TODO(b/425270067): Format in the same way that "Summary" detail tab does.
|
|
1073
|
-
|
|
1074
|
-
if (Trace.Types.Events.isSyntheticNetworkRequest(event)) {
|
|
1075
|
-
const eventToSerialize = {
|
|
1076
|
-
...event,
|
|
1077
|
-
args: {
|
|
1078
|
-
...event.args,
|
|
1079
|
-
data: {
|
|
1080
|
-
...event.args.data,
|
|
1081
|
-
responseHeaders: event.args.data.responseHeaders ? sanitizeHeaders(event.args.data.responseHeaders) :
|
|
1082
|
-
null,
|
|
1083
|
-
},
|
|
1084
|
-
},
|
|
1085
|
-
};
|
|
1086
|
-
details = JSON.stringify(eventToSerialize);
|
|
1087
|
-
} else if (Trace.Types.Events.isResourceReceiveResponse(event)) {
|
|
1088
|
-
const eventToSerialize = {
|
|
1089
|
-
...event,
|
|
1090
|
-
args: {
|
|
1091
|
-
...event.args,
|
|
1092
|
-
data: {
|
|
1093
|
-
...event.args.data,
|
|
1094
|
-
headers: event.args.data.headers ? sanitizeHeaders(event.args.data.headers) : undefined,
|
|
1095
|
-
},
|
|
1096
|
-
},
|
|
1097
|
-
};
|
|
1098
|
-
details = JSON.stringify(eventToSerialize);
|
|
1099
|
-
} else {
|
|
1100
|
-
details = JSON.stringify(event);
|
|
1101
|
-
}
|
|
1072
|
+
const details = formatEventForAI(event);
|
|
1102
1073
|
|
|
1103
1074
|
const key = `getEventByKey('${params.eventKey}')`;
|
|
1104
1075
|
this.#cacheFunctionResult(focus, key, details);
|
|
@@ -1393,6 +1364,11 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
1393
1364
|
},
|
|
1394
1365
|
handler: async args => {
|
|
1395
1366
|
debugLog('Function call: getFunctionCode');
|
|
1367
|
+
if (!isFresh) {
|
|
1368
|
+
return {
|
|
1369
|
+
error: 'Cannot use this tool on an imported file.',
|
|
1370
|
+
};
|
|
1371
|
+
}
|
|
1396
1372
|
|
|
1397
1373
|
if (args.line === undefined) {
|
|
1398
1374
|
return {error: 'Missing arg: line'};
|
|
@@ -1436,7 +1412,6 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
1436
1412
|
},
|
|
1437
1413
|
});
|
|
1438
1414
|
|
|
1439
|
-
const isFresh = Tracing.FreshRecording.Tracker.instance().recordingIsFresh(parsedTrace);
|
|
1440
1415
|
const isTraceApp = Root.Runtime.Runtime.isTraceApp();
|
|
1441
1416
|
|
|
1442
1417
|
this.declareFunction<{url: UrlString}, {content: string}>('getResourceContent', {
|
|
@@ -1502,48 +1477,46 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
1502
1477
|
},
|
|
1503
1478
|
});
|
|
1504
1479
|
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
nullable: false,
|
|
1518
|
-
}
|
|
1519
|
-
},
|
|
1520
|
-
required: ['eventKey']
|
|
1521
|
-
},
|
|
1522
|
-
displayInfoFromArgs: params => {
|
|
1523
|
-
return {title: lockedString('Selecting event'), action: `selectEventByKey('${params.eventKey}')`};
|
|
1524
|
-
},
|
|
1525
|
-
handler: async params => {
|
|
1526
|
-
debugLog('Function call: selectEventByKey', params);
|
|
1527
|
-
const event = focus.lookupEvent(params.eventKey);
|
|
1528
|
-
if (!event) {
|
|
1529
|
-
return {error: 'Invalid eventKey'};
|
|
1480
|
+
this.declareFunction<{eventKey: string}, {success: boolean}>('selectEventByKey', {
|
|
1481
|
+
description:
|
|
1482
|
+
'Selects the event in the flamechart for the user. If the user asks to show them something, it\'s likely a good idea to call this function.',
|
|
1483
|
+
parameters: {
|
|
1484
|
+
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
1485
|
+
description: '',
|
|
1486
|
+
nullable: false,
|
|
1487
|
+
properties: {
|
|
1488
|
+
eventKey: {
|
|
1489
|
+
type: Host.AidaClient.ParametersTypes.STRING,
|
|
1490
|
+
description: 'The key for the event.',
|
|
1491
|
+
nullable: false,
|
|
1530
1492
|
}
|
|
1531
|
-
|
|
1532
|
-
const revealable = new SDK.TraceObject.RevealableEvent(event);
|
|
1533
|
-
await Common.Revealer.reveal(revealable);
|
|
1534
|
-
return {
|
|
1535
|
-
result: {success: true},
|
|
1536
|
-
widgets: [{
|
|
1537
|
-
name: 'TIMELINE_EVENT_SUMMARY',
|
|
1538
|
-
data: {
|
|
1539
|
-
event,
|
|
1540
|
-
parsedTrace,
|
|
1541
|
-
},
|
|
1542
|
-
}],
|
|
1543
|
-
};
|
|
1544
1493
|
},
|
|
1545
|
-
|
|
1546
|
-
|
|
1494
|
+
required: ['eventKey']
|
|
1495
|
+
},
|
|
1496
|
+
displayInfoFromArgs: params => {
|
|
1497
|
+
return {title: lockedString('Selecting event'), action: `selectEventByKey('${params.eventKey}')`};
|
|
1498
|
+
},
|
|
1499
|
+
handler: async params => {
|
|
1500
|
+
debugLog('Function call: selectEventByKey', params);
|
|
1501
|
+
const event = focus.lookupEvent(params.eventKey);
|
|
1502
|
+
if (!event) {
|
|
1503
|
+
return {error: 'Invalid eventKey'};
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
const revealable = new SDK.TraceObject.RevealableEvent(event);
|
|
1507
|
+
await Common.Revealer.reveal(revealable);
|
|
1508
|
+
return {
|
|
1509
|
+
result: {success: true},
|
|
1510
|
+
widgets: [{
|
|
1511
|
+
name: 'TIMELINE_EVENT_SUMMARY',
|
|
1512
|
+
data: {
|
|
1513
|
+
event,
|
|
1514
|
+
parsedTrace,
|
|
1515
|
+
},
|
|
1516
|
+
}],
|
|
1517
|
+
};
|
|
1518
|
+
},
|
|
1519
|
+
});
|
|
1547
1520
|
}
|
|
1548
1521
|
|
|
1549
1522
|
#getBoundsForLabel(label: MainThreadSectionLabel, focus: AgentFocus): Trace.Types.Timing.TraceWindowMicro|null {
|
|
@@ -1669,3 +1642,71 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
1669
1642
|
return undefined;
|
|
1670
1643
|
}
|
|
1671
1644
|
}
|
|
1645
|
+
|
|
1646
|
+
/**
|
|
1647
|
+
* Serializes a trace event to a JSON string for AI consumption,
|
|
1648
|
+
* ensuring sensitive data (like headers and raw script source code)
|
|
1649
|
+
* is sanitized or redacted.
|
|
1650
|
+
*/
|
|
1651
|
+
function formatEventForAI(event: Trace.Types.Events.Event): string {
|
|
1652
|
+
if (Trace.Types.Events.isSyntheticNetworkRequest(event)) {
|
|
1653
|
+
return JSON.stringify({
|
|
1654
|
+
...event,
|
|
1655
|
+
args: {
|
|
1656
|
+
...event.args,
|
|
1657
|
+
data: {
|
|
1658
|
+
...event.args.data,
|
|
1659
|
+
responseHeaders: event.args.data.responseHeaders ? sanitizeHeaders(event.args.data.responseHeaders) : null,
|
|
1660
|
+
},
|
|
1661
|
+
},
|
|
1662
|
+
});
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
if (Trace.Types.Events.isResourceReceiveResponse(event)) {
|
|
1666
|
+
return JSON.stringify({
|
|
1667
|
+
...event,
|
|
1668
|
+
args: {
|
|
1669
|
+
...event.args,
|
|
1670
|
+
data: {
|
|
1671
|
+
...event.args.data,
|
|
1672
|
+
headers: event.args.data.headers ? sanitizeHeaders(event.args.data.headers) : undefined,
|
|
1673
|
+
},
|
|
1674
|
+
},
|
|
1675
|
+
});
|
|
1676
|
+
}
|
|
1677
|
+
|
|
1678
|
+
if (Trace.Types.Events.isRundownScriptSource(event)) {
|
|
1679
|
+
// Redact sensitive cross-origin script source text.
|
|
1680
|
+
const safeData: Omit<Trace.Types.Events.RundownScriptSource['args']['data'], 'sourceText'> = {
|
|
1681
|
+
isolate: event.args.data.isolate,
|
|
1682
|
+
scriptId: event.args.data.scriptId,
|
|
1683
|
+
length: event.args.data.length,
|
|
1684
|
+
};
|
|
1685
|
+
return JSON.stringify({
|
|
1686
|
+
...event,
|
|
1687
|
+
args: {
|
|
1688
|
+
...event.args,
|
|
1689
|
+
data: safeData,
|
|
1690
|
+
},
|
|
1691
|
+
});
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
if (Trace.Types.Events.isRundownScriptSourceLarge(event)) {
|
|
1695
|
+
// Redact sensitive cross-origin script source text.
|
|
1696
|
+
const safeData: Omit<Trace.Types.Events.RundownScriptSourceLarge['args']['data'], 'sourceText'> = {
|
|
1697
|
+
isolate: event.args.data.isolate,
|
|
1698
|
+
scriptId: event.args.data.scriptId,
|
|
1699
|
+
splitIndex: event.args.data.splitIndex,
|
|
1700
|
+
splitCount: event.args.data.splitCount,
|
|
1701
|
+
};
|
|
1702
|
+
return JSON.stringify({
|
|
1703
|
+
...event,
|
|
1704
|
+
args: {
|
|
1705
|
+
...event.args,
|
|
1706
|
+
data: safeData,
|
|
1707
|
+
},
|
|
1708
|
+
});
|
|
1709
|
+
}
|
|
1710
|
+
|
|
1711
|
+
return JSON.stringify(event);
|
|
1712
|
+
}
|
|
@@ -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> {
|
|
@@ -1,28 +1,3 @@
|
|
|
1
|
-
Title: StylingAgent describeElement should describe an element with no children, siblings, or parent
|
|
2
|
-
Content:
|
|
3
|
-
* Element's uid is 99.
|
|
4
|
-
* Its selector is `div#myElement`
|
|
5
|
-
=== end content
|
|
6
|
-
|
|
7
|
-
Title: StylingAgent describeElement should describe an element with child element and text nodes
|
|
8
|
-
Content:
|
|
9
|
-
* Element's uid is 99.
|
|
10
|
-
* Its selector is `div#parentElement`
|
|
11
|
-
* It has 2 child element nodes: `span.child1` (uid=undefined), `span.child2` (uid=undefined)
|
|
12
|
-
* It only has 1 child text node
|
|
13
|
-
=== end content
|
|
14
|
-
|
|
15
|
-
Title: StylingAgent describeElement should describe an element with siblings and a parent
|
|
16
|
-
Content:
|
|
17
|
-
* Element's uid is 99.
|
|
18
|
-
* Its selector is `div#parentElement`
|
|
19
|
-
* It has a next sibling and it is an element (uid=undefined) node
|
|
20
|
-
* It has a previous sibling and it is a non element node
|
|
21
|
-
* Its parent's selector is `div#grandparentElement` (uid=undefined)
|
|
22
|
-
* Its parent is a non element node
|
|
23
|
-
* Its parent has only 1 child element node
|
|
24
|
-
* Its parent has only 1 child text node
|
|
25
|
-
=== end content
|
|
26
1
|
|
|
27
2
|
Title: StylingAgent buildRequest structure matches the snapshot
|
|
28
3
|
Content:
|