chrome-devtools-frontend 1.0.1598808 → 1.0.1601661

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 (161) hide show
  1. package/.agents/README.md +13 -0
  2. package/{agents/prompts/creating-a-model.md → .agents/skills/creating-a-model/SKILL.md} +7 -1
  3. package/{agents/prompts/devtools-imports.md → .agents/skills/devtools-imports/SKILL.md} +10 -5
  4. package/{agents/prompts/merging-devtools-module.md → .agents/skills/merging-devtools-module/SKILL.md} +5 -0
  5. package/{agents/prompts/ui-widgets.md → .agents/skills/ui-widgets/SKILL.md} +5 -0
  6. package/{agents/prompts/verification.md → .agents/skills/verification/SKILL.md} +5 -0
  7. package/front_end/core/common/Settings.ts +24 -1
  8. package/front_end/core/dom_extension/DOMExtension.ts +1 -0
  9. package/front_end/core/host/AidaClient.ts +5 -2
  10. package/front_end/core/host/AidaGcaTranslation.ts +377 -0
  11. package/front_end/core/host/GcaTypes.ts +520 -0
  12. package/front_end/core/host/UserMetrics.ts +0 -3
  13. package/front_end/core/host/host.ts +4 -0
  14. package/front_end/core/root/ExperimentNames.ts +0 -3
  15. package/front_end/core/sdk/CPUThrottlingManager.ts +12 -9
  16. package/front_end/core/sdk/ResourceTreeModel.ts +1 -1
  17. package/front_end/core/sdk/SourceMap.ts +4 -2
  18. package/front_end/entrypoints/main/MainImpl.ts +1 -12
  19. package/front_end/generated/Deprecation.ts +16 -0
  20. package/front_end/generated/InspectorBackendCommands.ts +4 -6
  21. package/front_end/generated/protocol.ts +46 -77
  22. package/front_end/models/ai_assistance/AiConversation.ts +49 -22
  23. package/front_end/models/ai_assistance/AiHistoryStorage.snapshot.txt +1 -1
  24. package/front_end/models/ai_assistance/AiHistoryStorage.ts +1 -0
  25. package/front_end/models/ai_assistance/ConversationHandler.ts +16 -11
  26. package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +76 -36
  27. package/front_end/models/ai_assistance/agents/AiAgent.ts +26 -2
  28. package/front_end/models/ai_assistance/agents/BreakpointDebuggerAgent.ts +0 -1
  29. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.snapshot.txt +11 -0
  30. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +39 -0
  31. package/front_end/models/ai_assistance/agents/ConversationSummaryAgent.ts +53 -12
  32. package/front_end/models/ai_assistance/agents/FileAgent.ts +0 -15
  33. package/front_end/models/ai_assistance/agents/NetworkAgent.ts +0 -5
  34. package/front_end/models/ai_assistance/agents/PerformanceAgent.snapshot.txt +57 -0
  35. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +87 -15
  36. package/front_end/models/ai_assistance/agents/PerformanceAnnotationsAgent.ts +0 -10
  37. package/front_end/models/ai_assistance/agents/StylingAgent.snapshot.txt +0 -6
  38. package/front_end/models/ai_assistance/agents/StylingAgent.ts +1 -5
  39. package/front_end/models/ai_assistance/ai_assistance.ts +2 -0
  40. package/front_end/models/ai_assistance/data_formatters/LighthouseFormatter.snapshot.txt +84 -0
  41. package/front_end/models/ai_assistance/data_formatters/LighthouseFormatter.ts +172 -0
  42. package/front_end/models/breakpoints/BreakpointManager.ts +20 -12
  43. package/front_end/models/emulation/DeviceModeModel.ts +5 -1
  44. package/front_end/models/emulation/EmulatedDevices.ts +3 -2
  45. package/front_end/models/javascript_metadata/NativeFunctions.js +60 -0
  46. package/front_end/models/lighthouse/LighthouseReporterTypes.ts +104 -10
  47. package/front_end/models/lighthouse/RunTypes.ts +42 -0
  48. package/front_end/models/lighthouse/lighthouse.ts +2 -0
  49. package/front_end/models/live-metrics/web-vitals-injected/web-vitals-injected.ts +59 -35
  50. package/front_end/models/stack_trace/StackTrace.ts +5 -0
  51. package/front_end/models/stack_trace/StackTraceImpl.ts +7 -1
  52. package/front_end/models/stack_trace/StackTraceModel.ts +2 -1
  53. package/front_end/models/stack_trace/stack_trace.ts +4 -0
  54. package/front_end/models/trace/ModelImpl.ts +4 -0
  55. package/front_end/models/trace/helpers/SamplesIntegrator.ts +1 -8
  56. package/front_end/models/trace/types/Configuration.ts +0 -5
  57. package/front_end/panels/accessibility/AccessibilityNodeView.ts +7 -3
  58. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +163 -74
  59. package/front_end/panels/ai_assistance/ExportConversation.ts +25 -0
  60. package/front_end/panels/ai_assistance/ai_assistance.ts +2 -0
  61. package/front_end/panels/ai_assistance/components/ChatInput.ts +2 -0
  62. package/front_end/panels/ai_assistance/components/ChatMessage.ts +120 -32
  63. package/front_end/panels/ai_assistance/components/ChatView.ts +44 -0
  64. package/front_end/panels/ai_assistance/components/ExportForAgentsDialog.ts +240 -0
  65. package/front_end/panels/ai_assistance/components/PerformanceAgentMarkdownRenderer.ts +4 -12
  66. package/front_end/panels/ai_assistance/components/StylingAgentMarkdownRenderer.ts +5 -27
  67. package/front_end/panels/ai_assistance/components/WalkthroughView.ts +115 -17
  68. package/front_end/panels/ai_assistance/components/chatMessage.css +65 -1
  69. package/front_end/panels/ai_assistance/components/chatView.css +8 -0
  70. package/front_end/panels/ai_assistance/components/exportForAgentsDialog.css +82 -0
  71. package/front_end/panels/ai_assistance/components/walkthroughView.css +9 -1
  72. package/front_end/panels/animation/AnimationTimeline.ts +5 -5
  73. package/front_end/panels/application/AppManifestView.ts +13 -7
  74. package/front_end/panels/application/FrameDetailsView.ts +4 -4
  75. package/front_end/panels/application/preloading/PreloadingView.ts +2 -4
  76. package/front_end/panels/application/preloading/components/PreloadingDetailsReportView.ts +6 -3
  77. package/front_end/panels/application/preloading/components/PreloadingString.ts +15 -2
  78. package/front_end/panels/application/preloading/helper/PreloadingForward.ts +31 -2
  79. package/front_end/panels/browser_debugger/DOMBreakpointsSidebarPane.ts +3 -2
  80. package/front_end/panels/common/DOMLinkifier.ts +10 -8
  81. package/front_end/panels/console/ConsoleView.ts +24 -2
  82. package/front_end/panels/console/ConsoleViewMessage.ts +22 -23
  83. package/front_end/panels/console/console.ts +0 -2
  84. package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +5 -5
  85. package/front_end/panels/elements/ElementsTreeElement.ts +2 -3
  86. package/front_end/panels/elements/PropertiesWidget.ts +5 -3
  87. package/front_end/panels/elements/StandaloneStylesContainer.ts +21 -9
  88. package/front_end/panels/elements/StylePropertiesSection.ts +98 -50
  89. package/front_end/panels/elements/StylePropertyTreeElement.ts +38 -4
  90. package/front_end/panels/elements/StylesAiCodeCompletionProvider.ts +43 -35
  91. package/front_end/panels/elements/StylesSidebarPane.ts +154 -24
  92. package/front_end/panels/elements/components/ComputedStyleTrace.ts +3 -2
  93. package/front_end/panels/event_listeners/EventListenersView.ts +16 -4
  94. package/front_end/panels/explain/components/ConsoleInsight.ts +6 -9
  95. package/front_end/panels/explain/explain-meta.ts +5 -0
  96. package/front_end/panels/issues/AffectedResourcesView.ts +5 -9
  97. package/front_end/panels/issues/AffectedSelectivePermissionsInterventionView.ts +1 -1
  98. package/front_end/panels/lighthouse/LighthouseController.ts +154 -164
  99. package/front_end/panels/lighthouse/LighthousePanel.ts +5 -9
  100. package/front_end/panels/lighthouse/LighthouseProtocolService.ts +1 -0
  101. package/front_end/panels/lighthouse/LighthouseReportRenderer.ts +9 -6
  102. package/front_end/panels/lighthouse/LighthouseStartView.ts +7 -6
  103. package/front_end/panels/lighthouse/LighthouseStatusView.ts +32 -8
  104. package/front_end/panels/linear_memory_inspector/components/LinearMemoryInspector.ts +7 -3
  105. package/front_end/panels/network/NetworkDataGridNode.ts +34 -0
  106. package/front_end/panels/network/NetworkLogViewColumns.ts +10 -0
  107. package/front_end/panels/network/RequestPayloadView.ts +4 -1
  108. package/front_end/panels/network/RequestTimingView.ts +8 -2
  109. package/front_end/panels/performance_monitor/performanceMonitor.css +6 -4
  110. package/front_end/panels/recorder/RecorderController.ts +52 -14
  111. package/front_end/panels/recorder/components/RecordingView.ts +2 -1
  112. package/front_end/panels/recorder/models/RecordingStorage.ts +15 -20
  113. package/front_end/panels/sensors/SensorsView.ts +333 -157
  114. package/front_end/panels/settings/emulation/DevicesSettingsTab.ts +18 -4
  115. package/front_end/panels/sources/DebuggerPausedMessage.ts +6 -6
  116. package/front_end/panels/sources/FilteredUISourceCodeListProvider.ts +2 -3
  117. package/front_end/panels/sources/NavigatorView.ts +11 -7
  118. package/front_end/panels/sources/ScopeChainSidebarPane.ts +1 -1
  119. package/front_end/panels/sources/SourcesPanel.ts +12 -34
  120. package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +5 -1
  121. package/front_end/panels/sources/sources-meta.ts +6 -0
  122. package/front_end/panels/timeline/StatusDialog.ts +159 -83
  123. package/front_end/panels/timeline/ThirdPartyTreeView.ts +6 -2
  124. package/front_end/panels/timeline/TimelineController.ts +0 -4
  125. package/front_end/panels/timeline/TimelineDetailsView.ts +35 -3
  126. package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +6 -1
  127. package/front_end/panels/timeline/TimelineFlameChartNetworkDataProvider.ts +9 -4
  128. package/front_end/panels/timeline/TimelinePanel.ts +36 -11
  129. package/front_end/panels/timeline/TimelineTreeView.ts +14 -3
  130. package/front_end/panels/timeline/TimelineUIUtils.ts +5 -57
  131. package/front_end/panels/timeline/components/InteractionBreakdown.ts +2 -1
  132. package/front_end/panels/timeline/components/LiveMetricsView.ts +2 -2
  133. package/front_end/panels/timeline/components/NetworkRequestTooltip.ts +3 -7
  134. package/front_end/panels/timeline/components/Sidebar.ts +11 -19
  135. package/front_end/panels/timeline/components/SidebarInsightsTab.ts +2 -1
  136. package/front_end/panels/timeline/components/SidebarSingleInsightSet.ts +60 -27
  137. package/front_end/panels/timeline/components/TimelineRangeSummaryView.ts +66 -0
  138. package/front_end/panels/timeline/components/TimelineSummary.ts +7 -19
  139. package/front_end/panels/timeline/components/components.ts +2 -0
  140. package/front_end/panels/timeline/components/insights/BaseInsightComponent.ts +55 -28
  141. package/front_end/panels/timeline/components/insights/NodeLink.ts +3 -3
  142. package/front_end/panels/timeline/components/insights/baseInsightComponent.css +7 -0
  143. package/front_end/panels/timeline/components/insights/insights.ts +0 -2
  144. package/front_end/panels/timeline/components/timelineRangeSummaryView.css +20 -0
  145. package/front_end/panels/timeline/overlays/OverlaysImpl.ts +7 -7
  146. package/front_end/panels/timeline/timeline-meta.ts +11 -0
  147. package/front_end/panels/timeline/timelineDetailsView.css +0 -9
  148. package/front_end/third_party/chromium/README.chromium +1 -1
  149. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onINP.js +11 -2
  150. package/front_end/third_party/web-vitals/package/src/attribution/onINP.ts +11 -2
  151. package/front_end/third_party/web-vitals/patches/0001-Add-onEachInteraction-to-onINP-options.patch +65 -4
  152. package/front_end/ui/kit/link/link.css +2 -2
  153. package/front_end/ui/legacy/Widget.ts +5 -3
  154. package/front_end/ui/legacy/components/object_ui/CustomPreviewComponent.ts +7 -2
  155. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +57 -35
  156. package/front_end/ui/legacy/components/source_frame/PreviewFactory.ts +1 -0
  157. package/front_end/ui/visual_logging/KnownContextValues.ts +6 -1
  158. package/package.json +1 -1
  159. package/agents/prompts/README.md +0 -18
  160. package/front_end/panels/timeline/components/insights/InsightRenderer.ts +0 -93
  161. /package/front_end/{panels/console → models/stack_trace}/ErrorStackParser.ts +0 -0
