chrome-devtools-frontend 1.0.1667564 → 1.0.1669021
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/devtools-ci/SKILL.md +65 -0
- package/.agents/skills/devtools-setting-migration/SKILL.md +290 -0
- package/.agents/skills/gerrit-cli/SKILL.md +59 -0
- package/.agents/skills/gerrit-cli/references/commands.md +93 -0
- package/.agents/skills/gerrit-cli/references/workflows.md +56 -0
- package/.agents/skills/gerrit-cli/scripts/gerrit_client_wrapper.py +47 -0
- package/.agents/skills/gerrit-cli/scripts/import_upstream.py +230 -0
- package/.agents/skills/ui-eng-vision-widget-promoter/SKILL.md +11 -4
- package/.agents/skills/ui-widgets/SKILL.md +25 -1
- package/docs/contributing/infrastructure.md +7 -1
- package/docs/ui_engineering.md +44 -1
- package/front_end/core/common/Settings.ts +11 -4
- package/front_end/core/host/AidaClient.ts +66 -47
- package/front_end/core/host/GcaClient.ts +4 -6
- package/front_end/core/host/ResourceLoader.ts +4 -2
- package/front_end/core/root/Runtime.ts +5 -5
- package/front_end/core/sdk/CSSModel.test.api.ts +102 -0
- package/front_end/core/sdk/CSSModel.ts +3 -2
- package/front_end/core/sdk/ConsoleModel.ts +3 -2
- package/front_end/core/sdk/DebuggerModel.ts +16 -7
- package/front_end/core/sdk/SDKSettings.ts +38 -0
- package/front_end/core/sdk/sdk-meta.ts +0 -120
- package/front_end/core/sdk/sdk.ts +2 -0
- package/front_end/entrypoints/main/MainImpl.ts +10 -3
- package/front_end/foundation/Universe.ts +7 -0
- package/front_end/generated/InspectorBackendCommands.ts +2 -2
- package/front_end/generated/protocol.ts +11 -3
- package/front_end/models/ai_assistance/AiAgent2.ts +1 -1
- package/front_end/models/ai_assistance/AiUtils.ts +67 -4
- package/front_end/models/ai_assistance/BuiltInAi.ts +11 -6
- package/front_end/models/ai_assistance/ChangeManager.ts +17 -1
- package/front_end/models/ai_assistance/StorageItem.ts +26 -5
- package/front_end/models/ai_code_completion/AiCodeCompletion.ts +2 -19
- package/front_end/models/ai_code_generation/AiCodeGeneration.ts +2 -3
- package/front_end/models/javascript_metadata/NativeFunctions.js +22 -9
- package/front_end/models/source_map_scopes/NamesResolver.ts +23 -17
- package/front_end/models/trace/handlers/RendererHandler.ts +20 -4
- package/front_end/models/trace/types/File.ts +1 -0
- package/front_end/models/workspace/UISourceCode.ts +0 -10
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +61 -182
- package/front_end/panels/ai_assistance/components/ChatInput.ts +25 -8
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +13 -69
- package/front_end/panels/ai_assistance/components/ChatView.ts +14 -8
- package/front_end/panels/ai_assistance/components/chatMessage.css +2 -20
- package/front_end/panels/application/ApplicationPanelSidebar.ts +2 -2
- package/front_end/panels/application/ApplicationPanelTreeElement.ts +41 -3
- package/front_end/panels/application/ServiceWorkerUpdateCycleView.ts +131 -134
- package/front_end/panels/application/ServiceWorkersView.ts +8 -8
- package/front_end/panels/application/application.ts +2 -0
- package/front_end/panels/application/components/AdsView.ts +10 -6
- package/front_end/panels/application/preloading/PreloadingView.ts +53 -45
- package/front_end/panels/application/preloading/components/PreloadingDetailsReportView.ts +111 -119
- package/front_end/panels/application/preloading/components/preloadingDetailsReportView.css +22 -24
- package/front_end/panels/application/serviceWorkerUpdateCycleView.css +105 -102
- package/front_end/panels/common/AiCodeCompletionDisclaimer.ts +107 -96
- package/front_end/panels/common/AiCodeCompletionSummaryToolbar.ts +17 -19
- package/front_end/panels/common/AiCodeCompletionTeaser.ts +6 -6
- package/front_end/panels/common/AiCodeGenerationTeaser.ts +28 -26
- package/front_end/panels/common/common.ts +1 -1
- package/front_end/panels/console/ConsoleInsightTeaser.ts +6 -8
- package/front_end/panels/console/ConsoleView.ts +6 -4
- package/front_end/panels/console/ConsoleViewMessage.ts +1 -1
- package/front_end/panels/console/console-meta.ts +28 -0
- package/front_end/panels/elements/StylesAiCodeCompletionProvider.ts +1 -1
- package/front_end/panels/elements/StylesSidebarPane.ts +3 -2
- package/front_end/panels/emulation/DeviceModeToolbar.ts +2 -2
- package/front_end/panels/emulation/DeviceModeView.ts +63 -104
- package/front_end/panels/emulation/DeviceModeWrapper.ts +18 -4
- package/front_end/panels/explain/components/ConsoleInsight.ts +4 -6
- package/front_end/panels/explain/explain-meta.ts +7 -49
- package/front_end/panels/network/NetworkDataGridNode.ts +1 -1
- package/front_end/panels/network/NetworkLogView.ts +1 -0
- package/front_end/panels/network/OriginalResourceChunkView.ts +340 -0
- package/front_end/panels/network/ResourceChunkView.ts +72 -46
- package/front_end/panels/network/ResourceDirectSocketChunkView.ts +3 -2
- package/front_end/panels/network/ResourceWebSocketFrameView.ts +3 -3
- package/front_end/panels/network/originalResourceChunkView.css +49 -0
- package/front_end/panels/screencast/ScreencastView.ts +401 -260
- package/front_end/panels/screencast/screencastView.css +113 -100
- package/front_end/panels/sensors/LocationsSettingsTab.ts +329 -135
- package/front_end/panels/sensors/locationsSettingsTab.css +78 -4
- package/front_end/panels/settings/AISettingsTab.ts +17 -100
- package/front_end/panels/snippets/ScriptSnippetFileSystem.ts +2 -2
- package/front_end/panels/snippets/SnippetsQuickOpen.ts +4 -4
- package/front_end/panels/sources/AddSourceMapURLDialog.ts +3 -3
- package/front_end/panels/sources/AiCodeCompletionPlugin.ts +4 -3
- package/front_end/panels/sources/BreakpointEditDialog.ts +14 -14
- package/front_end/panels/sources/BreakpointsView.ts +14 -14
- package/front_end/panels/sources/CallStackSidebarPane.ts +6 -6
- package/front_end/panels/sources/CategorizedBreakpointL10n.ts +18 -18
- package/front_end/panels/sources/CoveragePlugin.ts +7 -7
- package/front_end/panels/sources/DebuggerPausedMessage.ts +23 -23
- package/front_end/panels/sources/DebuggerPlugin.ts +31 -31
- package/front_end/panels/sources/FilteredUISourceCodeListProvider.ts +2 -2
- package/front_end/panels/sources/GoToLineQuickOpen.ts +10 -10
- package/front_end/panels/sources/NavigatorView.ts +34 -27
- package/front_end/panels/sources/OutlineQuickOpen.ts +3 -3
- package/front_end/panels/sources/PersistenceActions.ts +9 -9
- package/front_end/panels/sources/ProfilePlugin.ts +1 -1
- package/front_end/panels/sources/ScopeChainSidebarPane.ts +5 -5
- package/front_end/panels/sources/SnippetsPlugin.ts +2 -2
- package/front_end/panels/sources/SourcesNavigator.ts +20 -18
- package/front_end/panels/sources/SourcesPanel.ts +26 -25
- package/front_end/panels/sources/SourcesView.ts +5 -6
- package/front_end/panels/sources/TabbedEditorContainer.ts +3 -3
- package/front_end/panels/sources/ThreadsSidebarPane.ts +1 -1
- package/front_end/panels/sources/UISourceCodeFrame.ts +0 -2
- package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +7 -7
- package/front_end/panels/sources/components/HeadersView.ts +2 -2
- package/front_end/panels/sources/sources-meta.ts +164 -71
- package/front_end/panels/sources/sources.ts +0 -2
- package/front_end/panels/timeline/TimelineHistoryManager.ts +14 -3
- package/front_end/panels/timeline/TimelineLoader.ts +72 -42
- package/front_end/panels/timeline/TimelinePanel.ts +29 -4
- package/front_end/panels/timeline/timelineHistoryManager.css +4 -0
- 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/es5-iife/puppeteer-core-browser.d.ts +187 -1
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +91 -38
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.d.ts +145 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.js +0 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/BrowserContext.d.ts +0 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/BrowserContext.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/BrowserContext.js +0 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/BrowserContext.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Dialog.d.ts +3 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Dialog.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Dialog.js +8 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Dialog.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/JSHandle.d.ts +0 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/JSHandle.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/JSHandle.js +0 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/JSHandle.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.d.ts +1 -3
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.js +0 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Realm.d.ts +0 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Realm.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Realm.js +0 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Realm.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/BidiOverCdp.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/BidiOverCdp.js +2 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/BidiOverCdp.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Browser.d.ts +5 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Browser.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Browser.js +12 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Browser.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPResponse.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPResponse.js +4 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPResponse.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.d.ts +5 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.js +49 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/EventEmitter.d.ts +0 -6
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/EventEmitter.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/EventEmitter.js +0 -6
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/EventEmitter.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/generated/injected.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/generated/injected.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/generated/injected.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/generated/injected.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/injected/util.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/injected/util.js +3 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/injected/util.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ScreenRecorder.d.ts +0 -3
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ScreenRecorder.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ScreenRecorder.js +0 -3
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ScreenRecorder.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.d.ts +3 -3
- package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.js +3 -3
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/disposable.d.ts +2 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/disposable.js +2 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/types.d.ts +187 -1
- package/front_end/third_party/puppeteer/package/package.json +5 -5
- package/front_end/third_party/puppeteer/package/src/api/Browser.ts +155 -2
- package/front_end/third_party/puppeteer/package/src/api/BrowserContext.ts +0 -2
- package/front_end/third_party/puppeteer/package/src/api/Dialog.ts +10 -2
- package/front_end/third_party/puppeteer/package/src/api/JSHandle.ts +0 -2
- package/front_end/third_party/puppeteer/package/src/api/Page.ts +1 -3
- package/front_end/third_party/puppeteer/package/src/api/Realm.ts +0 -1
- package/front_end/third_party/puppeteer/package/src/bidi/BidiOverCdp.ts +4 -2
- package/front_end/third_party/puppeteer/package/src/bidi/Browser.ts +17 -0
- package/front_end/third_party/puppeteer/package/src/bidi/HTTPResponse.ts +5 -4
- package/front_end/third_party/puppeteer/package/src/cdp/Browser.ts +66 -0
- package/front_end/third_party/puppeteer/package/src/common/EventEmitter.ts +0 -6
- package/front_end/third_party/puppeteer/package/src/generated/injected.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/injected/util.ts +4 -1
- package/front_end/third_party/puppeteer/package/src/node/ScreenRecorder.ts +0 -3
- package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
- package/front_end/third_party/puppeteer/package/src/util/disposable.ts +2 -2
- package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
- package/front_end/ui/components/text_editor/AiCodeCompletionProvider.ts +9 -7
- package/front_end/ui/components/text_editor/AiCodeGenerationProvider.ts +7 -8
- package/front_end/ui/legacy/Dialog.ts +103 -4
- package/front_end/ui/legacy/InspectorView.ts +1 -5
- package/front_end/ui/legacy/PopoverHelper.ts +5 -5
- package/front_end/ui/legacy/TabbedPane.ts +7 -2
- package/front_end/ui/legacy/components/cookie_table/CookiesTable.ts +40 -24
- package/front_end/ui/legacy/components/data_grid/DataGrid.ts +1 -0
- package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +8 -4
- package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +14 -7
- package/front_end/ui/legacy/components/quick_open/CommandMenu.ts +11 -1
- package/front_end/ui/visual_logging/KnownContextValues.ts +3 -0
- package/package.json +1 -1
- package/front_end/panels/sources/AiWarningInfobarPlugin.ts +0 -78
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# Copyright 2026 The Chromium Authors
|
|
3
|
+
# Use of this source code is governed by a BSD-style license that can be
|
|
4
|
+
# found in the LICENSE file.
|
|
5
|
+
"""Imports the Gerrit CLI skill from upstream and applies DevTools revisions.
|
|
6
|
+
|
|
7
|
+
No external checkouts (like chromium/src) are required. The script downloads
|
|
8
|
+
the skill directly from the public Git repository.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import io
|
|
12
|
+
import re
|
|
13
|
+
import sys
|
|
14
|
+
import tarfile
|
|
15
|
+
import urllib.request
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
18
|
+
UPSTREAM_URL = "https://chromium.googlesource.com/chromium/agents/+archive/refs/heads/main/skills/gerrit-cli.tar.gz"
|
|
19
|
+
|
|
20
|
+
DEVTOOLS_WRAPPER_LOGIC = """ # DevTools specific defaults
|
|
21
|
+
default_args = [
|
|
22
|
+
'--host', 'https://chromium-review.googlesource.com',
|
|
23
|
+
'--project', 'devtools/devtools-frontend',
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
# gerrit_client.py expects: <command> [options] [args]
|
|
27
|
+
# We need to extract the command from sys.argv and put it first.
|
|
28
|
+
user_args = sys.argv[1:]
|
|
29
|
+
command = []
|
|
30
|
+
other_args = []
|
|
31
|
+
for i, arg in enumerate(user_args):
|
|
32
|
+
if not arg.startswith('-'):
|
|
33
|
+
command = [arg]
|
|
34
|
+
other_args = user_args[:i] + user_args[i + 1:]
|
|
35
|
+
break
|
|
36
|
+
else:
|
|
37
|
+
other_args = user_args
|
|
38
|
+
|
|
39
|
+
full_args = command + default_args + other_args
|
|
40
|
+
|
|
41
|
+
rc = subprocess.call(['vpython3', client] + full_args)"""
|
|
42
|
+
|
|
43
|
+
CAUTION_TEXT = """> [!CAUTION]
|
|
44
|
+
> **NEVER** use this to add patchset comments to an existing comment thread that
|
|
45
|
+
> contains human reviewers in it. Using an agent to reply to a human is a
|
|
46
|
+
> violation of Chromium's code of conduct.
|
|
47
|
+
>
|
|
48
|
+
> If the user requests this or you encounter this scenario as part of your work,
|
|
49
|
+
> inform the user about which comment threads cannot be updated but otherwise
|
|
50
|
+
> continue work.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def fetch_upstream_skill(target_dir: Path):
|
|
55
|
+
print(f"Downloading upstream skill from {UPSTREAM_URL}...")
|
|
56
|
+
try:
|
|
57
|
+
req = urllib.request.Request(UPSTREAM_URL,
|
|
58
|
+
headers={'User-Agent': 'Mozilla/5.0'})
|
|
59
|
+
with urllib.request.urlopen(req) as response:
|
|
60
|
+
tar_data = response.read()
|
|
61
|
+
except Exception as e:
|
|
62
|
+
print(f"Failed to download upstream skill: {e}")
|
|
63
|
+
sys.exit(1)
|
|
64
|
+
|
|
65
|
+
print(f"Extracting to {target_dir}...")
|
|
66
|
+
target_dir.mkdir(parents=True, exist_ok=True)
|
|
67
|
+
with tarfile.open(fileobj=io.BytesIO(tar_data), mode='r:gz') as tar:
|
|
68
|
+
tar.extractall(path=target_dir)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def apply_devtools_revisions(target_dir: Path):
|
|
72
|
+
print("Applying DevTools-specific adaptations...")
|
|
73
|
+
|
|
74
|
+
# 1. Update gerrit_client_wrapper.py
|
|
75
|
+
wrapper_path = target_dir / "scripts" / "gerrit_client_wrapper.py"
|
|
76
|
+
if wrapper_path.exists():
|
|
77
|
+
code = wrapper_path.read_text()
|
|
78
|
+
# Remove ". All rights reserved." from license header to satisfy DevTools presubmit
|
|
79
|
+
code = code.replace(". All rights reserved.", "")
|
|
80
|
+
target_line = " rc = subprocess.call(['vpython3', client] + sys.argv[1:])"
|
|
81
|
+
if target_line in code:
|
|
82
|
+
code = code.replace(target_line, DEVTOOLS_WRAPPER_LOGIC)
|
|
83
|
+
else:
|
|
84
|
+
# Fallback if upstream changed to python3
|
|
85
|
+
fallback_line = " rc = subprocess.call(['python3', client] + sys.argv[1:])"
|
|
86
|
+
code = code.replace(fallback_line, DEVTOOLS_WRAPPER_LOGIC)
|
|
87
|
+
wrapper_path.write_text(code)
|
|
88
|
+
print(" - Adapted gerrit_client_wrapper.py")
|
|
89
|
+
|
|
90
|
+
# 2. Update SKILL.md
|
|
91
|
+
skill_md_path = target_dir / "SKILL.md"
|
|
92
|
+
if skill_md_path.exists():
|
|
93
|
+
content = skill_md_path.read_text()
|
|
94
|
+
|
|
95
|
+
# Re-route wrapper script path & change python3 to vpython3
|
|
96
|
+
content = content.replace(
|
|
97
|
+
"python3 agents/shared/skills/gerrit-cli/scripts/gerrit_client_wrapper.py",
|
|
98
|
+
"vpython3 .agents/skills/gerrit-cli/scripts/gerrit_client_wrapper.py"
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
# Add vpython3 environment warning under Prerequisites
|
|
102
|
+
if "- **Environment**:" not in content:
|
|
103
|
+
prereq_note = "- **Environment**: Always execute the wrapper script using **`vpython3`** instead of `python3` to ensure all internal dependencies are satisfied.\n"
|
|
104
|
+
content = content.replace("## Prerequisites\n",
|
|
105
|
+
f"## Prerequisites\n\n{prereq_note}")
|
|
106
|
+
|
|
107
|
+
# Replace Gotchas section with DevTools defaults info
|
|
108
|
+
global_flags_section = """## Global Flags
|
|
109
|
+
|
|
110
|
+
The wrapper script includes DevTools-specific defaults for `--host` and
|
|
111
|
+
`--project`. You do not need to provide them unless you are targeting a
|
|
112
|
+
different host or project.
|
|
113
|
+
|
|
114
|
+
- **Default Host**: `https://chromium-review.googlesource.com`
|
|
115
|
+
- **Default Project**: `devtools/devtools-frontend`
|
|
116
|
+
- **JSON Output**: Always use the `--json_file=<path>` flag when querying
|
|
117
|
+
changes or fetching metadata to obtain structured, machine-readable output.
|
|
118
|
+
"""
|
|
119
|
+
gotchas_pattern = r"## Gotchas & Environment Constraints\n\n(?:[^\n]+\n)+"
|
|
120
|
+
content = re.sub(gotchas_pattern, global_flags_section, content)
|
|
121
|
+
|
|
122
|
+
# Add attribution note at the bottom
|
|
123
|
+
attribution = """
|
|
124
|
+
> [!NOTE]
|
|
125
|
+
> This skill was adapted from the [Chromium Gerrit CLI skill](https://chromium.googlesource.com/chromium/agents/+/main/skills/gerrit-cli/)
|
|
126
|
+
> (automatically rolled in from upstream).
|
|
127
|
+
"""
|
|
128
|
+
if "> [!NOTE]" not in content:
|
|
129
|
+
content += "\n" + attribution
|
|
130
|
+
|
|
131
|
+
skill_md_path.write_text(content)
|
|
132
|
+
print(" - Adapted SKILL.md")
|
|
133
|
+
|
|
134
|
+
# 3. Update references/commands.md and references/workflows.md
|
|
135
|
+
for filename in ["commands.md", "workflows.md"]:
|
|
136
|
+
ref_path = target_dir / "references" / filename
|
|
137
|
+
if ref_path.exists():
|
|
138
|
+
c = ref_path.read_text()
|
|
139
|
+
|
|
140
|
+
# Path & executable transformations
|
|
141
|
+
c = c.replace("python3 agents/shared/skills/gerrit-cli/",
|
|
142
|
+
"vpython3 .agents/skills/gerrit-cli/")
|
|
143
|
+
|
|
144
|
+
# Remove redundant host/project flags since our wrapper defaults them
|
|
145
|
+
# This matches the flag and any trailing backslash & newline to keep shell syntax valid
|
|
146
|
+
c = re.sub(r'^[ \t]+--(host|project)[ \t]+\S+[ \t]*(?:\\)?\n',
|
|
147
|
+
'',
|
|
148
|
+
c,
|
|
149
|
+
flags=re.M)
|
|
150
|
+
|
|
151
|
+
# Re-route positional arguments to flags for various commands.
|
|
152
|
+
# TODO(b/40292850): Simplify/remove these once CL lands upstream:
|
|
153
|
+
# https://chromium-review.googlesource.com/c/chromium/agents/+/8146436
|
|
154
|
+
|
|
155
|
+
# content
|
|
156
|
+
c = c.replace(
|
|
157
|
+
"<change_id> <revision> <file_path>",
|
|
158
|
+
"--change <change_id> --revision <revision> --path <file_path>"
|
|
159
|
+
)
|
|
160
|
+
c = c.replace(
|
|
161
|
+
"<change_id> current <file_path>",
|
|
162
|
+
"--change <change_id> --revision current --path <file_path>")
|
|
163
|
+
|
|
164
|
+
# changes (query flag is required)
|
|
165
|
+
c = c.replace('changes \\\n "owner:self status:open"',
|
|
166
|
+
'changes \\\n --query "owner:self status:open"')
|
|
167
|
+
c = c.replace('changes \\\n "change:<id>"',
|
|
168
|
+
'changes \\\n --query "change:<id>"')
|
|
169
|
+
|
|
170
|
+
# relatedchanges
|
|
171
|
+
c = c.replace(
|
|
172
|
+
"relatedchanges \\\n <change_id> <revision>",
|
|
173
|
+
"relatedchanges \\\n --change <change_id> --revision <revision>"
|
|
174
|
+
)
|
|
175
|
+
c = c.replace(
|
|
176
|
+
"relatedchanges \\\n <change_id> current",
|
|
177
|
+
"relatedchanges \\\n --change <change_id> --revision current"
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
# addpatchsetcomment
|
|
181
|
+
c = c.replace(
|
|
182
|
+
'addpatchsetcomment \\\n --message "Review findings: <message>" \\\n <change_id> <revision>',
|
|
183
|
+
'addpatchsetcomment \\\n --change <change_id> --revision <revision> \\\n --message "Review findings: <message>"'
|
|
184
|
+
)
|
|
185
|
+
c = c.replace(
|
|
186
|
+
'addpatchsetcomment \\\n --message "Review findings: ..." \\\n <change_id> current',
|
|
187
|
+
'addpatchsetcomment \\\n --change <change_id> --revision current \\\n --message "Review findings: ..."'
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
# setlabel
|
|
191
|
+
c = c.replace(
|
|
192
|
+
'setlabel \\\n --label "Code-Review" \\\n --value 1 \\\n <change_id>',
|
|
193
|
+
'setlabel \\\n --change <change_id> \\\n --label Code-Review 1'
|
|
194
|
+
)
|
|
195
|
+
c = c.replace(
|
|
196
|
+
'setlabel \\\n --label "Code-Review" \\\n --value 1 \\\n <change_id>',
|
|
197
|
+
'setlabel \\\n --change <change_id> \\\n --label Code-Review 1'
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
# submitchange
|
|
201
|
+
c = c.replace("submitchange \\\n <change_id>",
|
|
202
|
+
"submitchange \\\n --change <change_id>")
|
|
203
|
+
c = c.replace("submitchange \\\n <change_id>",
|
|
204
|
+
"submitchange \\\n --change <change_id>")
|
|
205
|
+
|
|
206
|
+
# abandon
|
|
207
|
+
c = c.replace(
|
|
208
|
+
'abandon \\\n --message "<reason>" \\\n <change_id>',
|
|
209
|
+
'abandon \\\n --change <change_id> \\\n --message "<reason>"'
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
# restore
|
|
213
|
+
c = c.replace(
|
|
214
|
+
'restore \\\n --message "<reason>" \\\n <change_id>',
|
|
215
|
+
'restore \\\n --change <change_id> \\\n --message "<reason>"'
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
ref_path.write_text(c)
|
|
219
|
+
print(f" - Adapted references/{filename}")
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def main():
|
|
223
|
+
skill_dir = Path(__file__).parent.parent.resolve()
|
|
224
|
+
fetch_upstream_skill(skill_dir)
|
|
225
|
+
apply_devtools_revisions(skill_dir)
|
|
226
|
+
print("Upstream sync completed successfully!")
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
if __name__ == "__main__":
|
|
230
|
+
main()
|
|
@@ -36,13 +36,21 @@ clean `UI.Widget` classes that use native update rendering delegates.
|
|
|
36
36
|
};
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
* Make the view injectable in the constructor for testability (as per `docs/ui_engineering.md`)
|
|
39
|
+
* Make the view injectable in the constructor for testability (as per `docs/ui_engineering.md`), and use static `INJECT` if requesting dependencies from `Universe`:
|
|
40
40
|
|
|
41
41
|
```typescript
|
|
42
42
|
class MyWidget extends UI.Widget.VBox {
|
|
43
|
+
static override readonly INJECT = [SDK.TargetManager.TargetManager] as const;
|
|
44
|
+
|
|
45
|
+
#targetManager: SDK.TargetManager.TargetManager;
|
|
43
46
|
#view: View;
|
|
44
|
-
constructor(
|
|
45
|
-
|
|
47
|
+
constructor(
|
|
48
|
+
element?: HTMLElement,
|
|
49
|
+
[targetManager]: UI.Widget.WidgetDependencies<typeof MyWidget> = [],
|
|
50
|
+
view: View = DEFAULT_VIEW,
|
|
51
|
+
) {
|
|
52
|
+
super(element);
|
|
53
|
+
this.#targetManager = targetManager;
|
|
46
54
|
this.#view = view;
|
|
47
55
|
}
|
|
48
56
|
```
|
|
@@ -84,4 +92,3 @@ clean `UI.Widget` classes that use native update rendering delegates.
|
|
|
84
92
|
2. ❓ **Inheritance**: Does the class now cleanly inherit from `UI.Widget` or its variants?
|
|
85
93
|
3. ❓ **Injectability**: Is the view injectable in the constructor?
|
|
86
94
|
4. ❓ **Build**: Does the code compile and do tests pass?
|
|
87
|
-
|
|
@@ -19,6 +19,7 @@ Adhere strictly to the Model-View-Presenter (MVP) architecture.
|
|
|
19
19
|
* MUST extend a base `UI.Widget` class (e.g., `UI.Widget.Widget`). Note that `UI.Widget.Widget` is not an `HTMLElement` and must be appended via `.show()` or `UI.Widget.widget`
|
|
20
20
|
* Constructor MUST assign the injected view function to a private `#view` field.
|
|
21
21
|
* Constructor MUST call `super()`. If taking `element?: HTMLElement`, pass it to `super(element)`. `super(true)` is forbidden.
|
|
22
|
+
* Dependencies from `Universe` SHOULD be requested via static `INJECT`: `static override readonly INJECT = [...] as const;` and received as constructor parameter #2 (`[dep1, dep2]: UI.Widget.WidgetDependencies<typeof MyWidget>`).
|
|
22
23
|
* Styling MUST be handled within the View. `this.registerCSSFiles()` is forbidden.
|
|
23
24
|
* Initial render MUST be triggered in `override wasShown(): void` by calling `this.requestUpdate()`.
|
|
24
25
|
* MUST hold all UI state as private class fields (e.g., `#counter`).
|
|
@@ -109,7 +110,30 @@ render(html`
|
|
|
109
110
|
* **Child Widgets:** Use `UI.Widget.widgetRef` to obtain the class instance of a child widget if you need to call methods on it directly (though declarative data flow is preferred).
|
|
110
111
|
|
|
111
112
|
### Dependencies
|
|
112
|
-
|
|
113
|
+
|
|
114
|
+
* **View Dependencies:** The `DEFAULT_VIEW` is typically a module-level function. Ensure all dependencies (enums, constants, other components) are imported at the top of the file so they are available in the function scope.
|
|
115
|
+
* **Presenter (`Universe`) Dependencies:** To access dependencies managed by `Universe` (e.g. `SDK.TargetManager.TargetManager`, `Common.Settings.Settings`), declare a static `INJECT` array on the `Widget` subclass:
|
|
116
|
+
```ts
|
|
117
|
+
export class MyWidget extends UI.Widget.Widget {
|
|
118
|
+
static override readonly INJECT = [SDK.TargetManager.TargetManager, Common.Settings.Settings] as const;
|
|
119
|
+
|
|
120
|
+
#targetManager: SDK.TargetManager.TargetManager;
|
|
121
|
+
#settings: Common.Settings.Settings;
|
|
122
|
+
#view: View;
|
|
123
|
+
|
|
124
|
+
constructor(
|
|
125
|
+
element?: HTMLElement,
|
|
126
|
+
[targetManager, settings]: UI.Widget.WidgetDependencies<typeof MyWidget> = [],
|
|
127
|
+
view: View = DEFAULT_VIEW,
|
|
128
|
+
) {
|
|
129
|
+
super(element);
|
|
130
|
+
this.#targetManager = targetManager;
|
|
131
|
+
this.#settings = settings;
|
|
132
|
+
this.#view = view;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
`instantiateWidget` automatically resolves dependencies from `Universe` and passes them as constructor parameter #2. In unit tests using `renderElementIntoDOM`, `TestUniverse` handles injection automatically (override via `setTestUniverseForWidgets`).
|
|
113
137
|
|
|
114
138
|
## Step-by-Step Implementation Example
|
|
115
139
|
|
|
@@ -257,7 +257,13 @@ because they picked up the test as it was being touched.
|
|
|
257
257
|
|
|
258
258
|
You can skip Flake Detection for your tests by adding the `Skip-Flake-Detection`
|
|
259
259
|
CL footer (see example [CL](https://crrev.com/c/6994031)). Make sure you use the
|
|
260
|
-
full path to your test.
|
|
260
|
+
full path to your test. If you need to skip multiple tests, you can repeat the footer:
|
|
261
|
+
```
|
|
262
|
+
Skip-Flake-Detection: test/e2e/foo.test.ts
|
|
263
|
+
Skip-Flake-Detection: test/e2e/bar.test.ts
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
You can also skip Flake Detection for multiple tests using a glob pattern by adding the `Skip-Flake-Detection-Pattern` CL footer. For example: `Skip-Flake-Detection-Pattern: test/e2e/performance/*`.
|
|
261
267
|
|
|
262
268
|
### Common build failures
|
|
263
269
|
|
package/docs/ui_engineering.md
CHANGED
|
@@ -38,13 +38,42 @@ Note that `VBox` and `HBox` inherit directly from `Widget`. They fully support v
|
|
|
38
38
|
|
|
39
39
|
To test the `DEFAULT_VIEW` function itself, we should use screenshot and e2e tests.
|
|
40
40
|
|
|
41
|
+
### Dependency Injection via `INJECT`
|
|
42
|
+
|
|
43
|
+
Subclasses of `UI.Widget.Widget` can declare dependencies from `Universe` to be automatically injected when instantiated (e.g. via `<devtools-widget>` or `UI.Widget.widget()`).
|
|
44
|
+
|
|
45
|
+
To opt into dependency injection, define a static `INJECT` array containing dependency constructors:
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
class MyWidget extends UI.Widget.Widget {
|
|
49
|
+
static override readonly INJECT = [SDK.TargetManager.TargetManager, Common.Settings.Settings] as const;
|
|
50
|
+
|
|
51
|
+
#targetManager: SDK.TargetManager.TargetManager;
|
|
52
|
+
#settings: Common.Settings.Settings;
|
|
53
|
+
|
|
54
|
+
constructor(
|
|
55
|
+
element?: HTMLElement,
|
|
56
|
+
[targetManager, settings]: UI.Widget.WidgetDependencies<typeof MyWidget> = [],
|
|
57
|
+
view: View = DEFAULT_VIEW,
|
|
58
|
+
) {
|
|
59
|
+
super(element);
|
|
60
|
+
this.#targetManager = targetManager;
|
|
61
|
+
this.#settings = settings;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
When `instantiateWidget` creates a widget with a non-empty `INJECT` array, it automatically resolves each requested constructor from the active `Universe` and passes the resolved instances array as parameter #2 to the constructor.
|
|
67
|
+
|
|
68
|
+
Use `UI.Widget.WidgetDependencies<typeof MyWidget>` to type the injected dependencies parameter.
|
|
69
|
+
|
|
41
70
|
## Declarative and orchestrated DOM updates
|
|
42
71
|
|
|
43
72
|
We should no longer use imperative API to update DOM. Instead we rely on orchestrated rendering of lit-html templates. The view function described above should be a call to lit-html `render`. The view function should be called from `UI.Widget`’s `performUpdate` method, which by default is scheduled using `requestAnimationFrame`.
|
|
44
73
|
|
|
45
74
|
To embed another presenter (`UI.Widget`) in the lit-html template, use `widget(<class>, {foo: 1, bar: 2})`
|
|
46
75
|
|
|
47
|
-
This will instantiate a `Widget` class with the web component as its `element` and, optionally, will set the properties provided in the second parameter. The widget won’t be re-instantiated on the subsequent template renders, but the properties would be updated. For this to work, the widget needs to accept `HTMLElement` as
|
|
76
|
+
This will instantiate a `Widget` class with the web component as its `element` and, optionally, will set the properties provided in the second parameter. The widget won’t be re-instantiated on the subsequent template renders, but the properties would be updated. For this to work, the widget needs to accept `HTMLElement` as its first constructor parameter, optional injected dependencies as parameter #2 (if `INJECT` is declared), and properties need to be public members or setters.
|
|
48
77
|
|
|
49
78
|
For backwards compatibility, the first argument to `widget` can also be a factory function: `widget(element => new MyWidget(foo, bar, element))`. Similar to the class constructor version, `element` is the actual `<devtools-widget>` so the following two invocations of `widget` are equivalent: `widget(MyWidget)` and `widget(element => new MyWidget(element))`.
|
|
50
79
|
|
|
@@ -218,6 +247,20 @@ const presenter = new Presenter();
|
|
|
218
247
|
presenter.doSomething();
|
|
219
248
|
```
|
|
220
249
|
|
|
250
|
+
#### Testing widgets with `INJECT` dependencies
|
|
251
|
+
|
|
252
|
+
When rendering widgets into DOM in unit tests (e.g. via `renderElementIntoDOM`), DOM test helpers automatically supply a default `TestUniverse` for resolving `INJECT` dependencies.
|
|
253
|
+
|
|
254
|
+
If a test requires a custom `TestUniverse` instance, pass it via `setTestUniverseForWidgets`:
|
|
255
|
+
|
|
256
|
+
```ts
|
|
257
|
+
import {setTestUniverseForWidgets} from '../../testing/DOMHelpers.js';
|
|
258
|
+
import {TestUniverse} from '../../testing/TestUniverse.js';
|
|
259
|
+
|
|
260
|
+
const customUniverse = new TestUniverse();
|
|
261
|
+
setTestUniverseForWidgets(customUniverse);
|
|
262
|
+
```
|
|
263
|
+
|
|
221
264
|
# Migrating Widgets and other "legacy" components
|
|
222
265
|
|
|
223
266
|
This section provides a series of examples for migrating from imperative DOM manipulation to a declarative approach using lit-html templates.
|
|
@@ -362,6 +362,8 @@ export class Settings {
|
|
|
362
362
|
this.createRegExpSetting(name, evaluatedDefaultValue, undefined, storageType) :
|
|
363
363
|
this.createSetting(name, evaluatedDefaultValue, storageType);
|
|
364
364
|
|
|
365
|
+
setting.setSettingType(type);
|
|
366
|
+
|
|
365
367
|
this.registerModuleSetting(setting);
|
|
366
368
|
return setting as Setting<T>;
|
|
367
369
|
}
|
|
@@ -511,6 +513,7 @@ export class Deprecation {
|
|
|
511
513
|
|
|
512
514
|
export class Setting<V> {
|
|
513
515
|
#registration: SettingRegistration|null = null;
|
|
516
|
+
#type: SettingType|null = null;
|
|
514
517
|
#requiresUserAction?: boolean;
|
|
515
518
|
#value?: V;
|
|
516
519
|
// TODO(crbug.com/1172300) Type cannot be inferred without changes to consumers. See above.
|
|
@@ -679,8 +682,15 @@ export class Setting<V> {
|
|
|
679
682
|
this.eventSupport.dispatchEventToListeners(this.name, value);
|
|
680
683
|
}
|
|
681
684
|
|
|
685
|
+
setSettingType(type: SettingType): void {
|
|
686
|
+
this.#type = type;
|
|
687
|
+
}
|
|
688
|
+
|
|
682
689
|
setRegistration(registration: SettingRegistration): void {
|
|
683
690
|
this.#registration = registration;
|
|
691
|
+
if (registration.settingType) {
|
|
692
|
+
this.#type = registration.settingType;
|
|
693
|
+
}
|
|
684
694
|
const {deprecationNotice} = registration;
|
|
685
695
|
if (deprecationNotice?.disabled) {
|
|
686
696
|
const experiment = deprecationNotice.experiment ?
|
|
@@ -694,10 +704,7 @@ export class Setting<V> {
|
|
|
694
704
|
}
|
|
695
705
|
|
|
696
706
|
type(): SettingType|null {
|
|
697
|
-
|
|
698
|
-
return this.#registration.settingType;
|
|
699
|
-
}
|
|
700
|
-
return null;
|
|
707
|
+
return this.#type ?? this.#registration?.settingType ?? null;
|
|
701
708
|
}
|
|
702
709
|
|
|
703
710
|
options(): SimpleSettingOption[] {
|
|
@@ -33,7 +33,7 @@ import * as GcaClient from './GcaClient.js';
|
|
|
33
33
|
import type {GenerateContentResponse} from './GcaTypes.js';
|
|
34
34
|
import {InspectorFrontendHostInstance} from './InspectorFrontendHost.js';
|
|
35
35
|
import type {AidaClientResult, AidaCodeCompleteResult, SyncInformation} from './InspectorFrontendHostAPI.js';
|
|
36
|
-
import {bindOutputStream} from './ResourceLoader.js';
|
|
36
|
+
import {bindOutputStream, discardOutputStream} from './ResourceLoader.js';
|
|
37
37
|
|
|
38
38
|
export * from './AidaClientTypes.js';
|
|
39
39
|
|
|
@@ -159,6 +159,10 @@ export class AidaClient {
|
|
|
159
159
|
throw new Error('dispatchHttpRequest is not available');
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
+
if (options?.signal?.aborted) {
|
|
163
|
+
throw new AidaAbortError();
|
|
164
|
+
}
|
|
165
|
+
|
|
162
166
|
// Disable logging for now.
|
|
163
167
|
// For context, see b/454563259#comment35.
|
|
164
168
|
// We should be able to remove this ~end of April.
|
|
@@ -166,51 +170,67 @@ export class AidaClient {
|
|
|
166
170
|
request.metadata.disable_user_content_logging = true;
|
|
167
171
|
}
|
|
168
172
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
|
|
173
|
+
let abortListener: (() => void)|undefined;
|
|
174
|
+
let streamId: number|undefined;
|
|
175
|
+
try {
|
|
176
|
+
const stream = (() => {
|
|
177
|
+
let {promise, resolve, reject} = Promise.withResolvers<string|null>();
|
|
178
|
+
// Prevent unhandled promise rejections if stream.fail() is called after
|
|
179
|
+
// doConversation has already exited early (e.g. on recitation block or abort).
|
|
180
|
+
// Active readers calling await stream.read() will still receive the rejection.
|
|
181
|
+
promise.catch(() => {});
|
|
182
|
+
abortListener = () => {
|
|
183
|
+
reject(new AidaAbortError());
|
|
184
|
+
};
|
|
185
|
+
options?.signal?.addEventListener('abort', abortListener, {once: true});
|
|
186
|
+
return {
|
|
187
|
+
write: async(data: string): Promise<void> => {
|
|
188
|
+
resolve(data);
|
|
189
|
+
({promise, resolve, reject} = Promise.withResolvers<string|null>());
|
|
190
|
+
promise.catch(() => {});
|
|
191
|
+
},
|
|
192
|
+
close: async(): Promise<void> => {
|
|
193
|
+
resolve(null);
|
|
194
|
+
},
|
|
195
|
+
read: (): Promise<string|null> => {
|
|
196
|
+
return promise;
|
|
197
|
+
},
|
|
198
|
+
fail: (e: Error) => reject(e),
|
|
199
|
+
};
|
|
200
|
+
})();
|
|
201
|
+
streamId = bindOutputStream(stream);
|
|
202
|
+
|
|
203
|
+
let response;
|
|
204
|
+
if (this.#gcaClient.enabled()) {
|
|
205
|
+
// Inline and remove the else clause after migration
|
|
206
|
+
response = this.#gcaClient.conversationRequest(request, streamId, options);
|
|
207
|
+
} else {
|
|
208
|
+
response = DispatchHttpRequestClient.makeHttpRequest({
|
|
209
|
+
service: SERVICE_NAME,
|
|
210
|
+
path: '/v1/aida:doConversation',
|
|
211
|
+
method: 'POST',
|
|
212
|
+
body: JSON.stringify(request),
|
|
213
|
+
streamId,
|
|
184
214
|
},
|
|
185
|
-
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
let response;
|
|
191
|
-
if (this.#gcaClient.enabled()) {
|
|
192
|
-
// Inline and remove the else clause after migration
|
|
193
|
-
response = this.#gcaClient.conversationRequest(request, streamId, options);
|
|
194
|
-
} else {
|
|
195
|
-
response = DispatchHttpRequestClient.makeHttpRequest(
|
|
196
|
-
{
|
|
197
|
-
service: SERVICE_NAME,
|
|
198
|
-
path: '/v1/aida:doConversation',
|
|
199
|
-
method: 'POST',
|
|
200
|
-
body: JSON.stringify(request),
|
|
201
|
-
streamId,
|
|
215
|
+
options);
|
|
216
|
+
}
|
|
217
|
+
response.then(
|
|
218
|
+
() => {
|
|
219
|
+
void stream.close();
|
|
202
220
|
},
|
|
203
|
-
|
|
221
|
+
err => {
|
|
222
|
+
debugLog('doConversation failed with error:', JSON.stringify(err));
|
|
223
|
+
stream.fail(mapError(err));
|
|
224
|
+
});
|
|
225
|
+
yield* this.#handleResponseStream(stream);
|
|
226
|
+
} finally {
|
|
227
|
+
if (options?.signal && abortListener) {
|
|
228
|
+
options.signal.removeEventListener('abort', abortListener);
|
|
229
|
+
}
|
|
230
|
+
if (streamId !== undefined) {
|
|
231
|
+
discardOutputStream(streamId);
|
|
232
|
+
}
|
|
204
233
|
}
|
|
205
|
-
response.then(
|
|
206
|
-
() => {
|
|
207
|
-
void stream.close();
|
|
208
|
-
},
|
|
209
|
-
err => {
|
|
210
|
-
debugLog('doConversation failed with error:', JSON.stringify(err));
|
|
211
|
-
stream.fail(mapError(err));
|
|
212
|
-
});
|
|
213
|
-
await (yield* this.#handleResponseStream(stream));
|
|
214
234
|
}
|
|
215
235
|
|
|
216
236
|
async * #handleResponseStream(stream: AiStream): AsyncGenerator<DoConversationResponse, void, void> {
|
|
@@ -397,8 +417,7 @@ export class AidaClient {
|
|
|
397
417
|
return {generatedSamples, metadata};
|
|
398
418
|
}
|
|
399
419
|
|
|
400
|
-
async generateCode(request: GenerateCodeRequest, options?: {signal?: AbortSignal}):
|
|
401
|
-
Promise<GenerateCodeResponse|null> {
|
|
420
|
+
async generateCode(request: GenerateCodeRequest, options?: {signal?: AbortSignal}): Promise<GenerateCodeResponse> {
|
|
402
421
|
// Disable logging for now.
|
|
403
422
|
// For context, see b/454563259#comment35.
|
|
404
423
|
// We should be able to remove this ~end of April.
|
|
@@ -495,8 +514,8 @@ export class HostConfigTracker extends Common.ObjectWrapper.ObjectWrapper<EventT
|
|
|
495
514
|
return eventDescriptor;
|
|
496
515
|
}
|
|
497
516
|
|
|
498
|
-
override removeEventListener(eventType: Events,
|
|
499
|
-
|
|
517
|
+
override removeEventListener(eventType: Events,
|
|
518
|
+
listener: Common.EventTarget.EventListener<EventTypes, Events>): void {
|
|
500
519
|
super.removeEventListener(eventType, listener);
|
|
501
520
|
if (!this.hasEventListeners(eventType)) {
|
|
502
521
|
clearTimeout(this.#pollTimer);
|
|
@@ -77,18 +77,16 @@ export class GcaClient {
|
|
|
77
77
|
});
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
async completeCode(request: CompletionRequest): Promise<CompletionResponse
|
|
80
|
+
async completeCode(request: CompletionRequest): Promise<CompletionResponse> {
|
|
81
81
|
const gcaRequest = aidaCompletionRequestToGcaRequest(request);
|
|
82
82
|
const result = await this.#requestContent(gcaRequest);
|
|
83
|
-
|
|
84
|
-
return aidaResult;
|
|
83
|
+
return gcaResponseToAidaCompletionResponse(result);
|
|
85
84
|
}
|
|
86
85
|
|
|
87
|
-
async generateCode(request: GenerateCodeRequest, options?: {signal?: AbortSignal}):
|
|
88
|
-
Promise<GenerateCodeResponse|null> {
|
|
86
|
+
async generateCode(request: GenerateCodeRequest, options?: {signal?: AbortSignal}): Promise<GenerateCodeResponse> {
|
|
89
87
|
const gcaRequest = aidaGenerateCodeRequestToGcaRequest(request);
|
|
90
88
|
const result = await this.#requestContent(gcaRequest, options);
|
|
91
|
-
return
|
|
89
|
+
return gcaResponseToAidaGenerateCodeResponse(result);
|
|
92
90
|
}
|
|
93
91
|
|
|
94
92
|
async #requestContent(request: GenerateContentRequest,
|
|
@@ -80,8 +80,10 @@ export const bindOutputStream = function(stream: Common.StringOutputStream.Outpu
|
|
|
80
80
|
};
|
|
81
81
|
|
|
82
82
|
export const discardOutputStream = function(id: number): void {
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
if (_boundStreams[id]) {
|
|
84
|
+
void _boundStreams[id].close();
|
|
85
|
+
delete _boundStreams[id];
|
|
86
|
+
}
|
|
85
87
|
};
|
|
86
88
|
|
|
87
89
|
export const streamWrite = function(id: number, chunk: string): void {
|
|
@@ -560,10 +560,6 @@ export interface HostConfigJpegXlImageFormat {
|
|
|
560
560
|
enabled: boolean;
|
|
561
561
|
}
|
|
562
562
|
|
|
563
|
-
export interface HostConfigAiAssistanceV2 {
|
|
564
|
-
enabled: boolean;
|
|
565
|
-
}
|
|
566
|
-
|
|
567
563
|
interface AiGeneratedTimelineLabels {
|
|
568
564
|
enabled: boolean;
|
|
569
565
|
}
|
|
@@ -648,6 +644,10 @@ interface DevToolsPlusButton {
|
|
|
648
644
|
enabled: boolean;
|
|
649
645
|
}
|
|
650
646
|
|
|
647
|
+
interface DevToolsInstrumentationBreakpoints {
|
|
648
|
+
enabled: boolean;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
651
|
/**
|
|
652
652
|
* The host configuration that we expect from the DevTools back-end.
|
|
653
653
|
*
|
|
@@ -673,7 +673,6 @@ export type HostConfig = Platform.TypeScriptUtilities.RecursivePartial<{
|
|
|
673
673
|
devToolsAiAssistancePerformanceAgent: HostConfigAiAssistancePerformanceAgent,
|
|
674
674
|
devToolsAiAssistanceAccessibilityAgent: HostConfigAiAssistanceAccessibilityAgent,
|
|
675
675
|
devToolsAiAssistanceStorageAgent: HostConfigAiAssistanceStorageAgent,
|
|
676
|
-
devToolsAiAssistanceV2: HostConfigAiAssistanceV2,
|
|
677
676
|
devToolsAiV2Architecture: DevToolsAiV2Architecture,
|
|
678
677
|
devToolsAiCodeCompletion: HostConfigAiCodeCompletion,
|
|
679
678
|
devToolsAiCodeGeneration: HostConfigAiCodeGeneration,
|
|
@@ -705,6 +704,7 @@ export type HostConfig = Platform.TypeScriptUtilities.RecursivePartial<{
|
|
|
705
704
|
devToolsAdsPanel: DevToolsAdsPanel,
|
|
706
705
|
devToolsUseGcaApi: UseGcaApi,
|
|
707
706
|
devToolsPlusButton: DevToolsPlusButton,
|
|
707
|
+
devToolsInstrumentationBreakpoints: DevToolsInstrumentationBreakpoints,
|
|
708
708
|
extensionsOnChromeUrls: ExtensionsOnChromeUrls,
|
|
709
709
|
}>;
|
|
710
710
|
|