chrome-devtools-frontend 1.0.1599001 → 1.0.1602348
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/.agents/skills/verification/SKILL.md +1 -1
- package/.agents/skills/version-control/SKILL.md +71 -0
- package/front_end/core/common/Settings.ts +24 -1
- package/front_end/core/dom_extension/DOMExtension.ts +1 -0
- package/front_end/core/host/AidaClient.ts +5 -2
- package/front_end/core/host/AidaGcaTranslation.ts +377 -0
- package/front_end/core/host/GcaTypes.ts +3 -1
- package/front_end/core/host/InspectorFrontendHostStub.ts +0 -5
- package/front_end/core/host/UserMetrics.ts +0 -2
- package/front_end/core/host/host.ts +2 -0
- package/front_end/core/root/ExperimentNames.ts +0 -2
- package/front_end/core/root/Runtime.ts +0 -8
- package/front_end/core/sdk/CPUThrottlingManager.ts +12 -9
- package/front_end/core/sdk/DOMModel.ts +5 -4
- package/front_end/core/sdk/ResourceTreeModel.ts +1 -1
- package/front_end/core/sdk/SourceMap.ts +4 -2
- package/front_end/entrypoints/inspector_main/InspectorMain.ts +1 -1
- package/front_end/entrypoints/main/GlobalAiButton.ts +1 -1
- package/front_end/entrypoints/main/MainImpl.ts +1 -10
- package/front_end/generated/Deprecation.ts +16 -0
- package/front_end/generated/InspectorBackendCommands.ts +11 -12
- package/front_end/generated/protocol.ts +83 -82
- package/front_end/models/ai_assistance/AiConversation.ts +37 -21
- package/front_end/models/ai_assistance/ConversationHandler.ts +8 -9
- package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +235 -22
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.snapshot.txt +11 -0
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +38 -0
- package/front_end/models/ai_assistance/agents/ConversationSummaryAgent.ts +55 -13
- package/front_end/models/ai_assistance/agents/PerformanceAgent.snapshot.txt +57 -0
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +41 -3
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +1 -0
- package/front_end/models/ai_assistance/ai_assistance.ts +2 -0
- package/front_end/models/ai_assistance/data_formatters/LighthouseFormatter.snapshot.txt +84 -0
- package/front_end/models/ai_assistance/data_formatters/LighthouseFormatter.ts +172 -0
- package/front_end/models/breakpoints/BreakpointManager.ts +20 -12
- package/front_end/models/issues_manager/SharedDictionaryIssue.ts +5 -15
- package/front_end/models/issues_manager/descriptions/sharedDictionaryUseErrorCrossOriginNoCorsRequest.md +1 -0
- package/front_end/models/javascript_metadata/NativeFunctions.js +56 -0
- package/front_end/models/lighthouse/LighthouseReporterTypes.ts +104 -10
- package/front_end/models/lighthouse/RunTypes.ts +2 -1
- package/front_end/models/live-metrics/LiveMetrics.ts +51 -31
- package/front_end/models/live-metrics/web-vitals-injected/web-vitals-injected.ts +59 -35
- package/front_end/models/stack_trace/StackTrace.ts +5 -0
- package/front_end/models/stack_trace/StackTraceImpl.ts +7 -1
- package/front_end/models/stack_trace/StackTraceModel.ts +2 -1
- package/front_end/models/stack_trace/stack_trace.ts +4 -0
- package/front_end/panels/accessibility/ARIAAttributesView.ts +2 -2
- package/front_end/panels/accessibility/AccessibilityNodeView.ts +7 -3
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +79 -69
- package/front_end/panels/ai_assistance/ExportConversation.ts +25 -0
- package/front_end/panels/ai_assistance/ai_assistance.ts +2 -0
- package/front_end/panels/ai_assistance/components/ChatInput.ts +3 -2
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +28 -31
- package/front_end/panels/ai_assistance/components/ChatView.ts +44 -0
- package/front_end/panels/ai_assistance/components/ExportForAgentsDialog.ts +240 -0
- package/front_end/panels/ai_assistance/components/PerformanceAgentMarkdownRenderer.ts +4 -12
- package/front_end/panels/ai_assistance/components/StylingAgentMarkdownRenderer.ts +5 -27
- package/front_end/panels/ai_assistance/components/WalkthroughView.ts +115 -17
- package/front_end/panels/ai_assistance/components/chatMessage.css +4 -1
- package/front_end/panels/ai_assistance/components/chatView.css +8 -0
- package/front_end/panels/ai_assistance/components/exportForAgentsDialog.css +82 -0
- package/front_end/panels/ai_assistance/components/walkthroughView.css +9 -1
- package/front_end/panels/animation/AnimationTimeline.ts +5 -5
- package/front_end/panels/application/AppManifestView.ts +13 -7
- package/front_end/panels/application/FrameDetailsView.ts +4 -4
- package/front_end/panels/application/KeyValueStorageItemsView.ts +4 -4
- package/front_end/panels/browser_debugger/DOMBreakpointsSidebarPane.ts +3 -2
- package/front_end/panels/common/AiCodeCompletionSummaryToolbar.ts +2 -1
- package/front_end/panels/common/DOMLinkifier.ts +10 -8
- package/front_end/panels/console/ConsoleView.ts +24 -2
- package/front_end/panels/console/ConsoleViewMessage.ts +22 -23
- package/front_end/panels/console/console.ts +0 -2
- package/front_end/panels/console_counters/WarningErrorCounter.ts +7 -14
- package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +5 -5
- package/front_end/panels/elements/ElementsTreeElement.ts +2 -3
- package/front_end/panels/elements/NodeStackTraceWidget.ts +2 -1
- package/front_end/panels/elements/PropertiesWidget.ts +5 -3
- package/front_end/panels/elements/StandaloneStylesContainer.ts +21 -9
- package/front_end/panels/elements/StylePropertiesSection.ts +98 -50
- package/front_end/panels/elements/StylePropertyTreeElement.ts +40 -5
- package/front_end/panels/elements/StylesAiCodeCompletionProvider.ts +43 -35
- package/front_end/panels/elements/StylesSidebarPane.ts +154 -24
- package/front_end/panels/elements/components/ComputedStyleTrace.ts +3 -2
- package/front_end/panels/event_listeners/EventListenersView.ts +16 -4
- package/front_end/panels/explain/components/ConsoleInsight.ts +6 -9
- package/front_end/panels/explain/explain-meta.ts +5 -0
- package/front_end/panels/issues/AffectedResourcesView.ts +5 -9
- package/front_end/panels/issues/AffectedSelectivePermissionsInterventionView.ts +1 -1
- package/front_end/panels/lighthouse/LighthouseController.ts +6 -2
- package/front_end/panels/lighthouse/LighthousePanel.ts +3 -2
- package/front_end/panels/lighthouse/LighthouseProtocolService.ts +1 -0
- package/front_end/panels/lighthouse/LighthouseReportRenderer.ts +9 -6
- package/front_end/panels/lighthouse/LighthouseStatusView.ts +29 -5
- package/front_end/panels/network/NetworkDataGridNode.ts +34 -0
- package/front_end/panels/network/NetworkLogViewColumns.ts +10 -0
- package/front_end/panels/network/RequestPayloadView.ts +6 -3
- package/front_end/panels/network/RequestTimingView.ts +8 -2
- package/front_end/panels/performance_monitor/performanceMonitor.css +6 -4
- package/front_end/panels/recorder/RecorderController.ts +56 -17
- package/front_end/panels/recorder/components/CreateRecordingView.ts +2 -1
- package/front_end/panels/recorder/components/RecordingView.ts +4 -3
- package/front_end/panels/recorder/models/RecordingPlayer.ts +3 -0
- package/front_end/panels/recorder/models/RecordingStorage.ts +15 -20
- package/front_end/panels/security/SecurityPanel.ts +3 -3
- package/front_end/panels/sensors/SensorsView.ts +417 -208
- package/front_end/panels/sources/DebuggerPausedMessage.ts +6 -6
- package/front_end/panels/sources/FilteredUISourceCodeListProvider.ts +2 -3
- package/front_end/panels/sources/NavigatorView.ts +11 -7
- package/front_end/panels/sources/ScopeChainSidebarPane.ts +1 -1
- package/front_end/panels/sources/SourcesPanel.ts +12 -34
- package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +5 -1
- package/front_end/panels/sources/sources-meta.ts +6 -0
- package/front_end/panels/timeline/ThirdPartyTreeView.ts +6 -2
- package/front_end/panels/timeline/TimelineDetailsView.ts +15 -14
- package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +6 -1
- package/front_end/panels/timeline/TimelineFlameChartNetworkDataProvider.ts +9 -4
- package/front_end/panels/timeline/TimelinePanel.ts +7 -9
- package/front_end/panels/timeline/TimelineTreeView.ts +14 -3
- package/front_end/panels/timeline/TimelineUIUtils.ts +5 -175
- package/front_end/panels/timeline/components/IgnoreListSetting.ts +1 -1
- package/front_end/panels/timeline/components/InteractionBreakdown.ts +2 -1
- package/front_end/panels/timeline/components/NetworkRequestTooltip.ts +3 -7
- package/front_end/panels/timeline/components/Sidebar.ts +10 -18
- package/front_end/panels/timeline/components/SidebarInsightsTab.ts +3 -2
- package/front_end/panels/timeline/components/TimelineRangeSummaryView.ts +219 -0
- package/front_end/panels/timeline/components/TimelineSummary.ts +7 -19
- package/front_end/panels/timeline/components/components.ts +2 -0
- package/front_end/panels/timeline/components/insights/BaseInsightComponent.ts +2 -0
- package/front_end/panels/timeline/components/insights/NodeLink.ts +3 -3
- package/front_end/panels/timeline/components/timelineRangeSummaryView.css +32 -0
- package/front_end/panels/timeline/overlays/OverlaysImpl.ts +7 -7
- package/front_end/panels/timeline/timelineDetailsView.css +0 -9
- package/front_end/panels/whats_new/ReleaseNoteText.ts +10 -10
- package/front_end/panels/whats_new/resources/WNDT.md +6 -6
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/puppeteer/README.chromium +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.js +4 -0
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +3 -3
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.js +4 -0
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +2 -2
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +2 -2
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.js +1 -1
- package/front_end/third_party/puppeteer/package/package.json +1 -1
- package/front_end/third_party/puppeteer/package/src/node/ChromeLauncher.ts +8 -0
- package/front_end/third_party/puppeteer/package/src/revisions.ts +2 -2
- package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
- package/front_end/third_party/web-vitals/package/dist/modules/attribution/onINP.js +11 -2
- package/front_end/third_party/web-vitals/package/src/attribution/onINP.ts +11 -2
- package/front_end/third_party/web-vitals/patches/0001-Add-onEachInteraction-to-onINP-options.patch +65 -4
- package/front_end/ui/kit/link/link.css +2 -2
- package/front_end/ui/legacy/Toolbar.ts +25 -3
- package/front_end/ui/legacy/Widget.ts +35 -40
- package/front_end/ui/legacy/components/object_ui/CustomPreviewComponent.ts +7 -2
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +57 -35
- package/front_end/ui/legacy/components/source_frame/PreviewFactory.ts +1 -0
- package/front_end/ui/visual_logging/KnownContextValues.ts +5 -0
- package/package.json +1 -1
- package/front_end/models/issues_manager/descriptions/sharedDictionaryUseErrorNoCorpCrossOriginNoCorsRequest.md +0 -3
- package/front_end/models/issues_manager/descriptions/sharedDictionaryWriteErrorNoCorpCossOriginNoCorsRequest.md +0 -3
- /package/front_end/{panels/console → models/stack_trace}/ErrorStackParser.ts +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: devtools-verification
|
|
3
|
-
description:
|
|
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
4
|
---
|
|
5
5
|
|
|
6
6
|
# Instructions on how to verify your changes
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: devtools-version-control
|
|
3
|
+
description: Use when managing branches, creating CLs, or handling stacked changes in the DevTools Gerrit-based workflow.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# DevTools Version Control
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
Chrome DevTools uses Gerrit for code review. The standard workflow is **one branch per Change List (CL)** and **one commit per branch**. Instead of multiple commits, you amend your single commit locally.
|
|
10
|
+
|
|
11
|
+
## Core Workflow
|
|
12
|
+
|
|
13
|
+
### Creating a New CL
|
|
14
|
+
To start a new task, create a new branch from `main`:
|
|
15
|
+
```bash
|
|
16
|
+
git new-branch <branch-name>
|
|
17
|
+
```
|
|
18
|
+
*Note: This automatically sets the upstream to `origin/main`.*
|
|
19
|
+
|
|
20
|
+
### Making Changes
|
|
21
|
+
1. Make your changes.
|
|
22
|
+
2. Stage them: `git add <files>`.
|
|
23
|
+
3. Create the commit: `git commit -m "Your message"`.
|
|
24
|
+
|
|
25
|
+
### Updating a CL (Amending)
|
|
26
|
+
To update your CL after feedback or more work:
|
|
27
|
+
1. Make more changes.
|
|
28
|
+
2. Stage them: `git add <files>`.
|
|
29
|
+
3. Amend the commit: `git commit --amend`.
|
|
30
|
+
4. Upload: `git cl upload`.
|
|
31
|
+
|
|
32
|
+
### Stacked CLs
|
|
33
|
+
If CL B depends on CL A:
|
|
34
|
+
1. While on branch A, create branch B:
|
|
35
|
+
```bash
|
|
36
|
+
git new-branch --upstream_current <branch-B>
|
|
37
|
+
```
|
|
38
|
+
2. Develop on branch B.
|
|
39
|
+
3. When uploading B, Gerrit will show the dependency on A.
|
|
40
|
+
|
|
41
|
+
### Reparenting
|
|
42
|
+
If you need to change the base of a branch (e.g., move CL B to be based on `main` instead of CL A):
|
|
43
|
+
```bash
|
|
44
|
+
git reparent-branch main
|
|
45
|
+
```
|
|
46
|
+
Or to make it depend on another branch C:
|
|
47
|
+
```bash
|
|
48
|
+
git reparent-branch <branch-C>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Syncing with Upstream
|
|
52
|
+
To update all your branches with the latest changes from `main` and their respective upstreams:
|
|
53
|
+
```bash
|
|
54
|
+
git rebase-update
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Quick Reference
|
|
58
|
+
|
|
59
|
+
| Action | Command |
|
|
60
|
+
| :--- | :--- |
|
|
61
|
+
| Create new CL from main | `git new-branch <name>` |
|
|
62
|
+
| Create stacked CL | `git new-branch --upstream_current <name>` |
|
|
63
|
+
| Update current CL | `git commit --amend` |
|
|
64
|
+
| Upload to Gerrit | `git cl upload` |
|
|
65
|
+
| Change branch parent | `git reparent-branch <new-parent>` |
|
|
66
|
+
| Sync all branches | `git rebase-update` |
|
|
67
|
+
|
|
68
|
+
## Common Mistakes
|
|
69
|
+
- **Multiple commits on one branch:** Gerrit expects one commit per CL. Always `commit --amend`.
|
|
70
|
+
- **Using `git checkout -b`:** Does not set up tracking information correctly for `depot_tools`. Use `git new-branch`.
|
|
71
|
+
- **Manual rebasing of stacked branches:** Can be complex. Use `git rebase-update` or `git reparent-branch` to let `depot_tools` handle the tracking updates.
|
|
@@ -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 =
|
|
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
|
|
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
|
+
}
|
|
@@ -203,9 +203,11 @@ export interface FileEdit {
|
|
|
203
203
|
}
|
|
204
204
|
/* eslint-enable @typescript-eslint/naming-convention */
|
|
205
205
|
|
|
206
|
+
export type Role = 'user'|'model';
|
|
207
|
+
|
|
206
208
|
export interface Content {
|
|
207
209
|
parts?: Part[];
|
|
208
|
-
role:
|
|
210
|
+
role: Role;
|
|
209
211
|
}
|
|
210
212
|
|
|
211
213
|
/* eslint-disable @typescript-eslint/naming-convention */
|
|
@@ -389,11 +389,6 @@ export class InspectorFrontendHostStub implements InspectorFrontendHostAPI {
|
|
|
389
389
|
devToolsVeLogging: {
|
|
390
390
|
enabled: true,
|
|
391
391
|
},
|
|
392
|
-
thirdPartyCookieControls: {
|
|
393
|
-
thirdPartyCookieMetadataEnabled: true,
|
|
394
|
-
thirdPartyCookieHeuristicsEnabled: true,
|
|
395
|
-
managedBlockThirdPartyCookies: 'Unset',
|
|
396
|
-
},
|
|
397
392
|
devToolsFlexibleLayout: {
|
|
398
393
|
verticalDrawerEnabled: true,
|
|
399
394
|
},
|
|
@@ -823,8 +823,6 @@ export enum DevtoolsExperiments {
|
|
|
823
823
|
'full-accessibility-tree' = 42,
|
|
824
824
|
'experimental-cookie-features' = 45,
|
|
825
825
|
'instrumentation-breakpoints' = 61,
|
|
826
|
-
'authored-deployed-grouping' = 63,
|
|
827
|
-
'just-my-code' = 65,
|
|
828
826
|
'use-source-map-scopes' = 76,
|
|
829
827
|
'timeline-debug-mode' = 93,
|
|
830
828
|
'durable-messages' = 110,
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
|
|
5
5
|
import * as AidaClient from './AidaClient.js';
|
|
6
|
+
import * as AidaGcaTranslation from './AidaGcaTranslation.js';
|
|
6
7
|
import * as DispatchHttpRequestClient from './DispatchHttpRequestClient.js';
|
|
7
8
|
import * as GcaTypes from './GcaTypes.js';
|
|
8
9
|
import * as GdpClient from './GdpClient.js';
|
|
@@ -14,6 +15,7 @@ import * as UserMetrics from './UserMetrics.js';
|
|
|
14
15
|
|
|
15
16
|
export {
|
|
16
17
|
AidaClient,
|
|
18
|
+
AidaGcaTranslation,
|
|
17
19
|
DispatchHttpRequestClient,
|
|
18
20
|
GcaTypes,
|
|
19
21
|
GdpClient,
|
|
@@ -16,8 +16,6 @@ export enum ExperimentName {
|
|
|
16
16
|
FULL_ACCESSIBILITY_TREE = 'full-accessibility-tree',
|
|
17
17
|
EXPERIMENTAL_COOKIE_FEATURES = 'experimental-cookie-features',
|
|
18
18
|
INSTRUMENTATION_BREAKPOINTS = 'instrumentation-breakpoints',
|
|
19
|
-
AUTHORED_DEPLOYED_GROUPING = 'authored-deployed-grouping',
|
|
20
|
-
JUST_MY_CODE = 'just-my-code',
|
|
21
19
|
USE_SOURCE_MAP_SCOPES = 'use-source-map-scopes',
|
|
22
20
|
TIMELINE_DEBUG_MODE = 'timeline-debug-mode',
|
|
23
21
|
DURABLE_MESSAGES = 'durable-messages',
|
|
@@ -542,13 +542,6 @@ export interface HostConfigJpegXlImageFormat {
|
|
|
542
542
|
enabled: boolean;
|
|
543
543
|
}
|
|
544
544
|
|
|
545
|
-
export interface HostConfigThirdPartyCookieControls {
|
|
546
|
-
thirdPartyCookieRestrictionEnabled: boolean;
|
|
547
|
-
thirdPartyCookieMetadataEnabled: boolean;
|
|
548
|
-
thirdPartyCookieHeuristicsEnabled: boolean;
|
|
549
|
-
managedBlockThirdPartyCookies: string|boolean;
|
|
550
|
-
}
|
|
551
|
-
|
|
552
545
|
export interface HostConfigAiAssistanceV2 {
|
|
553
546
|
enabled: boolean;
|
|
554
547
|
}
|
|
@@ -651,7 +644,6 @@ export type HostConfig = Platform.TypeScriptUtilities.RecursivePartial<{
|
|
|
651
644
|
devToolsEnableOriginBoundCookies: HostConfigEnableOriginBoundCookies,
|
|
652
645
|
devToolsAnimationStylesInStylesTab: HostConfigAnimationStylesInStylesTab,
|
|
653
646
|
devToolsJpegXlImageFormat: HostConfigJpegXlImageFormat,
|
|
654
|
-
thirdPartyCookieControls: HostConfigThirdPartyCookieControls,
|
|
655
647
|
devToolsAiGeneratedTimelineLabels: AiGeneratedTimelineLabels,
|
|
656
648
|
devToolsAllowPopoverForcing: AllowPopoverForcing,
|
|
657
649
|
devToolsGlobalAiButton: GlobalAiButton,
|