@@ -0,0 +1,13 @@
1
+ # .agents
2
+
3
+ This directory contains workspace-specific agent expertise and skills.
4
+
5
+ ## Skills
6
+
7
+ Workspace skills are located in `.agents/skills/`. These represent on-demand expertise that the AI agent can activate to complete specialized tasks.
8
+
9
+ To use a skill, the agent will autonomously identify it based on its description and pull in the instructions using the `activate_skill` tool.
10
+
11
+ ## Contributing
12
+
13
+ Contributions to existing skills or adding new ones are encouraged via CLs.
@@ -1,3 +1,9 @@
1
+ ```
2
+ ---
3
+ name: devtools-model-management
4
+ description: Guidelines for creating, migrating, and registering models in front_end/models/. Covers BUILD.gn, devtools_grd_files.gni, and entrypoints.
5
+ ---
6
+
1
7
  # Creating or Migrating a Model in DevTools
2
8
 
3
9
  This guide outlines the standard procedure for creating a new model or migrating an existing one to `front_end/models/`.
@@ -48,4 +54,4 @@ The build system does not auto-detect new modules. You must manually register th
48
54
  * **Circular Dependencies:** Occur when internal files import from the directory's own barrel file.
49
55
  * **Missing Tests:** Failing to add the target to `front_end/BUILD.gn` means tests exist but never run.
50
56
  * **Legacy Exports:** Forgetting to remove the class from the old location's `files` or `exports` allows old patterns to persist.
51
- * **Build Errors:** Including the barrel file in `devtools_module` sources causes duplicate definition errors.
57
+ * **Build Errors:** Including the barrel file in `devtools_module` sources causes duplicate definition errors.
@@ -1,3 +1,8 @@
1
+ ---
2
+ name: devtools-imports
3
+ description: Conventions for importing code in Devtools to avoid build errors. Covers cross-module imports, internal imports, and the "import * as" requirement.
4
+ ---
5
+
1
6
  # Imports
2
7
 
3
8
  This codebase follows a special convention for importing code that must be followed to avoid build errors.
@@ -16,23 +21,23 @@ Within each module there are multiple TypeScript files. *The file that is named
16
21
 
17
22
  When you want to reuse code from other modules, *you must import that module via its entrypoint*. Imagine we are in `front_end/panels/timeline/TimelinePanel.ts`. This import is GOOD:
18
23
 
19
- ```
24
+ ```ts
20
25
  import * as Trace from '../models/trace/trace.js'; // import the entrypoint
21
26
  ```
