chrome-devtools-frontend 1.0.1603822 → 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.
Files changed (89) hide show
  1. package/AUTHORS +1 -0
  2. package/front_end/Tests.js +23 -7
  3. package/front_end/core/host/AidaClient.ts +153 -525
  4. package/front_end/core/host/AidaClientTypes.ts +470 -0
  5. package/front_end/core/host/AidaGcaTranslation.ts +231 -122
  6. package/front_end/core/host/GcaClient.ts +112 -0
  7. package/front_end/core/host/GcaTypes.ts +107 -155
  8. package/front_end/core/host/UserMetrics.ts +0 -1
  9. package/front_end/core/host/host.ts +2 -0
  10. package/front_end/core/protocol_client/DevToolsCDPConnection.ts +1 -1
  11. package/front_end/core/root/ExperimentNames.ts +0 -1
  12. package/front_end/core/root/Runtime.ts +5 -0
  13. package/front_end/core/sdk/AutofillModel.ts +3 -2
  14. package/front_end/core/sdk/CSSModel.ts +3 -4
  15. package/front_end/core/sdk/CSSProperty.ts +1 -1
  16. package/front_end/core/sdk/ConsoleModel.ts +15 -13
  17. package/front_end/core/sdk/CookieModel.ts +5 -4
  18. package/front_end/core/sdk/DOMDebuggerModel.ts +20 -14
  19. package/front_end/core/sdk/DOMModel.ts +24 -22
  20. package/front_end/core/sdk/DebuggerModel.ts +21 -36
  21. package/front_end/core/sdk/EmulationModel.ts +21 -23
  22. package/front_end/core/sdk/EventBreakpointsModel.ts +16 -6
  23. package/front_end/core/sdk/HeapProfilerModel.ts +4 -7
  24. package/front_end/core/sdk/IsolateManager.ts +12 -7
  25. package/front_end/core/sdk/NetworkManager.ts +35 -28
  26. package/front_end/core/sdk/OverlayModel.ts +10 -10
  27. package/front_end/core/sdk/PreloadingModel.ts +3 -4
  28. package/front_end/core/sdk/ServiceWorkerManager.ts +2 -3
  29. package/front_end/core/sdk/SourceMapScopesInfo.ts +93 -63
  30. package/front_end/entrypoints/formatter_worker/FormatterWorker.ts +1 -3
  31. package/front_end/entrypoints/heap_snapshot_worker/AllocationProfile.ts +22 -48
  32. package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +1 -1
  33. package/front_end/entrypoints/main/MainImpl.ts +0 -4
  34. package/front_end/generated/InspectorBackendCommands.ts +4 -0
  35. package/front_end/generated/SupportedCSSProperties.js +68 -2
  36. package/front_end/generated/protocol-mapping.d.ts +7 -0
  37. package/front_end/generated/protocol-proxy-api.d.ts +14 -0
  38. package/front_end/generated/protocol.ts +22 -0
  39. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +31 -17
  40. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +1 -1
  41. package/front_end/models/bindings/TempFile.ts +1 -4
  42. package/front_end/models/emulation/DeviceModeModel.ts +21 -26
  43. package/front_end/models/extensions/ExtensionAPI.ts +1 -1
  44. package/front_end/models/heap_snapshot_model/HeapSnapshotModel.ts +34 -47
  45. package/front_end/models/javascript_metadata/NativeFunctions.js +6 -6
  46. package/front_end/models/trace/insights/LCPDiscovery.ts +14 -6
  47. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +85 -31
  48. package/front_end/panels/ai_assistance/components/ChatMessage.ts +50 -40
  49. package/front_end/panels/ai_assistance/components/ChatView.ts +3 -2
  50. package/front_end/panels/ai_assistance/components/WalkthroughView.ts +35 -7
  51. package/front_end/panels/ai_assistance/components/chatMessage.css +5 -1
  52. package/front_end/panels/application/ApplicationPanelSidebar.ts +6 -0
  53. package/front_end/panels/application/IndexedDBViews.ts +0 -9
  54. package/front_end/panels/application/WebMCPTreeElement.ts +35 -0
  55. package/front_end/panels/application/WebMCPView.ts +118 -0
  56. package/front_end/panels/application/application.ts +4 -0
  57. package/front_end/panels/application/webMCPView.css +65 -0
  58. package/front_end/panels/common/aiCodeCompletionSummaryToolbar.css +1 -1
  59. package/front_end/panels/console/consoleView.css +4 -0
  60. package/front_end/panels/elements/ElementsTreeElement.ts +91 -13
  61. package/front_end/panels/elements/StylesAiCodeCompletionProvider.ts +23 -2
  62. package/front_end/panels/elements/StylesSidebarPane.ts +85 -20
  63. package/front_end/panels/elements/elementsPanel.css +14 -0
  64. package/front_end/panels/elements/elementsTreeOutline.css +18 -0
  65. package/front_end/panels/network/NetworkLogViewColumns.ts +3 -3
  66. package/front_end/panels/profiler/HeapSnapshotDataGrids.ts +15 -19
  67. package/front_end/panels/profiler/HeapSnapshotGridNodes.ts +4 -2
  68. package/front_end/panels/profiler/HeapSnapshotProxy.ts +12 -16
  69. package/front_end/panels/profiler/HeapSnapshotView.ts +3 -10
  70. package/front_end/panels/profiler/ProfilesPanel.ts +5 -7
  71. package/front_end/panels/recorder/components/recordingView.css +0 -6
  72. package/front_end/panels/sensors/SensorsView.ts +28 -61
  73. package/front_end/panels/timeline/EventsTimelineTreeView.ts +2 -2
  74. package/front_end/panels/timeline/ThirdPartyTreeView.ts +35 -36
  75. package/front_end/panels/timeline/TimelineDetailsView.ts +47 -41
  76. package/front_end/panels/timeline/TimelinePanel.ts +1 -3
  77. package/front_end/panels/timeline/TimelineTreeView.ts +13 -13
  78. package/front_end/panels/timeline/components/LiveMetricsView.ts +852 -824
  79. package/front_end/panels/timeline/components/liveMetricsView.css +4 -0
  80. package/front_end/panels/timeline/thirdPartyTreeView.css +2 -2
  81. package/front_end/third_party/chromium/README.chromium +1 -1
  82. package/front_end/ui/components/buttons/button.css +2 -2
  83. package/front_end/ui/components/text_editor/AiCodeCompletionProvider.ts +0 -11
  84. package/front_end/ui/legacy/InspectorDrawerView.ts +206 -0
  85. package/front_end/ui/legacy/InspectorView.ts +41 -91
  86. package/front_end/ui/legacy/ViewManager.ts +14 -5
  87. package/front_end/ui/legacy/inspectorDrawerTabbedPane.css +5 -0
  88. package/front_end/ui/visual_logging/KnownContextValues.ts +2 -1
  89. package/package.json +1 -1
