chrome-devtools-frontend 1.0.1555174 → 1.0.1556696
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/front_end/core/protocol_client/InspectorBackend.ts +1 -1
- package/front_end/core/root/Runtime.ts +0 -4
- package/front_end/core/sdk/DOMModel.ts +101 -7
- package/front_end/entrypoints/formatter_worker/FormatterActions.ts +2 -0
- package/front_end/entrypoints/formatter_worker/ScopeParser.ts +75 -7
- package/front_end/entrypoints/formatter_worker/Substitute.ts +1 -1
- package/front_end/generated/InspectorBackendCommands.ts +1 -1
- package/front_end/generated/protocol.ts +0 -1
- package/front_end/models/ai_assistance/AiConversation.ts +71 -10
- package/front_end/models/ai_assistance/ArtifactsManager.ts +67 -0
- package/front_end/models/ai_assistance/ConversationHandler.ts +3 -2
- package/front_end/models/ai_assistance/agents/AiAgent.ts +17 -27
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +152 -4
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +2 -2
- package/front_end/models/ai_assistance/ai_assistance.ts +2 -0
- package/front_end/models/ai_assistance/data_formatters/NetworkRequestFormatter.ts +1 -1
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +0 -2
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +1 -1
- package/front_end/{ui/components → models}/annotations/AnnotationRepository.ts +4 -4
- package/front_end/models/annotations/README.md +7 -0
- package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +8 -0
- package/front_end/models/greendev/Prototypes.ts +56 -0
- package/front_end/models/greendev/README.md +5 -0
- package/front_end/models/greendev/greendev.ts +5 -0
- package/front_end/models/stack_trace/StackTrace.ts +13 -2
- package/front_end/models/stack_trace/StackTraceImpl.ts +81 -6
- package/front_end/models/stack_trace/StackTraceModel.ts +35 -3
- package/front_end/models/trace/extras/TraceTree.ts +4 -2
- package/front_end/models/trace/insights/LCPDiscovery.ts +0 -2
- package/front_end/models/trace/types/TraceEvents.ts +0 -1
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +116 -70
- package/front_end/panels/ai_assistance/aiAssistancePanel.css +16 -0
- package/front_end/panels/ai_assistance/components/ArtifactsViewer.ts +159 -0
- package/front_end/panels/ai_assistance/components/ChatView.ts +3 -2
- package/front_end/panels/ai_assistance/components/CollapsibleAssistanceContentWidget.ts +7 -8
- package/front_end/panels/ai_assistance/components/PerformanceAgentFlameChart.ts +15 -8
- package/front_end/panels/ai_assistance/components/PerformanceAgentMarkdownRenderer.ts +9 -9
- package/front_end/panels/ai_assistance/components/artifactsViewer.css +15 -0
- package/front_end/panels/ai_assistance/components/collapsibleAssistanceContentWidget.css +5 -6
- package/front_end/panels/application/AppManifestView.ts +263 -205
- package/front_end/panels/application/ApplicationPanelSidebar.ts +24 -57
- package/front_end/panels/application/OpenedWindowDetailsView.ts +2 -0
- package/front_end/panels/application/ServiceWorkersView.ts +2 -0
- package/front_end/panels/application/StorageView.ts +1 -0
- package/front_end/panels/application/appManifestView.css +48 -0
- package/front_end/panels/application/components/ProtocolHandlersView.ts +2 -2
- package/front_end/panels/application/preloading/PreloadingView.ts +12 -6
- package/front_end/panels/application/preloading/components/PreloadingDetailsReportView.ts +230 -237
- package/front_end/panels/application/preloading/components/PreloadingGrid.ts +96 -79
- package/front_end/panels/application/preloading/components/preloadingGrid.css +26 -29
- package/front_end/panels/application/preloading/preloadingView.css +6 -0
- package/front_end/panels/common/Annotation.ts +1 -1
- package/front_end/panels/common/AnnotationManager.ts +1 -1
- package/front_end/panels/common/ExtensionView.ts +1 -0
- package/front_end/panels/console/ConsoleContextSelector.ts +74 -9
- package/front_end/panels/console/consoleContextSelector.css +31 -29
- package/front_end/panels/coverage/coverageListView.css +59 -57
- package/front_end/panels/elements/ElementsPanel.ts +1 -1
- package/front_end/panels/elements/ElementsTreeElement.ts +39 -1
- package/front_end/panels/elements/ElementsTreeOutline.ts +23 -21
- package/front_end/panels/elements/TopLayerContainer.ts +26 -91
- package/front_end/panels/explain/components/ConsoleInsight.ts +3 -3
- package/front_end/panels/linear_memory_inspector/components/LinearMemoryInspector.ts +4 -8
- package/front_end/panels/linear_memory_inspector/components/LinearMemoryValueInterpreter.ts +148 -97
- package/front_end/panels/linear_memory_inspector/components/LinearMemoryViewer.ts +1 -1
- package/front_end/panels/linear_memory_inspector/components/linearMemoryValueInterpreter.css +37 -35
- package/front_end/panels/network/NetworkItemView.ts +1 -1
- package/front_end/panels/network/NetworkLogView.ts +1 -1
- package/front_end/panels/network/NetworkPanel.ts +1 -1
- package/front_end/panels/recorder/RecorderController.ts +0 -1
- package/front_end/panels/security/SecurityPanelSidebar.ts +5 -0
- package/front_end/panels/settings/SettingsScreen.ts +133 -1
- package/front_end/panels/settings/settings-meta.ts +24 -0
- package/front_end/panels/settings/settingsScreen.css +4 -0
- package/front_end/panels/sources/UISourceCodeFrame.ts +3 -17
- package/front_end/panels/timeline/TimelineUIUtils.ts +5 -8
- package/front_end/panels/timeline/components/TimelineSummary.ts +75 -54
- package/front_end/panels/timeline/components/insights/BaseInsightComponent.ts +18 -26
- package/front_end/panels/timeline/components/insights/Cache.ts +12 -8
- package/front_end/panels/timeline/components/insights/DOMSize.ts +25 -21
- package/front_end/panels/timeline/components/insights/DuplicatedJavaScript.ts +7 -7
- package/front_end/panels/timeline/components/insights/FontDisplay.ts +7 -5
- package/front_end/panels/timeline/components/insights/ForcedReflow.ts +11 -9
- package/front_end/panels/timeline/components/insights/INPBreakdown.ts +7 -6
- package/front_end/panels/timeline/components/insights/ImageDelivery.ts +7 -5
- package/front_end/panels/timeline/components/insights/InsightRenderer.ts +20 -18
- package/front_end/panels/timeline/components/insights/LCPBreakdown.ts +12 -12
- package/front_end/panels/timeline/components/insights/LegacyJavaScript.ts +7 -7
- package/front_end/panels/timeline/components/insights/ModernHTTP.ts +7 -5
- package/front_end/panels/timeline/components/insights/NetworkDependencyTree.ts +15 -13
- package/front_end/panels/timeline/components/insights/RenderBlocking.ts +2 -2
- package/front_end/panels/timeline/components/insights/SlowCSSSelector.ts +15 -14
- package/front_end/panels/timeline/components/insights/Table.ts +152 -130
- package/front_end/panels/timeline/components/insights/ThirdParties.ts +11 -9
- package/front_end/panels/timeline/components/timelineSummary.css +58 -57
- package/front_end/panels/timeline/thirdPartyTreeView.css +109 -0
- package/front_end/panels/timeline/timelineDetailsView.css +2 -4
- package/front_end/panels/timeline/timelinePanel.css +0 -110
- package/front_end/third_party/acorn/estree-legacy.d.ts +2 -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/cjs/puppeteer/api/CDPSession.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/CDPSession.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/ElementHandle.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/ElementHandle.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Frame.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Frame.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Connection.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/BrowserConnector.js +21 -7
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/BrowserConnector.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/EventEmitter.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +15 -6
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/CDPSession.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/CDPSession.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/ElementHandle.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/ElementHandle.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Frame.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Frame.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/Connection.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/BrowserConnector.js +21 -7
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/BrowserConnector.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/EventEmitter.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.js +1 -1
- package/front_end/third_party/puppeteer/package/package.json +2 -2
- package/front_end/third_party/puppeteer/package/src/api/CDPSession.ts +1 -2
- package/front_end/third_party/puppeteer/package/src/api/ElementHandle.ts +2 -4
- package/front_end/third_party/puppeteer/package/src/api/Frame.ts +2 -4
- package/front_end/third_party/puppeteer/package/src/api/Page.ts +2 -4
- package/front_end/third_party/puppeteer/package/src/bidi/core/Connection.ts +3 -2
- package/front_end/third_party/puppeteer/package/src/common/BrowserConnector.ts +29 -10
- package/front_end/third_party/puppeteer/package/src/common/EventEmitter.ts +3 -3
- package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
- package/front_end/ui/components/report_view/ReportView.docs.ts +37 -0
- package/front_end/ui/components/report_view/ReportView.ts +1 -4
- package/front_end/ui/components/settings/SettingCheckbox.ts +1 -1
- package/front_end/ui/legacy/Floaty.ts +5 -9
- package/front_end/ui/legacy/InspectorView.ts +2 -1
- package/front_end/ui/legacy/ReportView.ts +5 -4
- package/front_end/ui/legacy/TabbedPane.ts +1 -1
- package/front_end/ui/legacy/ViewManager.ts +2 -32
- package/front_end/ui/legacy/Widget.ts +7 -0
- package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +0 -1
- package/front_end/ui/legacy/reportView.css +0 -24
- package/front_end/ui/visual_logging/KnownContextValues.ts +7 -0
- package/package.json +1 -1
- /package/front_end/{ui/components → models}/annotations/AnnotationType.ts +0 -0
- /package/front_end/{ui/components → models}/annotations/annotations.ts +0 -0
|
@@ -7,7 +7,14 @@ import type * as Protocol from '../../generated/protocol.js';
|
|
|
7
7
|
|
|
8
8
|
// eslint-disable-next-line @devtools/es-modules-import
|
|
9
9
|
import * as StackTrace from './stack_trace.js';
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
type AnyStackTraceImpl,
|
|
12
|
+
AsyncFragmentImpl,
|
|
13
|
+
DebuggableFragmentImpl,
|
|
14
|
+
FragmentImpl,
|
|
15
|
+
FrameImpl,
|
|
16
|
+
StackTraceImpl
|
|
17
|
+
} from './StackTraceImpl.js';
|
|
11
18
|
import {type FrameNode, type RawFrame, Trie} from './Trie.js';
|
|
12
19
|
|
|
13
20
|
/**
|
|
@@ -45,10 +52,21 @@ export class StackTraceModel extends SDK.SDKModel.SDKModel<unknown> {
|
|
|
45
52
|
return new StackTraceImpl(syncFragment, asyncFragments);
|
|
46
53
|
}
|
|
47
54
|
|
|
55
|
+
async createFromDebuggerPaused(
|
|
56
|
+
pausedDetails: SDK.DebuggerModel.DebuggerPausedDetails,
|
|
57
|
+
rawFramesToUIFrames: TranslateRawFrames): Promise<StackTrace.StackTrace.DebuggableStackTrace> {
|
|
58
|
+
const [syncFragment, asyncFragments] = await Promise.all([
|
|
59
|
+
this.#createDebuggableFragment(pausedDetails, rawFramesToUIFrames),
|
|
60
|
+
this.#createAsyncFragments(pausedDetails, rawFramesToUIFrames),
|
|
61
|
+
]);
|
|
62
|
+
|
|
63
|
+
return new StackTraceImpl(syncFragment, asyncFragments);
|
|
64
|
+
}
|
|
65
|
+
|
|
48
66
|
/** Trigger re-translation of all fragments with the provide script in their call stack */
|
|
49
67
|
async scriptInfoChanged(script: SDK.Script.Script, translateRawFrames: TranslateRawFrames): Promise<void> {
|
|
50
68
|
const translatePromises: Array<Promise<unknown>> = [];
|
|
51
|
-
let stackTracesToUpdate = new Set<
|
|
69
|
+
let stackTracesToUpdate = new Set<AnyStackTraceImpl>();
|
|
52
70
|
|
|
53
71
|
for (const fragment of this.#affectedFragments(script)) {
|
|
54
72
|
// We trigger re-translation only for fragments of leaf-nodes. Any fragment along the ancestor-chain
|
|
@@ -75,8 +93,22 @@ export class StackTraceModel extends SDK.SDKModel.SDKModel<unknown> {
|
|
|
75
93
|
return fragment;
|
|
76
94
|
}
|
|
77
95
|
|
|
96
|
+
async #createDebuggableFragment(
|
|
97
|
+
pausedDetails: SDK.DebuggerModel.DebuggerPausedDetails,
|
|
98
|
+
rawFramesToUIFrames: TranslateRawFrames): Promise<DebuggableFragmentImpl> {
|
|
99
|
+
const fragment = this.#createFragment(pausedDetails.callFrames.map(frame => ({
|
|
100
|
+
scriptId: frame.script.scriptId,
|
|
101
|
+
url: frame.script.sourceURL,
|
|
102
|
+
functionName: frame.functionName,
|
|
103
|
+
lineNumber: frame.location().lineNumber,
|
|
104
|
+
columnNumber: frame.location().columnNumber,
|
|
105
|
+
})));
|
|
106
|
+
await this.#translateFragment(fragment, rawFramesToUIFrames);
|
|
107
|
+
return new DebuggableFragmentImpl(fragment, pausedDetails.callFrames);
|
|
108
|
+
}
|
|
109
|
+
|
|
78
110
|
async #createAsyncFragments(
|
|
79
|
-
stackTraceOrPausedEvent: Protocol.Runtime.StackTrace|
|
|
111
|
+
stackTraceOrPausedEvent: Protocol.Runtime.StackTrace|SDK.DebuggerModel.DebuggerPausedDetails,
|
|
80
112
|
rawFramesToUIFrames: TranslateRawFrames): Promise<AsyncFragmentImpl[]> {
|
|
81
113
|
const asyncFragments: AsyncFragmentImpl[] = [];
|
|
82
114
|
const translatePromises: Array<Promise<unknown>> = [];
|
|
@@ -493,8 +493,10 @@ export class BottomUpRootNode extends Node {
|
|
|
493
493
|
node.totalTime += totalTimeById.get(id) || 0;
|
|
494
494
|
totalTimeById.delete(id);
|
|
495
495
|
}
|
|
496
|
-
|
|
497
|
-
|
|
496
|
+
|
|
497
|
+
// An item on this stack means that this current node has a caller. Therefore,
|
|
498
|
+
// in a bottom-up view it has children.
|
|
499
|
+
if (idStack.length > 0) {
|
|
498
500
|
node.setHasChildren(true);
|
|
499
501
|
}
|
|
500
502
|
}
|
|
@@ -129,8 +129,6 @@ export function generateInsight(
|
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
const initiatorUrl = lcpRequest.args.data.initiator?.url;
|
|
132
|
-
// TODO(b/372319476): Explore using trace event HTMLDocumentParser::FetchQueuedPreloads to determine if the request
|
|
133
|
-
// is discovered by the preload scanner.
|
|
134
132
|
const initiatedByMainDoc =
|
|
135
133
|
lcpRequest?.args.data.initiator?.type === 'parser' && docRequest.args.data.url === initiatorUrl;
|
|
136
134
|
const imgPreloadedOrFoundInHTML = lcpRequest?.args.data.isLinkPreload || initiatedByMainDoc;
|
|
@@ -1078,7 +1078,6 @@ export interface ResourceSendRequest extends Instant {
|
|
|
1078
1078
|
resourceType?: Protocol.Network.ResourceType,
|
|
1079
1079
|
/** Added Feb 2024. https://crrev.com/c/5297615 */
|
|
1080
1080
|
fetchPriorityHint?: FetchPriorityHint,
|
|
1081
|
-
// TODO(crbug.com/1457985): change requestMethod to enum when confirm in the backend code.
|
|
1082
1081
|
requestMethod?: string,
|
|
1083
1082
|
renderBlocking?: RenderBlocking,
|
|
1084
1083
|
initiator?: Initiator,
|
|
@@ -12,10 +12,11 @@ import * as Root from '../../core/root/root.js';
|
|
|
12
12
|
import * as SDK from '../../core/sdk/sdk.js';
|
|
13
13
|
import * as Protocol from '../../generated/protocol.js';
|
|
14
14
|
import * as AiAssistanceModel from '../../models/ai_assistance/ai_assistance.js';
|
|
15
|
+
import * as Annotations from '../../models/annotations/annotations.js';
|
|
15
16
|
import * as Badges from '../../models/badges/badges.js';
|
|
17
|
+
import * as GreenDev from '../../models/greendev/greendev.js';
|
|
16
18
|
import * as TextUtils from '../../models/text_utils/text_utils.js';
|
|
17
19
|
import * as Workspace from '../../models/workspace/workspace.js';
|
|
18
|
-
import * as Annotations from '../../ui/components/annotations/annotations.js';
|
|
19
20
|
import * as Buttons from '../../ui/components/buttons/buttons.js';
|
|
20
21
|
import * as Snackbars from '../../ui/components/snackbars/snackbars.js';
|
|
21
22
|
import * as UIHelpers from '../../ui/helpers/helpers.js';
|
|
@@ -27,6 +28,7 @@ import * as NetworkPanel from '../network/network.js';
|
|
|
27
28
|
import * as TimelinePanel from '../timeline/timeline.js';
|
|
28
29
|
|
|
29
30
|
import aiAssistancePanelStyles from './aiAssistancePanel.css.js';
|
|
31
|
+
import {ArtifactsViewer} from './components/ArtifactsViewer.js';
|
|
30
32
|
import {
|
|
31
33
|
type AnswerPart,
|
|
32
34
|
type ChatMessage,
|
|
@@ -224,10 +226,10 @@ function selectedElementFilter(maybeNode: SDK.DOMModel.DOMNode|null): SDK.DOMMod
|
|
|
224
226
|
return null;
|
|
225
227
|
}
|
|
226
228
|
|
|
227
|
-
async function getEmptyStateSuggestions(
|
|
228
|
-
context: AiAssistanceModel.AiAgent.ConversationContext<unknown>|null,
|
|
229
|
-
conversation?: AiAssistanceModel.AiConversation.AiConversation):
|
|
229
|
+
async function getEmptyStateSuggestions(conversation?: AiAssistanceModel.AiConversation.AiConversation):
|
|
230
230
|
Promise<AiAssistanceModel.AiAgent.ConversationSuggestion[]> {
|
|
231
|
+
const context = conversation?.selectedContext;
|
|
232
|
+
|
|
231
233
|
if (context) {
|
|
232
234
|
const specialSuggestions = await context.getSuggestions();
|
|
233
235
|
|
|
@@ -270,9 +272,10 @@ async function getEmptyStateSuggestions(
|
|
|
270
272
|
}
|
|
271
273
|
}
|
|
272
274
|
|
|
273
|
-
function getMarkdownRenderer(
|
|
274
|
-
|
|
275
|
-
|
|
275
|
+
function getMarkdownRenderer(conversation?: AiAssistanceModel.AiConversation.AiConversation):
|
|
276
|
+
MarkdownRendererWithCodeBlock {
|
|
277
|
+
const context = conversation?.selectedContext;
|
|
278
|
+
|
|
276
279
|
if (context instanceof AiAssistanceModel.PerformanceAgent.PerformanceTraceContext) {
|
|
277
280
|
if (!context.external) {
|
|
278
281
|
const focus = context.getItem();
|
|
@@ -294,6 +297,8 @@ interface ToolbarViewInput {
|
|
|
294
297
|
onExportConversationClick: () => void;
|
|
295
298
|
onHelpClick: () => void;
|
|
296
299
|
onSettingsClick: () => void;
|
|
300
|
+
onArtifactsSidebarToggle: () => void;
|
|
301
|
+
artifactsSidebarVisible: boolean;
|
|
297
302
|
isLoading: boolean;
|
|
298
303
|
showChatActions: boolean;
|
|
299
304
|
showActiveConversationActions: boolean;
|
|
@@ -386,6 +391,13 @@ function toolbarView(input: ToolbarViewInput): Lit.LitTemplate {
|
|
|
386
391
|
.jslogContext=${'freestyler.settings'}
|
|
387
392
|
.variant=${Buttons.Button.Variant.TOOLBAR}
|
|
388
393
|
@click=${input.onSettingsClick}></devtools-button>
|
|
394
|
+
<!-- If the green experiment is enabled, render the artifacts sidebar toggle button -->
|
|
395
|
+
${GreenDev.Prototypes.instance().isEnabled('artifactViewer') ? html`<devtools-button
|
|
396
|
+
title=${i18nString(UIStrings.settings)}
|
|
397
|
+
aria-label=${i18nString(UIStrings.settings)}
|
|
398
|
+
.iconName=${input.artifactsSidebarVisible ? 'left-panel-open' : 'left-panel-close'}
|
|
399
|
+
.variant=${Buttons.Button.Variant.TOOLBAR}
|
|
400
|
+
@click=${input.onArtifactsSidebarToggle}></devtools-button>` : Lit.nothing}
|
|
389
401
|
</devtools-toolbar>
|
|
390
402
|
</div>
|
|
391
403
|
`;
|
|
@@ -396,8 +408,9 @@ function defaultView(input: ViewInput, output: PanelViewOutput, target: HTMLElem
|
|
|
396
408
|
// clang-format off
|
|
397
409
|
function renderState(): Lit.TemplateResult {
|
|
398
410
|
switch (input.state) {
|
|
399
|
-
case ViewState.CHAT_VIEW:
|
|
400
|
-
|
|
411
|
+
case ViewState.CHAT_VIEW: {
|
|
412
|
+
return html`
|
|
413
|
+
<devtools-ai-chat-view
|
|
401
414
|
.props=${input.props}
|
|
402
415
|
${Lit.Directives.ref((el: Element | undefined) => {
|
|
403
416
|
if (!el || !(el instanceof ChatView)) {
|
|
@@ -407,6 +420,7 @@ function defaultView(input: ViewInput, output: PanelViewOutput, target: HTMLElem
|
|
|
407
420
|
output.chatView = el;
|
|
408
421
|
})}
|
|
409
422
|
></devtools-ai-chat-view>`;
|
|
423
|
+
}
|
|
410
424
|
case ViewState.EXPLORE_VIEW:
|
|
411
425
|
return html`<devtools-widget
|
|
412
426
|
class="fill-panel"
|
|
@@ -421,13 +435,40 @@ function defaultView(input: ViewInput, output: PanelViewOutput, target: HTMLElem
|
|
|
421
435
|
}
|
|
422
436
|
}
|
|
423
437
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
)
|
|
438
|
+
const panelWithToolbar = html`
|
|
439
|
+
${toolbarView(input)}
|
|
440
|
+
<div class="ai-assistance-view-container">${renderState()}</div>`;
|
|
441
|
+
|
|
442
|
+
// If the green experiment is enabled, render the chat view inside
|
|
443
|
+
// a split view to also have an artifacts viewer sidebar.
|
|
444
|
+
if(GreenDev.Prototypes.instance().isEnabled('artifactViewer')) {
|
|
445
|
+
Lit.render(
|
|
446
|
+
html`
|
|
447
|
+
<devtools-split-view
|
|
448
|
+
direction="column"
|
|
449
|
+
sidebar-visibility=${input.artifactsSidebarVisible ? 'visible' : 'hidden'}
|
|
450
|
+
sidebar-position="second"
|
|
451
|
+
sidebar-initial-size="520"
|
|
452
|
+
style="width: 100%;">
|
|
453
|
+
<div slot="main" class="assistance-view-wrapper-with-sidebar">
|
|
454
|
+
${panelWithToolbar}
|
|
455
|
+
</div>
|
|
456
|
+
<div slot="sidebar">
|
|
457
|
+
<div class="artifacts-toolbar-container" role="toolbar">
|
|
458
|
+
<div>Artifacts Viewer</div>
|
|
459
|
+
</div>
|
|
460
|
+
<devtools-widget
|
|
461
|
+
class="fill-panel"
|
|
462
|
+
.widgetConfig=${UI.Widget.widgetConfig(ArtifactsViewer)}
|
|
463
|
+
></devtools-widget>
|
|
464
|
+
</div>
|
|
465
|
+
</devtools-split-view>
|
|
466
|
+
`,
|
|
467
|
+
target
|
|
468
|
+
);
|
|
469
|
+
} else {
|
|
470
|
+
Lit.render(panelWithToolbar, target);
|
|
471
|
+
}
|
|
431
472
|
// clang-format on
|
|
432
473
|
}
|
|
433
474
|
|
|
@@ -482,18 +523,12 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
482
523
|
#selectedElement: AiAssistanceModel.StylingAgent.NodeContext|null = null;
|
|
483
524
|
#selectedPerformanceTrace: AiAssistanceModel.PerformanceAgent.PerformanceTraceContext|null = null;
|
|
484
525
|
#selectedRequest: AiAssistanceModel.NetworkAgent.RequestContext|null = null;
|
|
485
|
-
|
|
526
|
+
#isArtifactsSidebarOpen = false;
|
|
486
527
|
// Messages displayed in the `ChatView` component.
|
|
487
528
|
#messages: ChatMessage[] = [];
|
|
488
529
|
|
|
489
530
|
// Whether the UI should show loading or not.
|
|
490
531
|
#isLoading = false;
|
|
491
|
-
// Selected conversation context. The reason we keep this as a
|
|
492
|
-
// state field rather than using `#getConversationContext` is that,
|
|
493
|
-
// there is a case where the context differs from the selectedElement (or other selected context type).
|
|
494
|
-
// Specifically, it allows restoring the previous context when a new selection is cross-origin.
|
|
495
|
-
// See `#onContextSelectionChanged` for details.
|
|
496
|
-
#selectedContext: AiAssistanceModel.AiAgent.ConversationContext<unknown>|null = null;
|
|
497
532
|
// Stores the availability status of the `AidaClient` and the reason for unavailability, if any.
|
|
498
533
|
#aidaAvailability: Host.AidaClient.AidaAccessPreconditions;
|
|
499
534
|
// Info of the currently logged in user.
|
|
@@ -530,6 +565,10 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
530
565
|
}
|
|
531
566
|
AiAssistanceModel.AiHistoryStorage.AiHistoryStorage.instance().addEventListener(
|
|
532
567
|
AiAssistanceModel.AiHistoryStorage.Events.HISTORY_DELETED, this.#onHistoryDeleted, this);
|
|
568
|
+
if (GreenDev.Prototypes.instance().isEnabled('artifactViewer')) {
|
|
569
|
+
AiAssistanceModel.ArtifactsManager.ArtifactsManager.instance().addEventListener(
|
|
570
|
+
AiAssistanceModel.ArtifactsManager.ArtifactAddedEvent.eventName, this.#onArtifactAdded.bind(this));
|
|
571
|
+
}
|
|
533
572
|
}
|
|
534
573
|
|
|
535
574
|
async #getPanelViewInput(): Promise<PanelViewInput> {
|
|
@@ -546,16 +585,16 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
546
585
|
}
|
|
547
586
|
|
|
548
587
|
if (this.#conversation) {
|
|
549
|
-
const emptyStateSuggestions = await getEmptyStateSuggestions(this.#
|
|
550
|
-
const markdownRenderer = getMarkdownRenderer(this.#
|
|
588
|
+
const emptyStateSuggestions = await getEmptyStateSuggestions(this.#conversation);
|
|
589
|
+
const markdownRenderer = getMarkdownRenderer(this.#conversation);
|
|
551
590
|
return {
|
|
552
591
|
state: ViewState.CHAT_VIEW,
|
|
553
592
|
props: {
|
|
554
593
|
additionalFloatyContext: this.#additionalContextItemsFromFloaty,
|
|
555
|
-
blockedByCrossOrigin: this.#
|
|
594
|
+
blockedByCrossOrigin: this.#conversation.isBlockedByOrigin,
|
|
556
595
|
isLoading: this.#isLoading,
|
|
557
596
|
messages: this.#messages,
|
|
558
|
-
selectedContext: this.#selectedContext,
|
|
597
|
+
selectedContext: this.#conversation.selectedContext ?? null,
|
|
559
598
|
conversationType: this.#conversation.type,
|
|
560
599
|
isReadOnly: this.#conversation.isReadOnly ?? false,
|
|
561
600
|
changeSummary: this.#getChangeSummary(),
|
|
@@ -574,6 +613,7 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
574
613
|
uploadImageInputEnabled: isAiAssistanceMultimodalUploadInputEnabled() &&
|
|
575
614
|
this.#conversation.type === AiAssistanceModel.AiHistoryStorage.ConversationType.STYLING,
|
|
576
615
|
markdownRenderer,
|
|
616
|
+
isArtifactsSidebarOpen: this.#isArtifactsSidebarOpen,
|
|
577
617
|
onTextSubmit: async (
|
|
578
618
|
text: string, imageInput?: Host.AidaClient.Part,
|
|
579
619
|
multimodalInputType?: AiAssistanceModel.AiAgent.MultimodalInputType) => {
|
|
@@ -726,6 +766,8 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
726
766
|
this.#conversation = conversation;
|
|
727
767
|
}
|
|
728
768
|
|
|
769
|
+
this.#conversation?.setContext(this.#getConversationContext(this.#conversation));
|
|
770
|
+
|
|
729
771
|
this.requestUpdate();
|
|
730
772
|
}
|
|
731
773
|
|
|
@@ -778,12 +820,19 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
778
820
|
|
|
779
821
|
Host.userMetrics.actionTaken(Host.UserMetrics.Action.AiAssistancePanelOpened);
|
|
780
822
|
|
|
781
|
-
if (
|
|
823
|
+
if (GreenDev.Prototypes.instance().isEnabled('inDevToolsFloaty')) {
|
|
782
824
|
UI.Context.Context.instance().addFlavorChangeListener(UI.Floaty.FloatyFlavor, this.#bindFloatyListener, this);
|
|
783
825
|
this.#bindFloatyListener();
|
|
784
826
|
}
|
|
785
827
|
}
|
|
786
828
|
|
|
829
|
+
#onArtifactAdded(): void {
|
|
830
|
+
if (AiAssistanceModel.ArtifactsManager.ArtifactsManager.instance().artifacts.length > 0) {
|
|
831
|
+
this.#isArtifactsSidebarOpen = true;
|
|
832
|
+
this.requestUpdate();
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
|
|
787
836
|
override willHide(): void {
|
|
788
837
|
super.willHide();
|
|
789
838
|
this.#aiAssistanceEnabledSetting?.removeChangeListener(this.requestUpdate, this);
|
|
@@ -927,6 +976,11 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
927
976
|
onSettingsClick: () => {
|
|
928
977
|
void UI.ViewManager.ViewManager.instance().showView('chrome-ai');
|
|
929
978
|
},
|
|
979
|
+
onArtifactsSidebarToggle: () => {
|
|
980
|
+
this.#isArtifactsSidebarOpen = !this.#isArtifactsSidebarOpen;
|
|
981
|
+
this.requestUpdate();
|
|
982
|
+
},
|
|
983
|
+
artifactsSidebarVisible: this.#isArtifactsSidebarOpen,
|
|
930
984
|
};
|
|
931
985
|
}
|
|
932
986
|
|
|
@@ -958,13 +1012,15 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
958
1012
|
#isTextInputDisabled(): boolean {
|
|
959
1013
|
// If sending a new message is blocked by cross origin context
|
|
960
1014
|
// the text input is disabled.
|
|
961
|
-
if (this.#
|
|
1015
|
+
if (this.#conversation && this.#conversation.isBlockedByOrigin) {
|
|
962
1016
|
return true;
|
|
963
1017
|
}
|
|
964
1018
|
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
1019
|
+
if (!this.#conversation) {
|
|
1020
|
+
return true;
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
if (!this.#conversation.selectedContext) {
|
|
968
1024
|
return true;
|
|
969
1025
|
}
|
|
970
1026
|
|
|
@@ -989,24 +1045,27 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
989
1045
|
return i18nString(UIStrings.followTheSteps);
|
|
990
1046
|
}
|
|
991
1047
|
|
|
992
|
-
if (this.#
|
|
1048
|
+
if (this.#conversation && this.#conversation.isBlockedByOrigin) {
|
|
993
1049
|
return lockedString(UIStringsNotTranslate.crossOriginError);
|
|
994
1050
|
}
|
|
995
1051
|
|
|
996
1052
|
switch (this.#conversation.type) {
|
|
997
1053
|
case AiAssistanceModel.AiHistoryStorage.ConversationType.STYLING:
|
|
998
|
-
return this.#selectedContext ?
|
|
999
|
-
|
|
1054
|
+
return this.#conversation.selectedContext ?
|
|
1055
|
+
lockedString(UIStringsNotTranslate.inputPlaceholderForStyling) :
|
|
1056
|
+
lockedString(UIStringsNotTranslate.inputPlaceholderForStylingNoContext);
|
|
1000
1057
|
case AiAssistanceModel.AiHistoryStorage.ConversationType.FILE:
|
|
1001
|
-
return this.#selectedContext ?
|
|
1002
|
-
|
|
1058
|
+
return this.#conversation.selectedContext ?
|
|
1059
|
+
lockedString(UIStringsNotTranslate.inputPlaceholderForFile) :
|
|
1060
|
+
lockedString(UIStringsNotTranslate.inputPlaceholderForFileNoContext);
|
|
1003
1061
|
case AiAssistanceModel.AiHistoryStorage.ConversationType.NETWORK:
|
|
1004
|
-
return this.#selectedContext ?
|
|
1005
|
-
|
|
1062
|
+
return this.#conversation.selectedContext ?
|
|
1063
|
+
lockedString(UIStringsNotTranslate.inputPlaceholderForNetwork) :
|
|
1064
|
+
lockedString(UIStringsNotTranslate.inputPlaceholderForNetworkNoContext);
|
|
1006
1065
|
case AiAssistanceModel.AiHistoryStorage.ConversationType.PERFORMANCE: {
|
|
1007
1066
|
const perfPanel = UI.Context.Context.instance().flavor(TimelinePanel.TimelinePanel.TimelinePanel);
|
|
1008
1067
|
if (perfPanel?.hasActiveTrace()) {
|
|
1009
|
-
return this.#selectedContext ?
|
|
1068
|
+
return this.#conversation.selectedContext ?
|
|
1010
1069
|
lockedString(UIStringsNotTranslate.inputPlaceholderForPerformanceTrace) :
|
|
1011
1070
|
lockedString(UIStringsNotTranslate.inputPlaceholderForPerformanceTraceNoContext);
|
|
1012
1071
|
}
|
|
@@ -1066,7 +1125,11 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
1066
1125
|
}
|
|
1067
1126
|
|
|
1068
1127
|
#handleContextClick(): void|Promise<void> {
|
|
1069
|
-
|
|
1128
|
+
if (!this.#conversation) {
|
|
1129
|
+
return;
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
const context = this.#conversation.selectedContext;
|
|
1070
1133
|
if (context instanceof AiAssistanceModel.NetworkAgent.RequestContext) {
|
|
1071
1134
|
const requestLocation = NetworkForward.UIRequestLocation.UIRequestLocation.tab(
|
|
1072
1135
|
context.getItem(), NetworkForward.UIRequestLocation.UIRequestTabs.HEADERS_COMPONENT);
|
|
@@ -1164,7 +1227,7 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
1164
1227
|
this.#imageInput = undefined;
|
|
1165
1228
|
this.#isTextInputEmpty = true;
|
|
1166
1229
|
Host.userMetrics.actionTaken(Host.UserMetrics.Action.AiAssistanceQuerySubmitted);
|
|
1167
|
-
if (this.#
|
|
1230
|
+
if (this.#conversation && this.#conversation.isBlockedByOrigin) {
|
|
1168
1231
|
this.#handleNewChatRequest();
|
|
1169
1232
|
}
|
|
1170
1233
|
await this.#startConversation(predefinedPrompt);
|
|
@@ -1358,41 +1421,21 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
1358
1421
|
this.#runAbortController = new AbortController();
|
|
1359
1422
|
}
|
|
1360
1423
|
|
|
1361
|
-
// Indicates whether the new conversation context is blocked due to cross-origin restrictions.
|
|
1362
|
-
// This happens when the conversation's context has a different
|
|
1363
|
-
// origin than the selected context.
|
|
1364
|
-
get #blockedByCrossOrigin(): boolean {
|
|
1365
|
-
if (!this.#conversation) {
|
|
1366
|
-
return false;
|
|
1367
|
-
}
|
|
1368
|
-
this.#selectedContext = this.#getConversationContext(this.#conversation);
|
|
1369
|
-
if (!this.#selectedContext) {
|
|
1370
|
-
return false;
|
|
1371
|
-
}
|
|
1372
|
-
return !this.#selectedContext.isOriginAllowed(this.#conversation.origin);
|
|
1373
|
-
}
|
|
1374
|
-
|
|
1375
1424
|
#getConversationContext(conversation?: AiAssistanceModel.AiConversation.AiConversation):
|
|
1376
1425
|
AiAssistanceModel.AiAgent.ConversationContext<unknown>|null {
|
|
1377
1426
|
if (!conversation) {
|
|
1378
1427
|
return null;
|
|
1379
1428
|
}
|
|
1380
|
-
let context: AiAssistanceModel.AiAgent.ConversationContext<unknown>|null;
|
|
1381
1429
|
switch (conversation.type) {
|
|
1382
1430
|
case AiAssistanceModel.AiHistoryStorage.ConversationType.STYLING:
|
|
1383
|
-
|
|
1384
|
-
break;
|
|
1431
|
+
return this.#selectedElement;
|
|
1385
1432
|
case AiAssistanceModel.AiHistoryStorage.ConversationType.FILE:
|
|
1386
|
-
|
|
1387
|
-
break;
|
|
1433
|
+
return this.#selectedFile;
|
|
1388
1434
|
case AiAssistanceModel.AiHistoryStorage.ConversationType.NETWORK:
|
|
1389
|
-
|
|
1390
|
-
break;
|
|
1435
|
+
return this.#selectedRequest;
|
|
1391
1436
|
case AiAssistanceModel.AiHistoryStorage.ConversationType.PERFORMANCE:
|
|
1392
|
-
|
|
1393
|
-
break;
|
|
1437
|
+
return this.#selectedPerformanceTrace;
|
|
1394
1438
|
}
|
|
1395
|
-
return context;
|
|
1396
1439
|
}
|
|
1397
1440
|
|
|
1398
1441
|
async #startConversation(
|
|
@@ -1407,8 +1450,10 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
1407
1450
|
this.#cancel();
|
|
1408
1451
|
const signal = this.#runAbortController.signal;
|
|
1409
1452
|
const context = this.#getConversationContext(this.#conversation);
|
|
1453
|
+
this.#conversation.setContext(context);
|
|
1454
|
+
|
|
1410
1455
|
// If a different context is provided, it must be from the same origin.
|
|
1411
|
-
if (
|
|
1456
|
+
if (this.#conversation.isBlockedByOrigin) {
|
|
1412
1457
|
// This error should not be reached. If it happens, some
|
|
1413
1458
|
// invariants do not hold anymore.
|
|
1414
1459
|
throw new Error('cross-origin context data should not be included');
|
|
@@ -1427,12 +1472,13 @@ export class AiAssistancePanel extends UI.Panel.Panel {
|
|
|
1427
1472
|
|
|
1428
1473
|
await this.#doConversation(
|
|
1429
1474
|
this.#conversation.run(
|
|
1430
|
-
text,
|
|
1475
|
+
text,
|
|
1476
|
+
{
|
|
1431
1477
|
signal,
|
|
1432
|
-
selected: context,
|
|
1433
1478
|
extraContext: this.#additionalContextItemsFromFloaty,
|
|
1479
|
+
multimodalInput,
|
|
1434
1480
|
},
|
|
1435
|
-
|
|
1481
|
+
),
|
|
1436
1482
|
);
|
|
1437
1483
|
}
|
|
1438
1484
|
|
|
@@ -13,6 +13,22 @@
|
|
|
13
13
|
justify-content: space-between;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
.artifacts-toolbar-container {
|
|
17
|
+
display: flex;
|
|
18
|
+
align-items: center;
|
|
19
|
+
justify-content: flex-start;
|
|
20
|
+
height: 27px;
|
|
21
|
+
padding: 5px;
|
|
22
|
+
border-bottom: 1px solid var(--sys-color-divider);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.assistance-view-wrapper-with-sidebar {
|
|
26
|
+
display: flex;
|
|
27
|
+
flex-direction: column;
|
|
28
|
+
height: 100%;
|
|
29
|
+
overflow: hidden;
|
|
30
|
+
}
|
|
31
|
+
|
|
16
32
|
.ai-assistance-view-container {
|
|
17
33
|
display: flex;
|
|
18
34
|
flex-direction: column;
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
// Copyright 2025 The Chromium Authors
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file.
|
|
4
|
+
|
|
5
|
+
import './CollapsibleAssistanceContentWidget.js';
|
|
6
|
+
import './PerformanceAgentFlameChart.js';
|
|
7
|
+
|
|
8
|
+
import * as AiAssistanceModel from '../../../models/ai_assistance/ai_assistance.js';
|
|
9
|
+
import * as Logs from '../../../models/logs/logs.js';
|
|
10
|
+
import * as NetworkTimeCalculator from '../../../models/network_time_calculator/network_time_calculator.js';
|
|
11
|
+
import * as Trace from '../../../models/trace/trace.js';
|
|
12
|
+
import * as UI from '../../../ui/legacy/legacy.js';
|
|
13
|
+
import * as Lit from '../../../ui/lit/lit.js';
|
|
14
|
+
import * as Network from '../../network/network.js';
|
|
15
|
+
import * as Insights from '../../timeline/components/insights/insights.js';
|
|
16
|
+
|
|
17
|
+
import artifactsViewerStyles from './artifactsViewer.css.js';
|
|
18
|
+
import type * as PerformanceAgentFlameChart from './PerformanceAgentFlameChart.js';
|
|
19
|
+
|
|
20
|
+
const {html, render} = Lit;
|
|
21
|
+
|
|
22
|
+
export interface ViewInput {
|
|
23
|
+
artifacts: AiAssistanceModel.ArtifactsManager.Artifact[];
|
|
24
|
+
parsedTrace: Trace.TraceModel.ParsedTrace;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function renderArtifact(
|
|
28
|
+
artifact: AiAssistanceModel.ArtifactsManager.Artifact, parsedTrace: Trace.TraceModel.ParsedTrace): Lit.LitTemplate {
|
|
29
|
+
switch (artifact.type) {
|
|
30
|
+
// clang-format off
|
|
31
|
+
case 'insight': {
|
|
32
|
+
const insightRenderer = new Insights.InsightRenderer.InsightRenderer();
|
|
33
|
+
const componentName = artifact.insightType;
|
|
34
|
+
const insightSet = parsedTrace.insights?.values().next().value;
|
|
35
|
+
const insightModel = insightSet?.model[componentName as Trace.Insights.Types.InsightKeys];
|
|
36
|
+
|
|
37
|
+
if (!insightModel) {
|
|
38
|
+
return Lit.nothing;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return html`
|
|
42
|
+
<devtools-collapsible-assistance-content-widget .data=${{headerText: `Insight - ${componentName}`}}>
|
|
43
|
+
${insightRenderer.renderInsightToWidgetElement(parsedTrace, insightSet, insightModel, componentName, {
|
|
44
|
+
selected: true,
|
|
45
|
+
isAIAssistanceContext: true,
|
|
46
|
+
})}
|
|
47
|
+
</devtools-collapsible-assistance-content-widget>`;
|
|
48
|
+
}
|
|
49
|
+
case 'network-request': {
|
|
50
|
+
const networkRequest = artifact.request;
|
|
51
|
+
if ('args' in networkRequest && Trace.Types.Events.isSyntheticNetworkRequest(networkRequest)) {
|
|
52
|
+
const calculator = new NetworkTimeCalculator.NetworkTimeCalculator(true);
|
|
53
|
+
const sdkRequest = Logs.NetworkLog.NetworkLog.instance()
|
|
54
|
+
.requestsForId(networkRequest.args.data.requestId)
|
|
55
|
+
.find(r => r.url() === networkRequest.args.data.url) ??
|
|
56
|
+
null;
|
|
57
|
+
if (!sdkRequest) {
|
|
58
|
+
return Lit.nothing;
|
|
59
|
+
}
|
|
60
|
+
return html`
|
|
61
|
+
<devtools-collapsible-assistance-content-widget
|
|
62
|
+
.data=${{headerText: `Network Request: ${
|
|
63
|
+
sdkRequest.url().length > 80 ? sdkRequest.url().slice(0, 80) + '...' : sdkRequest.url()}`}}>
|
|
64
|
+
<devtools-widget class="actions" .widgetConfig=${UI.Widget.widgetConfig(Network.RequestTimingView.RequestTimingView, {
|
|
65
|
+
request: sdkRequest,
|
|
66
|
+
calculator,
|
|
67
|
+
})}></devtools-widget>
|
|
68
|
+
</devtools-collapsible-assistance-content-widget>`;
|
|
69
|
+
}
|
|
70
|
+
return Lit.nothing;
|
|
71
|
+
}
|
|
72
|
+
case 'flamechart': {
|
|
73
|
+
return html`
|
|
74
|
+
<devtools-collapsible-assistance-content-widget .data=${{headerText: `Flamechart`}}>
|
|
75
|
+
<devtools-performance-agent-flame-chart .data=${{
|
|
76
|
+
parsedTrace,
|
|
77
|
+
start: artifact.start,
|
|
78
|
+
end: artifact.end,
|
|
79
|
+
} as PerformanceAgentFlameChart.PerformanceAgentFlameChartData}>
|
|
80
|
+
</devtools-performance-agent-flame-chart>
|
|
81
|
+
</devtools-collapsible-assistance-content-widget>`;
|
|
82
|
+
}
|
|
83
|
+
default:
|
|
84
|
+
return Lit.nothing;
|
|
85
|
+
// clang-format on
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export const DEFAULT_VIEW = (
|
|
90
|
+
input: ViewInput,
|
|
91
|
+
_output: Record<string, unknown>,
|
|
92
|
+
target: HTMLElement,
|
|
93
|
+
): void => {
|
|
94
|
+
// clang-format off
|
|
95
|
+
render(
|
|
96
|
+
html`
|
|
97
|
+
<style>${artifactsViewerStyles}</style>
|
|
98
|
+
<div class="artifacts-viewer">
|
|
99
|
+
${input.artifacts.map(artifact => renderArtifact(artifact, input.parsedTrace))}
|
|
100
|
+
</div>
|
|
101
|
+
`,
|
|
102
|
+
target
|
|
103
|
+
);
|
|
104
|
+
// clang-format on
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export type View = typeof DEFAULT_VIEW;
|
|
108
|
+
|
|
109
|
+
export class ArtifactsViewer extends UI.Widget.Widget {
|
|
110
|
+
#view: View;
|
|
111
|
+
#parsedTrace: Trace.TraceModel.ParsedTrace|null;
|
|
112
|
+
constructor(element?: HTMLElement, view = DEFAULT_VIEW) {
|
|
113
|
+
super(element);
|
|
114
|
+
this.#view = view;
|
|
115
|
+
this.#parsedTrace = null;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
override wasShown(): void {
|
|
119
|
+
super.wasShown();
|
|
120
|
+
AiAssistanceModel.ArtifactsManager.ArtifactsManager.instance().addEventListener(
|
|
121
|
+
AiAssistanceModel.ArtifactsManager.ArtifactAddedEvent.eventName,
|
|
122
|
+
() => {
|
|
123
|
+
if (this.#parsedTrace) {
|
|
124
|
+
this.performUpdate();
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
UI.Context.Context.instance().addFlavorChangeListener(
|
|
130
|
+
AiAssistanceModel.AIContext.AgentFocus,
|
|
131
|
+
({data}) => {
|
|
132
|
+
this.#parsedTrace = data.parsedTrace;
|
|
133
|
+
if (this.#parsedTrace) {
|
|
134
|
+
this.performUpdate();
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
const focus = UI.Context.Context.instance().flavor(AiAssistanceModel.AIContext.AgentFocus);
|
|
140
|
+
if (focus) {
|
|
141
|
+
this.#parsedTrace = focus.parsedTrace;
|
|
142
|
+
this.performUpdate();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
override performUpdate(): void {
|
|
147
|
+
if (!this.#parsedTrace) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
this.#view(
|
|
151
|
+
{
|
|
152
|
+
artifacts: AiAssistanceModel.ArtifactsManager.ArtifactsManager.instance().artifacts,
|
|
153
|
+
parsedTrace: this.#parsedTrace,
|
|
154
|
+
},
|
|
155
|
+
{},
|
|
156
|
+
this.contentElement,
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
}
|