22
27
 
23
28
  This import is BAD because we import a file that is NOT the entrypoint:
24
29
 
25
- ```
30
+ ```ts
26
31
  import * as ModelImpl from '../models/trace/ModelImpl.js' // NEVER ALLOWED
27
32
  ```
28
33
 
29
34
  Additionally, you **must import using the `import * as` syntax**.
30
35
 
31
- ```
36
+ ```ts
32
37
  import {ModelImpl, X, Y} from '../models/trace/trace.js'; // BAD
33
38
  ```
34
39
 
35
- ```
40
+ ```ts
36
41
  import * as Trace from '../models/trace/trace.js'; // GOOD
37
42
  ```
38
43
 
@@ -42,6 +47,6 @@ If you are within the same module, it is OK to import from files directly rather
42
47
 
43
48
  For example, if you are editing `front_end/models/trace/ModelImpl.ts` this would be acceptable:
44
49
 
45
- ```
50
+ ```ts
46
51
  import {Foo} from './Foo.js'; // allowed because Foo.ts is in the same directory.
47
52
  ```
@@ -1,3 +1,8 @@
1
+ ---
2
+ name: devtools-module-merging
3
+ description: Workflow for merging a DevTools submodule into its parent module. Covers BUILD.gn consolidation and updating devtools_grd_files.gni.
4
+ ---
5
+
1
6
  # Workflow: Merging a DevTools Submodule into its Parent
