chrome-devtools-frontend 1.0.1604514 → 1.0.1605219
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/AUTHORS +1 -0
- package/front_end/Tests.js +23 -7
- package/front_end/core/host/AidaClient.ts +114 -63
- package/front_end/core/host/AidaGcaTranslation.ts +6 -0
- package/front_end/core/host/GcaClient.ts +112 -0
- package/front_end/core/host/UserMetrics.ts +0 -1
- package/front_end/core/host/host.ts +2 -0
- package/front_end/core/root/ExperimentNames.ts +0 -1
- package/front_end/core/root/Runtime.ts +5 -0
- package/front_end/core/sdk/AutofillModel.ts +3 -2
- package/front_end/core/sdk/CSSModel.ts +3 -4
- package/front_end/core/sdk/CSSProperty.ts +1 -1
- package/front_end/core/sdk/ConsoleModel.ts +15 -13
- package/front_end/core/sdk/CookieModel.ts +5 -4
- package/front_end/core/sdk/DOMDebuggerModel.ts +20 -14
- package/front_end/core/sdk/DebuggerModel.ts +21 -36
- package/front_end/core/sdk/EventBreakpointsModel.ts +16 -6
- package/front_end/core/sdk/IsolateManager.ts +12 -7
- package/front_end/entrypoints/main/MainImpl.ts +0 -4
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +31 -17
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +1 -1
- package/front_end/models/emulation/DeviceModeModel.ts +21 -26
- package/front_end/models/trace/insights/LCPDiscovery.ts +14 -6
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +2 -17
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +36 -20
- package/front_end/panels/ai_assistance/components/chatMessage.css +5 -1
- package/front_end/panels/application/ApplicationPanelSidebar.ts +6 -0
- package/front_end/panels/application/IndexedDBViews.ts +0 -9
- package/front_end/panels/application/WebMCPTreeElement.ts +35 -0
- package/front_end/panels/application/WebMCPView.ts +118 -0
- package/front_end/panels/application/application.ts +4 -0
- package/front_end/panels/application/webMCPView.css +65 -0
- package/front_end/panels/common/aiCodeCompletionSummaryToolbar.css +1 -1
- package/front_end/panels/console/consoleView.css +4 -0
- package/front_end/panels/elements/StylesAiCodeCompletionProvider.ts +23 -2
- package/front_end/panels/elements/StylesSidebarPane.ts +85 -20
- package/front_end/panels/elements/elementsPanel.css +14 -0
- package/front_end/panels/network/NetworkLogViewColumns.ts +3 -3
- package/front_end/panels/recorder/components/recordingView.css +0 -6
- package/front_end/panels/sensors/SensorsView.ts +28 -59
- package/front_end/panels/timeline/EventsTimelineTreeView.ts +2 -2
- package/front_end/panels/timeline/ThirdPartyTreeView.ts +35 -36
- package/front_end/panels/timeline/TimelineDetailsView.ts +47 -41
- package/front_end/panels/timeline/TimelineTreeView.ts +13 -13
- package/front_end/panels/timeline/components/LiveMetricsView.ts +839 -783
- package/front_end/panels/timeline/thirdPartyTreeView.css +2 -2
- package/front_end/ui/components/buttons/button.css +2 -2
- package/front_end/ui/components/text_editor/AiCodeCompletionProvider.ts +0 -11
- package/front_end/ui/legacy/InspectorDrawerView.ts +206 -0
- package/front_end/ui/legacy/InspectorView.ts +41 -91
- package/front_end/ui/legacy/ViewManager.ts +14 -5
- package/front_end/ui/legacy/inspectorDrawerTabbedPane.css +5 -0
- package/front_end/ui/visual_logging/KnownContextValues.ts +2 -1
- package/package.json +1 -1
package/AUTHORS
CHANGED
|
@@ -58,6 +58,7 @@ Jithil p Ponnan <jithil.p@gmail.com>
|
|
|
58
58
|
Juba Borgohain <chromiumjuba@gmail.com>
|
|
59
59
|
Julian Geppert <spctstr@gmail.com>
|
|
60
60
|
Junseo Yoo <joon.yoo181@berkeley.edu>
|
|
61
|
+
Kanishk Ranjan <kanishkranjan17@gmail.com>
|
|
61
62
|
Karntino Areros <karntino.c.areros@gmail.com>
|
|
62
63
|
Kohei Ueno <kohei.ueno119@gmail.com>
|
|
63
64
|
Krishnal Ciccolella <ciccolella.krishnal@gmail.com>
|
package/front_end/Tests.js
CHANGED
|
@@ -1086,20 +1086,36 @@
|
|
|
1086
1086
|
this.takeControl({slownessFactor: 10});
|
|
1087
1087
|
};
|
|
1088
1088
|
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
top.removeEventListener('message', onMessage);
|
|
1089
|
+
const earlyTestResults = [];
|
|
1090
|
+
let testResultsWaiter = null;
|
|
1091
|
+
|
|
1092
|
+
top.addEventListener('message', event => {
|
|
1093
|
+
if (event.data && event.data.testOutput) {
|
|
1095
1094
|
const text = event.data.testOutput;
|
|
1095
|
+
if (testResultsWaiter) {
|
|
1096
|
+
testResultsWaiter(text);
|
|
1097
|
+
} else {
|
|
1098
|
+
earlyTestResults.push(text);
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
});
|
|
1102
|
+
|
|
1103
|
+
TestSuite.prototype.waitForTestResultsAsMessage = function() {
|
|
1104
|
+
const handleMessage = text => {
|
|
1105
|
+
testResultsWaiter = null;
|
|
1096
1106
|
if (text === 'PASS') {
|
|
1097
1107
|
this.releaseControl();
|
|
1098
1108
|
} else {
|
|
1099
1109
|
this.fail(text);
|
|
1100
1110
|
}
|
|
1101
1111
|
};
|
|
1102
|
-
|
|
1112
|
+
|
|
1113
|
+
if (earlyTestResults.length) {
|
|
1114
|
+
handleMessage(earlyTestResults.shift());
|
|
1115
|
+
return;
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
testResultsWaiter = handleMessage;
|
|
1103
1119
|
this.takeControl();
|
|
1104
1120
|
};
|
|
1105
1121
|
|
|
@@ -7,12 +7,14 @@ import * as Root from '../root/root.js';
|
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
9
|
AidaAccessPreconditions,
|
|
10
|
+
type AidaChunkResponse,
|
|
10
11
|
type AidaFunctionCallResponse,
|
|
11
12
|
AidaInferenceLanguage,
|
|
12
13
|
type AidaRegisterClientEvent,
|
|
13
14
|
ClientFeature,
|
|
14
15
|
type CompletionRequest,
|
|
15
16
|
type CompletionResponse,
|
|
17
|
+
debugLog,
|
|
16
18
|
type DoConversationRequest,
|
|
17
19
|
type DoConversationResponse,
|
|
18
20
|
FunctionalityType,
|
|
@@ -24,7 +26,10 @@ import {
|
|
|
24
26
|
Role,
|
|
25
27
|
UserTier,
|
|
26
28
|
} from './AidaClientTypes.js';
|
|
29
|
+
import {gcaChunkResponseToAidaChunkResponse} from './AidaGcaTranslation.js';
|
|
27
30
|
import * as DispatchHttpRequestClient from './DispatchHttpRequestClient.js';
|
|
31
|
+
import * as GcaClient from './GcaClient.js';
|
|
32
|
+
import type {GenerateContentResponse} from './GcaTypes.js';
|
|
28
33
|
import {InspectorFrontendHostInstance} from './InspectorFrontendHost.js';
|
|
29
34
|
import type {AidaClientResult, AidaCodeCompleteResult, SyncInformation} from './InspectorFrontendHostAPI.js';
|
|
30
35
|
import {bindOutputStream} from './ResourceLoader.js';
|
|
@@ -58,7 +63,17 @@ const AidaLanguageToMarkdown: Record<AidaInferenceLanguage, string> = {
|
|
|
58
63
|
export class AidaAbortError extends Error {}
|
|
59
64
|
export class AidaBlockError extends Error {}
|
|
60
65
|
|
|
66
|
+
interface AiStream {
|
|
67
|
+
write: (data: string) => Promise<void>;
|
|
68
|
+
close: () => Promise<void>;
|
|
69
|
+
read: () => Promise<string|null>;
|
|
70
|
+
fail: (e: Error) => void;
|
|
71
|
+
}
|
|
72
|
+
|
|
61
73
|
export class AidaClient {
|
|
74
|
+
// Delegate client
|
|
75
|
+
#gcaClient = new GcaClient.GcaClient();
|
|
76
|
+
|
|
62
77
|
static buildConsoleInsightsRequest(input: string): DoConversationRequest {
|
|
63
78
|
const disallowLogging = Root.Runtime.hostConfig.aidaAvailability?.disallowLogging ?? true;
|
|
64
79
|
const chromeVersion = Root.Runtime.getChromeVersion();
|
|
@@ -145,81 +160,71 @@ export class AidaClient {
|
|
|
145
160
|
};
|
|
146
161
|
})();
|
|
147
162
|
const streamId = bindOutputStream(stream);
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
()
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}
|
|
163
|
+
|
|
164
|
+
let response;
|
|
165
|
+
if (this.#gcaClient.enabled()) {
|
|
166
|
+
// Inline and remove the else clause after migration
|
|
167
|
+
response = this.#gcaClient.conversationRequest(request, streamId, options);
|
|
168
|
+
} else {
|
|
169
|
+
response = DispatchHttpRequestClient.makeHttpRequest(
|
|
170
|
+
{
|
|
171
|
+
service: SERVICE_NAME,
|
|
172
|
+
path: '/v1/aida:doConversation',
|
|
173
|
+
method: 'POST',
|
|
174
|
+
body: JSON.stringify(request),
|
|
175
|
+
streamId,
|
|
176
|
+
},
|
|
177
|
+
options);
|
|
178
|
+
}
|
|
179
|
+
response.then(
|
|
180
|
+
() => {
|
|
181
|
+
void stream.close();
|
|
182
|
+
},
|
|
183
|
+
err => {
|
|
184
|
+
debugLog('doConversation failed with error:', JSON.stringify(err));
|
|
185
|
+
if (err instanceof DispatchHttpRequestClient.DispatchHttpRequestError && err.response) {
|
|
186
|
+
const result = err.response;
|
|
187
|
+
if (result.statusCode === 403) {
|
|
188
|
+
stream.fail(new Error('Server responded: permission denied'));
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
if ('error' in result && result.error) {
|
|
192
|
+
stream.fail(new Error(`Cannot send request: ${result.error} ${result.detail || ''}`));
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
if ('netErrorName' in result && result.netErrorName === 'net::ERR_TIMED_OUT') {
|
|
196
|
+
stream.fail(new Error('doAidaConversation timed out'));
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
if (result.statusCode !== 200) {
|
|
200
|
+
stream.fail(new Error(`Request failed: ${JSON.stringify(result)}`));
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
stream.fail(err);
|
|
205
|
+
});
|
|
206
|
+
await (yield* this.#handleResponseStream(stream));
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async * #handleResponseStream(stream: AiStream): AsyncGenerator<DoConversationResponse, void, void> {
|
|
184
210
|
let chunk;
|
|
185
211
|
const text = [];
|
|
186
212
|
let inCodeChunk = false;
|
|
187
213
|
const functionCalls: AidaFunctionCallResponse[] = [];
|
|
188
214
|
let metadata: ResponseMetadata = {rpcGlobalId: 0};
|
|
189
215
|
while ((chunk = await stream.read())) {
|
|
216
|
+
debugLog('doConversation stream chunk:', chunk);
|
|
190
217
|
let textUpdated = false;
|
|
191
|
-
|
|
192
|
-
// boundary. Therefore each chunk may start with `[` or `,` and possibly
|
|
193
|
-
// followed by `]`. Each chunk may include one or more objects, so we
|
|
194
|
-
// make sure that each chunk becomes a well-formed JSON array when we
|
|
195
|
-
// parse it by adding `[` and `]` and removing `,` where appropriate.
|
|
196
|
-
if (!chunk.length) {
|
|
197
|
-
continue;
|
|
198
|
-
}
|
|
199
|
-
if (chunk.startsWith(',')) {
|
|
200
|
-
chunk = chunk.slice(1);
|
|
201
|
-
}
|
|
202
|
-
if (!chunk.startsWith('[')) {
|
|
203
|
-
chunk = '[' + chunk;
|
|
204
|
-
}
|
|
205
|
-
if (!chunk.endsWith(']')) {
|
|
206
|
-
chunk = chunk + ']';
|
|
207
|
-
}
|
|
208
|
-
let results;
|
|
209
|
-
try {
|
|
210
|
-
results = JSON.parse(chunk);
|
|
211
|
-
} catch (error) {
|
|
212
|
-
throw new Error('Cannot parse chunk: ' + chunk, {cause: error});
|
|
213
|
-
}
|
|
218
|
+
const results = this.#parseAndTranslate(chunk);
|
|
214
219
|
|
|
215
220
|
for (const result of results) {
|
|
216
|
-
if (
|
|
221
|
+
if (result.metadata) {
|
|
217
222
|
metadata = result.metadata;
|
|
218
223
|
if (metadata?.attributionMetadata?.attributionAction === RecitationAction.BLOCK) {
|
|
219
224
|
throw new AidaBlockError();
|
|
220
225
|
}
|
|
221
226
|
}
|
|
222
|
-
if (
|
|
227
|
+
if (result.textChunk) {
|
|
223
228
|
if (inCodeChunk) {
|
|
224
229
|
text.push(CODE_CHUNK_SEPARATOR());
|
|
225
230
|
inCodeChunk = false;
|
|
@@ -227,7 +232,7 @@ export class AidaClient {
|
|
|
227
232
|
|
|
228
233
|
text.push(result.textChunk.text);
|
|
229
234
|
textUpdated = true;
|
|
230
|
-
} else if (
|
|
235
|
+
} else if (result.codeChunk) {
|
|
231
236
|
if (!inCodeChunk) {
|
|
232
237
|
const language = AidaLanguageToMarkdown[result.codeChunk.inferenceLanguage as AidaInferenceLanguage] ?? '';
|
|
233
238
|
text.push(CODE_CHUNK_SEPARATOR(language));
|
|
@@ -236,7 +241,7 @@ export class AidaClient {
|
|
|
236
241
|
|
|
237
242
|
text.push(result.codeChunk.code);
|
|
238
243
|
textUpdated = true;
|
|
239
|
-
} else if (
|
|
244
|
+
} else if (result.functionCallChunk) {
|
|
240
245
|
functionCalls.push({
|
|
241
246
|
name: result.functionCallChunk.functionCall.name,
|
|
242
247
|
args: result.functionCallChunk.functionCall.args,
|
|
@@ -264,6 +269,40 @@ export class AidaClient {
|
|
|
264
269
|
};
|
|
265
270
|
}
|
|
266
271
|
|
|
272
|
+
#parseAndTranslate(chunk: string): AidaChunkResponse[] {
|
|
273
|
+
const results: AidaChunkResponse[] = this.#parseStreamChunk(chunk);
|
|
274
|
+
if (this.#gcaClient.enabled()) {
|
|
275
|
+
return (results as GenerateContentResponse[]).flatMap(gcaChunkResponseToAidaChunkResponse);
|
|
276
|
+
}
|
|
277
|
+
return results as AidaChunkResponse[];
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
281
|
+
#parseStreamChunk(chunk: string): any {
|
|
282
|
+
// The streamed response is a JSON array of objects, split at the object
|
|
283
|
+
// boundary. Therefore each chunk may start with `[` or `,` and possibly
|
|
284
|
+
// followed by `]`. Each chunk may include one or more objects, so we
|
|
285
|
+
// make sure that each chunk becomes a well-formed JSON array when we
|
|
286
|
+
// parse it by adding `[` and `]` and removing `,` where appropriate.
|
|
287
|
+
if (!chunk.length) {
|
|
288
|
+
return [];
|
|
289
|
+
}
|
|
290
|
+
if (chunk.startsWith(',')) {
|
|
291
|
+
chunk = chunk.slice(1);
|
|
292
|
+
}
|
|
293
|
+
if (!chunk.startsWith('[')) {
|
|
294
|
+
chunk = '[' + chunk;
|
|
295
|
+
}
|
|
296
|
+
if (!chunk.endsWith(']')) {
|
|
297
|
+
chunk = chunk + ']';
|
|
298
|
+
}
|
|
299
|
+
try {
|
|
300
|
+
return JSON.parse(chunk);
|
|
301
|
+
} catch (error) {
|
|
302
|
+
throw new Error('Cannot parse chunk: ' + chunk, {cause: error});
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
267
306
|
registerClientEvent(clientEvent: AidaRegisterClientEvent): Promise<AidaClientResult> {
|
|
268
307
|
// Disable logging for now.
|
|
269
308
|
// For context, see b/454563259#comment35.
|
|
@@ -272,7 +311,11 @@ export class AidaClient {
|
|
|
272
311
|
clientEvent.disable_user_content_logging = true;
|
|
273
312
|
}
|
|
274
313
|
|
|
314
|
+
if (this.#gcaClient.enabled()) {
|
|
315
|
+
return this.#gcaClient.registerClientEvent(clientEvent);
|
|
316
|
+
}
|
|
275
317
|
const {promise, resolve} = Promise.withResolvers<AidaClientResult>();
|
|
318
|
+
|
|
276
319
|
InspectorFrontendHostInstance.registerAidaClientEvent(
|
|
277
320
|
JSON.stringify({
|
|
278
321
|
client: CLIENT_NAME,
|
|
@@ -297,6 +340,9 @@ export class AidaClient {
|
|
|
297
340
|
request.metadata.disable_user_content_logging = true;
|
|
298
341
|
}
|
|
299
342
|
|
|
343
|
+
if (this.#gcaClient.enabled()) {
|
|
344
|
+
return await this.#gcaClient.completeCode(request);
|
|
345
|
+
}
|
|
300
346
|
const {promise, resolve} = Promise.withResolvers<AidaCodeCompleteResult>();
|
|
301
347
|
InspectorFrontendHostInstance.aidaCodeComplete(JSON.stringify(request), resolve);
|
|
302
348
|
const completeCodeResult = await promise;
|
|
@@ -348,6 +394,11 @@ export class AidaClient {
|
|
|
348
394
|
if (Root.Runtime.hostConfig.devToolsGeminiRebranding?.enabled) {
|
|
349
395
|
request.metadata.disable_user_content_logging = true;
|
|
350
396
|
}
|
|
397
|
+
|
|
398
|
+
if (this.#gcaClient.enabled()) {
|
|
399
|
+
// Inline and remove the else clause after migration
|
|
400
|
+
return await this.#gcaClient.generateCode(request, options);
|
|
401
|
+
}
|
|
351
402
|
const response = await DispatchHttpRequestClient.makeHttpRequest<GenerateCodeResponse>(
|
|
352
403
|
{
|
|
353
404
|
service: SERVICE_NAME,
|
|
@@ -254,6 +254,12 @@ function buildLabels(request: AidaRequest, gcaRequest: GCA.GenerateContentReques
|
|
|
254
254
|
if (options?.expect_code_output !== undefined) {
|
|
255
255
|
labels['expect_code_output'] = String(options.expect_code_output);
|
|
256
256
|
}
|
|
257
|
+
if (request.metadata.disable_user_content_logging !== undefined) {
|
|
258
|
+
labels['disable_user_content_logging'] = String(request.metadata.disable_user_content_logging);
|
|
259
|
+
}
|
|
260
|
+
if (request.metadata.client_version) {
|
|
261
|
+
labels['client_version'] = request.metadata.client_version;
|
|
262
|
+
}
|
|
257
263
|
|
|
258
264
|
if (Object.keys(labels).length > 0) {
|
|
259
265
|
gcaRequest.labels = labels;
|
|
@@ -0,0 +1,112 @@
|
|
|
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 Root from '../root/root.js';
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
type AidaRegisterClientEvent,
|
|
9
|
+
type CompletionRequest,
|
|
10
|
+
type CompletionResponse,
|
|
11
|
+
debugLog,
|
|
12
|
+
type DoConversationRequest,
|
|
13
|
+
type GenerateCodeRequest,
|
|
14
|
+
type GenerateCodeResponse
|
|
15
|
+
} from './AidaClientTypes.js';
|
|
16
|
+
import {
|
|
17
|
+
aidaCompletionRequestToGcaRequest,
|
|
18
|
+
aidaDoConversationRequestToGcaRequest,
|
|
19
|
+
aidaEventToGcaTelemetryRequest,
|
|
20
|
+
aidaGenerateCodeRequestToGcaRequest,
|
|
21
|
+
gcaResponseToAidaCompletionResponse,
|
|
22
|
+
gcaResponseToAidaGenerateCodeResponse
|
|
23
|
+
} from './AidaGcaTranslation.js';
|
|
24
|
+
import * as DispatchHttpRequestClient from './DispatchHttpRequestClient.js';
|
|
25
|
+
import type {GenerateContentRequest, GenerateContentResponse} from './GcaTypes.js';
|
|
26
|
+
import type {AidaClientResult} from './InspectorFrontendHostAPI.js';
|
|
27
|
+
|
|
28
|
+
const SERVICE_NAME = 'gcaService';
|
|
29
|
+
|
|
30
|
+
const ENDPOINTS = {
|
|
31
|
+
CONTENT: '/v1beta:generateContent',
|
|
32
|
+
SEND_TELEMETRY: '/v1beta:sendTelemetry',
|
|
33
|
+
STREAM_CONTENT: '/v1beta:streamGenerateContent',
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export class GcaClient {
|
|
37
|
+
enabled(): boolean|undefined {
|
|
38
|
+
return Root.Runtime.hostConfig.devToolsUseGcaApi?.enabled;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async conversationRequest(request: DoConversationRequest, streamId: number, options?: {signal?: AbortSignal}):
|
|
42
|
+
Promise<void> {
|
|
43
|
+
try {
|
|
44
|
+
const gcaRequest = aidaDoConversationRequestToGcaRequest(request);
|
|
45
|
+
const response = await DispatchHttpRequestClient.makeHttpRequest<GenerateContentResponse>(
|
|
46
|
+
{
|
|
47
|
+
service: SERVICE_NAME,
|
|
48
|
+
path: ENDPOINTS.STREAM_CONTENT,
|
|
49
|
+
method: 'POST',
|
|
50
|
+
body: JSON.stringify(gcaRequest),
|
|
51
|
+
streamId,
|
|
52
|
+
},
|
|
53
|
+
options);
|
|
54
|
+
debugLog('GCA conversation request succeeded:', JSON.stringify(request), JSON.stringify(response));
|
|
55
|
+
} catch (err) {
|
|
56
|
+
debugLog('GCA request failed:', JSON.stringify(request), err);
|
|
57
|
+
throw err;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
registerClientEvent(clientEvent: AidaRegisterClientEvent): Promise<AidaClientResult> {
|
|
62
|
+
const gcaEvent = aidaEventToGcaTelemetryRequest(clientEvent);
|
|
63
|
+
const response = DispatchHttpRequestClient.makeHttpRequest({
|
|
64
|
+
service: SERVICE_NAME,
|
|
65
|
+
path: ENDPOINTS.SEND_TELEMETRY,
|
|
66
|
+
method: 'POST',
|
|
67
|
+
body: JSON.stringify(gcaEvent),
|
|
68
|
+
});
|
|
69
|
+
return response.then(
|
|
70
|
+
result => {
|
|
71
|
+
debugLog('GCA register event succeeded:', JSON.stringify(gcaEvent), JSON.stringify(result));
|
|
72
|
+
return {} as AidaClientResult;
|
|
73
|
+
},
|
|
74
|
+
err => {
|
|
75
|
+
debugLog('GCA register event failed:', JSON.stringify(gcaEvent), err);
|
|
76
|
+
return {error: JSON.stringify(err)} as AidaClientResult;
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async completeCode(request: CompletionRequest): Promise<CompletionResponse|null> {
|
|
81
|
+
const gcaRequest = aidaCompletionRequestToGcaRequest(request);
|
|
82
|
+
const result = await this.#requestContent(gcaRequest);
|
|
83
|
+
const aidaResult = result ? gcaResponseToAidaCompletionResponse(result) : null;
|
|
84
|
+
return aidaResult;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async generateCode(request: GenerateCodeRequest, options?: {signal?: AbortSignal}):
|
|
88
|
+
Promise<GenerateCodeResponse|null> {
|
|
89
|
+
const gcaRequest = aidaGenerateCodeRequestToGcaRequest(request);
|
|
90
|
+
const result = await this.#requestContent(gcaRequest, options);
|
|
91
|
+
return result ? gcaResponseToAidaGenerateCodeResponse(result) : null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async #requestContent(request: GenerateContentRequest, options?: {signal?: AbortSignal}):
|
|
95
|
+
Promise<GenerateContentResponse|null> {
|
|
96
|
+
try {
|
|
97
|
+
const response = await DispatchHttpRequestClient.makeHttpRequest<GenerateContentResponse>(
|
|
98
|
+
{
|
|
99
|
+
service: SERVICE_NAME,
|
|
100
|
+
path: ENDPOINTS.CONTENT,
|
|
101
|
+
method: 'POST',
|
|
102
|
+
body: JSON.stringify(request),
|
|
103
|
+
},
|
|
104
|
+
options);
|
|
105
|
+
debugLog('GCA request succeeded:', JSON.stringify(request), JSON.stringify(response));
|
|
106
|
+
return response;
|
|
107
|
+
} catch (err) {
|
|
108
|
+
debugLog('GCA request failed:', JSON.stringify(request), err);
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -821,7 +821,6 @@ export enum DevtoolsExperiments {
|
|
|
821
821
|
apca = 39,
|
|
822
822
|
'font-editor' = 41,
|
|
823
823
|
'full-accessibility-tree' = 42,
|
|
824
|
-
'experimental-cookie-features' = 45,
|
|
825
824
|
'instrumentation-breakpoints' = 61,
|
|
826
825
|
'use-source-map-scopes' = 76,
|
|
827
826
|
'timeline-debug-mode' = 93,
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import * as AidaClient from './AidaClient.js';
|
|
6
6
|
import * as AidaGcaTranslation from './AidaGcaTranslation.js';
|
|
7
7
|
import * as DispatchHttpRequestClient from './DispatchHttpRequestClient.js';
|
|
8
|
+
import * as GcaClient from './GcaClient.js';
|
|
8
9
|
import * as GcaTypes from './GcaTypes.js';
|
|
9
10
|
import * as GdpClient from './GdpClient.js';
|
|
10
11
|
import * as InspectorFrontendHost from './InspectorFrontendHost.js';
|
|
@@ -17,6 +18,7 @@ export {
|
|
|
17
18
|
AidaClient,
|
|
18
19
|
AidaGcaTranslation,
|
|
19
20
|
DispatchHttpRequestClient,
|
|
21
|
+
GcaClient,
|
|
20
22
|
GcaTypes,
|
|
21
23
|
GdpClient,
|
|
22
24
|
InspectorFrontendHost,
|
|
@@ -14,7 +14,6 @@ export enum ExperimentName {
|
|
|
14
14
|
APCA = 'apca',
|
|
15
15
|
FONT_EDITOR = 'font-editor',
|
|
16
16
|
FULL_ACCESSIBILITY_TREE = 'full-accessibility-tree',
|
|
17
|
-
EXPERIMENTAL_COOKIE_FEATURES = 'experimental-cookie-features',
|
|
18
17
|
INSTRUMENTATION_BREAKPOINTS = 'instrumentation-breakpoints',
|
|
19
18
|
USE_SOURCE_MAP_SCOPES = 'use-source-map-scopes',
|
|
20
19
|
TIMELINE_DEBUG_MODE = 'timeline-debug-mode',
|
|
@@ -602,6 +602,10 @@ interface ConsoleInsightsTeasers {
|
|
|
602
602
|
allowWithoutGpu: boolean;
|
|
603
603
|
}
|
|
604
604
|
|
|
605
|
+
interface UseGcaApi {
|
|
606
|
+
enabled: boolean;
|
|
607
|
+
}
|
|
608
|
+
|
|
605
609
|
interface DevToolsProtocolMonitor {
|
|
606
610
|
enabled: boolean;
|
|
607
611
|
}
|
|
@@ -662,6 +666,7 @@ export type HostConfig = Platform.TypeScriptUtilities.RecursivePartial<{
|
|
|
662
666
|
devToolsGeminiRebranding: HostConfigGeminiRebranding,
|
|
663
667
|
devToolsProtocolMonitor: DevToolsProtocolMonitor,
|
|
664
668
|
devToolsWebMCPSupport: DevToolsWebMCPSupport,
|
|
669
|
+
devToolsUseGcaApi: UseGcaApi,
|
|
665
670
|
}>;
|
|
666
671
|
|
|
667
672
|
/**
|
|
@@ -2,7 +2,7 @@
|
|
|
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
|
+
import type * as Common from '../../core/common/common.js';
|
|
6
6
|
import type * as ProtocolProxyApi from '../../generated/protocol-proxy-api.js';
|
|
7
7
|
import type * as Protocol from '../../generated/protocol.js';
|
|
8
8
|
import * as Host from '../host/host.js';
|
|
@@ -19,8 +19,9 @@ export class AutofillModel extends SDKModel<EventTypes> implements ProtocolProxy
|
|
|
19
19
|
super(target);
|
|
20
20
|
|
|
21
21
|
this.agent = target.autofillAgent();
|
|
22
|
+
const settings = this.target().targetManager().settings;
|
|
22
23
|
this.#showTestAddressesInAutofillMenu =
|
|
23
|
-
|
|
24
|
+
settings.createSetting('show-test-addresses-in-autofill-menu-on-event', false);
|
|
24
25
|
this.#showTestAddressesInAutofillMenu.addChangeListener(this.#setTestAddresses, this);
|
|
25
26
|
target.registerAutofillDispatcher(this);
|
|
26
27
|
this.enable();
|
|
@@ -79,10 +79,9 @@ export class CSSModel extends SDKModel<EventTypes> {
|
|
|
79
79
|
void this.enable();
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
this
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
.moduleSetting<boolean>('css-source-maps-enabled')
|
|
82
|
+
const settings = this.target().targetManager().settings;
|
|
83
|
+
this.#sourceMapManager.setEnabled(settings.moduleSetting<boolean>('css-source-maps-enabled').get());
|
|
84
|
+
settings.moduleSetting<boolean>('css-source-maps-enabled')
|
|
86
85
|
.addChangeListener(event => this.#sourceMapManager.setEnabled(event.data));
|
|
87
86
|
}
|
|
88
87
|
|
|
@@ -225,7 +225,7 @@ export class CSSProperty extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
|
|
|
225
225
|
const range = this.range.relativeTo(this.ownerStyle.range.startLine, this.ownerStyle.range.startColumn);
|
|
226
226
|
const indentation = this.ownerStyle.cssText ?
|
|
227
227
|
this.detectIndentation(this.ownerStyle.cssText) :
|
|
228
|
-
|
|
228
|
+
this.ownerStyle.cssModel().target().targetManager().settings.moduleSetting('text-editor-indent').get();
|
|
229
229
|
const endIndentation = this.ownerStyle.cssText ? indentation.substring(0, this.ownerStyle.range.endColumn) : '';
|
|
230
230
|
const text = new TextUtils.Text.Text(this.ownerStyle.cssText || '');
|
|
231
231
|
const newStyleText = text.replaceRange(range, Platform.StringUtilities.sprintf(';%s;', propertyText));
|
|
@@ -153,7 +153,7 @@ export class ConsoleModel extends SDKModel<EventTypes> {
|
|
|
153
153
|
replMode: true,
|
|
154
154
|
allowUnsafeEvalBlockedByCSP: false,
|
|
155
155
|
},
|
|
156
|
-
|
|
156
|
+
this.target().targetManager().settings.moduleSetting('console-user-activation-eval').get(),
|
|
157
157
|
/* awaitPromise */ false);
|
|
158
158
|
Host.userMetrics.actionTaken(Host.UserMetrics.Action.ConsoleEvaluated);
|
|
159
159
|
if ('error' in result) {
|
|
@@ -284,7 +284,8 @@ export class ConsoleModel extends SDKModel<EventTypes> {
|
|
|
284
284
|
}
|
|
285
285
|
|
|
286
286
|
private clearIfNecessary(): void {
|
|
287
|
-
|
|
287
|
+
const settings = this.target().targetManager().settings;
|
|
288
|
+
if (!settings.moduleSetting('preserve-console-log').get()) {
|
|
288
289
|
this.clear();
|
|
289
290
|
}
|
|
290
291
|
++this.#pageLoadSequenceNumber;
|
|
@@ -292,7 +293,8 @@ export class ConsoleModel extends SDKModel<EventTypes> {
|
|
|
292
293
|
|
|
293
294
|
private primaryPageChanged(
|
|
294
295
|
event: Common.EventTarget.EventTargetEvent<{frame: ResourceTreeFrame, type: PrimaryPageChangeType}>): void {
|
|
295
|
-
|
|
296
|
+
const settings = this.target().targetManager().settings;
|
|
297
|
+
if (settings.moduleSetting('preserve-console-log').get()) {
|
|
296
298
|
const {frame} = event.data;
|
|
297
299
|
if (frame.backForwardCacheDetails.restoredFromCache) {
|
|
298
300
|
Common.Console.Console.instance().log(i18nString(UIStrings.bfcacheNavigation, {PH1: frame.url}));
|
|
@@ -353,25 +355,25 @@ export class ConsoleModel extends SDKModel<EventTypes> {
|
|
|
353
355
|
}
|
|
354
356
|
|
|
355
357
|
// messages[] are not ordered by timestamp.
|
|
356
|
-
static allMessagesUnordered(): ConsoleMessage[] {
|
|
358
|
+
static allMessagesUnordered(targetManager: TargetManager = TargetManager.instance()): ConsoleMessage[] {
|
|
357
359
|
const messages = [];
|
|
358
|
-
for (const target of
|
|
360
|
+
for (const target of targetManager.targets()) {
|
|
359
361
|
const targetMessages = target.model(ConsoleModel)?.messages() || [];
|
|
360
362
|
messages.push(...targetMessages);
|
|
361
363
|
}
|
|
362
364
|
return messages;
|
|
363
365
|
}
|
|
364
366
|
|
|
365
|
-
static requestClearMessages(): void {
|
|
366
|
-
for (const logModel of
|
|
367
|
+
static requestClearMessages(targetManager: TargetManager = TargetManager.instance()): void {
|
|
368
|
+
for (const logModel of targetManager.models(LogModel)) {
|
|
367
369
|
logModel.requestClear();
|
|
368
370
|
}
|
|
369
|
-
for (const runtimeModel of
|
|
371
|
+
for (const runtimeModel of targetManager.models(RuntimeModel)) {
|
|
370
372
|
runtimeModel.discardConsoleEntries();
|
|
371
373
|
// Runtime.discardConsoleEntries implies Runtime.releaseObjectGroup('console').
|
|
372
374
|
runtimeModel.releaseObjectGroup('live-expression');
|
|
373
375
|
}
|
|
374
|
-
for (const target of
|
|
376
|
+
for (const target of targetManager.targets()) {
|
|
375
377
|
target.model(ConsoleModel)?.clear();
|
|
376
378
|
}
|
|
377
379
|
}
|
|
@@ -390,9 +392,9 @@ export class ConsoleModel extends SDKModel<EventTypes> {
|
|
|
390
392
|
return this.#errors;
|
|
391
393
|
}
|
|
392
394
|
|
|
393
|
-
static allErrors(): number {
|
|
395
|
+
static allErrors(targetManager: TargetManager = TargetManager.instance()): number {
|
|
394
396
|
let errors = 0;
|
|
395
|
-
for (const target of
|
|
397
|
+
for (const target of targetManager.targets()) {
|
|
396
398
|
errors += target.model(ConsoleModel)?.errors() || 0;
|
|
397
399
|
}
|
|
398
400
|
return errors;
|
|
@@ -402,9 +404,9 @@ export class ConsoleModel extends SDKModel<EventTypes> {
|
|
|
402
404
|
return this.#warnings;
|
|
403
405
|
}
|
|
404
406
|
|
|
405
|
-
static allWarnings(): number {
|
|
407
|
+
static allWarnings(targetManager: TargetManager = TargetManager.instance()): number {
|
|
406
408
|
let warnings = 0;
|
|
407
|
-
for (const target of
|
|
409
|
+
for (const target of targetManager.targets()) {
|
|
408
410
|
warnings += target.model(ConsoleModel)?.warnings() || 0;
|
|
409
411
|
}
|
|
410
412
|
return warnings;
|
|
@@ -99,8 +99,9 @@ export class CookieModel extends SDKModel<EventTypes> {
|
|
|
99
99
|
if (cookie.expires()) {
|
|
100
100
|
expires = Math.floor(Date.parse(`${cookie.expires()}`) / 1000);
|
|
101
101
|
}
|
|
102
|
-
const
|
|
103
|
-
Root.Runtime.
|
|
102
|
+
const schemeBindingEnabled =
|
|
103
|
+
Boolean(Root.Runtime.hostConfig.devToolsEnableOriginBoundCookies?.schemeBindingEnabled);
|
|
104
|
+
const portBindingEnabled = Boolean(Root.Runtime.hostConfig.devToolsEnableOriginBoundCookies?.portBindingEnabled);
|
|
104
105
|
const preserveUnset = (scheme: Protocol.Network.CookieSourceScheme): Protocol.Network.CookieSourceScheme.Unset|
|
|
105
106
|
undefined => scheme === Protocol.Network.CookieSourceScheme.Unset ? scheme : undefined;
|
|
106
107
|
const protocolCookie = {
|
|
@@ -115,8 +116,8 @@ export class CookieModel extends SDKModel<EventTypes> {
|
|
|
115
116
|
expires,
|
|
116
117
|
priority: cookie.priority(),
|
|
117
118
|
partitionKey: cookie.partitionKey(),
|
|
118
|
-
sourceScheme:
|
|
119
|
-
sourcePort:
|
|
119
|
+
sourceScheme: schemeBindingEnabled ? cookie.sourceScheme() : preserveUnset(cookie.sourceScheme()),
|
|
120
|
+
sourcePort: portBindingEnabled ? cookie.sourcePort() : undefined,
|
|
120
121
|
};
|
|
121
122
|
const response = await this.target().networkAgent().invoke_setCookie(protocolCookie);
|
|
122
123
|
const error = response.getError();
|