Skip to content

Commit 1b6aa22

Browse files
wolfibDevtools-frontend LUCI CQ
authored andcommitted
[Refactoring] Migrate handleExternalNetworkRequest to ConversationHandler
Step 2 of multiple Bug: 427407133 Change-Id: I1be9e370b7f8348d19d3f0f79df6b001321ce7c0 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6818235 Reviewed-by: Alex Rudenko <[email protected]> Commit-Queue: Wolfgang Beyer <[email protected]>
1 parent 5a1264d commit 1b6aa22

File tree

6 files changed

+323
-182
lines changed

6 files changed

+323
-182
lines changed

front_end/entrypoints/main/MainImpl.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,10 +1100,9 @@ export async function handleExternalRequestGenerator(input: ExternalRequestInput
11001100
});
11011101
}
11021102
case 'NETWORK_DEBUGGER': {
1103-
const AiAssistance = await import('../../panels/ai_assistance/ai_assistance.js');
11041103
const AiAssistanceModel = await import('../../models/ai_assistance/ai_assistance.js');
1105-
const panelInstance = await AiAssistance.AiAssistancePanel.instance();
1106-
return panelInstance.handleExternalRequest({
1104+
const conversationHandler = await AiAssistanceModel.ConversationHandler.instance();
1105+
return await conversationHandler.handleExternalRequest({
11071106
conversationType: AiAssistanceModel.ConversationType.NETWORK,
11081107
prompt: input.args.prompt,
11091108
requestUrl: input.args.requestUrl,

front_end/models/ai_assistance/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ ts_library("unittests") {
7373
"AgentProject.test.ts",
7474
"AiHistoryStorage.test.ts",
7575
"ChangeManager.test.ts",
76+
"ConversationHandler.test.ts",
7677
"EvaluateAction.test.ts",
7778
"ExtensionScope.test.ts",
7879
"agents/AiAgent.test.ts",
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
// Copyright 2025 The Chromium Authors. All rights reserved.
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 Common from '../../core/common/common.js';
6+
import * as Host from '../../core/host/host.js';
7+
import * as SDK from '../../core/sdk/sdk.js';
8+
import * as AiAssistanceModel from '../../models/ai_assistance/ai_assistance.js';
9+
import {
10+
createNetworkRequest,
11+
mockAidaClient,
12+
} from '../../testing/AiAssistanceHelpers.js';
13+
import {registerNoopActions, updateHostConfig} from '../../testing/EnvironmentHelpers.js';
14+
import {describeWithMockConnection} from '../../testing/MockConnection.js';
15+
import {createNetworkPanelForMockConnection} from '../../testing/NetworkHelpers.js';
16+
import * as Snackbars from '../../ui/components/snackbars/snackbars.js';
17+
18+
describeWithMockConnection('ConversationHandler', () => {
19+
describe('handleExternalRequest', () => {
20+
const explanation = 'I need more information';
21+
22+
beforeEach(async () => {
23+
AiAssistanceModel.ConversationHandler.removeInstance(); // maybe move out
24+
registerNoopActions([
25+
'elements.toggle-element-search', 'timeline.record-reload', 'timeline.toggle-recording',
26+
'timeline.show-history', 'components.collect-garbage'
27+
]);
28+
Common.Settings.moduleSetting('ai-assistance-enabled').set(true);
29+
updateHostConfig({
30+
devToolsFreestyler: {
31+
enabled: true,
32+
33+
},
34+
devToolsAiAssistanceNetworkAgent: {
35+
enabled: true,
36+
}
37+
});
38+
});
39+
40+
describe('can be blocked', () => {
41+
it('by a setting', async () => {
42+
Common.Settings.moduleSetting('ai-assistance-enabled').set(false);
43+
const conversationHandler = AiAssistanceModel.ConversationHandler.instance({
44+
aidaClient: mockAidaClient([[{explanation}]]),
45+
aidaAvailability: Host.AidaClient.AidaAccessPreconditions.AVAILABLE,
46+
});
47+
const generator = await conversationHandler.handleExternalRequest({
48+
prompt: 'Please help me debug this problem',
49+
conversationType: AiAssistanceModel.ConversationType.STYLING,
50+
});
51+
const response = await generator.next();
52+
assert.strictEqual(response.value.type, 'error');
53+
assert.strictEqual(
54+
response.value.message,
55+
'For AI features to be available, you need to enable AI assistance in DevTools settings.');
56+
});
57+
58+
it('by feature availability', async () => {
59+
const conversationHandler = AiAssistanceModel.ConversationHandler.instance({
60+
aidaClient: mockAidaClient([[{explanation}]]),
61+
aidaAvailability: Host.AidaClient.AidaAccessPreconditions.SYNC_IS_PAUSED,
62+
});
63+
const generator = await conversationHandler.handleExternalRequest({
64+
prompt: 'Please help me debug this problem',
65+
conversationType: AiAssistanceModel.ConversationType.STYLING,
66+
});
67+
const response = await generator.next();
68+
assert.strictEqual(response.value.type, 'error');
69+
assert.strictEqual(
70+
response.value.message,
71+
'This feature is only available when you sign into Chrome with your Google account.');
72+
});
73+
74+
it('by user age', async () => {
75+
updateHostConfig({
76+
aidaAvailability: {
77+
blockedByAge: true,
78+
},
79+
devToolsFreestyler: {
80+
enabled: true,
81+
},
82+
});
83+
const conversationHandler = AiAssistanceModel.ConversationHandler.instance({
84+
aidaClient: mockAidaClient([[{explanation}]]),
85+
aidaAvailability: Host.AidaClient.AidaAccessPreconditions.AVAILABLE,
86+
});
87+
const generator = await conversationHandler.handleExternalRequest({
88+
prompt: 'Please help me debug this problem',
89+
conversationType: AiAssistanceModel.ConversationType.STYLING
90+
});
91+
const response = await generator.next();
92+
assert.strictEqual(response.value.type, 'error');
93+
assert.strictEqual(
94+
response.value.message, 'This feature is only available to users who are 18 years of age or older.');
95+
});
96+
});
97+
98+
it('returns an explanation for network assistance requests', async () => {
99+
await createNetworkPanelForMockConnection();
100+
Common.Settings.moduleSetting('ai-assistance-enabled').set(true);
101+
const conversationHandler = AiAssistanceModel.ConversationHandler.instance({
102+
aidaClient: mockAidaClient([[{explanation}]]),
103+
aidaAvailability: Host.AidaClient.AidaAccessPreconditions.AVAILABLE,
104+
});
105+
const snackbarShowStub = sinon.stub(Snackbars.Snackbar.Snackbar, 'show');
106+
107+
const request = createNetworkRequest();
108+
const networkManager = sinon.createStubInstance(SDK.NetworkManager.NetworkManager, {
109+
requestForURL: request,
110+
});
111+
sinon.stub(SDK.TargetManager.TargetManager.instance(), 'models').returns([networkManager]);
112+
113+
const generator = await conversationHandler.handleExternalRequest({
114+
prompt: 'Please help me debug this problem',
115+
conversationType: AiAssistanceModel.ConversationType.NETWORK,
116+
requestUrl: 'https://localhost:8080/'
117+
});
118+
let response = await generator.next();
119+
assert.strictEqual(response.value.message, 'Analyzing network data');
120+
response = await generator.next();
121+
assert.strictEqual(response.value.message, explanation);
122+
sinon.assert.calledOnceWithExactly(snackbarShowStub, {message: 'DevTools received an external request'});
123+
});
124+
});
125+
});

0 commit comments

Comments
 (0)