2
7
 
3
8
  This document outlines the process for merging a submodule (e.g., `panels/timeline/extensions`) into its parent module (e.g., `panels/timeline`) within the DevTools build system. The goal is to simplify the build configuration by consolidating `BUILD.gn` files while keeping the original source file directory structure.
@@ -1,3 +1,8 @@
1
+ ---
2
+ name: devtools-ui-widgets
3
+ description: Guidelines for building UI widgets using the MVP architecture in DevTools. Covers Widget lifecycle, lit-html views, and state management.
4
+ ---
5
+
1
6
  ## UI Widget Framework Guide (MVP Architecture)
2
7
 
3
8
  Adhere strictly to the Model-View-Presenter (MVP) architecture.
@@ -1,3 +1,8 @@
1
+ ---
2
+ name: devtools-verification
3
+ description: MANDATORY: Activate this skill ANY TIME you need to build the project, run tests, or verify code health in DevTools. You MUST use this skill before executing commands like npm test, npm run build, autoninja, or linters, as it contains critical, repository-specific instructions on how to correctly format these commands, filter test runs, and interpret failures.
4
+ ---
5
+
1
6
  # Instructions on how to verify your changes
2
7
 
3
8
  ## Testing
@@ -688,7 +688,7 @@ export class VersionController {
688
688
  static readonly SYNCED_VERSION_SETTING_NAME = 'syncedInspectorVersion';
689
689
  static readonly LOCAL_VERSION_SETTING_NAME = 'localInspectorVersion';
690
690
 
691
- static readonly CURRENT_VERSION = 41;
691
+ static readonly CURRENT_VERSION = 42;
692
692
 
693
693
  readonly #settings: Settings;
694
694
  readonly #globalVersionSetting: Setting<number>;
@@ -1480,6 +1480,29 @@ export class VersionController {
1480
1480
  }
1481
1481
  }
