chrome-devtools-frontend 1.0.1592129 → 1.0.1593518
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/Images/src/tab-move.svg +1 -0
- package/front_end/application_tokens.css +4 -4
- package/front_end/core/host/UserMetrics.ts +2 -1
- package/front_end/core/root/ExperimentNames.ts +1 -0
- package/front_end/entrypoints/main/MainImpl.ts +8 -0
- package/front_end/generated/InspectorBackendCommands.ts +3 -1
- package/front_end/generated/SupportedCSSProperties.js +2 -2
- package/front_end/generated/protocol-mapping.d.ts +13 -0
- package/front_end/generated/protocol-proxy-api.d.ts +12 -0
- package/front_end/generated/protocol.ts +75 -0
- package/front_end/models/ai_assistance/agents/AiAgent.ts +24 -1
- package/front_end/models/ai_assistance/agents/BreakpointDebuggerAgent.ts +320 -26
- package/front_end/models/ai_assistance/agents/BreakpointDebuggerAgentOverlay.ts +87 -0
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.snapshot.txt +8 -8
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +79 -48
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +16 -2
- package/front_end/models/computed_style/ComputedStyleModel.ts +40 -6
- package/front_end/models/javascript_metadata/NativeFunctions.js +6 -6
- package/front_end/panels/accessibility/AXBreadcrumbsPane.ts +5 -3
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +39 -7
- package/front_end/panels/ai_assistance/README.md +61 -0
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +141 -27
- package/front_end/panels/ai_assistance/components/ChatView.ts +5 -1
- package/front_end/panels/ai_assistance/components/MarkdownRendererWithCodeBlock.ts +55 -1
- package/front_end/panels/ai_assistance/components/WalkthroughView.ts +19 -7
- package/front_end/panels/ai_assistance/components/chatMessage.css +30 -0
- package/front_end/panels/ai_assistance/components/walkthroughView.css +12 -7
- package/front_end/panels/animation/AnimationGroupPreviewUI.ts +1 -1
- package/front_end/panels/application/CookieItemsView.ts +194 -134
- package/front_end/panels/application/DeviceBoundSessionsTreeElement.ts +1 -1
- package/front_end/panels/application/ServiceWorkerUpdateCycleView.ts +1 -0
- package/front_end/panels/application/StorageItemsToolbar.ts +25 -2
- package/front_end/panels/application/components/BackForwardCacheView.ts +4 -2
- package/front_end/panels/application/cookieItemsView.css +28 -26
- package/front_end/panels/autofill/AutofillView.ts +1 -1
- package/front_end/panels/browser_debugger/DOMBreakpointsSidebarPane.ts +161 -154
- package/front_end/panels/browser_debugger/XHRBreakpointsSidebarPane.ts +1 -0
- package/front_end/panels/browser_debugger/domBreakpointsSidebarPane.css +58 -36
- package/front_end/panels/console/ConsoleViewMessage.ts +2 -1
- package/front_end/panels/console/consoleView.css +7 -2
- package/front_end/panels/elements/ComputedStyleWidget.ts +16 -26
- package/front_end/panels/elements/ElementsPanel.ts +26 -3
- package/front_end/panels/elements/ElementsTreeElement.ts +1 -0
- package/front_end/panels/elements/LayoutPane.ts +8 -7
- package/front_end/panels/elements/StandaloneStylesContainer.ts +254 -0
- package/front_end/panels/elements/StylePropertyTreeElement.ts +33 -0
- package/front_end/panels/elements/StylesAiCodeCompletionProvider.ts +148 -1
- package/front_end/panels/elements/components/ComputedStyleTrace.ts +4 -0
- package/front_end/panels/elements/components/ElementsBreadcrumbs.ts +1 -1
- package/front_end/panels/elements/components/StylePropertyEditor.ts +2 -1
- package/front_end/panels/elements/components/computedStyleProperty.css +1 -1
- package/front_end/panels/elements/elements-meta.ts +3 -5
- package/front_end/panels/elements/elements.ts +2 -0
- package/front_end/panels/elements/stylePropertiesTreeOutline.css +6 -0
- package/front_end/panels/lighthouse/LighthouseReportRenderer.ts +1 -1
- package/front_end/panels/linear_memory_inspector/components/LinearMemoryValueInterpreter.ts +1 -1
- package/front_end/panels/linear_memory_inspector/components/ValueInterpreterDisplay.ts +1 -1
- package/front_end/panels/media/PlayerListView.ts +1 -1
- package/front_end/panels/network/NetworkLogViewColumns.ts +2 -1
- package/front_end/panels/network/components/RequestHeaderSection.ts +1 -1
- package/front_end/panels/protocol_monitor/JSONEditor.ts +1 -1
- package/front_end/panels/recorder/components/RecordingListView.ts +1 -1
- package/front_end/panels/recorder/components/StepEditor.ts +3 -3
- package/front_end/panels/settings/KeybindsSettingsTab.ts +2 -1
- package/front_end/panels/sources/components/HeadersView.ts +2 -2
- package/front_end/panels/timeline/components/BreadcrumbsUI.ts +1 -1
- package/front_end/panels/timeline/components/SidebarAnnotationsTab.ts +1 -1
- package/front_end/panels/timeline/components/metricCard.css +0 -4
- 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/bidi/core/Navigation.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Navigation.js +1 -0
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Navigation.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/BrowserContext.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/BrowserContext.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.js.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/node/ChromeLauncher.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.js +1 -0
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/ChromeLauncher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +3 -3
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +3 -3
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/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 +6 -6
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/Navigation.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/Navigation.js +1 -0
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/Navigation.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/BrowserContext.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/BrowserContext.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.js +1 -0
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/ChromeLauncher.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +3 -3
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +3 -3
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.js +1 -1
- package/front_end/third_party/puppeteer/package/package.json +4 -4
- package/front_end/third_party/puppeteer/package/src/bidi/core/Navigation.ts +1 -0
- package/front_end/third_party/puppeteer/package/src/cdp/BrowserContext.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/cdp/Page.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/node/ChromeLauncher.ts +1 -0
- package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
- package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
- package/front_end/ui/components/suggestion_input/SuggestionInput.ts +7 -12
- package/front_end/ui/components/text_editor/AiCodeCompletionProvider.ts +13 -2
- package/front_end/ui/components/tree_outline/TreeOutline.ts +6 -2
- package/front_end/ui/components/tree_outline/treeOutline.css +5 -0
- package/front_end/ui/legacy/ListControl.ts +5 -3
- package/front_end/ui/legacy/ListWidget.ts +1 -1
- package/front_end/ui/legacy/SoftContextMenu.ts +2 -1
- package/front_end/ui/legacy/Treeoutline.ts +1 -0
- package/front_end/ui/legacy/components/cookie_table/CookiesTable.ts +44 -24
- package/front_end/ui/legacy/components/data_grid/DataGrid.ts +4 -2
- package/front_end/ui/legacy/components/quick_open/FilteredListWidget.ts +1 -1
- package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +31 -0
- package/front_end/ui/visual_logging/Debugging.ts +4 -0
- package/front_end/ui/visual_logging/KnownContextValues.ts +2 -0
- package/package.json +1 -1
|
@@ -10,7 +10,10 @@ import * as Host from '../../../core/host/host.js';
|
|
|
10
10
|
import * as i18n from '../../../core/i18n/i18n.js';
|
|
11
11
|
import type * as Platform from '../../../core/platform/platform.js';
|
|
12
12
|
import * as Root from '../../../core/root/root.js';
|
|
13
|
+
import * as SDK from '../../../core/sdk/sdk.js';
|
|
14
|
+
import type {AiWidget, ComputedStyleAiWidget} from '../../../models/ai_assistance/agents/AiAgent.js';
|
|
13
15
|
import * as AiAssistanceModel from '../../../models/ai_assistance/ai_assistance.js';
|
|
16
|
+
import * as ComputedStyle from '../../../models/computed_style/computed_style.js';
|
|
14
17
|
import * as Marked from '../../../third_party/marked/marked.js';
|
|
15
18
|
import * as Buttons from '../../../ui/components/buttons/buttons.js';
|
|
16
19
|
import * as Input from '../../../ui/components/input/input.js';
|
|
@@ -20,9 +23,10 @@ import * as UIHelpers from '../../../ui/helpers/helpers.js';
|
|
|
20
23
|
import * as UI from '../../../ui/legacy/legacy.js';
|
|
21
24
|
import * as Lit from '../../../ui/lit/lit.js';
|
|
22
25
|
import * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';
|
|
26
|
+
import * as Elements from '../../elements/elements.js';
|
|
23
27
|
|
|
24
28
|
import chatMessageStyles from './chatMessage.css.js';
|
|
25
|
-
import {WalkthroughView} from './WalkthroughView.js';
|
|
29
|
+
import {walkthroughTitle, WalkthroughView} from './WalkthroughView.js';
|
|
26
30
|
|
|
27
31
|
const {html, Directives: {ref, ifDefined}} = Lit;
|
|
28
32
|
const lockedString = i18n.i18n.lockedString;
|
|
@@ -96,18 +100,14 @@ const UIStringsNotTranslate = {
|
|
|
96
100
|
* @description Displayed when the user stop the response
|
|
97
101
|
*/
|
|
98
102
|
stoppedResponse: 'You stopped this response',
|
|
99
|
-
/**
|
|
100
|
-
* @description Prompt for user to confirm code execution that may affect the page.
|
|
101
|
-
*/
|
|
102
|
-
sideEffectConfirmationDescription: 'This code may modify page content. Continue?',
|
|
103
103
|
/**
|
|
104
104
|
* @description Button text that confirm code execution that may affect the page.
|
|
105
105
|
*/
|
|
106
|
-
|
|
106
|
+
confirmActionRequestApproval: 'Continue',
|
|
107
107
|
/**
|
|
108
108
|
* @description Button text that cancels code execution that may affect the page.
|
|
109
109
|
*/
|
|
110
|
-
|
|
110
|
+
declineActionRequestApproval: 'Cancel',
|
|
111
111
|
/**
|
|
112
112
|
* @description The generic name of the AI agent (do not translate)
|
|
113
113
|
*/
|
|
@@ -168,6 +168,11 @@ const UIStringsNotTranslate = {
|
|
|
168
168
|
* @description Title for the button that shows the thinking process (walkthrough).
|
|
169
169
|
*/
|
|
170
170
|
showThinking: 'Show thinking',
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* @description Title for the button that takes the user into other DevTools panels to reveal items the AI references.
|
|
174
|
+
*/
|
|
175
|
+
reveal: 'Reveal'
|
|
171
176
|
} as const;
|
|
172
177
|
|
|
173
178
|
export interface Step {
|
|
@@ -176,12 +181,14 @@ export interface Step {
|
|
|
176
181
|
title?: string;
|
|
177
182
|
code?: string;
|
|
178
183
|
output?: string;
|
|
184
|
+
widgets?: AiWidget[];
|
|
179
185
|
canceled?: boolean;
|
|
180
|
-
|
|
186
|
+
requestApproval?: ConfirmSideEffectDialog;
|
|
181
187
|
contextDetails?: [AiAssistanceModel.AiAgent.ContextDetail, ...AiAssistanceModel.AiAgent.ContextDetail[]];
|
|
182
188
|
}
|
|
183
189
|
|
|
184
190
|
export interface ConfirmSideEffectDialog {
|
|
191
|
+
description: string|null;
|
|
185
192
|
onAnswer: (result: boolean) => void;
|
|
186
193
|
}
|
|
187
194
|
|
|
@@ -386,13 +393,14 @@ function renderTextAsMarkdown(text: string, markdownRenderer: MarkdownLitRendere
|
|
|
386
393
|
// clang-format on
|
|
387
394
|
}
|
|
388
395
|
|
|
389
|
-
function titleForStep(step: Step): string {
|
|
396
|
+
export function titleForStep(step: Step): string {
|
|
390
397
|
return step.title ?? `${lockedString(UIStringsNotTranslate.investigating)}…`;
|
|
391
398
|
}
|
|
392
399
|
|
|
393
400
|
function renderTitle(step: Step): Lit.LitTemplate {
|
|
394
|
-
const paused =
|
|
395
|
-
|
|
401
|
+
const paused = step.requestApproval ?
|
|
402
|
+
html`<span class="paused">${lockedString(UIStringsNotTranslate.paused)}: </span>` :
|
|
403
|
+
Lit.nothing;
|
|
396
404
|
|
|
397
405
|
return html`<span class="title">${paused}${titleForStep(step)}</span>`;
|
|
398
406
|
}
|
|
@@ -444,7 +452,7 @@ function renderStepDetails({
|
|
|
444
452
|
markdownRenderer: MarkdownLitRenderer,
|
|
445
453
|
isLast: boolean,
|
|
446
454
|
}): Lit.LitTemplate {
|
|
447
|
-
const sideEffects = isLast && step.
|
|
455
|
+
const sideEffects = isLast && step.requestApproval ? renderSideEffectConfirmationUi(step) : Lit.nothing;
|
|
448
456
|
const thought = step.thought ? html`<p>${renderTextAsMarkdown(step.thought, markdownRenderer)}</p>` : Lit.nothing;
|
|
449
457
|
|
|
450
458
|
// clang-format off
|
|
@@ -481,7 +489,10 @@ function renderWalkthroughSidebarButton(
|
|
|
481
489
|
if (walkthrough.isInlined) {
|
|
482
490
|
return Lit.nothing;
|
|
483
491
|
}
|
|
484
|
-
const title =
|
|
492
|
+
const title = walkthroughTitle({
|
|
493
|
+
isLoading: input.isLoading,
|
|
494
|
+
lastStep,
|
|
495
|
+
});
|
|
485
496
|
|
|
486
497
|
// clang-format off
|
|
487
498
|
return html`
|
|
@@ -520,7 +531,7 @@ function renderWalkthroughUI(input: ChatMessageViewInput, steps: Step[]): Lit.Li
|
|
|
520
531
|
// No steps = no walkthrough UI in the chat view.
|
|
521
532
|
return Lit.nothing;
|
|
522
533
|
}
|
|
523
|
-
const sideEffectSteps = steps.filter(s => s.
|
|
534
|
+
const sideEffectSteps = steps.filter(s => s.requestApproval);
|
|
524
535
|
// If the walkthrough is in the sidebar, we render a button into the
|
|
525
536
|
// ChatView to open it.
|
|
526
537
|
const openWalkThroughSidebarButton =
|
|
@@ -552,7 +563,7 @@ function renderWalkthroughUI(input: ChatMessageViewInput, steps: Step[]): Lit.Li
|
|
|
552
563
|
markdownRenderer: input.markdownRenderer,
|
|
553
564
|
isInlined: true,
|
|
554
565
|
isExpanded: input.isLastMessage &&
|
|
555
|
-
(input.walkthrough.isExpanded || steps.some(step => Boolean(step.
|
|
566
|
+
(input.walkthrough.isExpanded || steps.some(step => Boolean(step.requestApproval))),
|
|
556
567
|
onToggle: input.walkthrough.onToggle,
|
|
557
568
|
})}></devtools-widget>
|
|
558
569
|
</div>
|
|
@@ -571,14 +582,14 @@ function renderStepBadge({step, isLoading, isLast}: {
|
|
|
571
582
|
isLoading: boolean,
|
|
572
583
|
isLast: boolean,
|
|
573
584
|
}): Lit.LitTemplate {
|
|
574
|
-
if (isLoading && isLast && !step.
|
|
585
|
+
if (isLoading && isLast && !step.requestApproval) {
|
|
575
586
|
return html`<devtools-spinner></devtools-spinner>`;
|
|
576
587
|
}
|
|
577
588
|
|
|
578
589
|
let iconName = 'checkmark';
|
|
579
590
|
let ariaLabel: string|undefined = lockedString(UIStringsNotTranslate.completed);
|
|
580
591
|
let role: 'button'|undefined = 'button';
|
|
581
|
-
if (isLast && step.
|
|
592
|
+
if (isLast && step.requestApproval) {
|
|
582
593
|
role = undefined;
|
|
583
594
|
ariaLabel = undefined;
|
|
584
595
|
iconName = 'pause-circle';
|
|
@@ -601,17 +612,18 @@ export function renderStep({step, isLoading, markdownRenderer, isLast}: {
|
|
|
601
612
|
markdownRenderer: MarkdownLitRenderer,
|
|
602
613
|
isLast: boolean,
|
|
603
614
|
}): Lit.LitTemplate {
|
|
615
|
+
const shouldRenderWidgets = Boolean(step.widgets?.length && Root.Runtime.hostConfig.devToolsAiAssistanceV2?.enabled);
|
|
604
616
|
const stepClasses = Lit.Directives.classMap({
|
|
605
617
|
step: true,
|
|
606
|
-
empty: !step.thought && !step.code && !step.contextDetails && !step.
|
|
607
|
-
paused: Boolean(step.
|
|
618
|
+
empty: !step.thought && !step.code && !step.contextDetails && !step.requestApproval,
|
|
619
|
+
paused: Boolean(step.requestApproval),
|
|
608
620
|
canceled: Boolean(step.canceled),
|
|
609
621
|
});
|
|
610
622
|
// clang-format off
|
|
611
623
|
return html`
|
|
612
624
|
<details class=${stepClasses}
|
|
613
625
|
jslog=${VisualLogging.section('step')}
|
|
614
|
-
.open=${Boolean(step.
|
|
626
|
+
.open=${Boolean(step.requestApproval)}>
|
|
615
627
|
<summary>
|
|
616
628
|
<div class="summary">
|
|
617
629
|
${renderStepBadge({ step, isLoading, isLast })}
|
|
@@ -623,12 +635,114 @@ export function renderStep({step, isLoading, markdownRenderer, isLast}: {
|
|
|
623
635
|
</div>
|
|
624
636
|
</summary>
|
|
625
637
|
${renderStepDetails({step, markdownRenderer, isLast})}
|
|
626
|
-
</details
|
|
638
|
+
</details>
|
|
639
|
+
${shouldRenderWidgets ? html`
|
|
640
|
+
<div class="step-widgets-wrapper">
|
|
641
|
+
${Lit.Directives.until(renderStepWidgets(step))}
|
|
642
|
+
</div>` : Lit.nothing
|
|
643
|
+
}`;
|
|
644
|
+
// clang-format on
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
interface WidgetMakerResponse {
|
|
648
|
+
renderedWidget: Lit.LitTemplate;
|
|
649
|
+
revealable: unknown;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
async function makeComputedStyleWidget(widgetData: ComputedStyleAiWidget): Promise<WidgetMakerResponse|null> {
|
|
653
|
+
const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
|
|
654
|
+
if (!target) {
|
|
655
|
+
return null;
|
|
656
|
+
}
|
|
657
|
+
const node = new SDK.DOMModel.DeferredDOMNode(
|
|
658
|
+
target,
|
|
659
|
+
widgetData.data.backendNodeId,
|
|
660
|
+
);
|
|
661
|
+
const resolved = await node.resolvePromise();
|
|
662
|
+
if (!resolved) {
|
|
663
|
+
return null;
|
|
664
|
+
}
|
|
665
|
+
const model = new ComputedStyle.ComputedStyleModel.ComputedStyleModel(resolved);
|
|
666
|
+
const styles = new ComputedStyle.ComputedStyleModel.ComputedStyle(resolved, widgetData.data.computedStyles);
|
|
667
|
+
|
|
668
|
+
const widgetConfig = UI.Widget.widgetConfig(Elements.ComputedStyleWidget.ComputedStyleWidget, {
|
|
669
|
+
nodeStyle: styles,
|
|
670
|
+
matchedStyles: widgetData.data.matchedCascade,
|
|
671
|
+
// This disables showing the nested traces and detailed information in the widget.
|
|
672
|
+
propertyTraces: null,
|
|
673
|
+
computedStyleModel: model,
|
|
674
|
+
allowUserControl: false,
|
|
675
|
+
filterText: new RegExp(widgetData.data.properties.join('|'), 'i')
|
|
676
|
+
});
|
|
677
|
+
|
|
678
|
+
// clang-format off
|
|
679
|
+
const widget = html`<devtools-widget class="computed-styles-widget" .widgetConfig=${widgetConfig}></devtools-widget>`;
|
|
627
680
|
// clang-format on
|
|
681
|
+
|
|
682
|
+
return {renderedWidget: widget, revealable: new Elements.ElementsPanel.NodeComputedStyles(resolved)};
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
function renderWidgetResponse(response: WidgetMakerResponse|null): Lit.LitTemplate {
|
|
686
|
+
if (response === null) {
|
|
687
|
+
return Lit.nothing;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
function onReveal(): void {
|
|
691
|
+
if (response === null) {
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
694
|
+
void Common.Revealer.reveal(response?.revealable);
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
// clang-format off
|
|
698
|
+
return html`
|
|
699
|
+
<div class="widget-content-container">
|
|
700
|
+
${response.renderedWidget}
|
|
701
|
+
</div>
|
|
702
|
+
<div class="widget-reveal-container">
|
|
703
|
+
<devtools-button class="widget-reveal"
|
|
704
|
+
.iconName=${'tab-move'}
|
|
705
|
+
.variant=${Buttons.Button.Variant.TEXT}
|
|
706
|
+
@click=${onReveal}
|
|
707
|
+
>${lockedString(UIStringsNotTranslate.reveal)}</devtools-button>
|
|
708
|
+
</div>
|
|
709
|
+
`;
|
|
710
|
+
// clang-format on
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
/**
|
|
714
|
+
* Renders AI-defined UI widgets within a step.
|
|
715
|
+
* When a ModelChatMessage contains a WidgetPart, the ChatMessage component
|
|
716
|
+
* iterates through the `step.widgets` array. For each widget, it determines
|
|
717
|
+
* the appropriate rendering logic based on the `widgetData.name`.
|
|
718
|
+
*
|
|
719
|
+
* Currently, only 'COMPUTED_STYLES' widgets are supported. For these, the
|
|
720
|
+
* `makeComputedStyleWidget` function is called to construct the necessary
|
|
721
|
+
* data and configuration for the `Elements.ComputedStyleWidget.ComputedStyleWidget`
|
|
722
|
+
* component. The widget is then rendered using the `<devtools-widget>`
|
|
723
|
+
* custom element, which dynamically instantiates and displays the specified
|
|
724
|
+
* UI.Widget subclass with the provided configuration.
|
|
725
|
+
*
|
|
726
|
+
* This allows for a flexible and extensible system where new widget types
|
|
727
|
+
* can be added to the AI responses and rendered in DevTools by adding
|
|
728
|
+
* corresponding `make...Widget` functions and handling them here.
|
|
729
|
+
*/
|
|
730
|
+
async function renderStepWidgets(step: Step): Promise<Lit.LitTemplate> {
|
|
731
|
+
if (!step.widgets || step.widgets.length === 0) {
|
|
732
|
+
return Lit.nothing;
|
|
733
|
+
}
|
|
734
|
+
const ui = await Promise.all(step.widgets.map(async widgetData => {
|
|
735
|
+
if (widgetData.name === 'COMPUTED_STYLES') {
|
|
736
|
+
const response = await makeComputedStyleWidget(widgetData);
|
|
737
|
+
return renderWidgetResponse(response);
|
|
738
|
+
}
|
|
739
|
+
return Lit.nothing;
|
|
740
|
+
}));
|
|
741
|
+
return html`${ui}`;
|
|
628
742
|
}
|
|
629
743
|
|
|
630
744
|
function renderSideEffectConfirmationUi(step: Step): Lit.LitTemplate {
|
|
631
|
-
if (!step.
|
|
745
|
+
if (!step.requestApproval) {
|
|
632
746
|
return Lit.nothing;
|
|
633
747
|
}
|
|
634
748
|
|
|
@@ -637,7 +751,7 @@ function renderSideEffectConfirmationUi(step: Step): Lit.LitTemplate {
|
|
|
637
751
|
class="side-effect-confirmation"
|
|
638
752
|
jslog=${VisualLogging.section('side-effect-confirmation')}
|
|
639
753
|
>
|
|
640
|
-
|
|
754
|
+
${step.requestApproval.description ? html`<p>${step.requestApproval.description}</p>` : Lit.nothing}
|
|
641
755
|
<div class="side-effect-buttons-container">
|
|
642
756
|
<devtools-button
|
|
643
757
|
.data=${
|
|
@@ -646,9 +760,9 @@ function renderSideEffectConfirmationUi(step: Step): Lit.LitTemplate {
|
|
|
646
760
|
jslogContext: 'decline-execute-code',
|
|
647
761
|
} as Buttons.Button.ButtonData
|
|
648
762
|
}
|
|
649
|
-
@click=${() => step.
|
|
763
|
+
@click=${() => step.requestApproval?.onAnswer(false)}
|
|
650
764
|
>${lockedString(
|
|
651
|
-
UIStringsNotTranslate.
|
|
765
|
+
UIStringsNotTranslate.declineActionRequestApproval,
|
|
652
766
|
)}</devtools-button>
|
|
653
767
|
<devtools-button
|
|
654
768
|
.data=${
|
|
@@ -658,9 +772,9 @@ function renderSideEffectConfirmationUi(step: Step): Lit.LitTemplate {
|
|
|
658
772
|
iconName: 'play',
|
|
659
773
|
} as Buttons.Button.ButtonData
|
|
660
774
|
}
|
|
661
|
-
@click=${() => step.
|
|
775
|
+
@click=${() => step.requestApproval?.onAnswer(true)}
|
|
662
776
|
>${
|
|
663
|
-
lockedString(UIStringsNotTranslate.
|
|
777
|
+
lockedString(UIStringsNotTranslate.confirmActionRequestApproval)
|
|
664
778
|
}</devtools-button>
|
|
665
779
|
</div>
|
|
666
780
|
</div>`;
|
|
@@ -20,7 +20,11 @@ import chatViewStyles from './chatView.css.js';
|
|
|
20
20
|
|
|
21
21
|
export {ChatInput, type ImageInputData} from './ChatInput.js';
|
|
22
22
|
|
|
23
|
-
const {
|
|
23
|
+
const {
|
|
24
|
+
ref,
|
|
25
|
+
repeat,
|
|
26
|
+
classMap,
|
|
27
|
+
} = Directives;
|
|
24
28
|
|
|
25
29
|
/*
|
|
26
30
|
* Strings that don't need to be translated at this time.
|
|
@@ -2,9 +2,15 @@
|
|
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
|
|
5
|
+
import * as Common from '../../../core/common/common.js';
|
|
6
|
+
import * as Platform from '../../../core/platform/platform.js';
|
|
7
|
+
import * as AiAssistanceModel from '../../../models/ai_assistance/ai_assistance.js';
|
|
8
|
+
import * as Logs from '../../../models/logs/logs.js';
|
|
5
9
|
import type * as Marked from '../../../third_party/marked/marked.js';
|
|
6
10
|
import * as MarkdownView from '../../../ui/components/markdown_view/markdown_view.js';
|
|
7
|
-
import
|
|
11
|
+
import * as Lit from '../../../ui/lit/lit.js';
|
|
12
|
+
|
|
13
|
+
const {html} = Lit;
|
|
8
14
|
|
|
9
15
|
/**
|
|
10
16
|
* The model returns multiline code blocks in an erroneous way with the language being in new line.
|
|
@@ -19,7 +25,43 @@ import type * as Lit from '../../../ui/lit/lit.js';
|
|
|
19
25
|
* ```
|
|
20
26
|
**/
|
|
21
27
|
export class MarkdownRendererWithCodeBlock extends MarkdownView.MarkdownView.MarkdownInsightRenderer {
|
|
28
|
+
#revealableLink(revealable: unknown, label: string): Lit.LitTemplate {
|
|
29
|
+
return html`<devtools-link @click=${(e: Event) => {
|
|
30
|
+
e.preventDefault();
|
|
31
|
+
e.stopPropagation();
|
|
32
|
+
void Common.Revealer.reveal(revealable);
|
|
33
|
+
}}>${Platform.StringUtilities.trimEndWithMaxLength(label, 100)}</devtools-link>`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
#renderLink(href: string): Lit.LitTemplate|null {
|
|
37
|
+
if (href.startsWith('#req-')) {
|
|
38
|
+
const request =
|
|
39
|
+
Logs.NetworkLog.NetworkLog.instance().requests().find(req => req.requestId() === href.substring(5));
|
|
40
|
+
|
|
41
|
+
if (request) {
|
|
42
|
+
return this.#revealableLink(request, request.url());
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
} else if (href.startsWith('#file-')) {
|
|
46
|
+
const file = AiAssistanceModel.ContextSelectionAgent.ContextSelectionAgent.getUISourceCodes().find(
|
|
47
|
+
file => AiAssistanceModel.ContextSelectionAgent.ContextSelectionAgent.uiSourceCodeId.get(file) ===
|
|
48
|
+
Number(href.substring(6)));
|
|
49
|
+
|
|
50
|
+
if (file) {
|
|
51
|
+
return this.#revealableLink(file, file.name());
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
22
57
|
override templateForToken(token: Marked.Marked.MarkedToken): Lit.LitTemplate|null {
|
|
58
|
+
if (token.type === 'link') {
|
|
59
|
+
const link = this.#renderLink(token.href);
|
|
60
|
+
if (link) {
|
|
61
|
+
return link;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
23
65
|
if (token.type === 'code') {
|
|
24
66
|
const lines = (token.text).split('\n');
|
|
25
67
|
if (lines[0]?.trim() === 'css') {
|
|
@@ -28,6 +70,18 @@ export class MarkdownRendererWithCodeBlock extends MarkdownView.MarkdownView.Mar
|
|
|
28
70
|
}
|
|
29
71
|
}
|
|
30
72
|
|
|
73
|
+
if (token.type === 'codespan') {
|
|
74
|
+
// LLM likes outputting the link inside a codespan block.
|
|
75
|
+
// Remove the codespan and render the link directly
|
|
76
|
+
const matches = token.text.match(/^\[.*\]\((.+)\)$/);
|
|
77
|
+
if (matches?.[1]) {
|
|
78
|
+
const link = this.#renderLink(matches[1]);
|
|
79
|
+
if (link) {
|
|
80
|
+
return link;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
31
85
|
return super.templateForToken(token);
|
|
32
86
|
}
|
|
33
87
|
}
|
|
@@ -10,9 +10,11 @@ import * as UI from '../../../ui/legacy/legacy.js';
|
|
|
10
10
|
import * as Lit from '../../../ui/lit/lit.js';
|
|
11
11
|
|
|
12
12
|
import chatMessageStyles from './chatMessage.css.js';
|
|
13
|
-
import {type ModelChatMessage, renderStep} from './ChatMessage.js';
|
|
13
|
+
import {type ModelChatMessage, renderStep, type Step, titleForStep} from './ChatMessage.js';
|
|
14
14
|
import walkthroughViewStyles from './walkthroughView.css.js';
|
|
15
15
|
|
|
16
|
+
const lockedString = i18n.i18n.lockedString;
|
|
17
|
+
|
|
16
18
|
const {html, render} = Lit;
|
|
17
19
|
|
|
18
20
|
const UIStrings = {
|
|
@@ -25,9 +27,9 @@ const UIStrings = {
|
|
|
25
27
|
*/
|
|
26
28
|
title: 'Investigation steps',
|
|
27
29
|
/**
|
|
28
|
-
* @description Title for the
|
|
30
|
+
* @description Title for the button that shows the thinking process (walkthrough).
|
|
29
31
|
*/
|
|
30
|
-
|
|
32
|
+
showThinking: 'Show thinking',
|
|
31
33
|
} as const;
|
|
32
34
|
const str_ = i18n.i18n.registerUIStrings('panels/ai_assistance/components/WalkthroughView.ts', UIStrings);
|
|
33
35
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
@@ -41,8 +43,17 @@ export interface ViewInput {
|
|
|
41
43
|
onToggle: (isOpen: boolean) => void;
|
|
42
44
|
}
|
|
43
45
|
|
|
44
|
-
function
|
|
45
|
-
|
|
46
|
+
export function walkthroughTitle(input: {
|
|
47
|
+
isLoading: boolean,
|
|
48
|
+
lastStep: Step,
|
|
49
|
+
}): string {
|
|
50
|
+
const title = input.isLoading ? titleForStep(input.lastStep) : lockedString(UIStrings.showThinking);
|
|
51
|
+
return title;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function renderInlineWalkthrough(input: ViewInput, stepsOutput: Lit.LitTemplate, steps: Step[]): Lit.LitTemplate {
|
|
55
|
+
const lastStep = steps.at(-1);
|
|
56
|
+
if (!input.isInlined || !lastStep) {
|
|
46
57
|
return Lit.nothing;
|
|
47
58
|
}
|
|
48
59
|
|
|
@@ -54,7 +65,8 @@ function renderInlineWalkthrough(input: ViewInput, stepsOutput: Lit.LitTemplate)
|
|
|
54
65
|
return html`
|
|
55
66
|
<details class="walkthrough-inline" ?open=${input.isExpanded} @toggle=${onToggle}>
|
|
56
67
|
<summary>
|
|
57
|
-
${
|
|
68
|
+
${input.isLoading ? html`<devtools-spinner></devtools-spinner>` : Lit.nothing}
|
|
69
|
+
${walkthroughTitle({isLoading: input.isLoading, lastStep,})}
|
|
58
70
|
<devtools-icon name="chevron-down"></devtools-icon>
|
|
59
71
|
</summary>
|
|
60
72
|
${stepsOutput}
|
|
@@ -123,7 +135,7 @@ export const DEFAULT_VIEW = (
|
|
|
123
135
|
${chatMessageStyles}
|
|
124
136
|
${walkthroughViewStyles}
|
|
125
137
|
</style>
|
|
126
|
-
${input.isInlined ? renderInlineWalkthrough(input, stepsOutput)
|
|
138
|
+
${input.isInlined ? renderInlineWalkthrough(input, stepsOutput, steps)
|
|
127
139
|
: renderSidebarWalkthrough(input, stepsOutput, steps.length)
|
|
128
140
|
}`, target);
|
|
129
141
|
// clang-format on
|
|
@@ -333,6 +333,7 @@
|
|
|
333
333
|
}
|
|
334
334
|
}
|
|
335
335
|
|
|
336
|
+
|
|
336
337
|
.error-step {
|
|
337
338
|
color: var(--sys-color-error);
|
|
338
339
|
}
|
|
@@ -354,4 +355,33 @@
|
|
|
354
355
|
gap: var(--sys-size-4);
|
|
355
356
|
align-items: center;
|
|
356
357
|
}
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
.computed-styles-widget {
|
|
361
|
+
display: block;
|
|
362
|
+
width: fit-content;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
.step-widgets-wrapper {
|
|
366
|
+
width: fit-content;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
.widget-reveal-container {
|
|
370
|
+
width: 100%;
|
|
371
|
+
background: var(--sys-color-surface5);
|
|
372
|
+
border-bottom-right-radius: var(--sys-shape-corner-medium);
|
|
373
|
+
border-bottom-left-radius: var(--sys-shape-corner-medium);
|
|
374
|
+
padding: 0 var(--sys-size-4) var(--sys-size-4) 0;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
.widget-content-container {
|
|
378
|
+
padding: var(--sys-size-4);
|
|
379
|
+
border-top-left-radius: var(--sys-shape-corner-medium);
|
|
380
|
+
border-top-right-radius: var(--sys-shape-corner-medium);
|
|
381
|
+
width: 100%;
|
|
382
|
+
overflow-x: auto;
|
|
383
|
+
background-color: var(--sys-color-surface3);
|
|
384
|
+
|
|
385
|
+
--override-computed-style-property-white-space: normal;
|
|
386
|
+
}
|
|
357
387
|
}
|
|
@@ -78,26 +78,31 @@
|
|
|
78
78
|
border-radius: var(--sys-size-5);
|
|
79
79
|
overflow: hidden;
|
|
80
80
|
background-color: var(--sys-color-surface1);
|
|
81
|
+
width: fit-content;
|
|
82
|
+
|
|
83
|
+
&[open] {
|
|
84
|
+
width: auto;
|
|
85
|
+
}
|
|
81
86
|
}
|
|
82
87
|
|
|
83
|
-
.walkthrough-inline summary {
|
|
88
|
+
.walkthrough-inline > summary {
|
|
84
89
|
display: flex;
|
|
85
90
|
align-items: center;
|
|
86
|
-
|
|
87
|
-
padding: var(--sys-size-5) var(--sys-size-6);
|
|
91
|
+
padding: var(--sys-size-4) var(--sys-size-6);
|
|
88
92
|
cursor: pointer;
|
|
89
93
|
background-color: transparent;
|
|
90
|
-
font
|
|
91
|
-
font-size: 11px;
|
|
94
|
+
font: var(--sys-typescale-body4-regular);
|
|
92
95
|
user-select: none;
|
|
93
96
|
list-style: none; /* Hide default triangle */
|
|
97
|
+
justify-content: flex-start;
|
|
98
|
+
gap: var(--sys-size-4);
|
|
94
99
|
}
|
|
95
100
|
|
|
96
|
-
.walkthrough-inline summary::-webkit-details-marker {
|
|
101
|
+
.walkthrough-inline > summary::-webkit-details-marker {
|
|
97
102
|
display: none;
|
|
98
103
|
}
|
|
99
104
|
|
|
100
|
-
.walkthrough-inline summary:hover {
|
|
105
|
+
.walkthrough-inline > summary:hover {
|
|
101
106
|
background-color: var(--sys-color-state-hover-on-subtle);
|
|
102
107
|
}
|
|
103
108
|
|
|
@@ -98,7 +98,7 @@ const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
98
98
|
render(html`
|
|
99
99
|
<div class="animation-group-preview-ui">
|
|
100
100
|
<button
|
|
101
|
-
jslog=${VisualLogging.item(`animations.buffer-preview${input.isScrollDrivenAnimationGroup ? '-sda' : ''}`).track({click: true})}
|
|
101
|
+
jslog=${VisualLogging.item(`animations.buffer-preview${input.isScrollDrivenAnimationGroup ? '-sda' : ''}`).track({click: true, resize: true})}
|
|
102
102
|
class=${classes}
|
|
103
103
|
role="option"
|
|
104
104
|
aria-label=${input.label}
|