chrome-devtools-frontend 1.0.1642899 → 1.0.1643855
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/eslint.config.mjs +3 -1
- package/extension-api/ExtensionAPI.d.ts +83 -12
- package/front_end/core/host/UserMetrics.ts +0 -1
- package/front_end/core/protocol_client/InspectorBackend.ts +4 -0
- package/front_end/core/root/ExperimentNames.ts +0 -1
- package/front_end/core/sdk/ConsoleModel.ts +4 -0
- package/front_end/core/sdk/NetworkRequest.ts +12 -0
- package/front_end/core/sdk/SourceMap.ts +15 -18
- package/front_end/entrypoints/greendev_floaty/FloatyEntrypoint.ts +0 -2
- package/front_end/entrypoints/greendev_floaty/greendev_floaty.ts +0 -2
- package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +4 -5
- package/front_end/entrypoints/main/MainImpl.ts +0 -6
- package/front_end/generated/InspectorBackendCommands.ts +1 -1
- package/front_end/generated/protocol.ts +7 -0
- package/front_end/models/ai_assistance/AiAgent2.ts +24 -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 +47 -31
- package/front_end/models/ai_assistance/agents/AiAgent.ts +40 -12
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.snapshot.txt +11 -0
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +58 -8
- package/front_end/models/ai_assistance/agents/ExecuteJavascript.ts +1 -92
- package/front_end/models/ai_assistance/agents/NetworkAgent.ts +25 -0
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +94 -79
- package/front_end/models/ai_assistance/agents/StorageAgent.ts +101 -39
- package/front_end/models/ai_assistance/agents/StylingAgent.snapshot.txt +1 -2
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +27 -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 +134 -0
- package/front_end/models/ai_assistance/tools/GetStyles.ts +6 -2
- package/front_end/models/ai_assistance/tools/Tool.ts +16 -1
- package/front_end/models/ai_assistance/tools/ToolRegistry.ts +2 -0
- package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +6 -9
- package/front_end/models/bindings/DefaultScriptMapping.ts +2 -1
- package/front_end/models/bindings/SymbolizedError.ts +45 -35
- package/front_end/models/extensions/ExtensionAPI.ts +138 -47
- package/front_end/models/har/Importer.ts +1 -0
- package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +5 -7
- package/front_end/models/source_map_scopes/FunctionCodeResolver.ts +12 -2
- package/front_end/models/stack_trace/DetailedErrorStackParser.ts +44 -51
- package/front_end/models/stack_trace/StackTrace.ts +7 -0
- package/front_end/models/stack_trace/StackTraceImpl.ts +13 -4
- package/front_end/models/stack_trace/StackTraceModel.ts +9 -8
- package/front_end/panels/accessibility/AccessibilitySidebarView.ts +2 -1
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +8 -8
- 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/ApplicationPanelSidebar.ts +39 -0
- package/front_end/panels/application/ApplicationPanelTreeElement.ts +39 -0
- package/front_end/panels/application/CookieItemsView.ts +2 -2
- 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/application/resourcesSidebar.css +11 -0
- package/front_end/panels/console/SymbolizedErrorWidget.ts +79 -25
- package/front_end/panels/network/NetworkLogView.ts +5 -1
- package/front_end/panels/settings/emulation/DevicesSettingsTab.ts +1 -0
- package/front_end/panels/sources/SourcesPanel.ts +2 -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/StackedPane.ts +229 -0
- package/front_end/ui/legacy/ViewManager.ts +59 -169
- package/front_end/ui/legacy/Widget.ts +32 -8
- package/front_end/ui/legacy/legacy.ts +3 -1
- package/front_end/ui/visual_logging/KnownContextValues.ts +2 -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';
|
|
@@ -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 {
|
|
@@ -25,8 +27,9 @@ import {
|
|
|
25
27
|
type RequestOptions,
|
|
26
28
|
} from './AiAgent.js';
|
|
27
29
|
import {FileContext} from './FileAgent.js';
|
|
28
|
-
import {RequestContext} from './NetworkAgent.js';
|
|
30
|
+
import {getRequestContextOrigin, 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,8 +144,9 @@ 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
|
-
const
|
|
149
|
+
const requestOrigin = getRequestContextOrigin(request);
|
|
146
150
|
/**
|
|
147
151
|
* NOTE: this origin check does not ensure that all the requests are
|
|
148
152
|
* from the same origin as the target page. Instead, it ensures that
|
|
@@ -151,7 +155,7 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
151
155
|
* during the loading of the target page, and do not leak URLs from
|
|
152
156
|
* other pages.
|
|
153
157
|
*/
|
|
154
|
-
if (origin &&
|
|
158
|
+
if (origin && requestOrigin !== origin) {
|
|
155
159
|
hasCrossOriginRequest = true;
|
|
156
160
|
continue;
|
|
157
161
|
}
|
|
@@ -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
|
});
|
|
@@ -219,8 +230,8 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
219
230
|
return false;
|
|
220
231
|
}
|
|
221
232
|
|
|
222
|
-
const
|
|
223
|
-
return !origin ||
|
|
233
|
+
const requestOrigin = getRequestContextOrigin(req);
|
|
234
|
+
return !origin || requestOrigin === origin;
|
|
224
235
|
});
|
|
225
236
|
|
|
226
237
|
if (request) {
|
|
@@ -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> {
|
|
@@ -12,9 +12,7 @@ import {debugLog} from '../debug.js';
|
|
|
12
12
|
import {EvaluateAction, formatError, SideEffectError} from '../EvaluateAction.js';
|
|
13
13
|
import {FREESTYLER_WORLD_NAME} from '../injected.js';
|
|
14
14
|
|
|
15
|
-
import type {
|
|
16
|
-
AgentOptions as BaseAgentOptions, FunctionCallHandlerResult, FunctionDeclaration, FunctionHandlerOptions,} from
|
|
17
|
-
'./AiAgent.js';
|
|
15
|
+
import type {AgentOptions as BaseAgentOptions, FunctionCallHandlerResult, FunctionHandlerOptions,} from './AiAgent.js';
|
|
18
16
|
|
|
19
17
|
const lockedString = i18n.i18n.lockedString;
|
|
20
18
|
|
|
@@ -28,95 +26,6 @@ export interface ExecuteJsAgentOptions extends BaseAgentOptions {
|
|
|
28
26
|
execJs?: typeof executeJsCode;
|
|
29
27
|
}
|
|
30
28
|
|
|
31
|
-
export function executeJavaScriptFunction(executor: JavascriptExecutor): FunctionDeclaration<
|
|
32
|
-
{
|
|
33
|
-
title: string,
|
|
34
|
-
explanation: string,
|
|
35
|
-
code: string,
|
|
36
|
-
},
|
|
37
|
-
unknown> {
|
|
38
|
-
return {
|
|
39
|
-
description:
|
|
40
|
-
'This function allows you to run JavaScript code on the inspected page to access the element styles and page content.\nCall this function to gather additional information or modify the page state. Call this function enough times to investigate the user request.',
|
|
41
|
-
parameters: {
|
|
42
|
-
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
43
|
-
description: '',
|
|
44
|
-
nullable: false,
|
|
45
|
-
properties: {
|
|
46
|
-
code: {
|
|
47
|
-
type: Host.AidaClient.ParametersTypes.STRING,
|
|
48
|
-
description:
|
|
49
|
-
`JavaScript code snippet to run on the inspected page. Make sure the code is formatted for readability.
|
|
50
|
-
|
|
51
|
-
# Instructions
|
|
52
|
-
|
|
53
|
-
* To return data, define a top-level \`data\` variable and populate it with data you want to get. Only JSON-serializable objects can be assigned to \`data\`.
|
|
54
|
-
* If you modify styles on an element, ALWAYS call the pre-defined global \`async setElementStyles(el: Element, styles: object)\` function. This function is an internal mechanism for you and should never be presented as a command/advice to the user.
|
|
55
|
-
* **CRITICAL** Only get styles that might be relevant to the user request.
|
|
56
|
-
* **CRITICAL** Never assume a selector for the elements unless you verified your knowledge.
|
|
57
|
-
* **CRITICAL** Consider that \`data\` variable from the previous function calls are not available in a new function call.
|
|
58
|
-
|
|
59
|
-
For example, the code to change element styles:
|
|
60
|
-
|
|
61
|
-
\`\`\`
|
|
62
|
-
await setElementStyles($0, {
|
|
63
|
-
color: 'blue',
|
|
64
|
-
});
|
|
65
|
-
\`\`\`
|
|
66
|
-
|
|
67
|
-
For example, the code to get overlapping elements:
|
|
68
|
-
|
|
69
|
-
\`\`\`
|
|
70
|
-
const data = {
|
|
71
|
-
overlappingElements: Array.from(document.querySelectorAll('*'))
|
|
72
|
-
.filter(el => {
|
|
73
|
-
const rect = el.getBoundingClientRect();
|
|
74
|
-
const popupRect = $0.getBoundingClientRect();
|
|
75
|
-
return (
|
|
76
|
-
el !== $0 &&
|
|
77
|
-
rect.left < popupRect.right &&
|
|
78
|
-
rect.right > popupRect.left &&
|
|
79
|
-
rect.top < popupRect.bottom &&
|
|
80
|
-
rect.bottom > popupRect.top
|
|
81
|
-
);
|
|
82
|
-
})
|
|
83
|
-
.map(el => ({
|
|
84
|
-
tagName: el.tagName,
|
|
85
|
-
id: el.id,
|
|
86
|
-
className: el.className,
|
|
87
|
-
zIndex: window.getComputedStyle(el)['z-index']
|
|
88
|
-
}))
|
|
89
|
-
};
|
|
90
|
-
\`\`\`
|
|
91
|
-
`,
|
|
92
|
-
},
|
|
93
|
-
explanation: {
|
|
94
|
-
type: Host.AidaClient.ParametersTypes.STRING,
|
|
95
|
-
description: 'Explain why you want to run this code',
|
|
96
|
-
},
|
|
97
|
-
title: {
|
|
98
|
-
type: Host.AidaClient.ParametersTypes.STRING,
|
|
99
|
-
description: 'Provide a summary of what the code does. For example, "Checking related element styles".',
|
|
100
|
-
},
|
|
101
|
-
},
|
|
102
|
-
required: ['code', 'explanation', 'title']
|
|
103
|
-
},
|
|
104
|
-
displayInfoFromArgs: params => {
|
|
105
|
-
return {
|
|
106
|
-
title: params.title,
|
|
107
|
-
thought: params.explanation,
|
|
108
|
-
action: params.code,
|
|
109
|
-
};
|
|
110
|
-
},
|
|
111
|
-
handler: async (
|
|
112
|
-
params,
|
|
113
|
-
options,
|
|
114
|
-
) => {
|
|
115
|
-
return await executor.executeAction(params.code, options);
|
|
116
|
-
},
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
|
|
120
29
|
export async function executeJsCode(
|
|
121
30
|
functionDeclaration: string,
|
|
122
31
|
{throwOnSideEffect, contextNode}: {throwOnSideEffect: boolean, contextNode: SDK.DOMModel.DOMNode|null}):
|
|
@@ -2,11 +2,14 @@
|
|
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
|
|
5
|
+
import * as Common from '../../../core/common/common.js';
|
|
5
6
|
import * as Host from '../../../core/host/host.js';
|
|
6
7
|
import * as i18n from '../../../core/i18n/i18n.js';
|
|
8
|
+
import type * as Platform from '../../../core/platform/platform.js';
|
|
7
9
|
import * as Root from '../../../core/root/root.js';
|
|
8
10
|
import type * as SDK from '../../../core/sdk/sdk.js';
|
|
9
11
|
import type * as NetworkTimeCalculator from '../../network_time_calculator/network_time_calculator.js';
|
|
12
|
+
import {extractContextOrigin} from '../AiOrigins.js';
|
|
10
13
|
import {NetworkRequestFormatter} from '../data_formatters/NetworkRequestFormatter.js';
|
|
11
14
|
|
|
12
15
|
import {
|
|
@@ -98,6 +101,24 @@ const UIStringsNotTranslate = {
|
|
|
98
101
|
|
|
99
102
|
const lockedString = i18n.i18n.lockedString;
|
|
100
103
|
|
|
104
|
+
/**
|
|
105
|
+
* Returns the origin for a network request in the AI context.
|
|
106
|
+
*
|
|
107
|
+
* To prevent cross-origin prompt injection attacks, HAR-imported requests
|
|
108
|
+
* are isolated from live pages. We assign them a virtual origin
|
|
109
|
+
* (`imported-har://${domain}`) so they do not share the origin of live pages
|
|
110
|
+
* (e.g., `https://${domain}`). This forces a conversation reset when transitioning
|
|
111
|
+
* between imported HAR data and live pages.
|
|
112
|
+
*/
|
|
113
|
+
export function getRequestContextOrigin(request: SDK.NetworkRequest.NetworkRequest): string {
|
|
114
|
+
const origin = extractContextOrigin(request.documentURL);
|
|
115
|
+
if (request.isImportedHar()) {
|
|
116
|
+
const parsed = Common.ParsedURL.ParsedURL.fromString(origin as Platform.DevToolsPath.UrlString);
|
|
117
|
+
return `imported-har://${parsed ? parsed.domain() : origin}`;
|
|
118
|
+
}
|
|
119
|
+
return origin;
|
|
120
|
+
}
|
|
121
|
+
|
|
101
122
|
export class RequestContext extends ConversationContext<SDK.NetworkRequest.NetworkRequest> {
|
|
102
123
|
#request: SDK.NetworkRequest.NetworkRequest;
|
|
103
124
|
#calculator: NetworkTimeCalculator.NetworkTransferTimeCalculator;
|
|
@@ -119,6 +140,10 @@ export class RequestContext extends ConversationContext<SDK.NetworkRequest.Netwo
|
|
|
119
140
|
return this.#request.documentURL;
|
|
120
141
|
}
|
|
121
142
|
|
|
143
|
+
override getOrigin(): string {
|
|
144
|
+
return getRequestContextOrigin(this.#request);
|
|
145
|
+
}
|
|
146
|
+
|
|
122
147
|
override getItem(): SDK.NetworkRequest.NetworkRequest {
|
|
123
148
|
return this.#request;
|
|
124
149
|
}
|
|
@@ -15,6 +15,7 @@ import * as Logs from '../../logs/logs.js';
|
|
|
15
15
|
import * as SourceMapScopes from '../../source_map_scopes/source_map_scopes.js';
|
|
16
16
|
import * as TextUtils from '../../text_utils/text_utils.js';
|
|
17
17
|
import * as Trace from '../../trace/trace.js';
|
|
18
|
+
import {extractContextOrigin} from '../AiOrigins.js';
|
|
18
19
|
import {sanitizeHeaders} from '../data_formatters/NetworkRequestFormatter.js';
|
|
19
20
|
import {
|
|
20
21
|
PerformanceInsightFormatter,
|
|
@@ -63,12 +64,6 @@ export type MainThreadSectionLabel = 'nav-to-lcp'|'lcp-ttfb'|'lcp-render-delay'|
|
|
|
63
64
|
* chrome_preambles.gcl). Sync local changes with the server-side.
|
|
64
65
|
*/
|
|
65
66
|
|
|
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
67
|
const GREEN_DEV_ANNOTATIONS_INSTRUCTIONS = `
|
|
73
68
|
- CRITICAL: You also have access to functions called addElementAnnotation and addNeworkRequestAnnotation,
|
|
74
69
|
which should be used to highlight elements and network requests (respectively).
|
|
@@ -262,6 +257,27 @@ export class PerformanceTraceContext extends ConversationContext<AgentFocus> {
|
|
|
262
257
|
}
|
|
263
258
|
}
|
|
264
259
|
|
|
260
|
+
/**
|
|
261
|
+
* Returns the origin for a performance trace in the AI context.
|
|
262
|
+
*
|
|
263
|
+
* To prevent cross-origin prompt injection attacks, imported traces
|
|
264
|
+
* are isolated from live pages. We assign them a virtual origin
|
|
265
|
+
* (`imported-trace://${domain}`) so they do not share the origin of live pages
|
|
266
|
+
* (e.g., `https://${domain}`). This forces a conversation reset when transitioning
|
|
267
|
+
* between imported trace data and live pages.
|
|
268
|
+
*/
|
|
269
|
+
override getOrigin(): string {
|
|
270
|
+
const parsedTrace = this.#focus.parsedTrace;
|
|
271
|
+
const url = this.getURL();
|
|
272
|
+
const origin = extractContextOrigin(url);
|
|
273
|
+
const isFresh = Tracing.FreshRecording.Tracker.instance().recordingIsFresh(parsedTrace);
|
|
274
|
+
if (!isFresh) {
|
|
275
|
+
const parsed = Common.ParsedURL.ParsedURL.fromString(origin as Platform.DevToolsPath.UrlString);
|
|
276
|
+
return `imported-trace://${parsed ? parsed.domain() : origin}`;
|
|
277
|
+
}
|
|
278
|
+
return origin;
|
|
279
|
+
}
|
|
280
|
+
|
|
265
281
|
override getItem(): AgentFocus {
|
|
266
282
|
return this.#focus;
|
|
267
283
|
}
|
|
@@ -710,18 +726,14 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
710
726
|
}
|
|
711
727
|
}
|
|
712
728
|
|
|
713
|
-
const isFresh = Tracing.FreshRecording.Tracker.instance().recordingIsFresh(focus.parsedTrace);
|
|
714
|
-
|
|
715
729
|
if (!selected.length) {
|
|
716
730
|
this.#additionalSelectionsForDisclosure = [];
|
|
717
|
-
|
|
718
|
-
return isFresh ? finalQuery : `${SECURITY_WARNING}\n\n${finalQuery}`;
|
|
731
|
+
return query;
|
|
719
732
|
}
|
|
720
733
|
|
|
721
734
|
selected.push(`# User query\n\n${query}`);
|
|
722
735
|
this.#additionalSelectionsForDisclosure = [...selected];
|
|
723
|
-
|
|
724
|
-
return isFresh ? finalQuery : `${SECURITY_WARNING}\n\n${finalQuery}`;
|
|
736
|
+
return selected.join('');
|
|
725
737
|
}
|
|
726
738
|
|
|
727
739
|
override async * run(initialQuery: string, options: {
|
|
@@ -1340,84 +1352,87 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
1340
1352
|
});
|
|
1341
1353
|
}
|
|
1342
1354
|
|
|
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
|
-
},
|
|
1355
|
+
this.declareFunction<{scriptUrl: UrlString, line: number, column: number}, {result: string}>('getFunctionCode', {
|
|
1356
|
+
description:
|
|
1357
|
+
'Returns the code for a function defined at the given location. The result is annotated with the runtime performance of each line of code.',
|
|
1358
|
+
parameters: {
|
|
1359
|
+
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
1360
|
+
description: '',
|
|
1361
|
+
nullable: false,
|
|
1362
|
+
properties: {
|
|
1363
|
+
scriptUrl: {
|
|
1364
|
+
type: Host.AidaClient.ParametersTypes.STRING,
|
|
1365
|
+
description: 'The url of the function.',
|
|
1366
|
+
nullable: false,
|
|
1367
|
+
},
|
|
1368
|
+
line: {
|
|
1369
|
+
type: Host.AidaClient.ParametersTypes.INTEGER,
|
|
1370
|
+
description: 'The line number where the function is defined.',
|
|
1371
|
+
nullable: false,
|
|
1372
|
+
},
|
|
1373
|
+
column: {
|
|
1374
|
+
type: Host.AidaClient.ParametersTypes.INTEGER,
|
|
1375
|
+
description: 'The column number where the function is defined.',
|
|
1376
|
+
nullable: false,
|
|
1367
1377
|
},
|
|
1368
|
-
required: ['scriptUrl', 'line', 'column']
|
|
1369
1378
|
},
|
|
1370
|
-
|
|
1379
|
+
required: ['scriptUrl', 'line', 'column']
|
|
1380
|
+
},
|
|
1381
|
+
displayInfoFromArgs: args => {
|
|
1382
|
+
return {
|
|
1383
|
+
title: lockedString('Looking up function code'),
|
|
1384
|
+
action: `getFunctionCode('${args.scriptUrl}', ${args.line}, ${args.column})`
|
|
1385
|
+
};
|
|
1386
|
+
},
|
|
1387
|
+
handler: async args => {
|
|
1388
|
+
debugLog('Function call: getFunctionCode');
|
|
1389
|
+
if (!isFresh) {
|
|
1371
1390
|
return {
|
|
1372
|
-
|
|
1373
|
-
action: `getFunctionCode('${args.scriptUrl}', ${args.line}, ${args.column})`
|
|
1391
|
+
error: 'Cannot use this tool on an imported file.',
|
|
1374
1392
|
};
|
|
1375
|
-
}
|
|
1376
|
-
handler: async args => {
|
|
1377
|
-
debugLog('Function call: getFunctionCode');
|
|
1393
|
+
}
|
|
1378
1394
|
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1395
|
+
if (args.line === undefined) {
|
|
1396
|
+
return {error: 'Missing arg: line'};
|
|
1397
|
+
}
|
|
1382
1398
|
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1399
|
+
if (args.column === undefined) {
|
|
1400
|
+
return {error: 'Missing arg: column'};
|
|
1401
|
+
}
|
|
1386
1402
|
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1403
|
+
if (!this.#formatter) {
|
|
1404
|
+
throw new Error('missing formatter');
|
|
1405
|
+
}
|
|
1390
1406
|
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1407
|
+
const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
|
|
1408
|
+
if (!target) {
|
|
1409
|
+
throw new Error('missing target');
|
|
1410
|
+
}
|
|
1395
1411
|
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1412
|
+
const url = args.scriptUrl as Platform.DevToolsPath.UrlString;
|
|
1413
|
+
const code = await this.#formatter.resolveFunctionCodeAtLocation(url, args.line, args.column);
|
|
1414
|
+
if (!code) {
|
|
1415
|
+
return {error: 'Could not find code'};
|
|
1416
|
+
}
|
|
1401
1417
|
|
|
1402
|
-
|
|
1418
|
+
const result = this.#formatter.formatFunctionCode(code);
|
|
1403
1419
|
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
}
|
|
1420
|
+
const key = `getFunctionCode('${args.scriptUrl}', ${args.line}, ${args.column})`;
|
|
1421
|
+
this.#cacheFunctionResult(focus, key, result);
|
|
1422
|
+
return {
|
|
1423
|
+
result: {result},
|
|
1424
|
+
widgets: [{
|
|
1425
|
+
name: 'SOURCE_CODE',
|
|
1426
|
+
data: {
|
|
1427
|
+
url: args.scriptUrl,
|
|
1428
|
+
line: args.line,
|
|
1429
|
+
column: args.column,
|
|
1430
|
+
code: code.code,
|
|
1431
|
+
},
|
|
1432
|
+
}],
|
|
1433
|
+
};
|
|
1434
|
+
},
|
|
1435
|
+
});
|
|
1421
1436
|
|
|
1422
1437
|
const isTraceApp = Root.Runtime.Runtime.isTraceApp();
|
|
1423
1438
|
|