1482
1482
 
1483
+ /**
1484
+ * The recording in recorder panel may have unreasonably long titles
1485
+ * or a lot of steps which can cause renderer crashes.
1486
+ * Similar to https://crbug.com/40918380
1487
+ */
1488
+ updateVersionFrom41To42(): void {
1489
+ const recordingsSetting = this.#settings.createSetting<Array<{flow: {steps: unknown[], title: string}}>>(
1490
+ 'recorder-recordings-ng',
1491
+ [],
1492
+ );
1493
+ const recordings = recordingsSetting.get();
1494
+ if (recordings.length === 0) {
1495
+ return;
1496
+ }
1497
+
1498
+ for (const recording of recordings) {
1499
+ recording.flow.title = Platform.StringUtilities.trimEndWithMaxLength(recording.flow.title, 300);
1500
+ recording.flow.steps = recording.flow.steps.slice(0, 4096);
1501
+ }
1502
+
1503
+ recordingsSetting.set(recordings);
1504
+ }
1505
+
1483
1506
  /*
1484
1507
  * Any new migration should be added before this comment.
1485
1508
  *
@@ -36,6 +36,7 @@
36
36
 
37
37
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
38
38
  // @ts-nocheck This file is not checked by TypeScript Compiler as it has a lot of legacy code.
39
+ /* eslint-disable @devtools/no-imperative-dom-api */
39
40
 
40
41
  import * as Platform from '../platform/platform.js';
41
42
 
@@ -67,10 +67,10 @@ interface BaseFunctionParam {
67
67
  }
68
68
 
69
69
  export interface FunctionPrimitiveParams extends BaseFunctionParam {
70
- type: ParametersTypes.BOOLEAN|ParametersTypes.INTEGER|ParametersTypes.STRING|ParametersTypes.BOOLEAN;
70
+ type: ParametersTypes.BOOLEAN|ParametersTypes.INTEGER|ParametersTypes.STRING;
71
71
  }
72
72
 
