chrome-devtools-frontend 1.0.1654411 → 1.0.1656897
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/ui-eng-vision-local-lit-renderer/SKILL.md +116 -0
- package/.agents/skills/ui-eng-vision-logic-consolidator/SKILL.md +82 -0
- package/.agents/skills/ui-eng-vision-orchestrator/SKILL.md +123 -0
- package/.agents/skills/ui-eng-vision-test-scaffolder/SKILL.md +125 -0
- package/.agents/skills/ui-eng-vision-widget-promoter/SKILL.md +75 -0
- package/AUTHORS +1 -0
- package/config/owner/COMMON_OWNERS +0 -4
- package/docs/playbook.md +1 -1
- package/front_end/Tests.js +1 -0
- package/front_end/core/common/Settings.ts +47 -30
- package/front_end/core/sdk/CPUThrottlingManager.ts +10 -159
- package/front_end/core/sdk/ConsoleModel.ts +13 -11
- package/front_end/core/sdk/DOMDebuggerModel.ts +11 -5
- package/front_end/core/sdk/DOMModel.ts +7 -5
- package/front_end/core/sdk/EventBreakpointsModel.ts +9 -5
- package/front_end/core/sdk/IsolateManager.ts +6 -6
- package/front_end/core/sdk/ResourceTreeModel.ts +5 -3
- package/front_end/core/sdk/SourceMapCache.ts +2 -4
- package/front_end/core/sdk/SourceMapManager.ts +8 -7
- package/front_end/core/sdk/TargetManager.ts +17 -0
- package/front_end/entrypoints/devtools_app/devtools_app.ts +0 -1
- package/front_end/entrypoints/main/MainImpl.ts +12 -36
- package/front_end/entrypoints/main/SimpleApp.ts +0 -13
- package/front_end/entrypoints/main/main-meta.ts +1 -1
- package/front_end/foundation/Universe.ts +110 -3
- package/front_end/generated/InspectorBackendCommands.ts +5 -1
- package/front_end/generated/SupportedCSSProperties.js +2 -6
- package/front_end/generated/protocol-mapping.d.ts +8 -0
- package/front_end/generated/protocol-proxy-api.d.ts +15 -0
- package/front_end/generated/protocol.ts +36 -1
- package/front_end/models/ai_assistance/AiConversation.ts +0 -6
- package/front_end/models/ai_assistance/agents/NetworkAgent.snapshot.txt +1 -1
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +2 -156
- package/front_end/models/ai_assistance/agents/StylingAgent.snapshot.txt +0 -24
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +2 -358
- package/front_end/models/ai_assistance/ai_assistance.ts +0 -6
- package/front_end/models/ai_assistance/contexts/RequestContext.snapshot.txt +0 -1
- package/front_end/models/ai_assistance/data_formatters/NetworkRequestFormatter.ts +0 -2
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +1 -14
- package/front_end/models/autofill_manager/AutofillManager.ts +1 -2
- package/front_end/models/crux-manager/CrUXManager.ts +16 -11
- package/front_end/models/javascript_metadata/NativeFunctions.js +1 -1
- package/front_end/models/persistence/AutomaticFileSystemManager.ts +14 -13
- package/front_end/models/persistence/AutomaticFileSystemWorkspaceBinding.ts +12 -9
- package/front_end/models/persistence/IsolatedFileSystemManager.ts +18 -9
- package/front_end/models/project_settings/ProjectSettingsModel.ts +12 -11
- package/front_end/models/trace/handlers/ScreenshotsHandler.ts +14 -59
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +3 -29
- package/front_end/panels/application/DeviceBoundSessionsView.ts +15 -3
- package/front_end/panels/application/FrameDetailsView.ts +2 -1
- package/front_end/panels/application/ServiceWorkersView.ts +193 -161
- package/front_end/panels/application/serviceWorkersView.css +8 -0
- package/front_end/panels/common/CPUThrottlingOption.ts +142 -0
- package/front_end/panels/common/ThrottlingUtils.ts +9 -4
- package/front_end/panels/common/common.ts +1 -1
- package/front_end/panels/console/ConsoleViewMessage.ts +45 -0
- package/front_end/panels/elements/ElementsPanel.ts +35 -102
- package/front_end/panels/elements/ElementsTreeOutline.ts +0 -4
- package/front_end/panels/elements/elements-meta.ts +3 -2
- package/front_end/panels/emulation/DeviceModeToolbar.ts +46 -45
- package/front_end/panels/mobile_throttling/CalibrationController.ts +6 -5
- package/front_end/panels/mobile_throttling/MobileThrottlingSelector.ts +1 -1
- package/front_end/panels/mobile_throttling/ThrottlingManager.ts +40 -13
- package/front_end/panels/mobile_throttling/ThrottlingPresets.ts +13 -17
- package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +15 -13
- package/front_end/panels/network/NetworkLogView.ts +0 -9
- package/front_end/panels/network/NetworkPanel.ts +1 -63
- package/front_end/panels/network/RequestInitiatorView.ts +29 -4
- package/front_end/panels/network/components/HeaderSectionRow.css +9 -7
- package/front_end/panels/network/components/HeaderSectionRow.ts +20 -1
- package/front_end/panels/network/components/RequestHeaderSection.css +5 -3
- package/front_end/panels/network/components/RequestHeaderSection.ts +1 -2
- package/front_end/panels/network/components/RequestHeadersView.css +1 -1
- package/front_end/panels/security/SecurityPanel.ts +36 -23
- package/front_end/panels/settings/SettingsScreen.ts +18 -103
- package/front_end/panels/settings/settings-meta.ts +0 -24
- package/front_end/panels/timeline/TimelineController.ts +3 -2
- package/front_end/panels/timeline/TimelinePanel.ts +20 -3
- package/front_end/panels/timeline/components/CPUThrottlingSelector.ts +15 -14
- package/front_end/panels/timeline/timelineFlamechartPopover.css +2 -0
- package/front_end/panels/utils/utils.ts +25 -24
- 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 +34 -55
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +96 -83
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.d.ts +10 -1
- 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.map +1 -1
- 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 +1 -1
- 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/CDPSession.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/CDPSession.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPResponse.d.ts +3 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPResponse.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPResponse.js.map +1 -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.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Target.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Target.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/locators/locators.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/api/locators/locators.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 +2 -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/bidi/core/Realm.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/core/Realm.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.d.ts +2 -2
- 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 +5 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Frame.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Frame.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/FrameManager.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/FrameManager.js +23 -13
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/FrameManager.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPResponse.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPResponse.js +4 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPResponse.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Input.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/LifecycleWatcher.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/LifecycleWatcher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Target.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Target.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/WebMCP.d.ts +3 -41
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/WebMCP.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/WebMCP.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/common/ConnectOptions.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.js +4 -2
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/LaunchOptions.d.ts +5 -0
- package/front_end/third_party/puppeteer/package/lib/puppeteer/node/LaunchOptions.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/httpUtils.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/httpUtils.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/httpUtils.js +5 -5
- package/front_end/third_party/puppeteer/package/lib/puppeteer/util/httpUtils.js.map +1 -1
- 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 +34 -55
- package/front_end/third_party/puppeteer/package/package.json +4 -4
- package/front_end/third_party/puppeteer/package/src/api/Browser.ts +13 -1
- package/front_end/third_party/puppeteer/package/src/api/BrowserContext.ts +2 -3
- package/front_end/third_party/puppeteer/package/src/api/CDPSession.ts +3 -1
- package/front_end/third_party/puppeteer/package/src/api/HTTPResponse.ts +3 -2
- package/front_end/third_party/puppeteer/package/src/api/Realm.ts +1 -2
- package/front_end/third_party/puppeteer/package/src/api/Target.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/api/locators/locators.ts +1 -2
- package/front_end/third_party/puppeteer/package/src/bidi/HTTPResponse.ts +3 -1
- package/front_end/third_party/puppeteer/package/src/bidi/core/Realm.ts +1 -3
- package/front_end/third_party/puppeteer/package/src/cdp/Browser.ts +13 -3
- package/front_end/third_party/puppeteer/package/src/cdp/Frame.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/cdp/FrameManager.ts +24 -13
- package/front_end/third_party/puppeteer/package/src/cdp/HTTPResponse.ts +4 -1
- package/front_end/third_party/puppeteer/package/src/cdp/Input.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/cdp/LifecycleWatcher.ts +1 -4
- package/front_end/third_party/puppeteer/package/src/cdp/Target.ts +2 -4
- package/front_end/third_party/puppeteer/package/src/cdp/WebMCP.ts +7 -76
- package/front_end/third_party/puppeteer/package/src/common/ConnectOptions.ts +1 -4
- package/front_end/third_party/puppeteer/package/src/node/BrowserLauncher.ts +4 -1
- package/front_end/third_party/puppeteer/package/src/node/LaunchOptions.ts +5 -0
- package/front_end/third_party/puppeteer/package/src/revisions.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/util/httpUtils.ts +5 -5
- package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
- package/front_end/third_party/puppeteer/third_party/parsel/README.chromium +1 -1
- package/front_end/ui/components/dialogs/Dialog.ts +3 -0
- package/front_end/ui/components/markdown_view/MarkdownLinksMap.ts +0 -7
- package/front_end/ui/helpers/OpenInNewTab.ts +15 -7
- package/front_end/ui/legacy/TabbedPane.ts +1 -108
- package/front_end/ui/legacy/components/data_grid/DataGrid.ts +9 -0
- package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +172 -123
- package/front_end/ui/legacy/components/data_grid/DataGridExporter.ts +89 -0
- package/front_end/ui/legacy/components/data_grid/dataGrid.css +10 -0
- package/front_end/ui/legacy/components/data_grid/data_grid.ts +3 -1
- package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +89 -40
- package/front_end/ui/visual_logging/KnownContextValues.ts +2 -0
- package/package.json +1 -1
- package/front_end/Images/navigationControls.png +0 -0
- package/front_end/Images/navigationControls_2x.png +0 -0
- package/front_end/Images/popoverArrows.png +0 -0
- package/front_end/entrypoints/greendev_floaty/FloatyEntrypoint.ts +0 -746
- package/front_end/entrypoints/greendev_floaty/floaty.css +0 -301
- package/front_end/entrypoints/greendev_floaty/floaty.html +0 -38
- package/front_end/entrypoints/greendev_floaty/greendev_floaty.ts +0 -415
- package/front_end/models/ai_assistance/agents/GreenDevAgent.ts +0 -834
- package/front_end/models/ai_assistance/agents/GreenDevAgentAntigravityCliSocketClient.ts +0 -53
- package/front_end/models/ai_assistance/agents/GreenDevAgentGeminiCliSocketClient.ts +0 -117
- package/front_end/models/annotations/AnnotationRepository.ts +0 -238
- package/front_end/models/annotations/AnnotationType.ts +0 -10
- package/front_end/models/annotations/README.md +0 -7
- package/front_end/models/annotations/annotations.ts +0 -6
- package/front_end/models/greendev/Prototypes.ts +0 -68
- package/front_end/models/greendev/README.md +0 -5
- package/front_end/models/greendev/greendev.ts +0 -5
- package/front_end/panels/common/Annotation.ts +0 -184
- package/front_end/panels/common/AnnotationManager.ts +0 -208
- package/front_end/panels/common/annotation.css +0 -40
- package/front_end/panels/greendev/GreenDevPanel.css +0 -282
- package/front_end/panels/greendev/GreenDevPanel.ts +0 -364
- package/front_end/panels/greendev/GreenDevShared.ts +0 -13
- package/front_end/panels/greendev/greendev-meta.ts +0 -52
- package/front_end/panels/greendev/greendev.ts +0 -9
|
@@ -1,746 +0,0 @@
|
|
|
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
|
-
/* eslint-disable @devtools/no-imperative-dom-api */
|
|
5
|
-
|
|
6
|
-
import '../../core/sdk/sdk-meta.js';
|
|
7
|
-
import '../../models/workspace/workspace-meta.js';
|
|
8
|
-
import '../../models/logs/logs-meta.js';
|
|
9
|
-
import '../../panels/sensors/sensors-meta.js';
|
|
10
|
-
import '../../panels/sources/sources-meta.js';
|
|
11
|
-
import '../../entrypoints/inspector_main/inspector_main-meta.js';
|
|
12
|
-
import '../../entrypoints/main/main-meta.js';
|
|
13
|
-
import '../../ui/legacy/components/source_frame/source_frame-meta.js';
|
|
14
|
-
import '../../ui/components/markdown_view/markdown_view.js';
|
|
15
|
-
|
|
16
|
-
import * as Common from '../../core/common/common.js';
|
|
17
|
-
import * as Host from '../../core/host/host.js';
|
|
18
|
-
import * as i18n from '../../core/i18n/i18n.js';
|
|
19
|
-
import type * as Platform from '../../core/platform/platform.js';
|
|
20
|
-
import type * as ExperimentNames from '../../core/root/ExperimentNames.js';
|
|
21
|
-
import * as Root from '../../core/root/root.js';
|
|
22
|
-
import * as SDK from '../../core/sdk/sdk.js';
|
|
23
|
-
import * as Foundation from '../../foundation/foundation.js';
|
|
24
|
-
import type * as Protocol from '../../generated/protocol.js';
|
|
25
|
-
import * as AiAssistance from '../../models/ai_assistance/ai_assistance.js';
|
|
26
|
-
import * as Greendev from '../../models/greendev/greendev.js';
|
|
27
|
-
import type {SyncMessage} from '../../panels/greendev/GreenDevShared.js';
|
|
28
|
-
import * as Marked from '../../third_party/marked/marked.js';
|
|
29
|
-
import * as MarkdownView from '../../ui/components/markdown_view/markdown_view.js';
|
|
30
|
-
import * as UI from '../../ui/legacy/legacy.js';
|
|
31
|
-
import * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';
|
|
32
|
-
|
|
33
|
-
const {AidaClient} = Host.AidaClient;
|
|
34
|
-
const {ResponseType} = AiAssistance.AiAgent;
|
|
35
|
-
|
|
36
|
-
let pendingActivationSessionId: number|null = null;
|
|
37
|
-
|
|
38
|
-
class GreenDevFloaty {
|
|
39
|
-
#chatContainer!: HTMLDivElement;
|
|
40
|
-
#textField!: HTMLInputElement;
|
|
41
|
-
#playButton!: HTMLButtonElement;
|
|
42
|
-
#node?: SDK.DOMModel.DOMNode;
|
|
43
|
-
#agent?: AiAssistance.GreenDevAgent.GreenDevAgent|AiAssistance.StylingAgent.StylingAgent;
|
|
44
|
-
#nodeContext?: AiAssistance.DOMNodeContext.DOMNodeContext;
|
|
45
|
-
#backendNodeId?: Protocol.DOM.BackendNodeId;
|
|
46
|
-
#syncChannel: BroadcastChannel;
|
|
47
|
-
#isFloatyWindow: boolean;
|
|
48
|
-
#socketClient:
|
|
49
|
-
AiAssistance.GreenDevAgentAntigravityCliSocketClient.GreenDevAgentAntigravityCliSocketClient|
|
|
50
|
-
AiAssistance.GreenDevAgentGeminiCliSocketClient.GreenDevAgentGeminiCliSocketClient;
|
|
51
|
-
|
|
52
|
-
constructor(document: Document) {
|
|
53
|
-
const params = new URLSearchParams(window.location.hash.substring(1));
|
|
54
|
-
this.#backendNodeId = parseInt(params.get('backendNodeId') || '0', 10) as Protocol.DOM.BackendNodeId;
|
|
55
|
-
this.#isFloatyWindow = !!this.#backendNodeId;
|
|
56
|
-
|
|
57
|
-
this.#syncChannel = new BroadcastChannel('green-dev-sync');
|
|
58
|
-
this.#syncChannel.onmessage = event => {
|
|
59
|
-
this.#onSyncMessage(event.data);
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
this.#initFloatyMode(document);
|
|
63
|
-
if (Greendev.Prototypes.instance().isEnabled('beyondStylingAntigravity')) {
|
|
64
|
-
this.#socketClient =
|
|
65
|
-
new AiAssistance.GreenDevAgentAntigravityCliSocketClient.GreenDevAgentAntigravityCliSocketClient();
|
|
66
|
-
} else {
|
|
67
|
-
this.#socketClient = new AiAssistance.GreenDevAgentGeminiCliSocketClient.GreenDevAgentGeminiCliSocketClient();
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
#initFloatyMode(doc: Document): void {
|
|
72
|
-
this.#chatContainer = doc.getElementById('chat-container') as HTMLDivElement;
|
|
73
|
-
this.#textField = doc.querySelector('.green-dev-floaty-dialog-text-field') as HTMLInputElement;
|
|
74
|
-
this.#playButton = doc.querySelector('.green-dev-floaty-dialog-play-button') as HTMLButtonElement;
|
|
75
|
-
|
|
76
|
-
this.#playButton?.addEventListener('click', () => {
|
|
77
|
-
if (this.#node) {
|
|
78
|
-
void this.runConversation();
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
const contextText = doc.querySelector('.green-dev-floaty-dialog-context-text') as HTMLSpanElement;
|
|
83
|
-
if (contextText) {
|
|
84
|
-
contextText.style.cursor = 'pointer';
|
|
85
|
-
contextText.title = 'Click to show in DevTools Panel';
|
|
86
|
-
contextText.addEventListener('click', () => {
|
|
87
|
-
this.#broadcastFullState();
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const learnMoreLink = doc.querySelector('.learn-more-link');
|
|
92
|
-
if (learnMoreLink) {
|
|
93
|
-
learnMoreLink.addEventListener('click', event => {
|
|
94
|
-
event.preventDefault();
|
|
95
|
-
Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(
|
|
96
|
-
'https://developer.chrome.com/docs/devtools/ai-assistance' as Platform.DevToolsPath.UrlString);
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const nodeDescriptionElement = doc.querySelector('.green-dev-floaty-dialog-node-description') as HTMLDivElement;
|
|
101
|
-
nodeDescriptionElement?.addEventListener('mousemove', () => {
|
|
102
|
-
if (this.#node) {
|
|
103
|
-
this.#node.highlight();
|
|
104
|
-
}
|
|
105
|
-
});
|
|
106
|
-
nodeDescriptionElement?.addEventListener('mouseleave', () => {
|
|
107
|
-
if (this.#node && this.#backendNodeId) {
|
|
108
|
-
const msg = JSON.stringify({
|
|
109
|
-
id: 9999,
|
|
110
|
-
method: 'Overlay.setShowInspectedElementAnchor',
|
|
111
|
-
params: {inspectedElementAnchorConfig: {backendNodeId: this.#backendNodeId}},
|
|
112
|
-
});
|
|
113
|
-
Host.InspectorFrontendHost.InspectorFrontendHostInstance.sendMessageToBackend(msg);
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
this.#textField?.addEventListener('keydown', event => {
|
|
118
|
-
if (event.key === 'Enter' && this.#node) {
|
|
119
|
-
void this.runConversation();
|
|
120
|
-
}
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
this.#textField?.focus();
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
#broadcastFullState(): void {
|
|
127
|
-
const state = {
|
|
128
|
-
type: 'full-state',
|
|
129
|
-
messages: this.#getMessages(),
|
|
130
|
-
sessionId: this.#backendNodeId,
|
|
131
|
-
nodeDescription: document.querySelector('.green-dev-floaty-dialog-node-description')?.textContent,
|
|
132
|
-
};
|
|
133
|
-
this.#syncChannel.postMessage(state);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
#onSyncMessage(data: SyncMessage): void {
|
|
137
|
-
if (data.type === 'main-window-alive') {
|
|
138
|
-
if (pendingActivationSessionId) {
|
|
139
|
-
const syncChannel = new BroadcastChannel('green-dev-sync');
|
|
140
|
-
syncChannel.postMessage({type: 'activate-panel', sessionId: pendingActivationSessionId});
|
|
141
|
-
syncChannel.close();
|
|
142
|
-
}
|
|
143
|
-
} else if (data.type === 'request-session-state') {
|
|
144
|
-
this.#broadcastFullState();
|
|
145
|
-
|
|
146
|
-
if (pendingActivationSessionId) {
|
|
147
|
-
this.#syncChannel.postMessage({type: 'select-tab', sessionId: pendingActivationSessionId});
|
|
148
|
-
pendingActivationSessionId = null;
|
|
149
|
-
}
|
|
150
|
-
} else if (data.type === 'user-input' && data.sessionId === this.#backendNodeId) {
|
|
151
|
-
if (this.#textField) {
|
|
152
|
-
this.#textField.value = data.text ?? '';
|
|
153
|
-
void this.runConversation();
|
|
154
|
-
}
|
|
155
|
-
} else if (data.type === 'restore-floaty' && data.sessionId === this.#backendNodeId) {
|
|
156
|
-
// The main DevTools window will bring the floaty to the front,
|
|
157
|
-
// so the floaty window itself doesn't need to do it.
|
|
158
|
-
Host.InspectorFrontendHost.InspectorFrontendHostInstance.bringToFront();
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
static instance(opts: {forceNew: boolean|null, document: Document} = {forceNew: null, document}): GreenDevFloaty {
|
|
163
|
-
const {forceNew, document} = opts;
|
|
164
|
-
if (!greenDevFloatyInstance || forceNew) {
|
|
165
|
-
greenDevFloatyInstance = new GreenDevFloaty(document);
|
|
166
|
-
}
|
|
167
|
-
return greenDevFloatyInstance;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
handlePanelRequest = (event: Common.EventTarget.EventTargetEvent<number>): void => {
|
|
171
|
-
pendingActivationSessionId = event.data;
|
|
172
|
-
this.#sendActivatePanelMessage(pendingActivationSessionId, 0);
|
|
173
|
-
Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(
|
|
174
|
-
'magic:open-devtools' as Platform.DevToolsPath.UrlString);
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
readonly #maxActivationRetries = 10;
|
|
178
|
-
readonly #activationRetryDelayMs = 200;
|
|
179
|
-
|
|
180
|
-
#sendActivatePanelMessage(sessionId: number, retryCount: number): void {
|
|
181
|
-
if (retryCount >= this.#maxActivationRetries) {
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
const syncChannel = new BroadcastChannel('green-dev-sync');
|
|
186
|
-
syncChannel.postMessage({type: 'activate-panel', sessionId});
|
|
187
|
-
syncChannel.close();
|
|
188
|
-
|
|
189
|
-
// To ensure the activate-panel is always received, let's add a small delay and retry.
|
|
190
|
-
// This is a pragmatic fix for the prototype given the existing async message flow.
|
|
191
|
-
setTimeout(() => {
|
|
192
|
-
// Check if pendingActivationSessionId is still set. If it is, it means
|
|
193
|
-
// the panel hasn't been activated yet (or the confirmation message
|
|
194
|
-
// hasn't arrived), so we retry.
|
|
195
|
-
if (pendingActivationSessionId === sessionId) {
|
|
196
|
-
this.#sendActivatePanelMessage(sessionId, retryCount + 1);
|
|
197
|
-
}
|
|
198
|
-
}, this.#activationRetryDelayMs);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
handleRestoreEvent(event: Common.EventTarget.EventTargetEvent<number>): void {
|
|
202
|
-
const sessionId = event.data;
|
|
203
|
-
// Only the main DevTools window (which is NOT a floaty window) should broadcast the restore request.
|
|
204
|
-
if (!this.#isFloatyWindow) {
|
|
205
|
-
this.#syncChannel.postMessage({type: 'restore-floaty', sessionId});
|
|
206
|
-
} else if (this.#backendNodeId === sessionId) {
|
|
207
|
-
// If a floaty window receives a restore request for its own session,
|
|
208
|
-
// it should bring itself to the front.
|
|
209
|
-
console.error('[GreenDev] Calling bringToFront for session ' + sessionId);
|
|
210
|
-
Host.InspectorFrontendHost.InspectorFrontendHostInstance.bringToFront();
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
setNode(node: SDK.DOMModel.DOMNode): void {
|
|
215
|
-
if (this.#node) {
|
|
216
|
-
this.#node.domModel().overlayModel().removeEventListener(
|
|
217
|
-
SDK.OverlayModel.Events.INSPECT_PANEL_SHOW_REQUESTED, this.handlePanelRequest);
|
|
218
|
-
}
|
|
219
|
-
if (this.#node === node) {
|
|
220
|
-
return;
|
|
221
|
-
}
|
|
222
|
-
this.#node = node;
|
|
223
|
-
this.#node.domModel().overlayModel().addEventListener(
|
|
224
|
-
SDK.OverlayModel.Events.INSPECT_PANEL_SHOW_REQUESTED, this.handlePanelRequest);
|
|
225
|
-
this.#backendNodeId = node.backendNodeId();
|
|
226
|
-
|
|
227
|
-
void node.domModel().overlayModel().clearHighlight();
|
|
228
|
-
this.#textField?.focus();
|
|
229
|
-
this.#agent = undefined;
|
|
230
|
-
this.#nodeContext = undefined;
|
|
231
|
-
|
|
232
|
-
const nodeDescriptionElement = document.querySelector('.green-dev-floaty-dialog-node-description');
|
|
233
|
-
let description = '';
|
|
234
|
-
if (nodeDescriptionElement) {
|
|
235
|
-
const id = node.getAttribute('id');
|
|
236
|
-
if (id) {
|
|
237
|
-
description = `#${id}`;
|
|
238
|
-
} else {
|
|
239
|
-
const classes = node.classNames().join('.');
|
|
240
|
-
description = node.nodeName().toLowerCase() + (classes ? `.${classes}` : '');
|
|
241
|
-
}
|
|
242
|
-
nodeDescriptionElement.textContent = description;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
this.#syncChannel.postMessage({type: 'node-changed', sessionId: this.#backendNodeId, nodeDescription: description});
|
|
246
|
-
|
|
247
|
-
if (this.#backendNodeId) {
|
|
248
|
-
const msg = JSON.stringify({
|
|
249
|
-
id: 9999,
|
|
250
|
-
method: 'Overlay.setShowInspectedElementAnchor',
|
|
251
|
-
params: {inspectedElementAnchorConfig: {backendNodeId: this.#backendNodeId}},
|
|
252
|
-
});
|
|
253
|
-
Host.InspectorFrontendHost.InspectorFrontendHostInstance.sendMessageToBackend(msg);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
#getMessages(): Array<{text: string, isUser: boolean}> {
|
|
258
|
-
const messages = [];
|
|
259
|
-
if (this.#chatContainer) {
|
|
260
|
-
const messageElements = this.#chatContainer.querySelectorAll('.message');
|
|
261
|
-
for (const el of messageElements) {
|
|
262
|
-
const isUser = el.classList.contains('user-message');
|
|
263
|
-
const content = el.querySelector('.message-content')?.textContent || '';
|
|
264
|
-
messages.push({text: content, isUser});
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
return messages;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
#formatError(errorMessage: string): string {
|
|
271
|
-
return `Error: '${errorMessage}' - Protip: to use AI features you need to be signed in.`;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
runConversation = async(): Promise<void> => {
|
|
275
|
-
if (!this.#textField || !this.#node) {
|
|
276
|
-
return;
|
|
277
|
-
}
|
|
278
|
-
const query = this.#textField.value || this.#textField.placeholder;
|
|
279
|
-
this.#textField.value = '';
|
|
280
|
-
|
|
281
|
-
const useAntigravity = Greendev.Prototypes.instance().isEnabled('beyondStylingAntigravity');
|
|
282
|
-
const useGemini = Greendev.Prototypes.instance().isEnabled('beyondStylingGemini');
|
|
283
|
-
const useGreenDevAgent = useAntigravity || useGemini;
|
|
284
|
-
const isAntigravity = useAntigravity;
|
|
285
|
-
|
|
286
|
-
if (!this.#agent) {
|
|
287
|
-
const aidaClient = new AidaClient();
|
|
288
|
-
if (useGreenDevAgent) {
|
|
289
|
-
if (isAntigravity) {
|
|
290
|
-
this.#socketClient =
|
|
291
|
-
new AiAssistance.GreenDevAgentAntigravityCliSocketClient.GreenDevAgentAntigravityCliSocketClient();
|
|
292
|
-
} else {
|
|
293
|
-
this.#socketClient = new AiAssistance.GreenDevAgentGeminiCliSocketClient.GreenDevAgentGeminiCliSocketClient();
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
this.#agent = new AiAssistance.GreenDevAgent.GreenDevAgent({aidaClient});
|
|
297
|
-
this.#agent.addEventListener(
|
|
298
|
-
AiAssistance.GreenDevAgent.Events.CLI_PROMPT_REQUESTED,
|
|
299
|
-
async (
|
|
300
|
-
event: Common.EventTarget.EventTargetEvent<
|
|
301
|
-
AiAssistance.GreenDevAgent.EventTypes[AiAssistance.GreenDevAgent.Events.CLI_PROMPT_REQUESTED]>) => {
|
|
302
|
-
const {prompt} = event.data;
|
|
303
|
-
const remoteName = isAntigravity ? 'Antigravity' : 'Gemini';
|
|
304
|
-
const aiContent =
|
|
305
|
-
this.#addMessageInternal(`Fix has been submitted to ${remoteName} CLI, please wait...`, false);
|
|
306
|
-
|
|
307
|
-
if (isAntigravity) {
|
|
308
|
-
let fullResponse = '';
|
|
309
|
-
void (
|
|
310
|
-
this.#socketClient as
|
|
311
|
-
AiAssistance.GreenDevAgentAntigravityCliSocketClient.GreenDevAgentAntigravityCliSocketClient)
|
|
312
|
-
.sendPrompt(prompt, (chunk: string) => {
|
|
313
|
-
fullResponse += chunk;
|
|
314
|
-
const responseText = `Antigravity CLI responds: ${fullResponse}`;
|
|
315
|
-
const markdown = new MarkdownView.MarkdownView.MarkdownView();
|
|
316
|
-
markdown.data = {
|
|
317
|
-
tokens: Marked.Marked.lexer(responseText),
|
|
318
|
-
};
|
|
319
|
-
|
|
320
|
-
const style = document.createElement('style');
|
|
321
|
-
style.textContent =
|
|
322
|
-
'.message { font-size: 1.0rem; } .message code { font-size: 1.0rem; font-family: \'Roboto Mono\', ' +
|
|
323
|
-
'monospace; color: green; } .message ul { margin-left: 20px; }';
|
|
324
|
-
markdown.shadowRoot?.appendChild(style);
|
|
325
|
-
|
|
326
|
-
this.#updateAiMessage(aiContent, markdown, responseText);
|
|
327
|
-
});
|
|
328
|
-
} else {
|
|
329
|
-
const response =
|
|
330
|
-
await (this.#socketClient as
|
|
331
|
-
AiAssistance.GreenDevAgentGeminiCliSocketClient.GreenDevAgentGeminiCliSocketClient)
|
|
332
|
-
.sendPrompt(prompt);
|
|
333
|
-
|
|
334
|
-
const responseText = `Gemini CLI responds: ${response}`;
|
|
335
|
-
const markdown = new MarkdownView.MarkdownView.MarkdownView();
|
|
336
|
-
markdown.data = {
|
|
337
|
-
tokens: Marked.Marked.lexer(responseText),
|
|
338
|
-
};
|
|
339
|
-
this.#updateAiMessage(aiContent, markdown, responseText);
|
|
340
|
-
}
|
|
341
|
-
});
|
|
342
|
-
} else {
|
|
343
|
-
this.#agent = new AiAssistance.StylingAgent.StylingAgent({aidaClient});
|
|
344
|
-
this.#nodeContext = new AiAssistance.DOMNodeContext.DOMNodeContext(this.#node);
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
this.#addMessageInternal(query, true);
|
|
349
|
-
const aiContent = this.#addMessageInternal('Thinking...', false);
|
|
350
|
-
|
|
351
|
-
let agentFinished = false;
|
|
352
|
-
let steps = 0;
|
|
353
|
-
try {
|
|
354
|
-
let results;
|
|
355
|
-
if (useGreenDevAgent && this.#agent instanceof AiAssistance.GreenDevAgent.GreenDevAgent) {
|
|
356
|
-
const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
|
|
357
|
-
if (!target) {
|
|
358
|
-
return;
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
// --- Get the Accessibility Tree ---
|
|
362
|
-
const accessibilityModel = target.model(SDK.AccessibilityModel.AccessibilityModel);
|
|
363
|
-
let axTree = '';
|
|
364
|
-
if (accessibilityModel) {
|
|
365
|
-
await accessibilityModel.resumeModel();
|
|
366
|
-
const axResponse = await accessibilityModel.agent.invoke_getFullAXTree({});
|
|
367
|
-
if (!axResponse.getError()) {
|
|
368
|
-
axTree = JSON.stringify(axResponse.nodes);
|
|
369
|
-
} else {
|
|
370
|
-
console.error('Failed to capture Accessibility Tree:', axResponse.getError());
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
// --- Get the most recent network requests ---
|
|
375
|
-
const allNetworkRequests = await AiAssistance.GreenDevAgent.GreenDevAgent.getNetworkContextData(target);
|
|
376
|
-
const networkResourcesMax = 50;
|
|
377
|
-
const startNetworkIndex = Math.max(0, allNetworkRequests.length - networkResourcesMax);
|
|
378
|
-
const lastNetworkRequests = allNetworkRequests.slice(startNetworkIndex);
|
|
379
|
-
let formattedNetworkContext = lastNetworkRequests.map(req => req.string).join('\n');
|
|
380
|
-
|
|
381
|
-
if (!formattedNetworkContext) {
|
|
382
|
-
formattedNetworkContext = 'No network requests found.';
|
|
383
|
-
} else {
|
|
384
|
-
const footer = allNetworkRequests.length > lastNetworkRequests.length ?
|
|
385
|
-
`${
|
|
386
|
-
allNetworkRequests.length -
|
|
387
|
-
lastNetworkRequests.length} additional requests are available (network requests shown are capped at ${
|
|
388
|
-
networkResourcesMax} requests).` :
|
|
389
|
-
'No further network requests are available.';
|
|
390
|
-
|
|
391
|
-
formattedNetworkContext = `Showing network requests with indices ${startNetworkIndex}-${
|
|
392
|
-
startNetworkIndex + lastNetworkRequests.length - 1}:\n\n${formattedNetworkContext}\n\n${footer}`;
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
// --- Get the most recent console messages ---
|
|
396
|
-
const consoleModel = target.model(SDK.ConsoleModel.ConsoleModel);
|
|
397
|
-
const allConsoleMessages = consoleModel ? consoleModel.messages() : [];
|
|
398
|
-
const consoleMsgLimit = 50;
|
|
399
|
-
const startIndex = Math.max(0, allConsoleMessages.length - consoleMsgLimit);
|
|
400
|
-
const lastConsoleMessages = allConsoleMessages.slice(startIndex);
|
|
401
|
-
let formattedConsoleMessages =
|
|
402
|
-
lastConsoleMessages
|
|
403
|
-
.map(
|
|
404
|
-
(entry: SDK.ConsoleModel.ConsoleMessage, i: number) =>
|
|
405
|
-
AiAssistance.GreenDevAgent.GreenDevAgent.formatConsoleMessage(entry, startIndex + i))
|
|
406
|
-
.join('\n');
|
|
407
|
-
formattedConsoleMessages = formattedConsoleMessages.trimEnd();
|
|
408
|
-
|
|
409
|
-
if (!formattedConsoleMessages) {
|
|
410
|
-
formattedConsoleMessages = 'No console messages found.';
|
|
411
|
-
} else {
|
|
412
|
-
const footer = allConsoleMessages.length > lastConsoleMessages.length ?
|
|
413
|
-
`${
|
|
414
|
-
allConsoleMessages.length -
|
|
415
|
-
lastConsoleMessages.length} additional messages are available (errors shown are capped at ${
|
|
416
|
-
consoleMsgLimit} most recent).` :
|
|
417
|
-
'No further console messages are available.';
|
|
418
|
-
|
|
419
|
-
formattedConsoleMessages = `Showing console messages with indices ${startIndex}-${
|
|
420
|
-
startIndex + lastConsoleMessages.length - 1}:\n\n${formattedConsoleMessages}\n\n${footer}`;
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
const mainUrl = target.inspectedURL();
|
|
424
|
-
|
|
425
|
-
// --- Get the React Props for the selected node (if available) ---
|
|
426
|
-
const reactComponentProps = this.#backendNodeId ?
|
|
427
|
-
await this.#agent.getReactComponentProps(this.#backendNodeId, false) :
|
|
428
|
-
'Could not get the backendNodeId for the selected element.';
|
|
429
|
-
|
|
430
|
-
// --- Get some context information about the selected node ---
|
|
431
|
-
const domNodeContext = new AiAssistance.DOMNodeContext.DOMNodeContext(this.#node);
|
|
432
|
-
const elementContext = await domNodeContext.describe();
|
|
433
|
-
|
|
434
|
-
// Now construct the full context.
|
|
435
|
-
const context = `# Page URL
|
|
436
|
-
|
|
437
|
-
${mainUrl}
|
|
438
|
-
|
|
439
|
-
# User-selected node
|
|
440
|
-
|
|
441
|
-
${elementContext}
|
|
442
|
-
|
|
443
|
-
# React component props:
|
|
444
|
-
|
|
445
|
-
${reactComponentProps}
|
|
446
|
-
|
|
447
|
-
# Recent network requests
|
|
448
|
-
|
|
449
|
-
${formattedNetworkContext}
|
|
450
|
-
|
|
451
|
-
# Recent console messages
|
|
452
|
-
|
|
453
|
-
${formattedConsoleMessages}
|
|
454
|
-
|
|
455
|
-
# Accessibility tree
|
|
456
|
-
|
|
457
|
-
${axTree}`;
|
|
458
|
-
|
|
459
|
-
const nodeContext = new AiAssistance.GreenDevAgent.GreenDevContext(context);
|
|
460
|
-
results = this.#agent.run(query, {selected: nodeContext});
|
|
461
|
-
} else if (this.#agent instanceof AiAssistance.StylingAgent.StylingAgent) {
|
|
462
|
-
if (!this.#nodeContext) {
|
|
463
|
-
throw new Error('Node context not found.');
|
|
464
|
-
}
|
|
465
|
-
results = this.#agent.run(query, {selected: this.#nodeContext});
|
|
466
|
-
} else {
|
|
467
|
-
throw new Error('Agent not initialized correctly');
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
for await (const result of results) {
|
|
471
|
-
switch (result.type) {
|
|
472
|
-
case ResponseType.QUERYING:
|
|
473
|
-
steps++;
|
|
474
|
-
break;
|
|
475
|
-
case ResponseType.ANSWER: {
|
|
476
|
-
aiContent.textContent = '';
|
|
477
|
-
// Add a space in the protocol, which prevents links from being linkified in
|
|
478
|
-
// the markup. Why? Because there's an exception thrown if the links don't match the
|
|
479
|
-
// allowlist in getMarkdownLink(). Need to figure out later.
|
|
480
|
-
let sanitizedText = result.text.replace(/https:\/\//g, 'https: //');
|
|
481
|
-
sanitizedText = sanitizedText.replace(/http:\/\//g, 'http: //');
|
|
482
|
-
const markdown = new MarkdownView.MarkdownView.MarkdownView();
|
|
483
|
-
markdown.data = {
|
|
484
|
-
tokens: Marked.Marked.lexer(sanitizedText),
|
|
485
|
-
};
|
|
486
|
-
this.#updateAiMessage(aiContent, markdown, result.text);
|
|
487
|
-
|
|
488
|
-
void new Promise(resolve => setTimeout(resolve, 0)).then(() => {
|
|
489
|
-
const style = document.createElement('style');
|
|
490
|
-
style.textContent =
|
|
491
|
-
'.message { font-size: 1.0rem; } .message code { font-size: 1.0rem; font-family: \'Roboto Mono\', ' +
|
|
492
|
-
'monospace; color: green; } .message ul { margin-left: 20px; }';
|
|
493
|
-
markdown.shadowRoot?.appendChild(style);
|
|
494
|
-
|
|
495
|
-
const codeBlocks = markdown.shadowRoot?.querySelectorAll('devtools-code-block');
|
|
496
|
-
if (codeBlocks) {
|
|
497
|
-
for (const codeBlock of codeBlocks) {
|
|
498
|
-
const style = document.createElement('style');
|
|
499
|
-
style.textContent = `
|
|
500
|
-
.heading { color: black; background-color: #f2f6ff; font-family: 'Roboto Mono', monospace; padding: 2px 4px;
|
|
501
|
-
border-top-left-radius: 8px; border-top-right-radius: 8px; margin-bottom: 3px; }
|
|
502
|
-
.code { background-color: #f8f9fa; font-family: 'Roboto Mono', monospace; padding: 5px;
|
|
503
|
-
border-bottom-left-radius: 8px; border-bottom-right-radius: 8px; }
|
|
504
|
-
.editor-wrapper { margin-left: 20px; }
|
|
505
|
-
`;
|
|
506
|
-
codeBlock.shadowRoot?.appendChild(style);
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
});
|
|
510
|
-
agentFinished = true;
|
|
511
|
-
break;
|
|
512
|
-
}
|
|
513
|
-
case ResponseType.ERROR:
|
|
514
|
-
this.#updateAiMessage(
|
|
515
|
-
aiContent, document.createTextNode(this.#formatError(result.error)), this.#formatError(result.error));
|
|
516
|
-
agentFinished = true;
|
|
517
|
-
break;
|
|
518
|
-
case ResponseType.SIDE_EFFECT:
|
|
519
|
-
result.confirm(true);
|
|
520
|
-
break;
|
|
521
|
-
default:
|
|
522
|
-
break;
|
|
523
|
-
}
|
|
524
|
-
if (this.#chatContainer) {
|
|
525
|
-
this.#chatContainer.scrollTop = this.#chatContainer.scrollHeight;
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
} catch (e) {
|
|
529
|
-
aiContent.textContent = `Exception: ${e instanceof Error ? e.message : String(e)}`;
|
|
530
|
-
agentFinished = true;
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
const MAX_AGENT_STEPS = AiAssistance.AiAgent.MAX_STEPS;
|
|
534
|
-
if (!agentFinished && steps >= MAX_AGENT_STEPS) {
|
|
535
|
-
aiContent.textContent = `The agent has reached its internal limit of ${MAX_AGENT_STEPS} steps per turn before
|
|
536
|
-
finding an answer. Please try again with a more specific query or say 'continue' (to get ${MAX_AGENT_STEPS}
|
|
537
|
-
more steps and continue trying).`;
|
|
538
|
-
}
|
|
539
|
-
};
|
|
540
|
-
|
|
541
|
-
#addMessageInternal(text: string, isUser: boolean): HTMLDivElement {
|
|
542
|
-
const messageElement = document.createElement('div');
|
|
543
|
-
messageElement.className = `message ${isUser ? 'user-message' : 'ai-message'}`;
|
|
544
|
-
|
|
545
|
-
const content = document.createElement('div');
|
|
546
|
-
content.className = 'message-content';
|
|
547
|
-
content.textContent = text;
|
|
548
|
-
messageElement.appendChild(content);
|
|
549
|
-
|
|
550
|
-
if (this.#chatContainer) {
|
|
551
|
-
this.#chatContainer.appendChild(messageElement);
|
|
552
|
-
this.#chatContainer.scrollTop = this.#chatContainer.scrollHeight;
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
this.#syncChannel.postMessage({
|
|
556
|
-
type: 'new-message',
|
|
557
|
-
text,
|
|
558
|
-
isUser,
|
|
559
|
-
sessionId: this.#backendNodeId,
|
|
560
|
-
nodeDescription: document.querySelector('.green-dev-floaty-dialog-node-description')?.textContent,
|
|
561
|
-
});
|
|
562
|
-
|
|
563
|
-
return content;
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
#updateAiMessage(aiContentElement: HTMLDivElement, newContent: Node, newText: string): void {
|
|
567
|
-
aiContentElement.textContent = '';
|
|
568
|
-
aiContentElement.append(newContent);
|
|
569
|
-
this.#syncChannel.postMessage({type: 'update-last-message', text: newText, sessionId: this.#backendNodeId});
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
let greenDevFloatyInstance: GreenDevFloaty;
|
|
574
|
-
|
|
575
|
-
function safeRegisterExperiment(name: string, title: string): void {
|
|
576
|
-
try {
|
|
577
|
-
Root.Runtime.experiments.register(name as ExperimentNames.ExperimentName, title);
|
|
578
|
-
} catch (e) {
|
|
579
|
-
console.error('Unable to register experiment ', name, title, e);
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
async function init(): Promise<void> {
|
|
584
|
-
try {
|
|
585
|
-
Root.Runtime.Runtime.setPlatform(Host.Platform.platform());
|
|
586
|
-
const [config, prefs] = await Promise.all([
|
|
587
|
-
new Promise<Root.Runtime.HostConfig>(
|
|
588
|
-
resolve => Host.InspectorFrontendHost.InspectorFrontendHostInstance.getHostConfig(resolve)),
|
|
589
|
-
new Promise<Record<string, string>>(
|
|
590
|
-
resolve => Host.InspectorFrontendHost.InspectorFrontendHostInstance.getPreferences(resolve)),
|
|
591
|
-
]);
|
|
592
|
-
Object.assign(Root.Runtime.hostConfig, config);
|
|
593
|
-
|
|
594
|
-
safeRegisterExperiment(
|
|
595
|
-
Root.ExperimentNames.ExperimentName.INSTRUMENTATION_BREAKPOINTS, 'Enable instrumentation breakpoints');
|
|
596
|
-
safeRegisterExperiment(Root.ExperimentNames.ExperimentName.PROTOCOL_MONITOR, 'Protocol Monitor');
|
|
597
|
-
|
|
598
|
-
const hostUnsyncedStorage: Common.Settings.SettingsBackingStore = {
|
|
599
|
-
register: (name: string) =>
|
|
600
|
-
Host.InspectorFrontendHost.InspectorFrontendHostInstance.registerPreference(name, {synced: false}),
|
|
601
|
-
set: Host.InspectorFrontendHost.InspectorFrontendHostInstance.setPreference,
|
|
602
|
-
get: (name: string) =>
|
|
603
|
-
new Promise(resolve => Host.InspectorFrontendHost.InspectorFrontendHostInstance.getPreference(name, resolve)),
|
|
604
|
-
remove: Host.InspectorFrontendHost.InspectorFrontendHostInstance.removePreference,
|
|
605
|
-
clear: Host.InspectorFrontendHost.InspectorFrontendHostInstance.clearPreferences,
|
|
606
|
-
};
|
|
607
|
-
const syncedStorage = new Common.Settings.SettingsStorage(prefs, hostUnsyncedStorage, '');
|
|
608
|
-
const globalStorage = new Common.Settings.SettingsStorage(prefs, hostUnsyncedStorage, '');
|
|
609
|
-
const localStorage = new Common.Settings.SettingsStorage(
|
|
610
|
-
window.localStorage, {
|
|
611
|
-
register(_setting: string): void{},
|
|
612
|
-
async get(setting: string): Promise<string> {
|
|
613
|
-
return window.localStorage.getItem(setting) as unknown as string;
|
|
614
|
-
},
|
|
615
|
-
set(setting: string, value: string): void {
|
|
616
|
-
window.localStorage.setItem(setting, value);
|
|
617
|
-
},
|
|
618
|
-
remove(setting: string): void {
|
|
619
|
-
window.localStorage.removeItem(setting);
|
|
620
|
-
},
|
|
621
|
-
clear: () => window.localStorage.clear(),
|
|
622
|
-
},
|
|
623
|
-
'');
|
|
624
|
-
|
|
625
|
-
Common.Settings.Settings.instance({
|
|
626
|
-
forceNew: true,
|
|
627
|
-
syncedStorage,
|
|
628
|
-
globalStorage,
|
|
629
|
-
localStorage,
|
|
630
|
-
settingRegistrations: Common.SettingRegistration.getRegisteredSettings(),
|
|
631
|
-
});
|
|
632
|
-
|
|
633
|
-
UI.UIUtils.initializeUIUtils(document);
|
|
634
|
-
ThemeSupport.ThemeSupport.instance({
|
|
635
|
-
forceNew: true,
|
|
636
|
-
setting: Common.Settings.Settings.instance().moduleSetting('ui-theme'),
|
|
637
|
-
});
|
|
638
|
-
UI.ZoomManager.ZoomManager.instance(
|
|
639
|
-
{forceNew: true, win: window, frontendHost: Host.InspectorFrontendHost.InspectorFrontendHostInstance});
|
|
640
|
-
|
|
641
|
-
const settingLanguage = Common.Settings.Settings.instance().moduleSetting<string>('language').get();
|
|
642
|
-
i18n.DevToolsLocale.DevToolsLocale.instance({
|
|
643
|
-
create: true,
|
|
644
|
-
data: {
|
|
645
|
-
navigatorLanguage: navigator.language,
|
|
646
|
-
settingLanguage,
|
|
647
|
-
lookupClosestDevToolsLocale: i18n.i18n.lookupClosestSupportedDevToolsLocale,
|
|
648
|
-
},
|
|
649
|
-
});
|
|
650
|
-
|
|
651
|
-
const universe = new Foundation.Universe.Universe({
|
|
652
|
-
settingsCreationOptions: {
|
|
653
|
-
syncedStorage,
|
|
654
|
-
globalStorage,
|
|
655
|
-
localStorage,
|
|
656
|
-
settingRegistrations: Common.SettingRegistration.getRegisteredSettings(),
|
|
657
|
-
}
|
|
658
|
-
});
|
|
659
|
-
Root.DevToolsContext.setGlobalInstance(universe.context as Root.DevToolsContext.WritableDevToolsContext);
|
|
660
|
-
|
|
661
|
-
await i18n.i18n.fetchAndRegisterLocaleData('en-US');
|
|
662
|
-
Host.InspectorFrontendHost.InspectorFrontendHostInstance.connectionReady();
|
|
663
|
-
|
|
664
|
-
const hash = window.location.hash.substring(1);
|
|
665
|
-
const params = new URLSearchParams(hash);
|
|
666
|
-
const backendNodeId = parseInt(params.get('backendNodeId') || '0', 10);
|
|
667
|
-
|
|
668
|
-
const floaty = GreenDevFloaty.instance({forceNew: null, document});
|
|
669
|
-
|
|
670
|
-
if (backendNodeId) {
|
|
671
|
-
await SDK.Connections.initMainConnection(async () => {
|
|
672
|
-
const targetManager = SDK.TargetManager.TargetManager.instance();
|
|
673
|
-
targetManager.createTarget('main', 'Main', SDK.Target.Type.FRAME, null);
|
|
674
|
-
const mainTarget = await new Promise<SDK.Target.Target|null>(resolve => {
|
|
675
|
-
const t = targetManager.primaryPageTarget();
|
|
676
|
-
if (t) {
|
|
677
|
-
resolve(t);
|
|
678
|
-
return;
|
|
679
|
-
}
|
|
680
|
-
const observer = {
|
|
681
|
-
targetAdded: (target: SDK.Target.Target) => {
|
|
682
|
-
if (target === targetManager.primaryPageTarget()) {
|
|
683
|
-
targetManager.unobserveTargets(observer);
|
|
684
|
-
resolve(target);
|
|
685
|
-
}
|
|
686
|
-
},
|
|
687
|
-
targetRemoved: () => {},
|
|
688
|
-
};
|
|
689
|
-
targetManager.observeTargets(observer);
|
|
690
|
-
});
|
|
691
|
-
if (!mainTarget) {
|
|
692
|
-
return;
|
|
693
|
-
}
|
|
694
|
-
const domModel = mainTarget.model(SDK.DOMModel.DOMModel);
|
|
695
|
-
if (!domModel) {
|
|
696
|
-
return;
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
// Add listener for floaty restore events
|
|
700
|
-
const overlayModel = mainTarget.model(SDK.OverlayModel.OverlayModel);
|
|
701
|
-
if (overlayModel) {
|
|
702
|
-
overlayModel.addEventListener(
|
|
703
|
-
SDK.OverlayModel.Events.INSPECTED_ELEMENT_WINDOW_RESTORED, floaty.handleRestoreEvent, floaty);
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
const nodesMap =
|
|
707
|
-
await domModel.pushNodesByBackendIdsToFrontend(new Set([backendNodeId as Protocol.DOM.BackendNodeId]));
|
|
708
|
-
const node = nodesMap?.get(backendNodeId as Protocol.DOM.BackendNodeId) || null;
|
|
709
|
-
if (node) {
|
|
710
|
-
floaty.setNode(node);
|
|
711
|
-
}
|
|
712
|
-
}, () => {});
|
|
713
|
-
} else {
|
|
714
|
-
const targetManager = SDK.TargetManager.TargetManager.instance();
|
|
715
|
-
const observer = {
|
|
716
|
-
targetAdded: (target: SDK.Target.Target) => {
|
|
717
|
-
if (target.type() === SDK.Target.Type.FRAME) {
|
|
718
|
-
const overlayModel = target.model(SDK.OverlayModel.OverlayModel);
|
|
719
|
-
if (overlayModel) {
|
|
720
|
-
overlayModel.addEventListener(
|
|
721
|
-
SDK.OverlayModel.Events.INSPECTED_ELEMENT_WINDOW_RESTORED, floaty.handleRestoreEvent, floaty);
|
|
722
|
-
overlayModel.addEventListener(
|
|
723
|
-
SDK.OverlayModel.Events.INSPECT_PANEL_SHOW_REQUESTED, floaty.handlePanelRequest);
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
},
|
|
727
|
-
targetRemoved: (target: SDK.Target.Target) => {
|
|
728
|
-
if (target.type() === SDK.Target.Type.FRAME) {
|
|
729
|
-
const overlayModel = target.model(SDK.OverlayModel.OverlayModel);
|
|
730
|
-
if (overlayModel) {
|
|
731
|
-
overlayModel.removeEventListener(
|
|
732
|
-
SDK.OverlayModel.Events.INSPECTED_ELEMENT_WINDOW_RESTORED, floaty.handleRestoreEvent, floaty);
|
|
733
|
-
overlayModel.removeEventListener(
|
|
734
|
-
SDK.OverlayModel.Events.INSPECT_PANEL_SHOW_REQUESTED, floaty.handlePanelRequest);
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
},
|
|
738
|
-
};
|
|
739
|
-
targetManager.observeTargets(observer);
|
|
740
|
-
}
|
|
741
|
-
} catch (err) {
|
|
742
|
-
console.error('[GreenDev] FATAL ERROR during init():', err);
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
void init();
|