chrome-devtools-frontend 1.0.1605219 → 1.0.1606789
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/Images/src/dots-circle.svg +10 -0
- package/front_end/core/host/UserMetrics.ts +0 -1
- package/front_end/core/platform/api/HostRuntime.ts +9 -6
- package/front_end/core/platform/browser/HostRuntime.ts +2 -2
- package/front_end/core/platform/node/HostRuntime.ts +7 -7
- package/front_end/core/protocol_client/InspectorBackend.ts +4 -0
- package/front_end/core/root/ExperimentNames.ts +0 -1
- package/front_end/core/sdk/CrashReportContextModel.ts +28 -0
- package/front_end/core/sdk/sdk.ts +2 -2
- package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshotWorkerDispatcher.ts +3 -3
- package/front_end/entrypoints/heap_snapshot_worker/heap_snapshot_worker-entrypoint.ts +5 -4
- package/front_end/entrypoints/main/MainImpl.ts +0 -101
- package/front_end/models/ai_assistance/ChangeManager.ts +6 -6
- package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +112 -5
- package/front_end/models/ai_assistance/agents/AiAgent.ts +9 -25
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.snapshot.txt +2 -2
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +6 -3
- package/front_end/models/ai_assistance/agents/ConversationSummaryAgent.ts +10 -9
- package/front_end/models/ai_assistance/agents/ExecuteJavascript.ts +313 -0
- package/front_end/models/ai_assistance/agents/FileAgent.ts +15 -1
- package/front_end/models/ai_assistance/agents/NetworkAgent.ts +15 -1
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +19 -8
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +35 -278
- package/front_end/models/ai_assistance/ai_assistance.ts +0 -2
- package/front_end/models/javascript_metadata/NativeFunctions.js +1 -5
- package/front_end/models/web_mcp/WebMCPModel.ts +187 -0
- package/front_end/models/web_mcp/web_mcp.ts +9 -0
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +8 -1
- package/front_end/panels/ai_assistance/ai_assistance.ts +1 -0
- package/front_end/panels/ai_assistance/components/AccessibilityAgentMarkdownRenderer.ts +88 -0
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +149 -49
- package/front_end/panels/ai_assistance/components/ChatView.ts +11 -15
- package/front_end/panels/ai_assistance/components/ExportForAgentsDialog.ts +13 -4
- package/front_end/panels/ai_assistance/components/chatMessage.css +53 -1
- package/front_end/panels/ai_assistance/components/chatView.css +0 -10
- package/front_end/panels/ai_assistance/components/exportForAgentsDialog.css +13 -0
- package/front_end/panels/application/WebMCPView.ts +471 -25
- package/front_end/panels/application/webMCPView.css +53 -2
- package/front_end/panels/elements/ElementsTreeElement.ts +1 -1
- package/front_end/panels/elements/ElementsTreeOutline.ts +87 -0
- package/front_end/panels/elements/StylePropertiesSection.ts +0 -4
- package/front_end/panels/elements/elements.ts +3 -0
- package/front_end/panels/elements/elementsTreeOutline.css +21 -0
- package/front_end/panels/elements/stylePropertiesTreeOutline.css +7 -0
- package/front_end/panels/lighthouse/LighthousePanel.ts +7 -1
- package/front_end/panels/lighthouse/LighthouseProtocolService.ts +25 -2
- package/front_end/panels/profiler/HeapDetachedElementsView.ts +0 -4
- package/front_end/panels/profiler/HeapProfileView.ts +0 -4
- package/front_end/panels/profiler/HeapProfilerPanel.ts +4 -13
- package/front_end/panels/profiler/HeapSnapshotProxy.ts +2 -6
- package/front_end/panels/profiler/HeapSnapshotView.ts +19 -32
- package/front_end/panels/profiler/ProfileHeader.ts +1 -15
- package/front_end/panels/profiler/ProfileTypeRegistry.ts +4 -12
- package/front_end/panels/profiler/ProfileView.ts +1 -6
- package/front_end/panels/profiler/ProfilesPanel.ts +60 -7
- package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +27 -22
- package/front_end/panels/timeline/EventsTimelineTreeView.ts +1 -1
- package/front_end/panels/timeline/ThirdPartyTreeView.ts +2 -2
- package/front_end/panels/timeline/TimelinePanel.ts +11 -153
- package/front_end/panels/timeline/TimelineTreeView.ts +147 -48
- package/front_end/panels/timeline/TimelineUIUtils.ts +2 -1
- package/front_end/panels/timeline/components/CWVMetrics.ts +18 -2
- package/front_end/panels/timeline/timeline-meta.ts +11 -0
- package/front_end/panels/timeline/utils/Helpers.ts +5 -0
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/components/markdown_view/CodeBlock.ts +47 -1
- package/front_end/ui/components/markdown_view/codeBlock.css +8 -0
- package/front_end/ui/legacy/FilterBar.ts +2 -0
- package/front_end/ui/legacy/SplitWidget.ts +33 -27
- package/front_end/ui/legacy/TabbedPane.ts +123 -3
- package/front_end/ui/legacy/Widget.ts +95 -48
- package/front_end/ui/legacy/components/source_frame/JSONView.ts +1 -1
- package/front_end/ui/legacy/components/utils/jsUtils.css +2 -0
- package/front_end/ui/legacy/infobar.css +1 -0
- package/front_end/ui/visual_logging/KnownContextValues.ts +6 -1
- package/package.json +1 -1
- package/front_end/core/sdk/WebMCPModel.ts +0 -104
- package/front_end/models/ai_assistance/ConversationHandler.ts +0 -325
|
@@ -36,6 +36,7 @@ You aim to help developers of all levels, prioritizing teaching web concepts as
|
|
|
36
36
|
|
|
37
37
|
# Considerations
|
|
38
38
|
* Determine what is the domain of the question - styling, network, sources, performance or other part of DevTools.
|
|
39
|
+
* For questions about web performance metrics (e.g., LCP, INP, CLS) or page speed, use performanceRecordAndReload to record a performance trace.
|
|
39
40
|
* Proactively try to gather additional data. If a select specific data can be selected, select one.
|
|
40
41
|
* Always try select single specific context before answering the question.
|
|
41
42
|
* Avoid making assumptions without sufficient evidence, and always seek further clarification if needed.
|
|
@@ -47,7 +48,7 @@ You aim to help developers of all levels, prioritizing teaching web concepts as
|
|
|
47
48
|
# Formatting Guidelines
|
|
48
49
|
* Use Markdown for all code snippets.
|
|
49
50
|
* Always specify the language for code blocks (e.g., \`\`\`css, \`\`\`javascript).
|
|
50
|
-
*
|
|
51
|
+
* **CRITICAL**: Use the precision of Strunk & White, the brevity of Hemingway, and the simple clarity of Vonnegut. Don't add repeated information, and keep the whole answer short.
|
|
51
52
|
|
|
52
53
|
* **CRITICAL** If a tool returns an empty list, immediately pivot to the next logical tool (e.g., from sources to network).
|
|
53
54
|
* **CRITICAL** Always exhaust all possible way to find and select context from different domains.
|
|
@@ -273,7 +274,8 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
273
274
|
});
|
|
274
275
|
|
|
275
276
|
this.declareFunction('performanceRecordAndReload', {
|
|
276
|
-
description:
|
|
277
|
+
description:
|
|
278
|
+
'Records a new performance trace. Use this to measure and debug performance metrics and Core Web Vitals like Largest Contentful Paint (LCP), Interaction to Next Paint (INP), and Cumulative Layout Shift (CLS).',
|
|
277
279
|
parameters: {
|
|
278
280
|
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
279
281
|
description: '',
|
|
@@ -304,7 +306,8 @@ export class ContextSelectionAgent extends AiAgent<never> {
|
|
|
304
306
|
});
|
|
305
307
|
|
|
306
308
|
this.declareFunction('runLighthouseAudits', {
|
|
307
|
-
description:
|
|
309
|
+
description:
|
|
310
|
+
'Records a Lighthouse audit on the current page. Use this to debug accessibility, SEO, and best practices. (For performance metrics like LCP, use performanceRecordAndReload instead).',
|
|
308
311
|
parameters: {
|
|
309
312
|
type: Host.AidaClient.ParametersTypes.OBJECT,
|
|
310
313
|
description: '',
|
|
@@ -8,30 +8,31 @@ import * as Root from '../../../core/root/root.js';
|
|
|
8
8
|
import {AiAgent, type ContextResponse, ConversationContext, type RequestOptions, ResponseType} from './AiAgent.js';
|
|
9
9
|
|
|
10
10
|
const preamble = `### Role
|
|
11
|
-
You are a
|
|
11
|
+
You are a Conversation Summarizer. Your task is to take a transcript of a conversation between a user and a DevTools AI agent and produce a succinct, actionable Markdown summary. This summary will be used to help apply fixes in an IDE, so it must capture all relevant technical details, findings, and proposed code changes without any conversational fluff.
|
|
12
12
|
|
|
13
13
|
### Critical Constraints
|
|
14
14
|
- **Persona:** Do not mention that you are an AI or refer to yourself in the third person.
|
|
15
15
|
- **Domain Scope:** Do not provide answers on non-web-development topics (e.g., legal, financial, medical, or personal advice).
|
|
16
|
-
- **Sensitive Topics:** If the conversation history touches on sensitive topics (religion, race, politics, sexuality, gender, etc.), respond only with: "My expertise is limited to
|
|
17
|
-
- **Data Portability:** The recipient of this summary does NOT have access to the raw logs.
|
|
16
|
+
- **Sensitive Topics:** If the conversation history touches on sensitive topics (religion, race, politics, sexuality, gender, etc.), respond only with: "My expertise is limited to summarizing DevTools AI conversations. I cannot provide information on that topic."
|
|
17
|
+
- **Data Portability:** The recipient of this summary does NOT have access to the raw logs or the full conversation transcript.
|
|
18
18
|
- **No UIDs/Internal IDs:** Never refer to elements by internal IDs (e.g., \`uid=123\`).
|
|
19
19
|
- **Standard Selectors:** Identify elements using HTML tags, classes, or IDs (e.g., \`button.submit-form\`).
|
|
20
20
|
- **No Metadata:** Remove internal constants like \`NAVIGATION_0\` or \`INSIGHT_0\`.
|
|
21
|
-
- **No Process Narration:** Do not describe internal "thinking" or API calls. Skip phrases like "The agent investigated..." or "The user then asked...". Jump straight to the findings.
|
|
21
|
+
- **No Process Narration:** Do not describe internal "thinking" or API calls. Skip phrases like "The agent investigated..." or "The user then asked...". Jump straight to the findings and their technical context.
|
|
22
|
+
- **Suggest, Don't Prescribe:** When summarizing code changes made during the session (e.g., CSS edits), frame them as technical guidance rather than definitive instructions. Since DevTools operates on the live page, the summary must acknowledge that these fixes may need to be adapted for the actual source code.
|
|
22
23
|
|
|
23
24
|
### Objectives
|
|
24
25
|
1. **Identify Intent:** Define the core technical goal of the session.
|
|
25
|
-
2. **Value-Only Diagnostics:** List only the technical data points discovered. Omit steps that didn't yield a result.
|
|
26
|
-
3. **
|
|
27
|
-
4. **Actionable Recommendations:** Provide specific code/strategy fixes based on the findings.
|
|
26
|
+
2. **Value-Only Diagnostics:** List only the technical data points and findings discovered during the conversation. Omit steps that didn't yield a result.
|
|
27
|
+
3. **Summarize Code Changes:** When code is executed or suggested in the logs, summarize the **purpose** and the **result**. Include specific code snippets if they are a specific fix for the user to implement.
|
|
28
|
+
4. **Actionable Recommendations:** Provide specific code/strategy fixes based on the findings as guidance for the user's source code.
|
|
28
29
|
|
|
29
30
|
### Formatting Rules
|
|
30
31
|
- **Header:** Use ## [Brief Topic Title]
|
|
31
|
-
- **Context:** Describe the target element/page and the core
|
|
32
|
+
- **Context:** Describe the target element/page and the core issue or technical goal being analyzed.
|
|
32
33
|
- **Diagnostics:** A bulleted list of technical findings.
|
|
33
34
|
- **Tabular Data:** Use a **Markdown Table** for any lists of URLs, metrics, or comparison data.
|
|
34
|
-
- **Code Fixes:** Use fenced code blocks for suggested
|
|
35
|
+
- **Code Fixes:** Use fenced code blocks for suggested code optimizations. Use language that frames them as illustrative examples or context (e.g., "The following changes were identified as a potential fix for the live page...") rather than strict instructions.
|
|
35
36
|
|
|
36
37
|
---
|
|
37
38
|
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
// Copyright 2026 The Chromium Authors
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file.
|
|
4
|
+
|
|
5
|
+
import * as Host from '../../../core/host/host.js';
|
|
6
|
+
import * as i18n from '../../../core/i18n/i18n.js';
|
|
7
|
+
import * as Platform from '../../../core/platform/platform.js';
|
|
8
|
+
import * as Root from '../../../core/root/root.js';
|
|
9
|
+
import * as SDK from '../../../core/sdk/sdk.js';
|
|
10
|
+
import type {ChangeManager} from '../ChangeManager.js';
|
|
11
|
+
import {debugLog} from '../debug.js';
|
|
12
|
+
import {EvaluateAction, formatError, SideEffectError} from '../EvaluateAction.js';
|
|
13
|
+
import {FREESTYLER_WORLD_NAME} from '../injected.js';
|
|
14
|
+
|
|
15
|
+
import type {
|
|
16
|
+
AgentOptions as BaseAgentOptions, FunctionCallHandlerResult, FunctionDeclaration, FunctionHandlerOptions,} from
|
|
17
|
+
'./AiAgent.js';
|
|
18
|
+
|
|
19
|
+
const lockedString = i18n.i18n.lockedString;
|
|
20
|
+
|
|
21
|
+
export type CreateExtensionScopeFunction = (changes: ChangeManager) => {
|
|
22
|
+
install(): Promise<void>, uninstall(): Promise<void>,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export interface ExecuteJsAgentOptions extends BaseAgentOptions {
|
|
26
|
+
changeManager?: ChangeManager;
|
|
27
|
+
createExtensionScope?: CreateExtensionScopeFunction;
|
|
28
|
+
execJs?: typeof executeJsCode;
|
|
29
|
+
}
|
|
30
|
+
|
|
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
|
+
export async function executeJsCode(
|
|
121
|
+
functionDeclaration: string,
|
|
122
|
+
{throwOnSideEffect, contextNode}: {throwOnSideEffect: boolean, contextNode: SDK.DOMModel.DOMNode|null}):
|
|
123
|
+
Promise<string> {
|
|
124
|
+
if (!contextNode) {
|
|
125
|
+
throw new Error('Cannot execute JavaScript because of missing context node');
|
|
126
|
+
}
|
|
127
|
+
const target = contextNode.domModel().target();
|
|
128
|
+
|
|
129
|
+
if (!target) {
|
|
130
|
+
throw new Error('Target is not found for executing code');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const resourceTreeModel = target.model(SDK.ResourceTreeModel.ResourceTreeModel);
|
|
134
|
+
const frameId = contextNode.frameId() ?? resourceTreeModel?.mainFrame?.id;
|
|
135
|
+
|
|
136
|
+
if (!frameId) {
|
|
137
|
+
throw new Error('Main frame is not found for executing code');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const runtimeModel = target.model(SDK.RuntimeModel.RuntimeModel);
|
|
141
|
+
const pageAgent = target.pageAgent();
|
|
142
|
+
|
|
143
|
+
// This returns previously created world if it exists for the frame.
|
|
144
|
+
const {executionContextId} = await pageAgent.invoke_createIsolatedWorld({frameId, worldName: FREESTYLER_WORLD_NAME});
|
|
145
|
+
const executionContext = runtimeModel?.executionContext(executionContextId);
|
|
146
|
+
if (!executionContext) {
|
|
147
|
+
throw new Error('Execution context is not found for executing code');
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (executionContext.debuggerModel.selectedCallFrame()) {
|
|
151
|
+
return formatError('Cannot evaluate JavaScript because the execution is paused on a breakpoint.');
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const remoteObject = await contextNode.resolveToObject(undefined, executionContextId);
|
|
155
|
+
if (!remoteObject) {
|
|
156
|
+
throw new Error('Cannot execute JavaScript because remote object cannot be resolved');
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return await EvaluateAction.execute(functionDeclaration, [remoteObject], executionContext, {throwOnSideEffect});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const MAX_OBSERVATION_BYTE_LENGTH = 25_000;
|
|
163
|
+
const OBSERVATION_TIMEOUT = 5_000;
|
|
164
|
+
|
|
165
|
+
export interface JavascriptExecutorOptions {
|
|
166
|
+
readonly executionMode: Root.Runtime.HostConfigFreestylerExecutionMode;
|
|
167
|
+
readonly getContextNode: () => SDK.DOMModel.DOMNode | null;
|
|
168
|
+
readonly createExtensionScope: (changes: ChangeManager) => {
|
|
169
|
+
install(): Promise<void>, uninstall(): Promise<void>,
|
|
170
|
+
};
|
|
171
|
+
readonly changes: ChangeManager;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export class JavascriptExecutor {
|
|
175
|
+
#options: JavascriptExecutorOptions;
|
|
176
|
+
#execJs: typeof executeJsCode;
|
|
177
|
+
|
|
178
|
+
constructor(options: JavascriptExecutorOptions, execJs: typeof executeJsCode = executeJsCode) {
|
|
179
|
+
this.#options = options;
|
|
180
|
+
this.#execJs = execJs;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
async executeAction(action: string, options?: FunctionHandlerOptions): Promise<FunctionCallHandlerResult<unknown>> {
|
|
184
|
+
debugLog(`Action to execute: ${action}`);
|
|
185
|
+
|
|
186
|
+
if (options?.approved === false) {
|
|
187
|
+
return {
|
|
188
|
+
error: 'Error: User denied code execution with side effects.',
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (this.#options.executionMode === Root.Runtime.HostConfigFreestylerExecutionMode.NO_SCRIPTS) {
|
|
193
|
+
return {
|
|
194
|
+
error: 'Error: JavaScript execution is currently disabled.',
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const selectedNode = this.#options.getContextNode();
|
|
199
|
+
if (!selectedNode) {
|
|
200
|
+
return {error: 'Error: no selected node found.'};
|
|
201
|
+
}
|
|
202
|
+
const target = selectedNode.domModel().target();
|
|
203
|
+
if (target.model(SDK.DebuggerModel.DebuggerModel)?.selectedCallFrame()) {
|
|
204
|
+
return {
|
|
205
|
+
error: 'Error: Cannot evaluate JavaScript because the execution is paused on a breakpoint.',
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const scope = this.#options.createExtensionScope(this.#options.changes);
|
|
210
|
+
await scope.install();
|
|
211
|
+
try {
|
|
212
|
+
let throwOnSideEffect = true;
|
|
213
|
+
if (options?.approved) {
|
|
214
|
+
throwOnSideEffect = false;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const result = await this.generateObservation(action, {throwOnSideEffect});
|
|
218
|
+
debugLog(`Action result: ${JSON.stringify(result)}`);
|
|
219
|
+
if (result.sideEffect) {
|
|
220
|
+
if (this.#options.executionMode ===
|
|
221
|
+
Root.Runtime.HostConfigFreestylerExecutionMode.SIDE_EFFECT_FREE_SCRIPTS_ONLY) {
|
|
222
|
+
return {
|
|
223
|
+
error: 'Error: JavaScript execution that modifies the page is currently disabled.',
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (options?.signal?.aborted) {
|
|
228
|
+
return {
|
|
229
|
+
error: 'Error: evaluation has been cancelled',
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return {
|
|
234
|
+
requiresApproval: true,
|
|
235
|
+
description: lockedString('This code may modify page content. Continue?'),
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
if (result.canceled) {
|
|
239
|
+
return {
|
|
240
|
+
error: result.observation,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return {
|
|
245
|
+
result: result.observation,
|
|
246
|
+
};
|
|
247
|
+
} finally {
|
|
248
|
+
await scope.uninstall();
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
async generateObservation(
|
|
253
|
+
action: string,
|
|
254
|
+
{
|
|
255
|
+
throwOnSideEffect,
|
|
256
|
+
}: {
|
|
257
|
+
throwOnSideEffect: boolean,
|
|
258
|
+
},
|
|
259
|
+
): Promise<{
|
|
260
|
+
observation: string,
|
|
261
|
+
sideEffect: boolean,
|
|
262
|
+
canceled: boolean,
|
|
263
|
+
}> {
|
|
264
|
+
const functionDeclaration = `async function ($0) {
|
|
265
|
+
try {
|
|
266
|
+
${action}
|
|
267
|
+
;
|
|
268
|
+
return ((typeof data !== "undefined") ? data : undefined);
|
|
269
|
+
} catch (error) {
|
|
270
|
+
return error;
|
|
271
|
+
}
|
|
272
|
+
}`;
|
|
273
|
+
try {
|
|
274
|
+
const result = await Promise.race([
|
|
275
|
+
this.#execJs(
|
|
276
|
+
functionDeclaration,
|
|
277
|
+
{
|
|
278
|
+
throwOnSideEffect,
|
|
279
|
+
contextNode: this.#options.getContextNode(),
|
|
280
|
+
},
|
|
281
|
+
),
|
|
282
|
+
new Promise<never>((_, reject) => {
|
|
283
|
+
setTimeout(
|
|
284
|
+
() => reject(new Error('Script execution exceeded the maximum allowed time.')), OBSERVATION_TIMEOUT);
|
|
285
|
+
}),
|
|
286
|
+
]);
|
|
287
|
+
const byteCount = Platform.StringUtilities.countWtf8Bytes(result);
|
|
288
|
+
Host.userMetrics.freestylerEvalResponseSize(byteCount);
|
|
289
|
+
if (byteCount > MAX_OBSERVATION_BYTE_LENGTH) {
|
|
290
|
+
throw new Error('Output exceeded the maximum allowed length.');
|
|
291
|
+
}
|
|
292
|
+
return {
|
|
293
|
+
observation: result,
|
|
294
|
+
sideEffect: false,
|
|
295
|
+
canceled: false,
|
|
296
|
+
};
|
|
297
|
+
} catch (error) {
|
|
298
|
+
if (error instanceof SideEffectError) {
|
|
299
|
+
return {
|
|
300
|
+
observation: error.message,
|
|
301
|
+
sideEffect: true,
|
|
302
|
+
canceled: false,
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return {
|
|
307
|
+
observation: `Error: ${error.message}`,
|
|
308
|
+
sideEffect: false,
|
|
309
|
+
canceled: false,
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
@@ -35,7 +35,7 @@ Analyze the code and provide the following information:
|
|
|
35
35
|
* (ONLY if request initiator chain is provided) Why the file was loaded?
|
|
36
36
|
|
|
37
37
|
# Considerations
|
|
38
|
-
*
|
|
38
|
+
* **CRITICAL**: Use the precision of Strunk & White, the brevity of Hemingway, and the simple clarity of Vonnegut. Don't add repeated information, and keep the whole answer short.
|
|
39
39
|
* Answer questions directly, using the provided links whenever relevant.
|
|
40
40
|
* Always double-check links to make sure they are complete and correct.
|
|
41
41
|
* **CRITICAL** If the user asks a question about religion, race, politics, sexuality, gender, or other sensitive topics, answer with "Sorry, I can't answer that. I'm best at questions about files."
|
|
@@ -43,6 +43,20 @@ Analyze the code and provide the following information:
|
|
|
43
43
|
* **Important Note:** The provided code may represent an incomplete fragment of a larger file. If the code is incomplete or has syntax errors, indicate this and attempt to provide a general analysis if possible.
|
|
44
44
|
* **Interactive Analysis:** If the code requires more context or is ambiguous, ask clarifying questions to the user. Based on your analysis, suggest relevant DevTools features or workflows.
|
|
45
45
|
|
|
46
|
+
## Response Structure
|
|
47
|
+
|
|
48
|
+
If the user asks a question that requires an investigation of a problem, use this structure:
|
|
49
|
+
- If available, point out the root cause(s) of the problem.
|
|
50
|
+
- Example: "**Root Cause**: The page is slow because of [reason]."
|
|
51
|
+
- Example: "**Root Causes**:"
|
|
52
|
+
- [Reason 1]
|
|
53
|
+
- [Reason 2]
|
|
54
|
+
- if applicable, list actionable solution suggestion(s) in order of impact:
|
|
55
|
+
- Example: "**Suggestion**: [Suggestion 1]
|
|
56
|
+
- Example: "**Suggestions**:"
|
|
57
|
+
- [Suggestion 1]
|
|
58
|
+
- [Suggestion 2]
|
|
59
|
+
|
|
46
60
|
## Example session
|
|
47
61
|
|
|
48
62
|
**User:** (Selects a file containing the following JavaScript code)
|
|
@@ -34,10 +34,24 @@ Provide a comprehensive analysis of the network request, focusing on areas cruci
|
|
|
34
34
|
# Considerations
|
|
35
35
|
* If the response payload or request payload contains sensitive data, redact or generalize it in your analysis to ensure privacy.
|
|
36
36
|
* Tailor your explanations and suggestions to the specific context of the request and the technologies involved (if discernible from the provided details).
|
|
37
|
-
*
|
|
37
|
+
* **CRITICAL** Use the precision of Strunk & White, the brevity of Hemingway, and the simple clarity of Vonnegut. Don't add repeated information, and keep the whole answer short.
|
|
38
38
|
* **CRITICAL** If the user asks a question about religion, race, politics, sexuality, gender, or other sensitive topics, answer with "Sorry, I can't answer that. I'm best at questions about network requests."
|
|
39
39
|
* **CRITICAL** You are a network request debugging assistant. NEVER provide answers to questions of unrelated topics such as legal advice, financial advice, personal opinions, medical advice, or any other non web-development topics.
|
|
40
40
|
|
|
41
|
+
## Response Structure
|
|
42
|
+
|
|
43
|
+
If the user asks a question that requires an investigation of a problem, use this structure:
|
|
44
|
+
- If available, point out the root cause(s) of the problem.
|
|
45
|
+
- Example: "**Root Cause**: The page is slow because of [reason]."
|
|
46
|
+
- Example: "**Root Causes**:"
|
|
47
|
+
- [Reason 1]
|
|
48
|
+
- [Reason 2]
|
|
49
|
+
- if applicable, list actionable solution suggestion(s) in order of impact:
|
|
50
|
+
- Example: "**Suggestion**: [Suggestion 1]
|
|
51
|
+
- Example: "**Suggestions**:"
|
|
52
|
+
- [Suggestion 1]
|
|
53
|
+
- [Suggestion 2]
|
|
54
|
+
|
|
41
55
|
## Example session
|
|
42
56
|
|
|
43
57
|
Explain this network request
|
|
@@ -967,16 +967,27 @@ export class PerformanceAgent extends AiAgent<AgentFocus> {
|
|
|
967
967
|
|
|
968
968
|
const key = `getMainThreadTrackSummary({min: ${bounds.min}, max: ${bounds.max}})`;
|
|
969
969
|
this.#cacheFunctionResult(focus, key, summary);
|
|
970
|
+
const widgets: AiWidget[] = [];
|
|
971
|
+
widgets.push({
|
|
972
|
+
name: 'TIMELINE_RANGE_SUMMARY',
|
|
973
|
+
data: {
|
|
974
|
+
parsedTrace,
|
|
975
|
+
bounds,
|
|
976
|
+
track: 'main',
|
|
977
|
+
},
|
|
978
|
+
});
|
|
979
|
+
|
|
980
|
+
widgets.push({
|
|
981
|
+
name: 'BOTTOM_UP_TREE',
|
|
982
|
+
data: {
|
|
983
|
+
bounds,
|
|
984
|
+
parsedTrace,
|
|
985
|
+
},
|
|
986
|
+
});
|
|
987
|
+
|
|
970
988
|
return {
|
|
971
989
|
result: {summary},
|
|
972
|
-
widgets
|
|
973
|
-
name: 'TIMELINE_RANGE_SUMMARY',
|
|
974
|
-
data: {
|
|
975
|
-
parsedTrace,
|
|
976
|
-
bounds,
|
|
977
|
-
track: 'main',
|
|
978
|
-
},
|
|
979
|
-
}],
|
|
990
|
+
widgets,
|
|
980
991
|
};
|
|
981
992
|
},
|
|
982
993
|
|