@@ -5,483 +5,75 @@
5
5
  import * as Common from '../common/common.js';
6
6
  import * as Root from '../root/root.js';
7
7
 
8
+ import {
9
+ AidaAccessPreconditions,
10
+ type AidaChunkResponse,
11
+ type AidaFunctionCallResponse,
12
+ AidaInferenceLanguage,
13
+ type AidaRegisterClientEvent,
14
+ ClientFeature,
15
+ type CompletionRequest,
16
+ type CompletionResponse,
17
+ debugLog,
18
+ type DoConversationRequest,
19
+ type DoConversationResponse,
20
+ FunctionalityType,
21
+ type GenerateCodeRequest,
22
+ type GenerateCodeResponse,
23
+ type GenerationSample,
24
+ RecitationAction,
25
+ type ResponseMetadata,
26
+ Role,
27
+ UserTier,
28
+ } from './AidaClientTypes.js';
29
+ import {gcaChunkResponseToAidaChunkResponse} from './AidaGcaTranslation.js';
8
30
  import * as DispatchHttpRequestClient from './DispatchHttpRequestClient.js';
31
+ import * as GcaClient from './GcaClient.js';
32
+ import type {GenerateContentResponse} from './GcaTypes.js';
9
33
  import {InspectorFrontendHostInstance} from './InspectorFrontendHost.js';
