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
package/front_end/models/ai_assistance/{agents/ConversationSummaryAgent.ts → ConversationSummary.ts}
RENAMED
|
@@ -2,10 +2,10 @@
|
|
|
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 Host from '
|
|
6
|
-
import * as Root from '
|
|
5
|
+
import * as Host from '../../core/host/host.js';
|
|
6
|
+
import * as Root from '../../core/root/root.js';
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import {runOneShotPrompt} from './AiUtils.js';
|
|
9
9
|
|
|
10
10
|
const preamble = `### Role
|
|
11
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.
|
|
@@ -98,90 +98,53 @@ color: red;
|
|
|
98
98
|
- Professional, objective, and dense.
|
|
99
99
|
- Past tense for actions; Present tense for technical facts.`;
|
|
100
100
|
|
|
101
|
-
export
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
super();
|
|
105
|
-
this.#conversation = conversation;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
override getURL(): string {
|
|
109
|
-
return 'devtools://ai-assistance';
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
getItem(): string {
|
|
113
|
-
return this.#conversation;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
override getTitle(): string {
|
|
117
|
-
return 'Conversation';
|
|
118
|
-
}
|
|
101
|
+
export interface ConversationSummaryOptions {
|
|
102
|
+
aidaClient: Host.AidaClient.AidaClient;
|
|
103
|
+
serverSideLoggingEnabled?: boolean;
|
|
119
104
|
}
|
|
120
105
|
|
|
121
106
|
/**
|
|
122
|
-
*
|
|
107
|
+
* A class that takes a full conversation between a user and an agent in markdown
|
|
123
108
|
* format and produces a succinct summary of the conversation.
|
|
124
109
|
*
|
|
125
110
|
* This summary is designed to be read by a local agent in the user's IDE and it
|
|
126
111
|
* will be used to help apply fixes to the user's local codebase based on the
|
|
127
112
|
* debugging information the devtools agent found.
|
|
128
|
-
*
|
|
129
|
-
* This agent is not intended to be used directly by users in the AI Assistance
|
|
130
|
-
* panel when chatting with DevTools AI.
|
|
131
113
|
*/
|
|
132
|
-
export class
|
|
133
|
-
|
|
114
|
+
export class ConversationSummary {
|
|
115
|
+
readonly #aidaClient: Host.AidaClient.AidaClient;
|
|
116
|
+
readonly #serverSideLoggingEnabled: boolean;
|
|
134
117
|
|
|
135
|
-
|
|
136
|
-
|
|
118
|
+
constructor(options: ConversationSummaryOptions) {
|
|
119
|
+
this.#aidaClient = options.aidaClient;
|
|
120
|
+
this.#serverSideLoggingEnabled = options.serverSideLoggingEnabled ?? false;
|
|
137
121
|
}
|
|
138
122
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
return Root.Runtime.hostConfig.devToolsFreestyler?.userTier;
|
|
142
|
-
}
|
|
123
|
+
async summarizeConversation(conversation: string): Promise<string> {
|
|
124
|
+
const enhancedQuery = `Summarize the following conversation:\n\n${conversation}`;
|
|
143
125
|
|
|
144
|
-
get options(): RequestOptions {
|
|
145
126
|
// TODO(b/491772868): tidy up userTier & feature flags in the backend.
|
|
146
127
|
const temperature = Root.Runtime.hostConfig.devToolsFreestyler?.temperature;
|
|
147
128
|
const modelId = Root.Runtime.hostConfig.devToolsFreestyler?.modelId;
|
|
129
|
+
const userTier = Root.Runtime.hostConfig.devToolsFreestyler?.userTier;
|
|
148
130
|
|
|
149
|
-
|
|
131
|
+
const resultText = await runOneShotPrompt({
|
|
132
|
+
aidaClient: this.#aidaClient,
|
|
133
|
+
preamble,
|
|
134
|
+
query: enhancedQuery,
|
|
135
|
+
clientFeature: Host.AidaClient.ClientFeature.CHROME_CONVERSATION_SUMMARY_AGENT,
|
|
150
136
|
temperature,
|
|
151
137
|
modelId,
|
|
152
|
-
|
|
153
|
-
|
|
138
|
+
userTier,
|
|
139
|
+
serverSideLoggingEnabled: this.#serverSideLoggingEnabled,
|
|
140
|
+
});
|
|
154
141
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
return;
|
|
142
|
+
if (!resultText) {
|
|
143
|
+
throw new Error('Failed to summarize conversation');
|
|
158
144
|
}
|
|
159
145
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
{
|
|
164
|
-
title: 'Conversation transcript',
|
|
165
|
-
text: context.getItem(),
|
|
166
|
-
},
|
|
167
|
-
],
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
override async enhanceQuery(query: string, context: ConversationContext<string>|null): Promise<string> {
|
|
172
|
-
const conversation = context ? context.getItem() : query;
|
|
173
|
-
return `Summarize the following conversation:\n\n${conversation}`;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
async summarizeConversation(conversation: string): Promise<string> {
|
|
177
|
-
const context = new ConversationSummaryContext(conversation);
|
|
178
|
-
const response = await Array.fromAsync(this.run('', {selected: context}));
|
|
179
|
-
const lastResponse = response.at(-1);
|
|
180
|
-
if (lastResponse && lastResponse.type === ResponseType.ANSWER && lastResponse.complete === true) {
|
|
181
|
-
const disclaimer =
|
|
182
|
-
'*Note: The code fixes and findings above were identified on a live page in DevTools. When applying them to your codebase, please adapt them to your project\'s specific technical stack (e.g., Tailwind CSS classes, CSS modules, framework components) rather than applying them as literal CSS overrides.*';
|
|
183
|
-
return `${lastResponse.text.trim()}\n\n${disclaimer}`;
|
|
184
|
-
}
|
|
185
|
-
throw new Error('Failed to summarize conversation');
|
|
146
|
+
const disclaimer =
|
|
147
|
+
'*Note: The code fixes and findings above were identified on a live page in DevTools. When applying them to your codebase, please adapt them to your project\'s specific technical stack (e.g., Tailwind CSS classes, CSS modules, framework components) rather than applying them as literal CSS overrides.*';
|
|
148
|
+
return `${resultText.trim()}\n\n${disclaimer}`;
|
|
186
149
|
}
|
|
187
150
|
}
|
|
@@ -34,7 +34,6 @@ export class ExtensionScope {
|
|
|
34
34
|
}) => Promise<void>> = [];
|
|
35
35
|
#changeManager: ChangeManager;
|
|
36
36
|
#agentId: string;
|
|
37
|
-
#turnId?: number;
|
|
38
37
|
/** Don't use directly use the getter */
|
|
39
38
|
#frameId?: Protocol.Page.FrameId|null;
|
|
40
39
|
/** Don't use directly use the getter */
|
|
@@ -42,12 +41,11 @@ export class ExtensionScope {
|
|
|
42
41
|
|
|
43
42
|
readonly #bindingMutex = new Common.Mutex.Mutex();
|
|
44
43
|
|
|
45
|
-
constructor(changes: ChangeManager, agentId: string, selectedNode: SDK.DOMModel.DOMNode|null
|
|
44
|
+
constructor(changes: ChangeManager, agentId: string, selectedNode: SDK.DOMModel.DOMNode|null) {
|
|
46
45
|
this.#changeManager = changes;
|
|
47
46
|
const frameId = selectedNode?.frameId();
|
|
48
47
|
const target = selectedNode?.domModel().target();
|
|
49
48
|
this.#agentId = agentId;
|
|
50
|
-
this.#turnId = turnId;
|
|
51
49
|
this.#target = target;
|
|
52
50
|
this.#frameId = frameId;
|
|
53
51
|
}
|
|
@@ -357,7 +355,6 @@ export class ExtensionScope {
|
|
|
357
355
|
const sanitizedStyles = await this.sanitizedStyleChanges(context.selector, arg.styles);
|
|
358
356
|
const styleChanges = await this.#changeManager.addChange(cssModel, this.frameId, {
|
|
359
357
|
groupId: this.#agentId,
|
|
360
|
-
turnId: this.#turnId,
|
|
361
358
|
sourceLocation: context.sourceLocation,
|
|
362
359
|
selector: context.selector,
|
|
363
360
|
simpleSelector: context.simpleSelector,
|
|
@@ -2,21 +2,12 @@
|
|
|
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 Host from '
|
|
6
|
-
import * as Root from '
|
|
7
|
-
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
import {PerformanceTraceContext} from './PerformanceAgent.js';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Preamble clocks in at ~970 tokens.
|
|
15
|
-
* The prose is around 4.5 chars per token.
|
|
16
|
-
* The data can be as bad as 1.8 chars per token
|
|
17
|
-
*
|
|
18
|
-
* Check token length in https://aistudio.google.com/
|
|
19
|
-
*/
|
|
5
|
+
import * as Host from '../../core/host/host.js';
|
|
6
|
+
import * as Root from '../../core/root/root.js';
|
|
7
|
+
|
|
8
|
+
import {runOneShotPrompt} from './AiUtils.js';
|
|
9
|
+
import type {AICallTree} from './performance/AICallTree.js';
|
|
10
|
+
|
|
20
11
|
const callTreePreamble = `You are an expert performance analyst embedded within Chrome DevTools.
|
|
21
12
|
You meticulously examine web application behavior captured by the Chrome DevTools Performance Panel and Chrome tracing.
|
|
22
13
|
You will receive a structured text representation of a call tree, derived from a user-selected call frame within a performance trace's flame chart.
|
|
@@ -79,80 +70,6 @@ The 'calculatePosition' function, taking 80ms, is a potential bottleneck.
|
|
|
79
70
|
Consider optimizing the position calculation logic or reducing the frequency of calls to improve animation performance.
|
|
80
71
|
`;
|
|
81
72
|
|
|
82
|
-
export class PerformanceAnnotationsAgent extends AiAgent<AgentFocus> {
|
|
83
|
-
override preamble = callTreePreamble;
|
|
84
|
-
|
|
85
|
-
get clientFeature(): Host.AidaClient.ClientFeature {
|
|
86
|
-
return Host.AidaClient.ClientFeature.CHROME_PERFORMANCE_ANNOTATIONS_AGENT;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
get userTier(): string|undefined {
|
|
90
|
-
return Root.Runtime.hostConfig.devToolsAiAssistancePerformanceAgent?.userTier;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
get options(): RequestOptions {
|
|
94
|
-
const temperature = Root.Runtime.hostConfig.devToolsAiAssistancePerformanceAgent?.temperature;
|
|
95
|
-
const modelId = Root.Runtime.hostConfig.devToolsAiAssistancePerformanceAgent?.modelId;
|
|
96
|
-
|
|
97
|
-
return {
|
|
98
|
-
temperature,
|
|
99
|
-
modelId,
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
async *
|
|
104
|
-
handleContextDetails(context: ConversationContext<AgentFocus>|null): AsyncGenerator<ContextResponse, void, void> {
|
|
105
|
-
if (!context) {
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const focus = context.getItem();
|
|
110
|
-
if (!focus.callTree) {
|
|
111
|
-
throw new Error('unexpected context');
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
const callTree = focus.callTree;
|
|
115
|
-
|
|
116
|
-
yield {
|
|
117
|
-
type: ResponseType.CONTEXT,
|
|
118
|
-
details: [
|
|
119
|
-
{
|
|
120
|
-
title: 'Selected call tree',
|
|
121
|
-
text: callTree.serialize(),
|
|
122
|
-
},
|
|
123
|
-
],
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
override async enhanceQuery(query: string, context: ConversationContext<AgentFocus>|null): Promise<string> {
|
|
128
|
-
if (!context) {
|
|
129
|
-
return query;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const focus = context.getItem();
|
|
133
|
-
if (!focus.callTree) {
|
|
134
|
-
throw new Error('unexpected context');
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const callTree = focus.callTree;
|
|
138
|
-
const contextString = callTree.serialize();
|
|
139
|
-
return `${contextString}\n\n# User request\n\n${query}`;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Used in the Performance panel to automatically generate a label for a selected entry.
|
|
144
|
-
*/
|
|
145
|
-
async generateAIEntryLabel(callTree: AICallTree): Promise<string> {
|
|
146
|
-
const context = PerformanceTraceContext.fromCallTree(callTree);
|
|
147
|
-
const response = await Array.fromAsync(this.run(AI_LABEL_GENERATION_PROMPT, {selected: context}));
|
|
148
|
-
const lastResponse = response.at(-1);
|
|
149
|
-
if (lastResponse && lastResponse.type === ResponseType.ANSWER && lastResponse.complete === true) {
|
|
150
|
-
return lastResponse.text.trim();
|
|
151
|
-
}
|
|
152
|
-
throw new Error('Failed to generate AI entry label');
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
73
|
const AI_LABEL_GENERATION_PROMPT = `## Instruction:
|
|
157
74
|
Generate a concise label (max 60 chars, single line) describing the *user-visible effect* of the selected call tree's activity, based solely on the provided call tree data.
|
|
158
75
|
|
|
@@ -168,3 +85,44 @@ Generate a concise label (max 60 chars, single line) describing the *user-visibl
|
|
|
168
85
|
- Only include third-party script names if their identification is highly confident.
|
|
169
86
|
- Very important: Only output the 60 character label text, your response will be used in full to show to the user as an annotation in the timeline.
|
|
170
87
|
`;
|
|
88
|
+
|
|
89
|
+
export interface PerformanceAnnotationsOptions {
|
|
90
|
+
aidaClient: Host.AidaClient.AidaClient;
|
|
91
|
+
serverSideLoggingEnabled?: boolean;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export class PerformanceAnnotations {
|
|
95
|
+
readonly #aidaClient: Host.AidaClient.AidaClient;
|
|
96
|
+
readonly #serverSideLoggingEnabled: boolean;
|
|
97
|
+
|
|
98
|
+
constructor(options: PerformanceAnnotationsOptions) {
|
|
99
|
+
this.#aidaClient = options.aidaClient;
|
|
100
|
+
this.#serverSideLoggingEnabled = options.serverSideLoggingEnabled ?? false;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async generateAIEntryLabel(callTree: AICallTree): Promise<string> {
|
|
104
|
+
const contextString = callTree.serialize();
|
|
105
|
+
const query = `${contextString}\n\n# User request\n\n${AI_LABEL_GENERATION_PROMPT}`;
|
|
106
|
+
|
|
107
|
+
const temperature = Root.Runtime.hostConfig.devToolsAiAssistancePerformanceAgent?.temperature;
|
|
108
|
+
const modelId = Root.Runtime.hostConfig.devToolsAiAssistancePerformanceAgent?.modelId;
|
|
109
|
+
const userTier = Root.Runtime.hostConfig.devToolsAiAssistancePerformanceAgent?.userTier;
|
|
110
|
+
|
|
111
|
+
const resultText = await runOneShotPrompt({
|
|
112
|
+
aidaClient: this.#aidaClient,
|
|
113
|
+
preamble: callTreePreamble,
|
|
114
|
+
query,
|
|
115
|
+
clientFeature: Host.AidaClient.ClientFeature.CHROME_PERFORMANCE_ANNOTATIONS_AGENT,
|
|
116
|
+
temperature,
|
|
117
|
+
modelId,
|
|
118
|
+
userTier,
|
|
119
|
+
serverSideLoggingEnabled: this.#serverSideLoggingEnabled,
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
if (!resultText) {
|
|
123
|
+
throw new Error('Failed to generate AI entry label');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return resultText.trim();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -13,6 +13,8 @@ import {ChangeManager} from '../ChangeManager.js';
|
|
|
13
13
|
import {LighthouseFormatter} from '../data_formatters/LighthouseFormatter.js';
|
|
14
14
|
import {debugLog} from '../debug.js';
|
|
15
15
|
import {ExtensionScope} from '../ExtensionScope.js';
|
|
16
|
+
import {ToolName} from '../tools/Tool.js';
|
|
17
|
+
import {ToolRegistry} from '../tools/ToolRegistry.js';
|
|
16
18
|
|
|
17
19
|
import {
|
|
18
20
|
AiAgent,
|
|
@@ -25,10 +27,8 @@ import {
|
|
|
25
27
|
} from './AiAgent.js';
|
|
26
28
|
import {
|
|
27
29
|
type CreateExtensionScopeFunction,
|
|
28
|
-
executeJavaScriptFunction,
|
|
29
30
|
type ExecuteJsAgentOptions,
|
|
30
31
|
executeJsCode,
|
|
31
|
-
JavascriptExecutor
|
|
32
32
|
} from './ExecuteJavascript.js';
|
|
33
33
|
|
|
34
34
|
/**
|
|
@@ -81,12 +81,6 @@ If the user asks a question that requires an investigation of a problem, use thi
|
|
|
81
81
|
- [Suggestion 2]
|
|
82
82
|
`;
|
|
83
83
|
|
|
84
|
-
const SECURITY_WARNING = `**CRITICAL CONSTRAINT**: This Lighthouse report was imported from a file and is static.
|
|
85
|
-
You do NOT have access to the inspected page.
|
|
86
|
-
Tools like \`executeJavaScript\`, \`getStyles\`, or \`runAccessibilityAudits\` are disabled.
|
|
87
|
-
Do NOT attempt to use them or instruct the user that you will use them.
|
|
88
|
-
Rely ONLY on the static report data below.`;
|
|
89
|
-
|
|
90
84
|
export class AccessibilityContext extends ConversationContext<LHModel.ReporterTypes.ReportJSON> {
|
|
91
85
|
#lh: LHModel.ReporterTypes.ReportJSON;
|
|
92
86
|
|
|
@@ -123,28 +117,17 @@ export class AccessibilityAgent extends AiAgent<LHModel.ReporterTypes.ReportJSON
|
|
|
123
117
|
(overrides?: LHModel.RunTypes.RunOverrides) => Promise<LHModel.ReporterTypes.ReportJSON|null>;
|
|
124
118
|
|
|
125
119
|
#execJs: typeof executeJsCode;
|
|
126
|
-
#javascriptExecutor: JavascriptExecutor;
|
|
127
120
|
#changes: ChangeManager;
|
|
128
121
|
#createExtensionScope: CreateExtensionScopeFunction;
|
|
129
|
-
#currentTurnId = 0;
|
|
130
122
|
|
|
131
123
|
constructor(opts: ExecuteJsAgentOptions) {
|
|
132
124
|
super(opts);
|
|
133
125
|
this.#lighthouseRecording = opts.lighthouseRecording;
|
|
134
126
|
this.#changes = opts.changeManager || new ChangeManager();
|
|
135
127
|
this.#execJs = opts.execJs ?? executeJsCode;
|
|
136
|
-
this.#createExtensionScope =
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
});
|
|
140
|
-
this.#javascriptExecutor = new JavascriptExecutor(
|
|
141
|
-
{
|
|
142
|
-
executionMode: this.executionMode,
|
|
143
|
-
getContextNode: () => this.#getDocumentBodyNode(),
|
|
144
|
-
createExtensionScope: this.#createExtensionScope.bind(this),
|
|
145
|
-
changes: this.#changes,
|
|
146
|
-
},
|
|
147
|
-
this.#execJs);
|
|
128
|
+
this.#createExtensionScope = opts.createExtensionScope ?? ((changes: ChangeManager) => {
|
|
129
|
+
return new ExtensionScope(changes, this.sessionId, this.#getDocumentBodyNode());
|
|
130
|
+
});
|
|
148
131
|
}
|
|
149
132
|
|
|
150
133
|
get userTier(): string|undefined {
|
|
@@ -168,7 +151,6 @@ export class AccessibilityAgent extends AiAgent<LHModel.ReporterTypes.ReportJSON
|
|
|
168
151
|
}
|
|
169
152
|
|
|
170
153
|
protected override async preRun(): Promise<void> {
|
|
171
|
-
this.#currentTurnId++;
|
|
172
154
|
const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
|
|
173
155
|
const domModel = target?.model(SDK.DOMModel.DOMModel);
|
|
174
156
|
// We need to ensure the document is requested so that #getDocumentBodyNode()
|
|
@@ -280,11 +262,33 @@ export class AccessibilityAgent extends AiAgent<LHModel.ReporterTypes.ReportJSON
|
|
|
280
262
|
}
|
|
281
263
|
});
|
|
282
264
|
|
|
283
|
-
|
|
284
|
-
|
|
265
|
+
const executeJsTool = ToolRegistry.get(ToolName.EXECUTE_JAVASCRIPT);
|
|
266
|
+
if (!executeJsTool) {
|
|
267
|
+
throw new Error('Required tool "executeJavaScript" not found');
|
|
285
268
|
}
|
|
286
|
-
|
|
287
|
-
|
|
269
|
+
this.declareFunction(executeJsTool.name, {
|
|
270
|
+
description: executeJsTool.description,
|
|
271
|
+
parameters: executeJsTool.parameters,
|
|
272
|
+
displayInfoFromArgs: executeJsTool.displayInfoFromArgs,
|
|
273
|
+
handler: async (args, options) => {
|
|
274
|
+
if (isImported) {
|
|
275
|
+
return {
|
|
276
|
+
error: 'Cannot use this tool on an imported file.',
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
return await executeJsTool.handler(
|
|
280
|
+
args,
|
|
281
|
+
{
|
|
282
|
+
conversationContext: this.context ?? null,
|
|
283
|
+
changeManager: this.#changes,
|
|
284
|
+
createExtensionScope: this.#createExtensionScope.bind(this),
|
|
285
|
+
execJs: this.#execJs,
|
|
286
|
+
getExecutionContextNode: () => this.#getDocumentBodyNode(),
|
|
287
|
+
},
|
|
288
|
+
options,
|
|
289
|
+
);
|
|
290
|
+
},
|
|
291
|
+
});
|
|
288
292
|
|
|
289
293
|
this.declareFunction<{explanation: string}, {audits: string}>('runAccessibilityAudits', {
|
|
290
294
|
description:
|
|
@@ -311,6 +315,11 @@ export class AccessibilityAgent extends AiAgent<LHModel.ReporterTypes.ReportJSON
|
|
|
311
315
|
},
|
|
312
316
|
handler: async params => {
|
|
313
317
|
debugLog('Function call: runAccessibilityAudits', params);
|
|
318
|
+
if (isImported) {
|
|
319
|
+
return {
|
|
320
|
+
error: 'Cannot use this tool on an imported file.',
|
|
321
|
+
};
|
|
322
|
+
}
|
|
314
323
|
if (!this.#lighthouseRecording) {
|
|
315
324
|
return {error: 'Lighthouse recording is not available.'};
|
|
316
325
|
}
|
|
@@ -375,6 +384,11 @@ export class AccessibilityAgent extends AiAgent<LHModel.ReporterTypes.ReportJSON
|
|
|
375
384
|
},
|
|
376
385
|
handler: async params => {
|
|
377
386
|
debugLog('Function call: getStyles', params);
|
|
387
|
+
if (isImported) {
|
|
388
|
+
return {
|
|
389
|
+
error: 'Cannot use this tool on an imported file.',
|
|
390
|
+
};
|
|
391
|
+
}
|
|
378
392
|
const node = await this.#resolvePathToNode(params.path);
|
|
379
393
|
if (!node) {
|
|
380
394
|
return {error: `Could not find the element with path: ${params.path}`};
|
|
@@ -445,6 +459,11 @@ export class AccessibilityAgent extends AiAgent<LHModel.ReporterTypes.ReportJSON
|
|
|
445
459
|
},
|
|
446
460
|
handler: async params => {
|
|
447
461
|
debugLog('Function call: getElementAccessibilityDetails', params);
|
|
462
|
+
if (isImported) {
|
|
463
|
+
return {
|
|
464
|
+
error: 'Cannot use this tool on an imported file.',
|
|
465
|
+
};
|
|
466
|
+
}
|
|
448
467
|
const node = await this.#resolvePathToNode(params.path);
|
|
449
468
|
if (!node) {
|
|
450
469
|
return {error: `Could not find the element with path: ${params.path}`};
|
|
@@ -522,10 +541,7 @@ export class AccessibilityAgent extends AiAgent<LHModel.ReporterTypes.ReportJSON
|
|
|
522
541
|
if (lhr) {
|
|
523
542
|
this.#declareFunctions();
|
|
524
543
|
}
|
|
525
|
-
|
|
526
|
-
if (lhr?.getItem().isImported) {
|
|
527
|
-
enhancedQuery = `${SECURITY_WARNING}\n\n${enhancedQuery}`;
|
|
528
|
-
}
|
|
544
|
+
const enhancedQuery = lhr ? `${this.#getInitialPayload(lhr)}\n# User request:\n\n` : '';
|
|
529
545
|
return `${enhancedQuery}${query}`;
|
|
530
546
|
}
|
|
531
547
|
|
|
@@ -332,6 +332,13 @@ export interface SourceFilesListAiWidget {
|
|
|
332
332
|
};
|
|
333
333
|
}
|
|
334
334
|
|
|
335
|
+
export interface NetworkRequestsListAiWidget {
|
|
336
|
+
name: 'NETWORK_REQUESTS_LIST';
|
|
337
|
+
data: {
|
|
338
|
+
requests: SDK.NetworkRequest.NetworkRequest[],
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
|
|
335
342
|
export interface LighthouseReportAiWidget {
|
|
336
343
|
name: 'LIGHTHOUSE_REPORT';
|
|
337
344
|
data: {
|
|
@@ -366,10 +373,10 @@ export interface SourceCodeAiWidget {
|
|
|
366
373
|
};
|
|
367
374
|
}
|
|
368
375
|
|
|
369
|
-
export type AiWidget =
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
376
|
+
export type AiWidget = ComputedStyleAiWidget|CoreVitalsAiWidget|StylePropertiesAiWidget|DomTreeAiWidget|
|
|
377
|
+
PerformanceTraceAiWidget|PerfInsightAiWidget|TimelineRangeSummaryAiWidget|BottomUpTreeAiWidget|SourceFileAiWidget|
|
|
378
|
+
LighthouseReportAiWidget|TimelineEventSummaryAiWidget|NetworkRequestGeneralHeadersAiWidget|SourceCodeAiWidget|
|
|
379
|
+
SourceFilesListAiWidget|NetworkRequestsListAiWidget;
|
|
373
380
|
|
|
374
381
|
export type FunctionCallHandlerResult<Result> = {
|
|
375
382
|
requiresApproval: true,
|
|
@@ -463,7 +470,7 @@ export abstract class AiAgent<T> {
|
|
|
463
470
|
|
|
464
471
|
readonly #sessionId: string;
|
|
465
472
|
readonly #aidaClient: Host.AidaClient.AidaClient;
|
|
466
|
-
|
|
473
|
+
#serverSideLoggingEnabled: boolean;
|
|
467
474
|
readonly confirmSideEffect: typeof Promise.withResolvers;
|
|
468
475
|
readonly #functionDeclarations = new Map<string, FunctionDeclaration<Record<string, unknown>, unknown>>();
|
|
469
476
|
readonly #allowedOrigin?: () => AllowedOriginResult;
|
|
@@ -502,8 +509,8 @@ export abstract class AiAgent<T> {
|
|
|
502
509
|
this.#allowedOrigin = opts.allowedOrigin;
|
|
503
510
|
}
|
|
504
511
|
|
|
505
|
-
async enhanceQuery(query: string, selected: ConversationContext<T>|null,
|
|
506
|
-
|
|
512
|
+
async enhanceQuery(query: string, selected: ConversationContext<T>|null,
|
|
513
|
+
multimodalInputType?: MultimodalInputType): Promise<string>;
|
|
507
514
|
async enhanceQuery(query: string): Promise<string> {
|
|
508
515
|
return query;
|
|
509
516
|
}
|
|
@@ -542,13 +549,29 @@ export abstract class AiAgent<T> {
|
|
|
542
549
|
clearCache(): void {
|
|
543
550
|
}
|
|
544
551
|
|
|
552
|
+
protected disableServerSideLogging(): void {
|
|
553
|
+
this.#serverSideLoggingEnabled = false;
|
|
554
|
+
}
|
|
555
|
+
|
|
545
556
|
popPendingMultimodalInput(): MultimodalInput|undefined {
|
|
546
557
|
return undefined;
|
|
547
558
|
}
|
|
548
559
|
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
560
|
+
/**
|
|
561
|
+
* Preamble features appended to the `client_version` in metadata.
|
|
562
|
+
* This is required ONLY for the Styling Agent for legacy reasons to serve
|
|
563
|
+
* different server-side preambles based on the Chrome version.
|
|
564
|
+
* Other agents should NOT set or override this.
|
|
565
|
+
* If you are curious about this, look for `do_conversation_handler.cc` in
|
|
566
|
+
* Google3 or chat to @jacktfranklin.
|
|
567
|
+
*/
|
|
568
|
+
preambleFeatures(): string[] {
|
|
569
|
+
return [];
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
buildRequest(part: Host.AidaClient.Part|Host.AidaClient.Part[],
|
|
573
|
+
role: Host.AidaClient.Role.USER|
|
|
574
|
+
Host.AidaClient.Role.ROLE_UNSPECIFIED): Host.AidaClient.DoConversationRequest {
|
|
552
575
|
const parts = Array.isArray(part) ? part : [part];
|
|
553
576
|
const currentMessage: Host.AidaClient.Content = {
|
|
554
577
|
parts,
|
|
@@ -589,7 +612,8 @@ export abstract class AiAgent<T> {
|
|
|
589
612
|
disable_user_content_logging: !(this.#serverSideLoggingEnabled ?? false),
|
|
590
613
|
string_session_id: this.#sessionId,
|
|
591
614
|
user_tier: userTier,
|
|
592
|
-
client_version:
|
|
615
|
+
client_version:
|
|
616
|
+
Root.Runtime.getChromeVersion() + this.preambleFeatures().map(feature => `+${feature}`).join(''),
|
|
593
617
|
},
|
|
594
618
|
|
|
595
619
|
functionality_type: enableAidaFunctionCalling ? Host.AidaClient.FunctionalityType.AGENTIC_CHAT :
|
|
@@ -693,6 +717,10 @@ export abstract class AiAgent<T> {
|
|
|
693
717
|
this.#functionDeclarations.clear();
|
|
694
718
|
}
|
|
695
719
|
|
|
720
|
+
/**
|
|
721
|
+
* Executed immediately after the current context is populated with the selected
|
|
722
|
+
* context and before the request is built.
|
|
723
|
+
*/
|
|
696
724
|
protected async preRun(): Promise<void> {
|
|
697
725
|
}
|
|
698
726
|
|
|
@@ -705,11 +733,11 @@ export abstract class AiAgent<T> {
|
|
|
705
733
|
},
|
|
706
734
|
multimodalInput?: MultimodalInput,
|
|
707
735
|
): AsyncGenerator<ResponseData, void, void> {
|
|
708
|
-
await this.preRun();
|
|
709
736
|
await options.selected?.refresh();
|
|
710
737
|
if (options.selected) {
|
|
711
738
|
this.context = options.selected;
|
|
712
739
|
}
|
|
740
|
+
await this.preRun();
|
|
713
741
|
|
|
714
742
|
const enhancedQuery = await this.enhanceQuery(initialQuery, options.selected, multimodalInput?.type);
|
|
715
743
|
Host.userMetrics.freestylerQueryLength(enhancedQuery.length);
|
|
@@ -129,6 +129,17 @@ Content:
|
|
|
129
129
|
"required": [],
|
|
130
130
|
"properties": {}
|
|
131
131
|
}
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
"name": "analyzeStorage",
|
|
135
|
+
"description": "Selects the page storage. Use this when asked about browser storage (localStorage, sessionStorage, cookies) and issues related to these.",
|
|
136
|
+
"parameters": {
|
|
137
|
+
"type": 6,
|
|
138
|
+
"description": "",
|
|
139
|
+
"nullable": true,
|
|
140
|
+
"required": [],
|
|
141
|
+
"properties": {}
|
|
142
|
+
}
|
|
132
143
|
}
|
|
133
144
|
],
|
|
134
145
|
"options": {},
|