Skip to content

Commit 996c516

Browse files
Connor ClarkDevtools-frontend LUCI CQ
authored andcommitted
[AI] Add PERFORMANCE_ANALYZE external request
This external request uses the full trace agent, rather than confined to a specific insight. No impact on PERFORMANCE_ANALYZE_INSIGHT, but it will be removed soon. Bug: 425270067 Change-Id: I92553373618c2ed55df5464d735c45d6517d6a76 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6886192 Commit-Queue: Connor Clark <cjamcl@chromium.org> Reviewed-by: Paul Irish <paulirish@chromium.org> Auto-Submit: Connor Clark <cjamcl@chromium.org>
1 parent 77e1250 commit 996c516

3 files changed

Lines changed: 59 additions & 1 deletion

File tree

front_end/entrypoints/main/MainImpl.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,8 +1052,12 @@ type ExternalRequestInput = {
10521052
}|{
10531053
kind: 'PERFORMANCE_RELOAD_GATHER_INSIGHTS',
10541054
}|{
1055+
// TODO(b/425270067): remove once MCP removes insight tool.
10551056
kind: 'PERFORMANCE_ANALYZE_INSIGHT',
10561057
args: {insightTitle: string, prompt: string},
1058+
}|{
1059+
kind: 'PERFORMANCE_ANALYZE',
1060+
args: {prompt: string},
10571061
}|{
10581062
kind: 'NETWORK_DEBUGGER',
10591063
args: {requestUrl: string, prompt: string},
@@ -1104,6 +1108,17 @@ export async function handleExternalRequestGenerator(input: ExternalRequestInput
11041108
traceModel,
11051109
});
11061110
}
1111+
case 'PERFORMANCE_ANALYZE': {
1112+
const AiAssistanceModel = await import('../../models/ai_assistance/ai_assistance.js');
1113+
const TimelinePanel = await import('../../panels/timeline/timeline.js');
1114+
const traceModel = TimelinePanel.TimelinePanel.TimelinePanel.instance().model;
1115+
const conversationHandler = AiAssistanceModel.ConversationHandler.instance();
1116+
return await conversationHandler.handleExternalRequest({
1117+
conversationType: AiAssistanceModel.ConversationType.PERFORMANCE_FULL,
1118+
prompt: input.args.prompt,
1119+
traceModel,
1120+
});
1121+
}
11071122
case 'NETWORK_DEBUGGER': {
11081123
const AiAssistanceModel = await import('../../models/ai_assistance/ai_assistance.js');
11091124
const conversationHandler = await AiAssistanceModel.ConversationHandler.instance();

front_end/models/ai_assistance/ConversationHandler.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ export interface ExternalPerformanceInsightsRequestParameters {
5050
traceModel: Trace.TraceModel.Model;
5151
}
5252

53+
export interface ExternalPerformanceRequestParameters {
54+
conversationType: ConversationType.PERFORMANCE_FULL;
55+
prompt: string;
56+
traceModel: Trace.TraceModel.Model;
57+
}
58+
5359
const UIStrings = {
5460
/**
5561
* @description Notification shown to the user whenever DevTools receives an external request.
@@ -178,7 +184,7 @@ export class ConversationHandler {
178184
*/
179185
async handleExternalRequest(
180186
parameters: ExternalStylingRequestParameters|ExternalNetworkRequestParameters|
181-
ExternalPerformanceInsightsRequestParameters,
187+
ExternalPerformanceInsightsRequestParameters|ExternalPerformanceRequestParameters,
182188
): Promise<AsyncGenerator<ExternalRequestResponse, ExternalRequestResponse>> {
183189
try {
184190
Snackbars.Snackbar.Snackbar.show({message: i18nString(UIStrings.externalRequestReceived)});
@@ -203,6 +209,8 @@ export class ConversationHandler {
203209
}
204210
return await this.#handleExternalPerformanceInsightsConversation(
205211
parameters.prompt, parameters.insightTitle, parameters.traceModel);
212+
case ConversationType.PERFORMANCE_FULL:
213+
return await this.#handleExternalPerformanceConversation(parameters.prompt, parameters.traceModel);
206214
case ConversationType.NETWORK:
207215
if (!parameters.requestUrl) {
208216
return this.#generateErrorResponse('The url is required for debugging a network request.');
@@ -306,6 +314,23 @@ export class ConversationHandler {
306314
});
307315
}
308316

317+
async #handleExternalPerformanceConversation(prompt: string, traceModel: Trace.TraceModel.Model):
318+
Promise<AsyncGenerator<ExternalRequestResponse, ExternalRequestResponse>> {
319+
const agent = this.createAgent(ConversationType.PERFORMANCE_FULL);
320+
const focusOrError = await Tracing.ExternalRequests.getPerformanceAgentFocusToDebug(
321+
traceModel,
322+
);
323+
if ('error' in focusOrError) {
324+
return this.#generateErrorResponse(focusOrError.error);
325+
}
326+
return this.#doExternalConversation({
327+
conversationType: ConversationType.PERFORMANCE_FULL,
328+
aiAgent: agent,
329+
prompt,
330+
selected: new PerformanceTraceContext(focusOrError.focus),
331+
});
332+
}
333+
309334
async #handleExternalNetworkConversation(prompt: string, requestUrl: string):
310335
Promise<AsyncGenerator<ExternalRequestResponse, ExternalRequestResponse>> {
311336
const networkAgent = this.createAgent(ConversationType.NETWORK);

front_end/services/tracing/ExternalRequests.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,21 @@ export async function getInsightAgentFocusToDebug(
5454
const focus = TimelineUtils.AIContext.AgentFocus.fromInsight(parsedTrace, insight, insights.bounds);
5555
return {focus};
5656
}
57+
58+
export async function getPerformanceAgentFocusToDebug(model: Trace.TraceModel.Model): Promise<InsightResponse> {
59+
const parsedTrace = model.parsedTrace();
60+
const insights = model.traceInsights();
61+
const traceMetadata = model.metadata();
62+
if (!insights || !parsedTrace || !traceMetadata) {
63+
return {
64+
error:
65+
'No trace has been recorded, so we cannot analyze the performance. Must run the devtools_performance_run_trace tool first.',
66+
};
67+
}
68+
69+
// Currently only support a single insight set.
70+
const insightSet = [...insights.values()].at(0) ?? null;
71+
72+
const focus = TimelineUtils.AIContext.AgentFocus.full(parsedTrace, insightSet, traceMetadata);
73+
return {focus};
74+
}

0 commit comments

Comments
 (0)