10
34
  import type {AidaClientResult, AidaCodeCompleteResult, SyncInformation} from './InspectorFrontendHostAPI.js';
11
35
  import {bindOutputStream} from './ResourceLoader.js';
12
36
 
13
- export enum Role {
14
- /** Provide this role when giving a function call response */
15
- ROLE_UNSPECIFIED = 0,
16
- /** Tags the content came from the user */
17
- USER = 1,
18
- /** Tags the content came from the LLM */
19
- MODEL = 2,
20
- }
21
-
22
- export const enum Rating {
23
- // Resets the vote to null in the logs
24
- SENTIMENT_UNSPECIFIED = 'SENTIMENT_UNSPECIFIED',
25
- POSITIVE = 'POSITIVE',
26
- NEGATIVE = 'NEGATIVE',
27
- }
28
-
29
- /**
30
- * A `Content` represents a single turn message.
31
- */
32
- export interface Content {
33
- parts: Part[];
34
- /** The producer of the content. */
35
- role: Role;
36
- }
37
-
38
- export type Part = {
39
- text: string,
40
- }|{
41
- functionCall: {
42
- name: string,
43
- args: Record<string, unknown>,
44
- },
45
- }|{
46
- functionResponse: {
47
- name: string,
48
- response: Record<string, unknown>,
49
- },
50
- }|{
51
- /** Inline media bytes. */
52
- inlineData: MediaBlob,
53
- };
54
-
55
- export const enum ParametersTypes {
56
- STRING = 1,
57
- NUMBER = 2,
58
- INTEGER = 3,
59
- BOOLEAN = 4,
60
- ARRAY = 5,
61
- OBJECT = 6,
62
- }
63
-
64
- interface BaseFunctionParam {
65
- description: string;
66
- nullable?: boolean;
67
- }
68
-
69
- export interface FunctionPrimitiveParams extends BaseFunctionParam {
70
- type: ParametersTypes.BOOLEAN|ParametersTypes.INTEGER|ParametersTypes.STRING;
71
- }
72
-
73
- export interface FunctionArrayParam extends BaseFunctionParam {
74
- type: ParametersTypes.ARRAY;
75
- items: FunctionPrimitiveParams;
76
- }
77
-
78
- export interface FunctionObjectParam<T extends string|number|symbol = string> extends BaseFunctionParam {
79
- type: ParametersTypes.OBJECT;
80
- // TODO: this can be also be ObjectParams
81
- properties: Record<T, FunctionPrimitiveParams|FunctionArrayParam>;
82
- required: T[];
83
- }
84
-
85
- /**
86
- * More about function declaration can be read at
87
- * https://ai.google.dev/gemini-api/docs/function-calling
88
- */
89
- export interface FunctionDeclaration<T extends string|number|symbol = string> {
90
- name: string;
91
- /**
92
- * A description for the LLM to understand what the specific function will do once called.
93
- */
94
- description: string;
95
- parameters: FunctionObjectParam<T>;
96
- }
97
-
98
- /** Raw media bytes. **/
99
- export interface MediaBlob {
100
- // The IANA standard MIME type of the source data.
101
- // Currently supported types are: image/png, image/jpeg.
102
- // Format: base64-encoded
103
- // For reference: google3/google/x/pitchfork/aida/v1/content.proto
104
- mimeType: string;
105
- data: string;
106
- }
107
-
108
- export enum FunctionalityType {
109
- // Unspecified functionality type.
110
- FUNCTIONALITY_TYPE_UNSPECIFIED = 0,
111
- // The generic AI chatbot functionality.
112
- CHAT = 1,
113
- // The explain error functionality.
114
- EXPLAIN_ERROR = 2,
115
- AGENTIC_CHAT = 5,
116
- }
117
-
118
- /** See: cs/aida.proto (google3). **/
119
- export enum ClientFeature {
120
- // Unspecified client feature.
121
- CLIENT_FEATURE_UNSPECIFIED = 0,
122
- // Chrome console insights feature.
123
- CHROME_CONSOLE_INSIGHTS = 1,
124
- // Chrome AI Assistance Styling Agent.
125
- CHROME_STYLING_AGENT = 2,
126
- // Chrome AI Assistance Network Agent.
127
- CHROME_NETWORK_AGENT = 7,
128
- // Chrome AI Annotations Performance Agent
129
- CHROME_PERFORMANCE_ANNOTATIONS_AGENT = 20,
130
- // Chrome AI Assistance File Agent.
131
- CHROME_FILE_AGENT = 9,
132
- // Chrome AI Patch Agent.
133
- CHROME_PATCH_AGENT = 12,
134
- // Chrome AI Assistance Performance Agent.
135
- CHROME_PERFORMANCE_FULL_AGENT = 24,
136
- // Chrome Context Selection Agent.
137
- CHROME_CONTEXT_SELECTION_AGENT = 25,
138
- // Chrome Accessibility Agent
139
- CHROME_ACCESSIBILITY_AGENT = 26,
140
- // Chrome AI Assistance Conversation Summary Agent.
141
- CHROME_CONVERSATION_SUMMARY_AGENT = 27,
142
-
143
- // Removed features (for reference).
144
- // Chrome AI Assistance Performance Insights Agent.
145
- // CHROME_PERFORMANCE_INSIGHTS_AGENT = 13,
146
- // Chrome AI Assistance Performance Agent (call trees).
147
- // CHROME_PERFORMANCE_AGENT = 8,
148
- }
149
-
150
- export enum UserTier {
151
- // Unspecified user tier.
152
- USER_TIER_UNSPECIFIED = 0,
153
- // Users who are internal testers.
154
- TESTERS = 1,
155
- // Users who are early adopters.
156
- BETA = 2,
157
- // Users in the general public.
158
- PUBLIC = 3,
159
- }
160
-
161
- /** Googlers: see the Aida `retrieval` proto; this type is based on that. **/
162
- export interface RequestFactMetadata {
163
- /**
164
- * A description of where the fact comes from.
165
- */
166
- source: string;
167
- /**
168
- * Optional: a score to give this fact. Used because
169
- * if there are more facts than space in the context window,
170
- * higher scoring facts will be prioritized.
171
- */
172
- score?: number;
173
- }
174
- export interface RequestFact {
175
- /**
176
- * Content of the fact.
177
- */
178
- text: string;
179
- metadata: RequestFactMetadata;
180
- }
181
-
182
- export type RpcGlobalId = string|number;
183
-
184
- /* eslint-disable @typescript-eslint/naming-convention */
185
- export interface RequestMetadata {
186
- string_session_id?: string;
187
- user_tier?: UserTier;
188
- disable_user_content_logging: boolean;
189
- client_version: string;
190
- }
191
- /* eslint-enable @typescript-eslint/naming-convention */
192
-
193
- /* eslint-disable @typescript-eslint/naming-convention */
194
- export interface ConversationOptions {
195
- temperature?: number;
196
- model_id?: string;
197
- }
198
- /* eslint-enable @typescript-eslint/naming-convention */
199
-
200
- /* eslint-disable @typescript-eslint/naming-convention */
201
- export interface DoConversationRequest {
202
- client: string;
203
- current_message: Content;
204
- preamble?: string;
205
- historical_contexts?: Content[];
206
- function_declarations?: FunctionDeclaration[];
207
- facts?: RequestFact[];
208
- options?: ConversationOptions;
209
- metadata: RequestMetadata;
210
- functionality_type?: FunctionalityType;
211
- client_feature?: ClientFeature;
212
- }
213
- /* eslint-enable @typescript-eslint/naming-convention */
214
-
215
- /* eslint-disable @typescript-eslint/naming-convention */
216
- export interface CompleteCodeOptions {
217
- temperature?: number;
218
- model_id?: string;
219
- inference_language?: AidaInferenceLanguage;
220
- stop_sequences?: string[];
221
- }
222
- /* eslint-enable @typescript-eslint/naming-convention */
223
-
224
- /* eslint-disable @typescript-eslint/naming-convention */
225
- export interface GenerateCodeOptions {
226
- temperature?: number;
227
- model_id?: string;
228
- inference_language?: AidaInferenceLanguage;
229
- expect_code_output?: boolean;
230
- }
231
- /* eslint-enable @typescript-eslint/naming-convention */
232
-
233
- /* eslint-disable @typescript-eslint/naming-convention */
234
- export interface ContextFile {
235
- path: string;
236
- full_content: string;
237
- selected_content?: string;
238
- programming_language: AidaInferenceLanguage;
239
- }
240
- /* eslint-enable @typescript-eslint/naming-convention */
241
-
242
- export enum EditType {
243
- // Unknown edit type
244
- EDIT_TYPE_UNSPECIFIED = 0,
245
- // User typed code/text into file
246
- ADD = 1,
247
- // User deleted code/text from file
248
- DELETE = 2,
249
- // User pasted into file (this includes smart paste)
250
- PASTE = 3,
251
- // User performs an undo action
252
- UNDO = 4,
253
- // User performs a redo action
254
- REDO = 5,
255
- // User accepted a completion from AIDA
256
- ACCEPT_COMPLETION = 6,
257
- }
258
-
259
- export enum Reason {
260
- // Unknown reason.
261
- UNKNOWN = 0,
262
-
263
- // The file is currently open.
264
- CURRENTLY_OPEN = 1,
265
-
266
- // The file is opened recently.
267
- RECENTLY_OPENED = 2,
268
-
269
- // The file is edited recently.
270
- RECENTLY_EDITED = 3,
271
-
272
- // The file is located within the same directory.
273
- COLOCATED = 4,
274
-
275
- // Included based on relation to code around the cursor (e.g: could be
276
- // provided by local IDE analysis)
277
- RELATED_FILE = 5,
278
- }
279
-
280
- /* eslint-disable @typescript-eslint/naming-convention */
281
- export interface AdditionalFile {
282
- path: string;
283
- content: string;
284
- included_reason: Reason;
285
- }
286
-
287
- export interface CompletionRequest {
288
- client: string;
289
- prefix: string;
290
- suffix?: string;
291
- options?: CompleteCodeOptions;
292
- metadata: RequestMetadata;
293
- last_user_action?: EditType;
294
- additional_files?: AdditionalFile[];
295
- }
296
- /* eslint-enable @typescript-eslint/naming-convention */
297
-
298
- export enum UseCase {
299
- // Unspecified usecase.
300
- USE_CASE_UNSPECIFIED = 0,
301
-
302
- // Code generation use case is expected to generate code from scratch
303
- CODE_GENERATION = 1,
304
-
305
- // Code transformation or code editing use case.
306
- CODE_TRANSFORMATION = 2,
307
- }
308
-
309
- /* eslint-disable @typescript-eslint/naming-convention */
310
- export interface GenerateCodeRequest {
311
- client: string;
312
- preamble: string;
313
- current_message: Content;
314
- options?: GenerateCodeOptions;
315
- context_files?: ContextFile[];
316
- use_case: UseCase;
317
- metadata: RequestMetadata;
318
- client_feature?: ClientFeature;
319
- }
320
- /* eslint-enable @typescript-eslint/naming-convention */
321
-
322
- /* eslint-disable @typescript-eslint/naming-convention */
323
- export interface DoConversationClientEvent {
324
- user_feedback: {
325
- sentiment?: Rating,
326
- user_input?: {
327
- comment?: string,
328
- },
329
- };
330
- }
331
-
332
- export interface UserImpression {
333
- sample: {
334
- sample_id?: number,
335
- };
336
- latency: {
337
- duration: {
338
- seconds: number,
339
- nanos: number,
340
- },
341
- };
342
- }
343
-
344
- export interface UserAcceptance {
345
- sample: {
346
- sample_id?: number,
347
- };
348
- }
349
-
350
- export interface AidaRegisterClientEvent {
351
- corresponding_aida_rpc_global_id: RpcGlobalId;
352
- disable_user_content_logging: boolean;
353
- do_conversation_client_event?: DoConversationClientEvent;
354
- complete_code_client_event?: {user_acceptance: UserAcceptance}|{user_impression: UserImpression};
355
- generate_code_client_event?: {user_acceptance: UserAcceptance}|{user_impression: UserImpression};
356
- }
357
- /* eslint-enable @typescript-eslint/naming-convention */
358
-
359
- export enum RecitationAction {
360
- ACTION_UNSPECIFIED = 'ACTION_UNSPECIFIED',
361
- CITE = 'CITE',
362
- BLOCK = 'BLOCK',
363
- NO_ACTION = 'NO_ACTION',
364
- EXEMPT_FOUND_IN_PROMPT = 'EXEMPT_FOUND_IN_PROMPT',
365
- }
366
-
367
- export enum CitationSourceType {
368
- CITATION_SOURCE_TYPE_UNSPECIFIED = 'CITATION_SOURCE_TYPE_UNSPECIFIED',
369
- TRAINING_DATA = 'TRAINING_DATA',
370
- WORLD_FACTS = 'WORLD_FACTS',
371
- LOCAL_FACTS = 'LOCAL_FACTS',
372
- INDIRECT = 'INDIRECT',
373
- }
374
-
375
- export interface Citation {
376
- startIndex?: number;
377
- endIndex?: number;
378
- uri?: string;
379
- sourceType?: CitationSourceType;
380
- repository?: string;
381
- }
382
-
383
- export interface AttributionMetadata {
384
- attributionAction: RecitationAction;
385
- citations: Citation[];
386
- }
387
-
388
- export interface AidaFunctionCallResponse {
389
- name: string;
390
- args: Record<string, unknown>;
391
- }
392
-
393
- export interface FactualityFact {
394
- sourceUri?: string;
395
- }
396
-
397
- export interface FactualityMetadata {
398
- facts: FactualityFact[];
399
- }
400
-
401
- export interface ResponseMetadata {
402
- rpcGlobalId?: RpcGlobalId;
403
- attributionMetadata?: AttributionMetadata;
404
- factualityMetadata?: FactualityMetadata;
405
- }
406
-
407
- export interface DoConversationResponse {
408
- explanation: string;
409
- metadata: ResponseMetadata;
410
- functionCalls?: [AidaFunctionCallResponse, ...AidaFunctionCallResponse[]];
411
- completed: boolean;
412
- }
413
-
414
- export interface CompletionResponse {
415
- generatedSamples: GenerationSample[];
416
- metadata: ResponseMetadata;
417
- }
418
-
419
- export interface GenerateCodeResponse {
420
- samples: GenerationSample[];
421
- metadata: ResponseMetadata;
422
- }
423
-
424
- export interface GenerationSample {
425
- generationString: string;
426
- score: number;
427
- sampleId?: number;
428
- attributionMetadata?: AttributionMetadata;
429
- }
430
-
431
- export const enum AidaAccessPreconditions {
432
- AVAILABLE = 'available',
433
- NO_ACCOUNT_EMAIL = 'no-account-email',
434
- NO_INTERNET = 'no-internet',
435
- // This is the state (mostly enterprise) users are in, when they are automatically logged out from
436
- // Chrome after a certain time period. For making AIDA requests, they need to log in again.
437
- SYNC_IS_PAUSED = 'sync-is-paused',
438
- }
439
-
440
- export const enum AidaInferenceLanguage {
441
- CPP = 'CPP',
442
- PYTHON = 'PYTHON',
443
- KOTLIN = 'KOTLIN',
444
- JAVA = 'JAVA',
445
- JAVASCRIPT = 'JAVASCRIPT',
446
- GO = 'GO',
447
- TYPESCRIPT = 'TYPESCRIPT',
448
- HTML = 'HTML',
449
- BASH = 'BASH',
450
- CSS = 'CSS',
451
- DART = 'DART',
452
- JSON = 'JSON',
453
- MARKDOWN = 'MARKDOWN',
454
- VUE = 'VUE',
455
- XML = 'XML',
456
- }
457
-
458
- const AidaLanguageToMarkdown: Record<AidaInferenceLanguage, string> = {
459
- CPP: 'cpp',
460
- PYTHON: 'py',
461
- KOTLIN: 'kt',
462
- JAVA: 'java',
463
- JAVASCRIPT: 'js',
464
- GO: 'go',
465
- TYPESCRIPT: 'ts',
466
- HTML: 'html',
467
- BASH: 'sh',
468
- CSS: 'css',
469
- DART: 'dart',
470
- JSON: 'json',
471
- MARKDOWN: 'md',
472
- VUE: 'vue',
473
- XML: 'xml',
474
- };
37
+ export * from './AidaClientTypes.js';
475
38
 