73
- interface FunctionArrayParam extends BaseFunctionParam {
73
+ export interface FunctionArrayParam extends BaseFunctionParam {
74
74
  type: ParametersTypes.ARRAY;
75
75
  items: FunctionPrimitiveParams;
76
76
  }
@@ -301,6 +301,9 @@ export enum UseCase {
301
301
 
302
302
  // Code generation use case is expected to generate code from scratch
303
303
  CODE_GENERATION = 1,
304
+
305
+ // Code transformation or code editing use case.
306
+ CODE_TRANSFORMATION = 2,
304
307
  }
305
308
 
306
309
  /* eslint-disable @typescript-eslint/naming-convention */
@@ -0,0 +1,377 @@
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 AIDA from './AidaClient.js';
6
+ import * as GCA from './GcaTypes.js';
7
+
8
+ type AidaRequest = AIDA.DoConversationRequest|AIDA.CompletionRequest|AIDA.GenerateCodeRequest;
9
+
10
+ function createBaseGcaRequest(request: AidaRequest, contents: GCA.Content[]): GCA.GenerateContentRequest {
11
+ const gcaRequest: GCA.GenerateContentRequest = {contents};
12
+ mapCommonAidaRequestFields(request, gcaRequest);
13
+ buildLabels(request, gcaRequest);
14
+
15
+ if ('preamble' in request && request.preamble) {
16
+ gcaRequest.system_instruction = {
17
+ role: 'user',
18
+ parts: [{text: request.preamble}],
19
+ };
20
+ }
21
+
22
+ return gcaRequest;
23
+ }
24
+
25
+ export function aidaDoConversationRequestToGcaRequest(request: AIDA.DoConversationRequest): GCA.GenerateContentRequest {
26
+ const contents: GCA.Content[] = [];
27
+
28
+ if (request.historical_contexts) {
29
+ contents.push(...request.historical_contexts.map(convertAidaContentToGcaContent));
30
+ }
31
+ contents.push(convertAidaContentToGcaContent(request.current_message));
32
+
33
+ const gcaRequest = createBaseGcaRequest(request, contents);
34
+
35
+ if (request.function_declarations) {
36
+ gcaRequest.tools = [{
37
+ function_declarations: request.function_declarations.map(fd => ({
38
+ name: fd.name,
39
+ description: fd.description,
40
+ parameters: convertAidaParamToGcaSchema(fd.parameters),
41
+ })),
42
+ }];
43
+ }
44
+
45
+ return gcaRequest;
46
+ }
47
+
48
+ function mapCommonAidaRequestFields(aidaRequest: AidaRequest, gcaRequest: GCA.GenerateContentRequest): void {
49
+ if (aidaRequest.options?.model_id) {
50
+ gcaRequest.model = aidaRequest.options.model_id;
51
+ }
52
+ if (aidaRequest.metadata.string_session_id) {
53
+ gcaRequest.session_id = aidaRequest.metadata.string_session_id;
54
+ }
55
+ if (aidaRequest.options?.temperature !== undefined) {
56
+ gcaRequest.generation_config = {
57
+ ...gcaRequest.generation_config,
58
+ temperature: aidaRequest.options.temperature,
59
+ };
60
+ }
61
+ }
62
+
63
+ export function gcaResponseToAidaDoConversationResponse(response: GCA.GenerateContentResponse):
64
+ AIDA.DoConversationResponse {
65
+ const candidate = response.candidates[0];
66
+ const functionCalls: AIDA.AidaFunctionCallResponse[] = [];
67
+
68
+ if (candidate?.content?.parts) {
69
+ for (const part of candidate.content.parts) {
70
+ if (part.function_call) {
71
+ functionCalls.push({
72
+ name: part.function_call.name,
73
+ args: part.function_call.args || {},
74
+ });
75
+ }
76
+ }
77
+ }
78
+
79
+ return {
80
+ explanation: extractTextFromGcaParts(candidate?.content?.parts),
81
+ metadata: {
82
+ rpcGlobalId: response.response_id,
83
+ },
84
+ functionCalls: functionCalls.length > 0 ?
85
+ (functionCalls as [AIDA.AidaFunctionCallResponse, ...AIDA.AidaFunctionCallResponse[]]) :
86
+ undefined,
87
+ completed: true,
88
+ };
89
+ }
90
+
91
+ function extractTextFromGcaParts(parts: GCA.Part[]|undefined): string {
92
+ if (!parts) {
93
+ return '';
94
+ }
95
+ return parts.map(p => p.text || '').join('');
96
+ }
97
+
98
+ export function aidaEventToGcaTelemetryRequest(clientEvent: AIDA.AidaRegisterClientEvent): GCA.SendTelemetryRequest {
99
+ const feedbackMetrics: GCA.FeedbackMetric[] = [];
100
+ const responseId = String(clientEvent.corresponding_aida_rpc_global_id);
101
+ const eventTime = new Date().toISOString();
102
+
103
+ if (clientEvent.do_conversation_client_event) {
104
+ const feedback = clientEvent.do_conversation_client_event.user_feedback;
105
+ if (feedback.sentiment) {
106
+ let interaction: GCA.InteractionType = GCA.InteractionType.INTERACTION_TYPE_UNSPECIFIED;
107
+ if (feedback.sentiment === AIDA.Rating.POSITIVE) {
108
+ interaction = GCA.InteractionType.THUMBS_UP;
109
+ } else if (feedback.sentiment === AIDA.Rating.NEGATIVE) {
110
+ interaction = GCA.InteractionType.THUMBS_DOWN;
111
+ }
112
+ feedbackMetrics.push({
113
+ event_time: eventTime,
114
+ response_id: responseId,
115
+ suggestion_interaction: {interaction},
116
+ });
117
+ }
118
+ }
119
+
120
+ feedbackMetrics.push(
121
+ ...convertCodeTelemetry(clientEvent.complete_code_client_event, GCA.Method.COMPLETE_CODE, responseId, eventTime));
122
+ feedbackMetrics.push(
123
+ ...convertCodeTelemetry(clientEvent.generate_code_client_event, GCA.Method.GENERATE_CODE, responseId, eventTime));
124
+
125
+ return {feedback_metrics: feedbackMetrics};
126
+ }
127
+
128
+ /* eslint-disable @typescript-eslint/naming-convention */
129
+ function convertCodeTelemetry(
130
+ event: {user_acceptance?: AIDA.UserAcceptance, user_impression?: AIDA.UserImpression}|undefined, method: GCA.Method,
131
+ responseId: string, eventTime: string): GCA.FeedbackMetric[] {
132
+ if (!event) {
133
+ return [];
134
+ }
135
+ if ('user_impression' in event && event.user_impression) {
136
+ const impression = event.user_impression;
137
+ return [{
138
+ event_time: eventTime,
139
+ response_id: responseId,
140
+ suggestion_offered: {
141
+ method,
142
+ status: GCA.SuggestionStatus.NO_ERROR,
143
+ response_latency: `${impression.latency.duration.seconds + impression.latency.duration.nanos / 1e9}s`,
144
+ },
145
+ }];
146
+ }
147
+ if ('user_acceptance' in event && event.user_acceptance) {
148
+ const acceptance = event.user_acceptance;
149
+ return [{
150
+ event_time: eventTime,
151
+ response_id: responseId,
152
+ suggestion_interaction: {
153
+ interaction: GCA.InteractionType.ACCEPT,
154
+ candidate_index: acceptance.sample.sample_id,
155
+ },
156
+ }];
157
+ }
158
+ return [];
159
+ }
160
+ /* eslint-enable @typescript-eslint/naming-convention */
161
+
162
+ export function aidaCompletionRequestToGcaRequest(request: AIDA.CompletionRequest): GCA.GenerateContentRequest {
163
+ const contents: GCA.Content[] = [
164
+ {
165
+ role: 'user',
166
+ parts: [{text: request.prefix + (request.suffix || '')}],
167
+ },
168
+ ];
169
+
170
+ const gcaRequest = createBaseGcaRequest(request, contents);
171
+
172
+ if (request.options?.stop_sequences) {
173
+ gcaRequest.generation_config = {
174
+ ...gcaRequest.generation_config,
175
+ stop_sequences: request.options.stop_sequences,
176
+ };
177
+ }
178
+
179
+ if (request.additional_files) {
180
+ gcaRequest.aicode = {
181
+ experience: 'completion',
182
+ files: request.additional_files.map(f => ({
183
+ file_uri: f.path,
184
+ inclusion_reason: [AidaReasonToGcaInclusionReason[f.included_reason]],
185
+ })),
186
+ };
187
+ }
188
+
189
+ return gcaRequest;
190
+ }
191
+
192
+ /* eslint-disable @typescript-eslint/naming-convention */
193
+ function buildLabels(request: AidaRequest, gcaRequest: GCA.GenerateContentRequest): void {
194
+ const labels: Record<string, string> = {};
195
+ if (request.client) {
196
+ labels['client'] = request.client;
197
+ }
198
+ if ('functionality_type' in request && request.functionality_type !== undefined) {
199
+ labels['functionality_type'] = AIDA.FunctionalityType[request.functionality_type];
200
+ }
201
+ if ('client_feature' in request && request.client_feature !== undefined) {
202
+ labels['client_feature'] = AIDA.ClientFeature[request.client_feature];
203
+ }
204
+ if ('last_user_action' in request && request.last_user_action !== undefined) {
205
+ labels['last_user_action'] = AIDA.EditType[request.last_user_action];
206
+ }
207
+ if ('use_case' in request && request.use_case !== undefined) {
208
+ labels['use_case'] = AIDA.UseCase[request.use_case];
209
+ }
210
+ const options = request.options as {
211
+ inference_language?: string,
212
+ expect_code_output?: boolean,
213
+ } | undefined;
214
+ if (options?.inference_language) {
215
+ labels['inference_language'] = options.inference_language;
216
+ }
217
+ if (options?.expect_code_output !== undefined) {
218
+ labels['expect_code_output'] = String(options.expect_code_output);
219
+ }
220
+
221
+ if (Object.keys(labels).length > 0) {
222
+ gcaRequest.labels = labels;
223
+ }
224
+ }
225
+ /* eslint-enable @typescript-eslint/naming-convention */
226
+
227
+ const AidaReasonToGcaInclusionReason: Record<AIDA.Reason, GCA.InclusionReason> = {
228
+ [AIDA.Reason.UNKNOWN]: GCA.InclusionReason.INCLUSION_REASON_UNSPECIFIED,
229
+ [AIDA.Reason.CURRENTLY_OPEN]: GCA.InclusionReason.OPEN,
230
+ // Intentional mapping due to type mismatch
231
+ // TODO(liviurau): find a way to validate this mapping
232
+ [AIDA.Reason.RECENTLY_OPENED]: GCA.InclusionReason.RECENTLY_CLOSED,
233
+ [AIDA.Reason.RECENTLY_EDITED]: GCA.InclusionReason.RECENTLY_EDITED,
234
+ [AIDA.Reason.COLOCATED]: GCA.InclusionReason.COLOCATED,
235
+ [AIDA.Reason.RELATED_FILE]: GCA.InclusionReason.RELATED,
236
+ };
237
+
238
+ export function gcaResponseToAidaCompletionResponse(response: GCA.GenerateContentResponse): AIDA.CompletionResponse {
239
+ const {samples, metadata} = gcaResponseToAidaSamplesAndMetadata(response);
240
+ return {
241
+ generatedSamples: samples,
242
+ metadata,
243
+ };
244
+ }
245
+
246
+ function gcaResponseToAidaSamplesAndMetadata(response: GCA.GenerateContentResponse): {
247
+ samples: AIDA.GenerationSample[],
248
+ metadata: AIDA.ResponseMetadata,
249
+ } {
250
+ return {
251
+ samples: response.candidates.map(gcaCandidateToAidaGenerationSample),
252
+ metadata: {
253
+ rpcGlobalId: response.response_id,
254
+ },
255
+ };
256
+ }
257
+
258
+ export function aidaGenerateCodeRequestToGcaRequest(request: AIDA.GenerateCodeRequest): GCA.GenerateContentRequest {
259
+ const gcaRequest = createBaseGcaRequest(request, [convertAidaContentToGcaContent(request.current_message)]);
260
+
261
+ if (request.context_files) {
262
+ gcaRequest.aicode = {
263
+ experience: 'generate_code',
264
+ files: request.context_files.map(f => ({
265
+ file_uri: f.path,
266
+ programming_language: f.programming_language,
267
+ })),
268
+ };
269
+ }
270
+
271
+ return gcaRequest;
272
+ }
273
+
274
+ export function gcaResponseToAidaGenerateCodeResponse(response: GCA.GenerateContentResponse):
275
+ AIDA.GenerateCodeResponse {
276
+ return gcaResponseToAidaSamplesAndMetadata(response);
277
+ }
278
+
279
+ function gcaCandidateToAidaGenerationSample(candidate: GCA.Candidate): AIDA.GenerationSample {
280
+ const generationSample: AIDA.GenerationSample = {
281
+ generationString: extractTextFromGcaParts(candidate.content?.parts),
282
+ score: 0,
283
+ sampleId: candidate.index,
284
+ };
285
+ if (candidate.citation_metadata) {
286
+ generationSample.attributionMetadata = {
287
+ attributionAction: AIDA.RecitationAction.CITE,
288
+ citations: candidate.citation_metadata.citations.map(c => ({
289
+ startIndex: c.start_index,
290
+ endIndex: c.end_index,
291
+ uri: c.uri,
292
+ })),
293
+ };
294
+ }
295
+ return generationSample;
296
+ }
297
+
298
+ function convertAidaContentToGcaContent(content: AIDA.Content): GCA.Content {
299
+ // TODO(liviurau): decide how to map AIDA.Role.SYSTEM
300
+ // currently it will default to 'user'
301
+ let role: GCA.Role = 'user';
302
+
303
+ if (content.role === AIDA.Role.MODEL) {
304
+ role = 'model';
305
+ }
306
+ return {
307
+ role,
308
+ parts: content.parts.map(convertAidaPartToGcaPart),
309
+ };
310
+ }
311
+
312
+ function convertAidaPartToGcaPart(part: AIDA.Part): GCA.Part {
313
+ if ('text' in part) {
314
+ return {text: part.text};
315
+ }
316
+ if ('functionCall' in part) {
317
+ return {
318
+ function_call: {
319
+ name: part.functionCall.name,
320
+ args: part.functionCall.args,
321
+ },
322
+ };
323
+ }
324
+ if ('functionResponse' in part) {
325
+ const fResponse: Record<string, unknown> = {};
326
+ if ('result' in part.functionResponse.response) {
327
+ fResponse.output = part.functionResponse.response['result'];
328
+ } else if ('output' in part.functionResponse.response) {
329
+ fResponse.output = part.functionResponse.response['output'];
330
+ } else if (!('error' in part.functionResponse.response)) {
331
+ fResponse.output = part.functionResponse.response;
332
+ }
333
+ if ('error' in part.functionResponse.response) {
334
+ fResponse.error = part.functionResponse.response['error'];
335
+ }
336
+ return {
337
+ function_response: {
338
+ name: part.functionResponse.name,
339
+ response: fResponse,
340
+ },
341
+ };
342
+ }
343
+ if ('inlineData' in part) {
344
+ return {
345
+ inline_data: {
346
+ mime_type: part.inlineData.mimeType,
347
+ data: part.inlineData.data,
348
+ },
349
+ };
350
+ }
351
+ return {};
352
+ }
353
+
354
+ type FunctionParam<T extends string|number|symbol = string> =
355
+ AIDA.FunctionObjectParam<T>|AIDA.FunctionArrayParam|AIDA.FunctionPrimitiveParams;
356
+
357
+ function convertAidaParamToGcaSchema<T extends string|number|symbol = string>(param: FunctionParam<T>): GCA.Schema {
358
+ const schema: GCA.Schema = {
359
+ type: param.type as unknown as GCA.Type,
360
+ description: param.description,
361
+ };
362
+ if (param.nullable) {
363
+ schema.nullable = param.nullable;
364
+ }
365
+
366
+ if (param.type === AIDA.ParametersTypes.ARRAY && param.items) {
367
+ schema.items = convertAidaParamToGcaSchema(param.items);
368
+ } else if (param.type === AIDA.ParametersTypes.OBJECT && param.properties) {
369
+ schema.properties = {};
370
+ for (const [key, value] of Object.entries(param.properties)) {
371
+ schema.properties[key] = convertAidaParamToGcaSchema(value as FunctionParam);
372
+ }
373
+ schema.required = param.required.map(r => r.toString());
374
+ }
375
+
376
+ return schema;
377
+ }