476
39
  export const CLIENT_NAME = 'CHROME_DEVTOOLS';
477
40
  export const SERVICE_NAME = 'aidaService';
478
41
 
479
42
  const CODE_CHUNK_SEPARATOR = (lang = ''): string => ('\n`````' + lang + '\n');
480
43
 
44
+ const AidaLanguageToMarkdown: Record<AidaInferenceLanguage, string> = {
45
+ [AidaInferenceLanguage.CPP]: 'cpp',
46
+ [AidaInferenceLanguage.PYTHON]: 'py',
47
+ [AidaInferenceLanguage.KOTLIN]: 'kt',
48
+ [AidaInferenceLanguage.JAVA]: 'java',
49
+ [AidaInferenceLanguage.JAVASCRIPT]: 'js',
50
+ [AidaInferenceLanguage.GO]: 'go',
51
+ [AidaInferenceLanguage.TYPESCRIPT]: 'ts',
52
+ [AidaInferenceLanguage.HTML]: 'html',
53
+ [AidaInferenceLanguage.BASH]: 'sh',
54
+ [AidaInferenceLanguage.CSS]: 'css',
55
+ [AidaInferenceLanguage.DART]: 'dart',
56
+ [AidaInferenceLanguage.JSON]: 'json',
57
+ [AidaInferenceLanguage.MARKDOWN]: 'md',
58
+ [AidaInferenceLanguage.VUE]: 'vue',
59
+ [AidaInferenceLanguage.XML]: 'xml',
60
+ [AidaInferenceLanguage.UNKNOWN]: 'unknown',
61
+ };
62
+
481
63
  export class AidaAbortError extends Error {}
482
64
  export class AidaBlockError extends Error {}
483
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
+
484
73
  export class AidaClient {
74
+ // Delegate client
75
+ #gcaClient = new GcaClient.GcaClient();
76
+
485
77
  static buildConsoleInsightsRequest(input: string): DoConversationRequest {
486
78
  const disallowLogging = Root.Runtime.hostConfig.aidaAvailability?.disallowLogging ?? true;
487
79
  const chromeVersion = Root.Runtime.getChromeVersion();
@@ -568,81 +160,71 @@ export class AidaClient {
568
160
  };
569
161
  })();
570
162
  const streamId = bindOutputStream(stream);
571
- DispatchHttpRequestClient
572
- .makeHttpRequest(
573
- {
574
- service: SERVICE_NAME,
575
- path: '/v1/aida:doConversation',
576
- method: 'POST',
577
- body: JSON.stringify(request),
578
- streamId,
579
- },
580
- options)
581
- .then(
582
- () => {
583
- void stream.close();
584
- },
585
- err => {
586
- if (err instanceof DispatchHttpRequestClient.DispatchHttpRequestError && err.response) {
587
- const result = err.response;
588
- if (result.statusCode === 403) {
589
- stream.fail(new Error('Server responded: permission denied'));
590
- return;
591
- }
592
- if ('error' in result && result.error) {
593
- stream.fail(new Error(`Cannot send request: ${result.error} ${result.detail || ''}`));
594
- return;
595
- }
596
- if ('netErrorName' in result && result.netErrorName === 'net::ERR_TIMED_OUT') {
597
- stream.fail(new Error('doAidaConversation timed out'));
598
- return;
599
- }
600
- if (result.statusCode !== 200) {
601
- stream.fail(new Error(`Request failed: ${JSON.stringify(result)}`));
602
- return;
603
- }
604
- }
605
- stream.fail(err);
606
- });
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> {
607
210
  let chunk;
608
211
  const text = [];
609
212
  let inCodeChunk = false;
610
213
  const functionCalls: AidaFunctionCallResponse[] = [];
611
214
  let metadata: ResponseMetadata = {rpcGlobalId: 0};
612
215
  while ((chunk = await stream.read())) {
216
+ debugLog('doConversation stream chunk:', chunk);
613
217
  let textUpdated = false;
614
- // The AIDA response is a JSON array of objects, split at the object
615
- // boundary. Therefore each chunk may start with `[` or `,` and possibly
616
- // followed by `]`. Each chunk may include one or more objects, so we
617
- // make sure that each chunk becomes a well-formed JSON array when we
618
- // parse it by adding `[` and `]` and removing `,` where appropriate.
619
- if (!chunk.length) {
620
- continue;
621
- }
622
- if (chunk.startsWith(',')) {
623
- chunk = chunk.slice(1);
624
- }
625
- if (!chunk.startsWith('[')) {
626
- chunk = '[' + chunk;
627
- }
628
- if (!chunk.endsWith(']')) {
629
- chunk = chunk + ']';
630
- }
631
- let results;
632
- try {
633
- results = JSON.parse(chunk);
634
- } catch (error) {
635
- throw new Error('Cannot parse chunk: ' + chunk, {cause: error});
636
- }
218
+ const results = this.#parseAndTranslate(chunk);
637
219
 
638
220
  for (const result of results) {
639
- if ('metadata' in result) {
221
+ if (result.metadata) {
640
222
  metadata = result.metadata;
641
223
  if (metadata?.attributionMetadata?.attributionAction === RecitationAction.BLOCK) {
642
224
  throw new AidaBlockError();
643
225
  }
644
226
  }
645
- if ('textChunk' in result) {
227
+ if (result.textChunk) {
646
228
  if (inCodeChunk) {
647
229
  text.push(CODE_CHUNK_SEPARATOR());
648
230
  inCodeChunk = false;
@@ -650,7 +232,7 @@ export class AidaClient {
650
232
 
651
233
  text.push(result.textChunk.text);
652
234
  textUpdated = true;
653
- } else if ('codeChunk' in result) {
235
+ } else if (result.codeChunk) {
654
236
  if (!inCodeChunk) {
655
237
  const language = AidaLanguageToMarkdown[result.codeChunk.inferenceLanguage as AidaInferenceLanguage] ?? '';
656
238
  text.push(CODE_CHUNK_SEPARATOR(language));
@@ -659,7 +241,7 @@ export class AidaClient {
659
241
 
660
242
  text.push(result.codeChunk.code);
661
243
  textUpdated = true;
662
- } else if ('functionCallChunk' in result) {
244
+ } else if (result.functionCallChunk) {
663
245
  functionCalls.push({
664
246
  name: result.functionCallChunk.functionCall.name,
665
247
  args: result.functionCallChunk.functionCall.args,
@@ -687,6 +269,40 @@ export class AidaClient {
687
269
  };
688
270
  }
689
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
+
690
306
  registerClientEvent(clientEvent: AidaRegisterClientEvent): Promise<AidaClientResult> {
691
307
  // Disable logging for now.
692
308
  // For context, see b/454563259#comment35.
@@ -695,7 +311,11 @@ export class AidaClient {
695
311
  clientEvent.disable_user_content_logging = true;
696
312
  }
697
313
 
314
+ if (this.#gcaClient.enabled()) {
315
+ return this.#gcaClient.registerClientEvent(clientEvent);
316
+ }
698
317
  const {promise, resolve} = Promise.withResolvers<AidaClientResult>();
318
+
699
319
  InspectorFrontendHostInstance.registerAidaClientEvent(
700
320
  JSON.stringify({
701
321
  client: CLIENT_NAME,
@@ -720,6 +340,9 @@ export class AidaClient {
720
340
  request.metadata.disable_user_content_logging = true;
721
341
  }
722
342
 
343
+ if (this.#gcaClient.enabled()) {
344
+ return await this.#gcaClient.completeCode(request);
345
+ }
723
346
  const {promise, resolve} = Promise.withResolvers<AidaCodeCompleteResult>();
724
347
  InspectorFrontendHostInstance.aidaCodeComplete(JSON.stringify(request), resolve);
725
348
  const completeCodeResult = await promise;
@@ -771,6 +394,11 @@ export class AidaClient {
771
394
  if (Root.Runtime.hostConfig.devToolsGeminiRebranding?.enabled) {
772
395
  request.metadata.disable_user_content_logging = true;
773
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
+ }
774
402
  const response = await DispatchHttpRequestClient.makeHttpRequest<GenerateCodeResponse>(
775
403
  {
776
404
  service: SERVICE_NAME,